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 = new Date(y, m, d, h, M, s, ms);
    
        // the date constructor remaps years 0-99 to 1900-1999
        if (y < 100 && y >= 0 && isFinite(date.getFullYear())) {
            date.setFullYear(y);
        }
        return date;
    }
    
    function createUTCDate (y) {
        var date = new Date(Date.UTC.apply(null, arguments));
    
        // the Date.UTC function remaps years 0-99 to 1900-1999
        if (y < 100 && y >= 0 && isFinite(date.getUTCFullYear())) {
            date.setUTCFullYear(y);
        }
        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 1st 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
    
    var defaultLocaleWeekdays = 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_');
    function localeWeekdays (m, format) {
        if (!m) {
            return isArray(this._weekdays) ? this._weekdays :
                this._weekdays['standalone'];
        }
        return isArray(this._weekdays) ? this._weekdays[m.day()] :
            this._weekdays[this._weekdays.isFormat.test(format) ? 'format' : 'standalone'][m.day()];
    }
    
    var defaultLocaleWeekdaysShort = 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_');
    function localeWeekdaysShort (m) {
        return (m) ? this._weekdaysShort[m.day()] : this._weekdaysShort;
    }
    
    var defaultLocaleWeekdaysMin = 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_');
    function localeWeekdaysMin (m) {
        return (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 he wants. 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);
    
    // months
    // week
    // weekdays
    // meridiem
    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 null;
    }
    
    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;
            }
        }
    
        return globalLocale._abbr;
    }
    
    function defineLocale (name, config) {
        if (config !== null) {
            var 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 {
                    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 begining of week
                weekday = w.e + dow;
                if (w.e < 0 || w.e > 6) {
                    weekdayOverflow = true;
                }
            } else {
                // default to begining 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, ' ').trim();
    }
    
    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 || 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 : (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 = {milliseconds: 0, months: 0};
    
        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(!isUndefined(units) ? 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(!isUndefined(units) ? 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) {
        inclusivity = inclusivity || '()';
        return (inclusivity[0] === '(' ? this.isAfter(from, units) : !this.isBefore(from, units)) &&
            (inclusivity[1] === ')' ? this.isBefore(to, units) : !this.isAfter(to, 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,
            delta, 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._d.valueOf()).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;
    }
    
    function startOf (units) {
        units = normalizeUnits(units);
        // the following switch intentionally omits break keywords
        // to utilize falling through the cases.
        switch (units) {
            case 'year':
                this.month(0);
                /* falls through */
            case 'quarter':
            case 'month':
                this.date(1);
                /* falls through */
            case 'week':
            case 'isoWeek':
            case 'day':
            case 'date':
                this.hours(0);
                /* falls through */
            case 'hour':
                this.minutes(0);
                /* falls through */
            case 'minute':
                this.seconds(0);
                /* falls through */
            case 'second':
                this.milliseconds(0);
        }
    
        // weeks are a special case
        if (units === 'week') {
            this.weekday(0);
        }
        if (units === 'isoWeek') {
            this.isoWeekday(1);
        }
    
        // quarters are also special
        if (units === 'quarter') {
            this.month(Math.floor(this.month() / 3) * 3);
        }
    
        return this;
    }
    
    function endOf (units) {
        units = normalizeUnits(units);
        if (units === undefined || units === 'millisecond') {
            return this;
        }
    
        // 'date' is an alias for 'day', so it should be considered as such.
        if (units === 'date') {
            units = 'day';
        }
    
        return this.startOf(units).add(1, (units === 'isoWeek' ? 'week' : units)).subtract(1, 'ms');
    }
    
    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');
    
    // PRIOROITY
    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;
    
    // Year
    proto.year       = getSetYear;
    proto.isLeapYear = getIsLeapYear;
    
    // Week Year
    proto.weekYear    = getSetWeekYear;
    proto.isoWeekYear = getSetISOWeekYear;
    
    // Quarter
    proto.quarter = proto.quarters = getSetQuarter;
    
    // Month
    proto.month       = getSetMonth;
    proto.daysInMonth = getDaysInMonth;
    
    // Week
    proto.week           = proto.weeks        = getSetWeek;
    proto.isoWeek        = proto.isoWeeks     = getSetISOWeek;
    proto.weeksInYear    = getWeeksInYear;
    proto.isoWeeksInYear = getISOWeeksInYear;
    
    // Day
    proto.date       = getSetDayOfMonth;
    proto.day        = proto.days             = getSetDayOfWeek;
    proto.weekday    = getSetLocaleDayOfWeek;
    proto.isoWeekday = getSetISODayOfWeek;
    proto.dayOfYear  = getSetDayOfYear;
    
    // Hour
    proto.hour = proto.hours = getSetHour;
    
    // Minute
    proto.minute = proto.minutes = getSetMinute;
    
    // Second
    proto.second = proto.seconds = getSetSecond;
    
    // Millisecond
    proto.millisecond = proto.milliseconds = getSetMillisecond;
    
    // Offset
    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;
    
    // Timezone
    proto.zoneAbbr = getZoneAbbr;
    proto.zoneName = getZoneName;
    
    // Deprecations
    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;
    
    // Month
    proto$1.months            =        localeMonths;
    proto$1.monthsShort       =        localeMonthsShort;
    proto$1.monthsParse       =        localeMonthsParse;
    proto$1.monthsRegex       = monthsRegex;
    proto$1.monthsShortRegex  = monthsShortRegex;
    
    // Week
    proto$1.week = localeWeek;
    proto$1.firstDayOfYear = localeFirstDayOfYear;
    proto$1.firstDayOfWeek = localeFirstDayOfWeek;
    
    // Day of Week
    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;
    
    // Hours
    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 === 'year') {
            days   = this._days   + milliseconds / 864e5;
            months = this._months + daysToMonths(days);
            return units === 'month' ? months : 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 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.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;
    
    // Deprecations
    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
    //! version : 2.20.1
    //! authors : Tim Wood, Iskren Chernev, Moment.js contributors
    //! license : MIT
    //! momentjs.com
    
    hooks.version = '2.20.1';
    
    setHookCallback(createLocal);
    
    hooks.fn                    = proto;
    hooks.min                   = min;
    hooks.max                   = max;
    hooks.now                   = now;
    hooks.utc                   = createUTC;
    hooks.unix                  = createUnix;
    hooks.months                = listMonths;
    hooks.isDate                = isDate;
    hooks.locale                = getSetGlobalLocale;
    hooks.invalid               = createInvalid;
    hooks.duration              = createDuration;
    hooks.isMoment              = isMoment;
    hooks.weekdays              = listWeekdays;
    hooks.parseZone             = createInZone;
    hooks.localeData            = getLocale;
    hooks.isDuration            = isDuration;
    hooks.monthsShort           = listMonthsShort;
    hooks.weekdaysMin           = listWeekdaysMin;
    hooks.defineLocale          = defineLocale;
    hooks.updateLocale          = updateLocale;
    hooks.locales               = listLocales;
    hooks.weekdaysShort         = listWeekdaysShort;
    hooks.normalizeUnits        = normalizeUnits;
    hooks.relativeTimeRounding  = getSetRelativeTimeRounding;
    hooks.relativeTimeThreshold = getSetRelativeTimeThreshold;
    hooks.calendarFormat        = getCalendarFormat;
    hooks.prototype             = proto;
    
    // currently HTML5 input type only supports 24-hour formats
    hooks.HTML5_FMT = {
        DATETIME_LOCAL: 'YYYY-MM-DDTHH:mm',             // <input type="datetime-local" />
        DATETIME_LOCAL_SECONDS: 'YYYY-MM-DDTHH:mm:ss',  // <input type="datetime-local" step="1" />
        DATETIME_LOCAL_MS: 'YYYY-MM-DDTHH:mm:ss.SSS',   // <input type="datetime-local" step="0.001" />
        DATE: 'YYYY-MM-DD',                             // <input type="date" />
        TIME: 'HH:mm',                                  // <input type="time" />
        TIME_SECONDS: 'HH:mm:ss',                       // <input type="time" step="1" />
        TIME_MS: 'HH:mm:ss.SSS',                        // <input type="time" step="0.001" />
        WEEK: 'YYYY-[W]WW',                             // <input type="week" />
        MONTH: 'YYYY-MM'                                // <input type="month" />
    };
    
    //! moment.js locale configuration
    //! locale : Afrikaans [af]
    //! author : Werner Mollentze : https://github.com/wernerm
    
    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
    //! locale : Arabic (Algeria) [ar-dz]
    //! author : Noureddine LOUAHEDJ : https://github.com/noureddineme
    
    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 1st is the first week of the year.
        }
    });
    
    //! moment.js locale configuration
    //! locale : Arabic (Kuwait) [ar-kw]
    //! author : Nusret Parlak: https://github.com/nusretparlak
    
    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 1st is the first week of the year.
        }
    });
    
    //! moment.js locale configuration
    //! locale : Arabic (Lybia) [ar-ly]
    //! author : Ali Hmer: https://github.com/kikoanis
    
    var symbolMap = {
        '1': '1',
        '2': '2',
        '3': '3',
        '4': '4',
        '5': '5',
        '6': '6',
        '7': '7',
        '8': '8',
        '9': '9',
        '0': '0'
    };
    var pluralForm = function (n) {
        return n === 0 ? 0 : n === 1 ? 1 : n === 2 ? 2 : n % 100 >= 3 && n % 100 <= 10 ? 3 : n % 100 >= 11 ? 4 : 5;
    };
    var 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 عام']
    };
    var 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);
        };
    };
    var 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 1st is the first week of the year.
        }
    });
    
    //! moment.js locale configuration
    //! locale : Arabic (Morocco) [ar-ma]
    //! author : ElFadili Yassine : https://github.com/ElFadiliY
    //! author : Abdel Said : https://github.com/abdelsaid
    
    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 1st is the first week of the year.
        }
    });
    
    //! moment.js locale configuration
    //! locale : Arabic (Saudi Arabia) [ar-sa]
    //! author : Suhail Alkowaileet : https://github.com/xsoh
    
    var symbolMap$1 = {
        '1': '١',
        '2': '٢',
        '3': '٣',
        '4': '٤',
        '5': '٥',
        '6': '٦',
        '7': '٧',
        '8': '٨',
        '9': '٩',
        '0': '٠'
    };
    var 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 1st is the first week of the year.
        }
    });
    
    //! moment.js locale configuration
    //! locale  :  Arabic (Tunisia) [ar-tn]
    //! author : Nader Toukabri : https://github.com/naderio
    
    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
    //! locale : Arabic [ar]
    //! author : Abdel Said: https://github.com/abdelsaid
    //! author : Ahmed Elkhatib
    //! author : forabi https://github.com/forabi
    
    var symbolMap$2 = {
        '1': '١',
        '2': '٢',
        '3': '٣',
        '4': '٤',
        '5': '٥',
        '6': '٦',
        '7': '٧',
        '8': '٨',
        '9': '٩',
        '0': '٠'
    };
    var numberMap$1 = {
        '١': '1',
        '٢': '2',
        '٣': '3',
        '٤': '4',
        '٥': '5',
        '٦': '6',
        '٧': '7',
        '٨': '8',
        '٩': '9',
        '٠': '0'
    };
    var 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;
    };
    var 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 عام']
    };
    var 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);
        };
    };
    var 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 1st is the first week of the year.
        }
    });
    
    //! moment.js locale configuration
    //! locale : Azerbaijani [az]
    //! author : topchiyev : https://github.com/topchiyev
    
    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çə saniyyə',
            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 1st is the first week of the year.
        }
    });
    
    //! moment.js locale configuration
    //! locale : Belarusian [be]
    //! author : Dmitry Demidov : https://github.com/demidov91
    //! author: Praleska: http://praleska.pro/
    //! Author : Menelion Elensúle : https://github.com/Oire
    
    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 1st is the first week of the year.
        }
    });
    
    //! moment.js locale configuration
    //! locale : Bulgarian [bg]
    //! author : Krasen Borisov : https://github.com/kraz
    
    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 1st is the first week of the year.
        }
    });
    
    //! moment.js locale configuration
    //! locale : Bambara [bm]
    //! author : Estelle Comment : https://github.com/estellecomment
    // Language contact person : Abdoufata Kane : https://github.com/abdoufata
    
    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
    //! locale : Bengali [bn]
    //! author : Kaushik Gandhi : https://github.com/kaushikgandhi
    
    var symbolMap$3 = {
        '1': '১',
        '2': '২',
        '3': '৩',
        '4': '৪',
        '5': '৫',
        '6': '৬',
        '7': '৭',
        '8': '৮',
        '9': '৯',
        '0': '০'
    };
    var 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 1st is the first week of the year.
        }
    });
    
    //! moment.js locale configuration
    //! locale : Tibetan [bo]
    //! author : Thupten N. Chakrishar : https://github.com/vajradog
    
    var symbolMap$4 = {
        '1': '༡',
        '2': '༢',
        '3': '༣',
        '4': '༤',
        '5': '༥',
        '6': '༦',
        '7': '༧',
        '8': '༨',
        '9': '༩',
        '0': '༠'
    };
    var 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 1st is the first week of the year.
        }
    });
    
    //! moment.js locale configuration
    //! locale : Breton [br]
    //! author : Jean-Baptiste Le Duigou : https://github.com/jbleduigou
    
    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
    //! locale : Bosnian [bs]
    //! author : Nedim Cholich : https://github.com/frontyard
    //! based on (hr) translation by Bojan Marković
    
    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 1st is the first week of the year.
        }
    });
    
    //! moment.js locale configuration
    //! locale : Catalan [ca]
    //! author : Juan G. Hurtado : https://github.com/juanghurtado
    
    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
    //! locale : Czech [cs]
    //! author : petrbela : https://github.com/petrbela
    
    var months$3 = 'leden_únor_březen_duben_květen_červen_červenec_srpen_září_říjen_listopad_prosinec'.split('_');
    var monthsShort = 'led_úno_bře_dub_kvě_čvn_čvc_srp_zář_říj_lis_pro'.split('_');
    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,
        monthsParse : (function (months, monthsShort) {
            var i, _monthsParse = [];
            for (i = 0; i < 12; i++) {
                // use custom parser to solve problem with July (červenec)
                _monthsParse[i] = new RegExp('^' + months[i] + '$|^' + monthsShort[i] + '$', 'i');
            }
            return _monthsParse;
        }(months$3, monthsShort)),
        shortMonthsParse : (function (monthsShort) {
            var i, _shortMonthsParse = [];
            for (i = 0; i < 12; i++) {
                _shortMonthsParse[i] = new RegExp('^' + monthsShort[i] + '$', 'i');
            }
            return _shortMonthsParse;
        }(monthsShort)),
        longMonthsParse : (function (months) {
            var i, _longMonthsParse = [];
            for (i = 0; i < 12; i++) {
                _longMonthsParse[i] = new RegExp('^' + months[i] + '$', 'i');
            }
            return _longMonthsParse;
        }(months$3)),
        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
    //! locale : Chuvash [cv]
    //! author : Anatoly Mironov : https://github.com/mirontoli
    
    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 1st is the first week of the year.
        }
    });
    
    //! moment.js locale configuration
    //! locale : Welsh [cy]
    //! author : Robert Allen : https://github.com/robgallen
    //! author : https://github.com/ryangreaves
    
    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
    //! locale : Danish [da]
    //! author : Ulrik Nielsen : https://github.com/mrbase
    
    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
    //! locale : German (Austria) [de-at]
    //! author : lluchs : https://github.com/lluchs
    //! author: Menelion Elensúle: https://github.com/Oire
    //! author : Martin Groller : https://github.com/MadMG
    //! author : Mikolaj Dadela : https://github.com/mik01aj
    
    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
    //! locale : German (Switzerland) [de-ch]
    //! author : sschueller : https://github.com/sschueller
    
    // based on: https://www.bk.admin.ch/dokumentation/sprachen/04915/05016/index.html?lang=de#
    
    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
    //! locale : German [de]
    //! author : lluchs : https://github.com/lluchs
    //! author: Menelion Elensúle: https://github.com/Oire
    //! author : Mikolaj Dadela : https://github.com/mik01aj
    
    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
    //! locale : Maldivian [dv]
    //! author : Jawish Hameed : https://github.com/jawish
    
    var months$4 = [
        'ޖެނުއަރީ',
        'ފެބްރުއަރީ',
        'މާރިޗު',
        'އޭޕްރީލު',
        'މޭ',
        'ޖޫން',
        'ޖުލައި',
        'އޯގަސްޓު',
        'ސެޕްޓެމްބަރު',
        'އޮކްޓޯބަރު',
        'ނޮވެމްބަރު',
        'ޑިސެމްބަރު'
    ];
    var 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 1st is the first week of the year.
        }
    });
    
    //! moment.js locale configuration
    //! locale : Greek [el]
    //! author : Aggelos Karalias : https://github.com/mehiel
    
    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
    //! locale : English (Australia) [en-au]
    //! author : Jared Morse : https://github.com/jarcoal
    
    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
    //! locale : English (Canada) [en-ca]
    //! author : Jonathan Abourbih : https://github.com/jonbca
    
    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
    //! locale : English (United Kingdom) [en-gb]
    //! author : Chris Gedrim : https://github.com/chrisgedrim
    
    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
    //! locale : English (Ireland) [en-ie]
    //! author : Chris Cartlidge : https://github.com/chriscartlidge
    
    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
    //! locale : English (New Zealand) [en-nz]
    //! author : Luke McGregor : https://github.com/lukemcgregor
    
    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
    //! locale : Esperanto [eo]
    //! author : Colin Dean : https://github.com/colindean
    //! author : Mia Nordentoft Imperatori : https://github.com/miestasmia
    //! comment : miestasmia corrected the translation by colindean
    
    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 1st is the first week of the year.
        }
    });
    
    //! moment.js locale configuration
    //! locale : Spanish (Dominican Republic) [es-do]
    
    var monthsShortDot = 'ene._feb._mar._abr._may._jun._jul._ago._sep._oct._nov._dic.'.split('_');
    var monthsShort$1 = 'ene_feb_mar_abr_may_jun_jul_ago_sep_oct_nov_dic'.split('_');
    
    var monthsParse = [/^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$1 = /^(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$1,
        monthsShortRegex: monthsRegex$1,
        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,
        longMonthsParse: monthsParse,
        shortMonthsParse: monthsParse,
        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
    //! locale : Spanish (United States) [es-us]
    //! author : bustta : https://github.com/bustta
    
    var monthsShortDot$1 = 'ene._feb._mar._abr._may._jun._jul._ago._sep._oct._nov._dic.'.split('_');
    var monthsShort$2 = 'ene_feb_mar_abr_may_jun_jul_ago_sep_oct_nov_dic'.split('_');
    
    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()];
            }
        },
        monthsParseExact : true,
        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 : 'MMMM [de] D [de] YYYY',
            LLL : 'MMMM [de] D [de] YYYY h:mm A',
            LLLL : 'dddd, MMMM [de] D [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 1st is the first week of the year.
        }
    });
    
    //! moment.js locale configuration
    //! locale : Spanish [es]
    //! author : Julio Napurí : https://github.com/julionc
    
    var monthsShortDot$2 = 'ene._feb._mar._abr._may._jun._jul._ago._sep._oct._nov._dic.'.split('_');
    var monthsShort$3 = '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', {
        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$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',
            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
    //! locale : Estonian [et]
    //! author : Henry Kehlmann : https://github.com/madhenry
    //! improvements : Illimar Tambek : https://github.com/ragulka
    
    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
    //! locale : Basque [eu]
    //! author : Eneko Illarramendi : https://github.com/eillarra
    
    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 1st is the first week of the year.
        }
    });
    
    //! moment.js locale configuration
    //! locale : Persian [fa]
    //! author : Ebrahim Byagowi : https://github.com/ebraminio
    
    var symbolMap$5 = {
        '1': '۱',
        '2': '۲',
        '3': '۳',
        '4': '۴',
        '5': '۵',
        '6': '۶',
        '7': '۷',
        '8': '۸',
        '9': '۹',
        '0': '۰'
    };
    var 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 1st is the first week of the year.
        }
    });
    
    //! moment.js locale configuration
    //! locale : Finnish [fi]
    //! author : Tarmo Aidantausta : https://github.com/bleadof
    
    var numbersPast = 'nolla yksi kaksi kolme neljä viisi kuusi seitsemän kahdeksan yhdeksän'.split(' ');
    var 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
    //! locale : Faroese [fo]
    //! author : Ragnar Johannesen : https://github.com/ragnar123
    
    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 minutt',
            mm : '%d minuttir',
            h : 'ein tími',
            hh : '%d tímar',
            d : 'ein dagur',
            dd : '%d dagar',
            M : 'ein mánaði',
            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
    //! locale : French (Canada) [fr-ca]
    //! author : Jonathan Abourbih : https://github.com/jonbca
    
    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
    //! locale : French (Switzerland) [fr-ch]
    //! author : Gaspard Bucher : https://github.com/gaspard
    
    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
    //! locale : French [fr]
    //! author : John Fischer : https://github.com/jfroffice
    
    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
    //! locale : Frisian [fy]
    //! author : Robin van der Vliet : https://github.com/robin0van0der0v
    
    var monthsShortWithDots = 'jan._feb._mrt._apr._mai_jun._jul._aug._sep._okt._nov._des.'.split('_');
    var 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
    //! locale : Scottish Gaelic [gd]
    //! author : Jon Ashdown : https://github.com/jonashdown
    
    var months$5 = [
        '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$4 = ['Faoi', 'Gear', 'Màrt', 'Gibl', 'Cèit', 'Ògmh', 'Iuch', 'Lùn', 'Sult', 'Dàmh', 'Samh', 'Dùbh'];
    
    var weekdays$1 = ['Didòmhnaich', 'Diluain', 'Dimàirt', 'Diciadain', 'Diardaoin', 'Dihaoine', 'Disathairne'];
    
    var weekdaysShort = ['Did', 'Dil', 'Dim', 'Dic', 'Dia', 'Dih', 'Dis'];
    
    var weekdaysMin = ['Dò', 'Lu', 'Mà', 'Ci', 'Ar', 'Ha', 'Sa'];
    
    hooks.defineLocale('gd', {
        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 : '[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
    //! locale : Galician [gl]
    //! author : Juan G. Hurtado : https://github.com/juanghurtado
    
    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
    //! locale : Konkani Latin script [gom-latn]
    //! author : The Discoverer : https://github.com/WikiDiscoverer
    
    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 horan', 'ek hor'],
            'hh': [number + ' horanim', number + ' hor'],
            '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
    //! locale : Gujarati [gu]
    //! author : Kaushik Thanki : https://github.com/Kaushik1987
    
    var symbolMap$6 = {
            '1': '૧',
            '2': '૨',
            '3': '૩',
            '4': '૪',
            '5': '૫',
            '6': '૬',
            '7': '૭',
            '8': '૮',
            '9': '૯',
            '0': '૦'
        };
    var 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 1st is the first week of the year.
        }
    });
    
    //! moment.js locale configuration
    //! locale : Hebrew [he]
    //! author : Tomer Cohen : https://github.com/tomer
    //! author : Moshe Simantov : https://github.com/DevelopmentIL
    //! author : Tal Ater : https://github.com/TalAter
    
    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
    //! locale : Hindi [hi]
    //! author : Mayank Singhal : https://github.com/mayanksinghal
    
    var symbolMap$7 = {
        '1': '१',
        '2': '२',
        '3': '३',
        '4': '४',
        '5': '५',
        '6': '६',
        '7': '७',
        '8': '८',
        '9': '९',
        '0': '०'
    };
    var 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 1st is the first week of the year.
        }
    });
    
    //! moment.js locale configuration
    //! locale : Croatian [hr]
    //! author : Bojan Marković : https://github.com/bmarkovic
    
    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 1st is the first week of the year.
        }
    });
    
    //! moment.js locale configuration
    //! locale : Hungarian [hu]
    //! author : Adam Brunner : https://github.com/adambrunner
    
    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
    //! locale : Armenian [hy-am]
    //! author : Armendarabyan : https://github.com/armendarabyan
    
    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 1st is the first week of the year.
        }
    });
    
    //! moment.js locale configuration
    //! locale : Indonesian [id]
    //! author : Mohammad Satrio Utomo : https://github.com/tyok
    //! reference: http://id.wikisource.org/wiki/Pedoman_Umum_Ejaan_Bahasa_Indonesia_yang_Disempurnakan
    
    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_Ags_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 1st is the first week of the year.
        }
    });
    
    //! moment.js locale configuration
    //! locale : Icelandic [is]
    //! author : Hinrik Örn Sigurðsson : https://github.com/hinrik
    
    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
    //! locale : Italian [it]
    //! author : Lorenzo : https://github.com/aliem
    //! author: Mattia Larentis: https://github.com/nostalgiaz
    
    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
    //! locale : Japanese [ja]
    //! author : LI Long : https://github.com/baryon
    
    hooks.defineLocale('ja', {
        months : '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split('_'),
        monthsShort : '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split('_'),
        weekdays : '日曜日_月曜日_火曜日_水曜日_木曜日_金曜日_土曜日'.split('_'),
        weekdaysShort : '日_月_火_水_木_金_土'.split('_'),
        weekdaysMin : '日_月_火_水_木_金_土'.split('_'),
        longDateFormat : {
            LT : 'HH:mm',
            LTS : 'HH:mm:ss',
            L : 'YYYY/MM/DD',
            LL : 'YYYY年M月D日',
            LLL : 'YYYY年M月D日 HH:mm',
            LLLL : 'YYYY年M月D日 HH:mm dddd',
            l : 'YYYY/MM/DD',
            ll : 'YYYY年M月D日',
            lll : 'YYYY年M月D日 HH:mm',
            llll : 'YYYY年M月D日 HH:mm dddd'
        },
        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'
        },
        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
    //! locale : Javanese [jv]
    //! author : Rony Lantip : https://github.com/lantip
    //! reference: http://jv.wikipedia.org/wiki/Basa_Jawa
    
    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 1st is the first week of the year.
        }
    });
    
    //! moment.js locale configuration
    //! locale : Georgian [ka]
    //! author : Irakli Janiashvili : https://github.com/irakli-janiashvili
    
    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
    //! locale : Kazakh [kk]
    //! authors : Nurlan Rakhimzhanov : https://github.com/nurlan
    
    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 1st is the first week of the year.
        }
    });
    
    //! moment.js locale configuration
    //! locale : Cambodian [km]
    //! author : Kruy Vanna : https://github.com/kruyvanna
    
    hooks.defineLocale('km', {
        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 ឆ្នាំ'
        },
        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
    //! locale : Kannada [kn]
    //! author : Rajeev Naik : https://github.com/rajeevnaikte
    
    var symbolMap$8 = {
        '1': '೧',
        '2': '೨',
        '3': '೩',
        '4': '೪',
        '5': '೫',
        '6': '೬',
        '7': '೭',
        '8': '೮',
        '9': '೯',
        '0': '೦'
    };
    var numberMap$7 = {
        '೧': '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$7[match];
            });
        },
        postformat: function (string) {
            return string.replace(/\d/g, function (match) {
                return symbolMap$8[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 1st is the first week of the year.
        }
    });
    
    //! moment.js locale configuration
    //! locale : Korean [ko]
    //! author : Kyungwook, Park : https://github.com/kyungw00k
    //! author : Jeeeyul Lee <jeeeyul@gmail.com>
    
    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
    //! locale : Kyrgyz [ky]
    //! author : Chyngyz Arystan uulu : https://github.com/chyngyz
    
    
    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 1st is the first week of the year.
        }
    });
    
    //! moment.js locale configuration
    //! locale : Luxembourgish [lb]
    //! author : mweimerskirch : https://github.com/mweimerskirch
    //! author : David Raison : https://github.com/kwisatz
    
    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
    //! locale : Lao [lo]
    //! author : Ryan Hart : https://github.com/ryanhart2
    
    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
    //! locale : Lithuanian [lt]
    //! author : Mindaugas Mozūras : https://github.com/mmozuras
    
    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
    //! locale : Latvian [lv]
    //! author : Kristaps Karlsons : https://github.com/skakri
    //! author : Jānis Elmeris : https://github.com/JanisE
    
    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
    //! locale : Montenegrin [me]
    //! author : Miodrag Nikač <miodrag@restartit.me> : https://github.com/miodragnikac
    
    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 1st is the first week of the year.
        }
    });
    
    //! moment.js locale configuration
    //! locale : Maori [mi]
    //! author : John Corrigan <robbiecloset@gmail.com> : https://github.com/johnideal
    
    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
    //! locale : Macedonian [mk]
    //! author : Borislav Mickov : https://github.com/B0k0
    
    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 1st is the first week of the year.
        }
    });
    
    //! moment.js locale configuration
    //! locale : Malayalam [ml]
    //! author : Floyd Pink : https://github.com/floydpink
    
    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
    //! locale : Marathi [mr]
    //! author : Harshad Kale : https://github.com/kalehv
    //! author : Vivek Athalye : https://github.com/vnathalye
    
    var symbolMap$9 = {
        '1': '१',
        '2': '२',
        '3': '३',
        '4': '४',
        '5': '५',
        '6': '६',
        '7': '७',
        '8': '८',
        '9': '९',
        '0': '०'
    };
    var numberMap$8 = {
        '१': '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$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 'रात्री';
            }
        },
        week : {
            dow : 0, // Sunday is the first day of the week.
            doy : 6  // The week that contains Jan 1st is the first week of the year.
        }
    });
    
    //! moment.js locale configuration
    //! locale : Malay [ms-my]
    //! note : DEPRECATED, the correct one is [ms]
    //! author : Weldan Jamili : https://github.com/weldan
    
    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 1st is the first week of the year.
        }
    });
    
    //! moment.js locale configuration
    //! locale : Malay [ms]
    //! author : Weldan Jamili : https://github.com/weldan
    
    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 1st is the first week of the year.
        }
    });
    
    //! moment.js locale configuration
    //! locale : Maltese (Malta) [mt]
    //! author : Alessandro Maruccia : https://github.com/alesma
    
    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
    //! locale : Burmese [my]
    //! author : Squar team, mysquar.com
    //! author : David Rossellat : https://github.com/gholadr
    //! author : Tin Aung Lin : https://github.com/thanyawzinmin
    
    var symbolMap$10 = {
        '1': '၁',
        '2': '၂',
        '3': '၃',
        '4': '၄',
        '5': '၅',
        '6': '၆',
        '7': '၇',
        '8': '၈',
        '9': '၉',
        '0': '၀'
    };
    var numberMap$9 = {
        '၁': '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$9[match];
            });
        },
        postformat: function (string) {
            return string.replace(/\d/g, function (match) {
                return symbolMap$10[match];
            });
        },
        week: {
            dow: 1, // Monday is the first day of the week.
            doy: 4 // The week that contains Jan 1st is the first week of the year.
        }
    });
    
    //! moment.js locale configuration
    //! locale : Norwegian Bokmål [nb]
    //! authors : Espen Hovlandsdal : https://github.com/rexxars
    //!           Sigurd Gartmann : https://github.com/sigurdga
    
    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
    //! locale : Nepalese [ne]
    //! author : suvash : https://github.com/suvash
    
    var symbolMap$11 = {
        '1': '१',
        '2': '२',
        '3': '३',
        '4': '४',
        '5': '५',
        '6': '६',
        '7': '७',
        '8': '८',
        '9': '९',
        '0': '०'
    };
    var numberMap$10 = {
        '१': '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$10[match];
            });
        },
        postformat: function (string) {
            return string.replace(/\d/g, function (match) {
                return symbolMap$11[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 1st is the first week of the year.
        }
    });
    
    //! moment.js locale configuration
    //! locale : Dutch (Belgium) [nl-be]
    //! author : Joris Röling : https://github.com/jorisroling
    //! author : Jacob Middag : https://github.com/middagj
    
    var monthsShortWithDots$1 = 'jan._feb._mrt._apr._mei_jun._jul._aug._sep._okt._nov._dec.'.split('_');
    var monthsShortWithoutDots$1 = 'jan_feb_mrt_apr_mei_jun_jul_aug_sep_okt_nov_dec'.split('_');
    
    var monthsParse$2 = [/^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$3 = /^(januari|februari|maart|april|mei|april|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$3,
        monthsShortRegex: monthsRegex$3,
        monthsStrictRegex: /^(januari|februari|maart|mei|ju[nl]i|april|augustus|september|oktober|november|december)/i,
        monthsShortStrictRegex: /^(jan\.?|feb\.?|mrt\.?|apr\.?|mei|ju[nl]\.?|aug\.?|sep\.?|okt\.?|nov\.?|dec\.?)/i,
    
        monthsParse : monthsParse$2,
        longMonthsParse : monthsParse$2,
        shortMonthsParse : monthsParse$2,
    
        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
    //! locale : Dutch [nl]
    //! author : Joris Röling : https://github.com/jorisroling
    //! author : Jacob Middag : https://github.com/middagj
    
    var monthsShortWithDots$2 = 'jan._feb._mrt._apr._mei_jun._jul._aug._sep._okt._nov._dec.'.split('_');
    var monthsShortWithoutDots$2 = 'jan_feb_mrt_apr_mei_jun_jul_aug_sep_okt_nov_dec'.split('_');
    
    var monthsParse$3 = [/^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$4 = /^(januari|februari|maart|april|mei|april|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$4,
        monthsShortRegex: monthsRegex$4,
        monthsStrictRegex: /^(januari|februari|maart|mei|ju[nl]i|april|augustus|september|oktober|november|december)/i,
        monthsShortStrictRegex: /^(jan\.?|feb\.?|mrt\.?|apr\.?|mei|ju[nl]\.?|aug\.?|sep\.?|okt\.?|nov\.?|dec\.?)/i,
    
        monthsParse : monthsParse$3,
        longMonthsParse : monthsParse$3,
        shortMonthsParse : monthsParse$3,
    
        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
    //! locale : Nynorsk [nn]
    //! author : https://github.com/mechuwind
    
    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
    //! locale : Punjabi (India) [pa-in]
    //! author : Harpreet Singh : https://github.com/harpreetkhalsagtbit
    
    var symbolMap$12 = {
        '1': '੧',
        '2': '੨',
        '3': '੩',
        '4': '੪',
        '5': '੫',
        '6': '੬',
        '7': '੭',
        '8': '੮',
        '9': '੯',
        '0': '੦'
    };
    var numberMap$11 = {
        '੧': '1',
        '੨': '2',
        '੩': '3',
        '੪': '4',
        '੫': '5',
        '੬': '6',
        '੭': '7',
        '੮': '8',
        '੯': '9',
        '੦': '0'
    };
    
    hooks.defineLocale('pa-in', {
        // There are months name as per Nanakshahi Calender 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$11[match];
            });
        },
        postformat: function (string) {
            return string.replace(/\d/g, function (match) {
                return symbolMap$12[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 1st is the first week of the year.
        }
    });
    
    //! moment.js locale configuration
    //! locale : Polish [pl]
    //! author : Rafal Hirsz : https://github.com/evoL
    
    var monthsNominative = 'styczeń_luty_marzec_kwiecień_maj_czerwiec_lipiec_sierpień_wrzesień_październik_listopad_grudzień'.split('_');
    var 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$7(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$7,
            m : translate$7,
            mm : translate$7,
            h : translate$7,
            hh : translate$7,
            d : '1 dzień',
            dd : '%d dni',
            M : 'miesiąc',
            MM : translate$7,
            y : 'rok',
            yy : translate$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.
        }
    });
    
    //! moment.js locale configuration
    //! locale : Portuguese (Brazil) [pt-br]
    //! author : Caio Ribeiro Pereira : https://github.com/caio-ribeiro-pereira
    
    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 : '%s atrá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
    //! locale : Portuguese [pt]
    //! author : Jefferson : https://github.com/jalex79
    
    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
    //! locale : Romanian [ro]
    //! author : Vlad Gurdiga : https://github.com/gurdiga
    //! author : Valentin Agachi : https://github.com/avaly
    
    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 1st is the first week of the year.
        }
    });
    
    //! moment.js locale configuration
    //! locale : Russian [ru]
    //! author : Viktorminator : https://github.com/Viktorminator
    //! Author : Menelion Elensúle : https://github.com/Oire
    //! author : Коренберг Марк : https://github.com/socketpair
    
    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$4 = [/^янв/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$4,
        longMonthsParse : monthsParse$4,
        shortMonthsParse : monthsParse$4,
    
        // полные названия с падежами, по три буквы, для некоторых, по 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
    //! locale : Sindhi [sd]
    //! author : Narain Sagar : https://github.com/narainsagar
    
    var months$6 = [
        'جنوري',
        'فيبروري',
        'مارچ',
        'اپريل',
        'مئي',
        'جون',
        'جولاءِ',
        'آگسٽ',
        'سيپٽمبر',
        'آڪٽوبر',
        'نومبر',
        'ڊسمبر'
    ];
    var days$1 = [
        'آچر',
        'سومر',
        'اڱارو',
        'اربع',
        'خميس',
        'جمع',
        'ڇنڇر'
    ];
    
    hooks.defineLocale('sd', {
        months : months$6,
        monthsShort : months$6,
        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
    //! locale : Northern Sami [se]
    //! authors : Bård Rolstad Henriksen : https://github.com/karamell
    
    
    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
    //! locale : Sinhalese [si]
    //! author : Sampath Sitinamaluwa : https://github.com/sampathsris
    
    /*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
    //! locale : Slovak [sk]
    //! author : Martin Minka : https://github.com/k2s
    //! based on work of petrbela : https://github.com/petrbela
    
    var months$7 = 'január_február_marec_apríl_máj_jún_júl_august_september_október_november_december'.split('_');
    var monthsShort$5 = '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$8(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$7,
        monthsShort : monthsShort$5,
        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$8,
            ss : translate$8,
            m : translate$8,
            mm : translate$8,
            h : translate$8,
            hh : translate$8,
            d : translate$8,
            dd : translate$8,
            M : translate$8,
            MM : translate$8,
            y : translate$8,
            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
    //! locale : Slovenian [sl]
    //! author : Robert Sedovšek : https://github.com/sedovsek
    
    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 += withoutSuffix || isFuture ? 'sekund' : '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 1st is the first week of the year.
        }
    });
    
    //! moment.js locale configuration
    //! locale : Albanian [sq]
    //! author : Flakërim Ismani : https://github.com/flakerimi
    //! author : Menelion Elensúle : https://github.com/Oire
    //! author : Oerd Cukalla : https://github.com/oerd
    
    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
    //! locale : Serbian Cyrillic [sr-cyrl]
    //! author : Milan Janačković<milanjanackovic@gmail.com> : https://github.com/milan-j
    
    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 1st is the first week of the year.
        }
    });
    
    //! moment.js locale configuration
    //! locale : Serbian [sr]
    //! author : Milan Janačković<milanjanackovic@gmail.com> : https://github.com/milan-j
    
    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 1st is the first week of the year.
        }
    });
    
    //! moment.js locale configuration
    //! locale : siSwati [ss]
    //! author : Nicolai Davies<mail@nicolai.io> : https://github.com/nicolaidavies
    
    
    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
    //! locale : Swedish [sv]
    //! author : Jens Alm : https://github.com/ulmus
    
    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
    //! locale : Swahili [sw]
    //! author : Fahad Kassim : https://github.com/fadsel
    
    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 1st is the first week of the year.
        }
    });
    
    //! moment.js locale configuration
    //! locale : Tamil [ta]
    //! author : Arjunkumar Krishnamoorthy : https://github.com/tk120404
    
    var symbolMap$13 = {
        '1': '௧',
        '2': '௨',
        '3': '௩',
        '4': '௪',
        '5': '௫',
        '6': '௬',
        '7': '௭',
        '8': '௮',
        '9': '௯',
        '0': '௦'
    };
    var numberMap$12 = {
        '௧': '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$12[match];
            });
        },
        postformat: function (string) {
            return string.replace(/\d/g, function (match) {
                return symbolMap$13[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 1st is the first week of the year.
        }
    });
    
    //! moment.js locale configuration
    //! locale : Telugu [te]
    //! author : Krishna Chaitanya Thota : https://github.com/kcthota
    
    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 1st is the first week of the year.
        }
    });
    
    //! moment.js locale configuration
    //! locale : Tetun Dili (East Timor) [tet]
    //! author : Joshua Brooks : https://github.com/joshbrooks
    //! author : Onorio De J. Afonso : https://github.com/marobo
    
    hooks.defineLocale('tet', {
        months : 'Janeiru_Fevereiru_Marsu_Abril_Maiu_Juniu_Juliu_Augustu_Setembru_Outubru_Novembru_Dezembru'.split('_'),
        monthsShort : 'Jan_Fev_Mar_Abr_Mai_Jun_Jul_Aug_Set_Out_Nov_Dez'.split('_'),
        weekdays : 'Domingu_Segunda_Tersa_Kuarta_Kinta_Sexta_Sabadu'.split('_'),
        weekdaysShort : 'Dom_Seg_Ters_Kua_Kint_Sext_Sab'.split('_'),
        weekdaysMin : 'Do_Seg_Te_Ku_Ki_Sex_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 : 'minutus %d',
            h : 'horas ida',
            hh : 'horas %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
    //! locale : Thai [th]
    //! author : Kridsada Thanabulpong : https://github.com/sirn
    
    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
    //! locale : Tagalog (Philippines) [tl-ph]
    //! author : Dan Hagman : https://github.com/hagmandan
    
    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
    //! locale : Klingon [tlh]
    //! author : Dominika Kruk : https://github.com/amaranthrose
    
    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$9(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$9,
            m : 'wa’ tup',
            mm : translate$9,
            h : 'wa’ rep',
            hh : translate$9,
            d : 'wa’ jaj',
            dd : translate$9,
            M : 'wa’ jar',
            MM : translate$9,
            y : 'wa’ DIS',
            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
    //! locale : Turkish [tr]
    //! authors : Erhan Gundogan : https://github.com/erhangundogan,
    //!           Burak Yiğit Kaya: https://github.com/BYK
    
    var suffixes$3 = {
        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'
        },
        dayOfMonthOrdinalParse: /\d{1,2}'(inci|nci|üncü|ncı|uncu|ıncı)/,
        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$3[a] || suffixes$3[b] || suffixes$3[c]);
        },
        week : {
            dow : 1, // Monday is the first day of the week.
            doy : 7  // The week that contains Jan 1st is the first week of the year.
        }
    });
    
    //! moment.js locale configuration
    //! locale : Talossan [tzl]
    //! author : Robin van der Vliet : https://github.com/robin0van0der0v
    //! author : Iustì Canun
    
    // 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
    //! locale : Central Atlas Tamazight Latin [tzm-latn]
    //! author : Abdel Said : https://github.com/abdelsaid
    
    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 1st is the first week of the year.
        }
    });
    
    //! moment.js locale configuration
    //! locale : Central Atlas Tamazight [tzm]
    //! author : Abdel Said : https://github.com/abdelsaid
    
    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 1st is the first week of the year.
        }
    });
    
    //! moment.js locale configuration
    //! locale : Ukrainian [uk]
    //! author : zemlanin : https://github.com/zemlanin
    //! Author : Menelion Elensúle : https://github.com/Oire
    
    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) {
            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 1st is the first week of the year.
        }
    });
    
    //! moment.js locale configuration
    //! locale : Urdu [ur]
    //! author : Sawood Alam : https://github.com/ibnesayeed
    //! author : Zack : https://github.com/ZackVision
    
    var months$8 = [
        'جنوری',
        'فروری',
        'مارچ',
        'اپریل',
        'مئی',
        'جون',
        'جولائی',
        'اگست',
        'ستمبر',
        'اکتوبر',
        'نومبر',
        'دسمبر'
    ];
    var days$2 = [
        'اتوار',
        'پیر',
        'منگل',
        'بدھ',
        'جمعرات',
        'جمعہ',
        'ہفتہ'
    ];
    
    hooks.defineLocale('ur', {
        months : months$8,
        monthsShort : months$8,
        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
    //! locale : Uzbek Latin [uz-latn]
    //! author : Rasulbek Mirzayev : github.com/Rasulbeeek
    
    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 1st is the first week of the year.
        }
    });
    
    //! moment.js locale configuration
    //! locale : Uzbek [uz]
    //! author : Sardor Muminov : https://github.com/muminoff
    
    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
    //! locale : Vietnamese [vi]
    //! author : Bang Nguyen : https://github.com/bangnk
    
    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
    //! locale : Pseudo [x-pseudo]
    //! author : Andrew Hood : https://github.com/andrewhood125
    
    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
    //! locale : Yoruba Nigeria [yo]
    //! author : Atolagbe Abisoye : https://github.com/andela-batolagbe
    
    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
    //! locale : Chinese (China) [zh-cn]
    //! author : suupic : https://github.com/suupic
    //! author : Zeno Zeng : https://github.com/zenozeng
    
    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
    //! locale : Chinese (Hong Kong) [zh-hk]
    //! author : Ben : https://github.com/ben-lin
    //! author : Chris Lam : https://github.com/hehachris
    //! author : Konstantin : https://github.com/skfd
    
    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
    //! locale : Chinese (Taiwan) [zh-tw]
    //! author : Ben : https://github.com/ben-lin
    //! author : Chris Lam : https://github.com/hehachris
    
    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 : '[下]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 年'
        }
    });
    
    hooks.locale('en');
    
    return hooks;
    
    })));
    
    !function(t,e){"use strict";"function"==typeof define&&define.amd?define(["moment"],e):"object"==typeof module&&module.exports?module.exports=e(require("moment")):e(t.moment)}(this,function(t){"use strict";function e(t){return t>96?t-87:t>64?t-29:t-48}function n(t){var n=0,o=t.split("."),r=o[0],s=o[1]||"",i=1,f=0,a=1;for(45===t.charCodeAt(0)&&(n=1,a=-1),n;n<r.length;n++)f=60*f+e(r.charCodeAt(n));for(n=0;n<s.length;n++)i/=60,f+=e(s.charCodeAt(n))*i;return f*a}function o(t){for(var e=0;e<t.length;e++)t[e]=n(t[e])}function r(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}function s(t,e){var n,o=[];for(n=0;n<e.length;n++)o[n]=t[e[n]];return o}function i(t){var e=t.split("|"),n=e[2].split(" "),i=e[3].split(""),f=e[4].split(" ");return o(n),o(i),o(f),r(f,i.length),{name:e[0],abbrs:s(e[1].split(" "),i),offsets:s(n,i),untils:f,population:0|e[5]}}function f(t){t&&this._set(i(t))}function a(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 u(t){this.zone=t,this.offsetScore=0,this.abbrScore=0}function c(t,e){for(var n,o;o=6e4*((e.at-t.at)/12e4|0);)(n=new a(new Date(t.at+o))).offset===t.offset?t=n:e=n;return t}function h(){var t,e,n,o=(new Date).getFullYear()-2,r=new a(new Date(o,0,1)),s=[r];for(n=1;n<48;n++)(e=new a(new Date(o,n,1))).offset!==r.offset&&(t=c(r,e),s.push(t),s.push(new a(new Date(t.at+6e4)))),r=e;for(n=0;n<4;n++)s.push(new a(new Date(o+n,0,1))),s.push(new a(new Date(o+n,6,1)));return s}function l(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 p(t,e){var n,r;for(o(e),n=0;n<e.length;n++)r=e[n],x[r]=x[r]||{},x[r][t]=!0}function d(t){var e,n,o,r=t.length,s={},i=[];for(e=0;e<r;e++){o=x[t[e].offset]||{};for(n in o)o.hasOwnProperty(n)&&(s[n]=!0)}for(e in s)s.hasOwnProperty(e)&&i.push(D[e]);return i}function m(){try{var t=Intl.DateTimeFormat().resolvedOptions().timeZone;if(t&&t.length>3){var e=D[v(t)];if(e)return e;y("Moment Timezone found "+t+" from the Intl api, but did not have that data loaded.")}}catch(t){}var n,o,r,s=h(),i=s.length,f=d(s),a=[];for(o=0;o<f.length;o++){for(n=new u(b(f[o]),i),r=0;r<i;r++)n.scoreOffsetAt(s[r]);a.push(n)}return a.sort(l),a.length>0?a[0].zone.name:void 0}function v(t){return(t||"").toLowerCase().replace(/\//g,"_")}function z(t){var e,n,o,r;for("string"==typeof t&&(t=[t]),e=0;e<t.length;e++)r=v(n=(o=t[e].split("|"))[0]),M[r]=t[e],D[r]=n,p(r,o[2].split(" "))}function b(t,e){t=v(t);var n,o=M[t];return o instanceof f?o:"string"==typeof o?(o=new f(o),M[t]=o,o):j[t]&&e!==b&&(n=b(j[t],b))?((o=M[t]=new f)._set(n),o.name=D[t],o):null}function g(t){var e,n,o,r;for("string"==typeof t&&(t=[t]),e=0;e<t.length;e++)o=v((n=t[e].split("|"))[0]),r=v(n[1]),j[o]=r,D[o]=n[0],j[r]=o,D[r]=n[1]}function _(t){return _.didShowError||(_.didShowError=!0,y("moment.tz.zoneExists('"+t+"') has been deprecated in favor of !moment.tz.zone('"+t+"')")),!!b(t)}function w(t){var e="X"===t._f||"x"===t._f;return!(!t._a||void 0!==t._tzm||e)}function y(t){"undefined"!=typeof console&&"function"==typeof console.error&&console.error(t)}function S(e){var n=Array.prototype.slice.call(arguments,0,-1),o=arguments[arguments.length-1],r=b(o),s=t.utc.apply(null,n);return r&&!t.isMoment(e)&&w(s)&&s.add(r.parse(s),"minutes"),s.tz(o),s}function O(t){return function(){return this._z?this._z.abbr(this):t.call(this)}}var A,M={},j={},D={},x={},T=t.version.split("."),Z=+T[0],F=+T[1];(Z<2||2===Z&&F<6)&&y("Moment Timezone requires Moment.js >= 2.6.0. You are using Moment.js "+t.version+". See momentjs.com"),f.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&&S.moveAmbiguousForward?e=n:e>o&&S.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 y("zone.offset has been deprecated in favor of zone.utcOffset"),this.offsets[this._index(t)]},utcOffset:function(t){return this.offsets[this._index(t)]}},u.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++},S.version="0.5.14",S.dataVersion="",S._zones=M,S._links=j,S._names=D,S.add=z,S.link=g,S.load=function(t){z(t.zones),g(t.links),S.dataVersion=t.version},S.zone=b,S.zoneExists=_,S.guess=function(t){return A&&!t||(A=m()),A},S.names=function(){var t,e=[];for(t in D)D.hasOwnProperty(t)&&(M[t]||M[j[t]])&&D[t]&&e.push(D[t]);return e.sort()},S.Zone=f,S.unpack=i,S.unpackBase60=n,S.needsOffset=w,S.moveInvalidForward=!0,S.moveAmbiguousForward=!1;var k=t.fn;t.tz=S,t.defaultZone=null,t.updateOffset=function(e,n){var o,r=t.defaultZone;void 0===e._z&&(r&&w(e)&&!e._isUTC&&(e._d=t.utc(e._a)._d,e.utc().add(r.parse(e),"minutes")),e._z=r),e._z&&(o=e._z.utcOffset(e),Math.abs(o)<16&&(o/=60),void 0!==e.utcOffset?e.utcOffset(-o,n):e.zone(o,n))},k.tz=function(e,n){return e?(this._z=b(e),this._z?t.updateOffset(this,n):y("Moment Timezone has no data for "+e+". See http://momentjs.com/timezone/docs/#/data-loading/."),this):this._z?this._z.name:void 0},k.zoneName=O(k.zoneName),k.zoneAbbr=O(k.zoneAbbr),k.utc=function(t){return function(){return this._z=null,t.apply(this,arguments)}}(k.utc),t.tz.setDefault=function(e){return(Z<2||2===Z&&F<9)&&y("Moment Timezone setDefault() requires Moment.js >= 2.9.0. You are using Moment.js "+t.version+"."),t.defaultZone=e?b(e):null,t};var C=t.momentProperties;return"[object Array]"===Object.prototype.toString.call(C)?(C.push("_z"),C.push("_a")):C&&(C._z=null),t});
    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',
            VERSION = '5.0.0-alpha12',
            DATA_KEY = '' + NAME,
            EVENT_KEY = '.' + DATA_KEY,
            EMIT_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: EMIT_EVENT_KEY + 'update',
            ERROR: EMIT_EVENT_KEY + 'error',
            HIDE: EMIT_EVENT_KEY + 'hide',
            SHOW: EMIT_EVENT_KEY + 'show'
        },
            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 MinViewModeNumber = 0,
            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() {
                    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() {
                    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._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;
                    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(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.widget)) {
                        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')) {
                    MinViewModeNumber = 2;
                }
                if (this._isEnabled('M')) {
                    MinViewModeNumber = 1;
                }
                if (this._isEnabled('d')) {
                    MinViewModeNumber = 0;
                }
    
                this.currentViewMode = Math.max(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.useStrict, this._options.timeZone);
                } else {
                    returnMoment = moment(d, this.parseFormats, 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!');
                }
    
                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, DateTimePicker.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: 'VERSION',
                get: function get() {
                    return VERSION;
                }
    
                /**
                 * @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;
                }
    
                /**
                 * @return {number}
                 */
    
            }, {
                key: 'MinViewModeNumber',
                get: function get() {
                    return MinViewModeNumber;
                }
            }, {
                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.0.0-alpha16 (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 v1.9.1 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',
            VERSION = '5.0.0-alpha12',
            DATA_KEY = '' + NAME,
            EVENT_KEY = '.' + DATA_KEY,
            EMIT_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: EMIT_EVENT_KEY + 'update',
            ERROR: EMIT_EVENT_KEY + 'error',
            HIDE: EMIT_EVENT_KEY + 'hide',
            SHOW: EMIT_EVENT_KEY + 'show'
        },
            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 MinViewModeNumber = 0,
            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() {
                    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() {
                    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._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;
                    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(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.widget)) {
                        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')) {
                    MinViewModeNumber = 2;
                }
                if (this._isEnabled('M')) {
                    MinViewModeNumber = 1;
                }
                if (this._isEnabled('d')) {
                    MinViewModeNumber = 0;
                }
    
                this.currentViewMode = Math.max(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.useStrict, this._options.timeZone);
                } else {
                    returnMoment = moment(d, this.parseFormats, 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!');
                }
    
                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, DateTimePicker.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: 'VERSION',
                get: function get() {
                    return VERSION;
                }
    
                /**
                 * @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;
                }
    
                /**
                 * @return {number}
                 */
    
            }, {
                key: 'MinViewModeNumber',
                get: function get() {
                    return MinViewModeNumber;
                }
            }, {
                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()) {
                    row.push($('<td>').append($('<a>').attr({
                        href: '#',
                        tabindex: '-1',
                        'data-action': 'togglePicker',
                        'title': this._options.tooltips.selectTime
                    }).append($('<span>').addClass(this._options.icons.time))));
                }
                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 === 'time' ? '' : '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 === 'time' ? '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._element).position(),
                    offset = (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">' + (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">' + 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 === DateTimePicker.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 === DateTimePicker.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 === DateTimePicker.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');
                            }
                            this._setValue(day.date(parseInt($(e.target).text(), 10)), this._getLastPickedDateIndex());
                            if (!this._hasTime() && !this._options.keepOpen && !this._options.inline) {
                                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('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('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._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, config, 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 - 2017 Robin Herbots
    * Licensed under the MIT license (http://www.opensource.org/licenses/mit-license.php)
    * Version: 3.3.11
    */
    
    !function(modules) {
        function __webpack_require__(moduleId) {
            if (installedModules[moduleId]) return installedModules[moduleId].exports;
            var module = installedModules[moduleId] = {
                i: moduleId,
                l: !1,
                exports: {}
            };
            return modules[moduleId].call(module.exports, module, module.exports, __webpack_require__), 
            module.l = !0, module.exports;
        }
        var installedModules = {};
        __webpack_require__.m = modules, __webpack_require__.c = installedModules, __webpack_require__.d = function(exports, name, getter) {
            __webpack_require__.o(exports, name) || Object.defineProperty(exports, name, {
                configurable: !1,
                enumerable: !0,
                get: getter
            });
        }, __webpack_require__.n = function(module) {
            var getter = module && module.__esModule ? function() {
                return module.default;
            } : function() {
                return module;
            };
            return __webpack_require__.d(getter, "a", getter), getter;
        }, __webpack_require__.o = function(object, property) {
            return Object.prototype.hasOwnProperty.call(object, property);
        }, __webpack_require__.p = "", __webpack_require__(__webpack_require__.s = 3);
    }([ function(module, exports, __webpack_require__) {
        "use strict";
        var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;
        "function" == typeof Symbol && Symbol.iterator;
        !function(factory) {
            __WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(2) ], void 0 !== (__WEBPACK_AMD_DEFINE_RESULT__ = "function" == typeof (__WEBPACK_AMD_DEFINE_FACTORY__ = factory) ? __WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__) : __WEBPACK_AMD_DEFINE_FACTORY__) && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__);
        }(function($) {
            return $;
        });
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__, _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(obj) {
            return typeof obj;
        } : function(obj) {
            return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
        };
        !function(factory) {
            __WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(0), __webpack_require__(10), __webpack_require__(11) ], 
            void 0 !== (__WEBPACK_AMD_DEFINE_RESULT__ = "function" == typeof (__WEBPACK_AMD_DEFINE_FACTORY__ = factory) ? __WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__) : __WEBPACK_AMD_DEFINE_FACTORY__) && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__);
        }(function($, window, document, undefined) {
            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 = !1, 
                !0 !== internal && ($.isPlainObject(alias) ? options = alias : (options = options || {}).alias = alias, 
                this.opts = $.extend(!0, {}, this.defaults, options), this.noMasksCache = options && options.definitions !== undefined, 
                this.userOptions = options || {}, this.isRTL = this.opts.numericInput, resolveAlias(this.opts.alias, options, this.opts));
            }
            function resolveAlias(aliasStr, options, opts) {
                var aliasDefinition = Inputmask.prototype.aliases[aliasStr];
                return aliasDefinition ? (aliasDefinition.alias && resolveAlias(aliasDefinition.alias, undefined, opts), 
                $.extend(!0, opts, aliasDefinition), $.extend(!0, opts, options), !0) : (null === opts.mask && (opts.mask = aliasStr), 
                !1);
            }
            function generateMaskSet(opts, nocache) {
                function generateMask(mask, metadata, opts) {
                    var regexMask = !1;
                    if (null !== mask && "" !== mask || ((regexMask = null !== opts.regex) ? mask = (mask = opts.regex).replace(/^(\^)(.*)(\$)$/, "$2") : (regexMask = !0, 
                    mask = ".*")), 1 === mask.length && !1 === opts.greedy && 0 !== opts.repeat && (opts.placeholder = ""), 
                    opts.repeat > 0 || "*" === opts.repeat || "+" === opts.repeat) {
                        var repeatStart = "*" === opts.repeat ? 0 : "+" === opts.repeat ? 1 : opts.repeat;
                        mask = opts.groupmarker.start + mask + opts.groupmarker.end + opts.quantifiermarker.start + repeatStart + "," + opts.repeat + opts.quantifiermarker.end;
                    }
                    var masksetDefinition, maskdefKey = regexMask ? "regex_" + opts.regex : opts.numericInput ? mask.split("").reverse().join("") : mask;
                    return Inputmask.prototype.masksCache[maskdefKey] === undefined || !0 === nocache ? (masksetDefinition = {
                        mask: mask,
                        maskToken: Inputmask.prototype.analyseMask(mask, regexMask, opts),
                        validPositions: {},
                        _buffer: undefined,
                        buffer: undefined,
                        tests: {},
                        metadata: metadata,
                        maskLength: undefined
                    }, !0 !== nocache && (Inputmask.prototype.masksCache[maskdefKey] = masksetDefinition, 
                    masksetDefinition = $.extend(!0, {}, Inputmask.prototype.masksCache[maskdefKey]))) : masksetDefinition = $.extend(!0, {}, Inputmask.prototype.masksCache[maskdefKey]), 
                    masksetDefinition;
                }
                if ($.isFunction(opts.mask) && (opts.mask = opts.mask(opts)), $.isArray(opts.mask)) {
                    if (opts.mask.length > 1) {
                        opts.keepStatic = null === opts.keepStatic || opts.keepStatic;
                        var altMask = opts.groupmarker.start;
                        return $.each(opts.numericInput ? opts.mask.reverse() : opts.mask, function(ndx, msk) {
                            altMask.length > 1 && (altMask += opts.groupmarker.end + opts.alternatormarker + opts.groupmarker.start), 
                            msk.mask === undefined || $.isFunction(msk.mask) ? altMask += msk : altMask += msk.mask;
                        }), altMask += opts.groupmarker.end, generateMask(altMask, opts.mask, opts);
                    }
                    opts.mask = opts.mask.pop();
                }
                return opts.mask && opts.mask.mask !== undefined && !$.isFunction(opts.mask.mask) ? generateMask(opts.mask.mask, opts.mask, opts) : generateMask(opts.mask, opts.mask, opts);
            }
            function maskScope(actionObj, maskset, opts) {
                function getMaskTemplate(baseOnInput, minimalPos, includeMode) {
                    minimalPos = minimalPos || 0;
                    var ndxIntlzr, test, testPos, maskTemplate = [], pos = 0, lvp = getLastValidPosition();
                    do {
                        !0 === baseOnInput && getMaskSet().validPositions[pos] ? (test = (testPos = getMaskSet().validPositions[pos]).match, 
                        ndxIntlzr = testPos.locator.slice(), maskTemplate.push(!0 === includeMode ? testPos.input : !1 === includeMode ? test.nativeDef : getPlaceholder(pos, test))) : (test = (testPos = getTestTemplate(pos, ndxIntlzr, pos - 1)).match, 
                        ndxIntlzr = testPos.locator.slice(), (!1 === opts.jitMasking || pos < lvp || "number" == typeof opts.jitMasking && isFinite(opts.jitMasking) && opts.jitMasking > pos) && maskTemplate.push(!1 === includeMode ? test.nativeDef : getPlaceholder(pos, test))), 
                        pos++;
                    } while ((maxLength === undefined || pos < maxLength) && (null !== test.fn || "" !== test.def) || minimalPos > pos);
                    return "" === maskTemplate[maskTemplate.length - 1] && maskTemplate.pop(), getMaskSet().maskLength = pos + 1, 
                    maskTemplate;
                }
                function getMaskSet() {
                    return maskset;
                }
                function resetMaskSet(soft) {
                    var maskset = getMaskSet();
                    maskset.buffer = undefined, !0 !== soft && (maskset.validPositions = {}, maskset.p = 0);
                }
                function getLastValidPosition(closestTo, strict, validPositions) {
                    var before = -1, after = -1, valids = validPositions || getMaskSet().validPositions;
                    closestTo === undefined && (closestTo = -1);
                    for (var posNdx in valids) {
                        var psNdx = parseInt(posNdx);
                        valids[psNdx] && (strict || !0 !== valids[psNdx].generatedInput) && (psNdx <= closestTo && (before = psNdx), 
                        psNdx >= closestTo && (after = psNdx));
                    }
                    return -1 !== before && closestTo - before > 1 || after < closestTo ? before : after;
                }
                function stripValidPositions(start, end, nocheck, strict) {
                    var i, startPos = start, positionsClone = $.extend(!0, {}, getMaskSet().validPositions), needsValidation = !1;
                    for (getMaskSet().p = start, i = end - 1; i >= startPos; i--) getMaskSet().validPositions[i] !== undefined && (!0 !== nocheck && (!getMaskSet().validPositions[i].match.optionality && function(pos) {
                        var posMatch = getMaskSet().validPositions[pos];
                        if (posMatch !== undefined && null === posMatch.match.fn) {
                            var prevMatch = getMaskSet().validPositions[pos - 1], nextMatch = getMaskSet().validPositions[pos + 1];
                            return prevMatch !== undefined && nextMatch !== undefined;
                        }
                        return !1;
                    }(i) || !1 === opts.canClearPosition(getMaskSet(), i, getLastValidPosition(), strict, opts)) || delete getMaskSet().validPositions[i]);
                    for (resetMaskSet(!0), i = startPos + 1; i <= getLastValidPosition(); ) {
                        for (;getMaskSet().validPositions[startPos] !== undefined; ) startPos++;
                        if (i < startPos && (i = startPos + 1), getMaskSet().validPositions[i] === undefined && isMask(i)) i++; else {
                            var t = getTestTemplate(i);
                            !1 === needsValidation && positionsClone[startPos] && positionsClone[startPos].match.def === t.match.def ? (getMaskSet().validPositions[startPos] = $.extend(!0, {}, positionsClone[startPos]), 
                            getMaskSet().validPositions[startPos].input = t.input, delete getMaskSet().validPositions[i], 
                            i++) : positionCanMatchDefinition(startPos, t.match.def) ? !1 !== isValid(startPos, t.input || getPlaceholder(i), !0) && (delete getMaskSet().validPositions[i], 
                            i++, needsValidation = !0) : isMask(i) || (i++, startPos--), startPos++;
                        }
                    }
                    resetMaskSet(!0);
                }
                function determineTestTemplate(tests, guessNextBest) {
                    for (var testPos, testPositions = tests, lvp = getLastValidPosition(), lvTest = getMaskSet().validPositions[lvp] || getTests(0)[0], lvTestAltArr = lvTest.alternation !== undefined ? lvTest.locator[lvTest.alternation].toString().split(",") : [], ndx = 0; ndx < testPositions.length && (!((testPos = testPositions[ndx]).match && (opts.greedy && !0 !== testPos.match.optionalQuantifier || (!1 === testPos.match.optionality || !1 === testPos.match.newBlockMarker) && !0 !== testPos.match.optionalQuantifier) && (lvTest.alternation === undefined || lvTest.alternation !== testPos.alternation || testPos.locator[lvTest.alternation] !== undefined && checkAlternationMatch(testPos.locator[lvTest.alternation].toString().split(","), lvTestAltArr))) || !0 === guessNextBest && (null !== testPos.match.fn || /[0-9a-bA-Z]/.test(testPos.match.def))); ndx++) ;
                    return testPos;
                }
                function getTestTemplate(pos, ndxIntlzr, tstPs) {
                    return getMaskSet().validPositions[pos] || determineTestTemplate(getTests(pos, ndxIntlzr ? ndxIntlzr.slice() : ndxIntlzr, tstPs));
                }
                function getTest(pos) {
                    return getMaskSet().validPositions[pos] ? getMaskSet().validPositions[pos] : getTests(pos)[0];
                }
                function positionCanMatchDefinition(pos, def) {
                    for (var valid = !1, tests = getTests(pos), tndx = 0; tndx < tests.length; tndx++) if (tests[tndx].match && tests[tndx].match.def === def) {
                        valid = !0;
                        break;
                    }
                    return valid;
                }
                function getTests(pos, ndxIntlzr, tstPs) {
                    function resolveTestFromToken(maskToken, ndxInitializer, loopNdx, quantifierRecurse) {
                        function handleMatch(match, loopNdx, quantifierRecurse) {
                            function isFirstMatch(latestMatch, tokenGroup) {
                                var firstMatch = 0 === $.inArray(latestMatch, tokenGroup.matches);
                                return firstMatch || $.each(tokenGroup.matches, function(ndx, match) {
                                    if (!0 === match.isQuantifier && (firstMatch = isFirstMatch(latestMatch, tokenGroup.matches[ndx - 1]))) return !1;
                                }), firstMatch;
                            }
                            function resolveNdxInitializer(pos, alternateNdx, targetAlternation) {
                                var bestMatch, indexPos;
                                if (getMaskSet().validPositions[pos - 1] && targetAlternation && getMaskSet().tests[pos]) for (var vpAlternation = getMaskSet().validPositions[pos - 1].locator, tpAlternation = getMaskSet().tests[pos][0].locator, i = 0; i < targetAlternation; i++) if (vpAlternation[i] !== tpAlternation[i]) return vpAlternation.slice(targetAlternation + 1);
                                return (getMaskSet().tests[pos] || getMaskSet().validPositions[pos]) && $.each(getMaskSet().tests[pos] || [ getMaskSet().validPositions[pos] ], function(ndx, lmnt) {
                                    var alternation = targetAlternation !== undefined ? targetAlternation : lmnt.alternation, ndxPos = lmnt.locator[alternation] !== undefined ? lmnt.locator[alternation].toString().indexOf(alternateNdx) : -1;
                                    (indexPos === undefined || ndxPos < indexPos) && -1 !== ndxPos && (bestMatch = lmnt, 
                                    indexPos = ndxPos);
                                }), bestMatch ? bestMatch.locator.slice((targetAlternation !== undefined ? targetAlternation : bestMatch.alternation) + 1) : targetAlternation !== undefined ? resolveNdxInitializer(pos, alternateNdx) : undefined;
                            }
                            if (testPos > 1e4) 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) return matches.push({
                                match: match,
                                locator: loopNdx.reverse(),
                                cd: cacheDependency
                            }), !0;
                            if (match.matches !== undefined) {
                                if (match.isGroup && quantifierRecurse !== match) {
                                    if (match = handleMatch(maskToken.matches[$.inArray(match, maskToken.matches) + 1], loopNdx)) return !0;
                                } else if (match.isOptional) {
                                    var optionalToken = match;
                                    if (match = resolveTestFromToken(match, ndxInitializer, loopNdx, quantifierRecurse)) {
                                        if (latestMatch = matches[matches.length - 1].match, !isFirstMatch(latestMatch, optionalToken)) return !0;
                                        insertStop = !0, testPos = pos;
                                    }
                                } else if (match.isAlternator) {
                                    var maltMatches, alternateToken = match, malternateMatches = [], currentMatches = matches.slice(), loopNdxCnt = loopNdx.length, altIndex = ndxInitializer.length > 0 ? ndxInitializer.shift() : -1;
                                    if (-1 === altIndex || "string" == typeof altIndex) {
                                        var amndx, currentPos = testPos, ndxInitializerClone = ndxInitializer.slice(), altIndexArr = [];
                                        if ("string" == typeof altIndex) altIndexArr = altIndex.split(","); else for (amndx = 0; amndx < alternateToken.matches.length; amndx++) altIndexArr.push(amndx);
                                        for (var ndx = 0; ndx < altIndexArr.length; ndx++) {
                                            if (amndx = parseInt(altIndexArr[ndx]), matches = [], ndxInitializer = resolveNdxInitializer(testPos, amndx, loopNdxCnt) || ndxInitializerClone.slice(), 
                                            !0 !== (match = handleMatch(alternateToken.matches[amndx] || maskToken.matches[amndx], [ amndx ].concat(loopNdx), quantifierRecurse) || match) && match !== undefined && altIndexArr[altIndexArr.length - 1] < alternateToken.matches.length) {
                                                var ntndx = $.inArray(match, maskToken.matches) + 1;
                                                maskToken.matches.length > ntndx && (match = handleMatch(maskToken.matches[ntndx], [ ntndx ].concat(loopNdx.slice(1, loopNdx.length)), quantifierRecurse)) && (altIndexArr.push(ntndx.toString()), 
                                                $.each(matches, function(ndx, lmnt) {
                                                    lmnt.alternation = loopNdx.length - 1;
                                                }));
                                            }
                                            maltMatches = matches.slice(), testPos = currentPos, matches = [];
                                            for (var ndx1 = 0; ndx1 < maltMatches.length; ndx1++) {
                                                var altMatch = maltMatches[ndx1], dropMatch = !1;
                                                altMatch.alternation = altMatch.alternation || loopNdxCnt;
                                                for (var ndx2 = 0; ndx2 < malternateMatches.length; ndx2++) {
                                                    var altMatch2 = malternateMatches[ndx2];
                                                    if ("string" != typeof altIndex || -1 !== $.inArray(altMatch.locator[altMatch.alternation].toString(), altIndexArr)) {
                                                        if (function(source, target) {
                                                            return source.match.nativeDef === target.match.nativeDef || source.match.def === target.match.nativeDef || source.match.nativeDef === target.match.def;
                                                        }(altMatch, altMatch2)) {
                                                            dropMatch = !0, altMatch.alternation === altMatch2.alternation && -1 === altMatch2.locator[altMatch2.alternation].toString().indexOf(altMatch.locator[altMatch.alternation]) && (altMatch2.locator[altMatch2.alternation] = altMatch2.locator[altMatch2.alternation] + "," + altMatch.locator[altMatch.alternation], 
                                                            altMatch2.alternation = altMatch.alternation), altMatch.match.nativeDef === altMatch2.match.def && (altMatch.locator[altMatch.alternation] = altMatch2.locator[altMatch2.alternation], 
                                                            malternateMatches.splice(malternateMatches.indexOf(altMatch2), 1, altMatch));
                                                            break;
                                                        }
                                                        if (altMatch.match.def === altMatch2.match.def) {
                                                            dropMatch = !1;
                                                            break;
                                                        }
                                                        if (function(source, target) {
                                                            return null === source.match.fn && null !== target.match.fn && target.match.fn.test(source.match.def, getMaskSet(), pos, !1, opts, !1);
                                                        }(altMatch, altMatch2) || function(source, target) {
                                                            return null !== source.match.fn && null !== target.match.fn && target.match.fn.test(source.match.def.replace(/[\[\]]/g, ""), getMaskSet(), pos, !1, opts, !1);
                                                        }(altMatch, altMatch2)) {
                                                            altMatch.alternation === altMatch2.alternation && -1 === altMatch.locator[altMatch.alternation].toString().indexOf(altMatch2.locator[altMatch2.alternation].toString().split("")[0]) && (altMatch.na = altMatch.na || altMatch.locator[altMatch.alternation].toString(), 
                                                            -1 === altMatch.na.indexOf(altMatch.locator[altMatch.alternation].toString().split("")[0]) && (altMatch.na = altMatch.na + "," + altMatch.locator[altMatch2.alternation].toString().split("")[0]), 
                                                            dropMatch = !0, altMatch.locator[altMatch.alternation] = altMatch2.locator[altMatch2.alternation].toString().split("")[0] + "," + altMatch.locator[altMatch.alternation], 
                                                            malternateMatches.splice(malternateMatches.indexOf(altMatch2), 0, altMatch));
                                                            break;
                                                        }
                                                    }
                                                }
                                                dropMatch || malternateMatches.push(altMatch);
                                            }
                                        }
                                        "string" == typeof altIndex && (malternateMatches = $.map(malternateMatches, function(lmnt, ndx) {
                                            if (isFinite(ndx)) {
                                                var alternation = lmnt.alternation, altLocArr = lmnt.locator[alternation].toString().split(",");
                                                lmnt.locator[alternation] = undefined, lmnt.alternation = undefined;
                                                for (var alndx = 0; alndx < altLocArr.length; alndx++) -1 !== $.inArray(altLocArr[alndx], altIndexArr) && (lmnt.locator[alternation] !== undefined ? (lmnt.locator[alternation] += ",", 
                                                lmnt.locator[alternation] += altLocArr[alndx]) : lmnt.locator[alternation] = parseInt(altLocArr[alndx]), 
                                                lmnt.alternation = alternation);
                                                if (lmnt.locator[alternation] !== undefined) return lmnt;
                                            }
                                        })), 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 !0;
                                } else if (match.isQuantifier && quantifierRecurse !== maskToken.matches[$.inArray(match, maskToken.matches) - 1]) for (var qt = match, 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];
                                    if (match = handleMatch(tokenGroup, [ qndx ].concat(loopNdx), tokenGroup)) {
                                        if (latestMatch = matches[matches.length - 1].match, latestMatch.optionalQuantifier = qndx > qt.quantifier.min - 1, 
                                        isFirstMatch(latestMatch, tokenGroup)) {
                                            if (qndx > qt.quantifier.min - 1) {
                                                insertStop = !0, testPos = pos;
                                                break;
                                            }
                                            return !0;
                                        }
                                        return !0;
                                    }
                                } else if (match = resolveTestFromToken(match, ndxInitializer, loopNdx, quantifierRecurse)) return !0;
                            } else testPos++;
                        }
                        for (var tndx = ndxInitializer.length > 0 ? ndxInitializer.shift() : 0; tndx < maskToken.matches.length; tndx++) if (!0 !== maskToken.matches[tndx].isQuantifier) {
                            var match = handleMatch(maskToken.matches[tndx], [ tndx ].concat(loopNdx), quantifierRecurse);
                            if (match && testPos === pos) return match;
                            if (testPos > pos) break;
                        }
                    }
                    function filterTests(tests) {
                        if (opts.keepStatic && pos > 0 && tests.length > 1 + ("" === tests[tests.length - 1].match.def ? 1 : 0) && !0 !== tests[0].match.optionality && !0 !== tests[0].match.optionalQuantifier && null === tests[0].match.fn && !/[0-9a-bA-Z]/.test(tests[0].match.def)) {
                            if (getMaskSet().validPositions[pos - 1] === undefined) return [ determineTestTemplate(tests) ];
                            if (getMaskSet().validPositions[pos - 1].alternation === tests[0].alternation) return [ determineTestTemplate(tests) ];
                            if (getMaskSet().validPositions[pos - 1]) return [ determineTestTemplate(tests) ];
                        }
                        return tests;
                    }
                    var latestMatch, maskTokens = getMaskSet().maskToken, testPos = ndxIntlzr ? tstPs : 0, ndxInitializer = ndxIntlzr ? ndxIntlzr.slice() : [ 0 ], matches = [], insertStop = !1, cacheDependency = ndxIntlzr ? ndxIntlzr.join("") : "";
                    if (pos > -1) {
                        if (ndxIntlzr === undefined) {
                            for (var test, previousPos = pos - 1; (test = getMaskSet().validPositions[previousPos] || getMaskSet().tests[previousPos]) === undefined && previousPos > -1; ) previousPos--;
                            test !== undefined && previousPos > -1 && (ndxInitializer = function(tests) {
                                var locator = [];
                                return $.isArray(tests) || (tests = [ tests ]), tests.length > 0 && (tests[0].alternation === undefined ? 0 === (locator = determineTestTemplate(tests.slice()).locator.slice()).length && (locator = tests[0].locator.slice()) : $.each(tests, function(ndx, tst) {
                                    if ("" !== tst.def) if (0 === locator.length) locator = tst.locator.slice(); else for (var i = 0; i < locator.length; i++) tst.locator[i] && -1 === locator[i].toString().indexOf(tst.locator[i]) && (locator[i] += "," + tst.locator[i]);
                                })), locator;
                            }(test), cacheDependency = ndxInitializer.join(""), testPos = previousPos);
                        }
                        if (getMaskSet().tests[pos] && getMaskSet().tests[pos][0].cd === cacheDependency) return filterTests(getMaskSet().tests[pos]);
                        for (var mtndx = ndxInitializer.shift(); mtndx < maskTokens.length && !(resolveTestFromToken(maskTokens[mtndx], ndxInitializer, [ mtndx ]) && testPos === pos || testPos > pos); mtndx++) ;
                    }
                    return (0 === matches.length || insertStop) && matches.push({
                        match: {
                            fn: null,
                            cardinality: 0,
                            optionality: !0,
                            casing: null,
                            def: "",
                            placeholder: ""
                        },
                        locator: [],
                        cd: cacheDependency
                    }), ndxIntlzr !== undefined && getMaskSet().tests[pos] ? filterTests($.extend(!0, [], matches)) : (getMaskSet().tests[pos] = $.extend(!0, [], matches), 
                    filterTests(getMaskSet().tests[pos]));
                }
                function getBufferTemplate() {
                    return getMaskSet()._buffer === undefined && (getMaskSet()._buffer = getMaskTemplate(!1, 1), 
                    getMaskSet().buffer === undefined && (getMaskSet().buffer = getMaskSet()._buffer.slice())), 
                    getMaskSet()._buffer;
                }
                function getBuffer(noCache) {
                    return getMaskSet().buffer !== undefined && !0 !== noCache || (getMaskSet().buffer = getMaskTemplate(!0, getLastValidPosition(), !0)), 
                    getMaskSet().buffer;
                }
                function refreshFromBuffer(start, end, buffer) {
                    var i, p;
                    if (!0 === start) resetMaskSet(), start = 0, end = buffer.length; else for (i = start; i < end; i++) delete getMaskSet().validPositions[i];
                    for (p = start, i = start; i < end; i++) if (resetMaskSet(!0), buffer[i] !== opts.skipOptionalPartCharacter) {
                        var valResult = isValid(p, buffer[i], !0, !0);
                        !1 !== valResult && (resetMaskSet(!0), 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];
                        elem = 0 === pos || posBefore && posBefore.input === String.fromCharCode(Inputmask.keyCode.SPACE) ? elem.toUpperCase() : 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) {
                    for (var naNdx, altArrC = opts.greedy ? altArr2 : altArr2.slice(0, 1), isMatch = !1, naArr = na !== undefined ? na.split(",") : [], i = 0; i < naArr.length; i++) -1 !== (naNdx = altArr1.indexOf(naArr[i])) && altArr1.splice(naNdx, 1);
                    for (var alndx = 0; alndx < altArr1.length; alndx++) if (-1 !== $.inArray(altArr1[alndx], altArrC)) {
                        isMatch = !0;
                        break;
                    }
                    return isMatch;
                }
                function isValid(pos, c, strict, fromSetValid, fromAlternate, validateOnly) {
                    function isSelection(posObj) {
                        var selection = isRTL ? posObj.begin - posObj.end > 1 || posObj.begin - posObj.end == 1 : posObj.end - posObj.begin > 1 || posObj.end - posObj.begin == 1;
                        return selection && 0 === posObj.begin && posObj.end === getMaskSet().maskLength ? "full" : selection;
                    }
                    function _isValid(position, c, strict) {
                        var rslt = !1;
                        return $.each(getTests(position), function(ndx, tst) {
                            for (var test = tst.match, loopend = c ? 1 : 0, chrs = "", i = test.cardinality; i > loopend; i--) chrs += getBufferElement(position - (i - 1));
                            if (c && (chrs += c), getBuffer(!0), !1 !== (rslt = null != test.fn ? test.fn.test(chrs, getMaskSet(), position, strict, opts, isSelection(pos)) : (c === test.def || c === opts.skipOptionalPartCharacter) && "" !== test.def && {
                                c: getPlaceholder(position, test, !0) || test.def,
                                pos: position
                            })) {
                                var elem = rslt.c !== undefined ? rslt.c : c;
                                elem = elem === opts.skipOptionalPartCharacter && null === test.fn ? getPlaceholder(position, test, !0) || test.def : elem;
                                var validatedPos = position, possibleModifiedBuffer = getBuffer();
                                if (rslt.remove !== undefined && ($.isArray(rslt.remove) || (rslt.remove = [ rslt.remove ]), 
                                $.each(rslt.remove.sort(function(a, b) {
                                    return b - a;
                                }), function(ndx, lmnt) {
                                    stripValidPositions(lmnt, lmnt + 1, !0);
                                })), rslt.insert !== undefined && ($.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, !0, fromSetValid);
                                })), rslt.refreshFromBuffer) {
                                    var refresh = rslt.refreshFromBuffer;
                                    if (refreshFromBuffer(!0 === refresh ? refresh : refresh.start, refresh.end, possibleModifiedBuffer), 
                                    rslt.pos === undefined && rslt.c === undefined) return rslt.pos = getLastValidPosition(), 
                                    !1;
                                    if ((validatedPos = rslt.pos !== undefined ? rslt.pos : position) !== position) return rslt = $.extend(rslt, isValid(validatedPos, elem, !0, fromSetValid)), 
                                    !1;
                                } else if (!0 !== rslt && rslt.pos !== undefined && rslt.pos !== position && (validatedPos = rslt.pos, 
                                refreshFromBuffer(position, validatedPos, getBuffer().slice()), validatedPos !== position)) return rslt = $.extend(rslt, isValid(validatedPos, elem, !0)), 
                                !1;
                                return (!0 === rslt || rslt.pos !== undefined || rslt.c !== undefined) && (ndx > 0 && resetMaskSet(!0), 
                                setValidPosition(validatedPos, $.extend({}, tst, {
                                    input: casing(elem, test, validatedPos)
                                }), fromSetValid, isSelection(pos)) || (rslt = !1), !1);
                            }
                        }), rslt;
                    }
                    function setValidPosition(pos, validTest, fromSetValid, isSelection) {
                        if (isSelection || opts.insertMode && getMaskSet().validPositions[pos] !== undefined && fromSetValid === undefined) {
                            var i, positionsClone = $.extend(!0, {}, getMaskSet().validPositions), lvp = getLastValidPosition(undefined, !0);
                            for (i = pos; i <= lvp; i++) delete getMaskSet().validPositions[i];
                            getMaskSet().validPositions[pos] = $.extend(!0, {}, validTest);
                            var j, valid = !0, vps = getMaskSet().validPositions, needsValidation = !1, initialLength = getMaskSet().maskLength;
                            for (i = j = pos; i <= lvp; i++) {
                                var t = positionsClone[i];
                                if (t !== undefined) for (var posMatch = j; posMatch < getMaskSet().maskLength && (null === t.match.fn && vps[i] && (!0 === vps[i].match.optionalQuantifier || !0 === vps[i].match.optionality) || null != t.match.fn); ) {
                                    if (posMatch++, !1 === needsValidation && positionsClone[posMatch] && positionsClone[posMatch].match.def === t.match.def) getMaskSet().validPositions[posMatch] = $.extend(!0, {}, positionsClone[posMatch]), 
                                    getMaskSet().validPositions[posMatch].input = t.input, fillMissingNonMask(posMatch), 
                                    j = posMatch, valid = !0; else if (positionCanMatchDefinition(posMatch, t.match.def)) {
                                        var result = isValid(posMatch, t.input, !0, !0);
                                        valid = !1 !== result, j = result.caret || result.insert ? getLastValidPosition() : posMatch, 
                                        needsValidation = !0;
                                    } else if (!(valid = !0 === t.generatedInput) && posMatch >= getMaskSet().maskLength - 1) break;
                                    if (getMaskSet().maskLength < initialLength && (getMaskSet().maskLength = initialLength), 
                                    valid) break;
                                }
                                if (!valid) break;
                            }
                            if (!valid) return getMaskSet().validPositions = $.extend(!0, {}, positionsClone), 
                            resetMaskSet(!0), !1;
                        } else getMaskSet().validPositions[pos] = $.extend(!0, {}, validTest);
                        return resetMaskSet(!0), !0;
                    }
                    function fillMissingNonMask(maskPos) {
                        for (var pndx = maskPos - 1; pndx > -1 && !getMaskSet().validPositions[pndx]; pndx--) ;
                        var testTemplate, testsFromPos;
                        for (pndx++; pndx < maskPos; pndx++) getMaskSet().validPositions[pndx] === undefined && (!1 === opts.jitMasking || opts.jitMasking > pndx) && ("" === (testsFromPos = getTests(pndx, getTestTemplate(pndx - 1).locator, pndx - 1).slice())[testsFromPos.length - 1].match.def && testsFromPos.pop(), 
                        (testTemplate = determineTestTemplate(testsFromPos)) && (testTemplate.match.def === opts.radixPointDefinitionSymbol || !isMask(pndx, !0) || $.inArray(opts.radixPoint, getBuffer()) < pndx && testTemplate.match.fn && testTemplate.match.fn.test(getPlaceholder(pndx), getMaskSet(), pndx, !1, opts)) && !1 !== (result = _isValid(pndx, getPlaceholder(pndx, testTemplate.match, !0) || (null == testTemplate.match.fn ? testTemplate.match.def : "" !== getPlaceholder(pndx) ? getPlaceholder(pndx) : getBuffer()[pndx]), !0)) && (getMaskSet().validPositions[result.pos || pndx].generatedInput = !0));
                    }
                    strict = !0 === strict;
                    var maskPos = pos;
                    pos.begin !== undefined && (maskPos = isRTL && !isSelection(pos) ? pos.end : pos.begin);
                    var result = !0, positionsClone = $.extend(!0, {}, getMaskSet().validPositions);
                    if ($.isFunction(opts.preValidation) && !strict && !0 !== fromSetValid && !0 !== validateOnly && (result = opts.preValidation(getBuffer(), maskPos, c, isSelection(pos), opts)), 
                    !0 === result) {
                        if (fillMissingNonMask(maskPos), isSelection(pos) && (handleRemove(undefined, Inputmask.keyCode.DELETE, pos, !0, !0), 
                        maskPos = getMaskSet().p), maskPos < getMaskSet().maskLength && (maxLength === undefined || maskPos < maxLength) && (result = _isValid(maskPos, c, strict), 
                        (!strict || !0 === fromSetValid) && !1 === result && !0 !== validateOnly)) {
                            var currentPosValid = getMaskSet().validPositions[maskPos];
                            if (!currentPosValid || null !== currentPosValid.match.fn || currentPosValid.match.def !== c && c !== opts.skipOptionalPartCharacter) {
                                if ((opts.insertMode || getMaskSet().validPositions[seekNext(maskPos)] === undefined) && !isMask(maskPos, !0)) for (var nPos = maskPos + 1, snPos = seekNext(maskPos); nPos <= snPos; nPos++) if (!1 !== (result = _isValid(nPos, c, strict))) {
                                    !function(originalPos, newPos) {
                                        var vp = getMaskSet().validPositions[newPos];
                                        if (vp) for (var targetLocator = vp.locator, tll = targetLocator.length, ps = originalPos; ps < newPos; ps++) if (getMaskSet().validPositions[ps] === undefined && !isMask(ps, !0)) {
                                            var tests = getTests(ps).slice(), bestMatch = determineTestTemplate(tests, !0), equality = -1;
                                            "" === tests[tests.length - 1].match.def && tests.pop(), $.each(tests, function(ndx, tst) {
                                                for (var i = 0; i < tll; i++) {
                                                    if (tst.locator[i] === undefined || !checkAlternationMatch(tst.locator[i].toString().split(","), targetLocator[i].toString().split(","), tst.na)) {
                                                        var targetAI = targetLocator[i], bestMatchAI = bestMatch.locator[i], tstAI = tst.locator[i];
                                                        targetAI - bestMatchAI > Math.abs(targetAI - tstAI) && (bestMatch = tst);
                                                        break;
                                                    }
                                                    equality < i && (equality = i, bestMatch = tst);
                                                }
                                            }), (bestMatch = $.extend({}, bestMatch, {
                                                input: getPlaceholder(ps, bestMatch.match, !0) || bestMatch.match.def
                                            })).generatedInput = !0, setValidPosition(ps, bestMatch, !0), getMaskSet().validPositions[newPos] = undefined, 
                                            _isValid(newPos, vp.input, !0);
                                        }
                                    }(maskPos, result.pos !== undefined ? result.pos : nPos), maskPos = nPos;
                                    break;
                                }
                            } else result = {
                                caret: seekNext(maskPos)
                            };
                        }
                        !1 === result && opts.keepStatic && !strict && !0 !== fromAlternate && (result = function(pos, c, strict) {
                            var lastAlt, alternation, altPos, prevAltPos, i, validPos, altNdxs, decisionPos, validPsClone = $.extend(!0, {}, getMaskSet().validPositions), isValidRslt = !1, lAltPos = getLastValidPosition();
                            for (prevAltPos = getMaskSet().validPositions[lAltPos]; lAltPos >= 0; lAltPos--) if ((altPos = getMaskSet().validPositions[lAltPos]) && altPos.alternation !== undefined) {
                                if (lastAlt = lAltPos, alternation = getMaskSet().validPositions[lastAlt].alternation, 
                                prevAltPos.locator[altPos.alternation] !== altPos.locator[altPos.alternation]) break;
                                prevAltPos = altPos;
                            }
                            if (alternation !== undefined) {
                                decisionPos = parseInt(lastAlt);
                                var decisionTaker = prevAltPos.locator[prevAltPos.alternation || alternation] !== undefined ? prevAltPos.locator[prevAltPos.alternation || alternation] : altNdxs[0];
                                decisionTaker.length > 0 && (decisionTaker = decisionTaker.split(",")[0]);
                                var possibilityPos = getMaskSet().validPositions[decisionPos], prevPos = getMaskSet().validPositions[decisionPos - 1];
                                $.each(getTests(decisionPos, prevPos ? prevPos.locator : undefined, decisionPos - 1), function(ndx, test) {
                                    altNdxs = test.locator[alternation] ? test.locator[alternation].toString().split(",") : [];
                                    for (var mndx = 0; mndx < altNdxs.length; mndx++) {
                                        var validInputs = [], staticInputsBeforePos = 0, staticInputsBeforePosAlternate = 0, verifyValidInput = !1;
                                        if (decisionTaker < altNdxs[mndx] && (test.na === undefined || -1 === $.inArray(altNdxs[mndx], test.na.split(",")) || -1 === $.inArray(decisionTaker.toString(), altNdxs))) {
                                            getMaskSet().validPositions[decisionPos] = $.extend(!0, {}, test);
                                            var possibilities = getMaskSet().validPositions[decisionPos].locator;
                                            for (getMaskSet().validPositions[decisionPos].locator[alternation] = parseInt(altNdxs[mndx]), 
                                            null == test.match.fn ? (possibilityPos.input !== test.match.def && (verifyValidInput = !0, 
                                            !0 !== possibilityPos.generatedInput && validInputs.push(possibilityPos.input)), 
                                            staticInputsBeforePosAlternate++, getMaskSet().validPositions[decisionPos].generatedInput = !/[0-9a-bA-Z]/.test(test.match.def), 
                                            getMaskSet().validPositions[decisionPos].input = test.match.def) : getMaskSet().validPositions[decisionPos].input = possibilityPos.input, 
                                            i = decisionPos + 1; i < getLastValidPosition(undefined, !0) + 1; i++) (validPos = getMaskSet().validPositions[i]) && !0 !== validPos.generatedInput && /[0-9a-bA-Z]/.test(validPos.input) ? validInputs.push(validPos.input) : i < pos && staticInputsBeforePos++, 
                                            delete getMaskSet().validPositions[i];
                                            for (verifyValidInput && validInputs[0] === test.match.def && validInputs.shift(), 
                                            resetMaskSet(!0), isValidRslt = !0; validInputs.length > 0; ) {
                                                var input = validInputs.shift();
                                                if (input !== opts.skipOptionalPartCharacter && !(isValidRslt = isValid(getLastValidPosition(undefined, !0) + 1, input, !1, fromSetValid, !0))) break;
                                            }
                                            if (isValidRslt) {
                                                getMaskSet().validPositions[decisionPos].locator = possibilities;
                                                var targetLvp = getLastValidPosition(pos) + 1;
                                                for (i = decisionPos + 1; i < getLastValidPosition() + 1; i++) ((validPos = getMaskSet().validPositions[i]) === undefined || null == validPos.match.fn) && i < pos + (staticInputsBeforePosAlternate - staticInputsBeforePos) && staticInputsBeforePosAlternate++;
                                                isValidRslt = isValid((pos += staticInputsBeforePosAlternate - staticInputsBeforePos) > targetLvp ? targetLvp : pos, c, strict, fromSetValid, !0);
                                            }
                                            if (isValidRslt) return !1;
                                            resetMaskSet(), getMaskSet().validPositions = $.extend(!0, {}, validPsClone);
                                        }
                                    }
                                });
                            }
                            return isValidRslt;
                        }(maskPos, c, strict)), !0 === result && (result = {
                            pos: maskPos
                        });
                    }
                    if ($.isFunction(opts.postValidation) && !1 !== result && !strict && !0 !== fromSetValid && !0 !== validateOnly) {
                        var postResult = opts.postValidation(getBuffer(!0), result, opts);
                        if (postResult.refreshFromBuffer && postResult.buffer) {
                            var refresh = postResult.refreshFromBuffer;
                            refreshFromBuffer(!0 === refresh ? refresh : refresh.start, refresh.end, postResult.buffer);
                        }
                        result = !0 === postResult ? result : postResult;
                    }
                    return result && result.pos === undefined && (result.pos = maskPos), !1 !== result && !0 !== validateOnly || (resetMaskSet(!0), 
                    getMaskSet().validPositions = $.extend(!0, {}, positionsClone)), result;
                }
                function isMask(pos, strict) {
                    var test = getTestTemplate(pos).match;
                    if ("" === test.def && (test = getTest(pos).match), null != test.fn) return test.fn;
                    if (!0 !== strict && pos > -1) {
                        var tests = getTests(pos);
                        return tests.length > 1 + ("" === tests[tests.length - 1].match.def ? 1 : 0);
                    }
                    return !1;
                }
                function seekNext(pos, newBlock) {
                    var maskL = getMaskSet().maskLength;
                    if (pos >= maskL) return maskL;
                    var position = pos;
                    for (getTests(maskL + 1).length > 1 && (getMaskTemplate(!0, maskL + 1, !0), maskL = getMaskSet().maskLength); ++position < maskL && (!0 === newBlock && (!0 !== getTest(position).match.newBlockMarker || !isMask(position)) || !0 !== newBlock && !isMask(position)); ) ;
                    return position;
                }
                function seekPrevious(pos, newBlock) {
                    var tests, position = pos;
                    if (position <= 0) return 0;
                    for (;--position > 0 && (!0 === newBlock && !0 !== getTest(position).match.newBlockMarker || !0 !== newBlock && !isMask(position) && ((tests = getTests(position)).length < 2 || 2 === tests.length && "" === tests[1].match.def)); ) ;
                    return position;
                }
                function getBufferElement(position) {
                    return getMaskSet().validPositions[position] === undefined ? getPlaceholder(position) : getMaskSet().validPositions[position].input;
                }
                function writeBuffer(input, buffer, caretPos, event, triggerInputEvent) {
                    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(!0 === refresh ? refresh : refresh.start, refresh.end, result.buffer || buffer), 
                                buffer = getBuffer(!0);
                            }
                            caretPos !== undefined && (caretPos = result.caret !== undefined ? result.caret : caretPos);
                        }
                    }
                    input !== undefined && (input.inputmask._valueSet(buffer.join("")), caretPos === undefined || event !== undefined && "blur" === event.type ? renderColorMask(input, caretPos, 0 === buffer.length) : android && event && "input" === event.type ? setTimeout(function() {
                        caret(input, caretPos);
                    }, 0) : caret(input, caretPos), !0 === triggerInputEvent && (skipInputEvent = !0, 
                    $(input).trigger("input")));
                }
                function getPlaceholder(pos, test, returnPL) {
                    if ((test = test || getTest(pos).match).placeholder !== undefined || !0 === returnPL) return $.isFunction(test.placeholder) ? test.placeholder(opts) : test.placeholder;
                    if (null === test.fn) {
                        if (pos > -1 && getMaskSet().validPositions[pos] === undefined) {
                            var prevTest, tests = getTests(pos), staticAlternations = [];
                            if (tests.length > 1 + ("" === tests[tests.length - 1].match.def ? 1 : 0)) for (var i = 0; i < tests.length; i++) if (!0 !== tests[i].match.optionality && !0 !== tests[i].match.optionalQuantifier && (null === tests[i].match.fn || prevTest === undefined || !1 !== tests[i].match.fn.test(prevTest.match.def, getMaskSet(), pos, !0, opts)) && (staticAlternations.push(tests[i]), 
                            null === tests[i].match.fn && (prevTest = tests[i]), staticAlternations.length > 1 && /[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 checkVal(input, writeOut, strict, nptvl, initiatingEvent) {
                    function isTemplateMatch(ndx, charCodes) {
                        return -1 !== getBufferTemplate().slice(ndx, seekNext(ndx)).join("").indexOf(charCodes) && !isMask(ndx) && getTest(ndx).match.nativeDef === charCodes.charAt(charCodes.length - 1);
                    }
                    var inputValue = nptvl.slice(), charCodes = "", initialNdx = -1, result = undefined;
                    if (resetMaskSet(), strict || !0 === opts.autoUnmask) initialNdx = seekNext(initialNdx); else {
                        var staticInput = getBufferTemplate().slice(0, seekNext(-1)).join(""), matches = inputValue.join("").match(new RegExp("^" + Inputmask.escapeRegex(staticInput), "g"));
                        matches && matches.length > 0 && (inputValue.splice(0, matches.length * staticInput.length), 
                        initialNdx = seekNext(initialNdx));
                    }
                    if (-1 === initialNdx ? (getMaskSet().p = seekNext(initialNdx), initialNdx = 0) : getMaskSet().p = initialNdx, 
                    $.each(inputValue, function(ndx, charCode) {
                        if (charCode !== undefined) if (getMaskSet().validPositions[ndx] === undefined && inputValue[ndx] === getPlaceholder(ndx) && isMask(ndx, !0) && !1 === isValid(ndx, inputValue[ndx], !0, undefined, undefined, !0)) getMaskSet().p++; else {
                            var keypress = new $.Event("_checkval");
                            keypress.which = charCode.charCodeAt(0), charCodes += charCode;
                            var lvp = getLastValidPosition(undefined, !0), lvTest = getMaskSet().validPositions[lvp], nextTest = getTestTemplate(lvp + 1, lvTest ? lvTest.locator.slice() : undefined, lvp);
                            if (!isTemplateMatch(initialNdx, charCodes) || strict || opts.autoUnmask) {
                                var pos = strict ? ndx : null == nextTest.match.fn && nextTest.match.optionality && lvp + 1 < getMaskSet().p ? lvp + 1 : getMaskSet().p;
                                result = EventHandlers.keypressEvent.call(input, keypress, !0, !1, strict, pos), 
                                initialNdx = pos + 1, charCodes = "";
                            } else result = EventHandlers.keypressEvent.call(input, keypress, !0, !1, !0, lvp + 1);
                            if (!1 !== result && !strict && $.isFunction(opts.onBeforeWrite)) {
                                var origResult = result;
                                if (result = opts.onBeforeWrite.call(inputmask, keypress, getBuffer(), result.forwardPosition, opts), 
                                (result = $.extend(origResult, result)) && result.refreshFromBuffer) {
                                    var refresh = result.refreshFromBuffer;
                                    refreshFromBuffer(!0 === refresh ? refresh : refresh.start, refresh.end, result.buffer), 
                                    resetMaskSet(!0), result.caret && (getMaskSet().p = result.caret, result.forwardPosition = result.caret);
                                }
                            }
                        }
                    }), writeOut) {
                        var caretPos = undefined;
                        document.activeElement === input && result && (caretPos = opts.numericInput ? seekPrevious(result.forwardPosition) : result.forwardPosition), 
                        writeBuffer(input, getBuffer(), caretPos, initiatingEvent || new $.Event("checkval"), initiatingEvent && "input" === initiatingEvent.type);
                    }
                }
                function unmaskedvalue(input) {
                    if (input) {
                        if (input.inputmask === undefined) return input.value;
                        input.inputmask && input.inputmask.refreshValue && EventHandlers.setValueEvent.call(input);
                    }
                    var umValue = [], vps = getMaskSet().validPositions;
                    for (var pndx in vps) vps[pndx].match && null != vps[pndx].match.fn && umValue.push(vps[pndx].input);
                    var unmaskedValue = 0 === umValue.length ? "" : (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) {
                        return !0 === notranslate || !isRTL || "number" != typeof pos || opts.greedy && "" === opts.placeholder || (pos = getBuffer().join("").length - pos), 
                        pos;
                    }
                    var range;
                    if (begin === undefined) return input.setSelectionRange ? (begin = input.selectionStart, 
                    end = input.selectionEnd) : window.getSelection ? (range = window.getSelection().getRangeAt(0)).commonAncestorContainer.parentNode !== input && range.commonAncestorContainer !== input || (begin = range.startOffset, 
                    end = range.endOffset) : document.selection && document.selection.createRange && (end = (begin = 0 - (range = document.selection.createRange()).duplicate().moveStart("character", -input.inputmask._valueGet().length)) + range.text.length), 
                    {
                        begin: translatePosition(begin),
                        end: translatePosition(end)
                    };
                    if (begin.begin !== undefined && (end = begin.end, begin = begin.begin), "number" == typeof begin) {
                        begin = translatePosition(begin), end = "number" == typeof (end = translatePosition(end)) ? end : begin;
                        var scrollCalc = parseInt(((input.ownerDocument.defaultView || window).getComputedStyle ? (input.ownerDocument.defaultView || window).getComputedStyle(input, null) : input.currentStyle).fontSize) * end;
                        if (input.scrollLeft = scrollCalc > input.scrollWidth ? scrollCalc : 0, mobile || !1 !== opts.insertMode || begin !== end || end++, 
                        input.setSelectionRange) input.selectionStart = begin, input.selectionEnd = end; else if (window.getSelection) {
                            if (range = document.createRange(), input.firstChild === undefined || null === input.firstChild) {
                                var textNode = document.createTextNode("");
                                input.appendChild(textNode);
                            }
                            range.setStart(input.firstChild, begin < input.inputmask._valueGet().length ? begin : input.inputmask._valueGet().length), 
                            range.setEnd(input.firstChild, end < input.inputmask._valueGet().length ? end : input.inputmask._valueGet().length), 
                            range.collapse(!0);
                            var sel = window.getSelection();
                            sel.removeAllRanges(), sel.addRange(range);
                        } else input.createTextRange && ((range = input.createTextRange()).collapse(!0), 
                        range.moveEnd("character", end), range.moveStart("character", begin), range.select());
                        renderColorMask(input, {
                            begin: begin,
                            end: end
                        });
                    }
                }
                function determineLastRequiredPosition(returnDefinition) {
                    var pos, testPos, buffer = getBuffer(), bl = buffer.length, lvp = getLastValidPosition(), positions = {}, lvTest = getMaskSet().validPositions[lvp], ndxIntlzr = lvTest !== undefined ? lvTest.locator.slice() : undefined;
                    for (pos = lvp + 1; pos < buffer.length; pos++) ndxIntlzr = (testPos = getTestTemplate(pos, ndxIntlzr, pos - 1)).locator.slice(), 
                    positions[pos] = $.extend(!0, {}, testPos);
                    var lvTestAlt = lvTest && lvTest.alternation !== undefined ? lvTest.locator[lvTest.alternation] : undefined;
                    for (pos = bl - 1; pos > lvp && (((testPos = positions[pos]).match.optionality || testPos.match.optionalQuantifier && testPos.match.newBlockMarker || lvTestAlt && (lvTestAlt !== positions[pos].locator[lvTest.alternation] && null != testPos.match.fn || null === testPos.match.fn && testPos.locator[lvTest.alternation] && checkAlternationMatch(testPos.locator[lvTest.alternation].toString().split(","), lvTestAlt.toString().split(",")) && "" !== getTests(pos)[0].def)) && buffer[pos] === getPlaceholder(pos, testPos.match)); pos--) bl--;
                    return returnDefinition ? {
                        l: bl,
                        def: positions[bl] ? positions[bl].match : undefined
                    } : bl;
                }
                function clearOptionalTail(buffer) {
                    for (var validPos, rl = determineLastRequiredPosition(), bl = buffer.length, lv = getMaskSet().validPositions[getLastValidPosition()]; rl < bl && !isMask(rl, !0) && (validPos = lv !== undefined ? getTestTemplate(rl, lv.locator.slice(""), lv) : getTest(rl)) && !0 !== validPos.match.optionality && (!0 !== validPos.match.optionalQuantifier && !0 !== validPos.match.newBlockMarker || rl + 1 === bl && "" === (lv !== undefined ? getTestTemplate(rl + 1, lv.locator.slice(""), lv) : getTest(rl + 1)).match.def); ) rl++;
                    for (;(validPos = getMaskSet().validPositions[rl - 1]) && validPos && validPos.match.optionality && validPos.input === opts.skipOptionalPartCharacter; ) rl--;
                    return buffer.splice(rl), buffer;
                }
                function isComplete(buffer) {
                    if ($.isFunction(opts.isComplete)) return opts.isComplete(buffer, opts);
                    if ("*" === opts.repeat) return undefined;
                    var complete = !1, lrp = determineLastRequiredPosition(!0), aml = seekPrevious(lrp.l);
                    if (lrp.def === undefined || lrp.def.newBlockMarker || lrp.def.optionality || lrp.def.optionalQuantifier) {
                        complete = !0;
                        for (var i = 0; i <= aml; i++) {
                            var test = getTestTemplate(i).match;
                            if (null !== test.fn && getMaskSet().validPositions[i] === undefined && !0 !== test.optionality && !0 !== test.optionalQuantifier || null === test.fn && buffer[i] !== getPlaceholder(i, test)) {
                                complete = !1;
                                break;
                            }
                        }
                    }
                    return complete;
                }
                function handleRemove(input, k, pos, strict, fromIsValid) {
                    if ((opts.numericInput || isRTL) && (k === Inputmask.keyCode.BACKSPACE ? k = Inputmask.keyCode.DELETE : k === Inputmask.keyCode.DELETE && (k = Inputmask.keyCode.BACKSPACE), 
                    isRTL)) {
                        var pend = pos.end;
                        pos.end = pos.begin, pos.begin = pend;
                    }
                    k === Inputmask.keyCode.BACKSPACE && (pos.end - pos.begin < 1 || !1 === opts.insertMode) ? (pos.begin = seekPrevious(pos.begin), 
                    getMaskSet().validPositions[pos.begin] !== undefined && getMaskSet().validPositions[pos.begin].input === opts.groupSeparator && pos.begin--) : k === Inputmask.keyCode.DELETE && pos.begin === pos.end && (pos.end = isMask(pos.end, !0) && getMaskSet().validPositions[pos.end] && getMaskSet().validPositions[pos.end].input !== opts.radixPoint ? pos.end + 1 : seekNext(pos.end) + 1, 
                    getMaskSet().validPositions[pos.begin] !== undefined && getMaskSet().validPositions[pos.begin].input === opts.groupSeparator && pos.end++), 
                    stripValidPositions(pos.begin, pos.end, !1, strict), !0 !== strict && function() {
                        if (opts.keepStatic) {
                            for (var validInputs = [], lastAlt = getLastValidPosition(-1, !0), positionsClone = $.extend(!0, {}, getMaskSet().validPositions), prevAltPos = getMaskSet().validPositions[lastAlt]; lastAlt >= 0; lastAlt--) {
                                var altPos = getMaskSet().validPositions[lastAlt];
                                if (altPos) {
                                    if (!0 !== altPos.generatedInput && /[0-9a-bA-Z]/.test(altPos.input) && validInputs.push(altPos.input), 
                                    delete getMaskSet().validPositions[lastAlt], altPos.alternation !== undefined && altPos.locator[altPos.alternation] !== prevAltPos.locator[altPos.alternation]) break;
                                    prevAltPos = altPos;
                                }
                            }
                            if (lastAlt > -1) for (getMaskSet().p = seekNext(getLastValidPosition(-1, !0)); validInputs.length > 0; ) {
                                var keypress = new $.Event("keypress");
                                keypress.which = validInputs.pop().charCodeAt(0), EventHandlers.keypressEvent.call(input, keypress, !0, !1, !1, getMaskSet().p);
                            } else getMaskSet().validPositions = $.extend(!0, {}, positionsClone);
                        }
                    }();
                    var lvp = getLastValidPosition(pos.begin, !0);
                    if (lvp < pos.begin) getMaskSet().p = seekNext(lvp); else if (!0 !== strict && (getMaskSet().p = pos.begin, 
                    !0 !== fromIsValid)) for (;getMaskSet().p < lvp && getMaskSet().validPositions[getMaskSet().p] === undefined; ) getMaskSet().p++;
                }
                function initializeColorMask(input) {
                    function findCaretPos(clientx) {
                        var caretPos, e = document.createElement("span");
                        for (var style in computedStyle) isNaN(style) && -1 !== style.indexOf("font") && (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 itl, inputText = input.inputmask._valueGet(), previousWidth = 0;
                        for (caretPos = 0, itl = inputText.length; caretPos <= itl; caretPos++) {
                            if (e.innerHTML += inputText.charAt(caretPos) || "_", e.offsetWidth >= clientx) {
                                var offset1 = clientx - previousWidth, offset2 = e.offsetWidth - clientx;
                                e.innerHTML = inputText.charAt(caretPos), caretPos = (offset1 -= e.offsetWidth / 3) < offset2 ? caretPos - 1 : caretPos;
                                break;
                            }
                            previousWidth = e.offsetWidth;
                        }
                        return document.body.removeChild(e), caretPos;
                    }
                    var computedStyle = (input.ownerDocument.defaultView || window).getComputedStyle(input, null), template = document.createElement("div");
                    template.style.width = computedStyle.width, template.style.textAlign = computedStyle.textAlign, 
                    (colorMask = document.createElement("div")).className = "im-colormask", input.parentNode.insertBefore(colorMask, input), 
                    input.parentNode.removeChild(input), colorMask.appendChild(template), colorMask.appendChild(input), 
                    input.style.left = template.offsetLeft + "px", $(input).on("click", function(e) {
                        return caret(input, findCaretPos(e.clientX)), EventHandlers.clickEvent.call(input, [ e ]);
                    }), $(input).on("keydown", function(e) {
                        e.shiftKey || !1 === opts.insertMode || setTimeout(function() {
                            renderColorMask(input);
                        }, 0);
                    });
                }
                function renderColorMask(input, caretPos, clear) {
                    function handleStatic() {
                        isStatic || null !== test.fn && testPos.input !== undefined ? isStatic && (null !== test.fn && testPos.input !== undefined || "" === test.def) && (isStatic = !1, 
                        maskTemplate += "</span>") : (isStatic = !0, maskTemplate += "<span class='im-static'>");
                    }
                    function handleCaret(force) {
                        !0 !== force && pos !== caretPos.begin || document.activeElement !== input || (maskTemplate += "<span class='im-caret' style='border-right-width: 1px;border-right-style: solid;'></span>");
                    }
                    var test, testPos, ndxIntlzr, maskTemplate = "", isStatic = !1, pos = 0;
                    if (colorMask !== undefined) {
                        var buffer = getBuffer();
                        if (caretPos === undefined ? caretPos = caret(input) : caretPos.begin === undefined && (caretPos = {
                            begin: caretPos,
                            end: caretPos
                        }), !0 !== clear) {
                            var lvp = getLastValidPosition();
                            do {
                                handleCaret(), getMaskSet().validPositions[pos] ? (testPos = getMaskSet().validPositions[pos], 
                                test = testPos.match, ndxIntlzr = testPos.locator.slice(), handleStatic(), maskTemplate += buffer[pos]) : (testPos = getTestTemplate(pos, ndxIntlzr, pos - 1), 
                                test = testPos.match, ndxIntlzr = testPos.locator.slice(), (!1 === opts.jitMasking || pos < lvp || "number" == typeof opts.jitMasking && isFinite(opts.jitMasking) && opts.jitMasking > pos) && (handleStatic(), 
                                maskTemplate += getPlaceholder(pos, test))), pos++;
                            } while ((maxLength === undefined || pos < maxLength) && (null !== test.fn || "" !== test.def) || lvp > pos || isStatic);
                            -1 === maskTemplate.indexOf("im-caret") && handleCaret(!0), isStatic && handleStatic();
                        }
                        var template = colorMask.getElementsByTagName("div")[0];
                        template.innerHTML = maskTemplate, input.inputmask.positionColorMask(input, template);
                    }
                }
                maskset = maskset || this.maskset, opts = opts || this.opts;
                var undoValue, $el, maxLength, colorMask, inputmask = this, el = this.el, isRTL = this.isRTL, skipKeyPressEvent = !1, skipInputEvent = !1, ignorable = !1, mouseEnter = !1, EventRuler = {
                    on: function(input, eventName, eventHandler) {
                        var ev = function(e) {
                            if (this.inputmask === undefined && "FORM" !== this.nodeName) {
                                var imOpts = $.data(this, "_inputmask_opts");
                                imOpts ? new Inputmask(imOpts).mask(this) : EventRuler.off(this);
                            } else {
                                if ("setvalue" === e.type || "FORM" === this.nodeName || !(this.disabled || this.readOnly && !("keydown" === e.type && e.ctrlKey && 67 === e.keyCode || !1 === opts.tabThrough && e.keyCode === Inputmask.keyCode.TAB))) {
                                    switch (e.type) {
                                      case "input":
                                        if (!0 === skipInputEvent) return skipInputEvent = !1, e.preventDefault();
                                        break;
    
                                      case "keydown":
                                        skipKeyPressEvent = !1, skipInputEvent = !1;
                                        break;
    
                                      case "keypress":
                                        if (!0 === skipKeyPressEvent) return e.preventDefault();
                                        skipKeyPressEvent = !0;
                                        break;
    
                                      case "click":
                                        if (iemobile || iphone) {
                                            var that = this, args = arguments;
                                            return setTimeout(function() {
                                                eventHandler.apply(that, args);
                                            }, 0), !1;
                                        }
                                    }
                                    var returnVal = eventHandler.apply(this, arguments);
                                    return !1 === returnVal && (e.preventDefault(), e.stopPropagation()), returnVal;
                                }
                                e.preventDefault();
                            }
                        };
                        input.inputmask.events[eventName] = input.inputmask.events[eventName] || [], input.inputmask.events[eventName].push(ev), 
                        -1 !== $.inArray(eventName, [ "submit", "reset" ]) ? null !== input.form && $(input.form).on(eventName, ev) : $(input).on(eventName, ev);
                    },
                    off: function(input, event) {
                        if (input.inputmask && input.inputmask.events) {
                            var events;
                            event ? (events = [])[event] = input.inputmask.events[event] : events = input.inputmask.events, 
                            $.each(events, function(eventName, evArr) {
                                for (;evArr.length > 0; ) {
                                    var ev = evArr.pop();
                                    -1 !== $.inArray(eventName, [ "submit", "reset" ]) ? null !== input.form && $(input.form).off(eventName, ev) : $(input).off(eventName, ev);
                                }
                                delete input.inputmask.events[eventName];
                            });
                        }
                    }
                }, EventHandlers = {
                    keydownEvent: function(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 && !function(eventName) {
                            var el = document.createElement("input"), evName = "on" + eventName, isSupported = evName in el;
                            return isSupported || (el.setAttribute(evName, "return;"), isSupported = "function" == typeof el[evName]), 
                            el = null, isSupported;
                        }("cut")) e.preventDefault(), handleRemove(input, k, pos), writeBuffer(input, getBuffer(!0), getMaskSet().p, e, input.inputmask._valueGet() !== getBuffer().join("")), 
                        input.inputmask._valueGet() === getBufferTemplate().join("") ? $input.trigger("cleared") : !0 === isComplete(getBuffer()) && $input.trigger("complete"); else if (k === Inputmask.keyCode.END || k === Inputmask.keyCode.PAGE_DOWN) {
                            e.preventDefault();
                            var caretPos = seekNext(getLastValidPosition());
                            opts.insertMode || caretPos !== getMaskSet().maskLength || e.shiftKey || caretPos--, 
                            caret(input, e.shiftKey ? pos.begin : caretPos, caretPos, !0);
                        } else k === Inputmask.keyCode.HOME && !e.shiftKey || k === Inputmask.keyCode.PAGE_UP ? (e.preventDefault(), 
                        caret(input, 0, e.shiftKey ? pos.begin : 0, !0)) : (opts.undoOnEscape && k === Inputmask.keyCode.ESCAPE || 90 === k && e.ctrlKey) && !0 !== e.altKey ? (checkVal(input, !0, !1, undoValue.split("")), 
                        $input.trigger("click")) : k !== Inputmask.keyCode.INSERT || e.shiftKey || e.ctrlKey ? !0 === opts.tabThrough && k === Inputmask.keyCode.TAB ? (!0 === e.shiftKey ? (null === getTest(pos.begin).match.fn && (pos.begin = seekNext(pos.begin)), 
                        pos.end = seekPrevious(pos.begin, !0), pos.begin = seekPrevious(pos.end, !0)) : (pos.begin = seekNext(pos.begin, !0), 
                        pos.end = seekNext(pos.begin, !0), pos.end < getMaskSet().maskLength && pos.end--), 
                        pos.begin < getMaskSet().maskLength && (e.preventDefault(), caret(input, pos.begin, pos.end))) : e.shiftKey || !1 === opts.insertMode && (k === Inputmask.keyCode.RIGHT ? setTimeout(function() {
                            var caretPos = caret(input);
                            caret(input, caretPos.begin);
                        }, 0) : k === Inputmask.keyCode.LEFT && setTimeout(function() {
                            var caretPos = caret(input);
                            caret(input, isRTL ? caretPos.begin + 1 : caretPos.begin - 1);
                        }, 0)) : (opts.insertMode = !opts.insertMode, caret(input, opts.insertMode || pos.begin !== getMaskSet().maskLength ? pos.begin : pos.begin - 1));
                        opts.onKeyDown.call(this, e, getBuffer(), caret(input).begin, opts), ignorable = -1 !== $.inArray(k, opts.ignorables);
                    },
                    keypressEvent: function(e, checkval, writeOut, strict, ndx) {
                        var input = this, $input = $(input), k = e.which || e.charCode || e.keyCode;
                        if (!(!0 === checkval || e.ctrlKey && e.altKey) && (e.ctrlKey || e.metaKey || ignorable)) return k === Inputmask.keyCode.ENTER && undoValue !== getBuffer().join("") && (undoValue = getBuffer().join(""), 
                        setTimeout(function() {
                            $input.trigger("change");
                        }, 0)), !0;
                        if (k) {
                            46 === k && !1 === e.shiftKey && "" !== opts.radixPoint && (k = opts.radixPoint.charCodeAt(0));
                            var forwardPosition, pos = checkval ? {
                                begin: ndx,
                                end: ndx
                            } : caret(input), c = String.fromCharCode(k);
                            getMaskSet().writeOutBuffer = !0;
                            var valResult = isValid(pos, c, strict);
                            if (!1 !== valResult && (resetMaskSet(!0), forwardPosition = valResult.caret !== undefined ? valResult.caret : checkval ? valResult.pos + 1 : seekNext(valResult.pos), 
                            getMaskSet().p = forwardPosition), !1 !== writeOut && (setTimeout(function() {
                                opts.onKeyValidation.call(input, k, valResult, opts);
                            }, 0), getMaskSet().writeOutBuffer && !1 !== valResult)) {
                                var buffer = getBuffer();
                                writeBuffer(input, buffer, opts.numericInput && valResult.caret === undefined ? seekPrevious(forwardPosition) : forwardPosition, e, !0 !== checkval), 
                                !0 !== checkval && setTimeout(function() {
                                    !0 === isComplete(buffer) && $input.trigger("complete");
                                }, 0);
                            }
                            if (e.preventDefault(), checkval) return !1 !== valResult && (valResult.forwardPosition = forwardPosition), 
                            valResult;
                        }
                    },
                    pasteEvent: function(e) {
                        var tempValue, input = this, ev = e.originalEvent || e, $input = $(input), inputValue = input.inputmask._valueGet(!0), caretPos = caret(input);
                        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 = ""), 
                        valueAfterCaret === (isRTL ? getBufferTemplate().reverse() : getBufferTemplate()).slice(caretPos.end).join("") && (valueAfterCaret = ""), 
                        isRTL && (tempValue = valueBeforeCaret, valueBeforeCaret = valueAfterCaret, valueAfterCaret = tempValue), 
                        window.clipboardData && window.clipboardData.getData) inputValue = valueBeforeCaret + window.clipboardData.getData("Text") + valueAfterCaret; else {
                            if (!ev.clipboardData || !ev.clipboardData.getData) return !0;
                            inputValue = valueBeforeCaret + ev.clipboardData.getData("text/plain") + valueAfterCaret;
                        }
                        var pasteValue = inputValue;
                        if ($.isFunction(opts.onBeforePaste)) {
                            if (!1 === (pasteValue = opts.onBeforePaste.call(inputmask, inputValue, opts))) return e.preventDefault();
                            pasteValue || (pasteValue = inputValue);
                        }
                        return checkVal(input, !1, !1, isRTL ? pasteValue.split("").reverse() : pasteValue.toString().split("")), 
                        writeBuffer(input, getBuffer(), seekNext(getLastValidPosition()), e, undoValue !== getBuffer().join("")), 
                        !0 === isComplete(getBuffer()) && $input.trigger("complete"), e.preventDefault();
                    },
                    inputFallBackEvent: function(e) {
                        var input = this, inputValue = input.inputmask._valueGet();
                        if (getBuffer().join("") !== inputValue) {
                            var caretPos = caret(input);
                            if (!1 === function(input, inputValue, caretPos) {
                                if ("." === inputValue.charAt(caretPos.begin - 1) && "" !== opts.radixPoint && ((inputValue = inputValue.split(""))[caretPos.begin - 1] = opts.radixPoint.charAt(0), 
                                inputValue = inputValue.join("")), inputValue.charAt(caretPos.begin - 1) === opts.radixPoint && inputValue.length > getBuffer().length) {
                                    var keypress = new $.Event("keypress");
                                    return keypress.which = opts.radixPoint.charCodeAt(0), EventHandlers.keypressEvent.call(input, keypress, !0, !0, !1, caretPos.begin - 1), 
                                    !1;
                                }
                            }(input, inputValue, caretPos)) return !1;
                            if (inputValue = inputValue.replace(new RegExp("(" + Inputmask.escapeRegex(getBufferTemplate().join("")) + ")*"), ""), 
                            !1 === function(input, inputValue, caretPos) {
                                if (iemobile) {
                                    var inputChar = inputValue.replace(getBuffer().join(""), "");
                                    if (1 === inputChar.length) {
                                        var keypress = new $.Event("keypress");
                                        return keypress.which = inputChar.charCodeAt(0), EventHandlers.keypressEvent.call(input, keypress, !0, !0, !1, getMaskSet().validPositions[caretPos.begin - 1] ? caretPos.begin : caretPos.begin - 1), 
                                        !1;
                                    }
                                }
                            }(input, inputValue, caretPos)) return !1;
                            caretPos.begin > inputValue.length && (caret(input, inputValue.length), caretPos = caret(input));
                            var buffer = getBuffer().join(""), frontPart = inputValue.substr(0, caretPos.begin), backPart = inputValue.substr(caretPos.begin), frontBufferPart = buffer.substr(0, caretPos.begin), backBufferPart = buffer.substr(caretPos.begin), selection = caretPos, entries = "", isEntry = !1;
                            if (frontPart !== frontBufferPart) {
                                selection.begin = 0;
                                for (var fpl = (isEntry = frontPart.length >= frontBufferPart.length) ? frontPart.length : frontBufferPart.length, i = 0; frontPart.charAt(i) === frontBufferPart.charAt(i) && i < fpl; i++) selection.begin++;
                                isEntry && (entries += frontPart.slice(selection.begin, selection.end));
                            }
                            backPart !== backBufferPart && (backPart.length > backBufferPart.length ? isEntry && (selection.end = selection.begin) : backPart.length < backBufferPart.length ? selection.end += backBufferPart.length - backPart.length : backPart.charAt(0) !== backBufferPart.charAt(0) && selection.end++), 
                            writeBuffer(input, getBuffer(), selection), entries.length > 0 ? $.each(entries.split(""), function(ndx, entry) {
                                var keypress = new $.Event("keypress");
                                keypress.which = entry.charCodeAt(0), ignorable = !1, EventHandlers.keypressEvent.call(input, keypress);
                            }) : (selection.begin === selection.end - 1 && caret(input, seekPrevious(selection.begin + 1), selection.end), 
                            e.keyCode = Inputmask.keyCode.DELETE, EventHandlers.keydownEvent.call(input, e)), 
                            e.preventDefault();
                        }
                    },
                    setValueEvent: function(e) {
                        this.inputmask.refreshValue = !1;
                        var input = this, value = input.inputmask._valueGet(!0);
                        $.isFunction(opts.onBeforeMask) && (value = opts.onBeforeMask.call(inputmask, value, opts) || value), 
                        value = value.split(""), checkVal(input, !0, !1, isRTL ? value.reverse() : value), 
                        undoValue = getBuffer().join(""), (opts.clearMaskOnLostFocus || opts.clearIncomplete) && input.inputmask._valueGet() === getBufferTemplate().join("") && input.inputmask._valueSet("");
                    },
                    focusEvent: function(e) {
                        var input = this, nptValue = input.inputmask._valueGet();
                        opts.showMaskOnFocus && (!opts.showMaskOnHover || opts.showMaskOnHover && "" === nptValue) && (input.inputmask._valueGet() !== getBuffer().join("") ? writeBuffer(input, getBuffer(), seekNext(getLastValidPosition())) : !1 === mouseEnter && caret(input, seekNext(getLastValidPosition()))), 
                        !0 === opts.positionCaretOnTab && !1 === mouseEnter && "" !== nptValue && (writeBuffer(input, getBuffer(), caret(input)), 
                        EventHandlers.clickEvent.apply(input, [ e, !0 ])), undoValue = getBuffer().join("");
                    },
                    mouseleaveEvent: function(e) {
                        var input = this;
                        if (mouseEnter = !1, opts.clearMaskOnLostFocus && document.activeElement !== input) {
                            var buffer = getBuffer().slice(), nptValue = input.inputmask._valueGet();
                            nptValue !== input.getAttribute("placeholder") && "" !== nptValue && (-1 === getLastValidPosition() && nptValue === getBufferTemplate().join("") ? buffer = [] : clearOptionalTail(buffer), 
                            writeBuffer(input, buffer));
                        }
                    },
                    clickEvent: function(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 !0;
                                    var radixPos = $.inArray(opts.radixPoint, getBuffer());
                                    if (-1 !== radixPos) {
                                        for (var vp in vps) if (radixPos < vp && vps[vp].input !== getPlaceholder(vp)) return !1;
                                        return !0;
                                    }
                                }
                            }
                            return !1;
                        }
                        var input = this;
                        setTimeout(function() {
                            if (document.activeElement === input) {
                                var selectedCaret = caret(input);
                                if (tabbed && (isRTL ? selectedCaret.end = selectedCaret.begin : selectedCaret.begin = selectedCaret.end), 
                                selectedCaret.begin === selectedCaret.end) switch (opts.positionCaretOnClick) {
                                  case "none":
                                    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, !0), lastPosition = seekNext(lvclickPosition);
                                    if (clickPosition < lastPosition) caret(input, isMask(clickPosition, !0) || isMask(clickPosition - 1, !0) ? clickPosition : seekNext(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 && !0 !== tt.match.optionalQuantifier && !0 !== tt.match.newBlockMarker || !isMask(lastPosition, !0) && tt.match.def === placeholder) {
                                            var newPos = seekNext(lastPosition);
                                            (clickPosition >= newPos || clickPosition === lastPosition) && (lastPosition = newPos);
                                        }
                                        caret(input, lastPosition);
                                    }
                                }
                            }
                        }, 0);
                    },
                    dblclickEvent: function(e) {
                        var input = this;
                        setTimeout(function() {
                            caret(input, 0, seekNext(getLastValidPosition()));
                        }, 0);
                    },
                    cutEvent: function(e) {
                        var input = this, $input = $(input), pos = caret(input), ev = e.originalEvent || e, 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("")), 
                        document.execCommand && document.execCommand("copy"), handleRemove(input, Inputmask.keyCode.DELETE, pos), 
                        writeBuffer(input, getBuffer(), getMaskSet().p, e, undoValue !== getBuffer().join("")), 
                        input.inputmask._valueGet() === getBufferTemplate().join("") && $input.trigger("cleared");
                    },
                    blurEvent: function(e) {
                        var $input = $(this), input = this;
                        if (input.inputmask) {
                            var nptValue = input.inputmask._valueGet(), buffer = getBuffer().slice();
                            "" !== nptValue && (opts.clearMaskOnLostFocus && (-1 === getLastValidPosition() && nptValue === getBufferTemplate().join("") ? buffer = [] : clearOptionalTail(buffer)), 
                            !1 === isComplete(buffer) && (setTimeout(function() {
                                $input.trigger("incomplete");
                            }, 0), opts.clearIncomplete && (resetMaskSet(), buffer = opts.clearMaskOnLostFocus ? [] : getBufferTemplate().slice())), 
                            writeBuffer(input, buffer, undefined, e)), undoValue !== getBuffer().join("") && (undoValue = buffer.join(""), 
                            $input.trigger("change"));
                        }
                    },
                    mouseenterEvent: function(e) {
                        var input = this;
                        mouseEnter = !0, document.activeElement !== input && opts.showMaskOnHover && input.inputmask._valueGet() !== getBuffer().join("") && writeBuffer(input, getBuffer());
                    },
                    submitEvent: function(e) {
                        undoValue !== getBuffer().join("") && $el.trigger("change"), opts.clearMaskOnLostFocus && -1 === getLastValidPosition() && el.inputmask._valueGet && el.inputmask._valueGet() === getBufferTemplate().join("") && el.inputmask._valueSet(""), 
                        opts.removeMaskOnSubmit && (el.inputmask._valueSet(el.inputmask.unmaskedvalue(), !0), 
                        setTimeout(function() {
                            writeBuffer(el, getBuffer());
                        }, 0));
                    },
                    resetEvent: function(e) {
                        el.inputmask.refreshValue = !0, setTimeout(function() {
                            $el.trigger("setvalue");
                        }, 0);
                    }
                };
                Inputmask.prototype.positionColorMask = function(input, template) {
                    input.style.left = template.offsetLeft + "px";
                };
                var valueBuffer;
                if (actionObj !== undefined) switch (actionObj.action) {
                  case "isComplete":
                    return el = actionObj.el, isComplete(getBuffer());
    
                  case "unmaskedvalue":
                    return el !== undefined && actionObj.value === undefined || (valueBuffer = actionObj.value, 
                    valueBuffer = ($.isFunction(opts.onBeforeMask) ? opts.onBeforeMask.call(inputmask, valueBuffer, opts) || valueBuffer : valueBuffer).split(""), 
                    checkVal(undefined, !1, !1, isRTL ? valueBuffer.reverse() : valueBuffer), $.isFunction(opts.onBeforeWrite) && opts.onBeforeWrite.call(inputmask, undefined, getBuffer(), 0, opts)), 
                    unmaskedvalue(el);
    
                  case "mask":
                    !function(elem) {
                        EventRuler.off(elem);
                        var isSupported = function(input, opts) {
                            var elementType = input.getAttribute("type"), isSupported = "INPUT" === input.tagName && -1 !== $.inArray(elementType, opts.supportsInputType) || input.isContentEditable || "TEXTAREA" === input.tagName;
                            if (!isSupported) if ("INPUT" === input.tagName) {
                                var el = document.createElement("input");
                                el.setAttribute("type", elementType), isSupported = "text" === el.type, el = null;
                            } else isSupported = "partial";
                            return !1 !== isSupported ? function(npt) {
                                function getter() {
                                    return this.inputmask ? this.inputmask.opts.autoUnmask ? this.inputmask.unmaskedvalue() : -1 !== getLastValidPosition() || !0 !== opts.nullable ? document.activeElement === this && opts.clearMaskOnLostFocus ? (isRTL ? clearOptionalTail(getBuffer().slice()).reverse() : clearOptionalTail(getBuffer().slice())).join("") : valueGet.call(this) : "" : valueGet.call(this);
                                }
                                function setter(value) {
                                    valueSet.call(this, value), this.inputmask && $(this).trigger("setvalue");
                                }
                                var valueGet, valueSet;
                                if (!npt.inputmask.__valueGet) {
                                    if (!0 !== opts.noValuePatching) {
                                        if (Object.getOwnPropertyDescriptor) {
                                            "function" != typeof Object.getPrototypeOf && (Object.getPrototypeOf = "object" === _typeof("test".__proto__) ? function(object) {
                                                return object.__proto__;
                                            } : function(object) {
                                                return object.constructor.prototype;
                                            });
                                            var valueProperty = Object.getPrototypeOf ? Object.getOwnPropertyDescriptor(Object.getPrototypeOf(npt), "value") : undefined;
                                            valueProperty && valueProperty.get && valueProperty.set ? (valueGet = valueProperty.get, 
                                            valueSet = valueProperty.set, Object.defineProperty(npt, "value", {
                                                get: getter,
                                                set: setter,
                                                configurable: !0
                                            })) : "INPUT" !== npt.tagName && (valueGet = function() {
                                                return this.textContent;
                                            }, valueSet = function(value) {
                                                this.textContent = value;
                                            }, Object.defineProperty(npt, "value", {
                                                get: getter,
                                                set: setter,
                                                configurable: !0
                                            }));
                                        } else document.__lookupGetter__ && npt.__lookupGetter__("value") && (valueGet = npt.__lookupGetter__("value"), 
                                        valueSet = npt.__lookupSetter__("value"), npt.__defineGetter__("value", getter), 
                                        npt.__defineSetter__("value", setter));
                                        npt.inputmask.__valueGet = valueGet, npt.inputmask.__valueSet = valueSet;
                                    }
                                    npt.inputmask._valueGet = function(overruleRTL) {
                                        return isRTL && !0 !== overruleRTL ? valueGet.call(this.el).split("").reverse().join("") : valueGet.call(this.el);
                                    }, npt.inputmask._valueSet = function(value, overruleRTL) {
                                        valueSet.call(this.el, null === value || value === undefined ? "" : !0 !== overruleRTL && isRTL ? value.split("").reverse().join("") : value);
                                    }, valueGet === undefined && (valueGet = function() {
                                        return this.value;
                                    }, valueSet = function(value) {
                                        this.value = value;
                                    }, function(type) {
                                        if ($.valHooks && ($.valHooks[type] === undefined || !0 !== $.valHooks[type].inputmaskpatch)) {
                                            var valhookGet = $.valHooks[type] && $.valHooks[type].get ? $.valHooks[type].get : function(elem) {
                                                return elem.value;
                                            }, valhookSet = $.valHooks[type] && $.valHooks[type].set ? $.valHooks[type].set : function(elem, value) {
                                                return elem.value = value, elem;
                                            };
                                            $.valHooks[type] = {
                                                get: function(elem) {
                                                    if (elem.inputmask) {
                                                        if (elem.inputmask.opts.autoUnmask) return elem.inputmask.unmaskedvalue();
                                                        var result = valhookGet(elem);
                                                        return -1 !== getLastValidPosition(undefined, undefined, elem.inputmask.maskset.validPositions) || !0 !== opts.nullable ? result : "";
                                                    }
                                                    return valhookGet(elem);
                                                },
                                                set: function(elem, value) {
                                                    var result, $elem = $(elem);
                                                    return result = valhookSet(elem, value), elem.inputmask && $elem.trigger("setvalue"), 
                                                    result;
                                                },
                                                inputmaskpatch: !0
                                            };
                                        }
                                    }(npt.type), function(npt) {
                                        EventRuler.on(npt, "mouseenter", function(event) {
                                            var $input = $(this);
                                            this.inputmask._valueGet() !== getBuffer().join("") && $input.trigger("setvalue");
                                        });
                                    }(npt));
                                }
                            }(input) : input.inputmask = undefined, isSupported;
                        }(elem, opts);
                        if (!1 !== isSupported && (el = elem, $el = $(el), -1 === (maxLength = el !== undefined ? el.maxLength : undefined) && (maxLength = undefined), 
                        !0 === opts.colorMask && initializeColorMask(el), android && (el.hasOwnProperty("inputmode") && (el.inputmode = opts.inputmode, 
                        el.setAttribute("inputmode", opts.inputmode)), "rtfm" === opts.androidHack && (!0 !== opts.colorMask && initializeColorMask(el), 
                        el.type = "password")), !0 === isSupported && (EventRuler.on(el, "submit", EventHandlers.submitEvent), 
                        EventRuler.on(el, "reset", EventHandlers.resetEvent), EventRuler.on(el, "mouseenter", EventHandlers.mouseenterEvent), 
                        EventRuler.on(el, "blur", EventHandlers.blurEvent), EventRuler.on(el, "focus", EventHandlers.focusEvent), 
                        EventRuler.on(el, "mouseleave", EventHandlers.mouseleaveEvent), !0 !== opts.colorMask && EventRuler.on(el, "click", EventHandlers.clickEvent), 
                        EventRuler.on(el, "dblclick", EventHandlers.dblclickEvent), EventRuler.on(el, "paste", EventHandlers.pasteEvent), 
                        EventRuler.on(el, "dragdrop", EventHandlers.pasteEvent), EventRuler.on(el, "drop", 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), 
                        android || !0 === opts.inputEventOnly ? el.removeAttribute("maxLength") : (EventRuler.on(el, "keydown", EventHandlers.keydownEvent), 
                        EventRuler.on(el, "keypress", EventHandlers.keypressEvent)), EventRuler.on(el, "compositionstart", $.noop), 
                        EventRuler.on(el, "compositionupdate", $.noop), EventRuler.on(el, "compositionend", $.noop), 
                        EventRuler.on(el, "keyup", $.noop), EventRuler.on(el, "input", EventHandlers.inputFallBackEvent), 
                        EventRuler.on(el, "beforeinput", $.noop)), EventRuler.on(el, "setvalue", EventHandlers.setValueEvent), 
                        undoValue = getBufferTemplate().join(""), "" !== el.inputmask._valueGet(!0) || !1 === opts.clearMaskOnLostFocus || document.activeElement === el)) {
                            var initialValue = $.isFunction(opts.onBeforeMask) ? opts.onBeforeMask.call(inputmask, el.inputmask._valueGet(!0), opts) || el.inputmask._valueGet(!0) : el.inputmask._valueGet(!0);
                            "" !== initialValue && checkVal(el, !0, !1, isRTL ? initialValue.split("").reverse() : initialValue.split(""));
                            var buffer = getBuffer().slice();
                            undoValue = buffer.join(""), !1 === isComplete(buffer) && opts.clearIncomplete && resetMaskSet(), 
                            opts.clearMaskOnLostFocus && document.activeElement !== el && (-1 === getLastValidPosition() ? buffer = [] : clearOptionalTail(buffer)), 
                            writeBuffer(el, buffer), document.activeElement === el && caret(el, seekNext(getLastValidPosition()));
                        }
                    }(el);
                    break;
    
                  case "format":
                    return valueBuffer = ($.isFunction(opts.onBeforeMask) ? opts.onBeforeMask.call(inputmask, actionObj.value, opts) || actionObj.value : actionObj.value).split(""), 
                    checkVal(undefined, !0, !1, isRTL ? valueBuffer.reverse() : valueBuffer), actionObj.metadata ? {
                        value: isRTL ? getBuffer().slice().reverse().join("") : getBuffer().join(""),
                        metadata: maskScope.call(this, {
                            action: "getmetadata"
                        }, maskset, opts)
                    } : isRTL ? getBuffer().slice().reverse().join("") : getBuffer().join("");
    
                  case "isValid":
                    actionObj.value ? (valueBuffer = actionObj.value.split(""), checkVal(undefined, !0, !0, isRTL ? valueBuffer.reverse() : valueBuffer)) : actionObj.value = getBuffer().join("");
                    for (var buffer = getBuffer(), rl = determineLastRequiredPosition(), lmib = buffer.length - 1; lmib > rl && !isMask(lmib); lmib--) ;
                    return buffer.splice(rl, lmib + 1 - rl), isComplete(buffer) && actionObj.value === getBuffer().join("");
    
                  case "getemptymask":
                    return getBufferTemplate().join("");
    
                  case "remove":
                    if (el && el.inputmask) {
                        $el = $(el), el.inputmask._valueSet(opts.autoUnmask ? unmaskedvalue(el) : el.inputmask._valueGet(!0)), 
                        EventRuler.off(el);
                        Object.getOwnPropertyDescriptor && Object.getPrototypeOf ? Object.getOwnPropertyDescriptor(Object.getPrototypeOf(el), "value") && el.inputmask.__valueGet && Object.defineProperty(el, "value", {
                            get: el.inputmask.__valueGet,
                            set: el.inputmask.__valueSet,
                            configurable: !0
                        }) : document.__lookupGetter__ && el.__lookupGetter__("value") && el.inputmask.__valueGet && (el.__defineGetter__("value", el.inputmask.__valueGet), 
                        el.__defineSetter__("value", el.inputmask.__valueSet)), el.inputmask = undefined;
                    }
                    return el;
    
                  case "getmetadata":
                    if ($.isArray(maskset.metadata)) {
                        var maskTarget = getMaskTemplate(!0, 0, !1).join("");
                        return $.each(maskset.metadata, function(ndx, mtdt) {
                            if (mtdt.mask === maskTarget) return maskTarget = mtdt, !1;
                        }), maskTarget;
                    }
                    return maskset.metadata;
                }
            }
            var ua = navigator.userAgent, mobile = /mobile/i.test(ua), iemobile = /iemobile/i.test(ua), iphone = /iphone/i.test(ua) && !iemobile, android = /android/i.test(ua) && !iemobile;
            return Inputmask.prototype = {
                dataAttribute: "data-inputmask",
                defaults: {
                    placeholder: "_",
                    optionalmarker: {
                        start: "[",
                        end: "]"
                    },
                    quantifiermarker: {
                        start: "{",
                        end: "}"
                    },
                    groupmarker: {
                        start: "(",
                        end: ")"
                    },
                    alternatormarker: "|",
                    escapeChar: "\\",
                    mask: null,
                    regex: null,
                    oncomplete: $.noop,
                    onincomplete: $.noop,
                    oncleared: $.noop,
                    repeat: 0,
                    greedy: !0,
                    autoUnmask: !1,
                    removeMaskOnSubmit: !1,
                    clearMaskOnLostFocus: !0,
                    insertMode: !0,
                    clearIncomplete: !1,
                    alias: null,
                    onKeyDown: $.noop,
                    onBeforeMask: null,
                    onBeforePaste: function(pastedValue, opts) {
                        return $.isFunction(opts.onBeforeMask) ? opts.onBeforeMask.call(this, pastedValue, opts) : pastedValue;
                    },
                    onBeforeWrite: null,
                    onUnMask: null,
                    showMaskOnFocus: !0,
                    showMaskOnHover: !0,
                    onKeyValidation: $.noop,
                    skipOptionalPartCharacter: " ",
                    numericInput: !1,
                    rightAlign: !1,
                    undoOnEscape: !0,
                    radixPoint: "",
                    radixPointDefinitionSymbol: undefined,
                    groupSeparator: "",
                    keepStatic: null,
                    positionCaretOnTab: !0,
                    tabThrough: !1,
                    supportsInputType: [ "text", "tel", "password" ],
                    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,
                    canClearPosition: $.noop,
                    preValidation: null,
                    postValidation: null,
                    staticDefinitionSymbol: undefined,
                    jitMasking: !1,
                    nullable: !0,
                    inputEventOnly: !1,
                    noValuePatching: !1,
                    positionCaretOnClick: "lvp",
                    casing: null,
                    inputmode: "verbatim",
                    colorMask: !1,
                    androidHack: !1,
                    importDataAttributes: !0
                },
                definitions: {
                    "9": {
                        validator: "[0-91-9]",
                        cardinality: 1,
                        definitionSymbol: "*"
                    },
                    a: {
                        validator: "[A-Za-zА-яЁёÀ-ÿµ]",
                        cardinality: 1,
                        definitionSymbol: "*"
                    },
                    "*": {
                        validator: "[0-91-9A-Za-zА-яЁёÀ-ÿµ]",
                        cardinality: 1
                    }
                },
                aliases: {},
                masksCache: {},
                mask: function(elems) {
                    function importAttributeOptions(npt, opts, userOptions, dataAttribute) {
                        if (!0 === opts.importDataAttributes) {
                            var option, dataoptions, optionData, p, importOption = function(option, optionData) {
                                null !== (optionData = optionData !== undefined ? optionData : npt.getAttribute(dataAttribute + "-" + option)) && ("string" == typeof optionData && (0 === option.indexOf("on") ? optionData = window[optionData] : "false" === optionData ? optionData = !1 : "true" === optionData && (optionData = !0)), 
                                userOptions[option] = optionData);
                            }, attrOptions = npt.getAttribute(dataAttribute);
                            if (attrOptions && "" !== attrOptions && (attrOptions = attrOptions.replace(new RegExp("'", "g"), '"'), 
                            dataoptions = JSON.parse("{" + attrOptions + "}")), dataoptions) {
                                optionData = undefined;
                                for (p in dataoptions) if ("alias" === p.toLowerCase()) {
                                    optionData = dataoptions[p];
                                    break;
                                }
                            }
                            importOption("alias", optionData), 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);
                            }
                        }
                        return $.extend(!0, opts, userOptions), ("rtl" === npt.dir || opts.rightAlign) && (npt.style.textAlign = "right"), 
                        ("rtl" === npt.dir || opts.numericInput) && (npt.dir = "ltr", npt.removeAttribute("dir"), 
                        opts.isRTL = !0), opts;
                    }
                    var that = this;
                    return "string" == typeof elems && (elems = document.getElementById(elems) || document.querySelectorAll(elems)), 
                    elems = elems.nodeName ? [ elems ] : elems, $.each(elems, function(ndx, el) {
                        var scopedOpts = $.extend(!0, {}, that.opts);
                        importAttributeOptions(el, scopedOpts, $.extend(!0, {}, that.userOptions), that.dataAttribute);
                        var maskset = generateMaskSet(scopedOpts, that.noMasksCache);
                        maskset !== undefined && (el.inputmask !== undefined && (el.inputmask.opts.autoUnmask = !0, 
                        el.inputmask.remove()), el.inputmask = new Inputmask(undefined, undefined, !0), 
                        el.inputmask.opts = scopedOpts, el.inputmask.noMasksCache = that.noMasksCache, el.inputmask.userOptions = $.extend(!0, {}, 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"
                        }));
                    }), elems && elems[0] ? elems[0].inputmask || this : this;
                },
                option: function(options, noremask) {
                    return "string" == typeof options ? this.opts[options] : "object" === (void 0 === options ? "undefined" : _typeof(options)) ? ($.extend(this.userOptions, options), 
                    this.el && !0 !== noremask && this.mask(this.el), this) : void 0;
                },
                unmaskedvalue: function(value) {
                    return this.maskset = this.maskset || generateMaskSet(this.opts, this.noMasksCache), 
                    maskScope.call(this, {
                        action: "unmaskedvalue",
                        value: value
                    });
                },
                remove: function() {
                    return maskScope.call(this, {
                        action: "remove"
                    });
                },
                getemptymask: function() {
                    return this.maskset = this.maskset || generateMaskSet(this.opts, this.noMasksCache), 
                    maskScope.call(this, {
                        action: "getemptymask"
                    });
                },
                hasMaskedValue: function() {
                    return !this.opts.autoUnmask;
                },
                isComplete: function() {
                    return this.maskset = this.maskset || generateMaskSet(this.opts, this.noMasksCache), 
                    maskScope.call(this, {
                        action: "isComplete"
                    });
                },
                getmetadata: function() {
                    return this.maskset = this.maskset || generateMaskSet(this.opts, this.noMasksCache), 
                    maskScope.call(this, {
                        action: "getmetadata"
                    });
                },
                isValid: function(value) {
                    return this.maskset = this.maskset || generateMaskSet(this.opts, this.noMasksCache), 
                    maskScope.call(this, {
                        action: "isValid",
                        value: value
                    });
                },
                format: function(value, metadata) {
                    return this.maskset = this.maskset || generateMaskSet(this.opts, this.noMasksCache), 
                    maskScope.call(this, {
                        action: "format",
                        value: value,
                        metadata: metadata
                    });
                },
                analyseMask: function(mask, regexMask, opts) {
                    function MaskToken(isGroup, isOptional, isQuantifier, isAlternator) {
                        this.matches = [], this.openGroup = isGroup || !1, this.alternatorGroup = !1, this.isGroup = isGroup || !1, 
                        this.isOptional = isOptional || !1, this.isQuantifier = isQuantifier || !1, this.isAlternator = isAlternator || !1, 
                        this.quantifier = {
                            min: 1,
                            max: 1
                        };
                    }
                    function insertTestDefinition(mtoken, element, position) {
                        position = position !== undefined ? position : mtoken.matches.length;
                        var prevMatch = mtoken.matches[position - 1];
                        if (regexMask) 0 === element.indexOf("[") || escaped && /\\d|\\s|\\w]/i.test(element) || "." === element ? mtoken.matches.splice(position++, 0, {
                            fn: new RegExp(element, opts.casing ? "i" : ""),
                            cardinality: 1,
                            optionality: mtoken.isOptional,
                            newBlockMarker: prevMatch === undefined || prevMatch.def !== element,
                            casing: null,
                            def: element,
                            placeholder: undefined,
                            nativeDef: element
                        }) : (escaped && (element = element[element.length - 1]), $.each(element.split(""), function(ndx, lmnt) {
                            prevMatch = mtoken.matches[position - 1], mtoken.matches.splice(position++, 0, {
                                fn: null,
                                cardinality: 0,
                                optionality: mtoken.isOptional,
                                newBlockMarker: prevMatch === undefined || prevMatch.def !== lmnt && null !== prevMatch.fn,
                                casing: null,
                                def: opts.staticDefinitionSymbol || lmnt,
                                placeholder: opts.staticDefinitionSymbol !== undefined ? lmnt : undefined,
                                nativeDef: lmnt
                            });
                        })), escaped = !1; else {
                            var maskdef = (opts.definitions ? opts.definitions[element] : undefined) || Inputmask.prototype.definitions[element];
                            if (maskdef && !escaped) {
                                for (var prevalidators = maskdef.prevalidator, prevalidatorsL = prevalidators ? prevalidators.length : 0, i = 1; i < maskdef.cardinality; i++) {
                                    var prevalidator = prevalidatorsL >= i ? prevalidators[i - 1] : [], validator = prevalidator.validator, cardinality = prevalidator.cardinality;
                                    mtoken.matches.splice(position++, 0, {
                                        fn: validator ? "string" == typeof validator ? new RegExp(validator, opts.casing ? "i" : "") : new function() {
                                            this.test = validator;
                                        }() : new RegExp("."),
                                        cardinality: cardinality || 1,
                                        optionality: mtoken.isOptional,
                                        newBlockMarker: prevMatch === undefined || prevMatch.def !== (maskdef.definitionSymbol || element),
                                        casing: maskdef.casing,
                                        def: maskdef.definitionSymbol || element,
                                        placeholder: maskdef.placeholder,
                                        nativeDef: element
                                    }), prevMatch = mtoken.matches[position - 1];
                                }
                                mtoken.matches.splice(position++, 0, {
                                    fn: maskdef.validator ? "string" == typeof maskdef.validator ? new RegExp(maskdef.validator, opts.casing ? "i" : "") : new function() {
                                        this.test = maskdef.validator;
                                    }() : new RegExp("."),
                                    cardinality: maskdef.cardinality,
                                    optionality: mtoken.isOptional,
                                    newBlockMarker: prevMatch === undefined || 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,
                                cardinality: 0,
                                optionality: mtoken.isOptional,
                                newBlockMarker: prevMatch === undefined || prevMatch.def !== element && null !== prevMatch.fn,
                                casing: null,
                                def: opts.staticDefinitionSymbol || element,
                                placeholder: opts.staticDefinitionSymbol !== undefined ? element : undefined,
                                nativeDef: element
                            }), escaped = !1;
                        }
                    }
                    function verifyGroupMarker(maskToken) {
                        maskToken && maskToken.matches && $.each(maskToken.matches, function(ndx, token) {
                            var nextToken = maskToken.matches[ndx + 1];
                            (nextToken === undefined || nextToken.matches === undefined || !1 === nextToken.isQuantifier) && token && token.isGroup && (token.isGroup = !1, 
                            regexMask || (insertTestDefinition(token, opts.groupmarker.start, 0), !0 !== token.openGroup && insertTestDefinition(token, opts.groupmarker.end))), 
                            verifyGroupMarker(token);
                        });
                    }
                    function defaultCase() {
                        if (openenings.length > 0) {
                            if (currentOpeningToken = openenings[openenings.length - 1], insertTestDefinition(currentOpeningToken, m), 
                            currentOpeningToken.isAlternator) {
                                alternator = openenings.pop();
                                for (var mndx = 0; mndx < alternator.matches.length; mndx++) alternator.matches[mndx].isGroup = !1;
                                openenings.length > 0 ? (currentOpeningToken = openenings[openenings.length - 1]).matches.push(alternator) : currentToken.matches.push(alternator);
                            }
                        } else insertTestDefinition(currentToken, m);
                    }
                    function reverseTokens(maskToken) {
                        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);
                            }
                            maskToken.matches[match].matches !== undefined ? maskToken.matches[match] = reverseTokens(maskToken.matches[match]) : maskToken.matches[match] = function(st) {
                                return st === opts.optionalmarker.start ? st = opts.optionalmarker.end : st === opts.optionalmarker.end ? st = opts.optionalmarker.start : st === opts.groupmarker.start ? st = opts.groupmarker.end : st === opts.groupmarker.end && (st = opts.groupmarker.start), 
                                st;
                            }(maskToken.matches[match]);
                        }
                        return maskToken;
                    }
                    var match, m, openingToken, currentOpeningToken, alternator, lastMatch, groupToken, tokenizer = /(?:[?*+]|\{[0-9\+\*]+(?:,[0-9\+\*]*)?\})|[^.?*+^${[]()|\\]+|./g, regexTokenizer = /\[\^?]?(?:[^\\\]]+|\\[\S\s]?)*]?|\\(?:0(?:[0-3][0-7]{0,2}|[4-7][0-7]?)?|[1-9][0-9]*|x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4}|c[A-Za-z]|[\S\s]?)|\((?:\?[:=!]?)?|(?:[?*+]|\{[0-9]+(?:,[0-9]*)?\})\??|[^.?*+^${[()|\\]+|./g, escaped = !1, currentToken = new MaskToken(), openenings = [], maskTokens = [];
                    for (regexMask && (opts.optionalmarker.start = undefined, opts.optionalmarker.end = undefined); match = regexMask ? regexTokenizer.exec(mask) : tokenizer.exec(mask); ) {
                        if (m = match[0], regexMask) switch (m.charAt(0)) {
                          case "?":
                            m = "{0,1}";
                            break;
    
                          case "+":
                          case "*":
                            m = "{" + m + "}";
                        }
                        if (escaped) defaultCase(); else switch (m.charAt(0)) {
                          case opts.escapeChar:
                            escaped = !0, regexMask && defaultCase();
                            break;
    
                          case opts.optionalmarker.end:
                          case opts.groupmarker.end:
                            if (openingToken = openenings.pop(), openingToken.openGroup = !1, openingToken !== undefined) if (openenings.length > 0) {
                                if ((currentOpeningToken = openenings[openenings.length - 1]).matches.push(openingToken), 
                                currentOpeningToken.isAlternator) {
                                    alternator = openenings.pop();
                                    for (var mndx = 0; mndx < alternator.matches.length; mndx++) alternator.matches[mndx].isGroup = !1, 
                                    alternator.matches[mndx].alternatorGroup = !1;
                                    openenings.length > 0 ? (currentOpeningToken = openenings[openenings.length - 1]).matches.push(alternator) : currentToken.matches.push(alternator);
                                }
                            } else currentToken.matches.push(openingToken); else defaultCase();
                            break;
    
                          case opts.optionalmarker.start:
                            openenings.push(new MaskToken(!1, !0));
                            break;
    
                          case opts.groupmarker.start:
                            openenings.push(new MaskToken(!0));
                            break;
    
                          case opts.quantifiermarker.start:
                            var quantifier = new MaskToken(!1, !1, !0), mq = (m = m.replace(/[{}]/g, "")).split(","), mq0 = isNaN(mq[0]) ? mq[0] : parseInt(mq[0]), mq1 = 1 === mq.length ? mq0 : isNaN(mq[1]) ? mq[1] : parseInt(mq[1]);
                            if ("*" !== mq1 && "+" !== mq1 || (mq0 = "*" === mq1 ? 0 : 1), quantifier.quantifier = {
                                min: mq0,
                                max: mq1
                            }, openenings.length > 0) {
                                var matches = openenings[openenings.length - 1].matches;
                                (match = matches.pop()).isGroup || ((groupToken = new MaskToken(!0)).matches.push(match), 
                                match = groupToken), matches.push(match), matches.push(quantifier);
                            } else (match = currentToken.matches.pop()).isGroup || (regexMask && null === match.fn && "." === match.def && (match.fn = new RegExp(match.def, opts.casing ? "i" : "")), 
                            (groupToken = new MaskToken(!0)).matches.push(match), match = groupToken), currentToken.matches.push(match), 
                            currentToken.matches.push(quantifier);
                            break;
    
                          case opts.alternatormarker:
                            if (openenings.length > 0) {
                                var subToken = (currentOpeningToken = openenings[openenings.length - 1]).matches[currentOpeningToken.matches.length - 1];
                                lastMatch = currentOpeningToken.openGroup && (subToken.matches === undefined || !1 === subToken.isGroup && !1 === subToken.isAlternator) ? openenings.pop() : currentOpeningToken.matches.pop();
                            } else lastMatch = currentToken.matches.pop();
                            if (lastMatch.isAlternator) openenings.push(lastMatch); else if (lastMatch.alternatorGroup ? (alternator = openenings.pop(), 
                            lastMatch.alternatorGroup = !1) : alternator = new MaskToken(!1, !1, !1, !0), alternator.matches.push(lastMatch), 
                            openenings.push(alternator), lastMatch.openGroup) {
                                lastMatch.openGroup = !1;
                                var alternatorGroup = new MaskToken(!0);
                                alternatorGroup.alternatorGroup = !0, openenings.push(alternatorGroup);
                            }
                            break;
    
                          default:
                            defaultCase();
                        }
                    }
                    for (;openenings.length > 0; ) openingToken = openenings.pop(), currentToken.matches.push(openingToken);
                    return currentToken.matches.length > 0 && (verifyGroupMarker(currentToken), maskTokens.push(currentToken)), 
                    (opts.numericInput || opts.isRTL) && reverseTokens(maskTokens[0]), maskTokens;
                }
            }, Inputmask.extendDefaults = function(options) {
                $.extend(!0, Inputmask.prototype.defaults, options);
            }, Inputmask.extendDefinitions = function(definition) {
                $.extend(!0, Inputmask.prototype.definitions, definition);
            }, Inputmask.extendAliases = function(alias) {
                $.extend(!0, Inputmask.prototype.aliases, alias);
            }, Inputmask.format = function(value, options, metadata) {
                return Inputmask(options).format(value, metadata);
            }, Inputmask.unmask = function(value, options) {
                return Inputmask(options).unmaskedvalue(value);
            }, Inputmask.isValid = function(value, options) {
                return Inputmask(options).isValid(value);
            }, Inputmask.remove = function(elems) {
                $.each(elems, function(ndx, el) {
                    el.inputmask && el.inputmask.remove();
                });
            }, Inputmask.escapeRegex = function(str) {
                var specials = [ "/", ".", "*", "+", "?", "|", "(", ")", "[", "]", "{", "}", "\\", "$", "^" ];
                return str.replace(new RegExp("(\\" + specials.join("|\\") + ")", "gim"), "\\$1");
            }, Inputmask.keyCode = {
                ALT: 18,
                BACKSPACE: 8,
                BACKSPACE_SAFARI: 127,
                CAPS_LOCK: 20,
                COMMA: 188,
                COMMAND: 91,
                COMMAND_LEFT: 91,
                COMMAND_RIGHT: 93,
                CONTROL: 17,
                DELETE: 46,
                DOWN: 40,
                END: 35,
                ENTER: 13,
                ESCAPE: 27,
                HOME: 36,
                INSERT: 45,
                LEFT: 37,
                MENU: 93,
                NUMPAD_ADD: 107,
                NUMPAD_DECIMAL: 110,
                NUMPAD_DIVIDE: 111,
                NUMPAD_ENTER: 108,
                NUMPAD_MULTIPLY: 106,
                NUMPAD_SUBTRACT: 109,
                PAGE_DOWN: 34,
                PAGE_UP: 33,
                PERIOD: 190,
                RIGHT: 39,
                SHIFT: 16,
                SPACE: 32,
                TAB: 9,
                UP: 38,
                WINDOWS: 91,
                X: 88
            }, Inputmask;
        });
    }, function(module, exports) {
        module.exports = jQuery;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        function _interopRequireDefault(obj) {
            return obj && obj.__esModule ? obj : {
                default: obj
            };
        }
        __webpack_require__(4), __webpack_require__(9), __webpack_require__(12), __webpack_require__(13), 
        __webpack_require__(14), __webpack_require__(15);
        var _inputmask2 = _interopRequireDefault(__webpack_require__(1)), _inputmask4 = _interopRequireDefault(__webpack_require__(0)), _jquery2 = _interopRequireDefault(__webpack_require__(2));
        _inputmask4.default === _jquery2.default && __webpack_require__(16), window.Inputmask = _inputmask2.default;
    }, function(module, exports, __webpack_require__) {
        var content = __webpack_require__(5);
        "string" == typeof content && (content = [ [ module.i, content, "" ] ]);
        var options = {
            hmr: !0
        };
        options.transform = void 0;
        __webpack_require__(7)(content, options);
        content.locals && (module.exports = content.locals);
    }, function(module, exports, __webpack_require__) {
        (module.exports = __webpack_require__(6)(void 0)).push([ module.i, "span.im-caret {\r\n    -webkit-animation: 1s blink step-end infinite;\r\n    animation: 1s blink step-end infinite;\r\n}\r\n\r\n@keyframes blink {\r\n    from, to {\r\n        border-right-color: black;\r\n    }\r\n    50% {\r\n        border-right-color: transparent;\r\n    }\r\n}\r\n\r\n@-webkit-keyframes blink {\r\n    from, to {\r\n        border-right-color: black;\r\n    }\r\n    50% {\r\n        border-right-color: transparent;\r\n    }\r\n}\r\n\r\nspan.im-static {\r\n    color: grey;\r\n}\r\n\r\ndiv.im-colormask {\r\n    display: inline-block;\r\n    border-style: inset;\r\n    border-width: 2px;\r\n    -webkit-appearance: textfield;\r\n    -moz-appearance: textfield;\r\n    appearance: textfield;\r\n}\r\n\r\ndiv.im-colormask > input {\r\n    position: absolute;\r\n    display: inline-block;\r\n    background-color: transparent;\r\n    color: transparent;\r\n    -webkit-appearance: caret;\r\n    -moz-appearance: caret;\r\n    appearance: caret;\r\n    border-style: none;\r\n    left: 0; /*calculated*/\r\n}\r\n\r\ndiv.im-colormask > input:focus {\r\n    outline: none;\r\n}\r\n\r\ndiv.im-colormask > input::-moz-selection{\r\n    background: none;\r\n}\r\n\r\ndiv.im-colormask > input::selection{\r\n    background: none;\r\n}\r\ndiv.im-colormask > input::-moz-selection{\r\n    background: none;\r\n}\r\n\r\ndiv.im-colormask > div {\r\n    color: black;\r\n    display: inline-block;\r\n    width: 100px; /*calculated*/\r\n}", "" ]);
    }, function(module, exports) {
        function cssWithMappingToString(item, useSourceMap) {
            var content = item[1] || "", cssMapping = item[3];
            if (!cssMapping) return content;
            if (useSourceMap && "function" == typeof btoa) {
                var sourceMapping = toComment(cssMapping), sourceURLs = cssMapping.sources.map(function(source) {
                    return "/*# sourceURL=" + cssMapping.sourceRoot + source + " */";
                });
                return [ content ].concat(sourceURLs).concat([ sourceMapping ]).join("\n");
            }
            return [ content ].join("\n");
        }
        function toComment(sourceMap) {
            return "/*# " + ("sourceMappingURL=data:application/json;charset=utf-8;base64," + btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap))))) + " */";
        }
        module.exports = function(useSourceMap) {
            var list = [];
            return list.toString = function() {
                return this.map(function(item) {
                    var content = cssWithMappingToString(item, useSourceMap);
                    return item[2] ? "@media " + item[2] + "{" + content + "}" : content;
                }).join("");
            }, list.i = function(modules, mediaQuery) {
                "string" == typeof modules && (modules = [ [ null, modules, "" ] ]);
                for (var alreadyImportedModules = {}, i = 0; i < this.length; i++) {
                    var id = this[i][0];
                    "number" == typeof id && (alreadyImportedModules[id] = !0);
                }
                for (i = 0; i < modules.length; i++) {
                    var item = modules[i];
                    "number" == typeof item[0] && alreadyImportedModules[item[0]] || (mediaQuery && !item[2] ? item[2] = mediaQuery : mediaQuery && (item[2] = "(" + item[2] + ") and (" + mediaQuery + ")"), 
                    list.push(item));
                }
            }, list;
        };
    }, function(module, exports, __webpack_require__) {
        function addStylesToDom(styles, options) {
            for (var i = 0; i < styles.length; i++) {
                var item = styles[i], domStyle = stylesInDom[item.id];
                if (domStyle) {
                    domStyle.refs++;
                    for (j = 0; j < domStyle.parts.length; j++) domStyle.parts[j](item.parts[j]);
                    for (;j < item.parts.length; j++) domStyle.parts.push(addStyle(item.parts[j], options));
                } else {
                    for (var parts = [], j = 0; j < item.parts.length; j++) parts.push(addStyle(item.parts[j], options));
                    stylesInDom[item.id] = {
                        id: item.id,
                        refs: 1,
                        parts: parts
                    };
                }
            }
        }
        function listToStyles(list, options) {
            for (var styles = [], newStyles = {}, i = 0; i < list.length; i++) {
                var item = list[i], id = options.base ? item[0] + options.base : item[0], part = {
                    css: item[1],
                    media: item[2],
                    sourceMap: item[3]
                };
                newStyles[id] ? newStyles[id].parts.push(part) : styles.push(newStyles[id] = {
                    id: id,
                    parts: [ part ]
                });
            }
            return styles;
        }
        function insertStyleElement(options, style) {
            var target = getElement(options.insertInto);
            if (!target) throw new Error("Couldn't find a style target. This probably means that the value for the 'insertInto' parameter is invalid.");
            var lastStyleElementInsertedAtTop = stylesInsertedAtTop[stylesInsertedAtTop.length - 1];
            if ("top" === options.insertAt) lastStyleElementInsertedAtTop ? lastStyleElementInsertedAtTop.nextSibling ? target.insertBefore(style, lastStyleElementInsertedAtTop.nextSibling) : target.appendChild(style) : target.insertBefore(style, target.firstChild), 
            stylesInsertedAtTop.push(style); else if ("bottom" === options.insertAt) target.appendChild(style); else {
                if ("object" != typeof options.insertAt || !options.insertAt.before) throw new Error("[Style Loader]\n\n Invalid value for parameter 'insertAt' ('options.insertAt') found.\n Must be 'top', 'bottom', or Object.\n (https://github.com/webpack-contrib/style-loader#insertat)\n");
                var nextSibling = getElement(options.insertInto + " " + options.insertAt.before);
                target.insertBefore(style, nextSibling);
            }
        }
        function removeStyleElement(style) {
            if (null === style.parentNode) return !1;
            style.parentNode.removeChild(style);
            var idx = stylesInsertedAtTop.indexOf(style);
            idx >= 0 && stylesInsertedAtTop.splice(idx, 1);
        }
        function createStyleElement(options) {
            var style = document.createElement("style");
            return options.attrs.type = "text/css", addAttrs(style, options.attrs), insertStyleElement(options, style), 
            style;
        }
        function createLinkElement(options) {
            var link = document.createElement("link");
            return options.attrs.type = "text/css", options.attrs.rel = "stylesheet", addAttrs(link, options.attrs), 
            insertStyleElement(options, link), link;
        }
        function addAttrs(el, attrs) {
            Object.keys(attrs).forEach(function(key) {
                el.setAttribute(key, attrs[key]);
            });
        }
        function addStyle(obj, options) {
            var style, update, remove, result;
            if (options.transform && obj.css) {
                if (!(result = options.transform(obj.css))) return function() {};
                obj.css = result;
            }
            if (options.singleton) {
                var styleIndex = singletonCounter++;
                style = singleton || (singleton = createStyleElement(options)), update = applyToSingletonTag.bind(null, style, styleIndex, !1), 
                remove = applyToSingletonTag.bind(null, style, styleIndex, !0);
            } else obj.sourceMap && "function" == typeof URL && "function" == typeof URL.createObjectURL && "function" == typeof URL.revokeObjectURL && "function" == typeof Blob && "function" == typeof btoa ? (style = createLinkElement(options), 
            update = updateLink.bind(null, style, options), remove = function() {
                removeStyleElement(style), style.href && URL.revokeObjectURL(style.href);
            }) : (style = createStyleElement(options), update = applyToTag.bind(null, style), 
            remove = function() {
                removeStyleElement(style);
            });
            return update(obj), function(newObj) {
                if (newObj) {
                    if (newObj.css === obj.css && newObj.media === obj.media && newObj.sourceMap === obj.sourceMap) return;
                    update(obj = newObj);
                } else remove();
            };
        }
        function applyToSingletonTag(style, index, remove, obj) {
            var css = remove ? "" : obj.css;
            if (style.styleSheet) style.styleSheet.cssText = replaceText(index, css); else {
                var cssNode = document.createTextNode(css), childNodes = style.childNodes;
                childNodes[index] && style.removeChild(childNodes[index]), childNodes.length ? style.insertBefore(cssNode, childNodes[index]) : style.appendChild(cssNode);
            }
        }
        function applyToTag(style, obj) {
            var css = obj.css, media = obj.media;
            if (media && style.setAttribute("media", media), style.styleSheet) style.styleSheet.cssText = css; else {
                for (;style.firstChild; ) style.removeChild(style.firstChild);
                style.appendChild(document.createTextNode(css));
            }
        }
        function updateLink(link, options, obj) {
            var css = obj.css, sourceMap = obj.sourceMap, autoFixUrls = void 0 === options.convertToAbsoluteUrls && sourceMap;
            (options.convertToAbsoluteUrls || autoFixUrls) && (css = fixUrls(css)), sourceMap && (css += "\n/*# sourceMappingURL=data:application/json;base64," + btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap)))) + " */");
            var blob = new Blob([ css ], {
                type: "text/css"
            }), oldSrc = link.href;
            link.href = URL.createObjectURL(blob), oldSrc && URL.revokeObjectURL(oldSrc);
        }
        var stylesInDom = {}, isOldIE = function(fn) {
            var memo;
            return function() {
                return void 0 === memo && (memo = fn.apply(this, arguments)), memo;
            };
        }(function() {
            return window && document && document.all && !window.atob;
        }), getElement = function(fn) {
            var memo = {};
            return function(selector) {
                if (void 0 === memo[selector]) {
                    var styleTarget = fn.call(this, selector);
                    if (styleTarget instanceof window.HTMLIFrameElement) try {
                        styleTarget = styleTarget.contentDocument.head;
                    } catch (e) {
                        styleTarget = null;
                    }
                    memo[selector] = styleTarget;
                }
                return memo[selector];
            };
        }(function(target) {
            return document.querySelector(target);
        }), singleton = null, singletonCounter = 0, stylesInsertedAtTop = [], fixUrls = __webpack_require__(8);
        module.exports = function(list, options) {
            if ("undefined" != typeof DEBUG && DEBUG && "object" != typeof document) throw new Error("The style-loader cannot be used in a non-browser environment");
            (options = options || {}).attrs = "object" == typeof options.attrs ? options.attrs : {}, 
            options.singleton || (options.singleton = isOldIE()), options.insertInto || (options.insertInto = "head"), 
            options.insertAt || (options.insertAt = "bottom");
            var styles = listToStyles(list, options);
            return addStylesToDom(styles, options), function(newList) {
                for (var mayRemove = [], i = 0; i < styles.length; i++) {
                    var item = styles[i];
                    (domStyle = stylesInDom[item.id]).refs--, mayRemove.push(domStyle);
                }
                newList && addStylesToDom(listToStyles(newList, options), options);
                for (i = 0; i < mayRemove.length; i++) {
                    var domStyle = mayRemove[i];
                    if (0 === domStyle.refs) {
                        for (var j = 0; j < domStyle.parts.length; j++) domStyle.parts[j]();
                        delete stylesInDom[domStyle.id];
                    }
                }
            };
        };
        var replaceText = function() {
            var textStore = [];
            return function(index, replacement) {
                return textStore[index] = replacement, textStore.filter(Boolean).join("\n");
            };
        }();
    }, function(module, exports) {
        module.exports = function(css) {
            var location = "undefined" != typeof window && window.location;
            if (!location) throw new Error("fixUrls requires window.location");
            if (!css || "string" != typeof css) return css;
            var baseUrl = location.protocol + "//" + location.host, currentDir = baseUrl + location.pathname.replace(/\/[^\/]*$/, "/");
            return css.replace(/url\s*\(((?:[^)(]|\((?:[^)(]+|\([^)(]*\))*\))*)\)/gi, function(fullMatch, origUrl) {
                var unquotedOrigUrl = origUrl.trim().replace(/^"(.*)"$/, function(o, $1) {
                    return $1;
                }).replace(/^'(.*)'$/, function(o, $1) {
                    return $1;
                });
                if (/^(#|data:|http:\/\/|https:\/\/|file:\/\/\/)/i.test(unquotedOrigUrl)) return fullMatch;
                var newUrl;
                return newUrl = 0 === unquotedOrigUrl.indexOf("//") ? unquotedOrigUrl : 0 === unquotedOrigUrl.indexOf("/") ? baseUrl + unquotedOrigUrl : currentDir + unquotedOrigUrl.replace(/^\.\//, ""), 
                "url(" + JSON.stringify(newUrl) + ")";
            });
        };
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;
        "function" == typeof Symbol && Symbol.iterator;
        !function(factory) {
            __WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(0), __webpack_require__(1) ], 
            void 0 !== (__WEBPACK_AMD_DEFINE_RESULT__ = "function" == typeof (__WEBPACK_AMD_DEFINE_FACTORY__ = factory) ? __WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__) : __WEBPACK_AMD_DEFINE_FACTORY__) && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__);
        }(function($, Inputmask) {
            function isLeapYear(year) {
                return isNaN(year) || 29 === new Date(year, 2, 0).getDate();
            }
            return Inputmask.extendAliases({
                "dd/mm/yyyy": {
                    mask: "1/2/y",
                    placeholder: "dd/mm/yyyy",
                    regex: {
                        val1pre: new RegExp("[0-3]"),
                        val1: new RegExp("0[1-9]|[12][0-9]|3[01]"),
                        val2pre: function(separator) {
                            var escapedSeparator = Inputmask.escapeRegex.call(this, separator);
                            return new RegExp("((0[1-9]|[12][0-9]|3[01])" + escapedSeparator + "[01])");
                        },
                        val2: function(separator) {
                            var escapedSeparator = Inputmask.escapeRegex.call(this, separator);
                            return new RegExp("((0[1-9]|[12][0-9])" + escapedSeparator + "(0[1-9]|1[012]))|(30" + escapedSeparator + "(0[13-9]|1[012]))|(31" + escapedSeparator + "(0[13578]|1[02]))");
                        }
                    },
                    leapday: "29/02/",
                    separator: "/",
                    yearrange: {
                        minyear: 1900,
                        maxyear: 2099
                    },
                    isInYearRange: function(chrs, minyear, maxyear) {
                        if (isNaN(chrs)) return !1;
                        var enteredyear = parseInt(chrs.concat(minyear.toString().slice(chrs.length))), enteredyear2 = parseInt(chrs.concat(maxyear.toString().slice(chrs.length)));
                        return !isNaN(enteredyear) && (minyear <= enteredyear && enteredyear <= maxyear) || !isNaN(enteredyear2) && (minyear <= enteredyear2 && enteredyear2 <= maxyear);
                    },
                    determinebaseyear: function(minyear, maxyear, hint) {
                        var currentyear = new Date().getFullYear();
                        if (minyear > currentyear) return minyear;
                        if (maxyear < currentyear) {
                            for (var maxYearPrefix = maxyear.toString().slice(0, 2), maxYearPostfix = maxyear.toString().slice(2, 4); maxyear < maxYearPrefix + hint; ) maxYearPrefix--;
                            var maxxYear = maxYearPrefix + maxYearPostfix;
                            return minyear > maxxYear ? minyear : maxxYear;
                        }
                        if (minyear <= currentyear && currentyear <= maxyear) {
                            for (var currentYearPrefix = currentyear.toString().slice(0, 2); maxyear < currentYearPrefix + hint; ) currentYearPrefix--;
                            var currentYearAndHint = currentYearPrefix + hint;
                            return currentYearAndHint < minyear ? minyear : currentYearAndHint;
                        }
                        return currentyear;
                    },
                    onKeyDown: function(e, buffer, caretPos, opts) {
                        var $input = $(this);
                        if (e.ctrlKey && e.keyCode === Inputmask.keyCode.RIGHT) {
                            var today = new Date();
                            $input.val(today.getDate().toString() + (today.getMonth() + 1).toString() + today.getFullYear().toString()), 
                            $input.trigger("setvalue");
                        }
                    },
                    getFrontValue: function(mask, buffer, opts) {
                        for (var start = 0, length = 0, i = 0; i < mask.length && "2" !== mask.charAt(i); i++) {
                            var definition = opts.definitions[mask.charAt(i)];
                            definition ? (start += length, length = definition.cardinality) : length++;
                        }
                        return buffer.join("").substr(start, length);
                    },
                    postValidation: function(buffer, currentResult, opts) {
                        var dayMonthValue, year, bufferStr = buffer.join("");
                        return 0 === opts.mask.indexOf("y") ? (year = bufferStr.substr(0, 4), dayMonthValue = bufferStr.substring(4, 10)) : (year = bufferStr.substring(6, 10), 
                        dayMonthValue = bufferStr.substr(0, 6)), currentResult && (dayMonthValue !== opts.leapday || isLeapYear(year));
                    },
                    definitions: {
                        "1": {
                            validator: function(chrs, maskset, pos, strict, opts) {
                                var isValid = opts.regex.val1.test(chrs);
                                return strict || isValid || chrs.charAt(1) !== opts.separator && -1 === "-./".indexOf(chrs.charAt(1)) || !(isValid = opts.regex.val1.test("0" + chrs.charAt(0))) ? isValid : (maskset.buffer[pos - 1] = "0", 
                                {
                                    refreshFromBuffer: {
                                        start: pos - 1,
                                        end: pos
                                    },
                                    pos: pos,
                                    c: chrs.charAt(0)
                                });
                            },
                            cardinality: 2,
                            prevalidator: [ {
                                validator: function(chrs, maskset, pos, strict, opts) {
                                    var pchrs = chrs;
                                    isNaN(maskset.buffer[pos + 1]) || (pchrs += maskset.buffer[pos + 1]);
                                    var isValid = 1 === pchrs.length ? opts.regex.val1pre.test(pchrs) : opts.regex.val1.test(pchrs);
                                    if (isValid && maskset.validPositions[pos] && (opts.regex.val2(opts.separator).test(chrs + maskset.validPositions[pos].input) || (maskset.validPositions[pos].input = "0" === chrs ? "1" : "0")), 
                                    !strict && !isValid) {
                                        if (isValid = opts.regex.val1.test(chrs + "0")) return maskset.buffer[pos] = chrs, 
                                        maskset.buffer[++pos] = "0", {
                                            pos: pos,
                                            c: "0"
                                        };
                                        if (isValid = opts.regex.val1.test("0" + chrs)) return maskset.buffer[pos] = "0", 
                                        pos++, {
                                            pos: pos
                                        };
                                    }
                                    return isValid;
                                },
                                cardinality: 1
                            } ]
                        },
                        "2": {
                            validator: function(chrs, maskset, pos, strict, opts) {
                                var frontValue = opts.getFrontValue(maskset.mask, maskset.buffer, opts);
                                -1 !== frontValue.indexOf(opts.placeholder[0]) && (frontValue = "01" + opts.separator);
                                var isValid = opts.regex.val2(opts.separator).test(frontValue + chrs);
                                return strict || isValid || chrs.charAt(1) !== opts.separator && -1 === "-./".indexOf(chrs.charAt(1)) || !(isValid = opts.regex.val2(opts.separator).test(frontValue + "0" + chrs.charAt(0))) ? isValid : (maskset.buffer[pos - 1] = "0", 
                                {
                                    refreshFromBuffer: {
                                        start: pos - 1,
                                        end: pos
                                    },
                                    pos: pos,
                                    c: chrs.charAt(0)
                                });
                            },
                            cardinality: 2,
                            prevalidator: [ {
                                validator: function(chrs, maskset, pos, strict, opts) {
                                    isNaN(maskset.buffer[pos + 1]) || (chrs += maskset.buffer[pos + 1]);
                                    var frontValue = opts.getFrontValue(maskset.mask, maskset.buffer, opts);
                                    -1 !== frontValue.indexOf(opts.placeholder[0]) && (frontValue = "01" + opts.separator);
                                    var isValid = 1 === chrs.length ? opts.regex.val2pre(opts.separator).test(frontValue + chrs) : opts.regex.val2(opts.separator).test(frontValue + chrs);
                                    return isValid && maskset.validPositions[pos] && (opts.regex.val2(opts.separator).test(chrs + maskset.validPositions[pos].input) || (maskset.validPositions[pos].input = "0" === chrs ? "1" : "0")), 
                                    strict || isValid || !(isValid = opts.regex.val2(opts.separator).test(frontValue + "0" + chrs)) ? isValid : (maskset.buffer[pos] = "0", 
                                    pos++, {
                                        pos: pos
                                    });
                                },
                                cardinality: 1
                            } ]
                        },
                        y: {
                            validator: function(chrs, maskset, pos, strict, opts) {
                                return opts.isInYearRange(chrs, opts.yearrange.minyear, opts.yearrange.maxyear);
                            },
                            cardinality: 4,
                            prevalidator: [ {
                                validator: function(chrs, maskset, pos, strict, opts) {
                                    var isValid = opts.isInYearRange(chrs, opts.yearrange.minyear, opts.yearrange.maxyear);
                                    if (!strict && !isValid) {
                                        var yearPrefix = opts.determinebaseyear(opts.yearrange.minyear, opts.yearrange.maxyear, chrs + "0").toString().slice(0, 1);
                                        if (isValid = opts.isInYearRange(yearPrefix + chrs, opts.yearrange.minyear, opts.yearrange.maxyear)) return maskset.buffer[pos++] = yearPrefix.charAt(0), 
                                        {
                                            pos: pos
                                        };
                                        if (yearPrefix = opts.determinebaseyear(opts.yearrange.minyear, opts.yearrange.maxyear, chrs + "0").toString().slice(0, 2), 
                                        isValid = opts.isInYearRange(yearPrefix + chrs, opts.yearrange.minyear, opts.yearrange.maxyear)) return maskset.buffer[pos++] = yearPrefix.charAt(0), 
                                        maskset.buffer[pos++] = yearPrefix.charAt(1), {
                                            pos: pos
                                        };
                                    }
                                    return isValid;
                                },
                                cardinality: 1
                            }, {
                                validator: function(chrs, maskset, pos, strict, opts) {
                                    var isValid = opts.isInYearRange(chrs, opts.yearrange.minyear, opts.yearrange.maxyear);
                                    if (!strict && !isValid) {
                                        var yearPrefix = opts.determinebaseyear(opts.yearrange.minyear, opts.yearrange.maxyear, chrs).toString().slice(0, 2);
                                        if (isValid = opts.isInYearRange(chrs[0] + yearPrefix[1] + chrs[1], opts.yearrange.minyear, opts.yearrange.maxyear)) return maskset.buffer[pos++] = yearPrefix.charAt(1), 
                                        {
                                            pos: pos
                                        };
                                        if (yearPrefix = opts.determinebaseyear(opts.yearrange.minyear, opts.yearrange.maxyear, chrs).toString().slice(0, 2), 
                                        isValid = opts.isInYearRange(yearPrefix + chrs, opts.yearrange.minyear, opts.yearrange.maxyear)) return maskset.buffer[pos - 1] = yearPrefix.charAt(0), 
                                        maskset.buffer[pos++] = yearPrefix.charAt(1), maskset.buffer[pos++] = chrs.charAt(0), 
                                        {
                                            refreshFromBuffer: {
                                                start: pos - 3,
                                                end: pos
                                            },
                                            pos: pos
                                        };
                                    }
                                    return isValid;
                                },
                                cardinality: 2
                            }, {
                                validator: function(chrs, maskset, pos, strict, opts) {
                                    return opts.isInYearRange(chrs, opts.yearrange.minyear, opts.yearrange.maxyear);
                                },
                                cardinality: 3
                            } ]
                        }
                    },
                    insertMode: !1,
                    autoUnmask: !1
                },
                "mm/dd/yyyy": {
                    placeholder: "mm/dd/yyyy",
                    alias: "dd/mm/yyyy",
                    regex: {
                        val2pre: function(separator) {
                            var escapedSeparator = Inputmask.escapeRegex.call(this, separator);
                            return new RegExp("((0[13-9]|1[012])" + escapedSeparator + "[0-3])|(02" + escapedSeparator + "[0-2])");
                        },
                        val2: function(separator) {
                            var escapedSeparator = Inputmask.escapeRegex.call(this, separator);
                            return new RegExp("((0[1-9]|1[012])" + escapedSeparator + "(0[1-9]|[12][0-9]))|((0[13-9]|1[012])" + escapedSeparator + "30)|((0[13578]|1[02])" + escapedSeparator + "31)");
                        },
                        val1pre: new RegExp("[01]"),
                        val1: new RegExp("0[1-9]|1[012]")
                    },
                    leapday: "02/29/",
                    onKeyDown: function(e, buffer, caretPos, opts) {
                        var $input = $(this);
                        if (e.ctrlKey && e.keyCode === Inputmask.keyCode.RIGHT) {
                            var today = new Date();
                            $input.val((today.getMonth() + 1).toString() + today.getDate().toString() + today.getFullYear().toString()), 
                            $input.trigger("setvalue");
                        }
                    }
                },
                "yyyy/mm/dd": {
                    mask: "y/1/2",
                    placeholder: "yyyy/mm/dd",
                    alias: "mm/dd/yyyy",
                    leapday: "/02/29",
                    onKeyDown: function(e, buffer, caretPos, opts) {
                        var $input = $(this);
                        if (e.ctrlKey && e.keyCode === Inputmask.keyCode.RIGHT) {
                            var today = new Date();
                            $input.val(today.getFullYear().toString() + (today.getMonth() + 1).toString() + today.getDate().toString()), 
                            $input.trigger("setvalue");
                        }
                    }
                },
                "dd.mm.yyyy": {
                    mask: "1.2.y",
                    placeholder: "dd.mm.yyyy",
                    leapday: "29.02.",
                    separator: ".",
                    alias: "dd/mm/yyyy"
                },
                "dd-mm-yyyy": {
                    mask: "1-2-y",
                    placeholder: "dd-mm-yyyy",
                    leapday: "29-02-",
                    separator: "-",
                    alias: "dd/mm/yyyy"
                },
                "mm.dd.yyyy": {
                    mask: "1.2.y",
                    placeholder: "mm.dd.yyyy",
                    leapday: "02.29.",
                    separator: ".",
                    alias: "mm/dd/yyyy"
                },
                "mm-dd-yyyy": {
                    mask: "1-2-y",
                    placeholder: "mm-dd-yyyy",
                    leapday: "02-29-",
                    separator: "-",
                    alias: "mm/dd/yyyy"
                },
                "yyyy.mm.dd": {
                    mask: "y.1.2",
                    placeholder: "yyyy.mm.dd",
                    leapday: ".02.29",
                    separator: ".",
                    alias: "yyyy/mm/dd"
                },
                "yyyy-mm-dd": {
                    mask: "y-1-2",
                    placeholder: "yyyy-mm-dd",
                    leapday: "-02-29",
                    separator: "-",
                    alias: "yyyy/mm/dd"
                },
                datetime: {
                    mask: "1/2/y h:s",
                    placeholder: "dd/mm/yyyy hh:mm",
                    alias: "dd/mm/yyyy",
                    regex: {
                        hrspre: new RegExp("[012]"),
                        hrs24: new RegExp("2[0-4]|1[3-9]"),
                        hrs: new RegExp("[01][0-9]|2[0-4]"),
                        ampm: new RegExp("^[a|p|A|P][m|M]"),
                        mspre: new RegExp("[0-5]"),
                        ms: new RegExp("[0-5][0-9]")
                    },
                    timeseparator: ":",
                    hourFormat: "24",
                    definitions: {
                        h: {
                            validator: function(chrs, maskset, pos, strict, opts) {
                                if ("24" === opts.hourFormat && 24 === parseInt(chrs, 10)) return maskset.buffer[pos - 1] = "0", 
                                maskset.buffer[pos] = "0", {
                                    refreshFromBuffer: {
                                        start: pos - 1,
                                        end: pos
                                    },
                                    c: "0"
                                };
                                var isValid = opts.regex.hrs.test(chrs);
                                if (!strict && !isValid && (chrs.charAt(1) === opts.timeseparator || -1 !== "-.:".indexOf(chrs.charAt(1))) && (isValid = opts.regex.hrs.test("0" + chrs.charAt(0)))) return maskset.buffer[pos - 1] = "0", 
                                maskset.buffer[pos] = chrs.charAt(0), pos++, {
                                    refreshFromBuffer: {
                                        start: pos - 2,
                                        end: pos
                                    },
                                    pos: pos,
                                    c: opts.timeseparator
                                };
                                if (isValid && "24" !== opts.hourFormat && opts.regex.hrs24.test(chrs)) {
                                    var tmp = parseInt(chrs, 10);
                                    return 24 === tmp ? (maskset.buffer[pos + 5] = "a", maskset.buffer[pos + 6] = "m") : (maskset.buffer[pos + 5] = "p", 
                                    maskset.buffer[pos + 6] = "m"), (tmp -= 12) < 10 ? (maskset.buffer[pos] = tmp.toString(), 
                                    maskset.buffer[pos - 1] = "0") : (maskset.buffer[pos] = tmp.toString().charAt(1), 
                                    maskset.buffer[pos - 1] = tmp.toString().charAt(0)), {
                                        refreshFromBuffer: {
                                            start: pos - 1,
                                            end: pos + 6
                                        },
                                        c: maskset.buffer[pos]
                                    };
                                }
                                return isValid;
                            },
                            cardinality: 2,
                            prevalidator: [ {
                                validator: function(chrs, maskset, pos, strict, opts) {
                                    var isValid = opts.regex.hrspre.test(chrs);
                                    return strict || isValid || !(isValid = opts.regex.hrs.test("0" + chrs)) ? isValid : (maskset.buffer[pos] = "0", 
                                    pos++, {
                                        pos: pos
                                    });
                                },
                                cardinality: 1
                            } ]
                        },
                        s: {
                            validator: "[0-5][0-9]",
                            cardinality: 2,
                            prevalidator: [ {
                                validator: function(chrs, maskset, pos, strict, opts) {
                                    var isValid = opts.regex.mspre.test(chrs);
                                    return strict || isValid || !(isValid = opts.regex.ms.test("0" + chrs)) ? isValid : (maskset.buffer[pos] = "0", 
                                    pos++, {
                                        pos: pos
                                    });
                                },
                                cardinality: 1
                            } ]
                        },
                        t: {
                            validator: function(chrs, maskset, pos, strict, opts) {
                                return opts.regex.ampm.test(chrs + "m");
                            },
                            casing: "lower",
                            cardinality: 1
                        }
                    },
                    insertMode: !1,
                    autoUnmask: !1
                },
                datetime12: {
                    mask: "1/2/y h:s t\\m",
                    placeholder: "dd/mm/yyyy hh:mm xm",
                    alias: "datetime",
                    hourFormat: "12"
                },
                "mm/dd/yyyy hh:mm xm": {
                    mask: "1/2/y h:s t\\m",
                    placeholder: "mm/dd/yyyy hh:mm xm",
                    alias: "datetime12",
                    regex: {
                        val2pre: function(separator) {
                            var escapedSeparator = Inputmask.escapeRegex.call(this, separator);
                            return new RegExp("((0[13-9]|1[012])" + escapedSeparator + "[0-3])|(02" + escapedSeparator + "[0-2])");
                        },
                        val2: function(separator) {
                            var escapedSeparator = Inputmask.escapeRegex.call(this, separator);
                            return new RegExp("((0[1-9]|1[012])" + escapedSeparator + "(0[1-9]|[12][0-9]))|((0[13-9]|1[012])" + escapedSeparator + "30)|((0[13578]|1[02])" + escapedSeparator + "31)");
                        },
                        val1pre: new RegExp("[01]"),
                        val1: new RegExp("0[1-9]|1[012]")
                    },
                    leapday: "02/29/",
                    onKeyDown: function(e, buffer, caretPos, opts) {
                        var $input = $(this);
                        if (e.ctrlKey && e.keyCode === Inputmask.keyCode.RIGHT) {
                            var today = new Date();
                            $input.val((today.getMonth() + 1).toString() + today.getDate().toString() + today.getFullYear().toString()), 
                            $input.trigger("setvalue");
                        }
                    }
                },
                "hh:mm t": {
                    mask: "h:s t\\m",
                    placeholder: "hh:mm xm",
                    alias: "datetime",
                    hourFormat: "12"
                },
                "h:s t": {
                    mask: "h:s t\\m",
                    placeholder: "hh:mm xm",
                    alias: "datetime",
                    hourFormat: "12"
                },
                "hh:mm:ss": {
                    mask: "h:s:s",
                    placeholder: "hh:mm:ss",
                    alias: "datetime",
                    autoUnmask: !1
                },
                "hh:mm": {
                    mask: "h:s",
                    placeholder: "hh:mm",
                    alias: "datetime",
                    autoUnmask: !1
                },
                date: {
                    alias: "dd/mm/yyyy"
                },
                "mm/yyyy": {
                    mask: "1/y",
                    placeholder: "mm/yyyy",
                    leapday: "donotuse",
                    separator: "/",
                    alias: "mm/dd/yyyy"
                },
                shamsi: {
                    regex: {
                        val2pre: function(separator) {
                            var escapedSeparator = Inputmask.escapeRegex.call(this, separator);
                            return new RegExp("((0[1-9]|1[012])" + escapedSeparator + "[0-3])");
                        },
                        val2: function(separator) {
                            var escapedSeparator = Inputmask.escapeRegex.call(this, separator);
                            return new RegExp("((0[1-9]|1[012])" + escapedSeparator + "(0[1-9]|[12][0-9]))|((0[1-9]|1[012])" + escapedSeparator + "30)|((0[1-6])" + escapedSeparator + "31)");
                        },
                        val1pre: new RegExp("[01]"),
                        val1: new RegExp("0[1-9]|1[012]")
                    },
                    yearrange: {
                        minyear: 1300,
                        maxyear: 1499
                    },
                    mask: "y/1/2",
                    leapday: "/12/30",
                    placeholder: "yyyy/mm/dd",
                    alias: "mm/dd/yyyy",
                    clearIncomplete: !0
                },
                "yyyy-mm-dd hh:mm:ss": {
                    mask: "y-1-2 h:s:s",
                    placeholder: "yyyy-mm-dd hh:mm:ss",
                    alias: "datetime",
                    separator: "-",
                    leapday: "-02-29",
                    regex: {
                        val2pre: function(separator) {
                            var escapedSeparator = Inputmask.escapeRegex.call(this, separator);
                            return new RegExp("((0[13-9]|1[012])" + escapedSeparator + "[0-3])|(02" + escapedSeparator + "[0-2])");
                        },
                        val2: function(separator) {
                            var escapedSeparator = Inputmask.escapeRegex.call(this, separator);
                            return new RegExp("((0[1-9]|1[012])" + escapedSeparator + "(0[1-9]|[12][0-9]))|((0[13-9]|1[012])" + escapedSeparator + "30)|((0[13578]|1[02])" + escapedSeparator + "31)");
                        },
                        val1pre: new RegExp("[01]"),
                        val1: new RegExp("0[1-9]|1[012]")
                    },
                    onKeyDown: function(e, buffer, caretPos, opts) {}
                }
            }), Inputmask;
        });
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __WEBPACK_AMD_DEFINE_RESULT__;
        "function" == typeof Symbol && Symbol.iterator;
        void 0 !== (__WEBPACK_AMD_DEFINE_RESULT__ = function() {
            return window;
        }.call(exports, __webpack_require__, exports, module)) && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__);
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __WEBPACK_AMD_DEFINE_RESULT__;
        "function" == typeof Symbol && Symbol.iterator;
        void 0 !== (__WEBPACK_AMD_DEFINE_RESULT__ = function() {
            return document;
        }.call(exports, __webpack_require__, exports, module)) && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__);
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;
        "function" == typeof Symbol && Symbol.iterator;
        !function(factory) {
            __WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(0), __webpack_require__(1) ], 
            void 0 !== (__WEBPACK_AMD_DEFINE_RESULT__ = "function" == typeof (__WEBPACK_AMD_DEFINE_FACTORY__ = factory) ? __WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__) : __WEBPACK_AMD_DEFINE_FACTORY__) && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__);
        }(function($, Inputmask) {
            return Inputmask.extendDefinitions({
                A: {
                    validator: "[A-Za-zА-яЁёÀ-ÿµ]",
                    cardinality: 1,
                    casing: "upper"
                },
                "&": {
                    validator: "[0-9A-Za-zА-яЁёÀ-ÿµ]",
                    cardinality: 1,
                    casing: "upper"
                },
                "#": {
                    validator: "[0-9A-Fa-f]",
                    cardinality: 1,
                    casing: "upper"
                }
            }), Inputmask.extendAliases({
                url: {
                    definitions: {
                        i: {
                            validator: ".",
                            cardinality: 1
                        }
                    },
                    mask: "(\\http://)|(\\http\\s://)|(ftp://)|(ftp\\s://)i{+}",
                    insertMode: !1,
                    autoUnmask: !1,
                    inputmode: "url"
                },
                ip: {
                    mask: "i[i[i]].i[i[i]].i[i[i]].i[i[i]]",
                    definitions: {
                        i: {
                            validator: function(chrs, maskset, pos, strict, opts) {
                                return pos - 1 > -1 && "." !== maskset.buffer[pos - 1] ? (chrs = maskset.buffer[pos - 1] + chrs, 
                                chrs = pos - 2 > -1 && "." !== maskset.buffer[pos - 2] ? maskset.buffer[pos - 2] + chrs : "0" + chrs) : chrs = "00" + chrs, 
                                new RegExp("25[0-5]|2[0-4][0-9]|[01][0-9][0-9]").test(chrs);
                            },
                            cardinality: 1
                        }
                    },
                    onUnMask: function(maskedValue, unmaskedValue, opts) {
                        return maskedValue;
                    },
                    inputmode: "numeric"
                },
                email: {
                    mask: "*{1,64}[.*{1,64}][.*{1,64}][.*{1,63}]@-{1,63}.-{1,63}[.-{1,63}][.-{1,63}]",
                    greedy: !1,
                    onBeforePaste: function(pastedValue, opts) {
                        return (pastedValue = pastedValue.toLowerCase()).replace("mailto:", "");
                    },
                    definitions: {
                        "*": {
                            validator: "[0-9A-Za-z!#$%&'*+/=?^_`{|}~-]",
                            cardinality: 1,
                            casing: "lower"
                        },
                        "-": {
                            validator: "[0-9A-Za-z-]",
                            cardinality: 1,
                            casing: "lower"
                        }
                    },
                    onUnMask: function(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]",
                            cardinality: 1,
                            casing: "upper"
                        }
                    },
                    clearIncomplete: !0,
                    autoUnmask: !0
                }
            }), Inputmask;
        });
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;
        "function" == typeof Symbol && Symbol.iterator;
        !function(factory) {
            __WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(0), __webpack_require__(1) ], 
            void 0 !== (__WEBPACK_AMD_DEFINE_RESULT__ = "function" == typeof (__WEBPACK_AMD_DEFINE_FACTORY__ = factory) ? __WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__) : __WEBPACK_AMD_DEFINE_FACTORY__) && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__);
        }(function($, Inputmask, undefined) {
            function autoEscape(txt, opts) {
                for (var escapedTxt = "", i = 0; i < txt.length; i++) 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) : escapedTxt += txt.charAt(i);
                return escapedTxt;
            }
            return Inputmask.extendAliases({
                numeric: {
                    mask: function(opts) {
                        if (0 !== opts.repeat && isNaN(opts.integerDigits) && (opts.integerDigits = opts.repeat), 
                        opts.repeat = 0, opts.groupSeparator === opts.radixPoint && ("." === opts.radixPoint ? opts.groupSeparator = "," : "," === opts.radixPoint ? opts.groupSeparator = "." : opts.groupSeparator = ""), 
                        " " === opts.groupSeparator && (opts.skipOptionalPartCharacter = undefined), opts.autoGroup = opts.autoGroup && "" !== opts.groupSeparator, 
                        opts.autoGroup && ("string" == typeof opts.groupSize && isFinite(opts.groupSize) && (opts.groupSize = parseInt(opts.groupSize)), 
                        isFinite(opts.integerDigits))) {
                            var seps = Math.floor(opts.integerDigits / opts.groupSize), mod = opts.integerDigits % opts.groupSize;
                            opts.integerDigits = parseInt(opts.integerDigits) + (0 === mod ? seps - 1 : seps), 
                            opts.integerDigits < 1 && (opts.integerDigits = "*");
                        }
                        opts.placeholder.length > 1 && (opts.placeholder = opts.placeholder.charAt(0)), 
                        "radixFocus" === opts.positionCaretOnClick && "" === opts.placeholder && !1 === opts.integerOptional && (opts.positionCaretOnClick = "lvp"), 
                        opts.definitions[";"] = opts.definitions["~"], opts.definitions[";"].definitionSymbol = "~", 
                        !0 === opts.numericInput && (opts.positionCaretOnClick = "radixFocus" === opts.positionCaretOnClick ? "lvp" : opts.positionCaretOnClick, 
                        opts.digitsOptional = !1, isNaN(opts.digits) && (opts.digits = 2), opts.decimalProtect = !1);
                        var mask = "[+]";
                        if (mask += autoEscape(opts.prefix, opts), !0 === opts.integerOptional ? mask += "~{1," + opts.integerDigits + "}" : mask += "~{" + opts.integerDigits + "}", 
                        opts.digits !== undefined) {
                            opts.radixPointDefinitionSymbol = opts.decimalProtect ? ":" : opts.radixPoint;
                            var dq = opts.digits.toString().split(",");
                            isFinite(dq[0] && dq[1] && isFinite(dq[1])) ? mask += opts.radixPointDefinitionSymbol + ";{" + opts.digits + "}" : (isNaN(opts.digits) || parseInt(opts.digits) > 0) && (opts.digitsOptional ? mask += "[" + opts.radixPointDefinitionSymbol + ";{1," + opts.digits + "}]" : mask += opts.radixPointDefinitionSymbol + ";{" + opts.digits + "}");
                        }
                        return mask += autoEscape(opts.suffix, opts), mask += "[-]", opts.greedy = !1, mask;
                    },
                    placeholder: "",
                    greedy: !1,
                    digits: "*",
                    digitsOptional: !0,
                    enforceDigitsOnBlur: !1,
                    radixPoint: ".",
                    positionCaretOnClick: "radixFocus",
                    groupSize: 3,
                    groupSeparator: "",
                    autoGroup: !1,
                    allowMinus: !0,
                    negationSymbol: {
                        front: "-",
                        back: ""
                    },
                    integerDigits: "+",
                    integerOptional: !0,
                    prefix: "",
                    suffix: "",
                    rightAlign: !0,
                    decimalProtect: !0,
                    min: null,
                    max: null,
                    step: 1,
                    insertMode: !0,
                    autoUnmask: !1,
                    unmaskAsNumber: !1,
                    inputmode: "numeric",
                    preValidation: function(buffer, pos, c, isSelection, opts) {
                        if ("-" === c || c === opts.negationSymbol.front) return !0 === opts.allowMinus && (opts.isNegative = opts.isNegative === undefined || !opts.isNegative, 
                        "" === buffer.join("") || {
                            caret: pos,
                            dopost: !0
                        });
                        if (!1 === isSelection && c === opts.radixPoint && opts.digits !== undefined && (isNaN(opts.digits) || parseInt(opts.digits) > 0)) {
                            var radixPos = $.inArray(opts.radixPoint, buffer);
                            if (-1 !== radixPos) return !0 === opts.numericInput ? pos === radixPos : {
                                caret: radixPos + 1
                            };
                        }
                        return !0;
                    },
                    postValidation: function(buffer, currentResult, opts) {
                        var suffix = opts.suffix.split(""), prefix = opts.prefix.split("");
                        if (currentResult.pos === undefined && currentResult.caret !== undefined && !0 !== currentResult.dopost) return currentResult;
                        var caretPos = currentResult.caret !== undefined ? currentResult.caret : currentResult.pos, maskedValue = buffer.slice();
                        opts.numericInput && (caretPos = maskedValue.length - caretPos - 1, maskedValue = maskedValue.reverse());
                        var charAtPos = maskedValue[caretPos];
                        if (charAtPos === opts.groupSeparator && (charAtPos = maskedValue[caretPos += 1]), 
                        caretPos === maskedValue.length - opts.suffix.length - 1 && charAtPos === opts.radixPoint) return currentResult;
                        charAtPos !== undefined && charAtPos !== opts.radixPoint && charAtPos !== opts.negationSymbol.front && charAtPos !== opts.negationSymbol.back && (maskedValue[caretPos] = "?", 
                        opts.prefix.length > 0 && caretPos >= (!1 === opts.isNegative ? 1 : 0) && caretPos < opts.prefix.length - 1 + (!1 === opts.isNegative ? 1 : 0) ? prefix[caretPos - (!1 === opts.isNegative ? 1 : 0)] = "?" : opts.suffix.length > 0 && caretPos >= maskedValue.length - opts.suffix.length - (!1 === opts.isNegative ? 1 : 0) && (suffix[caretPos - (maskedValue.length - opts.suffix.length - (!1 === opts.isNegative ? 1 : 0))] = "?")), 
                        prefix = prefix.join(""), suffix = suffix.join("");
                        var processValue = maskedValue.join("").replace(prefix, "");
                        if (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) + "$"), ""), 
                        isNaN(opts.placeholder) && (processValue = processValue.replace(new RegExp(Inputmask.escapeRegex(opts.placeholder), "g"), "")), 
                        processValue.length > 1 && 1 !== processValue.indexOf(opts.radixPoint) && ("0" === charAtPos && (processValue = processValue.replace(/^\?/g, "")), 
                        processValue = processValue.replace(/^0/g, "")), processValue.charAt(0) === opts.radixPoint && "" !== opts.radixPoint && !0 !== opts.numericInput && (processValue = "0" + processValue), 
                        "" !== processValue) {
                            if (processValue = processValue.split(""), (!opts.digitsOptional || opts.enforceDigitsOnBlur && "blur" === currentResult.event) && isFinite(opts.digits)) {
                                var radixPosition = $.inArray(opts.radixPoint, processValue), rpb = $.inArray(opts.radixPoint, maskedValue);
                                -1 === radixPosition && (processValue.push(opts.radixPoint), radixPosition = processValue.length - 1);
                                for (var i = 1; i <= opts.digits; i++) opts.digitsOptional && (!opts.enforceDigitsOnBlur || "blur" !== currentResult.event) || processValue[radixPosition + i] !== undefined && processValue[radixPosition + i] !== opts.placeholder.charAt(0) ? -1 !== rpb && maskedValue[rpb + i] !== undefined && (processValue[radixPosition + i] = processValue[radixPosition + i] || maskedValue[rpb + i]) : processValue[radixPosition + i] = currentResult.placeholder || opts.placeholder.charAt(0);
                            }
                            if (!0 !== opts.autoGroup || "" === opts.groupSeparator || charAtPos === opts.radixPoint && currentResult.pos === undefined && !currentResult.dopost) processValue = processValue.join(""); else {
                                var addRadix = processValue[processValue.length - 1] === opts.radixPoint && currentResult.c === opts.radixPoint;
                                processValue = Inputmask(function(buffer, opts) {
                                    var postMask = "";
                                    if (postMask += "(" + opts.groupSeparator + "*{" + opts.groupSize + "}){*}", "" !== opts.radixPoint) {
                                        var radixSplit = buffer.join("").split(opts.radixPoint);
                                        radixSplit[1] && (postMask += opts.radixPoint + "*{" + radixSplit[1].match(/^\d*\??\d*/)[0].length + "}");
                                    }
                                    return postMask;
                                }(processValue, opts), {
                                    numericInput: !0,
                                    jitMasking: !0,
                                    definitions: {
                                        "*": {
                                            validator: "[0-9?]",
                                            cardinality: 1
                                        }
                                    }
                                }).format(processValue.join("")), addRadix && (processValue += opts.radixPoint), 
                                processValue.charAt(0) === opts.groupSeparator && processValue.substr(1);
                            }
                        }
                        if (opts.isNegative && "blur" === currentResult.event && (opts.isNegative = "0" !== processValue), 
                        processValue = prefix + processValue, processValue += suffix, opts.isNegative && (processValue = opts.negationSymbol.front + processValue, 
                        processValue += opts.negationSymbol.back), processValue = processValue.split(""), 
                        charAtPos !== undefined) if (charAtPos !== opts.radixPoint && charAtPos !== opts.negationSymbol.front && charAtPos !== opts.negationSymbol.back) (caretPos = $.inArray("?", processValue)) > -1 ? processValue[caretPos] = charAtPos : caretPos = currentResult.caret || 0; else if (charAtPos === opts.radixPoint || charAtPos === opts.negationSymbol.front || charAtPos === opts.negationSymbol.back) {
                            var newCaretPos = $.inArray(charAtPos, processValue);
                            -1 !== newCaretPos && (caretPos = newCaretPos);
                        }
                        opts.numericInput && (caretPos = processValue.length - caretPos - 1, processValue = processValue.reverse());
                        var rslt = {
                            caret: charAtPos === undefined || currentResult.pos !== undefined ? caretPos + (opts.numericInput ? -1 : 1) : caretPos,
                            buffer: processValue,
                            refreshFromBuffer: currentResult.dopost || buffer.join("") !== processValue.join("")
                        };
                        return rslt.refreshFromBuffer ? rslt : currentResult;
                    },
                    onBeforeWrite: function(e, buffer, caretPos, opts) {
                        if (e) switch (e.type) {
                          case "keydown":
                            return opts.postValidation(buffer, {
                                caret: caretPos,
                                dopost: !0
                            }, opts);
    
                          case "blur":
                          case "checkval":
                            var unmasked;
                            if (function(opts) {
                                opts.parseMinMaxOptions === undefined && (null !== opts.min && (opts.min = opts.min.toString().replace(new RegExp(Inputmask.escapeRegex(opts.groupSeparator), "g"), ""), 
                                "," === opts.radixPoint && (opts.min = opts.min.replace(opts.radixPoint, ".")), 
                                opts.min = isFinite(opts.min) ? parseFloat(opts.min) : NaN, isNaN(opts.min) && (opts.min = Number.MIN_VALUE)), 
                                null !== opts.max && (opts.max = opts.max.toString().replace(new RegExp(Inputmask.escapeRegex(opts.groupSeparator), "g"), ""), 
                                "," === opts.radixPoint && (opts.max = opts.max.replace(opts.radixPoint, ".")), 
                                opts.max = isFinite(opts.max) ? parseFloat(opts.max) : NaN, isNaN(opts.max) && (opts.max = Number.MAX_VALUE)), 
                                opts.parseMinMaxOptions = "done");
                            }(opts), null !== opts.min || null !== opts.max) {
                                if (unmasked = opts.onUnMask(buffer.join(""), undefined, $.extend({}, opts, {
                                    unmaskAsNumber: !0
                                })), null !== opts.min && unmasked < opts.min) return opts.isNegative = opts.min < 0, 
                                opts.postValidation(opts.min.toString().replace(".", opts.radixPoint).split(""), {
                                    caret: caretPos,
                                    dopost: !0,
                                    placeholder: "0"
                                }, opts);
                                if (null !== opts.max && unmasked > opts.max) return opts.isNegative = opts.max < 0, 
                                opts.postValidation(opts.max.toString().replace(".", opts.radixPoint).split(""), {
                                    caret: caretPos,
                                    dopost: !0,
                                    placeholder: "0"
                                }, opts);
                            }
                            return opts.postValidation(buffer, {
                                caret: caretPos,
                                placeholder: "0",
                                event: "blur"
                            }, opts);
    
                          case "_checkval":
                            return {
                                caret: caretPos
                            };
                        }
                    },
                    regex: {
                        integerPart: function(opts, emptyCheck) {
                            return emptyCheck ? new RegExp("[" + Inputmask.escapeRegex(opts.negationSymbol.front) + "+]?") : new RegExp("[" + Inputmask.escapeRegex(opts.negationSymbol.front) + "+]?\\d+");
                        },
                        integerNPart: function(opts) {
                            return new RegExp("[\\d" + Inputmask.escapeRegex(opts.groupSeparator) + Inputmask.escapeRegex(opts.placeholder.charAt(0)) + "]+");
                        }
                    },
                    definitions: {
                        "~": {
                            validator: function(chrs, maskset, pos, strict, opts, isSelection) {
                                var isValid = strict ? new RegExp("[0-9" + Inputmask.escapeRegex(opts.groupSeparator) + "]").test(chrs) : new RegExp("[0-9]").test(chrs);
                                if (!0 === isValid) {
                                    if (!0 !== opts.numericInput && maskset.validPositions[pos] !== undefined && "~" === maskset.validPositions[pos].match.def && !isSelection) {
                                        var processValue = maskset.buffer.join(""), pvRadixSplit = (processValue = (processValue = processValue.replace(new RegExp("[-" + Inputmask.escapeRegex(opts.negationSymbol.front) + "]", "g"), "")).replace(new RegExp(Inputmask.escapeRegex(opts.negationSymbol.back) + "$"), "")).split(opts.radixPoint);
                                        pvRadixSplit.length > 1 && (pvRadixSplit[1] = pvRadixSplit[1].replace(/0/g, opts.placeholder.charAt(0))), 
                                        "0" === pvRadixSplit[0] && (pvRadixSplit[0] = pvRadixSplit[0].replace(/0/g, opts.placeholder.charAt(0))), 
                                        processValue = pvRadixSplit[0] + opts.radixPoint + pvRadixSplit[1] || "";
                                        var bufferTemplate = maskset._buffer.join("");
                                        for (processValue === opts.radixPoint && (processValue = bufferTemplate); null === processValue.match(Inputmask.escapeRegex(bufferTemplate) + "$"); ) bufferTemplate = bufferTemplate.slice(1);
                                        isValid = (processValue = (processValue = processValue.replace(bufferTemplate, "")).split(""))[pos] === undefined ? {
                                            pos: pos,
                                            remove: pos
                                        } : {
                                            pos: pos
                                        };
                                    }
                                } else strict || chrs !== opts.radixPoint || maskset.validPositions[pos - 1] !== undefined || (maskset.buffer[pos] = "0", 
                                isValid = {
                                    pos: pos + 1
                                });
                                return isValid;
                            },
                            cardinality: 1
                        },
                        "+": {
                            validator: function(chrs, maskset, pos, strict, opts) {
                                return opts.allowMinus && ("-" === chrs || chrs === opts.negationSymbol.front);
                            },
                            cardinality: 1,
                            placeholder: ""
                        },
                        "-": {
                            validator: function(chrs, maskset, pos, strict, opts) {
                                return opts.allowMinus && chrs === opts.negationSymbol.back;
                            },
                            cardinality: 1,
                            placeholder: ""
                        },
                        ":": {
                            validator: function(chrs, maskset, pos, strict, opts) {
                                var radix = "[" + Inputmask.escapeRegex(opts.radixPoint) + "]", isValid = new RegExp(radix).test(chrs);
                                return isValid && maskset.validPositions[pos] && maskset.validPositions[pos].match.placeholder === opts.radixPoint && (isValid = {
                                    caret: pos + 1
                                }), isValid;
                            },
                            cardinality: 1,
                            placeholder: function(opts) {
                                return opts.radixPoint;
                            }
                        }
                    },
                    onUnMask: function(maskedValue, unmaskedValue, opts) {
                        if ("" === unmaskedValue && !0 === opts.nullable) return unmaskedValue;
                        var processValue = maskedValue.replace(opts.prefix, "");
                        return processValue = processValue.replace(opts.suffix, ""), processValue = processValue.replace(new RegExp(Inputmask.escapeRegex(opts.groupSeparator), "g"), ""), 
                        "" !== opts.placeholder.charAt(0) && (processValue = processValue.replace(new RegExp(opts.placeholder.charAt(0), "g"), "0")), 
                        opts.unmaskAsNumber ? ("" !== opts.radixPoint && -1 !== processValue.indexOf(opts.radixPoint) && (processValue = processValue.replace(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) + "$"), ""), 
                        Number(processValue)) : processValue;
                    },
                    isComplete: function(buffer, opts) {
                        var maskedValue = buffer.join("");
                        if (buffer.slice().join("") !== maskedValue) return !1;
                        var processValue = maskedValue.replace(opts.prefix, "");
                        return processValue = processValue.replace(opts.suffix, ""), processValue = processValue.replace(new RegExp(Inputmask.escapeRegex(opts.groupSeparator), "g"), ""), 
                        "," === opts.radixPoint && (processValue = processValue.replace(Inputmask.escapeRegex(opts.radixPoint), ".")), 
                        isFinite(processValue);
                    },
                    onBeforeMask: function(initialValue, opts) {
                        if (opts.isNegative = undefined, initialValue = initialValue.toString().charAt(initialValue.length - 1) === opts.radixPoint ? initialValue.toString().substr(0, initialValue.length - 1) : initialValue.toString(), 
                        "" !== opts.radixPoint && isFinite(initialValue)) {
                            var vs = initialValue.split("."), groupSize = "" !== opts.groupSeparator ? parseInt(opts.groupSize) : 0;
                            2 === vs.length && (vs[0].length > groupSize || vs[1].length > groupSize || vs[0].length <= groupSize && vs[1].length < groupSize) && (initialValue = initialValue.replace(".", opts.radixPoint));
                        }
                        var kommaMatches = initialValue.match(/,/g), dotMatches = initialValue.match(/\./g);
                        if (initialValue = dotMatches && kommaMatches ? dotMatches.length > kommaMatches.length ? (initialValue = initialValue.replace(/\./g, "")).replace(",", opts.radixPoint) : kommaMatches.length > dotMatches.length ? (initialValue = initialValue.replace(/,/g, "")).replace(".", opts.radixPoint) : initialValue.indexOf(".") < initialValue.indexOf(",") ? initialValue.replace(/\./g, "") : initialValue.replace(/,/g, "") : initialValue.replace(new RegExp(Inputmask.escapeRegex(opts.groupSeparator), "g"), ""), 
                        0 === opts.digits && (-1 !== initialValue.indexOf(".") ? initialValue = initialValue.substring(0, initialValue.indexOf(".")) : -1 !== initialValue.indexOf(",") && (initialValue = initialValue.substring(0, initialValue.indexOf(",")))), 
                        "" !== opts.radixPoint && isFinite(opts.digits) && -1 !== initialValue.indexOf(opts.radixPoint)) {
                            var decPart = initialValue.split(opts.radixPoint)[1].match(new RegExp("\\d*"))[0];
                            if (parseInt(opts.digits) < decPart.toString().length) {
                                var digitsFactor = Math.pow(10, parseInt(opts.digits));
                                initialValue = initialValue.replace(Inputmask.escapeRegex(opts.radixPoint), "."), 
                                initialValue = (initialValue = Math.round(parseFloat(initialValue) * digitsFactor) / digitsFactor).toString().replace(".", opts.radixPoint);
                            }
                        }
                        return initialValue;
                    },
                    canClearPosition: function(maskset, position, lvp, strict, opts) {
                        var vp = maskset.validPositions[position], canClear = vp.input !== opts.radixPoint || null !== maskset.validPositions[position].match.fn && !1 === opts.decimalProtect || vp.input === opts.radixPoint && maskset.validPositions[position + 1] && null === maskset.validPositions[position + 1].match.fn || isFinite(vp.input) || position === lvp || vp.input === opts.groupSeparator || vp.input === opts.negationSymbol.front || vp.input === opts.negationSymbol.back;
                        return !canClear || "+" !== vp.match.nativeDef && "-" !== vp.match.nativeDef || (opts.isNegative = !1), 
                        canClear;
                    },
                    onKeyDown: function(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");
                        }
                    }
                },
                currency: {
                    prefix: "$ ",
                    groupSeparator: ",",
                    alias: "numeric",
                    placeholder: "0",
                    autoGroup: !0,
                    digits: 2,
                    digitsOptional: !1,
                    clearMaskOnLostFocus: !1
                },
                decimal: {
                    alias: "numeric"
                },
                integer: {
                    alias: "numeric",
                    digits: 0,
                    radixPoint: ""
                },
                percentage: {
                    alias: "numeric",
                    digits: 2,
                    digitsOptional: !0,
                    radixPoint: ".",
                    placeholder: "0",
                    autoGroup: !1,
                    min: 0,
                    max: 100,
                    suffix: " %",
                    allowMinus: !1
                }
            }), Inputmask;
        });
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;
        "function" == typeof Symbol && Symbol.iterator;
        !function(factory) {
            __WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(0), __webpack_require__(1) ], 
            void 0 !== (__WEBPACK_AMD_DEFINE_RESULT__ = "function" == typeof (__WEBPACK_AMD_DEFINE_FACTORY__ = factory) ? __WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__) : __WEBPACK_AMD_DEFINE_FACTORY__) && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__);
        }(function($, Inputmask) {
            function maskSort(a, b) {
                var maska = (a.mask || a).replace(/#/g, "9").replace(/\)/, "9").replace(/[+()#-]/g, ""), maskb = (b.mask || b).replace(/#/g, "9").replace(/\)/, "9").replace(/[+()#-]/g, ""), maskas = (a.mask || a).split("#")[0], maskbs = (b.mask || b).split("#")[0];
                return 0 === maskbs.indexOf(maskas) ? -1 : 0 === maskas.indexOf(maskbs) ? 1 : maska.localeCompare(maskb);
            }
            var analyseMaskBase = Inputmask.prototype.analyseMask;
            return Inputmask.prototype.analyseMask = function(mask, regexMask, opts) {
                function reduceVariations(masks, previousVariation, previousmaskGroup) {
                    previousVariation = previousVariation || "", previousmaskGroup = previousmaskGroup || maskGroups, 
                    "" !== previousVariation && (previousmaskGroup[previousVariation] = {});
                    for (var variation = "", maskGroup = previousmaskGroup[previousVariation] || previousmaskGroup, i = masks.length - 1; i >= 0; i--) maskGroup[variation = (mask = masks[i].mask || masks[i]).substr(0, 1)] = maskGroup[variation] || [], 
                    maskGroup[variation].unshift(mask.substr(1)), masks.splice(i, 1);
                    for (var ndx in maskGroup) maskGroup[ndx].length > 500 && reduceVariations(maskGroup[ndx].slice(), ndx, maskGroup);
                }
                function rebuild(maskGroup) {
                    var mask = "", submasks = [];
                    for (var ndx in maskGroup) $.isArray(maskGroup[ndx]) ? 1 === maskGroup[ndx].length ? submasks.push(ndx + maskGroup[ndx]) : submasks.push(ndx + opts.groupmarker.start + maskGroup[ndx].join(opts.groupmarker.end + opts.alternatormarker + opts.groupmarker.start) + opts.groupmarker.end) : submasks.push(ndx + rebuild(maskGroup[ndx]));
                    return 1 === submasks.length ? mask += submasks[0] : mask += opts.groupmarker.start + submasks.join(opts.groupmarker.end + opts.alternatormarker + opts.groupmarker.start) + opts.groupmarker.end, 
                    mask;
                }
                var maskGroups = {};
                return opts.phoneCodes && (opts.phoneCodes && opts.phoneCodes.length > 1e3 && (reduceVariations((mask = mask.substr(1, mask.length - 2)).split(opts.groupmarker.end + opts.alternatormarker + opts.groupmarker.start)), 
                mask = rebuild(maskGroups)), mask = mask.replace(/9/g, "\\9")), analyseMaskBase.call(this, mask, regexMask, opts);
            }, Inputmask.extendAliases({
                abstractphone: {
                    groupmarker: {
                        start: "<",
                        end: ">"
                    },
                    countrycode: "",
                    phoneCodes: [],
                    mask: function(opts) {
                        return opts.definitions = {
                            "#": Inputmask.prototype.definitions[9]
                        }, opts.phoneCodes.sort(maskSort);
                    },
                    keepStatic: !0,
                    onBeforeMask: function(value, opts) {
                        var processedValue = value.replace(/^0{1,2}/, "").replace(/[\s]/g, "");
                        return (processedValue.indexOf(opts.countrycode) > 1 || -1 === processedValue.indexOf(opts.countrycode)) && (processedValue = "+" + opts.countrycode + processedValue), 
                        processedValue;
                    },
                    onUnMask: function(maskedValue, unmaskedValue, opts) {
                        return maskedValue.replace(/[()#-]/g, "");
                    },
                    inputmode: "tel"
                }
            }), Inputmask;
        });
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;
        "function" == typeof Symbol && Symbol.iterator;
        !function(factory) {
            __WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(0), __webpack_require__(1) ], 
            void 0 !== (__WEBPACK_AMD_DEFINE_RESULT__ = "function" == typeof (__WEBPACK_AMD_DEFINE_FACTORY__ = factory) ? __WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__) : __WEBPACK_AMD_DEFINE_FACTORY__) && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__);
        }(function($, Inputmask) {
            return Inputmask.extendAliases({
                Regex: {
                    mask: "r",
                    greedy: !1,
                    repeat: "*",
                    regex: null,
                    regexTokens: null,
                    tokenizer: /\[\^?]?(?:[^\\\]]+|\\[\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,
                    quantifierFilter: /[0-9]+[^,]/,
                    isComplete: function(buffer, opts) {
                        return new RegExp(opts.regex, opts.casing ? "i" : "").test(buffer.join(""));
                    },
                    definitions: {
                        r: {
                            validator: function(chrs, maskset, pos, strict, opts) {
                                function RegexToken(isGroup, isQuantifier) {
                                    this.matches = [], this.isGroup = isGroup || !1, this.isQuantifier = isQuantifier || !1, 
                                    this.quantifier = {
                                        min: 1,
                                        max: 1
                                    }, this.repeaterPart = void 0;
                                }
                                function validateRegexToken(token, fromGroup) {
                                    var isvalid = !1;
                                    fromGroup && (regexPart += "(", openGroupCount++);
                                    for (var mndx = 0; mndx < token.matches.length; mndx++) {
                                        var matchToken = token.matches[mndx];
                                        if (!0 === matchToken.isGroup) isvalid = validateRegexToken(matchToken, !0); else if (!0 === matchToken.isQuantifier) {
                                            var crrntndx = $.inArray(matchToken, token.matches), matchGroup = token.matches[crrntndx - 1], regexPartBak = regexPart;
                                            if (isNaN(matchToken.quantifier.max)) {
                                                for (;matchToken.repeaterPart && matchToken.repeaterPart !== regexPart && matchToken.repeaterPart.length > regexPart.length && !(isvalid = validateRegexToken(matchGroup, !0)); ) ;
                                                (isvalid = isvalid || validateRegexToken(matchGroup, !0)) && (matchToken.repeaterPart = regexPart), 
                                                regexPart = regexPartBak + matchToken.quantifier.max;
                                            } else {
                                                for (var i = 0, qm = matchToken.quantifier.max - 1; i < qm && !(isvalid = validateRegexToken(matchGroup, !0)); i++) ;
                                                regexPart = regexPartBak + "{" + matchToken.quantifier.min + "," + matchToken.quantifier.max + "}";
                                            }
                                        } else if (void 0 !== matchToken.matches) for (var k = 0; k < matchToken.length && !(isvalid = validateRegexToken(matchToken[k], fromGroup)); k++) ; else {
                                            var testExp;
                                            if ("[" == matchToken.charAt(0)) {
                                                testExp = regexPart, testExp += matchToken;
                                                for (j = 0; j < openGroupCount; j++) testExp += ")";
                                                isvalid = (exp = new RegExp("^(" + testExp + ")$", opts.casing ? "i" : "")).test(bufferStr);
                                            } else for (var l = 0, tl = matchToken.length; l < tl; l++) if ("\\" !== matchToken.charAt(l)) {
                                                testExp = regexPart, testExp = (testExp += matchToken.substr(0, l + 1)).replace(/\|$/, "");
                                                for (var j = 0; j < openGroupCount; j++) testExp += ")";
                                                var exp = new RegExp("^(" + testExp + ")$", opts.casing ? "i" : "");
                                                if (isvalid = exp.test(bufferStr)) break;
                                            }
                                            regexPart += matchToken;
                                        }
                                        if (isvalid) break;
                                    }
                                    return fromGroup && (regexPart += ")", openGroupCount--), isvalid;
                                }
                                var bufferStr, groupToken, cbuffer = maskset.buffer.slice(), regexPart = "", isValid = !1, openGroupCount = 0;
                                null === opts.regexTokens && function() {
                                    var match, m, currentToken = new RegexToken(), opengroups = [];
                                    for (opts.regexTokens = []; match = opts.tokenizer.exec(opts.regex); ) switch ((m = match[0]).charAt(0)) {
                                      case "(":
                                        opengroups.push(new RegexToken(!0));
                                        break;
    
                                      case ")":
                                        groupToken = opengroups.pop(), opengroups.length > 0 ? opengroups[opengroups.length - 1].matches.push(groupToken) : currentToken.matches.push(groupToken);
                                        break;
    
                                      case "{":
                                      case "+":
                                      case "*":
                                        var quantifierToken = new RegexToken(!1, !0), mq = (m = m.replace(/[{}]/g, "")).split(","), mq0 = isNaN(mq[0]) ? mq[0] : parseInt(mq[0]), mq1 = 1 === mq.length ? mq0 : isNaN(mq[1]) ? mq[1] : parseInt(mq[1]);
                                        if (quantifierToken.quantifier = {
                                            min: mq0,
                                            max: mq1
                                        }, opengroups.length > 0) {
                                            var matches = opengroups[opengroups.length - 1].matches;
                                            (match = matches.pop()).isGroup || ((groupToken = new RegexToken(!0)).matches.push(match), 
                                            match = groupToken), matches.push(match), matches.push(quantifierToken);
                                        } else (match = currentToken.matches.pop()).isGroup || ((groupToken = new RegexToken(!0)).matches.push(match), 
                                        match = groupToken), currentToken.matches.push(match), currentToken.matches.push(quantifierToken);
                                        break;
    
                                      default:
                                        opengroups.length > 0 ? opengroups[opengroups.length - 1].matches.push(m) : currentToken.matches.push(m);
                                    }
                                    currentToken.matches.length > 0 && opts.regexTokens.push(currentToken);
                                }(), cbuffer.splice(pos, 0, chrs), bufferStr = cbuffer.join("");
                                for (var i = 0; i < opts.regexTokens.length; i++) {
                                    var regexToken = opts.regexTokens[i];
                                    if (isValid = validateRegexToken(regexToken, regexToken.isGroup)) break;
                                }
                                return isValid;
                            },
                            cardinality: 1
                        }
                    }
                }
            }), Inputmask;
        });
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__, _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(obj) {
            return typeof obj;
        } : function(obj) {
            return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
        };
        !function(factory) {
            __WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(2), __webpack_require__(1) ], 
            void 0 !== (__WEBPACK_AMD_DEFINE_RESULT__ = "function" == typeof (__WEBPACK_AMD_DEFINE_FACTORY__ = factory) ? __WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__) : __WEBPACK_AMD_DEFINE_FACTORY__) && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__);
        }(function($, Inputmask) {
            return void 0 === $.fn.inputmask && ($.fn.inputmask = function(fn, options) {
                var nptmask, input = this[0];
                if (void 0 === options && (options = {}), "string" == typeof fn) switch (fn) {
                  case "unmaskedvalue":
                    return input && input.inputmask ? input.inputmask.unmaskedvalue() : $(input).val();
    
                  case "remove":
                    return this.each(function() {
                        this.inputmask && this.inputmask.remove();
                    });
    
                  case "getemptymask":
                    return input && input.inputmask ? input.inputmask.getemptymask() : "";
    
                  case "hasMaskedValue":
                    return !(!input || !input.inputmask) && input.inputmask.hasMaskedValue();
    
                  case "isComplete":
                    return !input || !input.inputmask || input.inputmask.isComplete();
    
                  case "getmetadata":
                    return input && input.inputmask ? input.inputmask.getmetadata() : void 0;
    
                  case "setvalue":
                    $(input).val(options), input && void 0 === input.inputmask && $(input).triggerHandler("setvalue");
                    break;
    
                  case "option":
                    if ("string" != typeof options) return this.each(function() {
                        if (void 0 !== this.inputmask) return this.inputmask.option(options);
                    });
                    if (input && void 0 !== input.inputmask) return input.inputmask.option(options);
                    break;
    
                  default:
                    return options.alias = fn, nptmask = new Inputmask(options), this.each(function() {
                        nptmask.mask(this);
                    });
                } else {
                    if ("object" == (void 0 === fn ? "undefined" : _typeof(fn))) return nptmask = new Inputmask(fn), 
                    void 0 === fn.mask && void 0 === fn.alias ? this.each(function() {
                        if (void 0 !== this.inputmask) return this.inputmask.option(fn);
                        nptmask.mask(this);
                    }) : this.each(function() {
                        nptmask.mask(this);
                    });
                    if (void 0 === fn) return this.each(function() {
                        (nptmask = new Inputmask(options)).mask(this);
                    });
                }
            }), $.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.8.6 - 22-12-2017 */
    (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;
    };
    
    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;
    };
    
    /**
     * 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 width="20" height="20" align="absmiddle" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAOwUlEQVR42uVbCVyO6RbPmn0sw9gZS0aZO4y5GTEUE2ObxjZjrbHEJVy3sWS5pkaWxjLEkCVDSbSgFLdESaWSLIVUSIi4kvb9f895vi/zbbR+yZ339/tbnu99n/ec/3Oe85xznufV0CjDBaAdwZqwnzCJ0FXjHV70/i8J5oQDhCFV8cJdq1atwqxZs+Ds7Iz4+HhqwgXCLELNKlK6G2Ej4e6lS5ewZcsWzJgxA+fOnWNZFqvzxT1v3boF/qcsBg0ahP3796OwsJAFWKYuIqjfPoS9cXFxWL58Obp06SInh5aWFr//jjoJWLlu3TolAorRuXNn7Ny5k4W4Spgj81xrgj5hLmED4RDhlNRygglBhADCSakpWxFMCHoETUJTwrYHDx7A1NT0je9nPHz4kN/fXl0EeI0aNeqtAjB69+4NPz8/FsSdlXvy5An8/f1hZ2cHCwsLGBsbY/To0cJy9PT0MGDAAAwePBhGRkbClNesWYODBw8iODgYOTk53M/d9evXo27duiW++8iRI3z/ZHURENOjR48ShSjGuHHjhHJ16tQp9TOKaNWqlZKpvw1MHluQOpSvk5eXh5YtW5ZbmarAvHnzmIBd6iCgXnZ2Npo1a1atCWAfwY5SHQTUKCoqQocOHao1AebmHBJgi7p8QBDP6epMwKFDvMDAWF0ELLS1ta3WBNy9e5cJMFIXAdvt7e2rNQHDhw9nAv5D+KKylV9y8+bNCi1pVYWZM2cyCfaVTcDdsqzH7xpBQRxcwqyylLdi5/K+KM/Q0dFhAqIri4Bn1T0AUgVpdmhYUeVHnD59+r1TnjF27Fgm4HhFCThoYmLyXhLQoEGD4mRKsyIE3OrZs+d7SQCDCyZcNSqv8k1evXoFTU3NUr+wzUcfYqRBf8yb/C2WzfoBFoTF08fBdMIITDD8CsP1+kL30x7Q6dYZH7drjfZ0f4fWLdG1Q1t81qMLBvTRwejB/TBl1BDMnzQGS2dMxKo5k7Fs9iSY/jAaBvR8Pc26pZaH02quLZSXgO6xsbGlelGnli1wZKcVMqN8gKcRwItrf+K/VB95doXaLwOJIVSzOU/+2Re5kV7IuuyJrIhTyLt6mmztLBBPNZLHoUAy9fE8UvJ8ikxfj8PwJPQErJeYlkquTZs2MQFLykuANgc/Jb2kn3Z3ZMaQUrmxwO1zyAo7gfRAJ6RfOIyMEFdkXj5F8BTK5lzxQv610yi8QcFatI8gQoCIK7x+hojwRnaE5H4JTiEj9Pjr/rJDqcZyn9b4ovu45LYbdWvXeqtsXMHiSlZ5CegRExPz1hd83PYj5POo0QinXyLFg48hnZTOiQ1Dzr1IZEaeQRoJn0HKZIR7lA2kfHrQUerXHTlx4ZL+rnjjFRGRGeYB5MUj2GnbW+XbuJFrp1heXgI6JCYmvvUFN1x3Aek3SWkapRAXMeJFGS8ge2Xfuog0toaykED3Mpk8+shOk+sv68Y50V9WuKewBKt5094o39atW/mRf5WXgIYZGRlo3Lixys4nj6A6Z1YMcqRCpwU4ouDlUyHk/QA/hNttR25Wlvh/ZthJUsil9ATQ/axkYbqEzDgfL0Ts/x35+aLyTES7IY36Q6w/+Q4/tP6wuUoZ9+7dy7ebVmQZjO/atavKzn32rAdeXkd6KCkXdAxZ13yFcLFnvPD73zrDVrsdTs6eggKSuSjjORHkUGoC0i86Iyc6QPQX7eqMnTodYNuzHU4vnosiaitMSUSavwMy6d3IvEUrzViVMrq5uXEX4ytCgL++vr5Sx7Vr1cIDX0dKkQJfj37Rs3jw1sBxkwlwGD4Ax3+ciN1faCHW76xQRFgAOcjSEMBkIe0x8nLzcez7kTg8Rh/uxuOxR/cTJISFSfq7eATpZCk8CAfXLVFJwIULXHnHoIoQYLtw4UKljps2aogXQcQuef/XAiMDKY+S4DhyEFwpDnCj9f+Afl8EbbWRTANaAdihlYoAMn8aZzyNuYODX/eD29TvRH/7v+qN8H27JdOAyWQfQQ74xPafVRLAPox9WUlK6hIGEgx4f00Kg2JcvHhRqeP6FIwknXemyen/2gLIIeC/CYk49M0AuE4xgtu0sThg8AUCN62TEuBdRgJo2Y+Kxh9D/k59SQiwH9QHobt3SAk4KSGA4oWjm1YqyVi8U6Soj4yOrHM/jTAyKVby/PnzIoNi8L+L4eXlpXoFcLcTgc1rAlISkJeXDxeK2A6P1hdTwI6mQPTJE+WbAlnJyE7PhNO3Q3BkrKGYWtxfHMkkmQLO0ilwA7+vXqAkn66urtBLUZ9iHfm30NBQaPAf165dA0d9vP2UlJSEp0+f4vHjx3j06JH4e+rUqUovcNmyGkiNEkLwklXsBG+ecMUOnfbYod1emG5uboFKJ8jPFVD0l0dBUHqoPDHpQeQEb0qc4FUHe3KAbYUT9JgzDbwOFL5MfN0fXkXhJ5PxSvLt2LFD1Ah5u4z1YJ14l4qnBe8v3rhxAzz4PAVG8nLHivIP0dHRiIiIQGRkpEgmrl69ClW1QBMjQ7LDW8hmU+RRI69ckJIkhL7jfRJBm62R+TJVYq6h0jhBRslsivqenT2MF/7OyI70VmkFhWnPJaS6OyPkt43IycqR9EfWlH7JDQUUTuNhCHR7Ke9YcRp/5coVoQPrcvnyZURFRYmBZlLS0kR8MVLD29sbnp6e8PHxQUBAgCgn8YO8E3z79m3BGKeVc+bMkXuBZt06SA12F/F5Go0gR4C8HBalPZMPXKL8lQKhPAqF+f97KXFyNx6HQsoPsshJ/kmAp2TKkJLISpXvjyxNhMYcDVLOEO+lPDi8B5mamipkZx1YF9YpJCRErAy+vr5CZ9ZdWABhDGEYYTBhAOFz3g4nfMJelNCbkNCpUye5F034mvxIPi1/FM+zQCw0k5B9O0iEr5kRXkqhMJOVf9NXIHjtT7hmaymSoBzKETimkAuFpaF1dkwI9RcmIYaXv3BJXoGCuyIgk5WpefPmKCgoYK46SmX/RKoL69Sfl0WuFEl1HlmWJXE5z6WmTZvKJxxmxkIQ3AuU5APk6NICj4hRT6eITTEEzqWk55HHPjz3cxJhNF5cxeNT9kj2cRDTQjEkzpDtjyyCic5l5fEA7uSHFEefR5pPsahrb2B9QkICFHeJ51HunkdLIg0VLY0BFKdLwllVHp4dHyvst3QuEiiju21vA/+VZkiluIKt4I3RIfWXQ4QgKUxkni47LJWUP3PmjHo2RxVI+CebmKJP6EiFDVurxUgmExe5PHlnPAkn8w4QqW62NCVmYopozid5H0CI9RKE21ggJeAYEeMnfitOnRn5XCfgeJ+VTosWQU8MOc6ZE0cqnUm4fv165SrPBVHCfMI4TowUfmOfsIcdJh92kBWmUcP6GDt8EDZbzIffH5tx3/ewSFjw5LKk0MEFEkZenDBjgew7Yiog5brkt+QrknvJmhIp4Apw/A1bVpjhG/0v5d7Vrl07bNu2TelUSqUoz8uI3Z49OEtBAy+TdP1CqKtwHzvQUxxgTJs2TeX5gdq1a0ObSmCjh+jB+NuvRamL1+3ls77HCip1rTSdJP5eNnMizKndjMLoH42G4bthX+FzHS3UVVEC69evH3799VeKMXJZrlWKclUGAZ5jxoxB02ZNsNlxH74aagBHZyex986HlVTczyGmI58h4CjL2toa48ePFxsUPEotWrQoc0GT0/C2bduiY8eO4ISMcxLeoOFYhS6qm2EpoZG65jmbv+dPSyRZlt5QfVjvtX19AOFNL+aDFNI4m0eFc9Ho5ORkaGtrl5kAVp6DMOk88efEjLe++ZhclZwHTJHEHbs4YOCmLj2645fdvwnTK42zoXtaEHwNDQ3LXdZm5yad3/2r+gQmDsRnIF5KAldX6zdsgG/GG8F44Vzcu3eP2y1K6GPr2rVrK1zbnz59Or/LoaoJCPZ4kCZsjw9GECL79OmDj9q2wb+320C3/5fgPQO6Vrzh+fpcDqxXr16lbHBwgkZXm6okYJr0ECMrX5vraiJ1lArEjrEnzWuOqemiYj9spGd2ee478XkiPsJakmJ83qA05/8qXNurJFLiunXrhpo1a6LxB02wyHIFZpovgOHwYfjZ0hK2lH5u2rwZ5suWYv5ycyUlmjRpgl69eimlrFy3kwuoyOvXr19frm3RokVMwPZ3TYC57E6xVq+e6KzVDSaL/oEp82Zh8IhhWLjGAp/p9oX5ujVKBNjY2MDV1VWuzd3dXaTesm2biUQuZ8u28elSPmKr8a4vdog8GnJpcT1N1KHUuBbt0jSgWuGbzJh3mVhh2TYHBwdxjFa2jVcZnvPVlQBOLXdZWlqW2ZFxNYYVlm07fPgwAgMD5dr4OD5HeHLFFxM+O42DGtXhIkFaMQlcUjIzM0P37t1Ro0YNpZPjPJcVK7SOjo5ybU5OTqIAo0gAh97VlgAZIj4l8Pn4WFaO64ocuXG6zJtDbMqySnC7IgF8uptLVrJtq1evFuWqak+A4j4i4TNpltiJ8LPiNFFFwNGjRyWFyfedAFUny/joekkEuLi4KK0CfykCeFnkiu1flgBeFtl3/D8SsMbKykpOifv37ysRcPz4cVHKUiSA8wwNdR9/VTMBSh9Y8S4Nf2qnSICiBbDzVCRg9uzZTMC+94kAv6FDh8opwRsVHPjItnl4eEDxHNLKlStFXV+2javQ/M1SpZe+1KA4L4G7WDG57fSm/OUbXiqG0ewAFYOeYcN4fwZhvLkp2y4tftrxcltdlf/w+fPn4qNGxTCYU2m6nrRu3VqunT/EoiuZvw6TTZHpyuNNmEaNGsndP3fu3OJAq1N1JOAHDmyKheVtNP4OkE2crULRAW7fvl20EyyLy24a8p+/7WISFixYIMLt4t82bNhQYjXqXREgPq3j74mlX3AmSL8E1eOPIBXnuVT5OsVZpuLnOMeOHeN7vifwiYhYzhC5IpwlOXj1QXWdBmy/XWU/X+UqMZfKBw4cKAobHPlJlZe9h6tOu+7cuSN2dg0MDMSSyZUpmXvaSD+crq/xvl0k9BTCRa7qEPq+5T4t6ffF52WVV+f1P6zyLG30bsU4AAAAAElFTkSuQmCC">',
      'showdown': '<img width="20" height="20" align="absmiddle" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAACXBIWXMAAAsTAAALEwEAmpwYAAAKT2lDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVNnVFPpFj333vRCS4iAlEtvUhUIIFJCi4AUkSYqIQkQSoghodkVUcERRUUEG8igiAOOjoCMFVEsDIoK2AfkIaKOg6OIisr74Xuja9a89+bN/rXXPues852zzwfACAyWSDNRNYAMqUIeEeCDx8TG4eQuQIEKJHAAEAizZCFz/SMBAPh+PDwrIsAHvgABeNMLCADATZvAMByH/w/qQplcAYCEAcB0kThLCIAUAEB6jkKmAEBGAYCdmCZTAKAEAGDLY2LjAFAtAGAnf+bTAICd+Jl7AQBblCEVAaCRACATZYhEAGg7AKzPVopFAFgwABRmS8Q5ANgtADBJV2ZIALC3AMDOEAuyAAgMADBRiIUpAAR7AGDIIyN4AISZABRG8lc88SuuEOcqAAB4mbI8uSQ5RYFbCC1xB1dXLh4ozkkXKxQ2YQJhmkAuwnmZGTKBNA/g88wAAKCRFRHgg/P9eM4Ors7ONo62Dl8t6r8G/yJiYuP+5c+rcEAAAOF0ftH+LC+zGoA7BoBt/qIl7gRoXgugdfeLZrIPQLUAoOnaV/Nw+H48PEWhkLnZ2eXk5NhKxEJbYcpXff5nwl/AV/1s+X48/Pf14L7iJIEyXYFHBPjgwsz0TKUcz5IJhGLc5o9H/LcL//wd0yLESWK5WCoU41EScY5EmozzMqUiiUKSKcUl0v9k4t8s+wM+3zUAsGo+AXuRLahdYwP2SycQWHTA4vcAAPK7b8HUKAgDgGiD4c93/+8//UegJQCAZkmScQAAXkQkLlTKsz/HCAAARKCBKrBBG/TBGCzABhzBBdzBC/xgNoRCJMTCQhBCCmSAHHJgKayCQiiGzbAdKmAv1EAdNMBRaIaTcA4uwlW4Dj1wD/phCJ7BKLyBCQRByAgTYSHaiAFiilgjjggXmYX4IcFIBBKLJCDJiBRRIkuRNUgxUopUIFVIHfI9cgI5h1xGupE7yAAygvyGvEcxlIGyUT3UDLVDuag3GoRGogvQZHQxmo8WoJvQcrQaPYw2oefQq2gP2o8+Q8cwwOgYBzPEbDAuxsNCsTgsCZNjy7EirAyrxhqwVqwDu4n1Y8+xdwQSgUXACTYEd0IgYR5BSFhMWE7YSKggHCQ0EdoJNwkDhFHCJyKTqEu0JroR+cQYYjIxh1hILCPWEo8TLxB7iEPENyQSiUMyJ7mQAkmxpFTSEtJG0m5SI+ksqZs0SBojk8naZGuyBzmULCAryIXkneTD5DPkG+Qh8lsKnWJAcaT4U+IoUspqShnlEOU05QZlmDJBVaOaUt2ooVQRNY9aQq2htlKvUYeoEzR1mjnNgxZJS6WtopXTGmgXaPdpr+h0uhHdlR5Ol9BX0svpR+iX6AP0dwwNhhWDx4hnKBmbGAcYZxl3GK+YTKYZ04sZx1QwNzHrmOeZD5lvVVgqtip8FZHKCpVKlSaVGyovVKmqpqreqgtV81XLVI+pXlN9rkZVM1PjqQnUlqtVqp1Q61MbU2epO6iHqmeob1Q/pH5Z/YkGWcNMw09DpFGgsV/jvMYgC2MZs3gsIWsNq4Z1gTXEJrHN2Xx2KruY/R27iz2qqaE5QzNKM1ezUvOUZj8H45hx+Jx0TgnnKKeX836K3hTvKeIpG6Y0TLkxZVxrqpaXllirSKtRq0frvTau7aedpr1Fu1n7gQ5Bx0onXCdHZ4/OBZ3nU9lT3acKpxZNPTr1ri6qa6UbobtEd79up+6Ynr5egJ5Mb6feeb3n+hx9L/1U/W36p/VHDFgGswwkBtsMzhg8xTVxbzwdL8fb8VFDXcNAQ6VhlWGX4YSRudE8o9VGjUYPjGnGXOMk423GbcajJgYmISZLTepN7ppSTbmmKaY7TDtMx83MzaLN1pk1mz0x1zLnm+eb15vft2BaeFostqi2uGVJsuRaplnutrxuhVo5WaVYVVpds0atna0l1rutu6cRp7lOk06rntZnw7Dxtsm2qbcZsOXYBtuutm22fWFnYhdnt8Wuw+6TvZN9un2N/T0HDYfZDqsdWh1+c7RyFDpWOt6azpzuP33F9JbpL2dYzxDP2DPjthPLKcRpnVOb00dnF2e5c4PziIuJS4LLLpc+Lpsbxt3IveRKdPVxXeF60vWdm7Obwu2o26/uNu5p7ofcn8w0nymeWTNz0MPIQ+BR5dE/C5+VMGvfrH5PQ0+BZ7XnIy9jL5FXrdewt6V3qvdh7xc+9j5yn+M+4zw33jLeWV/MN8C3yLfLT8Nvnl+F30N/I/9k/3r/0QCngCUBZwOJgUGBWwL7+Hp8Ib+OPzrbZfay2e1BjKC5QRVBj4KtguXBrSFoyOyQrSH355jOkc5pDoVQfujW0Adh5mGLw34MJ4WHhVeGP45wiFga0TGXNXfR3ENz30T6RJZE3ptnMU85ry1KNSo+qi5qPNo3ujS6P8YuZlnM1VidWElsSxw5LiquNm5svt/87fOH4p3iC+N7F5gvyF1weaHOwvSFpxapLhIsOpZATIhOOJTwQRAqqBaMJfITdyWOCnnCHcJnIi/RNtGI2ENcKh5O8kgqTXqS7JG8NXkkxTOlLOW5hCepkLxMDUzdmzqeFpp2IG0yPTq9MYOSkZBxQqohTZO2Z+pn5mZ2y6xlhbL+xW6Lty8elQfJa7OQrAVZLQq2QqboVFoo1yoHsmdlV2a/zYnKOZarnivN7cyzytuQN5zvn//tEsIS4ZK2pYZLVy0dWOa9rGo5sjxxedsK4xUFK4ZWBqw8uIq2Km3VT6vtV5eufr0mek1rgV7ByoLBtQFr6wtVCuWFfevc1+1dT1gvWd+1YfqGnRs+FYmKrhTbF5cVf9go3HjlG4dvyr+Z3JS0qavEuWTPZtJm6ebeLZ5bDpaql+aXDm4N2dq0Dd9WtO319kXbL5fNKNu7g7ZDuaO/PLi8ZafJzs07P1SkVPRU+lQ27tLdtWHX+G7R7ht7vPY07NXbW7z3/T7JvttVAVVN1WbVZftJ+7P3P66Jqun4lvttXa1ObXHtxwPSA/0HIw6217nU1R3SPVRSj9Yr60cOxx++/p3vdy0NNg1VjZzG4iNwRHnk6fcJ3/ceDTradox7rOEH0x92HWcdL2pCmvKaRptTmvtbYlu6T8w+0dbq3nr8R9sfD5w0PFl5SvNUyWna6YLTk2fyz4ydlZ19fi753GDborZ752PO32oPb++6EHTh0kX/i+c7vDvOXPK4dPKy2+UTV7hXmq86X23qdOo8/pPTT8e7nLuarrlca7nuer21e2b36RueN87d9L158Rb/1tWeOT3dvfN6b/fF9/XfFt1+cif9zsu72Xcn7q28T7xf9EDtQdlD3YfVP1v+3Njv3H9qwHeg89HcR/cGhYPP/pH1jw9DBY+Zj8uGDYbrnjg+OTniP3L96fynQ89kzyaeF/6i/suuFxYvfvjV69fO0ZjRoZfyl5O/bXyl/erA6xmv28bCxh6+yXgzMV70VvvtwXfcdx3vo98PT+R8IH8o/2j5sfVT0Kf7kxmTk/8EA5jz/GMzLdsAAECtaVRYdFhNTDpjb20uYWRvYmUueG1wAAAAAAA8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/Pgo8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJBZG9iZSBYTVAgQ29yZSA1LjYtYzA2NyA3OS4xNTc3NDcsIDIwMTUvMDMvMzAtMjM6NDA6NDIgICAgICAgICI+CiAgIDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+CiAgICAgIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiCiAgICAgICAgICAgIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIKICAgICAgICAgICAgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIgogICAgICAgICAgICB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iCiAgICAgICAgICAgIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIgogICAgICAgICAgICB4bWxuczpzdEV2dD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlRXZlbnQjIgogICAgICAgICAgICB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIKICAgICAgICAgICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iCiAgICAgICAgICAgIHhtbG5zOmV4aWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20vZXhpZi8xLjAvIj4KICAgICAgICAgPHhtcDpDcmVhdG9yVG9vbD5BZG9iZSBQaG90b3Nob3AgQ0MgMjAxNSAoV2luZG93cyk8L3htcDpDcmVhdG9yVG9vbD4KICAgICAgICAgPHhtcDpDcmVhdGVEYXRlPjIwMTUtMDEtMTVUMjE6MDE6MTlaPC94bXA6Q3JlYXRlRGF0ZT4KICAgICAgICAgPHhtcDpNZXRhZGF0YURhdGU+MjAxNy0xMC0yNFQxMzozMTozMCswMTowMDwveG1wOk1ldGFkYXRhRGF0ZT4KICAgICAgICAgPHhtcDpNb2RpZnlEYXRlPjIwMTctMTAtMjRUMTM6MzE6MzArMDE6MDA8L3htcDpNb2RpZnlEYXRlPgogICAgICAgICA8cGhvdG9zaG9wOkNvbG9yTW9kZT4zPC9waG90b3Nob3A6Q29sb3JNb2RlPgogICAgICAgICA8cGhvdG9zaG9wOklDQ1Byb2ZpbGU+c1JHQiBJRUM2MTk2Ni0yLjE8L3Bob3Rvc2hvcDpJQ0NQcm9maWxlPgogICAgICAgICA8cGhvdG9zaG9wOlRleHRMYXllcnM+CiAgICAgICAgICAgIDxyZGY6QmFnPgogICAgICAgICAgICAgICA8cmRmOmxpIHJkZjpwYXJzZVR5cGU9IlJlc291cmNlIj4KICAgICAgICAgICAgICAgICAgPHBob3Rvc2hvcDpMYXllck5hbWU+UyAtPC9waG90b3Nob3A6TGF5ZXJOYW1lPgogICAgICAgICAgICAgICAgICA8cGhvdG9zaG9wOkxheWVyVGV4dD5TIC08L3Bob3Rvc2hvcDpMYXllclRleHQ+CiAgICAgICAgICAgICAgIDwvcmRmOmxpPgogICAgICAgICAgICA8L3JkZjpCYWc+CiAgICAgICAgIDwvcGhvdG9zaG9wOlRleHRMYXllcnM+CiAgICAgICAgIDxkYzpmb3JtYXQ+aW1hZ2UvcG5nPC9kYzpmb3JtYXQ+CiAgICAgICAgIDx4bXBNTTpJbnN0YW5jZUlEPnhtcC5paWQ6N2NkMzQxNzctOWYyZi0yNDRiLWEyYjQtMzU1MzJkY2Y1MWJiPC94bXBNTTpJbnN0YW5jZUlEPgogICAgICAgICA8eG1wTU06RG9jdW1lbnRJRD5hZG9iZTpkb2NpZDpwaG90b3Nob3A6M2E1YzgxYmYtYjhiNy0xMWU3LTk0NDktYTQ2MzdlZjJkNjMzPC94bXBNTTpEb2N1bWVudElEPgogICAgICAgICA8eG1wTU06T3JpZ2luYWxEb2N1bWVudElEPnhtcC5kaWQ6NjBDNUFFNjVGNjlDRTQxMTk0NUE4NTVFM0JDQTdFRUI8L3htcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD4KICAgICAgICAgPHhtcE1NOkhpc3Rvcnk+CiAgICAgICAgICAgIDxyZGY6U2VxPgogICAgICAgICAgICAgICA8cmRmOmxpIHJkZjpwYXJzZVR5cGU9IlJlc291cmNlIj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmFjdGlvbj5jcmVhdGVkPC9zdEV2dDphY3Rpb24+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDppbnN0YW5jZUlEPnhtcC5paWQ6NjBDNUFFNjVGNjlDRTQxMTk0NUE4NTVFM0JDQTdFRUI8L3N0RXZ0Omluc3RhbmNlSUQ+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDp3aGVuPjIwMTUtMDEtMTVUMjE6MDE6MTlaPC9zdEV2dDp3aGVuPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6c29mdHdhcmVBZ2VudD5BZG9iZSBQaG90b3Nob3AgQ1M2IChXaW5kb3dzKTwvc3RFdnQ6c29mdHdhcmVBZ2VudD4KICAgICAgICAgICAgICAgPC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGkgcmRmOnBhcnNlVHlwZT0iUmVzb3VyY2UiPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6YWN0aW9uPnNhdmVkPC9zdEV2dDphY3Rpb24+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDppbnN0YW5jZUlEPnhtcC5paWQ6ODZjNjBkMGQtOGY0Yy01ZTRlLWEwMjQtODI4ZWQyNTIwZDc3PC9zdEV2dDppbnN0YW5jZUlEPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6d2hlbj4yMDE3LTEwLTI0VDEzOjMxOjMwKzAxOjAwPC9zdEV2dDp3aGVuPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6c29mdHdhcmVBZ2VudD5BZG9iZSBQaG90b3Nob3AgQ0MgMjAxNSAoV2luZG93cyk8L3N0RXZ0OnNvZnR3YXJlQWdlbnQ+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDpjaGFuZ2VkPi88L3N0RXZ0OmNoYW5nZWQ+CiAgICAgICAgICAgICAgIDwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpIHJkZjpwYXJzZVR5cGU9IlJlc291cmNlIj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmFjdGlvbj5jb252ZXJ0ZWQ8L3N0RXZ0OmFjdGlvbj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OnBhcmFtZXRlcnM+ZnJvbSBhcHBsaWNhdGlvbi92bmQuYWRvYmUucGhvdG9zaG9wIHRvIGltYWdlL3BuZzwvc3RFdnQ6cGFyYW1ldGVycz4KICAgICAgICAgICAgICAgPC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGkgcmRmOnBhcnNlVHlwZT0iUmVzb3VyY2UiPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6YWN0aW9uPmRlcml2ZWQ8L3N0RXZ0OmFjdGlvbj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OnBhcmFtZXRlcnM+Y29udmVydGVkIGZyb20gYXBwbGljYXRpb24vdm5kLmFkb2JlLnBob3Rvc2hvcCB0byBpbWFnZS9wbmc8L3N0RXZ0OnBhcmFtZXRlcnM+CiAgICAgICAgICAgICAgIDwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpIHJkZjpwYXJzZVR5cGU9IlJlc291cmNlIj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmFjdGlvbj5zYXZlZDwvc3RFdnQ6YWN0aW9uPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6aW5zdGFuY2VJRD54bXAuaWlkOjdjZDM0MTc3LTlmMmYtMjQ0Yi1hMmI0LTM1NTMyZGNmNTFiYjwvc3RFdnQ6aW5zdGFuY2VJRD4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OndoZW4+MjAxNy0xMC0yNFQxMzozMTozMCswMTowMDwvc3RFdnQ6d2hlbj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OnNvZnR3YXJlQWdlbnQ+QWRvYmUgUGhvdG9zaG9wIENDIDIwMTUgKFdpbmRvd3MpPC9zdEV2dDpzb2Z0d2FyZUFnZW50PgogICAgICAgICAgICAgICAgICA8c3RFdnQ6Y2hhbmdlZD4vPC9zdEV2dDpjaGFuZ2VkPgogICAgICAgICAgICAgICA8L3JkZjpsaT4KICAgICAgICAgICAgPC9yZGY6U2VxPgogICAgICAgICA8L3htcE1NOkhpc3Rvcnk+CiAgICAgICAgIDx4bXBNTTpEZXJpdmVkRnJvbSByZGY6cGFyc2VUeXBlPSJSZXNvdXJjZSI+CiAgICAgICAgICAgIDxzdFJlZjppbnN0YW5jZUlEPnhtcC5paWQ6ODZjNjBkMGQtOGY0Yy01ZTRlLWEwMjQtODI4ZWQyNTIwZDc3PC9zdFJlZjppbnN0YW5jZUlEPgogICAgICAgICAgICA8c3RSZWY6ZG9jdW1lbnRJRD54bXAuZGlkOjYwQzVBRTY1RjY5Q0U0MTE5NDVBODU1RTNCQ0E3RUVCPC9zdFJlZjpkb2N1bWVudElEPgogICAgICAgICAgICA8c3RSZWY6b3JpZ2luYWxEb2N1bWVudElEPnhtcC5kaWQ6NjBDNUFFNjVGNjlDRTQxMTk0NUE4NTVFM0JDQTdFRUI8L3N0UmVmOm9yaWdpbmFsRG9jdW1lbnRJRD4KICAgICAgICAgPC94bXBNTTpEZXJpdmVkRnJvbT4KICAgICAgICAgPHRpZmY6T3JpZW50YXRpb24+MTwvdGlmZjpPcmllbnRhdGlvbj4KICAgICAgICAgPHRpZmY6WFJlc29sdXRpb24+NzIwMDAwLzEwMDAwPC90aWZmOlhSZXNvbHV0aW9uPgogICAgICAgICA8dGlmZjpZUmVzb2x1dGlvbj43MjAwMDAvMTAwMDA8L3RpZmY6WVJlc29sdXRpb24+CiAgICAgICAgIDx0aWZmOlJlc29sdXRpb25Vbml0PjI8L3RpZmY6UmVzb2x1dGlvblVuaXQ+CiAgICAgICAgIDxleGlmOkNvbG9yU3BhY2U+MTwvZXhpZjpDb2xvclNwYWNlPgogICAgICAgICA8ZXhpZjpQaXhlbFhEaW1lbnNpb24+NjQ8L2V4aWY6UGl4ZWxYRGltZW5zaW9uPgogICAgICAgICA8ZXhpZjpQaXhlbFlEaW1lbnNpb24+NjQ8L2V4aWY6UGl4ZWxZRGltZW5zaW9uPgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAKPD94cGFja2V0IGVuZD0idyI/Pse7bzcAAAAgY0hSTQAAeiUAAICDAAD5/wAAgOkAAHUwAADqYAAAOpgAABdvkl/FRgAAA1JJREFUeNrsm1+OmlAUhz+aeS9dwZggJn1AnRUMO6jpBgZXULuC2hWUWUGZBTSxKyiuoA4mfUBMnB04K5g+9DihRBHlyh/lJLwIXLgf99xzzu9etZeXFy7Z3nDh1gBoAFy4XeVtQNO0zNcapmUDfUBPnFoBfhQGq6IBaHmjwD4Ahmk5wAD4kKG5J8CNwsAFaHe6DvA9cc0wCgOv8gDka3vA9RHNPgo0D7hNnJtGYWBXxgV2dH4MfMnRRA+Y1WIO2NJ5F/ikoKm3tYsChmkNFHW+fmHQMC1dfHaXPQP3wM1yMdc2B/AOGALTWobBmI1Shu0UGCwX83XyRBQGawHntTtdG5gUNfxVu4CTNqNv6/wWGL7kCc+1AmCYVisl3I2ydD4GYZUCs7IjoLXrxHIx9w9tLAqDCfBwDrXAY457x+cAoCfuwRGjYFUnAGk+PsjR7s8Dn1VeLWCYVlpDw+VivjVHSHt+u9PVJbzGzZXQWTkAkz0V31fATUaEsjVJlQBs4FeGcteLgzgbAALBA+4y3voAeJL8nA0AHfClnM1qm1HhnYUidCSE+KzvSSJUTwAxCOMcpfETMFYpfRUKIAbCFhC3OTJJJwqDWS0BxED0JZ4Pjix1P2+E0loCSMBwyK4S/xc1ojBwag8gMU84cvTKGgmlAYhngu1O9xAXuVE5J1QCQCz3bwHuHvdQui5QKQAxEO6eEKpsFCgTRSXkvdoxSlBMCxhJJbgrrbZRtHCiShN0pRB6PeQ3ckBw2K0oKXMBVYJIP+Nvh9qulFivGoBt1lLQxowT2ykBXCfnhZIglgYACWmqXQv+baioBYCeiCQHm+QEg1O7RhF7hO4OhSAhcJKSFU7qBGADwZeqMMuXn6TUBw8qlaMrirNb4LdhWlP+SWD+cjFfxTpuS2GUpik+o3jFSEkqbJiWn0P0OMSGqlWiOu0TvD+FRHZKAE+oW+cfRmEwqlsesJJEJs8y91QqP+9UL6lqEtz2gpuNEY5sm9sIHln2DRa2aFKGJtiXkZEMiWtgVvRKUSUFkSKt2S7fAGgAXLYpmQQXf36MUChTZdUa2u8/rkvPA6Tz30r4eH3ybcBS5gJ6SaNXb+aABkA1AMxKenclBZLW/He4cYEGwEXb3wEASelexk6LIIIAAAAASUVORK5CYII=">'
    };
    
    /**
     * 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 (nbsp causes trouble in older browsers and some regex flavors)
        text = text.replace(/\u00A0/g, ' ');
    
        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;
      };
    
      /**
       * 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\-]+))(?=[.!?;,[\]()]|\s|$)/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;
    });
    
    /**
     * Turn Markdown link shortcuts into XHTML <a> tags.
     */
    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;
    });
    
    /**
     * These are all the transformations that occur *within* block-level
     * tags like paragraphs, headers, and list items.
     */
    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)(```+|~~~+)([^\s`~]*)\n([\s\S]*?)\n\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) {
          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>';
        });
      } else {
        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;
    });
    
    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}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,names,index,lookupHit=false;while(context){if(name.indexOf(".")>0){value=context.view;names=name.split(".");index=0;while(value!=null&&index<names.length){if(index===names.length-1)lookupHit=hasProperty(value,names[index]);value=value[names[index++]]}}else{value=context.view[name];lookupHit=hasProperty(context.view,name)}if(lookupHit)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 tokens=cache[template];if(tokens==null)tokens=cache[template]=parseTemplate(template,tags);return tokens};Writer.prototype.render=function render(template,view,partials){var tokens=this.parse(template);var context=view instanceof Context?view:new Context(view);return this.renderTokens(tokens,context,partials,template)};Writer.prototype.renderTokens=function renderTokens(tokens,context,partials,originalTemplate){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,originalTemplate);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){if(!partials)return;var value=isFunction(partials)?partials(token[1]):partials[token[1]];if(value!=null)return this.renderTokens(this.parse(value),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="2.3.0";mustache.tags=["{{","}}"];var defaultWriter=new Writer;mustache.clearCache=function clearCache(){return defaultWriter.clearCache()};mustache.parse=function parse(template,tags){return defaultWriter.parse(template,tags)};mustache.render=function render(template,view,partials){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)};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", "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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInByZXR0aWZ5LmpzIiwibW9tZW50LXdpdGgtbG9jYWxlcy5qcyIsIm1vbWVudC10aW1lem9uZS5taW4uanMiLCJ0ZW1wdXNkb21pbnVzLWNvcmUuanMiLCJ0ZW1wdXNkb21pbnVzLWJvb3RzdHJhcC00LmpzIiwianF1ZXJ5LmlucHV0bWFzay5idW5kbGUuanMiLCJ2ZXJzaW9uLmpzIiwicG9zaXRpb24uanMiLCJzaG93ZG93bi5qcyIsIm1hcmtkb3duLmpzIiwidG8tbWFya2Rvd24uanMiLCJib290c3RyYXAtbWFya2Rvd24uanMiLCJib290c3RyYXAtbWFya2Rvd24uYXIuanMiLCJib290c3RyYXAtbWFya2Rvd24uY3MuanMiLCJib290c3RyYXAtbWFya2Rvd24uZGEuanMiLCJib290c3RyYXAtbWFya2Rvd24uZGUuanMiLCJib290c3RyYXAtbWFya2Rvd24uZXMuanMiLCJib290c3RyYXAtbWFya2Rvd24uZmEuanMiLCJib290c3RyYXAtbWFya2Rvd24uZnIuanMiLCJib290c3RyYXAtbWFya2Rvd24uamEuanMiLCJib290c3RyYXAtbWFya2Rvd24ua3IuanMiLCJib290c3RyYXAtbWFya2Rvd24ubmIuanMiLCJib290c3RyYXAtbWFya2Rvd24ubmwuanMiLCJib290c3RyYXAtbWFya2Rvd24ucGwuanMiLCJib290c3RyYXAtbWFya2Rvd24uc2wuanMiLCJib290c3RyYXAtbWFya2Rvd24uc3YuanMiLCJib290c3RyYXAtbWFya2Rvd24udHIuanMiLCJib290c3RyYXAtbWFya2Rvd24uemguanMiLCJtdXN0YWNoZS5taW4uanMiLCJ0cml2aWFsLWNvbXBvbmVudHMuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FDdm5EQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQ2o5YkE7QUNBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUNqaERBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQ2h0RkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUM5K0ZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQ2pCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQ2xmQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FDeDVJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQzdyREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FDcHhCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FDOTJDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQ3hCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQzNCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUMxQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUMzQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUN4QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUN4QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQy9CQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUM3QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUN4QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUN4QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUN4QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUMzQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUMzQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUN4QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQy9CQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUNoQ0E7QUFDQTtBQ0RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsImZpbGUiOiJidXR0ZXJmYWNlcy10aGlyZC1wYXJ0eS5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCAoQykgMjAwNiBHb29nbGUgSW5jLlxuLy9cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4vLyB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4vLyBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbi8vXG4vLyAgICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuLy9cbi8vIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbi8vIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbi8vIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuLy8gU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuLy8gbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cblxuLyoqXG4gKiBAZmlsZW92ZXJ2aWV3XG4gKiBzb21lIGZ1bmN0aW9ucyBmb3IgYnJvd3Nlci1zaWRlIHByZXR0eSBwcmludGluZyBvZiBjb2RlIGNvbnRhaW5lZCBpbiBodG1sLlxuICpcbiAqIDxwPlxuICogRm9yIGEgZmFpcmx5IGNvbXByZWhlbnNpdmUgc2V0IG9mIGxhbmd1YWdlcyBzZWUgdGhlXG4gKiA8YSBocmVmPVwiaHR0cDovL2dvb2dsZS1jb2RlLXByZXR0aWZ5Lmdvb2dsZWNvZGUuY29tL3N2bi90cnVuay9SRUFETUUuaHRtbCNsYW5nc1wiPlJFQURNRTwvYT5cbiAqIGZpbGUgdGhhdCBjYW1lIHdpdGggdGhpcyBzb3VyY2UuICBBdCBhIG1pbmltdW0sIHRoZSBsZXhlciBzaG91bGQgd29yayBvbiBhXG4gKiBudW1iZXIgb2YgbGFuZ3VhZ2VzIGluY2x1ZGluZyBDIGFuZCBmcmllbmRzLCBKYXZhLCBQeXRob24sIEJhc2gsIFNRTCwgSFRNTCxcbiAqIFhNTCwgQ1NTLCBKYXZhc2NyaXB0LCBhbmQgTWFrZWZpbGVzLiAgSXQgd29ya3MgcGFzc2FibHkgb24gUnVieSwgUEhQIGFuZCBBd2tcbiAqIGFuZCBhIHN1YnNldCBvZiBQZXJsLCBidXQsIGJlY2F1c2Ugb2YgY29tbWVudGluZyBjb252ZW50aW9ucywgZG9lc24ndCB3b3JrIG9uXG4gKiBTbWFsbHRhbGssIExpc3AtbGlrZSwgb3IgQ0FNTC1saWtlIGxhbmd1YWdlcyB3aXRob3V0IGFuIGV4cGxpY2l0IGxhbmcgY2xhc3MuXG4gKiA8cD5cbiAqIFVzYWdlOiA8b2w+XG4gKiA8bGk+IGluY2x1ZGUgdGhpcyBzb3VyY2UgZmlsZSBpbiBhbiBodG1sIHBhZ2UgdmlhXG4gKiAgIHtAY29kZSA8c2NyaXB0IHR5cGU9XCJ0ZXh0L2phdmFzY3JpcHRcIiBzcmM9XCIvcGF0aC90by9wcmV0dGlmeS5qc1wiPjwvc2NyaXB0Pn1cbiAqIDxsaT4gZGVmaW5lIHN0eWxlIHJ1bGVzLiAgU2VlIHRoZSBleGFtcGxlIHBhZ2UgZm9yIGV4YW1wbGVzLlxuICogPGxpPiBtYXJrIHRoZSB7QGNvZGUgPHByZT59IGFuZCB7QGNvZGUgPGNvZGU+fSB0YWdzIGluIHlvdXIgc291cmNlIHdpdGhcbiAqICAgIHtAY29kZSBjbGFzcz1wcmV0dHlwcmludC59XG4gKiAgICBZb3UgY2FuIGFsc28gdXNlIHRoZSAoaHRtbCBkZXByZWNhdGVkKSB7QGNvZGUgPHhtcD59IHRhZywgYnV0IHRoZSBwcmV0dHlcbiAqICAgIHByaW50ZXIgbmVlZHMgdG8gZG8gbW9yZSBzdWJzdGFudGlhbCBET00gbWFuaXB1bGF0aW9ucyB0byBzdXBwb3J0IHRoYXQsIHNvXG4gKiAgICBzb21lIGNzcyBzdHlsZXMgbWF5IG5vdCBiZSBwcmVzZXJ2ZWQuXG4gKiA8L29sPlxuICogVGhhdCdzIGl0LiAgSSB3YW50ZWQgdG8ga2VlcCB0aGUgQVBJIGFzIHNpbXBsZSBhcyBwb3NzaWJsZSwgc28gdGhlcmUncyBub1xuICogbmVlZCB0byBzcGVjaWZ5IHdoaWNoIGxhbmd1YWdlIHRoZSBjb2RlIGlzIGluLCBidXQgaWYgeW91IHdpc2gsIHlvdSBjYW4gYWRkXG4gKiBhbm90aGVyIGNsYXNzIHRvIHRoZSB7QGNvZGUgPHByZT59IG9yIHtAY29kZSA8Y29kZT59IGVsZW1lbnQgdG8gc3BlY2lmeSB0aGVcbiAqIGxhbmd1YWdlLCBhcyBpbiB7QGNvZGUgPHByZSBjbGFzcz1cInByZXR0eXByaW50IGxhbmctamF2YVwiPn0uICBBbnkgY2xhc3MgdGhhdFxuICogc3RhcnRzIHdpdGggXCJsYW5nLVwiIGZvbGxvd2VkIGJ5IGEgZmlsZSBleHRlbnNpb24sIHNwZWNpZmllcyB0aGUgZmlsZSB0eXBlLlxuICogU2VlIHRoZSBcImxhbmctKi5qc1wiIGZpbGVzIGluIHRoaXMgZGlyZWN0b3J5IGZvciBjb2RlIHRoYXQgaW1wbGVtZW50c1xuICogcGVyLWxhbmd1YWdlIGZpbGUgaGFuZGxlcnMuXG4gKiA8cD5cbiAqIENoYW5nZSBsb2c6PGJyPlxuICogY2JldXN0LCAyMDA2LzA4LzIyXG4gKiA8YmxvY2txdW90ZT5cbiAqICAgSmF2YSBhbm5vdGF0aW9ucyAoc3RhcnQgd2l0aCBcIkBcIikgYXJlIG5vdyBjYXB0dXJlZCBhcyBsaXRlcmFscyAoXCJsaXRcIilcbiAqIDwvYmxvY2txdW90ZT5cbiAqIEByZXF1aXJlcyBjb25zb2xlXG4gKi9cblxuLy8gSlNMaW50IGRlY2xhcmF0aW9uc1xuLypnbG9iYWwgY29uc29sZSwgZG9jdW1lbnQsIG5hdmlnYXRvciwgc2V0VGltZW91dCwgd2luZG93LCBkZWZpbmUgKi9cblxuLyoqIEBkZWZpbmUge2Jvb2xlYW59ICovXG52YXIgSU5fR0xPQkFMX1NDT1BFID0gdHJ1ZTtcblxuLyoqXG4gKiBTcGxpdCB7QGNvZGUgcHJldHR5UHJpbnR9IGludG8gbXVsdGlwbGUgdGltZW91dHMgc28gYXMgbm90IHRvIGludGVyZmVyZSB3aXRoXG4gKiBVSSBldmVudHMuXG4gKiBJZiBzZXQgdG8ge0Bjb2RlIGZhbHNlfSwge0Bjb2RlIHByZXR0eVByaW50KCl9IGlzIHN5bmNocm9ub3VzLlxuICovXG53aW5kb3dbJ1BSX1NIT1VMRF9VU0VfQ09OVElOVUFUSU9OJ10gPSB0cnVlO1xuXG4vKipcbiAqIFByZXR0eSBwcmludCBhIGNodW5rIG9mIGNvZGUuXG4gKiBAcGFyYW0ge3N0cmluZ30gc291cmNlQ29kZUh0bWwgVGhlIEhUTUwgdG8gcHJldHR5IHByaW50LlxuICogQHBhcmFtIHtzdHJpbmd9IG9wdF9sYW5nRXh0ZW5zaW9uIFRoZSBsYW5ndWFnZSBuYW1lIHRvIHVzZS5cbiAqICAgICBUeXBpY2FsbHksIGEgZmlsZW5hbWUgZXh0ZW5zaW9uIGxpa2UgJ2NwcCcgb3IgJ2phdmEnLlxuICogQHBhcmFtIHtudW1iZXJ8Ym9vbGVhbn0gb3B0X251bWJlckxpbmVzIFRydWUgdG8gbnVtYmVyIGxpbmVzLFxuICogICAgIG9yIHRoZSAxLWluZGV4ZWQgbnVtYmVyIG9mIHRoZSBmaXJzdCBsaW5lIGluIHNvdXJjZUNvZGVIdG1sLlxuICogQHJldHVybiB7c3RyaW5nfSBjb2RlIGFzIGh0bWwsIGJ1dCBwcmV0dGllclxuICovXG52YXIgcHJldHR5UHJpbnRPbmU7XG4vKipcbiAqIEZpbmQgYWxsIHRoZSB7QGNvZGUgPHByZT59IGFuZCB7QGNvZGUgPGNvZGU+fSB0YWdzIGluIHRoZSBET00gd2l0aFxuICoge0Bjb2RlIGNsYXNzPXByZXR0eXByaW50fSBhbmQgcHJldHRpZnkgdGhlbS5cbiAqXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBvcHRfd2hlbkRvbmUgY2FsbGVkIHdoZW4gcHJldHRpZnlpbmcgaXMgZG9uZS5cbiAqIEBwYXJhbSB7SFRNTEVsZW1lbnR8SFRNTERvY3VtZW50fSBvcHRfcm9vdCBhbiBlbGVtZW50IG9yIGRvY3VtZW50XG4gKiAgIGNvbnRhaW5pbmcgYWxsIHRoZSBlbGVtZW50cyB0byBwcmV0dHkgcHJpbnQuXG4gKiAgIERlZmF1bHRzIHRvIHtAY29kZSBkb2N1bWVudC5ib2R5fS5cbiAqL1xudmFyIHByZXR0eVByaW50O1xuXG5cbihmdW5jdGlvbiAoKSB7XG4gIHZhciB3aW4gPSB3aW5kb3c7XG4gIC8vIEtleXdvcmQgbGlzdHMgZm9yIHZhcmlvdXMgbGFuZ3VhZ2VzLlxuICAvLyBXZSB1c2UgdGhpbmdzIHRoYXQgY29lcmNlIHRvIHN0cmluZ3MgdG8gbWFrZSB0aGVtIGNvbXBhY3Qgd2hlbiBtaW5pZmllZFxuICAvLyBhbmQgdG8gZGVmZWF0IGFnZ3Jlc3NpdmUgb3B0aW1pemVycyB0aGF0IGZvbGQgbGFyZ2Ugc3RyaW5nIGNvbnN0YW50cy5cbiAgdmFyIEZMT1dfQ09OVFJPTF9LRVlXT1JEUyA9IFtcImJyZWFrLGNvbnRpbnVlLGRvLGVsc2UsZm9yLGlmLHJldHVybix3aGlsZVwiXTtcbiAgdmFyIENfS0VZV09SRFMgPSBbRkxPV19DT05UUk9MX0tFWVdPUkRTLFwiYXV0byxjYXNlLGNoYXIsY29uc3QsZGVmYXVsdCxcIiArIFxuICAgICAgXCJkb3VibGUsZW51bSxleHRlcm4sZmxvYXQsZ290byxpbmxpbmUsaW50LGxvbmcscmVnaXN0ZXIsc2hvcnQsc2lnbmVkLFwiICtcbiAgICAgIFwic2l6ZW9mLHN0YXRpYyxzdHJ1Y3Qsc3dpdGNoLHR5cGVkZWYsdW5pb24sdW5zaWduZWQsdm9pZCx2b2xhdGlsZVwiXTtcbiAgdmFyIENPTU1PTl9LRVlXT1JEUyA9IFtDX0tFWVdPUkRTLFwiY2F0Y2gsY2xhc3MsZGVsZXRlLGZhbHNlLGltcG9ydCxcIiArXG4gICAgICBcIm5ldyxvcGVyYXRvcixwcml2YXRlLHByb3RlY3RlZCxwdWJsaWMsdGhpcyx0aHJvdyx0cnVlLHRyeSx0eXBlb2ZcIl07XG4gIHZhciBDUFBfS0VZV09SRFMgPSBbQ09NTU9OX0tFWVdPUkRTLFwiYWxpZ25vZixhbGlnbl91bmlvbixhc20sYXhpb20sYm9vbCxcIiArXG4gICAgICBcImNvbmNlcHQsY29uY2VwdF9tYXAsY29uc3RfY2FzdCxjb25zdGV4cHIsZGVjbHR5cGUsZGVsZWdhdGUsXCIgK1xuICAgICAgXCJkeW5hbWljX2Nhc3QsZXhwbGljaXQsZXhwb3J0LGZyaWVuZCxnZW5lcmljLGxhdGVfY2hlY2ssXCIgK1xuICAgICAgXCJtdXRhYmxlLG5hbWVzcGFjZSxudWxscHRyLHByb3BlcnR5LHJlaW50ZXJwcmV0X2Nhc3Qsc3RhdGljX2Fzc2VydCxcIiArXG4gICAgICBcInN0YXRpY19jYXN0LHRlbXBsYXRlLHR5cGVpZCx0eXBlbmFtZSx1c2luZyx2aXJ0dWFsLHdoZXJlXCJdO1xuICB2YXIgSkFWQV9LRVlXT1JEUyA9IFtDT01NT05fS0VZV09SRFMsXG4gICAgICBcImFic3RyYWN0LGFzc2VydCxib29sZWFuLGJ5dGUsZXh0ZW5kcyxmaW5hbCxmaW5hbGx5LGltcGxlbWVudHMsaW1wb3J0LFwiICtcbiAgICAgIFwiaW5zdGFuY2VvZixpbnRlcmZhY2UsbnVsbCxuYXRpdmUscGFja2FnZSxzdHJpY3RmcCxzdXBlcixzeW5jaHJvbml6ZWQsXCIgK1xuICAgICAgXCJ0aHJvd3MsdHJhbnNpZW50XCJdO1xuICB2YXIgQ1NIQVJQX0tFWVdPUkRTID0gW0pBVkFfS0VZV09SRFMsXG4gICAgICBcImFzLGJhc2UsYnksY2hlY2tlZCxkZWNpbWFsLGRlbGVnYXRlLGRlc2NlbmRpbmcsZHluYW1pYyxldmVudCxcIiArXG4gICAgICBcImZpeGVkLGZvcmVhY2gsZnJvbSxncm91cCxpbXBsaWNpdCxpbixpbnRlcm5hbCxpbnRvLGlzLGxldCxcIiArXG4gICAgICBcImxvY2ssb2JqZWN0LG91dCxvdmVycmlkZSxvcmRlcmJ5LHBhcmFtcyxwYXJ0aWFsLHJlYWRvbmx5LHJlZixzYnl0ZSxcIiArXG4gICAgICBcInNlYWxlZCxzdGFja2FsbG9jLHN0cmluZyxzZWxlY3QsdWludCx1bG9uZyx1bmNoZWNrZWQsdW5zYWZlLHVzaG9ydCxcIiArXG4gICAgICBcInZhcix2aXJ0dWFsLHdoZXJlXCJdO1xuICB2YXIgQ09GRkVFX0tFWVdPUkRTID0gXCJhbGwsYW5kLGJ5LGNhdGNoLGNsYXNzLGVsc2UsZXh0ZW5kcyxmYWxzZSxmaW5hbGx5LFwiICtcbiAgICAgIFwiZm9yLGlmLGluLGlzLGlzbnQsbG9vcCxuZXcsbm8sbm90LG51bGwsb2Ysb2ZmLG9uLG9yLHJldHVybixzdXBlcix0aGVuLFwiICtcbiAgICAgIFwidGhyb3csdHJ1ZSx0cnksdW5sZXNzLHVudGlsLHdoZW4sd2hpbGUseWVzXCI7XG4gIHZhciBKU0NSSVBUX0tFWVdPUkRTID0gW0NPTU1PTl9LRVlXT1JEUyxcbiAgICAgIFwiZGVidWdnZXIsZXZhbCxleHBvcnQsZnVuY3Rpb24sZ2V0LG51bGwsc2V0LHVuZGVmaW5lZCx2YXIsd2l0aCxcIiArXG4gICAgICBcIkluZmluaXR5LE5hTlwiXTtcbiAgdmFyIFBFUkxfS0VZV09SRFMgPSBcImNhbGxlcixkZWxldGUsZGllLGRvLGR1bXAsZWxzaWYsZXZhbCxleGl0LGZvcmVhY2gsZm9yLFwiICtcbiAgICAgIFwiZ290byxpZixpbXBvcnQsbGFzdCxsb2NhbCxteSxuZXh0LG5vLG91cixwcmludCxwYWNrYWdlLHJlZG8scmVxdWlyZSxcIiArXG4gICAgICBcInN1Yix1bmRlZix1bmxlc3MsdW50aWwsdXNlLHdhbnRhcnJheSx3aGlsZSxCRUdJTixFTkRcIjtcbiAgdmFyIFBZVEhPTl9LRVlXT1JEUyA9IFtGTE9XX0NPTlRST0xfS0VZV09SRFMsIFwiYW5kLGFzLGFzc2VydCxjbGFzcyxkZWYsZGVsLFwiICtcbiAgICAgIFwiZWxpZixleGNlcHQsZXhlYyxmaW5hbGx5LGZyb20sZ2xvYmFsLGltcG9ydCxpbixpcyxsYW1iZGEsXCIgK1xuICAgICAgXCJub25sb2NhbCxub3Qsb3IscGFzcyxwcmludCxyYWlzZSx0cnksd2l0aCx5aWVsZCxcIiArXG4gICAgICBcIkZhbHNlLFRydWUsTm9uZVwiXTtcbiAgdmFyIFJVQllfS0VZV09SRFMgPSBbRkxPV19DT05UUk9MX0tFWVdPUkRTLCBcImFsaWFzLGFuZCxiZWdpbixjYXNlLGNsYXNzLFwiICtcbiAgICAgIFwiZGVmLGRlZmluZWQsZWxzaWYsZW5kLGVuc3VyZSxmYWxzZSxpbixtb2R1bGUsbmV4dCxuaWwsbm90LG9yLHJlZG8sXCIgK1xuICAgICAgXCJyZXNjdWUscmV0cnksc2VsZixzdXBlcix0aGVuLHRydWUsdW5kZWYsdW5sZXNzLHVudGlsLHdoZW4seWllbGQsXCIgK1xuICAgICAgXCJCRUdJTixFTkRcIl07XG4gICB2YXIgUlVTVF9LRVlXT1JEUyA9IFtGTE9XX0NPTlRST0xfS0VZV09SRFMsIFwiYXMsYXNzZXJ0LGNvbnN0LGNvcHksZHJvcCxcIiArXG4gICAgICBcImVudW0sZXh0ZXJuLGZhaWwsZmFsc2UsZm4saW1wbCxsZXQsbG9nLGxvb3AsbWF0Y2gsbW9kLG1vdmUsbXV0LHByaXYsXCIgK1xuICAgICAgXCJwdWIscHVyZSxyZWYsc2VsZixzdGF0aWMsc3RydWN0LHRydWUsdHJhaXQsdHlwZSx1bnNhZmUsdXNlXCJdO1xuICB2YXIgU0hfS0VZV09SRFMgPSBbRkxPV19DT05UUk9MX0tFWVdPUkRTLCBcImNhc2UsZG9uZSxlbGlmLGVzYWMsZXZhbCxmaSxcIiArXG4gICAgICBcImZ1bmN0aW9uLGluLGxvY2FsLHNldCx0aGVuLHVudGlsXCJdO1xuICB2YXIgQUxMX0tFWVdPUkRTID0gW1xuICAgICAgQ1BQX0tFWVdPUkRTLCBDU0hBUlBfS0VZV09SRFMsIEpTQ1JJUFRfS0VZV09SRFMsIFBFUkxfS0VZV09SRFMsXG4gICAgICBQWVRIT05fS0VZV09SRFMsIFJVQllfS0VZV09SRFMsIFNIX0tFWVdPUkRTXTtcbiAgdmFyIENfVFlQRVMgPSAvXihESVJ8RklMRXx2ZWN0b3J8KGRlfHByaW9yaXR5Xyk/cXVldWV8bGlzdHxzdGFja3woY29uc3RfKT9pdGVyYXRvcnwobXVsdGkpPyhzZXR8bWFwKXxiaXRzZXR8dT8oaW50fGZsb2F0KVxcZCopXFxiLztcblxuICAvLyB0b2tlbiBzdHlsZSBuYW1lcy4gIGNvcnJlc3BvbmQgdG8gY3NzIGNsYXNzZXNcbiAgLyoqXG4gICAqIHRva2VuIHN0eWxlIGZvciBhIHN0cmluZyBsaXRlcmFsXG4gICAqIEBjb25zdFxuICAgKi9cbiAgdmFyIFBSX1NUUklORyA9ICdzdHInO1xuICAvKipcbiAgICogdG9rZW4gc3R5bGUgZm9yIGEga2V5d29yZFxuICAgKiBAY29uc3RcbiAgICovXG4gIHZhciBQUl9LRVlXT1JEID0gJ2t3ZCc7XG4gIC8qKlxuICAgKiB0b2tlbiBzdHlsZSBmb3IgYSBjb21tZW50XG4gICAqIEBjb25zdFxuICAgKi9cbiAgdmFyIFBSX0NPTU1FTlQgPSAnY29tJztcbiAgLyoqXG4gICAqIHRva2VuIHN0eWxlIGZvciBhIHR5cGVcbiAgICogQGNvbnN0XG4gICAqL1xuICB2YXIgUFJfVFlQRSA9ICd0eXAnO1xuICAvKipcbiAgICogdG9rZW4gc3R5bGUgZm9yIGEgbGl0ZXJhbCB2YWx1ZS4gIGUuZy4gMSwgbnVsbCwgdHJ1ZS5cbiAgICogQGNvbnN0XG4gICAqL1xuICB2YXIgUFJfTElURVJBTCA9ICdsaXQnO1xuICAvKipcbiAgICogdG9rZW4gc3R5bGUgZm9yIGEgcHVuY3R1YXRpb24gc3RyaW5nLlxuICAgKiBAY29uc3RcbiAgICovXG4gIHZhciBQUl9QVU5DVFVBVElPTiA9ICdwdW4nO1xuICAvKipcbiAgICogdG9rZW4gc3R5bGUgZm9yIHBsYWluIHRleHQuXG4gICAqIEBjb25zdFxuICAgKi9cbiAgdmFyIFBSX1BMQUlOID0gJ3Bsbic7XG5cbiAgLyoqXG4gICAqIHRva2VuIHN0eWxlIGZvciBhbiBzZ21sIHRhZy5cbiAgICogQGNvbnN0XG4gICAqL1xuICB2YXIgUFJfVEFHID0gJ3RhZyc7XG4gIC8qKlxuICAgKiB0b2tlbiBzdHlsZSBmb3IgYSBtYXJrdXAgZGVjbGFyYXRpb24gc3VjaCBhcyBhIERPQ1RZUEUuXG4gICAqIEBjb25zdFxuICAgKi9cbiAgdmFyIFBSX0RFQ0xBUkFUSU9OID0gJ2RlYyc7XG4gIC8qKlxuICAgKiB0b2tlbiBzdHlsZSBmb3IgZW1iZWRkZWQgc291cmNlLlxuICAgKiBAY29uc3RcbiAgICovXG4gIHZhciBQUl9TT1VSQ0UgPSAnc3JjJztcbiAgLyoqXG4gICAqIHRva2VuIHN0eWxlIGZvciBhbiBzZ21sIGF0dHJpYnV0ZSBuYW1lLlxuICAgKiBAY29uc3RcbiAgICovXG4gIHZhciBQUl9BVFRSSUJfTkFNRSA9ICdhdG4nO1xuICAvKipcbiAgICogdG9rZW4gc3R5bGUgZm9yIGFuIHNnbWwgYXR0cmlidXRlIHZhbHVlLlxuICAgKiBAY29uc3RcbiAgICovXG4gIHZhciBQUl9BVFRSSUJfVkFMVUUgPSAnYXR2JztcblxuICAvKipcbiAgICogQSBjbGFzcyB0aGF0IGluZGljYXRlcyBhIHNlY3Rpb24gb2YgbWFya3VwIHRoYXQgaXMgbm90IGNvZGUsIGUuZy4gdG8gYWxsb3dcbiAgICogZW1iZWRkaW5nIG9mIGxpbmUgbnVtYmVycyB3aXRoaW4gY29kZSBsaXN0aW5ncy5cbiAgICogQGNvbnN0XG4gICAqL1xuICB2YXIgUFJfTk9DT0RFID0gJ25vY29kZSc7XG5cbiAgXG4gIFxuICAvKipcbiAgICogQSBzZXQgb2YgdG9rZW5zIHRoYXQgY2FuIHByZWNlZGUgYSByZWd1bGFyIGV4cHJlc3Npb24gbGl0ZXJhbCBpblxuICAgKiBqYXZhc2NyaXB0XG4gICAqIGh0dHA6Ly93ZWIuYXJjaGl2ZS5vcmcvd2ViLzIwMDcwNzE3MTQyNTE1L2h0dHA6Ly93d3cubW96aWxsYS5vcmcvanMvbGFuZ3VhZ2UvanMyMC9yYXRpb25hbGUvc3ludGF4Lmh0bWxcbiAgICogaGFzIHRoZSBmdWxsIGxpc3QsIGJ1dCBJJ3ZlIHJlbW92ZWQgb25lcyB0aGF0IG1pZ2h0IGJlIHByb2JsZW1hdGljIHdoZW5cbiAgICogc2VlbiBpbiBsYW5ndWFnZXMgdGhhdCBkb24ndCBzdXBwb3J0IHJlZ3VsYXIgZXhwcmVzc2lvbiBsaXRlcmFscy5cbiAgICpcbiAgICogPHA+U3BlY2lmaWNhbGx5LCBJJ3ZlIHJlbW92ZWQgYW55IGtleXdvcmRzIHRoYXQgY2FuJ3QgcHJlY2VkZSBhIHJlZ2V4cFxuICAgKiBsaXRlcmFsIGluIGEgc3ludGFjdGljYWxseSBsZWdhbCBqYXZhc2NyaXB0IHByb2dyYW0sIGFuZCBJJ3ZlIHJlbW92ZWQgdGhlXG4gICAqIFwiaW5cIiBrZXl3b3JkIHNpbmNlIGl0J3Mgbm90IGEga2V5d29yZCBpbiBtYW55IGxhbmd1YWdlcywgYW5kIG1pZ2h0IGJlIHVzZWRcbiAgICogYXMgYSBjb3VudCBvZiBpbmNoZXMuXG4gICAqXG4gICAqIDxwPlRoZSBsaW5rIGFib3ZlIGRvZXMgbm90IGFjY3VyYXRlbHkgZGVzY3JpYmUgRWNtYVNjcmlwdCBydWxlcyBzaW5jZVxuICAgKiBpdCBmYWlscyB0byBkaXN0aW5ndWlzaCBiZXR3ZWVuIChhPSsrL2IvaSkgYW5kIChhKysvYi9pKSBidXQgaXQgd29ya3NcbiAgICogdmVyeSB3ZWxsIGluIHByYWN0aWNlLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAY29uc3RcbiAgICovXG4gIHZhciBSRUdFWFBfUFJFQ0VERVJfUEFUVEVSTiA9ICcoPzpeXlxcXFwuP3xbKy1dfFshPV09Pz0/fFxcXFwjfCU9P3wmJj89P3xcXFxcKHxcXFxcKj0/fFsrXFxcXC1dPXwtPnxcXFxcLz0/fDo6P3w8PD89P3w+Pj8+Pz0/fCx8O3xcXFxcP3xAfFxcXFxbfH58e3xcXFxcXlxcXFxePz0/fFxcXFx8XFxcXHw/PT98YnJlYWt8Y2FzZXxjb250aW51ZXxkZWxldGV8ZG98ZWxzZXxmaW5hbGx5fGluc3RhbmNlb2Z8cmV0dXJufHRocm93fHRyeXx0eXBlb2YpXFxcXHMqJztcbiAgXG4gIC8vIENBVkVBVDogdGhpcyBkb2VzIG5vdCBwcm9wZXJseSBoYW5kbGUgdGhlIGNhc2Ugd2hlcmUgYSByZWd1bGFyXG4gIC8vIGV4cHJlc3Npb24gaW1tZWRpYXRlbHkgZm9sbG93cyBhbm90aGVyIHNpbmNlIGEgcmVndWxhciBleHByZXNzaW9uIG1heVxuICAvLyBoYXZlIGZsYWdzIGZvciBjYXNlLXNlbnNpdGl2aXR5IGFuZCB0aGUgbGlrZS4gIEhhdmluZyByZWdleHAgdG9rZW5zXG4gIC8vIGFkamFjZW50IGlzIG5vdCB2YWxpZCBpbiBhbnkgbGFuZ3VhZ2UgSSdtIGF3YXJlIG9mLCBzbyBJJ20gcHVudGluZy5cbiAgLy8gVE9ETzogbWF5YmUgc3R5bGUgc3BlY2lhbCBjaGFyYWN0ZXJzIGluc2lkZSBhIHJlZ2V4cCBhcyBwdW5jdHVhdGlvbi5cblxuICAvKipcbiAgICogR2l2ZW4gYSBncm91cCBvZiB7QGxpbmsgUmVnRXhwfXMsIHJldHVybnMgYSB7QGNvZGUgUmVnRXhwfSB0aGF0IGdsb2JhbGx5XG4gICAqIG1hdGNoZXMgdGhlIHVuaW9uIG9mIHRoZSBzZXRzIG9mIHN0cmluZ3MgbWF0Y2hlZCBieSB0aGUgaW5wdXQgUmVnRXhwLlxuICAgKiBTaW5jZSBpdCBtYXRjaGVzIGdsb2JhbGx5LCBpZiB0aGUgaW5wdXQgc3RyaW5ncyBoYXZlIGEgc3RhcnQtb2YtaW5wdXRcbiAgICogYW5jaG9yICgvXi4uLi8pLCBpdCBpcyBpZ25vcmVkIGZvciB0aGUgcHVycG9zZXMgb2YgdW5pb25pbmcuXG4gICAqIEBwYXJhbSB7QXJyYXkuPFJlZ0V4cD59IHJlZ2V4cyBub24gbXVsdGlsaW5lLCBub24tZ2xvYmFsIHJlZ2V4cy5cbiAgICogQHJldHVybiB7UmVnRXhwfSBhIGdsb2JhbCByZWdleC5cbiAgICovXG4gIGZ1bmN0aW9uIGNvbWJpbmVQcmVmaXhQYXR0ZXJucyhyZWdleHMpIHtcbiAgICB2YXIgY2FwdHVyZWRHcm91cEluZGV4ID0gMDtcbiAgXG4gICAgdmFyIG5lZWRUb0ZvbGRDYXNlID0gZmFsc2U7XG4gICAgdmFyIGlnbm9yZUNhc2UgPSBmYWxzZTtcbiAgICBmb3IgKHZhciBpID0gMCwgbiA9IHJlZ2V4cy5sZW5ndGg7IGkgPCBuOyArK2kpIHtcbiAgICAgIHZhciByZWdleCA9IHJlZ2V4c1tpXTtcbiAgICAgIGlmIChyZWdleC5pZ25vcmVDYXNlKSB7XG4gICAgICAgIGlnbm9yZUNhc2UgPSB0cnVlO1xuICAgICAgfSBlbHNlIGlmICgvW2Etel0vaS50ZXN0KHJlZ2V4LnNvdXJjZS5yZXBsYWNlKFxuICAgICAgICAgICAgICAgICAgICAgL1xcXFx1WzAtOWEtZl17NH18XFxcXHhbMC05YS1mXXsyfXxcXFxcW151eF0vZ2ksICcnKSkpIHtcbiAgICAgICAgbmVlZFRvRm9sZENhc2UgPSB0cnVlO1xuICAgICAgICBpZ25vcmVDYXNlID0gZmFsc2U7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cbiAgXG4gICAgdmFyIGVzY2FwZUNoYXJUb0NvZGVVbml0ID0ge1xuICAgICAgJ2InOiA4LFxuICAgICAgJ3QnOiA5LFxuICAgICAgJ24nOiAweGEsXG4gICAgICAndic6IDB4YixcbiAgICAgICdmJzogMHhjLFxuICAgICAgJ3InOiAweGRcbiAgICB9O1xuICBcbiAgICBmdW5jdGlvbiBkZWNvZGVFc2NhcGUoY2hhcnNldFBhcnQpIHtcbiAgICAgIHZhciBjYzAgPSBjaGFyc2V0UGFydC5jaGFyQ29kZUF0KDApO1xuICAgICAgaWYgKGNjMCAhPT0gOTIgLyogXFxcXCAqLykge1xuICAgICAgICByZXR1cm4gY2MwO1xuICAgICAgfVxuICAgICAgdmFyIGMxID0gY2hhcnNldFBhcnQuY2hhckF0KDEpO1xuICAgICAgY2MwID0gZXNjYXBlQ2hhclRvQ29kZVVuaXRbYzFdO1xuICAgICAgaWYgKGNjMCkge1xuICAgICAgICByZXR1cm4gY2MwO1xuICAgICAgfSBlbHNlIGlmICgnMCcgPD0gYzEgJiYgYzEgPD0gJzcnKSB7XG4gICAgICAgIHJldHVybiBwYXJzZUludChjaGFyc2V0UGFydC5zdWJzdHJpbmcoMSksIDgpO1xuICAgICAgfSBlbHNlIGlmIChjMSA9PT0gJ3UnIHx8IGMxID09PSAneCcpIHtcbiAgICAgICAgcmV0dXJuIHBhcnNlSW50KGNoYXJzZXRQYXJ0LnN1YnN0cmluZygyKSwgMTYpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIGNoYXJzZXRQYXJ0LmNoYXJDb2RlQXQoMSk7XG4gICAgICB9XG4gICAgfVxuICBcbiAgICBmdW5jdGlvbiBlbmNvZGVFc2NhcGUoY2hhckNvZGUpIHtcbiAgICAgIGlmIChjaGFyQ29kZSA8IDB4MjApIHtcbiAgICAgICAgcmV0dXJuIChjaGFyQ29kZSA8IDB4MTAgPyAnXFxcXHgwJyA6ICdcXFxceCcpICsgY2hhckNvZGUudG9TdHJpbmcoMTYpO1xuICAgICAgfVxuICAgICAgdmFyIGNoID0gU3RyaW5nLmZyb21DaGFyQ29kZShjaGFyQ29kZSk7XG4gICAgICByZXR1cm4gKGNoID09PSAnXFxcXCcgfHwgY2ggPT09ICctJyB8fCBjaCA9PT0gJ10nIHx8IGNoID09PSAnXicpXG4gICAgICAgICAgPyBcIlxcXFxcIiArIGNoIDogY2g7XG4gICAgfVxuICBcbiAgICBmdW5jdGlvbiBjYXNlRm9sZENoYXJzZXQoY2hhclNldCkge1xuICAgICAgdmFyIGNoYXJzZXRQYXJ0cyA9IGNoYXJTZXQuc3Vic3RyaW5nKDEsIGNoYXJTZXQubGVuZ3RoIC0gMSkubWF0Y2goXG4gICAgICAgICAgbmV3IFJlZ0V4cChcbiAgICAgICAgICAgICAgJ1xcXFxcXFxcdVswLTlBLUZhLWZdezR9J1xuICAgICAgICAgICAgICArICd8XFxcXFxcXFx4WzAtOUEtRmEtZl17Mn0nXG4gICAgICAgICAgICAgICsgJ3xcXFxcXFxcXFswLTNdWzAtN117MCwyfSdcbiAgICAgICAgICAgICAgKyAnfFxcXFxcXFxcWzAtN117MSwyfSdcbiAgICAgICAgICAgICAgKyAnfFxcXFxcXFxcW1xcXFxzXFxcXFNdJ1xuICAgICAgICAgICAgICArICd8LSdcbiAgICAgICAgICAgICAgKyAnfFteLVxcXFxcXFxcXScsXG4gICAgICAgICAgICAgICdnJykpO1xuICAgICAgdmFyIHJhbmdlcyA9IFtdO1xuICAgICAgdmFyIGludmVyc2UgPSBjaGFyc2V0UGFydHNbMF0gPT09ICdeJztcbiAgXG4gICAgICB2YXIgb3V0ID0gWydbJ107XG4gICAgICBpZiAoaW52ZXJzZSkgeyBvdXQucHVzaCgnXicpOyB9XG4gIFxuICAgICAgZm9yICh2YXIgaSA9IGludmVyc2UgPyAxIDogMCwgbiA9IGNoYXJzZXRQYXJ0cy5sZW5ndGg7IGkgPCBuOyArK2kpIHtcbiAgICAgICAgdmFyIHAgPSBjaGFyc2V0UGFydHNbaV07XG4gICAgICAgIGlmICgvXFxcXFtiZHN3XS9pLnRlc3QocCkpIHsgIC8vIERvbid0IG11Y2sgd2l0aCBuYW1lZCBncm91cHMuXG4gICAgICAgICAgb3V0LnB1c2gocCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdmFyIHN0YXJ0ID0gZGVjb2RlRXNjYXBlKHApO1xuICAgICAgICAgIHZhciBlbmQ7XG4gICAgICAgICAgaWYgKGkgKyAyIDwgbiAmJiAnLScgPT09IGNoYXJzZXRQYXJ0c1tpICsgMV0pIHtcbiAgICAgICAgICAgIGVuZCA9IGRlY29kZUVzY2FwZShjaGFyc2V0UGFydHNbaSArIDJdKTtcbiAgICAgICAgICAgIGkgKz0gMjtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZW5kID0gc3RhcnQ7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJhbmdlcy5wdXNoKFtzdGFydCwgZW5kXSk7XG4gICAgICAgICAgLy8gSWYgdGhlIHJhbmdlIG1pZ2h0IGludGVyc2VjdCBsZXR0ZXJzLCB0aGVuIGV4cGFuZCBpdC5cbiAgICAgICAgICAvLyBUaGlzIGNhc2UgaGFuZGxpbmcgaXMgdG9vIHNpbXBsaXN0aWMuXG4gICAgICAgICAgLy8gSXQgZG9lcyBub3QgZGVhbCB3aXRoIG5vbi1sYXRpbiBjYXNlIGZvbGRpbmcuXG4gICAgICAgICAgLy8gSXQgd29ya3MgZm9yIGxhdGluIHNvdXJjZSBjb2RlIGlkZW50aWZpZXJzIHRob3VnaC5cbiAgICAgICAgICBpZiAoIShlbmQgPCA2NSB8fCBzdGFydCA+IDEyMikpIHtcbiAgICAgICAgICAgIGlmICghKGVuZCA8IDY1IHx8IHN0YXJ0ID4gOTApKSB7XG4gICAgICAgICAgICAgIHJhbmdlcy5wdXNoKFtNYXRoLm1heCg2NSwgc3RhcnQpIHwgMzIsIE1hdGgubWluKGVuZCwgOTApIHwgMzJdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghKGVuZCA8IDk3IHx8IHN0YXJ0ID4gMTIyKSkge1xuICAgICAgICAgICAgICByYW5nZXMucHVzaChbTWF0aC5tYXgoOTcsIHN0YXJ0KSAmIH4zMiwgTWF0aC5taW4oZW5kLCAxMjIpICYgfjMyXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gIFxuICAgICAgLy8gW1sxLCAxMF0sIFszLCA0XSwgWzgsIDEyXSwgWzE0LCAxNF0sIFsxNiwgMTZdLCBbMTcsIDE3XV1cbiAgICAgIC8vIC0+IFtbMSwgMTJdLCBbMTQsIDE0XSwgWzE2LCAxN11dXG4gICAgICByYW5nZXMuc29ydChmdW5jdGlvbiAoYSwgYikgeyByZXR1cm4gKGFbMF0gLSBiWzBdKSB8fCAoYlsxXSAgLSBhWzFdKTsgfSk7XG4gICAgICB2YXIgY29uc29saWRhdGVkUmFuZ2VzID0gW107XG4gICAgICB2YXIgbGFzdFJhbmdlID0gW107XG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHJhbmdlcy5sZW5ndGg7ICsraSkge1xuICAgICAgICB2YXIgcmFuZ2UgPSByYW5nZXNbaV07XG4gICAgICAgIGlmIChyYW5nZVswXSA8PSBsYXN0UmFuZ2VbMV0gKyAxKSB7XG4gICAgICAgICAgbGFzdFJhbmdlWzFdID0gTWF0aC5tYXgobGFzdFJhbmdlWzFdLCByYW5nZVsxXSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY29uc29saWRhdGVkUmFuZ2VzLnB1c2gobGFzdFJhbmdlID0gcmFuZ2UpO1xuICAgICAgICB9XG4gICAgICB9XG4gIFxuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjb25zb2xpZGF0ZWRSYW5nZXMubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgdmFyIHJhbmdlID0gY29uc29saWRhdGVkUmFuZ2VzW2ldO1xuICAgICAgICBvdXQucHVzaChlbmNvZGVFc2NhcGUocmFuZ2VbMF0pKTtcbiAgICAgICAgaWYgKHJhbmdlWzFdID4gcmFuZ2VbMF0pIHtcbiAgICAgICAgICBpZiAocmFuZ2VbMV0gKyAxID4gcmFuZ2VbMF0pIHsgb3V0LnB1c2goJy0nKTsgfVxuICAgICAgICAgIG91dC5wdXNoKGVuY29kZUVzY2FwZShyYW5nZVsxXSkpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBvdXQucHVzaCgnXScpO1xuICAgICAgcmV0dXJuIG91dC5qb2luKCcnKTtcbiAgICB9XG4gIFxuICAgIGZ1bmN0aW9uIGFsbG93QW55d2hlcmVGb2xkQ2FzZUFuZFJlbnVtYmVyR3JvdXBzKHJlZ2V4KSB7XG4gICAgICAvLyBTcGxpdCBpbnRvIGNoYXJhY3RlciBzZXRzLCBlc2NhcGUgc2VxdWVuY2VzLCBwdW5jdHVhdGlvbiBzdHJpbmdzXG4gICAgICAvLyBsaWtlICgnKCcsICcoPzonLCAnKScsICdeJyksIGFuZCBydW5zIG9mIGNoYXJhY3RlcnMgdGhhdCBkbyBub3RcbiAgICAgIC8vIGluY2x1ZGUgYW55IG9mIHRoZSBhYm92ZS5cbiAgICAgIHZhciBwYXJ0cyA9IHJlZ2V4LnNvdXJjZS5tYXRjaChcbiAgICAgICAgICBuZXcgUmVnRXhwKFxuICAgICAgICAgICAgICAnKD86J1xuICAgICAgICAgICAgICArICdcXFxcWyg/OlteXFxcXHg1Q1xcXFx4NURdfFxcXFxcXFxcW1xcXFxzXFxcXFNdKSpcXFxcXScgIC8vIGEgY2hhcmFjdGVyIHNldFxuICAgICAgICAgICAgICArICd8XFxcXFxcXFx1W0EtRmEtZjAtOV17NH0nICAvLyBhIHVuaWNvZGUgZXNjYXBlXG4gICAgICAgICAgICAgICsgJ3xcXFxcXFxcXHhbQS1GYS1mMC05XXsyfScgIC8vIGEgaGV4IGVzY2FwZVxuICAgICAgICAgICAgICArICd8XFxcXFxcXFxbMC05XSsnICAvLyBhIGJhY2stcmVmZXJlbmNlIG9yIG9jdGFsIGVzY2FwZVxuICAgICAgICAgICAgICArICd8XFxcXFxcXFxbXnV4MC05XScgIC8vIG90aGVyIGVzY2FwZSBzZXF1ZW5jZVxuICAgICAgICAgICAgICArICd8XFxcXChcXFxcP1s6IT1dJyAgLy8gc3RhcnQgb2YgYSBub24tY2FwdHVyaW5nIGdyb3VwXG4gICAgICAgICAgICAgICsgJ3xbXFxcXChcXFxcKVxcXFxeXScgIC8vIHN0YXJ0L2VuZCBvZiBhIGdyb3VwLCBvciBsaW5lIHN0YXJ0XG4gICAgICAgICAgICAgICsgJ3xbXlxcXFx4NUJcXFxceDVDXFxcXChcXFxcKVxcXFxeXSsnICAvLyBydW4gb2Ygb3RoZXIgY2hhcmFjdGVyc1xuICAgICAgICAgICAgICArICcpJyxcbiAgICAgICAgICAgICAgJ2cnKSk7XG4gICAgICB2YXIgbiA9IHBhcnRzLmxlbmd0aDtcbiAgXG4gICAgICAvLyBNYXBzIGNhcHR1cmVkIGdyb3VwIG51bWJlcnMgdG8gdGhlIG51bWJlciB0aGV5IHdpbGwgb2NjdXB5IGluXG4gICAgICAvLyB0aGUgb3V0cHV0IG9yIHRvIC0xIGlmIHRoYXQgaGFzIG5vdCBiZWVuIGRldGVybWluZWQsIG9yIHRvXG4gICAgICAvLyB1bmRlZmluZWQgaWYgdGhleSBuZWVkIG5vdCBiZSBjYXB0dXJpbmcgaW4gdGhlIG91dHB1dC5cbiAgICAgIHZhciBjYXB0dXJlZEdyb3VwcyA9IFtdO1xuICBcbiAgICAgIC8vIFdhbGsgb3ZlciBhbmQgaWRlbnRpZnkgYmFjayByZWZlcmVuY2VzIHRvIGJ1aWxkIHRoZSBjYXB0dXJlZEdyb3Vwc1xuICAgICAgLy8gbWFwcGluZy5cbiAgICAgIGZvciAodmFyIGkgPSAwLCBncm91cEluZGV4ID0gMDsgaSA8IG47ICsraSkge1xuICAgICAgICB2YXIgcCA9IHBhcnRzW2ldO1xuICAgICAgICBpZiAocCA9PT0gJygnKSB7XG4gICAgICAgICAgLy8gZ3JvdXBzIGFyZSAxLWluZGV4ZWQsIHNvIG1heCBncm91cCBpbmRleCBpcyBjb3VudCBvZiAnKCdcbiAgICAgICAgICArK2dyb3VwSW5kZXg7XG4gICAgICAgIH0gZWxzZSBpZiAoJ1xcXFwnID09PSBwLmNoYXJBdCgwKSkge1xuICAgICAgICAgIHZhciBkZWNpbWFsVmFsdWUgPSArcC5zdWJzdHJpbmcoMSk7XG4gICAgICAgICAgaWYgKGRlY2ltYWxWYWx1ZSkge1xuICAgICAgICAgICAgaWYgKGRlY2ltYWxWYWx1ZSA8PSBncm91cEluZGV4KSB7XG4gICAgICAgICAgICAgIGNhcHR1cmVkR3JvdXBzW2RlY2ltYWxWYWx1ZV0gPSAtMTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIC8vIFJlcGxhY2Ugd2l0aCBhbiB1bmFtYmlndW91cyBlc2NhcGUgc2VxdWVuY2Ugc28gdGhhdFxuICAgICAgICAgICAgICAvLyBhbiBvY3RhbCBlc2NhcGUgc2VxdWVuY2UgZG9lcyBub3QgdHVybiBpbnRvIGEgYmFja3JlZmVyZW5jZVxuICAgICAgICAgICAgICAvLyB0byBhIGNhcHR1cmluZyBncm91cCBmcm9tIGFuIGVhcmxpZXIgcmVnZXguXG4gICAgICAgICAgICAgIHBhcnRzW2ldID0gZW5jb2RlRXNjYXBlKGRlY2ltYWxWYWx1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gIFxuICAgICAgLy8gUmVudW1iZXIgZ3JvdXBzIGFuZCByZWR1Y2UgY2FwdHVyaW5nIGdyb3VwcyB0byBub24tY2FwdHVyaW5nIGdyb3Vwc1xuICAgICAgLy8gd2hlcmUgcG9zc2libGUuXG4gICAgICBmb3IgKHZhciBpID0gMTsgaSA8IGNhcHR1cmVkR3JvdXBzLmxlbmd0aDsgKytpKSB7XG4gICAgICAgIGlmICgtMSA9PT0gY2FwdHVyZWRHcm91cHNbaV0pIHtcbiAgICAgICAgICBjYXB0dXJlZEdyb3Vwc1tpXSA9ICsrY2FwdHVyZWRHcm91cEluZGV4O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBmb3IgKHZhciBpID0gMCwgZ3JvdXBJbmRleCA9IDA7IGkgPCBuOyArK2kpIHtcbiAgICAgICAgdmFyIHAgPSBwYXJ0c1tpXTtcbiAgICAgICAgaWYgKHAgPT09ICcoJykge1xuICAgICAgICAgICsrZ3JvdXBJbmRleDtcbiAgICAgICAgICBpZiAoIWNhcHR1cmVkR3JvdXBzW2dyb3VwSW5kZXhdKSB7XG4gICAgICAgICAgICBwYXJ0c1tpXSA9ICcoPzonO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmICgnXFxcXCcgPT09IHAuY2hhckF0KDApKSB7XG4gICAgICAgICAgdmFyIGRlY2ltYWxWYWx1ZSA9ICtwLnN1YnN0cmluZygxKTtcbiAgICAgICAgICBpZiAoZGVjaW1hbFZhbHVlICYmIGRlY2ltYWxWYWx1ZSA8PSBncm91cEluZGV4KSB7XG4gICAgICAgICAgICBwYXJ0c1tpXSA9ICdcXFxcJyArIGNhcHR1cmVkR3JvdXBzW2RlY2ltYWxWYWx1ZV07XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gIFxuICAgICAgLy8gUmVtb3ZlIGFueSBwcmVmaXggYW5jaG9ycyBzbyB0aGF0IHRoZSBvdXRwdXQgd2lsbCBtYXRjaCBhbnl3aGVyZS5cbiAgICAgIC8vIF5eIHJlYWxseSBkb2VzIG1lYW4gYW4gYW5jaG9yZWQgbWF0Y2ggdGhvdWdoLlxuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBuOyArK2kpIHtcbiAgICAgICAgaWYgKCdeJyA9PT0gcGFydHNbaV0gJiYgJ14nICE9PSBwYXJ0c1tpICsgMV0pIHsgcGFydHNbaV0gPSAnJzsgfVxuICAgICAgfVxuICBcbiAgICAgIC8vIEV4cGFuZCBsZXR0ZXJzIHRvIGdyb3VwcyB0byBoYW5kbGUgbWl4aW5nIG9mIGNhc2Utc2Vuc2l0aXZlIGFuZFxuICAgICAgLy8gY2FzZS1pbnNlbnNpdGl2ZSBwYXR0ZXJucyBpZiBuZWNlc3NhcnkuXG4gICAgICBpZiAocmVnZXguaWdub3JlQ2FzZSAmJiBuZWVkVG9Gb2xkQ2FzZSkge1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG47ICsraSkge1xuICAgICAgICAgIHZhciBwID0gcGFydHNbaV07XG4gICAgICAgICAgdmFyIGNoMCA9IHAuY2hhckF0KDApO1xuICAgICAgICAgIGlmIChwLmxlbmd0aCA+PSAyICYmIGNoMCA9PT0gJ1snKSB7XG4gICAgICAgICAgICBwYXJ0c1tpXSA9IGNhc2VGb2xkQ2hhcnNldChwKTtcbiAgICAgICAgICB9IGVsc2UgaWYgKGNoMCAhPT0gJ1xcXFwnKSB7XG4gICAgICAgICAgICAvLyBUT0RPOiBoYW5kbGUgbGV0dGVycyBpbiBudW1lcmljIGVzY2FwZXMuXG4gICAgICAgICAgICBwYXJ0c1tpXSA9IHAucmVwbGFjZShcbiAgICAgICAgICAgICAgICAvW2EtekEtWl0vZyxcbiAgICAgICAgICAgICAgICBmdW5jdGlvbiAoY2gpIHtcbiAgICAgICAgICAgICAgICAgIHZhciBjYyA9IGNoLmNoYXJDb2RlQXQoMCk7XG4gICAgICAgICAgICAgICAgICByZXR1cm4gJ1snICsgU3RyaW5nLmZyb21DaGFyQ29kZShjYyAmIH4zMiwgY2MgfCAzMikgKyAnXSc7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gIFxuICAgICAgcmV0dXJuIHBhcnRzLmpvaW4oJycpO1xuICAgIH1cbiAgXG4gICAgdmFyIHJld3JpdHRlbiA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwLCBuID0gcmVnZXhzLmxlbmd0aDsgaSA8IG47ICsraSkge1xuICAgICAgdmFyIHJlZ2V4ID0gcmVnZXhzW2ldO1xuICAgICAgaWYgKHJlZ2V4Lmdsb2JhbCB8fCByZWdleC5tdWx0aWxpbmUpIHsgdGhyb3cgbmV3IEVycm9yKCcnICsgcmVnZXgpOyB9XG4gICAgICByZXdyaXR0ZW4ucHVzaChcbiAgICAgICAgICAnKD86JyArIGFsbG93QW55d2hlcmVGb2xkQ2FzZUFuZFJlbnVtYmVyR3JvdXBzKHJlZ2V4KSArICcpJyk7XG4gICAgfVxuICBcbiAgICByZXR1cm4gbmV3IFJlZ0V4cChyZXdyaXR0ZW4uam9pbignfCcpLCBpZ25vcmVDYXNlID8gJ2dpJyA6ICdnJyk7XG4gIH1cblxuICAvKipcbiAgICogU3BsaXQgbWFya3VwIGludG8gYSBzdHJpbmcgb2Ygc291cmNlIGNvZGUgYW5kIGFuIGFycmF5IG1hcHBpbmcgcmFuZ2VzIGluXG4gICAqIHRoYXQgc3RyaW5nIHRvIHRoZSB0ZXh0IG5vZGVzIGluIHdoaWNoIHRoZXkgYXBwZWFyLlxuICAgKlxuICAgKiA8cD5cbiAgICogVGhlIEhUTUwgRE9NIHN0cnVjdHVyZTo8L3A+XG4gICAqIDxwcmU+XG4gICAqIChFbGVtZW50ICAgXCJwXCJcbiAgICogICAoRWxlbWVudCBcImJcIlxuICAgKiAgICAgKFRleHQgIFwicHJpbnQgXCIpKSAgICAgICA7ICMxXG4gICAqICAgKFRleHQgICAgXCInSGVsbG8gJ1wiKSAgICAgIDsgIzJcbiAgICogICAoRWxlbWVudCBcImJyXCIpICAgICAgICAgICAgOyAjM1xuICAgKiAgIChUZXh0ICAgIFwiICArICdXb3JsZCc7XCIpKSA7ICM0XG4gICAqIDwvcHJlPlxuICAgKiA8cD5cbiAgICogY29ycmVzcG9uZHMgdG8gdGhlIEhUTUxcbiAgICoge0Bjb2RlIDxwPjxiPnByaW50IDwvYj4nSGVsbG8gJzxicj4gICsgJ1dvcmxkJzs8L3A+fS48L3A+XG4gICAqXG4gICAqIDxwPlxuICAgKiBJdCB3aWxsIHByb2R1Y2UgdGhlIG91dHB1dDo8L3A+XG4gICAqIDxwcmU+XG4gICAqIHtcbiAgICogICBzb3VyY2VDb2RlOiBcInByaW50ICdIZWxsbyAnXFxuICArICdXb3JsZCc7XCIsXG4gICAqICAgLy8gICAgICAgICAgICAgICAgICAgICAxICAgICAgICAgIDJcbiAgICogICAvLyAgICAgICAgICAgMDEyMzQ1Njc4OTAxMjM0IDU2Nzg5MDEyMzQ1NjdcbiAgICogICBzcGFuczogWzAsICMxLCA2LCAjMiwgMTQsICMzLCAxNSwgIzRdXG4gICAqIH1cbiAgICogPC9wcmU+XG4gICAqIDxwPlxuICAgKiB3aGVyZSAjMSBpcyBhIHJlZmVyZW5jZSB0byB0aGUge0Bjb2RlIFwicHJpbnQgXCJ9IHRleHQgbm9kZSBhYm92ZSwgYW5kIHNvXG4gICAqIG9uIGZvciB0aGUgb3RoZXIgdGV4dCBub2Rlcy5cbiAgICogPC9wPlxuICAgKlxuICAgKiA8cD5cbiAgICogVGhlIHtAY29kZX0gc3BhbnMgYXJyYXkgaXMgYW4gYXJyYXkgb2YgcGFpcnMuICBFdmVuIGVsZW1lbnRzIGFyZSB0aGUgc3RhcnRcbiAgICogaW5kaWNlcyBvZiBzdWJzdHJpbmdzLCBhbmQgb2RkIGVsZW1lbnRzIGFyZSB0aGUgdGV4dCBub2RlcyAob3IgQlIgZWxlbWVudHMpXG4gICAqIHRoYXQgY29udGFpbiB0aGUgdGV4dCBmb3IgdGhvc2Ugc3Vic3RyaW5ncy5cbiAgICogU3Vic3RyaW5ncyBjb250aW51ZSB1bnRpbCB0aGUgbmV4dCBpbmRleCBvciB0aGUgZW5kIG9mIHRoZSBzb3VyY2UuXG4gICAqIDwvcD5cbiAgICpcbiAgICogQHBhcmFtIHtOb2RlfSBub2RlIGFuIEhUTUwgRE9NIHN1YnRyZWUgY29udGFpbmluZyBzb3VyY2UtY29kZS5cbiAgICogQHBhcmFtIHtib29sZWFufSBpc1ByZWZvcm1hdHRlZCB0cnVlIGlmIHdoaXRlLXNwYWNlIGluIHRleHQgbm9kZXMgc2hvdWxkXG4gICAqICAgIGJlIGNvbnNpZGVyZWQgc2lnbmlmaWNhbnQuXG4gICAqIEByZXR1cm4ge09iamVjdH0gc291cmNlIGNvZGUgYW5kIHRoZSB0ZXh0IG5vZGVzIGluIHdoaWNoIHRoZXkgb2NjdXIuXG4gICAqL1xuICBmdW5jdGlvbiBleHRyYWN0U291cmNlU3BhbnMobm9kZSwgaXNQcmVmb3JtYXR0ZWQpIHtcbiAgICB2YXIgbm9jb2RlID0gLyg/Ol58XFxzKW5vY29kZSg/Olxcc3wkKS87XG4gIFxuICAgIHZhciBjaHVua3MgPSBbXTtcbiAgICB2YXIgbGVuZ3RoID0gMDtcbiAgICB2YXIgc3BhbnMgPSBbXTtcbiAgICB2YXIgayA9IDA7XG4gIFxuICAgIGZ1bmN0aW9uIHdhbGsobm9kZSkge1xuICAgICAgdmFyIHR5cGUgPSBub2RlLm5vZGVUeXBlO1xuICAgICAgaWYgKHR5cGUgPT0gMSkgeyAgLy8gRWxlbWVudFxuICAgICAgICBpZiAobm9jb2RlLnRlc3Qobm9kZS5jbGFzc05hbWUpKSB7IHJldHVybjsgfVxuICAgICAgICBmb3IgKHZhciBjaGlsZCA9IG5vZGUuZmlyc3RDaGlsZDsgY2hpbGQ7IGNoaWxkID0gY2hpbGQubmV4dFNpYmxpbmcpIHtcbiAgICAgICAgICB3YWxrKGNoaWxkKTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgbm9kZU5hbWUgPSBub2RlLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCk7XG4gICAgICAgIGlmICgnYnInID09PSBub2RlTmFtZSB8fCAnbGknID09PSBub2RlTmFtZSkge1xuICAgICAgICAgIGNodW5rc1trXSA9ICdcXG4nO1xuICAgICAgICAgIHNwYW5zW2sgPDwgMV0gPSBsZW5ndGgrKztcbiAgICAgICAgICBzcGFuc1soaysrIDw8IDEpIHwgMV0gPSBub2RlO1xuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKHR5cGUgPT0gMyB8fCB0eXBlID09IDQpIHsgIC8vIFRleHRcbiAgICAgICAgdmFyIHRleHQgPSBub2RlLm5vZGVWYWx1ZTtcbiAgICAgICAgaWYgKHRleHQubGVuZ3RoKSB7XG4gICAgICAgICAgaWYgKCFpc1ByZWZvcm1hdHRlZCkge1xuICAgICAgICAgICAgdGV4dCA9IHRleHQucmVwbGFjZSgvWyBcXHRcXHJcXG5dKy9nLCAnICcpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC9cXHJcXG4/L2csICdcXG4nKTsgIC8vIE5vcm1hbGl6ZSBuZXdsaW5lcy5cbiAgICAgICAgICB9XG4gICAgICAgICAgLy8gVE9ETzogaGFuZGxlIHRhYnMgaGVyZT9cbiAgICAgICAgICBjaHVua3Nba10gPSB0ZXh0O1xuICAgICAgICAgIHNwYW5zW2sgPDwgMV0gPSBsZW5ndGg7XG4gICAgICAgICAgbGVuZ3RoICs9IHRleHQubGVuZ3RoO1xuICAgICAgICAgIHNwYW5zWyhrKysgPDwgMSkgfCAxXSA9IG5vZGU7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIFxuICAgIHdhbGsobm9kZSk7XG4gIFxuICAgIHJldHVybiB7XG4gICAgICBzb3VyY2VDb2RlOiBjaHVua3Muam9pbignJykucmVwbGFjZSgvXFxuJC8sICcnKSxcbiAgICAgIHNwYW5zOiBzcGFuc1xuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogQXBwbHkgdGhlIGdpdmVuIGxhbmd1YWdlIGhhbmRsZXIgdG8gc291cmNlQ29kZSBhbmQgYWRkIHRoZSByZXN1bHRpbmdcbiAgICogZGVjb3JhdGlvbnMgdG8gb3V0LlxuICAgKiBAcGFyYW0ge251bWJlcn0gYmFzZVBvcyB0aGUgaW5kZXggb2Ygc291cmNlQ29kZSB3aXRoaW4gdGhlIGNodW5rIG9mIHNvdXJjZVxuICAgKiAgICB3aG9zZSBkZWNvcmF0aW9ucyBhcmUgYWxyZWFkeSBwcmVzZW50IG9uIG91dC5cbiAgICovXG4gIGZ1bmN0aW9uIGFwcGVuZERlY29yYXRpb25zKGJhc2VQb3MsIHNvdXJjZUNvZGUsIGxhbmdIYW5kbGVyLCBvdXQpIHtcbiAgICBpZiAoIXNvdXJjZUNvZGUpIHsgcmV0dXJuOyB9XG4gICAgdmFyIGpvYiA9IHtcbiAgICAgIHNvdXJjZUNvZGU6IHNvdXJjZUNvZGUsXG4gICAgICBiYXNlUG9zOiBiYXNlUG9zXG4gICAgfTtcbiAgICBsYW5nSGFuZGxlcihqb2IpO1xuICAgIG91dC5wdXNoLmFwcGx5KG91dCwgam9iLmRlY29yYXRpb25zKTtcbiAgfVxuXG4gIHZhciBub3RXcyA9IC9cXFMvO1xuXG4gIC8qKlxuICAgKiBHaXZlbiBhbiBlbGVtZW50LCBpZiBpdCBjb250YWlucyBvbmx5IG9uZSBjaGlsZCBlbGVtZW50IGFuZCBhbnkgdGV4dCBub2Rlc1xuICAgKiBpdCBjb250YWlucyBjb250YWluIG9ubHkgc3BhY2UgY2hhcmFjdGVycywgcmV0dXJuIHRoZSBzb2xlIGNoaWxkIGVsZW1lbnQuXG4gICAqIE90aGVyd2lzZSByZXR1cm5zIHVuZGVmaW5lZC5cbiAgICogPHA+XG4gICAqIFRoaXMgaXMgbWVhbnQgdG8gcmV0dXJuIHRoZSBDT0RFIGVsZW1lbnQgaW4ge0Bjb2RlIDxwcmU+PGNvZGUgLi4uPn0gd2hlblxuICAgKiB0aGVyZSBpcyBhIHNpbmdsZSBjaGlsZCBlbGVtZW50IHRoYXQgY29udGFpbnMgYWxsIHRoZSBub24tc3BhY2UgdGV4dHVhbFxuICAgKiBjb250ZW50LCBidXQgbm90IHRvIHJldHVybiBhbnl0aGluZyB3aGVyZSB0aGVyZSBhcmUgbXVsdGlwbGUgY2hpbGQgZWxlbWVudHNcbiAgICogYXMgaW4ge0Bjb2RlIDxwcmU+PGNvZGU+Li4uPC9jb2RlPjxjb2RlPi4uLjwvY29kZT48L3ByZT59IG9yIHdoZW4gdGhlcmVcbiAgICogaXMgdGV4dHVhbCBjb250ZW50LlxuICAgKi9cbiAgZnVuY3Rpb24gY2hpbGRDb250ZW50V3JhcHBlcihlbGVtZW50KSB7XG4gICAgdmFyIHdyYXBwZXIgPSB1bmRlZmluZWQ7XG4gICAgZm9yICh2YXIgYyA9IGVsZW1lbnQuZmlyc3RDaGlsZDsgYzsgYyA9IGMubmV4dFNpYmxpbmcpIHtcbiAgICAgIHZhciB0eXBlID0gYy5ub2RlVHlwZTtcbiAgICAgIHdyYXBwZXIgPSAodHlwZSA9PT0gMSkgIC8vIEVsZW1lbnQgTm9kZVxuICAgICAgICAgID8gKHdyYXBwZXIgPyBlbGVtZW50IDogYylcbiAgICAgICAgICA6ICh0eXBlID09PSAzKSAgLy8gVGV4dCBOb2RlXG4gICAgICAgICAgPyAobm90V3MudGVzdChjLm5vZGVWYWx1ZSkgPyBlbGVtZW50IDogd3JhcHBlcilcbiAgICAgICAgICA6IHdyYXBwZXI7XG4gICAgfVxuICAgIHJldHVybiB3cmFwcGVyID09PSBlbGVtZW50ID8gdW5kZWZpbmVkIDogd3JhcHBlcjtcbiAgfVxuXG4gIC8qKiBHaXZlbiB0cmlwbGVzIG9mIFtzdHlsZSwgcGF0dGVybiwgY29udGV4dF0gcmV0dXJucyBhIGxleGluZyBmdW5jdGlvbixcbiAgICAqIFRoZSBsZXhpbmcgZnVuY3Rpb24gaW50ZXJwcmV0cyB0aGUgcGF0dGVybnMgdG8gZmluZCB0b2tlbiBib3VuZGFyaWVzIGFuZFxuICAgICogcmV0dXJucyBhIGRlY29yYXRpb24gbGlzdCBvZiB0aGUgZm9ybVxuICAgICogW2luZGV4XzAsIHN0eWxlXzAsIGluZGV4XzEsIHN0eWxlXzEsIC4uLiwgaW5kZXhfbiwgc3R5bGVfbl1cbiAgICAqIHdoZXJlIGluZGV4X24gaXMgYW4gaW5kZXggaW50byB0aGUgc291cmNlQ29kZSwgYW5kIHN0eWxlX24gaXMgYSBzdHlsZVxuICAgICogY29uc3RhbnQgbGlrZSBQUl9QTEFJTi4gIGluZGV4X24tMSA8PSBpbmRleF9uLCBhbmQgc3R5bGVfbi0xIGFwcGxpZXMgdG9cbiAgICAqIGFsbCBjaGFyYWN0ZXJzIGluIHNvdXJjZUNvZGVbaW5kZXhfbi0xOmluZGV4X25dLlxuICAgICpcbiAgICAqIFRoZSBzdHlsZVBhdHRlcm5zIGlzIGEgbGlzdCB3aG9zZSBlbGVtZW50cyBoYXZlIHRoZSBmb3JtXG4gICAgKiBbc3R5bGUgOiBzdHJpbmcsIHBhdHRlcm4gOiBSZWdFeHAsIERFUFJFQ0FURUQsIHNob3J0Y3V0IDogc3RyaW5nXS5cbiAgICAqXG4gICAgKiBTdHlsZSBpcyBhIHN0eWxlIGNvbnN0YW50IGxpa2UgUFJfUExBSU4sIG9yIGNhbiBiZSBhIHN0cmluZyBvZiB0aGVcbiAgICAqIGZvcm0gJ2xhbmctRk9PJywgd2hlcmUgRk9PIGlzIGEgbGFuZ3VhZ2UgZXh0ZW5zaW9uIGRlc2NyaWJpbmcgdGhlXG4gICAgKiBsYW5ndWFnZSBvZiB0aGUgcG9ydGlvbiBvZiB0aGUgdG9rZW4gaW4gJDEgYWZ0ZXIgcGF0dGVybiBleGVjdXRlcy5cbiAgICAqIEUuZy4sIGlmIHN0eWxlIGlzICdsYW5nLWxpc3AnLCBhbmQgZ3JvdXAgMSBjb250YWlucyB0aGUgdGV4dFxuICAgICogJyhoZWxsbyAod29ybGQpKScsIHRoZW4gdGhhdCBwb3J0aW9uIG9mIHRoZSB0b2tlbiB3aWxsIGJlIHBhc3NlZCB0byB0aGVcbiAgICAqIHJlZ2lzdGVyZWQgbGlzcCBoYW5kbGVyIGZvciBmb3JtYXR0aW5nLlxuICAgICogVGhlIHRleHQgYmVmb3JlIGFuZCBhZnRlciBncm91cCAxIHdpbGwgYmUgcmVzdHlsZWQgdXNpbmcgdGhpcyBkZWNvcmF0b3JcbiAgICAqIHNvIGRlY29yYXRvcnMgc2hvdWxkIHRha2UgY2FyZSB0aGF0IHRoaXMgZG9lc24ndCByZXN1bHQgaW4gaW5maW5pdGVcbiAgICAqIHJlY3Vyc2lvbi4gIEZvciBleGFtcGxlLCB0aGUgSFRNTCBsZXhlciBydWxlIGZvciBTQ1JJUFQgZWxlbWVudHMgbG9va3NcbiAgICAqIHNvbWV0aGluZyBsaWtlIFsnbGFuZy1qcycsIC88W3NdY3JpcHQ+KC4rPyk8XFwvc2NyaXB0Pi9dLiAgVGhpcyBtYXkgbWF0Y2hcbiAgICAqICc8c2NyaXB0PmZvbygpPFxcL3NjcmlwdD4nLCB3aGljaCB3b3VsZCBjYXVzZSB0aGUgY3VycmVudCBkZWNvcmF0b3IgdG9cbiAgICAqIGJlIGNhbGxlZCB3aXRoICc8c2NyaXB0Picgd2hpY2ggd291bGQgbm90IG1hdGNoIHRoZSBzYW1lIHJ1bGUgc2luY2VcbiAgICAqIGdyb3VwIDEgbXVzdCBub3QgYmUgZW1wdHksIHNvIGl0IHdvdWxkIGJlIGluc3RlYWQgc3R5bGVkIGFzIFBSX1RBRyBieVxuICAgICogdGhlIGdlbmVyaWMgdGFnIHJ1bGUuICBUaGUgaGFuZGxlciByZWdpc3RlcmVkIGZvciB0aGUgJ2pzJyBleHRlbnNpb24gd291bGRcbiAgICAqIHRoZW4gYmUgY2FsbGVkIHdpdGggJ2ZvbygpJywgYW5kIGZpbmFsbHksIHRoZSBjdXJyZW50IGRlY29yYXRvciB3b3VsZFxuICAgICogYmUgY2FsbGVkIHdpdGggJzxcXC9zY3JpcHQ+JyB3aGljaCB3b3VsZCBub3QgbWF0Y2ggdGhlIG9yaWdpbmFsIHJ1bGUgYW5kXG4gICAgKiBzbyB0aGUgZ2VuZXJpYyB0YWcgcnVsZSB3b3VsZCBpZGVudGlmeSBpdCBhcyBhIHRhZy5cbiAgICAqXG4gICAgKiBQYXR0ZXJuIG11c3Qgb25seSBtYXRjaCBwcmVmaXhlcywgYW5kIGlmIGl0IG1hdGNoZXMgYSBwcmVmaXgsIHRoZW4gdGhhdFxuICAgICogbWF0Y2ggaXMgY29uc2lkZXJlZCBhIHRva2VuIHdpdGggdGhlIHNhbWUgc3R5bGUuXG4gICAgKlxuICAgICogQ29udGV4dCBpcyBhcHBsaWVkIHRvIHRoZSBsYXN0IG5vbi13aGl0ZXNwYWNlLCBub24tY29tbWVudCB0b2tlblxuICAgICogcmVjb2duaXplZC5cbiAgICAqXG4gICAgKiBTaG9ydGN1dCBpcyBhbiBvcHRpb25hbCBzdHJpbmcgb2YgY2hhcmFjdGVycywgYW55IG9mIHdoaWNoLCBpZiB0aGUgZmlyc3RcbiAgICAqIGNoYXJhY3RlciwgZ3VyYW50ZWUgdGhhdCB0aGlzIHBhdHRlcm4gYW5kIG9ubHkgdGhpcyBwYXR0ZXJuIG1hdGNoZXMuXG4gICAgKlxuICAgICogQHBhcmFtIHtBcnJheX0gc2hvcnRjdXRTdHlsZVBhdHRlcm5zIHBhdHRlcm5zIHRoYXQgYWx3YXlzIHN0YXJ0IHdpdGhcbiAgICAqICAgYSBrbm93biBjaGFyYWN0ZXIuICBNdXN0IGhhdmUgYSBzaG9ydGN1dCBzdHJpbmcuXG4gICAgKiBAcGFyYW0ge0FycmF5fSBmYWxsdGhyb3VnaFN0eWxlUGF0dGVybnMgcGF0dGVybnMgdGhhdCB3aWxsIGJlIHRyaWVkIGluXG4gICAgKiAgIG9yZGVyIGlmIHRoZSBzaG9ydGN1dCBvbmVzIGZhaWwuICBNYXkgaGF2ZSBzaG9ydGN1dHMuXG4gICAgKlxuICAgICogQHJldHVybiB7ZnVuY3Rpb24gKE9iamVjdCl9IGFcbiAgICAqICAgZnVuY3Rpb24gdGhhdCB0YWtlcyBzb3VyY2UgY29kZSBhbmQgcmV0dXJucyBhIGxpc3Qgb2YgZGVjb3JhdGlvbnMuXG4gICAgKi9cbiAgZnVuY3Rpb24gY3JlYXRlU2ltcGxlTGV4ZXIoc2hvcnRjdXRTdHlsZVBhdHRlcm5zLCBmYWxsdGhyb3VnaFN0eWxlUGF0dGVybnMpIHtcbiAgICB2YXIgc2hvcnRjdXRzID0ge307XG4gICAgdmFyIHRva2VuaXplcjtcbiAgICAoZnVuY3Rpb24gKCkge1xuICAgICAgdmFyIGFsbFBhdHRlcm5zID0gc2hvcnRjdXRTdHlsZVBhdHRlcm5zLmNvbmNhdChmYWxsdGhyb3VnaFN0eWxlUGF0dGVybnMpO1xuICAgICAgdmFyIGFsbFJlZ2V4cyA9IFtdO1xuICAgICAgdmFyIHJlZ2V4S2V5cyA9IHt9O1xuICAgICAgZm9yICh2YXIgaSA9IDAsIG4gPSBhbGxQYXR0ZXJucy5sZW5ndGg7IGkgPCBuOyArK2kpIHtcbiAgICAgICAgdmFyIHBhdHRlcm5QYXJ0cyA9IGFsbFBhdHRlcm5zW2ldO1xuICAgICAgICB2YXIgc2hvcnRjdXRDaGFycyA9IHBhdHRlcm5QYXJ0c1szXTtcbiAgICAgICAgaWYgKHNob3J0Y3V0Q2hhcnMpIHtcbiAgICAgICAgICBmb3IgKHZhciBjID0gc2hvcnRjdXRDaGFycy5sZW5ndGg7IC0tYyA+PSAwOykge1xuICAgICAgICAgICAgc2hvcnRjdXRzW3Nob3J0Y3V0Q2hhcnMuY2hhckF0KGMpXSA9IHBhdHRlcm5QYXJ0cztcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHJlZ2V4ID0gcGF0dGVyblBhcnRzWzFdO1xuICAgICAgICB2YXIgayA9ICcnICsgcmVnZXg7XG4gICAgICAgIGlmICghcmVnZXhLZXlzLmhhc093blByb3BlcnR5KGspKSB7XG4gICAgICAgICAgYWxsUmVnZXhzLnB1c2gocmVnZXgpO1xuICAgICAgICAgIHJlZ2V4S2V5c1trXSA9IG51bGw7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGFsbFJlZ2V4cy5wdXNoKC9bXFwwLVxcdWZmZmZdLyk7XG4gICAgICB0b2tlbml6ZXIgPSBjb21iaW5lUHJlZml4UGF0dGVybnMoYWxsUmVnZXhzKTtcbiAgICB9KSgpO1xuXG4gICAgdmFyIG5QYXR0ZXJucyA9IGZhbGx0aHJvdWdoU3R5bGVQYXR0ZXJucy5sZW5ndGg7XG5cbiAgICAvKipcbiAgICAgKiBMZXhlcyBqb2Iuc291cmNlQ29kZSBhbmQgcHJvZHVjZXMgYW4gb3V0cHV0IGFycmF5IGpvYi5kZWNvcmF0aW9ucyBvZlxuICAgICAqIHN0eWxlIGNsYXNzZXMgcHJlY2VkZWQgYnkgdGhlIHBvc2l0aW9uIGF0IHdoaWNoIHRoZXkgc3RhcnQgaW5cbiAgICAgKiBqb2Iuc291cmNlQ29kZSBpbiBvcmRlci5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBqb2IgYW4gb2JqZWN0IGxpa2UgPHByZT57XG4gICAgICogICAgc291cmNlQ29kZToge3N0cmluZ30gc291cmNlVGV4dCBwbGFpbiB0ZXh0LFxuICAgICAqICAgIGJhc2VQb3M6IHtpbnR9IHBvc2l0aW9uIG9mIGpvYi5zb3VyY2VDb2RlIGluIHRoZSBsYXJnZXIgY2h1bmsgb2ZcbiAgICAgKiAgICAgICAgc291cmNlQ29kZS5cbiAgICAgKiB9PC9wcmU+XG4gICAgICovXG4gICAgdmFyIGRlY29yYXRlID0gZnVuY3Rpb24gKGpvYikge1xuICAgICAgdmFyIHNvdXJjZUNvZGUgPSBqb2Iuc291cmNlQ29kZSwgYmFzZVBvcyA9IGpvYi5iYXNlUG9zO1xuICAgICAgLyoqIEV2ZW4gZW50cmllcyBhcmUgcG9zaXRpb25zIGluIHNvdXJjZSBpbiBhc2NlbmRpbmcgb3JkZXIuICBPZGQgZW50aWVzXG4gICAgICAgICogYXJlIHN0eWxlIG1hcmtlcnMgKGUuZy4sIFBSX0NPTU1FTlQpIHRoYXQgcnVuIGZyb20gdGhhdCBwb3NpdGlvbiB1bnRpbFxuICAgICAgICAqIHRoZSBlbmQuXG4gICAgICAgICogQHR5cGUge0FycmF5LjxudW1iZXJ8c3RyaW5nPn1cbiAgICAgICAgKi9cbiAgICAgIHZhciBkZWNvcmF0aW9ucyA9IFtiYXNlUG9zLCBQUl9QTEFJTl07XG4gICAgICB2YXIgcG9zID0gMDsgIC8vIGluZGV4IGludG8gc291cmNlQ29kZVxuICAgICAgdmFyIHRva2VucyA9IHNvdXJjZUNvZGUubWF0Y2godG9rZW5pemVyKSB8fCBbXTtcbiAgICAgIHZhciBzdHlsZUNhY2hlID0ge307XG5cbiAgICAgIGZvciAodmFyIHRpID0gMCwgblRva2VucyA9IHRva2Vucy5sZW5ndGg7IHRpIDwgblRva2VuczsgKyt0aSkge1xuICAgICAgICB2YXIgdG9rZW4gPSB0b2tlbnNbdGldO1xuICAgICAgICB2YXIgc3R5bGUgPSBzdHlsZUNhY2hlW3Rva2VuXTtcbiAgICAgICAgdmFyIG1hdGNoID0gdm9pZCAwO1xuXG4gICAgICAgIHZhciBpc0VtYmVkZGVkO1xuICAgICAgICBpZiAodHlwZW9mIHN0eWxlID09PSAnc3RyaW5nJykge1xuICAgICAgICAgIGlzRW1iZWRkZWQgPSBmYWxzZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB2YXIgcGF0dGVyblBhcnRzID0gc2hvcnRjdXRzW3Rva2VuLmNoYXJBdCgwKV07XG4gICAgICAgICAgaWYgKHBhdHRlcm5QYXJ0cykge1xuICAgICAgICAgICAgbWF0Y2ggPSB0b2tlbi5tYXRjaChwYXR0ZXJuUGFydHNbMV0pO1xuICAgICAgICAgICAgc3R5bGUgPSBwYXR0ZXJuUGFydHNbMF07XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgblBhdHRlcm5zOyArK2kpIHtcbiAgICAgICAgICAgICAgcGF0dGVyblBhcnRzID0gZmFsbHRocm91Z2hTdHlsZVBhdHRlcm5zW2ldO1xuICAgICAgICAgICAgICBtYXRjaCA9IHRva2VuLm1hdGNoKHBhdHRlcm5QYXJ0c1sxXSk7XG4gICAgICAgICAgICAgIGlmIChtYXRjaCkge1xuICAgICAgICAgICAgICAgIHN0eWxlID0gcGF0dGVyblBhcnRzWzBdO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICghbWF0Y2gpIHsgIC8vIG1ha2Ugc3VyZSB0aGF0IHdlIG1ha2UgcHJvZ3Jlc3NcbiAgICAgICAgICAgICAgc3R5bGUgPSBQUl9QTEFJTjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpc0VtYmVkZGVkID0gc3R5bGUubGVuZ3RoID49IDUgJiYgJ2xhbmctJyA9PT0gc3R5bGUuc3Vic3RyaW5nKDAsIDUpO1xuICAgICAgICAgIGlmIChpc0VtYmVkZGVkICYmICEobWF0Y2ggJiYgdHlwZW9mIG1hdGNoWzFdID09PSAnc3RyaW5nJykpIHtcbiAgICAgICAgICAgIGlzRW1iZWRkZWQgPSBmYWxzZTtcbiAgICAgICAgICAgIHN0eWxlID0gUFJfU09VUkNFO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmICghaXNFbWJlZGRlZCkgeyBzdHlsZUNhY2hlW3Rva2VuXSA9IHN0eWxlOyB9XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgdG9rZW5TdGFydCA9IHBvcztcbiAgICAgICAgcG9zICs9IHRva2VuLmxlbmd0aDtcblxuICAgICAgICBpZiAoIWlzRW1iZWRkZWQpIHtcbiAgICAgICAgICBkZWNvcmF0aW9ucy5wdXNoKGJhc2VQb3MgKyB0b2tlblN0YXJ0LCBzdHlsZSk7XG4gICAgICAgIH0gZWxzZSB7ICAvLyBUcmVhdCBncm91cCAxIGFzIGFuIGVtYmVkZGVkIGJsb2NrIG9mIHNvdXJjZSBjb2RlLlxuICAgICAgICAgIHZhciBlbWJlZGRlZFNvdXJjZSA9IG1hdGNoWzFdO1xuICAgICAgICAgIHZhciBlbWJlZGRlZFNvdXJjZVN0YXJ0ID0gdG9rZW4uaW5kZXhPZihlbWJlZGRlZFNvdXJjZSk7XG4gICAgICAgICAgdmFyIGVtYmVkZGVkU291cmNlRW5kID0gZW1iZWRkZWRTb3VyY2VTdGFydCArIGVtYmVkZGVkU291cmNlLmxlbmd0aDtcbiAgICAgICAgICBpZiAobWF0Y2hbMl0pIHtcbiAgICAgICAgICAgIC8vIElmIGVtYmVkZGVkU291cmNlIGNhbiBiZSBibGFuaywgdGhlbiBpdCB3b3VsZCBtYXRjaCBhdCB0aGVcbiAgICAgICAgICAgIC8vIGJlZ2lubmluZyB3aGljaCB3b3VsZCBjYXVzZSB1cyB0byBpbmZpbml0ZWx5IHJlY3Vyc2Ugb24gdGhlXG4gICAgICAgICAgICAvLyBlbnRpcmUgdG9rZW4sIHNvIHdlIGNhdGNoIHRoZSByaWdodCBjb250ZXh0IGluIG1hdGNoWzJdLlxuICAgICAgICAgICAgZW1iZWRkZWRTb3VyY2VFbmQgPSB0b2tlbi5sZW5ndGggLSBtYXRjaFsyXS5sZW5ndGg7XG4gICAgICAgICAgICBlbWJlZGRlZFNvdXJjZVN0YXJ0ID0gZW1iZWRkZWRTb3VyY2VFbmQgLSBlbWJlZGRlZFNvdXJjZS5sZW5ndGg7XG4gICAgICAgICAgfVxuICAgICAgICAgIHZhciBsYW5nID0gc3R5bGUuc3Vic3RyaW5nKDUpO1xuICAgICAgICAgIC8vIERlY29yYXRlIHRoZSBsZWZ0IG9mIHRoZSBlbWJlZGRlZCBzb3VyY2VcbiAgICAgICAgICBhcHBlbmREZWNvcmF0aW9ucyhcbiAgICAgICAgICAgICAgYmFzZVBvcyArIHRva2VuU3RhcnQsXG4gICAgICAgICAgICAgIHRva2VuLnN1YnN0cmluZygwLCBlbWJlZGRlZFNvdXJjZVN0YXJ0KSxcbiAgICAgICAgICAgICAgZGVjb3JhdGUsIGRlY29yYXRpb25zKTtcbiAgICAgICAgICAvLyBEZWNvcmF0ZSB0aGUgZW1iZWRkZWQgc291cmNlXG4gICAgICAgICAgYXBwZW5kRGVjb3JhdGlvbnMoXG4gICAgICAgICAgICAgIGJhc2VQb3MgKyB0b2tlblN0YXJ0ICsgZW1iZWRkZWRTb3VyY2VTdGFydCxcbiAgICAgICAgICAgICAgZW1iZWRkZWRTb3VyY2UsXG4gICAgICAgICAgICAgIGxhbmdIYW5kbGVyRm9yRXh0ZW5zaW9uKGxhbmcsIGVtYmVkZGVkU291cmNlKSxcbiAgICAgICAgICAgICAgZGVjb3JhdGlvbnMpO1xuICAgICAgICAgIC8vIERlY29yYXRlIHRoZSByaWdodCBvZiB0aGUgZW1iZWRkZWQgc2VjdGlvblxuICAgICAgICAgIGFwcGVuZERlY29yYXRpb25zKFxuICAgICAgICAgICAgICBiYXNlUG9zICsgdG9rZW5TdGFydCArIGVtYmVkZGVkU291cmNlRW5kLFxuICAgICAgICAgICAgICB0b2tlbi5zdWJzdHJpbmcoZW1iZWRkZWRTb3VyY2VFbmQpLFxuICAgICAgICAgICAgICBkZWNvcmF0ZSwgZGVjb3JhdGlvbnMpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBqb2IuZGVjb3JhdGlvbnMgPSBkZWNvcmF0aW9ucztcbiAgICB9O1xuICAgIHJldHVybiBkZWNvcmF0ZTtcbiAgfVxuXG4gIC8qKiByZXR1cm5zIGEgZnVuY3Rpb24gdGhhdCBwcm9kdWNlcyBhIGxpc3Qgb2YgZGVjb3JhdGlvbnMgZnJvbSBzb3VyY2UgdGV4dC5cbiAgICAqXG4gICAgKiBUaGlzIGNvZGUgdHJlYXRzIFwiLCAnLCBhbmQgYCBhcyBzdHJpbmcgZGVsaW1pdGVycywgYW5kIFxcIGFzIGEgc3RyaW5nXG4gICAgKiBlc2NhcGUuICBJdCBkb2VzIG5vdCByZWNvZ25pemUgcGVybCdzIHFxKCkgc3R5bGUgc3RyaW5ncy5cbiAgICAqIEl0IGhhcyBubyBzcGVjaWFsIGhhbmRsaW5nIGZvciBkb3VibGUgZGVsaW1pdGVyIGVzY2FwZXMgYXMgaW4gYmFzaWMsIG9yXG4gICAgKiB0aGUgdHJpcGxlZCBkZWxpbWl0ZXJzIHVzZWQgaW4gcHl0aG9uLCBidXQgc2hvdWxkIHdvcmsgb24gdGhvc2UgcmVnYXJkbGVzc1xuICAgICogYWx0aG91Z2ggaW4gdGhvc2UgY2FzZXMgYSBzaW5nbGUgc3RyaW5nIGxpdGVyYWwgbWF5IGJlIGJyb2tlbiB1cCBpbnRvXG4gICAgKiBtdWx0aXBsZSBhZGphY2VudCBzdHJpbmcgbGl0ZXJhbHMuXG4gICAgKlxuICAgICogSXQgcmVjb2duaXplcyBDLCBDKyssIGFuZCBzaGVsbCBzdHlsZSBjb21tZW50cy5cbiAgICAqXG4gICAgKiBAcGFyYW0ge09iamVjdH0gb3B0aW9ucyBhIHNldCBvZiBvcHRpb25hbCBwYXJhbWV0ZXJzLlxuICAgICogQHJldHVybiB7ZnVuY3Rpb24gKE9iamVjdCl9IGEgZnVuY3Rpb24gdGhhdCBleGFtaW5lcyB0aGUgc291cmNlIGNvZGVcbiAgICAqICAgICBpbiB0aGUgaW5wdXQgam9iIGFuZCBidWlsZHMgdGhlIGRlY29yYXRpb24gbGlzdC5cbiAgICAqL1xuICBmdW5jdGlvbiBzb3VyY2VEZWNvcmF0b3Iob3B0aW9ucykge1xuICAgIHZhciBzaG9ydGN1dFN0eWxlUGF0dGVybnMgPSBbXSwgZmFsbHRocm91Z2hTdHlsZVBhdHRlcm5zID0gW107XG4gICAgaWYgKG9wdGlvbnNbJ3RyaXBsZVF1b3RlZFN0cmluZ3MnXSkge1xuICAgICAgLy8gJycnbXVsdGktbGluZS1zdHJpbmcnJycsICdzaW5nbGUtbGluZS1zdHJpbmcnLCBhbmQgZG91YmxlLXF1b3RlZFxuICAgICAgc2hvcnRjdXRTdHlsZVBhdHRlcm5zLnB1c2goXG4gICAgICAgICAgW1BSX1NUUklORywgIC9eKD86XFwnXFwnXFwnKD86W15cXCdcXFxcXXxcXFxcW1xcc1xcU118XFwnezEsMn0oPz1bXlxcJ10pKSooPzpcXCdcXCdcXCd8JCl8XFxcIlxcXCJcXFwiKD86W15cXFwiXFxcXF18XFxcXFtcXHNcXFNdfFxcXCJ7MSwyfSg/PVteXFxcIl0pKSooPzpcXFwiXFxcIlxcXCJ8JCl8XFwnKD86W15cXFxcXFwnXXxcXFxcW1xcc1xcU10pKig/OlxcJ3wkKXxcXFwiKD86W15cXFxcXFxcIl18XFxcXFtcXHNcXFNdKSooPzpcXFwifCQpKS8sXG4gICAgICAgICAgIG51bGwsICdcXCdcIiddKTtcbiAgICB9IGVsc2UgaWYgKG9wdGlvbnNbJ211bHRpTGluZVN0cmluZ3MnXSkge1xuICAgICAgLy8gJ211bHRpLWxpbmUtc3RyaW5nJywgXCJtdWx0aS1saW5lLXN0cmluZ1wiXG4gICAgICBzaG9ydGN1dFN0eWxlUGF0dGVybnMucHVzaChcbiAgICAgICAgICBbUFJfU1RSSU5HLCAgL14oPzpcXCcoPzpbXlxcXFxcXCddfFxcXFxbXFxzXFxTXSkqKD86XFwnfCQpfFxcXCIoPzpbXlxcXFxcXFwiXXxcXFxcW1xcc1xcU10pKig/OlxcXCJ8JCl8XFxgKD86W15cXFxcXFxgXXxcXFxcW1xcc1xcU10pKig/OlxcYHwkKSkvLFxuICAgICAgICAgICBudWxsLCAnXFwnXCJgJ10pO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyAnc2luZ2xlLWxpbmUtc3RyaW5nJywgXCJzaW5nbGUtbGluZS1zdHJpbmdcIlxuICAgICAgc2hvcnRjdXRTdHlsZVBhdHRlcm5zLnB1c2goXG4gICAgICAgICAgW1BSX1NUUklORyxcbiAgICAgICAgICAgL14oPzpcXCcoPzpbXlxcXFxcXCdcXHJcXG5dfFxcXFwuKSooPzpcXCd8JCl8XFxcIig/OlteXFxcXFxcXCJcXHJcXG5dfFxcXFwuKSooPzpcXFwifCQpKS8sXG4gICAgICAgICAgIG51bGwsICdcIlxcJyddKTtcbiAgICB9XG4gICAgaWYgKG9wdGlvbnNbJ3ZlcmJhdGltU3RyaW5ncyddKSB7XG4gICAgICAvLyB2ZXJiYXRpbS1zdHJpbmctbGl0ZXJhbCBwcm9kdWN0aW9uIGZyb20gdGhlIEMjIGdyYW1tYXIuICBTZWUgaXNzdWUgOTMuXG4gICAgICBmYWxsdGhyb3VnaFN0eWxlUGF0dGVybnMucHVzaChcbiAgICAgICAgICBbUFJfU1RSSU5HLCAvXkBcXFwiKD86W15cXFwiXXxcXFwiXFxcIikqKD86XFxcInwkKS8sIG51bGxdKTtcbiAgICB9XG4gICAgdmFyIGhjID0gb3B0aW9uc1snaGFzaENvbW1lbnRzJ107XG4gICAgaWYgKGhjKSB7XG4gICAgICBpZiAob3B0aW9uc1snY1N0eWxlQ29tbWVudHMnXSkge1xuICAgICAgICBpZiAoaGMgPiAxKSB7ICAvLyBtdWx0aWxpbmUgaGFzaCBjb21tZW50c1xuICAgICAgICAgIHNob3J0Y3V0U3R5bGVQYXR0ZXJucy5wdXNoKFxuICAgICAgICAgICAgICBbUFJfQ09NTUVOVCwgL14jKD86IyMoPzpbXiNdfCMoPyEjIykpKig/OiMjI3wkKXwuKikvLCBudWxsLCAnIyddKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAvLyBTdG9wIEMgcHJlcHJvY2Vzc29yIGRlY2xhcmF0aW9ucyBhdCBhbiB1bmNsb3NlZCBvcGVuIGNvbW1lbnRcbiAgICAgICAgICBzaG9ydGN1dFN0eWxlUGF0dGVybnMucHVzaChcbiAgICAgICAgICAgICAgW1BSX0NPTU1FTlQsIC9eIyg/Oig/OmRlZmluZXxlKD86bHxuZClpZnxlbHNlfGVycm9yfGlmbj9kZWZ8aW5jbHVkZXxsaW5lfHByYWdtYXx1bmRlZnx3YXJuaW5nKVxcYnxbXlxcclxcbl0qKS8sXG4gICAgICAgICAgICAgICBudWxsLCAnIyddKTtcbiAgICAgICAgfVxuICAgICAgICAvLyAjaW5jbHVkZSA8c3RkaW8uaD5cbiAgICAgICAgZmFsbHRocm91Z2hTdHlsZVBhdHRlcm5zLnB1c2goXG4gICAgICAgICAgICBbUFJfU1RSSU5HLFxuICAgICAgICAgICAgIC9ePCg/Oig/Oig/OlxcLlxcLlxcLykqfFxcLz8pKD86W1xcdy1dKyg/OlxcL1tcXHctXSspKyk/W1xcdy1dK1xcLmgoPzpofHBwfFxcK1xcKyk/fFthLXpdXFx3Kik+LyxcbiAgICAgICAgICAgICBudWxsXSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzaG9ydGN1dFN0eWxlUGF0dGVybnMucHVzaChbUFJfQ09NTUVOVCwgL14jW15cXHJcXG5dKi8sIG51bGwsICcjJ10pO1xuICAgICAgfVxuICAgIH1cbiAgICBpZiAob3B0aW9uc1snY1N0eWxlQ29tbWVudHMnXSkge1xuICAgICAgZmFsbHRocm91Z2hTdHlsZVBhdHRlcm5zLnB1c2goW1BSX0NPTU1FTlQsIC9eXFwvXFwvW15cXHJcXG5dKi8sIG51bGxdKTtcbiAgICAgIGZhbGx0aHJvdWdoU3R5bGVQYXR0ZXJucy5wdXNoKFxuICAgICAgICAgIFtQUl9DT01NRU5ULCAvXlxcL1xcKltcXHNcXFNdKj8oPzpcXCpcXC98JCkvLCBudWxsXSk7XG4gICAgfVxuICAgIHZhciByZWdleExpdGVyYWxzID0gb3B0aW9uc1sncmVnZXhMaXRlcmFscyddO1xuICAgIGlmIChyZWdleExpdGVyYWxzKSB7XG4gICAgICAvKipcbiAgICAgICAqIEBjb25zdFxuICAgICAgICovXG4gICAgICB2YXIgcmVnZXhFeGNscyA9IHJlZ2V4TGl0ZXJhbHMgPiAxXG4gICAgICAgID8gJycgIC8vIE11bHRpbGluZSByZWdleCBsaXRlcmFsc1xuICAgICAgICA6ICdcXG5cXHInO1xuICAgICAgLyoqXG4gICAgICAgKiBAY29uc3RcbiAgICAgICAqL1xuICAgICAgdmFyIHJlZ2V4QW55ID0gcmVnZXhFeGNscyA/ICcuJyA6ICdbXFxcXFNcXFxcc10nO1xuICAgICAgLyoqXG4gICAgICAgKiBAY29uc3RcbiAgICAgICAqL1xuICAgICAgdmFyIFJFR0VYX0xJVEVSQUwgPSAoXG4gICAgICAgICAgLy8gQSByZWd1bGFyIGV4cHJlc3Npb24gbGl0ZXJhbCBzdGFydHMgd2l0aCBhIHNsYXNoIHRoYXQgaXNcbiAgICAgICAgICAvLyBub3QgZm9sbG93ZWQgYnkgKiBvciAvIHNvIHRoYXQgaXQgaXMgbm90IGNvbmZ1c2VkIHdpdGhcbiAgICAgICAgICAvLyBjb21tZW50cy5cbiAgICAgICAgICAnLyg/PVteLyonICsgcmVnZXhFeGNscyArICddKSdcbiAgICAgICAgICAvLyBhbmQgdGhlbiBjb250YWlucyBhbnkgbnVtYmVyIG9mIHJhdyBjaGFyYWN0ZXJzLFxuICAgICAgICAgICsgJyg/OlteL1xcXFx4NUJcXFxceDVDJyArIHJlZ2V4RXhjbHMgKyAnXSdcbiAgICAgICAgICAvLyBlc2NhcGUgc2VxdWVuY2VzIChcXHg1QyksXG4gICAgICAgICAgKyAgICAnfFxcXFx4NUMnICsgcmVnZXhBbnlcbiAgICAgICAgICAvLyBvciBub24tbmVzdGluZyBjaGFyYWN0ZXIgc2V0cyAoXFx4NUJcXHg1RCk7XG4gICAgICAgICAgKyAgICAnfFxcXFx4NUIoPzpbXlxcXFx4NUNcXFxceDVEJyArIHJlZ2V4RXhjbHMgKyAnXSdcbiAgICAgICAgICArICAgICAgICAgICAgICd8XFxcXHg1QycgKyByZWdleEFueSArICcpKig/OlxcXFx4NUR8JCkpKydcbiAgICAgICAgICAvLyBmaW5hbGx5IGNsb3NlZCBieSBhIC8uXG4gICAgICAgICAgKyAnLycpO1xuICAgICAgZmFsbHRocm91Z2hTdHlsZVBhdHRlcm5zLnB1c2goXG4gICAgICAgICAgWydsYW5nLXJlZ2V4JyxcbiAgICAgICAgICAgUmVnRXhwKCdeJyArIFJFR0VYUF9QUkVDRURFUl9QQVRURVJOICsgJygnICsgUkVHRVhfTElURVJBTCArICcpJylcbiAgICAgICAgICAgXSk7XG4gICAgfVxuXG4gICAgdmFyIHR5cGVzID0gb3B0aW9uc1sndHlwZXMnXTtcbiAgICBpZiAodHlwZXMpIHtcbiAgICAgIGZhbGx0aHJvdWdoU3R5bGVQYXR0ZXJucy5wdXNoKFtQUl9UWVBFLCB0eXBlc10pO1xuICAgIH1cblxuICAgIHZhciBrZXl3b3JkcyA9IChcIlwiICsgb3B0aW9uc1sna2V5d29yZHMnXSkucmVwbGFjZSgvXiB8ICQvZywgJycpO1xuICAgIGlmIChrZXl3b3Jkcy5sZW5ndGgpIHtcbiAgICAgIGZhbGx0aHJvdWdoU3R5bGVQYXR0ZXJucy5wdXNoKFxuICAgICAgICAgIFtQUl9LRVlXT1JELFxuICAgICAgICAgICBuZXcgUmVnRXhwKCdeKD86JyArIGtleXdvcmRzLnJlcGxhY2UoL1tcXHMsXSsvZywgJ3wnKSArICcpXFxcXGInKSxcbiAgICAgICAgICAgbnVsbF0pO1xuICAgIH1cblxuICAgIHNob3J0Y3V0U3R5bGVQYXR0ZXJucy5wdXNoKFtQUl9QTEFJTiwgICAgICAgL15cXHMrLywgbnVsbCwgJyBcXHJcXG5cXHRcXHhBMCddKTtcblxuICAgIHZhciBwdW5jdHVhdGlvbiA9XG4gICAgICAvLyBUaGUgQmFzaCBtYW4gcGFnZSBzYXlzXG5cbiAgICAgIC8vIEEgd29yZCBpcyBhIHNlcXVlbmNlIG9mIGNoYXJhY3RlcnMgY29uc2lkZXJlZCBhcyBhIHNpbmdsZVxuICAgICAgLy8gdW5pdCBieSBHUlVCLiBXb3JkcyBhcmUgc2VwYXJhdGVkIGJ5IG1ldGFjaGFyYWN0ZXJzLFxuICAgICAgLy8gd2hpY2ggYXJlIHRoZSBmb2xsb3dpbmcgcGx1cyBzcGFjZSwgdGFiLCBhbmQgbmV3bGluZTogeyB9XG4gICAgICAvLyB8ICYgJCA7IDwgPlxuICAgICAgLy8gLi4uXG4gICAgICBcbiAgICAgIC8vIEEgd29yZCBiZWdpbm5pbmcgd2l0aCAjIGNhdXNlcyB0aGF0IHdvcmQgYW5kIGFsbCByZW1haW5pbmdcbiAgICAgIC8vIGNoYXJhY3RlcnMgb24gdGhhdCBsaW5lIHRvIGJlIGlnbm9yZWQuXG5cbiAgICAgIC8vIHdoaWNoIG1lYW5zIHRoYXQgb25seSBhICcjJyBhZnRlciAvKD86Xnxbe318JiQ7PD5cXHNdKS8gc3RhcnRzIGFcbiAgICAgIC8vIGNvbW1lbnQgYnV0IGVtcGlyaWNhbGx5XG4gICAgICAvLyAkIGVjaG8geyN9XG4gICAgICAvLyB7I31cbiAgICAgIC8vICQgZWNobyBcXCQjXG4gICAgICAvLyAkI1xuICAgICAgLy8gJCBlY2hvIH0jXG4gICAgICAvLyB9I1xuXG4gICAgICAvLyBzbyAvKD86XnxbfCY7PD5cXHNdKS8gaXMgbW9yZSBhcHByb3ByaWF0ZS5cblxuICAgICAgLy8gaHR0cDovL2djYy5nbnUub3JnL29ubGluZWRvY3MvZ2NjLTIuOTUuMy9jcHBfMS5odG1sI1NFQzNcbiAgICAgIC8vIHN1Z2dlc3RzIHRoYXQgdGhpcyBkZWZpbml0aW9uIGlzIGNvbXBhdGlibGUgd2l0aCBhXG4gICAgICAvLyBkZWZhdWx0IG1vZGUgdGhhdCB0cmllcyB0byB1c2UgYSBzaW5nbGUgdG9rZW4gZGVmaW5pdGlvblxuICAgICAgLy8gdG8gcmVjb2duaXplIGJvdGggYmFzaC9weXRob24gc3R5bGUgY29tbWVudHMgYW5kIENcbiAgICAgIC8vIHByZXByb2Nlc3NvciBkaXJlY3RpdmVzLlxuXG4gICAgICAvLyBUaGlzIGRlZmluaXRpb24gb2YgcHVuY3R1YXRpb24gZG9lcyBub3QgaW5jbHVkZSAjIGluIHRoZSBsaXN0IG9mXG4gICAgICAvLyBmb2xsb3ctb24gZXhjbHVzaW9ucywgc28gIyB3aWxsIG5vdCBiZSBicm9rZW4gYmVmb3JlIGlmIHByZWNlZWRlZFxuICAgICAgLy8gYnkgYSBwdW5jdHVhdGlvbiBjaGFyYWN0ZXIuICBXZSBjb3VsZCB0cnkgdG8gZXhjbHVkZSAjIGFmdGVyXG4gICAgICAvLyBbfCY7PD5dIGJ1dCB0aGF0IGRvZXNuJ3Qgc2VlbSB0byBjYXVzZSBtYW55IG1ham9yIHByb2JsZW1zLlxuICAgICAgLy8gSWYgdGhhdCBkb2VzIHR1cm4gb3V0IHRvIGJlIGEgcHJvYmxlbSwgd2Ugc2hvdWxkIGNoYW5nZSB0aGUgYmVsb3dcbiAgICAgIC8vIHdoZW4gaGMgaXMgdHJ1dGh5IHRvIGluY2x1ZGUgIyBpbiB0aGUgcnVuIG9mIHB1bmN0dWF0aW9uIGNoYXJhY3RlcnNcbiAgICAgIC8vIG9ubHkgd2hlbiBub3QgZm9sbG93aW50IFt8Jjs8Pl0uXG4gICAgICAnXi5bXlxcXFxzXFxcXHcuJEBcXCdcImAvXFxcXFxcXFxdKic7XG4gICAgaWYgKG9wdGlvbnNbJ3JlZ2V4TGl0ZXJhbHMnXSkge1xuICAgICAgcHVuY3R1YXRpb24gKz0gJyg/IVxccypcXC8pJztcbiAgICB9XG5cbiAgICBmYWxsdGhyb3VnaFN0eWxlUGF0dGVybnMucHVzaChcbiAgICAgICAgLy8gVE9ETyhtaWtlc2FtdWVsKTogcmVjb2duaXplIG5vbi1sYXRpbiBsZXR0ZXJzIGFuZCBudW1lcmFscyBpbiBpZGVudHNcbiAgICAgICAgW1BSX0xJVEVSQUwsICAgICAvXkBbYS16XyRdW2Etel8kQDAtOV0qL2ksIG51bGxdLFxuICAgICAgICBbUFJfVFlQRSwgICAgICAgIC9eKD86W0BfXT9bQS1aXStbYS16XVtBLVphLXpfJEAwLTldKnxcXHcrX3RcXGIpLywgbnVsbF0sXG4gICAgICAgIFtQUl9QTEFJTiwgICAgICAgL15bYS16XyRdW2Etel8kQDAtOV0qL2ksIG51bGxdLFxuICAgICAgICBbUFJfTElURVJBTCxcbiAgICAgICAgIG5ldyBSZWdFeHAoXG4gICAgICAgICAgICAgJ14oPzonXG4gICAgICAgICAgICAgLy8gQSBoZXggbnVtYmVyXG4gICAgICAgICAgICAgKyAnMHhbYS1mMC05XSsnXG4gICAgICAgICAgICAgLy8gb3IgYW4gb2N0YWwgb3IgZGVjaW1hbCBudW1iZXIsXG4gICAgICAgICAgICAgKyAnfCg/OlxcXFxkKD86X1xcXFxkKykqXFxcXGQqKD86XFxcXC5cXFxcZCopP3xcXFxcLlxcXFxkXFxcXCspJ1xuICAgICAgICAgICAgIC8vIHBvc3NpYmx5IGluIHNjaWVudGlmaWMgbm90YXRpb25cbiAgICAgICAgICAgICArICcoPzplWytcXFxcLV0/XFxcXGQrKT8nXG4gICAgICAgICAgICAgKyAnKSdcbiAgICAgICAgICAgICAvLyB3aXRoIGFuIG9wdGlvbmFsIG1vZGlmaWVyIGxpa2UgVUwgZm9yIHVuc2lnbmVkIGxvbmdcbiAgICAgICAgICAgICArICdbYS16XSonLCAnaScpLFxuICAgICAgICAgbnVsbCwgJzAxMjM0NTY3ODknXSxcbiAgICAgICAgLy8gRG9uJ3QgdHJlYXQgZXNjYXBlZCBxdW90ZXMgaW4gYmFzaCBhcyBzdGFydGluZyBzdHJpbmdzLlxuICAgICAgICAvLyBTZWUgaXNzdWUgMTQ0LlxuICAgICAgICBbUFJfUExBSU4sICAgICAgIC9eXFxcXFtcXHNcXFNdPy8sIG51bGxdLFxuICAgICAgICBbUFJfUFVOQ1RVQVRJT04sIG5ldyBSZWdFeHAocHVuY3R1YXRpb24pLCBudWxsXSk7XG5cbiAgICByZXR1cm4gY3JlYXRlU2ltcGxlTGV4ZXIoc2hvcnRjdXRTdHlsZVBhdHRlcm5zLCBmYWxsdGhyb3VnaFN0eWxlUGF0dGVybnMpO1xuICB9XG5cbiAgdmFyIGRlY29yYXRlU291cmNlID0gc291cmNlRGVjb3JhdG9yKHtcbiAgICAgICAgJ2tleXdvcmRzJzogQUxMX0tFWVdPUkRTLFxuICAgICAgICAnaGFzaENvbW1lbnRzJzogdHJ1ZSxcbiAgICAgICAgJ2NTdHlsZUNvbW1lbnRzJzogdHJ1ZSxcbiAgICAgICAgJ211bHRpTGluZVN0cmluZ3MnOiB0cnVlLFxuICAgICAgICAncmVnZXhMaXRlcmFscyc6IHRydWVcbiAgICAgIH0pO1xuXG4gIC8qKlxuICAgKiBHaXZlbiBhIERPTSBzdWJ0cmVlLCB3cmFwcyBpdCBpbiBhIGxpc3QsIGFuZCBwdXRzIGVhY2ggbGluZSBpbnRvIGl0cyBvd25cbiAgICogbGlzdCBpdGVtLlxuICAgKlxuICAgKiBAcGFyYW0ge05vZGV9IG5vZGUgbW9kaWZpZWQgaW4gcGxhY2UuICBJdHMgY29udGVudCBpcyBwdWxsZWQgaW50byBhblxuICAgKiAgICAgSFRNTE9MaXN0RWxlbWVudCwgYW5kIGVhY2ggbGluZSBpcyBtb3ZlZCBpbnRvIGEgc2VwYXJhdGUgbGlzdCBpdGVtLlxuICAgKiAgICAgVGhpcyByZXF1aXJlcyBjbG9uaW5nIGVsZW1lbnRzLCBzbyB0aGUgaW5wdXQgbWlnaHQgbm90IGhhdmUgdW5pcXVlXG4gICAqICAgICBJRHMgYWZ0ZXIgbnVtYmVyaW5nLlxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IGlzUHJlZm9ybWF0dGVkIHRydWUgaWZmIHdoaXRlLXNwYWNlIGluIHRleHQgbm9kZXMgc2hvdWxkXG4gICAqICAgICBiZSB0cmVhdGVkIGFzIHNpZ25pZmljYW50LlxuICAgKi9cbiAgZnVuY3Rpb24gbnVtYmVyTGluZXMobm9kZSwgb3B0X3N0YXJ0TGluZU51bSwgaXNQcmVmb3JtYXR0ZWQpIHtcbiAgICB2YXIgbm9jb2RlID0gLyg/Ol58XFxzKW5vY29kZSg/Olxcc3wkKS87XG4gICAgdmFyIGxpbmVCcmVhayA9IC9cXHJcXG4/fFxcbi87XG4gIFxuICAgIHZhciBkb2N1bWVudCA9IG5vZGUub3duZXJEb2N1bWVudDtcbiAgXG4gICAgdmFyIGxpID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnbGknKTtcbiAgICB3aGlsZSAobm9kZS5maXJzdENoaWxkKSB7XG4gICAgICBsaS5hcHBlbmRDaGlsZChub2RlLmZpcnN0Q2hpbGQpO1xuICAgIH1cbiAgICAvLyBBbiBhcnJheSBvZiBsaW5lcy4gIFdlIHNwbGl0IGJlbG93LCBzbyB0aGlzIGlzIGluaXRpYWxpemVkIHRvIG9uZVxuICAgIC8vIHVuLXNwbGl0IGxpbmUuXG4gICAgdmFyIGxpc3RJdGVtcyA9IFtsaV07XG4gIFxuICAgIGZ1bmN0aW9uIHdhbGsobm9kZSkge1xuICAgICAgdmFyIHR5cGUgPSBub2RlLm5vZGVUeXBlO1xuICAgICAgaWYgKHR5cGUgPT0gMSAmJiAhbm9jb2RlLnRlc3Qobm9kZS5jbGFzc05hbWUpKSB7ICAvLyBFbGVtZW50XG4gICAgICAgIGlmICgnYnInID09PSBub2RlLm5vZGVOYW1lKSB7XG4gICAgICAgICAgYnJlYWtBZnRlcihub2RlKTtcbiAgICAgICAgICAvLyBEaXNjYXJkIHRoZSA8QlI+IHNpbmNlIGl0IGlzIG5vdyBmbHVzaCBhZ2FpbnN0IGEgPC9MST4uXG4gICAgICAgICAgaWYgKG5vZGUucGFyZW50Tm9kZSkge1xuICAgICAgICAgICAgbm9kZS5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKG5vZGUpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBmb3IgKHZhciBjaGlsZCA9IG5vZGUuZmlyc3RDaGlsZDsgY2hpbGQ7IGNoaWxkID0gY2hpbGQubmV4dFNpYmxpbmcpIHtcbiAgICAgICAgICAgIHdhbGsoY2hpbGQpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmICgodHlwZSA9PSAzIHx8IHR5cGUgPT0gNCkgJiYgaXNQcmVmb3JtYXR0ZWQpIHsgIC8vIFRleHRcbiAgICAgICAgdmFyIHRleHQgPSBub2RlLm5vZGVWYWx1ZTtcbiAgICAgICAgdmFyIG1hdGNoID0gdGV4dC5tYXRjaChsaW5lQnJlYWspO1xuICAgICAgICBpZiAobWF0Y2gpIHtcbiAgICAgICAgICB2YXIgZmlyc3RMaW5lID0gdGV4dC5zdWJzdHJpbmcoMCwgbWF0Y2guaW5kZXgpO1xuICAgICAgICAgIG5vZGUubm9kZVZhbHVlID0gZmlyc3RMaW5lO1xuICAgICAgICAgIHZhciB0YWlsID0gdGV4dC5zdWJzdHJpbmcobWF0Y2guaW5kZXggKyBtYXRjaFswXS5sZW5ndGgpO1xuICAgICAgICAgIGlmICh0YWlsKSB7XG4gICAgICAgICAgICB2YXIgcGFyZW50ID0gbm9kZS5wYXJlbnROb2RlO1xuICAgICAgICAgICAgcGFyZW50Lmluc2VydEJlZm9yZShcbiAgICAgICAgICAgICAgZG9jdW1lbnQuY3JlYXRlVGV4dE5vZGUodGFpbCksIG5vZGUubmV4dFNpYmxpbmcpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBicmVha0FmdGVyKG5vZGUpO1xuICAgICAgICAgIGlmICghZmlyc3RMaW5lKSB7XG4gICAgICAgICAgICAvLyBEb24ndCBsZWF2ZSBibGFuayB0ZXh0IG5vZGVzIGluIHRoZSBET00uXG4gICAgICAgICAgICBub2RlLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQobm9kZSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICBcbiAgICAvLyBTcGxpdCBhIGxpbmUgYWZ0ZXIgdGhlIGdpdmVuIG5vZGUuXG4gICAgZnVuY3Rpb24gYnJlYWtBZnRlcihsaW5lRW5kTm9kZSkge1xuICAgICAgLy8gSWYgdGhlcmUncyBub3RoaW5nIHRvIHRoZSByaWdodCwgdGhlbiB3ZSBjYW4gc2tpcCBlbmRpbmcgdGhlIGxpbmVcbiAgICAgIC8vIGhlcmUsIGFuZCBtb3ZlIHJvb3Qtd2FyZHMgc2luY2Ugc3BsaXR0aW5nIGp1c3QgYmVmb3JlIGFuIGVuZC10YWdcbiAgICAgIC8vIHdvdWxkIHJlcXVpcmUgdXMgdG8gY3JlYXRlIGEgYnVuY2ggb2YgZW1wdHkgY29waWVzLlxuICAgICAgd2hpbGUgKCFsaW5lRW5kTm9kZS5uZXh0U2libGluZykge1xuICAgICAgICBsaW5lRW5kTm9kZSA9IGxpbmVFbmROb2RlLnBhcmVudE5vZGU7XG4gICAgICAgIGlmICghbGluZUVuZE5vZGUpIHsgcmV0dXJuOyB9XG4gICAgICB9XG4gIFxuICAgICAgZnVuY3Rpb24gYnJlYWtMZWZ0T2YobGltaXQsIGNvcHkpIHtcbiAgICAgICAgLy8gQ2xvbmUgc2hhbGxvd2x5IGlmIHRoaXMgbm9kZSBuZWVkcyB0byBiZSBvbiBib3RoIHNpZGVzIG9mIHRoZSBicmVhay5cbiAgICAgICAgdmFyIHJpZ2h0U2lkZSA9IGNvcHkgPyBsaW1pdC5jbG9uZU5vZGUoZmFsc2UpIDogbGltaXQ7XG4gICAgICAgIHZhciBwYXJlbnQgPSBsaW1pdC5wYXJlbnROb2RlO1xuICAgICAgICBpZiAocGFyZW50KSB7XG4gICAgICAgICAgLy8gV2UgY2xvbmUgdGhlIHBhcmVudCBjaGFpbi5cbiAgICAgICAgICAvLyBUaGlzIGhlbHBzIHVzIHJlc3VycmVjdCBpbXBvcnRhbnQgc3R5bGluZyBlbGVtZW50cyB0aGF0IGNyb3NzIGxpbmVzLlxuICAgICAgICAgIC8vIEUuZy4gaW4gPGk+Rm9vPGJyPkJhcjwvaT5cbiAgICAgICAgICAvLyBzaG91bGQgYmUgcmV3cml0dGVuIHRvIDxsaT48aT5Gb288L2k+PC9saT48bGk+PGk+QmFyPC9pPjwvbGk+LlxuICAgICAgICAgIHZhciBwYXJlbnRDbG9uZSA9IGJyZWFrTGVmdE9mKHBhcmVudCwgMSk7XG4gICAgICAgICAgLy8gTW92ZSB0aGUgY2xvbmUgYW5kIGV2ZXJ5dGhpbmcgdG8gdGhlIHJpZ2h0IG9mIHRoZSBvcmlnaW5hbFxuICAgICAgICAgIC8vIG9udG8gdGhlIGNsb25lZCBwYXJlbnQuXG4gICAgICAgICAgdmFyIG5leHQgPSBsaW1pdC5uZXh0U2libGluZztcbiAgICAgICAgICBwYXJlbnRDbG9uZS5hcHBlbmRDaGlsZChyaWdodFNpZGUpO1xuICAgICAgICAgIGZvciAodmFyIHNpYmxpbmcgPSBuZXh0OyBzaWJsaW5nOyBzaWJsaW5nID0gbmV4dCkge1xuICAgICAgICAgICAgbmV4dCA9IHNpYmxpbmcubmV4dFNpYmxpbmc7XG4gICAgICAgICAgICBwYXJlbnRDbG9uZS5hcHBlbmRDaGlsZChzaWJsaW5nKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJpZ2h0U2lkZTtcbiAgICAgIH1cbiAgXG4gICAgICB2YXIgY29waWVkTGlzdEl0ZW0gPSBicmVha0xlZnRPZihsaW5lRW5kTm9kZS5uZXh0U2libGluZywgMCk7XG4gIFxuICAgICAgLy8gV2FsayB0aGUgcGFyZW50IGNoYWluIHVudGlsIHdlIHJlYWNoIGFuIHVuYXR0YWNoZWQgTEkuXG4gICAgICBmb3IgKHZhciBwYXJlbnQ7XG4gICAgICAgICAgIC8vIENoZWNrIG5vZGVUeXBlIHNpbmNlIElFIGludmVudHMgZG9jdW1lbnQgZnJhZ21lbnRzLlxuICAgICAgICAgICAocGFyZW50ID0gY29waWVkTGlzdEl0ZW0ucGFyZW50Tm9kZSkgJiYgcGFyZW50Lm5vZGVUeXBlID09PSAxOykge1xuICAgICAgICBjb3BpZWRMaXN0SXRlbSA9IHBhcmVudDtcbiAgICAgIH1cbiAgICAgIC8vIFB1dCBpdCBvbiB0aGUgbGlzdCBvZiBsaW5lcyBmb3IgbGF0ZXIgcHJvY2Vzc2luZy5cbiAgICAgIGxpc3RJdGVtcy5wdXNoKGNvcGllZExpc3RJdGVtKTtcbiAgICB9XG4gIFxuICAgIC8vIFNwbGl0IGxpbmVzIHdoaWxlIHRoZXJlIGFyZSBsaW5lcyBsZWZ0IHRvIHNwbGl0LlxuICAgIGZvciAodmFyIGkgPSAwOyAgLy8gTnVtYmVyIG9mIGxpbmVzIHRoYXQgaGF2ZSBiZWVuIHNwbGl0IHNvIGZhci5cbiAgICAgICAgIGkgPCBsaXN0SXRlbXMubGVuZ3RoOyAgLy8gbGVuZ3RoIHVwZGF0ZWQgYnkgYnJlYWtBZnRlciBjYWxscy5cbiAgICAgICAgICsraSkge1xuICAgICAgd2FsayhsaXN0SXRlbXNbaV0pO1xuICAgIH1cbiAgXG4gICAgLy8gTWFrZSBzdXJlIG51bWVyaWMgaW5kaWNlcyBzaG93IGNvcnJlY3RseS5cbiAgICBpZiAob3B0X3N0YXJ0TGluZU51bSA9PT0gKG9wdF9zdGFydExpbmVOdW18MCkpIHtcbiAgICAgIGxpc3RJdGVtc1swXS5zZXRBdHRyaWJ1dGUoJ3ZhbHVlJywgb3B0X3N0YXJ0TGluZU51bSk7XG4gICAgfVxuICBcbiAgICB2YXIgb2wgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdvbCcpO1xuICAgIG9sLmNsYXNzTmFtZSA9ICdsaW5lbnVtcyc7XG4gICAgdmFyIG9mZnNldCA9IE1hdGgubWF4KDAsICgob3B0X3N0YXJ0TGluZU51bSAtIDEgLyogemVybyBpbmRleCAqLykpIHwgMCkgfHwgMDtcbiAgICBmb3IgKHZhciBpID0gMCwgbiA9IGxpc3RJdGVtcy5sZW5ndGg7IGkgPCBuOyArK2kpIHtcbiAgICAgIGxpID0gbGlzdEl0ZW1zW2ldO1xuICAgICAgLy8gU3RpY2sgYSBjbGFzcyBvbiB0aGUgTElzIHNvIHRoYXQgc3R5bGVzaGVldHMgY2FuXG4gICAgICAvLyBjb2xvciBvZGQvZXZlbiByb3dzLCBvciBhbnkgb3RoZXIgcm93IHBhdHRlcm4gdGhhdFxuICAgICAgLy8gaXMgY28tcHJpbWUgd2l0aCAxMC5cbiAgICAgIGxpLmNsYXNzTmFtZSA9ICdMJyArICgoaSArIG9mZnNldCkgJSAxMCk7XG4gICAgICBpZiAoIWxpLmZpcnN0Q2hpbGQpIHtcbiAgICAgICAgbGkuYXBwZW5kQ2hpbGQoZG9jdW1lbnQuY3JlYXRlVGV4dE5vZGUoJ1xceEEwJykpO1xuICAgICAgfVxuICAgICAgb2wuYXBwZW5kQ2hpbGQobGkpO1xuICAgIH1cbiAgXG4gICAgbm9kZS5hcHBlbmRDaGlsZChvbCk7XG4gIH1cbiAgLyoqXG4gICAqIEJyZWFrcyB7QGNvZGUgam9iLnNvdXJjZUNvZGV9IGFyb3VuZCBzdHlsZSBib3VuZGFyaWVzIGluXG4gICAqIHtAY29kZSBqb2IuZGVjb3JhdGlvbnN9IGFuZCBtb2RpZmllcyB7QGNvZGUgam9iLnNvdXJjZU5vZGV9IGluIHBsYWNlLlxuICAgKiBAcGFyYW0ge09iamVjdH0gam9iIGxpa2UgPHByZT57XG4gICAqICAgIHNvdXJjZUNvZGU6IHtzdHJpbmd9IHNvdXJjZSBhcyBwbGFpbiB0ZXh0LFxuICAgKiAgICBzb3VyY2VOb2RlOiB7SFRNTEVsZW1lbnR9IHRoZSBlbGVtZW50IGNvbnRhaW5pbmcgdGhlIHNvdXJjZSxcbiAgICogICAgc3BhbnM6IHtBcnJheS48bnVtYmVyfE5vZGU+fSBhbHRlcm5hdGluZyBzcGFuIHN0YXJ0IGluZGljZXMgaW50byBzb3VyY2VcbiAgICogICAgICAgYW5kIHRoZSB0ZXh0IG5vZGUgb3IgZWxlbWVudCAoZS5nLiB7QGNvZGUgPEJSPn0pIGNvcnJlc3BvbmRpbmcgdG8gdGhhdFxuICAgKiAgICAgICBzcGFuLlxuICAgKiAgICBkZWNvcmF0aW9uczoge0FycmF5LjxudW1iZXJ8c3RyaW5nfSBhbiBhcnJheSBvZiBzdHlsZSBjbGFzc2VzIHByZWNlZGVkXG4gICAqICAgICAgIGJ5IHRoZSBwb3NpdGlvbiBhdCB3aGljaCB0aGV5IHN0YXJ0IGluIGpvYi5zb3VyY2VDb2RlIGluIG9yZGVyXG4gICAqIH08L3ByZT5cbiAgICogQHByaXZhdGVcbiAgICovXG4gIGZ1bmN0aW9uIHJlY29tYmluZVRhZ3NBbmREZWNvcmF0aW9ucyhqb2IpIHtcbiAgICB2YXIgaXNJRThPckVhcmxpZXIgPSAvXFxiTVNJRVxccyhcXGQrKS8uZXhlYyhuYXZpZ2F0b3IudXNlckFnZW50KTtcbiAgICBpc0lFOE9yRWFybGllciA9IGlzSUU4T3JFYXJsaWVyICYmICtpc0lFOE9yRWFybGllclsxXSA8PSA4O1xuICAgIHZhciBuZXdsaW5lUmUgPSAvXFxuL2c7XG4gIFxuICAgIHZhciBzb3VyY2UgPSBqb2Iuc291cmNlQ29kZTtcbiAgICB2YXIgc291cmNlTGVuZ3RoID0gc291cmNlLmxlbmd0aDtcbiAgICAvLyBJbmRleCBpbnRvIHNvdXJjZSBhZnRlciB0aGUgbGFzdCBjb2RlLXVuaXQgcmVjb21iaW5lZC5cbiAgICB2YXIgc291cmNlSW5kZXggPSAwO1xuICBcbiAgICB2YXIgc3BhbnMgPSBqb2Iuc3BhbnM7XG4gICAgdmFyIG5TcGFucyA9IHNwYW5zLmxlbmd0aDtcbiAgICAvLyBJbmRleCBpbnRvIHNwYW5zIGFmdGVyIHRoZSBsYXN0IHNwYW4gd2hpY2ggZW5kcyBhdCBvciBiZWZvcmUgc291cmNlSW5kZXguXG4gICAgdmFyIHNwYW5JbmRleCA9IDA7XG4gIFxuICAgIHZhciBkZWNvcmF0aW9ucyA9IGpvYi5kZWNvcmF0aW9ucztcbiAgICB2YXIgbkRlY29yYXRpb25zID0gZGVjb3JhdGlvbnMubGVuZ3RoO1xuICAgIC8vIEluZGV4IGludG8gZGVjb3JhdGlvbnMgYWZ0ZXIgdGhlIGxhc3QgZGVjb3JhdGlvbiB3aGljaCBlbmRzIGF0IG9yIGJlZm9yZVxuICAgIC8vIHNvdXJjZUluZGV4LlxuICAgIHZhciBkZWNvcmF0aW9uSW5kZXggPSAwO1xuICBcbiAgICAvLyBSZW1vdmUgYWxsIHplcm8tbGVuZ3RoIGRlY29yYXRpb25zLlxuICAgIGRlY29yYXRpb25zW25EZWNvcmF0aW9uc10gPSBzb3VyY2VMZW5ndGg7XG4gICAgdmFyIGRlY1BvcywgaTtcbiAgICBmb3IgKGkgPSBkZWNQb3MgPSAwOyBpIDwgbkRlY29yYXRpb25zOykge1xuICAgICAgaWYgKGRlY29yYXRpb25zW2ldICE9PSBkZWNvcmF0aW9uc1tpICsgMl0pIHtcbiAgICAgICAgZGVjb3JhdGlvbnNbZGVjUG9zKytdID0gZGVjb3JhdGlvbnNbaSsrXTtcbiAgICAgICAgZGVjb3JhdGlvbnNbZGVjUG9zKytdID0gZGVjb3JhdGlvbnNbaSsrXTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGkgKz0gMjtcbiAgICAgIH1cbiAgICB9XG4gICAgbkRlY29yYXRpb25zID0gZGVjUG9zO1xuICBcbiAgICAvLyBTaW1wbGlmeSBkZWNvcmF0aW9ucy5cbiAgICBmb3IgKGkgPSBkZWNQb3MgPSAwOyBpIDwgbkRlY29yYXRpb25zOykge1xuICAgICAgdmFyIHN0YXJ0UG9zID0gZGVjb3JhdGlvbnNbaV07XG4gICAgICAvLyBDb25mbGF0ZSBhbGwgYWRqYWNlbnQgZGVjb3JhdGlvbnMgdGhhdCB1c2UgdGhlIHNhbWUgc3R5bGUuXG4gICAgICB2YXIgc3RhcnREZWMgPSBkZWNvcmF0aW9uc1tpICsgMV07XG4gICAgICB2YXIgZW5kID0gaSArIDI7XG4gICAgICB3aGlsZSAoZW5kICsgMiA8PSBuRGVjb3JhdGlvbnMgJiYgZGVjb3JhdGlvbnNbZW5kICsgMV0gPT09IHN0YXJ0RGVjKSB7XG4gICAgICAgIGVuZCArPSAyO1xuICAgICAgfVxuICAgICAgZGVjb3JhdGlvbnNbZGVjUG9zKytdID0gc3RhcnRQb3M7XG4gICAgICBkZWNvcmF0aW9uc1tkZWNQb3MrK10gPSBzdGFydERlYztcbiAgICAgIGkgPSBlbmQ7XG4gICAgfVxuICBcbiAgICBuRGVjb3JhdGlvbnMgPSBkZWNvcmF0aW9ucy5sZW5ndGggPSBkZWNQb3M7XG4gIFxuICAgIHZhciBzb3VyY2VOb2RlID0gam9iLnNvdXJjZU5vZGU7XG4gICAgdmFyIG9sZERpc3BsYXk7XG4gICAgaWYgKHNvdXJjZU5vZGUpIHtcbiAgICAgIG9sZERpc3BsYXkgPSBzb3VyY2VOb2RlLnN0eWxlLmRpc3BsYXk7XG4gICAgICBzb3VyY2VOb2RlLnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7XG4gICAgfVxuICAgIHRyeSB7XG4gICAgICB2YXIgZGVjb3JhdGlvbiA9IG51bGw7XG4gICAgICB3aGlsZSAoc3BhbkluZGV4IDwgblNwYW5zKSB7XG4gICAgICAgIHZhciBzcGFuU3RhcnQgPSBzcGFuc1tzcGFuSW5kZXhdO1xuICAgICAgICB2YXIgc3BhbkVuZCA9IHNwYW5zW3NwYW5JbmRleCArIDJdIHx8IHNvdXJjZUxlbmd0aDtcbiAgXG4gICAgICAgIHZhciBkZWNFbmQgPSBkZWNvcmF0aW9uc1tkZWNvcmF0aW9uSW5kZXggKyAyXSB8fCBzb3VyY2VMZW5ndGg7XG4gIFxuICAgICAgICB2YXIgZW5kID0gTWF0aC5taW4oc3BhbkVuZCwgZGVjRW5kKTtcbiAgXG4gICAgICAgIHZhciB0ZXh0Tm9kZSA9IHNwYW5zW3NwYW5JbmRleCArIDFdO1xuICAgICAgICB2YXIgc3R5bGVkVGV4dDtcbiAgICAgICAgaWYgKHRleHROb2RlLm5vZGVUeXBlICE9PSAxICAvLyBEb24ndCBtdWNrIHdpdGggPEJSPnMgb3IgPExJPnNcbiAgICAgICAgICAgIC8vIERvbid0IGludHJvZHVjZSBzcGFucyBhcm91bmQgZW1wdHkgdGV4dCBub2Rlcy5cbiAgICAgICAgICAgICYmIChzdHlsZWRUZXh0ID0gc291cmNlLnN1YnN0cmluZyhzb3VyY2VJbmRleCwgZW5kKSkpIHtcbiAgICAgICAgICAvLyBUaGlzIG1heSBzZWVtIGJpemFycmUsIGFuZCBpdCBpcy4gIEVtaXR0aW5nIExGIG9uIElFIGNhdXNlcyB0aGVcbiAgICAgICAgICAvLyBjb2RlIHRvIGRpc3BsYXkgd2l0aCBzcGFjZXMgaW5zdGVhZCBvZiBsaW5lIGJyZWFrcy5cbiAgICAgICAgICAvLyBFbWl0dGluZyBXaW5kb3dzIHN0YW5kYXJkIGlzc3VlIGxpbmVicmVha3MgKENSTEYpIGNhdXNlcyBhIGJsYW5rXG4gICAgICAgICAgLy8gc3BhY2UgdG8gYXBwZWFyIGF0IHRoZSBiZWdpbm5pbmcgb2YgZXZlcnkgbGluZSBidXQgdGhlIGZpcnN0LlxuICAgICAgICAgIC8vIEVtaXR0aW5nIGFuIG9sZCBNYWMgT1MgOSBsaW5lIHNlcGFyYXRvciBtYWtlcyBldmVyeXRoaW5nIHNwaWZmeS5cbiAgICAgICAgICBpZiAoaXNJRThPckVhcmxpZXIpIHtcbiAgICAgICAgICAgIHN0eWxlZFRleHQgPSBzdHlsZWRUZXh0LnJlcGxhY2UobmV3bGluZVJlLCAnXFxyJyk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHRleHROb2RlLm5vZGVWYWx1ZSA9IHN0eWxlZFRleHQ7XG4gICAgICAgICAgdmFyIGRvY3VtZW50ID0gdGV4dE5vZGUub3duZXJEb2N1bWVudDtcbiAgICAgICAgICB2YXIgc3BhbiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3NwYW4nKTtcbiAgICAgICAgICBzcGFuLmNsYXNzTmFtZSA9IGRlY29yYXRpb25zW2RlY29yYXRpb25JbmRleCArIDFdO1xuICAgICAgICAgIHZhciBwYXJlbnROb2RlID0gdGV4dE5vZGUucGFyZW50Tm9kZTtcbiAgICAgICAgICBwYXJlbnROb2RlLnJlcGxhY2VDaGlsZChzcGFuLCB0ZXh0Tm9kZSk7XG4gICAgICAgICAgc3Bhbi5hcHBlbmRDaGlsZCh0ZXh0Tm9kZSk7XG4gICAgICAgICAgaWYgKHNvdXJjZUluZGV4IDwgc3BhbkVuZCkgeyAgLy8gU3BsaXQgb2ZmIGEgdGV4dCBub2RlLlxuICAgICAgICAgICAgc3BhbnNbc3BhbkluZGV4ICsgMV0gPSB0ZXh0Tm9kZVxuICAgICAgICAgICAgICAgIC8vIFRPRE86IFBvc3NpYmx5IG9wdGltaXplIGJ5IHVzaW5nICcnIGlmIHRoZXJlJ3Mgbm8gZmxpY2tlci5cbiAgICAgICAgICAgICAgICA9IGRvY3VtZW50LmNyZWF0ZVRleHROb2RlKHNvdXJjZS5zdWJzdHJpbmcoZW5kLCBzcGFuRW5kKSk7XG4gICAgICAgICAgICBwYXJlbnROb2RlLmluc2VydEJlZm9yZSh0ZXh0Tm9kZSwgc3Bhbi5uZXh0U2libGluZyk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gIFxuICAgICAgICBzb3VyY2VJbmRleCA9IGVuZDtcbiAgXG4gICAgICAgIGlmIChzb3VyY2VJbmRleCA+PSBzcGFuRW5kKSB7XG4gICAgICAgICAgc3BhbkluZGV4ICs9IDI7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHNvdXJjZUluZGV4ID49IGRlY0VuZCkge1xuICAgICAgICAgIGRlY29yYXRpb25JbmRleCArPSAyO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIGlmIChzb3VyY2VOb2RlKSB7XG4gICAgICAgIHNvdXJjZU5vZGUuc3R5bGUuZGlzcGxheSA9IG9sZERpc3BsYXk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqIE1hcHMgbGFuZ3VhZ2Utc3BlY2lmaWMgZmlsZSBleHRlbnNpb25zIHRvIGhhbmRsZXJzLiAqL1xuICB2YXIgbGFuZ0hhbmRsZXJSZWdpc3RyeSA9IHt9O1xuICAvKiogUmVnaXN0ZXIgYSBsYW5ndWFnZSBoYW5kbGVyIGZvciB0aGUgZ2l2ZW4gZmlsZSBleHRlbnNpb25zLlxuICAgICogQHBhcmFtIHtmdW5jdGlvbiAoT2JqZWN0KX0gaGFuZGxlciBhIGZ1bmN0aW9uIGZyb20gc291cmNlIGNvZGUgdG8gYSBsaXN0XG4gICAgKiAgICAgIG9mIGRlY29yYXRpb25zLiAgVGFrZXMgYSBzaW5nbGUgYXJndW1lbnQgam9iIHdoaWNoIGRlc2NyaWJlcyB0aGVcbiAgICAqICAgICAgc3RhdGUgb2YgdGhlIGNvbXB1dGF0aW9uLiAgIFRoZSBzaW5nbGUgcGFyYW1ldGVyIGhhcyB0aGUgZm9ybVxuICAgICogICAgICB7QGNvZGUge1xuICAgICogICAgICAgIHNvdXJjZUNvZGU6IHtzdHJpbmd9IGFzIHBsYWluIHRleHQuXG4gICAgKiAgICAgICAgZGVjb3JhdGlvbnM6IHtBcnJheS48bnVtYmVyfHN0cmluZz59IGFuIGFycmF5IG9mIHN0eWxlIGNsYXNzZXNcbiAgICAqICAgICAgICAgICAgICAgICAgICAgcHJlY2VkZWQgYnkgdGhlIHBvc2l0aW9uIGF0IHdoaWNoIHRoZXkgc3RhcnQgaW5cbiAgICAqICAgICAgICAgICAgICAgICAgICAgam9iLnNvdXJjZUNvZGUgaW4gb3JkZXIuXG4gICAgKiAgICAgICAgICAgICAgICAgICAgIFRoZSBsYW5ndWFnZSBoYW5kbGVyIHNob3VsZCBhc3NpZ25lZCB0aGlzIGZpZWxkLlxuICAgICogICAgICAgIGJhc2VQb3M6IHtpbnR9IHRoZSBwb3NpdGlvbiBvZiBzb3VyY2UgaW4gdGhlIGxhcmdlciBzb3VyY2UgY2h1bmsuXG4gICAgKiAgICAgICAgICAgICAgICAgQWxsIHBvc2l0aW9ucyBpbiB0aGUgb3V0cHV0IGRlY29yYXRpb25zIGFycmF5IGFyZSByZWxhdGl2ZVxuICAgICogICAgICAgICAgICAgICAgIHRvIHRoZSBsYXJnZXIgc291cmNlIGNodW5rLlxuICAgICogICAgICB9IH1cbiAgICAqIEBwYXJhbSB7QXJyYXkuPHN0cmluZz59IGZpbGVFeHRlbnNpb25zXG4gICAgKi9cbiAgZnVuY3Rpb24gcmVnaXN0ZXJMYW5nSGFuZGxlcihoYW5kbGVyLCBmaWxlRXh0ZW5zaW9ucykge1xuICAgIGZvciAodmFyIGkgPSBmaWxlRXh0ZW5zaW9ucy5sZW5ndGg7IC0taSA+PSAwOykge1xuICAgICAgdmFyIGV4dCA9IGZpbGVFeHRlbnNpb25zW2ldO1xuICAgICAgaWYgKCFsYW5nSGFuZGxlclJlZ2lzdHJ5Lmhhc093blByb3BlcnR5KGV4dCkpIHtcbiAgICAgICAgbGFuZ0hhbmRsZXJSZWdpc3RyeVtleHRdID0gaGFuZGxlcjtcbiAgICAgIH0gZWxzZSBpZiAod2luWydjb25zb2xlJ10pIHtcbiAgICAgICAgY29uc29sZVsnd2FybiddKCdjYW5ub3Qgb3ZlcnJpZGUgbGFuZ3VhZ2UgaGFuZGxlciAlcycsIGV4dCk7XG4gICAgICB9XG4gICAgfVxuICB9XG4gIGZ1bmN0aW9uIGxhbmdIYW5kbGVyRm9yRXh0ZW5zaW9uKGV4dGVuc2lvbiwgc291cmNlKSB7XG4gICAgaWYgKCEoZXh0ZW5zaW9uICYmIGxhbmdIYW5kbGVyUmVnaXN0cnkuaGFzT3duUHJvcGVydHkoZXh0ZW5zaW9uKSkpIHtcbiAgICAgIC8vIFRyZWF0IGl0IGFzIG1hcmt1cCBpZiB0aGUgZmlyc3Qgbm9uIHdoaXRlc3BhY2UgY2hhcmFjdGVyIGlzIGEgPCBhbmRcbiAgICAgIC8vIHRoZSBsYXN0IG5vbi13aGl0ZXNwYWNlIGNoYXJhY3RlciBpcyBhID4uXG4gICAgICBleHRlbnNpb24gPSAvXlxccyo8Ly50ZXN0KHNvdXJjZSlcbiAgICAgICAgICA/ICdkZWZhdWx0LW1hcmt1cCdcbiAgICAgICAgICA6ICdkZWZhdWx0LWNvZGUnO1xuICAgIH1cbiAgICByZXR1cm4gbGFuZ0hhbmRsZXJSZWdpc3RyeVtleHRlbnNpb25dO1xuICB9XG4gIHJlZ2lzdGVyTGFuZ0hhbmRsZXIoZGVjb3JhdGVTb3VyY2UsIFsnZGVmYXVsdC1jb2RlJ10pO1xuICByZWdpc3RlckxhbmdIYW5kbGVyKFxuICAgICAgY3JlYXRlU2ltcGxlTGV4ZXIoXG4gICAgICAgICAgW10sXG4gICAgICAgICAgW1xuICAgICAgICAgICBbUFJfUExBSU4sICAgICAgIC9eW148P10rL10sXG4gICAgICAgICAgIFtQUl9ERUNMQVJBVElPTiwgL148IVxcd1tePl0qKD86PnwkKS9dLFxuICAgICAgICAgICBbUFJfQ09NTUVOVCwgICAgIC9ePFxcIS0tW1xcc1xcU10qPyg/Oi1cXC0+fCQpL10sXG4gICAgICAgICAgIC8vIFVuZXNjYXBlZCBjb250ZW50IGluIGFuIHVua25vd24gbGFuZ3VhZ2VcbiAgICAgICAgICAgWydsYW5nLScsICAgICAgICAvXjxcXD8oW1xcc1xcU10rPykoPzpcXD8+fCQpL10sXG4gICAgICAgICAgIFsnbGFuZy0nLCAgICAgICAgL148JShbXFxzXFxTXSs/KSg/OiU+fCQpL10sXG4gICAgICAgICAgIFtQUl9QVU5DVFVBVElPTiwgL14oPzo8WyU/XXxbJT9dPikvXSxcbiAgICAgICAgICAgWydsYW5nLScsICAgICAgICAvXjx4bXBcXGJbXj5dKj4oW1xcc1xcU10rPyk8XFwveG1wXFxiW14+XSo+L2ldLFxuICAgICAgICAgICAvLyBVbmVzY2FwZWQgY29udGVudCBpbiBqYXZhc2NyaXB0LiAgKE9yIHBvc3NpYmx5IHZic2NyaXB0KS5cbiAgICAgICAgICAgWydsYW5nLWpzJywgICAgICAvXjxzY3JpcHRcXGJbXj5dKj4oW1xcc1xcU10qPykoPFxcL3NjcmlwdFxcYltePl0qPikvaV0sXG4gICAgICAgICAgIC8vIENvbnRhaW5zIHVuZXNjYXBlZCBzdHlsZXNoZWV0IGNvbnRlbnRcbiAgICAgICAgICAgWydsYW5nLWNzcycsICAgICAvXjxzdHlsZVxcYltePl0qPihbXFxzXFxTXSo/KSg8XFwvc3R5bGVcXGJbXj5dKj4pL2ldLFxuICAgICAgICAgICBbJ2xhbmctaW4udGFnJywgIC9eKDxcXC8/W2Etel1bXjw+XSo+KS9pXVxuICAgICAgICAgIF0pLFxuICAgICAgWydkZWZhdWx0LW1hcmt1cCcsICdodG0nLCAnaHRtbCcsICdteG1sJywgJ3hodG1sJywgJ3htbCcsICd4c2wnXSk7XG4gIHJlZ2lzdGVyTGFuZ0hhbmRsZXIoXG4gICAgICBjcmVhdGVTaW1wbGVMZXhlcihcbiAgICAgICAgICBbXG4gICAgICAgICAgIFtQUl9QTEFJTiwgICAgICAgIC9eW1xcc10rLywgbnVsbCwgJyBcXHRcXHJcXG4nXSxcbiAgICAgICAgICAgW1BSX0FUVFJJQl9WQUxVRSwgL14oPzpcXFwiW15cXFwiXSpcXFwiP3xcXCdbXlxcJ10qXFwnPykvLCBudWxsLCAnXFxcIlxcJyddXG4gICAgICAgICAgIF0sXG4gICAgICAgICAgW1xuICAgICAgICAgICBbUFJfVEFHLCAgICAgICAgICAvXl48XFwvP1thLXpdKD86W1xcdy46LV0qXFx3KT98XFwvPz4kL2ldLFxuICAgICAgICAgICBbUFJfQVRUUklCX05BTUUsICAvXig/IXN0eWxlW1xccz1dfG9uKVthLXpdKD86W1xcdzotXSpcXHcpPy9pXSxcbiAgICAgICAgICAgWydsYW5nLXVxLnZhbCcsICAgL149XFxzKihbXj5cXCdcXFwiXFxzXSooPzpbXj5cXCdcXFwiXFxzXFwvXXxcXC8oPz1cXHMpKSkvXSxcbiAgICAgICAgICAgW1BSX1BVTkNUVUFUSU9OLCAgL15bPTw+XFwvXSsvXSxcbiAgICAgICAgICAgWydsYW5nLWpzJywgICAgICAgL15vblxcdytcXHMqPVxccypcXFwiKFteXFxcIl0rKVxcXCIvaV0sXG4gICAgICAgICAgIFsnbGFuZy1qcycsICAgICAgIC9eb25cXHcrXFxzKj1cXHMqXFwnKFteXFwnXSspXFwnL2ldLFxuICAgICAgICAgICBbJ2xhbmctanMnLCAgICAgICAvXm9uXFx3K1xccyo9XFxzKihbXlxcXCJcXCc+XFxzXSspL2ldLFxuICAgICAgICAgICBbJ2xhbmctY3NzJywgICAgICAvXnN0eWxlXFxzKj1cXHMqXFxcIihbXlxcXCJdKylcXFwiL2ldLFxuICAgICAgICAgICBbJ2xhbmctY3NzJywgICAgICAvXnN0eWxlXFxzKj1cXHMqXFwnKFteXFwnXSspXFwnL2ldLFxuICAgICAgICAgICBbJ2xhbmctY3NzJywgICAgICAvXnN0eWxlXFxzKj1cXHMqKFteXFxcIlxcJz5cXHNdKykvaV1cbiAgICAgICAgICAgXSksXG4gICAgICBbJ2luLnRhZyddKTtcbiAgcmVnaXN0ZXJMYW5nSGFuZGxlcihcbiAgICAgIGNyZWF0ZVNpbXBsZUxleGVyKFtdLCBbW1BSX0FUVFJJQl9WQUxVRSwgL15bXFxzXFxTXSsvXV0pLCBbJ3VxLnZhbCddKTtcbiAgcmVnaXN0ZXJMYW5nSGFuZGxlcihzb3VyY2VEZWNvcmF0b3Ioe1xuICAgICAgICAgICdrZXl3b3Jkcyc6IENQUF9LRVlXT1JEUyxcbiAgICAgICAgICAnaGFzaENvbW1lbnRzJzogdHJ1ZSxcbiAgICAgICAgICAnY1N0eWxlQ29tbWVudHMnOiB0cnVlLFxuICAgICAgICAgICd0eXBlcyc6IENfVFlQRVNcbiAgICAgICAgfSksIFsnYycsICdjYycsICdjcHAnLCAnY3h4JywgJ2N5YycsICdtJ10pO1xuICByZWdpc3RlckxhbmdIYW5kbGVyKHNvdXJjZURlY29yYXRvcih7XG4gICAgICAgICAgJ2tleXdvcmRzJzogJ251bGwsdHJ1ZSxmYWxzZSdcbiAgICAgICAgfSksIFsnanNvbiddKTtcbiAgcmVnaXN0ZXJMYW5nSGFuZGxlcihzb3VyY2VEZWNvcmF0b3Ioe1xuICAgICAgICAgICdrZXl3b3Jkcyc6IENTSEFSUF9LRVlXT1JEUyxcbiAgICAgICAgICAnaGFzaENvbW1lbnRzJzogdHJ1ZSxcbiAgICAgICAgICAnY1N0eWxlQ29tbWVudHMnOiB0cnVlLFxuICAgICAgICAgICd2ZXJiYXRpbVN0cmluZ3MnOiB0cnVlLFxuICAgICAgICAgICd0eXBlcyc6IENfVFlQRVNcbiAgICAgICAgfSksIFsnY3MnXSk7XG4gIHJlZ2lzdGVyTGFuZ0hhbmRsZXIoc291cmNlRGVjb3JhdG9yKHtcbiAgICAgICAgICAna2V5d29yZHMnOiBKQVZBX0tFWVdPUkRTLFxuICAgICAgICAgICdjU3R5bGVDb21tZW50cyc6IHRydWVcbiAgICAgICAgfSksIFsnamF2YSddKTtcbiAgcmVnaXN0ZXJMYW5nSGFuZGxlcihzb3VyY2VEZWNvcmF0b3Ioe1xuICAgICAgICAgICdrZXl3b3Jkcyc6IFNIX0tFWVdPUkRTLFxuICAgICAgICAgICdoYXNoQ29tbWVudHMnOiB0cnVlLFxuICAgICAgICAgICdtdWx0aUxpbmVTdHJpbmdzJzogdHJ1ZVxuICAgICAgICB9KSwgWydiYXNoJywgJ2JzaCcsICdjc2gnLCAnc2gnXSk7XG4gIHJlZ2lzdGVyTGFuZ0hhbmRsZXIoc291cmNlRGVjb3JhdG9yKHtcbiAgICAgICAgICAna2V5d29yZHMnOiBQWVRIT05fS0VZV09SRFMsXG4gICAgICAgICAgJ2hhc2hDb21tZW50cyc6IHRydWUsXG4gICAgICAgICAgJ211bHRpTGluZVN0cmluZ3MnOiB0cnVlLFxuICAgICAgICAgICd0cmlwbGVRdW90ZWRTdHJpbmdzJzogdHJ1ZVxuICAgICAgICB9KSwgWydjdicsICdweScsICdweXRob24nXSk7XG4gIHJlZ2lzdGVyTGFuZ0hhbmRsZXIoc291cmNlRGVjb3JhdG9yKHtcbiAgICAgICAgICAna2V5d29yZHMnOiBQRVJMX0tFWVdPUkRTLFxuICAgICAgICAgICdoYXNoQ29tbWVudHMnOiB0cnVlLFxuICAgICAgICAgICdtdWx0aUxpbmVTdHJpbmdzJzogdHJ1ZSxcbiAgICAgICAgICAncmVnZXhMaXRlcmFscyc6IDIgIC8vIG11bHRpbGluZSByZWdleCBsaXRlcmFsc1xuICAgICAgICB9KSwgWydwZXJsJywgJ3BsJywgJ3BtJ10pO1xuICByZWdpc3RlckxhbmdIYW5kbGVyKHNvdXJjZURlY29yYXRvcih7XG4gICAgICAgICAgJ2tleXdvcmRzJzogUlVCWV9LRVlXT1JEUyxcbiAgICAgICAgICAnaGFzaENvbW1lbnRzJzogdHJ1ZSxcbiAgICAgICAgICAnbXVsdGlMaW5lU3RyaW5ncyc6IHRydWUsXG4gICAgICAgICAgJ3JlZ2V4TGl0ZXJhbHMnOiB0cnVlXG4gICAgICAgIH0pLCBbJ3JiJywgJ3J1YnknXSk7XG4gIHJlZ2lzdGVyTGFuZ0hhbmRsZXIoc291cmNlRGVjb3JhdG9yKHtcbiAgICAgICAgICAna2V5d29yZHMnOiBKU0NSSVBUX0tFWVdPUkRTLFxuICAgICAgICAgICdjU3R5bGVDb21tZW50cyc6IHRydWUsXG4gICAgICAgICAgJ3JlZ2V4TGl0ZXJhbHMnOiB0cnVlXG4gICAgICAgIH0pLCBbJ2phdmFzY3JpcHQnLCAnanMnXSk7XG4gIHJlZ2lzdGVyTGFuZ0hhbmRsZXIoc291cmNlRGVjb3JhdG9yKHtcbiAgICAgICAgICAna2V5d29yZHMnOiBDT0ZGRUVfS0VZV09SRFMsXG4gICAgICAgICAgJ2hhc2hDb21tZW50cyc6IDMsICAvLyAjIyMgc3R5bGUgYmxvY2sgY29tbWVudHNcbiAgICAgICAgICAnY1N0eWxlQ29tbWVudHMnOiB0cnVlLFxuICAgICAgICAgICdtdWx0aWxpbmVTdHJpbmdzJzogdHJ1ZSxcbiAgICAgICAgICAndHJpcGxlUXVvdGVkU3RyaW5ncyc6IHRydWUsXG4gICAgICAgICAgJ3JlZ2V4TGl0ZXJhbHMnOiB0cnVlXG4gICAgICAgIH0pLCBbJ2NvZmZlZSddKTtcbiAgcmVnaXN0ZXJMYW5nSGFuZGxlcihzb3VyY2VEZWNvcmF0b3Ioe1xuICAgICAgICAgICdrZXl3b3Jkcyc6IFJVU1RfS0VZV09SRFMsXG4gICAgICAgICAgJ2NTdHlsZUNvbW1lbnRzJzogdHJ1ZSxcbiAgICAgICAgICAnbXVsdGlsaW5lU3RyaW5ncyc6IHRydWVcbiAgICAgICAgfSksIFsncmMnLCAncnMnLCAncnVzdCddKTtcbiAgcmVnaXN0ZXJMYW5nSGFuZGxlcihcbiAgICAgIGNyZWF0ZVNpbXBsZUxleGVyKFtdLCBbW1BSX1NUUklORywgL15bXFxzXFxTXSsvXV0pLCBbJ3JlZ2V4J10pO1xuXG4gIGZ1bmN0aW9uIGFwcGx5RGVjb3JhdG9yKGpvYikge1xuICAgIHZhciBvcHRfbGFuZ0V4dGVuc2lvbiA9IGpvYi5sYW5nRXh0ZW5zaW9uO1xuXG4gICAgdHJ5IHtcbiAgICAgIC8vIEV4dHJhY3QgdGFncywgYW5kIGNvbnZlcnQgdGhlIHNvdXJjZSBjb2RlIHRvIHBsYWluIHRleHQuXG4gICAgICB2YXIgc291cmNlQW5kU3BhbnMgPSBleHRyYWN0U291cmNlU3BhbnMoam9iLnNvdXJjZU5vZGUsIGpvYi5wcmUpO1xuICAgICAgLyoqIFBsYWluIHRleHQuIEB0eXBlIHtzdHJpbmd9ICovXG4gICAgICB2YXIgc291cmNlID0gc291cmNlQW5kU3BhbnMuc291cmNlQ29kZTtcbiAgICAgIGpvYi5zb3VyY2VDb2RlID0gc291cmNlO1xuICAgICAgam9iLnNwYW5zID0gc291cmNlQW5kU3BhbnMuc3BhbnM7XG4gICAgICBqb2IuYmFzZVBvcyA9IDA7XG5cbiAgICAgIC8vIEFwcGx5IHRoZSBhcHByb3ByaWF0ZSBsYW5ndWFnZSBoYW5kbGVyXG4gICAgICBsYW5nSGFuZGxlckZvckV4dGVuc2lvbihvcHRfbGFuZ0V4dGVuc2lvbiwgc291cmNlKShqb2IpO1xuXG4gICAgICAvLyBJbnRlZ3JhdGUgdGhlIGRlY29yYXRpb25zIGFuZCB0YWdzIGJhY2sgaW50byB0aGUgc291cmNlIGNvZGUsXG4gICAgICAvLyBtb2RpZnlpbmcgdGhlIHNvdXJjZU5vZGUgaW4gcGxhY2UuXG4gICAgICByZWNvbWJpbmVUYWdzQW5kRGVjb3JhdGlvbnMoam9iKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAod2luWydjb25zb2xlJ10pIHtcbiAgICAgICAgY29uc29sZVsnbG9nJ10oZSAmJiBlWydzdGFjayddIHx8IGUpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBQcmV0dHkgcHJpbnQgYSBjaHVuayBvZiBjb2RlLlxuICAgKiBAcGFyYW0gc291cmNlQ29kZUh0bWwge3N0cmluZ30gVGhlIEhUTUwgdG8gcHJldHR5IHByaW50LlxuICAgKiBAcGFyYW0gb3B0X2xhbmdFeHRlbnNpb24ge3N0cmluZ30gVGhlIGxhbmd1YWdlIG5hbWUgdG8gdXNlLlxuICAgKiAgICAgVHlwaWNhbGx5LCBhIGZpbGVuYW1lIGV4dGVuc2lvbiBsaWtlICdjcHAnIG9yICdqYXZhJy5cbiAgICogQHBhcmFtIG9wdF9udW1iZXJMaW5lcyB7bnVtYmVyfGJvb2xlYW59IFRydWUgdG8gbnVtYmVyIGxpbmVzLFxuICAgKiAgICAgb3IgdGhlIDEtaW5kZXhlZCBudW1iZXIgb2YgdGhlIGZpcnN0IGxpbmUgaW4gc291cmNlQ29kZUh0bWwuXG4gICAqL1xuICBmdW5jdGlvbiAkcHJldHR5UHJpbnRPbmUoc291cmNlQ29kZUh0bWwsIG9wdF9sYW5nRXh0ZW5zaW9uLCBvcHRfbnVtYmVyTGluZXMpIHtcbiAgICB2YXIgY29udGFpbmVyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgLy8gVGhpcyBjb3VsZCBjYXVzZSBpbWFnZXMgdG8gbG9hZCBhbmQgb25sb2FkIGxpc3RlbmVycyB0byBmaXJlLlxuICAgIC8vIEUuZy4gPGltZyBvbmVycm9yPVwiYWxlcnQoMTMzNylcIiBzcmM9XCJub3N1Y2hpbWFnZS5wbmdcIj4uXG4gICAgLy8gV2UgYXNzdW1lIHRoYXQgdGhlIGlubmVyIEhUTUwgaXMgZnJvbSBhIHRydXN0ZWQgc291cmNlLlxuICAgIC8vIFRoZSBwcmUtdGFnIGlzIHJlcXVpcmVkIGZvciBJRTggd2hpY2ggc3RyaXBzIG5ld2xpbmVzIGZyb20gaW5uZXJIVE1MXG4gICAgLy8gd2hlbiBpdCBpcyBpbmplY3RlZCBpbnRvIGEgPHByZT4gdGFnLlxuICAgIC8vIGh0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvNDUxNDg2L3ByZS10YWctbG9zZXMtbGluZS1icmVha3Mtd2hlbi1zZXR0aW5nLWlubmVyaHRtbC1pbi1pZVxuICAgIC8vIGh0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMTk1MzYzL2luc2VydGluZy1hLW5ld2xpbmUtaW50by1hLXByZS10YWctaWUtamF2YXNjcmlwdFxuICAgIGNvbnRhaW5lci5pbm5lckhUTUwgPSAnPHByZT4nICsgc291cmNlQ29kZUh0bWwgKyAnPC9wcmU+JztcbiAgICBjb250YWluZXIgPSBjb250YWluZXIuZmlyc3RDaGlsZDtcbiAgICBpZiAob3B0X251bWJlckxpbmVzKSB7XG4gICAgICBudW1iZXJMaW5lcyhjb250YWluZXIsIG9wdF9udW1iZXJMaW5lcywgdHJ1ZSk7XG4gICAgfVxuXG4gICAgdmFyIGpvYiA9IHtcbiAgICAgIGxhbmdFeHRlbnNpb246IG9wdF9sYW5nRXh0ZW5zaW9uLFxuICAgICAgbnVtYmVyTGluZXM6IG9wdF9udW1iZXJMaW5lcyxcbiAgICAgIHNvdXJjZU5vZGU6IGNvbnRhaW5lcixcbiAgICAgIHByZTogMVxuICAgIH07XG4gICAgYXBwbHlEZWNvcmF0b3Ioam9iKTtcbiAgICByZXR1cm4gY29udGFpbmVyLmlubmVySFRNTDtcbiAgfVxuXG4gICAvKipcbiAgICAqIEZpbmQgYWxsIHRoZSB7QGNvZGUgPHByZT59IGFuZCB7QGNvZGUgPGNvZGU+fSB0YWdzIGluIHRoZSBET00gd2l0aFxuICAgICoge0Bjb2RlIGNsYXNzPXByZXR0eXByaW50fSBhbmQgcHJldHRpZnkgdGhlbS5cbiAgICAqXG4gICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBvcHRfd2hlbkRvbmUgY2FsbGVkIHdoZW4gcHJldHRpZnlpbmcgaXMgZG9uZS5cbiAgICAqIEBwYXJhbSB7SFRNTEVsZW1lbnR8SFRNTERvY3VtZW50fSBvcHRfcm9vdCBhbiBlbGVtZW50IG9yIGRvY3VtZW50XG4gICAgKiAgIGNvbnRhaW5pbmcgYWxsIHRoZSBlbGVtZW50cyB0byBwcmV0dHkgcHJpbnQuXG4gICAgKiAgIERlZmF1bHRzIHRvIHtAY29kZSBkb2N1bWVudC5ib2R5fS5cbiAgICAqL1xuICBmdW5jdGlvbiAkcHJldHR5UHJpbnQob3B0X3doZW5Eb25lLCBvcHRfcm9vdCkge1xuICAgIHZhciByb290ID0gb3B0X3Jvb3QgfHwgZG9jdW1lbnQuYm9keTtcbiAgICB2YXIgZG9jID0gcm9vdC5vd25lckRvY3VtZW50IHx8IGRvY3VtZW50O1xuICAgIGZ1bmN0aW9uIGJ5VGFnTmFtZSh0bikgeyByZXR1cm4gcm9vdC5nZXRFbGVtZW50c0J5VGFnTmFtZSh0bik7IH1cbiAgICAvLyBmZXRjaCBhIGxpc3Qgb2Ygbm9kZXMgdG8gcmV3cml0ZVxuICAgIHZhciBjb2RlU2VnbWVudHMgPSBbYnlUYWdOYW1lKCdwcmUnKSwgYnlUYWdOYW1lKCdjb2RlJyksIGJ5VGFnTmFtZSgneG1wJyldO1xuICAgIHZhciBlbGVtZW50cyA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY29kZVNlZ21lbnRzLmxlbmd0aDsgKytpKSB7XG4gICAgICBmb3IgKHZhciBqID0gMCwgbiA9IGNvZGVTZWdtZW50c1tpXS5sZW5ndGg7IGogPCBuOyArK2opIHtcbiAgICAgICAgZWxlbWVudHMucHVzaChjb2RlU2VnbWVudHNbaV1bal0pO1xuICAgICAgfVxuICAgIH1cbiAgICBjb2RlU2VnbWVudHMgPSBudWxsO1xuXG4gICAgdmFyIGNsb2NrID0gRGF0ZTtcbiAgICBpZiAoIWNsb2NrWydub3cnXSkge1xuICAgICAgY2xvY2sgPSB7ICdub3cnOiBmdW5jdGlvbiAoKSB7IHJldHVybiArKG5ldyBEYXRlKTsgfSB9O1xuICAgIH1cblxuICAgIC8vIFRoZSBsb29wIGlzIGJyb2tlbiBpbnRvIGEgc2VyaWVzIG9mIGNvbnRpbnVhdGlvbnMgdG8gbWFrZSBzdXJlIHRoYXQgd2VcbiAgICAvLyBkb24ndCBtYWtlIHRoZSBicm93c2VyIHVucmVzcG9uc2l2ZSB3aGVuIHJld3JpdGluZyBhIGxhcmdlIHBhZ2UuXG4gICAgdmFyIGsgPSAwO1xuICAgIHZhciBwcmV0dHlQcmludGluZ0pvYjtcblxuICAgIHZhciBsYW5nRXh0ZW5zaW9uUmUgPSAvXFxibGFuZyg/OnVhZ2UpPy0oW1xcdy5dKykoPyFcXFMpLztcbiAgICB2YXIgcHJldHR5UHJpbnRSZSA9IC9cXGJwcmV0dHlwcmludFxcYi87XG4gICAgdmFyIHByZXR0eVByaW50ZWRSZSA9IC9cXGJwcmV0dHlwcmludGVkXFxiLztcbiAgICB2YXIgcHJlZm9ybWF0dGVkVGFnTmFtZVJlID0gL3ByZXx4bXAvaTtcbiAgICB2YXIgY29kZVJlID0gL15jb2RlJC9pO1xuICAgIHZhciBwcmVDb2RlWG1wUmUgPSAvXig/OnByZXxjb2RlfHhtcCkkL2k7XG4gICAgdmFyIEVNUFRZID0ge307XG5cbiAgICBmdW5jdGlvbiBkb1dvcmsoKSB7XG4gICAgICB2YXIgZW5kVGltZSA9ICh3aW5bJ1BSX1NIT1VMRF9VU0VfQ09OVElOVUFUSU9OJ10gP1xuICAgICAgICAgICAgICAgICAgICAgY2xvY2tbJ25vdyddKCkgKyAyNTAgLyogbXMgKi8gOlxuICAgICAgICAgICAgICAgICAgICAgSW5maW5pdHkpO1xuICAgICAgZm9yICg7IGsgPCBlbGVtZW50cy5sZW5ndGggJiYgY2xvY2tbJ25vdyddKCkgPCBlbmRUaW1lOyBrKyspIHtcbiAgICAgICAgdmFyIGNzID0gZWxlbWVudHNba107XG5cbiAgICAgICAgLy8gTG9vayBmb3IgYSBwcmVjZWRpbmcgY29tbWVudCBsaWtlXG4gICAgICAgIC8vIDw/cHJldHRpZnkgbGFuZz1cIi4uLlwiIGxpbmVudW1zPVwiLi4uXCI/PlxuICAgICAgICB2YXIgYXR0cnMgPSBFTVBUWTtcbiAgICAgICAge1xuICAgICAgICAgIGZvciAodmFyIHByZWNlZGVyID0gY3M7IChwcmVjZWRlciA9IHByZWNlZGVyLnByZXZpb3VzU2libGluZyk7KSB7XG4gICAgICAgICAgICB2YXIgbnQgPSBwcmVjZWRlci5ub2RlVHlwZTtcbiAgICAgICAgICAgIC8vIDw/Zm9vPz4gaXMgcGFyc2VkIGJ5IEhUTUwgNSB0byBhIGNvbW1lbnQgbm9kZSAoOClcbiAgICAgICAgICAgIC8vIGxpa2UgPCEtLT9mb28/LS0+LCBidXQgaW4gWE1MIGlzIGEgcHJvY2Vzc2luZyBpbnN0cnVjdGlvblxuICAgICAgICAgICAgdmFyIHZhbHVlID0gKG50ID09PSA3IHx8IG50ID09PSA4KSAmJiBwcmVjZWRlci5ub2RlVmFsdWU7XG4gICAgICAgICAgICBpZiAodmFsdWVcbiAgICAgICAgICAgICAgICA/ICEvXlxcPz9wcmV0dGlmeVxcYi8udGVzdCh2YWx1ZSlcbiAgICAgICAgICAgICAgICA6IChudCAhPT0gMyB8fCAvXFxTLy50ZXN0KHByZWNlZGVyLm5vZGVWYWx1ZSkpKSB7XG4gICAgICAgICAgICAgIC8vIFNraXAgb3ZlciB3aGl0ZS1zcGFjZSB0ZXh0IG5vZGVzIGJ1dCBub3Qgb3RoZXJzLlxuICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh2YWx1ZSkge1xuICAgICAgICAgICAgICBhdHRycyA9IHt9O1xuICAgICAgICAgICAgICB2YWx1ZS5yZXBsYWNlKFxuICAgICAgICAgICAgICAgICAgL1xcYihcXHcrKT0oW1xcdzouJSstXSspL2csXG4gICAgICAgICAgICAgICAgZnVuY3Rpb24gKF8sIG5hbWUsIHZhbHVlKSB7IGF0dHJzW25hbWVdID0gdmFsdWU7IH0pO1xuICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgY2xhc3NOYW1lID0gY3MuY2xhc3NOYW1lO1xuICAgICAgICBpZiAoKGF0dHJzICE9PSBFTVBUWSB8fCBwcmV0dHlQcmludFJlLnRlc3QoY2xhc3NOYW1lKSlcbiAgICAgICAgICAgIC8vIERvbid0IHJlZG8gdGhpcyBpZiB3ZSd2ZSBhbHJlYWR5IGRvbmUgaXQuXG4gICAgICAgICAgICAvLyBUaGlzIGFsbG93cyByZWNhbGxpbmcgcHJldHR5IHByaW50IHRvIGp1c3QgcHJldHR5cHJpbnQgZWxlbWVudHNcbiAgICAgICAgICAgIC8vIHRoYXQgaGF2ZSBiZWVuIGFkZGVkIHRvIHRoZSBwYWdlIHNpbmNlIGxhc3QgY2FsbC5cbiAgICAgICAgICAgICYmICFwcmV0dHlQcmludGVkUmUudGVzdChjbGFzc05hbWUpKSB7XG5cbiAgICAgICAgICAvLyBtYWtlIHN1cmUgdGhpcyBpcyBub3QgbmVzdGVkIGluIGFuIGFscmVhZHkgcHJldHRpZmllZCBlbGVtZW50XG4gICAgICAgICAgdmFyIG5lc3RlZCA9IGZhbHNlO1xuICAgICAgICAgIGZvciAodmFyIHAgPSBjcy5wYXJlbnROb2RlOyBwOyBwID0gcC5wYXJlbnROb2RlKSB7XG4gICAgICAgICAgICB2YXIgdG4gPSBwLnRhZ05hbWU7XG4gICAgICAgICAgICBpZiAocHJlQ29kZVhtcFJlLnRlc3QodG4pXG4gICAgICAgICAgICAgICAgJiYgcC5jbGFzc05hbWUgJiYgcHJldHR5UHJpbnRSZS50ZXN0KHAuY2xhc3NOYW1lKSkge1xuICAgICAgICAgICAgICBuZXN0ZWQgPSB0cnVlO1xuICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKCFuZXN0ZWQpIHtcbiAgICAgICAgICAgIC8vIE1hcmsgZG9uZS4gIElmIHdlIGZhaWwgdG8gcHJldHR5cHJpbnQgZm9yIHdoYXRldmVyIHJlYXNvbixcbiAgICAgICAgICAgIC8vIHdlIHNob3VsZG4ndCB0cnkgYWdhaW4uXG4gICAgICAgICAgICBjcy5jbGFzc05hbWUgKz0gJyBwcmV0dHlwcmludGVkJztcblxuICAgICAgICAgICAgLy8gSWYgdGhlIGNsYXNzZXMgaW5jbHVkZXMgYSBsYW5ndWFnZSBleHRlbnNpb25zLCB1c2UgaXQuXG4gICAgICAgICAgICAvLyBMYW5ndWFnZSBleHRlbnNpb25zIGNhbiBiZSBzcGVjaWZpZWQgbGlrZVxuICAgICAgICAgICAgLy8gICAgIDxwcmUgY2xhc3M9XCJwcmV0dHlwcmludCBsYW5nLWNwcFwiPlxuICAgICAgICAgICAgLy8gdGhlIGxhbmd1YWdlIGV4dGVuc2lvbiBcImNwcFwiIGlzIHVzZWQgdG8gZmluZCBhIGxhbmd1YWdlIGhhbmRsZXJcbiAgICAgICAgICAgIC8vIGFzIHBhc3NlZCB0byBQUi5yZWdpc3RlckxhbmdIYW5kbGVyLlxuICAgICAgICAgICAgLy8gSFRNTDUgcmVjb21tZW5kcyB0aGF0IGEgbGFuZ3VhZ2UgYmUgc3BlY2lmaWVkIHVzaW5nIFwibGFuZ3VhZ2UtXCJcbiAgICAgICAgICAgIC8vIGFzIHRoZSBwcmVmaXggaW5zdGVhZC4gIEdvb2dsZSBDb2RlIFByZXR0aWZ5IHN1cHBvcnRzIGJvdGguXG4gICAgICAgICAgICAvLyBodHRwOi8vZGV2LnczLm9yZy9odG1sNS9zcGVjLWF1dGhvci12aWV3L3RoZS1jb2RlLWVsZW1lbnQuaHRtbFxuICAgICAgICAgICAgdmFyIGxhbmdFeHRlbnNpb24gPSBhdHRyc1snbGFuZyddO1xuICAgICAgICAgICAgaWYgKCFsYW5nRXh0ZW5zaW9uKSB7XG4gICAgICAgICAgICAgIGxhbmdFeHRlbnNpb24gPSBjbGFzc05hbWUubWF0Y2gobGFuZ0V4dGVuc2lvblJlKTtcbiAgICAgICAgICAgICAgLy8gU3VwcG9ydCA8cHJlIGNsYXNzPVwicHJldHR5cHJpbnRcIj48Y29kZSBjbGFzcz1cImxhbmd1YWdlLWNcIj5cbiAgICAgICAgICAgICAgdmFyIHdyYXBwZXI7XG4gICAgICAgICAgICAgIGlmICghbGFuZ0V4dGVuc2lvbiAmJiAod3JhcHBlciA9IGNoaWxkQ29udGVudFdyYXBwZXIoY3MpKVxuICAgICAgICAgICAgICAgICAgJiYgY29kZVJlLnRlc3Qod3JhcHBlci50YWdOYW1lKSkge1xuICAgICAgICAgICAgICAgIGxhbmdFeHRlbnNpb24gPSB3cmFwcGVyLmNsYXNzTmFtZS5tYXRjaChsYW5nRXh0ZW5zaW9uUmUpO1xuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgaWYgKGxhbmdFeHRlbnNpb24pIHsgbGFuZ0V4dGVuc2lvbiA9IGxhbmdFeHRlbnNpb25bMV07IH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdmFyIHByZWZvcm1hdHRlZDtcbiAgICAgICAgICAgIGlmIChwcmVmb3JtYXR0ZWRUYWdOYW1lUmUudGVzdChjcy50YWdOYW1lKSkge1xuICAgICAgICAgICAgICBwcmVmb3JtYXR0ZWQgPSAxO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgdmFyIGN1cnJlbnRTdHlsZSA9IGNzWydjdXJyZW50U3R5bGUnXTtcbiAgICAgICAgICAgICAgdmFyIGRlZmF1bHRWaWV3ID0gZG9jLmRlZmF1bHRWaWV3O1xuICAgICAgICAgICAgICB2YXIgd2hpdGVzcGFjZSA9IChcbiAgICAgICAgICAgICAgICAgIGN1cnJlbnRTdHlsZVxuICAgICAgICAgICAgICAgICAgPyBjdXJyZW50U3R5bGVbJ3doaXRlU3BhY2UnXVxuICAgICAgICAgICAgICAgICAgOiAoZGVmYXVsdFZpZXdcbiAgICAgICAgICAgICAgICAgICAgICYmIGRlZmF1bHRWaWV3LmdldENvbXB1dGVkU3R5bGUpXG4gICAgICAgICAgICAgICAgICA/IGRlZmF1bHRWaWV3LmdldENvbXB1dGVkU3R5bGUoY3MsIG51bGwpXG4gICAgICAgICAgICAgICAgICAuZ2V0UHJvcGVydHlWYWx1ZSgnd2hpdGUtc3BhY2UnKVxuICAgICAgICAgICAgICAgICAgOiAwKTtcbiAgICAgICAgICAgICAgcHJlZm9ybWF0dGVkID0gd2hpdGVzcGFjZVxuICAgICAgICAgICAgICAgICAgJiYgJ3ByZScgPT09IHdoaXRlc3BhY2Uuc3Vic3RyaW5nKDAsIDMpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBMb29rIGZvciBhIGNsYXNzIGxpa2UgbGluZW51bXMgb3IgbGluZW51bXM6PG4+IHdoZXJlIDxuPiBpcyB0aGVcbiAgICAgICAgICAgIC8vIDEtaW5kZXhlZCBudW1iZXIgb2YgdGhlIGZpcnN0IGxpbmUuXG4gICAgICAgICAgICB2YXIgbGluZU51bXMgPSBhdHRyc1snbGluZW51bXMnXTtcbiAgICAgICAgICAgIGlmICghKGxpbmVOdW1zID0gbGluZU51bXMgPT09ICd0cnVlJyB8fCArbGluZU51bXMpKSB7XG4gICAgICAgICAgICAgIGxpbmVOdW1zID0gY2xhc3NOYW1lLm1hdGNoKC9cXGJsaW5lbnVtc1xcYig/OjooXFxkKykpPy8pO1xuICAgICAgICAgICAgICBsaW5lTnVtcyA9XG4gICAgICAgICAgICAgICAgbGluZU51bXNcbiAgICAgICAgICAgICAgICA/IGxpbmVOdW1zWzFdICYmIGxpbmVOdW1zWzFdLmxlbmd0aFxuICAgICAgICAgICAgICAgICAgPyArbGluZU51bXNbMV0gOiB0cnVlXG4gICAgICAgICAgICAgICAgOiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChsaW5lTnVtcykgeyBudW1iZXJMaW5lcyhjcywgbGluZU51bXMsIHByZWZvcm1hdHRlZCk7IH1cblxuICAgICAgICAgICAgLy8gZG8gdGhlIHByZXR0eSBwcmludGluZ1xuICAgICAgICAgICAgcHJldHR5UHJpbnRpbmdKb2IgPSB7XG4gICAgICAgICAgICAgIGxhbmdFeHRlbnNpb246IGxhbmdFeHRlbnNpb24sXG4gICAgICAgICAgICAgIHNvdXJjZU5vZGU6IGNzLFxuICAgICAgICAgICAgICBudW1iZXJMaW5lczogbGluZU51bXMsXG4gICAgICAgICAgICAgIHByZTogcHJlZm9ybWF0dGVkXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgYXBwbHlEZWNvcmF0b3IocHJldHR5UHJpbnRpbmdKb2IpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKGsgPCBlbGVtZW50cy5sZW5ndGgpIHtcbiAgICAgICAgLy8gZmluaXNoIHVwIGluIGEgY29udGludWF0aW9uXG4gICAgICAgIHNldFRpbWVvdXQoZG9Xb3JrLCAyNTApO1xuICAgICAgfSBlbHNlIGlmICgnZnVuY3Rpb24nID09PSB0eXBlb2Ygb3B0X3doZW5Eb25lKSB7XG4gICAgICAgIG9wdF93aGVuRG9uZSgpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGRvV29yaygpO1xuICB9XG5cbiAgLyoqXG4gICAqIENvbnRhaW5zIGZ1bmN0aW9ucyBmb3IgY3JlYXRpbmcgYW5kIHJlZ2lzdGVyaW5nIG5ldyBsYW5ndWFnZSBoYW5kbGVycy5cbiAgICogQHR5cGUge09iamVjdH1cbiAgICovXG4gIHZhciBQUiA9IHdpblsnUFInXSA9IHtcbiAgICAgICAgJ2NyZWF0ZVNpbXBsZUxleGVyJzogY3JlYXRlU2ltcGxlTGV4ZXIsXG4gICAgICAgICdyZWdpc3RlckxhbmdIYW5kbGVyJzogcmVnaXN0ZXJMYW5nSGFuZGxlcixcbiAgICAgICAgJ3NvdXJjZURlY29yYXRvcic6IHNvdXJjZURlY29yYXRvcixcbiAgICAgICAgJ1BSX0FUVFJJQl9OQU1FJzogUFJfQVRUUklCX05BTUUsXG4gICAgICAgICdQUl9BVFRSSUJfVkFMVUUnOiBQUl9BVFRSSUJfVkFMVUUsXG4gICAgICAgICdQUl9DT01NRU5UJzogUFJfQ09NTUVOVCxcbiAgICAgICAgJ1BSX0RFQ0xBUkFUSU9OJzogUFJfREVDTEFSQVRJT04sXG4gICAgICAgICdQUl9LRVlXT1JEJzogUFJfS0VZV09SRCxcbiAgICAgICAgJ1BSX0xJVEVSQUwnOiBQUl9MSVRFUkFMLFxuICAgICAgICAnUFJfTk9DT0RFJzogUFJfTk9DT0RFLFxuICAgICAgICAnUFJfUExBSU4nOiBQUl9QTEFJTixcbiAgICAgICAgJ1BSX1BVTkNUVUFUSU9OJzogUFJfUFVOQ1RVQVRJT04sXG4gICAgICAgICdQUl9TT1VSQ0UnOiBQUl9TT1VSQ0UsXG4gICAgICAgICdQUl9TVFJJTkcnOiBQUl9TVFJJTkcsXG4gICAgICAgICdQUl9UQUcnOiBQUl9UQUcsXG4gICAgICAgICdQUl9UWVBFJzogUFJfVFlQRSxcbiAgICAgICAgJ3ByZXR0eVByaW50T25lJzpcbiAgICAgICAgICAgSU5fR0xPQkFMX1NDT1BFXG4gICAgICAgICAgICAgPyAod2luWydwcmV0dHlQcmludE9uZSddID0gJHByZXR0eVByaW50T25lKVxuICAgICAgICAgICAgIDogKHByZXR0eVByaW50T25lID0gJHByZXR0eVByaW50T25lKSxcbiAgICAgICAgJ3ByZXR0eVByaW50JzogcHJldHR5UHJpbnQgPVxuICAgICAgICAgICBJTl9HTE9CQUxfU0NPUEVcbiAgICAgICAgICAgICA/ICh3aW5bJ3ByZXR0eVByaW50J10gPSAkcHJldHR5UHJpbnQpXG4gICAgICAgICAgICAgOiAocHJldHR5UHJpbnQgPSAkcHJldHR5UHJpbnQpXG4gICAgICB9O1xuXG4gIC8vIE1ha2UgUFIgYXZhaWxhYmxlIHZpYSB0aGUgQXN5bmNocm9ub3VzIE1vZHVsZSBEZWZpbml0aW9uIChBTUQpIEFQSS5cbiAgLy8gUGVyIGh0dHBzOi8vZ2l0aHViLmNvbS9hbWRqcy9hbWRqcy1hcGkvd2lraS9BTUQ6XG4gIC8vIFRoZSBBc3luY2hyb25vdXMgTW9kdWxlIERlZmluaXRpb24gKEFNRCkgQVBJIHNwZWNpZmllcyBhXG4gIC8vIG1lY2hhbmlzbSBmb3IgZGVmaW5pbmcgbW9kdWxlcyBzdWNoIHRoYXQgdGhlIG1vZHVsZSBhbmQgaXRzXG4gIC8vIGRlcGVuZGVuY2llcyBjYW4gYmUgYXN5bmNocm9ub3VzbHkgbG9hZGVkLlxuICAvLyAuLi5cbiAgLy8gVG8gYWxsb3cgYSBjbGVhciBpbmRpY2F0b3IgdGhhdCBhIGdsb2JhbCBkZWZpbmUgZnVuY3Rpb24gKGFzXG4gIC8vIG5lZWRlZCBmb3Igc2NyaXB0IHNyYyBicm93c2VyIGxvYWRpbmcpIGNvbmZvcm1zIHRvIHRoZSBBTUQgQVBJLFxuICAvLyBhbnkgZ2xvYmFsIGRlZmluZSBmdW5jdGlvbiBTSE9VTEQgaGF2ZSBhIHByb3BlcnR5IGNhbGxlZCBcImFtZFwiXG4gIC8vIHdob3NlIHZhbHVlIGlzIGFuIG9iamVjdC4gVGhpcyBoZWxwcyBhdm9pZCBjb25mbGljdCB3aXRoIGFueVxuICAvLyBvdGhlciBleGlzdGluZyBKYXZhU2NyaXB0IGNvZGUgdGhhdCBjb3VsZCBoYXZlIGRlZmluZWQgYSBkZWZpbmUoKVxuICAvLyBmdW5jdGlvbiB0aGF0IGRvZXMgbm90IGNvbmZvcm0gdG8gdGhlIEFNRCBBUEkuXG4gIGlmICh0eXBlb2YgZGVmaW5lID09PSBcImZ1bmN0aW9uXCIgJiYgZGVmaW5lWydhbWQnXSkge1xuICAgIGRlZmluZShcImdvb2dsZS1jb2RlLXByZXR0aWZ5XCIsIFtdLCBmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gUFI7IFxuICAgIH0pO1xuICB9XG59KSgpO1xuIiwiOyhmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG4gICAgdHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnID8gbW9kdWxlLmV4cG9ydHMgPSBmYWN0b3J5KCkgOlxuICAgIHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShmYWN0b3J5KSA6XG4gICAgZ2xvYmFsLm1vbWVudCA9IGZhY3RvcnkoKVxufSh0aGlzLCAoZnVuY3Rpb24gKCkgeyAndXNlIHN0cmljdCc7XG5cbnZhciBob29rQ2FsbGJhY2s7XG5cbmZ1bmN0aW9uIGhvb2tzICgpIHtcbiAgICByZXR1cm4gaG9va0NhbGxiYWNrLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7XG59XG5cbi8vIFRoaXMgaXMgZG9uZSB0byByZWdpc3RlciB0aGUgbWV0aG9kIGNhbGxlZCB3aXRoIG1vbWVudCgpXG4vLyB3aXRob3V0IGNyZWF0aW5nIGNpcmN1bGFyIGRlcGVuZGVuY2llcy5cbmZ1bmN0aW9uIHNldEhvb2tDYWxsYmFjayAoY2FsbGJhY2spIHtcbiAgICBob29rQ2FsbGJhY2sgPSBjYWxsYmFjaztcbn1cblxuZnVuY3Rpb24gaXNBcnJheShpbnB1dCkge1xuICAgIHJldHVybiBpbnB1dCBpbnN0YW5jZW9mIEFycmF5IHx8IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChpbnB1dCkgPT09ICdbb2JqZWN0IEFycmF5XSc7XG59XG5cbmZ1bmN0aW9uIGlzT2JqZWN0KGlucHV0KSB7XG4gICAgLy8gSUU4IHdpbGwgdHJlYXQgdW5kZWZpbmVkIGFuZCBudWxsIGFzIG9iamVjdCBpZiBpdCB3YXNuJ3QgZm9yXG4gICAgLy8gaW5wdXQgIT0gbnVsbFxuICAgIHJldHVybiBpbnB1dCAhPSBudWxsICYmIE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChpbnB1dCkgPT09ICdbb2JqZWN0IE9iamVjdF0nO1xufVxuXG5mdW5jdGlvbiBpc09iamVjdEVtcHR5KG9iaikge1xuICAgIGlmIChPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcykge1xuICAgICAgICByZXR1cm4gKE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKG9iaikubGVuZ3RoID09PSAwKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICB2YXIgaztcbiAgICAgICAgZm9yIChrIGluIG9iaikge1xuICAgICAgICAgICAgaWYgKG9iai5oYXNPd25Qcm9wZXJ0eShrKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGlzVW5kZWZpbmVkKGlucHV0KSB7XG4gICAgcmV0dXJuIGlucHV0ID09PSB2b2lkIDA7XG59XG5cbmZ1bmN0aW9uIGlzTnVtYmVyKGlucHV0KSB7XG4gICAgcmV0dXJuIHR5cGVvZiBpbnB1dCA9PT0gJ251bWJlcicgfHwgT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKGlucHV0KSA9PT0gJ1tvYmplY3QgTnVtYmVyXSc7XG59XG5cbmZ1bmN0aW9uIGlzRGF0ZShpbnB1dCkge1xuICAgIHJldHVybiBpbnB1dCBpbnN0YW5jZW9mIERhdGUgfHwgT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKGlucHV0KSA9PT0gJ1tvYmplY3QgRGF0ZV0nO1xufVxuXG5mdW5jdGlvbiBtYXAoYXJyLCBmbikge1xuICAgIHZhciByZXMgPSBbXSwgaTtcbiAgICBmb3IgKGkgPSAwOyBpIDwgYXJyLmxlbmd0aDsgKytpKSB7XG4gICAgICAgIHJlcy5wdXNoKGZuKGFycltpXSwgaSkpO1xuICAgIH1cbiAgICByZXR1cm4gcmVzO1xufVxuXG5mdW5jdGlvbiBoYXNPd25Qcm9wKGEsIGIpIHtcbiAgICByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGEsIGIpO1xufVxuXG5mdW5jdGlvbiBleHRlbmQoYSwgYikge1xuICAgIGZvciAodmFyIGkgaW4gYikge1xuICAgICAgICBpZiAoaGFzT3duUHJvcChiLCBpKSkge1xuICAgICAgICAgICAgYVtpXSA9IGJbaV07XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoaGFzT3duUHJvcChiLCAndG9TdHJpbmcnKSkge1xuICAgICAgICBhLnRvU3RyaW5nID0gYi50b1N0cmluZztcbiAgICB9XG5cbiAgICBpZiAoaGFzT3duUHJvcChiLCAndmFsdWVPZicpKSB7XG4gICAgICAgIGEudmFsdWVPZiA9IGIudmFsdWVPZjtcbiAgICB9XG5cbiAgICByZXR1cm4gYTtcbn1cblxuZnVuY3Rpb24gY3JlYXRlVVRDIChpbnB1dCwgZm9ybWF0LCBsb2NhbGUsIHN0cmljdCkge1xuICAgIHJldHVybiBjcmVhdGVMb2NhbE9yVVRDKGlucHV0LCBmb3JtYXQsIGxvY2FsZSwgc3RyaWN0LCB0cnVlKS51dGMoKTtcbn1cblxuZnVuY3Rpb24gZGVmYXVsdFBhcnNpbmdGbGFncygpIHtcbiAgICAvLyBXZSBuZWVkIHRvIGRlZXAgY2xvbmUgdGhpcyBvYmplY3QuXG4gICAgcmV0dXJuIHtcbiAgICAgICAgZW1wdHkgICAgICAgICAgIDogZmFsc2UsXG4gICAgICAgIHVudXNlZFRva2VucyAgICA6IFtdLFxuICAgICAgICB1bnVzZWRJbnB1dCAgICAgOiBbXSxcbiAgICAgICAgb3ZlcmZsb3cgICAgICAgIDogLTIsXG4gICAgICAgIGNoYXJzTGVmdE92ZXIgICA6IDAsXG4gICAgICAgIG51bGxJbnB1dCAgICAgICA6IGZhbHNlLFxuICAgICAgICBpbnZhbGlkTW9udGggICAgOiBudWxsLFxuICAgICAgICBpbnZhbGlkRm9ybWF0ICAgOiBmYWxzZSxcbiAgICAgICAgdXNlckludmFsaWRhdGVkIDogZmFsc2UsXG4gICAgICAgIGlzbyAgICAgICAgICAgICA6IGZhbHNlLFxuICAgICAgICBwYXJzZWREYXRlUGFydHMgOiBbXSxcbiAgICAgICAgbWVyaWRpZW0gICAgICAgIDogbnVsbCxcbiAgICAgICAgcmZjMjgyMiAgICAgICAgIDogZmFsc2UsXG4gICAgICAgIHdlZWtkYXlNaXNtYXRjaCA6IGZhbHNlXG4gICAgfTtcbn1cblxuZnVuY3Rpb24gZ2V0UGFyc2luZ0ZsYWdzKG0pIHtcbiAgICBpZiAobS5fcGYgPT0gbnVsbCkge1xuICAgICAgICBtLl9wZiA9IGRlZmF1bHRQYXJzaW5nRmxhZ3MoKTtcbiAgICB9XG4gICAgcmV0dXJuIG0uX3BmO1xufVxuXG52YXIgc29tZTtcbmlmIChBcnJheS5wcm90b3R5cGUuc29tZSkge1xuICAgIHNvbWUgPSBBcnJheS5wcm90b3R5cGUuc29tZTtcbn0gZWxzZSB7XG4gICAgc29tZSA9IGZ1bmN0aW9uIChmdW4pIHtcbiAgICAgICAgdmFyIHQgPSBPYmplY3QodGhpcyk7XG4gICAgICAgIHZhciBsZW4gPSB0Lmxlbmd0aCA+Pj4gMDtcblxuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICBpZiAoaSBpbiB0ICYmIGZ1bi5jYWxsKHRoaXMsIHRbaV0sIGksIHQpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfTtcbn1cblxuZnVuY3Rpb24gaXNWYWxpZChtKSB7XG4gICAgaWYgKG0uX2lzVmFsaWQgPT0gbnVsbCkge1xuICAgICAgICB2YXIgZmxhZ3MgPSBnZXRQYXJzaW5nRmxhZ3MobSk7XG4gICAgICAgIHZhciBwYXJzZWRQYXJ0cyA9IHNvbWUuY2FsbChmbGFncy5wYXJzZWREYXRlUGFydHMsIGZ1bmN0aW9uIChpKSB7XG4gICAgICAgICAgICByZXR1cm4gaSAhPSBudWxsO1xuICAgICAgICB9KTtcbiAgICAgICAgdmFyIGlzTm93VmFsaWQgPSAhaXNOYU4obS5fZC5nZXRUaW1lKCkpICYmXG4gICAgICAgICAgICBmbGFncy5vdmVyZmxvdyA8IDAgJiZcbiAgICAgICAgICAgICFmbGFncy5lbXB0eSAmJlxuICAgICAgICAgICAgIWZsYWdzLmludmFsaWRNb250aCAmJlxuICAgICAgICAgICAgIWZsYWdzLmludmFsaWRXZWVrZGF5ICYmXG4gICAgICAgICAgICAhZmxhZ3Mud2Vla2RheU1pc21hdGNoICYmXG4gICAgICAgICAgICAhZmxhZ3MubnVsbElucHV0ICYmXG4gICAgICAgICAgICAhZmxhZ3MuaW52YWxpZEZvcm1hdCAmJlxuICAgICAgICAgICAgIWZsYWdzLnVzZXJJbnZhbGlkYXRlZCAmJlxuICAgICAgICAgICAgKCFmbGFncy5tZXJpZGllbSB8fCAoZmxhZ3MubWVyaWRpZW0gJiYgcGFyc2VkUGFydHMpKTtcblxuICAgICAgICBpZiAobS5fc3RyaWN0KSB7XG4gICAgICAgICAgICBpc05vd1ZhbGlkID0gaXNOb3dWYWxpZCAmJlxuICAgICAgICAgICAgICAgIGZsYWdzLmNoYXJzTGVmdE92ZXIgPT09IDAgJiZcbiAgICAgICAgICAgICAgICBmbGFncy51bnVzZWRUb2tlbnMubGVuZ3RoID09PSAwICYmXG4gICAgICAgICAgICAgICAgZmxhZ3MuYmlnSG91ciA9PT0gdW5kZWZpbmVkO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKE9iamVjdC5pc0Zyb3plbiA9PSBudWxsIHx8ICFPYmplY3QuaXNGcm96ZW4obSkpIHtcbiAgICAgICAgICAgIG0uX2lzVmFsaWQgPSBpc05vd1ZhbGlkO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIGlzTm93VmFsaWQ7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG0uX2lzVmFsaWQ7XG59XG5cbmZ1bmN0aW9uIGNyZWF0ZUludmFsaWQgKGZsYWdzKSB7XG4gICAgdmFyIG0gPSBjcmVhdGVVVEMoTmFOKTtcbiAgICBpZiAoZmxhZ3MgIT0gbnVsbCkge1xuICAgICAgICBleHRlbmQoZ2V0UGFyc2luZ0ZsYWdzKG0pLCBmbGFncyk7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICBnZXRQYXJzaW5nRmxhZ3MobSkudXNlckludmFsaWRhdGVkID0gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gbTtcbn1cblxuLy8gUGx1Z2lucyB0aGF0IGFkZCBwcm9wZXJ0aWVzIHNob3VsZCBhbHNvIGFkZCB0aGUga2V5IGhlcmUgKG51bGwgdmFsdWUpLFxuLy8gc28gd2UgY2FuIHByb3Blcmx5IGNsb25lIG91cnNlbHZlcy5cbnZhciBtb21lbnRQcm9wZXJ0aWVzID0gaG9va3MubW9tZW50UHJvcGVydGllcyA9IFtdO1xuXG5mdW5jdGlvbiBjb3B5Q29uZmlnKHRvLCBmcm9tKSB7XG4gICAgdmFyIGksIHByb3AsIHZhbDtcblxuICAgIGlmICghaXNVbmRlZmluZWQoZnJvbS5faXNBTW9tZW50T2JqZWN0KSkge1xuICAgICAgICB0by5faXNBTW9tZW50T2JqZWN0ID0gZnJvbS5faXNBTW9tZW50T2JqZWN0O1xuICAgIH1cbiAgICBpZiAoIWlzVW5kZWZpbmVkKGZyb20uX2kpKSB7XG4gICAgICAgIHRvLl9pID0gZnJvbS5faTtcbiAgICB9XG4gICAgaWYgKCFpc1VuZGVmaW5lZChmcm9tLl9mKSkge1xuICAgICAgICB0by5fZiA9IGZyb20uX2Y7XG4gICAgfVxuICAgIGlmICghaXNVbmRlZmluZWQoZnJvbS5fbCkpIHtcbiAgICAgICAgdG8uX2wgPSBmcm9tLl9sO1xuICAgIH1cbiAgICBpZiAoIWlzVW5kZWZpbmVkKGZyb20uX3N0cmljdCkpIHtcbiAgICAgICAgdG8uX3N0cmljdCA9IGZyb20uX3N0cmljdDtcbiAgICB9XG4gICAgaWYgKCFpc1VuZGVmaW5lZChmcm9tLl90em0pKSB7XG4gICAgICAgIHRvLl90em0gPSBmcm9tLl90em07XG4gICAgfVxuICAgIGlmICghaXNVbmRlZmluZWQoZnJvbS5faXNVVEMpKSB7XG4gICAgICAgIHRvLl9pc1VUQyA9IGZyb20uX2lzVVRDO1xuICAgIH1cbiAgICBpZiAoIWlzVW5kZWZpbmVkKGZyb20uX29mZnNldCkpIHtcbiAgICAgICAgdG8uX29mZnNldCA9IGZyb20uX29mZnNldDtcbiAgICB9XG4gICAgaWYgKCFpc1VuZGVmaW5lZChmcm9tLl9wZikpIHtcbiAgICAgICAgdG8uX3BmID0gZ2V0UGFyc2luZ0ZsYWdzKGZyb20pO1xuICAgIH1cbiAgICBpZiAoIWlzVW5kZWZpbmVkKGZyb20uX2xvY2FsZSkpIHtcbiAgICAgICAgdG8uX2xvY2FsZSA9IGZyb20uX2xvY2FsZTtcbiAgICB9XG5cbiAgICBpZiAobW9tZW50UHJvcGVydGllcy5sZW5ndGggPiAwKSB7XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBtb21lbnRQcm9wZXJ0aWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBwcm9wID0gbW9tZW50UHJvcGVydGllc1tpXTtcbiAgICAgICAgICAgIHZhbCA9IGZyb21bcHJvcF07XG4gICAgICAgICAgICBpZiAoIWlzVW5kZWZpbmVkKHZhbCkpIHtcbiAgICAgICAgICAgICAgICB0b1twcm9wXSA9IHZhbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0bztcbn1cblxudmFyIHVwZGF0ZUluUHJvZ3Jlc3MgPSBmYWxzZTtcblxuLy8gTW9tZW50IHByb3RvdHlwZSBvYmplY3RcbmZ1bmN0aW9uIE1vbWVudChjb25maWcpIHtcbiAgICBjb3B5Q29uZmlnKHRoaXMsIGNvbmZpZyk7XG4gICAgdGhpcy5fZCA9IG5ldyBEYXRlKGNvbmZpZy5fZCAhPSBudWxsID8gY29uZmlnLl9kLmdldFRpbWUoKSA6IE5hTik7XG4gICAgaWYgKCF0aGlzLmlzVmFsaWQoKSkge1xuICAgICAgICB0aGlzLl9kID0gbmV3IERhdGUoTmFOKTtcbiAgICB9XG4gICAgLy8gUHJldmVudCBpbmZpbml0ZSBsb29wIGluIGNhc2UgdXBkYXRlT2Zmc2V0IGNyZWF0ZXMgbmV3IG1vbWVudFxuICAgIC8vIG9iamVjdHMuXG4gICAgaWYgKHVwZGF0ZUluUHJvZ3Jlc3MgPT09IGZhbHNlKSB7XG4gICAgICAgIHVwZGF0ZUluUHJvZ3Jlc3MgPSB0cnVlO1xuICAgICAgICBob29rcy51cGRhdGVPZmZzZXQodGhpcyk7XG4gICAgICAgIHVwZGF0ZUluUHJvZ3Jlc3MgPSBmYWxzZTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGlzTW9tZW50IChvYmopIHtcbiAgICByZXR1cm4gb2JqIGluc3RhbmNlb2YgTW9tZW50IHx8IChvYmogIT0gbnVsbCAmJiBvYmouX2lzQU1vbWVudE9iamVjdCAhPSBudWxsKTtcbn1cblxuZnVuY3Rpb24gYWJzRmxvb3IgKG51bWJlcikge1xuICAgIGlmIChudW1iZXIgPCAwKSB7XG4gICAgICAgIC8vIC0wIC0+IDBcbiAgICAgICAgcmV0dXJuIE1hdGguY2VpbChudW1iZXIpIHx8IDA7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIE1hdGguZmxvb3IobnVtYmVyKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIHRvSW50KGFyZ3VtZW50Rm9yQ29lcmNpb24pIHtcbiAgICB2YXIgY29lcmNlZE51bWJlciA9ICthcmd1bWVudEZvckNvZXJjaW9uLFxuICAgICAgICB2YWx1ZSA9IDA7XG5cbiAgICBpZiAoY29lcmNlZE51bWJlciAhPT0gMCAmJiBpc0Zpbml0ZShjb2VyY2VkTnVtYmVyKSkge1xuICAgICAgICB2YWx1ZSA9IGFic0Zsb29yKGNvZXJjZWROdW1iZXIpO1xuICAgIH1cblxuICAgIHJldHVybiB2YWx1ZTtcbn1cblxuLy8gY29tcGFyZSB0d28gYXJyYXlzLCByZXR1cm4gdGhlIG51bWJlciBvZiBkaWZmZXJlbmNlc1xuZnVuY3Rpb24gY29tcGFyZUFycmF5cyhhcnJheTEsIGFycmF5MiwgZG9udENvbnZlcnQpIHtcbiAgICB2YXIgbGVuID0gTWF0aC5taW4oYXJyYXkxLmxlbmd0aCwgYXJyYXkyLmxlbmd0aCksXG4gICAgICAgIGxlbmd0aERpZmYgPSBNYXRoLmFicyhhcnJheTEubGVuZ3RoIC0gYXJyYXkyLmxlbmd0aCksXG4gICAgICAgIGRpZmZzID0gMCxcbiAgICAgICAgaTtcbiAgICBmb3IgKGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgaWYgKChkb250Q29udmVydCAmJiBhcnJheTFbaV0gIT09IGFycmF5MltpXSkgfHxcbiAgICAgICAgICAgICghZG9udENvbnZlcnQgJiYgdG9JbnQoYXJyYXkxW2ldKSAhPT0gdG9JbnQoYXJyYXkyW2ldKSkpIHtcbiAgICAgICAgICAgIGRpZmZzKys7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGRpZmZzICsgbGVuZ3RoRGlmZjtcbn1cblxuZnVuY3Rpb24gd2Fybihtc2cpIHtcbiAgICBpZiAoaG9va3Muc3VwcHJlc3NEZXByZWNhdGlvbldhcm5pbmdzID09PSBmYWxzZSAmJlxuICAgICAgICAgICAgKHR5cGVvZiBjb25zb2xlICE9PSAgJ3VuZGVmaW5lZCcpICYmIGNvbnNvbGUud2Fybikge1xuICAgICAgICBjb25zb2xlLndhcm4oJ0RlcHJlY2F0aW9uIHdhcm5pbmc6ICcgKyBtc2cpO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gZGVwcmVjYXRlKG1zZywgZm4pIHtcbiAgICB2YXIgZmlyc3RUaW1lID0gdHJ1ZTtcblxuICAgIHJldHVybiBleHRlbmQoZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoaG9va3MuZGVwcmVjYXRpb25IYW5kbGVyICE9IG51bGwpIHtcbiAgICAgICAgICAgIGhvb2tzLmRlcHJlY2F0aW9uSGFuZGxlcihudWxsLCBtc2cpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChmaXJzdFRpbWUpIHtcbiAgICAgICAgICAgIHZhciBhcmdzID0gW107XG4gICAgICAgICAgICB2YXIgYXJnO1xuICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBhcmd1bWVudHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBhcmcgPSAnJztcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGFyZ3VtZW50c1tpXSA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgICAgICAgICAgYXJnICs9ICdcXG5bJyArIGkgKyAnXSAnO1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBrZXkgaW4gYXJndW1lbnRzWzBdKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcmcgKz0ga2V5ICsgJzogJyArIGFyZ3VtZW50c1swXVtrZXldICsgJywgJztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBhcmcgPSBhcmcuc2xpY2UoMCwgLTIpOyAvLyBSZW1vdmUgdHJhaWxpbmcgY29tbWEgYW5kIHNwYWNlXG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgYXJnID0gYXJndW1lbnRzW2ldO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBhcmdzLnB1c2goYXJnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHdhcm4obXNnICsgJ1xcbkFyZ3VtZW50czogJyArIEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3MpLmpvaW4oJycpICsgJ1xcbicgKyAobmV3IEVycm9yKCkpLnN0YWNrKTtcbiAgICAgICAgICAgIGZpcnN0VGltZSA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmbi5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgIH0sIGZuKTtcbn1cblxudmFyIGRlcHJlY2F0aW9ucyA9IHt9O1xuXG5mdW5jdGlvbiBkZXByZWNhdGVTaW1wbGUobmFtZSwgbXNnKSB7XG4gICAgaWYgKGhvb2tzLmRlcHJlY2F0aW9uSGFuZGxlciAhPSBudWxsKSB7XG4gICAgICAgIGhvb2tzLmRlcHJlY2F0aW9uSGFuZGxlcihuYW1lLCBtc2cpO1xuICAgIH1cbiAgICBpZiAoIWRlcHJlY2F0aW9uc1tuYW1lXSkge1xuICAgICAgICB3YXJuKG1zZyk7XG4gICAgICAgIGRlcHJlY2F0aW9uc1tuYW1lXSA9IHRydWU7XG4gICAgfVxufVxuXG5ob29rcy5zdXBwcmVzc0RlcHJlY2F0aW9uV2FybmluZ3MgPSBmYWxzZTtcbmhvb2tzLmRlcHJlY2F0aW9uSGFuZGxlciA9IG51bGw7XG5cbmZ1bmN0aW9uIGlzRnVuY3Rpb24oaW5wdXQpIHtcbiAgICByZXR1cm4gaW5wdXQgaW5zdGFuY2VvZiBGdW5jdGlvbiB8fCBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwoaW5wdXQpID09PSAnW29iamVjdCBGdW5jdGlvbl0nO1xufVxuXG5mdW5jdGlvbiBzZXQgKGNvbmZpZykge1xuICAgIHZhciBwcm9wLCBpO1xuICAgIGZvciAoaSBpbiBjb25maWcpIHtcbiAgICAgICAgcHJvcCA9IGNvbmZpZ1tpXTtcbiAgICAgICAgaWYgKGlzRnVuY3Rpb24ocHJvcCkpIHtcbiAgICAgICAgICAgIHRoaXNbaV0gPSBwcm9wO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpc1snXycgKyBpXSA9IHByb3A7XG4gICAgICAgIH1cbiAgICB9XG4gICAgdGhpcy5fY29uZmlnID0gY29uZmlnO1xuICAgIC8vIExlbmllbnQgb3JkaW5hbCBwYXJzaW5nIGFjY2VwdHMganVzdCBhIG51bWJlciBpbiBhZGRpdGlvbiB0b1xuICAgIC8vIG51bWJlciArIChwb3NzaWJseSkgc3R1ZmYgY29taW5nIGZyb20gX2RheU9mTW9udGhPcmRpbmFsUGFyc2UuXG4gICAgLy8gVE9ETzogUmVtb3ZlIFwib3JkaW5hbFBhcnNlXCIgZmFsbGJhY2sgaW4gbmV4dCBtYWpvciByZWxlYXNlLlxuICAgIHRoaXMuX2RheU9mTW9udGhPcmRpbmFsUGFyc2VMZW5pZW50ID0gbmV3IFJlZ0V4cChcbiAgICAgICAgKHRoaXMuX2RheU9mTW9udGhPcmRpbmFsUGFyc2Uuc291cmNlIHx8IHRoaXMuX29yZGluYWxQYXJzZS5zb3VyY2UpICtcbiAgICAgICAgICAgICd8JyArICgvXFxkezEsMn0vKS5zb3VyY2UpO1xufVxuXG5mdW5jdGlvbiBtZXJnZUNvbmZpZ3MocGFyZW50Q29uZmlnLCBjaGlsZENvbmZpZykge1xuICAgIHZhciByZXMgPSBleHRlbmQoe30sIHBhcmVudENvbmZpZyksIHByb3A7XG4gICAgZm9yIChwcm9wIGluIGNoaWxkQ29uZmlnKSB7XG4gICAgICAgIGlmIChoYXNPd25Qcm9wKGNoaWxkQ29uZmlnLCBwcm9wKSkge1xuICAgICAgICAgICAgaWYgKGlzT2JqZWN0KHBhcmVudENvbmZpZ1twcm9wXSkgJiYgaXNPYmplY3QoY2hpbGRDb25maWdbcHJvcF0pKSB7XG4gICAgICAgICAgICAgICAgcmVzW3Byb3BdID0ge307XG4gICAgICAgICAgICAgICAgZXh0ZW5kKHJlc1twcm9wXSwgcGFyZW50Q29uZmlnW3Byb3BdKTtcbiAgICAgICAgICAgICAgICBleHRlbmQocmVzW3Byb3BdLCBjaGlsZENvbmZpZ1twcm9wXSk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGNoaWxkQ29uZmlnW3Byb3BdICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICByZXNbcHJvcF0gPSBjaGlsZENvbmZpZ1twcm9wXTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgZGVsZXRlIHJlc1twcm9wXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICBmb3IgKHByb3AgaW4gcGFyZW50Q29uZmlnKSB7XG4gICAgICAgIGlmIChoYXNPd25Qcm9wKHBhcmVudENvbmZpZywgcHJvcCkgJiZcbiAgICAgICAgICAgICAgICAhaGFzT3duUHJvcChjaGlsZENvbmZpZywgcHJvcCkgJiZcbiAgICAgICAgICAgICAgICBpc09iamVjdChwYXJlbnRDb25maWdbcHJvcF0pKSB7XG4gICAgICAgICAgICAvLyBtYWtlIHN1cmUgY2hhbmdlcyB0byBwcm9wZXJ0aWVzIGRvbid0IG1vZGlmeSBwYXJlbnQgY29uZmlnXG4gICAgICAgICAgICByZXNbcHJvcF0gPSBleHRlbmQoe30sIHJlc1twcm9wXSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHJlcztcbn1cblxuZnVuY3Rpb24gTG9jYWxlKGNvbmZpZykge1xuICAgIGlmIChjb25maWcgIT0gbnVsbCkge1xuICAgICAgICB0aGlzLnNldChjb25maWcpO1xuICAgIH1cbn1cblxudmFyIGtleXM7XG5cbmlmIChPYmplY3Qua2V5cykge1xuICAgIGtleXMgPSBPYmplY3Qua2V5cztcbn0gZWxzZSB7XG4gICAga2V5cyA9IGZ1bmN0aW9uIChvYmopIHtcbiAgICAgICAgdmFyIGksIHJlcyA9IFtdO1xuICAgICAgICBmb3IgKGkgaW4gb2JqKSB7XG4gICAgICAgICAgICBpZiAoaGFzT3duUHJvcChvYmosIGkpKSB7XG4gICAgICAgICAgICAgICAgcmVzLnB1c2goaSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9O1xufVxuXG52YXIgZGVmYXVsdENhbGVuZGFyID0ge1xuICAgIHNhbWVEYXkgOiAnW1RvZGF5IGF0XSBMVCcsXG4gICAgbmV4dERheSA6ICdbVG9tb3Jyb3cgYXRdIExUJyxcbiAgICBuZXh0V2VlayA6ICdkZGRkIFthdF0gTFQnLFxuICAgIGxhc3REYXkgOiAnW1llc3RlcmRheSBhdF0gTFQnLFxuICAgIGxhc3RXZWVrIDogJ1tMYXN0XSBkZGRkIFthdF0gTFQnLFxuICAgIHNhbWVFbHNlIDogJ0wnXG59O1xuXG5mdW5jdGlvbiBjYWxlbmRhciAoa2V5LCBtb20sIG5vdykge1xuICAgIHZhciBvdXRwdXQgPSB0aGlzLl9jYWxlbmRhcltrZXldIHx8IHRoaXMuX2NhbGVuZGFyWydzYW1lRWxzZSddO1xuICAgIHJldHVybiBpc0Z1bmN0aW9uKG91dHB1dCkgPyBvdXRwdXQuY2FsbChtb20sIG5vdykgOiBvdXRwdXQ7XG59XG5cbnZhciBkZWZhdWx0TG9uZ0RhdGVGb3JtYXQgPSB7XG4gICAgTFRTICA6ICdoOm1tOnNzIEEnLFxuICAgIExUICAgOiAnaDptbSBBJyxcbiAgICBMICAgIDogJ01NL0REL1lZWVknLFxuICAgIExMICAgOiAnTU1NTSBELCBZWVlZJyxcbiAgICBMTEwgIDogJ01NTU0gRCwgWVlZWSBoOm1tIEEnLFxuICAgIExMTEwgOiAnZGRkZCwgTU1NTSBELCBZWVlZIGg6bW0gQSdcbn07XG5cbmZ1bmN0aW9uIGxvbmdEYXRlRm9ybWF0IChrZXkpIHtcbiAgICB2YXIgZm9ybWF0ID0gdGhpcy5fbG9uZ0RhdGVGb3JtYXRba2V5XSxcbiAgICAgICAgZm9ybWF0VXBwZXIgPSB0aGlzLl9sb25nRGF0ZUZvcm1hdFtrZXkudG9VcHBlckNhc2UoKV07XG5cbiAgICBpZiAoZm9ybWF0IHx8ICFmb3JtYXRVcHBlcikge1xuICAgICAgICByZXR1cm4gZm9ybWF0O1xuICAgIH1cblxuICAgIHRoaXMuX2xvbmdEYXRlRm9ybWF0W2tleV0gPSBmb3JtYXRVcHBlci5yZXBsYWNlKC9NTU1NfE1NfEREfGRkZGQvZywgZnVuY3Rpb24gKHZhbCkge1xuICAgICAgICByZXR1cm4gdmFsLnNsaWNlKDEpO1xuICAgIH0pO1xuXG4gICAgcmV0dXJuIHRoaXMuX2xvbmdEYXRlRm9ybWF0W2tleV07XG59XG5cbnZhciBkZWZhdWx0SW52YWxpZERhdGUgPSAnSW52YWxpZCBkYXRlJztcblxuZnVuY3Rpb24gaW52YWxpZERhdGUgKCkge1xuICAgIHJldHVybiB0aGlzLl9pbnZhbGlkRGF0ZTtcbn1cblxudmFyIGRlZmF1bHRPcmRpbmFsID0gJyVkJztcbnZhciBkZWZhdWx0RGF5T2ZNb250aE9yZGluYWxQYXJzZSA9IC9cXGR7MSwyfS87XG5cbmZ1bmN0aW9uIG9yZGluYWwgKG51bWJlcikge1xuICAgIHJldHVybiB0aGlzLl9vcmRpbmFsLnJlcGxhY2UoJyVkJywgbnVtYmVyKTtcbn1cblxudmFyIGRlZmF1bHRSZWxhdGl2ZVRpbWUgPSB7XG4gICAgZnV0dXJlIDogJ2luICVzJyxcbiAgICBwYXN0ICAgOiAnJXMgYWdvJyxcbiAgICBzICA6ICdhIGZldyBzZWNvbmRzJyxcbiAgICBzcyA6ICclZCBzZWNvbmRzJyxcbiAgICBtICA6ICdhIG1pbnV0ZScsXG4gICAgbW0gOiAnJWQgbWludXRlcycsXG4gICAgaCAgOiAnYW4gaG91cicsXG4gICAgaGggOiAnJWQgaG91cnMnLFxuICAgIGQgIDogJ2EgZGF5JyxcbiAgICBkZCA6ICclZCBkYXlzJyxcbiAgICBNICA6ICdhIG1vbnRoJyxcbiAgICBNTSA6ICclZCBtb250aHMnLFxuICAgIHkgIDogJ2EgeWVhcicsXG4gICAgeXkgOiAnJWQgeWVhcnMnXG59O1xuXG5mdW5jdGlvbiByZWxhdGl2ZVRpbWUgKG51bWJlciwgd2l0aG91dFN1ZmZpeCwgc3RyaW5nLCBpc0Z1dHVyZSkge1xuICAgIHZhciBvdXRwdXQgPSB0aGlzLl9yZWxhdGl2ZVRpbWVbc3RyaW5nXTtcbiAgICByZXR1cm4gKGlzRnVuY3Rpb24ob3V0cHV0KSkgP1xuICAgICAgICBvdXRwdXQobnVtYmVyLCB3aXRob3V0U3VmZml4LCBzdHJpbmcsIGlzRnV0dXJlKSA6XG4gICAgICAgIG91dHB1dC5yZXBsYWNlKC8lZC9pLCBudW1iZXIpO1xufVxuXG5mdW5jdGlvbiBwYXN0RnV0dXJlIChkaWZmLCBvdXRwdXQpIHtcbiAgICB2YXIgZm9ybWF0ID0gdGhpcy5fcmVsYXRpdmVUaW1lW2RpZmYgPiAwID8gJ2Z1dHVyZScgOiAncGFzdCddO1xuICAgIHJldHVybiBpc0Z1bmN0aW9uKGZvcm1hdCkgPyBmb3JtYXQob3V0cHV0KSA6IGZvcm1hdC5yZXBsYWNlKC8lcy9pLCBvdXRwdXQpO1xufVxuXG52YXIgYWxpYXNlcyA9IHt9O1xuXG5mdW5jdGlvbiBhZGRVbml0QWxpYXMgKHVuaXQsIHNob3J0aGFuZCkge1xuICAgIHZhciBsb3dlckNhc2UgPSB1bml0LnRvTG93ZXJDYXNlKCk7XG4gICAgYWxpYXNlc1tsb3dlckNhc2VdID0gYWxpYXNlc1tsb3dlckNhc2UgKyAncyddID0gYWxpYXNlc1tzaG9ydGhhbmRdID0gdW5pdDtcbn1cblxuZnVuY3Rpb24gbm9ybWFsaXplVW5pdHModW5pdHMpIHtcbiAgICByZXR1cm4gdHlwZW9mIHVuaXRzID09PSAnc3RyaW5nJyA/IGFsaWFzZXNbdW5pdHNdIHx8IGFsaWFzZXNbdW5pdHMudG9Mb3dlckNhc2UoKV0gOiB1bmRlZmluZWQ7XG59XG5cbmZ1bmN0aW9uIG5vcm1hbGl6ZU9iamVjdFVuaXRzKGlucHV0T2JqZWN0KSB7XG4gICAgdmFyIG5vcm1hbGl6ZWRJbnB1dCA9IHt9LFxuICAgICAgICBub3JtYWxpemVkUHJvcCxcbiAgICAgICAgcHJvcDtcblxuICAgIGZvciAocHJvcCBpbiBpbnB1dE9iamVjdCkge1xuICAgICAgICBpZiAoaGFzT3duUHJvcChpbnB1dE9iamVjdCwgcHJvcCkpIHtcbiAgICAgICAgICAgIG5vcm1hbGl6ZWRQcm9wID0gbm9ybWFsaXplVW5pdHMocHJvcCk7XG4gICAgICAgICAgICBpZiAobm9ybWFsaXplZFByb3ApIHtcbiAgICAgICAgICAgICAgICBub3JtYWxpemVkSW5wdXRbbm9ybWFsaXplZFByb3BdID0gaW5wdXRPYmplY3RbcHJvcF07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gbm9ybWFsaXplZElucHV0O1xufVxuXG52YXIgcHJpb3JpdGllcyA9IHt9O1xuXG5mdW5jdGlvbiBhZGRVbml0UHJpb3JpdHkodW5pdCwgcHJpb3JpdHkpIHtcbiAgICBwcmlvcml0aWVzW3VuaXRdID0gcHJpb3JpdHk7XG59XG5cbmZ1bmN0aW9uIGdldFByaW9yaXRpemVkVW5pdHModW5pdHNPYmopIHtcbiAgICB2YXIgdW5pdHMgPSBbXTtcbiAgICBmb3IgKHZhciB1IGluIHVuaXRzT2JqKSB7XG4gICAgICAgIHVuaXRzLnB1c2goe3VuaXQ6IHUsIHByaW9yaXR5OiBwcmlvcml0aWVzW3VdfSk7XG4gICAgfVxuICAgIHVuaXRzLnNvcnQoZnVuY3Rpb24gKGEsIGIpIHtcbiAgICAgICAgcmV0dXJuIGEucHJpb3JpdHkgLSBiLnByaW9yaXR5O1xuICAgIH0pO1xuICAgIHJldHVybiB1bml0cztcbn1cblxuZnVuY3Rpb24gemVyb0ZpbGwobnVtYmVyLCB0YXJnZXRMZW5ndGgsIGZvcmNlU2lnbikge1xuICAgIHZhciBhYnNOdW1iZXIgPSAnJyArIE1hdGguYWJzKG51bWJlciksXG4gICAgICAgIHplcm9zVG9GaWxsID0gdGFyZ2V0TGVuZ3RoIC0gYWJzTnVtYmVyLmxlbmd0aCxcbiAgICAgICAgc2lnbiA9IG51bWJlciA+PSAwO1xuICAgIHJldHVybiAoc2lnbiA/IChmb3JjZVNpZ24gPyAnKycgOiAnJykgOiAnLScpICtcbiAgICAgICAgTWF0aC5wb3coMTAsIE1hdGgubWF4KDAsIHplcm9zVG9GaWxsKSkudG9TdHJpbmcoKS5zdWJzdHIoMSkgKyBhYnNOdW1iZXI7XG59XG5cbnZhciBmb3JtYXR0aW5nVG9rZW5zID0gLyhcXFtbXlxcW10qXFxdKXwoXFxcXCk/KFtIaF1tbShzcyk/fE1vfE1NP00/TT98RG98REREb3xERD9EP0Q/fGRkZD9kP3xkbz98d1tvfHddP3xXW298V10/fFFvP3xZWVlZWVl8WVlZWVl8WVlZWXxZWXxnZyhnZ2c/KT98R0coR0dHPyk/fGV8RXxhfEF8aGg/fEhIP3xraz98bW0/fHNzP3xTezEsOX18eHxYfHp6P3xaWj98LikvZztcblxudmFyIGxvY2FsRm9ybWF0dGluZ1Rva2VucyA9IC8oXFxbW15cXFtdKlxcXSl8KFxcXFwpPyhMVFN8TFR8TEw/TD9MP3xsezEsNH0pL2c7XG5cbnZhciBmb3JtYXRGdW5jdGlvbnMgPSB7fTtcblxudmFyIGZvcm1hdFRva2VuRnVuY3Rpb25zID0ge307XG5cbi8vIHRva2VuOiAgICAnTSdcbi8vIHBhZGRlZDogICBbJ01NJywgMl1cbi8vIG9yZGluYWw6ICAnTW8nXG4vLyBjYWxsYmFjazogZnVuY3Rpb24gKCkgeyB0aGlzLm1vbnRoKCkgKyAxIH1cbmZ1bmN0aW9uIGFkZEZvcm1hdFRva2VuICh0b2tlbiwgcGFkZGVkLCBvcmRpbmFsLCBjYWxsYmFjaykge1xuICAgIHZhciBmdW5jID0gY2FsbGJhY2s7XG4gICAgaWYgKHR5cGVvZiBjYWxsYmFjayA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgZnVuYyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzW2NhbGxiYWNrXSgpO1xuICAgICAgICB9O1xuICAgIH1cbiAgICBpZiAodG9rZW4pIHtcbiAgICAgICAgZm9ybWF0VG9rZW5GdW5jdGlvbnNbdG9rZW5dID0gZnVuYztcbiAgICB9XG4gICAgaWYgKHBhZGRlZCkge1xuICAgICAgICBmb3JtYXRUb2tlbkZ1bmN0aW9uc1twYWRkZWRbMF1dID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIHplcm9GaWxsKGZ1bmMuYXBwbHkodGhpcywgYXJndW1lbnRzKSwgcGFkZGVkWzFdLCBwYWRkZWRbMl0pO1xuICAgICAgICB9O1xuICAgIH1cbiAgICBpZiAob3JkaW5hbCkge1xuICAgICAgICBmb3JtYXRUb2tlbkZ1bmN0aW9uc1tvcmRpbmFsXSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmxvY2FsZURhdGEoKS5vcmRpbmFsKGZ1bmMuYXBwbHkodGhpcywgYXJndW1lbnRzKSwgdG9rZW4pO1xuICAgICAgICB9O1xuICAgIH1cbn1cblxuZnVuY3Rpb24gcmVtb3ZlRm9ybWF0dGluZ1Rva2VucyhpbnB1dCkge1xuICAgIGlmIChpbnB1dC5tYXRjaCgvXFxbW1xcc1xcU10vKSkge1xuICAgICAgICByZXR1cm4gaW5wdXQucmVwbGFjZSgvXlxcW3xcXF0kL2csICcnKTtcbiAgICB9XG4gICAgcmV0dXJuIGlucHV0LnJlcGxhY2UoL1xcXFwvZywgJycpO1xufVxuXG5mdW5jdGlvbiBtYWtlRm9ybWF0RnVuY3Rpb24oZm9ybWF0KSB7XG4gICAgdmFyIGFycmF5ID0gZm9ybWF0Lm1hdGNoKGZvcm1hdHRpbmdUb2tlbnMpLCBpLCBsZW5ndGg7XG5cbiAgICBmb3IgKGkgPSAwLCBsZW5ndGggPSBhcnJheS5sZW5ndGg7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgICBpZiAoZm9ybWF0VG9rZW5GdW5jdGlvbnNbYXJyYXlbaV1dKSB7XG4gICAgICAgICAgICBhcnJheVtpXSA9IGZvcm1hdFRva2VuRnVuY3Rpb25zW2FycmF5W2ldXTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGFycmF5W2ldID0gcmVtb3ZlRm9ybWF0dGluZ1Rva2VucyhhcnJheVtpXSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gZnVuY3Rpb24gKG1vbSkge1xuICAgICAgICB2YXIgb3V0cHV0ID0gJycsIGk7XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgb3V0cHV0ICs9IGlzRnVuY3Rpb24oYXJyYXlbaV0pID8gYXJyYXlbaV0uY2FsbChtb20sIGZvcm1hdCkgOiBhcnJheVtpXTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gb3V0cHV0O1xuICAgIH07XG59XG5cbi8vIGZvcm1hdCBkYXRlIHVzaW5nIG5hdGl2ZSBkYXRlIG9iamVjdFxuZnVuY3Rpb24gZm9ybWF0TW9tZW50KG0sIGZvcm1hdCkge1xuICAgIGlmICghbS5pc1ZhbGlkKCkpIHtcbiAgICAgICAgcmV0dXJuIG0ubG9jYWxlRGF0YSgpLmludmFsaWREYXRlKCk7XG4gICAgfVxuXG4gICAgZm9ybWF0ID0gZXhwYW5kRm9ybWF0KGZvcm1hdCwgbS5sb2NhbGVEYXRhKCkpO1xuICAgIGZvcm1hdEZ1bmN0aW9uc1tmb3JtYXRdID0gZm9ybWF0RnVuY3Rpb25zW2Zvcm1hdF0gfHwgbWFrZUZvcm1hdEZ1bmN0aW9uKGZvcm1hdCk7XG5cbiAgICByZXR1cm4gZm9ybWF0RnVuY3Rpb25zW2Zvcm1hdF0obSk7XG59XG5cbmZ1bmN0aW9uIGV4cGFuZEZvcm1hdChmb3JtYXQsIGxvY2FsZSkge1xuICAgIHZhciBpID0gNTtcblxuICAgIGZ1bmN0aW9uIHJlcGxhY2VMb25nRGF0ZUZvcm1hdFRva2VucyhpbnB1dCkge1xuICAgICAgICByZXR1cm4gbG9jYWxlLmxvbmdEYXRlRm9ybWF0KGlucHV0KSB8fCBpbnB1dDtcbiAgICB9XG5cbiAgICBsb2NhbEZvcm1hdHRpbmdUb2tlbnMubGFzdEluZGV4ID0gMDtcbiAgICB3aGlsZSAoaSA+PSAwICYmIGxvY2FsRm9ybWF0dGluZ1Rva2Vucy50ZXN0KGZvcm1hdCkpIHtcbiAgICAgICAgZm9ybWF0ID0gZm9ybWF0LnJlcGxhY2UobG9jYWxGb3JtYXR0aW5nVG9rZW5zLCByZXBsYWNlTG9uZ0RhdGVGb3JtYXRUb2tlbnMpO1xuICAgICAgICBsb2NhbEZvcm1hdHRpbmdUb2tlbnMubGFzdEluZGV4ID0gMDtcbiAgICAgICAgaSAtPSAxO1xuICAgIH1cblxuICAgIHJldHVybiBmb3JtYXQ7XG59XG5cbnZhciBtYXRjaDEgICAgICAgICA9IC9cXGQvOyAgICAgICAgICAgIC8vICAgICAgIDAgLSA5XG52YXIgbWF0Y2gyICAgICAgICAgPSAvXFxkXFxkLzsgICAgICAgICAgLy8gICAgICAwMCAtIDk5XG52YXIgbWF0Y2gzICAgICAgICAgPSAvXFxkezN9LzsgICAgICAgICAvLyAgICAgMDAwIC0gOTk5XG52YXIgbWF0Y2g0ICAgICAgICAgPSAvXFxkezR9LzsgICAgICAgICAvLyAgICAwMDAwIC0gOTk5OVxudmFyIG1hdGNoNiAgICAgICAgID0gL1srLV0/XFxkezZ9LzsgICAgLy8gLTk5OTk5OSAtIDk5OTk5OVxudmFyIG1hdGNoMXRvMiAgICAgID0gL1xcZFxcZD8vOyAgICAgICAgIC8vICAgICAgIDAgLSA5OVxudmFyIG1hdGNoM3RvNCAgICAgID0gL1xcZFxcZFxcZFxcZD8vOyAgICAgLy8gICAgIDk5OSAtIDk5OTlcbnZhciBtYXRjaDV0bzYgICAgICA9IC9cXGRcXGRcXGRcXGRcXGRcXGQ/LzsgLy8gICA5OTk5OSAtIDk5OTk5OVxudmFyIG1hdGNoMXRvMyAgICAgID0gL1xcZHsxLDN9LzsgICAgICAgLy8gICAgICAgMCAtIDk5OVxudmFyIG1hdGNoMXRvNCAgICAgID0gL1xcZHsxLDR9LzsgICAgICAgLy8gICAgICAgMCAtIDk5OTlcbnZhciBtYXRjaDF0bzYgICAgICA9IC9bKy1dP1xcZHsxLDZ9LzsgIC8vIC05OTk5OTkgLSA5OTk5OTlcblxudmFyIG1hdGNoVW5zaWduZWQgID0gL1xcZCsvOyAgICAgICAgICAgLy8gICAgICAgMCAtIGluZlxudmFyIG1hdGNoU2lnbmVkICAgID0gL1srLV0/XFxkKy87ICAgICAgLy8gICAgLWluZiAtIGluZlxuXG52YXIgbWF0Y2hPZmZzZXQgICAgPSAvWnxbKy1dXFxkXFxkOj9cXGRcXGQvZ2k7IC8vICswMDowMCAtMDA6MDAgKzAwMDAgLTAwMDAgb3IgWlxudmFyIG1hdGNoU2hvcnRPZmZzZXQgPSAvWnxbKy1dXFxkXFxkKD86Oj9cXGRcXGQpPy9naTsgLy8gKzAwIC0wMCArMDA6MDAgLTAwOjAwICswMDAwIC0wMDAwIG9yIFpcblxudmFyIG1hdGNoVGltZXN0YW1wID0gL1srLV0/XFxkKyhcXC5cXGR7MSwzfSk/LzsgLy8gMTIzNDU2Nzg5IDEyMzQ1Njc4OS4xMjNcblxuLy8gYW55IHdvcmQgKG9yIHR3bykgY2hhcmFjdGVycyBvciBudW1iZXJzIGluY2x1ZGluZyB0d28vdGhyZWUgd29yZCBtb250aCBpbiBhcmFiaWMuXG4vLyBpbmNsdWRlcyBzY290dGlzaCBnYWVsaWMgdHdvIHdvcmQgYW5kIGh5cGhlbmF0ZWQgbW9udGhzXG52YXIgbWF0Y2hXb3JkID0gL1swLTldezAsMjU2fVsnYS16XFx1MDBBMC1cXHUwNUZGXFx1MDcwMC1cXHVEN0ZGXFx1RjkwMC1cXHVGRENGXFx1RkRGMC1cXHVGRjA3XFx1RkYxMC1cXHVGRkVGXXsxLDI1Nn18W1xcdTA2MDAtXFx1MDZGRlxcL117MSwyNTZ9KFxccyo/W1xcdTA2MDAtXFx1MDZGRl17MSwyNTZ9KXsxLDJ9L2k7XG5cblxudmFyIHJlZ2V4ZXMgPSB7fTtcblxuZnVuY3Rpb24gYWRkUmVnZXhUb2tlbiAodG9rZW4sIHJlZ2V4LCBzdHJpY3RSZWdleCkge1xuICAgIHJlZ2V4ZXNbdG9rZW5dID0gaXNGdW5jdGlvbihyZWdleCkgPyByZWdleCA6IGZ1bmN0aW9uIChpc1N0cmljdCwgbG9jYWxlRGF0YSkge1xuICAgICAgICByZXR1cm4gKGlzU3RyaWN0ICYmIHN0cmljdFJlZ2V4KSA/IHN0cmljdFJlZ2V4IDogcmVnZXg7XG4gICAgfTtcbn1cblxuZnVuY3Rpb24gZ2V0UGFyc2VSZWdleEZvclRva2VuICh0b2tlbiwgY29uZmlnKSB7XG4gICAgaWYgKCFoYXNPd25Qcm9wKHJlZ2V4ZXMsIHRva2VuKSkge1xuICAgICAgICByZXR1cm4gbmV3IFJlZ0V4cCh1bmVzY2FwZUZvcm1hdCh0b2tlbikpO1xuICAgIH1cblxuICAgIHJldHVybiByZWdleGVzW3Rva2VuXShjb25maWcuX3N0cmljdCwgY29uZmlnLl9sb2NhbGUpO1xufVxuXG4vLyBDb2RlIGZyb20gaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy8zNTYxNDkzL2lzLXRoZXJlLWEtcmVnZXhwLWVzY2FwZS1mdW5jdGlvbi1pbi1qYXZhc2NyaXB0XG5mdW5jdGlvbiB1bmVzY2FwZUZvcm1hdChzKSB7XG4gICAgcmV0dXJuIHJlZ2V4RXNjYXBlKHMucmVwbGFjZSgnXFxcXCcsICcnKS5yZXBsYWNlKC9cXFxcKFxcWyl8XFxcXChcXF0pfFxcWyhbXlxcXVxcW10qKVxcXXxcXFxcKC4pL2csIGZ1bmN0aW9uIChtYXRjaGVkLCBwMSwgcDIsIHAzLCBwNCkge1xuICAgICAgICByZXR1cm4gcDEgfHwgcDIgfHwgcDMgfHwgcDQ7XG4gICAgfSkpO1xufVxuXG5mdW5jdGlvbiByZWdleEVzY2FwZShzKSB7XG4gICAgcmV0dXJuIHMucmVwbGFjZSgvWy1cXC9cXFxcXiQqKz8uKCl8W1xcXXt9XS9nLCAnXFxcXCQmJyk7XG59XG5cbnZhciB0b2tlbnMgPSB7fTtcblxuZnVuY3Rpb24gYWRkUGFyc2VUb2tlbiAodG9rZW4sIGNhbGxiYWNrKSB7XG4gICAgdmFyIGksIGZ1bmMgPSBjYWxsYmFjaztcbiAgICBpZiAodHlwZW9mIHRva2VuID09PSAnc3RyaW5nJykge1xuICAgICAgICB0b2tlbiA9IFt0b2tlbl07XG4gICAgfVxuICAgIGlmIChpc051bWJlcihjYWxsYmFjaykpIHtcbiAgICAgICAgZnVuYyA9IGZ1bmN0aW9uIChpbnB1dCwgYXJyYXkpIHtcbiAgICAgICAgICAgIGFycmF5W2NhbGxiYWNrXSA9IHRvSW50KGlucHV0KTtcbiAgICAgICAgfTtcbiAgICB9XG4gICAgZm9yIChpID0gMDsgaSA8IHRva2VuLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHRva2Vuc1t0b2tlbltpXV0gPSBmdW5jO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gYWRkV2Vla1BhcnNlVG9rZW4gKHRva2VuLCBjYWxsYmFjaykge1xuICAgIGFkZFBhcnNlVG9rZW4odG9rZW4sIGZ1bmN0aW9uIChpbnB1dCwgYXJyYXksIGNvbmZpZywgdG9rZW4pIHtcbiAgICAgICAgY29uZmlnLl93ID0gY29uZmlnLl93IHx8IHt9O1xuICAgICAgICBjYWxsYmFjayhpbnB1dCwgY29uZmlnLl93LCBjb25maWcsIHRva2VuKTtcbiAgICB9KTtcbn1cblxuZnVuY3Rpb24gYWRkVGltZVRvQXJyYXlGcm9tVG9rZW4odG9rZW4sIGlucHV0LCBjb25maWcpIHtcbiAgICBpZiAoaW5wdXQgIT0gbnVsbCAmJiBoYXNPd25Qcm9wKHRva2VucywgdG9rZW4pKSB7XG4gICAgICAgIHRva2Vuc1t0b2tlbl0oaW5wdXQsIGNvbmZpZy5fYSwgY29uZmlnLCB0b2tlbik7XG4gICAgfVxufVxuXG52YXIgWUVBUiA9IDA7XG52YXIgTU9OVEggPSAxO1xudmFyIERBVEUgPSAyO1xudmFyIEhPVVIgPSAzO1xudmFyIE1JTlVURSA9IDQ7XG52YXIgU0VDT05EID0gNTtcbnZhciBNSUxMSVNFQ09ORCA9IDY7XG52YXIgV0VFSyA9IDc7XG52YXIgV0VFS0RBWSA9IDg7XG5cbi8vIEZPUk1BVFRJTkdcblxuYWRkRm9ybWF0VG9rZW4oJ1knLCAwLCAwLCBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIHkgPSB0aGlzLnllYXIoKTtcbiAgICByZXR1cm4geSA8PSA5OTk5ID8gJycgKyB5IDogJysnICsgeTtcbn0pO1xuXG5hZGRGb3JtYXRUb2tlbigwLCBbJ1lZJywgMl0sIDAsIGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy55ZWFyKCkgJSAxMDA7XG59KTtcblxuYWRkRm9ybWF0VG9rZW4oMCwgWydZWVlZJywgICA0XSwgICAgICAgMCwgJ3llYXInKTtcbmFkZEZvcm1hdFRva2VuKDAsIFsnWVlZWVknLCAgNV0sICAgICAgIDAsICd5ZWFyJyk7XG5hZGRGb3JtYXRUb2tlbigwLCBbJ1lZWVlZWScsIDYsIHRydWVdLCAwLCAneWVhcicpO1xuXG4vLyBBTElBU0VTXG5cbmFkZFVuaXRBbGlhcygneWVhcicsICd5Jyk7XG5cbi8vIFBSSU9SSVRJRVNcblxuYWRkVW5pdFByaW9yaXR5KCd5ZWFyJywgMSk7XG5cbi8vIFBBUlNJTkdcblxuYWRkUmVnZXhUb2tlbignWScsICAgICAgbWF0Y2hTaWduZWQpO1xuYWRkUmVnZXhUb2tlbignWVknLCAgICAgbWF0Y2gxdG8yLCBtYXRjaDIpO1xuYWRkUmVnZXhUb2tlbignWVlZWScsICAgbWF0Y2gxdG80LCBtYXRjaDQpO1xuYWRkUmVnZXhUb2tlbignWVlZWVknLCAgbWF0Y2gxdG82LCBtYXRjaDYpO1xuYWRkUmVnZXhUb2tlbignWVlZWVlZJywgbWF0Y2gxdG82LCBtYXRjaDYpO1xuXG5hZGRQYXJzZVRva2VuKFsnWVlZWVknLCAnWVlZWVlZJ10sIFlFQVIpO1xuYWRkUGFyc2VUb2tlbignWVlZWScsIGZ1bmN0aW9uIChpbnB1dCwgYXJyYXkpIHtcbiAgICBhcnJheVtZRUFSXSA9IGlucHV0Lmxlbmd0aCA9PT0gMiA/IGhvb2tzLnBhcnNlVHdvRGlnaXRZZWFyKGlucHV0KSA6IHRvSW50KGlucHV0KTtcbn0pO1xuYWRkUGFyc2VUb2tlbignWVknLCBmdW5jdGlvbiAoaW5wdXQsIGFycmF5KSB7XG4gICAgYXJyYXlbWUVBUl0gPSBob29rcy5wYXJzZVR3b0RpZ2l0WWVhcihpbnB1dCk7XG59KTtcbmFkZFBhcnNlVG9rZW4oJ1knLCBmdW5jdGlvbiAoaW5wdXQsIGFycmF5KSB7XG4gICAgYXJyYXlbWUVBUl0gPSBwYXJzZUludChpbnB1dCwgMTApO1xufSk7XG5cbi8vIEhFTFBFUlNcblxuZnVuY3Rpb24gZGF5c0luWWVhcih5ZWFyKSB7XG4gICAgcmV0dXJuIGlzTGVhcFllYXIoeWVhcikgPyAzNjYgOiAzNjU7XG59XG5cbmZ1bmN0aW9uIGlzTGVhcFllYXIoeWVhcikge1xuICAgIHJldHVybiAoeWVhciAlIDQgPT09IDAgJiYgeWVhciAlIDEwMCAhPT0gMCkgfHwgeWVhciAlIDQwMCA9PT0gMDtcbn1cblxuLy8gSE9PS1NcblxuaG9va3MucGFyc2VUd29EaWdpdFllYXIgPSBmdW5jdGlvbiAoaW5wdXQpIHtcbiAgICByZXR1cm4gdG9JbnQoaW5wdXQpICsgKHRvSW50KGlucHV0KSA+IDY4ID8gMTkwMCA6IDIwMDApO1xufTtcblxuLy8gTU9NRU5UU1xuXG52YXIgZ2V0U2V0WWVhciA9IG1ha2VHZXRTZXQoJ0Z1bGxZZWFyJywgdHJ1ZSk7XG5cbmZ1bmN0aW9uIGdldElzTGVhcFllYXIgKCkge1xuICAgIHJldHVybiBpc0xlYXBZZWFyKHRoaXMueWVhcigpKTtcbn1cblxuZnVuY3Rpb24gbWFrZUdldFNldCAodW5pdCwga2VlcFRpbWUpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIGlmICh2YWx1ZSAhPSBudWxsKSB7XG4gICAgICAgICAgICBzZXQkMSh0aGlzLCB1bml0LCB2YWx1ZSk7XG4gICAgICAgICAgICBob29rcy51cGRhdGVPZmZzZXQodGhpcywga2VlcFRpbWUpO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gZ2V0KHRoaXMsIHVuaXQpO1xuICAgICAgICB9XG4gICAgfTtcbn1cblxuZnVuY3Rpb24gZ2V0IChtb20sIHVuaXQpIHtcbiAgICByZXR1cm4gbW9tLmlzVmFsaWQoKSA/XG4gICAgICAgIG1vbS5fZFsnZ2V0JyArIChtb20uX2lzVVRDID8gJ1VUQycgOiAnJykgKyB1bml0XSgpIDogTmFOO1xufVxuXG5mdW5jdGlvbiBzZXQkMSAobW9tLCB1bml0LCB2YWx1ZSkge1xuICAgIGlmIChtb20uaXNWYWxpZCgpICYmICFpc05hTih2YWx1ZSkpIHtcbiAgICAgICAgaWYgKHVuaXQgPT09ICdGdWxsWWVhcicgJiYgaXNMZWFwWWVhcihtb20ueWVhcigpKSAmJiBtb20ubW9udGgoKSA9PT0gMSAmJiBtb20uZGF0ZSgpID09PSAyOSkge1xuICAgICAgICAgICAgbW9tLl9kWydzZXQnICsgKG1vbS5faXNVVEMgPyAnVVRDJyA6ICcnKSArIHVuaXRdKHZhbHVlLCBtb20ubW9udGgoKSwgZGF5c0luTW9udGgodmFsdWUsIG1vbS5tb250aCgpKSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBtb20uX2RbJ3NldCcgKyAobW9tLl9pc1VUQyA/ICdVVEMnIDogJycpICsgdW5pdF0odmFsdWUpO1xuICAgICAgICB9XG4gICAgfVxufVxuXG4vLyBNT01FTlRTXG5cbmZ1bmN0aW9uIHN0cmluZ0dldCAodW5pdHMpIHtcbiAgICB1bml0cyA9IG5vcm1hbGl6ZVVuaXRzKHVuaXRzKTtcbiAgICBpZiAoaXNGdW5jdGlvbih0aGlzW3VuaXRzXSkpIHtcbiAgICAgICAgcmV0dXJuIHRoaXNbdW5pdHNdKCk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzO1xufVxuXG5cbmZ1bmN0aW9uIHN0cmluZ1NldCAodW5pdHMsIHZhbHVlKSB7XG4gICAgaWYgKHR5cGVvZiB1bml0cyA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgdW5pdHMgPSBub3JtYWxpemVPYmplY3RVbml0cyh1bml0cyk7XG4gICAgICAgIHZhciBwcmlvcml0aXplZCA9IGdldFByaW9yaXRpemVkVW5pdHModW5pdHMpO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHByaW9yaXRpemVkLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB0aGlzW3ByaW9yaXRpemVkW2ldLnVuaXRdKHVuaXRzW3ByaW9yaXRpemVkW2ldLnVuaXRdKTtcbiAgICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAgIHVuaXRzID0gbm9ybWFsaXplVW5pdHModW5pdHMpO1xuICAgICAgICBpZiAoaXNGdW5jdGlvbih0aGlzW3VuaXRzXSkpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzW3VuaXRzXSh2YWx1ZSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHRoaXM7XG59XG5cbmZ1bmN0aW9uIG1vZChuLCB4KSB7XG4gICAgcmV0dXJuICgobiAlIHgpICsgeCkgJSB4O1xufVxuXG52YXIgaW5kZXhPZjtcblxuaWYgKEFycmF5LnByb3RvdHlwZS5pbmRleE9mKSB7XG4gICAgaW5kZXhPZiA9IEFycmF5LnByb3RvdHlwZS5pbmRleE9mO1xufSBlbHNlIHtcbiAgICBpbmRleE9mID0gZnVuY3Rpb24gKG8pIHtcbiAgICAgICAgLy8gSSBrbm93XG4gICAgICAgIHZhciBpO1xuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgdGhpcy5sZW5ndGg7ICsraSkge1xuICAgICAgICAgICAgaWYgKHRoaXNbaV0gPT09IG8pIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gLTE7XG4gICAgfTtcbn1cblxuZnVuY3Rpb24gZGF5c0luTW9udGgoeWVhciwgbW9udGgpIHtcbiAgICBpZiAoaXNOYU4oeWVhcikgfHwgaXNOYU4obW9udGgpKSB7XG4gICAgICAgIHJldHVybiBOYU47XG4gICAgfVxuICAgIHZhciBtb2RNb250aCA9IG1vZChtb250aCwgMTIpO1xuICAgIHllYXIgKz0gKG1vbnRoIC0gbW9kTW9udGgpIC8gMTI7XG4gICAgcmV0dXJuIG1vZE1vbnRoID09PSAxID8gKGlzTGVhcFllYXIoeWVhcikgPyAyOSA6IDI4KSA6ICgzMSAtIG1vZE1vbnRoICUgNyAlIDIpO1xufVxuXG4vLyBGT1JNQVRUSU5HXG5cbmFkZEZvcm1hdFRva2VuKCdNJywgWydNTScsIDJdLCAnTW8nLCBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMubW9udGgoKSArIDE7XG59KTtcblxuYWRkRm9ybWF0VG9rZW4oJ01NTScsIDAsIDAsIGZ1bmN0aW9uIChmb3JtYXQpIHtcbiAgICByZXR1cm4gdGhpcy5sb2NhbGVEYXRhKCkubW9udGhzU2hvcnQodGhpcywgZm9ybWF0KTtcbn0pO1xuXG5hZGRGb3JtYXRUb2tlbignTU1NTScsIDAsIDAsIGZ1bmN0aW9uIChmb3JtYXQpIHtcbiAgICByZXR1cm4gdGhpcy5sb2NhbGVEYXRhKCkubW9udGhzKHRoaXMsIGZvcm1hdCk7XG59KTtcblxuLy8gQUxJQVNFU1xuXG5hZGRVbml0QWxpYXMoJ21vbnRoJywgJ00nKTtcblxuLy8gUFJJT1JJVFlcblxuYWRkVW5pdFByaW9yaXR5KCdtb250aCcsIDgpO1xuXG4vLyBQQVJTSU5HXG5cbmFkZFJlZ2V4VG9rZW4oJ00nLCAgICBtYXRjaDF0bzIpO1xuYWRkUmVnZXhUb2tlbignTU0nLCAgIG1hdGNoMXRvMiwgbWF0Y2gyKTtcbmFkZFJlZ2V4VG9rZW4oJ01NTScsICBmdW5jdGlvbiAoaXNTdHJpY3QsIGxvY2FsZSkge1xuICAgIHJldHVybiBsb2NhbGUubW9udGhzU2hvcnRSZWdleChpc1N0cmljdCk7XG59KTtcbmFkZFJlZ2V4VG9rZW4oJ01NTU0nLCBmdW5jdGlvbiAoaXNTdHJpY3QsIGxvY2FsZSkge1xuICAgIHJldHVybiBsb2NhbGUubW9udGhzUmVnZXgoaXNTdHJpY3QpO1xufSk7XG5cbmFkZFBhcnNlVG9rZW4oWydNJywgJ01NJ10sIGZ1bmN0aW9uIChpbnB1dCwgYXJyYXkpIHtcbiAgICBhcnJheVtNT05USF0gPSB0b0ludChpbnB1dCkgLSAxO1xufSk7XG5cbmFkZFBhcnNlVG9rZW4oWydNTU0nLCAnTU1NTSddLCBmdW5jdGlvbiAoaW5wdXQsIGFycmF5LCBjb25maWcsIHRva2VuKSB7XG4gICAgdmFyIG1vbnRoID0gY29uZmlnLl9sb2NhbGUubW9udGhzUGFyc2UoaW5wdXQsIHRva2VuLCBjb25maWcuX3N0cmljdCk7XG4gICAgLy8gaWYgd2UgZGlkbid0IGZpbmQgYSBtb250aCBuYW1lLCBtYXJrIHRoZSBkYXRlIGFzIGludmFsaWQuXG4gICAgaWYgKG1vbnRoICE9IG51bGwpIHtcbiAgICAgICAgYXJyYXlbTU9OVEhdID0gbW9udGg7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgZ2V0UGFyc2luZ0ZsYWdzKGNvbmZpZykuaW52YWxpZE1vbnRoID0gaW5wdXQ7XG4gICAgfVxufSk7XG5cbi8vIExPQ0FMRVNcblxudmFyIE1PTlRIU19JTl9GT1JNQVQgPSAvRFtvRF0/KFxcW1teXFxbXFxdXSpcXF18XFxzKStNTU1NPy87XG52YXIgZGVmYXVsdExvY2FsZU1vbnRocyA9ICdKYW51YXJ5X0ZlYnJ1YXJ5X01hcmNoX0FwcmlsX01heV9KdW5lX0p1bHlfQXVndXN0X1NlcHRlbWJlcl9PY3RvYmVyX05vdmVtYmVyX0RlY2VtYmVyJy5zcGxpdCgnXycpO1xuZnVuY3Rpb24gbG9jYWxlTW9udGhzIChtLCBmb3JtYXQpIHtcbiAgICBpZiAoIW0pIHtcbiAgICAgICAgcmV0dXJuIGlzQXJyYXkodGhpcy5fbW9udGhzKSA/IHRoaXMuX21vbnRocyA6XG4gICAgICAgICAgICB0aGlzLl9tb250aHNbJ3N0YW5kYWxvbmUnXTtcbiAgICB9XG4gICAgcmV0dXJuIGlzQXJyYXkodGhpcy5fbW9udGhzKSA/IHRoaXMuX21vbnRoc1ttLm1vbnRoKCldIDpcbiAgICAgICAgdGhpcy5fbW9udGhzWyh0aGlzLl9tb250aHMuaXNGb3JtYXQgfHwgTU9OVEhTX0lOX0ZPUk1BVCkudGVzdChmb3JtYXQpID8gJ2Zvcm1hdCcgOiAnc3RhbmRhbG9uZSddW20ubW9udGgoKV07XG59XG5cbnZhciBkZWZhdWx0TG9jYWxlTW9udGhzU2hvcnQgPSAnSmFuX0ZlYl9NYXJfQXByX01heV9KdW5fSnVsX0F1Z19TZXBfT2N0X05vdl9EZWMnLnNwbGl0KCdfJyk7XG5mdW5jdGlvbiBsb2NhbGVNb250aHNTaG9ydCAobSwgZm9ybWF0KSB7XG4gICAgaWYgKCFtKSB7XG4gICAgICAgIHJldHVybiBpc0FycmF5KHRoaXMuX21vbnRoc1Nob3J0KSA/IHRoaXMuX21vbnRoc1Nob3J0IDpcbiAgICAgICAgICAgIHRoaXMuX21vbnRoc1Nob3J0WydzdGFuZGFsb25lJ107XG4gICAgfVxuICAgIHJldHVybiBpc0FycmF5KHRoaXMuX21vbnRoc1Nob3J0KSA/IHRoaXMuX21vbnRoc1Nob3J0W20ubW9udGgoKV0gOlxuICAgICAgICB0aGlzLl9tb250aHNTaG9ydFtNT05USFNfSU5fRk9STUFULnRlc3QoZm9ybWF0KSA/ICdmb3JtYXQnIDogJ3N0YW5kYWxvbmUnXVttLm1vbnRoKCldO1xufVxuXG5mdW5jdGlvbiBoYW5kbGVTdHJpY3RQYXJzZShtb250aE5hbWUsIGZvcm1hdCwgc3RyaWN0KSB7XG4gICAgdmFyIGksIGlpLCBtb20sIGxsYyA9IG1vbnRoTmFtZS50b0xvY2FsZUxvd2VyQ2FzZSgpO1xuICAgIGlmICghdGhpcy5fbW9udGhzUGFyc2UpIHtcbiAgICAgICAgLy8gdGhpcyBpcyBub3QgdXNlZFxuICAgICAgICB0aGlzLl9tb250aHNQYXJzZSA9IFtdO1xuICAgICAgICB0aGlzLl9sb25nTW9udGhzUGFyc2UgPSBbXTtcbiAgICAgICAgdGhpcy5fc2hvcnRNb250aHNQYXJzZSA9IFtdO1xuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgMTI7ICsraSkge1xuICAgICAgICAgICAgbW9tID0gY3JlYXRlVVRDKFsyMDAwLCBpXSk7XG4gICAgICAgICAgICB0aGlzLl9zaG9ydE1vbnRoc1BhcnNlW2ldID0gdGhpcy5tb250aHNTaG9ydChtb20sICcnKS50b0xvY2FsZUxvd2VyQ2FzZSgpO1xuICAgICAgICAgICAgdGhpcy5fbG9uZ01vbnRoc1BhcnNlW2ldID0gdGhpcy5tb250aHMobW9tLCAnJykudG9Mb2NhbGVMb3dlckNhc2UoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGlmIChzdHJpY3QpIHtcbiAgICAgICAgaWYgKGZvcm1hdCA9PT0gJ01NTScpIHtcbiAgICAgICAgICAgIGlpID0gaW5kZXhPZi5jYWxsKHRoaXMuX3Nob3J0TW9udGhzUGFyc2UsIGxsYyk7XG4gICAgICAgICAgICByZXR1cm4gaWkgIT09IC0xID8gaWkgOiBudWxsO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWkgPSBpbmRleE9mLmNhbGwodGhpcy5fbG9uZ01vbnRoc1BhcnNlLCBsbGMpO1xuICAgICAgICAgICAgcmV0dXJuIGlpICE9PSAtMSA/IGlpIDogbnVsbDtcbiAgICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAgIGlmIChmb3JtYXQgPT09ICdNTU0nKSB7XG4gICAgICAgICAgICBpaSA9IGluZGV4T2YuY2FsbCh0aGlzLl9zaG9ydE1vbnRoc1BhcnNlLCBsbGMpO1xuICAgICAgICAgICAgaWYgKGlpICE9PSAtMSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBpaTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlpID0gaW5kZXhPZi5jYWxsKHRoaXMuX2xvbmdNb250aHNQYXJzZSwgbGxjKTtcbiAgICAgICAgICAgIHJldHVybiBpaSAhPT0gLTEgPyBpaSA6IG51bGw7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpaSA9IGluZGV4T2YuY2FsbCh0aGlzLl9sb25nTW9udGhzUGFyc2UsIGxsYyk7XG4gICAgICAgICAgICBpZiAoaWkgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGlpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWkgPSBpbmRleE9mLmNhbGwodGhpcy5fc2hvcnRNb250aHNQYXJzZSwgbGxjKTtcbiAgICAgICAgICAgIHJldHVybiBpaSAhPT0gLTEgPyBpaSA6IG51bGw7XG4gICAgICAgIH1cbiAgICB9XG59XG5cbmZ1bmN0aW9uIGxvY2FsZU1vbnRoc1BhcnNlIChtb250aE5hbWUsIGZvcm1hdCwgc3RyaWN0KSB7XG4gICAgdmFyIGksIG1vbSwgcmVnZXg7XG5cbiAgICBpZiAodGhpcy5fbW9udGhzUGFyc2VFeGFjdCkge1xuICAgICAgICByZXR1cm4gaGFuZGxlU3RyaWN0UGFyc2UuY2FsbCh0aGlzLCBtb250aE5hbWUsIGZvcm1hdCwgc3RyaWN0KTtcbiAgICB9XG5cbiAgICBpZiAoIXRoaXMuX21vbnRoc1BhcnNlKSB7XG4gICAgICAgIHRoaXMuX21vbnRoc1BhcnNlID0gW107XG4gICAgICAgIHRoaXMuX2xvbmdNb250aHNQYXJzZSA9IFtdO1xuICAgICAgICB0aGlzLl9zaG9ydE1vbnRoc1BhcnNlID0gW107XG4gICAgfVxuXG4gICAgLy8gVE9ETzogYWRkIHNvcnRpbmdcbiAgICAvLyBTb3J0aW5nIG1ha2VzIHN1cmUgaWYgb25lIG1vbnRoIChvciBhYmJyKSBpcyBhIHByZWZpeCBvZiBhbm90aGVyXG4gICAgLy8gc2VlIHNvcnRpbmcgaW4gY29tcHV0ZU1vbnRoc1BhcnNlXG4gICAgZm9yIChpID0gMDsgaSA8IDEyOyBpKyspIHtcbiAgICAgICAgLy8gbWFrZSB0aGUgcmVnZXggaWYgd2UgZG9uJ3QgaGF2ZSBpdCBhbHJlYWR5XG4gICAgICAgIG1vbSA9IGNyZWF0ZVVUQyhbMjAwMCwgaV0pO1xuICAgICAgICBpZiAoc3RyaWN0ICYmICF0aGlzLl9sb25nTW9udGhzUGFyc2VbaV0pIHtcbiAgICAgICAgICAgIHRoaXMuX2xvbmdNb250aHNQYXJzZVtpXSA9IG5ldyBSZWdFeHAoJ14nICsgdGhpcy5tb250aHMobW9tLCAnJykucmVwbGFjZSgnLicsICcnKSArICckJywgJ2knKTtcbiAgICAgICAgICAgIHRoaXMuX3Nob3J0TW9udGhzUGFyc2VbaV0gPSBuZXcgUmVnRXhwKCdeJyArIHRoaXMubW9udGhzU2hvcnQobW9tLCAnJykucmVwbGFjZSgnLicsICcnKSArICckJywgJ2knKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIXN0cmljdCAmJiAhdGhpcy5fbW9udGhzUGFyc2VbaV0pIHtcbiAgICAgICAgICAgIHJlZ2V4ID0gJ14nICsgdGhpcy5tb250aHMobW9tLCAnJykgKyAnfF4nICsgdGhpcy5tb250aHNTaG9ydChtb20sICcnKTtcbiAgICAgICAgICAgIHRoaXMuX21vbnRoc1BhcnNlW2ldID0gbmV3IFJlZ0V4cChyZWdleC5yZXBsYWNlKCcuJywgJycpLCAnaScpO1xuICAgICAgICB9XG4gICAgICAgIC8vIHRlc3QgdGhlIHJlZ2V4XG4gICAgICAgIGlmIChzdHJpY3QgJiYgZm9ybWF0ID09PSAnTU1NTScgJiYgdGhpcy5fbG9uZ01vbnRoc1BhcnNlW2ldLnRlc3QobW9udGhOYW1lKSkge1xuICAgICAgICAgICAgcmV0dXJuIGk7XG4gICAgICAgIH0gZWxzZSBpZiAoc3RyaWN0ICYmIGZvcm1hdCA9PT0gJ01NTScgJiYgdGhpcy5fc2hvcnRNb250aHNQYXJzZVtpXS50ZXN0KG1vbnRoTmFtZSkpIHtcbiAgICAgICAgICAgIHJldHVybiBpO1xuICAgICAgICB9IGVsc2UgaWYgKCFzdHJpY3QgJiYgdGhpcy5fbW9udGhzUGFyc2VbaV0udGVzdChtb250aE5hbWUpKSB7XG4gICAgICAgICAgICByZXR1cm4gaTtcbiAgICAgICAgfVxuICAgIH1cbn1cblxuLy8gTU9NRU5UU1xuXG5mdW5jdGlvbiBzZXRNb250aCAobW9tLCB2YWx1ZSkge1xuICAgIHZhciBkYXlPZk1vbnRoO1xuXG4gICAgaWYgKCFtb20uaXNWYWxpZCgpKSB7XG4gICAgICAgIC8vIE5vIG9wXG4gICAgICAgIHJldHVybiBtb207XG4gICAgfVxuXG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgaWYgKC9eXFxkKyQvLnRlc3QodmFsdWUpKSB7XG4gICAgICAgICAgICB2YWx1ZSA9IHRvSW50KHZhbHVlKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHZhbHVlID0gbW9tLmxvY2FsZURhdGEoKS5tb250aHNQYXJzZSh2YWx1ZSk7XG4gICAgICAgICAgICAvLyBUT0RPOiBBbm90aGVyIHNpbGVudCBmYWlsdXJlP1xuICAgICAgICAgICAgaWYgKCFpc051bWJlcih2YWx1ZSkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbW9tO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgZGF5T2ZNb250aCA9IE1hdGgubWluKG1vbS5kYXRlKCksIGRheXNJbk1vbnRoKG1vbS55ZWFyKCksIHZhbHVlKSk7XG4gICAgbW9tLl9kWydzZXQnICsgKG1vbS5faXNVVEMgPyAnVVRDJyA6ICcnKSArICdNb250aCddKHZhbHVlLCBkYXlPZk1vbnRoKTtcbiAgICByZXR1cm4gbW9tO1xufVxuXG5mdW5jdGlvbiBnZXRTZXRNb250aCAodmFsdWUpIHtcbiAgICBpZiAodmFsdWUgIT0gbnVsbCkge1xuICAgICAgICBzZXRNb250aCh0aGlzLCB2YWx1ZSk7XG4gICAgICAgIGhvb2tzLnVwZGF0ZU9mZnNldCh0aGlzLCB0cnVlKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIGdldCh0aGlzLCAnTW9udGgnKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGdldERheXNJbk1vbnRoICgpIHtcbiAgICByZXR1cm4gZGF5c0luTW9udGgodGhpcy55ZWFyKCksIHRoaXMubW9udGgoKSk7XG59XG5cbnZhciBkZWZhdWx0TW9udGhzU2hvcnRSZWdleCA9IG1hdGNoV29yZDtcbmZ1bmN0aW9uIG1vbnRoc1Nob3J0UmVnZXggKGlzU3RyaWN0KSB7XG4gICAgaWYgKHRoaXMuX21vbnRoc1BhcnNlRXhhY3QpIHtcbiAgICAgICAgaWYgKCFoYXNPd25Qcm9wKHRoaXMsICdfbW9udGhzUmVnZXgnKSkge1xuICAgICAgICAgICAgY29tcHV0ZU1vbnRoc1BhcnNlLmNhbGwodGhpcyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGlzU3RyaWN0KSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fbW9udGhzU2hvcnRTdHJpY3RSZWdleDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9tb250aHNTaG9ydFJlZ2V4O1xuICAgICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgICAgaWYgKCFoYXNPd25Qcm9wKHRoaXMsICdfbW9udGhzU2hvcnRSZWdleCcpKSB7XG4gICAgICAgICAgICB0aGlzLl9tb250aHNTaG9ydFJlZ2V4ID0gZGVmYXVsdE1vbnRoc1Nob3J0UmVnZXg7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuX21vbnRoc1Nob3J0U3RyaWN0UmVnZXggJiYgaXNTdHJpY3QgP1xuICAgICAgICAgICAgdGhpcy5fbW9udGhzU2hvcnRTdHJpY3RSZWdleCA6IHRoaXMuX21vbnRoc1Nob3J0UmVnZXg7XG4gICAgfVxufVxuXG52YXIgZGVmYXVsdE1vbnRoc1JlZ2V4ID0gbWF0Y2hXb3JkO1xuZnVuY3Rpb24gbW9udGhzUmVnZXggKGlzU3RyaWN0KSB7XG4gICAgaWYgKHRoaXMuX21vbnRoc1BhcnNlRXhhY3QpIHtcbiAgICAgICAgaWYgKCFoYXNPd25Qcm9wKHRoaXMsICdfbW9udGhzUmVnZXgnKSkge1xuICAgICAgICAgICAgY29tcHV0ZU1vbnRoc1BhcnNlLmNhbGwodGhpcyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGlzU3RyaWN0KSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fbW9udGhzU3RyaWN0UmVnZXg7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fbW9udGhzUmVnZXg7XG4gICAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgICBpZiAoIWhhc093blByb3AodGhpcywgJ19tb250aHNSZWdleCcpKSB7XG4gICAgICAgICAgICB0aGlzLl9tb250aHNSZWdleCA9IGRlZmF1bHRNb250aHNSZWdleDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5fbW9udGhzU3RyaWN0UmVnZXggJiYgaXNTdHJpY3QgP1xuICAgICAgICAgICAgdGhpcy5fbW9udGhzU3RyaWN0UmVnZXggOiB0aGlzLl9tb250aHNSZWdleDtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGNvbXB1dGVNb250aHNQYXJzZSAoKSB7XG4gICAgZnVuY3Rpb24gY21wTGVuUmV2KGEsIGIpIHtcbiAgICAgICAgcmV0dXJuIGIubGVuZ3RoIC0gYS5sZW5ndGg7XG4gICAgfVxuXG4gICAgdmFyIHNob3J0UGllY2VzID0gW10sIGxvbmdQaWVjZXMgPSBbXSwgbWl4ZWRQaWVjZXMgPSBbXSxcbiAgICAgICAgaSwgbW9tO1xuICAgIGZvciAoaSA9IDA7IGkgPCAxMjsgaSsrKSB7XG4gICAgICAgIC8vIG1ha2UgdGhlIHJlZ2V4IGlmIHdlIGRvbid0IGhhdmUgaXQgYWxyZWFkeVxuICAgICAgICBtb20gPSBjcmVhdGVVVEMoWzIwMDAsIGldKTtcbiAgICAgICAgc2hvcnRQaWVjZXMucHVzaCh0aGlzLm1vbnRoc1Nob3J0KG1vbSwgJycpKTtcbiAgICAgICAgbG9uZ1BpZWNlcy5wdXNoKHRoaXMubW9udGhzKG1vbSwgJycpKTtcbiAgICAgICAgbWl4ZWRQaWVjZXMucHVzaCh0aGlzLm1vbnRocyhtb20sICcnKSk7XG4gICAgICAgIG1peGVkUGllY2VzLnB1c2godGhpcy5tb250aHNTaG9ydChtb20sICcnKSk7XG4gICAgfVxuICAgIC8vIFNvcnRpbmcgbWFrZXMgc3VyZSBpZiBvbmUgbW9udGggKG9yIGFiYnIpIGlzIGEgcHJlZml4IG9mIGFub3RoZXIgaXRcbiAgICAvLyB3aWxsIG1hdGNoIHRoZSBsb25nZXIgcGllY2UuXG4gICAgc2hvcnRQaWVjZXMuc29ydChjbXBMZW5SZXYpO1xuICAgIGxvbmdQaWVjZXMuc29ydChjbXBMZW5SZXYpO1xuICAgIG1peGVkUGllY2VzLnNvcnQoY21wTGVuUmV2KTtcbiAgICBmb3IgKGkgPSAwOyBpIDwgMTI7IGkrKykge1xuICAgICAgICBzaG9ydFBpZWNlc1tpXSA9IHJlZ2V4RXNjYXBlKHNob3J0UGllY2VzW2ldKTtcbiAgICAgICAgbG9uZ1BpZWNlc1tpXSA9IHJlZ2V4RXNjYXBlKGxvbmdQaWVjZXNbaV0pO1xuICAgIH1cbiAgICBmb3IgKGkgPSAwOyBpIDwgMjQ7IGkrKykge1xuICAgICAgICBtaXhlZFBpZWNlc1tpXSA9IHJlZ2V4RXNjYXBlKG1peGVkUGllY2VzW2ldKTtcbiAgICB9XG5cbiAgICB0aGlzLl9tb250aHNSZWdleCA9IG5ldyBSZWdFeHAoJ14oJyArIG1peGVkUGllY2VzLmpvaW4oJ3wnKSArICcpJywgJ2knKTtcbiAgICB0aGlzLl9tb250aHNTaG9ydFJlZ2V4ID0gdGhpcy5fbW9udGhzUmVnZXg7XG4gICAgdGhpcy5fbW9udGhzU3RyaWN0UmVnZXggPSBuZXcgUmVnRXhwKCdeKCcgKyBsb25nUGllY2VzLmpvaW4oJ3wnKSArICcpJywgJ2knKTtcbiAgICB0aGlzLl9tb250aHNTaG9ydFN0cmljdFJlZ2V4ID0gbmV3IFJlZ0V4cCgnXignICsgc2hvcnRQaWVjZXMuam9pbignfCcpICsgJyknLCAnaScpO1xufVxuXG5mdW5jdGlvbiBjcmVhdGVEYXRlICh5LCBtLCBkLCBoLCBNLCBzLCBtcykge1xuICAgIC8vIGNhbid0IGp1c3QgYXBwbHkoKSB0byBjcmVhdGUgYSBkYXRlOlxuICAgIC8vIGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vcS8xODEzNDhcbiAgICB2YXIgZGF0ZSA9IG5ldyBEYXRlKHksIG0sIGQsIGgsIE0sIHMsIG1zKTtcblxuICAgIC8vIHRoZSBkYXRlIGNvbnN0cnVjdG9yIHJlbWFwcyB5ZWFycyAwLTk5IHRvIDE5MDAtMTk5OVxuICAgIGlmICh5IDwgMTAwICYmIHkgPj0gMCAmJiBpc0Zpbml0ZShkYXRlLmdldEZ1bGxZZWFyKCkpKSB7XG4gICAgICAgIGRhdGUuc2V0RnVsbFllYXIoeSk7XG4gICAgfVxuICAgIHJldHVybiBkYXRlO1xufVxuXG5mdW5jdGlvbiBjcmVhdGVVVENEYXRlICh5KSB7XG4gICAgdmFyIGRhdGUgPSBuZXcgRGF0ZShEYXRlLlVUQy5hcHBseShudWxsLCBhcmd1bWVudHMpKTtcblxuICAgIC8vIHRoZSBEYXRlLlVUQyBmdW5jdGlvbiByZW1hcHMgeWVhcnMgMC05OSB0byAxOTAwLTE5OTlcbiAgICBpZiAoeSA8IDEwMCAmJiB5ID49IDAgJiYgaXNGaW5pdGUoZGF0ZS5nZXRVVENGdWxsWWVhcigpKSkge1xuICAgICAgICBkYXRlLnNldFVUQ0Z1bGxZZWFyKHkpO1xuICAgIH1cbiAgICByZXR1cm4gZGF0ZTtcbn1cblxuLy8gc3RhcnQtb2YtZmlyc3Qtd2VlayAtIHN0YXJ0LW9mLXllYXJcbmZ1bmN0aW9uIGZpcnN0V2Vla09mZnNldCh5ZWFyLCBkb3csIGRveSkge1xuICAgIHZhciAvLyBmaXJzdC13ZWVrIGRheSAtLSB3aGljaCBqYW51YXJ5IGlzIGFsd2F5cyBpbiB0aGUgZmlyc3Qgd2VlayAoNCBmb3IgaXNvLCAxIGZvciBvdGhlcilcbiAgICAgICAgZndkID0gNyArIGRvdyAtIGRveSxcbiAgICAgICAgLy8gZmlyc3Qtd2VlayBkYXkgbG9jYWwgd2Vla2RheSAtLSB3aGljaCBsb2NhbCB3ZWVrZGF5IGlzIGZ3ZFxuICAgICAgICBmd2RsdyA9ICg3ICsgY3JlYXRlVVRDRGF0ZSh5ZWFyLCAwLCBmd2QpLmdldFVUQ0RheSgpIC0gZG93KSAlIDc7XG5cbiAgICByZXR1cm4gLWZ3ZGx3ICsgZndkIC0gMTtcbn1cblxuLy8gaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvSVNPX3dlZWtfZGF0ZSNDYWxjdWxhdGluZ19hX2RhdGVfZ2l2ZW5fdGhlX3llYXIuMkNfd2Vla19udW1iZXJfYW5kX3dlZWtkYXlcbmZ1bmN0aW9uIGRheU9mWWVhckZyb21XZWVrcyh5ZWFyLCB3ZWVrLCB3ZWVrZGF5LCBkb3csIGRveSkge1xuICAgIHZhciBsb2NhbFdlZWtkYXkgPSAoNyArIHdlZWtkYXkgLSBkb3cpICUgNyxcbiAgICAgICAgd2Vla09mZnNldCA9IGZpcnN0V2Vla09mZnNldCh5ZWFyLCBkb3csIGRveSksXG4gICAgICAgIGRheU9mWWVhciA9IDEgKyA3ICogKHdlZWsgLSAxKSArIGxvY2FsV2Vla2RheSArIHdlZWtPZmZzZXQsXG4gICAgICAgIHJlc1llYXIsIHJlc0RheU9mWWVhcjtcblxuICAgIGlmIChkYXlPZlllYXIgPD0gMCkge1xuICAgICAgICByZXNZZWFyID0geWVhciAtIDE7XG4gICAgICAgIHJlc0RheU9mWWVhciA9IGRheXNJblllYXIocmVzWWVhcikgKyBkYXlPZlllYXI7XG4gICAgfSBlbHNlIGlmIChkYXlPZlllYXIgPiBkYXlzSW5ZZWFyKHllYXIpKSB7XG4gICAgICAgIHJlc1llYXIgPSB5ZWFyICsgMTtcbiAgICAgICAgcmVzRGF5T2ZZZWFyID0gZGF5T2ZZZWFyIC0gZGF5c0luWWVhcih5ZWFyKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICByZXNZZWFyID0geWVhcjtcbiAgICAgICAgcmVzRGF5T2ZZZWFyID0gZGF5T2ZZZWFyO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICAgIHllYXI6IHJlc1llYXIsXG4gICAgICAgIGRheU9mWWVhcjogcmVzRGF5T2ZZZWFyXG4gICAgfTtcbn1cblxuZnVuY3Rpb24gd2Vla09mWWVhcihtb20sIGRvdywgZG95KSB7XG4gICAgdmFyIHdlZWtPZmZzZXQgPSBmaXJzdFdlZWtPZmZzZXQobW9tLnllYXIoKSwgZG93LCBkb3kpLFxuICAgICAgICB3ZWVrID0gTWF0aC5mbG9vcigobW9tLmRheU9mWWVhcigpIC0gd2Vla09mZnNldCAtIDEpIC8gNykgKyAxLFxuICAgICAgICByZXNXZWVrLCByZXNZZWFyO1xuXG4gICAgaWYgKHdlZWsgPCAxKSB7XG4gICAgICAgIHJlc1llYXIgPSBtb20ueWVhcigpIC0gMTtcbiAgICAgICAgcmVzV2VlayA9IHdlZWsgKyB3ZWVrc0luWWVhcihyZXNZZWFyLCBkb3csIGRveSk7XG4gICAgfSBlbHNlIGlmICh3ZWVrID4gd2Vla3NJblllYXIobW9tLnllYXIoKSwgZG93LCBkb3kpKSB7XG4gICAgICAgIHJlc1dlZWsgPSB3ZWVrIC0gd2Vla3NJblllYXIobW9tLnllYXIoKSwgZG93LCBkb3kpO1xuICAgICAgICByZXNZZWFyID0gbW9tLnllYXIoKSArIDE7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcmVzWWVhciA9IG1vbS55ZWFyKCk7XG4gICAgICAgIHJlc1dlZWsgPSB3ZWVrO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICAgIHdlZWs6IHJlc1dlZWssXG4gICAgICAgIHllYXI6IHJlc1llYXJcbiAgICB9O1xufVxuXG5mdW5jdGlvbiB3ZWVrc0luWWVhcih5ZWFyLCBkb3csIGRveSkge1xuICAgIHZhciB3ZWVrT2Zmc2V0ID0gZmlyc3RXZWVrT2Zmc2V0KHllYXIsIGRvdywgZG95KSxcbiAgICAgICAgd2Vla09mZnNldE5leHQgPSBmaXJzdFdlZWtPZmZzZXQoeWVhciArIDEsIGRvdywgZG95KTtcbiAgICByZXR1cm4gKGRheXNJblllYXIoeWVhcikgLSB3ZWVrT2Zmc2V0ICsgd2Vla09mZnNldE5leHQpIC8gNztcbn1cblxuLy8gRk9STUFUVElOR1xuXG5hZGRGb3JtYXRUb2tlbigndycsIFsnd3cnLCAyXSwgJ3dvJywgJ3dlZWsnKTtcbmFkZEZvcm1hdFRva2VuKCdXJywgWydXVycsIDJdLCAnV28nLCAnaXNvV2VlaycpO1xuXG4vLyBBTElBU0VTXG5cbmFkZFVuaXRBbGlhcygnd2VlaycsICd3Jyk7XG5hZGRVbml0QWxpYXMoJ2lzb1dlZWsnLCAnVycpO1xuXG4vLyBQUklPUklUSUVTXG5cbmFkZFVuaXRQcmlvcml0eSgnd2VlaycsIDUpO1xuYWRkVW5pdFByaW9yaXR5KCdpc29XZWVrJywgNSk7XG5cbi8vIFBBUlNJTkdcblxuYWRkUmVnZXhUb2tlbigndycsICBtYXRjaDF0bzIpO1xuYWRkUmVnZXhUb2tlbignd3cnLCBtYXRjaDF0bzIsIG1hdGNoMik7XG5hZGRSZWdleFRva2VuKCdXJywgIG1hdGNoMXRvMik7XG5hZGRSZWdleFRva2VuKCdXVycsIG1hdGNoMXRvMiwgbWF0Y2gyKTtcblxuYWRkV2Vla1BhcnNlVG9rZW4oWyd3JywgJ3d3JywgJ1cnLCAnV1cnXSwgZnVuY3Rpb24gKGlucHV0LCB3ZWVrLCBjb25maWcsIHRva2VuKSB7XG4gICAgd2Vla1t0b2tlbi5zdWJzdHIoMCwgMSldID0gdG9JbnQoaW5wdXQpO1xufSk7XG5cbi8vIEhFTFBFUlNcblxuLy8gTE9DQUxFU1xuXG5mdW5jdGlvbiBsb2NhbGVXZWVrIChtb20pIHtcbiAgICByZXR1cm4gd2Vla09mWWVhcihtb20sIHRoaXMuX3dlZWsuZG93LCB0aGlzLl93ZWVrLmRveSkud2Vlaztcbn1cblxudmFyIGRlZmF1bHRMb2NhbGVXZWVrID0ge1xuICAgIGRvdyA6IDAsIC8vIFN1bmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgIGRveSA6IDYgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDFzdCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbn07XG5cbmZ1bmN0aW9uIGxvY2FsZUZpcnN0RGF5T2ZXZWVrICgpIHtcbiAgICByZXR1cm4gdGhpcy5fd2Vlay5kb3c7XG59XG5cbmZ1bmN0aW9uIGxvY2FsZUZpcnN0RGF5T2ZZZWFyICgpIHtcbiAgICByZXR1cm4gdGhpcy5fd2Vlay5kb3k7XG59XG5cbi8vIE1PTUVOVFNcblxuZnVuY3Rpb24gZ2V0U2V0V2VlayAoaW5wdXQpIHtcbiAgICB2YXIgd2VlayA9IHRoaXMubG9jYWxlRGF0YSgpLndlZWsodGhpcyk7XG4gICAgcmV0dXJuIGlucHV0ID09IG51bGwgPyB3ZWVrIDogdGhpcy5hZGQoKGlucHV0IC0gd2VlaykgKiA3LCAnZCcpO1xufVxuXG5mdW5jdGlvbiBnZXRTZXRJU09XZWVrIChpbnB1dCkge1xuICAgIHZhciB3ZWVrID0gd2Vla09mWWVhcih0aGlzLCAxLCA0KS53ZWVrO1xuICAgIHJldHVybiBpbnB1dCA9PSBudWxsID8gd2VlayA6IHRoaXMuYWRkKChpbnB1dCAtIHdlZWspICogNywgJ2QnKTtcbn1cblxuLy8gRk9STUFUVElOR1xuXG5hZGRGb3JtYXRUb2tlbignZCcsIDAsICdkbycsICdkYXknKTtcblxuYWRkRm9ybWF0VG9rZW4oJ2RkJywgMCwgMCwgZnVuY3Rpb24gKGZvcm1hdCkge1xuICAgIHJldHVybiB0aGlzLmxvY2FsZURhdGEoKS53ZWVrZGF5c01pbih0aGlzLCBmb3JtYXQpO1xufSk7XG5cbmFkZEZvcm1hdFRva2VuKCdkZGQnLCAwLCAwLCBmdW5jdGlvbiAoZm9ybWF0KSB7XG4gICAgcmV0dXJuIHRoaXMubG9jYWxlRGF0YSgpLndlZWtkYXlzU2hvcnQodGhpcywgZm9ybWF0KTtcbn0pO1xuXG5hZGRGb3JtYXRUb2tlbignZGRkZCcsIDAsIDAsIGZ1bmN0aW9uIChmb3JtYXQpIHtcbiAgICByZXR1cm4gdGhpcy5sb2NhbGVEYXRhKCkud2Vla2RheXModGhpcywgZm9ybWF0KTtcbn0pO1xuXG5hZGRGb3JtYXRUb2tlbignZScsIDAsIDAsICd3ZWVrZGF5Jyk7XG5hZGRGb3JtYXRUb2tlbignRScsIDAsIDAsICdpc29XZWVrZGF5Jyk7XG5cbi8vIEFMSUFTRVNcblxuYWRkVW5pdEFsaWFzKCdkYXknLCAnZCcpO1xuYWRkVW5pdEFsaWFzKCd3ZWVrZGF5JywgJ2UnKTtcbmFkZFVuaXRBbGlhcygnaXNvV2Vla2RheScsICdFJyk7XG5cbi8vIFBSSU9SSVRZXG5hZGRVbml0UHJpb3JpdHkoJ2RheScsIDExKTtcbmFkZFVuaXRQcmlvcml0eSgnd2Vla2RheScsIDExKTtcbmFkZFVuaXRQcmlvcml0eSgnaXNvV2Vla2RheScsIDExKTtcblxuLy8gUEFSU0lOR1xuXG5hZGRSZWdleFRva2VuKCdkJywgICAgbWF0Y2gxdG8yKTtcbmFkZFJlZ2V4VG9rZW4oJ2UnLCAgICBtYXRjaDF0bzIpO1xuYWRkUmVnZXhUb2tlbignRScsICAgIG1hdGNoMXRvMik7XG5hZGRSZWdleFRva2VuKCdkZCcsICAgZnVuY3Rpb24gKGlzU3RyaWN0LCBsb2NhbGUpIHtcbiAgICByZXR1cm4gbG9jYWxlLndlZWtkYXlzTWluUmVnZXgoaXNTdHJpY3QpO1xufSk7XG5hZGRSZWdleFRva2VuKCdkZGQnLCAgIGZ1bmN0aW9uIChpc1N0cmljdCwgbG9jYWxlKSB7XG4gICAgcmV0dXJuIGxvY2FsZS53ZWVrZGF5c1Nob3J0UmVnZXgoaXNTdHJpY3QpO1xufSk7XG5hZGRSZWdleFRva2VuKCdkZGRkJywgICBmdW5jdGlvbiAoaXNTdHJpY3QsIGxvY2FsZSkge1xuICAgIHJldHVybiBsb2NhbGUud2Vla2RheXNSZWdleChpc1N0cmljdCk7XG59KTtcblxuYWRkV2Vla1BhcnNlVG9rZW4oWydkZCcsICdkZGQnLCAnZGRkZCddLCBmdW5jdGlvbiAoaW5wdXQsIHdlZWssIGNvbmZpZywgdG9rZW4pIHtcbiAgICB2YXIgd2Vla2RheSA9IGNvbmZpZy5fbG9jYWxlLndlZWtkYXlzUGFyc2UoaW5wdXQsIHRva2VuLCBjb25maWcuX3N0cmljdCk7XG4gICAgLy8gaWYgd2UgZGlkbid0IGdldCBhIHdlZWtkYXkgbmFtZSwgbWFyayB0aGUgZGF0ZSBhcyBpbnZhbGlkXG4gICAgaWYgKHdlZWtkYXkgIT0gbnVsbCkge1xuICAgICAgICB3ZWVrLmQgPSB3ZWVrZGF5O1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGdldFBhcnNpbmdGbGFncyhjb25maWcpLmludmFsaWRXZWVrZGF5ID0gaW5wdXQ7XG4gICAgfVxufSk7XG5cbmFkZFdlZWtQYXJzZVRva2VuKFsnZCcsICdlJywgJ0UnXSwgZnVuY3Rpb24gKGlucHV0LCB3ZWVrLCBjb25maWcsIHRva2VuKSB7XG4gICAgd2Vla1t0b2tlbl0gPSB0b0ludChpbnB1dCk7XG59KTtcblxuLy8gSEVMUEVSU1xuXG5mdW5jdGlvbiBwYXJzZVdlZWtkYXkoaW5wdXQsIGxvY2FsZSkge1xuICAgIGlmICh0eXBlb2YgaW5wdXQgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHJldHVybiBpbnB1dDtcbiAgICB9XG5cbiAgICBpZiAoIWlzTmFOKGlucHV0KSkge1xuICAgICAgICByZXR1cm4gcGFyc2VJbnQoaW5wdXQsIDEwKTtcbiAgICB9XG5cbiAgICBpbnB1dCA9IGxvY2FsZS53ZWVrZGF5c1BhcnNlKGlucHV0KTtcbiAgICBpZiAodHlwZW9mIGlucHV0ID09PSAnbnVtYmVyJykge1xuICAgICAgICByZXR1cm4gaW5wdXQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIG51bGw7XG59XG5cbmZ1bmN0aW9uIHBhcnNlSXNvV2Vla2RheShpbnB1dCwgbG9jYWxlKSB7XG4gICAgaWYgKHR5cGVvZiBpbnB1dCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgcmV0dXJuIGxvY2FsZS53ZWVrZGF5c1BhcnNlKGlucHV0KSAlIDcgfHwgNztcbiAgICB9XG4gICAgcmV0dXJuIGlzTmFOKGlucHV0KSA/IG51bGwgOiBpbnB1dDtcbn1cblxuLy8gTE9DQUxFU1xuXG52YXIgZGVmYXVsdExvY2FsZVdlZWtkYXlzID0gJ1N1bmRheV9Nb25kYXlfVHVlc2RheV9XZWRuZXNkYXlfVGh1cnNkYXlfRnJpZGF5X1NhdHVyZGF5Jy5zcGxpdCgnXycpO1xuZnVuY3Rpb24gbG9jYWxlV2Vla2RheXMgKG0sIGZvcm1hdCkge1xuICAgIGlmICghbSkge1xuICAgICAgICByZXR1cm4gaXNBcnJheSh0aGlzLl93ZWVrZGF5cykgPyB0aGlzLl93ZWVrZGF5cyA6XG4gICAgICAgICAgICB0aGlzLl93ZWVrZGF5c1snc3RhbmRhbG9uZSddO1xuICAgIH1cbiAgICByZXR1cm4gaXNBcnJheSh0aGlzLl93ZWVrZGF5cykgPyB0aGlzLl93ZWVrZGF5c1ttLmRheSgpXSA6XG4gICAgICAgIHRoaXMuX3dlZWtkYXlzW3RoaXMuX3dlZWtkYXlzLmlzRm9ybWF0LnRlc3QoZm9ybWF0KSA/ICdmb3JtYXQnIDogJ3N0YW5kYWxvbmUnXVttLmRheSgpXTtcbn1cblxudmFyIGRlZmF1bHRMb2NhbGVXZWVrZGF5c1Nob3J0ID0gJ1N1bl9Nb25fVHVlX1dlZF9UaHVfRnJpX1NhdCcuc3BsaXQoJ18nKTtcbmZ1bmN0aW9uIGxvY2FsZVdlZWtkYXlzU2hvcnQgKG0pIHtcbiAgICByZXR1cm4gKG0pID8gdGhpcy5fd2Vla2RheXNTaG9ydFttLmRheSgpXSA6IHRoaXMuX3dlZWtkYXlzU2hvcnQ7XG59XG5cbnZhciBkZWZhdWx0TG9jYWxlV2Vla2RheXNNaW4gPSAnU3VfTW9fVHVfV2VfVGhfRnJfU2EnLnNwbGl0KCdfJyk7XG5mdW5jdGlvbiBsb2NhbGVXZWVrZGF5c01pbiAobSkge1xuICAgIHJldHVybiAobSkgPyB0aGlzLl93ZWVrZGF5c01pblttLmRheSgpXSA6IHRoaXMuX3dlZWtkYXlzTWluO1xufVxuXG5mdW5jdGlvbiBoYW5kbGVTdHJpY3RQYXJzZSQxKHdlZWtkYXlOYW1lLCBmb3JtYXQsIHN0cmljdCkge1xuICAgIHZhciBpLCBpaSwgbW9tLCBsbGMgPSB3ZWVrZGF5TmFtZS50b0xvY2FsZUxvd2VyQ2FzZSgpO1xuICAgIGlmICghdGhpcy5fd2Vla2RheXNQYXJzZSkge1xuICAgICAgICB0aGlzLl93ZWVrZGF5c1BhcnNlID0gW107XG4gICAgICAgIHRoaXMuX3Nob3J0V2Vla2RheXNQYXJzZSA9IFtdO1xuICAgICAgICB0aGlzLl9taW5XZWVrZGF5c1BhcnNlID0gW107XG5cbiAgICAgICAgZm9yIChpID0gMDsgaSA8IDc7ICsraSkge1xuICAgICAgICAgICAgbW9tID0gY3JlYXRlVVRDKFsyMDAwLCAxXSkuZGF5KGkpO1xuICAgICAgICAgICAgdGhpcy5fbWluV2Vla2RheXNQYXJzZVtpXSA9IHRoaXMud2Vla2RheXNNaW4obW9tLCAnJykudG9Mb2NhbGVMb3dlckNhc2UoKTtcbiAgICAgICAgICAgIHRoaXMuX3Nob3J0V2Vla2RheXNQYXJzZVtpXSA9IHRoaXMud2Vla2RheXNTaG9ydChtb20sICcnKS50b0xvY2FsZUxvd2VyQ2FzZSgpO1xuICAgICAgICAgICAgdGhpcy5fd2Vla2RheXNQYXJzZVtpXSA9IHRoaXMud2Vla2RheXMobW9tLCAnJykudG9Mb2NhbGVMb3dlckNhc2UoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGlmIChzdHJpY3QpIHtcbiAgICAgICAgaWYgKGZvcm1hdCA9PT0gJ2RkZGQnKSB7XG4gICAgICAgICAgICBpaSA9IGluZGV4T2YuY2FsbCh0aGlzLl93ZWVrZGF5c1BhcnNlLCBsbGMpO1xuICAgICAgICAgICAgcmV0dXJuIGlpICE9PSAtMSA/IGlpIDogbnVsbDtcbiAgICAgICAgfSBlbHNlIGlmIChmb3JtYXQgPT09ICdkZGQnKSB7XG4gICAgICAgICAgICBpaSA9IGluZGV4T2YuY2FsbCh0aGlzLl9zaG9ydFdlZWtkYXlzUGFyc2UsIGxsYyk7XG4gICAgICAgICAgICByZXR1cm4gaWkgIT09IC0xID8gaWkgOiBudWxsO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWkgPSBpbmRleE9mLmNhbGwodGhpcy5fbWluV2Vla2RheXNQYXJzZSwgbGxjKTtcbiAgICAgICAgICAgIHJldHVybiBpaSAhPT0gLTEgPyBpaSA6IG51bGw7XG4gICAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgICBpZiAoZm9ybWF0ID09PSAnZGRkZCcpIHtcbiAgICAgICAgICAgIGlpID0gaW5kZXhPZi5jYWxsKHRoaXMuX3dlZWtkYXlzUGFyc2UsIGxsYyk7XG4gICAgICAgICAgICBpZiAoaWkgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGlpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWkgPSBpbmRleE9mLmNhbGwodGhpcy5fc2hvcnRXZWVrZGF5c1BhcnNlLCBsbGMpO1xuICAgICAgICAgICAgaWYgKGlpICE9PSAtMSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBpaTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlpID0gaW5kZXhPZi5jYWxsKHRoaXMuX21pbldlZWtkYXlzUGFyc2UsIGxsYyk7XG4gICAgICAgICAgICByZXR1cm4gaWkgIT09IC0xID8gaWkgOiBudWxsO1xuICAgICAgICB9IGVsc2UgaWYgKGZvcm1hdCA9PT0gJ2RkZCcpIHtcbiAgICAgICAgICAgIGlpID0gaW5kZXhPZi5jYWxsKHRoaXMuX3Nob3J0V2Vla2RheXNQYXJzZSwgbGxjKTtcbiAgICAgICAgICAgIGlmIChpaSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaWk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpaSA9IGluZGV4T2YuY2FsbCh0aGlzLl93ZWVrZGF5c1BhcnNlLCBsbGMpO1xuICAgICAgICAgICAgaWYgKGlpICE9PSAtMSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBpaTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlpID0gaW5kZXhPZi5jYWxsKHRoaXMuX21pbldlZWtkYXlzUGFyc2UsIGxsYyk7XG4gICAgICAgICAgICByZXR1cm4gaWkgIT09IC0xID8gaWkgOiBudWxsO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWkgPSBpbmRleE9mLmNhbGwodGhpcy5fbWluV2Vla2RheXNQYXJzZSwgbGxjKTtcbiAgICAgICAgICAgIGlmIChpaSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaWk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpaSA9IGluZGV4T2YuY2FsbCh0aGlzLl93ZWVrZGF5c1BhcnNlLCBsbGMpO1xuICAgICAgICAgICAgaWYgKGlpICE9PSAtMSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBpaTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlpID0gaW5kZXhPZi5jYWxsKHRoaXMuX3Nob3J0V2Vla2RheXNQYXJzZSwgbGxjKTtcbiAgICAgICAgICAgIHJldHVybiBpaSAhPT0gLTEgPyBpaSA6IG51bGw7XG4gICAgICAgIH1cbiAgICB9XG59XG5cbmZ1bmN0aW9uIGxvY2FsZVdlZWtkYXlzUGFyc2UgKHdlZWtkYXlOYW1lLCBmb3JtYXQsIHN0cmljdCkge1xuICAgIHZhciBpLCBtb20sIHJlZ2V4O1xuXG4gICAgaWYgKHRoaXMuX3dlZWtkYXlzUGFyc2VFeGFjdCkge1xuICAgICAgICByZXR1cm4gaGFuZGxlU3RyaWN0UGFyc2UkMS5jYWxsKHRoaXMsIHdlZWtkYXlOYW1lLCBmb3JtYXQsIHN0cmljdCk7XG4gICAgfVxuXG4gICAgaWYgKCF0aGlzLl93ZWVrZGF5c1BhcnNlKSB7XG4gICAgICAgIHRoaXMuX3dlZWtkYXlzUGFyc2UgPSBbXTtcbiAgICAgICAgdGhpcy5fbWluV2Vla2RheXNQYXJzZSA9IFtdO1xuICAgICAgICB0aGlzLl9zaG9ydFdlZWtkYXlzUGFyc2UgPSBbXTtcbiAgICAgICAgdGhpcy5fZnVsbFdlZWtkYXlzUGFyc2UgPSBbXTtcbiAgICB9XG5cbiAgICBmb3IgKGkgPSAwOyBpIDwgNzsgaSsrKSB7XG4gICAgICAgIC8vIG1ha2UgdGhlIHJlZ2V4IGlmIHdlIGRvbid0IGhhdmUgaXQgYWxyZWFkeVxuXG4gICAgICAgIG1vbSA9IGNyZWF0ZVVUQyhbMjAwMCwgMV0pLmRheShpKTtcbiAgICAgICAgaWYgKHN0cmljdCAmJiAhdGhpcy5fZnVsbFdlZWtkYXlzUGFyc2VbaV0pIHtcbiAgICAgICAgICAgIHRoaXMuX2Z1bGxXZWVrZGF5c1BhcnNlW2ldID0gbmV3IFJlZ0V4cCgnXicgKyB0aGlzLndlZWtkYXlzKG1vbSwgJycpLnJlcGxhY2UoJy4nLCAnXFwuPycpICsgJyQnLCAnaScpO1xuICAgICAgICAgICAgdGhpcy5fc2hvcnRXZWVrZGF5c1BhcnNlW2ldID0gbmV3IFJlZ0V4cCgnXicgKyB0aGlzLndlZWtkYXlzU2hvcnQobW9tLCAnJykucmVwbGFjZSgnLicsICdcXC4/JykgKyAnJCcsICdpJyk7XG4gICAgICAgICAgICB0aGlzLl9taW5XZWVrZGF5c1BhcnNlW2ldID0gbmV3IFJlZ0V4cCgnXicgKyB0aGlzLndlZWtkYXlzTWluKG1vbSwgJycpLnJlcGxhY2UoJy4nLCAnXFwuPycpICsgJyQnLCAnaScpO1xuICAgICAgICB9XG4gICAgICAgIGlmICghdGhpcy5fd2Vla2RheXNQYXJzZVtpXSkge1xuICAgICAgICAgICAgcmVnZXggPSAnXicgKyB0aGlzLndlZWtkYXlzKG1vbSwgJycpICsgJ3xeJyArIHRoaXMud2Vla2RheXNTaG9ydChtb20sICcnKSArICd8XicgKyB0aGlzLndlZWtkYXlzTWluKG1vbSwgJycpO1xuICAgICAgICAgICAgdGhpcy5fd2Vla2RheXNQYXJzZVtpXSA9IG5ldyBSZWdFeHAocmVnZXgucmVwbGFjZSgnLicsICcnKSwgJ2knKTtcbiAgICAgICAgfVxuICAgICAgICAvLyB0ZXN0IHRoZSByZWdleFxuICAgICAgICBpZiAoc3RyaWN0ICYmIGZvcm1hdCA9PT0gJ2RkZGQnICYmIHRoaXMuX2Z1bGxXZWVrZGF5c1BhcnNlW2ldLnRlc3Qod2Vla2RheU5hbWUpKSB7XG4gICAgICAgICAgICByZXR1cm4gaTtcbiAgICAgICAgfSBlbHNlIGlmIChzdHJpY3QgJiYgZm9ybWF0ID09PSAnZGRkJyAmJiB0aGlzLl9zaG9ydFdlZWtkYXlzUGFyc2VbaV0udGVzdCh3ZWVrZGF5TmFtZSkpIHtcbiAgICAgICAgICAgIHJldHVybiBpO1xuICAgICAgICB9IGVsc2UgaWYgKHN0cmljdCAmJiBmb3JtYXQgPT09ICdkZCcgJiYgdGhpcy5fbWluV2Vla2RheXNQYXJzZVtpXS50ZXN0KHdlZWtkYXlOYW1lKSkge1xuICAgICAgICAgICAgcmV0dXJuIGk7XG4gICAgICAgIH0gZWxzZSBpZiAoIXN0cmljdCAmJiB0aGlzLl93ZWVrZGF5c1BhcnNlW2ldLnRlc3Qod2Vla2RheU5hbWUpKSB7XG4gICAgICAgICAgICByZXR1cm4gaTtcbiAgICAgICAgfVxuICAgIH1cbn1cblxuLy8gTU9NRU5UU1xuXG5mdW5jdGlvbiBnZXRTZXREYXlPZldlZWsgKGlucHV0KSB7XG4gICAgaWYgKCF0aGlzLmlzVmFsaWQoKSkge1xuICAgICAgICByZXR1cm4gaW5wdXQgIT0gbnVsbCA/IHRoaXMgOiBOYU47XG4gICAgfVxuICAgIHZhciBkYXkgPSB0aGlzLl9pc1VUQyA/IHRoaXMuX2QuZ2V0VVRDRGF5KCkgOiB0aGlzLl9kLmdldERheSgpO1xuICAgIGlmIChpbnB1dCAhPSBudWxsKSB7XG4gICAgICAgIGlucHV0ID0gcGFyc2VXZWVrZGF5KGlucHV0LCB0aGlzLmxvY2FsZURhdGEoKSk7XG4gICAgICAgIHJldHVybiB0aGlzLmFkZChpbnB1dCAtIGRheSwgJ2QnKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gZGF5O1xuICAgIH1cbn1cblxuZnVuY3Rpb24gZ2V0U2V0TG9jYWxlRGF5T2ZXZWVrIChpbnB1dCkge1xuICAgIGlmICghdGhpcy5pc1ZhbGlkKCkpIHtcbiAgICAgICAgcmV0dXJuIGlucHV0ICE9IG51bGwgPyB0aGlzIDogTmFOO1xuICAgIH1cbiAgICB2YXIgd2Vla2RheSA9ICh0aGlzLmRheSgpICsgNyAtIHRoaXMubG9jYWxlRGF0YSgpLl93ZWVrLmRvdykgJSA3O1xuICAgIHJldHVybiBpbnB1dCA9PSBudWxsID8gd2Vla2RheSA6IHRoaXMuYWRkKGlucHV0IC0gd2Vla2RheSwgJ2QnKTtcbn1cblxuZnVuY3Rpb24gZ2V0U2V0SVNPRGF5T2ZXZWVrIChpbnB1dCkge1xuICAgIGlmICghdGhpcy5pc1ZhbGlkKCkpIHtcbiAgICAgICAgcmV0dXJuIGlucHV0ICE9IG51bGwgPyB0aGlzIDogTmFOO1xuICAgIH1cblxuICAgIC8vIGJlaGF2ZXMgdGhlIHNhbWUgYXMgbW9tZW50I2RheSBleGNlcHRcbiAgICAvLyBhcyBhIGdldHRlciwgcmV0dXJucyA3IGluc3RlYWQgb2YgMCAoMS03IHJhbmdlIGluc3RlYWQgb2YgMC02KVxuICAgIC8vIGFzIGEgc2V0dGVyLCBzdW5kYXkgc2hvdWxkIGJlbG9uZyB0byB0aGUgcHJldmlvdXMgd2Vlay5cblxuICAgIGlmIChpbnB1dCAhPSBudWxsKSB7XG4gICAgICAgIHZhciB3ZWVrZGF5ID0gcGFyc2VJc29XZWVrZGF5KGlucHV0LCB0aGlzLmxvY2FsZURhdGEoKSk7XG4gICAgICAgIHJldHVybiB0aGlzLmRheSh0aGlzLmRheSgpICUgNyA/IHdlZWtkYXkgOiB3ZWVrZGF5IC0gNyk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZGF5KCkgfHwgNztcbiAgICB9XG59XG5cbnZhciBkZWZhdWx0V2Vla2RheXNSZWdleCA9IG1hdGNoV29yZDtcbmZ1bmN0aW9uIHdlZWtkYXlzUmVnZXggKGlzU3RyaWN0KSB7XG4gICAgaWYgKHRoaXMuX3dlZWtkYXlzUGFyc2VFeGFjdCkge1xuICAgICAgICBpZiAoIWhhc093blByb3AodGhpcywgJ193ZWVrZGF5c1JlZ2V4JykpIHtcbiAgICAgICAgICAgIGNvbXB1dGVXZWVrZGF5c1BhcnNlLmNhbGwodGhpcyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGlzU3RyaWN0KSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fd2Vla2RheXNTdHJpY3RSZWdleDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl93ZWVrZGF5c1JlZ2V4O1xuICAgICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgICAgaWYgKCFoYXNPd25Qcm9wKHRoaXMsICdfd2Vla2RheXNSZWdleCcpKSB7XG4gICAgICAgICAgICB0aGlzLl93ZWVrZGF5c1JlZ2V4ID0gZGVmYXVsdFdlZWtkYXlzUmVnZXg7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuX3dlZWtkYXlzU3RyaWN0UmVnZXggJiYgaXNTdHJpY3QgP1xuICAgICAgICAgICAgdGhpcy5fd2Vla2RheXNTdHJpY3RSZWdleCA6IHRoaXMuX3dlZWtkYXlzUmVnZXg7XG4gICAgfVxufVxuXG52YXIgZGVmYXVsdFdlZWtkYXlzU2hvcnRSZWdleCA9IG1hdGNoV29yZDtcbmZ1bmN0aW9uIHdlZWtkYXlzU2hvcnRSZWdleCAoaXNTdHJpY3QpIHtcbiAgICBpZiAodGhpcy5fd2Vla2RheXNQYXJzZUV4YWN0KSB7XG4gICAgICAgIGlmICghaGFzT3duUHJvcCh0aGlzLCAnX3dlZWtkYXlzUmVnZXgnKSkge1xuICAgICAgICAgICAgY29tcHV0ZVdlZWtkYXlzUGFyc2UuY2FsbCh0aGlzKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaXNTdHJpY3QpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl93ZWVrZGF5c1Nob3J0U3RyaWN0UmVnZXg7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fd2Vla2RheXNTaG9ydFJlZ2V4O1xuICAgICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgICAgaWYgKCFoYXNPd25Qcm9wKHRoaXMsICdfd2Vla2RheXNTaG9ydFJlZ2V4JykpIHtcbiAgICAgICAgICAgIHRoaXMuX3dlZWtkYXlzU2hvcnRSZWdleCA9IGRlZmF1bHRXZWVrZGF5c1Nob3J0UmVnZXg7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuX3dlZWtkYXlzU2hvcnRTdHJpY3RSZWdleCAmJiBpc1N0cmljdCA/XG4gICAgICAgICAgICB0aGlzLl93ZWVrZGF5c1Nob3J0U3RyaWN0UmVnZXggOiB0aGlzLl93ZWVrZGF5c1Nob3J0UmVnZXg7XG4gICAgfVxufVxuXG52YXIgZGVmYXVsdFdlZWtkYXlzTWluUmVnZXggPSBtYXRjaFdvcmQ7XG5mdW5jdGlvbiB3ZWVrZGF5c01pblJlZ2V4IChpc1N0cmljdCkge1xuICAgIGlmICh0aGlzLl93ZWVrZGF5c1BhcnNlRXhhY3QpIHtcbiAgICAgICAgaWYgKCFoYXNPd25Qcm9wKHRoaXMsICdfd2Vla2RheXNSZWdleCcpKSB7XG4gICAgICAgICAgICBjb21wdXRlV2Vla2RheXNQYXJzZS5jYWxsKHRoaXMpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChpc1N0cmljdCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX3dlZWtkYXlzTWluU3RyaWN0UmVnZXg7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fd2Vla2RheXNNaW5SZWdleDtcbiAgICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAgIGlmICghaGFzT3duUHJvcCh0aGlzLCAnX3dlZWtkYXlzTWluUmVnZXgnKSkge1xuICAgICAgICAgICAgdGhpcy5fd2Vla2RheXNNaW5SZWdleCA9IGRlZmF1bHRXZWVrZGF5c01pblJlZ2V4O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLl93ZWVrZGF5c01pblN0cmljdFJlZ2V4ICYmIGlzU3RyaWN0ID9cbiAgICAgICAgICAgIHRoaXMuX3dlZWtkYXlzTWluU3RyaWN0UmVnZXggOiB0aGlzLl93ZWVrZGF5c01pblJlZ2V4O1xuICAgIH1cbn1cblxuXG5mdW5jdGlvbiBjb21wdXRlV2Vla2RheXNQYXJzZSAoKSB7XG4gICAgZnVuY3Rpb24gY21wTGVuUmV2KGEsIGIpIHtcbiAgICAgICAgcmV0dXJuIGIubGVuZ3RoIC0gYS5sZW5ndGg7XG4gICAgfVxuXG4gICAgdmFyIG1pblBpZWNlcyA9IFtdLCBzaG9ydFBpZWNlcyA9IFtdLCBsb25nUGllY2VzID0gW10sIG1peGVkUGllY2VzID0gW10sXG4gICAgICAgIGksIG1vbSwgbWlucCwgc2hvcnRwLCBsb25ncDtcbiAgICBmb3IgKGkgPSAwOyBpIDwgNzsgaSsrKSB7XG4gICAgICAgIC8vIG1ha2UgdGhlIHJlZ2V4IGlmIHdlIGRvbid0IGhhdmUgaXQgYWxyZWFkeVxuICAgICAgICBtb20gPSBjcmVhdGVVVEMoWzIwMDAsIDFdKS5kYXkoaSk7XG4gICAgICAgIG1pbnAgPSB0aGlzLndlZWtkYXlzTWluKG1vbSwgJycpO1xuICAgICAgICBzaG9ydHAgPSB0aGlzLndlZWtkYXlzU2hvcnQobW9tLCAnJyk7XG4gICAgICAgIGxvbmdwID0gdGhpcy53ZWVrZGF5cyhtb20sICcnKTtcbiAgICAgICAgbWluUGllY2VzLnB1c2gobWlucCk7XG4gICAgICAgIHNob3J0UGllY2VzLnB1c2goc2hvcnRwKTtcbiAgICAgICAgbG9uZ1BpZWNlcy5wdXNoKGxvbmdwKTtcbiAgICAgICAgbWl4ZWRQaWVjZXMucHVzaChtaW5wKTtcbiAgICAgICAgbWl4ZWRQaWVjZXMucHVzaChzaG9ydHApO1xuICAgICAgICBtaXhlZFBpZWNlcy5wdXNoKGxvbmdwKTtcbiAgICB9XG4gICAgLy8gU29ydGluZyBtYWtlcyBzdXJlIGlmIG9uZSB3ZWVrZGF5IChvciBhYmJyKSBpcyBhIHByZWZpeCBvZiBhbm90aGVyIGl0XG4gICAgLy8gd2lsbCBtYXRjaCB0aGUgbG9uZ2VyIHBpZWNlLlxuICAgIG1pblBpZWNlcy5zb3J0KGNtcExlblJldik7XG4gICAgc2hvcnRQaWVjZXMuc29ydChjbXBMZW5SZXYpO1xuICAgIGxvbmdQaWVjZXMuc29ydChjbXBMZW5SZXYpO1xuICAgIG1peGVkUGllY2VzLnNvcnQoY21wTGVuUmV2KTtcbiAgICBmb3IgKGkgPSAwOyBpIDwgNzsgaSsrKSB7XG4gICAgICAgIHNob3J0UGllY2VzW2ldID0gcmVnZXhFc2NhcGUoc2hvcnRQaWVjZXNbaV0pO1xuICAgICAgICBsb25nUGllY2VzW2ldID0gcmVnZXhFc2NhcGUobG9uZ1BpZWNlc1tpXSk7XG4gICAgICAgIG1peGVkUGllY2VzW2ldID0gcmVnZXhFc2NhcGUobWl4ZWRQaWVjZXNbaV0pO1xuICAgIH1cblxuICAgIHRoaXMuX3dlZWtkYXlzUmVnZXggPSBuZXcgUmVnRXhwKCdeKCcgKyBtaXhlZFBpZWNlcy5qb2luKCd8JykgKyAnKScsICdpJyk7XG4gICAgdGhpcy5fd2Vla2RheXNTaG9ydFJlZ2V4ID0gdGhpcy5fd2Vla2RheXNSZWdleDtcbiAgICB0aGlzLl93ZWVrZGF5c01pblJlZ2V4ID0gdGhpcy5fd2Vla2RheXNSZWdleDtcblxuICAgIHRoaXMuX3dlZWtkYXlzU3RyaWN0UmVnZXggPSBuZXcgUmVnRXhwKCdeKCcgKyBsb25nUGllY2VzLmpvaW4oJ3wnKSArICcpJywgJ2knKTtcbiAgICB0aGlzLl93ZWVrZGF5c1Nob3J0U3RyaWN0UmVnZXggPSBuZXcgUmVnRXhwKCdeKCcgKyBzaG9ydFBpZWNlcy5qb2luKCd8JykgKyAnKScsICdpJyk7XG4gICAgdGhpcy5fd2Vla2RheXNNaW5TdHJpY3RSZWdleCA9IG5ldyBSZWdFeHAoJ14oJyArIG1pblBpZWNlcy5qb2luKCd8JykgKyAnKScsICdpJyk7XG59XG5cbi8vIEZPUk1BVFRJTkdcblxuZnVuY3Rpb24gaEZvcm1hdCgpIHtcbiAgICByZXR1cm4gdGhpcy5ob3VycygpICUgMTIgfHwgMTI7XG59XG5cbmZ1bmN0aW9uIGtGb3JtYXQoKSB7XG4gICAgcmV0dXJuIHRoaXMuaG91cnMoKSB8fCAyNDtcbn1cblxuYWRkRm9ybWF0VG9rZW4oJ0gnLCBbJ0hIJywgMl0sIDAsICdob3VyJyk7XG5hZGRGb3JtYXRUb2tlbignaCcsIFsnaGgnLCAyXSwgMCwgaEZvcm1hdCk7XG5hZGRGb3JtYXRUb2tlbignaycsIFsna2snLCAyXSwgMCwga0Zvcm1hdCk7XG5cbmFkZEZvcm1hdFRva2VuKCdobW0nLCAwLCAwLCBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuICcnICsgaEZvcm1hdC5hcHBseSh0aGlzKSArIHplcm9GaWxsKHRoaXMubWludXRlcygpLCAyKTtcbn0pO1xuXG5hZGRGb3JtYXRUb2tlbignaG1tc3MnLCAwLCAwLCBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuICcnICsgaEZvcm1hdC5hcHBseSh0aGlzKSArIHplcm9GaWxsKHRoaXMubWludXRlcygpLCAyKSArXG4gICAgICAgIHplcm9GaWxsKHRoaXMuc2Vjb25kcygpLCAyKTtcbn0pO1xuXG5hZGRGb3JtYXRUb2tlbignSG1tJywgMCwgMCwgZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiAnJyArIHRoaXMuaG91cnMoKSArIHplcm9GaWxsKHRoaXMubWludXRlcygpLCAyKTtcbn0pO1xuXG5hZGRGb3JtYXRUb2tlbignSG1tc3MnLCAwLCAwLCBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuICcnICsgdGhpcy5ob3VycygpICsgemVyb0ZpbGwodGhpcy5taW51dGVzKCksIDIpICtcbiAgICAgICAgemVyb0ZpbGwodGhpcy5zZWNvbmRzKCksIDIpO1xufSk7XG5cbmZ1bmN0aW9uIG1lcmlkaWVtICh0b2tlbiwgbG93ZXJjYXNlKSB7XG4gICAgYWRkRm9ybWF0VG9rZW4odG9rZW4sIDAsIDAsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubG9jYWxlRGF0YSgpLm1lcmlkaWVtKHRoaXMuaG91cnMoKSwgdGhpcy5taW51dGVzKCksIGxvd2VyY2FzZSk7XG4gICAgfSk7XG59XG5cbm1lcmlkaWVtKCdhJywgdHJ1ZSk7XG5tZXJpZGllbSgnQScsIGZhbHNlKTtcblxuLy8gQUxJQVNFU1xuXG5hZGRVbml0QWxpYXMoJ2hvdXInLCAnaCcpO1xuXG4vLyBQUklPUklUWVxuYWRkVW5pdFByaW9yaXR5KCdob3VyJywgMTMpO1xuXG4vLyBQQVJTSU5HXG5cbmZ1bmN0aW9uIG1hdGNoTWVyaWRpZW0gKGlzU3RyaWN0LCBsb2NhbGUpIHtcbiAgICByZXR1cm4gbG9jYWxlLl9tZXJpZGllbVBhcnNlO1xufVxuXG5hZGRSZWdleFRva2VuKCdhJywgIG1hdGNoTWVyaWRpZW0pO1xuYWRkUmVnZXhUb2tlbignQScsICBtYXRjaE1lcmlkaWVtKTtcbmFkZFJlZ2V4VG9rZW4oJ0gnLCAgbWF0Y2gxdG8yKTtcbmFkZFJlZ2V4VG9rZW4oJ2gnLCAgbWF0Y2gxdG8yKTtcbmFkZFJlZ2V4VG9rZW4oJ2snLCAgbWF0Y2gxdG8yKTtcbmFkZFJlZ2V4VG9rZW4oJ0hIJywgbWF0Y2gxdG8yLCBtYXRjaDIpO1xuYWRkUmVnZXhUb2tlbignaGgnLCBtYXRjaDF0bzIsIG1hdGNoMik7XG5hZGRSZWdleFRva2VuKCdraycsIG1hdGNoMXRvMiwgbWF0Y2gyKTtcblxuYWRkUmVnZXhUb2tlbignaG1tJywgbWF0Y2gzdG80KTtcbmFkZFJlZ2V4VG9rZW4oJ2htbXNzJywgbWF0Y2g1dG82KTtcbmFkZFJlZ2V4VG9rZW4oJ0htbScsIG1hdGNoM3RvNCk7XG5hZGRSZWdleFRva2VuKCdIbW1zcycsIG1hdGNoNXRvNik7XG5cbmFkZFBhcnNlVG9rZW4oWydIJywgJ0hIJ10sIEhPVVIpO1xuYWRkUGFyc2VUb2tlbihbJ2snLCAna2snXSwgZnVuY3Rpb24gKGlucHV0LCBhcnJheSwgY29uZmlnKSB7XG4gICAgdmFyIGtJbnB1dCA9IHRvSW50KGlucHV0KTtcbiAgICBhcnJheVtIT1VSXSA9IGtJbnB1dCA9PT0gMjQgPyAwIDoga0lucHV0O1xufSk7XG5hZGRQYXJzZVRva2VuKFsnYScsICdBJ10sIGZ1bmN0aW9uIChpbnB1dCwgYXJyYXksIGNvbmZpZykge1xuICAgIGNvbmZpZy5faXNQbSA9IGNvbmZpZy5fbG9jYWxlLmlzUE0oaW5wdXQpO1xuICAgIGNvbmZpZy5fbWVyaWRpZW0gPSBpbnB1dDtcbn0pO1xuYWRkUGFyc2VUb2tlbihbJ2gnLCAnaGgnXSwgZnVuY3Rpb24gKGlucHV0LCBhcnJheSwgY29uZmlnKSB7XG4gICAgYXJyYXlbSE9VUl0gPSB0b0ludChpbnB1dCk7XG4gICAgZ2V0UGFyc2luZ0ZsYWdzKGNvbmZpZykuYmlnSG91ciA9IHRydWU7XG59KTtcbmFkZFBhcnNlVG9rZW4oJ2htbScsIGZ1bmN0aW9uIChpbnB1dCwgYXJyYXksIGNvbmZpZykge1xuICAgIHZhciBwb3MgPSBpbnB1dC5sZW5ndGggLSAyO1xuICAgIGFycmF5W0hPVVJdID0gdG9JbnQoaW5wdXQuc3Vic3RyKDAsIHBvcykpO1xuICAgIGFycmF5W01JTlVURV0gPSB0b0ludChpbnB1dC5zdWJzdHIocG9zKSk7XG4gICAgZ2V0UGFyc2luZ0ZsYWdzKGNvbmZpZykuYmlnSG91ciA9IHRydWU7XG59KTtcbmFkZFBhcnNlVG9rZW4oJ2htbXNzJywgZnVuY3Rpb24gKGlucHV0LCBhcnJheSwgY29uZmlnKSB7XG4gICAgdmFyIHBvczEgPSBpbnB1dC5sZW5ndGggLSA0O1xuICAgIHZhciBwb3MyID0gaW5wdXQubGVuZ3RoIC0gMjtcbiAgICBhcnJheVtIT1VSXSA9IHRvSW50KGlucHV0LnN1YnN0cigwLCBwb3MxKSk7XG4gICAgYXJyYXlbTUlOVVRFXSA9IHRvSW50KGlucHV0LnN1YnN0cihwb3MxLCAyKSk7XG4gICAgYXJyYXlbU0VDT05EXSA9IHRvSW50KGlucHV0LnN1YnN0cihwb3MyKSk7XG4gICAgZ2V0UGFyc2luZ0ZsYWdzKGNvbmZpZykuYmlnSG91ciA9IHRydWU7XG59KTtcbmFkZFBhcnNlVG9rZW4oJ0htbScsIGZ1bmN0aW9uIChpbnB1dCwgYXJyYXksIGNvbmZpZykge1xuICAgIHZhciBwb3MgPSBpbnB1dC5sZW5ndGggLSAyO1xuICAgIGFycmF5W0hPVVJdID0gdG9JbnQoaW5wdXQuc3Vic3RyKDAsIHBvcykpO1xuICAgIGFycmF5W01JTlVURV0gPSB0b0ludChpbnB1dC5zdWJzdHIocG9zKSk7XG59KTtcbmFkZFBhcnNlVG9rZW4oJ0htbXNzJywgZnVuY3Rpb24gKGlucHV0LCBhcnJheSwgY29uZmlnKSB7XG4gICAgdmFyIHBvczEgPSBpbnB1dC5sZW5ndGggLSA0O1xuICAgIHZhciBwb3MyID0gaW5wdXQubGVuZ3RoIC0gMjtcbiAgICBhcnJheVtIT1VSXSA9IHRvSW50KGlucHV0LnN1YnN0cigwLCBwb3MxKSk7XG4gICAgYXJyYXlbTUlOVVRFXSA9IHRvSW50KGlucHV0LnN1YnN0cihwb3MxLCAyKSk7XG4gICAgYXJyYXlbU0VDT05EXSA9IHRvSW50KGlucHV0LnN1YnN0cihwb3MyKSk7XG59KTtcblxuLy8gTE9DQUxFU1xuXG5mdW5jdGlvbiBsb2NhbGVJc1BNIChpbnB1dCkge1xuICAgIC8vIElFOCBRdWlya3MgTW9kZSAmIElFNyBTdGFuZGFyZHMgTW9kZSBkbyBub3QgYWxsb3cgYWNjZXNzaW5nIHN0cmluZ3MgbGlrZSBhcnJheXNcbiAgICAvLyBVc2luZyBjaGFyQXQgc2hvdWxkIGJlIG1vcmUgY29tcGF0aWJsZS5cbiAgICByZXR1cm4gKChpbnB1dCArICcnKS50b0xvd2VyQ2FzZSgpLmNoYXJBdCgwKSA9PT0gJ3AnKTtcbn1cblxudmFyIGRlZmF1bHRMb2NhbGVNZXJpZGllbVBhcnNlID0gL1thcF1cXC4/bT9cXC4/L2k7XG5mdW5jdGlvbiBsb2NhbGVNZXJpZGllbSAoaG91cnMsIG1pbnV0ZXMsIGlzTG93ZXIpIHtcbiAgICBpZiAoaG91cnMgPiAxMSkge1xuICAgICAgICByZXR1cm4gaXNMb3dlciA/ICdwbScgOiAnUE0nO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBpc0xvd2VyID8gJ2FtJyA6ICdBTSc7XG4gICAgfVxufVxuXG5cbi8vIE1PTUVOVFNcblxuLy8gU2V0dGluZyB0aGUgaG91ciBzaG91bGQga2VlcCB0aGUgdGltZSwgYmVjYXVzZSB0aGUgdXNlciBleHBsaWNpdGx5XG4vLyBzcGVjaWZpZWQgd2hpY2ggaG91ciBoZSB3YW50cy4gU28gdHJ5aW5nIHRvIG1haW50YWluIHRoZSBzYW1lIGhvdXIgKGluXG4vLyBhIG5ldyB0aW1lem9uZSkgbWFrZXMgc2Vuc2UuIEFkZGluZy9zdWJ0cmFjdGluZyBob3VycyBkb2VzIG5vdCBmb2xsb3dcbi8vIHRoaXMgcnVsZS5cbnZhciBnZXRTZXRIb3VyID0gbWFrZUdldFNldCgnSG91cnMnLCB0cnVlKTtcblxuLy8gbW9udGhzXG4vLyB3ZWVrXG4vLyB3ZWVrZGF5c1xuLy8gbWVyaWRpZW1cbnZhciBiYXNlQ29uZmlnID0ge1xuICAgIGNhbGVuZGFyOiBkZWZhdWx0Q2FsZW5kYXIsXG4gICAgbG9uZ0RhdGVGb3JtYXQ6IGRlZmF1bHRMb25nRGF0ZUZvcm1hdCxcbiAgICBpbnZhbGlkRGF0ZTogZGVmYXVsdEludmFsaWREYXRlLFxuICAgIG9yZGluYWw6IGRlZmF1bHRPcmRpbmFsLFxuICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IGRlZmF1bHREYXlPZk1vbnRoT3JkaW5hbFBhcnNlLFxuICAgIHJlbGF0aXZlVGltZTogZGVmYXVsdFJlbGF0aXZlVGltZSxcblxuICAgIG1vbnRoczogZGVmYXVsdExvY2FsZU1vbnRocyxcbiAgICBtb250aHNTaG9ydDogZGVmYXVsdExvY2FsZU1vbnRoc1Nob3J0LFxuXG4gICAgd2VlazogZGVmYXVsdExvY2FsZVdlZWssXG5cbiAgICB3ZWVrZGF5czogZGVmYXVsdExvY2FsZVdlZWtkYXlzLFxuICAgIHdlZWtkYXlzTWluOiBkZWZhdWx0TG9jYWxlV2Vla2RheXNNaW4sXG4gICAgd2Vla2RheXNTaG9ydDogZGVmYXVsdExvY2FsZVdlZWtkYXlzU2hvcnQsXG5cbiAgICBtZXJpZGllbVBhcnNlOiBkZWZhdWx0TG9jYWxlTWVyaWRpZW1QYXJzZVxufTtcblxuLy8gaW50ZXJuYWwgc3RvcmFnZSBmb3IgbG9jYWxlIGNvbmZpZyBmaWxlc1xudmFyIGxvY2FsZXMgPSB7fTtcbnZhciBsb2NhbGVGYW1pbGllcyA9IHt9O1xudmFyIGdsb2JhbExvY2FsZTtcblxuZnVuY3Rpb24gbm9ybWFsaXplTG9jYWxlKGtleSkge1xuICAgIHJldHVybiBrZXkgPyBrZXkudG9Mb3dlckNhc2UoKS5yZXBsYWNlKCdfJywgJy0nKSA6IGtleTtcbn1cblxuLy8gcGljayB0aGUgbG9jYWxlIGZyb20gdGhlIGFycmF5XG4vLyB0cnkgWydlbi1hdScsICdlbi1nYiddIGFzICdlbi1hdScsICdlbi1nYicsICdlbicsIGFzIGluIG1vdmUgdGhyb3VnaCB0aGUgbGlzdCB0cnlpbmcgZWFjaFxuLy8gc3Vic3RyaW5nIGZyb20gbW9zdCBzcGVjaWZpYyB0byBsZWFzdCwgYnV0IG1vdmUgdG8gdGhlIG5leHQgYXJyYXkgaXRlbSBpZiBpdCdzIGEgbW9yZSBzcGVjaWZpYyB2YXJpYW50IHRoYW4gdGhlIGN1cnJlbnQgcm9vdFxuZnVuY3Rpb24gY2hvb3NlTG9jYWxlKG5hbWVzKSB7XG4gICAgdmFyIGkgPSAwLCBqLCBuZXh0LCBsb2NhbGUsIHNwbGl0O1xuXG4gICAgd2hpbGUgKGkgPCBuYW1lcy5sZW5ndGgpIHtcbiAgICAgICAgc3BsaXQgPSBub3JtYWxpemVMb2NhbGUobmFtZXNbaV0pLnNwbGl0KCctJyk7XG4gICAgICAgIGogPSBzcGxpdC5sZW5ndGg7XG4gICAgICAgIG5leHQgPSBub3JtYWxpemVMb2NhbGUobmFtZXNbaSArIDFdKTtcbiAgICAgICAgbmV4dCA9IG5leHQgPyBuZXh0LnNwbGl0KCctJykgOiBudWxsO1xuICAgICAgICB3aGlsZSAoaiA+IDApIHtcbiAgICAgICAgICAgIGxvY2FsZSA9IGxvYWRMb2NhbGUoc3BsaXQuc2xpY2UoMCwgaikuam9pbignLScpKTtcbiAgICAgICAgICAgIGlmIChsb2NhbGUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbG9jYWxlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG5leHQgJiYgbmV4dC5sZW5ndGggPj0gaiAmJiBjb21wYXJlQXJyYXlzKHNwbGl0LCBuZXh0LCB0cnVlKSA+PSBqIC0gMSkge1xuICAgICAgICAgICAgICAgIC8vdGhlIG5leHQgYXJyYXkgaXRlbSBpcyBiZXR0ZXIgdGhhbiBhIHNoYWxsb3dlciBzdWJzdHJpbmcgb2YgdGhpcyBvbmVcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGotLTtcbiAgICAgICAgfVxuICAgICAgICBpKys7XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xufVxuXG5mdW5jdGlvbiBsb2FkTG9jYWxlKG5hbWUpIHtcbiAgICB2YXIgb2xkTG9jYWxlID0gbnVsbDtcbiAgICAvLyBUT0RPOiBGaW5kIGEgYmV0dGVyIHdheSB0byByZWdpc3RlciBhbmQgbG9hZCBhbGwgdGhlIGxvY2FsZXMgaW4gTm9kZVxuICAgIGlmICghbG9jYWxlc1tuYW1lXSAmJiAodHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCcpICYmXG4gICAgICAgICAgICBtb2R1bGUgJiYgbW9kdWxlLmV4cG9ydHMpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIG9sZExvY2FsZSA9IGdsb2JhbExvY2FsZS5fYWJicjtcbiAgICAgICAgICAgIHZhciBhbGlhc2VkUmVxdWlyZSA9IHJlcXVpcmU7XG4gICAgICAgICAgICBhbGlhc2VkUmVxdWlyZSgnLi9sb2NhbGUvJyArIG5hbWUpO1xuICAgICAgICAgICAgZ2V0U2V0R2xvYmFsTG9jYWxlKG9sZExvY2FsZSk7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHt9XG4gICAgfVxuICAgIHJldHVybiBsb2NhbGVzW25hbWVdO1xufVxuXG4vLyBUaGlzIGZ1bmN0aW9uIHdpbGwgbG9hZCBsb2NhbGUgYW5kIHRoZW4gc2V0IHRoZSBnbG9iYWwgbG9jYWxlLiAgSWZcbi8vIG5vIGFyZ3VtZW50cyBhcmUgcGFzc2VkIGluLCBpdCB3aWxsIHNpbXBseSByZXR1cm4gdGhlIGN1cnJlbnQgZ2xvYmFsXG4vLyBsb2NhbGUga2V5LlxuZnVuY3Rpb24gZ2V0U2V0R2xvYmFsTG9jYWxlIChrZXksIHZhbHVlcykge1xuICAgIHZhciBkYXRhO1xuICAgIGlmIChrZXkpIHtcbiAgICAgICAgaWYgKGlzVW5kZWZpbmVkKHZhbHVlcykpIHtcbiAgICAgICAgICAgIGRhdGEgPSBnZXRMb2NhbGUoa2V5KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGRhdGEgPSBkZWZpbmVMb2NhbGUoa2V5LCB2YWx1ZXMpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGRhdGEpIHtcbiAgICAgICAgICAgIC8vIG1vbWVudC5kdXJhdGlvbi5fbG9jYWxlID0gbW9tZW50Ll9sb2NhbGUgPSBkYXRhO1xuICAgICAgICAgICAgZ2xvYmFsTG9jYWxlID0gZGF0YTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBnbG9iYWxMb2NhbGUuX2FiYnI7XG59XG5cbmZ1bmN0aW9uIGRlZmluZUxvY2FsZSAobmFtZSwgY29uZmlnKSB7XG4gICAgaWYgKGNvbmZpZyAhPT0gbnVsbCkge1xuICAgICAgICB2YXIgcGFyZW50Q29uZmlnID0gYmFzZUNvbmZpZztcbiAgICAgICAgY29uZmlnLmFiYnIgPSBuYW1lO1xuICAgICAgICBpZiAobG9jYWxlc1tuYW1lXSAhPSBudWxsKSB7XG4gICAgICAgICAgICBkZXByZWNhdGVTaW1wbGUoJ2RlZmluZUxvY2FsZU92ZXJyaWRlJyxcbiAgICAgICAgICAgICAgICAgICAgJ3VzZSBtb21lbnQudXBkYXRlTG9jYWxlKGxvY2FsZU5hbWUsIGNvbmZpZykgdG8gY2hhbmdlICcgK1xuICAgICAgICAgICAgICAgICAgICAnYW4gZXhpc3RpbmcgbG9jYWxlLiBtb21lbnQuZGVmaW5lTG9jYWxlKGxvY2FsZU5hbWUsICcgK1xuICAgICAgICAgICAgICAgICAgICAnY29uZmlnKSBzaG91bGQgb25seSBiZSB1c2VkIGZvciBjcmVhdGluZyBhIG5ldyBsb2NhbGUgJyArXG4gICAgICAgICAgICAgICAgICAgICdTZWUgaHR0cDovL21vbWVudGpzLmNvbS9ndWlkZXMvIy93YXJuaW5ncy9kZWZpbmUtbG9jYWxlLyBmb3IgbW9yZSBpbmZvLicpO1xuICAgICAgICAgICAgcGFyZW50Q29uZmlnID0gbG9jYWxlc1tuYW1lXS5fY29uZmlnO1xuICAgICAgICB9IGVsc2UgaWYgKGNvbmZpZy5wYXJlbnRMb2NhbGUgIT0gbnVsbCkge1xuICAgICAgICAgICAgaWYgKGxvY2FsZXNbY29uZmlnLnBhcmVudExvY2FsZV0gIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHBhcmVudENvbmZpZyA9IGxvY2FsZXNbY29uZmlnLnBhcmVudExvY2FsZV0uX2NvbmZpZztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgaWYgKCFsb2NhbGVGYW1pbGllc1tjb25maWcucGFyZW50TG9jYWxlXSkge1xuICAgICAgICAgICAgICAgICAgICBsb2NhbGVGYW1pbGllc1tjb25maWcucGFyZW50TG9jYWxlXSA9IFtdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBsb2NhbGVGYW1pbGllc1tjb25maWcucGFyZW50TG9jYWxlXS5wdXNoKHtcbiAgICAgICAgICAgICAgICAgICAgbmFtZTogbmFtZSxcbiAgICAgICAgICAgICAgICAgICAgY29uZmlnOiBjb25maWdcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBsb2NhbGVzW25hbWVdID0gbmV3IExvY2FsZShtZXJnZUNvbmZpZ3MocGFyZW50Q29uZmlnLCBjb25maWcpKTtcblxuICAgICAgICBpZiAobG9jYWxlRmFtaWxpZXNbbmFtZV0pIHtcbiAgICAgICAgICAgIGxvY2FsZUZhbWlsaWVzW25hbWVdLmZvckVhY2goZnVuY3Rpb24gKHgpIHtcbiAgICAgICAgICAgICAgICBkZWZpbmVMb2NhbGUoeC5uYW1lLCB4LmNvbmZpZyk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGJhY2t3YXJkcyBjb21wYXQgZm9yIG5vdzogYWxzbyBzZXQgdGhlIGxvY2FsZVxuICAgICAgICAvLyBtYWtlIHN1cmUgd2Ugc2V0IHRoZSBsb2NhbGUgQUZURVIgYWxsIGNoaWxkIGxvY2FsZXMgaGF2ZSBiZWVuXG4gICAgICAgIC8vIGNyZWF0ZWQsIHNvIHdlIHdvbid0IGVuZCB1cCB3aXRoIHRoZSBjaGlsZCBsb2NhbGUgc2V0LlxuICAgICAgICBnZXRTZXRHbG9iYWxMb2NhbGUobmFtZSk7XG5cblxuICAgICAgICByZXR1cm4gbG9jYWxlc1tuYW1lXTtcbiAgICB9IGVsc2Uge1xuICAgICAgICAvLyB1c2VmdWwgZm9yIHRlc3RpbmdcbiAgICAgICAgZGVsZXRlIGxvY2FsZXNbbmFtZV07XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gdXBkYXRlTG9jYWxlKG5hbWUsIGNvbmZpZykge1xuICAgIGlmIChjb25maWcgIT0gbnVsbCkge1xuICAgICAgICB2YXIgbG9jYWxlLCB0bXBMb2NhbGUsIHBhcmVudENvbmZpZyA9IGJhc2VDb25maWc7XG4gICAgICAgIC8vIE1FUkdFXG4gICAgICAgIHRtcExvY2FsZSA9IGxvYWRMb2NhbGUobmFtZSk7XG4gICAgICAgIGlmICh0bXBMb2NhbGUgIT0gbnVsbCkge1xuICAgICAgICAgICAgcGFyZW50Q29uZmlnID0gdG1wTG9jYWxlLl9jb25maWc7XG4gICAgICAgIH1cbiAgICAgICAgY29uZmlnID0gbWVyZ2VDb25maWdzKHBhcmVudENvbmZpZywgY29uZmlnKTtcbiAgICAgICAgbG9jYWxlID0gbmV3IExvY2FsZShjb25maWcpO1xuICAgICAgICBsb2NhbGUucGFyZW50TG9jYWxlID0gbG9jYWxlc1tuYW1lXTtcbiAgICAgICAgbG9jYWxlc1tuYW1lXSA9IGxvY2FsZTtcblxuICAgICAgICAvLyBiYWNrd2FyZHMgY29tcGF0IGZvciBub3c6IGFsc28gc2V0IHRoZSBsb2NhbGVcbiAgICAgICAgZ2V0U2V0R2xvYmFsTG9jYWxlKG5hbWUpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIHBhc3MgbnVsbCBmb3IgY29uZmlnIHRvIHVudXBkYXRlLCB1c2VmdWwgZm9yIHRlc3RzXG4gICAgICAgIGlmIChsb2NhbGVzW25hbWVdICE9IG51bGwpIHtcbiAgICAgICAgICAgIGlmIChsb2NhbGVzW25hbWVdLnBhcmVudExvY2FsZSAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgbG9jYWxlc1tuYW1lXSA9IGxvY2FsZXNbbmFtZV0ucGFyZW50TG9jYWxlO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChsb2NhbGVzW25hbWVdICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICBkZWxldGUgbG9jYWxlc1tuYW1lXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gbG9jYWxlc1tuYW1lXTtcbn1cblxuLy8gcmV0dXJucyBsb2NhbGUgZGF0YVxuZnVuY3Rpb24gZ2V0TG9jYWxlIChrZXkpIHtcbiAgICB2YXIgbG9jYWxlO1xuXG4gICAgaWYgKGtleSAmJiBrZXkuX2xvY2FsZSAmJiBrZXkuX2xvY2FsZS5fYWJicikge1xuICAgICAgICBrZXkgPSBrZXkuX2xvY2FsZS5fYWJicjtcbiAgICB9XG5cbiAgICBpZiAoIWtleSkge1xuICAgICAgICByZXR1cm4gZ2xvYmFsTG9jYWxlO1xuICAgIH1cblxuICAgIGlmICghaXNBcnJheShrZXkpKSB7XG4gICAgICAgIC8vc2hvcnQtY2lyY3VpdCBldmVyeXRoaW5nIGVsc2VcbiAgICAgICAgbG9jYWxlID0gbG9hZExvY2FsZShrZXkpO1xuICAgICAgICBpZiAobG9jYWxlKSB7XG4gICAgICAgICAgICByZXR1cm4gbG9jYWxlO1xuICAgICAgICB9XG4gICAgICAgIGtleSA9IFtrZXldO1xuICAgIH1cblxuICAgIHJldHVybiBjaG9vc2VMb2NhbGUoa2V5KTtcbn1cblxuZnVuY3Rpb24gbGlzdExvY2FsZXMoKSB7XG4gICAgcmV0dXJuIGtleXMobG9jYWxlcyk7XG59XG5cbmZ1bmN0aW9uIGNoZWNrT3ZlcmZsb3cgKG0pIHtcbiAgICB2YXIgb3ZlcmZsb3c7XG4gICAgdmFyIGEgPSBtLl9hO1xuXG4gICAgaWYgKGEgJiYgZ2V0UGFyc2luZ0ZsYWdzKG0pLm92ZXJmbG93ID09PSAtMikge1xuICAgICAgICBvdmVyZmxvdyA9XG4gICAgICAgICAgICBhW01PTlRIXSAgICAgICA8IDAgfHwgYVtNT05USF0gICAgICAgPiAxMSAgPyBNT05USCA6XG4gICAgICAgICAgICBhW0RBVEVdICAgICAgICA8IDEgfHwgYVtEQVRFXSAgICAgICAgPiBkYXlzSW5Nb250aChhW1lFQVJdLCBhW01PTlRIXSkgPyBEQVRFIDpcbiAgICAgICAgICAgIGFbSE9VUl0gICAgICAgIDwgMCB8fCBhW0hPVVJdICAgICAgICA+IDI0IHx8IChhW0hPVVJdID09PSAyNCAmJiAoYVtNSU5VVEVdICE9PSAwIHx8IGFbU0VDT05EXSAhPT0gMCB8fCBhW01JTExJU0VDT05EXSAhPT0gMCkpID8gSE9VUiA6XG4gICAgICAgICAgICBhW01JTlVURV0gICAgICA8IDAgfHwgYVtNSU5VVEVdICAgICAgPiA1OSAgPyBNSU5VVEUgOlxuICAgICAgICAgICAgYVtTRUNPTkRdICAgICAgPCAwIHx8IGFbU0VDT05EXSAgICAgID4gNTkgID8gU0VDT05EIDpcbiAgICAgICAgICAgIGFbTUlMTElTRUNPTkRdIDwgMCB8fCBhW01JTExJU0VDT05EXSA+IDk5OSA/IE1JTExJU0VDT05EIDpcbiAgICAgICAgICAgIC0xO1xuXG4gICAgICAgIGlmIChnZXRQYXJzaW5nRmxhZ3MobSkuX292ZXJmbG93RGF5T2ZZZWFyICYmIChvdmVyZmxvdyA8IFlFQVIgfHwgb3ZlcmZsb3cgPiBEQVRFKSkge1xuICAgICAgICAgICAgb3ZlcmZsb3cgPSBEQVRFO1xuICAgICAgICB9XG4gICAgICAgIGlmIChnZXRQYXJzaW5nRmxhZ3MobSkuX292ZXJmbG93V2Vla3MgJiYgb3ZlcmZsb3cgPT09IC0xKSB7XG4gICAgICAgICAgICBvdmVyZmxvdyA9IFdFRUs7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGdldFBhcnNpbmdGbGFncyhtKS5fb3ZlcmZsb3dXZWVrZGF5ICYmIG92ZXJmbG93ID09PSAtMSkge1xuICAgICAgICAgICAgb3ZlcmZsb3cgPSBXRUVLREFZO1xuICAgICAgICB9XG5cbiAgICAgICAgZ2V0UGFyc2luZ0ZsYWdzKG0pLm92ZXJmbG93ID0gb3ZlcmZsb3c7XG4gICAgfVxuXG4gICAgcmV0dXJuIG07XG59XG5cbi8vIFBpY2sgdGhlIGZpcnN0IGRlZmluZWQgb2YgdHdvIG9yIHRocmVlIGFyZ3VtZW50cy5cbmZ1bmN0aW9uIGRlZmF1bHRzKGEsIGIsIGMpIHtcbiAgICBpZiAoYSAhPSBudWxsKSB7XG4gICAgICAgIHJldHVybiBhO1xuICAgIH1cbiAgICBpZiAoYiAhPSBudWxsKSB7XG4gICAgICAgIHJldHVybiBiO1xuICAgIH1cbiAgICByZXR1cm4gYztcbn1cblxuZnVuY3Rpb24gY3VycmVudERhdGVBcnJheShjb25maWcpIHtcbiAgICAvLyBob29rcyBpcyBhY3R1YWxseSB0aGUgZXhwb3J0ZWQgbW9tZW50IG9iamVjdFxuICAgIHZhciBub3dWYWx1ZSA9IG5ldyBEYXRlKGhvb2tzLm5vdygpKTtcbiAgICBpZiAoY29uZmlnLl91c2VVVEMpIHtcbiAgICAgICAgcmV0dXJuIFtub3dWYWx1ZS5nZXRVVENGdWxsWWVhcigpLCBub3dWYWx1ZS5nZXRVVENNb250aCgpLCBub3dWYWx1ZS5nZXRVVENEYXRlKCldO1xuICAgIH1cbiAgICByZXR1cm4gW25vd1ZhbHVlLmdldEZ1bGxZZWFyKCksIG5vd1ZhbHVlLmdldE1vbnRoKCksIG5vd1ZhbHVlLmdldERhdGUoKV07XG59XG5cbi8vIGNvbnZlcnQgYW4gYXJyYXkgdG8gYSBkYXRlLlxuLy8gdGhlIGFycmF5IHNob3VsZCBtaXJyb3IgdGhlIHBhcmFtZXRlcnMgYmVsb3dcbi8vIG5vdGU6IGFsbCB2YWx1ZXMgcGFzdCB0aGUgeWVhciBhcmUgb3B0aW9uYWwgYW5kIHdpbGwgZGVmYXVsdCB0byB0aGUgbG93ZXN0IHBvc3NpYmxlIHZhbHVlLlxuLy8gW3llYXIsIG1vbnRoLCBkYXkgLCBob3VyLCBtaW51dGUsIHNlY29uZCwgbWlsbGlzZWNvbmRdXG5mdW5jdGlvbiBjb25maWdGcm9tQXJyYXkgKGNvbmZpZykge1xuICAgIHZhciBpLCBkYXRlLCBpbnB1dCA9IFtdLCBjdXJyZW50RGF0ZSwgZXhwZWN0ZWRXZWVrZGF5LCB5ZWFyVG9Vc2U7XG5cbiAgICBpZiAoY29uZmlnLl9kKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjdXJyZW50RGF0ZSA9IGN1cnJlbnREYXRlQXJyYXkoY29uZmlnKTtcblxuICAgIC8vY29tcHV0ZSBkYXkgb2YgdGhlIHllYXIgZnJvbSB3ZWVrcyBhbmQgd2Vla2RheXNcbiAgICBpZiAoY29uZmlnLl93ICYmIGNvbmZpZy5fYVtEQVRFXSA9PSBudWxsICYmIGNvbmZpZy5fYVtNT05USF0gPT0gbnVsbCkge1xuICAgICAgICBkYXlPZlllYXJGcm9tV2Vla0luZm8oY29uZmlnKTtcbiAgICB9XG5cbiAgICAvL2lmIHRoZSBkYXkgb2YgdGhlIHllYXIgaXMgc2V0LCBmaWd1cmUgb3V0IHdoYXQgaXQgaXNcbiAgICBpZiAoY29uZmlnLl9kYXlPZlllYXIgIT0gbnVsbCkge1xuICAgICAgICB5ZWFyVG9Vc2UgPSBkZWZhdWx0cyhjb25maWcuX2FbWUVBUl0sIGN1cnJlbnREYXRlW1lFQVJdKTtcblxuICAgICAgICBpZiAoY29uZmlnLl9kYXlPZlllYXIgPiBkYXlzSW5ZZWFyKHllYXJUb1VzZSkgfHwgY29uZmlnLl9kYXlPZlllYXIgPT09IDApIHtcbiAgICAgICAgICAgIGdldFBhcnNpbmdGbGFncyhjb25maWcpLl9vdmVyZmxvd0RheU9mWWVhciA9IHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICBkYXRlID0gY3JlYXRlVVRDRGF0ZSh5ZWFyVG9Vc2UsIDAsIGNvbmZpZy5fZGF5T2ZZZWFyKTtcbiAgICAgICAgY29uZmlnLl9hW01PTlRIXSA9IGRhdGUuZ2V0VVRDTW9udGgoKTtcbiAgICAgICAgY29uZmlnLl9hW0RBVEVdID0gZGF0ZS5nZXRVVENEYXRlKCk7XG4gICAgfVxuXG4gICAgLy8gRGVmYXVsdCB0byBjdXJyZW50IGRhdGUuXG4gICAgLy8gKiBpZiBubyB5ZWFyLCBtb250aCwgZGF5IG9mIG1vbnRoIGFyZSBnaXZlbiwgZGVmYXVsdCB0byB0b2RheVxuICAgIC8vICogaWYgZGF5IG9mIG1vbnRoIGlzIGdpdmVuLCBkZWZhdWx0IG1vbnRoIGFuZCB5ZWFyXG4gICAgLy8gKiBpZiBtb250aCBpcyBnaXZlbiwgZGVmYXVsdCBvbmx5IHllYXJcbiAgICAvLyAqIGlmIHllYXIgaXMgZ2l2ZW4sIGRvbid0IGRlZmF1bHQgYW55dGhpbmdcbiAgICBmb3IgKGkgPSAwOyBpIDwgMyAmJiBjb25maWcuX2FbaV0gPT0gbnVsbDsgKytpKSB7XG4gICAgICAgIGNvbmZpZy5fYVtpXSA9IGlucHV0W2ldID0gY3VycmVudERhdGVbaV07XG4gICAgfVxuXG4gICAgLy8gWmVybyBvdXQgd2hhdGV2ZXIgd2FzIG5vdCBkZWZhdWx0ZWQsIGluY2x1ZGluZyB0aW1lXG4gICAgZm9yICg7IGkgPCA3OyBpKyspIHtcbiAgICAgICAgY29uZmlnLl9hW2ldID0gaW5wdXRbaV0gPSAoY29uZmlnLl9hW2ldID09IG51bGwpID8gKGkgPT09IDIgPyAxIDogMCkgOiBjb25maWcuX2FbaV07XG4gICAgfVxuXG4gICAgLy8gQ2hlY2sgZm9yIDI0OjAwOjAwLjAwMFxuICAgIGlmIChjb25maWcuX2FbSE9VUl0gPT09IDI0ICYmXG4gICAgICAgICAgICBjb25maWcuX2FbTUlOVVRFXSA9PT0gMCAmJlxuICAgICAgICAgICAgY29uZmlnLl9hW1NFQ09ORF0gPT09IDAgJiZcbiAgICAgICAgICAgIGNvbmZpZy5fYVtNSUxMSVNFQ09ORF0gPT09IDApIHtcbiAgICAgICAgY29uZmlnLl9uZXh0RGF5ID0gdHJ1ZTtcbiAgICAgICAgY29uZmlnLl9hW0hPVVJdID0gMDtcbiAgICB9XG5cbiAgICBjb25maWcuX2QgPSAoY29uZmlnLl91c2VVVEMgPyBjcmVhdGVVVENEYXRlIDogY3JlYXRlRGF0ZSkuYXBwbHkobnVsbCwgaW5wdXQpO1xuICAgIGV4cGVjdGVkV2Vla2RheSA9IGNvbmZpZy5fdXNlVVRDID8gY29uZmlnLl9kLmdldFVUQ0RheSgpIDogY29uZmlnLl9kLmdldERheSgpO1xuXG4gICAgLy8gQXBwbHkgdGltZXpvbmUgb2Zmc2V0IGZyb20gaW5wdXQuIFRoZSBhY3R1YWwgdXRjT2Zmc2V0IGNhbiBiZSBjaGFuZ2VkXG4gICAgLy8gd2l0aCBwYXJzZVpvbmUuXG4gICAgaWYgKGNvbmZpZy5fdHptICE9IG51bGwpIHtcbiAgICAgICAgY29uZmlnLl9kLnNldFVUQ01pbnV0ZXMoY29uZmlnLl9kLmdldFVUQ01pbnV0ZXMoKSAtIGNvbmZpZy5fdHptKTtcbiAgICB9XG5cbiAgICBpZiAoY29uZmlnLl9uZXh0RGF5KSB7XG4gICAgICAgIGNvbmZpZy5fYVtIT1VSXSA9IDI0O1xuICAgIH1cblxuICAgIC8vIGNoZWNrIGZvciBtaXNtYXRjaGluZyBkYXkgb2Ygd2Vla1xuICAgIGlmIChjb25maWcuX3cgJiYgdHlwZW9mIGNvbmZpZy5fdy5kICE9PSAndW5kZWZpbmVkJyAmJiBjb25maWcuX3cuZCAhPT0gZXhwZWN0ZWRXZWVrZGF5KSB7XG4gICAgICAgIGdldFBhcnNpbmdGbGFncyhjb25maWcpLndlZWtkYXlNaXNtYXRjaCA9IHRydWU7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBkYXlPZlllYXJGcm9tV2Vla0luZm8oY29uZmlnKSB7XG4gICAgdmFyIHcsIHdlZWtZZWFyLCB3ZWVrLCB3ZWVrZGF5LCBkb3csIGRveSwgdGVtcCwgd2Vla2RheU92ZXJmbG93O1xuXG4gICAgdyA9IGNvbmZpZy5fdztcbiAgICBpZiAody5HRyAhPSBudWxsIHx8IHcuVyAhPSBudWxsIHx8IHcuRSAhPSBudWxsKSB7XG4gICAgICAgIGRvdyA9IDE7XG4gICAgICAgIGRveSA9IDQ7XG5cbiAgICAgICAgLy8gVE9ETzogV2UgbmVlZCB0byB0YWtlIHRoZSBjdXJyZW50IGlzb1dlZWtZZWFyLCBidXQgdGhhdCBkZXBlbmRzIG9uXG4gICAgICAgIC8vIGhvdyB3ZSBpbnRlcnByZXQgbm93IChsb2NhbCwgdXRjLCBmaXhlZCBvZmZzZXQpLiBTbyBjcmVhdGVcbiAgICAgICAgLy8gYSBub3cgdmVyc2lvbiBvZiBjdXJyZW50IGNvbmZpZyAodGFrZSBsb2NhbC91dGMvb2Zmc2V0IGZsYWdzLCBhbmRcbiAgICAgICAgLy8gY3JlYXRlIG5vdykuXG4gICAgICAgIHdlZWtZZWFyID0gZGVmYXVsdHMody5HRywgY29uZmlnLl9hW1lFQVJdLCB3ZWVrT2ZZZWFyKGNyZWF0ZUxvY2FsKCksIDEsIDQpLnllYXIpO1xuICAgICAgICB3ZWVrID0gZGVmYXVsdHMody5XLCAxKTtcbiAgICAgICAgd2Vla2RheSA9IGRlZmF1bHRzKHcuRSwgMSk7XG4gICAgICAgIGlmICh3ZWVrZGF5IDwgMSB8fCB3ZWVrZGF5ID4gNykge1xuICAgICAgICAgICAgd2Vla2RheU92ZXJmbG93ID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAgIGRvdyA9IGNvbmZpZy5fbG9jYWxlLl93ZWVrLmRvdztcbiAgICAgICAgZG95ID0gY29uZmlnLl9sb2NhbGUuX3dlZWsuZG95O1xuXG4gICAgICAgIHZhciBjdXJXZWVrID0gd2Vla09mWWVhcihjcmVhdGVMb2NhbCgpLCBkb3csIGRveSk7XG5cbiAgICAgICAgd2Vla1llYXIgPSBkZWZhdWx0cyh3LmdnLCBjb25maWcuX2FbWUVBUl0sIGN1cldlZWsueWVhcik7XG5cbiAgICAgICAgLy8gRGVmYXVsdCB0byBjdXJyZW50IHdlZWsuXG4gICAgICAgIHdlZWsgPSBkZWZhdWx0cyh3LncsIGN1cldlZWsud2Vlayk7XG5cbiAgICAgICAgaWYgKHcuZCAhPSBudWxsKSB7XG4gICAgICAgICAgICAvLyB3ZWVrZGF5IC0tIGxvdyBkYXkgbnVtYmVycyBhcmUgY29uc2lkZXJlZCBuZXh0IHdlZWtcbiAgICAgICAgICAgIHdlZWtkYXkgPSB3LmQ7XG4gICAgICAgICAgICBpZiAod2Vla2RheSA8IDAgfHwgd2Vla2RheSA+IDYpIHtcbiAgICAgICAgICAgICAgICB3ZWVrZGF5T3ZlcmZsb3cgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKHcuZSAhPSBudWxsKSB7XG4gICAgICAgICAgICAvLyBsb2NhbCB3ZWVrZGF5IC0tIGNvdW50aW5nIHN0YXJ0cyBmcm9tIGJlZ2luaW5nIG9mIHdlZWtcbiAgICAgICAgICAgIHdlZWtkYXkgPSB3LmUgKyBkb3c7XG4gICAgICAgICAgICBpZiAody5lIDwgMCB8fCB3LmUgPiA2KSB7XG4gICAgICAgICAgICAgICAgd2Vla2RheU92ZXJmbG93ID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIGRlZmF1bHQgdG8gYmVnaW5pbmcgb2Ygd2Vla1xuICAgICAgICAgICAgd2Vla2RheSA9IGRvdztcbiAgICAgICAgfVxuICAgIH1cbiAgICBpZiAod2VlayA8IDEgfHwgd2VlayA+IHdlZWtzSW5ZZWFyKHdlZWtZZWFyLCBkb3csIGRveSkpIHtcbiAgICAgICAgZ2V0UGFyc2luZ0ZsYWdzKGNvbmZpZykuX292ZXJmbG93V2Vla3MgPSB0cnVlO1xuICAgIH0gZWxzZSBpZiAod2Vla2RheU92ZXJmbG93ICE9IG51bGwpIHtcbiAgICAgICAgZ2V0UGFyc2luZ0ZsYWdzKGNvbmZpZykuX292ZXJmbG93V2Vla2RheSA9IHRydWU7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgdGVtcCA9IGRheU9mWWVhckZyb21XZWVrcyh3ZWVrWWVhciwgd2Vlaywgd2Vla2RheSwgZG93LCBkb3kpO1xuICAgICAgICBjb25maWcuX2FbWUVBUl0gPSB0ZW1wLnllYXI7XG4gICAgICAgIGNvbmZpZy5fZGF5T2ZZZWFyID0gdGVtcC5kYXlPZlllYXI7XG4gICAgfVxufVxuXG4vLyBpc28gODYwMSByZWdleFxuLy8gMDAwMC0wMC0wMCAwMDAwLVcwMCBvciAwMDAwLVcwMC0wICsgVCArIDAwIG9yIDAwOjAwIG9yIDAwOjAwOjAwIG9yIDAwOjAwOjAwLjAwMCArICswMDowMCBvciArMDAwMCBvciArMDApXG52YXIgZXh0ZW5kZWRJc29SZWdleCA9IC9eXFxzKigoPzpbKy1dXFxkezZ9fFxcZHs0fSktKD86XFxkXFxkLVxcZFxcZHxXXFxkXFxkLVxcZHxXXFxkXFxkfFxcZFxcZFxcZHxcXGRcXGQpKSg/OihUfCApKFxcZFxcZCg/OjpcXGRcXGQoPzo6XFxkXFxkKD86Wy4sXVxcZCspPyk/KT8pKFtcXCtcXC1dXFxkXFxkKD86Oj9cXGRcXGQpP3xcXHMqWik/KT8kLztcbnZhciBiYXNpY0lzb1JlZ2V4ID0gL15cXHMqKCg/OlsrLV1cXGR7Nn18XFxkezR9KSg/OlxcZFxcZFxcZFxcZHxXXFxkXFxkXFxkfFdcXGRcXGR8XFxkXFxkXFxkfFxcZFxcZCkpKD86KFR8ICkoXFxkXFxkKD86XFxkXFxkKD86XFxkXFxkKD86Wy4sXVxcZCspPyk/KT8pKFtcXCtcXC1dXFxkXFxkKD86Oj9cXGRcXGQpP3xcXHMqWik/KT8kLztcblxudmFyIHR6UmVnZXggPSAvWnxbKy1dXFxkXFxkKD86Oj9cXGRcXGQpPy87XG5cbnZhciBpc29EYXRlcyA9IFtcbiAgICBbJ1lZWVlZWS1NTS1ERCcsIC9bKy1dXFxkezZ9LVxcZFxcZC1cXGRcXGQvXSxcbiAgICBbJ1lZWVktTU0tREQnLCAvXFxkezR9LVxcZFxcZC1cXGRcXGQvXSxcbiAgICBbJ0dHR0ctW1ddV1ctRScsIC9cXGR7NH0tV1xcZFxcZC1cXGQvXSxcbiAgICBbJ0dHR0ctW1ddV1cnLCAvXFxkezR9LVdcXGRcXGQvLCBmYWxzZV0sXG4gICAgWydZWVlZLURERCcsIC9cXGR7NH0tXFxkezN9L10sXG4gICAgWydZWVlZLU1NJywgL1xcZHs0fS1cXGRcXGQvLCBmYWxzZV0sXG4gICAgWydZWVlZWVlNTUREJywgL1srLV1cXGR7MTB9L10sXG4gICAgWydZWVlZTU1ERCcsIC9cXGR7OH0vXSxcbiAgICAvLyBZWVlZTU0gaXMgTk9UIGFsbG93ZWQgYnkgdGhlIHN0YW5kYXJkXG4gICAgWydHR0dHW1ddV1dFJywgL1xcZHs0fVdcXGR7M30vXSxcbiAgICBbJ0dHR0dbV11XVycsIC9cXGR7NH1XXFxkezJ9LywgZmFsc2VdLFxuICAgIFsnWVlZWURERCcsIC9cXGR7N30vXVxuXTtcblxuLy8gaXNvIHRpbWUgZm9ybWF0cyBhbmQgcmVnZXhlc1xudmFyIGlzb1RpbWVzID0gW1xuICAgIFsnSEg6bW06c3MuU1NTUycsIC9cXGRcXGQ6XFxkXFxkOlxcZFxcZFxcLlxcZCsvXSxcbiAgICBbJ0hIOm1tOnNzLFNTU1MnLCAvXFxkXFxkOlxcZFxcZDpcXGRcXGQsXFxkKy9dLFxuICAgIFsnSEg6bW06c3MnLCAvXFxkXFxkOlxcZFxcZDpcXGRcXGQvXSxcbiAgICBbJ0hIOm1tJywgL1xcZFxcZDpcXGRcXGQvXSxcbiAgICBbJ0hIbW1zcy5TU1NTJywgL1xcZFxcZFxcZFxcZFxcZFxcZFxcLlxcZCsvXSxcbiAgICBbJ0hIbW1zcyxTU1NTJywgL1xcZFxcZFxcZFxcZFxcZFxcZCxcXGQrL10sXG4gICAgWydISG1tc3MnLCAvXFxkXFxkXFxkXFxkXFxkXFxkL10sXG4gICAgWydISG1tJywgL1xcZFxcZFxcZFxcZC9dLFxuICAgIFsnSEgnLCAvXFxkXFxkL11cbl07XG5cbnZhciBhc3BOZXRKc29uUmVnZXggPSAvXlxcLz9EYXRlXFwoKFxcLT9cXGQrKS9pO1xuXG4vLyBkYXRlIGZyb20gaXNvIGZvcm1hdFxuZnVuY3Rpb24gY29uZmlnRnJvbUlTTyhjb25maWcpIHtcbiAgICB2YXIgaSwgbCxcbiAgICAgICAgc3RyaW5nID0gY29uZmlnLl9pLFxuICAgICAgICBtYXRjaCA9IGV4dGVuZGVkSXNvUmVnZXguZXhlYyhzdHJpbmcpIHx8IGJhc2ljSXNvUmVnZXguZXhlYyhzdHJpbmcpLFxuICAgICAgICBhbGxvd1RpbWUsIGRhdGVGb3JtYXQsIHRpbWVGb3JtYXQsIHR6Rm9ybWF0O1xuXG4gICAgaWYgKG1hdGNoKSB7XG4gICAgICAgIGdldFBhcnNpbmdGbGFncyhjb25maWcpLmlzbyA9IHRydWU7XG5cbiAgICAgICAgZm9yIChpID0gMCwgbCA9IGlzb0RhdGVzLmxlbmd0aDsgaSA8IGw7IGkrKykge1xuICAgICAgICAgICAgaWYgKGlzb0RhdGVzW2ldWzFdLmV4ZWMobWF0Y2hbMV0pKSB7XG4gICAgICAgICAgICAgICAgZGF0ZUZvcm1hdCA9IGlzb0RhdGVzW2ldWzBdO1xuICAgICAgICAgICAgICAgIGFsbG93VGltZSA9IGlzb0RhdGVzW2ldWzJdICE9PSBmYWxzZTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoZGF0ZUZvcm1hdCA9PSBudWxsKSB7XG4gICAgICAgICAgICBjb25maWcuX2lzVmFsaWQgPSBmYWxzZTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAobWF0Y2hbM10pIHtcbiAgICAgICAgICAgIGZvciAoaSA9IDAsIGwgPSBpc29UaW1lcy5sZW5ndGg7IGkgPCBsOyBpKyspIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNvVGltZXNbaV1bMV0uZXhlYyhtYXRjaFszXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gbWF0Y2hbMl0gc2hvdWxkIGJlICdUJyBvciBzcGFjZVxuICAgICAgICAgICAgICAgICAgICB0aW1lRm9ybWF0ID0gKG1hdGNoWzJdIHx8ICcgJykgKyBpc29UaW1lc1tpXVswXTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRpbWVGb3JtYXQgPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIGNvbmZpZy5faXNWYWxpZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoIWFsbG93VGltZSAmJiB0aW1lRm9ybWF0ICE9IG51bGwpIHtcbiAgICAgICAgICAgIGNvbmZpZy5faXNWYWxpZCA9IGZhbHNlO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmIChtYXRjaFs0XSkge1xuICAgICAgICAgICAgaWYgKHR6UmVnZXguZXhlYyhtYXRjaFs0XSkpIHtcbiAgICAgICAgICAgICAgICB0ekZvcm1hdCA9ICdaJztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uZmlnLl9pc1ZhbGlkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGNvbmZpZy5fZiA9IGRhdGVGb3JtYXQgKyAodGltZUZvcm1hdCB8fCAnJykgKyAodHpGb3JtYXQgfHwgJycpO1xuICAgICAgICBjb25maWdGcm9tU3RyaW5nQW5kRm9ybWF0KGNvbmZpZyk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgY29uZmlnLl9pc1ZhbGlkID0gZmFsc2U7XG4gICAgfVxufVxuXG4vLyBSRkMgMjgyMiByZWdleDogRm9yIGRldGFpbHMgc2VlIGh0dHBzOi8vdG9vbHMuaWV0Zi5vcmcvaHRtbC9yZmMyODIyI3NlY3Rpb24tMy4zXG52YXIgcmZjMjgyMiA9IC9eKD86KE1vbnxUdWV8V2VkfFRodXxGcml8U2F0fFN1biksP1xccyk/KFxcZHsxLDJ9KVxccyhKYW58RmVifE1hcnxBcHJ8TWF5fEp1bnxKdWx8QXVnfFNlcHxPY3R8Tm92fERlYylcXHMoXFxkezIsNH0pXFxzKFxcZFxcZCk6KFxcZFxcZCkoPzo6KFxcZFxcZCkpP1xccyg/OihVVHxHTVR8W0VDTVBdW1NEXVQpfChbWnpdKXwoWystXVxcZHs0fSkpJC87XG5cbmZ1bmN0aW9uIGV4dHJhY3RGcm9tUkZDMjgyMlN0cmluZ3MoeWVhclN0ciwgbW9udGhTdHIsIGRheVN0ciwgaG91clN0ciwgbWludXRlU3RyLCBzZWNvbmRTdHIpIHtcbiAgICB2YXIgcmVzdWx0ID0gW1xuICAgICAgICB1bnRydW5jYXRlWWVhcih5ZWFyU3RyKSxcbiAgICAgICAgZGVmYXVsdExvY2FsZU1vbnRoc1Nob3J0LmluZGV4T2YobW9udGhTdHIpLFxuICAgICAgICBwYXJzZUludChkYXlTdHIsIDEwKSxcbiAgICAgICAgcGFyc2VJbnQoaG91clN0ciwgMTApLFxuICAgICAgICBwYXJzZUludChtaW51dGVTdHIsIDEwKVxuICAgIF07XG5cbiAgICBpZiAoc2Vjb25kU3RyKSB7XG4gICAgICAgIHJlc3VsdC5wdXNoKHBhcnNlSW50KHNlY29uZFN0ciwgMTApKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xufVxuXG5mdW5jdGlvbiB1bnRydW5jYXRlWWVhcih5ZWFyU3RyKSB7XG4gICAgdmFyIHllYXIgPSBwYXJzZUludCh5ZWFyU3RyLCAxMCk7XG4gICAgaWYgKHllYXIgPD0gNDkpIHtcbiAgICAgICAgcmV0dXJuIDIwMDAgKyB5ZWFyO1xuICAgIH0gZWxzZSBpZiAoeWVhciA8PSA5OTkpIHtcbiAgICAgICAgcmV0dXJuIDE5MDAgKyB5ZWFyO1xuICAgIH1cbiAgICByZXR1cm4geWVhcjtcbn1cblxuZnVuY3Rpb24gcHJlcHJvY2Vzc1JGQzI4MjIocykge1xuICAgIC8vIFJlbW92ZSBjb21tZW50cyBhbmQgZm9sZGluZyB3aGl0ZXNwYWNlIGFuZCByZXBsYWNlIG11bHRpcGxlLXNwYWNlcyB3aXRoIGEgc2luZ2xlIHNwYWNlXG4gICAgcmV0dXJuIHMucmVwbGFjZSgvXFwoW14pXSpcXCl8W1xcblxcdF0vZywgJyAnKS5yZXBsYWNlKC8oXFxzXFxzKykvZywgJyAnKS50cmltKCk7XG59XG5cbmZ1bmN0aW9uIGNoZWNrV2Vla2RheSh3ZWVrZGF5U3RyLCBwYXJzZWRJbnB1dCwgY29uZmlnKSB7XG4gICAgaWYgKHdlZWtkYXlTdHIpIHtcbiAgICAgICAgLy8gVE9ETzogUmVwbGFjZSB0aGUgdmFuaWxsYSBKUyBEYXRlIG9iamVjdCB3aXRoIGFuIGluZGVwZW50ZW50IGRheS1vZi13ZWVrIGNoZWNrLlxuICAgICAgICB2YXIgd2Vla2RheVByb3ZpZGVkID0gZGVmYXVsdExvY2FsZVdlZWtkYXlzU2hvcnQuaW5kZXhPZih3ZWVrZGF5U3RyKSxcbiAgICAgICAgICAgIHdlZWtkYXlBY3R1YWwgPSBuZXcgRGF0ZShwYXJzZWRJbnB1dFswXSwgcGFyc2VkSW5wdXRbMV0sIHBhcnNlZElucHV0WzJdKS5nZXREYXkoKTtcbiAgICAgICAgaWYgKHdlZWtkYXlQcm92aWRlZCAhPT0gd2Vla2RheUFjdHVhbCkge1xuICAgICAgICAgICAgZ2V0UGFyc2luZ0ZsYWdzKGNvbmZpZykud2Vla2RheU1pc21hdGNoID0gdHJ1ZTtcbiAgICAgICAgICAgIGNvbmZpZy5faXNWYWxpZCA9IGZhbHNlO1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xufVxuXG52YXIgb2JzT2Zmc2V0cyA9IHtcbiAgICBVVDogMCxcbiAgICBHTVQ6IDAsXG4gICAgRURUOiAtNCAqIDYwLFxuICAgIEVTVDogLTUgKiA2MCxcbiAgICBDRFQ6IC01ICogNjAsXG4gICAgQ1NUOiAtNiAqIDYwLFxuICAgIE1EVDogLTYgKiA2MCxcbiAgICBNU1Q6IC03ICogNjAsXG4gICAgUERUOiAtNyAqIDYwLFxuICAgIFBTVDogLTggKiA2MFxufTtcblxuZnVuY3Rpb24gY2FsY3VsYXRlT2Zmc2V0KG9ic09mZnNldCwgbWlsaXRhcnlPZmZzZXQsIG51bU9mZnNldCkge1xuICAgIGlmIChvYnNPZmZzZXQpIHtcbiAgICAgICAgcmV0dXJuIG9ic09mZnNldHNbb2JzT2Zmc2V0XTtcbiAgICB9IGVsc2UgaWYgKG1pbGl0YXJ5T2Zmc2V0KSB7XG4gICAgICAgIC8vIHRoZSBvbmx5IGFsbG93ZWQgbWlsaXRhcnkgdHogaXMgWlxuICAgICAgICByZXR1cm4gMDtcbiAgICB9IGVsc2Uge1xuICAgICAgICB2YXIgaG0gPSBwYXJzZUludChudW1PZmZzZXQsIDEwKTtcbiAgICAgICAgdmFyIG0gPSBobSAlIDEwMCwgaCA9IChobSAtIG0pIC8gMTAwO1xuICAgICAgICByZXR1cm4gaCAqIDYwICsgbTtcbiAgICB9XG59XG5cbi8vIGRhdGUgYW5kIHRpbWUgZnJvbSByZWYgMjgyMiBmb3JtYXRcbmZ1bmN0aW9uIGNvbmZpZ0Zyb21SRkMyODIyKGNvbmZpZykge1xuICAgIHZhciBtYXRjaCA9IHJmYzI4MjIuZXhlYyhwcmVwcm9jZXNzUkZDMjgyMihjb25maWcuX2kpKTtcbiAgICBpZiAobWF0Y2gpIHtcbiAgICAgICAgdmFyIHBhcnNlZEFycmF5ID0gZXh0cmFjdEZyb21SRkMyODIyU3RyaW5ncyhtYXRjaFs0XSwgbWF0Y2hbM10sIG1hdGNoWzJdLCBtYXRjaFs1XSwgbWF0Y2hbNl0sIG1hdGNoWzddKTtcbiAgICAgICAgaWYgKCFjaGVja1dlZWtkYXkobWF0Y2hbMV0sIHBhcnNlZEFycmF5LCBjb25maWcpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBjb25maWcuX2EgPSBwYXJzZWRBcnJheTtcbiAgICAgICAgY29uZmlnLl90em0gPSBjYWxjdWxhdGVPZmZzZXQobWF0Y2hbOF0sIG1hdGNoWzldLCBtYXRjaFsxMF0pO1xuXG4gICAgICAgIGNvbmZpZy5fZCA9IGNyZWF0ZVVUQ0RhdGUuYXBwbHkobnVsbCwgY29uZmlnLl9hKTtcbiAgICAgICAgY29uZmlnLl9kLnNldFVUQ01pbnV0ZXMoY29uZmlnLl9kLmdldFVUQ01pbnV0ZXMoKSAtIGNvbmZpZy5fdHptKTtcblxuICAgICAgICBnZXRQYXJzaW5nRmxhZ3MoY29uZmlnKS5yZmMyODIyID0gdHJ1ZTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBjb25maWcuX2lzVmFsaWQgPSBmYWxzZTtcbiAgICB9XG59XG5cbi8vIGRhdGUgZnJvbSBpc28gZm9ybWF0IG9yIGZhbGxiYWNrXG5mdW5jdGlvbiBjb25maWdGcm9tU3RyaW5nKGNvbmZpZykge1xuICAgIHZhciBtYXRjaGVkID0gYXNwTmV0SnNvblJlZ2V4LmV4ZWMoY29uZmlnLl9pKTtcblxuICAgIGlmIChtYXRjaGVkICE9PSBudWxsKSB7XG4gICAgICAgIGNvbmZpZy5fZCA9IG5ldyBEYXRlKCttYXRjaGVkWzFdKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbmZpZ0Zyb21JU08oY29uZmlnKTtcbiAgICBpZiAoY29uZmlnLl9pc1ZhbGlkID09PSBmYWxzZSkge1xuICAgICAgICBkZWxldGUgY29uZmlnLl9pc1ZhbGlkO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25maWdGcm9tUkZDMjgyMihjb25maWcpO1xuICAgIGlmIChjb25maWcuX2lzVmFsaWQgPT09IGZhbHNlKSB7XG4gICAgICAgIGRlbGV0ZSBjb25maWcuX2lzVmFsaWQ7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIEZpbmFsIGF0dGVtcHQsIHVzZSBJbnB1dCBGYWxsYmFja1xuICAgIGhvb2tzLmNyZWF0ZUZyb21JbnB1dEZhbGxiYWNrKGNvbmZpZyk7XG59XG5cbmhvb2tzLmNyZWF0ZUZyb21JbnB1dEZhbGxiYWNrID0gZGVwcmVjYXRlKFxuICAgICd2YWx1ZSBwcm92aWRlZCBpcyBub3QgaW4gYSByZWNvZ25pemVkIFJGQzI4MjIgb3IgSVNPIGZvcm1hdC4gbW9tZW50IGNvbnN0cnVjdGlvbiBmYWxscyBiYWNrIHRvIGpzIERhdGUoKSwgJyArXG4gICAgJ3doaWNoIGlzIG5vdCByZWxpYWJsZSBhY3Jvc3MgYWxsIGJyb3dzZXJzIGFuZCB2ZXJzaW9ucy4gTm9uIFJGQzI4MjIvSVNPIGRhdGUgZm9ybWF0cyBhcmUgJyArXG4gICAgJ2Rpc2NvdXJhZ2VkIGFuZCB3aWxsIGJlIHJlbW92ZWQgaW4gYW4gdXBjb21pbmcgbWFqb3IgcmVsZWFzZS4gUGxlYXNlIHJlZmVyIHRvICcgK1xuICAgICdodHRwOi8vbW9tZW50anMuY29tL2d1aWRlcy8jL3dhcm5pbmdzL2pzLWRhdGUvIGZvciBtb3JlIGluZm8uJyxcbiAgICBmdW5jdGlvbiAoY29uZmlnKSB7XG4gICAgICAgIGNvbmZpZy5fZCA9IG5ldyBEYXRlKGNvbmZpZy5faSArIChjb25maWcuX3VzZVVUQyA/ICcgVVRDJyA6ICcnKSk7XG4gICAgfVxuKTtcblxuLy8gY29uc3RhbnQgdGhhdCByZWZlcnMgdG8gdGhlIElTTyBzdGFuZGFyZFxuaG9va3MuSVNPXzg2MDEgPSBmdW5jdGlvbiAoKSB7fTtcblxuLy8gY29uc3RhbnQgdGhhdCByZWZlcnMgdG8gdGhlIFJGQyAyODIyIGZvcm1cbmhvb2tzLlJGQ18yODIyID0gZnVuY3Rpb24gKCkge307XG5cbi8vIGRhdGUgZnJvbSBzdHJpbmcgYW5kIGZvcm1hdCBzdHJpbmdcbmZ1bmN0aW9uIGNvbmZpZ0Zyb21TdHJpbmdBbmRGb3JtYXQoY29uZmlnKSB7XG4gICAgLy8gVE9ETzogTW92ZSB0aGlzIHRvIGFub3RoZXIgcGFydCBvZiB0aGUgY3JlYXRpb24gZmxvdyB0byBwcmV2ZW50IGNpcmN1bGFyIGRlcHNcbiAgICBpZiAoY29uZmlnLl9mID09PSBob29rcy5JU09fODYwMSkge1xuICAgICAgICBjb25maWdGcm9tSVNPKGNvbmZpZyk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKGNvbmZpZy5fZiA9PT0gaG9va3MuUkZDXzI4MjIpIHtcbiAgICAgICAgY29uZmlnRnJvbVJGQzI4MjIoY29uZmlnKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25maWcuX2EgPSBbXTtcbiAgICBnZXRQYXJzaW5nRmxhZ3MoY29uZmlnKS5lbXB0eSA9IHRydWU7XG5cbiAgICAvLyBUaGlzIGFycmF5IGlzIHVzZWQgdG8gbWFrZSBhIERhdGUsIGVpdGhlciB3aXRoIGBuZXcgRGF0ZWAgb3IgYERhdGUuVVRDYFxuICAgIHZhciBzdHJpbmcgPSAnJyArIGNvbmZpZy5faSxcbiAgICAgICAgaSwgcGFyc2VkSW5wdXQsIHRva2VucywgdG9rZW4sIHNraXBwZWQsXG4gICAgICAgIHN0cmluZ0xlbmd0aCA9IHN0cmluZy5sZW5ndGgsXG4gICAgICAgIHRvdGFsUGFyc2VkSW5wdXRMZW5ndGggPSAwO1xuXG4gICAgdG9rZW5zID0gZXhwYW5kRm9ybWF0KGNvbmZpZy5fZiwgY29uZmlnLl9sb2NhbGUpLm1hdGNoKGZvcm1hdHRpbmdUb2tlbnMpIHx8IFtdO1xuXG4gICAgZm9yIChpID0gMDsgaSA8IHRva2Vucy5sZW5ndGg7IGkrKykge1xuICAgICAgICB0b2tlbiA9IHRva2Vuc1tpXTtcbiAgICAgICAgcGFyc2VkSW5wdXQgPSAoc3RyaW5nLm1hdGNoKGdldFBhcnNlUmVnZXhGb3JUb2tlbih0b2tlbiwgY29uZmlnKSkgfHwgW10pWzBdO1xuICAgICAgICAvLyBjb25zb2xlLmxvZygndG9rZW4nLCB0b2tlbiwgJ3BhcnNlZElucHV0JywgcGFyc2VkSW5wdXQsXG4gICAgICAgIC8vICAgICAgICAgJ3JlZ2V4JywgZ2V0UGFyc2VSZWdleEZvclRva2VuKHRva2VuLCBjb25maWcpKTtcbiAgICAgICAgaWYgKHBhcnNlZElucHV0KSB7XG4gICAgICAgICAgICBza2lwcGVkID0gc3RyaW5nLnN1YnN0cigwLCBzdHJpbmcuaW5kZXhPZihwYXJzZWRJbnB1dCkpO1xuICAgICAgICAgICAgaWYgKHNraXBwZWQubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgIGdldFBhcnNpbmdGbGFncyhjb25maWcpLnVudXNlZElucHV0LnB1c2goc2tpcHBlZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzdHJpbmcgPSBzdHJpbmcuc2xpY2Uoc3RyaW5nLmluZGV4T2YocGFyc2VkSW5wdXQpICsgcGFyc2VkSW5wdXQubGVuZ3RoKTtcbiAgICAgICAgICAgIHRvdGFsUGFyc2VkSW5wdXRMZW5ndGggKz0gcGFyc2VkSW5wdXQubGVuZ3RoO1xuICAgICAgICB9XG4gICAgICAgIC8vIGRvbid0IHBhcnNlIGlmIGl0J3Mgbm90IGEga25vd24gdG9rZW5cbiAgICAgICAgaWYgKGZvcm1hdFRva2VuRnVuY3Rpb25zW3Rva2VuXSkge1xuICAgICAgICAgICAgaWYgKHBhcnNlZElucHV0KSB7XG4gICAgICAgICAgICAgICAgZ2V0UGFyc2luZ0ZsYWdzKGNvbmZpZykuZW1wdHkgPSBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGdldFBhcnNpbmdGbGFncyhjb25maWcpLnVudXNlZFRva2Vucy5wdXNoKHRva2VuKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGFkZFRpbWVUb0FycmF5RnJvbVRva2VuKHRva2VuLCBwYXJzZWRJbnB1dCwgY29uZmlnKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChjb25maWcuX3N0cmljdCAmJiAhcGFyc2VkSW5wdXQpIHtcbiAgICAgICAgICAgIGdldFBhcnNpbmdGbGFncyhjb25maWcpLnVudXNlZFRva2Vucy5wdXNoKHRva2VuKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIGFkZCByZW1haW5pbmcgdW5wYXJzZWQgaW5wdXQgbGVuZ3RoIHRvIHRoZSBzdHJpbmdcbiAgICBnZXRQYXJzaW5nRmxhZ3MoY29uZmlnKS5jaGFyc0xlZnRPdmVyID0gc3RyaW5nTGVuZ3RoIC0gdG90YWxQYXJzZWRJbnB1dExlbmd0aDtcbiAgICBpZiAoc3RyaW5nLmxlbmd0aCA+IDApIHtcbiAgICAgICAgZ2V0UGFyc2luZ0ZsYWdzKGNvbmZpZykudW51c2VkSW5wdXQucHVzaChzdHJpbmcpO1xuICAgIH1cblxuICAgIC8vIGNsZWFyIF8xMmggZmxhZyBpZiBob3VyIGlzIDw9IDEyXG4gICAgaWYgKGNvbmZpZy5fYVtIT1VSXSA8PSAxMiAmJlxuICAgICAgICBnZXRQYXJzaW5nRmxhZ3MoY29uZmlnKS5iaWdIb3VyID09PSB0cnVlICYmXG4gICAgICAgIGNvbmZpZy5fYVtIT1VSXSA+IDApIHtcbiAgICAgICAgZ2V0UGFyc2luZ0ZsYWdzKGNvbmZpZykuYmlnSG91ciA9IHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICBnZXRQYXJzaW5nRmxhZ3MoY29uZmlnKS5wYXJzZWREYXRlUGFydHMgPSBjb25maWcuX2Euc2xpY2UoMCk7XG4gICAgZ2V0UGFyc2luZ0ZsYWdzKGNvbmZpZykubWVyaWRpZW0gPSBjb25maWcuX21lcmlkaWVtO1xuICAgIC8vIGhhbmRsZSBtZXJpZGllbVxuICAgIGNvbmZpZy5fYVtIT1VSXSA9IG1lcmlkaWVtRml4V3JhcChjb25maWcuX2xvY2FsZSwgY29uZmlnLl9hW0hPVVJdLCBjb25maWcuX21lcmlkaWVtKTtcblxuICAgIGNvbmZpZ0Zyb21BcnJheShjb25maWcpO1xuICAgIGNoZWNrT3ZlcmZsb3coY29uZmlnKTtcbn1cblxuXG5mdW5jdGlvbiBtZXJpZGllbUZpeFdyYXAgKGxvY2FsZSwgaG91ciwgbWVyaWRpZW0pIHtcbiAgICB2YXIgaXNQbTtcblxuICAgIGlmIChtZXJpZGllbSA9PSBudWxsKSB7XG4gICAgICAgIC8vIG5vdGhpbmcgdG8gZG9cbiAgICAgICAgcmV0dXJuIGhvdXI7XG4gICAgfVxuICAgIGlmIChsb2NhbGUubWVyaWRpZW1Ib3VyICE9IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIGxvY2FsZS5tZXJpZGllbUhvdXIoaG91ciwgbWVyaWRpZW0pO1xuICAgIH0gZWxzZSBpZiAobG9jYWxlLmlzUE0gIT0gbnVsbCkge1xuICAgICAgICAvLyBGYWxsYmFja1xuICAgICAgICBpc1BtID0gbG9jYWxlLmlzUE0obWVyaWRpZW0pO1xuICAgICAgICBpZiAoaXNQbSAmJiBob3VyIDwgMTIpIHtcbiAgICAgICAgICAgIGhvdXIgKz0gMTI7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFpc1BtICYmIGhvdXIgPT09IDEyKSB7XG4gICAgICAgICAgICBob3VyID0gMDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gaG91cjtcbiAgICB9IGVsc2Uge1xuICAgICAgICAvLyB0aGlzIGlzIG5vdCBzdXBwb3NlZCB0byBoYXBwZW5cbiAgICAgICAgcmV0dXJuIGhvdXI7XG4gICAgfVxufVxuXG4vLyBkYXRlIGZyb20gc3RyaW5nIGFuZCBhcnJheSBvZiBmb3JtYXQgc3RyaW5nc1xuZnVuY3Rpb24gY29uZmlnRnJvbVN0cmluZ0FuZEFycmF5KGNvbmZpZykge1xuICAgIHZhciB0ZW1wQ29uZmlnLFxuICAgICAgICBiZXN0TW9tZW50LFxuXG4gICAgICAgIHNjb3JlVG9CZWF0LFxuICAgICAgICBpLFxuICAgICAgICBjdXJyZW50U2NvcmU7XG5cbiAgICBpZiAoY29uZmlnLl9mLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICBnZXRQYXJzaW5nRmxhZ3MoY29uZmlnKS5pbnZhbGlkRm9ybWF0ID0gdHJ1ZTtcbiAgICAgICAgY29uZmlnLl9kID0gbmV3IERhdGUoTmFOKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGZvciAoaSA9IDA7IGkgPCBjb25maWcuX2YubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgY3VycmVudFNjb3JlID0gMDtcbiAgICAgICAgdGVtcENvbmZpZyA9IGNvcHlDb25maWcoe30sIGNvbmZpZyk7XG4gICAgICAgIGlmIChjb25maWcuX3VzZVVUQyAhPSBudWxsKSB7XG4gICAgICAgICAgICB0ZW1wQ29uZmlnLl91c2VVVEMgPSBjb25maWcuX3VzZVVUQztcbiAgICAgICAgfVxuICAgICAgICB0ZW1wQ29uZmlnLl9mID0gY29uZmlnLl9mW2ldO1xuICAgICAgICBjb25maWdGcm9tU3RyaW5nQW5kRm9ybWF0KHRlbXBDb25maWcpO1xuXG4gICAgICAgIGlmICghaXNWYWxpZCh0ZW1wQ29uZmlnKSkge1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBpZiB0aGVyZSBpcyBhbnkgaW5wdXQgdGhhdCB3YXMgbm90IHBhcnNlZCBhZGQgYSBwZW5hbHR5IGZvciB0aGF0IGZvcm1hdFxuICAgICAgICBjdXJyZW50U2NvcmUgKz0gZ2V0UGFyc2luZ0ZsYWdzKHRlbXBDb25maWcpLmNoYXJzTGVmdE92ZXI7XG5cbiAgICAgICAgLy9vciB0b2tlbnNcbiAgICAgICAgY3VycmVudFNjb3JlICs9IGdldFBhcnNpbmdGbGFncyh0ZW1wQ29uZmlnKS51bnVzZWRUb2tlbnMubGVuZ3RoICogMTA7XG5cbiAgICAgICAgZ2V0UGFyc2luZ0ZsYWdzKHRlbXBDb25maWcpLnNjb3JlID0gY3VycmVudFNjb3JlO1xuXG4gICAgICAgIGlmIChzY29yZVRvQmVhdCA9PSBudWxsIHx8IGN1cnJlbnRTY29yZSA8IHNjb3JlVG9CZWF0KSB7XG4gICAgICAgICAgICBzY29yZVRvQmVhdCA9IGN1cnJlbnRTY29yZTtcbiAgICAgICAgICAgIGJlc3RNb21lbnQgPSB0ZW1wQ29uZmlnO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZXh0ZW5kKGNvbmZpZywgYmVzdE1vbWVudCB8fCB0ZW1wQ29uZmlnKTtcbn1cblxuZnVuY3Rpb24gY29uZmlnRnJvbU9iamVjdChjb25maWcpIHtcbiAgICBpZiAoY29uZmlnLl9kKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB2YXIgaSA9IG5vcm1hbGl6ZU9iamVjdFVuaXRzKGNvbmZpZy5faSk7XG4gICAgY29uZmlnLl9hID0gbWFwKFtpLnllYXIsIGkubW9udGgsIGkuZGF5IHx8IGkuZGF0ZSwgaS5ob3VyLCBpLm1pbnV0ZSwgaS5zZWNvbmQsIGkubWlsbGlzZWNvbmRdLCBmdW5jdGlvbiAob2JqKSB7XG4gICAgICAgIHJldHVybiBvYmogJiYgcGFyc2VJbnQob2JqLCAxMCk7XG4gICAgfSk7XG5cbiAgICBjb25maWdGcm9tQXJyYXkoY29uZmlnKTtcbn1cblxuZnVuY3Rpb24gY3JlYXRlRnJvbUNvbmZpZyAoY29uZmlnKSB7XG4gICAgdmFyIHJlcyA9IG5ldyBNb21lbnQoY2hlY2tPdmVyZmxvdyhwcmVwYXJlQ29uZmlnKGNvbmZpZykpKTtcbiAgICBpZiAocmVzLl9uZXh0RGF5KSB7XG4gICAgICAgIC8vIEFkZGluZyBpcyBzbWFydCBlbm91Z2ggYXJvdW5kIERTVFxuICAgICAgICByZXMuYWRkKDEsICdkJyk7XG4gICAgICAgIHJlcy5fbmV4dERheSA9IHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzO1xufVxuXG5mdW5jdGlvbiBwcmVwYXJlQ29uZmlnIChjb25maWcpIHtcbiAgICB2YXIgaW5wdXQgPSBjb25maWcuX2ksXG4gICAgICAgIGZvcm1hdCA9IGNvbmZpZy5fZjtcblxuICAgIGNvbmZpZy5fbG9jYWxlID0gY29uZmlnLl9sb2NhbGUgfHwgZ2V0TG9jYWxlKGNvbmZpZy5fbCk7XG5cbiAgICBpZiAoaW5wdXQgPT09IG51bGwgfHwgKGZvcm1hdCA9PT0gdW5kZWZpbmVkICYmIGlucHV0ID09PSAnJykpIHtcbiAgICAgICAgcmV0dXJuIGNyZWF0ZUludmFsaWQoe251bGxJbnB1dDogdHJ1ZX0pO1xuICAgIH1cblxuICAgIGlmICh0eXBlb2YgaW5wdXQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIGNvbmZpZy5faSA9IGlucHV0ID0gY29uZmlnLl9sb2NhbGUucHJlcGFyc2UoaW5wdXQpO1xuICAgIH1cblxuICAgIGlmIChpc01vbWVudChpbnB1dCkpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBNb21lbnQoY2hlY2tPdmVyZmxvdyhpbnB1dCkpO1xuICAgIH0gZWxzZSBpZiAoaXNEYXRlKGlucHV0KSkge1xuICAgICAgICBjb25maWcuX2QgPSBpbnB1dDtcbiAgICB9IGVsc2UgaWYgKGlzQXJyYXkoZm9ybWF0KSkge1xuICAgICAgICBjb25maWdGcm9tU3RyaW5nQW5kQXJyYXkoY29uZmlnKTtcbiAgICB9IGVsc2UgaWYgKGZvcm1hdCkge1xuICAgICAgICBjb25maWdGcm9tU3RyaW5nQW5kRm9ybWF0KGNvbmZpZyk7XG4gICAgfSAgZWxzZSB7XG4gICAgICAgIGNvbmZpZ0Zyb21JbnB1dChjb25maWcpO1xuICAgIH1cblxuICAgIGlmICghaXNWYWxpZChjb25maWcpKSB7XG4gICAgICAgIGNvbmZpZy5fZCA9IG51bGw7XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbmZpZztcbn1cblxuZnVuY3Rpb24gY29uZmlnRnJvbUlucHV0KGNvbmZpZykge1xuICAgIHZhciBpbnB1dCA9IGNvbmZpZy5faTtcbiAgICBpZiAoaXNVbmRlZmluZWQoaW5wdXQpKSB7XG4gICAgICAgIGNvbmZpZy5fZCA9IG5ldyBEYXRlKGhvb2tzLm5vdygpKTtcbiAgICB9IGVsc2UgaWYgKGlzRGF0ZShpbnB1dCkpIHtcbiAgICAgICAgY29uZmlnLl9kID0gbmV3IERhdGUoaW5wdXQudmFsdWVPZigpKTtcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBpbnB1dCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgY29uZmlnRnJvbVN0cmluZyhjb25maWcpO1xuICAgIH0gZWxzZSBpZiAoaXNBcnJheShpbnB1dCkpIHtcbiAgICAgICAgY29uZmlnLl9hID0gbWFwKGlucHV0LnNsaWNlKDApLCBmdW5jdGlvbiAob2JqKSB7XG4gICAgICAgICAgICByZXR1cm4gcGFyc2VJbnQob2JqLCAxMCk7XG4gICAgICAgIH0pO1xuICAgICAgICBjb25maWdGcm9tQXJyYXkoY29uZmlnKTtcbiAgICB9IGVsc2UgaWYgKGlzT2JqZWN0KGlucHV0KSkge1xuICAgICAgICBjb25maWdGcm9tT2JqZWN0KGNvbmZpZyk7XG4gICAgfSBlbHNlIGlmIChpc051bWJlcihpbnB1dCkpIHtcbiAgICAgICAgLy8gZnJvbSBtaWxsaXNlY29uZHNcbiAgICAgICAgY29uZmlnLl9kID0gbmV3IERhdGUoaW5wdXQpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGhvb2tzLmNyZWF0ZUZyb21JbnB1dEZhbGxiYWNrKGNvbmZpZyk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBjcmVhdGVMb2NhbE9yVVRDIChpbnB1dCwgZm9ybWF0LCBsb2NhbGUsIHN0cmljdCwgaXNVVEMpIHtcbiAgICB2YXIgYyA9IHt9O1xuXG4gICAgaWYgKGxvY2FsZSA9PT0gdHJ1ZSB8fCBsb2NhbGUgPT09IGZhbHNlKSB7XG4gICAgICAgIHN0cmljdCA9IGxvY2FsZTtcbiAgICAgICAgbG9jYWxlID0gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIGlmICgoaXNPYmplY3QoaW5wdXQpICYmIGlzT2JqZWN0RW1wdHkoaW5wdXQpKSB8fFxuICAgICAgICAgICAgKGlzQXJyYXkoaW5wdXQpICYmIGlucHV0Lmxlbmd0aCA9PT0gMCkpIHtcbiAgICAgICAgaW5wdXQgPSB1bmRlZmluZWQ7XG4gICAgfVxuICAgIC8vIG9iamVjdCBjb25zdHJ1Y3Rpb24gbXVzdCBiZSBkb25lIHRoaXMgd2F5LlxuICAgIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9tb21lbnQvbW9tZW50L2lzc3Vlcy8xNDIzXG4gICAgYy5faXNBTW9tZW50T2JqZWN0ID0gdHJ1ZTtcbiAgICBjLl91c2VVVEMgPSBjLl9pc1VUQyA9IGlzVVRDO1xuICAgIGMuX2wgPSBsb2NhbGU7XG4gICAgYy5faSA9IGlucHV0O1xuICAgIGMuX2YgPSBmb3JtYXQ7XG4gICAgYy5fc3RyaWN0ID0gc3RyaWN0O1xuXG4gICAgcmV0dXJuIGNyZWF0ZUZyb21Db25maWcoYyk7XG59XG5cbmZ1bmN0aW9uIGNyZWF0ZUxvY2FsIChpbnB1dCwgZm9ybWF0LCBsb2NhbGUsIHN0cmljdCkge1xuICAgIHJldHVybiBjcmVhdGVMb2NhbE9yVVRDKGlucHV0LCBmb3JtYXQsIGxvY2FsZSwgc3RyaWN0LCBmYWxzZSk7XG59XG5cbnZhciBwcm90b3R5cGVNaW4gPSBkZXByZWNhdGUoXG4gICAgJ21vbWVudCgpLm1pbiBpcyBkZXByZWNhdGVkLCB1c2UgbW9tZW50Lm1heCBpbnN0ZWFkLiBodHRwOi8vbW9tZW50anMuY29tL2d1aWRlcy8jL3dhcm5pbmdzL21pbi1tYXgvJyxcbiAgICBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBvdGhlciA9IGNyZWF0ZUxvY2FsLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7XG4gICAgICAgIGlmICh0aGlzLmlzVmFsaWQoKSAmJiBvdGhlci5pc1ZhbGlkKCkpIHtcbiAgICAgICAgICAgIHJldHVybiBvdGhlciA8IHRoaXMgPyB0aGlzIDogb3RoZXI7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gY3JlYXRlSW52YWxpZCgpO1xuICAgICAgICB9XG4gICAgfVxuKTtcblxudmFyIHByb3RvdHlwZU1heCA9IGRlcHJlY2F0ZShcbiAgICAnbW9tZW50KCkubWF4IGlzIGRlcHJlY2F0ZWQsIHVzZSBtb21lbnQubWluIGluc3RlYWQuIGh0dHA6Ly9tb21lbnRqcy5jb20vZ3VpZGVzLyMvd2FybmluZ3MvbWluLW1heC8nLFxuICAgIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIG90aGVyID0gY3JlYXRlTG9jYWwuYXBwbHkobnVsbCwgYXJndW1lbnRzKTtcbiAgICAgICAgaWYgKHRoaXMuaXNWYWxpZCgpICYmIG90aGVyLmlzVmFsaWQoKSkge1xuICAgICAgICAgICAgcmV0dXJuIG90aGVyID4gdGhpcyA/IHRoaXMgOiBvdGhlcjtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBjcmVhdGVJbnZhbGlkKCk7XG4gICAgICAgIH1cbiAgICB9XG4pO1xuXG4vLyBQaWNrIGEgbW9tZW50IG0gZnJvbSBtb21lbnRzIHNvIHRoYXQgbVtmbl0ob3RoZXIpIGlzIHRydWUgZm9yIGFsbFxuLy8gb3RoZXIuIFRoaXMgcmVsaWVzIG9uIHRoZSBmdW5jdGlvbiBmbiB0byBiZSB0cmFuc2l0aXZlLlxuLy9cbi8vIG1vbWVudHMgc2hvdWxkIGVpdGhlciBiZSBhbiBhcnJheSBvZiBtb21lbnQgb2JqZWN0cyBvciBhbiBhcnJheSwgd2hvc2Vcbi8vIGZpcnN0IGVsZW1lbnQgaXMgYW4gYXJyYXkgb2YgbW9tZW50IG9iamVjdHMuXG5mdW5jdGlvbiBwaWNrQnkoZm4sIG1vbWVudHMpIHtcbiAgICB2YXIgcmVzLCBpO1xuICAgIGlmIChtb21lbnRzLmxlbmd0aCA9PT0gMSAmJiBpc0FycmF5KG1vbWVudHNbMF0pKSB7XG4gICAgICAgIG1vbWVudHMgPSBtb21lbnRzWzBdO1xuICAgIH1cbiAgICBpZiAoIW1vbWVudHMubGVuZ3RoKSB7XG4gICAgICAgIHJldHVybiBjcmVhdGVMb2NhbCgpO1xuICAgIH1cbiAgICByZXMgPSBtb21lbnRzWzBdO1xuICAgIGZvciAoaSA9IDE7IGkgPCBtb21lbnRzLmxlbmd0aDsgKytpKSB7XG4gICAgICAgIGlmICghbW9tZW50c1tpXS5pc1ZhbGlkKCkgfHwgbW9tZW50c1tpXVtmbl0ocmVzKSkge1xuICAgICAgICAgICAgcmVzID0gbW9tZW50c1tpXTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcmVzO1xufVxuXG4vLyBUT0RPOiBVc2UgW10uc29ydCBpbnN0ZWFkP1xuZnVuY3Rpb24gbWluICgpIHtcbiAgICB2YXIgYXJncyA9IFtdLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAwKTtcblxuICAgIHJldHVybiBwaWNrQnkoJ2lzQmVmb3JlJywgYXJncyk7XG59XG5cbmZ1bmN0aW9uIG1heCAoKSB7XG4gICAgdmFyIGFyZ3MgPSBbXS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMCk7XG5cbiAgICByZXR1cm4gcGlja0J5KCdpc0FmdGVyJywgYXJncyk7XG59XG5cbnZhciBub3cgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIERhdGUubm93ID8gRGF0ZS5ub3coKSA6ICsobmV3IERhdGUoKSk7XG59O1xuXG52YXIgb3JkZXJpbmcgPSBbJ3llYXInLCAncXVhcnRlcicsICdtb250aCcsICd3ZWVrJywgJ2RheScsICdob3VyJywgJ21pbnV0ZScsICdzZWNvbmQnLCAnbWlsbGlzZWNvbmQnXTtcblxuZnVuY3Rpb24gaXNEdXJhdGlvblZhbGlkKG0pIHtcbiAgICBmb3IgKHZhciBrZXkgaW4gbSkge1xuICAgICAgICBpZiAoIShpbmRleE9mLmNhbGwob3JkZXJpbmcsIGtleSkgIT09IC0xICYmIChtW2tleV0gPT0gbnVsbCB8fCAhaXNOYU4obVtrZXldKSkpKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgdW5pdEhhc0RlY2ltYWwgPSBmYWxzZTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IG9yZGVyaW5nLmxlbmd0aDsgKytpKSB7XG4gICAgICAgIGlmIChtW29yZGVyaW5nW2ldXSkge1xuICAgICAgICAgICAgaWYgKHVuaXRIYXNEZWNpbWFsKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlOyAvLyBvbmx5IGFsbG93IG5vbi1pbnRlZ2VycyBmb3Igc21hbGxlc3QgdW5pdFxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHBhcnNlRmxvYXQobVtvcmRlcmluZ1tpXV0pICE9PSB0b0ludChtW29yZGVyaW5nW2ldXSkpIHtcbiAgICAgICAgICAgICAgICB1bml0SGFzRGVjaW1hbCA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZTtcbn1cblxuZnVuY3Rpb24gaXNWYWxpZCQxKCkge1xuICAgIHJldHVybiB0aGlzLl9pc1ZhbGlkO1xufVxuXG5mdW5jdGlvbiBjcmVhdGVJbnZhbGlkJDEoKSB7XG4gICAgcmV0dXJuIGNyZWF0ZUR1cmF0aW9uKE5hTik7XG59XG5cbmZ1bmN0aW9uIER1cmF0aW9uIChkdXJhdGlvbikge1xuICAgIHZhciBub3JtYWxpemVkSW5wdXQgPSBub3JtYWxpemVPYmplY3RVbml0cyhkdXJhdGlvbiksXG4gICAgICAgIHllYXJzID0gbm9ybWFsaXplZElucHV0LnllYXIgfHwgMCxcbiAgICAgICAgcXVhcnRlcnMgPSBub3JtYWxpemVkSW5wdXQucXVhcnRlciB8fCAwLFxuICAgICAgICBtb250aHMgPSBub3JtYWxpemVkSW5wdXQubW9udGggfHwgMCxcbiAgICAgICAgd2Vla3MgPSBub3JtYWxpemVkSW5wdXQud2VlayB8fCAwLFxuICAgICAgICBkYXlzID0gbm9ybWFsaXplZElucHV0LmRheSB8fCAwLFxuICAgICAgICBob3VycyA9IG5vcm1hbGl6ZWRJbnB1dC5ob3VyIHx8IDAsXG4gICAgICAgIG1pbnV0ZXMgPSBub3JtYWxpemVkSW5wdXQubWludXRlIHx8IDAsXG4gICAgICAgIHNlY29uZHMgPSBub3JtYWxpemVkSW5wdXQuc2Vjb25kIHx8IDAsXG4gICAgICAgIG1pbGxpc2Vjb25kcyA9IG5vcm1hbGl6ZWRJbnB1dC5taWxsaXNlY29uZCB8fCAwO1xuXG4gICAgdGhpcy5faXNWYWxpZCA9IGlzRHVyYXRpb25WYWxpZChub3JtYWxpemVkSW5wdXQpO1xuXG4gICAgLy8gcmVwcmVzZW50YXRpb24gZm9yIGRhdGVBZGRSZW1vdmVcbiAgICB0aGlzLl9taWxsaXNlY29uZHMgPSArbWlsbGlzZWNvbmRzICtcbiAgICAgICAgc2Vjb25kcyAqIDFlMyArIC8vIDEwMDBcbiAgICAgICAgbWludXRlcyAqIDZlNCArIC8vIDEwMDAgKiA2MFxuICAgICAgICBob3VycyAqIDEwMDAgKiA2MCAqIDYwOyAvL3VzaW5nIDEwMDAgKiA2MCAqIDYwIGluc3RlYWQgb2YgMzZlNSB0byBhdm9pZCBmbG9hdGluZyBwb2ludCByb3VuZGluZyBlcnJvcnMgaHR0cHM6Ly9naXRodWIuY29tL21vbWVudC9tb21lbnQvaXNzdWVzLzI5NzhcbiAgICAvLyBCZWNhdXNlIG9mIGRhdGVBZGRSZW1vdmUgdHJlYXRzIDI0IGhvdXJzIGFzIGRpZmZlcmVudCBmcm9tIGFcbiAgICAvLyBkYXkgd2hlbiB3b3JraW5nIGFyb3VuZCBEU1QsIHdlIG5lZWQgdG8gc3RvcmUgdGhlbSBzZXBhcmF0ZWx5XG4gICAgdGhpcy5fZGF5cyA9ICtkYXlzICtcbiAgICAgICAgd2Vla3MgKiA3O1xuICAgIC8vIEl0IGlzIGltcG9zc2libGUgdG8gdHJhbnNsYXRlIG1vbnRocyBpbnRvIGRheXMgd2l0aG91dCBrbm93aW5nXG4gICAgLy8gd2hpY2ggbW9udGhzIHlvdSBhcmUgYXJlIHRhbGtpbmcgYWJvdXQsIHNvIHdlIGhhdmUgdG8gc3RvcmVcbiAgICAvLyBpdCBzZXBhcmF0ZWx5LlxuICAgIHRoaXMuX21vbnRocyA9ICttb250aHMgK1xuICAgICAgICBxdWFydGVycyAqIDMgK1xuICAgICAgICB5ZWFycyAqIDEyO1xuXG4gICAgdGhpcy5fZGF0YSA9IHt9O1xuXG4gICAgdGhpcy5fbG9jYWxlID0gZ2V0TG9jYWxlKCk7XG5cbiAgICB0aGlzLl9idWJibGUoKTtcbn1cblxuZnVuY3Rpb24gaXNEdXJhdGlvbiAob2JqKSB7XG4gICAgcmV0dXJuIG9iaiBpbnN0YW5jZW9mIER1cmF0aW9uO1xufVxuXG5mdW5jdGlvbiBhYnNSb3VuZCAobnVtYmVyKSB7XG4gICAgaWYgKG51bWJlciA8IDApIHtcbiAgICAgICAgcmV0dXJuIE1hdGgucm91bmQoLTEgKiBudW1iZXIpICogLTE7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIE1hdGgucm91bmQobnVtYmVyKTtcbiAgICB9XG59XG5cbi8vIEZPUk1BVFRJTkdcblxuZnVuY3Rpb24gb2Zmc2V0ICh0b2tlbiwgc2VwYXJhdG9yKSB7XG4gICAgYWRkRm9ybWF0VG9rZW4odG9rZW4sIDAsIDAsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIG9mZnNldCA9IHRoaXMudXRjT2Zmc2V0KCk7XG4gICAgICAgIHZhciBzaWduID0gJysnO1xuICAgICAgICBpZiAob2Zmc2V0IDwgMCkge1xuICAgICAgICAgICAgb2Zmc2V0ID0gLW9mZnNldDtcbiAgICAgICAgICAgIHNpZ24gPSAnLSc7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHNpZ24gKyB6ZXJvRmlsbCh+fihvZmZzZXQgLyA2MCksIDIpICsgc2VwYXJhdG9yICsgemVyb0ZpbGwofn4ob2Zmc2V0KSAlIDYwLCAyKTtcbiAgICB9KTtcbn1cblxub2Zmc2V0KCdaJywgJzonKTtcbm9mZnNldCgnWlonLCAnJyk7XG5cbi8vIFBBUlNJTkdcblxuYWRkUmVnZXhUb2tlbignWicsICBtYXRjaFNob3J0T2Zmc2V0KTtcbmFkZFJlZ2V4VG9rZW4oJ1paJywgbWF0Y2hTaG9ydE9mZnNldCk7XG5hZGRQYXJzZVRva2VuKFsnWicsICdaWiddLCBmdW5jdGlvbiAoaW5wdXQsIGFycmF5LCBjb25maWcpIHtcbiAgICBjb25maWcuX3VzZVVUQyA9IHRydWU7XG4gICAgY29uZmlnLl90em0gPSBvZmZzZXRGcm9tU3RyaW5nKG1hdGNoU2hvcnRPZmZzZXQsIGlucHV0KTtcbn0pO1xuXG4vLyBIRUxQRVJTXG5cbi8vIHRpbWV6b25lIGNodW5rZXJcbi8vICcrMTA6MDAnID4gWycxMCcsICAnMDAnXVxuLy8gJy0xNTMwJyAgPiBbJy0xNScsICczMCddXG52YXIgY2h1bmtPZmZzZXQgPSAvKFtcXCtcXC1dfFxcZFxcZCkvZ2k7XG5cbmZ1bmN0aW9uIG9mZnNldEZyb21TdHJpbmcobWF0Y2hlciwgc3RyaW5nKSB7XG4gICAgdmFyIG1hdGNoZXMgPSAoc3RyaW5nIHx8ICcnKS5tYXRjaChtYXRjaGVyKTtcblxuICAgIGlmIChtYXRjaGVzID09PSBudWxsKSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHZhciBjaHVuayAgID0gbWF0Y2hlc1ttYXRjaGVzLmxlbmd0aCAtIDFdIHx8IFtdO1xuICAgIHZhciBwYXJ0cyAgID0gKGNodW5rICsgJycpLm1hdGNoKGNodW5rT2Zmc2V0KSB8fCBbJy0nLCAwLCAwXTtcbiAgICB2YXIgbWludXRlcyA9ICsocGFydHNbMV0gKiA2MCkgKyB0b0ludChwYXJ0c1syXSk7XG5cbiAgICByZXR1cm4gbWludXRlcyA9PT0gMCA/XG4gICAgICAwIDpcbiAgICAgIHBhcnRzWzBdID09PSAnKycgPyBtaW51dGVzIDogLW1pbnV0ZXM7XG59XG5cbi8vIFJldHVybiBhIG1vbWVudCBmcm9tIGlucHV0LCB0aGF0IGlzIGxvY2FsL3V0Yy96b25lIGVxdWl2YWxlbnQgdG8gbW9kZWwuXG5mdW5jdGlvbiBjbG9uZVdpdGhPZmZzZXQoaW5wdXQsIG1vZGVsKSB7XG4gICAgdmFyIHJlcywgZGlmZjtcbiAgICBpZiAobW9kZWwuX2lzVVRDKSB7XG4gICAgICAgIHJlcyA9IG1vZGVsLmNsb25lKCk7XG4gICAgICAgIGRpZmYgPSAoaXNNb21lbnQoaW5wdXQpIHx8IGlzRGF0ZShpbnB1dCkgPyBpbnB1dC52YWx1ZU9mKCkgOiBjcmVhdGVMb2NhbChpbnB1dCkudmFsdWVPZigpKSAtIHJlcy52YWx1ZU9mKCk7XG4gICAgICAgIC8vIFVzZSBsb3ctbGV2ZWwgYXBpLCBiZWNhdXNlIHRoaXMgZm4gaXMgbG93LWxldmVsIGFwaS5cbiAgICAgICAgcmVzLl9kLnNldFRpbWUocmVzLl9kLnZhbHVlT2YoKSArIGRpZmYpO1xuICAgICAgICBob29rcy51cGRhdGVPZmZzZXQocmVzLCBmYWxzZSk7XG4gICAgICAgIHJldHVybiByZXM7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIGNyZWF0ZUxvY2FsKGlucHV0KS5sb2NhbCgpO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gZ2V0RGF0ZU9mZnNldCAobSkge1xuICAgIC8vIE9uIEZpcmVmb3guMjQgRGF0ZSNnZXRUaW1lem9uZU9mZnNldCByZXR1cm5zIGEgZmxvYXRpbmcgcG9pbnQuXG4gICAgLy8gaHR0cHM6Ly9naXRodWIuY29tL21vbWVudC9tb21lbnQvcHVsbC8xODcxXG4gICAgcmV0dXJuIC1NYXRoLnJvdW5kKG0uX2QuZ2V0VGltZXpvbmVPZmZzZXQoKSAvIDE1KSAqIDE1O1xufVxuXG4vLyBIT09LU1xuXG4vLyBUaGlzIGZ1bmN0aW9uIHdpbGwgYmUgY2FsbGVkIHdoZW5ldmVyIGEgbW9tZW50IGlzIG11dGF0ZWQuXG4vLyBJdCBpcyBpbnRlbmRlZCB0byBrZWVwIHRoZSBvZmZzZXQgaW4gc3luYyB3aXRoIHRoZSB0aW1lem9uZS5cbmhvb2tzLnVwZGF0ZU9mZnNldCA9IGZ1bmN0aW9uICgpIHt9O1xuXG4vLyBNT01FTlRTXG5cbi8vIGtlZXBMb2NhbFRpbWUgPSB0cnVlIG1lYW5zIG9ubHkgY2hhbmdlIHRoZSB0aW1lem9uZSwgd2l0aG91dFxuLy8gYWZmZWN0aW5nIHRoZSBsb2NhbCBob3VyLiBTbyA1OjMxOjI2ICswMzAwIC0tW3V0Y09mZnNldCgyLCB0cnVlKV0tLT5cbi8vIDU6MzE6MjYgKzAyMDAgSXQgaXMgcG9zc2libGUgdGhhdCA1OjMxOjI2IGRvZXNuJ3QgZXhpc3Qgd2l0aCBvZmZzZXRcbi8vICswMjAwLCBzbyB3ZSBhZGp1c3QgdGhlIHRpbWUgYXMgbmVlZGVkLCB0byBiZSB2YWxpZC5cbi8vXG4vLyBLZWVwaW5nIHRoZSB0aW1lIGFjdHVhbGx5IGFkZHMvc3VidHJhY3RzIChvbmUgaG91cilcbi8vIGZyb20gdGhlIGFjdHVhbCByZXByZXNlbnRlZCB0aW1lLiBUaGF0IGlzIHdoeSB3ZSBjYWxsIHVwZGF0ZU9mZnNldFxuLy8gYSBzZWNvbmQgdGltZS4gSW4gY2FzZSBpdCB3YW50cyB1cyB0byBjaGFuZ2UgdGhlIG9mZnNldCBhZ2FpblxuLy8gX2NoYW5nZUluUHJvZ3Jlc3MgPT0gdHJ1ZSBjYXNlLCB0aGVuIHdlIGhhdmUgdG8gYWRqdXN0LCBiZWNhdXNlXG4vLyB0aGVyZSBpcyBubyBzdWNoIHRpbWUgaW4gdGhlIGdpdmVuIHRpbWV6b25lLlxuZnVuY3Rpb24gZ2V0U2V0T2Zmc2V0IChpbnB1dCwga2VlcExvY2FsVGltZSwga2VlcE1pbnV0ZXMpIHtcbiAgICB2YXIgb2Zmc2V0ID0gdGhpcy5fb2Zmc2V0IHx8IDAsXG4gICAgICAgIGxvY2FsQWRqdXN0O1xuICAgIGlmICghdGhpcy5pc1ZhbGlkKCkpIHtcbiAgICAgICAgcmV0dXJuIGlucHV0ICE9IG51bGwgPyB0aGlzIDogTmFOO1xuICAgIH1cbiAgICBpZiAoaW5wdXQgIT0gbnVsbCkge1xuICAgICAgICBpZiAodHlwZW9mIGlucHV0ID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgaW5wdXQgPSBvZmZzZXRGcm9tU3RyaW5nKG1hdGNoU2hvcnRPZmZzZXQsIGlucHV0KTtcbiAgICAgICAgICAgIGlmIChpbnB1dCA9PT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKE1hdGguYWJzKGlucHV0KSA8IDE2ICYmICFrZWVwTWludXRlcykge1xuICAgICAgICAgICAgaW5wdXQgPSBpbnB1dCAqIDYwO1xuICAgICAgICB9XG4gICAgICAgIGlmICghdGhpcy5faXNVVEMgJiYga2VlcExvY2FsVGltZSkge1xuICAgICAgICAgICAgbG9jYWxBZGp1c3QgPSBnZXREYXRlT2Zmc2V0KHRoaXMpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuX29mZnNldCA9IGlucHV0O1xuICAgICAgICB0aGlzLl9pc1VUQyA9IHRydWU7XG4gICAgICAgIGlmIChsb2NhbEFkanVzdCAhPSBudWxsKSB7XG4gICAgICAgICAgICB0aGlzLmFkZChsb2NhbEFkanVzdCwgJ20nKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAob2Zmc2V0ICE9PSBpbnB1dCkge1xuICAgICAgICAgICAgaWYgKCFrZWVwTG9jYWxUaW1lIHx8IHRoaXMuX2NoYW5nZUluUHJvZ3Jlc3MpIHtcbiAgICAgICAgICAgICAgICBhZGRTdWJ0cmFjdCh0aGlzLCBjcmVhdGVEdXJhdGlvbihpbnB1dCAtIG9mZnNldCwgJ20nKSwgMSwgZmFsc2UpO1xuICAgICAgICAgICAgfSBlbHNlIGlmICghdGhpcy5fY2hhbmdlSW5Qcm9ncmVzcykge1xuICAgICAgICAgICAgICAgIHRoaXMuX2NoYW5nZUluUHJvZ3Jlc3MgPSB0cnVlO1xuICAgICAgICAgICAgICAgIGhvb2tzLnVwZGF0ZU9mZnNldCh0aGlzLCB0cnVlKTtcbiAgICAgICAgICAgICAgICB0aGlzLl9jaGFuZ2VJblByb2dyZXNzID0gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gdGhpcy5faXNVVEMgPyBvZmZzZXQgOiBnZXREYXRlT2Zmc2V0KHRoaXMpO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gZ2V0U2V0Wm9uZSAoaW5wdXQsIGtlZXBMb2NhbFRpbWUpIHtcbiAgICBpZiAoaW5wdXQgIT0gbnVsbCkge1xuICAgICAgICBpZiAodHlwZW9mIGlucHV0ICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgaW5wdXQgPSAtaW5wdXQ7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnV0Y09mZnNldChpbnB1dCwga2VlcExvY2FsVGltZSk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIC10aGlzLnV0Y09mZnNldCgpO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gc2V0T2Zmc2V0VG9VVEMgKGtlZXBMb2NhbFRpbWUpIHtcbiAgICByZXR1cm4gdGhpcy51dGNPZmZzZXQoMCwga2VlcExvY2FsVGltZSk7XG59XG5cbmZ1bmN0aW9uIHNldE9mZnNldFRvTG9jYWwgKGtlZXBMb2NhbFRpbWUpIHtcbiAgICBpZiAodGhpcy5faXNVVEMpIHtcbiAgICAgICAgdGhpcy51dGNPZmZzZXQoMCwga2VlcExvY2FsVGltZSk7XG4gICAgICAgIHRoaXMuX2lzVVRDID0gZmFsc2U7XG5cbiAgICAgICAgaWYgKGtlZXBMb2NhbFRpbWUpIHtcbiAgICAgICAgICAgIHRoaXMuc3VidHJhY3QoZ2V0RGF0ZU9mZnNldCh0aGlzKSwgJ20nKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdGhpcztcbn1cblxuZnVuY3Rpb24gc2V0T2Zmc2V0VG9QYXJzZWRPZmZzZXQgKCkge1xuICAgIGlmICh0aGlzLl90em0gIT0gbnVsbCkge1xuICAgICAgICB0aGlzLnV0Y09mZnNldCh0aGlzLl90em0sIGZhbHNlLCB0cnVlKTtcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiB0aGlzLl9pID09PSAnc3RyaW5nJykge1xuICAgICAgICB2YXIgdFpvbmUgPSBvZmZzZXRGcm9tU3RyaW5nKG1hdGNoT2Zmc2V0LCB0aGlzLl9pKTtcbiAgICAgICAgaWYgKHRab25lICE9IG51bGwpIHtcbiAgICAgICAgICAgIHRoaXMudXRjT2Zmc2V0KHRab25lKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMudXRjT2Zmc2V0KDAsIHRydWUpO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiB0aGlzO1xufVxuXG5mdW5jdGlvbiBoYXNBbGlnbmVkSG91ck9mZnNldCAoaW5wdXQpIHtcbiAgICBpZiAoIXRoaXMuaXNWYWxpZCgpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgaW5wdXQgPSBpbnB1dCA/IGNyZWF0ZUxvY2FsKGlucHV0KS51dGNPZmZzZXQoKSA6IDA7XG5cbiAgICByZXR1cm4gKHRoaXMudXRjT2Zmc2V0KCkgLSBpbnB1dCkgJSA2MCA9PT0gMDtcbn1cblxuZnVuY3Rpb24gaXNEYXlsaWdodFNhdmluZ1RpbWUgKCkge1xuICAgIHJldHVybiAoXG4gICAgICAgIHRoaXMudXRjT2Zmc2V0KCkgPiB0aGlzLmNsb25lKCkubW9udGgoMCkudXRjT2Zmc2V0KCkgfHxcbiAgICAgICAgdGhpcy51dGNPZmZzZXQoKSA+IHRoaXMuY2xvbmUoKS5tb250aCg1KS51dGNPZmZzZXQoKVxuICAgICk7XG59XG5cbmZ1bmN0aW9uIGlzRGF5bGlnaHRTYXZpbmdUaW1lU2hpZnRlZCAoKSB7XG4gICAgaWYgKCFpc1VuZGVmaW5lZCh0aGlzLl9pc0RTVFNoaWZ0ZWQpKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9pc0RTVFNoaWZ0ZWQ7XG4gICAgfVxuXG4gICAgdmFyIGMgPSB7fTtcblxuICAgIGNvcHlDb25maWcoYywgdGhpcyk7XG4gICAgYyA9IHByZXBhcmVDb25maWcoYyk7XG5cbiAgICBpZiAoYy5fYSkge1xuICAgICAgICB2YXIgb3RoZXIgPSBjLl9pc1VUQyA/IGNyZWF0ZVVUQyhjLl9hKSA6IGNyZWF0ZUxvY2FsKGMuX2EpO1xuICAgICAgICB0aGlzLl9pc0RTVFNoaWZ0ZWQgPSB0aGlzLmlzVmFsaWQoKSAmJlxuICAgICAgICAgICAgY29tcGFyZUFycmF5cyhjLl9hLCBvdGhlci50b0FycmF5KCkpID4gMDtcbiAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLl9pc0RTVFNoaWZ0ZWQgPSBmYWxzZTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5faXNEU1RTaGlmdGVkO1xufVxuXG5mdW5jdGlvbiBpc0xvY2FsICgpIHtcbiAgICByZXR1cm4gdGhpcy5pc1ZhbGlkKCkgPyAhdGhpcy5faXNVVEMgOiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gaXNVdGNPZmZzZXQgKCkge1xuICAgIHJldHVybiB0aGlzLmlzVmFsaWQoKSA/IHRoaXMuX2lzVVRDIDogZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGlzVXRjICgpIHtcbiAgICByZXR1cm4gdGhpcy5pc1ZhbGlkKCkgPyB0aGlzLl9pc1VUQyAmJiB0aGlzLl9vZmZzZXQgPT09IDAgOiBmYWxzZTtcbn1cblxuLy8gQVNQLk5FVCBqc29uIGRhdGUgZm9ybWF0IHJlZ2V4XG52YXIgYXNwTmV0UmVnZXggPSAvXihcXC18XFwrKT8oPzooXFxkKilbLiBdKT8oXFxkKylcXDooXFxkKykoPzpcXDooXFxkKykoXFwuXFxkKik/KT8kLztcblxuLy8gZnJvbSBodHRwOi8vZG9jcy5jbG9zdXJlLWxpYnJhcnkuZ29vZ2xlY29kZS5jb20vZ2l0L2Nsb3N1cmVfZ29vZ19kYXRlX2RhdGUuanMuc291cmNlLmh0bWxcbi8vIHNvbWV3aGF0IG1vcmUgaW4gbGluZSB3aXRoIDQuNC4zLjIgMjAwNCBzcGVjLCBidXQgYWxsb3dzIGRlY2ltYWwgYW55d2hlcmVcbi8vIGFuZCBmdXJ0aGVyIG1vZGlmaWVkIHRvIGFsbG93IGZvciBzdHJpbmdzIGNvbnRhaW5pbmcgYm90aCB3ZWVrIGFuZCBkYXlcbnZhciBpc29SZWdleCA9IC9eKC18XFwrKT9QKD86KFstK10/WzAtOSwuXSopWSk/KD86KFstK10/WzAtOSwuXSopTSk/KD86KFstK10/WzAtOSwuXSopVyk/KD86KFstK10/WzAtOSwuXSopRCk/KD86VCg/OihbLStdP1swLTksLl0qKUgpPyg/OihbLStdP1swLTksLl0qKU0pPyg/OihbLStdP1swLTksLl0qKVMpPyk/JC87XG5cbmZ1bmN0aW9uIGNyZWF0ZUR1cmF0aW9uIChpbnB1dCwga2V5KSB7XG4gICAgdmFyIGR1cmF0aW9uID0gaW5wdXQsXG4gICAgICAgIC8vIG1hdGNoaW5nIGFnYWluc3QgcmVnZXhwIGlzIGV4cGVuc2l2ZSwgZG8gaXQgb24gZGVtYW5kXG4gICAgICAgIG1hdGNoID0gbnVsbCxcbiAgICAgICAgc2lnbixcbiAgICAgICAgcmV0LFxuICAgICAgICBkaWZmUmVzO1xuXG4gICAgaWYgKGlzRHVyYXRpb24oaW5wdXQpKSB7XG4gICAgICAgIGR1cmF0aW9uID0ge1xuICAgICAgICAgICAgbXMgOiBpbnB1dC5fbWlsbGlzZWNvbmRzLFxuICAgICAgICAgICAgZCAgOiBpbnB1dC5fZGF5cyxcbiAgICAgICAgICAgIE0gIDogaW5wdXQuX21vbnRoc1xuICAgICAgICB9O1xuICAgIH0gZWxzZSBpZiAoaXNOdW1iZXIoaW5wdXQpKSB7XG4gICAgICAgIGR1cmF0aW9uID0ge307XG4gICAgICAgIGlmIChrZXkpIHtcbiAgICAgICAgICAgIGR1cmF0aW9uW2tleV0gPSBpbnB1dDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGR1cmF0aW9uLm1pbGxpc2Vjb25kcyA9IGlucHV0O1xuICAgICAgICB9XG4gICAgfSBlbHNlIGlmICghIShtYXRjaCA9IGFzcE5ldFJlZ2V4LmV4ZWMoaW5wdXQpKSkge1xuICAgICAgICBzaWduID0gKG1hdGNoWzFdID09PSAnLScpID8gLTEgOiAxO1xuICAgICAgICBkdXJhdGlvbiA9IHtcbiAgICAgICAgICAgIHkgIDogMCxcbiAgICAgICAgICAgIGQgIDogdG9JbnQobWF0Y2hbREFURV0pICAgICAgICAgICAgICAgICAgICAgICAgICogc2lnbixcbiAgICAgICAgICAgIGggIDogdG9JbnQobWF0Y2hbSE9VUl0pICAgICAgICAgICAgICAgICAgICAgICAgICogc2lnbixcbiAgICAgICAgICAgIG0gIDogdG9JbnQobWF0Y2hbTUlOVVRFXSkgICAgICAgICAgICAgICAgICAgICAgICogc2lnbixcbiAgICAgICAgICAgIHMgIDogdG9JbnQobWF0Y2hbU0VDT05EXSkgICAgICAgICAgICAgICAgICAgICAgICogc2lnbixcbiAgICAgICAgICAgIG1zIDogdG9JbnQoYWJzUm91bmQobWF0Y2hbTUlMTElTRUNPTkRdICogMTAwMCkpICogc2lnbiAvLyB0aGUgbWlsbGlzZWNvbmQgZGVjaW1hbCBwb2ludCBpcyBpbmNsdWRlZCBpbiB0aGUgbWF0Y2hcbiAgICAgICAgfTtcbiAgICB9IGVsc2UgaWYgKCEhKG1hdGNoID0gaXNvUmVnZXguZXhlYyhpbnB1dCkpKSB7XG4gICAgICAgIHNpZ24gPSAobWF0Y2hbMV0gPT09ICctJykgPyAtMSA6IChtYXRjaFsxXSA9PT0gJysnKSA/IDEgOiAxO1xuICAgICAgICBkdXJhdGlvbiA9IHtcbiAgICAgICAgICAgIHkgOiBwYXJzZUlzbyhtYXRjaFsyXSwgc2lnbiksXG4gICAgICAgICAgICBNIDogcGFyc2VJc28obWF0Y2hbM10sIHNpZ24pLFxuICAgICAgICAgICAgdyA6IHBhcnNlSXNvKG1hdGNoWzRdLCBzaWduKSxcbiAgICAgICAgICAgIGQgOiBwYXJzZUlzbyhtYXRjaFs1XSwgc2lnbiksXG4gICAgICAgICAgICBoIDogcGFyc2VJc28obWF0Y2hbNl0sIHNpZ24pLFxuICAgICAgICAgICAgbSA6IHBhcnNlSXNvKG1hdGNoWzddLCBzaWduKSxcbiAgICAgICAgICAgIHMgOiBwYXJzZUlzbyhtYXRjaFs4XSwgc2lnbilcbiAgICAgICAgfTtcbiAgICB9IGVsc2UgaWYgKGR1cmF0aW9uID09IG51bGwpIHsvLyBjaGVja3MgZm9yIG51bGwgb3IgdW5kZWZpbmVkXG4gICAgICAgIGR1cmF0aW9uID0ge307XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgZHVyYXRpb24gPT09ICdvYmplY3QnICYmICgnZnJvbScgaW4gZHVyYXRpb24gfHwgJ3RvJyBpbiBkdXJhdGlvbikpIHtcbiAgICAgICAgZGlmZlJlcyA9IG1vbWVudHNEaWZmZXJlbmNlKGNyZWF0ZUxvY2FsKGR1cmF0aW9uLmZyb20pLCBjcmVhdGVMb2NhbChkdXJhdGlvbi50bykpO1xuXG4gICAgICAgIGR1cmF0aW9uID0ge307XG4gICAgICAgIGR1cmF0aW9uLm1zID0gZGlmZlJlcy5taWxsaXNlY29uZHM7XG4gICAgICAgIGR1cmF0aW9uLk0gPSBkaWZmUmVzLm1vbnRocztcbiAgICB9XG5cbiAgICByZXQgPSBuZXcgRHVyYXRpb24oZHVyYXRpb24pO1xuXG4gICAgaWYgKGlzRHVyYXRpb24oaW5wdXQpICYmIGhhc093blByb3AoaW5wdXQsICdfbG9jYWxlJykpIHtcbiAgICAgICAgcmV0Ll9sb2NhbGUgPSBpbnB1dC5fbG9jYWxlO1xuICAgIH1cblxuICAgIHJldHVybiByZXQ7XG59XG5cbmNyZWF0ZUR1cmF0aW9uLmZuID0gRHVyYXRpb24ucHJvdG90eXBlO1xuY3JlYXRlRHVyYXRpb24uaW52YWxpZCA9IGNyZWF0ZUludmFsaWQkMTtcblxuZnVuY3Rpb24gcGFyc2VJc28gKGlucCwgc2lnbikge1xuICAgIC8vIFdlJ2Qgbm9ybWFsbHkgdXNlIH5+aW5wIGZvciB0aGlzLCBidXQgdW5mb3J0dW5hdGVseSBpdCBhbHNvXG4gICAgLy8gY29udmVydHMgZmxvYXRzIHRvIGludHMuXG4gICAgLy8gaW5wIG1heSBiZSB1bmRlZmluZWQsIHNvIGNhcmVmdWwgY2FsbGluZyByZXBsYWNlIG9uIGl0LlxuICAgIHZhciByZXMgPSBpbnAgJiYgcGFyc2VGbG9hdChpbnAucmVwbGFjZSgnLCcsICcuJykpO1xuICAgIC8vIGFwcGx5IHNpZ24gd2hpbGUgd2UncmUgYXQgaXRcbiAgICByZXR1cm4gKGlzTmFOKHJlcykgPyAwIDogcmVzKSAqIHNpZ247XG59XG5cbmZ1bmN0aW9uIHBvc2l0aXZlTW9tZW50c0RpZmZlcmVuY2UoYmFzZSwgb3RoZXIpIHtcbiAgICB2YXIgcmVzID0ge21pbGxpc2Vjb25kczogMCwgbW9udGhzOiAwfTtcblxuICAgIHJlcy5tb250aHMgPSBvdGhlci5tb250aCgpIC0gYmFzZS5tb250aCgpICtcbiAgICAgICAgKG90aGVyLnllYXIoKSAtIGJhc2UueWVhcigpKSAqIDEyO1xuICAgIGlmIChiYXNlLmNsb25lKCkuYWRkKHJlcy5tb250aHMsICdNJykuaXNBZnRlcihvdGhlcikpIHtcbiAgICAgICAgLS1yZXMubW9udGhzO1xuICAgIH1cblxuICAgIHJlcy5taWxsaXNlY29uZHMgPSArb3RoZXIgLSArKGJhc2UuY2xvbmUoKS5hZGQocmVzLm1vbnRocywgJ00nKSk7XG5cbiAgICByZXR1cm4gcmVzO1xufVxuXG5mdW5jdGlvbiBtb21lbnRzRGlmZmVyZW5jZShiYXNlLCBvdGhlcikge1xuICAgIHZhciByZXM7XG4gICAgaWYgKCEoYmFzZS5pc1ZhbGlkKCkgJiYgb3RoZXIuaXNWYWxpZCgpKSkge1xuICAgICAgICByZXR1cm4ge21pbGxpc2Vjb25kczogMCwgbW9udGhzOiAwfTtcbiAgICB9XG5cbiAgICBvdGhlciA9IGNsb25lV2l0aE9mZnNldChvdGhlciwgYmFzZSk7XG4gICAgaWYgKGJhc2UuaXNCZWZvcmUob3RoZXIpKSB7XG4gICAgICAgIHJlcyA9IHBvc2l0aXZlTW9tZW50c0RpZmZlcmVuY2UoYmFzZSwgb3RoZXIpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHJlcyA9IHBvc2l0aXZlTW9tZW50c0RpZmZlcmVuY2Uob3RoZXIsIGJhc2UpO1xuICAgICAgICByZXMubWlsbGlzZWNvbmRzID0gLXJlcy5taWxsaXNlY29uZHM7XG4gICAgICAgIHJlcy5tb250aHMgPSAtcmVzLm1vbnRocztcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzO1xufVxuXG4vLyBUT0RPOiByZW1vdmUgJ25hbWUnIGFyZyBhZnRlciBkZXByZWNhdGlvbiBpcyByZW1vdmVkXG5mdW5jdGlvbiBjcmVhdGVBZGRlcihkaXJlY3Rpb24sIG5hbWUpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24gKHZhbCwgcGVyaW9kKSB7XG4gICAgICAgIHZhciBkdXIsIHRtcDtcbiAgICAgICAgLy9pbnZlcnQgdGhlIGFyZ3VtZW50cywgYnV0IGNvbXBsYWluIGFib3V0IGl0XG4gICAgICAgIGlmIChwZXJpb2QgIT09IG51bGwgJiYgIWlzTmFOKCtwZXJpb2QpKSB7XG4gICAgICAgICAgICBkZXByZWNhdGVTaW1wbGUobmFtZSwgJ21vbWVudCgpLicgKyBuYW1lICArICcocGVyaW9kLCBudW1iZXIpIGlzIGRlcHJlY2F0ZWQuIFBsZWFzZSB1c2UgbW9tZW50KCkuJyArIG5hbWUgKyAnKG51bWJlciwgcGVyaW9kKS4gJyArXG4gICAgICAgICAgICAnU2VlIGh0dHA6Ly9tb21lbnRqcy5jb20vZ3VpZGVzLyMvd2FybmluZ3MvYWRkLWludmVydGVkLXBhcmFtLyBmb3IgbW9yZSBpbmZvLicpO1xuICAgICAgICAgICAgdG1wID0gdmFsOyB2YWwgPSBwZXJpb2Q7IHBlcmlvZCA9IHRtcDtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhbCA9IHR5cGVvZiB2YWwgPT09ICdzdHJpbmcnID8gK3ZhbCA6IHZhbDtcbiAgICAgICAgZHVyID0gY3JlYXRlRHVyYXRpb24odmFsLCBwZXJpb2QpO1xuICAgICAgICBhZGRTdWJ0cmFjdCh0aGlzLCBkdXIsIGRpcmVjdGlvbik7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG59XG5cbmZ1bmN0aW9uIGFkZFN1YnRyYWN0IChtb20sIGR1cmF0aW9uLCBpc0FkZGluZywgdXBkYXRlT2Zmc2V0KSB7XG4gICAgdmFyIG1pbGxpc2Vjb25kcyA9IGR1cmF0aW9uLl9taWxsaXNlY29uZHMsXG4gICAgICAgIGRheXMgPSBhYnNSb3VuZChkdXJhdGlvbi5fZGF5cyksXG4gICAgICAgIG1vbnRocyA9IGFic1JvdW5kKGR1cmF0aW9uLl9tb250aHMpO1xuXG4gICAgaWYgKCFtb20uaXNWYWxpZCgpKSB7XG4gICAgICAgIC8vIE5vIG9wXG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB1cGRhdGVPZmZzZXQgPSB1cGRhdGVPZmZzZXQgPT0gbnVsbCA/IHRydWUgOiB1cGRhdGVPZmZzZXQ7XG5cbiAgICBpZiAobW9udGhzKSB7XG4gICAgICAgIHNldE1vbnRoKG1vbSwgZ2V0KG1vbSwgJ01vbnRoJykgKyBtb250aHMgKiBpc0FkZGluZyk7XG4gICAgfVxuICAgIGlmIChkYXlzKSB7XG4gICAgICAgIHNldCQxKG1vbSwgJ0RhdGUnLCBnZXQobW9tLCAnRGF0ZScpICsgZGF5cyAqIGlzQWRkaW5nKTtcbiAgICB9XG4gICAgaWYgKG1pbGxpc2Vjb25kcykge1xuICAgICAgICBtb20uX2Quc2V0VGltZShtb20uX2QudmFsdWVPZigpICsgbWlsbGlzZWNvbmRzICogaXNBZGRpbmcpO1xuICAgIH1cbiAgICBpZiAodXBkYXRlT2Zmc2V0KSB7XG4gICAgICAgIGhvb2tzLnVwZGF0ZU9mZnNldChtb20sIGRheXMgfHwgbW9udGhzKTtcbiAgICB9XG59XG5cbnZhciBhZGQgICAgICA9IGNyZWF0ZUFkZGVyKDEsICdhZGQnKTtcbnZhciBzdWJ0cmFjdCA9IGNyZWF0ZUFkZGVyKC0xLCAnc3VidHJhY3QnKTtcblxuZnVuY3Rpb24gZ2V0Q2FsZW5kYXJGb3JtYXQobXlNb21lbnQsIG5vdykge1xuICAgIHZhciBkaWZmID0gbXlNb21lbnQuZGlmZihub3csICdkYXlzJywgdHJ1ZSk7XG4gICAgcmV0dXJuIGRpZmYgPCAtNiA/ICdzYW1lRWxzZScgOlxuICAgICAgICAgICAgZGlmZiA8IC0xID8gJ2xhc3RXZWVrJyA6XG4gICAgICAgICAgICBkaWZmIDwgMCA/ICdsYXN0RGF5JyA6XG4gICAgICAgICAgICBkaWZmIDwgMSA/ICdzYW1lRGF5JyA6XG4gICAgICAgICAgICBkaWZmIDwgMiA/ICduZXh0RGF5JyA6XG4gICAgICAgICAgICBkaWZmIDwgNyA/ICduZXh0V2VlaycgOiAnc2FtZUVsc2UnO1xufVxuXG5mdW5jdGlvbiBjYWxlbmRhciQxICh0aW1lLCBmb3JtYXRzKSB7XG4gICAgLy8gV2Ugd2FudCB0byBjb21wYXJlIHRoZSBzdGFydCBvZiB0b2RheSwgdnMgdGhpcy5cbiAgICAvLyBHZXR0aW5nIHN0YXJ0LW9mLXRvZGF5IGRlcGVuZHMgb24gd2hldGhlciB3ZSdyZSBsb2NhbC91dGMvb2Zmc2V0IG9yIG5vdC5cbiAgICB2YXIgbm93ID0gdGltZSB8fCBjcmVhdGVMb2NhbCgpLFxuICAgICAgICBzb2QgPSBjbG9uZVdpdGhPZmZzZXQobm93LCB0aGlzKS5zdGFydE9mKCdkYXknKSxcbiAgICAgICAgZm9ybWF0ID0gaG9va3MuY2FsZW5kYXJGb3JtYXQodGhpcywgc29kKSB8fCAnc2FtZUVsc2UnO1xuXG4gICAgdmFyIG91dHB1dCA9IGZvcm1hdHMgJiYgKGlzRnVuY3Rpb24oZm9ybWF0c1tmb3JtYXRdKSA/IGZvcm1hdHNbZm9ybWF0XS5jYWxsKHRoaXMsIG5vdykgOiBmb3JtYXRzW2Zvcm1hdF0pO1xuXG4gICAgcmV0dXJuIHRoaXMuZm9ybWF0KG91dHB1dCB8fCB0aGlzLmxvY2FsZURhdGEoKS5jYWxlbmRhcihmb3JtYXQsIHRoaXMsIGNyZWF0ZUxvY2FsKG5vdykpKTtcbn1cblxuZnVuY3Rpb24gY2xvbmUgKCkge1xuICAgIHJldHVybiBuZXcgTW9tZW50KHRoaXMpO1xufVxuXG5mdW5jdGlvbiBpc0FmdGVyIChpbnB1dCwgdW5pdHMpIHtcbiAgICB2YXIgbG9jYWxJbnB1dCA9IGlzTW9tZW50KGlucHV0KSA/IGlucHV0IDogY3JlYXRlTG9jYWwoaW5wdXQpO1xuICAgIGlmICghKHRoaXMuaXNWYWxpZCgpICYmIGxvY2FsSW5wdXQuaXNWYWxpZCgpKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHVuaXRzID0gbm9ybWFsaXplVW5pdHMoIWlzVW5kZWZpbmVkKHVuaXRzKSA/IHVuaXRzIDogJ21pbGxpc2Vjb25kJyk7XG4gICAgaWYgKHVuaXRzID09PSAnbWlsbGlzZWNvbmQnKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnZhbHVlT2YoKSA+IGxvY2FsSW5wdXQudmFsdWVPZigpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBsb2NhbElucHV0LnZhbHVlT2YoKSA8IHRoaXMuY2xvbmUoKS5zdGFydE9mKHVuaXRzKS52YWx1ZU9mKCk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBpc0JlZm9yZSAoaW5wdXQsIHVuaXRzKSB7XG4gICAgdmFyIGxvY2FsSW5wdXQgPSBpc01vbWVudChpbnB1dCkgPyBpbnB1dCA6IGNyZWF0ZUxvY2FsKGlucHV0KTtcbiAgICBpZiAoISh0aGlzLmlzVmFsaWQoKSAmJiBsb2NhbElucHV0LmlzVmFsaWQoKSkpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICB1bml0cyA9IG5vcm1hbGl6ZVVuaXRzKCFpc1VuZGVmaW5lZCh1bml0cykgPyB1bml0cyA6ICdtaWxsaXNlY29uZCcpO1xuICAgIGlmICh1bml0cyA9PT0gJ21pbGxpc2Vjb25kJykge1xuICAgICAgICByZXR1cm4gdGhpcy52YWx1ZU9mKCkgPCBsb2NhbElucHV0LnZhbHVlT2YoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gdGhpcy5jbG9uZSgpLmVuZE9mKHVuaXRzKS52YWx1ZU9mKCkgPCBsb2NhbElucHV0LnZhbHVlT2YoKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGlzQmV0d2VlbiAoZnJvbSwgdG8sIHVuaXRzLCBpbmNsdXNpdml0eSkge1xuICAgIGluY2x1c2l2aXR5ID0gaW5jbHVzaXZpdHkgfHwgJygpJztcbiAgICByZXR1cm4gKGluY2x1c2l2aXR5WzBdID09PSAnKCcgPyB0aGlzLmlzQWZ0ZXIoZnJvbSwgdW5pdHMpIDogIXRoaXMuaXNCZWZvcmUoZnJvbSwgdW5pdHMpKSAmJlxuICAgICAgICAoaW5jbHVzaXZpdHlbMV0gPT09ICcpJyA/IHRoaXMuaXNCZWZvcmUodG8sIHVuaXRzKSA6ICF0aGlzLmlzQWZ0ZXIodG8sIHVuaXRzKSk7XG59XG5cbmZ1bmN0aW9uIGlzU2FtZSAoaW5wdXQsIHVuaXRzKSB7XG4gICAgdmFyIGxvY2FsSW5wdXQgPSBpc01vbWVudChpbnB1dCkgPyBpbnB1dCA6IGNyZWF0ZUxvY2FsKGlucHV0KSxcbiAgICAgICAgaW5wdXRNcztcbiAgICBpZiAoISh0aGlzLmlzVmFsaWQoKSAmJiBsb2NhbElucHV0LmlzVmFsaWQoKSkpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICB1bml0cyA9IG5vcm1hbGl6ZVVuaXRzKHVuaXRzIHx8ICdtaWxsaXNlY29uZCcpO1xuICAgIGlmICh1bml0cyA9PT0gJ21pbGxpc2Vjb25kJykge1xuICAgICAgICByZXR1cm4gdGhpcy52YWx1ZU9mKCkgPT09IGxvY2FsSW5wdXQudmFsdWVPZigpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGlucHV0TXMgPSBsb2NhbElucHV0LnZhbHVlT2YoKTtcbiAgICAgICAgcmV0dXJuIHRoaXMuY2xvbmUoKS5zdGFydE9mKHVuaXRzKS52YWx1ZU9mKCkgPD0gaW5wdXRNcyAmJiBpbnB1dE1zIDw9IHRoaXMuY2xvbmUoKS5lbmRPZih1bml0cykudmFsdWVPZigpO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gaXNTYW1lT3JBZnRlciAoaW5wdXQsIHVuaXRzKSB7XG4gICAgcmV0dXJuIHRoaXMuaXNTYW1lKGlucHV0LCB1bml0cykgfHwgdGhpcy5pc0FmdGVyKGlucHV0LHVuaXRzKTtcbn1cblxuZnVuY3Rpb24gaXNTYW1lT3JCZWZvcmUgKGlucHV0LCB1bml0cykge1xuICAgIHJldHVybiB0aGlzLmlzU2FtZShpbnB1dCwgdW5pdHMpIHx8IHRoaXMuaXNCZWZvcmUoaW5wdXQsdW5pdHMpO1xufVxuXG5mdW5jdGlvbiBkaWZmIChpbnB1dCwgdW5pdHMsIGFzRmxvYXQpIHtcbiAgICB2YXIgdGhhdCxcbiAgICAgICAgem9uZURlbHRhLFxuICAgICAgICBkZWx0YSwgb3V0cHV0O1xuXG4gICAgaWYgKCF0aGlzLmlzVmFsaWQoKSkge1xuICAgICAgICByZXR1cm4gTmFOO1xuICAgIH1cblxuICAgIHRoYXQgPSBjbG9uZVdpdGhPZmZzZXQoaW5wdXQsIHRoaXMpO1xuXG4gICAgaWYgKCF0aGF0LmlzVmFsaWQoKSkge1xuICAgICAgICByZXR1cm4gTmFOO1xuICAgIH1cblxuICAgIHpvbmVEZWx0YSA9ICh0aGF0LnV0Y09mZnNldCgpIC0gdGhpcy51dGNPZmZzZXQoKSkgKiA2ZTQ7XG5cbiAgICB1bml0cyA9IG5vcm1hbGl6ZVVuaXRzKHVuaXRzKTtcblxuICAgIHN3aXRjaCAodW5pdHMpIHtcbiAgICAgICAgY2FzZSAneWVhcic6IG91dHB1dCA9IG1vbnRoRGlmZih0aGlzLCB0aGF0KSAvIDEyOyBicmVhaztcbiAgICAgICAgY2FzZSAnbW9udGgnOiBvdXRwdXQgPSBtb250aERpZmYodGhpcywgdGhhdCk7IGJyZWFrO1xuICAgICAgICBjYXNlICdxdWFydGVyJzogb3V0cHV0ID0gbW9udGhEaWZmKHRoaXMsIHRoYXQpIC8gMzsgYnJlYWs7XG4gICAgICAgIGNhc2UgJ3NlY29uZCc6IG91dHB1dCA9ICh0aGlzIC0gdGhhdCkgLyAxZTM7IGJyZWFrOyAvLyAxMDAwXG4gICAgICAgIGNhc2UgJ21pbnV0ZSc6IG91dHB1dCA9ICh0aGlzIC0gdGhhdCkgLyA2ZTQ7IGJyZWFrOyAvLyAxMDAwICogNjBcbiAgICAgICAgY2FzZSAnaG91cic6IG91dHB1dCA9ICh0aGlzIC0gdGhhdCkgLyAzNmU1OyBicmVhazsgLy8gMTAwMCAqIDYwICogNjBcbiAgICAgICAgY2FzZSAnZGF5Jzogb3V0cHV0ID0gKHRoaXMgLSB0aGF0IC0gem9uZURlbHRhKSAvIDg2NGU1OyBicmVhazsgLy8gMTAwMCAqIDYwICogNjAgKiAyNCwgbmVnYXRlIGRzdFxuICAgICAgICBjYXNlICd3ZWVrJzogb3V0cHV0ID0gKHRoaXMgLSB0aGF0IC0gem9uZURlbHRhKSAvIDYwNDhlNTsgYnJlYWs7IC8vIDEwMDAgKiA2MCAqIDYwICogMjQgKiA3LCBuZWdhdGUgZHN0XG4gICAgICAgIGRlZmF1bHQ6IG91dHB1dCA9IHRoaXMgLSB0aGF0O1xuICAgIH1cblxuICAgIHJldHVybiBhc0Zsb2F0ID8gb3V0cHV0IDogYWJzRmxvb3Iob3V0cHV0KTtcbn1cblxuZnVuY3Rpb24gbW9udGhEaWZmIChhLCBiKSB7XG4gICAgLy8gZGlmZmVyZW5jZSBpbiBtb250aHNcbiAgICB2YXIgd2hvbGVNb250aERpZmYgPSAoKGIueWVhcigpIC0gYS55ZWFyKCkpICogMTIpICsgKGIubW9udGgoKSAtIGEubW9udGgoKSksXG4gICAgICAgIC8vIGIgaXMgaW4gKGFuY2hvciAtIDEgbW9udGgsIGFuY2hvciArIDEgbW9udGgpXG4gICAgICAgIGFuY2hvciA9IGEuY2xvbmUoKS5hZGQod2hvbGVNb250aERpZmYsICdtb250aHMnKSxcbiAgICAgICAgYW5jaG9yMiwgYWRqdXN0O1xuXG4gICAgaWYgKGIgLSBhbmNob3IgPCAwKSB7XG4gICAgICAgIGFuY2hvcjIgPSBhLmNsb25lKCkuYWRkKHdob2xlTW9udGhEaWZmIC0gMSwgJ21vbnRocycpO1xuICAgICAgICAvLyBsaW5lYXIgYWNyb3NzIHRoZSBtb250aFxuICAgICAgICBhZGp1c3QgPSAoYiAtIGFuY2hvcikgLyAoYW5jaG9yIC0gYW5jaG9yMik7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgYW5jaG9yMiA9IGEuY2xvbmUoKS5hZGQod2hvbGVNb250aERpZmYgKyAxLCAnbW9udGhzJyk7XG4gICAgICAgIC8vIGxpbmVhciBhY3Jvc3MgdGhlIG1vbnRoXG4gICAgICAgIGFkanVzdCA9IChiIC0gYW5jaG9yKSAvIChhbmNob3IyIC0gYW5jaG9yKTtcbiAgICB9XG5cbiAgICAvL2NoZWNrIGZvciBuZWdhdGl2ZSB6ZXJvLCByZXR1cm4gemVybyBpZiBuZWdhdGl2ZSB6ZXJvXG4gICAgcmV0dXJuIC0od2hvbGVNb250aERpZmYgKyBhZGp1c3QpIHx8IDA7XG59XG5cbmhvb2tzLmRlZmF1bHRGb3JtYXQgPSAnWVlZWS1NTS1ERFRISDptbTpzc1onO1xuaG9va3MuZGVmYXVsdEZvcm1hdFV0YyA9ICdZWVlZLU1NLUREVEhIOm1tOnNzW1pdJztcblxuZnVuY3Rpb24gdG9TdHJpbmcgKCkge1xuICAgIHJldHVybiB0aGlzLmNsb25lKCkubG9jYWxlKCdlbicpLmZvcm1hdCgnZGRkIE1NTSBERCBZWVlZIEhIOm1tOnNzIFtHTVRdWlonKTtcbn1cblxuZnVuY3Rpb24gdG9JU09TdHJpbmcoa2VlcE9mZnNldCkge1xuICAgIGlmICghdGhpcy5pc1ZhbGlkKCkpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIHZhciB1dGMgPSBrZWVwT2Zmc2V0ICE9PSB0cnVlO1xuICAgIHZhciBtID0gdXRjID8gdGhpcy5jbG9uZSgpLnV0YygpIDogdGhpcztcbiAgICBpZiAobS55ZWFyKCkgPCAwIHx8IG0ueWVhcigpID4gOTk5OSkge1xuICAgICAgICByZXR1cm4gZm9ybWF0TW9tZW50KG0sIHV0YyA/ICdZWVlZWVktTU0tRERbVF1ISDptbTpzcy5TU1NbWl0nIDogJ1lZWVlZWS1NTS1ERFtUXUhIOm1tOnNzLlNTU1onKTtcbiAgICB9XG4gICAgaWYgKGlzRnVuY3Rpb24oRGF0ZS5wcm90b3R5cGUudG9JU09TdHJpbmcpKSB7XG4gICAgICAgIC8vIG5hdGl2ZSBpbXBsZW1lbnRhdGlvbiBpcyB+NTB4IGZhc3RlciwgdXNlIGl0IHdoZW4gd2UgY2FuXG4gICAgICAgIGlmICh1dGMpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnRvRGF0ZSgpLnRvSVNPU3RyaW5nKCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gbmV3IERhdGUodGhpcy5fZC52YWx1ZU9mKCkpLnRvSVNPU3RyaW5nKCkucmVwbGFjZSgnWicsIGZvcm1hdE1vbWVudChtLCAnWicpKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZm9ybWF0TW9tZW50KG0sIHV0YyA/ICdZWVlZLU1NLUREW1RdSEg6bW06c3MuU1NTW1pdJyA6ICdZWVlZLU1NLUREW1RdSEg6bW06c3MuU1NTWicpO1xufVxuXG4vKipcbiAqIFJldHVybiBhIGh1bWFuIHJlYWRhYmxlIHJlcHJlc2VudGF0aW9uIG9mIGEgbW9tZW50IHRoYXQgY2FuXG4gKiBhbHNvIGJlIGV2YWx1YXRlZCB0byBnZXQgYSBuZXcgbW9tZW50IHdoaWNoIGlzIHRoZSBzYW1lXG4gKlxuICogQGxpbmsgaHR0cHM6Ly9ub2RlanMub3JnL2Rpc3QvbGF0ZXN0L2RvY3MvYXBpL3V0aWwuaHRtbCN1dGlsX2N1c3RvbV9pbnNwZWN0X2Z1bmN0aW9uX29uX29iamVjdHNcbiAqL1xuZnVuY3Rpb24gaW5zcGVjdCAoKSB7XG4gICAgaWYgKCF0aGlzLmlzVmFsaWQoKSkge1xuICAgICAgICByZXR1cm4gJ21vbWVudC5pbnZhbGlkKC8qICcgKyB0aGlzLl9pICsgJyAqLyknO1xuICAgIH1cbiAgICB2YXIgZnVuYyA9ICdtb21lbnQnO1xuICAgIHZhciB6b25lID0gJyc7XG4gICAgaWYgKCF0aGlzLmlzTG9jYWwoKSkge1xuICAgICAgICBmdW5jID0gdGhpcy51dGNPZmZzZXQoKSA9PT0gMCA/ICdtb21lbnQudXRjJyA6ICdtb21lbnQucGFyc2Vab25lJztcbiAgICAgICAgem9uZSA9ICdaJztcbiAgICB9XG4gICAgdmFyIHByZWZpeCA9ICdbJyArIGZ1bmMgKyAnKFwiXSc7XG4gICAgdmFyIHllYXIgPSAoMCA8PSB0aGlzLnllYXIoKSAmJiB0aGlzLnllYXIoKSA8PSA5OTk5KSA/ICdZWVlZJyA6ICdZWVlZWVknO1xuICAgIHZhciBkYXRldGltZSA9ICctTU0tRERbVF1ISDptbTpzcy5TU1MnO1xuICAgIHZhciBzdWZmaXggPSB6b25lICsgJ1tcIildJztcblxuICAgIHJldHVybiB0aGlzLmZvcm1hdChwcmVmaXggKyB5ZWFyICsgZGF0ZXRpbWUgKyBzdWZmaXgpO1xufVxuXG5mdW5jdGlvbiBmb3JtYXQgKGlucHV0U3RyaW5nKSB7XG4gICAgaWYgKCFpbnB1dFN0cmluZykge1xuICAgICAgICBpbnB1dFN0cmluZyA9IHRoaXMuaXNVdGMoKSA/IGhvb2tzLmRlZmF1bHRGb3JtYXRVdGMgOiBob29rcy5kZWZhdWx0Rm9ybWF0O1xuICAgIH1cbiAgICB2YXIgb3V0cHV0ID0gZm9ybWF0TW9tZW50KHRoaXMsIGlucHV0U3RyaW5nKTtcbiAgICByZXR1cm4gdGhpcy5sb2NhbGVEYXRhKCkucG9zdGZvcm1hdChvdXRwdXQpO1xufVxuXG5mdW5jdGlvbiBmcm9tICh0aW1lLCB3aXRob3V0U3VmZml4KSB7XG4gICAgaWYgKHRoaXMuaXNWYWxpZCgpICYmXG4gICAgICAgICAgICAoKGlzTW9tZW50KHRpbWUpICYmIHRpbWUuaXNWYWxpZCgpKSB8fFxuICAgICAgICAgICAgIGNyZWF0ZUxvY2FsKHRpbWUpLmlzVmFsaWQoKSkpIHtcbiAgICAgICAgcmV0dXJuIGNyZWF0ZUR1cmF0aW9uKHt0bzogdGhpcywgZnJvbTogdGltZX0pLmxvY2FsZSh0aGlzLmxvY2FsZSgpKS5odW1hbml6ZSghd2l0aG91dFN1ZmZpeCk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubG9jYWxlRGF0YSgpLmludmFsaWREYXRlKCk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBmcm9tTm93ICh3aXRob3V0U3VmZml4KSB7XG4gICAgcmV0dXJuIHRoaXMuZnJvbShjcmVhdGVMb2NhbCgpLCB3aXRob3V0U3VmZml4KTtcbn1cblxuZnVuY3Rpb24gdG8gKHRpbWUsIHdpdGhvdXRTdWZmaXgpIHtcbiAgICBpZiAodGhpcy5pc1ZhbGlkKCkgJiZcbiAgICAgICAgICAgICgoaXNNb21lbnQodGltZSkgJiYgdGltZS5pc1ZhbGlkKCkpIHx8XG4gICAgICAgICAgICAgY3JlYXRlTG9jYWwodGltZSkuaXNWYWxpZCgpKSkge1xuICAgICAgICByZXR1cm4gY3JlYXRlRHVyYXRpb24oe2Zyb206IHRoaXMsIHRvOiB0aW1lfSkubG9jYWxlKHRoaXMubG9jYWxlKCkpLmh1bWFuaXplKCF3aXRob3V0U3VmZml4KTtcbiAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gdGhpcy5sb2NhbGVEYXRhKCkuaW52YWxpZERhdGUoKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIHRvTm93ICh3aXRob3V0U3VmZml4KSB7XG4gICAgcmV0dXJuIHRoaXMudG8oY3JlYXRlTG9jYWwoKSwgd2l0aG91dFN1ZmZpeCk7XG59XG5cbi8vIElmIHBhc3NlZCBhIGxvY2FsZSBrZXksIGl0IHdpbGwgc2V0IHRoZSBsb2NhbGUgZm9yIHRoaXNcbi8vIGluc3RhbmNlLiAgT3RoZXJ3aXNlLCBpdCB3aWxsIHJldHVybiB0aGUgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vIHZhcmlhYmxlcyBmb3IgdGhpcyBpbnN0YW5jZS5cbmZ1bmN0aW9uIGxvY2FsZSAoa2V5KSB7XG4gICAgdmFyIG5ld0xvY2FsZURhdGE7XG5cbiAgICBpZiAoa2V5ID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2xvY2FsZS5fYWJicjtcbiAgICB9IGVsc2Uge1xuICAgICAgICBuZXdMb2NhbGVEYXRhID0gZ2V0TG9jYWxlKGtleSk7XG4gICAgICAgIGlmIChuZXdMb2NhbGVEYXRhICE9IG51bGwpIHtcbiAgICAgICAgICAgIHRoaXMuX2xvY2FsZSA9IG5ld0xvY2FsZURhdGE7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxufVxuXG52YXIgbGFuZyA9IGRlcHJlY2F0ZShcbiAgICAnbW9tZW50KCkubGFuZygpIGlzIGRlcHJlY2F0ZWQuIEluc3RlYWQsIHVzZSBtb21lbnQoKS5sb2NhbGVEYXRhKCkgdG8gZ2V0IHRoZSBsYW5ndWFnZSBjb25maWd1cmF0aW9uLiBVc2UgbW9tZW50KCkubG9jYWxlKCkgdG8gY2hhbmdlIGxhbmd1YWdlcy4nLFxuICAgIGZ1bmN0aW9uIChrZXkpIHtcbiAgICAgICAgaWYgKGtleSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5sb2NhbGVEYXRhKCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5sb2NhbGUoa2V5KTtcbiAgICAgICAgfVxuICAgIH1cbik7XG5cbmZ1bmN0aW9uIGxvY2FsZURhdGEgKCkge1xuICAgIHJldHVybiB0aGlzLl9sb2NhbGU7XG59XG5cbmZ1bmN0aW9uIHN0YXJ0T2YgKHVuaXRzKSB7XG4gICAgdW5pdHMgPSBub3JtYWxpemVVbml0cyh1bml0cyk7XG4gICAgLy8gdGhlIGZvbGxvd2luZyBzd2l0Y2ggaW50ZW50aW9uYWxseSBvbWl0cyBicmVhayBrZXl3b3Jkc1xuICAgIC8vIHRvIHV0aWxpemUgZmFsbGluZyB0aHJvdWdoIHRoZSBjYXNlcy5cbiAgICBzd2l0Y2ggKHVuaXRzKSB7XG4gICAgICAgIGNhc2UgJ3llYXInOlxuICAgICAgICAgICAgdGhpcy5tb250aCgwKTtcbiAgICAgICAgICAgIC8qIGZhbGxzIHRocm91Z2ggKi9cbiAgICAgICAgY2FzZSAncXVhcnRlcic6XG4gICAgICAgIGNhc2UgJ21vbnRoJzpcbiAgICAgICAgICAgIHRoaXMuZGF0ZSgxKTtcbiAgICAgICAgICAgIC8qIGZhbGxzIHRocm91Z2ggKi9cbiAgICAgICAgY2FzZSAnd2Vlayc6XG4gICAgICAgIGNhc2UgJ2lzb1dlZWsnOlxuICAgICAgICBjYXNlICdkYXknOlxuICAgICAgICBjYXNlICdkYXRlJzpcbiAgICAgICAgICAgIHRoaXMuaG91cnMoMCk7XG4gICAgICAgICAgICAvKiBmYWxscyB0aHJvdWdoICovXG4gICAgICAgIGNhc2UgJ2hvdXInOlxuICAgICAgICAgICAgdGhpcy5taW51dGVzKDApO1xuICAgICAgICAgICAgLyogZmFsbHMgdGhyb3VnaCAqL1xuICAgICAgICBjYXNlICdtaW51dGUnOlxuICAgICAgICAgICAgdGhpcy5zZWNvbmRzKDApO1xuICAgICAgICAgICAgLyogZmFsbHMgdGhyb3VnaCAqL1xuICAgICAgICBjYXNlICdzZWNvbmQnOlxuICAgICAgICAgICAgdGhpcy5taWxsaXNlY29uZHMoMCk7XG4gICAgfVxuXG4gICAgLy8gd2Vla3MgYXJlIGEgc3BlY2lhbCBjYXNlXG4gICAgaWYgKHVuaXRzID09PSAnd2VlaycpIHtcbiAgICAgICAgdGhpcy53ZWVrZGF5KDApO1xuICAgIH1cbiAgICBpZiAodW5pdHMgPT09ICdpc29XZWVrJykge1xuICAgICAgICB0aGlzLmlzb1dlZWtkYXkoMSk7XG4gICAgfVxuXG4gICAgLy8gcXVhcnRlcnMgYXJlIGFsc28gc3BlY2lhbFxuICAgIGlmICh1bml0cyA9PT0gJ3F1YXJ0ZXInKSB7XG4gICAgICAgIHRoaXMubW9udGgoTWF0aC5mbG9vcih0aGlzLm1vbnRoKCkgLyAzKSAqIDMpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzO1xufVxuXG5mdW5jdGlvbiBlbmRPZiAodW5pdHMpIHtcbiAgICB1bml0cyA9IG5vcm1hbGl6ZVVuaXRzKHVuaXRzKTtcbiAgICBpZiAodW5pdHMgPT09IHVuZGVmaW5lZCB8fCB1bml0cyA9PT0gJ21pbGxpc2Vjb25kJykge1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvLyAnZGF0ZScgaXMgYW4gYWxpYXMgZm9yICdkYXknLCBzbyBpdCBzaG91bGQgYmUgY29uc2lkZXJlZCBhcyBzdWNoLlxuICAgIGlmICh1bml0cyA9PT0gJ2RhdGUnKSB7XG4gICAgICAgIHVuaXRzID0gJ2RheSc7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuc3RhcnRPZih1bml0cykuYWRkKDEsICh1bml0cyA9PT0gJ2lzb1dlZWsnID8gJ3dlZWsnIDogdW5pdHMpKS5zdWJ0cmFjdCgxLCAnbXMnKTtcbn1cblxuZnVuY3Rpb24gdmFsdWVPZiAoKSB7XG4gICAgcmV0dXJuIHRoaXMuX2QudmFsdWVPZigpIC0gKCh0aGlzLl9vZmZzZXQgfHwgMCkgKiA2MDAwMCk7XG59XG5cbmZ1bmN0aW9uIHVuaXggKCkge1xuICAgIHJldHVybiBNYXRoLmZsb29yKHRoaXMudmFsdWVPZigpIC8gMTAwMCk7XG59XG5cbmZ1bmN0aW9uIHRvRGF0ZSAoKSB7XG4gICAgcmV0dXJuIG5ldyBEYXRlKHRoaXMudmFsdWVPZigpKTtcbn1cblxuZnVuY3Rpb24gdG9BcnJheSAoKSB7XG4gICAgdmFyIG0gPSB0aGlzO1xuICAgIHJldHVybiBbbS55ZWFyKCksIG0ubW9udGgoKSwgbS5kYXRlKCksIG0uaG91cigpLCBtLm1pbnV0ZSgpLCBtLnNlY29uZCgpLCBtLm1pbGxpc2Vjb25kKCldO1xufVxuXG5mdW5jdGlvbiB0b09iamVjdCAoKSB7XG4gICAgdmFyIG0gPSB0aGlzO1xuICAgIHJldHVybiB7XG4gICAgICAgIHllYXJzOiBtLnllYXIoKSxcbiAgICAgICAgbW9udGhzOiBtLm1vbnRoKCksXG4gICAgICAgIGRhdGU6IG0uZGF0ZSgpLFxuICAgICAgICBob3VyczogbS5ob3VycygpLFxuICAgICAgICBtaW51dGVzOiBtLm1pbnV0ZXMoKSxcbiAgICAgICAgc2Vjb25kczogbS5zZWNvbmRzKCksXG4gICAgICAgIG1pbGxpc2Vjb25kczogbS5taWxsaXNlY29uZHMoKVxuICAgIH07XG59XG5cbmZ1bmN0aW9uIHRvSlNPTiAoKSB7XG4gICAgLy8gbmV3IERhdGUoTmFOKS50b0pTT04oKSA9PT0gbnVsbFxuICAgIHJldHVybiB0aGlzLmlzVmFsaWQoKSA/IHRoaXMudG9JU09TdHJpbmcoKSA6IG51bGw7XG59XG5cbmZ1bmN0aW9uIGlzVmFsaWQkMiAoKSB7XG4gICAgcmV0dXJuIGlzVmFsaWQodGhpcyk7XG59XG5cbmZ1bmN0aW9uIHBhcnNpbmdGbGFncyAoKSB7XG4gICAgcmV0dXJuIGV4dGVuZCh7fSwgZ2V0UGFyc2luZ0ZsYWdzKHRoaXMpKTtcbn1cblxuZnVuY3Rpb24gaW52YWxpZEF0ICgpIHtcbiAgICByZXR1cm4gZ2V0UGFyc2luZ0ZsYWdzKHRoaXMpLm92ZXJmbG93O1xufVxuXG5mdW5jdGlvbiBjcmVhdGlvbkRhdGEoKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgaW5wdXQ6IHRoaXMuX2ksXG4gICAgICAgIGZvcm1hdDogdGhpcy5fZixcbiAgICAgICAgbG9jYWxlOiB0aGlzLl9sb2NhbGUsXG4gICAgICAgIGlzVVRDOiB0aGlzLl9pc1VUQyxcbiAgICAgICAgc3RyaWN0OiB0aGlzLl9zdHJpY3RcbiAgICB9O1xufVxuXG4vLyBGT1JNQVRUSU5HXG5cbmFkZEZvcm1hdFRva2VuKDAsIFsnZ2cnLCAyXSwgMCwgZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLndlZWtZZWFyKCkgJSAxMDA7XG59KTtcblxuYWRkRm9ybWF0VG9rZW4oMCwgWydHRycsIDJdLCAwLCBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMuaXNvV2Vla1llYXIoKSAlIDEwMDtcbn0pO1xuXG5mdW5jdGlvbiBhZGRXZWVrWWVhckZvcm1hdFRva2VuICh0b2tlbiwgZ2V0dGVyKSB7XG4gICAgYWRkRm9ybWF0VG9rZW4oMCwgW3Rva2VuLCB0b2tlbi5sZW5ndGhdLCAwLCBnZXR0ZXIpO1xufVxuXG5hZGRXZWVrWWVhckZvcm1hdFRva2VuKCdnZ2dnJywgICAgICd3ZWVrWWVhcicpO1xuYWRkV2Vla1llYXJGb3JtYXRUb2tlbignZ2dnZ2cnLCAgICAnd2Vla1llYXInKTtcbmFkZFdlZWtZZWFyRm9ybWF0VG9rZW4oJ0dHR0cnLCAgJ2lzb1dlZWtZZWFyJyk7XG5hZGRXZWVrWWVhckZvcm1hdFRva2VuKCdHR0dHRycsICdpc29XZWVrWWVhcicpO1xuXG4vLyBBTElBU0VTXG5cbmFkZFVuaXRBbGlhcygnd2Vla1llYXInLCAnZ2cnKTtcbmFkZFVuaXRBbGlhcygnaXNvV2Vla1llYXInLCAnR0cnKTtcblxuLy8gUFJJT1JJVFlcblxuYWRkVW5pdFByaW9yaXR5KCd3ZWVrWWVhcicsIDEpO1xuYWRkVW5pdFByaW9yaXR5KCdpc29XZWVrWWVhcicsIDEpO1xuXG5cbi8vIFBBUlNJTkdcblxuYWRkUmVnZXhUb2tlbignRycsICAgICAgbWF0Y2hTaWduZWQpO1xuYWRkUmVnZXhUb2tlbignZycsICAgICAgbWF0Y2hTaWduZWQpO1xuYWRkUmVnZXhUb2tlbignR0cnLCAgICAgbWF0Y2gxdG8yLCBtYXRjaDIpO1xuYWRkUmVnZXhUb2tlbignZ2cnLCAgICAgbWF0Y2gxdG8yLCBtYXRjaDIpO1xuYWRkUmVnZXhUb2tlbignR0dHRycsICAgbWF0Y2gxdG80LCBtYXRjaDQpO1xuYWRkUmVnZXhUb2tlbignZ2dnZycsICAgbWF0Y2gxdG80LCBtYXRjaDQpO1xuYWRkUmVnZXhUb2tlbignR0dHR0cnLCAgbWF0Y2gxdG82LCBtYXRjaDYpO1xuYWRkUmVnZXhUb2tlbignZ2dnZ2cnLCAgbWF0Y2gxdG82LCBtYXRjaDYpO1xuXG5hZGRXZWVrUGFyc2VUb2tlbihbJ2dnZ2cnLCAnZ2dnZ2cnLCAnR0dHRycsICdHR0dHRyddLCBmdW5jdGlvbiAoaW5wdXQsIHdlZWssIGNvbmZpZywgdG9rZW4pIHtcbiAgICB3ZWVrW3Rva2VuLnN1YnN0cigwLCAyKV0gPSB0b0ludChpbnB1dCk7XG59KTtcblxuYWRkV2Vla1BhcnNlVG9rZW4oWydnZycsICdHRyddLCBmdW5jdGlvbiAoaW5wdXQsIHdlZWssIGNvbmZpZywgdG9rZW4pIHtcbiAgICB3ZWVrW3Rva2VuXSA9IGhvb2tzLnBhcnNlVHdvRGlnaXRZZWFyKGlucHV0KTtcbn0pO1xuXG4vLyBNT01FTlRTXG5cbmZ1bmN0aW9uIGdldFNldFdlZWtZZWFyIChpbnB1dCkge1xuICAgIHJldHVybiBnZXRTZXRXZWVrWWVhckhlbHBlci5jYWxsKHRoaXMsXG4gICAgICAgICAgICBpbnB1dCxcbiAgICAgICAgICAgIHRoaXMud2VlaygpLFxuICAgICAgICAgICAgdGhpcy53ZWVrZGF5KCksXG4gICAgICAgICAgICB0aGlzLmxvY2FsZURhdGEoKS5fd2Vlay5kb3csXG4gICAgICAgICAgICB0aGlzLmxvY2FsZURhdGEoKS5fd2Vlay5kb3kpO1xufVxuXG5mdW5jdGlvbiBnZXRTZXRJU09XZWVrWWVhciAoaW5wdXQpIHtcbiAgICByZXR1cm4gZ2V0U2V0V2Vla1llYXJIZWxwZXIuY2FsbCh0aGlzLFxuICAgICAgICAgICAgaW5wdXQsIHRoaXMuaXNvV2VlaygpLCB0aGlzLmlzb1dlZWtkYXkoKSwgMSwgNCk7XG59XG5cbmZ1bmN0aW9uIGdldElTT1dlZWtzSW5ZZWFyICgpIHtcbiAgICByZXR1cm4gd2Vla3NJblllYXIodGhpcy55ZWFyKCksIDEsIDQpO1xufVxuXG5mdW5jdGlvbiBnZXRXZWVrc0luWWVhciAoKSB7XG4gICAgdmFyIHdlZWtJbmZvID0gdGhpcy5sb2NhbGVEYXRhKCkuX3dlZWs7XG4gICAgcmV0dXJuIHdlZWtzSW5ZZWFyKHRoaXMueWVhcigpLCB3ZWVrSW5mby5kb3csIHdlZWtJbmZvLmRveSk7XG59XG5cbmZ1bmN0aW9uIGdldFNldFdlZWtZZWFySGVscGVyKGlucHV0LCB3ZWVrLCB3ZWVrZGF5LCBkb3csIGRveSkge1xuICAgIHZhciB3ZWVrc1RhcmdldDtcbiAgICBpZiAoaW5wdXQgPT0gbnVsbCkge1xuICAgICAgICByZXR1cm4gd2Vla09mWWVhcih0aGlzLCBkb3csIGRveSkueWVhcjtcbiAgICB9IGVsc2Uge1xuICAgICAgICB3ZWVrc1RhcmdldCA9IHdlZWtzSW5ZZWFyKGlucHV0LCBkb3csIGRveSk7XG4gICAgICAgIGlmICh3ZWVrID4gd2Vla3NUYXJnZXQpIHtcbiAgICAgICAgICAgIHdlZWsgPSB3ZWVrc1RhcmdldDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc2V0V2Vla0FsbC5jYWxsKHRoaXMsIGlucHV0LCB3ZWVrLCB3ZWVrZGF5LCBkb3csIGRveSk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBzZXRXZWVrQWxsKHdlZWtZZWFyLCB3ZWVrLCB3ZWVrZGF5LCBkb3csIGRveSkge1xuICAgIHZhciBkYXlPZlllYXJEYXRhID0gZGF5T2ZZZWFyRnJvbVdlZWtzKHdlZWtZZWFyLCB3ZWVrLCB3ZWVrZGF5LCBkb3csIGRveSksXG4gICAgICAgIGRhdGUgPSBjcmVhdGVVVENEYXRlKGRheU9mWWVhckRhdGEueWVhciwgMCwgZGF5T2ZZZWFyRGF0YS5kYXlPZlllYXIpO1xuXG4gICAgdGhpcy55ZWFyKGRhdGUuZ2V0VVRDRnVsbFllYXIoKSk7XG4gICAgdGhpcy5tb250aChkYXRlLmdldFVUQ01vbnRoKCkpO1xuICAgIHRoaXMuZGF0ZShkYXRlLmdldFVUQ0RhdGUoKSk7XG4gICAgcmV0dXJuIHRoaXM7XG59XG5cbi8vIEZPUk1BVFRJTkdcblxuYWRkRm9ybWF0VG9rZW4oJ1EnLCAwLCAnUW8nLCAncXVhcnRlcicpO1xuXG4vLyBBTElBU0VTXG5cbmFkZFVuaXRBbGlhcygncXVhcnRlcicsICdRJyk7XG5cbi8vIFBSSU9SSVRZXG5cbmFkZFVuaXRQcmlvcml0eSgncXVhcnRlcicsIDcpO1xuXG4vLyBQQVJTSU5HXG5cbmFkZFJlZ2V4VG9rZW4oJ1EnLCBtYXRjaDEpO1xuYWRkUGFyc2VUb2tlbignUScsIGZ1bmN0aW9uIChpbnB1dCwgYXJyYXkpIHtcbiAgICBhcnJheVtNT05USF0gPSAodG9JbnQoaW5wdXQpIC0gMSkgKiAzO1xufSk7XG5cbi8vIE1PTUVOVFNcblxuZnVuY3Rpb24gZ2V0U2V0UXVhcnRlciAoaW5wdXQpIHtcbiAgICByZXR1cm4gaW5wdXQgPT0gbnVsbCA/IE1hdGguY2VpbCgodGhpcy5tb250aCgpICsgMSkgLyAzKSA6IHRoaXMubW9udGgoKGlucHV0IC0gMSkgKiAzICsgdGhpcy5tb250aCgpICUgMyk7XG59XG5cbi8vIEZPUk1BVFRJTkdcblxuYWRkRm9ybWF0VG9rZW4oJ0QnLCBbJ0REJywgMl0sICdEbycsICdkYXRlJyk7XG5cbi8vIEFMSUFTRVNcblxuYWRkVW5pdEFsaWFzKCdkYXRlJywgJ0QnKTtcblxuLy8gUFJJT1JPSVRZXG5hZGRVbml0UHJpb3JpdHkoJ2RhdGUnLCA5KTtcblxuLy8gUEFSU0lOR1xuXG5hZGRSZWdleFRva2VuKCdEJywgIG1hdGNoMXRvMik7XG5hZGRSZWdleFRva2VuKCdERCcsIG1hdGNoMXRvMiwgbWF0Y2gyKTtcbmFkZFJlZ2V4VG9rZW4oJ0RvJywgZnVuY3Rpb24gKGlzU3RyaWN0LCBsb2NhbGUpIHtcbiAgICAvLyBUT0RPOiBSZW1vdmUgXCJvcmRpbmFsUGFyc2VcIiBmYWxsYmFjayBpbiBuZXh0IG1ham9yIHJlbGVhc2UuXG4gICAgcmV0dXJuIGlzU3RyaWN0ID9cbiAgICAgIChsb2NhbGUuX2RheU9mTW9udGhPcmRpbmFsUGFyc2UgfHwgbG9jYWxlLl9vcmRpbmFsUGFyc2UpIDpcbiAgICAgIGxvY2FsZS5fZGF5T2ZNb250aE9yZGluYWxQYXJzZUxlbmllbnQ7XG59KTtcblxuYWRkUGFyc2VUb2tlbihbJ0QnLCAnREQnXSwgREFURSk7XG5hZGRQYXJzZVRva2VuKCdEbycsIGZ1bmN0aW9uIChpbnB1dCwgYXJyYXkpIHtcbiAgICBhcnJheVtEQVRFXSA9IHRvSW50KGlucHV0Lm1hdGNoKG1hdGNoMXRvMilbMF0pO1xufSk7XG5cbi8vIE1PTUVOVFNcblxudmFyIGdldFNldERheU9mTW9udGggPSBtYWtlR2V0U2V0KCdEYXRlJywgdHJ1ZSk7XG5cbi8vIEZPUk1BVFRJTkdcblxuYWRkRm9ybWF0VG9rZW4oJ0RERCcsIFsnRERERCcsIDNdLCAnREREbycsICdkYXlPZlllYXInKTtcblxuLy8gQUxJQVNFU1xuXG5hZGRVbml0QWxpYXMoJ2RheU9mWWVhcicsICdEREQnKTtcblxuLy8gUFJJT1JJVFlcbmFkZFVuaXRQcmlvcml0eSgnZGF5T2ZZZWFyJywgNCk7XG5cbi8vIFBBUlNJTkdcblxuYWRkUmVnZXhUb2tlbignREREJywgIG1hdGNoMXRvMyk7XG5hZGRSZWdleFRva2VuKCdEREREJywgbWF0Y2gzKTtcbmFkZFBhcnNlVG9rZW4oWydEREQnLCAnRERERCddLCBmdW5jdGlvbiAoaW5wdXQsIGFycmF5LCBjb25maWcpIHtcbiAgICBjb25maWcuX2RheU9mWWVhciA9IHRvSW50KGlucHV0KTtcbn0pO1xuXG4vLyBIRUxQRVJTXG5cbi8vIE1PTUVOVFNcblxuZnVuY3Rpb24gZ2V0U2V0RGF5T2ZZZWFyIChpbnB1dCkge1xuICAgIHZhciBkYXlPZlllYXIgPSBNYXRoLnJvdW5kKCh0aGlzLmNsb25lKCkuc3RhcnRPZignZGF5JykgLSB0aGlzLmNsb25lKCkuc3RhcnRPZigneWVhcicpKSAvIDg2NGU1KSArIDE7XG4gICAgcmV0dXJuIGlucHV0ID09IG51bGwgPyBkYXlPZlllYXIgOiB0aGlzLmFkZCgoaW5wdXQgLSBkYXlPZlllYXIpLCAnZCcpO1xufVxuXG4vLyBGT1JNQVRUSU5HXG5cbmFkZEZvcm1hdFRva2VuKCdtJywgWydtbScsIDJdLCAwLCAnbWludXRlJyk7XG5cbi8vIEFMSUFTRVNcblxuYWRkVW5pdEFsaWFzKCdtaW51dGUnLCAnbScpO1xuXG4vLyBQUklPUklUWVxuXG5hZGRVbml0UHJpb3JpdHkoJ21pbnV0ZScsIDE0KTtcblxuLy8gUEFSU0lOR1xuXG5hZGRSZWdleFRva2VuKCdtJywgIG1hdGNoMXRvMik7XG5hZGRSZWdleFRva2VuKCdtbScsIG1hdGNoMXRvMiwgbWF0Y2gyKTtcbmFkZFBhcnNlVG9rZW4oWydtJywgJ21tJ10sIE1JTlVURSk7XG5cbi8vIE1PTUVOVFNcblxudmFyIGdldFNldE1pbnV0ZSA9IG1ha2VHZXRTZXQoJ01pbnV0ZXMnLCBmYWxzZSk7XG5cbi8vIEZPUk1BVFRJTkdcblxuYWRkRm9ybWF0VG9rZW4oJ3MnLCBbJ3NzJywgMl0sIDAsICdzZWNvbmQnKTtcblxuLy8gQUxJQVNFU1xuXG5hZGRVbml0QWxpYXMoJ3NlY29uZCcsICdzJyk7XG5cbi8vIFBSSU9SSVRZXG5cbmFkZFVuaXRQcmlvcml0eSgnc2Vjb25kJywgMTUpO1xuXG4vLyBQQVJTSU5HXG5cbmFkZFJlZ2V4VG9rZW4oJ3MnLCAgbWF0Y2gxdG8yKTtcbmFkZFJlZ2V4VG9rZW4oJ3NzJywgbWF0Y2gxdG8yLCBtYXRjaDIpO1xuYWRkUGFyc2VUb2tlbihbJ3MnLCAnc3MnXSwgU0VDT05EKTtcblxuLy8gTU9NRU5UU1xuXG52YXIgZ2V0U2V0U2Vjb25kID0gbWFrZUdldFNldCgnU2Vjb25kcycsIGZhbHNlKTtcblxuLy8gRk9STUFUVElOR1xuXG5hZGRGb3JtYXRUb2tlbignUycsIDAsIDAsIGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gfn4odGhpcy5taWxsaXNlY29uZCgpIC8gMTAwKTtcbn0pO1xuXG5hZGRGb3JtYXRUb2tlbigwLCBbJ1NTJywgMl0sIDAsIGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gfn4odGhpcy5taWxsaXNlY29uZCgpIC8gMTApO1xufSk7XG5cbmFkZEZvcm1hdFRva2VuKDAsIFsnU1NTJywgM10sIDAsICdtaWxsaXNlY29uZCcpO1xuYWRkRm9ybWF0VG9rZW4oMCwgWydTU1NTJywgNF0sIDAsIGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5taWxsaXNlY29uZCgpICogMTA7XG59KTtcbmFkZEZvcm1hdFRva2VuKDAsIFsnU1NTU1MnLCA1XSwgMCwgZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLm1pbGxpc2Vjb25kKCkgKiAxMDA7XG59KTtcbmFkZEZvcm1hdFRva2VuKDAsIFsnU1NTU1NTJywgNl0sIDAsIGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5taWxsaXNlY29uZCgpICogMTAwMDtcbn0pO1xuYWRkRm9ybWF0VG9rZW4oMCwgWydTU1NTU1NTJywgN10sIDAsIGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5taWxsaXNlY29uZCgpICogMTAwMDA7XG59KTtcbmFkZEZvcm1hdFRva2VuKDAsIFsnU1NTU1NTU1MnLCA4XSwgMCwgZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLm1pbGxpc2Vjb25kKCkgKiAxMDAwMDA7XG59KTtcbmFkZEZvcm1hdFRva2VuKDAsIFsnU1NTU1NTU1NTJywgOV0sIDAsIGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5taWxsaXNlY29uZCgpICogMTAwMDAwMDtcbn0pO1xuXG5cbi8vIEFMSUFTRVNcblxuYWRkVW5pdEFsaWFzKCdtaWxsaXNlY29uZCcsICdtcycpO1xuXG4vLyBQUklPUklUWVxuXG5hZGRVbml0UHJpb3JpdHkoJ21pbGxpc2Vjb25kJywgMTYpO1xuXG4vLyBQQVJTSU5HXG5cbmFkZFJlZ2V4VG9rZW4oJ1MnLCAgICBtYXRjaDF0bzMsIG1hdGNoMSk7XG5hZGRSZWdleFRva2VuKCdTUycsICAgbWF0Y2gxdG8zLCBtYXRjaDIpO1xuYWRkUmVnZXhUb2tlbignU1NTJywgIG1hdGNoMXRvMywgbWF0Y2gzKTtcblxudmFyIHRva2VuO1xuZm9yICh0b2tlbiA9ICdTU1NTJzsgdG9rZW4ubGVuZ3RoIDw9IDk7IHRva2VuICs9ICdTJykge1xuICAgIGFkZFJlZ2V4VG9rZW4odG9rZW4sIG1hdGNoVW5zaWduZWQpO1xufVxuXG5mdW5jdGlvbiBwYXJzZU1zKGlucHV0LCBhcnJheSkge1xuICAgIGFycmF5W01JTExJU0VDT05EXSA9IHRvSW50KCgnMC4nICsgaW5wdXQpICogMTAwMCk7XG59XG5cbmZvciAodG9rZW4gPSAnUyc7IHRva2VuLmxlbmd0aCA8PSA5OyB0b2tlbiArPSAnUycpIHtcbiAgICBhZGRQYXJzZVRva2VuKHRva2VuLCBwYXJzZU1zKTtcbn1cbi8vIE1PTUVOVFNcblxudmFyIGdldFNldE1pbGxpc2Vjb25kID0gbWFrZUdldFNldCgnTWlsbGlzZWNvbmRzJywgZmFsc2UpO1xuXG4vLyBGT1JNQVRUSU5HXG5cbmFkZEZvcm1hdFRva2VuKCd6JywgIDAsIDAsICd6b25lQWJicicpO1xuYWRkRm9ybWF0VG9rZW4oJ3p6JywgMCwgMCwgJ3pvbmVOYW1lJyk7XG5cbi8vIE1PTUVOVFNcblxuZnVuY3Rpb24gZ2V0Wm9uZUFiYnIgKCkge1xuICAgIHJldHVybiB0aGlzLl9pc1VUQyA/ICdVVEMnIDogJyc7XG59XG5cbmZ1bmN0aW9uIGdldFpvbmVOYW1lICgpIHtcbiAgICByZXR1cm4gdGhpcy5faXNVVEMgPyAnQ29vcmRpbmF0ZWQgVW5pdmVyc2FsIFRpbWUnIDogJyc7XG59XG5cbnZhciBwcm90byA9IE1vbWVudC5wcm90b3R5cGU7XG5cbnByb3RvLmFkZCAgICAgICAgICAgICAgID0gYWRkO1xucHJvdG8uY2FsZW5kYXIgICAgICAgICAgPSBjYWxlbmRhciQxO1xucHJvdG8uY2xvbmUgICAgICAgICAgICAgPSBjbG9uZTtcbnByb3RvLmRpZmYgICAgICAgICAgICAgID0gZGlmZjtcbnByb3RvLmVuZE9mICAgICAgICAgICAgID0gZW5kT2Y7XG5wcm90by5mb3JtYXQgICAgICAgICAgICA9IGZvcm1hdDtcbnByb3RvLmZyb20gICAgICAgICAgICAgID0gZnJvbTtcbnByb3RvLmZyb21Ob3cgICAgICAgICAgID0gZnJvbU5vdztcbnByb3RvLnRvICAgICAgICAgICAgICAgID0gdG87XG5wcm90by50b05vdyAgICAgICAgICAgICA9IHRvTm93O1xucHJvdG8uZ2V0ICAgICAgICAgICAgICAgPSBzdHJpbmdHZXQ7XG5wcm90by5pbnZhbGlkQXQgICAgICAgICA9IGludmFsaWRBdDtcbnByb3RvLmlzQWZ0ZXIgICAgICAgICAgID0gaXNBZnRlcjtcbnByb3RvLmlzQmVmb3JlICAgICAgICAgID0gaXNCZWZvcmU7XG5wcm90by5pc0JldHdlZW4gICAgICAgICA9IGlzQmV0d2VlbjtcbnByb3RvLmlzU2FtZSAgICAgICAgICAgID0gaXNTYW1lO1xucHJvdG8uaXNTYW1lT3JBZnRlciAgICAgPSBpc1NhbWVPckFmdGVyO1xucHJvdG8uaXNTYW1lT3JCZWZvcmUgICAgPSBpc1NhbWVPckJlZm9yZTtcbnByb3RvLmlzVmFsaWQgICAgICAgICAgID0gaXNWYWxpZCQyO1xucHJvdG8ubGFuZyAgICAgICAgICAgICAgPSBsYW5nO1xucHJvdG8ubG9jYWxlICAgICAgICAgICAgPSBsb2NhbGU7XG5wcm90by5sb2NhbGVEYXRhICAgICAgICA9IGxvY2FsZURhdGE7XG5wcm90by5tYXggICAgICAgICAgICAgICA9IHByb3RvdHlwZU1heDtcbnByb3RvLm1pbiAgICAgICAgICAgICAgID0gcHJvdG90eXBlTWluO1xucHJvdG8ucGFyc2luZ0ZsYWdzICAgICAgPSBwYXJzaW5nRmxhZ3M7XG5wcm90by5zZXQgICAgICAgICAgICAgICA9IHN0cmluZ1NldDtcbnByb3RvLnN0YXJ0T2YgICAgICAgICAgID0gc3RhcnRPZjtcbnByb3RvLnN1YnRyYWN0ICAgICAgICAgID0gc3VidHJhY3Q7XG5wcm90by50b0FycmF5ICAgICAgICAgICA9IHRvQXJyYXk7XG5wcm90by50b09iamVjdCAgICAgICAgICA9IHRvT2JqZWN0O1xucHJvdG8udG9EYXRlICAgICAgICAgICAgPSB0b0RhdGU7XG5wcm90by50b0lTT1N0cmluZyAgICAgICA9IHRvSVNPU3RyaW5nO1xucHJvdG8uaW5zcGVjdCAgICAgICAgICAgPSBpbnNwZWN0O1xucHJvdG8udG9KU09OICAgICAgICAgICAgPSB0b0pTT047XG5wcm90by50b1N0cmluZyAgICAgICAgICA9IHRvU3RyaW5nO1xucHJvdG8udW5peCAgICAgICAgICAgICAgPSB1bml4O1xucHJvdG8udmFsdWVPZiAgICAgICAgICAgPSB2YWx1ZU9mO1xucHJvdG8uY3JlYXRpb25EYXRhICAgICAgPSBjcmVhdGlvbkRhdGE7XG5cbi8vIFllYXJcbnByb3RvLnllYXIgICAgICAgPSBnZXRTZXRZZWFyO1xucHJvdG8uaXNMZWFwWWVhciA9IGdldElzTGVhcFllYXI7XG5cbi8vIFdlZWsgWWVhclxucHJvdG8ud2Vla1llYXIgICAgPSBnZXRTZXRXZWVrWWVhcjtcbnByb3RvLmlzb1dlZWtZZWFyID0gZ2V0U2V0SVNPV2Vla1llYXI7XG5cbi8vIFF1YXJ0ZXJcbnByb3RvLnF1YXJ0ZXIgPSBwcm90by5xdWFydGVycyA9IGdldFNldFF1YXJ0ZXI7XG5cbi8vIE1vbnRoXG5wcm90by5tb250aCAgICAgICA9IGdldFNldE1vbnRoO1xucHJvdG8uZGF5c0luTW9udGggPSBnZXREYXlzSW5Nb250aDtcblxuLy8gV2Vla1xucHJvdG8ud2VlayAgICAgICAgICAgPSBwcm90by53ZWVrcyAgICAgICAgPSBnZXRTZXRXZWVrO1xucHJvdG8uaXNvV2VlayAgICAgICAgPSBwcm90by5pc29XZWVrcyAgICAgPSBnZXRTZXRJU09XZWVrO1xucHJvdG8ud2Vla3NJblllYXIgICAgPSBnZXRXZWVrc0luWWVhcjtcbnByb3RvLmlzb1dlZWtzSW5ZZWFyID0gZ2V0SVNPV2Vla3NJblllYXI7XG5cbi8vIERheVxucHJvdG8uZGF0ZSAgICAgICA9IGdldFNldERheU9mTW9udGg7XG5wcm90by5kYXkgICAgICAgID0gcHJvdG8uZGF5cyAgICAgICAgICAgICA9IGdldFNldERheU9mV2VlaztcbnByb3RvLndlZWtkYXkgICAgPSBnZXRTZXRMb2NhbGVEYXlPZldlZWs7XG5wcm90by5pc29XZWVrZGF5ID0gZ2V0U2V0SVNPRGF5T2ZXZWVrO1xucHJvdG8uZGF5T2ZZZWFyICA9IGdldFNldERheU9mWWVhcjtcblxuLy8gSG91clxucHJvdG8uaG91ciA9IHByb3RvLmhvdXJzID0gZ2V0U2V0SG91cjtcblxuLy8gTWludXRlXG5wcm90by5taW51dGUgPSBwcm90by5taW51dGVzID0gZ2V0U2V0TWludXRlO1xuXG4vLyBTZWNvbmRcbnByb3RvLnNlY29uZCA9IHByb3RvLnNlY29uZHMgPSBnZXRTZXRTZWNvbmQ7XG5cbi8vIE1pbGxpc2Vjb25kXG5wcm90by5taWxsaXNlY29uZCA9IHByb3RvLm1pbGxpc2Vjb25kcyA9IGdldFNldE1pbGxpc2Vjb25kO1xuXG4vLyBPZmZzZXRcbnByb3RvLnV0Y09mZnNldCAgICAgICAgICAgID0gZ2V0U2V0T2Zmc2V0O1xucHJvdG8udXRjICAgICAgICAgICAgICAgICAgPSBzZXRPZmZzZXRUb1VUQztcbnByb3RvLmxvY2FsICAgICAgICAgICAgICAgID0gc2V0T2Zmc2V0VG9Mb2NhbDtcbnByb3RvLnBhcnNlWm9uZSAgICAgICAgICAgID0gc2V0T2Zmc2V0VG9QYXJzZWRPZmZzZXQ7XG5wcm90by5oYXNBbGlnbmVkSG91ck9mZnNldCA9IGhhc0FsaWduZWRIb3VyT2Zmc2V0O1xucHJvdG8uaXNEU1QgICAgICAgICAgICAgICAgPSBpc0RheWxpZ2h0U2F2aW5nVGltZTtcbnByb3RvLmlzTG9jYWwgICAgICAgICAgICAgID0gaXNMb2NhbDtcbnByb3RvLmlzVXRjT2Zmc2V0ICAgICAgICAgID0gaXNVdGNPZmZzZXQ7XG5wcm90by5pc1V0YyAgICAgICAgICAgICAgICA9IGlzVXRjO1xucHJvdG8uaXNVVEMgICAgICAgICAgICAgICAgPSBpc1V0YztcblxuLy8gVGltZXpvbmVcbnByb3RvLnpvbmVBYmJyID0gZ2V0Wm9uZUFiYnI7XG5wcm90by56b25lTmFtZSA9IGdldFpvbmVOYW1lO1xuXG4vLyBEZXByZWNhdGlvbnNcbnByb3RvLmRhdGVzICA9IGRlcHJlY2F0ZSgnZGF0ZXMgYWNjZXNzb3IgaXMgZGVwcmVjYXRlZC4gVXNlIGRhdGUgaW5zdGVhZC4nLCBnZXRTZXREYXlPZk1vbnRoKTtcbnByb3RvLm1vbnRocyA9IGRlcHJlY2F0ZSgnbW9udGhzIGFjY2Vzc29yIGlzIGRlcHJlY2F0ZWQuIFVzZSBtb250aCBpbnN0ZWFkJywgZ2V0U2V0TW9udGgpO1xucHJvdG8ueWVhcnMgID0gZGVwcmVjYXRlKCd5ZWFycyBhY2Nlc3NvciBpcyBkZXByZWNhdGVkLiBVc2UgeWVhciBpbnN0ZWFkJywgZ2V0U2V0WWVhcik7XG5wcm90by56b25lICAgPSBkZXByZWNhdGUoJ21vbWVudCgpLnpvbmUgaXMgZGVwcmVjYXRlZCwgdXNlIG1vbWVudCgpLnV0Y09mZnNldCBpbnN0ZWFkLiBodHRwOi8vbW9tZW50anMuY29tL2d1aWRlcy8jL3dhcm5pbmdzL3pvbmUvJywgZ2V0U2V0Wm9uZSk7XG5wcm90by5pc0RTVFNoaWZ0ZWQgPSBkZXByZWNhdGUoJ2lzRFNUU2hpZnRlZCBpcyBkZXByZWNhdGVkLiBTZWUgaHR0cDovL21vbWVudGpzLmNvbS9ndWlkZXMvIy93YXJuaW5ncy9kc3Qtc2hpZnRlZC8gZm9yIG1vcmUgaW5mb3JtYXRpb24nLCBpc0RheWxpZ2h0U2F2aW5nVGltZVNoaWZ0ZWQpO1xuXG5mdW5jdGlvbiBjcmVhdGVVbml4IChpbnB1dCkge1xuICAgIHJldHVybiBjcmVhdGVMb2NhbChpbnB1dCAqIDEwMDApO1xufVxuXG5mdW5jdGlvbiBjcmVhdGVJblpvbmUgKCkge1xuICAgIHJldHVybiBjcmVhdGVMb2NhbC5hcHBseShudWxsLCBhcmd1bWVudHMpLnBhcnNlWm9uZSgpO1xufVxuXG5mdW5jdGlvbiBwcmVQYXJzZVBvc3RGb3JtYXQgKHN0cmluZykge1xuICAgIHJldHVybiBzdHJpbmc7XG59XG5cbnZhciBwcm90byQxID0gTG9jYWxlLnByb3RvdHlwZTtcblxucHJvdG8kMS5jYWxlbmRhciAgICAgICAgPSBjYWxlbmRhcjtcbnByb3RvJDEubG9uZ0RhdGVGb3JtYXQgID0gbG9uZ0RhdGVGb3JtYXQ7XG5wcm90byQxLmludmFsaWREYXRlICAgICA9IGludmFsaWREYXRlO1xucHJvdG8kMS5vcmRpbmFsICAgICAgICAgPSBvcmRpbmFsO1xucHJvdG8kMS5wcmVwYXJzZSAgICAgICAgPSBwcmVQYXJzZVBvc3RGb3JtYXQ7XG5wcm90byQxLnBvc3Rmb3JtYXQgICAgICA9IHByZVBhcnNlUG9zdEZvcm1hdDtcbnByb3RvJDEucmVsYXRpdmVUaW1lICAgID0gcmVsYXRpdmVUaW1lO1xucHJvdG8kMS5wYXN0RnV0dXJlICAgICAgPSBwYXN0RnV0dXJlO1xucHJvdG8kMS5zZXQgICAgICAgICAgICAgPSBzZXQ7XG5cbi8vIE1vbnRoXG5wcm90byQxLm1vbnRocyAgICAgICAgICAgID0gICAgICAgIGxvY2FsZU1vbnRocztcbnByb3RvJDEubW9udGhzU2hvcnQgICAgICAgPSAgICAgICAgbG9jYWxlTW9udGhzU2hvcnQ7XG5wcm90byQxLm1vbnRoc1BhcnNlICAgICAgID0gICAgICAgIGxvY2FsZU1vbnRoc1BhcnNlO1xucHJvdG8kMS5tb250aHNSZWdleCAgICAgICA9IG1vbnRoc1JlZ2V4O1xucHJvdG8kMS5tb250aHNTaG9ydFJlZ2V4ICA9IG1vbnRoc1Nob3J0UmVnZXg7XG5cbi8vIFdlZWtcbnByb3RvJDEud2VlayA9IGxvY2FsZVdlZWs7XG5wcm90byQxLmZpcnN0RGF5T2ZZZWFyID0gbG9jYWxlRmlyc3REYXlPZlllYXI7XG5wcm90byQxLmZpcnN0RGF5T2ZXZWVrID0gbG9jYWxlRmlyc3REYXlPZldlZWs7XG5cbi8vIERheSBvZiBXZWVrXG5wcm90byQxLndlZWtkYXlzICAgICAgID0gICAgICAgIGxvY2FsZVdlZWtkYXlzO1xucHJvdG8kMS53ZWVrZGF5c01pbiAgICA9ICAgICAgICBsb2NhbGVXZWVrZGF5c01pbjtcbnByb3RvJDEud2Vla2RheXNTaG9ydCAgPSAgICAgICAgbG9jYWxlV2Vla2RheXNTaG9ydDtcbnByb3RvJDEud2Vla2RheXNQYXJzZSAgPSAgICAgICAgbG9jYWxlV2Vla2RheXNQYXJzZTtcblxucHJvdG8kMS53ZWVrZGF5c1JlZ2V4ICAgICAgID0gICAgICAgIHdlZWtkYXlzUmVnZXg7XG5wcm90byQxLndlZWtkYXlzU2hvcnRSZWdleCAgPSAgICAgICAgd2Vla2RheXNTaG9ydFJlZ2V4O1xucHJvdG8kMS53ZWVrZGF5c01pblJlZ2V4ICAgID0gICAgICAgIHdlZWtkYXlzTWluUmVnZXg7XG5cbi8vIEhvdXJzXG5wcm90byQxLmlzUE0gPSBsb2NhbGVJc1BNO1xucHJvdG8kMS5tZXJpZGllbSA9IGxvY2FsZU1lcmlkaWVtO1xuXG5mdW5jdGlvbiBnZXQkMSAoZm9ybWF0LCBpbmRleCwgZmllbGQsIHNldHRlcikge1xuICAgIHZhciBsb2NhbGUgPSBnZXRMb2NhbGUoKTtcbiAgICB2YXIgdXRjID0gY3JlYXRlVVRDKCkuc2V0KHNldHRlciwgaW5kZXgpO1xuICAgIHJldHVybiBsb2NhbGVbZmllbGRdKHV0YywgZm9ybWF0KTtcbn1cblxuZnVuY3Rpb24gbGlzdE1vbnRoc0ltcGwgKGZvcm1hdCwgaW5kZXgsIGZpZWxkKSB7XG4gICAgaWYgKGlzTnVtYmVyKGZvcm1hdCkpIHtcbiAgICAgICAgaW5kZXggPSBmb3JtYXQ7XG4gICAgICAgIGZvcm1hdCA9IHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICBmb3JtYXQgPSBmb3JtYXQgfHwgJyc7XG5cbiAgICBpZiAoaW5kZXggIT0gbnVsbCkge1xuICAgICAgICByZXR1cm4gZ2V0JDEoZm9ybWF0LCBpbmRleCwgZmllbGQsICdtb250aCcpO1xuICAgIH1cblxuICAgIHZhciBpO1xuICAgIHZhciBvdXQgPSBbXTtcbiAgICBmb3IgKGkgPSAwOyBpIDwgMTI7IGkrKykge1xuICAgICAgICBvdXRbaV0gPSBnZXQkMShmb3JtYXQsIGksIGZpZWxkLCAnbW9udGgnKTtcbiAgICB9XG4gICAgcmV0dXJuIG91dDtcbn1cblxuLy8gKClcbi8vICg1KVxuLy8gKGZtdCwgNSlcbi8vIChmbXQpXG4vLyAodHJ1ZSlcbi8vICh0cnVlLCA1KVxuLy8gKHRydWUsIGZtdCwgNSlcbi8vICh0cnVlLCBmbXQpXG5mdW5jdGlvbiBsaXN0V2Vla2RheXNJbXBsIChsb2NhbGVTb3J0ZWQsIGZvcm1hdCwgaW5kZXgsIGZpZWxkKSB7XG4gICAgaWYgKHR5cGVvZiBsb2NhbGVTb3J0ZWQgPT09ICdib29sZWFuJykge1xuICAgICAgICBpZiAoaXNOdW1iZXIoZm9ybWF0KSkge1xuICAgICAgICAgICAgaW5kZXggPSBmb3JtYXQ7XG4gICAgICAgICAgICBmb3JtYXQgPSB1bmRlZmluZWQ7XG4gICAgICAgIH1cblxuICAgICAgICBmb3JtYXQgPSBmb3JtYXQgfHwgJyc7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgZm9ybWF0ID0gbG9jYWxlU29ydGVkO1xuICAgICAgICBpbmRleCA9IGZvcm1hdDtcbiAgICAgICAgbG9jYWxlU29ydGVkID0gZmFsc2U7XG5cbiAgICAgICAgaWYgKGlzTnVtYmVyKGZvcm1hdCkpIHtcbiAgICAgICAgICAgIGluZGV4ID0gZm9ybWF0O1xuICAgICAgICAgICAgZm9ybWF0ID0gdW5kZWZpbmVkO1xuICAgICAgICB9XG5cbiAgICAgICAgZm9ybWF0ID0gZm9ybWF0IHx8ICcnO1xuICAgIH1cblxuICAgIHZhciBsb2NhbGUgPSBnZXRMb2NhbGUoKSxcbiAgICAgICAgc2hpZnQgPSBsb2NhbGVTb3J0ZWQgPyBsb2NhbGUuX3dlZWsuZG93IDogMDtcblxuICAgIGlmIChpbmRleCAhPSBudWxsKSB7XG4gICAgICAgIHJldHVybiBnZXQkMShmb3JtYXQsIChpbmRleCArIHNoaWZ0KSAlIDcsIGZpZWxkLCAnZGF5Jyk7XG4gICAgfVxuXG4gICAgdmFyIGk7XG4gICAgdmFyIG91dCA9IFtdO1xuICAgIGZvciAoaSA9IDA7IGkgPCA3OyBpKyspIHtcbiAgICAgICAgb3V0W2ldID0gZ2V0JDEoZm9ybWF0LCAoaSArIHNoaWZ0KSAlIDcsIGZpZWxkLCAnZGF5Jyk7XG4gICAgfVxuICAgIHJldHVybiBvdXQ7XG59XG5cbmZ1bmN0aW9uIGxpc3RNb250aHMgKGZvcm1hdCwgaW5kZXgpIHtcbiAgICByZXR1cm4gbGlzdE1vbnRoc0ltcGwoZm9ybWF0LCBpbmRleCwgJ21vbnRocycpO1xufVxuXG5mdW5jdGlvbiBsaXN0TW9udGhzU2hvcnQgKGZvcm1hdCwgaW5kZXgpIHtcbiAgICByZXR1cm4gbGlzdE1vbnRoc0ltcGwoZm9ybWF0LCBpbmRleCwgJ21vbnRoc1Nob3J0Jyk7XG59XG5cbmZ1bmN0aW9uIGxpc3RXZWVrZGF5cyAobG9jYWxlU29ydGVkLCBmb3JtYXQsIGluZGV4KSB7XG4gICAgcmV0dXJuIGxpc3RXZWVrZGF5c0ltcGwobG9jYWxlU29ydGVkLCBmb3JtYXQsIGluZGV4LCAnd2Vla2RheXMnKTtcbn1cblxuZnVuY3Rpb24gbGlzdFdlZWtkYXlzU2hvcnQgKGxvY2FsZVNvcnRlZCwgZm9ybWF0LCBpbmRleCkge1xuICAgIHJldHVybiBsaXN0V2Vla2RheXNJbXBsKGxvY2FsZVNvcnRlZCwgZm9ybWF0LCBpbmRleCwgJ3dlZWtkYXlzU2hvcnQnKTtcbn1cblxuZnVuY3Rpb24gbGlzdFdlZWtkYXlzTWluIChsb2NhbGVTb3J0ZWQsIGZvcm1hdCwgaW5kZXgpIHtcbiAgICByZXR1cm4gbGlzdFdlZWtkYXlzSW1wbChsb2NhbGVTb3J0ZWQsIGZvcm1hdCwgaW5kZXgsICd3ZWVrZGF5c01pbicpO1xufVxuXG5nZXRTZXRHbG9iYWxMb2NhbGUoJ2VuJywge1xuICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfSh0aHxzdHxuZHxyZCkvLFxuICAgIG9yZGluYWwgOiBmdW5jdGlvbiAobnVtYmVyKSB7XG4gICAgICAgIHZhciBiID0gbnVtYmVyICUgMTAsXG4gICAgICAgICAgICBvdXRwdXQgPSAodG9JbnQobnVtYmVyICUgMTAwIC8gMTApID09PSAxKSA/ICd0aCcgOlxuICAgICAgICAgICAgKGIgPT09IDEpID8gJ3N0JyA6XG4gICAgICAgICAgICAoYiA9PT0gMikgPyAnbmQnIDpcbiAgICAgICAgICAgIChiID09PSAzKSA/ICdyZCcgOiAndGgnO1xuICAgICAgICByZXR1cm4gbnVtYmVyICsgb3V0cHV0O1xuICAgIH1cbn0pO1xuXG4vLyBTaWRlIGVmZmVjdCBpbXBvcnRzXG5ob29rcy5sYW5nID0gZGVwcmVjYXRlKCdtb21lbnQubGFuZyBpcyBkZXByZWNhdGVkLiBVc2UgbW9tZW50LmxvY2FsZSBpbnN0ZWFkLicsIGdldFNldEdsb2JhbExvY2FsZSk7XG5ob29rcy5sYW5nRGF0YSA9IGRlcHJlY2F0ZSgnbW9tZW50LmxhbmdEYXRhIGlzIGRlcHJlY2F0ZWQuIFVzZSBtb21lbnQubG9jYWxlRGF0YSBpbnN0ZWFkLicsIGdldExvY2FsZSk7XG5cbnZhciBtYXRoQWJzID0gTWF0aC5hYnM7XG5cbmZ1bmN0aW9uIGFicyAoKSB7XG4gICAgdmFyIGRhdGEgICAgICAgICAgID0gdGhpcy5fZGF0YTtcblxuICAgIHRoaXMuX21pbGxpc2Vjb25kcyA9IG1hdGhBYnModGhpcy5fbWlsbGlzZWNvbmRzKTtcbiAgICB0aGlzLl9kYXlzICAgICAgICAgPSBtYXRoQWJzKHRoaXMuX2RheXMpO1xuICAgIHRoaXMuX21vbnRocyAgICAgICA9IG1hdGhBYnModGhpcy5fbW9udGhzKTtcblxuICAgIGRhdGEubWlsbGlzZWNvbmRzICA9IG1hdGhBYnMoZGF0YS5taWxsaXNlY29uZHMpO1xuICAgIGRhdGEuc2Vjb25kcyAgICAgICA9IG1hdGhBYnMoZGF0YS5zZWNvbmRzKTtcbiAgICBkYXRhLm1pbnV0ZXMgICAgICAgPSBtYXRoQWJzKGRhdGEubWludXRlcyk7XG4gICAgZGF0YS5ob3VycyAgICAgICAgID0gbWF0aEFicyhkYXRhLmhvdXJzKTtcbiAgICBkYXRhLm1vbnRocyAgICAgICAgPSBtYXRoQWJzKGRhdGEubW9udGhzKTtcbiAgICBkYXRhLnllYXJzICAgICAgICAgPSBtYXRoQWJzKGRhdGEueWVhcnMpO1xuXG4gICAgcmV0dXJuIHRoaXM7XG59XG5cbmZ1bmN0aW9uIGFkZFN1YnRyYWN0JDEgKGR1cmF0aW9uLCBpbnB1dCwgdmFsdWUsIGRpcmVjdGlvbikge1xuICAgIHZhciBvdGhlciA9IGNyZWF0ZUR1cmF0aW9uKGlucHV0LCB2YWx1ZSk7XG5cbiAgICBkdXJhdGlvbi5fbWlsbGlzZWNvbmRzICs9IGRpcmVjdGlvbiAqIG90aGVyLl9taWxsaXNlY29uZHM7XG4gICAgZHVyYXRpb24uX2RheXMgICAgICAgICArPSBkaXJlY3Rpb24gKiBvdGhlci5fZGF5cztcbiAgICBkdXJhdGlvbi5fbW9udGhzICAgICAgICs9IGRpcmVjdGlvbiAqIG90aGVyLl9tb250aHM7XG5cbiAgICByZXR1cm4gZHVyYXRpb24uX2J1YmJsZSgpO1xufVxuXG4vLyBzdXBwb3J0cyBvbmx5IDIuMC1zdHlsZSBhZGQoMSwgJ3MnKSBvciBhZGQoZHVyYXRpb24pXG5mdW5jdGlvbiBhZGQkMSAoaW5wdXQsIHZhbHVlKSB7XG4gICAgcmV0dXJuIGFkZFN1YnRyYWN0JDEodGhpcywgaW5wdXQsIHZhbHVlLCAxKTtcbn1cblxuLy8gc3VwcG9ydHMgb25seSAyLjAtc3R5bGUgc3VidHJhY3QoMSwgJ3MnKSBvciBzdWJ0cmFjdChkdXJhdGlvbilcbmZ1bmN0aW9uIHN1YnRyYWN0JDEgKGlucHV0LCB2YWx1ZSkge1xuICAgIHJldHVybiBhZGRTdWJ0cmFjdCQxKHRoaXMsIGlucHV0LCB2YWx1ZSwgLTEpO1xufVxuXG5mdW5jdGlvbiBhYnNDZWlsIChudW1iZXIpIHtcbiAgICBpZiAobnVtYmVyIDwgMCkge1xuICAgICAgICByZXR1cm4gTWF0aC5mbG9vcihudW1iZXIpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBNYXRoLmNlaWwobnVtYmVyKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGJ1YmJsZSAoKSB7XG4gICAgdmFyIG1pbGxpc2Vjb25kcyA9IHRoaXMuX21pbGxpc2Vjb25kcztcbiAgICB2YXIgZGF5cyAgICAgICAgID0gdGhpcy5fZGF5cztcbiAgICB2YXIgbW9udGhzICAgICAgID0gdGhpcy5fbW9udGhzO1xuICAgIHZhciBkYXRhICAgICAgICAgPSB0aGlzLl9kYXRhO1xuICAgIHZhciBzZWNvbmRzLCBtaW51dGVzLCBob3VycywgeWVhcnMsIG1vbnRoc0Zyb21EYXlzO1xuXG4gICAgLy8gaWYgd2UgaGF2ZSBhIG1peCBvZiBwb3NpdGl2ZSBhbmQgbmVnYXRpdmUgdmFsdWVzLCBidWJibGUgZG93biBmaXJzdFxuICAgIC8vIGNoZWNrOiBodHRwczovL2dpdGh1Yi5jb20vbW9tZW50L21vbWVudC9pc3N1ZXMvMjE2NlxuICAgIGlmICghKChtaWxsaXNlY29uZHMgPj0gMCAmJiBkYXlzID49IDAgJiYgbW9udGhzID49IDApIHx8XG4gICAgICAgICAgICAobWlsbGlzZWNvbmRzIDw9IDAgJiYgZGF5cyA8PSAwICYmIG1vbnRocyA8PSAwKSkpIHtcbiAgICAgICAgbWlsbGlzZWNvbmRzICs9IGFic0NlaWwobW9udGhzVG9EYXlzKG1vbnRocykgKyBkYXlzKSAqIDg2NGU1O1xuICAgICAgICBkYXlzID0gMDtcbiAgICAgICAgbW9udGhzID0gMDtcbiAgICB9XG5cbiAgICAvLyBUaGUgZm9sbG93aW5nIGNvZGUgYnViYmxlcyB1cCB2YWx1ZXMsIHNlZSB0aGUgdGVzdHMgZm9yXG4gICAgLy8gZXhhbXBsZXMgb2Ygd2hhdCB0aGF0IG1lYW5zLlxuICAgIGRhdGEubWlsbGlzZWNvbmRzID0gbWlsbGlzZWNvbmRzICUgMTAwMDtcblxuICAgIHNlY29uZHMgICAgICAgICAgID0gYWJzRmxvb3IobWlsbGlzZWNvbmRzIC8gMTAwMCk7XG4gICAgZGF0YS5zZWNvbmRzICAgICAgPSBzZWNvbmRzICUgNjA7XG5cbiAgICBtaW51dGVzICAgICAgICAgICA9IGFic0Zsb29yKHNlY29uZHMgLyA2MCk7XG4gICAgZGF0YS5taW51dGVzICAgICAgPSBtaW51dGVzICUgNjA7XG5cbiAgICBob3VycyAgICAgICAgICAgICA9IGFic0Zsb29yKG1pbnV0ZXMgLyA2MCk7XG4gICAgZGF0YS5ob3VycyAgICAgICAgPSBob3VycyAlIDI0O1xuXG4gICAgZGF5cyArPSBhYnNGbG9vcihob3VycyAvIDI0KTtcblxuICAgIC8vIGNvbnZlcnQgZGF5cyB0byBtb250aHNcbiAgICBtb250aHNGcm9tRGF5cyA9IGFic0Zsb29yKGRheXNUb01vbnRocyhkYXlzKSk7XG4gICAgbW9udGhzICs9IG1vbnRoc0Zyb21EYXlzO1xuICAgIGRheXMgLT0gYWJzQ2VpbChtb250aHNUb0RheXMobW9udGhzRnJvbURheXMpKTtcblxuICAgIC8vIDEyIG1vbnRocyAtPiAxIHllYXJcbiAgICB5ZWFycyA9IGFic0Zsb29yKG1vbnRocyAvIDEyKTtcbiAgICBtb250aHMgJT0gMTI7XG5cbiAgICBkYXRhLmRheXMgICA9IGRheXM7XG4gICAgZGF0YS5tb250aHMgPSBtb250aHM7XG4gICAgZGF0YS55ZWFycyAgPSB5ZWFycztcblxuICAgIHJldHVybiB0aGlzO1xufVxuXG5mdW5jdGlvbiBkYXlzVG9Nb250aHMgKGRheXMpIHtcbiAgICAvLyA0MDAgeWVhcnMgaGF2ZSAxNDYwOTcgZGF5cyAodGFraW5nIGludG8gYWNjb3VudCBsZWFwIHllYXIgcnVsZXMpXG4gICAgLy8gNDAwIHllYXJzIGhhdmUgMTIgbW9udGhzID09PSA0ODAwXG4gICAgcmV0dXJuIGRheXMgKiA0ODAwIC8gMTQ2MDk3O1xufVxuXG5mdW5jdGlvbiBtb250aHNUb0RheXMgKG1vbnRocykge1xuICAgIC8vIHRoZSByZXZlcnNlIG9mIGRheXNUb01vbnRoc1xuICAgIHJldHVybiBtb250aHMgKiAxNDYwOTcgLyA0ODAwO1xufVxuXG5mdW5jdGlvbiBhcyAodW5pdHMpIHtcbiAgICBpZiAoIXRoaXMuaXNWYWxpZCgpKSB7XG4gICAgICAgIHJldHVybiBOYU47XG4gICAgfVxuICAgIHZhciBkYXlzO1xuICAgIHZhciBtb250aHM7XG4gICAgdmFyIG1pbGxpc2Vjb25kcyA9IHRoaXMuX21pbGxpc2Vjb25kcztcblxuICAgIHVuaXRzID0gbm9ybWFsaXplVW5pdHModW5pdHMpO1xuXG4gICAgaWYgKHVuaXRzID09PSAnbW9udGgnIHx8IHVuaXRzID09PSAneWVhcicpIHtcbiAgICAgICAgZGF5cyAgID0gdGhpcy5fZGF5cyAgICsgbWlsbGlzZWNvbmRzIC8gODY0ZTU7XG4gICAgICAgIG1vbnRocyA9IHRoaXMuX21vbnRocyArIGRheXNUb01vbnRocyhkYXlzKTtcbiAgICAgICAgcmV0dXJuIHVuaXRzID09PSAnbW9udGgnID8gbW9udGhzIDogbW9udGhzIC8gMTI7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgLy8gaGFuZGxlIG1pbGxpc2Vjb25kcyBzZXBhcmF0ZWx5IGJlY2F1c2Ugb2YgZmxvYXRpbmcgcG9pbnQgbWF0aCBlcnJvcnMgKGlzc3VlICMxODY3KVxuICAgICAgICBkYXlzID0gdGhpcy5fZGF5cyArIE1hdGgucm91bmQobW9udGhzVG9EYXlzKHRoaXMuX21vbnRocykpO1xuICAgICAgICBzd2l0Y2ggKHVuaXRzKSB7XG4gICAgICAgICAgICBjYXNlICd3ZWVrJyAgIDogcmV0dXJuIGRheXMgLyA3ICAgICArIG1pbGxpc2Vjb25kcyAvIDYwNDhlNTtcbiAgICAgICAgICAgIGNhc2UgJ2RheScgICAgOiByZXR1cm4gZGF5cyAgICAgICAgICsgbWlsbGlzZWNvbmRzIC8gODY0ZTU7XG4gICAgICAgICAgICBjYXNlICdob3VyJyAgIDogcmV0dXJuIGRheXMgKiAyNCAgICArIG1pbGxpc2Vjb25kcyAvIDM2ZTU7XG4gICAgICAgICAgICBjYXNlICdtaW51dGUnIDogcmV0dXJuIGRheXMgKiAxNDQwICArIG1pbGxpc2Vjb25kcyAvIDZlNDtcbiAgICAgICAgICAgIGNhc2UgJ3NlY29uZCcgOiByZXR1cm4gZGF5cyAqIDg2NDAwICsgbWlsbGlzZWNvbmRzIC8gMTAwMDtcbiAgICAgICAgICAgIC8vIE1hdGguZmxvb3IgcHJldmVudHMgZmxvYXRpbmcgcG9pbnQgbWF0aCBlcnJvcnMgaGVyZVxuICAgICAgICAgICAgY2FzZSAnbWlsbGlzZWNvbmQnOiByZXR1cm4gTWF0aC5mbG9vcihkYXlzICogODY0ZTUpICsgbWlsbGlzZWNvbmRzO1xuICAgICAgICAgICAgZGVmYXVsdDogdGhyb3cgbmV3IEVycm9yKCdVbmtub3duIHVuaXQgJyArIHVuaXRzKTtcbiAgICAgICAgfVxuICAgIH1cbn1cblxuLy8gVE9ETzogVXNlIHRoaXMuYXMoJ21zJyk/XG5mdW5jdGlvbiB2YWx1ZU9mJDEgKCkge1xuICAgIGlmICghdGhpcy5pc1ZhbGlkKCkpIHtcbiAgICAgICAgcmV0dXJuIE5hTjtcbiAgICB9XG4gICAgcmV0dXJuIChcbiAgICAgICAgdGhpcy5fbWlsbGlzZWNvbmRzICtcbiAgICAgICAgdGhpcy5fZGF5cyAqIDg2NGU1ICtcbiAgICAgICAgKHRoaXMuX21vbnRocyAlIDEyKSAqIDI1OTJlNiArXG4gICAgICAgIHRvSW50KHRoaXMuX21vbnRocyAvIDEyKSAqIDMxNTM2ZTZcbiAgICApO1xufVxuXG5mdW5jdGlvbiBtYWtlQXMgKGFsaWFzKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYXMoYWxpYXMpO1xuICAgIH07XG59XG5cbnZhciBhc01pbGxpc2Vjb25kcyA9IG1ha2VBcygnbXMnKTtcbnZhciBhc1NlY29uZHMgICAgICA9IG1ha2VBcygncycpO1xudmFyIGFzTWludXRlcyAgICAgID0gbWFrZUFzKCdtJyk7XG52YXIgYXNIb3VycyAgICAgICAgPSBtYWtlQXMoJ2gnKTtcbnZhciBhc0RheXMgICAgICAgICA9IG1ha2VBcygnZCcpO1xudmFyIGFzV2Vla3MgICAgICAgID0gbWFrZUFzKCd3Jyk7XG52YXIgYXNNb250aHMgICAgICAgPSBtYWtlQXMoJ00nKTtcbnZhciBhc1llYXJzICAgICAgICA9IG1ha2VBcygneScpO1xuXG5mdW5jdGlvbiBjbG9uZSQxICgpIHtcbiAgICByZXR1cm4gY3JlYXRlRHVyYXRpb24odGhpcyk7XG59XG5cbmZ1bmN0aW9uIGdldCQyICh1bml0cykge1xuICAgIHVuaXRzID0gbm9ybWFsaXplVW5pdHModW5pdHMpO1xuICAgIHJldHVybiB0aGlzLmlzVmFsaWQoKSA/IHRoaXNbdW5pdHMgKyAncyddKCkgOiBOYU47XG59XG5cbmZ1bmN0aW9uIG1ha2VHZXR0ZXIobmFtZSkge1xuICAgIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmlzVmFsaWQoKSA/IHRoaXMuX2RhdGFbbmFtZV0gOiBOYU47XG4gICAgfTtcbn1cblxudmFyIG1pbGxpc2Vjb25kcyA9IG1ha2VHZXR0ZXIoJ21pbGxpc2Vjb25kcycpO1xudmFyIHNlY29uZHMgICAgICA9IG1ha2VHZXR0ZXIoJ3NlY29uZHMnKTtcbnZhciBtaW51dGVzICAgICAgPSBtYWtlR2V0dGVyKCdtaW51dGVzJyk7XG52YXIgaG91cnMgICAgICAgID0gbWFrZUdldHRlcignaG91cnMnKTtcbnZhciBkYXlzICAgICAgICAgPSBtYWtlR2V0dGVyKCdkYXlzJyk7XG52YXIgbW9udGhzICAgICAgID0gbWFrZUdldHRlcignbW9udGhzJyk7XG52YXIgeWVhcnMgICAgICAgID0gbWFrZUdldHRlcigneWVhcnMnKTtcblxuZnVuY3Rpb24gd2Vla3MgKCkge1xuICAgIHJldHVybiBhYnNGbG9vcih0aGlzLmRheXMoKSAvIDcpO1xufVxuXG52YXIgcm91bmQgPSBNYXRoLnJvdW5kO1xudmFyIHRocmVzaG9sZHMgPSB7XG4gICAgc3M6IDQ0LCAgICAgICAgIC8vIGEgZmV3IHNlY29uZHMgdG8gc2Vjb25kc1xuICAgIHMgOiA0NSwgICAgICAgICAvLyBzZWNvbmRzIHRvIG1pbnV0ZVxuICAgIG0gOiA0NSwgICAgICAgICAvLyBtaW51dGVzIHRvIGhvdXJcbiAgICBoIDogMjIsICAgICAgICAgLy8gaG91cnMgdG8gZGF5XG4gICAgZCA6IDI2LCAgICAgICAgIC8vIGRheXMgdG8gbW9udGhcbiAgICBNIDogMTEgICAgICAgICAgLy8gbW9udGhzIHRvIHllYXJcbn07XG5cbi8vIGhlbHBlciBmdW5jdGlvbiBmb3IgbW9tZW50LmZuLmZyb20sIG1vbWVudC5mbi5mcm9tTm93LCBhbmQgbW9tZW50LmR1cmF0aW9uLmZuLmh1bWFuaXplXG5mdW5jdGlvbiBzdWJzdGl0dXRlVGltZUFnbyhzdHJpbmcsIG51bWJlciwgd2l0aG91dFN1ZmZpeCwgaXNGdXR1cmUsIGxvY2FsZSkge1xuICAgIHJldHVybiBsb2NhbGUucmVsYXRpdmVUaW1lKG51bWJlciB8fCAxLCAhIXdpdGhvdXRTdWZmaXgsIHN0cmluZywgaXNGdXR1cmUpO1xufVxuXG5mdW5jdGlvbiByZWxhdGl2ZVRpbWUkMSAocG9zTmVnRHVyYXRpb24sIHdpdGhvdXRTdWZmaXgsIGxvY2FsZSkge1xuICAgIHZhciBkdXJhdGlvbiA9IGNyZWF0ZUR1cmF0aW9uKHBvc05lZ0R1cmF0aW9uKS5hYnMoKTtcbiAgICB2YXIgc2Vjb25kcyAgPSByb3VuZChkdXJhdGlvbi5hcygncycpKTtcbiAgICB2YXIgbWludXRlcyAgPSByb3VuZChkdXJhdGlvbi5hcygnbScpKTtcbiAgICB2YXIgaG91cnMgICAgPSByb3VuZChkdXJhdGlvbi5hcygnaCcpKTtcbiAgICB2YXIgZGF5cyAgICAgPSByb3VuZChkdXJhdGlvbi5hcygnZCcpKTtcbiAgICB2YXIgbW9udGhzICAgPSByb3VuZChkdXJhdGlvbi5hcygnTScpKTtcbiAgICB2YXIgeWVhcnMgICAgPSByb3VuZChkdXJhdGlvbi5hcygneScpKTtcblxuICAgIHZhciBhID0gc2Vjb25kcyA8PSB0aHJlc2hvbGRzLnNzICYmIFsncycsIHNlY29uZHNdICB8fFxuICAgICAgICAgICAgc2Vjb25kcyA8IHRocmVzaG9sZHMucyAgICYmIFsnc3MnLCBzZWNvbmRzXSB8fFxuICAgICAgICAgICAgbWludXRlcyA8PSAxICAgICAgICAgICAgICYmIFsnbSddICAgICAgICAgICB8fFxuICAgICAgICAgICAgbWludXRlcyA8IHRocmVzaG9sZHMubSAgICYmIFsnbW0nLCBtaW51dGVzXSB8fFxuICAgICAgICAgICAgaG91cnMgICA8PSAxICAgICAgICAgICAgICYmIFsnaCddICAgICAgICAgICB8fFxuICAgICAgICAgICAgaG91cnMgICA8IHRocmVzaG9sZHMuaCAgICYmIFsnaGgnLCBob3Vyc10gICB8fFxuICAgICAgICAgICAgZGF5cyAgICA8PSAxICAgICAgICAgICAgICYmIFsnZCddICAgICAgICAgICB8fFxuICAgICAgICAgICAgZGF5cyAgICA8IHRocmVzaG9sZHMuZCAgICYmIFsnZGQnLCBkYXlzXSAgICB8fFxuICAgICAgICAgICAgbW9udGhzICA8PSAxICAgICAgICAgICAgICYmIFsnTSddICAgICAgICAgICB8fFxuICAgICAgICAgICAgbW9udGhzICA8IHRocmVzaG9sZHMuTSAgICYmIFsnTU0nLCBtb250aHNdICB8fFxuICAgICAgICAgICAgeWVhcnMgICA8PSAxICAgICAgICAgICAgICYmIFsneSddICAgICAgICAgICB8fCBbJ3l5JywgeWVhcnNdO1xuXG4gICAgYVsyXSA9IHdpdGhvdXRTdWZmaXg7XG4gICAgYVszXSA9ICtwb3NOZWdEdXJhdGlvbiA+IDA7XG4gICAgYVs0XSA9IGxvY2FsZTtcbiAgICByZXR1cm4gc3Vic3RpdHV0ZVRpbWVBZ28uYXBwbHkobnVsbCwgYSk7XG59XG5cbi8vIFRoaXMgZnVuY3Rpb24gYWxsb3dzIHlvdSB0byBzZXQgdGhlIHJvdW5kaW5nIGZ1bmN0aW9uIGZvciByZWxhdGl2ZSB0aW1lIHN0cmluZ3NcbmZ1bmN0aW9uIGdldFNldFJlbGF0aXZlVGltZVJvdW5kaW5nIChyb3VuZGluZ0Z1bmN0aW9uKSB7XG4gICAgaWYgKHJvdW5kaW5nRnVuY3Rpb24gPT09IHVuZGVmaW5lZCkge1xuICAgICAgICByZXR1cm4gcm91bmQ7XG4gICAgfVxuICAgIGlmICh0eXBlb2Yocm91bmRpbmdGdW5jdGlvbikgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgcm91bmQgPSByb3VuZGluZ0Z1bmN0aW9uO1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xufVxuXG4vLyBUaGlzIGZ1bmN0aW9uIGFsbG93cyB5b3UgdG8gc2V0IGEgdGhyZXNob2xkIGZvciByZWxhdGl2ZSB0aW1lIHN0cmluZ3NcbmZ1bmN0aW9uIGdldFNldFJlbGF0aXZlVGltZVRocmVzaG9sZCAodGhyZXNob2xkLCBsaW1pdCkge1xuICAgIGlmICh0aHJlc2hvbGRzW3RocmVzaG9sZF0gPT09IHVuZGVmaW5lZCkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIGlmIChsaW1pdCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHJldHVybiB0aHJlc2hvbGRzW3RocmVzaG9sZF07XG4gICAgfVxuICAgIHRocmVzaG9sZHNbdGhyZXNob2xkXSA9IGxpbWl0O1xuICAgIGlmICh0aHJlc2hvbGQgPT09ICdzJykge1xuICAgICAgICB0aHJlc2hvbGRzLnNzID0gbGltaXQgLSAxO1xuICAgIH1cbiAgICByZXR1cm4gdHJ1ZTtcbn1cblxuZnVuY3Rpb24gaHVtYW5pemUgKHdpdGhTdWZmaXgpIHtcbiAgICBpZiAoIXRoaXMuaXNWYWxpZCgpKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmxvY2FsZURhdGEoKS5pbnZhbGlkRGF0ZSgpO1xuICAgIH1cblxuICAgIHZhciBsb2NhbGUgPSB0aGlzLmxvY2FsZURhdGEoKTtcbiAgICB2YXIgb3V0cHV0ID0gcmVsYXRpdmVUaW1lJDEodGhpcywgIXdpdGhTdWZmaXgsIGxvY2FsZSk7XG5cbiAgICBpZiAod2l0aFN1ZmZpeCkge1xuICAgICAgICBvdXRwdXQgPSBsb2NhbGUucGFzdEZ1dHVyZSgrdGhpcywgb3V0cHV0KTtcbiAgICB9XG5cbiAgICByZXR1cm4gbG9jYWxlLnBvc3Rmb3JtYXQob3V0cHV0KTtcbn1cblxudmFyIGFicyQxID0gTWF0aC5hYnM7XG5cbmZ1bmN0aW9uIHNpZ24oeCkge1xuICAgIHJldHVybiAoKHggPiAwKSAtICh4IDwgMCkpIHx8ICt4O1xufVxuXG5mdW5jdGlvbiB0b0lTT1N0cmluZyQxKCkge1xuICAgIC8vIGZvciBJU08gc3RyaW5ncyB3ZSBkbyBub3QgdXNlIHRoZSBub3JtYWwgYnViYmxpbmcgcnVsZXM6XG4gICAgLy8gICogbWlsbGlzZWNvbmRzIGJ1YmJsZSB1cCB1bnRpbCB0aGV5IGJlY29tZSBob3Vyc1xuICAgIC8vICAqIGRheXMgZG8gbm90IGJ1YmJsZSBhdCBhbGxcbiAgICAvLyAgKiBtb250aHMgYnViYmxlIHVwIHVudGlsIHRoZXkgYmVjb21lIHllYXJzXG4gICAgLy8gVGhpcyBpcyBiZWNhdXNlIHRoZXJlIGlzIG5vIGNvbnRleHQtZnJlZSBjb252ZXJzaW9uIGJldHdlZW4gaG91cnMgYW5kIGRheXNcbiAgICAvLyAodGhpbmsgb2YgY2xvY2sgY2hhbmdlcylcbiAgICAvLyBhbmQgYWxzbyBub3QgYmV0d2VlbiBkYXlzIGFuZCBtb250aHMgKDI4LTMxIGRheXMgcGVyIG1vbnRoKVxuICAgIGlmICghdGhpcy5pc1ZhbGlkKCkpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubG9jYWxlRGF0YSgpLmludmFsaWREYXRlKCk7XG4gICAgfVxuXG4gICAgdmFyIHNlY29uZHMgPSBhYnMkMSh0aGlzLl9taWxsaXNlY29uZHMpIC8gMTAwMDtcbiAgICB2YXIgZGF5cyAgICAgICAgID0gYWJzJDEodGhpcy5fZGF5cyk7XG4gICAgdmFyIG1vbnRocyAgICAgICA9IGFicyQxKHRoaXMuX21vbnRocyk7XG4gICAgdmFyIG1pbnV0ZXMsIGhvdXJzLCB5ZWFycztcblxuICAgIC8vIDM2MDAgc2Vjb25kcyAtPiA2MCBtaW51dGVzIC0+IDEgaG91clxuICAgIG1pbnV0ZXMgICAgICAgICAgID0gYWJzRmxvb3Ioc2Vjb25kcyAvIDYwKTtcbiAgICBob3VycyAgICAgICAgICAgICA9IGFic0Zsb29yKG1pbnV0ZXMgLyA2MCk7XG4gICAgc2Vjb25kcyAlPSA2MDtcbiAgICBtaW51dGVzICU9IDYwO1xuXG4gICAgLy8gMTIgbW9udGhzIC0+IDEgeWVhclxuICAgIHllYXJzICA9IGFic0Zsb29yKG1vbnRocyAvIDEyKTtcbiAgICBtb250aHMgJT0gMTI7XG5cblxuICAgIC8vIGluc3BpcmVkIGJ5IGh0dHBzOi8vZ2l0aHViLmNvbS9kb3JkaWxsZS9tb21lbnQtaXNvZHVyYXRpb24vYmxvYi9tYXN0ZXIvbW9tZW50Lmlzb2R1cmF0aW9uLmpzXG4gICAgdmFyIFkgPSB5ZWFycztcbiAgICB2YXIgTSA9IG1vbnRocztcbiAgICB2YXIgRCA9IGRheXM7XG4gICAgdmFyIGggPSBob3VycztcbiAgICB2YXIgbSA9IG1pbnV0ZXM7XG4gICAgdmFyIHMgPSBzZWNvbmRzID8gc2Vjb25kcy50b0ZpeGVkKDMpLnJlcGxhY2UoL1xcLj8wKyQvLCAnJykgOiAnJztcbiAgICB2YXIgdG90YWwgPSB0aGlzLmFzU2Vjb25kcygpO1xuXG4gICAgaWYgKCF0b3RhbCkge1xuICAgICAgICAvLyB0aGlzIGlzIHRoZSBzYW1lIGFzIEMjJ3MgKE5vZGEpIGFuZCBweXRob24gKGlzb2RhdGUpLi4uXG4gICAgICAgIC8vIGJ1dCBub3Qgb3RoZXIgSlMgKGdvb2cuZGF0ZSlcbiAgICAgICAgcmV0dXJuICdQMEQnO1xuICAgIH1cblxuICAgIHZhciB0b3RhbFNpZ24gPSB0b3RhbCA8IDAgPyAnLScgOiAnJztcbiAgICB2YXIgeW1TaWduID0gc2lnbih0aGlzLl9tb250aHMpICE9PSBzaWduKHRvdGFsKSA/ICctJyA6ICcnO1xuICAgIHZhciBkYXlzU2lnbiA9IHNpZ24odGhpcy5fZGF5cykgIT09IHNpZ24odG90YWwpID8gJy0nIDogJyc7XG4gICAgdmFyIGhtc1NpZ24gPSBzaWduKHRoaXMuX21pbGxpc2Vjb25kcykgIT09IHNpZ24odG90YWwpID8gJy0nIDogJyc7XG5cbiAgICByZXR1cm4gdG90YWxTaWduICsgJ1AnICtcbiAgICAgICAgKFkgPyB5bVNpZ24gKyBZICsgJ1knIDogJycpICtcbiAgICAgICAgKE0gPyB5bVNpZ24gKyBNICsgJ00nIDogJycpICtcbiAgICAgICAgKEQgPyBkYXlzU2lnbiArIEQgKyAnRCcgOiAnJykgK1xuICAgICAgICAoKGggfHwgbSB8fCBzKSA/ICdUJyA6ICcnKSArXG4gICAgICAgIChoID8gaG1zU2lnbiArIGggKyAnSCcgOiAnJykgK1xuICAgICAgICAobSA/IGhtc1NpZ24gKyBtICsgJ00nIDogJycpICtcbiAgICAgICAgKHMgPyBobXNTaWduICsgcyArICdTJyA6ICcnKTtcbn1cblxudmFyIHByb3RvJDIgPSBEdXJhdGlvbi5wcm90b3R5cGU7XG5cbnByb3RvJDIuaXNWYWxpZCAgICAgICAgPSBpc1ZhbGlkJDE7XG5wcm90byQyLmFicyAgICAgICAgICAgID0gYWJzO1xucHJvdG8kMi5hZGQgICAgICAgICAgICA9IGFkZCQxO1xucHJvdG8kMi5zdWJ0cmFjdCAgICAgICA9IHN1YnRyYWN0JDE7XG5wcm90byQyLmFzICAgICAgICAgICAgID0gYXM7XG5wcm90byQyLmFzTWlsbGlzZWNvbmRzID0gYXNNaWxsaXNlY29uZHM7XG5wcm90byQyLmFzU2Vjb25kcyAgICAgID0gYXNTZWNvbmRzO1xucHJvdG8kMi5hc01pbnV0ZXMgICAgICA9IGFzTWludXRlcztcbnByb3RvJDIuYXNIb3VycyAgICAgICAgPSBhc0hvdXJzO1xucHJvdG8kMi5hc0RheXMgICAgICAgICA9IGFzRGF5cztcbnByb3RvJDIuYXNXZWVrcyAgICAgICAgPSBhc1dlZWtzO1xucHJvdG8kMi5hc01vbnRocyAgICAgICA9IGFzTW9udGhzO1xucHJvdG8kMi5hc1llYXJzICAgICAgICA9IGFzWWVhcnM7XG5wcm90byQyLnZhbHVlT2YgICAgICAgID0gdmFsdWVPZiQxO1xucHJvdG8kMi5fYnViYmxlICAgICAgICA9IGJ1YmJsZTtcbnByb3RvJDIuY2xvbmUgICAgICAgICAgPSBjbG9uZSQxO1xucHJvdG8kMi5nZXQgICAgICAgICAgICA9IGdldCQyO1xucHJvdG8kMi5taWxsaXNlY29uZHMgICA9IG1pbGxpc2Vjb25kcztcbnByb3RvJDIuc2Vjb25kcyAgICAgICAgPSBzZWNvbmRzO1xucHJvdG8kMi5taW51dGVzICAgICAgICA9IG1pbnV0ZXM7XG5wcm90byQyLmhvdXJzICAgICAgICAgID0gaG91cnM7XG5wcm90byQyLmRheXMgICAgICAgICAgID0gZGF5cztcbnByb3RvJDIud2Vla3MgICAgICAgICAgPSB3ZWVrcztcbnByb3RvJDIubW9udGhzICAgICAgICAgPSBtb250aHM7XG5wcm90byQyLnllYXJzICAgICAgICAgID0geWVhcnM7XG5wcm90byQyLmh1bWFuaXplICAgICAgID0gaHVtYW5pemU7XG5wcm90byQyLnRvSVNPU3RyaW5nICAgID0gdG9JU09TdHJpbmckMTtcbnByb3RvJDIudG9TdHJpbmcgICAgICAgPSB0b0lTT1N0cmluZyQxO1xucHJvdG8kMi50b0pTT04gICAgICAgICA9IHRvSVNPU3RyaW5nJDE7XG5wcm90byQyLmxvY2FsZSAgICAgICAgID0gbG9jYWxlO1xucHJvdG8kMi5sb2NhbGVEYXRhICAgICA9IGxvY2FsZURhdGE7XG5cbi8vIERlcHJlY2F0aW9uc1xucHJvdG8kMi50b0lzb1N0cmluZyA9IGRlcHJlY2F0ZSgndG9Jc29TdHJpbmcoKSBpcyBkZXByZWNhdGVkLiBQbGVhc2UgdXNlIHRvSVNPU3RyaW5nKCkgaW5zdGVhZCAobm90aWNlIHRoZSBjYXBpdGFscyknLCB0b0lTT1N0cmluZyQxKTtcbnByb3RvJDIubGFuZyA9IGxhbmc7XG5cbi8vIFNpZGUgZWZmZWN0IGltcG9ydHNcblxuLy8gRk9STUFUVElOR1xuXG5hZGRGb3JtYXRUb2tlbignWCcsIDAsIDAsICd1bml4Jyk7XG5hZGRGb3JtYXRUb2tlbigneCcsIDAsIDAsICd2YWx1ZU9mJyk7XG5cbi8vIFBBUlNJTkdcblxuYWRkUmVnZXhUb2tlbigneCcsIG1hdGNoU2lnbmVkKTtcbmFkZFJlZ2V4VG9rZW4oJ1gnLCBtYXRjaFRpbWVzdGFtcCk7XG5hZGRQYXJzZVRva2VuKCdYJywgZnVuY3Rpb24gKGlucHV0LCBhcnJheSwgY29uZmlnKSB7XG4gICAgY29uZmlnLl9kID0gbmV3IERhdGUocGFyc2VGbG9hdChpbnB1dCwgMTApICogMTAwMCk7XG59KTtcbmFkZFBhcnNlVG9rZW4oJ3gnLCBmdW5jdGlvbiAoaW5wdXQsIGFycmF5LCBjb25maWcpIHtcbiAgICBjb25maWcuX2QgPSBuZXcgRGF0ZSh0b0ludChpbnB1dCkpO1xufSk7XG5cbi8vIFNpZGUgZWZmZWN0IGltcG9ydHNcblxuLy8hIG1vbWVudC5qc1xuLy8hIHZlcnNpb24gOiAyLjIwLjFcbi8vISBhdXRob3JzIDogVGltIFdvb2QsIElza3JlbiBDaGVybmV2LCBNb21lbnQuanMgY29udHJpYnV0b3JzXG4vLyEgbGljZW5zZSA6IE1JVFxuLy8hIG1vbWVudGpzLmNvbVxuXG5ob29rcy52ZXJzaW9uID0gJzIuMjAuMSc7XG5cbnNldEhvb2tDYWxsYmFjayhjcmVhdGVMb2NhbCk7XG5cbmhvb2tzLmZuICAgICAgICAgICAgICAgICAgICA9IHByb3RvO1xuaG9va3MubWluICAgICAgICAgICAgICAgICAgID0gbWluO1xuaG9va3MubWF4ICAgICAgICAgICAgICAgICAgID0gbWF4O1xuaG9va3Mubm93ICAgICAgICAgICAgICAgICAgID0gbm93O1xuaG9va3MudXRjICAgICAgICAgICAgICAgICAgID0gY3JlYXRlVVRDO1xuaG9va3MudW5peCAgICAgICAgICAgICAgICAgID0gY3JlYXRlVW5peDtcbmhvb2tzLm1vbnRocyAgICAgICAgICAgICAgICA9IGxpc3RNb250aHM7XG5ob29rcy5pc0RhdGUgICAgICAgICAgICAgICAgPSBpc0RhdGU7XG5ob29rcy5sb2NhbGUgICAgICAgICAgICAgICAgPSBnZXRTZXRHbG9iYWxMb2NhbGU7XG5ob29rcy5pbnZhbGlkICAgICAgICAgICAgICAgPSBjcmVhdGVJbnZhbGlkO1xuaG9va3MuZHVyYXRpb24gICAgICAgICAgICAgID0gY3JlYXRlRHVyYXRpb247XG5ob29rcy5pc01vbWVudCAgICAgICAgICAgICAgPSBpc01vbWVudDtcbmhvb2tzLndlZWtkYXlzICAgICAgICAgICAgICA9IGxpc3RXZWVrZGF5cztcbmhvb2tzLnBhcnNlWm9uZSAgICAgICAgICAgICA9IGNyZWF0ZUluWm9uZTtcbmhvb2tzLmxvY2FsZURhdGEgICAgICAgICAgICA9IGdldExvY2FsZTtcbmhvb2tzLmlzRHVyYXRpb24gICAgICAgICAgICA9IGlzRHVyYXRpb247XG5ob29rcy5tb250aHNTaG9ydCAgICAgICAgICAgPSBsaXN0TW9udGhzU2hvcnQ7XG5ob29rcy53ZWVrZGF5c01pbiAgICAgICAgICAgPSBsaXN0V2Vla2RheXNNaW47XG5ob29rcy5kZWZpbmVMb2NhbGUgICAgICAgICAgPSBkZWZpbmVMb2NhbGU7XG5ob29rcy51cGRhdGVMb2NhbGUgICAgICAgICAgPSB1cGRhdGVMb2NhbGU7XG5ob29rcy5sb2NhbGVzICAgICAgICAgICAgICAgPSBsaXN0TG9jYWxlcztcbmhvb2tzLndlZWtkYXlzU2hvcnQgICAgICAgICA9IGxpc3RXZWVrZGF5c1Nob3J0O1xuaG9va3Mubm9ybWFsaXplVW5pdHMgICAgICAgID0gbm9ybWFsaXplVW5pdHM7XG5ob29rcy5yZWxhdGl2ZVRpbWVSb3VuZGluZyAgPSBnZXRTZXRSZWxhdGl2ZVRpbWVSb3VuZGluZztcbmhvb2tzLnJlbGF0aXZlVGltZVRocmVzaG9sZCA9IGdldFNldFJlbGF0aXZlVGltZVRocmVzaG9sZDtcbmhvb2tzLmNhbGVuZGFyRm9ybWF0ICAgICAgICA9IGdldENhbGVuZGFyRm9ybWF0O1xuaG9va3MucHJvdG90eXBlICAgICAgICAgICAgID0gcHJvdG87XG5cbi8vIGN1cnJlbnRseSBIVE1MNSBpbnB1dCB0eXBlIG9ubHkgc3VwcG9ydHMgMjQtaG91ciBmb3JtYXRzXG5ob29rcy5IVE1MNV9GTVQgPSB7XG4gICAgREFURVRJTUVfTE9DQUw6ICdZWVlZLU1NLUREVEhIOm1tJywgICAgICAgICAgICAgLy8gPGlucHV0IHR5cGU9XCJkYXRldGltZS1sb2NhbFwiIC8+XG4gICAgREFURVRJTUVfTE9DQUxfU0VDT05EUzogJ1lZWVktTU0tRERUSEg6bW06c3MnLCAgLy8gPGlucHV0IHR5cGU9XCJkYXRldGltZS1sb2NhbFwiIHN0ZXA9XCIxXCIgLz5cbiAgICBEQVRFVElNRV9MT0NBTF9NUzogJ1lZWVktTU0tRERUSEg6bW06c3MuU1NTJywgICAvLyA8aW5wdXQgdHlwZT1cImRhdGV0aW1lLWxvY2FsXCIgc3RlcD1cIjAuMDAxXCIgLz5cbiAgICBEQVRFOiAnWVlZWS1NTS1ERCcsICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyA8aW5wdXQgdHlwZT1cImRhdGVcIiAvPlxuICAgIFRJTUU6ICdISDptbScsICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIDxpbnB1dCB0eXBlPVwidGltZVwiIC8+XG4gICAgVElNRV9TRUNPTkRTOiAnSEg6bW06c3MnLCAgICAgICAgICAgICAgICAgICAgICAgLy8gPGlucHV0IHR5cGU9XCJ0aW1lXCIgc3RlcD1cIjFcIiAvPlxuICAgIFRJTUVfTVM6ICdISDptbTpzcy5TU1MnLCAgICAgICAgICAgICAgICAgICAgICAgIC8vIDxpbnB1dCB0eXBlPVwidGltZVwiIHN0ZXA9XCIwLjAwMVwiIC8+XG4gICAgV0VFSzogJ1lZWVktW1ddV1cnLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gPGlucHV0IHR5cGU9XCJ3ZWVrXCIgLz5cbiAgICBNT05USDogJ1lZWVktTU0nICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyA8aW5wdXQgdHlwZT1cIm1vbnRoXCIgLz5cbn07XG5cbi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBBZnJpa2FhbnMgW2FmXVxuLy8hIGF1dGhvciA6IFdlcm5lciBNb2xsZW50emUgOiBodHRwczovL2dpdGh1Yi5jb20vd2VybmVybVxuXG5ob29rcy5kZWZpbmVMb2NhbGUoJ2FmJywge1xuICAgIG1vbnRocyA6ICdKYW51YXJpZV9GZWJydWFyaWVfTWFhcnRfQXByaWxfTWVpX0p1bmllX0p1bGllX0F1Z3VzdHVzX1NlcHRlbWJlcl9Pa3RvYmVyX05vdmVtYmVyX0Rlc2VtYmVyJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0IDogJ0phbl9GZWJfTXJ0X0Fwcl9NZWlfSnVuX0p1bF9BdWdfU2VwX09rdF9Ob3ZfRGVzJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzIDogJ1NvbmRhZ19NYWFuZGFnX0RpbnNkYWdfV29lbnNkYWdfRG9uZGVyZGFnX1ZyeWRhZ19TYXRlcmRhZycuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0IDogJ1Nvbl9NYWFfRGluX1dvZV9Eb25fVnJ5X1NhdCcuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbiA6ICdTb19NYV9EaV9Xb19Eb19Wcl9TYScuc3BsaXQoJ18nKSxcbiAgICBtZXJpZGllbVBhcnNlOiAvdm18bm0vaSxcbiAgICBpc1BNIDogZnVuY3Rpb24gKGlucHV0KSB7XG4gICAgICAgIHJldHVybiAvXm5tJC9pLnRlc3QoaW5wdXQpO1xuICAgIH0sXG4gICAgbWVyaWRpZW0gOiBmdW5jdGlvbiAoaG91cnMsIG1pbnV0ZXMsIGlzTG93ZXIpIHtcbiAgICAgICAgaWYgKGhvdXJzIDwgMTIpIHtcbiAgICAgICAgICAgIHJldHVybiBpc0xvd2VyID8gJ3ZtJyA6ICdWTSc7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gaXNMb3dlciA/ICdubScgOiAnTk0nO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgTFQgOiAnSEg6bW0nLFxuICAgICAgICBMVFMgOiAnSEg6bW06c3MnLFxuICAgICAgICBMIDogJ0REL01NL1lZWVknLFxuICAgICAgICBMTCA6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgIExMTCA6ICdEIE1NTU0gWVlZWSBISDptbScsXG4gICAgICAgIExMTEwgOiAnZGRkZCwgRCBNTU1NIFlZWVkgSEg6bW0nXG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheSA6ICdbVmFuZGFnIG9tXSBMVCcsXG4gICAgICAgIG5leHREYXkgOiAnW03DtHJlIG9tXSBMVCcsXG4gICAgICAgIG5leHRXZWVrIDogJ2RkZGQgW29tXSBMVCcsXG4gICAgICAgIGxhc3REYXkgOiAnW0dpc3RlciBvbV0gTFQnLFxuICAgICAgICBsYXN0V2VlayA6ICdbTGFhc10gZGRkZCBbb21dIExUJyxcbiAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJ29vciAlcycsXG4gICAgICAgIHBhc3QgOiAnJXMgZ2VsZWRlJyxcbiAgICAgICAgcyA6ICdcXCduIHBhYXIgc2Vrb25kZXMnLFxuICAgICAgICBzcyA6ICclZCBzZWtvbmRlcycsXG4gICAgICAgIG0gOiAnXFwnbiBtaW51dXQnLFxuICAgICAgICBtbSA6ICclZCBtaW51dGUnLFxuICAgICAgICBoIDogJ1xcJ24gdXVyJyxcbiAgICAgICAgaGggOiAnJWQgdXJlJyxcbiAgICAgICAgZCA6ICdcXCduIGRhZycsXG4gICAgICAgIGRkIDogJyVkIGRhZScsXG4gICAgICAgIE0gOiAnXFwnbiBtYWFuZCcsXG4gICAgICAgIE1NIDogJyVkIG1hYW5kZScsXG4gICAgICAgIHkgOiAnXFwnbiBqYWFyJyxcbiAgICAgICAgeXkgOiAnJWQgamFhcidcbiAgICB9LFxuICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfShzdGV8ZGUpLyxcbiAgICBvcmRpbmFsIDogZnVuY3Rpb24gKG51bWJlcikge1xuICAgICAgICByZXR1cm4gbnVtYmVyICsgKChudW1iZXIgPT09IDEgfHwgbnVtYmVyID09PSA4IHx8IG51bWJlciA+PSAyMCkgPyAnc3RlJyA6ICdkZScpOyAvLyBUaGFua3MgdG8gSm9yaXMgUsO2bGluZyA6IGh0dHBzOi8vZ2l0aHViLmNvbS9qanVwaXRlclxuICAgIH0sXG4gICAgd2VlayA6IHtcbiAgICAgICAgZG93IDogMSwgLy8gTWFhbmRhZyBpcyBkaWUgZWVyc3RlIGRhZyB2YW4gZGllIHdlZWsuXG4gICAgICAgIGRveSA6IDQgIC8vIERpZSB3ZWVrIHdhdCBkaWUgNGRlIEphbnVhcmllIGJldmF0IGlzIGRpZSBlZXJzdGUgd2VlayB2YW4gZGllIGphYXIuXG4gICAgfVxufSk7XG5cbi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBBcmFiaWMgKEFsZ2VyaWEpIFthci1kel1cbi8vISBhdXRob3IgOiBOb3VyZWRkaW5lIExPVUFIRURKIDogaHR0cHM6Ly9naXRodWIuY29tL25vdXJlZGRpbmVtZVxuXG5ob29rcy5kZWZpbmVMb2NhbGUoJ2FyLWR6Jywge1xuICAgIG1vbnRocyA6ICfYrNin2YbZgdmKX9mB2YrZgdix2Ypf2YXYp9ix2LNf2KPZgdix2YrZhF/Zhdin2Ypf2KzZiNin2YZf2KzZiNmK2YTZitipX9ij2YjYql/Ys9io2KrZhdio2LFf2KPZg9iq2YjYqNixX9mG2YjZgdmF2KjYsV/Yr9mK2LPZhdio2LEnLnNwbGl0KCdfJyksXG4gICAgbW9udGhzU2hvcnQgOiAn2KzYp9mG2YHZil/ZgdmK2YHYsdmKX9mF2KfYsdizX9ij2YHYsdmK2YRf2YXYp9mKX9is2YjYp9mGX9is2YjZitmE2YrYqV/Yo9mI2Kpf2LPYqNiq2YXYqNixX9ij2YPYqtmI2KjYsV/ZhtmI2YHZhdio2LFf2K/Zitiz2YXYqNixJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzIDogJ9in2YTYo9it2K9f2KfZhNil2KvZhtmK2YZf2KfZhNir2YTYp9ir2KfYoV/Yp9mE2KPYsdio2LnYp9ihX9in2YTYrtmF2YrYs1/Yp9mE2KzZhdi52Klf2KfZhNiz2KjYqicuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0IDogJ9in2K3Yr1/Yp9ir2YbZitmGX9ir2YTYp9ir2KfYoV/Yp9ix2KjYudin2KFf2K7ZhdmK2LNf2KzZhdi52Klf2LPYqNiqJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzTWluIDogJ9ij2K1f2KXYq1/Yq9mE2Kdf2KPYsV/YrtmFX9is2YVf2LPYqCcuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdISDptbScsXG4gICAgICAgIExUUyA6ICdISDptbTpzcycsXG4gICAgICAgIEwgOiAnREQvTU0vWVlZWScsXG4gICAgICAgIExMIDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgTExMIDogJ0QgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgTExMTCA6ICdkZGRkIEQgTU1NTSBZWVlZIEhIOm1tJ1xuICAgIH0sXG4gICAgY2FsZW5kYXIgOiB7XG4gICAgICAgIHNhbWVEYXk6ICdb2KfZhNmK2YjZhSDYudmE2Ykg2KfZhNiz2KfYudipXSBMVCcsXG4gICAgICAgIG5leHREYXk6ICdb2LrYr9inINi52YTZiSDYp9mE2LPYp9i52KldIExUJyxcbiAgICAgICAgbmV4dFdlZWs6ICdkZGRkIFvYudmE2Ykg2KfZhNiz2KfYudipXSBMVCcsXG4gICAgICAgIGxhc3REYXk6ICdb2KPZhdizINi52YTZiSDYp9mE2LPYp9i52KldIExUJyxcbiAgICAgICAgbGFzdFdlZWs6ICdkZGRkIFvYudmE2Ykg2KfZhNiz2KfYudipXSBMVCcsXG4gICAgICAgIHNhbWVFbHNlOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJ9mB2YogJXMnLFxuICAgICAgICBwYXN0IDogJ9mF2YbYsCAlcycsXG4gICAgICAgIHMgOiAn2KvZiNin2YYnLFxuICAgICAgICBzcyA6ICclZCDYq9in2YbZitipJyxcbiAgICAgICAgbSA6ICfYr9mC2YrZgtipJyxcbiAgICAgICAgbW0gOiAnJWQg2K/Zgtin2KbZgicsXG4gICAgICAgIGggOiAn2LPYp9i52KknLFxuICAgICAgICBoaCA6ICclZCDYs9in2LnYp9iqJyxcbiAgICAgICAgZCA6ICfZitmI2YUnLFxuICAgICAgICBkZCA6ICclZCDYo9mK2KfZhScsXG4gICAgICAgIE0gOiAn2LTZh9ixJyxcbiAgICAgICAgTU0gOiAnJWQg2KPYtNmH2LEnLFxuICAgICAgICB5IDogJ9iz2YbYqScsXG4gICAgICAgIHl5IDogJyVkINiz2YbZiNin2KonXG4gICAgfSxcbiAgICB3ZWVrIDoge1xuICAgICAgICBkb3cgOiAwLCAvLyBTdW5kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogNCAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gMXN0IGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH1cbn0pO1xuXG4vLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogQXJhYmljIChLdXdhaXQpIFthci1rd11cbi8vISBhdXRob3IgOiBOdXNyZXQgUGFybGFrOiBodHRwczovL2dpdGh1Yi5jb20vbnVzcmV0cGFybGFrXG5cbmhvb2tzLmRlZmluZUxvY2FsZSgnYXIta3cnLCB7XG4gICAgbW9udGhzIDogJ9mK2YbYp9mK2LFf2YHYqNix2KfZitixX9mF2KfYsdizX9ij2KjYsdmK2YRf2YXYp9mKX9mK2YjZhtmK2Yhf2YrZiNmE2YrZiNiyX9i62LTYql/YtNiq2YbYqNixX9ij2YPYqtmI2KjYsV/ZhtmI2YbYqNixX9iv2KzZhtio2LEnLnNwbGl0KCdfJyksXG4gICAgbW9udGhzU2hvcnQgOiAn2YrZhtin2YrYsV/Zgdio2LHYp9mK2LFf2YXYp9ix2LNf2KPYqNix2YrZhF/Zhdin2Ypf2YrZiNmG2YrZiF/ZitmI2YTZitmI2LJf2LrYtNiqX9i02KrZhtio2LFf2KPZg9iq2YjYqNixX9mG2YjZhtio2LFf2K/YrNmG2KjYsScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5cyA6ICfYp9mE2KPYrdivX9in2YTYpdiq2YbZitmGX9in2YTYq9mE2KfYq9in2KFf2KfZhNij2LHYqNi52KfYoV/Yp9mE2K7ZhdmK2LNf2KfZhNis2YXYudipX9in2YTYs9io2KonLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydCA6ICfYp9it2K9f2KfYqtmG2YrZhl/Yq9mE2KfYq9in2KFf2KfYsdio2LnYp9ihX9iu2YXZitizX9is2YXYudipX9iz2KjYqicuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbiA6ICfYrV/Zhl/Yq1/YsV/Yrl/YrF/Ysycuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdISDptbScsXG4gICAgICAgIExUUyA6ICdISDptbTpzcycsXG4gICAgICAgIEwgOiAnREQvTU0vWVlZWScsXG4gICAgICAgIExMIDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgTExMIDogJ0QgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgTExMTCA6ICdkZGRkIEQgTU1NTSBZWVlZIEhIOm1tJ1xuICAgIH0sXG4gICAgY2FsZW5kYXIgOiB7XG4gICAgICAgIHNhbWVEYXk6ICdb2KfZhNmK2YjZhSDYudmE2Ykg2KfZhNiz2KfYudipXSBMVCcsXG4gICAgICAgIG5leHREYXk6ICdb2LrYr9inINi52YTZiSDYp9mE2LPYp9i52KldIExUJyxcbiAgICAgICAgbmV4dFdlZWs6ICdkZGRkIFvYudmE2Ykg2KfZhNiz2KfYudipXSBMVCcsXG4gICAgICAgIGxhc3REYXk6ICdb2KPZhdizINi52YTZiSDYp9mE2LPYp9i52KldIExUJyxcbiAgICAgICAgbGFzdFdlZWs6ICdkZGRkIFvYudmE2Ykg2KfZhNiz2KfYudipXSBMVCcsXG4gICAgICAgIHNhbWVFbHNlOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJ9mB2YogJXMnLFxuICAgICAgICBwYXN0IDogJ9mF2YbYsCAlcycsXG4gICAgICAgIHMgOiAn2KvZiNin2YYnLFxuICAgICAgICBzcyA6ICclZCDYq9in2YbZitipJyxcbiAgICAgICAgbSA6ICfYr9mC2YrZgtipJyxcbiAgICAgICAgbW0gOiAnJWQg2K/Zgtin2KbZgicsXG4gICAgICAgIGggOiAn2LPYp9i52KknLFxuICAgICAgICBoaCA6ICclZCDYs9in2LnYp9iqJyxcbiAgICAgICAgZCA6ICfZitmI2YUnLFxuICAgICAgICBkZCA6ICclZCDYo9mK2KfZhScsXG4gICAgICAgIE0gOiAn2LTZh9ixJyxcbiAgICAgICAgTU0gOiAnJWQg2KPYtNmH2LEnLFxuICAgICAgICB5IDogJ9iz2YbYqScsXG4gICAgICAgIHl5IDogJyVkINiz2YbZiNin2KonXG4gICAgfSxcbiAgICB3ZWVrIDoge1xuICAgICAgICBkb3cgOiAwLCAvLyBTdW5kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogMTIgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDFzdCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICB9XG59KTtcblxuLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSA6IEFyYWJpYyAoTHliaWEpIFthci1seV1cbi8vISBhdXRob3IgOiBBbGkgSG1lcjogaHR0cHM6Ly9naXRodWIuY29tL2tpa29hbmlzXG5cbnZhciBzeW1ib2xNYXAgPSB7XG4gICAgJzEnOiAnMScsXG4gICAgJzInOiAnMicsXG4gICAgJzMnOiAnMycsXG4gICAgJzQnOiAnNCcsXG4gICAgJzUnOiAnNScsXG4gICAgJzYnOiAnNicsXG4gICAgJzcnOiAnNycsXG4gICAgJzgnOiAnOCcsXG4gICAgJzknOiAnOScsXG4gICAgJzAnOiAnMCdcbn07XG52YXIgcGx1cmFsRm9ybSA9IGZ1bmN0aW9uIChuKSB7XG4gICAgcmV0dXJuIG4gPT09IDAgPyAwIDogbiA9PT0gMSA/IDEgOiBuID09PSAyID8gMiA6IG4gJSAxMDAgPj0gMyAmJiBuICUgMTAwIDw9IDEwID8gMyA6IG4gJSAxMDAgPj0gMTEgPyA0IDogNTtcbn07XG52YXIgcGx1cmFscyA9IHtcbiAgICBzIDogWyfYo9mC2YQg2YXZhiDYq9in2YbZitipJywgJ9ir2KfZhtmK2Kkg2YjYp9it2K/YqScsIFsn2KvYp9mG2YrYqtin2YYnLCAn2KvYp9mG2YrYqtmK2YYnXSwgJyVkINir2YjYp9mGJywgJyVkINir2KfZhtmK2KknLCAnJWQg2KvYp9mG2YrYqSddLFxuICAgIG0gOiBbJ9ij2YLZhCDZhdmGINiv2YLZitmC2KknLCAn2K/ZgtmK2YLYqSDZiNin2K3Yr9ipJywgWyfYr9mC2YrZgtiq2KfZhicsICfYr9mC2YrZgtiq2YrZhiddLCAnJWQg2K/Zgtin2KbZgicsICclZCDYr9mC2YrZgtipJywgJyVkINiv2YLZitmC2KknXSxcbiAgICBoIDogWyfYo9mC2YQg2YXZhiDYs9in2LnYqScsICfYs9in2LnYqSDZiNin2K3Yr9ipJywgWyfYs9in2LnYqtin2YYnLCAn2LPYp9i52KrZitmGJ10sICclZCDYs9in2LnYp9iqJywgJyVkINiz2KfYudipJywgJyVkINiz2KfYudipJ10sXG4gICAgZCA6IFsn2KPZgtmEINmF2YYg2YrZiNmFJywgJ9mK2YjZhSDZiNin2K3YrycsIFsn2YrZiNmF2KfZhicsICfZitmI2YXZitmGJ10sICclZCDYo9mK2KfZhScsICclZCDZitmI2YXZi9inJywgJyVkINmK2YjZhSddLFxuICAgIE0gOiBbJ9ij2YLZhCDZhdmGINi02YfYsScsICfYtNmH2LEg2YjYp9it2K8nLCBbJ9i02YfYsdin2YYnLCAn2LTZh9ix2YrZhiddLCAnJWQg2KPYtNmH2LEnLCAnJWQg2LTZh9ix2KcnLCAnJWQg2LTZh9ixJ10sXG4gICAgeSA6IFsn2KPZgtmEINmF2YYg2LnYp9mFJywgJ9i52KfZhSDZiNin2K3YrycsIFsn2LnYp9mF2KfZhicsICfYudin2YXZitmGJ10sICclZCDYo9i52YjYp9mFJywgJyVkINi52KfZhdmL2KcnLCAnJWQg2LnYp9mFJ11cbn07XG52YXIgcGx1cmFsaXplID0gZnVuY3Rpb24gKHUpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24gKG51bWJlciwgd2l0aG91dFN1ZmZpeCwgc3RyaW5nLCBpc0Z1dHVyZSkge1xuICAgICAgICB2YXIgZiA9IHBsdXJhbEZvcm0obnVtYmVyKSxcbiAgICAgICAgICAgIHN0ciA9IHBsdXJhbHNbdV1bcGx1cmFsRm9ybShudW1iZXIpXTtcbiAgICAgICAgaWYgKGYgPT09IDIpIHtcbiAgICAgICAgICAgIHN0ciA9IHN0clt3aXRob3V0U3VmZml4ID8gMCA6IDFdO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBzdHIucmVwbGFjZSgvJWQvaSwgbnVtYmVyKTtcbiAgICB9O1xufTtcbnZhciBtb250aHMkMSA9IFtcbiAgICAn2YrZhtin2YrYsScsXG4gICAgJ9mB2KjYsdin2YrYsScsXG4gICAgJ9mF2KfYsdizJyxcbiAgICAn2KPYqNix2YrZhCcsXG4gICAgJ9mF2KfZitmIJyxcbiAgICAn2YrZiNmG2YrZiCcsXG4gICAgJ9mK2YjZhNmK2YgnLFxuICAgICfYo9i62LPYt9izJyxcbiAgICAn2LPYqNiq2YXYqNixJyxcbiAgICAn2KPZg9iq2YjYqNixJyxcbiAgICAn2YbZiNmB2YXYqNixJyxcbiAgICAn2K/Zitiz2YXYqNixJ1xuXTtcblxuaG9va3MuZGVmaW5lTG9jYWxlKCdhci1seScsIHtcbiAgICBtb250aHMgOiBtb250aHMkMSxcbiAgICBtb250aHNTaG9ydCA6IG1vbnRocyQxLFxuICAgIHdlZWtkYXlzIDogJ9in2YTYo9it2K9f2KfZhNil2KvZhtmK2YZf2KfZhNir2YTYp9ir2KfYoV/Yp9mE2KPYsdio2LnYp9ihX9in2YTYrtmF2YrYs1/Yp9mE2KzZhdi52Klf2KfZhNiz2KjYqicuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0IDogJ9ij2K3Yr1/Ypdir2YbZitmGX9ir2YTYp9ir2KfYoV/Yo9ix2KjYudin2KFf2K7ZhdmK2LNf2KzZhdi52Klf2LPYqNiqJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzTWluIDogJ9itX9mGX9irX9ixX9iuX9isX9izJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzUGFyc2VFeGFjdCA6IHRydWUsXG4gICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgIExUIDogJ0hIOm1tJyxcbiAgICAgICAgTFRTIDogJ0hIOm1tOnNzJyxcbiAgICAgICAgTCA6ICdEL1xcdTIwMEZNL1xcdTIwMEZZWVlZJyxcbiAgICAgICAgTEwgOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICBMTEwgOiAnRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICBMTExMIDogJ2RkZGQgRCBNTU1NIFlZWVkgSEg6bW0nXG4gICAgfSxcbiAgICBtZXJpZGllbVBhcnNlOiAv2LV82YUvLFxuICAgIGlzUE0gOiBmdW5jdGlvbiAoaW5wdXQpIHtcbiAgICAgICAgcmV0dXJuICfZhScgPT09IGlucHV0O1xuICAgIH0sXG4gICAgbWVyaWRpZW0gOiBmdW5jdGlvbiAoaG91ciwgbWludXRlLCBpc0xvd2VyKSB7XG4gICAgICAgIGlmIChob3VyIDwgMTIpIHtcbiAgICAgICAgICAgIHJldHVybiAn2LUnO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuICfZhSc7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIGNhbGVuZGFyIDoge1xuICAgICAgICBzYW1lRGF5OiAnW9in2YTZitmI2YUg2LnZhtivINin2YTYs9in2LnYqV0gTFQnLFxuICAgICAgICBuZXh0RGF5OiAnW9i62K/Zi9inINi52YbYryDYp9mE2LPYp9i52KldIExUJyxcbiAgICAgICAgbmV4dFdlZWs6ICdkZGRkIFvYudmG2K8g2KfZhNiz2KfYudipXSBMVCcsXG4gICAgICAgIGxhc3REYXk6ICdb2KPZhdizINi52YbYryDYp9mE2LPYp9i52KldIExUJyxcbiAgICAgICAgbGFzdFdlZWs6ICdkZGRkIFvYudmG2K8g2KfZhNiz2KfYudipXSBMVCcsXG4gICAgICAgIHNhbWVFbHNlOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJ9io2LnYryAlcycsXG4gICAgICAgIHBhc3QgOiAn2YXZhtiwICVzJyxcbiAgICAgICAgcyA6IHBsdXJhbGl6ZSgncycpLFxuICAgICAgICBzcyA6IHBsdXJhbGl6ZSgncycpLFxuICAgICAgICBtIDogcGx1cmFsaXplKCdtJyksXG4gICAgICAgIG1tIDogcGx1cmFsaXplKCdtJyksXG4gICAgICAgIGggOiBwbHVyYWxpemUoJ2gnKSxcbiAgICAgICAgaGggOiBwbHVyYWxpemUoJ2gnKSxcbiAgICAgICAgZCA6IHBsdXJhbGl6ZSgnZCcpLFxuICAgICAgICBkZCA6IHBsdXJhbGl6ZSgnZCcpLFxuICAgICAgICBNIDogcGx1cmFsaXplKCdNJyksXG4gICAgICAgIE1NIDogcGx1cmFsaXplKCdNJyksXG4gICAgICAgIHkgOiBwbHVyYWxpemUoJ3knKSxcbiAgICAgICAgeXkgOiBwbHVyYWxpemUoJ3knKVxuICAgIH0sXG4gICAgcHJlcGFyc2U6IGZ1bmN0aW9uIChzdHJpbmcpIHtcbiAgICAgICAgcmV0dXJuIHN0cmluZy5yZXBsYWNlKC/YjC9nLCAnLCcpO1xuICAgIH0sXG4gICAgcG9zdGZvcm1hdDogZnVuY3Rpb24gKHN0cmluZykge1xuICAgICAgICByZXR1cm4gc3RyaW5nLnJlcGxhY2UoL1xcZC9nLCBmdW5jdGlvbiAobWF0Y2gpIHtcbiAgICAgICAgICAgIHJldHVybiBzeW1ib2xNYXBbbWF0Y2hdO1xuICAgICAgICB9KS5yZXBsYWNlKC8sL2csICfYjCcpO1xuICAgIH0sXG4gICAgd2VlayA6IHtcbiAgICAgICAgZG93IDogNiwgLy8gU2F0dXJkYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogMTIgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDFzdCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICB9XG59KTtcblxuLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSA6IEFyYWJpYyAoTW9yb2NjbykgW2FyLW1hXVxuLy8hIGF1dGhvciA6IEVsRmFkaWxpIFlhc3NpbmUgOiBodHRwczovL2dpdGh1Yi5jb20vRWxGYWRpbGlZXG4vLyEgYXV0aG9yIDogQWJkZWwgU2FpZCA6IGh0dHBzOi8vZ2l0aHViLmNvbS9hYmRlbHNhaWRcblxuaG9va3MuZGVmaW5lTG9jYWxlKCdhci1tYScsIHtcbiAgICBtb250aHMgOiAn2YrZhtin2YrYsV/Zgdio2LHYp9mK2LFf2YXYp9ix2LNf2KPYqNix2YrZhF/Zhdin2Ypf2YrZiNmG2YrZiF/ZitmI2YTZitmI2LJf2LrYtNiqX9i02KrZhtio2LFf2KPZg9iq2YjYqNixX9mG2YjZhtio2LFf2K/YrNmG2KjYsScuc3BsaXQoJ18nKSxcbiAgICBtb250aHNTaG9ydCA6ICfZitmG2KfZitixX9mB2KjYsdin2YrYsV/Zhdin2LHYs1/Yo9io2LHZitmEX9mF2KfZil/ZitmI2YbZitmIX9mK2YjZhNmK2YjYsl/Yuti02Kpf2LTYqtmG2KjYsV/Yo9mD2KrZiNio2LFf2YbZiNmG2KjYsV/Yr9is2YbYqNixJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzIDogJ9in2YTYo9it2K9f2KfZhNil2KrZhtmK2YZf2KfZhNir2YTYp9ir2KfYoV/Yp9mE2KPYsdio2LnYp9ihX9in2YTYrtmF2YrYs1/Yp9mE2KzZhdi52Klf2KfZhNiz2KjYqicuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0IDogJ9in2K3Yr1/Yp9iq2YbZitmGX9ir2YTYp9ir2KfYoV/Yp9ix2KjYudin2KFf2K7ZhdmK2LNf2KzZhdi52Klf2LPYqNiqJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzTWluIDogJ9itX9mGX9irX9ixX9iuX9isX9izJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzUGFyc2VFeGFjdCA6IHRydWUsXG4gICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgIExUIDogJ0hIOm1tJyxcbiAgICAgICAgTFRTIDogJ0hIOm1tOnNzJyxcbiAgICAgICAgTCA6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgTEwgOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICBMTEwgOiAnRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICBMTExMIDogJ2RkZGQgRCBNTU1NIFlZWVkgSEg6bW0nXG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheTogJ1vYp9mE2YrZiNmFINi52YTZiSDYp9mE2LPYp9i52KldIExUJyxcbiAgICAgICAgbmV4dERheTogJ1vYutiv2Kcg2LnZhNmJINin2YTYs9in2LnYqV0gTFQnLFxuICAgICAgICBuZXh0V2VlazogJ2RkZGQgW9i52YTZiSDYp9mE2LPYp9i52KldIExUJyxcbiAgICAgICAgbGFzdERheTogJ1vYo9mF2LMg2LnZhNmJINin2YTYs9in2LnYqV0gTFQnLFxuICAgICAgICBsYXN0V2VlazogJ2RkZGQgW9i52YTZiSDYp9mE2LPYp9i52KldIExUJyxcbiAgICAgICAgc2FtZUVsc2U6ICdMJ1xuICAgIH0sXG4gICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICBmdXR1cmUgOiAn2YHZiiAlcycsXG4gICAgICAgIHBhc3QgOiAn2YXZhtiwICVzJyxcbiAgICAgICAgcyA6ICfYq9mI2KfZhicsXG4gICAgICAgIHNzIDogJyVkINir2KfZhtmK2KknLFxuICAgICAgICBtIDogJ9iv2YLZitmC2KknLFxuICAgICAgICBtbSA6ICclZCDYr9mC2KfYptmCJyxcbiAgICAgICAgaCA6ICfYs9in2LnYqScsXG4gICAgICAgIGhoIDogJyVkINiz2KfYudin2KonLFxuICAgICAgICBkIDogJ9mK2YjZhScsXG4gICAgICAgIGRkIDogJyVkINij2YrYp9mFJyxcbiAgICAgICAgTSA6ICfYtNmH2LEnLFxuICAgICAgICBNTSA6ICclZCDYo9i02YfYsScsXG4gICAgICAgIHkgOiAn2LPZhtipJyxcbiAgICAgICAgeXkgOiAnJWQg2LPZhtmI2KfYqidcbiAgICB9LFxuICAgIHdlZWsgOiB7XG4gICAgICAgIGRvdyA6IDYsIC8vIFNhdHVyZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgIGRveSA6IDEyICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiAxc3QgaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgfVxufSk7XG5cbi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBBcmFiaWMgKFNhdWRpIEFyYWJpYSkgW2FyLXNhXVxuLy8hIGF1dGhvciA6IFN1aGFpbCBBbGtvd2FpbGVldCA6IGh0dHBzOi8vZ2l0aHViLmNvbS94c29oXG5cbnZhciBzeW1ib2xNYXAkMSA9IHtcbiAgICAnMSc6ICfZoScsXG4gICAgJzInOiAn2aInLFxuICAgICczJzogJ9mjJyxcbiAgICAnNCc6ICfZpCcsXG4gICAgJzUnOiAn2aUnLFxuICAgICc2JzogJ9mmJyxcbiAgICAnNyc6ICfZpycsXG4gICAgJzgnOiAn2agnLFxuICAgICc5JzogJ9mpJyxcbiAgICAnMCc6ICfZoCdcbn07XG52YXIgbnVtYmVyTWFwID0ge1xuICAgICfZoSc6ICcxJyxcbiAgICAn2aInOiAnMicsXG4gICAgJ9mjJzogJzMnLFxuICAgICfZpCc6ICc0JyxcbiAgICAn2aUnOiAnNScsXG4gICAgJ9mmJzogJzYnLFxuICAgICfZpyc6ICc3JyxcbiAgICAn2agnOiAnOCcsXG4gICAgJ9mpJzogJzknLFxuICAgICfZoCc6ICcwJ1xufTtcblxuaG9va3MuZGVmaW5lTG9jYWxlKCdhci1zYScsIHtcbiAgICBtb250aHMgOiAn2YrZhtin2YrYsV/Zgdio2LHYp9mK2LFf2YXYp9ix2LNf2KPYqNix2YrZhF/Zhdin2YrZiF/ZitmI2YbZitmIX9mK2YjZhNmK2Yhf2KPYutiz2LfYs1/Ys9io2KrZhdio2LFf2KPZg9iq2YjYqNixX9mG2YjZgdmF2KjYsV/Yr9mK2LPZhdio2LEnLnNwbGl0KCdfJyksXG4gICAgbW9udGhzU2hvcnQgOiAn2YrZhtin2YrYsV/Zgdio2LHYp9mK2LFf2YXYp9ix2LNf2KPYqNix2YrZhF/Zhdin2YrZiF/ZitmI2YbZitmIX9mK2YjZhNmK2Yhf2KPYutiz2LfYs1/Ys9io2KrZhdio2LFf2KPZg9iq2YjYqNixX9mG2YjZgdmF2KjYsV/Yr9mK2LPZhdio2LEnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXMgOiAn2KfZhNij2K3Yr1/Yp9mE2KXYq9mG2YrZhl/Yp9mE2KvZhNin2KvYp9ihX9in2YTYo9ix2KjYudin2KFf2KfZhNiu2YXZitizX9in2YTYrNmF2LnYqV/Yp9mE2LPYqNiqJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzU2hvcnQgOiAn2KPYrdivX9il2KvZhtmK2YZf2KvZhNin2KvYp9ihX9ij2LHYqNi52KfYoV/YrtmF2YrYs1/YrNmF2LnYqV/Ys9io2KonLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW4gOiAn2K1f2YZf2Ktf2LFf2K5f2Kxf2LMnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNQYXJzZUV4YWN0IDogdHJ1ZSxcbiAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgTFQgOiAnSEg6bW0nLFxuICAgICAgICBMVFMgOiAnSEg6bW06c3MnLFxuICAgICAgICBMIDogJ0REL01NL1lZWVknLFxuICAgICAgICBMTCA6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgIExMTCA6ICdEIE1NTU0gWVlZWSBISDptbScsXG4gICAgICAgIExMTEwgOiAnZGRkZCBEIE1NTU0gWVlZWSBISDptbSdcbiAgICB9LFxuICAgIG1lcmlkaWVtUGFyc2U6IC/YtXzZhS8sXG4gICAgaXNQTSA6IGZ1bmN0aW9uIChpbnB1dCkge1xuICAgICAgICByZXR1cm4gJ9mFJyA9PT0gaW5wdXQ7XG4gICAgfSxcbiAgICBtZXJpZGllbSA6IGZ1bmN0aW9uIChob3VyLCBtaW51dGUsIGlzTG93ZXIpIHtcbiAgICAgICAgaWYgKGhvdXIgPCAxMikge1xuICAgICAgICAgICAgcmV0dXJuICfYtSc7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gJ9mFJztcbiAgICAgICAgfVxuICAgIH0sXG4gICAgY2FsZW5kYXIgOiB7XG4gICAgICAgIHNhbWVEYXk6ICdb2KfZhNmK2YjZhSDYudmE2Ykg2KfZhNiz2KfYudipXSBMVCcsXG4gICAgICAgIG5leHREYXk6ICdb2LrYr9inINi52YTZiSDYp9mE2LPYp9i52KldIExUJyxcbiAgICAgICAgbmV4dFdlZWs6ICdkZGRkIFvYudmE2Ykg2KfZhNiz2KfYudipXSBMVCcsXG4gICAgICAgIGxhc3REYXk6ICdb2KPZhdizINi52YTZiSDYp9mE2LPYp9i52KldIExUJyxcbiAgICAgICAgbGFzdFdlZWs6ICdkZGRkIFvYudmE2Ykg2KfZhNiz2KfYudipXSBMVCcsXG4gICAgICAgIHNhbWVFbHNlOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJ9mB2YogJXMnLFxuICAgICAgICBwYXN0IDogJ9mF2YbYsCAlcycsXG4gICAgICAgIHMgOiAn2KvZiNin2YYnLFxuICAgICAgICBzcyA6ICclZCDYq9in2YbZitipJyxcbiAgICAgICAgbSA6ICfYr9mC2YrZgtipJyxcbiAgICAgICAgbW0gOiAnJWQg2K/Zgtin2KbZgicsXG4gICAgICAgIGggOiAn2LPYp9i52KknLFxuICAgICAgICBoaCA6ICclZCDYs9in2LnYp9iqJyxcbiAgICAgICAgZCA6ICfZitmI2YUnLFxuICAgICAgICBkZCA6ICclZCDYo9mK2KfZhScsXG4gICAgICAgIE0gOiAn2LTZh9ixJyxcbiAgICAgICAgTU0gOiAnJWQg2KPYtNmH2LEnLFxuICAgICAgICB5IDogJ9iz2YbYqScsXG4gICAgICAgIHl5IDogJyVkINiz2YbZiNin2KonXG4gICAgfSxcbiAgICBwcmVwYXJzZTogZnVuY3Rpb24gKHN0cmluZykge1xuICAgICAgICByZXR1cm4gc3RyaW5nLnJlcGxhY2UoL1vZodmi2aPZpNml2abZp9mo2anZoF0vZywgZnVuY3Rpb24gKG1hdGNoKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVtYmVyTWFwW21hdGNoXTtcbiAgICAgICAgfSkucmVwbGFjZSgv2IwvZywgJywnKTtcbiAgICB9LFxuICAgIHBvc3Rmb3JtYXQ6IGZ1bmN0aW9uIChzdHJpbmcpIHtcbiAgICAgICAgcmV0dXJuIHN0cmluZy5yZXBsYWNlKC9cXGQvZywgZnVuY3Rpb24gKG1hdGNoKSB7XG4gICAgICAgICAgICByZXR1cm4gc3ltYm9sTWFwJDFbbWF0Y2hdO1xuICAgICAgICB9KS5yZXBsYWNlKC8sL2csICfYjCcpO1xuICAgIH0sXG4gICAgd2VlayA6IHtcbiAgICAgICAgZG93IDogMCwgLy8gU3VuZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgIGRveSA6IDYgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDFzdCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICB9XG59KTtcblxuLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSAgOiAgQXJhYmljIChUdW5pc2lhKSBbYXItdG5dXG4vLyEgYXV0aG9yIDogTmFkZXIgVG91a2FicmkgOiBodHRwczovL2dpdGh1Yi5jb20vbmFkZXJpb1xuXG5ob29rcy5kZWZpbmVMb2NhbGUoJ2FyLXRuJywge1xuICAgIG1vbnRoczogJ9is2KfZhtmB2Ypf2YHZitmB2LHZil/Zhdin2LHYs1/Yo9mB2LHZitmEX9mF2KfZil/YrNmI2KfZhl/YrNmI2YrZhNmK2Klf2KPZiNiqX9iz2KjYqtmF2KjYsV/Yo9mD2KrZiNio2LFf2YbZiNmB2YXYqNixX9iv2YrYs9mF2KjYsScuc3BsaXQoJ18nKSxcbiAgICBtb250aHNTaG9ydDogJ9is2KfZhtmB2Ypf2YHZitmB2LHZil/Zhdin2LHYs1/Yo9mB2LHZitmEX9mF2KfZil/YrNmI2KfZhl/YrNmI2YrZhNmK2Klf2KPZiNiqX9iz2KjYqtmF2KjYsV/Yo9mD2KrZiNio2LFf2YbZiNmB2YXYqNixX9iv2YrYs9mF2KjYsScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5czogJ9in2YTYo9it2K9f2KfZhNil2KvZhtmK2YZf2KfZhNir2YTYp9ir2KfYoV/Yp9mE2KPYsdio2LnYp9ihX9in2YTYrtmF2YrYs1/Yp9mE2KzZhdi52Klf2KfZhNiz2KjYqicuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0OiAn2KPYrdivX9il2KvZhtmK2YZf2KvZhNin2KvYp9ihX9ij2LHYqNi52KfYoV/YrtmF2YrYs1/YrNmF2LnYqV/Ys9io2KonLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW46ICfYrV/Zhl/Yq1/YsV/Yrl/YrF/Ysycuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgIGxvbmdEYXRlRm9ybWF0OiB7XG4gICAgICAgIExUOiAnSEg6bW0nLFxuICAgICAgICBMVFM6ICdISDptbTpzcycsXG4gICAgICAgIEw6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgTEw6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgIExMTDogJ0QgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgTExMTDogJ2RkZGQgRCBNTU1NIFlZWVkgSEg6bW0nXG4gICAgfSxcbiAgICBjYWxlbmRhcjoge1xuICAgICAgICBzYW1lRGF5OiAnW9in2YTZitmI2YUg2LnZhNmJINin2YTYs9in2LnYqV0gTFQnLFxuICAgICAgICBuZXh0RGF5OiAnW9i62K/YpyDYudmE2Ykg2KfZhNiz2KfYudipXSBMVCcsXG4gICAgICAgIG5leHRXZWVrOiAnZGRkZCBb2LnZhNmJINin2YTYs9in2LnYqV0gTFQnLFxuICAgICAgICBsYXN0RGF5OiAnW9ij2YXYsyDYudmE2Ykg2KfZhNiz2KfYudipXSBMVCcsXG4gICAgICAgIGxhc3RXZWVrOiAnZGRkZCBb2LnZhNmJINin2YTYs9in2LnYqV0gTFQnLFxuICAgICAgICBzYW1lRWxzZTogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWU6IHtcbiAgICAgICAgZnV0dXJlOiAn2YHZiiAlcycsXG4gICAgICAgIHBhc3Q6ICfZhdmG2LAgJXMnLFxuICAgICAgICBzOiAn2KvZiNin2YYnLFxuICAgICAgICBzcyA6ICclZCDYq9in2YbZitipJyxcbiAgICAgICAgbTogJ9iv2YLZitmC2KknLFxuICAgICAgICBtbTogJyVkINiv2YLYp9im2YInLFxuICAgICAgICBoOiAn2LPYp9i52KknLFxuICAgICAgICBoaDogJyVkINiz2KfYudin2KonLFxuICAgICAgICBkOiAn2YrZiNmFJyxcbiAgICAgICAgZGQ6ICclZCDYo9mK2KfZhScsXG4gICAgICAgIE06ICfYtNmH2LEnLFxuICAgICAgICBNTTogJyVkINij2LTZh9ixJyxcbiAgICAgICAgeTogJ9iz2YbYqScsXG4gICAgICAgIHl5OiAnJWQg2LPZhtmI2KfYqidcbiAgICB9LFxuICAgIHdlZWs6IHtcbiAgICAgICAgZG93OiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95OiA0IC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDR0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICB9XG59KTtcblxuLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSA6IEFyYWJpYyBbYXJdXG4vLyEgYXV0aG9yIDogQWJkZWwgU2FpZDogaHR0cHM6Ly9naXRodWIuY29tL2FiZGVsc2FpZFxuLy8hIGF1dGhvciA6IEFobWVkIEVsa2hhdGliXG4vLyEgYXV0aG9yIDogZm9yYWJpIGh0dHBzOi8vZ2l0aHViLmNvbS9mb3JhYmlcblxudmFyIHN5bWJvbE1hcCQyID0ge1xuICAgICcxJzogJ9mhJyxcbiAgICAnMic6ICfZoicsXG4gICAgJzMnOiAn2aMnLFxuICAgICc0JzogJ9mkJyxcbiAgICAnNSc6ICfZpScsXG4gICAgJzYnOiAn2aYnLFxuICAgICc3JzogJ9mnJyxcbiAgICAnOCc6ICfZqCcsXG4gICAgJzknOiAn2aknLFxuICAgICcwJzogJ9mgJ1xufTtcbnZhciBudW1iZXJNYXAkMSA9IHtcbiAgICAn2aEnOiAnMScsXG4gICAgJ9miJzogJzInLFxuICAgICfZoyc6ICczJyxcbiAgICAn2aQnOiAnNCcsXG4gICAgJ9mlJzogJzUnLFxuICAgICfZpic6ICc2JyxcbiAgICAn2acnOiAnNycsXG4gICAgJ9moJzogJzgnLFxuICAgICfZqSc6ICc5JyxcbiAgICAn2aAnOiAnMCdcbn07XG52YXIgcGx1cmFsRm9ybSQxID0gZnVuY3Rpb24gKG4pIHtcbiAgICByZXR1cm4gbiA9PT0gMCA/IDAgOiBuID09PSAxID8gMSA6IG4gPT09IDIgPyAyIDogbiAlIDEwMCA+PSAzICYmIG4gJSAxMDAgPD0gMTAgPyAzIDogbiAlIDEwMCA+PSAxMSA/IDQgOiA1O1xufTtcbnZhciBwbHVyYWxzJDEgPSB7XG4gICAgcyA6IFsn2KPZgtmEINmF2YYg2KvYp9mG2YrYqScsICfYq9in2YbZitipINmI2KfYrdiv2KknLCBbJ9ir2KfZhtmK2KrYp9mGJywgJ9ir2KfZhtmK2KrZitmGJ10sICclZCDYq9mI2KfZhicsICclZCDYq9in2YbZitipJywgJyVkINir2KfZhtmK2KknXSxcbiAgICBtIDogWyfYo9mC2YQg2YXZhiDYr9mC2YrZgtipJywgJ9iv2YLZitmC2Kkg2YjYp9it2K/YqScsIFsn2K/ZgtmK2YLYqtin2YYnLCAn2K/ZgtmK2YLYqtmK2YYnXSwgJyVkINiv2YLYp9im2YInLCAnJWQg2K/ZgtmK2YLYqScsICclZCDYr9mC2YrZgtipJ10sXG4gICAgaCA6IFsn2KPZgtmEINmF2YYg2LPYp9i52KknLCAn2LPYp9i52Kkg2YjYp9it2K/YqScsIFsn2LPYp9i52KrYp9mGJywgJ9iz2KfYudiq2YrZhiddLCAnJWQg2LPYp9i52KfYqicsICclZCDYs9in2LnYqScsICclZCDYs9in2LnYqSddLFxuICAgIGQgOiBbJ9ij2YLZhCDZhdmGINmK2YjZhScsICfZitmI2YUg2YjYp9it2K8nLCBbJ9mK2YjZhdin2YYnLCAn2YrZiNmF2YrZhiddLCAnJWQg2KPZitin2YUnLCAnJWQg2YrZiNmF2YvYpycsICclZCDZitmI2YUnXSxcbiAgICBNIDogWyfYo9mC2YQg2YXZhiDYtNmH2LEnLCAn2LTZh9ixINmI2KfYrdivJywgWyfYtNmH2LHYp9mGJywgJ9i02YfYsdmK2YYnXSwgJyVkINij2LTZh9ixJywgJyVkINi02YfYsdinJywgJyVkINi02YfYsSddLFxuICAgIHkgOiBbJ9ij2YLZhCDZhdmGINi52KfZhScsICfYudin2YUg2YjYp9it2K8nLCBbJ9i52KfZhdin2YYnLCAn2LnYp9mF2YrZhiddLCAnJWQg2KPYudmI2KfZhScsICclZCDYudin2YXZi9inJywgJyVkINi52KfZhSddXG59O1xudmFyIHBsdXJhbGl6ZSQxID0gZnVuY3Rpb24gKHUpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24gKG51bWJlciwgd2l0aG91dFN1ZmZpeCwgc3RyaW5nLCBpc0Z1dHVyZSkge1xuICAgICAgICB2YXIgZiA9IHBsdXJhbEZvcm0kMShudW1iZXIpLFxuICAgICAgICAgICAgc3RyID0gcGx1cmFscyQxW3VdW3BsdXJhbEZvcm0kMShudW1iZXIpXTtcbiAgICAgICAgaWYgKGYgPT09IDIpIHtcbiAgICAgICAgICAgIHN0ciA9IHN0clt3aXRob3V0U3VmZml4ID8gMCA6IDFdO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBzdHIucmVwbGFjZSgvJWQvaSwgbnVtYmVyKTtcbiAgICB9O1xufTtcbnZhciBtb250aHMkMiA9IFtcbiAgICAn2YrZhtin2YrYsScsXG4gICAgJ9mB2KjYsdin2YrYsScsXG4gICAgJ9mF2KfYsdizJyxcbiAgICAn2KPYqNix2YrZhCcsXG4gICAgJ9mF2KfZitmIJyxcbiAgICAn2YrZiNmG2YrZiCcsXG4gICAgJ9mK2YjZhNmK2YgnLFxuICAgICfYo9i62LPYt9izJyxcbiAgICAn2LPYqNiq2YXYqNixJyxcbiAgICAn2KPZg9iq2YjYqNixJyxcbiAgICAn2YbZiNmB2YXYqNixJyxcbiAgICAn2K/Zitiz2YXYqNixJ1xuXTtcblxuaG9va3MuZGVmaW5lTG9jYWxlKCdhcicsIHtcbiAgICBtb250aHMgOiBtb250aHMkMixcbiAgICBtb250aHNTaG9ydCA6IG1vbnRocyQyLFxuICAgIHdlZWtkYXlzIDogJ9in2YTYo9it2K9f2KfZhNil2KvZhtmK2YZf2KfZhNir2YTYp9ir2KfYoV/Yp9mE2KPYsdio2LnYp9ihX9in2YTYrtmF2YrYs1/Yp9mE2KzZhdi52Klf2KfZhNiz2KjYqicuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0IDogJ9ij2K3Yr1/Ypdir2YbZitmGX9ir2YTYp9ir2KfYoV/Yo9ix2KjYudin2KFf2K7ZhdmK2LNf2KzZhdi52Klf2LPYqNiqJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzTWluIDogJ9itX9mGX9irX9ixX9iuX9isX9izJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzUGFyc2VFeGFjdCA6IHRydWUsXG4gICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgIExUIDogJ0hIOm1tJyxcbiAgICAgICAgTFRTIDogJ0hIOm1tOnNzJyxcbiAgICAgICAgTCA6ICdEL1xcdTIwMEZNL1xcdTIwMEZZWVlZJyxcbiAgICAgICAgTEwgOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICBMTEwgOiAnRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICBMTExMIDogJ2RkZGQgRCBNTU1NIFlZWVkgSEg6bW0nXG4gICAgfSxcbiAgICBtZXJpZGllbVBhcnNlOiAv2LV82YUvLFxuICAgIGlzUE0gOiBmdW5jdGlvbiAoaW5wdXQpIHtcbiAgICAgICAgcmV0dXJuICfZhScgPT09IGlucHV0O1xuICAgIH0sXG4gICAgbWVyaWRpZW0gOiBmdW5jdGlvbiAoaG91ciwgbWludXRlLCBpc0xvd2VyKSB7XG4gICAgICAgIGlmIChob3VyIDwgMTIpIHtcbiAgICAgICAgICAgIHJldHVybiAn2LUnO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuICfZhSc7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIGNhbGVuZGFyIDoge1xuICAgICAgICBzYW1lRGF5OiAnW9in2YTZitmI2YUg2LnZhtivINin2YTYs9in2LnYqV0gTFQnLFxuICAgICAgICBuZXh0RGF5OiAnW9i62K/Zi9inINi52YbYryDYp9mE2LPYp9i52KldIExUJyxcbiAgICAgICAgbmV4dFdlZWs6ICdkZGRkIFvYudmG2K8g2KfZhNiz2KfYudipXSBMVCcsXG4gICAgICAgIGxhc3REYXk6ICdb2KPZhdizINi52YbYryDYp9mE2LPYp9i52KldIExUJyxcbiAgICAgICAgbGFzdFdlZWs6ICdkZGRkIFvYudmG2K8g2KfZhNiz2KfYudipXSBMVCcsXG4gICAgICAgIHNhbWVFbHNlOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJ9io2LnYryAlcycsXG4gICAgICAgIHBhc3QgOiAn2YXZhtiwICVzJyxcbiAgICAgICAgcyA6IHBsdXJhbGl6ZSQxKCdzJyksXG4gICAgICAgIHNzIDogcGx1cmFsaXplJDEoJ3MnKSxcbiAgICAgICAgbSA6IHBsdXJhbGl6ZSQxKCdtJyksXG4gICAgICAgIG1tIDogcGx1cmFsaXplJDEoJ20nKSxcbiAgICAgICAgaCA6IHBsdXJhbGl6ZSQxKCdoJyksXG4gICAgICAgIGhoIDogcGx1cmFsaXplJDEoJ2gnKSxcbiAgICAgICAgZCA6IHBsdXJhbGl6ZSQxKCdkJyksXG4gICAgICAgIGRkIDogcGx1cmFsaXplJDEoJ2QnKSxcbiAgICAgICAgTSA6IHBsdXJhbGl6ZSQxKCdNJyksXG4gICAgICAgIE1NIDogcGx1cmFsaXplJDEoJ00nKSxcbiAgICAgICAgeSA6IHBsdXJhbGl6ZSQxKCd5JyksXG4gICAgICAgIHl5IDogcGx1cmFsaXplJDEoJ3knKVxuICAgIH0sXG4gICAgcHJlcGFyc2U6IGZ1bmN0aW9uIChzdHJpbmcpIHtcbiAgICAgICAgcmV0dXJuIHN0cmluZy5yZXBsYWNlKC9b2aHZotmj2aTZpdmm2afZqNmp2aBdL2csIGZ1bmN0aW9uIChtYXRjaCkge1xuICAgICAgICAgICAgcmV0dXJuIG51bWJlck1hcCQxW21hdGNoXTtcbiAgICAgICAgfSkucmVwbGFjZSgv2IwvZywgJywnKTtcbiAgICB9LFxuICAgIHBvc3Rmb3JtYXQ6IGZ1bmN0aW9uIChzdHJpbmcpIHtcbiAgICAgICAgcmV0dXJuIHN0cmluZy5yZXBsYWNlKC9cXGQvZywgZnVuY3Rpb24gKG1hdGNoKSB7XG4gICAgICAgICAgICByZXR1cm4gc3ltYm9sTWFwJDJbbWF0Y2hdO1xuICAgICAgICB9KS5yZXBsYWNlKC8sL2csICfYjCcpO1xuICAgIH0sXG4gICAgd2VlayA6IHtcbiAgICAgICAgZG93IDogNiwgLy8gU2F0dXJkYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogMTIgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDFzdCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICB9XG59KTtcblxuLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSA6IEF6ZXJiYWlqYW5pIFthel1cbi8vISBhdXRob3IgOiB0b3BjaGl5ZXYgOiBodHRwczovL2dpdGh1Yi5jb20vdG9wY2hpeWV2XG5cbnZhciBzdWZmaXhlcyA9IHtcbiAgICAxOiAnLWluY2knLFxuICAgIDU6ICctaW5jaScsXG4gICAgODogJy1pbmNpJyxcbiAgICA3MDogJy1pbmNpJyxcbiAgICA4MDogJy1pbmNpJyxcbiAgICAyOiAnLW5jaScsXG4gICAgNzogJy1uY2knLFxuICAgIDIwOiAnLW5jaScsXG4gICAgNTA6ICctbmNpJyxcbiAgICAzOiAnLcO8bmPDvCcsXG4gICAgNDogJy3DvG5jw7wnLFxuICAgIDEwMDogJy3DvG5jw7wnLFxuICAgIDY6ICctbmPEsScsXG4gICAgOTogJy11bmN1JyxcbiAgICAxMDogJy11bmN1JyxcbiAgICAzMDogJy11bmN1JyxcbiAgICA2MDogJy3EsW5jxLEnLFxuICAgIDkwOiAnLcSxbmPEsSdcbn07XG5cbmhvb2tzLmRlZmluZUxvY2FsZSgnYXonLCB7XG4gICAgbW9udGhzIDogJ3lhbnZhcl9mZXZyYWxfbWFydF9hcHJlbF9tYXlfaXl1bl9peXVsX2F2cXVzdF9zZW50eWFicl9va3R5YWJyX25veWFicl9kZWthYnInLnNwbGl0KCdfJyksXG4gICAgbW9udGhzU2hvcnQgOiAneWFuX2Zldl9tYXJfYXByX21heV9peW5faXlsX2F2cV9zZW5fb2t0X25veV9kZWsnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXMgOiAnQmF6YXJfQmF6YXIgZXJ0yZlzaV/Dh8mZcsWfyZluYsmZIGF4xZ9hbcSxX8OHyZlyxZ/JmW5iyZlfQ8O8bcmZIGF4xZ9hbcSxX0PDvG3JmV/FnsmZbmLJmScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0IDogJ0Jhel9CekVfw4dBeF/Dh8mZcl9DQXhfQ8O8bV/FnsmZbicuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbiA6ICdCel9CRV/Dh0Ffw4fJmV9DQV9Dw7xfxZ7JmScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdISDptbScsXG4gICAgICAgIExUUyA6ICdISDptbTpzcycsXG4gICAgICAgIEwgOiAnREQuTU0uWVlZWScsXG4gICAgICAgIExMIDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgTExMIDogJ0QgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgTExMTCA6ICdkZGRkLCBEIE1NTU0gWVlZWSBISDptbSdcbiAgICB9LFxuICAgIGNhbGVuZGFyIDoge1xuICAgICAgICBzYW1lRGF5IDogJ1tidWfDvG4gc2FhdF0gTFQnLFxuICAgICAgICBuZXh0RGF5IDogJ1tzYWJhaCBzYWF0XSBMVCcsXG4gICAgICAgIG5leHRXZWVrIDogJ1tnyZlsyZluIGjJmWZ0yZldIGRkZGQgW3NhYXRdIExUJyxcbiAgICAgICAgbGFzdERheSA6ICdbZMO8bsmZbl0gTFQnLFxuICAgICAgICBsYXN0V2VlayA6ICdba2XDp8mZbiBoyZlmdMmZXSBkZGRkIFtzYWF0XSBMVCcsXG4gICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6ICclcyBzb25yYScsXG4gICAgICAgIHBhc3QgOiAnJXMgyZl2dsmZbCcsXG4gICAgICAgIHMgOiAnYmlybmXDp8mZIHNhbml5ecmZJyxcbiAgICAgICAgc3MgOiAnJWQgc2FuaXnJmScsXG4gICAgICAgIG0gOiAnYmlyIGTJmXFpccmZJyxcbiAgICAgICAgbW0gOiAnJWQgZMmZcWlxyZknLFxuICAgICAgICBoIDogJ2JpciBzYWF0JyxcbiAgICAgICAgaGggOiAnJWQgc2FhdCcsXG4gICAgICAgIGQgOiAnYmlyIGfDvG4nLFxuICAgICAgICBkZCA6ICclZCBnw7xuJyxcbiAgICAgICAgTSA6ICdiaXIgYXknLFxuICAgICAgICBNTSA6ICclZCBheScsXG4gICAgICAgIHkgOiAnYmlyIGlsJyxcbiAgICAgICAgeXkgOiAnJWQgaWwnXG4gICAgfSxcbiAgICBtZXJpZGllbVBhcnNlOiAvZ2VjyZl8c8mZaMmZcnxnw7xuZMO8enxheMWfYW0vLFxuICAgIGlzUE0gOiBmdW5jdGlvbiAoaW5wdXQpIHtcbiAgICAgICAgcmV0dXJuIC9eKGfDvG5kw7x6fGF4xZ9hbSkkLy50ZXN0KGlucHV0KTtcbiAgICB9LFxuICAgIG1lcmlkaWVtIDogZnVuY3Rpb24gKGhvdXIsIG1pbnV0ZSwgaXNMb3dlcikge1xuICAgICAgICBpZiAoaG91ciA8IDQpIHtcbiAgICAgICAgICAgIHJldHVybiAnZ2VjyZknO1xuICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAxMikge1xuICAgICAgICAgICAgcmV0dXJuICdzyZloyZlyJztcbiAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgMTcpIHtcbiAgICAgICAgICAgIHJldHVybiAnZ8O8bmTDvHonO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuICdheMWfYW0nO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn0tKMSxbmPEsXxpbmNpfG5jaXzDvG5jw7x8bmPEsXx1bmN1KS8sXG4gICAgb3JkaW5hbCA6IGZ1bmN0aW9uIChudW1iZXIpIHtcbiAgICAgICAgaWYgKG51bWJlciA9PT0gMCkgeyAgLy8gc3BlY2lhbCBjYXNlIGZvciB6ZXJvXG4gICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJy3EsW5jxLEnO1xuICAgICAgICB9XG4gICAgICAgIHZhciBhID0gbnVtYmVyICUgMTAsXG4gICAgICAgICAgICBiID0gbnVtYmVyICUgMTAwIC0gYSxcbiAgICAgICAgICAgIGMgPSBudW1iZXIgPj0gMTAwID8gMTAwIDogbnVsbDtcbiAgICAgICAgcmV0dXJuIG51bWJlciArIChzdWZmaXhlc1thXSB8fCBzdWZmaXhlc1tiXSB8fCBzdWZmaXhlc1tjXSk7XG4gICAgfSxcbiAgICB3ZWVrIDoge1xuICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogNyAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gMXN0IGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH1cbn0pO1xuXG4vLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogQmVsYXJ1c2lhbiBbYmVdXG4vLyEgYXV0aG9yIDogRG1pdHJ5IERlbWlkb3YgOiBodHRwczovL2dpdGh1Yi5jb20vZGVtaWRvdjkxXG4vLyEgYXV0aG9yOiBQcmFsZXNrYTogaHR0cDovL3ByYWxlc2thLnByby9cbi8vISBBdXRob3IgOiBNZW5lbGlvbiBFbGVuc8O6bGUgOiBodHRwczovL2dpdGh1Yi5jb20vT2lyZVxuXG5mdW5jdGlvbiBwbHVyYWwod29yZCwgbnVtKSB7XG4gICAgdmFyIGZvcm1zID0gd29yZC5zcGxpdCgnXycpO1xuICAgIHJldHVybiBudW0gJSAxMCA9PT0gMSAmJiBudW0gJSAxMDAgIT09IDExID8gZm9ybXNbMF0gOiAobnVtICUgMTAgPj0gMiAmJiBudW0gJSAxMCA8PSA0ICYmIChudW0gJSAxMDAgPCAxMCB8fCBudW0gJSAxMDAgPj0gMjApID8gZm9ybXNbMV0gOiBmb3Jtc1syXSk7XG59XG5mdW5jdGlvbiByZWxhdGl2ZVRpbWVXaXRoUGx1cmFsKG51bWJlciwgd2l0aG91dFN1ZmZpeCwga2V5KSB7XG4gICAgdmFyIGZvcm1hdCA9IHtcbiAgICAgICAgJ3NzJzogd2l0aG91dFN1ZmZpeCA/ICfRgdC10LrRg9C90LTQsF/RgdC10LrRg9C90LTRi1/RgdC10LrRg9C90LQnIDogJ9GB0LXQutGD0L3QtNGDX9GB0LXQutGD0L3QtNGLX9GB0LXQutGD0L3QtCcsXG4gICAgICAgICdtbSc6IHdpdGhvdXRTdWZmaXggPyAn0YXQstGW0LvRltC90LBf0YXQstGW0LvRltC90Ytf0YXQstGW0LvRltC9JyA6ICfRhdCy0ZbQu9GW0L3Rg1/RhdCy0ZbQu9GW0L3Ri1/RhdCy0ZbQu9GW0L0nLFxuICAgICAgICAnaGgnOiB3aXRob3V0U3VmZml4ID8gJ9Cz0LDQtNC30ZbQvdCwX9Cz0LDQtNC30ZbQvdGLX9Cz0LDQtNC30ZbQvScgOiAn0LPQsNC00LfRltC90YNf0LPQsNC00LfRltC90Ytf0LPQsNC00LfRltC9JyxcbiAgICAgICAgJ2RkJzogJ9C00LfQtdC90Yxf0LTQvdGWX9C00LfRkdC9JyxcbiAgICAgICAgJ01NJzogJ9C80LXRgdGP0YZf0LzQtdGB0Y/RhtGLX9C80LXRgdGP0YbQsNGeJyxcbiAgICAgICAgJ3l5JzogJ9Cz0L7QtF/Qs9Cw0LTRi1/Qs9Cw0LTQvtGeJ1xuICAgIH07XG4gICAgaWYgKGtleSA9PT0gJ20nKSB7XG4gICAgICAgIHJldHVybiB3aXRob3V0U3VmZml4ID8gJ9GF0LLRltC70ZbQvdCwJyA6ICfRhdCy0ZbQu9GW0L3Rgyc7XG4gICAgfVxuICAgIGVsc2UgaWYgKGtleSA9PT0gJ2gnKSB7XG4gICAgICAgIHJldHVybiB3aXRob3V0U3VmZml4ID8gJ9Cz0LDQtNC30ZbQvdCwJyA6ICfQs9Cw0LTQt9GW0L3Rgyc7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICByZXR1cm4gbnVtYmVyICsgJyAnICsgcGx1cmFsKGZvcm1hdFtrZXldLCArbnVtYmVyKTtcbiAgICB9XG59XG5cbmhvb2tzLmRlZmluZUxvY2FsZSgnYmUnLCB7XG4gICAgbW9udGhzIDoge1xuICAgICAgICBmb3JtYXQ6ICfRgdGC0YPQtNC30LXQvdGPX9C70Y7RgtCw0LPQsF/RgdCw0LrQsNCy0ZbQutCwX9C60YDQsNGB0LDQstGW0LrQsF/RgtGA0LDRntC90Y9f0YfRjdGA0LLQtdC90Y9f0LvRltC/0LXQvdGPX9C20L3RltGe0L3Rj1/QstC10YDQsNGB0L3Rj1/QutCw0YHRgtGA0YvRh9C90ZbQutCwX9C70ZbRgdGC0LDQv9Cw0LTQsF/RgdC90LXQttC90Y8nLnNwbGl0KCdfJyksXG4gICAgICAgIHN0YW5kYWxvbmU6ICfRgdGC0YPQtNC30LXQvdGMX9C70Y7RgtGLX9GB0LDQutCw0LLRltC6X9C60YDQsNGB0LDQstGW0Lpf0YLRgNCw0LLQtdC90Yxf0YfRjdGA0LLQtdC90Yxf0LvRltC/0LXQvdGMX9C20L3RltCy0LXQvdGMX9Cy0LXRgNCw0YHQtdC90Yxf0LrQsNGB0YLRgNGL0YfQvdGW0Lpf0LvRltGB0YLQsNC/0LDQtF/RgdC90LXQttCw0L3RjCcuc3BsaXQoJ18nKVxuICAgIH0sXG4gICAgbW9udGhzU2hvcnQgOiAn0YHRgtGD0LRf0LvRjtGCX9GB0LDQul/QutGA0LDRgV/RgtGA0LDQsl/Rh9GN0YDQsl/Qu9GW0L9f0LbQvdGW0LJf0LLQtdGAX9C60LDRgdGCX9C70ZbRgdGCX9GB0L3QtdC2Jy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzIDoge1xuICAgICAgICBmb3JtYXQ6ICfQvdGP0LTQt9C10LvRjl/Qv9Cw0L3Rj9C00LfQtdC70LDQul/QsNGe0YLQvtGA0LDQul/RgdC10YDQsNC00YNf0YfQsNGG0LLQtdGAX9C/0Y/RgtC90ZbRhtGDX9GB0YPQsdC+0YLRgycuc3BsaXQoJ18nKSxcbiAgICAgICAgc3RhbmRhbG9uZTogJ9C90Y/QtNC30LXQu9GPX9C/0LDQvdGP0LTQt9C10LvQsNC6X9Cw0Z7RgtC+0YDQsNC6X9GB0LXRgNCw0LTQsF/Rh9Cw0YbQstC10YBf0L/Rj9GC0L3RltGG0LBf0YHRg9Cx0L7RgtCwJy5zcGxpdCgnXycpLFxuICAgICAgICBpc0Zvcm1hdDogL1xcWyA/W9CS0LJdID8oPzrQvNGW0L3Rg9C70YPRjnzQvdCw0YHRgtGD0L/QvdGD0Y4pPyA/XFxdID9kZGRkL1xuICAgIH0sXG4gICAgd2Vla2RheXNTaG9ydCA6ICfQvdC0X9C/0L1f0LDRgl/RgdGAX9GH0YZf0L/Rgl/RgdCxJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzTWluIDogJ9C90LRf0L/QvV/QsNGCX9GB0YBf0YfRhl/Qv9GCX9GB0LEnLnNwbGl0KCdfJyksXG4gICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgIExUIDogJ0hIOm1tJyxcbiAgICAgICAgTFRTIDogJ0hIOm1tOnNzJyxcbiAgICAgICAgTCA6ICdERC5NTS5ZWVlZJyxcbiAgICAgICAgTEwgOiAnRCBNTU1NIFlZWVkg0LMuJyxcbiAgICAgICAgTExMIDogJ0QgTU1NTSBZWVlZINCzLiwgSEg6bW0nLFxuICAgICAgICBMTExMIDogJ2RkZGQsIEQgTU1NTSBZWVlZINCzLiwgSEg6bW0nXG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheTogJ1vQodGR0L3QvdGPINGeXSBMVCcsXG4gICAgICAgIG5leHREYXk6ICdb0JfQsNGe0YLRgNCwINGeXSBMVCcsXG4gICAgICAgIGxhc3REYXk6ICdb0KPRh9C+0YDQsCDRnl0gTFQnLFxuICAgICAgICBuZXh0V2VlazogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuICdb0KNdIGRkZGQgW9GeXSBMVCc7XG4gICAgICAgIH0sXG4gICAgICAgIGxhc3RXZWVrOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBzd2l0Y2ggKHRoaXMuZGF5KCkpIHtcbiAgICAgICAgICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICAgICAgY2FzZSAzOlxuICAgICAgICAgICAgICAgIGNhc2UgNTpcbiAgICAgICAgICAgICAgICBjYXNlIDY6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnW9CjINC80ZbQvdGD0LvRg9GOXSBkZGRkIFvRnl0gTFQnO1xuICAgICAgICAgICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgICAgICAgY2FzZSA0OlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1vQoyDQvNGW0L3Rg9C70YtdIGRkZGQgW9GeXSBMVCc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIHNhbWVFbHNlOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJ9C/0YDQsNC3ICVzJyxcbiAgICAgICAgcGFzdCA6ICclcyDRgtCw0LzRgycsXG4gICAgICAgIHMgOiAn0L3QtdC60LDQu9GM0LrRliDRgdC10LrRg9C90LQnLFxuICAgICAgICBtIDogcmVsYXRpdmVUaW1lV2l0aFBsdXJhbCxcbiAgICAgICAgbW0gOiByZWxhdGl2ZVRpbWVXaXRoUGx1cmFsLFxuICAgICAgICBoIDogcmVsYXRpdmVUaW1lV2l0aFBsdXJhbCxcbiAgICAgICAgaGggOiByZWxhdGl2ZVRpbWVXaXRoUGx1cmFsLFxuICAgICAgICBkIDogJ9C00LfQtdC90YwnLFxuICAgICAgICBkZCA6IHJlbGF0aXZlVGltZVdpdGhQbHVyYWwsXG4gICAgICAgIE0gOiAn0LzQtdGB0Y/RhicsXG4gICAgICAgIE1NIDogcmVsYXRpdmVUaW1lV2l0aFBsdXJhbCxcbiAgICAgICAgeSA6ICfQs9C+0LQnLFxuICAgICAgICB5eSA6IHJlbGF0aXZlVGltZVdpdGhQbHVyYWxcbiAgICB9LFxuICAgIG1lcmlkaWVtUGFyc2U6IC/QvdC+0YfRi3zRgNCw0L3RltGG0Yt80LTQvdGPfNCy0LXRh9Cw0YDQsC8sXG4gICAgaXNQTSA6IGZ1bmN0aW9uIChpbnB1dCkge1xuICAgICAgICByZXR1cm4gL14o0LTQvdGPfNCy0LXRh9Cw0YDQsCkkLy50ZXN0KGlucHV0KTtcbiAgICB9LFxuICAgIG1lcmlkaWVtIDogZnVuY3Rpb24gKGhvdXIsIG1pbnV0ZSwgaXNMb3dlcikge1xuICAgICAgICBpZiAoaG91ciA8IDQpIHtcbiAgICAgICAgICAgIHJldHVybiAn0L3QvtGH0YsnO1xuICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAxMikge1xuICAgICAgICAgICAgcmV0dXJuICfRgNCw0L3RltGG0YsnO1xuICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAxNykge1xuICAgICAgICAgICAgcmV0dXJuICfQtNC90Y8nO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuICfQstC10YfQsNGA0LAnO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn0tKNGWfNGLfNCz0LApLyxcbiAgICBvcmRpbmFsOiBmdW5jdGlvbiAobnVtYmVyLCBwZXJpb2QpIHtcbiAgICAgICAgc3dpdGNoIChwZXJpb2QpIHtcbiAgICAgICAgICAgIGNhc2UgJ00nOlxuICAgICAgICAgICAgY2FzZSAnZCc6XG4gICAgICAgICAgICBjYXNlICdEREQnOlxuICAgICAgICAgICAgY2FzZSAndyc6XG4gICAgICAgICAgICBjYXNlICdXJzpcbiAgICAgICAgICAgICAgICByZXR1cm4gKG51bWJlciAlIDEwID09PSAyIHx8IG51bWJlciAlIDEwID09PSAzKSAmJiAobnVtYmVyICUgMTAwICE9PSAxMiAmJiBudW1iZXIgJSAxMDAgIT09IDEzKSA/IG51bWJlciArICct0ZYnIDogbnVtYmVyICsgJy3Riyc7XG4gICAgICAgICAgICBjYXNlICdEJzpcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJy3Qs9CwJztcbiAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlcjtcbiAgICAgICAgfVxuICAgIH0sXG4gICAgd2VlayA6IHtcbiAgICAgICAgZG93IDogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgIGRveSA6IDcgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDFzdCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICB9XG59KTtcblxuLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSA6IEJ1bGdhcmlhbiBbYmddXG4vLyEgYXV0aG9yIDogS3Jhc2VuIEJvcmlzb3YgOiBodHRwczovL2dpdGh1Yi5jb20va3JhelxuXG5ob29rcy5kZWZpbmVMb2NhbGUoJ2JnJywge1xuICAgIG1vbnRocyA6ICfRj9C90YPQsNGA0Lhf0YTQtdCy0YDRg9Cw0YDQuF/QvNCw0YDRgl/QsNC/0YDQuNC7X9C80LDQuV/RjtC90Lhf0Y7Qu9C4X9Cw0LLQs9GD0YHRgl/RgdC10L/RgtC10LzQstGA0Lhf0L7QutGC0L7QvNCy0YDQuF/QvdC+0LXQvNCy0YDQuF/QtNC10LrQtdC80LLRgNC4Jy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0IDogJ9GP0L3RgF/RhNC10LJf0LzQsNGAX9Cw0L/RgF/QvNCw0Llf0Y7QvdC4X9GO0LvQuF/QsNCy0LNf0YHQtdC/X9C+0LrRgl/QvdC+0LVf0LTQtdC6Jy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzIDogJ9C90LXQtNC10LvRj1/Qv9C+0L3QtdC00LXQu9C90LjQul/QstGC0L7RgNC90LjQul/RgdGA0Y/QtNCwX9GH0LXRgtCy0YrRgNGC0YrQul/Qv9C10YLRitC6X9GB0YrQsdC+0YLQsCcuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0IDogJ9C90LXQtF/Qv9C+0L1f0LLRgtC+X9GB0YDRj1/Rh9C10YJf0L/QtdGCX9GB0YrQsScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbiA6ICfQvdC0X9C/0L1f0LLRgl/RgdGAX9GH0YJf0L/Rgl/RgdCxJy5zcGxpdCgnXycpLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdIOm1tJyxcbiAgICAgICAgTFRTIDogJ0g6bW06c3MnLFxuICAgICAgICBMIDogJ0QuTU0uWVlZWScsXG4gICAgICAgIExMIDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgTExMIDogJ0QgTU1NTSBZWVlZIEg6bW0nLFxuICAgICAgICBMTExMIDogJ2RkZGQsIEQgTU1NTSBZWVlZIEg6bW0nXG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheSA6ICdb0JTQvdC10YEg0LJdIExUJyxcbiAgICAgICAgbmV4dERheSA6ICdb0KPRgtGA0LUg0LJdIExUJyxcbiAgICAgICAgbmV4dFdlZWsgOiAnZGRkZCBb0LJdIExUJyxcbiAgICAgICAgbGFzdERheSA6ICdb0JLRh9C10YDQsCDQsl0gTFQnLFxuICAgICAgICBsYXN0V2VlayA6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHN3aXRjaCAodGhpcy5kYXkoKSkge1xuICAgICAgICAgICAgICAgIGNhc2UgMDpcbiAgICAgICAgICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgICAgICAgY2FzZSA2OlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1vQkiDQuNC30LzQuNC90LDQu9Cw0YLQsF0gZGRkZCBb0LJdIExUJztcbiAgICAgICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgICAgIGNhc2UgNDpcbiAgICAgICAgICAgICAgICBjYXNlIDU6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnW9CSINC40LfQvNC40L3QsNC70LjRj10gZGRkZCBb0LJdIExUJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJ9GB0LvQtdC0ICVzJyxcbiAgICAgICAgcGFzdCA6ICfQv9GA0LXQtNC4ICVzJyxcbiAgICAgICAgcyA6ICfQvdGP0LrQvtC70LrQviDRgdC10LrRg9C90LTQuCcsXG4gICAgICAgIHNzIDogJyVkINGB0LXQutGD0L3QtNC4JyxcbiAgICAgICAgbSA6ICfQvNC40L3Rg9GC0LAnLFxuICAgICAgICBtbSA6ICclZCDQvNC40L3Rg9GC0LgnLFxuICAgICAgICBoIDogJ9GH0LDRgScsXG4gICAgICAgIGhoIDogJyVkINGH0LDRgdCwJyxcbiAgICAgICAgZCA6ICfQtNC10L0nLFxuICAgICAgICBkZCA6ICclZCDQtNC90LgnLFxuICAgICAgICBNIDogJ9C80LXRgdC10YYnLFxuICAgICAgICBNTSA6ICclZCDQvNC10YHQtdGG0LAnLFxuICAgICAgICB5IDogJ9Cz0L7QtNC40L3QsCcsXG4gICAgICAgIHl5IDogJyVkINCz0L7QtNC40L3QuCdcbiAgICB9LFxuICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfS0o0LXQsnzQtdC9fNGC0Lh80LLQuHzRgNC4fNC80LgpLyxcbiAgICBvcmRpbmFsIDogZnVuY3Rpb24gKG51bWJlcikge1xuICAgICAgICB2YXIgbGFzdERpZ2l0ID0gbnVtYmVyICUgMTAsXG4gICAgICAgICAgICBsYXN0MkRpZ2l0cyA9IG51bWJlciAlIDEwMDtcbiAgICAgICAgaWYgKG51bWJlciA9PT0gMCkge1xuICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICct0LXQsic7XG4gICAgICAgIH0gZWxzZSBpZiAobGFzdDJEaWdpdHMgPT09IDApIHtcbiAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAnLdC10L0nO1xuICAgICAgICB9IGVsc2UgaWYgKGxhc3QyRGlnaXRzID4gMTAgJiYgbGFzdDJEaWdpdHMgPCAyMCkge1xuICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICct0YLQuCc7XG4gICAgICAgIH0gZWxzZSBpZiAobGFzdERpZ2l0ID09PSAxKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJy3QstC4JztcbiAgICAgICAgfSBlbHNlIGlmIChsYXN0RGlnaXQgPT09IDIpIHtcbiAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAnLdGA0LgnO1xuICAgICAgICB9IGVsc2UgaWYgKGxhc3REaWdpdCA9PT0gNyB8fCBsYXN0RGlnaXQgPT09IDgpIHtcbiAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAnLdC80LgnO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICct0YLQuCc7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIHdlZWsgOiB7XG4gICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICBkb3kgOiA3ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiAxc3QgaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgfVxufSk7XG5cbi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBCYW1iYXJhIFtibV1cbi8vISBhdXRob3IgOiBFc3RlbGxlIENvbW1lbnQgOiBodHRwczovL2dpdGh1Yi5jb20vZXN0ZWxsZWNvbW1lbnRcbi8vIExhbmd1YWdlIGNvbnRhY3QgcGVyc29uIDogQWJkb3VmYXRhIEthbmUgOiBodHRwczovL2dpdGh1Yi5jb20vYWJkb3VmYXRhXG5cbmhvb2tzLmRlZmluZUxvY2FsZSgnYm0nLCB7XG4gICAgbW9udGhzIDogJ1phbnd1eWVrYWxvX0Zld3VydXlla2Fsb19NYXJpc2lrYWxvX0F3aXJpbGlrYWxvX03Jm2thbG9fWnV3yZtua2Fsb19adWx1eWVrYWxvX1V0aWthbG9fU8mbdGFuYnVydWthbG9fyZRrdXTJlGJ1cnVrYWxvX05vd2FuYnVydWthbG9fRGVzYW5idXJ1a2Fsbycuc3BsaXQoJ18nKSxcbiAgICBtb250aHNTaG9ydCA6ICdaYW5fRmV3X01hcl9Bd2lfTcmbX1p1d19adWxfVXRpX1PJm3RfyZRrdV9Ob3dfRGVzJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzIDogJ0thcmlfTnTJm27Jm25fVGFyYXRhX0FyYWJhX0FsYW1pc2FfSnVtYV9TaWJpcmknLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydCA6ICdLYXJfTnTJm19UYXJfQXJhX0FsYV9KdW1fU2liJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzTWluIDogJ0thX050X1RhX0FyX0FsX0p1X1NpJy5zcGxpdCgnXycpLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdISDptbScsXG4gICAgICAgIExUUyA6ICdISDptbTpzcycsXG4gICAgICAgIEwgOiAnREQvTU0vWVlZWScsXG4gICAgICAgIExMIDogJ01NTU0gW3RpbGVdIEQgW3Nhbl0gWVlZWScsXG4gICAgICAgIExMTCA6ICdNTU1NIFt0aWxlXSBEIFtzYW5dIFlZWVkgW2zJm3LJm10gSEg6bW0nLFxuICAgICAgICBMTExMIDogJ2RkZGQgTU1NTSBbdGlsZV0gRCBbc2FuXSBZWVlZIFtsyZtyyZtdIEhIOm1tJ1xuICAgIH0sXG4gICAgY2FsZW5kYXIgOiB7XG4gICAgICAgIHNhbWVEYXkgOiAnW0JpIGzJm3LJm10gTFQnLFxuICAgICAgICBuZXh0RGF5IDogJ1tTaW5pIGzJm3LJm10gTFQnLFxuICAgICAgICBuZXh0V2VlayA6ICdkZGRkIFtkb24gbMmbcsmbXSBMVCcsXG4gICAgICAgIGxhc3REYXkgOiAnW0t1bnUgbMmbcsmbXSBMVCcsXG4gICAgICAgIGxhc3RXZWVrIDogJ2RkZGQgW3TJm23Jm25lbiBsyZtyyZtdIExUJyxcbiAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJyVzIGvJlG7JlCcsXG4gICAgICAgIHBhc3QgOiAnYSBiyZsgJXMgYsmUJyxcbiAgICAgICAgcyA6ICdzYW5nYSBkYW1hIGRhbWEnLFxuICAgICAgICBzcyA6ICdzZWtvbmRpICVkJyxcbiAgICAgICAgbSA6ICdtaW5pdGkga2VsZW4nLFxuICAgICAgICBtbSA6ICdtaW5pdGkgJWQnLFxuICAgICAgICBoIDogJ2zJm3LJmyBrZWxlbicsXG4gICAgICAgIGhoIDogJ2zJm3LJmyAlZCcsXG4gICAgICAgIGQgOiAndGlsZSBrZWxlbicsXG4gICAgICAgIGRkIDogJ3RpbGUgJWQnLFxuICAgICAgICBNIDogJ2thbG8ga2VsZW4nLFxuICAgICAgICBNTSA6ICdrYWxvICVkJyxcbiAgICAgICAgeSA6ICdzYW4ga2VsZW4nLFxuICAgICAgICB5eSA6ICdzYW4gJWQnXG4gICAgfSxcbiAgICB3ZWVrIDoge1xuICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogNCAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH1cbn0pO1xuXG4vLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogQmVuZ2FsaSBbYm5dXG4vLyEgYXV0aG9yIDogS2F1c2hpayBHYW5kaGkgOiBodHRwczovL2dpdGh1Yi5jb20va2F1c2hpa2dhbmRoaVxuXG52YXIgc3ltYm9sTWFwJDMgPSB7XG4gICAgJzEnOiAn4KenJyxcbiAgICAnMic6ICfgp6gnLFxuICAgICczJzogJ+CnqScsXG4gICAgJzQnOiAn4KeqJyxcbiAgICAnNSc6ICfgp6snLFxuICAgICc2JzogJ+CnrCcsXG4gICAgJzcnOiAn4KetJyxcbiAgICAnOCc6ICfgp64nLFxuICAgICc5JzogJ+CnrycsXG4gICAgJzAnOiAn4KemJ1xufTtcbnZhciBudW1iZXJNYXAkMiA9IHtcbiAgICAn4KenJzogJzEnLFxuICAgICfgp6gnOiAnMicsXG4gICAgJ+CnqSc6ICczJyxcbiAgICAn4KeqJzogJzQnLFxuICAgICfgp6snOiAnNScsXG4gICAgJ+CnrCc6ICc2JyxcbiAgICAn4KetJzogJzcnLFxuICAgICfgp64nOiAnOCcsXG4gICAgJ+Cnryc6ICc5JyxcbiAgICAn4KemJzogJzAnXG59O1xuXG5ob29rcy5kZWZpbmVMb2NhbGUoJ2JuJywge1xuICAgIG1vbnRocyA6ICfgppzgpr7gpqjgp4Hgp5/gpr7gprDgp4Bf4Kar4KeH4Kas4KeN4Kaw4KeB4Kef4Ka+4Kaw4Ka/X+CmruCmvuCmsOCnjeCmml/gpo/gpqrgp43gprDgpr/gprJf4Kau4KeHX+CmnOCngeCmqF/gppzgp4HgprLgpr7gpodf4KaG4KaX4Ka44KeN4KafX+CmuOCnh+CmquCnjeCmn+Cnh+CmruCnjeCmrOCmsF/gpoXgppXgp43gpp/gp4vgpqzgprBf4Kao4Kat4KeH4Kau4KeN4Kas4KawX+CmoeCmv+CmuOCnh+CmruCnjeCmrOCmsCcuc3BsaXQoJ18nKSxcbiAgICBtb250aHNTaG9ydCA6ICfgppzgpr7gpqjgp4Ff4Kar4KeH4KasX+CmruCmvuCmsOCnjeCmml/gpo/gpqrgp43gprBf4Kau4KeHX+CmnOCngeCmqF/gppzgp4HgprJf4KaG4KaXX+CmuOCnh+CmquCnjeCmn1/gpoXgppXgp43gpp/gp4tf4Kao4Kat4KeHX+CmoeCmv+CmuOCnhycuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5cyA6ICfgprDgpqzgpr/gpqzgpr7gprBf4Ka44KeL4Kau4Kas4Ka+4KawX+CmruCmmeCnjeCml+CmsuCmrOCmvuCmsF/gpqzgp4Hgpqfgpqzgpr7gprBf4Kas4KeD4Ka54Ka44KeN4Kaq4Kak4Ka/4Kas4Ka+4KawX+CmtuCngeCmleCnjeCmsOCmrOCmvuCmsF/gprbgpqjgpr/gpqzgpr7gprAnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydCA6ICfgprDgpqzgpr9f4Ka44KeL4KauX+CmruCmmeCnjeCml+Cmsl/gpqzgp4Hgpqdf4Kas4KeD4Ka54Ka44KeN4Kaq4Kak4Ka/X+CmtuCngeCmleCnjeCmsF/gprbgpqjgpr8nLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW4gOiAn4Kaw4Kas4Ka/X+CmuOCni+Cmrl/gpq7gppngp43gppdf4Kas4KeB4KanX+CmrOCng+CmueCmg1/gprbgp4HgppXgp43gprBf4Ka24Kao4Ka/Jy5zcGxpdCgnXycpLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdBIGg6bW0g4Ka44Kau4KefJyxcbiAgICAgICAgTFRTIDogJ0EgaDptbTpzcyDgprjgpq7gp58nLFxuICAgICAgICBMIDogJ0REL01NL1lZWVknLFxuICAgICAgICBMTCA6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgIExMTCA6ICdEIE1NTU0gWVlZWSwgQSBoOm1tIOCmuOCmruCnnycsXG4gICAgICAgIExMTEwgOiAnZGRkZCwgRCBNTU1NIFlZWVksIEEgaDptbSDgprjgpq7gp58nXG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheSA6ICdb4KaG4KacXSBMVCcsXG4gICAgICAgIG5leHREYXkgOiAnW+CmhuCml+CmvuCmruCngOCmleCmvuCmsl0gTFQnLFxuICAgICAgICBuZXh0V2VlayA6ICdkZGRkLCBMVCcsXG4gICAgICAgIGxhc3REYXkgOiAnW+Cml+CmpOCmleCmvuCmsl0gTFQnLFxuICAgICAgICBsYXN0V2VlayA6ICdb4KaX4KakXSBkZGRkLCBMVCcsXG4gICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6ICclcyDgpqrgprDgp4cnLFxuICAgICAgICBwYXN0IDogJyVzIOCmhuCml+CnhycsXG4gICAgICAgIHMgOiAn4KaV4Kef4KeH4KaVIOCmuOCnh+CmleCnh+CmqOCnjeCmoScsXG4gICAgICAgIHNzIDogJyVkIOCmuOCnh+CmleCnh+CmqOCnjeCmoScsXG4gICAgICAgIG0gOiAn4KaP4KaVIOCmruCmv+CmqOCmv+CmnycsXG4gICAgICAgIG1tIDogJyVkIOCmruCmv+CmqOCmv+CmnycsXG4gICAgICAgIGggOiAn4KaP4KaVIOCmmOCmqOCnjeCmn+CmvicsXG4gICAgICAgIGhoIDogJyVkIOCmmOCmqOCnjeCmn+CmvicsXG4gICAgICAgIGQgOiAn4KaP4KaVIOCmpuCmv+CmqCcsXG4gICAgICAgIGRkIDogJyVkIOCmpuCmv+CmqCcsXG4gICAgICAgIE0gOiAn4KaP4KaVIOCmruCmvuCmuCcsXG4gICAgICAgIE1NIDogJyVkIOCmruCmvuCmuCcsXG4gICAgICAgIHkgOiAn4KaP4KaVIOCmrOCmm+CmsCcsXG4gICAgICAgIHl5IDogJyVkIOCmrOCmm+CmsCdcbiAgICB9LFxuICAgIHByZXBhcnNlOiBmdW5jdGlvbiAoc3RyaW5nKSB7XG4gICAgICAgIHJldHVybiBzdHJpbmcucmVwbGFjZSgvW+Cnp+CnqOCnqeCnquCnq+CnrOCnreCnruCnr+Cnpl0vZywgZnVuY3Rpb24gKG1hdGNoKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVtYmVyTWFwJDJbbWF0Y2hdO1xuICAgICAgICB9KTtcbiAgICB9LFxuICAgIHBvc3Rmb3JtYXQ6IGZ1bmN0aW9uIChzdHJpbmcpIHtcbiAgICAgICAgcmV0dXJuIHN0cmluZy5yZXBsYWNlKC9cXGQvZywgZnVuY3Rpb24gKG1hdGNoKSB7XG4gICAgICAgICAgICByZXR1cm4gc3ltYm9sTWFwJDNbbWF0Y2hdO1xuICAgICAgICB9KTtcbiAgICB9LFxuICAgIG1lcmlkaWVtUGFyc2U6IC/gprDgpr7gpqR84Ka44KaV4Ka+4KayfOCmpuCngeCmquCngeCmsHzgpqzgpr/gppXgpr7gprJ84Kaw4Ka+4KakLyxcbiAgICBtZXJpZGllbUhvdXIgOiBmdW5jdGlvbiAoaG91ciwgbWVyaWRpZW0pIHtcbiAgICAgICAgaWYgKGhvdXIgPT09IDEyKSB7XG4gICAgICAgICAgICBob3VyID0gMDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoKG1lcmlkaWVtID09PSAn4Kaw4Ka+4KakJyAmJiBob3VyID49IDQpIHx8XG4gICAgICAgICAgICAgICAgKG1lcmlkaWVtID09PSAn4Kam4KeB4Kaq4KeB4KawJyAmJiBob3VyIDwgNSkgfHxcbiAgICAgICAgICAgICAgICBtZXJpZGllbSA9PT0gJ+CmrOCmv+CmleCmvuCmsicpIHtcbiAgICAgICAgICAgIHJldHVybiBob3VyICsgMTI7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gaG91cjtcbiAgICAgICAgfVxuICAgIH0sXG4gICAgbWVyaWRpZW0gOiBmdW5jdGlvbiAoaG91ciwgbWludXRlLCBpc0xvd2VyKSB7XG4gICAgICAgIGlmIChob3VyIDwgNCkge1xuICAgICAgICAgICAgcmV0dXJuICfgprDgpr7gpqQnO1xuICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAxMCkge1xuICAgICAgICAgICAgcmV0dXJuICfgprjgppXgpr7gprInO1xuICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAxNykge1xuICAgICAgICAgICAgcmV0dXJuICfgpqbgp4Hgpqrgp4HgprAnO1xuICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAyMCkge1xuICAgICAgICAgICAgcmV0dXJuICfgpqzgpr/gppXgpr7gprInO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuICfgprDgpr7gpqQnO1xuICAgICAgICB9XG4gICAgfSxcbiAgICB3ZWVrIDoge1xuICAgICAgICBkb3cgOiAwLCAvLyBTdW5kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogNiAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gMXN0IGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH1cbn0pO1xuXG4vLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogVGliZXRhbiBbYm9dXG4vLyEgYXV0aG9yIDogVGh1cHRlbiBOLiBDaGFrcmlzaGFyIDogaHR0cHM6Ly9naXRodWIuY29tL3ZhanJhZG9nXG5cbnZhciBzeW1ib2xNYXAkNCA9IHtcbiAgICAnMSc6ICfgvKEnLFxuICAgICcyJzogJ+C8oicsXG4gICAgJzMnOiAn4LyjJyxcbiAgICAnNCc6ICfgvKQnLFxuICAgICc1JzogJ+C8pScsXG4gICAgJzYnOiAn4LymJyxcbiAgICAnNyc6ICfgvKcnLFxuICAgICc4JzogJ+C8qCcsXG4gICAgJzknOiAn4LypJyxcbiAgICAnMCc6ICfgvKAnXG59O1xudmFyIG51bWJlck1hcCQzID0ge1xuICAgICfgvKEnOiAnMScsXG4gICAgJ+C8oic6ICcyJyxcbiAgICAn4LyjJzogJzMnLFxuICAgICfgvKQnOiAnNCcsXG4gICAgJ+C8pSc6ICc1JyxcbiAgICAn4LymJzogJzYnLFxuICAgICfgvKcnOiAnNycsXG4gICAgJ+C8qCc6ICc4JyxcbiAgICAn4LypJzogJzknLFxuICAgICfgvKAnOiAnMCdcbn07XG5cbmhvb2tzLmRlZmluZUxvY2FsZSgnYm8nLCB7XG4gICAgbW9udGhzIDogJ+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/gvrPgvIvgvZbgvIvgvZbgvYXgvbTgvIvgvYLgvYXgvbLgvYLgvIvgvZRf4L2f4L6z4LyL4L2W4LyL4L2W4L2F4L204LyL4L2C4L2J4L2y4L2m4LyL4L2UJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0IDogJ+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/gvrPgvIvgvZbgvIvgvZbgvYXgvbTgvIvgvYLgvYXgvbLgvYLgvIvgvZRf4L2f4L6z4LyL4L2W4LyL4L2W4L2F4L204LyL4L2C4L2J4L2y4L2m4LyL4L2UJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzIDogJ+C9guC9n+C9oOC8i+C9ieC9suC8i+C9mOC8i1/gvYLgvZ/gvaDgvIvgvZ/gvrPgvIvgvZbgvItf4L2C4L2f4L2g4LyL4L2Y4L2y4L2C4LyL4L2R4L2Y4L2i4LyLX+C9guC9n+C9oOC8i+C9o+C+t+C9guC8i+C9lOC8i1/gvYLgvZ/gvaDgvIvgvZXgvbTgvaLgvIvgvZbgvbRf4L2C4L2f4L2g4LyL4L2U4LyL4L2m4L2E4L2m4LyLX+C9guC9n+C9oOC8i+C9puC+pOC9uuC9k+C8i+C9lOC8iycuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0IDogJ+C9ieC9suC8i+C9mOC8i1/gvZ/gvrPgvIvgvZbgvItf4L2Y4L2y4L2C4LyL4L2R4L2Y4L2i4LyLX+C9o+C+t+C9guC8i+C9lOC8i1/gvZXgvbTgvaLgvIvgvZbgvbRf4L2U4LyL4L2m4L2E4L2m4LyLX+C9puC+pOC9uuC9k+C8i+C9lOC8iycuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbiA6ICfgvYngvbLgvIvgvZjgvItf4L2f4L6z4LyL4L2W4LyLX+C9mOC9suC9guC8i+C9keC9mOC9ouC8i1/gvaPgvrfgvYLgvIvgvZTgvItf4L2V4L204L2i4LyL4L2W4L20X+C9lOC8i+C9puC9hOC9puC8i1/gvabgvqTgvbrgvZPgvIvgvZTgvIsnLnNwbGl0KCdfJyksXG4gICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgIExUIDogJ0EgaDptbScsXG4gICAgICAgIExUUyA6ICdBIGg6bW06c3MnLFxuICAgICAgICBMIDogJ0REL01NL1lZWVknLFxuICAgICAgICBMTCA6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgIExMTCA6ICdEIE1NTU0gWVlZWSwgQSBoOm1tJyxcbiAgICAgICAgTExMTCA6ICdkZGRkLCBEIE1NTU0gWVlZWSwgQSBoOm1tJ1xuICAgIH0sXG4gICAgY2FsZW5kYXIgOiB7XG4gICAgICAgIHNhbWVEYXkgOiAnW+C9keC9suC8i+C9ouC9suC9hF0gTFQnLFxuICAgICAgICBuZXh0RGF5IDogJ1vgvabgvYTgvIvgvYngvbLgvZNdIExUJyxcbiAgICAgICAgbmV4dFdlZWsgOiAnW+C9luC9keC9tOC9k+C8i+C9leC+suC9guC8i+C9ouC+l+C9uuC9puC8i+C9mF0sIExUJyxcbiAgICAgICAgbGFzdERheSA6ICdb4L2B4LyL4L2m4L2EXSBMVCcsXG4gICAgICAgIGxhc3RXZWVrIDogJ1vgvZbgvZHgvbTgvZPgvIvgvZXgvrLgvYLgvIvgvZjgvZDgvaDgvIvgvZhdIGRkZGQsIExUJyxcbiAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJyVzIOC9o+C8iycsXG4gICAgICAgIHBhc3QgOiAnJXMg4L2m4L6U4L2T4LyL4L2jJyxcbiAgICAgICAgcyA6ICfgvaPgvZjgvIvgvabgvYQnLFxuICAgICAgICBzcyA6ICclZCDgvabgvpDgvaLgvIvgvYbgvI0nLFxuICAgICAgICBtIDogJ+C9puC+kOC9ouC8i+C9mOC8i+C9guC9heC9suC9gicsXG4gICAgICAgIG1tIDogJyVkIOC9puC+kOC9ouC8i+C9mCcsXG4gICAgICAgIGggOiAn4L2G4L204LyL4L2a4L284L2R4LyL4L2C4L2F4L2y4L2CJyxcbiAgICAgICAgaGggOiAnJWQg4L2G4L204LyL4L2a4L284L2RJyxcbiAgICAgICAgZCA6ICfgvYngvbLgvZPgvIvgvYLgvYXgvbLgvYInLFxuICAgICAgICBkZCA6ICclZCDgvYngvbLgvZPgvIsnLFxuICAgICAgICBNIDogJ+C9n+C+s+C8i+C9luC8i+C9guC9heC9suC9gicsXG4gICAgICAgIE1NIDogJyVkIOC9n+C+s+C8i+C9licsXG4gICAgICAgIHkgOiAn4L2j4L284LyL4L2C4L2F4L2y4L2CJyxcbiAgICAgICAgeXkgOiAnJWQg4L2j4L28J1xuICAgIH0sXG4gICAgcHJlcGFyc2U6IGZ1bmN0aW9uIChzdHJpbmcpIHtcbiAgICAgICAgcmV0dXJuIHN0cmluZy5yZXBsYWNlKC9b4Lyh4Lyi4Lyj4Lyk4Lyl4Lym4Lyn4Lyo4Lyp4LygXS9nLCBmdW5jdGlvbiAobWF0Y2gpIHtcbiAgICAgICAgICAgIHJldHVybiBudW1iZXJNYXAkM1ttYXRjaF07XG4gICAgICAgIH0pO1xuICAgIH0sXG4gICAgcG9zdGZvcm1hdDogZnVuY3Rpb24gKHN0cmluZykge1xuICAgICAgICByZXR1cm4gc3RyaW5nLnJlcGxhY2UoL1xcZC9nLCBmdW5jdGlvbiAobWF0Y2gpIHtcbiAgICAgICAgICAgIHJldHVybiBzeW1ib2xNYXAkNFttYXRjaF07XG4gICAgICAgIH0pO1xuICAgIH0sXG4gICAgbWVyaWRpZW1QYXJzZTogL+C9mOC9muC9k+C8i+C9mOC9vHzgvZ7gvbzgvYLgvabgvIvgvYDgvaZ84L2J4L2y4L2T4LyL4L2C4L204L2EfOC9keC9guC9vOC9hOC8i+C9keC9gnzgvZjgvZrgvZPgvIvgvZjgvbwvLFxuICAgIG1lcmlkaWVtSG91ciA6IGZ1bmN0aW9uIChob3VyLCBtZXJpZGllbSkge1xuICAgICAgICBpZiAoaG91ciA9PT0gMTIpIHtcbiAgICAgICAgICAgIGhvdXIgPSAwO1xuICAgICAgICB9XG4gICAgICAgIGlmICgobWVyaWRpZW0gPT09ICfgvZjgvZrgvZPgvIvgvZjgvbwnICYmIGhvdXIgPj0gNCkgfHxcbiAgICAgICAgICAgICAgICAobWVyaWRpZW0gPT09ICfgvYngvbLgvZPgvIvgvYLgvbTgvYQnICYmIGhvdXIgPCA1KSB8fFxuICAgICAgICAgICAgICAgIG1lcmlkaWVtID09PSAn4L2R4L2C4L284L2E4LyL4L2R4L2CJykge1xuICAgICAgICAgICAgcmV0dXJuIGhvdXIgKyAxMjtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBob3VyO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBtZXJpZGllbSA6IGZ1bmN0aW9uIChob3VyLCBtaW51dGUsIGlzTG93ZXIpIHtcbiAgICAgICAgaWYgKGhvdXIgPCA0KSB7XG4gICAgICAgICAgICByZXR1cm4gJ+C9mOC9muC9k+C8i+C9mOC9vCc7XG4gICAgICAgIH0gZWxzZSBpZiAoaG91ciA8IDEwKSB7XG4gICAgICAgICAgICByZXR1cm4gJ+C9nuC9vOC9guC9puC8i+C9gOC9pic7XG4gICAgICAgIH0gZWxzZSBpZiAoaG91ciA8IDE3KSB7XG4gICAgICAgICAgICByZXR1cm4gJ+C9ieC9suC9k+C8i+C9guC9tOC9hCc7XG4gICAgICAgIH0gZWxzZSBpZiAoaG91ciA8IDIwKSB7XG4gICAgICAgICAgICByZXR1cm4gJ+C9keC9guC9vOC9hOC8i+C9keC9gic7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gJ+C9mOC9muC9k+C8i+C9mOC9vCc7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIHdlZWsgOiB7XG4gICAgICAgIGRvdyA6IDAsIC8vIFN1bmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICBkb3kgOiA2ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiAxc3QgaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgfVxufSk7XG5cbi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBCcmV0b24gW2JyXVxuLy8hIGF1dGhvciA6IEplYW4tQmFwdGlzdGUgTGUgRHVpZ291IDogaHR0cHM6Ly9naXRodWIuY29tL2pibGVkdWlnb3VcblxuZnVuY3Rpb24gcmVsYXRpdmVUaW1lV2l0aE11dGF0aW9uKG51bWJlciwgd2l0aG91dFN1ZmZpeCwga2V5KSB7XG4gICAgdmFyIGZvcm1hdCA9IHtcbiAgICAgICAgJ21tJzogJ211bnV0ZW5uJyxcbiAgICAgICAgJ01NJzogJ21peicsXG4gICAgICAgICdkZCc6ICdkZXZlemgnXG4gICAgfTtcbiAgICByZXR1cm4gbnVtYmVyICsgJyAnICsgbXV0YXRpb24oZm9ybWF0W2tleV0sIG51bWJlcik7XG59XG5mdW5jdGlvbiBzcGVjaWFsTXV0YXRpb25Gb3JZZWFycyhudW1iZXIpIHtcbiAgICBzd2l0Y2ggKGxhc3ROdW1iZXIobnVtYmVyKSkge1xuICAgICAgICBjYXNlIDE6XG4gICAgICAgIGNhc2UgMzpcbiAgICAgICAgY2FzZSA0OlxuICAgICAgICBjYXNlIDU6XG4gICAgICAgIGNhc2UgOTpcbiAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAnIGJsb2F6JztcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAnIHZsb2F6JztcbiAgICB9XG59XG5mdW5jdGlvbiBsYXN0TnVtYmVyKG51bWJlcikge1xuICAgIGlmIChudW1iZXIgPiA5KSB7XG4gICAgICAgIHJldHVybiBsYXN0TnVtYmVyKG51bWJlciAlIDEwKTtcbiAgICB9XG4gICAgcmV0dXJuIG51bWJlcjtcbn1cbmZ1bmN0aW9uIG11dGF0aW9uKHRleHQsIG51bWJlcikge1xuICAgIGlmIChudW1iZXIgPT09IDIpIHtcbiAgICAgICAgcmV0dXJuIHNvZnRNdXRhdGlvbih0ZXh0KTtcbiAgICB9XG4gICAgcmV0dXJuIHRleHQ7XG59XG5mdW5jdGlvbiBzb2Z0TXV0YXRpb24odGV4dCkge1xuICAgIHZhciBtdXRhdGlvblRhYmxlID0ge1xuICAgICAgICAnbSc6ICd2JyxcbiAgICAgICAgJ2InOiAndicsXG4gICAgICAgICdkJzogJ3onXG4gICAgfTtcbiAgICBpZiAobXV0YXRpb25UYWJsZVt0ZXh0LmNoYXJBdCgwKV0gPT09IHVuZGVmaW5lZCkge1xuICAgICAgICByZXR1cm4gdGV4dDtcbiAgICB9XG4gICAgcmV0dXJuIG11dGF0aW9uVGFibGVbdGV4dC5jaGFyQXQoMCldICsgdGV4dC5zdWJzdHJpbmcoMSk7XG59XG5cbmhvb2tzLmRlZmluZUxvY2FsZSgnYnInLCB7XG4gICAgbW9udGhzIDogJ0dlbnZlcl9DXFwnaHdldnJlcl9NZXVyemhfRWJyZWxfTWFlX01lemhldmVuX0dvdWVyZV9Fb3N0X0d3ZW5nb2xvX0hlcmVfRHVfS2VyenUnLnNwbGl0KCdfJyksXG4gICAgbW9udGhzU2hvcnQgOiAnR2VuX0NcXCdod2VfTWV1X0Vicl9NYWVfRXZlX0dvdV9Fb3NfR3dlX0hlcl9EdV9LZXInLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXMgOiAnU3VsX0x1bl9NZXVyemhfTWVyY1xcJ2hlcl9ZYW91X0d3ZW5lcl9TYWRvcm4nLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydCA6ICdTdWxfTHVuX01ldV9NZXJfWWFvX0d3ZV9TYWQnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW4gOiAnU3VfTHVfTWVfTWVyX1lhX0d3X1NhJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzUGFyc2VFeGFjdCA6IHRydWUsXG4gICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgIExUIDogJ2hbZV1tbSBBJyxcbiAgICAgICAgTFRTIDogJ2hbZV1tbTpzcyBBJyxcbiAgICAgICAgTCA6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgTEwgOiAnRCBbYSB2aXpdIE1NTU0gWVlZWScsXG4gICAgICAgIExMTCA6ICdEIFthIHZpel0gTU1NTSBZWVlZIGhbZV1tbSBBJyxcbiAgICAgICAgTExMTCA6ICdkZGRkLCBEIFthIHZpel0gTU1NTSBZWVlZIGhbZV1tbSBBJ1xuICAgIH0sXG4gICAgY2FsZW5kYXIgOiB7XG4gICAgICAgIHNhbWVEYXkgOiAnW0hpeml2IGRhXSBMVCcsXG4gICAgICAgIG5leHREYXkgOiAnW1dhcmNcXCdob2F6aCBkYV0gTFQnLFxuICAgICAgICBuZXh0V2VlayA6ICdkZGRkIFtkYV0gTFQnLFxuICAgICAgICBsYXN0RGF5IDogJ1tEZWNcXCdoIGRhXSBMVCcsXG4gICAgICAgIGxhc3RXZWVrIDogJ2RkZGQgW3Bhc2V0IGRhXSBMVCcsXG4gICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6ICdhLWJlbm4gJXMnLFxuICAgICAgICBwYXN0IDogJyVzIFxcJ3pvJyxcbiAgICAgICAgcyA6ICd1biBuZWJldWQgc2Vnb25kZW5ub8O5JyxcbiAgICAgICAgc3MgOiAnJWQgZWlsZW5uJyxcbiAgICAgICAgbSA6ICd1ciB2dW51dGVubicsXG4gICAgICAgIG1tIDogcmVsYXRpdmVUaW1lV2l0aE11dGF0aW9uLFxuICAgICAgICBoIDogJ3VuIGV1cicsXG4gICAgICAgIGhoIDogJyVkIGV1cicsXG4gICAgICAgIGQgOiAndW4gZGV2ZXpoJyxcbiAgICAgICAgZGQgOiByZWxhdGl2ZVRpbWVXaXRoTXV0YXRpb24sXG4gICAgICAgIE0gOiAndXIgbWl6JyxcbiAgICAgICAgTU0gOiByZWxhdGl2ZVRpbWVXaXRoTXV0YXRpb24sXG4gICAgICAgIHkgOiAndXIgYmxvYXonLFxuICAgICAgICB5eSA6IHNwZWNpYWxNdXRhdGlvbkZvclllYXJzXG4gICAgfSxcbiAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn0oYcOxfHZldCkvLFxuICAgIG9yZGluYWwgOiBmdW5jdGlvbiAobnVtYmVyKSB7XG4gICAgICAgIHZhciBvdXRwdXQgPSAobnVtYmVyID09PSAxKSA/ICdhw7EnIDogJ3ZldCc7XG4gICAgICAgIHJldHVybiBudW1iZXIgKyBvdXRwdXQ7XG4gICAgfSxcbiAgICB3ZWVrIDoge1xuICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogNCAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH1cbn0pO1xuXG4vLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogQm9zbmlhbiBbYnNdXG4vLyEgYXV0aG9yIDogTmVkaW0gQ2hvbGljaCA6IGh0dHBzOi8vZ2l0aHViLmNvbS9mcm9udHlhcmRcbi8vISBiYXNlZCBvbiAoaHIpIHRyYW5zbGF0aW9uIGJ5IEJvamFuIE1hcmtvdmnEh1xuXG5mdW5jdGlvbiB0cmFuc2xhdGUobnVtYmVyLCB3aXRob3V0U3VmZml4LCBrZXkpIHtcbiAgICB2YXIgcmVzdWx0ID0gbnVtYmVyICsgJyAnO1xuICAgIHN3aXRjaCAoa2V5KSB7XG4gICAgICAgIGNhc2UgJ3NzJzpcbiAgICAgICAgICAgIGlmIChudW1iZXIgPT09IDEpIHtcbiAgICAgICAgICAgICAgICByZXN1bHQgKz0gJ3Nla3VuZGEnO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChudW1iZXIgPT09IDIgfHwgbnVtYmVyID09PSAzIHx8IG51bWJlciA9PT0gNCkge1xuICAgICAgICAgICAgICAgIHJlc3VsdCArPSAnc2VrdW5kZSc7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlc3VsdCArPSAnc2VrdW5kaSc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICBjYXNlICdtJzpcbiAgICAgICAgICAgIHJldHVybiB3aXRob3V0U3VmZml4ID8gJ2plZG5hIG1pbnV0YScgOiAnamVkbmUgbWludXRlJztcbiAgICAgICAgY2FzZSAnbW0nOlxuICAgICAgICAgICAgaWYgKG51bWJlciA9PT0gMSkge1xuICAgICAgICAgICAgICAgIHJlc3VsdCArPSAnbWludXRhJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAobnVtYmVyID09PSAyIHx8IG51bWJlciA9PT0gMyB8fCBudW1iZXIgPT09IDQpIHtcbiAgICAgICAgICAgICAgICByZXN1bHQgKz0gJ21pbnV0ZSc7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlc3VsdCArPSAnbWludXRhJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIGNhc2UgJ2gnOlxuICAgICAgICAgICAgcmV0dXJuIHdpdGhvdXRTdWZmaXggPyAnamVkYW4gc2F0JyA6ICdqZWRub2cgc2F0YSc7XG4gICAgICAgIGNhc2UgJ2hoJzpcbiAgICAgICAgICAgIGlmIChudW1iZXIgPT09IDEpIHtcbiAgICAgICAgICAgICAgICByZXN1bHQgKz0gJ3NhdCc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKG51bWJlciA9PT0gMiB8fCBudW1iZXIgPT09IDMgfHwgbnVtYmVyID09PSA0KSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ICs9ICdzYXRhJztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ICs9ICdzYXRpJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIGNhc2UgJ2RkJzpcbiAgICAgICAgICAgIGlmIChudW1iZXIgPT09IDEpIHtcbiAgICAgICAgICAgICAgICByZXN1bHQgKz0gJ2Rhbic7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlc3VsdCArPSAnZGFuYSc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICBjYXNlICdNTSc6XG4gICAgICAgICAgICBpZiAobnVtYmVyID09PSAxKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ICs9ICdtamVzZWMnO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChudW1iZXIgPT09IDIgfHwgbnVtYmVyID09PSAzIHx8IG51bWJlciA9PT0gNCkge1xuICAgICAgICAgICAgICAgIHJlc3VsdCArPSAnbWplc2VjYSc7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlc3VsdCArPSAnbWplc2VjaSc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICBjYXNlICd5eSc6XG4gICAgICAgICAgICBpZiAobnVtYmVyID09PSAxKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ICs9ICdnb2RpbmEnO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChudW1iZXIgPT09IDIgfHwgbnVtYmVyID09PSAzIHx8IG51bWJlciA9PT0gNCkge1xuICAgICAgICAgICAgICAgIHJlc3VsdCArPSAnZ29kaW5lJztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ICs9ICdnb2RpbmEnO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG59XG5cbmhvb2tzLmRlZmluZUxvY2FsZSgnYnMnLCB7XG4gICAgbW9udGhzIDogJ2phbnVhcl9mZWJydWFyX21hcnRfYXByaWxfbWFqX2p1bmlfanVsaV9hdWd1c3Rfc2VwdGVtYmFyX29rdG9iYXJfbm92ZW1iYXJfZGVjZW1iYXInLnNwbGl0KCdfJyksXG4gICAgbW9udGhzU2hvcnQgOiAnamFuLl9mZWIuX21hci5fYXByLl9tYWouX2p1bi5fanVsLl9hdWcuX3NlcC5fb2t0Ll9ub3YuX2RlYy4nLnNwbGl0KCdfJyksXG4gICAgbW9udGhzUGFyc2VFeGFjdDogdHJ1ZSxcbiAgICB3ZWVrZGF5cyA6ICduZWRqZWxqYV9wb25lZGplbGpha191dG9yYWtfc3JpamVkYV/EjWV0dnJ0YWtfcGV0YWtfc3Vib3RhJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzU2hvcnQgOiAnbmVkLl9wb24uX3V0by5fc3JpLl/EjWV0Ll9wZXQuX3N1Yi4nLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW4gOiAnbmVfcG9fdXRfc3JfxI1lX3BlX3N1Jy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzUGFyc2VFeGFjdCA6IHRydWUsXG4gICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgIExUIDogJ0g6bW0nLFxuICAgICAgICBMVFMgOiAnSDptbTpzcycsXG4gICAgICAgIEwgOiAnREQuTU0uWVlZWScsXG4gICAgICAgIExMIDogJ0QuIE1NTU0gWVlZWScsXG4gICAgICAgIExMTCA6ICdELiBNTU1NIFlZWVkgSDptbScsXG4gICAgICAgIExMTEwgOiAnZGRkZCwgRC4gTU1NTSBZWVlZIEg6bW0nXG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheSAgOiAnW2RhbmFzIHVdIExUJyxcbiAgICAgICAgbmV4dERheSAgOiAnW3N1dHJhIHVdIExUJyxcbiAgICAgICAgbmV4dFdlZWsgOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBzd2l0Y2ggKHRoaXMuZGF5KCkpIHtcbiAgICAgICAgICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnW3VdIFtuZWRqZWxqdV0gW3VdIExUJztcbiAgICAgICAgICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnW3VdIFtzcmlqZWR1XSBbdV0gTFQnO1xuICAgICAgICAgICAgICAgIGNhc2UgNjpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbdV0gW3N1Ym90dV0gW3VdIExUJztcbiAgICAgICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgICAgIGNhc2UgNDpcbiAgICAgICAgICAgICAgICBjYXNlIDU6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnW3VdIGRkZGQgW3VdIExUJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgbGFzdERheSAgOiAnW2p1xI1lciB1XSBMVCcsXG4gICAgICAgIGxhc3RXZWVrIDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgc3dpdGNoICh0aGlzLmRheSgpKSB7XG4gICAgICAgICAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgICAgIGNhc2UgMzpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbcHJvxaFsdV0gZGRkZCBbdV0gTFQnO1xuICAgICAgICAgICAgICAgIGNhc2UgNjpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbcHJvxaFsZV0gW3N1Ym90ZV0gW3VdIExUJztcbiAgICAgICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgICAgIGNhc2UgNDpcbiAgICAgICAgICAgICAgICBjYXNlIDU6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnW3Byb8WhbGldIGRkZGQgW3VdIExUJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJ3phICVzJyxcbiAgICAgICAgcGFzdCAgIDogJ3ByaWplICVzJyxcbiAgICAgICAgcyAgICAgIDogJ3BhciBzZWt1bmRpJyxcbiAgICAgICAgc3MgICAgIDogdHJhbnNsYXRlLFxuICAgICAgICBtICAgICAgOiB0cmFuc2xhdGUsXG4gICAgICAgIG1tICAgICA6IHRyYW5zbGF0ZSxcbiAgICAgICAgaCAgICAgIDogdHJhbnNsYXRlLFxuICAgICAgICBoaCAgICAgOiB0cmFuc2xhdGUsXG4gICAgICAgIGQgICAgICA6ICdkYW4nLFxuICAgICAgICBkZCAgICAgOiB0cmFuc2xhdGUsXG4gICAgICAgIE0gICAgICA6ICdtamVzZWMnLFxuICAgICAgICBNTSAgICAgOiB0cmFuc2xhdGUsXG4gICAgICAgIHkgICAgICA6ICdnb2RpbnUnLFxuICAgICAgICB5eSAgICAgOiB0cmFuc2xhdGVcbiAgICB9LFxuICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfVxcLi8sXG4gICAgb3JkaW5hbCA6ICclZC4nLFxuICAgIHdlZWsgOiB7XG4gICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICBkb3kgOiA3ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiAxc3QgaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgfVxufSk7XG5cbi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBDYXRhbGFuIFtjYV1cbi8vISBhdXRob3IgOiBKdWFuIEcuIEh1cnRhZG8gOiBodHRwczovL2dpdGh1Yi5jb20vanVhbmdodXJ0YWRvXG5cbmhvb2tzLmRlZmluZUxvY2FsZSgnY2EnLCB7XG4gICAgbW9udGhzIDoge1xuICAgICAgICBzdGFuZGFsb25lOiAnZ2VuZXJfZmVicmVyX21hcsOnX2FicmlsX21haWdfanVueV9qdWxpb2xfYWdvc3Rfc2V0ZW1icmVfb2N0dWJyZV9ub3ZlbWJyZV9kZXNlbWJyZScuc3BsaXQoJ18nKSxcbiAgICAgICAgZm9ybWF0OiAnZGUgZ2VuZXJfZGUgZmVicmVyX2RlIG1hcsOnX2RcXCdhYnJpbF9kZSBtYWlnX2RlIGp1bnlfZGUganVsaW9sX2RcXCdhZ29zdF9kZSBzZXRlbWJyZV9kXFwnb2N0dWJyZV9kZSBub3ZlbWJyZV9kZSBkZXNlbWJyZScuc3BsaXQoJ18nKSxcbiAgICAgICAgaXNGb3JtYXQ6IC9EW29EXT8oXFxzKStNTU1NL1xuICAgIH0sXG4gICAgbW9udGhzU2hvcnQgOiAnZ2VuLl9mZWJyLl9tYXLDp19hYnIuX21haWdfanVueV9qdWwuX2FnLl9zZXQuX29jdC5fbm92Ll9kZXMuJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgIHdlZWtkYXlzIDogJ2RpdW1lbmdlX2RpbGx1bnNfZGltYXJ0c19kaW1lY3Jlc19kaWpvdXNfZGl2ZW5kcmVzX2Rpc3NhYnRlJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzU2hvcnQgOiAnZGcuX2RsLl9kdC5fZGMuX2RqLl9kdi5fZHMuJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzTWluIDogJ2RnX2RsX2R0X2RjX2RqX2R2X2RzJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzUGFyc2VFeGFjdCA6IHRydWUsXG4gICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgIExUIDogJ0g6bW0nLFxuICAgICAgICBMVFMgOiAnSDptbTpzcycsXG4gICAgICAgIEwgOiAnREQvTU0vWVlZWScsXG4gICAgICAgIExMIDogJ0QgTU1NTSBbZGVdIFlZWVknLFxuICAgICAgICBsbCA6ICdEIE1NTSBZWVlZJyxcbiAgICAgICAgTExMIDogJ0QgTU1NTSBbZGVdIFlZWVkgW2EgbGVzXSBIOm1tJyxcbiAgICAgICAgbGxsIDogJ0QgTU1NIFlZWVksIEg6bW0nLFxuICAgICAgICBMTExMIDogJ2RkZGQgRCBNTU1NIFtkZV0gWVlZWSBbYSBsZXNdIEg6bW0nLFxuICAgICAgICBsbGxsIDogJ2RkZCBEIE1NTSBZWVlZLCBIOm1tJ1xuICAgIH0sXG4gICAgY2FsZW5kYXIgOiB7XG4gICAgICAgIHNhbWVEYXkgOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gJ1thdnVpIGEgJyArICgodGhpcy5ob3VycygpICE9PSAxKSA/ICdsZXMnIDogJ2xhJykgKyAnXSBMVCc7XG4gICAgICAgIH0sXG4gICAgICAgIG5leHREYXkgOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gJ1tkZW3DoCBhICcgKyAoKHRoaXMuaG91cnMoKSAhPT0gMSkgPyAnbGVzJyA6ICdsYScpICsgJ10gTFQnO1xuICAgICAgICB9LFxuICAgICAgICBuZXh0V2VlayA6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiAnZGRkZCBbYSAnICsgKCh0aGlzLmhvdXJzKCkgIT09IDEpID8gJ2xlcycgOiAnbGEnKSArICddIExUJztcbiAgICAgICAgfSxcbiAgICAgICAgbGFzdERheSA6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiAnW2FoaXIgYSAnICsgKCh0aGlzLmhvdXJzKCkgIT09IDEpID8gJ2xlcycgOiAnbGEnKSArICddIExUJztcbiAgICAgICAgfSxcbiAgICAgICAgbGFzdFdlZWsgOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gJ1tlbF0gZGRkZCBbcGFzc2F0IGEgJyArICgodGhpcy5ob3VycygpICE9PSAxKSA/ICdsZXMnIDogJ2xhJykgKyAnXSBMVCc7XG4gICAgICAgIH0sXG4gICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6ICdkXFwnYXF1w60gJXMnLFxuICAgICAgICBwYXN0IDogJ2ZhICVzJyxcbiAgICAgICAgcyA6ICd1bnMgc2Vnb25zJyxcbiAgICAgICAgc3MgOiAnJWQgc2Vnb25zJyxcbiAgICAgICAgbSA6ICd1biBtaW51dCcsXG4gICAgICAgIG1tIDogJyVkIG1pbnV0cycsXG4gICAgICAgIGggOiAndW5hIGhvcmEnLFxuICAgICAgICBoaCA6ICclZCBob3JlcycsXG4gICAgICAgIGQgOiAndW4gZGlhJyxcbiAgICAgICAgZGQgOiAnJWQgZGllcycsXG4gICAgICAgIE0gOiAndW4gbWVzJyxcbiAgICAgICAgTU0gOiAnJWQgbWVzb3MnLFxuICAgICAgICB5IDogJ3VuIGFueScsXG4gICAgICAgIHl5IDogJyVkIGFueXMnXG4gICAgfSxcbiAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn0ocnxufHR8w6h8YSkvLFxuICAgIG9yZGluYWwgOiBmdW5jdGlvbiAobnVtYmVyLCBwZXJpb2QpIHtcbiAgICAgICAgdmFyIG91dHB1dCA9IChudW1iZXIgPT09IDEpID8gJ3InIDpcbiAgICAgICAgICAgIChudW1iZXIgPT09IDIpID8gJ24nIDpcbiAgICAgICAgICAgIChudW1iZXIgPT09IDMpID8gJ3InIDpcbiAgICAgICAgICAgIChudW1iZXIgPT09IDQpID8gJ3QnIDogJ8OoJztcbiAgICAgICAgaWYgKHBlcmlvZCA9PT0gJ3cnIHx8IHBlcmlvZCA9PT0gJ1cnKSB7XG4gICAgICAgICAgICBvdXRwdXQgPSAnYSc7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG51bWJlciArIG91dHB1dDtcbiAgICB9LFxuICAgIHdlZWsgOiB7XG4gICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICBkb3kgOiA0ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgfVxufSk7XG5cbi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBDemVjaCBbY3NdXG4vLyEgYXV0aG9yIDogcGV0cmJlbGEgOiBodHRwczovL2dpdGh1Yi5jb20vcGV0cmJlbGFcblxudmFyIG1vbnRocyQzID0gJ2xlZGVuX8O6bm9yX2LFmWV6ZW5fZHViZW5fa3bEm3Rlbl/EjWVydmVuX8SNZXJ2ZW5lY19zcnBlbl96w6HFmcOtX8WZw61qZW5fbGlzdG9wYWRfcHJvc2luZWMnLnNwbGl0KCdfJyk7XG52YXIgbW9udGhzU2hvcnQgPSAnbGVkX8O6bm9fYsWZZV9kdWJfa3bEm1/EjXZuX8SNdmNfc3JwX3rDocWZX8WZw61qX2xpc19wcm8nLnNwbGl0KCdfJyk7XG5mdW5jdGlvbiBwbHVyYWwkMShuKSB7XG4gICAgcmV0dXJuIChuID4gMSkgJiYgKG4gPCA1KSAmJiAofn4obiAvIDEwKSAhPT0gMSk7XG59XG5mdW5jdGlvbiB0cmFuc2xhdGUkMShudW1iZXIsIHdpdGhvdXRTdWZmaXgsIGtleSwgaXNGdXR1cmUpIHtcbiAgICB2YXIgcmVzdWx0ID0gbnVtYmVyICsgJyAnO1xuICAgIHN3aXRjaCAoa2V5KSB7XG4gICAgICAgIGNhc2UgJ3MnOiAgLy8gYSBmZXcgc2Vjb25kcyAvIGluIGEgZmV3IHNlY29uZHMgLyBhIGZldyBzZWNvbmRzIGFnb1xuICAgICAgICAgICAgcmV0dXJuICh3aXRob3V0U3VmZml4IHx8IGlzRnV0dXJlKSA/ICdww6FyIHNla3VuZCcgOiAncMOhciBzZWt1bmRhbWknO1xuICAgICAgICBjYXNlICdzcyc6IC8vIDkgc2Vjb25kcyAvIGluIDkgc2Vjb25kcyAvIDkgc2Vjb25kcyBhZ29cbiAgICAgICAgICAgIGlmICh3aXRob3V0U3VmZml4IHx8IGlzRnV0dXJlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCArIChwbHVyYWwkMShudW1iZXIpID8gJ3Nla3VuZHknIDogJ3Nla3VuZCcpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0ICsgJ3Nla3VuZGFtaSc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnbSc6ICAvLyBhIG1pbnV0ZSAvIGluIGEgbWludXRlIC8gYSBtaW51dGUgYWdvXG4gICAgICAgICAgICByZXR1cm4gd2l0aG91dFN1ZmZpeCA/ICdtaW51dGEnIDogKGlzRnV0dXJlID8gJ21pbnV0dScgOiAnbWludXRvdScpO1xuICAgICAgICBjYXNlICdtbSc6IC8vIDkgbWludXRlcyAvIGluIDkgbWludXRlcyAvIDkgbWludXRlcyBhZ29cbiAgICAgICAgICAgIGlmICh3aXRob3V0U3VmZml4IHx8IGlzRnV0dXJlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCArIChwbHVyYWwkMShudW1iZXIpID8gJ21pbnV0eScgOiAnbWludXQnKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCArICdtaW51dGFtaSc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnaCc6ICAvLyBhbiBob3VyIC8gaW4gYW4gaG91ciAvIGFuIGhvdXIgYWdvXG4gICAgICAgICAgICByZXR1cm4gd2l0aG91dFN1ZmZpeCA/ICdob2RpbmEnIDogKGlzRnV0dXJlID8gJ2hvZGludScgOiAnaG9kaW5vdScpO1xuICAgICAgICBjYXNlICdoaCc6IC8vIDkgaG91cnMgLyBpbiA5IGhvdXJzIC8gOSBob3VycyBhZ29cbiAgICAgICAgICAgIGlmICh3aXRob3V0U3VmZml4IHx8IGlzRnV0dXJlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCArIChwbHVyYWwkMShudW1iZXIpID8gJ2hvZGlueScgOiAnaG9kaW4nKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCArICdob2RpbmFtaSc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnZCc6ICAvLyBhIGRheSAvIGluIGEgZGF5IC8gYSBkYXkgYWdvXG4gICAgICAgICAgICByZXR1cm4gKHdpdGhvdXRTdWZmaXggfHwgaXNGdXR1cmUpID8gJ2RlbicgOiAnZG5lbSc7XG4gICAgICAgIGNhc2UgJ2RkJzogLy8gOSBkYXlzIC8gaW4gOSBkYXlzIC8gOSBkYXlzIGFnb1xuICAgICAgICAgICAgaWYgKHdpdGhvdXRTdWZmaXggfHwgaXNGdXR1cmUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0ICsgKHBsdXJhbCQxKG51bWJlcikgPyAnZG55JyA6ICdkbsOtJyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQgKyAnZG55JztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICdNJzogIC8vIGEgbW9udGggLyBpbiBhIG1vbnRoIC8gYSBtb250aCBhZ29cbiAgICAgICAgICAgIHJldHVybiAod2l0aG91dFN1ZmZpeCB8fCBpc0Z1dHVyZSkgPyAnbcSbc8OtYycgOiAnbcSbc8OtY2VtJztcbiAgICAgICAgY2FzZSAnTU0nOiAvLyA5IG1vbnRocyAvIGluIDkgbW9udGhzIC8gOSBtb250aHMgYWdvXG4gICAgICAgICAgICBpZiAod2l0aG91dFN1ZmZpeCB8fCBpc0Z1dHVyZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQgKyAocGx1cmFsJDEobnVtYmVyKSA/ICdtxJtzw61jZScgOiAnbcSbc8OtY8WvJyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQgKyAnbcSbc8OtY2knO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ3knOiAgLy8gYSB5ZWFyIC8gaW4gYSB5ZWFyIC8gYSB5ZWFyIGFnb1xuICAgICAgICAgICAgcmV0dXJuICh3aXRob3V0U3VmZml4IHx8IGlzRnV0dXJlKSA/ICdyb2snIDogJ3Jva2VtJztcbiAgICAgICAgY2FzZSAneXknOiAvLyA5IHllYXJzIC8gaW4gOSB5ZWFycyAvIDkgeWVhcnMgYWdvXG4gICAgICAgICAgICBpZiAod2l0aG91dFN1ZmZpeCB8fCBpc0Z1dHVyZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQgKyAocGx1cmFsJDEobnVtYmVyKSA/ICdyb2t5JyA6ICdsZXQnKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCArICdsZXR5JztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJyZWFrO1xuICAgIH1cbn1cblxuaG9va3MuZGVmaW5lTG9jYWxlKCdjcycsIHtcbiAgICBtb250aHMgOiBtb250aHMkMyxcbiAgICBtb250aHNTaG9ydCA6IG1vbnRoc1Nob3J0LFxuICAgIG1vbnRoc1BhcnNlIDogKGZ1bmN0aW9uIChtb250aHMsIG1vbnRoc1Nob3J0KSB7XG4gICAgICAgIHZhciBpLCBfbW9udGhzUGFyc2UgPSBbXTtcbiAgICAgICAgZm9yIChpID0gMDsgaSA8IDEyOyBpKyspIHtcbiAgICAgICAgICAgIC8vIHVzZSBjdXN0b20gcGFyc2VyIHRvIHNvbHZlIHByb2JsZW0gd2l0aCBKdWx5ICjEjWVydmVuZWMpXG4gICAgICAgICAgICBfbW9udGhzUGFyc2VbaV0gPSBuZXcgUmVnRXhwKCdeJyArIG1vbnRoc1tpXSArICckfF4nICsgbW9udGhzU2hvcnRbaV0gKyAnJCcsICdpJyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIF9tb250aHNQYXJzZTtcbiAgICB9KG1vbnRocyQzLCBtb250aHNTaG9ydCkpLFxuICAgIHNob3J0TW9udGhzUGFyc2UgOiAoZnVuY3Rpb24gKG1vbnRoc1Nob3J0KSB7XG4gICAgICAgIHZhciBpLCBfc2hvcnRNb250aHNQYXJzZSA9IFtdO1xuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgMTI7IGkrKykge1xuICAgICAgICAgICAgX3Nob3J0TW9udGhzUGFyc2VbaV0gPSBuZXcgUmVnRXhwKCdeJyArIG1vbnRoc1Nob3J0W2ldICsgJyQnLCAnaScpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBfc2hvcnRNb250aHNQYXJzZTtcbiAgICB9KG1vbnRoc1Nob3J0KSksXG4gICAgbG9uZ01vbnRoc1BhcnNlIDogKGZ1bmN0aW9uIChtb250aHMpIHtcbiAgICAgICAgdmFyIGksIF9sb25nTW9udGhzUGFyc2UgPSBbXTtcbiAgICAgICAgZm9yIChpID0gMDsgaSA8IDEyOyBpKyspIHtcbiAgICAgICAgICAgIF9sb25nTW9udGhzUGFyc2VbaV0gPSBuZXcgUmVnRXhwKCdeJyArIG1vbnRoc1tpXSArICckJywgJ2knKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gX2xvbmdNb250aHNQYXJzZTtcbiAgICB9KG1vbnRocyQzKSksXG4gICAgd2Vla2RheXMgOiAnbmVkxJtsZV9wb25kxJtsw61fw7p0ZXLDvV9zdMWZZWRhX8SNdHZydGVrX3DDoXRla19zb2JvdGEnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydCA6ICduZV9wb1/DunRfc3RfxI10X3DDoV9zbycuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbiA6ICduZV9wb1/DunRfc3RfxI10X3DDoV9zbycuc3BsaXQoJ18nKSxcbiAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgTFQ6ICdIOm1tJyxcbiAgICAgICAgTFRTIDogJ0g6bW06c3MnLFxuICAgICAgICBMIDogJ0RELk1NLllZWVknLFxuICAgICAgICBMTCA6ICdELiBNTU1NIFlZWVknLFxuICAgICAgICBMTEwgOiAnRC4gTU1NTSBZWVlZIEg6bW0nLFxuICAgICAgICBMTExMIDogJ2RkZGQgRC4gTU1NTSBZWVlZIEg6bW0nLFxuICAgICAgICBsIDogJ0QuIE0uIFlZWVknXG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheTogJ1tkbmVzIHZdIExUJyxcbiAgICAgICAgbmV4dERheTogJ1t6w610cmEgdl0gTFQnLFxuICAgICAgICBuZXh0V2VlazogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgc3dpdGNoICh0aGlzLmRheSgpKSB7XG4gICAgICAgICAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1t2IG5lZMSbbGkgdl0gTFQnO1xuICAgICAgICAgICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnW3ZdIGRkZGQgW3ZdIExUJztcbiAgICAgICAgICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnW3ZlIHN0xZllZHUgdl0gTFQnO1xuICAgICAgICAgICAgICAgIGNhc2UgNDpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbdmUgxI10dnJ0ZWsgdl0gTFQnO1xuICAgICAgICAgICAgICAgIGNhc2UgNTpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbdiBww6F0ZWsgdl0gTFQnO1xuICAgICAgICAgICAgICAgIGNhc2UgNjpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbdiBzb2JvdHUgdl0gTFQnO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBsYXN0RGF5OiAnW3bEjWVyYSB2XSBMVCcsXG4gICAgICAgIGxhc3RXZWVrOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBzd2l0Y2ggKHRoaXMuZGF5KCkpIHtcbiAgICAgICAgICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnW21pbnVsb3UgbmVkxJtsaSB2XSBMVCc7XG4gICAgICAgICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgICAgIGNhc2UgMjpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbbWludWzDqV0gZGRkZCBbdl0gTFQnO1xuICAgICAgICAgICAgICAgIGNhc2UgMzpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbbWludWxvdSBzdMWZZWR1IHZdIExUJztcbiAgICAgICAgICAgICAgICBjYXNlIDQ6XG4gICAgICAgICAgICAgICAgY2FzZSA1OlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1ttaW51bMO9XSBkZGRkIFt2XSBMVCc7XG4gICAgICAgICAgICAgICAgY2FzZSA2OlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1ttaW51bG91IHNvYm90dSB2XSBMVCc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIHNhbWVFbHNlOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJ3phICVzJyxcbiAgICAgICAgcGFzdCA6ICdwxZllZCAlcycsXG4gICAgICAgIHMgOiB0cmFuc2xhdGUkMSxcbiAgICAgICAgc3MgOiB0cmFuc2xhdGUkMSxcbiAgICAgICAgbSA6IHRyYW5zbGF0ZSQxLFxuICAgICAgICBtbSA6IHRyYW5zbGF0ZSQxLFxuICAgICAgICBoIDogdHJhbnNsYXRlJDEsXG4gICAgICAgIGhoIDogdHJhbnNsYXRlJDEsXG4gICAgICAgIGQgOiB0cmFuc2xhdGUkMSxcbiAgICAgICAgZGQgOiB0cmFuc2xhdGUkMSxcbiAgICAgICAgTSA6IHRyYW5zbGF0ZSQxLFxuICAgICAgICBNTSA6IHRyYW5zbGF0ZSQxLFxuICAgICAgICB5IDogdHJhbnNsYXRlJDEsXG4gICAgICAgIHl5IDogdHJhbnNsYXRlJDFcbiAgICB9LFxuICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2UgOiAvXFxkezEsMn1cXC4vLFxuICAgIG9yZGluYWwgOiAnJWQuJyxcbiAgICB3ZWVrIDoge1xuICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogNCAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH1cbn0pO1xuXG4vLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogQ2h1dmFzaCBbY3ZdXG4vLyEgYXV0aG9yIDogQW5hdG9seSBNaXJvbm92IDogaHR0cHM6Ly9naXRodWIuY29tL21pcm9udG9saVxuXG5ob29rcy5kZWZpbmVMb2NhbGUoJ2N2Jywge1xuICAgIG1vbnRocyA6ICfQutOR0YDQu9Cw0Ydf0L3QsNGA05HRgV/Qv9GD0Yhf0LDQutCwX9C80LDQuV/Sq9OX0YDRgtC80LVf0YPRgtORX9Kr0YPRgNC70LBf0LDQstOR0L1f0Y7Qv9CwX9GH07PQul/RgNCw0YjRgtCw0LInLnNwbGl0KCdfJyksXG4gICAgbW9udGhzU2hvcnQgOiAn0LrTkdGAX9C90LDRgF/Qv9GD0Yhf0LDQutCwX9C80LDQuV/Sq9OX0YBf0YPRgtORX9Kr0YPRgF/QsNCy0L1f0Y7Qv9CwX9GH07PQul/RgNCw0YgnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXMgOiAn0LLRi9GA0YHQsNGA0L3QuNC60YPQvV/RgtGD0L3RgtC40LrRg9C9X9GL0YLQu9Cw0YDQuNC60YPQvV/RjtC90LrRg9C9X9C605fSq9C90LXRgNC90LjQutGD0L1f0Y3RgNC90LXQutGD0L1f0YjTkdC80LDRgtC60YPQvScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0IDogJ9Cy0YvRgF/RgtGD0L1f0YvRgtC7X9GO0L1f0LrTl9KrX9GN0YDQvV/RiNOR0LwnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW4gOiAn0LLRgF/RgtC9X9GL0YJf0Y7QvV/QutKrX9GN0YBf0YjQvCcuc3BsaXQoJ18nKSxcbiAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgTFQgOiAnSEg6bW0nLFxuICAgICAgICBMVFMgOiAnSEg6bW06c3MnLFxuICAgICAgICBMIDogJ0RELU1NLVlZWVknLFxuICAgICAgICBMTCA6ICdZWVlZIFvSq9GD0LvRhdC4XSBNTU1NIFvRg9C505HRhdOX0L1dIERbLdC805fRiNOXXScsXG4gICAgICAgIExMTCA6ICdZWVlZIFvSq9GD0LvRhdC4XSBNTU1NIFvRg9C505HRhdOX0L1dIERbLdC805fRiNOXXSwgSEg6bW0nLFxuICAgICAgICBMTExMIDogJ2RkZGQsIFlZWVkgW9Kr0YPQu9GF0LhdIE1NTU0gW9GD0LnTkdGF05fQvV0gRFst0LzTl9GI05ddLCBISDptbSdcbiAgICB9LFxuICAgIGNhbGVuZGFyIDoge1xuICAgICAgICBzYW1lRGF5OiAnW9Cf0LDRj9C9XSBMVCBb0YHQtdGF0LXRgtGA0LVdJyxcbiAgICAgICAgbmV4dERheTogJ1vQq9GA0LDQvV0gTFQgW9GB0LXRhdC10YLRgNC1XScsXG4gICAgICAgIGxhc3REYXk6ICdb05bQvdC10YBdIExUIFvRgdC10YXQtdGC0YDQtV0nLFxuICAgICAgICBuZXh0V2VlazogJ1vSqtC40YLQtdGBXSBkZGRkIExUIFvRgdC10YXQtdGC0YDQtV0nLFxuICAgICAgICBsYXN0V2VlazogJ1vQmNGA0YLQvdOXXSBkZGRkIExUIFvRgdC10YXQtdGC0YDQtV0nLFxuICAgICAgICBzYW1lRWxzZTogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6IGZ1bmN0aW9uIChvdXRwdXQpIHtcbiAgICAgICAgICAgIHZhciBhZmZpeCA9IC/RgdC10YXQtdGCJC9pLmV4ZWMob3V0cHV0KSA/ICfRgNC10L0nIDogL9Kr0YPQuyQvaS5leGVjKG91dHB1dCkgPyAn0YLQsNC9JyA6ICfRgNCw0L0nO1xuICAgICAgICAgICAgcmV0dXJuIG91dHB1dCArIGFmZml4O1xuICAgICAgICB9LFxuICAgICAgICBwYXN0IDogJyVzINC60LDRj9C70LvQsCcsXG4gICAgICAgIHMgOiAn0L/Tl9GALdC40Log0qvQtdC60LrRg9C90YInLFxuICAgICAgICBzcyA6ICclZCDSq9C10LrQutGD0L3RgicsXG4gICAgICAgIG0gOiAn0L/Tl9GAINC80LjQvdGD0YInLFxuICAgICAgICBtbSA6ICclZCDQvNC40L3Rg9GCJyxcbiAgICAgICAgaCA6ICfQv9OX0YAg0YHQtdGF0LXRgicsXG4gICAgICAgIGhoIDogJyVkINGB0LXRhdC10YInLFxuICAgICAgICBkIDogJ9C/05fRgCDQutGD0L0nLFxuICAgICAgICBkZCA6ICclZCDQutGD0L0nLFxuICAgICAgICBNIDogJ9C/05fRgCDRg9C505HRhScsXG4gICAgICAgIE1NIDogJyVkINGD0LnTkdGFJyxcbiAgICAgICAgeSA6ICfQv9OX0YAg0qvRg9C7JyxcbiAgICAgICAgeXkgOiAnJWQg0qvRg9C7J1xuICAgIH0sXG4gICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9LdC805fRiC8sXG4gICAgb3JkaW5hbCA6ICclZC3QvNOX0YgnLFxuICAgIHdlZWsgOiB7XG4gICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICBkb3kgOiA3ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiAxc3QgaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgfVxufSk7XG5cbi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBXZWxzaCBbY3ldXG4vLyEgYXV0aG9yIDogUm9iZXJ0IEFsbGVuIDogaHR0cHM6Ly9naXRodWIuY29tL3JvYmdhbGxlblxuLy8hIGF1dGhvciA6IGh0dHBzOi8vZ2l0aHViLmNvbS9yeWFuZ3JlYXZlc1xuXG5ob29rcy5kZWZpbmVMb2NhbGUoJ2N5Jywge1xuICAgIG1vbnRoczogJ0lvbmF3cl9DaHdlZnJvcl9NYXdydGhfRWJyaWxsX01haV9NZWhlZmluX0dvcmZmZW5uYWZfQXdzdF9NZWRpX0h5ZHJlZl9UYWNod2VkZF9SaGFnZnlyJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0OiAnSW9uX0Nod2VfTWF3X0Vicl9NYWlfTWVoX0dvcl9Bd3NfTWVkX0h5ZF9UYWNoX1JoYWcnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXM6ICdEeWRkIFN1bF9EeWRkIExsdW5fRHlkZCBNYXdydGhfRHlkZCBNZXJjaGVyX0R5ZGQgSWF1X0R5ZGQgR3dlbmVyX0R5ZGQgU2Fkd3JuJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzU2hvcnQ6ICdTdWxfTGx1bl9NYXdfTWVyX0lhdV9Hd2VfU2FkJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzTWluOiAnU3VfTGxfTWFfTWVfSWFfR3dfU2EnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNQYXJzZUV4YWN0IDogdHJ1ZSxcbiAgICAvLyB0aW1lIGZvcm1hdHMgYXJlIHRoZSBzYW1lIGFzIGVuLWdiXG4gICAgbG9uZ0RhdGVGb3JtYXQ6IHtcbiAgICAgICAgTFQ6ICdISDptbScsXG4gICAgICAgIExUUyA6ICdISDptbTpzcycsXG4gICAgICAgIEw6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgTEw6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgIExMTDogJ0QgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgTExMTDogJ2RkZGQsIEQgTU1NTSBZWVlZIEhIOm1tJ1xuICAgIH0sXG4gICAgY2FsZW5kYXI6IHtcbiAgICAgICAgc2FtZURheTogJ1tIZWRkaXcgYW1dIExUJyxcbiAgICAgICAgbmV4dERheTogJ1tZZm9yeSBhbV0gTFQnLFxuICAgICAgICBuZXh0V2VlazogJ2RkZGQgW2FtXSBMVCcsXG4gICAgICAgIGxhc3REYXk6ICdbRGRvZSBhbV0gTFQnLFxuICAgICAgICBsYXN0V2VlazogJ2RkZGQgW2Rpd2V0aGFmIGFtXSBMVCcsXG4gICAgICAgIHNhbWVFbHNlOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZToge1xuICAgICAgICBmdXR1cmU6ICdtZXduICVzJyxcbiAgICAgICAgcGFzdDogJyVzIHluIMO0bCcsXG4gICAgICAgIHM6ICd5Y2h5ZGlnIGVpbGlhZGF1JyxcbiAgICAgICAgc3M6ICclZCBlaWxpYWQnLFxuICAgICAgICBtOiAnbXVudWQnLFxuICAgICAgICBtbTogJyVkIG11bnVkJyxcbiAgICAgICAgaDogJ2F3cicsXG4gICAgICAgIGhoOiAnJWQgYXdyJyxcbiAgICAgICAgZDogJ2Rpd3Jub2QnLFxuICAgICAgICBkZDogJyVkIGRpd3Jub2QnLFxuICAgICAgICBNOiAnbWlzJyxcbiAgICAgICAgTU06ICclZCBtaXMnLFxuICAgICAgICB5OiAnYmx3eWRkeW4nLFxuICAgICAgICB5eTogJyVkIGZseW5lZGQnXG4gICAgfSxcbiAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn0oZmVkfGFpbnxhZnxpbHx5ZGR8ZWR8ZWcpLyxcbiAgICAvLyB0cmFkaXRpb25hbCBvcmRpbmFsIG51bWJlcnMgYWJvdmUgMzEgYXJlIG5vdCBjb21tb25seSB1c2VkIGluIGNvbGxvcXVpYWwgV2Vsc2hcbiAgICBvcmRpbmFsOiBmdW5jdGlvbiAobnVtYmVyKSB7XG4gICAgICAgIHZhciBiID0gbnVtYmVyLFxuICAgICAgICAgICAgb3V0cHV0ID0gJycsXG4gICAgICAgICAgICBsb29rdXAgPSBbXG4gICAgICAgICAgICAgICAgJycsICdhZicsICdpbCcsICd5ZGQnLCAneWRkJywgJ2VkJywgJ2VkJywgJ2VkJywgJ2ZlZCcsICdmZWQnLCAnZmVkJywgLy8gMWFmIHRvIDEwZmVkXG4gICAgICAgICAgICAgICAgJ2VnJywgJ2ZlZCcsICdlZycsICdlZycsICdmZWQnLCAnZWcnLCAnZWcnLCAnZmVkJywgJ2VnJywgJ2ZlZCcgLy8gMTFlZyB0byAyMGZlZFxuICAgICAgICAgICAgXTtcbiAgICAgICAgaWYgKGIgPiAyMCkge1xuICAgICAgICAgICAgaWYgKGIgPT09IDQwIHx8IGIgPT09IDUwIHx8IGIgPT09IDYwIHx8IGIgPT09IDgwIHx8IGIgPT09IDEwMCkge1xuICAgICAgICAgICAgICAgIG91dHB1dCA9ICdmZWQnOyAvLyBub3QgMzBhaW4sIDcwYWluIG9yIDkwYWluXG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIG91dHB1dCA9ICdhaW4nO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKGIgPiAwKSB7XG4gICAgICAgICAgICBvdXRwdXQgPSBsb29rdXBbYl07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG51bWJlciArIG91dHB1dDtcbiAgICB9LFxuICAgIHdlZWsgOiB7XG4gICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICBkb3kgOiA0ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgfVxufSk7XG5cbi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBEYW5pc2ggW2RhXVxuLy8hIGF1dGhvciA6IFVscmlrIE5pZWxzZW4gOiBodHRwczovL2dpdGh1Yi5jb20vbXJiYXNlXG5cbmhvb2tzLmRlZmluZUxvY2FsZSgnZGEnLCB7XG4gICAgbW9udGhzIDogJ2phbnVhcl9mZWJydWFyX21hcnRzX2FwcmlsX21hal9qdW5pX2p1bGlfYXVndXN0X3NlcHRlbWJlcl9va3RvYmVyX25vdmVtYmVyX2RlY2VtYmVyJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0IDogJ2phbl9mZWJfbWFyX2Fwcl9tYWpfanVuX2p1bF9hdWdfc2VwX29rdF9ub3ZfZGVjJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzIDogJ3PDuG5kYWdfbWFuZGFnX3RpcnNkYWdfb25zZGFnX3RvcnNkYWdfZnJlZGFnX2zDuHJkYWcnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydCA6ICdzw7huX21hbl90aXJfb25zX3Rvcl9mcmVfbMO4cicuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbiA6ICdzw7hfbWFfdGlfb25fdG9fZnJfbMO4Jy5zcGxpdCgnXycpLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdISDptbScsXG4gICAgICAgIExUUyA6ICdISDptbTpzcycsXG4gICAgICAgIEwgOiAnREQuTU0uWVlZWScsXG4gICAgICAgIExMIDogJ0QuIE1NTU0gWVlZWScsXG4gICAgICAgIExMTCA6ICdELiBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICBMTExMIDogJ2RkZGQgW2QuXSBELiBNTU1NIFlZWVkgW2tsLl0gSEg6bW0nXG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheSA6ICdbaSBkYWcga2wuXSBMVCcsXG4gICAgICAgIG5leHREYXkgOiAnW2kgbW9yZ2VuIGtsLl0gTFQnLFxuICAgICAgICBuZXh0V2VlayA6ICdww6UgZGRkZCBba2wuXSBMVCcsXG4gICAgICAgIGxhc3REYXkgOiAnW2kgZ8OlciBrbC5dIExUJyxcbiAgICAgICAgbGFzdFdlZWsgOiAnW2ldIGRkZGRbcyBrbC5dIExUJyxcbiAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJ29tICVzJyxcbiAgICAgICAgcGFzdCA6ICclcyBzaWRlbicsXG4gICAgICAgIHMgOiAnZsOlIHNla3VuZGVyJyxcbiAgICAgICAgc3MgOiAnJWQgc2VrdW5kZXInLFxuICAgICAgICBtIDogJ2V0IG1pbnV0JyxcbiAgICAgICAgbW0gOiAnJWQgbWludXR0ZXInLFxuICAgICAgICBoIDogJ2VuIHRpbWUnLFxuICAgICAgICBoaCA6ICclZCB0aW1lcicsXG4gICAgICAgIGQgOiAnZW4gZGFnJyxcbiAgICAgICAgZGQgOiAnJWQgZGFnZScsXG4gICAgICAgIE0gOiAnZW4gbcOlbmVkJyxcbiAgICAgICAgTU0gOiAnJWQgbcOlbmVkZXInLFxuICAgICAgICB5IDogJ2V0IMOlcicsXG4gICAgICAgIHl5IDogJyVkIMOlcidcbiAgICB9LFxuICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfVxcLi8sXG4gICAgb3JkaW5hbCA6ICclZC4nLFxuICAgIHdlZWsgOiB7XG4gICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICBkb3kgOiA0ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgfVxufSk7XG5cbi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBHZXJtYW4gKEF1c3RyaWEpIFtkZS1hdF1cbi8vISBhdXRob3IgOiBsbHVjaHMgOiBodHRwczovL2dpdGh1Yi5jb20vbGx1Y2hzXG4vLyEgYXV0aG9yOiBNZW5lbGlvbiBFbGVuc8O6bGU6IGh0dHBzOi8vZ2l0aHViLmNvbS9PaXJlXG4vLyEgYXV0aG9yIDogTWFydGluIEdyb2xsZXIgOiBodHRwczovL2dpdGh1Yi5jb20vTWFkTUdcbi8vISBhdXRob3IgOiBNaWtvbGFqIERhZGVsYSA6IGh0dHBzOi8vZ2l0aHViLmNvbS9taWswMWFqXG5cbmZ1bmN0aW9uIHByb2Nlc3NSZWxhdGl2ZVRpbWUobnVtYmVyLCB3aXRob3V0U3VmZml4LCBrZXksIGlzRnV0dXJlKSB7XG4gICAgdmFyIGZvcm1hdCA9IHtcbiAgICAgICAgJ20nOiBbJ2VpbmUgTWludXRlJywgJ2VpbmVyIE1pbnV0ZSddLFxuICAgICAgICAnaCc6IFsnZWluZSBTdHVuZGUnLCAnZWluZXIgU3R1bmRlJ10sXG4gICAgICAgICdkJzogWydlaW4gVGFnJywgJ2VpbmVtIFRhZyddLFxuICAgICAgICAnZGQnOiBbbnVtYmVyICsgJyBUYWdlJywgbnVtYmVyICsgJyBUYWdlbiddLFxuICAgICAgICAnTSc6IFsnZWluIE1vbmF0JywgJ2VpbmVtIE1vbmF0J10sXG4gICAgICAgICdNTSc6IFtudW1iZXIgKyAnIE1vbmF0ZScsIG51bWJlciArICcgTW9uYXRlbiddLFxuICAgICAgICAneSc6IFsnZWluIEphaHInLCAnZWluZW0gSmFociddLFxuICAgICAgICAneXknOiBbbnVtYmVyICsgJyBKYWhyZScsIG51bWJlciArICcgSmFocmVuJ11cbiAgICB9O1xuICAgIHJldHVybiB3aXRob3V0U3VmZml4ID8gZm9ybWF0W2tleV1bMF0gOiBmb3JtYXRba2V5XVsxXTtcbn1cblxuaG9va3MuZGVmaW5lTG9jYWxlKCdkZS1hdCcsIHtcbiAgICBtb250aHMgOiAnSsOkbm5lcl9GZWJydWFyX03DpHJ6X0FwcmlsX01haV9KdW5pX0p1bGlfQXVndXN0X1NlcHRlbWJlcl9Pa3RvYmVyX05vdmVtYmVyX0RlemVtYmVyJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0IDogJ0rDpG4uX0ZlYi5fTcOkcnpfQXByLl9NYWlfSnVuaV9KdWxpX0F1Zy5fU2VwLl9Pa3QuX05vdi5fRGV6Licuc3BsaXQoJ18nKSxcbiAgICBtb250aHNQYXJzZUV4YWN0IDogdHJ1ZSxcbiAgICB3ZWVrZGF5cyA6ICdTb25udGFnX01vbnRhZ19EaWVuc3RhZ19NaXR0d29jaF9Eb25uZXJzdGFnX0ZyZWl0YWdfU2Ftc3RhZycuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0IDogJ1NvLl9Nby5fRGkuX01pLl9Eby5fRnIuX1NhLicuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbiA6ICdTb19Nb19EaV9NaV9Eb19Gcl9TYScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVDogJ0hIOm1tJyxcbiAgICAgICAgTFRTOiAnSEg6bW06c3MnLFxuICAgICAgICBMIDogJ0RELk1NLllZWVknLFxuICAgICAgICBMTCA6ICdELiBNTU1NIFlZWVknLFxuICAgICAgICBMTEwgOiAnRC4gTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgTExMTCA6ICdkZGRkLCBELiBNTU1NIFlZWVkgSEg6bW0nXG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheTogJ1toZXV0ZSB1bV0gTFQgW1Vocl0nLFxuICAgICAgICBzYW1lRWxzZTogJ0wnLFxuICAgICAgICBuZXh0RGF5OiAnW21vcmdlbiB1bV0gTFQgW1Vocl0nLFxuICAgICAgICBuZXh0V2VlazogJ2RkZGQgW3VtXSBMVCBbVWhyXScsXG4gICAgICAgIGxhc3REYXk6ICdbZ2VzdGVybiB1bV0gTFQgW1Vocl0nLFxuICAgICAgICBsYXN0V2VlazogJ1tsZXR6dGVuXSBkZGRkIFt1bV0gTFQgW1Vocl0nXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6ICdpbiAlcycsXG4gICAgICAgIHBhc3QgOiAndm9yICVzJyxcbiAgICAgICAgcyA6ICdlaW4gcGFhciBTZWt1bmRlbicsXG4gICAgICAgIHNzIDogJyVkIFNla3VuZGVuJyxcbiAgICAgICAgbSA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUsXG4gICAgICAgIG1tIDogJyVkIE1pbnV0ZW4nLFxuICAgICAgICBoIDogcHJvY2Vzc1JlbGF0aXZlVGltZSxcbiAgICAgICAgaGggOiAnJWQgU3R1bmRlbicsXG4gICAgICAgIGQgOiBwcm9jZXNzUmVsYXRpdmVUaW1lLFxuICAgICAgICBkZCA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUsXG4gICAgICAgIE0gOiBwcm9jZXNzUmVsYXRpdmVUaW1lLFxuICAgICAgICBNTSA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUsXG4gICAgICAgIHkgOiBwcm9jZXNzUmVsYXRpdmVUaW1lLFxuICAgICAgICB5eSA6IHByb2Nlc3NSZWxhdGl2ZVRpbWVcbiAgICB9LFxuICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfVxcLi8sXG4gICAgb3JkaW5hbCA6ICclZC4nLFxuICAgIHdlZWsgOiB7XG4gICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICBkb3kgOiA0ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgfVxufSk7XG5cbi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBHZXJtYW4gKFN3aXR6ZXJsYW5kKSBbZGUtY2hdXG4vLyEgYXV0aG9yIDogc3NjaHVlbGxlciA6IGh0dHBzOi8vZ2l0aHViLmNvbS9zc2NodWVsbGVyXG5cbi8vIGJhc2VkIG9uOiBodHRwczovL3d3dy5iay5hZG1pbi5jaC9kb2t1bWVudGF0aW9uL3NwcmFjaGVuLzA0OTE1LzA1MDE2L2luZGV4Lmh0bWw/bGFuZz1kZSNcblxuZnVuY3Rpb24gcHJvY2Vzc1JlbGF0aXZlVGltZSQxKG51bWJlciwgd2l0aG91dFN1ZmZpeCwga2V5LCBpc0Z1dHVyZSkge1xuICAgIHZhciBmb3JtYXQgPSB7XG4gICAgICAgICdtJzogWydlaW5lIE1pbnV0ZScsICdlaW5lciBNaW51dGUnXSxcbiAgICAgICAgJ2gnOiBbJ2VpbmUgU3R1bmRlJywgJ2VpbmVyIFN0dW5kZSddLFxuICAgICAgICAnZCc6IFsnZWluIFRhZycsICdlaW5lbSBUYWcnXSxcbiAgICAgICAgJ2RkJzogW251bWJlciArICcgVGFnZScsIG51bWJlciArICcgVGFnZW4nXSxcbiAgICAgICAgJ00nOiBbJ2VpbiBNb25hdCcsICdlaW5lbSBNb25hdCddLFxuICAgICAgICAnTU0nOiBbbnVtYmVyICsgJyBNb25hdGUnLCBudW1iZXIgKyAnIE1vbmF0ZW4nXSxcbiAgICAgICAgJ3knOiBbJ2VpbiBKYWhyJywgJ2VpbmVtIEphaHInXSxcbiAgICAgICAgJ3l5JzogW251bWJlciArICcgSmFocmUnLCBudW1iZXIgKyAnIEphaHJlbiddXG4gICAgfTtcbiAgICByZXR1cm4gd2l0aG91dFN1ZmZpeCA/IGZvcm1hdFtrZXldWzBdIDogZm9ybWF0W2tleV1bMV07XG59XG5cbmhvb2tzLmRlZmluZUxvY2FsZSgnZGUtY2gnLCB7XG4gICAgbW9udGhzIDogJ0phbnVhcl9GZWJydWFyX03DpHJ6X0FwcmlsX01haV9KdW5pX0p1bGlfQXVndXN0X1NlcHRlbWJlcl9Pa3RvYmVyX05vdmVtYmVyX0RlemVtYmVyJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0IDogJ0phbi5fRmViLl9Nw6Ryel9BcHIuX01haV9KdW5pX0p1bGlfQXVnLl9TZXAuX09rdC5fTm92Ll9EZXouJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgIHdlZWtkYXlzIDogJ1Nvbm50YWdfTW9udGFnX0RpZW5zdGFnX01pdHR3b2NoX0Rvbm5lcnN0YWdfRnJlaXRhZ19TYW1zdGFnJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzU2hvcnQgOiAnU29fTW9fRGlfTWlfRG9fRnJfU2EnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW4gOiAnU29fTW9fRGlfTWlfRG9fRnJfU2EnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNQYXJzZUV4YWN0IDogdHJ1ZSxcbiAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgTFQ6ICdISDptbScsXG4gICAgICAgIExUUzogJ0hIOm1tOnNzJyxcbiAgICAgICAgTCA6ICdERC5NTS5ZWVlZJyxcbiAgICAgICAgTEwgOiAnRC4gTU1NTSBZWVlZJyxcbiAgICAgICAgTExMIDogJ0QuIE1NTU0gWVlZWSBISDptbScsXG4gICAgICAgIExMTEwgOiAnZGRkZCwgRC4gTU1NTSBZWVlZIEhIOm1tJ1xuICAgIH0sXG4gICAgY2FsZW5kYXIgOiB7XG4gICAgICAgIHNhbWVEYXk6ICdbaGV1dGUgdW1dIExUIFtVaHJdJyxcbiAgICAgICAgc2FtZUVsc2U6ICdMJyxcbiAgICAgICAgbmV4dERheTogJ1ttb3JnZW4gdW1dIExUIFtVaHJdJyxcbiAgICAgICAgbmV4dFdlZWs6ICdkZGRkIFt1bV0gTFQgW1Vocl0nLFxuICAgICAgICBsYXN0RGF5OiAnW2dlc3Rlcm4gdW1dIExUIFtVaHJdJyxcbiAgICAgICAgbGFzdFdlZWs6ICdbbGV0enRlbl0gZGRkZCBbdW1dIExUIFtVaHJdJ1xuICAgIH0sXG4gICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICBmdXR1cmUgOiAnaW4gJXMnLFxuICAgICAgICBwYXN0IDogJ3ZvciAlcycsXG4gICAgICAgIHMgOiAnZWluIHBhYXIgU2VrdW5kZW4nLFxuICAgICAgICBzcyA6ICclZCBTZWt1bmRlbicsXG4gICAgICAgIG0gOiBwcm9jZXNzUmVsYXRpdmVUaW1lJDEsXG4gICAgICAgIG1tIDogJyVkIE1pbnV0ZW4nLFxuICAgICAgICBoIDogcHJvY2Vzc1JlbGF0aXZlVGltZSQxLFxuICAgICAgICBoaCA6ICclZCBTdHVuZGVuJyxcbiAgICAgICAgZCA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUkMSxcbiAgICAgICAgZGQgOiBwcm9jZXNzUmVsYXRpdmVUaW1lJDEsXG4gICAgICAgIE0gOiBwcm9jZXNzUmVsYXRpdmVUaW1lJDEsXG4gICAgICAgIE1NIDogcHJvY2Vzc1JlbGF0aXZlVGltZSQxLFxuICAgICAgICB5IDogcHJvY2Vzc1JlbGF0aXZlVGltZSQxLFxuICAgICAgICB5eSA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUkMVxuICAgIH0sXG4gICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9XFwuLyxcbiAgICBvcmRpbmFsIDogJyVkLicsXG4gICAgd2VlayA6IHtcbiAgICAgICAgZG93IDogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgIGRveSA6IDQgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDR0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICB9XG59KTtcblxuLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSA6IEdlcm1hbiBbZGVdXG4vLyEgYXV0aG9yIDogbGx1Y2hzIDogaHR0cHM6Ly9naXRodWIuY29tL2xsdWNoc1xuLy8hIGF1dGhvcjogTWVuZWxpb24gRWxlbnPDumxlOiBodHRwczovL2dpdGh1Yi5jb20vT2lyZVxuLy8hIGF1dGhvciA6IE1pa29sYWogRGFkZWxhIDogaHR0cHM6Ly9naXRodWIuY29tL21pazAxYWpcblxuZnVuY3Rpb24gcHJvY2Vzc1JlbGF0aXZlVGltZSQyKG51bWJlciwgd2l0aG91dFN1ZmZpeCwga2V5LCBpc0Z1dHVyZSkge1xuICAgIHZhciBmb3JtYXQgPSB7XG4gICAgICAgICdtJzogWydlaW5lIE1pbnV0ZScsICdlaW5lciBNaW51dGUnXSxcbiAgICAgICAgJ2gnOiBbJ2VpbmUgU3R1bmRlJywgJ2VpbmVyIFN0dW5kZSddLFxuICAgICAgICAnZCc6IFsnZWluIFRhZycsICdlaW5lbSBUYWcnXSxcbiAgICAgICAgJ2RkJzogW251bWJlciArICcgVGFnZScsIG51bWJlciArICcgVGFnZW4nXSxcbiAgICAgICAgJ00nOiBbJ2VpbiBNb25hdCcsICdlaW5lbSBNb25hdCddLFxuICAgICAgICAnTU0nOiBbbnVtYmVyICsgJyBNb25hdGUnLCBudW1iZXIgKyAnIE1vbmF0ZW4nXSxcbiAgICAgICAgJ3knOiBbJ2VpbiBKYWhyJywgJ2VpbmVtIEphaHInXSxcbiAgICAgICAgJ3l5JzogW251bWJlciArICcgSmFocmUnLCBudW1iZXIgKyAnIEphaHJlbiddXG4gICAgfTtcbiAgICByZXR1cm4gd2l0aG91dFN1ZmZpeCA/IGZvcm1hdFtrZXldWzBdIDogZm9ybWF0W2tleV1bMV07XG59XG5cbmhvb2tzLmRlZmluZUxvY2FsZSgnZGUnLCB7XG4gICAgbW9udGhzIDogJ0phbnVhcl9GZWJydWFyX03DpHJ6X0FwcmlsX01haV9KdW5pX0p1bGlfQXVndXN0X1NlcHRlbWJlcl9Pa3RvYmVyX05vdmVtYmVyX0RlemVtYmVyJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0IDogJ0phbi5fRmViLl9Nw6Ryel9BcHIuX01haV9KdW5pX0p1bGlfQXVnLl9TZXAuX09rdC5fTm92Ll9EZXouJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgIHdlZWtkYXlzIDogJ1Nvbm50YWdfTW9udGFnX0RpZW5zdGFnX01pdHR3b2NoX0Rvbm5lcnN0YWdfRnJlaXRhZ19TYW1zdGFnJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzU2hvcnQgOiAnU28uX01vLl9EaS5fTWkuX0RvLl9Gci5fU2EuJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzTWluIDogJ1NvX01vX0RpX01pX0RvX0ZyX1NhJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzUGFyc2VFeGFjdCA6IHRydWUsXG4gICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgIExUOiAnSEg6bW0nLFxuICAgICAgICBMVFM6ICdISDptbTpzcycsXG4gICAgICAgIEwgOiAnREQuTU0uWVlZWScsXG4gICAgICAgIExMIDogJ0QuIE1NTU0gWVlZWScsXG4gICAgICAgIExMTCA6ICdELiBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICBMTExMIDogJ2RkZGQsIEQuIE1NTU0gWVlZWSBISDptbSdcbiAgICB9LFxuICAgIGNhbGVuZGFyIDoge1xuICAgICAgICBzYW1lRGF5OiAnW2hldXRlIHVtXSBMVCBbVWhyXScsXG4gICAgICAgIHNhbWVFbHNlOiAnTCcsXG4gICAgICAgIG5leHREYXk6ICdbbW9yZ2VuIHVtXSBMVCBbVWhyXScsXG4gICAgICAgIG5leHRXZWVrOiAnZGRkZCBbdW1dIExUIFtVaHJdJyxcbiAgICAgICAgbGFzdERheTogJ1tnZXN0ZXJuIHVtXSBMVCBbVWhyXScsXG4gICAgICAgIGxhc3RXZWVrOiAnW2xldHp0ZW5dIGRkZGQgW3VtXSBMVCBbVWhyXSdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJ2luICVzJyxcbiAgICAgICAgcGFzdCA6ICd2b3IgJXMnLFxuICAgICAgICBzIDogJ2VpbiBwYWFyIFNla3VuZGVuJyxcbiAgICAgICAgc3MgOiAnJWQgU2VrdW5kZW4nLFxuICAgICAgICBtIDogcHJvY2Vzc1JlbGF0aXZlVGltZSQyLFxuICAgICAgICBtbSA6ICclZCBNaW51dGVuJyxcbiAgICAgICAgaCA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUkMixcbiAgICAgICAgaGggOiAnJWQgU3R1bmRlbicsXG4gICAgICAgIGQgOiBwcm9jZXNzUmVsYXRpdmVUaW1lJDIsXG4gICAgICAgIGRkIDogcHJvY2Vzc1JlbGF0aXZlVGltZSQyLFxuICAgICAgICBNIDogcHJvY2Vzc1JlbGF0aXZlVGltZSQyLFxuICAgICAgICBNTSA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUkMixcbiAgICAgICAgeSA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUkMixcbiAgICAgICAgeXkgOiBwcm9jZXNzUmVsYXRpdmVUaW1lJDJcbiAgICB9LFxuICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfVxcLi8sXG4gICAgb3JkaW5hbCA6ICclZC4nLFxuICAgIHdlZWsgOiB7XG4gICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICBkb3kgOiA0ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgfVxufSk7XG5cbi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBNYWxkaXZpYW4gW2R2XVxuLy8hIGF1dGhvciA6IEphd2lzaCBIYW1lZWQgOiBodHRwczovL2dpdGh1Yi5jb20vamF3aXNoXG5cbnZhciBtb250aHMkNCA9IFtcbiAgICAn3pberN6C3qreh96m3oPeqScsXG4gICAgJ96K3qzehN6w3oPeqt6H3qbeg96pJyxcbiAgICAn3onep96D3qjel96qJyxcbiAgICAn3oferd6V3rDeg96p3o3eqicsXG4gICAgJ96J3q0nLFxuICAgICfelt6r3oLesCcsXG4gICAgJ96W3qrejd6m3ofeqCcsXG4gICAgJ96H3q/ejt6m3pDesN6T3qonLFxuICAgICfekN6s3pXesN6T3qzeid6w3oTept6D3qonLFxuICAgICfeh96u3obesN6T3q/ehN6m3oPeqicsXG4gICAgJ96C3q7eiN6s3onesN6E3qbeg96qJyxcbiAgICAn3pHeqN6Q3qzeid6w3oTept6D3qonXG5dO1xudmFyIHdlZWtkYXlzID0gW1xuICAgICfeh96n3oveqN6H3rDejN6mJyxcbiAgICAn3oDer96J3qYnLFxuICAgICfeh96m3oLesN6O3qfeg96mJyxcbiAgICAn3oTeqt6L3qYnLFxuICAgICfehN6q3oPep96Q3rDeit6m3ozeqCcsXG4gICAgJ96A3qreht6q3oPeqicsXG4gICAgJ96A3q7egt6o3oDeqN6D3qonXG5dO1xuXG5ob29rcy5kZWZpbmVMb2NhbGUoJ2R2Jywge1xuICAgIG1vbnRocyA6IG1vbnRocyQ0LFxuICAgIG1vbnRoc1Nob3J0IDogbW9udGhzJDQsXG4gICAgd2Vla2RheXMgOiB3ZWVrZGF5cyxcbiAgICB3ZWVrZGF5c1Nob3J0IDogd2Vla2RheXMsXG4gICAgd2Vla2RheXNNaW4gOiAn3ofep96L3qhf3oDer96J3qZf3ofept6C3rBf3oTeqt6L3qZf3oTeqt6D3qdf3oDeqt6G3qpf3oDert6C3qgnLnNwbGl0KCdfJyksXG4gICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG5cbiAgICAgICAgTFQgOiAnSEg6bW0nLFxuICAgICAgICBMVFMgOiAnSEg6bW06c3MnLFxuICAgICAgICBMIDogJ0QvTS9ZWVlZJyxcbiAgICAgICAgTEwgOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICBMTEwgOiAnRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICBMTExMIDogJ2RkZGQgRCBNTU1NIFlZWVkgSEg6bW0nXG4gICAgfSxcbiAgICBtZXJpZGllbVBhcnNlOiAv3onehnzeid6KLyxcbiAgICBpc1BNIDogZnVuY3Rpb24gKGlucHV0KSB7XG4gICAgICAgIHJldHVybiAn3oneiicgPT09IGlucHV0O1xuICAgIH0sXG4gICAgbWVyaWRpZW0gOiBmdW5jdGlvbiAoaG91ciwgbWludXRlLCBpc0xvd2VyKSB7XG4gICAgICAgIGlmIChob3VyIDwgMTIpIHtcbiAgICAgICAgICAgIHJldHVybiAn3onehic7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gJ96J3oonO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheSA6ICdb3oneqN6H3qbei96qXSBMVCcsXG4gICAgICAgIG5leHREYXkgOiAnW96J3qfei96m3onep10gTFQnLFxuICAgICAgICBuZXh0V2VlayA6ICdkZGRkIExUJyxcbiAgICAgICAgbGFzdERheSA6ICdb3ofeqN6H3rDelN6sXSBMVCcsXG4gICAgICAgIGxhc3RXZWVrIDogJ1veit6n3ofeqN6M3qreiN6oXSBkZGRkIExUJyxcbiAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJ96M3qzeg96t3o7ept6H3qggJXMnLFxuICAgICAgICBwYXN0IDogJ96G3qreg96o3oLesCAlcycsXG4gICAgICAgIHMgOiAn3pDeqN6G3qregt6w3ozeqt6G3q7ehd6s3ofesCcsXG4gICAgICAgIHNzIDogJ2QlIN6Q3qjeht6q3oLesN6M3qonLFxuICAgICAgICBtIDogJ96J3qjegt6o3pPerN6H3rAnLFxuICAgICAgICBtbSA6ICfeid6o3oLeqN6T3qogJWQnLFxuICAgICAgICBoIDogJ96O3qbekd6o3ofeqN6D3qzeh96wJyxcbiAgICAgICAgaGggOiAn3o7ept6R3qjeh96o3oPeqiAlZCcsXG4gICAgICAgIGQgOiAn3oveqt6I3qbegN6s3ofesCcsXG4gICAgICAgIGRkIDogJ96L3qreiN6m3pDesCAlZCcsXG4gICAgICAgIE0gOiAn3onept6A3qzeh96wJyxcbiAgICAgICAgTU0gOiAn3onept6Q3rAgJWQnLFxuICAgICAgICB5IDogJ96H3qbegN6m3oPerN6H3rAnLFxuICAgICAgICB5eSA6ICfeh96m3oDept6D3qogJWQnXG4gICAgfSxcbiAgICBwcmVwYXJzZTogZnVuY3Rpb24gKHN0cmluZykge1xuICAgICAgICByZXR1cm4gc3RyaW5nLnJlcGxhY2UoL9iML2csICcsJyk7XG4gICAgfSxcbiAgICBwb3N0Zm9ybWF0OiBmdW5jdGlvbiAoc3RyaW5nKSB7XG4gICAgICAgIHJldHVybiBzdHJpbmcucmVwbGFjZSgvLC9nLCAn2IwnKTtcbiAgICB9LFxuICAgIHdlZWsgOiB7XG4gICAgICAgIGRvdyA6IDcsICAvLyBTdW5kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogMTIgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDFzdCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICB9XG59KTtcblxuLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSA6IEdyZWVrIFtlbF1cbi8vISBhdXRob3IgOiBBZ2dlbG9zIEthcmFsaWFzIDogaHR0cHM6Ly9naXRodWIuY29tL21laGllbFxuXG5ob29rcy5kZWZpbmVMb2NhbGUoJ2VsJywge1xuICAgIG1vbnRoc05vbWluYXRpdmVFbCA6ICfOmc6xzr3Ov8+FzqzPgc65zr/Pgl/Ops61zrLPgc6/z4XOrM+BzrnOv8+CX86czqzPgc+EzrnOv8+CX86Rz4DPgc6vzrvOuc6/z4JfzpzOrM65zr/Pgl/Omc6/z43Ovc65zr/Pgl/Omc6/z43Ou865zr/Pgl/Okc+NzrPOv8+Fz4PPhM6/z4JfzqPOtc+Az4TOrc68zrLPgc65zr/Pgl/On866z4TPjs6yz4HOuc6/z4Jfzp3Ov86tzrzOss+BzrnOv8+CX86UzrXOus6tzrzOss+BzrnOv8+CJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc0dlbml0aXZlRWwgOiAnzpnOsc69zr/Phc6xz4HOr86/z4VfzqbOtc6yz4HOv8+FzrHPgc6vzr/PhV/OnM6xz4HPhM6vzr/PhV/Okc+Az4HOuc67zq/Ov8+FX86czrHOkM6/z4VfzpnOv8+Fzr3Or86/z4VfzpnOv8+FzrvOr86/z4VfzpHPhc6zzr/Pjc+Dz4TOv8+FX86jzrXPgM+EzrXOvM6yz4HOr86/z4Vfzp/Ous+Ez4nOss+Bzq/Ov8+FX86dzr/Otc68zrLPgc6vzr/PhV/OlM61zrrOtc68zrLPgc6vzr/PhScuc3BsaXQoJ18nKSxcbiAgICBtb250aHMgOiBmdW5jdGlvbiAobW9tZW50VG9Gb3JtYXQsIGZvcm1hdCkge1xuICAgICAgICBpZiAoIW1vbWVudFRvRm9ybWF0KSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fbW9udGhzTm9taW5hdGl2ZUVsO1xuICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBmb3JtYXQgPT09ICdzdHJpbmcnICYmIC9ELy50ZXN0KGZvcm1hdC5zdWJzdHJpbmcoMCwgZm9ybWF0LmluZGV4T2YoJ01NTU0nKSkpKSB7IC8vIGlmIHRoZXJlIGlzIGEgZGF5IG51bWJlciBiZWZvcmUgJ01NTU0nXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fbW9udGhzR2VuaXRpdmVFbFttb21lbnRUb0Zvcm1hdC5tb250aCgpXTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9tb250aHNOb21pbmF0aXZlRWxbbW9tZW50VG9Gb3JtYXQubW9udGgoKV07XG4gICAgICAgIH1cbiAgICB9LFxuICAgIG1vbnRoc1Nob3J0IDogJ86ZzrHOvV/Ops61zrJfzpzOsc+BX86Rz4DPgV/OnM6xz4pfzpnOv8+Fzr1fzpnOv8+FzrtfzpHPhc6zX86jzrXPgF/On866z4Rfzp3Ov861X86UzrXOuicuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5cyA6ICfOms+Fz4HOuc6xzrrOrl/OlM61z4XPhM6tz4HOsV/OpM+Bzq/PhM63X86kzrXPhM6sz4HPhM63X86gzq3OvM+Az4TOt1/OoM6xz4HOsc+DzrrOtc+Fzq5fzqPOrM6yzrLOsc+Ezr8nLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydCA6ICfOms+Fz4FfzpTOtc+FX86kz4HOuV/OpM61z4RfzqDOtc68X86gzrHPgV/Oo86xzrInLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW4gOiAnzprPhV/OlM61X86kz4FfzqTOtV/OoM61X86gzrFfzqPOsScuc3BsaXQoJ18nKSxcbiAgICBtZXJpZGllbSA6IGZ1bmN0aW9uIChob3VycywgbWludXRlcywgaXNMb3dlcikge1xuICAgICAgICBpZiAoaG91cnMgPiAxMSkge1xuICAgICAgICAgICAgcmV0dXJuIGlzTG93ZXIgPyAnzrzOvCcgOiAnzpzOnCc7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gaXNMb3dlciA/ICfPgM68JyA6ICfOoM6cJztcbiAgICAgICAgfVxuICAgIH0sXG4gICAgaXNQTSA6IGZ1bmN0aW9uIChpbnB1dCkge1xuICAgICAgICByZXR1cm4gKChpbnB1dCArICcnKS50b0xvd2VyQ2FzZSgpWzBdID09PSAnzrwnKTtcbiAgICB9LFxuICAgIG1lcmlkaWVtUGFyc2UgOiAvW86gzpxdXFwuP86cP1xcLj8vaSxcbiAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgTFQgOiAnaDptbSBBJyxcbiAgICAgICAgTFRTIDogJ2g6bW06c3MgQScsXG4gICAgICAgIEwgOiAnREQvTU0vWVlZWScsXG4gICAgICAgIExMIDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgTExMIDogJ0QgTU1NTSBZWVlZIGg6bW0gQScsXG4gICAgICAgIExMTEwgOiAnZGRkZCwgRCBNTU1NIFlZWVkgaDptbSBBJ1xuICAgIH0sXG4gICAgY2FsZW5kYXJFbCA6IHtcbiAgICAgICAgc2FtZURheSA6ICdbzqPOrs68zrXPgc6xIHt9XSBMVCcsXG4gICAgICAgIG5leHREYXkgOiAnW86Rz43Pgc65zr8ge31dIExUJyxcbiAgICAgICAgbmV4dFdlZWsgOiAnZGRkZCBbe31dIExUJyxcbiAgICAgICAgbGFzdERheSA6ICdbzqfOuM61z4Ige31dIExUJyxcbiAgICAgICAgbGFzdFdlZWsgOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBzd2l0Y2ggKHRoaXMuZGF5KCkpIHtcbiAgICAgICAgICAgICAgICBjYXNlIDY6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnW8+Ezr8gz4DPgc6/zrfOs86/z43OvM61zr3Ov10gZGRkZCBbe31dIExUJztcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1vPhM63zr0gz4DPgc6/zrfOs86/z43OvM61zr3Ot10gZGRkZCBbe31dIExUJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICB9LFxuICAgIGNhbGVuZGFyIDogZnVuY3Rpb24gKGtleSwgbW9tKSB7XG4gICAgICAgIHZhciBvdXRwdXQgPSB0aGlzLl9jYWxlbmRhckVsW2tleV0sXG4gICAgICAgICAgICBob3VycyA9IG1vbSAmJiBtb20uaG91cnMoKTtcbiAgICAgICAgaWYgKGlzRnVuY3Rpb24ob3V0cHV0KSkge1xuICAgICAgICAgICAgb3V0cHV0ID0gb3V0cHV0LmFwcGx5KG1vbSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG91dHB1dC5yZXBsYWNlKCd7fScsIChob3VycyAlIDEyID09PSAxID8gJ8+Dz4TOtycgOiAnz4PPhM65z4InKSk7XG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6ICfPg861ICVzJyxcbiAgICAgICAgcGFzdCA6ICclcyDPgM+BzrnOvScsXG4gICAgICAgIHMgOiAnzrvOr86zzrEgzrTOtc+Fz4TOtc+Bz4zOu861z4DPhM6xJyxcbiAgICAgICAgc3MgOiAnJWQgzrTOtc+Fz4TOtc+Bz4zOu861z4DPhM6xJyxcbiAgICAgICAgbSA6ICfOrc69zrEgzrvOtc+Az4TPjCcsXG4gICAgICAgIG1tIDogJyVkIM67zrXPgM+EzqwnLFxuICAgICAgICBoIDogJ868zq/OsSDPjs+BzrEnLFxuICAgICAgICBoaCA6ICclZCDPjs+BzrXPgicsXG4gICAgICAgIGQgOiAnzrzOr86xIM68zq3Pgc6xJyxcbiAgICAgICAgZGQgOiAnJWQgzrzOrc+BzrXPgicsXG4gICAgICAgIE0gOiAnzq3Ovc6xz4IgzrzOrs69zrHPgicsXG4gICAgICAgIE1NIDogJyVkIM68zq7Ovc61z4InLFxuICAgICAgICB5IDogJ86tzr3Osc+CIM+Hz4HPjM69zr/PgicsXG4gICAgICAgIHl5IDogJyVkIM+Hz4HPjM69zrnOsSdcbiAgICB9LFxuICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfc63LyxcbiAgICBvcmRpbmFsOiAnJWTOtycsXG4gICAgd2VlayA6IHtcbiAgICAgICAgZG93IDogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgIGRveSA6IDQgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDRzdCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICB9XG59KTtcblxuLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSA6IEVuZ2xpc2ggKEF1c3RyYWxpYSkgW2VuLWF1XVxuLy8hIGF1dGhvciA6IEphcmVkIE1vcnNlIDogaHR0cHM6Ly9naXRodWIuY29tL2phcmNvYWxcblxuaG9va3MuZGVmaW5lTG9jYWxlKCdlbi1hdScsIHtcbiAgICBtb250aHMgOiAnSmFudWFyeV9GZWJydWFyeV9NYXJjaF9BcHJpbF9NYXlfSnVuZV9KdWx5X0F1Z3VzdF9TZXB0ZW1iZXJfT2N0b2Jlcl9Ob3ZlbWJlcl9EZWNlbWJlcicuc3BsaXQoJ18nKSxcbiAgICBtb250aHNTaG9ydCA6ICdKYW5fRmViX01hcl9BcHJfTWF5X0p1bl9KdWxfQXVnX1NlcF9PY3RfTm92X0RlYycuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5cyA6ICdTdW5kYXlfTW9uZGF5X1R1ZXNkYXlfV2VkbmVzZGF5X1RodXJzZGF5X0ZyaWRheV9TYXR1cmRheScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0IDogJ1N1bl9Nb25fVHVlX1dlZF9UaHVfRnJpX1NhdCcuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbiA6ICdTdV9Nb19UdV9XZV9UaF9Gcl9TYScuc3BsaXQoJ18nKSxcbiAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgTFQgOiAnaDptbSBBJyxcbiAgICAgICAgTFRTIDogJ2g6bW06c3MgQScsXG4gICAgICAgIEwgOiAnREQvTU0vWVlZWScsXG4gICAgICAgIExMIDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgTExMIDogJ0QgTU1NTSBZWVlZIGg6bW0gQScsXG4gICAgICAgIExMTEwgOiAnZGRkZCwgRCBNTU1NIFlZWVkgaDptbSBBJ1xuICAgIH0sXG4gICAgY2FsZW5kYXIgOiB7XG4gICAgICAgIHNhbWVEYXkgOiAnW1RvZGF5IGF0XSBMVCcsXG4gICAgICAgIG5leHREYXkgOiAnW1RvbW9ycm93IGF0XSBMVCcsXG4gICAgICAgIG5leHRXZWVrIDogJ2RkZGQgW2F0XSBMVCcsXG4gICAgICAgIGxhc3REYXkgOiAnW1llc3RlcmRheSBhdF0gTFQnLFxuICAgICAgICBsYXN0V2VlayA6ICdbTGFzdF0gZGRkZCBbYXRdIExUJyxcbiAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJ2luICVzJyxcbiAgICAgICAgcGFzdCA6ICclcyBhZ28nLFxuICAgICAgICBzIDogJ2EgZmV3IHNlY29uZHMnLFxuICAgICAgICBzcyA6ICclZCBzZWNvbmRzJyxcbiAgICAgICAgbSA6ICdhIG1pbnV0ZScsXG4gICAgICAgIG1tIDogJyVkIG1pbnV0ZXMnLFxuICAgICAgICBoIDogJ2FuIGhvdXInLFxuICAgICAgICBoaCA6ICclZCBob3VycycsXG4gICAgICAgIGQgOiAnYSBkYXknLFxuICAgICAgICBkZCA6ICclZCBkYXlzJyxcbiAgICAgICAgTSA6ICdhIG1vbnRoJyxcbiAgICAgICAgTU0gOiAnJWQgbW9udGhzJyxcbiAgICAgICAgeSA6ICdhIHllYXInLFxuICAgICAgICB5eSA6ICclZCB5ZWFycydcbiAgICB9LFxuICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfShzdHxuZHxyZHx0aCkvLFxuICAgIG9yZGluYWwgOiBmdW5jdGlvbiAobnVtYmVyKSB7XG4gICAgICAgIHZhciBiID0gbnVtYmVyICUgMTAsXG4gICAgICAgICAgICBvdXRwdXQgPSAofn4obnVtYmVyICUgMTAwIC8gMTApID09PSAxKSA/ICd0aCcgOlxuICAgICAgICAgICAgKGIgPT09IDEpID8gJ3N0JyA6XG4gICAgICAgICAgICAoYiA9PT0gMikgPyAnbmQnIDpcbiAgICAgICAgICAgIChiID09PSAzKSA/ICdyZCcgOiAndGgnO1xuICAgICAgICByZXR1cm4gbnVtYmVyICsgb3V0cHV0O1xuICAgIH0sXG4gICAgd2VlayA6IHtcbiAgICAgICAgZG93IDogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgIGRveSA6IDQgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDR0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICB9XG59KTtcblxuLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSA6IEVuZ2xpc2ggKENhbmFkYSkgW2VuLWNhXVxuLy8hIGF1dGhvciA6IEpvbmF0aGFuIEFib3VyYmloIDogaHR0cHM6Ly9naXRodWIuY29tL2pvbmJjYVxuXG5ob29rcy5kZWZpbmVMb2NhbGUoJ2VuLWNhJywge1xuICAgIG1vbnRocyA6ICdKYW51YXJ5X0ZlYnJ1YXJ5X01hcmNoX0FwcmlsX01heV9KdW5lX0p1bHlfQXVndXN0X1NlcHRlbWJlcl9PY3RvYmVyX05vdmVtYmVyX0RlY2VtYmVyJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0IDogJ0phbl9GZWJfTWFyX0Fwcl9NYXlfSnVuX0p1bF9BdWdfU2VwX09jdF9Ob3ZfRGVjJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzIDogJ1N1bmRheV9Nb25kYXlfVHVlc2RheV9XZWRuZXNkYXlfVGh1cnNkYXlfRnJpZGF5X1NhdHVyZGF5Jy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzU2hvcnQgOiAnU3VuX01vbl9UdWVfV2VkX1RodV9GcmlfU2F0Jy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzTWluIDogJ1N1X01vX1R1X1dlX1RoX0ZyX1NhJy5zcGxpdCgnXycpLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdoOm1tIEEnLFxuICAgICAgICBMVFMgOiAnaDptbTpzcyBBJyxcbiAgICAgICAgTCA6ICdZWVlZLU1NLUREJyxcbiAgICAgICAgTEwgOiAnTU1NTSBELCBZWVlZJyxcbiAgICAgICAgTExMIDogJ01NTU0gRCwgWVlZWSBoOm1tIEEnLFxuICAgICAgICBMTExMIDogJ2RkZGQsIE1NTU0gRCwgWVlZWSBoOm1tIEEnXG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheSA6ICdbVG9kYXkgYXRdIExUJyxcbiAgICAgICAgbmV4dERheSA6ICdbVG9tb3Jyb3cgYXRdIExUJyxcbiAgICAgICAgbmV4dFdlZWsgOiAnZGRkZCBbYXRdIExUJyxcbiAgICAgICAgbGFzdERheSA6ICdbWWVzdGVyZGF5IGF0XSBMVCcsXG4gICAgICAgIGxhc3RXZWVrIDogJ1tMYXN0XSBkZGRkIFthdF0gTFQnLFxuICAgICAgICBzYW1lRWxzZSA6ICdMJ1xuICAgIH0sXG4gICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICBmdXR1cmUgOiAnaW4gJXMnLFxuICAgICAgICBwYXN0IDogJyVzIGFnbycsXG4gICAgICAgIHMgOiAnYSBmZXcgc2Vjb25kcycsXG4gICAgICAgIHNzIDogJyVkIHNlY29uZHMnLFxuICAgICAgICBtIDogJ2EgbWludXRlJyxcbiAgICAgICAgbW0gOiAnJWQgbWludXRlcycsXG4gICAgICAgIGggOiAnYW4gaG91cicsXG4gICAgICAgIGhoIDogJyVkIGhvdXJzJyxcbiAgICAgICAgZCA6ICdhIGRheScsXG4gICAgICAgIGRkIDogJyVkIGRheXMnLFxuICAgICAgICBNIDogJ2EgbW9udGgnLFxuICAgICAgICBNTSA6ICclZCBtb250aHMnLFxuICAgICAgICB5IDogJ2EgeWVhcicsXG4gICAgICAgIHl5IDogJyVkIHllYXJzJ1xuICAgIH0sXG4gICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9KHN0fG5kfHJkfHRoKS8sXG4gICAgb3JkaW5hbCA6IGZ1bmN0aW9uIChudW1iZXIpIHtcbiAgICAgICAgdmFyIGIgPSBudW1iZXIgJSAxMCxcbiAgICAgICAgICAgIG91dHB1dCA9ICh+fihudW1iZXIgJSAxMDAgLyAxMCkgPT09IDEpID8gJ3RoJyA6XG4gICAgICAgICAgICAoYiA9PT0gMSkgPyAnc3QnIDpcbiAgICAgICAgICAgIChiID09PSAyKSA/ICduZCcgOlxuICAgICAgICAgICAgKGIgPT09IDMpID8gJ3JkJyA6ICd0aCc7XG4gICAgICAgIHJldHVybiBudW1iZXIgKyBvdXRwdXQ7XG4gICAgfVxufSk7XG5cbi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBFbmdsaXNoIChVbml0ZWQgS2luZ2RvbSkgW2VuLWdiXVxuLy8hIGF1dGhvciA6IENocmlzIEdlZHJpbSA6IGh0dHBzOi8vZ2l0aHViLmNvbS9jaHJpc2dlZHJpbVxuXG5ob29rcy5kZWZpbmVMb2NhbGUoJ2VuLWdiJywge1xuICAgIG1vbnRocyA6ICdKYW51YXJ5X0ZlYnJ1YXJ5X01hcmNoX0FwcmlsX01heV9KdW5lX0p1bHlfQXVndXN0X1NlcHRlbWJlcl9PY3RvYmVyX05vdmVtYmVyX0RlY2VtYmVyJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0IDogJ0phbl9GZWJfTWFyX0Fwcl9NYXlfSnVuX0p1bF9BdWdfU2VwX09jdF9Ob3ZfRGVjJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzIDogJ1N1bmRheV9Nb25kYXlfVHVlc2RheV9XZWRuZXNkYXlfVGh1cnNkYXlfRnJpZGF5X1NhdHVyZGF5Jy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzU2hvcnQgOiAnU3VuX01vbl9UdWVfV2VkX1RodV9GcmlfU2F0Jy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzTWluIDogJ1N1X01vX1R1X1dlX1RoX0ZyX1NhJy5zcGxpdCgnXycpLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdISDptbScsXG4gICAgICAgIExUUyA6ICdISDptbTpzcycsXG4gICAgICAgIEwgOiAnREQvTU0vWVlZWScsXG4gICAgICAgIExMIDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgTExMIDogJ0QgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgTExMTCA6ICdkZGRkLCBEIE1NTU0gWVlZWSBISDptbSdcbiAgICB9LFxuICAgIGNhbGVuZGFyIDoge1xuICAgICAgICBzYW1lRGF5IDogJ1tUb2RheSBhdF0gTFQnLFxuICAgICAgICBuZXh0RGF5IDogJ1tUb21vcnJvdyBhdF0gTFQnLFxuICAgICAgICBuZXh0V2VlayA6ICdkZGRkIFthdF0gTFQnLFxuICAgICAgICBsYXN0RGF5IDogJ1tZZXN0ZXJkYXkgYXRdIExUJyxcbiAgICAgICAgbGFzdFdlZWsgOiAnW0xhc3RdIGRkZGQgW2F0XSBMVCcsXG4gICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6ICdpbiAlcycsXG4gICAgICAgIHBhc3QgOiAnJXMgYWdvJyxcbiAgICAgICAgcyA6ICdhIGZldyBzZWNvbmRzJyxcbiAgICAgICAgc3MgOiAnJWQgc2Vjb25kcycsXG4gICAgICAgIG0gOiAnYSBtaW51dGUnLFxuICAgICAgICBtbSA6ICclZCBtaW51dGVzJyxcbiAgICAgICAgaCA6ICdhbiBob3VyJyxcbiAgICAgICAgaGggOiAnJWQgaG91cnMnLFxuICAgICAgICBkIDogJ2EgZGF5JyxcbiAgICAgICAgZGQgOiAnJWQgZGF5cycsXG4gICAgICAgIE0gOiAnYSBtb250aCcsXG4gICAgICAgIE1NIDogJyVkIG1vbnRocycsXG4gICAgICAgIHkgOiAnYSB5ZWFyJyxcbiAgICAgICAgeXkgOiAnJWQgeWVhcnMnXG4gICAgfSxcbiAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn0oc3R8bmR8cmR8dGgpLyxcbiAgICBvcmRpbmFsIDogZnVuY3Rpb24gKG51bWJlcikge1xuICAgICAgICB2YXIgYiA9IG51bWJlciAlIDEwLFxuICAgICAgICAgICAgb3V0cHV0ID0gKH5+KG51bWJlciAlIDEwMCAvIDEwKSA9PT0gMSkgPyAndGgnIDpcbiAgICAgICAgICAgIChiID09PSAxKSA/ICdzdCcgOlxuICAgICAgICAgICAgKGIgPT09IDIpID8gJ25kJyA6XG4gICAgICAgICAgICAoYiA9PT0gMykgPyAncmQnIDogJ3RoJztcbiAgICAgICAgcmV0dXJuIG51bWJlciArIG91dHB1dDtcbiAgICB9LFxuICAgIHdlZWsgOiB7XG4gICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICBkb3kgOiA0ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgfVxufSk7XG5cbi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBFbmdsaXNoIChJcmVsYW5kKSBbZW4taWVdXG4vLyEgYXV0aG9yIDogQ2hyaXMgQ2FydGxpZGdlIDogaHR0cHM6Ly9naXRodWIuY29tL2NocmlzY2FydGxpZGdlXG5cbmhvb2tzLmRlZmluZUxvY2FsZSgnZW4taWUnLCB7XG4gICAgbW9udGhzIDogJ0phbnVhcnlfRmVicnVhcnlfTWFyY2hfQXByaWxfTWF5X0p1bmVfSnVseV9BdWd1c3RfU2VwdGVtYmVyX09jdG9iZXJfTm92ZW1iZXJfRGVjZW1iZXInLnNwbGl0KCdfJyksXG4gICAgbW9udGhzU2hvcnQgOiAnSmFuX0ZlYl9NYXJfQXByX01heV9KdW5fSnVsX0F1Z19TZXBfT2N0X05vdl9EZWMnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXMgOiAnU3VuZGF5X01vbmRheV9UdWVzZGF5X1dlZG5lc2RheV9UaHVyc2RheV9GcmlkYXlfU2F0dXJkYXknLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydCA6ICdTdW5fTW9uX1R1ZV9XZWRfVGh1X0ZyaV9TYXQnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW4gOiAnU3VfTW9fVHVfV2VfVGhfRnJfU2EnLnNwbGl0KCdfJyksXG4gICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgIExUIDogJ0hIOm1tJyxcbiAgICAgICAgTFRTIDogJ0hIOm1tOnNzJyxcbiAgICAgICAgTCA6ICdERC1NTS1ZWVlZJyxcbiAgICAgICAgTEwgOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICBMTEwgOiAnRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICBMTExMIDogJ2RkZGQgRCBNTU1NIFlZWVkgSEg6bW0nXG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheSA6ICdbVG9kYXkgYXRdIExUJyxcbiAgICAgICAgbmV4dERheSA6ICdbVG9tb3Jyb3cgYXRdIExUJyxcbiAgICAgICAgbmV4dFdlZWsgOiAnZGRkZCBbYXRdIExUJyxcbiAgICAgICAgbGFzdERheSA6ICdbWWVzdGVyZGF5IGF0XSBMVCcsXG4gICAgICAgIGxhc3RXZWVrIDogJ1tMYXN0XSBkZGRkIFthdF0gTFQnLFxuICAgICAgICBzYW1lRWxzZSA6ICdMJ1xuICAgIH0sXG4gICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICBmdXR1cmUgOiAnaW4gJXMnLFxuICAgICAgICBwYXN0IDogJyVzIGFnbycsXG4gICAgICAgIHMgOiAnYSBmZXcgc2Vjb25kcycsXG4gICAgICAgIHNzIDogJyVkIHNlY29uZHMnLFxuICAgICAgICBtIDogJ2EgbWludXRlJyxcbiAgICAgICAgbW0gOiAnJWQgbWludXRlcycsXG4gICAgICAgIGggOiAnYW4gaG91cicsXG4gICAgICAgIGhoIDogJyVkIGhvdXJzJyxcbiAgICAgICAgZCA6ICdhIGRheScsXG4gICAgICAgIGRkIDogJyVkIGRheXMnLFxuICAgICAgICBNIDogJ2EgbW9udGgnLFxuICAgICAgICBNTSA6ICclZCBtb250aHMnLFxuICAgICAgICB5IDogJ2EgeWVhcicsXG4gICAgICAgIHl5IDogJyVkIHllYXJzJ1xuICAgIH0sXG4gICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9KHN0fG5kfHJkfHRoKS8sXG4gICAgb3JkaW5hbCA6IGZ1bmN0aW9uIChudW1iZXIpIHtcbiAgICAgICAgdmFyIGIgPSBudW1iZXIgJSAxMCxcbiAgICAgICAgICAgIG91dHB1dCA9ICh+fihudW1iZXIgJSAxMDAgLyAxMCkgPT09IDEpID8gJ3RoJyA6XG4gICAgICAgICAgICAoYiA9PT0gMSkgPyAnc3QnIDpcbiAgICAgICAgICAgIChiID09PSAyKSA/ICduZCcgOlxuICAgICAgICAgICAgKGIgPT09IDMpID8gJ3JkJyA6ICd0aCc7XG4gICAgICAgIHJldHVybiBudW1iZXIgKyBvdXRwdXQ7XG4gICAgfSxcbiAgICB3ZWVrIDoge1xuICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogNCAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH1cbn0pO1xuXG4vLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogRW5nbGlzaCAoTmV3IFplYWxhbmQpIFtlbi1uel1cbi8vISBhdXRob3IgOiBMdWtlIE1jR3JlZ29yIDogaHR0cHM6Ly9naXRodWIuY29tL2x1a2VtY2dyZWdvclxuXG5ob29rcy5kZWZpbmVMb2NhbGUoJ2VuLW56Jywge1xuICAgIG1vbnRocyA6ICdKYW51YXJ5X0ZlYnJ1YXJ5X01hcmNoX0FwcmlsX01heV9KdW5lX0p1bHlfQXVndXN0X1NlcHRlbWJlcl9PY3RvYmVyX05vdmVtYmVyX0RlY2VtYmVyJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0IDogJ0phbl9GZWJfTWFyX0Fwcl9NYXlfSnVuX0p1bF9BdWdfU2VwX09jdF9Ob3ZfRGVjJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzIDogJ1N1bmRheV9Nb25kYXlfVHVlc2RheV9XZWRuZXNkYXlfVGh1cnNkYXlfRnJpZGF5X1NhdHVyZGF5Jy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzU2hvcnQgOiAnU3VuX01vbl9UdWVfV2VkX1RodV9GcmlfU2F0Jy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzTWluIDogJ1N1X01vX1R1X1dlX1RoX0ZyX1NhJy5zcGxpdCgnXycpLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdoOm1tIEEnLFxuICAgICAgICBMVFMgOiAnaDptbTpzcyBBJyxcbiAgICAgICAgTCA6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgTEwgOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICBMTEwgOiAnRCBNTU1NIFlZWVkgaDptbSBBJyxcbiAgICAgICAgTExMTCA6ICdkZGRkLCBEIE1NTU0gWVlZWSBoOm1tIEEnXG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheSA6ICdbVG9kYXkgYXRdIExUJyxcbiAgICAgICAgbmV4dERheSA6ICdbVG9tb3Jyb3cgYXRdIExUJyxcbiAgICAgICAgbmV4dFdlZWsgOiAnZGRkZCBbYXRdIExUJyxcbiAgICAgICAgbGFzdERheSA6ICdbWWVzdGVyZGF5IGF0XSBMVCcsXG4gICAgICAgIGxhc3RXZWVrIDogJ1tMYXN0XSBkZGRkIFthdF0gTFQnLFxuICAgICAgICBzYW1lRWxzZSA6ICdMJ1xuICAgIH0sXG4gICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICBmdXR1cmUgOiAnaW4gJXMnLFxuICAgICAgICBwYXN0IDogJyVzIGFnbycsXG4gICAgICAgIHMgOiAnYSBmZXcgc2Vjb25kcycsXG4gICAgICAgIHNzIDogJyVkIHNlY29uZHMnLFxuICAgICAgICBtIDogJ2EgbWludXRlJyxcbiAgICAgICAgbW0gOiAnJWQgbWludXRlcycsXG4gICAgICAgIGggOiAnYW4gaG91cicsXG4gICAgICAgIGhoIDogJyVkIGhvdXJzJyxcbiAgICAgICAgZCA6ICdhIGRheScsXG4gICAgICAgIGRkIDogJyVkIGRheXMnLFxuICAgICAgICBNIDogJ2EgbW9udGgnLFxuICAgICAgICBNTSA6ICclZCBtb250aHMnLFxuICAgICAgICB5IDogJ2EgeWVhcicsXG4gICAgICAgIHl5IDogJyVkIHllYXJzJ1xuICAgIH0sXG4gICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9KHN0fG5kfHJkfHRoKS8sXG4gICAgb3JkaW5hbCA6IGZ1bmN0aW9uIChudW1iZXIpIHtcbiAgICAgICAgdmFyIGIgPSBudW1iZXIgJSAxMCxcbiAgICAgICAgICAgIG91dHB1dCA9ICh+fihudW1iZXIgJSAxMDAgLyAxMCkgPT09IDEpID8gJ3RoJyA6XG4gICAgICAgICAgICAoYiA9PT0gMSkgPyAnc3QnIDpcbiAgICAgICAgICAgIChiID09PSAyKSA/ICduZCcgOlxuICAgICAgICAgICAgKGIgPT09IDMpID8gJ3JkJyA6ICd0aCc7XG4gICAgICAgIHJldHVybiBudW1iZXIgKyBvdXRwdXQ7XG4gICAgfSxcbiAgICB3ZWVrIDoge1xuICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogNCAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH1cbn0pO1xuXG4vLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogRXNwZXJhbnRvIFtlb11cbi8vISBhdXRob3IgOiBDb2xpbiBEZWFuIDogaHR0cHM6Ly9naXRodWIuY29tL2NvbGluZGVhblxuLy8hIGF1dGhvciA6IE1pYSBOb3JkZW50b2Z0IEltcGVyYXRvcmkgOiBodHRwczovL2dpdGh1Yi5jb20vbWllc3Rhc21pYVxuLy8hIGNvbW1lbnQgOiBtaWVzdGFzbWlhIGNvcnJlY3RlZCB0aGUgdHJhbnNsYXRpb24gYnkgY29saW5kZWFuXG5cbmhvb2tzLmRlZmluZUxvY2FsZSgnZW8nLCB7XG4gICAgbW9udGhzIDogJ2phbnVhcm9fZmVicnVhcm9fbWFydG9fYXByaWxvX21ham9fanVuaW9fanVsaW9fYcWtZ3VzdG9fc2VwdGVtYnJvX29rdG9icm9fbm92ZW1icm9fZGVjZW1icm8nLnNwbGl0KCdfJyksXG4gICAgbW9udGhzU2hvcnQgOiAnamFuX2ZlYl9tYXJfYXByX21hal9qdW5fanVsX2HFrWdfc2VwX29rdF9ub3ZfZGVjJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzIDogJ2RpbWFuxIlvX2x1bmRvX21hcmRvX21lcmtyZWRvX8S1YcWtZG9fdmVuZHJlZG9fc2FiYXRvJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzU2hvcnQgOiAnZGltX2x1bl9tYXJkX21lcmtfxLVhxa1fdmVuX3NhYicuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbiA6ICdkaV9sdV9tYV9tZV/EtWFfdmVfc2EnLnNwbGl0KCdfJyksXG4gICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgIExUIDogJ0hIOm1tJyxcbiAgICAgICAgTFRTIDogJ0hIOm1tOnNzJyxcbiAgICAgICAgTCA6ICdZWVlZLU1NLUREJyxcbiAgICAgICAgTEwgOiAnRFstYSBkZV0gTU1NTSwgWVlZWScsXG4gICAgICAgIExMTCA6ICdEWy1hIGRlXSBNTU1NLCBZWVlZIEhIOm1tJyxcbiAgICAgICAgTExMTCA6ICdkZGRkLCBbbGFdIERbLWEgZGVdIE1NTU0sIFlZWVkgSEg6bW0nXG4gICAgfSxcbiAgICBtZXJpZGllbVBhcnNlOiAvW2FwXVxcLnRcXC5tL2ksXG4gICAgaXNQTTogZnVuY3Rpb24gKGlucHV0KSB7XG4gICAgICAgIHJldHVybiBpbnB1dC5jaGFyQXQoMCkudG9Mb3dlckNhc2UoKSA9PT0gJ3AnO1xuICAgIH0sXG4gICAgbWVyaWRpZW0gOiBmdW5jdGlvbiAoaG91cnMsIG1pbnV0ZXMsIGlzTG93ZXIpIHtcbiAgICAgICAgaWYgKGhvdXJzID4gMTEpIHtcbiAgICAgICAgICAgIHJldHVybiBpc0xvd2VyID8gJ3AudC5tLicgOiAnUC5ULk0uJztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBpc0xvd2VyID8gJ2EudC5tLicgOiAnQS5ULk0uJztcbiAgICAgICAgfVxuICAgIH0sXG4gICAgY2FsZW5kYXIgOiB7XG4gICAgICAgIHNhbWVEYXkgOiAnW0hvZGlhxa0gamVdIExUJyxcbiAgICAgICAgbmV4dERheSA6ICdbTW9yZ2HFrSBqZV0gTFQnLFxuICAgICAgICBuZXh0V2VlayA6ICdkZGRkIFtqZV0gTFQnLFxuICAgICAgICBsYXN0RGF5IDogJ1tIaWVyYcWtIGplXSBMVCcsXG4gICAgICAgIGxhc3RXZWVrIDogJ1twYXNpbnRhXSBkZGRkIFtqZV0gTFQnLFxuICAgICAgICBzYW1lRWxzZSA6ICdMJ1xuICAgIH0sXG4gICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICBmdXR1cmUgOiAncG9zdCAlcycsXG4gICAgICAgIHBhc3QgOiAnYW50YcWtICVzJyxcbiAgICAgICAgcyA6ICdzZWt1bmRvaicsXG4gICAgICAgIHNzIDogJyVkIHNla3VuZG9qJyxcbiAgICAgICAgbSA6ICdtaW51dG8nLFxuICAgICAgICBtbSA6ICclZCBtaW51dG9qJyxcbiAgICAgICAgaCA6ICdob3JvJyxcbiAgICAgICAgaGggOiAnJWQgaG9yb2onLFxuICAgICAgICBkIDogJ3RhZ28nLC8vbmUgJ2RpdXJubycsIMSJYXIgZXN0YXMgdXppdGEgcG9yIHByb2tzaW11bW9cbiAgICAgICAgZGQgOiAnJWQgdGFnb2onLFxuICAgICAgICBNIDogJ21vbmF0bycsXG4gICAgICAgIE1NIDogJyVkIG1vbmF0b2onLFxuICAgICAgICB5IDogJ2phcm8nLFxuICAgICAgICB5eSA6ICclZCBqYXJvaidcbiAgICB9LFxuICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfWEvLFxuICAgIG9yZGluYWwgOiAnJWRhJyxcbiAgICB3ZWVrIDoge1xuICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogNyAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gMXN0IGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH1cbn0pO1xuXG4vLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogU3BhbmlzaCAoRG9taW5pY2FuIFJlcHVibGljKSBbZXMtZG9dXG5cbnZhciBtb250aHNTaG9ydERvdCA9ICdlbmUuX2ZlYi5fbWFyLl9hYnIuX21heS5fanVuLl9qdWwuX2Fnby5fc2VwLl9vY3QuX25vdi5fZGljLicuc3BsaXQoJ18nKTtcbnZhciBtb250aHNTaG9ydCQxID0gJ2VuZV9mZWJfbWFyX2Ficl9tYXlfanVuX2p1bF9hZ29fc2VwX29jdF9ub3ZfZGljJy5zcGxpdCgnXycpO1xuXG52YXIgbW9udGhzUGFyc2UgPSBbL15lbmUvaSwgL15mZWIvaSwgL15tYXIvaSwgL15hYnIvaSwgL15tYXkvaSwgL15qdW4vaSwgL15qdWwvaSwgL15hZ28vaSwgL15zZXAvaSwgL15vY3QvaSwgL15ub3YvaSwgL15kaWMvaV07XG52YXIgbW9udGhzUmVnZXgkMSA9IC9eKGVuZXJvfGZlYnJlcm98bWFyem98YWJyaWx8bWF5b3xqdW5pb3xqdWxpb3xhZ29zdG98c2VwdGllbWJyZXxvY3R1YnJlfG5vdmllbWJyZXxkaWNpZW1icmV8ZW5lXFwuP3xmZWJcXC4/fG1hclxcLj98YWJyXFwuP3xtYXlcXC4/fGp1blxcLj98anVsXFwuP3xhZ29cXC4/fHNlcFxcLj98b2N0XFwuP3xub3ZcXC4/fGRpY1xcLj8pL2k7XG5cbmhvb2tzLmRlZmluZUxvY2FsZSgnZXMtZG8nLCB7XG4gICAgbW9udGhzIDogJ2VuZXJvX2ZlYnJlcm9fbWFyem9fYWJyaWxfbWF5b19qdW5pb19qdWxpb19hZ29zdG9fc2VwdGllbWJyZV9vY3R1YnJlX25vdmllbWJyZV9kaWNpZW1icmUnLnNwbGl0KCdfJyksXG4gICAgbW9udGhzU2hvcnQgOiBmdW5jdGlvbiAobSwgZm9ybWF0KSB7XG4gICAgICAgIGlmICghbSkge1xuICAgICAgICAgICAgcmV0dXJuIG1vbnRoc1Nob3J0RG90O1xuICAgICAgICB9IGVsc2UgaWYgKC8tTU1NLS8udGVzdChmb3JtYXQpKSB7XG4gICAgICAgICAgICByZXR1cm4gbW9udGhzU2hvcnQkMVttLm1vbnRoKCldO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIG1vbnRoc1Nob3J0RG90W20ubW9udGgoKV07XG4gICAgICAgIH1cbiAgICB9LFxuICAgIG1vbnRoc1JlZ2V4OiBtb250aHNSZWdleCQxLFxuICAgIG1vbnRoc1Nob3J0UmVnZXg6IG1vbnRoc1JlZ2V4JDEsXG4gICAgbW9udGhzU3RyaWN0UmVnZXg6IC9eKGVuZXJvfGZlYnJlcm98bWFyem98YWJyaWx8bWF5b3xqdW5pb3xqdWxpb3xhZ29zdG98c2VwdGllbWJyZXxvY3R1YnJlfG5vdmllbWJyZXxkaWNpZW1icmUpL2ksXG4gICAgbW9udGhzU2hvcnRTdHJpY3RSZWdleDogL14oZW5lXFwuP3xmZWJcXC4/fG1hclxcLj98YWJyXFwuP3xtYXlcXC4/fGp1blxcLj98anVsXFwuP3xhZ29cXC4/fHNlcFxcLj98b2N0XFwuP3xub3ZcXC4/fGRpY1xcLj8pL2ksXG4gICAgbW9udGhzUGFyc2U6IG1vbnRoc1BhcnNlLFxuICAgIGxvbmdNb250aHNQYXJzZTogbW9udGhzUGFyc2UsXG4gICAgc2hvcnRNb250aHNQYXJzZTogbW9udGhzUGFyc2UsXG4gICAgd2Vla2RheXMgOiAnZG9taW5nb19sdW5lc19tYXJ0ZXNfbWnDqXJjb2xlc19qdWV2ZXNfdmllcm5lc19zw6FiYWRvJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzU2hvcnQgOiAnZG9tLl9sdW4uX21hci5fbWnDqS5fanVlLl92aWUuX3PDoWIuJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzTWluIDogJ2RvX2x1X21hX21pX2p1X3ZpX3PDoScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdoOm1tIEEnLFxuICAgICAgICBMVFMgOiAnaDptbTpzcyBBJyxcbiAgICAgICAgTCA6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgTEwgOiAnRCBbZGVdIE1NTU0gW2RlXSBZWVlZJyxcbiAgICAgICAgTExMIDogJ0QgW2RlXSBNTU1NIFtkZV0gWVlZWSBoOm1tIEEnLFxuICAgICAgICBMTExMIDogJ2RkZGQsIEQgW2RlXSBNTU1NIFtkZV0gWVlZWSBoOm1tIEEnXG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheSA6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiAnW2hveSBhIGxhJyArICgodGhpcy5ob3VycygpICE9PSAxKSA/ICdzJyA6ICcnKSArICddIExUJztcbiAgICAgICAgfSxcbiAgICAgICAgbmV4dERheSA6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiAnW21hw7FhbmEgYSBsYScgKyAoKHRoaXMuaG91cnMoKSAhPT0gMSkgPyAncycgOiAnJykgKyAnXSBMVCc7XG4gICAgICAgIH0sXG4gICAgICAgIG5leHRXZWVrIDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuICdkZGRkIFthIGxhJyArICgodGhpcy5ob3VycygpICE9PSAxKSA/ICdzJyA6ICcnKSArICddIExUJztcbiAgICAgICAgfSxcbiAgICAgICAgbGFzdERheSA6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiAnW2F5ZXIgYSBsYScgKyAoKHRoaXMuaG91cnMoKSAhPT0gMSkgPyAncycgOiAnJykgKyAnXSBMVCc7XG4gICAgICAgIH0sXG4gICAgICAgIGxhc3RXZWVrIDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuICdbZWxdIGRkZGQgW3Bhc2FkbyBhIGxhJyArICgodGhpcy5ob3VycygpICE9PSAxKSA/ICdzJyA6ICcnKSArICddIExUJztcbiAgICAgICAgfSxcbiAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJ2VuICVzJyxcbiAgICAgICAgcGFzdCA6ICdoYWNlICVzJyxcbiAgICAgICAgcyA6ICd1bm9zIHNlZ3VuZG9zJyxcbiAgICAgICAgc3MgOiAnJWQgc2VndW5kb3MnLFxuICAgICAgICBtIDogJ3VuIG1pbnV0bycsXG4gICAgICAgIG1tIDogJyVkIG1pbnV0b3MnLFxuICAgICAgICBoIDogJ3VuYSBob3JhJyxcbiAgICAgICAgaGggOiAnJWQgaG9yYXMnLFxuICAgICAgICBkIDogJ3VuIGTDrWEnLFxuICAgICAgICBkZCA6ICclZCBkw61hcycsXG4gICAgICAgIE0gOiAndW4gbWVzJyxcbiAgICAgICAgTU0gOiAnJWQgbWVzZXMnLFxuICAgICAgICB5IDogJ3VuIGHDsW8nLFxuICAgICAgICB5eSA6ICclZCBhw7FvcydcbiAgICB9LFxuICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2UgOiAvXFxkezEsMn3Cui8sXG4gICAgb3JkaW5hbCA6ICclZMK6JyxcbiAgICB3ZWVrIDoge1xuICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogNCAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH1cbn0pO1xuXG4vLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogU3BhbmlzaCAoVW5pdGVkIFN0YXRlcykgW2VzLXVzXVxuLy8hIGF1dGhvciA6IGJ1c3R0YSA6IGh0dHBzOi8vZ2l0aHViLmNvbS9idXN0dGFcblxudmFyIG1vbnRoc1Nob3J0RG90JDEgPSAnZW5lLl9mZWIuX21hci5fYWJyLl9tYXkuX2p1bi5fanVsLl9hZ28uX3NlcC5fb2N0Ll9ub3YuX2RpYy4nLnNwbGl0KCdfJyk7XG52YXIgbW9udGhzU2hvcnQkMiA9ICdlbmVfZmViX21hcl9hYnJfbWF5X2p1bl9qdWxfYWdvX3NlcF9vY3Rfbm92X2RpYycuc3BsaXQoJ18nKTtcblxuaG9va3MuZGVmaW5lTG9jYWxlKCdlcy11cycsIHtcbiAgICBtb250aHMgOiAnZW5lcm9fZmVicmVyb19tYXJ6b19hYnJpbF9tYXlvX2p1bmlvX2p1bGlvX2Fnb3N0b19zZXB0aWVtYnJlX29jdHVicmVfbm92aWVtYnJlX2RpY2llbWJyZScuc3BsaXQoJ18nKSxcbiAgICBtb250aHNTaG9ydCA6IGZ1bmN0aW9uIChtLCBmb3JtYXQpIHtcbiAgICAgICAgaWYgKCFtKSB7XG4gICAgICAgICAgICByZXR1cm4gbW9udGhzU2hvcnREb3QkMTtcbiAgICAgICAgfSBlbHNlIGlmICgvLU1NTS0vLnRlc3QoZm9ybWF0KSkge1xuICAgICAgICAgICAgcmV0dXJuIG1vbnRoc1Nob3J0JDJbbS5tb250aCgpXTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBtb250aHNTaG9ydERvdCQxW20ubW9udGgoKV07XG4gICAgICAgIH1cbiAgICB9LFxuICAgIG1vbnRoc1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgIHdlZWtkYXlzIDogJ2RvbWluZ29fbHVuZXNfbWFydGVzX21pw6lyY29sZXNfanVldmVzX3ZpZXJuZXNfc8OhYmFkbycuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0IDogJ2RvbS5fbHVuLl9tYXIuX21pw6kuX2p1ZS5fdmllLl9zw6FiLicuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbiA6ICdkb19sdV9tYV9taV9qdV92aV9zw6EnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNQYXJzZUV4YWN0IDogdHJ1ZSxcbiAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgTFQgOiAnaDptbSBBJyxcbiAgICAgICAgTFRTIDogJ2g6bW06c3MgQScsXG4gICAgICAgIEwgOiAnTU0vREQvWVlZWScsXG4gICAgICAgIExMIDogJ01NTU0gW2RlXSBEIFtkZV0gWVlZWScsXG4gICAgICAgIExMTCA6ICdNTU1NIFtkZV0gRCBbZGVdIFlZWVkgaDptbSBBJyxcbiAgICAgICAgTExMTCA6ICdkZGRkLCBNTU1NIFtkZV0gRCBbZGVdIFlZWVkgaDptbSBBJ1xuICAgIH0sXG4gICAgY2FsZW5kYXIgOiB7XG4gICAgICAgIHNhbWVEYXkgOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gJ1tob3kgYSBsYScgKyAoKHRoaXMuaG91cnMoKSAhPT0gMSkgPyAncycgOiAnJykgKyAnXSBMVCc7XG4gICAgICAgIH0sXG4gICAgICAgIG5leHREYXkgOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gJ1ttYcOxYW5hIGEgbGEnICsgKCh0aGlzLmhvdXJzKCkgIT09IDEpID8gJ3MnIDogJycpICsgJ10gTFQnO1xuICAgICAgICB9LFxuICAgICAgICBuZXh0V2VlayA6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiAnZGRkZCBbYSBsYScgKyAoKHRoaXMuaG91cnMoKSAhPT0gMSkgPyAncycgOiAnJykgKyAnXSBMVCc7XG4gICAgICAgIH0sXG4gICAgICAgIGxhc3REYXkgOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gJ1theWVyIGEgbGEnICsgKCh0aGlzLmhvdXJzKCkgIT09IDEpID8gJ3MnIDogJycpICsgJ10gTFQnO1xuICAgICAgICB9LFxuICAgICAgICBsYXN0V2VlayA6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiAnW2VsXSBkZGRkIFtwYXNhZG8gYSBsYScgKyAoKHRoaXMuaG91cnMoKSAhPT0gMSkgPyAncycgOiAnJykgKyAnXSBMVCc7XG4gICAgICAgIH0sXG4gICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6ICdlbiAlcycsXG4gICAgICAgIHBhc3QgOiAnaGFjZSAlcycsXG4gICAgICAgIHMgOiAndW5vcyBzZWd1bmRvcycsXG4gICAgICAgIHNzIDogJyVkIHNlZ3VuZG9zJyxcbiAgICAgICAgbSA6ICd1biBtaW51dG8nLFxuICAgICAgICBtbSA6ICclZCBtaW51dG9zJyxcbiAgICAgICAgaCA6ICd1bmEgaG9yYScsXG4gICAgICAgIGhoIDogJyVkIGhvcmFzJyxcbiAgICAgICAgZCA6ICd1biBkw61hJyxcbiAgICAgICAgZGQgOiAnJWQgZMOtYXMnLFxuICAgICAgICBNIDogJ3VuIG1lcycsXG4gICAgICAgIE1NIDogJyVkIG1lc2VzJyxcbiAgICAgICAgeSA6ICd1biBhw7FvJyxcbiAgICAgICAgeXkgOiAnJWQgYcOxb3MnXG4gICAgfSxcbiAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlIDogL1xcZHsxLDJ9wrovLFxuICAgIG9yZGluYWwgOiAnJWTCuicsXG4gICAgd2VlayA6IHtcbiAgICAgICAgZG93IDogMCwgLy8gU3VuZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgIGRveSA6IDYgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDFzdCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICB9XG59KTtcblxuLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSA6IFNwYW5pc2ggW2VzXVxuLy8hIGF1dGhvciA6IEp1bGlvIE5hcHVyw60gOiBodHRwczovL2dpdGh1Yi5jb20vanVsaW9uY1xuXG52YXIgbW9udGhzU2hvcnREb3QkMiA9ICdlbmUuX2ZlYi5fbWFyLl9hYnIuX21heS5fanVuLl9qdWwuX2Fnby5fc2VwLl9vY3QuX25vdi5fZGljLicuc3BsaXQoJ18nKTtcbnZhciBtb250aHNTaG9ydCQzID0gJ2VuZV9mZWJfbWFyX2Ficl9tYXlfanVuX2p1bF9hZ29fc2VwX29jdF9ub3ZfZGljJy5zcGxpdCgnXycpO1xuXG52YXIgbW9udGhzUGFyc2UkMSA9IFsvXmVuZS9pLCAvXmZlYi9pLCAvXm1hci9pLCAvXmFici9pLCAvXm1heS9pLCAvXmp1bi9pLCAvXmp1bC9pLCAvXmFnby9pLCAvXnNlcC9pLCAvXm9jdC9pLCAvXm5vdi9pLCAvXmRpYy9pXTtcbnZhciBtb250aHNSZWdleCQyID0gL14oZW5lcm98ZmVicmVyb3xtYXJ6b3xhYnJpbHxtYXlvfGp1bmlvfGp1bGlvfGFnb3N0b3xzZXB0aWVtYnJlfG9jdHVicmV8bm92aWVtYnJlfGRpY2llbWJyZXxlbmVcXC4/fGZlYlxcLj98bWFyXFwuP3xhYnJcXC4/fG1heVxcLj98anVuXFwuP3xqdWxcXC4/fGFnb1xcLj98c2VwXFwuP3xvY3RcXC4/fG5vdlxcLj98ZGljXFwuPykvaTtcblxuaG9va3MuZGVmaW5lTG9jYWxlKCdlcycsIHtcbiAgICBtb250aHMgOiAnZW5lcm9fZmVicmVyb19tYXJ6b19hYnJpbF9tYXlvX2p1bmlvX2p1bGlvX2Fnb3N0b19zZXB0aWVtYnJlX29jdHVicmVfbm92aWVtYnJlX2RpY2llbWJyZScuc3BsaXQoJ18nKSxcbiAgICBtb250aHNTaG9ydCA6IGZ1bmN0aW9uIChtLCBmb3JtYXQpIHtcbiAgICAgICAgaWYgKCFtKSB7XG4gICAgICAgICAgICByZXR1cm4gbW9udGhzU2hvcnREb3QkMjtcbiAgICAgICAgfSBlbHNlIGlmICgvLU1NTS0vLnRlc3QoZm9ybWF0KSkge1xuICAgICAgICAgICAgcmV0dXJuIG1vbnRoc1Nob3J0JDNbbS5tb250aCgpXTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBtb250aHNTaG9ydERvdCQyW20ubW9udGgoKV07XG4gICAgICAgIH1cbiAgICB9LFxuICAgIG1vbnRoc1JlZ2V4IDogbW9udGhzUmVnZXgkMixcbiAgICBtb250aHNTaG9ydFJlZ2V4IDogbW9udGhzUmVnZXgkMixcbiAgICBtb250aHNTdHJpY3RSZWdleCA6IC9eKGVuZXJvfGZlYnJlcm98bWFyem98YWJyaWx8bWF5b3xqdW5pb3xqdWxpb3xhZ29zdG98c2VwdGllbWJyZXxvY3R1YnJlfG5vdmllbWJyZXxkaWNpZW1icmUpL2ksXG4gICAgbW9udGhzU2hvcnRTdHJpY3RSZWdleCA6IC9eKGVuZVxcLj98ZmViXFwuP3xtYXJcXC4/fGFiclxcLj98bWF5XFwuP3xqdW5cXC4/fGp1bFxcLj98YWdvXFwuP3xzZXBcXC4/fG9jdFxcLj98bm92XFwuP3xkaWNcXC4/KS9pLFxuICAgIG1vbnRoc1BhcnNlIDogbW9udGhzUGFyc2UkMSxcbiAgICBsb25nTW9udGhzUGFyc2UgOiBtb250aHNQYXJzZSQxLFxuICAgIHNob3J0TW9udGhzUGFyc2UgOiBtb250aHNQYXJzZSQxLFxuICAgIHdlZWtkYXlzIDogJ2RvbWluZ29fbHVuZXNfbWFydGVzX21pw6lyY29sZXNfanVldmVzX3ZpZXJuZXNfc8OhYmFkbycuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0IDogJ2RvbS5fbHVuLl9tYXIuX21pw6kuX2p1ZS5fdmllLl9zw6FiLicuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbiA6ICdkb19sdV9tYV9taV9qdV92aV9zw6EnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNQYXJzZUV4YWN0IDogdHJ1ZSxcbiAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgTFQgOiAnSDptbScsXG4gICAgICAgIExUUyA6ICdIOm1tOnNzJyxcbiAgICAgICAgTCA6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgTEwgOiAnRCBbZGVdIE1NTU0gW2RlXSBZWVlZJyxcbiAgICAgICAgTExMIDogJ0QgW2RlXSBNTU1NIFtkZV0gWVlZWSBIOm1tJyxcbiAgICAgICAgTExMTCA6ICdkZGRkLCBEIFtkZV0gTU1NTSBbZGVdIFlZWVkgSDptbSdcbiAgICB9LFxuICAgIGNhbGVuZGFyIDoge1xuICAgICAgICBzYW1lRGF5IDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuICdbaG95IGEgbGEnICsgKCh0aGlzLmhvdXJzKCkgIT09IDEpID8gJ3MnIDogJycpICsgJ10gTFQnO1xuICAgICAgICB9LFxuICAgICAgICBuZXh0RGF5IDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuICdbbWHDsWFuYSBhIGxhJyArICgodGhpcy5ob3VycygpICE9PSAxKSA/ICdzJyA6ICcnKSArICddIExUJztcbiAgICAgICAgfSxcbiAgICAgICAgbmV4dFdlZWsgOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gJ2RkZGQgW2EgbGEnICsgKCh0aGlzLmhvdXJzKCkgIT09IDEpID8gJ3MnIDogJycpICsgJ10gTFQnO1xuICAgICAgICB9LFxuICAgICAgICBsYXN0RGF5IDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuICdbYXllciBhIGxhJyArICgodGhpcy5ob3VycygpICE9PSAxKSA/ICdzJyA6ICcnKSArICddIExUJztcbiAgICAgICAgfSxcbiAgICAgICAgbGFzdFdlZWsgOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gJ1tlbF0gZGRkZCBbcGFzYWRvIGEgbGEnICsgKCh0aGlzLmhvdXJzKCkgIT09IDEpID8gJ3MnIDogJycpICsgJ10gTFQnO1xuICAgICAgICB9LFxuICAgICAgICBzYW1lRWxzZSA6ICdMJ1xuICAgIH0sXG4gICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICBmdXR1cmUgOiAnZW4gJXMnLFxuICAgICAgICBwYXN0IDogJ2hhY2UgJXMnLFxuICAgICAgICBzIDogJ3Vub3Mgc2VndW5kb3MnLFxuICAgICAgICBzcyA6ICclZCBzZWd1bmRvcycsXG4gICAgICAgIG0gOiAndW4gbWludXRvJyxcbiAgICAgICAgbW0gOiAnJWQgbWludXRvcycsXG4gICAgICAgIGggOiAndW5hIGhvcmEnLFxuICAgICAgICBoaCA6ICclZCBob3JhcycsXG4gICAgICAgIGQgOiAndW4gZMOtYScsXG4gICAgICAgIGRkIDogJyVkIGTDrWFzJyxcbiAgICAgICAgTSA6ICd1biBtZXMnLFxuICAgICAgICBNTSA6ICclZCBtZXNlcycsXG4gICAgICAgIHkgOiAndW4gYcOxbycsXG4gICAgICAgIHl5IDogJyVkIGHDsW9zJ1xuICAgIH0sXG4gICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZSA6IC9cXGR7MSwyfcK6LyxcbiAgICBvcmRpbmFsIDogJyVkwronLFxuICAgIHdlZWsgOiB7XG4gICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICBkb3kgOiA0ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgfVxufSk7XG5cbi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBFc3RvbmlhbiBbZXRdXG4vLyEgYXV0aG9yIDogSGVucnkgS2VobG1hbm4gOiBodHRwczovL2dpdGh1Yi5jb20vbWFkaGVucnlcbi8vISBpbXByb3ZlbWVudHMgOiBJbGxpbWFyIFRhbWJlayA6IGh0dHBzOi8vZ2l0aHViLmNvbS9yYWd1bGthXG5cbmZ1bmN0aW9uIHByb2Nlc3NSZWxhdGl2ZVRpbWUkMyhudW1iZXIsIHdpdGhvdXRTdWZmaXgsIGtleSwgaXNGdXR1cmUpIHtcbiAgICB2YXIgZm9ybWF0ID0ge1xuICAgICAgICAncycgOiBbJ23DtW5lIHNla3VuZGknLCAnbcO1bmkgc2VrdW5kJywgJ3BhYXIgc2VrdW5kaXQnXSxcbiAgICAgICAgJ3NzJzogW251bWJlciArICdzZWt1bmRpJywgbnVtYmVyICsgJ3Nla3VuZGl0J10sXG4gICAgICAgICdtJyA6IFsnw7xoZSBtaW51dGknLCAnw7xrcyBtaW51dCddLFxuICAgICAgICAnbW0nOiBbbnVtYmVyICsgJyBtaW51dGknLCBudW1iZXIgKyAnIG1pbnV0aXQnXSxcbiAgICAgICAgJ2gnIDogWyfDvGhlIHR1bm5pJywgJ3R1bmQgYWVnYScsICfDvGtzIHR1bmQnXSxcbiAgICAgICAgJ2hoJzogW251bWJlciArICcgdHVubmknLCBudW1iZXIgKyAnIHR1bmRpJ10sXG4gICAgICAgICdkJyA6IFsnw7xoZSBww6RldmEnLCAnw7xrcyBww6RldiddLFxuICAgICAgICAnTScgOiBbJ2t1dSBhamEnLCAna3V1IGFlZ2EnLCAnw7xrcyBrdXUnXSxcbiAgICAgICAgJ01NJzogW251bWJlciArICcga3V1JywgbnVtYmVyICsgJyBrdXVkJ10sXG4gICAgICAgICd5JyA6IFsnw7xoZSBhYXN0YScsICdhYXN0YScsICfDvGtzIGFhc3RhJ10sXG4gICAgICAgICd5eSc6IFtudW1iZXIgKyAnIGFhc3RhJywgbnVtYmVyICsgJyBhYXN0YXQnXVxuICAgIH07XG4gICAgaWYgKHdpdGhvdXRTdWZmaXgpIHtcbiAgICAgICAgcmV0dXJuIGZvcm1hdFtrZXldWzJdID8gZm9ybWF0W2tleV1bMl0gOiBmb3JtYXRba2V5XVsxXTtcbiAgICB9XG4gICAgcmV0dXJuIGlzRnV0dXJlID8gZm9ybWF0W2tleV1bMF0gOiBmb3JtYXRba2V5XVsxXTtcbn1cblxuaG9va3MuZGVmaW5lTG9jYWxlKCdldCcsIHtcbiAgICBtb250aHMgICAgICAgIDogJ2phYW51YXJfdmVlYnJ1YXJfbcOkcnRzX2FwcmlsbF9tYWlfanV1bmlfanV1bGlfYXVndXN0X3NlcHRlbWJlcl9va3Rvb2Jlcl9ub3ZlbWJlcl9kZXRzZW1iZXInLnNwbGl0KCdfJyksXG4gICAgbW9udGhzU2hvcnQgICA6ICdqYWFuX3ZlZWJyX23DpHJ0c19hcHJfbWFpX2p1dW5pX2p1dWxpX2F1Z19zZXB0X29rdF9ub3ZfZGV0cycuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5cyAgICAgIDogJ3DDvGhhcMOkZXZfZXNtYXNww6Rldl90ZWlzaXDDpGV2X2tvbG1hcMOkZXZfbmVsamFww6Rldl9yZWVkZV9sYXVww6Rldicuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0IDogJ1BfRV9UX0tfTl9SX0wnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW4gICA6ICdQX0VfVF9LX05fUl9MJy5zcGxpdCgnXycpLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCAgIDogJ0g6bW0nLFxuICAgICAgICBMVFMgOiAnSDptbTpzcycsXG4gICAgICAgIEwgICAgOiAnREQuTU0uWVlZWScsXG4gICAgICAgIExMICAgOiAnRC4gTU1NTSBZWVlZJyxcbiAgICAgICAgTExMICA6ICdELiBNTU1NIFlZWVkgSDptbScsXG4gICAgICAgIExMTEwgOiAnZGRkZCwgRC4gTU1NTSBZWVlZIEg6bW0nXG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheSAgOiAnW1TDpG5hLF0gTFQnLFxuICAgICAgICBuZXh0RGF5ICA6ICdbSG9tbWUsXSBMVCcsXG4gICAgICAgIG5leHRXZWVrIDogJ1tKw6RyZ21pbmVdIGRkZGQgTFQnLFxuICAgICAgICBsYXN0RGF5ICA6ICdbRWlsZSxdIExUJyxcbiAgICAgICAgbGFzdFdlZWsgOiAnW0VlbG1pbmVdIGRkZGQgTFQnLFxuICAgICAgICBzYW1lRWxzZSA6ICdMJ1xuICAgIH0sXG4gICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICBmdXR1cmUgOiAnJXMgcMOkcmFzdCcsXG4gICAgICAgIHBhc3QgICA6ICclcyB0YWdhc2knLFxuICAgICAgICBzICAgICAgOiBwcm9jZXNzUmVsYXRpdmVUaW1lJDMsXG4gICAgICAgIHNzICAgICA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUkMyxcbiAgICAgICAgbSAgICAgIDogcHJvY2Vzc1JlbGF0aXZlVGltZSQzLFxuICAgICAgICBtbSAgICAgOiBwcm9jZXNzUmVsYXRpdmVUaW1lJDMsXG4gICAgICAgIGggICAgICA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUkMyxcbiAgICAgICAgaGggICAgIDogcHJvY2Vzc1JlbGF0aXZlVGltZSQzLFxuICAgICAgICBkICAgICAgOiBwcm9jZXNzUmVsYXRpdmVUaW1lJDMsXG4gICAgICAgIGRkICAgICA6ICclZCBww6RldmEnLFxuICAgICAgICBNICAgICAgOiBwcm9jZXNzUmVsYXRpdmVUaW1lJDMsXG4gICAgICAgIE1NICAgICA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUkMyxcbiAgICAgICAgeSAgICAgIDogcHJvY2Vzc1JlbGF0aXZlVGltZSQzLFxuICAgICAgICB5eSAgICAgOiBwcm9jZXNzUmVsYXRpdmVUaW1lJDNcbiAgICB9LFxuICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfVxcLi8sXG4gICAgb3JkaW5hbCA6ICclZC4nLFxuICAgIHdlZWsgOiB7XG4gICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICBkb3kgOiA0ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgfVxufSk7XG5cbi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBCYXNxdWUgW2V1XVxuLy8hIGF1dGhvciA6IEVuZWtvIElsbGFycmFtZW5kaSA6IGh0dHBzOi8vZ2l0aHViLmNvbS9laWxsYXJyYVxuXG5ob29rcy5kZWZpbmVMb2NhbGUoJ2V1Jywge1xuICAgIG1vbnRocyA6ICd1cnRhcnJpbGFfb3RzYWlsYV9tYXJ0eG9hX2FwaXJpbGFfbWFpYXR6YV9la2FpbmFfdXp0YWlsYV9hYnV6dHVhX2lyYWlsYV91cnJpYV9hemFyb2FfYWJlbmR1YScuc3BsaXQoJ18nKSxcbiAgICBtb250aHNTaG9ydCA6ICd1cnQuX290cy5fbWFyLl9hcGkuX21haS5fZWthLl91enQuX2FidS5faXJhLl91cnIuX2F6YS5fYWJlLicuc3BsaXQoJ18nKSxcbiAgICBtb250aHNQYXJzZUV4YWN0IDogdHJ1ZSxcbiAgICB3ZWVrZGF5cyA6ICdpZ2FuZGVhX2FzdGVsZWhlbmFfYXN0ZWFydGVhX2FzdGVhemtlbmFfb3N0ZWd1bmFfb3N0aXJhbGFfbGFydW5iYXRhJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzU2hvcnQgOiAnaWcuX2FsLl9hci5fYXouX29nLl9vbC5fbHIuJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzTWluIDogJ2lnX2FsX2FyX2F6X29nX29sX2xyJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzUGFyc2VFeGFjdCA6IHRydWUsXG4gICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgIExUIDogJ0hIOm1tJyxcbiAgICAgICAgTFRTIDogJ0hIOm1tOnNzJyxcbiAgICAgICAgTCA6ICdZWVlZLU1NLUREJyxcbiAgICAgICAgTEwgOiAnWVlZWVtrb10gTU1NTVtyZW5dIERbYV0nLFxuICAgICAgICBMTEwgOiAnWVlZWVtrb10gTU1NTVtyZW5dIERbYV0gSEg6bW0nLFxuICAgICAgICBMTExMIDogJ2RkZGQsIFlZWVlba29dIE1NTU1bcmVuXSBEW2FdIEhIOm1tJyxcbiAgICAgICAgbCA6ICdZWVlZLU0tRCcsXG4gICAgICAgIGxsIDogJ1lZWVlba29dIE1NTSBEW2FdJyxcbiAgICAgICAgbGxsIDogJ1lZWVlba29dIE1NTSBEW2FdIEhIOm1tJyxcbiAgICAgICAgbGxsbCA6ICdkZGQsIFlZWVlba29dIE1NTSBEW2FdIEhIOm1tJ1xuICAgIH0sXG4gICAgY2FsZW5kYXIgOiB7XG4gICAgICAgIHNhbWVEYXkgOiAnW2dhdXJdIExUW2V0YW5dJyxcbiAgICAgICAgbmV4dERheSA6ICdbYmloYXJdIExUW2V0YW5dJyxcbiAgICAgICAgbmV4dFdlZWsgOiAnZGRkZCBMVFtldGFuXScsXG4gICAgICAgIGxhc3REYXkgOiAnW2F0em9dIExUW2V0YW5dJyxcbiAgICAgICAgbGFzdFdlZWsgOiAnW2F1cnJla29dIGRkZGQgTFRbZXRhbl0nLFxuICAgICAgICBzYW1lRWxzZSA6ICdMJ1xuICAgIH0sXG4gICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICBmdXR1cmUgOiAnJXMgYmFycnUnLFxuICAgICAgICBwYXN0IDogJ2R1ZWxhICVzJyxcbiAgICAgICAgcyA6ICdzZWd1bmRvIGJhdHp1aycsXG4gICAgICAgIHNzIDogJyVkIHNlZ3VuZG8nLFxuICAgICAgICBtIDogJ21pbnV0dSBiYXQnLFxuICAgICAgICBtbSA6ICclZCBtaW51dHUnLFxuICAgICAgICBoIDogJ29yZHUgYmF0JyxcbiAgICAgICAgaGggOiAnJWQgb3JkdScsXG4gICAgICAgIGQgOiAnZWd1biBiYXQnLFxuICAgICAgICBkZCA6ICclZCBlZ3VuJyxcbiAgICAgICAgTSA6ICdoaWxhYmV0ZSBiYXQnLFxuICAgICAgICBNTSA6ICclZCBoaWxhYmV0ZScsXG4gICAgICAgIHkgOiAndXJ0ZSBiYXQnLFxuICAgICAgICB5eSA6ICclZCB1cnRlJ1xuICAgIH0sXG4gICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9XFwuLyxcbiAgICBvcmRpbmFsIDogJyVkLicsXG4gICAgd2VlayA6IHtcbiAgICAgICAgZG93IDogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgIGRveSA6IDcgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDFzdCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICB9XG59KTtcblxuLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSA6IFBlcnNpYW4gW2ZhXVxuLy8hIGF1dGhvciA6IEVicmFoaW0gQnlhZ293aSA6IGh0dHBzOi8vZ2l0aHViLmNvbS9lYnJhbWluaW9cblxudmFyIHN5bWJvbE1hcCQ1ID0ge1xuICAgICcxJzogJ9uxJyxcbiAgICAnMic6ICfbsicsXG4gICAgJzMnOiAn27MnLFxuICAgICc0JzogJ9u0JyxcbiAgICAnNSc6ICfbtScsXG4gICAgJzYnOiAn27YnLFxuICAgICc3JzogJ9u3JyxcbiAgICAnOCc6ICfbuCcsXG4gICAgJzknOiAn27knLFxuICAgICcwJzogJ9uwJ1xufTtcbnZhciBudW1iZXJNYXAkNCA9IHtcbiAgICAn27EnOiAnMScsXG4gICAgJ9uyJzogJzInLFxuICAgICfbsyc6ICczJyxcbiAgICAn27QnOiAnNCcsXG4gICAgJ9u1JzogJzUnLFxuICAgICfbtic6ICc2JyxcbiAgICAn27cnOiAnNycsXG4gICAgJ9u4JzogJzgnLFxuICAgICfbuSc6ICc5JyxcbiAgICAn27AnOiAnMCdcbn07XG5cbmhvb2tzLmRlZmluZUxvY2FsZSgnZmEnLCB7XG4gICAgbW9udGhzIDogJ9qY2KfZhtmI24zZh1/ZgdmI2LHbjNmHX9mF2KfYsdizX9ii2YjYsduM2YRf2YXZh1/amNmI2KbZhl/amNmI2KbbjNmHX9in2YjYql/Ys9m+2KrYp9mF2KjYsV/Yp9qp2KrYqNixX9mG2YjYp9mF2KjYsV/Yr9iz2KfZhdio2LEnLnNwbGl0KCdfJyksXG4gICAgbW9udGhzU2hvcnQgOiAn2pjYp9mG2YjbjNmHX9mB2YjYsduM2Ydf2YXYp9ix2LNf2KLZiNix24zZhF/ZhdmHX9qY2YjYptmGX9qY2YjYptuM2Ydf2KfZiNiqX9iz2b7Yqtin2YXYqNixX9in2qnYqtio2LFf2YbZiNin2YXYqNixX9iv2LPYp9mF2KjYsScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5cyA6ICfbjNqpXFx1MjAwY9i02YbYqNmHX9iv2YjYtNmG2KjZh1/Ys9mHXFx1MjAwY9i02YbYqNmHX9qG2YfYp9ix2LTZhtio2Ydf2b7ZhtisXFx1MjAwY9i02YbYqNmHX9is2YXYudmHX9i02YbYqNmHJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzU2hvcnQgOiAn24zaqVxcdTIwMGPYtNmG2KjZh1/Yr9mI2LTZhtio2Ydf2LPZh1xcdTIwMGPYtNmG2KjZh1/ahtmH2KfYsdi02YbYqNmHX9m+2YbYrFxcdTIwMGPYtNmG2KjZh1/YrNmF2LnZh1/YtNmG2KjZhycuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbiA6ICfbjF/Yr1/Ys1/ahl/Zvl/YrF/YtCcuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdISDptbScsXG4gICAgICAgIExUUyA6ICdISDptbTpzcycsXG4gICAgICAgIEwgOiAnREQvTU0vWVlZWScsXG4gICAgICAgIExMIDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgTExMIDogJ0QgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgTExMTCA6ICdkZGRkLCBEIE1NTU0gWVlZWSBISDptbSdcbiAgICB9LFxuICAgIG1lcmlkaWVtUGFyc2U6IC/Zgtio2YQg2KfYsiDYuNmH2LF82KjYudivINin2LIg2LjZh9ixLyxcbiAgICBpc1BNOiBmdW5jdGlvbiAoaW5wdXQpIHtcbiAgICAgICAgcmV0dXJuIC/YqNi52K8g2KfYsiDYuNmH2LEvLnRlc3QoaW5wdXQpO1xuICAgIH0sXG4gICAgbWVyaWRpZW0gOiBmdW5jdGlvbiAoaG91ciwgbWludXRlLCBpc0xvd2VyKSB7XG4gICAgICAgIGlmIChob3VyIDwgMTIpIHtcbiAgICAgICAgICAgIHJldHVybiAn2YLYqNmEINin2LIg2LjZh9ixJztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiAn2KjYudivINin2LIg2LjZh9ixJztcbiAgICAgICAgfVxuICAgIH0sXG4gICAgY2FsZW5kYXIgOiB7XG4gICAgICAgIHNhbWVEYXkgOiAnW9in2YXYsdmI2LIg2LPYp9i52KpdIExUJyxcbiAgICAgICAgbmV4dERheSA6ICdb2YHYsdiv2Kcg2LPYp9i52KpdIExUJyxcbiAgICAgICAgbmV4dFdlZWsgOiAnZGRkZCBb2LPYp9i52KpdIExUJyxcbiAgICAgICAgbGFzdERheSA6ICdb2K/bjNix2YjYsiDYs9in2LnYql0gTFQnLFxuICAgICAgICBsYXN0V2VlayA6ICdkZGRkIFvZvtuM2LRdIFvYs9in2LnYql0gTFQnLFxuICAgICAgICBzYW1lRWxzZSA6ICdMJ1xuICAgIH0sXG4gICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICBmdXR1cmUgOiAn2K/YsSAlcycsXG4gICAgICAgIHBhc3QgOiAnJXMg2b7bjNi0JyxcbiAgICAgICAgcyA6ICfahtmG2K8g2KvYp9mG24zZhycsXG4gICAgICAgIHNzIDogJ9ir2KfZhtuM2YcgZCUnLFxuICAgICAgICBtIDogJ9uM2qkg2K/ZgtuM2YLZhycsXG4gICAgICAgIG1tIDogJyVkINiv2YLbjNmC2YcnLFxuICAgICAgICBoIDogJ9uM2qkg2LPYp9i52KonLFxuICAgICAgICBoaCA6ICclZCDYs9in2LnYqicsXG4gICAgICAgIGQgOiAn24zaqSDYsdmI2LInLFxuICAgICAgICBkZCA6ICclZCDYsdmI2LInLFxuICAgICAgICBNIDogJ9uM2qkg2YXYp9mHJyxcbiAgICAgICAgTU0gOiAnJWQg2YXYp9mHJyxcbiAgICAgICAgeSA6ICfbjNqpINiz2KfZhCcsXG4gICAgICAgIHl5IDogJyVkINiz2KfZhCdcbiAgICB9LFxuICAgIHByZXBhcnNlOiBmdW5jdGlvbiAoc3RyaW5nKSB7XG4gICAgICAgIHJldHVybiBzdHJpbmcucmVwbGFjZSgvW9uwLdu5XS9nLCBmdW5jdGlvbiAobWF0Y2gpIHtcbiAgICAgICAgICAgIHJldHVybiBudW1iZXJNYXAkNFttYXRjaF07XG4gICAgICAgIH0pLnJlcGxhY2UoL9iML2csICcsJyk7XG4gICAgfSxcbiAgICBwb3N0Zm9ybWF0OiBmdW5jdGlvbiAoc3RyaW5nKSB7XG4gICAgICAgIHJldHVybiBzdHJpbmcucmVwbGFjZSgvXFxkL2csIGZ1bmN0aW9uIChtYXRjaCkge1xuICAgICAgICAgICAgcmV0dXJuIHN5bWJvbE1hcCQ1W21hdGNoXTtcbiAgICAgICAgfSkucmVwbGFjZSgvLC9nLCAn2IwnKTtcbiAgICB9LFxuICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfdmFLyxcbiAgICBvcmRpbmFsIDogJyVk2YUnLFxuICAgIHdlZWsgOiB7XG4gICAgICAgIGRvdyA6IDYsIC8vIFNhdHVyZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgIGRveSA6IDEyIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDFzdCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICB9XG59KTtcblxuLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSA6IEZpbm5pc2ggW2ZpXVxuLy8hIGF1dGhvciA6IFRhcm1vIEFpZGFudGF1c3RhIDogaHR0cHM6Ly9naXRodWIuY29tL2JsZWFkb2ZcblxudmFyIG51bWJlcnNQYXN0ID0gJ25vbGxhIHlrc2kga2Frc2kga29sbWUgbmVsasOkIHZpaXNpIGt1dXNpIHNlaXRzZW3DpG4ga2FoZGVrc2FuIHloZGVrc8Okbicuc3BsaXQoJyAnKTtcbnZhciBudW1iZXJzRnV0dXJlID0gW1xuICAgICAgICAnbm9sbGEnLCAneWhkZW4nLCAna2FoZGVuJywgJ2tvbG1lbicsICduZWxqw6RuJywgJ3ZpaWRlbicsICdrdXVkZW4nLFxuICAgICAgICBudW1iZXJzUGFzdFs3XSwgbnVtYmVyc1Bhc3RbOF0sIG51bWJlcnNQYXN0WzldXG4gICAgXTtcbmZ1bmN0aW9uIHRyYW5zbGF0ZSQyKG51bWJlciwgd2l0aG91dFN1ZmZpeCwga2V5LCBpc0Z1dHVyZSkge1xuICAgIHZhciByZXN1bHQgPSAnJztcbiAgICBzd2l0Y2ggKGtleSkge1xuICAgICAgICBjYXNlICdzJzpcbiAgICAgICAgICAgIHJldHVybiBpc0Z1dHVyZSA/ICdtdXV0YW1hbiBzZWt1bm5pbicgOiAnbXV1dGFtYSBzZWt1bnRpJztcbiAgICAgICAgY2FzZSAnc3MnOlxuICAgICAgICAgICAgcmV0dXJuIGlzRnV0dXJlID8gJ3Nla3VubmluJyA6ICdzZWt1bnRpYSc7XG4gICAgICAgIGNhc2UgJ20nOlxuICAgICAgICAgICAgcmV0dXJuIGlzRnV0dXJlID8gJ21pbnV1dGluJyA6ICdtaW51dXR0aSc7XG4gICAgICAgIGNhc2UgJ21tJzpcbiAgICAgICAgICAgIHJlc3VsdCA9IGlzRnV0dXJlID8gJ21pbnV1dGluJyA6ICdtaW51dXR0aWEnO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ2gnOlxuICAgICAgICAgICAgcmV0dXJuIGlzRnV0dXJlID8gJ3R1bm5pbicgOiAndHVudGknO1xuICAgICAgICBjYXNlICdoaCc6XG4gICAgICAgICAgICByZXN1bHQgPSBpc0Z1dHVyZSA/ICd0dW5uaW4nIDogJ3R1bnRpYSc7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnZCc6XG4gICAgICAgICAgICByZXR1cm4gaXNGdXR1cmUgPyAncMOkaXbDpG4nIDogJ3DDpGl2w6QnO1xuICAgICAgICBjYXNlICdkZCc6XG4gICAgICAgICAgICByZXN1bHQgPSBpc0Z1dHVyZSA/ICdww6RpdsOkbicgOiAncMOkaXbDpMOkJztcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICdNJzpcbiAgICAgICAgICAgIHJldHVybiBpc0Z1dHVyZSA/ICdrdXVrYXVkZW4nIDogJ2t1dWthdXNpJztcbiAgICAgICAgY2FzZSAnTU0nOlxuICAgICAgICAgICAgcmVzdWx0ID0gaXNGdXR1cmUgPyAna3V1a2F1ZGVuJyA6ICdrdXVrYXV0dGEnO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ3knOlxuICAgICAgICAgICAgcmV0dXJuIGlzRnV0dXJlID8gJ3Z1b2RlbicgOiAndnVvc2knO1xuICAgICAgICBjYXNlICd5eSc6XG4gICAgICAgICAgICByZXN1bHQgPSBpc0Z1dHVyZSA/ICd2dW9kZW4nIDogJ3Z1b3R0YSc7XG4gICAgICAgICAgICBicmVhaztcbiAgICB9XG4gICAgcmVzdWx0ID0gdmVyYmFsTnVtYmVyKG51bWJlciwgaXNGdXR1cmUpICsgJyAnICsgcmVzdWx0O1xuICAgIHJldHVybiByZXN1bHQ7XG59XG5mdW5jdGlvbiB2ZXJiYWxOdW1iZXIobnVtYmVyLCBpc0Z1dHVyZSkge1xuICAgIHJldHVybiBudW1iZXIgPCAxMCA/IChpc0Z1dHVyZSA/IG51bWJlcnNGdXR1cmVbbnVtYmVyXSA6IG51bWJlcnNQYXN0W251bWJlcl0pIDogbnVtYmVyO1xufVxuXG5ob29rcy5kZWZpbmVMb2NhbGUoJ2ZpJywge1xuICAgIG1vbnRocyA6ICd0YW1taWt1dV9oZWxtaWt1dV9tYWFsaXNrdXVfaHVodGlrdXVfdG91a29rdXVfa2Vzw6RrdXVfaGVpbsOka3V1X2Vsb2t1dV9zeXlza3V1X2xva2FrdXVfbWFycmFza3V1X2pvdWx1a3V1Jy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0IDogJ3RhbW1pX2hlbG1pX21hYWxpc19odWh0aV90b3Vrb19rZXPDpF9oZWluw6RfZWxvX3N5eXNfbG9rYV9tYXJyYXNfam91bHUnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXMgOiAnc3VubnVudGFpX21hYW5hbnRhaV90aWlzdGFpX2tlc2tpdmlpa2tvX3RvcnN0YWlfcGVyamFudGFpX2xhdWFudGFpJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzU2hvcnQgOiAnc3VfbWFfdGlfa2VfdG9fcGVfbGEnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW4gOiAnc3VfbWFfdGlfa2VfdG9fcGVfbGEnLnNwbGl0KCdfJyksXG4gICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgIExUIDogJ0hILm1tJyxcbiAgICAgICAgTFRTIDogJ0hILm1tLnNzJyxcbiAgICAgICAgTCA6ICdERC5NTS5ZWVlZJyxcbiAgICAgICAgTEwgOiAnRG8gTU1NTVt0YV0gWVlZWScsXG4gICAgICAgIExMTCA6ICdEbyBNTU1NW3RhXSBZWVlZLCBba2xvXSBISC5tbScsXG4gICAgICAgIExMTEwgOiAnZGRkZCwgRG8gTU1NTVt0YV0gWVlZWSwgW2tsb10gSEgubW0nLFxuICAgICAgICBsIDogJ0QuTS5ZWVlZJyxcbiAgICAgICAgbGwgOiAnRG8gTU1NIFlZWVknLFxuICAgICAgICBsbGwgOiAnRG8gTU1NIFlZWVksIFtrbG9dIEhILm1tJyxcbiAgICAgICAgbGxsbCA6ICdkZGQsIERvIE1NTSBZWVlZLCBba2xvXSBISC5tbSdcbiAgICB9LFxuICAgIGNhbGVuZGFyIDoge1xuICAgICAgICBzYW1lRGF5IDogJ1t0w6Ruw6TDpG5dIFtrbG9dIExUJyxcbiAgICAgICAgbmV4dERheSA6ICdbaHVvbWVubmFdIFtrbG9dIExUJyxcbiAgICAgICAgbmV4dFdlZWsgOiAnZGRkZCBba2xvXSBMVCcsXG4gICAgICAgIGxhc3REYXkgOiAnW2VpbGVuXSBba2xvXSBMVCcsXG4gICAgICAgIGxhc3RXZWVrIDogJ1t2aWltZV0gZGRkZFtuYV0gW2tsb10gTFQnLFxuICAgICAgICBzYW1lRWxzZSA6ICdMJ1xuICAgIH0sXG4gICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICBmdXR1cmUgOiAnJXMgcMOkw6RzdMOkJyxcbiAgICAgICAgcGFzdCA6ICclcyBzaXR0ZW4nLFxuICAgICAgICBzIDogdHJhbnNsYXRlJDIsXG4gICAgICAgIHNzIDogdHJhbnNsYXRlJDIsXG4gICAgICAgIG0gOiB0cmFuc2xhdGUkMixcbiAgICAgICAgbW0gOiB0cmFuc2xhdGUkMixcbiAgICAgICAgaCA6IHRyYW5zbGF0ZSQyLFxuICAgICAgICBoaCA6IHRyYW5zbGF0ZSQyLFxuICAgICAgICBkIDogdHJhbnNsYXRlJDIsXG4gICAgICAgIGRkIDogdHJhbnNsYXRlJDIsXG4gICAgICAgIE0gOiB0cmFuc2xhdGUkMixcbiAgICAgICAgTU0gOiB0cmFuc2xhdGUkMixcbiAgICAgICAgeSA6IHRyYW5zbGF0ZSQyLFxuICAgICAgICB5eSA6IHRyYW5zbGF0ZSQyXG4gICAgfSxcbiAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn1cXC4vLFxuICAgIG9yZGluYWwgOiAnJWQuJyxcbiAgICB3ZWVrIDoge1xuICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogNCAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH1cbn0pO1xuXG4vLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogRmFyb2VzZSBbZm9dXG4vLyEgYXV0aG9yIDogUmFnbmFyIEpvaGFubmVzZW4gOiBodHRwczovL2dpdGh1Yi5jb20vcmFnbmFyMTIzXG5cbmhvb2tzLmRlZmluZUxvY2FsZSgnZm8nLCB7XG4gICAgbW9udGhzIDogJ2phbnVhcl9mZWJydWFyX21hcnNfYXByw61sX21haV9qdW5pX2p1bGlfYXVndXN0X3NlcHRlbWJlcl9va3RvYmVyX25vdmVtYmVyX2Rlc2VtYmVyJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0IDogJ2phbl9mZWJfbWFyX2Fwcl9tYWlfanVuX2p1bF9hdWdfc2VwX29rdF9ub3ZfZGVzJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzIDogJ3N1bm51ZGFndXJfbcOhbmFkYWd1cl90w71zZGFndXJfbWlrdWRhZ3VyX2jDs3NkYWd1cl9mcsOtZ2dqYWRhZ3VyX2xleWdhcmRhZ3VyJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzU2hvcnQgOiAnc3VuX23DoW5fdMO9c19taWtfaMOzc19mcsOtX2xleScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbiA6ICdzdV9tw6FfdMO9X21pX2jDs19mcl9sZScuc3BsaXQoJ18nKSxcbiAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgTFQgOiAnSEg6bW0nLFxuICAgICAgICBMVFMgOiAnSEg6bW06c3MnLFxuICAgICAgICBMIDogJ0REL01NL1lZWVknLFxuICAgICAgICBMTCA6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgIExMTCA6ICdEIE1NTU0gWVlZWSBISDptbScsXG4gICAgICAgIExMTEwgOiAnZGRkZCBELiBNTU1NLCBZWVlZIEhIOm1tJ1xuICAgIH0sXG4gICAgY2FsZW5kYXIgOiB7XG4gICAgICAgIHNhbWVEYXkgOiAnW8ONIGRhZyBrbC5dIExUJyxcbiAgICAgICAgbmV4dERheSA6ICdbw40gbW9yZ2luIGtsLl0gTFQnLFxuICAgICAgICBuZXh0V2VlayA6ICdkZGRkIFtrbC5dIExUJyxcbiAgICAgICAgbGFzdERheSA6ICdbw40gZ2rDoXIga2wuXSBMVCcsXG4gICAgICAgIGxhc3RXZWVrIDogJ1tzw63DsHN0dV0gZGRkZCBba2xdIExUJyxcbiAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJ3VtICVzJyxcbiAgICAgICAgcGFzdCA6ICclcyBzw63DsGFuaScsXG4gICAgICAgIHMgOiAnZsOhIHNla3VuZCcsXG4gICAgICAgIHNzIDogJyVkIHNla3VuZGlyJyxcbiAgICAgICAgbSA6ICdlaW4gbWludXR0JyxcbiAgICAgICAgbW0gOiAnJWQgbWludXR0aXInLFxuICAgICAgICBoIDogJ2VpbiB0w61taScsXG4gICAgICAgIGhoIDogJyVkIHTDrW1hcicsXG4gICAgICAgIGQgOiAnZWluIGRhZ3VyJyxcbiAgICAgICAgZGQgOiAnJWQgZGFnYXInLFxuICAgICAgICBNIDogJ2VpbiBtw6FuYcOwaScsXG4gICAgICAgIE1NIDogJyVkIG3DoW5hw7BpcicsXG4gICAgICAgIHkgOiAnZWl0dCDDoXInLFxuICAgICAgICB5eSA6ICclZCDDoXInXG4gICAgfSxcbiAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn1cXC4vLFxuICAgIG9yZGluYWwgOiAnJWQuJyxcbiAgICB3ZWVrIDoge1xuICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogNCAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH1cbn0pO1xuXG4vLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogRnJlbmNoIChDYW5hZGEpIFtmci1jYV1cbi8vISBhdXRob3IgOiBKb25hdGhhbiBBYm91cmJpaCA6IGh0dHBzOi8vZ2l0aHViLmNvbS9qb25iY2FcblxuaG9va3MuZGVmaW5lTG9jYWxlKCdmci1jYScsIHtcbiAgICBtb250aHMgOiAnamFudmllcl9mw6l2cmllcl9tYXJzX2F2cmlsX21haV9qdWluX2p1aWxsZXRfYW/Du3Rfc2VwdGVtYnJlX29jdG9icmVfbm92ZW1icmVfZMOpY2VtYnJlJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0IDogJ2phbnYuX2bDqXZyLl9tYXJzX2F2ci5fbWFpX2p1aW5fanVpbC5fYW/Du3Rfc2VwdC5fb2N0Ll9ub3YuX2TDqWMuJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgIHdlZWtkYXlzIDogJ2RpbWFuY2hlX2x1bmRpX21hcmRpX21lcmNyZWRpX2pldWRpX3ZlbmRyZWRpX3NhbWVkaScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0IDogJ2RpbS5fbHVuLl9tYXIuX21lci5famV1Ll92ZW4uX3NhbS4nLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW4gOiAnZGlfbHVfbWFfbWVfamVfdmVfc2EnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNQYXJzZUV4YWN0IDogdHJ1ZSxcbiAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgTFQgOiAnSEg6bW0nLFxuICAgICAgICBMVFMgOiAnSEg6bW06c3MnLFxuICAgICAgICBMIDogJ1lZWVktTU0tREQnLFxuICAgICAgICBMTCA6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgIExMTCA6ICdEIE1NTU0gWVlZWSBISDptbScsXG4gICAgICAgIExMTEwgOiAnZGRkZCBEIE1NTU0gWVlZWSBISDptbSdcbiAgICB9LFxuICAgIGNhbGVuZGFyIDoge1xuICAgICAgICBzYW1lRGF5IDogJ1tBdWpvdXJk4oCZaHVpIMOgXSBMVCcsXG4gICAgICAgIG5leHREYXkgOiAnW0RlbWFpbiDDoF0gTFQnLFxuICAgICAgICBuZXh0V2VlayA6ICdkZGRkIFvDoF0gTFQnLFxuICAgICAgICBsYXN0RGF5IDogJ1tIaWVyIMOgXSBMVCcsXG4gICAgICAgIGxhc3RXZWVrIDogJ2RkZGQgW2Rlcm5pZXIgw6BdIExUJyxcbiAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJ2RhbnMgJXMnLFxuICAgICAgICBwYXN0IDogJ2lsIHkgYSAlcycsXG4gICAgICAgIHMgOiAncXVlbHF1ZXMgc2Vjb25kZXMnLFxuICAgICAgICBzcyA6ICclZCBzZWNvbmRlcycsXG4gICAgICAgIG0gOiAndW5lIG1pbnV0ZScsXG4gICAgICAgIG1tIDogJyVkIG1pbnV0ZXMnLFxuICAgICAgICBoIDogJ3VuZSBoZXVyZScsXG4gICAgICAgIGhoIDogJyVkIGhldXJlcycsXG4gICAgICAgIGQgOiAndW4gam91cicsXG4gICAgICAgIGRkIDogJyVkIGpvdXJzJyxcbiAgICAgICAgTSA6ICd1biBtb2lzJyxcbiAgICAgICAgTU0gOiAnJWQgbW9pcycsXG4gICAgICAgIHkgOiAndW4gYW4nLFxuICAgICAgICB5eSA6ICclZCBhbnMnXG4gICAgfSxcbiAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn0oZXJ8ZSkvLFxuICAgIG9yZGluYWwgOiBmdW5jdGlvbiAobnVtYmVyLCBwZXJpb2QpIHtcbiAgICAgICAgc3dpdGNoIChwZXJpb2QpIHtcbiAgICAgICAgICAgIC8vIFdvcmRzIHdpdGggbWFzY3VsaW5lIGdyYW1tYXRpY2FsIGdlbmRlcjogbW9pcywgdHJpbWVzdHJlLCBqb3VyXG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgY2FzZSAnTSc6XG4gICAgICAgICAgICBjYXNlICdRJzpcbiAgICAgICAgICAgIGNhc2UgJ0QnOlxuICAgICAgICAgICAgY2FzZSAnREREJzpcbiAgICAgICAgICAgIGNhc2UgJ2QnOlxuICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAobnVtYmVyID09PSAxID8gJ2VyJyA6ICdlJyk7XG5cbiAgICAgICAgICAgIC8vIFdvcmRzIHdpdGggZmVtaW5pbmUgZ3JhbW1hdGljYWwgZ2VuZGVyOiBzZW1haW5lXG4gICAgICAgICAgICBjYXNlICd3JzpcbiAgICAgICAgICAgIGNhc2UgJ1cnOlxuICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAobnVtYmVyID09PSAxID8gJ3JlJyA6ICdlJyk7XG4gICAgICAgIH1cbiAgICB9XG59KTtcblxuLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSA6IEZyZW5jaCAoU3dpdHplcmxhbmQpIFtmci1jaF1cbi8vISBhdXRob3IgOiBHYXNwYXJkIEJ1Y2hlciA6IGh0dHBzOi8vZ2l0aHViLmNvbS9nYXNwYXJkXG5cbmhvb2tzLmRlZmluZUxvY2FsZSgnZnItY2gnLCB7XG4gICAgbW9udGhzIDogJ2phbnZpZXJfZsOpdnJpZXJfbWFyc19hdnJpbF9tYWlfanVpbl9qdWlsbGV0X2Fvw7t0X3NlcHRlbWJyZV9vY3RvYnJlX25vdmVtYnJlX2TDqWNlbWJyZScuc3BsaXQoJ18nKSxcbiAgICBtb250aHNTaG9ydCA6ICdqYW52Ll9mw6l2ci5fbWFyc19hdnIuX21haV9qdWluX2p1aWwuX2Fvw7t0X3NlcHQuX29jdC5fbm92Ll9kw6ljLicuc3BsaXQoJ18nKSxcbiAgICBtb250aHNQYXJzZUV4YWN0IDogdHJ1ZSxcbiAgICB3ZWVrZGF5cyA6ICdkaW1hbmNoZV9sdW5kaV9tYXJkaV9tZXJjcmVkaV9qZXVkaV92ZW5kcmVkaV9zYW1lZGknLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydCA6ICdkaW0uX2x1bi5fbWFyLl9tZXIuX2pldS5fdmVuLl9zYW0uJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzTWluIDogJ2RpX2x1X21hX21lX2plX3ZlX3NhJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzUGFyc2VFeGFjdCA6IHRydWUsXG4gICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgIExUIDogJ0hIOm1tJyxcbiAgICAgICAgTFRTIDogJ0hIOm1tOnNzJyxcbiAgICAgICAgTCA6ICdERC5NTS5ZWVlZJyxcbiAgICAgICAgTEwgOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICBMTEwgOiAnRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICBMTExMIDogJ2RkZGQgRCBNTU1NIFlZWVkgSEg6bW0nXG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheSA6ICdbQXVqb3VyZOKAmWh1aSDDoF0gTFQnLFxuICAgICAgICBuZXh0RGF5IDogJ1tEZW1haW4gw6BdIExUJyxcbiAgICAgICAgbmV4dFdlZWsgOiAnZGRkZCBbw6BdIExUJyxcbiAgICAgICAgbGFzdERheSA6ICdbSGllciDDoF0gTFQnLFxuICAgICAgICBsYXN0V2VlayA6ICdkZGRkIFtkZXJuaWVyIMOgXSBMVCcsXG4gICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6ICdkYW5zICVzJyxcbiAgICAgICAgcGFzdCA6ICdpbCB5IGEgJXMnLFxuICAgICAgICBzIDogJ3F1ZWxxdWVzIHNlY29uZGVzJyxcbiAgICAgICAgc3MgOiAnJWQgc2Vjb25kZXMnLFxuICAgICAgICBtIDogJ3VuZSBtaW51dGUnLFxuICAgICAgICBtbSA6ICclZCBtaW51dGVzJyxcbiAgICAgICAgaCA6ICd1bmUgaGV1cmUnLFxuICAgICAgICBoaCA6ICclZCBoZXVyZXMnLFxuICAgICAgICBkIDogJ3VuIGpvdXInLFxuICAgICAgICBkZCA6ICclZCBqb3VycycsXG4gICAgICAgIE0gOiAndW4gbW9pcycsXG4gICAgICAgIE1NIDogJyVkIG1vaXMnLFxuICAgICAgICB5IDogJ3VuIGFuJyxcbiAgICAgICAgeXkgOiAnJWQgYW5zJ1xuICAgIH0sXG4gICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9KGVyfGUpLyxcbiAgICBvcmRpbmFsIDogZnVuY3Rpb24gKG51bWJlciwgcGVyaW9kKSB7XG4gICAgICAgIHN3aXRjaCAocGVyaW9kKSB7XG4gICAgICAgICAgICAvLyBXb3JkcyB3aXRoIG1hc2N1bGluZSBncmFtbWF0aWNhbCBnZW5kZXI6IG1vaXMsIHRyaW1lc3RyZSwgam91clxuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIGNhc2UgJ00nOlxuICAgICAgICAgICAgY2FzZSAnUSc6XG4gICAgICAgICAgICBjYXNlICdEJzpcbiAgICAgICAgICAgIGNhc2UgJ0RERCc6XG4gICAgICAgICAgICBjYXNlICdkJzpcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgKG51bWJlciA9PT0gMSA/ICdlcicgOiAnZScpO1xuXG4gICAgICAgICAgICAvLyBXb3JkcyB3aXRoIGZlbWluaW5lIGdyYW1tYXRpY2FsIGdlbmRlcjogc2VtYWluZVxuICAgICAgICAgICAgY2FzZSAndyc6XG4gICAgICAgICAgICBjYXNlICdXJzpcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgKG51bWJlciA9PT0gMSA/ICdyZScgOiAnZScpO1xuICAgICAgICB9XG4gICAgfSxcbiAgICB3ZWVrIDoge1xuICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogNCAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH1cbn0pO1xuXG4vLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogRnJlbmNoIFtmcl1cbi8vISBhdXRob3IgOiBKb2huIEZpc2NoZXIgOiBodHRwczovL2dpdGh1Yi5jb20vamZyb2ZmaWNlXG5cbmhvb2tzLmRlZmluZUxvY2FsZSgnZnInLCB7XG4gICAgbW9udGhzIDogJ2phbnZpZXJfZsOpdnJpZXJfbWFyc19hdnJpbF9tYWlfanVpbl9qdWlsbGV0X2Fvw7t0X3NlcHRlbWJyZV9vY3RvYnJlX25vdmVtYnJlX2TDqWNlbWJyZScuc3BsaXQoJ18nKSxcbiAgICBtb250aHNTaG9ydCA6ICdqYW52Ll9mw6l2ci5fbWFyc19hdnIuX21haV9qdWluX2p1aWwuX2Fvw7t0X3NlcHQuX29jdC5fbm92Ll9kw6ljLicuc3BsaXQoJ18nKSxcbiAgICBtb250aHNQYXJzZUV4YWN0IDogdHJ1ZSxcbiAgICB3ZWVrZGF5cyA6ICdkaW1hbmNoZV9sdW5kaV9tYXJkaV9tZXJjcmVkaV9qZXVkaV92ZW5kcmVkaV9zYW1lZGknLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydCA6ICdkaW0uX2x1bi5fbWFyLl9tZXIuX2pldS5fdmVuLl9zYW0uJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzTWluIDogJ2RpX2x1X21hX21lX2plX3ZlX3NhJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzUGFyc2VFeGFjdCA6IHRydWUsXG4gICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgIExUIDogJ0hIOm1tJyxcbiAgICAgICAgTFRTIDogJ0hIOm1tOnNzJyxcbiAgICAgICAgTCA6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgTEwgOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICBMTEwgOiAnRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICBMTExMIDogJ2RkZGQgRCBNTU1NIFlZWVkgSEg6bW0nXG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheSA6ICdbQXVqb3VyZOKAmWh1aSDDoF0gTFQnLFxuICAgICAgICBuZXh0RGF5IDogJ1tEZW1haW4gw6BdIExUJyxcbiAgICAgICAgbmV4dFdlZWsgOiAnZGRkZCBbw6BdIExUJyxcbiAgICAgICAgbGFzdERheSA6ICdbSGllciDDoF0gTFQnLFxuICAgICAgICBsYXN0V2VlayA6ICdkZGRkIFtkZXJuaWVyIMOgXSBMVCcsXG4gICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6ICdkYW5zICVzJyxcbiAgICAgICAgcGFzdCA6ICdpbCB5IGEgJXMnLFxuICAgICAgICBzIDogJ3F1ZWxxdWVzIHNlY29uZGVzJyxcbiAgICAgICAgc3MgOiAnJWQgc2Vjb25kZXMnLFxuICAgICAgICBtIDogJ3VuZSBtaW51dGUnLFxuICAgICAgICBtbSA6ICclZCBtaW51dGVzJyxcbiAgICAgICAgaCA6ICd1bmUgaGV1cmUnLFxuICAgICAgICBoaCA6ICclZCBoZXVyZXMnLFxuICAgICAgICBkIDogJ3VuIGpvdXInLFxuICAgICAgICBkZCA6ICclZCBqb3VycycsXG4gICAgICAgIE0gOiAndW4gbW9pcycsXG4gICAgICAgIE1NIDogJyVkIG1vaXMnLFxuICAgICAgICB5IDogJ3VuIGFuJyxcbiAgICAgICAgeXkgOiAnJWQgYW5zJ1xuICAgIH0sXG4gICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9KGVyfCkvLFxuICAgIG9yZGluYWwgOiBmdW5jdGlvbiAobnVtYmVyLCBwZXJpb2QpIHtcbiAgICAgICAgc3dpdGNoIChwZXJpb2QpIHtcbiAgICAgICAgICAgIC8vIFRPRE86IFJldHVybiAnZScgd2hlbiBkYXkgb2YgbW9udGggPiAxLiBNb3ZlIHRoaXMgY2FzZSBpbnNpZGVcbiAgICAgICAgICAgIC8vIGJsb2NrIGZvciBtYXNjdWxpbmUgd29yZHMgYmVsb3cuXG4gICAgICAgICAgICAvLyBTZWUgaHR0cHM6Ly9naXRodWIuY29tL21vbWVudC9tb21lbnQvaXNzdWVzLzMzNzVcbiAgICAgICAgICAgIGNhc2UgJ0QnOlxuICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAobnVtYmVyID09PSAxID8gJ2VyJyA6ICcnKTtcblxuICAgICAgICAgICAgLy8gV29yZHMgd2l0aCBtYXNjdWxpbmUgZ3JhbW1hdGljYWwgZ2VuZGVyOiBtb2lzLCB0cmltZXN0cmUsIGpvdXJcbiAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICBjYXNlICdNJzpcbiAgICAgICAgICAgIGNhc2UgJ1EnOlxuICAgICAgICAgICAgY2FzZSAnREREJzpcbiAgICAgICAgICAgIGNhc2UgJ2QnOlxuICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAobnVtYmVyID09PSAxID8gJ2VyJyA6ICdlJyk7XG5cbiAgICAgICAgICAgIC8vIFdvcmRzIHdpdGggZmVtaW5pbmUgZ3JhbW1hdGljYWwgZ2VuZGVyOiBzZW1haW5lXG4gICAgICAgICAgICBjYXNlICd3JzpcbiAgICAgICAgICAgIGNhc2UgJ1cnOlxuICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAobnVtYmVyID09PSAxID8gJ3JlJyA6ICdlJyk7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIHdlZWsgOiB7XG4gICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICBkb3kgOiA0ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgfVxufSk7XG5cbi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBGcmlzaWFuIFtmeV1cbi8vISBhdXRob3IgOiBSb2JpbiB2YW4gZGVyIFZsaWV0IDogaHR0cHM6Ly9naXRodWIuY29tL3JvYmluMHZhbjBkZXIwdlxuXG52YXIgbW9udGhzU2hvcnRXaXRoRG90cyA9ICdqYW4uX2ZlYi5fbXJ0Ll9hcHIuX21haV9qdW4uX2p1bC5fYXVnLl9zZXAuX29rdC5fbm92Ll9kZXMuJy5zcGxpdCgnXycpO1xudmFyIG1vbnRoc1Nob3J0V2l0aG91dERvdHMgPSAnamFuX2ZlYl9tcnRfYXByX21haV9qdW5fanVsX2F1Z19zZXBfb2t0X25vdl9kZXMnLnNwbGl0KCdfJyk7XG5cbmhvb2tzLmRlZmluZUxvY2FsZSgnZnknLCB7XG4gICAgbW9udGhzIDogJ2phbm5ld2FyaXNfZmVicmV3YXJpc19tYWFydF9hcHJpbF9tYWFpZV9qdW55X2p1bHlfYXVndXN0dXNfc2VwdGltYmVyX29rdG9iZXJfbm92aW1iZXJfZGVzaW1iZXInLnNwbGl0KCdfJyksXG4gICAgbW9udGhzU2hvcnQgOiBmdW5jdGlvbiAobSwgZm9ybWF0KSB7XG4gICAgICAgIGlmICghbSkge1xuICAgICAgICAgICAgcmV0dXJuIG1vbnRoc1Nob3J0V2l0aERvdHM7XG4gICAgICAgIH0gZWxzZSBpZiAoLy1NTU0tLy50ZXN0KGZvcm1hdCkpIHtcbiAgICAgICAgICAgIHJldHVybiBtb250aHNTaG9ydFdpdGhvdXREb3RzW20ubW9udGgoKV07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gbW9udGhzU2hvcnRXaXRoRG90c1ttLm1vbnRoKCldO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBtb250aHNQYXJzZUV4YWN0IDogdHJ1ZSxcbiAgICB3ZWVrZGF5cyA6ICdzbmVpbl9tb2FuZGVpX3RpaXNkZWlfd29hbnNkZWlfdG9uZ2Vyc2RlaV9mcmVlZF9zbmVvbicuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0IDogJ3NpLl9tby5fdGkuX3dvLl90by5fZnIuX3NvLicuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbiA6ICdTaV9Nb19UaV9Xb19Ub19Gcl9Tbycuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdISDptbScsXG4gICAgICAgIExUUyA6ICdISDptbTpzcycsXG4gICAgICAgIEwgOiAnREQtTU0tWVlZWScsXG4gICAgICAgIExMIDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgTExMIDogJ0QgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgTExMTCA6ICdkZGRkIEQgTU1NTSBZWVlZIEhIOm1tJ1xuICAgIH0sXG4gICAgY2FsZW5kYXIgOiB7XG4gICAgICAgIHNhbWVEYXk6ICdbaGpvZWQgb21dIExUJyxcbiAgICAgICAgbmV4dERheTogJ1ttb2FybiBvbV0gTFQnLFxuICAgICAgICBuZXh0V2VlazogJ2RkZGQgW29tXSBMVCcsXG4gICAgICAgIGxhc3REYXk6ICdbanVzdGVyIG9tXSBMVCcsXG4gICAgICAgIGxhc3RXZWVrOiAnW8O0ZnLDu25lXSBkZGRkIFtvbV0gTFQnLFxuICAgICAgICBzYW1lRWxzZTogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6ICdvZXIgJXMnLFxuICAgICAgICBwYXN0IDogJyVzIGx5bicsXG4gICAgICAgIHMgOiAnaW4gcGVhciBzZWtvbmRlbicsXG4gICAgICAgIHNzIDogJyVkIHNla29uZGVuJyxcbiAgICAgICAgbSA6ICdpZW4gbWluw7p0JyxcbiAgICAgICAgbW0gOiAnJWQgbWludXRlbicsXG4gICAgICAgIGggOiAnaWVuIG9lcmUnLFxuICAgICAgICBoaCA6ICclZCBvZXJlbicsXG4gICAgICAgIGQgOiAnaWVuIGRlaScsXG4gICAgICAgIGRkIDogJyVkIGRhZ2VuJyxcbiAgICAgICAgTSA6ICdpZW4gbW9hbm5lJyxcbiAgICAgICAgTU0gOiAnJWQgbW9hbm5lbicsXG4gICAgICAgIHkgOiAnaWVuIGppZXInLFxuICAgICAgICB5eSA6ICclZCBqaWVycmVuJ1xuICAgIH0sXG4gICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9KHN0ZXxkZSkvLFxuICAgIG9yZGluYWwgOiBmdW5jdGlvbiAobnVtYmVyKSB7XG4gICAgICAgIHJldHVybiBudW1iZXIgKyAoKG51bWJlciA9PT0gMSB8fCBudW1iZXIgPT09IDggfHwgbnVtYmVyID49IDIwKSA/ICdzdGUnIDogJ2RlJyk7XG4gICAgfSxcbiAgICB3ZWVrIDoge1xuICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogNCAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH1cbn0pO1xuXG4vLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogU2NvdHRpc2ggR2FlbGljIFtnZF1cbi8vISBhdXRob3IgOiBKb24gQXNoZG93biA6IGh0dHBzOi8vZ2l0aHViLmNvbS9qb25hc2hkb3duXG5cbnZhciBtb250aHMkNSA9IFtcbiAgICAnQW0gRmFvaWxsZWFjaCcsICdBbiBHZWFycmFuJywgJ0FtIE3DoHJ0JywgJ0FuIEdpYmxlYW4nLCAnQW4gQ8OoaXRlYW4nLCAnQW4gdC3DkmdtaGlvcycsICdBbiB0LUl1Y2hhcicsICdBbiBMw7luYXN0YWwnLCAnQW4gdC1TdWx0YWluJywgJ0FuIETDoG1oYWlyJywgJ0FuIHQtU2FtaGFpbicsICdBbiBEw7liaGxhY2hkJ1xuXTtcblxudmFyIG1vbnRoc1Nob3J0JDQgPSBbJ0Zhb2knLCAnR2VhcicsICdNw6BydCcsICdHaWJsJywgJ0PDqGl0JywgJ8OSZ21oJywgJ0l1Y2gnLCAnTMO5bicsICdTdWx0JywgJ0TDoG1oJywgJ1NhbWgnLCAnRMO5YmgnXTtcblxudmFyIHdlZWtkYXlzJDEgPSBbJ0RpZMOybWhuYWljaCcsICdEaWx1YWluJywgJ0RpbcOgaXJ0JywgJ0RpY2lhZGFpbicsICdEaWFyZGFvaW4nLCAnRGloYW9pbmUnLCAnRGlzYXRoYWlybmUnXTtcblxudmFyIHdlZWtkYXlzU2hvcnQgPSBbJ0RpZCcsICdEaWwnLCAnRGltJywgJ0RpYycsICdEaWEnLCAnRGloJywgJ0RpcyddO1xuXG52YXIgd2Vla2RheXNNaW4gPSBbJ0TDsicsICdMdScsICdNw6AnLCAnQ2knLCAnQXInLCAnSGEnLCAnU2EnXTtcblxuaG9va3MuZGVmaW5lTG9jYWxlKCdnZCcsIHtcbiAgICBtb250aHMgOiBtb250aHMkNSxcbiAgICBtb250aHNTaG9ydCA6IG1vbnRoc1Nob3J0JDQsXG4gICAgbW9udGhzUGFyc2VFeGFjdCA6IHRydWUsXG4gICAgd2Vla2RheXMgOiB3ZWVrZGF5cyQxLFxuICAgIHdlZWtkYXlzU2hvcnQgOiB3ZWVrZGF5c1Nob3J0LFxuICAgIHdlZWtkYXlzTWluIDogd2Vla2RheXNNaW4sXG4gICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgIExUIDogJ0hIOm1tJyxcbiAgICAgICAgTFRTIDogJ0hIOm1tOnNzJyxcbiAgICAgICAgTCA6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgTEwgOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICBMTEwgOiAnRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICBMTExMIDogJ2RkZGQsIEQgTU1NTSBZWVlZIEhIOm1tJ1xuICAgIH0sXG4gICAgY2FsZW5kYXIgOiB7XG4gICAgICAgIHNhbWVEYXkgOiAnW0FuLWRpdWdoIGFpZ10gTFQnLFxuICAgICAgICBuZXh0RGF5IDogJ1tBLW3DoGlyZWFjaCBhaWddIExUJyxcbiAgICAgICAgbmV4dFdlZWsgOiAnZGRkZCBbYWlnXSBMVCcsXG4gICAgICAgIGxhc3REYXkgOiAnW0FuLWTDqCBhaWddIExUJyxcbiAgICAgICAgbGFzdFdlZWsgOiAnZGRkZCBbc2VvIGNoYWlkaF0gW2FpZ10gTFQnLFxuICAgICAgICBzYW1lRWxzZSA6ICdMJ1xuICAgIH0sXG4gICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICBmdXR1cmUgOiAnYW5uIGFuICVzJyxcbiAgICAgICAgcGFzdCA6ICdiaG8gY2hpb25uICVzJyxcbiAgICAgICAgcyA6ICdiZWFnYW4gZGlvZ2FuJyxcbiAgICAgICAgc3MgOiAnJWQgZGlvZ2FuJyxcbiAgICAgICAgbSA6ICdtaW9uYWlkJyxcbiAgICAgICAgbW0gOiAnJWQgbWlvbmFpZGVhbicsXG4gICAgICAgIGggOiAndWFpcicsXG4gICAgICAgIGhoIDogJyVkIHVhaXJlYW4nLFxuICAgICAgICBkIDogJ2xhdGhhJyxcbiAgICAgICAgZGQgOiAnJWQgbGF0aGEnLFxuICAgICAgICBNIDogJ23DrG9zJyxcbiAgICAgICAgTU0gOiAnJWQgbcOsb3NhbicsXG4gICAgICAgIHkgOiAnYmxpYWRobmEnLFxuICAgICAgICB5eSA6ICclZCBibGlhZGhuYSdcbiAgICB9LFxuICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2UgOiAvXFxkezEsMn0oZHxuYXxtaCkvLFxuICAgIG9yZGluYWwgOiBmdW5jdGlvbiAobnVtYmVyKSB7XG4gICAgICAgIHZhciBvdXRwdXQgPSBudW1iZXIgPT09IDEgPyAnZCcgOiBudW1iZXIgJSAxMCA9PT0gMiA/ICduYScgOiAnbWgnO1xuICAgICAgICByZXR1cm4gbnVtYmVyICsgb3V0cHV0O1xuICAgIH0sXG4gICAgd2VlayA6IHtcbiAgICAgICAgZG93IDogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgIGRveSA6IDQgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDR0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICB9XG59KTtcblxuLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSA6IEdhbGljaWFuIFtnbF1cbi8vISBhdXRob3IgOiBKdWFuIEcuIEh1cnRhZG8gOiBodHRwczovL2dpdGh1Yi5jb20vanVhbmdodXJ0YWRvXG5cbmhvb2tzLmRlZmluZUxvY2FsZSgnZ2wnLCB7XG4gICAgbW9udGhzIDogJ3hhbmVpcm9fZmVicmVpcm9fbWFyem9fYWJyaWxfbWFpb194dcOxb194dWxsb19hZ29zdG9fc2V0ZW1icm9fb3V0dWJyb19ub3ZlbWJyb19kZWNlbWJybycuc3BsaXQoJ18nKSxcbiAgICBtb250aHNTaG9ydCA6ICd4YW4uX2ZlYi5fbWFyLl9hYnIuX21haS5feHXDsS5feHVsLl9hZ28uX3NldC5fb3V0Ll9ub3YuX2RlYy4nLnNwbGl0KCdfJyksXG4gICAgbW9udGhzUGFyc2VFeGFjdDogdHJ1ZSxcbiAgICB3ZWVrZGF5cyA6ICdkb21pbmdvX2x1bnNfbWFydGVzX23DqXJjb3Jlc194b3Zlc192ZW5yZXNfc8OhYmFkbycuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0IDogJ2RvbS5fbHVuLl9tYXIuX23DqXIuX3hvdi5fdmVuLl9zw6FiLicuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbiA6ICdkb19sdV9tYV9tw6lfeG9fdmVfc8OhJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzUGFyc2VFeGFjdCA6IHRydWUsXG4gICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgIExUIDogJ0g6bW0nLFxuICAgICAgICBMVFMgOiAnSDptbTpzcycsXG4gICAgICAgIEwgOiAnREQvTU0vWVlZWScsXG4gICAgICAgIExMIDogJ0QgW2RlXSBNTU1NIFtkZV0gWVlZWScsXG4gICAgICAgIExMTCA6ICdEIFtkZV0gTU1NTSBbZGVdIFlZWVkgSDptbScsXG4gICAgICAgIExMTEwgOiAnZGRkZCwgRCBbZGVdIE1NTU0gW2RlXSBZWVlZIEg6bW0nXG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheSA6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiAnW2hveGUgJyArICgodGhpcy5ob3VycygpICE9PSAxKSA/ICfDoXMnIDogJ8OhJykgKyAnXSBMVCc7XG4gICAgICAgIH0sXG4gICAgICAgIG5leHREYXkgOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gJ1ttYcOxw6EgJyArICgodGhpcy5ob3VycygpICE9PSAxKSA/ICfDoXMnIDogJ8OhJykgKyAnXSBMVCc7XG4gICAgICAgIH0sXG4gICAgICAgIG5leHRXZWVrIDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuICdkZGRkIFsnICsgKCh0aGlzLmhvdXJzKCkgIT09IDEpID8gJ8OhcycgOiAnYScpICsgJ10gTFQnO1xuICAgICAgICB9LFxuICAgICAgICBsYXN0RGF5IDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuICdbb250ZSAnICsgKCh0aGlzLmhvdXJzKCkgIT09IDEpID8gJ8OhJyA6ICdhJykgKyAnXSBMVCc7XG4gICAgICAgIH0sXG4gICAgICAgIGxhc3RXZWVrIDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuICdbb10gZGRkZCBbcGFzYWRvICcgKyAoKHRoaXMuaG91cnMoKSAhPT0gMSkgPyAnw6FzJyA6ICdhJykgKyAnXSBMVCc7XG4gICAgICAgIH0sXG4gICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6IGZ1bmN0aW9uIChzdHIpIHtcbiAgICAgICAgICAgIGlmIChzdHIuaW5kZXhPZigndW4nKSA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAnbicgKyBzdHI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gJ2VuICcgKyBzdHI7XG4gICAgICAgIH0sXG4gICAgICAgIHBhc3QgOiAnaGFpICVzJyxcbiAgICAgICAgcyA6ICd1bnMgc2VndW5kb3MnLFxuICAgICAgICBzcyA6ICclZCBzZWd1bmRvcycsXG4gICAgICAgIG0gOiAndW4gbWludXRvJyxcbiAgICAgICAgbW0gOiAnJWQgbWludXRvcycsXG4gICAgICAgIGggOiAndW5oYSBob3JhJyxcbiAgICAgICAgaGggOiAnJWQgaG9yYXMnLFxuICAgICAgICBkIDogJ3VuIGTDrWEnLFxuICAgICAgICBkZCA6ICclZCBkw61hcycsXG4gICAgICAgIE0gOiAndW4gbWVzJyxcbiAgICAgICAgTU0gOiAnJWQgbWVzZXMnLFxuICAgICAgICB5IDogJ3VuIGFubycsXG4gICAgICAgIHl5IDogJyVkIGFub3MnXG4gICAgfSxcbiAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlIDogL1xcZHsxLDJ9wrovLFxuICAgIG9yZGluYWwgOiAnJWTCuicsXG4gICAgd2VlayA6IHtcbiAgICAgICAgZG93IDogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgIGRveSA6IDQgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDR0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICB9XG59KTtcblxuLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSA6IEtvbmthbmkgTGF0aW4gc2NyaXB0IFtnb20tbGF0bl1cbi8vISBhdXRob3IgOiBUaGUgRGlzY292ZXJlciA6IGh0dHBzOi8vZ2l0aHViLmNvbS9XaWtpRGlzY292ZXJlclxuXG5mdW5jdGlvbiBwcm9jZXNzUmVsYXRpdmVUaW1lJDQobnVtYmVyLCB3aXRob3V0U3VmZml4LCBrZXksIGlzRnV0dXJlKSB7XG4gICAgdmFyIGZvcm1hdCA9IHtcbiAgICAgICAgJ3MnOiBbJ3Rob2RkZSBzZWNvbmRhbmltJywgJ3Rob2RkZSBzZWNvbmQnXSxcbiAgICAgICAgJ3NzJzogW251bWJlciArICcgc2Vjb25kYW5pbScsIG51bWJlciArICcgc2Vjb25kJ10sXG4gICAgICAgICdtJzogWydla2EgbWludGFuJywgJ2VrIG1pbnV0ZSddLFxuICAgICAgICAnbW0nOiBbbnVtYmVyICsgJyBtaW50YW5pbScsIG51bWJlciArICcgbWludGFtJ10sXG4gICAgICAgICdoJzogWydla2EgaG9yYW4nLCAnZWsgaG9yJ10sXG4gICAgICAgICdoaCc6IFtudW1iZXIgKyAnIGhvcmFuaW0nLCBudW1iZXIgKyAnIGhvciddLFxuICAgICAgICAnZCc6IFsnZWthIGRpc2FuJywgJ2VrIGRpcyddLFxuICAgICAgICAnZGQnOiBbbnVtYmVyICsgJyBkaXNhbmltJywgbnVtYmVyICsgJyBkaXMnXSxcbiAgICAgICAgJ00nOiBbJ2VrYSBtaG9pbmVhbicsICdlayBtaG9pbm8nXSxcbiAgICAgICAgJ01NJzogW251bWJlciArICcgbWhvaW5lYW5pbScsIG51bWJlciArICcgbWhvaW5lJ10sXG4gICAgICAgICd5JzogWydla2Egdm9yc2FuJywgJ2VrIHZvcm9zJ10sXG4gICAgICAgICd5eSc6IFtudW1iZXIgKyAnIHZvcnNhbmltJywgbnVtYmVyICsgJyB2b3JzYW0nXVxuICAgIH07XG4gICAgcmV0dXJuIHdpdGhvdXRTdWZmaXggPyBmb3JtYXRba2V5XVswXSA6IGZvcm1hdFtrZXldWzFdO1xufVxuXG5ob29rcy5kZWZpbmVMb2NhbGUoJ2dvbS1sYXRuJywge1xuICAgIG1vbnRocyA6ICdKYW5lcl9GZWJyZXJfTWFyc19BYnJpbF9NYWlfSnVuX0p1bGFpX0Fnb3N0X1NldGVtYnJfT3R1YnJfTm92ZW1icl9EZXplbWJyJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0IDogJ0phbi5fRmViLl9NYXJzX0Fici5fTWFpX0p1bl9KdWwuX0Fnby5fU2V0Ll9PdHUuX05vdi5fRGV6Licuc3BsaXQoJ18nKSxcbiAgICBtb250aHNQYXJzZUV4YWN0IDogdHJ1ZSxcbiAgICB3ZWVrZGF5cyA6ICdBaXRhcl9Tb21hcl9Nb25nbGxhcl9CdWR2YXJfQnJlc3Rhcl9TdWtyYXJfU29uXFwndmFyJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzU2hvcnQgOiAnQWl0Ll9Tb20uX01vbi5fQnVkLl9CcmUuX1N1ay5fU29uLicuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbiA6ICdBaV9TbV9Nb19CdV9Ccl9TdV9Tbicuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdBIGg6bW0gW3ZhenRhXScsXG4gICAgICAgIExUUyA6ICdBIGg6bW06c3MgW3ZhenRhXScsXG4gICAgICAgIEwgOiAnREQtTU0tWVlZWScsXG4gICAgICAgIExMIDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgTExMIDogJ0QgTU1NTSBZWVlZIEEgaDptbSBbdmF6dGFdJyxcbiAgICAgICAgTExMTCA6ICdkZGRkLCBNTU1NW2FjaGVhXSBEbywgWVlZWSwgQSBoOm1tIFt2YXp0YV0nLFxuICAgICAgICBsbGxsOiAnZGRkLCBEIE1NTSBZWVlZLCBBIGg6bW0gW3ZhenRhXSdcbiAgICB9LFxuICAgIGNhbGVuZGFyIDoge1xuICAgICAgICBzYW1lRGF5OiAnW0Fpel0gTFQnLFxuICAgICAgICBuZXh0RGF5OiAnW0ZhbGVhbV0gTFQnLFxuICAgICAgICBuZXh0V2VlazogJ1tJZXRhIHRvXSBkZGRkWyxdIExUJyxcbiAgICAgICAgbGFzdERheTogJ1tLYWxdIExUJyxcbiAgICAgICAgbGFzdFdlZWs6ICdbRmF0bG9dIGRkZGRbLF0gTFQnLFxuICAgICAgICBzYW1lRWxzZTogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6ICclcycsXG4gICAgICAgIHBhc3QgOiAnJXMgYWRpbScsXG4gICAgICAgIHMgOiBwcm9jZXNzUmVsYXRpdmVUaW1lJDQsXG4gICAgICAgIHNzIDogcHJvY2Vzc1JlbGF0aXZlVGltZSQ0LFxuICAgICAgICBtIDogcHJvY2Vzc1JlbGF0aXZlVGltZSQ0LFxuICAgICAgICBtbSA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUkNCxcbiAgICAgICAgaCA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUkNCxcbiAgICAgICAgaGggOiBwcm9jZXNzUmVsYXRpdmVUaW1lJDQsXG4gICAgICAgIGQgOiBwcm9jZXNzUmVsYXRpdmVUaW1lJDQsXG4gICAgICAgIGRkIDogcHJvY2Vzc1JlbGF0aXZlVGltZSQ0LFxuICAgICAgICBNIDogcHJvY2Vzc1JlbGF0aXZlVGltZSQ0LFxuICAgICAgICBNTSA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUkNCxcbiAgICAgICAgeSA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUkNCxcbiAgICAgICAgeXkgOiBwcm9jZXNzUmVsYXRpdmVUaW1lJDRcbiAgICB9LFxuICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2UgOiAvXFxkezEsMn0oZXIpLyxcbiAgICBvcmRpbmFsIDogZnVuY3Rpb24gKG51bWJlciwgcGVyaW9kKSB7XG4gICAgICAgIHN3aXRjaCAocGVyaW9kKSB7XG4gICAgICAgICAgICAvLyB0aGUgb3JkaW5hbCAnZXInIG9ubHkgYXBwbGllcyB0byBkYXkgb2YgdGhlIG1vbnRoXG4gICAgICAgICAgICBjYXNlICdEJzpcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJ2VyJztcbiAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICBjYXNlICdNJzpcbiAgICAgICAgICAgIGNhc2UgJ1EnOlxuICAgICAgICAgICAgY2FzZSAnREREJzpcbiAgICAgICAgICAgIGNhc2UgJ2QnOlxuICAgICAgICAgICAgY2FzZSAndyc6XG4gICAgICAgICAgICBjYXNlICdXJzpcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyO1xuICAgICAgICB9XG4gICAgfSxcbiAgICB3ZWVrIDoge1xuICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogNCAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH0sXG4gICAgbWVyaWRpZW1QYXJzZTogL3JhdGl8c29rYWxsaXxkb25wYXJhbXxzYW5qZS8sXG4gICAgbWVyaWRpZW1Ib3VyIDogZnVuY3Rpb24gKGhvdXIsIG1lcmlkaWVtKSB7XG4gICAgICAgIGlmIChob3VyID09PSAxMikge1xuICAgICAgICAgICAgaG91ciA9IDA7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG1lcmlkaWVtID09PSAncmF0aScpIHtcbiAgICAgICAgICAgIHJldHVybiBob3VyIDwgNCA/IGhvdXIgOiBob3VyICsgMTI7XG4gICAgICAgIH0gZWxzZSBpZiAobWVyaWRpZW0gPT09ICdzb2thbGxpJykge1xuICAgICAgICAgICAgcmV0dXJuIGhvdXI7XG4gICAgICAgIH0gZWxzZSBpZiAobWVyaWRpZW0gPT09ICdkb25wYXJhbScpIHtcbiAgICAgICAgICAgIHJldHVybiBob3VyID4gMTIgPyBob3VyIDogaG91ciArIDEyO1xuICAgICAgICB9IGVsc2UgaWYgKG1lcmlkaWVtID09PSAnc2FuamUnKSB7XG4gICAgICAgICAgICByZXR1cm4gaG91ciArIDEyO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBtZXJpZGllbSA6IGZ1bmN0aW9uIChob3VyLCBtaW51dGUsIGlzTG93ZXIpIHtcbiAgICAgICAgaWYgKGhvdXIgPCA0KSB7XG4gICAgICAgICAgICByZXR1cm4gJ3JhdGknO1xuICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAxMikge1xuICAgICAgICAgICAgcmV0dXJuICdzb2thbGxpJztcbiAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgMTYpIHtcbiAgICAgICAgICAgIHJldHVybiAnZG9ucGFyYW0nO1xuICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAyMCkge1xuICAgICAgICAgICAgcmV0dXJuICdzYW5qZSc7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gJ3JhdGknO1xuICAgICAgICB9XG4gICAgfVxufSk7XG5cbi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBHdWphcmF0aSBbZ3VdXG4vLyEgYXV0aG9yIDogS2F1c2hpayBUaGFua2kgOiBodHRwczovL2dpdGh1Yi5jb20vS2F1c2hpazE5ODdcblxudmFyIHN5bWJvbE1hcCQ2ID0ge1xuICAgICAgICAnMSc6ICfgq6cnLFxuICAgICAgICAnMic6ICfgq6gnLFxuICAgICAgICAnMyc6ICfgq6knLFxuICAgICAgICAnNCc6ICfgq6onLFxuICAgICAgICAnNSc6ICfgq6snLFxuICAgICAgICAnNic6ICfgq6wnLFxuICAgICAgICAnNyc6ICfgq60nLFxuICAgICAgICAnOCc6ICfgq64nLFxuICAgICAgICAnOSc6ICfgq68nLFxuICAgICAgICAnMCc6ICfgq6YnXG4gICAgfTtcbnZhciBudW1iZXJNYXAkNSA9IHtcbiAgICAgICAgJ+Crpyc6ICcxJyxcbiAgICAgICAgJ+CrqCc6ICcyJyxcbiAgICAgICAgJ+CrqSc6ICczJyxcbiAgICAgICAgJ+Crqic6ICc0JyxcbiAgICAgICAgJ+Crqyc6ICc1JyxcbiAgICAgICAgJ+CrrCc6ICc2JyxcbiAgICAgICAgJ+CrrSc6ICc3JyxcbiAgICAgICAgJ+Crric6ICc4JyxcbiAgICAgICAgJ+Crryc6ICc5JyxcbiAgICAgICAgJ+Crpic6ICcwJ1xuICAgIH07XG5cbmhvb2tzLmRlZmluZUxvY2FsZSgnZ3UnLCB7XG4gICAgbW9udGhzOiAn4Kqc4Kq+4Kqo4KuN4Kqv4KuB4KqG4Kqw4KuAX+Cqq+Crh+CqrOCrjeCqsOCrgeCqhuCqsOCrgF/gqq7gqr7gqrDgq43gqppf4KqP4Kqq4KuN4Kqw4Kq/4KqyX+CqruCrh1/gqpzgq4Lgqqhf4Kqc4KuB4Kqy4Kq+4KqIX+CqkeCql+CquOCrjeCqn1/gqrjgqqrgq43gqp/gq4fgqq7gq43gqqzgqrBf4KqR4KqV4KuN4Kqf4KuN4Kqs4KqwX+CqqOCqteCrh+CqruCrjeCqrOCqsF/gqqHgqr/gqrjgq4fgqq7gq43gqqzgqrAnLnNwbGl0KCdfJyksXG4gICAgbW9udGhzU2hvcnQ6ICfgqpzgqr7gqqjgq43gqq/gq4EuX+Cqq+Crh+CqrOCrjeCqsOCrgS5f4Kqu4Kq+4Kqw4KuN4KqaX+Cqj+CqquCrjeCqsOCqvy5f4Kqu4KuHX+CqnOCrguCqqF/gqpzgq4HgqrLgqr4uX+CqkeCqly5f4Kq44Kqq4KuN4Kqf4KuHLl/gqpHgqpXgq43gqp/gq40uX+CqqOCqteCrhy5f4Kqh4Kq/4Kq44KuHLicuc3BsaXQoJ18nKSxcbiAgICBtb250aHNQYXJzZUV4YWN0OiB0cnVlLFxuICAgIHdlZWtkYXlzOiAn4Kqw4Kq14Kq/4Kq14Kq+4KqwX+CquOCri+CqruCqteCqvuCqsF/gqq7gqoLgqpfgqrPgqrXgqr7gqrBf4Kqs4KuB4Kqn4KuN4Kq14Kq+4KqwX+Cql+CrgeCqsOCrgeCqteCqvuCqsF/gqrbgq4HgqpXgq43gqrDgqrXgqr7gqrBf4Kq24Kqo4Kq/4Kq14Kq+4KqwJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzU2hvcnQ6ICfgqrDgqrXgqr9f4Kq44KuL4KquX+CqruCqguCql+Cqs1/gqqzgq4Hgqqfgq41f4KqX4KuB4Kqw4KuBX+CqtuCrgeCqleCrjeCqsF/gqrbgqqjgqr8nLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW46ICfgqrBf4Kq44KuLX+CqruCqgl/gqqzgq4Ff4KqX4KuBX+CqtuCrgV/gqrYnLnNwbGl0KCdfJyksXG4gICAgbG9uZ0RhdGVGb3JtYXQ6IHtcbiAgICAgICAgTFQ6ICdBIGg6bW0g4Kq14Kq+4KqX4KuN4Kqv4KuHJyxcbiAgICAgICAgTFRTOiAnQSBoOm1tOnNzIOCqteCqvuCql+CrjeCqr+CrhycsXG4gICAgICAgIEw6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgTEw6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgIExMTDogJ0QgTU1NTSBZWVlZLCBBIGg6bW0g4Kq14Kq+4KqX4KuN4Kqv4KuHJyxcbiAgICAgICAgTExMTDogJ2RkZGQsIEQgTU1NTSBZWVlZLCBBIGg6bW0g4Kq14Kq+4KqX4KuN4Kqv4KuHJ1xuICAgIH0sXG4gICAgY2FsZW5kYXI6IHtcbiAgICAgICAgc2FtZURheTogJ1vgqobgqpxdIExUJyxcbiAgICAgICAgbmV4dERheTogJ1vgqpXgqr7gqrLgq4ddIExUJyxcbiAgICAgICAgbmV4dFdlZWs6ICdkZGRkLCBMVCcsXG4gICAgICAgIGxhc3REYXk6ICdb4KqX4KqH4KqV4Kq+4Kqy4KuHXSBMVCcsXG4gICAgICAgIGxhc3RXZWVrOiAnW+CqquCqvuCqm+CqsuCqvl0gZGRkZCwgTFQnLFxuICAgICAgICBzYW1lRWxzZTogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWU6IHtcbiAgICAgICAgZnV0dXJlOiAnJXMg4Kqu4Kq+JyxcbiAgICAgICAgcGFzdDogJyVzIOCqquCrh+CqueCqsuCqvicsXG4gICAgICAgIHM6ICfgqoXgqq7gq4HgqpUg4Kqq4Kqz4KuLJyxcbiAgICAgICAgc3M6ICclZCDgqrjgq4fgqpXgqoLgqqEnLFxuICAgICAgICBtOiAn4KqP4KqVIOCqruCqv+CqqOCqv+CqnycsXG4gICAgICAgIG1tOiAnJWQg4Kqu4Kq/4Kqo4Kq/4KqfJyxcbiAgICAgICAgaDogJ+Cqj+CqlSDgqpXgqrLgqr7gqpUnLFxuICAgICAgICBoaDogJyVkIOCqleCqsuCqvuCqlScsXG4gICAgICAgIGQ6ICfgqo/gqpUg4Kqm4Kq/4Kq14Kq4JyxcbiAgICAgICAgZGQ6ICclZCDgqqbgqr/gqrXgqrgnLFxuICAgICAgICBNOiAn4KqP4KqVIOCqruCqueCqv+CqqOCriycsXG4gICAgICAgIE1NOiAnJWQg4Kqu4Kq54Kq/4Kqo4KuLJyxcbiAgICAgICAgeTogJ+Cqj+CqlSDgqrXgqrDgq43gqrcnLFxuICAgICAgICB5eTogJyVkIOCqteCqsOCrjeCqtydcbiAgICB9LFxuICAgIHByZXBhcnNlOiBmdW5jdGlvbiAoc3RyaW5nKSB7XG4gICAgICAgIHJldHVybiBzdHJpbmcucmVwbGFjZSgvW+Crp+CrqOCrqeCrquCrq+CrrOCrreCrruCrr+Crpl0vZywgZnVuY3Rpb24gKG1hdGNoKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVtYmVyTWFwJDVbbWF0Y2hdO1xuICAgICAgICB9KTtcbiAgICB9LFxuICAgIHBvc3Rmb3JtYXQ6IGZ1bmN0aW9uIChzdHJpbmcpIHtcbiAgICAgICAgcmV0dXJuIHN0cmluZy5yZXBsYWNlKC9cXGQvZywgZnVuY3Rpb24gKG1hdGNoKSB7XG4gICAgICAgICAgICByZXR1cm4gc3ltYm9sTWFwJDZbbWF0Y2hdO1xuICAgICAgICB9KTtcbiAgICB9LFxuICAgIC8vIEd1amFyYXRpIG5vdGF0aW9uIGZvciBtZXJpZGllbXMgYXJlIHF1aXRlIGZ1enp5IGluIHByYWN0aWNlLiBXaGlsZSB0aGVyZSBleGlzdHNcbiAgICAvLyBhIHJpZ2lkIG5vdGlvbiBvZiBhICdQYWhhcicgaXQgaXMgbm90IHVzZWQgYXMgcmlnaWRseSBpbiBtb2Rlcm4gR3VqYXJhdGkuXG4gICAgbWVyaWRpZW1QYXJzZTogL+CqsOCqvuCqpHzgqqzgqqrgq4vgqrB84Kq44Kq14Kq+4KqwfOCquOCqvuCqguCqnC8sXG4gICAgbWVyaWRpZW1Ib3VyOiBmdW5jdGlvbiAoaG91ciwgbWVyaWRpZW0pIHtcbiAgICAgICAgaWYgKGhvdXIgPT09IDEyKSB7XG4gICAgICAgICAgICBob3VyID0gMDtcbiAgICAgICAgfVxuICAgICAgICBpZiAobWVyaWRpZW0gPT09ICfgqrDgqr7gqqQnKSB7XG4gICAgICAgICAgICByZXR1cm4gaG91ciA8IDQgPyBob3VyIDogaG91ciArIDEyO1xuICAgICAgICB9IGVsc2UgaWYgKG1lcmlkaWVtID09PSAn4Kq44Kq14Kq+4KqwJykge1xuICAgICAgICAgICAgcmV0dXJuIGhvdXI7XG4gICAgICAgIH0gZWxzZSBpZiAobWVyaWRpZW0gPT09ICfgqqzgqqrgq4vgqrAnKSB7XG4gICAgICAgICAgICByZXR1cm4gaG91ciA+PSAxMCA/IGhvdXIgOiBob3VyICsgMTI7XG4gICAgICAgIH0gZWxzZSBpZiAobWVyaWRpZW0gPT09ICfgqrjgqr7gqoLgqpwnKSB7XG4gICAgICAgICAgICByZXR1cm4gaG91ciArIDEyO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBtZXJpZGllbTogZnVuY3Rpb24gKGhvdXIsIG1pbnV0ZSwgaXNMb3dlcikge1xuICAgICAgICBpZiAoaG91ciA8IDQpIHtcbiAgICAgICAgICAgIHJldHVybiAn4Kqw4Kq+4KqkJztcbiAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgMTApIHtcbiAgICAgICAgICAgIHJldHVybiAn4Kq44Kq14Kq+4KqwJztcbiAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgMTcpIHtcbiAgICAgICAgICAgIHJldHVybiAn4Kqs4Kqq4KuL4KqwJztcbiAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgMjApIHtcbiAgICAgICAgICAgIHJldHVybiAn4Kq44Kq+4KqC4KqcJztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiAn4Kqw4Kq+4KqkJztcbiAgICAgICAgfVxuICAgIH0sXG4gICAgd2Vlazoge1xuICAgICAgICBkb3c6IDAsIC8vIFN1bmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICBkb3k6IDYgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gMXN0IGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH1cbn0pO1xuXG4vLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogSGVicmV3IFtoZV1cbi8vISBhdXRob3IgOiBUb21lciBDb2hlbiA6IGh0dHBzOi8vZ2l0aHViLmNvbS90b21lclxuLy8hIGF1dGhvciA6IE1vc2hlIFNpbWFudG92IDogaHR0cHM6Ly9naXRodWIuY29tL0RldmVsb3BtZW50SUxcbi8vISBhdXRob3IgOiBUYWwgQXRlciA6IGh0dHBzOi8vZ2l0aHViLmNvbS9UYWxBdGVyXG5cbmhvb2tzLmRlZmluZUxvY2FsZSgnaGUnLCB7XG4gICAgbW9udGhzIDogJ9eZ16DXldeQ16hf16TXkdeo15XXkNeoX9ee16jXpV/XkNek16jXmdecX9ee15DXmV/XmdeV16DXmV/XmdeV15zXmV/XkNeV15LXldeh15hf16HXpNeY157XkdeoX9eQ15XXp9eY15XXkdeoX9eg15XXkdee15HXqF/Xk9em157XkdeoJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0IDogJ9eZ16DXldezX9ek15HXqNezX9ee16jXpV/XkNek16jXs1/XnteQ15lf15nXldeg15lf15nXldec15lf15DXldeS17Nf16HXpNeY17Nf15DXlden17Nf16DXldeR17Nf15PXptee17MnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXMgOiAn16jXkNep15XXn1/Xqdeg15lf16nXnNeZ16nXmV/XqNeR15nXoteZX9eX157Xmdep15lf16nXmdep15lf16nXkdeqJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzU2hvcnQgOiAn15DXs1/XkdezX9eS17Nf15PXs1/XlNezX9eV17Nf16nXsycuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbiA6ICfXkF/XkV/Xkl/Xk1/XlF/XlV/XqScuc3BsaXQoJ18nKSxcbiAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgTFQgOiAnSEg6bW0nLFxuICAgICAgICBMVFMgOiAnSEg6bW06c3MnLFxuICAgICAgICBMIDogJ0REL01NL1lZWVknLFxuICAgICAgICBMTCA6ICdEIFvXkV1NTU1NIFlZWVknLFxuICAgICAgICBMTEwgOiAnRCBb15FdTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgTExMTCA6ICdkZGRkLCBEIFvXkV1NTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICBsIDogJ0QvTS9ZWVlZJyxcbiAgICAgICAgbGwgOiAnRCBNTU0gWVlZWScsXG4gICAgICAgIGxsbCA6ICdEIE1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgbGxsbCA6ICdkZGQsIEQgTU1NIFlZWVkgSEg6bW0nXG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheSA6ICdb15TXmdeV150g15HWvl1MVCcsXG4gICAgICAgIG5leHREYXkgOiAnW9ee15fXqCDXkda+XUxUJyxcbiAgICAgICAgbmV4dFdlZWsgOiAnZGRkZCBb15HXqdei15RdIExUJyxcbiAgICAgICAgbGFzdERheSA6ICdb15DXqtee15XXnCDXkda+XUxUJyxcbiAgICAgICAgbGFzdFdlZWsgOiAnW9eR15nXldedXSBkZGRkIFvXlNeQ15fXqNeV158g15HXqdei15RdIExUJyxcbiAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJ9eR16LXldeTICVzJyxcbiAgICAgICAgcGFzdCA6ICfXnNek16DXmSAlcycsXG4gICAgICAgIHMgOiAn157Xodek16gg16nXoNeZ15XXqicsXG4gICAgICAgIHNzIDogJyVkINep16DXmdeV16onLFxuICAgICAgICBtIDogJ9eT16fXlCcsXG4gICAgICAgIG1tIDogJyVkINeT16fXldeqJyxcbiAgICAgICAgaCA6ICfXqdei15QnLFxuICAgICAgICBoaCA6IGZ1bmN0aW9uIChudW1iZXIpIHtcbiAgICAgICAgICAgIGlmIChudW1iZXIgPT09IDIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ9ep16LXqteZ15nXnSc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJyDXqdei15XXqic7XG4gICAgICAgIH0sXG4gICAgICAgIGQgOiAn15nXldedJyxcbiAgICAgICAgZGQgOiBmdW5jdGlvbiAobnVtYmVyKSB7XG4gICAgICAgICAgICBpZiAobnVtYmVyID09PSAyKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfXmdeV157XmdeZ150nO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICcg15nXnteZ150nO1xuICAgICAgICB9LFxuICAgICAgICBNIDogJ9eX15XXk9epJyxcbiAgICAgICAgTU0gOiBmdW5jdGlvbiAobnVtYmVyKSB7XG4gICAgICAgICAgICBpZiAobnVtYmVyID09PSAyKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfXl9eV15PXqdeZ15nXnSc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJyDXl9eV15PXqdeZ150nO1xuICAgICAgICB9LFxuICAgICAgICB5IDogJ9ep16DXlCcsXG4gICAgICAgIHl5IDogZnVuY3Rpb24gKG51bWJlcikge1xuICAgICAgICAgICAgaWYgKG51bWJlciA9PT0gMikge1xuICAgICAgICAgICAgICAgIHJldHVybiAn16nXoNeq15nXmdedJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAobnVtYmVyICUgMTAgPT09IDAgJiYgbnVtYmVyICE9PSAxMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAnINep16DXlCc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJyDXqdeg15nXnSc7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIG1lcmlkaWVtUGFyc2U6IC/XkNeX15RcItemfNec16TXoNeUXCLXpnzXkNeX16jXmSDXlNem15TXqNeZ15nXnXzXnNek16DXmSDXlNem15TXqNeZ15nXnXzXnNek16DXldeqINeR15XXp9eofNeR15HXlden16h815HXoteo15EvaSxcbiAgICBpc1BNIDogZnVuY3Rpb24gKGlucHV0KSB7XG4gICAgICAgIHJldHVybiAvXijXkNeX15RcItemfNeQ15fXqNeZINeU16bXlNeo15nXmdedfNeR16LXqNeRKSQvLnRlc3QoaW5wdXQpO1xuICAgIH0sXG4gICAgbWVyaWRpZW0gOiBmdW5jdGlvbiAoaG91ciwgbWludXRlLCBpc0xvd2VyKSB7XG4gICAgICAgIGlmIChob3VyIDwgNSkge1xuICAgICAgICAgICAgcmV0dXJuICfXnNek16DXldeqINeR15XXp9eoJztcbiAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgMTApIHtcbiAgICAgICAgICAgIHJldHVybiAn15HXkdeV16fXqCc7XG4gICAgICAgIH0gZWxzZSBpZiAoaG91ciA8IDEyKSB7XG4gICAgICAgICAgICByZXR1cm4gaXNMb3dlciA/ICfXnNek16DXlFwi16YnIDogJ9ec16TXoNeZINeU16bXlNeo15nXmdedJztcbiAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgMTgpIHtcbiAgICAgICAgICAgIHJldHVybiBpc0xvd2VyID8gJ9eQ15fXlFwi16YnIDogJ9eQ15fXqNeZINeU16bXlNeo15nXmdedJztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiAn15HXoteo15EnO1xuICAgICAgICB9XG4gICAgfVxufSk7XG5cbi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBIaW5kaSBbaGldXG4vLyEgYXV0aG9yIDogTWF5YW5rIFNpbmdoYWwgOiBodHRwczovL2dpdGh1Yi5jb20vbWF5YW5rc2luZ2hhbFxuXG52YXIgc3ltYm9sTWFwJDcgPSB7XG4gICAgJzEnOiAn4KWnJyxcbiAgICAnMic6ICfgpagnLFxuICAgICczJzogJ+ClqScsXG4gICAgJzQnOiAn4KWqJyxcbiAgICAnNSc6ICfgpasnLFxuICAgICc2JzogJ+ClrCcsXG4gICAgJzcnOiAn4KWtJyxcbiAgICAnOCc6ICfgpa4nLFxuICAgICc5JzogJ+ClrycsXG4gICAgJzAnOiAn4KWmJ1xufTtcbnZhciBudW1iZXJNYXAkNiA9IHtcbiAgICAn4KWnJzogJzEnLFxuICAgICfgpagnOiAnMicsXG4gICAgJ+ClqSc6ICczJyxcbiAgICAn4KWqJzogJzQnLFxuICAgICfgpasnOiAnNScsXG4gICAgJ+ClrCc6ICc2JyxcbiAgICAn4KWtJzogJzcnLFxuICAgICfgpa4nOiAnOCcsXG4gICAgJ+Clryc6ICc5JyxcbiAgICAn4KWmJzogJzAnXG59O1xuXG5ob29rcy5kZWZpbmVMb2NhbGUoJ2hpJywge1xuICAgIG1vbnRocyA6ICfgpJzgpKjgpLXgpLDgpYBf4KSr4KS84KSw4KS14KSw4KWAX+CkruCkvuCksOCljeCkml/gpIXgpKrgpY3gpLDgpYjgpLJf4KSu4KSIX+CknOClguCkqF/gpJzgpYHgpLLgpL7gpIhf4KSF4KSX4KS44KWN4KSkX+CkuOCkv+CkpOCkruCljeCkrOCksF/gpIXgpJXgpY3gpJ/gpYLgpKzgpLBf4KSo4KS14KSu4KWN4KSs4KSwX+CkpuCkv+CkuOCkruCljeCkrOCksCcuc3BsaXQoJ18nKSxcbiAgICBtb250aHNTaG9ydCA6ICfgpJzgpKguX+Ckq+CkvOCksC5f4KSu4KS+4KSw4KWN4KSaX+CkheCkquCljeCksOCliC5f4KSu4KSIX+CknOClguCkqF/gpJzgpYHgpLIuX+CkheCkly5f4KS44KS/4KSkLl/gpIXgpJXgpY3gpJ/gpYIuX+CkqOCktS5f4KSm4KS/4KS4Licuc3BsaXQoJ18nKSxcbiAgICBtb250aHNQYXJzZUV4YWN0OiB0cnVlLFxuICAgIHdlZWtkYXlzIDogJ+CksOCkteCkv+CkteCkvuCksF/gpLjgpYvgpK7gpLXgpL7gpLBf4KSu4KSC4KSX4KSy4KS14KS+4KSwX+CkrOClgeCkp+CkteCkvuCksF/gpJfgpYHgpLDgpYLgpLXgpL7gpLBf4KS24KWB4KSV4KWN4KSw4KS14KS+4KSwX+CktuCkqOCkv+CkteCkvuCksCcuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0IDogJ+CksOCkteCkv1/gpLjgpYvgpK5f4KSu4KSC4KSX4KSyX+CkrOClgeCkp1/gpJfgpYHgpLDgpYJf4KS24KWB4KSV4KWN4KSwX+CktuCkqOCkvycuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbiA6ICfgpLBf4KS44KWLX+CkruCkgl/gpKzgpYFf4KSX4KWBX+CktuClgV/gpLYnLnNwbGl0KCdfJyksXG4gICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgIExUIDogJ0EgaDptbSDgpKzgpJzgpYcnLFxuICAgICAgICBMVFMgOiAnQSBoOm1tOnNzIOCkrOCknOClhycsXG4gICAgICAgIEwgOiAnREQvTU0vWVlZWScsXG4gICAgICAgIExMIDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgTExMIDogJ0QgTU1NTSBZWVlZLCBBIGg6bW0g4KSs4KSc4KWHJyxcbiAgICAgICAgTExMTCA6ICdkZGRkLCBEIE1NTU0gWVlZWSwgQSBoOm1tIOCkrOCknOClhydcbiAgICB9LFxuICAgIGNhbGVuZGFyIDoge1xuICAgICAgICBzYW1lRGF5IDogJ1vgpIbgpJxdIExUJyxcbiAgICAgICAgbmV4dERheSA6ICdb4KSV4KSyXSBMVCcsXG4gICAgICAgIG5leHRXZWVrIDogJ2RkZGQsIExUJyxcbiAgICAgICAgbGFzdERheSA6ICdb4KSV4KSyXSBMVCcsXG4gICAgICAgIGxhc3RXZWVrIDogJ1vgpKrgpL/gpJvgpLLgpYddIGRkZGQsIExUJyxcbiAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJyVzIOCkruClh+CkgicsXG4gICAgICAgIHBhc3QgOiAnJXMg4KSq4KS54KSy4KWHJyxcbiAgICAgICAgcyA6ICfgpJXgpYHgpJsg4KS54KWAIOCkleCljeCkt+CkoycsXG4gICAgICAgIHNzIDogJyVkIOCkuOClh+CkleCkguCkoScsXG4gICAgICAgIG0gOiAn4KSP4KSVIOCkruCkv+CkqOCknycsXG4gICAgICAgIG1tIDogJyVkIOCkruCkv+CkqOCknycsXG4gICAgICAgIGggOiAn4KSP4KSVIOCkmOCkguCkn+CkvicsXG4gICAgICAgIGhoIDogJyVkIOCkmOCkguCkn+ClhycsXG4gICAgICAgIGQgOiAn4KSP4KSVIOCkpuCkv+CkqCcsXG4gICAgICAgIGRkIDogJyVkIOCkpuCkv+CkqCcsXG4gICAgICAgIE0gOiAn4KSP4KSVIOCkruCkueClgOCkqOClhycsXG4gICAgICAgIE1NIDogJyVkIOCkruCkueClgOCkqOClhycsXG4gICAgICAgIHkgOiAn4KSP4KSVIOCkteCksOCljeCktycsXG4gICAgICAgIHl5IDogJyVkIOCkteCksOCljeCktydcbiAgICB9LFxuICAgIHByZXBhcnNlOiBmdW5jdGlvbiAoc3RyaW5nKSB7XG4gICAgICAgIHJldHVybiBzdHJpbmcucmVwbGFjZSgvW+Clp+ClqOClqeClquClq+ClrOClreClruClr+Clpl0vZywgZnVuY3Rpb24gKG1hdGNoKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVtYmVyTWFwJDZbbWF0Y2hdO1xuICAgICAgICB9KTtcbiAgICB9LFxuICAgIHBvc3Rmb3JtYXQ6IGZ1bmN0aW9uIChzdHJpbmcpIHtcbiAgICAgICAgcmV0dXJuIHN0cmluZy5yZXBsYWNlKC9cXGQvZywgZnVuY3Rpb24gKG1hdGNoKSB7XG4gICAgICAgICAgICByZXR1cm4gc3ltYm9sTWFwJDdbbWF0Y2hdO1xuICAgICAgICB9KTtcbiAgICB9LFxuICAgIC8vIEhpbmRpIG5vdGF0aW9uIGZvciBtZXJpZGllbXMgYXJlIHF1aXRlIGZ1enp5IGluIHByYWN0aWNlLiBXaGlsZSB0aGVyZSBleGlzdHNcbiAgICAvLyBhIHJpZ2lkIG5vdGlvbiBvZiBhICdQYWhhcicgaXQgaXMgbm90IHVzZWQgYXMgcmlnaWRseSBpbiBtb2Rlcm4gSGluZGkuXG4gICAgbWVyaWRpZW1QYXJzZTogL+CksOCkvuCkpHzgpLjgpYHgpKzgpLl84KSm4KWL4KSq4KS54KSwfOCktuCkvuCkri8sXG4gICAgbWVyaWRpZW1Ib3VyIDogZnVuY3Rpb24gKGhvdXIsIG1lcmlkaWVtKSB7XG4gICAgICAgIGlmIChob3VyID09PSAxMikge1xuICAgICAgICAgICAgaG91ciA9IDA7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG1lcmlkaWVtID09PSAn4KSw4KS+4KSkJykge1xuICAgICAgICAgICAgcmV0dXJuIGhvdXIgPCA0ID8gaG91ciA6IGhvdXIgKyAxMjtcbiAgICAgICAgfSBlbHNlIGlmIChtZXJpZGllbSA9PT0gJ+CkuOClgeCkrOCkuScpIHtcbiAgICAgICAgICAgIHJldHVybiBob3VyO1xuICAgICAgICB9IGVsc2UgaWYgKG1lcmlkaWVtID09PSAn4KSm4KWL4KSq4KS54KSwJykge1xuICAgICAgICAgICAgcmV0dXJuIGhvdXIgPj0gMTAgPyBob3VyIDogaG91ciArIDEyO1xuICAgICAgICB9IGVsc2UgaWYgKG1lcmlkaWVtID09PSAn4KS24KS+4KSuJykge1xuICAgICAgICAgICAgcmV0dXJuIGhvdXIgKyAxMjtcbiAgICAgICAgfVxuICAgIH0sXG4gICAgbWVyaWRpZW0gOiBmdW5jdGlvbiAoaG91ciwgbWludXRlLCBpc0xvd2VyKSB7XG4gICAgICAgIGlmIChob3VyIDwgNCkge1xuICAgICAgICAgICAgcmV0dXJuICfgpLDgpL7gpKQnO1xuICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAxMCkge1xuICAgICAgICAgICAgcmV0dXJuICfgpLjgpYHgpKzgpLknO1xuICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAxNykge1xuICAgICAgICAgICAgcmV0dXJuICfgpKbgpYvgpKrgpLngpLAnO1xuICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAyMCkge1xuICAgICAgICAgICAgcmV0dXJuICfgpLbgpL7gpK4nO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuICfgpLDgpL7gpKQnO1xuICAgICAgICB9XG4gICAgfSxcbiAgICB3ZWVrIDoge1xuICAgICAgICBkb3cgOiAwLCAvLyBTdW5kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogNiAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gMXN0IGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH1cbn0pO1xuXG4vLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogQ3JvYXRpYW4gW2hyXVxuLy8hIGF1dGhvciA6IEJvamFuIE1hcmtvdmnEhyA6IGh0dHBzOi8vZ2l0aHViLmNvbS9ibWFya292aWNcblxuZnVuY3Rpb24gdHJhbnNsYXRlJDMobnVtYmVyLCB3aXRob3V0U3VmZml4LCBrZXkpIHtcbiAgICB2YXIgcmVzdWx0ID0gbnVtYmVyICsgJyAnO1xuICAgIHN3aXRjaCAoa2V5KSB7XG4gICAgICAgIGNhc2UgJ3NzJzpcbiAgICAgICAgICAgIGlmIChudW1iZXIgPT09IDEpIHtcbiAgICAgICAgICAgICAgICByZXN1bHQgKz0gJ3Nla3VuZGEnO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChudW1iZXIgPT09IDIgfHwgbnVtYmVyID09PSAzIHx8IG51bWJlciA9PT0gNCkge1xuICAgICAgICAgICAgICAgIHJlc3VsdCArPSAnc2VrdW5kZSc7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlc3VsdCArPSAnc2VrdW5kaSc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICBjYXNlICdtJzpcbiAgICAgICAgICAgIHJldHVybiB3aXRob3V0U3VmZml4ID8gJ2plZG5hIG1pbnV0YScgOiAnamVkbmUgbWludXRlJztcbiAgICAgICAgY2FzZSAnbW0nOlxuICAgICAgICAgICAgaWYgKG51bWJlciA9PT0gMSkge1xuICAgICAgICAgICAgICAgIHJlc3VsdCArPSAnbWludXRhJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAobnVtYmVyID09PSAyIHx8IG51bWJlciA9PT0gMyB8fCBudW1iZXIgPT09IDQpIHtcbiAgICAgICAgICAgICAgICByZXN1bHQgKz0gJ21pbnV0ZSc7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlc3VsdCArPSAnbWludXRhJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIGNhc2UgJ2gnOlxuICAgICAgICAgICAgcmV0dXJuIHdpdGhvdXRTdWZmaXggPyAnamVkYW4gc2F0JyA6ICdqZWRub2cgc2F0YSc7XG4gICAgICAgIGNhc2UgJ2hoJzpcbiAgICAgICAgICAgIGlmIChudW1iZXIgPT09IDEpIHtcbiAgICAgICAgICAgICAgICByZXN1bHQgKz0gJ3NhdCc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKG51bWJlciA9PT0gMiB8fCBudW1iZXIgPT09IDMgfHwgbnVtYmVyID09PSA0KSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ICs9ICdzYXRhJztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ICs9ICdzYXRpJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIGNhc2UgJ2RkJzpcbiAgICAgICAgICAgIGlmIChudW1iZXIgPT09IDEpIHtcbiAgICAgICAgICAgICAgICByZXN1bHQgKz0gJ2Rhbic7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlc3VsdCArPSAnZGFuYSc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICBjYXNlICdNTSc6XG4gICAgICAgICAgICBpZiAobnVtYmVyID09PSAxKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ICs9ICdtamVzZWMnO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChudW1iZXIgPT09IDIgfHwgbnVtYmVyID09PSAzIHx8IG51bWJlciA9PT0gNCkge1xuICAgICAgICAgICAgICAgIHJlc3VsdCArPSAnbWplc2VjYSc7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlc3VsdCArPSAnbWplc2VjaSc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICBjYXNlICd5eSc6XG4gICAgICAgICAgICBpZiAobnVtYmVyID09PSAxKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ICs9ICdnb2RpbmEnO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChudW1iZXIgPT09IDIgfHwgbnVtYmVyID09PSAzIHx8IG51bWJlciA9PT0gNCkge1xuICAgICAgICAgICAgICAgIHJlc3VsdCArPSAnZ29kaW5lJztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ICs9ICdnb2RpbmEnO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG59XG5cbmhvb2tzLmRlZmluZUxvY2FsZSgnaHInLCB7XG4gICAgbW9udGhzIDoge1xuICAgICAgICBmb3JtYXQ6ICdzaWplxI1uamFfdmVsamHEjWVfb8W+dWprYV90cmF2bmphX3N2aWJuamFfbGlwbmphX3NycG5qYV9rb2xvdm96YV9ydWpuYV9saXN0b3BhZGFfc3R1ZGVub2dhX3Byb3NpbmNhJy5zcGxpdCgnXycpLFxuICAgICAgICBzdGFuZGFsb25lOiAnc2lqZcSNYW5qX3ZlbGphxI1hX2/FvnVqYWtfdHJhdmFual9zdmliYW5qX2xpcGFual9zcnBhbmpfa29sb3Zvel9ydWphbl9saXN0b3BhZF9zdHVkZW5pX3Byb3NpbmFjJy5zcGxpdCgnXycpXG4gICAgfSxcbiAgICBtb250aHNTaG9ydCA6ICdzaWouX3ZlbGouX2/FvnUuX3RyYS5fc3ZpLl9saXAuX3NycC5fa29sLl9ydWouX2xpcy5fc3R1Ll9wcm8uJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1BhcnNlRXhhY3Q6IHRydWUsXG4gICAgd2Vla2RheXMgOiAnbmVkamVsamFfcG9uZWRqZWxqYWtfdXRvcmFrX3NyaWplZGFfxI1ldHZydGFrX3BldGFrX3N1Ym90YScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0IDogJ25lZC5fcG9uLl91dG8uX3NyaS5fxI1ldC5fcGV0Ll9zdWIuJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzTWluIDogJ25lX3BvX3V0X3NyX8SNZV9wZV9zdScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdIOm1tJyxcbiAgICAgICAgTFRTIDogJ0g6bW06c3MnLFxuICAgICAgICBMIDogJ0RELk1NLllZWVknLFxuICAgICAgICBMTCA6ICdELiBNTU1NIFlZWVknLFxuICAgICAgICBMTEwgOiAnRC4gTU1NTSBZWVlZIEg6bW0nLFxuICAgICAgICBMTExMIDogJ2RkZGQsIEQuIE1NTU0gWVlZWSBIOm1tJ1xuICAgIH0sXG4gICAgY2FsZW5kYXIgOiB7XG4gICAgICAgIHNhbWVEYXkgIDogJ1tkYW5hcyB1XSBMVCcsXG4gICAgICAgIG5leHREYXkgIDogJ1tzdXRyYSB1XSBMVCcsXG4gICAgICAgIG5leHRXZWVrIDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgc3dpdGNoICh0aGlzLmRheSgpKSB7XG4gICAgICAgICAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1t1XSBbbmVkamVsanVdIFt1XSBMVCc7XG4gICAgICAgICAgICAgICAgY2FzZSAzOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1t1XSBbc3JpamVkdV0gW3VdIExUJztcbiAgICAgICAgICAgICAgICBjYXNlIDY6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnW3VdIFtzdWJvdHVdIFt1XSBMVCc7XG4gICAgICAgICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgICAgIGNhc2UgMjpcbiAgICAgICAgICAgICAgICBjYXNlIDQ6XG4gICAgICAgICAgICAgICAgY2FzZSA1OlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1t1XSBkZGRkIFt1XSBMVCc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIGxhc3REYXkgIDogJ1tqdcSNZXIgdV0gTFQnLFxuICAgICAgICBsYXN0V2VlayA6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHN3aXRjaCAodGhpcy5kYXkoKSkge1xuICAgICAgICAgICAgICAgIGNhc2UgMDpcbiAgICAgICAgICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnW3Byb8WhbHVdIGRkZGQgW3VdIExUJztcbiAgICAgICAgICAgICAgICBjYXNlIDY6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnW3Byb8WhbGVdIFtzdWJvdGVdIFt1XSBMVCc7XG4gICAgICAgICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgICAgIGNhc2UgMjpcbiAgICAgICAgICAgICAgICBjYXNlIDQ6XG4gICAgICAgICAgICAgICAgY2FzZSA1OlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1twcm/FoWxpXSBkZGRkIFt1XSBMVCc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6ICd6YSAlcycsXG4gICAgICAgIHBhc3QgICA6ICdwcmlqZSAlcycsXG4gICAgICAgIHMgICAgICA6ICdwYXIgc2VrdW5kaScsXG4gICAgICAgIHNzICAgICA6IHRyYW5zbGF0ZSQzLFxuICAgICAgICBtICAgICAgOiB0cmFuc2xhdGUkMyxcbiAgICAgICAgbW0gICAgIDogdHJhbnNsYXRlJDMsXG4gICAgICAgIGggICAgICA6IHRyYW5zbGF0ZSQzLFxuICAgICAgICBoaCAgICAgOiB0cmFuc2xhdGUkMyxcbiAgICAgICAgZCAgICAgIDogJ2RhbicsXG4gICAgICAgIGRkICAgICA6IHRyYW5zbGF0ZSQzLFxuICAgICAgICBNICAgICAgOiAnbWplc2VjJyxcbiAgICAgICAgTU0gICAgIDogdHJhbnNsYXRlJDMsXG4gICAgICAgIHkgICAgICA6ICdnb2RpbnUnLFxuICAgICAgICB5eSAgICAgOiB0cmFuc2xhdGUkM1xuICAgIH0sXG4gICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9XFwuLyxcbiAgICBvcmRpbmFsIDogJyVkLicsXG4gICAgd2VlayA6IHtcbiAgICAgICAgZG93IDogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgIGRveSA6IDcgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDFzdCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICB9XG59KTtcblxuLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSA6IEh1bmdhcmlhbiBbaHVdXG4vLyEgYXV0aG9yIDogQWRhbSBCcnVubmVyIDogaHR0cHM6Ly9naXRodWIuY29tL2FkYW1icnVubmVyXG5cbnZhciB3ZWVrRW5kaW5ncyA9ICd2YXPDoXJuYXAgaMOpdGbFkW4ga2VkZGVuIHN6ZXJkw6FuIGNzw7x0w7ZydMO2a8O2biBww6ludGVrZW4gc3pvbWJhdG9uJy5zcGxpdCgnICcpO1xuZnVuY3Rpb24gdHJhbnNsYXRlJDQobnVtYmVyLCB3aXRob3V0U3VmZml4LCBrZXksIGlzRnV0dXJlKSB7XG4gICAgdmFyIG51bSA9IG51bWJlcjtcbiAgICBzd2l0Y2ggKGtleSkge1xuICAgICAgICBjYXNlICdzJzpcbiAgICAgICAgICAgIHJldHVybiAoaXNGdXR1cmUgfHwgd2l0aG91dFN1ZmZpeCkgPyAnbsOpaMOhbnkgbcOhc29kcGVyYycgOiAnbsOpaMOhbnkgbcOhc29kcGVyY2UnO1xuICAgICAgICBjYXNlICdzcyc6XG4gICAgICAgICAgICByZXR1cm4gbnVtICsgKGlzRnV0dXJlIHx8IHdpdGhvdXRTdWZmaXgpID8gJyBtw6Fzb2RwZXJjJyA6ICcgbcOhc29kcGVyY2UnO1xuICAgICAgICBjYXNlICdtJzpcbiAgICAgICAgICAgIHJldHVybiAnZWd5JyArIChpc0Z1dHVyZSB8fCB3aXRob3V0U3VmZml4ID8gJyBwZXJjJyA6ICcgcGVyY2UnKTtcbiAgICAgICAgY2FzZSAnbW0nOlxuICAgICAgICAgICAgcmV0dXJuIG51bSArIChpc0Z1dHVyZSB8fCB3aXRob3V0U3VmZml4ID8gJyBwZXJjJyA6ICcgcGVyY2UnKTtcbiAgICAgICAgY2FzZSAnaCc6XG4gICAgICAgICAgICByZXR1cm4gJ2VneScgKyAoaXNGdXR1cmUgfHwgd2l0aG91dFN1ZmZpeCA/ICcgw7NyYScgOiAnIMOzcsOhamEnKTtcbiAgICAgICAgY2FzZSAnaGgnOlxuICAgICAgICAgICAgcmV0dXJuIG51bSArIChpc0Z1dHVyZSB8fCB3aXRob3V0U3VmZml4ID8gJyDDs3JhJyA6ICcgw7Nyw6FqYScpO1xuICAgICAgICBjYXNlICdkJzpcbiAgICAgICAgICAgIHJldHVybiAnZWd5JyArIChpc0Z1dHVyZSB8fCB3aXRob3V0U3VmZml4ID8gJyBuYXAnIDogJyBuYXBqYScpO1xuICAgICAgICBjYXNlICdkZCc6XG4gICAgICAgICAgICByZXR1cm4gbnVtICsgKGlzRnV0dXJlIHx8IHdpdGhvdXRTdWZmaXggPyAnIG5hcCcgOiAnIG5hcGphJyk7XG4gICAgICAgIGNhc2UgJ00nOlxuICAgICAgICAgICAgcmV0dXJuICdlZ3knICsgKGlzRnV0dXJlIHx8IHdpdGhvdXRTdWZmaXggPyAnIGjDs25hcCcgOiAnIGjDs25hcGphJyk7XG4gICAgICAgIGNhc2UgJ01NJzpcbiAgICAgICAgICAgIHJldHVybiBudW0gKyAoaXNGdXR1cmUgfHwgd2l0aG91dFN1ZmZpeCA/ICcgaMOzbmFwJyA6ICcgaMOzbmFwamEnKTtcbiAgICAgICAgY2FzZSAneSc6XG4gICAgICAgICAgICByZXR1cm4gJ2VneScgKyAoaXNGdXR1cmUgfHwgd2l0aG91dFN1ZmZpeCA/ICcgw6l2JyA6ICcgw6l2ZScpO1xuICAgICAgICBjYXNlICd5eSc6XG4gICAgICAgICAgICByZXR1cm4gbnVtICsgKGlzRnV0dXJlIHx8IHdpdGhvdXRTdWZmaXggPyAnIMOpdicgOiAnIMOpdmUnKTtcbiAgICB9XG4gICAgcmV0dXJuICcnO1xufVxuZnVuY3Rpb24gd2Vlayhpc0Z1dHVyZSkge1xuICAgIHJldHVybiAoaXNGdXR1cmUgPyAnJyA6ICdbbcO6bHRdICcpICsgJ1snICsgd2Vla0VuZGluZ3NbdGhpcy5kYXkoKV0gKyAnXSBMVFsta29yXSc7XG59XG5cbmhvb2tzLmRlZmluZUxvY2FsZSgnaHUnLCB7XG4gICAgbW9udGhzIDogJ2phbnXDoXJfZmVicnXDoXJfbcOhcmNpdXNfw6FwcmlsaXNfbcOhanVzX2rDum5pdXNfasO6bGl1c19hdWd1c3p0dXNfc3plcHRlbWJlcl9va3TDs2Jlcl9ub3ZlbWJlcl9kZWNlbWJlcicuc3BsaXQoJ18nKSxcbiAgICBtb250aHNTaG9ydCA6ICdqYW5fZmViX23DoXJjX8OhcHJfbcOhal9qw7puX2rDumxfYXVnX3N6ZXB0X29rdF9ub3ZfZGVjJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzIDogJ3Zhc8Ohcm5hcF9ow6l0ZsWRX2tlZGRfc3plcmRhX2Nzw7x0w7ZydMO2a19ww6ludGVrX3N6b21iYXQnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydCA6ICd2YXNfaMOpdF9rZWRkX3N6ZV9jc8O8dF9ww6luX3N6bycuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbiA6ICd2X2hfa19zemVfY3NfcF9zem8nLnNwbGl0KCdfJyksXG4gICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgIExUIDogJ0g6bW0nLFxuICAgICAgICBMVFMgOiAnSDptbTpzcycsXG4gICAgICAgIEwgOiAnWVlZWS5NTS5ERC4nLFxuICAgICAgICBMTCA6ICdZWVlZLiBNTU1NIEQuJyxcbiAgICAgICAgTExMIDogJ1lZWVkuIE1NTU0gRC4gSDptbScsXG4gICAgICAgIExMTEwgOiAnWVlZWS4gTU1NTSBELiwgZGRkZCBIOm1tJ1xuICAgIH0sXG4gICAgbWVyaWRpZW1QYXJzZTogL2RlfGR1L2ksXG4gICAgaXNQTTogZnVuY3Rpb24gKGlucHV0KSB7XG4gICAgICAgIHJldHVybiBpbnB1dC5jaGFyQXQoMSkudG9Mb3dlckNhc2UoKSA9PT0gJ3UnO1xuICAgIH0sXG4gICAgbWVyaWRpZW0gOiBmdW5jdGlvbiAoaG91cnMsIG1pbnV0ZXMsIGlzTG93ZXIpIHtcbiAgICAgICAgaWYgKGhvdXJzIDwgMTIpIHtcbiAgICAgICAgICAgIHJldHVybiBpc0xvd2VyID09PSB0cnVlID8gJ2RlJyA6ICdERSc7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gaXNMb3dlciA9PT0gdHJ1ZSA/ICdkdScgOiAnRFUnO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheSA6ICdbbWFdIExUWy1rb3JdJyxcbiAgICAgICAgbmV4dERheSA6ICdbaG9sbmFwXSBMVFsta29yXScsXG4gICAgICAgIG5leHRXZWVrIDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIHdlZWsuY2FsbCh0aGlzLCB0cnVlKTtcbiAgICAgICAgfSxcbiAgICAgICAgbGFzdERheSA6ICdbdGVnbmFwXSBMVFsta29yXScsXG4gICAgICAgIGxhc3RXZWVrIDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIHdlZWsuY2FsbCh0aGlzLCBmYWxzZSk7XG4gICAgICAgIH0sXG4gICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6ICclcyBtw7psdmEnLFxuICAgICAgICBwYXN0IDogJyVzJyxcbiAgICAgICAgcyA6IHRyYW5zbGF0ZSQ0LFxuICAgICAgICBzcyA6IHRyYW5zbGF0ZSQ0LFxuICAgICAgICBtIDogdHJhbnNsYXRlJDQsXG4gICAgICAgIG1tIDogdHJhbnNsYXRlJDQsXG4gICAgICAgIGggOiB0cmFuc2xhdGUkNCxcbiAgICAgICAgaGggOiB0cmFuc2xhdGUkNCxcbiAgICAgICAgZCA6IHRyYW5zbGF0ZSQ0LFxuICAgICAgICBkZCA6IHRyYW5zbGF0ZSQ0LFxuICAgICAgICBNIDogdHJhbnNsYXRlJDQsXG4gICAgICAgIE1NIDogdHJhbnNsYXRlJDQsXG4gICAgICAgIHkgOiB0cmFuc2xhdGUkNCxcbiAgICAgICAgeXkgOiB0cmFuc2xhdGUkNFxuICAgIH0sXG4gICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9XFwuLyxcbiAgICBvcmRpbmFsIDogJyVkLicsXG4gICAgd2VlayA6IHtcbiAgICAgICAgZG93IDogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgIGRveSA6IDQgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDR0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICB9XG59KTtcblxuLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSA6IEFybWVuaWFuIFtoeS1hbV1cbi8vISBhdXRob3IgOiBBcm1lbmRhcmFieWFuIDogaHR0cHM6Ly9naXRodWIuY29tL2FybWVuZGFyYWJ5YW5cblxuaG9va3MuZGVmaW5lTG9jYWxlKCdoeS1hbScsIHtcbiAgICBtb250aHMgOiB7XG4gICAgICAgIGZvcm1hdDogJ9Ww1bjWgtW21b7VodaA1atf1oPVpdW/1oDVvtWh1oDVq1/VtNWh1oDVv9WrX9Wh1brWgNWr1azVq1/VtNWh1bXVq9W91atf1bDVuNaC1bbVq9W91atf1bDVuNaC1azVq9W91atf1oXVo9W41b3Vv9W41b3Vq1/VvdWl1brVv9Wl1bTVotWl1oDVq1/VsNW41a/Vv9Wl1bTVotWl1oDVq1/VttW41bXVpdW01aLVpdaA1atf1aTVpdWv1b/VpdW01aLVpdaA1asnLnNwbGl0KCdfJyksXG4gICAgICAgIHN0YW5kYWxvbmU6ICfVsNW41oLVttW+1aHWgF/Wg9Wl1b/WgNW+1aHWgF/VtNWh1oDVv1/VodW61oDVq9WsX9W01aHVtdWr1b1f1bDVuNaC1bbVq9W9X9Ww1bjWgtWs1avVvV/WhdWj1bjVvdW/1bjVvV/VvdWl1brVv9Wl1bTVotWl1oBf1bDVuNWv1b/VpdW01aLVpdaAX9W21bjVtdWl1bTVotWl1oBf1aTVpdWv1b/VpdW01aLVpdaAJy5zcGxpdCgnXycpXG4gICAgfSxcbiAgICBtb250aHNTaG9ydCA6ICfVsNW21b5f1oPVv9aAX9W01oDVv1/VodW61oBf1bTVtdW9X9Ww1bbVvV/VsNWs1b1f1oXVo9W9X9W91brVv1/VsNWv1b9f1bbVtNWiX9Wk1a/Vvycuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5cyA6ICfVr9Wr1oDVodWv1atf1aXWgNWv1bjWgtW31aHVotWp1atf1aXWgNWl1oTVt9Wh1aLVqdWrX9W51bjWgNWl1oTVt9Wh1aLVqdWrX9Ww1avVttWj1bfVodWi1anVq1/VuNaC1oDVotWh1alf1bfVodWi1aHVqScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0IDogJ9Wv1oDVr1/VpdaA1a9f1aXWgNaEX9W51oDWhF/VsNW21aNf1bjWgtaA1aJf1bfVotWpJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzTWluIDogJ9Wv1oDVr1/VpdaA1a9f1aXWgNaEX9W51oDWhF/VsNW21aNf1bjWgtaA1aJf1bfVotWpJy5zcGxpdCgnXycpLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdISDptbScsXG4gICAgICAgIExUUyA6ICdISDptbTpzcycsXG4gICAgICAgIEwgOiAnREQuTU0uWVlZWScsXG4gICAgICAgIExMIDogJ0QgTU1NTSBZWVlZINWpLicsXG4gICAgICAgIExMTCA6ICdEIE1NTU0gWVlZWSDVqS4sIEhIOm1tJyxcbiAgICAgICAgTExMTCA6ICdkZGRkLCBEIE1NTU0gWVlZWSDVqS4sIEhIOm1tJ1xuICAgIH0sXG4gICAgY2FsZW5kYXIgOiB7XG4gICAgICAgIHNhbWVEYXk6ICdb1aHVtdW91oXWgF0gTFQnLFxuICAgICAgICBuZXh0RGF5OiAnW9W+1aHVstWoXSBMVCcsXG4gICAgICAgIGxhc3REYXk6ICdb1aXWgNWl1a9dIExUJyxcbiAgICAgICAgbmV4dFdlZWs6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiAnZGRkZCBb1oXWgNWoINWq1aHVtNWoXSBMVCc7XG4gICAgICAgIH0sXG4gICAgICAgIGxhc3RXZWVrOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gJ1vVodW21oHVodWuXSBkZGRkIFvWhdaA1agg1arVodW01ahdIExUJztcbiAgICAgICAgfSxcbiAgICAgICAgc2FtZUVsc2U6ICdMJ1xuICAgIH0sXG4gICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICBmdXR1cmUgOiAnJXMg1bDVpdW/1bgnLFxuICAgICAgICBwYXN0IDogJyVzINWh1bzVodW7JyxcbiAgICAgICAgcyA6ICfVtNWrINaE1aHVttWrINW+1aHVtdaA1a/VtdWh1bYnLFxuICAgICAgICBzcyA6ICclZCDVvtWh1bXWgNWv1bXVodW2JyxcbiAgICAgICAgbSA6ICfWgNW41brVpScsXG4gICAgICAgIG1tIDogJyVkINaA1bjVutWlJyxcbiAgICAgICAgaCA6ICfVqtWh1bQnLFxuICAgICAgICBoaCA6ICclZCDVqtWh1bQnLFxuICAgICAgICBkIDogJ9aF1oAnLFxuICAgICAgICBkZCA6ICclZCDWhdaAJyxcbiAgICAgICAgTSA6ICfVodW01avVvScsXG4gICAgICAgIE1NIDogJyVkINWh1bTVq9W9JyxcbiAgICAgICAgeSA6ICfVv9Wh1oDVqycsXG4gICAgICAgIHl5IDogJyVkINW/1aHWgNWrJ1xuICAgIH0sXG4gICAgbWVyaWRpZW1QYXJzZTogL9Wj1avVt9Wl1oDVvtWhfNWh1bzVodW+1bjVv9W+1aF81oHVpdaA1aXVr9W+1aF81aXWgNWl1a/VuNW11aHVti8sXG4gICAgaXNQTTogZnVuY3Rpb24gKGlucHV0KSB7XG4gICAgICAgIHJldHVybiAvXijWgdWl1oDVpdWv1b7VoXzVpdaA1aXVr9W41bXVodW2KSQvLnRlc3QoaW5wdXQpO1xuICAgIH0sXG4gICAgbWVyaWRpZW0gOiBmdW5jdGlvbiAoaG91cikge1xuICAgICAgICBpZiAoaG91ciA8IDQpIHtcbiAgICAgICAgICAgIHJldHVybiAn1aPVq9W31aXWgNW+1aEnO1xuICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAxMikge1xuICAgICAgICAgICAgcmV0dXJuICfVodW81aHVvtW41b/VvtWhJztcbiAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgMTcpIHtcbiAgICAgICAgICAgIHJldHVybiAn1oHVpdaA1aXVr9W+1aEnO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuICfVpdaA1aXVr9W41bXVodW2JztcbiAgICAgICAgfVxuICAgIH0sXG4gICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9fFxcZHsxLDJ9LSjVq9W2fNaA1aQpLyxcbiAgICBvcmRpbmFsOiBmdW5jdGlvbiAobnVtYmVyLCBwZXJpb2QpIHtcbiAgICAgICAgc3dpdGNoIChwZXJpb2QpIHtcbiAgICAgICAgICAgIGNhc2UgJ0RERCc6XG4gICAgICAgICAgICBjYXNlICd3JzpcbiAgICAgICAgICAgIGNhc2UgJ1cnOlxuICAgICAgICAgICAgY2FzZSAnREREbyc6XG4gICAgICAgICAgICAgICAgaWYgKG51bWJlciA9PT0gMSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJy3Vq9W2JztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICct1oDVpCc7XG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXI7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIHdlZWsgOiB7XG4gICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICBkb3kgOiA3ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiAxc3QgaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgfVxufSk7XG5cbi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBJbmRvbmVzaWFuIFtpZF1cbi8vISBhdXRob3IgOiBNb2hhbW1hZCBTYXRyaW8gVXRvbW8gOiBodHRwczovL2dpdGh1Yi5jb20vdHlva1xuLy8hIHJlZmVyZW5jZTogaHR0cDovL2lkLndpa2lzb3VyY2Uub3JnL3dpa2kvUGVkb21hbl9VbXVtX0VqYWFuX0JhaGFzYV9JbmRvbmVzaWFfeWFuZ19EaXNlbXB1cm5ha2FuXG5cbmhvb2tzLmRlZmluZUxvY2FsZSgnaWQnLCB7XG4gICAgbW9udGhzIDogJ0phbnVhcmlfRmVicnVhcmlfTWFyZXRfQXByaWxfTWVpX0p1bmlfSnVsaV9BZ3VzdHVzX1NlcHRlbWJlcl9Pa3RvYmVyX05vdmVtYmVyX0Rlc2VtYmVyJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0IDogJ0phbl9GZWJfTWFyX0Fwcl9NZWlfSnVuX0p1bF9BZ3NfU2VwX09rdF9Ob3ZfRGVzJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzIDogJ01pbmdndV9TZW5pbl9TZWxhc2FfUmFidV9LYW1pc19KdW1hdF9TYWJ0dScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0IDogJ01pbl9TZW5fU2VsX1JhYl9LYW1fSnVtX1NhYicuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbiA6ICdNZ19Tbl9TbF9SYl9LbV9KbV9TYicuc3BsaXQoJ18nKSxcbiAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgTFQgOiAnSEgubW0nLFxuICAgICAgICBMVFMgOiAnSEgubW0uc3MnLFxuICAgICAgICBMIDogJ0REL01NL1lZWVknLFxuICAgICAgICBMTCA6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgIExMTCA6ICdEIE1NTU0gWVlZWSBbcHVrdWxdIEhILm1tJyxcbiAgICAgICAgTExMTCA6ICdkZGRkLCBEIE1NTU0gWVlZWSBbcHVrdWxdIEhILm1tJ1xuICAgIH0sXG4gICAgbWVyaWRpZW1QYXJzZTogL3BhZ2l8c2lhbmd8c29yZXxtYWxhbS8sXG4gICAgbWVyaWRpZW1Ib3VyIDogZnVuY3Rpb24gKGhvdXIsIG1lcmlkaWVtKSB7XG4gICAgICAgIGlmIChob3VyID09PSAxMikge1xuICAgICAgICAgICAgaG91ciA9IDA7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG1lcmlkaWVtID09PSAncGFnaScpIHtcbiAgICAgICAgICAgIHJldHVybiBob3VyO1xuICAgICAgICB9IGVsc2UgaWYgKG1lcmlkaWVtID09PSAnc2lhbmcnKSB7XG4gICAgICAgICAgICByZXR1cm4gaG91ciA+PSAxMSA/IGhvdXIgOiBob3VyICsgMTI7XG4gICAgICAgIH0gZWxzZSBpZiAobWVyaWRpZW0gPT09ICdzb3JlJyB8fCBtZXJpZGllbSA9PT0gJ21hbGFtJykge1xuICAgICAgICAgICAgcmV0dXJuIGhvdXIgKyAxMjtcbiAgICAgICAgfVxuICAgIH0sXG4gICAgbWVyaWRpZW0gOiBmdW5jdGlvbiAoaG91cnMsIG1pbnV0ZXMsIGlzTG93ZXIpIHtcbiAgICAgICAgaWYgKGhvdXJzIDwgMTEpIHtcbiAgICAgICAgICAgIHJldHVybiAncGFnaSc7XG4gICAgICAgIH0gZWxzZSBpZiAoaG91cnMgPCAxNSkge1xuICAgICAgICAgICAgcmV0dXJuICdzaWFuZyc7XG4gICAgICAgIH0gZWxzZSBpZiAoaG91cnMgPCAxOSkge1xuICAgICAgICAgICAgcmV0dXJuICdzb3JlJztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiAnbWFsYW0nO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheSA6ICdbSGFyaSBpbmkgcHVrdWxdIExUJyxcbiAgICAgICAgbmV4dERheSA6ICdbQmVzb2sgcHVrdWxdIExUJyxcbiAgICAgICAgbmV4dFdlZWsgOiAnZGRkZCBbcHVrdWxdIExUJyxcbiAgICAgICAgbGFzdERheSA6ICdbS2VtYXJpbiBwdWt1bF0gTFQnLFxuICAgICAgICBsYXN0V2VlayA6ICdkZGRkIFtsYWx1IHB1a3VsXSBMVCcsXG4gICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6ICdkYWxhbSAlcycsXG4gICAgICAgIHBhc3QgOiAnJXMgeWFuZyBsYWx1JyxcbiAgICAgICAgcyA6ICdiZWJlcmFwYSBkZXRpaycsXG4gICAgICAgIHNzIDogJyVkIGRldGlrJyxcbiAgICAgICAgbSA6ICdzZW1lbml0JyxcbiAgICAgICAgbW0gOiAnJWQgbWVuaXQnLFxuICAgICAgICBoIDogJ3NlamFtJyxcbiAgICAgICAgaGggOiAnJWQgamFtJyxcbiAgICAgICAgZCA6ICdzZWhhcmknLFxuICAgICAgICBkZCA6ICclZCBoYXJpJyxcbiAgICAgICAgTSA6ICdzZWJ1bGFuJyxcbiAgICAgICAgTU0gOiAnJWQgYnVsYW4nLFxuICAgICAgICB5IDogJ3NldGFodW4nLFxuICAgICAgICB5eSA6ICclZCB0YWh1bidcbiAgICB9LFxuICAgIHdlZWsgOiB7XG4gICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICBkb3kgOiA3ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiAxc3QgaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgfVxufSk7XG5cbi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBJY2VsYW5kaWMgW2lzXVxuLy8hIGF1dGhvciA6IEhpbnJpayDDlnJuIFNpZ3Vyw7Bzc29uIDogaHR0cHM6Ly9naXRodWIuY29tL2hpbnJpa1xuXG5mdW5jdGlvbiBwbHVyYWwkMihuKSB7XG4gICAgaWYgKG4gJSAxMDAgPT09IDExKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH0gZWxzZSBpZiAobiAlIDEwID09PSAxKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgcmV0dXJuIHRydWU7XG59XG5mdW5jdGlvbiB0cmFuc2xhdGUkNShudW1iZXIsIHdpdGhvdXRTdWZmaXgsIGtleSwgaXNGdXR1cmUpIHtcbiAgICB2YXIgcmVzdWx0ID0gbnVtYmVyICsgJyAnO1xuICAgIHN3aXRjaCAoa2V5KSB7XG4gICAgICAgIGNhc2UgJ3MnOlxuICAgICAgICAgICAgcmV0dXJuIHdpdGhvdXRTdWZmaXggfHwgaXNGdXR1cmUgPyAnbm9ra3JhciBzZWvDum5kdXInIDogJ25va2tydW0gc2Vrw7puZHVtJztcbiAgICAgICAgY2FzZSAnc3MnOlxuICAgICAgICAgICAgaWYgKHBsdXJhbCQyKG51bWJlcikpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0ICsgKHdpdGhvdXRTdWZmaXggfHwgaXNGdXR1cmUgPyAnc2Vrw7puZHVyJyA6ICdzZWvDum5kdW0nKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByZXN1bHQgKyAnc2Vrw7puZGEnO1xuICAgICAgICBjYXNlICdtJzpcbiAgICAgICAgICAgIHJldHVybiB3aXRob3V0U3VmZml4ID8gJ23DrW7DunRhJyA6ICdtw61uw7p0dSc7XG4gICAgICAgIGNhc2UgJ21tJzpcbiAgICAgICAgICAgIGlmIChwbHVyYWwkMihudW1iZXIpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCArICh3aXRob3V0U3VmZml4IHx8IGlzRnV0dXJlID8gJ23DrW7DunR1cicgOiAnbcOtbsO6dHVtJyk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHdpdGhvdXRTdWZmaXgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0ICsgJ23DrW7DunRhJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByZXN1bHQgKyAnbcOtbsO6dHUnO1xuICAgICAgICBjYXNlICdoaCc6XG4gICAgICAgICAgICBpZiAocGx1cmFsJDIobnVtYmVyKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQgKyAod2l0aG91dFN1ZmZpeCB8fCBpc0Z1dHVyZSA/ICdrbHVra3VzdHVuZGlyJyA6ICdrbHVra3VzdHVuZHVtJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0ICsgJ2tsdWtrdXN0dW5kJztcbiAgICAgICAgY2FzZSAnZCc6XG4gICAgICAgICAgICBpZiAod2l0aG91dFN1ZmZpeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAnZGFndXInO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGlzRnV0dXJlID8gJ2RhZycgOiAnZGVnaSc7XG4gICAgICAgIGNhc2UgJ2RkJzpcbiAgICAgICAgICAgIGlmIChwbHVyYWwkMihudW1iZXIpKSB7XG4gICAgICAgICAgICAgICAgaWYgKHdpdGhvdXRTdWZmaXgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCArICdkYWdhcic7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQgKyAoaXNGdXR1cmUgPyAnZGFnYScgOiAnZMO2Z3VtJyk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHdpdGhvdXRTdWZmaXgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0ICsgJ2RhZ3VyJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByZXN1bHQgKyAoaXNGdXR1cmUgPyAnZGFnJyA6ICdkZWdpJyk7XG4gICAgICAgIGNhc2UgJ00nOlxuICAgICAgICAgICAgaWYgKHdpdGhvdXRTdWZmaXgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ23DoW51w7B1cic7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gaXNGdXR1cmUgPyAnbcOhbnXDsCcgOiAnbcOhbnXDsGknO1xuICAgICAgICBjYXNlICdNTSc6XG4gICAgICAgICAgICBpZiAocGx1cmFsJDIobnVtYmVyKSkge1xuICAgICAgICAgICAgICAgIGlmICh3aXRob3V0U3VmZml4KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQgKyAnbcOhbnXDsGlyJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCArIChpc0Z1dHVyZSA/ICdtw6FudcOwaScgOiAnbcOhbnXDsHVtJyk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHdpdGhvdXRTdWZmaXgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0ICsgJ23DoW51w7B1cic7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0ICsgKGlzRnV0dXJlID8gJ23DoW51w7AnIDogJ23DoW51w7BpJyk7XG4gICAgICAgIGNhc2UgJ3knOlxuICAgICAgICAgICAgcmV0dXJuIHdpdGhvdXRTdWZmaXggfHwgaXNGdXR1cmUgPyAnw6FyJyA6ICfDoXJpJztcbiAgICAgICAgY2FzZSAneXknOlxuICAgICAgICAgICAgaWYgKHBsdXJhbCQyKG51bWJlcikpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0ICsgKHdpdGhvdXRTdWZmaXggfHwgaXNGdXR1cmUgPyAnw6FyJyA6ICfDoXJ1bScpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCArICh3aXRob3V0U3VmZml4IHx8IGlzRnV0dXJlID8gJ8OhcicgOiAnw6FyaScpO1xuICAgIH1cbn1cblxuaG9va3MuZGVmaW5lTG9jYWxlKCdpcycsIHtcbiAgICBtb250aHMgOiAnamFuw7phcl9mZWJyw7phcl9tYXJzX2FwcsOtbF9tYcOtX2rDum7DrV9qw7psw61fw6Fnw7pzdF9zZXB0ZW1iZXJfb2t0w7NiZXJfbsOzdmVtYmVyX2Rlc2VtYmVyJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0IDogJ2phbl9mZWJfbWFyX2Fwcl9tYcOtX2rDum5fasO6bF/DoWfDul9zZXBfb2t0X27Ds3ZfZGVzJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzIDogJ3N1bm51ZGFndXJfbcOhbnVkYWd1cl/DvnJpw7BqdWRhZ3VyX21pw7B2aWt1ZGFndXJfZmltbXR1ZGFndXJfZsO2c3R1ZGFndXJfbGF1Z2FyZGFndXInLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydCA6ICdzdW5fbcOhbl/DvnJpX21pw7BfZmltX2bDtnNfbGF1Jy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzTWluIDogJ1N1X03DoV/DnnJfTWlfRmlfRsO2X0xhJy5zcGxpdCgnXycpLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdIOm1tJyxcbiAgICAgICAgTFRTIDogJ0g6bW06c3MnLFxuICAgICAgICBMIDogJ0RELk1NLllZWVknLFxuICAgICAgICBMTCA6ICdELiBNTU1NIFlZWVknLFxuICAgICAgICBMTEwgOiAnRC4gTU1NTSBZWVlZIFtrbC5dIEg6bW0nLFxuICAgICAgICBMTExMIDogJ2RkZGQsIEQuIE1NTU0gWVlZWSBba2wuXSBIOm1tJ1xuICAgIH0sXG4gICAgY2FsZW5kYXIgOiB7XG4gICAgICAgIHNhbWVEYXkgOiAnW8OtIGRhZyBrbC5dIExUJyxcbiAgICAgICAgbmV4dERheSA6ICdbw6EgbW9yZ3VuIGtsLl0gTFQnLFxuICAgICAgICBuZXh0V2VlayA6ICdkZGRkIFtrbC5dIExUJyxcbiAgICAgICAgbGFzdERheSA6ICdbw60gZ8OmciBrbC5dIExUJyxcbiAgICAgICAgbGFzdFdlZWsgOiAnW3PDrcOwYXN0YV0gZGRkZCBba2wuXSBMVCcsXG4gICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6ICdlZnRpciAlcycsXG4gICAgICAgIHBhc3QgOiAnZnlyaXIgJXMgc8Otw7BhbicsXG4gICAgICAgIHMgOiB0cmFuc2xhdGUkNSxcbiAgICAgICAgc3MgOiB0cmFuc2xhdGUkNSxcbiAgICAgICAgbSA6IHRyYW5zbGF0ZSQ1LFxuICAgICAgICBtbSA6IHRyYW5zbGF0ZSQ1LFxuICAgICAgICBoIDogJ2tsdWtrdXN0dW5kJyxcbiAgICAgICAgaGggOiB0cmFuc2xhdGUkNSxcbiAgICAgICAgZCA6IHRyYW5zbGF0ZSQ1LFxuICAgICAgICBkZCA6IHRyYW5zbGF0ZSQ1LFxuICAgICAgICBNIDogdHJhbnNsYXRlJDUsXG4gICAgICAgIE1NIDogdHJhbnNsYXRlJDUsXG4gICAgICAgIHkgOiB0cmFuc2xhdGUkNSxcbiAgICAgICAgeXkgOiB0cmFuc2xhdGUkNVxuICAgIH0sXG4gICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9XFwuLyxcbiAgICBvcmRpbmFsIDogJyVkLicsXG4gICAgd2VlayA6IHtcbiAgICAgICAgZG93IDogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgIGRveSA6IDQgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDR0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICB9XG59KTtcblxuLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSA6IEl0YWxpYW4gW2l0XVxuLy8hIGF1dGhvciA6IExvcmVuem8gOiBodHRwczovL2dpdGh1Yi5jb20vYWxpZW1cbi8vISBhdXRob3I6IE1hdHRpYSBMYXJlbnRpczogaHR0cHM6Ly9naXRodWIuY29tL25vc3RhbGdpYXpcblxuaG9va3MuZGVmaW5lTG9jYWxlKCdpdCcsIHtcbiAgICBtb250aHMgOiAnZ2VubmFpb19mZWJicmFpb19tYXJ6b19hcHJpbGVfbWFnZ2lvX2dpdWdub19sdWdsaW9fYWdvc3RvX3NldHRlbWJyZV9vdHRvYnJlX25vdmVtYnJlX2RpY2VtYnJlJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0IDogJ2dlbl9mZWJfbWFyX2Fwcl9tYWdfZ2l1X2x1Z19hZ29fc2V0X290dF9ub3ZfZGljJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzIDogJ2RvbWVuaWNhX2x1bmVkw6xfbWFydGVkw6xfbWVyY29sZWTDrF9naW92ZWTDrF92ZW5lcmTDrF9zYWJhdG8nLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydCA6ICdkb21fbHVuX21hcl9tZXJfZ2lvX3Zlbl9zYWInLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW4gOiAnZG9fbHVfbWFfbWVfZ2lfdmVfc2EnLnNwbGl0KCdfJyksXG4gICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgIExUIDogJ0hIOm1tJyxcbiAgICAgICAgTFRTIDogJ0hIOm1tOnNzJyxcbiAgICAgICAgTCA6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgTEwgOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICBMTEwgOiAnRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICBMTExMIDogJ2RkZGQgRCBNTU1NIFlZWVkgSEg6bW0nXG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheTogJ1tPZ2dpIGFsbGVdIExUJyxcbiAgICAgICAgbmV4dERheTogJ1tEb21hbmkgYWxsZV0gTFQnLFxuICAgICAgICBuZXh0V2VlazogJ2RkZGQgW2FsbGVdIExUJyxcbiAgICAgICAgbGFzdERheTogJ1tJZXJpIGFsbGVdIExUJyxcbiAgICAgICAgbGFzdFdlZWs6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHN3aXRjaCAodGhpcy5kYXkoKSkge1xuICAgICAgICAgICAgICAgIGNhc2UgMDpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbbGEgc2NvcnNhXSBkZGRkIFthbGxlXSBMVCc7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbbG8gc2NvcnNvXSBkZGRkIFthbGxlXSBMVCc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIHNhbWVFbHNlOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogZnVuY3Rpb24gKHMpIHtcbiAgICAgICAgICAgIHJldHVybiAoKC9eWzAtOV0uKyQvKS50ZXN0KHMpID8gJ3RyYScgOiAnaW4nKSArICcgJyArIHM7XG4gICAgICAgIH0sXG4gICAgICAgIHBhc3QgOiAnJXMgZmEnLFxuICAgICAgICBzIDogJ2FsY3VuaSBzZWNvbmRpJyxcbiAgICAgICAgc3MgOiAnJWQgc2Vjb25kaScsXG4gICAgICAgIG0gOiAndW4gbWludXRvJyxcbiAgICAgICAgbW0gOiAnJWQgbWludXRpJyxcbiAgICAgICAgaCA6ICd1blxcJ29yYScsXG4gICAgICAgIGhoIDogJyVkIG9yZScsXG4gICAgICAgIGQgOiAndW4gZ2lvcm5vJyxcbiAgICAgICAgZGQgOiAnJWQgZ2lvcm5pJyxcbiAgICAgICAgTSA6ICd1biBtZXNlJyxcbiAgICAgICAgTU0gOiAnJWQgbWVzaScsXG4gICAgICAgIHkgOiAndW4gYW5ubycsXG4gICAgICAgIHl5IDogJyVkIGFubmknXG4gICAgfSxcbiAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlIDogL1xcZHsxLDJ9wrovLFxuICAgIG9yZGluYWw6ICclZMK6JyxcbiAgICB3ZWVrIDoge1xuICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogNCAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH1cbn0pO1xuXG4vLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogSmFwYW5lc2UgW2phXVxuLy8hIGF1dGhvciA6IExJIExvbmcgOiBodHRwczovL2dpdGh1Yi5jb20vYmFyeW9uXG5cbmhvb2tzLmRlZmluZUxvY2FsZSgnamEnLCB7XG4gICAgbW9udGhzIDogJzHmnIhfMuaciF8z5pyIXzTmnIhfNeaciF825pyIXzfmnIhfOOaciF855pyIXzEw5pyIXzEx5pyIXzEy5pyIJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0IDogJzHmnIhfMuaciF8z5pyIXzTmnIhfNeaciF825pyIXzfmnIhfOOaciF855pyIXzEw5pyIXzEx5pyIXzEy5pyIJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzIDogJ+aXpeabnOaXpV/mnIjmm5zml6Vf54Gr5puc5pelX+awtOabnOaXpV/mnKjmm5zml6Vf6YeR5puc5pelX+Wcn+abnOaXpScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0IDogJ+aXpV/mnIhf54GrX+awtF/mnKhf6YeRX+Wcnycuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbiA6ICfml6Vf5pyIX+eBq1/msLRf5pyoX+mHkV/lnJ8nLnNwbGl0KCdfJyksXG4gICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgIExUIDogJ0hIOm1tJyxcbiAgICAgICAgTFRTIDogJ0hIOm1tOnNzJyxcbiAgICAgICAgTCA6ICdZWVlZL01NL0REJyxcbiAgICAgICAgTEwgOiAnWVlZWeW5tE3mnIhE5pelJyxcbiAgICAgICAgTExMIDogJ1lZWVnlubRN5pyIROaXpSBISDptbScsXG4gICAgICAgIExMTEwgOiAnWVlZWeW5tE3mnIhE5pelIEhIOm1tIGRkZGQnLFxuICAgICAgICBsIDogJ1lZWVkvTU0vREQnLFxuICAgICAgICBsbCA6ICdZWVlZ5bm0TeaciETml6UnLFxuICAgICAgICBsbGwgOiAnWVlZWeW5tE3mnIhE5pelIEhIOm1tJyxcbiAgICAgICAgbGxsbCA6ICdZWVlZ5bm0TeaciETml6UgSEg6bW0gZGRkZCdcbiAgICB9LFxuICAgIG1lcmlkaWVtUGFyc2U6IC/ljYjliY185Y2I5b6ML2ksXG4gICAgaXNQTSA6IGZ1bmN0aW9uIChpbnB1dCkge1xuICAgICAgICByZXR1cm4gaW5wdXQgPT09ICfljYjlvownO1xuICAgIH0sXG4gICAgbWVyaWRpZW0gOiBmdW5jdGlvbiAoaG91ciwgbWludXRlLCBpc0xvd2VyKSB7XG4gICAgICAgIGlmIChob3VyIDwgMTIpIHtcbiAgICAgICAgICAgIHJldHVybiAn5Y2I5YmNJztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiAn5Y2I5b6MJztcbiAgICAgICAgfVxuICAgIH0sXG4gICAgY2FsZW5kYXIgOiB7XG4gICAgICAgIHNhbWVEYXkgOiAnW+S7iuaXpV0gTFQnLFxuICAgICAgICBuZXh0RGF5IDogJ1vmmI7ml6VdIExUJyxcbiAgICAgICAgbmV4dFdlZWsgOiAnW+adpemAsV1kZGRkIExUJyxcbiAgICAgICAgbGFzdERheSA6ICdb5pio5pelXSBMVCcsXG4gICAgICAgIGxhc3RXZWVrIDogJ1vliY3pgLFdZGRkZCBMVCcsXG4gICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgfSxcbiAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlIDogL1xcZHsxLDJ95pelLyxcbiAgICBvcmRpbmFsIDogZnVuY3Rpb24gKG51bWJlciwgcGVyaW9kKSB7XG4gICAgICAgIHN3aXRjaCAocGVyaW9kKSB7XG4gICAgICAgICAgICBjYXNlICdkJzpcbiAgICAgICAgICAgIGNhc2UgJ0QnOlxuICAgICAgICAgICAgY2FzZSAnREREJzpcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJ+aXpSc7XG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXI7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJyVz5b6MJyxcbiAgICAgICAgcGFzdCA6ICclc+WJjScsXG4gICAgICAgIHMgOiAn5pWw56eSJyxcbiAgICAgICAgc3MgOiAnJWTnp5InLFxuICAgICAgICBtIDogJzHliIYnLFxuICAgICAgICBtbSA6ICclZOWIhicsXG4gICAgICAgIGggOiAnMeaZgumWkycsXG4gICAgICAgIGhoIDogJyVk5pmC6ZaTJyxcbiAgICAgICAgZCA6ICcx5pelJyxcbiAgICAgICAgZGQgOiAnJWTml6UnLFxuICAgICAgICBNIDogJzHjg7bmnIgnLFxuICAgICAgICBNTSA6ICclZOODtuaciCcsXG4gICAgICAgIHkgOiAnMeW5tCcsXG4gICAgICAgIHl5IDogJyVk5bm0J1xuICAgIH1cbn0pO1xuXG4vLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogSmF2YW5lc2UgW2p2XVxuLy8hIGF1dGhvciA6IFJvbnkgTGFudGlwIDogaHR0cHM6Ly9naXRodWIuY29tL2xhbnRpcFxuLy8hIHJlZmVyZW5jZTogaHR0cDovL2p2Lndpa2lwZWRpYS5vcmcvd2lraS9CYXNhX0phd2FcblxuaG9va3MuZGVmaW5lTG9jYWxlKCdqdicsIHtcbiAgICBtb250aHMgOiAnSmFudWFyaV9GZWJydWFyaV9NYXJldF9BcHJpbF9NZWlfSnVuaV9KdWxpX0FndXN0dXNfU2VwdGVtYmVyX09rdG9iZXJfTm9wZW1iZXJfRGVzZW1iZXInLnNwbGl0KCdfJyksXG4gICAgbW9udGhzU2hvcnQgOiAnSmFuX0ZlYl9NYXJfQXByX01laV9KdW5fSnVsX0Fnc19TZXBfT2t0X05vcF9EZXMnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXMgOiAnTWluZ2d1X1NlbmVuX1NlbG9zb19SZWJ1X0tlbWlzX0plbXV3YWhfU2VwdHUnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydCA6ICdNaW5fU2VuX1NlbF9SZWJfS2VtX0plbV9TZXAnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW4gOiAnTWdfU25fU2xfUmJfS21fSm1fU3AnLnNwbGl0KCdfJyksXG4gICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgIExUIDogJ0hILm1tJyxcbiAgICAgICAgTFRTIDogJ0hILm1tLnNzJyxcbiAgICAgICAgTCA6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgTEwgOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICBMTEwgOiAnRCBNTU1NIFlZWVkgW3B1a3VsXSBISC5tbScsXG4gICAgICAgIExMTEwgOiAnZGRkZCwgRCBNTU1NIFlZWVkgW3B1a3VsXSBISC5tbSdcbiAgICB9LFxuICAgIG1lcmlkaWVtUGFyc2U6IC9lbmppbmd8c2l5YW5nfHNvbnRlbnxuZGFsdS8sXG4gICAgbWVyaWRpZW1Ib3VyIDogZnVuY3Rpb24gKGhvdXIsIG1lcmlkaWVtKSB7XG4gICAgICAgIGlmIChob3VyID09PSAxMikge1xuICAgICAgICAgICAgaG91ciA9IDA7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG1lcmlkaWVtID09PSAnZW5qaW5nJykge1xuICAgICAgICAgICAgcmV0dXJuIGhvdXI7XG4gICAgICAgIH0gZWxzZSBpZiAobWVyaWRpZW0gPT09ICdzaXlhbmcnKSB7XG4gICAgICAgICAgICByZXR1cm4gaG91ciA+PSAxMSA/IGhvdXIgOiBob3VyICsgMTI7XG4gICAgICAgIH0gZWxzZSBpZiAobWVyaWRpZW0gPT09ICdzb250ZW4nIHx8IG1lcmlkaWVtID09PSAnbmRhbHUnKSB7XG4gICAgICAgICAgICByZXR1cm4gaG91ciArIDEyO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBtZXJpZGllbSA6IGZ1bmN0aW9uIChob3VycywgbWludXRlcywgaXNMb3dlcikge1xuICAgICAgICBpZiAoaG91cnMgPCAxMSkge1xuICAgICAgICAgICAgcmV0dXJuICdlbmppbmcnO1xuICAgICAgICB9IGVsc2UgaWYgKGhvdXJzIDwgMTUpIHtcbiAgICAgICAgICAgIHJldHVybiAnc2l5YW5nJztcbiAgICAgICAgfSBlbHNlIGlmIChob3VycyA8IDE5KSB7XG4gICAgICAgICAgICByZXR1cm4gJ3NvbnRlbic7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gJ25kYWx1JztcbiAgICAgICAgfVxuICAgIH0sXG4gICAgY2FsZW5kYXIgOiB7XG4gICAgICAgIHNhbWVEYXkgOiAnW0RpbnRlbiBwdW5pa28gcHVrdWxdIExUJyxcbiAgICAgICAgbmV4dERheSA6ICdbTWJlbmphbmcgcHVrdWxdIExUJyxcbiAgICAgICAgbmV4dFdlZWsgOiAnZGRkZCBbcHVrdWxdIExUJyxcbiAgICAgICAgbGFzdERheSA6ICdbS2FsYSB3aW5naSBwdWt1bF0gTFQnLFxuICAgICAgICBsYXN0V2VlayA6ICdkZGRkIFtrZXBlbmdrZXIgcHVrdWxdIExUJyxcbiAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJ3dvbnRlbiBpbmcgJXMnLFxuICAgICAgICBwYXN0IDogJyVzIGluZ2thbmcga2VwZW5na2VyJyxcbiAgICAgICAgcyA6ICdzYXdldGF3aXMgZGV0aWsnLFxuICAgICAgICBzcyA6ICclZCBkZXRpaycsXG4gICAgICAgIG0gOiAnc2V0dW5nZ2FsIG1lbml0JyxcbiAgICAgICAgbW0gOiAnJWQgbWVuaXQnLFxuICAgICAgICBoIDogJ3NldHVuZ2dhbCBqYW0nLFxuICAgICAgICBoaCA6ICclZCBqYW0nLFxuICAgICAgICBkIDogJ3NlZGludGVuJyxcbiAgICAgICAgZGQgOiAnJWQgZGludGVuJyxcbiAgICAgICAgTSA6ICdzZXd1bGFuJyxcbiAgICAgICAgTU0gOiAnJWQgd3VsYW4nLFxuICAgICAgICB5IDogJ3NldGF1bicsXG4gICAgICAgIHl5IDogJyVkIHRhdW4nXG4gICAgfSxcbiAgICB3ZWVrIDoge1xuICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogNyAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gMXN0IGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH1cbn0pO1xuXG4vLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogR2VvcmdpYW4gW2thXVxuLy8hIGF1dGhvciA6IElyYWtsaSBKYW5pYXNodmlsaSA6IGh0dHBzOi8vZ2l0aHViLmNvbS9pcmFrbGktamFuaWFzaHZpbGlcblxuaG9va3MuZGVmaW5lTG9jYWxlKCdrYScsIHtcbiAgICBtb250aHMgOiB7XG4gICAgICAgIHN0YW5kYWxvbmU6ICfhg5jhg5Dhg5zhg5Xhg5Dhg6Dhg5hf4YOX4YOU4YOR4YOU4YOg4YOV4YOQ4YOa4YOYX+GDm+GDkOGDoOGDouGDmF/hg5Dhg57hg6Dhg5jhg5rhg5hf4YOb4YOQ4YOY4YOh4YOYX+GDmOGDleGDnOGDmOGDoeGDmF/hg5jhg5Xhg5rhg5jhg6Hhg5hf4YOQ4YOS4YOV4YOY4YOh4YOi4YOdX+GDoeGDlOGDpeGDouGDlOGDm+GDkeGDlOGDoOGDmF/hg53hg6Xhg6Lhg53hg5vhg5Hhg5Thg6Dhg5hf4YOc4YOd4YOU4YOb4YOR4YOU4YOg4YOYX+GDk+GDlOGDmeGDlOGDm+GDkeGDlOGDoOGDmCcuc3BsaXQoJ18nKSxcbiAgICAgICAgZm9ybWF0OiAn4YOY4YOQ4YOc4YOV4YOQ4YOg4YOhX+GDl+GDlOGDkeGDlOGDoOGDleGDkOGDmuGDoV/hg5vhg5Dhg6Dhg6Lhg6Ff4YOQ4YOe4YOg4YOY4YOa4YOY4YOhX+GDm+GDkOGDmOGDoeGDoV/hg5jhg5Xhg5zhg5jhg6Hhg6Ff4YOY4YOV4YOa4YOY4YOh4YOhX+GDkOGDkuGDleGDmOGDoeGDouGDoV/hg6Hhg5Thg6Xhg6Lhg5Thg5vhg5Hhg5Thg6Dhg6Ff4YOd4YOl4YOi4YOd4YOb4YOR4YOU4YOg4YOhX+GDnOGDneGDlOGDm+GDkeGDlOGDoOGDoV/hg5Phg5Thg5nhg5Thg5vhg5Hhg5Thg6Dhg6EnLnNwbGl0KCdfJylcbiAgICB9LFxuICAgIG1vbnRoc1Nob3J0IDogJ+GDmOGDkOGDnF/hg5fhg5Thg5Ff4YOb4YOQ4YOgX+GDkOGDnuGDoF/hg5vhg5Dhg5hf4YOY4YOV4YOcX+GDmOGDleGDml/hg5Dhg5Lhg5Vf4YOh4YOU4YOlX+GDneGDpeGDol/hg5zhg53hg5Rf4YOT4YOU4YOZJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzIDoge1xuICAgICAgICBzdGFuZGFsb25lOiAn4YOZ4YOV4YOY4YOg4YOQX+GDneGDoOGDqOGDkOGDkeGDkOGDl+GDmF/hg6Hhg5Dhg5vhg6jhg5Dhg5Hhg5Dhg5fhg5hf4YOd4YOX4YOu4YOo4YOQ4YOR4YOQ4YOX4YOYX+GDruGDo+GDl+GDqOGDkOGDkeGDkOGDl+GDmF/hg57hg5Dhg6Dhg5Dhg6Hhg5nhg5Thg5Xhg5hf4YOo4YOQ4YOR4YOQ4YOX4YOYJy5zcGxpdCgnXycpLFxuICAgICAgICBmb3JtYXQ6ICfhg5nhg5Xhg5jhg6Dhg5Dhg6Ff4YOd4YOg4YOo4YOQ4YOR4YOQ4YOX4YOhX+GDoeGDkOGDm+GDqOGDkOGDkeGDkOGDl+GDoV/hg53hg5fhg67hg6jhg5Dhg5Hhg5Dhg5fhg6Ff4YOu4YOj4YOX4YOo4YOQ4YOR4YOQ4YOX4YOhX+GDnuGDkOGDoOGDkOGDoeGDmeGDlOGDleGDoV/hg6jhg5Dhg5Hhg5Dhg5fhg6EnLnNwbGl0KCdfJyksXG4gICAgICAgIGlzRm9ybWF0OiAvKOGDrOGDmOGDnOGDkHzhg6jhg5Thg5vhg5Phg5Thg5IpL1xuICAgIH0sXG4gICAgd2Vla2RheXNTaG9ydCA6ICfhg5nhg5Xhg5hf4YOd4YOg4YOoX+GDoeGDkOGDm1/hg53hg5fhg65f4YOu4YOj4YOXX+GDnuGDkOGDoF/hg6jhg5Dhg5EnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW4gOiAn4YOZ4YOVX+GDneGDoF/hg6Hhg5Bf4YOd4YOXX+GDruGDo1/hg57hg5Bf4YOo4YOQJy5zcGxpdCgnXycpLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdoOm1tIEEnLFxuICAgICAgICBMVFMgOiAnaDptbTpzcyBBJyxcbiAgICAgICAgTCA6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgTEwgOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICBMTEwgOiAnRCBNTU1NIFlZWVkgaDptbSBBJyxcbiAgICAgICAgTExMTCA6ICdkZGRkLCBEIE1NTU0gWVlZWSBoOm1tIEEnXG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheSA6ICdb4YOT4YOm4YOU4YOhXSBMVFst4YOW4YOUXScsXG4gICAgICAgIG5leHREYXkgOiAnW+GDruGDleGDkOGDml0gTFRbLeGDluGDlF0nLFxuICAgICAgICBsYXN0RGF5IDogJ1vhg5Lhg6Phg6jhg5jhg5xdIExUWy3hg5bhg5RdJyxcbiAgICAgICAgbmV4dFdlZWsgOiAnW+GDqOGDlOGDm+GDk+GDlOGDkl0gZGRkZCBMVFst4YOW4YOUXScsXG4gICAgICAgIGxhc3RXZWVrIDogJ1vhg6zhg5jhg5zhg5BdIGRkZGQgTFQt4YOW4YOUJyxcbiAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogZnVuY3Rpb24gKHMpIHtcbiAgICAgICAgICAgIHJldHVybiAoLyjhg6zhg5Dhg5vhg5h84YOs4YOj4YOX4YOYfOGDoeGDkOGDkOGDl+GDmHzhg6zhg5Thg5rhg5gpLykudGVzdChzKSA/XG4gICAgICAgICAgICAgICAgcy5yZXBsYWNlKC/hg5gkLywgJ+GDqOGDmCcpIDpcbiAgICAgICAgICAgICAgICBzICsgJ+GDqOGDmCc7XG4gICAgICAgIH0sXG4gICAgICAgIHBhc3QgOiBmdW5jdGlvbiAocykge1xuICAgICAgICAgICAgaWYgKCgvKOGDrOGDkOGDm+GDmHzhg6zhg6Phg5fhg5h84YOh4YOQ4YOQ4YOX4YOYfOGDk+GDpuGDlHzhg5fhg5Xhg5QpLykudGVzdChzKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBzLnJlcGxhY2UoLyjhg5h84YOUKSQvLCAn4YOY4YOhIOGDo+GDmeGDkOGDnCcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCgv4YOs4YOU4YOa4YOYLykudGVzdChzKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBzLnJlcGxhY2UoL+GDrOGDlOGDmuGDmCQvLCAn4YOs4YOa4YOY4YOhIOGDo+GDmeGDkOGDnCcpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBzIDogJ+GDoOGDkOGDm+GDk+GDlOGDnOGDmOGDm+GDlCDhg6zhg5Dhg5vhg5gnLFxuICAgICAgICBzcyA6ICclZCDhg6zhg5Dhg5vhg5gnLFxuICAgICAgICBtIDogJ+GDrOGDo+GDl+GDmCcsXG4gICAgICAgIG1tIDogJyVkIOGDrOGDo+GDl+GDmCcsXG4gICAgICAgIGggOiAn4YOh4YOQ4YOQ4YOX4YOYJyxcbiAgICAgICAgaGggOiAnJWQg4YOh4YOQ4YOQ4YOX4YOYJyxcbiAgICAgICAgZCA6ICfhg5Phg6bhg5QnLFxuICAgICAgICBkZCA6ICclZCDhg5Phg6bhg5QnLFxuICAgICAgICBNIDogJ+GDl+GDleGDlCcsXG4gICAgICAgIE1NIDogJyVkIOGDl+GDleGDlCcsXG4gICAgICAgIHkgOiAn4YOs4YOU4YOa4YOYJyxcbiAgICAgICAgeXkgOiAnJWQg4YOs4YOU4YOa4YOYJ1xuICAgIH0sXG4gICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogLzB8MS3hg5rhg5h84YOb4YOULVxcZHsxLDJ9fFxcZHsxLDJ9LeGDlC8sXG4gICAgb3JkaW5hbCA6IGZ1bmN0aW9uIChudW1iZXIpIHtcbiAgICAgICAgaWYgKG51bWJlciA9PT0gMCkge1xuICAgICAgICAgICAgcmV0dXJuIG51bWJlcjtcbiAgICAgICAgfVxuICAgICAgICBpZiAobnVtYmVyID09PSAxKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJy3hg5rhg5gnO1xuICAgICAgICB9XG4gICAgICAgIGlmICgobnVtYmVyIDwgMjApIHx8IChudW1iZXIgPD0gMTAwICYmIChudW1iZXIgJSAyMCA9PT0gMCkpIHx8IChudW1iZXIgJSAxMDAgPT09IDApKSB7XG4gICAgICAgICAgICByZXR1cm4gJ+GDm+GDlC0nICsgbnVtYmVyO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBudW1iZXIgKyAnLeGDlCc7XG4gICAgfSxcbiAgICB3ZWVrIDoge1xuICAgICAgICBkb3cgOiAxLFxuICAgICAgICBkb3kgOiA3XG4gICAgfVxufSk7XG5cbi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBLYXpha2ggW2trXVxuLy8hIGF1dGhvcnMgOiBOdXJsYW4gUmFraGltemhhbm92IDogaHR0cHM6Ly9naXRodWIuY29tL251cmxhblxuXG52YXIgc3VmZml4ZXMkMSA9IHtcbiAgICAwOiAnLdGI0ZYnLFxuICAgIDE6ICct0YjRlicsXG4gICAgMjogJy3RiNGWJyxcbiAgICAzOiAnLdGI0ZYnLFxuICAgIDQ6ICct0YjRlicsXG4gICAgNTogJy3RiNGWJyxcbiAgICA2OiAnLdGI0YsnLFxuICAgIDc6ICct0YjRlicsXG4gICAgODogJy3RiNGWJyxcbiAgICA5OiAnLdGI0YsnLFxuICAgIDEwOiAnLdGI0YsnLFxuICAgIDIwOiAnLdGI0YsnLFxuICAgIDMwOiAnLdGI0YsnLFxuICAgIDQwOiAnLdGI0YsnLFxuICAgIDUwOiAnLdGI0ZYnLFxuICAgIDYwOiAnLdGI0YsnLFxuICAgIDcwOiAnLdGI0ZYnLFxuICAgIDgwOiAnLdGI0ZYnLFxuICAgIDkwOiAnLdGI0YsnLFxuICAgIDEwMDogJy3RiNGWJ1xufTtcblxuaG9va3MuZGVmaW5lTG9jYWxlKCdraycsIHtcbiAgICBtb250aHMgOiAn0pvQsNKj0YLQsNGAX9Cw0pvQv9Cw0L1f0L3QsNGD0YDRi9C3X9GB05nRg9GW0YBf0LzQsNC80YvRgF/QvNCw0YPRgdGL0Lxf0YjRltC70LTQtV/RgtCw0LzRi9C3X9Kb0YvRgNC60q/QudC10Lpf0pvQsNC30LDQvV/Sm9Cw0YDQsNGI0LBf0LbQtdC70YLQvtKb0YHQsNC9Jy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0IDogJ9Kb0LDSo1/QsNKb0L9f0L3QsNGDX9GB05nRg1/QvNCw0Lxf0LzQsNGDX9GI0ZbQu1/RgtCw0Lxf0pvRi9GAX9Kb0LDQt1/Sm9Cw0YBf0LbQtdC7Jy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzIDogJ9C20LXQutGB0LXQvdCx0ZZf0LTSr9C50YHQtdC90LHRll/RgdC10LnRgdC10L3QsdGWX9GB05nRgNGB0LXQvdCx0ZZf0LHQtdC50YHQtdC90LHRll/QttKx0LzQsF/RgdC10L3QsdGWJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzU2hvcnQgOiAn0LbQtdC6X9C00q/QuV/RgdC10Llf0YHTmdGAX9Cx0LXQuV/QttKx0Lxf0YHQtdC9Jy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzTWluIDogJ9C20Lpf0LTQuV/RgdC5X9GB0YBf0LHQuV/QttC8X9GB0L0nLnNwbGl0KCdfJyksXG4gICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgIExUIDogJ0hIOm1tJyxcbiAgICAgICAgTFRTIDogJ0hIOm1tOnNzJyxcbiAgICAgICAgTCA6ICdERC5NTS5ZWVlZJyxcbiAgICAgICAgTEwgOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICBMTEwgOiAnRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICBMTExMIDogJ2RkZGQsIEQgTU1NTSBZWVlZIEhIOm1tJ1xuICAgIH0sXG4gICAgY2FsZW5kYXIgOiB7XG4gICAgICAgIHNhbWVEYXkgOiAnW9CR0q/Qs9GW0L0g0YHQsNKT0LDRgl0gTFQnLFxuICAgICAgICBuZXh0RGF5IDogJ1vQldGA0YLQtdKjINGB0LDSk9Cw0YJdIExUJyxcbiAgICAgICAgbmV4dFdlZWsgOiAnZGRkZCBb0YHQsNKT0LDRgl0gTFQnLFxuICAgICAgICBsYXN0RGF5IDogJ1vQmtC10YjQtSDRgdCw0pPQsNGCXSBMVCcsXG4gICAgICAgIGxhc3RXZWVrIDogJ1vTqNGC0LrQtdC9INCw0L/RgtCw0L3Ri9KjXSBkZGRkIFvRgdCw0pPQsNGCXSBMVCcsXG4gICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6ICclcyDRltGI0ZbQvdC00LUnLFxuICAgICAgICBwYXN0IDogJyVzINCx0rHRgNGL0L0nLFxuICAgICAgICBzIDogJ9Cx0ZbRgNC90LXRiNC1INGB0LXQutGD0L3QtCcsXG4gICAgICAgIHNzIDogJyVkINGB0LXQutGD0L3QtCcsXG4gICAgICAgIG0gOiAn0LHRltGAINC80LjQvdGD0YInLFxuICAgICAgICBtbSA6ICclZCDQvNC40L3Rg9GCJyxcbiAgICAgICAgaCA6ICfQsdGW0YAg0YHQsNKT0LDRgicsXG4gICAgICAgIGhoIDogJyVkINGB0LDSk9Cw0YInLFxuICAgICAgICBkIDogJ9Cx0ZbRgCDQutKv0L0nLFxuICAgICAgICBkZCA6ICclZCDQutKv0L0nLFxuICAgICAgICBNIDogJ9Cx0ZbRgCDQsNC5JyxcbiAgICAgICAgTU0gOiAnJWQg0LDQuScsXG4gICAgICAgIHkgOiAn0LHRltGAINC20YvQuycsXG4gICAgICAgIHl5IDogJyVkINC20YvQuydcbiAgICB9LFxuICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfS0o0YjRlnzRiNGLKS8sXG4gICAgb3JkaW5hbCA6IGZ1bmN0aW9uIChudW1iZXIpIHtcbiAgICAgICAgdmFyIGEgPSBudW1iZXIgJSAxMCxcbiAgICAgICAgICAgIGIgPSBudW1iZXIgPj0gMTAwID8gMTAwIDogbnVsbDtcbiAgICAgICAgcmV0dXJuIG51bWJlciArIChzdWZmaXhlcyQxW251bWJlcl0gfHwgc3VmZml4ZXMkMVthXSB8fCBzdWZmaXhlcyQxW2JdKTtcbiAgICB9LFxuICAgIHdlZWsgOiB7XG4gICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICBkb3kgOiA3ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiAxc3QgaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgfVxufSk7XG5cbi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBDYW1ib2RpYW4gW2ttXVxuLy8hIGF1dGhvciA6IEtydXkgVmFubmEgOiBodHRwczovL2dpdGh1Yi5jb20va3J1eXZhbm5hXG5cbmhvb2tzLmRlZmluZUxvY2FsZSgna20nLCB7XG4gICAgbW9udGhzOiAn4Z6Y4Z6A4Z6a4Z62X+GegOGeu+GemOGfkuGel+GfiF/hnpjhnrjhnpPhnrZf4Z6Y4Z+B4Z6f4Z62X+Gep+Gen+Gel+Getl/hnpjhnrfhnpDhnrvhnpPhnrZf4Z6A4Z6A4Z+S4Z6A4Z6K4Z62X+Gen+GeuOGeoOGetl/hnoDhnonhn5LhnonhnrZf4Z6P4Z674Z6b4Z62X+GenOGet+GeheGfkuGehuGet+GegOGetl/hnpLhn5LhnpPhnrwnLnNwbGl0KCdfJyksXG4gICAgbW9udGhzU2hvcnQ6ICfhnpjhnoDhnprhnrZf4Z6A4Z674Z6Y4Z+S4Z6X4Z+IX+GemOGeuOGek+Getl/hnpjhn4Hhnp/hnrZf4Z6n4Z6f4Z6X4Z62X+GemOGet+GekOGeu+Gek+Getl/hnoDhnoDhn5LhnoDhnorhnrZf4Z6f4Z644Z6g4Z62X+GegOGeieGfkuGeieGetl/hno/hnrvhnpvhnrZf4Z6c4Z634Z6F4Z+S4Z6G4Z634Z6A4Z62X+GekuGfkuGek+GevCcuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5czogJ+GeouGetuGekeGet+Gej+GfkuGemV/hnoXhn5DhnpPhn5LhnpFf4Z6i4Z6E4Z+S4Z6C4Z624Z6aX+GeluGeu+Gekl/hnpbhn5LhnprhnqDhnp/hn5LhnpThno/hnrfhn41f4Z6f4Z674Z6A4Z+S4Z6aX+Gen+GfheGemuGfjScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0OiAn4Z6i4Z624Z6R4Z634Z6P4Z+S4Z6ZX+GeheGfkOGek+GfkuGekV/hnqLhnoThn5LhnoLhnrbhnppf4Z6W4Z674Z6SX+GeluGfkuGemuGeoOGen+GfkuGelOGej+Get+GfjV/hnp/hnrvhnoDhn5Lhnppf4Z6f4Z+F4Z6a4Z+NJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzTWluOiAn4Z6i4Z624Z6R4Z634Z6P4Z+S4Z6ZX+GeheGfkOGek+GfkuGekV/hnqLhnoThn5LhnoLhnrbhnppf4Z6W4Z674Z6SX+GeluGfkuGemuGeoOGen+GfkuGelOGej+Get+GfjV/hnp/hnrvhnoDhn5Lhnppf4Z6f4Z+F4Z6a4Z+NJy5zcGxpdCgnXycpLFxuICAgIGxvbmdEYXRlRm9ybWF0OiB7XG4gICAgICAgIExUOiAnSEg6bW0nLFxuICAgICAgICBMVFMgOiAnSEg6bW06c3MnLFxuICAgICAgICBMOiAnREQvTU0vWVlZWScsXG4gICAgICAgIExMOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICBMTEw6ICdEIE1NTU0gWVlZWSBISDptbScsXG4gICAgICAgIExMTEw6ICdkZGRkLCBEIE1NTU0gWVlZWSBISDptbSdcbiAgICB9LFxuICAgIGNhbGVuZGFyOiB7XG4gICAgICAgIHNhbWVEYXk6ICdb4Z6Q4Z+S4Z6E4Z+D4Z6T4Z+B4Z+HIOGemOGfieGfhOGehF0gTFQnLFxuICAgICAgICBuZXh0RGF5OiAnW+Gen+GfkuGeouGfguGegCDhnpjhn4nhn4ThnoRdIExUJyxcbiAgICAgICAgbmV4dFdlZWs6ICdkZGRkIFvhnpjhn4nhn4ThnoRdIExUJyxcbiAgICAgICAgbGFzdERheTogJ1vhnpjhn5Lhnp/hnrfhnpvhnpjhnrfhnokg4Z6Y4Z+J4Z+E4Z6EXSBMVCcsXG4gICAgICAgIGxhc3RXZWVrOiAnZGRkZCBb4Z6f4Z6U4Z+S4Z6P4Z624Z6g4Z+N4Z6Y4Z674Z6TXSBb4Z6Y4Z+J4Z+E4Z6EXSBMVCcsXG4gICAgICAgIHNhbWVFbHNlOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZToge1xuICAgICAgICBmdXR1cmU6ICclc+GekeGfgOGejycsXG4gICAgICAgIHBhc3Q6ICclc+GemOGeu+GekycsXG4gICAgICAgIHM6ICfhnpThn4nhnrvhnpPhn5LhnpjhnrbhnpPhnpzhnrfhnpPhnrbhnpHhnrgnLFxuICAgICAgICBzczogJyVkIOGenOGet+Gek+GetuGekeGeuCcsXG4gICAgICAgIG06ICfhnpjhnr3hnpnhnpPhnrbhnpHhnrgnLFxuICAgICAgICBtbTogJyVkIOGek+GetuGekeGeuCcsXG4gICAgICAgIGg6ICfhnpjhnr3hnpnhnpjhn4nhn4ThnoQnLFxuICAgICAgICBoaDogJyVkIOGemOGfieGfhOGehCcsXG4gICAgICAgIGQ6ICfhnpjhnr3hnpnhnpDhn5LhnoThn4MnLFxuICAgICAgICBkZDogJyVkIOGekOGfkuGehOGfgycsXG4gICAgICAgIE06ICfhnpjhnr3hnpnhnoHhn4InLFxuICAgICAgICBNTTogJyVkIOGegeGfgicsXG4gICAgICAgIHk6ICfhnpjhnr3hnpnhnobhn5LhnpPhnrbhn4YnLFxuICAgICAgICB5eTogJyVkIOGehuGfkuGek+GetuGfhidcbiAgICB9LFxuICAgIHdlZWs6IHtcbiAgICAgICAgZG93OiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95OiA0IC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDR0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICB9XG59KTtcblxuLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSA6IEthbm5hZGEgW2tuXVxuLy8hIGF1dGhvciA6IFJhamVldiBOYWlrIDogaHR0cHM6Ly9naXRodWIuY29tL3JhamVldm5haWt0ZVxuXG52YXIgc3ltYm9sTWFwJDggPSB7XG4gICAgJzEnOiAn4LOnJyxcbiAgICAnMic6ICfgs6gnLFxuICAgICczJzogJ+CzqScsXG4gICAgJzQnOiAn4LOqJyxcbiAgICAnNSc6ICfgs6snLFxuICAgICc2JzogJ+CzrCcsXG4gICAgJzcnOiAn4LOtJyxcbiAgICAnOCc6ICfgs64nLFxuICAgICc5JzogJ+CzrycsXG4gICAgJzAnOiAn4LOmJ1xufTtcbnZhciBudW1iZXJNYXAkNyA9IHtcbiAgICAn4LOnJzogJzEnLFxuICAgICfgs6gnOiAnMicsXG4gICAgJ+CzqSc6ICczJyxcbiAgICAn4LOqJzogJzQnLFxuICAgICfgs6snOiAnNScsXG4gICAgJ+CzrCc6ICc2JyxcbiAgICAn4LOtJzogJzcnLFxuICAgICfgs64nOiAnOCcsXG4gICAgJ+Czryc6ICc5JyxcbiAgICAn4LOmJzogJzAnXG59O1xuXG5ob29rcy5kZWZpbmVMb2NhbGUoJ2tuJywge1xuICAgIG1vbnRocyA6ICfgspzgsqjgsrXgsrDgsr9f4LKr4LOG4LKs4LON4LKw4LK14LKw4LK/X+CyruCyvuCysOCzjeCymuCzjV/gso/gsqrgs43gsrDgsr/gsrLgs41f4LKu4LOG4LOVX+CynOCzguCyqOCzjV/gspzgs4HgsrLgs4bgs5Zf4LKG4LKX4LK44LON4LKf4LONX+CyuOCzhuCyquCzjeCyn+CzhuCyguCyrOCysOCzjV/gsoXgspXgs43gsp/gs4bgs4Lgs5XgsqzgsrDgs41f4LKo4LK14LOG4LKC4LKs4LKw4LONX+CyoeCyv+CyuOCzhuCyguCyrOCysOCzjScuc3BsaXQoJ18nKSxcbiAgICBtb250aHNTaG9ydCA6ICfgspzgsqhf4LKr4LOG4LKs4LON4LKwX+CyruCyvuCysOCzjeCymuCzjV/gso/gsqrgs43gsrDgsr/gsrLgs41f4LKu4LOG4LOVX+CynOCzguCyqOCzjV/gspzgs4HgsrLgs4bgs5Zf4LKG4LKX4LK44LON4LKf4LONX+CyuOCzhuCyquCzjeCyn+CzhuCyguCyrF/gsoXgspXgs43gsp/gs4bgs4Lgs5Xgsqxf4LKo4LK14LOG4LKC4LKsX+CyoeCyv+CyuOCzhuCyguCyrCcuc3BsaXQoJ18nKSxcbiAgICBtb250aHNQYXJzZUV4YWN0OiB0cnVlLFxuICAgIHdlZWtkYXlzIDogJ+CyreCyvuCyqOCzgeCyteCyvuCysF/gsrjgs4bgs4Lgs5Xgsq7gsrXgsr7gsrBf4LKu4LKC4LKX4LKz4LK14LK+4LKwX+CyrOCzgeCyp+CyteCyvuCysF/gspfgs4HgsrDgs4HgsrXgsr7gsrBf4LK24LOB4LKV4LON4LKw4LK14LK+4LKwX+CytuCyqOCyv+CyteCyvuCysCcuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0IDogJ+CyreCyvuCyqOCzgV/gsrjgs4bgs4Lgs5Xgsq5f4LKu4LKC4LKX4LKzX+CyrOCzgeCyp1/gspfgs4HgsrDgs4Ff4LK24LOB4LKV4LON4LKwX+CytuCyqOCyvycuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbiA6ICfgsq3gsr5f4LK44LOG4LOC4LOVX+CyruCygl/gsqzgs4Ff4LKX4LOBX+CytuCzgV/gsrYnLnNwbGl0KCdfJyksXG4gICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgIExUIDogJ0EgaDptbScsXG4gICAgICAgIExUUyA6ICdBIGg6bW06c3MnLFxuICAgICAgICBMIDogJ0REL01NL1lZWVknLFxuICAgICAgICBMTCA6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgIExMTCA6ICdEIE1NTU0gWVlZWSwgQSBoOm1tJyxcbiAgICAgICAgTExMTCA6ICdkZGRkLCBEIE1NTU0gWVlZWSwgQSBoOm1tJ1xuICAgIH0sXG4gICAgY2FsZW5kYXIgOiB7XG4gICAgICAgIHNhbWVEYXkgOiAnW+Cyh+CyguCypuCzgV0gTFQnLFxuICAgICAgICBuZXh0RGF5IDogJ1vgsqjgsr7gsrPgs4ZdIExUJyxcbiAgICAgICAgbmV4dFdlZWsgOiAnZGRkZCwgTFQnLFxuICAgICAgICBsYXN0RGF5IDogJ1vgsqjgsr/gsqjgs43gsqjgs4ZdIExUJyxcbiAgICAgICAgbGFzdFdlZWsgOiAnW+CyleCzhuCzguCyqOCzhuCyr10gZGRkZCwgTFQnLFxuICAgICAgICBzYW1lRWxzZSA6ICdMJ1xuICAgIH0sXG4gICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICBmdXR1cmUgOiAnJXMg4LKo4LKC4LKk4LKwJyxcbiAgICAgICAgcGFzdCA6ICclcyDgsrngsr/gsoLgsqbgs4YnLFxuICAgICAgICBzIDogJ+CyleCzhuCysuCyteCzgSDgspXgs43gsrfgsqPgspfgsrPgs4EnLFxuICAgICAgICBzcyA6ICclZCDgsrjgs4bgspXgs4bgsoLgsqHgs4HgspfgsrPgs4EnLFxuICAgICAgICBtIDogJ+CykuCyguCypuCzgSDgsqjgsr/gsq7gsr/gsrcnLFxuICAgICAgICBtbSA6ICclZCDgsqjgsr/gsq7gsr/gsrcnLFxuICAgICAgICBoIDogJ+CykuCyguCypuCzgSDgspfgsoLgsp/gs4YnLFxuICAgICAgICBoaCA6ICclZCDgspfgsoLgsp/gs4YnLFxuICAgICAgICBkIDogJ+CykuCyguCypuCzgSDgsqbgsr/gsqgnLFxuICAgICAgICBkZCA6ICclZCDgsqbgsr/gsqgnLFxuICAgICAgICBNIDogJ+CykuCyguCypuCzgSDgsqTgsr/gsoLgspfgsrPgs4EnLFxuICAgICAgICBNTSA6ICclZCDgsqTgsr/gsoLgspfgsrPgs4EnLFxuICAgICAgICB5IDogJ+CykuCyguCypuCzgSDgsrXgsrDgs43gsrcnLFxuICAgICAgICB5eSA6ICclZCDgsrXgsrDgs43gsrcnXG4gICAgfSxcbiAgICBwcmVwYXJzZTogZnVuY3Rpb24gKHN0cmluZykge1xuICAgICAgICByZXR1cm4gc3RyaW5nLnJlcGxhY2UoL1vgs6fgs6jgs6ngs6rgs6vgs6zgs63gs67gs6/gs6ZdL2csIGZ1bmN0aW9uIChtYXRjaCkge1xuICAgICAgICAgICAgcmV0dXJuIG51bWJlck1hcCQ3W21hdGNoXTtcbiAgICAgICAgfSk7XG4gICAgfSxcbiAgICBwb3N0Zm9ybWF0OiBmdW5jdGlvbiAoc3RyaW5nKSB7XG4gICAgICAgIHJldHVybiBzdHJpbmcucmVwbGFjZSgvXFxkL2csIGZ1bmN0aW9uIChtYXRjaCkge1xuICAgICAgICAgICAgcmV0dXJuIHN5bWJvbE1hcCQ4W21hdGNoXTtcbiAgICAgICAgfSk7XG4gICAgfSxcbiAgICBtZXJpZGllbVBhcnNlOiAv4LKw4LK+4LKk4LON4LKw4LK/fOCyrOCzhuCys+Cyv+Cyl+CzjeCyl+Czhnzgsq7gsqfgs43gsq/gsr7gsrngs43gsqh84LK44LKC4LKc4LOGLyxcbiAgICBtZXJpZGllbUhvdXIgOiBmdW5jdGlvbiAoaG91ciwgbWVyaWRpZW0pIHtcbiAgICAgICAgaWYgKGhvdXIgPT09IDEyKSB7XG4gICAgICAgICAgICBob3VyID0gMDtcbiAgICAgICAgfVxuICAgICAgICBpZiAobWVyaWRpZW0gPT09ICfgsrDgsr7gsqTgs43gsrDgsr8nKSB7XG4gICAgICAgICAgICByZXR1cm4gaG91ciA8IDQgPyBob3VyIDogaG91ciArIDEyO1xuICAgICAgICB9IGVsc2UgaWYgKG1lcmlkaWVtID09PSAn4LKs4LOG4LKz4LK/4LKX4LON4LKX4LOGJykge1xuICAgICAgICAgICAgcmV0dXJuIGhvdXI7XG4gICAgICAgIH0gZWxzZSBpZiAobWVyaWRpZW0gPT09ICfgsq7gsqfgs43gsq/gsr7gsrngs43gsqgnKSB7XG4gICAgICAgICAgICByZXR1cm4gaG91ciA+PSAxMCA/IGhvdXIgOiBob3VyICsgMTI7XG4gICAgICAgIH0gZWxzZSBpZiAobWVyaWRpZW0gPT09ICfgsrjgsoLgspzgs4YnKSB7XG4gICAgICAgICAgICByZXR1cm4gaG91ciArIDEyO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBtZXJpZGllbSA6IGZ1bmN0aW9uIChob3VyLCBtaW51dGUsIGlzTG93ZXIpIHtcbiAgICAgICAgaWYgKGhvdXIgPCA0KSB7XG4gICAgICAgICAgICByZXR1cm4gJ+CysOCyvuCypOCzjeCysOCyvyc7XG4gICAgICAgIH0gZWxzZSBpZiAoaG91ciA8IDEwKSB7XG4gICAgICAgICAgICByZXR1cm4gJ+CyrOCzhuCys+Cyv+Cyl+CzjeCyl+Czhic7XG4gICAgICAgIH0gZWxzZSBpZiAoaG91ciA8IDE3KSB7XG4gICAgICAgICAgICByZXR1cm4gJ+CyruCyp+CzjeCyr+CyvuCyueCzjeCyqCc7XG4gICAgICAgIH0gZWxzZSBpZiAoaG91ciA8IDIwKSB7XG4gICAgICAgICAgICByZXR1cm4gJ+CyuOCyguCynOCzhic7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gJ+CysOCyvuCypOCzjeCysOCyvyc7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfSjgsqjgs4bgs5UpLyxcbiAgICBvcmRpbmFsIDogZnVuY3Rpb24gKG51bWJlcikge1xuICAgICAgICByZXR1cm4gbnVtYmVyICsgJ+CyqOCzhuCzlSc7XG4gICAgfSxcbiAgICB3ZWVrIDoge1xuICAgICAgICBkb3cgOiAwLCAvLyBTdW5kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogNiAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gMXN0IGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH1cbn0pO1xuXG4vLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogS29yZWFuIFtrb11cbi8vISBhdXRob3IgOiBLeXVuZ3dvb2ssIFBhcmsgOiBodHRwczovL2dpdGh1Yi5jb20va3l1bmd3MDBrXG4vLyEgYXV0aG9yIDogSmVlZXl1bCBMZWUgPGplZWV5dWxAZ21haWwuY29tPlxuXG5ob29rcy5kZWZpbmVMb2NhbGUoJ2tvJywge1xuICAgIG1vbnRocyA6ICcx7JuUXzLsm5RfM+yblF807JuUXzXsm5RfNuyblF837JuUXzjsm5RfOeyblF8xMOyblF8xMeyblF8xMuyblCcuc3BsaXQoJ18nKSxcbiAgICBtb250aHNTaG9ydCA6ICcx7JuUXzLsm5RfM+yblF807JuUXzXsm5RfNuyblF837JuUXzjsm5RfOeyblF8xMOyblF8xMeyblF8xMuyblCcuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5cyA6ICfsnbzsmpTsnbxf7JuU7JqU7J28X+2ZlOyalOydvF/siJjsmpTsnbxf66qp7JqU7J28X+q4iOyalOydvF/thqDsmpTsnbwnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydCA6ICfsnbxf7JuUX+2ZlF/siJhf66qpX+q4iF/thqAnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW4gOiAn7J28X+yblF/tmZRf7IiYX+uqqV/quIhf7YagJy5zcGxpdCgnXycpLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdBIGg6bW0nLFxuICAgICAgICBMVFMgOiAnQSBoOm1tOnNzJyxcbiAgICAgICAgTCA6ICdZWVlZLk1NLkREJyxcbiAgICAgICAgTEwgOiAnWVlZWeuFhCBNTU1NIETsnbwnLFxuICAgICAgICBMTEwgOiAnWVlZWeuFhCBNTU1NIETsnbwgQSBoOm1tJyxcbiAgICAgICAgTExMTCA6ICdZWVlZ64WEIE1NTU0gROydvCBkZGRkIEEgaDptbScsXG4gICAgICAgIGwgOiAnWVlZWS5NTS5ERCcsXG4gICAgICAgIGxsIDogJ1lZWVnrhYQgTU1NTSBE7J28JyxcbiAgICAgICAgbGxsIDogJ1lZWVnrhYQgTU1NTSBE7J28IEEgaDptbScsXG4gICAgICAgIGxsbGwgOiAnWVlZWeuFhCBNTU1NIETsnbwgZGRkZCBBIGg6bW0nXG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheSA6ICfsmKTripggTFQnLFxuICAgICAgICBuZXh0RGF5IDogJ+uCtOydvCBMVCcsXG4gICAgICAgIG5leHRXZWVrIDogJ2RkZGQgTFQnLFxuICAgICAgICBsYXN0RGF5IDogJ+yWtOygnCBMVCcsXG4gICAgICAgIGxhc3RXZWVrIDogJ+yngOuCnOyjvCBkZGRkIExUJyxcbiAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJyVzIO2bhCcsXG4gICAgICAgIHBhc3QgOiAnJXMg7KCEJyxcbiAgICAgICAgcyA6ICfrqocg7LSIJyxcbiAgICAgICAgc3MgOiAnJWTstIgnLFxuICAgICAgICBtIDogJzHrtoQnLFxuICAgICAgICBtbSA6ICclZOu2hCcsXG4gICAgICAgIGggOiAn7ZWcIOyLnOqwhCcsXG4gICAgICAgIGhoIDogJyVk7Iuc6rCEJyxcbiAgICAgICAgZCA6ICftlZjro6gnLFxuICAgICAgICBkZCA6ICclZOydvCcsXG4gICAgICAgIE0gOiAn7ZWcIOuLrCcsXG4gICAgICAgIE1NIDogJyVk64usJyxcbiAgICAgICAgeSA6ICfsnbwg64WEJyxcbiAgICAgICAgeXkgOiAnJWTrhYQnXG4gICAgfSxcbiAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlIDogL1xcZHsxLDJ9KOydvHzsm5R87KO8KS8sXG4gICAgb3JkaW5hbCA6IGZ1bmN0aW9uIChudW1iZXIsIHBlcmlvZCkge1xuICAgICAgICBzd2l0Y2ggKHBlcmlvZCkge1xuICAgICAgICAgICAgY2FzZSAnZCc6XG4gICAgICAgICAgICBjYXNlICdEJzpcbiAgICAgICAgICAgIGNhc2UgJ0RERCc6XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICfsnbwnO1xuICAgICAgICAgICAgY2FzZSAnTSc6XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICfsm5QnO1xuICAgICAgICAgICAgY2FzZSAndyc6XG4gICAgICAgICAgICBjYXNlICdXJzpcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJ+yjvCc7XG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXI7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIG1lcmlkaWVtUGFyc2UgOiAv7Jik7KCEfOyYpO2bhC8sXG4gICAgaXNQTSA6IGZ1bmN0aW9uICh0b2tlbikge1xuICAgICAgICByZXR1cm4gdG9rZW4gPT09ICfsmKTtm4QnO1xuICAgIH0sXG4gICAgbWVyaWRpZW0gOiBmdW5jdGlvbiAoaG91ciwgbWludXRlLCBpc1VwcGVyKSB7XG4gICAgICAgIHJldHVybiBob3VyIDwgMTIgPyAn7Jik7KCEJyA6ICfsmKTtm4QnO1xuICAgIH1cbn0pO1xuXG4vLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogS3lyZ3l6IFtreV1cbi8vISBhdXRob3IgOiBDaHluZ3l6IEFyeXN0YW4gdXVsdSA6IGh0dHBzOi8vZ2l0aHViLmNvbS9jaHluZ3l6XG5cblxudmFyIHN1ZmZpeGVzJDIgPSB7XG4gICAgMDogJy3Rh9KvJyxcbiAgICAxOiAnLdGH0LgnLFxuICAgIDI6ICct0YfQuCcsXG4gICAgMzogJy3Rh9KvJyxcbiAgICA0OiAnLdGH0q8nLFxuICAgIDU6ICct0YfQuCcsXG4gICAgNjogJy3Rh9GLJyxcbiAgICA3OiAnLdGH0LgnLFxuICAgIDg6ICct0YfQuCcsXG4gICAgOTogJy3Rh9GDJyxcbiAgICAxMDogJy3Rh9GDJyxcbiAgICAyMDogJy3Rh9GLJyxcbiAgICAzMDogJy3Rh9GDJyxcbiAgICA0MDogJy3Rh9GLJyxcbiAgICA1MDogJy3Rh9KvJyxcbiAgICA2MDogJy3Rh9GLJyxcbiAgICA3MDogJy3Rh9C4JyxcbiAgICA4MDogJy3Rh9C4JyxcbiAgICA5MDogJy3Rh9GDJyxcbiAgICAxMDA6ICct0YfSrydcbn07XG5cbmhvb2tzLmRlZmluZUxvY2FsZSgna3knLCB7XG4gICAgbW9udGhzIDogJ9GP0L3QstCw0YDRjF/RhNC10LLRgNCw0LvRjF/QvNCw0YDRgl/QsNC/0YDQtdC70Yxf0LzQsNC5X9C40Y7QvdGMX9C40Y7Qu9GMX9Cw0LLQs9GD0YHRgl/RgdC10L3RgtGP0LHRgNGMX9C+0LrRgtGP0LHRgNGMX9C90L7Rj9Cx0YDRjF/QtNC10LrQsNCx0YDRjCcuc3BsaXQoJ18nKSxcbiAgICBtb250aHNTaG9ydCA6ICfRj9C90LJf0YTQtdCyX9C80LDRgNGCX9Cw0L/RgF/QvNCw0Llf0LjRjtC90Yxf0LjRjtC70Yxf0LDQstCzX9GB0LXQvV/QvtC60YJf0L3QvtGPX9C00LXQuicuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5cyA6ICfQltC10LrRiNC10LzQsdC4X9CU0q/QudGI06nQvNCx0q9f0KjQtdC50YjQtdC80LHQuF/QqNCw0YDRiNC10LzQsdC4X9CR0LXQudGI0LXQvNCx0Lhf0JbRg9C80LBf0JjRiNC10LzQsdC4Jy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzU2hvcnQgOiAn0JbQtdC6X9CU0q/QuV/QqNC10Llf0KjQsNGAX9CR0LXQuV/QltGD0Lxf0JjRiNC1Jy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzTWluIDogJ9CW0Lpf0JTQuV/QqNC5X9Co0YBf0JHQuV/QltC8X9CY0YgnLnNwbGl0KCdfJyksXG4gICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgIExUIDogJ0hIOm1tJyxcbiAgICAgICAgTFRTIDogJ0hIOm1tOnNzJyxcbiAgICAgICAgTCA6ICdERC5NTS5ZWVlZJyxcbiAgICAgICAgTEwgOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICBMTEwgOiAnRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICBMTExMIDogJ2RkZGQsIEQgTU1NTSBZWVlZIEhIOm1tJ1xuICAgIH0sXG4gICAgY2FsZW5kYXIgOiB7XG4gICAgICAgIHNhbWVEYXkgOiAnW9CR0q/Qs9Kv0L0g0YHQsNCw0YJdIExUJyxcbiAgICAgICAgbmV4dERheSA6ICdb0K3RgNGC0LXSoyDRgdCw0LDRgl0gTFQnLFxuICAgICAgICBuZXh0V2VlayA6ICdkZGRkIFvRgdCw0LDRgl0gTFQnLFxuICAgICAgICBsYXN0RGF5IDogJ1vQmtC10YfQtSDRgdCw0LDRgl0gTFQnLFxuICAgICAgICBsYXN0V2VlayA6ICdb06jRgtC60LXQvSDQsNC/0YLQsNC90YvQvV0gZGRkZCBb0LrSr9C90q9dIFvRgdCw0LDRgl0gTFQnLFxuICAgICAgICBzYW1lRWxzZSA6ICdMJ1xuICAgIH0sXG4gICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICBmdXR1cmUgOiAnJXMg0LjRh9C40L3QtNC1JyxcbiAgICAgICAgcGFzdCA6ICclcyDQvNGD0YDRg9C9JyxcbiAgICAgICAgcyA6ICfQsdC40YDQvdC10YfQtSDRgdC10LrRg9C90LQnLFxuICAgICAgICBzcyA6ICclZCDRgdC10LrRg9C90LQnLFxuICAgICAgICBtIDogJ9Cx0LjRgCDQvNKv0L3TqdGCJyxcbiAgICAgICAgbW0gOiAnJWQg0LzSr9C906nRgicsXG4gICAgICAgIGggOiAn0LHQuNGAINGB0LDQsNGCJyxcbiAgICAgICAgaGggOiAnJWQg0YHQsNCw0YInLFxuICAgICAgICBkIDogJ9Cx0LjRgCDQutKv0L0nLFxuICAgICAgICBkZCA6ICclZCDQutKv0L0nLFxuICAgICAgICBNIDogJ9Cx0LjRgCDQsNC5JyxcbiAgICAgICAgTU0gOiAnJWQg0LDQuScsXG4gICAgICAgIHkgOiAn0LHQuNGAINC20YvQuycsXG4gICAgICAgIHl5IDogJyVkINC20YvQuydcbiAgICB9LFxuICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfS0o0YfQuHzRh9GLfNGH0q980YfRgykvLFxuICAgIG9yZGluYWwgOiBmdW5jdGlvbiAobnVtYmVyKSB7XG4gICAgICAgIHZhciBhID0gbnVtYmVyICUgMTAsXG4gICAgICAgICAgICBiID0gbnVtYmVyID49IDEwMCA/IDEwMCA6IG51bGw7XG4gICAgICAgIHJldHVybiBudW1iZXIgKyAoc3VmZml4ZXMkMltudW1iZXJdIHx8IHN1ZmZpeGVzJDJbYV0gfHwgc3VmZml4ZXMkMltiXSk7XG4gICAgfSxcbiAgICB3ZWVrIDoge1xuICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogNyAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gMXN0IGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH1cbn0pO1xuXG4vLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogTHV4ZW1ib3VyZ2lzaCBbbGJdXG4vLyEgYXV0aG9yIDogbXdlaW1lcnNraXJjaCA6IGh0dHBzOi8vZ2l0aHViLmNvbS9td2VpbWVyc2tpcmNoXG4vLyEgYXV0aG9yIDogRGF2aWQgUmFpc29uIDogaHR0cHM6Ly9naXRodWIuY29tL2t3aXNhdHpcblxuZnVuY3Rpb24gcHJvY2Vzc1JlbGF0aXZlVGltZSQ1KG51bWJlciwgd2l0aG91dFN1ZmZpeCwga2V5LCBpc0Z1dHVyZSkge1xuICAgIHZhciBmb3JtYXQgPSB7XG4gICAgICAgICdtJzogWydlbmcgTWludXR0JywgJ2VuZ2VyIE1pbnV0dCddLFxuICAgICAgICAnaCc6IFsnZW5nIFN0b25uJywgJ2VuZ2VyIFN0b25uJ10sXG4gICAgICAgICdkJzogWydlZW4gRGFnJywgJ2VuZ2VtIERhZyddLFxuICAgICAgICAnTSc6IFsnZWUgTW91bnQnLCAnZW5nZW0gTW91bnQnXSxcbiAgICAgICAgJ3knOiBbJ2VlIEpvZXInLCAnZW5nZW0gSm9lciddXG4gICAgfTtcbiAgICByZXR1cm4gd2l0aG91dFN1ZmZpeCA/IGZvcm1hdFtrZXldWzBdIDogZm9ybWF0W2tleV1bMV07XG59XG5mdW5jdGlvbiBwcm9jZXNzRnV0dXJlVGltZShzdHJpbmcpIHtcbiAgICB2YXIgbnVtYmVyID0gc3RyaW5nLnN1YnN0cigwLCBzdHJpbmcuaW5kZXhPZignICcpKTtcbiAgICBpZiAoZWlmZWxlclJlZ2VsQXBwbGllc1RvTnVtYmVyKG51bWJlcikpIHtcbiAgICAgICAgcmV0dXJuICdhICcgKyBzdHJpbmc7XG4gICAgfVxuICAgIHJldHVybiAnYW4gJyArIHN0cmluZztcbn1cbmZ1bmN0aW9uIHByb2Nlc3NQYXN0VGltZShzdHJpbmcpIHtcbiAgICB2YXIgbnVtYmVyID0gc3RyaW5nLnN1YnN0cigwLCBzdHJpbmcuaW5kZXhPZignICcpKTtcbiAgICBpZiAoZWlmZWxlclJlZ2VsQXBwbGllc1RvTnVtYmVyKG51bWJlcikpIHtcbiAgICAgICAgcmV0dXJuICd2aXJ1ICcgKyBzdHJpbmc7XG4gICAgfVxuICAgIHJldHVybiAndmlydW4gJyArIHN0cmluZztcbn1cbi8qKlxuICogUmV0dXJucyB0cnVlIGlmIHRoZSB3b3JkIGJlZm9yZSB0aGUgZ2l2ZW4gbnVtYmVyIGxvc2VzIHRoZSAnLW4nIGVuZGluZy5cbiAqIGUuZy4gJ2FuIDEwIERlZWcnIGJ1dCAnYSA1IERlZWcnXG4gKlxuICogQHBhcmFtIG51bWJlciB7aW50ZWdlcn1cbiAqIEByZXR1cm5zIHtib29sZWFufVxuICovXG5mdW5jdGlvbiBlaWZlbGVyUmVnZWxBcHBsaWVzVG9OdW1iZXIobnVtYmVyKSB7XG4gICAgbnVtYmVyID0gcGFyc2VJbnQobnVtYmVyLCAxMCk7XG4gICAgaWYgKGlzTmFOKG51bWJlcikpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBpZiAobnVtYmVyIDwgMCkge1xuICAgICAgICAvLyBOZWdhdGl2ZSBOdW1iZXIgLS0+IGFsd2F5cyB0cnVlXG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH0gZWxzZSBpZiAobnVtYmVyIDwgMTApIHtcbiAgICAgICAgLy8gT25seSAxIGRpZ2l0XG4gICAgICAgIGlmICg0IDw9IG51bWJlciAmJiBudW1iZXIgPD0gNykge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH0gZWxzZSBpZiAobnVtYmVyIDwgMTAwKSB7XG4gICAgICAgIC8vIDIgZGlnaXRzXG4gICAgICAgIHZhciBsYXN0RGlnaXQgPSBudW1iZXIgJSAxMCwgZmlyc3REaWdpdCA9IG51bWJlciAvIDEwO1xuICAgICAgICBpZiAobGFzdERpZ2l0ID09PSAwKSB7XG4gICAgICAgICAgICByZXR1cm4gZWlmZWxlclJlZ2VsQXBwbGllc1RvTnVtYmVyKGZpcnN0RGlnaXQpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBlaWZlbGVyUmVnZWxBcHBsaWVzVG9OdW1iZXIobGFzdERpZ2l0KTtcbiAgICB9IGVsc2UgaWYgKG51bWJlciA8IDEwMDAwKSB7XG4gICAgICAgIC8vIDMgb3IgNCBkaWdpdHMgLS0+IHJlY3Vyc2l2ZWx5IGNoZWNrIGZpcnN0IGRpZ2l0XG4gICAgICAgIHdoaWxlIChudW1iZXIgPj0gMTApIHtcbiAgICAgICAgICAgIG51bWJlciA9IG51bWJlciAvIDEwO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBlaWZlbGVyUmVnZWxBcHBsaWVzVG9OdW1iZXIobnVtYmVyKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICAvLyBBbnl0aGluZyBsYXJnZXIgdGhhbiA0IGRpZ2l0czogcmVjdXJzaXZlbHkgY2hlY2sgZmlyc3Qgbi0zIGRpZ2l0c1xuICAgICAgICBudW1iZXIgPSBudW1iZXIgLyAxMDAwO1xuICAgICAgICByZXR1cm4gZWlmZWxlclJlZ2VsQXBwbGllc1RvTnVtYmVyKG51bWJlcik7XG4gICAgfVxufVxuXG5ob29rcy5kZWZpbmVMb2NhbGUoJ2xiJywge1xuICAgIG1vbnRoczogJ0phbnVhcl9GZWJydWFyX03DpGVyel9BYnLDq2xsX01lZV9KdW5pX0p1bGlfQXVndXN0X1NlcHRlbWJlcl9Pa3RvYmVyX05vdmVtYmVyX0RlemVtYmVyJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0OiAnSmFuLl9GZWJyLl9NcnouX0Fici5fTWVlX0p1bi5fSnVsLl9BdWcuX1NlcHQuX09rdC5fTm92Ll9EZXouJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgIHdlZWtkYXlzOiAnU29ubmRlZ19Nw6lpbmRlZ19Ew6tuc2NoZGVnX03Dq3R0d29jaF9Eb25uZXNjaGRlZ19GcmVpZGVnX1NhbXNjaGRlZycuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0OiAnU28uX03DqS5fRMOrLl9Nw6suX0RvLl9Gci5fU2EuJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzTWluOiAnU29fTcOpX0TDq19Nw6tfRG9fRnJfU2EnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNQYXJzZUV4YWN0IDogdHJ1ZSxcbiAgICBsb25nRGF0ZUZvcm1hdDoge1xuICAgICAgICBMVDogJ0g6bW0gW0F1ZXJdJyxcbiAgICAgICAgTFRTOiAnSDptbTpzcyBbQXVlcl0nLFxuICAgICAgICBMOiAnREQuTU0uWVlZWScsXG4gICAgICAgIExMOiAnRC4gTU1NTSBZWVlZJyxcbiAgICAgICAgTExMOiAnRC4gTU1NTSBZWVlZIEg6bW0gW0F1ZXJdJyxcbiAgICAgICAgTExMTDogJ2RkZGQsIEQuIE1NTU0gWVlZWSBIOm1tIFtBdWVyXSdcbiAgICB9LFxuICAgIGNhbGVuZGFyOiB7XG4gICAgICAgIHNhbWVEYXk6ICdbSGF1dCB1bV0gTFQnLFxuICAgICAgICBzYW1lRWxzZTogJ0wnLFxuICAgICAgICBuZXh0RGF5OiAnW011ZXIgdW1dIExUJyxcbiAgICAgICAgbmV4dFdlZWs6ICdkZGRkIFt1bV0gTFQnLFxuICAgICAgICBsYXN0RGF5OiAnW0fDq3NjaHRlciB1bV0gTFQnLFxuICAgICAgICBsYXN0V2VlazogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgLy8gRGlmZmVyZW50IGRhdGUgc3RyaW5nIGZvciAnRMOrbnNjaGRlZycgKFR1ZXNkYXkpIGFuZCAnRG9ubmVzY2hkZWcnIChUaHVyc2RheSkgZHVlIHRvIHBob25vbG9naWNhbCBydWxlXG4gICAgICAgICAgICBzd2l0Y2ggKHRoaXMuZGF5KCkpIHtcbiAgICAgICAgICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgICAgICAgY2FzZSA0OlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1tMZXNjaHRlbl0gZGRkZCBbdW1dIExUJztcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1tMZXNjaHRlXSBkZGRkIFt1bV0gTFQnO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6IHByb2Nlc3NGdXR1cmVUaW1lLFxuICAgICAgICBwYXN0IDogcHJvY2Vzc1Bhc3RUaW1lLFxuICAgICAgICBzIDogJ2UgcHVlciBTZWtvbm5lbicsXG4gICAgICAgIHNzIDogJyVkIFNla29ubmVuJyxcbiAgICAgICAgbSA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUkNSxcbiAgICAgICAgbW0gOiAnJWQgTWludXR0ZW4nLFxuICAgICAgICBoIDogcHJvY2Vzc1JlbGF0aXZlVGltZSQ1LFxuICAgICAgICBoaCA6ICclZCBTdG9ubmVuJyxcbiAgICAgICAgZCA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUkNSxcbiAgICAgICAgZGQgOiAnJWQgRGVlZycsXG4gICAgICAgIE0gOiBwcm9jZXNzUmVsYXRpdmVUaW1lJDUsXG4gICAgICAgIE1NIDogJyVkIE3DqWludCcsXG4gICAgICAgIHkgOiBwcm9jZXNzUmVsYXRpdmVUaW1lJDUsXG4gICAgICAgIHl5IDogJyVkIEpvZXInXG4gICAgfSxcbiAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn1cXC4vLFxuICAgIG9yZGluYWw6ICclZC4nLFxuICAgIHdlZWs6IHtcbiAgICAgICAgZG93OiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95OiA0ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgfVxufSk7XG5cbi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBMYW8gW2xvXVxuLy8hIGF1dGhvciA6IFJ5YW4gSGFydCA6IGh0dHBzOi8vZ2l0aHViLmNvbS9yeWFuaGFydDJcblxuaG9va3MuZGVmaW5lTG9jYWxlKCdsbycsIHtcbiAgICBtb250aHMgOiAn4Lqh4Lqx4LqH4LqB4Lqt4LqZX+C6geC6uOC6oeC6nuC6sl/guqHgurXgupngurJf4LuA4Lqh4Lqq4LqyX+C6nuC6tuC6lOC6quC6sOC6nuC6sl/guqHgurTgupbgurjgupngurJf4LqB4LuN4Lql4Lqw4LqB4Lq74LqUX+C6quC6tOC6h+C6q+C6sl/guoHgurHgupnguo3gurJf4LqV4Lq44Lql4LqyX+C6nuC6sOC6iOC6tOC6gV/gupfgurHgupnguqfgurInLnNwbGl0KCdfJyksXG4gICAgbW9udGhzU2hvcnQgOiAn4Lqh4Lqx4LqH4LqB4Lqt4LqZX+C6geC6uOC6oeC6nuC6sl/guqHgurXgupngurJf4LuA4Lqh4Lqq4LqyX+C6nuC6tuC6lOC6quC6sOC6nuC6sl/guqHgurTgupbgurjgupngurJf4LqB4LuN4Lql4Lqw4LqB4Lq74LqUX+C6quC6tOC6h+C6q+C6sl/guoHgurHgupnguo3gurJf4LqV4Lq44Lql4LqyX+C6nuC6sOC6iOC6tOC6gV/gupfgurHgupnguqfgurInLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXMgOiAn4Lqt4Lqy4LqX4Lq04LqUX+C6iOC6seC6mV/guq3gurHguofguoTgurLguplf4Lqe4Lq44LqUX+C6nuC6sOC6q+C6seC6lF/guqrgurjguoFf4LuA4Lqq4Lq74LqyJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzU2hvcnQgOiAn4LqX4Lq04LqUX+C6iOC6seC6mV/guq3gurHguofguoTgurLguplf4Lqe4Lq44LqUX+C6nuC6sOC6q+C6seC6lF/guqrgurjguoFf4LuA4Lqq4Lq74LqyJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzTWluIDogJ+C6l1/guohf4Lqt4LqEX+C6nl/gup7guqtf4Lqq4LqBX+C6qicuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdISDptbScsXG4gICAgICAgIExUUyA6ICdISDptbTpzcycsXG4gICAgICAgIEwgOiAnREQvTU0vWVlZWScsXG4gICAgICAgIExMIDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgTExMIDogJ0QgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgTExMTCA6ICfguqfgurHguplkZGRkIEQgTU1NTSBZWVlZIEhIOm1tJ1xuICAgIH0sXG4gICAgbWVyaWRpZW1QYXJzZTogL+C6leC6reC6meC7gOC6iuC6u+C7ieC6snzgupXguq3gupngu4HguqXguocvLFxuICAgIGlzUE06IGZ1bmN0aW9uIChpbnB1dCkge1xuICAgICAgICByZXR1cm4gaW5wdXQgPT09ICfgupXguq3gupngu4HguqXguocnO1xuICAgIH0sXG4gICAgbWVyaWRpZW0gOiBmdW5jdGlvbiAoaG91ciwgbWludXRlLCBpc0xvd2VyKSB7XG4gICAgICAgIGlmIChob3VyIDwgMTIpIHtcbiAgICAgICAgICAgIHJldHVybiAn4LqV4Lqt4LqZ4LuA4LqK4Lq74LuJ4LqyJztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiAn4LqV4Lqt4LqZ4LuB4Lql4LqHJztcbiAgICAgICAgfVxuICAgIH0sXG4gICAgY2FsZW5kYXIgOiB7XG4gICAgICAgIHNhbWVEYXkgOiAnW+C6oeC6t+C7ieC6meC6teC7ieC7gOC6p+C6peC6sl0gTFQnLFxuICAgICAgICBuZXh0RGF5IDogJ1vguqHgurfgu4nguq3gurfgu4jgupngu4DguqfguqXgurJdIExUJyxcbiAgICAgICAgbmV4dFdlZWsgOiAnW+C6p+C6seC6mV1kZGRkW+C7nOC7ieC6suC7gOC6p+C6peC6sl0gTFQnLFxuICAgICAgICBsYXN0RGF5IDogJ1vguqHgurfgu4nguqfgurLgupngupngurXgu4ngu4DguqfguqXgurJdIExUJyxcbiAgICAgICAgbGFzdFdlZWsgOiAnW+C6p+C6seC6mV1kZGRkW+C7geC6peC7ieC6p+C6meC6teC7ieC7gOC6p+C6peC6sl0gTFQnLFxuICAgICAgICBzYW1lRWxzZSA6ICdMJ1xuICAgIH0sXG4gICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICBmdXR1cmUgOiAn4Lqt4Lq14LqBICVzJyxcbiAgICAgICAgcGFzdCA6ICclc+C6nOC7iOC6suC6meC6oeC6sicsXG4gICAgICAgIHMgOiAn4Lqa4LuN4LuI4LuA4LqX4Lq74LuI4Lqy4LuD4LqU4Lqn4Lq04LqZ4Lqy4LqX4Lq1JyxcbiAgICAgICAgc3MgOiAnJWQg4Lqn4Lq04LqZ4Lqy4LqX4Lq1JyAsXG4gICAgICAgIG0gOiAnMSDgupngurLgupfgurUnLFxuICAgICAgICBtbSA6ICclZCDgupngurLgupfgurUnLFxuICAgICAgICBoIDogJzEg4LqK4Lq74LuI4Lqn4LuC4Lqh4LqHJyxcbiAgICAgICAgaGggOiAnJWQg4LqK4Lq74LuI4Lqn4LuC4Lqh4LqHJyxcbiAgICAgICAgZCA6ICcxIOC6oeC6t+C7iScsXG4gICAgICAgIGRkIDogJyVkIOC6oeC6t+C7iScsXG4gICAgICAgIE0gOiAnMSDgu4DgupTgurfguq3gupknLFxuICAgICAgICBNTSA6ICclZCDgu4DgupTgurfguq3gupknLFxuICAgICAgICB5IDogJzEg4Lqb4Lq1JyxcbiAgICAgICAgeXkgOiAnJWQg4Lqb4Lq1J1xuICAgIH0sXG4gICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogLyjgupfgurXgu4gpXFxkezEsMn0vLFxuICAgIG9yZGluYWwgOiBmdW5jdGlvbiAobnVtYmVyKSB7XG4gICAgICAgIHJldHVybiAn4LqX4Lq14LuIJyArIG51bWJlcjtcbiAgICB9XG59KTtcblxuLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSA6IExpdGh1YW5pYW4gW2x0XVxuLy8hIGF1dGhvciA6IE1pbmRhdWdhcyBNb3rFq3JhcyA6IGh0dHBzOi8vZ2l0aHViLmNvbS9tbW96dXJhc1xuXG52YXIgdW5pdHMgPSB7XG4gICAgJ3NzJyA6ICdzZWt1bmTEl19zZWt1bmTFvmnFs19zZWt1bmRlcycsXG4gICAgJ20nIDogJ21pbnV0xJdfbWludXTEl3NfbWludXTEmScsXG4gICAgJ21tJzogJ21pbnV0xJdzX21pbnXEjWnFs19taW51dGVzJyxcbiAgICAnaCcgOiAndmFsYW5kYV92YWxhbmRvc192YWxhbmTEhScsXG4gICAgJ2hoJzogJ3ZhbGFuZG9zX3ZhbGFuZMWzX3ZhbGFuZGFzJyxcbiAgICAnZCcgOiAnZGllbmFfZGllbm9zX2RpZW7EhScsXG4gICAgJ2RkJzogJ2RpZW5vc19kaWVuxbNfZGllbmFzJyxcbiAgICAnTScgOiAnbcSXbnVvX23El25lc2lvX23El25lc8SvJyxcbiAgICAnTU0nOiAnbcSXbmVzaWFpX23El25lc2nFs19txJduZXNpdXMnLFxuICAgICd5JyA6ICdtZXRhaV9tZXTFs19tZXR1cycsXG4gICAgJ3l5JzogJ21ldGFpX21ldMWzX21ldHVzJ1xufTtcbmZ1bmN0aW9uIHRyYW5zbGF0ZVNlY29uZHMobnVtYmVyLCB3aXRob3V0U3VmZml4LCBrZXksIGlzRnV0dXJlKSB7XG4gICAgaWYgKHdpdGhvdXRTdWZmaXgpIHtcbiAgICAgICAgcmV0dXJuICdrZWxpb3Mgc2VrdW5kxJdzJztcbiAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gaXNGdXR1cmUgPyAna2VsacWzIHNla3VuZMW+acWzJyA6ICdrZWxpYXMgc2VrdW5kZXMnO1xuICAgIH1cbn1cbmZ1bmN0aW9uIHRyYW5zbGF0ZVNpbmd1bGFyKG51bWJlciwgd2l0aG91dFN1ZmZpeCwga2V5LCBpc0Z1dHVyZSkge1xuICAgIHJldHVybiB3aXRob3V0U3VmZml4ID8gZm9ybXMoa2V5KVswXSA6IChpc0Z1dHVyZSA/IGZvcm1zKGtleSlbMV0gOiBmb3JtcyhrZXkpWzJdKTtcbn1cbmZ1bmN0aW9uIHNwZWNpYWwobnVtYmVyKSB7XG4gICAgcmV0dXJuIG51bWJlciAlIDEwID09PSAwIHx8IChudW1iZXIgPiAxMCAmJiBudW1iZXIgPCAyMCk7XG59XG5mdW5jdGlvbiBmb3JtcyhrZXkpIHtcbiAgICByZXR1cm4gdW5pdHNba2V5XS5zcGxpdCgnXycpO1xufVxuZnVuY3Rpb24gdHJhbnNsYXRlJDYobnVtYmVyLCB3aXRob3V0U3VmZml4LCBrZXksIGlzRnV0dXJlKSB7XG4gICAgdmFyIHJlc3VsdCA9IG51bWJlciArICcgJztcbiAgICBpZiAobnVtYmVyID09PSAxKSB7XG4gICAgICAgIHJldHVybiByZXN1bHQgKyB0cmFuc2xhdGVTaW5ndWxhcihudW1iZXIsIHdpdGhvdXRTdWZmaXgsIGtleVswXSwgaXNGdXR1cmUpO1xuICAgIH0gZWxzZSBpZiAod2l0aG91dFN1ZmZpeCkge1xuICAgICAgICByZXR1cm4gcmVzdWx0ICsgKHNwZWNpYWwobnVtYmVyKSA/IGZvcm1zKGtleSlbMV0gOiBmb3JtcyhrZXkpWzBdKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBpZiAoaXNGdXR1cmUpIHtcbiAgICAgICAgICAgIHJldHVybiByZXN1bHQgKyBmb3JtcyhrZXkpWzFdO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCArIChzcGVjaWFsKG51bWJlcikgPyBmb3JtcyhrZXkpWzFdIDogZm9ybXMoa2V5KVsyXSk7XG4gICAgICAgIH1cbiAgICB9XG59XG5ob29rcy5kZWZpbmVMb2NhbGUoJ2x0Jywge1xuICAgIG1vbnRocyA6IHtcbiAgICAgICAgZm9ybWF0OiAnc2F1c2lvX3Zhc2FyaW9fa292b19iYWxhbmTFvmlvX2dlZ3XFvsSXc19iaXLFvmVsaW9fbGllcG9zX3J1Z3BqxavEjWlvX3J1Z3PEl2pvX3NwYWxpb19sYXBrcmnEjWlvX2dydW9kxb5pbycuc3BsaXQoJ18nKSxcbiAgICAgICAgc3RhbmRhbG9uZTogJ3NhdXNpc192YXNhcmlzX2tvdmFzX2JhbGFuZGlzX2dlZ3XFvsSXX2JpcsW+ZWxpc19saWVwYV9ydWdwasWrdGlzX3J1Z3PEl2ppc19zcGFsaXNfbGFwa3JpdGlzX2dydW9kaXMnLnNwbGl0KCdfJyksXG4gICAgICAgIGlzRm9ybWF0OiAvRFtvRF0/KFxcW1teXFxbXFxdXSpcXF18XFxzKStNTU1NP3xNTU1NPyhcXFtbXlxcW1xcXV0qXFxdfFxccykrRFtvRF0/L1xuICAgIH0sXG4gICAgbW9udGhzU2hvcnQgOiAnc2F1X3Zhc19rb3ZfYmFsX2dlZ19iaXJfbGllX3JncF9yZ3Nfc3BhX2xhcF9ncmQnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXMgOiB7XG4gICAgICAgIGZvcm1hdDogJ3Nla21hZGllbsSvX3Bpcm1hZGllbsSvX2FudHJhZGllbsSvX3RyZcSNaWFkaWVuxK9fa2V0dmlydGFkaWVuxK9fcGVua3RhZGllbsSvX8WhZcWhdGFkaWVuxK8nLnNwbGl0KCdfJyksXG4gICAgICAgIHN0YW5kYWxvbmU6ICdzZWttYWRpZW5pc19waXJtYWRpZW5pc19hbnRyYWRpZW5pc190cmXEjWlhZGllbmlzX2tldHZpcnRhZGllbmlzX3Blbmt0YWRpZW5pc1/FoWXFoXRhZGllbmlzJy5zcGxpdCgnXycpLFxuICAgICAgICBpc0Zvcm1hdDogL2RkZGQgSEg6bW0vXG4gICAgfSxcbiAgICB3ZWVrZGF5c1Nob3J0IDogJ1Nla19QaXJfQW50X1RyZV9LZXRfUGVuX8WgZcWhJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzTWluIDogJ1NfUF9BX1RfS19Qbl/FoCcuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdISDptbScsXG4gICAgICAgIExUUyA6ICdISDptbTpzcycsXG4gICAgICAgIEwgOiAnWVlZWS1NTS1ERCcsXG4gICAgICAgIExMIDogJ1lZWVkgW20uXSBNTU1NIEQgW2QuXScsXG4gICAgICAgIExMTCA6ICdZWVlZIFttLl0gTU1NTSBEIFtkLl0sIEhIOm1tIFt2YWwuXScsXG4gICAgICAgIExMTEwgOiAnWVlZWSBbbS5dIE1NTU0gRCBbZC5dLCBkZGRkLCBISDptbSBbdmFsLl0nLFxuICAgICAgICBsIDogJ1lZWVktTU0tREQnLFxuICAgICAgICBsbCA6ICdZWVlZIFttLl0gTU1NTSBEIFtkLl0nLFxuICAgICAgICBsbGwgOiAnWVlZWSBbbS5dIE1NTU0gRCBbZC5dLCBISDptbSBbdmFsLl0nLFxuICAgICAgICBsbGxsIDogJ1lZWVkgW20uXSBNTU1NIEQgW2QuXSwgZGRkLCBISDptbSBbdmFsLl0nXG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheSA6ICdbxaBpYW5kaWVuXSBMVCcsXG4gICAgICAgIG5leHREYXkgOiAnW1J5dG9qXSBMVCcsXG4gICAgICAgIG5leHRXZWVrIDogJ2RkZGQgTFQnLFxuICAgICAgICBsYXN0RGF5IDogJ1tWYWthcl0gTFQnLFxuICAgICAgICBsYXN0V2VlayA6ICdbUHJhxJdqdXPEr10gZGRkZCBMVCcsXG4gICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6ICdwbyAlcycsXG4gICAgICAgIHBhc3QgOiAncHJpZcWhICVzJyxcbiAgICAgICAgcyA6IHRyYW5zbGF0ZVNlY29uZHMsXG4gICAgICAgIHNzIDogdHJhbnNsYXRlJDYsXG4gICAgICAgIG0gOiB0cmFuc2xhdGVTaW5ndWxhcixcbiAgICAgICAgbW0gOiB0cmFuc2xhdGUkNixcbiAgICAgICAgaCA6IHRyYW5zbGF0ZVNpbmd1bGFyLFxuICAgICAgICBoaCA6IHRyYW5zbGF0ZSQ2LFxuICAgICAgICBkIDogdHJhbnNsYXRlU2luZ3VsYXIsXG4gICAgICAgIGRkIDogdHJhbnNsYXRlJDYsXG4gICAgICAgIE0gOiB0cmFuc2xhdGVTaW5ndWxhcixcbiAgICAgICAgTU0gOiB0cmFuc2xhdGUkNixcbiAgICAgICAgeSA6IHRyYW5zbGF0ZVNpbmd1bGFyLFxuICAgICAgICB5eSA6IHRyYW5zbGF0ZSQ2XG4gICAgfSxcbiAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn0tb2ppLyxcbiAgICBvcmRpbmFsIDogZnVuY3Rpb24gKG51bWJlcikge1xuICAgICAgICByZXR1cm4gbnVtYmVyICsgJy1vamknO1xuICAgIH0sXG4gICAgd2VlayA6IHtcbiAgICAgICAgZG93IDogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgIGRveSA6IDQgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDR0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICB9XG59KTtcblxuLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSA6IExhdHZpYW4gW2x2XVxuLy8hIGF1dGhvciA6IEtyaXN0YXBzIEthcmxzb25zIDogaHR0cHM6Ly9naXRodWIuY29tL3NrYWtyaVxuLy8hIGF1dGhvciA6IErEgW5pcyBFbG1lcmlzIDogaHR0cHM6Ly9naXRodWIuY29tL0phbmlzRVxuXG52YXIgdW5pdHMkMSA9IHtcbiAgICAnc3MnOiAnc2VrdW5kZXNfc2VrdW5kxJNtX3Nla3VuZGVfc2VrdW5kZXMnLnNwbGl0KCdfJyksXG4gICAgJ20nOiAnbWluxat0ZXNfbWluxat0xJNtX21pbsWrdGVfbWluxat0ZXMnLnNwbGl0KCdfJyksXG4gICAgJ21tJzogJ21pbsWrdGVzX21pbsWrdMSTbV9taW7Fq3RlX21pbsWrdGVzJy5zcGxpdCgnXycpLFxuICAgICdoJzogJ3N0dW5kYXNfc3R1bmTEgW1fc3R1bmRhX3N0dW5kYXMnLnNwbGl0KCdfJyksXG4gICAgJ2hoJzogJ3N0dW5kYXNfc3R1bmTEgW1fc3R1bmRhX3N0dW5kYXMnLnNwbGl0KCdfJyksXG4gICAgJ2QnOiAnZGllbmFzX2RpZW7EgW1fZGllbmFfZGllbmFzJy5zcGxpdCgnXycpLFxuICAgICdkZCc6ICdkaWVuYXNfZGllbsSBbV9kaWVuYV9kaWVuYXMnLnNwbGl0KCdfJyksXG4gICAgJ00nOiAnbcSTbmXFoWFfbcSTbmXFoWllbV9txJNuZXNpc19txJNuZcWhaScuc3BsaXQoJ18nKSxcbiAgICAnTU0nOiAnbcSTbmXFoWFfbcSTbmXFoWllbV9txJNuZXNpc19txJNuZcWhaScuc3BsaXQoJ18nKSxcbiAgICAneSc6ICdnYWRhX2dhZGllbV9nYWRzX2dhZGknLnNwbGl0KCdfJyksXG4gICAgJ3l5JzogJ2dhZGFfZ2FkaWVtX2dhZHNfZ2FkaScuc3BsaXQoJ18nKVxufTtcbi8qKlxuICogQHBhcmFtIHdpdGhvdXRTdWZmaXggYm9vbGVhbiB0cnVlID0gYSBsZW5ndGggb2YgdGltZTsgZmFsc2UgPSBiZWZvcmUvYWZ0ZXIgYSBwZXJpb2Qgb2YgdGltZS5cbiAqL1xuZnVuY3Rpb24gZm9ybWF0JDEoZm9ybXMsIG51bWJlciwgd2l0aG91dFN1ZmZpeCkge1xuICAgIGlmICh3aXRob3V0U3VmZml4KSB7XG4gICAgICAgIC8vIEUuZy4gXCIyMSBtaW7Fq3RlXCIsIFwiMyBtaW7Fq3Rlc1wiLlxuICAgICAgICByZXR1cm4gbnVtYmVyICUgMTAgPT09IDEgJiYgbnVtYmVyICUgMTAwICE9PSAxMSA/IGZvcm1zWzJdIDogZm9ybXNbM107XG4gICAgfSBlbHNlIHtcbiAgICAgICAgLy8gRS5nLiBcIjIxIG1pbsWrdGVzXCIgYXMgaW4gXCJwxJNjIDIxIG1pbsWrdGVzXCIuXG4gICAgICAgIC8vIEUuZy4gXCIzIG1pbsWrdMSTbVwiIGFzIGluIFwicMSTYyAzIG1pbsWrdMSTbVwiLlxuICAgICAgICByZXR1cm4gbnVtYmVyICUgMTAgPT09IDEgJiYgbnVtYmVyICUgMTAwICE9PSAxMSA/IGZvcm1zWzBdIDogZm9ybXNbMV07XG4gICAgfVxufVxuZnVuY3Rpb24gcmVsYXRpdmVUaW1lV2l0aFBsdXJhbCQxKG51bWJlciwgd2l0aG91dFN1ZmZpeCwga2V5KSB7XG4gICAgcmV0dXJuIG51bWJlciArICcgJyArIGZvcm1hdCQxKHVuaXRzJDFba2V5XSwgbnVtYmVyLCB3aXRob3V0U3VmZml4KTtcbn1cbmZ1bmN0aW9uIHJlbGF0aXZlVGltZVdpdGhTaW5ndWxhcihudW1iZXIsIHdpdGhvdXRTdWZmaXgsIGtleSkge1xuICAgIHJldHVybiBmb3JtYXQkMSh1bml0cyQxW2tleV0sIG51bWJlciwgd2l0aG91dFN1ZmZpeCk7XG59XG5mdW5jdGlvbiByZWxhdGl2ZVNlY29uZHMobnVtYmVyLCB3aXRob3V0U3VmZml4KSB7XG4gICAgcmV0dXJuIHdpdGhvdXRTdWZmaXggPyAnZGHFvmFzIHNla3VuZGVzJyA6ICdkYcW+xIFtIHNla3VuZMSTbSc7XG59XG5cbmhvb2tzLmRlZmluZUxvY2FsZSgnbHYnLCB7XG4gICAgbW9udGhzIDogJ2phbnbEgXJpc19mZWJydcSBcmlzX21hcnRzX2FwcsSrbGlzX21haWpzX2rFq25panNfasWrbGlqc19hdWd1c3RzX3NlcHRlbWJyaXNfb2t0b2JyaXNfbm92ZW1icmlzX2RlY2VtYnJpcycuc3BsaXQoJ18nKSxcbiAgICBtb250aHNTaG9ydCA6ICdqYW5fZmViX21hcl9hcHJfbWFpX2rFq25fasWrbF9hdWdfc2VwX29rdF9ub3ZfZGVjJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzIDogJ3N2xJN0ZGllbmFfcGlybWRpZW5hX290cmRpZW5hX3RyZcWhZGllbmFfY2V0dXJ0ZGllbmFfcGlla3RkaWVuYV9zZXN0ZGllbmEnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydCA6ICdTdl9QX09fVF9DX1BrX1MnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW4gOiAnU3ZfUF9PX1RfQ19Qa19TJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzUGFyc2VFeGFjdCA6IHRydWUsXG4gICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgIExUIDogJ0hIOm1tJyxcbiAgICAgICAgTFRTIDogJ0hIOm1tOnNzJyxcbiAgICAgICAgTCA6ICdERC5NTS5ZWVlZLicsXG4gICAgICAgIExMIDogJ1lZWVkuIFtnYWRhXSBELiBNTU1NJyxcbiAgICAgICAgTExMIDogJ1lZWVkuIFtnYWRhXSBELiBNTU1NLCBISDptbScsXG4gICAgICAgIExMTEwgOiAnWVlZWS4gW2dhZGFdIEQuIE1NTU0sIGRkZGQsIEhIOm1tJ1xuICAgIH0sXG4gICAgY2FsZW5kYXIgOiB7XG4gICAgICAgIHNhbWVEYXkgOiAnW8Wgb2RpZW4gcHVsa3N0ZW5dIExUJyxcbiAgICAgICAgbmV4dERheSA6ICdbUsSrdCBwdWxrc3Rlbl0gTFQnLFxuICAgICAgICBuZXh0V2VlayA6ICdkZGRkIFtwdWxrc3Rlbl0gTFQnLFxuICAgICAgICBsYXN0RGF5IDogJ1tWYWthciBwdWxrc3Rlbl0gTFQnLFxuICAgICAgICBsYXN0V2VlayA6ICdbUGFnxIFqdcWhxIFdIGRkZGQgW3B1bGtzdGVuXSBMVCcsXG4gICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6ICdwxJNjICVzJyxcbiAgICAgICAgcGFzdCA6ICdwaXJtcyAlcycsXG4gICAgICAgIHMgOiByZWxhdGl2ZVNlY29uZHMsXG4gICAgICAgIHNzIDogcmVsYXRpdmVUaW1lV2l0aFBsdXJhbCQxLFxuICAgICAgICBtIDogcmVsYXRpdmVUaW1lV2l0aFNpbmd1bGFyLFxuICAgICAgICBtbSA6IHJlbGF0aXZlVGltZVdpdGhQbHVyYWwkMSxcbiAgICAgICAgaCA6IHJlbGF0aXZlVGltZVdpdGhTaW5ndWxhcixcbiAgICAgICAgaGggOiByZWxhdGl2ZVRpbWVXaXRoUGx1cmFsJDEsXG4gICAgICAgIGQgOiByZWxhdGl2ZVRpbWVXaXRoU2luZ3VsYXIsXG4gICAgICAgIGRkIDogcmVsYXRpdmVUaW1lV2l0aFBsdXJhbCQxLFxuICAgICAgICBNIDogcmVsYXRpdmVUaW1lV2l0aFNpbmd1bGFyLFxuICAgICAgICBNTSA6IHJlbGF0aXZlVGltZVdpdGhQbHVyYWwkMSxcbiAgICAgICAgeSA6IHJlbGF0aXZlVGltZVdpdGhTaW5ndWxhcixcbiAgICAgICAgeXkgOiByZWxhdGl2ZVRpbWVXaXRoUGx1cmFsJDFcbiAgICB9LFxuICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfVxcLi8sXG4gICAgb3JkaW5hbCA6ICclZC4nLFxuICAgIHdlZWsgOiB7XG4gICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICBkb3kgOiA0ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgfVxufSk7XG5cbi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBNb250ZW5lZ3JpbiBbbWVdXG4vLyEgYXV0aG9yIDogTWlvZHJhZyBOaWthxI0gPG1pb2RyYWdAcmVzdGFydGl0Lm1lPiA6IGh0dHBzOi8vZ2l0aHViLmNvbS9taW9kcmFnbmlrYWNcblxudmFyIHRyYW5zbGF0b3IgPSB7XG4gICAgd29yZHM6IHsgLy9EaWZmZXJlbnQgZ3JhbW1hdGljYWwgY2FzZXNcbiAgICAgICAgc3M6IFsnc2VrdW5kJywgJ3Nla3VuZGEnLCAnc2VrdW5kaSddLFxuICAgICAgICBtOiBbJ2plZGFuIG1pbnV0JywgJ2plZG5vZyBtaW51dGEnXSxcbiAgICAgICAgbW06IFsnbWludXQnLCAnbWludXRhJywgJ21pbnV0YSddLFxuICAgICAgICBoOiBbJ2plZGFuIHNhdCcsICdqZWRub2cgc2F0YSddLFxuICAgICAgICBoaDogWydzYXQnLCAnc2F0YScsICdzYXRpJ10sXG4gICAgICAgIGRkOiBbJ2RhbicsICdkYW5hJywgJ2RhbmEnXSxcbiAgICAgICAgTU06IFsnbWplc2VjJywgJ21qZXNlY2EnLCAnbWplc2VjaSddLFxuICAgICAgICB5eTogWydnb2RpbmEnLCAnZ29kaW5lJywgJ2dvZGluYSddXG4gICAgfSxcbiAgICBjb3JyZWN0R3JhbW1hdGljYWxDYXNlOiBmdW5jdGlvbiAobnVtYmVyLCB3b3JkS2V5KSB7XG4gICAgICAgIHJldHVybiBudW1iZXIgPT09IDEgPyB3b3JkS2V5WzBdIDogKG51bWJlciA+PSAyICYmIG51bWJlciA8PSA0ID8gd29yZEtleVsxXSA6IHdvcmRLZXlbMl0pO1xuICAgIH0sXG4gICAgdHJhbnNsYXRlOiBmdW5jdGlvbiAobnVtYmVyLCB3aXRob3V0U3VmZml4LCBrZXkpIHtcbiAgICAgICAgdmFyIHdvcmRLZXkgPSB0cmFuc2xhdG9yLndvcmRzW2tleV07XG4gICAgICAgIGlmIChrZXkubGVuZ3RoID09PSAxKSB7XG4gICAgICAgICAgICByZXR1cm4gd2l0aG91dFN1ZmZpeCA/IHdvcmRLZXlbMF0gOiB3b3JkS2V5WzFdO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICcgJyArIHRyYW5zbGF0b3IuY29ycmVjdEdyYW1tYXRpY2FsQ2FzZShudW1iZXIsIHdvcmRLZXkpO1xuICAgICAgICB9XG4gICAgfVxufTtcblxuaG9va3MuZGVmaW5lTG9jYWxlKCdtZScsIHtcbiAgICBtb250aHM6ICdqYW51YXJfZmVicnVhcl9tYXJ0X2FwcmlsX21hal9qdW5fanVsX2F2Z3VzdF9zZXB0ZW1iYXJfb2t0b2Jhcl9ub3ZlbWJhcl9kZWNlbWJhcicuc3BsaXQoJ18nKSxcbiAgICBtb250aHNTaG9ydDogJ2phbi5fZmViLl9tYXIuX2Fwci5fbWFqX2p1bl9qdWxfYXZnLl9zZXAuX29rdC5fbm92Ll9kZWMuJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgIHdlZWtkYXlzOiAnbmVkamVsamFfcG9uZWRqZWxqYWtfdXRvcmFrX3NyaWplZGFfxI1ldHZydGFrX3BldGFrX3N1Ym90YScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0OiAnbmVkLl9wb24uX3V0by5fc3JpLl/EjWV0Ll9wZXQuX3N1Yi4nLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW46ICduZV9wb191dF9zcl/EjWVfcGVfc3UnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNQYXJzZUV4YWN0IDogdHJ1ZSxcbiAgICBsb25nRGF0ZUZvcm1hdDoge1xuICAgICAgICBMVDogJ0g6bW0nLFxuICAgICAgICBMVFMgOiAnSDptbTpzcycsXG4gICAgICAgIEw6ICdERC5NTS5ZWVlZJyxcbiAgICAgICAgTEw6ICdELiBNTU1NIFlZWVknLFxuICAgICAgICBMTEw6ICdELiBNTU1NIFlZWVkgSDptbScsXG4gICAgICAgIExMTEw6ICdkZGRkLCBELiBNTU1NIFlZWVkgSDptbSdcbiAgICB9LFxuICAgIGNhbGVuZGFyOiB7XG4gICAgICAgIHNhbWVEYXk6ICdbZGFuYXMgdV0gTFQnLFxuICAgICAgICBuZXh0RGF5OiAnW3NqdXRyYSB1XSBMVCcsXG5cbiAgICAgICAgbmV4dFdlZWs6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHN3aXRjaCAodGhpcy5kYXkoKSkge1xuICAgICAgICAgICAgICAgIGNhc2UgMDpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbdV0gW25lZGplbGp1XSBbdV0gTFQnO1xuICAgICAgICAgICAgICAgIGNhc2UgMzpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbdV0gW3NyaWplZHVdIFt1XSBMVCc7XG4gICAgICAgICAgICAgICAgY2FzZSA2OlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1t1XSBbc3Vib3R1XSBbdV0gTFQnO1xuICAgICAgICAgICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgICAgICAgY2FzZSA0OlxuICAgICAgICAgICAgICAgIGNhc2UgNTpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbdV0gZGRkZCBbdV0gTFQnO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBsYXN0RGF5ICA6ICdbanXEjWUgdV0gTFQnLFxuICAgICAgICBsYXN0V2VlayA6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBsYXN0V2Vla0RheXMgPSBbXG4gICAgICAgICAgICAgICAgJ1twcm/FoWxlXSBbbmVkamVsamVdIFt1XSBMVCcsXG4gICAgICAgICAgICAgICAgJ1twcm/FoWxvZ10gW3BvbmVkamVsamthXSBbdV0gTFQnLFxuICAgICAgICAgICAgICAgICdbcHJvxaFsb2ddIFt1dG9ya2FdIFt1XSBMVCcsXG4gICAgICAgICAgICAgICAgJ1twcm/FoWxlXSBbc3JpamVkZV0gW3VdIExUJyxcbiAgICAgICAgICAgICAgICAnW3Byb8WhbG9nXSBbxI1ldHZydGthXSBbdV0gTFQnLFxuICAgICAgICAgICAgICAgICdbcHJvxaFsb2ddIFtwZXRrYV0gW3VdIExUJyxcbiAgICAgICAgICAgICAgICAnW3Byb8WhbGVdIFtzdWJvdGVdIFt1XSBMVCdcbiAgICAgICAgICAgIF07XG4gICAgICAgICAgICByZXR1cm4gbGFzdFdlZWtEYXlzW3RoaXMuZGF5KCldO1xuICAgICAgICB9LFxuICAgICAgICBzYW1lRWxzZSA6ICdMJ1xuICAgIH0sXG4gICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICBmdXR1cmUgOiAnemEgJXMnLFxuICAgICAgICBwYXN0ICAgOiAncHJpamUgJXMnLFxuICAgICAgICBzICAgICAgOiAnbmVrb2xpa28gc2VrdW5kaScsXG4gICAgICAgIHNzICAgICA6IHRyYW5zbGF0b3IudHJhbnNsYXRlLFxuICAgICAgICBtICAgICAgOiB0cmFuc2xhdG9yLnRyYW5zbGF0ZSxcbiAgICAgICAgbW0gICAgIDogdHJhbnNsYXRvci50cmFuc2xhdGUsXG4gICAgICAgIGggICAgICA6IHRyYW5zbGF0b3IudHJhbnNsYXRlLFxuICAgICAgICBoaCAgICAgOiB0cmFuc2xhdG9yLnRyYW5zbGF0ZSxcbiAgICAgICAgZCAgICAgIDogJ2RhbicsXG4gICAgICAgIGRkICAgICA6IHRyYW5zbGF0b3IudHJhbnNsYXRlLFxuICAgICAgICBNICAgICAgOiAnbWplc2VjJyxcbiAgICAgICAgTU0gICAgIDogdHJhbnNsYXRvci50cmFuc2xhdGUsXG4gICAgICAgIHkgICAgICA6ICdnb2RpbnUnLFxuICAgICAgICB5eSAgICAgOiB0cmFuc2xhdG9yLnRyYW5zbGF0ZVxuICAgIH0sXG4gICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9XFwuLyxcbiAgICBvcmRpbmFsIDogJyVkLicsXG4gICAgd2VlayA6IHtcbiAgICAgICAgZG93IDogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgIGRveSA6IDcgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDFzdCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICB9XG59KTtcblxuLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSA6IE1hb3JpIFttaV1cbi8vISBhdXRob3IgOiBKb2huIENvcnJpZ2FuIDxyb2JiaWVjbG9zZXRAZ21haWwuY29tPiA6IGh0dHBzOi8vZ2l0aHViLmNvbS9qb2huaWRlYWxcblxuaG9va3MuZGVmaW5lTG9jYWxlKCdtaScsIHtcbiAgICBtb250aHM6ICdLb2hpLXTEgXRlX0h1aS10YW5ndXJ1X1BvdXTFqy10ZS1yYW5naV9QYWVuZ2Etd2jEgXdoxIFfSGFyYXR1YV9QaXBpcmlfSMWNbmdvaW5nb2lfSGVyZS10dXJpLWvFjWvEgV9NYWh1cnVfV2hpcmluZ2EtxIEtbnVrdV9XaGlyaW5nYS3EgS1yYW5naV9IYWtpaGVhJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0OiAnS29oaV9IdWlfUG91X1BhZV9IYXJhX1BpcGlfSMWNbmdvaV9IZXJlX01haHVfV2hpLW51X1doaS1yYV9IYWtpJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1JlZ2V4OiAvKD86WydhLXpcXHUwMTAxXFx1MDE0RFxcdTAxNkJdK1xcLT8pezEsM30vaSxcbiAgICBtb250aHNTdHJpY3RSZWdleDogLyg/OlsnYS16XFx1MDEwMVxcdTAxNERcXHUwMTZCXStcXC0/KXsxLDN9L2ksXG4gICAgbW9udGhzU2hvcnRSZWdleDogLyg/OlsnYS16XFx1MDEwMVxcdTAxNERcXHUwMTZCXStcXC0/KXsxLDN9L2ksXG4gICAgbW9udGhzU2hvcnRTdHJpY3RSZWdleDogLyg/OlsnYS16XFx1MDEwMVxcdTAxNERcXHUwMTZCXStcXC0/KXsxLDJ9L2ksXG4gICAgd2Vla2RheXM6ICdSxIF0YXB1X01hbmVfVMWrcmVpX1dlbmVyZWlfVMSBaXRlX1BhcmFpcmVfSMSBdGFyZWknLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydDogJ1RhX01hX1TFq19XZV9UxIFpX1BhX0jEgScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbjogJ1RhX01hX1TFq19XZV9UxIFpX1BhX0jEgScuc3BsaXQoJ18nKSxcbiAgICBsb25nRGF0ZUZvcm1hdDoge1xuICAgICAgICBMVDogJ0hIOm1tJyxcbiAgICAgICAgTFRTOiAnSEg6bW06c3MnLFxuICAgICAgICBMOiAnREQvTU0vWVlZWScsXG4gICAgICAgIExMOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICBMTEw6ICdEIE1NTU0gWVlZWSBbaV0gSEg6bW0nLFxuICAgICAgICBMTExMOiAnZGRkZCwgRCBNTU1NIFlZWVkgW2ldIEhIOm1tJ1xuICAgIH0sXG4gICAgY2FsZW5kYXI6IHtcbiAgICAgICAgc2FtZURheTogJ1tpIHRlaWUgbWFoYW5hLCBpXSBMVCcsXG4gICAgICAgIG5leHREYXk6ICdbYXBvcG8gaV0gTFQnLFxuICAgICAgICBuZXh0V2VlazogJ2RkZGQgW2ldIExUJyxcbiAgICAgICAgbGFzdERheTogJ1tpbmFuYWhpIGldIExUJyxcbiAgICAgICAgbGFzdFdlZWs6ICdkZGRkIFt3aGFrYW11dHVuZ2EgaV0gTFQnLFxuICAgICAgICBzYW1lRWxzZTogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWU6IHtcbiAgICAgICAgZnV0dXJlOiAnaSByb3RvIGkgJXMnLFxuICAgICAgICBwYXN0OiAnJXMgaSBtdWEnLFxuICAgICAgICBzOiAndGUgaMSTa29uYSBydWFydWEnLFxuICAgICAgICBzczogJyVkIGjEk2tvbmEnLFxuICAgICAgICBtOiAnaGUgbWVuZXRpJyxcbiAgICAgICAgbW06ICclZCBtZW5ldGknLFxuICAgICAgICBoOiAndGUgaGFvcmEnLFxuICAgICAgICBoaDogJyVkIGhhb3JhJyxcbiAgICAgICAgZDogJ2hlIHJhJyxcbiAgICAgICAgZGQ6ICclZCByYScsXG4gICAgICAgIE06ICdoZSBtYXJhbWEnLFxuICAgICAgICBNTTogJyVkIG1hcmFtYScsXG4gICAgICAgIHk6ICdoZSB0YXUnLFxuICAgICAgICB5eTogJyVkIHRhdSdcbiAgICB9LFxuICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfcK6LyxcbiAgICBvcmRpbmFsOiAnJWTCuicsXG4gICAgd2VlayA6IHtcbiAgICAgICAgZG93IDogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgIGRveSA6IDQgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDR0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICB9XG59KTtcblxuLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSA6IE1hY2Vkb25pYW4gW21rXVxuLy8hIGF1dGhvciA6IEJvcmlzbGF2IE1pY2tvdiA6IGh0dHBzOi8vZ2l0aHViLmNvbS9CMGswXG5cbmhvb2tzLmRlZmluZUxvY2FsZSgnbWsnLCB7XG4gICAgbW9udGhzIDogJ9GY0LDQvdGD0LDRgNC4X9GE0LXQstGA0YPQsNGA0Lhf0LzQsNGA0YJf0LDQv9GA0LjQu1/QvNCw0Zhf0ZjRg9C90Lhf0ZjRg9C70Lhf0LDQstCz0YPRgdGCX9GB0LXQv9GC0LXQvNCy0YDQuF/QvtC60YLQvtC80LLRgNC4X9C90L7QtdC80LLRgNC4X9C00LXQutC10LzQstGA0LgnLnNwbGl0KCdfJyksXG4gICAgbW9udGhzU2hvcnQgOiAn0ZjQsNC9X9GE0LXQsl/QvNCw0YBf0LDQv9GAX9C80LDRmF/RmNGD0L1f0ZjRg9C7X9Cw0LLQs1/RgdC10L9f0L7QutGCX9C90L7QtV/QtNC10LonLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXMgOiAn0L3QtdC00LXQu9CwX9C/0L7QvdC10LTQtdC70L3QuNC6X9Cy0YLQvtGA0L3QuNC6X9GB0YDQtdC00LBf0YfQtdGC0LLRgNGC0L7Qul/Qv9C10YLQvtC6X9GB0LDQsdC+0YLQsCcuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0IDogJ9C90LXQtF/Qv9C+0L1f0LLRgtC+X9GB0YDQtV/Rh9C10YJf0L/QtdGCX9GB0LDQsScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbiA6ICfQvWVf0L9vX9Cy0YJf0YHRgF/Rh9C1X9C/0LVf0YFhJy5zcGxpdCgnXycpLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdIOm1tJyxcbiAgICAgICAgTFRTIDogJ0g6bW06c3MnLFxuICAgICAgICBMIDogJ0QuTU0uWVlZWScsXG4gICAgICAgIExMIDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgTExMIDogJ0QgTU1NTSBZWVlZIEg6bW0nLFxuICAgICAgICBMTExMIDogJ2RkZGQsIEQgTU1NTSBZWVlZIEg6bW0nXG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheSA6ICdb0JTQtdC90LXRgSDQstC+XSBMVCcsXG4gICAgICAgIG5leHREYXkgOiAnW9Cj0YLRgNC1INCy0L5dIExUJyxcbiAgICAgICAgbmV4dFdlZWsgOiAnW9CS0L5dIGRkZGQgW9Cy0L5dIExUJyxcbiAgICAgICAgbGFzdERheSA6ICdb0JLRh9C10YDQsCDQstC+XSBMVCcsXG4gICAgICAgIGxhc3RXZWVrIDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgc3dpdGNoICh0aGlzLmRheSgpKSB7XG4gICAgICAgICAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgICAgIGNhc2UgMzpcbiAgICAgICAgICAgICAgICBjYXNlIDY6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnW9CY0LfQvNC40L3QsNGC0LDRgtCwXSBkZGRkIFvQstC+XSBMVCc7XG4gICAgICAgICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgICAgIGNhc2UgMjpcbiAgICAgICAgICAgICAgICBjYXNlIDQ6XG4gICAgICAgICAgICAgICAgY2FzZSA1OlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1vQmNC30LzQuNC90LDRgtC40L7Rgl0gZGRkZCBb0LLQvl0gTFQnO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBzYW1lRWxzZSA6ICdMJ1xuICAgIH0sXG4gICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICBmdXR1cmUgOiAn0L/QvtGB0LvQtSAlcycsXG4gICAgICAgIHBhc3QgOiAn0L/RgNC10LQgJXMnLFxuICAgICAgICBzIDogJ9C90LXQutC+0LvQutGDINGB0LXQutGD0L3QtNC4JyxcbiAgICAgICAgc3MgOiAnJWQg0YHQtdC60YPQvdC00LgnLFxuICAgICAgICBtIDogJ9C80LjQvdGD0YLQsCcsXG4gICAgICAgIG1tIDogJyVkINC80LjQvdGD0YLQuCcsXG4gICAgICAgIGggOiAn0YfQsNGBJyxcbiAgICAgICAgaGggOiAnJWQg0YfQsNGB0LAnLFxuICAgICAgICBkIDogJ9C00LXQvScsXG4gICAgICAgIGRkIDogJyVkINC00LXQvdCwJyxcbiAgICAgICAgTSA6ICfQvNC10YHQtdGGJyxcbiAgICAgICAgTU0gOiAnJWQg0LzQtdGB0LXRhtC4JyxcbiAgICAgICAgeSA6ICfQs9C+0LTQuNC90LAnLFxuICAgICAgICB5eSA6ICclZCDQs9C+0LTQuNC90LgnXG4gICAgfSxcbiAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn0tKNC10LJ80LXQvXzRgtC4fNCy0Lh80YDQuHzQvNC4KS8sXG4gICAgb3JkaW5hbCA6IGZ1bmN0aW9uIChudW1iZXIpIHtcbiAgICAgICAgdmFyIGxhc3REaWdpdCA9IG51bWJlciAlIDEwLFxuICAgICAgICAgICAgbGFzdDJEaWdpdHMgPSBudW1iZXIgJSAxMDA7XG4gICAgICAgIGlmIChudW1iZXIgPT09IDApIHtcbiAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAnLdC10LInO1xuICAgICAgICB9IGVsc2UgaWYgKGxhc3QyRGlnaXRzID09PSAwKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJy3QtdC9JztcbiAgICAgICAgfSBlbHNlIGlmIChsYXN0MkRpZ2l0cyA+IDEwICYmIGxhc3QyRGlnaXRzIDwgMjApIHtcbiAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAnLdGC0LgnO1xuICAgICAgICB9IGVsc2UgaWYgKGxhc3REaWdpdCA9PT0gMSkge1xuICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICct0LLQuCc7XG4gICAgICAgIH0gZWxzZSBpZiAobGFzdERpZ2l0ID09PSAyKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJy3RgNC4JztcbiAgICAgICAgfSBlbHNlIGlmIChsYXN0RGlnaXQgPT09IDcgfHwgbGFzdERpZ2l0ID09PSA4KSB7XG4gICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJy3QvNC4JztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAnLdGC0LgnO1xuICAgICAgICB9XG4gICAgfSxcbiAgICB3ZWVrIDoge1xuICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogNyAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gMXN0IGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH1cbn0pO1xuXG4vLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogTWFsYXlhbGFtIFttbF1cbi8vISBhdXRob3IgOiBGbG95ZCBQaW5rIDogaHR0cHM6Ly9naXRodWIuY29tL2Zsb3lkcGlua1xuXG5ob29rcy5kZWZpbmVMb2NhbGUoJ21sJywge1xuICAgIG1vbnRocyA6ICfgtJzgtKjgtYHgtLXgtLDgtL9f4LSr4LWG4LSs4LWN4LSw4LWB4LS14LSw4LS/X+C0ruC0vuC1vOC0muC1jeC0muC1jV/gtI/gtKrgtY3gtLDgtL/gtb1f4LSu4LWH4LSv4LWNX+C0nOC1guC1ul/gtJzgtYLgtLLgtYhf4LST4LSX4LS44LWN4LSx4LWN4LSx4LWNX+C0uOC1huC0quC1jeC0seC1jeC0seC0guC0rOC1vF/gtJLgtJXgtY3gtJ/gtYvgtKzgtbxf4LSo4LS14LSC4LSs4LW8X+C0oeC0v+C0uOC0guC0rOC1vCcuc3BsaXQoJ18nKSxcbiAgICBtb250aHNTaG9ydCA6ICfgtJzgtKjgtYEuX+C0q+C1huC0rOC1jeC0sOC1gS5f4LSu4LS+4LW8Ll/gtI/gtKrgtY3gtLDgtL8uX+C0ruC1h+C0r+C1jV/gtJzgtYLgtbpf4LSc4LWC4LSy4LWILl/gtJPgtJcuX+C0uOC1huC0quC1jeC0seC1jeC0sS5f4LSS4LSV4LWN4LSf4LWLLl/gtKjgtLXgtIIuX+C0oeC0v+C0uOC0gi4nLnNwbGl0KCdfJyksXG4gICAgbW9udGhzUGFyc2VFeGFjdCA6IHRydWUsXG4gICAgd2Vla2RheXMgOiAn4LSe4LS+4LSv4LSx4LS+4LS04LWN4LSaX+C0pOC0v+C0meC1jeC0leC0s+C0vuC0tOC1jeC0ml/gtJrgtYrgtLXgtY3gtLXgtL7gtLTgtY3gtJpf4LSs4LWB4LSn4LSo4LS+4LS04LWN4LSaX+C0teC1jeC0r+C0vuC0tOC0vuC0tOC1jeC0ml/gtLXgtYbgtLPgtY3gtLPgtL/gtK/gtL7gtLTgtY3gtJpf4LS24LSo4LS/4LSv4LS+4LS04LWN4LSaJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzU2hvcnQgOiAn4LSe4LS+4LSv4LW8X+C0pOC0v+C0meC1jeC0leC1vl/gtJrgtYrgtLXgtY3gtLVf4LSs4LWB4LSn4LW7X+C0teC1jeC0r+C0vuC0tOC0gl/gtLXgtYbgtLPgtY3gtLPgtL9f4LS24LSo4LS/Jy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzTWluIDogJ+C0nuC0vl/gtKTgtL9f4LSa4LWKX+C0rOC1gV/gtLXgtY3gtK/gtL5f4LS14LWGX+C0ticuc3BsaXQoJ18nKSxcbiAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgTFQgOiAnQSBoOm1tIC3gtKjgtYEnLFxuICAgICAgICBMVFMgOiAnQSBoOm1tOnNzIC3gtKjgtYEnLFxuICAgICAgICBMIDogJ0REL01NL1lZWVknLFxuICAgICAgICBMTCA6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgIExMTCA6ICdEIE1NTU0gWVlZWSwgQSBoOm1tIC3gtKjgtYEnLFxuICAgICAgICBMTExMIDogJ2RkZGQsIEQgTU1NTSBZWVlZLCBBIGg6bW0gLeC0qOC1gSdcbiAgICB9LFxuICAgIGNhbGVuZGFyIDoge1xuICAgICAgICBzYW1lRGF5IDogJ1vgtIfgtKjgtY3gtKjgtY1dIExUJyxcbiAgICAgICAgbmV4dERheSA6ICdb4LSo4LS+4LSz4LWGXSBMVCcsXG4gICAgICAgIG5leHRXZWVrIDogJ2RkZGQsIExUJyxcbiAgICAgICAgbGFzdERheSA6ICdb4LSH4LSo4LWN4LSo4LSy4LWGXSBMVCcsXG4gICAgICAgIGxhc3RXZWVrIDogJ1vgtJXgtLTgtL/gtJ7gtY3gtJ5dIGRkZGQsIExUJyxcbiAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJyVzIOC0leC0tOC0v+C0nuC1jeC0nuC1jScsXG4gICAgICAgIHBhc3QgOiAnJXMg4LSu4LWB4LW74LSq4LWNJyxcbiAgICAgICAgcyA6ICfgtIXgtb3gtKog4LSo4LS/4LSu4LS/4LS34LSZ4LWN4LSZ4LW+JyxcbiAgICAgICAgc3MgOiAnJWQg4LS44LWG4LSV4LWN4LSV4LW74LSh4LWNJyxcbiAgICAgICAgbSA6ICfgtJLgtLDgtYEg4LSu4LS/4LSo4LS/4LSx4LWN4LSx4LWNJyxcbiAgICAgICAgbW0gOiAnJWQg4LSu4LS/4LSo4LS/4LSx4LWN4LSx4LWNJyxcbiAgICAgICAgaCA6ICfgtJLgtLDgtYEg4LSu4LSj4LS/4LSV4LWN4LSV4LWC4LW8JyxcbiAgICAgICAgaGggOiAnJWQg4LSu4LSj4LS/4LSV4LWN4LSV4LWC4LW8JyxcbiAgICAgICAgZCA6ICfgtJLgtLDgtYEg4LSm4LS/4LS14LS44LSCJyxcbiAgICAgICAgZGQgOiAnJWQg4LSm4LS/4LS14LS44LSCJyxcbiAgICAgICAgTSA6ICfgtJLgtLDgtYEg4LSu4LS+4LS44LSCJyxcbiAgICAgICAgTU0gOiAnJWQg4LSu4LS+4LS44LSCJyxcbiAgICAgICAgeSA6ICfgtJLgtLDgtYEg4LS14LW84LS34LSCJyxcbiAgICAgICAgeXkgOiAnJWQg4LS14LW84LS34LSCJ1xuICAgIH0sXG4gICAgbWVyaWRpZW1QYXJzZTogL+C0sOC0vuC0pOC1jeC0sOC0v3zgtLDgtL7gtLXgtL/gtLLgtYZ84LSJ4LSa4LWN4LSaIOC0leC0tOC0v+C0nuC1jeC0nuC1jXzgtLXgtYjgtJXgtYHgtKjgtY3gtKjgtYfgtLDgtIJ84LSw4LS+4LSk4LWN4LSw4LS/L2ksXG4gICAgbWVyaWRpZW1Ib3VyIDogZnVuY3Rpb24gKGhvdXIsIG1lcmlkaWVtKSB7XG4gICAgICAgIGlmIChob3VyID09PSAxMikge1xuICAgICAgICAgICAgaG91ciA9IDA7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKChtZXJpZGllbSA9PT0gJ+C0sOC0vuC0pOC1jeC0sOC0vycgJiYgaG91ciA+PSA0KSB8fFxuICAgICAgICAgICAgICAgIG1lcmlkaWVtID09PSAn4LSJ4LSa4LWN4LSaIOC0leC0tOC0v+C0nuC1jeC0nuC1jScgfHxcbiAgICAgICAgICAgICAgICBtZXJpZGllbSA9PT0gJ+C0teC1iOC0leC1geC0qOC1jeC0qOC1h+C0sOC0gicpIHtcbiAgICAgICAgICAgIHJldHVybiBob3VyICsgMTI7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gaG91cjtcbiAgICAgICAgfVxuICAgIH0sXG4gICAgbWVyaWRpZW0gOiBmdW5jdGlvbiAoaG91ciwgbWludXRlLCBpc0xvd2VyKSB7XG4gICAgICAgIGlmIChob3VyIDwgNCkge1xuICAgICAgICAgICAgcmV0dXJuICfgtLDgtL7gtKTgtY3gtLDgtL8nO1xuICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAxMikge1xuICAgICAgICAgICAgcmV0dXJuICfgtLDgtL7gtLXgtL/gtLLgtYYnO1xuICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAxNykge1xuICAgICAgICAgICAgcmV0dXJuICfgtIngtJrgtY3gtJog4LSV4LS04LS/4LSe4LWN4LSe4LWNJztcbiAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgMjApIHtcbiAgICAgICAgICAgIHJldHVybiAn4LS14LWI4LSV4LWB4LSo4LWN4LSo4LWH4LSw4LSCJztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiAn4LSw4LS+4LSk4LWN4LSw4LS/JztcbiAgICAgICAgfVxuICAgIH1cbn0pO1xuXG4vLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogTWFyYXRoaSBbbXJdXG4vLyEgYXV0aG9yIDogSGFyc2hhZCBLYWxlIDogaHR0cHM6Ly9naXRodWIuY29tL2thbGVodlxuLy8hIGF1dGhvciA6IFZpdmVrIEF0aGFseWUgOiBodHRwczovL2dpdGh1Yi5jb20vdm5hdGhhbHllXG5cbnZhciBzeW1ib2xNYXAkOSA9IHtcbiAgICAnMSc6ICfgpacnLFxuICAgICcyJzogJ+ClqCcsXG4gICAgJzMnOiAn4KWpJyxcbiAgICAnNCc6ICfgpaonLFxuICAgICc1JzogJ+ClqycsXG4gICAgJzYnOiAn4KWsJyxcbiAgICAnNyc6ICfgpa0nLFxuICAgICc4JzogJ+ClricsXG4gICAgJzknOiAn4KWvJyxcbiAgICAnMCc6ICfgpaYnXG59O1xudmFyIG51bWJlck1hcCQ4ID0ge1xuICAgICfgpacnOiAnMScsXG4gICAgJ+ClqCc6ICcyJyxcbiAgICAn4KWpJzogJzMnLFxuICAgICfgpaonOiAnNCcsXG4gICAgJ+Clqyc6ICc1JyxcbiAgICAn4KWsJzogJzYnLFxuICAgICfgpa0nOiAnNycsXG4gICAgJ+Clric6ICc4JyxcbiAgICAn4KWvJzogJzknLFxuICAgICfgpaYnOiAnMCdcbn07XG5cbmZ1bmN0aW9uIHJlbGF0aXZlVGltZU1yKG51bWJlciwgd2l0aG91dFN1ZmZpeCwgc3RyaW5nLCBpc0Z1dHVyZSlcbntcbiAgICB2YXIgb3V0cHV0ID0gJyc7XG4gICAgaWYgKHdpdGhvdXRTdWZmaXgpIHtcbiAgICAgICAgc3dpdGNoIChzdHJpbmcpIHtcbiAgICAgICAgICAgIGNhc2UgJ3MnOiBvdXRwdXQgPSAn4KSV4KS+4KS54KWAIOCkuOClh+CkleCkguCkpic7IGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnc3MnOiBvdXRwdXQgPSAnJWQg4KS44KWH4KSV4KSC4KSmJzsgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICdtJzogb3V0cHV0ID0gJ+Ckj+CklSDgpK7gpL/gpKjgpL/gpJ8nOyBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ21tJzogb3V0cHV0ID0gJyVkIOCkruCkv+CkqOCkv+Ckn+Clhyc7IGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnaCc6IG91dHB1dCA9ICfgpI/gpJUg4KSk4KS+4KS4JzsgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICdoaCc6IG91dHB1dCA9ICclZCDgpKTgpL7gpLgnOyBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ2QnOiBvdXRwdXQgPSAn4KSP4KSVIOCkpuCkv+CkteCkuCc7IGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnZGQnOiBvdXRwdXQgPSAnJWQg4KSm4KS/4KS14KS4JzsgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICdNJzogb3V0cHV0ID0gJ+Ckj+CklSDgpK7gpLngpL/gpKjgpL4nOyBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ01NJzogb3V0cHV0ID0gJyVkIOCkruCkueCkv+CkqOClhyc7IGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAneSc6IG91dHB1dCA9ICfgpI/gpJUg4KS14KSw4KWN4KS3JzsgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICd5eSc6IG91dHB1dCA9ICclZCDgpLXgpLDgpY3gpLfgpYcnOyBicmVhaztcbiAgICAgICAgfVxuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgc3dpdGNoIChzdHJpbmcpIHtcbiAgICAgICAgICAgIGNhc2UgJ3MnOiBvdXRwdXQgPSAn4KSV4KS+4KS54KWAIOCkuOClh+CkleCkguCkpuCkvuCkgic7IGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnc3MnOiBvdXRwdXQgPSAnJWQg4KS44KWH4KSV4KSC4KSm4KS+4KSCJzsgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICdtJzogb3V0cHV0ID0gJ+Ckj+CkleCkviDgpK7gpL/gpKjgpL/gpJ/gpL4nOyBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ21tJzogb3V0cHV0ID0gJyVkIOCkruCkv+CkqOCkv+Ckn+CkvuCkgic7IGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnaCc6IG91dHB1dCA9ICfgpI/gpJXgpL4g4KSk4KS+4KS44KS+JzsgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICdoaCc6IG91dHB1dCA9ICclZCDgpKTgpL7gpLjgpL7gpIInOyBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ2QnOiBvdXRwdXQgPSAn4KSP4KSV4KS+IOCkpuCkv+CkteCkuOCkvic7IGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnZGQnOiBvdXRwdXQgPSAnJWQg4KSm4KS/4KS14KS44KS+4KSCJzsgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICdNJzogb3V0cHV0ID0gJ+Ckj+CkleCkviDgpK7gpLngpL/gpKjgpY3gpK/gpL4nOyBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ01NJzogb3V0cHV0ID0gJyVkIOCkruCkueCkv+CkqOCljeCkr+CkvuCkgic7IGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAneSc6IG91dHB1dCA9ICfgpI/gpJXgpL4g4KS14KSw4KWN4KS34KS+JzsgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICd5eSc6IG91dHB1dCA9ICclZCDgpLXgpLDgpY3gpLfgpL7gpIInOyBicmVhaztcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gb3V0cHV0LnJlcGxhY2UoLyVkL2ksIG51bWJlcik7XG59XG5cbmhvb2tzLmRlZmluZUxvY2FsZSgnbXInLCB7XG4gICAgbW9udGhzIDogJ+CknOCkvuCkqOClh+CkteCkvuCksOClgF/gpKvgpYfgpKzgpY3gpLDgpYHgpLXgpL7gpLDgpYBf4KSu4KS+4KSw4KWN4KSaX+Ckj+CkquCljeCksOCkv+Cksl/gpK7gpYdf4KSc4KWC4KSoX+CknOClgeCksuCliF/gpJHgpJfgpLjgpY3gpJ9f4KS44KSq4KWN4KSf4KWH4KSC4KSs4KSwX+CkkeCkleCljeCkn+Cli+CkrOCksF/gpKjgpYvgpLXgpY3gpLngpYfgpILgpKzgpLBf4KSh4KS/4KS44KWH4KSC4KSs4KSwJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0OiAn4KSc4KS+4KSo4KWHLl/gpKvgpYfgpKzgpY3gpLDgpYEuX+CkruCkvuCksOCljeCkmi5f4KSP4KSq4KWN4KSw4KS/Ll/gpK7gpYcuX+CknOClguCkqC5f4KSc4KWB4KSy4KWILl/gpJHgpJcuX+CkuOCkquCljeCkn+Clh+Ckgi5f4KSR4KSV4KWN4KSf4KWLLl/gpKjgpYvgpLXgpY3gpLngpYfgpIIuX+CkoeCkv+CkuOClh+Ckgi4nLnNwbGl0KCdfJyksXG4gICAgbW9udGhzUGFyc2VFeGFjdCA6IHRydWUsXG4gICAgd2Vla2RheXMgOiAn4KSw4KS14KS/4KS14KS+4KSwX+CkuOCli+CkruCkteCkvuCksF/gpK7gpILgpJfgpLPgpLXgpL7gpLBf4KSs4KWB4KSn4KS14KS+4KSwX+Ckl+ClgeCksOClguCkteCkvuCksF/gpLbgpYHgpJXgpY3gpLDgpLXgpL7gpLBf4KS24KSo4KS/4KS14KS+4KSwJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzU2hvcnQgOiAn4KSw4KS14KS/X+CkuOCli+Ckrl/gpK7gpILgpJfgpLNf4KSs4KWB4KSnX+Ckl+ClgeCksOClgl/gpLbgpYHgpJXgpY3gpLBf4KS24KSo4KS/Jy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzTWluIDogJ+CksF/gpLjgpYtf4KSu4KSCX+CkrOClgV/gpJfgpYFf4KS24KWBX+Ckticuc3BsaXQoJ18nKSxcbiAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgTFQgOiAnQSBoOm1tIOCkteCkvuCknOCkpOCkvicsXG4gICAgICAgIExUUyA6ICdBIGg6bW06c3Mg4KS14KS+4KSc4KSk4KS+JyxcbiAgICAgICAgTCA6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgTEwgOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICBMTEwgOiAnRCBNTU1NIFlZWVksIEEgaDptbSDgpLXgpL7gpJzgpKTgpL4nLFxuICAgICAgICBMTExMIDogJ2RkZGQsIEQgTU1NTSBZWVlZLCBBIGg6bW0g4KS14KS+4KSc4KSk4KS+J1xuICAgIH0sXG4gICAgY2FsZW5kYXIgOiB7XG4gICAgICAgIHNhbWVEYXkgOiAnW+CkhuCknF0gTFQnLFxuICAgICAgICBuZXh0RGF5IDogJ1vgpIngpKbgpY3gpK/gpL5dIExUJyxcbiAgICAgICAgbmV4dFdlZWsgOiAnZGRkZCwgTFQnLFxuICAgICAgICBsYXN0RGF5IDogJ1vgpJXgpL7gpLJdIExUJyxcbiAgICAgICAgbGFzdFdlZWs6ICdb4KSu4KS+4KSX4KWA4KSyXSBkZGRkLCBMVCcsXG4gICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZTogJyVz4KSu4KSn4KWN4KSv4KWHJyxcbiAgICAgICAgcGFzdDogJyVz4KSq4KWC4KSw4KWN4KS14KWAJyxcbiAgICAgICAgczogcmVsYXRpdmVUaW1lTXIsXG4gICAgICAgIHNzOiByZWxhdGl2ZVRpbWVNcixcbiAgICAgICAgbTogcmVsYXRpdmVUaW1lTXIsXG4gICAgICAgIG1tOiByZWxhdGl2ZVRpbWVNcixcbiAgICAgICAgaDogcmVsYXRpdmVUaW1lTXIsXG4gICAgICAgIGhoOiByZWxhdGl2ZVRpbWVNcixcbiAgICAgICAgZDogcmVsYXRpdmVUaW1lTXIsXG4gICAgICAgIGRkOiByZWxhdGl2ZVRpbWVNcixcbiAgICAgICAgTTogcmVsYXRpdmVUaW1lTXIsXG4gICAgICAgIE1NOiByZWxhdGl2ZVRpbWVNcixcbiAgICAgICAgeTogcmVsYXRpdmVUaW1lTXIsXG4gICAgICAgIHl5OiByZWxhdGl2ZVRpbWVNclxuICAgIH0sXG4gICAgcHJlcGFyc2U6IGZ1bmN0aW9uIChzdHJpbmcpIHtcbiAgICAgICAgcmV0dXJuIHN0cmluZy5yZXBsYWNlKC9b4KWn4KWo4KWp4KWq4KWr4KWs4KWt4KWu4KWv4KWmXS9nLCBmdW5jdGlvbiAobWF0Y2gpIHtcbiAgICAgICAgICAgIHJldHVybiBudW1iZXJNYXAkOFttYXRjaF07XG4gICAgICAgIH0pO1xuICAgIH0sXG4gICAgcG9zdGZvcm1hdDogZnVuY3Rpb24gKHN0cmluZykge1xuICAgICAgICByZXR1cm4gc3RyaW5nLnJlcGxhY2UoL1xcZC9nLCBmdW5jdGlvbiAobWF0Y2gpIHtcbiAgICAgICAgICAgIHJldHVybiBzeW1ib2xNYXAkOVttYXRjaF07XG4gICAgICAgIH0pO1xuICAgIH0sXG4gICAgbWVyaWRpZW1QYXJzZTogL+CksOCkvuCkpOCljeCksOClgHzgpLjgpJXgpL7gpLPgpYB84KSm4KWB4KSq4KS+4KSw4KWAfOCkuOCkvuCkr+CkguCkleCkvuCks+ClgC8sXG4gICAgbWVyaWRpZW1Ib3VyIDogZnVuY3Rpb24gKGhvdXIsIG1lcmlkaWVtKSB7XG4gICAgICAgIGlmIChob3VyID09PSAxMikge1xuICAgICAgICAgICAgaG91ciA9IDA7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG1lcmlkaWVtID09PSAn4KSw4KS+4KSk4KWN4KSw4KWAJykge1xuICAgICAgICAgICAgcmV0dXJuIGhvdXIgPCA0ID8gaG91ciA6IGhvdXIgKyAxMjtcbiAgICAgICAgfSBlbHNlIGlmIChtZXJpZGllbSA9PT0gJ+CkuOCkleCkvuCks+ClgCcpIHtcbiAgICAgICAgICAgIHJldHVybiBob3VyO1xuICAgICAgICB9IGVsc2UgaWYgKG1lcmlkaWVtID09PSAn4KSm4KWB4KSq4KS+4KSw4KWAJykge1xuICAgICAgICAgICAgcmV0dXJuIGhvdXIgPj0gMTAgPyBob3VyIDogaG91ciArIDEyO1xuICAgICAgICB9IGVsc2UgaWYgKG1lcmlkaWVtID09PSAn4KS44KS+4KSv4KSC4KSV4KS+4KSz4KWAJykge1xuICAgICAgICAgICAgcmV0dXJuIGhvdXIgKyAxMjtcbiAgICAgICAgfVxuICAgIH0sXG4gICAgbWVyaWRpZW06IGZ1bmN0aW9uIChob3VyLCBtaW51dGUsIGlzTG93ZXIpIHtcbiAgICAgICAgaWYgKGhvdXIgPCA0KSB7XG4gICAgICAgICAgICByZXR1cm4gJ+CksOCkvuCkpOCljeCksOClgCc7XG4gICAgICAgIH0gZWxzZSBpZiAoaG91ciA8IDEwKSB7XG4gICAgICAgICAgICByZXR1cm4gJ+CkuOCkleCkvuCks+ClgCc7XG4gICAgICAgIH0gZWxzZSBpZiAoaG91ciA8IDE3KSB7XG4gICAgICAgICAgICByZXR1cm4gJ+CkpuClgeCkquCkvuCksOClgCc7XG4gICAgICAgIH0gZWxzZSBpZiAoaG91ciA8IDIwKSB7XG4gICAgICAgICAgICByZXR1cm4gJ+CkuOCkvuCkr+CkguCkleCkvuCks+ClgCc7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gJ+CksOCkvuCkpOCljeCksOClgCc7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIHdlZWsgOiB7XG4gICAgICAgIGRvdyA6IDAsIC8vIFN1bmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICBkb3kgOiA2ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiAxc3QgaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgfVxufSk7XG5cbi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBNYWxheSBbbXMtbXldXG4vLyEgbm90ZSA6IERFUFJFQ0FURUQsIHRoZSBjb3JyZWN0IG9uZSBpcyBbbXNdXG4vLyEgYXV0aG9yIDogV2VsZGFuIEphbWlsaSA6IGh0dHBzOi8vZ2l0aHViLmNvbS93ZWxkYW5cblxuaG9va3MuZGVmaW5lTG9jYWxlKCdtcy1teScsIHtcbiAgICBtb250aHMgOiAnSmFudWFyaV9GZWJydWFyaV9NYWNfQXByaWxfTWVpX0p1bl9KdWxhaV9PZ29zX1NlcHRlbWJlcl9Pa3RvYmVyX05vdmVtYmVyX0Rpc2VtYmVyJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0IDogJ0phbl9GZWJfTWFjX0Fwcl9NZWlfSnVuX0p1bF9PZ3NfU2VwX09rdF9Ob3ZfRGlzJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzIDogJ0FoYWRfSXNuaW5fU2VsYXNhX1JhYnVfS2hhbWlzX0p1bWFhdF9TYWJ0dScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0IDogJ0FoZF9Jc25fU2VsX1JhYl9LaGFfSnVtX1NhYicuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbiA6ICdBaF9Jc19TbF9SYl9LbV9KbV9TYicuc3BsaXQoJ18nKSxcbiAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgTFQgOiAnSEgubW0nLFxuICAgICAgICBMVFMgOiAnSEgubW0uc3MnLFxuICAgICAgICBMIDogJ0REL01NL1lZWVknLFxuICAgICAgICBMTCA6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgIExMTCA6ICdEIE1NTU0gWVlZWSBbcHVrdWxdIEhILm1tJyxcbiAgICAgICAgTExMTCA6ICdkZGRkLCBEIE1NTU0gWVlZWSBbcHVrdWxdIEhILm1tJ1xuICAgIH0sXG4gICAgbWVyaWRpZW1QYXJzZTogL3BhZ2l8dGVuZ2FoYXJpfHBldGFuZ3xtYWxhbS8sXG4gICAgbWVyaWRpZW1Ib3VyOiBmdW5jdGlvbiAoaG91ciwgbWVyaWRpZW0pIHtcbiAgICAgICAgaWYgKGhvdXIgPT09IDEyKSB7XG4gICAgICAgICAgICBob3VyID0gMDtcbiAgICAgICAgfVxuICAgICAgICBpZiAobWVyaWRpZW0gPT09ICdwYWdpJykge1xuICAgICAgICAgICAgcmV0dXJuIGhvdXI7XG4gICAgICAgIH0gZWxzZSBpZiAobWVyaWRpZW0gPT09ICd0ZW5nYWhhcmknKSB7XG4gICAgICAgICAgICByZXR1cm4gaG91ciA+PSAxMSA/IGhvdXIgOiBob3VyICsgMTI7XG4gICAgICAgIH0gZWxzZSBpZiAobWVyaWRpZW0gPT09ICdwZXRhbmcnIHx8IG1lcmlkaWVtID09PSAnbWFsYW0nKSB7XG4gICAgICAgICAgICByZXR1cm4gaG91ciArIDEyO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBtZXJpZGllbSA6IGZ1bmN0aW9uIChob3VycywgbWludXRlcywgaXNMb3dlcikge1xuICAgICAgICBpZiAoaG91cnMgPCAxMSkge1xuICAgICAgICAgICAgcmV0dXJuICdwYWdpJztcbiAgICAgICAgfSBlbHNlIGlmIChob3VycyA8IDE1KSB7XG4gICAgICAgICAgICByZXR1cm4gJ3RlbmdhaGFyaSc7XG4gICAgICAgIH0gZWxzZSBpZiAoaG91cnMgPCAxOSkge1xuICAgICAgICAgICAgcmV0dXJuICdwZXRhbmcnO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuICdtYWxhbSc7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIGNhbGVuZGFyIDoge1xuICAgICAgICBzYW1lRGF5IDogJ1tIYXJpIGluaSBwdWt1bF0gTFQnLFxuICAgICAgICBuZXh0RGF5IDogJ1tFc29rIHB1a3VsXSBMVCcsXG4gICAgICAgIG5leHRXZWVrIDogJ2RkZGQgW3B1a3VsXSBMVCcsXG4gICAgICAgIGxhc3REYXkgOiAnW0tlbG1hcmluIHB1a3VsXSBMVCcsXG4gICAgICAgIGxhc3RXZWVrIDogJ2RkZGQgW2xlcGFzIHB1a3VsXSBMVCcsXG4gICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6ICdkYWxhbSAlcycsXG4gICAgICAgIHBhc3QgOiAnJXMgeWFuZyBsZXBhcycsXG4gICAgICAgIHMgOiAnYmViZXJhcGEgc2FhdCcsXG4gICAgICAgIHNzIDogJyVkIHNhYXQnLFxuICAgICAgICBtIDogJ3NlbWluaXQnLFxuICAgICAgICBtbSA6ICclZCBtaW5pdCcsXG4gICAgICAgIGggOiAnc2VqYW0nLFxuICAgICAgICBoaCA6ICclZCBqYW0nLFxuICAgICAgICBkIDogJ3NlaGFyaScsXG4gICAgICAgIGRkIDogJyVkIGhhcmknLFxuICAgICAgICBNIDogJ3NlYnVsYW4nLFxuICAgICAgICBNTSA6ICclZCBidWxhbicsXG4gICAgICAgIHkgOiAnc2V0YWh1bicsXG4gICAgICAgIHl5IDogJyVkIHRhaHVuJ1xuICAgIH0sXG4gICAgd2VlayA6IHtcbiAgICAgICAgZG93IDogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgIGRveSA6IDcgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDFzdCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICB9XG59KTtcblxuLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSA6IE1hbGF5IFttc11cbi8vISBhdXRob3IgOiBXZWxkYW4gSmFtaWxpIDogaHR0cHM6Ly9naXRodWIuY29tL3dlbGRhblxuXG5ob29rcy5kZWZpbmVMb2NhbGUoJ21zJywge1xuICAgIG1vbnRocyA6ICdKYW51YXJpX0ZlYnJ1YXJpX01hY19BcHJpbF9NZWlfSnVuX0p1bGFpX09nb3NfU2VwdGVtYmVyX09rdG9iZXJfTm92ZW1iZXJfRGlzZW1iZXInLnNwbGl0KCdfJyksXG4gICAgbW9udGhzU2hvcnQgOiAnSmFuX0ZlYl9NYWNfQXByX01laV9KdW5fSnVsX09nc19TZXBfT2t0X05vdl9EaXMnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXMgOiAnQWhhZF9Jc25pbl9TZWxhc2FfUmFidV9LaGFtaXNfSnVtYWF0X1NhYnR1Jy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzU2hvcnQgOiAnQWhkX0lzbl9TZWxfUmFiX0toYV9KdW1fU2FiJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzTWluIDogJ0FoX0lzX1NsX1JiX0ttX0ptX1NiJy5zcGxpdCgnXycpLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdISC5tbScsXG4gICAgICAgIExUUyA6ICdISC5tbS5zcycsXG4gICAgICAgIEwgOiAnREQvTU0vWVlZWScsXG4gICAgICAgIExMIDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgTExMIDogJ0QgTU1NTSBZWVlZIFtwdWt1bF0gSEgubW0nLFxuICAgICAgICBMTExMIDogJ2RkZGQsIEQgTU1NTSBZWVlZIFtwdWt1bF0gSEgubW0nXG4gICAgfSxcbiAgICBtZXJpZGllbVBhcnNlOiAvcGFnaXx0ZW5nYWhhcml8cGV0YW5nfG1hbGFtLyxcbiAgICBtZXJpZGllbUhvdXI6IGZ1bmN0aW9uIChob3VyLCBtZXJpZGllbSkge1xuICAgICAgICBpZiAoaG91ciA9PT0gMTIpIHtcbiAgICAgICAgICAgIGhvdXIgPSAwO1xuICAgICAgICB9XG4gICAgICAgIGlmIChtZXJpZGllbSA9PT0gJ3BhZ2knKSB7XG4gICAgICAgICAgICByZXR1cm4gaG91cjtcbiAgICAgICAgfSBlbHNlIGlmIChtZXJpZGllbSA9PT0gJ3RlbmdhaGFyaScpIHtcbiAgICAgICAgICAgIHJldHVybiBob3VyID49IDExID8gaG91ciA6IGhvdXIgKyAxMjtcbiAgICAgICAgfSBlbHNlIGlmIChtZXJpZGllbSA9PT0gJ3BldGFuZycgfHwgbWVyaWRpZW0gPT09ICdtYWxhbScpIHtcbiAgICAgICAgICAgIHJldHVybiBob3VyICsgMTI7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIG1lcmlkaWVtIDogZnVuY3Rpb24gKGhvdXJzLCBtaW51dGVzLCBpc0xvd2VyKSB7XG4gICAgICAgIGlmIChob3VycyA8IDExKSB7XG4gICAgICAgICAgICByZXR1cm4gJ3BhZ2knO1xuICAgICAgICB9IGVsc2UgaWYgKGhvdXJzIDwgMTUpIHtcbiAgICAgICAgICAgIHJldHVybiAndGVuZ2FoYXJpJztcbiAgICAgICAgfSBlbHNlIGlmIChob3VycyA8IDE5KSB7XG4gICAgICAgICAgICByZXR1cm4gJ3BldGFuZyc7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gJ21hbGFtJztcbiAgICAgICAgfVxuICAgIH0sXG4gICAgY2FsZW5kYXIgOiB7XG4gICAgICAgIHNhbWVEYXkgOiAnW0hhcmkgaW5pIHB1a3VsXSBMVCcsXG4gICAgICAgIG5leHREYXkgOiAnW0Vzb2sgcHVrdWxdIExUJyxcbiAgICAgICAgbmV4dFdlZWsgOiAnZGRkZCBbcHVrdWxdIExUJyxcbiAgICAgICAgbGFzdERheSA6ICdbS2VsbWFyaW4gcHVrdWxdIExUJyxcbiAgICAgICAgbGFzdFdlZWsgOiAnZGRkZCBbbGVwYXMgcHVrdWxdIExUJyxcbiAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJ2RhbGFtICVzJyxcbiAgICAgICAgcGFzdCA6ICclcyB5YW5nIGxlcGFzJyxcbiAgICAgICAgcyA6ICdiZWJlcmFwYSBzYWF0JyxcbiAgICAgICAgc3MgOiAnJWQgc2FhdCcsXG4gICAgICAgIG0gOiAnc2VtaW5pdCcsXG4gICAgICAgIG1tIDogJyVkIG1pbml0JyxcbiAgICAgICAgaCA6ICdzZWphbScsXG4gICAgICAgIGhoIDogJyVkIGphbScsXG4gICAgICAgIGQgOiAnc2VoYXJpJyxcbiAgICAgICAgZGQgOiAnJWQgaGFyaScsXG4gICAgICAgIE0gOiAnc2VidWxhbicsXG4gICAgICAgIE1NIDogJyVkIGJ1bGFuJyxcbiAgICAgICAgeSA6ICdzZXRhaHVuJyxcbiAgICAgICAgeXkgOiAnJWQgdGFodW4nXG4gICAgfSxcbiAgICB3ZWVrIDoge1xuICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogNyAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gMXN0IGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH1cbn0pO1xuXG4vLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogTWFsdGVzZSAoTWFsdGEpIFttdF1cbi8vISBhdXRob3IgOiBBbGVzc2FuZHJvIE1hcnVjY2lhIDogaHR0cHM6Ly9naXRodWIuY29tL2FsZXNtYVxuXG5ob29rcy5kZWZpbmVMb2NhbGUoJ210Jywge1xuICAgIG1vbnRocyA6ICdKYW5uYXJfRnJhcl9NYXJ6dV9BcHJpbF9NZWpqdV/EoHVuanVfTHVsanVfQXd3aXNzdV9TZXR0ZW1icnVfT3R0dWJydV9Ob3ZlbWJydV9EacSLZW1icnUnLnNwbGl0KCdfJyksXG4gICAgbW9udGhzU2hvcnQgOiAnSmFuX0ZyYV9NYXJfQXByX01lal/EoHVuX0x1bF9Bd3dfU2V0X090dF9Ob3ZfRGnEiycuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5cyA6ICdJbC3EpmFkZF9JdC1UbmVqbl9JdC1UbGlldGFfTC1FcmJnxKdhX0lsLcSmYW1pc19JbC3EoGltZ8SnYV9Jcy1TaWJ0Jy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzU2hvcnQgOiAnxKZhZF9UbmVfVGxpX0VyYl/EpmFtX8SgaW1fU2liJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzTWluIDogJ8SmYV9Ubl9UbF9Fcl/EpmFfxKBpX1NpJy5zcGxpdCgnXycpLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdISDptbScsXG4gICAgICAgIExUUyA6ICdISDptbTpzcycsXG4gICAgICAgIEwgOiAnREQvTU0vWVlZWScsXG4gICAgICAgIExMIDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgTExMIDogJ0QgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgTExMTCA6ICdkZGRkLCBEIE1NTU0gWVlZWSBISDptbSdcbiAgICB9LFxuICAgIGNhbGVuZGFyIDoge1xuICAgICAgICBzYW1lRGF5IDogJ1tJbGx1bSBmaWwtXUxUJyxcbiAgICAgICAgbmV4dERheSA6ICdbR8SnYWRhIGZpbC1dTFQnLFxuICAgICAgICBuZXh0V2VlayA6ICdkZGRkIFtmaWwtXUxUJyxcbiAgICAgICAgbGFzdERheSA6ICdbSWwtYmllcmHEpyBmaWwtXUxUJyxcbiAgICAgICAgbGFzdFdlZWsgOiAnZGRkZCBbbGkgZ8SnYWRkYV0gW2ZpbC1dTFQnLFxuICAgICAgICBzYW1lRWxzZSA6ICdMJ1xuICAgIH0sXG4gICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICBmdXR1cmUgOiAnZuKAmSAlcycsXG4gICAgICAgIHBhc3QgOiAnJXMgaWx1JyxcbiAgICAgICAgcyA6ICdmdGl0IHNla29uZGknLFxuICAgICAgICBzcyA6ICclZCBzZWtvbmRpJyxcbiAgICAgICAgbSA6ICdtaW51dGEnLFxuICAgICAgICBtbSA6ICclZCBtaW51dGknLFxuICAgICAgICBoIDogJ3NpZWfEp2EnLFxuICAgICAgICBoaCA6ICclZCBzaWVnxKdhdCcsXG4gICAgICAgIGQgOiAnxKF1cm5hdGEnLFxuICAgICAgICBkZCA6ICclZCDEoXJhbmV0JyxcbiAgICAgICAgTSA6ICd4YWhhcicsXG4gICAgICAgIE1NIDogJyVkIHhodXInLFxuICAgICAgICB5IDogJ3NlbmEnLFxuICAgICAgICB5eSA6ICclZCBzbmknXG4gICAgfSxcbiAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlIDogL1xcZHsxLDJ9wrovLFxuICAgIG9yZGluYWw6ICclZMK6JyxcbiAgICB3ZWVrIDoge1xuICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogNCAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH1cbn0pO1xuXG4vLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogQnVybWVzZSBbbXldXG4vLyEgYXV0aG9yIDogU3F1YXIgdGVhbSwgbXlzcXVhci5jb21cbi8vISBhdXRob3IgOiBEYXZpZCBSb3NzZWxsYXQgOiBodHRwczovL2dpdGh1Yi5jb20vZ2hvbGFkclxuLy8hIGF1dGhvciA6IFRpbiBBdW5nIExpbiA6IGh0dHBzOi8vZ2l0aHViLmNvbS90aGFueWF3emlubWluXG5cbnZhciBzeW1ib2xNYXAkMTAgPSB7XG4gICAgJzEnOiAn4YGBJyxcbiAgICAnMic6ICfhgYInLFxuICAgICczJzogJ+GBgycsXG4gICAgJzQnOiAn4YGEJyxcbiAgICAnNSc6ICfhgYUnLFxuICAgICc2JzogJ+GBhicsXG4gICAgJzcnOiAn4YGHJyxcbiAgICAnOCc6ICfhgYgnLFxuICAgICc5JzogJ+GBiScsXG4gICAgJzAnOiAn4YGAJ1xufTtcbnZhciBudW1iZXJNYXAkOSA9IHtcbiAgICAn4YGBJzogJzEnLFxuICAgICfhgYInOiAnMicsXG4gICAgJ+GBgyc6ICczJyxcbiAgICAn4YGEJzogJzQnLFxuICAgICfhgYUnOiAnNScsXG4gICAgJ+GBhic6ICc2JyxcbiAgICAn4YGHJzogJzcnLFxuICAgICfhgYgnOiAnOCcsXG4gICAgJ+GBiSc6ICc5JyxcbiAgICAn4YGAJzogJzAnXG59O1xuXG5ob29rcy5kZWZpbmVMb2NhbGUoJ215Jywge1xuICAgIG1vbnRoczogJ+GAh+GAlOGAuuGAlOGAneGAq+GAm+GArl/hgJbhgLHhgJbhgLHhgKzhgLrhgJ3hgKvhgJvhgK5f4YCZ4YCQ4YC6X+GAp+GAleGAvOGArl/hgJnhgLFf4YCH4YC94YCU4YC6X+GAh+GAsOGAnOGAreGAr+GAhOGAul/hgJ7hgLzhgILhgK/hgJDhgLpf4YCF4YCA4YC64YCQ4YCE4YC64YCY4YCsX+GAoeGAseGArOGAgOGAuuGAkOGAreGAr+GAmOGArF/hgJThgK3hgK/hgJ3hgIThgLrhgJjhgKxf4YCS4YCu4YCH4YCE4YC64YCY4YCsJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0OiAn4YCH4YCU4YC6X+GAluGAsV/hgJnhgJDhgLpf4YCV4YC84YCuX+GAmeGAsV/hgIfhgL3hgJThgLpf4YCc4YCt4YCv4YCE4YC6X+GAnuGAvF/hgIXhgIDhgLpf4YCh4YCx4YCs4YCA4YC6X+GAlOGAreGAr1/hgJLhgK4nLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXM6ICfhgJDhgJThgIThgLrhgLnhgILhgJThgL3hgLFf4YCQ4YCU4YCE4YC64YC54YCc4YCsX+GAoeGAhOGAuuGAueGAguGAq1/hgJfhgK/hgJLhgLnhgJPhgJ/hgLDhgLhf4YCA4YC84YCs4YCe4YCV4YCQ4YCx4YC4X+GAnuGAseGArOGAgOGAvOGArF/hgIXhgJThgLEnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydDogJ+GAlOGAveGAsV/hgJzhgKxf4YCC4YCrX+GAn+GAsOGAuF/hgIDhgLzhgKxf4YCe4YCx4YCsX+GAlOGAsScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbjogJ+GAlOGAveGAsV/hgJzhgKxf4YCC4YCrX+GAn+GAsOGAuF/hgIDhgLzhgKxf4YCe4YCx4YCsX+GAlOGAsScuc3BsaXQoJ18nKSxcblxuICAgIGxvbmdEYXRlRm9ybWF0OiB7XG4gICAgICAgIExUOiAnSEg6bW0nLFxuICAgICAgICBMVFM6ICdISDptbTpzcycsXG4gICAgICAgIEw6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgTEw6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgIExMTDogJ0QgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgTExMTDogJ2RkZGQgRCBNTU1NIFlZWVkgSEg6bW0nXG4gICAgfSxcbiAgICBjYWxlbmRhcjoge1xuICAgICAgICBzYW1lRGF5OiAnW+GAmuGAlOGAsS5dIExUIFvhgJnhgL7hgKxdJyxcbiAgICAgICAgbmV4dERheTogJ1vhgJnhgJThgIDhgLrhgJbhgLzhgJThgLpdIExUIFvhgJnhgL7hgKxdJyxcbiAgICAgICAgbmV4dFdlZWs6ICdkZGRkIExUIFvhgJnhgL7hgKxdJyxcbiAgICAgICAgbGFzdERheTogJ1vhgJnhgJThgLEu4YCAXSBMVCBb4YCZ4YC+4YCsXScsXG4gICAgICAgIGxhc3RXZWVrOiAnW+GAleGAvOGAruGAuOGAgeGAsuGAt+GAnuGAseGArF0gZGRkZCBMVCBb4YCZ4YC+4YCsXScsXG4gICAgICAgIHNhbWVFbHNlOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZToge1xuICAgICAgICBmdXR1cmU6ICfhgJzhgKzhgJnhgIrhgLrhgLcgJXMg4YCZ4YC+4YCsJyxcbiAgICAgICAgcGFzdDogJ+GAnOGAveGAlOGAuuGAgeGAsuGAt+GAnuGAseGArCAlcyDhgIAnLFxuICAgICAgICBzOiAn4YCF4YCA4YC54YCA4YCU4YC6LuGAoeGAlOGAiuGAuuGAuOGAhOGAmuGAuicsXG4gICAgICAgIHNzIDogJyVkIOGAheGAgOGAueGAgOGAlOGAt+GAuicsXG4gICAgICAgIG06ICfhgJDhgIXhgLrhgJnhgK3hgJThgIXhgLonLFxuICAgICAgICBtbTogJyVkIOGAmeGAreGAlOGAheGAuicsXG4gICAgICAgIGg6ICfhgJDhgIXhgLrhgJThgKzhgJvhgK4nLFxuICAgICAgICBoaDogJyVkIOGAlOGArOGAm+GAricsXG4gICAgICAgIGQ6ICfhgJDhgIXhgLrhgJvhgIDhgLonLFxuICAgICAgICBkZDogJyVkIOGAm+GAgOGAuicsXG4gICAgICAgIE06ICfhgJDhgIXhgLrhgJwnLFxuICAgICAgICBNTTogJyVkIOGAnCcsXG4gICAgICAgIHk6ICfhgJDhgIXhgLrhgJThgL7hgIXhgLonLFxuICAgICAgICB5eTogJyVkIOGAlOGAvuGAheGAuidcbiAgICB9LFxuICAgIHByZXBhcnNlOiBmdW5jdGlvbiAoc3RyaW5nKSB7XG4gICAgICAgIHJldHVybiBzdHJpbmcucmVwbGFjZSgvW+GBgeGBguGBg+GBhOGBheGBhuGBh+GBiOGBieGBgF0vZywgZnVuY3Rpb24gKG1hdGNoKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVtYmVyTWFwJDlbbWF0Y2hdO1xuICAgICAgICB9KTtcbiAgICB9LFxuICAgIHBvc3Rmb3JtYXQ6IGZ1bmN0aW9uIChzdHJpbmcpIHtcbiAgICAgICAgcmV0dXJuIHN0cmluZy5yZXBsYWNlKC9cXGQvZywgZnVuY3Rpb24gKG1hdGNoKSB7XG4gICAgICAgICAgICByZXR1cm4gc3ltYm9sTWFwJDEwW21hdGNoXTtcbiAgICAgICAgfSk7XG4gICAgfSxcbiAgICB3ZWVrOiB7XG4gICAgICAgIGRvdzogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgIGRveTogNCAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiAxc3QgaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgfVxufSk7XG5cbi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBOb3J3ZWdpYW4gQm9rbcOlbCBbbmJdXG4vLyEgYXV0aG9ycyA6IEVzcGVuIEhvdmxhbmRzZGFsIDogaHR0cHM6Ly9naXRodWIuY29tL3JleHhhcnNcbi8vISAgICAgICAgICAgU2lndXJkIEdhcnRtYW5uIDogaHR0cHM6Ly9naXRodWIuY29tL3NpZ3VyZGdhXG5cbmhvb2tzLmRlZmluZUxvY2FsZSgnbmInLCB7XG4gICAgbW9udGhzIDogJ2phbnVhcl9mZWJydWFyX21hcnNfYXByaWxfbWFpX2p1bmlfanVsaV9hdWd1c3Rfc2VwdGVtYmVyX29rdG9iZXJfbm92ZW1iZXJfZGVzZW1iZXInLnNwbGl0KCdfJyksXG4gICAgbW9udGhzU2hvcnQgOiAnamFuLl9mZWIuX21hcnNfYXByaWxfbWFpX2p1bmlfanVsaV9hdWcuX3NlcC5fb2t0Ll9ub3YuX2Rlcy4nLnNwbGl0KCdfJyksXG4gICAgbW9udGhzUGFyc2VFeGFjdCA6IHRydWUsXG4gICAgd2Vla2RheXMgOiAnc8O4bmRhZ19tYW5kYWdfdGlyc2RhZ19vbnNkYWdfdG9yc2RhZ19mcmVkYWdfbMO4cmRhZycuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0IDogJ3PDuC5fbWEuX3RpLl9vbi5fdG8uX2ZyLl9sw7guJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzTWluIDogJ3PDuF9tYV90aV9vbl90b19mcl9sw7gnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNQYXJzZUV4YWN0IDogdHJ1ZSxcbiAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgTFQgOiAnSEg6bW0nLFxuICAgICAgICBMVFMgOiAnSEg6bW06c3MnLFxuICAgICAgICBMIDogJ0RELk1NLllZWVknLFxuICAgICAgICBMTCA6ICdELiBNTU1NIFlZWVknLFxuICAgICAgICBMTEwgOiAnRC4gTU1NTSBZWVlZIFtrbC5dIEhIOm1tJyxcbiAgICAgICAgTExMTCA6ICdkZGRkIEQuIE1NTU0gWVlZWSBba2wuXSBISDptbSdcbiAgICB9LFxuICAgIGNhbGVuZGFyIDoge1xuICAgICAgICBzYW1lRGF5OiAnW2kgZGFnIGtsLl0gTFQnLFxuICAgICAgICBuZXh0RGF5OiAnW2kgbW9yZ2VuIGtsLl0gTFQnLFxuICAgICAgICBuZXh0V2VlazogJ2RkZGQgW2tsLl0gTFQnLFxuICAgICAgICBsYXN0RGF5OiAnW2kgZ8OlciBrbC5dIExUJyxcbiAgICAgICAgbGFzdFdlZWs6ICdbZm9ycmlnZV0gZGRkZCBba2wuXSBMVCcsXG4gICAgICAgIHNhbWVFbHNlOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJ29tICVzJyxcbiAgICAgICAgcGFzdCA6ICclcyBzaWRlbicsXG4gICAgICAgIHMgOiAnbm9lbiBzZWt1bmRlcicsXG4gICAgICAgIHNzIDogJyVkIHNla3VuZGVyJyxcbiAgICAgICAgbSA6ICdldHQgbWludXR0JyxcbiAgICAgICAgbW0gOiAnJWQgbWludXR0ZXInLFxuICAgICAgICBoIDogJ2VuIHRpbWUnLFxuICAgICAgICBoaCA6ICclZCB0aW1lcicsXG4gICAgICAgIGQgOiAnZW4gZGFnJyxcbiAgICAgICAgZGQgOiAnJWQgZGFnZXInLFxuICAgICAgICBNIDogJ2VuIG3DpW5lZCcsXG4gICAgICAgIE1NIDogJyVkIG3DpW5lZGVyJyxcbiAgICAgICAgeSA6ICdldHQgw6VyJyxcbiAgICAgICAgeXkgOiAnJWQgw6VyJ1xuICAgIH0sXG4gICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9XFwuLyxcbiAgICBvcmRpbmFsIDogJyVkLicsXG4gICAgd2VlayA6IHtcbiAgICAgICAgZG93IDogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgIGRveSA6IDQgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDR0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICB9XG59KTtcblxuLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSA6IE5lcGFsZXNlIFtuZV1cbi8vISBhdXRob3IgOiBzdXZhc2ggOiBodHRwczovL2dpdGh1Yi5jb20vc3V2YXNoXG5cbnZhciBzeW1ib2xNYXAkMTEgPSB7XG4gICAgJzEnOiAn4KWnJyxcbiAgICAnMic6ICfgpagnLFxuICAgICczJzogJ+ClqScsXG4gICAgJzQnOiAn4KWqJyxcbiAgICAnNSc6ICfgpasnLFxuICAgICc2JzogJ+ClrCcsXG4gICAgJzcnOiAn4KWtJyxcbiAgICAnOCc6ICfgpa4nLFxuICAgICc5JzogJ+ClrycsXG4gICAgJzAnOiAn4KWmJ1xufTtcbnZhciBudW1iZXJNYXAkMTAgPSB7XG4gICAgJ+Clpyc6ICcxJyxcbiAgICAn4KWoJzogJzInLFxuICAgICfgpaknOiAnMycsXG4gICAgJ+Clqic6ICc0JyxcbiAgICAn4KWrJzogJzUnLFxuICAgICfgpawnOiAnNicsXG4gICAgJ+ClrSc6ICc3JyxcbiAgICAn4KWuJzogJzgnLFxuICAgICfgpa8nOiAnOScsXG4gICAgJ+Clpic6ICcwJ1xufTtcblxuaG9va3MuZGVmaW5lTG9jYWxlKCduZScsIHtcbiAgICBtb250aHMgOiAn4KSc4KSo4KS14KSw4KWAX+Ckq+Clh+CkrOCljeCksOClgeCkteCksOClgF/gpK7gpL7gpLDgpY3gpJpf4KSF4KSq4KWN4KSw4KS/4KSyX+CkruCkiF/gpJzgpYHgpKhf4KSc4KWB4KSy4KS+4KSIX+CkheCkl+Ckt+CljeCkn1/gpLjgpYfgpKrgpY3gpJ/gpYfgpK7gpY3gpKzgpLBf4KSF4KSV4KWN4KSf4KWL4KSs4KSwX+CkqOCli+CkreClh+CkruCljeCkrOCksF/gpKHgpL/gpLjgpYfgpK7gpY3gpKzgpLAnLnNwbGl0KCdfJyksXG4gICAgbW9udGhzU2hvcnQgOiAn4KSc4KSoLl/gpKvgpYfgpKzgpY3gpLDgpYEuX+CkruCkvuCksOCljeCkml/gpIXgpKrgpY3gpLDgpL8uX+CkruCkiF/gpJzgpYHgpKhf4KSc4KWB4KSy4KS+4KSILl/gpIXgpJcuX+CkuOClh+CkquCljeCkny5f4KSF4KSV4KWN4KSf4KWLLl/gpKjgpYvgpK3gpYcuX+CkoeCkv+CkuOClhy4nLnNwbGl0KCdfJyksXG4gICAgbW9udGhzUGFyc2VFeGFjdCA6IHRydWUsXG4gICAgd2Vla2RheXMgOiAn4KSG4KSH4KSk4KSs4KS+4KSwX+CkuOCli+CkruCkrOCkvuCksF/gpK7gpJngpY3gpJfgpLLgpKzgpL7gpLBf4KSs4KWB4KSn4KSs4KS+4KSwX+CkrOCkv+CkueCkv+CkrOCkvuCksF/gpLbgpYHgpJXgpY3gpLDgpKzgpL7gpLBf4KS24KSo4KS/4KSs4KS+4KSwJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzU2hvcnQgOiAn4KSG4KSH4KSkLl/gpLjgpYvgpK4uX+CkruCkmeCljeCkl+Cksi5f4KSs4KWB4KSnLl/gpKzgpL/gpLngpL8uX+CktuClgeCkleCljeCksC5f4KS24KSo4KS/Licuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbiA6ICfgpIYuX+CkuOCliy5f4KSu4KSCLl/gpKzgpYEuX+CkrOCkvy5f4KS24KWBLl/gpLYuJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzUGFyc2VFeGFjdCA6IHRydWUsXG4gICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgIExUIDogJ0HgpJXgpYsgaDptbSDgpKzgpJzgpYcnLFxuICAgICAgICBMVFMgOiAnQeCkleCliyBoOm1tOnNzIOCkrOCknOClhycsXG4gICAgICAgIEwgOiAnREQvTU0vWVlZWScsXG4gICAgICAgIExMIDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgTExMIDogJ0QgTU1NTSBZWVlZLCBB4KSV4KWLIGg6bW0g4KSs4KSc4KWHJyxcbiAgICAgICAgTExMTCA6ICdkZGRkLCBEIE1NTU0gWVlZWSwgQeCkleCliyBoOm1tIOCkrOCknOClhydcbiAgICB9LFxuICAgIHByZXBhcnNlOiBmdW5jdGlvbiAoc3RyaW5nKSB7XG4gICAgICAgIHJldHVybiBzdHJpbmcucmVwbGFjZSgvW+Clp+ClqOClqeClquClq+ClrOClreClruClr+Clpl0vZywgZnVuY3Rpb24gKG1hdGNoKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVtYmVyTWFwJDEwW21hdGNoXTtcbiAgICAgICAgfSk7XG4gICAgfSxcbiAgICBwb3N0Zm9ybWF0OiBmdW5jdGlvbiAoc3RyaW5nKSB7XG4gICAgICAgIHJldHVybiBzdHJpbmcucmVwbGFjZSgvXFxkL2csIGZ1bmN0aW9uIChtYXRjaCkge1xuICAgICAgICAgICAgcmV0dXJuIHN5bWJvbE1hcCQxMVttYXRjaF07XG4gICAgICAgIH0pO1xuICAgIH0sXG4gICAgbWVyaWRpZW1QYXJzZTogL+CksOCkvuCkpOCkv3zgpKzgpL/gpLngpL7gpKh84KSm4KS/4KSJ4KSB4KS44KWLfOCkuOCkvuCkgeCknS8sXG4gICAgbWVyaWRpZW1Ib3VyIDogZnVuY3Rpb24gKGhvdXIsIG1lcmlkaWVtKSB7XG4gICAgICAgIGlmIChob3VyID09PSAxMikge1xuICAgICAgICAgICAgaG91ciA9IDA7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG1lcmlkaWVtID09PSAn4KSw4KS+4KSk4KS/Jykge1xuICAgICAgICAgICAgcmV0dXJuIGhvdXIgPCA0ID8gaG91ciA6IGhvdXIgKyAxMjtcbiAgICAgICAgfSBlbHNlIGlmIChtZXJpZGllbSA9PT0gJ+CkrOCkv+CkueCkvuCkqCcpIHtcbiAgICAgICAgICAgIHJldHVybiBob3VyO1xuICAgICAgICB9IGVsc2UgaWYgKG1lcmlkaWVtID09PSAn4KSm4KS/4KSJ4KSB4KS44KWLJykge1xuICAgICAgICAgICAgcmV0dXJuIGhvdXIgPj0gMTAgPyBob3VyIDogaG91ciArIDEyO1xuICAgICAgICB9IGVsc2UgaWYgKG1lcmlkaWVtID09PSAn4KS44KS+4KSB4KSdJykge1xuICAgICAgICAgICAgcmV0dXJuIGhvdXIgKyAxMjtcbiAgICAgICAgfVxuICAgIH0sXG4gICAgbWVyaWRpZW0gOiBmdW5jdGlvbiAoaG91ciwgbWludXRlLCBpc0xvd2VyKSB7XG4gICAgICAgIGlmIChob3VyIDwgMykge1xuICAgICAgICAgICAgcmV0dXJuICfgpLDgpL7gpKTgpL8nO1xuICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAxMikge1xuICAgICAgICAgICAgcmV0dXJuICfgpKzgpL/gpLngpL7gpKgnO1xuICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAxNikge1xuICAgICAgICAgICAgcmV0dXJuICfgpKbgpL/gpIngpIHgpLjgpYsnO1xuICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAyMCkge1xuICAgICAgICAgICAgcmV0dXJuICfgpLjgpL7gpIHgpJ0nO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuICfgpLDgpL7gpKTgpL8nO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheSA6ICdb4KSG4KScXSBMVCcsXG4gICAgICAgIG5leHREYXkgOiAnW+CkreCli+CksuCkv10gTFQnLFxuICAgICAgICBuZXh0V2VlayA6ICdb4KSG4KSJ4KSB4KSm4KWLXSBkZGRkWyxdIExUJyxcbiAgICAgICAgbGFzdERheSA6ICdb4KS54KS/4KSc4KWLXSBMVCcsXG4gICAgICAgIGxhc3RXZWVrIDogJ1vgpJfgpI/gpJXgpYtdIGRkZGRbLF0gTFQnLFxuICAgICAgICBzYW1lRWxzZSA6ICdMJ1xuICAgIH0sXG4gICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICBmdXR1cmUgOiAnJXPgpK7gpL4nLFxuICAgICAgICBwYXN0IDogJyVzIOCkheCkl+CkvuCkoeCkvycsXG4gICAgICAgIHMgOiAn4KSV4KWH4KS54KWAIOCkleCljeCkt+CkoycsXG4gICAgICAgIHNzIDogJyVkIOCkuOClh+CkleClh+Cko+CljeCkoScsXG4gICAgICAgIG0gOiAn4KSP4KSVIOCkruCkv+CkqOClh+CknycsXG4gICAgICAgIG1tIDogJyVkIOCkruCkv+CkqOClh+CknycsXG4gICAgICAgIGggOiAn4KSP4KSVIOCkmOCko+CljeCkn+CkvicsXG4gICAgICAgIGhoIDogJyVkIOCkmOCko+CljeCkn+CkvicsXG4gICAgICAgIGQgOiAn4KSP4KSVIOCkpuCkv+CkqCcsXG4gICAgICAgIGRkIDogJyVkIOCkpuCkv+CkqCcsXG4gICAgICAgIE0gOiAn4KSP4KSVIOCkruCkueCkv+CkqOCkvicsXG4gICAgICAgIE1NIDogJyVkIOCkruCkueCkv+CkqOCkvicsXG4gICAgICAgIHkgOiAn4KSP4KSVIOCkrOCksOCljeCktycsXG4gICAgICAgIHl5IDogJyVkIOCkrOCksOCljeCktydcbiAgICB9LFxuICAgIHdlZWsgOiB7XG4gICAgICAgIGRvdyA6IDAsIC8vIFN1bmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICBkb3kgOiA2ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiAxc3QgaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgfVxufSk7XG5cbi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBEdXRjaCAoQmVsZ2l1bSkgW25sLWJlXVxuLy8hIGF1dGhvciA6IEpvcmlzIFLDtmxpbmcgOiBodHRwczovL2dpdGh1Yi5jb20vam9yaXNyb2xpbmdcbi8vISBhdXRob3IgOiBKYWNvYiBNaWRkYWcgOiBodHRwczovL2dpdGh1Yi5jb20vbWlkZGFnalxuXG52YXIgbW9udGhzU2hvcnRXaXRoRG90cyQxID0gJ2phbi5fZmViLl9tcnQuX2Fwci5fbWVpX2p1bi5fanVsLl9hdWcuX3NlcC5fb2t0Ll9ub3YuX2RlYy4nLnNwbGl0KCdfJyk7XG52YXIgbW9udGhzU2hvcnRXaXRob3V0RG90cyQxID0gJ2phbl9mZWJfbXJ0X2Fwcl9tZWlfanVuX2p1bF9hdWdfc2VwX29rdF9ub3ZfZGVjJy5zcGxpdCgnXycpO1xuXG52YXIgbW9udGhzUGFyc2UkMiA9IFsvXmphbi9pLCAvXmZlYi9pLCAvXm1hYXJ0fG1ydC4/JC9pLCAvXmFwci9pLCAvXm1laSQvaSwgL15qdW5baS5dPyQvaSwgL15qdWxbaS5dPyQvaSwgL15hdWcvaSwgL15zZXAvaSwgL15va3QvaSwgL15ub3YvaSwgL15kZWMvaV07XG52YXIgbW9udGhzUmVnZXgkMyA9IC9eKGphbnVhcml8ZmVicnVhcml8bWFhcnR8YXByaWx8bWVpfGFwcmlsfGp1W25sXWl8YXVndXN0dXN8c2VwdGVtYmVyfG9rdG9iZXJ8bm92ZW1iZXJ8ZGVjZW1iZXJ8amFuXFwuP3xmZWJcXC4/fG1ydFxcLj98YXByXFwuP3xqdVtubF1cXC4/fGF1Z1xcLj98c2VwXFwuP3xva3RcXC4/fG5vdlxcLj98ZGVjXFwuPykvaTtcblxuaG9va3MuZGVmaW5lTG9jYWxlKCdubC1iZScsIHtcbiAgICBtb250aHMgOiAnamFudWFyaV9mZWJydWFyaV9tYWFydF9hcHJpbF9tZWlfanVuaV9qdWxpX2F1Z3VzdHVzX3NlcHRlbWJlcl9va3RvYmVyX25vdmVtYmVyX2RlY2VtYmVyJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0IDogZnVuY3Rpb24gKG0sIGZvcm1hdCkge1xuICAgICAgICBpZiAoIW0pIHtcbiAgICAgICAgICAgIHJldHVybiBtb250aHNTaG9ydFdpdGhEb3RzJDE7XG4gICAgICAgIH0gZWxzZSBpZiAoLy1NTU0tLy50ZXN0KGZvcm1hdCkpIHtcbiAgICAgICAgICAgIHJldHVybiBtb250aHNTaG9ydFdpdGhvdXREb3RzJDFbbS5tb250aCgpXTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBtb250aHNTaG9ydFdpdGhEb3RzJDFbbS5tb250aCgpXTtcbiAgICAgICAgfVxuICAgIH0sXG5cbiAgICBtb250aHNSZWdleDogbW9udGhzUmVnZXgkMyxcbiAgICBtb250aHNTaG9ydFJlZ2V4OiBtb250aHNSZWdleCQzLFxuICAgIG1vbnRoc1N0cmljdFJlZ2V4OiAvXihqYW51YXJpfGZlYnJ1YXJpfG1hYXJ0fG1laXxqdVtubF1pfGFwcmlsfGF1Z3VzdHVzfHNlcHRlbWJlcnxva3RvYmVyfG5vdmVtYmVyfGRlY2VtYmVyKS9pLFxuICAgIG1vbnRoc1Nob3J0U3RyaWN0UmVnZXg6IC9eKGphblxcLj98ZmViXFwuP3xtcnRcXC4/fGFwclxcLj98bWVpfGp1W25sXVxcLj98YXVnXFwuP3xzZXBcXC4/fG9rdFxcLj98bm92XFwuP3xkZWNcXC4/KS9pLFxuXG4gICAgbW9udGhzUGFyc2UgOiBtb250aHNQYXJzZSQyLFxuICAgIGxvbmdNb250aHNQYXJzZSA6IG1vbnRoc1BhcnNlJDIsXG4gICAgc2hvcnRNb250aHNQYXJzZSA6IG1vbnRoc1BhcnNlJDIsXG5cbiAgICB3ZWVrZGF5cyA6ICd6b25kYWdfbWFhbmRhZ19kaW5zZGFnX3dvZW5zZGFnX2RvbmRlcmRhZ192cmlqZGFnX3phdGVyZGFnJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzU2hvcnQgOiAnem8uX21hLl9kaS5fd28uX2RvLl92ci5femEuJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzTWluIDogJ3pvX21hX2RpX3dvX2RvX3ZyX3phJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzUGFyc2VFeGFjdCA6IHRydWUsXG4gICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgIExUIDogJ0hIOm1tJyxcbiAgICAgICAgTFRTIDogJ0hIOm1tOnNzJyxcbiAgICAgICAgTCA6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgTEwgOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICBMTEwgOiAnRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICBMTExMIDogJ2RkZGQgRCBNTU1NIFlZWVkgSEg6bW0nXG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheTogJ1t2YW5kYWFnIG9tXSBMVCcsXG4gICAgICAgIG5leHREYXk6ICdbbW9yZ2VuIG9tXSBMVCcsXG4gICAgICAgIG5leHRXZWVrOiAnZGRkZCBbb21dIExUJyxcbiAgICAgICAgbGFzdERheTogJ1tnaXN0ZXJlbiBvbV0gTFQnLFxuICAgICAgICBsYXN0V2VlazogJ1thZmdlbG9wZW5dIGRkZGQgW29tXSBMVCcsXG4gICAgICAgIHNhbWVFbHNlOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJ292ZXIgJXMnLFxuICAgICAgICBwYXN0IDogJyVzIGdlbGVkZW4nLFxuICAgICAgICBzIDogJ2VlbiBwYWFyIHNlY29uZGVuJyxcbiAgICAgICAgc3MgOiAnJWQgc2Vjb25kZW4nLFxuICAgICAgICBtIDogJ8Opw6luIG1pbnV1dCcsXG4gICAgICAgIG1tIDogJyVkIG1pbnV0ZW4nLFxuICAgICAgICBoIDogJ8Opw6luIHV1cicsXG4gICAgICAgIGhoIDogJyVkIHV1cicsXG4gICAgICAgIGQgOiAnw6nDqW4gZGFnJyxcbiAgICAgICAgZGQgOiAnJWQgZGFnZW4nLFxuICAgICAgICBNIDogJ8Opw6luIG1hYW5kJyxcbiAgICAgICAgTU0gOiAnJWQgbWFhbmRlbicsXG4gICAgICAgIHkgOiAnw6nDqW4gamFhcicsXG4gICAgICAgIHl5IDogJyVkIGphYXInXG4gICAgfSxcbiAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn0oc3RlfGRlKS8sXG4gICAgb3JkaW5hbCA6IGZ1bmN0aW9uIChudW1iZXIpIHtcbiAgICAgICAgcmV0dXJuIG51bWJlciArICgobnVtYmVyID09PSAxIHx8IG51bWJlciA9PT0gOCB8fCBudW1iZXIgPj0gMjApID8gJ3N0ZScgOiAnZGUnKTtcbiAgICB9LFxuICAgIHdlZWsgOiB7XG4gICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICBkb3kgOiA0ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgfVxufSk7XG5cbi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBEdXRjaCBbbmxdXG4vLyEgYXV0aG9yIDogSm9yaXMgUsO2bGluZyA6IGh0dHBzOi8vZ2l0aHViLmNvbS9qb3Jpc3JvbGluZ1xuLy8hIGF1dGhvciA6IEphY29iIE1pZGRhZyA6IGh0dHBzOi8vZ2l0aHViLmNvbS9taWRkYWdqXG5cbnZhciBtb250aHNTaG9ydFdpdGhEb3RzJDIgPSAnamFuLl9mZWIuX21ydC5fYXByLl9tZWlfanVuLl9qdWwuX2F1Zy5fc2VwLl9va3QuX25vdi5fZGVjLicuc3BsaXQoJ18nKTtcbnZhciBtb250aHNTaG9ydFdpdGhvdXREb3RzJDIgPSAnamFuX2ZlYl9tcnRfYXByX21laV9qdW5fanVsX2F1Z19zZXBfb2t0X25vdl9kZWMnLnNwbGl0KCdfJyk7XG5cbnZhciBtb250aHNQYXJzZSQzID0gWy9eamFuL2ksIC9eZmViL2ksIC9ebWFhcnR8bXJ0Lj8kL2ksIC9eYXByL2ksIC9ebWVpJC9pLCAvXmp1bltpLl0/JC9pLCAvXmp1bFtpLl0/JC9pLCAvXmF1Zy9pLCAvXnNlcC9pLCAvXm9rdC9pLCAvXm5vdi9pLCAvXmRlYy9pXTtcbnZhciBtb250aHNSZWdleCQ0ID0gL14oamFudWFyaXxmZWJydWFyaXxtYWFydHxhcHJpbHxtZWl8YXByaWx8anVbbmxdaXxhdWd1c3R1c3xzZXB0ZW1iZXJ8b2t0b2Jlcnxub3ZlbWJlcnxkZWNlbWJlcnxqYW5cXC4/fGZlYlxcLj98bXJ0XFwuP3xhcHJcXC4/fGp1W25sXVxcLj98YXVnXFwuP3xzZXBcXC4/fG9rdFxcLj98bm92XFwuP3xkZWNcXC4/KS9pO1xuXG5ob29rcy5kZWZpbmVMb2NhbGUoJ25sJywge1xuICAgIG1vbnRocyA6ICdqYW51YXJpX2ZlYnJ1YXJpX21hYXJ0X2FwcmlsX21laV9qdW5pX2p1bGlfYXVndXN0dXNfc2VwdGVtYmVyX29rdG9iZXJfbm92ZW1iZXJfZGVjZW1iZXInLnNwbGl0KCdfJyksXG4gICAgbW9udGhzU2hvcnQgOiBmdW5jdGlvbiAobSwgZm9ybWF0KSB7XG4gICAgICAgIGlmICghbSkge1xuICAgICAgICAgICAgcmV0dXJuIG1vbnRoc1Nob3J0V2l0aERvdHMkMjtcbiAgICAgICAgfSBlbHNlIGlmICgvLU1NTS0vLnRlc3QoZm9ybWF0KSkge1xuICAgICAgICAgICAgcmV0dXJuIG1vbnRoc1Nob3J0V2l0aG91dERvdHMkMlttLm1vbnRoKCldO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIG1vbnRoc1Nob3J0V2l0aERvdHMkMlttLm1vbnRoKCldO1xuICAgICAgICB9XG4gICAgfSxcblxuICAgIG1vbnRoc1JlZ2V4OiBtb250aHNSZWdleCQ0LFxuICAgIG1vbnRoc1Nob3J0UmVnZXg6IG1vbnRoc1JlZ2V4JDQsXG4gICAgbW9udGhzU3RyaWN0UmVnZXg6IC9eKGphbnVhcml8ZmVicnVhcml8bWFhcnR8bWVpfGp1W25sXWl8YXByaWx8YXVndXN0dXN8c2VwdGVtYmVyfG9rdG9iZXJ8bm92ZW1iZXJ8ZGVjZW1iZXIpL2ksXG4gICAgbW9udGhzU2hvcnRTdHJpY3RSZWdleDogL14oamFuXFwuP3xmZWJcXC4/fG1ydFxcLj98YXByXFwuP3xtZWl8anVbbmxdXFwuP3xhdWdcXC4/fHNlcFxcLj98b2t0XFwuP3xub3ZcXC4/fGRlY1xcLj8pL2ksXG5cbiAgICBtb250aHNQYXJzZSA6IG1vbnRoc1BhcnNlJDMsXG4gICAgbG9uZ01vbnRoc1BhcnNlIDogbW9udGhzUGFyc2UkMyxcbiAgICBzaG9ydE1vbnRoc1BhcnNlIDogbW9udGhzUGFyc2UkMyxcblxuICAgIHdlZWtkYXlzIDogJ3pvbmRhZ19tYWFuZGFnX2RpbnNkYWdfd29lbnNkYWdfZG9uZGVyZGFnX3ZyaWpkYWdfemF0ZXJkYWcnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydCA6ICd6by5fbWEuX2RpLl93by5fZG8uX3ZyLl96YS4nLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW4gOiAnem9fbWFfZGlfd29fZG9fdnJfemEnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNQYXJzZUV4YWN0IDogdHJ1ZSxcbiAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgTFQgOiAnSEg6bW0nLFxuICAgICAgICBMVFMgOiAnSEg6bW06c3MnLFxuICAgICAgICBMIDogJ0RELU1NLVlZWVknLFxuICAgICAgICBMTCA6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgIExMTCA6ICdEIE1NTU0gWVlZWSBISDptbScsXG4gICAgICAgIExMTEwgOiAnZGRkZCBEIE1NTU0gWVlZWSBISDptbSdcbiAgICB9LFxuICAgIGNhbGVuZGFyIDoge1xuICAgICAgICBzYW1lRGF5OiAnW3ZhbmRhYWcgb21dIExUJyxcbiAgICAgICAgbmV4dERheTogJ1ttb3JnZW4gb21dIExUJyxcbiAgICAgICAgbmV4dFdlZWs6ICdkZGRkIFtvbV0gTFQnLFxuICAgICAgICBsYXN0RGF5OiAnW2dpc3RlcmVuIG9tXSBMVCcsXG4gICAgICAgIGxhc3RXZWVrOiAnW2FmZ2Vsb3Blbl0gZGRkZCBbb21dIExUJyxcbiAgICAgICAgc2FtZUVsc2U6ICdMJ1xuICAgIH0sXG4gICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICBmdXR1cmUgOiAnb3ZlciAlcycsXG4gICAgICAgIHBhc3QgOiAnJXMgZ2VsZWRlbicsXG4gICAgICAgIHMgOiAnZWVuIHBhYXIgc2Vjb25kZW4nLFxuICAgICAgICBzcyA6ICclZCBzZWNvbmRlbicsXG4gICAgICAgIG0gOiAnw6nDqW4gbWludXV0JyxcbiAgICAgICAgbW0gOiAnJWQgbWludXRlbicsXG4gICAgICAgIGggOiAnw6nDqW4gdXVyJyxcbiAgICAgICAgaGggOiAnJWQgdXVyJyxcbiAgICAgICAgZCA6ICfDqcOpbiBkYWcnLFxuICAgICAgICBkZCA6ICclZCBkYWdlbicsXG4gICAgICAgIE0gOiAnw6nDqW4gbWFhbmQnLFxuICAgICAgICBNTSA6ICclZCBtYWFuZGVuJyxcbiAgICAgICAgeSA6ICfDqcOpbiBqYWFyJyxcbiAgICAgICAgeXkgOiAnJWQgamFhcidcbiAgICB9LFxuICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfShzdGV8ZGUpLyxcbiAgICBvcmRpbmFsIDogZnVuY3Rpb24gKG51bWJlcikge1xuICAgICAgICByZXR1cm4gbnVtYmVyICsgKChudW1iZXIgPT09IDEgfHwgbnVtYmVyID09PSA4IHx8IG51bWJlciA+PSAyMCkgPyAnc3RlJyA6ICdkZScpO1xuICAgIH0sXG4gICAgd2VlayA6IHtcbiAgICAgICAgZG93IDogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgIGRveSA6IDQgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDR0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICB9XG59KTtcblxuLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSA6IE55bm9yc2sgW25uXVxuLy8hIGF1dGhvciA6IGh0dHBzOi8vZ2l0aHViLmNvbS9tZWNodXdpbmRcblxuaG9va3MuZGVmaW5lTG9jYWxlKCdubicsIHtcbiAgICBtb250aHMgOiAnamFudWFyX2ZlYnJ1YXJfbWFyc19hcHJpbF9tYWlfanVuaV9qdWxpX2F1Z3VzdF9zZXB0ZW1iZXJfb2t0b2Jlcl9ub3ZlbWJlcl9kZXNlbWJlcicuc3BsaXQoJ18nKSxcbiAgICBtb250aHNTaG9ydCA6ICdqYW5fZmViX21hcl9hcHJfbWFpX2p1bl9qdWxfYXVnX3NlcF9va3Rfbm92X2Rlcycuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5cyA6ICdzdW5kYWdfbcOlbmRhZ190eXNkYWdfb25zZGFnX3RvcnNkYWdfZnJlZGFnX2xhdXJkYWcnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydCA6ICdzdW5fbcOlbl90eXNfb25zX3Rvcl9mcmVfbGF1Jy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzTWluIDogJ3N1X23DpV90eV9vbl90b19mcl9sw7gnLnNwbGl0KCdfJyksXG4gICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgIExUIDogJ0hIOm1tJyxcbiAgICAgICAgTFRTIDogJ0hIOm1tOnNzJyxcbiAgICAgICAgTCA6ICdERC5NTS5ZWVlZJyxcbiAgICAgICAgTEwgOiAnRC4gTU1NTSBZWVlZJyxcbiAgICAgICAgTExMIDogJ0QuIE1NTU0gWVlZWSBba2wuXSBIOm1tJyxcbiAgICAgICAgTExMTCA6ICdkZGRkIEQuIE1NTU0gWVlZWSBba2wuXSBISDptbSdcbiAgICB9LFxuICAgIGNhbGVuZGFyIDoge1xuICAgICAgICBzYW1lRGF5OiAnW0kgZGFnIGtsb2trYV0gTFQnLFxuICAgICAgICBuZXh0RGF5OiAnW0kgbW9yZ29uIGtsb2trYV0gTFQnLFxuICAgICAgICBuZXh0V2VlazogJ2RkZGQgW2tsb2trYV0gTFQnLFxuICAgICAgICBsYXN0RGF5OiAnW0kgZ8OlciBrbG9ra2FdIExUJyxcbiAgICAgICAgbGFzdFdlZWs6ICdbRsO4cmVnw6VhbmRlXSBkZGRkIFtrbG9ra2FdIExUJyxcbiAgICAgICAgc2FtZUVsc2U6ICdMJ1xuICAgIH0sXG4gICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICBmdXR1cmUgOiAnb20gJXMnLFxuICAgICAgICBwYXN0IDogJyVzIHNpZGFuJyxcbiAgICAgICAgcyA6ICdub2tyZSBzZWt1bmQnLFxuICAgICAgICBzcyA6ICclZCBzZWt1bmQnLFxuICAgICAgICBtIDogJ2VpdCBtaW51dHQnLFxuICAgICAgICBtbSA6ICclZCBtaW51dHQnLFxuICAgICAgICBoIDogJ2VpbiB0aW1lJyxcbiAgICAgICAgaGggOiAnJWQgdGltYXInLFxuICAgICAgICBkIDogJ2VpbiBkYWcnLFxuICAgICAgICBkZCA6ICclZCBkYWdhcicsXG4gICAgICAgIE0gOiAnZWluIG3DpW5hZCcsXG4gICAgICAgIE1NIDogJyVkIG3DpW5hZGVyJyxcbiAgICAgICAgeSA6ICdlaXQgw6VyJyxcbiAgICAgICAgeXkgOiAnJWQgw6VyJ1xuICAgIH0sXG4gICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9XFwuLyxcbiAgICBvcmRpbmFsIDogJyVkLicsXG4gICAgd2VlayA6IHtcbiAgICAgICAgZG93IDogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgIGRveSA6IDQgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDR0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICB9XG59KTtcblxuLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSA6IFB1bmphYmkgKEluZGlhKSBbcGEtaW5dXG4vLyEgYXV0aG9yIDogSGFycHJlZXQgU2luZ2ggOiBodHRwczovL2dpdGh1Yi5jb20vaGFycHJlZXRraGFsc2FndGJpdFxuXG52YXIgc3ltYm9sTWFwJDEyID0ge1xuICAgICcxJzogJ+CppycsXG4gICAgJzInOiAn4KmoJyxcbiAgICAnMyc6ICfgqaknLFxuICAgICc0JzogJ+CpqicsXG4gICAgJzUnOiAn4KmrJyxcbiAgICAnNic6ICfgqawnLFxuICAgICc3JzogJ+CprScsXG4gICAgJzgnOiAn4KmuJyxcbiAgICAnOSc6ICfgqa8nLFxuICAgICcwJzogJ+Cppidcbn07XG52YXIgbnVtYmVyTWFwJDExID0ge1xuICAgICfgqacnOiAnMScsXG4gICAgJ+CpqCc6ICcyJyxcbiAgICAn4KmpJzogJzMnLFxuICAgICfgqaonOiAnNCcsXG4gICAgJ+Cpqyc6ICc1JyxcbiAgICAn4KmsJzogJzYnLFxuICAgICfgqa0nOiAnNycsXG4gICAgJ+Cpric6ICc4JyxcbiAgICAn4KmvJzogJzknLFxuICAgICfgqaYnOiAnMCdcbn07XG5cbmhvb2tzLmRlZmluZUxvY2FsZSgncGEtaW4nLCB7XG4gICAgLy8gVGhlcmUgYXJlIG1vbnRocyBuYW1lIGFzIHBlciBOYW5ha3NoYWhpIENhbGVuZGVyIGJ1dCB0aGV5IGFyZSBub3QgdXNlZCBhcyByaWdpZGx5IGluIG1vZGVybiBQdW5qYWJpLlxuICAgIG1vbnRocyA6ICfgqJzgqKjgqLXgqLDgqYBf4Kir4Ki84Kiw4Ki14Kiw4KmAX+CoruCovuCosOComl/gqIXgqKrgqY3gqLDgqYjgqLJf4Kiu4KiIX+ConOCpguCoqF/gqJzgqYHgqLLgqL7gqIhf4KiF4KiX4Ki44KikX+CouOCopOCpsOCorOCosF/gqIXgqJXgqKTgqYLgqKzgqLBf4Kio4Ki14Kmw4Kis4KiwX+CopuCouOCpsOCorOCosCcuc3BsaXQoJ18nKSxcbiAgICBtb250aHNTaG9ydCA6ICfgqJzgqKjgqLXgqLDgqYBf4Kir4Ki84Kiw4Ki14Kiw4KmAX+CoruCovuCosOComl/gqIXgqKrgqY3gqLDgqYjgqLJf4Kiu4KiIX+ConOCpguCoqF/gqJzgqYHgqLLgqL7gqIhf4KiF4KiX4Ki44KikX+CouOCopOCpsOCorOCosF/gqIXgqJXgqKTgqYLgqKzgqLBf4Kio4Ki14Kmw4Kis4KiwX+CopuCouOCpsOCorOCosCcuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5cyA6ICfgqJDgqKTgqLXgqL7gqLBf4Ki44KmL4Kiu4Ki14Ki+4KiwX+CoruCpsOCol+CosuCoteCovuCosF/gqKzgqYHgqKfgqLXgqL7gqLBf4Ki14KmA4Kiw4Ki14Ki+4KiwX+CouOCovOCpgeCpseColeCosOCoteCovuCosF/gqLjgqLzgqKjgqYDgqJrgqLDgqLXgqL7gqLAnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydCA6ICfgqJDgqKRf4Ki44KmL4KiuX+CoruCpsOCol+Cosl/gqKzgqYHgqKdf4Ki14KmA4KiwX+CouOCovOCpgeColeCosF/gqLjgqLzgqKjgqYAnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW4gOiAn4KiQ4KikX+CouOCpi+Corl/gqK7gqbDgqJfgqLJf4Kis4KmB4KinX+CoteCpgOCosF/gqLjgqLzgqYHgqJXgqLBf4Ki44Ki84Kio4KmAJy5zcGxpdCgnXycpLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdBIGg6bW0g4Ki14Kic4KmHJyxcbiAgICAgICAgTFRTIDogJ0EgaDptbTpzcyDgqLXgqJzgqYcnLFxuICAgICAgICBMIDogJ0REL01NL1lZWVknLFxuICAgICAgICBMTCA6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgIExMTCA6ICdEIE1NTU0gWVlZWSwgQSBoOm1tIOCoteConOCphycsXG4gICAgICAgIExMTEwgOiAnZGRkZCwgRCBNTU1NIFlZWVksIEEgaDptbSDgqLXgqJzgqYcnXG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheSA6ICdb4KiF4KicXSBMVCcsXG4gICAgICAgIG5leHREYXkgOiAnW+ColeCosl0gTFQnLFxuICAgICAgICBuZXh0V2VlayA6ICdkZGRkLCBMVCcsXG4gICAgICAgIGxhc3REYXkgOiAnW+ColeCosl0gTFQnLFxuICAgICAgICBsYXN0V2VlayA6ICdb4Kiq4Ki/4Kib4Kiy4KmHXSBkZGRkLCBMVCcsXG4gICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6ICclcyDgqLXgqL/gqbHgqJonLFxuICAgICAgICBwYXN0IDogJyVzIOCoquCov+Com+CosuCphycsXG4gICAgICAgIHMgOiAn4KiV4KmB4KidIOCouOColeCov+CpsOConycsXG4gICAgICAgIHNzIDogJyVkIOCouOColeCov+CpsOConycsXG4gICAgICAgIG0gOiAn4KiH4KiVIOCoruCov+CpsOConycsXG4gICAgICAgIG1tIDogJyVkIOCoruCov+CpsOConycsXG4gICAgICAgIGggOiAn4KiH4Kmx4KiVIOComOCpsOCon+CovicsXG4gICAgICAgIGhoIDogJyVkIOComOCpsOCon+CphycsXG4gICAgICAgIGQgOiAn4KiH4Kmx4KiVIOCopuCov+CoqCcsXG4gICAgICAgIGRkIDogJyVkIOCopuCov+CoqCcsXG4gICAgICAgIE0gOiAn4KiH4Kmx4KiVIOCoruCoueCpgOCoqOCovicsXG4gICAgICAgIE1NIDogJyVkIOCoruCoueCpgOCoqOCphycsXG4gICAgICAgIHkgOiAn4KiH4Kmx4KiVIOCouOCovuCosicsXG4gICAgICAgIHl5IDogJyVkIOCouOCovuCosidcbiAgICB9LFxuICAgIHByZXBhcnNlOiBmdW5jdGlvbiAoc3RyaW5nKSB7XG4gICAgICAgIHJldHVybiBzdHJpbmcucmVwbGFjZSgvW+Cpp+CpqOCpqeCpquCpq+CprOCpreCpruCpr+Cppl0vZywgZnVuY3Rpb24gKG1hdGNoKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVtYmVyTWFwJDExW21hdGNoXTtcbiAgICAgICAgfSk7XG4gICAgfSxcbiAgICBwb3N0Zm9ybWF0OiBmdW5jdGlvbiAoc3RyaW5nKSB7XG4gICAgICAgIHJldHVybiBzdHJpbmcucmVwbGFjZSgvXFxkL2csIGZ1bmN0aW9uIChtYXRjaCkge1xuICAgICAgICAgICAgcmV0dXJuIHN5bWJvbE1hcCQxMlttYXRjaF07XG4gICAgICAgIH0pO1xuICAgIH0sXG4gICAgLy8gUHVuamFiaSBub3RhdGlvbiBmb3IgbWVyaWRpZW1zIGFyZSBxdWl0ZSBmdXp6eSBpbiBwcmFjdGljZS4gV2hpbGUgdGhlcmUgZXhpc3RzXG4gICAgLy8gYSByaWdpZCBub3Rpb24gb2YgYSAnUGFoYXInIGl0IGlzIG5vdCB1c2VkIGFzIHJpZ2lkbHkgaW4gbW9kZXJuIFB1bmphYmkuXG4gICAgbWVyaWRpZW1QYXJzZTogL+CosOCovuCopHzgqLjgqLXgqYfgqLB84Kim4KmB4Kiq4Ki54Ki/4KiwfOCouOCovOCovuCori8sXG4gICAgbWVyaWRpZW1Ib3VyIDogZnVuY3Rpb24gKGhvdXIsIG1lcmlkaWVtKSB7XG4gICAgICAgIGlmIChob3VyID09PSAxMikge1xuICAgICAgICAgICAgaG91ciA9IDA7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG1lcmlkaWVtID09PSAn4Kiw4Ki+4KikJykge1xuICAgICAgICAgICAgcmV0dXJuIGhvdXIgPCA0ID8gaG91ciA6IGhvdXIgKyAxMjtcbiAgICAgICAgfSBlbHNlIGlmIChtZXJpZGllbSA9PT0gJ+CouOCoteCph+CosCcpIHtcbiAgICAgICAgICAgIHJldHVybiBob3VyO1xuICAgICAgICB9IGVsc2UgaWYgKG1lcmlkaWVtID09PSAn4Kim4KmB4Kiq4Ki54Ki/4KiwJykge1xuICAgICAgICAgICAgcmV0dXJuIGhvdXIgPj0gMTAgPyBob3VyIDogaG91ciArIDEyO1xuICAgICAgICB9IGVsc2UgaWYgKG1lcmlkaWVtID09PSAn4Ki44Ki84Ki+4KiuJykge1xuICAgICAgICAgICAgcmV0dXJuIGhvdXIgKyAxMjtcbiAgICAgICAgfVxuICAgIH0sXG4gICAgbWVyaWRpZW0gOiBmdW5jdGlvbiAoaG91ciwgbWludXRlLCBpc0xvd2VyKSB7XG4gICAgICAgIGlmIChob3VyIDwgNCkge1xuICAgICAgICAgICAgcmV0dXJuICfgqLDgqL7gqKQnO1xuICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAxMCkge1xuICAgICAgICAgICAgcmV0dXJuICfgqLjgqLXgqYfgqLAnO1xuICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAxNykge1xuICAgICAgICAgICAgcmV0dXJuICfgqKbgqYHgqKrgqLngqL/gqLAnO1xuICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAyMCkge1xuICAgICAgICAgICAgcmV0dXJuICfgqLjgqLzgqL7gqK4nO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuICfgqLDgqL7gqKQnO1xuICAgICAgICB9XG4gICAgfSxcbiAgICB3ZWVrIDoge1xuICAgICAgICBkb3cgOiAwLCAvLyBTdW5kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogNiAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gMXN0IGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH1cbn0pO1xuXG4vLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogUG9saXNoIFtwbF1cbi8vISBhdXRob3IgOiBSYWZhbCBIaXJzeiA6IGh0dHBzOi8vZ2l0aHViLmNvbS9ldm9MXG5cbnZhciBtb250aHNOb21pbmF0aXZlID0gJ3N0eWN6ZcWEX2x1dHlfbWFyemVjX2t3aWVjaWXFhF9tYWpfY3plcndpZWNfbGlwaWVjX3NpZXJwaWXFhF93cnplc2llxYRfcGHFumR6aWVybmlrX2xpc3RvcGFkX2dydWR6aWXFhCcuc3BsaXQoJ18nKTtcbnZhciBtb250aHNTdWJqZWN0aXZlID0gJ3N0eWN6bmlhX2x1dGVnb19tYXJjYV9rd2lldG5pYV9tYWphX2N6ZXJ3Y2FfbGlwY2Ffc2llcnBuaWFfd3J6ZcWbbmlhX3Bhxbpkemllcm5pa2FfbGlzdG9wYWRhX2dydWRuaWEnLnNwbGl0KCdfJyk7XG5mdW5jdGlvbiBwbHVyYWwkMyhuKSB7XG4gICAgcmV0dXJuIChuICUgMTAgPCA1KSAmJiAobiAlIDEwID4gMSkgJiYgKCh+fihuIC8gMTApICUgMTApICE9PSAxKTtcbn1cbmZ1bmN0aW9uIHRyYW5zbGF0ZSQ3KG51bWJlciwgd2l0aG91dFN1ZmZpeCwga2V5KSB7XG4gICAgdmFyIHJlc3VsdCA9IG51bWJlciArICcgJztcbiAgICBzd2l0Y2ggKGtleSkge1xuICAgICAgICBjYXNlICdzcyc6XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0ICsgKHBsdXJhbCQzKG51bWJlcikgPyAnc2VrdW5keScgOiAnc2VrdW5kJyk7XG4gICAgICAgIGNhc2UgJ20nOlxuICAgICAgICAgICAgcmV0dXJuIHdpdGhvdXRTdWZmaXggPyAnbWludXRhJyA6ICdtaW51dMSZJztcbiAgICAgICAgY2FzZSAnbW0nOlxuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCArIChwbHVyYWwkMyhudW1iZXIpID8gJ21pbnV0eScgOiAnbWludXQnKTtcbiAgICAgICAgY2FzZSAnaCc6XG4gICAgICAgICAgICByZXR1cm4gd2l0aG91dFN1ZmZpeCAgPyAnZ29kemluYScgIDogJ2dvZHppbsSZJztcbiAgICAgICAgY2FzZSAnaGgnOlxuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCArIChwbHVyYWwkMyhudW1iZXIpID8gJ2dvZHppbnknIDogJ2dvZHppbicpO1xuICAgICAgICBjYXNlICdNTSc6XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0ICsgKHBsdXJhbCQzKG51bWJlcikgPyAnbWllc2nEhWNlJyA6ICdtaWVzacSZY3knKTtcbiAgICAgICAgY2FzZSAneXknOlxuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCArIChwbHVyYWwkMyhudW1iZXIpID8gJ2xhdGEnIDogJ2xhdCcpO1xuICAgIH1cbn1cblxuaG9va3MuZGVmaW5lTG9jYWxlKCdwbCcsIHtcbiAgICBtb250aHMgOiBmdW5jdGlvbiAobW9tZW50VG9Gb3JtYXQsIGZvcm1hdCkge1xuICAgICAgICBpZiAoIW1vbWVudFRvRm9ybWF0KSB7XG4gICAgICAgICAgICByZXR1cm4gbW9udGhzTm9taW5hdGl2ZTtcbiAgICAgICAgfSBlbHNlIGlmIChmb3JtYXQgPT09ICcnKSB7XG4gICAgICAgICAgICAvLyBIYWNrOiBpZiBmb3JtYXQgZW1wdHkgd2Uga25vdyB0aGlzIGlzIHVzZWQgdG8gZ2VuZXJhdGVcbiAgICAgICAgICAgIC8vIFJlZ0V4cCBieSBtb21lbnQuIEdpdmUgdGhlbiBiYWNrIGJvdGggdmFsaWQgZm9ybXMgb2YgbW9udGhzXG4gICAgICAgICAgICAvLyBpbiBSZWdFeHAgcmVhZHkgZm9ybWF0LlxuICAgICAgICAgICAgcmV0dXJuICcoJyArIG1vbnRoc1N1YmplY3RpdmVbbW9tZW50VG9Gb3JtYXQubW9udGgoKV0gKyAnfCcgKyBtb250aHNOb21pbmF0aXZlW21vbWVudFRvRm9ybWF0Lm1vbnRoKCldICsgJyknO1xuICAgICAgICB9IGVsc2UgaWYgKC9EIE1NTU0vLnRlc3QoZm9ybWF0KSkge1xuICAgICAgICAgICAgcmV0dXJuIG1vbnRoc1N1YmplY3RpdmVbbW9tZW50VG9Gb3JtYXQubW9udGgoKV07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gbW9udGhzTm9taW5hdGl2ZVttb21lbnRUb0Zvcm1hdC5tb250aCgpXTtcbiAgICAgICAgfVxuICAgIH0sXG4gICAgbW9udGhzU2hvcnQgOiAnc3R5X2x1dF9tYXJfa3dpX21hal9jemVfbGlwX3NpZV93cnpfcGHFul9saXNfZ3J1Jy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzIDogJ25pZWR6aWVsYV9wb25pZWR6aWHFgmVrX3d0b3Jla1/Fm3JvZGFfY3p3YXJ0ZWtfcGnEhXRla19zb2JvdGEnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydCA6ICduZHpfcG9uX3d0X8Wbcl9jendfcHRfc29iJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzTWluIDogJ05kX1BuX1d0X8Wacl9Del9QdF9Tbycuc3BsaXQoJ18nKSxcbiAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgTFQgOiAnSEg6bW0nLFxuICAgICAgICBMVFMgOiAnSEg6bW06c3MnLFxuICAgICAgICBMIDogJ0RELk1NLllZWVknLFxuICAgICAgICBMTCA6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgIExMTCA6ICdEIE1NTU0gWVlZWSBISDptbScsXG4gICAgICAgIExMTEwgOiAnZGRkZCwgRCBNTU1NIFlZWVkgSEg6bW0nXG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheTogJ1tEemnFmyBvXSBMVCcsXG4gICAgICAgIG5leHREYXk6ICdbSnV0cm8gb10gTFQnLFxuICAgICAgICBuZXh0V2VlazogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgc3dpdGNoICh0aGlzLmRheSgpKSB7XG4gICAgICAgICAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1tXIG5pZWR6aWVsxJkgb10gTFQnO1xuXG4gICAgICAgICAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1tXZSB3dG9yZWsgb10gTFQnO1xuXG4gICAgICAgICAgICAgICAgY2FzZSAzOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1tXIMWbcm9kxJkgb10gTFQnO1xuXG4gICAgICAgICAgICAgICAgY2FzZSA2OlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1tXIHNvYm90xJkgb10gTFQnO1xuXG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbV10gZGRkZCBbb10gTFQnO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBsYXN0RGF5OiAnW1djem9yYWogb10gTFQnLFxuICAgICAgICBsYXN0V2VlazogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgc3dpdGNoICh0aGlzLmRheSgpKSB7XG4gICAgICAgICAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1tXIHplc3rFgsSFIG5pZWR6aWVsxJkgb10gTFQnO1xuICAgICAgICAgICAgICAgIGNhc2UgMzpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbVyB6ZXN6xYLEhSDFm3JvZMSZIG9dIExUJztcbiAgICAgICAgICAgICAgICBjYXNlIDY6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnW1cgemVzesWCxIUgc29ib3TEmSBvXSBMVCc7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbVyB6ZXN6xYJ5XSBkZGRkIFtvXSBMVCc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIHNhbWVFbHNlOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJ3phICVzJyxcbiAgICAgICAgcGFzdCA6ICclcyB0ZW11JyxcbiAgICAgICAgcyA6ICdraWxrYSBzZWt1bmQnLFxuICAgICAgICBzcyA6IHRyYW5zbGF0ZSQ3LFxuICAgICAgICBtIDogdHJhbnNsYXRlJDcsXG4gICAgICAgIG1tIDogdHJhbnNsYXRlJDcsXG4gICAgICAgIGggOiB0cmFuc2xhdGUkNyxcbiAgICAgICAgaGggOiB0cmFuc2xhdGUkNyxcbiAgICAgICAgZCA6ICcxIGR6aWXFhCcsXG4gICAgICAgIGRkIDogJyVkIGRuaScsXG4gICAgICAgIE0gOiAnbWllc2nEhWMnLFxuICAgICAgICBNTSA6IHRyYW5zbGF0ZSQ3LFxuICAgICAgICB5IDogJ3JvaycsXG4gICAgICAgIHl5IDogdHJhbnNsYXRlJDdcbiAgICB9LFxuICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfVxcLi8sXG4gICAgb3JkaW5hbCA6ICclZC4nLFxuICAgIHdlZWsgOiB7XG4gICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICBkb3kgOiA0ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgfVxufSk7XG5cbi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBQb3J0dWd1ZXNlIChCcmF6aWwpIFtwdC1icl1cbi8vISBhdXRob3IgOiBDYWlvIFJpYmVpcm8gUGVyZWlyYSA6IGh0dHBzOi8vZ2l0aHViLmNvbS9jYWlvLXJpYmVpcm8tcGVyZWlyYVxuXG5ob29rcy5kZWZpbmVMb2NhbGUoJ3B0LWJyJywge1xuICAgIG1vbnRocyA6ICdqYW5laXJvX2ZldmVyZWlyb19tYXLDp29fYWJyaWxfbWFpb19qdW5ob19qdWxob19hZ29zdG9fc2V0ZW1icm9fb3V0dWJyb19ub3ZlbWJyb19kZXplbWJybycuc3BsaXQoJ18nKSxcbiAgICBtb250aHNTaG9ydCA6ICdqYW5fZmV2X21hcl9hYnJfbWFpX2p1bl9qdWxfYWdvX3NldF9vdXRfbm92X2Rleicuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5cyA6ICdEb21pbmdvX1NlZ3VuZGEtZmVpcmFfVGVyw6dhLWZlaXJhX1F1YXJ0YS1mZWlyYV9RdWludGEtZmVpcmFfU2V4dGEtZmVpcmFfU8OhYmFkbycuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0IDogJ0RvbV9TZWdfVGVyX1F1YV9RdWlfU2V4X1PDoWInLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW4gOiAnRG9fMsKqXzPCql80wqpfNcKqXzbCql9Tw6EnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNQYXJzZUV4YWN0IDogdHJ1ZSxcbiAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgTFQgOiAnSEg6bW0nLFxuICAgICAgICBMVFMgOiAnSEg6bW06c3MnLFxuICAgICAgICBMIDogJ0REL01NL1lZWVknLFxuICAgICAgICBMTCA6ICdEIFtkZV0gTU1NTSBbZGVdIFlZWVknLFxuICAgICAgICBMTEwgOiAnRCBbZGVdIE1NTU0gW2RlXSBZWVlZIFvDoHNdIEhIOm1tJyxcbiAgICAgICAgTExMTCA6ICdkZGRkLCBEIFtkZV0gTU1NTSBbZGVdIFlZWVkgW8Ogc10gSEg6bW0nXG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheTogJ1tIb2plIMOgc10gTFQnLFxuICAgICAgICBuZXh0RGF5OiAnW0FtYW5ow6Mgw6BzXSBMVCcsXG4gICAgICAgIG5leHRXZWVrOiAnZGRkZCBbw6BzXSBMVCcsXG4gICAgICAgIGxhc3REYXk6ICdbT250ZW0gw6BzXSBMVCcsXG4gICAgICAgIGxhc3RXZWVrOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gKHRoaXMuZGF5KCkgPT09IDAgfHwgdGhpcy5kYXkoKSA9PT0gNikgP1xuICAgICAgICAgICAgICAgICdbw5psdGltb10gZGRkZCBbw6BzXSBMVCcgOiAvLyBTYXR1cmRheSArIFN1bmRheVxuICAgICAgICAgICAgICAgICdbw5psdGltYV0gZGRkZCBbw6BzXSBMVCc7IC8vIE1vbmRheSAtIEZyaWRheVxuICAgICAgICB9LFxuICAgICAgICBzYW1lRWxzZTogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6ICdlbSAlcycsXG4gICAgICAgIHBhc3QgOiAnJXMgYXRyw6FzJyxcbiAgICAgICAgcyA6ICdwb3Vjb3Mgc2VndW5kb3MnLFxuICAgICAgICBzcyA6ICclZCBzZWd1bmRvcycsXG4gICAgICAgIG0gOiAndW0gbWludXRvJyxcbiAgICAgICAgbW0gOiAnJWQgbWludXRvcycsXG4gICAgICAgIGggOiAndW1hIGhvcmEnLFxuICAgICAgICBoaCA6ICclZCBob3JhcycsXG4gICAgICAgIGQgOiAndW0gZGlhJyxcbiAgICAgICAgZGQgOiAnJWQgZGlhcycsXG4gICAgICAgIE0gOiAndW0gbcOqcycsXG4gICAgICAgIE1NIDogJyVkIG1lc2VzJyxcbiAgICAgICAgeSA6ICd1bSBhbm8nLFxuICAgICAgICB5eSA6ICclZCBhbm9zJ1xuICAgIH0sXG4gICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9wrovLFxuICAgIG9yZGluYWwgOiAnJWTCuidcbn0pO1xuXG4vLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogUG9ydHVndWVzZSBbcHRdXG4vLyEgYXV0aG9yIDogSmVmZmVyc29uIDogaHR0cHM6Ly9naXRodWIuY29tL2phbGV4NzlcblxuaG9va3MuZGVmaW5lTG9jYWxlKCdwdCcsIHtcbiAgICBtb250aHMgOiAnamFuZWlyb19mZXZlcmVpcm9fbWFyw6dvX2FicmlsX21haW9fanVuaG9fanVsaG9fYWdvc3RvX3NldGVtYnJvX291dHVicm9fbm92ZW1icm9fZGV6ZW1icm8nLnNwbGl0KCdfJyksXG4gICAgbW9udGhzU2hvcnQgOiAnamFuX2Zldl9tYXJfYWJyX21haV9qdW5fanVsX2Fnb19zZXRfb3V0X25vdl9kZXonLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXMgOiAnRG9taW5nb19TZWd1bmRhLWZlaXJhX1RlcsOnYS1mZWlyYV9RdWFydGEtZmVpcmFfUXVpbnRhLWZlaXJhX1NleHRhLWZlaXJhX1PDoWJhZG8nLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydCA6ICdEb21fU2VnX1Rlcl9RdWFfUXVpX1NleF9Tw6FiJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzTWluIDogJ0RvXzLCql8zwqpfNMKqXzXCql82wqpfU8OhJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzUGFyc2VFeGFjdCA6IHRydWUsXG4gICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgIExUIDogJ0hIOm1tJyxcbiAgICAgICAgTFRTIDogJ0hIOm1tOnNzJyxcbiAgICAgICAgTCA6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgTEwgOiAnRCBbZGVdIE1NTU0gW2RlXSBZWVlZJyxcbiAgICAgICAgTExMIDogJ0QgW2RlXSBNTU1NIFtkZV0gWVlZWSBISDptbScsXG4gICAgICAgIExMTEwgOiAnZGRkZCwgRCBbZGVdIE1NTU0gW2RlXSBZWVlZIEhIOm1tJ1xuICAgIH0sXG4gICAgY2FsZW5kYXIgOiB7XG4gICAgICAgIHNhbWVEYXk6ICdbSG9qZSDDoHNdIExUJyxcbiAgICAgICAgbmV4dERheTogJ1tBbWFuaMOjIMOgc10gTFQnLFxuICAgICAgICBuZXh0V2VlazogJ2RkZGQgW8Ogc10gTFQnLFxuICAgICAgICBsYXN0RGF5OiAnW09udGVtIMOgc10gTFQnLFxuICAgICAgICBsYXN0V2VlazogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuICh0aGlzLmRheSgpID09PSAwIHx8IHRoaXMuZGF5KCkgPT09IDYpID9cbiAgICAgICAgICAgICAgICAnW8OabHRpbW9dIGRkZGQgW8Ogc10gTFQnIDogLy8gU2F0dXJkYXkgKyBTdW5kYXlcbiAgICAgICAgICAgICAgICAnW8OabHRpbWFdIGRkZGQgW8Ogc10gTFQnOyAvLyBNb25kYXkgLSBGcmlkYXlcbiAgICAgICAgfSxcbiAgICAgICAgc2FtZUVsc2U6ICdMJ1xuICAgIH0sXG4gICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICBmdXR1cmUgOiAnZW0gJXMnLFxuICAgICAgICBwYXN0IDogJ2jDoSAlcycsXG4gICAgICAgIHMgOiAnc2VndW5kb3MnLFxuICAgICAgICBzcyA6ICclZCBzZWd1bmRvcycsXG4gICAgICAgIG0gOiAndW0gbWludXRvJyxcbiAgICAgICAgbW0gOiAnJWQgbWludXRvcycsXG4gICAgICAgIGggOiAndW1hIGhvcmEnLFxuICAgICAgICBoaCA6ICclZCBob3JhcycsXG4gICAgICAgIGQgOiAndW0gZGlhJyxcbiAgICAgICAgZGQgOiAnJWQgZGlhcycsXG4gICAgICAgIE0gOiAndW0gbcOqcycsXG4gICAgICAgIE1NIDogJyVkIG1lc2VzJyxcbiAgICAgICAgeSA6ICd1bSBhbm8nLFxuICAgICAgICB5eSA6ICclZCBhbm9zJ1xuICAgIH0sXG4gICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9wrovLFxuICAgIG9yZGluYWwgOiAnJWTCuicsXG4gICAgd2VlayA6IHtcbiAgICAgICAgZG93IDogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgIGRveSA6IDQgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDR0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICB9XG59KTtcblxuLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSA6IFJvbWFuaWFuIFtyb11cbi8vISBhdXRob3IgOiBWbGFkIEd1cmRpZ2EgOiBodHRwczovL2dpdGh1Yi5jb20vZ3VyZGlnYVxuLy8hIGF1dGhvciA6IFZhbGVudGluIEFnYWNoaSA6IGh0dHBzOi8vZ2l0aHViLmNvbS9hdmFseVxuXG5mdW5jdGlvbiByZWxhdGl2ZVRpbWVXaXRoUGx1cmFsJDIobnVtYmVyLCB3aXRob3V0U3VmZml4LCBrZXkpIHtcbiAgICB2YXIgZm9ybWF0ID0ge1xuICAgICAgICAgICAgJ3NzJzogJ3NlY3VuZGUnLFxuICAgICAgICAgICAgJ21tJzogJ21pbnV0ZScsXG4gICAgICAgICAgICAnaGgnOiAnb3JlJyxcbiAgICAgICAgICAgICdkZCc6ICd6aWxlJyxcbiAgICAgICAgICAgICdNTSc6ICdsdW5pJyxcbiAgICAgICAgICAgICd5eSc6ICdhbmknXG4gICAgICAgIH0sXG4gICAgICAgIHNlcGFyYXRvciA9ICcgJztcbiAgICBpZiAobnVtYmVyICUgMTAwID49IDIwIHx8IChudW1iZXIgPj0gMTAwICYmIG51bWJlciAlIDEwMCA9PT0gMCkpIHtcbiAgICAgICAgc2VwYXJhdG9yID0gJyBkZSAnO1xuICAgIH1cbiAgICByZXR1cm4gbnVtYmVyICsgc2VwYXJhdG9yICsgZm9ybWF0W2tleV07XG59XG5cbmhvb2tzLmRlZmluZUxvY2FsZSgncm8nLCB7XG4gICAgbW9udGhzIDogJ2lhbnVhcmllX2ZlYnJ1YXJpZV9tYXJ0aWVfYXByaWxpZV9tYWlfaXVuaWVfaXVsaWVfYXVndXN0X3NlcHRlbWJyaWVfb2N0b21icmllX25vaWVtYnJpZV9kZWNlbWJyaWUnLnNwbGl0KCdfJyksXG4gICAgbW9udGhzU2hvcnQgOiAnaWFuLl9mZWJyLl9tYXJ0Ll9hcHIuX21haV9pdW4uX2l1bC5fYXVnLl9zZXB0Ll9vY3QuX25vdi5fZGVjLicuc3BsaXQoJ18nKSxcbiAgICBtb250aHNQYXJzZUV4YWN0OiB0cnVlLFxuICAgIHdlZWtkYXlzIDogJ2R1bWluaWPEg19sdW5pX21hcsibaV9taWVyY3VyaV9qb2lfdmluZXJpX3PDom1ixIN0xIMnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydCA6ICdEdW1fTHVuX01hcl9NaWVfSm9pX1Zpbl9Tw6JtJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzTWluIDogJ0R1X0x1X01hX01pX0pvX1ZpX1PDoicuc3BsaXQoJ18nKSxcbiAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgTFQgOiAnSDptbScsXG4gICAgICAgIExUUyA6ICdIOm1tOnNzJyxcbiAgICAgICAgTCA6ICdERC5NTS5ZWVlZJyxcbiAgICAgICAgTEwgOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICBMTEwgOiAnRCBNTU1NIFlZWVkgSDptbScsXG4gICAgICAgIExMTEwgOiAnZGRkZCwgRCBNTU1NIFlZWVkgSDptbSdcbiAgICB9LFxuICAgIGNhbGVuZGFyIDoge1xuICAgICAgICBzYW1lRGF5OiAnW2F6aSBsYV0gTFQnLFxuICAgICAgICBuZXh0RGF5OiAnW23DomluZSBsYV0gTFQnLFxuICAgICAgICBuZXh0V2VlazogJ2RkZGQgW2xhXSBMVCcsXG4gICAgICAgIGxhc3REYXk6ICdbaWVyaSBsYV0gTFQnLFxuICAgICAgICBsYXN0V2VlazogJ1tmb3N0YV0gZGRkZCBbbGFdIExUJyxcbiAgICAgICAgc2FtZUVsc2U6ICdMJ1xuICAgIH0sXG4gICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICBmdXR1cmUgOiAncGVzdGUgJXMnLFxuICAgICAgICBwYXN0IDogJyVzIMOubiB1cm3EgycsXG4gICAgICAgIHMgOiAnY8OidGV2YSBzZWN1bmRlJyxcbiAgICAgICAgc3MgOiByZWxhdGl2ZVRpbWVXaXRoUGx1cmFsJDIsXG4gICAgICAgIG0gOiAndW4gbWludXQnLFxuICAgICAgICBtbSA6IHJlbGF0aXZlVGltZVdpdGhQbHVyYWwkMixcbiAgICAgICAgaCA6ICdvIG9yxIMnLFxuICAgICAgICBoaCA6IHJlbGF0aXZlVGltZVdpdGhQbHVyYWwkMixcbiAgICAgICAgZCA6ICdvIHppJyxcbiAgICAgICAgZGQgOiByZWxhdGl2ZVRpbWVXaXRoUGx1cmFsJDIsXG4gICAgICAgIE0gOiAnbyBsdW7EgycsXG4gICAgICAgIE1NIDogcmVsYXRpdmVUaW1lV2l0aFBsdXJhbCQyLFxuICAgICAgICB5IDogJ3VuIGFuJyxcbiAgICAgICAgeXkgOiByZWxhdGl2ZVRpbWVXaXRoUGx1cmFsJDJcbiAgICB9LFxuICAgIHdlZWsgOiB7XG4gICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICBkb3kgOiA3ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiAxc3QgaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgfVxufSk7XG5cbi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBSdXNzaWFuIFtydV1cbi8vISBhdXRob3IgOiBWaWt0b3JtaW5hdG9yIDogaHR0cHM6Ly9naXRodWIuY29tL1Zpa3Rvcm1pbmF0b3Jcbi8vISBBdXRob3IgOiBNZW5lbGlvbiBFbGVuc8O6bGUgOiBodHRwczovL2dpdGh1Yi5jb20vT2lyZVxuLy8hIGF1dGhvciA6INCa0L7RgNC10L3QsdC10YDQsyDQnNCw0YDQuiA6IGh0dHBzOi8vZ2l0aHViLmNvbS9zb2NrZXRwYWlyXG5cbmZ1bmN0aW9uIHBsdXJhbCQ0KHdvcmQsIG51bSkge1xuICAgIHZhciBmb3JtcyA9IHdvcmQuc3BsaXQoJ18nKTtcbiAgICByZXR1cm4gbnVtICUgMTAgPT09IDEgJiYgbnVtICUgMTAwICE9PSAxMSA/IGZvcm1zWzBdIDogKG51bSAlIDEwID49IDIgJiYgbnVtICUgMTAgPD0gNCAmJiAobnVtICUgMTAwIDwgMTAgfHwgbnVtICUgMTAwID49IDIwKSA/IGZvcm1zWzFdIDogZm9ybXNbMl0pO1xufVxuZnVuY3Rpb24gcmVsYXRpdmVUaW1lV2l0aFBsdXJhbCQzKG51bWJlciwgd2l0aG91dFN1ZmZpeCwga2V5KSB7XG4gICAgdmFyIGZvcm1hdCA9IHtcbiAgICAgICAgJ3NzJzogd2l0aG91dFN1ZmZpeCA/ICfRgdC10LrRg9C90LTQsF/RgdC10LrRg9C90LTRi1/RgdC10LrRg9C90LQnIDogJ9GB0LXQutGD0L3QtNGDX9GB0LXQutGD0L3QtNGLX9GB0LXQutGD0L3QtCcsXG4gICAgICAgICdtbSc6IHdpdGhvdXRTdWZmaXggPyAn0LzQuNC90YPRgtCwX9C80LjQvdGD0YLRi1/QvNC40L3Rg9GCJyA6ICfQvNC40L3Rg9GC0YNf0LzQuNC90YPRgtGLX9C80LjQvdGD0YInLFxuICAgICAgICAnaGgnOiAn0YfQsNGBX9GH0LDRgdCwX9GH0LDRgdC+0LInLFxuICAgICAgICAnZGQnOiAn0LTQtdC90Yxf0LTQvdGPX9C00L3QtdC5JyxcbiAgICAgICAgJ01NJzogJ9C80LXRgdGP0YZf0LzQtdGB0Y/RhtCwX9C80LXRgdGP0YbQtdCyJyxcbiAgICAgICAgJ3l5JzogJ9Cz0L7QtF/Qs9C+0LTQsF/Qu9C10YInXG4gICAgfTtcbiAgICBpZiAoa2V5ID09PSAnbScpIHtcbiAgICAgICAgcmV0dXJuIHdpdGhvdXRTdWZmaXggPyAn0LzQuNC90YPRgtCwJyA6ICfQvNC40L3Rg9GC0YMnO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgcmV0dXJuIG51bWJlciArICcgJyArIHBsdXJhbCQ0KGZvcm1hdFtrZXldLCArbnVtYmVyKTtcbiAgICB9XG59XG52YXIgbW9udGhzUGFyc2UkNCA9IFsvXtGP0L3Qsi9pLCAvXtGE0LXQsi9pLCAvXtC80LDRgC9pLCAvXtCw0L/RgC9pLCAvXtC80LBb0LnRj10vaSwgL17QuNGO0L0vaSwgL17QuNGO0LsvaSwgL17QsNCy0LMvaSwgL17RgdC10L0vaSwgL17QvtC60YIvaSwgL17QvdC+0Y8vaSwgL17QtNC10LovaV07XG5cbi8vIGh0dHA6Ly9uZXcuZ3JhbW90YS5ydS9zcHJhdmthL3J1bGVzLzEzOS1wcm9wIDogwqcgMTAzXG4vLyDQodC+0LrRgNCw0YnQtdC90LjRjyDQvNC10YHRj9GG0LXQsjogaHR0cDovL25ldy5ncmFtb3RhLnJ1L3NwcmF2a2EvYnVyby9zZWFyY2gtYW5zd2VyP3M9MjQyNjM3XG4vLyBDTERSIGRhdGE6ICAgICAgICAgIGh0dHA6Ly93d3cudW5pY29kZS5vcmcvY2xkci9jaGFydHMvMjgvc3VtbWFyeS9ydS5odG1sIzE3NTNcbmhvb2tzLmRlZmluZUxvY2FsZSgncnUnLCB7XG4gICAgbW9udGhzIDoge1xuICAgICAgICBmb3JtYXQ6ICfRj9C90LLQsNGA0Y9f0YTQtdCy0YDQsNC70Y9f0LzQsNGA0YLQsF/QsNC/0YDQtdC70Y9f0LzQsNGPX9C40Y7QvdGPX9C40Y7Qu9GPX9Cw0LLQs9GD0YHRgtCwX9GB0LXQvdGC0Y/QsdGA0Y9f0L7QutGC0Y/QsdGA0Y9f0L3QvtGP0LHRgNGPX9C00LXQutCw0LHRgNGPJy5zcGxpdCgnXycpLFxuICAgICAgICBzdGFuZGFsb25lOiAn0Y/QvdCy0LDRgNGMX9GE0LXQstGA0LDQu9GMX9C80LDRgNGCX9Cw0L/RgNC10LvRjF/QvNCw0Llf0LjRjtC90Yxf0LjRjtC70Yxf0LDQstCz0YPRgdGCX9GB0LXQvdGC0Y/QsdGA0Yxf0L7QutGC0Y/QsdGA0Yxf0L3QvtGP0LHRgNGMX9C00LXQutCw0LHRgNGMJy5zcGxpdCgnXycpXG4gICAgfSxcbiAgICBtb250aHNTaG9ydCA6IHtcbiAgICAgICAgLy8g0L/QviBDTERSINC40LzQtdC90L3QviBcItC40Y7Quy5cIiDQuCBcItC40Y7QvS5cIiwg0L3QviDQutCw0LrQvtC5INGB0LzRi9GB0Lsg0LzQtdC90Y/RgtGMINCx0YPQutCy0YMg0L3QsCDRgtC+0YfQutGDID9cbiAgICAgICAgZm9ybWF0OiAn0Y/QvdCyLl/RhNC10LLRgC5f0LzQsNGALl/QsNC/0YAuX9C80LDRj1/QuNGO0L3Rj1/QuNGO0LvRj1/QsNCy0LMuX9GB0LXQvdGCLl/QvtC60YIuX9C90L7Rj9CxLl/QtNC10LouJy5zcGxpdCgnXycpLFxuICAgICAgICBzdGFuZGFsb25lOiAn0Y/QvdCyLl/RhNC10LLRgC5f0LzQsNGA0YJf0LDQv9GALl/QvNCw0Llf0LjRjtC90Yxf0LjRjtC70Yxf0LDQstCzLl/RgdC10L3Rgi5f0L7QutGCLl/QvdC+0Y/QsS5f0LTQtdC6Licuc3BsaXQoJ18nKVxuICAgIH0sXG4gICAgd2Vla2RheXMgOiB7XG4gICAgICAgIHN0YW5kYWxvbmU6ICfQstC+0YHQutGA0LXRgdC10L3RjNC1X9C/0L7QvdC10LTQtdC70YzQvdC40Lpf0LLRgtC+0YDQvdC40Lpf0YHRgNC10LTQsF/Rh9C10YLQstC10YDQs1/Qv9GP0YLQvdC40YbQsF/RgdGD0LHQsdC+0YLQsCcuc3BsaXQoJ18nKSxcbiAgICAgICAgZm9ybWF0OiAn0LLQvtGB0LrRgNC10YHQtdC90YzQtV/Qv9C+0L3QtdC00LXQu9GM0L3QuNC6X9Cy0YLQvtGA0L3QuNC6X9GB0YDQtdC00YNf0YfQtdGC0LLQtdGA0LNf0L/Rj9GC0L3QuNGG0YNf0YHRg9Cx0LHQvtGC0YMnLnNwbGl0KCdfJyksXG4gICAgICAgIGlzRm9ybWF0OiAvXFxbID9b0JLQsl0gPyg/OtC/0YDQvtGI0LvRg9GOfNGB0LvQtdC00YPRjtGJ0YPRjnzRjdGC0YMpPyA/XFxdID9kZGRkL1xuICAgIH0sXG4gICAgd2Vla2RheXNTaG9ydCA6ICfQstGBX9C/0L1f0LLRgl/RgdGAX9GH0YJf0L/Rgl/RgdCxJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzTWluIDogJ9Cy0YFf0L/QvV/QstGCX9GB0YBf0YfRgl/Qv9GCX9GB0LEnLnNwbGl0KCdfJyksXG4gICAgbW9udGhzUGFyc2UgOiBtb250aHNQYXJzZSQ0LFxuICAgIGxvbmdNb250aHNQYXJzZSA6IG1vbnRoc1BhcnNlJDQsXG4gICAgc2hvcnRNb250aHNQYXJzZSA6IG1vbnRoc1BhcnNlJDQsXG5cbiAgICAvLyDQv9C+0LvQvdGL0LUg0L3QsNC30LLQsNC90LjRjyDRgSDQv9Cw0LTQtdC20LDQvNC4LCDQv9C+INGC0YDQuCDQsdGD0LrQstGLLCDQtNC70Y8g0L3QtdC60L7RgtC+0YDRi9GFLCDQv9C+IDQg0LHRg9C60LLRiywg0YHQvtC60YDQsNGJ0LXQvdC40Y8g0YEg0YLQvtGH0LrQvtC5INC4INCx0LXQtyDRgtC+0YfQutC4XG4gICAgbW9udGhzUmVnZXg6IC9eKNGP0L3QstCw0YBb0YzRj1180Y/QvdCyXFwuP3zRhNC10LLRgNCw0Ltb0YzRj1180YTQtdCy0YA/XFwuP3zQvNCw0YDRgtCwP3zQvNCw0YBcXC4/fNCw0L/RgNC10Ltb0YzRj1180LDQv9GAXFwuP3zQvNCwW9C50Y9dfNC40Y7QvVvRjNGPXXzQuNGO0L1cXC4/fNC40Y7Qu1vRjNGPXXzQuNGO0LtcXC4/fNCw0LLQs9GD0YHRgtCwP3zQsNCy0LNcXC4/fNGB0LXQvdGC0Y/QsdGAW9GM0Y9dfNGB0LXQvdGCP1xcLj980L7QutGC0Y/QsdGAW9GM0Y9dfNC+0LrRglxcLj980L3QvtGP0LHRgFvRjNGPXXzQvdC+0Y/QsT9cXC4/fNC00LXQutCw0LHRgFvRjNGPXXzQtNC10LpcXC4/KS9pLFxuXG4gICAgLy8g0LrQvtC/0LjRjyDQv9GA0LXQtNGL0LTRg9GJ0LXQs9C+XG4gICAgbW9udGhzU2hvcnRSZWdleDogL14o0Y/QvdCy0LDRgFvRjNGPXXzRj9C90LJcXC4/fNGE0LXQstGA0LDQu1vRjNGPXXzRhNC10LLRgD9cXC4/fNC80LDRgNGC0LA/fNC80LDRgFxcLj980LDQv9GA0LXQu1vRjNGPXXzQsNC/0YBcXC4/fNC80LBb0LnRj1180LjRjtC9W9GM0Y9dfNC40Y7QvVxcLj980LjRjtC7W9GM0Y9dfNC40Y7Qu1xcLj980LDQstCz0YPRgdGC0LA/fNCw0LLQs1xcLj980YHQtdC90YLRj9Cx0YBb0YzRj1180YHQtdC90YI/XFwuP3zQvtC60YLRj9Cx0YBb0YzRj1180L7QutGCXFwuP3zQvdC+0Y/QsdGAW9GM0Y9dfNC90L7Rj9CxP1xcLj980LTQtdC60LDQsdGAW9GM0Y9dfNC00LXQulxcLj8pL2ksXG5cbiAgICAvLyDQv9C+0LvQvdGL0LUg0L3QsNC30LLQsNC90LjRjyDRgSDQv9Cw0LTQtdC20LDQvNC4XG4gICAgbW9udGhzU3RyaWN0UmVnZXg6IC9eKNGP0L3QstCw0YBb0Y/RjF180YTQtdCy0YDQsNC7W9GP0YxdfNC80LDRgNGC0LA/fNCw0L/RgNC10Ltb0Y/RjF180LzQsFvRj9C5XXzQuNGO0L1b0Y/RjF180LjRjtC7W9GP0YxdfNCw0LLQs9GD0YHRgtCwP3zRgdC10L3RgtGP0LHRgFvRj9GMXXzQvtC60YLRj9Cx0YBb0Y/RjF180L3QvtGP0LHRgFvRj9GMXXzQtNC10LrQsNCx0YBb0Y/RjF0pL2ksXG5cbiAgICAvLyDQktGL0YDQsNC20LXQvdC40LUsINC60L7RgtC+0YDQvtC1INGB0L7QvtGC0LLQtdGB0YLQstGD0LXRgiDRgtC+0LvRjNC60L4g0YHQvtC60YDQsNGJ0ZHQvdC90YvQvCDRhNC+0YDQvNCw0LxcbiAgICBtb250aHNTaG9ydFN0cmljdFJlZ2V4OiAvXijRj9C90LJcXC580YTQtdCy0YA/XFwufNC80LDRgFvRgi5dfNCw0L/RgFxcLnzQvNCwW9GP0LldfNC40Y7QvVvRjNGPLl180LjRjtC7W9GM0Y8uXXzQsNCy0LNcXC580YHQtdC90YI/XFwufNC+0LrRglxcLnzQvdC+0Y/QsT9cXC580LTQtdC6XFwuKS9pLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdIOm1tJyxcbiAgICAgICAgTFRTIDogJ0g6bW06c3MnLFxuICAgICAgICBMIDogJ0RELk1NLllZWVknLFxuICAgICAgICBMTCA6ICdEIE1NTU0gWVlZWSDQsy4nLFxuICAgICAgICBMTEwgOiAnRCBNTU1NIFlZWVkg0LMuLCBIOm1tJyxcbiAgICAgICAgTExMTCA6ICdkZGRkLCBEIE1NTU0gWVlZWSDQsy4sIEg6bW0nXG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheTogJ1vQodC10LPQvtC00L3RjyDQsl0gTFQnLFxuICAgICAgICBuZXh0RGF5OiAnW9CX0LDQstGC0YDQsCDQsl0gTFQnLFxuICAgICAgICBsYXN0RGF5OiAnW9CS0YfQtdGA0LAg0LJdIExUJyxcbiAgICAgICAgbmV4dFdlZWs6IGZ1bmN0aW9uIChub3cpIHtcbiAgICAgICAgICAgIGlmIChub3cud2VlaygpICE9PSB0aGlzLndlZWsoKSkge1xuICAgICAgICAgICAgICAgIHN3aXRjaCAodGhpcy5kYXkoKSkge1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1vQkiDRgdC70LXQtNGD0Y7RidC10LVdIGRkZGQgW9CyXSBMVCc7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgICAgICAgICBjYXNlIDQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1vQkiDRgdC70LXQtNGD0Y7RidC40LldIGRkZGQgW9CyXSBMVCc7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMzpcbiAgICAgICAgICAgICAgICAgICAgY2FzZSA1OlxuICAgICAgICAgICAgICAgICAgICBjYXNlIDY6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1vQkiDRgdC70LXQtNGD0Y7RidGD0Y5dIGRkZGQgW9CyXSBMVCc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5kYXkoKSA9PT0gMikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1vQktC+XSBkZGRkIFvQsl0gTFQnO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnW9CSXSBkZGRkIFvQsl0gTFQnO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgbGFzdFdlZWs6IGZ1bmN0aW9uIChub3cpIHtcbiAgICAgICAgICAgIGlmIChub3cud2VlaygpICE9PSB0aGlzLndlZWsoKSkge1xuICAgICAgICAgICAgICAgIHN3aXRjaCAodGhpcy5kYXkoKSkge1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1vQkiDQv9GA0L7RiNC70L7QtV0gZGRkZCBb0LJdIExUJztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgNDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnW9CSINC/0YDQvtGI0LvRi9C5XSBkZGRkIFvQsl0gTFQnO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgNTpcbiAgICAgICAgICAgICAgICAgICAgY2FzZSA2OlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdb0JIg0L/RgNC+0YjQu9GD0Y5dIGRkZGQgW9CyXSBMVCc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5kYXkoKSA9PT0gMikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1vQktC+XSBkZGRkIFvQsl0gTFQnO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnW9CSXSBkZGRkIFvQsl0gTFQnO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgc2FtZUVsc2U6ICdMJ1xuICAgIH0sXG4gICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICBmdXR1cmUgOiAn0YfQtdGA0LXQtyAlcycsXG4gICAgICAgIHBhc3QgOiAnJXMg0L3QsNC30LDQtCcsXG4gICAgICAgIHMgOiAn0L3QtdGB0LrQvtC70YzQutC+INGB0LXQutGD0L3QtCcsXG4gICAgICAgIHNzIDogcmVsYXRpdmVUaW1lV2l0aFBsdXJhbCQzLFxuICAgICAgICBtIDogcmVsYXRpdmVUaW1lV2l0aFBsdXJhbCQzLFxuICAgICAgICBtbSA6IHJlbGF0aXZlVGltZVdpdGhQbHVyYWwkMyxcbiAgICAgICAgaCA6ICfRh9Cw0YEnLFxuICAgICAgICBoaCA6IHJlbGF0aXZlVGltZVdpdGhQbHVyYWwkMyxcbiAgICAgICAgZCA6ICfQtNC10L3RjCcsXG4gICAgICAgIGRkIDogcmVsYXRpdmVUaW1lV2l0aFBsdXJhbCQzLFxuICAgICAgICBNIDogJ9C80LXRgdGP0YYnLFxuICAgICAgICBNTSA6IHJlbGF0aXZlVGltZVdpdGhQbHVyYWwkMyxcbiAgICAgICAgeSA6ICfQs9C+0LQnLFxuICAgICAgICB5eSA6IHJlbGF0aXZlVGltZVdpdGhQbHVyYWwkM1xuICAgIH0sXG4gICAgbWVyaWRpZW1QYXJzZTogL9C90L7Rh9C4fNGD0YLRgNCwfNC00L3Rj3zQstC10YfQtdGA0LAvaSxcbiAgICBpc1BNIDogZnVuY3Rpb24gKGlucHV0KSB7XG4gICAgICAgIHJldHVybiAvXijQtNC90Y980LLQtdGH0LXRgNCwKSQvLnRlc3QoaW5wdXQpO1xuICAgIH0sXG4gICAgbWVyaWRpZW0gOiBmdW5jdGlvbiAoaG91ciwgbWludXRlLCBpc0xvd2VyKSB7XG4gICAgICAgIGlmIChob3VyIDwgNCkge1xuICAgICAgICAgICAgcmV0dXJuICfQvdC+0YfQuCc7XG4gICAgICAgIH0gZWxzZSBpZiAoaG91ciA8IDEyKSB7XG4gICAgICAgICAgICByZXR1cm4gJ9GD0YLRgNCwJztcbiAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgMTcpIHtcbiAgICAgICAgICAgIHJldHVybiAn0LTQvdGPJztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiAn0LLQtdGH0LXRgNCwJztcbiAgICAgICAgfVxuICAgIH0sXG4gICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9LSjQuXzQs9C+fNGPKS8sXG4gICAgb3JkaW5hbDogZnVuY3Rpb24gKG51bWJlciwgcGVyaW9kKSB7XG4gICAgICAgIHN3aXRjaCAocGVyaW9kKSB7XG4gICAgICAgICAgICBjYXNlICdNJzpcbiAgICAgICAgICAgIGNhc2UgJ2QnOlxuICAgICAgICAgICAgY2FzZSAnREREJzpcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJy3QuSc7XG4gICAgICAgICAgICBjYXNlICdEJzpcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJy3Qs9C+JztcbiAgICAgICAgICAgIGNhc2UgJ3cnOlxuICAgICAgICAgICAgY2FzZSAnVyc6XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICct0Y8nO1xuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyO1xuICAgICAgICB9XG4gICAgfSxcbiAgICB3ZWVrIDoge1xuICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogNCAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH1cbn0pO1xuXG4vLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogU2luZGhpIFtzZF1cbi8vISBhdXRob3IgOiBOYXJhaW4gU2FnYXIgOiBodHRwczovL2dpdGh1Yi5jb20vbmFyYWluc2FnYXJcblxudmFyIG1vbnRocyQ2ID0gW1xuICAgICfYrNmG2YjYsdmKJyxcbiAgICAn2YHZitio2LHZiNix2YonLFxuICAgICfZhdin2LHahicsXG4gICAgJ9in2b7YsdmK2YQnLFxuICAgICfZhdim2YonLFxuICAgICfYrNmI2YYnLFxuICAgICfYrNmI2YTYp9ih2ZAnLFxuICAgICfYotqv2LPZvScsXG4gICAgJ9iz2YrZvtm92YXYqNixJyxcbiAgICAn2KLaqtm92YjYqNixJyxcbiAgICAn2YbZiNmF2KjYsScsXG4gICAgJ9qK2LPZhdio2LEnXG5dO1xudmFyIGRheXMkMSA9IFtcbiAgICAn2KLahtixJyxcbiAgICAn2LPZiNmF2LEnLFxuICAgICfYp9qx2KfYsdmIJyxcbiAgICAn2KfYsdio2LknLFxuICAgICfYrtmF2YrYsycsXG4gICAgJ9is2YXYuScsXG4gICAgJ9qH2Ybah9ixJ1xuXTtcblxuaG9va3MuZGVmaW5lTG9jYWxlKCdzZCcsIHtcbiAgICBtb250aHMgOiBtb250aHMkNixcbiAgICBtb250aHNTaG9ydCA6IG1vbnRocyQ2LFxuICAgIHdlZWtkYXlzIDogZGF5cyQxLFxuICAgIHdlZWtkYXlzU2hvcnQgOiBkYXlzJDEsXG4gICAgd2Vla2RheXNNaW4gOiBkYXlzJDEsXG4gICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgIExUIDogJ0hIOm1tJyxcbiAgICAgICAgTFRTIDogJ0hIOm1tOnNzJyxcbiAgICAgICAgTCA6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgTEwgOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICBMTEwgOiAnRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICBMTExMIDogJ2RkZGTYjCBEIE1NTU0gWVlZWSBISDptbSdcbiAgICB9LFxuICAgIG1lcmlkaWVtUGFyc2U6IC/Ytdio2K182LTYp9mFLyxcbiAgICBpc1BNIDogZnVuY3Rpb24gKGlucHV0KSB7XG4gICAgICAgIHJldHVybiAn2LTYp9mFJyA9PT0gaW5wdXQ7XG4gICAgfSxcbiAgICBtZXJpZGllbSA6IGZ1bmN0aW9uIChob3VyLCBtaW51dGUsIGlzTG93ZXIpIHtcbiAgICAgICAgaWYgKGhvdXIgPCAxMikge1xuICAgICAgICAgICAgcmV0dXJuICfYtdio2K0nO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiAn2LTYp9mFJztcbiAgICB9LFxuICAgIGNhbGVuZGFyIDoge1xuICAgICAgICBzYW1lRGF5IDogJ1vYp9qEXSBMVCcsXG4gICAgICAgIG5leHREYXkgOiAnW9iz2oDYp9q72YpdIExUJyxcbiAgICAgICAgbmV4dFdlZWsgOiAnZGRkZCBb2Kfas9mK2YYg2YfZgdiq2Yog2KrZil0gTFQnLFxuICAgICAgICBsYXN0RGF5IDogJ1vaqtin2YTZh9mHXSBMVCcsXG4gICAgICAgIGxhc3RXZWVrIDogJ1var9iy2LHZitmEINmH2YHYqtmKXSBkZGRkIFvYqtmKXSBMVCcsXG4gICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6ICclcyDZvtmI2KEnLFxuICAgICAgICBwYXN0IDogJyVzINin2rMnLFxuICAgICAgICBzIDogJ9qG2YbYryDYs9mK2qrZhtqKJyxcbiAgICAgICAgc3MgOiAnJWQg2LPZitqq2YbaiicsXG4gICAgICAgIG0gOiAn2YfaqiDZhdmG2b0nLFxuICAgICAgICBtbSA6ICclZCDZhdmG2b0nLFxuICAgICAgICBoIDogJ9mH2qog2qrZhNin2qonLFxuICAgICAgICBoaCA6ICclZCDaqtmE2KfaqicsXG4gICAgICAgIGQgOiAn2YfaqiDaj9mK2YbZh9mGJyxcbiAgICAgICAgZGQgOiAnJWQg2o/ZitmG2YfZhicsXG4gICAgICAgIE0gOiAn2YfaqiDZhdmH2YrZhtmIJyxcbiAgICAgICAgTU0gOiAnJWQg2YXZh9mK2YbYpycsXG4gICAgICAgIHkgOiAn2YfaqiDYs9in2YQnLFxuICAgICAgICB5eSA6ICclZCDYs9in2YQnXG4gICAgfSxcbiAgICBwcmVwYXJzZTogZnVuY3Rpb24gKHN0cmluZykge1xuICAgICAgICByZXR1cm4gc3RyaW5nLnJlcGxhY2UoL9iML2csICcsJyk7XG4gICAgfSxcbiAgICBwb3N0Zm9ybWF0OiBmdW5jdGlvbiAoc3RyaW5nKSB7XG4gICAgICAgIHJldHVybiBzdHJpbmcucmVwbGFjZSgvLC9nLCAn2IwnKTtcbiAgICB9LFxuICAgIHdlZWsgOiB7XG4gICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICBkb3kgOiA0ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgfVxufSk7XG5cbi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBOb3J0aGVybiBTYW1pIFtzZV1cbi8vISBhdXRob3JzIDogQsOlcmQgUm9sc3RhZCBIZW5yaWtzZW4gOiBodHRwczovL2dpdGh1Yi5jb20va2FyYW1lbGxcblxuXG5ob29rcy5kZWZpbmVMb2NhbGUoJ3NlJywge1xuICAgIG1vbnRocyA6ICdvxJHEkWFqYWdlbcOhbm51X2d1b3Z2YW3DoW5udV9uanVrxI1hbcOhbm51X2N1b8WLb23DoW5udV9taWVzc2Vtw6FubnVfZ2Vhc3NlbcOhbm51X3N1b2lkbmVtw6FubnVfYm9yZ2Vtw6FubnVfxI1ha8SNYW3DoW5udV9nb2xnZ290bcOhbm51X3Nrw6FibWFtw6FubnVfanVvdmxhbcOhbm51Jy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0IDogJ2/EkcSRal9ndW92X25qdWtfY3VvX21pZXNfZ2Vhc19zdW9pX2JvcmdfxI1ha8SNX2dvbGdfc2vDoWJfanVvdicuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5cyA6ICdzb3RuYWJlYWl2aV92dW9zc8OhcmdhX21hxYvFi2Viw6FyZ2FfZ2Fza2F2YWhra3VfZHVvcmFzdGF0X2JlYXJqYWRhdF9sw6F2dmFyZGF0Jy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzU2hvcnQgOiAnc290bl92dW9zX21hxYtfZ2Fza19kdW9yX2JlYXJfbMOhdicuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbiA6ICdzX3ZfbV9nX2RfYl9MJy5zcGxpdCgnXycpLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdISDptbScsXG4gICAgICAgIExUUyA6ICdISDptbTpzcycsXG4gICAgICAgIEwgOiAnREQuTU0uWVlZWScsXG4gICAgICAgIExMIDogJ01NTU0gRC4gW2IuXSBZWVlZJyxcbiAgICAgICAgTExMIDogJ01NTU0gRC4gW2IuXSBZWVlZIFt0aS5dIEhIOm1tJyxcbiAgICAgICAgTExMTCA6ICdkZGRkLCBNTU1NIEQuIFtiLl0gWVlZWSBbdGkuXSBISDptbSdcbiAgICB9LFxuICAgIGNhbGVuZGFyIDoge1xuICAgICAgICBzYW1lRGF5OiAnW290bmUgdGldIExUJyxcbiAgICAgICAgbmV4dERheTogJ1tpaHR0aW4gdGldIExUJyxcbiAgICAgICAgbmV4dFdlZWs6ICdkZGRkIFt0aV0gTFQnLFxuICAgICAgICBsYXN0RGF5OiAnW2lrdGUgdGldIExUJyxcbiAgICAgICAgbGFzdFdlZWs6ICdbb3ZkZGl0XSBkZGRkIFt0aV0gTFQnLFxuICAgICAgICBzYW1lRWxzZTogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6ICclcyBnZWHFvmVzJyxcbiAgICAgICAgcGFzdCA6ICdtYcWLaXQgJXMnLFxuICAgICAgICBzIDogJ21vYWRkZSBzZWt1bmRkYXQnLFxuICAgICAgICBzczogJyVkIHNla3VuZGRhdCcsXG4gICAgICAgIG0gOiAnb2t0YSBtaW51aHRhJyxcbiAgICAgICAgbW0gOiAnJWQgbWludWh0YXQnLFxuICAgICAgICBoIDogJ29rdGEgZGlpbW11JyxcbiAgICAgICAgaGggOiAnJWQgZGlpbW11dCcsXG4gICAgICAgIGQgOiAnb2t0YSBiZWFpdmknLFxuICAgICAgICBkZCA6ICclZCBiZWFpdnZpdCcsXG4gICAgICAgIE0gOiAnb2t0YSBtw6FubnUnLFxuICAgICAgICBNTSA6ICclZCBtw6FudXQnLFxuICAgICAgICB5IDogJ29rdGEgamFoa2knLFxuICAgICAgICB5eSA6ICclZCBqYWdpdCdcbiAgICB9LFxuICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfVxcLi8sXG4gICAgb3JkaW5hbCA6ICclZC4nLFxuICAgIHdlZWsgOiB7XG4gICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICBkb3kgOiA0ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgfVxufSk7XG5cbi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBTaW5oYWxlc2UgW3NpXVxuLy8hIGF1dGhvciA6IFNhbXBhdGggU2l0aW5hbWFsdXdhIDogaHR0cHM6Ly9naXRodWIuY29tL3NhbXBhdGhzcmlzXG5cbi8qanNoaW50IC1XMTAwKi9cbmhvb2tzLmRlZmluZUxvY2FsZSgnc2knLCB7XG4gICAgbW9udGhzIDogJ+C2ouC2seC3gOC3j+C2u+C3kl/gtrTgt5ngtrbgtrvgt4Dgt4/gtrvgt5Jf4La44LeP4La74LeK4Lat4LeUX+C2heC2tOC3iuKAjeC2u+C3muC2veC3il/gtrjgt5Dgtrrgt5Jf4Lai4LeW4Lax4LeSX+C2ouC3luC2veC3kl/gtoXgtpzgt53gt4Pgt4rgtq3gt5Rf4LeD4LeQ4La04LeK4Lat4LeQ4La44LeK4La24La74LeKX+C2lOC2muC3iuC2reC3neC2tuC2u+C3il/gtrHgt5zgt4Dgt5Dgtrjgt4rgtrbgtrvgt4pf4Lav4LeZ4LeD4LeQ4La44LeK4La24La74LeKJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0IDogJ+C2ouC2sV/gtrTgt5ngtrZf4La44LeP4La74LeKX+C2heC2tOC3il/gtrjgt5Dgtrrgt5Jf4Lai4LeW4Lax4LeSX+C2ouC3luC2veC3kl/gtoXgtpzgt51f4LeD4LeQ4La04LeKX+C2lOC2muC3il/gtrHgt5zgt4Dgt5Bf4Lav4LeZ4LeD4LeQJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzIDogJ+C2ieC2u+C3kuC2r+C3j1/gt4PgtrPgt5Tgtq/gt49f4LaF4Laf4LeE4La74LeU4LeA4LeP4Lav4LePX+C2tuC2r+C3j+C2r+C3j1/gtrbgt4rigI3gtrvgt4Tgt4Pgt4rgtrTgtq3gt5LgtrHgt4rgtq/gt49f4LeD4LeS4Laa4LeU4La74LeP4Lav4LePX+C3g+C3meC2seC3g+C3lOC2u+C3j+C2r+C3jycuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0IDogJ+C2ieC2u+C3kl/gt4PgtrPgt5Rf4LaF4LafX+C2tuC2r+C3j1/gtrbgt4rigI3gtrvgt4Rf4LeD4LeS4Laa4LeUX+C3g+C3meC2sScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbiA6ICfgtolf4LeDX+C2hV/gtrZf4La24LeK4oCN4La7X+C3g+C3kl/gt4Pgt5knLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNQYXJzZUV4YWN0IDogdHJ1ZSxcbiAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgTFQgOiAnYSBoOm1tJyxcbiAgICAgICAgTFRTIDogJ2EgaDptbTpzcycsXG4gICAgICAgIEwgOiAnWVlZWS9NTS9ERCcsXG4gICAgICAgIExMIDogJ1lZWVkgTU1NTSBEJyxcbiAgICAgICAgTExMIDogJ1lZWVkgTU1NTSBELCBhIGg6bW0nLFxuICAgICAgICBMTExMIDogJ1lZWVkgTU1NTSBEIFvgt4Dgt5DgtrHgt5JdIGRkZGQsIGEgaDptbTpzcydcbiAgICB9LFxuICAgIGNhbGVuZGFyIDoge1xuICAgICAgICBzYW1lRGF5IDogJ1vgtoXgtq9dIExUW+C2p10nLFxuICAgICAgICBuZXh0RGF5IDogJ1vgt4Tgt5ngtqddIExUW+C2p10nLFxuICAgICAgICBuZXh0V2VlayA6ICdkZGRkIExUW+C2p10nLFxuICAgICAgICBsYXN0RGF5IDogJ1vgtorgtrrgt5pdIExUW+C2p10nLFxuICAgICAgICBsYXN0V2VlayA6ICdb4La04LeD4LeU4Lac4LeS4La6XSBkZGRkIExUW+C2p10nLFxuICAgICAgICBzYW1lRWxzZSA6ICdMJ1xuICAgIH0sXG4gICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICBmdXR1cmUgOiAnJXPgtprgt5LgtrHgt4onLFxuICAgICAgICBwYXN0IDogJyVz4Laa4LanIOC2tOC3meC2uycsXG4gICAgICAgIHMgOiAn4Lat4Lat4LeK4La04La7IOC2muC3kuC3hOC3kuC2tOC2uicsXG4gICAgICAgIHNzIDogJ+C2reC2reC3iuC2tOC2uyAlZCcsXG4gICAgICAgIG0gOiAn4La44LeS4Lax4LeS4Lat4LeK4Lat4LeU4LeAJyxcbiAgICAgICAgbW0gOiAn4La44LeS4Lax4LeS4Lat4LeK4Lat4LeUICVkJyxcbiAgICAgICAgaCA6ICfgtrTgt5DgtronLFxuICAgICAgICBoaCA6ICfgtrTgt5DgtrogJWQnLFxuICAgICAgICBkIDogJ+C2r+C3kuC2seC2uicsXG4gICAgICAgIGRkIDogJ+C2r+C3kuC2sSAlZCcsXG4gICAgICAgIE0gOiAn4La44LeP4LeD4La6JyxcbiAgICAgICAgTU0gOiAn4La44LeP4LeDICVkJyxcbiAgICAgICAgeSA6ICfgt4Dgt4PgtrsnLFxuICAgICAgICB5eSA6ICfgt4Dgt4PgtrsgJWQnXG4gICAgfSxcbiAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn0g4LeA4LeQ4Lax4LeSLyxcbiAgICBvcmRpbmFsIDogZnVuY3Rpb24gKG51bWJlcikge1xuICAgICAgICByZXR1cm4gbnVtYmVyICsgJyDgt4Dgt5DgtrHgt5InO1xuICAgIH0sXG4gICAgbWVyaWRpZW1QYXJzZSA6IC/gtrTgt5ngtrsg4LeA4La74LeUfOC2tOC3g+C3iiDgt4Dgtrvgt5R84La04LeZLuC3gHzgtrQu4LeALi8sXG4gICAgaXNQTSA6IGZ1bmN0aW9uIChpbnB1dCkge1xuICAgICAgICByZXR1cm4gaW5wdXQgPT09ICfgtrQu4LeALicgfHwgaW5wdXQgPT09ICfgtrTgt4Pgt4og4LeA4La74LeUJztcbiAgICB9LFxuICAgIG1lcmlkaWVtIDogZnVuY3Rpb24gKGhvdXJzLCBtaW51dGVzLCBpc0xvd2VyKSB7XG4gICAgICAgIGlmIChob3VycyA+IDExKSB7XG4gICAgICAgICAgICByZXR1cm4gaXNMb3dlciA/ICfgtrQu4LeALicgOiAn4La04LeD4LeKIOC3gOC2u+C3lCc7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gaXNMb3dlciA/ICfgtrTgt5ku4LeALicgOiAn4La04LeZ4La7IOC3gOC2u+C3lCc7XG4gICAgICAgIH1cbiAgICB9XG59KTtcblxuLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSA6IFNsb3ZhayBbc2tdXG4vLyEgYXV0aG9yIDogTWFydGluIE1pbmthIDogaHR0cHM6Ly9naXRodWIuY29tL2syc1xuLy8hIGJhc2VkIG9uIHdvcmsgb2YgcGV0cmJlbGEgOiBodHRwczovL2dpdGh1Yi5jb20vcGV0cmJlbGFcblxudmFyIG1vbnRocyQ3ID0gJ2phbnXDoXJfZmVicnXDoXJfbWFyZWNfYXByw61sX23DoWpfasO6bl9qw7psX2F1Z3VzdF9zZXB0ZW1iZXJfb2t0w7NiZXJfbm92ZW1iZXJfZGVjZW1iZXInLnNwbGl0KCdfJyk7XG52YXIgbW9udGhzU2hvcnQkNSA9ICdqYW5fZmViX21hcl9hcHJfbcOhal9qw7puX2rDumxfYXVnX3NlcF9va3Rfbm92X2RlYycuc3BsaXQoJ18nKTtcbmZ1bmN0aW9uIHBsdXJhbCQ1KG4pIHtcbiAgICByZXR1cm4gKG4gPiAxKSAmJiAobiA8IDUpO1xufVxuZnVuY3Rpb24gdHJhbnNsYXRlJDgobnVtYmVyLCB3aXRob3V0U3VmZml4LCBrZXksIGlzRnV0dXJlKSB7XG4gICAgdmFyIHJlc3VsdCA9IG51bWJlciArICcgJztcbiAgICBzd2l0Y2ggKGtleSkge1xuICAgICAgICBjYXNlICdzJzogIC8vIGEgZmV3IHNlY29uZHMgLyBpbiBhIGZldyBzZWNvbmRzIC8gYSBmZXcgc2Vjb25kcyBhZ29cbiAgICAgICAgICAgIHJldHVybiAod2l0aG91dFN1ZmZpeCB8fCBpc0Z1dHVyZSkgPyAncMOhciBzZWvDum5kJyA6ICdww6FyIHNla3VuZGFtaSc7XG4gICAgICAgIGNhc2UgJ3NzJzogLy8gOSBzZWNvbmRzIC8gaW4gOSBzZWNvbmRzIC8gOSBzZWNvbmRzIGFnb1xuICAgICAgICAgICAgaWYgKHdpdGhvdXRTdWZmaXggfHwgaXNGdXR1cmUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0ICsgKHBsdXJhbCQ1KG51bWJlcikgPyAnc2VrdW5keScgOiAnc2Vrw7puZCcpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0ICsgJ3Nla3VuZGFtaSc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnbSc6ICAvLyBhIG1pbnV0ZSAvIGluIGEgbWludXRlIC8gYSBtaW51dGUgYWdvXG4gICAgICAgICAgICByZXR1cm4gd2l0aG91dFN1ZmZpeCA/ICdtaW7DunRhJyA6IChpc0Z1dHVyZSA/ICdtaW7DunR1JyA6ICdtaW7DunRvdScpO1xuICAgICAgICBjYXNlICdtbSc6IC8vIDkgbWludXRlcyAvIGluIDkgbWludXRlcyAvIDkgbWludXRlcyBhZ29cbiAgICAgICAgICAgIGlmICh3aXRob3V0U3VmZml4IHx8IGlzRnV0dXJlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCArIChwbHVyYWwkNShudW1iZXIpID8gJ21pbsO6dHknIDogJ21pbsO6dCcpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0ICsgJ21pbsO6dGFtaSc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnaCc6ICAvLyBhbiBob3VyIC8gaW4gYW4gaG91ciAvIGFuIGhvdXIgYWdvXG4gICAgICAgICAgICByZXR1cm4gd2l0aG91dFN1ZmZpeCA/ICdob2RpbmEnIDogKGlzRnV0dXJlID8gJ2hvZGludScgOiAnaG9kaW5vdScpO1xuICAgICAgICBjYXNlICdoaCc6IC8vIDkgaG91cnMgLyBpbiA5IGhvdXJzIC8gOSBob3VycyBhZ29cbiAgICAgICAgICAgIGlmICh3aXRob3V0U3VmZml4IHx8IGlzRnV0dXJlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCArIChwbHVyYWwkNShudW1iZXIpID8gJ2hvZGlueScgOiAnaG9kw61uJyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQgKyAnaG9kaW5hbWknO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ2QnOiAgLy8gYSBkYXkgLyBpbiBhIGRheSAvIGEgZGF5IGFnb1xuICAgICAgICAgICAgcmV0dXJuICh3aXRob3V0U3VmZml4IHx8IGlzRnV0dXJlKSA/ICdkZcWIJyA6ICdkxYhvbSc7XG4gICAgICAgIGNhc2UgJ2RkJzogLy8gOSBkYXlzIC8gaW4gOSBkYXlzIC8gOSBkYXlzIGFnb1xuICAgICAgICAgICAgaWYgKHdpdGhvdXRTdWZmaXggfHwgaXNGdXR1cmUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0ICsgKHBsdXJhbCQ1KG51bWJlcikgPyAnZG5pJyA6ICdkbsOtJyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQgKyAnZMWIYW1pJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICdNJzogIC8vIGEgbW9udGggLyBpbiBhIG1vbnRoIC8gYSBtb250aCBhZ29cbiAgICAgICAgICAgIHJldHVybiAod2l0aG91dFN1ZmZpeCB8fCBpc0Z1dHVyZSkgPyAnbWVzaWFjJyA6ICdtZXNpYWNvbSc7XG4gICAgICAgIGNhc2UgJ01NJzogLy8gOSBtb250aHMgLyBpbiA5IG1vbnRocyAvIDkgbW9udGhzIGFnb1xuICAgICAgICAgICAgaWYgKHdpdGhvdXRTdWZmaXggfHwgaXNGdXR1cmUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0ICsgKHBsdXJhbCQ1KG51bWJlcikgPyAnbWVzaWFjZScgOiAnbWVzaWFjb3YnKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCArICdtZXNpYWNtaSc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAneSc6ICAvLyBhIHllYXIgLyBpbiBhIHllYXIgLyBhIHllYXIgYWdvXG4gICAgICAgICAgICByZXR1cm4gKHdpdGhvdXRTdWZmaXggfHwgaXNGdXR1cmUpID8gJ3JvaycgOiAncm9rb20nO1xuICAgICAgICBjYXNlICd5eSc6IC8vIDkgeWVhcnMgLyBpbiA5IHllYXJzIC8gOSB5ZWFycyBhZ29cbiAgICAgICAgICAgIGlmICh3aXRob3V0U3VmZml4IHx8IGlzRnV0dXJlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCArIChwbHVyYWwkNShudW1iZXIpID8gJ3Jva3knIDogJ3Jva292Jyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQgKyAncm9rbWknO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnJlYWs7XG4gICAgfVxufVxuXG5ob29rcy5kZWZpbmVMb2NhbGUoJ3NrJywge1xuICAgIG1vbnRocyA6IG1vbnRocyQ3LFxuICAgIG1vbnRoc1Nob3J0IDogbW9udGhzU2hvcnQkNSxcbiAgICB3ZWVrZGF5cyA6ICduZWRlxL5hX3BvbmRlbG9rX3V0b3Jva19zdHJlZGFfxaF0dnJ0b2tfcGlhdG9rX3NvYm90YScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0IDogJ25lX3BvX3V0X3N0X8WhdF9waV9zbycuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbiA6ICduZV9wb191dF9zdF/FoXRfcGlfc28nLnNwbGl0KCdfJyksXG4gICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgIExUOiAnSDptbScsXG4gICAgICAgIExUUyA6ICdIOm1tOnNzJyxcbiAgICAgICAgTCA6ICdERC5NTS5ZWVlZJyxcbiAgICAgICAgTEwgOiAnRC4gTU1NTSBZWVlZJyxcbiAgICAgICAgTExMIDogJ0QuIE1NTU0gWVlZWSBIOm1tJyxcbiAgICAgICAgTExMTCA6ICdkZGRkIEQuIE1NTU0gWVlZWSBIOm1tJ1xuICAgIH0sXG4gICAgY2FsZW5kYXIgOiB7XG4gICAgICAgIHNhbWVEYXk6ICdbZG5lcyBvXSBMVCcsXG4gICAgICAgIG5leHREYXk6ICdbemFqdHJhIG9dIExUJyxcbiAgICAgICAgbmV4dFdlZWs6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHN3aXRjaCAodGhpcy5kYXkoKSkge1xuICAgICAgICAgICAgICAgIGNhc2UgMDpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbdiBuZWRlxL51IG9dIExUJztcbiAgICAgICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1t2XSBkZGRkIFtvXSBMVCc7XG4gICAgICAgICAgICAgICAgY2FzZSAzOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1t2IHN0cmVkdSBvXSBMVCc7XG4gICAgICAgICAgICAgICAgY2FzZSA0OlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1t2byDFoXR2cnRvayBvXSBMVCc7XG4gICAgICAgICAgICAgICAgY2FzZSA1OlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1t2IHBpYXRvayBvXSBMVCc7XG4gICAgICAgICAgICAgICAgY2FzZSA2OlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1t2IHNvYm90dSBvXSBMVCc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIGxhc3REYXk6ICdbdsSNZXJhIG9dIExUJyxcbiAgICAgICAgbGFzdFdlZWs6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHN3aXRjaCAodGhpcy5kYXkoKSkge1xuICAgICAgICAgICAgICAgIGNhc2UgMDpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbbWludWzDuiBuZWRlxL51IG9dIExUJztcbiAgICAgICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1ttaW51bMO9XSBkZGRkIFtvXSBMVCc7XG4gICAgICAgICAgICAgICAgY2FzZSAzOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1ttaW51bMO6IHN0cmVkdSBvXSBMVCc7XG4gICAgICAgICAgICAgICAgY2FzZSA0OlxuICAgICAgICAgICAgICAgIGNhc2UgNTpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbbWludWzDvV0gZGRkZCBbb10gTFQnO1xuICAgICAgICAgICAgICAgIGNhc2UgNjpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbbWludWzDuiBzb2JvdHUgb10gTFQnO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBzYW1lRWxzZTogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6ICd6YSAlcycsXG4gICAgICAgIHBhc3QgOiAncHJlZCAlcycsXG4gICAgICAgIHMgOiB0cmFuc2xhdGUkOCxcbiAgICAgICAgc3MgOiB0cmFuc2xhdGUkOCxcbiAgICAgICAgbSA6IHRyYW5zbGF0ZSQ4LFxuICAgICAgICBtbSA6IHRyYW5zbGF0ZSQ4LFxuICAgICAgICBoIDogdHJhbnNsYXRlJDgsXG4gICAgICAgIGhoIDogdHJhbnNsYXRlJDgsXG4gICAgICAgIGQgOiB0cmFuc2xhdGUkOCxcbiAgICAgICAgZGQgOiB0cmFuc2xhdGUkOCxcbiAgICAgICAgTSA6IHRyYW5zbGF0ZSQ4LFxuICAgICAgICBNTSA6IHRyYW5zbGF0ZSQ4LFxuICAgICAgICB5IDogdHJhbnNsYXRlJDgsXG4gICAgICAgIHl5IDogdHJhbnNsYXRlJDhcbiAgICB9LFxuICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfVxcLi8sXG4gICAgb3JkaW5hbCA6ICclZC4nLFxuICAgIHdlZWsgOiB7XG4gICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICBkb3kgOiA0ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgfVxufSk7XG5cbi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBTbG92ZW5pYW4gW3NsXVxuLy8hIGF1dGhvciA6IFJvYmVydCBTZWRvdsWhZWsgOiBodHRwczovL2dpdGh1Yi5jb20vc2Vkb3ZzZWtcblxuZnVuY3Rpb24gcHJvY2Vzc1JlbGF0aXZlVGltZSQ2KG51bWJlciwgd2l0aG91dFN1ZmZpeCwga2V5LCBpc0Z1dHVyZSkge1xuICAgIHZhciByZXN1bHQgPSBudW1iZXIgKyAnICc7XG4gICAgc3dpdGNoIChrZXkpIHtcbiAgICAgICAgY2FzZSAncyc6XG4gICAgICAgICAgICByZXR1cm4gd2l0aG91dFN1ZmZpeCB8fCBpc0Z1dHVyZSA/ICduZWthaiBzZWt1bmQnIDogJ25la2FqIHNla3VuZGFtaSc7XG4gICAgICAgIGNhc2UgJ3NzJzpcbiAgICAgICAgICAgIGlmIChudW1iZXIgPT09IDEpIHtcbiAgICAgICAgICAgICAgICByZXN1bHQgKz0gd2l0aG91dFN1ZmZpeCA/ICdzZWt1bmRvJyA6ICdzZWt1bmRpJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAobnVtYmVyID09PSAyKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ICs9IHdpdGhvdXRTdWZmaXggfHwgaXNGdXR1cmUgPyAnc2VrdW5kaScgOiAnc2VrdW5kYWgnO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChudW1iZXIgPCA1KSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ICs9IHdpdGhvdXRTdWZmaXggfHwgaXNGdXR1cmUgPyAnc2VrdW5kZScgOiAnc2VrdW5kYWgnO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXN1bHQgKz0gd2l0aG91dFN1ZmZpeCB8fCBpc0Z1dHVyZSA/ICdzZWt1bmQnIDogJ3Nla3VuZCc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICBjYXNlICdtJzpcbiAgICAgICAgICAgIHJldHVybiB3aXRob3V0U3VmZml4ID8gJ2VuYSBtaW51dGEnIDogJ2VubyBtaW51dG8nO1xuICAgICAgICBjYXNlICdtbSc6XG4gICAgICAgICAgICBpZiAobnVtYmVyID09PSAxKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ICs9IHdpdGhvdXRTdWZmaXggPyAnbWludXRhJyA6ICdtaW51dG8nO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChudW1iZXIgPT09IDIpIHtcbiAgICAgICAgICAgICAgICByZXN1bHQgKz0gd2l0aG91dFN1ZmZpeCB8fCBpc0Z1dHVyZSA/ICdtaW51dGknIDogJ21pbnV0YW1hJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAobnVtYmVyIDwgNSkge1xuICAgICAgICAgICAgICAgIHJlc3VsdCArPSB3aXRob3V0U3VmZml4IHx8IGlzRnV0dXJlID8gJ21pbnV0ZScgOiAnbWludXRhbWknO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXN1bHQgKz0gd2l0aG91dFN1ZmZpeCB8fCBpc0Z1dHVyZSA/ICdtaW51dCcgOiAnbWludXRhbWknO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgY2FzZSAnaCc6XG4gICAgICAgICAgICByZXR1cm4gd2l0aG91dFN1ZmZpeCA/ICdlbmEgdXJhJyA6ICdlbm8gdXJvJztcbiAgICAgICAgY2FzZSAnaGgnOlxuICAgICAgICAgICAgaWYgKG51bWJlciA9PT0gMSkge1xuICAgICAgICAgICAgICAgIHJlc3VsdCArPSB3aXRob3V0U3VmZml4ID8gJ3VyYScgOiAndXJvJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAobnVtYmVyID09PSAyKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ICs9IHdpdGhvdXRTdWZmaXggfHwgaXNGdXR1cmUgPyAndXJpJyA6ICd1cmFtYSc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKG51bWJlciA8IDUpIHtcbiAgICAgICAgICAgICAgICByZXN1bHQgKz0gd2l0aG91dFN1ZmZpeCB8fCBpc0Z1dHVyZSA/ICd1cmUnIDogJ3VyYW1pJztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ICs9IHdpdGhvdXRTdWZmaXggfHwgaXNGdXR1cmUgPyAndXInIDogJ3VyYW1pJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIGNhc2UgJ2QnOlxuICAgICAgICAgICAgcmV0dXJuIHdpdGhvdXRTdWZmaXggfHwgaXNGdXR1cmUgPyAnZW4gZGFuJyA6ICdlbmltIGRuZW0nO1xuICAgICAgICBjYXNlICdkZCc6XG4gICAgICAgICAgICBpZiAobnVtYmVyID09PSAxKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ICs9IHdpdGhvdXRTdWZmaXggfHwgaXNGdXR1cmUgPyAnZGFuJyA6ICdkbmVtJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAobnVtYmVyID09PSAyKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ICs9IHdpdGhvdXRTdWZmaXggfHwgaXNGdXR1cmUgPyAnZG5pJyA6ICdkbmV2b21hJztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ICs9IHdpdGhvdXRTdWZmaXggfHwgaXNGdXR1cmUgPyAnZG5pJyA6ICdkbmV2aSc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICBjYXNlICdNJzpcbiAgICAgICAgICAgIHJldHVybiB3aXRob3V0U3VmZml4IHx8IGlzRnV0dXJlID8gJ2VuIG1lc2VjJyA6ICdlbmltIG1lc2VjZW0nO1xuICAgICAgICBjYXNlICdNTSc6XG4gICAgICAgICAgICBpZiAobnVtYmVyID09PSAxKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ICs9IHdpdGhvdXRTdWZmaXggfHwgaXNGdXR1cmUgPyAnbWVzZWMnIDogJ21lc2VjZW0nO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChudW1iZXIgPT09IDIpIHtcbiAgICAgICAgICAgICAgICByZXN1bHQgKz0gd2l0aG91dFN1ZmZpeCB8fCBpc0Z1dHVyZSA/ICdtZXNlY2EnIDogJ21lc2VjZW1hJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAobnVtYmVyIDwgNSkge1xuICAgICAgICAgICAgICAgIHJlc3VsdCArPSB3aXRob3V0U3VmZml4IHx8IGlzRnV0dXJlID8gJ21lc2VjZScgOiAnbWVzZWNpJztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ICs9IHdpdGhvdXRTdWZmaXggfHwgaXNGdXR1cmUgPyAnbWVzZWNldicgOiAnbWVzZWNpJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIGNhc2UgJ3knOlxuICAgICAgICAgICAgcmV0dXJuIHdpdGhvdXRTdWZmaXggfHwgaXNGdXR1cmUgPyAnZW5vIGxldG8nIDogJ2VuaW0gbGV0b20nO1xuICAgICAgICBjYXNlICd5eSc6XG4gICAgICAgICAgICBpZiAobnVtYmVyID09PSAxKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ICs9IHdpdGhvdXRTdWZmaXggfHwgaXNGdXR1cmUgPyAnbGV0bycgOiAnbGV0b20nO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChudW1iZXIgPT09IDIpIHtcbiAgICAgICAgICAgICAgICByZXN1bHQgKz0gd2l0aG91dFN1ZmZpeCB8fCBpc0Z1dHVyZSA/ICdsZXRpJyA6ICdsZXRvbWEnO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChudW1iZXIgPCA1KSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ICs9IHdpdGhvdXRTdWZmaXggfHwgaXNGdXR1cmUgPyAnbGV0YScgOiAnbGV0aSc7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlc3VsdCArPSB3aXRob3V0U3VmZml4IHx8IGlzRnV0dXJlID8gJ2xldCcgOiAnbGV0aSc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cbn1cblxuaG9va3MuZGVmaW5lTG9jYWxlKCdzbCcsIHtcbiAgICBtb250aHMgOiAnamFudWFyX2ZlYnJ1YXJfbWFyZWNfYXByaWxfbWFqX2p1bmlqX2p1bGlqX2F2Z3VzdF9zZXB0ZW1iZXJfb2t0b2Jlcl9ub3ZlbWJlcl9kZWNlbWJlcicuc3BsaXQoJ18nKSxcbiAgICBtb250aHNTaG9ydCA6ICdqYW4uX2ZlYi5fbWFyLl9hcHIuX21hai5fanVuLl9qdWwuX2F2Zy5fc2VwLl9va3QuX25vdi5fZGVjLicuc3BsaXQoJ18nKSxcbiAgICBtb250aHNQYXJzZUV4YWN0OiB0cnVlLFxuICAgIHdlZWtkYXlzIDogJ25lZGVsamFfcG9uZWRlbGpla190b3Jla19zcmVkYV/EjWV0cnRla19wZXRla19zb2JvdGEnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydCA6ICduZWQuX3Bvbi5fdG9yLl9zcmUuX8SNZXQuX3BldC5fc29iLicuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbiA6ICduZV9wb190b19zcl/EjWVfcGVfc28nLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNQYXJzZUV4YWN0IDogdHJ1ZSxcbiAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgTFQgOiAnSDptbScsXG4gICAgICAgIExUUyA6ICdIOm1tOnNzJyxcbiAgICAgICAgTCA6ICdERC5NTS5ZWVlZJyxcbiAgICAgICAgTEwgOiAnRC4gTU1NTSBZWVlZJyxcbiAgICAgICAgTExMIDogJ0QuIE1NTU0gWVlZWSBIOm1tJyxcbiAgICAgICAgTExMTCA6ICdkZGRkLCBELiBNTU1NIFlZWVkgSDptbSdcbiAgICB9LFxuICAgIGNhbGVuZGFyIDoge1xuICAgICAgICBzYW1lRGF5ICA6ICdbZGFuZXMgb2JdIExUJyxcbiAgICAgICAgbmV4dERheSAgOiAnW2p1dHJpIG9iXSBMVCcsXG5cbiAgICAgICAgbmV4dFdlZWsgOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBzd2l0Y2ggKHRoaXMuZGF5KCkpIHtcbiAgICAgICAgICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnW3ZdIFtuZWRlbGpvXSBbb2JdIExUJztcbiAgICAgICAgICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnW3ZdIFtzcmVkb10gW29iXSBMVCc7XG4gICAgICAgICAgICAgICAgY2FzZSA2OlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1t2XSBbc29ib3RvXSBbb2JdIExUJztcbiAgICAgICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgICAgIGNhc2UgNDpcbiAgICAgICAgICAgICAgICBjYXNlIDU6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnW3ZdIGRkZGQgW29iXSBMVCc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIGxhc3REYXkgIDogJ1t2xI1lcmFqIG9iXSBMVCcsXG4gICAgICAgIGxhc3RXZWVrIDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgc3dpdGNoICh0aGlzLmRheSgpKSB7XG4gICAgICAgICAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1twcmVqxaFuam9dIFtuZWRlbGpvXSBbb2JdIExUJztcbiAgICAgICAgICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnW3ByZWrFoW5qb10gW3NyZWRvXSBbb2JdIExUJztcbiAgICAgICAgICAgICAgICBjYXNlIDY6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnW3ByZWrFoW5qb10gW3NvYm90b10gW29iXSBMVCc7XG4gICAgICAgICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgICAgIGNhc2UgMjpcbiAgICAgICAgICAgICAgICBjYXNlIDQ6XG4gICAgICAgICAgICAgICAgY2FzZSA1OlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1twcmVqxaFuamldIGRkZGQgW29iXSBMVCc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6ICfEjWV6ICVzJyxcbiAgICAgICAgcGFzdCAgIDogJ3ByZWQgJXMnLFxuICAgICAgICBzICAgICAgOiBwcm9jZXNzUmVsYXRpdmVUaW1lJDYsXG4gICAgICAgIHNzICAgICA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUkNixcbiAgICAgICAgbSAgICAgIDogcHJvY2Vzc1JlbGF0aXZlVGltZSQ2LFxuICAgICAgICBtbSAgICAgOiBwcm9jZXNzUmVsYXRpdmVUaW1lJDYsXG4gICAgICAgIGggICAgICA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUkNixcbiAgICAgICAgaGggICAgIDogcHJvY2Vzc1JlbGF0aXZlVGltZSQ2LFxuICAgICAgICBkICAgICAgOiBwcm9jZXNzUmVsYXRpdmVUaW1lJDYsXG4gICAgICAgIGRkICAgICA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUkNixcbiAgICAgICAgTSAgICAgIDogcHJvY2Vzc1JlbGF0aXZlVGltZSQ2LFxuICAgICAgICBNTSAgICAgOiBwcm9jZXNzUmVsYXRpdmVUaW1lJDYsXG4gICAgICAgIHkgICAgICA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUkNixcbiAgICAgICAgeXkgICAgIDogcHJvY2Vzc1JlbGF0aXZlVGltZSQ2XG4gICAgfSxcbiAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn1cXC4vLFxuICAgIG9yZGluYWwgOiAnJWQuJyxcbiAgICB3ZWVrIDoge1xuICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogNyAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gMXN0IGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH1cbn0pO1xuXG4vLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogQWxiYW5pYW4gW3NxXVxuLy8hIGF1dGhvciA6IEZsYWvDq3JpbSBJc21hbmkgOiBodHRwczovL2dpdGh1Yi5jb20vZmxha2VyaW1pXG4vLyEgYXV0aG9yIDogTWVuZWxpb24gRWxlbnPDumxlIDogaHR0cHM6Ly9naXRodWIuY29tL09pcmVcbi8vISBhdXRob3IgOiBPZXJkIEN1a2FsbGEgOiBodHRwczovL2dpdGh1Yi5jb20vb2VyZFxuXG5ob29rcy5kZWZpbmVMb2NhbGUoJ3NxJywge1xuICAgIG1vbnRocyA6ICdKYW5hcl9TaGt1cnRfTWFyc19QcmlsbF9NYWpfUWVyc2hvcl9Lb3JyaWtfR3VzaHRfU2h0YXRvcl9UZXRvcl9Ow6tudG9yX0RoamV0b3InLnNwbGl0KCdfJyksXG4gICAgbW9udGhzU2hvcnQgOiAnSmFuX1Noa19NYXJfUHJpX01hal9RZXJfS29yX0d1c19TaHRfVGV0X07Dq25fRGhqJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzIDogJ0UgRGllbF9FIEjDq27Dq19FIE1hcnTDq19FIE3Dq3JrdXLDq19FIEVuanRlX0UgUHJlbXRlX0UgU2h0dW7Dqycuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0IDogJ0RpZV9Iw6tuX01hcl9Nw6tyX0Vual9QcmVfU2h0Jy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzTWluIDogJ0RfSF9NYV9Nw6tfRV9QX1NoJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzUGFyc2VFeGFjdCA6IHRydWUsXG4gICAgbWVyaWRpZW1QYXJzZTogL1BEfE1ELyxcbiAgICBpc1BNOiBmdW5jdGlvbiAoaW5wdXQpIHtcbiAgICAgICAgcmV0dXJuIGlucHV0LmNoYXJBdCgwKSA9PT0gJ00nO1xuICAgIH0sXG4gICAgbWVyaWRpZW0gOiBmdW5jdGlvbiAoaG91cnMsIG1pbnV0ZXMsIGlzTG93ZXIpIHtcbiAgICAgICAgcmV0dXJuIGhvdXJzIDwgMTIgPyAnUEQnIDogJ01EJztcbiAgICB9LFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdISDptbScsXG4gICAgICAgIExUUyA6ICdISDptbTpzcycsXG4gICAgICAgIEwgOiAnREQvTU0vWVlZWScsXG4gICAgICAgIExMIDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgTExMIDogJ0QgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgTExMTCA6ICdkZGRkLCBEIE1NTU0gWVlZWSBISDptbSdcbiAgICB9LFxuICAgIGNhbGVuZGFyIDoge1xuICAgICAgICBzYW1lRGF5IDogJ1tTb3QgbsOrXSBMVCcsXG4gICAgICAgIG5leHREYXkgOiAnW05lc8OrciBuw6tdIExUJyxcbiAgICAgICAgbmV4dFdlZWsgOiAnZGRkZCBbbsOrXSBMVCcsXG4gICAgICAgIGxhc3REYXkgOiAnW0RqZSBuw6tdIExUJyxcbiAgICAgICAgbGFzdFdlZWsgOiAnZGRkZCBbZSBrYWx1YXIgbsOrXSBMVCcsXG4gICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6ICduw6sgJXMnLFxuICAgICAgICBwYXN0IDogJyVzIG3DqyBwYXLDqycsXG4gICAgICAgIHMgOiAnZGlzYSBzZWtvbmRhJyxcbiAgICAgICAgc3MgOiAnJWQgc2Vrb25kYScsXG4gICAgICAgIG0gOiAnbmrDqyBtaW51dMOrJyxcbiAgICAgICAgbW0gOiAnJWQgbWludXRhJyxcbiAgICAgICAgaCA6ICduasOrIG9yw6snLFxuICAgICAgICBoaCA6ICclZCBvcsOrJyxcbiAgICAgICAgZCA6ICduasOrIGRpdMOrJyxcbiAgICAgICAgZGQgOiAnJWQgZGl0w6snLFxuICAgICAgICBNIDogJ25qw6sgbXVhaicsXG4gICAgICAgIE1NIDogJyVkIG11YWonLFxuICAgICAgICB5IDogJ25qw6sgdml0JyxcbiAgICAgICAgeXkgOiAnJWQgdml0ZSdcbiAgICB9LFxuICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfVxcLi8sXG4gICAgb3JkaW5hbCA6ICclZC4nLFxuICAgIHdlZWsgOiB7XG4gICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICBkb3kgOiA0ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgfVxufSk7XG5cbi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBTZXJiaWFuIEN5cmlsbGljIFtzci1jeXJsXVxuLy8hIGF1dGhvciA6IE1pbGFuIEphbmHEjWtvdmnEhzxtaWxhbmphbmFja292aWNAZ21haWwuY29tPiA6IGh0dHBzOi8vZ2l0aHViLmNvbS9taWxhbi1qXG5cbnZhciB0cmFuc2xhdG9yJDEgPSB7XG4gICAgd29yZHM6IHsgLy9EaWZmZXJlbnQgZ3JhbW1hdGljYWwgY2FzZXNcbiAgICAgICAgc3M6IFsn0YHQtdC60YPQvdC00LAnLCAn0YHQtdC60YPQvdC00LUnLCAn0YHQtdC60YPQvdC00LgnXSxcbiAgICAgICAgbTogWyfRmNC10LTQsNC9INC80LjQvdGD0YInLCAn0ZjQtdC00L3QtSDQvNC40L3Rg9GC0LUnXSxcbiAgICAgICAgbW06IFsn0LzQuNC90YPRgicsICfQvNC40L3Rg9GC0LUnLCAn0LzQuNC90YPRgtCwJ10sXG4gICAgICAgIGg6IFsn0ZjQtdC00LDQvSDRgdCw0YInLCAn0ZjQtdC00L3QvtCzINGB0LDRgtCwJ10sXG4gICAgICAgIGhoOiBbJ9GB0LDRgicsICfRgdCw0YLQsCcsICfRgdCw0YLQuCddLFxuICAgICAgICBkZDogWyfQtNCw0L0nLCAn0LTQsNC90LAnLCAn0LTQsNC90LAnXSxcbiAgICAgICAgTU06IFsn0LzQtdGB0LXRhicsICfQvNC10YHQtdGG0LAnLCAn0LzQtdGB0LXRhtC4J10sXG4gICAgICAgIHl5OiBbJ9Cz0L7QtNC40L3QsCcsICfQs9C+0LTQuNC90LUnLCAn0LPQvtC00LjQvdCwJ11cbiAgICB9LFxuICAgIGNvcnJlY3RHcmFtbWF0aWNhbENhc2U6IGZ1bmN0aW9uIChudW1iZXIsIHdvcmRLZXkpIHtcbiAgICAgICAgcmV0dXJuIG51bWJlciA9PT0gMSA/IHdvcmRLZXlbMF0gOiAobnVtYmVyID49IDIgJiYgbnVtYmVyIDw9IDQgPyB3b3JkS2V5WzFdIDogd29yZEtleVsyXSk7XG4gICAgfSxcbiAgICB0cmFuc2xhdGU6IGZ1bmN0aW9uIChudW1iZXIsIHdpdGhvdXRTdWZmaXgsIGtleSkge1xuICAgICAgICB2YXIgd29yZEtleSA9IHRyYW5zbGF0b3IkMS53b3Jkc1trZXldO1xuICAgICAgICBpZiAoa2V5Lmxlbmd0aCA9PT0gMSkge1xuICAgICAgICAgICAgcmV0dXJuIHdpdGhvdXRTdWZmaXggPyB3b3JkS2V5WzBdIDogd29yZEtleVsxXTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAnICcgKyB0cmFuc2xhdG9yJDEuY29ycmVjdEdyYW1tYXRpY2FsQ2FzZShudW1iZXIsIHdvcmRLZXkpO1xuICAgICAgICB9XG4gICAgfVxufTtcblxuaG9va3MuZGVmaW5lTG9jYWxlKCdzci1jeXJsJywge1xuICAgIG1vbnRoczogJ9GY0LDQvdGD0LDRgF/RhNC10LHRgNGD0LDRgF/QvNCw0YDRgl/QsNC/0YDQuNC7X9C80LDRmF/RmNGD0L1f0ZjRg9C7X9Cw0LLQs9GD0YHRgl/RgdC10L/RgtC10LzQsdCw0YBf0L7QutGC0L7QsdCw0YBf0L3QvtCy0LXQvNCx0LDRgF/QtNC10YbQtdC80LHQsNGAJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0OiAn0ZjQsNC9Ll/RhNC10LEuX9C80LDRgC5f0LDQv9GALl/QvNCw0Zhf0ZjRg9C9X9GY0YPQu1/QsNCy0LMuX9GB0LXQvy5f0L7QutGCLl/QvdC+0LIuX9C00LXRhi4nLnNwbGl0KCdfJyksXG4gICAgbW9udGhzUGFyc2VFeGFjdDogdHJ1ZSxcbiAgICB3ZWVrZGF5czogJ9C90LXQtNC10ZnQsF/Qv9C+0L3QtdC00LXRmdCw0Lpf0YPRgtC+0YDQsNC6X9GB0YDQtdC00LBf0YfQtdGC0LLRgNGC0LDQul/Qv9C10YLQsNC6X9GB0YPQsdC+0YLQsCcuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0OiAn0L3QtdC0Ll/Qv9C+0L0uX9GD0YLQvi5f0YHRgNC1Ll/Rh9C10YIuX9C/0LXRgi5f0YHRg9CxLicuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbjogJ9C90LVf0L/Qvl/Rg9GCX9GB0YBf0YfQtV/Qv9C1X9GB0YMnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNQYXJzZUV4YWN0IDogdHJ1ZSxcbiAgICBsb25nRGF0ZUZvcm1hdDoge1xuICAgICAgICBMVDogJ0g6bW0nLFxuICAgICAgICBMVFMgOiAnSDptbTpzcycsXG4gICAgICAgIEw6ICdERC5NTS5ZWVlZJyxcbiAgICAgICAgTEw6ICdELiBNTU1NIFlZWVknLFxuICAgICAgICBMTEw6ICdELiBNTU1NIFlZWVkgSDptbScsXG4gICAgICAgIExMTEw6ICdkZGRkLCBELiBNTU1NIFlZWVkgSDptbSdcbiAgICB9LFxuICAgIGNhbGVuZGFyOiB7XG4gICAgICAgIHNhbWVEYXk6ICdb0LTQsNC90LDRgSDRg10gTFQnLFxuICAgICAgICBuZXh0RGF5OiAnW9GB0YPRgtGA0LAg0YNdIExUJyxcbiAgICAgICAgbmV4dFdlZWs6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHN3aXRjaCAodGhpcy5kYXkoKSkge1xuICAgICAgICAgICAgICAgIGNhc2UgMDpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdb0YNdIFvQvdC10LTQtdGZ0YNdIFvRg10gTFQnO1xuICAgICAgICAgICAgICAgIGNhc2UgMzpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdb0YNdIFvRgdGA0LXQtNGDXSBb0YNdIExUJztcbiAgICAgICAgICAgICAgICBjYXNlIDY6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnW9GDXSBb0YHRg9Cx0L7RgtGDXSBb0YNdIExUJztcbiAgICAgICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgICAgIGNhc2UgNDpcbiAgICAgICAgICAgICAgICBjYXNlIDU6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnW9GDXSBkZGRkIFvRg10gTFQnO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBsYXN0RGF5ICA6ICdb0ZjRg9GH0LUg0YNdIExUJyxcbiAgICAgICAgbGFzdFdlZWsgOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgbGFzdFdlZWtEYXlzID0gW1xuICAgICAgICAgICAgICAgICdb0L/RgNC+0YjQu9C1XSBb0L3QtdC00LXRmdC1XSBb0YNdIExUJyxcbiAgICAgICAgICAgICAgICAnW9C/0YDQvtGI0LvQvtCzXSBb0L/QvtC90LXQtNC10ZnQutCwXSBb0YNdIExUJyxcbiAgICAgICAgICAgICAgICAnW9C/0YDQvtGI0LvQvtCzXSBb0YPRgtC+0YDQutCwXSBb0YNdIExUJyxcbiAgICAgICAgICAgICAgICAnW9C/0YDQvtGI0LvQtV0gW9GB0YDQtdC00LVdIFvRg10gTFQnLFxuICAgICAgICAgICAgICAgICdb0L/RgNC+0YjQu9C+0LNdIFvRh9C10YLQstGA0YLQutCwXSBb0YNdIExUJyxcbiAgICAgICAgICAgICAgICAnW9C/0YDQvtGI0LvQvtCzXSBb0L/QtdGC0LrQsF0gW9GDXSBMVCcsXG4gICAgICAgICAgICAgICAgJ1vQv9GA0L7RiNC70LVdIFvRgdGD0LHQvtGC0LVdIFvRg10gTFQnXG4gICAgICAgICAgICBdO1xuICAgICAgICAgICAgcmV0dXJuIGxhc3RXZWVrRGF5c1t0aGlzLmRheSgpXTtcbiAgICAgICAgfSxcbiAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJ9C30LAgJXMnLFxuICAgICAgICBwYXN0ICAgOiAn0L/RgNC1ICVzJyxcbiAgICAgICAgcyAgICAgIDogJ9C90LXQutC+0LvQuNC60L4g0YHQtdC60YPQvdC00LgnLFxuICAgICAgICBzcyAgICAgOiB0cmFuc2xhdG9yJDEudHJhbnNsYXRlLFxuICAgICAgICBtICAgICAgOiB0cmFuc2xhdG9yJDEudHJhbnNsYXRlLFxuICAgICAgICBtbSAgICAgOiB0cmFuc2xhdG9yJDEudHJhbnNsYXRlLFxuICAgICAgICBoICAgICAgOiB0cmFuc2xhdG9yJDEudHJhbnNsYXRlLFxuICAgICAgICBoaCAgICAgOiB0cmFuc2xhdG9yJDEudHJhbnNsYXRlLFxuICAgICAgICBkICAgICAgOiAn0LTQsNC9JyxcbiAgICAgICAgZGQgICAgIDogdHJhbnNsYXRvciQxLnRyYW5zbGF0ZSxcbiAgICAgICAgTSAgICAgIDogJ9C80LXRgdC10YYnLFxuICAgICAgICBNTSAgICAgOiB0cmFuc2xhdG9yJDEudHJhbnNsYXRlLFxuICAgICAgICB5ICAgICAgOiAn0LPQvtC00LjQvdGDJyxcbiAgICAgICAgeXkgICAgIDogdHJhbnNsYXRvciQxLnRyYW5zbGF0ZVxuICAgIH0sXG4gICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9XFwuLyxcbiAgICBvcmRpbmFsIDogJyVkLicsXG4gICAgd2VlayA6IHtcbiAgICAgICAgZG93IDogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgIGRveSA6IDcgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDFzdCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICB9XG59KTtcblxuLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSA6IFNlcmJpYW4gW3NyXVxuLy8hIGF1dGhvciA6IE1pbGFuIEphbmHEjWtvdmnEhzxtaWxhbmphbmFja292aWNAZ21haWwuY29tPiA6IGh0dHBzOi8vZ2l0aHViLmNvbS9taWxhbi1qXG5cbnZhciB0cmFuc2xhdG9yJDIgPSB7XG4gICAgd29yZHM6IHsgLy9EaWZmZXJlbnQgZ3JhbW1hdGljYWwgY2FzZXNcbiAgICAgICAgc3M6IFsnc2VrdW5kYScsICdzZWt1bmRlJywgJ3Nla3VuZGknXSxcbiAgICAgICAgbTogWydqZWRhbiBtaW51dCcsICdqZWRuZSBtaW51dGUnXSxcbiAgICAgICAgbW06IFsnbWludXQnLCAnbWludXRlJywgJ21pbnV0YSddLFxuICAgICAgICBoOiBbJ2plZGFuIHNhdCcsICdqZWRub2cgc2F0YSddLFxuICAgICAgICBoaDogWydzYXQnLCAnc2F0YScsICdzYXRpJ10sXG4gICAgICAgIGRkOiBbJ2RhbicsICdkYW5hJywgJ2RhbmEnXSxcbiAgICAgICAgTU06IFsnbWVzZWMnLCAnbWVzZWNhJywgJ21lc2VjaSddLFxuICAgICAgICB5eTogWydnb2RpbmEnLCAnZ29kaW5lJywgJ2dvZGluYSddXG4gICAgfSxcbiAgICBjb3JyZWN0R3JhbW1hdGljYWxDYXNlOiBmdW5jdGlvbiAobnVtYmVyLCB3b3JkS2V5KSB7XG4gICAgICAgIHJldHVybiBudW1iZXIgPT09IDEgPyB3b3JkS2V5WzBdIDogKG51bWJlciA+PSAyICYmIG51bWJlciA8PSA0ID8gd29yZEtleVsxXSA6IHdvcmRLZXlbMl0pO1xuICAgIH0sXG4gICAgdHJhbnNsYXRlOiBmdW5jdGlvbiAobnVtYmVyLCB3aXRob3V0U3VmZml4LCBrZXkpIHtcbiAgICAgICAgdmFyIHdvcmRLZXkgPSB0cmFuc2xhdG9yJDIud29yZHNba2V5XTtcbiAgICAgICAgaWYgKGtleS5sZW5ndGggPT09IDEpIHtcbiAgICAgICAgICAgIHJldHVybiB3aXRob3V0U3VmZml4ID8gd29yZEtleVswXSA6IHdvcmRLZXlbMV07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJyAnICsgdHJhbnNsYXRvciQyLmNvcnJlY3RHcmFtbWF0aWNhbENhc2UobnVtYmVyLCB3b3JkS2V5KTtcbiAgICAgICAgfVxuICAgIH1cbn07XG5cbmhvb2tzLmRlZmluZUxvY2FsZSgnc3InLCB7XG4gICAgbW9udGhzOiAnamFudWFyX2ZlYnJ1YXJfbWFydF9hcHJpbF9tYWpfanVuX2p1bF9hdmd1c3Rfc2VwdGVtYmFyX29rdG9iYXJfbm92ZW1iYXJfZGVjZW1iYXInLnNwbGl0KCdfJyksXG4gICAgbW9udGhzU2hvcnQ6ICdqYW4uX2ZlYi5fbWFyLl9hcHIuX21hal9qdW5fanVsX2F2Zy5fc2VwLl9va3QuX25vdi5fZGVjLicuc3BsaXQoJ18nKSxcbiAgICBtb250aHNQYXJzZUV4YWN0OiB0cnVlLFxuICAgIHdlZWtkYXlzOiAnbmVkZWxqYV9wb25lZGVsamFrX3V0b3Jha19zcmVkYV/EjWV0dnJ0YWtfcGV0YWtfc3Vib3RhJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzU2hvcnQ6ICduZWQuX3Bvbi5fdXRvLl9zcmUuX8SNZXQuX3BldC5fc3ViLicuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbjogJ25lX3BvX3V0X3NyX8SNZV9wZV9zdScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgIGxvbmdEYXRlRm9ybWF0OiB7XG4gICAgICAgIExUOiAnSDptbScsXG4gICAgICAgIExUUyA6ICdIOm1tOnNzJyxcbiAgICAgICAgTDogJ0RELk1NLllZWVknLFxuICAgICAgICBMTDogJ0QuIE1NTU0gWVlZWScsXG4gICAgICAgIExMTDogJ0QuIE1NTU0gWVlZWSBIOm1tJyxcbiAgICAgICAgTExMTDogJ2RkZGQsIEQuIE1NTU0gWVlZWSBIOm1tJ1xuICAgIH0sXG4gICAgY2FsZW5kYXI6IHtcbiAgICAgICAgc2FtZURheTogJ1tkYW5hcyB1XSBMVCcsXG4gICAgICAgIG5leHREYXk6ICdbc3V0cmEgdV0gTFQnLFxuICAgICAgICBuZXh0V2VlazogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgc3dpdGNoICh0aGlzLmRheSgpKSB7XG4gICAgICAgICAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1t1XSBbbmVkZWxqdV0gW3VdIExUJztcbiAgICAgICAgICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnW3VdIFtzcmVkdV0gW3VdIExUJztcbiAgICAgICAgICAgICAgICBjYXNlIDY6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnW3VdIFtzdWJvdHVdIFt1XSBMVCc7XG4gICAgICAgICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgICAgIGNhc2UgMjpcbiAgICAgICAgICAgICAgICBjYXNlIDQ6XG4gICAgICAgICAgICAgICAgY2FzZSA1OlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1t1XSBkZGRkIFt1XSBMVCc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIGxhc3REYXkgIDogJ1tqdcSNZSB1XSBMVCcsXG4gICAgICAgIGxhc3RXZWVrIDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIGxhc3RXZWVrRGF5cyA9IFtcbiAgICAgICAgICAgICAgICAnW3Byb8WhbGVdIFtuZWRlbGplXSBbdV0gTFQnLFxuICAgICAgICAgICAgICAgICdbcHJvxaFsb2ddIFtwb25lZGVsamthXSBbdV0gTFQnLFxuICAgICAgICAgICAgICAgICdbcHJvxaFsb2ddIFt1dG9ya2FdIFt1XSBMVCcsXG4gICAgICAgICAgICAgICAgJ1twcm/FoWxlXSBbc3JlZGVdIFt1XSBMVCcsXG4gICAgICAgICAgICAgICAgJ1twcm/FoWxvZ10gW8SNZXR2cnRrYV0gW3VdIExUJyxcbiAgICAgICAgICAgICAgICAnW3Byb8WhbG9nXSBbcGV0a2FdIFt1XSBMVCcsXG4gICAgICAgICAgICAgICAgJ1twcm/FoWxlXSBbc3Vib3RlXSBbdV0gTFQnXG4gICAgICAgICAgICBdO1xuICAgICAgICAgICAgcmV0dXJuIGxhc3RXZWVrRGF5c1t0aGlzLmRheSgpXTtcbiAgICAgICAgfSxcbiAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJ3phICVzJyxcbiAgICAgICAgcGFzdCAgIDogJ3ByZSAlcycsXG4gICAgICAgIHMgICAgICA6ICduZWtvbGlrbyBzZWt1bmRpJyxcbiAgICAgICAgc3MgICAgIDogdHJhbnNsYXRvciQyLnRyYW5zbGF0ZSxcbiAgICAgICAgbSAgICAgIDogdHJhbnNsYXRvciQyLnRyYW5zbGF0ZSxcbiAgICAgICAgbW0gICAgIDogdHJhbnNsYXRvciQyLnRyYW5zbGF0ZSxcbiAgICAgICAgaCAgICAgIDogdHJhbnNsYXRvciQyLnRyYW5zbGF0ZSxcbiAgICAgICAgaGggICAgIDogdHJhbnNsYXRvciQyLnRyYW5zbGF0ZSxcbiAgICAgICAgZCAgICAgIDogJ2RhbicsXG4gICAgICAgIGRkICAgICA6IHRyYW5zbGF0b3IkMi50cmFuc2xhdGUsXG4gICAgICAgIE0gICAgICA6ICdtZXNlYycsXG4gICAgICAgIE1NICAgICA6IHRyYW5zbGF0b3IkMi50cmFuc2xhdGUsXG4gICAgICAgIHkgICAgICA6ICdnb2RpbnUnLFxuICAgICAgICB5eSAgICAgOiB0cmFuc2xhdG9yJDIudHJhbnNsYXRlXG4gICAgfSxcbiAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn1cXC4vLFxuICAgIG9yZGluYWwgOiAnJWQuJyxcbiAgICB3ZWVrIDoge1xuICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogNyAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gMXN0IGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH1cbn0pO1xuXG4vLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogc2lTd2F0aSBbc3NdXG4vLyEgYXV0aG9yIDogTmljb2xhaSBEYXZpZXM8bWFpbEBuaWNvbGFpLmlvPiA6IGh0dHBzOi8vZ2l0aHViLmNvbS9uaWNvbGFpZGF2aWVzXG5cblxuaG9va3MuZGVmaW5lTG9jYWxlKCdzcycsIHtcbiAgICBtb250aHMgOiBcIkJoaW1iaWR2d2FuZV9JbmRsb3ZhbmFfSW5kbG92J2xlbmtodWx1X01hYmFzYV9Jbmtod2VraHdldGlfSW5obGFiYV9LaG9sd2FuZV9JbmdjaV9JbnlvbmlfSW1waGFsYV9Md2V0aV9JbmdvbmdvbmlcIi5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0IDogJ0JoaV9JbmFfSW51X01hYl9JbmtfSW5oX0tob19JZ2NfSW55X0ltcF9Md2VfSWdvJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzIDogJ0xpc29udGZvX1Vtc29tYnVsdWtvX0xlc2liaWxpX0xlc2l0c2F0ZnVfTGVzaW5lX0xlc2lobGFudV9VbWdjaWJlbG8nLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydCA6ICdMaXNfVW1iX0xzYl9MZXNfTHNpX0xzaF9VbWcnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW4gOiAnTGlfVXNfTGJfTHRfTHNfTGhfVWcnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNQYXJzZUV4YWN0IDogdHJ1ZSxcbiAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgTFQgOiAnaDptbSBBJyxcbiAgICAgICAgTFRTIDogJ2g6bW06c3MgQScsXG4gICAgICAgIEwgOiAnREQvTU0vWVlZWScsXG4gICAgICAgIExMIDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgTExMIDogJ0QgTU1NTSBZWVlZIGg6bW0gQScsXG4gICAgICAgIExMTEwgOiAnZGRkZCwgRCBNTU1NIFlZWVkgaDptbSBBJ1xuICAgIH0sXG4gICAgY2FsZW5kYXIgOiB7XG4gICAgICAgIHNhbWVEYXkgOiAnW05hbXVobGEgbmdhXSBMVCcsXG4gICAgICAgIG5leHREYXkgOiAnW0t1c2FzYSBuZ2FdIExUJyxcbiAgICAgICAgbmV4dFdlZWsgOiAnZGRkZCBbbmdhXSBMVCcsXG4gICAgICAgIGxhc3REYXkgOiAnW0l0b2xvIG5nYV0gTFQnLFxuICAgICAgICBsYXN0V2VlayA6ICdkZGRkIFtsZWxpcGhlbGlsZV0gW25nYV0gTFQnLFxuICAgICAgICBzYW1lRWxzZSA6ICdMJ1xuICAgIH0sXG4gICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICBmdXR1cmUgOiAnbmdhICVzJyxcbiAgICAgICAgcGFzdCA6ICd3ZW50ZWthIG5nYSAlcycsXG4gICAgICAgIHMgOiAnZW1penV6d2FuYSBsb21jYW5lJyxcbiAgICAgICAgc3MgOiAnJWQgbXp1endhbmEnLFxuICAgICAgICBtIDogJ3VtenV6dScsXG4gICAgICAgIG1tIDogJyVkIGVtaXp1enUnLFxuICAgICAgICBoIDogJ2xpaG9yYScsXG4gICAgICAgIGhoIDogJyVkIGVtYWhvcmEnLFxuICAgICAgICBkIDogJ2xpbGFuZ2EnLFxuICAgICAgICBkZCA6ICclZCBlbWFsYW5nYScsXG4gICAgICAgIE0gOiAnaW55YW5nYScsXG4gICAgICAgIE1NIDogJyVkIHRpbnlhbmdhJyxcbiAgICAgICAgeSA6ICd1bW55YWthJyxcbiAgICAgICAgeXkgOiAnJWQgaW1pbnlha2EnXG4gICAgfSxcbiAgICBtZXJpZGllbVBhcnNlOiAvZWt1c2VuaXxlbWluaXxlbnRzYW1iYW1hfGVidXN1a3UvLFxuICAgIG1lcmlkaWVtIDogZnVuY3Rpb24gKGhvdXJzLCBtaW51dGVzLCBpc0xvd2VyKSB7XG4gICAgICAgIGlmIChob3VycyA8IDExKSB7XG4gICAgICAgICAgICByZXR1cm4gJ2VrdXNlbmknO1xuICAgICAgICB9IGVsc2UgaWYgKGhvdXJzIDwgMTUpIHtcbiAgICAgICAgICAgIHJldHVybiAnZW1pbmknO1xuICAgICAgICB9IGVsc2UgaWYgKGhvdXJzIDwgMTkpIHtcbiAgICAgICAgICAgIHJldHVybiAnZW50c2FtYmFtYSc7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gJ2VidXN1a3UnO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBtZXJpZGllbUhvdXIgOiBmdW5jdGlvbiAoaG91ciwgbWVyaWRpZW0pIHtcbiAgICAgICAgaWYgKGhvdXIgPT09IDEyKSB7XG4gICAgICAgICAgICBob3VyID0gMDtcbiAgICAgICAgfVxuICAgICAgICBpZiAobWVyaWRpZW0gPT09ICdla3VzZW5pJykge1xuICAgICAgICAgICAgcmV0dXJuIGhvdXI7XG4gICAgICAgIH0gZWxzZSBpZiAobWVyaWRpZW0gPT09ICdlbWluaScpIHtcbiAgICAgICAgICAgIHJldHVybiBob3VyID49IDExID8gaG91ciA6IGhvdXIgKyAxMjtcbiAgICAgICAgfSBlbHNlIGlmIChtZXJpZGllbSA9PT0gJ2VudHNhbWJhbWEnIHx8IG1lcmlkaWVtID09PSAnZWJ1c3VrdScpIHtcbiAgICAgICAgICAgIGlmIChob3VyID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gaG91ciArIDEyO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn0vLFxuICAgIG9yZGluYWwgOiAnJWQnLFxuICAgIHdlZWsgOiB7XG4gICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICBkb3kgOiA0ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgfVxufSk7XG5cbi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBTd2VkaXNoIFtzdl1cbi8vISBhdXRob3IgOiBKZW5zIEFsbSA6IGh0dHBzOi8vZ2l0aHViLmNvbS91bG11c1xuXG5ob29rcy5kZWZpbmVMb2NhbGUoJ3N2Jywge1xuICAgIG1vbnRocyA6ICdqYW51YXJpX2ZlYnJ1YXJpX21hcnNfYXByaWxfbWFqX2p1bmlfanVsaV9hdWd1c3RpX3NlcHRlbWJlcl9va3RvYmVyX25vdmVtYmVyX2RlY2VtYmVyJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0IDogJ2phbl9mZWJfbWFyX2Fwcl9tYWpfanVuX2p1bF9hdWdfc2VwX29rdF9ub3ZfZGVjJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzIDogJ3PDtm5kYWdfbcOlbmRhZ190aXNkYWdfb25zZGFnX3RvcnNkYWdfZnJlZGFnX2zDtnJkYWcnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydCA6ICdzw7ZuX23DpW5fdGlzX29uc190b3JfZnJlX2zDtnInLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW4gOiAnc8O2X23DpV90aV9vbl90b19mcl9sw7YnLnNwbGl0KCdfJyksXG4gICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgIExUIDogJ0hIOm1tJyxcbiAgICAgICAgTFRTIDogJ0hIOm1tOnNzJyxcbiAgICAgICAgTCA6ICdZWVlZLU1NLUREJyxcbiAgICAgICAgTEwgOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICBMTEwgOiAnRCBNTU1NIFlZWVkgW2tsLl0gSEg6bW0nLFxuICAgICAgICBMTExMIDogJ2RkZGQgRCBNTU1NIFlZWVkgW2tsLl0gSEg6bW0nLFxuICAgICAgICBsbGwgOiAnRCBNTU0gWVlZWSBISDptbScsXG4gICAgICAgIGxsbGwgOiAnZGRkIEQgTU1NIFlZWVkgSEg6bW0nXG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheTogJ1tJZGFnXSBMVCcsXG4gICAgICAgIG5leHREYXk6ICdbSW1vcmdvbl0gTFQnLFxuICAgICAgICBsYXN0RGF5OiAnW0lnw6VyXSBMVCcsXG4gICAgICAgIG5leHRXZWVrOiAnW1DDpV0gZGRkZCBMVCcsXG4gICAgICAgIGxhc3RXZWVrOiAnW0ldIGRkZGRbc10gTFQnLFxuICAgICAgICBzYW1lRWxzZTogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6ICdvbSAlcycsXG4gICAgICAgIHBhc3QgOiAnZsO2ciAlcyBzZWRhbicsXG4gICAgICAgIHMgOiAnbsOlZ3JhIHNla3VuZGVyJyxcbiAgICAgICAgc3MgOiAnJWQgc2VrdW5kZXInLFxuICAgICAgICBtIDogJ2VuIG1pbnV0JyxcbiAgICAgICAgbW0gOiAnJWQgbWludXRlcicsXG4gICAgICAgIGggOiAnZW4gdGltbWUnLFxuICAgICAgICBoaCA6ICclZCB0aW1tYXInLFxuICAgICAgICBkIDogJ2VuIGRhZycsXG4gICAgICAgIGRkIDogJyVkIGRhZ2FyJyxcbiAgICAgICAgTSA6ICdlbiBtw6VuYWQnLFxuICAgICAgICBNTSA6ICclZCBtw6VuYWRlcicsXG4gICAgICAgIHkgOiAnZXR0IMOlcicsXG4gICAgICAgIHl5IDogJyVkIMOlcidcbiAgICB9LFxuICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfShlfGEpLyxcbiAgICBvcmRpbmFsIDogZnVuY3Rpb24gKG51bWJlcikge1xuICAgICAgICB2YXIgYiA9IG51bWJlciAlIDEwLFxuICAgICAgICAgICAgb3V0cHV0ID0gKH5+KG51bWJlciAlIDEwMCAvIDEwKSA9PT0gMSkgPyAnZScgOlxuICAgICAgICAgICAgKGIgPT09IDEpID8gJ2EnIDpcbiAgICAgICAgICAgIChiID09PSAyKSA/ICdhJyA6XG4gICAgICAgICAgICAoYiA9PT0gMykgPyAnZScgOiAnZSc7XG4gICAgICAgIHJldHVybiBudW1iZXIgKyBvdXRwdXQ7XG4gICAgfSxcbiAgICB3ZWVrIDoge1xuICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogNCAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH1cbn0pO1xuXG4vLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogU3dhaGlsaSBbc3ddXG4vLyEgYXV0aG9yIDogRmFoYWQgS2Fzc2ltIDogaHR0cHM6Ly9naXRodWIuY29tL2ZhZHNlbFxuXG5ob29rcy5kZWZpbmVMb2NhbGUoJ3N3Jywge1xuICAgIG1vbnRocyA6ICdKYW51YXJpX0ZlYnJ1YXJpX01hY2hpX0FwcmlsaV9NZWlfSnVuaV9KdWxhaV9BZ29zdGlfU2VwdGVtYmFfT2t0b2JhX05vdmVtYmFfRGVzZW1iYScuc3BsaXQoJ18nKSxcbiAgICBtb250aHNTaG9ydCA6ICdKYW5fRmViX01hY19BcHJfTWVpX0p1bl9KdWxfQWdvX1NlcF9Pa3RfTm92X0Rlcycuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5cyA6ICdKdW1hcGlsaV9KdW1hdGF0dV9KdW1hbm5lX0p1bWF0YW5vX0FsaGFtaXNpX0lqdW1hYV9KdW1hbW9zaScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0IDogJ0pwbF9KdGF0X0pubmVfSnRhbl9BbGhfSWptX0ptb3MnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW4gOiAnSjJfSjNfSjRfSjVfQWxfSWpfSjEnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNQYXJzZUV4YWN0IDogdHJ1ZSxcbiAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgTFQgOiAnSEg6bW0nLFxuICAgICAgICBMVFMgOiAnSEg6bW06c3MnLFxuICAgICAgICBMIDogJ0RELk1NLllZWVknLFxuICAgICAgICBMTCA6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgIExMTCA6ICdEIE1NTU0gWVlZWSBISDptbScsXG4gICAgICAgIExMTEwgOiAnZGRkZCwgRCBNTU1NIFlZWVkgSEg6bW0nXG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheSA6ICdbbGVvIHNhYV0gTFQnLFxuICAgICAgICBuZXh0RGF5IDogJ1trZXNobyBzYWFdIExUJyxcbiAgICAgICAgbmV4dFdlZWsgOiAnW3dpa2kgaWpheW9dIGRkZGQgW3NhYXRdIExUJyxcbiAgICAgICAgbGFzdERheSA6ICdbamFuYV0gTFQnLFxuICAgICAgICBsYXN0V2VlayA6ICdbd2lraSBpbGl5b3BpdGFdIGRkZGQgW3NhYXRdIExUJyxcbiAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJyVzIGJhYWRheWUnLFxuICAgICAgICBwYXN0IDogJ3Rva2VhICVzJyxcbiAgICAgICAgcyA6ICdoaXZpIHB1bmRlJyxcbiAgICAgICAgc3MgOiAnc2VrdW5kZSAlZCcsXG4gICAgICAgIG0gOiAnZGFraWthIG1vamEnLFxuICAgICAgICBtbSA6ICdkYWtpa2EgJWQnLFxuICAgICAgICBoIDogJ3NhYSBsaW1vamEnLFxuICAgICAgICBoaCA6ICdtYXNhYSAlZCcsXG4gICAgICAgIGQgOiAnc2lrdSBtb2phJyxcbiAgICAgICAgZGQgOiAnbWFzaWt1ICVkJyxcbiAgICAgICAgTSA6ICdtd2V6aSBtbW9qYScsXG4gICAgICAgIE1NIDogJ21pZXppICVkJyxcbiAgICAgICAgeSA6ICdtd2FrYSBtbW9qYScsXG4gICAgICAgIHl5IDogJ21pYWthICVkJ1xuICAgIH0sXG4gICAgd2VlayA6IHtcbiAgICAgICAgZG93IDogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgIGRveSA6IDcgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDFzdCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICB9XG59KTtcblxuLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSA6IFRhbWlsIFt0YV1cbi8vISBhdXRob3IgOiBBcmp1bmt1bWFyIEtyaXNobmFtb29ydGh5IDogaHR0cHM6Ly9naXRodWIuY29tL3RrMTIwNDA0XG5cbnZhciBzeW1ib2xNYXAkMTMgPSB7XG4gICAgJzEnOiAn4K+nJyxcbiAgICAnMic6ICfgr6gnLFxuICAgICczJzogJ+CvqScsXG4gICAgJzQnOiAn4K+qJyxcbiAgICAnNSc6ICfgr6snLFxuICAgICc2JzogJ+CvrCcsXG4gICAgJzcnOiAn4K+tJyxcbiAgICAnOCc6ICfgr64nLFxuICAgICc5JzogJ+CvrycsXG4gICAgJzAnOiAn4K+mJ1xufTtcbnZhciBudW1iZXJNYXAkMTIgPSB7XG4gICAgJ+Cvpyc6ICcxJyxcbiAgICAn4K+oJzogJzInLFxuICAgICfgr6knOiAnMycsXG4gICAgJ+Cvqic6ICc0JyxcbiAgICAn4K+rJzogJzUnLFxuICAgICfgr6wnOiAnNicsXG4gICAgJ+CvrSc6ICc3JyxcbiAgICAn4K+uJzogJzgnLFxuICAgICfgr68nOiAnOScsXG4gICAgJ+Cvpic6ICcwJ1xufTtcblxuaG9va3MuZGVmaW5lTG9jYWxlKCd0YScsIHtcbiAgICBtb250aHMgOiAn4K6c4K6p4K614K6w4K6/X+CuquCuv+CuquCvjeCusOCuteCusOCuv1/grq7grr7grrDgr43grprgr41f4K6P4K6q4K+N4K6w4K6y4K+NX+CuruCvh1/grpzgr4Lgrqngr41f4K6c4K+C4K6y4K+IX+CuhuCuleCuuOCvjeCun+CvjV/grprgr4bgrqrgr43grp/gr4bgrq7gr43grqrgrrDgr41f4K6F4K6V4K+N4K6f4K+H4K6+4K6q4K6w4K+NX+CuqOCuteCuruCvjeCuquCusOCvjV/grp/grr/grprgrq7gr43grqrgrrDgr40nLnNwbGl0KCdfJyksXG4gICAgbW9udGhzU2hvcnQgOiAn4K6c4K6p4K614K6w4K6/X+CuquCuv+CuquCvjeCusOCuteCusOCuv1/grq7grr7grrDgr43grprgr41f4K6P4K6q4K+N4K6w4K6y4K+NX+CuruCvh1/grpzgr4Lgrqngr41f4K6c4K+C4K6y4K+IX+CuhuCuleCuuOCvjeCun+CvjV/grprgr4bgrqrgr43grp/gr4bgrq7gr43grqrgrrDgr41f4K6F4K6V4K+N4K6f4K+H4K6+4K6q4K6w4K+NX+CuqOCuteCuruCvjeCuquCusOCvjV/grp/grr/grprgrq7gr43grqrgrrDgr40nLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXMgOiAn4K6e4K6+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+IJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzU2hvcnQgOiAn4K6e4K6+4K6v4K6/4K6x4K+BX+CupOCuv+CumeCvjeCuleCus+CvjV/grprgr4bgrrXgr43grrXgrr7grq/gr41f4K6q4K+B4K6k4K6p4K+NX+CuteCuv+Cur+CuvuCutOCuqeCvjV/grrXgr4bgrrPgr43grrPgrr9f4K6a4K6p4K6/Jy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzTWluIDogJ+CunuCuvl/grqTgrr9f4K6a4K+GX+CuquCvgV/grrXgrr9f4K614K+GX+Cumicuc3BsaXQoJ18nKSxcbiAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgTFQgOiAnSEg6bW0nLFxuICAgICAgICBMVFMgOiAnSEg6bW06c3MnLFxuICAgICAgICBMIDogJ0REL01NL1lZWVknLFxuICAgICAgICBMTCA6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgIExMTCA6ICdEIE1NTU0gWVlZWSwgSEg6bW0nLFxuICAgICAgICBMTExMIDogJ2RkZGQsIEQgTU1NTSBZWVlZLCBISDptbSdcbiAgICB9LFxuICAgIGNhbGVuZGFyIDoge1xuICAgICAgICBzYW1lRGF5IDogJ1vgrofgrqngr43grrHgr4FdIExUJyxcbiAgICAgICAgbmV4dERheSA6ICdb4K6o4K6+4K6z4K+IXSBMVCcsXG4gICAgICAgIG5leHRXZWVrIDogJ2RkZGQsIExUJyxcbiAgICAgICAgbGFzdERheSA6ICdb4K6o4K+H4K6x4K+N4K6x4K+BXSBMVCcsXG4gICAgICAgIGxhc3RXZWVrIDogJ1vgrpXgrp/grqjgr43grqQg4K614K6+4K6w4K6u4K+NXSBkZGRkLCBMVCcsXG4gICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6ICclcyDgrofgrrLgr40nLFxuICAgICAgICBwYXN0IDogJyVzIOCuruCvgeCuqeCvjScsXG4gICAgICAgIHMgOiAn4K6S4K6w4K+BIOCumuCuv+CusiDgrrXgrr/grqjgrr7grp/grr/grpXgrrPgr40nLFxuICAgICAgICBzcyA6ICclZCDgrrXgrr/grqjgrr7grp/grr/grpXgrrPgr40nLFxuICAgICAgICBtIDogJ+CukuCusOCvgSDgrqjgrr/grq7grr/grp/grq7gr40nLFxuICAgICAgICBtbSA6ICclZCDgrqjgrr/grq7grr/grp/grpngr43grpXgrrPgr40nLFxuICAgICAgICBoIDogJ+CukuCusOCvgSDgrq7grqPgrr8g4K6o4K+H4K6w4K6u4K+NJyxcbiAgICAgICAgaGggOiAnJWQg4K6u4K6j4K6/IOCuqOCvh+CusOCuruCvjScsXG4gICAgICAgIGQgOiAn4K6S4K6w4K+BIOCuqOCuvuCus+CvjScsXG4gICAgICAgIGRkIDogJyVkIOCuqOCuvuCun+CvjeCuleCus+CvjScsXG4gICAgICAgIE0gOiAn4K6S4K6w4K+BIOCuruCuvuCupOCuruCvjScsXG4gICAgICAgIE1NIDogJyVkIOCuruCuvuCupOCumeCvjeCuleCus+CvjScsXG4gICAgICAgIHkgOiAn4K6S4K6w4K+BIOCuteCusOCvgeCun+CuruCvjScsXG4gICAgICAgIHl5IDogJyVkIOCuhuCuo+CvjeCun+CvgeCuleCus+CvjSdcbiAgICB9LFxuICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfeCuteCupOCvgS8sXG4gICAgb3JkaW5hbCA6IGZ1bmN0aW9uIChudW1iZXIpIHtcbiAgICAgICAgcmV0dXJuIG51bWJlciArICfgrrXgrqTgr4EnO1xuICAgIH0sXG4gICAgcHJlcGFyc2U6IGZ1bmN0aW9uIChzdHJpbmcpIHtcbiAgICAgICAgcmV0dXJuIHN0cmluZy5yZXBsYWNlKC9b4K+n4K+o4K+p4K+q4K+r4K+s4K+t4K+u4K+v4K+mXS9nLCBmdW5jdGlvbiAobWF0Y2gpIHtcbiAgICAgICAgICAgIHJldHVybiBudW1iZXJNYXAkMTJbbWF0Y2hdO1xuICAgICAgICB9KTtcbiAgICB9LFxuICAgIHBvc3Rmb3JtYXQ6IGZ1bmN0aW9uIChzdHJpbmcpIHtcbiAgICAgICAgcmV0dXJuIHN0cmluZy5yZXBsYWNlKC9cXGQvZywgZnVuY3Rpb24gKG1hdGNoKSB7XG4gICAgICAgICAgICByZXR1cm4gc3ltYm9sTWFwJDEzW21hdGNoXTtcbiAgICAgICAgfSk7XG4gICAgfSxcbiAgICAvLyByZWZlciBodHRwOi8vdGEud2lraXBlZGlhLm9yZy9zLzFlcjFcbiAgICBtZXJpZGllbVBhcnNlOiAv4K6v4K6+4K6u4K6u4K+NfOCuteCviOCuleCuseCviHzgrpXgrr7grrLgr4h84K6o4K6j4K+N4K6q4K6V4K6y4K+NfOCujuCuseCvjeCuquCuvuCun+CvgXzgrq7grr7grrLgr4gvLFxuICAgIG1lcmlkaWVtIDogZnVuY3Rpb24gKGhvdXIsIG1pbnV0ZSwgaXNMb3dlcikge1xuICAgICAgICBpZiAoaG91ciA8IDIpIHtcbiAgICAgICAgICAgIHJldHVybiAnIOCur+CuvuCuruCuruCvjSc7XG4gICAgICAgIH0gZWxzZSBpZiAoaG91ciA8IDYpIHtcbiAgICAgICAgICAgIHJldHVybiAnIOCuteCviOCuleCuseCviCc7ICAvLyDgrrXgr4jgrpXgrrHgr4hcbiAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgMTApIHtcbiAgICAgICAgICAgIHJldHVybiAnIOCuleCuvuCusuCviCc7IC8vIOCuleCuvuCusuCviFxuICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAxNCkge1xuICAgICAgICAgICAgcmV0dXJuICcg4K6o4K6j4K+N4K6q4K6V4K6y4K+NJzsgLy8g4K6o4K6j4K+N4K6q4K6V4K6y4K+NXG4gICAgICAgIH0gZWxzZSBpZiAoaG91ciA8IDE4KSB7XG4gICAgICAgICAgICByZXR1cm4gJyDgro7grrHgr43grqrgrr7grp/gr4EnOyAvLyDgro7grrHgr43grqrgrr7grp/gr4FcbiAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgMjIpIHtcbiAgICAgICAgICAgIHJldHVybiAnIOCuruCuvuCusuCviCc7IC8vIOCuruCuvuCusuCviFxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuICcg4K6v4K6+4K6u4K6u4K+NJztcbiAgICAgICAgfVxuICAgIH0sXG4gICAgbWVyaWRpZW1Ib3VyIDogZnVuY3Rpb24gKGhvdXIsIG1lcmlkaWVtKSB7XG4gICAgICAgIGlmIChob3VyID09PSAxMikge1xuICAgICAgICAgICAgaG91ciA9IDA7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG1lcmlkaWVtID09PSAn4K6v4K6+4K6u4K6u4K+NJykge1xuICAgICAgICAgICAgcmV0dXJuIGhvdXIgPCAyID8gaG91ciA6IGhvdXIgKyAxMjtcbiAgICAgICAgfSBlbHNlIGlmIChtZXJpZGllbSA9PT0gJ+CuteCviOCuleCuseCviCcgfHwgbWVyaWRpZW0gPT09ICfgrpXgrr7grrLgr4gnKSB7XG4gICAgICAgICAgICByZXR1cm4gaG91cjtcbiAgICAgICAgfSBlbHNlIGlmIChtZXJpZGllbSA9PT0gJ+CuqOCuo+CvjeCuquCuleCusuCvjScpIHtcbiAgICAgICAgICAgIHJldHVybiBob3VyID49IDEwID8gaG91ciA6IGhvdXIgKyAxMjtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBob3VyICsgMTI7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIHdlZWsgOiB7XG4gICAgICAgIGRvdyA6IDAsIC8vIFN1bmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICBkb3kgOiA2ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiAxc3QgaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgfVxufSk7XG5cbi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBUZWx1Z3UgW3RlXVxuLy8hIGF1dGhvciA6IEtyaXNobmEgQ2hhaXRhbnlhIFRob3RhIDogaHR0cHM6Ly9naXRodWIuY29tL2tjdGhvdGFcblxuaG9va3MuZGVmaW5lTG9jYWxlKCd0ZScsIHtcbiAgICBtb250aHMgOiAn4LCc4LCo4LC14LCw4LC/X+Cwq+Cwv+CwrOCxjeCwsOCwteCwsOCwv1/gsK7gsL7gsLDgsY3gsJrgsL9f4LCP4LCq4LGN4LCw4LC/4LCy4LGNX+CwruCxh1/gsJzgsYLgsKjgsY1f4LCc4LGC4LCy4LGG4LGWX+CwhuCwl+CwuOCxjeCwn+CxgV/gsLjgsYbgsKrgsY3gsJ/gsYbgsILgsKzgsLDgsY1f4LCF4LCV4LGN4LCf4LGL4LCs4LCw4LGNX+CwqOCwteCwguCwrOCwsOCxjV/gsKHgsL/gsLjgsYbgsILgsKzgsLDgsY0nLnNwbGl0KCdfJyksXG4gICAgbW9udGhzU2hvcnQgOiAn4LCc4LCoLl/gsKvgsL/gsKzgsY3gsLAuX+CwruCwvuCwsOCxjeCwmuCwv1/gsI/gsKrgsY3gsLDgsL8uX+CwruCxh1/gsJzgsYLgsKjgsY1f4LCc4LGC4LCy4LGG4LGWX+CwhuCwly5f4LC44LGG4LCq4LGNLl/gsIXgsJXgsY3gsJ/gsYsuX+CwqOCwtS5f4LCh4LC/4LC44LGGLicuc3BsaXQoJ18nKSxcbiAgICBtb250aHNQYXJzZUV4YWN0IDogdHJ1ZSxcbiAgICB3ZWVrZGF5cyA6ICfgsIbgsKbgsL/gsLXgsL7gsLDgsIJf4LC44LGL4LCu4LC14LC+4LCw4LCCX+CwruCwguCwl+Cws+CwteCwvuCwsOCwgl/gsKzgsYHgsKfgsLXgsL7gsLDgsIJf4LCX4LGB4LCw4LGB4LC14LC+4LCw4LCCX+CwtuCxgeCwleCxjeCwsOCwteCwvuCwsOCwgl/gsLbgsKjgsL/gsLXgsL7gsLDgsIInLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydCA6ICfgsIbgsKbgsL9f4LC44LGL4LCuX+CwruCwguCwl+Cws1/gsKzgsYHgsKdf4LCX4LGB4LCw4LGBX+CwtuCxgeCwleCxjeCwsF/gsLbgsKjgsL8nLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW4gOiAn4LCGX+CwuOCxi1/gsK7gsIJf4LCs4LGBX+Cwl+CxgV/gsLbgsYFf4LC2Jy5zcGxpdCgnXycpLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdBIGg6bW0nLFxuICAgICAgICBMVFMgOiAnQSBoOm1tOnNzJyxcbiAgICAgICAgTCA6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgTEwgOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICBMTEwgOiAnRCBNTU1NIFlZWVksIEEgaDptbScsXG4gICAgICAgIExMTEwgOiAnZGRkZCwgRCBNTU1NIFlZWVksIEEgaDptbSdcbiAgICB9LFxuICAgIGNhbGVuZGFyIDoge1xuICAgICAgICBzYW1lRGF5IDogJ1vgsKjgsYfgsKHgsYFdIExUJyxcbiAgICAgICAgbmV4dERheSA6ICdb4LCw4LGH4LCq4LGBXSBMVCcsXG4gICAgICAgIG5leHRXZWVrIDogJ2RkZGQsIExUJyxcbiAgICAgICAgbGFzdERheSA6ICdb4LCo4LC/4LCo4LGN4LCoXSBMVCcsXG4gICAgICAgIGxhc3RXZWVrIDogJ1vgsJfgsKRdIGRkZGQsIExUJyxcbiAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJyVzIOCwsuCxiycsXG4gICAgICAgIHBhc3QgOiAnJXMg4LCV4LGN4LCw4LC/4LCk4LCCJyxcbiAgICAgICAgcyA6ICfgsJXgsYrgsKjgsY3gsKjgsL8g4LCV4LGN4LC34LCj4LC+4LCy4LGBJyxcbiAgICAgICAgc3MgOiAnJWQg4LC44LGG4LCV4LCo4LGN4LCy4LGBJyxcbiAgICAgICAgbSA6ICfgsJLgsJUg4LCo4LC/4LCu4LC/4LC34LCCJyxcbiAgICAgICAgbW0gOiAnJWQg4LCo4LC/4LCu4LC/4LC34LC+4LCy4LGBJyxcbiAgICAgICAgaCA6ICfgsJLgsJUg4LCX4LCC4LCfJyxcbiAgICAgICAgaGggOiAnJWQg4LCX4LCC4LCf4LCy4LGBJyxcbiAgICAgICAgZCA6ICfgsJLgsJUg4LCw4LGL4LCc4LGBJyxcbiAgICAgICAgZGQgOiAnJWQg4LCw4LGL4LCc4LGB4LCy4LGBJyxcbiAgICAgICAgTSA6ICfgsJLgsJUg4LCo4LGG4LCyJyxcbiAgICAgICAgTU0gOiAnJWQg4LCo4LGG4LCy4LCy4LGBJyxcbiAgICAgICAgeSA6ICfgsJLgsJUg4LC44LCC4LC14LCk4LGN4LC44LCw4LCCJyxcbiAgICAgICAgeXkgOiAnJWQg4LC44LCC4LC14LCk4LGN4LC44LCw4LC+4LCy4LGBJ1xuICAgIH0sXG4gICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZSA6IC9cXGR7MSwyfeCwtS8sXG4gICAgb3JkaW5hbCA6ICclZOCwtScsXG4gICAgbWVyaWRpZW1QYXJzZTogL+CwsOCwvuCwpOCxjeCwsOCwv3zgsIngsKbgsK/gsIJ84LCu4LCn4LGN4LCv4LC+4LC54LGN4LCo4LCCfOCwuOCwvuCwr+CwguCwpOCxjeCwsOCwgi8sXG4gICAgbWVyaWRpZW1Ib3VyIDogZnVuY3Rpb24gKGhvdXIsIG1lcmlkaWVtKSB7XG4gICAgICAgIGlmIChob3VyID09PSAxMikge1xuICAgICAgICAgICAgaG91ciA9IDA7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG1lcmlkaWVtID09PSAn4LCw4LC+4LCk4LGN4LCw4LC/Jykge1xuICAgICAgICAgICAgcmV0dXJuIGhvdXIgPCA0ID8gaG91ciA6IGhvdXIgKyAxMjtcbiAgICAgICAgfSBlbHNlIGlmIChtZXJpZGllbSA9PT0gJ+CwieCwpuCwr+CwgicpIHtcbiAgICAgICAgICAgIHJldHVybiBob3VyO1xuICAgICAgICB9IGVsc2UgaWYgKG1lcmlkaWVtID09PSAn4LCu4LCn4LGN4LCv4LC+4LC54LGN4LCo4LCCJykge1xuICAgICAgICAgICAgcmV0dXJuIGhvdXIgPj0gMTAgPyBob3VyIDogaG91ciArIDEyO1xuICAgICAgICB9IGVsc2UgaWYgKG1lcmlkaWVtID09PSAn4LC44LC+4LCv4LCC4LCk4LGN4LCw4LCCJykge1xuICAgICAgICAgICAgcmV0dXJuIGhvdXIgKyAxMjtcbiAgICAgICAgfVxuICAgIH0sXG4gICAgbWVyaWRpZW0gOiBmdW5jdGlvbiAoaG91ciwgbWludXRlLCBpc0xvd2VyKSB7XG4gICAgICAgIGlmIChob3VyIDwgNCkge1xuICAgICAgICAgICAgcmV0dXJuICfgsLDgsL7gsKTgsY3gsLDgsL8nO1xuICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAxMCkge1xuICAgICAgICAgICAgcmV0dXJuICfgsIngsKbgsK/gsIInO1xuICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAxNykge1xuICAgICAgICAgICAgcmV0dXJuICfgsK7gsKfgsY3gsK/gsL7gsLngsY3gsKjgsIInO1xuICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAyMCkge1xuICAgICAgICAgICAgcmV0dXJuICfgsLjgsL7gsK/gsILgsKTgsY3gsLDgsIInO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuICfgsLDgsL7gsKTgsY3gsLDgsL8nO1xuICAgICAgICB9XG4gICAgfSxcbiAgICB3ZWVrIDoge1xuICAgICAgICBkb3cgOiAwLCAvLyBTdW5kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogNiAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gMXN0IGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH1cbn0pO1xuXG4vLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogVGV0dW4gRGlsaSAoRWFzdCBUaW1vcikgW3RldF1cbi8vISBhdXRob3IgOiBKb3NodWEgQnJvb2tzIDogaHR0cHM6Ly9naXRodWIuY29tL2pvc2hicm9va3Ncbi8vISBhdXRob3IgOiBPbm9yaW8gRGUgSi4gQWZvbnNvIDogaHR0cHM6Ly9naXRodWIuY29tL21hcm9ib1xuXG5ob29rcy5kZWZpbmVMb2NhbGUoJ3RldCcsIHtcbiAgICBtb250aHMgOiAnSmFuZWlydV9GZXZlcmVpcnVfTWFyc3VfQWJyaWxfTWFpdV9KdW5pdV9KdWxpdV9BdWd1c3R1X1NldGVtYnJ1X091dHVicnVfTm92ZW1icnVfRGV6ZW1icnUnLnNwbGl0KCdfJyksXG4gICAgbW9udGhzU2hvcnQgOiAnSmFuX0Zldl9NYXJfQWJyX01haV9KdW5fSnVsX0F1Z19TZXRfT3V0X05vdl9EZXonLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXMgOiAnRG9taW5ndV9TZWd1bmRhX1RlcnNhX0t1YXJ0YV9LaW50YV9TZXh0YV9TYWJhZHUnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydCA6ICdEb21fU2VnX1RlcnNfS3VhX0tpbnRfU2V4dF9TYWInLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW4gOiAnRG9fU2VnX1RlX0t1X0tpX1NleF9TYScuc3BsaXQoJ18nKSxcbiAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgTFQgOiAnSEg6bW0nLFxuICAgICAgICBMVFMgOiAnSEg6bW06c3MnLFxuICAgICAgICBMIDogJ0REL01NL1lZWVknLFxuICAgICAgICBMTCA6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgIExMTCA6ICdEIE1NTU0gWVlZWSBISDptbScsXG4gICAgICAgIExMTEwgOiAnZGRkZCwgRCBNTU1NIFlZWVkgSEg6bW0nXG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheTogJ1tPaGluIGloYV0gTFQnLFxuICAgICAgICBuZXh0RGF5OiAnW0FiYW4gaWhhXSBMVCcsXG4gICAgICAgIG5leHRXZWVrOiAnZGRkZCBbaWhhXSBMVCcsXG4gICAgICAgIGxhc3REYXk6ICdbSG9yaXNlaWsgaWhhXSBMVCcsXG4gICAgICAgIGxhc3RXZWVrOiAnZGRkZCBbc2VtYW5hIGtvdHVrXSBbaWhhXSBMVCcsXG4gICAgICAgIHNhbWVFbHNlOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJ2loYSAlcycsXG4gICAgICAgIHBhc3QgOiAnJXMgbGl1YmEnLFxuICAgICAgICBzIDogJ21pbnV0dSBiYWx1bicsXG4gICAgICAgIHNzIDogJ21pbnV0dSAlZCcsXG4gICAgICAgIG0gOiAnbWludXR1IGlkYScsXG4gICAgICAgIG1tIDogJ21pbnV0dXMgJWQnLFxuICAgICAgICBoIDogJ2hvcmFzIGlkYScsXG4gICAgICAgIGhoIDogJ2hvcmFzICVkJyxcbiAgICAgICAgZCA6ICdsb3JvbiBpZGEnLFxuICAgICAgICBkZCA6ICdsb3JvbiAlZCcsXG4gICAgICAgIE0gOiAnZnVsYW4gaWRhJyxcbiAgICAgICAgTU0gOiAnZnVsYW4gJWQnLFxuICAgICAgICB5IDogJ3RpbmFuIGlkYScsXG4gICAgICAgIHl5IDogJ3RpbmFuICVkJ1xuICAgIH0sXG4gICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9KHN0fG5kfHJkfHRoKS8sXG4gICAgb3JkaW5hbCA6IGZ1bmN0aW9uIChudW1iZXIpIHtcbiAgICAgICAgdmFyIGIgPSBudW1iZXIgJSAxMCxcbiAgICAgICAgICAgIG91dHB1dCA9ICh+fihudW1iZXIgJSAxMDAgLyAxMCkgPT09IDEpID8gJ3RoJyA6XG4gICAgICAgICAgICAoYiA9PT0gMSkgPyAnc3QnIDpcbiAgICAgICAgICAgIChiID09PSAyKSA/ICduZCcgOlxuICAgICAgICAgICAgKGIgPT09IDMpID8gJ3JkJyA6ICd0aCc7XG4gICAgICAgIHJldHVybiBudW1iZXIgKyBvdXRwdXQ7XG4gICAgfSxcbiAgICB3ZWVrIDoge1xuICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogNCAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH1cbn0pO1xuXG4vLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogVGhhaSBbdGhdXG4vLyEgYXV0aG9yIDogS3JpZHNhZGEgVGhhbmFidWxwb25nIDogaHR0cHM6Ly9naXRodWIuY29tL3Npcm5cblxuaG9va3MuZGVmaW5lTG9jYWxlKCd0aCcsIHtcbiAgICBtb250aHMgOiAn4Lih4LiB4Lij4Liy4LiE4LihX+C4geC4uOC4oeC4oOC4suC4nuC4seC4meC4mOC5jF/guKHguLXguJnguLLguITguKFf4LmA4Lih4Lip4Liy4Lii4LiZX+C4nuC4pOC4qeC4oOC4suC4hOC4oV/guKHguLTguJbguLjguJnguLLguKLguJlf4LiB4Lij4LiB4LiO4Liy4LiE4LihX+C4quC4tOC4h+C4q+C4suC4hOC4oV/guIHguLHguJnguKLguLLguKLguJlf4LiV4Li44Lil4Liy4LiE4LihX+C4nuC4pOC4qOC4iOC4tOC4geC4suC4ouC4mV/guJjguLHguJnguKfguLLguITguKEnLnNwbGl0KCdfJyksXG4gICAgbW9udGhzU2hvcnQgOiAn4LihLuC4hC5f4LiBLuC4ni5f4Lih4Li1LuC4hC5f4LmA4LihLuC4oi5f4LieLuC4hC5f4Lih4Li0LuC4oi5f4LiBLuC4hC5f4LiqLuC4hC5f4LiBLuC4oi5f4LiVLuC4hC5f4LieLuC4oi5f4LiYLuC4hC4nLnNwbGl0KCdfJyksXG4gICAgbW9udGhzUGFyc2VFeGFjdDogdHJ1ZSxcbiAgICB3ZWVrZGF5cyA6ICfguK3guLLguJfguLTguJXguKLguYxf4LiI4Lix4LiZ4LiX4Lij4LmMX+C4reC4seC4h+C4hOC4suC4o1/guJ7guLjguJhf4Lie4Lik4Lir4Lix4Liq4Lia4LiU4Li1X+C4qOC4uOC4geC4o+C5jF/guYDguKrguLLguKPguYwnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydCA6ICfguK3guLLguJfguLTguJXguKLguYxf4LiI4Lix4LiZ4LiX4Lij4LmMX+C4reC4seC4h+C4hOC4suC4o1/guJ7guLjguJhf4Lie4Lik4Lir4Lix4LiqX+C4qOC4uOC4geC4o+C5jF/guYDguKrguLLguKPguYwnLnNwbGl0KCdfJyksIC8vIHllcywgdGhyZWUgY2hhcmFjdGVycyBkaWZmZXJlbmNlXG4gICAgd2Vla2RheXNNaW4gOiAn4Lit4LiyLl/guIguX+C4rS5f4LieLl/guJ7guKQuX+C4qC5f4LiqLicuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdIOm1tJyxcbiAgICAgICAgTFRTIDogJ0g6bW06c3MnLFxuICAgICAgICBMIDogJ0REL01NL1lZWVknLFxuICAgICAgICBMTCA6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgIExMTCA6ICdEIE1NTU0gWVlZWSDguYDguKfguKXguLIgSDptbScsXG4gICAgICAgIExMTEwgOiAn4Lin4Lix4LiZZGRkZOC4l+C4teC5iCBEIE1NTU0gWVlZWSDguYDguKfguKXguLIgSDptbSdcbiAgICB9LFxuICAgIG1lcmlkaWVtUGFyc2U6IC/guIHguYjguK3guJnguYDguJfguLXguYjguKLguId84Lir4Lil4Lix4LiH4LmA4LiX4Li14LmI4Lii4LiHLyxcbiAgICBpc1BNOiBmdW5jdGlvbiAoaW5wdXQpIHtcbiAgICAgICAgcmV0dXJuIGlucHV0ID09PSAn4Lir4Lil4Lix4LiH4LmA4LiX4Li14LmI4Lii4LiHJztcbiAgICB9LFxuICAgIG1lcmlkaWVtIDogZnVuY3Rpb24gKGhvdXIsIG1pbnV0ZSwgaXNMb3dlcikge1xuICAgICAgICBpZiAoaG91ciA8IDEyKSB7XG4gICAgICAgICAgICByZXR1cm4gJ+C4geC5iOC4reC4meC5gOC4l+C4teC5iOC4ouC4hyc7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gJ+C4q+C4peC4seC4h+C5gOC4l+C4teC5iOC4ouC4hyc7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIGNhbGVuZGFyIDoge1xuICAgICAgICBzYW1lRGF5IDogJ1vguKfguLHguJnguJnguLXguYkg4LmA4Lin4Lil4LiyXSBMVCcsXG4gICAgICAgIG5leHREYXkgOiAnW+C4nuC4o+C4uOC5iOC4h+C4meC4teC5iSDguYDguKfguKXguLJdIExUJyxcbiAgICAgICAgbmV4dFdlZWsgOiAnZGRkZFvguKvguJnguYnguLIg4LmA4Lin4Lil4LiyXSBMVCcsXG4gICAgICAgIGxhc3REYXkgOiAnW+C5gOC4oeC4t+C5iOC4reC4p+C4suC4meC4meC4teC5iSDguYDguKfguKXguLJdIExUJyxcbiAgICAgICAgbGFzdFdlZWsgOiAnW+C4p+C4seC4mV1kZGRkW+C4l+C4teC5iOC5geC4peC5ieC4pyDguYDguKfguKXguLJdIExUJyxcbiAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJ+C4reC4teC4gSAlcycsXG4gICAgICAgIHBhc3QgOiAnJXPguJfguLXguYjguYHguKXguYnguKcnLFxuICAgICAgICBzIDogJ+C5hOC4oeC5iOC4geC4teC5iOC4p+C4tOC4meC4suC4l+C4tScsXG4gICAgICAgIHNzIDogJyVkIOC4p+C4tOC4meC4suC4l+C4tScsXG4gICAgICAgIG0gOiAnMSDguJnguLLguJfguLUnLFxuICAgICAgICBtbSA6ICclZCDguJnguLLguJfguLUnLFxuICAgICAgICBoIDogJzEg4LiK4Lix4LmI4Lin4LmC4Lih4LiHJyxcbiAgICAgICAgaGggOiAnJWQg4LiK4Lix4LmI4Lin4LmC4Lih4LiHJyxcbiAgICAgICAgZCA6ICcxIOC4p+C4seC4mScsXG4gICAgICAgIGRkIDogJyVkIOC4p+C4seC4mScsXG4gICAgICAgIE0gOiAnMSDguYDguJTguLfguK3guJknLFxuICAgICAgICBNTSA6ICclZCDguYDguJTguLfguK3guJknLFxuICAgICAgICB5IDogJzEg4Lib4Li1JyxcbiAgICAgICAgeXkgOiAnJWQg4Lib4Li1J1xuICAgIH1cbn0pO1xuXG4vLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogVGFnYWxvZyAoUGhpbGlwcGluZXMpIFt0bC1waF1cbi8vISBhdXRob3IgOiBEYW4gSGFnbWFuIDogaHR0cHM6Ly9naXRodWIuY29tL2hhZ21hbmRhblxuXG5ob29rcy5kZWZpbmVMb2NhbGUoJ3RsLXBoJywge1xuICAgIG1vbnRocyA6ICdFbmVyb19QZWJyZXJvX01hcnNvX0FicmlsX01heW9fSHVueW9fSHVseW9fQWdvc3RvX1NldHllbWJyZV9Pa3R1YnJlX05vYnllbWJyZV9EaXN5ZW1icmUnLnNwbGl0KCdfJyksXG4gICAgbW9udGhzU2hvcnQgOiAnRW5lX1BlYl9NYXJfQWJyX01heV9IdW5fSHVsX0Fnb19TZXRfT2t0X05vYl9EaXMnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXMgOiAnTGluZ2dvX0x1bmVzX01hcnRlc19NaXllcmt1bGVzX0h1d2ViZXNfQml5ZXJuZXNfU2FiYWRvJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzU2hvcnQgOiAnTGluX0x1bl9NYXJfTWl5X0h1d19CaXlfU2FiJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzTWluIDogJ0xpX0x1X01hX01pX0h1X0JpX1NhYicuc3BsaXQoJ18nKSxcbiAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgTFQgOiAnSEg6bW0nLFxuICAgICAgICBMVFMgOiAnSEg6bW06c3MnLFxuICAgICAgICBMIDogJ01NL0QvWVlZWScsXG4gICAgICAgIExMIDogJ01NTU0gRCwgWVlZWScsXG4gICAgICAgIExMTCA6ICdNTU1NIEQsIFlZWVkgSEg6bW0nLFxuICAgICAgICBMTExMIDogJ2RkZGQsIE1NTU0gREQsIFlZWVkgSEg6bW0nXG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheTogJ0xUIFtuZ2F5b25nIGFyYXddJyxcbiAgICAgICAgbmV4dERheTogJ1tCdWthcyBuZ10gTFQnLFxuICAgICAgICBuZXh0V2VlazogJ0xUIFtzYSBzdXN1bm9kIG5hXSBkZGRkJyxcbiAgICAgICAgbGFzdERheTogJ0xUIFtrYWhhcG9uXScsXG4gICAgICAgIGxhc3RXZWVrOiAnTFQgW25vb25nIG5ha2FyYWFuZ10gZGRkZCcsXG4gICAgICAgIHNhbWVFbHNlOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJ3NhIGxvb2IgbmcgJXMnLFxuICAgICAgICBwYXN0IDogJyVzIGFuZyBuYWthbGlwYXMnLFxuICAgICAgICBzIDogJ2lsYW5nIHNlZ3VuZG8nLFxuICAgICAgICBzcyA6ICclZCBzZWd1bmRvJyxcbiAgICAgICAgbSA6ICdpc2FuZyBtaW51dG8nLFxuICAgICAgICBtbSA6ICclZCBtaW51dG8nLFxuICAgICAgICBoIDogJ2lzYW5nIG9yYXMnLFxuICAgICAgICBoaCA6ICclZCBvcmFzJyxcbiAgICAgICAgZCA6ICdpc2FuZyBhcmF3JyxcbiAgICAgICAgZGQgOiAnJWQgYXJhdycsXG4gICAgICAgIE0gOiAnaXNhbmcgYnV3YW4nLFxuICAgICAgICBNTSA6ICclZCBidXdhbicsXG4gICAgICAgIHkgOiAnaXNhbmcgdGFvbicsXG4gICAgICAgIHl5IDogJyVkIHRhb24nXG4gICAgfSxcbiAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn0vLFxuICAgIG9yZGluYWwgOiBmdW5jdGlvbiAobnVtYmVyKSB7XG4gICAgICAgIHJldHVybiBudW1iZXI7XG4gICAgfSxcbiAgICB3ZWVrIDoge1xuICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogNCAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH1cbn0pO1xuXG4vLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogS2xpbmdvbiBbdGxoXVxuLy8hIGF1dGhvciA6IERvbWluaWthIEtydWsgOiBodHRwczovL2dpdGh1Yi5jb20vYW1hcmFudGhyb3NlXG5cbnZhciBudW1iZXJzTm91bnMgPSAncGFnaF93YeKAmV9jaGHigJlfd2VqX2xvU192YWdoX2phdl9Tb2NoX2Nob3JnaF9IdXQnLnNwbGl0KCdfJyk7XG5cbmZ1bmN0aW9uIHRyYW5zbGF0ZUZ1dHVyZShvdXRwdXQpIHtcbiAgICB2YXIgdGltZSA9IG91dHB1dDtcbiAgICB0aW1lID0gKG91dHB1dC5pbmRleE9mKCdqYWonKSAhPT0gLTEpID9cbiAgICB0aW1lLnNsaWNlKDAsIC0zKSArICdsZVMnIDpcbiAgICAob3V0cHV0LmluZGV4T2YoJ2phcicpICE9PSAtMSkgP1xuICAgIHRpbWUuc2xpY2UoMCwgLTMpICsgJ3dhUScgOlxuICAgIChvdXRwdXQuaW5kZXhPZignRElTJykgIT09IC0xKSA/XG4gICAgdGltZS5zbGljZSgwLCAtMykgKyAnbmVtJyA6XG4gICAgdGltZSArICcgcElxJztcbiAgICByZXR1cm4gdGltZTtcbn1cblxuZnVuY3Rpb24gdHJhbnNsYXRlUGFzdChvdXRwdXQpIHtcbiAgICB2YXIgdGltZSA9IG91dHB1dDtcbiAgICB0aW1lID0gKG91dHB1dC5pbmRleE9mKCdqYWonKSAhPT0gLTEpID9cbiAgICB0aW1lLnNsaWNlKDAsIC0zKSArICdIdeKAmScgOlxuICAgIChvdXRwdXQuaW5kZXhPZignamFyJykgIT09IC0xKSA/XG4gICAgdGltZS5zbGljZSgwLCAtMykgKyAnd2VuJyA6XG4gICAgKG91dHB1dC5pbmRleE9mKCdESVMnKSAhPT0gLTEpID9cbiAgICB0aW1lLnNsaWNlKDAsIC0zKSArICdiZW4nIDpcbiAgICB0aW1lICsgJyByZXQnO1xuICAgIHJldHVybiB0aW1lO1xufVxuXG5mdW5jdGlvbiB0cmFuc2xhdGUkOShudW1iZXIsIHdpdGhvdXRTdWZmaXgsIHN0cmluZywgaXNGdXR1cmUpIHtcbiAgICB2YXIgbnVtYmVyTm91biA9IG51bWJlckFzTm91bihudW1iZXIpO1xuICAgIHN3aXRjaCAoc3RyaW5nKSB7XG4gICAgICAgIGNhc2UgJ3NzJzpcbiAgICAgICAgICAgIHJldHVybiBudW1iZXJOb3VuICsgJyBsdXAnO1xuICAgICAgICBjYXNlICdtbSc6XG4gICAgICAgICAgICByZXR1cm4gbnVtYmVyTm91biArICcgdHVwJztcbiAgICAgICAgY2FzZSAnaGgnOlxuICAgICAgICAgICAgcmV0dXJuIG51bWJlck5vdW4gKyAnIHJlcCc7XG4gICAgICAgIGNhc2UgJ2RkJzpcbiAgICAgICAgICAgIHJldHVybiBudW1iZXJOb3VuICsgJyBqYWonO1xuICAgICAgICBjYXNlICdNTSc6XG4gICAgICAgICAgICByZXR1cm4gbnVtYmVyTm91biArICcgamFyJztcbiAgICAgICAgY2FzZSAneXknOlxuICAgICAgICAgICAgcmV0dXJuIG51bWJlck5vdW4gKyAnIERJUyc7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBudW1iZXJBc05vdW4obnVtYmVyKSB7XG4gICAgdmFyIGh1bmRyZWQgPSBNYXRoLmZsb29yKChudW1iZXIgJSAxMDAwKSAvIDEwMCksXG4gICAgdGVuID0gTWF0aC5mbG9vcigobnVtYmVyICUgMTAwKSAvIDEwKSxcbiAgICBvbmUgPSBudW1iZXIgJSAxMCxcbiAgICB3b3JkID0gJyc7XG4gICAgaWYgKGh1bmRyZWQgPiAwKSB7XG4gICAgICAgIHdvcmQgKz0gbnVtYmVyc05vdW5zW2h1bmRyZWRdICsgJ3ZhdGxoJztcbiAgICB9XG4gICAgaWYgKHRlbiA+IDApIHtcbiAgICAgICAgd29yZCArPSAoKHdvcmQgIT09ICcnKSA/ICcgJyA6ICcnKSArIG51bWJlcnNOb3Vuc1t0ZW5dICsgJ21hSCc7XG4gICAgfVxuICAgIGlmIChvbmUgPiAwKSB7XG4gICAgICAgIHdvcmQgKz0gKCh3b3JkICE9PSAnJykgPyAnICcgOiAnJykgKyBudW1iZXJzTm91bnNbb25lXTtcbiAgICB9XG4gICAgcmV0dXJuICh3b3JkID09PSAnJykgPyAncGFnaCcgOiB3b3JkO1xufVxuXG5ob29rcy5kZWZpbmVMb2NhbGUoJ3RsaCcsIHtcbiAgICBtb250aHMgOiAndGVyYeKAmSBqYXIgd2HigJlfdGVyYeKAmSBqYXIgY2hh4oCZX3RlcmHigJkgamFyIHdlal90ZXJh4oCZIGphciBsb1NfdGVyYeKAmSBqYXIgdmFnaF90ZXJh4oCZIGphciBqYXZfdGVyYeKAmSBqYXIgU29jaF90ZXJh4oCZIGphciBjaG9yZ2hfdGVyYeKAmSBqYXIgSHV0X3RlcmHigJkgamFyIHdh4oCZbWFIX3RlcmHigJkgamFyIHdh4oCZbWFIIHdh4oCZX3RlcmHigJkgamFyIHdh4oCZbWFIIGNoYeKAmScuc3BsaXQoJ18nKSxcbiAgICBtb250aHNTaG9ydCA6ICdqYXIgd2HigJlfamFyIGNoYeKAmV9qYXIgd2VqX2phciBsb1NfamFyIHZhZ2hfamFyIGphdl9qYXIgU29jaF9qYXIgY2hvcmdoX2phciBIdXRfamFyIHdh4oCZbWFIX2phciB3YeKAmW1hSCB3YeKAmV9qYXIgd2HigJltYUggY2hh4oCZJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgIHdlZWtkYXlzIDogJ2xvam1JdGphal9EYVNqYWpfcG92amFqX2doSXRsaGphal9sb2doamFqX2J1cWphal9naEluamFqJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzU2hvcnQgOiAnbG9qbUl0amFqX0RhU2phal9wb3ZqYWpfZ2hJdGxoamFqX2xvZ2hqYWpfYnVxamFqX2doSW5qYWonLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW4gOiAnbG9qbUl0amFqX0RhU2phal9wb3ZqYWpfZ2hJdGxoamFqX2xvZ2hqYWpfYnVxamFqX2doSW5qYWonLnNwbGl0KCdfJyksXG4gICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgIExUIDogJ0hIOm1tJyxcbiAgICAgICAgTFRTIDogJ0hIOm1tOnNzJyxcbiAgICAgICAgTCA6ICdERC5NTS5ZWVlZJyxcbiAgICAgICAgTEwgOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICBMTEwgOiAnRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICBMTExMIDogJ2RkZGQsIEQgTU1NTSBZWVlZIEhIOm1tJ1xuICAgIH0sXG4gICAgY2FsZW5kYXIgOiB7XG4gICAgICAgIHNhbWVEYXk6ICdbRGFIamFqXSBMVCcsXG4gICAgICAgIG5leHREYXk6ICdbd2HigJlsZVNdIExUJyxcbiAgICAgICAgbmV4dFdlZWs6ICdMTEwnLFxuICAgICAgICBsYXN0RGF5OiAnW3dh4oCZSHXigJldIExUJyxcbiAgICAgICAgbGFzdFdlZWs6ICdMTEwnLFxuICAgICAgICBzYW1lRWxzZTogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6IHRyYW5zbGF0ZUZ1dHVyZSxcbiAgICAgICAgcGFzdCA6IHRyYW5zbGF0ZVBhc3QsXG4gICAgICAgIHMgOiAncHVTIGx1cCcsXG4gICAgICAgIHNzIDogdHJhbnNsYXRlJDksXG4gICAgICAgIG0gOiAnd2HigJkgdHVwJyxcbiAgICAgICAgbW0gOiB0cmFuc2xhdGUkOSxcbiAgICAgICAgaCA6ICd3YeKAmSByZXAnLFxuICAgICAgICBoaCA6IHRyYW5zbGF0ZSQ5LFxuICAgICAgICBkIDogJ3dh4oCZIGphaicsXG4gICAgICAgIGRkIDogdHJhbnNsYXRlJDksXG4gICAgICAgIE0gOiAnd2HigJkgamFyJyxcbiAgICAgICAgTU0gOiB0cmFuc2xhdGUkOSxcbiAgICAgICAgeSA6ICd3YeKAmSBESVMnLFxuICAgICAgICB5eSA6IHRyYW5zbGF0ZSQ5XG4gICAgfSxcbiAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn1cXC4vLFxuICAgIG9yZGluYWwgOiAnJWQuJyxcbiAgICB3ZWVrIDoge1xuICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogNCAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH1cbn0pO1xuXG4vLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogVHVya2lzaCBbdHJdXG4vLyEgYXV0aG9ycyA6IEVyaGFuIEd1bmRvZ2FuIDogaHR0cHM6Ly9naXRodWIuY29tL2VyaGFuZ3VuZG9nYW4sXG4vLyEgICAgICAgICAgIEJ1cmFrIFlpxJ9pdCBLYXlhOiBodHRwczovL2dpdGh1Yi5jb20vQllLXG5cbnZhciBzdWZmaXhlcyQzID0ge1xuICAgIDE6ICdcXCdpbmNpJyxcbiAgICA1OiAnXFwnaW5jaScsXG4gICAgODogJ1xcJ2luY2knLFxuICAgIDcwOiAnXFwnaW5jaScsXG4gICAgODA6ICdcXCdpbmNpJyxcbiAgICAyOiAnXFwnbmNpJyxcbiAgICA3OiAnXFwnbmNpJyxcbiAgICAyMDogJ1xcJ25jaScsXG4gICAgNTA6ICdcXCduY2knLFxuICAgIDM6ICdcXCfDvG5jw7wnLFxuICAgIDQ6ICdcXCfDvG5jw7wnLFxuICAgIDEwMDogJ1xcJ8O8bmPDvCcsXG4gICAgNjogJ1xcJ25jxLEnLFxuICAgIDk6ICdcXCd1bmN1JyxcbiAgICAxMDogJ1xcJ3VuY3UnLFxuICAgIDMwOiAnXFwndW5jdScsXG4gICAgNjA6ICdcXCfEsW5jxLEnLFxuICAgIDkwOiAnXFwnxLFuY8SxJ1xufTtcblxuaG9va3MuZGVmaW5lTG9jYWxlKCd0cicsIHtcbiAgICBtb250aHMgOiAnT2Nha1/FnnViYXRfTWFydF9OaXNhbl9NYXnEsXNfSGF6aXJhbl9UZW1tdXpfQcSfdXN0b3NfRXlsw7xsX0VraW1fS2FzxLFtX0FyYWzEsWsnLnNwbGl0KCdfJyksXG4gICAgbW9udGhzU2hvcnQgOiAnT2NhX8WedWJfTWFyX05pc19NYXlfSGF6X1RlbV9BxJ91X0V5bF9Fa2lfS2FzX0FyYScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5cyA6ICdQYXphcl9QYXphcnRlc2lfU2FsxLFfw4dhcsWfYW1iYV9QZXLFn2VtYmVfQ3VtYV9DdW1hcnRlc2knLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydCA6ICdQYXpfUHRzX1NhbF/Dh2FyX1Blcl9DdW1fQ3RzJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzTWluIDogJ1B6X1B0X1NhX8OHYV9QZV9DdV9DdCcuc3BsaXQoJ18nKSxcbiAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgTFQgOiAnSEg6bW0nLFxuICAgICAgICBMVFMgOiAnSEg6bW06c3MnLFxuICAgICAgICBMIDogJ0RELk1NLllZWVknLFxuICAgICAgICBMTCA6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgIExMTCA6ICdEIE1NTU0gWVlZWSBISDptbScsXG4gICAgICAgIExMTEwgOiAnZGRkZCwgRCBNTU1NIFlZWVkgSEg6bW0nXG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheSA6ICdbYnVnw7xuIHNhYXRdIExUJyxcbiAgICAgICAgbmV4dERheSA6ICdbeWFyxLFuIHNhYXRdIExUJyxcbiAgICAgICAgbmV4dFdlZWsgOiAnW2dlbGVjZWtdIGRkZGQgW3NhYXRdIExUJyxcbiAgICAgICAgbGFzdERheSA6ICdbZMO8bl0gTFQnLFxuICAgICAgICBsYXN0V2VlayA6ICdbZ2XDp2VuXSBkZGRkIFtzYWF0XSBMVCcsXG4gICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6ICclcyBzb25yYScsXG4gICAgICAgIHBhc3QgOiAnJXMgw7ZuY2UnLFxuICAgICAgICBzIDogJ2Jpcmthw6cgc2FuaXllJyxcbiAgICAgICAgc3MgOiAnJWQgc2FuaXllJyxcbiAgICAgICAgbSA6ICdiaXIgZGFraWthJyxcbiAgICAgICAgbW0gOiAnJWQgZGFraWthJyxcbiAgICAgICAgaCA6ICdiaXIgc2FhdCcsXG4gICAgICAgIGhoIDogJyVkIHNhYXQnLFxuICAgICAgICBkIDogJ2JpciBnw7xuJyxcbiAgICAgICAgZGQgOiAnJWQgZ8O8bicsXG4gICAgICAgIE0gOiAnYmlyIGF5JyxcbiAgICAgICAgTU0gOiAnJWQgYXknLFxuICAgICAgICB5IDogJ2JpciB5xLFsJyxcbiAgICAgICAgeXkgOiAnJWQgecSxbCdcbiAgICB9LFxuICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfScoaW5jaXxuY2l8w7xuY8O8fG5jxLF8dW5jdXzEsW5jxLEpLyxcbiAgICBvcmRpbmFsIDogZnVuY3Rpb24gKG51bWJlcikge1xuICAgICAgICBpZiAobnVtYmVyID09PSAwKSB7ICAvLyBzcGVjaWFsIGNhc2UgZm9yIHplcm9cbiAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAnXFwnxLFuY8SxJztcbiAgICAgICAgfVxuICAgICAgICB2YXIgYSA9IG51bWJlciAlIDEwLFxuICAgICAgICAgICAgYiA9IG51bWJlciAlIDEwMCAtIGEsXG4gICAgICAgICAgICBjID0gbnVtYmVyID49IDEwMCA/IDEwMCA6IG51bGw7XG4gICAgICAgIHJldHVybiBudW1iZXIgKyAoc3VmZml4ZXMkM1thXSB8fCBzdWZmaXhlcyQzW2JdIHx8IHN1ZmZpeGVzJDNbY10pO1xuICAgIH0sXG4gICAgd2VlayA6IHtcbiAgICAgICAgZG93IDogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgIGRveSA6IDcgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDFzdCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICB9XG59KTtcblxuLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSA6IFRhbG9zc2FuIFt0emxdXG4vLyEgYXV0aG9yIDogUm9iaW4gdmFuIGRlciBWbGlldCA6IGh0dHBzOi8vZ2l0aHViLmNvbS9yb2JpbjB2YW4wZGVyMHZcbi8vISBhdXRob3IgOiBJdXN0w6wgQ2FudW5cblxuLy8gQWZ0ZXIgdGhlIHllYXIgdGhlcmUgc2hvdWxkIGJlIGEgc2xhc2ggYW5kIHRoZSBhbW91bnQgb2YgeWVhcnMgc2luY2UgRGVjZW1iZXIgMjYsIDE5NzkgaW4gUm9tYW4gbnVtZXJhbHMuXG4vLyBUaGlzIGlzIGN1cnJlbnRseSB0b28gZGlmZmljdWx0IChtYXliZSBldmVuIGltcG9zc2libGUpIHRvIGFkZC5cbmhvb2tzLmRlZmluZUxvY2FsZSgndHpsJywge1xuICAgIG1vbnRocyA6ICdKYW51YXJfRmV2cmFnbGhfTWFyw6dfQXZyw691X01haV9Hw7xuX0p1bGlhX0d1c2NodF9TZXRlbXZhcl9MaXN0b3DDpHRzX05vZW12YXJfWmVjZW12YXInLnNwbGl0KCdfJyksXG4gICAgbW9udGhzU2hvcnQgOiAnSmFuX0Zldl9NYXJfQXZyX01haV9Hw7xuX0p1bF9HdXNfU2V0X0xpc19Ob2VfWmVjJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzIDogJ1PDumxhZGlfTMO6bmXDp2lfTWFpdHppX03DoXJjdXJpX1how7phZGlfVmnDqW5lcsOnaV9Tw6F0dXJpJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzU2hvcnQgOiAnU8O6bF9Mw7puX01haV9Nw6FyX1how7pfVmnDqV9Tw6F0Jy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzTWluIDogJ1PDul9Mw7pfTWFfTcOhX1hoX1ZpX1PDoScuc3BsaXQoJ18nKSxcbiAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgTFQgOiAnSEgubW0nLFxuICAgICAgICBMVFMgOiAnSEgubW0uc3MnLFxuICAgICAgICBMIDogJ0RELk1NLllZWVknLFxuICAgICAgICBMTCA6ICdELiBNTU1NIFtkYWxsYXNdIFlZWVknLFxuICAgICAgICBMTEwgOiAnRC4gTU1NTSBbZGFsbGFzXSBZWVlZIEhILm1tJyxcbiAgICAgICAgTExMTCA6ICdkZGRkLCBbbGldIEQuIE1NTU0gW2RhbGxhc10gWVlZWSBISC5tbSdcbiAgICB9LFxuICAgIG1lcmlkaWVtUGFyc2U6IC9kXFwnb3xkXFwnYS9pLFxuICAgIGlzUE0gOiBmdW5jdGlvbiAoaW5wdXQpIHtcbiAgICAgICAgcmV0dXJuICdkXFwnbycgPT09IGlucHV0LnRvTG93ZXJDYXNlKCk7XG4gICAgfSxcbiAgICBtZXJpZGllbSA6IGZ1bmN0aW9uIChob3VycywgbWludXRlcywgaXNMb3dlcikge1xuICAgICAgICBpZiAoaG91cnMgPiAxMSkge1xuICAgICAgICAgICAgcmV0dXJuIGlzTG93ZXIgPyAnZFxcJ28nIDogJ0RcXCdPJztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBpc0xvd2VyID8gJ2RcXCdhJyA6ICdEXFwnQSc7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIGNhbGVuZGFyIDoge1xuICAgICAgICBzYW1lRGF5IDogJ1tveGhpIMOgXSBMVCcsXG4gICAgICAgIG5leHREYXkgOiAnW2RlbcOgIMOgXSBMVCcsXG4gICAgICAgIG5leHRXZWVrIDogJ2RkZGQgW8OgXSBMVCcsXG4gICAgICAgIGxhc3REYXkgOiAnW2llaXJpIMOgXSBMVCcsXG4gICAgICAgIGxhc3RXZWVrIDogJ1tzw7xyIGVsXSBkZGRkIFtsYXN0ZXUgw6BdIExUJyxcbiAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJ29zcHJlaSAlcycsXG4gICAgICAgIHBhc3QgOiAnamElcycsXG4gICAgICAgIHMgOiBwcm9jZXNzUmVsYXRpdmVUaW1lJDcsXG4gICAgICAgIHNzIDogcHJvY2Vzc1JlbGF0aXZlVGltZSQ3LFxuICAgICAgICBtIDogcHJvY2Vzc1JlbGF0aXZlVGltZSQ3LFxuICAgICAgICBtbSA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUkNyxcbiAgICAgICAgaCA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUkNyxcbiAgICAgICAgaGggOiBwcm9jZXNzUmVsYXRpdmVUaW1lJDcsXG4gICAgICAgIGQgOiBwcm9jZXNzUmVsYXRpdmVUaW1lJDcsXG4gICAgICAgIGRkIDogcHJvY2Vzc1JlbGF0aXZlVGltZSQ3LFxuICAgICAgICBNIDogcHJvY2Vzc1JlbGF0aXZlVGltZSQ3LFxuICAgICAgICBNTSA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUkNyxcbiAgICAgICAgeSA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUkNyxcbiAgICAgICAgeXkgOiBwcm9jZXNzUmVsYXRpdmVUaW1lJDdcbiAgICB9LFxuICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfVxcLi8sXG4gICAgb3JkaW5hbCA6ICclZC4nLFxuICAgIHdlZWsgOiB7XG4gICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICBkb3kgOiA0ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgfVxufSk7XG5cbmZ1bmN0aW9uIHByb2Nlc3NSZWxhdGl2ZVRpbWUkNyhudW1iZXIsIHdpdGhvdXRTdWZmaXgsIGtleSwgaXNGdXR1cmUpIHtcbiAgICB2YXIgZm9ybWF0ID0ge1xuICAgICAgICAncyc6IFsndmllbnNhcyBzZWN1bmRzJywgJ1xcJ2llbnNhcyBzZWN1bmRzJ10sXG4gICAgICAgICdzcyc6IFtudW1iZXIgKyAnIHNlY3VuZHMnLCAnJyArIG51bWJlciArICcgc2VjdW5kcyddLFxuICAgICAgICAnbSc6IFsnXFwnbiBtw611dCcsICdcXCdpZW5zIG3DrXV0J10sXG4gICAgICAgICdtbSc6IFtudW1iZXIgKyAnIG3DrXV0cycsICcnICsgbnVtYmVyICsgJyBtw611dHMnXSxcbiAgICAgICAgJ2gnOiBbJ1xcJ24gw75vcmEnLCAnXFwnaWVuc2Egw75vcmEnXSxcbiAgICAgICAgJ2hoJzogW251bWJlciArICcgw75vcmFzJywgJycgKyBudW1iZXIgKyAnIMO+b3JhcyddLFxuICAgICAgICAnZCc6IFsnXFwnbiB6aXVhJywgJ1xcJ2llbnNhIHppdWEnXSxcbiAgICAgICAgJ2RkJzogW251bWJlciArICcgeml1YXMnLCAnJyArIG51bWJlciArICcgeml1YXMnXSxcbiAgICAgICAgJ00nOiBbJ1xcJ24gbWVzJywgJ1xcJ2llbnMgbWVzJ10sXG4gICAgICAgICdNTSc6IFtudW1iZXIgKyAnIG1lc2VuJywgJycgKyBudW1iZXIgKyAnIG1lc2VuJ10sXG4gICAgICAgICd5JzogWydcXCduIGFyJywgJ1xcJ2llbnMgYXInXSxcbiAgICAgICAgJ3l5JzogW251bWJlciArICcgYXJzJywgJycgKyBudW1iZXIgKyAnIGFycyddXG4gICAgfTtcbiAgICByZXR1cm4gaXNGdXR1cmUgPyBmb3JtYXRba2V5XVswXSA6ICh3aXRob3V0U3VmZml4ID8gZm9ybWF0W2tleV1bMF0gOiBmb3JtYXRba2V5XVsxXSk7XG59XG5cbi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBDZW50cmFsIEF0bGFzIFRhbWF6aWdodCBMYXRpbiBbdHptLWxhdG5dXG4vLyEgYXV0aG9yIDogQWJkZWwgU2FpZCA6IGh0dHBzOi8vZ2l0aHViLmNvbS9hYmRlbHNhaWRcblxuaG9va3MuZGVmaW5lTG9jYWxlKCd0em0tbGF0bicsIHtcbiAgICBtb250aHMgOiAnaW5uYXlyX2Jyy6RheXLLpF9tYXLLpHPLpF9pYnJpcl9tYXl5d195d255d195d2x5d3pfyaN3xaF0X8Whd3RhbmJpcl9rdMukd2Jyy6Rfbnd3YW5iaXJfZHdqbmJpcicuc3BsaXQoJ18nKSxcbiAgICBtb250aHNTaG9ydCA6ICdpbm5heXJfYnLLpGF5csukX21hcsukc8ukX2licmlyX21heXl3X3l3bnl3X3l3bHl3el/Jo3fFoXRfxaF3dGFuYmlyX2t0y6R3YnLLpF9ud3dhbmJpcl9kd2puYmlyJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzIDogJ2FzYW1hc19heW5hc19hc2luYXNfYWtyYXNfYWt3YXNfYXNpbXdhc19hc2nhuI15YXMnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydCA6ICdhc2FtYXNfYXluYXNfYXNpbmFzX2FrcmFzX2Frd2FzX2FzaW13YXNfYXNp4biNeWFzJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzTWluIDogJ2FzYW1hc19heW5hc19hc2luYXNfYWtyYXNfYWt3YXNfYXNpbXdhc19hc2nhuI15YXMnLnNwbGl0KCdfJyksXG4gICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgIExUIDogJ0hIOm1tJyxcbiAgICAgICAgTFRTIDogJ0hIOm1tOnNzJyxcbiAgICAgICAgTCA6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgTEwgOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICBMTEwgOiAnRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICBMTExMIDogJ2RkZGQgRCBNTU1NIFlZWVkgSEg6bW0nXG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheTogJ1thc2RraCBnXSBMVCcsXG4gICAgICAgIG5leHREYXk6ICdbYXNrYSBnXSBMVCcsXG4gICAgICAgIG5leHRXZWVrOiAnZGRkZCBbZ10gTFQnLFxuICAgICAgICBsYXN0RGF5OiAnW2Fzc2FudCBnXSBMVCcsXG4gICAgICAgIGxhc3RXZWVrOiAnZGRkZCBbZ10gTFQnLFxuICAgICAgICBzYW1lRWxzZTogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6ICdkYWRraCBzIHlhbiAlcycsXG4gICAgICAgIHBhc3QgOiAneWFuICVzJyxcbiAgICAgICAgcyA6ICdpbWlrJyxcbiAgICAgICAgc3MgOiAnJWQgaW1paycsXG4gICAgICAgIG0gOiAnbWludeG4jScsXG4gICAgICAgIG1tIDogJyVkIG1pbnXhuI0nLFxuICAgICAgICBoIDogJ3NhyZthJyxcbiAgICAgICAgaGggOiAnJWQgdGFzc2HJm2luJyxcbiAgICAgICAgZCA6ICdhc3MnLFxuICAgICAgICBkZCA6ICclZCBvc3NhbicsXG4gICAgICAgIE0gOiAnYXlvd3InLFxuICAgICAgICBNTSA6ICclZCBpeXlpcm4nLFxuICAgICAgICB5IDogJ2FzZ2FzJyxcbiAgICAgICAgeXkgOiAnJWQgaXNnYXNuJ1xuICAgIH0sXG4gICAgd2VlayA6IHtcbiAgICAgICAgZG93IDogNiwgLy8gU2F0dXJkYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogMTIgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDFzdCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICB9XG59KTtcblxuLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSA6IENlbnRyYWwgQXRsYXMgVGFtYXppZ2h0IFt0em1dXG4vLyEgYXV0aG9yIDogQWJkZWwgU2FpZCA6IGh0dHBzOi8vZ2l0aHViLmNvbS9hYmRlbHNhaWRcblxuaG9va3MuZGVmaW5lTG9jYWxlKCd0em0nLCB7XG4gICAgbW9udGhzIDogJ+K1ieK1j+K1j+K0sOK1ouK1lF/itLHitZXitLDitaLitZVf4rWO4rSw4rWV4rWaX+K1ieK0seK1lOK1ieK1lF/itY7itLDitaLitaLitZNf4rWi4rWT4rWP4rWi4rWTX+K1ouK1k+K1jeK1ouK1k+K1o1/itZbitZPitZvitZxf4rWb4rWT4rWc4rSw4rWP4rSx4rWJ4rWUX+K0veK1n+K1k+K0seK1lV/itY/itZPitaHitLDitY/itLHitYnitZRf4rS34rWT4rWK4rWP4rSx4rWJ4rWUJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0IDogJ+K1ieK1j+K1j+K0sOK1ouK1lF/itLHitZXitLDitaLitZVf4rWO4rSw4rWV4rWaX+K1ieK0seK1lOK1ieK1lF/itY7itLDitaLitaLitZNf4rWi4rWT4rWP4rWi4rWTX+K1ouK1k+K1jeK1ouK1k+K1o1/itZbitZPitZvitZxf4rWb4rWT4rWc4rSw4rWP4rSx4rWJ4rWUX+K0veK1n+K1k+K0seK1lV/itY/itZPitaHitLDitY/itLHitYnitZRf4rS34rWT4rWK4rWP4rSx4rWJ4rWUJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzIDogJ+K0sOK1meK0sOK1juK0sOK1mV/itLDitaLitY/itLDitZlf4rSw4rWZ4rWJ4rWP4rSw4rWZX+K0sOK0veK1lOK0sOK1mV/itLDitL3itaHitLDitZlf4rSw4rWZ4rWJ4rWO4rWh4rSw4rWZX+K0sOK1meK1ieK0ueK1ouK0sOK1mScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0IDogJ+K0sOK1meK0sOK1juK0sOK1mV/itLDitaLitY/itLDitZlf4rSw4rWZ4rWJ4rWP4rSw4rWZX+K0sOK0veK1lOK0sOK1mV/itLDitL3itaHitLDitZlf4rSw4rWZ4rWJ4rWO4rWh4rSw4rWZX+K0sOK1meK1ieK0ueK1ouK0sOK1mScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbiA6ICfitLDitZnitLDitY7itLDitZlf4rSw4rWi4rWP4rSw4rWZX+K0sOK1meK1ieK1j+K0sOK1mV/itLDitL3itZTitLDitZlf4rSw4rS94rWh4rSw4rWZX+K0sOK1meK1ieK1juK1oeK0sOK1mV/itLDitZnitYnitLnitaLitLDitZknLnNwbGl0KCdfJyksXG4gICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgIExUIDogJ0hIOm1tJyxcbiAgICAgICAgTFRTOiAnSEg6bW06c3MnLFxuICAgICAgICBMIDogJ0REL01NL1lZWVknLFxuICAgICAgICBMTCA6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgIExMTCA6ICdEIE1NTU0gWVlZWSBISDptbScsXG4gICAgICAgIExMTEwgOiAnZGRkZCBEIE1NTU0gWVlZWSBISDptbSdcbiAgICB9LFxuICAgIGNhbGVuZGFyIDoge1xuICAgICAgICBzYW1lRGF5OiAnW+K0sOK1meK0t+K1hSDitLRdIExUJyxcbiAgICAgICAgbmV4dERheTogJ1vitLDitZnitL3itLAg4rS0XSBMVCcsXG4gICAgICAgIG5leHRXZWVrOiAnZGRkZCBb4rS0XSBMVCcsXG4gICAgICAgIGxhc3REYXk6ICdb4rSw4rWa4rSw4rWP4rWcIOK0tF0gTFQnLFxuICAgICAgICBsYXN0V2VlazogJ2RkZGQgW+K0tF0gTFQnLFxuICAgICAgICBzYW1lRWxzZTogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6ICfitLfitLDitLfitYUg4rWZIOK1ouK0sOK1jyAlcycsXG4gICAgICAgIHBhc3QgOiAn4rWi4rSw4rWPICVzJyxcbiAgICAgICAgcyA6ICfitYnitY7itYnitL0nLFxuICAgICAgICBzcyA6ICclZCDitYnitY7itYnitL0nLFxuICAgICAgICBtIDogJ+K1juK1ieK1j+K1k+K0uicsXG4gICAgICAgIG1tIDogJyVkIOK1juK1ieK1j+K1k+K0uicsXG4gICAgICAgIGggOiAn4rWZ4rSw4rWE4rSwJyxcbiAgICAgICAgaGggOiAnJWQg4rWc4rSw4rWZ4rWZ4rSw4rWE4rWJ4rWPJyxcbiAgICAgICAgZCA6ICfitLDitZnitZknLFxuICAgICAgICBkZCA6ICclZCBv4rWZ4rWZ4rSw4rWPJyxcbiAgICAgICAgTSA6ICfitLDitaJv4rWT4rWUJyxcbiAgICAgICAgTU0gOiAnJWQg4rWJ4rWi4rWi4rWJ4rWU4rWPJyxcbiAgICAgICAgeSA6ICfitLDitZnitLPitLDitZknLFxuICAgICAgICB5eSA6ICclZCDitYnitZnitLPitLDitZnitY8nXG4gICAgfSxcbiAgICB3ZWVrIDoge1xuICAgICAgICBkb3cgOiA2LCAvLyBTYXR1cmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICBkb3kgOiAxMiAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gMXN0IGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH1cbn0pO1xuXG4vLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogVWtyYWluaWFuIFt1a11cbi8vISBhdXRob3IgOiB6ZW1sYW5pbiA6IGh0dHBzOi8vZ2l0aHViLmNvbS96ZW1sYW5pblxuLy8hIEF1dGhvciA6IE1lbmVsaW9uIEVsZW5zw7psZSA6IGh0dHBzOi8vZ2l0aHViLmNvbS9PaXJlXG5cbmZ1bmN0aW9uIHBsdXJhbCQ2KHdvcmQsIG51bSkge1xuICAgIHZhciBmb3JtcyA9IHdvcmQuc3BsaXQoJ18nKTtcbiAgICByZXR1cm4gbnVtICUgMTAgPT09IDEgJiYgbnVtICUgMTAwICE9PSAxMSA/IGZvcm1zWzBdIDogKG51bSAlIDEwID49IDIgJiYgbnVtICUgMTAgPD0gNCAmJiAobnVtICUgMTAwIDwgMTAgfHwgbnVtICUgMTAwID49IDIwKSA/IGZvcm1zWzFdIDogZm9ybXNbMl0pO1xufVxuZnVuY3Rpb24gcmVsYXRpdmVUaW1lV2l0aFBsdXJhbCQ0KG51bWJlciwgd2l0aG91dFN1ZmZpeCwga2V5KSB7XG4gICAgdmFyIGZvcm1hdCA9IHtcbiAgICAgICAgJ3NzJzogd2l0aG91dFN1ZmZpeCA/ICfRgdC10LrRg9C90LTQsF/RgdC10LrRg9C90LTQuF/RgdC10LrRg9C90LQnIDogJ9GB0LXQutGD0L3QtNGDX9GB0LXQutGD0L3QtNC4X9GB0LXQutGD0L3QtCcsXG4gICAgICAgICdtbSc6IHdpdGhvdXRTdWZmaXggPyAn0YXQstC40LvQuNC90LBf0YXQstC40LvQuNC90Lhf0YXQstC40LvQuNC9JyA6ICfRhdCy0LjQu9C40L3Rg1/RhdCy0LjQu9C40L3QuF/RhdCy0LjQu9C40L0nLFxuICAgICAgICAnaGgnOiB3aXRob3V0U3VmZml4ID8gJ9Cz0L7QtNC40L3QsF/Qs9C+0LTQuNC90Lhf0LPQvtC00LjQvScgOiAn0LPQvtC00LjQvdGDX9Cz0L7QtNC40L3QuF/Qs9C+0LTQuNC9JyxcbiAgICAgICAgJ2RkJzogJ9C00LXQvdGMX9C00L3Rll/QtNC90ZbQsicsXG4gICAgICAgICdNTSc6ICfQvNGW0YHRj9GG0Yxf0LzRltGB0Y/RhtGWX9C80ZbRgdGP0YbRltCyJyxcbiAgICAgICAgJ3l5JzogJ9GA0ZbQul/RgNC+0LrQuF/RgNC+0LrRltCyJ1xuICAgIH07XG4gICAgaWYgKGtleSA9PT0gJ20nKSB7XG4gICAgICAgIHJldHVybiB3aXRob3V0U3VmZml4ID8gJ9GF0LLQuNC70LjQvdCwJyA6ICfRhdCy0LjQu9C40L3Rgyc7XG4gICAgfVxuICAgIGVsc2UgaWYgKGtleSA9PT0gJ2gnKSB7XG4gICAgICAgIHJldHVybiB3aXRob3V0U3VmZml4ID8gJ9Cz0L7QtNC40L3QsCcgOiAn0LPQvtC00LjQvdGDJztcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHJldHVybiBudW1iZXIgKyAnICcgKyBwbHVyYWwkNihmb3JtYXRba2V5XSwgK251bWJlcik7XG4gICAgfVxufVxuZnVuY3Rpb24gd2Vla2RheXNDYXNlUmVwbGFjZShtLCBmb3JtYXQpIHtcbiAgICB2YXIgd2Vla2RheXMgPSB7XG4gICAgICAgICdub21pbmF0aXZlJzogJ9C90LXQtNGW0LvRj1/Qv9C+0L3QtdC00ZbQu9C+0Lpf0LLRltCy0YLQvtGA0L7Qul/RgdC10YDQtdC00LBf0YfQtdGC0LLQtdGAX9C/4oCZ0Y/RgtC90LjRhtGPX9GB0YPQsdC+0YLQsCcuc3BsaXQoJ18nKSxcbiAgICAgICAgJ2FjY3VzYXRpdmUnOiAn0L3QtdC00ZbQu9GOX9C/0L7QvdC10LTRltC70L7Qul/QstGW0LLRgtC+0YDQvtC6X9GB0LXRgNC10LTRg1/Rh9C10YLQstC10YBf0L/igJnRj9GC0L3QuNGG0Y5f0YHRg9Cx0L7RgtGDJy5zcGxpdCgnXycpLFxuICAgICAgICAnZ2VuaXRpdmUnOiAn0L3QtdC00ZbQu9GWX9C/0L7QvdC10LTRltC70LrQsF/QstGW0LLRgtC+0YDQutCwX9GB0LXRgNC10LTQuF/Rh9C10YLQstC10YDQs9CwX9C/4oCZ0Y/RgtC90LjRhtGWX9GB0YPQsdC+0YLQuCcuc3BsaXQoJ18nKVxuICAgIH07XG5cbiAgICBpZiAoIW0pIHtcbiAgICAgICAgcmV0dXJuIHdlZWtkYXlzWydub21pbmF0aXZlJ107XG4gICAgfVxuXG4gICAgdmFyIG5vdW5DYXNlID0gKC8oXFxbW9CS0LLQo9GDXVxcXSkgP2RkZGQvKS50ZXN0KGZvcm1hdCkgP1xuICAgICAgICAnYWNjdXNhdGl2ZScgOlxuICAgICAgICAoKC9cXFs/KD860LzQuNC90YPQu9C+0Zd80L3QsNGB0YLRg9C/0L3QvtGXKT8gP1xcXSA/ZGRkZC8pLnRlc3QoZm9ybWF0KSA/XG4gICAgICAgICAgICAnZ2VuaXRpdmUnIDpcbiAgICAgICAgICAgICdub21pbmF0aXZlJyk7XG4gICAgcmV0dXJuIHdlZWtkYXlzW25vdW5DYXNlXVttLmRheSgpXTtcbn1cbmZ1bmN0aW9uIHByb2Nlc3NIb3Vyc0Z1bmN0aW9uKHN0cikge1xuICAgIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBzdHIgKyAn0L4nICsgKHRoaXMuaG91cnMoKSA9PT0gMTEgPyAn0LEnIDogJycpICsgJ10gTFQnO1xuICAgIH07XG59XG5cbmhvb2tzLmRlZmluZUxvY2FsZSgndWsnLCB7XG4gICAgbW9udGhzIDoge1xuICAgICAgICAnZm9ybWF0JzogJ9GB0ZbRh9C90Y9f0LvRjtGC0L7Qs9C+X9Cx0LXRgNC10LfQvdGPX9C60LLRltGC0L3Rj1/RgtGA0LDQstC90Y9f0YfQtdGA0LLQvdGPX9C70LjQv9C90Y9f0YHQtdGA0L/QvdGPX9Cy0LXRgNC10YHQvdGPX9C20L7QstGC0L3Rj1/Qu9C40YHRgtC+0L/QsNC00LBf0LPRgNGD0LTQvdGPJy5zcGxpdCgnXycpLFxuICAgICAgICAnc3RhbmRhbG9uZSc6ICfRgdGW0YfQtdC90Yxf0LvRjtGC0LjQuV/QsdC10YDQtdC30LXQvdGMX9C60LLRltGC0LXQvdGMX9GC0YDQsNCy0LXQvdGMX9GH0LXRgNCy0LXQvdGMX9C70LjQv9C10L3RjF/RgdC10YDQv9C10L3RjF/QstC10YDQtdGB0LXQvdGMX9C20L7QstGC0LXQvdGMX9C70LjRgdGC0L7Qv9Cw0LRf0LPRgNGD0LTQtdC90YwnLnNwbGl0KCdfJylcbiAgICB9LFxuICAgIG1vbnRoc1Nob3J0IDogJ9GB0ZbRh1/Qu9GO0YJf0LHQtdGAX9C60LLRltGCX9GC0YDQsNCyX9GH0LXRgNCyX9C70LjQv1/RgdC10YDQv1/QstC10YBf0LbQvtCy0YJf0LvQuNGB0YJf0LPRgNGD0LQnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXMgOiB3ZWVrZGF5c0Nhc2VSZXBsYWNlLFxuICAgIHdlZWtkYXlzU2hvcnQgOiAn0L3QtF/Qv9C9X9Cy0YJf0YHRgF/Rh9GCX9C/0YJf0YHQsScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbiA6ICfQvdC0X9C/0L1f0LLRgl/RgdGAX9GH0YJf0L/Rgl/RgdCxJy5zcGxpdCgnXycpLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdISDptbScsXG4gICAgICAgIExUUyA6ICdISDptbTpzcycsXG4gICAgICAgIEwgOiAnREQuTU0uWVlZWScsXG4gICAgICAgIExMIDogJ0QgTU1NTSBZWVlZINGALicsXG4gICAgICAgIExMTCA6ICdEIE1NTU0gWVlZWSDRgC4sIEhIOm1tJyxcbiAgICAgICAgTExMTCA6ICdkZGRkLCBEIE1NTU0gWVlZWSDRgC4sIEhIOm1tJ1xuICAgIH0sXG4gICAgY2FsZW5kYXIgOiB7XG4gICAgICAgIHNhbWVEYXk6IHByb2Nlc3NIb3Vyc0Z1bmN0aW9uKCdb0KHRjNC+0LPQvtC00L3RliAnKSxcbiAgICAgICAgbmV4dERheTogcHJvY2Vzc0hvdXJzRnVuY3Rpb24oJ1vQl9Cw0LLRgtGA0LAgJyksXG4gICAgICAgIGxhc3REYXk6IHByb2Nlc3NIb3Vyc0Z1bmN0aW9uKCdb0JLRh9C+0YDQsCAnKSxcbiAgICAgICAgbmV4dFdlZWs6IHByb2Nlc3NIb3Vyc0Z1bmN0aW9uKCdb0KNdIGRkZGQgWycpLFxuICAgICAgICBsYXN0V2VlazogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgc3dpdGNoICh0aGlzLmRheSgpKSB7XG4gICAgICAgICAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgICAgIGNhc2UgMzpcbiAgICAgICAgICAgICAgICBjYXNlIDU6XG4gICAgICAgICAgICAgICAgY2FzZSA2OlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcHJvY2Vzc0hvdXJzRnVuY3Rpb24oJ1vQnNC40L3Rg9C70L7Rl10gZGRkZCBbJykuY2FsbCh0aGlzKTtcbiAgICAgICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgICAgIGNhc2UgNDpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHByb2Nlc3NIb3Vyc0Z1bmN0aW9uKCdb0JzQuNC90YPQu9C+0LPQvl0gZGRkZCBbJykuY2FsbCh0aGlzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgc2FtZUVsc2U6ICdMJ1xuICAgIH0sXG4gICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICBmdXR1cmUgOiAn0LfQsCAlcycsXG4gICAgICAgIHBhc3QgOiAnJXMg0YLQvtC80YMnLFxuICAgICAgICBzIDogJ9C00LXQutGW0LvRjNC60LAg0YHQtdC60YPQvdC0JyxcbiAgICAgICAgc3MgOiByZWxhdGl2ZVRpbWVXaXRoUGx1cmFsJDQsXG4gICAgICAgIG0gOiByZWxhdGl2ZVRpbWVXaXRoUGx1cmFsJDQsXG4gICAgICAgIG1tIDogcmVsYXRpdmVUaW1lV2l0aFBsdXJhbCQ0LFxuICAgICAgICBoIDogJ9Cz0L7QtNC40L3RgycsXG4gICAgICAgIGhoIDogcmVsYXRpdmVUaW1lV2l0aFBsdXJhbCQ0LFxuICAgICAgICBkIDogJ9C00LXQvdGMJyxcbiAgICAgICAgZGQgOiByZWxhdGl2ZVRpbWVXaXRoUGx1cmFsJDQsXG4gICAgICAgIE0gOiAn0LzRltGB0Y/RhtGMJyxcbiAgICAgICAgTU0gOiByZWxhdGl2ZVRpbWVXaXRoUGx1cmFsJDQsXG4gICAgICAgIHkgOiAn0YDRltC6JyxcbiAgICAgICAgeXkgOiByZWxhdGl2ZVRpbWVXaXRoUGx1cmFsJDRcbiAgICB9LFxuICAgIC8vIE0uIEUuOiB0aG9zZSB0d28gYXJlIHZpcnR1YWxseSB1bnVzZWQgYnV0IGEgdXNlciBtaWdodCB3YW50IHRvIGltcGxlbWVudCB0aGVtIGZvciBoaXMvaGVyIHdlYnNpdGUgZm9yIHNvbWUgcmVhc29uXG4gICAgbWVyaWRpZW1QYXJzZTogL9C90L7Rh9GWfNGA0LDQvdC60YN80LTQvdGPfNCy0LXRh9C+0YDQsC8sXG4gICAgaXNQTTogZnVuY3Rpb24gKGlucHV0KSB7XG4gICAgICAgIHJldHVybiAvXijQtNC90Y980LLQtdGH0L7RgNCwKSQvLnRlc3QoaW5wdXQpO1xuICAgIH0sXG4gICAgbWVyaWRpZW0gOiBmdW5jdGlvbiAoaG91ciwgbWludXRlLCBpc0xvd2VyKSB7XG4gICAgICAgIGlmIChob3VyIDwgNCkge1xuICAgICAgICAgICAgcmV0dXJuICfQvdC+0YfRlic7XG4gICAgICAgIH0gZWxzZSBpZiAoaG91ciA8IDEyKSB7XG4gICAgICAgICAgICByZXR1cm4gJ9GA0LDQvdC60YMnO1xuICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAxNykge1xuICAgICAgICAgICAgcmV0dXJuICfQtNC90Y8nO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuICfQstC10YfQvtGA0LAnO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn0tKNC5fNCz0L4pLyxcbiAgICBvcmRpbmFsOiBmdW5jdGlvbiAobnVtYmVyLCBwZXJpb2QpIHtcbiAgICAgICAgc3dpdGNoIChwZXJpb2QpIHtcbiAgICAgICAgICAgIGNhc2UgJ00nOlxuICAgICAgICAgICAgY2FzZSAnZCc6XG4gICAgICAgICAgICBjYXNlICdEREQnOlxuICAgICAgICAgICAgY2FzZSAndyc6XG4gICAgICAgICAgICBjYXNlICdXJzpcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJy3QuSc7XG4gICAgICAgICAgICBjYXNlICdEJzpcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJy3Qs9C+JztcbiAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlcjtcbiAgICAgICAgfVxuICAgIH0sXG4gICAgd2VlayA6IHtcbiAgICAgICAgZG93IDogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgIGRveSA6IDcgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDFzdCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICB9XG59KTtcblxuLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSA6IFVyZHUgW3VyXVxuLy8hIGF1dGhvciA6IFNhd29vZCBBbGFtIDogaHR0cHM6Ly9naXRodWIuY29tL2libmVzYXllZWRcbi8vISBhdXRob3IgOiBaYWNrIDogaHR0cHM6Ly9naXRodWIuY29tL1phY2tWaXNpb25cblxudmFyIG1vbnRocyQ4ID0gW1xuICAgICfYrNmG2YjYsduMJyxcbiAgICAn2YHYsdmI2LHbjCcsXG4gICAgJ9mF2KfYsdqGJyxcbiAgICAn2KfZvtix24zZhCcsXG4gICAgJ9mF2KbbjCcsXG4gICAgJ9is2YjZhicsXG4gICAgJ9is2YjZhNin2KbbjCcsXG4gICAgJ9in2q/Ys9iqJyxcbiAgICAn2LPYqtmF2KjYsScsXG4gICAgJ9in2qnYqtmI2KjYsScsXG4gICAgJ9mG2YjZhdio2LEnLFxuICAgICfYr9iz2YXYqNixJ1xuXTtcbnZhciBkYXlzJDIgPSBbXG4gICAgJ9in2KrZiNin2LEnLFxuICAgICfZvtuM2LEnLFxuICAgICfZhdmG2q/ZhCcsXG4gICAgJ9io2K/avicsXG4gICAgJ9is2YXYudix2KfYqicsXG4gICAgJ9is2YXYuduBJyxcbiAgICAn24HZgdiq24EnXG5dO1xuXG5ob29rcy5kZWZpbmVMb2NhbGUoJ3VyJywge1xuICAgIG1vbnRocyA6IG1vbnRocyQ4LFxuICAgIG1vbnRoc1Nob3J0IDogbW9udGhzJDgsXG4gICAgd2Vla2RheXMgOiBkYXlzJDIsXG4gICAgd2Vla2RheXNTaG9ydCA6IGRheXMkMixcbiAgICB3ZWVrZGF5c01pbiA6IGRheXMkMixcbiAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgTFQgOiAnSEg6bW0nLFxuICAgICAgICBMVFMgOiAnSEg6bW06c3MnLFxuICAgICAgICBMIDogJ0REL01NL1lZWVknLFxuICAgICAgICBMTCA6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgIExMTCA6ICdEIE1NTU0gWVlZWSBISDptbScsXG4gICAgICAgIExMTEwgOiAnZGRkZNiMIEQgTU1NTSBZWVlZIEhIOm1tJ1xuICAgIH0sXG4gICAgbWVyaWRpZW1QYXJzZTogL9i12KjYrXzYtNin2YUvLFxuICAgIGlzUE0gOiBmdW5jdGlvbiAoaW5wdXQpIHtcbiAgICAgICAgcmV0dXJuICfYtNin2YUnID09PSBpbnB1dDtcbiAgICB9LFxuICAgIG1lcmlkaWVtIDogZnVuY3Rpb24gKGhvdXIsIG1pbnV0ZSwgaXNMb3dlcikge1xuICAgICAgICBpZiAoaG91ciA8IDEyKSB7XG4gICAgICAgICAgICByZXR1cm4gJ9i12KjYrSc7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuICfYtNin2YUnO1xuICAgIH0sXG4gICAgY2FsZW5kYXIgOiB7XG4gICAgICAgIHNhbWVEYXkgOiAnW9ii2Kwg2KjZiNmC2KpdIExUJyxcbiAgICAgICAgbmV4dERheSA6ICdb2qnZhCDYqNmI2YLYql0gTFQnLFxuICAgICAgICBuZXh0V2VlayA6ICdkZGRkIFvYqNmI2YLYql0gTFQnLFxuICAgICAgICBsYXN0RGF5IDogJ1var9iw2LTYqtuBINix2YjYsiDYqNmI2YLYql0gTFQnLFxuICAgICAgICBsYXN0V2VlayA6ICdb2q/YsNi02KrbgV0gZGRkZCBb2KjZiNmC2KpdIExUJyxcbiAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJyVzINio2LnYrycsXG4gICAgICAgIHBhc3QgOiAnJXMg2YLYqNmEJyxcbiAgICAgICAgcyA6ICfahtmG2K8g2LPbjNqp2YbaiCcsXG4gICAgICAgIHNzIDogJyVkINiz24zaqdmG2ognLFxuICAgICAgICBtIDogJ9in24zaqSDZhdmG2bknLFxuICAgICAgICBtbSA6ICclZCDZhdmG2bknLFxuICAgICAgICBoIDogJ9in24zaqSDar9q+2YbZuduBJyxcbiAgICAgICAgaGggOiAnJWQg2q/avtmG2bnbkicsXG4gICAgICAgIGQgOiAn2KfbjNqpINiv2YYnLFxuICAgICAgICBkZCA6ICclZCDYr9mGJyxcbiAgICAgICAgTSA6ICfYp9uM2qkg2YXYp9uBJyxcbiAgICAgICAgTU0gOiAnJWQg2YXYp9uBJyxcbiAgICAgICAgeSA6ICfYp9uM2qkg2LPYp9mEJyxcbiAgICAgICAgeXkgOiAnJWQg2LPYp9mEJ1xuICAgIH0sXG4gICAgcHJlcGFyc2U6IGZ1bmN0aW9uIChzdHJpbmcpIHtcbiAgICAgICAgcmV0dXJuIHN0cmluZy5yZXBsYWNlKC/YjC9nLCAnLCcpO1xuICAgIH0sXG4gICAgcG9zdGZvcm1hdDogZnVuY3Rpb24gKHN0cmluZykge1xuICAgICAgICByZXR1cm4gc3RyaW5nLnJlcGxhY2UoLywvZywgJ9iMJyk7XG4gICAgfSxcbiAgICB3ZWVrIDoge1xuICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogNCAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH1cbn0pO1xuXG4vLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogVXpiZWsgTGF0aW4gW3V6LWxhdG5dXG4vLyEgYXV0aG9yIDogUmFzdWxiZWsgTWlyemF5ZXYgOiBnaXRodWIuY29tL1Jhc3VsYmVlZWtcblxuaG9va3MuZGVmaW5lTG9jYWxlKCd1ei1sYXRuJywge1xuICAgIG1vbnRocyA6ICdZYW52YXJfRmV2cmFsX01hcnRfQXByZWxfTWF5X0l5dW5fSXl1bF9Bdmd1c3RfU2VudGFicl9Pa3RhYnJfTm95YWJyX0Rla2Ficicuc3BsaXQoJ18nKSxcbiAgICBtb250aHNTaG9ydCA6ICdZYW5fRmV2X01hcl9BcHJfTWF5X0l5dW5fSXl1bF9BdmdfU2VuX09rdF9Ob3lfRGVrJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzIDogJ1lha3NoYW5iYV9EdXNoYW5iYV9TZXNoYW5iYV9DaG9yc2hhbmJhX1BheXNoYW5iYV9KdW1hX1NoYW5iYScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0IDogJ1lha19EdXNoX1Nlc2hfQ2hvcl9QYXlfSnVtX1NoYW4nLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW4gOiAnWWFfRHVfU2VfQ2hvX1BhX0p1X1NoYScuc3BsaXQoJ18nKSxcbiAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgTFQgOiAnSEg6bW0nLFxuICAgICAgICBMVFMgOiAnSEg6bW06c3MnLFxuICAgICAgICBMIDogJ0REL01NL1lZWVknLFxuICAgICAgICBMTCA6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgIExMTCA6ICdEIE1NTU0gWVlZWSBISDptbScsXG4gICAgICAgIExMTEwgOiAnRCBNTU1NIFlZWVksIGRkZGQgSEg6bW0nXG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheSA6ICdbQnVndW4gc29hdF0gTFQgW2RhXScsXG4gICAgICAgIG5leHREYXkgOiAnW0VydGFnYV0gTFQgW2RhXScsXG4gICAgICAgIG5leHRXZWVrIDogJ2RkZGQgW2t1bmkgc29hdF0gTFQgW2RhXScsXG4gICAgICAgIGxhc3REYXkgOiAnW0tlY2hhIHNvYXRdIExUIFtkYV0nLFxuICAgICAgICBsYXN0V2VlayA6ICdbT1xcJ3RnYW5dIGRkZGQgW2t1bmkgc29hdF0gTFQgW2RhXScsXG4gICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6ICdZYXFpbiAlcyBpY2hpZGEnLFxuICAgICAgICBwYXN0IDogJ0JpciBuZWNoYSAlcyBvbGRpbicsXG4gICAgICAgIHMgOiAnc29uaXlhJyxcbiAgICAgICAgc3MgOiAnJWQgc29uaXlhJyxcbiAgICAgICAgbSA6ICdiaXIgZGFxaXFhJyxcbiAgICAgICAgbW0gOiAnJWQgZGFxaXFhJyxcbiAgICAgICAgaCA6ICdiaXIgc29hdCcsXG4gICAgICAgIGhoIDogJyVkIHNvYXQnLFxuICAgICAgICBkIDogJ2JpciBrdW4nLFxuICAgICAgICBkZCA6ICclZCBrdW4nLFxuICAgICAgICBNIDogJ2JpciBveScsXG4gICAgICAgIE1NIDogJyVkIG95JyxcbiAgICAgICAgeSA6ICdiaXIgeWlsJyxcbiAgICAgICAgeXkgOiAnJWQgeWlsJ1xuICAgIH0sXG4gICAgd2VlayA6IHtcbiAgICAgICAgZG93IDogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgIGRveSA6IDcgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDFzdCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICB9XG59KTtcblxuLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSA6IFV6YmVrIFt1el1cbi8vISBhdXRob3IgOiBTYXJkb3IgTXVtaW5vdiA6IGh0dHBzOi8vZ2l0aHViLmNvbS9tdW1pbm9mZlxuXG5ob29rcy5kZWZpbmVMb2NhbGUoJ3V6Jywge1xuICAgIG1vbnRocyA6ICfRj9C90LLQsNGAX9GE0LXQstGA0LDQu1/QvNCw0YDRgl/QsNC/0YDQtdC7X9C80LDQuV/QuNGO0L1f0LjRjtC7X9Cw0LLQs9GD0YHRgl/RgdC10L3RgtGP0LHRgF/QvtC60YLRj9Cx0YBf0L3QvtGP0LHRgF/QtNC10LrQsNCx0YAnLnNwbGl0KCdfJyksXG4gICAgbW9udGhzU2hvcnQgOiAn0Y/QvdCyX9GE0LXQsl/QvNCw0YBf0LDQv9GAX9C80LDQuV/QuNGO0L1f0LjRjtC7X9Cw0LLQs1/RgdC10L1f0L7QutGCX9C90L7Rj1/QtNC10LonLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXMgOiAn0K/QutGI0LDQvdCx0LBf0JTRg9GI0LDQvdCx0LBf0KHQtdGI0LDQvdCx0LBf0KfQvtGA0YjQsNC90LHQsF/Qn9Cw0LnRiNCw0L3QsdCwX9CW0YPQvNCwX9Co0LDQvdCx0LAnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydCA6ICfQr9C60Yhf0JTRg9GIX9Ch0LXRiF/Qp9C+0YBf0J/QsNC5X9CW0YPQvF/QqNCw0L0nLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW4gOiAn0K/Qul/QlNGDX9Ch0LVf0KfQvl/Qn9CwX9CW0YNf0KjQsCcuc3BsaXQoJ18nKSxcbiAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgTFQgOiAnSEg6bW0nLFxuICAgICAgICBMVFMgOiAnSEg6bW06c3MnLFxuICAgICAgICBMIDogJ0REL01NL1lZWVknLFxuICAgICAgICBMTCA6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgIExMTCA6ICdEIE1NTU0gWVlZWSBISDptbScsXG4gICAgICAgIExMTEwgOiAnRCBNTU1NIFlZWVksIGRkZGQgSEg6bW0nXG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheSA6ICdb0JHRg9Cz0YPQvSDRgdC+0LDRgl0gTFQgW9C00LBdJyxcbiAgICAgICAgbmV4dERheSA6ICdb0K3RgNGC0LDQs9CwXSBMVCBb0LTQsF0nLFxuICAgICAgICBuZXh0V2VlayA6ICdkZGRkIFvQutGD0L3QuCDRgdC+0LDRgl0gTFQgW9C00LBdJyxcbiAgICAgICAgbGFzdERheSA6ICdb0JrQtdGH0LAg0YHQvtCw0YJdIExUIFvQtNCwXScsXG4gICAgICAgIGxhc3RXZWVrIDogJ1vQo9GC0LPQsNC9XSBkZGRkIFvQutGD0L3QuCDRgdC+0LDRgl0gTFQgW9C00LBdJyxcbiAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJ9Cv0LrQuNC9ICVzINC40YfQuNC00LAnLFxuICAgICAgICBwYXN0IDogJ9CR0LjRgCDQvdC10YfQsCAlcyDQvtC70LTQuNC9JyxcbiAgICAgICAgcyA6ICfRhNGD0YDRgdCw0YInLFxuICAgICAgICBzcyA6ICclZCDRhNGD0YDRgdCw0YInLFxuICAgICAgICBtIDogJ9Cx0LjRgCDQtNCw0LrQuNC60LAnLFxuICAgICAgICBtbSA6ICclZCDQtNCw0LrQuNC60LAnLFxuICAgICAgICBoIDogJ9Cx0LjRgCDRgdC+0LDRgicsXG4gICAgICAgIGhoIDogJyVkINGB0L7QsNGCJyxcbiAgICAgICAgZCA6ICfQsdC40YAg0LrRg9C9JyxcbiAgICAgICAgZGQgOiAnJWQg0LrRg9C9JyxcbiAgICAgICAgTSA6ICfQsdC40YAg0L7QuScsXG4gICAgICAgIE1NIDogJyVkINC+0LknLFxuICAgICAgICB5IDogJ9Cx0LjRgCDQudC40LsnLFxuICAgICAgICB5eSA6ICclZCDQudC40LsnXG4gICAgfSxcbiAgICB3ZWVrIDoge1xuICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogNyAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH1cbn0pO1xuXG4vLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogVmlldG5hbWVzZSBbdmldXG4vLyEgYXV0aG9yIDogQmFuZyBOZ3V5ZW4gOiBodHRwczovL2dpdGh1Yi5jb20vYmFuZ25rXG5cbmhvb2tzLmRlZmluZUxvY2FsZSgndmknLCB7XG4gICAgbW9udGhzIDogJ3Row6FuZyAxX3Row6FuZyAyX3Row6FuZyAzX3Row6FuZyA0X3Row6FuZyA1X3Row6FuZyA2X3Row6FuZyA3X3Row6FuZyA4X3Row6FuZyA5X3Row6FuZyAxMF90aMOhbmcgMTFfdGjDoW5nIDEyJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0IDogJ1RoMDFfVGgwMl9UaDAzX1RoMDRfVGgwNV9UaDA2X1RoMDdfVGgwOF9UaDA5X1RoMTBfVGgxMV9UaDEyJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgIHdlZWtkYXlzIDogJ2No4bunIG5o4bqtdF90aOG7qSBoYWlfdGjhu6kgYmFfdGjhu6kgdMawX3Ro4bupIG7Eg21fdGjhu6kgc8OhdV90aOG7qSBi4bqjeScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0IDogJ0NOX1QyX1QzX1Q0X1Q1X1Q2X1Q3Jy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzTWluIDogJ0NOX1QyX1QzX1Q0X1Q1X1Q2X1Q3Jy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzUGFyc2VFeGFjdCA6IHRydWUsXG4gICAgbWVyaWRpZW1QYXJzZTogL3NhfGNoL2ksXG4gICAgaXNQTSA6IGZ1bmN0aW9uIChpbnB1dCkge1xuICAgICAgICByZXR1cm4gL15jaCQvaS50ZXN0KGlucHV0KTtcbiAgICB9LFxuICAgIG1lcmlkaWVtIDogZnVuY3Rpb24gKGhvdXJzLCBtaW51dGVzLCBpc0xvd2VyKSB7XG4gICAgICAgIGlmIChob3VycyA8IDEyKSB7XG4gICAgICAgICAgICByZXR1cm4gaXNMb3dlciA/ICdzYScgOiAnU0EnO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIGlzTG93ZXIgPyAnY2gnIDogJ0NIJztcbiAgICAgICAgfVxuICAgIH0sXG4gICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgIExUIDogJ0hIOm1tJyxcbiAgICAgICAgTFRTIDogJ0hIOm1tOnNzJyxcbiAgICAgICAgTCA6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgTEwgOiAnRCBNTU1NIFtuxINtXSBZWVlZJyxcbiAgICAgICAgTExMIDogJ0QgTU1NTSBbbsSDbV0gWVlZWSBISDptbScsXG4gICAgICAgIExMTEwgOiAnZGRkZCwgRCBNTU1NIFtuxINtXSBZWVlZIEhIOm1tJyxcbiAgICAgICAgbCA6ICdERC9NL1lZWVknLFxuICAgICAgICBsbCA6ICdEIE1NTSBZWVlZJyxcbiAgICAgICAgbGxsIDogJ0QgTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICBsbGxsIDogJ2RkZCwgRCBNTU0gWVlZWSBISDptbSdcbiAgICB9LFxuICAgIGNhbGVuZGFyIDoge1xuICAgICAgICBzYW1lRGF5OiAnW0jDtG0gbmF5IGzDumNdIExUJyxcbiAgICAgICAgbmV4dERheTogJ1tOZ8OgeSBtYWkgbMO6Y10gTFQnLFxuICAgICAgICBuZXh0V2VlazogJ2RkZGQgW3R14bqnbiB04bubaSBsw7pjXSBMVCcsXG4gICAgICAgIGxhc3REYXk6ICdbSMO0bSBxdWEgbMO6Y10gTFQnLFxuICAgICAgICBsYXN0V2VlazogJ2RkZGQgW3R14bqnbiBy4buTaSBsw7pjXSBMVCcsXG4gICAgICAgIHNhbWVFbHNlOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJyVzIHThu5tpJyxcbiAgICAgICAgcGFzdCA6ICclcyB0csaw4bubYycsXG4gICAgICAgIHMgOiAndsOgaSBnacOieScsXG4gICAgICAgIHNzIDogJyVkIGdpw6J5JyAsXG4gICAgICAgIG0gOiAnbeG7mXQgcGjDunQnLFxuICAgICAgICBtbSA6ICclZCBwaMO6dCcsXG4gICAgICAgIGggOiAnbeG7mXQgZ2nhu50nLFxuICAgICAgICBoaCA6ICclZCBnaeG7nScsXG4gICAgICAgIGQgOiAnbeG7mXQgbmfDoHknLFxuICAgICAgICBkZCA6ICclZCBuZ8OgeScsXG4gICAgICAgIE0gOiAnbeG7mXQgdGjDoW5nJyxcbiAgICAgICAgTU0gOiAnJWQgdGjDoW5nJyxcbiAgICAgICAgeSA6ICdt4buZdCBuxINtJyxcbiAgICAgICAgeXkgOiAnJWQgbsSDbSdcbiAgICB9LFxuICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfS8sXG4gICAgb3JkaW5hbCA6IGZ1bmN0aW9uIChudW1iZXIpIHtcbiAgICAgICAgcmV0dXJuIG51bWJlcjtcbiAgICB9LFxuICAgIHdlZWsgOiB7XG4gICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICBkb3kgOiA0ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgfVxufSk7XG5cbi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBQc2V1ZG8gW3gtcHNldWRvXVxuLy8hIGF1dGhvciA6IEFuZHJldyBIb29kIDogaHR0cHM6Ly9naXRodWIuY29tL2FuZHJld2hvb2QxMjVcblxuaG9va3MuZGVmaW5lTG9jYWxlKCd4LXBzZXVkbycsIHtcbiAgICBtb250aHMgOiAnSn7DocOxw7rDoX5yw71fRn7DqWJyw7p+w6Fyw71ffk3DoXJjfmhfw4FwfnLDrWxffk3DocO9X35Kw7rDscOpfl9Kw7psfsO9X8OBw7p+Z8O6c3R+X1PDqXB+dMOpbWJ+w6lyX8OTfmN0w7NifsOpcl/DkX7Ds3bDqW1+YsOpcl9+RMOpY8Opfm1iw6lyJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0IDogJ0p+w6HDsV9+RsOpYl9+TcOhcl9+w4Fwcl9+TcOhw71ffkrDusOxX35Kw7psX37DgcO6Z19+U8OpcF9+w5NjdF9+w5HDs3ZffkTDqWMnLnNwbGl0KCdfJyksXG4gICAgbW9udGhzUGFyc2VFeGFjdCA6IHRydWUsXG4gICAgd2Vla2RheXMgOiAnU37DusOxZMOhfsO9X03Ds37DsWTDocO9fl9Uw7rDqX5zZMOhw71+X1fDqWR+w7HDqXNkfsOhw71fVH5ow7pyc35kw6HDvV9+RnLDrWR+w6HDvV9TfsOhdMO6cn5kw6HDvScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0IDogJ1N+w7rDsV9+TcOzw7FfflTDusOpX35Xw6lkX35UaMO6X35GcsOtX35Tw6F0Jy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzTWluIDogJ1N+w7pfTcOzfl9Uw7pfflfDqV9UfmhfRnJ+X1PDoScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdISDptbScsXG4gICAgICAgIEwgOiAnREQvTU0vWVlZWScsXG4gICAgICAgIExMIDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgTExMIDogJ0QgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgTExMTCA6ICdkZGRkLCBEIE1NTU0gWVlZWSBISDptbSdcbiAgICB9LFxuICAgIGNhbGVuZGFyIDoge1xuICAgICAgICBzYW1lRGF5IDogJ1tUfsOzZMOhfsO9IMOhdF0gTFQnLFxuICAgICAgICBuZXh0RGF5IDogJ1tUfsOzbcOzfnJyw7N+dyDDoXRdIExUJyxcbiAgICAgICAgbmV4dFdlZWsgOiAnZGRkZCBbw6F0XSBMVCcsXG4gICAgICAgIGxhc3REYXkgOiAnW8OdfsOpc3R+w6lyZMOhfsO9IMOhdF0gTFQnLFxuICAgICAgICBsYXN0V2VlayA6ICdbTH7DoXN0XSBkZGRkIFvDoXRdIExUJyxcbiAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJ8OtfsOxICVzJyxcbiAgICAgICAgcGFzdCA6ICclcyDDoX5nw7MnLFxuICAgICAgICBzIDogJ8OhIH5mw6l3IH5zw6ljw7N+w7FkcycsXG4gICAgICAgIHNzIDogJyVkIHN+w6ljw7PDsX5kcycsXG4gICAgICAgIG0gOiAnw6Egfm3DrcOxfsO6dMOpJyxcbiAgICAgICAgbW0gOiAnJWQgbX7DrcOxw7p+dMOpcycsXG4gICAgICAgIGggOiAnw6F+w7EgaMOzfsO6cicsXG4gICAgICAgIGhoIDogJyVkIGh+w7PDunJzJyxcbiAgICAgICAgZCA6ICfDoSB+ZMOhw70nLFxuICAgICAgICBkZCA6ICclZCBkfsOhw71zJyxcbiAgICAgICAgTSA6ICfDoSB+bcOzw7F+dGgnLFxuICAgICAgICBNTSA6ICclZCBtfsOzw7F0fmhzJyxcbiAgICAgICAgeSA6ICfDoSB+w73DqcOhcicsXG4gICAgICAgIHl5IDogJyVkIMO9fsOpw6FycydcbiAgICB9LFxuICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfSh0aHxzdHxuZHxyZCkvLFxuICAgIG9yZGluYWwgOiBmdW5jdGlvbiAobnVtYmVyKSB7XG4gICAgICAgIHZhciBiID0gbnVtYmVyICUgMTAsXG4gICAgICAgICAgICBvdXRwdXQgPSAofn4obnVtYmVyICUgMTAwIC8gMTApID09PSAxKSA/ICd0aCcgOlxuICAgICAgICAgICAgKGIgPT09IDEpID8gJ3N0JyA6XG4gICAgICAgICAgICAoYiA9PT0gMikgPyAnbmQnIDpcbiAgICAgICAgICAgIChiID09PSAzKSA/ICdyZCcgOiAndGgnO1xuICAgICAgICByZXR1cm4gbnVtYmVyICsgb3V0cHV0O1xuICAgIH0sXG4gICAgd2VlayA6IHtcbiAgICAgICAgZG93IDogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgIGRveSA6IDQgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDR0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICB9XG59KTtcblxuLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSA6IFlvcnViYSBOaWdlcmlhIFt5b11cbi8vISBhdXRob3IgOiBBdG9sYWdiZSBBYmlzb3llIDogaHR0cHM6Ly9naXRodWIuY29tL2FuZGVsYS1iYXRvbGFnYmVcblxuaG9va3MuZGVmaW5lTG9jYWxlKCd5bycsIHtcbiAgICBtb250aHMgOiAnU+G6ucyBcuG6ucyBX0XMgHJlzIBsZcyAX+G6uHLhurnMgG5hzIBfScyAZ2JlzIFfRcyAYmliaV9PzIBrdcyAZHVfQWfhurltb19PzIBndcyBbl9Pd2V3ZV/hu4zMgHdhzIByYcyAX0JlzIFsdcyBX+G7jMyAcOG6ucyAzIAnLnNwbGl0KCdfJyksXG4gICAgbW9udGhzU2hvcnQgOiAnU+G6ucyBcl9FzIBybF/hurhybl9JzIBnYl9FzIBiaV9PzIBrdcyAX0Fn4bq5X0/MgGd1zIFfT3dlX+G7jMyAd2HMgF9CZcyBbF/hu4zMgHDhurnMgMyAJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzIDogJ0HMgGnMgGt1zIFfQWplzIFfScyAc+G6ucyBZ3VuX+G7jGrhu43MgXJ1zIFf4buMauG7jcyBYuG7jV/hurh0acyAX0HMgGJhzIFt4bq5zIF0YScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0IDogJ0HMgGnMgGtfQWplzIFfScyAc+G6ucyBX+G7jGpyX+G7jGpiX+G6uHRpzIBfQcyAYmHMgScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbiA6ICdBzIBpzIBfQWpfScyAc1/hu4xyX+G7jGJf4bq4dF9BzIBiJy5zcGxpdCgnXycpLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdoOm1tIEEnLFxuICAgICAgICBMVFMgOiAnaDptbTpzcyBBJyxcbiAgICAgICAgTCA6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgTEwgOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICBMTEwgOiAnRCBNTU1NIFlZWVkgaDptbSBBJyxcbiAgICAgICAgTExMTCA6ICdkZGRkLCBEIE1NTU0gWVlZWSBoOm1tIEEnXG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheSA6ICdbT8yAbmnMgCBuaV0gTFQnLFxuICAgICAgICBuZXh0RGF5IDogJ1vhu4zMgGxhIG5pXSBMVCcsXG4gICAgICAgIG5leHRXZWVrIDogJ2RkZGQgW+G7jHPhurnMgCB0b8yBblxcJ2Lhu41dIFtuaV0gTFQnLFxuICAgICAgICBsYXN0RGF5IDogJ1tBzIBuYSBuaV0gTFQnLFxuICAgICAgICBsYXN0V2VlayA6ICdkZGRkIFvhu4xz4bq5zIAgdG/MgWzhu43MgV0gW25pXSBMVCcsXG4gICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6ICduacyBICVzJyxcbiAgICAgICAgcGFzdCA6ICclcyBr4buNamHMgScsXG4gICAgICAgIHMgOiAnacyAc+G6uWp1zIEgYWF5YcyBIGRpZScsXG4gICAgICAgIHNzIDonYWF5YcyBICVkJyxcbiAgICAgICAgbSA6ICdpzIBz4bq5anXMgSBrYW4nLFxuICAgICAgICBtbSA6ICdpzIBz4bq5anXMgSAlZCcsXG4gICAgICAgIGggOiAnd2HMgWthdGkga2FuJyxcbiAgICAgICAgaGggOiAnd2HMgWthdGkgJWQnLFxuICAgICAgICBkIDogJ+G7jWrhu43MgSBrYW4nLFxuICAgICAgICBkZCA6ICfhu41q4buNzIEgJWQnLFxuICAgICAgICBNIDogJ29zdcyAIGthbicsXG4gICAgICAgIE1NIDogJ29zdcyAICVkJyxcbiAgICAgICAgeSA6ICfhu41kdcyBbiBrYW4nLFxuICAgICAgICB5eSA6ICfhu41kdcyBbiAlZCdcbiAgICB9LFxuICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2UgOiAv4buNauG7jcyBXFxzXFxkezEsMn0vLFxuICAgIG9yZGluYWwgOiAn4buNauG7jcyBICVkJyxcbiAgICB3ZWVrIDoge1xuICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogNCAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgfVxufSk7XG5cbi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBDaGluZXNlIChDaGluYSkgW3poLWNuXVxuLy8hIGF1dGhvciA6IHN1dXBpYyA6IGh0dHBzOi8vZ2l0aHViLmNvbS9zdXVwaWNcbi8vISBhdXRob3IgOiBaZW5vIFplbmcgOiBodHRwczovL2dpdGh1Yi5jb20vemVub3plbmdcblxuaG9va3MuZGVmaW5lTG9jYWxlKCd6aC1jbicsIHtcbiAgICBtb250aHMgOiAn5LiA5pyIX+S6jOaciF/kuInmnIhf5Zub5pyIX+S6lOaciF/lha3mnIhf5LiD5pyIX+WFq+aciF/kuZ3mnIhf5Y2B5pyIX+WNgeS4gOaciF/ljYHkuozmnIgnLnNwbGl0KCdfJyksXG4gICAgbW9udGhzU2hvcnQgOiAnMeaciF8y5pyIXzPmnIhfNOaciF815pyIXzbmnIhfN+aciF845pyIXznmnIhfMTDmnIhfMTHmnIhfMTLmnIgnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXMgOiAn5pif5pyf5pelX+aYn+acn+S4gF/mmJ/mnJ/kuoxf5pif5pyf5LiJX+aYn+acn+Wbm1/mmJ/mnJ/kupRf5pif5pyf5YWtJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzU2hvcnQgOiAn5ZGo5pelX+WRqOS4gF/lkajkuoxf5ZGo5LiJX+WRqOWbm1/lkajkupRf5ZGo5YWtJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzTWluIDogJ+aXpV/kuIBf5LqMX+S4iV/lm5tf5LqUX+WFrScuc3BsaXQoJ18nKSxcbiAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgTFQgOiAnSEg6bW0nLFxuICAgICAgICBMVFMgOiAnSEg6bW06c3MnLFxuICAgICAgICBMIDogJ1lZWVkvTU0vREQnLFxuICAgICAgICBMTCA6ICdZWVlZ5bm0TeaciETml6UnLFxuICAgICAgICBMTEwgOiAnWVlZWeW5tE3mnIhE5pelQWjngrltbeWIhicsXG4gICAgICAgIExMTEwgOiAnWVlZWeW5tE3mnIhE5pelZGRkZEFo54K5bW3liIYnLFxuICAgICAgICBsIDogJ1lZWVkvTS9EJyxcbiAgICAgICAgbGwgOiAnWVlZWeW5tE3mnIhE5pelJyxcbiAgICAgICAgbGxsIDogJ1lZWVnlubRN5pyIROaXpSBISDptbScsXG4gICAgICAgIGxsbGwgOiAnWVlZWeW5tE3mnIhE5pelZGRkZCBISDptbSdcbiAgICB9LFxuICAgIG1lcmlkaWVtUGFyc2U6IC/lh4zmmah85pep5LiKfOS4iuWNiHzkuK3ljYh85LiL5Y2IfOaZmuS4ii8sXG4gICAgbWVyaWRpZW1Ib3VyOiBmdW5jdGlvbiAoaG91ciwgbWVyaWRpZW0pIHtcbiAgICAgICAgaWYgKGhvdXIgPT09IDEyKSB7XG4gICAgICAgICAgICBob3VyID0gMDtcbiAgICAgICAgfVxuICAgICAgICBpZiAobWVyaWRpZW0gPT09ICflh4zmmagnIHx8IG1lcmlkaWVtID09PSAn5pep5LiKJyB8fFxuICAgICAgICAgICAgICAgIG1lcmlkaWVtID09PSAn5LiK5Y2IJykge1xuICAgICAgICAgICAgcmV0dXJuIGhvdXI7XG4gICAgICAgIH0gZWxzZSBpZiAobWVyaWRpZW0gPT09ICfkuIvljYgnIHx8IG1lcmlkaWVtID09PSAn5pma5LiKJykge1xuICAgICAgICAgICAgcmV0dXJuIGhvdXIgKyAxMjtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vICfkuK3ljYgnXG4gICAgICAgICAgICByZXR1cm4gaG91ciA+PSAxMSA/IGhvdXIgOiBob3VyICsgMTI7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIG1lcmlkaWVtIDogZnVuY3Rpb24gKGhvdXIsIG1pbnV0ZSwgaXNMb3dlcikge1xuICAgICAgICB2YXIgaG0gPSBob3VyICogMTAwICsgbWludXRlO1xuICAgICAgICBpZiAoaG0gPCA2MDApIHtcbiAgICAgICAgICAgIHJldHVybiAn5YeM5pmoJztcbiAgICAgICAgfSBlbHNlIGlmIChobSA8IDkwMCkge1xuICAgICAgICAgICAgcmV0dXJuICfml6nkuIonO1xuICAgICAgICB9IGVsc2UgaWYgKGhtIDwgMTEzMCkge1xuICAgICAgICAgICAgcmV0dXJuICfkuIrljYgnO1xuICAgICAgICB9IGVsc2UgaWYgKGhtIDwgMTIzMCkge1xuICAgICAgICAgICAgcmV0dXJuICfkuK3ljYgnO1xuICAgICAgICB9IGVsc2UgaWYgKGhtIDwgMTgwMCkge1xuICAgICAgICAgICAgcmV0dXJuICfkuIvljYgnO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuICfmmZrkuIonO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheSA6ICdb5LuK5aSpXUxUJyxcbiAgICAgICAgbmV4dERheSA6ICdb5piO5aSpXUxUJyxcbiAgICAgICAgbmV4dFdlZWsgOiAnW+S4i11kZGRkTFQnLFxuICAgICAgICBsYXN0RGF5IDogJ1vmmKjlpKldTFQnLFxuICAgICAgICBsYXN0V2VlayA6ICdb5LiKXWRkZGRMVCcsXG4gICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgfSxcbiAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn0o5pelfOaciHzlkagpLyxcbiAgICBvcmRpbmFsIDogZnVuY3Rpb24gKG51bWJlciwgcGVyaW9kKSB7XG4gICAgICAgIHN3aXRjaCAocGVyaW9kKSB7XG4gICAgICAgICAgICBjYXNlICdkJzpcbiAgICAgICAgICAgIGNhc2UgJ0QnOlxuICAgICAgICAgICAgY2FzZSAnREREJzpcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJ+aXpSc7XG4gICAgICAgICAgICBjYXNlICdNJzpcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJ+aciCc7XG4gICAgICAgICAgICBjYXNlICd3JzpcbiAgICAgICAgICAgIGNhc2UgJ1cnOlxuICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAn5ZGoJztcbiAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlcjtcbiAgICAgICAgfVxuICAgIH0sXG4gICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICBmdXR1cmUgOiAnJXPlhoUnLFxuICAgICAgICBwYXN0IDogJyVz5YmNJyxcbiAgICAgICAgcyA6ICflh6Dnp5InLFxuICAgICAgICBzcyA6ICclZCDnp5InLFxuICAgICAgICBtIDogJzEg5YiG6ZKfJyxcbiAgICAgICAgbW0gOiAnJWQg5YiG6ZKfJyxcbiAgICAgICAgaCA6ICcxIOWwj+aXticsXG4gICAgICAgIGhoIDogJyVkIOWwj+aXticsXG4gICAgICAgIGQgOiAnMSDlpKknLFxuICAgICAgICBkZCA6ICclZCDlpKknLFxuICAgICAgICBNIDogJzEg5Liq5pyIJyxcbiAgICAgICAgTU0gOiAnJWQg5Liq5pyIJyxcbiAgICAgICAgeSA6ICcxIOW5tCcsXG4gICAgICAgIHl5IDogJyVkIOW5tCdcbiAgICB9LFxuICAgIHdlZWsgOiB7XG4gICAgICAgIC8vIEdCL1QgNzQwOC0xOTk044CK5pWw5o2u5YWD5ZKM5Lqk5o2i5qC85byPwrfkv6Hmga/kuqTmjaLCt+aXpeacn+WSjOaXtumXtOihqOekuuazleOAi+S4jklTTyA4NjAxOjE5ODjnrYnmlYhcbiAgICAgICAgZG93IDogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgIGRveSA6IDQgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDR0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICB9XG59KTtcblxuLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSA6IENoaW5lc2UgKEhvbmcgS29uZykgW3poLWhrXVxuLy8hIGF1dGhvciA6IEJlbiA6IGh0dHBzOi8vZ2l0aHViLmNvbS9iZW4tbGluXG4vLyEgYXV0aG9yIDogQ2hyaXMgTGFtIDogaHR0cHM6Ly9naXRodWIuY29tL2hlaGFjaHJpc1xuLy8hIGF1dGhvciA6IEtvbnN0YW50aW4gOiBodHRwczovL2dpdGh1Yi5jb20vc2tmZFxuXG5ob29rcy5kZWZpbmVMb2NhbGUoJ3poLWhrJywge1xuICAgIG1vbnRocyA6ICfkuIDmnIhf5LqM5pyIX+S4ieaciF/lm5vmnIhf5LqU5pyIX+WFreaciF/kuIPmnIhf5YWr5pyIX+S5neaciF/ljYHmnIhf5Y2B5LiA5pyIX+WNgeS6jOaciCcuc3BsaXQoJ18nKSxcbiAgICBtb250aHNTaG9ydCA6ICcx5pyIXzLmnIhfM+aciF805pyIXzXmnIhfNuaciF835pyIXzjmnIhfOeaciF8xMOaciF8xMeaciF8xMuaciCcuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5cyA6ICfmmJ/mnJ/ml6Vf5pif5pyf5LiAX+aYn+acn+S6jF/mmJ/mnJ/kuIlf5pif5pyf5ZubX+aYn+acn+S6lF/mmJ/mnJ/lha0nLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydCA6ICfpgLHml6Vf6YCx5LiAX+mAseS6jF/pgLHkuIlf6YCx5ZubX+mAseS6lF/pgLHlha0nLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW4gOiAn5pelX+S4gF/kuoxf5LiJX+Wbm1/kupRf5YWtJy5zcGxpdCgnXycpLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdISDptbScsXG4gICAgICAgIExUUyA6ICdISDptbTpzcycsXG4gICAgICAgIEwgOiAnWVlZWS9NTS9ERCcsXG4gICAgICAgIExMIDogJ1lZWVnlubRN5pyIROaXpScsXG4gICAgICAgIExMTCA6ICdZWVlZ5bm0TeaciETml6UgSEg6bW0nLFxuICAgICAgICBMTExMIDogJ1lZWVnlubRN5pyIROaXpWRkZGQgSEg6bW0nLFxuICAgICAgICBsIDogJ1lZWVkvTS9EJyxcbiAgICAgICAgbGwgOiAnWVlZWeW5tE3mnIhE5pelJyxcbiAgICAgICAgbGxsIDogJ1lZWVnlubRN5pyIROaXpSBISDptbScsXG4gICAgICAgIGxsbGwgOiAnWVlZWeW5tE3mnIhE5pelZGRkZCBISDptbSdcbiAgICB9LFxuICAgIG1lcmlkaWVtUGFyc2U6IC/lh4zmmah85pep5LiKfOS4iuWNiHzkuK3ljYh85LiL5Y2IfOaZmuS4ii8sXG4gICAgbWVyaWRpZW1Ib3VyIDogZnVuY3Rpb24gKGhvdXIsIG1lcmlkaWVtKSB7XG4gICAgICAgIGlmIChob3VyID09PSAxMikge1xuICAgICAgICAgICAgaG91ciA9IDA7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG1lcmlkaWVtID09PSAn5YeM5pmoJyB8fCBtZXJpZGllbSA9PT0gJ+aXqeS4iicgfHwgbWVyaWRpZW0gPT09ICfkuIrljYgnKSB7XG4gICAgICAgICAgICByZXR1cm4gaG91cjtcbiAgICAgICAgfSBlbHNlIGlmIChtZXJpZGllbSA9PT0gJ+S4reWNiCcpIHtcbiAgICAgICAgICAgIHJldHVybiBob3VyID49IDExID8gaG91ciA6IGhvdXIgKyAxMjtcbiAgICAgICAgfSBlbHNlIGlmIChtZXJpZGllbSA9PT0gJ+S4i+WNiCcgfHwgbWVyaWRpZW0gPT09ICfmmZrkuIonKSB7XG4gICAgICAgICAgICByZXR1cm4gaG91ciArIDEyO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBtZXJpZGllbSA6IGZ1bmN0aW9uIChob3VyLCBtaW51dGUsIGlzTG93ZXIpIHtcbiAgICAgICAgdmFyIGhtID0gaG91ciAqIDEwMCArIG1pbnV0ZTtcbiAgICAgICAgaWYgKGhtIDwgNjAwKSB7XG4gICAgICAgICAgICByZXR1cm4gJ+WHjOaZqCc7XG4gICAgICAgIH0gZWxzZSBpZiAoaG0gPCA5MDApIHtcbiAgICAgICAgICAgIHJldHVybiAn5pep5LiKJztcbiAgICAgICAgfSBlbHNlIGlmIChobSA8IDExMzApIHtcbiAgICAgICAgICAgIHJldHVybiAn5LiK5Y2IJztcbiAgICAgICAgfSBlbHNlIGlmIChobSA8IDEyMzApIHtcbiAgICAgICAgICAgIHJldHVybiAn5Lit5Y2IJztcbiAgICAgICAgfSBlbHNlIGlmIChobSA8IDE4MDApIHtcbiAgICAgICAgICAgIHJldHVybiAn5LiL5Y2IJztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiAn5pma5LiKJztcbiAgICAgICAgfVxuICAgIH0sXG4gICAgY2FsZW5kYXIgOiB7XG4gICAgICAgIHNhbWVEYXkgOiAnW+S7iuWkqV1MVCcsXG4gICAgICAgIG5leHREYXkgOiAnW+aYjuWkqV1MVCcsXG4gICAgICAgIG5leHRXZWVrIDogJ1vkuItdZGRkZExUJyxcbiAgICAgICAgbGFzdERheSA6ICdb5pio5aSpXUxUJyxcbiAgICAgICAgbGFzdFdlZWsgOiAnW+S4il1kZGRkTFQnLFxuICAgICAgICBzYW1lRWxzZSA6ICdMJ1xuICAgIH0sXG4gICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9KOaXpXzmnIh86YCxKS8sXG4gICAgb3JkaW5hbCA6IGZ1bmN0aW9uIChudW1iZXIsIHBlcmlvZCkge1xuICAgICAgICBzd2l0Y2ggKHBlcmlvZCkge1xuICAgICAgICAgICAgY2FzZSAnZCcgOlxuICAgICAgICAgICAgY2FzZSAnRCcgOlxuICAgICAgICAgICAgY2FzZSAnREREJyA6XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICfml6UnO1xuICAgICAgICAgICAgY2FzZSAnTScgOlxuICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAn5pyIJztcbiAgICAgICAgICAgIGNhc2UgJ3cnIDpcbiAgICAgICAgICAgIGNhc2UgJ1cnIDpcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJ+mAsSc7XG4gICAgICAgICAgICBkZWZhdWx0IDpcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyO1xuICAgICAgICB9XG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6ICclc+WFpycsXG4gICAgICAgIHBhc3QgOiAnJXPliY0nLFxuICAgICAgICBzIDogJ+W5vuenkicsXG4gICAgICAgIHNzIDogJyVkIOenkicsXG4gICAgICAgIG0gOiAnMSDliIbpkJgnLFxuICAgICAgICBtbSA6ICclZCDliIbpkJgnLFxuICAgICAgICBoIDogJzEg5bCP5pmCJyxcbiAgICAgICAgaGggOiAnJWQg5bCP5pmCJyxcbiAgICAgICAgZCA6ICcxIOWkqScsXG4gICAgICAgIGRkIDogJyVkIOWkqScsXG4gICAgICAgIE0gOiAnMSDlgIvmnIgnLFxuICAgICAgICBNTSA6ICclZCDlgIvmnIgnLFxuICAgICAgICB5IDogJzEg5bm0JyxcbiAgICAgICAgeXkgOiAnJWQg5bm0J1xuICAgIH1cbn0pO1xuXG4vLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogQ2hpbmVzZSAoVGFpd2FuKSBbemgtdHddXG4vLyEgYXV0aG9yIDogQmVuIDogaHR0cHM6Ly9naXRodWIuY29tL2Jlbi1saW5cbi8vISBhdXRob3IgOiBDaHJpcyBMYW0gOiBodHRwczovL2dpdGh1Yi5jb20vaGVoYWNocmlzXG5cbmhvb2tzLmRlZmluZUxvY2FsZSgnemgtdHcnLCB7XG4gICAgbW9udGhzIDogJ+S4gOaciF/kuozmnIhf5LiJ5pyIX+Wbm+aciF/kupTmnIhf5YWt5pyIX+S4g+aciF/lhavmnIhf5Lmd5pyIX+WNgeaciF/ljYHkuIDmnIhf5Y2B5LqM5pyIJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0IDogJzHmnIhfMuaciF8z5pyIXzTmnIhfNeaciF825pyIXzfmnIhfOOaciF855pyIXzEw5pyIXzEx5pyIXzEy5pyIJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzIDogJ+aYn+acn+aXpV/mmJ/mnJ/kuIBf5pif5pyf5LqMX+aYn+acn+S4iV/mmJ/mnJ/lm5tf5pif5pyf5LqUX+aYn+acn+WFrScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0IDogJ+mAseaXpV/pgLHkuIBf6YCx5LqMX+mAseS4iV/pgLHlm5tf6YCx5LqUX+mAseWFrScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbiA6ICfml6Vf5LiAX+S6jF/kuIlf5ZubX+S6lF/lha0nLnNwbGl0KCdfJyksXG4gICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgIExUIDogJ0hIOm1tJyxcbiAgICAgICAgTFRTIDogJ0hIOm1tOnNzJyxcbiAgICAgICAgTCA6ICdZWVlZL01NL0REJyxcbiAgICAgICAgTEwgOiAnWVlZWeW5tE3mnIhE5pelJyxcbiAgICAgICAgTExMIDogJ1lZWVnlubRN5pyIROaXpSBISDptbScsXG4gICAgICAgIExMTEwgOiAnWVlZWeW5tE3mnIhE5pelZGRkZCBISDptbScsXG4gICAgICAgIGwgOiAnWVlZWS9NL0QnLFxuICAgICAgICBsbCA6ICdZWVlZ5bm0TeaciETml6UnLFxuICAgICAgICBsbGwgOiAnWVlZWeW5tE3mnIhE5pelIEhIOm1tJyxcbiAgICAgICAgbGxsbCA6ICdZWVlZ5bm0TeaciETml6VkZGRkIEhIOm1tJ1xuICAgIH0sXG4gICAgbWVyaWRpZW1QYXJzZTogL+WHjOaZqHzml6nkuIp85LiK5Y2IfOS4reWNiHzkuIvljYh85pma5LiKLyxcbiAgICBtZXJpZGllbUhvdXIgOiBmdW5jdGlvbiAoaG91ciwgbWVyaWRpZW0pIHtcbiAgICAgICAgaWYgKGhvdXIgPT09IDEyKSB7XG4gICAgICAgICAgICBob3VyID0gMDtcbiAgICAgICAgfVxuICAgICAgICBpZiAobWVyaWRpZW0gPT09ICflh4zmmagnIHx8IG1lcmlkaWVtID09PSAn5pep5LiKJyB8fCBtZXJpZGllbSA9PT0gJ+S4iuWNiCcpIHtcbiAgICAgICAgICAgIHJldHVybiBob3VyO1xuICAgICAgICB9IGVsc2UgaWYgKG1lcmlkaWVtID09PSAn5Lit5Y2IJykge1xuICAgICAgICAgICAgcmV0dXJuIGhvdXIgPj0gMTEgPyBob3VyIDogaG91ciArIDEyO1xuICAgICAgICB9IGVsc2UgaWYgKG1lcmlkaWVtID09PSAn5LiL5Y2IJyB8fCBtZXJpZGllbSA9PT0gJ+aZmuS4iicpIHtcbiAgICAgICAgICAgIHJldHVybiBob3VyICsgMTI7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIG1lcmlkaWVtIDogZnVuY3Rpb24gKGhvdXIsIG1pbnV0ZSwgaXNMb3dlcikge1xuICAgICAgICB2YXIgaG0gPSBob3VyICogMTAwICsgbWludXRlO1xuICAgICAgICBpZiAoaG0gPCA2MDApIHtcbiAgICAgICAgICAgIHJldHVybiAn5YeM5pmoJztcbiAgICAgICAgfSBlbHNlIGlmIChobSA8IDkwMCkge1xuICAgICAgICAgICAgcmV0dXJuICfml6nkuIonO1xuICAgICAgICB9IGVsc2UgaWYgKGhtIDwgMTEzMCkge1xuICAgICAgICAgICAgcmV0dXJuICfkuIrljYgnO1xuICAgICAgICB9IGVsc2UgaWYgKGhtIDwgMTIzMCkge1xuICAgICAgICAgICAgcmV0dXJuICfkuK3ljYgnO1xuICAgICAgICB9IGVsc2UgaWYgKGhtIDwgMTgwMCkge1xuICAgICAgICAgICAgcmV0dXJuICfkuIvljYgnO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuICfmmZrkuIonO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheSA6ICdb5LuK5aSpXUxUJyxcbiAgICAgICAgbmV4dERheSA6ICdb5piO5aSpXUxUJyxcbiAgICAgICAgbmV4dFdlZWsgOiAnW+S4i11kZGRkTFQnLFxuICAgICAgICBsYXN0RGF5IDogJ1vmmKjlpKldTFQnLFxuICAgICAgICBsYXN0V2VlayA6ICdb5LiKXWRkZGRMVCcsXG4gICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgfSxcbiAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn0o5pelfOaciHzpgLEpLyxcbiAgICBvcmRpbmFsIDogZnVuY3Rpb24gKG51bWJlciwgcGVyaW9kKSB7XG4gICAgICAgIHN3aXRjaCAocGVyaW9kKSB7XG4gICAgICAgICAgICBjYXNlICdkJyA6XG4gICAgICAgICAgICBjYXNlICdEJyA6XG4gICAgICAgICAgICBjYXNlICdEREQnIDpcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJ+aXpSc7XG4gICAgICAgICAgICBjYXNlICdNJyA6XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICfmnIgnO1xuICAgICAgICAgICAgY2FzZSAndycgOlxuICAgICAgICAgICAgY2FzZSAnVycgOlxuICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAn6YCxJztcbiAgICAgICAgICAgIGRlZmF1bHQgOlxuICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXI7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJyVz5YWnJyxcbiAgICAgICAgcGFzdCA6ICclc+WJjScsXG4gICAgICAgIHMgOiAn5bm+56eSJyxcbiAgICAgICAgc3MgOiAnJWQg56eSJyxcbiAgICAgICAgbSA6ICcxIOWIhumQmCcsXG4gICAgICAgIG1tIDogJyVkIOWIhumQmCcsXG4gICAgICAgIGggOiAnMSDlsI/mmYInLFxuICAgICAgICBoaCA6ICclZCDlsI/mmYInLFxuICAgICAgICBkIDogJzEg5aSpJyxcbiAgICAgICAgZGQgOiAnJWQg5aSpJyxcbiAgICAgICAgTSA6ICcxIOWAi+aciCcsXG4gICAgICAgIE1NIDogJyVkIOWAi+aciCcsXG4gICAgICAgIHkgOiAnMSDlubQnLFxuICAgICAgICB5eSA6ICclZCDlubQnXG4gICAgfVxufSk7XG5cbmhvb2tzLmxvY2FsZSgnZW4nKTtcblxucmV0dXJuIGhvb2tzO1xuXG59KSkpO1xuIiwiIWZ1bmN0aW9uKHQsZSl7XCJ1c2Ugc3RyaWN0XCI7XCJmdW5jdGlvblwiPT10eXBlb2YgZGVmaW5lJiZkZWZpbmUuYW1kP2RlZmluZShbXCJtb21lbnRcIl0sZSk6XCJvYmplY3RcIj09dHlwZW9mIG1vZHVsZSYmbW9kdWxlLmV4cG9ydHM/bW9kdWxlLmV4cG9ydHM9ZShyZXF1aXJlKFwibW9tZW50XCIpKTplKHQubW9tZW50KX0odGhpcyxmdW5jdGlvbih0KXtcInVzZSBzdHJpY3RcIjtmdW5jdGlvbiBlKHQpe3JldHVybiB0Pjk2P3QtODc6dD42ND90LTI5OnQtNDh9ZnVuY3Rpb24gbih0KXt2YXIgbj0wLG89dC5zcGxpdChcIi5cIikscj1vWzBdLHM9b1sxXXx8XCJcIixpPTEsZj0wLGE9MTtmb3IoNDU9PT10LmNoYXJDb2RlQXQoMCkmJihuPTEsYT0tMSksbjtuPHIubGVuZ3RoO24rKylmPTYwKmYrZShyLmNoYXJDb2RlQXQobikpO2ZvcihuPTA7bjxzLmxlbmd0aDtuKyspaS89NjAsZis9ZShzLmNoYXJDb2RlQXQobikpKmk7cmV0dXJuIGYqYX1mdW5jdGlvbiBvKHQpe2Zvcih2YXIgZT0wO2U8dC5sZW5ndGg7ZSsrKXRbZV09bih0W2VdKX1mdW5jdGlvbiByKHQsZSl7Zm9yKHZhciBuPTA7bjxlO24rKyl0W25dPU1hdGgucm91bmQoKHRbbi0xXXx8MCkrNmU0KnRbbl0pO3RbZS0xXT0xLzB9ZnVuY3Rpb24gcyh0LGUpe3ZhciBuLG89W107Zm9yKG49MDtuPGUubGVuZ3RoO24rKylvW25dPXRbZVtuXV07cmV0dXJuIG99ZnVuY3Rpb24gaSh0KXt2YXIgZT10LnNwbGl0KFwifFwiKSxuPWVbMl0uc3BsaXQoXCIgXCIpLGk9ZVszXS5zcGxpdChcIlwiKSxmPWVbNF0uc3BsaXQoXCIgXCIpO3JldHVybiBvKG4pLG8oaSksbyhmKSxyKGYsaS5sZW5ndGgpLHtuYW1lOmVbMF0sYWJicnM6cyhlWzFdLnNwbGl0KFwiIFwiKSxpKSxvZmZzZXRzOnMobixpKSx1bnRpbHM6Zixwb3B1bGF0aW9uOjB8ZVs1XX19ZnVuY3Rpb24gZih0KXt0JiZ0aGlzLl9zZXQoaSh0KSl9ZnVuY3Rpb24gYSh0KXt2YXIgZT10LnRvVGltZVN0cmluZygpLG49ZS5tYXRjaCgvXFwoW2EteiBdK1xcKS9pKTtcIkdNVFwiPT09KG49biYmblswXT8obj1uWzBdLm1hdGNoKC9bQS1aXS9nKSk/bi5qb2luKFwiXCIpOnZvaWQgMDoobj1lLm1hdGNoKC9bQS1aXXszLDV9L2cpKT9uWzBdOnZvaWQgMCkmJihuPXZvaWQgMCksdGhpcy5hdD0rdCx0aGlzLmFiYnI9bix0aGlzLm9mZnNldD10LmdldFRpbWV6b25lT2Zmc2V0KCl9ZnVuY3Rpb24gdSh0KXt0aGlzLnpvbmU9dCx0aGlzLm9mZnNldFNjb3JlPTAsdGhpcy5hYmJyU2NvcmU9MH1mdW5jdGlvbiBjKHQsZSl7Zm9yKHZhciBuLG87bz02ZTQqKChlLmF0LXQuYXQpLzEyZTR8MCk7KShuPW5ldyBhKG5ldyBEYXRlKHQuYXQrbykpKS5vZmZzZXQ9PT10Lm9mZnNldD90PW46ZT1uO3JldHVybiB0fWZ1bmN0aW9uIGgoKXt2YXIgdCxlLG4sbz0obmV3IERhdGUpLmdldEZ1bGxZZWFyKCktMixyPW5ldyBhKG5ldyBEYXRlKG8sMCwxKSkscz1bcl07Zm9yKG49MTtuPDQ4O24rKykoZT1uZXcgYShuZXcgRGF0ZShvLG4sMSkpKS5vZmZzZXQhPT1yLm9mZnNldCYmKHQ9YyhyLGUpLHMucHVzaCh0KSxzLnB1c2gobmV3IGEobmV3IERhdGUodC5hdCs2ZTQpKSkpLHI9ZTtmb3Iobj0wO248NDtuKyspcy5wdXNoKG5ldyBhKG5ldyBEYXRlKG8rbiwwLDEpKSkscy5wdXNoKG5ldyBhKG5ldyBEYXRlKG8rbiw2LDEpKSk7cmV0dXJuIHN9ZnVuY3Rpb24gbCh0LGUpe3JldHVybiB0Lm9mZnNldFNjb3JlIT09ZS5vZmZzZXRTY29yZT90Lm9mZnNldFNjb3JlLWUub2Zmc2V0U2NvcmU6dC5hYmJyU2NvcmUhPT1lLmFiYnJTY29yZT90LmFiYnJTY29yZS1lLmFiYnJTY29yZTplLnpvbmUucG9wdWxhdGlvbi10LnpvbmUucG9wdWxhdGlvbn1mdW5jdGlvbiBwKHQsZSl7dmFyIG4scjtmb3IobyhlKSxuPTA7bjxlLmxlbmd0aDtuKyspcj1lW25dLHhbcl09eFtyXXx8e30seFtyXVt0XT0hMH1mdW5jdGlvbiBkKHQpe3ZhciBlLG4sbyxyPXQubGVuZ3RoLHM9e30saT1bXTtmb3IoZT0wO2U8cjtlKyspe289eFt0W2VdLm9mZnNldF18fHt9O2ZvcihuIGluIG8pby5oYXNPd25Qcm9wZXJ0eShuKSYmKHNbbl09ITApfWZvcihlIGluIHMpcy5oYXNPd25Qcm9wZXJ0eShlKSYmaS5wdXNoKERbZV0pO3JldHVybiBpfWZ1bmN0aW9uIG0oKXt0cnl7dmFyIHQ9SW50bC5EYXRlVGltZUZvcm1hdCgpLnJlc29sdmVkT3B0aW9ucygpLnRpbWVab25lO2lmKHQmJnQubGVuZ3RoPjMpe3ZhciBlPURbdih0KV07aWYoZSlyZXR1cm4gZTt5KFwiTW9tZW50IFRpbWV6b25lIGZvdW5kIFwiK3QrXCIgZnJvbSB0aGUgSW50bCBhcGksIGJ1dCBkaWQgbm90IGhhdmUgdGhhdCBkYXRhIGxvYWRlZC5cIil9fWNhdGNoKHQpe312YXIgbixvLHIscz1oKCksaT1zLmxlbmd0aCxmPWQocyksYT1bXTtmb3Iobz0wO288Zi5sZW5ndGg7bysrKXtmb3Iobj1uZXcgdShiKGZbb10pLGkpLHI9MDtyPGk7cisrKW4uc2NvcmVPZmZzZXRBdChzW3JdKTthLnB1c2gobil9cmV0dXJuIGEuc29ydChsKSxhLmxlbmd0aD4wP2FbMF0uem9uZS5uYW1lOnZvaWQgMH1mdW5jdGlvbiB2KHQpe3JldHVybih0fHxcIlwiKS50b0xvd2VyQ2FzZSgpLnJlcGxhY2UoL1xcLy9nLFwiX1wiKX1mdW5jdGlvbiB6KHQpe3ZhciBlLG4sbyxyO2ZvcihcInN0cmluZ1wiPT10eXBlb2YgdCYmKHQ9W3RdKSxlPTA7ZTx0Lmxlbmd0aDtlKyspcj12KG49KG89dFtlXS5zcGxpdChcInxcIikpWzBdKSxNW3JdPXRbZV0sRFtyXT1uLHAocixvWzJdLnNwbGl0KFwiIFwiKSl9ZnVuY3Rpb24gYih0LGUpe3Q9dih0KTt2YXIgbixvPU1bdF07cmV0dXJuIG8gaW5zdGFuY2VvZiBmP286XCJzdHJpbmdcIj09dHlwZW9mIG8/KG89bmV3IGYobyksTVt0XT1vLG8pOmpbdF0mJmUhPT1iJiYobj1iKGpbdF0sYikpPygobz1NW3RdPW5ldyBmKS5fc2V0KG4pLG8ubmFtZT1EW3RdLG8pOm51bGx9ZnVuY3Rpb24gZyh0KXt2YXIgZSxuLG8scjtmb3IoXCJzdHJpbmdcIj09dHlwZW9mIHQmJih0PVt0XSksZT0wO2U8dC5sZW5ndGg7ZSsrKW89digobj10W2VdLnNwbGl0KFwifFwiKSlbMF0pLHI9dihuWzFdKSxqW29dPXIsRFtvXT1uWzBdLGpbcl09byxEW3JdPW5bMV19ZnVuY3Rpb24gXyh0KXtyZXR1cm4gXy5kaWRTaG93RXJyb3J8fChfLmRpZFNob3dFcnJvcj0hMCx5KFwibW9tZW50LnR6LnpvbmVFeGlzdHMoJ1wiK3QrXCInKSBoYXMgYmVlbiBkZXByZWNhdGVkIGluIGZhdm9yIG9mICFtb21lbnQudHouem9uZSgnXCIrdCtcIicpXCIpKSwhIWIodCl9ZnVuY3Rpb24gdyh0KXt2YXIgZT1cIlhcIj09PXQuX2Z8fFwieFwiPT09dC5fZjtyZXR1cm4hKCF0Ll9hfHx2b2lkIDAhPT10Ll90em18fGUpfWZ1bmN0aW9uIHkodCl7XCJ1bmRlZmluZWRcIiE9dHlwZW9mIGNvbnNvbGUmJlwiZnVuY3Rpb25cIj09dHlwZW9mIGNvbnNvbGUuZXJyb3ImJmNvbnNvbGUuZXJyb3IodCl9ZnVuY3Rpb24gUyhlKXt2YXIgbj1BcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsMCwtMSksbz1hcmd1bWVudHNbYXJndW1lbnRzLmxlbmd0aC0xXSxyPWIobykscz10LnV0Yy5hcHBseShudWxsLG4pO3JldHVybiByJiYhdC5pc01vbWVudChlKSYmdyhzKSYmcy5hZGQoci5wYXJzZShzKSxcIm1pbnV0ZXNcIikscy50eihvKSxzfWZ1bmN0aW9uIE8odCl7cmV0dXJuIGZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX3o/dGhpcy5fei5hYmJyKHRoaXMpOnQuY2FsbCh0aGlzKX19dmFyIEEsTT17fSxqPXt9LEQ9e30seD17fSxUPXQudmVyc2lvbi5zcGxpdChcIi5cIiksWj0rVFswXSxGPStUWzFdOyhaPDJ8fDI9PT1aJiZGPDYpJiZ5KFwiTW9tZW50IFRpbWV6b25lIHJlcXVpcmVzIE1vbWVudC5qcyA+PSAyLjYuMC4gWW91IGFyZSB1c2luZyBNb21lbnQuanMgXCIrdC52ZXJzaW9uK1wiLiBTZWUgbW9tZW50anMuY29tXCIpLGYucHJvdG90eXBlPXtfc2V0OmZ1bmN0aW9uKHQpe3RoaXMubmFtZT10Lm5hbWUsdGhpcy5hYmJycz10LmFiYnJzLHRoaXMudW50aWxzPXQudW50aWxzLHRoaXMub2Zmc2V0cz10Lm9mZnNldHMsdGhpcy5wb3B1bGF0aW9uPXQucG9wdWxhdGlvbn0sX2luZGV4OmZ1bmN0aW9uKHQpe3ZhciBlLG49K3Qsbz10aGlzLnVudGlscztmb3IoZT0wO2U8by5sZW5ndGg7ZSsrKWlmKG48b1tlXSlyZXR1cm4gZX0scGFyc2U6ZnVuY3Rpb24odCl7dmFyIGUsbixvLHIscz0rdCxpPXRoaXMub2Zmc2V0cyxmPXRoaXMudW50aWxzLGE9Zi5sZW5ndGgtMTtmb3Iocj0wO3I8YTtyKyspaWYoZT1pW3JdLG49aVtyKzFdLG89aVtyP3ItMTpyXSxlPG4mJlMubW92ZUFtYmlndW91c0ZvcndhcmQ/ZT1uOmU+byYmUy5tb3ZlSW52YWxpZEZvcndhcmQmJihlPW8pLHM8ZltyXS02ZTQqZSlyZXR1cm4gaVtyXTtyZXR1cm4gaVthXX0sYWJicjpmdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5hYmJyc1t0aGlzLl9pbmRleCh0KV19LG9mZnNldDpmdW5jdGlvbih0KXtyZXR1cm4geShcInpvbmUub2Zmc2V0IGhhcyBiZWVuIGRlcHJlY2F0ZWQgaW4gZmF2b3Igb2Ygem9uZS51dGNPZmZzZXRcIiksdGhpcy5vZmZzZXRzW3RoaXMuX2luZGV4KHQpXX0sdXRjT2Zmc2V0OmZ1bmN0aW9uKHQpe3JldHVybiB0aGlzLm9mZnNldHNbdGhpcy5faW5kZXgodCldfX0sdS5wcm90b3R5cGUuc2NvcmVPZmZzZXRBdD1mdW5jdGlvbih0KXt0aGlzLm9mZnNldFNjb3JlKz1NYXRoLmFicyh0aGlzLnpvbmUudXRjT2Zmc2V0KHQuYXQpLXQub2Zmc2V0KSx0aGlzLnpvbmUuYWJicih0LmF0KS5yZXBsYWNlKC9bXkEtWl0vZyxcIlwiKSE9PXQuYWJiciYmdGhpcy5hYmJyU2NvcmUrK30sUy52ZXJzaW9uPVwiMC41LjE0XCIsUy5kYXRhVmVyc2lvbj1cIlwiLFMuX3pvbmVzPU0sUy5fbGlua3M9aixTLl9uYW1lcz1ELFMuYWRkPXosUy5saW5rPWcsUy5sb2FkPWZ1bmN0aW9uKHQpe3oodC56b25lcyksZyh0LmxpbmtzKSxTLmRhdGFWZXJzaW9uPXQudmVyc2lvbn0sUy56b25lPWIsUy56b25lRXhpc3RzPV8sUy5ndWVzcz1mdW5jdGlvbih0KXtyZXR1cm4gQSYmIXR8fChBPW0oKSksQX0sUy5uYW1lcz1mdW5jdGlvbigpe3ZhciB0LGU9W107Zm9yKHQgaW4gRClELmhhc093blByb3BlcnR5KHQpJiYoTVt0XXx8TVtqW3RdXSkmJkRbdF0mJmUucHVzaChEW3RdKTtyZXR1cm4gZS5zb3J0KCl9LFMuWm9uZT1mLFMudW5wYWNrPWksUy51bnBhY2tCYXNlNjA9bixTLm5lZWRzT2Zmc2V0PXcsUy5tb3ZlSW52YWxpZEZvcndhcmQ9ITAsUy5tb3ZlQW1iaWd1b3VzRm9yd2FyZD0hMTt2YXIgaz10LmZuO3QudHo9Uyx0LmRlZmF1bHRab25lPW51bGwsdC51cGRhdGVPZmZzZXQ9ZnVuY3Rpb24oZSxuKXt2YXIgbyxyPXQuZGVmYXVsdFpvbmU7dm9pZCAwPT09ZS5feiYmKHImJncoZSkmJiFlLl9pc1VUQyYmKGUuX2Q9dC51dGMoZS5fYSkuX2QsZS51dGMoKS5hZGQoci5wYXJzZShlKSxcIm1pbnV0ZXNcIikpLGUuX3o9ciksZS5feiYmKG89ZS5fei51dGNPZmZzZXQoZSksTWF0aC5hYnMobyk8MTYmJihvLz02MCksdm9pZCAwIT09ZS51dGNPZmZzZXQ/ZS51dGNPZmZzZXQoLW8sbik6ZS56b25lKG8sbikpfSxrLnR6PWZ1bmN0aW9uKGUsbil7cmV0dXJuIGU/KHRoaXMuX3o9YihlKSx0aGlzLl96P3QudXBkYXRlT2Zmc2V0KHRoaXMsbik6eShcIk1vbWVudCBUaW1lem9uZSBoYXMgbm8gZGF0YSBmb3IgXCIrZStcIi4gU2VlIGh0dHA6Ly9tb21lbnRqcy5jb20vdGltZXpvbmUvZG9jcy8jL2RhdGEtbG9hZGluZy8uXCIpLHRoaXMpOnRoaXMuX3o/dGhpcy5fei5uYW1lOnZvaWQgMH0say56b25lTmFtZT1PKGsuem9uZU5hbWUpLGsuem9uZUFiYnI9TyhrLnpvbmVBYmJyKSxrLnV0Yz1mdW5jdGlvbih0KXtyZXR1cm4gZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5fej1udWxsLHQuYXBwbHkodGhpcyxhcmd1bWVudHMpfX0oay51dGMpLHQudHouc2V0RGVmYXVsdD1mdW5jdGlvbihlKXtyZXR1cm4oWjwyfHwyPT09WiYmRjw5KSYmeShcIk1vbWVudCBUaW1lem9uZSBzZXREZWZhdWx0KCkgcmVxdWlyZXMgTW9tZW50LmpzID49IDIuOS4wLiBZb3UgYXJlIHVzaW5nIE1vbWVudC5qcyBcIit0LnZlcnNpb24rXCIuXCIpLHQuZGVmYXVsdFpvbmU9ZT9iKGUpOm51bGwsdH07dmFyIEM9dC5tb21lbnRQcm9wZXJ0aWVzO3JldHVyblwiW29iamVjdCBBcnJheV1cIj09PU9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChDKT8oQy5wdXNoKFwiX3pcIiksQy5wdXNoKFwiX2FcIikpOkMmJihDLl96PW51bGwpLHR9KTsiLCJ2YXIgX2NyZWF0ZUNsYXNzID0gZnVuY3Rpb24gKCkgeyBmdW5jdGlvbiBkZWZpbmVQcm9wZXJ0aWVzKHRhcmdldCwgcHJvcHMpIHsgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykgeyB2YXIgZGVzY3JpcHRvciA9IHByb3BzW2ldOyBkZXNjcmlwdG9yLmVudW1lcmFibGUgPSBkZXNjcmlwdG9yLmVudW1lcmFibGUgfHwgZmFsc2U7IGRlc2NyaXB0b3IuY29uZmlndXJhYmxlID0gdHJ1ZTsgaWYgKFwidmFsdWVcIiBpbiBkZXNjcmlwdG9yKSBkZXNjcmlwdG9yLndyaXRhYmxlID0gdHJ1ZTsgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwgZGVzY3JpcHRvci5rZXksIGRlc2NyaXB0b3IpOyB9IH0gcmV0dXJuIGZ1bmN0aW9uIChDb25zdHJ1Y3RvciwgcHJvdG9Qcm9wcywgc3RhdGljUHJvcHMpIHsgaWYgKHByb3RvUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IucHJvdG90eXBlLCBwcm90b1Byb3BzKTsgaWYgKHN0YXRpY1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLCBzdGF0aWNQcm9wcyk7IHJldHVybiBDb25zdHJ1Y3RvcjsgfTsgfSgpO1xuXG5mdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7IGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoXCJDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb25cIik7IH0gfVxuXG4vLyBSZVNoYXJwZXIgZGlzYWJsZSBvbmNlIEluY29uc2lzdGVudE5hbWluZ1xudmFyIERhdGVUaW1lUGlja2VyID0gZnVuY3Rpb24gKCQsIG1vbWVudCkge1xuICAgIC8vIFJlU2hhcnBlciBkaXNhYmxlIEluY29uc2lzdGVudE5hbWluZ1xuICAgIHZhciBOQU1FID0gJ2RhdGV0aW1lcGlja2VyJyxcbiAgICAgICAgVkVSU0lPTiA9ICc1LjAuMC1hbHBoYTEyJyxcbiAgICAgICAgREFUQV9LRVkgPSAnJyArIE5BTUUsXG4gICAgICAgIEVWRU5UX0tFWSA9ICcuJyArIERBVEFfS0VZLFxuICAgICAgICBFTUlUX0VWRU5UX0tFWSA9IERBVEFfS0VZICsgJy4nLFxuICAgICAgICBEQVRBX0FQSV9LRVkgPSAnLmRhdGEtYXBpJyxcbiAgICAgICAgU2VsZWN0b3IgPSB7XG4gICAgICAgIERBVEFfVE9HR0xFOiAnW2RhdGEtdG9nZ2xlPVwiJyArIERBVEFfS0VZICsgJ1wiXSdcbiAgICB9LFxuICAgICAgICBDbGFzc05hbWUgPSB7XG4gICAgICAgIElOUFVUOiBOQU1FICsgJy1pbnB1dCdcbiAgICB9LFxuICAgICAgICBFdmVudCA9IHtcbiAgICAgICAgQ0hBTkdFOiAnY2hhbmdlJyArIEVWRU5UX0tFWSxcbiAgICAgICAgQkxVUjogJ2JsdXInICsgRVZFTlRfS0VZLFxuICAgICAgICBLRVlVUDogJ2tleXVwJyArIEVWRU5UX0tFWSxcbiAgICAgICAgS0VZRE9XTjogJ2tleWRvd24nICsgRVZFTlRfS0VZLFxuICAgICAgICBGT0NVUzogJ2ZvY3VzJyArIEVWRU5UX0tFWSxcbiAgICAgICAgQ0xJQ0tfREFUQV9BUEk6ICdjbGljaycgKyBFVkVOVF9LRVkgKyBEQVRBX0FQSV9LRVksXG4gICAgICAgIC8vZW1pdHRlZFxuICAgICAgICBVUERBVEU6IEVNSVRfRVZFTlRfS0VZICsgJ3VwZGF0ZScsXG4gICAgICAgIEVSUk9SOiBFTUlUX0VWRU5UX0tFWSArICdlcnJvcicsXG4gICAgICAgIEhJREU6IEVNSVRfRVZFTlRfS0VZICsgJ2hpZGUnLFxuICAgICAgICBTSE9XOiBFTUlUX0VWRU5UX0tFWSArICdzaG93J1xuICAgIH0sXG4gICAgICAgIERhdGVQaWNrZXJNb2RlcyA9IFt7XG4gICAgICAgIENMQVNTX05BTUU6ICdkYXlzJyxcbiAgICAgICAgTkFWX0ZVTkNUSU9OOiAnTScsXG4gICAgICAgIE5BVl9TVEVQOiAxXG4gICAgfSwge1xuICAgICAgICBDTEFTU19OQU1FOiAnbW9udGhzJyxcbiAgICAgICAgTkFWX0ZVTkNUSU9OOiAneScsXG4gICAgICAgIE5BVl9TVEVQOiAxXG4gICAgfSwge1xuICAgICAgICBDTEFTU19OQU1FOiAneWVhcnMnLFxuICAgICAgICBOQVZfRlVOQ1RJT046ICd5JyxcbiAgICAgICAgTkFWX1NURVA6IDEwXG4gICAgfSwge1xuICAgICAgICBDTEFTU19OQU1FOiAnZGVjYWRlcycsXG4gICAgICAgIE5BVl9GVU5DVElPTjogJ3knLFxuICAgICAgICBOQVZfU1RFUDogMTAwXG4gICAgfV0sXG4gICAgICAgIEtleU1hcCA9IHtcbiAgICAgICAgJ3VwJzogMzgsXG4gICAgICAgIDM4OiAndXAnLFxuICAgICAgICAnZG93bic6IDQwLFxuICAgICAgICA0MDogJ2Rvd24nLFxuICAgICAgICAnbGVmdCc6IDM3LFxuICAgICAgICAzNzogJ2xlZnQnLFxuICAgICAgICAncmlnaHQnOiAzOSxcbiAgICAgICAgMzk6ICdyaWdodCcsXG4gICAgICAgICd0YWInOiA5LFxuICAgICAgICA5OiAndGFiJyxcbiAgICAgICAgJ2VzY2FwZSc6IDI3LFxuICAgICAgICAyNzogJ2VzY2FwZScsXG4gICAgICAgICdlbnRlcic6IDEzLFxuICAgICAgICAxMzogJ2VudGVyJyxcbiAgICAgICAgJ3BhZ2VVcCc6IDMzLFxuICAgICAgICAzMzogJ3BhZ2VVcCcsXG4gICAgICAgICdwYWdlRG93bic6IDM0LFxuICAgICAgICAzNDogJ3BhZ2VEb3duJyxcbiAgICAgICAgJ3NoaWZ0JzogMTYsXG4gICAgICAgIDE2OiAnc2hpZnQnLFxuICAgICAgICAnY29udHJvbCc6IDE3LFxuICAgICAgICAxNzogJ2NvbnRyb2wnLFxuICAgICAgICAnc3BhY2UnOiAzMixcbiAgICAgICAgMzI6ICdzcGFjZScsXG4gICAgICAgICd0JzogODQsXG4gICAgICAgIDg0OiAndCcsXG4gICAgICAgICdkZWxldGUnOiA0NixcbiAgICAgICAgNDY6ICdkZWxldGUnXG4gICAgfSxcbiAgICAgICAgVmlld01vZGVzID0gWyd0aW1lcycsICdkYXlzJywgJ21vbnRocycsICd5ZWFycycsICdkZWNhZGVzJ10sXG4gICAgICAgIGtleVN0YXRlID0ge30sXG4gICAgICAgIGtleVByZXNzSGFuZGxlZCA9IHt9O1xuXG4gICAgdmFyIE1pblZpZXdNb2RlTnVtYmVyID0gMCxcbiAgICAgICAgRGVmYXVsdCA9IHtcbiAgICAgICAgdGltZVpvbmU6ICcnLFxuICAgICAgICBmb3JtYXQ6IGZhbHNlLFxuICAgICAgICBkYXlWaWV3SGVhZGVyRm9ybWF0OiAnTU1NTSBZWVlZJyxcbiAgICAgICAgZXh0cmFGb3JtYXRzOiBmYWxzZSxcbiAgICAgICAgc3RlcHBpbmc6IDEsXG4gICAgICAgIG1pbkRhdGU6IGZhbHNlLFxuICAgICAgICBtYXhEYXRlOiBmYWxzZSxcbiAgICAgICAgdXNlQ3VycmVudDogdHJ1ZSxcbiAgICAgICAgY29sbGFwc2U6IHRydWUsXG4gICAgICAgIGxvY2FsZTogbW9tZW50LmxvY2FsZSgpLFxuICAgICAgICBkZWZhdWx0RGF0ZTogZmFsc2UsXG4gICAgICAgIGRpc2FibGVkRGF0ZXM6IGZhbHNlLFxuICAgICAgICBlbmFibGVkRGF0ZXM6IGZhbHNlLFxuICAgICAgICBpY29uczoge1xuICAgICAgICAgICAgdGltZTogJ2ZhIGZhLWNsb2NrLW8nLFxuICAgICAgICAgICAgZGF0ZTogJ2ZhIGZhLWNhbGVuZGFyJyxcbiAgICAgICAgICAgIHVwOiAnZmEgZmEtYXJyb3ctdXAnLFxuICAgICAgICAgICAgZG93bjogJ2ZhIGZhLWFycm93LWRvd24nLFxuICAgICAgICAgICAgcHJldmlvdXM6ICdmYSBmYS1jaGV2cm9uLWxlZnQnLFxuICAgICAgICAgICAgbmV4dDogJ2ZhIGZhLWNoZXZyb24tcmlnaHQnLFxuICAgICAgICAgICAgdG9kYXk6ICdmYSBmYS1jYWxlbmRhci1jaGVjay1vJyxcbiAgICAgICAgICAgIGNsZWFyOiAnZmEgZmEtZGVsZXRlJyxcbiAgICAgICAgICAgIGNsb3NlOiAnZmEgZmEtdGltZXMnXG4gICAgICAgIH0sXG4gICAgICAgIHRvb2x0aXBzOiB7XG4gICAgICAgICAgICB0b2RheTogJ0dvIHRvIHRvZGF5JyxcbiAgICAgICAgICAgIGNsZWFyOiAnQ2xlYXIgc2VsZWN0aW9uJyxcbiAgICAgICAgICAgIGNsb3NlOiAnQ2xvc2UgdGhlIHBpY2tlcicsXG4gICAgICAgICAgICBzZWxlY3RNb250aDogJ1NlbGVjdCBNb250aCcsXG4gICAgICAgICAgICBwcmV2TW9udGg6ICdQcmV2aW91cyBNb250aCcsXG4gICAgICAgICAgICBuZXh0TW9udGg6ICdOZXh0IE1vbnRoJyxcbiAgICAgICAgICAgIHNlbGVjdFllYXI6ICdTZWxlY3QgWWVhcicsXG4gICAgICAgICAgICBwcmV2WWVhcjogJ1ByZXZpb3VzIFllYXInLFxuICAgICAgICAgICAgbmV4dFllYXI6ICdOZXh0IFllYXInLFxuICAgICAgICAgICAgc2VsZWN0RGVjYWRlOiAnU2VsZWN0IERlY2FkZScsXG4gICAgICAgICAgICBwcmV2RGVjYWRlOiAnUHJldmlvdXMgRGVjYWRlJyxcbiAgICAgICAgICAgIG5leHREZWNhZGU6ICdOZXh0IERlY2FkZScsXG4gICAgICAgICAgICBwcmV2Q2VudHVyeTogJ1ByZXZpb3VzIENlbnR1cnknLFxuICAgICAgICAgICAgbmV4dENlbnR1cnk6ICdOZXh0IENlbnR1cnknLFxuICAgICAgICAgICAgcGlja0hvdXI6ICdQaWNrIEhvdXInLFxuICAgICAgICAgICAgaW5jcmVtZW50SG91cjogJ0luY3JlbWVudCBIb3VyJyxcbiAgICAgICAgICAgIGRlY3JlbWVudEhvdXI6ICdEZWNyZW1lbnQgSG91cicsXG4gICAgICAgICAgICBwaWNrTWludXRlOiAnUGljayBNaW51dGUnLFxuICAgICAgICAgICAgaW5jcmVtZW50TWludXRlOiAnSW5jcmVtZW50IE1pbnV0ZScsXG4gICAgICAgICAgICBkZWNyZW1lbnRNaW51dGU6ICdEZWNyZW1lbnQgTWludXRlJyxcbiAgICAgICAgICAgIHBpY2tTZWNvbmQ6ICdQaWNrIFNlY29uZCcsXG4gICAgICAgICAgICBpbmNyZW1lbnRTZWNvbmQ6ICdJbmNyZW1lbnQgU2Vjb25kJyxcbiAgICAgICAgICAgIGRlY3JlbWVudFNlY29uZDogJ0RlY3JlbWVudCBTZWNvbmQnLFxuICAgICAgICAgICAgdG9nZ2xlUGVyaW9kOiAnVG9nZ2xlIFBlcmlvZCcsXG4gICAgICAgICAgICBzZWxlY3RUaW1lOiAnU2VsZWN0IFRpbWUnLFxuICAgICAgICAgICAgc2VsZWN0RGF0ZTogJ1NlbGVjdCBEYXRlJ1xuICAgICAgICB9LFxuICAgICAgICB1c2VTdHJpY3Q6IGZhbHNlLFxuICAgICAgICBzaWRlQnlTaWRlOiBmYWxzZSxcbiAgICAgICAgZGF5c09mV2Vla0Rpc2FibGVkOiBmYWxzZSxcbiAgICAgICAgY2FsZW5kYXJXZWVrczogZmFsc2UsXG4gICAgICAgIHZpZXdNb2RlOiAnZGF5cycsXG4gICAgICAgIHRvb2xiYXJQbGFjZW1lbnQ6ICdkZWZhdWx0JyxcbiAgICAgICAgYnV0dG9uczoge1xuICAgICAgICAgICAgc2hvd1RvZGF5OiBmYWxzZSxcbiAgICAgICAgICAgIHNob3dDbGVhcjogZmFsc2UsXG4gICAgICAgICAgICBzaG93Q2xvc2U6IGZhbHNlXG4gICAgICAgIH0sXG4gICAgICAgIHdpZGdldFBvc2l0aW9uaW5nOiB7XG4gICAgICAgICAgICBob3Jpem9udGFsOiAnYXV0bycsXG4gICAgICAgICAgICB2ZXJ0aWNhbDogJ2F1dG8nXG4gICAgICAgIH0sXG4gICAgICAgIHdpZGdldFBhcmVudDogbnVsbCxcbiAgICAgICAgaWdub3JlUmVhZG9ubHk6IGZhbHNlLFxuICAgICAgICBrZWVwT3BlbjogZmFsc2UsXG4gICAgICAgIGZvY3VzT25TaG93OiB0cnVlLFxuICAgICAgICBpbmxpbmU6IGZhbHNlLFxuICAgICAgICBrZWVwSW52YWxpZDogZmFsc2UsXG4gICAgICAgIGtleUJpbmRzOiB7XG4gICAgICAgICAgICB1cDogZnVuY3Rpb24gdXAoKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLndpZGdldCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciBkID0gdGhpcy5fZGF0ZXNbMF0gfHwgdGhpcy5nZXRNb21lbnQoKTtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy53aWRnZXQuZmluZCgnLmRhdGVwaWNrZXInKS5pcygnOnZpc2libGUnKSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmRhdGUoZC5jbG9uZSgpLnN1YnRyYWN0KDcsICdkJykpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGF0ZShkLmNsb25lKCkuYWRkKHRoaXMuc3RlcHBpbmcoKSwgJ20nKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGRvd246IGZ1bmN0aW9uIGRvd24oKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLndpZGdldCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnNob3coKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgZCA9IHRoaXMuX2RhdGVzWzBdIHx8IHRoaXMuZ2V0TW9tZW50KCk7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMud2lkZ2V0LmZpbmQoJy5kYXRlcGlja2VyJykuaXMoJzp2aXNpYmxlJykpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kYXRlKGQuY2xvbmUoKS5hZGQoNywgJ2QnKSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kYXRlKGQuY2xvbmUoKS5zdWJ0cmFjdCh0aGlzLnN0ZXBwaW5nKCksICdtJykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAnY29udHJvbCB1cCc6IGZ1bmN0aW9uIGNvbnRyb2xVcCgpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMud2lkZ2V0KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdmFyIGQgPSB0aGlzLl9kYXRlc1swXSB8fCB0aGlzLmdldE1vbWVudCgpO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLndpZGdldC5maW5kKCcuZGF0ZXBpY2tlcicpLmlzKCc6dmlzaWJsZScpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGF0ZShkLmNsb25lKCkuc3VidHJhY3QoMSwgJ3knKSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kYXRlKGQuY2xvbmUoKS5hZGQoMSwgJ2gnKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICdjb250cm9sIGRvd24nOiBmdW5jdGlvbiBjb250cm9sRG93bigpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMud2lkZ2V0KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdmFyIGQgPSB0aGlzLl9kYXRlc1swXSB8fCB0aGlzLmdldE1vbWVudCgpO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLndpZGdldC5maW5kKCcuZGF0ZXBpY2tlcicpLmlzKCc6dmlzaWJsZScpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGF0ZShkLmNsb25lKCkuYWRkKDEsICd5JykpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGF0ZShkLmNsb25lKCkuc3VidHJhY3QoMSwgJ2gnKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGxlZnQ6IGZ1bmN0aW9uIGxlZnQoKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLndpZGdldCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciBkID0gdGhpcy5fZGF0ZXNbMF0gfHwgdGhpcy5nZXRNb21lbnQoKTtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy53aWRnZXQuZmluZCgnLmRhdGVwaWNrZXInKS5pcygnOnZpc2libGUnKSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmRhdGUoZC5jbG9uZSgpLnN1YnRyYWN0KDEsICdkJykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICByaWdodDogZnVuY3Rpb24gcmlnaHQoKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLndpZGdldCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciBkID0gdGhpcy5fZGF0ZXNbMF0gfHwgdGhpcy5nZXRNb21lbnQoKTtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy53aWRnZXQuZmluZCgnLmRhdGVwaWNrZXInKS5pcygnOnZpc2libGUnKSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmRhdGUoZC5jbG9uZSgpLmFkZCgxLCAnZCcpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgcGFnZVVwOiBmdW5jdGlvbiBwYWdlVXAoKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLndpZGdldCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciBkID0gdGhpcy5fZGF0ZXNbMF0gfHwgdGhpcy5nZXRNb21lbnQoKTtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy53aWRnZXQuZmluZCgnLmRhdGVwaWNrZXInKS5pcygnOnZpc2libGUnKSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmRhdGUoZC5jbG9uZSgpLnN1YnRyYWN0KDEsICdNJykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBwYWdlRG93bjogZnVuY3Rpb24gcGFnZURvd24oKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLndpZGdldCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciBkID0gdGhpcy5fZGF0ZXNbMF0gfHwgdGhpcy5nZXRNb21lbnQoKTtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy53aWRnZXQuZmluZCgnLmRhdGVwaWNrZXInKS5pcygnOnZpc2libGUnKSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmRhdGUoZC5jbG9uZSgpLmFkZCgxLCAnTScpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZW50ZXI6IGZ1bmN0aW9uIGVudGVyKCkge1xuICAgICAgICAgICAgICAgIHRoaXMuaGlkZSgpO1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGVzY2FwZTogZnVuY3Rpb24gZXNjYXBlKCkge1xuICAgICAgICAgICAgICAgIGlmICghdGhpcy53aWRnZXQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLmhpZGUoKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAnY29udHJvbCBzcGFjZSc6IGZ1bmN0aW9uIGNvbnRyb2xTcGFjZSgpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMud2lkZ2V0KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMud2lkZ2V0LmZpbmQoJy50aW1lcGlja2VyJykuaXMoJzp2aXNpYmxlJykpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy53aWRnZXQuZmluZCgnLmJ0bltkYXRhLWFjdGlvbj1cInRvZ2dsZVBlcmlvZFwiXScpLmNsaWNrKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHQ6IGZ1bmN0aW9uIHQoKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5kYXRlKHRoaXMuZ2V0TW9tZW50KCkpO1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICdkZWxldGUnOiBmdW5jdGlvbiBfZGVsZXRlKCkge1xuICAgICAgICAgICAgICAgIGlmICghdGhpcy53aWRnZXQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLmNsZWFyKCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIGRlYnVnOiBmYWxzZSxcbiAgICAgICAgYWxsb3dJbnB1dFRvZ2dsZTogZmFsc2UsXG4gICAgICAgIGRpc2FibGVkVGltZUludGVydmFsczogZmFsc2UsXG4gICAgICAgIGRpc2FibGVkSG91cnM6IGZhbHNlLFxuICAgICAgICBlbmFibGVkSG91cnM6IGZhbHNlLFxuICAgICAgICB2aWV3RGF0ZTogZmFsc2UsXG4gICAgICAgIGFsbG93TXVsdGlkYXRlOiBmYWxzZSxcbiAgICAgICAgbXVsdGlkYXRlU2VwYXJhdG9yOiAnLCdcbiAgICB9O1xuXG4gICAgLy8gUmVTaGFycGVyIHJlc3RvcmUgSW5jb25zaXN0ZW50TmFtaW5nXG5cbiAgICAvLyBSZVNoYXJwZXIgZGlzYWJsZSBvbmNlIERlY2xhcmF0aW9uSGlkZXNcbiAgICAvLyBSZVNoYXJwZXIgZGlzYWJsZSBvbmNlIEluY29uc2lzdGVudE5hbWluZ1xuXG4gICAgdmFyIERhdGVUaW1lUGlja2VyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAvKiogQG5hbWVzcGFjZSBlRGF0YS5kYXRlT3B0aW9ucyAqL1xuICAgICAgICAvKiogQG5hbWVzcGFjZSBtb21lbnQudHogKi9cblxuICAgICAgICBmdW5jdGlvbiBEYXRlVGltZVBpY2tlcihlbGVtZW50LCBvcHRpb25zKSB7XG4gICAgICAgICAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgRGF0ZVRpbWVQaWNrZXIpO1xuXG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zID0gdGhpcy5fZ2V0T3B0aW9ucyhvcHRpb25zKTtcbiAgICAgICAgICAgIHRoaXMuX2VsZW1lbnQgPSBlbGVtZW50O1xuICAgICAgICAgICAgdGhpcy5fZGF0ZXMgPSBbXTtcbiAgICAgICAgICAgIHRoaXMuX2RhdGVzRm9ybWF0dGVkID0gW107XG4gICAgICAgICAgICB0aGlzLl92aWV3RGF0ZSA9IG51bGw7XG4gICAgICAgICAgICB0aGlzLnVuc2V0ID0gdHJ1ZTtcbiAgICAgICAgICAgIHRoaXMuY29tcG9uZW50ID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLndpZGdldCA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy51c2UyNEhvdXJzID0gbnVsbDtcbiAgICAgICAgICAgIHRoaXMuYWN0dWFsRm9ybWF0ID0gbnVsbDtcbiAgICAgICAgICAgIHRoaXMucGFyc2VGb3JtYXRzID0gbnVsbDtcbiAgICAgICAgICAgIHRoaXMuY3VycmVudFZpZXdNb2RlID0gbnVsbDtcblxuICAgICAgICAgICAgdGhpcy5faW50KCk7XG4gICAgICAgIH1cblxuICAgICAgICAvKipcclxuICAgICAgICAgKiBAcmV0dXJuIHtzdHJpbmd9XHJcbiAgICAgICAgICovXG5cblxuICAgICAgICAvL3ByaXZhdGVcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuX2ludCA9IGZ1bmN0aW9uIF9pbnQoKSB7XG4gICAgICAgICAgICB2YXIgdGFyZ2V0SW5wdXQgPSB0aGlzLl9lbGVtZW50LmRhdGEoJ3RhcmdldC1pbnB1dCcpO1xuICAgICAgICAgICAgaWYgKHRoaXMuX2VsZW1lbnQuaXMoJ2lucHV0JykpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmlucHV0ID0gdGhpcy5fZWxlbWVudDtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAodGFyZ2V0SW5wdXQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIGlmICh0YXJnZXRJbnB1dCA9PT0gJ25lYXJlc3QnKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuaW5wdXQgPSB0aGlzLl9lbGVtZW50LmZpbmQoJ2lucHV0Jyk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5pbnB1dCA9ICQodGFyZ2V0SW5wdXQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5fZGF0ZXMgPSBbXTtcbiAgICAgICAgICAgIHRoaXMuX2RhdGVzWzBdID0gdGhpcy5nZXRNb21lbnQoKTtcbiAgICAgICAgICAgIHRoaXMuX3ZpZXdEYXRlID0gdGhpcy5nZXRNb21lbnQoKS5jbG9uZSgpO1xuXG4gICAgICAgICAgICAkLmV4dGVuZCh0cnVlLCB0aGlzLl9vcHRpb25zLCB0aGlzLl9kYXRhVG9PcHRpb25zKCkpO1xuXG4gICAgICAgICAgICB0aGlzLm9wdGlvbnModGhpcy5fb3B0aW9ucyk7XG5cbiAgICAgICAgICAgIHRoaXMuX2luaXRGb3JtYXR0aW5nKCk7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLmlucHV0ICE9PSB1bmRlZmluZWQgJiYgdGhpcy5pbnB1dC5pcygnaW5wdXQnKSAmJiB0aGlzLmlucHV0LnZhbCgpLnRyaW0oKS5sZW5ndGggIT09IDApIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9zZXRWYWx1ZSh0aGlzLl9wYXJzZUlucHV0RGF0ZSh0aGlzLmlucHV0LnZhbCgpLnRyaW0oKSksIDApO1xuICAgICAgICAgICAgfSBlbHNlIGlmICh0aGlzLl9vcHRpb25zLmRlZmF1bHREYXRlICYmIHRoaXMuaW5wdXQgIT09IHVuZGVmaW5lZCAmJiB0aGlzLmlucHV0LmF0dHIoJ3BsYWNlaG9sZGVyJykgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIHRoaXMuX3NldFZhbHVlKHRoaXMuX29wdGlvbnMuZGVmYXVsdERhdGUsIDApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMuaW5saW5lKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zaG93KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl91cGRhdGUgPSBmdW5jdGlvbiBfdXBkYXRlKCkge1xuICAgICAgICAgICAgaWYgKCF0aGlzLndpZGdldCkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX2ZpbGxEYXRlKCk7XG4gICAgICAgICAgICB0aGlzLl9maWxsVGltZSgpO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5fc2V0VmFsdWUgPSBmdW5jdGlvbiBfc2V0VmFsdWUodGFyZ2V0TW9tZW50LCBpbmRleCkge1xuICAgICAgICAgICAgdmFyIG9sZERhdGUgPSB0aGlzLnVuc2V0ID8gbnVsbCA6IHRoaXMuX2RhdGVzW2luZGV4XTtcbiAgICAgICAgICAgIHZhciBvdXRwVmFsdWUgPSAnJztcbiAgICAgICAgICAgIC8vIGNhc2Ugb2YgY2FsbGluZyBzZXRWYWx1ZShudWxsIG9yIGZhbHNlKVxuICAgICAgICAgICAgaWYgKCF0YXJnZXRNb21lbnQpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuX29wdGlvbnMuYWxsb3dNdWx0aWRhdGUgfHwgdGhpcy5fZGF0ZXMubGVuZ3RoID09PSAxKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMudW5zZXQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9kYXRlcyA9IFtdO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9kYXRlc0Zvcm1hdHRlZCA9IFtdO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG91dHBWYWx1ZSA9IHRoaXMuX2VsZW1lbnQuZGF0YSgnZGF0ZScpICsgJywnO1xuICAgICAgICAgICAgICAgICAgICBvdXRwVmFsdWUgPSBvdXRwVmFsdWUucmVwbGFjZShvbGREYXRlLmZvcm1hdCh0aGlzLmFjdHVhbEZvcm1hdCkgKyAnLCcsICcnKS5yZXBsYWNlKCcsLCcsICcnKS5yZXBsYWNlKC8sXFxzKiQvLCAnJyk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX2RhdGVzLnNwbGljZShpbmRleCwgMSk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX2RhdGVzRm9ybWF0dGVkLnNwbGljZShpbmRleCwgMSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICh0aGlzLmlucHV0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5pbnB1dC52YWwob3V0cFZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5pbnB1dC50cmlnZ2VyKCdpbnB1dCcpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLl9lbGVtZW50LmRhdGEoJ2RhdGUnLCBvdXRwVmFsdWUpO1xuICAgICAgICAgICAgICAgIHRoaXMuX25vdGlmeUV2ZW50KHtcbiAgICAgICAgICAgICAgICAgICAgdHlwZTogRGF0ZVRpbWVQaWNrZXIuRXZlbnQuQ0hBTkdFLFxuICAgICAgICAgICAgICAgICAgICBkYXRlOiBmYWxzZSxcbiAgICAgICAgICAgICAgICAgICAgb2xkRGF0ZTogb2xkRGF0ZVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHRoaXMuX3VwZGF0ZSgpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGFyZ2V0TW9tZW50ID0gdGFyZ2V0TW9tZW50LmNsb25lKCkubG9jYWxlKHRoaXMuX29wdGlvbnMubG9jYWxlKTtcblxuICAgICAgICAgICAgaWYgKHRoaXMuX2hhc1RpbWVab25lKCkpIHtcbiAgICAgICAgICAgICAgICB0YXJnZXRNb21lbnQudHoodGhpcy5fb3B0aW9ucy50aW1lWm9uZSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0aGlzLl9vcHRpb25zLnN0ZXBwaW5nICE9PSAxKSB7XG4gICAgICAgICAgICAgICAgdGFyZ2V0TW9tZW50Lm1pbnV0ZXMoTWF0aC5yb3VuZCh0YXJnZXRNb21lbnQubWludXRlcygpIC8gdGhpcy5fb3B0aW9ucy5zdGVwcGluZykgKiB0aGlzLl9vcHRpb25zLnN0ZXBwaW5nKS5zZWNvbmRzKDApO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodGhpcy5faXNWYWxpZCh0YXJnZXRNb21lbnQpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fZGF0ZXNbaW5kZXhdID0gdGFyZ2V0TW9tZW50O1xuICAgICAgICAgICAgICAgIHRoaXMuX2RhdGVzRm9ybWF0dGVkW2luZGV4XSA9IHRhcmdldE1vbWVudC5mb3JtYXQoJ1lZWVktTU0tREQnKTtcbiAgICAgICAgICAgICAgICB0aGlzLl92aWV3RGF0ZSA9IHRhcmdldE1vbWVudC5jbG9uZSgpO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLl9vcHRpb25zLmFsbG93TXVsdGlkYXRlICYmIHRoaXMuX2RhdGVzLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLl9kYXRlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgb3V0cFZhbHVlICs9ICcnICsgdGhpcy5fZGF0ZXNbaV0uZm9ybWF0KHRoaXMuYWN0dWFsRm9ybWF0KSArIHRoaXMuX29wdGlvbnMubXVsdGlkYXRlU2VwYXJhdG9yO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIG91dHBWYWx1ZSA9IG91dHBWYWx1ZS5yZXBsYWNlKC8sXFxzKiQvLCAnJyk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgb3V0cFZhbHVlID0gdGhpcy5fZGF0ZXNbaW5kZXhdLmZvcm1hdCh0aGlzLmFjdHVhbEZvcm1hdCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICh0aGlzLmlucHV0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5pbnB1dC52YWwob3V0cFZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5pbnB1dC50cmlnZ2VyKCdpbnB1dCcpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLl9lbGVtZW50LmRhdGEoJ2RhdGUnLCBvdXRwVmFsdWUpO1xuXG4gICAgICAgICAgICAgICAgdGhpcy51bnNldCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHRoaXMuX3VwZGF0ZSgpO1xuICAgICAgICAgICAgICAgIHRoaXMuX25vdGlmeUV2ZW50KHtcbiAgICAgICAgICAgICAgICAgICAgdHlwZTogRGF0ZVRpbWVQaWNrZXIuRXZlbnQuQ0hBTkdFLFxuICAgICAgICAgICAgICAgICAgICBkYXRlOiB0aGlzLl9kYXRlc1tpbmRleF0uY2xvbmUoKSxcbiAgICAgICAgICAgICAgICAgICAgb2xkRGF0ZTogb2xkRGF0ZVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuX29wdGlvbnMua2VlcEludmFsaWQpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuaW5wdXQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5pbnB1dC52YWwoJycgKyAodGhpcy51bnNldCA/ICcnIDogdGhpcy5fZGF0ZXNbaW5kZXhdLmZvcm1hdCh0aGlzLmFjdHVhbEZvcm1hdCkpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuaW5wdXQudHJpZ2dlcignaW5wdXQnKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX25vdGlmeUV2ZW50KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6IERhdGVUaW1lUGlja2VyLkV2ZW50LkNIQU5HRSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGRhdGU6IHRhcmdldE1vbWVudCxcbiAgICAgICAgICAgICAgICAgICAgICAgIG9sZERhdGU6IG9sZERhdGVcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMuX25vdGlmeUV2ZW50KHtcbiAgICAgICAgICAgICAgICAgICAgdHlwZTogRGF0ZVRpbWVQaWNrZXIuRXZlbnQuRVJST1IsXG4gICAgICAgICAgICAgICAgICAgIGRhdGU6IHRhcmdldE1vbWVudCxcbiAgICAgICAgICAgICAgICAgICAgb2xkRGF0ZTogb2xkRGF0ZVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5fY2hhbmdlID0gZnVuY3Rpb24gX2NoYW5nZShlKSB7XG4gICAgICAgICAgICB2YXIgdmFsID0gJChlLnRhcmdldCkudmFsKCkudHJpbSgpLFxuICAgICAgICAgICAgICAgIHBhcnNlZERhdGUgPSB2YWwgPyB0aGlzLl9wYXJzZUlucHV0RGF0ZSh2YWwpIDogbnVsbDtcbiAgICAgICAgICAgIHRoaXMuX3NldFZhbHVlKHBhcnNlZERhdGUpO1xuICAgICAgICAgICAgZS5zdG9wSW1tZWRpYXRlUHJvcGFnYXRpb24oKTtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfTtcblxuICAgICAgICAvL25vaW5zcGVjdGlvbiBKU01ldGhvZENhbkJlU3RhdGljXG5cblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuX2dldE9wdGlvbnMgPSBmdW5jdGlvbiBfZ2V0T3B0aW9ucyhvcHRpb25zKSB7XG4gICAgICAgICAgICBvcHRpb25zID0gJC5leHRlbmQodHJ1ZSwge30sIERlZmF1bHQsIG9wdGlvbnMpO1xuICAgICAgICAgICAgcmV0dXJuIG9wdGlvbnM7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl9oYXNUaW1lWm9uZSA9IGZ1bmN0aW9uIF9oYXNUaW1lWm9uZSgpIHtcbiAgICAgICAgICAgIHJldHVybiBtb21lbnQudHogIT09IHVuZGVmaW5lZCAmJiB0aGlzLl9vcHRpb25zLnRpbWVab25lICE9PSB1bmRlZmluZWQgJiYgdGhpcy5fb3B0aW9ucy50aW1lWm9uZSAhPT0gbnVsbCAmJiB0aGlzLl9vcHRpb25zLnRpbWVab25lICE9PSAnJztcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuX2lzRW5hYmxlZCA9IGZ1bmN0aW9uIF9pc0VuYWJsZWQoZ3JhbnVsYXJpdHkpIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgZ3JhbnVsYXJpdHkgIT09ICdzdHJpbmcnIHx8IGdyYW51bGFyaXR5Lmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdpc0VuYWJsZWQgZXhwZWN0cyBhIHNpbmdsZSBjaGFyYWN0ZXIgc3RyaW5nIHBhcmFtZXRlcicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc3dpdGNoIChncmFudWxhcml0eSkge1xuICAgICAgICAgICAgICAgIGNhc2UgJ3knOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5hY3R1YWxGb3JtYXQuaW5kZXhPZignWScpICE9PSAtMTtcbiAgICAgICAgICAgICAgICBjYXNlICdNJzpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuYWN0dWFsRm9ybWF0LmluZGV4T2YoJ00nKSAhPT0gLTE7XG4gICAgICAgICAgICAgICAgY2FzZSAnZCc6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmFjdHVhbEZvcm1hdC50b0xvd2VyQ2FzZSgpLmluZGV4T2YoJ2QnKSAhPT0gLTE7XG4gICAgICAgICAgICAgICAgY2FzZSAnaCc6XG4gICAgICAgICAgICAgICAgY2FzZSAnSCc6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmFjdHVhbEZvcm1hdC50b0xvd2VyQ2FzZSgpLmluZGV4T2YoJ2gnKSAhPT0gLTE7XG4gICAgICAgICAgICAgICAgY2FzZSAnbSc6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmFjdHVhbEZvcm1hdC5pbmRleE9mKCdtJykgIT09IC0xO1xuICAgICAgICAgICAgICAgIGNhc2UgJ3MnOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5hY3R1YWxGb3JtYXQuaW5kZXhPZigncycpICE9PSAtMTtcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl9oYXNUaW1lID0gZnVuY3Rpb24gX2hhc1RpbWUoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5faXNFbmFibGVkKCdoJykgfHwgdGhpcy5faXNFbmFibGVkKCdtJykgfHwgdGhpcy5faXNFbmFibGVkKCdzJyk7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl9oYXNEYXRlID0gZnVuY3Rpb24gX2hhc0RhdGUoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5faXNFbmFibGVkKCd5JykgfHwgdGhpcy5faXNFbmFibGVkKCdNJykgfHwgdGhpcy5faXNFbmFibGVkKCdkJyk7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl9kYXRhVG9PcHRpb25zID0gZnVuY3Rpb24gX2RhdGFUb09wdGlvbnMoKSB7XG4gICAgICAgICAgICB2YXIgZURhdGEgPSB0aGlzLl9lbGVtZW50LmRhdGEoKTtcbiAgICAgICAgICAgIHZhciBkYXRhT3B0aW9ucyA9IHt9O1xuXG4gICAgICAgICAgICBpZiAoZURhdGEuZGF0ZU9wdGlvbnMgJiYgZURhdGEuZGF0ZU9wdGlvbnMgaW5zdGFuY2VvZiBPYmplY3QpIHtcbiAgICAgICAgICAgICAgICBkYXRhT3B0aW9ucyA9ICQuZXh0ZW5kKHRydWUsIGRhdGFPcHRpb25zLCBlRGF0YS5kYXRlT3B0aW9ucyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICQuZWFjaCh0aGlzLl9vcHRpb25zLCBmdW5jdGlvbiAoa2V5KSB7XG4gICAgICAgICAgICAgICAgdmFyIGF0dHJpYnV0ZU5hbWUgPSAnZGF0ZScgKyBrZXkuY2hhckF0KDApLnRvVXBwZXJDYXNlKCkgKyBrZXkuc2xpY2UoMSk7IC8vdG9kbyBkYXRhIGFwaSBrZXlcbiAgICAgICAgICAgICAgICBpZiAoZURhdGFbYXR0cmlidXRlTmFtZV0gIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICBkYXRhT3B0aW9uc1trZXldID0gZURhdGFbYXR0cmlidXRlTmFtZV07XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIGRhdGFPcHRpb25zW2tleV07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZXR1cm4gZGF0YU9wdGlvbnM7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl9ub3RpZnlFdmVudCA9IGZ1bmN0aW9uIF9ub3RpZnlFdmVudChlKSB7XG4gICAgICAgICAgICBpZiAoZS50eXBlID09PSBEYXRlVGltZVBpY2tlci5FdmVudC5DSEFOR0UgJiYgZS5kYXRlICYmIGUuZGF0ZS5pc1NhbWUoZS5vbGREYXRlKSB8fCAhZS5kYXRlICYmICFlLm9sZERhdGUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl9lbGVtZW50LnRyaWdnZXIoZSk7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl92aWV3VXBkYXRlID0gZnVuY3Rpb24gX3ZpZXdVcGRhdGUoZSkge1xuICAgICAgICAgICAgaWYgKGUgPT09ICd5Jykge1xuICAgICAgICAgICAgICAgIGUgPSAnWVlZWSc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl9ub3RpZnlFdmVudCh7XG4gICAgICAgICAgICAgICAgdHlwZTogRGF0ZVRpbWVQaWNrZXIuRXZlbnQuVVBEQVRFLFxuICAgICAgICAgICAgICAgIGNoYW5nZTogZSxcbiAgICAgICAgICAgICAgICB2aWV3RGF0ZTogdGhpcy5fdmlld0RhdGUuY2xvbmUoKVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl9zaG93TW9kZSA9IGZ1bmN0aW9uIF9zaG93TW9kZShkaXIpIHtcbiAgICAgICAgICAgIGlmICghdGhpcy53aWRnZXQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoZGlyKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50Vmlld01vZGUgPSBNYXRoLm1heChNaW5WaWV3TW9kZU51bWJlciwgTWF0aC5taW4oMywgdGhpcy5jdXJyZW50Vmlld01vZGUgKyBkaXIpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMud2lkZ2V0LmZpbmQoJy5kYXRlcGlja2VyID4gZGl2JykuaGlkZSgpLmZpbHRlcignLmRhdGVwaWNrZXItJyArIERhdGVQaWNrZXJNb2Rlc1t0aGlzLmN1cnJlbnRWaWV3TW9kZV0uQ0xBU1NfTkFNRSkuc2hvdygpO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5faXNJbkRpc2FibGVkRGF0ZXMgPSBmdW5jdGlvbiBfaXNJbkRpc2FibGVkRGF0ZXModGVzdERhdGUpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLmRpc2FibGVkRGF0ZXNbdGVzdERhdGUuZm9ybWF0KCdZWVlZLU1NLUREJyldID09PSB0cnVlO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5faXNJbkVuYWJsZWREYXRlcyA9IGZ1bmN0aW9uIF9pc0luRW5hYmxlZERhdGVzKHRlc3REYXRlKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5lbmFibGVkRGF0ZXNbdGVzdERhdGUuZm9ybWF0KCdZWVlZLU1NLUREJyldID09PSB0cnVlO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5faXNJbkRpc2FibGVkSG91cnMgPSBmdW5jdGlvbiBfaXNJbkRpc2FibGVkSG91cnModGVzdERhdGUpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLmRpc2FibGVkSG91cnNbdGVzdERhdGUuZm9ybWF0KCdIJyldID09PSB0cnVlO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5faXNJbkVuYWJsZWRIb3VycyA9IGZ1bmN0aW9uIF9pc0luRW5hYmxlZEhvdXJzKHRlc3REYXRlKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5lbmFibGVkSG91cnNbdGVzdERhdGUuZm9ybWF0KCdIJyldID09PSB0cnVlO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5faXNWYWxpZCA9IGZ1bmN0aW9uIF9pc1ZhbGlkKHRhcmdldE1vbWVudCwgZ3JhbnVsYXJpdHkpIHtcbiAgICAgICAgICAgIGlmICghdGFyZ2V0TW9tZW50LmlzVmFsaWQoKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLl9vcHRpb25zLmRpc2FibGVkRGF0ZXMgJiYgZ3JhbnVsYXJpdHkgPT09ICdkJyAmJiB0aGlzLl9pc0luRGlzYWJsZWREYXRlcyh0YXJnZXRNb21lbnQpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMuZW5hYmxlZERhdGVzICYmIGdyYW51bGFyaXR5ID09PSAnZCcgJiYgIXRoaXMuX2lzSW5FbmFibGVkRGF0ZXModGFyZ2V0TW9tZW50KSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLl9vcHRpb25zLm1pbkRhdGUgJiYgdGFyZ2V0TW9tZW50LmlzQmVmb3JlKHRoaXMuX29wdGlvbnMubWluRGF0ZSwgZ3JhbnVsYXJpdHkpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMubWF4RGF0ZSAmJiB0YXJnZXRNb21lbnQuaXNBZnRlcih0aGlzLl9vcHRpb25zLm1heERhdGUsIGdyYW51bGFyaXR5KSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLl9vcHRpb25zLmRheXNPZldlZWtEaXNhYmxlZCAmJiBncmFudWxhcml0eSA9PT0gJ2QnICYmIHRoaXMuX29wdGlvbnMuZGF5c09mV2Vla0Rpc2FibGVkLmluZGV4T2YodGFyZ2V0TW9tZW50LmRheSgpKSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy5kaXNhYmxlZEhvdXJzICYmIChncmFudWxhcml0eSA9PT0gJ2gnIHx8IGdyYW51bGFyaXR5ID09PSAnbScgfHwgZ3JhbnVsYXJpdHkgPT09ICdzJykgJiYgdGhpcy5faXNJbkRpc2FibGVkSG91cnModGFyZ2V0TW9tZW50KSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLl9vcHRpb25zLmVuYWJsZWRIb3VycyAmJiAoZ3JhbnVsYXJpdHkgPT09ICdoJyB8fCBncmFudWxhcml0eSA9PT0gJ20nIHx8IGdyYW51bGFyaXR5ID09PSAncycpICYmICF0aGlzLl9pc0luRW5hYmxlZEhvdXJzKHRhcmdldE1vbWVudCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy5kaXNhYmxlZFRpbWVJbnRlcnZhbHMgJiYgKGdyYW51bGFyaXR5ID09PSAnaCcgfHwgZ3JhbnVsYXJpdHkgPT09ICdtJyB8fCBncmFudWxhcml0eSA9PT0gJ3MnKSkge1xuICAgICAgICAgICAgICAgIHZhciBmb3VuZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICQuZWFjaCh0aGlzLl9vcHRpb25zLmRpc2FibGVkVGltZUludGVydmFscywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodGFyZ2V0TW9tZW50LmlzQmV0d2Vlbih0aGlzWzBdLCB0aGlzWzFdKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZm91bmQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgaWYgKGZvdW5kKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuX3BhcnNlSW5wdXREYXRlID0gZnVuY3Rpb24gX3BhcnNlSW5wdXREYXRlKGlucHV0RGF0ZSkge1xuICAgICAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMucGFyc2VJbnB1dERhdGUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIGlmICghbW9tZW50LmlzTW9tZW50KGlucHV0RGF0ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgaW5wdXREYXRlID0gdGhpcy5nZXRNb21lbnQoaW5wdXREYXRlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGlucHV0RGF0ZSA9IHRoaXMuX29wdGlvbnMucGFyc2VJbnB1dERhdGUoaW5wdXREYXRlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vaW5wdXREYXRlLmxvY2FsZSh0aGlzLm9wdGlvbnMubG9jYWxlKTtcbiAgICAgICAgICAgIHJldHVybiBpbnB1dERhdGU7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl9rZXlkb3duID0gZnVuY3Rpb24gX2tleWRvd24oZSkge1xuICAgICAgICAgICAgdmFyIGhhbmRsZXIgPSBudWxsLFxuICAgICAgICAgICAgICAgIGluZGV4ID0gdm9pZCAwLFxuICAgICAgICAgICAgICAgIGluZGV4MiA9IHZvaWQgMCxcbiAgICAgICAgICAgICAgICBrZXlCaW5kS2V5cyA9IHZvaWQgMCxcbiAgICAgICAgICAgICAgICBhbGxNb2RpZmllcnNQcmVzc2VkID0gdm9pZCAwO1xuICAgICAgICAgICAgdmFyIHByZXNzZWRLZXlzID0gW10sXG4gICAgICAgICAgICAgICAgcHJlc3NlZE1vZGlmaWVycyA9IHt9LFxuICAgICAgICAgICAgICAgIGN1cnJlbnRLZXkgPSBlLndoaWNoLFxuICAgICAgICAgICAgICAgIHByZXNzZWQgPSAncCc7XG5cbiAgICAgICAgICAgIGtleVN0YXRlW2N1cnJlbnRLZXldID0gcHJlc3NlZDtcblxuICAgICAgICAgICAgZm9yIChpbmRleCBpbiBrZXlTdGF0ZSkge1xuICAgICAgICAgICAgICAgIGlmIChrZXlTdGF0ZS5oYXNPd25Qcm9wZXJ0eShpbmRleCkgJiYga2V5U3RhdGVbaW5kZXhdID09PSBwcmVzc2VkKSB7XG4gICAgICAgICAgICAgICAgICAgIHByZXNzZWRLZXlzLnB1c2goaW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICBpZiAocGFyc2VJbnQoaW5kZXgsIDEwKSAhPT0gY3VycmVudEtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJlc3NlZE1vZGlmaWVyc1tpbmRleF0gPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmb3IgKGluZGV4IGluIHRoaXMuX29wdGlvbnMua2V5QmluZHMpIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy5rZXlCaW5kcy5oYXNPd25Qcm9wZXJ0eShpbmRleCkgJiYgdHlwZW9mIHRoaXMuX29wdGlvbnMua2V5QmluZHNbaW5kZXhdID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICAgICAgICAgIGtleUJpbmRLZXlzID0gaW5kZXguc3BsaXQoJyAnKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGtleUJpbmRLZXlzLmxlbmd0aCA9PT0gcHJlc3NlZEtleXMubGVuZ3RoICYmIEtleU1hcFtjdXJyZW50S2V5XSA9PT0ga2V5QmluZEtleXNba2V5QmluZEtleXMubGVuZ3RoIC0gMV0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFsbE1vZGlmaWVyc1ByZXNzZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChpbmRleDIgPSBrZXlCaW5kS2V5cy5sZW5ndGggLSAyOyBpbmRleDIgPj0gMDsgaW5kZXgyLS0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIShLZXlNYXBba2V5QmluZEtleXNbaW5kZXgyXV0gaW4gcHJlc3NlZE1vZGlmaWVycykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWxsTW9kaWZpZXJzUHJlc3NlZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYWxsTW9kaWZpZXJzUHJlc3NlZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhbmRsZXIgPSB0aGlzLl9vcHRpb25zLmtleUJpbmRzW2luZGV4XTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGhhbmRsZXIpIHtcbiAgICAgICAgICAgICAgICBpZiAoaGFuZGxlci5jYWxsKHRoaXMud2lkZ2V0KSkge1xuICAgICAgICAgICAgICAgICAgICBlLnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgICAgICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIC8vbm9pbnNwZWN0aW9uIEpTTWV0aG9kQ2FuQmVTdGF0aWMsU3BlbGxDaGVja2luZ0luc3BlY3Rpb25cblxuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5fa2V5dXAgPSBmdW5jdGlvbiBfa2V5dXAoZSkge1xuICAgICAgICAgICAga2V5U3RhdGVbZS53aGljaF0gPSAncic7XG4gICAgICAgICAgICBpZiAoa2V5UHJlc3NIYW5kbGVkW2Uud2hpY2hdKSB7XG4gICAgICAgICAgICAgICAga2V5UHJlc3NIYW5kbGVkW2Uud2hpY2hdID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgZS5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl9pbmRleEdpdmVuRGF0ZXMgPSBmdW5jdGlvbiBfaW5kZXhHaXZlbkRhdGVzKGdpdmVuRGF0ZXNBcnJheSkge1xuICAgICAgICAgICAgLy8gU3RvcmUgZ2l2ZW4gZW5hYmxlZERhdGVzIGFuZCBkaXNhYmxlZERhdGVzIGFzIGtleXMuXG4gICAgICAgICAgICAvLyBUaGlzIHdheSB3ZSBjYW4gY2hlY2sgdGhlaXIgZXhpc3RlbmNlIGluIE8oMSkgdGltZSBpbnN0ZWFkIG9mIGxvb3BpbmcgdGhyb3VnaCB3aG9sZSBhcnJheS5cbiAgICAgICAgICAgIC8vIChmb3IgZXhhbXBsZTogb3B0aW9ucy5lbmFibGVkRGF0ZXNbJzIwMTQtMDItMjcnXSA9PT0gdHJ1ZSlcbiAgICAgICAgICAgIHZhciBnaXZlbkRhdGVzSW5kZXhlZCA9IHt9LFxuICAgICAgICAgICAgICAgIHNlbGYgPSB0aGlzO1xuICAgICAgICAgICAgJC5lYWNoKGdpdmVuRGF0ZXNBcnJheSwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHZhciBkRGF0ZSA9IHNlbGYuX3BhcnNlSW5wdXREYXRlKHRoaXMpO1xuICAgICAgICAgICAgICAgIGlmIChkRGF0ZS5pc1ZhbGlkKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgZ2l2ZW5EYXRlc0luZGV4ZWRbZERhdGUuZm9ybWF0KCdZWVlZLU1NLUREJyldID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHJldHVybiBPYmplY3Qua2V5cyhnaXZlbkRhdGVzSW5kZXhlZCkubGVuZ3RoID8gZ2l2ZW5EYXRlc0luZGV4ZWQgOiBmYWxzZTtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuX2luZGV4R2l2ZW5Ib3VycyA9IGZ1bmN0aW9uIF9pbmRleEdpdmVuSG91cnMoZ2l2ZW5Ib3Vyc0FycmF5KSB7XG4gICAgICAgICAgICAvLyBTdG9yZSBnaXZlbiBlbmFibGVkSG91cnMgYW5kIGRpc2FibGVkSG91cnMgYXMga2V5cy5cbiAgICAgICAgICAgIC8vIFRoaXMgd2F5IHdlIGNhbiBjaGVjayB0aGVpciBleGlzdGVuY2UgaW4gTygxKSB0aW1lIGluc3RlYWQgb2YgbG9vcGluZyB0aHJvdWdoIHdob2xlIGFycmF5LlxuICAgICAgICAgICAgLy8gKGZvciBleGFtcGxlOiBvcHRpb25zLmVuYWJsZWRIb3Vyc1snMjAxNC0wMi0yNyddID09PSB0cnVlKVxuICAgICAgICAgICAgdmFyIGdpdmVuSG91cnNJbmRleGVkID0ge307XG4gICAgICAgICAgICAkLmVhY2goZ2l2ZW5Ib3Vyc0FycmF5LCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgZ2l2ZW5Ib3Vyc0luZGV4ZWRbdGhpc10gPSB0cnVlO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZXR1cm4gT2JqZWN0LmtleXMoZ2l2ZW5Ib3Vyc0luZGV4ZWQpLmxlbmd0aCA/IGdpdmVuSG91cnNJbmRleGVkIDogZmFsc2U7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl9pbml0Rm9ybWF0dGluZyA9IGZ1bmN0aW9uIF9pbml0Rm9ybWF0dGluZygpIHtcbiAgICAgICAgICAgIHZhciBmb3JtYXQgPSB0aGlzLl9vcHRpb25zLmZvcm1hdCB8fCAnTCBMVCcsXG4gICAgICAgICAgICAgICAgc2VsZiA9IHRoaXM7XG5cbiAgICAgICAgICAgIHRoaXMuYWN0dWFsRm9ybWF0ID0gZm9ybWF0LnJlcGxhY2UoLyhcXFtbXlxcW10qXSl8KFxcXFwpPyhMVFN8TFR8TEw/TD9MP3xsezEsNH0pL2csIGZ1bmN0aW9uIChmb3JtYXRJbnB1dCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBzZWxmLl9kYXRlc1swXS5sb2NhbGVEYXRhKCkubG9uZ0RhdGVGb3JtYXQoZm9ybWF0SW5wdXQpIHx8IGZvcm1hdElucHV0OyAvL3RvZG8gdGFraW5nIHRoZSBmaXJzdCBkYXRlIHNob3VsZCBiZSBva1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIHRoaXMucGFyc2VGb3JtYXRzID0gdGhpcy5fb3B0aW9ucy5leHRyYUZvcm1hdHMgPyB0aGlzLl9vcHRpb25zLmV4dHJhRm9ybWF0cy5zbGljZSgpIDogW107XG4gICAgICAgICAgICBpZiAodGhpcy5wYXJzZUZvcm1hdHMuaW5kZXhPZihmb3JtYXQpIDwgMCAmJiB0aGlzLnBhcnNlRm9ybWF0cy5pbmRleE9mKHRoaXMuYWN0dWFsRm9ybWF0KSA8IDApIHtcbiAgICAgICAgICAgICAgICB0aGlzLnBhcnNlRm9ybWF0cy5wdXNoKHRoaXMuYWN0dWFsRm9ybWF0KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy51c2UyNEhvdXJzID0gdGhpcy5hY3R1YWxGb3JtYXQudG9Mb3dlckNhc2UoKS5pbmRleE9mKCdhJykgPCAxICYmIHRoaXMuYWN0dWFsRm9ybWF0LnJlcGxhY2UoL1xcWy4qP10vZywgJycpLmluZGV4T2YoJ2gnKSA8IDE7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLl9pc0VuYWJsZWQoJ3knKSkge1xuICAgICAgICAgICAgICAgIE1pblZpZXdNb2RlTnVtYmVyID0gMjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLl9pc0VuYWJsZWQoJ00nKSkge1xuICAgICAgICAgICAgICAgIE1pblZpZXdNb2RlTnVtYmVyID0gMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLl9pc0VuYWJsZWQoJ2QnKSkge1xuICAgICAgICAgICAgICAgIE1pblZpZXdNb2RlTnVtYmVyID0gMDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5jdXJyZW50Vmlld01vZGUgPSBNYXRoLm1heChNaW5WaWV3TW9kZU51bWJlciwgdGhpcy5jdXJyZW50Vmlld01vZGUpO1xuXG4gICAgICAgICAgICBpZiAoIXRoaXMudW5zZXQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9zZXRWYWx1ZSh0aGlzLl9kYXRlc1swXSwgMCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl9nZXRMYXN0UGlja2VkRGF0ZSA9IGZ1bmN0aW9uIF9nZXRMYXN0UGlja2VkRGF0ZSgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9kYXRlc1t0aGlzLl9nZXRMYXN0UGlja2VkRGF0ZUluZGV4KCldO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5fZ2V0TGFzdFBpY2tlZERhdGVJbmRleCA9IGZ1bmN0aW9uIF9nZXRMYXN0UGlja2VkRGF0ZUluZGV4KCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2RhdGVzLmxlbmd0aCAtIDE7XG4gICAgICAgIH07XG5cbiAgICAgICAgLy9wdWJsaWNcblxuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5nZXRNb21lbnQgPSBmdW5jdGlvbiBnZXRNb21lbnQoZCkge1xuICAgICAgICAgICAgdmFyIHJldHVybk1vbWVudCA9IHZvaWQgMDtcblxuICAgICAgICAgICAgaWYgKGQgPT09IHVuZGVmaW5lZCB8fCBkID09PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuTW9tZW50ID0gbW9tZW50KCk7IC8vVE9ETyBzaG91bGQgdGhpcyB1c2UgZm9ybWF0PyBhbmQgbG9jYWxlP1xuICAgICAgICAgICAgfSBlbHNlIGlmICh0aGlzLl9oYXNUaW1lWm9uZSgpKSB7XG4gICAgICAgICAgICAgICAgLy8gVGhlcmUgaXMgYSBzdHJpbmcgdG8gcGFyc2UgYW5kIGEgZGVmYXVsdCB0aW1lIHpvbmVcbiAgICAgICAgICAgICAgICAvLyBwYXJzZSB3aXRoIHRoZSB0eiBmdW5jdGlvbiB3aGljaCB0YWtlcyBhIGRlZmF1bHQgdGltZSB6b25lIGlmIGl0IGlzIG5vdCBpbiB0aGUgZm9ybWF0IHN0cmluZ1xuICAgICAgICAgICAgICAgIHJldHVybk1vbWVudCA9IG1vbWVudC50eihkLCB0aGlzLnBhcnNlRm9ybWF0cywgdGhpcy5fb3B0aW9ucy51c2VTdHJpY3QsIHRoaXMuX29wdGlvbnMudGltZVpvbmUpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm5Nb21lbnQgPSBtb21lbnQoZCwgdGhpcy5wYXJzZUZvcm1hdHMsIHRoaXMuX29wdGlvbnMudXNlU3RyaWN0KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHRoaXMuX2hhc1RpbWVab25lKCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm5Nb21lbnQudHoodGhpcy5fb3B0aW9ucy50aW1lWm9uZSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiByZXR1cm5Nb21lbnQ7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLnRvZ2dsZSA9IGZ1bmN0aW9uIHRvZ2dsZSgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLndpZGdldCA/IHRoaXMuaGlkZSgpIDogdGhpcy5zaG93KCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLmlnbm9yZVJlYWRvbmx5ID0gZnVuY3Rpb24gaWdub3JlUmVhZG9ubHkoX2lnbm9yZVJlYWRvbmx5KSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLmlnbm9yZVJlYWRvbmx5O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHR5cGVvZiBfaWdub3JlUmVhZG9ubHkgIT09ICdib29sZWFuJykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2lnbm9yZVJlYWRvbmx5ICgpIGV4cGVjdHMgYSBib29sZWFuIHBhcmFtZXRlcicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5pZ25vcmVSZWFkb25seSA9IF9pZ25vcmVSZWFkb25seTtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUub3B0aW9ucyA9IGZ1bmN0aW9uIG9wdGlvbnMobmV3T3B0aW9ucykge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJC5leHRlbmQodHJ1ZSwge30sIHRoaXMuX29wdGlvbnMpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoIShuZXdPcHRpb25zIGluc3RhbmNlb2YgT2JqZWN0KSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ29wdGlvbnMoKSB0aGlzLm9wdGlvbnMgcGFyYW1ldGVyIHNob3VsZCBiZSBhbiBvYmplY3QnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgICQuZXh0ZW5kKHRydWUsIHRoaXMuX29wdGlvbnMsIG5ld09wdGlvbnMpO1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgICAgICAgICAgJC5lYWNoKHRoaXMuX29wdGlvbnMsIGZ1bmN0aW9uIChrZXksIHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKHNlbGZba2V5XSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlbGZba2V5XSh2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLmRhdGUgPSBmdW5jdGlvbiBkYXRlKG5ld0RhdGUsIGluZGV4KSB7XG4gICAgICAgICAgICBpbmRleCA9IGluZGV4IHx8IDA7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLnVuc2V0KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy5hbGxvd011bHRpZGF0ZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fZGF0ZXMuam9pbih0aGlzLl9vcHRpb25zLm11bHRpZGF0ZVNlcGFyYXRvcik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2RhdGVzW2luZGV4XS5jbG9uZSgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKG5ld0RhdGUgIT09IG51bGwgJiYgdHlwZW9mIG5ld0RhdGUgIT09ICdzdHJpbmcnICYmICFtb21lbnQuaXNNb21lbnQobmV3RGF0ZSkgJiYgIShuZXdEYXRlIGluc3RhbmNlb2YgRGF0ZSkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdkYXRlKCkgcGFyYW1ldGVyIG11c3QgYmUgb25lIG9mIFtudWxsLCBzdHJpbmcsIG1vbWVudCBvciBEYXRlXScpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLl9zZXRWYWx1ZShuZXdEYXRlID09PSBudWxsID8gbnVsbCA6IHRoaXMuX3BhcnNlSW5wdXREYXRlKG5ld0RhdGUpLCBpbmRleCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLmZvcm1hdCA9IGZ1bmN0aW9uIGZvcm1hdChuZXdGb3JtYXQpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMuZm9ybWF0O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodHlwZW9mIG5ld0Zvcm1hdCAhPT0gJ3N0cmluZycgJiYgKHR5cGVvZiBuZXdGb3JtYXQgIT09ICdib29sZWFuJyB8fCBuZXdGb3JtYXQgIT09IGZhbHNlKSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2Zvcm1hdCgpIGV4cGVjdHMgYSBzdHJpbmcgb3IgYm9vbGVhbjpmYWxzZSBwYXJhbWV0ZXIgJyArIG5ld0Zvcm1hdCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuZm9ybWF0ID0gbmV3Rm9ybWF0O1xuICAgICAgICAgICAgaWYgKHRoaXMuYWN0dWFsRm9ybWF0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5faW5pdEZvcm1hdHRpbmcoKTsgLy8gcmVpbml0aWFsaXplIGZvcm1hdHRpbmdcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUudGltZVpvbmUgPSBmdW5jdGlvbiB0aW1lWm9uZShuZXdab25lKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLnRpbWVab25lO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodHlwZW9mIG5ld1pvbmUgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignbmV3Wm9uZSgpIGV4cGVjdHMgYSBzdHJpbmcgcGFyYW1ldGVyJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMudGltZVpvbmUgPSBuZXdab25lO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5kYXlWaWV3SGVhZGVyRm9ybWF0ID0gZnVuY3Rpb24gZGF5Vmlld0hlYWRlckZvcm1hdChuZXdGb3JtYXQpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMuZGF5Vmlld0hlYWRlckZvcm1hdDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBuZXdGb3JtYXQgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignZGF5Vmlld0hlYWRlckZvcm1hdCgpIGV4cGVjdHMgYSBzdHJpbmcgcGFyYW1ldGVyJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuZGF5Vmlld0hlYWRlckZvcm1hdCA9IG5ld0Zvcm1hdDtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuZXh0cmFGb3JtYXRzID0gZnVuY3Rpb24gZXh0cmFGb3JtYXRzKGZvcm1hdHMpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMuZXh0cmFGb3JtYXRzO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoZm9ybWF0cyAhPT0gZmFsc2UgJiYgIShmb3JtYXRzIGluc3RhbmNlb2YgQXJyYXkpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignZXh0cmFGb3JtYXRzKCkgZXhwZWN0cyBhbiBhcnJheSBvciBmYWxzZSBwYXJhbWV0ZXInKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5leHRyYUZvcm1hdHMgPSBmb3JtYXRzO1xuICAgICAgICAgICAgaWYgKHRoaXMucGFyc2VGb3JtYXRzKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5faW5pdEZvcm1hdHRpbmcoKTsgLy8gcmVpbml0IGZvcm1hdHRpbmdcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuZGlzYWJsZWREYXRlcyA9IGZ1bmN0aW9uIGRpc2FibGVkRGF0ZXMoZGF0ZXMpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMuZGlzYWJsZWREYXRlcyA/ICQuZXh0ZW5kKHt9LCB0aGlzLl9vcHRpb25zLmRpc2FibGVkRGF0ZXMpIDogdGhpcy5fb3B0aW9ucy5kaXNhYmxlZERhdGVzO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoIWRhdGVzKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5kaXNhYmxlZERhdGVzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdGhpcy5fdXBkYXRlKCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIShkYXRlcyBpbnN0YW5jZW9mIEFycmF5KSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2Rpc2FibGVkRGF0ZXMoKSBleHBlY3RzIGFuIGFycmF5IHBhcmFtZXRlcicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5kaXNhYmxlZERhdGVzID0gdGhpcy5faW5kZXhHaXZlbkRhdGVzKGRhdGVzKTtcbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuZW5hYmxlZERhdGVzID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLl91cGRhdGUoKTtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuZW5hYmxlZERhdGVzID0gZnVuY3Rpb24gZW5hYmxlZERhdGVzKGRhdGVzKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLmVuYWJsZWREYXRlcyA/ICQuZXh0ZW5kKHt9LCB0aGlzLl9vcHRpb25zLmVuYWJsZWREYXRlcykgOiB0aGlzLl9vcHRpb25zLmVuYWJsZWREYXRlcztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCFkYXRlcykge1xuICAgICAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuZW5hYmxlZERhdGVzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdGhpcy5fdXBkYXRlKCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIShkYXRlcyBpbnN0YW5jZW9mIEFycmF5KSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2VuYWJsZWREYXRlcygpIGV4cGVjdHMgYW4gYXJyYXkgcGFyYW1ldGVyJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLmVuYWJsZWREYXRlcyA9IHRoaXMuX2luZGV4R2l2ZW5EYXRlcyhkYXRlcyk7XG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLmRpc2FibGVkRGF0ZXMgPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMuX3VwZGF0ZSgpO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5kYXlzT2ZXZWVrRGlzYWJsZWQgPSBmdW5jdGlvbiBkYXlzT2ZXZWVrRGlzYWJsZWQoX2RheXNPZldlZWtEaXNhYmxlZCkge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5kYXlzT2ZXZWVrRGlzYWJsZWQuc3BsaWNlKDApO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodHlwZW9mIF9kYXlzT2ZXZWVrRGlzYWJsZWQgPT09ICdib29sZWFuJyAmJiAhX2RheXNPZldlZWtEaXNhYmxlZCkge1xuICAgICAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuZGF5c09mV2Vla0Rpc2FibGVkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdGhpcy5fdXBkYXRlKCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICghKF9kYXlzT2ZXZWVrRGlzYWJsZWQgaW5zdGFuY2VvZiBBcnJheSkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdkYXlzT2ZXZWVrRGlzYWJsZWQoKSBleHBlY3RzIGFuIGFycmF5IHBhcmFtZXRlcicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5kYXlzT2ZXZWVrRGlzYWJsZWQgPSBfZGF5c09mV2Vla0Rpc2FibGVkLnJlZHVjZShmdW5jdGlvbiAocHJldmlvdXNWYWx1ZSwgY3VycmVudFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgY3VycmVudFZhbHVlID0gcGFyc2VJbnQoY3VycmVudFZhbHVlLCAxMCk7XG4gICAgICAgICAgICAgICAgaWYgKGN1cnJlbnRWYWx1ZSA+IDYgfHwgY3VycmVudFZhbHVlIDwgMCB8fCBpc05hTihjdXJyZW50VmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBwcmV2aW91c1ZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAocHJldmlvdXNWYWx1ZS5pbmRleE9mKGN1cnJlbnRWYWx1ZSkgPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgIHByZXZpb3VzVmFsdWUucHVzaChjdXJyZW50VmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gcHJldmlvdXNWYWx1ZTtcbiAgICAgICAgICAgIH0sIFtdKS5zb3J0KCk7XG4gICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy51c2VDdXJyZW50ICYmICF0aGlzLl9vcHRpb25zLmtlZXBJbnZhbGlkKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLl9kYXRlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgdHJpZXMgPSAwO1xuICAgICAgICAgICAgICAgICAgICB3aGlsZSAoIXRoaXMuX2lzVmFsaWQodGhpcy5fZGF0ZXNbaV0sICdkJykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2RhdGVzW2ldLmFkZCgxLCAnZCcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRyaWVzID09PSAzMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93ICdUcmllZCAzMSB0aW1lcyB0byBmaW5kIGEgdmFsaWQgZGF0ZSc7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB0cmllcysrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX3NldFZhbHVlKHRoaXMuX2RhdGVzW2ldLCBpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl91cGRhdGUoKTtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUubWF4RGF0ZSA9IGZ1bmN0aW9uIG1heERhdGUoX21heERhdGUpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMubWF4RGF0ZSA/IHRoaXMuX29wdGlvbnMubWF4RGF0ZS5jbG9uZSgpIDogdGhpcy5fb3B0aW9ucy5tYXhEYXRlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodHlwZW9mIF9tYXhEYXRlID09PSAnYm9vbGVhbicgJiYgX21heERhdGUgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5tYXhEYXRlID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdGhpcy5fdXBkYXRlKCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgX21heERhdGUgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgaWYgKF9tYXhEYXRlID09PSAnbm93JyB8fCBfbWF4RGF0ZSA9PT0gJ21vbWVudCcpIHtcbiAgICAgICAgICAgICAgICAgICAgX21heERhdGUgPSB0aGlzLmdldE1vbWVudCgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdmFyIHBhcnNlZERhdGUgPSB0aGlzLl9wYXJzZUlucHV0RGF0ZShfbWF4RGF0ZSk7XG5cbiAgICAgICAgICAgIGlmICghcGFyc2VkRGF0ZS5pc1ZhbGlkKCkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdtYXhEYXRlKCkgQ291bGQgbm90IHBhcnNlIGRhdGUgcGFyYW1ldGVyOiAnICsgX21heERhdGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMubWluRGF0ZSAmJiBwYXJzZWREYXRlLmlzQmVmb3JlKHRoaXMuX29wdGlvbnMubWluRGF0ZSkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdtYXhEYXRlKCkgZGF0ZSBwYXJhbWV0ZXIgaXMgYmVmb3JlIHRoaXMub3B0aW9ucy5taW5EYXRlOiAnICsgcGFyc2VkRGF0ZS5mb3JtYXQodGhpcy5hY3R1YWxGb3JtYXQpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMubWF4RGF0ZSA9IHBhcnNlZERhdGU7XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuX2RhdGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMudXNlQ3VycmVudCAmJiAhdGhpcy5fb3B0aW9ucy5rZWVwSW52YWxpZCAmJiB0aGlzLl9kYXRlc1tpXS5pc0FmdGVyKF9tYXhEYXRlKSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9zZXRWYWx1ZSh0aGlzLl9vcHRpb25zLm1heERhdGUsIGkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLl92aWV3RGF0ZS5pc0FmdGVyKHBhcnNlZERhdGUpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fdmlld0RhdGUgPSBwYXJzZWREYXRlLmNsb25lKCkuc3VidHJhY3QodGhpcy5fb3B0aW9ucy5zdGVwcGluZywgJ20nKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX3VwZGF0ZSgpO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5taW5EYXRlID0gZnVuY3Rpb24gbWluRGF0ZShfbWluRGF0ZSkge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5taW5EYXRlID8gdGhpcy5fb3B0aW9ucy5taW5EYXRlLmNsb25lKCkgOiB0aGlzLl9vcHRpb25zLm1pbkRhdGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgX21pbkRhdGUgPT09ICdib29sZWFuJyAmJiBfbWluRGF0ZSA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9vcHRpb25zLm1pbkRhdGUgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB0aGlzLl91cGRhdGUoKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBfbWluRGF0ZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICBpZiAoX21pbkRhdGUgPT09ICdub3cnIHx8IF9taW5EYXRlID09PSAnbW9tZW50Jykge1xuICAgICAgICAgICAgICAgICAgICBfbWluRGF0ZSA9IHRoaXMuZ2V0TW9tZW50KCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YXIgcGFyc2VkRGF0ZSA9IHRoaXMuX3BhcnNlSW5wdXREYXRlKF9taW5EYXRlKTtcblxuICAgICAgICAgICAgaWYgKCFwYXJzZWREYXRlLmlzVmFsaWQoKSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ21pbkRhdGUoKSBDb3VsZCBub3QgcGFyc2UgZGF0ZSBwYXJhbWV0ZXI6ICcgKyBfbWluRGF0ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy5tYXhEYXRlICYmIHBhcnNlZERhdGUuaXNBZnRlcih0aGlzLl9vcHRpb25zLm1heERhdGUpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignbWluRGF0ZSgpIGRhdGUgcGFyYW1ldGVyIGlzIGFmdGVyIHRoaXMub3B0aW9ucy5tYXhEYXRlOiAnICsgcGFyc2VkRGF0ZS5mb3JtYXQodGhpcy5hY3R1YWxGb3JtYXQpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMubWluRGF0ZSA9IHBhcnNlZERhdGU7XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuX2RhdGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMudXNlQ3VycmVudCAmJiAhdGhpcy5fb3B0aW9ucy5rZWVwSW52YWxpZCAmJiB0aGlzLl9kYXRlc1tpXS5pc0JlZm9yZShfbWluRGF0ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fc2V0VmFsdWUodGhpcy5fb3B0aW9ucy5taW5EYXRlLCBpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5fdmlld0RhdGUuaXNCZWZvcmUocGFyc2VkRGF0ZSkpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl92aWV3RGF0ZSA9IHBhcnNlZERhdGUuY2xvbmUoKS5hZGQodGhpcy5fb3B0aW9ucy5zdGVwcGluZywgJ20nKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX3VwZGF0ZSgpO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5kZWZhdWx0RGF0ZSA9IGZ1bmN0aW9uIGRlZmF1bHREYXRlKF9kZWZhdWx0RGF0ZSkge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5kZWZhdWx0RGF0ZSA/IHRoaXMuX29wdGlvbnMuZGVmYXVsdERhdGUuY2xvbmUoKSA6IHRoaXMuX29wdGlvbnMuZGVmYXVsdERhdGU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIV9kZWZhdWx0RGF0ZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuZGVmYXVsdERhdGUgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBfZGVmYXVsdERhdGUgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgaWYgKF9kZWZhdWx0RGF0ZSA9PT0gJ25vdycgfHwgX2RlZmF1bHREYXRlID09PSAnbW9tZW50Jykge1xuICAgICAgICAgICAgICAgICAgICBfZGVmYXVsdERhdGUgPSB0aGlzLmdldE1vbWVudCgpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIF9kZWZhdWx0RGF0ZSA9IHRoaXMuZ2V0TW9tZW50KF9kZWZhdWx0RGF0ZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YXIgcGFyc2VkRGF0ZSA9IHRoaXMuX3BhcnNlSW5wdXREYXRlKF9kZWZhdWx0RGF0ZSk7XG4gICAgICAgICAgICBpZiAoIXBhcnNlZERhdGUuaXNWYWxpZCgpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignZGVmYXVsdERhdGUoKSBDb3VsZCBub3QgcGFyc2UgZGF0ZSBwYXJhbWV0ZXI6ICcgKyBfZGVmYXVsdERhdGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCF0aGlzLl9pc1ZhbGlkKHBhcnNlZERhdGUpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignZGVmYXVsdERhdGUoKSBkYXRlIHBhc3NlZCBpcyBpbnZhbGlkIGFjY29yZGluZyB0byBjb21wb25lbnQgc2V0dXAgdmFsaWRhdGlvbnMnKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5kZWZhdWx0RGF0ZSA9IHBhcnNlZERhdGU7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLl9vcHRpb25zLmRlZmF1bHREYXRlICYmIHRoaXMuX29wdGlvbnMuaW5saW5lIHx8IHRoaXMuaW5wdXQgIT09IHVuZGVmaW5lZCAmJiB0aGlzLmlucHV0LnZhbCgpLnRyaW0oKSA9PT0gJycpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9zZXRWYWx1ZSh0aGlzLl9vcHRpb25zLmRlZmF1bHREYXRlLCAwKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUubG9jYWxlID0gZnVuY3Rpb24gbG9jYWxlKF9sb2NhbGUpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMubG9jYWxlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoIW1vbWVudC5sb2NhbGVEYXRhKF9sb2NhbGUpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignbG9jYWxlKCkgbG9jYWxlICcgKyBfbG9jYWxlICsgJyBpcyBub3QgbG9hZGVkIGZyb20gbW9tZW50IGxvY2FsZXMhJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5fZGF0ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9kYXRlc1tpXS5sb2NhbGUodGhpcy5fb3B0aW9ucy5sb2NhbGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fdmlld0RhdGUubG9jYWxlKHRoaXMuX29wdGlvbnMubG9jYWxlKTtcblxuICAgICAgICAgICAgaWYgKHRoaXMuYWN0dWFsRm9ybWF0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5faW5pdEZvcm1hdHRpbmcoKTsgLy8gcmVpbml0aWFsaXplIGZvcm1hdHRpbmdcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLndpZGdldCkge1xuICAgICAgICAgICAgICAgIHRoaXMuaGlkZSgpO1xuICAgICAgICAgICAgICAgIHRoaXMuc2hvdygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5zdGVwcGluZyA9IGZ1bmN0aW9uIHN0ZXBwaW5nKF9zdGVwcGluZykge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5zdGVwcGluZztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgX3N0ZXBwaW5nID0gcGFyc2VJbnQoX3N0ZXBwaW5nLCAxMCk7XG4gICAgICAgICAgICBpZiAoaXNOYU4oX3N0ZXBwaW5nKSB8fCBfc3RlcHBpbmcgPCAxKSB7XG4gICAgICAgICAgICAgICAgX3N0ZXBwaW5nID0gMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuc3RlcHBpbmcgPSBfc3RlcHBpbmc7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLnVzZUN1cnJlbnQgPSBmdW5jdGlvbiB1c2VDdXJyZW50KF91c2VDdXJyZW50KSB7XG4gICAgICAgICAgICB2YXIgdXNlQ3VycmVudE9wdGlvbnMgPSBbJ3llYXInLCAnbW9udGgnLCAnZGF5JywgJ2hvdXInLCAnbWludXRlJ107XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLnVzZUN1cnJlbnQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgX3VzZUN1cnJlbnQgIT09ICdib29sZWFuJyAmJiB0eXBlb2YgX3VzZUN1cnJlbnQgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigndXNlQ3VycmVudCgpIGV4cGVjdHMgYSBib29sZWFuIG9yIHN0cmluZyBwYXJhbWV0ZXInKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0eXBlb2YgX3VzZUN1cnJlbnQgPT09ICdzdHJpbmcnICYmIHVzZUN1cnJlbnRPcHRpb25zLmluZGV4T2YoX3VzZUN1cnJlbnQudG9Mb3dlckNhc2UoKSkgPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigndXNlQ3VycmVudCgpIGV4cGVjdHMgYSBzdHJpbmcgcGFyYW1ldGVyIG9mICcgKyB1c2VDdXJyZW50T3B0aW9ucy5qb2luKCcsICcpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMudXNlQ3VycmVudCA9IF91c2VDdXJyZW50O1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5jb2xsYXBzZSA9IGZ1bmN0aW9uIGNvbGxhcHNlKF9jb2xsYXBzZSkge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5jb2xsYXBzZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBfY29sbGFwc2UgIT09ICdib29sZWFuJykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2NvbGxhcHNlKCkgZXhwZWN0cyBhIGJvb2xlYW4gcGFyYW1ldGVyJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy5jb2xsYXBzZSA9PT0gX2NvbGxhcHNlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLmNvbGxhcHNlID0gX2NvbGxhcHNlO1xuICAgICAgICAgICAgaWYgKHRoaXMud2lkZ2V0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5oaWRlKCk7XG4gICAgICAgICAgICAgICAgdGhpcy5zaG93KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLmljb25zID0gZnVuY3Rpb24gaWNvbnMoX2ljb25zKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAkLmV4dGVuZCh7fSwgdGhpcy5fb3B0aW9ucy5pY29ucyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICghKF9pY29ucyBpbnN0YW5jZW9mIE9iamVjdCkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdpY29ucygpIGV4cGVjdHMgcGFyYW1ldGVyIHRvIGJlIGFuIE9iamVjdCcpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAkLmV4dGVuZCh0aGlzLl9vcHRpb25zLmljb25zLCBfaWNvbnMpO1xuXG4gICAgICAgICAgICBpZiAodGhpcy53aWRnZXQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmhpZGUoKTtcbiAgICAgICAgICAgICAgICB0aGlzLnNob3coKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUudG9vbHRpcHMgPSBmdW5jdGlvbiB0b29sdGlwcyhfdG9vbHRpcHMpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICQuZXh0ZW5kKHt9LCB0aGlzLl9vcHRpb25zLnRvb2x0aXBzKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCEoX3Rvb2x0aXBzIGluc3RhbmNlb2YgT2JqZWN0KSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ3Rvb2x0aXBzKCkgZXhwZWN0cyBwYXJhbWV0ZXIgdG8gYmUgYW4gT2JqZWN0Jyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAkLmV4dGVuZCh0aGlzLl9vcHRpb25zLnRvb2x0aXBzLCBfdG9vbHRpcHMpO1xuICAgICAgICAgICAgaWYgKHRoaXMud2lkZ2V0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5oaWRlKCk7XG4gICAgICAgICAgICAgICAgdGhpcy5zaG93KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLnVzZVN0cmljdCA9IGZ1bmN0aW9uIHVzZVN0cmljdChfdXNlU3RyaWN0KSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLnVzZVN0cmljdDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBfdXNlU3RyaWN0ICE9PSAnYm9vbGVhbicpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCd1c2VTdHJpY3QoKSBleHBlY3RzIGEgYm9vbGVhbiBwYXJhbWV0ZXInKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMudXNlU3RyaWN0ID0gX3VzZVN0cmljdDtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuc2lkZUJ5U2lkZSA9IGZ1bmN0aW9uIHNpZGVCeVNpZGUoX3NpZGVCeVNpZGUpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMuc2lkZUJ5U2lkZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBfc2lkZUJ5U2lkZSAhPT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignc2lkZUJ5U2lkZSgpIGV4cGVjdHMgYSBib29sZWFuIHBhcmFtZXRlcicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5zaWRlQnlTaWRlID0gX3NpZGVCeVNpZGU7XG4gICAgICAgICAgICBpZiAodGhpcy53aWRnZXQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmhpZGUoKTtcbiAgICAgICAgICAgICAgICB0aGlzLnNob3coKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUudmlld01vZGUgPSBmdW5jdGlvbiB2aWV3TW9kZShfdmlld01vZGUpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMudmlld01vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgX3ZpZXdNb2RlICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ3ZpZXdNb2RlKCkgZXhwZWN0cyBhIHN0cmluZyBwYXJhbWV0ZXInKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKERhdGVUaW1lUGlja2VyLlZpZXdNb2Rlcy5pbmRleE9mKF92aWV3TW9kZSkgPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigndmlld01vZGUoKSBwYXJhbWV0ZXIgbXVzdCBiZSBvbmUgb2YgKCcgKyBEYXRlVGltZVBpY2tlci5WaWV3TW9kZXMuam9pbignLCAnKSArICcpIHZhbHVlJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMudmlld01vZGUgPSBfdmlld01vZGU7XG4gICAgICAgICAgICB0aGlzLmN1cnJlbnRWaWV3TW9kZSA9IE1hdGgubWF4KERhdGVUaW1lUGlja2VyLlZpZXdNb2Rlcy5pbmRleE9mKF92aWV3TW9kZSkgLSAxLCBEYXRlVGltZVBpY2tlci5NaW5WaWV3TW9kZU51bWJlcik7XG5cbiAgICAgICAgICAgIHRoaXMuX3Nob3dNb2RlKCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLmNhbGVuZGFyV2Vla3MgPSBmdW5jdGlvbiBjYWxlbmRhcldlZWtzKF9jYWxlbmRhcldlZWtzKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLmNhbGVuZGFyV2Vla3M7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgX2NhbGVuZGFyV2Vla3MgIT09ICdib29sZWFuJykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2NhbGVuZGFyV2Vla3MoKSBleHBlY3RzIHBhcmFtZXRlciB0byBiZSBhIGJvb2xlYW4gdmFsdWUnKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5jYWxlbmRhcldlZWtzID0gX2NhbGVuZGFyV2Vla3M7XG4gICAgICAgICAgICB0aGlzLl91cGRhdGUoKTtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuYnV0dG9ucyA9IGZ1bmN0aW9uIGJ1dHRvbnMoX2J1dHRvbnMpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICQuZXh0ZW5kKHt9LCB0aGlzLl9vcHRpb25zLmJ1dHRvbnMpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoIShfYnV0dG9ucyBpbnN0YW5jZW9mIE9iamVjdCkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdidXR0b25zKCkgZXhwZWN0cyBwYXJhbWV0ZXIgdG8gYmUgYW4gT2JqZWN0Jyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICQuZXh0ZW5kKHRoaXMuX29wdGlvbnMuYnV0dG9ucywgX2J1dHRvbnMpO1xuXG4gICAgICAgICAgICBpZiAodHlwZW9mIHRoaXMuX29wdGlvbnMuYnV0dG9ucy5zaG93VG9kYXkgIT09ICdib29sZWFuJykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2J1dHRvbnMuc2hvd1RvZGF5IGV4cGVjdHMgYSBib29sZWFuIHBhcmFtZXRlcicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHR5cGVvZiB0aGlzLl9vcHRpb25zLmJ1dHRvbnMuc2hvd0NsZWFyICE9PSAnYm9vbGVhbicpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdidXR0b25zLnNob3dDbGVhciBleHBlY3RzIGEgYm9vbGVhbiBwYXJhbWV0ZXInKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0eXBlb2YgdGhpcy5fb3B0aW9ucy5idXR0b25zLnNob3dDbG9zZSAhPT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignYnV0dG9ucy5zaG93Q2xvc2UgZXhwZWN0cyBhIGJvb2xlYW4gcGFyYW1ldGVyJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0aGlzLndpZGdldCkge1xuICAgICAgICAgICAgICAgIHRoaXMuaGlkZSgpO1xuICAgICAgICAgICAgICAgIHRoaXMuc2hvdygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5rZWVwT3BlbiA9IGZ1bmN0aW9uIGtlZXBPcGVuKF9rZWVwT3Blbikge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5rZWVwT3BlbjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBfa2VlcE9wZW4gIT09ICdib29sZWFuJykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2tlZXBPcGVuKCkgZXhwZWN0cyBhIGJvb2xlYW4gcGFyYW1ldGVyJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMua2VlcE9wZW4gPSBfa2VlcE9wZW47XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLmZvY3VzT25TaG93ID0gZnVuY3Rpb24gZm9jdXNPblNob3coX2ZvY3VzT25TaG93KSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLmZvY3VzT25TaG93O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodHlwZW9mIF9mb2N1c09uU2hvdyAhPT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignZm9jdXNPblNob3coKSBleHBlY3RzIGEgYm9vbGVhbiBwYXJhbWV0ZXInKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5mb2N1c09uU2hvdyA9IF9mb2N1c09uU2hvdztcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuaW5saW5lID0gZnVuY3Rpb24gaW5saW5lKF9pbmxpbmUpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMuaW5saW5lO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodHlwZW9mIF9pbmxpbmUgIT09ICdib29sZWFuJykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2lubGluZSgpIGV4cGVjdHMgYSBib29sZWFuIHBhcmFtZXRlcicpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLmlubGluZSA9IF9pbmxpbmU7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLmNsZWFyID0gZnVuY3Rpb24gY2xlYXIoKSB7XG4gICAgICAgICAgICB0aGlzLl9zZXRWYWx1ZShudWxsKTsgLy90b2RvXG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLmtleUJpbmRzID0gZnVuY3Rpb24ga2V5QmluZHMoX2tleUJpbmRzKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLmtleUJpbmRzO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLmtleUJpbmRzID0gX2tleUJpbmRzO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5kZWJ1ZyA9IGZ1bmN0aW9uIGRlYnVnKF9kZWJ1Zykge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBfZGVidWcgIT09ICdib29sZWFuJykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2RlYnVnKCkgZXhwZWN0cyBhIGJvb2xlYW4gcGFyYW1ldGVyJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuZGVidWcgPSBfZGVidWc7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLmFsbG93SW5wdXRUb2dnbGUgPSBmdW5jdGlvbiBhbGxvd0lucHV0VG9nZ2xlKF9hbGxvd0lucHV0VG9nZ2xlKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLmFsbG93SW5wdXRUb2dnbGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgX2FsbG93SW5wdXRUb2dnbGUgIT09ICdib29sZWFuJykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2FsbG93SW5wdXRUb2dnbGUoKSBleHBlY3RzIGEgYm9vbGVhbiBwYXJhbWV0ZXInKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5hbGxvd0lucHV0VG9nZ2xlID0gX2FsbG93SW5wdXRUb2dnbGU7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLmtlZXBJbnZhbGlkID0gZnVuY3Rpb24ga2VlcEludmFsaWQoX2tlZXBJbnZhbGlkKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLmtlZXBJbnZhbGlkO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodHlwZW9mIF9rZWVwSW52YWxpZCAhPT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigna2VlcEludmFsaWQoKSBleHBlY3RzIGEgYm9vbGVhbiBwYXJhbWV0ZXInKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMua2VlcEludmFsaWQgPSBfa2VlcEludmFsaWQ7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLmRhdGVwaWNrZXJJbnB1dCA9IGZ1bmN0aW9uIGRhdGVwaWNrZXJJbnB1dChfZGF0ZXBpY2tlcklucHV0KSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLmRhdGVwaWNrZXJJbnB1dDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBfZGF0ZXBpY2tlcklucHV0ICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2RhdGVwaWNrZXJJbnB1dCgpIGV4cGVjdHMgYSBzdHJpbmcgcGFyYW1ldGVyJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuZGF0ZXBpY2tlcklucHV0ID0gX2RhdGVwaWNrZXJJbnB1dDtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUucGFyc2VJbnB1dERhdGUgPSBmdW5jdGlvbiBwYXJzZUlucHV0RGF0ZShfcGFyc2VJbnB1dERhdGUyKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLnBhcnNlSW5wdXREYXRlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodHlwZW9mIF9wYXJzZUlucHV0RGF0ZTIgIT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdwYXJzZUlucHV0RGF0ZSgpIHNob3VsZCBiZSBhcyBmdW5jdGlvbicpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLnBhcnNlSW5wdXREYXRlID0gX3BhcnNlSW5wdXREYXRlMjtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuZGlzYWJsZWRUaW1lSW50ZXJ2YWxzID0gZnVuY3Rpb24gZGlzYWJsZWRUaW1lSW50ZXJ2YWxzKF9kaXNhYmxlZFRpbWVJbnRlcnZhbHMpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMuZGlzYWJsZWRUaW1lSW50ZXJ2YWxzID8gJC5leHRlbmQoe30sIHRoaXMuX29wdGlvbnMuZGlzYWJsZWRUaW1lSW50ZXJ2YWxzKSA6IHRoaXMuX29wdGlvbnMuZGlzYWJsZWRUaW1lSW50ZXJ2YWxzO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoIV9kaXNhYmxlZFRpbWVJbnRlcnZhbHMpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9vcHRpb25zLmRpc2FibGVkVGltZUludGVydmFscyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHRoaXMuX3VwZGF0ZSgpO1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCEoX2Rpc2FibGVkVGltZUludGVydmFscyBpbnN0YW5jZW9mIEFycmF5KSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2Rpc2FibGVkVGltZUludGVydmFscygpIGV4cGVjdHMgYW4gYXJyYXkgcGFyYW1ldGVyJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLmRpc2FibGVkVGltZUludGVydmFscyA9IF9kaXNhYmxlZFRpbWVJbnRlcnZhbHM7XG4gICAgICAgICAgICB0aGlzLl91cGRhdGUoKTtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuZGlzYWJsZWRIb3VycyA9IGZ1bmN0aW9uIGRpc2FibGVkSG91cnMoaG91cnMpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMuZGlzYWJsZWRIb3VycyA/ICQuZXh0ZW5kKHt9LCB0aGlzLl9vcHRpb25zLmRpc2FibGVkSG91cnMpIDogdGhpcy5fb3B0aW9ucy5kaXNhYmxlZEhvdXJzO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoIWhvdXJzKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5kaXNhYmxlZEhvdXJzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdGhpcy5fdXBkYXRlKCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIShob3VycyBpbnN0YW5jZW9mIEFycmF5KSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2Rpc2FibGVkSG91cnMoKSBleHBlY3RzIGFuIGFycmF5IHBhcmFtZXRlcicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5kaXNhYmxlZEhvdXJzID0gdGhpcy5faW5kZXhHaXZlbkhvdXJzKGhvdXJzKTtcbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuZW5hYmxlZEhvdXJzID0gZmFsc2U7XG4gICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy51c2VDdXJyZW50ICYmICF0aGlzLl9vcHRpb25zLmtlZXBJbnZhbGlkKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLl9kYXRlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgdHJpZXMgPSAwO1xuICAgICAgICAgICAgICAgICAgICB3aGlsZSAoIXRoaXMuX2lzVmFsaWQodGhpcy5fZGF0ZXNbaV0sICdoJykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2RhdGVzW2ldLmFkZCgxLCAnaCcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRyaWVzID09PSAyNCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93ICdUcmllZCAyNCB0aW1lcyB0byBmaW5kIGEgdmFsaWQgZGF0ZSc7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB0cmllcysrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX3NldFZhbHVlKHRoaXMuX2RhdGVzW2ldLCBpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl91cGRhdGUoKTtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuZW5hYmxlZEhvdXJzID0gZnVuY3Rpb24gZW5hYmxlZEhvdXJzKGhvdXJzKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLmVuYWJsZWRIb3VycyA/ICQuZXh0ZW5kKHt9LCB0aGlzLl9vcHRpb25zLmVuYWJsZWRIb3VycykgOiB0aGlzLl9vcHRpb25zLmVuYWJsZWRIb3VycztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCFob3Vycykge1xuICAgICAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuZW5hYmxlZEhvdXJzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdGhpcy5fdXBkYXRlKCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIShob3VycyBpbnN0YW5jZW9mIEFycmF5KSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2VuYWJsZWRIb3VycygpIGV4cGVjdHMgYW4gYXJyYXkgcGFyYW1ldGVyJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLmVuYWJsZWRIb3VycyA9IHRoaXMuX2luZGV4R2l2ZW5Ib3Vycyhob3Vycyk7XG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLmRpc2FibGVkSG91cnMgPSBmYWxzZTtcbiAgICAgICAgICAgIGlmICh0aGlzLl9vcHRpb25zLnVzZUN1cnJlbnQgJiYgIXRoaXMuX29wdGlvbnMua2VlcEludmFsaWQpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuX2RhdGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB0cmllcyA9IDA7XG4gICAgICAgICAgICAgICAgICAgIHdoaWxlICghdGhpcy5faXNWYWxpZCh0aGlzLl9kYXRlc1tpXSwgJ2gnKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fZGF0ZXNbaV0uYWRkKDEsICdoJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodHJpZXMgPT09IDI0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgJ1RyaWVkIDI0IHRpbWVzIHRvIGZpbmQgYSB2YWxpZCBkYXRlJztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHRyaWVzKys7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fc2V0VmFsdWUodGhpcy5fZGF0ZXNbaV0sIGkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX3VwZGF0ZSgpO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS52aWV3RGF0ZSA9IGZ1bmN0aW9uIHZpZXdEYXRlKG5ld0RhdGUpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX3ZpZXdEYXRlLmNsb25lKCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICghbmV3RGF0ZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuX3ZpZXdEYXRlID0gKHRoaXMuX2RhdGVzWzBdIHx8IHRoaXMuZ2V0TW9tZW50KCkpLmNsb25lKCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgbmV3RGF0ZSAhPT0gJ3N0cmluZycgJiYgIW1vbWVudC5pc01vbWVudChuZXdEYXRlKSAmJiAhKG5ld0RhdGUgaW5zdGFuY2VvZiBEYXRlKSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ3ZpZXdEYXRlKCkgcGFyYW1ldGVyIG11c3QgYmUgb25lIG9mIFtzdHJpbmcsIG1vbWVudCBvciBEYXRlXScpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLl92aWV3RGF0ZSA9IHRoaXMuX3BhcnNlSW5wdXREYXRlKG5ld0RhdGUpO1xuICAgICAgICAgICAgdGhpcy5fdmlld1VwZGF0ZSgpO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5hbGxvd011bHRpZGF0ZSA9IGZ1bmN0aW9uIGFsbG93TXVsdGlkYXRlKF9hbGxvd011bHRpZGF0ZSkge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBfYWxsb3dNdWx0aWRhdGUgIT09ICdib29sZWFuJykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2FsbG93TXVsdGlkYXRlKCkgZXhwZWN0cyBhIGJvb2xlYW4gcGFyYW1ldGVyJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuYWxsb3dNdWx0aWRhdGUgPSBfYWxsb3dNdWx0aWRhdGU7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLm11bHRpZGF0ZVNlcGFyYXRvciA9IGZ1bmN0aW9uIG11bHRpZGF0ZVNlcGFyYXRvcihfbXVsdGlkYXRlU2VwYXJhdG9yKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLm11bHRpZGF0ZVNlcGFyYXRvcjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBfbXVsdGlkYXRlU2VwYXJhdG9yICE9PSAnc3RyaW5nJyB8fCBfbXVsdGlkYXRlU2VwYXJhdG9yLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdtdWx0aWRhdGVTZXBhcmF0b3IgZXhwZWN0cyBhIHNpbmdsZSBjaGFyYWN0ZXIgc3RyaW5nIHBhcmFtZXRlcicpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLm11bHRpZGF0ZVNlcGFyYXRvciA9IF9tdWx0aWRhdGVTZXBhcmF0b3I7XG4gICAgICAgIH07XG5cbiAgICAgICAgX2NyZWF0ZUNsYXNzKERhdGVUaW1lUGlja2VyLCBudWxsLCBbe1xuICAgICAgICAgICAga2V5OiAnTkFNRScsXG4gICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gTkFNRTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLyoqXHJcbiAgICAgICAgICAgICAqIEByZXR1cm4ge3N0cmluZ31cclxuICAgICAgICAgICAgICovXG5cbiAgICAgICAgfSwge1xuICAgICAgICAgICAga2V5OiAnVkVSU0lPTicsXG4gICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gVkVSU0lPTjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLyoqXHJcbiAgICAgICAgICAgICAqIEByZXR1cm4ge3N0cmluZ31cclxuICAgICAgICAgICAgICovXG5cbiAgICAgICAgfSwge1xuICAgICAgICAgICAga2V5OiAnREFUQV9LRVknLFxuICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIERBVEFfS0VZO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvKipcclxuICAgICAgICAgICAgICogQHJldHVybiB7c3RyaW5nfVxyXG4gICAgICAgICAgICAgKi9cblxuICAgICAgICB9LCB7XG4gICAgICAgICAgICBrZXk6ICdFVkVOVF9LRVknLFxuICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIEVWRU5UX0tFWTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLyoqXHJcbiAgICAgICAgICAgICAqIEByZXR1cm4ge3N0cmluZ31cclxuICAgICAgICAgICAgICovXG5cbiAgICAgICAgfSwge1xuICAgICAgICAgICAga2V5OiAnREFUQV9BUElfS0VZJyxcbiAgICAgICAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBEQVRBX0FQSV9LRVk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHtcbiAgICAgICAgICAgIGtleTogJ0RhdGVQaWNrZXJNb2RlcycsXG4gICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gRGF0ZVBpY2tlck1vZGVzO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7XG4gICAgICAgICAgICBrZXk6ICdWaWV3TW9kZXMnLFxuICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFZpZXdNb2RlcztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLyoqXHJcbiAgICAgICAgICAgICAqIEByZXR1cm4ge251bWJlcn1cclxuICAgICAgICAgICAgICovXG5cbiAgICAgICAgfSwge1xuICAgICAgICAgICAga2V5OiAnTWluVmlld01vZGVOdW1iZXInLFxuICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIE1pblZpZXdNb2RlTnVtYmVyO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7XG4gICAgICAgICAgICBrZXk6ICdFdmVudCcsXG4gICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gRXZlbnQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHtcbiAgICAgICAgICAgIGtleTogJ1NlbGVjdG9yJyxcbiAgICAgICAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBTZWxlY3RvcjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge1xuICAgICAgICAgICAga2V5OiAnRGVmYXVsdCcsXG4gICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gRGVmYXVsdDtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBzZXQ6IGZ1bmN0aW9uIHNldCh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIERlZmF1bHQgPSB2YWx1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge1xuICAgICAgICAgICAga2V5OiAnQ2xhc3NOYW1lJyxcbiAgICAgICAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBDbGFzc05hbWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1dKTtcblxuICAgICAgICByZXR1cm4gRGF0ZVRpbWVQaWNrZXI7XG4gICAgfSgpO1xuXG4gICAgcmV0dXJuIERhdGVUaW1lUGlja2VyO1xufShqUXVlcnksIG1vbWVudCk7XG4iLCIvKkBwcmVzZXJ2ZVxuICogVGVtcHVzIERvbWludXMgQm9vdHN0cmFwNCB2NS4wLjAtYWxwaGExNiAoaHR0cHM6Ly90ZW1wdXNkb21pbnVzLmdpdGh1Yi5pby9ib290c3RyYXAtNC8pXG4gKiBDb3B5cmlnaHQgMjAxNi0yMDE4IEpvbmF0aGFuIFBldGVyc29uXG4gKiBMaWNlbnNlZCB1bmRlciBNSVQgKGh0dHBzOi8vZ2l0aHViLmNvbS90ZW1wdXNkb21pbnVzL2Jvb3RzdHJhcC0zL2Jsb2IvbWFzdGVyL0xJQ0VOU0UpXG4gKi9cblxuaWYgKHR5cGVvZiBqUXVlcnkgPT09ICd1bmRlZmluZWQnKSB7XG4gIHRocm93IG5ldyBFcnJvcignVGVtcHVzIERvbWludXMgQm9vdHN0cmFwNFxcJ3MgcmVxdWlyZXMgalF1ZXJ5LiBqUXVlcnkgbXVzdCBiZSBpbmNsdWRlZCBiZWZvcmUgVGVtcHVzIERvbWludXMgQm9vdHN0cmFwNFxcJ3MgSmF2YVNjcmlwdC4nKTtcbn1cblxuK2Z1bmN0aW9uICgkKSB7XG4gIHZhciB2ZXJzaW9uID0gJC5mbi5qcXVlcnkuc3BsaXQoJyAnKVswXS5zcGxpdCgnLicpO1xuICBpZiAoKHZlcnNpb25bMF0gPCAyICYmIHZlcnNpb25bMV0gPCA5KSB8fCAodmVyc2lvblswXSA9PT0gMSAmJiB2ZXJzaW9uWzFdID09PSA5ICYmIHZlcnNpb25bMl0gPCAxKSB8fCAodmVyc2lvblswXSA+PSA0KSkge1xuICAgIHRocm93IG5ldyBFcnJvcignVGVtcHVzIERvbWludXMgQm9vdHN0cmFwNFxcJ3MgcmVxdWlyZXMgYXQgbGVhc3QgalF1ZXJ5IHYxLjkuMSBidXQgbGVzcyB0aGFuIHY0LjAuMCcpO1xuICB9XG59KGpRdWVyeSk7XG5cblxuaWYgKHR5cGVvZiBtb21lbnQgPT09ICd1bmRlZmluZWQnKSB7XG4gIHRocm93IG5ldyBFcnJvcignVGVtcHVzIERvbWludXMgQm9vdHN0cmFwNFxcJ3MgcmVxdWlyZXMgbW9tZW50LmpzLiBNb21lbnQuanMgbXVzdCBiZSBpbmNsdWRlZCBiZWZvcmUgVGVtcHVzIERvbWludXMgQm9vdHN0cmFwNFxcJ3MgSmF2YVNjcmlwdC4nKTtcbn1cblxudmFyIHZlcnNpb24gPSBtb21lbnQudmVyc2lvbi5zcGxpdCgnLicpXG5pZiAoKHZlcnNpb25bMF0gPD0gMiAmJiB2ZXJzaW9uWzFdIDwgMTcpIHx8ICh2ZXJzaW9uWzBdID49IDMpKSB7XG4gIHRocm93IG5ldyBFcnJvcignVGVtcHVzIERvbWludXMgQm9vdHN0cmFwNFxcJ3MgcmVxdWlyZXMgYXQgbGVhc3QgbW9tZW50LmpzIHYyLjE3LjAgYnV0IGxlc3MgdGhhbiB2My4wLjAnKTtcbn1cblxuK2Z1bmN0aW9uICgpIHtcblxudmFyIF90eXBlb2YgPSB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgdHlwZW9mIFN5bWJvbC5pdGVyYXRvciA9PT0gXCJzeW1ib2xcIiA/IGZ1bmN0aW9uIChvYmopIHsgcmV0dXJuIHR5cGVvZiBvYmo7IH0gOiBmdW5jdGlvbiAob2JqKSB7IHJldHVybiBvYmogJiYgdHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICYmIG9iai5jb25zdHJ1Y3RvciA9PT0gU3ltYm9sICYmIG9iaiAhPT0gU3ltYm9sLnByb3RvdHlwZSA/IFwic3ltYm9sXCIgOiB0eXBlb2Ygb2JqOyB9O1xuXG52YXIgX2NyZWF0ZUNsYXNzID0gZnVuY3Rpb24gKCkgeyBmdW5jdGlvbiBkZWZpbmVQcm9wZXJ0aWVzKHRhcmdldCwgcHJvcHMpIHsgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykgeyB2YXIgZGVzY3JpcHRvciA9IHByb3BzW2ldOyBkZXNjcmlwdG9yLmVudW1lcmFibGUgPSBkZXNjcmlwdG9yLmVudW1lcmFibGUgfHwgZmFsc2U7IGRlc2NyaXB0b3IuY29uZmlndXJhYmxlID0gdHJ1ZTsgaWYgKFwidmFsdWVcIiBpbiBkZXNjcmlwdG9yKSBkZXNjcmlwdG9yLndyaXRhYmxlID0gdHJ1ZTsgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwgZGVzY3JpcHRvci5rZXksIGRlc2NyaXB0b3IpOyB9IH0gcmV0dXJuIGZ1bmN0aW9uIChDb25zdHJ1Y3RvciwgcHJvdG9Qcm9wcywgc3RhdGljUHJvcHMpIHsgaWYgKHByb3RvUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IucHJvdG90eXBlLCBwcm90b1Byb3BzKTsgaWYgKHN0YXRpY1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLCBzdGF0aWNQcm9wcyk7IHJldHVybiBDb25zdHJ1Y3RvcjsgfTsgfSgpO1xuXG5mdW5jdGlvbiBfcG9zc2libGVDb25zdHJ1Y3RvclJldHVybihzZWxmLCBjYWxsKSB7IGlmICghc2VsZikgeyB0aHJvdyBuZXcgUmVmZXJlbmNlRXJyb3IoXCJ0aGlzIGhhc24ndCBiZWVuIGluaXRpYWxpc2VkIC0gc3VwZXIoKSBoYXNuJ3QgYmVlbiBjYWxsZWRcIik7IH0gcmV0dXJuIGNhbGwgJiYgKHR5cGVvZiBjYWxsID09PSBcIm9iamVjdFwiIHx8IHR5cGVvZiBjYWxsID09PSBcImZ1bmN0aW9uXCIpID8gY2FsbCA6IHNlbGY7IH1cblxuZnVuY3Rpb24gX2luaGVyaXRzKHN1YkNsYXNzLCBzdXBlckNsYXNzKSB7IGlmICh0eXBlb2Ygc3VwZXJDbGFzcyAhPT0gXCJmdW5jdGlvblwiICYmIHN1cGVyQ2xhc3MgIT09IG51bGwpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlN1cGVyIGV4cHJlc3Npb24gbXVzdCBlaXRoZXIgYmUgbnVsbCBvciBhIGZ1bmN0aW9uLCBub3QgXCIgKyB0eXBlb2Ygc3VwZXJDbGFzcyk7IH0gc3ViQ2xhc3MucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShzdXBlckNsYXNzICYmIHN1cGVyQ2xhc3MucHJvdG90eXBlLCB7IGNvbnN0cnVjdG9yOiB7IHZhbHVlOiBzdWJDbGFzcywgZW51bWVyYWJsZTogZmFsc2UsIHdyaXRhYmxlOiB0cnVlLCBjb25maWd1cmFibGU6IHRydWUgfSB9KTsgaWYgKHN1cGVyQ2xhc3MpIE9iamVjdC5zZXRQcm90b3R5cGVPZiA/IE9iamVjdC5zZXRQcm90b3R5cGVPZihzdWJDbGFzcywgc3VwZXJDbGFzcykgOiBzdWJDbGFzcy5fX3Byb3RvX18gPSBzdXBlckNsYXNzOyB9XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvblwiKTsgfSB9XG5cbi8vIFJlU2hhcnBlciBkaXNhYmxlIG9uY2UgSW5jb25zaXN0ZW50TmFtaW5nXG52YXIgRGF0ZVRpbWVQaWNrZXIgPSBmdW5jdGlvbiAoJCwgbW9tZW50KSB7XG4gICAgLy8gUmVTaGFycGVyIGRpc2FibGUgSW5jb25zaXN0ZW50TmFtaW5nXG4gICAgdmFyIE5BTUUgPSAnZGF0ZXRpbWVwaWNrZXInLFxuICAgICAgICBWRVJTSU9OID0gJzUuMC4wLWFscGhhMTInLFxuICAgICAgICBEQVRBX0tFWSA9ICcnICsgTkFNRSxcbiAgICAgICAgRVZFTlRfS0VZID0gJy4nICsgREFUQV9LRVksXG4gICAgICAgIEVNSVRfRVZFTlRfS0VZID0gREFUQV9LRVkgKyAnLicsXG4gICAgICAgIERBVEFfQVBJX0tFWSA9ICcuZGF0YS1hcGknLFxuICAgICAgICBTZWxlY3RvciA9IHtcbiAgICAgICAgREFUQV9UT0dHTEU6ICdbZGF0YS10b2dnbGU9XCInICsgREFUQV9LRVkgKyAnXCJdJ1xuICAgIH0sXG4gICAgICAgIENsYXNzTmFtZSA9IHtcbiAgICAgICAgSU5QVVQ6IE5BTUUgKyAnLWlucHV0J1xuICAgIH0sXG4gICAgICAgIEV2ZW50ID0ge1xuICAgICAgICBDSEFOR0U6ICdjaGFuZ2UnICsgRVZFTlRfS0VZLFxuICAgICAgICBCTFVSOiAnYmx1cicgKyBFVkVOVF9LRVksXG4gICAgICAgIEtFWVVQOiAna2V5dXAnICsgRVZFTlRfS0VZLFxuICAgICAgICBLRVlET1dOOiAna2V5ZG93bicgKyBFVkVOVF9LRVksXG4gICAgICAgIEZPQ1VTOiAnZm9jdXMnICsgRVZFTlRfS0VZLFxuICAgICAgICBDTElDS19EQVRBX0FQSTogJ2NsaWNrJyArIEVWRU5UX0tFWSArIERBVEFfQVBJX0tFWSxcbiAgICAgICAgLy9lbWl0dGVkXG4gICAgICAgIFVQREFURTogRU1JVF9FVkVOVF9LRVkgKyAndXBkYXRlJyxcbiAgICAgICAgRVJST1I6IEVNSVRfRVZFTlRfS0VZICsgJ2Vycm9yJyxcbiAgICAgICAgSElERTogRU1JVF9FVkVOVF9LRVkgKyAnaGlkZScsXG4gICAgICAgIFNIT1c6IEVNSVRfRVZFTlRfS0VZICsgJ3Nob3cnXG4gICAgfSxcbiAgICAgICAgRGF0ZVBpY2tlck1vZGVzID0gW3tcbiAgICAgICAgQ0xBU1NfTkFNRTogJ2RheXMnLFxuICAgICAgICBOQVZfRlVOQ1RJT046ICdNJyxcbiAgICAgICAgTkFWX1NURVA6IDFcbiAgICB9LCB7XG4gICAgICAgIENMQVNTX05BTUU6ICdtb250aHMnLFxuICAgICAgICBOQVZfRlVOQ1RJT046ICd5JyxcbiAgICAgICAgTkFWX1NURVA6IDFcbiAgICB9LCB7XG4gICAgICAgIENMQVNTX05BTUU6ICd5ZWFycycsXG4gICAgICAgIE5BVl9GVU5DVElPTjogJ3knLFxuICAgICAgICBOQVZfU1RFUDogMTBcbiAgICB9LCB7XG4gICAgICAgIENMQVNTX05BTUU6ICdkZWNhZGVzJyxcbiAgICAgICAgTkFWX0ZVTkNUSU9OOiAneScsXG4gICAgICAgIE5BVl9TVEVQOiAxMDBcbiAgICB9XSxcbiAgICAgICAgS2V5TWFwID0ge1xuICAgICAgICAndXAnOiAzOCxcbiAgICAgICAgMzg6ICd1cCcsXG4gICAgICAgICdkb3duJzogNDAsXG4gICAgICAgIDQwOiAnZG93bicsXG4gICAgICAgICdsZWZ0JzogMzcsXG4gICAgICAgIDM3OiAnbGVmdCcsXG4gICAgICAgICdyaWdodCc6IDM5LFxuICAgICAgICAzOTogJ3JpZ2h0JyxcbiAgICAgICAgJ3RhYic6IDksXG4gICAgICAgIDk6ICd0YWInLFxuICAgICAgICAnZXNjYXBlJzogMjcsXG4gICAgICAgIDI3OiAnZXNjYXBlJyxcbiAgICAgICAgJ2VudGVyJzogMTMsXG4gICAgICAgIDEzOiAnZW50ZXInLFxuICAgICAgICAncGFnZVVwJzogMzMsXG4gICAgICAgIDMzOiAncGFnZVVwJyxcbiAgICAgICAgJ3BhZ2VEb3duJzogMzQsXG4gICAgICAgIDM0OiAncGFnZURvd24nLFxuICAgICAgICAnc2hpZnQnOiAxNixcbiAgICAgICAgMTY6ICdzaGlmdCcsXG4gICAgICAgICdjb250cm9sJzogMTcsXG4gICAgICAgIDE3OiAnY29udHJvbCcsXG4gICAgICAgICdzcGFjZSc6IDMyLFxuICAgICAgICAzMjogJ3NwYWNlJyxcbiAgICAgICAgJ3QnOiA4NCxcbiAgICAgICAgODQ6ICd0JyxcbiAgICAgICAgJ2RlbGV0ZSc6IDQ2LFxuICAgICAgICA0NjogJ2RlbGV0ZSdcbiAgICB9LFxuICAgICAgICBWaWV3TW9kZXMgPSBbJ3RpbWVzJywgJ2RheXMnLCAnbW9udGhzJywgJ3llYXJzJywgJ2RlY2FkZXMnXSxcbiAgICAgICAga2V5U3RhdGUgPSB7fSxcbiAgICAgICAga2V5UHJlc3NIYW5kbGVkID0ge307XG5cbiAgICB2YXIgTWluVmlld01vZGVOdW1iZXIgPSAwLFxuICAgICAgICBEZWZhdWx0ID0ge1xuICAgICAgICB0aW1lWm9uZTogJycsXG4gICAgICAgIGZvcm1hdDogZmFsc2UsXG4gICAgICAgIGRheVZpZXdIZWFkZXJGb3JtYXQ6ICdNTU1NIFlZWVknLFxuICAgICAgICBleHRyYUZvcm1hdHM6IGZhbHNlLFxuICAgICAgICBzdGVwcGluZzogMSxcbiAgICAgICAgbWluRGF0ZTogZmFsc2UsXG4gICAgICAgIG1heERhdGU6IGZhbHNlLFxuICAgICAgICB1c2VDdXJyZW50OiB0cnVlLFxuICAgICAgICBjb2xsYXBzZTogdHJ1ZSxcbiAgICAgICAgbG9jYWxlOiBtb21lbnQubG9jYWxlKCksXG4gICAgICAgIGRlZmF1bHREYXRlOiBmYWxzZSxcbiAgICAgICAgZGlzYWJsZWREYXRlczogZmFsc2UsXG4gICAgICAgIGVuYWJsZWREYXRlczogZmFsc2UsXG4gICAgICAgIGljb25zOiB7XG4gICAgICAgICAgICB0aW1lOiAnZmEgZmEtY2xvY2stbycsXG4gICAgICAgICAgICBkYXRlOiAnZmEgZmEtY2FsZW5kYXInLFxuICAgICAgICAgICAgdXA6ICdmYSBmYS1hcnJvdy11cCcsXG4gICAgICAgICAgICBkb3duOiAnZmEgZmEtYXJyb3ctZG93bicsXG4gICAgICAgICAgICBwcmV2aW91czogJ2ZhIGZhLWNoZXZyb24tbGVmdCcsXG4gICAgICAgICAgICBuZXh0OiAnZmEgZmEtY2hldnJvbi1yaWdodCcsXG4gICAgICAgICAgICB0b2RheTogJ2ZhIGZhLWNhbGVuZGFyLWNoZWNrLW8nLFxuICAgICAgICAgICAgY2xlYXI6ICdmYSBmYS1kZWxldGUnLFxuICAgICAgICAgICAgY2xvc2U6ICdmYSBmYS10aW1lcydcbiAgICAgICAgfSxcbiAgICAgICAgdG9vbHRpcHM6IHtcbiAgICAgICAgICAgIHRvZGF5OiAnR28gdG8gdG9kYXknLFxuICAgICAgICAgICAgY2xlYXI6ICdDbGVhciBzZWxlY3Rpb24nLFxuICAgICAgICAgICAgY2xvc2U6ICdDbG9zZSB0aGUgcGlja2VyJyxcbiAgICAgICAgICAgIHNlbGVjdE1vbnRoOiAnU2VsZWN0IE1vbnRoJyxcbiAgICAgICAgICAgIHByZXZNb250aDogJ1ByZXZpb3VzIE1vbnRoJyxcbiAgICAgICAgICAgIG5leHRNb250aDogJ05leHQgTW9udGgnLFxuICAgICAgICAgICAgc2VsZWN0WWVhcjogJ1NlbGVjdCBZZWFyJyxcbiAgICAgICAgICAgIHByZXZZZWFyOiAnUHJldmlvdXMgWWVhcicsXG4gICAgICAgICAgICBuZXh0WWVhcjogJ05leHQgWWVhcicsXG4gICAgICAgICAgICBzZWxlY3REZWNhZGU6ICdTZWxlY3QgRGVjYWRlJyxcbiAgICAgICAgICAgIHByZXZEZWNhZGU6ICdQcmV2aW91cyBEZWNhZGUnLFxuICAgICAgICAgICAgbmV4dERlY2FkZTogJ05leHQgRGVjYWRlJyxcbiAgICAgICAgICAgIHByZXZDZW50dXJ5OiAnUHJldmlvdXMgQ2VudHVyeScsXG4gICAgICAgICAgICBuZXh0Q2VudHVyeTogJ05leHQgQ2VudHVyeScsXG4gICAgICAgICAgICBwaWNrSG91cjogJ1BpY2sgSG91cicsXG4gICAgICAgICAgICBpbmNyZW1lbnRIb3VyOiAnSW5jcmVtZW50IEhvdXInLFxuICAgICAgICAgICAgZGVjcmVtZW50SG91cjogJ0RlY3JlbWVudCBIb3VyJyxcbiAgICAgICAgICAgIHBpY2tNaW51dGU6ICdQaWNrIE1pbnV0ZScsXG4gICAgICAgICAgICBpbmNyZW1lbnRNaW51dGU6ICdJbmNyZW1lbnQgTWludXRlJyxcbiAgICAgICAgICAgIGRlY3JlbWVudE1pbnV0ZTogJ0RlY3JlbWVudCBNaW51dGUnLFxuICAgICAgICAgICAgcGlja1NlY29uZDogJ1BpY2sgU2Vjb25kJyxcbiAgICAgICAgICAgIGluY3JlbWVudFNlY29uZDogJ0luY3JlbWVudCBTZWNvbmQnLFxuICAgICAgICAgICAgZGVjcmVtZW50U2Vjb25kOiAnRGVjcmVtZW50IFNlY29uZCcsXG4gICAgICAgICAgICB0b2dnbGVQZXJpb2Q6ICdUb2dnbGUgUGVyaW9kJyxcbiAgICAgICAgICAgIHNlbGVjdFRpbWU6ICdTZWxlY3QgVGltZScsXG4gICAgICAgICAgICBzZWxlY3REYXRlOiAnU2VsZWN0IERhdGUnXG4gICAgICAgIH0sXG4gICAgICAgIHVzZVN0cmljdDogZmFsc2UsXG4gICAgICAgIHNpZGVCeVNpZGU6IGZhbHNlLFxuICAgICAgICBkYXlzT2ZXZWVrRGlzYWJsZWQ6IGZhbHNlLFxuICAgICAgICBjYWxlbmRhcldlZWtzOiBmYWxzZSxcbiAgICAgICAgdmlld01vZGU6ICdkYXlzJyxcbiAgICAgICAgdG9vbGJhclBsYWNlbWVudDogJ2RlZmF1bHQnLFxuICAgICAgICBidXR0b25zOiB7XG4gICAgICAgICAgICBzaG93VG9kYXk6IGZhbHNlLFxuICAgICAgICAgICAgc2hvd0NsZWFyOiBmYWxzZSxcbiAgICAgICAgICAgIHNob3dDbG9zZTogZmFsc2VcbiAgICAgICAgfSxcbiAgICAgICAgd2lkZ2V0UG9zaXRpb25pbmc6IHtcbiAgICAgICAgICAgIGhvcml6b250YWw6ICdhdXRvJyxcbiAgICAgICAgICAgIHZlcnRpY2FsOiAnYXV0bydcbiAgICAgICAgfSxcbiAgICAgICAgd2lkZ2V0UGFyZW50OiBudWxsLFxuICAgICAgICBpZ25vcmVSZWFkb25seTogZmFsc2UsXG4gICAgICAgIGtlZXBPcGVuOiBmYWxzZSxcbiAgICAgICAgZm9jdXNPblNob3c6IHRydWUsXG4gICAgICAgIGlubGluZTogZmFsc2UsXG4gICAgICAgIGtlZXBJbnZhbGlkOiBmYWxzZSxcbiAgICAgICAga2V5QmluZHM6IHtcbiAgICAgICAgICAgIHVwOiBmdW5jdGlvbiB1cCgpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMud2lkZ2V0KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdmFyIGQgPSB0aGlzLl9kYXRlc1swXSB8fCB0aGlzLmdldE1vbWVudCgpO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLndpZGdldC5maW5kKCcuZGF0ZXBpY2tlcicpLmlzKCc6dmlzaWJsZScpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGF0ZShkLmNsb25lKCkuc3VidHJhY3QoNywgJ2QnKSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kYXRlKGQuY2xvbmUoKS5hZGQodGhpcy5zdGVwcGluZygpLCAnbScpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZG93bjogZnVuY3Rpb24gZG93bigpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMud2lkZ2V0KSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2hvdygpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciBkID0gdGhpcy5fZGF0ZXNbMF0gfHwgdGhpcy5nZXRNb21lbnQoKTtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy53aWRnZXQuZmluZCgnLmRhdGVwaWNrZXInKS5pcygnOnZpc2libGUnKSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmRhdGUoZC5jbG9uZSgpLmFkZCg3LCAnZCcpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmRhdGUoZC5jbG9uZSgpLnN1YnRyYWN0KHRoaXMuc3RlcHBpbmcoKSwgJ20nKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICdjb250cm9sIHVwJzogZnVuY3Rpb24gY29udHJvbFVwKCkge1xuICAgICAgICAgICAgICAgIGlmICghdGhpcy53aWRnZXQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgZCA9IHRoaXMuX2RhdGVzWzBdIHx8IHRoaXMuZ2V0TW9tZW50KCk7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMud2lkZ2V0LmZpbmQoJy5kYXRlcGlja2VyJykuaXMoJzp2aXNpYmxlJykpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kYXRlKGQuY2xvbmUoKS5zdWJ0cmFjdCgxLCAneScpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmRhdGUoZC5jbG9uZSgpLmFkZCgxLCAnaCcpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgJ2NvbnRyb2wgZG93bic6IGZ1bmN0aW9uIGNvbnRyb2xEb3duKCkge1xuICAgICAgICAgICAgICAgIGlmICghdGhpcy53aWRnZXQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgZCA9IHRoaXMuX2RhdGVzWzBdIHx8IHRoaXMuZ2V0TW9tZW50KCk7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMud2lkZ2V0LmZpbmQoJy5kYXRlcGlja2VyJykuaXMoJzp2aXNpYmxlJykpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kYXRlKGQuY2xvbmUoKS5hZGQoMSwgJ3knKSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kYXRlKGQuY2xvbmUoKS5zdWJ0cmFjdCgxLCAnaCcpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgbGVmdDogZnVuY3Rpb24gbGVmdCgpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMud2lkZ2V0KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdmFyIGQgPSB0aGlzLl9kYXRlc1swXSB8fCB0aGlzLmdldE1vbWVudCgpO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLndpZGdldC5maW5kKCcuZGF0ZXBpY2tlcicpLmlzKCc6dmlzaWJsZScpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGF0ZShkLmNsb25lKCkuc3VidHJhY3QoMSwgJ2QnKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHJpZ2h0OiBmdW5jdGlvbiByaWdodCgpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMud2lkZ2V0KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdmFyIGQgPSB0aGlzLl9kYXRlc1swXSB8fCB0aGlzLmdldE1vbWVudCgpO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLndpZGdldC5maW5kKCcuZGF0ZXBpY2tlcicpLmlzKCc6dmlzaWJsZScpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGF0ZShkLmNsb25lKCkuYWRkKDEsICdkJykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBwYWdlVXA6IGZ1bmN0aW9uIHBhZ2VVcCgpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMud2lkZ2V0KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdmFyIGQgPSB0aGlzLl9kYXRlc1swXSB8fCB0aGlzLmdldE1vbWVudCgpO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLndpZGdldC5maW5kKCcuZGF0ZXBpY2tlcicpLmlzKCc6dmlzaWJsZScpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGF0ZShkLmNsb25lKCkuc3VidHJhY3QoMSwgJ00nKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHBhZ2VEb3duOiBmdW5jdGlvbiBwYWdlRG93bigpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMud2lkZ2V0KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdmFyIGQgPSB0aGlzLl9kYXRlc1swXSB8fCB0aGlzLmdldE1vbWVudCgpO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLndpZGdldC5maW5kKCcuZGF0ZXBpY2tlcicpLmlzKCc6dmlzaWJsZScpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGF0ZShkLmNsb25lKCkuYWRkKDEsICdNJykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBlbnRlcjogZnVuY3Rpb24gZW50ZXIoKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5oaWRlKCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZXNjYXBlOiBmdW5jdGlvbiBlc2NhcGUoKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLndpZGdldCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMuaGlkZSgpO1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICdjb250cm9sIHNwYWNlJzogZnVuY3Rpb24gY29udHJvbFNwYWNlKCkge1xuICAgICAgICAgICAgICAgIGlmICghdGhpcy53aWRnZXQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAodGhpcy53aWRnZXQuZmluZCgnLnRpbWVwaWNrZXInKS5pcygnOnZpc2libGUnKSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLndpZGdldC5maW5kKCcuYnRuW2RhdGEtYWN0aW9uPVwidG9nZ2xlUGVyaW9kXCJdJykuY2xpY2soKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgdDogZnVuY3Rpb24gdCgpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmRhdGUodGhpcy5nZXRNb21lbnQoKSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgJ2RlbGV0ZSc6IGZ1bmN0aW9uIF9kZWxldGUoKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLndpZGdldCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMuY2xlYXIoKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgZGVidWc6IGZhbHNlLFxuICAgICAgICBhbGxvd0lucHV0VG9nZ2xlOiBmYWxzZSxcbiAgICAgICAgZGlzYWJsZWRUaW1lSW50ZXJ2YWxzOiBmYWxzZSxcbiAgICAgICAgZGlzYWJsZWRIb3VyczogZmFsc2UsXG4gICAgICAgIGVuYWJsZWRIb3VyczogZmFsc2UsXG4gICAgICAgIHZpZXdEYXRlOiBmYWxzZSxcbiAgICAgICAgYWxsb3dNdWx0aWRhdGU6IGZhbHNlLFxuICAgICAgICBtdWx0aWRhdGVTZXBhcmF0b3I6ICcsJ1xuICAgIH07XG5cbiAgICAvLyBSZVNoYXJwZXIgcmVzdG9yZSBJbmNvbnNpc3RlbnROYW1pbmdcblxuICAgIC8vIFJlU2hhcnBlciBkaXNhYmxlIG9uY2UgRGVjbGFyYXRpb25IaWRlc1xuICAgIC8vIFJlU2hhcnBlciBkaXNhYmxlIG9uY2UgSW5jb25zaXN0ZW50TmFtaW5nXG5cbiAgICB2YXIgRGF0ZVRpbWVQaWNrZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIC8qKiBAbmFtZXNwYWNlIGVEYXRhLmRhdGVPcHRpb25zICovXG4gICAgICAgIC8qKiBAbmFtZXNwYWNlIG1vbWVudC50eiAqL1xuXG4gICAgICAgIGZ1bmN0aW9uIERhdGVUaW1lUGlja2VyKGVsZW1lbnQsIG9wdGlvbnMpIHtcbiAgICAgICAgICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBEYXRlVGltZVBpY2tlcik7XG5cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMgPSB0aGlzLl9nZXRPcHRpb25zKG9wdGlvbnMpO1xuICAgICAgICAgICAgdGhpcy5fZWxlbWVudCA9IGVsZW1lbnQ7XG4gICAgICAgICAgICB0aGlzLl9kYXRlcyA9IFtdO1xuICAgICAgICAgICAgdGhpcy5fZGF0ZXNGb3JtYXR0ZWQgPSBbXTtcbiAgICAgICAgICAgIHRoaXMuX3ZpZXdEYXRlID0gbnVsbDtcbiAgICAgICAgICAgIHRoaXMudW5zZXQgPSB0cnVlO1xuICAgICAgICAgICAgdGhpcy5jb21wb25lbnQgPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMud2lkZ2V0ID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLnVzZTI0SG91cnMgPSBudWxsO1xuICAgICAgICAgICAgdGhpcy5hY3R1YWxGb3JtYXQgPSBudWxsO1xuICAgICAgICAgICAgdGhpcy5wYXJzZUZvcm1hdHMgPSBudWxsO1xuICAgICAgICAgICAgdGhpcy5jdXJyZW50Vmlld01vZGUgPSBudWxsO1xuXG4gICAgICAgICAgICB0aGlzLl9pbnQoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcmV0dXJuIHtzdHJpbmd9XG4gICAgICAgICAqL1xuXG5cbiAgICAgICAgLy9wcml2YXRlXG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl9pbnQgPSBmdW5jdGlvbiBfaW50KCkge1xuICAgICAgICAgICAgdmFyIHRhcmdldElucHV0ID0gdGhpcy5fZWxlbWVudC5kYXRhKCd0YXJnZXQtaW5wdXQnKTtcbiAgICAgICAgICAgIGlmICh0aGlzLl9lbGVtZW50LmlzKCdpbnB1dCcpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5pbnB1dCA9IHRoaXMuX2VsZW1lbnQ7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRhcmdldElucHV0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICBpZiAodGFyZ2V0SW5wdXQgPT09ICduZWFyZXN0Jykge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmlucHV0ID0gdGhpcy5fZWxlbWVudC5maW5kKCdpbnB1dCcpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuaW5wdXQgPSAkKHRhcmdldElucHV0KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuX2RhdGVzID0gW107XG4gICAgICAgICAgICB0aGlzLl9kYXRlc1swXSA9IHRoaXMuZ2V0TW9tZW50KCk7XG4gICAgICAgICAgICB0aGlzLl92aWV3RGF0ZSA9IHRoaXMuZ2V0TW9tZW50KCkuY2xvbmUoKTtcblxuICAgICAgICAgICAgJC5leHRlbmQodHJ1ZSwgdGhpcy5fb3B0aW9ucywgdGhpcy5fZGF0YVRvT3B0aW9ucygpKTtcblxuICAgICAgICAgICAgdGhpcy5vcHRpb25zKHRoaXMuX29wdGlvbnMpO1xuXG4gICAgICAgICAgICB0aGlzLl9pbml0Rm9ybWF0dGluZygpO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5pbnB1dCAhPT0gdW5kZWZpbmVkICYmIHRoaXMuaW5wdXQuaXMoJ2lucHV0JykgJiYgdGhpcy5pbnB1dC52YWwoKS50cmltKCkubGVuZ3RoICE9PSAwKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fc2V0VmFsdWUodGhpcy5fcGFyc2VJbnB1dERhdGUodGhpcy5pbnB1dC52YWwoKS50cmltKCkpLCAwKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAodGhpcy5fb3B0aW9ucy5kZWZhdWx0RGF0ZSAmJiB0aGlzLmlucHV0ICE9PSB1bmRlZmluZWQgJiYgdGhpcy5pbnB1dC5hdHRyKCdwbGFjZWhvbGRlcicpID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9zZXRWYWx1ZSh0aGlzLl9vcHRpb25zLmRlZmF1bHREYXRlLCAwKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLl9vcHRpb25zLmlubGluZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuc2hvdygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5fdXBkYXRlID0gZnVuY3Rpb24gX3VwZGF0ZSgpIHtcbiAgICAgICAgICAgIGlmICghdGhpcy53aWRnZXQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl9maWxsRGF0ZSgpO1xuICAgICAgICAgICAgdGhpcy5fZmlsbFRpbWUoKTtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuX3NldFZhbHVlID0gZnVuY3Rpb24gX3NldFZhbHVlKHRhcmdldE1vbWVudCwgaW5kZXgpIHtcbiAgICAgICAgICAgIHZhciBvbGREYXRlID0gdGhpcy51bnNldCA/IG51bGwgOiB0aGlzLl9kYXRlc1tpbmRleF07XG4gICAgICAgICAgICB2YXIgb3V0cFZhbHVlID0gJyc7XG4gICAgICAgICAgICAvLyBjYXNlIG9mIGNhbGxpbmcgc2V0VmFsdWUobnVsbCBvciBmYWxzZSlcbiAgICAgICAgICAgIGlmICghdGFyZ2V0TW9tZW50KSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLl9vcHRpb25zLmFsbG93TXVsdGlkYXRlIHx8IHRoaXMuX2RhdGVzLmxlbmd0aCA9PT0gMSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnVuc2V0ID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fZGF0ZXMgPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fZGF0ZXNGb3JtYXR0ZWQgPSBbXTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBvdXRwVmFsdWUgPSB0aGlzLl9lbGVtZW50LmRhdGEoJ2RhdGUnKSArICcsJztcbiAgICAgICAgICAgICAgICAgICAgb3V0cFZhbHVlID0gb3V0cFZhbHVlLnJlcGxhY2Uob2xkRGF0ZS5mb3JtYXQodGhpcy5hY3R1YWxGb3JtYXQpICsgJywnLCAnJykucmVwbGFjZSgnLCwnLCAnJykucmVwbGFjZSgvLFxccyokLywgJycpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9kYXRlcy5zcGxpY2UoaW5kZXgsIDEpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9kYXRlc0Zvcm1hdHRlZC5zcGxpY2UoaW5kZXgsIDEpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5pbnB1dCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuaW5wdXQudmFsKG91dHBWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuaW5wdXQudHJpZ2dlcignaW5wdXQnKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5fZWxlbWVudC5kYXRhKCdkYXRlJywgb3V0cFZhbHVlKTtcbiAgICAgICAgICAgICAgICB0aGlzLl9ub3RpZnlFdmVudCh7XG4gICAgICAgICAgICAgICAgICAgIHR5cGU6IERhdGVUaW1lUGlja2VyLkV2ZW50LkNIQU5HRSxcbiAgICAgICAgICAgICAgICAgICAgZGF0ZTogZmFsc2UsXG4gICAgICAgICAgICAgICAgICAgIG9sZERhdGU6IG9sZERhdGVcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB0aGlzLl91cGRhdGUoKTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRhcmdldE1vbWVudCA9IHRhcmdldE1vbWVudC5jbG9uZSgpLmxvY2FsZSh0aGlzLl9vcHRpb25zLmxvY2FsZSk7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLl9oYXNUaW1lWm9uZSgpKSB7XG4gICAgICAgICAgICAgICAgdGFyZ2V0TW9tZW50LnR6KHRoaXMuX29wdGlvbnMudGltZVpvbmUpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy5zdGVwcGluZyAhPT0gMSkge1xuICAgICAgICAgICAgICAgIHRhcmdldE1vbWVudC5taW51dGVzKE1hdGgucm91bmQodGFyZ2V0TW9tZW50Lm1pbnV0ZXMoKSAvIHRoaXMuX29wdGlvbnMuc3RlcHBpbmcpICogdGhpcy5fb3B0aW9ucy5zdGVwcGluZykuc2Vjb25kcygwKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHRoaXMuX2lzVmFsaWQodGFyZ2V0TW9tZW50KSkge1xuICAgICAgICAgICAgICAgIHRoaXMuX2RhdGVzW2luZGV4XSA9IHRhcmdldE1vbWVudDtcbiAgICAgICAgICAgICAgICB0aGlzLl9kYXRlc0Zvcm1hdHRlZFtpbmRleF0gPSB0YXJnZXRNb21lbnQuZm9ybWF0KCdZWVlZLU1NLUREJyk7XG4gICAgICAgICAgICAgICAgdGhpcy5fdmlld0RhdGUgPSB0YXJnZXRNb21lbnQuY2xvbmUoKTtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy5hbGxvd011bHRpZGF0ZSAmJiB0aGlzLl9kYXRlcy5sZW5ndGggPiAxKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5fZGF0ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG91dHBWYWx1ZSArPSAnJyArIHRoaXMuX2RhdGVzW2ldLmZvcm1hdCh0aGlzLmFjdHVhbEZvcm1hdCkgKyB0aGlzLl9vcHRpb25zLm11bHRpZGF0ZVNlcGFyYXRvcjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBvdXRwVmFsdWUgPSBvdXRwVmFsdWUucmVwbGFjZSgvLFxccyokLywgJycpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG91dHBWYWx1ZSA9IHRoaXMuX2RhdGVzW2luZGV4XS5mb3JtYXQodGhpcy5hY3R1YWxGb3JtYXQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5pbnB1dCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuaW5wdXQudmFsKG91dHBWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuaW5wdXQudHJpZ2dlcignaW5wdXQnKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5fZWxlbWVudC5kYXRhKCdkYXRlJywgb3V0cFZhbHVlKTtcblxuICAgICAgICAgICAgICAgIHRoaXMudW5zZXQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB0aGlzLl91cGRhdGUoKTtcbiAgICAgICAgICAgICAgICB0aGlzLl9ub3RpZnlFdmVudCh7XG4gICAgICAgICAgICAgICAgICAgIHR5cGU6IERhdGVUaW1lUGlja2VyLkV2ZW50LkNIQU5HRSxcbiAgICAgICAgICAgICAgICAgICAgZGF0ZTogdGhpcy5fZGF0ZXNbaW5kZXhdLmNsb25lKCksXG4gICAgICAgICAgICAgICAgICAgIG9sZERhdGU6IG9sZERhdGVcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLl9vcHRpb25zLmtlZXBJbnZhbGlkKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmlucHV0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuaW5wdXQudmFsKCcnICsgKHRoaXMudW5zZXQgPyAnJyA6IHRoaXMuX2RhdGVzW2luZGV4XS5mb3JtYXQodGhpcy5hY3R1YWxGb3JtYXQpKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmlucHV0LnRyaWdnZXIoJ2lucHV0Jyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9ub3RpZnlFdmVudCh7XG4gICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiBEYXRlVGltZVBpY2tlci5FdmVudC5DSEFOR0UsXG4gICAgICAgICAgICAgICAgICAgICAgICBkYXRlOiB0YXJnZXRNb21lbnQsXG4gICAgICAgICAgICAgICAgICAgICAgICBvbGREYXRlOiBvbGREYXRlXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLl9ub3RpZnlFdmVudCh7XG4gICAgICAgICAgICAgICAgICAgIHR5cGU6IERhdGVUaW1lUGlja2VyLkV2ZW50LkVSUk9SLFxuICAgICAgICAgICAgICAgICAgICBkYXRlOiB0YXJnZXRNb21lbnQsXG4gICAgICAgICAgICAgICAgICAgIG9sZERhdGU6IG9sZERhdGVcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuX2NoYW5nZSA9IGZ1bmN0aW9uIF9jaGFuZ2UoZSkge1xuICAgICAgICAgICAgdmFyIHZhbCA9ICQoZS50YXJnZXQpLnZhbCgpLnRyaW0oKSxcbiAgICAgICAgICAgICAgICBwYXJzZWREYXRlID0gdmFsID8gdGhpcy5fcGFyc2VJbnB1dERhdGUodmFsKSA6IG51bGw7XG4gICAgICAgICAgICB0aGlzLl9zZXRWYWx1ZShwYXJzZWREYXRlKTtcbiAgICAgICAgICAgIGUuc3RvcEltbWVkaWF0ZVByb3BhZ2F0aW9uKCk7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH07XG5cbiAgICAgICAgLy9ub2luc3BlY3Rpb24gSlNNZXRob2RDYW5CZVN0YXRpY1xuXG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl9nZXRPcHRpb25zID0gZnVuY3Rpb24gX2dldE9wdGlvbnMob3B0aW9ucykge1xuICAgICAgICAgICAgb3B0aW9ucyA9ICQuZXh0ZW5kKHRydWUsIHt9LCBEZWZhdWx0LCBvcHRpb25zKTtcbiAgICAgICAgICAgIHJldHVybiBvcHRpb25zO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5faGFzVGltZVpvbmUgPSBmdW5jdGlvbiBfaGFzVGltZVpvbmUoKSB7XG4gICAgICAgICAgICByZXR1cm4gbW9tZW50LnR6ICE9PSB1bmRlZmluZWQgJiYgdGhpcy5fb3B0aW9ucy50aW1lWm9uZSAhPT0gdW5kZWZpbmVkICYmIHRoaXMuX29wdGlvbnMudGltZVpvbmUgIT09IG51bGwgJiYgdGhpcy5fb3B0aW9ucy50aW1lWm9uZSAhPT0gJyc7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl9pc0VuYWJsZWQgPSBmdW5jdGlvbiBfaXNFbmFibGVkKGdyYW51bGFyaXR5KSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIGdyYW51bGFyaXR5ICE9PSAnc3RyaW5nJyB8fCBncmFudWxhcml0eS5sZW5ndGggPiAxKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignaXNFbmFibGVkIGV4cGVjdHMgYSBzaW5nbGUgY2hhcmFjdGVyIHN0cmluZyBwYXJhbWV0ZXInKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHN3aXRjaCAoZ3JhbnVsYXJpdHkpIHtcbiAgICAgICAgICAgICAgICBjYXNlICd5JzpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuYWN0dWFsRm9ybWF0LmluZGV4T2YoJ1knKSAhPT0gLTE7XG4gICAgICAgICAgICAgICAgY2FzZSAnTSc6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmFjdHVhbEZvcm1hdC5pbmRleE9mKCdNJykgIT09IC0xO1xuICAgICAgICAgICAgICAgIGNhc2UgJ2QnOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5hY3R1YWxGb3JtYXQudG9Mb3dlckNhc2UoKS5pbmRleE9mKCdkJykgIT09IC0xO1xuICAgICAgICAgICAgICAgIGNhc2UgJ2gnOlxuICAgICAgICAgICAgICAgIGNhc2UgJ0gnOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5hY3R1YWxGb3JtYXQudG9Mb3dlckNhc2UoKS5pbmRleE9mKCdoJykgIT09IC0xO1xuICAgICAgICAgICAgICAgIGNhc2UgJ20nOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5hY3R1YWxGb3JtYXQuaW5kZXhPZignbScpICE9PSAtMTtcbiAgICAgICAgICAgICAgICBjYXNlICdzJzpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuYWN0dWFsRm9ybWF0LmluZGV4T2YoJ3MnKSAhPT0gLTE7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5faGFzVGltZSA9IGZ1bmN0aW9uIF9oYXNUaW1lKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2lzRW5hYmxlZCgnaCcpIHx8IHRoaXMuX2lzRW5hYmxlZCgnbScpIHx8IHRoaXMuX2lzRW5hYmxlZCgncycpO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5faGFzRGF0ZSA9IGZ1bmN0aW9uIF9oYXNEYXRlKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2lzRW5hYmxlZCgneScpIHx8IHRoaXMuX2lzRW5hYmxlZCgnTScpIHx8IHRoaXMuX2lzRW5hYmxlZCgnZCcpO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5fZGF0YVRvT3B0aW9ucyA9IGZ1bmN0aW9uIF9kYXRhVG9PcHRpb25zKCkge1xuICAgICAgICAgICAgdmFyIGVEYXRhID0gdGhpcy5fZWxlbWVudC5kYXRhKCk7XG4gICAgICAgICAgICB2YXIgZGF0YU9wdGlvbnMgPSB7fTtcblxuICAgICAgICAgICAgaWYgKGVEYXRhLmRhdGVPcHRpb25zICYmIGVEYXRhLmRhdGVPcHRpb25zIGluc3RhbmNlb2YgT2JqZWN0KSB7XG4gICAgICAgICAgICAgICAgZGF0YU9wdGlvbnMgPSAkLmV4dGVuZCh0cnVlLCBkYXRhT3B0aW9ucywgZURhdGEuZGF0ZU9wdGlvbnMpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAkLmVhY2godGhpcy5fb3B0aW9ucywgZnVuY3Rpb24gKGtleSkge1xuICAgICAgICAgICAgICAgIHZhciBhdHRyaWJ1dGVOYW1lID0gJ2RhdGUnICsga2V5LmNoYXJBdCgwKS50b1VwcGVyQ2FzZSgpICsga2V5LnNsaWNlKDEpOyAvL3RvZG8gZGF0YSBhcGkga2V5XG4gICAgICAgICAgICAgICAgaWYgKGVEYXRhW2F0dHJpYnV0ZU5hbWVdICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgZGF0YU9wdGlvbnNba2V5XSA9IGVEYXRhW2F0dHJpYnV0ZU5hbWVdO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGRlbGV0ZSBkYXRhT3B0aW9uc1trZXldO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcmV0dXJuIGRhdGFPcHRpb25zO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5fbm90aWZ5RXZlbnQgPSBmdW5jdGlvbiBfbm90aWZ5RXZlbnQoZSkge1xuICAgICAgICAgICAgaWYgKGUudHlwZSA9PT0gRGF0ZVRpbWVQaWNrZXIuRXZlbnQuQ0hBTkdFICYmIGUuZGF0ZSAmJiBlLmRhdGUuaXNTYW1lKGUub2xkRGF0ZSkgfHwgIWUuZGF0ZSAmJiAhZS5vbGREYXRlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fZWxlbWVudC50cmlnZ2VyKGUpO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5fdmlld1VwZGF0ZSA9IGZ1bmN0aW9uIF92aWV3VXBkYXRlKGUpIHtcbiAgICAgICAgICAgIGlmIChlID09PSAneScpIHtcbiAgICAgICAgICAgICAgICBlID0gJ1lZWVknO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fbm90aWZ5RXZlbnQoe1xuICAgICAgICAgICAgICAgIHR5cGU6IERhdGVUaW1lUGlja2VyLkV2ZW50LlVQREFURSxcbiAgICAgICAgICAgICAgICBjaGFuZ2U6IGUsXG4gICAgICAgICAgICAgICAgdmlld0RhdGU6IHRoaXMuX3ZpZXdEYXRlLmNsb25lKClcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5fc2hvd01vZGUgPSBmdW5jdGlvbiBfc2hvd01vZGUoZGlyKSB7XG4gICAgICAgICAgICBpZiAoIXRoaXMud2lkZ2V0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGRpcikge1xuICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudFZpZXdNb2RlID0gTWF0aC5tYXgoTWluVmlld01vZGVOdW1iZXIsIE1hdGgubWluKDMsIHRoaXMuY3VycmVudFZpZXdNb2RlICsgZGlyKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLndpZGdldC5maW5kKCcuZGF0ZXBpY2tlciA+IGRpdicpLmhpZGUoKS5maWx0ZXIoJy5kYXRlcGlja2VyLScgKyBEYXRlUGlja2VyTW9kZXNbdGhpcy5jdXJyZW50Vmlld01vZGVdLkNMQVNTX05BTUUpLnNob3coKTtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuX2lzSW5EaXNhYmxlZERhdGVzID0gZnVuY3Rpb24gX2lzSW5EaXNhYmxlZERhdGVzKHRlc3REYXRlKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5kaXNhYmxlZERhdGVzW3Rlc3REYXRlLmZvcm1hdCgnWVlZWS1NTS1ERCcpXSA9PT0gdHJ1ZTtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuX2lzSW5FbmFibGVkRGF0ZXMgPSBmdW5jdGlvbiBfaXNJbkVuYWJsZWREYXRlcyh0ZXN0RGF0ZSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMuZW5hYmxlZERhdGVzW3Rlc3REYXRlLmZvcm1hdCgnWVlZWS1NTS1ERCcpXSA9PT0gdHJ1ZTtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuX2lzSW5EaXNhYmxlZEhvdXJzID0gZnVuY3Rpb24gX2lzSW5EaXNhYmxlZEhvdXJzKHRlc3REYXRlKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5kaXNhYmxlZEhvdXJzW3Rlc3REYXRlLmZvcm1hdCgnSCcpXSA9PT0gdHJ1ZTtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuX2lzSW5FbmFibGVkSG91cnMgPSBmdW5jdGlvbiBfaXNJbkVuYWJsZWRIb3Vycyh0ZXN0RGF0ZSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMuZW5hYmxlZEhvdXJzW3Rlc3REYXRlLmZvcm1hdCgnSCcpXSA9PT0gdHJ1ZTtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuX2lzVmFsaWQgPSBmdW5jdGlvbiBfaXNWYWxpZCh0YXJnZXRNb21lbnQsIGdyYW51bGFyaXR5KSB7XG4gICAgICAgICAgICBpZiAoIXRhcmdldE1vbWVudC5pc1ZhbGlkKCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy5kaXNhYmxlZERhdGVzICYmIGdyYW51bGFyaXR5ID09PSAnZCcgJiYgdGhpcy5faXNJbkRpc2FibGVkRGF0ZXModGFyZ2V0TW9tZW50KSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLl9vcHRpb25zLmVuYWJsZWREYXRlcyAmJiBncmFudWxhcml0eSA9PT0gJ2QnICYmICF0aGlzLl9pc0luRW5hYmxlZERhdGVzKHRhcmdldE1vbWVudCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy5taW5EYXRlICYmIHRhcmdldE1vbWVudC5pc0JlZm9yZSh0aGlzLl9vcHRpb25zLm1pbkRhdGUsIGdyYW51bGFyaXR5KSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLl9vcHRpb25zLm1heERhdGUgJiYgdGFyZ2V0TW9tZW50LmlzQWZ0ZXIodGhpcy5fb3B0aW9ucy5tYXhEYXRlLCBncmFudWxhcml0eSkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy5kYXlzT2ZXZWVrRGlzYWJsZWQgJiYgZ3JhbnVsYXJpdHkgPT09ICdkJyAmJiB0aGlzLl9vcHRpb25zLmRheXNPZldlZWtEaXNhYmxlZC5pbmRleE9mKHRhcmdldE1vbWVudC5kYXkoKSkgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMuZGlzYWJsZWRIb3VycyAmJiAoZ3JhbnVsYXJpdHkgPT09ICdoJyB8fCBncmFudWxhcml0eSA9PT0gJ20nIHx8IGdyYW51bGFyaXR5ID09PSAncycpICYmIHRoaXMuX2lzSW5EaXNhYmxlZEhvdXJzKHRhcmdldE1vbWVudCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy5lbmFibGVkSG91cnMgJiYgKGdyYW51bGFyaXR5ID09PSAnaCcgfHwgZ3JhbnVsYXJpdHkgPT09ICdtJyB8fCBncmFudWxhcml0eSA9PT0gJ3MnKSAmJiAhdGhpcy5faXNJbkVuYWJsZWRIb3Vycyh0YXJnZXRNb21lbnQpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMuZGlzYWJsZWRUaW1lSW50ZXJ2YWxzICYmIChncmFudWxhcml0eSA9PT0gJ2gnIHx8IGdyYW51bGFyaXR5ID09PSAnbScgfHwgZ3JhbnVsYXJpdHkgPT09ICdzJykpIHtcbiAgICAgICAgICAgICAgICB2YXIgZm91bmQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAkLmVhY2godGhpcy5fb3B0aW9ucy5kaXNhYmxlZFRpbWVJbnRlcnZhbHMsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRhcmdldE1vbWVudC5pc0JldHdlZW4odGhpc1swXSwgdGhpc1sxXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvdW5kID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIGlmIChmb3VuZCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl9wYXJzZUlucHV0RGF0ZSA9IGZ1bmN0aW9uIF9wYXJzZUlucHV0RGF0ZShpbnB1dERhdGUpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLl9vcHRpb25zLnBhcnNlSW5wdXREYXRlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICBpZiAoIW1vbWVudC5pc01vbWVudChpbnB1dERhdGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlucHV0RGF0ZSA9IHRoaXMuZ2V0TW9tZW50KGlucHV0RGF0ZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpbnB1dERhdGUgPSB0aGlzLl9vcHRpb25zLnBhcnNlSW5wdXREYXRlKGlucHV0RGF0ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvL2lucHV0RGF0ZS5sb2NhbGUodGhpcy5vcHRpb25zLmxvY2FsZSk7XG4gICAgICAgICAgICByZXR1cm4gaW5wdXREYXRlO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5fa2V5ZG93biA9IGZ1bmN0aW9uIF9rZXlkb3duKGUpIHtcbiAgICAgICAgICAgIHZhciBoYW5kbGVyID0gbnVsbCxcbiAgICAgICAgICAgICAgICBpbmRleCA9IHZvaWQgMCxcbiAgICAgICAgICAgICAgICBpbmRleDIgPSB2b2lkIDAsXG4gICAgICAgICAgICAgICAga2V5QmluZEtleXMgPSB2b2lkIDAsXG4gICAgICAgICAgICAgICAgYWxsTW9kaWZpZXJzUHJlc3NlZCA9IHZvaWQgMDtcbiAgICAgICAgICAgIHZhciBwcmVzc2VkS2V5cyA9IFtdLFxuICAgICAgICAgICAgICAgIHByZXNzZWRNb2RpZmllcnMgPSB7fSxcbiAgICAgICAgICAgICAgICBjdXJyZW50S2V5ID0gZS53aGljaCxcbiAgICAgICAgICAgICAgICBwcmVzc2VkID0gJ3AnO1xuXG4gICAgICAgICAgICBrZXlTdGF0ZVtjdXJyZW50S2V5XSA9IHByZXNzZWQ7XG5cbiAgICAgICAgICAgIGZvciAoaW5kZXggaW4ga2V5U3RhdGUpIHtcbiAgICAgICAgICAgICAgICBpZiAoa2V5U3RhdGUuaGFzT3duUHJvcGVydHkoaW5kZXgpICYmIGtleVN0YXRlW2luZGV4XSA9PT0gcHJlc3NlZCkge1xuICAgICAgICAgICAgICAgICAgICBwcmVzc2VkS2V5cy5wdXNoKGluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHBhcnNlSW50KGluZGV4LCAxMCkgIT09IGN1cnJlbnRLZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHByZXNzZWRNb2RpZmllcnNbaW5kZXhdID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZm9yIChpbmRleCBpbiB0aGlzLl9vcHRpb25zLmtleUJpbmRzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMua2V5QmluZHMuaGFzT3duUHJvcGVydHkoaW5kZXgpICYmIHR5cGVvZiB0aGlzLl9vcHRpb25zLmtleUJpbmRzW2luZGV4XSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgICAgICAgICBrZXlCaW5kS2V5cyA9IGluZGV4LnNwbGl0KCcgJyk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChrZXlCaW5kS2V5cy5sZW5ndGggPT09IHByZXNzZWRLZXlzLmxlbmd0aCAmJiBLZXlNYXBbY3VycmVudEtleV0gPT09IGtleUJpbmRLZXlzW2tleUJpbmRLZXlzLmxlbmd0aCAtIDFdKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhbGxNb2RpZmllcnNQcmVzc2VkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoaW5kZXgyID0ga2V5QmluZEtleXMubGVuZ3RoIC0gMjsgaW5kZXgyID49IDA7IGluZGV4Mi0tKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCEoS2V5TWFwW2tleUJpbmRLZXlzW2luZGV4Ml1dIGluIHByZXNzZWRNb2RpZmllcnMpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFsbE1vZGlmaWVyc1ByZXNzZWQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGFsbE1vZGlmaWVyc1ByZXNzZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYW5kbGVyID0gdGhpcy5fb3B0aW9ucy5rZXlCaW5kc1tpbmRleF07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChoYW5kbGVyKSB7XG4gICAgICAgICAgICAgICAgaWYgKGhhbmRsZXIuY2FsbCh0aGlzLndpZGdldCkpIHtcbiAgICAgICAgICAgICAgICAgICAgZS5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgICAgICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICAvL25vaW5zcGVjdGlvbiBKU01ldGhvZENhbkJlU3RhdGljLFNwZWxsQ2hlY2tpbmdJbnNwZWN0aW9uXG5cblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuX2tleXVwID0gZnVuY3Rpb24gX2tleXVwKGUpIHtcbiAgICAgICAgICAgIGtleVN0YXRlW2Uud2hpY2hdID0gJ3InO1xuICAgICAgICAgICAgaWYgKGtleVByZXNzSGFuZGxlZFtlLndoaWNoXSkge1xuICAgICAgICAgICAgICAgIGtleVByZXNzSGFuZGxlZFtlLndoaWNoXSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIGUuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5faW5kZXhHaXZlbkRhdGVzID0gZnVuY3Rpb24gX2luZGV4R2l2ZW5EYXRlcyhnaXZlbkRhdGVzQXJyYXkpIHtcbiAgICAgICAgICAgIC8vIFN0b3JlIGdpdmVuIGVuYWJsZWREYXRlcyBhbmQgZGlzYWJsZWREYXRlcyBhcyBrZXlzLlxuICAgICAgICAgICAgLy8gVGhpcyB3YXkgd2UgY2FuIGNoZWNrIHRoZWlyIGV4aXN0ZW5jZSBpbiBPKDEpIHRpbWUgaW5zdGVhZCBvZiBsb29waW5nIHRocm91Z2ggd2hvbGUgYXJyYXkuXG4gICAgICAgICAgICAvLyAoZm9yIGV4YW1wbGU6IG9wdGlvbnMuZW5hYmxlZERhdGVzWycyMDE0LTAyLTI3J10gPT09IHRydWUpXG4gICAgICAgICAgICB2YXIgZ2l2ZW5EYXRlc0luZGV4ZWQgPSB7fSxcbiAgICAgICAgICAgICAgICBzZWxmID0gdGhpcztcbiAgICAgICAgICAgICQuZWFjaChnaXZlbkRhdGVzQXJyYXksIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICB2YXIgZERhdGUgPSBzZWxmLl9wYXJzZUlucHV0RGF0ZSh0aGlzKTtcbiAgICAgICAgICAgICAgICBpZiAoZERhdGUuaXNWYWxpZCgpKSB7XG4gICAgICAgICAgICAgICAgICAgIGdpdmVuRGF0ZXNJbmRleGVkW2REYXRlLmZvcm1hdCgnWVlZWS1NTS1ERCcpXSA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZXR1cm4gT2JqZWN0LmtleXMoZ2l2ZW5EYXRlc0luZGV4ZWQpLmxlbmd0aCA/IGdpdmVuRGF0ZXNJbmRleGVkIDogZmFsc2U7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl9pbmRleEdpdmVuSG91cnMgPSBmdW5jdGlvbiBfaW5kZXhHaXZlbkhvdXJzKGdpdmVuSG91cnNBcnJheSkge1xuICAgICAgICAgICAgLy8gU3RvcmUgZ2l2ZW4gZW5hYmxlZEhvdXJzIGFuZCBkaXNhYmxlZEhvdXJzIGFzIGtleXMuXG4gICAgICAgICAgICAvLyBUaGlzIHdheSB3ZSBjYW4gY2hlY2sgdGhlaXIgZXhpc3RlbmNlIGluIE8oMSkgdGltZSBpbnN0ZWFkIG9mIGxvb3BpbmcgdGhyb3VnaCB3aG9sZSBhcnJheS5cbiAgICAgICAgICAgIC8vIChmb3IgZXhhbXBsZTogb3B0aW9ucy5lbmFibGVkSG91cnNbJzIwMTQtMDItMjcnXSA9PT0gdHJ1ZSlcbiAgICAgICAgICAgIHZhciBnaXZlbkhvdXJzSW5kZXhlZCA9IHt9O1xuICAgICAgICAgICAgJC5lYWNoKGdpdmVuSG91cnNBcnJheSwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIGdpdmVuSG91cnNJbmRleGVkW3RoaXNdID0gdHJ1ZTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5rZXlzKGdpdmVuSG91cnNJbmRleGVkKS5sZW5ndGggPyBnaXZlbkhvdXJzSW5kZXhlZCA6IGZhbHNlO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5faW5pdEZvcm1hdHRpbmcgPSBmdW5jdGlvbiBfaW5pdEZvcm1hdHRpbmcoKSB7XG4gICAgICAgICAgICB2YXIgZm9ybWF0ID0gdGhpcy5fb3B0aW9ucy5mb3JtYXQgfHwgJ0wgTFQnLFxuICAgICAgICAgICAgICAgIHNlbGYgPSB0aGlzO1xuXG4gICAgICAgICAgICB0aGlzLmFjdHVhbEZvcm1hdCA9IGZvcm1hdC5yZXBsYWNlKC8oXFxbW15cXFtdKl0pfChcXFxcKT8oTFRTfExUfExMP0w/TD98bHsxLDR9KS9nLCBmdW5jdGlvbiAoZm9ybWF0SW5wdXQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gc2VsZi5fZGF0ZXNbMF0ubG9jYWxlRGF0YSgpLmxvbmdEYXRlRm9ybWF0KGZvcm1hdElucHV0KSB8fCBmb3JtYXRJbnB1dDsgLy90b2RvIHRha2luZyB0aGUgZmlyc3QgZGF0ZSBzaG91bGQgYmUgb2tcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICB0aGlzLnBhcnNlRm9ybWF0cyA9IHRoaXMuX29wdGlvbnMuZXh0cmFGb3JtYXRzID8gdGhpcy5fb3B0aW9ucy5leHRyYUZvcm1hdHMuc2xpY2UoKSA6IFtdO1xuICAgICAgICAgICAgaWYgKHRoaXMucGFyc2VGb3JtYXRzLmluZGV4T2YoZm9ybWF0KSA8IDAgJiYgdGhpcy5wYXJzZUZvcm1hdHMuaW5kZXhPZih0aGlzLmFjdHVhbEZvcm1hdCkgPCAwKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5wYXJzZUZvcm1hdHMucHVzaCh0aGlzLmFjdHVhbEZvcm1hdCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMudXNlMjRIb3VycyA9IHRoaXMuYWN0dWFsRm9ybWF0LnRvTG93ZXJDYXNlKCkuaW5kZXhPZignYScpIDwgMSAmJiB0aGlzLmFjdHVhbEZvcm1hdC5yZXBsYWNlKC9cXFsuKj9dL2csICcnKS5pbmRleE9mKCdoJykgPCAxO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5faXNFbmFibGVkKCd5JykpIHtcbiAgICAgICAgICAgICAgICBNaW5WaWV3TW9kZU51bWJlciA9IDI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5faXNFbmFibGVkKCdNJykpIHtcbiAgICAgICAgICAgICAgICBNaW5WaWV3TW9kZU51bWJlciA9IDE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5faXNFbmFibGVkKCdkJykpIHtcbiAgICAgICAgICAgICAgICBNaW5WaWV3TW9kZU51bWJlciA9IDA7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuY3VycmVudFZpZXdNb2RlID0gTWF0aC5tYXgoTWluVmlld01vZGVOdW1iZXIsIHRoaXMuY3VycmVudFZpZXdNb2RlKTtcblxuICAgICAgICAgICAgaWYgKCF0aGlzLnVuc2V0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fc2V0VmFsdWUodGhpcy5fZGF0ZXNbMF0sIDApO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5fZ2V0TGFzdFBpY2tlZERhdGUgPSBmdW5jdGlvbiBfZ2V0TGFzdFBpY2tlZERhdGUoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fZGF0ZXNbdGhpcy5fZ2V0TGFzdFBpY2tlZERhdGVJbmRleCgpXTtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuX2dldExhc3RQaWNrZWREYXRlSW5kZXggPSBmdW5jdGlvbiBfZ2V0TGFzdFBpY2tlZERhdGVJbmRleCgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9kYXRlcy5sZW5ndGggLSAxO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8vcHVibGljXG5cblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuZ2V0TW9tZW50ID0gZnVuY3Rpb24gZ2V0TW9tZW50KGQpIHtcbiAgICAgICAgICAgIHZhciByZXR1cm5Nb21lbnQgPSB2b2lkIDA7XG5cbiAgICAgICAgICAgIGlmIChkID09PSB1bmRlZmluZWQgfHwgZCA9PT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHJldHVybk1vbWVudCA9IG1vbWVudCgpOyAvL1RPRE8gc2hvdWxkIHRoaXMgdXNlIGZvcm1hdD8gYW5kIGxvY2FsZT9cbiAgICAgICAgICAgIH0gZWxzZSBpZiAodGhpcy5faGFzVGltZVpvbmUoKSkge1xuICAgICAgICAgICAgICAgIC8vIFRoZXJlIGlzIGEgc3RyaW5nIHRvIHBhcnNlIGFuZCBhIGRlZmF1bHQgdGltZSB6b25lXG4gICAgICAgICAgICAgICAgLy8gcGFyc2Ugd2l0aCB0aGUgdHogZnVuY3Rpb24gd2hpY2ggdGFrZXMgYSBkZWZhdWx0IHRpbWUgem9uZSBpZiBpdCBpcyBub3QgaW4gdGhlIGZvcm1hdCBzdHJpbmdcbiAgICAgICAgICAgICAgICByZXR1cm5Nb21lbnQgPSBtb21lbnQudHooZCwgdGhpcy5wYXJzZUZvcm1hdHMsIHRoaXMuX29wdGlvbnMudXNlU3RyaWN0LCB0aGlzLl9vcHRpb25zLnRpbWVab25lKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuTW9tZW50ID0gbW9tZW50KGQsIHRoaXMucGFyc2VGb3JtYXRzLCB0aGlzLl9vcHRpb25zLnVzZVN0cmljdCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0aGlzLl9oYXNUaW1lWm9uZSgpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuTW9tZW50LnR6KHRoaXMuX29wdGlvbnMudGltZVpvbmUpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gcmV0dXJuTW9tZW50O1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS50b2dnbGUgPSBmdW5jdGlvbiB0b2dnbGUoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy53aWRnZXQgPyB0aGlzLmhpZGUoKSA6IHRoaXMuc2hvdygpO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5pZ25vcmVSZWFkb25seSA9IGZ1bmN0aW9uIGlnbm9yZVJlYWRvbmx5KF9pZ25vcmVSZWFkb25seSkge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5pZ25vcmVSZWFkb25seTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0eXBlb2YgX2lnbm9yZVJlYWRvbmx5ICE9PSAnYm9vbGVhbicpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdpZ25vcmVSZWFkb25seSAoKSBleHBlY3RzIGEgYm9vbGVhbiBwYXJhbWV0ZXInKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuaWdub3JlUmVhZG9ubHkgPSBfaWdub3JlUmVhZG9ubHk7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLm9wdGlvbnMgPSBmdW5jdGlvbiBvcHRpb25zKG5ld09wdGlvbnMpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICQuZXh0ZW5kKHRydWUsIHt9LCB0aGlzLl9vcHRpb25zKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCEobmV3T3B0aW9ucyBpbnN0YW5jZW9mIE9iamVjdCkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdvcHRpb25zKCkgdGhpcy5vcHRpb25zIHBhcmFtZXRlciBzaG91bGQgYmUgYW4gb2JqZWN0Jyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAkLmV4dGVuZCh0cnVlLCB0aGlzLl9vcHRpb25zLCBuZXdPcHRpb25zKTtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcztcbiAgICAgICAgICAgICQuZWFjaCh0aGlzLl9vcHRpb25zLCBmdW5jdGlvbiAoa2V5LCB2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmIChzZWxmW2tleV0gIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICBzZWxmW2tleV0odmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5kYXRlID0gZnVuY3Rpb24gZGF0ZShuZXdEYXRlLCBpbmRleCkge1xuICAgICAgICAgICAgaW5kZXggPSBpbmRleCB8fCAwO1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy51bnNldCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMuYWxsb3dNdWx0aWRhdGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2RhdGVzLmpvaW4odGhpcy5fb3B0aW9ucy5tdWx0aWRhdGVTZXBhcmF0b3IpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9kYXRlc1tpbmRleF0uY2xvbmUoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChuZXdEYXRlICE9PSBudWxsICYmIHR5cGVvZiBuZXdEYXRlICE9PSAnc3RyaW5nJyAmJiAhbW9tZW50LmlzTW9tZW50KG5ld0RhdGUpICYmICEobmV3RGF0ZSBpbnN0YW5jZW9mIERhdGUpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignZGF0ZSgpIHBhcmFtZXRlciBtdXN0IGJlIG9uZSBvZiBbbnVsbCwgc3RyaW5nLCBtb21lbnQgb3IgRGF0ZV0nKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5fc2V0VmFsdWUobmV3RGF0ZSA9PT0gbnVsbCA/IG51bGwgOiB0aGlzLl9wYXJzZUlucHV0RGF0ZShuZXdEYXRlKSwgaW5kZXgpO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5mb3JtYXQgPSBmdW5jdGlvbiBmb3JtYXQobmV3Rm9ybWF0KSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLmZvcm1hdDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBuZXdGb3JtYXQgIT09ICdzdHJpbmcnICYmICh0eXBlb2YgbmV3Rm9ybWF0ICE9PSAnYm9vbGVhbicgfHwgbmV3Rm9ybWF0ICE9PSBmYWxzZSkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdmb3JtYXQoKSBleHBlY3RzIGEgc3RyaW5nIG9yIGJvb2xlYW46ZmFsc2UgcGFyYW1ldGVyICcgKyBuZXdGb3JtYXQpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLmZvcm1hdCA9IG5ld0Zvcm1hdDtcbiAgICAgICAgICAgIGlmICh0aGlzLmFjdHVhbEZvcm1hdCkge1xuICAgICAgICAgICAgICAgIHRoaXMuX2luaXRGb3JtYXR0aW5nKCk7IC8vIHJlaW5pdGlhbGl6ZSBmb3JtYXR0aW5nXG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLnRpbWVab25lID0gZnVuY3Rpb24gdGltZVpvbmUobmV3Wm9uZSkge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy50aW1lWm9uZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBuZXdab25lICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ25ld1pvbmUoKSBleHBlY3RzIGEgc3RyaW5nIHBhcmFtZXRlcicpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLnRpbWVab25lID0gbmV3Wm9uZTtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuZGF5Vmlld0hlYWRlckZvcm1hdCA9IGZ1bmN0aW9uIGRheVZpZXdIZWFkZXJGb3JtYXQobmV3Rm9ybWF0KSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLmRheVZpZXdIZWFkZXJGb3JtYXQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgbmV3Rm9ybWF0ICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2RheVZpZXdIZWFkZXJGb3JtYXQoKSBleHBlY3RzIGEgc3RyaW5nIHBhcmFtZXRlcicpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLmRheVZpZXdIZWFkZXJGb3JtYXQgPSBuZXdGb3JtYXQ7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLmV4dHJhRm9ybWF0cyA9IGZ1bmN0aW9uIGV4dHJhRm9ybWF0cyhmb3JtYXRzKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLmV4dHJhRm9ybWF0cztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGZvcm1hdHMgIT09IGZhbHNlICYmICEoZm9ybWF0cyBpbnN0YW5jZW9mIEFycmF5KSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2V4dHJhRm9ybWF0cygpIGV4cGVjdHMgYW4gYXJyYXkgb3IgZmFsc2UgcGFyYW1ldGVyJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuZXh0cmFGb3JtYXRzID0gZm9ybWF0cztcbiAgICAgICAgICAgIGlmICh0aGlzLnBhcnNlRm9ybWF0cykge1xuICAgICAgICAgICAgICAgIHRoaXMuX2luaXRGb3JtYXR0aW5nKCk7IC8vIHJlaW5pdCBmb3JtYXR0aW5nXG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLmRpc2FibGVkRGF0ZXMgPSBmdW5jdGlvbiBkaXNhYmxlZERhdGVzKGRhdGVzKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLmRpc2FibGVkRGF0ZXMgPyAkLmV4dGVuZCh7fSwgdGhpcy5fb3B0aW9ucy5kaXNhYmxlZERhdGVzKSA6IHRoaXMuX29wdGlvbnMuZGlzYWJsZWREYXRlcztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCFkYXRlcykge1xuICAgICAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuZGlzYWJsZWREYXRlcyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHRoaXMuX3VwZGF0ZSgpO1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCEoZGF0ZXMgaW5zdGFuY2VvZiBBcnJheSkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdkaXNhYmxlZERhdGVzKCkgZXhwZWN0cyBhbiBhcnJheSBwYXJhbWV0ZXInKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuZGlzYWJsZWREYXRlcyA9IHRoaXMuX2luZGV4R2l2ZW5EYXRlcyhkYXRlcyk7XG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLmVuYWJsZWREYXRlcyA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy5fdXBkYXRlKCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLmVuYWJsZWREYXRlcyA9IGZ1bmN0aW9uIGVuYWJsZWREYXRlcyhkYXRlcykge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5lbmFibGVkRGF0ZXMgPyAkLmV4dGVuZCh7fSwgdGhpcy5fb3B0aW9ucy5lbmFibGVkRGF0ZXMpIDogdGhpcy5fb3B0aW9ucy5lbmFibGVkRGF0ZXM7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICghZGF0ZXMpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9vcHRpb25zLmVuYWJsZWREYXRlcyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHRoaXMuX3VwZGF0ZSgpO1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCEoZGF0ZXMgaW5zdGFuY2VvZiBBcnJheSkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdlbmFibGVkRGF0ZXMoKSBleHBlY3RzIGFuIGFycmF5IHBhcmFtZXRlcicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5lbmFibGVkRGF0ZXMgPSB0aGlzLl9pbmRleEdpdmVuRGF0ZXMoZGF0ZXMpO1xuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5kaXNhYmxlZERhdGVzID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLl91cGRhdGUoKTtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuZGF5c09mV2Vla0Rpc2FibGVkID0gZnVuY3Rpb24gZGF5c09mV2Vla0Rpc2FibGVkKF9kYXlzT2ZXZWVrRGlzYWJsZWQpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMuZGF5c09mV2Vla0Rpc2FibGVkLnNwbGljZSgwKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBfZGF5c09mV2Vla0Rpc2FibGVkID09PSAnYm9vbGVhbicgJiYgIV9kYXlzT2ZXZWVrRGlzYWJsZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9vcHRpb25zLmRheXNPZldlZWtEaXNhYmxlZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHRoaXMuX3VwZGF0ZSgpO1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoIShfZGF5c09mV2Vla0Rpc2FibGVkIGluc3RhbmNlb2YgQXJyYXkpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignZGF5c09mV2Vla0Rpc2FibGVkKCkgZXhwZWN0cyBhbiBhcnJheSBwYXJhbWV0ZXInKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuZGF5c09mV2Vla0Rpc2FibGVkID0gX2RheXNPZldlZWtEaXNhYmxlZC5yZWR1Y2UoZnVuY3Rpb24gKHByZXZpb3VzVmFsdWUsIGN1cnJlbnRWYWx1ZSkge1xuICAgICAgICAgICAgICAgIGN1cnJlbnRWYWx1ZSA9IHBhcnNlSW50KGN1cnJlbnRWYWx1ZSwgMTApO1xuICAgICAgICAgICAgICAgIGlmIChjdXJyZW50VmFsdWUgPiA2IHx8IGN1cnJlbnRWYWx1ZSA8IDAgfHwgaXNOYU4oY3VycmVudFZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcHJldmlvdXNWYWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHByZXZpb3VzVmFsdWUuaW5kZXhPZihjdXJyZW50VmFsdWUpID09PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICBwcmV2aW91c1ZhbHVlLnB1c2goY3VycmVudFZhbHVlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHByZXZpb3VzVmFsdWU7XG4gICAgICAgICAgICB9LCBbXSkuc29ydCgpO1xuICAgICAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMudXNlQ3VycmVudCAmJiAhdGhpcy5fb3B0aW9ucy5rZWVwSW52YWxpZCkge1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5fZGF0ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHRyaWVzID0gMDtcbiAgICAgICAgICAgICAgICAgICAgd2hpbGUgKCF0aGlzLl9pc1ZhbGlkKHRoaXMuX2RhdGVzW2ldLCAnZCcpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9kYXRlc1tpXS5hZGQoMSwgJ2QnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0cmllcyA9PT0gMzEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyAnVHJpZWQgMzEgdGltZXMgdG8gZmluZCBhIHZhbGlkIGRhdGUnO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgdHJpZXMrKztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB0aGlzLl9zZXRWYWx1ZSh0aGlzLl9kYXRlc1tpXSwgaSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fdXBkYXRlKCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLm1heERhdGUgPSBmdW5jdGlvbiBtYXhEYXRlKF9tYXhEYXRlKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLm1heERhdGUgPyB0aGlzLl9vcHRpb25zLm1heERhdGUuY2xvbmUoKSA6IHRoaXMuX29wdGlvbnMubWF4RGF0ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBfbWF4RGF0ZSA9PT0gJ2Jvb2xlYW4nICYmIF9tYXhEYXRlID09PSBmYWxzZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuX29wdGlvbnMubWF4RGF0ZSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHRoaXMuX3VwZGF0ZSgpO1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodHlwZW9mIF9tYXhEYXRlID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICAgIGlmIChfbWF4RGF0ZSA9PT0gJ25vdycgfHwgX21heERhdGUgPT09ICdtb21lbnQnKSB7XG4gICAgICAgICAgICAgICAgICAgIF9tYXhEYXRlID0gdGhpcy5nZXRNb21lbnQoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHZhciBwYXJzZWREYXRlID0gdGhpcy5fcGFyc2VJbnB1dERhdGUoX21heERhdGUpO1xuXG4gICAgICAgICAgICBpZiAoIXBhcnNlZERhdGUuaXNWYWxpZCgpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignbWF4RGF0ZSgpIENvdWxkIG5vdCBwYXJzZSBkYXRlIHBhcmFtZXRlcjogJyArIF9tYXhEYXRlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLl9vcHRpb25zLm1pbkRhdGUgJiYgcGFyc2VkRGF0ZS5pc0JlZm9yZSh0aGlzLl9vcHRpb25zLm1pbkRhdGUpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignbWF4RGF0ZSgpIGRhdGUgcGFyYW1ldGVyIGlzIGJlZm9yZSB0aGlzLm9wdGlvbnMubWluRGF0ZTogJyArIHBhcnNlZERhdGUuZm9ybWF0KHRoaXMuYWN0dWFsRm9ybWF0KSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLm1heERhdGUgPSBwYXJzZWREYXRlO1xuICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLl9kYXRlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLl9vcHRpb25zLnVzZUN1cnJlbnQgJiYgIXRoaXMuX29wdGlvbnMua2VlcEludmFsaWQgJiYgdGhpcy5fZGF0ZXNbaV0uaXNBZnRlcihfbWF4RGF0ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fc2V0VmFsdWUodGhpcy5fb3B0aW9ucy5tYXhEYXRlLCBpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5fdmlld0RhdGUuaXNBZnRlcihwYXJzZWREYXRlKSkge1xuICAgICAgICAgICAgICAgIHRoaXMuX3ZpZXdEYXRlID0gcGFyc2VkRGF0ZS5jbG9uZSgpLnN1YnRyYWN0KHRoaXMuX29wdGlvbnMuc3RlcHBpbmcsICdtJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl91cGRhdGUoKTtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUubWluRGF0ZSA9IGZ1bmN0aW9uIG1pbkRhdGUoX21pbkRhdGUpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMubWluRGF0ZSA/IHRoaXMuX29wdGlvbnMubWluRGF0ZS5jbG9uZSgpIDogdGhpcy5fb3B0aW9ucy5taW5EYXRlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodHlwZW9mIF9taW5EYXRlID09PSAnYm9vbGVhbicgJiYgX21pbkRhdGUgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5taW5EYXRlID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdGhpcy5fdXBkYXRlKCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgX21pbkRhdGUgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgaWYgKF9taW5EYXRlID09PSAnbm93JyB8fCBfbWluRGF0ZSA9PT0gJ21vbWVudCcpIHtcbiAgICAgICAgICAgICAgICAgICAgX21pbkRhdGUgPSB0aGlzLmdldE1vbWVudCgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdmFyIHBhcnNlZERhdGUgPSB0aGlzLl9wYXJzZUlucHV0RGF0ZShfbWluRGF0ZSk7XG5cbiAgICAgICAgICAgIGlmICghcGFyc2VkRGF0ZS5pc1ZhbGlkKCkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdtaW5EYXRlKCkgQ291bGQgbm90IHBhcnNlIGRhdGUgcGFyYW1ldGVyOiAnICsgX21pbkRhdGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMubWF4RGF0ZSAmJiBwYXJzZWREYXRlLmlzQWZ0ZXIodGhpcy5fb3B0aW9ucy5tYXhEYXRlKSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ21pbkRhdGUoKSBkYXRlIHBhcmFtZXRlciBpcyBhZnRlciB0aGlzLm9wdGlvbnMubWF4RGF0ZTogJyArIHBhcnNlZERhdGUuZm9ybWF0KHRoaXMuYWN0dWFsRm9ybWF0KSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLm1pbkRhdGUgPSBwYXJzZWREYXRlO1xuICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLl9kYXRlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLl9vcHRpb25zLnVzZUN1cnJlbnQgJiYgIXRoaXMuX29wdGlvbnMua2VlcEludmFsaWQgJiYgdGhpcy5fZGF0ZXNbaV0uaXNCZWZvcmUoX21pbkRhdGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX3NldFZhbHVlKHRoaXMuX29wdGlvbnMubWluRGF0ZSwgaSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuX3ZpZXdEYXRlLmlzQmVmb3JlKHBhcnNlZERhdGUpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fdmlld0RhdGUgPSBwYXJzZWREYXRlLmNsb25lKCkuYWRkKHRoaXMuX29wdGlvbnMuc3RlcHBpbmcsICdtJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl91cGRhdGUoKTtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuZGVmYXVsdERhdGUgPSBmdW5jdGlvbiBkZWZhdWx0RGF0ZShfZGVmYXVsdERhdGUpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMuZGVmYXVsdERhdGUgPyB0aGlzLl9vcHRpb25zLmRlZmF1bHREYXRlLmNsb25lKCkgOiB0aGlzLl9vcHRpb25zLmRlZmF1bHREYXRlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFfZGVmYXVsdERhdGUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9vcHRpb25zLmRlZmF1bHREYXRlID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgX2RlZmF1bHREYXRlID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICAgIGlmIChfZGVmYXVsdERhdGUgPT09ICdub3cnIHx8IF9kZWZhdWx0RGF0ZSA9PT0gJ21vbWVudCcpIHtcbiAgICAgICAgICAgICAgICAgICAgX2RlZmF1bHREYXRlID0gdGhpcy5nZXRNb21lbnQoKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBfZGVmYXVsdERhdGUgPSB0aGlzLmdldE1vbWVudChfZGVmYXVsdERhdGUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdmFyIHBhcnNlZERhdGUgPSB0aGlzLl9wYXJzZUlucHV0RGF0ZShfZGVmYXVsdERhdGUpO1xuICAgICAgICAgICAgaWYgKCFwYXJzZWREYXRlLmlzVmFsaWQoKSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2RlZmF1bHREYXRlKCkgQ291bGQgbm90IHBhcnNlIGRhdGUgcGFyYW1ldGVyOiAnICsgX2RlZmF1bHREYXRlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghdGhpcy5faXNWYWxpZChwYXJzZWREYXRlKSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2RlZmF1bHREYXRlKCkgZGF0ZSBwYXNzZWQgaXMgaW52YWxpZCBhY2NvcmRpbmcgdG8gY29tcG9uZW50IHNldHVwIHZhbGlkYXRpb25zJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuZGVmYXVsdERhdGUgPSBwYXJzZWREYXRlO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy5kZWZhdWx0RGF0ZSAmJiB0aGlzLl9vcHRpb25zLmlubGluZSB8fCB0aGlzLmlucHV0ICE9PSB1bmRlZmluZWQgJiYgdGhpcy5pbnB1dC52YWwoKS50cmltKCkgPT09ICcnKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fc2V0VmFsdWUodGhpcy5fb3B0aW9ucy5kZWZhdWx0RGF0ZSwgMCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLmxvY2FsZSA9IGZ1bmN0aW9uIGxvY2FsZShfbG9jYWxlKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLmxvY2FsZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCFtb21lbnQubG9jYWxlRGF0YShfbG9jYWxlKSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2xvY2FsZSgpIGxvY2FsZSAnICsgX2xvY2FsZSArICcgaXMgbm90IGxvYWRlZCBmcm9tIG1vbWVudCBsb2NhbGVzIScpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuX2RhdGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fZGF0ZXNbaV0ubG9jYWxlKHRoaXMuX29wdGlvbnMubG9jYWxlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX3ZpZXdEYXRlLmxvY2FsZSh0aGlzLl9vcHRpb25zLmxvY2FsZSk7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLmFjdHVhbEZvcm1hdCkge1xuICAgICAgICAgICAgICAgIHRoaXMuX2luaXRGb3JtYXR0aW5nKCk7IC8vIHJlaW5pdGlhbGl6ZSBmb3JtYXR0aW5nXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy53aWRnZXQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmhpZGUoKTtcbiAgICAgICAgICAgICAgICB0aGlzLnNob3coKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuc3RlcHBpbmcgPSBmdW5jdGlvbiBzdGVwcGluZyhfc3RlcHBpbmcpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMuc3RlcHBpbmc7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIF9zdGVwcGluZyA9IHBhcnNlSW50KF9zdGVwcGluZywgMTApO1xuICAgICAgICAgICAgaWYgKGlzTmFOKF9zdGVwcGluZykgfHwgX3N0ZXBwaW5nIDwgMSkge1xuICAgICAgICAgICAgICAgIF9zdGVwcGluZyA9IDE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLnN0ZXBwaW5nID0gX3N0ZXBwaW5nO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS51c2VDdXJyZW50ID0gZnVuY3Rpb24gdXNlQ3VycmVudChfdXNlQ3VycmVudCkge1xuICAgICAgICAgICAgdmFyIHVzZUN1cnJlbnRPcHRpb25zID0gWyd5ZWFyJywgJ21vbnRoJywgJ2RheScsICdob3VyJywgJ21pbnV0ZSddO1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy51c2VDdXJyZW50O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodHlwZW9mIF91c2VDdXJyZW50ICE9PSAnYm9vbGVhbicgJiYgdHlwZW9mIF91c2VDdXJyZW50ICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ3VzZUN1cnJlbnQoKSBleHBlY3RzIGEgYm9vbGVhbiBvciBzdHJpbmcgcGFyYW1ldGVyJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodHlwZW9mIF91c2VDdXJyZW50ID09PSAnc3RyaW5nJyAmJiB1c2VDdXJyZW50T3B0aW9ucy5pbmRleE9mKF91c2VDdXJyZW50LnRvTG93ZXJDYXNlKCkpID09PSAtMSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ3VzZUN1cnJlbnQoKSBleHBlY3RzIGEgc3RyaW5nIHBhcmFtZXRlciBvZiAnICsgdXNlQ3VycmVudE9wdGlvbnMuam9pbignLCAnKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLnVzZUN1cnJlbnQgPSBfdXNlQ3VycmVudDtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuY29sbGFwc2UgPSBmdW5jdGlvbiBjb2xsYXBzZShfY29sbGFwc2UpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMuY29sbGFwc2U7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgX2NvbGxhcHNlICE9PSAnYm9vbGVhbicpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdjb2xsYXBzZSgpIGV4cGVjdHMgYSBib29sZWFuIHBhcmFtZXRlcicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMuY29sbGFwc2UgPT09IF9jb2xsYXBzZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5jb2xsYXBzZSA9IF9jb2xsYXBzZTtcbiAgICAgICAgICAgIGlmICh0aGlzLndpZGdldCkge1xuICAgICAgICAgICAgICAgIHRoaXMuaGlkZSgpO1xuICAgICAgICAgICAgICAgIHRoaXMuc2hvdygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5pY29ucyA9IGZ1bmN0aW9uIGljb25zKF9pY29ucykge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJC5leHRlbmQoe30sIHRoaXMuX29wdGlvbnMuaWNvbnMpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoIShfaWNvbnMgaW5zdGFuY2VvZiBPYmplY3QpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignaWNvbnMoKSBleHBlY3RzIHBhcmFtZXRlciB0byBiZSBhbiBPYmplY3QnKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgJC5leHRlbmQodGhpcy5fb3B0aW9ucy5pY29ucywgX2ljb25zKTtcblxuICAgICAgICAgICAgaWYgKHRoaXMud2lkZ2V0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5oaWRlKCk7XG4gICAgICAgICAgICAgICAgdGhpcy5zaG93KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLnRvb2x0aXBzID0gZnVuY3Rpb24gdG9vbHRpcHMoX3Rvb2x0aXBzKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAkLmV4dGVuZCh7fSwgdGhpcy5fb3B0aW9ucy50b29sdGlwcyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICghKF90b29sdGlwcyBpbnN0YW5jZW9mIE9iamVjdCkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCd0b29sdGlwcygpIGV4cGVjdHMgcGFyYW1ldGVyIHRvIGJlIGFuIE9iamVjdCcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgJC5leHRlbmQodGhpcy5fb3B0aW9ucy50b29sdGlwcywgX3Rvb2x0aXBzKTtcbiAgICAgICAgICAgIGlmICh0aGlzLndpZGdldCkge1xuICAgICAgICAgICAgICAgIHRoaXMuaGlkZSgpO1xuICAgICAgICAgICAgICAgIHRoaXMuc2hvdygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS51c2VTdHJpY3QgPSBmdW5jdGlvbiB1c2VTdHJpY3QoX3VzZVN0cmljdCkge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy51c2VTdHJpY3Q7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgX3VzZVN0cmljdCAhPT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigndXNlU3RyaWN0KCkgZXhwZWN0cyBhIGJvb2xlYW4gcGFyYW1ldGVyJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLnVzZVN0cmljdCA9IF91c2VTdHJpY3Q7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLnNpZGVCeVNpZGUgPSBmdW5jdGlvbiBzaWRlQnlTaWRlKF9zaWRlQnlTaWRlKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLnNpZGVCeVNpZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgX3NpZGVCeVNpZGUgIT09ICdib29sZWFuJykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ3NpZGVCeVNpZGUoKSBleHBlY3RzIGEgYm9vbGVhbiBwYXJhbWV0ZXInKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuc2lkZUJ5U2lkZSA9IF9zaWRlQnlTaWRlO1xuICAgICAgICAgICAgaWYgKHRoaXMud2lkZ2V0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5oaWRlKCk7XG4gICAgICAgICAgICAgICAgdGhpcy5zaG93KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLnZpZXdNb2RlID0gZnVuY3Rpb24gdmlld01vZGUoX3ZpZXdNb2RlKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLnZpZXdNb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodHlwZW9mIF92aWV3TW9kZSAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCd2aWV3TW9kZSgpIGV4cGVjdHMgYSBzdHJpbmcgcGFyYW1ldGVyJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChEYXRlVGltZVBpY2tlci5WaWV3TW9kZXMuaW5kZXhPZihfdmlld01vZGUpID09PSAtMSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ3ZpZXdNb2RlKCkgcGFyYW1ldGVyIG11c3QgYmUgb25lIG9mICgnICsgRGF0ZVRpbWVQaWNrZXIuVmlld01vZGVzLmpvaW4oJywgJykgKyAnKSB2YWx1ZScpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLnZpZXdNb2RlID0gX3ZpZXdNb2RlO1xuICAgICAgICAgICAgdGhpcy5jdXJyZW50Vmlld01vZGUgPSBNYXRoLm1heChEYXRlVGltZVBpY2tlci5WaWV3TW9kZXMuaW5kZXhPZihfdmlld01vZGUpIC0gMSwgRGF0ZVRpbWVQaWNrZXIuTWluVmlld01vZGVOdW1iZXIpO1xuXG4gICAgICAgICAgICB0aGlzLl9zaG93TW9kZSgpO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5jYWxlbmRhcldlZWtzID0gZnVuY3Rpb24gY2FsZW5kYXJXZWVrcyhfY2FsZW5kYXJXZWVrcykge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5jYWxlbmRhcldlZWtzO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodHlwZW9mIF9jYWxlbmRhcldlZWtzICE9PSAnYm9vbGVhbicpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdjYWxlbmRhcldlZWtzKCkgZXhwZWN0cyBwYXJhbWV0ZXIgdG8gYmUgYSBib29sZWFuIHZhbHVlJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuY2FsZW5kYXJXZWVrcyA9IF9jYWxlbmRhcldlZWtzO1xuICAgICAgICAgICAgdGhpcy5fdXBkYXRlKCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLmJ1dHRvbnMgPSBmdW5jdGlvbiBidXR0b25zKF9idXR0b25zKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAkLmV4dGVuZCh7fSwgdGhpcy5fb3B0aW9ucy5idXR0b25zKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCEoX2J1dHRvbnMgaW5zdGFuY2VvZiBPYmplY3QpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignYnV0dG9ucygpIGV4cGVjdHMgcGFyYW1ldGVyIHRvIGJlIGFuIE9iamVjdCcpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAkLmV4dGVuZCh0aGlzLl9vcHRpb25zLmJ1dHRvbnMsIF9idXR0b25zKTtcblxuICAgICAgICAgICAgaWYgKHR5cGVvZiB0aGlzLl9vcHRpb25zLmJ1dHRvbnMuc2hvd1RvZGF5ICE9PSAnYm9vbGVhbicpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdidXR0b25zLnNob3dUb2RheSBleHBlY3RzIGEgYm9vbGVhbiBwYXJhbWV0ZXInKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0eXBlb2YgdGhpcy5fb3B0aW9ucy5idXR0b25zLnNob3dDbGVhciAhPT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignYnV0dG9ucy5zaG93Q2xlYXIgZXhwZWN0cyBhIGJvb2xlYW4gcGFyYW1ldGVyJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodHlwZW9mIHRoaXMuX29wdGlvbnMuYnV0dG9ucy5zaG93Q2xvc2UgIT09ICdib29sZWFuJykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2J1dHRvbnMuc2hvd0Nsb3NlIGV4cGVjdHMgYSBib29sZWFuIHBhcmFtZXRlcicpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodGhpcy53aWRnZXQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmhpZGUoKTtcbiAgICAgICAgICAgICAgICB0aGlzLnNob3coKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUua2VlcE9wZW4gPSBmdW5jdGlvbiBrZWVwT3Blbihfa2VlcE9wZW4pIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMua2VlcE9wZW47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgX2tlZXBPcGVuICE9PSAnYm9vbGVhbicpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdrZWVwT3BlbigpIGV4cGVjdHMgYSBib29sZWFuIHBhcmFtZXRlcicpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLmtlZXBPcGVuID0gX2tlZXBPcGVuO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5mb2N1c09uU2hvdyA9IGZ1bmN0aW9uIGZvY3VzT25TaG93KF9mb2N1c09uU2hvdykge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5mb2N1c09uU2hvdztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBfZm9jdXNPblNob3cgIT09ICdib29sZWFuJykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2ZvY3VzT25TaG93KCkgZXhwZWN0cyBhIGJvb2xlYW4gcGFyYW1ldGVyJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuZm9jdXNPblNob3cgPSBfZm9jdXNPblNob3c7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLmlubGluZSA9IGZ1bmN0aW9uIGlubGluZShfaW5saW5lKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLmlubGluZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBfaW5saW5lICE9PSAnYm9vbGVhbicpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdpbmxpbmUoKSBleHBlY3RzIGEgYm9vbGVhbiBwYXJhbWV0ZXInKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5pbmxpbmUgPSBfaW5saW5lO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5jbGVhciA9IGZ1bmN0aW9uIGNsZWFyKCkge1xuICAgICAgICAgICAgdGhpcy5fc2V0VmFsdWUobnVsbCk7IC8vdG9kb1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5rZXlCaW5kcyA9IGZ1bmN0aW9uIGtleUJpbmRzKF9rZXlCaW5kcykge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5rZXlCaW5kcztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5rZXlCaW5kcyA9IF9rZXlCaW5kcztcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuZGVidWcgPSBmdW5jdGlvbiBkZWJ1ZyhfZGVidWcpIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgX2RlYnVnICE9PSAnYm9vbGVhbicpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdkZWJ1ZygpIGV4cGVjdHMgYSBib29sZWFuIHBhcmFtZXRlcicpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLmRlYnVnID0gX2RlYnVnO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5hbGxvd0lucHV0VG9nZ2xlID0gZnVuY3Rpb24gYWxsb3dJbnB1dFRvZ2dsZShfYWxsb3dJbnB1dFRvZ2dsZSkge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5hbGxvd0lucHV0VG9nZ2xlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodHlwZW9mIF9hbGxvd0lucHV0VG9nZ2xlICE9PSAnYm9vbGVhbicpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdhbGxvd0lucHV0VG9nZ2xlKCkgZXhwZWN0cyBhIGJvb2xlYW4gcGFyYW1ldGVyJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuYWxsb3dJbnB1dFRvZ2dsZSA9IF9hbGxvd0lucHV0VG9nZ2xlO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5rZWVwSW52YWxpZCA9IGZ1bmN0aW9uIGtlZXBJbnZhbGlkKF9rZWVwSW52YWxpZCkge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5rZWVwSW52YWxpZDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBfa2VlcEludmFsaWQgIT09ICdib29sZWFuJykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2tlZXBJbnZhbGlkKCkgZXhwZWN0cyBhIGJvb2xlYW4gcGFyYW1ldGVyJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLmtlZXBJbnZhbGlkID0gX2tlZXBJbnZhbGlkO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5kYXRlcGlja2VySW5wdXQgPSBmdW5jdGlvbiBkYXRlcGlja2VySW5wdXQoX2RhdGVwaWNrZXJJbnB1dCkge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5kYXRlcGlja2VySW5wdXQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgX2RhdGVwaWNrZXJJbnB1dCAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdkYXRlcGlja2VySW5wdXQoKSBleHBlY3RzIGEgc3RyaW5nIHBhcmFtZXRlcicpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLmRhdGVwaWNrZXJJbnB1dCA9IF9kYXRlcGlja2VySW5wdXQ7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLnBhcnNlSW5wdXREYXRlID0gZnVuY3Rpb24gcGFyc2VJbnB1dERhdGUoX3BhcnNlSW5wdXREYXRlMikge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5wYXJzZUlucHV0RGF0ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBfcGFyc2VJbnB1dERhdGUyICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigncGFyc2VJbnB1dERhdGUoKSBzaG91bGQgYmUgYXMgZnVuY3Rpb24nKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5wYXJzZUlucHV0RGF0ZSA9IF9wYXJzZUlucHV0RGF0ZTI7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLmRpc2FibGVkVGltZUludGVydmFscyA9IGZ1bmN0aW9uIGRpc2FibGVkVGltZUludGVydmFscyhfZGlzYWJsZWRUaW1lSW50ZXJ2YWxzKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLmRpc2FibGVkVGltZUludGVydmFscyA/ICQuZXh0ZW5kKHt9LCB0aGlzLl9vcHRpb25zLmRpc2FibGVkVGltZUludGVydmFscykgOiB0aGlzLl9vcHRpb25zLmRpc2FibGVkVGltZUludGVydmFscztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCFfZGlzYWJsZWRUaW1lSW50ZXJ2YWxzKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5kaXNhYmxlZFRpbWVJbnRlcnZhbHMgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB0aGlzLl91cGRhdGUoKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghKF9kaXNhYmxlZFRpbWVJbnRlcnZhbHMgaW5zdGFuY2VvZiBBcnJheSkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdkaXNhYmxlZFRpbWVJbnRlcnZhbHMoKSBleHBlY3RzIGFuIGFycmF5IHBhcmFtZXRlcicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5kaXNhYmxlZFRpbWVJbnRlcnZhbHMgPSBfZGlzYWJsZWRUaW1lSW50ZXJ2YWxzO1xuICAgICAgICAgICAgdGhpcy5fdXBkYXRlKCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLmRpc2FibGVkSG91cnMgPSBmdW5jdGlvbiBkaXNhYmxlZEhvdXJzKGhvdXJzKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLmRpc2FibGVkSG91cnMgPyAkLmV4dGVuZCh7fSwgdGhpcy5fb3B0aW9ucy5kaXNhYmxlZEhvdXJzKSA6IHRoaXMuX29wdGlvbnMuZGlzYWJsZWRIb3VycztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCFob3Vycykge1xuICAgICAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuZGlzYWJsZWRIb3VycyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHRoaXMuX3VwZGF0ZSgpO1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCEoaG91cnMgaW5zdGFuY2VvZiBBcnJheSkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdkaXNhYmxlZEhvdXJzKCkgZXhwZWN0cyBhbiBhcnJheSBwYXJhbWV0ZXInKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuZGlzYWJsZWRIb3VycyA9IHRoaXMuX2luZGV4R2l2ZW5Ib3Vycyhob3Vycyk7XG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLmVuYWJsZWRIb3VycyA9IGZhbHNlO1xuICAgICAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMudXNlQ3VycmVudCAmJiAhdGhpcy5fb3B0aW9ucy5rZWVwSW52YWxpZCkge1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5fZGF0ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHRyaWVzID0gMDtcbiAgICAgICAgICAgICAgICAgICAgd2hpbGUgKCF0aGlzLl9pc1ZhbGlkKHRoaXMuX2RhdGVzW2ldLCAnaCcpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9kYXRlc1tpXS5hZGQoMSwgJ2gnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0cmllcyA9PT0gMjQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyAnVHJpZWQgMjQgdGltZXMgdG8gZmluZCBhIHZhbGlkIGRhdGUnO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgdHJpZXMrKztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB0aGlzLl9zZXRWYWx1ZSh0aGlzLl9kYXRlc1tpXSwgaSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fdXBkYXRlKCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLmVuYWJsZWRIb3VycyA9IGZ1bmN0aW9uIGVuYWJsZWRIb3Vycyhob3Vycykge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5lbmFibGVkSG91cnMgPyAkLmV4dGVuZCh7fSwgdGhpcy5fb3B0aW9ucy5lbmFibGVkSG91cnMpIDogdGhpcy5fb3B0aW9ucy5lbmFibGVkSG91cnM7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICghaG91cnMpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9vcHRpb25zLmVuYWJsZWRIb3VycyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHRoaXMuX3VwZGF0ZSgpO1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCEoaG91cnMgaW5zdGFuY2VvZiBBcnJheSkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdlbmFibGVkSG91cnMoKSBleHBlY3RzIGFuIGFycmF5IHBhcmFtZXRlcicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5lbmFibGVkSG91cnMgPSB0aGlzLl9pbmRleEdpdmVuSG91cnMoaG91cnMpO1xuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5kaXNhYmxlZEhvdXJzID0gZmFsc2U7XG4gICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy51c2VDdXJyZW50ICYmICF0aGlzLl9vcHRpb25zLmtlZXBJbnZhbGlkKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLl9kYXRlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgdHJpZXMgPSAwO1xuICAgICAgICAgICAgICAgICAgICB3aGlsZSAoIXRoaXMuX2lzVmFsaWQodGhpcy5fZGF0ZXNbaV0sICdoJykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2RhdGVzW2ldLmFkZCgxLCAnaCcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRyaWVzID09PSAyNCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93ICdUcmllZCAyNCB0aW1lcyB0byBmaW5kIGEgdmFsaWQgZGF0ZSc7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB0cmllcysrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX3NldFZhbHVlKHRoaXMuX2RhdGVzW2ldLCBpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl91cGRhdGUoKTtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUudmlld0RhdGUgPSBmdW5jdGlvbiB2aWV3RGF0ZShuZXdEYXRlKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl92aWV3RGF0ZS5jbG9uZSgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoIW5ld0RhdGUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl92aWV3RGF0ZSA9ICh0aGlzLl9kYXRlc1swXSB8fCB0aGlzLmdldE1vbWVudCgpKS5jbG9uZSgpO1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodHlwZW9mIG5ld0RhdGUgIT09ICdzdHJpbmcnICYmICFtb21lbnQuaXNNb21lbnQobmV3RGF0ZSkgJiYgIShuZXdEYXRlIGluc3RhbmNlb2YgRGF0ZSkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCd2aWV3RGF0ZSgpIHBhcmFtZXRlciBtdXN0IGJlIG9uZSBvZiBbc3RyaW5nLCBtb21lbnQgb3IgRGF0ZV0nKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5fdmlld0RhdGUgPSB0aGlzLl9wYXJzZUlucHV0RGF0ZShuZXdEYXRlKTtcbiAgICAgICAgICAgIHRoaXMuX3ZpZXdVcGRhdGUoKTtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuYWxsb3dNdWx0aWRhdGUgPSBmdW5jdGlvbiBhbGxvd011bHRpZGF0ZShfYWxsb3dNdWx0aWRhdGUpIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgX2FsbG93TXVsdGlkYXRlICE9PSAnYm9vbGVhbicpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdhbGxvd011bHRpZGF0ZSgpIGV4cGVjdHMgYSBib29sZWFuIHBhcmFtZXRlcicpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLmFsbG93TXVsdGlkYXRlID0gX2FsbG93TXVsdGlkYXRlO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5tdWx0aWRhdGVTZXBhcmF0b3IgPSBmdW5jdGlvbiBtdWx0aWRhdGVTZXBhcmF0b3IoX211bHRpZGF0ZVNlcGFyYXRvcikge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5tdWx0aWRhdGVTZXBhcmF0b3I7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgX211bHRpZGF0ZVNlcGFyYXRvciAhPT0gJ3N0cmluZycgfHwgX211bHRpZGF0ZVNlcGFyYXRvci5sZW5ndGggPiAxKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignbXVsdGlkYXRlU2VwYXJhdG9yIGV4cGVjdHMgYSBzaW5nbGUgY2hhcmFjdGVyIHN0cmluZyBwYXJhbWV0ZXInKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5tdWx0aWRhdGVTZXBhcmF0b3IgPSBfbXVsdGlkYXRlU2VwYXJhdG9yO1xuICAgICAgICB9O1xuXG4gICAgICAgIF9jcmVhdGVDbGFzcyhEYXRlVGltZVBpY2tlciwgbnVsbCwgW3tcbiAgICAgICAgICAgIGtleTogJ05BTUUnLFxuICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIE5BTUU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogQHJldHVybiB7c3RyaW5nfVxuICAgICAgICAgICAgICovXG5cbiAgICAgICAgfSwge1xuICAgICAgICAgICAga2V5OiAnVkVSU0lPTicsXG4gICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gVkVSU0lPTjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBAcmV0dXJuIHtzdHJpbmd9XG4gICAgICAgICAgICAgKi9cblxuICAgICAgICB9LCB7XG4gICAgICAgICAgICBrZXk6ICdEQVRBX0tFWScsXG4gICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gREFUQV9LRVk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogQHJldHVybiB7c3RyaW5nfVxuICAgICAgICAgICAgICovXG5cbiAgICAgICAgfSwge1xuICAgICAgICAgICAga2V5OiAnRVZFTlRfS0VZJyxcbiAgICAgICAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBFVkVOVF9LRVk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogQHJldHVybiB7c3RyaW5nfVxuICAgICAgICAgICAgICovXG5cbiAgICAgICAgfSwge1xuICAgICAgICAgICAga2V5OiAnREFUQV9BUElfS0VZJyxcbiAgICAgICAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBEQVRBX0FQSV9LRVk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHtcbiAgICAgICAgICAgIGtleTogJ0RhdGVQaWNrZXJNb2RlcycsXG4gICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gRGF0ZVBpY2tlck1vZGVzO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7XG4gICAgICAgICAgICBrZXk6ICdWaWV3TW9kZXMnLFxuICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFZpZXdNb2RlcztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBAcmV0dXJuIHtudW1iZXJ9XG4gICAgICAgICAgICAgKi9cblxuICAgICAgICB9LCB7XG4gICAgICAgICAgICBrZXk6ICdNaW5WaWV3TW9kZU51bWJlcicsXG4gICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gTWluVmlld01vZGVOdW1iZXI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHtcbiAgICAgICAgICAgIGtleTogJ0V2ZW50JyxcbiAgICAgICAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBFdmVudDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge1xuICAgICAgICAgICAga2V5OiAnU2VsZWN0b3InLFxuICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFNlbGVjdG9yO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7XG4gICAgICAgICAgICBrZXk6ICdEZWZhdWx0JyxcbiAgICAgICAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBEZWZhdWx0O1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHNldDogZnVuY3Rpb24gc2V0KHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgRGVmYXVsdCA9IHZhbHVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7XG4gICAgICAgICAgICBrZXk6ICdDbGFzc05hbWUnLFxuICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIENsYXNzTmFtZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfV0pO1xuXG4gICAgICAgIHJldHVybiBEYXRlVGltZVBpY2tlcjtcbiAgICB9KCk7XG5cbiAgICByZXR1cm4gRGF0ZVRpbWVQaWNrZXI7XG59KGpRdWVyeSwgbW9tZW50KTtcblxuLy9ub2luc3BlY3Rpb24gSlNVbnVzZWRHbG9iYWxTeW1ib2xzXG4vKiBnbG9iYWwgRGF0ZVRpbWVQaWNrZXIgKi9cbnZhciBUZW1wdXNEb21pbnVzQm9vdHN0cmFwNCA9IGZ1bmN0aW9uICgkKSB7XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby11bnVzZWQtdmFyc1xuICAgIC8vIFJlU2hhcnBlciBkaXNhYmxlIG9uY2UgSW5jb25zaXN0ZW50TmFtaW5nXG4gICAgdmFyIEpRVUVSWV9OT19DT05GTElDVCA9ICQuZm5bRGF0ZVRpbWVQaWNrZXIuTkFNRV0sXG4gICAgICAgIHZlcnRpY2FsTW9kZXMgPSBbJ3RvcCcsICdib3R0b20nLCAnYXV0byddLFxuICAgICAgICBob3Jpem9udGFsTW9kZXMgPSBbJ2xlZnQnLCAncmlnaHQnLCAnYXV0byddLFxuICAgICAgICB0b29sYmFyUGxhY2VtZW50cyA9IFsnZGVmYXVsdCcsICd0b3AnLCAnYm90dG9tJ10sXG4gICAgICAgIGdldFNlbGVjdG9yRnJvbUVsZW1lbnQgPSBmdW5jdGlvbiBnZXRTZWxlY3RvckZyb21FbGVtZW50KCRlbGVtZW50KSB7XG4gICAgICAgIHZhciBzZWxlY3RvciA9ICRlbGVtZW50LmRhdGEoJ3RhcmdldCcpLFxuICAgICAgICAgICAgJHNlbGVjdG9yID0gdm9pZCAwO1xuXG4gICAgICAgIGlmICghc2VsZWN0b3IpIHtcbiAgICAgICAgICAgIHNlbGVjdG9yID0gJGVsZW1lbnQuYXR0cignaHJlZicpIHx8ICcnO1xuICAgICAgICAgICAgc2VsZWN0b3IgPSAvXiNbYS16XS9pLnRlc3Qoc2VsZWN0b3IpID8gc2VsZWN0b3IgOiBudWxsO1xuICAgICAgICB9XG4gICAgICAgICRzZWxlY3RvciA9ICQoc2VsZWN0b3IpO1xuICAgICAgICBpZiAoJHNlbGVjdG9yLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgcmV0dXJuICRzZWxlY3RvcjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghJHNlbGVjdG9yLmRhdGEoRGF0ZVRpbWVQaWNrZXIuREFUQV9LRVkpKSB7XG4gICAgICAgICAgICAkLmV4dGVuZCh7fSwgJHNlbGVjdG9yLmRhdGEoKSwgJCh0aGlzKS5kYXRhKCkpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuICRzZWxlY3RvcjtcbiAgICB9O1xuXG4gICAgLy8gUmVTaGFycGVyIGRpc2FibGUgb25jZSBJbmNvbnNpc3RlbnROYW1pbmdcblxuICAgIHZhciBUZW1wdXNEb21pbnVzQm9vdHN0cmFwNCA9IGZ1bmN0aW9uIChfRGF0ZVRpbWVQaWNrZXIpIHtcbiAgICAgICAgX2luaGVyaXRzKFRlbXB1c0RvbWludXNCb290c3RyYXA0LCBfRGF0ZVRpbWVQaWNrZXIpO1xuXG4gICAgICAgIGZ1bmN0aW9uIFRlbXB1c0RvbWludXNCb290c3RyYXA0KGVsZW1lbnQsIG9wdGlvbnMpIHtcbiAgICAgICAgICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBUZW1wdXNEb21pbnVzQm9vdHN0cmFwNCk7XG5cbiAgICAgICAgICAgIHZhciBfdGhpcyA9IF9wb3NzaWJsZUNvbnN0cnVjdG9yUmV0dXJuKHRoaXMsIF9EYXRlVGltZVBpY2tlci5jYWxsKHRoaXMsIGVsZW1lbnQsIG9wdGlvbnMpKTtcblxuICAgICAgICAgICAgX3RoaXMuX2luaXQoKTtcbiAgICAgICAgICAgIHJldHVybiBfdGhpcztcbiAgICAgICAgfVxuXG4gICAgICAgIFRlbXB1c0RvbWludXNCb290c3RyYXA0LnByb3RvdHlwZS5faW5pdCA9IGZ1bmN0aW9uIF9pbml0KCkge1xuICAgICAgICAgICAgaWYgKHRoaXMuX2VsZW1lbnQuaGFzQ2xhc3MoJ2lucHV0LWdyb3VwJykpIHtcbiAgICAgICAgICAgICAgICB2YXIgZGF0ZXBpY2tlckJ1dHRvbiA9IHRoaXMuX2VsZW1lbnQuZmluZCgnLmRhdGVwaWNrZXJidXR0b24nKTtcbiAgICAgICAgICAgICAgICBpZiAoZGF0ZXBpY2tlckJ1dHRvbi5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5jb21wb25lbnQgPSB0aGlzLl9lbGVtZW50LmZpbmQoJ1tkYXRhLXRvZ2dsZT1cImRhdGV0aW1lcGlja2VyXCJdJyk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5jb21wb25lbnQgPSBkYXRlcGlja2VyQnV0dG9uO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICBUZW1wdXNEb21pbnVzQm9vdHN0cmFwNC5wcm90b3R5cGUuX2dldERhdGVQaWNrZXJUZW1wbGF0ZSA9IGZ1bmN0aW9uIF9nZXREYXRlUGlja2VyVGVtcGxhdGUoKSB7XG4gICAgICAgICAgICB2YXIgaGVhZFRlbXBsYXRlID0gJCgnPHRoZWFkPicpLmFwcGVuZCgkKCc8dHI+JykuYXBwZW5kKCQoJzx0aD4nKS5hZGRDbGFzcygncHJldicpLmF0dHIoJ2RhdGEtYWN0aW9uJywgJ3ByZXZpb3VzJykuYXBwZW5kKCQoJzxzcGFuPicpLmFkZENsYXNzKHRoaXMuX29wdGlvbnMuaWNvbnMucHJldmlvdXMpKSkuYXBwZW5kKCQoJzx0aD4nKS5hZGRDbGFzcygncGlja2VyLXN3aXRjaCcpLmF0dHIoJ2RhdGEtYWN0aW9uJywgJ3BpY2tlclN3aXRjaCcpLmF0dHIoJ2NvbHNwYW4nLCAnJyArICh0aGlzLl9vcHRpb25zLmNhbGVuZGFyV2Vla3MgPyAnNicgOiAnNScpKSkuYXBwZW5kKCQoJzx0aD4nKS5hZGRDbGFzcygnbmV4dCcpLmF0dHIoJ2RhdGEtYWN0aW9uJywgJ25leHQnKS5hcHBlbmQoJCgnPHNwYW4+JykuYWRkQ2xhc3ModGhpcy5fb3B0aW9ucy5pY29ucy5uZXh0KSkpKSxcbiAgICAgICAgICAgICAgICBjb250VGVtcGxhdGUgPSAkKCc8dGJvZHk+JykuYXBwZW5kKCQoJzx0cj4nKS5hcHBlbmQoJCgnPHRkPicpLmF0dHIoJ2NvbHNwYW4nLCAnJyArICh0aGlzLl9vcHRpb25zLmNhbGVuZGFyV2Vla3MgPyAnOCcgOiAnNycpKSkpO1xuXG4gICAgICAgICAgICByZXR1cm4gWyQoJzxkaXY+JykuYWRkQ2xhc3MoJ2RhdGVwaWNrZXItZGF5cycpLmFwcGVuZCgkKCc8dGFibGU+JykuYWRkQ2xhc3MoJ3RhYmxlIHRhYmxlLXNtJykuYXBwZW5kKGhlYWRUZW1wbGF0ZSkuYXBwZW5kKCQoJzx0Ym9keT4nKSkpLCAkKCc8ZGl2PicpLmFkZENsYXNzKCdkYXRlcGlja2VyLW1vbnRocycpLmFwcGVuZCgkKCc8dGFibGU+JykuYWRkQ2xhc3MoJ3RhYmxlLWNvbmRlbnNlZCcpLmFwcGVuZChoZWFkVGVtcGxhdGUuY2xvbmUoKSkuYXBwZW5kKGNvbnRUZW1wbGF0ZS5jbG9uZSgpKSksICQoJzxkaXY+JykuYWRkQ2xhc3MoJ2RhdGVwaWNrZXIteWVhcnMnKS5hcHBlbmQoJCgnPHRhYmxlPicpLmFkZENsYXNzKCd0YWJsZS1jb25kZW5zZWQnKS5hcHBlbmQoaGVhZFRlbXBsYXRlLmNsb25lKCkpLmFwcGVuZChjb250VGVtcGxhdGUuY2xvbmUoKSkpLCAkKCc8ZGl2PicpLmFkZENsYXNzKCdkYXRlcGlja2VyLWRlY2FkZXMnKS5hcHBlbmQoJCgnPHRhYmxlPicpLmFkZENsYXNzKCd0YWJsZS1jb25kZW5zZWQnKS5hcHBlbmQoaGVhZFRlbXBsYXRlLmNsb25lKCkpLmFwcGVuZChjb250VGVtcGxhdGUuY2xvbmUoKSkpXTtcbiAgICAgICAgfTtcblxuICAgICAgICBUZW1wdXNEb21pbnVzQm9vdHN0cmFwNC5wcm90b3R5cGUuX2dldFRpbWVQaWNrZXJNYWluVGVtcGxhdGUgPSBmdW5jdGlvbiBfZ2V0VGltZVBpY2tlck1haW5UZW1wbGF0ZSgpIHtcbiAgICAgICAgICAgIHZhciB0b3BSb3cgPSAkKCc8dHI+JyksXG4gICAgICAgICAgICAgICAgbWlkZGxlUm93ID0gJCgnPHRyPicpLFxuICAgICAgICAgICAgICAgIGJvdHRvbVJvdyA9ICQoJzx0cj4nKTtcblxuICAgICAgICAgICAgaWYgKHRoaXMuX2lzRW5hYmxlZCgnaCcpKSB7XG4gICAgICAgICAgICAgICAgdG9wUm93LmFwcGVuZCgkKCc8dGQ+JykuYXBwZW5kKCQoJzxhPicpLmF0dHIoe1xuICAgICAgICAgICAgICAgICAgICBocmVmOiAnIycsXG4gICAgICAgICAgICAgICAgICAgIHRhYmluZGV4OiAnLTEnLFxuICAgICAgICAgICAgICAgICAgICAndGl0bGUnOiB0aGlzLl9vcHRpb25zLnRvb2x0aXBzLmluY3JlbWVudEhvdXJcbiAgICAgICAgICAgICAgICB9KS5hZGRDbGFzcygnYnRuJykuYXR0cignZGF0YS1hY3Rpb24nLCAnaW5jcmVtZW50SG91cnMnKS5hcHBlbmQoJCgnPHNwYW4+JykuYWRkQ2xhc3ModGhpcy5fb3B0aW9ucy5pY29ucy51cCkpKSk7XG4gICAgICAgICAgICAgICAgbWlkZGxlUm93LmFwcGVuZCgkKCc8dGQ+JykuYXBwZW5kKCQoJzxzcGFuPicpLmFkZENsYXNzKCd0aW1lcGlja2VyLWhvdXInKS5hdHRyKHtcbiAgICAgICAgICAgICAgICAgICAgJ2RhdGEtdGltZS1jb21wb25lbnQnOiAnaG91cnMnLFxuICAgICAgICAgICAgICAgICAgICAndGl0bGUnOiB0aGlzLl9vcHRpb25zLnRvb2x0aXBzLnBpY2tIb3VyXG4gICAgICAgICAgICAgICAgfSkuYXR0cignZGF0YS1hY3Rpb24nLCAnc2hvd0hvdXJzJykpKTtcbiAgICAgICAgICAgICAgICBib3R0b21Sb3cuYXBwZW5kKCQoJzx0ZD4nKS5hcHBlbmQoJCgnPGE+JykuYXR0cih7XG4gICAgICAgICAgICAgICAgICAgIGhyZWY6ICcjJyxcbiAgICAgICAgICAgICAgICAgICAgdGFiaW5kZXg6ICctMScsXG4gICAgICAgICAgICAgICAgICAgICd0aXRsZSc6IHRoaXMuX29wdGlvbnMudG9vbHRpcHMuZGVjcmVtZW50SG91clxuICAgICAgICAgICAgICAgIH0pLmFkZENsYXNzKCdidG4nKS5hdHRyKCdkYXRhLWFjdGlvbicsICdkZWNyZW1lbnRIb3VycycpLmFwcGVuZCgkKCc8c3Bhbj4nKS5hZGRDbGFzcyh0aGlzLl9vcHRpb25zLmljb25zLmRvd24pKSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuX2lzRW5hYmxlZCgnbScpKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuX2lzRW5hYmxlZCgnaCcpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRvcFJvdy5hcHBlbmQoJCgnPHRkPicpLmFkZENsYXNzKCdzZXBhcmF0b3InKSk7XG4gICAgICAgICAgICAgICAgICAgIG1pZGRsZVJvdy5hcHBlbmQoJCgnPHRkPicpLmFkZENsYXNzKCdzZXBhcmF0b3InKS5odG1sKCc6JykpO1xuICAgICAgICAgICAgICAgICAgICBib3R0b21Sb3cuYXBwZW5kKCQoJzx0ZD4nKS5hZGRDbGFzcygnc2VwYXJhdG9yJykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0b3BSb3cuYXBwZW5kKCQoJzx0ZD4nKS5hcHBlbmQoJCgnPGE+JykuYXR0cih7XG4gICAgICAgICAgICAgICAgICAgIGhyZWY6ICcjJyxcbiAgICAgICAgICAgICAgICAgICAgdGFiaW5kZXg6ICctMScsXG4gICAgICAgICAgICAgICAgICAgICd0aXRsZSc6IHRoaXMuX29wdGlvbnMudG9vbHRpcHMuaW5jcmVtZW50TWludXRlXG4gICAgICAgICAgICAgICAgfSkuYWRkQ2xhc3MoJ2J0bicpLmF0dHIoJ2RhdGEtYWN0aW9uJywgJ2luY3JlbWVudE1pbnV0ZXMnKS5hcHBlbmQoJCgnPHNwYW4+JykuYWRkQ2xhc3ModGhpcy5fb3B0aW9ucy5pY29ucy51cCkpKSk7XG4gICAgICAgICAgICAgICAgbWlkZGxlUm93LmFwcGVuZCgkKCc8dGQ+JykuYXBwZW5kKCQoJzxzcGFuPicpLmFkZENsYXNzKCd0aW1lcGlja2VyLW1pbnV0ZScpLmF0dHIoe1xuICAgICAgICAgICAgICAgICAgICAnZGF0YS10aW1lLWNvbXBvbmVudCc6ICdtaW51dGVzJyxcbiAgICAgICAgICAgICAgICAgICAgJ3RpdGxlJzogdGhpcy5fb3B0aW9ucy50b29sdGlwcy5waWNrTWludXRlXG4gICAgICAgICAgICAgICAgfSkuYXR0cignZGF0YS1hY3Rpb24nLCAnc2hvd01pbnV0ZXMnKSkpO1xuICAgICAgICAgICAgICAgIGJvdHRvbVJvdy5hcHBlbmQoJCgnPHRkPicpLmFwcGVuZCgkKCc8YT4nKS5hdHRyKHtcbiAgICAgICAgICAgICAgICAgICAgaHJlZjogJyMnLFxuICAgICAgICAgICAgICAgICAgICB0YWJpbmRleDogJy0xJyxcbiAgICAgICAgICAgICAgICAgICAgJ3RpdGxlJzogdGhpcy5fb3B0aW9ucy50b29sdGlwcy5kZWNyZW1lbnRNaW51dGVcbiAgICAgICAgICAgICAgICB9KS5hZGRDbGFzcygnYnRuJykuYXR0cignZGF0YS1hY3Rpb24nLCAnZGVjcmVtZW50TWludXRlcycpLmFwcGVuZCgkKCc8c3Bhbj4nKS5hZGRDbGFzcyh0aGlzLl9vcHRpb25zLmljb25zLmRvd24pKSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuX2lzRW5hYmxlZCgncycpKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuX2lzRW5hYmxlZCgnbScpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRvcFJvdy5hcHBlbmQoJCgnPHRkPicpLmFkZENsYXNzKCdzZXBhcmF0b3InKSk7XG4gICAgICAgICAgICAgICAgICAgIG1pZGRsZVJvdy5hcHBlbmQoJCgnPHRkPicpLmFkZENsYXNzKCdzZXBhcmF0b3InKS5odG1sKCc6JykpO1xuICAgICAgICAgICAgICAgICAgICBib3R0b21Sb3cuYXBwZW5kKCQoJzx0ZD4nKS5hZGRDbGFzcygnc2VwYXJhdG9yJykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0b3BSb3cuYXBwZW5kKCQoJzx0ZD4nKS5hcHBlbmQoJCgnPGE+JykuYXR0cih7XG4gICAgICAgICAgICAgICAgICAgIGhyZWY6ICcjJyxcbiAgICAgICAgICAgICAgICAgICAgdGFiaW5kZXg6ICctMScsXG4gICAgICAgICAgICAgICAgICAgICd0aXRsZSc6IHRoaXMuX29wdGlvbnMudG9vbHRpcHMuaW5jcmVtZW50U2Vjb25kXG4gICAgICAgICAgICAgICAgfSkuYWRkQ2xhc3MoJ2J0bicpLmF0dHIoJ2RhdGEtYWN0aW9uJywgJ2luY3JlbWVudFNlY29uZHMnKS5hcHBlbmQoJCgnPHNwYW4+JykuYWRkQ2xhc3ModGhpcy5fb3B0aW9ucy5pY29ucy51cCkpKSk7XG4gICAgICAgICAgICAgICAgbWlkZGxlUm93LmFwcGVuZCgkKCc8dGQ+JykuYXBwZW5kKCQoJzxzcGFuPicpLmFkZENsYXNzKCd0aW1lcGlja2VyLXNlY29uZCcpLmF0dHIoe1xuICAgICAgICAgICAgICAgICAgICAnZGF0YS10aW1lLWNvbXBvbmVudCc6ICdzZWNvbmRzJyxcbiAgICAgICAgICAgICAgICAgICAgJ3RpdGxlJzogdGhpcy5fb3B0aW9ucy50b29sdGlwcy5waWNrU2Vjb25kXG4gICAgICAgICAgICAgICAgfSkuYXR0cignZGF0YS1hY3Rpb24nLCAnc2hvd1NlY29uZHMnKSkpO1xuICAgICAgICAgICAgICAgIGJvdHRvbVJvdy5hcHBlbmQoJCgnPHRkPicpLmFwcGVuZCgkKCc8YT4nKS5hdHRyKHtcbiAgICAgICAgICAgICAgICAgICAgaHJlZjogJyMnLFxuICAgICAgICAgICAgICAgICAgICB0YWJpbmRleDogJy0xJyxcbiAgICAgICAgICAgICAgICAgICAgJ3RpdGxlJzogdGhpcy5fb3B0aW9ucy50b29sdGlwcy5kZWNyZW1lbnRTZWNvbmRcbiAgICAgICAgICAgICAgICB9KS5hZGRDbGFzcygnYnRuJykuYXR0cignZGF0YS1hY3Rpb24nLCAnZGVjcmVtZW50U2Vjb25kcycpLmFwcGVuZCgkKCc8c3Bhbj4nKS5hZGRDbGFzcyh0aGlzLl9vcHRpb25zLmljb25zLmRvd24pKSkpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoIXRoaXMudXNlMjRIb3Vycykge1xuICAgICAgICAgICAgICAgIHRvcFJvdy5hcHBlbmQoJCgnPHRkPicpLmFkZENsYXNzKCdzZXBhcmF0b3InKSk7XG4gICAgICAgICAgICAgICAgbWlkZGxlUm93LmFwcGVuZCgkKCc8dGQ+JykuYXBwZW5kKCQoJzxidXR0b24+JykuYWRkQ2xhc3MoJ2J0biBidG4tcHJpbWFyeScpLmF0dHIoe1xuICAgICAgICAgICAgICAgICAgICAnZGF0YS1hY3Rpb24nOiAndG9nZ2xlUGVyaW9kJyxcbiAgICAgICAgICAgICAgICAgICAgdGFiaW5kZXg6ICctMScsXG4gICAgICAgICAgICAgICAgICAgICd0aXRsZSc6IHRoaXMuX29wdGlvbnMudG9vbHRpcHMudG9nZ2xlUGVyaW9kXG4gICAgICAgICAgICAgICAgfSkpKTtcbiAgICAgICAgICAgICAgICBib3R0b21Sb3cuYXBwZW5kKCQoJzx0ZD4nKS5hZGRDbGFzcygnc2VwYXJhdG9yJykpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gJCgnPGRpdj4nKS5hZGRDbGFzcygndGltZXBpY2tlci1waWNrZXInKS5hcHBlbmQoJCgnPHRhYmxlPicpLmFkZENsYXNzKCd0YWJsZS1jb25kZW5zZWQnKS5hcHBlbmQoW3RvcFJvdywgbWlkZGxlUm93LCBib3R0b21Sb3ddKSk7XG4gICAgICAgIH07XG5cbiAgICAgICAgVGVtcHVzRG9taW51c0Jvb3RzdHJhcDQucHJvdG90eXBlLl9nZXRUaW1lUGlja2VyVGVtcGxhdGUgPSBmdW5jdGlvbiBfZ2V0VGltZVBpY2tlclRlbXBsYXRlKCkge1xuICAgICAgICAgICAgdmFyIGhvdXJzVmlldyA9ICQoJzxkaXY+JykuYWRkQ2xhc3MoJ3RpbWVwaWNrZXItaG91cnMnKS5hcHBlbmQoJCgnPHRhYmxlPicpLmFkZENsYXNzKCd0YWJsZS1jb25kZW5zZWQnKSksXG4gICAgICAgICAgICAgICAgbWludXRlc1ZpZXcgPSAkKCc8ZGl2PicpLmFkZENsYXNzKCd0aW1lcGlja2VyLW1pbnV0ZXMnKS5hcHBlbmQoJCgnPHRhYmxlPicpLmFkZENsYXNzKCd0YWJsZS1jb25kZW5zZWQnKSksXG4gICAgICAgICAgICAgICAgc2Vjb25kc1ZpZXcgPSAkKCc8ZGl2PicpLmFkZENsYXNzKCd0aW1lcGlja2VyLXNlY29uZHMnKS5hcHBlbmQoJCgnPHRhYmxlPicpLmFkZENsYXNzKCd0YWJsZS1jb25kZW5zZWQnKSksXG4gICAgICAgICAgICAgICAgcmV0ID0gW3RoaXMuX2dldFRpbWVQaWNrZXJNYWluVGVtcGxhdGUoKV07XG5cbiAgICAgICAgICAgIGlmICh0aGlzLl9pc0VuYWJsZWQoJ2gnKSkge1xuICAgICAgICAgICAgICAgIHJldC5wdXNoKGhvdXJzVmlldyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5faXNFbmFibGVkKCdtJykpIHtcbiAgICAgICAgICAgICAgICByZXQucHVzaChtaW51dGVzVmlldyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5faXNFbmFibGVkKCdzJykpIHtcbiAgICAgICAgICAgICAgICByZXQucHVzaChzZWNvbmRzVmlldyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiByZXQ7XG4gICAgICAgIH07XG5cbiAgICAgICAgVGVtcHVzRG9taW51c0Jvb3RzdHJhcDQucHJvdG90eXBlLl9nZXRUb29sYmFyID0gZnVuY3Rpb24gX2dldFRvb2xiYXIoKSB7XG4gICAgICAgICAgICB2YXIgcm93ID0gW107XG4gICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy5idXR0b25zLnNob3dUb2RheSkge1xuICAgICAgICAgICAgICAgIHJvdy5wdXNoKCQoJzx0ZD4nKS5hcHBlbmQoJCgnPGE+JykuYXR0cih7XG4gICAgICAgICAgICAgICAgICAgIGhyZWY6ICcjJyxcbiAgICAgICAgICAgICAgICAgICAgdGFiaW5kZXg6ICctMScsXG4gICAgICAgICAgICAgICAgICAgICdkYXRhLWFjdGlvbic6ICd0b2RheScsXG4gICAgICAgICAgICAgICAgICAgICd0aXRsZSc6IHRoaXMuX29wdGlvbnMudG9vbHRpcHMudG9kYXlcbiAgICAgICAgICAgICAgICB9KS5hcHBlbmQoJCgnPHNwYW4+JykuYWRkQ2xhc3ModGhpcy5fb3B0aW9ucy5pY29ucy50b2RheSkpKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIXRoaXMuX29wdGlvbnMuc2lkZUJ5U2lkZSAmJiB0aGlzLl9oYXNEYXRlKCkgJiYgdGhpcy5faGFzVGltZSgpKSB7XG4gICAgICAgICAgICAgICAgcm93LnB1c2goJCgnPHRkPicpLmFwcGVuZCgkKCc8YT4nKS5hdHRyKHtcbiAgICAgICAgICAgICAgICAgICAgaHJlZjogJyMnLFxuICAgICAgICAgICAgICAgICAgICB0YWJpbmRleDogJy0xJyxcbiAgICAgICAgICAgICAgICAgICAgJ2RhdGEtYWN0aW9uJzogJ3RvZ2dsZVBpY2tlcicsXG4gICAgICAgICAgICAgICAgICAgICd0aXRsZSc6IHRoaXMuX29wdGlvbnMudG9vbHRpcHMuc2VsZWN0VGltZVxuICAgICAgICAgICAgICAgIH0pLmFwcGVuZCgkKCc8c3Bhbj4nKS5hZGRDbGFzcyh0aGlzLl9vcHRpb25zLmljb25zLnRpbWUpKSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMuYnV0dG9ucy5zaG93Q2xlYXIpIHtcbiAgICAgICAgICAgICAgICByb3cucHVzaCgkKCc8dGQ+JykuYXBwZW5kKCQoJzxhPicpLmF0dHIoe1xuICAgICAgICAgICAgICAgICAgICBocmVmOiAnIycsXG4gICAgICAgICAgICAgICAgICAgIHRhYmluZGV4OiAnLTEnLFxuICAgICAgICAgICAgICAgICAgICAnZGF0YS1hY3Rpb24nOiAnY2xlYXInLFxuICAgICAgICAgICAgICAgICAgICAndGl0bGUnOiB0aGlzLl9vcHRpb25zLnRvb2x0aXBzLmNsZWFyXG4gICAgICAgICAgICAgICAgfSkuYXBwZW5kKCQoJzxzcGFuPicpLmFkZENsYXNzKHRoaXMuX29wdGlvbnMuaWNvbnMuY2xlYXIpKSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMuYnV0dG9ucy5zaG93Q2xvc2UpIHtcbiAgICAgICAgICAgICAgICByb3cucHVzaCgkKCc8dGQ+JykuYXBwZW5kKCQoJzxhPicpLmF0dHIoe1xuICAgICAgICAgICAgICAgICAgICBocmVmOiAnIycsXG4gICAgICAgICAgICAgICAgICAgIHRhYmluZGV4OiAnLTEnLFxuICAgICAgICAgICAgICAgICAgICAnZGF0YS1hY3Rpb24nOiAnY2xvc2UnLFxuICAgICAgICAgICAgICAgICAgICAndGl0bGUnOiB0aGlzLl9vcHRpb25zLnRvb2x0aXBzLmNsb3NlXG4gICAgICAgICAgICAgICAgfSkuYXBwZW5kKCQoJzxzcGFuPicpLmFkZENsYXNzKHRoaXMuX29wdGlvbnMuaWNvbnMuY2xvc2UpKSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHJvdy5sZW5ndGggPT09IDAgPyAnJyA6ICQoJzx0YWJsZT4nKS5hZGRDbGFzcygndGFibGUtY29uZGVuc2VkJykuYXBwZW5kKCQoJzx0Ym9keT4nKS5hcHBlbmQoJCgnPHRyPicpLmFwcGVuZChyb3cpKSk7XG4gICAgICAgIH07XG5cbiAgICAgICAgVGVtcHVzRG9taW51c0Jvb3RzdHJhcDQucHJvdG90eXBlLl9nZXRUZW1wbGF0ZSA9IGZ1bmN0aW9uIF9nZXRUZW1wbGF0ZSgpIHtcbiAgICAgICAgICAgIHZhciB0ZW1wbGF0ZSA9ICQoJzxkaXY+JykuYWRkQ2xhc3MoJ2Jvb3RzdHJhcC1kYXRldGltZXBpY2tlci13aWRnZXQgZHJvcGRvd24tbWVudScpLFxuICAgICAgICAgICAgICAgIGRhdGVWaWV3ID0gJCgnPGRpdj4nKS5hZGRDbGFzcygnZGF0ZXBpY2tlcicpLmFwcGVuZCh0aGlzLl9nZXREYXRlUGlja2VyVGVtcGxhdGUoKSksXG4gICAgICAgICAgICAgICAgdGltZVZpZXcgPSAkKCc8ZGl2PicpLmFkZENsYXNzKCd0aW1lcGlja2VyJykuYXBwZW5kKHRoaXMuX2dldFRpbWVQaWNrZXJUZW1wbGF0ZSgpKSxcbiAgICAgICAgICAgICAgICBjb250ZW50ID0gJCgnPHVsPicpLmFkZENsYXNzKCdsaXN0LXVuc3R5bGVkJyksXG4gICAgICAgICAgICAgICAgdG9vbGJhciA9ICQoJzxsaT4nKS5hZGRDbGFzcygncGlja2VyLXN3aXRjaCcgKyAodGhpcy5fb3B0aW9ucy5jb2xsYXBzZSA/ICcgYWNjb3JkaW9uLXRvZ2dsZScgOiAnJykpLmFwcGVuZCh0aGlzLl9nZXRUb29sYmFyKCkpO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy5pbmxpbmUpIHtcbiAgICAgICAgICAgICAgICB0ZW1wbGF0ZS5yZW1vdmVDbGFzcygnZHJvcGRvd24tbWVudScpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodGhpcy51c2UyNEhvdXJzKSB7XG4gICAgICAgICAgICAgICAgdGVtcGxhdGUuYWRkQ2xhc3MoJ3VzZXR3ZW50eWZvdXInKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLl9pc0VuYWJsZWQoJ3MnKSAmJiAhdGhpcy51c2UyNEhvdXJzKSB7XG4gICAgICAgICAgICAgICAgdGVtcGxhdGUuYWRkQ2xhc3MoJ3dpZGVyJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0aGlzLl9vcHRpb25zLnNpZGVCeVNpZGUgJiYgdGhpcy5faGFzRGF0ZSgpICYmIHRoaXMuX2hhc1RpbWUoKSkge1xuICAgICAgICAgICAgICAgIHRlbXBsYXRlLmFkZENsYXNzKCd0aW1lcGlja2VyLXNicycpO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLl9vcHRpb25zLnRvb2xiYXJQbGFjZW1lbnQgPT09ICd0b3AnKSB7XG4gICAgICAgICAgICAgICAgICAgIHRlbXBsYXRlLmFwcGVuZCh0b29sYmFyKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGVtcGxhdGUuYXBwZW5kKCQoJzxkaXY+JykuYWRkQ2xhc3MoJ3JvdycpLmFwcGVuZChkYXRlVmlldy5hZGRDbGFzcygnY29sLW1kLTYnKSkuYXBwZW5kKHRpbWVWaWV3LmFkZENsYXNzKCdjb2wtbWQtNicpKSk7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMudG9vbGJhclBsYWNlbWVudCA9PT0gJ2JvdHRvbScgfHwgdGhpcy5fb3B0aW9ucy50b29sYmFyUGxhY2VtZW50ID09PSAnZGVmYXVsdCcpIHtcbiAgICAgICAgICAgICAgICAgICAgdGVtcGxhdGUuYXBwZW5kKHRvb2xiYXIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gdGVtcGxhdGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0aGlzLl9vcHRpb25zLnRvb2xiYXJQbGFjZW1lbnQgPT09ICd0b3AnKSB7XG4gICAgICAgICAgICAgICAgY29udGVudC5hcHBlbmQodG9vbGJhcik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5faGFzRGF0ZSgpKSB7XG4gICAgICAgICAgICAgICAgY29udGVudC5hcHBlbmQoJCgnPGxpPicpLmFkZENsYXNzKHRoaXMuX29wdGlvbnMuY29sbGFwc2UgJiYgdGhpcy5faGFzVGltZSgpID8gJ2NvbGxhcHNlJyA6ICcnKS5hZGRDbGFzcyh0aGlzLl9vcHRpb25zLmNvbGxhcHNlICYmIHRoaXMuX2hhc1RpbWUoKSAmJiB0aGlzLl9vcHRpb25zLnZpZXdNb2RlID09PSAndGltZScgPyAnJyA6ICdzaG93JykuYXBwZW5kKGRhdGVWaWV3KSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy50b29sYmFyUGxhY2VtZW50ID09PSAnZGVmYXVsdCcpIHtcbiAgICAgICAgICAgICAgICBjb250ZW50LmFwcGVuZCh0b29sYmFyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLl9oYXNUaW1lKCkpIHtcbiAgICAgICAgICAgICAgICBjb250ZW50LmFwcGVuZCgkKCc8bGk+JykuYWRkQ2xhc3ModGhpcy5fb3B0aW9ucy5jb2xsYXBzZSAmJiB0aGlzLl9oYXNEYXRlKCkgPyAnY29sbGFwc2UnIDogJycpLmFkZENsYXNzKHRoaXMuX29wdGlvbnMuY29sbGFwc2UgJiYgdGhpcy5faGFzRGF0ZSgpICYmIHRoaXMuX29wdGlvbnMudmlld01vZGUgPT09ICd0aW1lJyA/ICdzaG93JyA6ICcnKS5hcHBlbmQodGltZVZpZXcpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLl9vcHRpb25zLnRvb2xiYXJQbGFjZW1lbnQgPT09ICdib3R0b20nKSB7XG4gICAgICAgICAgICAgICAgY29udGVudC5hcHBlbmQodG9vbGJhcik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdGVtcGxhdGUuYXBwZW5kKGNvbnRlbnQpO1xuICAgICAgICB9O1xuXG4gICAgICAgIFRlbXB1c0RvbWludXNCb290c3RyYXA0LnByb3RvdHlwZS5fcGxhY2UgPSBmdW5jdGlvbiBfcGxhY2UoZSkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSBlICYmIGUuZGF0YSAmJiBlLmRhdGEucGlja2VyIHx8IHRoaXMsXG4gICAgICAgICAgICAgICAgdmVydGljYWwgPSBzZWxmLl9vcHRpb25zLndpZGdldFBvc2l0aW9uaW5nLnZlcnRpY2FsLFxuICAgICAgICAgICAgICAgIGhvcml6b250YWwgPSBzZWxmLl9vcHRpb25zLndpZGdldFBvc2l0aW9uaW5nLmhvcml6b250YWwsXG4gICAgICAgICAgICAgICAgcGFyZW50ID0gdm9pZCAwO1xuICAgICAgICAgICAgdmFyIHBvc2l0aW9uID0gKHNlbGYuY29tcG9uZW50IHx8IHNlbGYuX2VsZW1lbnQpLnBvc2l0aW9uKCksXG4gICAgICAgICAgICAgICAgb2Zmc2V0ID0gKHNlbGYuY29tcG9uZW50IHx8IHNlbGYuX2VsZW1lbnQpLm9mZnNldCgpO1xuICAgICAgICAgICAgaWYgKHNlbGYuX29wdGlvbnMud2lkZ2V0UGFyZW50KSB7XG4gICAgICAgICAgICAgICAgcGFyZW50ID0gc2VsZi5fb3B0aW9ucy53aWRnZXRQYXJlbnQuYXBwZW5kKHNlbGYud2lkZ2V0KTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoc2VsZi5fZWxlbWVudC5pcygnaW5wdXQnKSkge1xuICAgICAgICAgICAgICAgIHBhcmVudCA9IHNlbGYuX2VsZW1lbnQuYWZ0ZXIoc2VsZi53aWRnZXQpLnBhcmVudCgpO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChzZWxmLl9vcHRpb25zLmlubGluZSkge1xuICAgICAgICAgICAgICAgIHBhcmVudCA9IHNlbGYuX2VsZW1lbnQuYXBwZW5kKHNlbGYud2lkZ2V0KTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHBhcmVudCA9IHNlbGYuX2VsZW1lbnQ7XG4gICAgICAgICAgICAgICAgc2VsZi5fZWxlbWVudC5jaGlsZHJlbigpLmZpcnN0KCkuYWZ0ZXIoc2VsZi53aWRnZXQpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBUb3AgYW5kIGJvdHRvbSBsb2dpY1xuICAgICAgICAgICAgaWYgKHZlcnRpY2FsID09PSAnYXV0bycpIHtcbiAgICAgICAgICAgICAgICAvL25vaW5zcGVjdGlvbiBKU1ZhbGlkYXRlVHlwZXNcbiAgICAgICAgICAgICAgICBpZiAob2Zmc2V0LnRvcCArIHNlbGYud2lkZ2V0LmhlaWdodCgpICogMS41ID49ICQod2luZG93KS5oZWlnaHQoKSArICQod2luZG93KS5zY3JvbGxUb3AoKSAmJiBzZWxmLndpZGdldC5oZWlnaHQoKSArIHNlbGYuX2VsZW1lbnQub3V0ZXJIZWlnaHQoKSA8IG9mZnNldC50b3ApIHtcbiAgICAgICAgICAgICAgICAgICAgdmVydGljYWwgPSAndG9wJztcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2ZXJ0aWNhbCA9ICdib3R0b20nO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gTGVmdCBhbmQgcmlnaHQgbG9naWNcbiAgICAgICAgICAgIGlmIChob3Jpem9udGFsID09PSAnYXV0bycpIHtcbiAgICAgICAgICAgICAgICBpZiAocGFyZW50LndpZHRoKCkgPCBvZmZzZXQubGVmdCArIHNlbGYud2lkZ2V0Lm91dGVyV2lkdGgoKSAvIDIgJiYgb2Zmc2V0LmxlZnQgKyBzZWxmLndpZGdldC5vdXRlcldpZHRoKCkgPiAkKHdpbmRvdykud2lkdGgoKSkge1xuICAgICAgICAgICAgICAgICAgICBob3Jpem9udGFsID0gJ3JpZ2h0JztcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBob3Jpem9udGFsID0gJ2xlZnQnO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHZlcnRpY2FsID09PSAndG9wJykge1xuICAgICAgICAgICAgICAgIHNlbGYud2lkZ2V0LmFkZENsYXNzKCd0b3AnKS5yZW1vdmVDbGFzcygnYm90dG9tJyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHNlbGYud2lkZ2V0LmFkZENsYXNzKCdib3R0b20nKS5yZW1vdmVDbGFzcygndG9wJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChob3Jpem9udGFsID09PSAncmlnaHQnKSB7XG4gICAgICAgICAgICAgICAgc2VsZi53aWRnZXQuYWRkQ2xhc3MoJ2Zsb2F0LXJpZ2h0Jyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHNlbGYud2lkZ2V0LnJlbW92ZUNsYXNzKCdmbG9hdC1yaWdodCcpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBmaW5kIHRoZSBmaXJzdCBwYXJlbnQgZWxlbWVudCB0aGF0IGhhcyBhIHJlbGF0aXZlIGNzcyBwb3NpdGlvbmluZ1xuICAgICAgICAgICAgaWYgKHBhcmVudC5jc3MoJ3Bvc2l0aW9uJykgIT09ICdyZWxhdGl2ZScpIHtcbiAgICAgICAgICAgICAgICBwYXJlbnQgPSBwYXJlbnQucGFyZW50cygpLmZpbHRlcihmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAkKHRoaXMpLmNzcygncG9zaXRpb24nKSA9PT0gJ3JlbGF0aXZlJztcbiAgICAgICAgICAgICAgICB9KS5maXJzdCgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAocGFyZW50Lmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignZGF0ZXRpbWVwaWNrZXIgY29tcG9uZW50IHNob3VsZCBiZSBwbGFjZWQgd2l0aGluIGEgcmVsYXRpdmUgcG9zaXRpb25lZCBjb250YWluZXInKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgc2VsZi53aWRnZXQuY3NzKHtcbiAgICAgICAgICAgICAgICB0b3A6IHZlcnRpY2FsID09PSAndG9wJyA/ICdhdXRvJyA6IHBvc2l0aW9uLnRvcCArIHNlbGYuX2VsZW1lbnQub3V0ZXJIZWlnaHQoKSArICdweCcsXG4gICAgICAgICAgICAgICAgYm90dG9tOiB2ZXJ0aWNhbCA9PT0gJ3RvcCcgPyBwYXJlbnQub3V0ZXJIZWlnaHQoKSAtIChwYXJlbnQgPT09IHNlbGYuX2VsZW1lbnQgPyAwIDogcG9zaXRpb24udG9wKSArICdweCcgOiAnYXV0bycsXG4gICAgICAgICAgICAgICAgbGVmdDogaG9yaXpvbnRhbCA9PT0gJ2xlZnQnID8gKHBhcmVudCA9PT0gc2VsZi5fZWxlbWVudCA/IDAgOiBwb3NpdGlvbi5sZWZ0KSArICdweCcgOiAnYXV0bycsXG4gICAgICAgICAgICAgICAgcmlnaHQ6IGhvcml6b250YWwgPT09ICdsZWZ0JyA/ICdhdXRvJyA6IHBhcmVudC5vdXRlcldpZHRoKCkgLSBzZWxmLl9lbGVtZW50Lm91dGVyV2lkdGgoKSAtIChwYXJlbnQgPT09IHNlbGYuX2VsZW1lbnQgPyAwIDogcG9zaXRpb24ubGVmdCkgKyAncHgnXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfTtcblxuICAgICAgICBUZW1wdXNEb21pbnVzQm9vdHN0cmFwNC5wcm90b3R5cGUuX2ZpbGxEb3cgPSBmdW5jdGlvbiBfZmlsbERvdygpIHtcbiAgICAgICAgICAgIHZhciByb3cgPSAkKCc8dHI+JyksXG4gICAgICAgICAgICAgICAgY3VycmVudERhdGUgPSB0aGlzLl92aWV3RGF0ZS5jbG9uZSgpLnN0YXJ0T2YoJ3cnKS5zdGFydE9mKCdkJyk7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLl9vcHRpb25zLmNhbGVuZGFyV2Vla3MgPT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICByb3cuYXBwZW5kKCQoJzx0aD4nKS5hZGRDbGFzcygnY3cnKS50ZXh0KCcjJykpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB3aGlsZSAoY3VycmVudERhdGUuaXNCZWZvcmUodGhpcy5fdmlld0RhdGUuY2xvbmUoKS5lbmRPZigndycpKSkge1xuICAgICAgICAgICAgICAgIHJvdy5hcHBlbmQoJCgnPHRoPicpLmFkZENsYXNzKCdkb3cnKS50ZXh0KGN1cnJlbnREYXRlLmZvcm1hdCgnZGQnKSkpO1xuICAgICAgICAgICAgICAgIGN1cnJlbnREYXRlLmFkZCgxLCAnZCcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy53aWRnZXQuZmluZCgnLmRhdGVwaWNrZXItZGF5cyB0aGVhZCcpLmFwcGVuZChyb3cpO1xuICAgICAgICB9O1xuXG4gICAgICAgIFRlbXB1c0RvbWludXNCb290c3RyYXA0LnByb3RvdHlwZS5fZmlsbE1vbnRocyA9IGZ1bmN0aW9uIF9maWxsTW9udGhzKCkge1xuICAgICAgICAgICAgdmFyIHNwYW5zID0gW10sXG4gICAgICAgICAgICAgICAgbW9udGhzU2hvcnQgPSB0aGlzLl92aWV3RGF0ZS5jbG9uZSgpLnN0YXJ0T2YoJ3knKS5zdGFydE9mKCdkJyk7XG4gICAgICAgICAgICB3aGlsZSAobW9udGhzU2hvcnQuaXNTYW1lKHRoaXMuX3ZpZXdEYXRlLCAneScpKSB7XG4gICAgICAgICAgICAgICAgc3BhbnMucHVzaCgkKCc8c3Bhbj4nKS5hdHRyKCdkYXRhLWFjdGlvbicsICdzZWxlY3RNb250aCcpLmFkZENsYXNzKCdtb250aCcpLnRleHQobW9udGhzU2hvcnQuZm9ybWF0KCdNTU0nKSkpO1xuICAgICAgICAgICAgICAgIG1vbnRoc1Nob3J0LmFkZCgxLCAnTScpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy53aWRnZXQuZmluZCgnLmRhdGVwaWNrZXItbW9udGhzIHRkJykuZW1wdHkoKS5hcHBlbmQoc3BhbnMpO1xuICAgICAgICB9O1xuXG4gICAgICAgIFRlbXB1c0RvbWludXNCb290c3RyYXA0LnByb3RvdHlwZS5fdXBkYXRlTW9udGhzID0gZnVuY3Rpb24gX3VwZGF0ZU1vbnRocygpIHtcbiAgICAgICAgICAgIHZhciBtb250aHNWaWV3ID0gdGhpcy53aWRnZXQuZmluZCgnLmRhdGVwaWNrZXItbW9udGhzJyksXG4gICAgICAgICAgICAgICAgbW9udGhzVmlld0hlYWRlciA9IG1vbnRoc1ZpZXcuZmluZCgndGgnKSxcbiAgICAgICAgICAgICAgICBtb250aHMgPSBtb250aHNWaWV3LmZpbmQoJ3Rib2R5JykuZmluZCgnc3BhbicpLFxuICAgICAgICAgICAgICAgIHNlbGYgPSB0aGlzO1xuXG4gICAgICAgICAgICBtb250aHNWaWV3SGVhZGVyLmVxKDApLmZpbmQoJ3NwYW4nKS5hdHRyKCd0aXRsZScsIHRoaXMuX29wdGlvbnMudG9vbHRpcHMucHJldlllYXIpO1xuICAgICAgICAgICAgbW9udGhzVmlld0hlYWRlci5lcSgxKS5hdHRyKCd0aXRsZScsIHRoaXMuX29wdGlvbnMudG9vbHRpcHMuc2VsZWN0WWVhcik7XG4gICAgICAgICAgICBtb250aHNWaWV3SGVhZGVyLmVxKDIpLmZpbmQoJ3NwYW4nKS5hdHRyKCd0aXRsZScsIHRoaXMuX29wdGlvbnMudG9vbHRpcHMubmV4dFllYXIpO1xuXG4gICAgICAgICAgICBtb250aHNWaWV3LmZpbmQoJy5kaXNhYmxlZCcpLnJlbW92ZUNsYXNzKCdkaXNhYmxlZCcpO1xuXG4gICAgICAgICAgICBpZiAoIXRoaXMuX2lzVmFsaWQodGhpcy5fdmlld0RhdGUuY2xvbmUoKS5zdWJ0cmFjdCgxLCAneScpLCAneScpKSB7XG4gICAgICAgICAgICAgICAgbW9udGhzVmlld0hlYWRlci5lcSgwKS5hZGRDbGFzcygnZGlzYWJsZWQnKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgbW9udGhzVmlld0hlYWRlci5lcSgxKS50ZXh0KHRoaXMuX3ZpZXdEYXRlLnllYXIoKSk7XG5cbiAgICAgICAgICAgIGlmICghdGhpcy5faXNWYWxpZCh0aGlzLl92aWV3RGF0ZS5jbG9uZSgpLmFkZCgxLCAneScpLCAneScpKSB7XG4gICAgICAgICAgICAgICAgbW9udGhzVmlld0hlYWRlci5lcSgyKS5hZGRDbGFzcygnZGlzYWJsZWQnKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgbW9udGhzLnJlbW92ZUNsYXNzKCdhY3RpdmUnKTtcbiAgICAgICAgICAgIGlmICh0aGlzLl9nZXRMYXN0UGlja2VkRGF0ZSgpLmlzU2FtZSh0aGlzLl92aWV3RGF0ZSwgJ3knKSAmJiAhdGhpcy51bnNldCkge1xuICAgICAgICAgICAgICAgIG1vbnRocy5lcSh0aGlzLl9nZXRMYXN0UGlja2VkRGF0ZSgpLm1vbnRoKCkpLmFkZENsYXNzKCdhY3RpdmUnKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgbW9udGhzLmVhY2goZnVuY3Rpb24gKGluZGV4KSB7XG4gICAgICAgICAgICAgICAgaWYgKCFzZWxmLl9pc1ZhbGlkKHNlbGYuX3ZpZXdEYXRlLmNsb25lKCkubW9udGgoaW5kZXgpLCAnTScpKSB7XG4gICAgICAgICAgICAgICAgICAgICQodGhpcykuYWRkQ2xhc3MoJ2Rpc2FibGVkJyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH07XG5cbiAgICAgICAgVGVtcHVzRG9taW51c0Jvb3RzdHJhcDQucHJvdG90eXBlLl9nZXRTdGFydEVuZFllYXIgPSBmdW5jdGlvbiBfZ2V0U3RhcnRFbmRZZWFyKGZhY3RvciwgeWVhcikge1xuICAgICAgICAgICAgdmFyIHN0ZXAgPSBmYWN0b3IgLyAxMCxcbiAgICAgICAgICAgICAgICBzdGFydFllYXIgPSBNYXRoLmZsb29yKHllYXIgLyBmYWN0b3IpICogZmFjdG9yLFxuICAgICAgICAgICAgICAgIGVuZFllYXIgPSBzdGFydFllYXIgKyBzdGVwICogOSxcbiAgICAgICAgICAgICAgICBmb2N1c1ZhbHVlID0gTWF0aC5mbG9vcih5ZWFyIC8gc3RlcCkgKiBzdGVwO1xuICAgICAgICAgICAgcmV0dXJuIFtzdGFydFllYXIsIGVuZFllYXIsIGZvY3VzVmFsdWVdO1xuICAgICAgICB9O1xuXG4gICAgICAgIFRlbXB1c0RvbWludXNCb290c3RyYXA0LnByb3RvdHlwZS5fdXBkYXRlWWVhcnMgPSBmdW5jdGlvbiBfdXBkYXRlWWVhcnMoKSB7XG4gICAgICAgICAgICB2YXIgeWVhcnNWaWV3ID0gdGhpcy53aWRnZXQuZmluZCgnLmRhdGVwaWNrZXIteWVhcnMnKSxcbiAgICAgICAgICAgICAgICB5ZWFyc1ZpZXdIZWFkZXIgPSB5ZWFyc1ZpZXcuZmluZCgndGgnKSxcbiAgICAgICAgICAgICAgICB5ZWFyQ2FwcyA9IHRoaXMuX2dldFN0YXJ0RW5kWWVhcigxMCwgdGhpcy5fdmlld0RhdGUueWVhcigpKSxcbiAgICAgICAgICAgICAgICBzdGFydFllYXIgPSB0aGlzLl92aWV3RGF0ZS5jbG9uZSgpLnllYXIoeWVhckNhcHNbMF0pLFxuICAgICAgICAgICAgICAgIGVuZFllYXIgPSB0aGlzLl92aWV3RGF0ZS5jbG9uZSgpLnllYXIoeWVhckNhcHNbMV0pO1xuICAgICAgICAgICAgdmFyIGh0bWwgPSAnJztcblxuICAgICAgICAgICAgeWVhcnNWaWV3SGVhZGVyLmVxKDApLmZpbmQoJ3NwYW4nKS5hdHRyKCd0aXRsZScsIHRoaXMuX29wdGlvbnMudG9vbHRpcHMucHJldkRlY2FkZSk7XG4gICAgICAgICAgICB5ZWFyc1ZpZXdIZWFkZXIuZXEoMSkuYXR0cigndGl0bGUnLCB0aGlzLl9vcHRpb25zLnRvb2x0aXBzLnNlbGVjdERlY2FkZSk7XG4gICAgICAgICAgICB5ZWFyc1ZpZXdIZWFkZXIuZXEoMikuZmluZCgnc3BhbicpLmF0dHIoJ3RpdGxlJywgdGhpcy5fb3B0aW9ucy50b29sdGlwcy5uZXh0RGVjYWRlKTtcblxuICAgICAgICAgICAgeWVhcnNWaWV3LmZpbmQoJy5kaXNhYmxlZCcpLnJlbW92ZUNsYXNzKCdkaXNhYmxlZCcpO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy5taW5EYXRlICYmIHRoaXMuX29wdGlvbnMubWluRGF0ZS5pc0FmdGVyKHN0YXJ0WWVhciwgJ3knKSkge1xuICAgICAgICAgICAgICAgIHllYXJzVmlld0hlYWRlci5lcSgwKS5hZGRDbGFzcygnZGlzYWJsZWQnKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgeWVhcnNWaWV3SGVhZGVyLmVxKDEpLnRleHQoc3RhcnRZZWFyLnllYXIoKSArICctJyArIGVuZFllYXIueWVhcigpKTtcblxuICAgICAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMubWF4RGF0ZSAmJiB0aGlzLl9vcHRpb25zLm1heERhdGUuaXNCZWZvcmUoZW5kWWVhciwgJ3knKSkge1xuICAgICAgICAgICAgICAgIHllYXJzVmlld0hlYWRlci5lcSgyKS5hZGRDbGFzcygnZGlzYWJsZWQnKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaHRtbCArPSAnPHNwYW4gZGF0YS1hY3Rpb249XCJzZWxlY3RZZWFyXCIgY2xhc3M9XCJ5ZWFyIG9sZFwiPicgKyAoc3RhcnRZZWFyLnllYXIoKSAtIDEpICsgJzwvc3Bhbj4nO1xuICAgICAgICAgICAgd2hpbGUgKCFzdGFydFllYXIuaXNBZnRlcihlbmRZZWFyLCAneScpKSB7XG4gICAgICAgICAgICAgICAgaHRtbCArPSAnPHNwYW4gZGF0YS1hY3Rpb249XCJzZWxlY3RZZWFyXCIgY2xhc3M9XCJ5ZWFyJyArIChzdGFydFllYXIuaXNTYW1lKHRoaXMuX2dldExhc3RQaWNrZWREYXRlKCksICd5JykgJiYgIXRoaXMudW5zZXQgPyAnIGFjdGl2ZScgOiAnJykgKyAoIXRoaXMuX2lzVmFsaWQoc3RhcnRZZWFyLCAneScpID8gJyBkaXNhYmxlZCcgOiAnJykgKyAnXCI+JyArIHN0YXJ0WWVhci55ZWFyKCkgKyAnPC9zcGFuPic7XG4gICAgICAgICAgICAgICAgc3RhcnRZZWFyLmFkZCgxLCAneScpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaHRtbCArPSAnPHNwYW4gZGF0YS1hY3Rpb249XCJzZWxlY3RZZWFyXCIgY2xhc3M9XCJ5ZWFyIG9sZFwiPicgKyBzdGFydFllYXIueWVhcigpICsgJzwvc3Bhbj4nO1xuXG4gICAgICAgICAgICB5ZWFyc1ZpZXcuZmluZCgndGQnKS5odG1sKGh0bWwpO1xuICAgICAgICB9O1xuXG4gICAgICAgIFRlbXB1c0RvbWludXNCb290c3RyYXA0LnByb3RvdHlwZS5fdXBkYXRlRGVjYWRlcyA9IGZ1bmN0aW9uIF91cGRhdGVEZWNhZGVzKCkge1xuICAgICAgICAgICAgdmFyIGRlY2FkZXNWaWV3ID0gdGhpcy53aWRnZXQuZmluZCgnLmRhdGVwaWNrZXItZGVjYWRlcycpLFxuICAgICAgICAgICAgICAgIGRlY2FkZXNWaWV3SGVhZGVyID0gZGVjYWRlc1ZpZXcuZmluZCgndGgnKSxcbiAgICAgICAgICAgICAgICB5ZWFyQ2FwcyA9IHRoaXMuX2dldFN0YXJ0RW5kWWVhcigxMDAsIHRoaXMuX3ZpZXdEYXRlLnllYXIoKSksXG4gICAgICAgICAgICAgICAgc3RhcnREZWNhZGUgPSB0aGlzLl92aWV3RGF0ZS5jbG9uZSgpLnllYXIoeWVhckNhcHNbMF0pLFxuICAgICAgICAgICAgICAgIGVuZERlY2FkZSA9IHRoaXMuX3ZpZXdEYXRlLmNsb25lKCkueWVhcih5ZWFyQ2Fwc1sxXSk7XG4gICAgICAgICAgICB2YXIgbWluRGF0ZURlY2FkZSA9IGZhbHNlLFxuICAgICAgICAgICAgICAgIG1heERhdGVEZWNhZGUgPSBmYWxzZSxcbiAgICAgICAgICAgICAgICBlbmREZWNhZGVZZWFyID0gdm9pZCAwLFxuICAgICAgICAgICAgICAgIGh0bWwgPSAnJztcblxuICAgICAgICAgICAgZGVjYWRlc1ZpZXdIZWFkZXIuZXEoMCkuZmluZCgnc3BhbicpLmF0dHIoJ3RpdGxlJywgdGhpcy5fb3B0aW9ucy50b29sdGlwcy5wcmV2Q2VudHVyeSk7XG4gICAgICAgICAgICBkZWNhZGVzVmlld0hlYWRlci5lcSgyKS5maW5kKCdzcGFuJykuYXR0cigndGl0bGUnLCB0aGlzLl9vcHRpb25zLnRvb2x0aXBzLm5leHRDZW50dXJ5KTtcblxuICAgICAgICAgICAgZGVjYWRlc1ZpZXcuZmluZCgnLmRpc2FibGVkJykucmVtb3ZlQ2xhc3MoJ2Rpc2FibGVkJyk7XG5cbiAgICAgICAgICAgIGlmIChzdGFydERlY2FkZS55ZWFyKCkgPT09IDAgfHwgdGhpcy5fb3B0aW9ucy5taW5EYXRlICYmIHRoaXMuX29wdGlvbnMubWluRGF0ZS5pc0FmdGVyKHN0YXJ0RGVjYWRlLCAneScpKSB7XG4gICAgICAgICAgICAgICAgZGVjYWRlc1ZpZXdIZWFkZXIuZXEoMCkuYWRkQ2xhc3MoJ2Rpc2FibGVkJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGRlY2FkZXNWaWV3SGVhZGVyLmVxKDEpLnRleHQoc3RhcnREZWNhZGUueWVhcigpICsgJy0nICsgZW5kRGVjYWRlLnllYXIoKSk7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLl9vcHRpb25zLm1heERhdGUgJiYgdGhpcy5fb3B0aW9ucy5tYXhEYXRlLmlzQmVmb3JlKGVuZERlY2FkZSwgJ3knKSkge1xuICAgICAgICAgICAgICAgIGRlY2FkZXNWaWV3SGVhZGVyLmVxKDIpLmFkZENsYXNzKCdkaXNhYmxlZCcpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoc3RhcnREZWNhZGUueWVhcigpIC0gMTAgPCAwKSB7XG4gICAgICAgICAgICAgICAgaHRtbCArPSAnPHNwYW4+Jm5ic3A7PC9zcGFuPic7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGh0bWwgKz0gJzxzcGFuIGRhdGEtYWN0aW9uPVwic2VsZWN0RGVjYWRlXCIgY2xhc3M9XCJkZWNhZGUgb2xkXCIgZGF0YS1zZWxlY3Rpb249XCInICsgKHN0YXJ0RGVjYWRlLnllYXIoKSArIDYpICsgJ1wiPicgKyAoc3RhcnREZWNhZGUueWVhcigpIC0gMTApICsgJzwvc3Bhbj4nO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB3aGlsZSAoIXN0YXJ0RGVjYWRlLmlzQWZ0ZXIoZW5kRGVjYWRlLCAneScpKSB7XG4gICAgICAgICAgICAgICAgZW5kRGVjYWRlWWVhciA9IHN0YXJ0RGVjYWRlLnllYXIoKSArIDExO1xuICAgICAgICAgICAgICAgIG1pbkRhdGVEZWNhZGUgPSB0aGlzLl9vcHRpb25zLm1pbkRhdGUgJiYgdGhpcy5fb3B0aW9ucy5taW5EYXRlLmlzQWZ0ZXIoc3RhcnREZWNhZGUsICd5JykgJiYgdGhpcy5fb3B0aW9ucy5taW5EYXRlLnllYXIoKSA8PSBlbmREZWNhZGVZZWFyO1xuICAgICAgICAgICAgICAgIG1heERhdGVEZWNhZGUgPSB0aGlzLl9vcHRpb25zLm1heERhdGUgJiYgdGhpcy5fb3B0aW9ucy5tYXhEYXRlLmlzQWZ0ZXIoc3RhcnREZWNhZGUsICd5JykgJiYgdGhpcy5fb3B0aW9ucy5tYXhEYXRlLnllYXIoKSA8PSBlbmREZWNhZGVZZWFyO1xuICAgICAgICAgICAgICAgIGh0bWwgKz0gJzxzcGFuIGRhdGEtYWN0aW9uPVwic2VsZWN0RGVjYWRlXCIgY2xhc3M9XCJkZWNhZGUnICsgKHRoaXMuX2dldExhc3RQaWNrZWREYXRlKCkuaXNBZnRlcihzdGFydERlY2FkZSkgJiYgdGhpcy5fZ2V0TGFzdFBpY2tlZERhdGUoKS55ZWFyKCkgPD0gZW5kRGVjYWRlWWVhciA/ICcgYWN0aXZlJyA6ICcnKSArICghdGhpcy5faXNWYWxpZChzdGFydERlY2FkZSwgJ3knKSAmJiAhbWluRGF0ZURlY2FkZSAmJiAhbWF4RGF0ZURlY2FkZSA/ICcgZGlzYWJsZWQnIDogJycpICsgJ1wiIGRhdGEtc2VsZWN0aW9uPVwiJyArIChzdGFydERlY2FkZS55ZWFyKCkgKyA2KSArICdcIj4nICsgc3RhcnREZWNhZGUueWVhcigpICsgJzwvc3Bhbj4nO1xuICAgICAgICAgICAgICAgIHN0YXJ0RGVjYWRlLmFkZCgxMCwgJ3knKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGh0bWwgKz0gJzxzcGFuIGRhdGEtYWN0aW9uPVwic2VsZWN0RGVjYWRlXCIgY2xhc3M9XCJkZWNhZGUgb2xkXCIgZGF0YS1zZWxlY3Rpb249XCInICsgKHN0YXJ0RGVjYWRlLnllYXIoKSArIDYpICsgJ1wiPicgKyBzdGFydERlY2FkZS55ZWFyKCkgKyAnPC9zcGFuPic7XG5cbiAgICAgICAgICAgIGRlY2FkZXNWaWV3LmZpbmQoJ3RkJykuaHRtbChodG1sKTtcbiAgICAgICAgfTtcblxuICAgICAgICBUZW1wdXNEb21pbnVzQm9vdHN0cmFwNC5wcm90b3R5cGUuX2ZpbGxEYXRlID0gZnVuY3Rpb24gX2ZpbGxEYXRlKCkge1xuICAgICAgICAgICAgdmFyIGRheXNWaWV3ID0gdGhpcy53aWRnZXQuZmluZCgnLmRhdGVwaWNrZXItZGF5cycpLFxuICAgICAgICAgICAgICAgIGRheXNWaWV3SGVhZGVyID0gZGF5c1ZpZXcuZmluZCgndGgnKSxcbiAgICAgICAgICAgICAgICBodG1sID0gW107XG4gICAgICAgICAgICB2YXIgY3VycmVudERhdGUgPSB2b2lkIDAsXG4gICAgICAgICAgICAgICAgcm93ID0gdm9pZCAwLFxuICAgICAgICAgICAgICAgIGNsc05hbWUgPSB2b2lkIDAsXG4gICAgICAgICAgICAgICAgaSA9IHZvaWQgMDtcblxuICAgICAgICAgICAgaWYgKCF0aGlzLl9oYXNEYXRlKCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGRheXNWaWV3SGVhZGVyLmVxKDApLmZpbmQoJ3NwYW4nKS5hdHRyKCd0aXRsZScsIHRoaXMuX29wdGlvbnMudG9vbHRpcHMucHJldk1vbnRoKTtcbiAgICAgICAgICAgIGRheXNWaWV3SGVhZGVyLmVxKDEpLmF0dHIoJ3RpdGxlJywgdGhpcy5fb3B0aW9ucy50b29sdGlwcy5zZWxlY3RNb250aCk7XG4gICAgICAgICAgICBkYXlzVmlld0hlYWRlci5lcSgyKS5maW5kKCdzcGFuJykuYXR0cigndGl0bGUnLCB0aGlzLl9vcHRpb25zLnRvb2x0aXBzLm5leHRNb250aCk7XG5cbiAgICAgICAgICAgIGRheXNWaWV3LmZpbmQoJy5kaXNhYmxlZCcpLnJlbW92ZUNsYXNzKCdkaXNhYmxlZCcpO1xuICAgICAgICAgICAgZGF5c1ZpZXdIZWFkZXIuZXEoMSkudGV4dCh0aGlzLl92aWV3RGF0ZS5mb3JtYXQodGhpcy5fb3B0aW9ucy5kYXlWaWV3SGVhZGVyRm9ybWF0KSk7XG5cbiAgICAgICAgICAgIGlmICghdGhpcy5faXNWYWxpZCh0aGlzLl92aWV3RGF0ZS5jbG9uZSgpLnN1YnRyYWN0KDEsICdNJyksICdNJykpIHtcbiAgICAgICAgICAgICAgICBkYXlzVmlld0hlYWRlci5lcSgwKS5hZGRDbGFzcygnZGlzYWJsZWQnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghdGhpcy5faXNWYWxpZCh0aGlzLl92aWV3RGF0ZS5jbG9uZSgpLmFkZCgxLCAnTScpLCAnTScpKSB7XG4gICAgICAgICAgICAgICAgZGF5c1ZpZXdIZWFkZXIuZXEoMikuYWRkQ2xhc3MoJ2Rpc2FibGVkJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGN1cnJlbnREYXRlID0gdGhpcy5fdmlld0RhdGUuY2xvbmUoKS5zdGFydE9mKCdNJykuc3RhcnRPZigndycpLnN0YXJ0T2YoJ2QnKTtcblxuICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IDQyOyBpKyspIHtcbiAgICAgICAgICAgICAgICAvL2Fsd2F5cyBkaXNwbGF5IDQyIGRheXMgKHNob3VsZCBzaG93IDYgd2Vla3MpXG4gICAgICAgICAgICAgICAgaWYgKGN1cnJlbnREYXRlLndlZWtkYXkoKSA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICByb3cgPSAkKCc8dHI+Jyk7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLl9vcHRpb25zLmNhbGVuZGFyV2Vla3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJvdy5hcHBlbmQoJzx0ZCBjbGFzcz1cImN3XCI+JyArIGN1cnJlbnREYXRlLndlZWsoKSArICc8L3RkPicpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGh0bWwucHVzaChyb3cpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjbHNOYW1lID0gJyc7XG4gICAgICAgICAgICAgICAgaWYgKGN1cnJlbnREYXRlLmlzQmVmb3JlKHRoaXMuX3ZpZXdEYXRlLCAnTScpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNsc05hbWUgKz0gJyBvbGQnO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoY3VycmVudERhdGUuaXNBZnRlcih0aGlzLl92aWV3RGF0ZSwgJ00nKSkge1xuICAgICAgICAgICAgICAgICAgICBjbHNOYW1lICs9ICcgbmV3JztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMuYWxsb3dNdWx0aWRhdGUpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGluZGV4ID0gdGhpcy5fZGF0ZXNGb3JtYXR0ZWQuaW5kZXhPZihjdXJyZW50RGF0ZS5mb3JtYXQoJ1lZWVktTU0tREQnKSk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpbmRleCAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjdXJyZW50RGF0ZS5pc1NhbWUodGhpcy5fZGF0ZXNGb3JtYXR0ZWRbaW5kZXhdLCAnZCcpICYmICF0aGlzLnVuc2V0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xzTmFtZSArPSAnIGFjdGl2ZSc7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBpZiAoY3VycmVudERhdGUuaXNTYW1lKHRoaXMuX2dldExhc3RQaWNrZWREYXRlKCksICdkJykgJiYgIXRoaXMudW5zZXQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsc05hbWUgKz0gJyBhY3RpdmUnO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICghdGhpcy5faXNWYWxpZChjdXJyZW50RGF0ZSwgJ2QnKSkge1xuICAgICAgICAgICAgICAgICAgICBjbHNOYW1lICs9ICcgZGlzYWJsZWQnO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoY3VycmVudERhdGUuaXNTYW1lKHRoaXMuZ2V0TW9tZW50KCksICdkJykpIHtcbiAgICAgICAgICAgICAgICAgICAgY2xzTmFtZSArPSAnIHRvZGF5JztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGN1cnJlbnREYXRlLmRheSgpID09PSAwIHx8IGN1cnJlbnREYXRlLmRheSgpID09PSA2KSB7XG4gICAgICAgICAgICAgICAgICAgIGNsc05hbWUgKz0gJyB3ZWVrZW5kJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcm93LmFwcGVuZCgnPHRkIGRhdGEtYWN0aW9uPVwic2VsZWN0RGF5XCIgZGF0YS1kYXk9XCInICsgY3VycmVudERhdGUuZm9ybWF0KCdMJykgKyAnXCIgY2xhc3M9XCJkYXknICsgY2xzTmFtZSArICdcIj4nICsgY3VycmVudERhdGUuZGF0ZSgpICsgJzwvdGQ+Jyk7XG4gICAgICAgICAgICAgICAgY3VycmVudERhdGUuYWRkKDEsICdkJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGRheXNWaWV3LmZpbmQoJ3Rib2R5JykuZW1wdHkoKS5hcHBlbmQoaHRtbCk7XG5cbiAgICAgICAgICAgIHRoaXMuX3VwZGF0ZU1vbnRocygpO1xuXG4gICAgICAgICAgICB0aGlzLl91cGRhdGVZZWFycygpO1xuXG4gICAgICAgICAgICB0aGlzLl91cGRhdGVEZWNhZGVzKCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgVGVtcHVzRG9taW51c0Jvb3RzdHJhcDQucHJvdG90eXBlLl9maWxsSG91cnMgPSBmdW5jdGlvbiBfZmlsbEhvdXJzKCkge1xuICAgICAgICAgICAgdmFyIHRhYmxlID0gdGhpcy53aWRnZXQuZmluZCgnLnRpbWVwaWNrZXItaG91cnMgdGFibGUnKSxcbiAgICAgICAgICAgICAgICBjdXJyZW50SG91ciA9IHRoaXMuX3ZpZXdEYXRlLmNsb25lKCkuc3RhcnRPZignZCcpLFxuICAgICAgICAgICAgICAgIGh0bWwgPSBbXTtcbiAgICAgICAgICAgIHZhciByb3cgPSAkKCc8dHI+Jyk7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLl92aWV3RGF0ZS5ob3VyKCkgPiAxMSAmJiAhdGhpcy51c2UyNEhvdXJzKSB7XG4gICAgICAgICAgICAgICAgY3VycmVudEhvdXIuaG91cigxMik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB3aGlsZSAoY3VycmVudEhvdXIuaXNTYW1lKHRoaXMuX3ZpZXdEYXRlLCAnZCcpICYmICh0aGlzLnVzZTI0SG91cnMgfHwgdGhpcy5fdmlld0RhdGUuaG91cigpIDwgMTIgJiYgY3VycmVudEhvdXIuaG91cigpIDwgMTIgfHwgdGhpcy5fdmlld0RhdGUuaG91cigpID4gMTEpKSB7XG4gICAgICAgICAgICAgICAgaWYgKGN1cnJlbnRIb3VyLmhvdXIoKSAlIDQgPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcm93ID0gJCgnPHRyPicpO1xuICAgICAgICAgICAgICAgICAgICBodG1sLnB1c2gocm93KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcm93LmFwcGVuZCgnPHRkIGRhdGEtYWN0aW9uPVwic2VsZWN0SG91clwiIGNsYXNzPVwiaG91cicgKyAoIXRoaXMuX2lzVmFsaWQoY3VycmVudEhvdXIsICdoJykgPyAnIGRpc2FibGVkJyA6ICcnKSArICdcIj4nICsgY3VycmVudEhvdXIuZm9ybWF0KHRoaXMudXNlMjRIb3VycyA/ICdISCcgOiAnaGgnKSArICc8L3RkPicpO1xuICAgICAgICAgICAgICAgIGN1cnJlbnRIb3VyLmFkZCgxLCAnaCcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGFibGUuZW1wdHkoKS5hcHBlbmQoaHRtbCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgVGVtcHVzRG9taW51c0Jvb3RzdHJhcDQucHJvdG90eXBlLl9maWxsTWludXRlcyA9IGZ1bmN0aW9uIF9maWxsTWludXRlcygpIHtcbiAgICAgICAgICAgIHZhciB0YWJsZSA9IHRoaXMud2lkZ2V0LmZpbmQoJy50aW1lcGlja2VyLW1pbnV0ZXMgdGFibGUnKSxcbiAgICAgICAgICAgICAgICBjdXJyZW50TWludXRlID0gdGhpcy5fdmlld0RhdGUuY2xvbmUoKS5zdGFydE9mKCdoJyksXG4gICAgICAgICAgICAgICAgaHRtbCA9IFtdLFxuICAgICAgICAgICAgICAgIHN0ZXAgPSB0aGlzLl9vcHRpb25zLnN0ZXBwaW5nID09PSAxID8gNSA6IHRoaXMuX29wdGlvbnMuc3RlcHBpbmc7XG4gICAgICAgICAgICB2YXIgcm93ID0gJCgnPHRyPicpO1xuXG4gICAgICAgICAgICB3aGlsZSAodGhpcy5fdmlld0RhdGUuaXNTYW1lKGN1cnJlbnRNaW51dGUsICdoJykpIHtcbiAgICAgICAgICAgICAgICBpZiAoY3VycmVudE1pbnV0ZS5taW51dGUoKSAlIChzdGVwICogNCkgPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcm93ID0gJCgnPHRyPicpO1xuICAgICAgICAgICAgICAgICAgICBodG1sLnB1c2gocm93KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcm93LmFwcGVuZCgnPHRkIGRhdGEtYWN0aW9uPVwic2VsZWN0TWludXRlXCIgY2xhc3M9XCJtaW51dGUnICsgKCF0aGlzLl9pc1ZhbGlkKGN1cnJlbnRNaW51dGUsICdtJykgPyAnIGRpc2FibGVkJyA6ICcnKSArICdcIj4nICsgY3VycmVudE1pbnV0ZS5mb3JtYXQoJ21tJykgKyAnPC90ZD4nKTtcbiAgICAgICAgICAgICAgICBjdXJyZW50TWludXRlLmFkZChzdGVwLCAnbScpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGFibGUuZW1wdHkoKS5hcHBlbmQoaHRtbCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgVGVtcHVzRG9taW51c0Jvb3RzdHJhcDQucHJvdG90eXBlLl9maWxsU2Vjb25kcyA9IGZ1bmN0aW9uIF9maWxsU2Vjb25kcygpIHtcbiAgICAgICAgICAgIHZhciB0YWJsZSA9IHRoaXMud2lkZ2V0LmZpbmQoJy50aW1lcGlja2VyLXNlY29uZHMgdGFibGUnKSxcbiAgICAgICAgICAgICAgICBjdXJyZW50U2Vjb25kID0gdGhpcy5fdmlld0RhdGUuY2xvbmUoKS5zdGFydE9mKCdtJyksXG4gICAgICAgICAgICAgICAgaHRtbCA9IFtdO1xuICAgICAgICAgICAgdmFyIHJvdyA9ICQoJzx0cj4nKTtcblxuICAgICAgICAgICAgd2hpbGUgKHRoaXMuX3ZpZXdEYXRlLmlzU2FtZShjdXJyZW50U2Vjb25kLCAnbScpKSB7XG4gICAgICAgICAgICAgICAgaWYgKGN1cnJlbnRTZWNvbmQuc2Vjb25kKCkgJSAyMCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICByb3cgPSAkKCc8dHI+Jyk7XG4gICAgICAgICAgICAgICAgICAgIGh0bWwucHVzaChyb3cpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByb3cuYXBwZW5kKCc8dGQgZGF0YS1hY3Rpb249XCJzZWxlY3RTZWNvbmRcIiBjbGFzcz1cInNlY29uZCcgKyAoIXRoaXMuX2lzVmFsaWQoY3VycmVudFNlY29uZCwgJ3MnKSA/ICcgZGlzYWJsZWQnIDogJycpICsgJ1wiPicgKyBjdXJyZW50U2Vjb25kLmZvcm1hdCgnc3MnKSArICc8L3RkPicpO1xuICAgICAgICAgICAgICAgIGN1cnJlbnRTZWNvbmQuYWRkKDUsICdzJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRhYmxlLmVtcHR5KCkuYXBwZW5kKGh0bWwpO1xuICAgICAgICB9O1xuXG4gICAgICAgIFRlbXB1c0RvbWludXNCb290c3RyYXA0LnByb3RvdHlwZS5fZmlsbFRpbWUgPSBmdW5jdGlvbiBfZmlsbFRpbWUoKSB7XG4gICAgICAgICAgICB2YXIgdG9nZ2xlID0gdm9pZCAwLFxuICAgICAgICAgICAgICAgIG5ld0RhdGUgPSB2b2lkIDA7XG4gICAgICAgICAgICB2YXIgdGltZUNvbXBvbmVudHMgPSB0aGlzLndpZGdldC5maW5kKCcudGltZXBpY2tlciBzcGFuW2RhdGEtdGltZS1jb21wb25lbnRdJyk7XG5cbiAgICAgICAgICAgIGlmICghdGhpcy51c2UyNEhvdXJzKSB7XG4gICAgICAgICAgICAgICAgdG9nZ2xlID0gdGhpcy53aWRnZXQuZmluZCgnLnRpbWVwaWNrZXIgW2RhdGEtYWN0aW9uPXRvZ2dsZVBlcmlvZF0nKTtcbiAgICAgICAgICAgICAgICBuZXdEYXRlID0gdGhpcy5fZ2V0TGFzdFBpY2tlZERhdGUoKS5jbG9uZSgpLmFkZCh0aGlzLl9nZXRMYXN0UGlja2VkRGF0ZSgpLmhvdXJzKCkgPj0gMTIgPyAtMTIgOiAxMiwgJ2gnKTtcblxuICAgICAgICAgICAgICAgIHRvZ2dsZS50ZXh0KHRoaXMuX2dldExhc3RQaWNrZWREYXRlKCkuZm9ybWF0KCdBJykpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuX2lzVmFsaWQobmV3RGF0ZSwgJ2gnKSkge1xuICAgICAgICAgICAgICAgICAgICB0b2dnbGUucmVtb3ZlQ2xhc3MoJ2Rpc2FibGVkJyk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdG9nZ2xlLmFkZENsYXNzKCdkaXNhYmxlZCcpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRpbWVDb21wb25lbnRzLmZpbHRlcignW2RhdGEtdGltZS1jb21wb25lbnQ9aG91cnNdJykudGV4dCh0aGlzLl9nZXRMYXN0UGlja2VkRGF0ZSgpLmZvcm1hdCgnJyArICh0aGlzLnVzZTI0SG91cnMgPyAnSEgnIDogJ2hoJykpKTtcbiAgICAgICAgICAgIHRpbWVDb21wb25lbnRzLmZpbHRlcignW2RhdGEtdGltZS1jb21wb25lbnQ9bWludXRlc10nKS50ZXh0KHRoaXMuX2dldExhc3RQaWNrZWREYXRlKCkuZm9ybWF0KCdtbScpKTtcbiAgICAgICAgICAgIHRpbWVDb21wb25lbnRzLmZpbHRlcignW2RhdGEtdGltZS1jb21wb25lbnQ9c2Vjb25kc10nKS50ZXh0KHRoaXMuX2dldExhc3RQaWNrZWREYXRlKCkuZm9ybWF0KCdzcycpKTtcblxuICAgICAgICAgICAgdGhpcy5fZmlsbEhvdXJzKCk7XG4gICAgICAgICAgICB0aGlzLl9maWxsTWludXRlcygpO1xuICAgICAgICAgICAgdGhpcy5fZmlsbFNlY29uZHMoKTtcbiAgICAgICAgfTtcblxuICAgICAgICBUZW1wdXNEb21pbnVzQm9vdHN0cmFwNC5wcm90b3R5cGUuX2RvQWN0aW9uID0gZnVuY3Rpb24gX2RvQWN0aW9uKGUsIGFjdGlvbikge1xuICAgICAgICAgICAgdmFyIGxhc3RQaWNrZWQgPSB0aGlzLl9nZXRMYXN0UGlja2VkRGF0ZSgpO1xuICAgICAgICAgICAgaWYgKCQoZS5jdXJyZW50VGFyZ2V0KS5pcygnLmRpc2FibGVkJykpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBhY3Rpb24gPSBhY3Rpb24gfHwgJChlLmN1cnJlbnRUYXJnZXQpLmRhdGEoJ2FjdGlvbicpO1xuICAgICAgICAgICAgc3dpdGNoIChhY3Rpb24pIHtcbiAgICAgICAgICAgICAgICBjYXNlICduZXh0JzpcbiAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG5hdkZuYyA9IERhdGVUaW1lUGlja2VyLkRhdGVQaWNrZXJNb2Rlc1t0aGlzLmN1cnJlbnRWaWV3TW9kZV0uTkFWX0ZVTkNUSU9OO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fdmlld0RhdGUuYWRkKERhdGVUaW1lUGlja2VyLkRhdGVQaWNrZXJNb2Rlc1t0aGlzLmN1cnJlbnRWaWV3TW9kZV0uTkFWX1NURVAsIG5hdkZuYyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9maWxsRGF0ZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fdmlld1VwZGF0ZShuYXZGbmMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjYXNlICdwcmV2aW91cyc6XG4gICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBfbmF2Rm5jID0gRGF0ZVRpbWVQaWNrZXIuRGF0ZVBpY2tlck1vZGVzW3RoaXMuY3VycmVudFZpZXdNb2RlXS5OQVZfRlVOQ1RJT047XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl92aWV3RGF0ZS5zdWJ0cmFjdChEYXRlVGltZVBpY2tlci5EYXRlUGlja2VyTW9kZXNbdGhpcy5jdXJyZW50Vmlld01vZGVdLk5BVl9TVEVQLCBfbmF2Rm5jKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2ZpbGxEYXRlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl92aWV3VXBkYXRlKF9uYXZGbmMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjYXNlICdwaWNrZXJTd2l0Y2gnOlxuICAgICAgICAgICAgICAgICAgICB0aGlzLl9zaG93TW9kZSgxKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnc2VsZWN0TW9udGgnOlxuICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgbW9udGggPSAkKGUudGFyZ2V0KS5jbG9zZXN0KCd0Ym9keScpLmZpbmQoJ3NwYW4nKS5pbmRleCgkKGUudGFyZ2V0KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl92aWV3RGF0ZS5tb250aChtb250aCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5jdXJyZW50Vmlld01vZGUgPT09IERhdGVUaW1lUGlja2VyLk1pblZpZXdNb2RlTnVtYmVyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fc2V0VmFsdWUobGFzdFBpY2tlZC5jbG9uZSgpLnllYXIodGhpcy5fdmlld0RhdGUueWVhcigpKS5tb250aCh0aGlzLl92aWV3RGF0ZS5tb250aCgpKSwgdGhpcy5fZ2V0TGFzdFBpY2tlZERhdGVJbmRleCgpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXRoaXMuX29wdGlvbnMuaW5saW5lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuaGlkZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fc2hvd01vZGUoLTEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2ZpbGxEYXRlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl92aWV3VXBkYXRlKCdNJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNhc2UgJ3NlbGVjdFllYXInOlxuICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgeWVhciA9IHBhcnNlSW50KCQoZS50YXJnZXQpLnRleHQoKSwgMTApIHx8IDA7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl92aWV3RGF0ZS55ZWFyKHllYXIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuY3VycmVudFZpZXdNb2RlID09PSBEYXRlVGltZVBpY2tlci5NaW5WaWV3TW9kZU51bWJlcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3NldFZhbHVlKGxhc3RQaWNrZWQuY2xvbmUoKS55ZWFyKHRoaXMuX3ZpZXdEYXRlLnllYXIoKSksIHRoaXMuX2dldExhc3RQaWNrZWREYXRlSW5kZXgoKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLl9vcHRpb25zLmlubGluZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmhpZGUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3Nob3dNb2RlKC0xKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9maWxsRGF0ZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fdmlld1VwZGF0ZSgnWVlZWScpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjYXNlICdzZWxlY3REZWNhZGUnOlxuICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgX3llYXIgPSBwYXJzZUludCgkKGUudGFyZ2V0KS5kYXRhKCdzZWxlY3Rpb24nKSwgMTApIHx8IDA7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl92aWV3RGF0ZS55ZWFyKF95ZWFyKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmN1cnJlbnRWaWV3TW9kZSA9PT0gRGF0ZVRpbWVQaWNrZXIuTWluVmlld01vZGVOdW1iZXIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9zZXRWYWx1ZShsYXN0UGlja2VkLmNsb25lKCkueWVhcih0aGlzLl92aWV3RGF0ZS55ZWFyKCkpLCB0aGlzLl9nZXRMYXN0UGlja2VkRGF0ZUluZGV4KCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghdGhpcy5fb3B0aW9ucy5pbmxpbmUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5oaWRlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9zaG93TW9kZSgtMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fZmlsbERhdGUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3ZpZXdVcGRhdGUoJ1lZWVknKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY2FzZSAnc2VsZWN0RGF5JzpcbiAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGRheSA9IHRoaXMuX3ZpZXdEYXRlLmNsb25lKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoJChlLnRhcmdldCkuaXMoJy5vbGQnKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRheS5zdWJ0cmFjdCgxLCAnTScpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCQoZS50YXJnZXQpLmlzKCcubmV3JykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXkuYWRkKDEsICdNJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9zZXRWYWx1ZShkYXkuZGF0ZShwYXJzZUludCgkKGUudGFyZ2V0KS50ZXh0KCksIDEwKSksIHRoaXMuX2dldExhc3RQaWNrZWREYXRlSW5kZXgoKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXRoaXMuX2hhc1RpbWUoKSAmJiAhdGhpcy5fb3B0aW9ucy5rZWVwT3BlbiAmJiAhdGhpcy5fb3B0aW9ucy5pbmxpbmUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmhpZGUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY2FzZSAnaW5jcmVtZW50SG91cnMnOlxuICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgbmV3RGF0ZSA9IGxhc3RQaWNrZWQuY2xvbmUoKS5hZGQoMSwgJ2gnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLl9pc1ZhbGlkKG5ld0RhdGUsICdoJykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9zZXRWYWx1ZShuZXdEYXRlLCB0aGlzLl9nZXRMYXN0UGlja2VkRGF0ZUluZGV4KCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjYXNlICdpbmNyZW1lbnRNaW51dGVzJzpcbiAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIF9uZXdEYXRlID0gbGFzdFBpY2tlZC5jbG9uZSgpLmFkZCh0aGlzLl9vcHRpb25zLnN0ZXBwaW5nLCAnbScpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuX2lzVmFsaWQoX25ld0RhdGUsICdtJykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9zZXRWYWx1ZShfbmV3RGF0ZSwgdGhpcy5fZ2V0TGFzdFBpY2tlZERhdGVJbmRleCgpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY2FzZSAnaW5jcmVtZW50U2Vjb25kcyc6XG4gICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBfbmV3RGF0ZTIgPSBsYXN0UGlja2VkLmNsb25lKCkuYWRkKDEsICdzJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5faXNWYWxpZChfbmV3RGF0ZTIsICdzJykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9zZXRWYWx1ZShfbmV3RGF0ZTIsIHRoaXMuX2dldExhc3RQaWNrZWREYXRlSW5kZXgoKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNhc2UgJ2RlY3JlbWVudEhvdXJzJzpcbiAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIF9uZXdEYXRlMyA9IGxhc3RQaWNrZWQuY2xvbmUoKS5zdWJ0cmFjdCgxLCAnaCcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuX2lzVmFsaWQoX25ld0RhdGUzLCAnaCcpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fc2V0VmFsdWUoX25ld0RhdGUzLCB0aGlzLl9nZXRMYXN0UGlja2VkRGF0ZUluZGV4KCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjYXNlICdkZWNyZW1lbnRNaW51dGVzJzpcbiAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIF9uZXdEYXRlNCA9IGxhc3RQaWNrZWQuY2xvbmUoKS5zdWJ0cmFjdCh0aGlzLl9vcHRpb25zLnN0ZXBwaW5nLCAnbScpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuX2lzVmFsaWQoX25ld0RhdGU0LCAnbScpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fc2V0VmFsdWUoX25ld0RhdGU0LCB0aGlzLl9nZXRMYXN0UGlja2VkRGF0ZUluZGV4KCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjYXNlICdkZWNyZW1lbnRTZWNvbmRzJzpcbiAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIF9uZXdEYXRlNSA9IGxhc3RQaWNrZWQuY2xvbmUoKS5zdWJ0cmFjdCgxLCAncycpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuX2lzVmFsaWQoX25ld0RhdGU1LCAncycpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fc2V0VmFsdWUoX25ld0RhdGU1LCB0aGlzLl9nZXRMYXN0UGlja2VkRGF0ZUluZGV4KCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjYXNlICd0b2dnbGVQZXJpb2QnOlxuICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9zZXRWYWx1ZShsYXN0UGlja2VkLmNsb25lKCkuYWRkKGxhc3RQaWNrZWQuaG91cnMoKSA+PSAxMiA/IC0xMiA6IDEyLCAnaCcpLCB0aGlzLl9nZXRMYXN0UGlja2VkRGF0ZUluZGV4KCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjYXNlICd0b2dnbGVQaWNrZXInOlxuICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgJHRoaXMgPSAkKGUudGFyZ2V0KSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkbGluayA9ICR0aGlzLmNsb3Nlc3QoJ2EnKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkcGFyZW50ID0gJHRoaXMuY2xvc2VzdCgndWwnKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBleHBhbmRlZCA9ICRwYXJlbnQuZmluZCgnLnNob3cnKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbG9zZWQgPSAkcGFyZW50LmZpbmQoJy5jb2xsYXBzZTpub3QoLnNob3cpJyksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJHNwYW4gPSAkdGhpcy5pcygnc3BhbicpID8gJHRoaXMgOiAkdGhpcy5maW5kKCdzcGFuJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgY29sbGFwc2VEYXRhID0gdm9pZCAwO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZXhwYW5kZWQgJiYgZXhwYW5kZWQubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sbGFwc2VEYXRhID0gZXhwYW5kZWQuZGF0YSgnY29sbGFwc2UnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoY29sbGFwc2VEYXRhICYmIGNvbGxhcHNlRGF0YS50cmFuc2l0aW9uaW5nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZXhwYW5kZWQuY29sbGFwc2UpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaWYgY29sbGFwc2UgcGx1Z2luIGlzIGF2YWlsYWJsZSB0aHJvdWdoIGJvb3RzdHJhcC5qcyB0aGVuIHVzZSBpdFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBleHBhbmRlZC5jb2xsYXBzZSgnaGlkZScpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbG9zZWQuY29sbGFwc2UoJ3Nob3cnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBvdGhlcndpc2UganVzdCB0b2dnbGUgaW4gY2xhc3Mgb24gdGhlIHR3byB2aWV3c1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBleHBhbmRlZC5yZW1vdmVDbGFzcygnc2hvdycpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbG9zZWQuYWRkQ2xhc3MoJ3Nob3cnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJHNwYW4udG9nZ2xlQ2xhc3ModGhpcy5fb3B0aW9ucy5pY29ucy50aW1lICsgJyAnICsgdGhpcy5fb3B0aW9ucy5pY29ucy5kYXRlKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICgkc3Bhbi5oYXNDbGFzcyh0aGlzLl9vcHRpb25zLmljb25zLmRhdGUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICRsaW5rLmF0dHIoJ3RpdGxlJywgdGhpcy5fb3B0aW9ucy50b29sdGlwcy5zZWxlY3REYXRlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkbGluay5hdHRyKCd0aXRsZScsIHRoaXMuX29wdGlvbnMudG9vbHRpcHMuc2VsZWN0VGltZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgJ3Nob3dQaWNrZXInOlxuICAgICAgICAgICAgICAgICAgICB0aGlzLndpZGdldC5maW5kKCcudGltZXBpY2tlciA+IGRpdjpub3QoLnRpbWVwaWNrZXItcGlja2VyKScpLmhpZGUoKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy53aWRnZXQuZmluZCgnLnRpbWVwaWNrZXIgLnRpbWVwaWNrZXItcGlja2VyJykuc2hvdygpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdzaG93SG91cnMnOlxuICAgICAgICAgICAgICAgICAgICB0aGlzLndpZGdldC5maW5kKCcudGltZXBpY2tlciAudGltZXBpY2tlci1waWNrZXInKS5oaWRlKCk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMud2lkZ2V0LmZpbmQoJy50aW1lcGlja2VyIC50aW1lcGlja2VyLWhvdXJzJykuc2hvdygpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdzaG93TWludXRlcyc6XG4gICAgICAgICAgICAgICAgICAgIHRoaXMud2lkZ2V0LmZpbmQoJy50aW1lcGlja2VyIC50aW1lcGlja2VyLXBpY2tlcicpLmhpZGUoKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy53aWRnZXQuZmluZCgnLnRpbWVwaWNrZXIgLnRpbWVwaWNrZXItbWludXRlcycpLnNob3coKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnc2hvd1NlY29uZHMnOlxuICAgICAgICAgICAgICAgICAgICB0aGlzLndpZGdldC5maW5kKCcudGltZXBpY2tlciAudGltZXBpY2tlci1waWNrZXInKS5oaWRlKCk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMud2lkZ2V0LmZpbmQoJy50aW1lcGlja2VyIC50aW1lcGlja2VyLXNlY29uZHMnKS5zaG93KCk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgJ3NlbGVjdEhvdXInOlxuICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgaG91ciA9IHBhcnNlSW50KCQoZS50YXJnZXQpLnRleHQoKSwgMTApO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXRoaXMudXNlMjRIb3Vycykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChsYXN0UGlja2VkLmhvdXJzKCkgPj0gMTIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGhvdXIgIT09IDEyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBob3VyICs9IDEyO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGhvdXIgPT09IDEyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBob3VyID0gMDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3NldFZhbHVlKGxhc3RQaWNrZWQuY2xvbmUoKS5ob3Vycyhob3VyKSwgdGhpcy5fZ2V0TGFzdFBpY2tlZERhdGVJbmRleCgpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghdGhpcy5faXNFbmFibGVkKCdtJykgJiYgIXRoaXMuX29wdGlvbnMua2VlcE9wZW4gJiYgIXRoaXMuX29wdGlvbnMuaW5saW5lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5oaWRlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2RvQWN0aW9uKGUsICdzaG93UGlja2VyJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNhc2UgJ3NlbGVjdE1pbnV0ZSc6XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX3NldFZhbHVlKGxhc3RQaWNrZWQuY2xvbmUoKS5taW51dGVzKHBhcnNlSW50KCQoZS50YXJnZXQpLnRleHQoKSwgMTApKSwgdGhpcy5fZ2V0TGFzdFBpY2tlZERhdGVJbmRleCgpKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLl9pc0VuYWJsZWQoJ3MnKSAmJiAhdGhpcy5fb3B0aW9ucy5rZWVwT3BlbiAmJiAhdGhpcy5fb3B0aW9ucy5pbmxpbmUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuaGlkZSgpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fZG9BY3Rpb24oZSwgJ3Nob3dQaWNrZXInKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdzZWxlY3RTZWNvbmQnOlxuICAgICAgICAgICAgICAgICAgICB0aGlzLl9zZXRWYWx1ZShsYXN0UGlja2VkLmNsb25lKCkuc2Vjb25kcyhwYXJzZUludCgkKGUudGFyZ2V0KS50ZXh0KCksIDEwKSksIHRoaXMuX2dldExhc3RQaWNrZWREYXRlSW5kZXgoKSk7XG4gICAgICAgICAgICAgICAgICAgIGlmICghdGhpcy5fb3B0aW9ucy5rZWVwT3BlbiAmJiAhdGhpcy5fb3B0aW9ucy5pbmxpbmUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuaGlkZSgpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fZG9BY3Rpb24oZSwgJ3Nob3dQaWNrZXInKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdjbGVhcic6XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY2xlYXIoKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnY2xvc2UnOlxuICAgICAgICAgICAgICAgICAgICB0aGlzLmhpZGUoKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAndG9kYXknOlxuICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgdG9kYXlzRGF0ZSA9IHRoaXMuZ2V0TW9tZW50KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5faXNWYWxpZCh0b2RheXNEYXRlLCAnZCcpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fc2V0VmFsdWUodG9kYXlzRGF0ZSwgdGhpcy5fZ2V0TGFzdFBpY2tlZERhdGVJbmRleCgpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH07XG5cbiAgICAgICAgLy9wdWJsaWNcblxuXG4gICAgICAgIFRlbXB1c0RvbWludXNCb290c3RyYXA0LnByb3RvdHlwZS5oaWRlID0gZnVuY3Rpb24gaGlkZSgpIHtcbiAgICAgICAgICAgIHZhciB0cmFuc2l0aW9uaW5nID0gZmFsc2U7XG4gICAgICAgICAgICBpZiAoIXRoaXMud2lkZ2V0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gSWdub3JlIGV2ZW50IGlmIGluIHRoZSBtaWRkbGUgb2YgYSBwaWNrZXIgdHJhbnNpdGlvblxuICAgICAgICAgICAgdGhpcy53aWRnZXQuZmluZCgnLmNvbGxhcHNlJykuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgdmFyIGNvbGxhcHNlRGF0YSA9ICQodGhpcykuZGF0YSgnY29sbGFwc2UnKTtcbiAgICAgICAgICAgICAgICBpZiAoY29sbGFwc2VEYXRhICYmIGNvbGxhcHNlRGF0YS50cmFuc2l0aW9uaW5nKSB7XG4gICAgICAgICAgICAgICAgICAgIHRyYW5zaXRpb25pbmcgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBpZiAodHJhbnNpdGlvbmluZykge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLmNvbXBvbmVudCAmJiB0aGlzLmNvbXBvbmVudC5oYXNDbGFzcygnYnRuJykpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbXBvbmVudC50b2dnbGVDbGFzcygnYWN0aXZlJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLndpZGdldC5oaWRlKCk7XG5cbiAgICAgICAgICAgICQod2luZG93KS5vZmYoJ3Jlc2l6ZScsIHRoaXMuX3BsYWNlKCkpO1xuICAgICAgICAgICAgdGhpcy53aWRnZXQub2ZmKCdjbGljaycsICdbZGF0YS1hY3Rpb25dJyk7XG4gICAgICAgICAgICB0aGlzLndpZGdldC5vZmYoJ21vdXNlZG93bicsIGZhbHNlKTtcblxuICAgICAgICAgICAgdGhpcy53aWRnZXQucmVtb3ZlKCk7XG4gICAgICAgICAgICB0aGlzLndpZGdldCA9IGZhbHNlO1xuXG4gICAgICAgICAgICB0aGlzLl9ub3RpZnlFdmVudCh7XG4gICAgICAgICAgICAgICAgdHlwZTogRGF0ZVRpbWVQaWNrZXIuRXZlbnQuSElERSxcbiAgICAgICAgICAgICAgICBkYXRlOiB0aGlzLl9nZXRMYXN0UGlja2VkRGF0ZSgpLmNsb25lKClcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5pbnB1dCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5pbnB1dC5ibHVyKCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuX3ZpZXdEYXRlID0gdGhpcy5fZ2V0TGFzdFBpY2tlZERhdGUoKS5jbG9uZSgpO1xuICAgICAgICB9O1xuXG4gICAgICAgIFRlbXB1c0RvbWludXNCb290c3RyYXA0LnByb3RvdHlwZS5zaG93ID0gZnVuY3Rpb24gc2hvdygpIHtcbiAgICAgICAgICAgIHZhciBjdXJyZW50TW9tZW50ID0gdm9pZCAwO1xuICAgICAgICAgICAgdmFyIHVzZUN1cnJlbnRHcmFudWxhcml0eSA9IHtcbiAgICAgICAgICAgICAgICAneWVhcic6IGZ1bmN0aW9uIHllYXIobSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbS5tb250aCgwKS5kYXRlKDEpLmhvdXJzKDApLnNlY29uZHMoMCkubWludXRlcygwKTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICdtb250aCc6IGZ1bmN0aW9uIG1vbnRoKG0pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG0uZGF0ZSgxKS5ob3VycygwKS5zZWNvbmRzKDApLm1pbnV0ZXMoMCk7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAnZGF5JzogZnVuY3Rpb24gZGF5KG0pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG0uaG91cnMoMCkuc2Vjb25kcygwKS5taW51dGVzKDApO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgJ2hvdXInOiBmdW5jdGlvbiBob3VyKG0pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG0uc2Vjb25kcygwKS5taW51dGVzKDApO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgJ21pbnV0ZSc6IGZ1bmN0aW9uIG1pbnV0ZShtKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBtLnNlY29uZHMoMCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgaWYgKHRoaXMuaW5wdXQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLmlucHV0LnByb3AoJ2Rpc2FibGVkJykgfHwgIXRoaXMuX29wdGlvbnMuaWdub3JlUmVhZG9ubHkgJiYgdGhpcy5pbnB1dC5wcm9wKCdyZWFkb25seScpIHx8IHRoaXMud2lkZ2V0KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuaW5wdXQudmFsKCkgIT09IHVuZGVmaW5lZCAmJiB0aGlzLmlucHV0LnZhbCgpLnRyaW0oKS5sZW5ndGggIT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fc2V0VmFsdWUodGhpcy5fcGFyc2VJbnB1dERhdGUodGhpcy5pbnB1dC52YWwoKS50cmltKCkpLCAwKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMudW5zZXQgJiYgdGhpcy5fb3B0aW9ucy51c2VDdXJyZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRNb21lbnQgPSB0aGlzLmdldE1vbWVudCgpO1xuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHRoaXMuX29wdGlvbnMudXNlQ3VycmVudCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnRNb21lbnQgPSB1c2VDdXJyZW50R3JhbnVsYXJpdHlbdGhpcy5fb3B0aW9ucy51c2VDdXJyZW50XShjdXJyZW50TW9tZW50KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB0aGlzLl9zZXRWYWx1ZShjdXJyZW50TW9tZW50LCAwKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMudW5zZXQgJiYgdGhpcy5fb3B0aW9ucy51c2VDdXJyZW50KSB7XG4gICAgICAgICAgICAgICAgY3VycmVudE1vbWVudCA9IHRoaXMuZ2V0TW9tZW50KCk7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiB0aGlzLl9vcHRpb25zLnVzZUN1cnJlbnQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRNb21lbnQgPSB1c2VDdXJyZW50R3JhbnVsYXJpdHlbdGhpcy5fb3B0aW9ucy51c2VDdXJyZW50XShjdXJyZW50TW9tZW50KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5fc2V0VmFsdWUoY3VycmVudE1vbWVudCwgMCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMud2lkZ2V0ID0gdGhpcy5fZ2V0VGVtcGxhdGUoKTtcblxuICAgICAgICAgICAgdGhpcy5fZmlsbERvdygpO1xuICAgICAgICAgICAgdGhpcy5fZmlsbE1vbnRocygpO1xuXG4gICAgICAgICAgICB0aGlzLndpZGdldC5maW5kKCcudGltZXBpY2tlci1ob3VycycpLmhpZGUoKTtcbiAgICAgICAgICAgIHRoaXMud2lkZ2V0LmZpbmQoJy50aW1lcGlja2VyLW1pbnV0ZXMnKS5oaWRlKCk7XG4gICAgICAgICAgICB0aGlzLndpZGdldC5maW5kKCcudGltZXBpY2tlci1zZWNvbmRzJykuaGlkZSgpO1xuXG4gICAgICAgICAgICB0aGlzLl91cGRhdGUoKTtcbiAgICAgICAgICAgIHRoaXMuX3Nob3dNb2RlKCk7XG5cbiAgICAgICAgICAgICQod2luZG93KS5vbigncmVzaXplJywgeyBwaWNrZXI6IHRoaXMgfSwgdGhpcy5fcGxhY2UpO1xuICAgICAgICAgICAgdGhpcy53aWRnZXQub24oJ2NsaWNrJywgJ1tkYXRhLWFjdGlvbl0nLCAkLnByb3h5KHRoaXMuX2RvQWN0aW9uLCB0aGlzKSk7IC8vIHRoaXMgaGFuZGxlcyBjbGlja3Mgb24gdGhlIHdpZGdldFxuICAgICAgICAgICAgdGhpcy53aWRnZXQub24oJ21vdXNlZG93bicsIGZhbHNlKTtcblxuICAgICAgICAgICAgaWYgKHRoaXMuY29tcG9uZW50ICYmIHRoaXMuY29tcG9uZW50Lmhhc0NsYXNzKCdidG4nKSkge1xuICAgICAgICAgICAgICAgIHRoaXMuY29tcG9uZW50LnRvZ2dsZUNsYXNzKCdhY3RpdmUnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX3BsYWNlKCk7XG4gICAgICAgICAgICB0aGlzLndpZGdldC5zaG93KCk7XG4gICAgICAgICAgICBpZiAodGhpcy5pbnB1dCAhPT0gdW5kZWZpbmVkICYmIHRoaXMuX29wdGlvbnMuZm9jdXNPblNob3cgJiYgIXRoaXMuaW5wdXQuaXMoJzpmb2N1cycpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5pbnB1dC5mb2N1cygpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLl9ub3RpZnlFdmVudCh7XG4gICAgICAgICAgICAgICAgdHlwZTogRGF0ZVRpbWVQaWNrZXIuRXZlbnQuU0hPV1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH07XG5cbiAgICAgICAgVGVtcHVzRG9taW51c0Jvb3RzdHJhcDQucHJvdG90eXBlLmRlc3Ryb3kgPSBmdW5jdGlvbiBkZXN0cm95KCkge1xuICAgICAgICAgICAgdGhpcy5oaWRlKCk7XG4gICAgICAgICAgICAvL3RvZG8gZG9jIG9mZj9cbiAgICAgICAgICAgIHRoaXMuX2VsZW1lbnQucmVtb3ZlRGF0YShEYXRlVGltZVBpY2tlci5EQVRBX0tFWSk7XG4gICAgICAgICAgICB0aGlzLl9lbGVtZW50LnJlbW92ZURhdGEoJ2RhdGUnKTtcbiAgICAgICAgfTtcblxuICAgICAgICBUZW1wdXNEb21pbnVzQm9vdHN0cmFwNC5wcm90b3R5cGUuZGlzYWJsZSA9IGZ1bmN0aW9uIGRpc2FibGUoKSB7XG4gICAgICAgICAgICB0aGlzLmhpZGUoKTtcbiAgICAgICAgICAgIGlmICh0aGlzLmNvbXBvbmVudCAmJiB0aGlzLmNvbXBvbmVudC5oYXNDbGFzcygnYnRuJykpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbXBvbmVudC5hZGRDbGFzcygnZGlzYWJsZWQnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLmlucHV0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmlucHV0LnByb3AoJ2Rpc2FibGVkJywgdHJ1ZSk7IC8vdG9kbyBkaXNhYmxlIHRoaXMvY29tcCBpZiBpbnB1dCBpcyBudWxsXG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgVGVtcHVzRG9taW51c0Jvb3RzdHJhcDQucHJvdG90eXBlLmVuYWJsZSA9IGZ1bmN0aW9uIGVuYWJsZSgpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLmNvbXBvbmVudCAmJiB0aGlzLmNvbXBvbmVudC5oYXNDbGFzcygnYnRuJykpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbXBvbmVudC5yZW1vdmVDbGFzcygnZGlzYWJsZWQnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLmlucHV0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmlucHV0LnByb3AoJ2Rpc2FibGVkJywgZmFsc2UpOyAvL3RvZG8gZW5hYmxlIGNvbXAvdGhpcyBpZiBpbnB1dCBpcyBudWxsXG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgVGVtcHVzRG9taW51c0Jvb3RzdHJhcDQucHJvdG90eXBlLnRvb2xiYXJQbGFjZW1lbnQgPSBmdW5jdGlvbiB0b29sYmFyUGxhY2VtZW50KF90b29sYmFyUGxhY2VtZW50KSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLnRvb2xiYXJQbGFjZW1lbnQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgX3Rvb2xiYXJQbGFjZW1lbnQgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigndG9vbGJhclBsYWNlbWVudCgpIGV4cGVjdHMgYSBzdHJpbmcgcGFyYW1ldGVyJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodG9vbGJhclBsYWNlbWVudHMuaW5kZXhPZihfdG9vbGJhclBsYWNlbWVudCkgPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigndG9vbGJhclBsYWNlbWVudCgpIHBhcmFtZXRlciBtdXN0IGJlIG9uZSBvZiAoJyArIHRvb2xiYXJQbGFjZW1lbnRzLmpvaW4oJywgJykgKyAnKSB2YWx1ZScpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy50b29sYmFyUGxhY2VtZW50ID0gX3Rvb2xiYXJQbGFjZW1lbnQ7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLndpZGdldCkge1xuICAgICAgICAgICAgICAgIHRoaXMuaGlkZSgpO1xuICAgICAgICAgICAgICAgIHRoaXMuc2hvdygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIFRlbXB1c0RvbWludXNCb290c3RyYXA0LnByb3RvdHlwZS53aWRnZXRQb3NpdGlvbmluZyA9IGZ1bmN0aW9uIHdpZGdldFBvc2l0aW9uaW5nKF93aWRnZXRQb3NpdGlvbmluZykge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJC5leHRlbmQoe30sIHRoaXMuX29wdGlvbnMud2lkZ2V0UG9zaXRpb25pbmcpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoe30udG9TdHJpbmcuY2FsbChfd2lkZ2V0UG9zaXRpb25pbmcpICE9PSAnW29iamVjdCBPYmplY3RdJykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ3dpZGdldFBvc2l0aW9uaW5nKCkgZXhwZWN0cyBhbiBvYmplY3QgdmFyaWFibGUnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChfd2lkZ2V0UG9zaXRpb25pbmcuaG9yaXpvbnRhbCkge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgX3dpZGdldFBvc2l0aW9uaW5nLmhvcml6b250YWwgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ3dpZGdldFBvc2l0aW9uaW5nKCkgaG9yaXpvbnRhbCB2YXJpYWJsZSBtdXN0IGJlIGEgc3RyaW5nJyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIF93aWRnZXRQb3NpdGlvbmluZy5ob3Jpem9udGFsID0gX3dpZGdldFBvc2l0aW9uaW5nLmhvcml6b250YWwudG9Mb3dlckNhc2UoKTtcbiAgICAgICAgICAgICAgICBpZiAoaG9yaXpvbnRhbE1vZGVzLmluZGV4T2YoX3dpZGdldFBvc2l0aW9uaW5nLmhvcml6b250YWwpID09PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCd3aWRnZXRQb3NpdGlvbmluZygpIGV4cGVjdHMgaG9yaXpvbnRhbCBwYXJhbWV0ZXIgdG8gYmUgb25lIG9mICgnICsgaG9yaXpvbnRhbE1vZGVzLmpvaW4oJywgJykgKyAnKScpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLl9vcHRpb25zLndpZGdldFBvc2l0aW9uaW5nLmhvcml6b250YWwgPSBfd2lkZ2V0UG9zaXRpb25pbmcuaG9yaXpvbnRhbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChfd2lkZ2V0UG9zaXRpb25pbmcudmVydGljYWwpIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIF93aWRnZXRQb3NpdGlvbmluZy52ZXJ0aWNhbCAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignd2lkZ2V0UG9zaXRpb25pbmcoKSB2ZXJ0aWNhbCB2YXJpYWJsZSBtdXN0IGJlIGEgc3RyaW5nJyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIF93aWRnZXRQb3NpdGlvbmluZy52ZXJ0aWNhbCA9IF93aWRnZXRQb3NpdGlvbmluZy52ZXJ0aWNhbC50b0xvd2VyQ2FzZSgpO1xuICAgICAgICAgICAgICAgIGlmICh2ZXJ0aWNhbE1vZGVzLmluZGV4T2YoX3dpZGdldFBvc2l0aW9uaW5nLnZlcnRpY2FsKSA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignd2lkZ2V0UG9zaXRpb25pbmcoKSBleHBlY3RzIHZlcnRpY2FsIHBhcmFtZXRlciB0byBiZSBvbmUgb2YgKCcgKyB2ZXJ0aWNhbE1vZGVzLmpvaW4oJywgJykgKyAnKScpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLl9vcHRpb25zLndpZGdldFBvc2l0aW9uaW5nLnZlcnRpY2FsID0gX3dpZGdldFBvc2l0aW9uaW5nLnZlcnRpY2FsO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fdXBkYXRlKCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgVGVtcHVzRG9taW51c0Jvb3RzdHJhcDQucHJvdG90eXBlLndpZGdldFBhcmVudCA9IGZ1bmN0aW9uIHdpZGdldFBhcmVudChfd2lkZ2V0UGFyZW50KSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLndpZGdldFBhcmVudDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBfd2lkZ2V0UGFyZW50ID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICAgIF93aWRnZXRQYXJlbnQgPSAkKF93aWRnZXRQYXJlbnQpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoX3dpZGdldFBhcmVudCAhPT0gbnVsbCAmJiB0eXBlb2YgX3dpZGdldFBhcmVudCAhPT0gJ3N0cmluZycgJiYgIShfd2lkZ2V0UGFyZW50IGluc3RhbmNlb2YgJCkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCd3aWRnZXRQYXJlbnQoKSBleHBlY3RzIGEgc3RyaW5nIG9yIGEgalF1ZXJ5IG9iamVjdCBwYXJhbWV0ZXInKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy53aWRnZXRQYXJlbnQgPSBfd2lkZ2V0UGFyZW50O1xuICAgICAgICAgICAgaWYgKHRoaXMud2lkZ2V0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5oaWRlKCk7XG4gICAgICAgICAgICAgICAgdGhpcy5zaG93KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgLy9zdGF0aWNcblxuXG4gICAgICAgIFRlbXB1c0RvbWludXNCb290c3RyYXA0Ll9qUXVlcnlIYW5kbGVUaGlzID0gZnVuY3Rpb24gX2pRdWVyeUhhbmRsZVRoaXMobWUsIG9wdGlvbiwgYXJndW1lbnQpIHtcbiAgICAgICAgICAgIHZhciBkYXRhID0gJChtZSkuZGF0YShEYXRlVGltZVBpY2tlci5EQVRBX0tFWSk7XG4gICAgICAgICAgICBpZiAoKHR5cGVvZiBvcHRpb24gPT09ICd1bmRlZmluZWQnID8gJ3VuZGVmaW5lZCcgOiBfdHlwZW9mKG9wdGlvbikpID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgICAgICQuZXh0ZW5kKHt9LCBEYXRlVGltZVBpY2tlci5EZWZhdWx0LCBvcHRpb24pO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoIWRhdGEpIHtcbiAgICAgICAgICAgICAgICBkYXRhID0gbmV3IFRlbXB1c0RvbWludXNCb290c3RyYXA0KCQobWUpLCBvcHRpb24pO1xuICAgICAgICAgICAgICAgICQobWUpLmRhdGEoRGF0ZVRpbWVQaWNrZXIuREFUQV9LRVksIGRhdGEpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodHlwZW9mIG9wdGlvbiA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICBpZiAoZGF0YVtvcHRpb25dID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdObyBtZXRob2QgbmFtZWQgXCInICsgb3B0aW9uICsgJ1wiJyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChhcmd1bWVudCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBkYXRhW29wdGlvbl0oKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZGF0YVtvcHRpb25dKGFyZ3VtZW50KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgVGVtcHVzRG9taW51c0Jvb3RzdHJhcDQuX2pRdWVyeUludGVyZmFjZSA9IGZ1bmN0aW9uIF9qUXVlcnlJbnRlcmZhY2Uob3B0aW9uLCBhcmd1bWVudCkge1xuICAgICAgICAgICAgaWYgKHRoaXMubGVuZ3RoID09PSAxKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFRlbXB1c0RvbWludXNCb290c3RyYXA0Ll9qUXVlcnlIYW5kbGVUaGlzKHRoaXNbMF0sIG9wdGlvbiwgYXJndW1lbnQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgVGVtcHVzRG9taW51c0Jvb3RzdHJhcDQuX2pRdWVyeUhhbmRsZVRoaXModGhpcywgb3B0aW9uLCBhcmd1bWVudCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfTtcblxuICAgICAgICByZXR1cm4gVGVtcHVzRG9taW51c0Jvb3RzdHJhcDQ7XG4gICAgfShEYXRlVGltZVBpY2tlcik7XG5cbiAgICAvKipcbiAgICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICogalF1ZXJ5XG4gICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAqL1xuXG5cbiAgICAkKGRvY3VtZW50KS5vbihEYXRlVGltZVBpY2tlci5FdmVudC5DTElDS19EQVRBX0FQSSwgRGF0ZVRpbWVQaWNrZXIuU2VsZWN0b3IuREFUQV9UT0dHTEUsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyICR0YXJnZXQgPSBnZXRTZWxlY3RvckZyb21FbGVtZW50KCQodGhpcykpO1xuICAgICAgICBpZiAoJHRhcmdldC5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBUZW1wdXNEb21pbnVzQm9vdHN0cmFwNC5falF1ZXJ5SW50ZXJmYWNlLmNhbGwoJHRhcmdldCwgJ3RvZ2dsZScpO1xuICAgIH0pLm9uKERhdGVUaW1lUGlja2VyLkV2ZW50LkNIQU5HRSwgJy4nICsgRGF0ZVRpbWVQaWNrZXIuQ2xhc3NOYW1lLklOUFVULCBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgdmFyICR0YXJnZXQgPSBnZXRTZWxlY3RvckZyb21FbGVtZW50KCQodGhpcykpO1xuICAgICAgICBpZiAoJHRhcmdldC5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBUZW1wdXNEb21pbnVzQm9vdHN0cmFwNC5falF1ZXJ5SW50ZXJmYWNlLmNhbGwoJHRhcmdldCwgJ19jaGFuZ2UnLCBldmVudCk7XG4gICAgfSkub24oRGF0ZVRpbWVQaWNrZXIuRXZlbnQuQkxVUiwgJy4nICsgRGF0ZVRpbWVQaWNrZXIuQ2xhc3NOYW1lLklOUFVULCBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgdmFyICR0YXJnZXQgPSBnZXRTZWxlY3RvckZyb21FbGVtZW50KCQodGhpcykpLFxuICAgICAgICAgICAgY29uZmlnID0gJHRhcmdldC5kYXRhKERhdGVUaW1lUGlja2VyLkRBVEFfS0VZKTtcbiAgICAgICAgaWYgKCR0YXJnZXQubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGNvbmZpZy5fb3B0aW9ucy5kZWJ1ZyB8fCB3aW5kb3cuZGVidWcpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBUZW1wdXNEb21pbnVzQm9vdHN0cmFwNC5falF1ZXJ5SW50ZXJmYWNlLmNhbGwoJHRhcmdldCwgJ2hpZGUnLCBldmVudCk7XG4gICAgfSkub24oRGF0ZVRpbWVQaWNrZXIuRXZlbnQuS0VZRE9XTiwgJy4nICsgRGF0ZVRpbWVQaWNrZXIuQ2xhc3NOYW1lLklOUFVULCBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgdmFyICR0YXJnZXQgPSBnZXRTZWxlY3RvckZyb21FbGVtZW50KCQodGhpcykpO1xuICAgICAgICBpZiAoJHRhcmdldC5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBUZW1wdXNEb21pbnVzQm9vdHN0cmFwNC5falF1ZXJ5SW50ZXJmYWNlLmNhbGwoJHRhcmdldCwgJ19rZXlkb3duJywgZXZlbnQpO1xuICAgIH0pLm9uKERhdGVUaW1lUGlja2VyLkV2ZW50LktFWVVQLCAnLicgKyBEYXRlVGltZVBpY2tlci5DbGFzc05hbWUuSU5QVVQsIGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICB2YXIgJHRhcmdldCA9IGdldFNlbGVjdG9yRnJvbUVsZW1lbnQoJCh0aGlzKSk7XG4gICAgICAgIGlmICgkdGFyZ2V0Lmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIFRlbXB1c0RvbWludXNCb290c3RyYXA0Ll9qUXVlcnlJbnRlcmZhY2UuY2FsbCgkdGFyZ2V0LCAnX2tleXVwJywgZXZlbnQpO1xuICAgIH0pLm9uKERhdGVUaW1lUGlja2VyLkV2ZW50LkZPQ1VTLCAnLicgKyBEYXRlVGltZVBpY2tlci5DbGFzc05hbWUuSU5QVVQsIGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICB2YXIgJHRhcmdldCA9IGdldFNlbGVjdG9yRnJvbUVsZW1lbnQoJCh0aGlzKSksXG4gICAgICAgICAgICBjb25maWcgPSAkdGFyZ2V0LmRhdGEoRGF0ZVRpbWVQaWNrZXIuREFUQV9LRVkpO1xuICAgICAgICBpZiAoJHRhcmdldC5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIWNvbmZpZy5fb3B0aW9ucy5hbGxvd0lucHV0VG9nZ2xlKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgVGVtcHVzRG9taW51c0Jvb3RzdHJhcDQuX2pRdWVyeUludGVyZmFjZS5jYWxsKCR0YXJnZXQsIGNvbmZpZywgZXZlbnQpO1xuICAgIH0pO1xuXG4gICAgJC5mbltEYXRlVGltZVBpY2tlci5OQU1FXSA9IFRlbXB1c0RvbWludXNCb290c3RyYXA0Ll9qUXVlcnlJbnRlcmZhY2U7XG4gICAgJC5mbltEYXRlVGltZVBpY2tlci5OQU1FXS5Db25zdHJ1Y3RvciA9IFRlbXB1c0RvbWludXNCb290c3RyYXA0O1xuICAgICQuZm5bRGF0ZVRpbWVQaWNrZXIuTkFNRV0ubm9Db25mbGljdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgJC5mbltEYXRlVGltZVBpY2tlci5OQU1FXSA9IEpRVUVSWV9OT19DT05GTElDVDtcbiAgICAgICAgcmV0dXJuIFRlbXB1c0RvbWludXNCb290c3RyYXA0Ll9qUXVlcnlJbnRlcmZhY2U7XG4gICAgfTtcblxuICAgIHJldHVybiBUZW1wdXNEb21pbnVzQm9vdHN0cmFwNDtcbn0oalF1ZXJ5KTtcblxufSgpO1xuIiwiLyohXG4qIGpxdWVyeS5pbnB1dG1hc2suYnVuZGxlLmpzXG4qIGh0dHBzOi8vZ2l0aHViLmNvbS9Sb2JpbkhlcmJvdHMvSW5wdXRtYXNrXG4qIENvcHlyaWdodCAoYykgMjAxMCAtIDIwMTcgUm9iaW4gSGVyYm90c1xuKiBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgKGh0dHA6Ly93d3cub3BlbnNvdXJjZS5vcmcvbGljZW5zZXMvbWl0LWxpY2Vuc2UucGhwKVxuKiBWZXJzaW9uOiAzLjMuMTFcbiovXG5cbiFmdW5jdGlvbihtb2R1bGVzKSB7XG4gICAgZnVuY3Rpb24gX193ZWJwYWNrX3JlcXVpcmVfXyhtb2R1bGVJZCkge1xuICAgICAgICBpZiAoaW5zdGFsbGVkTW9kdWxlc1ttb2R1bGVJZF0pIHJldHVybiBpbnN0YWxsZWRNb2R1bGVzW21vZHVsZUlkXS5leHBvcnRzO1xuICAgICAgICB2YXIgbW9kdWxlID0gaW5zdGFsbGVkTW9kdWxlc1ttb2R1bGVJZF0gPSB7XG4gICAgICAgICAgICBpOiBtb2R1bGVJZCxcbiAgICAgICAgICAgIGw6ICExLFxuICAgICAgICAgICAgZXhwb3J0czoge31cbiAgICAgICAgfTtcbiAgICAgICAgcmV0dXJuIG1vZHVsZXNbbW9kdWxlSWRdLmNhbGwobW9kdWxlLmV4cG9ydHMsIG1vZHVsZSwgbW9kdWxlLmV4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pLCBcbiAgICAgICAgbW9kdWxlLmwgPSAhMCwgbW9kdWxlLmV4cG9ydHM7XG4gICAgfVxuICAgIHZhciBpbnN0YWxsZWRNb2R1bGVzID0ge307XG4gICAgX193ZWJwYWNrX3JlcXVpcmVfXy5tID0gbW9kdWxlcywgX193ZWJwYWNrX3JlcXVpcmVfXy5jID0gaW5zdGFsbGVkTW9kdWxlcywgX193ZWJwYWNrX3JlcXVpcmVfXy5kID0gZnVuY3Rpb24oZXhwb3J0cywgbmFtZSwgZ2V0dGVyKSB7XG4gICAgICAgIF9fd2VicGFja19yZXF1aXJlX18ubyhleHBvcnRzLCBuYW1lKSB8fCBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgbmFtZSwge1xuICAgICAgICAgICAgY29uZmlndXJhYmxlOiAhMSxcbiAgICAgICAgICAgIGVudW1lcmFibGU6ICEwLFxuICAgICAgICAgICAgZ2V0OiBnZXR0ZXJcbiAgICAgICAgfSk7XG4gICAgfSwgX193ZWJwYWNrX3JlcXVpcmVfXy5uID0gZnVuY3Rpb24obW9kdWxlKSB7XG4gICAgICAgIHZhciBnZXR0ZXIgPSBtb2R1bGUgJiYgbW9kdWxlLl9fZXNNb2R1bGUgPyBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHJldHVybiBtb2R1bGUuZGVmYXVsdDtcbiAgICAgICAgfSA6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgcmV0dXJuIG1vZHVsZTtcbiAgICAgICAgfTtcbiAgICAgICAgcmV0dXJuIF9fd2VicGFja19yZXF1aXJlX18uZChnZXR0ZXIsIFwiYVwiLCBnZXR0ZXIpLCBnZXR0ZXI7XG4gICAgfSwgX193ZWJwYWNrX3JlcXVpcmVfXy5vID0gZnVuY3Rpb24ob2JqZWN0LCBwcm9wZXJ0eSkge1xuICAgICAgICByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG9iamVjdCwgcHJvcGVydHkpO1xuICAgIH0sIF9fd2VicGFja19yZXF1aXJlX18ucCA9IFwiXCIsIF9fd2VicGFja19yZXF1aXJlX18oX193ZWJwYWNrX3JlcXVpcmVfXy5zID0gMyk7XG59KFsgZnVuY3Rpb24obW9kdWxlLCBleHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSB7XG4gICAgXCJ1c2Ugc3RyaWN0XCI7XG4gICAgdmFyIF9fV0VCUEFDS19BTURfREVGSU5FX0ZBQ1RPUllfXywgX19XRUJQQUNLX0FNRF9ERUZJTkVfQVJSQVlfXywgX19XRUJQQUNLX0FNRF9ERUZJTkVfUkVTVUxUX187XG4gICAgXCJmdW5jdGlvblwiID09IHR5cGVvZiBTeW1ib2wgJiYgU3ltYm9sLml0ZXJhdG9yO1xuICAgICFmdW5jdGlvbihmYWN0b3J5KSB7XG4gICAgICAgIF9fV0VCUEFDS19BTURfREVGSU5FX0FSUkFZX18gPSBbIF9fd2VicGFja19yZXF1aXJlX18oMikgXSwgdm9pZCAwICE9PSAoX19XRUJQQUNLX0FNRF9ERUZJTkVfUkVTVUxUX18gPSBcImZ1bmN0aW9uXCIgPT0gdHlwZW9mIChfX1dFQlBBQ0tfQU1EX0RFRklORV9GQUNUT1JZX18gPSBmYWN0b3J5KSA/IF9fV0VCUEFDS19BTURfREVGSU5FX0ZBQ1RPUllfXy5hcHBseShleHBvcnRzLCBfX1dFQlBBQ0tfQU1EX0RFRklORV9BUlJBWV9fKSA6IF9fV0VCUEFDS19BTURfREVGSU5FX0ZBQ1RPUllfXykgJiYgKG1vZHVsZS5leHBvcnRzID0gX19XRUJQQUNLX0FNRF9ERUZJTkVfUkVTVUxUX18pO1xuICAgIH0oZnVuY3Rpb24oJCkge1xuICAgICAgICByZXR1cm4gJDtcbiAgICB9KTtcbn0sIGZ1bmN0aW9uKG1vZHVsZSwgZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykge1xuICAgIFwidXNlIHN0cmljdFwiO1xuICAgIHZhciBfX1dFQlBBQ0tfQU1EX0RFRklORV9GQUNUT1JZX18sIF9fV0VCUEFDS19BTURfREVGSU5FX0FSUkFZX18sIF9fV0VCUEFDS19BTURfREVGSU5FX1JFU1VMVF9fLCBfdHlwZW9mID0gXCJmdW5jdGlvblwiID09IHR5cGVvZiBTeW1ib2wgJiYgXCJzeW1ib2xcIiA9PSB0eXBlb2YgU3ltYm9sLml0ZXJhdG9yID8gZnVuY3Rpb24ob2JqKSB7XG4gICAgICAgIHJldHVybiB0eXBlb2Ygb2JqO1xuICAgIH0gOiBmdW5jdGlvbihvYmopIHtcbiAgICAgICAgcmV0dXJuIG9iaiAmJiBcImZ1bmN0aW9uXCIgPT0gdHlwZW9mIFN5bWJvbCAmJiBvYmouY29uc3RydWN0b3IgPT09IFN5bWJvbCAmJiBvYmogIT09IFN5bWJvbC5wcm90b3R5cGUgPyBcInN5bWJvbFwiIDogdHlwZW9mIG9iajtcbiAgICB9O1xuICAgICFmdW5jdGlvbihmYWN0b3J5KSB7XG4gICAgICAgIF9fV0VCUEFDS19BTURfREVGSU5FX0FSUkFZX18gPSBbIF9fd2VicGFja19yZXF1aXJlX18oMCksIF9fd2VicGFja19yZXF1aXJlX18oMTApLCBfX3dlYnBhY2tfcmVxdWlyZV9fKDExKSBdLCBcbiAgICAgICAgdm9pZCAwICE9PSAoX19XRUJQQUNLX0FNRF9ERUZJTkVfUkVTVUxUX18gPSBcImZ1bmN0aW9uXCIgPT0gdHlwZW9mIChfX1dFQlBBQ0tfQU1EX0RFRklORV9GQUNUT1JZX18gPSBmYWN0b3J5KSA/IF9fV0VCUEFDS19BTURfREVGSU5FX0ZBQ1RPUllfXy5hcHBseShleHBvcnRzLCBfX1dFQlBBQ0tfQU1EX0RFRklORV9BUlJBWV9fKSA6IF9fV0VCUEFDS19BTURfREVGSU5FX0ZBQ1RPUllfXykgJiYgKG1vZHVsZS5leHBvcnRzID0gX19XRUJQQUNLX0FNRF9ERUZJTkVfUkVTVUxUX18pO1xuICAgIH0oZnVuY3Rpb24oJCwgd2luZG93LCBkb2N1bWVudCwgdW5kZWZpbmVkKSB7XG4gICAgICAgIGZ1bmN0aW9uIElucHV0bWFzayhhbGlhcywgb3B0aW9ucywgaW50ZXJuYWwpIHtcbiAgICAgICAgICAgIGlmICghKHRoaXMgaW5zdGFuY2VvZiBJbnB1dG1hc2spKSByZXR1cm4gbmV3IElucHV0bWFzayhhbGlhcywgb3B0aW9ucywgaW50ZXJuYWwpO1xuICAgICAgICAgICAgdGhpcy5lbCA9IHVuZGVmaW5lZCwgdGhpcy5ldmVudHMgPSB7fSwgdGhpcy5tYXNrc2V0ID0gdW5kZWZpbmVkLCB0aGlzLnJlZnJlc2hWYWx1ZSA9ICExLCBcbiAgICAgICAgICAgICEwICE9PSBpbnRlcm5hbCAmJiAoJC5pc1BsYWluT2JqZWN0KGFsaWFzKSA/IG9wdGlvbnMgPSBhbGlhcyA6IChvcHRpb25zID0gb3B0aW9ucyB8fCB7fSkuYWxpYXMgPSBhbGlhcywgXG4gICAgICAgICAgICB0aGlzLm9wdHMgPSAkLmV4dGVuZCghMCwge30sIHRoaXMuZGVmYXVsdHMsIG9wdGlvbnMpLCB0aGlzLm5vTWFza3NDYWNoZSA9IG9wdGlvbnMgJiYgb3B0aW9ucy5kZWZpbml0aW9ucyAhPT0gdW5kZWZpbmVkLCBcbiAgICAgICAgICAgIHRoaXMudXNlck9wdGlvbnMgPSBvcHRpb25zIHx8IHt9LCB0aGlzLmlzUlRMID0gdGhpcy5vcHRzLm51bWVyaWNJbnB1dCwgcmVzb2x2ZUFsaWFzKHRoaXMub3B0cy5hbGlhcywgb3B0aW9ucywgdGhpcy5vcHRzKSk7XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gcmVzb2x2ZUFsaWFzKGFsaWFzU3RyLCBvcHRpb25zLCBvcHRzKSB7XG4gICAgICAgICAgICB2YXIgYWxpYXNEZWZpbml0aW9uID0gSW5wdXRtYXNrLnByb3RvdHlwZS5hbGlhc2VzW2FsaWFzU3RyXTtcbiAgICAgICAgICAgIHJldHVybiBhbGlhc0RlZmluaXRpb24gPyAoYWxpYXNEZWZpbml0aW9uLmFsaWFzICYmIHJlc29sdmVBbGlhcyhhbGlhc0RlZmluaXRpb24uYWxpYXMsIHVuZGVmaW5lZCwgb3B0cyksIFxuICAgICAgICAgICAgJC5leHRlbmQoITAsIG9wdHMsIGFsaWFzRGVmaW5pdGlvbiksICQuZXh0ZW5kKCEwLCBvcHRzLCBvcHRpb25zKSwgITApIDogKG51bGwgPT09IG9wdHMubWFzayAmJiAob3B0cy5tYXNrID0gYWxpYXNTdHIpLCBcbiAgICAgICAgICAgICExKTtcbiAgICAgICAgfVxuICAgICAgICBmdW5jdGlvbiBnZW5lcmF0ZU1hc2tTZXQob3B0cywgbm9jYWNoZSkge1xuICAgICAgICAgICAgZnVuY3Rpb24gZ2VuZXJhdGVNYXNrKG1hc2ssIG1ldGFkYXRhLCBvcHRzKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlZ2V4TWFzayA9ICExO1xuICAgICAgICAgICAgICAgIGlmIChudWxsICE9PSBtYXNrICYmIFwiXCIgIT09IG1hc2sgfHwgKChyZWdleE1hc2sgPSBudWxsICE9PSBvcHRzLnJlZ2V4KSA/IG1hc2sgPSAobWFzayA9IG9wdHMucmVnZXgpLnJlcGxhY2UoL14oXFxeKSguKikoXFwkKSQvLCBcIiQyXCIpIDogKHJlZ2V4TWFzayA9ICEwLCBcbiAgICAgICAgICAgICAgICBtYXNrID0gXCIuKlwiKSksIDEgPT09IG1hc2subGVuZ3RoICYmICExID09PSBvcHRzLmdyZWVkeSAmJiAwICE9PSBvcHRzLnJlcGVhdCAmJiAob3B0cy5wbGFjZWhvbGRlciA9IFwiXCIpLCBcbiAgICAgICAgICAgICAgICBvcHRzLnJlcGVhdCA+IDAgfHwgXCIqXCIgPT09IG9wdHMucmVwZWF0IHx8IFwiK1wiID09PSBvcHRzLnJlcGVhdCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcmVwZWF0U3RhcnQgPSBcIipcIiA9PT0gb3B0cy5yZXBlYXQgPyAwIDogXCIrXCIgPT09IG9wdHMucmVwZWF0ID8gMSA6IG9wdHMucmVwZWF0O1xuICAgICAgICAgICAgICAgICAgICBtYXNrID0gb3B0cy5ncm91cG1hcmtlci5zdGFydCArIG1hc2sgKyBvcHRzLmdyb3VwbWFya2VyLmVuZCArIG9wdHMucXVhbnRpZmllcm1hcmtlci5zdGFydCArIHJlcGVhdFN0YXJ0ICsgXCIsXCIgKyBvcHRzLnJlcGVhdCArIG9wdHMucXVhbnRpZmllcm1hcmtlci5lbmQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciBtYXNrc2V0RGVmaW5pdGlvbiwgbWFza2RlZktleSA9IHJlZ2V4TWFzayA/IFwicmVnZXhfXCIgKyBvcHRzLnJlZ2V4IDogb3B0cy5udW1lcmljSW5wdXQgPyBtYXNrLnNwbGl0KFwiXCIpLnJldmVyc2UoKS5qb2luKFwiXCIpIDogbWFzaztcbiAgICAgICAgICAgICAgICByZXR1cm4gSW5wdXRtYXNrLnByb3RvdHlwZS5tYXNrc0NhY2hlW21hc2tkZWZLZXldID09PSB1bmRlZmluZWQgfHwgITAgPT09IG5vY2FjaGUgPyAobWFza3NldERlZmluaXRpb24gPSB7XG4gICAgICAgICAgICAgICAgICAgIG1hc2s6IG1hc2ssXG4gICAgICAgICAgICAgICAgICAgIG1hc2tUb2tlbjogSW5wdXRtYXNrLnByb3RvdHlwZS5hbmFseXNlTWFzayhtYXNrLCByZWdleE1hc2ssIG9wdHMpLFxuICAgICAgICAgICAgICAgICAgICB2YWxpZFBvc2l0aW9uczoge30sXG4gICAgICAgICAgICAgICAgICAgIF9idWZmZXI6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgICAgICAgICAgYnVmZmVyOiB1bmRlZmluZWQsXG4gICAgICAgICAgICAgICAgICAgIHRlc3RzOiB7fSxcbiAgICAgICAgICAgICAgICAgICAgbWV0YWRhdGE6IG1ldGFkYXRhLFxuICAgICAgICAgICAgICAgICAgICBtYXNrTGVuZ3RoOiB1bmRlZmluZWRcbiAgICAgICAgICAgICAgICB9LCAhMCAhPT0gbm9jYWNoZSAmJiAoSW5wdXRtYXNrLnByb3RvdHlwZS5tYXNrc0NhY2hlW21hc2tkZWZLZXldID0gbWFza3NldERlZmluaXRpb24sIFxuICAgICAgICAgICAgICAgIG1hc2tzZXREZWZpbml0aW9uID0gJC5leHRlbmQoITAsIHt9LCBJbnB1dG1hc2sucHJvdG90eXBlLm1hc2tzQ2FjaGVbbWFza2RlZktleV0pKSkgOiBtYXNrc2V0RGVmaW5pdGlvbiA9ICQuZXh0ZW5kKCEwLCB7fSwgSW5wdXRtYXNrLnByb3RvdHlwZS5tYXNrc0NhY2hlW21hc2tkZWZLZXldKSwgXG4gICAgICAgICAgICAgICAgbWFza3NldERlZmluaXRpb247XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoJC5pc0Z1bmN0aW9uKG9wdHMubWFzaykgJiYgKG9wdHMubWFzayA9IG9wdHMubWFzayhvcHRzKSksICQuaXNBcnJheShvcHRzLm1hc2spKSB7XG4gICAgICAgICAgICAgICAgaWYgKG9wdHMubWFzay5sZW5ndGggPiAxKSB7XG4gICAgICAgICAgICAgICAgICAgIG9wdHMua2VlcFN0YXRpYyA9IG51bGwgPT09IG9wdHMua2VlcFN0YXRpYyB8fCBvcHRzLmtlZXBTdGF0aWM7XG4gICAgICAgICAgICAgICAgICAgIHZhciBhbHRNYXNrID0gb3B0cy5ncm91cG1hcmtlci5zdGFydDtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICQuZWFjaChvcHRzLm51bWVyaWNJbnB1dCA/IG9wdHMubWFzay5yZXZlcnNlKCkgOiBvcHRzLm1hc2ssIGZ1bmN0aW9uKG5keCwgbXNrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhbHRNYXNrLmxlbmd0aCA+IDEgJiYgKGFsdE1hc2sgKz0gb3B0cy5ncm91cG1hcmtlci5lbmQgKyBvcHRzLmFsdGVybmF0b3JtYXJrZXIgKyBvcHRzLmdyb3VwbWFya2VyLnN0YXJ0KSwgXG4gICAgICAgICAgICAgICAgICAgICAgICBtc2subWFzayA9PT0gdW5kZWZpbmVkIHx8ICQuaXNGdW5jdGlvbihtc2subWFzaykgPyBhbHRNYXNrICs9IG1zayA6IGFsdE1hc2sgKz0gbXNrLm1hc2s7XG4gICAgICAgICAgICAgICAgICAgIH0pLCBhbHRNYXNrICs9IG9wdHMuZ3JvdXBtYXJrZXIuZW5kLCBnZW5lcmF0ZU1hc2soYWx0TWFzaywgb3B0cy5tYXNrLCBvcHRzKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgb3B0cy5tYXNrID0gb3B0cy5tYXNrLnBvcCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG9wdHMubWFzayAmJiBvcHRzLm1hc2subWFzayAhPT0gdW5kZWZpbmVkICYmICEkLmlzRnVuY3Rpb24ob3B0cy5tYXNrLm1hc2spID8gZ2VuZXJhdGVNYXNrKG9wdHMubWFzay5tYXNrLCBvcHRzLm1hc2ssIG9wdHMpIDogZ2VuZXJhdGVNYXNrKG9wdHMubWFzaywgb3B0cy5tYXNrLCBvcHRzKTtcbiAgICAgICAgfVxuICAgICAgICBmdW5jdGlvbiBtYXNrU2NvcGUoYWN0aW9uT2JqLCBtYXNrc2V0LCBvcHRzKSB7XG4gICAgICAgICAgICBmdW5jdGlvbiBnZXRNYXNrVGVtcGxhdGUoYmFzZU9uSW5wdXQsIG1pbmltYWxQb3MsIGluY2x1ZGVNb2RlKSB7XG4gICAgICAgICAgICAgICAgbWluaW1hbFBvcyA9IG1pbmltYWxQb3MgfHwgMDtcbiAgICAgICAgICAgICAgICB2YXIgbmR4SW50bHpyLCB0ZXN0LCB0ZXN0UG9zLCBtYXNrVGVtcGxhdGUgPSBbXSwgcG9zID0gMCwgbHZwID0gZ2V0TGFzdFZhbGlkUG9zaXRpb24oKTtcbiAgICAgICAgICAgICAgICBkbyB7XG4gICAgICAgICAgICAgICAgICAgICEwID09PSBiYXNlT25JbnB1dCAmJiBnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnNbcG9zXSA/ICh0ZXN0ID0gKHRlc3RQb3MgPSBnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnNbcG9zXSkubWF0Y2gsIFxuICAgICAgICAgICAgICAgICAgICBuZHhJbnRsenIgPSB0ZXN0UG9zLmxvY2F0b3Iuc2xpY2UoKSwgbWFza1RlbXBsYXRlLnB1c2goITAgPT09IGluY2x1ZGVNb2RlID8gdGVzdFBvcy5pbnB1dCA6ICExID09PSBpbmNsdWRlTW9kZSA/IHRlc3QubmF0aXZlRGVmIDogZ2V0UGxhY2Vob2xkZXIocG9zLCB0ZXN0KSkpIDogKHRlc3QgPSAodGVzdFBvcyA9IGdldFRlc3RUZW1wbGF0ZShwb3MsIG5keEludGx6ciwgcG9zIC0gMSkpLm1hdGNoLCBcbiAgICAgICAgICAgICAgICAgICAgbmR4SW50bHpyID0gdGVzdFBvcy5sb2NhdG9yLnNsaWNlKCksICghMSA9PT0gb3B0cy5qaXRNYXNraW5nIHx8IHBvcyA8IGx2cCB8fCBcIm51bWJlclwiID09IHR5cGVvZiBvcHRzLmppdE1hc2tpbmcgJiYgaXNGaW5pdGUob3B0cy5qaXRNYXNraW5nKSAmJiBvcHRzLmppdE1hc2tpbmcgPiBwb3MpICYmIG1hc2tUZW1wbGF0ZS5wdXNoKCExID09PSBpbmNsdWRlTW9kZSA/IHRlc3QubmF0aXZlRGVmIDogZ2V0UGxhY2Vob2xkZXIocG9zLCB0ZXN0KSkpLCBcbiAgICAgICAgICAgICAgICAgICAgcG9zKys7XG4gICAgICAgICAgICAgICAgfSB3aGlsZSAoKG1heExlbmd0aCA9PT0gdW5kZWZpbmVkIHx8IHBvcyA8IG1heExlbmd0aCkgJiYgKG51bGwgIT09IHRlc3QuZm4gfHwgXCJcIiAhPT0gdGVzdC5kZWYpIHx8IG1pbmltYWxQb3MgPiBwb3MpO1xuICAgICAgICAgICAgICAgIHJldHVybiBcIlwiID09PSBtYXNrVGVtcGxhdGVbbWFza1RlbXBsYXRlLmxlbmd0aCAtIDFdICYmIG1hc2tUZW1wbGF0ZS5wb3AoKSwgZ2V0TWFza1NldCgpLm1hc2tMZW5ndGggPSBwb3MgKyAxLCBcbiAgICAgICAgICAgICAgICBtYXNrVGVtcGxhdGU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmdW5jdGlvbiBnZXRNYXNrU2V0KCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBtYXNrc2V0O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZnVuY3Rpb24gcmVzZXRNYXNrU2V0KHNvZnQpIHtcbiAgICAgICAgICAgICAgICB2YXIgbWFza3NldCA9IGdldE1hc2tTZXQoKTtcbiAgICAgICAgICAgICAgICBtYXNrc2V0LmJ1ZmZlciA9IHVuZGVmaW5lZCwgITAgIT09IHNvZnQgJiYgKG1hc2tzZXQudmFsaWRQb3NpdGlvbnMgPSB7fSwgbWFza3NldC5wID0gMCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmdW5jdGlvbiBnZXRMYXN0VmFsaWRQb3NpdGlvbihjbG9zZXN0VG8sIHN0cmljdCwgdmFsaWRQb3NpdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgYmVmb3JlID0gLTEsIGFmdGVyID0gLTEsIHZhbGlkcyA9IHZhbGlkUG9zaXRpb25zIHx8IGdldE1hc2tTZXQoKS52YWxpZFBvc2l0aW9ucztcbiAgICAgICAgICAgICAgICBjbG9zZXN0VG8gPT09IHVuZGVmaW5lZCAmJiAoY2xvc2VzdFRvID0gLTEpO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIHBvc05keCBpbiB2YWxpZHMpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHBzTmR4ID0gcGFyc2VJbnQocG9zTmR4KTtcbiAgICAgICAgICAgICAgICAgICAgdmFsaWRzW3BzTmR4XSAmJiAoc3RyaWN0IHx8ICEwICE9PSB2YWxpZHNbcHNOZHhdLmdlbmVyYXRlZElucHV0KSAmJiAocHNOZHggPD0gY2xvc2VzdFRvICYmIChiZWZvcmUgPSBwc05keCksIFxuICAgICAgICAgICAgICAgICAgICBwc05keCA+PSBjbG9zZXN0VG8gJiYgKGFmdGVyID0gcHNOZHgpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIC0xICE9PSBiZWZvcmUgJiYgY2xvc2VzdFRvIC0gYmVmb3JlID4gMSB8fCBhZnRlciA8IGNsb3Nlc3RUbyA/IGJlZm9yZSA6IGFmdGVyO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZnVuY3Rpb24gc3RyaXBWYWxpZFBvc2l0aW9ucyhzdGFydCwgZW5kLCBub2NoZWNrLCBzdHJpY3QpIHtcbiAgICAgICAgICAgICAgICB2YXIgaSwgc3RhcnRQb3MgPSBzdGFydCwgcG9zaXRpb25zQ2xvbmUgPSAkLmV4dGVuZCghMCwge30sIGdldE1hc2tTZXQoKS52YWxpZFBvc2l0aW9ucyksIG5lZWRzVmFsaWRhdGlvbiA9ICExO1xuICAgICAgICAgICAgICAgIGZvciAoZ2V0TWFza1NldCgpLnAgPSBzdGFydCwgaSA9IGVuZCAtIDE7IGkgPj0gc3RhcnRQb3M7IGktLSkgZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zW2ldICE9PSB1bmRlZmluZWQgJiYgKCEwICE9PSBub2NoZWNrICYmICghZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zW2ldLm1hdGNoLm9wdGlvbmFsaXR5ICYmIGZ1bmN0aW9uKHBvcykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcG9zTWF0Y2ggPSBnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnNbcG9zXTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHBvc01hdGNoICE9PSB1bmRlZmluZWQgJiYgbnVsbCA9PT0gcG9zTWF0Y2gubWF0Y2guZm4pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwcmV2TWF0Y2ggPSBnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnNbcG9zIC0gMV0sIG5leHRNYXRjaCA9IGdldE1hc2tTZXQoKS52YWxpZFBvc2l0aW9uc1twb3MgKyAxXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBwcmV2TWF0Y2ggIT09IHVuZGVmaW5lZCAmJiBuZXh0TWF0Y2ggIT09IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gITE7XG4gICAgICAgICAgICAgICAgfShpKSB8fCAhMSA9PT0gb3B0cy5jYW5DbGVhclBvc2l0aW9uKGdldE1hc2tTZXQoKSwgaSwgZ2V0TGFzdFZhbGlkUG9zaXRpb24oKSwgc3RyaWN0LCBvcHRzKSkgfHwgZGVsZXRlIGdldE1hc2tTZXQoKS52YWxpZFBvc2l0aW9uc1tpXSk7XG4gICAgICAgICAgICAgICAgZm9yIChyZXNldE1hc2tTZXQoITApLCBpID0gc3RhcnRQb3MgKyAxOyBpIDw9IGdldExhc3RWYWxpZFBvc2l0aW9uKCk7ICkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKDtnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnNbc3RhcnRQb3NdICE9PSB1bmRlZmluZWQ7ICkgc3RhcnRQb3MrKztcbiAgICAgICAgICAgICAgICAgICAgaWYgKGkgPCBzdGFydFBvcyAmJiAoaSA9IHN0YXJ0UG9zICsgMSksIGdldE1hc2tTZXQoKS52YWxpZFBvc2l0aW9uc1tpXSA9PT0gdW5kZWZpbmVkICYmIGlzTWFzayhpKSkgaSsrOyBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciB0ID0gZ2V0VGVzdFRlbXBsYXRlKGkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgITEgPT09IG5lZWRzVmFsaWRhdGlvbiAmJiBwb3NpdGlvbnNDbG9uZVtzdGFydFBvc10gJiYgcG9zaXRpb25zQ2xvbmVbc3RhcnRQb3NdLm1hdGNoLmRlZiA9PT0gdC5tYXRjaC5kZWYgPyAoZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zW3N0YXJ0UG9zXSA9ICQuZXh0ZW5kKCEwLCB7fSwgcG9zaXRpb25zQ2xvbmVbc3RhcnRQb3NdKSwgXG4gICAgICAgICAgICAgICAgICAgICAgICBnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnNbc3RhcnRQb3NdLmlucHV0ID0gdC5pbnB1dCwgZGVsZXRlIGdldE1hc2tTZXQoKS52YWxpZFBvc2l0aW9uc1tpXSwgXG4gICAgICAgICAgICAgICAgICAgICAgICBpKyspIDogcG9zaXRpb25DYW5NYXRjaERlZmluaXRpb24oc3RhcnRQb3MsIHQubWF0Y2guZGVmKSA/ICExICE9PSBpc1ZhbGlkKHN0YXJ0UG9zLCB0LmlucHV0IHx8IGdldFBsYWNlaG9sZGVyKGkpLCAhMCkgJiYgKGRlbGV0ZSBnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnNbaV0sIFxuICAgICAgICAgICAgICAgICAgICAgICAgaSsrLCBuZWVkc1ZhbGlkYXRpb24gPSAhMCkgOiBpc01hc2soaSkgfHwgKGkrKywgc3RhcnRQb3MtLSksIHN0YXJ0UG9zKys7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmVzZXRNYXNrU2V0KCEwKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRldGVybWluZVRlc3RUZW1wbGF0ZSh0ZXN0cywgZ3Vlc3NOZXh0QmVzdCkge1xuICAgICAgICAgICAgICAgIGZvciAodmFyIHRlc3RQb3MsIHRlc3RQb3NpdGlvbnMgPSB0ZXN0cywgbHZwID0gZ2V0TGFzdFZhbGlkUG9zaXRpb24oKSwgbHZUZXN0ID0gZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zW2x2cF0gfHwgZ2V0VGVzdHMoMClbMF0sIGx2VGVzdEFsdEFyciA9IGx2VGVzdC5hbHRlcm5hdGlvbiAhPT0gdW5kZWZpbmVkID8gbHZUZXN0LmxvY2F0b3JbbHZUZXN0LmFsdGVybmF0aW9uXS50b1N0cmluZygpLnNwbGl0KFwiLFwiKSA6IFtdLCBuZHggPSAwOyBuZHggPCB0ZXN0UG9zaXRpb25zLmxlbmd0aCAmJiAoISgodGVzdFBvcyA9IHRlc3RQb3NpdGlvbnNbbmR4XSkubWF0Y2ggJiYgKG9wdHMuZ3JlZWR5ICYmICEwICE9PSB0ZXN0UG9zLm1hdGNoLm9wdGlvbmFsUXVhbnRpZmllciB8fCAoITEgPT09IHRlc3RQb3MubWF0Y2gub3B0aW9uYWxpdHkgfHwgITEgPT09IHRlc3RQb3MubWF0Y2gubmV3QmxvY2tNYXJrZXIpICYmICEwICE9PSB0ZXN0UG9zLm1hdGNoLm9wdGlvbmFsUXVhbnRpZmllcikgJiYgKGx2VGVzdC5hbHRlcm5hdGlvbiA9PT0gdW5kZWZpbmVkIHx8IGx2VGVzdC5hbHRlcm5hdGlvbiAhPT0gdGVzdFBvcy5hbHRlcm5hdGlvbiB8fCB0ZXN0UG9zLmxvY2F0b3JbbHZUZXN0LmFsdGVybmF0aW9uXSAhPT0gdW5kZWZpbmVkICYmIGNoZWNrQWx0ZXJuYXRpb25NYXRjaCh0ZXN0UG9zLmxvY2F0b3JbbHZUZXN0LmFsdGVybmF0aW9uXS50b1N0cmluZygpLnNwbGl0KFwiLFwiKSwgbHZUZXN0QWx0QXJyKSkpIHx8ICEwID09PSBndWVzc05leHRCZXN0ICYmIChudWxsICE9PSB0ZXN0UG9zLm1hdGNoLmZuIHx8IC9bMC05YS1iQS1aXS8udGVzdCh0ZXN0UG9zLm1hdGNoLmRlZikpKTsgbmR4KyspIDtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGVzdFBvcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZ1bmN0aW9uIGdldFRlc3RUZW1wbGF0ZShwb3MsIG5keEludGx6ciwgdHN0UHMpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zW3Bvc10gfHwgZGV0ZXJtaW5lVGVzdFRlbXBsYXRlKGdldFRlc3RzKHBvcywgbmR4SW50bHpyID8gbmR4SW50bHpyLnNsaWNlKCkgOiBuZHhJbnRsenIsIHRzdFBzKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmdW5jdGlvbiBnZXRUZXN0KHBvcykge1xuICAgICAgICAgICAgICAgIHJldHVybiBnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnNbcG9zXSA/IGdldE1hc2tTZXQoKS52YWxpZFBvc2l0aW9uc1twb3NdIDogZ2V0VGVzdHMocG9zKVswXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBvc2l0aW9uQ2FuTWF0Y2hEZWZpbml0aW9uKHBvcywgZGVmKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgdmFsaWQgPSAhMSwgdGVzdHMgPSBnZXRUZXN0cyhwb3MpLCB0bmR4ID0gMDsgdG5keCA8IHRlc3RzLmxlbmd0aDsgdG5keCsrKSBpZiAodGVzdHNbdG5keF0ubWF0Y2ggJiYgdGVzdHNbdG5keF0ubWF0Y2guZGVmID09PSBkZWYpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFsaWQgPSAhMDtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiB2YWxpZDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZ1bmN0aW9uIGdldFRlc3RzKHBvcywgbmR4SW50bHpyLCB0c3RQcykge1xuICAgICAgICAgICAgICAgIGZ1bmN0aW9uIHJlc29sdmVUZXN0RnJvbVRva2VuKG1hc2tUb2tlbiwgbmR4SW5pdGlhbGl6ZXIsIGxvb3BOZHgsIHF1YW50aWZpZXJSZWN1cnNlKSB7XG4gICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uIGhhbmRsZU1hdGNoKG1hdGNoLCBsb29wTmR4LCBxdWFudGlmaWVyUmVjdXJzZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZnVuY3Rpb24gaXNGaXJzdE1hdGNoKGxhdGVzdE1hdGNoLCB0b2tlbkdyb3VwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGZpcnN0TWF0Y2ggPSAwID09PSAkLmluQXJyYXkobGF0ZXN0TWF0Y2gsIHRva2VuR3JvdXAubWF0Y2hlcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZpcnN0TWF0Y2ggfHwgJC5lYWNoKHRva2VuR3JvdXAubWF0Y2hlcywgZnVuY3Rpb24obmR4LCBtYXRjaCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoITAgPT09IG1hdGNoLmlzUXVhbnRpZmllciAmJiAoZmlyc3RNYXRjaCA9IGlzRmlyc3RNYXRjaChsYXRlc3RNYXRjaCwgdG9rZW5Hcm91cC5tYXRjaGVzW25keCAtIDFdKSkpIHJldHVybiAhMTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KSwgZmlyc3RNYXRjaDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uIHJlc29sdmVOZHhJbml0aWFsaXplcihwb3MsIGFsdGVybmF0ZU5keCwgdGFyZ2V0QWx0ZXJuYXRpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgYmVzdE1hdGNoLCBpbmRleFBvcztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zW3BvcyAtIDFdICYmIHRhcmdldEFsdGVybmF0aW9uICYmIGdldE1hc2tTZXQoKS50ZXN0c1twb3NdKSBmb3IgKHZhciB2cEFsdGVybmF0aW9uID0gZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zW3BvcyAtIDFdLmxvY2F0b3IsIHRwQWx0ZXJuYXRpb24gPSBnZXRNYXNrU2V0KCkudGVzdHNbcG9zXVswXS5sb2NhdG9yLCBpID0gMDsgaSA8IHRhcmdldEFsdGVybmF0aW9uOyBpKyspIGlmICh2cEFsdGVybmF0aW9uW2ldICE9PSB0cEFsdGVybmF0aW9uW2ldKSByZXR1cm4gdnBBbHRlcm5hdGlvbi5zbGljZSh0YXJnZXRBbHRlcm5hdGlvbiArIDEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAoZ2V0TWFza1NldCgpLnRlc3RzW3Bvc10gfHwgZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zW3Bvc10pICYmICQuZWFjaChnZXRNYXNrU2V0KCkudGVzdHNbcG9zXSB8fCBbIGdldE1hc2tTZXQoKS52YWxpZFBvc2l0aW9uc1twb3NdIF0sIGZ1bmN0aW9uKG5keCwgbG1udCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgYWx0ZXJuYXRpb24gPSB0YXJnZXRBbHRlcm5hdGlvbiAhPT0gdW5kZWZpbmVkID8gdGFyZ2V0QWx0ZXJuYXRpb24gOiBsbW50LmFsdGVybmF0aW9uLCBuZHhQb3MgPSBsbW50LmxvY2F0b3JbYWx0ZXJuYXRpb25dICE9PSB1bmRlZmluZWQgPyBsbW50LmxvY2F0b3JbYWx0ZXJuYXRpb25dLnRvU3RyaW5nKCkuaW5kZXhPZihhbHRlcm5hdGVOZHgpIDogLTE7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChpbmRleFBvcyA9PT0gdW5kZWZpbmVkIHx8IG5keFBvcyA8IGluZGV4UG9zKSAmJiAtMSAhPT0gbmR4UG9zICYmIChiZXN0TWF0Y2ggPSBsbW50LCBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXhQb3MgPSBuZHhQb3MpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pLCBiZXN0TWF0Y2ggPyBiZXN0TWF0Y2gubG9jYXRvci5zbGljZSgodGFyZ2V0QWx0ZXJuYXRpb24gIT09IHVuZGVmaW5lZCA/IHRhcmdldEFsdGVybmF0aW9uIDogYmVzdE1hdGNoLmFsdGVybmF0aW9uKSArIDEpIDogdGFyZ2V0QWx0ZXJuYXRpb24gIT09IHVuZGVmaW5lZCA/IHJlc29sdmVOZHhJbml0aWFsaXplcihwb3MsIGFsdGVybmF0ZU5keCkgOiB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodGVzdFBvcyA+IDFlNCkgdGhyb3cgXCJJbnB1dG1hc2s6IFRoZXJlIGlzIHByb2JhYmx5IGFuIGVycm9yIGluIHlvdXIgbWFzayBkZWZpbml0aW9uIG9yIGluIHRoZSBjb2RlLiBDcmVhdGUgYW4gaXNzdWUgb24gZ2l0aHViIHdpdGggYW4gZXhhbXBsZSBvZiB0aGUgbWFzayB5b3UgYXJlIHVzaW5nLiBcIiArIGdldE1hc2tTZXQoKS5tYXNrO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRlc3RQb3MgPT09IHBvcyAmJiBtYXRjaC5tYXRjaGVzID09PSB1bmRlZmluZWQpIHJldHVybiBtYXRjaGVzLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoOiBtYXRjaCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb2NhdG9yOiBsb29wTmR4LnJldmVyc2UoKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjZDogY2FjaGVEZXBlbmRlbmN5XG4gICAgICAgICAgICAgICAgICAgICAgICB9KSwgITA7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobWF0Y2gubWF0Y2hlcyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG1hdGNoLmlzR3JvdXAgJiYgcXVhbnRpZmllclJlY3Vyc2UgIT09IG1hdGNoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtYXRjaCA9IGhhbmRsZU1hdGNoKG1hc2tUb2tlbi5tYXRjaGVzWyQuaW5BcnJheShtYXRjaCwgbWFza1Rva2VuLm1hdGNoZXMpICsgMV0sIGxvb3BOZHgpKSByZXR1cm4gITA7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChtYXRjaC5pc09wdGlvbmFsKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBvcHRpb25hbFRva2VuID0gbWF0Y2g7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtYXRjaCA9IHJlc29sdmVUZXN0RnJvbVRva2VuKG1hdGNoLCBuZHhJbml0aWFsaXplciwgbG9vcE5keCwgcXVhbnRpZmllclJlY3Vyc2UpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAobGF0ZXN0TWF0Y2ggPSBtYXRjaGVzW21hdGNoZXMubGVuZ3RoIC0gMV0ubWF0Y2gsICFpc0ZpcnN0TWF0Y2gobGF0ZXN0TWF0Y2gsIG9wdGlvbmFsVG9rZW4pKSByZXR1cm4gITA7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRTdG9wID0gITAsIHRlc3RQb3MgPSBwb3M7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKG1hdGNoLmlzQWx0ZXJuYXRvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgbWFsdE1hdGNoZXMsIGFsdGVybmF0ZVRva2VuID0gbWF0Y2gsIG1hbHRlcm5hdGVNYXRjaGVzID0gW10sIGN1cnJlbnRNYXRjaGVzID0gbWF0Y2hlcy5zbGljZSgpLCBsb29wTmR4Q250ID0gbG9vcE5keC5sZW5ndGgsIGFsdEluZGV4ID0gbmR4SW5pdGlhbGl6ZXIubGVuZ3RoID4gMCA/IG5keEluaXRpYWxpemVyLnNoaWZ0KCkgOiAtMTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKC0xID09PSBhbHRJbmRleCB8fCBcInN0cmluZ1wiID09IHR5cGVvZiBhbHRJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGFtbmR4LCBjdXJyZW50UG9zID0gdGVzdFBvcywgbmR4SW5pdGlhbGl6ZXJDbG9uZSA9IG5keEluaXRpYWxpemVyLnNsaWNlKCksIGFsdEluZGV4QXJyID0gW107XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoXCJzdHJpbmdcIiA9PSB0eXBlb2YgYWx0SW5kZXgpIGFsdEluZGV4QXJyID0gYWx0SW5kZXguc3BsaXQoXCIsXCIpOyBlbHNlIGZvciAoYW1uZHggPSAwOyBhbW5keCA8IGFsdGVybmF0ZVRva2VuLm1hdGNoZXMubGVuZ3RoOyBhbW5keCsrKSBhbHRJbmRleEFyci5wdXNoKGFtbmR4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIG5keCA9IDA7IG5keCA8IGFsdEluZGV4QXJyLmxlbmd0aDsgbmR4KyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoYW1uZHggPSBwYXJzZUludChhbHRJbmRleEFycltuZHhdKSwgbWF0Y2hlcyA9IFtdLCBuZHhJbml0aWFsaXplciA9IHJlc29sdmVOZHhJbml0aWFsaXplcih0ZXN0UG9zLCBhbW5keCwgbG9vcE5keENudCkgfHwgbmR4SW5pdGlhbGl6ZXJDbG9uZS5zbGljZSgpLCBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAhMCAhPT0gKG1hdGNoID0gaGFuZGxlTWF0Y2goYWx0ZXJuYXRlVG9rZW4ubWF0Y2hlc1thbW5keF0gfHwgbWFza1Rva2VuLm1hdGNoZXNbYW1uZHhdLCBbIGFtbmR4IF0uY29uY2F0KGxvb3BOZHgpLCBxdWFudGlmaWVyUmVjdXJzZSkgfHwgbWF0Y2gpICYmIG1hdGNoICE9PSB1bmRlZmluZWQgJiYgYWx0SW5kZXhBcnJbYWx0SW5kZXhBcnIubGVuZ3RoIC0gMV0gPCBhbHRlcm5hdGVUb2tlbi5tYXRjaGVzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgbnRuZHggPSAkLmluQXJyYXkobWF0Y2gsIG1hc2tUb2tlbi5tYXRjaGVzKSArIDE7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hc2tUb2tlbi5tYXRjaGVzLmxlbmd0aCA+IG50bmR4ICYmIChtYXRjaCA9IGhhbmRsZU1hdGNoKG1hc2tUb2tlbi5tYXRjaGVzW250bmR4XSwgWyBudG5keCBdLmNvbmNhdChsb29wTmR4LnNsaWNlKDEsIGxvb3BOZHgubGVuZ3RoKSksIHF1YW50aWZpZXJSZWN1cnNlKSkgJiYgKGFsdEluZGV4QXJyLnB1c2gobnRuZHgudG9TdHJpbmcoKSksIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkLmVhY2gobWF0Y2hlcywgZnVuY3Rpb24obmR4LCBsbW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsbW50LmFsdGVybmF0aW9uID0gbG9vcE5keC5sZW5ndGggLSAxO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hbHRNYXRjaGVzID0gbWF0Y2hlcy5zbGljZSgpLCB0ZXN0UG9zID0gY3VycmVudFBvcywgbWF0Y2hlcyA9IFtdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIG5keDEgPSAwOyBuZHgxIDwgbWFsdE1hdGNoZXMubGVuZ3RoOyBuZHgxKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGFsdE1hdGNoID0gbWFsdE1hdGNoZXNbbmR4MV0sIGRyb3BNYXRjaCA9ICExO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbHRNYXRjaC5hbHRlcm5hdGlvbiA9IGFsdE1hdGNoLmFsdGVybmF0aW9uIHx8IGxvb3BOZHhDbnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIG5keDIgPSAwOyBuZHgyIDwgbWFsdGVybmF0ZU1hdGNoZXMubGVuZ3RoOyBuZHgyKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBhbHRNYXRjaDIgPSBtYWx0ZXJuYXRlTWF0Y2hlc1tuZHgyXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChcInN0cmluZ1wiICE9IHR5cGVvZiBhbHRJbmRleCB8fCAtMSAhPT0gJC5pbkFycmF5KGFsdE1hdGNoLmxvY2F0b3JbYWx0TWF0Y2guYWx0ZXJuYXRpb25dLnRvU3RyaW5nKCksIGFsdEluZGV4QXJyKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChmdW5jdGlvbihzb3VyY2UsIHRhcmdldCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gc291cmNlLm1hdGNoLm5hdGl2ZURlZiA9PT0gdGFyZ2V0Lm1hdGNoLm5hdGl2ZURlZiB8fCBzb3VyY2UubWF0Y2guZGVmID09PSB0YXJnZXQubWF0Y2gubmF0aXZlRGVmIHx8IHNvdXJjZS5tYXRjaC5uYXRpdmVEZWYgPT09IHRhcmdldC5tYXRjaC5kZWY7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfShhbHRNYXRjaCwgYWx0TWF0Y2gyKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkcm9wTWF0Y2ggPSAhMCwgYWx0TWF0Y2guYWx0ZXJuYXRpb24gPT09IGFsdE1hdGNoMi5hbHRlcm5hdGlvbiAmJiAtMSA9PT0gYWx0TWF0Y2gyLmxvY2F0b3JbYWx0TWF0Y2gyLmFsdGVybmF0aW9uXS50b1N0cmluZygpLmluZGV4T2YoYWx0TWF0Y2gubG9jYXRvclthbHRNYXRjaC5hbHRlcm5hdGlvbl0pICYmIChhbHRNYXRjaDIubG9jYXRvclthbHRNYXRjaDIuYWx0ZXJuYXRpb25dID0gYWx0TWF0Y2gyLmxvY2F0b3JbYWx0TWF0Y2gyLmFsdGVybmF0aW9uXSArIFwiLFwiICsgYWx0TWF0Y2gubG9jYXRvclthbHRNYXRjaC5hbHRlcm5hdGlvbl0sIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbHRNYXRjaDIuYWx0ZXJuYXRpb24gPSBhbHRNYXRjaC5hbHRlcm5hdGlvbiksIGFsdE1hdGNoLm1hdGNoLm5hdGl2ZURlZiA9PT0gYWx0TWF0Y2gyLm1hdGNoLmRlZiAmJiAoYWx0TWF0Y2gubG9jYXRvclthbHRNYXRjaC5hbHRlcm5hdGlvbl0gPSBhbHRNYXRjaDIubG9jYXRvclthbHRNYXRjaDIuYWx0ZXJuYXRpb25dLCBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFsdGVybmF0ZU1hdGNoZXMuc3BsaWNlKG1hbHRlcm5hdGVNYXRjaGVzLmluZGV4T2YoYWx0TWF0Y2gyKSwgMSwgYWx0TWF0Y2gpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhbHRNYXRjaC5tYXRjaC5kZWYgPT09IGFsdE1hdGNoMi5tYXRjaC5kZWYpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZHJvcE1hdGNoID0gITE7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZnVuY3Rpb24oc291cmNlLCB0YXJnZXQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bGwgPT09IHNvdXJjZS5tYXRjaC5mbiAmJiBudWxsICE9PSB0YXJnZXQubWF0Y2guZm4gJiYgdGFyZ2V0Lm1hdGNoLmZuLnRlc3Qoc291cmNlLm1hdGNoLmRlZiwgZ2V0TWFza1NldCgpLCBwb3MsICExLCBvcHRzLCAhMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfShhbHRNYXRjaCwgYWx0TWF0Y2gyKSB8fCBmdW5jdGlvbihzb3VyY2UsIHRhcmdldCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVsbCAhPT0gc291cmNlLm1hdGNoLmZuICYmIG51bGwgIT09IHRhcmdldC5tYXRjaC5mbiAmJiB0YXJnZXQubWF0Y2guZm4udGVzdChzb3VyY2UubWF0Y2guZGVmLnJlcGxhY2UoL1tcXFtcXF1dL2csIFwiXCIpLCBnZXRNYXNrU2V0KCksIHBvcywgITEsIG9wdHMsICExKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KGFsdE1hdGNoLCBhbHRNYXRjaDIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFsdE1hdGNoLmFsdGVybmF0aW9uID09PSBhbHRNYXRjaDIuYWx0ZXJuYXRpb24gJiYgLTEgPT09IGFsdE1hdGNoLmxvY2F0b3JbYWx0TWF0Y2guYWx0ZXJuYXRpb25dLnRvU3RyaW5nKCkuaW5kZXhPZihhbHRNYXRjaDIubG9jYXRvclthbHRNYXRjaDIuYWx0ZXJuYXRpb25dLnRvU3RyaW5nKCkuc3BsaXQoXCJcIilbMF0pICYmIChhbHRNYXRjaC5uYSA9IGFsdE1hdGNoLm5hIHx8IGFsdE1hdGNoLmxvY2F0b3JbYWx0TWF0Y2guYWx0ZXJuYXRpb25dLnRvU3RyaW5nKCksIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAtMSA9PT0gYWx0TWF0Y2gubmEuaW5kZXhPZihhbHRNYXRjaC5sb2NhdG9yW2FsdE1hdGNoLmFsdGVybmF0aW9uXS50b1N0cmluZygpLnNwbGl0KFwiXCIpWzBdKSAmJiAoYWx0TWF0Y2gubmEgPSBhbHRNYXRjaC5uYSArIFwiLFwiICsgYWx0TWF0Y2gubG9jYXRvclthbHRNYXRjaDIuYWx0ZXJuYXRpb25dLnRvU3RyaW5nKCkuc3BsaXQoXCJcIilbMF0pLCBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZHJvcE1hdGNoID0gITAsIGFsdE1hdGNoLmxvY2F0b3JbYWx0TWF0Y2guYWx0ZXJuYXRpb25dID0gYWx0TWF0Y2gyLmxvY2F0b3JbYWx0TWF0Y2gyLmFsdGVybmF0aW9uXS50b1N0cmluZygpLnNwbGl0KFwiXCIpWzBdICsgXCIsXCIgKyBhbHRNYXRjaC5sb2NhdG9yW2FsdE1hdGNoLmFsdGVybmF0aW9uXSwgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hbHRlcm5hdGVNYXRjaGVzLnNwbGljZShtYWx0ZXJuYXRlTWF0Y2hlcy5pbmRleE9mKGFsdE1hdGNoMiksIDAsIGFsdE1hdGNoKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkcm9wTWF0Y2ggfHwgbWFsdGVybmF0ZU1hdGNoZXMucHVzaChhbHRNYXRjaCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJzdHJpbmdcIiA9PSB0eXBlb2YgYWx0SW5kZXggJiYgKG1hbHRlcm5hdGVNYXRjaGVzID0gJC5tYXAobWFsdGVybmF0ZU1hdGNoZXMsIGZ1bmN0aW9uKGxtbnQsIG5keCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc0Zpbml0ZShuZHgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBhbHRlcm5hdGlvbiA9IGxtbnQuYWx0ZXJuYXRpb24sIGFsdExvY0FyciA9IGxtbnQubG9jYXRvclthbHRlcm5hdGlvbl0udG9TdHJpbmcoKS5zcGxpdChcIixcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxtbnQubG9jYXRvclthbHRlcm5hdGlvbl0gPSB1bmRlZmluZWQsIGxtbnQuYWx0ZXJuYXRpb24gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGFsbmR4ID0gMDsgYWxuZHggPCBhbHRMb2NBcnIubGVuZ3RoOyBhbG5keCsrKSAtMSAhPT0gJC5pbkFycmF5KGFsdExvY0FyclthbG5keF0sIGFsdEluZGV4QXJyKSAmJiAobG1udC5sb2NhdG9yW2FsdGVybmF0aW9uXSAhPT0gdW5kZWZpbmVkID8gKGxtbnQubG9jYXRvclthbHRlcm5hdGlvbl0gKz0gXCIsXCIsIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsbW50LmxvY2F0b3JbYWx0ZXJuYXRpb25dICs9IGFsdExvY0FyclthbG5keF0pIDogbG1udC5sb2NhdG9yW2FsdGVybmF0aW9uXSA9IHBhcnNlSW50KGFsdExvY0FyclthbG5keF0pLCBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbG1udC5hbHRlcm5hdGlvbiA9IGFsdGVybmF0aW9uKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGxtbnQubG9jYXRvclthbHRlcm5hdGlvbl0gIT09IHVuZGVmaW5lZCkgcmV0dXJuIGxtbnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSkpLCBtYXRjaGVzID0gY3VycmVudE1hdGNoZXMuY29uY2F0KG1hbHRlcm5hdGVNYXRjaGVzKSwgdGVzdFBvcyA9IHBvcywgaW5zZXJ0U3RvcCA9IG1hdGNoZXMubGVuZ3RoID4gMCwgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRjaCA9IG1hbHRlcm5hdGVNYXRjaGVzLmxlbmd0aCA+IDAsIG5keEluaXRpYWxpemVyID0gbmR4SW5pdGlhbGl6ZXJDbG9uZS5zbGljZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgbWF0Y2ggPSBoYW5kbGVNYXRjaChhbHRlcm5hdGVUb2tlbi5tYXRjaGVzW2FsdEluZGV4XSB8fCBtYXNrVG9rZW4ubWF0Y2hlc1thbHRJbmRleF0sIFsgYWx0SW5kZXggXS5jb25jYXQobG9vcE5keCksIHF1YW50aWZpZXJSZWN1cnNlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG1hdGNoKSByZXR1cm4gITA7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChtYXRjaC5pc1F1YW50aWZpZXIgJiYgcXVhbnRpZmllclJlY3Vyc2UgIT09IG1hc2tUb2tlbi5tYXRjaGVzWyQuaW5BcnJheShtYXRjaCwgbWFza1Rva2VuLm1hdGNoZXMpIC0gMV0pIGZvciAodmFyIHF0ID0gbWF0Y2gsIHFuZHggPSBuZHhJbml0aWFsaXplci5sZW5ndGggPiAwID8gbmR4SW5pdGlhbGl6ZXIuc2hpZnQoKSA6IDA7IHFuZHggPCAoaXNOYU4ocXQucXVhbnRpZmllci5tYXgpID8gcW5keCArIDEgOiBxdC5xdWFudGlmaWVyLm1heCkgJiYgdGVzdFBvcyA8PSBwb3M7IHFuZHgrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgdG9rZW5Hcm91cCA9IG1hc2tUb2tlbi5tYXRjaGVzWyQuaW5BcnJheShxdCwgbWFza1Rva2VuLm1hdGNoZXMpIC0gMV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtYXRjaCA9IGhhbmRsZU1hdGNoKHRva2VuR3JvdXAsIFsgcW5keCBdLmNvbmNhdChsb29wTmR4KSwgdG9rZW5Hcm91cCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChsYXRlc3RNYXRjaCA9IG1hdGNoZXNbbWF0Y2hlcy5sZW5ndGggLSAxXS5tYXRjaCwgbGF0ZXN0TWF0Y2gub3B0aW9uYWxRdWFudGlmaWVyID0gcW5keCA+IHF0LnF1YW50aWZpZXIubWluIC0gMSwgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpc0ZpcnN0TWF0Y2gobGF0ZXN0TWF0Y2gsIHRva2VuR3JvdXApKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHFuZHggPiBxdC5xdWFudGlmaWVyLm1pbiAtIDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0U3RvcCA9ICEwLCB0ZXN0UG9zID0gcG9zO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICEwO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICEwO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChtYXRjaCA9IHJlc29sdmVUZXN0RnJvbVRva2VuKG1hdGNoLCBuZHhJbml0aWFsaXplciwgbG9vcE5keCwgcXVhbnRpZmllclJlY3Vyc2UpKSByZXR1cm4gITA7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgdGVzdFBvcysrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIHRuZHggPSBuZHhJbml0aWFsaXplci5sZW5ndGggPiAwID8gbmR4SW5pdGlhbGl6ZXIuc2hpZnQoKSA6IDA7IHRuZHggPCBtYXNrVG9rZW4ubWF0Y2hlcy5sZW5ndGg7IHRuZHgrKykgaWYgKCEwICE9PSBtYXNrVG9rZW4ubWF0Y2hlc1t0bmR4XS5pc1F1YW50aWZpZXIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBtYXRjaCA9IGhhbmRsZU1hdGNoKG1hc2tUb2tlbi5tYXRjaGVzW3RuZHhdLCBbIHRuZHggXS5jb25jYXQobG9vcE5keCksIHF1YW50aWZpZXJSZWN1cnNlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtYXRjaCAmJiB0ZXN0UG9zID09PSBwb3MpIHJldHVybiBtYXRjaDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0ZXN0UG9zID4gcG9zKSBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBmdW5jdGlvbiBmaWx0ZXJUZXN0cyh0ZXN0cykge1xuICAgICAgICAgICAgICAgICAgICBpZiAob3B0cy5rZWVwU3RhdGljICYmIHBvcyA+IDAgJiYgdGVzdHMubGVuZ3RoID4gMSArIChcIlwiID09PSB0ZXN0c1t0ZXN0cy5sZW5ndGggLSAxXS5tYXRjaC5kZWYgPyAxIDogMCkgJiYgITAgIT09IHRlc3RzWzBdLm1hdGNoLm9wdGlvbmFsaXR5ICYmICEwICE9PSB0ZXN0c1swXS5tYXRjaC5vcHRpb25hbFF1YW50aWZpZXIgJiYgbnVsbCA9PT0gdGVzdHNbMF0ubWF0Y2guZm4gJiYgIS9bMC05YS1iQS1aXS8udGVzdCh0ZXN0c1swXS5tYXRjaC5kZWYpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zW3BvcyAtIDFdID09PSB1bmRlZmluZWQpIHJldHVybiBbIGRldGVybWluZVRlc3RUZW1wbGF0ZSh0ZXN0cykgXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnNbcG9zIC0gMV0uYWx0ZXJuYXRpb24gPT09IHRlc3RzWzBdLmFsdGVybmF0aW9uKSByZXR1cm4gWyBkZXRlcm1pbmVUZXN0VGVtcGxhdGUodGVzdHMpIF07XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zW3BvcyAtIDFdKSByZXR1cm4gWyBkZXRlcm1pbmVUZXN0VGVtcGxhdGUodGVzdHMpIF07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRlc3RzO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgbGF0ZXN0TWF0Y2gsIG1hc2tUb2tlbnMgPSBnZXRNYXNrU2V0KCkubWFza1Rva2VuLCB0ZXN0UG9zID0gbmR4SW50bHpyID8gdHN0UHMgOiAwLCBuZHhJbml0aWFsaXplciA9IG5keEludGx6ciA/IG5keEludGx6ci5zbGljZSgpIDogWyAwIF0sIG1hdGNoZXMgPSBbXSwgaW5zZXJ0U3RvcCA9ICExLCBjYWNoZURlcGVuZGVuY3kgPSBuZHhJbnRsenIgPyBuZHhJbnRsenIuam9pbihcIlwiKSA6IFwiXCI7XG4gICAgICAgICAgICAgICAgaWYgKHBvcyA+IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChuZHhJbnRsenIgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgdGVzdCwgcHJldmlvdXNQb3MgPSBwb3MgLSAxOyAodGVzdCA9IGdldE1hc2tTZXQoKS52YWxpZFBvc2l0aW9uc1twcmV2aW91c1Bvc10gfHwgZ2V0TWFza1NldCgpLnRlc3RzW3ByZXZpb3VzUG9zXSkgPT09IHVuZGVmaW5lZCAmJiBwcmV2aW91c1BvcyA+IC0xOyApIHByZXZpb3VzUG9zLS07XG4gICAgICAgICAgICAgICAgICAgICAgICB0ZXN0ICE9PSB1bmRlZmluZWQgJiYgcHJldmlvdXNQb3MgPiAtMSAmJiAobmR4SW5pdGlhbGl6ZXIgPSBmdW5jdGlvbih0ZXN0cykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBsb2NhdG9yID0gW107XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICQuaXNBcnJheSh0ZXN0cykgfHwgKHRlc3RzID0gWyB0ZXN0cyBdKSwgdGVzdHMubGVuZ3RoID4gMCAmJiAodGVzdHNbMF0uYWx0ZXJuYXRpb24gPT09IHVuZGVmaW5lZCA/IDAgPT09IChsb2NhdG9yID0gZGV0ZXJtaW5lVGVzdFRlbXBsYXRlKHRlc3RzLnNsaWNlKCkpLmxvY2F0b3Iuc2xpY2UoKSkubGVuZ3RoICYmIChsb2NhdG9yID0gdGVzdHNbMF0ubG9jYXRvci5zbGljZSgpKSA6ICQuZWFjaCh0ZXN0cywgZnVuY3Rpb24obmR4LCB0c3QpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKFwiXCIgIT09IHRzdC5kZWYpIGlmICgwID09PSBsb2NhdG9yLmxlbmd0aCkgbG9jYXRvciA9IHRzdC5sb2NhdG9yLnNsaWNlKCk7IGVsc2UgZm9yICh2YXIgaSA9IDA7IGkgPCBsb2NhdG9yLmxlbmd0aDsgaSsrKSB0c3QubG9jYXRvcltpXSAmJiAtMSA9PT0gbG9jYXRvcltpXS50b1N0cmluZygpLmluZGV4T2YodHN0LmxvY2F0b3JbaV0pICYmIChsb2NhdG9yW2ldICs9IFwiLFwiICsgdHN0LmxvY2F0b3JbaV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pKSwgbG9jYXRvcjtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0odGVzdCksIGNhY2hlRGVwZW5kZW5jeSA9IG5keEluaXRpYWxpemVyLmpvaW4oXCJcIiksIHRlc3RQb3MgPSBwcmV2aW91c1Bvcyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKGdldE1hc2tTZXQoKS50ZXN0c1twb3NdICYmIGdldE1hc2tTZXQoKS50ZXN0c1twb3NdWzBdLmNkID09PSBjYWNoZURlcGVuZGVuY3kpIHJldHVybiBmaWx0ZXJUZXN0cyhnZXRNYXNrU2V0KCkudGVzdHNbcG9zXSk7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIG10bmR4ID0gbmR4SW5pdGlhbGl6ZXIuc2hpZnQoKTsgbXRuZHggPCBtYXNrVG9rZW5zLmxlbmd0aCAmJiAhKHJlc29sdmVUZXN0RnJvbVRva2VuKG1hc2tUb2tlbnNbbXRuZHhdLCBuZHhJbml0aWFsaXplciwgWyBtdG5keCBdKSAmJiB0ZXN0UG9zID09PSBwb3MgfHwgdGVzdFBvcyA+IHBvcyk7IG10bmR4KyspIDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuICgwID09PSBtYXRjaGVzLmxlbmd0aCB8fCBpbnNlcnRTdG9wKSAmJiBtYXRjaGVzLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICBtYXRjaDoge1xuICAgICAgICAgICAgICAgICAgICAgICAgZm46IG51bGwsXG4gICAgICAgICAgICAgICAgICAgICAgICBjYXJkaW5hbGl0eTogMCxcbiAgICAgICAgICAgICAgICAgICAgICAgIG9wdGlvbmFsaXR5OiAhMCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2luZzogbnVsbCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGRlZjogXCJcIixcbiAgICAgICAgICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyOiBcIlwiXG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIGxvY2F0b3I6IFtdLFxuICAgICAgICAgICAgICAgICAgICBjZDogY2FjaGVEZXBlbmRlbmN5XG4gICAgICAgICAgICAgICAgfSksIG5keEludGx6ciAhPT0gdW5kZWZpbmVkICYmIGdldE1hc2tTZXQoKS50ZXN0c1twb3NdID8gZmlsdGVyVGVzdHMoJC5leHRlbmQoITAsIFtdLCBtYXRjaGVzKSkgOiAoZ2V0TWFza1NldCgpLnRlc3RzW3Bvc10gPSAkLmV4dGVuZCghMCwgW10sIG1hdGNoZXMpLCBcbiAgICAgICAgICAgICAgICBmaWx0ZXJUZXN0cyhnZXRNYXNrU2V0KCkudGVzdHNbcG9zXSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZnVuY3Rpb24gZ2V0QnVmZmVyVGVtcGxhdGUoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGdldE1hc2tTZXQoKS5fYnVmZmVyID09PSB1bmRlZmluZWQgJiYgKGdldE1hc2tTZXQoKS5fYnVmZmVyID0gZ2V0TWFza1RlbXBsYXRlKCExLCAxKSwgXG4gICAgICAgICAgICAgICAgZ2V0TWFza1NldCgpLmJ1ZmZlciA9PT0gdW5kZWZpbmVkICYmIChnZXRNYXNrU2V0KCkuYnVmZmVyID0gZ2V0TWFza1NldCgpLl9idWZmZXIuc2xpY2UoKSkpLCBcbiAgICAgICAgICAgICAgICBnZXRNYXNrU2V0KCkuX2J1ZmZlcjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZ1bmN0aW9uIGdldEJ1ZmZlcihub0NhY2hlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGdldE1hc2tTZXQoKS5idWZmZXIgIT09IHVuZGVmaW5lZCAmJiAhMCAhPT0gbm9DYWNoZSB8fCAoZ2V0TWFza1NldCgpLmJ1ZmZlciA9IGdldE1hc2tUZW1wbGF0ZSghMCwgZ2V0TGFzdFZhbGlkUG9zaXRpb24oKSwgITApKSwgXG4gICAgICAgICAgICAgICAgZ2V0TWFza1NldCgpLmJ1ZmZlcjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlZnJlc2hGcm9tQnVmZmVyKHN0YXJ0LCBlbmQsIGJ1ZmZlcikge1xuICAgICAgICAgICAgICAgIHZhciBpLCBwO1xuICAgICAgICAgICAgICAgIGlmICghMCA9PT0gc3RhcnQpIHJlc2V0TWFza1NldCgpLCBzdGFydCA9IDAsIGVuZCA9IGJ1ZmZlci5sZW5ndGg7IGVsc2UgZm9yIChpID0gc3RhcnQ7IGkgPCBlbmQ7IGkrKykgZGVsZXRlIGdldE1hc2tTZXQoKS52YWxpZFBvc2l0aW9uc1tpXTtcbiAgICAgICAgICAgICAgICBmb3IgKHAgPSBzdGFydCwgaSA9IHN0YXJ0OyBpIDwgZW5kOyBpKyspIGlmIChyZXNldE1hc2tTZXQoITApLCBidWZmZXJbaV0gIT09IG9wdHMuc2tpcE9wdGlvbmFsUGFydENoYXJhY3Rlcikge1xuICAgICAgICAgICAgICAgICAgICB2YXIgdmFsUmVzdWx0ID0gaXNWYWxpZChwLCBidWZmZXJbaV0sICEwLCAhMCk7XG4gICAgICAgICAgICAgICAgICAgICExICE9PSB2YWxSZXN1bHQgJiYgKHJlc2V0TWFza1NldCghMCksIHAgPSB2YWxSZXN1bHQuY2FyZXQgIT09IHVuZGVmaW5lZCA/IHZhbFJlc3VsdC5jYXJldCA6IHZhbFJlc3VsdC5wb3MgKyAxKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmdW5jdGlvbiBjYXNpbmcoZWxlbSwgdGVzdCwgcG9zKSB7XG4gICAgICAgICAgICAgICAgc3dpdGNoIChvcHRzLmNhc2luZyB8fCB0ZXN0LmNhc2luZykge1xuICAgICAgICAgICAgICAgICAgY2FzZSBcInVwcGVyXCI6XG4gICAgICAgICAgICAgICAgICAgIGVsZW0gPSBlbGVtLnRvVXBwZXJDYXNlKCk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICAgICAgICBjYXNlIFwibG93ZXJcIjpcbiAgICAgICAgICAgICAgICAgICAgZWxlbSA9IGVsZW0udG9Mb3dlckNhc2UoKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgICAgICAgIGNhc2UgXCJ0aXRsZVwiOlxuICAgICAgICAgICAgICAgICAgICB2YXIgcG9zQmVmb3JlID0gZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zW3BvcyAtIDFdO1xuICAgICAgICAgICAgICAgICAgICBlbGVtID0gMCA9PT0gcG9zIHx8IHBvc0JlZm9yZSAmJiBwb3NCZWZvcmUuaW5wdXQgPT09IFN0cmluZy5mcm9tQ2hhckNvZGUoSW5wdXRtYXNrLmtleUNvZGUuU1BBQ0UpID8gZWxlbS50b1VwcGVyQ2FzZSgpIDogZWxlbS50b0xvd2VyQ2FzZSgpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgaWYgKCQuaXNGdW5jdGlvbihvcHRzLmNhc2luZykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBhcmdzID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFyZ3MucHVzaChnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnMpLCBlbGVtID0gb3B0cy5jYXNpbmcuYXBwbHkodGhpcywgYXJncyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIGVsZW07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmdW5jdGlvbiBjaGVja0FsdGVybmF0aW9uTWF0Y2goYWx0QXJyMSwgYWx0QXJyMiwgbmEpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBuYU5keCwgYWx0QXJyQyA9IG9wdHMuZ3JlZWR5ID8gYWx0QXJyMiA6IGFsdEFycjIuc2xpY2UoMCwgMSksIGlzTWF0Y2ggPSAhMSwgbmFBcnIgPSBuYSAhPT0gdW5kZWZpbmVkID8gbmEuc3BsaXQoXCIsXCIpIDogW10sIGkgPSAwOyBpIDwgbmFBcnIubGVuZ3RoOyBpKyspIC0xICE9PSAobmFOZHggPSBhbHRBcnIxLmluZGV4T2YobmFBcnJbaV0pKSAmJiBhbHRBcnIxLnNwbGljZShuYU5keCwgMSk7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgYWxuZHggPSAwOyBhbG5keCA8IGFsdEFycjEubGVuZ3RoOyBhbG5keCsrKSBpZiAoLTEgIT09ICQuaW5BcnJheShhbHRBcnIxW2FsbmR4XSwgYWx0QXJyQykpIHtcbiAgICAgICAgICAgICAgICAgICAgaXNNYXRjaCA9ICEwO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIGlzTWF0Y2g7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmdW5jdGlvbiBpc1ZhbGlkKHBvcywgYywgc3RyaWN0LCBmcm9tU2V0VmFsaWQsIGZyb21BbHRlcm5hdGUsIHZhbGlkYXRlT25seSkge1xuICAgICAgICAgICAgICAgIGZ1bmN0aW9uIGlzU2VsZWN0aW9uKHBvc09iaikge1xuICAgICAgICAgICAgICAgICAgICB2YXIgc2VsZWN0aW9uID0gaXNSVEwgPyBwb3NPYmouYmVnaW4gLSBwb3NPYmouZW5kID4gMSB8fCBwb3NPYmouYmVnaW4gLSBwb3NPYmouZW5kID09IDEgOiBwb3NPYmouZW5kIC0gcG9zT2JqLmJlZ2luID4gMSB8fCBwb3NPYmouZW5kIC0gcG9zT2JqLmJlZ2luID09IDE7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBzZWxlY3Rpb24gJiYgMCA9PT0gcG9zT2JqLmJlZ2luICYmIHBvc09iai5lbmQgPT09IGdldE1hc2tTZXQoKS5tYXNrTGVuZ3RoID8gXCJmdWxsXCIgOiBzZWxlY3Rpb247XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGZ1bmN0aW9uIF9pc1ZhbGlkKHBvc2l0aW9uLCBjLCBzdHJpY3QpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHJzbHQgPSAhMTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICQuZWFjaChnZXRUZXN0cyhwb3NpdGlvbiksIGZ1bmN0aW9uKG5keCwgdHN0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciB0ZXN0ID0gdHN0Lm1hdGNoLCBsb29wZW5kID0gYyA/IDEgOiAwLCBjaHJzID0gXCJcIiwgaSA9IHRlc3QuY2FyZGluYWxpdHk7IGkgPiBsb29wZW5kOyBpLS0pIGNocnMgKz0gZ2V0QnVmZmVyRWxlbWVudChwb3NpdGlvbiAtIChpIC0gMSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGMgJiYgKGNocnMgKz0gYyksIGdldEJ1ZmZlcighMCksICExICE9PSAocnNsdCA9IG51bGwgIT0gdGVzdC5mbiA/IHRlc3QuZm4udGVzdChjaHJzLCBnZXRNYXNrU2V0KCksIHBvc2l0aW9uLCBzdHJpY3QsIG9wdHMsIGlzU2VsZWN0aW9uKHBvcykpIDogKGMgPT09IHRlc3QuZGVmIHx8IGMgPT09IG9wdHMuc2tpcE9wdGlvbmFsUGFydENoYXJhY3RlcikgJiYgXCJcIiAhPT0gdGVzdC5kZWYgJiYge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGM6IGdldFBsYWNlaG9sZGVyKHBvc2l0aW9uLCB0ZXN0LCAhMCkgfHwgdGVzdC5kZWYsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9zOiBwb3NpdGlvblxuICAgICAgICAgICAgICAgICAgICAgICAgfSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgZWxlbSA9IHJzbHQuYyAhPT0gdW5kZWZpbmVkID8gcnNsdC5jIDogYztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGVtID0gZWxlbSA9PT0gb3B0cy5za2lwT3B0aW9uYWxQYXJ0Q2hhcmFjdGVyICYmIG51bGwgPT09IHRlc3QuZm4gPyBnZXRQbGFjZWhvbGRlcihwb3NpdGlvbiwgdGVzdCwgITApIHx8IHRlc3QuZGVmIDogZWxlbTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgdmFsaWRhdGVkUG9zID0gcG9zaXRpb24sIHBvc3NpYmxlTW9kaWZpZWRCdWZmZXIgPSBnZXRCdWZmZXIoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocnNsdC5yZW1vdmUgIT09IHVuZGVmaW5lZCAmJiAoJC5pc0FycmF5KHJzbHQucmVtb3ZlKSB8fCAocnNsdC5yZW1vdmUgPSBbIHJzbHQucmVtb3ZlIF0pLCBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkLmVhY2gocnNsdC5yZW1vdmUuc29ydChmdW5jdGlvbihhLCBiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBiIC0gYTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KSwgZnVuY3Rpb24obmR4LCBsbW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmlwVmFsaWRQb3NpdGlvbnMobG1udCwgbG1udCArIDEsICEwKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KSksIHJzbHQuaW5zZXJ0ICE9PSB1bmRlZmluZWQgJiYgKCQuaXNBcnJheShyc2x0Lmluc2VydCkgfHwgKHJzbHQuaW5zZXJ0ID0gWyByc2x0Lmluc2VydCBdKSwgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJC5lYWNoKHJzbHQuaW5zZXJ0LnNvcnQoZnVuY3Rpb24oYSwgYikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gYSAtIGI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSksIGZ1bmN0aW9uKG5keCwgbG1udCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpc1ZhbGlkKGxtbnQucG9zLCBsbW50LmMsICEwLCBmcm9tU2V0VmFsaWQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pKSwgcnNsdC5yZWZyZXNoRnJvbUJ1ZmZlcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgcmVmcmVzaCA9IHJzbHQucmVmcmVzaEZyb21CdWZmZXI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyZWZyZXNoRnJvbUJ1ZmZlcighMCA9PT0gcmVmcmVzaCA/IHJlZnJlc2ggOiByZWZyZXNoLnN0YXJ0LCByZWZyZXNoLmVuZCwgcG9zc2libGVNb2RpZmllZEJ1ZmZlciksIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByc2x0LnBvcyA9PT0gdW5kZWZpbmVkICYmIHJzbHQuYyA9PT0gdW5kZWZpbmVkKSByZXR1cm4gcnNsdC5wb3MgPSBnZXRMYXN0VmFsaWRQb3NpdGlvbigpLCBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgITE7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICgodmFsaWRhdGVkUG9zID0gcnNsdC5wb3MgIT09IHVuZGVmaW5lZCA/IHJzbHQucG9zIDogcG9zaXRpb24pICE9PSBwb3NpdGlvbikgcmV0dXJuIHJzbHQgPSAkLmV4dGVuZChyc2x0LCBpc1ZhbGlkKHZhbGlkYXRlZFBvcywgZWxlbSwgITAsIGZyb21TZXRWYWxpZCkpLCBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgITE7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICghMCAhPT0gcnNsdCAmJiByc2x0LnBvcyAhPT0gdW5kZWZpbmVkICYmIHJzbHQucG9zICE9PSBwb3NpdGlvbiAmJiAodmFsaWRhdGVkUG9zID0gcnNsdC5wb3MsIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlZnJlc2hGcm9tQnVmZmVyKHBvc2l0aW9uLCB2YWxpZGF0ZWRQb3MsIGdldEJ1ZmZlcigpLnNsaWNlKCkpLCB2YWxpZGF0ZWRQb3MgIT09IHBvc2l0aW9uKSkgcmV0dXJuIHJzbHQgPSAkLmV4dGVuZChyc2x0LCBpc1ZhbGlkKHZhbGlkYXRlZFBvcywgZWxlbSwgITApKSwgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgITE7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICghMCA9PT0gcnNsdCB8fCByc2x0LnBvcyAhPT0gdW5kZWZpbmVkIHx8IHJzbHQuYyAhPT0gdW5kZWZpbmVkKSAmJiAobmR4ID4gMCAmJiByZXNldE1hc2tTZXQoITApLCBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZXRWYWxpZFBvc2l0aW9uKHZhbGlkYXRlZFBvcywgJC5leHRlbmQoe30sIHRzdCwge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnB1dDogY2FzaW5nKGVsZW0sIHRlc3QsIHZhbGlkYXRlZFBvcylcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KSwgZnJvbVNldFZhbGlkLCBpc1NlbGVjdGlvbihwb3MpKSB8fCAocnNsdCA9ICExKSwgITEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KSwgcnNsdDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZnVuY3Rpb24gc2V0VmFsaWRQb3NpdGlvbihwb3MsIHZhbGlkVGVzdCwgZnJvbVNldFZhbGlkLCBpc1NlbGVjdGlvbikge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNTZWxlY3Rpb24gfHwgb3B0cy5pbnNlcnRNb2RlICYmIGdldE1hc2tTZXQoKS52YWxpZFBvc2l0aW9uc1twb3NdICE9PSB1bmRlZmluZWQgJiYgZnJvbVNldFZhbGlkID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBpLCBwb3NpdGlvbnNDbG9uZSA9ICQuZXh0ZW5kKCEwLCB7fSwgZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zKSwgbHZwID0gZ2V0TGFzdFZhbGlkUG9zaXRpb24odW5kZWZpbmVkLCAhMCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGkgPSBwb3M7IGkgPD0gbHZwOyBpKyspIGRlbGV0ZSBnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnNbaV07XG4gICAgICAgICAgICAgICAgICAgICAgICBnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnNbcG9zXSA9ICQuZXh0ZW5kKCEwLCB7fSwgdmFsaWRUZXN0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBqLCB2YWxpZCA9ICEwLCB2cHMgPSBnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnMsIG5lZWRzVmFsaWRhdGlvbiA9ICExLCBpbml0aWFsTGVuZ3RoID0gZ2V0TWFza1NldCgpLm1hc2tMZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGkgPSBqID0gcG9zOyBpIDw9IGx2cDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHQgPSBwb3NpdGlvbnNDbG9uZVtpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodCAhPT0gdW5kZWZpbmVkKSBmb3IgKHZhciBwb3NNYXRjaCA9IGo7IHBvc01hdGNoIDwgZ2V0TWFza1NldCgpLm1hc2tMZW5ndGggJiYgKG51bGwgPT09IHQubWF0Y2guZm4gJiYgdnBzW2ldICYmICghMCA9PT0gdnBzW2ldLm1hdGNoLm9wdGlvbmFsUXVhbnRpZmllciB8fCAhMCA9PT0gdnBzW2ldLm1hdGNoLm9wdGlvbmFsaXR5KSB8fCBudWxsICE9IHQubWF0Y2guZm4pOyApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHBvc01hdGNoKyssICExID09PSBuZWVkc1ZhbGlkYXRpb24gJiYgcG9zaXRpb25zQ2xvbmVbcG9zTWF0Y2hdICYmIHBvc2l0aW9uc0Nsb25lW3Bvc01hdGNoXS5tYXRjaC5kZWYgPT09IHQubWF0Y2guZGVmKSBnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnNbcG9zTWF0Y2hdID0gJC5leHRlbmQoITAsIHt9LCBwb3NpdGlvbnNDbG9uZVtwb3NNYXRjaF0pLCBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zW3Bvc01hdGNoXS5pbnB1dCA9IHQuaW5wdXQsIGZpbGxNaXNzaW5nTm9uTWFzayhwb3NNYXRjaCksIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBqID0gcG9zTWF0Y2gsIHZhbGlkID0gITA7IGVsc2UgaWYgKHBvc2l0aW9uQ2FuTWF0Y2hEZWZpbml0aW9uKHBvc01hdGNoLCB0Lm1hdGNoLmRlZikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciByZXN1bHQgPSBpc1ZhbGlkKHBvc01hdGNoLCB0LmlucHV0LCAhMCwgITApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsaWQgPSAhMSAhPT0gcmVzdWx0LCBqID0gcmVzdWx0LmNhcmV0IHx8IHJlc3VsdC5pbnNlcnQgPyBnZXRMYXN0VmFsaWRQb3NpdGlvbigpIDogcG9zTWF0Y2gsIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmVlZHNWYWxpZGF0aW9uID0gITA7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoISh2YWxpZCA9ICEwID09PSB0LmdlbmVyYXRlZElucHV0KSAmJiBwb3NNYXRjaCA+PSBnZXRNYXNrU2V0KCkubWFza0xlbmd0aCAtIDEpIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZ2V0TWFza1NldCgpLm1hc2tMZW5ndGggPCBpbml0aWFsTGVuZ3RoICYmIChnZXRNYXNrU2V0KCkubWFza0xlbmd0aCA9IGluaXRpYWxMZW5ndGgpLCBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsaWQpIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXZhbGlkKSBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghdmFsaWQpIHJldHVybiBnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnMgPSAkLmV4dGVuZCghMCwge30sIHBvc2l0aW9uc0Nsb25lKSwgXG4gICAgICAgICAgICAgICAgICAgICAgICByZXNldE1hc2tTZXQoITApLCAhMTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGdldE1hc2tTZXQoKS52YWxpZFBvc2l0aW9uc1twb3NdID0gJC5leHRlbmQoITAsIHt9LCB2YWxpZFRlc3QpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzZXRNYXNrU2V0KCEwKSwgITA7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGZ1bmN0aW9uIGZpbGxNaXNzaW5nTm9uTWFzayhtYXNrUG9zKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIHBuZHggPSBtYXNrUG9zIC0gMTsgcG5keCA+IC0xICYmICFnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnNbcG5keF07IHBuZHgtLSkgO1xuICAgICAgICAgICAgICAgICAgICB2YXIgdGVzdFRlbXBsYXRlLCB0ZXN0c0Zyb21Qb3M7XG4gICAgICAgICAgICAgICAgICAgIGZvciAocG5keCsrOyBwbmR4IDwgbWFza1BvczsgcG5keCsrKSBnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnNbcG5keF0gPT09IHVuZGVmaW5lZCAmJiAoITEgPT09IG9wdHMuaml0TWFza2luZyB8fCBvcHRzLmppdE1hc2tpbmcgPiBwbmR4KSAmJiAoXCJcIiA9PT0gKHRlc3RzRnJvbVBvcyA9IGdldFRlc3RzKHBuZHgsIGdldFRlc3RUZW1wbGF0ZShwbmR4IC0gMSkubG9jYXRvciwgcG5keCAtIDEpLnNsaWNlKCkpW3Rlc3RzRnJvbVBvcy5sZW5ndGggLSAxXS5tYXRjaC5kZWYgJiYgdGVzdHNGcm9tUG9zLnBvcCgpLCBcbiAgICAgICAgICAgICAgICAgICAgKHRlc3RUZW1wbGF0ZSA9IGRldGVybWluZVRlc3RUZW1wbGF0ZSh0ZXN0c0Zyb21Qb3MpKSAmJiAodGVzdFRlbXBsYXRlLm1hdGNoLmRlZiA9PT0gb3B0cy5yYWRpeFBvaW50RGVmaW5pdGlvblN5bWJvbCB8fCAhaXNNYXNrKHBuZHgsICEwKSB8fCAkLmluQXJyYXkob3B0cy5yYWRpeFBvaW50LCBnZXRCdWZmZXIoKSkgPCBwbmR4ICYmIHRlc3RUZW1wbGF0ZS5tYXRjaC5mbiAmJiB0ZXN0VGVtcGxhdGUubWF0Y2guZm4udGVzdChnZXRQbGFjZWhvbGRlcihwbmR4KSwgZ2V0TWFza1NldCgpLCBwbmR4LCAhMSwgb3B0cykpICYmICExICE9PSAocmVzdWx0ID0gX2lzVmFsaWQocG5keCwgZ2V0UGxhY2Vob2xkZXIocG5keCwgdGVzdFRlbXBsYXRlLm1hdGNoLCAhMCkgfHwgKG51bGwgPT0gdGVzdFRlbXBsYXRlLm1hdGNoLmZuID8gdGVzdFRlbXBsYXRlLm1hdGNoLmRlZiA6IFwiXCIgIT09IGdldFBsYWNlaG9sZGVyKHBuZHgpID8gZ2V0UGxhY2Vob2xkZXIocG5keCkgOiBnZXRCdWZmZXIoKVtwbmR4XSksICEwKSkgJiYgKGdldE1hc2tTZXQoKS52YWxpZFBvc2l0aW9uc1tyZXN1bHQucG9zIHx8IHBuZHhdLmdlbmVyYXRlZElucHV0ID0gITApKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgc3RyaWN0ID0gITAgPT09IHN0cmljdDtcbiAgICAgICAgICAgICAgICB2YXIgbWFza1BvcyA9IHBvcztcbiAgICAgICAgICAgICAgICBwb3MuYmVnaW4gIT09IHVuZGVmaW5lZCAmJiAobWFza1BvcyA9IGlzUlRMICYmICFpc1NlbGVjdGlvbihwb3MpID8gcG9zLmVuZCA6IHBvcy5iZWdpbik7XG4gICAgICAgICAgICAgICAgdmFyIHJlc3VsdCA9ICEwLCBwb3NpdGlvbnNDbG9uZSA9ICQuZXh0ZW5kKCEwLCB7fSwgZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zKTtcbiAgICAgICAgICAgICAgICBpZiAoJC5pc0Z1bmN0aW9uKG9wdHMucHJlVmFsaWRhdGlvbikgJiYgIXN0cmljdCAmJiAhMCAhPT0gZnJvbVNldFZhbGlkICYmICEwICE9PSB2YWxpZGF0ZU9ubHkgJiYgKHJlc3VsdCA9IG9wdHMucHJlVmFsaWRhdGlvbihnZXRCdWZmZXIoKSwgbWFza1BvcywgYywgaXNTZWxlY3Rpb24ocG9zKSwgb3B0cykpLCBcbiAgICAgICAgICAgICAgICAhMCA9PT0gcmVzdWx0KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChmaWxsTWlzc2luZ05vbk1hc2sobWFza1BvcyksIGlzU2VsZWN0aW9uKHBvcykgJiYgKGhhbmRsZVJlbW92ZSh1bmRlZmluZWQsIElucHV0bWFzay5rZXlDb2RlLkRFTEVURSwgcG9zLCAhMCwgITApLCBcbiAgICAgICAgICAgICAgICAgICAgbWFza1BvcyA9IGdldE1hc2tTZXQoKS5wKSwgbWFza1BvcyA8IGdldE1hc2tTZXQoKS5tYXNrTGVuZ3RoICYmIChtYXhMZW5ndGggPT09IHVuZGVmaW5lZCB8fCBtYXNrUG9zIDwgbWF4TGVuZ3RoKSAmJiAocmVzdWx0ID0gX2lzVmFsaWQobWFza1BvcywgYywgc3RyaWN0KSwgXG4gICAgICAgICAgICAgICAgICAgICghc3RyaWN0IHx8ICEwID09PSBmcm9tU2V0VmFsaWQpICYmICExID09PSByZXN1bHQgJiYgITAgIT09IHZhbGlkYXRlT25seSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjdXJyZW50UG9zVmFsaWQgPSBnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnNbbWFza1Bvc107XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWN1cnJlbnRQb3NWYWxpZCB8fCBudWxsICE9PSBjdXJyZW50UG9zVmFsaWQubWF0Y2guZm4gfHwgY3VycmVudFBvc1ZhbGlkLm1hdGNoLmRlZiAhPT0gYyAmJiBjICE9PSBvcHRzLnNraXBPcHRpb25hbFBhcnRDaGFyYWN0ZXIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoKG9wdHMuaW5zZXJ0TW9kZSB8fCBnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnNbc2Vla05leHQobWFza1BvcyldID09PSB1bmRlZmluZWQpICYmICFpc01hc2sobWFza1BvcywgITApKSBmb3IgKHZhciBuUG9zID0gbWFza1BvcyArIDEsIHNuUG9zID0gc2Vla05leHQobWFza1Bvcyk7IG5Qb3MgPD0gc25Qb3M7IG5Qb3MrKykgaWYgKCExICE9PSAocmVzdWx0ID0gX2lzVmFsaWQoblBvcywgYywgc3RyaWN0KSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIWZ1bmN0aW9uKG9yaWdpbmFsUG9zLCBuZXdQb3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciB2cCA9IGdldE1hc2tTZXQoKS52YWxpZFBvc2l0aW9uc1tuZXdQb3NdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHZwKSBmb3IgKHZhciB0YXJnZXRMb2NhdG9yID0gdnAubG9jYXRvciwgdGxsID0gdGFyZ2V0TG9jYXRvci5sZW5ndGgsIHBzID0gb3JpZ2luYWxQb3M7IHBzIDwgbmV3UG9zOyBwcysrKSBpZiAoZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zW3BzXSA9PT0gdW5kZWZpbmVkICYmICFpc01hc2socHMsICEwKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciB0ZXN0cyA9IGdldFRlc3RzKHBzKS5zbGljZSgpLCBiZXN0TWF0Y2ggPSBkZXRlcm1pbmVUZXN0VGVtcGxhdGUodGVzdHMsICEwKSwgZXF1YWxpdHkgPSAtMTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIlwiID09PSB0ZXN0c1t0ZXN0cy5sZW5ndGggLSAxXS5tYXRjaC5kZWYgJiYgdGVzdHMucG9wKCksICQuZWFjaCh0ZXN0cywgZnVuY3Rpb24obmR4LCB0c3QpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0bGw7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRzdC5sb2NhdG9yW2ldID09PSB1bmRlZmluZWQgfHwgIWNoZWNrQWx0ZXJuYXRpb25NYXRjaCh0c3QubG9jYXRvcltpXS50b1N0cmluZygpLnNwbGl0KFwiLFwiKSwgdGFyZ2V0TG9jYXRvcltpXS50b1N0cmluZygpLnNwbGl0KFwiLFwiKSwgdHN0Lm5hKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciB0YXJnZXRBSSA9IHRhcmdldExvY2F0b3JbaV0sIGJlc3RNYXRjaEFJID0gYmVzdE1hdGNoLmxvY2F0b3JbaV0sIHRzdEFJID0gdHN0LmxvY2F0b3JbaV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGFyZ2V0QUkgLSBiZXN0TWF0Y2hBSSA+IE1hdGguYWJzKHRhcmdldEFJIC0gdHN0QUkpICYmIChiZXN0TWF0Y2ggPSB0c3QpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXF1YWxpdHkgPCBpICYmIChlcXVhbGl0eSA9IGksIGJlc3RNYXRjaCA9IHRzdCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KSwgKGJlc3RNYXRjaCA9ICQuZXh0ZW5kKHt9LCBiZXN0TWF0Y2gsIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5wdXQ6IGdldFBsYWNlaG9sZGVyKHBzLCBiZXN0TWF0Y2gubWF0Y2gsICEwKSB8fCBiZXN0TWF0Y2gubWF0Y2guZGVmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSkpLmdlbmVyYXRlZElucHV0ID0gITAsIHNldFZhbGlkUG9zaXRpb24ocHMsIGJlc3RNYXRjaCwgITApLCBnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnNbbmV3UG9zXSA9IHVuZGVmaW5lZCwgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgX2lzVmFsaWQobmV3UG9zLCB2cC5pbnB1dCwgITApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KG1hc2tQb3MsIHJlc3VsdC5wb3MgIT09IHVuZGVmaW5lZCA/IHJlc3VsdC5wb3MgOiBuUG9zKSwgbWFza1BvcyA9IG5Qb3M7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSByZXN1bHQgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FyZXQ6IHNlZWtOZXh0KG1hc2tQb3MpXG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICExID09PSByZXN1bHQgJiYgb3B0cy5rZWVwU3RhdGljICYmICFzdHJpY3QgJiYgITAgIT09IGZyb21BbHRlcm5hdGUgJiYgKHJlc3VsdCA9IGZ1bmN0aW9uKHBvcywgYywgc3RyaWN0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgbGFzdEFsdCwgYWx0ZXJuYXRpb24sIGFsdFBvcywgcHJldkFsdFBvcywgaSwgdmFsaWRQb3MsIGFsdE5keHMsIGRlY2lzaW9uUG9zLCB2YWxpZFBzQ2xvbmUgPSAkLmV4dGVuZCghMCwge30sIGdldE1hc2tTZXQoKS52YWxpZFBvc2l0aW9ucyksIGlzVmFsaWRSc2x0ID0gITEsIGxBbHRQb3MgPSBnZXRMYXN0VmFsaWRQb3NpdGlvbigpO1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChwcmV2QWx0UG9zID0gZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zW2xBbHRQb3NdOyBsQWx0UG9zID49IDA7IGxBbHRQb3MtLSkgaWYgKChhbHRQb3MgPSBnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnNbbEFsdFBvc10pICYmIGFsdFBvcy5hbHRlcm5hdGlvbiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGxhc3RBbHQgPSBsQWx0UG9zLCBhbHRlcm5hdGlvbiA9IGdldE1hc2tTZXQoKS52YWxpZFBvc2l0aW9uc1tsYXN0QWx0XS5hbHRlcm5hdGlvbiwgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJldkFsdFBvcy5sb2NhdG9yW2FsdFBvcy5hbHRlcm5hdGlvbl0gIT09IGFsdFBvcy5sb2NhdG9yW2FsdFBvcy5hbHRlcm5hdGlvbl0pIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByZXZBbHRQb3MgPSBhbHRQb3M7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYWx0ZXJuYXRpb24gIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlY2lzaW9uUG9zID0gcGFyc2VJbnQobGFzdEFsdCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGRlY2lzaW9uVGFrZXIgPSBwcmV2QWx0UG9zLmxvY2F0b3JbcHJldkFsdFBvcy5hbHRlcm5hdGlvbiB8fCBhbHRlcm5hdGlvbl0gIT09IHVuZGVmaW5lZCA/IHByZXZBbHRQb3MubG9jYXRvcltwcmV2QWx0UG9zLmFsdGVybmF0aW9uIHx8IGFsdGVybmF0aW9uXSA6IGFsdE5keHNbMF07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVjaXNpb25UYWtlci5sZW5ndGggPiAwICYmIChkZWNpc2lvblRha2VyID0gZGVjaXNpb25UYWtlci5zcGxpdChcIixcIilbMF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwb3NzaWJpbGl0eVBvcyA9IGdldE1hc2tTZXQoKS52YWxpZFBvc2l0aW9uc1tkZWNpc2lvblBvc10sIHByZXZQb3MgPSBnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnNbZGVjaXNpb25Qb3MgLSAxXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkLmVhY2goZ2V0VGVzdHMoZGVjaXNpb25Qb3MsIHByZXZQb3MgPyBwcmV2UG9zLmxvY2F0b3IgOiB1bmRlZmluZWQsIGRlY2lzaW9uUG9zIC0gMSksIGZ1bmN0aW9uKG5keCwgdGVzdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbHROZHhzID0gdGVzdC5sb2NhdG9yW2FsdGVybmF0aW9uXSA/IHRlc3QubG9jYXRvclthbHRlcm5hdGlvbl0udG9TdHJpbmcoKS5zcGxpdChcIixcIikgOiBbXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgbW5keCA9IDA7IG1uZHggPCBhbHROZHhzLmxlbmd0aDsgbW5keCsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgdmFsaWRJbnB1dHMgPSBbXSwgc3RhdGljSW5wdXRzQmVmb3JlUG9zID0gMCwgc3RhdGljSW5wdXRzQmVmb3JlUG9zQWx0ZXJuYXRlID0gMCwgdmVyaWZ5VmFsaWRJbnB1dCA9ICExO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRlY2lzaW9uVGFrZXIgPCBhbHROZHhzW21uZHhdICYmICh0ZXN0Lm5hID09PSB1bmRlZmluZWQgfHwgLTEgPT09ICQuaW5BcnJheShhbHROZHhzW21uZHhdLCB0ZXN0Lm5hLnNwbGl0KFwiLFwiKSkgfHwgLTEgPT09ICQuaW5BcnJheShkZWNpc2lvblRha2VyLnRvU3RyaW5nKCksIGFsdE5keHMpKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdldE1hc2tTZXQoKS52YWxpZFBvc2l0aW9uc1tkZWNpc2lvblBvc10gPSAkLmV4dGVuZCghMCwge30sIHRlc3QpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwb3NzaWJpbGl0aWVzID0gZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zW2RlY2lzaW9uUG9zXS5sb2NhdG9yO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zW2RlY2lzaW9uUG9zXS5sb2NhdG9yW2FsdGVybmF0aW9uXSA9IHBhcnNlSW50KGFsdE5keHNbbW5keF0pLCBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBudWxsID09IHRlc3QubWF0Y2guZm4gPyAocG9zc2liaWxpdHlQb3MuaW5wdXQgIT09IHRlc3QubWF0Y2guZGVmICYmICh2ZXJpZnlWYWxpZElucHV0ID0gITAsIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICEwICE9PSBwb3NzaWJpbGl0eVBvcy5nZW5lcmF0ZWRJbnB1dCAmJiB2YWxpZElucHV0cy5wdXNoKHBvc3NpYmlsaXR5UG9zLmlucHV0KSksIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXRpY0lucHV0c0JlZm9yZVBvc0FsdGVybmF0ZSsrLCBnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnNbZGVjaXNpb25Qb3NdLmdlbmVyYXRlZElucHV0ID0gIS9bMC05YS1iQS1aXS8udGVzdCh0ZXN0Lm1hdGNoLmRlZiksIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdldE1hc2tTZXQoKS52YWxpZFBvc2l0aW9uc1tkZWNpc2lvblBvc10uaW5wdXQgPSB0ZXN0Lm1hdGNoLmRlZikgOiBnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnNbZGVjaXNpb25Qb3NdLmlucHV0ID0gcG9zc2liaWxpdHlQb3MuaW5wdXQsIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGkgPSBkZWNpc2lvblBvcyArIDE7IGkgPCBnZXRMYXN0VmFsaWRQb3NpdGlvbih1bmRlZmluZWQsICEwKSArIDE7IGkrKykgKHZhbGlkUG9zID0gZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zW2ldKSAmJiAhMCAhPT0gdmFsaWRQb3MuZ2VuZXJhdGVkSW5wdXQgJiYgL1swLTlhLWJBLVpdLy50ZXN0KHZhbGlkUG9zLmlucHV0KSA/IHZhbGlkSW5wdXRzLnB1c2godmFsaWRQb3MuaW5wdXQpIDogaSA8IHBvcyAmJiBzdGF0aWNJbnB1dHNCZWZvcmVQb3MrKywgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVsZXRlIGdldE1hc2tTZXQoKS52YWxpZFBvc2l0aW9uc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZlcmlmeVZhbGlkSW5wdXQgJiYgdmFsaWRJbnB1dHNbMF0gPT09IHRlc3QubWF0Y2guZGVmICYmIHZhbGlkSW5wdXRzLnNoaWZ0KCksIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc2V0TWFza1NldCghMCksIGlzVmFsaWRSc2x0ID0gITA7IHZhbGlkSW5wdXRzLmxlbmd0aCA+IDA7ICkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgaW5wdXQgPSB2YWxpZElucHV0cy5zaGlmdCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoaW5wdXQgIT09IG9wdHMuc2tpcE9wdGlvbmFsUGFydENoYXJhY3RlciAmJiAhKGlzVmFsaWRSc2x0ID0gaXNWYWxpZChnZXRMYXN0VmFsaWRQb3NpdGlvbih1bmRlZmluZWQsICEwKSArIDEsIGlucHV0LCAhMSwgZnJvbVNldFZhbGlkLCAhMCkpKSBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzVmFsaWRSc2x0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdldE1hc2tTZXQoKS52YWxpZFBvc2l0aW9uc1tkZWNpc2lvblBvc10ubG9jYXRvciA9IHBvc3NpYmlsaXRpZXM7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciB0YXJnZXRMdnAgPSBnZXRMYXN0VmFsaWRQb3NpdGlvbihwb3MpICsgMTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChpID0gZGVjaXNpb25Qb3MgKyAxOyBpIDwgZ2V0TGFzdFZhbGlkUG9zaXRpb24oKSArIDE7IGkrKykgKCh2YWxpZFBvcyA9IGdldE1hc2tTZXQoKS52YWxpZFBvc2l0aW9uc1tpXSkgPT09IHVuZGVmaW5lZCB8fCBudWxsID09IHZhbGlkUG9zLm1hdGNoLmZuKSAmJiBpIDwgcG9zICsgKHN0YXRpY0lucHV0c0JlZm9yZVBvc0FsdGVybmF0ZSAtIHN0YXRpY0lucHV0c0JlZm9yZVBvcykgJiYgc3RhdGljSW5wdXRzQmVmb3JlUG9zQWx0ZXJuYXRlKys7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzVmFsaWRSc2x0ID0gaXNWYWxpZCgocG9zICs9IHN0YXRpY0lucHV0c0JlZm9yZVBvc0FsdGVybmF0ZSAtIHN0YXRpY0lucHV0c0JlZm9yZVBvcykgPiB0YXJnZXRMdnAgPyB0YXJnZXRMdnAgOiBwb3MsIGMsIHN0cmljdCwgZnJvbVNldFZhbGlkLCAhMCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc1ZhbGlkUnNsdCkgcmV0dXJuICExO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc2V0TWFza1NldCgpLCBnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnMgPSAkLmV4dGVuZCghMCwge30sIHZhbGlkUHNDbG9uZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBpc1ZhbGlkUnNsdDtcbiAgICAgICAgICAgICAgICAgICAgfShtYXNrUG9zLCBjLCBzdHJpY3QpKSwgITAgPT09IHJlc3VsdCAmJiAocmVzdWx0ID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgcG9zOiBtYXNrUG9zXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoJC5pc0Z1bmN0aW9uKG9wdHMucG9zdFZhbGlkYXRpb24pICYmICExICE9PSByZXN1bHQgJiYgIXN0cmljdCAmJiAhMCAhPT0gZnJvbVNldFZhbGlkICYmICEwICE9PSB2YWxpZGF0ZU9ubHkpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHBvc3RSZXN1bHQgPSBvcHRzLnBvc3RWYWxpZGF0aW9uKGdldEJ1ZmZlcighMCksIHJlc3VsdCwgb3B0cyk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChwb3N0UmVzdWx0LnJlZnJlc2hGcm9tQnVmZmVyICYmIHBvc3RSZXN1bHQuYnVmZmVyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgcmVmcmVzaCA9IHBvc3RSZXN1bHQucmVmcmVzaEZyb21CdWZmZXI7XG4gICAgICAgICAgICAgICAgICAgICAgICByZWZyZXNoRnJvbUJ1ZmZlcighMCA9PT0gcmVmcmVzaCA/IHJlZnJlc2ggOiByZWZyZXNoLnN0YXJ0LCByZWZyZXNoLmVuZCwgcG9zdFJlc3VsdC5idWZmZXIpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9ICEwID09PSBwb3N0UmVzdWx0ID8gcmVzdWx0IDogcG9zdFJlc3VsdDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCAmJiByZXN1bHQucG9zID09PSB1bmRlZmluZWQgJiYgKHJlc3VsdC5wb3MgPSBtYXNrUG9zKSwgITEgIT09IHJlc3VsdCAmJiAhMCAhPT0gdmFsaWRhdGVPbmx5IHx8IChyZXNldE1hc2tTZXQoITApLCBcbiAgICAgICAgICAgICAgICBnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnMgPSAkLmV4dGVuZCghMCwge30sIHBvc2l0aW9uc0Nsb25lKSksIHJlc3VsdDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzTWFzayhwb3MsIHN0cmljdCkge1xuICAgICAgICAgICAgICAgIHZhciB0ZXN0ID0gZ2V0VGVzdFRlbXBsYXRlKHBvcykubWF0Y2g7XG4gICAgICAgICAgICAgICAgaWYgKFwiXCIgPT09IHRlc3QuZGVmICYmICh0ZXN0ID0gZ2V0VGVzdChwb3MpLm1hdGNoKSwgbnVsbCAhPSB0ZXN0LmZuKSByZXR1cm4gdGVzdC5mbjtcbiAgICAgICAgICAgICAgICBpZiAoITAgIT09IHN0cmljdCAmJiBwb3MgPiAtMSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgdGVzdHMgPSBnZXRUZXN0cyhwb3MpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGVzdHMubGVuZ3RoID4gMSArIChcIlwiID09PSB0ZXN0c1t0ZXN0cy5sZW5ndGggLSAxXS5tYXRjaC5kZWYgPyAxIDogMCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiAhMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZ1bmN0aW9uIHNlZWtOZXh0KHBvcywgbmV3QmxvY2spIHtcbiAgICAgICAgICAgICAgICB2YXIgbWFza0wgPSBnZXRNYXNrU2V0KCkubWFza0xlbmd0aDtcbiAgICAgICAgICAgICAgICBpZiAocG9zID49IG1hc2tMKSByZXR1cm4gbWFza0w7XG4gICAgICAgICAgICAgICAgdmFyIHBvc2l0aW9uID0gcG9zO1xuICAgICAgICAgICAgICAgIGZvciAoZ2V0VGVzdHMobWFza0wgKyAxKS5sZW5ndGggPiAxICYmIChnZXRNYXNrVGVtcGxhdGUoITAsIG1hc2tMICsgMSwgITApLCBtYXNrTCA9IGdldE1hc2tTZXQoKS5tYXNrTGVuZ3RoKTsgKytwb3NpdGlvbiA8IG1hc2tMICYmICghMCA9PT0gbmV3QmxvY2sgJiYgKCEwICE9PSBnZXRUZXN0KHBvc2l0aW9uKS5tYXRjaC5uZXdCbG9ja01hcmtlciB8fCAhaXNNYXNrKHBvc2l0aW9uKSkgfHwgITAgIT09IG5ld0Jsb2NrICYmICFpc01hc2socG9zaXRpb24pKTsgKSA7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHBvc2l0aW9uO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZnVuY3Rpb24gc2Vla1ByZXZpb3VzKHBvcywgbmV3QmxvY2spIHtcbiAgICAgICAgICAgICAgICB2YXIgdGVzdHMsIHBvc2l0aW9uID0gcG9zO1xuICAgICAgICAgICAgICAgIGlmIChwb3NpdGlvbiA8PSAwKSByZXR1cm4gMDtcbiAgICAgICAgICAgICAgICBmb3IgKDstLXBvc2l0aW9uID4gMCAmJiAoITAgPT09IG5ld0Jsb2NrICYmICEwICE9PSBnZXRUZXN0KHBvc2l0aW9uKS5tYXRjaC5uZXdCbG9ja01hcmtlciB8fCAhMCAhPT0gbmV3QmxvY2sgJiYgIWlzTWFzayhwb3NpdGlvbikgJiYgKCh0ZXN0cyA9IGdldFRlc3RzKHBvc2l0aW9uKSkubGVuZ3RoIDwgMiB8fCAyID09PSB0ZXN0cy5sZW5ndGggJiYgXCJcIiA9PT0gdGVzdHNbMV0ubWF0Y2guZGVmKSk7ICkgO1xuICAgICAgICAgICAgICAgIHJldHVybiBwb3NpdGlvbjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZ1bmN0aW9uIGdldEJ1ZmZlckVsZW1lbnQocG9zaXRpb24pIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zW3Bvc2l0aW9uXSA9PT0gdW5kZWZpbmVkID8gZ2V0UGxhY2Vob2xkZXIocG9zaXRpb24pIDogZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zW3Bvc2l0aW9uXS5pbnB1dDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZ1bmN0aW9uIHdyaXRlQnVmZmVyKGlucHV0LCBidWZmZXIsIGNhcmV0UG9zLCBldmVudCwgdHJpZ2dlcklucHV0RXZlbnQpIHtcbiAgICAgICAgICAgICAgICBpZiAoZXZlbnQgJiYgJC5pc0Z1bmN0aW9uKG9wdHMub25CZWZvcmVXcml0ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHJlc3VsdCA9IG9wdHMub25CZWZvcmVXcml0ZS5jYWxsKGlucHV0bWFzaywgZXZlbnQsIGJ1ZmZlciwgY2FyZXRQb3MsIG9wdHMpO1xuICAgICAgICAgICAgICAgICAgICBpZiAocmVzdWx0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocmVzdWx0LnJlZnJlc2hGcm9tQnVmZmVyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHJlZnJlc2ggPSByZXN1bHQucmVmcmVzaEZyb21CdWZmZXI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVmcmVzaEZyb21CdWZmZXIoITAgPT09IHJlZnJlc2ggPyByZWZyZXNoIDogcmVmcmVzaC5zdGFydCwgcmVmcmVzaC5lbmQsIHJlc3VsdC5idWZmZXIgfHwgYnVmZmVyKSwgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnVmZmVyID0gZ2V0QnVmZmVyKCEwKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGNhcmV0UG9zICE9PSB1bmRlZmluZWQgJiYgKGNhcmV0UG9zID0gcmVzdWx0LmNhcmV0ICE9PSB1bmRlZmluZWQgPyByZXN1bHQuY2FyZXQgOiBjYXJldFBvcyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaW5wdXQgIT09IHVuZGVmaW5lZCAmJiAoaW5wdXQuaW5wdXRtYXNrLl92YWx1ZVNldChidWZmZXIuam9pbihcIlwiKSksIGNhcmV0UG9zID09PSB1bmRlZmluZWQgfHwgZXZlbnQgIT09IHVuZGVmaW5lZCAmJiBcImJsdXJcIiA9PT0gZXZlbnQudHlwZSA/IHJlbmRlckNvbG9yTWFzayhpbnB1dCwgY2FyZXRQb3MsIDAgPT09IGJ1ZmZlci5sZW5ndGgpIDogYW5kcm9pZCAmJiBldmVudCAmJiBcImlucHV0XCIgPT09IGV2ZW50LnR5cGUgPyBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICBjYXJldChpbnB1dCwgY2FyZXRQb3MpO1xuICAgICAgICAgICAgICAgIH0sIDApIDogY2FyZXQoaW5wdXQsIGNhcmV0UG9zKSwgITAgPT09IHRyaWdnZXJJbnB1dEV2ZW50ICYmIChza2lwSW5wdXRFdmVudCA9ICEwLCBcbiAgICAgICAgICAgICAgICAkKGlucHV0KS50cmlnZ2VyKFwiaW5wdXRcIikpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZ1bmN0aW9uIGdldFBsYWNlaG9sZGVyKHBvcywgdGVzdCwgcmV0dXJuUEwpIHtcbiAgICAgICAgICAgICAgICBpZiAoKHRlc3QgPSB0ZXN0IHx8IGdldFRlc3QocG9zKS5tYXRjaCkucGxhY2Vob2xkZXIgIT09IHVuZGVmaW5lZCB8fCAhMCA9PT0gcmV0dXJuUEwpIHJldHVybiAkLmlzRnVuY3Rpb24odGVzdC5wbGFjZWhvbGRlcikgPyB0ZXN0LnBsYWNlaG9sZGVyKG9wdHMpIDogdGVzdC5wbGFjZWhvbGRlcjtcbiAgICAgICAgICAgICAgICBpZiAobnVsbCA9PT0gdGVzdC5mbikge1xuICAgICAgICAgICAgICAgICAgICBpZiAocG9zID4gLTEgJiYgZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zW3Bvc10gPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHByZXZUZXN0LCB0ZXN0cyA9IGdldFRlc3RzKHBvcyksIHN0YXRpY0FsdGVybmF0aW9ucyA9IFtdO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRlc3RzLmxlbmd0aCA+IDEgKyAoXCJcIiA9PT0gdGVzdHNbdGVzdHMubGVuZ3RoIC0gMV0ubWF0Y2guZGVmID8gMSA6IDApKSBmb3IgKHZhciBpID0gMDsgaSA8IHRlc3RzLmxlbmd0aDsgaSsrKSBpZiAoITAgIT09IHRlc3RzW2ldLm1hdGNoLm9wdGlvbmFsaXR5ICYmICEwICE9PSB0ZXN0c1tpXS5tYXRjaC5vcHRpb25hbFF1YW50aWZpZXIgJiYgKG51bGwgPT09IHRlc3RzW2ldLm1hdGNoLmZuIHx8IHByZXZUZXN0ID09PSB1bmRlZmluZWQgfHwgITEgIT09IHRlc3RzW2ldLm1hdGNoLmZuLnRlc3QocHJldlRlc3QubWF0Y2guZGVmLCBnZXRNYXNrU2V0KCksIHBvcywgITAsIG9wdHMpKSAmJiAoc3RhdGljQWx0ZXJuYXRpb25zLnB1c2godGVzdHNbaV0pLCBcbiAgICAgICAgICAgICAgICAgICAgICAgIG51bGwgPT09IHRlc3RzW2ldLm1hdGNoLmZuICYmIChwcmV2VGVzdCA9IHRlc3RzW2ldKSwgc3RhdGljQWx0ZXJuYXRpb25zLmxlbmd0aCA+IDEgJiYgL1swLTlhLWJBLVpdLy50ZXN0KHN0YXRpY0FsdGVybmF0aW9uc1swXS5tYXRjaC5kZWYpKSkgcmV0dXJuIG9wdHMucGxhY2Vob2xkZXIuY2hhckF0KHBvcyAlIG9wdHMucGxhY2Vob2xkZXIubGVuZ3RoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGVzdC5kZWY7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBvcHRzLnBsYWNlaG9sZGVyLmNoYXJBdChwb3MgJSBvcHRzLnBsYWNlaG9sZGVyLmxlbmd0aCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmdW5jdGlvbiBjaGVja1ZhbChpbnB1dCwgd3JpdGVPdXQsIHN0cmljdCwgbnB0dmwsIGluaXRpYXRpbmdFdmVudCkge1xuICAgICAgICAgICAgICAgIGZ1bmN0aW9uIGlzVGVtcGxhdGVNYXRjaChuZHgsIGNoYXJDb2Rlcykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gLTEgIT09IGdldEJ1ZmZlclRlbXBsYXRlKCkuc2xpY2UobmR4LCBzZWVrTmV4dChuZHgpKS5qb2luKFwiXCIpLmluZGV4T2YoY2hhckNvZGVzKSAmJiAhaXNNYXNrKG5keCkgJiYgZ2V0VGVzdChuZHgpLm1hdGNoLm5hdGl2ZURlZiA9PT0gY2hhckNvZGVzLmNoYXJBdChjaGFyQ29kZXMubGVuZ3RoIC0gMSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciBpbnB1dFZhbHVlID0gbnB0dmwuc2xpY2UoKSwgY2hhckNvZGVzID0gXCJcIiwgaW5pdGlhbE5keCA9IC0xLCByZXN1bHQgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgaWYgKHJlc2V0TWFza1NldCgpLCBzdHJpY3QgfHwgITAgPT09IG9wdHMuYXV0b1VubWFzaykgaW5pdGlhbE5keCA9IHNlZWtOZXh0KGluaXRpYWxOZHgpOyBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHN0YXRpY0lucHV0ID0gZ2V0QnVmZmVyVGVtcGxhdGUoKS5zbGljZSgwLCBzZWVrTmV4dCgtMSkpLmpvaW4oXCJcIiksIG1hdGNoZXMgPSBpbnB1dFZhbHVlLmpvaW4oXCJcIikubWF0Y2gobmV3IFJlZ0V4cChcIl5cIiArIElucHV0bWFzay5lc2NhcGVSZWdleChzdGF0aWNJbnB1dCksIFwiZ1wiKSk7XG4gICAgICAgICAgICAgICAgICAgIG1hdGNoZXMgJiYgbWF0Y2hlcy5sZW5ndGggPiAwICYmIChpbnB1dFZhbHVlLnNwbGljZSgwLCBtYXRjaGVzLmxlbmd0aCAqIHN0YXRpY0lucHV0Lmxlbmd0aCksIFxuICAgICAgICAgICAgICAgICAgICBpbml0aWFsTmR4ID0gc2Vla05leHQoaW5pdGlhbE5keCkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoLTEgPT09IGluaXRpYWxOZHggPyAoZ2V0TWFza1NldCgpLnAgPSBzZWVrTmV4dChpbml0aWFsTmR4KSwgaW5pdGlhbE5keCA9IDApIDogZ2V0TWFza1NldCgpLnAgPSBpbml0aWFsTmR4LCBcbiAgICAgICAgICAgICAgICAkLmVhY2goaW5wdXRWYWx1ZSwgZnVuY3Rpb24obmR4LCBjaGFyQ29kZSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoY2hhckNvZGUgIT09IHVuZGVmaW5lZCkgaWYgKGdldE1hc2tTZXQoKS52YWxpZFBvc2l0aW9uc1tuZHhdID09PSB1bmRlZmluZWQgJiYgaW5wdXRWYWx1ZVtuZHhdID09PSBnZXRQbGFjZWhvbGRlcihuZHgpICYmIGlzTWFzayhuZHgsICEwKSAmJiAhMSA9PT0gaXNWYWxpZChuZHgsIGlucHV0VmFsdWVbbmR4XSwgITAsIHVuZGVmaW5lZCwgdW5kZWZpbmVkLCAhMCkpIGdldE1hc2tTZXQoKS5wKys7IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGtleXByZXNzID0gbmV3ICQuRXZlbnQoXCJfY2hlY2t2YWxcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICBrZXlwcmVzcy53aGljaCA9IGNoYXJDb2RlLmNoYXJDb2RlQXQoMCksIGNoYXJDb2RlcyArPSBjaGFyQ29kZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBsdnAgPSBnZXRMYXN0VmFsaWRQb3NpdGlvbih1bmRlZmluZWQsICEwKSwgbHZUZXN0ID0gZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zW2x2cF0sIG5leHRUZXN0ID0gZ2V0VGVzdFRlbXBsYXRlKGx2cCArIDEsIGx2VGVzdCA/IGx2VGVzdC5sb2NhdG9yLnNsaWNlKCkgOiB1bmRlZmluZWQsIGx2cCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWlzVGVtcGxhdGVNYXRjaChpbml0aWFsTmR4LCBjaGFyQ29kZXMpIHx8IHN0cmljdCB8fCBvcHRzLmF1dG9Vbm1hc2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgcG9zID0gc3RyaWN0ID8gbmR4IDogbnVsbCA9PSBuZXh0VGVzdC5tYXRjaC5mbiAmJiBuZXh0VGVzdC5tYXRjaC5vcHRpb25hbGl0eSAmJiBsdnAgKyAxIDwgZ2V0TWFza1NldCgpLnAgPyBsdnAgKyAxIDogZ2V0TWFza1NldCgpLnA7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gRXZlbnRIYW5kbGVycy5rZXlwcmVzc0V2ZW50LmNhbGwoaW5wdXQsIGtleXByZXNzLCAhMCwgITEsIHN0cmljdCwgcG9zKSwgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5pdGlhbE5keCA9IHBvcyArIDEsIGNoYXJDb2RlcyA9IFwiXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgcmVzdWx0ID0gRXZlbnRIYW5kbGVycy5rZXlwcmVzc0V2ZW50LmNhbGwoaW5wdXQsIGtleXByZXNzLCAhMCwgITEsICEwLCBsdnAgKyAxKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghMSAhPT0gcmVzdWx0ICYmICFzdHJpY3QgJiYgJC5pc0Z1bmN0aW9uKG9wdHMub25CZWZvcmVXcml0ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgb3JpZ1Jlc3VsdCA9IHJlc3VsdDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocmVzdWx0ID0gb3B0cy5vbkJlZm9yZVdyaXRlLmNhbGwoaW5wdXRtYXNrLCBrZXlwcmVzcywgZ2V0QnVmZmVyKCksIHJlc3VsdC5mb3J3YXJkUG9zaXRpb24sIG9wdHMpLCBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAocmVzdWx0ID0gJC5leHRlbmQob3JpZ1Jlc3VsdCwgcmVzdWx0KSkgJiYgcmVzdWx0LnJlZnJlc2hGcm9tQnVmZmVyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciByZWZyZXNoID0gcmVzdWx0LnJlZnJlc2hGcm9tQnVmZmVyO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWZyZXNoRnJvbUJ1ZmZlcighMCA9PT0gcmVmcmVzaCA/IHJlZnJlc2ggOiByZWZyZXNoLnN0YXJ0LCByZWZyZXNoLmVuZCwgcmVzdWx0LmJ1ZmZlciksIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNldE1hc2tTZXQoITApLCByZXN1bHQuY2FyZXQgJiYgKGdldE1hc2tTZXQoKS5wID0gcmVzdWx0LmNhcmV0LCByZXN1bHQuZm9yd2FyZFBvc2l0aW9uID0gcmVzdWx0LmNhcmV0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KSwgd3JpdGVPdXQpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNhcmV0UG9zID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgICAgICBkb2N1bWVudC5hY3RpdmVFbGVtZW50ID09PSBpbnB1dCAmJiByZXN1bHQgJiYgKGNhcmV0UG9zID0gb3B0cy5udW1lcmljSW5wdXQgPyBzZWVrUHJldmlvdXMocmVzdWx0LmZvcndhcmRQb3NpdGlvbikgOiByZXN1bHQuZm9yd2FyZFBvc2l0aW9uKSwgXG4gICAgICAgICAgICAgICAgICAgIHdyaXRlQnVmZmVyKGlucHV0LCBnZXRCdWZmZXIoKSwgY2FyZXRQb3MsIGluaXRpYXRpbmdFdmVudCB8fCBuZXcgJC5FdmVudChcImNoZWNrdmFsXCIpLCBpbml0aWF0aW5nRXZlbnQgJiYgXCJpbnB1dFwiID09PSBpbml0aWF0aW5nRXZlbnQudHlwZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZnVuY3Rpb24gdW5tYXNrZWR2YWx1ZShpbnB1dCkge1xuICAgICAgICAgICAgICAgIGlmIChpbnB1dCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaW5wdXQuaW5wdXRtYXNrID09PSB1bmRlZmluZWQpIHJldHVybiBpbnB1dC52YWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgaW5wdXQuaW5wdXRtYXNrICYmIGlucHV0LmlucHV0bWFzay5yZWZyZXNoVmFsdWUgJiYgRXZlbnRIYW5kbGVycy5zZXRWYWx1ZUV2ZW50LmNhbGwoaW5wdXQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgdW1WYWx1ZSA9IFtdLCB2cHMgPSBnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnM7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgcG5keCBpbiB2cHMpIHZwc1twbmR4XS5tYXRjaCAmJiBudWxsICE9IHZwc1twbmR4XS5tYXRjaC5mbiAmJiB1bVZhbHVlLnB1c2godnBzW3BuZHhdLmlucHV0KTtcbiAgICAgICAgICAgICAgICB2YXIgdW5tYXNrZWRWYWx1ZSA9IDAgPT09IHVtVmFsdWUubGVuZ3RoID8gXCJcIiA6IChpc1JUTCA/IHVtVmFsdWUucmV2ZXJzZSgpIDogdW1WYWx1ZSkuam9pbihcIlwiKTtcbiAgICAgICAgICAgICAgICBpZiAoJC5pc0Z1bmN0aW9uKG9wdHMub25Vbk1hc2spKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBidWZmZXJWYWx1ZSA9IChpc1JUTCA/IGdldEJ1ZmZlcigpLnNsaWNlKCkucmV2ZXJzZSgpIDogZ2V0QnVmZmVyKCkpLmpvaW4oXCJcIik7XG4gICAgICAgICAgICAgICAgICAgIHVubWFza2VkVmFsdWUgPSBvcHRzLm9uVW5NYXNrLmNhbGwoaW5wdXRtYXNrLCBidWZmZXJWYWx1ZSwgdW5tYXNrZWRWYWx1ZSwgb3B0cyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiB1bm1hc2tlZFZhbHVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZnVuY3Rpb24gY2FyZXQoaW5wdXQsIGJlZ2luLCBlbmQsIG5vdHJhbnNsYXRlKSB7XG4gICAgICAgICAgICAgICAgZnVuY3Rpb24gdHJhbnNsYXRlUG9zaXRpb24ocG9zKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAhMCA9PT0gbm90cmFuc2xhdGUgfHwgIWlzUlRMIHx8IFwibnVtYmVyXCIgIT0gdHlwZW9mIHBvcyB8fCBvcHRzLmdyZWVkeSAmJiBcIlwiID09PSBvcHRzLnBsYWNlaG9sZGVyIHx8IChwb3MgPSBnZXRCdWZmZXIoKS5qb2luKFwiXCIpLmxlbmd0aCAtIHBvcyksIFxuICAgICAgICAgICAgICAgICAgICBwb3M7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciByYW5nZTtcbiAgICAgICAgICAgICAgICBpZiAoYmVnaW4gPT09IHVuZGVmaW5lZCkgcmV0dXJuIGlucHV0LnNldFNlbGVjdGlvblJhbmdlID8gKGJlZ2luID0gaW5wdXQuc2VsZWN0aW9uU3RhcnQsIFxuICAgICAgICAgICAgICAgIGVuZCA9IGlucHV0LnNlbGVjdGlvbkVuZCkgOiB3aW5kb3cuZ2V0U2VsZWN0aW9uID8gKHJhbmdlID0gd2luZG93LmdldFNlbGVjdGlvbigpLmdldFJhbmdlQXQoMCkpLmNvbW1vbkFuY2VzdG9yQ29udGFpbmVyLnBhcmVudE5vZGUgIT09IGlucHV0ICYmIHJhbmdlLmNvbW1vbkFuY2VzdG9yQ29udGFpbmVyICE9PSBpbnB1dCB8fCAoYmVnaW4gPSByYW5nZS5zdGFydE9mZnNldCwgXG4gICAgICAgICAgICAgICAgZW5kID0gcmFuZ2UuZW5kT2Zmc2V0KSA6IGRvY3VtZW50LnNlbGVjdGlvbiAmJiBkb2N1bWVudC5zZWxlY3Rpb24uY3JlYXRlUmFuZ2UgJiYgKGVuZCA9IChiZWdpbiA9IDAgLSAocmFuZ2UgPSBkb2N1bWVudC5zZWxlY3Rpb24uY3JlYXRlUmFuZ2UoKSkuZHVwbGljYXRlKCkubW92ZVN0YXJ0KFwiY2hhcmFjdGVyXCIsIC1pbnB1dC5pbnB1dG1hc2suX3ZhbHVlR2V0KCkubGVuZ3RoKSkgKyByYW5nZS50ZXh0Lmxlbmd0aCksIFxuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgYmVnaW46IHRyYW5zbGF0ZVBvc2l0aW9uKGJlZ2luKSxcbiAgICAgICAgICAgICAgICAgICAgZW5kOiB0cmFuc2xhdGVQb3NpdGlvbihlbmQpXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICBpZiAoYmVnaW4uYmVnaW4gIT09IHVuZGVmaW5lZCAmJiAoZW5kID0gYmVnaW4uZW5kLCBiZWdpbiA9IGJlZ2luLmJlZ2luKSwgXCJudW1iZXJcIiA9PSB0eXBlb2YgYmVnaW4pIHtcbiAgICAgICAgICAgICAgICAgICAgYmVnaW4gPSB0cmFuc2xhdGVQb3NpdGlvbihiZWdpbiksIGVuZCA9IFwibnVtYmVyXCIgPT0gdHlwZW9mIChlbmQgPSB0cmFuc2xhdGVQb3NpdGlvbihlbmQpKSA/IGVuZCA6IGJlZ2luO1xuICAgICAgICAgICAgICAgICAgICB2YXIgc2Nyb2xsQ2FsYyA9IHBhcnNlSW50KCgoaW5wdXQub3duZXJEb2N1bWVudC5kZWZhdWx0VmlldyB8fCB3aW5kb3cpLmdldENvbXB1dGVkU3R5bGUgPyAoaW5wdXQub3duZXJEb2N1bWVudC5kZWZhdWx0VmlldyB8fCB3aW5kb3cpLmdldENvbXB1dGVkU3R5bGUoaW5wdXQsIG51bGwpIDogaW5wdXQuY3VycmVudFN0eWxlKS5mb250U2l6ZSkgKiBlbmQ7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpbnB1dC5zY3JvbGxMZWZ0ID0gc2Nyb2xsQ2FsYyA+IGlucHV0LnNjcm9sbFdpZHRoID8gc2Nyb2xsQ2FsYyA6IDAsIG1vYmlsZSB8fCAhMSAhPT0gb3B0cy5pbnNlcnRNb2RlIHx8IGJlZ2luICE9PSBlbmQgfHwgZW5kKyssIFxuICAgICAgICAgICAgICAgICAgICBpbnB1dC5zZXRTZWxlY3Rpb25SYW5nZSkgaW5wdXQuc2VsZWN0aW9uU3RhcnQgPSBiZWdpbiwgaW5wdXQuc2VsZWN0aW9uRW5kID0gZW5kOyBlbHNlIGlmICh3aW5kb3cuZ2V0U2VsZWN0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocmFuZ2UgPSBkb2N1bWVudC5jcmVhdGVSYW5nZSgpLCBpbnB1dC5maXJzdENoaWxkID09PSB1bmRlZmluZWQgfHwgbnVsbCA9PT0gaW5wdXQuZmlyc3RDaGlsZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciB0ZXh0Tm9kZSA9IGRvY3VtZW50LmNyZWF0ZVRleHROb2RlKFwiXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlucHV0LmFwcGVuZENoaWxkKHRleHROb2RlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHJhbmdlLnNldFN0YXJ0KGlucHV0LmZpcnN0Q2hpbGQsIGJlZ2luIDwgaW5wdXQuaW5wdXRtYXNrLl92YWx1ZUdldCgpLmxlbmd0aCA/IGJlZ2luIDogaW5wdXQuaW5wdXRtYXNrLl92YWx1ZUdldCgpLmxlbmd0aCksIFxuICAgICAgICAgICAgICAgICAgICAgICAgcmFuZ2Uuc2V0RW5kKGlucHV0LmZpcnN0Q2hpbGQsIGVuZCA8IGlucHV0LmlucHV0bWFzay5fdmFsdWVHZXQoKS5sZW5ndGggPyBlbmQgOiBpbnB1dC5pbnB1dG1hc2suX3ZhbHVlR2V0KCkubGVuZ3RoKSwgXG4gICAgICAgICAgICAgICAgICAgICAgICByYW5nZS5jb2xsYXBzZSghMCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgc2VsID0gd2luZG93LmdldFNlbGVjdGlvbigpO1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsLnJlbW92ZUFsbFJhbmdlcygpLCBzZWwuYWRkUmFuZ2UocmFuZ2UpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaW5wdXQuY3JlYXRlVGV4dFJhbmdlICYmICgocmFuZ2UgPSBpbnB1dC5jcmVhdGVUZXh0UmFuZ2UoKSkuY29sbGFwc2UoITApLCBcbiAgICAgICAgICAgICAgICAgICAgcmFuZ2UubW92ZUVuZChcImNoYXJhY3RlclwiLCBlbmQpLCByYW5nZS5tb3ZlU3RhcnQoXCJjaGFyYWN0ZXJcIiwgYmVnaW4pLCByYW5nZS5zZWxlY3QoKSk7XG4gICAgICAgICAgICAgICAgICAgIHJlbmRlckNvbG9yTWFzayhpbnB1dCwge1xuICAgICAgICAgICAgICAgICAgICAgICAgYmVnaW46IGJlZ2luLFxuICAgICAgICAgICAgICAgICAgICAgICAgZW5kOiBlbmRcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZnVuY3Rpb24gZGV0ZXJtaW5lTGFzdFJlcXVpcmVkUG9zaXRpb24ocmV0dXJuRGVmaW5pdGlvbikge1xuICAgICAgICAgICAgICAgIHZhciBwb3MsIHRlc3RQb3MsIGJ1ZmZlciA9IGdldEJ1ZmZlcigpLCBibCA9IGJ1ZmZlci5sZW5ndGgsIGx2cCA9IGdldExhc3RWYWxpZFBvc2l0aW9uKCksIHBvc2l0aW9ucyA9IHt9LCBsdlRlc3QgPSBnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnNbbHZwXSwgbmR4SW50bHpyID0gbHZUZXN0ICE9PSB1bmRlZmluZWQgPyBsdlRlc3QubG9jYXRvci5zbGljZSgpIDogdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIGZvciAocG9zID0gbHZwICsgMTsgcG9zIDwgYnVmZmVyLmxlbmd0aDsgcG9zKyspIG5keEludGx6ciA9ICh0ZXN0UG9zID0gZ2V0VGVzdFRlbXBsYXRlKHBvcywgbmR4SW50bHpyLCBwb3MgLSAxKSkubG9jYXRvci5zbGljZSgpLCBcbiAgICAgICAgICAgICAgICBwb3NpdGlvbnNbcG9zXSA9ICQuZXh0ZW5kKCEwLCB7fSwgdGVzdFBvcyk7XG4gICAgICAgICAgICAgICAgdmFyIGx2VGVzdEFsdCA9IGx2VGVzdCAmJiBsdlRlc3QuYWx0ZXJuYXRpb24gIT09IHVuZGVmaW5lZCA/IGx2VGVzdC5sb2NhdG9yW2x2VGVzdC5hbHRlcm5hdGlvbl0gOiB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgZm9yIChwb3MgPSBibCAtIDE7IHBvcyA+IGx2cCAmJiAoKCh0ZXN0UG9zID0gcG9zaXRpb25zW3Bvc10pLm1hdGNoLm9wdGlvbmFsaXR5IHx8IHRlc3RQb3MubWF0Y2gub3B0aW9uYWxRdWFudGlmaWVyICYmIHRlc3RQb3MubWF0Y2gubmV3QmxvY2tNYXJrZXIgfHwgbHZUZXN0QWx0ICYmIChsdlRlc3RBbHQgIT09IHBvc2l0aW9uc1twb3NdLmxvY2F0b3JbbHZUZXN0LmFsdGVybmF0aW9uXSAmJiBudWxsICE9IHRlc3RQb3MubWF0Y2guZm4gfHwgbnVsbCA9PT0gdGVzdFBvcy5tYXRjaC5mbiAmJiB0ZXN0UG9zLmxvY2F0b3JbbHZUZXN0LmFsdGVybmF0aW9uXSAmJiBjaGVja0FsdGVybmF0aW9uTWF0Y2godGVzdFBvcy5sb2NhdG9yW2x2VGVzdC5hbHRlcm5hdGlvbl0udG9TdHJpbmcoKS5zcGxpdChcIixcIiksIGx2VGVzdEFsdC50b1N0cmluZygpLnNwbGl0KFwiLFwiKSkgJiYgXCJcIiAhPT0gZ2V0VGVzdHMocG9zKVswXS5kZWYpKSAmJiBidWZmZXJbcG9zXSA9PT0gZ2V0UGxhY2Vob2xkZXIocG9zLCB0ZXN0UG9zLm1hdGNoKSk7IHBvcy0tKSBibC0tO1xuICAgICAgICAgICAgICAgIHJldHVybiByZXR1cm5EZWZpbml0aW9uID8ge1xuICAgICAgICAgICAgICAgICAgICBsOiBibCxcbiAgICAgICAgICAgICAgICAgICAgZGVmOiBwb3NpdGlvbnNbYmxdID8gcG9zaXRpb25zW2JsXS5tYXRjaCA6IHVuZGVmaW5lZFxuICAgICAgICAgICAgICAgIH0gOiBibDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZ1bmN0aW9uIGNsZWFyT3B0aW9uYWxUYWlsKGJ1ZmZlcikge1xuICAgICAgICAgICAgICAgIGZvciAodmFyIHZhbGlkUG9zLCBybCA9IGRldGVybWluZUxhc3RSZXF1aXJlZFBvc2l0aW9uKCksIGJsID0gYnVmZmVyLmxlbmd0aCwgbHYgPSBnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnNbZ2V0TGFzdFZhbGlkUG9zaXRpb24oKV07IHJsIDwgYmwgJiYgIWlzTWFzayhybCwgITApICYmICh2YWxpZFBvcyA9IGx2ICE9PSB1bmRlZmluZWQgPyBnZXRUZXN0VGVtcGxhdGUocmwsIGx2LmxvY2F0b3Iuc2xpY2UoXCJcIiksIGx2KSA6IGdldFRlc3QocmwpKSAmJiAhMCAhPT0gdmFsaWRQb3MubWF0Y2gub3B0aW9uYWxpdHkgJiYgKCEwICE9PSB2YWxpZFBvcy5tYXRjaC5vcHRpb25hbFF1YW50aWZpZXIgJiYgITAgIT09IHZhbGlkUG9zLm1hdGNoLm5ld0Jsb2NrTWFya2VyIHx8IHJsICsgMSA9PT0gYmwgJiYgXCJcIiA9PT0gKGx2ICE9PSB1bmRlZmluZWQgPyBnZXRUZXN0VGVtcGxhdGUocmwgKyAxLCBsdi5sb2NhdG9yLnNsaWNlKFwiXCIpLCBsdikgOiBnZXRUZXN0KHJsICsgMSkpLm1hdGNoLmRlZik7ICkgcmwrKztcbiAgICAgICAgICAgICAgICBmb3IgKDsodmFsaWRQb3MgPSBnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnNbcmwgLSAxXSkgJiYgdmFsaWRQb3MgJiYgdmFsaWRQb3MubWF0Y2gub3B0aW9uYWxpdHkgJiYgdmFsaWRQb3MuaW5wdXQgPT09IG9wdHMuc2tpcE9wdGlvbmFsUGFydENoYXJhY3RlcjsgKSBybC0tO1xuICAgICAgICAgICAgICAgIHJldHVybiBidWZmZXIuc3BsaWNlKHJsKSwgYnVmZmVyO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZnVuY3Rpb24gaXNDb21wbGV0ZShidWZmZXIpIHtcbiAgICAgICAgICAgICAgICBpZiAoJC5pc0Z1bmN0aW9uKG9wdHMuaXNDb21wbGV0ZSkpIHJldHVybiBvcHRzLmlzQ29tcGxldGUoYnVmZmVyLCBvcHRzKTtcbiAgICAgICAgICAgICAgICBpZiAoXCIqXCIgPT09IG9wdHMucmVwZWF0KSByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIHZhciBjb21wbGV0ZSA9ICExLCBscnAgPSBkZXRlcm1pbmVMYXN0UmVxdWlyZWRQb3NpdGlvbighMCksIGFtbCA9IHNlZWtQcmV2aW91cyhscnAubCk7XG4gICAgICAgICAgICAgICAgaWYgKGxycC5kZWYgPT09IHVuZGVmaW5lZCB8fCBscnAuZGVmLm5ld0Jsb2NrTWFya2VyIHx8IGxycC5kZWYub3B0aW9uYWxpdHkgfHwgbHJwLmRlZi5vcHRpb25hbFF1YW50aWZpZXIpIHtcbiAgICAgICAgICAgICAgICAgICAgY29tcGxldGUgPSAhMDtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPD0gYW1sOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciB0ZXN0ID0gZ2V0VGVzdFRlbXBsYXRlKGkpLm1hdGNoO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG51bGwgIT09IHRlc3QuZm4gJiYgZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zW2ldID09PSB1bmRlZmluZWQgJiYgITAgIT09IHRlc3Qub3B0aW9uYWxpdHkgJiYgITAgIT09IHRlc3Qub3B0aW9uYWxRdWFudGlmaWVyIHx8IG51bGwgPT09IHRlc3QuZm4gJiYgYnVmZmVyW2ldICE9PSBnZXRQbGFjZWhvbGRlcihpLCB0ZXN0KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbXBsZXRlID0gITE7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIGNvbXBsZXRlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZnVuY3Rpb24gaGFuZGxlUmVtb3ZlKGlucHV0LCBrLCBwb3MsIHN0cmljdCwgZnJvbUlzVmFsaWQpIHtcbiAgICAgICAgICAgICAgICBpZiAoKG9wdHMubnVtZXJpY0lucHV0IHx8IGlzUlRMKSAmJiAoayA9PT0gSW5wdXRtYXNrLmtleUNvZGUuQkFDS1NQQUNFID8gayA9IElucHV0bWFzay5rZXlDb2RlLkRFTEVURSA6IGsgPT09IElucHV0bWFzay5rZXlDb2RlLkRFTEVURSAmJiAoayA9IElucHV0bWFzay5rZXlDb2RlLkJBQ0tTUEFDRSksIFxuICAgICAgICAgICAgICAgIGlzUlRMKSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcGVuZCA9IHBvcy5lbmQ7XG4gICAgICAgICAgICAgICAgICAgIHBvcy5lbmQgPSBwb3MuYmVnaW4sIHBvcy5iZWdpbiA9IHBlbmQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGsgPT09IElucHV0bWFzay5rZXlDb2RlLkJBQ0tTUEFDRSAmJiAocG9zLmVuZCAtIHBvcy5iZWdpbiA8IDEgfHwgITEgPT09IG9wdHMuaW5zZXJ0TW9kZSkgPyAocG9zLmJlZ2luID0gc2Vla1ByZXZpb3VzKHBvcy5iZWdpbiksIFxuICAgICAgICAgICAgICAgIGdldE1hc2tTZXQoKS52YWxpZFBvc2l0aW9uc1twb3MuYmVnaW5dICE9PSB1bmRlZmluZWQgJiYgZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zW3Bvcy5iZWdpbl0uaW5wdXQgPT09IG9wdHMuZ3JvdXBTZXBhcmF0b3IgJiYgcG9zLmJlZ2luLS0pIDogayA9PT0gSW5wdXRtYXNrLmtleUNvZGUuREVMRVRFICYmIHBvcy5iZWdpbiA9PT0gcG9zLmVuZCAmJiAocG9zLmVuZCA9IGlzTWFzayhwb3MuZW5kLCAhMCkgJiYgZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zW3Bvcy5lbmRdICYmIGdldE1hc2tTZXQoKS52YWxpZFBvc2l0aW9uc1twb3MuZW5kXS5pbnB1dCAhPT0gb3B0cy5yYWRpeFBvaW50ID8gcG9zLmVuZCArIDEgOiBzZWVrTmV4dChwb3MuZW5kKSArIDEsIFxuICAgICAgICAgICAgICAgIGdldE1hc2tTZXQoKS52YWxpZFBvc2l0aW9uc1twb3MuYmVnaW5dICE9PSB1bmRlZmluZWQgJiYgZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zW3Bvcy5iZWdpbl0uaW5wdXQgPT09IG9wdHMuZ3JvdXBTZXBhcmF0b3IgJiYgcG9zLmVuZCsrKSwgXG4gICAgICAgICAgICAgICAgc3RyaXBWYWxpZFBvc2l0aW9ucyhwb3MuYmVnaW4sIHBvcy5lbmQsICExLCBzdHJpY3QpLCAhMCAhPT0gc3RyaWN0ICYmIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAob3B0cy5rZWVwU3RhdGljKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciB2YWxpZElucHV0cyA9IFtdLCBsYXN0QWx0ID0gZ2V0TGFzdFZhbGlkUG9zaXRpb24oLTEsICEwKSwgcG9zaXRpb25zQ2xvbmUgPSAkLmV4dGVuZCghMCwge30sIGdldE1hc2tTZXQoKS52YWxpZFBvc2l0aW9ucyksIHByZXZBbHRQb3MgPSBnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnNbbGFzdEFsdF07IGxhc3RBbHQgPj0gMDsgbGFzdEFsdC0tKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGFsdFBvcyA9IGdldE1hc2tTZXQoKS52YWxpZFBvc2l0aW9uc1tsYXN0QWx0XTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoYWx0UG9zKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghMCAhPT0gYWx0UG9zLmdlbmVyYXRlZElucHV0ICYmIC9bMC05YS1iQS1aXS8udGVzdChhbHRQb3MuaW5wdXQpICYmIHZhbGlkSW5wdXRzLnB1c2goYWx0UG9zLmlucHV0KSwgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlbGV0ZSBnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnNbbGFzdEFsdF0sIGFsdFBvcy5hbHRlcm5hdGlvbiAhPT0gdW5kZWZpbmVkICYmIGFsdFBvcy5sb2NhdG9yW2FsdFBvcy5hbHRlcm5hdGlvbl0gIT09IHByZXZBbHRQb3MubG9jYXRvclthbHRQb3MuYWx0ZXJuYXRpb25dKSBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJldkFsdFBvcyA9IGFsdFBvcztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobGFzdEFsdCA+IC0xKSBmb3IgKGdldE1hc2tTZXQoKS5wID0gc2Vla05leHQoZ2V0TGFzdFZhbGlkUG9zaXRpb24oLTEsICEwKSk7IHZhbGlkSW5wdXRzLmxlbmd0aCA+IDA7ICkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBrZXlwcmVzcyA9IG5ldyAkLkV2ZW50KFwia2V5cHJlc3NcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAga2V5cHJlc3Mud2hpY2ggPSB2YWxpZElucHV0cy5wb3AoKS5jaGFyQ29kZUF0KDApLCBFdmVudEhhbmRsZXJzLmtleXByZXNzRXZlbnQuY2FsbChpbnB1dCwga2V5cHJlc3MsICEwLCAhMSwgITEsIGdldE1hc2tTZXQoKS5wKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnMgPSAkLmV4dGVuZCghMCwge30sIHBvc2l0aW9uc0Nsb25lKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0oKTtcbiAgICAgICAgICAgICAgICB2YXIgbHZwID0gZ2V0TGFzdFZhbGlkUG9zaXRpb24ocG9zLmJlZ2luLCAhMCk7XG4gICAgICAgICAgICAgICAgaWYgKGx2cCA8IHBvcy5iZWdpbikgZ2V0TWFza1NldCgpLnAgPSBzZWVrTmV4dChsdnApOyBlbHNlIGlmICghMCAhPT0gc3RyaWN0ICYmIChnZXRNYXNrU2V0KCkucCA9IHBvcy5iZWdpbiwgXG4gICAgICAgICAgICAgICAgITAgIT09IGZyb21Jc1ZhbGlkKSkgZm9yICg7Z2V0TWFza1NldCgpLnAgPCBsdnAgJiYgZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zW2dldE1hc2tTZXQoKS5wXSA9PT0gdW5kZWZpbmVkOyApIGdldE1hc2tTZXQoKS5wKys7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmdW5jdGlvbiBpbml0aWFsaXplQ29sb3JNYXNrKGlucHV0KSB7XG4gICAgICAgICAgICAgICAgZnVuY3Rpb24gZmluZENhcmV0UG9zKGNsaWVudHgpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNhcmV0UG9zLCBlID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcInNwYW5cIik7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIHN0eWxlIGluIGNvbXB1dGVkU3R5bGUpIGlzTmFOKHN0eWxlKSAmJiAtMSAhPT0gc3R5bGUuaW5kZXhPZihcImZvbnRcIikgJiYgKGUuc3R5bGVbc3R5bGVdID0gY29tcHV0ZWRTdHlsZVtzdHlsZV0pO1xuICAgICAgICAgICAgICAgICAgICBlLnN0eWxlLnRleHRUcmFuc2Zvcm0gPSBjb21wdXRlZFN0eWxlLnRleHRUcmFuc2Zvcm0sIGUuc3R5bGUubGV0dGVyU3BhY2luZyA9IGNvbXB1dGVkU3R5bGUubGV0dGVyU3BhY2luZywgXG4gICAgICAgICAgICAgICAgICAgIGUuc3R5bGUucG9zaXRpb24gPSBcImFic29sdXRlXCIsIGUuc3R5bGUuaGVpZ2h0ID0gXCJhdXRvXCIsIGUuc3R5bGUud2lkdGggPSBcImF1dG9cIiwgXG4gICAgICAgICAgICAgICAgICAgIGUuc3R5bGUudmlzaWJpbGl0eSA9IFwiaGlkZGVuXCIsIGUuc3R5bGUud2hpdGVTcGFjZSA9IFwibm93cmFwXCIsIGRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQoZSk7XG4gICAgICAgICAgICAgICAgICAgIHZhciBpdGwsIGlucHV0VGV4dCA9IGlucHV0LmlucHV0bWFzay5fdmFsdWVHZXQoKSwgcHJldmlvdXNXaWR0aCA9IDA7XG4gICAgICAgICAgICAgICAgICAgIGZvciAoY2FyZXRQb3MgPSAwLCBpdGwgPSBpbnB1dFRleHQubGVuZ3RoOyBjYXJldFBvcyA8PSBpdGw7IGNhcmV0UG9zKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlLmlubmVySFRNTCArPSBpbnB1dFRleHQuY2hhckF0KGNhcmV0UG9zKSB8fCBcIl9cIiwgZS5vZmZzZXRXaWR0aCA+PSBjbGllbnR4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG9mZnNldDEgPSBjbGllbnR4IC0gcHJldmlvdXNXaWR0aCwgb2Zmc2V0MiA9IGUub2Zmc2V0V2lkdGggLSBjbGllbnR4O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGUuaW5uZXJIVE1MID0gaW5wdXRUZXh0LmNoYXJBdChjYXJldFBvcyksIGNhcmV0UG9zID0gKG9mZnNldDEgLT0gZS5vZmZzZXRXaWR0aCAvIDMpIDwgb2Zmc2V0MiA/IGNhcmV0UG9zIC0gMSA6IGNhcmV0UG9zO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgcHJldmlvdXNXaWR0aCA9IGUub2Zmc2V0V2lkdGg7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvY3VtZW50LmJvZHkucmVtb3ZlQ2hpbGQoZSksIGNhcmV0UG9zO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgY29tcHV0ZWRTdHlsZSA9IChpbnB1dC5vd25lckRvY3VtZW50LmRlZmF1bHRWaWV3IHx8IHdpbmRvdykuZ2V0Q29tcHV0ZWRTdHlsZShpbnB1dCwgbnVsbCksIHRlbXBsYXRlID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImRpdlwiKTtcbiAgICAgICAgICAgICAgICB0ZW1wbGF0ZS5zdHlsZS53aWR0aCA9IGNvbXB1dGVkU3R5bGUud2lkdGgsIHRlbXBsYXRlLnN0eWxlLnRleHRBbGlnbiA9IGNvbXB1dGVkU3R5bGUudGV4dEFsaWduLCBcbiAgICAgICAgICAgICAgICAoY29sb3JNYXNrID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImRpdlwiKSkuY2xhc3NOYW1lID0gXCJpbS1jb2xvcm1hc2tcIiwgaW5wdXQucGFyZW50Tm9kZS5pbnNlcnRCZWZvcmUoY29sb3JNYXNrLCBpbnB1dCksIFxuICAgICAgICAgICAgICAgIGlucHV0LnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoaW5wdXQpLCBjb2xvck1hc2suYXBwZW5kQ2hpbGQodGVtcGxhdGUpLCBjb2xvck1hc2suYXBwZW5kQ2hpbGQoaW5wdXQpLCBcbiAgICAgICAgICAgICAgICBpbnB1dC5zdHlsZS5sZWZ0ID0gdGVtcGxhdGUub2Zmc2V0TGVmdCArIFwicHhcIiwgJChpbnB1dCkub24oXCJjbGlja1wiLCBmdW5jdGlvbihlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBjYXJldChpbnB1dCwgZmluZENhcmV0UG9zKGUuY2xpZW50WCkpLCBFdmVudEhhbmRsZXJzLmNsaWNrRXZlbnQuY2FsbChpbnB1dCwgWyBlIF0pO1xuICAgICAgICAgICAgICAgIH0pLCAkKGlucHV0KS5vbihcImtleWRvd25cIiwgZnVuY3Rpb24oZSkge1xuICAgICAgICAgICAgICAgICAgICBlLnNoaWZ0S2V5IHx8ICExID09PSBvcHRzLmluc2VydE1vZGUgfHwgc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbmRlckNvbG9yTWFzayhpbnB1dCk7XG4gICAgICAgICAgICAgICAgICAgIH0sIDApO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZnVuY3Rpb24gcmVuZGVyQ29sb3JNYXNrKGlucHV0LCBjYXJldFBvcywgY2xlYXIpIHtcbiAgICAgICAgICAgICAgICBmdW5jdGlvbiBoYW5kbGVTdGF0aWMoKSB7XG4gICAgICAgICAgICAgICAgICAgIGlzU3RhdGljIHx8IG51bGwgIT09IHRlc3QuZm4gJiYgdGVzdFBvcy5pbnB1dCAhPT0gdW5kZWZpbmVkID8gaXNTdGF0aWMgJiYgKG51bGwgIT09IHRlc3QuZm4gJiYgdGVzdFBvcy5pbnB1dCAhPT0gdW5kZWZpbmVkIHx8IFwiXCIgPT09IHRlc3QuZGVmKSAmJiAoaXNTdGF0aWMgPSAhMSwgXG4gICAgICAgICAgICAgICAgICAgIG1hc2tUZW1wbGF0ZSArPSBcIjwvc3Bhbj5cIikgOiAoaXNTdGF0aWMgPSAhMCwgbWFza1RlbXBsYXRlICs9IFwiPHNwYW4gY2xhc3M9J2ltLXN0YXRpYyc+XCIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBmdW5jdGlvbiBoYW5kbGVDYXJldChmb3JjZSkge1xuICAgICAgICAgICAgICAgICAgICAhMCAhPT0gZm9yY2UgJiYgcG9zICE9PSBjYXJldFBvcy5iZWdpbiB8fCBkb2N1bWVudC5hY3RpdmVFbGVtZW50ICE9PSBpbnB1dCB8fCAobWFza1RlbXBsYXRlICs9IFwiPHNwYW4gY2xhc3M9J2ltLWNhcmV0JyBzdHlsZT0nYm9yZGVyLXJpZ2h0LXdpZHRoOiAxcHg7Ym9yZGVyLXJpZ2h0LXN0eWxlOiBzb2xpZDsnPjwvc3Bhbj5cIik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciB0ZXN0LCB0ZXN0UG9zLCBuZHhJbnRsenIsIG1hc2tUZW1wbGF0ZSA9IFwiXCIsIGlzU3RhdGljID0gITEsIHBvcyA9IDA7XG4gICAgICAgICAgICAgICAgaWYgKGNvbG9yTWFzayAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBidWZmZXIgPSBnZXRCdWZmZXIoKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGNhcmV0UG9zID09PSB1bmRlZmluZWQgPyBjYXJldFBvcyA9IGNhcmV0KGlucHV0KSA6IGNhcmV0UG9zLmJlZ2luID09PSB1bmRlZmluZWQgJiYgKGNhcmV0UG9zID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgYmVnaW46IGNhcmV0UG9zLFxuICAgICAgICAgICAgICAgICAgICAgICAgZW5kOiBjYXJldFBvc1xuICAgICAgICAgICAgICAgICAgICB9KSwgITAgIT09IGNsZWFyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgbHZwID0gZ2V0TGFzdFZhbGlkUG9zaXRpb24oKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRvIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYW5kbGVDYXJldCgpLCBnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnNbcG9zXSA/ICh0ZXN0UG9zID0gZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zW3Bvc10sIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRlc3QgPSB0ZXN0UG9zLm1hdGNoLCBuZHhJbnRsenIgPSB0ZXN0UG9zLmxvY2F0b3Iuc2xpY2UoKSwgaGFuZGxlU3RhdGljKCksIG1hc2tUZW1wbGF0ZSArPSBidWZmZXJbcG9zXSkgOiAodGVzdFBvcyA9IGdldFRlc3RUZW1wbGF0ZShwb3MsIG5keEludGx6ciwgcG9zIC0gMSksIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRlc3QgPSB0ZXN0UG9zLm1hdGNoLCBuZHhJbnRsenIgPSB0ZXN0UG9zLmxvY2F0b3Iuc2xpY2UoKSwgKCExID09PSBvcHRzLmppdE1hc2tpbmcgfHwgcG9zIDwgbHZwIHx8IFwibnVtYmVyXCIgPT0gdHlwZW9mIG9wdHMuaml0TWFza2luZyAmJiBpc0Zpbml0ZShvcHRzLmppdE1hc2tpbmcpICYmIG9wdHMuaml0TWFza2luZyA+IHBvcykgJiYgKGhhbmRsZVN0YXRpYygpLCBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXNrVGVtcGxhdGUgKz0gZ2V0UGxhY2Vob2xkZXIocG9zLCB0ZXN0KSkpLCBwb3MrKztcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gd2hpbGUgKChtYXhMZW5ndGggPT09IHVuZGVmaW5lZCB8fCBwb3MgPCBtYXhMZW5ndGgpICYmIChudWxsICE9PSB0ZXN0LmZuIHx8IFwiXCIgIT09IHRlc3QuZGVmKSB8fCBsdnAgPiBwb3MgfHwgaXNTdGF0aWMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgLTEgPT09IG1hc2tUZW1wbGF0ZS5pbmRleE9mKFwiaW0tY2FyZXRcIikgJiYgaGFuZGxlQ2FyZXQoITApLCBpc1N0YXRpYyAmJiBoYW5kbGVTdGF0aWMoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB2YXIgdGVtcGxhdGUgPSBjb2xvck1hc2suZ2V0RWxlbWVudHNCeVRhZ05hbWUoXCJkaXZcIilbMF07XG4gICAgICAgICAgICAgICAgICAgIHRlbXBsYXRlLmlubmVySFRNTCA9IG1hc2tUZW1wbGF0ZSwgaW5wdXQuaW5wdXRtYXNrLnBvc2l0aW9uQ29sb3JNYXNrKGlucHV0LCB0ZW1wbGF0ZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbWFza3NldCA9IG1hc2tzZXQgfHwgdGhpcy5tYXNrc2V0LCBvcHRzID0gb3B0cyB8fCB0aGlzLm9wdHM7XG4gICAgICAgICAgICB2YXIgdW5kb1ZhbHVlLCAkZWwsIG1heExlbmd0aCwgY29sb3JNYXNrLCBpbnB1dG1hc2sgPSB0aGlzLCBlbCA9IHRoaXMuZWwsIGlzUlRMID0gdGhpcy5pc1JUTCwgc2tpcEtleVByZXNzRXZlbnQgPSAhMSwgc2tpcElucHV0RXZlbnQgPSAhMSwgaWdub3JhYmxlID0gITEsIG1vdXNlRW50ZXIgPSAhMSwgRXZlbnRSdWxlciA9IHtcbiAgICAgICAgICAgICAgICBvbjogZnVuY3Rpb24oaW5wdXQsIGV2ZW50TmFtZSwgZXZlbnRIYW5kbGVyKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBldiA9IGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmlucHV0bWFzayA9PT0gdW5kZWZpbmVkICYmIFwiRk9STVwiICE9PSB0aGlzLm5vZGVOYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGltT3B0cyA9ICQuZGF0YSh0aGlzLCBcIl9pbnB1dG1hc2tfb3B0c1wiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbU9wdHMgPyBuZXcgSW5wdXRtYXNrKGltT3B0cykubWFzayh0aGlzKSA6IEV2ZW50UnVsZXIub2ZmKHRoaXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoXCJzZXR2YWx1ZVwiID09PSBlLnR5cGUgfHwgXCJGT1JNXCIgPT09IHRoaXMubm9kZU5hbWUgfHwgISh0aGlzLmRpc2FibGVkIHx8IHRoaXMucmVhZE9ubHkgJiYgIShcImtleWRvd25cIiA9PT0gZS50eXBlICYmIGUuY3RybEtleSAmJiA2NyA9PT0gZS5rZXlDb2RlIHx8ICExID09PSBvcHRzLnRhYlRocm91Z2ggJiYgZS5rZXlDb2RlID09PSBJbnB1dG1hc2sua2V5Q29kZS5UQUIpKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKGUudHlwZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgXCJpbnB1dFwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCEwID09PSBza2lwSW5wdXRFdmVudCkgcmV0dXJuIHNraXBJbnB1dEV2ZW50ID0gITEsIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBcImtleWRvd25cIjpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNraXBLZXlQcmVzc0V2ZW50ID0gITEsIHNraXBJbnB1dEV2ZW50ID0gITE7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgXCJrZXlwcmVzc1wiOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCEwID09PSBza2lwS2V5UHJlc3NFdmVudCkgcmV0dXJuIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNraXBLZXlQcmVzc0V2ZW50ID0gITA7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgXCJjbGlja1wiOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGllbW9iaWxlIHx8IGlwaG9uZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciB0aGF0ID0gdGhpcywgYXJncyA9IGFyZ3VtZW50cztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRIYW5kbGVyLmFwcGx5KHRoYXQsIGFyZ3MpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sIDApLCAhMTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgcmV0dXJuVmFsID0gZXZlbnRIYW5kbGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAhMSA9PT0gcmV0dXJuVmFsICYmIChlLnByZXZlbnREZWZhdWx0KCksIGUuc3RvcFByb3BhZ2F0aW9uKCkpLCByZXR1cm5WYWw7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgaW5wdXQuaW5wdXRtYXNrLmV2ZW50c1tldmVudE5hbWVdID0gaW5wdXQuaW5wdXRtYXNrLmV2ZW50c1tldmVudE5hbWVdIHx8IFtdLCBpbnB1dC5pbnB1dG1hc2suZXZlbnRzW2V2ZW50TmFtZV0ucHVzaChldiksIFxuICAgICAgICAgICAgICAgICAgICAtMSAhPT0gJC5pbkFycmF5KGV2ZW50TmFtZSwgWyBcInN1Ym1pdFwiLCBcInJlc2V0XCIgXSkgPyBudWxsICE9PSBpbnB1dC5mb3JtICYmICQoaW5wdXQuZm9ybSkub24oZXZlbnROYW1lLCBldikgOiAkKGlucHV0KS5vbihldmVudE5hbWUsIGV2KTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIG9mZjogZnVuY3Rpb24oaW5wdXQsIGV2ZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpbnB1dC5pbnB1dG1hc2sgJiYgaW5wdXQuaW5wdXRtYXNrLmV2ZW50cykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGV2ZW50cztcbiAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50ID8gKGV2ZW50cyA9IFtdKVtldmVudF0gPSBpbnB1dC5pbnB1dG1hc2suZXZlbnRzW2V2ZW50XSA6IGV2ZW50cyA9IGlucHV0LmlucHV0bWFzay5ldmVudHMsIFxuICAgICAgICAgICAgICAgICAgICAgICAgJC5lYWNoKGV2ZW50cywgZnVuY3Rpb24oZXZlbnROYW1lLCBldkFycikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoO2V2QXJyLmxlbmd0aCA+IDA7ICkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgZXYgPSBldkFyci5wb3AoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLTEgIT09ICQuaW5BcnJheShldmVudE5hbWUsIFsgXCJzdWJtaXRcIiwgXCJyZXNldFwiIF0pID8gbnVsbCAhPT0gaW5wdXQuZm9ybSAmJiAkKGlucHV0LmZvcm0pLm9mZihldmVudE5hbWUsIGV2KSA6ICQoaW5wdXQpLm9mZihldmVudE5hbWUsIGV2KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVsZXRlIGlucHV0LmlucHV0bWFzay5ldmVudHNbZXZlbnROYW1lXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSwgRXZlbnRIYW5kbGVycyA9IHtcbiAgICAgICAgICAgICAgICBrZXlkb3duRXZlbnQ6IGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGlucHV0ID0gdGhpcywgJGlucHV0ID0gJChpbnB1dCksIGsgPSBlLmtleUNvZGUsIHBvcyA9IGNhcmV0KGlucHV0KTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGsgPT09IElucHV0bWFzay5rZXlDb2RlLkJBQ0tTUEFDRSB8fCBrID09PSBJbnB1dG1hc2sua2V5Q29kZS5ERUxFVEUgfHwgaXBob25lICYmIGsgPT09IElucHV0bWFzay5rZXlDb2RlLkJBQ0tTUEFDRV9TQUZBUkkgfHwgZS5jdHJsS2V5ICYmIGsgPT09IElucHV0bWFzay5rZXlDb2RlLlggJiYgIWZ1bmN0aW9uKGV2ZW50TmFtZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGVsID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImlucHV0XCIpLCBldk5hbWUgPSBcIm9uXCIgKyBldmVudE5hbWUsIGlzU3VwcG9ydGVkID0gZXZOYW1lIGluIGVsO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGlzU3VwcG9ydGVkIHx8IChlbC5zZXRBdHRyaWJ1dGUoZXZOYW1lLCBcInJldHVybjtcIiksIGlzU3VwcG9ydGVkID0gXCJmdW5jdGlvblwiID09IHR5cGVvZiBlbFtldk5hbWVdKSwgXG4gICAgICAgICAgICAgICAgICAgICAgICBlbCA9IG51bGwsIGlzU3VwcG9ydGVkO1xuICAgICAgICAgICAgICAgICAgICB9KFwiY3V0XCIpKSBlLnByZXZlbnREZWZhdWx0KCksIGhhbmRsZVJlbW92ZShpbnB1dCwgaywgcG9zKSwgd3JpdGVCdWZmZXIoaW5wdXQsIGdldEJ1ZmZlcighMCksIGdldE1hc2tTZXQoKS5wLCBlLCBpbnB1dC5pbnB1dG1hc2suX3ZhbHVlR2V0KCkgIT09IGdldEJ1ZmZlcigpLmpvaW4oXCJcIikpLCBcbiAgICAgICAgICAgICAgICAgICAgaW5wdXQuaW5wdXRtYXNrLl92YWx1ZUdldCgpID09PSBnZXRCdWZmZXJUZW1wbGF0ZSgpLmpvaW4oXCJcIikgPyAkaW5wdXQudHJpZ2dlcihcImNsZWFyZWRcIikgOiAhMCA9PT0gaXNDb21wbGV0ZShnZXRCdWZmZXIoKSkgJiYgJGlucHV0LnRyaWdnZXIoXCJjb21wbGV0ZVwiKTsgZWxzZSBpZiAoayA9PT0gSW5wdXRtYXNrLmtleUNvZGUuRU5EIHx8IGsgPT09IElucHV0bWFzay5rZXlDb2RlLlBBR0VfRE9XTikge1xuICAgICAgICAgICAgICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNhcmV0UG9zID0gc2Vla05leHQoZ2V0TGFzdFZhbGlkUG9zaXRpb24oKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBvcHRzLmluc2VydE1vZGUgfHwgY2FyZXRQb3MgIT09IGdldE1hc2tTZXQoKS5tYXNrTGVuZ3RoIHx8IGUuc2hpZnRLZXkgfHwgY2FyZXRQb3MtLSwgXG4gICAgICAgICAgICAgICAgICAgICAgICBjYXJldChpbnB1dCwgZS5zaGlmdEtleSA/IHBvcy5iZWdpbiA6IGNhcmV0UG9zLCBjYXJldFBvcywgITApO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgayA9PT0gSW5wdXRtYXNrLmtleUNvZGUuSE9NRSAmJiAhZS5zaGlmdEtleSB8fCBrID09PSBJbnB1dG1hc2sua2V5Q29kZS5QQUdFX1VQID8gKGUucHJldmVudERlZmF1bHQoKSwgXG4gICAgICAgICAgICAgICAgICAgIGNhcmV0KGlucHV0LCAwLCBlLnNoaWZ0S2V5ID8gcG9zLmJlZ2luIDogMCwgITApKSA6IChvcHRzLnVuZG9PbkVzY2FwZSAmJiBrID09PSBJbnB1dG1hc2sua2V5Q29kZS5FU0NBUEUgfHwgOTAgPT09IGsgJiYgZS5jdHJsS2V5KSAmJiAhMCAhPT0gZS5hbHRLZXkgPyAoY2hlY2tWYWwoaW5wdXQsICEwLCAhMSwgdW5kb1ZhbHVlLnNwbGl0KFwiXCIpKSwgXG4gICAgICAgICAgICAgICAgICAgICRpbnB1dC50cmlnZ2VyKFwiY2xpY2tcIikpIDogayAhPT0gSW5wdXRtYXNrLmtleUNvZGUuSU5TRVJUIHx8IGUuc2hpZnRLZXkgfHwgZS5jdHJsS2V5ID8gITAgPT09IG9wdHMudGFiVGhyb3VnaCAmJiBrID09PSBJbnB1dG1hc2sua2V5Q29kZS5UQUIgPyAoITAgPT09IGUuc2hpZnRLZXkgPyAobnVsbCA9PT0gZ2V0VGVzdChwb3MuYmVnaW4pLm1hdGNoLmZuICYmIChwb3MuYmVnaW4gPSBzZWVrTmV4dChwb3MuYmVnaW4pKSwgXG4gICAgICAgICAgICAgICAgICAgIHBvcy5lbmQgPSBzZWVrUHJldmlvdXMocG9zLmJlZ2luLCAhMCksIHBvcy5iZWdpbiA9IHNlZWtQcmV2aW91cyhwb3MuZW5kLCAhMCkpIDogKHBvcy5iZWdpbiA9IHNlZWtOZXh0KHBvcy5iZWdpbiwgITApLCBcbiAgICAgICAgICAgICAgICAgICAgcG9zLmVuZCA9IHNlZWtOZXh0KHBvcy5iZWdpbiwgITApLCBwb3MuZW5kIDwgZ2V0TWFza1NldCgpLm1hc2tMZW5ndGggJiYgcG9zLmVuZC0tKSwgXG4gICAgICAgICAgICAgICAgICAgIHBvcy5iZWdpbiA8IGdldE1hc2tTZXQoKS5tYXNrTGVuZ3RoICYmIChlLnByZXZlbnREZWZhdWx0KCksIGNhcmV0KGlucHV0LCBwb3MuYmVnaW4sIHBvcy5lbmQpKSkgOiBlLnNoaWZ0S2V5IHx8ICExID09PSBvcHRzLmluc2VydE1vZGUgJiYgKGsgPT09IElucHV0bWFzay5rZXlDb2RlLlJJR0hUID8gc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjYXJldFBvcyA9IGNhcmV0KGlucHV0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhcmV0KGlucHV0LCBjYXJldFBvcy5iZWdpbik7XG4gICAgICAgICAgICAgICAgICAgIH0sIDApIDogayA9PT0gSW5wdXRtYXNrLmtleUNvZGUuTEVGVCAmJiBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNhcmV0UG9zID0gY2FyZXQoaW5wdXQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FyZXQoaW5wdXQsIGlzUlRMID8gY2FyZXRQb3MuYmVnaW4gKyAxIDogY2FyZXRQb3MuYmVnaW4gLSAxKTtcbiAgICAgICAgICAgICAgICAgICAgfSwgMCkpIDogKG9wdHMuaW5zZXJ0TW9kZSA9ICFvcHRzLmluc2VydE1vZGUsIGNhcmV0KGlucHV0LCBvcHRzLmluc2VydE1vZGUgfHwgcG9zLmJlZ2luICE9PSBnZXRNYXNrU2V0KCkubWFza0xlbmd0aCA/IHBvcy5iZWdpbiA6IHBvcy5iZWdpbiAtIDEpKTtcbiAgICAgICAgICAgICAgICAgICAgb3B0cy5vbktleURvd24uY2FsbCh0aGlzLCBlLCBnZXRCdWZmZXIoKSwgY2FyZXQoaW5wdXQpLmJlZ2luLCBvcHRzKSwgaWdub3JhYmxlID0gLTEgIT09ICQuaW5BcnJheShrLCBvcHRzLmlnbm9yYWJsZXMpO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAga2V5cHJlc3NFdmVudDogZnVuY3Rpb24oZSwgY2hlY2t2YWwsIHdyaXRlT3V0LCBzdHJpY3QsIG5keCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgaW5wdXQgPSB0aGlzLCAkaW5wdXQgPSAkKGlucHV0KSwgayA9IGUud2hpY2ggfHwgZS5jaGFyQ29kZSB8fCBlLmtleUNvZGU7XG4gICAgICAgICAgICAgICAgICAgIGlmICghKCEwID09PSBjaGVja3ZhbCB8fCBlLmN0cmxLZXkgJiYgZS5hbHRLZXkpICYmIChlLmN0cmxLZXkgfHwgZS5tZXRhS2V5IHx8IGlnbm9yYWJsZSkpIHJldHVybiBrID09PSBJbnB1dG1hc2sua2V5Q29kZS5FTlRFUiAmJiB1bmRvVmFsdWUgIT09IGdldEJ1ZmZlcigpLmpvaW4oXCJcIikgJiYgKHVuZG9WYWx1ZSA9IGdldEJ1ZmZlcigpLmpvaW4oXCJcIiksIFxuICAgICAgICAgICAgICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgJGlucHV0LnRyaWdnZXIoXCJjaGFuZ2VcIik7XG4gICAgICAgICAgICAgICAgICAgIH0sIDApKSwgITA7XG4gICAgICAgICAgICAgICAgICAgIGlmIChrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICA0NiA9PT0gayAmJiAhMSA9PT0gZS5zaGlmdEtleSAmJiBcIlwiICE9PSBvcHRzLnJhZGl4UG9pbnQgJiYgKGsgPSBvcHRzLnJhZGl4UG9pbnQuY2hhckNvZGVBdCgwKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgZm9yd2FyZFBvc2l0aW9uLCBwb3MgPSBjaGVja3ZhbCA/IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBiZWdpbjogbmR4LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVuZDogbmR4XG4gICAgICAgICAgICAgICAgICAgICAgICB9IDogY2FyZXQoaW5wdXQpLCBjID0gU3RyaW5nLmZyb21DaGFyQ29kZShrKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGdldE1hc2tTZXQoKS53cml0ZU91dEJ1ZmZlciA9ICEwO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHZhbFJlc3VsdCA9IGlzVmFsaWQocG9zLCBjLCBzdHJpY3QpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCExICE9PSB2YWxSZXN1bHQgJiYgKHJlc2V0TWFza1NldCghMCksIGZvcndhcmRQb3NpdGlvbiA9IHZhbFJlc3VsdC5jYXJldCAhPT0gdW5kZWZpbmVkID8gdmFsUmVzdWx0LmNhcmV0IDogY2hlY2t2YWwgPyB2YWxSZXN1bHQucG9zICsgMSA6IHNlZWtOZXh0KHZhbFJlc3VsdC5wb3MpLCBcbiAgICAgICAgICAgICAgICAgICAgICAgIGdldE1hc2tTZXQoKS5wID0gZm9yd2FyZFBvc2l0aW9uKSwgITEgIT09IHdyaXRlT3V0ICYmIChzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9wdHMub25LZXlWYWxpZGF0aW9uLmNhbGwoaW5wdXQsIGssIHZhbFJlc3VsdCwgb3B0cyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9LCAwKSwgZ2V0TWFza1NldCgpLndyaXRlT3V0QnVmZmVyICYmICExICE9PSB2YWxSZXN1bHQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGJ1ZmZlciA9IGdldEJ1ZmZlcigpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdyaXRlQnVmZmVyKGlucHV0LCBidWZmZXIsIG9wdHMubnVtZXJpY0lucHV0ICYmIHZhbFJlc3VsdC5jYXJldCA9PT0gdW5kZWZpbmVkID8gc2Vla1ByZXZpb3VzKGZvcndhcmRQb3NpdGlvbikgOiBmb3J3YXJkUG9zaXRpb24sIGUsICEwICE9PSBjaGVja3ZhbCksIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICEwICE9PSBjaGVja3ZhbCAmJiBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAhMCA9PT0gaXNDb21wbGV0ZShidWZmZXIpICYmICRpbnB1dC50cmlnZ2VyKFwiY29tcGxldGVcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSwgMCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZS5wcmV2ZW50RGVmYXVsdCgpLCBjaGVja3ZhbCkgcmV0dXJuICExICE9PSB2YWxSZXN1bHQgJiYgKHZhbFJlc3VsdC5mb3J3YXJkUG9zaXRpb24gPSBmb3J3YXJkUG9zaXRpb24pLCBcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhbFJlc3VsdDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgcGFzdGVFdmVudDogZnVuY3Rpb24oZSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgdGVtcFZhbHVlLCBpbnB1dCA9IHRoaXMsIGV2ID0gZS5vcmlnaW5hbEV2ZW50IHx8IGUsICRpbnB1dCA9ICQoaW5wdXQpLCBpbnB1dFZhbHVlID0gaW5wdXQuaW5wdXRtYXNrLl92YWx1ZUdldCghMCksIGNhcmV0UG9zID0gY2FyZXQoaW5wdXQpO1xuICAgICAgICAgICAgICAgICAgICBpc1JUTCAmJiAodGVtcFZhbHVlID0gY2FyZXRQb3MuZW5kLCBjYXJldFBvcy5lbmQgPSBjYXJldFBvcy5iZWdpbiwgY2FyZXRQb3MuYmVnaW4gPSB0ZW1wVmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICB2YXIgdmFsdWVCZWZvcmVDYXJldCA9IGlucHV0VmFsdWUuc3Vic3RyKDAsIGNhcmV0UG9zLmJlZ2luKSwgdmFsdWVBZnRlckNhcmV0ID0gaW5wdXRWYWx1ZS5zdWJzdHIoY2FyZXRQb3MuZW5kLCBpbnB1dFZhbHVlLmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgICAgIGlmICh2YWx1ZUJlZm9yZUNhcmV0ID09PSAoaXNSVEwgPyBnZXRCdWZmZXJUZW1wbGF0ZSgpLnJldmVyc2UoKSA6IGdldEJ1ZmZlclRlbXBsYXRlKCkpLnNsaWNlKDAsIGNhcmV0UG9zLmJlZ2luKS5qb2luKFwiXCIpICYmICh2YWx1ZUJlZm9yZUNhcmV0ID0gXCJcIiksIFxuICAgICAgICAgICAgICAgICAgICB2YWx1ZUFmdGVyQ2FyZXQgPT09IChpc1JUTCA/IGdldEJ1ZmZlclRlbXBsYXRlKCkucmV2ZXJzZSgpIDogZ2V0QnVmZmVyVGVtcGxhdGUoKSkuc2xpY2UoY2FyZXRQb3MuZW5kKS5qb2luKFwiXCIpICYmICh2YWx1ZUFmdGVyQ2FyZXQgPSBcIlwiKSwgXG4gICAgICAgICAgICAgICAgICAgIGlzUlRMICYmICh0ZW1wVmFsdWUgPSB2YWx1ZUJlZm9yZUNhcmV0LCB2YWx1ZUJlZm9yZUNhcmV0ID0gdmFsdWVBZnRlckNhcmV0LCB2YWx1ZUFmdGVyQ2FyZXQgPSB0ZW1wVmFsdWUpLCBcbiAgICAgICAgICAgICAgICAgICAgd2luZG93LmNsaXBib2FyZERhdGEgJiYgd2luZG93LmNsaXBib2FyZERhdGEuZ2V0RGF0YSkgaW5wdXRWYWx1ZSA9IHZhbHVlQmVmb3JlQ2FyZXQgKyB3aW5kb3cuY2xpcGJvYXJkRGF0YS5nZXREYXRhKFwiVGV4dFwiKSArIHZhbHVlQWZ0ZXJDYXJldDsgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWV2LmNsaXBib2FyZERhdGEgfHwgIWV2LmNsaXBib2FyZERhdGEuZ2V0RGF0YSkgcmV0dXJuICEwO1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5wdXRWYWx1ZSA9IHZhbHVlQmVmb3JlQ2FyZXQgKyBldi5jbGlwYm9hcmREYXRhLmdldERhdGEoXCJ0ZXh0L3BsYWluXCIpICsgdmFsdWVBZnRlckNhcmV0O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHZhciBwYXN0ZVZhbHVlID0gaW5wdXRWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCQuaXNGdW5jdGlvbihvcHRzLm9uQmVmb3JlUGFzdGUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoITEgPT09IChwYXN0ZVZhbHVlID0gb3B0cy5vbkJlZm9yZVBhc3RlLmNhbGwoaW5wdXRtYXNrLCBpbnB1dFZhbHVlLCBvcHRzKSkpIHJldHVybiBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXN0ZVZhbHVlIHx8IChwYXN0ZVZhbHVlID0gaW5wdXRWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGNoZWNrVmFsKGlucHV0LCAhMSwgITEsIGlzUlRMID8gcGFzdGVWYWx1ZS5zcGxpdChcIlwiKS5yZXZlcnNlKCkgOiBwYXN0ZVZhbHVlLnRvU3RyaW5nKCkuc3BsaXQoXCJcIikpLCBcbiAgICAgICAgICAgICAgICAgICAgd3JpdGVCdWZmZXIoaW5wdXQsIGdldEJ1ZmZlcigpLCBzZWVrTmV4dChnZXRMYXN0VmFsaWRQb3NpdGlvbigpKSwgZSwgdW5kb1ZhbHVlICE9PSBnZXRCdWZmZXIoKS5qb2luKFwiXCIpKSwgXG4gICAgICAgICAgICAgICAgICAgICEwID09PSBpc0NvbXBsZXRlKGdldEJ1ZmZlcigpKSAmJiAkaW5wdXQudHJpZ2dlcihcImNvbXBsZXRlXCIpLCBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBpbnB1dEZhbGxCYWNrRXZlbnQ6IGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGlucHV0ID0gdGhpcywgaW5wdXRWYWx1ZSA9IGlucHV0LmlucHV0bWFzay5fdmFsdWVHZXQoKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGdldEJ1ZmZlcigpLmpvaW4oXCJcIikgIT09IGlucHV0VmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjYXJldFBvcyA9IGNhcmV0KGlucHV0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghMSA9PT0gZnVuY3Rpb24oaW5wdXQsIGlucHV0VmFsdWUsIGNhcmV0UG9zKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKFwiLlwiID09PSBpbnB1dFZhbHVlLmNoYXJBdChjYXJldFBvcy5iZWdpbiAtIDEpICYmIFwiXCIgIT09IG9wdHMucmFkaXhQb2ludCAmJiAoKGlucHV0VmFsdWUgPSBpbnB1dFZhbHVlLnNwbGl0KFwiXCIpKVtjYXJldFBvcy5iZWdpbiAtIDFdID0gb3B0cy5yYWRpeFBvaW50LmNoYXJBdCgwKSwgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5wdXRWYWx1ZSA9IGlucHV0VmFsdWUuam9pbihcIlwiKSksIGlucHV0VmFsdWUuY2hhckF0KGNhcmV0UG9zLmJlZ2luIC0gMSkgPT09IG9wdHMucmFkaXhQb2ludCAmJiBpbnB1dFZhbHVlLmxlbmd0aCA+IGdldEJ1ZmZlcigpLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIga2V5cHJlc3MgPSBuZXcgJC5FdmVudChcImtleXByZXNzXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4ga2V5cHJlc3Mud2hpY2ggPSBvcHRzLnJhZGl4UG9pbnQuY2hhckNvZGVBdCgwKSwgRXZlbnRIYW5kbGVycy5rZXlwcmVzc0V2ZW50LmNhbGwoaW5wdXQsIGtleXByZXNzLCAhMCwgITAsICExLCBjYXJldFBvcy5iZWdpbiAtIDEpLCBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgITE7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfShpbnB1dCwgaW5wdXRWYWx1ZSwgY2FyZXRQb3MpKSByZXR1cm4gITE7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaW5wdXRWYWx1ZSA9IGlucHV0VmFsdWUucmVwbGFjZShuZXcgUmVnRXhwKFwiKFwiICsgSW5wdXRtYXNrLmVzY2FwZVJlZ2V4KGdldEJ1ZmZlclRlbXBsYXRlKCkuam9pbihcIlwiKSkgKyBcIikqXCIpLCBcIlwiKSwgXG4gICAgICAgICAgICAgICAgICAgICAgICAhMSA9PT0gZnVuY3Rpb24oaW5wdXQsIGlucHV0VmFsdWUsIGNhcmV0UG9zKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGllbW9iaWxlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBpbnB1dENoYXIgPSBpbnB1dFZhbHVlLnJlcGxhY2UoZ2V0QnVmZmVyKCkuam9pbihcIlwiKSwgXCJcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICgxID09PSBpbnB1dENoYXIubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIga2V5cHJlc3MgPSBuZXcgJC5FdmVudChcImtleXByZXNzXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGtleXByZXNzLndoaWNoID0gaW5wdXRDaGFyLmNoYXJDb2RlQXQoMCksIEV2ZW50SGFuZGxlcnMua2V5cHJlc3NFdmVudC5jYWxsKGlucHV0LCBrZXlwcmVzcywgITAsICEwLCAhMSwgZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zW2NhcmV0UG9zLmJlZ2luIC0gMV0gPyBjYXJldFBvcy5iZWdpbiA6IGNhcmV0UG9zLmJlZ2luIC0gMSksIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgITE7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9KGlucHV0LCBpbnB1dFZhbHVlLCBjYXJldFBvcykpIHJldHVybiAhMTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhcmV0UG9zLmJlZ2luID4gaW5wdXRWYWx1ZS5sZW5ndGggJiYgKGNhcmV0KGlucHV0LCBpbnB1dFZhbHVlLmxlbmd0aCksIGNhcmV0UG9zID0gY2FyZXQoaW5wdXQpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBidWZmZXIgPSBnZXRCdWZmZXIoKS5qb2luKFwiXCIpLCBmcm9udFBhcnQgPSBpbnB1dFZhbHVlLnN1YnN0cigwLCBjYXJldFBvcy5iZWdpbiksIGJhY2tQYXJ0ID0gaW5wdXRWYWx1ZS5zdWJzdHIoY2FyZXRQb3MuYmVnaW4pLCBmcm9udEJ1ZmZlclBhcnQgPSBidWZmZXIuc3Vic3RyKDAsIGNhcmV0UG9zLmJlZ2luKSwgYmFja0J1ZmZlclBhcnQgPSBidWZmZXIuc3Vic3RyKGNhcmV0UG9zLmJlZ2luKSwgc2VsZWN0aW9uID0gY2FyZXRQb3MsIGVudHJpZXMgPSBcIlwiLCBpc0VudHJ5ID0gITE7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZnJvbnRQYXJ0ICE9PSBmcm9udEJ1ZmZlclBhcnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxlY3Rpb24uYmVnaW4gPSAwO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGZwbCA9IChpc0VudHJ5ID0gZnJvbnRQYXJ0Lmxlbmd0aCA+PSBmcm9udEJ1ZmZlclBhcnQubGVuZ3RoKSA/IGZyb250UGFydC5sZW5ndGggOiBmcm9udEJ1ZmZlclBhcnQubGVuZ3RoLCBpID0gMDsgZnJvbnRQYXJ0LmNoYXJBdChpKSA9PT0gZnJvbnRCdWZmZXJQYXJ0LmNoYXJBdChpKSAmJiBpIDwgZnBsOyBpKyspIHNlbGVjdGlvbi5iZWdpbisrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzRW50cnkgJiYgKGVudHJpZXMgKz0gZnJvbnRQYXJ0LnNsaWNlKHNlbGVjdGlvbi5iZWdpbiwgc2VsZWN0aW9uLmVuZCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgYmFja1BhcnQgIT09IGJhY2tCdWZmZXJQYXJ0ICYmIChiYWNrUGFydC5sZW5ndGggPiBiYWNrQnVmZmVyUGFydC5sZW5ndGggPyBpc0VudHJ5ICYmIChzZWxlY3Rpb24uZW5kID0gc2VsZWN0aW9uLmJlZ2luKSA6IGJhY2tQYXJ0Lmxlbmd0aCA8IGJhY2tCdWZmZXJQYXJ0Lmxlbmd0aCA/IHNlbGVjdGlvbi5lbmQgKz0gYmFja0J1ZmZlclBhcnQubGVuZ3RoIC0gYmFja1BhcnQubGVuZ3RoIDogYmFja1BhcnQuY2hhckF0KDApICE9PSBiYWNrQnVmZmVyUGFydC5jaGFyQXQoMCkgJiYgc2VsZWN0aW9uLmVuZCsrKSwgXG4gICAgICAgICAgICAgICAgICAgICAgICB3cml0ZUJ1ZmZlcihpbnB1dCwgZ2V0QnVmZmVyKCksIHNlbGVjdGlvbiksIGVudHJpZXMubGVuZ3RoID4gMCA/ICQuZWFjaChlbnRyaWVzLnNwbGl0KFwiXCIpLCBmdW5jdGlvbihuZHgsIGVudHJ5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGtleXByZXNzID0gbmV3ICQuRXZlbnQoXCJrZXlwcmVzc1wiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBrZXlwcmVzcy53aGljaCA9IGVudHJ5LmNoYXJDb2RlQXQoMCksIGlnbm9yYWJsZSA9ICExLCBFdmVudEhhbmRsZXJzLmtleXByZXNzRXZlbnQuY2FsbChpbnB1dCwga2V5cHJlc3MpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSkgOiAoc2VsZWN0aW9uLmJlZ2luID09PSBzZWxlY3Rpb24uZW5kIC0gMSAmJiBjYXJldChpbnB1dCwgc2Vla1ByZXZpb3VzKHNlbGVjdGlvbi5iZWdpbiArIDEpLCBzZWxlY3Rpb24uZW5kKSwgXG4gICAgICAgICAgICAgICAgICAgICAgICBlLmtleUNvZGUgPSBJbnB1dG1hc2sua2V5Q29kZS5ERUxFVEUsIEV2ZW50SGFuZGxlcnMua2V5ZG93bkV2ZW50LmNhbGwoaW5wdXQsIGUpKSwgXG4gICAgICAgICAgICAgICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHNldFZhbHVlRXZlbnQ6IGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5pbnB1dG1hc2sucmVmcmVzaFZhbHVlID0gITE7XG4gICAgICAgICAgICAgICAgICAgIHZhciBpbnB1dCA9IHRoaXMsIHZhbHVlID0gaW5wdXQuaW5wdXRtYXNrLl92YWx1ZUdldCghMCk7XG4gICAgICAgICAgICAgICAgICAgICQuaXNGdW5jdGlvbihvcHRzLm9uQmVmb3JlTWFzaykgJiYgKHZhbHVlID0gb3B0cy5vbkJlZm9yZU1hc2suY2FsbChpbnB1dG1hc2ssIHZhbHVlLCBvcHRzKSB8fCB2YWx1ZSksIFxuICAgICAgICAgICAgICAgICAgICB2YWx1ZSA9IHZhbHVlLnNwbGl0KFwiXCIpLCBjaGVja1ZhbChpbnB1dCwgITAsICExLCBpc1JUTCA/IHZhbHVlLnJldmVyc2UoKSA6IHZhbHVlKSwgXG4gICAgICAgICAgICAgICAgICAgIHVuZG9WYWx1ZSA9IGdldEJ1ZmZlcigpLmpvaW4oXCJcIiksIChvcHRzLmNsZWFyTWFza09uTG9zdEZvY3VzIHx8IG9wdHMuY2xlYXJJbmNvbXBsZXRlKSAmJiBpbnB1dC5pbnB1dG1hc2suX3ZhbHVlR2V0KCkgPT09IGdldEJ1ZmZlclRlbXBsYXRlKCkuam9pbihcIlwiKSAmJiBpbnB1dC5pbnB1dG1hc2suX3ZhbHVlU2V0KFwiXCIpO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgZm9jdXNFdmVudDogZnVuY3Rpb24oZSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgaW5wdXQgPSB0aGlzLCBucHRWYWx1ZSA9IGlucHV0LmlucHV0bWFzay5fdmFsdWVHZXQoKTtcbiAgICAgICAgICAgICAgICAgICAgb3B0cy5zaG93TWFza09uRm9jdXMgJiYgKCFvcHRzLnNob3dNYXNrT25Ib3ZlciB8fCBvcHRzLnNob3dNYXNrT25Ib3ZlciAmJiBcIlwiID09PSBucHRWYWx1ZSkgJiYgKGlucHV0LmlucHV0bWFzay5fdmFsdWVHZXQoKSAhPT0gZ2V0QnVmZmVyKCkuam9pbihcIlwiKSA/IHdyaXRlQnVmZmVyKGlucHV0LCBnZXRCdWZmZXIoKSwgc2Vla05leHQoZ2V0TGFzdFZhbGlkUG9zaXRpb24oKSkpIDogITEgPT09IG1vdXNlRW50ZXIgJiYgY2FyZXQoaW5wdXQsIHNlZWtOZXh0KGdldExhc3RWYWxpZFBvc2l0aW9uKCkpKSksIFxuICAgICAgICAgICAgICAgICAgICAhMCA9PT0gb3B0cy5wb3NpdGlvbkNhcmV0T25UYWIgJiYgITEgPT09IG1vdXNlRW50ZXIgJiYgXCJcIiAhPT0gbnB0VmFsdWUgJiYgKHdyaXRlQnVmZmVyKGlucHV0LCBnZXRCdWZmZXIoKSwgY2FyZXQoaW5wdXQpKSwgXG4gICAgICAgICAgICAgICAgICAgIEV2ZW50SGFuZGxlcnMuY2xpY2tFdmVudC5hcHBseShpbnB1dCwgWyBlLCAhMCBdKSksIHVuZG9WYWx1ZSA9IGdldEJ1ZmZlcigpLmpvaW4oXCJcIik7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBtb3VzZWxlYXZlRXZlbnQ6IGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGlucHV0ID0gdGhpcztcbiAgICAgICAgICAgICAgICAgICAgaWYgKG1vdXNlRW50ZXIgPSAhMSwgb3B0cy5jbGVhck1hc2tPbkxvc3RGb2N1cyAmJiBkb2N1bWVudC5hY3RpdmVFbGVtZW50ICE9PSBpbnB1dCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGJ1ZmZlciA9IGdldEJ1ZmZlcigpLnNsaWNlKCksIG5wdFZhbHVlID0gaW5wdXQuaW5wdXRtYXNrLl92YWx1ZUdldCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgbnB0VmFsdWUgIT09IGlucHV0LmdldEF0dHJpYnV0ZShcInBsYWNlaG9sZGVyXCIpICYmIFwiXCIgIT09IG5wdFZhbHVlICYmICgtMSA9PT0gZ2V0TGFzdFZhbGlkUG9zaXRpb24oKSAmJiBucHRWYWx1ZSA9PT0gZ2V0QnVmZmVyVGVtcGxhdGUoKS5qb2luKFwiXCIpID8gYnVmZmVyID0gW10gOiBjbGVhck9wdGlvbmFsVGFpbChidWZmZXIpLCBcbiAgICAgICAgICAgICAgICAgICAgICAgIHdyaXRlQnVmZmVyKGlucHV0LCBidWZmZXIpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgY2xpY2tFdmVudDogZnVuY3Rpb24oZSwgdGFiYmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uIGRvUmFkaXhGb2N1cyhjbGlja1Bvcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKFwiXCIgIT09IG9wdHMucmFkaXhQb2ludCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciB2cHMgPSBnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnM7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHZwc1tjbGlja1Bvc10gPT09IHVuZGVmaW5lZCB8fCB2cHNbY2xpY2tQb3NdLmlucHV0ID09PSBnZXRQbGFjZWhvbGRlcihjbGlja1BvcykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNsaWNrUG9zIDwgc2Vla05leHQoLTEpKSByZXR1cm4gITA7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciByYWRpeFBvcyA9ICQuaW5BcnJheShvcHRzLnJhZGl4UG9pbnQsIGdldEJ1ZmZlcigpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKC0xICE9PSByYWRpeFBvcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgdnAgaW4gdnBzKSBpZiAocmFkaXhQb3MgPCB2cCAmJiB2cHNbdnBdLmlucHV0ICE9PSBnZXRQbGFjZWhvbGRlcih2cCkpIHJldHVybiAhMTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAhMDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAhMTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB2YXIgaW5wdXQgPSB0aGlzO1xuICAgICAgICAgICAgICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRvY3VtZW50LmFjdGl2ZUVsZW1lbnQgPT09IGlucHV0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHNlbGVjdGVkQ2FyZXQgPSBjYXJldChpbnB1dCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRhYmJlZCAmJiAoaXNSVEwgPyBzZWxlY3RlZENhcmV0LmVuZCA9IHNlbGVjdGVkQ2FyZXQuYmVnaW4gOiBzZWxlY3RlZENhcmV0LmJlZ2luID0gc2VsZWN0ZWRDYXJldC5lbmQpLCBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxlY3RlZENhcmV0LmJlZ2luID09PSBzZWxlY3RlZENhcmV0LmVuZCkgc3dpdGNoIChvcHRzLnBvc2l0aW9uQ2FyZXRPbkNsaWNrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFwibm9uZVwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBcInJhZGl4Rm9jdXNcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRvUmFkaXhGb2N1cyhzZWxlY3RlZENhcmV0LmJlZ2luKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHJhZGl4UG9zID0gZ2V0QnVmZmVyKCkuam9pbihcIlwiKS5pbmRleE9mKG9wdHMucmFkaXhQb2ludCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXJldChpbnB1dCwgb3B0cy5udW1lcmljSW5wdXQgPyBzZWVrTmV4dChyYWRpeFBvcykgOiByYWRpeFBvcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2xpY2tQb3NpdGlvbiA9IHNlbGVjdGVkQ2FyZXQuYmVnaW4sIGx2Y2xpY2tQb3NpdGlvbiA9IGdldExhc3RWYWxpZFBvc2l0aW9uKGNsaWNrUG9zaXRpb24sICEwKSwgbGFzdFBvc2l0aW9uID0gc2Vla05leHQobHZjbGlja1Bvc2l0aW9uKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNsaWNrUG9zaXRpb24gPCBsYXN0UG9zaXRpb24pIGNhcmV0KGlucHV0LCBpc01hc2soY2xpY2tQb3NpdGlvbiwgITApIHx8IGlzTWFzayhjbGlja1Bvc2l0aW9uIC0gMSwgITApID8gY2xpY2tQb3NpdGlvbiA6IHNlZWtOZXh0KGNsaWNrUG9zaXRpb24pKTsgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgbHZwID0gZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zW2x2Y2xpY2tQb3NpdGlvbl0sIHR0ID0gZ2V0VGVzdFRlbXBsYXRlKGxhc3RQb3NpdGlvbiwgbHZwID8gbHZwLm1hdGNoLmxvY2F0b3IgOiB1bmRlZmluZWQsIGx2cCksIHBsYWNlaG9sZGVyID0gZ2V0UGxhY2Vob2xkZXIobGFzdFBvc2l0aW9uLCB0dC5tYXRjaCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoXCJcIiAhPT0gcGxhY2Vob2xkZXIgJiYgZ2V0QnVmZmVyKClbbGFzdFBvc2l0aW9uXSAhPT0gcGxhY2Vob2xkZXIgJiYgITAgIT09IHR0Lm1hdGNoLm9wdGlvbmFsUXVhbnRpZmllciAmJiAhMCAhPT0gdHQubWF0Y2gubmV3QmxvY2tNYXJrZXIgfHwgIWlzTWFzayhsYXN0UG9zaXRpb24sICEwKSAmJiB0dC5tYXRjaC5kZWYgPT09IHBsYWNlaG9sZGVyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG5ld1BvcyA9IHNlZWtOZXh0KGxhc3RQb3NpdGlvbik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKGNsaWNrUG9zaXRpb24gPj0gbmV3UG9zIHx8IGNsaWNrUG9zaXRpb24gPT09IGxhc3RQb3NpdGlvbikgJiYgKGxhc3RQb3NpdGlvbiA9IG5ld1Bvcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXJldChpbnB1dCwgbGFzdFBvc2l0aW9uKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSwgMCk7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBkYmxjbGlja0V2ZW50OiBmdW5jdGlvbihlKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBpbnB1dCA9IHRoaXM7XG4gICAgICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXJldChpbnB1dCwgMCwgc2Vla05leHQoZ2V0TGFzdFZhbGlkUG9zaXRpb24oKSkpO1xuICAgICAgICAgICAgICAgICAgICB9LCAwKTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGN1dEV2ZW50OiBmdW5jdGlvbihlKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBpbnB1dCA9IHRoaXMsICRpbnB1dCA9ICQoaW5wdXQpLCBwb3MgPSBjYXJldChpbnB1dCksIGV2ID0gZS5vcmlnaW5hbEV2ZW50IHx8IGUsIGNsaXBib2FyZERhdGEgPSB3aW5kb3cuY2xpcGJvYXJkRGF0YSB8fCBldi5jbGlwYm9hcmREYXRhLCBjbGlwRGF0YSA9IGlzUlRMID8gZ2V0QnVmZmVyKCkuc2xpY2UocG9zLmVuZCwgcG9zLmJlZ2luKSA6IGdldEJ1ZmZlcigpLnNsaWNlKHBvcy5iZWdpbiwgcG9zLmVuZCk7XG4gICAgICAgICAgICAgICAgICAgIGNsaXBib2FyZERhdGEuc2V0RGF0YShcInRleHRcIiwgaXNSVEwgPyBjbGlwRGF0YS5yZXZlcnNlKCkuam9pbihcIlwiKSA6IGNsaXBEYXRhLmpvaW4oXCJcIikpLCBcbiAgICAgICAgICAgICAgICAgICAgZG9jdW1lbnQuZXhlY0NvbW1hbmQgJiYgZG9jdW1lbnQuZXhlY0NvbW1hbmQoXCJjb3B5XCIpLCBoYW5kbGVSZW1vdmUoaW5wdXQsIElucHV0bWFzay5rZXlDb2RlLkRFTEVURSwgcG9zKSwgXG4gICAgICAgICAgICAgICAgICAgIHdyaXRlQnVmZmVyKGlucHV0LCBnZXRCdWZmZXIoKSwgZ2V0TWFza1NldCgpLnAsIGUsIHVuZG9WYWx1ZSAhPT0gZ2V0QnVmZmVyKCkuam9pbihcIlwiKSksIFxuICAgICAgICAgICAgICAgICAgICBpbnB1dC5pbnB1dG1hc2suX3ZhbHVlR2V0KCkgPT09IGdldEJ1ZmZlclRlbXBsYXRlKCkuam9pbihcIlwiKSAmJiAkaW5wdXQudHJpZ2dlcihcImNsZWFyZWRcIik7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBibHVyRXZlbnQ6IGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyICRpbnB1dCA9ICQodGhpcyksIGlucHV0ID0gdGhpcztcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlucHV0LmlucHV0bWFzaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG5wdFZhbHVlID0gaW5wdXQuaW5wdXRtYXNrLl92YWx1ZUdldCgpLCBidWZmZXIgPSBnZXRCdWZmZXIoKS5zbGljZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgXCJcIiAhPT0gbnB0VmFsdWUgJiYgKG9wdHMuY2xlYXJNYXNrT25Mb3N0Rm9jdXMgJiYgKC0xID09PSBnZXRMYXN0VmFsaWRQb3NpdGlvbigpICYmIG5wdFZhbHVlID09PSBnZXRCdWZmZXJUZW1wbGF0ZSgpLmpvaW4oXCJcIikgPyBidWZmZXIgPSBbXSA6IGNsZWFyT3B0aW9uYWxUYWlsKGJ1ZmZlcikpLCBcbiAgICAgICAgICAgICAgICAgICAgICAgICExID09PSBpc0NvbXBsZXRlKGJ1ZmZlcikgJiYgKHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJGlucHV0LnRyaWdnZXIoXCJpbmNvbXBsZXRlXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSwgMCksIG9wdHMuY2xlYXJJbmNvbXBsZXRlICYmIChyZXNldE1hc2tTZXQoKSwgYnVmZmVyID0gb3B0cy5jbGVhck1hc2tPbkxvc3RGb2N1cyA/IFtdIDogZ2V0QnVmZmVyVGVtcGxhdGUoKS5zbGljZSgpKSksIFxuICAgICAgICAgICAgICAgICAgICAgICAgd3JpdGVCdWZmZXIoaW5wdXQsIGJ1ZmZlciwgdW5kZWZpbmVkLCBlKSksIHVuZG9WYWx1ZSAhPT0gZ2V0QnVmZmVyKCkuam9pbihcIlwiKSAmJiAodW5kb1ZhbHVlID0gYnVmZmVyLmpvaW4oXCJcIiksIFxuICAgICAgICAgICAgICAgICAgICAgICAgJGlucHV0LnRyaWdnZXIoXCJjaGFuZ2VcIikpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBtb3VzZWVudGVyRXZlbnQ6IGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGlucHV0ID0gdGhpcztcbiAgICAgICAgICAgICAgICAgICAgbW91c2VFbnRlciA9ICEwLCBkb2N1bWVudC5hY3RpdmVFbGVtZW50ICE9PSBpbnB1dCAmJiBvcHRzLnNob3dNYXNrT25Ib3ZlciAmJiBpbnB1dC5pbnB1dG1hc2suX3ZhbHVlR2V0KCkgIT09IGdldEJ1ZmZlcigpLmpvaW4oXCJcIikgJiYgd3JpdGVCdWZmZXIoaW5wdXQsIGdldEJ1ZmZlcigpKTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHN1Ym1pdEV2ZW50OiBmdW5jdGlvbihlKSB7XG4gICAgICAgICAgICAgICAgICAgIHVuZG9WYWx1ZSAhPT0gZ2V0QnVmZmVyKCkuam9pbihcIlwiKSAmJiAkZWwudHJpZ2dlcihcImNoYW5nZVwiKSwgb3B0cy5jbGVhck1hc2tPbkxvc3RGb2N1cyAmJiAtMSA9PT0gZ2V0TGFzdFZhbGlkUG9zaXRpb24oKSAmJiBlbC5pbnB1dG1hc2suX3ZhbHVlR2V0ICYmIGVsLmlucHV0bWFzay5fdmFsdWVHZXQoKSA9PT0gZ2V0QnVmZmVyVGVtcGxhdGUoKS5qb2luKFwiXCIpICYmIGVsLmlucHV0bWFzay5fdmFsdWVTZXQoXCJcIiksIFxuICAgICAgICAgICAgICAgICAgICBvcHRzLnJlbW92ZU1hc2tPblN1Ym1pdCAmJiAoZWwuaW5wdXRtYXNrLl92YWx1ZVNldChlbC5pbnB1dG1hc2sudW5tYXNrZWR2YWx1ZSgpLCAhMCksIFxuICAgICAgICAgICAgICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgd3JpdGVCdWZmZXIoZWwsIGdldEJ1ZmZlcigpKTtcbiAgICAgICAgICAgICAgICAgICAgfSwgMCkpO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgcmVzZXRFdmVudDogZnVuY3Rpb24oZSkge1xuICAgICAgICAgICAgICAgICAgICBlbC5pbnB1dG1hc2sucmVmcmVzaFZhbHVlID0gITAsIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAkZWwudHJpZ2dlcihcInNldHZhbHVlXCIpO1xuICAgICAgICAgICAgICAgICAgICB9LCAwKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgSW5wdXRtYXNrLnByb3RvdHlwZS5wb3NpdGlvbkNvbG9yTWFzayA9IGZ1bmN0aW9uKGlucHV0LCB0ZW1wbGF0ZSkge1xuICAgICAgICAgICAgICAgIGlucHV0LnN0eWxlLmxlZnQgPSB0ZW1wbGF0ZS5vZmZzZXRMZWZ0ICsgXCJweFwiO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHZhciB2YWx1ZUJ1ZmZlcjtcbiAgICAgICAgICAgIGlmIChhY3Rpb25PYmogIT09IHVuZGVmaW5lZCkgc3dpdGNoIChhY3Rpb25PYmouYWN0aW9uKSB7XG4gICAgICAgICAgICAgIGNhc2UgXCJpc0NvbXBsZXRlXCI6XG4gICAgICAgICAgICAgICAgcmV0dXJuIGVsID0gYWN0aW9uT2JqLmVsLCBpc0NvbXBsZXRlKGdldEJ1ZmZlcigpKTtcblxuICAgICAgICAgICAgICBjYXNlIFwidW5tYXNrZWR2YWx1ZVwiOlxuICAgICAgICAgICAgICAgIHJldHVybiBlbCAhPT0gdW5kZWZpbmVkICYmIGFjdGlvbk9iai52YWx1ZSA9PT0gdW5kZWZpbmVkIHx8ICh2YWx1ZUJ1ZmZlciA9IGFjdGlvbk9iai52YWx1ZSwgXG4gICAgICAgICAgICAgICAgdmFsdWVCdWZmZXIgPSAoJC5pc0Z1bmN0aW9uKG9wdHMub25CZWZvcmVNYXNrKSA/IG9wdHMub25CZWZvcmVNYXNrLmNhbGwoaW5wdXRtYXNrLCB2YWx1ZUJ1ZmZlciwgb3B0cykgfHwgdmFsdWVCdWZmZXIgOiB2YWx1ZUJ1ZmZlcikuc3BsaXQoXCJcIiksIFxuICAgICAgICAgICAgICAgIGNoZWNrVmFsKHVuZGVmaW5lZCwgITEsICExLCBpc1JUTCA/IHZhbHVlQnVmZmVyLnJldmVyc2UoKSA6IHZhbHVlQnVmZmVyKSwgJC5pc0Z1bmN0aW9uKG9wdHMub25CZWZvcmVXcml0ZSkgJiYgb3B0cy5vbkJlZm9yZVdyaXRlLmNhbGwoaW5wdXRtYXNrLCB1bmRlZmluZWQsIGdldEJ1ZmZlcigpLCAwLCBvcHRzKSksIFxuICAgICAgICAgICAgICAgIHVubWFza2VkdmFsdWUoZWwpO1xuXG4gICAgICAgICAgICAgIGNhc2UgXCJtYXNrXCI6XG4gICAgICAgICAgICAgICAgIWZ1bmN0aW9uKGVsZW0pIHtcbiAgICAgICAgICAgICAgICAgICAgRXZlbnRSdWxlci5vZmYoZWxlbSk7XG4gICAgICAgICAgICAgICAgICAgIHZhciBpc1N1cHBvcnRlZCA9IGZ1bmN0aW9uKGlucHV0LCBvcHRzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgZWxlbWVudFR5cGUgPSBpbnB1dC5nZXRBdHRyaWJ1dGUoXCJ0eXBlXCIpLCBpc1N1cHBvcnRlZCA9IFwiSU5QVVRcIiA9PT0gaW5wdXQudGFnTmFtZSAmJiAtMSAhPT0gJC5pbkFycmF5KGVsZW1lbnRUeXBlLCBvcHRzLnN1cHBvcnRzSW5wdXRUeXBlKSB8fCBpbnB1dC5pc0NvbnRlbnRFZGl0YWJsZSB8fCBcIlRFWFRBUkVBXCIgPT09IGlucHV0LnRhZ05hbWU7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWlzU3VwcG9ydGVkKSBpZiAoXCJJTlBVVFwiID09PSBpbnB1dC50YWdOYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGVsID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImlucHV0XCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsLnNldEF0dHJpYnV0ZShcInR5cGVcIiwgZWxlbWVudFR5cGUpLCBpc1N1cHBvcnRlZCA9IFwidGV4dFwiID09PSBlbC50eXBlLCBlbCA9IG51bGw7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaXNTdXBwb3J0ZWQgPSBcInBhcnRpYWxcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAhMSAhPT0gaXNTdXBwb3J0ZWQgPyBmdW5jdGlvbihucHQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmdW5jdGlvbiBnZXR0ZXIoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmlucHV0bWFzayA/IHRoaXMuaW5wdXRtYXNrLm9wdHMuYXV0b1VubWFzayA/IHRoaXMuaW5wdXRtYXNrLnVubWFza2VkdmFsdWUoKSA6IC0xICE9PSBnZXRMYXN0VmFsaWRQb3NpdGlvbigpIHx8ICEwICE9PSBvcHRzLm51bGxhYmxlID8gZG9jdW1lbnQuYWN0aXZlRWxlbWVudCA9PT0gdGhpcyAmJiBvcHRzLmNsZWFyTWFza09uTG9zdEZvY3VzID8gKGlzUlRMID8gY2xlYXJPcHRpb25hbFRhaWwoZ2V0QnVmZmVyKCkuc2xpY2UoKSkucmV2ZXJzZSgpIDogY2xlYXJPcHRpb25hbFRhaWwoZ2V0QnVmZmVyKCkuc2xpY2UoKSkpLmpvaW4oXCJcIikgOiB2YWx1ZUdldC5jYWxsKHRoaXMpIDogXCJcIiA6IHZhbHVlR2V0LmNhbGwodGhpcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uIHNldHRlcih2YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZVNldC5jYWxsKHRoaXMsIHZhbHVlKSwgdGhpcy5pbnB1dG1hc2sgJiYgJCh0aGlzKS50cmlnZ2VyKFwic2V0dmFsdWVcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciB2YWx1ZUdldCwgdmFsdWVTZXQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFucHQuaW5wdXRtYXNrLl9fdmFsdWVHZXQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCEwICE9PSBvcHRzLm5vVmFsdWVQYXRjaGluZykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcImZ1bmN0aW9uXCIgIT0gdHlwZW9mIE9iamVjdC5nZXRQcm90b3R5cGVPZiAmJiAoT2JqZWN0LmdldFByb3RvdHlwZU9mID0gXCJvYmplY3RcIiA9PT0gX3R5cGVvZihcInRlc3RcIi5fX3Byb3RvX18pID8gZnVuY3Rpb24ob2JqZWN0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBvYmplY3QuX19wcm90b19fO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gOiBmdW5jdGlvbihvYmplY3QpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG9iamVjdC5jb25zdHJ1Y3Rvci5wcm90b3R5cGU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHZhbHVlUHJvcGVydHkgPSBPYmplY3QuZ2V0UHJvdG90eXBlT2YgPyBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKE9iamVjdC5nZXRQcm90b3R5cGVPZihucHQpLCBcInZhbHVlXCIpIDogdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlUHJvcGVydHkgJiYgdmFsdWVQcm9wZXJ0eS5nZXQgJiYgdmFsdWVQcm9wZXJ0eS5zZXQgPyAodmFsdWVHZXQgPSB2YWx1ZVByb3BlcnR5LmdldCwgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWVTZXQgPSB2YWx1ZVByb3BlcnR5LnNldCwgT2JqZWN0LmRlZmluZVByb3BlcnR5KG5wdCwgXCJ2YWx1ZVwiLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdldDogZ2V0dGVyLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZXQ6IHNldHRlcixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uZmlndXJhYmxlOiAhMFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pKSA6IFwiSU5QVVRcIiAhPT0gbnB0LnRhZ05hbWUgJiYgKHZhbHVlR2V0ID0gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLnRleHRDb250ZW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sIHZhbHVlU2V0ID0gZnVuY3Rpb24odmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy50ZXh0Q29udGVudCA9IHZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShucHQsIFwidmFsdWVcIiwge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZXQ6IGdldHRlcixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2V0OiBzZXR0ZXIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbmZpZ3VyYWJsZTogITBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgZG9jdW1lbnQuX19sb29rdXBHZXR0ZXJfXyAmJiBucHQuX19sb29rdXBHZXR0ZXJfXyhcInZhbHVlXCIpICYmICh2YWx1ZUdldCA9IG5wdC5fX2xvb2t1cEdldHRlcl9fKFwidmFsdWVcIiksIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWVTZXQgPSBucHQuX19sb29rdXBTZXR0ZXJfXyhcInZhbHVlXCIpLCBucHQuX19kZWZpbmVHZXR0ZXJfXyhcInZhbHVlXCIsIGdldHRlciksIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbnB0Ll9fZGVmaW5lU2V0dGVyX18oXCJ2YWx1ZVwiLCBzZXR0ZXIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5wdC5pbnB1dG1hc2suX192YWx1ZUdldCA9IHZhbHVlR2V0LCBucHQuaW5wdXRtYXNrLl9fdmFsdWVTZXQgPSB2YWx1ZVNldDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBucHQuaW5wdXRtYXNrLl92YWx1ZUdldCA9IGZ1bmN0aW9uKG92ZXJydWxlUlRMKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gaXNSVEwgJiYgITAgIT09IG92ZXJydWxlUlRMID8gdmFsdWVHZXQuY2FsbCh0aGlzLmVsKS5zcGxpdChcIlwiKS5yZXZlcnNlKCkuam9pbihcIlwiKSA6IHZhbHVlR2V0LmNhbGwodGhpcy5lbCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sIG5wdC5pbnB1dG1hc2suX3ZhbHVlU2V0ID0gZnVuY3Rpb24odmFsdWUsIG92ZXJydWxlUlRMKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZVNldC5jYWxsKHRoaXMuZWwsIG51bGwgPT09IHZhbHVlIHx8IHZhbHVlID09PSB1bmRlZmluZWQgPyBcIlwiIDogITAgIT09IG92ZXJydWxlUlRMICYmIGlzUlRMID8gdmFsdWUuc3BsaXQoXCJcIikucmV2ZXJzZSgpLmpvaW4oXCJcIikgOiB2YWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sIHZhbHVlR2V0ID09PSB1bmRlZmluZWQgJiYgKHZhbHVlR2V0ID0gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy52YWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSwgdmFsdWVTZXQgPSBmdW5jdGlvbih2YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LCBmdW5jdGlvbih0eXBlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoJC52YWxIb29rcyAmJiAoJC52YWxIb29rc1t0eXBlXSA9PT0gdW5kZWZpbmVkIHx8ICEwICE9PSAkLnZhbEhvb2tzW3R5cGVdLmlucHV0bWFza3BhdGNoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciB2YWxob29rR2V0ID0gJC52YWxIb29rc1t0eXBlXSAmJiAkLnZhbEhvb2tzW3R5cGVdLmdldCA/ICQudmFsSG9va3NbdHlwZV0uZ2V0IDogZnVuY3Rpb24oZWxlbSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZWxlbS52YWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LCB2YWxob29rU2V0ID0gJC52YWxIb29rc1t0eXBlXSAmJiAkLnZhbEhvb2tzW3R5cGVdLnNldCA/ICQudmFsSG9va3NbdHlwZV0uc2V0IDogZnVuY3Rpb24oZWxlbSwgdmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGVsZW0udmFsdWUgPSB2YWx1ZSwgZWxlbTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICQudmFsSG9va3NbdHlwZV0gPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdldDogZnVuY3Rpb24oZWxlbSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVsZW0uaW5wdXRtYXNrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVsZW0uaW5wdXRtYXNrLm9wdHMuYXV0b1VubWFzaykgcmV0dXJuIGVsZW0uaW5wdXRtYXNrLnVubWFza2VkdmFsdWUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgcmVzdWx0ID0gdmFsaG9va0dldChlbGVtKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gLTEgIT09IGdldExhc3RWYWxpZFBvc2l0aW9uKHVuZGVmaW5lZCwgdW5kZWZpbmVkLCBlbGVtLmlucHV0bWFzay5tYXNrc2V0LnZhbGlkUG9zaXRpb25zKSB8fCAhMCAhPT0gb3B0cy5udWxsYWJsZSA/IHJlc3VsdCA6IFwiXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsaG9va0dldChlbGVtKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2V0OiBmdW5jdGlvbihlbGVtLCB2YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHJlc3VsdCwgJGVsZW0gPSAkKGVsZW0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCA9IHZhbGhvb2tTZXQoZWxlbSwgdmFsdWUpLCBlbGVtLmlucHV0bWFzayAmJiAkZWxlbS50cmlnZ2VyKFwic2V0dmFsdWVcIiksIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnB1dG1hc2twYXRjaDogITBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KG5wdC50eXBlKSwgZnVuY3Rpb24obnB0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBFdmVudFJ1bGVyLm9uKG5wdCwgXCJtb3VzZWVudGVyXCIsIGZ1bmN0aW9uKGV2ZW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyICRpbnB1dCA9ICQodGhpcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5pbnB1dG1hc2suX3ZhbHVlR2V0KCkgIT09IGdldEJ1ZmZlcigpLmpvaW4oXCJcIikgJiYgJGlucHV0LnRyaWdnZXIoXCJzZXR2YWx1ZVwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KG5wdCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0oaW5wdXQpIDogaW5wdXQuaW5wdXRtYXNrID0gdW5kZWZpbmVkLCBpc1N1cHBvcnRlZDtcbiAgICAgICAgICAgICAgICAgICAgfShlbGVtLCBvcHRzKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCExICE9PSBpc1N1cHBvcnRlZCAmJiAoZWwgPSBlbGVtLCAkZWwgPSAkKGVsKSwgLTEgPT09IChtYXhMZW5ndGggPSBlbCAhPT0gdW5kZWZpbmVkID8gZWwubWF4TGVuZ3RoIDogdW5kZWZpbmVkKSAmJiAobWF4TGVuZ3RoID0gdW5kZWZpbmVkKSwgXG4gICAgICAgICAgICAgICAgICAgICEwID09PSBvcHRzLmNvbG9yTWFzayAmJiBpbml0aWFsaXplQ29sb3JNYXNrKGVsKSwgYW5kcm9pZCAmJiAoZWwuaGFzT3duUHJvcGVydHkoXCJpbnB1dG1vZGVcIikgJiYgKGVsLmlucHV0bW9kZSA9IG9wdHMuaW5wdXRtb2RlLCBcbiAgICAgICAgICAgICAgICAgICAgZWwuc2V0QXR0cmlidXRlKFwiaW5wdXRtb2RlXCIsIG9wdHMuaW5wdXRtb2RlKSksIFwicnRmbVwiID09PSBvcHRzLmFuZHJvaWRIYWNrICYmICghMCAhPT0gb3B0cy5jb2xvck1hc2sgJiYgaW5pdGlhbGl6ZUNvbG9yTWFzayhlbCksIFxuICAgICAgICAgICAgICAgICAgICBlbC50eXBlID0gXCJwYXNzd29yZFwiKSksICEwID09PSBpc1N1cHBvcnRlZCAmJiAoRXZlbnRSdWxlci5vbihlbCwgXCJzdWJtaXRcIiwgRXZlbnRIYW5kbGVycy5zdWJtaXRFdmVudCksIFxuICAgICAgICAgICAgICAgICAgICBFdmVudFJ1bGVyLm9uKGVsLCBcInJlc2V0XCIsIEV2ZW50SGFuZGxlcnMucmVzZXRFdmVudCksIEV2ZW50UnVsZXIub24oZWwsIFwibW91c2VlbnRlclwiLCBFdmVudEhhbmRsZXJzLm1vdXNlZW50ZXJFdmVudCksIFxuICAgICAgICAgICAgICAgICAgICBFdmVudFJ1bGVyLm9uKGVsLCBcImJsdXJcIiwgRXZlbnRIYW5kbGVycy5ibHVyRXZlbnQpLCBFdmVudFJ1bGVyLm9uKGVsLCBcImZvY3VzXCIsIEV2ZW50SGFuZGxlcnMuZm9jdXNFdmVudCksIFxuICAgICAgICAgICAgICAgICAgICBFdmVudFJ1bGVyLm9uKGVsLCBcIm1vdXNlbGVhdmVcIiwgRXZlbnRIYW5kbGVycy5tb3VzZWxlYXZlRXZlbnQpLCAhMCAhPT0gb3B0cy5jb2xvck1hc2sgJiYgRXZlbnRSdWxlci5vbihlbCwgXCJjbGlja1wiLCBFdmVudEhhbmRsZXJzLmNsaWNrRXZlbnQpLCBcbiAgICAgICAgICAgICAgICAgICAgRXZlbnRSdWxlci5vbihlbCwgXCJkYmxjbGlja1wiLCBFdmVudEhhbmRsZXJzLmRibGNsaWNrRXZlbnQpLCBFdmVudFJ1bGVyLm9uKGVsLCBcInBhc3RlXCIsIEV2ZW50SGFuZGxlcnMucGFzdGVFdmVudCksIFxuICAgICAgICAgICAgICAgICAgICBFdmVudFJ1bGVyLm9uKGVsLCBcImRyYWdkcm9wXCIsIEV2ZW50SGFuZGxlcnMucGFzdGVFdmVudCksIEV2ZW50UnVsZXIub24oZWwsIFwiZHJvcFwiLCBFdmVudEhhbmRsZXJzLnBhc3RlRXZlbnQpLCBcbiAgICAgICAgICAgICAgICAgICAgRXZlbnRSdWxlci5vbihlbCwgXCJjdXRcIiwgRXZlbnRIYW5kbGVycy5jdXRFdmVudCksIEV2ZW50UnVsZXIub24oZWwsIFwiY29tcGxldGVcIiwgb3B0cy5vbmNvbXBsZXRlKSwgXG4gICAgICAgICAgICAgICAgICAgIEV2ZW50UnVsZXIub24oZWwsIFwiaW5jb21wbGV0ZVwiLCBvcHRzLm9uaW5jb21wbGV0ZSksIEV2ZW50UnVsZXIub24oZWwsIFwiY2xlYXJlZFwiLCBvcHRzLm9uY2xlYXJlZCksIFxuICAgICAgICAgICAgICAgICAgICBhbmRyb2lkIHx8ICEwID09PSBvcHRzLmlucHV0RXZlbnRPbmx5ID8gZWwucmVtb3ZlQXR0cmlidXRlKFwibWF4TGVuZ3RoXCIpIDogKEV2ZW50UnVsZXIub24oZWwsIFwia2V5ZG93blwiLCBFdmVudEhhbmRsZXJzLmtleWRvd25FdmVudCksIFxuICAgICAgICAgICAgICAgICAgICBFdmVudFJ1bGVyLm9uKGVsLCBcImtleXByZXNzXCIsIEV2ZW50SGFuZGxlcnMua2V5cHJlc3NFdmVudCkpLCBFdmVudFJ1bGVyLm9uKGVsLCBcImNvbXBvc2l0aW9uc3RhcnRcIiwgJC5ub29wKSwgXG4gICAgICAgICAgICAgICAgICAgIEV2ZW50UnVsZXIub24oZWwsIFwiY29tcG9zaXRpb251cGRhdGVcIiwgJC5ub29wKSwgRXZlbnRSdWxlci5vbihlbCwgXCJjb21wb3NpdGlvbmVuZFwiLCAkLm5vb3ApLCBcbiAgICAgICAgICAgICAgICAgICAgRXZlbnRSdWxlci5vbihlbCwgXCJrZXl1cFwiLCAkLm5vb3ApLCBFdmVudFJ1bGVyLm9uKGVsLCBcImlucHV0XCIsIEV2ZW50SGFuZGxlcnMuaW5wdXRGYWxsQmFja0V2ZW50KSwgXG4gICAgICAgICAgICAgICAgICAgIEV2ZW50UnVsZXIub24oZWwsIFwiYmVmb3JlaW5wdXRcIiwgJC5ub29wKSksIEV2ZW50UnVsZXIub24oZWwsIFwic2V0dmFsdWVcIiwgRXZlbnRIYW5kbGVycy5zZXRWYWx1ZUV2ZW50KSwgXG4gICAgICAgICAgICAgICAgICAgIHVuZG9WYWx1ZSA9IGdldEJ1ZmZlclRlbXBsYXRlKCkuam9pbihcIlwiKSwgXCJcIiAhPT0gZWwuaW5wdXRtYXNrLl92YWx1ZUdldCghMCkgfHwgITEgPT09IG9wdHMuY2xlYXJNYXNrT25Mb3N0Rm9jdXMgfHwgZG9jdW1lbnQuYWN0aXZlRWxlbWVudCA9PT0gZWwpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgaW5pdGlhbFZhbHVlID0gJC5pc0Z1bmN0aW9uKG9wdHMub25CZWZvcmVNYXNrKSA/IG9wdHMub25CZWZvcmVNYXNrLmNhbGwoaW5wdXRtYXNrLCBlbC5pbnB1dG1hc2suX3ZhbHVlR2V0KCEwKSwgb3B0cykgfHwgZWwuaW5wdXRtYXNrLl92YWx1ZUdldCghMCkgOiBlbC5pbnB1dG1hc2suX3ZhbHVlR2V0KCEwKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIFwiXCIgIT09IGluaXRpYWxWYWx1ZSAmJiBjaGVja1ZhbChlbCwgITAsICExLCBpc1JUTCA/IGluaXRpYWxWYWx1ZS5zcGxpdChcIlwiKS5yZXZlcnNlKCkgOiBpbml0aWFsVmFsdWUuc3BsaXQoXCJcIikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGJ1ZmZlciA9IGdldEJ1ZmZlcigpLnNsaWNlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB1bmRvVmFsdWUgPSBidWZmZXIuam9pbihcIlwiKSwgITEgPT09IGlzQ29tcGxldGUoYnVmZmVyKSAmJiBvcHRzLmNsZWFySW5jb21wbGV0ZSAmJiByZXNldE1hc2tTZXQoKSwgXG4gICAgICAgICAgICAgICAgICAgICAgICBvcHRzLmNsZWFyTWFza09uTG9zdEZvY3VzICYmIGRvY3VtZW50LmFjdGl2ZUVsZW1lbnQgIT09IGVsICYmICgtMSA9PT0gZ2V0TGFzdFZhbGlkUG9zaXRpb24oKSA/IGJ1ZmZlciA9IFtdIDogY2xlYXJPcHRpb25hbFRhaWwoYnVmZmVyKSksIFxuICAgICAgICAgICAgICAgICAgICAgICAgd3JpdGVCdWZmZXIoZWwsIGJ1ZmZlciksIGRvY3VtZW50LmFjdGl2ZUVsZW1lbnQgPT09IGVsICYmIGNhcmV0KGVsLCBzZWVrTmV4dChnZXRMYXN0VmFsaWRQb3NpdGlvbigpKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KGVsKTtcbiAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgICBjYXNlIFwiZm9ybWF0XCI6XG4gICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlQnVmZmVyID0gKCQuaXNGdW5jdGlvbihvcHRzLm9uQmVmb3JlTWFzaykgPyBvcHRzLm9uQmVmb3JlTWFzay5jYWxsKGlucHV0bWFzaywgYWN0aW9uT2JqLnZhbHVlLCBvcHRzKSB8fCBhY3Rpb25PYmoudmFsdWUgOiBhY3Rpb25PYmoudmFsdWUpLnNwbGl0KFwiXCIpLCBcbiAgICAgICAgICAgICAgICBjaGVja1ZhbCh1bmRlZmluZWQsICEwLCAhMSwgaXNSVEwgPyB2YWx1ZUJ1ZmZlci5yZXZlcnNlKCkgOiB2YWx1ZUJ1ZmZlciksIGFjdGlvbk9iai5tZXRhZGF0YSA/IHtcbiAgICAgICAgICAgICAgICAgICAgdmFsdWU6IGlzUlRMID8gZ2V0QnVmZmVyKCkuc2xpY2UoKS5yZXZlcnNlKCkuam9pbihcIlwiKSA6IGdldEJ1ZmZlcigpLmpvaW4oXCJcIiksXG4gICAgICAgICAgICAgICAgICAgIG1ldGFkYXRhOiBtYXNrU2NvcGUuY2FsbCh0aGlzLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhY3Rpb246IFwiZ2V0bWV0YWRhdGFcIlxuICAgICAgICAgICAgICAgICAgICB9LCBtYXNrc2V0LCBvcHRzKVxuICAgICAgICAgICAgICAgIH0gOiBpc1JUTCA/IGdldEJ1ZmZlcigpLnNsaWNlKCkucmV2ZXJzZSgpLmpvaW4oXCJcIikgOiBnZXRCdWZmZXIoKS5qb2luKFwiXCIpO1xuXG4gICAgICAgICAgICAgIGNhc2UgXCJpc1ZhbGlkXCI6XG4gICAgICAgICAgICAgICAgYWN0aW9uT2JqLnZhbHVlID8gKHZhbHVlQnVmZmVyID0gYWN0aW9uT2JqLnZhbHVlLnNwbGl0KFwiXCIpLCBjaGVja1ZhbCh1bmRlZmluZWQsICEwLCAhMCwgaXNSVEwgPyB2YWx1ZUJ1ZmZlci5yZXZlcnNlKCkgOiB2YWx1ZUJ1ZmZlcikpIDogYWN0aW9uT2JqLnZhbHVlID0gZ2V0QnVmZmVyKCkuam9pbihcIlwiKTtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBidWZmZXIgPSBnZXRCdWZmZXIoKSwgcmwgPSBkZXRlcm1pbmVMYXN0UmVxdWlyZWRQb3NpdGlvbigpLCBsbWliID0gYnVmZmVyLmxlbmd0aCAtIDE7IGxtaWIgPiBybCAmJiAhaXNNYXNrKGxtaWIpOyBsbWliLS0pIDtcbiAgICAgICAgICAgICAgICByZXR1cm4gYnVmZmVyLnNwbGljZShybCwgbG1pYiArIDEgLSBybCksIGlzQ29tcGxldGUoYnVmZmVyKSAmJiBhY3Rpb25PYmoudmFsdWUgPT09IGdldEJ1ZmZlcigpLmpvaW4oXCJcIik7XG5cbiAgICAgICAgICAgICAgY2FzZSBcImdldGVtcHR5bWFza1wiOlxuICAgICAgICAgICAgICAgIHJldHVybiBnZXRCdWZmZXJUZW1wbGF0ZSgpLmpvaW4oXCJcIik7XG5cbiAgICAgICAgICAgICAgY2FzZSBcInJlbW92ZVwiOlxuICAgICAgICAgICAgICAgIGlmIChlbCAmJiBlbC5pbnB1dG1hc2spIHtcbiAgICAgICAgICAgICAgICAgICAgJGVsID0gJChlbCksIGVsLmlucHV0bWFzay5fdmFsdWVTZXQob3B0cy5hdXRvVW5tYXNrID8gdW5tYXNrZWR2YWx1ZShlbCkgOiBlbC5pbnB1dG1hc2suX3ZhbHVlR2V0KCEwKSksIFxuICAgICAgICAgICAgICAgICAgICBFdmVudFJ1bGVyLm9mZihlbCk7XG4gICAgICAgICAgICAgICAgICAgIE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IgJiYgT2JqZWN0LmdldFByb3RvdHlwZU9mID8gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihPYmplY3QuZ2V0UHJvdG90eXBlT2YoZWwpLCBcInZhbHVlXCIpICYmIGVsLmlucHV0bWFzay5fX3ZhbHVlR2V0ICYmIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShlbCwgXCJ2YWx1ZVwiLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICBnZXQ6IGVsLmlucHV0bWFzay5fX3ZhbHVlR2V0LFxuICAgICAgICAgICAgICAgICAgICAgICAgc2V0OiBlbC5pbnB1dG1hc2suX192YWx1ZVNldCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbmZpZ3VyYWJsZTogITBcbiAgICAgICAgICAgICAgICAgICAgfSkgOiBkb2N1bWVudC5fX2xvb2t1cEdldHRlcl9fICYmIGVsLl9fbG9va3VwR2V0dGVyX18oXCJ2YWx1ZVwiKSAmJiBlbC5pbnB1dG1hc2suX192YWx1ZUdldCAmJiAoZWwuX19kZWZpbmVHZXR0ZXJfXyhcInZhbHVlXCIsIGVsLmlucHV0bWFzay5fX3ZhbHVlR2V0KSwgXG4gICAgICAgICAgICAgICAgICAgIGVsLl9fZGVmaW5lU2V0dGVyX18oXCJ2YWx1ZVwiLCBlbC5pbnB1dG1hc2suX192YWx1ZVNldCkpLCBlbC5pbnB1dG1hc2sgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBlbDtcblxuICAgICAgICAgICAgICBjYXNlIFwiZ2V0bWV0YWRhdGFcIjpcbiAgICAgICAgICAgICAgICBpZiAoJC5pc0FycmF5KG1hc2tzZXQubWV0YWRhdGEpKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBtYXNrVGFyZ2V0ID0gZ2V0TWFza1RlbXBsYXRlKCEwLCAwLCAhMSkuam9pbihcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICQuZWFjaChtYXNrc2V0Lm1ldGFkYXRhLCBmdW5jdGlvbihuZHgsIG10ZHQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtdGR0Lm1hc2sgPT09IG1hc2tUYXJnZXQpIHJldHVybiBtYXNrVGFyZ2V0ID0gbXRkdCwgITE7XG4gICAgICAgICAgICAgICAgICAgIH0pLCBtYXNrVGFyZ2V0O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gbWFza3NldC5tZXRhZGF0YTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB2YXIgdWEgPSBuYXZpZ2F0b3IudXNlckFnZW50LCBtb2JpbGUgPSAvbW9iaWxlL2kudGVzdCh1YSksIGllbW9iaWxlID0gL2llbW9iaWxlL2kudGVzdCh1YSksIGlwaG9uZSA9IC9pcGhvbmUvaS50ZXN0KHVhKSAmJiAhaWVtb2JpbGUsIGFuZHJvaWQgPSAvYW5kcm9pZC9pLnRlc3QodWEpICYmICFpZW1vYmlsZTtcbiAgICAgICAgcmV0dXJuIElucHV0bWFzay5wcm90b3R5cGUgPSB7XG4gICAgICAgICAgICBkYXRhQXR0cmlidXRlOiBcImRhdGEtaW5wdXRtYXNrXCIsXG4gICAgICAgICAgICBkZWZhdWx0czoge1xuICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyOiBcIl9cIixcbiAgICAgICAgICAgICAgICBvcHRpb25hbG1hcmtlcjoge1xuICAgICAgICAgICAgICAgICAgICBzdGFydDogXCJbXCIsXG4gICAgICAgICAgICAgICAgICAgIGVuZDogXCJdXCJcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHF1YW50aWZpZXJtYXJrZXI6IHtcbiAgICAgICAgICAgICAgICAgICAgc3RhcnQ6IFwie1wiLFxuICAgICAgICAgICAgICAgICAgICBlbmQ6IFwifVwiXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBncm91cG1hcmtlcjoge1xuICAgICAgICAgICAgICAgICAgICBzdGFydDogXCIoXCIsXG4gICAgICAgICAgICAgICAgICAgIGVuZDogXCIpXCJcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGFsdGVybmF0b3JtYXJrZXI6IFwifFwiLFxuICAgICAgICAgICAgICAgIGVzY2FwZUNoYXI6IFwiXFxcXFwiLFxuICAgICAgICAgICAgICAgIG1hc2s6IG51bGwsXG4gICAgICAgICAgICAgICAgcmVnZXg6IG51bGwsXG4gICAgICAgICAgICAgICAgb25jb21wbGV0ZTogJC5ub29wLFxuICAgICAgICAgICAgICAgIG9uaW5jb21wbGV0ZTogJC5ub29wLFxuICAgICAgICAgICAgICAgIG9uY2xlYXJlZDogJC5ub29wLFxuICAgICAgICAgICAgICAgIHJlcGVhdDogMCxcbiAgICAgICAgICAgICAgICBncmVlZHk6ICEwLFxuICAgICAgICAgICAgICAgIGF1dG9Vbm1hc2s6ICExLFxuICAgICAgICAgICAgICAgIHJlbW92ZU1hc2tPblN1Ym1pdDogITEsXG4gICAgICAgICAgICAgICAgY2xlYXJNYXNrT25Mb3N0Rm9jdXM6ICEwLFxuICAgICAgICAgICAgICAgIGluc2VydE1vZGU6ICEwLFxuICAgICAgICAgICAgICAgIGNsZWFySW5jb21wbGV0ZTogITEsXG4gICAgICAgICAgICAgICAgYWxpYXM6IG51bGwsXG4gICAgICAgICAgICAgICAgb25LZXlEb3duOiAkLm5vb3AsXG4gICAgICAgICAgICAgICAgb25CZWZvcmVNYXNrOiBudWxsLFxuICAgICAgICAgICAgICAgIG9uQmVmb3JlUGFzdGU6IGZ1bmN0aW9uKHBhc3RlZFZhbHVlLCBvcHRzKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAkLmlzRnVuY3Rpb24ob3B0cy5vbkJlZm9yZU1hc2spID8gb3B0cy5vbkJlZm9yZU1hc2suY2FsbCh0aGlzLCBwYXN0ZWRWYWx1ZSwgb3B0cykgOiBwYXN0ZWRWYWx1ZTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIG9uQmVmb3JlV3JpdGU6IG51bGwsXG4gICAgICAgICAgICAgICAgb25Vbk1hc2s6IG51bGwsXG4gICAgICAgICAgICAgICAgc2hvd01hc2tPbkZvY3VzOiAhMCxcbiAgICAgICAgICAgICAgICBzaG93TWFza09uSG92ZXI6ICEwLFxuICAgICAgICAgICAgICAgIG9uS2V5VmFsaWRhdGlvbjogJC5ub29wLFxuICAgICAgICAgICAgICAgIHNraXBPcHRpb25hbFBhcnRDaGFyYWN0ZXI6IFwiIFwiLFxuICAgICAgICAgICAgICAgIG51bWVyaWNJbnB1dDogITEsXG4gICAgICAgICAgICAgICAgcmlnaHRBbGlnbjogITEsXG4gICAgICAgICAgICAgICAgdW5kb09uRXNjYXBlOiAhMCxcbiAgICAgICAgICAgICAgICByYWRpeFBvaW50OiBcIlwiLFxuICAgICAgICAgICAgICAgIHJhZGl4UG9pbnREZWZpbml0aW9uU3ltYm9sOiB1bmRlZmluZWQsXG4gICAgICAgICAgICAgICAgZ3JvdXBTZXBhcmF0b3I6IFwiXCIsXG4gICAgICAgICAgICAgICAga2VlcFN0YXRpYzogbnVsbCxcbiAgICAgICAgICAgICAgICBwb3NpdGlvbkNhcmV0T25UYWI6ICEwLFxuICAgICAgICAgICAgICAgIHRhYlRocm91Z2g6ICExLFxuICAgICAgICAgICAgICAgIHN1cHBvcnRzSW5wdXRUeXBlOiBbIFwidGV4dFwiLCBcInRlbFwiLCBcInBhc3N3b3JkXCIgXSxcbiAgICAgICAgICAgICAgICBpZ25vcmFibGVzOiBbIDgsIDksIDEzLCAxOSwgMjcsIDMzLCAzNCwgMzUsIDM2LCAzNywgMzgsIDM5LCA0MCwgNDUsIDQ2LCA5MywgMTEyLCAxMTMsIDExNCwgMTE1LCAxMTYsIDExNywgMTE4LCAxMTksIDEyMCwgMTIxLCAxMjIsIDEyMywgMCwgMjI5IF0sXG4gICAgICAgICAgICAgICAgaXNDb21wbGV0ZTogbnVsbCxcbiAgICAgICAgICAgICAgICBjYW5DbGVhclBvc2l0aW9uOiAkLm5vb3AsXG4gICAgICAgICAgICAgICAgcHJlVmFsaWRhdGlvbjogbnVsbCxcbiAgICAgICAgICAgICAgICBwb3N0VmFsaWRhdGlvbjogbnVsbCxcbiAgICAgICAgICAgICAgICBzdGF0aWNEZWZpbml0aW9uU3ltYm9sOiB1bmRlZmluZWQsXG4gICAgICAgICAgICAgICAgaml0TWFza2luZzogITEsXG4gICAgICAgICAgICAgICAgbnVsbGFibGU6ICEwLFxuICAgICAgICAgICAgICAgIGlucHV0RXZlbnRPbmx5OiAhMSxcbiAgICAgICAgICAgICAgICBub1ZhbHVlUGF0Y2hpbmc6ICExLFxuICAgICAgICAgICAgICAgIHBvc2l0aW9uQ2FyZXRPbkNsaWNrOiBcImx2cFwiLFxuICAgICAgICAgICAgICAgIGNhc2luZzogbnVsbCxcbiAgICAgICAgICAgICAgICBpbnB1dG1vZGU6IFwidmVyYmF0aW1cIixcbiAgICAgICAgICAgICAgICBjb2xvck1hc2s6ICExLFxuICAgICAgICAgICAgICAgIGFuZHJvaWRIYWNrOiAhMSxcbiAgICAgICAgICAgICAgICBpbXBvcnREYXRhQXR0cmlidXRlczogITBcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBkZWZpbml0aW9uczoge1xuICAgICAgICAgICAgICAgIFwiOVwiOiB7XG4gICAgICAgICAgICAgICAgICAgIHZhbGlkYXRvcjogXCJbMC0577yRLe+8mV1cIixcbiAgICAgICAgICAgICAgICAgICAgY2FyZGluYWxpdHk6IDEsXG4gICAgICAgICAgICAgICAgICAgIGRlZmluaXRpb25TeW1ib2w6IFwiKlwiXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBhOiB7XG4gICAgICAgICAgICAgICAgICAgIHZhbGlkYXRvcjogXCJbQS1aYS160JAt0Y/QgdGRw4Atw7/CtV1cIixcbiAgICAgICAgICAgICAgICAgICAgY2FyZGluYWxpdHk6IDEsXG4gICAgICAgICAgICAgICAgICAgIGRlZmluaXRpb25TeW1ib2w6IFwiKlwiXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBcIipcIjoge1xuICAgICAgICAgICAgICAgICAgICB2YWxpZGF0b3I6IFwiWzAtOe+8kS3vvJlBLVphLXrQkC3Rj9CB0ZHDgC3Dv8K1XVwiLFxuICAgICAgICAgICAgICAgICAgICBjYXJkaW5hbGl0eTogMVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBhbGlhc2VzOiB7fSxcbiAgICAgICAgICAgIG1hc2tzQ2FjaGU6IHt9LFxuICAgICAgICAgICAgbWFzazogZnVuY3Rpb24oZWxlbXMpIHtcbiAgICAgICAgICAgICAgICBmdW5jdGlvbiBpbXBvcnRBdHRyaWJ1dGVPcHRpb25zKG5wdCwgb3B0cywgdXNlck9wdGlvbnMsIGRhdGFBdHRyaWJ1dGUpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEwID09PSBvcHRzLmltcG9ydERhdGFBdHRyaWJ1dGVzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgb3B0aW9uLCBkYXRhb3B0aW9ucywgb3B0aW9uRGF0YSwgcCwgaW1wb3J0T3B0aW9uID0gZnVuY3Rpb24ob3B0aW9uLCBvcHRpb25EYXRhKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbnVsbCAhPT0gKG9wdGlvbkRhdGEgPSBvcHRpb25EYXRhICE9PSB1bmRlZmluZWQgPyBvcHRpb25EYXRhIDogbnB0LmdldEF0dHJpYnV0ZShkYXRhQXR0cmlidXRlICsgXCItXCIgKyBvcHRpb24pKSAmJiAoXCJzdHJpbmdcIiA9PSB0eXBlb2Ygb3B0aW9uRGF0YSAmJiAoMCA9PT0gb3B0aW9uLmluZGV4T2YoXCJvblwiKSA/IG9wdGlvbkRhdGEgPSB3aW5kb3dbb3B0aW9uRGF0YV0gOiBcImZhbHNlXCIgPT09IG9wdGlvbkRhdGEgPyBvcHRpb25EYXRhID0gITEgOiBcInRydWVcIiA9PT0gb3B0aW9uRGF0YSAmJiAob3B0aW9uRGF0YSA9ICEwKSksIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVzZXJPcHRpb25zW29wdGlvbl0gPSBvcHRpb25EYXRhKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0sIGF0dHJPcHRpb25zID0gbnB0LmdldEF0dHJpYnV0ZShkYXRhQXR0cmlidXRlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhdHRyT3B0aW9ucyAmJiBcIlwiICE9PSBhdHRyT3B0aW9ucyAmJiAoYXR0ck9wdGlvbnMgPSBhdHRyT3B0aW9ucy5yZXBsYWNlKG5ldyBSZWdFeHAoXCInXCIsIFwiZ1wiKSwgJ1wiJyksIFxuICAgICAgICAgICAgICAgICAgICAgICAgZGF0YW9wdGlvbnMgPSBKU09OLnBhcnNlKFwie1wiICsgYXR0ck9wdGlvbnMgKyBcIn1cIikpLCBkYXRhb3B0aW9ucykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9wdGlvbkRhdGEgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChwIGluIGRhdGFvcHRpb25zKSBpZiAoXCJhbGlhc1wiID09PSBwLnRvTG93ZXJDYXNlKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3B0aW9uRGF0YSA9IGRhdGFvcHRpb25zW3BdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBpbXBvcnRPcHRpb24oXCJhbGlhc1wiLCBvcHRpb25EYXRhKSwgdXNlck9wdGlvbnMuYWxpYXMgJiYgcmVzb2x2ZUFsaWFzKHVzZXJPcHRpb25zLmFsaWFzLCB1c2VyT3B0aW9ucywgb3B0cyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKG9wdGlvbiBpbiBvcHRzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRhdGFvcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9wdGlvbkRhdGEgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAocCBpbiBkYXRhb3B0aW9ucykgaWYgKHAudG9Mb3dlckNhc2UoKSA9PT0gb3B0aW9uLnRvTG93ZXJDYXNlKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9wdGlvbkRhdGEgPSBkYXRhb3B0aW9uc1twXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGltcG9ydE9wdGlvbihvcHRpb24sIG9wdGlvbkRhdGEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAkLmV4dGVuZCghMCwgb3B0cywgdXNlck9wdGlvbnMpLCAoXCJydGxcIiA9PT0gbnB0LmRpciB8fCBvcHRzLnJpZ2h0QWxpZ24pICYmIChucHQuc3R5bGUudGV4dEFsaWduID0gXCJyaWdodFwiKSwgXG4gICAgICAgICAgICAgICAgICAgIChcInJ0bFwiID09PSBucHQuZGlyIHx8IG9wdHMubnVtZXJpY0lucHV0KSAmJiAobnB0LmRpciA9IFwibHRyXCIsIG5wdC5yZW1vdmVBdHRyaWJ1dGUoXCJkaXJcIiksIFxuICAgICAgICAgICAgICAgICAgICBvcHRzLmlzUlRMID0gITApLCBvcHRzO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgdGhhdCA9IHRoaXM7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFwic3RyaW5nXCIgPT0gdHlwZW9mIGVsZW1zICYmIChlbGVtcyA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGVsZW1zKSB8fCBkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKGVsZW1zKSksIFxuICAgICAgICAgICAgICAgIGVsZW1zID0gZWxlbXMubm9kZU5hbWUgPyBbIGVsZW1zIF0gOiBlbGVtcywgJC5lYWNoKGVsZW1zLCBmdW5jdGlvbihuZHgsIGVsKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBzY29wZWRPcHRzID0gJC5leHRlbmQoITAsIHt9LCB0aGF0Lm9wdHMpO1xuICAgICAgICAgICAgICAgICAgICBpbXBvcnRBdHRyaWJ1dGVPcHRpb25zKGVsLCBzY29wZWRPcHRzLCAkLmV4dGVuZCghMCwge30sIHRoYXQudXNlck9wdGlvbnMpLCB0aGF0LmRhdGFBdHRyaWJ1dGUpO1xuICAgICAgICAgICAgICAgICAgICB2YXIgbWFza3NldCA9IGdlbmVyYXRlTWFza1NldChzY29wZWRPcHRzLCB0aGF0Lm5vTWFza3NDYWNoZSk7XG4gICAgICAgICAgICAgICAgICAgIG1hc2tzZXQgIT09IHVuZGVmaW5lZCAmJiAoZWwuaW5wdXRtYXNrICE9PSB1bmRlZmluZWQgJiYgKGVsLmlucHV0bWFzay5vcHRzLmF1dG9Vbm1hc2sgPSAhMCwgXG4gICAgICAgICAgICAgICAgICAgIGVsLmlucHV0bWFzay5yZW1vdmUoKSksIGVsLmlucHV0bWFzayA9IG5ldyBJbnB1dG1hc2sodW5kZWZpbmVkLCB1bmRlZmluZWQsICEwKSwgXG4gICAgICAgICAgICAgICAgICAgIGVsLmlucHV0bWFzay5vcHRzID0gc2NvcGVkT3B0cywgZWwuaW5wdXRtYXNrLm5vTWFza3NDYWNoZSA9IHRoYXQubm9NYXNrc0NhY2hlLCBlbC5pbnB1dG1hc2sudXNlck9wdGlvbnMgPSAkLmV4dGVuZCghMCwge30sIHRoYXQudXNlck9wdGlvbnMpLCBcbiAgICAgICAgICAgICAgICAgICAgZWwuaW5wdXRtYXNrLmlzUlRMID0gc2NvcGVkT3B0cy5pc1JUTCB8fCBzY29wZWRPcHRzLm51bWVyaWNJbnB1dCwgZWwuaW5wdXRtYXNrLmVsID0gZWwsIFxuICAgICAgICAgICAgICAgICAgICBlbC5pbnB1dG1hc2subWFza3NldCA9IG1hc2tzZXQsICQuZGF0YShlbCwgXCJfaW5wdXRtYXNrX29wdHNcIiwgc2NvcGVkT3B0cyksIG1hc2tTY29wZS5jYWxsKGVsLmlucHV0bWFzaywge1xuICAgICAgICAgICAgICAgICAgICAgICAgYWN0aW9uOiBcIm1hc2tcIlxuICAgICAgICAgICAgICAgICAgICB9KSk7XG4gICAgICAgICAgICAgICAgfSksIGVsZW1zICYmIGVsZW1zWzBdID8gZWxlbXNbMF0uaW5wdXRtYXNrIHx8IHRoaXMgOiB0aGlzO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG9wdGlvbjogZnVuY3Rpb24ob3B0aW9ucywgbm9yZW1hc2spIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gXCJzdHJpbmdcIiA9PSB0eXBlb2Ygb3B0aW9ucyA/IHRoaXMub3B0c1tvcHRpb25zXSA6IFwib2JqZWN0XCIgPT09ICh2b2lkIDAgPT09IG9wdGlvbnMgPyBcInVuZGVmaW5lZFwiIDogX3R5cGVvZihvcHRpb25zKSkgPyAoJC5leHRlbmQodGhpcy51c2VyT3B0aW9ucywgb3B0aW9ucyksIFxuICAgICAgICAgICAgICAgIHRoaXMuZWwgJiYgITAgIT09IG5vcmVtYXNrICYmIHRoaXMubWFzayh0aGlzLmVsKSwgdGhpcykgOiB2b2lkIDA7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgdW5tYXNrZWR2YWx1ZTogZnVuY3Rpb24odmFsdWUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5tYXNrc2V0ID0gdGhpcy5tYXNrc2V0IHx8IGdlbmVyYXRlTWFza1NldCh0aGlzLm9wdHMsIHRoaXMubm9NYXNrc0NhY2hlKSwgXG4gICAgICAgICAgICAgICAgbWFza1Njb3BlLmNhbGwodGhpcywge1xuICAgICAgICAgICAgICAgICAgICBhY3Rpb246IFwidW5tYXNrZWR2YWx1ZVwiLFxuICAgICAgICAgICAgICAgICAgICB2YWx1ZTogdmFsdWVcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICByZW1vdmU6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBtYXNrU2NvcGUuY2FsbCh0aGlzLCB7XG4gICAgICAgICAgICAgICAgICAgIGFjdGlvbjogXCJyZW1vdmVcIlxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGdldGVtcHR5bWFzazogZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMubWFza3NldCA9IHRoaXMubWFza3NldCB8fCBnZW5lcmF0ZU1hc2tTZXQodGhpcy5vcHRzLCB0aGlzLm5vTWFza3NDYWNoZSksIFxuICAgICAgICAgICAgICAgIG1hc2tTY29wZS5jYWxsKHRoaXMsIHtcbiAgICAgICAgICAgICAgICAgICAgYWN0aW9uOiBcImdldGVtcHR5bWFza1wiXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgaGFzTWFza2VkVmFsdWU6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAhdGhpcy5vcHRzLmF1dG9Vbm1hc2s7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgaXNDb21wbGV0ZTogZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMubWFza3NldCA9IHRoaXMubWFza3NldCB8fCBnZW5lcmF0ZU1hc2tTZXQodGhpcy5vcHRzLCB0aGlzLm5vTWFza3NDYWNoZSksIFxuICAgICAgICAgICAgICAgIG1hc2tTY29wZS5jYWxsKHRoaXMsIHtcbiAgICAgICAgICAgICAgICAgICAgYWN0aW9uOiBcImlzQ29tcGxldGVcIlxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGdldG1ldGFkYXRhOiBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5tYXNrc2V0ID0gdGhpcy5tYXNrc2V0IHx8IGdlbmVyYXRlTWFza1NldCh0aGlzLm9wdHMsIHRoaXMubm9NYXNrc0NhY2hlKSwgXG4gICAgICAgICAgICAgICAgbWFza1Njb3BlLmNhbGwodGhpcywge1xuICAgICAgICAgICAgICAgICAgICBhY3Rpb246IFwiZ2V0bWV0YWRhdGFcIlxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGlzVmFsaWQ6IGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMubWFza3NldCA9IHRoaXMubWFza3NldCB8fCBnZW5lcmF0ZU1hc2tTZXQodGhpcy5vcHRzLCB0aGlzLm5vTWFza3NDYWNoZSksIFxuICAgICAgICAgICAgICAgIG1hc2tTY29wZS5jYWxsKHRoaXMsIHtcbiAgICAgICAgICAgICAgICAgICAgYWN0aW9uOiBcImlzVmFsaWRcIixcbiAgICAgICAgICAgICAgICAgICAgdmFsdWU6IHZhbHVlXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZm9ybWF0OiBmdW5jdGlvbih2YWx1ZSwgbWV0YWRhdGEpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5tYXNrc2V0ID0gdGhpcy5tYXNrc2V0IHx8IGdlbmVyYXRlTWFza1NldCh0aGlzLm9wdHMsIHRoaXMubm9NYXNrc0NhY2hlKSwgXG4gICAgICAgICAgICAgICAgbWFza1Njb3BlLmNhbGwodGhpcywge1xuICAgICAgICAgICAgICAgICAgICBhY3Rpb246IFwiZm9ybWF0XCIsXG4gICAgICAgICAgICAgICAgICAgIHZhbHVlOiB2YWx1ZSxcbiAgICAgICAgICAgICAgICAgICAgbWV0YWRhdGE6IG1ldGFkYXRhXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgYW5hbHlzZU1hc2s6IGZ1bmN0aW9uKG1hc2ssIHJlZ2V4TWFzaywgb3B0cykge1xuICAgICAgICAgICAgICAgIGZ1bmN0aW9uIE1hc2tUb2tlbihpc0dyb3VwLCBpc09wdGlvbmFsLCBpc1F1YW50aWZpZXIsIGlzQWx0ZXJuYXRvcikge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLm1hdGNoZXMgPSBbXSwgdGhpcy5vcGVuR3JvdXAgPSBpc0dyb3VwIHx8ICExLCB0aGlzLmFsdGVybmF0b3JHcm91cCA9ICExLCB0aGlzLmlzR3JvdXAgPSBpc0dyb3VwIHx8ICExLCBcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5pc09wdGlvbmFsID0gaXNPcHRpb25hbCB8fCAhMSwgdGhpcy5pc1F1YW50aWZpZXIgPSBpc1F1YW50aWZpZXIgfHwgITEsIHRoaXMuaXNBbHRlcm5hdG9yID0gaXNBbHRlcm5hdG9yIHx8ICExLCBcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5xdWFudGlmaWVyID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWluOiAxLFxuICAgICAgICAgICAgICAgICAgICAgICAgbWF4OiAxXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGZ1bmN0aW9uIGluc2VydFRlc3REZWZpbml0aW9uKG10b2tlbiwgZWxlbWVudCwgcG9zaXRpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbiAhPT0gdW5kZWZpbmVkID8gcG9zaXRpb24gOiBtdG9rZW4ubWF0Y2hlcy5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwcmV2TWF0Y2ggPSBtdG9rZW4ubWF0Y2hlc1twb3NpdGlvbiAtIDFdO1xuICAgICAgICAgICAgICAgICAgICBpZiAocmVnZXhNYXNrKSAwID09PSBlbGVtZW50LmluZGV4T2YoXCJbXCIpIHx8IGVzY2FwZWQgJiYgL1xcXFxkfFxcXFxzfFxcXFx3XS9pLnRlc3QoZWxlbWVudCkgfHwgXCIuXCIgPT09IGVsZW1lbnQgPyBtdG9rZW4ubWF0Y2hlcy5zcGxpY2UocG9zaXRpb24rKywgMCwge1xuICAgICAgICAgICAgICAgICAgICAgICAgZm46IG5ldyBSZWdFeHAoZWxlbWVudCwgb3B0cy5jYXNpbmcgPyBcImlcIiA6IFwiXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgY2FyZGluYWxpdHk6IDEsXG4gICAgICAgICAgICAgICAgICAgICAgICBvcHRpb25hbGl0eTogbXRva2VuLmlzT3B0aW9uYWwsXG4gICAgICAgICAgICAgICAgICAgICAgICBuZXdCbG9ja01hcmtlcjogcHJldk1hdGNoID09PSB1bmRlZmluZWQgfHwgcHJldk1hdGNoLmRlZiAhPT0gZWxlbWVudCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2luZzogbnVsbCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGRlZjogZWxlbWVudCxcbiAgICAgICAgICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyOiB1bmRlZmluZWQsXG4gICAgICAgICAgICAgICAgICAgICAgICBuYXRpdmVEZWY6IGVsZW1lbnRcbiAgICAgICAgICAgICAgICAgICAgfSkgOiAoZXNjYXBlZCAmJiAoZWxlbWVudCA9IGVsZW1lbnRbZWxlbWVudC5sZW5ndGggLSAxXSksICQuZWFjaChlbGVtZW50LnNwbGl0KFwiXCIpLCBmdW5jdGlvbihuZHgsIGxtbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHByZXZNYXRjaCA9IG10b2tlbi5tYXRjaGVzW3Bvc2l0aW9uIC0gMV0sIG10b2tlbi5tYXRjaGVzLnNwbGljZShwb3NpdGlvbisrLCAwLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm46IG51bGwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FyZGluYWxpdHk6IDAsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb3B0aW9uYWxpdHk6IG10b2tlbi5pc09wdGlvbmFsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0Jsb2NrTWFya2VyOiBwcmV2TWF0Y2ggPT09IHVuZGVmaW5lZCB8fCBwcmV2TWF0Y2guZGVmICE9PSBsbW50ICYmIG51bGwgIT09IHByZXZNYXRjaC5mbixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNpbmc6IG51bGwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVmOiBvcHRzLnN0YXRpY0RlZmluaXRpb25TeW1ib2wgfHwgbG1udCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwbGFjZWhvbGRlcjogb3B0cy5zdGF0aWNEZWZpbml0aW9uU3ltYm9sICE9PSB1bmRlZmluZWQgPyBsbW50IDogdW5kZWZpbmVkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hdGl2ZURlZjogbG1udFxuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH0pKSwgZXNjYXBlZCA9ICExOyBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBtYXNrZGVmID0gKG9wdHMuZGVmaW5pdGlvbnMgPyBvcHRzLmRlZmluaXRpb25zW2VsZW1lbnRdIDogdW5kZWZpbmVkKSB8fCBJbnB1dG1hc2sucHJvdG90eXBlLmRlZmluaXRpb25zW2VsZW1lbnRdO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG1hc2tkZWYgJiYgIWVzY2FwZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBwcmV2YWxpZGF0b3JzID0gbWFza2RlZi5wcmV2YWxpZGF0b3IsIHByZXZhbGlkYXRvcnNMID0gcHJldmFsaWRhdG9ycyA/IHByZXZhbGlkYXRvcnMubGVuZ3RoIDogMCwgaSA9IDE7IGkgPCBtYXNrZGVmLmNhcmRpbmFsaXR5OyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHByZXZhbGlkYXRvciA9IHByZXZhbGlkYXRvcnNMID49IGkgPyBwcmV2YWxpZGF0b3JzW2kgLSAxXSA6IFtdLCB2YWxpZGF0b3IgPSBwcmV2YWxpZGF0b3IudmFsaWRhdG9yLCBjYXJkaW5hbGl0eSA9IHByZXZhbGlkYXRvci5jYXJkaW5hbGl0eTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbXRva2VuLm1hdGNoZXMuc3BsaWNlKHBvc2l0aW9uKyssIDAsIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZuOiB2YWxpZGF0b3IgPyBcInN0cmluZ1wiID09IHR5cGVvZiB2YWxpZGF0b3IgPyBuZXcgUmVnRXhwKHZhbGlkYXRvciwgb3B0cy5jYXNpbmcgPyBcImlcIiA6IFwiXCIpIDogbmV3IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMudGVzdCA9IHZhbGlkYXRvcjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0oKSA6IG5ldyBSZWdFeHAoXCIuXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FyZGluYWxpdHk6IGNhcmRpbmFsaXR5IHx8IDEsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcHRpb25hbGl0eTogbXRva2VuLmlzT3B0aW9uYWwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdCbG9ja01hcmtlcjogcHJldk1hdGNoID09PSB1bmRlZmluZWQgfHwgcHJldk1hdGNoLmRlZiAhPT0gKG1hc2tkZWYuZGVmaW5pdGlvblN5bWJvbCB8fCBlbGVtZW50KSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2luZzogbWFza2RlZi5jYXNpbmcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWY6IG1hc2tkZWYuZGVmaW5pdGlvblN5bWJvbCB8fCBlbGVtZW50LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI6IG1hc2tkZWYucGxhY2Vob2xkZXIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYXRpdmVEZWY6IGVsZW1lbnRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSksIHByZXZNYXRjaCA9IG10b2tlbi5tYXRjaGVzW3Bvc2l0aW9uIC0gMV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG10b2tlbi5tYXRjaGVzLnNwbGljZShwb3NpdGlvbisrLCAwLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZuOiBtYXNrZGVmLnZhbGlkYXRvciA/IFwic3RyaW5nXCIgPT0gdHlwZW9mIG1hc2tkZWYudmFsaWRhdG9yID8gbmV3IFJlZ0V4cChtYXNrZGVmLnZhbGlkYXRvciwgb3B0cy5jYXNpbmcgPyBcImlcIiA6IFwiXCIpIDogbmV3IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy50ZXN0ID0gbWFza2RlZi52YWxpZGF0b3I7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0oKSA6IG5ldyBSZWdFeHAoXCIuXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXJkaW5hbGl0eTogbWFza2RlZi5jYXJkaW5hbGl0eSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3B0aW9uYWxpdHk6IG10b2tlbi5pc09wdGlvbmFsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdCbG9ja01hcmtlcjogcHJldk1hdGNoID09PSB1bmRlZmluZWQgfHwgcHJldk1hdGNoLmRlZiAhPT0gKG1hc2tkZWYuZGVmaW5pdGlvblN5bWJvbCB8fCBlbGVtZW50KSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzaW5nOiBtYXNrZGVmLmNhc2luZyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVmOiBtYXNrZGVmLmRlZmluaXRpb25TeW1ib2wgfHwgZWxlbWVudCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI6IG1hc2tkZWYucGxhY2Vob2xkZXIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hdGl2ZURlZjogZWxlbWVudFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIG10b2tlbi5tYXRjaGVzLnNwbGljZShwb3NpdGlvbisrLCAwLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm46IG51bGwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FyZGluYWxpdHk6IDAsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb3B0aW9uYWxpdHk6IG10b2tlbi5pc09wdGlvbmFsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0Jsb2NrTWFya2VyOiBwcmV2TWF0Y2ggPT09IHVuZGVmaW5lZCB8fCBwcmV2TWF0Y2guZGVmICE9PSBlbGVtZW50ICYmIG51bGwgIT09IHByZXZNYXRjaC5mbixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNpbmc6IG51bGwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVmOiBvcHRzLnN0YXRpY0RlZmluaXRpb25TeW1ib2wgfHwgZWxlbWVudCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwbGFjZWhvbGRlcjogb3B0cy5zdGF0aWNEZWZpbml0aW9uU3ltYm9sICE9PSB1bmRlZmluZWQgPyBlbGVtZW50IDogdW5kZWZpbmVkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hdGl2ZURlZjogZWxlbWVudFxuICAgICAgICAgICAgICAgICAgICAgICAgfSksIGVzY2FwZWQgPSAhMTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBmdW5jdGlvbiB2ZXJpZnlHcm91cE1hcmtlcihtYXNrVG9rZW4pIHtcbiAgICAgICAgICAgICAgICAgICAgbWFza1Rva2VuICYmIG1hc2tUb2tlbi5tYXRjaGVzICYmICQuZWFjaChtYXNrVG9rZW4ubWF0Y2hlcywgZnVuY3Rpb24obmR4LCB0b2tlbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG5leHRUb2tlbiA9IG1hc2tUb2tlbi5tYXRjaGVzW25keCArIDFdO1xuICAgICAgICAgICAgICAgICAgICAgICAgKG5leHRUb2tlbiA9PT0gdW5kZWZpbmVkIHx8IG5leHRUb2tlbi5tYXRjaGVzID09PSB1bmRlZmluZWQgfHwgITEgPT09IG5leHRUb2tlbi5pc1F1YW50aWZpZXIpICYmIHRva2VuICYmIHRva2VuLmlzR3JvdXAgJiYgKHRva2VuLmlzR3JvdXAgPSAhMSwgXG4gICAgICAgICAgICAgICAgICAgICAgICByZWdleE1hc2sgfHwgKGluc2VydFRlc3REZWZpbml0aW9uKHRva2VuLCBvcHRzLmdyb3VwbWFya2VyLnN0YXJ0LCAwKSwgITAgIT09IHRva2VuLm9wZW5Hcm91cCAmJiBpbnNlcnRUZXN0RGVmaW5pdGlvbih0b2tlbiwgb3B0cy5ncm91cG1hcmtlci5lbmQpKSksIFxuICAgICAgICAgICAgICAgICAgICAgICAgdmVyaWZ5R3JvdXBNYXJrZXIodG9rZW4pO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZnVuY3Rpb24gZGVmYXVsdENhc2UoKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChvcGVuZW5pbmdzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjdXJyZW50T3BlbmluZ1Rva2VuID0gb3BlbmVuaW5nc1tvcGVuZW5pbmdzLmxlbmd0aCAtIDFdLCBpbnNlcnRUZXN0RGVmaW5pdGlvbihjdXJyZW50T3BlbmluZ1Rva2VuLCBtKSwgXG4gICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50T3BlbmluZ1Rva2VuLmlzQWx0ZXJuYXRvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFsdGVybmF0b3IgPSBvcGVuZW5pbmdzLnBvcCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIG1uZHggPSAwOyBtbmR4IDwgYWx0ZXJuYXRvci5tYXRjaGVzLmxlbmd0aDsgbW5keCsrKSBhbHRlcm5hdG9yLm1hdGNoZXNbbW5keF0uaXNHcm91cCA9ICExO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9wZW5lbmluZ3MubGVuZ3RoID4gMCA/IChjdXJyZW50T3BlbmluZ1Rva2VuID0gb3BlbmVuaW5nc1tvcGVuZW5pbmdzLmxlbmd0aCAtIDFdKS5tYXRjaGVzLnB1c2goYWx0ZXJuYXRvcikgOiBjdXJyZW50VG9rZW4ubWF0Y2hlcy5wdXNoKGFsdGVybmF0b3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaW5zZXJ0VGVzdERlZmluaXRpb24oY3VycmVudFRva2VuLCBtKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZnVuY3Rpb24gcmV2ZXJzZVRva2VucyhtYXNrVG9rZW4pIHtcbiAgICAgICAgICAgICAgICAgICAgbWFza1Rva2VuLm1hdGNoZXMgPSBtYXNrVG9rZW4ubWF0Y2hlcy5yZXZlcnNlKCk7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIG1hdGNoIGluIG1hc2tUb2tlbi5tYXRjaGVzKSBpZiAobWFza1Rva2VuLm1hdGNoZXMuaGFzT3duUHJvcGVydHkobWF0Y2gpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgaW50TWF0Y2ggPSBwYXJzZUludChtYXRjaCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobWFza1Rva2VuLm1hdGNoZXNbbWF0Y2hdLmlzUXVhbnRpZmllciAmJiBtYXNrVG9rZW4ubWF0Y2hlc1tpbnRNYXRjaCArIDFdICYmIG1hc2tUb2tlbi5tYXRjaGVzW2ludE1hdGNoICsgMV0uaXNHcm91cCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBxdCA9IG1hc2tUb2tlbi5tYXRjaGVzW21hdGNoXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXNrVG9rZW4ubWF0Y2hlcy5zcGxpY2UobWF0Y2gsIDEpLCBtYXNrVG9rZW4ubWF0Y2hlcy5zcGxpY2UoaW50TWF0Y2ggKyAxLCAwLCBxdCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBtYXNrVG9rZW4ubWF0Y2hlc1ttYXRjaF0ubWF0Y2hlcyAhPT0gdW5kZWZpbmVkID8gbWFza1Rva2VuLm1hdGNoZXNbbWF0Y2hdID0gcmV2ZXJzZVRva2VucyhtYXNrVG9rZW4ubWF0Y2hlc1ttYXRjaF0pIDogbWFza1Rva2VuLm1hdGNoZXNbbWF0Y2hdID0gZnVuY3Rpb24oc3QpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gc3QgPT09IG9wdHMub3B0aW9uYWxtYXJrZXIuc3RhcnQgPyBzdCA9IG9wdHMub3B0aW9uYWxtYXJrZXIuZW5kIDogc3QgPT09IG9wdHMub3B0aW9uYWxtYXJrZXIuZW5kID8gc3QgPSBvcHRzLm9wdGlvbmFsbWFya2VyLnN0YXJ0IDogc3QgPT09IG9wdHMuZ3JvdXBtYXJrZXIuc3RhcnQgPyBzdCA9IG9wdHMuZ3JvdXBtYXJrZXIuZW5kIDogc3QgPT09IG9wdHMuZ3JvdXBtYXJrZXIuZW5kICYmIChzdCA9IG9wdHMuZ3JvdXBtYXJrZXIuc3RhcnQpLCBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0obWFza1Rva2VuLm1hdGNoZXNbbWF0Y2hdKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbWFza1Rva2VuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgbWF0Y2gsIG0sIG9wZW5pbmdUb2tlbiwgY3VycmVudE9wZW5pbmdUb2tlbiwgYWx0ZXJuYXRvciwgbGFzdE1hdGNoLCBncm91cFRva2VuLCB0b2tlbml6ZXIgPSAvKD86Wz8qK118XFx7WzAtOVxcK1xcKl0rKD86LFswLTlcXCtcXCpdKik/XFx9KXxbXi4/KiteJHtbXSgpfFxcXFxdK3wuL2csIHJlZ2V4VG9rZW5pemVyID0gL1xcW1xcXj9dPyg/OlteXFxcXFxcXV0rfFxcXFxbXFxTXFxzXT8pKl0/fFxcXFwoPzowKD86WzAtM11bMC03XXswLDJ9fFs0LTddWzAtN10/KT98WzEtOV1bMC05XSp8eFswLTlBLUZhLWZdezJ9fHVbMC05QS1GYS1mXXs0fXxjW0EtWmEtel18W1xcU1xcc10/KXxcXCgoPzpcXD9bOj0hXT8pP3woPzpbPyorXXxcXHtbMC05XSsoPzosWzAtOV0qKT9cXH0pXFw/P3xbXi4/KiteJHtbKCl8XFxcXF0rfC4vZywgZXNjYXBlZCA9ICExLCBjdXJyZW50VG9rZW4gPSBuZXcgTWFza1Rva2VuKCksIG9wZW5lbmluZ3MgPSBbXSwgbWFza1Rva2VucyA9IFtdO1xuICAgICAgICAgICAgICAgIGZvciAocmVnZXhNYXNrICYmIChvcHRzLm9wdGlvbmFsbWFya2VyLnN0YXJ0ID0gdW5kZWZpbmVkLCBvcHRzLm9wdGlvbmFsbWFya2VyLmVuZCA9IHVuZGVmaW5lZCk7IG1hdGNoID0gcmVnZXhNYXNrID8gcmVnZXhUb2tlbml6ZXIuZXhlYyhtYXNrKSA6IHRva2VuaXplci5leGVjKG1hc2spOyApIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG0gPSBtYXRjaFswXSwgcmVnZXhNYXNrKSBzd2l0Y2ggKG0uY2hhckF0KDApKSB7XG4gICAgICAgICAgICAgICAgICAgICAgY2FzZSBcIj9cIjpcbiAgICAgICAgICAgICAgICAgICAgICAgIG0gPSBcInswLDF9XCI7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgICAgICAgICAgIGNhc2UgXCIrXCI6XG4gICAgICAgICAgICAgICAgICAgICAgY2FzZSBcIipcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgIG0gPSBcIntcIiArIG0gKyBcIn1cIjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoZXNjYXBlZCkgZGVmYXVsdENhc2UoKTsgZWxzZSBzd2l0Y2ggKG0uY2hhckF0KDApKSB7XG4gICAgICAgICAgICAgICAgICAgICAgY2FzZSBvcHRzLmVzY2FwZUNoYXI6XG4gICAgICAgICAgICAgICAgICAgICAgICBlc2NhcGVkID0gITAsIHJlZ2V4TWFzayAmJiBkZWZhdWx0Q2FzZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgICAgICAgICAgICBjYXNlIG9wdHMub3B0aW9uYWxtYXJrZXIuZW5kOlxuICAgICAgICAgICAgICAgICAgICAgIGNhc2Ugb3B0cy5ncm91cG1hcmtlci5lbmQ6XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAob3BlbmluZ1Rva2VuID0gb3BlbmVuaW5ncy5wb3AoKSwgb3BlbmluZ1Rva2VuLm9wZW5Hcm91cCA9ICExLCBvcGVuaW5nVG9rZW4gIT09IHVuZGVmaW5lZCkgaWYgKG9wZW5lbmluZ3MubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICgoY3VycmVudE9wZW5pbmdUb2tlbiA9IG9wZW5lbmluZ3Nbb3BlbmVuaW5ncy5sZW5ndGggLSAxXSkubWF0Y2hlcy5wdXNoKG9wZW5pbmdUb2tlbiksIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnRPcGVuaW5nVG9rZW4uaXNBbHRlcm5hdG9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFsdGVybmF0b3IgPSBvcGVuZW5pbmdzLnBvcCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBtbmR4ID0gMDsgbW5keCA8IGFsdGVybmF0b3IubWF0Y2hlcy5sZW5ndGg7IG1uZHgrKykgYWx0ZXJuYXRvci5tYXRjaGVzW21uZHhdLmlzR3JvdXAgPSAhMSwgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFsdGVybmF0b3IubWF0Y2hlc1ttbmR4XS5hbHRlcm5hdG9yR3JvdXAgPSAhMTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3BlbmVuaW5ncy5sZW5ndGggPiAwID8gKGN1cnJlbnRPcGVuaW5nVG9rZW4gPSBvcGVuZW5pbmdzW29wZW5lbmluZ3MubGVuZ3RoIC0gMV0pLm1hdGNoZXMucHVzaChhbHRlcm5hdG9yKSA6IGN1cnJlbnRUb2tlbi5tYXRjaGVzLnB1c2goYWx0ZXJuYXRvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGN1cnJlbnRUb2tlbi5tYXRjaGVzLnB1c2gob3BlbmluZ1Rva2VuKTsgZWxzZSBkZWZhdWx0Q2FzZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgICAgICAgICAgICBjYXNlIG9wdHMub3B0aW9uYWxtYXJrZXIuc3RhcnQ6XG4gICAgICAgICAgICAgICAgICAgICAgICBvcGVuZW5pbmdzLnB1c2gobmV3IE1hc2tUb2tlbighMSwgITApKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICAgICAgICAgICAgY2FzZSBvcHRzLmdyb3VwbWFya2VyLnN0YXJ0OlxuICAgICAgICAgICAgICAgICAgICAgICAgb3BlbmVuaW5ncy5wdXNoKG5ldyBNYXNrVG9rZW4oITApKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICAgICAgICAgICAgY2FzZSBvcHRzLnF1YW50aWZpZXJtYXJrZXIuc3RhcnQ6XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgcXVhbnRpZmllciA9IG5ldyBNYXNrVG9rZW4oITEsICExLCAhMCksIG1xID0gKG0gPSBtLnJlcGxhY2UoL1t7fV0vZywgXCJcIikpLnNwbGl0KFwiLFwiKSwgbXEwID0gaXNOYU4obXFbMF0pID8gbXFbMF0gOiBwYXJzZUludChtcVswXSksIG1xMSA9IDEgPT09IG1xLmxlbmd0aCA/IG1xMCA6IGlzTmFOKG1xWzFdKSA/IG1xWzFdIDogcGFyc2VJbnQobXFbMV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKFwiKlwiICE9PSBtcTEgJiYgXCIrXCIgIT09IG1xMSB8fCAobXEwID0gXCIqXCIgPT09IG1xMSA/IDAgOiAxKSwgcXVhbnRpZmllci5xdWFudGlmaWVyID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbjogbXEwLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heDogbXExXG4gICAgICAgICAgICAgICAgICAgICAgICB9LCBvcGVuZW5pbmdzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgbWF0Y2hlcyA9IG9wZW5lbmluZ3Nbb3BlbmVuaW5ncy5sZW5ndGggLSAxXS5tYXRjaGVzO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIChtYXRjaCA9IG1hdGNoZXMucG9wKCkpLmlzR3JvdXAgfHwgKChncm91cFRva2VuID0gbmV3IE1hc2tUb2tlbighMCkpLm1hdGNoZXMucHVzaChtYXRjaCksIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoID0gZ3JvdXBUb2tlbiksIG1hdGNoZXMucHVzaChtYXRjaCksIG1hdGNoZXMucHVzaChxdWFudGlmaWVyKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSAobWF0Y2ggPSBjdXJyZW50VG9rZW4ubWF0Y2hlcy5wb3AoKSkuaXNHcm91cCB8fCAocmVnZXhNYXNrICYmIG51bGwgPT09IG1hdGNoLmZuICYmIFwiLlwiID09PSBtYXRjaC5kZWYgJiYgKG1hdGNoLmZuID0gbmV3IFJlZ0V4cChtYXRjaC5kZWYsIG9wdHMuY2FzaW5nID8gXCJpXCIgOiBcIlwiKSksIFxuICAgICAgICAgICAgICAgICAgICAgICAgKGdyb3VwVG9rZW4gPSBuZXcgTWFza1Rva2VuKCEwKSkubWF0Y2hlcy5wdXNoKG1hdGNoKSwgbWF0Y2ggPSBncm91cFRva2VuKSwgY3VycmVudFRva2VuLm1hdGNoZXMucHVzaChtYXRjaCksIFxuICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudFRva2VuLm1hdGNoZXMucHVzaChxdWFudGlmaWVyKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICAgICAgICAgICAgY2FzZSBvcHRzLmFsdGVybmF0b3JtYXJrZXI6XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAob3BlbmVuaW5ncy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHN1YlRva2VuID0gKGN1cnJlbnRPcGVuaW5nVG9rZW4gPSBvcGVuZW5pbmdzW29wZW5lbmluZ3MubGVuZ3RoIC0gMV0pLm1hdGNoZXNbY3VycmVudE9wZW5pbmdUb2tlbi5tYXRjaGVzLmxlbmd0aCAtIDFdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RNYXRjaCA9IGN1cnJlbnRPcGVuaW5nVG9rZW4ub3Blbkdyb3VwICYmIChzdWJUb2tlbi5tYXRjaGVzID09PSB1bmRlZmluZWQgfHwgITEgPT09IHN1YlRva2VuLmlzR3JvdXAgJiYgITEgPT09IHN1YlRva2VuLmlzQWx0ZXJuYXRvcikgPyBvcGVuZW5pbmdzLnBvcCgpIDogY3VycmVudE9wZW5pbmdUb2tlbi5tYXRjaGVzLnBvcCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGxhc3RNYXRjaCA9IGN1cnJlbnRUb2tlbi5tYXRjaGVzLnBvcCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGxhc3RNYXRjaC5pc0FsdGVybmF0b3IpIG9wZW5lbmluZ3MucHVzaChsYXN0TWF0Y2gpOyBlbHNlIGlmIChsYXN0TWF0Y2guYWx0ZXJuYXRvckdyb3VwID8gKGFsdGVybmF0b3IgPSBvcGVuZW5pbmdzLnBvcCgpLCBcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RNYXRjaC5hbHRlcm5hdG9yR3JvdXAgPSAhMSkgOiBhbHRlcm5hdG9yID0gbmV3IE1hc2tUb2tlbighMSwgITEsICExLCAhMCksIGFsdGVybmF0b3IubWF0Y2hlcy5wdXNoKGxhc3RNYXRjaCksIFxuICAgICAgICAgICAgICAgICAgICAgICAgb3BlbmVuaW5ncy5wdXNoKGFsdGVybmF0b3IpLCBsYXN0TWF0Y2gub3Blbkdyb3VwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFzdE1hdGNoLm9wZW5Hcm91cCA9ICExO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBhbHRlcm5hdG9yR3JvdXAgPSBuZXcgTWFza1Rva2VuKCEwKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbHRlcm5hdG9yR3JvdXAuYWx0ZXJuYXRvckdyb3VwID0gITAsIG9wZW5lbmluZ3MucHVzaChhbHRlcm5hdG9yR3JvdXApO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICAgICAgZGVmYXVsdENhc2UoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBmb3IgKDtvcGVuZW5pbmdzLmxlbmd0aCA+IDA7ICkgb3BlbmluZ1Rva2VuID0gb3BlbmVuaW5ncy5wb3AoKSwgY3VycmVudFRva2VuLm1hdGNoZXMucHVzaChvcGVuaW5nVG9rZW4pO1xuICAgICAgICAgICAgICAgIHJldHVybiBjdXJyZW50VG9rZW4ubWF0Y2hlcy5sZW5ndGggPiAwICYmICh2ZXJpZnlHcm91cE1hcmtlcihjdXJyZW50VG9rZW4pLCBtYXNrVG9rZW5zLnB1c2goY3VycmVudFRva2VuKSksIFxuICAgICAgICAgICAgICAgIChvcHRzLm51bWVyaWNJbnB1dCB8fCBvcHRzLmlzUlRMKSAmJiByZXZlcnNlVG9rZW5zKG1hc2tUb2tlbnNbMF0pLCBtYXNrVG9rZW5zO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCBJbnB1dG1hc2suZXh0ZW5kRGVmYXVsdHMgPSBmdW5jdGlvbihvcHRpb25zKSB7XG4gICAgICAgICAgICAkLmV4dGVuZCghMCwgSW5wdXRtYXNrLnByb3RvdHlwZS5kZWZhdWx0cywgb3B0aW9ucyk7XG4gICAgICAgIH0sIElucHV0bWFzay5leHRlbmREZWZpbml0aW9ucyA9IGZ1bmN0aW9uKGRlZmluaXRpb24pIHtcbiAgICAgICAgICAgICQuZXh0ZW5kKCEwLCBJbnB1dG1hc2sucHJvdG90eXBlLmRlZmluaXRpb25zLCBkZWZpbml0aW9uKTtcbiAgICAgICAgfSwgSW5wdXRtYXNrLmV4dGVuZEFsaWFzZXMgPSBmdW5jdGlvbihhbGlhcykge1xuICAgICAgICAgICAgJC5leHRlbmQoITAsIElucHV0bWFzay5wcm90b3R5cGUuYWxpYXNlcywgYWxpYXMpO1xuICAgICAgICB9LCBJbnB1dG1hc2suZm9ybWF0ID0gZnVuY3Rpb24odmFsdWUsIG9wdGlvbnMsIG1ldGFkYXRhKSB7XG4gICAgICAgICAgICByZXR1cm4gSW5wdXRtYXNrKG9wdGlvbnMpLmZvcm1hdCh2YWx1ZSwgbWV0YWRhdGEpO1xuICAgICAgICB9LCBJbnB1dG1hc2sudW5tYXNrID0gZnVuY3Rpb24odmFsdWUsIG9wdGlvbnMpIHtcbiAgICAgICAgICAgIHJldHVybiBJbnB1dG1hc2sob3B0aW9ucykudW5tYXNrZWR2YWx1ZSh2YWx1ZSk7XG4gICAgICAgIH0sIElucHV0bWFzay5pc1ZhbGlkID0gZnVuY3Rpb24odmFsdWUsIG9wdGlvbnMpIHtcbiAgICAgICAgICAgIHJldHVybiBJbnB1dG1hc2sob3B0aW9ucykuaXNWYWxpZCh2YWx1ZSk7XG4gICAgICAgIH0sIElucHV0bWFzay5yZW1vdmUgPSBmdW5jdGlvbihlbGVtcykge1xuICAgICAgICAgICAgJC5lYWNoKGVsZW1zLCBmdW5jdGlvbihuZHgsIGVsKSB7XG4gICAgICAgICAgICAgICAgZWwuaW5wdXRtYXNrICYmIGVsLmlucHV0bWFzay5yZW1vdmUoKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9LCBJbnB1dG1hc2suZXNjYXBlUmVnZXggPSBmdW5jdGlvbihzdHIpIHtcbiAgICAgICAgICAgIHZhciBzcGVjaWFscyA9IFsgXCIvXCIsIFwiLlwiLCBcIipcIiwgXCIrXCIsIFwiP1wiLCBcInxcIiwgXCIoXCIsIFwiKVwiLCBcIltcIiwgXCJdXCIsIFwie1wiLCBcIn1cIiwgXCJcXFxcXCIsIFwiJFwiLCBcIl5cIiBdO1xuICAgICAgICAgICAgcmV0dXJuIHN0ci5yZXBsYWNlKG5ldyBSZWdFeHAoXCIoXFxcXFwiICsgc3BlY2lhbHMuam9pbihcInxcXFxcXCIpICsgXCIpXCIsIFwiZ2ltXCIpLCBcIlxcXFwkMVwiKTtcbiAgICAgICAgfSwgSW5wdXRtYXNrLmtleUNvZGUgPSB7XG4gICAgICAgICAgICBBTFQ6IDE4LFxuICAgICAgICAgICAgQkFDS1NQQUNFOiA4LFxuICAgICAgICAgICAgQkFDS1NQQUNFX1NBRkFSSTogMTI3LFxuICAgICAgICAgICAgQ0FQU19MT0NLOiAyMCxcbiAgICAgICAgICAgIENPTU1BOiAxODgsXG4gICAgICAgICAgICBDT01NQU5EOiA5MSxcbiAgICAgICAgICAgIENPTU1BTkRfTEVGVDogOTEsXG4gICAgICAgICAgICBDT01NQU5EX1JJR0hUOiA5MyxcbiAgICAgICAgICAgIENPTlRST0w6IDE3LFxuICAgICAgICAgICAgREVMRVRFOiA0NixcbiAgICAgICAgICAgIERPV046IDQwLFxuICAgICAgICAgICAgRU5EOiAzNSxcbiAgICAgICAgICAgIEVOVEVSOiAxMyxcbiAgICAgICAgICAgIEVTQ0FQRTogMjcsXG4gICAgICAgICAgICBIT01FOiAzNixcbiAgICAgICAgICAgIElOU0VSVDogNDUsXG4gICAgICAgICAgICBMRUZUOiAzNyxcbiAgICAgICAgICAgIE1FTlU6IDkzLFxuICAgICAgICAgICAgTlVNUEFEX0FERDogMTA3LFxuICAgICAgICAgICAgTlVNUEFEX0RFQ0lNQUw6IDExMCxcbiAgICAgICAgICAgIE5VTVBBRF9ESVZJREU6IDExMSxcbiAgICAgICAgICAgIE5VTVBBRF9FTlRFUjogMTA4LFxuICAgICAgICAgICAgTlVNUEFEX01VTFRJUExZOiAxMDYsXG4gICAgICAgICAgICBOVU1QQURfU1VCVFJBQ1Q6IDEwOSxcbiAgICAgICAgICAgIFBBR0VfRE9XTjogMzQsXG4gICAgICAgICAgICBQQUdFX1VQOiAzMyxcbiAgICAgICAgICAgIFBFUklPRDogMTkwLFxuICAgICAgICAgICAgUklHSFQ6IDM5LFxuICAgICAgICAgICAgU0hJRlQ6IDE2LFxuICAgICAgICAgICAgU1BBQ0U6IDMyLFxuICAgICAgICAgICAgVEFCOiA5LFxuICAgICAgICAgICAgVVA6IDM4LFxuICAgICAgICAgICAgV0lORE9XUzogOTEsXG4gICAgICAgICAgICBYOiA4OFxuICAgICAgICB9LCBJbnB1dG1hc2s7XG4gICAgfSk7XG59LCBmdW5jdGlvbihtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICBtb2R1bGUuZXhwb3J0cyA9IGpRdWVyeTtcbn0sIGZ1bmN0aW9uKG1vZHVsZSwgZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykge1xuICAgIFwidXNlIHN0cmljdFwiO1xuICAgIGZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7XG4gICAgICAgIHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7XG4gICAgICAgICAgICBkZWZhdWx0OiBvYmpcbiAgICAgICAgfTtcbiAgICB9XG4gICAgX193ZWJwYWNrX3JlcXVpcmVfXyg0KSwgX193ZWJwYWNrX3JlcXVpcmVfXyg5KSwgX193ZWJwYWNrX3JlcXVpcmVfXygxMiksIF9fd2VicGFja19yZXF1aXJlX18oMTMpLCBcbiAgICBfX3dlYnBhY2tfcmVxdWlyZV9fKDE0KSwgX193ZWJwYWNrX3JlcXVpcmVfXygxNSk7XG4gICAgdmFyIF9pbnB1dG1hc2syID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfX3dlYnBhY2tfcmVxdWlyZV9fKDEpKSwgX2lucHV0bWFzazQgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9fd2VicGFja19yZXF1aXJlX18oMCkpLCBfanF1ZXJ5MiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX193ZWJwYWNrX3JlcXVpcmVfXygyKSk7XG4gICAgX2lucHV0bWFzazQuZGVmYXVsdCA9PT0gX2pxdWVyeTIuZGVmYXVsdCAmJiBfX3dlYnBhY2tfcmVxdWlyZV9fKDE2KSwgd2luZG93LklucHV0bWFzayA9IF9pbnB1dG1hc2syLmRlZmF1bHQ7XG59LCBmdW5jdGlvbihtb2R1bGUsIGV4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pIHtcbiAgICB2YXIgY29udGVudCA9IF9fd2VicGFja19yZXF1aXJlX18oNSk7XG4gICAgXCJzdHJpbmdcIiA9PSB0eXBlb2YgY29udGVudCAmJiAoY29udGVudCA9IFsgWyBtb2R1bGUuaSwgY29udGVudCwgXCJcIiBdIF0pO1xuICAgIHZhciBvcHRpb25zID0ge1xuICAgICAgICBobXI6ICEwXG4gICAgfTtcbiAgICBvcHRpb25zLnRyYW5zZm9ybSA9IHZvaWQgMDtcbiAgICBfX3dlYnBhY2tfcmVxdWlyZV9fKDcpKGNvbnRlbnQsIG9wdGlvbnMpO1xuICAgIGNvbnRlbnQubG9jYWxzICYmIChtb2R1bGUuZXhwb3J0cyA9IGNvbnRlbnQubG9jYWxzKTtcbn0sIGZ1bmN0aW9uKG1vZHVsZSwgZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykge1xuICAgIChtb2R1bGUuZXhwb3J0cyA9IF9fd2VicGFja19yZXF1aXJlX18oNikodm9pZCAwKSkucHVzaChbIG1vZHVsZS5pLCBcInNwYW4uaW0tY2FyZXQge1xcclxcbiAgICAtd2Via2l0LWFuaW1hdGlvbjogMXMgYmxpbmsgc3RlcC1lbmQgaW5maW5pdGU7XFxyXFxuICAgIGFuaW1hdGlvbjogMXMgYmxpbmsgc3RlcC1lbmQgaW5maW5pdGU7XFxyXFxufVxcclxcblxcclxcbkBrZXlmcmFtZXMgYmxpbmsge1xcclxcbiAgICBmcm9tLCB0byB7XFxyXFxuICAgICAgICBib3JkZXItcmlnaHQtY29sb3I6IGJsYWNrO1xcclxcbiAgICB9XFxyXFxuICAgIDUwJSB7XFxyXFxuICAgICAgICBib3JkZXItcmlnaHQtY29sb3I6IHRyYW5zcGFyZW50O1xcclxcbiAgICB9XFxyXFxufVxcclxcblxcclxcbkAtd2Via2l0LWtleWZyYW1lcyBibGluayB7XFxyXFxuICAgIGZyb20sIHRvIHtcXHJcXG4gICAgICAgIGJvcmRlci1yaWdodC1jb2xvcjogYmxhY2s7XFxyXFxuICAgIH1cXHJcXG4gICAgNTAlIHtcXHJcXG4gICAgICAgIGJvcmRlci1yaWdodC1jb2xvcjogdHJhbnNwYXJlbnQ7XFxyXFxuICAgIH1cXHJcXG59XFxyXFxuXFxyXFxuc3Bhbi5pbS1zdGF0aWMge1xcclxcbiAgICBjb2xvcjogZ3JleTtcXHJcXG59XFxyXFxuXFxyXFxuZGl2LmltLWNvbG9ybWFzayB7XFxyXFxuICAgIGRpc3BsYXk6IGlubGluZS1ibG9jaztcXHJcXG4gICAgYm9yZGVyLXN0eWxlOiBpbnNldDtcXHJcXG4gICAgYm9yZGVyLXdpZHRoOiAycHg7XFxyXFxuICAgIC13ZWJraXQtYXBwZWFyYW5jZTogdGV4dGZpZWxkO1xcclxcbiAgICAtbW96LWFwcGVhcmFuY2U6IHRleHRmaWVsZDtcXHJcXG4gICAgYXBwZWFyYW5jZTogdGV4dGZpZWxkO1xcclxcbn1cXHJcXG5cXHJcXG5kaXYuaW0tY29sb3JtYXNrID4gaW5wdXQge1xcclxcbiAgICBwb3NpdGlvbjogYWJzb2x1dGU7XFxyXFxuICAgIGRpc3BsYXk6IGlubGluZS1ibG9jaztcXHJcXG4gICAgYmFja2dyb3VuZC1jb2xvcjogdHJhbnNwYXJlbnQ7XFxyXFxuICAgIGNvbG9yOiB0cmFuc3BhcmVudDtcXHJcXG4gICAgLXdlYmtpdC1hcHBlYXJhbmNlOiBjYXJldDtcXHJcXG4gICAgLW1vei1hcHBlYXJhbmNlOiBjYXJldDtcXHJcXG4gICAgYXBwZWFyYW5jZTogY2FyZXQ7XFxyXFxuICAgIGJvcmRlci1zdHlsZTogbm9uZTtcXHJcXG4gICAgbGVmdDogMDsgLypjYWxjdWxhdGVkKi9cXHJcXG59XFxyXFxuXFxyXFxuZGl2LmltLWNvbG9ybWFzayA+IGlucHV0OmZvY3VzIHtcXHJcXG4gICAgb3V0bGluZTogbm9uZTtcXHJcXG59XFxyXFxuXFxyXFxuZGl2LmltLWNvbG9ybWFzayA+IGlucHV0OjotbW96LXNlbGVjdGlvbntcXHJcXG4gICAgYmFja2dyb3VuZDogbm9uZTtcXHJcXG59XFxyXFxuXFxyXFxuZGl2LmltLWNvbG9ybWFzayA+IGlucHV0OjpzZWxlY3Rpb257XFxyXFxuICAgIGJhY2tncm91bmQ6IG5vbmU7XFxyXFxufVxcclxcbmRpdi5pbS1jb2xvcm1hc2sgPiBpbnB1dDo6LW1vei1zZWxlY3Rpb257XFxyXFxuICAgIGJhY2tncm91bmQ6IG5vbmU7XFxyXFxufVxcclxcblxcclxcbmRpdi5pbS1jb2xvcm1hc2sgPiBkaXYge1xcclxcbiAgICBjb2xvcjogYmxhY2s7XFxyXFxuICAgIGRpc3BsYXk6IGlubGluZS1ibG9jaztcXHJcXG4gICAgd2lkdGg6IDEwMHB4OyAvKmNhbGN1bGF0ZWQqL1xcclxcbn1cIiwgXCJcIiBdKTtcbn0sIGZ1bmN0aW9uKG1vZHVsZSwgZXhwb3J0cykge1xuICAgIGZ1bmN0aW9uIGNzc1dpdGhNYXBwaW5nVG9TdHJpbmcoaXRlbSwgdXNlU291cmNlTWFwKSB7XG4gICAgICAgIHZhciBjb250ZW50ID0gaXRlbVsxXSB8fCBcIlwiLCBjc3NNYXBwaW5nID0gaXRlbVszXTtcbiAgICAgICAgaWYgKCFjc3NNYXBwaW5nKSByZXR1cm4gY29udGVudDtcbiAgICAgICAgaWYgKHVzZVNvdXJjZU1hcCAmJiBcImZ1bmN0aW9uXCIgPT0gdHlwZW9mIGJ0b2EpIHtcbiAgICAgICAgICAgIHZhciBzb3VyY2VNYXBwaW5nID0gdG9Db21tZW50KGNzc01hcHBpbmcpLCBzb3VyY2VVUkxzID0gY3NzTWFwcGluZy5zb3VyY2VzLm1hcChmdW5jdGlvbihzb3VyY2UpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gXCIvKiMgc291cmNlVVJMPVwiICsgY3NzTWFwcGluZy5zb3VyY2VSb290ICsgc291cmNlICsgXCIgKi9cIjtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcmV0dXJuIFsgY29udGVudCBdLmNvbmNhdChzb3VyY2VVUkxzKS5jb25jYXQoWyBzb3VyY2VNYXBwaW5nIF0pLmpvaW4oXCJcXG5cIik7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIFsgY29udGVudCBdLmpvaW4oXCJcXG5cIik7XG4gICAgfVxuICAgIGZ1bmN0aW9uIHRvQ29tbWVudChzb3VyY2VNYXApIHtcbiAgICAgICAgcmV0dXJuIFwiLyojIFwiICsgKFwic291cmNlTWFwcGluZ1VSTD1kYXRhOmFwcGxpY2F0aW9uL2pzb247Y2hhcnNldD11dGYtODtiYXNlNjQsXCIgKyBidG9hKHVuZXNjYXBlKGVuY29kZVVSSUNvbXBvbmVudChKU09OLnN0cmluZ2lmeShzb3VyY2VNYXApKSkpKSArIFwiICovXCI7XG4gICAgfVxuICAgIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24odXNlU291cmNlTWFwKSB7XG4gICAgICAgIHZhciBsaXN0ID0gW107XG4gICAgICAgIHJldHVybiBsaXN0LnRvU3RyaW5nID0gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5tYXAoZnVuY3Rpb24oaXRlbSkge1xuICAgICAgICAgICAgICAgIHZhciBjb250ZW50ID0gY3NzV2l0aE1hcHBpbmdUb1N0cmluZyhpdGVtLCB1c2VTb3VyY2VNYXApO1xuICAgICAgICAgICAgICAgIHJldHVybiBpdGVtWzJdID8gXCJAbWVkaWEgXCIgKyBpdGVtWzJdICsgXCJ7XCIgKyBjb250ZW50ICsgXCJ9XCIgOiBjb250ZW50O1xuICAgICAgICAgICAgfSkuam9pbihcIlwiKTtcbiAgICAgICAgfSwgbGlzdC5pID0gZnVuY3Rpb24obW9kdWxlcywgbWVkaWFRdWVyeSkge1xuICAgICAgICAgICAgXCJzdHJpbmdcIiA9PSB0eXBlb2YgbW9kdWxlcyAmJiAobW9kdWxlcyA9IFsgWyBudWxsLCBtb2R1bGVzLCBcIlwiIF0gXSk7XG4gICAgICAgICAgICBmb3IgKHZhciBhbHJlYWR5SW1wb3J0ZWRNb2R1bGVzID0ge30sIGkgPSAwOyBpIDwgdGhpcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIHZhciBpZCA9IHRoaXNbaV1bMF07XG4gICAgICAgICAgICAgICAgXCJudW1iZXJcIiA9PSB0eXBlb2YgaWQgJiYgKGFscmVhZHlJbXBvcnRlZE1vZHVsZXNbaWRdID0gITApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IG1vZHVsZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgaXRlbSA9IG1vZHVsZXNbaV07XG4gICAgICAgICAgICAgICAgXCJudW1iZXJcIiA9PSB0eXBlb2YgaXRlbVswXSAmJiBhbHJlYWR5SW1wb3J0ZWRNb2R1bGVzW2l0ZW1bMF1dIHx8IChtZWRpYVF1ZXJ5ICYmICFpdGVtWzJdID8gaXRlbVsyXSA9IG1lZGlhUXVlcnkgOiBtZWRpYVF1ZXJ5ICYmIChpdGVtWzJdID0gXCIoXCIgKyBpdGVtWzJdICsgXCIpIGFuZCAoXCIgKyBtZWRpYVF1ZXJ5ICsgXCIpXCIpLCBcbiAgICAgICAgICAgICAgICBsaXN0LnB1c2goaXRlbSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCBsaXN0O1xuICAgIH07XG59LCBmdW5jdGlvbihtb2R1bGUsIGV4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pIHtcbiAgICBmdW5jdGlvbiBhZGRTdHlsZXNUb0RvbShzdHlsZXMsIG9wdGlvbnMpIHtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdHlsZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciBpdGVtID0gc3R5bGVzW2ldLCBkb21TdHlsZSA9IHN0eWxlc0luRG9tW2l0ZW0uaWRdO1xuICAgICAgICAgICAgaWYgKGRvbVN0eWxlKSB7XG4gICAgICAgICAgICAgICAgZG9tU3R5bGUucmVmcysrO1xuICAgICAgICAgICAgICAgIGZvciAoaiA9IDA7IGogPCBkb21TdHlsZS5wYXJ0cy5sZW5ndGg7IGorKykgZG9tU3R5bGUucGFydHNbal0oaXRlbS5wYXJ0c1tqXSk7XG4gICAgICAgICAgICAgICAgZm9yICg7aiA8IGl0ZW0ucGFydHMubGVuZ3RoOyBqKyspIGRvbVN0eWxlLnBhcnRzLnB1c2goYWRkU3R5bGUoaXRlbS5wYXJ0c1tqXSwgb3B0aW9ucykpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBwYXJ0cyA9IFtdLCBqID0gMDsgaiA8IGl0ZW0ucGFydHMubGVuZ3RoOyBqKyspIHBhcnRzLnB1c2goYWRkU3R5bGUoaXRlbS5wYXJ0c1tqXSwgb3B0aW9ucykpO1xuICAgICAgICAgICAgICAgIHN0eWxlc0luRG9tW2l0ZW0uaWRdID0ge1xuICAgICAgICAgICAgICAgICAgICBpZDogaXRlbS5pZCxcbiAgICAgICAgICAgICAgICAgICAgcmVmczogMSxcbiAgICAgICAgICAgICAgICAgICAgcGFydHM6IHBhcnRzXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICBmdW5jdGlvbiBsaXN0VG9TdHlsZXMobGlzdCwgb3B0aW9ucykge1xuICAgICAgICBmb3IgKHZhciBzdHlsZXMgPSBbXSwgbmV3U3R5bGVzID0ge30sIGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIGl0ZW0gPSBsaXN0W2ldLCBpZCA9IG9wdGlvbnMuYmFzZSA/IGl0ZW1bMF0gKyBvcHRpb25zLmJhc2UgOiBpdGVtWzBdLCBwYXJ0ID0ge1xuICAgICAgICAgICAgICAgIGNzczogaXRlbVsxXSxcbiAgICAgICAgICAgICAgICBtZWRpYTogaXRlbVsyXSxcbiAgICAgICAgICAgICAgICBzb3VyY2VNYXA6IGl0ZW1bM11cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBuZXdTdHlsZXNbaWRdID8gbmV3U3R5bGVzW2lkXS5wYXJ0cy5wdXNoKHBhcnQpIDogc3R5bGVzLnB1c2gobmV3U3R5bGVzW2lkXSA9IHtcbiAgICAgICAgICAgICAgICBpZDogaWQsXG4gICAgICAgICAgICAgICAgcGFydHM6IFsgcGFydCBdXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc3R5bGVzO1xuICAgIH1cbiAgICBmdW5jdGlvbiBpbnNlcnRTdHlsZUVsZW1lbnQob3B0aW9ucywgc3R5bGUpIHtcbiAgICAgICAgdmFyIHRhcmdldCA9IGdldEVsZW1lbnQob3B0aW9ucy5pbnNlcnRJbnRvKTtcbiAgICAgICAgaWYgKCF0YXJnZXQpIHRocm93IG5ldyBFcnJvcihcIkNvdWxkbid0IGZpbmQgYSBzdHlsZSB0YXJnZXQuIFRoaXMgcHJvYmFibHkgbWVhbnMgdGhhdCB0aGUgdmFsdWUgZm9yIHRoZSAnaW5zZXJ0SW50bycgcGFyYW1ldGVyIGlzIGludmFsaWQuXCIpO1xuICAgICAgICB2YXIgbGFzdFN0eWxlRWxlbWVudEluc2VydGVkQXRUb3AgPSBzdHlsZXNJbnNlcnRlZEF0VG9wW3N0eWxlc0luc2VydGVkQXRUb3AubGVuZ3RoIC0gMV07XG4gICAgICAgIGlmIChcInRvcFwiID09PSBvcHRpb25zLmluc2VydEF0KSBsYXN0U3R5bGVFbGVtZW50SW5zZXJ0ZWRBdFRvcCA/IGxhc3RTdHlsZUVsZW1lbnRJbnNlcnRlZEF0VG9wLm5leHRTaWJsaW5nID8gdGFyZ2V0Lmluc2VydEJlZm9yZShzdHlsZSwgbGFzdFN0eWxlRWxlbWVudEluc2VydGVkQXRUb3AubmV4dFNpYmxpbmcpIDogdGFyZ2V0LmFwcGVuZENoaWxkKHN0eWxlKSA6IHRhcmdldC5pbnNlcnRCZWZvcmUoc3R5bGUsIHRhcmdldC5maXJzdENoaWxkKSwgXG4gICAgICAgIHN0eWxlc0luc2VydGVkQXRUb3AucHVzaChzdHlsZSk7IGVsc2UgaWYgKFwiYm90dG9tXCIgPT09IG9wdGlvbnMuaW5zZXJ0QXQpIHRhcmdldC5hcHBlbmRDaGlsZChzdHlsZSk7IGVsc2Uge1xuICAgICAgICAgICAgaWYgKFwib2JqZWN0XCIgIT0gdHlwZW9mIG9wdGlvbnMuaW5zZXJ0QXQgfHwgIW9wdGlvbnMuaW5zZXJ0QXQuYmVmb3JlKSB0aHJvdyBuZXcgRXJyb3IoXCJbU3R5bGUgTG9hZGVyXVxcblxcbiBJbnZhbGlkIHZhbHVlIGZvciBwYXJhbWV0ZXIgJ2luc2VydEF0JyAoJ29wdGlvbnMuaW5zZXJ0QXQnKSBmb3VuZC5cXG4gTXVzdCBiZSAndG9wJywgJ2JvdHRvbScsIG9yIE9iamVjdC5cXG4gKGh0dHBzOi8vZ2l0aHViLmNvbS93ZWJwYWNrLWNvbnRyaWIvc3R5bGUtbG9hZGVyI2luc2VydGF0KVxcblwiKTtcbiAgICAgICAgICAgIHZhciBuZXh0U2libGluZyA9IGdldEVsZW1lbnQob3B0aW9ucy5pbnNlcnRJbnRvICsgXCIgXCIgKyBvcHRpb25zLmluc2VydEF0LmJlZm9yZSk7XG4gICAgICAgICAgICB0YXJnZXQuaW5zZXJ0QmVmb3JlKHN0eWxlLCBuZXh0U2libGluZyk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgZnVuY3Rpb24gcmVtb3ZlU3R5bGVFbGVtZW50KHN0eWxlKSB7XG4gICAgICAgIGlmIChudWxsID09PSBzdHlsZS5wYXJlbnROb2RlKSByZXR1cm4gITE7XG4gICAgICAgIHN0eWxlLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoc3R5bGUpO1xuICAgICAgICB2YXIgaWR4ID0gc3R5bGVzSW5zZXJ0ZWRBdFRvcC5pbmRleE9mKHN0eWxlKTtcbiAgICAgICAgaWR4ID49IDAgJiYgc3R5bGVzSW5zZXJ0ZWRBdFRvcC5zcGxpY2UoaWR4LCAxKTtcbiAgICB9XG4gICAgZnVuY3Rpb24gY3JlYXRlU3R5bGVFbGVtZW50KG9wdGlvbnMpIHtcbiAgICAgICAgdmFyIHN0eWxlID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcInN0eWxlXCIpO1xuICAgICAgICByZXR1cm4gb3B0aW9ucy5hdHRycy50eXBlID0gXCJ0ZXh0L2Nzc1wiLCBhZGRBdHRycyhzdHlsZSwgb3B0aW9ucy5hdHRycyksIGluc2VydFN0eWxlRWxlbWVudChvcHRpb25zLCBzdHlsZSksIFxuICAgICAgICBzdHlsZTtcbiAgICB9XG4gICAgZnVuY3Rpb24gY3JlYXRlTGlua0VsZW1lbnQob3B0aW9ucykge1xuICAgICAgICB2YXIgbGluayA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJsaW5rXCIpO1xuICAgICAgICByZXR1cm4gb3B0aW9ucy5hdHRycy50eXBlID0gXCJ0ZXh0L2Nzc1wiLCBvcHRpb25zLmF0dHJzLnJlbCA9IFwic3R5bGVzaGVldFwiLCBhZGRBdHRycyhsaW5rLCBvcHRpb25zLmF0dHJzKSwgXG4gICAgICAgIGluc2VydFN0eWxlRWxlbWVudChvcHRpb25zLCBsaW5rKSwgbGluaztcbiAgICB9XG4gICAgZnVuY3Rpb24gYWRkQXR0cnMoZWwsIGF0dHJzKSB7XG4gICAgICAgIE9iamVjdC5rZXlzKGF0dHJzKS5mb3JFYWNoKGZ1bmN0aW9uKGtleSkge1xuICAgICAgICAgICAgZWwuc2V0QXR0cmlidXRlKGtleSwgYXR0cnNba2V5XSk7XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBmdW5jdGlvbiBhZGRTdHlsZShvYmosIG9wdGlvbnMpIHtcbiAgICAgICAgdmFyIHN0eWxlLCB1cGRhdGUsIHJlbW92ZSwgcmVzdWx0O1xuICAgICAgICBpZiAob3B0aW9ucy50cmFuc2Zvcm0gJiYgb2JqLmNzcykge1xuICAgICAgICAgICAgaWYgKCEocmVzdWx0ID0gb3B0aW9ucy50cmFuc2Zvcm0ob2JqLmNzcykpKSByZXR1cm4gZnVuY3Rpb24oKSB7fTtcbiAgICAgICAgICAgIG9iai5jc3MgPSByZXN1bHQ7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG9wdGlvbnMuc2luZ2xldG9uKSB7XG4gICAgICAgICAgICB2YXIgc3R5bGVJbmRleCA9IHNpbmdsZXRvbkNvdW50ZXIrKztcbiAgICAgICAgICAgIHN0eWxlID0gc2luZ2xldG9uIHx8IChzaW5nbGV0b24gPSBjcmVhdGVTdHlsZUVsZW1lbnQob3B0aW9ucykpLCB1cGRhdGUgPSBhcHBseVRvU2luZ2xldG9uVGFnLmJpbmQobnVsbCwgc3R5bGUsIHN0eWxlSW5kZXgsICExKSwgXG4gICAgICAgICAgICByZW1vdmUgPSBhcHBseVRvU2luZ2xldG9uVGFnLmJpbmQobnVsbCwgc3R5bGUsIHN0eWxlSW5kZXgsICEwKTtcbiAgICAgICAgfSBlbHNlIG9iai5zb3VyY2VNYXAgJiYgXCJmdW5jdGlvblwiID09IHR5cGVvZiBVUkwgJiYgXCJmdW5jdGlvblwiID09IHR5cGVvZiBVUkwuY3JlYXRlT2JqZWN0VVJMICYmIFwiZnVuY3Rpb25cIiA9PSB0eXBlb2YgVVJMLnJldm9rZU9iamVjdFVSTCAmJiBcImZ1bmN0aW9uXCIgPT0gdHlwZW9mIEJsb2IgJiYgXCJmdW5jdGlvblwiID09IHR5cGVvZiBidG9hID8gKHN0eWxlID0gY3JlYXRlTGlua0VsZW1lbnQob3B0aW9ucyksIFxuICAgICAgICB1cGRhdGUgPSB1cGRhdGVMaW5rLmJpbmQobnVsbCwgc3R5bGUsIG9wdGlvbnMpLCByZW1vdmUgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHJlbW92ZVN0eWxlRWxlbWVudChzdHlsZSksIHN0eWxlLmhyZWYgJiYgVVJMLnJldm9rZU9iamVjdFVSTChzdHlsZS5ocmVmKTtcbiAgICAgICAgfSkgOiAoc3R5bGUgPSBjcmVhdGVTdHlsZUVsZW1lbnQob3B0aW9ucyksIHVwZGF0ZSA9IGFwcGx5VG9UYWcuYmluZChudWxsLCBzdHlsZSksIFxuICAgICAgICByZW1vdmUgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHJlbW92ZVN0eWxlRWxlbWVudChzdHlsZSk7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gdXBkYXRlKG9iaiksIGZ1bmN0aW9uKG5ld09iaikge1xuICAgICAgICAgICAgaWYgKG5ld09iaikge1xuICAgICAgICAgICAgICAgIGlmIChuZXdPYmouY3NzID09PSBvYmouY3NzICYmIG5ld09iai5tZWRpYSA9PT0gb2JqLm1lZGlhICYmIG5ld09iai5zb3VyY2VNYXAgPT09IG9iai5zb3VyY2VNYXApIHJldHVybjtcbiAgICAgICAgICAgICAgICB1cGRhdGUob2JqID0gbmV3T2JqKTtcbiAgICAgICAgICAgIH0gZWxzZSByZW1vdmUoKTtcbiAgICAgICAgfTtcbiAgICB9XG4gICAgZnVuY3Rpb24gYXBwbHlUb1NpbmdsZXRvblRhZyhzdHlsZSwgaW5kZXgsIHJlbW92ZSwgb2JqKSB7XG4gICAgICAgIHZhciBjc3MgPSByZW1vdmUgPyBcIlwiIDogb2JqLmNzcztcbiAgICAgICAgaWYgKHN0eWxlLnN0eWxlU2hlZXQpIHN0eWxlLnN0eWxlU2hlZXQuY3NzVGV4dCA9IHJlcGxhY2VUZXh0KGluZGV4LCBjc3MpOyBlbHNlIHtcbiAgICAgICAgICAgIHZhciBjc3NOb2RlID0gZG9jdW1lbnQuY3JlYXRlVGV4dE5vZGUoY3NzKSwgY2hpbGROb2RlcyA9IHN0eWxlLmNoaWxkTm9kZXM7XG4gICAgICAgICAgICBjaGlsZE5vZGVzW2luZGV4XSAmJiBzdHlsZS5yZW1vdmVDaGlsZChjaGlsZE5vZGVzW2luZGV4XSksIGNoaWxkTm9kZXMubGVuZ3RoID8gc3R5bGUuaW5zZXJ0QmVmb3JlKGNzc05vZGUsIGNoaWxkTm9kZXNbaW5kZXhdKSA6IHN0eWxlLmFwcGVuZENoaWxkKGNzc05vZGUpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGZ1bmN0aW9uIGFwcGx5VG9UYWcoc3R5bGUsIG9iaikge1xuICAgICAgICB2YXIgY3NzID0gb2JqLmNzcywgbWVkaWEgPSBvYmoubWVkaWE7XG4gICAgICAgIGlmIChtZWRpYSAmJiBzdHlsZS5zZXRBdHRyaWJ1dGUoXCJtZWRpYVwiLCBtZWRpYSksIHN0eWxlLnN0eWxlU2hlZXQpIHN0eWxlLnN0eWxlU2hlZXQuY3NzVGV4dCA9IGNzczsgZWxzZSB7XG4gICAgICAgICAgICBmb3IgKDtzdHlsZS5maXJzdENoaWxkOyApIHN0eWxlLnJlbW92ZUNoaWxkKHN0eWxlLmZpcnN0Q2hpbGQpO1xuICAgICAgICAgICAgc3R5bGUuYXBwZW5kQ2hpbGQoZG9jdW1lbnQuY3JlYXRlVGV4dE5vZGUoY3NzKSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgZnVuY3Rpb24gdXBkYXRlTGluayhsaW5rLCBvcHRpb25zLCBvYmopIHtcbiAgICAgICAgdmFyIGNzcyA9IG9iai5jc3MsIHNvdXJjZU1hcCA9IG9iai5zb3VyY2VNYXAsIGF1dG9GaXhVcmxzID0gdm9pZCAwID09PSBvcHRpb25zLmNvbnZlcnRUb0Fic29sdXRlVXJscyAmJiBzb3VyY2VNYXA7XG4gICAgICAgIChvcHRpb25zLmNvbnZlcnRUb0Fic29sdXRlVXJscyB8fCBhdXRvRml4VXJscykgJiYgKGNzcyA9IGZpeFVybHMoY3NzKSksIHNvdXJjZU1hcCAmJiAoY3NzICs9IFwiXFxuLyojIHNvdXJjZU1hcHBpbmdVUkw9ZGF0YTphcHBsaWNhdGlvbi9qc29uO2Jhc2U2NCxcIiArIGJ0b2EodW5lc2NhcGUoZW5jb2RlVVJJQ29tcG9uZW50KEpTT04uc3RyaW5naWZ5KHNvdXJjZU1hcCkpKSkgKyBcIiAqL1wiKTtcbiAgICAgICAgdmFyIGJsb2IgPSBuZXcgQmxvYihbIGNzcyBdLCB7XG4gICAgICAgICAgICB0eXBlOiBcInRleHQvY3NzXCJcbiAgICAgICAgfSksIG9sZFNyYyA9IGxpbmsuaHJlZjtcbiAgICAgICAgbGluay5ocmVmID0gVVJMLmNyZWF0ZU9iamVjdFVSTChibG9iKSwgb2xkU3JjICYmIFVSTC5yZXZva2VPYmplY3RVUkwob2xkU3JjKTtcbiAgICB9XG4gICAgdmFyIHN0eWxlc0luRG9tID0ge30sIGlzT2xkSUUgPSBmdW5jdGlvbihmbikge1xuICAgICAgICB2YXIgbWVtbztcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgcmV0dXJuIHZvaWQgMCA9PT0gbWVtbyAmJiAobWVtbyA9IGZuLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykpLCBtZW1vO1xuICAgICAgICB9O1xuICAgIH0oZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB3aW5kb3cgJiYgZG9jdW1lbnQgJiYgZG9jdW1lbnQuYWxsICYmICF3aW5kb3cuYXRvYjtcbiAgICB9KSwgZ2V0RWxlbWVudCA9IGZ1bmN0aW9uKGZuKSB7XG4gICAgICAgIHZhciBtZW1vID0ge307XG4gICAgICAgIHJldHVybiBmdW5jdGlvbihzZWxlY3Rvcikge1xuICAgICAgICAgICAgaWYgKHZvaWQgMCA9PT0gbWVtb1tzZWxlY3Rvcl0pIHtcbiAgICAgICAgICAgICAgICB2YXIgc3R5bGVUYXJnZXQgPSBmbi5jYWxsKHRoaXMsIHNlbGVjdG9yKTtcbiAgICAgICAgICAgICAgICBpZiAoc3R5bGVUYXJnZXQgaW5zdGFuY2VvZiB3aW5kb3cuSFRNTElGcmFtZUVsZW1lbnQpIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIHN0eWxlVGFyZ2V0ID0gc3R5bGVUYXJnZXQuY29udGVudERvY3VtZW50LmhlYWQ7XG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgICAgICBzdHlsZVRhcmdldCA9IG51bGw7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIG1lbW9bc2VsZWN0b3JdID0gc3R5bGVUYXJnZXQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbWVtb1tzZWxlY3Rvcl07XG4gICAgICAgIH07XG4gICAgfShmdW5jdGlvbih0YXJnZXQpIHtcbiAgICAgICAgcmV0dXJuIGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IodGFyZ2V0KTtcbiAgICB9KSwgc2luZ2xldG9uID0gbnVsbCwgc2luZ2xldG9uQ291bnRlciA9IDAsIHN0eWxlc0luc2VydGVkQXRUb3AgPSBbXSwgZml4VXJscyA9IF9fd2VicGFja19yZXF1aXJlX18oOCk7XG4gICAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihsaXN0LCBvcHRpb25zKSB7XG4gICAgICAgIGlmIChcInVuZGVmaW5lZFwiICE9IHR5cGVvZiBERUJVRyAmJiBERUJVRyAmJiBcIm9iamVjdFwiICE9IHR5cGVvZiBkb2N1bWVudCkgdGhyb3cgbmV3IEVycm9yKFwiVGhlIHN0eWxlLWxvYWRlciBjYW5ub3QgYmUgdXNlZCBpbiBhIG5vbi1icm93c2VyIGVudmlyb25tZW50XCIpO1xuICAgICAgICAob3B0aW9ucyA9IG9wdGlvbnMgfHwge30pLmF0dHJzID0gXCJvYmplY3RcIiA9PSB0eXBlb2Ygb3B0aW9ucy5hdHRycyA/IG9wdGlvbnMuYXR0cnMgOiB7fSwgXG4gICAgICAgIG9wdGlvbnMuc2luZ2xldG9uIHx8IChvcHRpb25zLnNpbmdsZXRvbiA9IGlzT2xkSUUoKSksIG9wdGlvbnMuaW5zZXJ0SW50byB8fCAob3B0aW9ucy5pbnNlcnRJbnRvID0gXCJoZWFkXCIpLCBcbiAgICAgICAgb3B0aW9ucy5pbnNlcnRBdCB8fCAob3B0aW9ucy5pbnNlcnRBdCA9IFwiYm90dG9tXCIpO1xuICAgICAgICB2YXIgc3R5bGVzID0gbGlzdFRvU3R5bGVzKGxpc3QsIG9wdGlvbnMpO1xuICAgICAgICByZXR1cm4gYWRkU3R5bGVzVG9Eb20oc3R5bGVzLCBvcHRpb25zKSwgZnVuY3Rpb24obmV3TGlzdCkge1xuICAgICAgICAgICAgZm9yICh2YXIgbWF5UmVtb3ZlID0gW10sIGkgPSAwOyBpIDwgc3R5bGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgdmFyIGl0ZW0gPSBzdHlsZXNbaV07XG4gICAgICAgICAgICAgICAgKGRvbVN0eWxlID0gc3R5bGVzSW5Eb21baXRlbS5pZF0pLnJlZnMtLSwgbWF5UmVtb3ZlLnB1c2goZG9tU3R5bGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbmV3TGlzdCAmJiBhZGRTdHlsZXNUb0RvbShsaXN0VG9TdHlsZXMobmV3TGlzdCwgb3B0aW9ucyksIG9wdGlvbnMpO1xuICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IG1heVJlbW92ZS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIHZhciBkb21TdHlsZSA9IG1heVJlbW92ZVtpXTtcbiAgICAgICAgICAgICAgICBpZiAoMCA9PT0gZG9tU3R5bGUucmVmcykge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IGRvbVN0eWxlLnBhcnRzLmxlbmd0aDsgaisrKSBkb21TdHlsZS5wYXJ0c1tqXSgpO1xuICAgICAgICAgICAgICAgICAgICBkZWxldGUgc3R5bGVzSW5Eb21bZG9tU3R5bGUuaWRdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICB9O1xuICAgIHZhciByZXBsYWNlVGV4dCA9IGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgdGV4dFN0b3JlID0gW107XG4gICAgICAgIHJldHVybiBmdW5jdGlvbihpbmRleCwgcmVwbGFjZW1lbnQpIHtcbiAgICAgICAgICAgIHJldHVybiB0ZXh0U3RvcmVbaW5kZXhdID0gcmVwbGFjZW1lbnQsIHRleHRTdG9yZS5maWx0ZXIoQm9vbGVhbikuam9pbihcIlxcblwiKTtcbiAgICAgICAgfTtcbiAgICB9KCk7XG59LCBmdW5jdGlvbihtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKGNzcykge1xuICAgICAgICB2YXIgbG9jYXRpb24gPSBcInVuZGVmaW5lZFwiICE9IHR5cGVvZiB3aW5kb3cgJiYgd2luZG93LmxvY2F0aW9uO1xuICAgICAgICBpZiAoIWxvY2F0aW9uKSB0aHJvdyBuZXcgRXJyb3IoXCJmaXhVcmxzIHJlcXVpcmVzIHdpbmRvdy5sb2NhdGlvblwiKTtcbiAgICAgICAgaWYgKCFjc3MgfHwgXCJzdHJpbmdcIiAhPSB0eXBlb2YgY3NzKSByZXR1cm4gY3NzO1xuICAgICAgICB2YXIgYmFzZVVybCA9IGxvY2F0aW9uLnByb3RvY29sICsgXCIvL1wiICsgbG9jYXRpb24uaG9zdCwgY3VycmVudERpciA9IGJhc2VVcmwgKyBsb2NhdGlvbi5wYXRobmFtZS5yZXBsYWNlKC9cXC9bXlxcL10qJC8sIFwiL1wiKTtcbiAgICAgICAgcmV0dXJuIGNzcy5yZXBsYWNlKC91cmxcXHMqXFwoKCg/OlteKShdfFxcKCg/OlteKShdK3xcXChbXikoXSpcXCkpKlxcKSkqKVxcKS9naSwgZnVuY3Rpb24oZnVsbE1hdGNoLCBvcmlnVXJsKSB7XG4gICAgICAgICAgICB2YXIgdW5xdW90ZWRPcmlnVXJsID0gb3JpZ1VybC50cmltKCkucmVwbGFjZSgvXlwiKC4qKVwiJC8sIGZ1bmN0aW9uKG8sICQxKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICQxO1xuICAgICAgICAgICAgfSkucmVwbGFjZSgvXicoLiopJyQvLCBmdW5jdGlvbihvLCAkMSkge1xuICAgICAgICAgICAgICAgIHJldHVybiAkMTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgaWYgKC9eKCN8ZGF0YTp8aHR0cDpcXC9cXC98aHR0cHM6XFwvXFwvfGZpbGU6XFwvXFwvXFwvKS9pLnRlc3QodW5xdW90ZWRPcmlnVXJsKSkgcmV0dXJuIGZ1bGxNYXRjaDtcbiAgICAgICAgICAgIHZhciBuZXdVcmw7XG4gICAgICAgICAgICByZXR1cm4gbmV3VXJsID0gMCA9PT0gdW5xdW90ZWRPcmlnVXJsLmluZGV4T2YoXCIvL1wiKSA/IHVucXVvdGVkT3JpZ1VybCA6IDAgPT09IHVucXVvdGVkT3JpZ1VybC5pbmRleE9mKFwiL1wiKSA/IGJhc2VVcmwgKyB1bnF1b3RlZE9yaWdVcmwgOiBjdXJyZW50RGlyICsgdW5xdW90ZWRPcmlnVXJsLnJlcGxhY2UoL15cXC5cXC8vLCBcIlwiKSwgXG4gICAgICAgICAgICBcInVybChcIiArIEpTT04uc3RyaW5naWZ5KG5ld1VybCkgKyBcIilcIjtcbiAgICAgICAgfSk7XG4gICAgfTtcbn0sIGZ1bmN0aW9uKG1vZHVsZSwgZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykge1xuICAgIFwidXNlIHN0cmljdFwiO1xuICAgIHZhciBfX1dFQlBBQ0tfQU1EX0RFRklORV9GQUNUT1JZX18sIF9fV0VCUEFDS19BTURfREVGSU5FX0FSUkFZX18sIF9fV0VCUEFDS19BTURfREVGSU5FX1JFU1VMVF9fO1xuICAgIFwiZnVuY3Rpb25cIiA9PSB0eXBlb2YgU3ltYm9sICYmIFN5bWJvbC5pdGVyYXRvcjtcbiAgICAhZnVuY3Rpb24oZmFjdG9yeSkge1xuICAgICAgICBfX1dFQlBBQ0tfQU1EX0RFRklORV9BUlJBWV9fID0gWyBfX3dlYnBhY2tfcmVxdWlyZV9fKDApLCBfX3dlYnBhY2tfcmVxdWlyZV9fKDEpIF0sIFxuICAgICAgICB2b2lkIDAgIT09IChfX1dFQlBBQ0tfQU1EX0RFRklORV9SRVNVTFRfXyA9IFwiZnVuY3Rpb25cIiA9PSB0eXBlb2YgKF9fV0VCUEFDS19BTURfREVGSU5FX0ZBQ1RPUllfXyA9IGZhY3RvcnkpID8gX19XRUJQQUNLX0FNRF9ERUZJTkVfRkFDVE9SWV9fLmFwcGx5KGV4cG9ydHMsIF9fV0VCUEFDS19BTURfREVGSU5FX0FSUkFZX18pIDogX19XRUJQQUNLX0FNRF9ERUZJTkVfRkFDVE9SWV9fKSAmJiAobW9kdWxlLmV4cG9ydHMgPSBfX1dFQlBBQ0tfQU1EX0RFRklORV9SRVNVTFRfXyk7XG4gICAgfShmdW5jdGlvbigkLCBJbnB1dG1hc2spIHtcbiAgICAgICAgZnVuY3Rpb24gaXNMZWFwWWVhcih5ZWFyKSB7XG4gICAgICAgICAgICByZXR1cm4gaXNOYU4oeWVhcikgfHwgMjkgPT09IG5ldyBEYXRlKHllYXIsIDIsIDApLmdldERhdGUoKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gSW5wdXRtYXNrLmV4dGVuZEFsaWFzZXMoe1xuICAgICAgICAgICAgXCJkZC9tbS95eXl5XCI6IHtcbiAgICAgICAgICAgICAgICBtYXNrOiBcIjEvMi95XCIsXG4gICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI6IFwiZGQvbW0veXl5eVwiLFxuICAgICAgICAgICAgICAgIHJlZ2V4OiB7XG4gICAgICAgICAgICAgICAgICAgIHZhbDFwcmU6IG5ldyBSZWdFeHAoXCJbMC0zXVwiKSxcbiAgICAgICAgICAgICAgICAgICAgdmFsMTogbmV3IFJlZ0V4cChcIjBbMS05XXxbMTJdWzAtOV18M1swMV1cIiksXG4gICAgICAgICAgICAgICAgICAgIHZhbDJwcmU6IGZ1bmN0aW9uKHNlcGFyYXRvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGVzY2FwZWRTZXBhcmF0b3IgPSBJbnB1dG1hc2suZXNjYXBlUmVnZXguY2FsbCh0aGlzLCBzZXBhcmF0b3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBSZWdFeHAoXCIoKDBbMS05XXxbMTJdWzAtOV18M1swMV0pXCIgKyBlc2NhcGVkU2VwYXJhdG9yICsgXCJbMDFdKVwiKTtcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgdmFsMjogZnVuY3Rpb24oc2VwYXJhdG9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgZXNjYXBlZFNlcGFyYXRvciA9IElucHV0bWFzay5lc2NhcGVSZWdleC5jYWxsKHRoaXMsIHNlcGFyYXRvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IFJlZ0V4cChcIigoMFsxLTldfFsxMl1bMC05XSlcIiArIGVzY2FwZWRTZXBhcmF0b3IgKyBcIigwWzEtOV18MVswMTJdKSl8KDMwXCIgKyBlc2NhcGVkU2VwYXJhdG9yICsgXCIoMFsxMy05XXwxWzAxMl0pKXwoMzFcIiArIGVzY2FwZWRTZXBhcmF0b3IgKyBcIigwWzEzNTc4XXwxWzAyXSkpXCIpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBsZWFwZGF5OiBcIjI5LzAyL1wiLFxuICAgICAgICAgICAgICAgIHNlcGFyYXRvcjogXCIvXCIsXG4gICAgICAgICAgICAgICAgeWVhcnJhbmdlOiB7XG4gICAgICAgICAgICAgICAgICAgIG1pbnllYXI6IDE5MDAsXG4gICAgICAgICAgICAgICAgICAgIG1heHllYXI6IDIwOTlcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGlzSW5ZZWFyUmFuZ2U6IGZ1bmN0aW9uKGNocnMsIG1pbnllYXIsIG1heHllYXIpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzTmFOKGNocnMpKSByZXR1cm4gITE7XG4gICAgICAgICAgICAgICAgICAgIHZhciBlbnRlcmVkeWVhciA9IHBhcnNlSW50KGNocnMuY29uY2F0KG1pbnllYXIudG9TdHJpbmcoKS5zbGljZShjaHJzLmxlbmd0aCkpKSwgZW50ZXJlZHllYXIyID0gcGFyc2VJbnQoY2hycy5jb25jYXQobWF4eWVhci50b1N0cmluZygpLnNsaWNlKGNocnMubGVuZ3RoKSkpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gIWlzTmFOKGVudGVyZWR5ZWFyKSAmJiAobWlueWVhciA8PSBlbnRlcmVkeWVhciAmJiBlbnRlcmVkeWVhciA8PSBtYXh5ZWFyKSB8fCAhaXNOYU4oZW50ZXJlZHllYXIyKSAmJiAobWlueWVhciA8PSBlbnRlcmVkeWVhcjIgJiYgZW50ZXJlZHllYXIyIDw9IG1heHllYXIpO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgZGV0ZXJtaW5lYmFzZXllYXI6IGZ1bmN0aW9uKG1pbnllYXIsIG1heHllYXIsIGhpbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGN1cnJlbnR5ZWFyID0gbmV3IERhdGUoKS5nZXRGdWxsWWVhcigpO1xuICAgICAgICAgICAgICAgICAgICBpZiAobWlueWVhciA+IGN1cnJlbnR5ZWFyKSByZXR1cm4gbWlueWVhcjtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG1heHllYXIgPCBjdXJyZW50eWVhcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgbWF4WWVhclByZWZpeCA9IG1heHllYXIudG9TdHJpbmcoKS5zbGljZSgwLCAyKSwgbWF4WWVhclBvc3RmaXggPSBtYXh5ZWFyLnRvU3RyaW5nKCkuc2xpY2UoMiwgNCk7IG1heHllYXIgPCBtYXhZZWFyUHJlZml4ICsgaGludDsgKSBtYXhZZWFyUHJlZml4LS07XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgbWF4eFllYXIgPSBtYXhZZWFyUHJlZml4ICsgbWF4WWVhclBvc3RmaXg7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbWlueWVhciA+IG1heHhZZWFyID8gbWlueWVhciA6IG1heHhZZWFyO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChtaW55ZWFyIDw9IGN1cnJlbnR5ZWFyICYmIGN1cnJlbnR5ZWFyIDw9IG1heHllYXIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGN1cnJlbnRZZWFyUHJlZml4ID0gY3VycmVudHllYXIudG9TdHJpbmcoKS5zbGljZSgwLCAyKTsgbWF4eWVhciA8IGN1cnJlbnRZZWFyUHJlZml4ICsgaGludDsgKSBjdXJyZW50WWVhclByZWZpeC0tO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGN1cnJlbnRZZWFyQW5kSGludCA9IGN1cnJlbnRZZWFyUHJlZml4ICsgaGludDtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBjdXJyZW50WWVhckFuZEhpbnQgPCBtaW55ZWFyID8gbWlueWVhciA6IGN1cnJlbnRZZWFyQW5kSGludDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gY3VycmVudHllYXI7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBvbktleURvd246IGZ1bmN0aW9uKGUsIGJ1ZmZlciwgY2FyZXRQb3MsIG9wdHMpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyICRpbnB1dCA9ICQodGhpcyk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlLmN0cmxLZXkgJiYgZS5rZXlDb2RlID09PSBJbnB1dG1hc2sua2V5Q29kZS5SSUdIVCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHRvZGF5ID0gbmV3IERhdGUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICRpbnB1dC52YWwodG9kYXkuZ2V0RGF0ZSgpLnRvU3RyaW5nKCkgKyAodG9kYXkuZ2V0TW9udGgoKSArIDEpLnRvU3RyaW5nKCkgKyB0b2RheS5nZXRGdWxsWWVhcigpLnRvU3RyaW5nKCkpLCBcbiAgICAgICAgICAgICAgICAgICAgICAgICRpbnB1dC50cmlnZ2VyKFwic2V0dmFsdWVcIik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGdldEZyb250VmFsdWU6IGZ1bmN0aW9uKG1hc2ssIGJ1ZmZlciwgb3B0cykge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBzdGFydCA9IDAsIGxlbmd0aCA9IDAsIGkgPSAwOyBpIDwgbWFzay5sZW5ndGggJiYgXCIyXCIgIT09IG1hc2suY2hhckF0KGkpOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBkZWZpbml0aW9uID0gb3B0cy5kZWZpbml0aW9uc1ttYXNrLmNoYXJBdChpKV07XG4gICAgICAgICAgICAgICAgICAgICAgICBkZWZpbml0aW9uID8gKHN0YXJ0ICs9IGxlbmd0aCwgbGVuZ3RoID0gZGVmaW5pdGlvbi5jYXJkaW5hbGl0eSkgOiBsZW5ndGgrKztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gYnVmZmVyLmpvaW4oXCJcIikuc3Vic3RyKHN0YXJ0LCBsZW5ndGgpO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgcG9zdFZhbGlkYXRpb246IGZ1bmN0aW9uKGJ1ZmZlciwgY3VycmVudFJlc3VsdCwgb3B0cykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgZGF5TW9udGhWYWx1ZSwgeWVhciwgYnVmZmVyU3RyID0gYnVmZmVyLmpvaW4oXCJcIik7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAwID09PSBvcHRzLm1hc2suaW5kZXhPZihcInlcIikgPyAoeWVhciA9IGJ1ZmZlclN0ci5zdWJzdHIoMCwgNCksIGRheU1vbnRoVmFsdWUgPSBidWZmZXJTdHIuc3Vic3RyaW5nKDQsIDEwKSkgOiAoeWVhciA9IGJ1ZmZlclN0ci5zdWJzdHJpbmcoNiwgMTApLCBcbiAgICAgICAgICAgICAgICAgICAgZGF5TW9udGhWYWx1ZSA9IGJ1ZmZlclN0ci5zdWJzdHIoMCwgNikpLCBjdXJyZW50UmVzdWx0ICYmIChkYXlNb250aFZhbHVlICE9PSBvcHRzLmxlYXBkYXkgfHwgaXNMZWFwWWVhcih5ZWFyKSk7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBkZWZpbml0aW9uczoge1xuICAgICAgICAgICAgICAgICAgICBcIjFcIjoge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFsaWRhdG9yOiBmdW5jdGlvbihjaHJzLCBtYXNrc2V0LCBwb3MsIHN0cmljdCwgb3B0cykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBpc1ZhbGlkID0gb3B0cy5yZWdleC52YWwxLnRlc3QoY2hycyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHN0cmljdCB8fCBpc1ZhbGlkIHx8IGNocnMuY2hhckF0KDEpICE9PSBvcHRzLnNlcGFyYXRvciAmJiAtMSA9PT0gXCItLi9cIi5pbmRleE9mKGNocnMuY2hhckF0KDEpKSB8fCAhKGlzVmFsaWQgPSBvcHRzLnJlZ2V4LnZhbDEudGVzdChcIjBcIiArIGNocnMuY2hhckF0KDApKSkgPyBpc1ZhbGlkIDogKG1hc2tzZXQuYnVmZmVyW3BvcyAtIDFdID0gXCIwXCIsIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVmcmVzaEZyb21CdWZmZXI6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXJ0OiBwb3MgLSAxLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZW5kOiBwb3NcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9zOiBwb3MsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGM6IGNocnMuY2hhckF0KDApXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgY2FyZGluYWxpdHk6IDIsXG4gICAgICAgICAgICAgICAgICAgICAgICBwcmV2YWxpZGF0b3I6IFsge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbGlkYXRvcjogZnVuY3Rpb24oY2hycywgbWFza3NldCwgcG9zLCBzdHJpY3QsIG9wdHMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHBjaHJzID0gY2hycztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXNOYU4obWFza3NldC5idWZmZXJbcG9zICsgMV0pIHx8IChwY2hycyArPSBtYXNrc2V0LmJ1ZmZlcltwb3MgKyAxXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBpc1ZhbGlkID0gMSA9PT0gcGNocnMubGVuZ3RoID8gb3B0cy5yZWdleC52YWwxcHJlLnRlc3QocGNocnMpIDogb3B0cy5yZWdleC52YWwxLnRlc3QocGNocnMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNWYWxpZCAmJiBtYXNrc2V0LnZhbGlkUG9zaXRpb25zW3Bvc10gJiYgKG9wdHMucmVnZXgudmFsMihvcHRzLnNlcGFyYXRvcikudGVzdChjaHJzICsgbWFza3NldC52YWxpZFBvc2l0aW9uc1twb3NdLmlucHV0KSB8fCAobWFza3NldC52YWxpZFBvc2l0aW9uc1twb3NdLmlucHV0ID0gXCIwXCIgPT09IGNocnMgPyBcIjFcIiA6IFwiMFwiKSksIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAhc3RyaWN0ICYmICFpc1ZhbGlkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNWYWxpZCA9IG9wdHMucmVnZXgudmFsMS50ZXN0KGNocnMgKyBcIjBcIikpIHJldHVybiBtYXNrc2V0LmJ1ZmZlcltwb3NdID0gY2hycywgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXNrc2V0LmJ1ZmZlclsrK3Bvc10gPSBcIjBcIiwge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvczogcG9zLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGM6IFwiMFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzVmFsaWQgPSBvcHRzLnJlZ2V4LnZhbDEudGVzdChcIjBcIiArIGNocnMpKSByZXR1cm4gbWFza3NldC5idWZmZXJbcG9zXSA9IFwiMFwiLCBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvcysrLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9zOiBwb3NcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGlzVmFsaWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXJkaW5hbGl0eTogMVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBdXG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIFwiMlwiOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YWxpZGF0b3I6IGZ1bmN0aW9uKGNocnMsIG1hc2tzZXQsIHBvcywgc3RyaWN0LCBvcHRzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGZyb250VmFsdWUgPSBvcHRzLmdldEZyb250VmFsdWUobWFza3NldC5tYXNrLCBtYXNrc2V0LmJ1ZmZlciwgb3B0cyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLTEgIT09IGZyb250VmFsdWUuaW5kZXhPZihvcHRzLnBsYWNlaG9sZGVyWzBdKSAmJiAoZnJvbnRWYWx1ZSA9IFwiMDFcIiArIG9wdHMuc2VwYXJhdG9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgaXNWYWxpZCA9IG9wdHMucmVnZXgudmFsMihvcHRzLnNlcGFyYXRvcikudGVzdChmcm9udFZhbHVlICsgY2hycyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHN0cmljdCB8fCBpc1ZhbGlkIHx8IGNocnMuY2hhckF0KDEpICE9PSBvcHRzLnNlcGFyYXRvciAmJiAtMSA9PT0gXCItLi9cIi5pbmRleE9mKGNocnMuY2hhckF0KDEpKSB8fCAhKGlzVmFsaWQgPSBvcHRzLnJlZ2V4LnZhbDIob3B0cy5zZXBhcmF0b3IpLnRlc3QoZnJvbnRWYWx1ZSArIFwiMFwiICsgY2hycy5jaGFyQXQoMCkpKSA/IGlzVmFsaWQgOiAobWFza3NldC5idWZmZXJbcG9zIC0gMV0gPSBcIjBcIiwgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWZyZXNoRnJvbUJ1ZmZlcjoge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhcnQ6IHBvcyAtIDEsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbmQ6IHBvc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwb3M6IHBvcyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYzogY2hycy5jaGFyQXQoMClcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICBjYXJkaW5hbGl0eTogMixcbiAgICAgICAgICAgICAgICAgICAgICAgIHByZXZhbGlkYXRvcjogWyB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsaWRhdG9yOiBmdW5jdGlvbihjaHJzLCBtYXNrc2V0LCBwb3MsIHN0cmljdCwgb3B0cykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpc05hTihtYXNrc2V0LmJ1ZmZlcltwb3MgKyAxXSkgfHwgKGNocnMgKz0gbWFza3NldC5idWZmZXJbcG9zICsgMV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgZnJvbnRWYWx1ZSA9IG9wdHMuZ2V0RnJvbnRWYWx1ZShtYXNrc2V0Lm1hc2ssIG1hc2tzZXQuYnVmZmVyLCBvcHRzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLTEgIT09IGZyb250VmFsdWUuaW5kZXhPZihvcHRzLnBsYWNlaG9sZGVyWzBdKSAmJiAoZnJvbnRWYWx1ZSA9IFwiMDFcIiArIG9wdHMuc2VwYXJhdG9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGlzVmFsaWQgPSAxID09PSBjaHJzLmxlbmd0aCA/IG9wdHMucmVnZXgudmFsMnByZShvcHRzLnNlcGFyYXRvcikudGVzdChmcm9udFZhbHVlICsgY2hycykgOiBvcHRzLnJlZ2V4LnZhbDIob3B0cy5zZXBhcmF0b3IpLnRlc3QoZnJvbnRWYWx1ZSArIGNocnMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gaXNWYWxpZCAmJiBtYXNrc2V0LnZhbGlkUG9zaXRpb25zW3Bvc10gJiYgKG9wdHMucmVnZXgudmFsMihvcHRzLnNlcGFyYXRvcikudGVzdChjaHJzICsgbWFza3NldC52YWxpZFBvc2l0aW9uc1twb3NdLmlucHV0KSB8fCAobWFza3NldC52YWxpZFBvc2l0aW9uc1twb3NdLmlucHV0ID0gXCIwXCIgPT09IGNocnMgPyBcIjFcIiA6IFwiMFwiKSksIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJpY3QgfHwgaXNWYWxpZCB8fCAhKGlzVmFsaWQgPSBvcHRzLnJlZ2V4LnZhbDIob3B0cy5zZXBhcmF0b3IpLnRlc3QoZnJvbnRWYWx1ZSArIFwiMFwiICsgY2hycykpID8gaXNWYWxpZCA6IChtYXNrc2V0LmJ1ZmZlcltwb3NdID0gXCIwXCIsIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwb3MrKywge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9zOiBwb3NcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXJkaW5hbGl0eTogMVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBdXG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIHk6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhbGlkYXRvcjogZnVuY3Rpb24oY2hycywgbWFza3NldCwgcG9zLCBzdHJpY3QsIG9wdHMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gb3B0cy5pc0luWWVhclJhbmdlKGNocnMsIG9wdHMueWVhcnJhbmdlLm1pbnllYXIsIG9wdHMueWVhcnJhbmdlLm1heHllYXIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhcmRpbmFsaXR5OiA0LFxuICAgICAgICAgICAgICAgICAgICAgICAgcHJldmFsaWRhdG9yOiBbIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWxpZGF0b3I6IGZ1bmN0aW9uKGNocnMsIG1hc2tzZXQsIHBvcywgc3RyaWN0LCBvcHRzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBpc1ZhbGlkID0gb3B0cy5pc0luWWVhclJhbmdlKGNocnMsIG9wdHMueWVhcnJhbmdlLm1pbnllYXIsIG9wdHMueWVhcnJhbmdlLm1heHllYXIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXN0cmljdCAmJiAhaXNWYWxpZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHllYXJQcmVmaXggPSBvcHRzLmRldGVybWluZWJhc2V5ZWFyKG9wdHMueWVhcnJhbmdlLm1pbnllYXIsIG9wdHMueWVhcnJhbmdlLm1heHllYXIsIGNocnMgKyBcIjBcIikudG9TdHJpbmcoKS5zbGljZSgwLCAxKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc1ZhbGlkID0gb3B0cy5pc0luWWVhclJhbmdlKHllYXJQcmVmaXggKyBjaHJzLCBvcHRzLnllYXJyYW5nZS5taW55ZWFyLCBvcHRzLnllYXJyYW5nZS5tYXh5ZWFyKSkgcmV0dXJuIG1hc2tzZXQuYnVmZmVyW3BvcysrXSA9IHllYXJQcmVmaXguY2hhckF0KDApLCBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwb3M6IHBvc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh5ZWFyUHJlZml4ID0gb3B0cy5kZXRlcm1pbmViYXNleWVhcihvcHRzLnllYXJyYW5nZS5taW55ZWFyLCBvcHRzLnllYXJyYW5nZS5tYXh5ZWFyLCBjaHJzICsgXCIwXCIpLnRvU3RyaW5nKCkuc2xpY2UoMCwgMiksIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXNWYWxpZCA9IG9wdHMuaXNJblllYXJSYW5nZSh5ZWFyUHJlZml4ICsgY2hycywgb3B0cy55ZWFycmFuZ2UubWlueWVhciwgb3B0cy55ZWFycmFuZ2UubWF4eWVhcikpIHJldHVybiBtYXNrc2V0LmJ1ZmZlcltwb3MrK10gPSB5ZWFyUHJlZml4LmNoYXJBdCgwKSwgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXNrc2V0LmJ1ZmZlcltwb3MrK10gPSB5ZWFyUHJlZml4LmNoYXJBdCgxKSwge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvczogcG9zXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBpc1ZhbGlkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FyZGluYWxpdHk6IDFcbiAgICAgICAgICAgICAgICAgICAgICAgIH0sIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWxpZGF0b3I6IGZ1bmN0aW9uKGNocnMsIG1hc2tzZXQsIHBvcywgc3RyaWN0LCBvcHRzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBpc1ZhbGlkID0gb3B0cy5pc0luWWVhclJhbmdlKGNocnMsIG9wdHMueWVhcnJhbmdlLm1pbnllYXIsIG9wdHMueWVhcnJhbmdlLm1heHllYXIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXN0cmljdCAmJiAhaXNWYWxpZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHllYXJQcmVmaXggPSBvcHRzLmRldGVybWluZWJhc2V5ZWFyKG9wdHMueWVhcnJhbmdlLm1pbnllYXIsIG9wdHMueWVhcnJhbmdlLm1heHllYXIsIGNocnMpLnRvU3RyaW5nKCkuc2xpY2UoMCwgMik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNWYWxpZCA9IG9wdHMuaXNJblllYXJSYW5nZShjaHJzWzBdICsgeWVhclByZWZpeFsxXSArIGNocnNbMV0sIG9wdHMueWVhcnJhbmdlLm1pbnllYXIsIG9wdHMueWVhcnJhbmdlLm1heHllYXIpKSByZXR1cm4gbWFza3NldC5idWZmZXJbcG9zKytdID0geWVhclByZWZpeC5jaGFyQXQoMSksIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvczogcG9zXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHllYXJQcmVmaXggPSBvcHRzLmRldGVybWluZWJhc2V5ZWFyKG9wdHMueWVhcnJhbmdlLm1pbnllYXIsIG9wdHMueWVhcnJhbmdlLm1heHllYXIsIGNocnMpLnRvU3RyaW5nKCkuc2xpY2UoMCwgMiksIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXNWYWxpZCA9IG9wdHMuaXNJblllYXJSYW5nZSh5ZWFyUHJlZml4ICsgY2hycywgb3B0cy55ZWFycmFuZ2UubWlueWVhciwgb3B0cy55ZWFycmFuZ2UubWF4eWVhcikpIHJldHVybiBtYXNrc2V0LmJ1ZmZlcltwb3MgLSAxXSA9IHllYXJQcmVmaXguY2hhckF0KDApLCBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hc2tzZXQuYnVmZmVyW3BvcysrXSA9IHllYXJQcmVmaXguY2hhckF0KDEpLCBtYXNrc2V0LmJ1ZmZlcltwb3MrK10gPSBjaHJzLmNoYXJBdCgwKSwgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVmcmVzaEZyb21CdWZmZXI6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhcnQ6IHBvcyAtIDMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVuZDogcG9zXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwb3M6IHBvc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gaXNWYWxpZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhcmRpbmFsaXR5OiAyXG4gICAgICAgICAgICAgICAgICAgICAgICB9LCB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsaWRhdG9yOiBmdW5jdGlvbihjaHJzLCBtYXNrc2V0LCBwb3MsIHN0cmljdCwgb3B0cykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gb3B0cy5pc0luWWVhclJhbmdlKGNocnMsIG9wdHMueWVhcnJhbmdlLm1pbnllYXIsIG9wdHMueWVhcnJhbmdlLm1heHllYXIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FyZGluYWxpdHk6IDNcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gXVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBpbnNlcnRNb2RlOiAhMSxcbiAgICAgICAgICAgICAgICBhdXRvVW5tYXNrOiAhMVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIFwibW0vZGQveXl5eVwiOiB7XG4gICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI6IFwibW0vZGQveXl5eVwiLFxuICAgICAgICAgICAgICAgIGFsaWFzOiBcImRkL21tL3l5eXlcIixcbiAgICAgICAgICAgICAgICByZWdleDoge1xuICAgICAgICAgICAgICAgICAgICB2YWwycHJlOiBmdW5jdGlvbihzZXBhcmF0b3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBlc2NhcGVkU2VwYXJhdG9yID0gSW5wdXRtYXNrLmVzY2FwZVJlZ2V4LmNhbGwodGhpcywgc2VwYXJhdG9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgUmVnRXhwKFwiKCgwWzEzLTldfDFbMDEyXSlcIiArIGVzY2FwZWRTZXBhcmF0b3IgKyBcIlswLTNdKXwoMDJcIiArIGVzY2FwZWRTZXBhcmF0b3IgKyBcIlswLTJdKVwiKTtcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgdmFsMjogZnVuY3Rpb24oc2VwYXJhdG9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgZXNjYXBlZFNlcGFyYXRvciA9IElucHV0bWFzay5lc2NhcGVSZWdleC5jYWxsKHRoaXMsIHNlcGFyYXRvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IFJlZ0V4cChcIigoMFsxLTldfDFbMDEyXSlcIiArIGVzY2FwZWRTZXBhcmF0b3IgKyBcIigwWzEtOV18WzEyXVswLTldKSl8KCgwWzEzLTldfDFbMDEyXSlcIiArIGVzY2FwZWRTZXBhcmF0b3IgKyBcIjMwKXwoKDBbMTM1NzhdfDFbMDJdKVwiICsgZXNjYXBlZFNlcGFyYXRvciArIFwiMzEpXCIpO1xuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICB2YWwxcHJlOiBuZXcgUmVnRXhwKFwiWzAxXVwiKSxcbiAgICAgICAgICAgICAgICAgICAgdmFsMTogbmV3IFJlZ0V4cChcIjBbMS05XXwxWzAxMl1cIilcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGxlYXBkYXk6IFwiMDIvMjkvXCIsXG4gICAgICAgICAgICAgICAgb25LZXlEb3duOiBmdW5jdGlvbihlLCBidWZmZXIsIGNhcmV0UG9zLCBvcHRzKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciAkaW5wdXQgPSAkKHRoaXMpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoZS5jdHJsS2V5ICYmIGUua2V5Q29kZSA9PT0gSW5wdXRtYXNrLmtleUNvZGUuUklHSFQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciB0b2RheSA9IG5ldyBEYXRlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAkaW5wdXQudmFsKCh0b2RheS5nZXRNb250aCgpICsgMSkudG9TdHJpbmcoKSArIHRvZGF5LmdldERhdGUoKS50b1N0cmluZygpICsgdG9kYXkuZ2V0RnVsbFllYXIoKS50b1N0cmluZygpKSwgXG4gICAgICAgICAgICAgICAgICAgICAgICAkaW5wdXQudHJpZ2dlcihcInNldHZhbHVlXCIpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIFwieXl5eS9tbS9kZFwiOiB7XG4gICAgICAgICAgICAgICAgbWFzazogXCJ5LzEvMlwiLFxuICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyOiBcInl5eXkvbW0vZGRcIixcbiAgICAgICAgICAgICAgICBhbGlhczogXCJtbS9kZC95eXl5XCIsXG4gICAgICAgICAgICAgICAgbGVhcGRheTogXCIvMDIvMjlcIixcbiAgICAgICAgICAgICAgICBvbktleURvd246IGZ1bmN0aW9uKGUsIGJ1ZmZlciwgY2FyZXRQb3MsIG9wdHMpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyICRpbnB1dCA9ICQodGhpcyk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlLmN0cmxLZXkgJiYgZS5rZXlDb2RlID09PSBJbnB1dG1hc2sua2V5Q29kZS5SSUdIVCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHRvZGF5ID0gbmV3IERhdGUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICRpbnB1dC52YWwodG9kYXkuZ2V0RnVsbFllYXIoKS50b1N0cmluZygpICsgKHRvZGF5LmdldE1vbnRoKCkgKyAxKS50b1N0cmluZygpICsgdG9kYXkuZ2V0RGF0ZSgpLnRvU3RyaW5nKCkpLCBcbiAgICAgICAgICAgICAgICAgICAgICAgICRpbnB1dC50cmlnZ2VyKFwic2V0dmFsdWVcIik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgXCJkZC5tbS55eXl5XCI6IHtcbiAgICAgICAgICAgICAgICBtYXNrOiBcIjEuMi55XCIsXG4gICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI6IFwiZGQubW0ueXl5eVwiLFxuICAgICAgICAgICAgICAgIGxlYXBkYXk6IFwiMjkuMDIuXCIsXG4gICAgICAgICAgICAgICAgc2VwYXJhdG9yOiBcIi5cIixcbiAgICAgICAgICAgICAgICBhbGlhczogXCJkZC9tbS95eXl5XCJcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBcImRkLW1tLXl5eXlcIjoge1xuICAgICAgICAgICAgICAgIG1hc2s6IFwiMS0yLXlcIixcbiAgICAgICAgICAgICAgICBwbGFjZWhvbGRlcjogXCJkZC1tbS15eXl5XCIsXG4gICAgICAgICAgICAgICAgbGVhcGRheTogXCIyOS0wMi1cIixcbiAgICAgICAgICAgICAgICBzZXBhcmF0b3I6IFwiLVwiLFxuICAgICAgICAgICAgICAgIGFsaWFzOiBcImRkL21tL3l5eXlcIlxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIFwibW0uZGQueXl5eVwiOiB7XG4gICAgICAgICAgICAgICAgbWFzazogXCIxLjIueVwiLFxuICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyOiBcIm1tLmRkLnl5eXlcIixcbiAgICAgICAgICAgICAgICBsZWFwZGF5OiBcIjAyLjI5LlwiLFxuICAgICAgICAgICAgICAgIHNlcGFyYXRvcjogXCIuXCIsXG4gICAgICAgICAgICAgICAgYWxpYXM6IFwibW0vZGQveXl5eVwiXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgXCJtbS1kZC15eXl5XCI6IHtcbiAgICAgICAgICAgICAgICBtYXNrOiBcIjEtMi15XCIsXG4gICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI6IFwibW0tZGQteXl5eVwiLFxuICAgICAgICAgICAgICAgIGxlYXBkYXk6IFwiMDItMjktXCIsXG4gICAgICAgICAgICAgICAgc2VwYXJhdG9yOiBcIi1cIixcbiAgICAgICAgICAgICAgICBhbGlhczogXCJtbS9kZC95eXl5XCJcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBcInl5eXkubW0uZGRcIjoge1xuICAgICAgICAgICAgICAgIG1hc2s6IFwieS4xLjJcIixcbiAgICAgICAgICAgICAgICBwbGFjZWhvbGRlcjogXCJ5eXl5Lm1tLmRkXCIsXG4gICAgICAgICAgICAgICAgbGVhcGRheTogXCIuMDIuMjlcIixcbiAgICAgICAgICAgICAgICBzZXBhcmF0b3I6IFwiLlwiLFxuICAgICAgICAgICAgICAgIGFsaWFzOiBcInl5eXkvbW0vZGRcIlxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIFwieXl5eS1tbS1kZFwiOiB7XG4gICAgICAgICAgICAgICAgbWFzazogXCJ5LTEtMlwiLFxuICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyOiBcInl5eXktbW0tZGRcIixcbiAgICAgICAgICAgICAgICBsZWFwZGF5OiBcIi0wMi0yOVwiLFxuICAgICAgICAgICAgICAgIHNlcGFyYXRvcjogXCItXCIsXG4gICAgICAgICAgICAgICAgYWxpYXM6IFwieXl5eS9tbS9kZFwiXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZGF0ZXRpbWU6IHtcbiAgICAgICAgICAgICAgICBtYXNrOiBcIjEvMi95IGg6c1wiLFxuICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyOiBcImRkL21tL3l5eXkgaGg6bW1cIixcbiAgICAgICAgICAgICAgICBhbGlhczogXCJkZC9tbS95eXl5XCIsXG4gICAgICAgICAgICAgICAgcmVnZXg6IHtcbiAgICAgICAgICAgICAgICAgICAgaHJzcHJlOiBuZXcgUmVnRXhwKFwiWzAxMl1cIiksXG4gICAgICAgICAgICAgICAgICAgIGhyczI0OiBuZXcgUmVnRXhwKFwiMlswLTRdfDFbMy05XVwiKSxcbiAgICAgICAgICAgICAgICAgICAgaHJzOiBuZXcgUmVnRXhwKFwiWzAxXVswLTldfDJbMC00XVwiKSxcbiAgICAgICAgICAgICAgICAgICAgYW1wbTogbmV3IFJlZ0V4cChcIl5bYXxwfEF8UF1bbXxNXVwiKSxcbiAgICAgICAgICAgICAgICAgICAgbXNwcmU6IG5ldyBSZWdFeHAoXCJbMC01XVwiKSxcbiAgICAgICAgICAgICAgICAgICAgbXM6IG5ldyBSZWdFeHAoXCJbMC01XVswLTldXCIpXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICB0aW1lc2VwYXJhdG9yOiBcIjpcIixcbiAgICAgICAgICAgICAgICBob3VyRm9ybWF0OiBcIjI0XCIsXG4gICAgICAgICAgICAgICAgZGVmaW5pdGlvbnM6IHtcbiAgICAgICAgICAgICAgICAgICAgaDoge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFsaWRhdG9yOiBmdW5jdGlvbihjaHJzLCBtYXNrc2V0LCBwb3MsIHN0cmljdCwgb3B0cykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChcIjI0XCIgPT09IG9wdHMuaG91ckZvcm1hdCAmJiAyNCA9PT0gcGFyc2VJbnQoY2hycywgMTApKSByZXR1cm4gbWFza3NldC5idWZmZXJbcG9zIC0gMV0gPSBcIjBcIiwgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFza3NldC5idWZmZXJbcG9zXSA9IFwiMFwiLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlZnJlc2hGcm9tQnVmZmVyOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGFydDogcG9zIC0gMSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVuZDogcG9zXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGM6IFwiMFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgaXNWYWxpZCA9IG9wdHMucmVnZXguaHJzLnRlc3QoY2hycyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFzdHJpY3QgJiYgIWlzVmFsaWQgJiYgKGNocnMuY2hhckF0KDEpID09PSBvcHRzLnRpbWVzZXBhcmF0b3IgfHwgLTEgIT09IFwiLS46XCIuaW5kZXhPZihjaHJzLmNoYXJBdCgxKSkpICYmIChpc1ZhbGlkID0gb3B0cy5yZWdleC5ocnMudGVzdChcIjBcIiArIGNocnMuY2hhckF0KDApKSkpIHJldHVybiBtYXNrc2V0LmJ1ZmZlcltwb3MgLSAxXSA9IFwiMFwiLCBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXNrc2V0LmJ1ZmZlcltwb3NdID0gY2hycy5jaGFyQXQoMCksIHBvcysrLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlZnJlc2hGcm9tQnVmZmVyOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGFydDogcG9zIC0gMixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVuZDogcG9zXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvczogcG9zLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjOiBvcHRzLnRpbWVzZXBhcmF0b3JcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc1ZhbGlkICYmIFwiMjRcIiAhPT0gb3B0cy5ob3VyRm9ybWF0ICYmIG9wdHMucmVnZXguaHJzMjQudGVzdChjaHJzKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgdG1wID0gcGFyc2VJbnQoY2hycywgMTApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gMjQgPT09IHRtcCA/IChtYXNrc2V0LmJ1ZmZlcltwb3MgKyA1XSA9IFwiYVwiLCBtYXNrc2V0LmJ1ZmZlcltwb3MgKyA2XSA9IFwibVwiKSA6IChtYXNrc2V0LmJ1ZmZlcltwb3MgKyA1XSA9IFwicFwiLCBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFza3NldC5idWZmZXJbcG9zICsgNl0gPSBcIm1cIiksICh0bXAgLT0gMTIpIDwgMTAgPyAobWFza3NldC5idWZmZXJbcG9zXSA9IHRtcC50b1N0cmluZygpLCBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFza3NldC5idWZmZXJbcG9zIC0gMV0gPSBcIjBcIikgOiAobWFza3NldC5idWZmZXJbcG9zXSA9IHRtcC50b1N0cmluZygpLmNoYXJBdCgxKSwgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hc2tzZXQuYnVmZmVyW3BvcyAtIDFdID0gdG1wLnRvU3RyaW5nKCkuY2hhckF0KDApKSwge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVmcmVzaEZyb21CdWZmZXI6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGFydDogcG9zIC0gMSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbmQ6IHBvcyArIDZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjOiBtYXNrc2V0LmJ1ZmZlcltwb3NdXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBpc1ZhbGlkO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhcmRpbmFsaXR5OiAyLFxuICAgICAgICAgICAgICAgICAgICAgICAgcHJldmFsaWRhdG9yOiBbIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWxpZGF0b3I6IGZ1bmN0aW9uKGNocnMsIG1hc2tzZXQsIHBvcywgc3RyaWN0LCBvcHRzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBpc1ZhbGlkID0gb3B0cy5yZWdleC5ocnNwcmUudGVzdChjaHJzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHN0cmljdCB8fCBpc1ZhbGlkIHx8ICEoaXNWYWxpZCA9IG9wdHMucmVnZXguaHJzLnRlc3QoXCIwXCIgKyBjaHJzKSkgPyBpc1ZhbGlkIDogKG1hc2tzZXQuYnVmZmVyW3Bvc10gPSBcIjBcIiwgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvcysrLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwb3M6IHBvc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhcmRpbmFsaXR5OiAxXG4gICAgICAgICAgICAgICAgICAgICAgICB9IF1cbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgczoge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFsaWRhdG9yOiBcIlswLTVdWzAtOV1cIixcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhcmRpbmFsaXR5OiAyLFxuICAgICAgICAgICAgICAgICAgICAgICAgcHJldmFsaWRhdG9yOiBbIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWxpZGF0b3I6IGZ1bmN0aW9uKGNocnMsIG1hc2tzZXQsIHBvcywgc3RyaWN0LCBvcHRzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBpc1ZhbGlkID0gb3B0cy5yZWdleC5tc3ByZS50ZXN0KGNocnMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gc3RyaWN0IHx8IGlzVmFsaWQgfHwgIShpc1ZhbGlkID0gb3B0cy5yZWdleC5tcy50ZXN0KFwiMFwiICsgY2hycykpID8gaXNWYWxpZCA6IChtYXNrc2V0LmJ1ZmZlcltwb3NdID0gXCIwXCIsIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwb3MrKywge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9zOiBwb3NcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXJkaW5hbGl0eTogMVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBdXG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIHQ6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhbGlkYXRvcjogZnVuY3Rpb24oY2hycywgbWFza3NldCwgcG9zLCBzdHJpY3QsIG9wdHMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gb3B0cy5yZWdleC5hbXBtLnRlc3QoY2hycyArIFwibVwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNpbmc6IFwibG93ZXJcIixcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhcmRpbmFsaXR5OiAxXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGluc2VydE1vZGU6ICExLFxuICAgICAgICAgICAgICAgIGF1dG9Vbm1hc2s6ICExXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZGF0ZXRpbWUxMjoge1xuICAgICAgICAgICAgICAgIG1hc2s6IFwiMS8yL3kgaDpzIHRcXFxcbVwiLFxuICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyOiBcImRkL21tL3l5eXkgaGg6bW0geG1cIixcbiAgICAgICAgICAgICAgICBhbGlhczogXCJkYXRldGltZVwiLFxuICAgICAgICAgICAgICAgIGhvdXJGb3JtYXQ6IFwiMTJcIlxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIFwibW0vZGQveXl5eSBoaDptbSB4bVwiOiB7XG4gICAgICAgICAgICAgICAgbWFzazogXCIxLzIveSBoOnMgdFxcXFxtXCIsXG4gICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI6IFwibW0vZGQveXl5eSBoaDptbSB4bVwiLFxuICAgICAgICAgICAgICAgIGFsaWFzOiBcImRhdGV0aW1lMTJcIixcbiAgICAgICAgICAgICAgICByZWdleDoge1xuICAgICAgICAgICAgICAgICAgICB2YWwycHJlOiBmdW5jdGlvbihzZXBhcmF0b3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBlc2NhcGVkU2VwYXJhdG9yID0gSW5wdXRtYXNrLmVzY2FwZVJlZ2V4LmNhbGwodGhpcywgc2VwYXJhdG9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgUmVnRXhwKFwiKCgwWzEzLTldfDFbMDEyXSlcIiArIGVzY2FwZWRTZXBhcmF0b3IgKyBcIlswLTNdKXwoMDJcIiArIGVzY2FwZWRTZXBhcmF0b3IgKyBcIlswLTJdKVwiKTtcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgdmFsMjogZnVuY3Rpb24oc2VwYXJhdG9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgZXNjYXBlZFNlcGFyYXRvciA9IElucHV0bWFzay5lc2NhcGVSZWdleC5jYWxsKHRoaXMsIHNlcGFyYXRvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IFJlZ0V4cChcIigoMFsxLTldfDFbMDEyXSlcIiArIGVzY2FwZWRTZXBhcmF0b3IgKyBcIigwWzEtOV18WzEyXVswLTldKSl8KCgwWzEzLTldfDFbMDEyXSlcIiArIGVzY2FwZWRTZXBhcmF0b3IgKyBcIjMwKXwoKDBbMTM1NzhdfDFbMDJdKVwiICsgZXNjYXBlZFNlcGFyYXRvciArIFwiMzEpXCIpO1xuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICB2YWwxcHJlOiBuZXcgUmVnRXhwKFwiWzAxXVwiKSxcbiAgICAgICAgICAgICAgICAgICAgdmFsMTogbmV3IFJlZ0V4cChcIjBbMS05XXwxWzAxMl1cIilcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGxlYXBkYXk6IFwiMDIvMjkvXCIsXG4gICAgICAgICAgICAgICAgb25LZXlEb3duOiBmdW5jdGlvbihlLCBidWZmZXIsIGNhcmV0UG9zLCBvcHRzKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciAkaW5wdXQgPSAkKHRoaXMpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoZS5jdHJsS2V5ICYmIGUua2V5Q29kZSA9PT0gSW5wdXRtYXNrLmtleUNvZGUuUklHSFQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciB0b2RheSA9IG5ldyBEYXRlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAkaW5wdXQudmFsKCh0b2RheS5nZXRNb250aCgpICsgMSkudG9TdHJpbmcoKSArIHRvZGF5LmdldERhdGUoKS50b1N0cmluZygpICsgdG9kYXkuZ2V0RnVsbFllYXIoKS50b1N0cmluZygpKSwgXG4gICAgICAgICAgICAgICAgICAgICAgICAkaW5wdXQudHJpZ2dlcihcInNldHZhbHVlXCIpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIFwiaGg6bW0gdFwiOiB7XG4gICAgICAgICAgICAgICAgbWFzazogXCJoOnMgdFxcXFxtXCIsXG4gICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI6IFwiaGg6bW0geG1cIixcbiAgICAgICAgICAgICAgICBhbGlhczogXCJkYXRldGltZVwiLFxuICAgICAgICAgICAgICAgIGhvdXJGb3JtYXQ6IFwiMTJcIlxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIFwiaDpzIHRcIjoge1xuICAgICAgICAgICAgICAgIG1hc2s6IFwiaDpzIHRcXFxcbVwiLFxuICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyOiBcImhoOm1tIHhtXCIsXG4gICAgICAgICAgICAgICAgYWxpYXM6IFwiZGF0ZXRpbWVcIixcbiAgICAgICAgICAgICAgICBob3VyRm9ybWF0OiBcIjEyXCJcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBcImhoOm1tOnNzXCI6IHtcbiAgICAgICAgICAgICAgICBtYXNrOiBcImg6czpzXCIsXG4gICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI6IFwiaGg6bW06c3NcIixcbiAgICAgICAgICAgICAgICBhbGlhczogXCJkYXRldGltZVwiLFxuICAgICAgICAgICAgICAgIGF1dG9Vbm1hc2s6ICExXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgXCJoaDptbVwiOiB7XG4gICAgICAgICAgICAgICAgbWFzazogXCJoOnNcIixcbiAgICAgICAgICAgICAgICBwbGFjZWhvbGRlcjogXCJoaDptbVwiLFxuICAgICAgICAgICAgICAgIGFsaWFzOiBcImRhdGV0aW1lXCIsXG4gICAgICAgICAgICAgICAgYXV0b1VubWFzazogITFcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBkYXRlOiB7XG4gICAgICAgICAgICAgICAgYWxpYXM6IFwiZGQvbW0veXl5eVwiXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgXCJtbS95eXl5XCI6IHtcbiAgICAgICAgICAgICAgICBtYXNrOiBcIjEveVwiLFxuICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyOiBcIm1tL3l5eXlcIixcbiAgICAgICAgICAgICAgICBsZWFwZGF5OiBcImRvbm90dXNlXCIsXG4gICAgICAgICAgICAgICAgc2VwYXJhdG9yOiBcIi9cIixcbiAgICAgICAgICAgICAgICBhbGlhczogXCJtbS9kZC95eXl5XCJcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBzaGFtc2k6IHtcbiAgICAgICAgICAgICAgICByZWdleDoge1xuICAgICAgICAgICAgICAgICAgICB2YWwycHJlOiBmdW5jdGlvbihzZXBhcmF0b3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBlc2NhcGVkU2VwYXJhdG9yID0gSW5wdXRtYXNrLmVzY2FwZVJlZ2V4LmNhbGwodGhpcywgc2VwYXJhdG9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgUmVnRXhwKFwiKCgwWzEtOV18MVswMTJdKVwiICsgZXNjYXBlZFNlcGFyYXRvciArIFwiWzAtM10pXCIpO1xuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICB2YWwyOiBmdW5jdGlvbihzZXBhcmF0b3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBlc2NhcGVkU2VwYXJhdG9yID0gSW5wdXRtYXNrLmVzY2FwZVJlZ2V4LmNhbGwodGhpcywgc2VwYXJhdG9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgUmVnRXhwKFwiKCgwWzEtOV18MVswMTJdKVwiICsgZXNjYXBlZFNlcGFyYXRvciArIFwiKDBbMS05XXxbMTJdWzAtOV0pKXwoKDBbMS05XXwxWzAxMl0pXCIgKyBlc2NhcGVkU2VwYXJhdG9yICsgXCIzMCl8KCgwWzEtNl0pXCIgKyBlc2NhcGVkU2VwYXJhdG9yICsgXCIzMSlcIik7XG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIHZhbDFwcmU6IG5ldyBSZWdFeHAoXCJbMDFdXCIpLFxuICAgICAgICAgICAgICAgICAgICB2YWwxOiBuZXcgUmVnRXhwKFwiMFsxLTldfDFbMDEyXVwiKVxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgeWVhcnJhbmdlOiB7XG4gICAgICAgICAgICAgICAgICAgIG1pbnllYXI6IDEzMDAsXG4gICAgICAgICAgICAgICAgICAgIG1heHllYXI6IDE0OTlcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIG1hc2s6IFwieS8xLzJcIixcbiAgICAgICAgICAgICAgICBsZWFwZGF5OiBcIi8xMi8zMFwiLFxuICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyOiBcInl5eXkvbW0vZGRcIixcbiAgICAgICAgICAgICAgICBhbGlhczogXCJtbS9kZC95eXl5XCIsXG4gICAgICAgICAgICAgICAgY2xlYXJJbmNvbXBsZXRlOiAhMFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIFwieXl5eS1tbS1kZCBoaDptbTpzc1wiOiB7XG4gICAgICAgICAgICAgICAgbWFzazogXCJ5LTEtMiBoOnM6c1wiLFxuICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyOiBcInl5eXktbW0tZGQgaGg6bW06c3NcIixcbiAgICAgICAgICAgICAgICBhbGlhczogXCJkYXRldGltZVwiLFxuICAgICAgICAgICAgICAgIHNlcGFyYXRvcjogXCItXCIsXG4gICAgICAgICAgICAgICAgbGVhcGRheTogXCItMDItMjlcIixcbiAgICAgICAgICAgICAgICByZWdleDoge1xuICAgICAgICAgICAgICAgICAgICB2YWwycHJlOiBmdW5jdGlvbihzZXBhcmF0b3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBlc2NhcGVkU2VwYXJhdG9yID0gSW5wdXRtYXNrLmVzY2FwZVJlZ2V4LmNhbGwodGhpcywgc2VwYXJhdG9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgUmVnRXhwKFwiKCgwWzEzLTldfDFbMDEyXSlcIiArIGVzY2FwZWRTZXBhcmF0b3IgKyBcIlswLTNdKXwoMDJcIiArIGVzY2FwZWRTZXBhcmF0b3IgKyBcIlswLTJdKVwiKTtcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgdmFsMjogZnVuY3Rpb24oc2VwYXJhdG9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgZXNjYXBlZFNlcGFyYXRvciA9IElucHV0bWFzay5lc2NhcGVSZWdleC5jYWxsKHRoaXMsIHNlcGFyYXRvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IFJlZ0V4cChcIigoMFsxLTldfDFbMDEyXSlcIiArIGVzY2FwZWRTZXBhcmF0b3IgKyBcIigwWzEtOV18WzEyXVswLTldKSl8KCgwWzEzLTldfDFbMDEyXSlcIiArIGVzY2FwZWRTZXBhcmF0b3IgKyBcIjMwKXwoKDBbMTM1NzhdfDFbMDJdKVwiICsgZXNjYXBlZFNlcGFyYXRvciArIFwiMzEpXCIpO1xuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICB2YWwxcHJlOiBuZXcgUmVnRXhwKFwiWzAxXVwiKSxcbiAgICAgICAgICAgICAgICAgICAgdmFsMTogbmV3IFJlZ0V4cChcIjBbMS05XXwxWzAxMl1cIilcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIG9uS2V5RG93bjogZnVuY3Rpb24oZSwgYnVmZmVyLCBjYXJldFBvcywgb3B0cykge31cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSksIElucHV0bWFzaztcbiAgICB9KTtcbn0sIGZ1bmN0aW9uKG1vZHVsZSwgZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykge1xuICAgIFwidXNlIHN0cmljdFwiO1xuICAgIHZhciBfX1dFQlBBQ0tfQU1EX0RFRklORV9SRVNVTFRfXztcbiAgICBcImZ1bmN0aW9uXCIgPT0gdHlwZW9mIFN5bWJvbCAmJiBTeW1ib2wuaXRlcmF0b3I7XG4gICAgdm9pZCAwICE9PSAoX19XRUJQQUNLX0FNRF9ERUZJTkVfUkVTVUxUX18gPSBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIHdpbmRvdztcbiAgICB9LmNhbGwoZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXywgZXhwb3J0cywgbW9kdWxlKSkgJiYgKG1vZHVsZS5leHBvcnRzID0gX19XRUJQQUNLX0FNRF9ERUZJTkVfUkVTVUxUX18pO1xufSwgZnVuY3Rpb24obW9kdWxlLCBleHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSB7XG4gICAgXCJ1c2Ugc3RyaWN0XCI7XG4gICAgdmFyIF9fV0VCUEFDS19BTURfREVGSU5FX1JFU1VMVF9fO1xuICAgIFwiZnVuY3Rpb25cIiA9PSB0eXBlb2YgU3ltYm9sICYmIFN5bWJvbC5pdGVyYXRvcjtcbiAgICB2b2lkIDAgIT09IChfX1dFQlBBQ0tfQU1EX0RFRklORV9SRVNVTFRfXyA9IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gZG9jdW1lbnQ7XG4gICAgfS5jYWxsKGV4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18sIGV4cG9ydHMsIG1vZHVsZSkpICYmIChtb2R1bGUuZXhwb3J0cyA9IF9fV0VCUEFDS19BTURfREVGSU5FX1JFU1VMVF9fKTtcbn0sIGZ1bmN0aW9uKG1vZHVsZSwgZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykge1xuICAgIFwidXNlIHN0cmljdFwiO1xuICAgIHZhciBfX1dFQlBBQ0tfQU1EX0RFRklORV9GQUNUT1JZX18sIF9fV0VCUEFDS19BTURfREVGSU5FX0FSUkFZX18sIF9fV0VCUEFDS19BTURfREVGSU5FX1JFU1VMVF9fO1xuICAgIFwiZnVuY3Rpb25cIiA9PSB0eXBlb2YgU3ltYm9sICYmIFN5bWJvbC5pdGVyYXRvcjtcbiAgICAhZnVuY3Rpb24oZmFjdG9yeSkge1xuICAgICAgICBfX1dFQlBBQ0tfQU1EX0RFRklORV9BUlJBWV9fID0gWyBfX3dlYnBhY2tfcmVxdWlyZV9fKDApLCBfX3dlYnBhY2tfcmVxdWlyZV9fKDEpIF0sIFxuICAgICAgICB2b2lkIDAgIT09IChfX1dFQlBBQ0tfQU1EX0RFRklORV9SRVNVTFRfXyA9IFwiZnVuY3Rpb25cIiA9PSB0eXBlb2YgKF9fV0VCUEFDS19BTURfREVGSU5FX0ZBQ1RPUllfXyA9IGZhY3RvcnkpID8gX19XRUJQQUNLX0FNRF9ERUZJTkVfRkFDVE9SWV9fLmFwcGx5KGV4cG9ydHMsIF9fV0VCUEFDS19BTURfREVGSU5FX0FSUkFZX18pIDogX19XRUJQQUNLX0FNRF9ERUZJTkVfRkFDVE9SWV9fKSAmJiAobW9kdWxlLmV4cG9ydHMgPSBfX1dFQlBBQ0tfQU1EX0RFRklORV9SRVNVTFRfXyk7XG4gICAgfShmdW5jdGlvbigkLCBJbnB1dG1hc2spIHtcbiAgICAgICAgcmV0dXJuIElucHV0bWFzay5leHRlbmREZWZpbml0aW9ucyh7XG4gICAgICAgICAgICBBOiB7XG4gICAgICAgICAgICAgICAgdmFsaWRhdG9yOiBcIltBLVphLXrQkC3Rj9CB0ZHDgC3Dv8K1XVwiLFxuICAgICAgICAgICAgICAgIGNhcmRpbmFsaXR5OiAxLFxuICAgICAgICAgICAgICAgIGNhc2luZzogXCJ1cHBlclwiXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgXCImXCI6IHtcbiAgICAgICAgICAgICAgICB2YWxpZGF0b3I6IFwiWzAtOUEtWmEtetCQLdGP0IHRkcOALcO/wrVdXCIsXG4gICAgICAgICAgICAgICAgY2FyZGluYWxpdHk6IDEsXG4gICAgICAgICAgICAgICAgY2FzaW5nOiBcInVwcGVyXCJcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBcIiNcIjoge1xuICAgICAgICAgICAgICAgIHZhbGlkYXRvcjogXCJbMC05QS1GYS1mXVwiLFxuICAgICAgICAgICAgICAgIGNhcmRpbmFsaXR5OiAxLFxuICAgICAgICAgICAgICAgIGNhc2luZzogXCJ1cHBlclwiXG4gICAgICAgICAgICB9XG4gICAgICAgIH0pLCBJbnB1dG1hc2suZXh0ZW5kQWxpYXNlcyh7XG4gICAgICAgICAgICB1cmw6IHtcbiAgICAgICAgICAgICAgICBkZWZpbml0aW9uczoge1xuICAgICAgICAgICAgICAgICAgICBpOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YWxpZGF0b3I6IFwiLlwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgY2FyZGluYWxpdHk6IDFcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgbWFzazogXCIoXFxcXGh0dHA6Ly8pfChcXFxcaHR0cFxcXFxzOi8vKXwoZnRwOi8vKXwoZnRwXFxcXHM6Ly8paXsrfVwiLFxuICAgICAgICAgICAgICAgIGluc2VydE1vZGU6ICExLFxuICAgICAgICAgICAgICAgIGF1dG9Vbm1hc2s6ICExLFxuICAgICAgICAgICAgICAgIGlucHV0bW9kZTogXCJ1cmxcIlxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGlwOiB7XG4gICAgICAgICAgICAgICAgbWFzazogXCJpW2lbaV1dLmlbaVtpXV0uaVtpW2ldXS5pW2lbaV1dXCIsXG4gICAgICAgICAgICAgICAgZGVmaW5pdGlvbnM6IHtcbiAgICAgICAgICAgICAgICAgICAgaToge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFsaWRhdG9yOiBmdW5jdGlvbihjaHJzLCBtYXNrc2V0LCBwb3MsIHN0cmljdCwgb3B0cykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBwb3MgLSAxID4gLTEgJiYgXCIuXCIgIT09IG1hc2tzZXQuYnVmZmVyW3BvcyAtIDFdID8gKGNocnMgPSBtYXNrc2V0LmJ1ZmZlcltwb3MgLSAxXSArIGNocnMsIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNocnMgPSBwb3MgLSAyID4gLTEgJiYgXCIuXCIgIT09IG1hc2tzZXQuYnVmZmVyW3BvcyAtIDJdID8gbWFza3NldC5idWZmZXJbcG9zIC0gMl0gKyBjaHJzIDogXCIwXCIgKyBjaHJzKSA6IGNocnMgPSBcIjAwXCIgKyBjaHJzLCBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXcgUmVnRXhwKFwiMjVbMC01XXwyWzAtNF1bMC05XXxbMDFdWzAtOV1bMC05XVwiKS50ZXN0KGNocnMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhcmRpbmFsaXR5OiAxXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIG9uVW5NYXNrOiBmdW5jdGlvbihtYXNrZWRWYWx1ZSwgdW5tYXNrZWRWYWx1ZSwgb3B0cykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbWFza2VkVmFsdWU7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBpbnB1dG1vZGU6IFwibnVtZXJpY1wiXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZW1haWw6IHtcbiAgICAgICAgICAgICAgICBtYXNrOiBcIip7MSw2NH1bLip7MSw2NH1dWy4qezEsNjR9XVsuKnsxLDYzfV1ALXsxLDYzfS4tezEsNjN9Wy4tezEsNjN9XVsuLXsxLDYzfV1cIixcbiAgICAgICAgICAgICAgICBncmVlZHk6ICExLFxuICAgICAgICAgICAgICAgIG9uQmVmb3JlUGFzdGU6IGZ1bmN0aW9uKHBhc3RlZFZhbHVlLCBvcHRzKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAocGFzdGVkVmFsdWUgPSBwYXN0ZWRWYWx1ZS50b0xvd2VyQ2FzZSgpKS5yZXBsYWNlKFwibWFpbHRvOlwiLCBcIlwiKTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGRlZmluaXRpb25zOiB7XG4gICAgICAgICAgICAgICAgICAgIFwiKlwiOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YWxpZGF0b3I6IFwiWzAtOUEtWmEteiEjJCUmJyorLz0/Xl9ge3x9fi1dXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICBjYXJkaW5hbGl0eTogMSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2luZzogXCJsb3dlclwiXG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIFwiLVwiOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YWxpZGF0b3I6IFwiWzAtOUEtWmEtei1dXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICBjYXJkaW5hbGl0eTogMSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2luZzogXCJsb3dlclwiXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIG9uVW5NYXNrOiBmdW5jdGlvbihtYXNrZWRWYWx1ZSwgdW5tYXNrZWRWYWx1ZSwgb3B0cykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbWFza2VkVmFsdWU7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBpbnB1dG1vZGU6IFwiZW1haWxcIlxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG1hYzoge1xuICAgICAgICAgICAgICAgIG1hc2s6IFwiIyM6IyM6IyM6IyM6IyM6IyNcIlxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHZpbjoge1xuICAgICAgICAgICAgICAgIG1hc2s6IFwiVnsxM305ezR9XCIsXG4gICAgICAgICAgICAgICAgZGVmaW5pdGlvbnM6IHtcbiAgICAgICAgICAgICAgICAgICAgVjoge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFsaWRhdG9yOiBcIltBLUhKLU5QUi1aYS1oai1ucHItelxcXFxkXVwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgY2FyZGluYWxpdHk6IDEsXG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNpbmc6IFwidXBwZXJcIlxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBjbGVhckluY29tcGxldGU6ICEwLFxuICAgICAgICAgICAgICAgIGF1dG9Vbm1hc2s6ICEwXG4gICAgICAgICAgICB9XG4gICAgICAgIH0pLCBJbnB1dG1hc2s7XG4gICAgfSk7XG59LCBmdW5jdGlvbihtb2R1bGUsIGV4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pIHtcbiAgICBcInVzZSBzdHJpY3RcIjtcbiAgICB2YXIgX19XRUJQQUNLX0FNRF9ERUZJTkVfRkFDVE9SWV9fLCBfX1dFQlBBQ0tfQU1EX0RFRklORV9BUlJBWV9fLCBfX1dFQlBBQ0tfQU1EX0RFRklORV9SRVNVTFRfXztcbiAgICBcImZ1bmN0aW9uXCIgPT0gdHlwZW9mIFN5bWJvbCAmJiBTeW1ib2wuaXRlcmF0b3I7XG4gICAgIWZ1bmN0aW9uKGZhY3RvcnkpIHtcbiAgICAgICAgX19XRUJQQUNLX0FNRF9ERUZJTkVfQVJSQVlfXyA9IFsgX193ZWJwYWNrX3JlcXVpcmVfXygwKSwgX193ZWJwYWNrX3JlcXVpcmVfXygxKSBdLCBcbiAgICAgICAgdm9pZCAwICE9PSAoX19XRUJQQUNLX0FNRF9ERUZJTkVfUkVTVUxUX18gPSBcImZ1bmN0aW9uXCIgPT0gdHlwZW9mIChfX1dFQlBBQ0tfQU1EX0RFRklORV9GQUNUT1JZX18gPSBmYWN0b3J5KSA/IF9fV0VCUEFDS19BTURfREVGSU5FX0ZBQ1RPUllfXy5hcHBseShleHBvcnRzLCBfX1dFQlBBQ0tfQU1EX0RFRklORV9BUlJBWV9fKSA6IF9fV0VCUEFDS19BTURfREVGSU5FX0ZBQ1RPUllfXykgJiYgKG1vZHVsZS5leHBvcnRzID0gX19XRUJQQUNLX0FNRF9ERUZJTkVfUkVTVUxUX18pO1xuICAgIH0oZnVuY3Rpb24oJCwgSW5wdXRtYXNrLCB1bmRlZmluZWQpIHtcbiAgICAgICAgZnVuY3Rpb24gYXV0b0VzY2FwZSh0eHQsIG9wdHMpIHtcbiAgICAgICAgICAgIGZvciAodmFyIGVzY2FwZWRUeHQgPSBcIlwiLCBpID0gMDsgaSA8IHR4dC5sZW5ndGg7IGkrKykgSW5wdXRtYXNrLnByb3RvdHlwZS5kZWZpbml0aW9uc1t0eHQuY2hhckF0KGkpXSB8fCBvcHRzLmRlZmluaXRpb25zW3R4dC5jaGFyQXQoaSldIHx8IG9wdHMub3B0aW9uYWxtYXJrZXIuc3RhcnQgPT09IHR4dC5jaGFyQXQoaSkgfHwgb3B0cy5vcHRpb25hbG1hcmtlci5lbmQgPT09IHR4dC5jaGFyQXQoaSkgfHwgb3B0cy5xdWFudGlmaWVybWFya2VyLnN0YXJ0ID09PSB0eHQuY2hhckF0KGkpIHx8IG9wdHMucXVhbnRpZmllcm1hcmtlci5lbmQgPT09IHR4dC5jaGFyQXQoaSkgfHwgb3B0cy5ncm91cG1hcmtlci5zdGFydCA9PT0gdHh0LmNoYXJBdChpKSB8fCBvcHRzLmdyb3VwbWFya2VyLmVuZCA9PT0gdHh0LmNoYXJBdChpKSB8fCBvcHRzLmFsdGVybmF0b3JtYXJrZXIgPT09IHR4dC5jaGFyQXQoaSkgPyBlc2NhcGVkVHh0ICs9IFwiXFxcXFwiICsgdHh0LmNoYXJBdChpKSA6IGVzY2FwZWRUeHQgKz0gdHh0LmNoYXJBdChpKTtcbiAgICAgICAgICAgIHJldHVybiBlc2NhcGVkVHh0O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBJbnB1dG1hc2suZXh0ZW5kQWxpYXNlcyh7XG4gICAgICAgICAgICBudW1lcmljOiB7XG4gICAgICAgICAgICAgICAgbWFzazogZnVuY3Rpb24ob3B0cykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoMCAhPT0gb3B0cy5yZXBlYXQgJiYgaXNOYU4ob3B0cy5pbnRlZ2VyRGlnaXRzKSAmJiAob3B0cy5pbnRlZ2VyRGlnaXRzID0gb3B0cy5yZXBlYXQpLCBcbiAgICAgICAgICAgICAgICAgICAgb3B0cy5yZXBlYXQgPSAwLCBvcHRzLmdyb3VwU2VwYXJhdG9yID09PSBvcHRzLnJhZGl4UG9pbnQgJiYgKFwiLlwiID09PSBvcHRzLnJhZGl4UG9pbnQgPyBvcHRzLmdyb3VwU2VwYXJhdG9yID0gXCIsXCIgOiBcIixcIiA9PT0gb3B0cy5yYWRpeFBvaW50ID8gb3B0cy5ncm91cFNlcGFyYXRvciA9IFwiLlwiIDogb3B0cy5ncm91cFNlcGFyYXRvciA9IFwiXCIpLCBcbiAgICAgICAgICAgICAgICAgICAgXCIgXCIgPT09IG9wdHMuZ3JvdXBTZXBhcmF0b3IgJiYgKG9wdHMuc2tpcE9wdGlvbmFsUGFydENoYXJhY3RlciA9IHVuZGVmaW5lZCksIG9wdHMuYXV0b0dyb3VwID0gb3B0cy5hdXRvR3JvdXAgJiYgXCJcIiAhPT0gb3B0cy5ncm91cFNlcGFyYXRvciwgXG4gICAgICAgICAgICAgICAgICAgIG9wdHMuYXV0b0dyb3VwICYmIChcInN0cmluZ1wiID09IHR5cGVvZiBvcHRzLmdyb3VwU2l6ZSAmJiBpc0Zpbml0ZShvcHRzLmdyb3VwU2l6ZSkgJiYgKG9wdHMuZ3JvdXBTaXplID0gcGFyc2VJbnQob3B0cy5ncm91cFNpemUpKSwgXG4gICAgICAgICAgICAgICAgICAgIGlzRmluaXRlKG9wdHMuaW50ZWdlckRpZ2l0cykpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgc2VwcyA9IE1hdGguZmxvb3Iob3B0cy5pbnRlZ2VyRGlnaXRzIC8gb3B0cy5ncm91cFNpemUpLCBtb2QgPSBvcHRzLmludGVnZXJEaWdpdHMgJSBvcHRzLmdyb3VwU2l6ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIG9wdHMuaW50ZWdlckRpZ2l0cyA9IHBhcnNlSW50KG9wdHMuaW50ZWdlckRpZ2l0cykgKyAoMCA9PT0gbW9kID8gc2VwcyAtIDEgOiBzZXBzKSwgXG4gICAgICAgICAgICAgICAgICAgICAgICBvcHRzLmludGVnZXJEaWdpdHMgPCAxICYmIChvcHRzLmludGVnZXJEaWdpdHMgPSBcIipcIik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgb3B0cy5wbGFjZWhvbGRlci5sZW5ndGggPiAxICYmIChvcHRzLnBsYWNlaG9sZGVyID0gb3B0cy5wbGFjZWhvbGRlci5jaGFyQXQoMCkpLCBcbiAgICAgICAgICAgICAgICAgICAgXCJyYWRpeEZvY3VzXCIgPT09IG9wdHMucG9zaXRpb25DYXJldE9uQ2xpY2sgJiYgXCJcIiA9PT0gb3B0cy5wbGFjZWhvbGRlciAmJiAhMSA9PT0gb3B0cy5pbnRlZ2VyT3B0aW9uYWwgJiYgKG9wdHMucG9zaXRpb25DYXJldE9uQ2xpY2sgPSBcImx2cFwiKSwgXG4gICAgICAgICAgICAgICAgICAgIG9wdHMuZGVmaW5pdGlvbnNbXCI7XCJdID0gb3B0cy5kZWZpbml0aW9uc1tcIn5cIl0sIG9wdHMuZGVmaW5pdGlvbnNbXCI7XCJdLmRlZmluaXRpb25TeW1ib2wgPSBcIn5cIiwgXG4gICAgICAgICAgICAgICAgICAgICEwID09PSBvcHRzLm51bWVyaWNJbnB1dCAmJiAob3B0cy5wb3NpdGlvbkNhcmV0T25DbGljayA9IFwicmFkaXhGb2N1c1wiID09PSBvcHRzLnBvc2l0aW9uQ2FyZXRPbkNsaWNrID8gXCJsdnBcIiA6IG9wdHMucG9zaXRpb25DYXJldE9uQ2xpY2ssIFxuICAgICAgICAgICAgICAgICAgICBvcHRzLmRpZ2l0c09wdGlvbmFsID0gITEsIGlzTmFOKG9wdHMuZGlnaXRzKSAmJiAob3B0cy5kaWdpdHMgPSAyKSwgb3B0cy5kZWNpbWFsUHJvdGVjdCA9ICExKTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG1hc2sgPSBcIlsrXVwiO1xuICAgICAgICAgICAgICAgICAgICBpZiAobWFzayArPSBhdXRvRXNjYXBlKG9wdHMucHJlZml4LCBvcHRzKSwgITAgPT09IG9wdHMuaW50ZWdlck9wdGlvbmFsID8gbWFzayArPSBcIn57MSxcIiArIG9wdHMuaW50ZWdlckRpZ2l0cyArIFwifVwiIDogbWFzayArPSBcIn57XCIgKyBvcHRzLmludGVnZXJEaWdpdHMgKyBcIn1cIiwgXG4gICAgICAgICAgICAgICAgICAgIG9wdHMuZGlnaXRzICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG9wdHMucmFkaXhQb2ludERlZmluaXRpb25TeW1ib2wgPSBvcHRzLmRlY2ltYWxQcm90ZWN0ID8gXCI6XCIgOiBvcHRzLnJhZGl4UG9pbnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgZHEgPSBvcHRzLmRpZ2l0cy50b1N0cmluZygpLnNwbGl0KFwiLFwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlzRmluaXRlKGRxWzBdICYmIGRxWzFdICYmIGlzRmluaXRlKGRxWzFdKSkgPyBtYXNrICs9IG9wdHMucmFkaXhQb2ludERlZmluaXRpb25TeW1ib2wgKyBcIjt7XCIgKyBvcHRzLmRpZ2l0cyArIFwifVwiIDogKGlzTmFOKG9wdHMuZGlnaXRzKSB8fCBwYXJzZUludChvcHRzLmRpZ2l0cykgPiAwKSAmJiAob3B0cy5kaWdpdHNPcHRpb25hbCA/IG1hc2sgKz0gXCJbXCIgKyBvcHRzLnJhZGl4UG9pbnREZWZpbml0aW9uU3ltYm9sICsgXCI7ezEsXCIgKyBvcHRzLmRpZ2l0cyArIFwifV1cIiA6IG1hc2sgKz0gb3B0cy5yYWRpeFBvaW50RGVmaW5pdGlvblN5bWJvbCArIFwiO3tcIiArIG9wdHMuZGlnaXRzICsgXCJ9XCIpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBtYXNrICs9IGF1dG9Fc2NhcGUob3B0cy5zdWZmaXgsIG9wdHMpLCBtYXNrICs9IFwiWy1dXCIsIG9wdHMuZ3JlZWR5ID0gITEsIG1hc2s7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBwbGFjZWhvbGRlcjogXCJcIixcbiAgICAgICAgICAgICAgICBncmVlZHk6ICExLFxuICAgICAgICAgICAgICAgIGRpZ2l0czogXCIqXCIsXG4gICAgICAgICAgICAgICAgZGlnaXRzT3B0aW9uYWw6ICEwLFxuICAgICAgICAgICAgICAgIGVuZm9yY2VEaWdpdHNPbkJsdXI6ICExLFxuICAgICAgICAgICAgICAgIHJhZGl4UG9pbnQ6IFwiLlwiLFxuICAgICAgICAgICAgICAgIHBvc2l0aW9uQ2FyZXRPbkNsaWNrOiBcInJhZGl4Rm9jdXNcIixcbiAgICAgICAgICAgICAgICBncm91cFNpemU6IDMsXG4gICAgICAgICAgICAgICAgZ3JvdXBTZXBhcmF0b3I6IFwiXCIsXG4gICAgICAgICAgICAgICAgYXV0b0dyb3VwOiAhMSxcbiAgICAgICAgICAgICAgICBhbGxvd01pbnVzOiAhMCxcbiAgICAgICAgICAgICAgICBuZWdhdGlvblN5bWJvbDoge1xuICAgICAgICAgICAgICAgICAgICBmcm9udDogXCItXCIsXG4gICAgICAgICAgICAgICAgICAgIGJhY2s6IFwiXCJcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGludGVnZXJEaWdpdHM6IFwiK1wiLFxuICAgICAgICAgICAgICAgIGludGVnZXJPcHRpb25hbDogITAsXG4gICAgICAgICAgICAgICAgcHJlZml4OiBcIlwiLFxuICAgICAgICAgICAgICAgIHN1ZmZpeDogXCJcIixcbiAgICAgICAgICAgICAgICByaWdodEFsaWduOiAhMCxcbiAgICAgICAgICAgICAgICBkZWNpbWFsUHJvdGVjdDogITAsXG4gICAgICAgICAgICAgICAgbWluOiBudWxsLFxuICAgICAgICAgICAgICAgIG1heDogbnVsbCxcbiAgICAgICAgICAgICAgICBzdGVwOiAxLFxuICAgICAgICAgICAgICAgIGluc2VydE1vZGU6ICEwLFxuICAgICAgICAgICAgICAgIGF1dG9Vbm1hc2s6ICExLFxuICAgICAgICAgICAgICAgIHVubWFza0FzTnVtYmVyOiAhMSxcbiAgICAgICAgICAgICAgICBpbnB1dG1vZGU6IFwibnVtZXJpY1wiLFxuICAgICAgICAgICAgICAgIHByZVZhbGlkYXRpb246IGZ1bmN0aW9uKGJ1ZmZlciwgcG9zLCBjLCBpc1NlbGVjdGlvbiwgb3B0cykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoXCItXCIgPT09IGMgfHwgYyA9PT0gb3B0cy5uZWdhdGlvblN5bWJvbC5mcm9udCkgcmV0dXJuICEwID09PSBvcHRzLmFsbG93TWludXMgJiYgKG9wdHMuaXNOZWdhdGl2ZSA9IG9wdHMuaXNOZWdhdGl2ZSA9PT0gdW5kZWZpbmVkIHx8ICFvcHRzLmlzTmVnYXRpdmUsIFxuICAgICAgICAgICAgICAgICAgICBcIlwiID09PSBidWZmZXIuam9pbihcIlwiKSB8fCB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXJldDogcG9zLFxuICAgICAgICAgICAgICAgICAgICAgICAgZG9wb3N0OiAhMFxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCExID09PSBpc1NlbGVjdGlvbiAmJiBjID09PSBvcHRzLnJhZGl4UG9pbnQgJiYgb3B0cy5kaWdpdHMgIT09IHVuZGVmaW5lZCAmJiAoaXNOYU4ob3B0cy5kaWdpdHMpIHx8IHBhcnNlSW50KG9wdHMuZGlnaXRzKSA+IDApKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgcmFkaXhQb3MgPSAkLmluQXJyYXkob3B0cy5yYWRpeFBvaW50LCBidWZmZXIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKC0xICE9PSByYWRpeFBvcykgcmV0dXJuICEwID09PSBvcHRzLm51bWVyaWNJbnB1dCA/IHBvcyA9PT0gcmFkaXhQb3MgOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FyZXQ6IHJhZGl4UG9zICsgMVxuICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gITA7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBwb3N0VmFsaWRhdGlvbjogZnVuY3Rpb24oYnVmZmVyLCBjdXJyZW50UmVzdWx0LCBvcHRzKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBzdWZmaXggPSBvcHRzLnN1ZmZpeC5zcGxpdChcIlwiKSwgcHJlZml4ID0gb3B0cy5wcmVmaXguc3BsaXQoXCJcIik7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjdXJyZW50UmVzdWx0LnBvcyA9PT0gdW5kZWZpbmVkICYmIGN1cnJlbnRSZXN1bHQuY2FyZXQgIT09IHVuZGVmaW5lZCAmJiAhMCAhPT0gY3VycmVudFJlc3VsdC5kb3Bvc3QpIHJldHVybiBjdXJyZW50UmVzdWx0O1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2FyZXRQb3MgPSBjdXJyZW50UmVzdWx0LmNhcmV0ICE9PSB1bmRlZmluZWQgPyBjdXJyZW50UmVzdWx0LmNhcmV0IDogY3VycmVudFJlc3VsdC5wb3MsIG1hc2tlZFZhbHVlID0gYnVmZmVyLnNsaWNlKCk7XG4gICAgICAgICAgICAgICAgICAgIG9wdHMubnVtZXJpY0lucHV0ICYmIChjYXJldFBvcyA9IG1hc2tlZFZhbHVlLmxlbmd0aCAtIGNhcmV0UG9zIC0gMSwgbWFza2VkVmFsdWUgPSBtYXNrZWRWYWx1ZS5yZXZlcnNlKCkpO1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hhckF0UG9zID0gbWFza2VkVmFsdWVbY2FyZXRQb3NdO1xuICAgICAgICAgICAgICAgICAgICBpZiAoY2hhckF0UG9zID09PSBvcHRzLmdyb3VwU2VwYXJhdG9yICYmIChjaGFyQXRQb3MgPSBtYXNrZWRWYWx1ZVtjYXJldFBvcyArPSAxXSksIFxuICAgICAgICAgICAgICAgICAgICBjYXJldFBvcyA9PT0gbWFza2VkVmFsdWUubGVuZ3RoIC0gb3B0cy5zdWZmaXgubGVuZ3RoIC0gMSAmJiBjaGFyQXRQb3MgPT09IG9wdHMucmFkaXhQb2ludCkgcmV0dXJuIGN1cnJlbnRSZXN1bHQ7XG4gICAgICAgICAgICAgICAgICAgIGNoYXJBdFBvcyAhPT0gdW5kZWZpbmVkICYmIGNoYXJBdFBvcyAhPT0gb3B0cy5yYWRpeFBvaW50ICYmIGNoYXJBdFBvcyAhPT0gb3B0cy5uZWdhdGlvblN5bWJvbC5mcm9udCAmJiBjaGFyQXRQb3MgIT09IG9wdHMubmVnYXRpb25TeW1ib2wuYmFjayAmJiAobWFza2VkVmFsdWVbY2FyZXRQb3NdID0gXCI/XCIsIFxuICAgICAgICAgICAgICAgICAgICBvcHRzLnByZWZpeC5sZW5ndGggPiAwICYmIGNhcmV0UG9zID49ICghMSA9PT0gb3B0cy5pc05lZ2F0aXZlID8gMSA6IDApICYmIGNhcmV0UG9zIDwgb3B0cy5wcmVmaXgubGVuZ3RoIC0gMSArICghMSA9PT0gb3B0cy5pc05lZ2F0aXZlID8gMSA6IDApID8gcHJlZml4W2NhcmV0UG9zIC0gKCExID09PSBvcHRzLmlzTmVnYXRpdmUgPyAxIDogMCldID0gXCI/XCIgOiBvcHRzLnN1ZmZpeC5sZW5ndGggPiAwICYmIGNhcmV0UG9zID49IG1hc2tlZFZhbHVlLmxlbmd0aCAtIG9wdHMuc3VmZml4Lmxlbmd0aCAtICghMSA9PT0gb3B0cy5pc05lZ2F0aXZlID8gMSA6IDApICYmIChzdWZmaXhbY2FyZXRQb3MgLSAobWFza2VkVmFsdWUubGVuZ3RoIC0gb3B0cy5zdWZmaXgubGVuZ3RoIC0gKCExID09PSBvcHRzLmlzTmVnYXRpdmUgPyAxIDogMCkpXSA9IFwiP1wiKSksIFxuICAgICAgICAgICAgICAgICAgICBwcmVmaXggPSBwcmVmaXguam9pbihcIlwiKSwgc3VmZml4ID0gc3VmZml4LmpvaW4oXCJcIik7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwcm9jZXNzVmFsdWUgPSBtYXNrZWRWYWx1ZS5qb2luKFwiXCIpLnJlcGxhY2UocHJlZml4LCBcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHByb2Nlc3NWYWx1ZSA9IHByb2Nlc3NWYWx1ZS5yZXBsYWNlKHN1ZmZpeCwgXCJcIiksIHByb2Nlc3NWYWx1ZSA9IHByb2Nlc3NWYWx1ZS5yZXBsYWNlKG5ldyBSZWdFeHAoSW5wdXRtYXNrLmVzY2FwZVJlZ2V4KG9wdHMuZ3JvdXBTZXBhcmF0b3IpLCBcImdcIiksIFwiXCIpLCBcbiAgICAgICAgICAgICAgICAgICAgcHJvY2Vzc1ZhbHVlID0gcHJvY2Vzc1ZhbHVlLnJlcGxhY2UobmV3IFJlZ0V4cChcIlstXCIgKyBJbnB1dG1hc2suZXNjYXBlUmVnZXgob3B0cy5uZWdhdGlvblN5bWJvbC5mcm9udCkgKyBcIl1cIiwgXCJnXCIpLCBcIlwiKSwgXG4gICAgICAgICAgICAgICAgICAgIHByb2Nlc3NWYWx1ZSA9IHByb2Nlc3NWYWx1ZS5yZXBsYWNlKG5ldyBSZWdFeHAoSW5wdXRtYXNrLmVzY2FwZVJlZ2V4KG9wdHMubmVnYXRpb25TeW1ib2wuYmFjaykgKyBcIiRcIiksIFwiXCIpLCBcbiAgICAgICAgICAgICAgICAgICAgaXNOYU4ob3B0cy5wbGFjZWhvbGRlcikgJiYgKHByb2Nlc3NWYWx1ZSA9IHByb2Nlc3NWYWx1ZS5yZXBsYWNlKG5ldyBSZWdFeHAoSW5wdXRtYXNrLmVzY2FwZVJlZ2V4KG9wdHMucGxhY2Vob2xkZXIpLCBcImdcIiksIFwiXCIpKSwgXG4gICAgICAgICAgICAgICAgICAgIHByb2Nlc3NWYWx1ZS5sZW5ndGggPiAxICYmIDEgIT09IHByb2Nlc3NWYWx1ZS5pbmRleE9mKG9wdHMucmFkaXhQb2ludCkgJiYgKFwiMFwiID09PSBjaGFyQXRQb3MgJiYgKHByb2Nlc3NWYWx1ZSA9IHByb2Nlc3NWYWx1ZS5yZXBsYWNlKC9eXFw/L2csIFwiXCIpKSwgXG4gICAgICAgICAgICAgICAgICAgIHByb2Nlc3NWYWx1ZSA9IHByb2Nlc3NWYWx1ZS5yZXBsYWNlKC9eMC9nLCBcIlwiKSksIHByb2Nlc3NWYWx1ZS5jaGFyQXQoMCkgPT09IG9wdHMucmFkaXhQb2ludCAmJiBcIlwiICE9PSBvcHRzLnJhZGl4UG9pbnQgJiYgITAgIT09IG9wdHMubnVtZXJpY0lucHV0ICYmIChwcm9jZXNzVmFsdWUgPSBcIjBcIiArIHByb2Nlc3NWYWx1ZSksIFxuICAgICAgICAgICAgICAgICAgICBcIlwiICE9PSBwcm9jZXNzVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9jZXNzVmFsdWUgPSBwcm9jZXNzVmFsdWUuc3BsaXQoXCJcIiksICghb3B0cy5kaWdpdHNPcHRpb25hbCB8fCBvcHRzLmVuZm9yY2VEaWdpdHNPbkJsdXIgJiYgXCJibHVyXCIgPT09IGN1cnJlbnRSZXN1bHQuZXZlbnQpICYmIGlzRmluaXRlKG9wdHMuZGlnaXRzKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciByYWRpeFBvc2l0aW9uID0gJC5pbkFycmF5KG9wdHMucmFkaXhQb2ludCwgcHJvY2Vzc1ZhbHVlKSwgcnBiID0gJC5pbkFycmF5KG9wdHMucmFkaXhQb2ludCwgbWFza2VkVmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC0xID09PSByYWRpeFBvc2l0aW9uICYmIChwcm9jZXNzVmFsdWUucHVzaChvcHRzLnJhZGl4UG9pbnQpLCByYWRpeFBvc2l0aW9uID0gcHJvY2Vzc1ZhbHVlLmxlbmd0aCAtIDEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAxOyBpIDw9IG9wdHMuZGlnaXRzOyBpKyspIG9wdHMuZGlnaXRzT3B0aW9uYWwgJiYgKCFvcHRzLmVuZm9yY2VEaWdpdHNPbkJsdXIgfHwgXCJibHVyXCIgIT09IGN1cnJlbnRSZXN1bHQuZXZlbnQpIHx8IHByb2Nlc3NWYWx1ZVtyYWRpeFBvc2l0aW9uICsgaV0gIT09IHVuZGVmaW5lZCAmJiBwcm9jZXNzVmFsdWVbcmFkaXhQb3NpdGlvbiArIGldICE9PSBvcHRzLnBsYWNlaG9sZGVyLmNoYXJBdCgwKSA/IC0xICE9PSBycGIgJiYgbWFza2VkVmFsdWVbcnBiICsgaV0gIT09IHVuZGVmaW5lZCAmJiAocHJvY2Vzc1ZhbHVlW3JhZGl4UG9zaXRpb24gKyBpXSA9IHByb2Nlc3NWYWx1ZVtyYWRpeFBvc2l0aW9uICsgaV0gfHwgbWFza2VkVmFsdWVbcnBiICsgaV0pIDogcHJvY2Vzc1ZhbHVlW3JhZGl4UG9zaXRpb24gKyBpXSA9IGN1cnJlbnRSZXN1bHQucGxhY2Vob2xkZXIgfHwgb3B0cy5wbGFjZWhvbGRlci5jaGFyQXQoMCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoITAgIT09IG9wdHMuYXV0b0dyb3VwIHx8IFwiXCIgPT09IG9wdHMuZ3JvdXBTZXBhcmF0b3IgfHwgY2hhckF0UG9zID09PSBvcHRzLnJhZGl4UG9pbnQgJiYgY3VycmVudFJlc3VsdC5wb3MgPT09IHVuZGVmaW5lZCAmJiAhY3VycmVudFJlc3VsdC5kb3Bvc3QpIHByb2Nlc3NWYWx1ZSA9IHByb2Nlc3NWYWx1ZS5qb2luKFwiXCIpOyBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgYWRkUmFkaXggPSBwcm9jZXNzVmFsdWVbcHJvY2Vzc1ZhbHVlLmxlbmd0aCAtIDFdID09PSBvcHRzLnJhZGl4UG9pbnQgJiYgY3VycmVudFJlc3VsdC5jID09PSBvcHRzLnJhZGl4UG9pbnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvY2Vzc1ZhbHVlID0gSW5wdXRtYXNrKGZ1bmN0aW9uKGJ1ZmZlciwgb3B0cykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgcG9zdE1hc2sgPSBcIlwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocG9zdE1hc2sgKz0gXCIoXCIgKyBvcHRzLmdyb3VwU2VwYXJhdG9yICsgXCIqe1wiICsgb3B0cy5ncm91cFNpemUgKyBcIn0peyp9XCIsIFwiXCIgIT09IG9wdHMucmFkaXhQb2ludCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHJhZGl4U3BsaXQgPSBidWZmZXIuam9pbihcIlwiKS5zcGxpdChvcHRzLnJhZGl4UG9pbnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmFkaXhTcGxpdFsxXSAmJiAocG9zdE1hc2sgKz0gb3B0cy5yYWRpeFBvaW50ICsgXCIqe1wiICsgcmFkaXhTcGxpdFsxXS5tYXRjaCgvXlxcZCpcXD8/XFxkKi8pWzBdLmxlbmd0aCArIFwifVwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcG9zdE1hc2s7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfShwcm9jZXNzVmFsdWUsIG9wdHMpLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG51bWVyaWNJbnB1dDogITAsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGppdE1hc2tpbmc6ICEwLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWZpbml0aW9uczoge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCIqXCI6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWxpZGF0b3I6IFwiWzAtOT9dXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FyZGluYWxpdHk6IDFcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pLmZvcm1hdChwcm9jZXNzVmFsdWUuam9pbihcIlwiKSksIGFkZFJhZGl4ICYmIChwcm9jZXNzVmFsdWUgKz0gb3B0cy5yYWRpeFBvaW50KSwgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvY2Vzc1ZhbHVlLmNoYXJBdCgwKSA9PT0gb3B0cy5ncm91cFNlcGFyYXRvciAmJiBwcm9jZXNzVmFsdWUuc3Vic3RyKDEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChvcHRzLmlzTmVnYXRpdmUgJiYgXCJibHVyXCIgPT09IGN1cnJlbnRSZXN1bHQuZXZlbnQgJiYgKG9wdHMuaXNOZWdhdGl2ZSA9IFwiMFwiICE9PSBwcm9jZXNzVmFsdWUpLCBcbiAgICAgICAgICAgICAgICAgICAgcHJvY2Vzc1ZhbHVlID0gcHJlZml4ICsgcHJvY2Vzc1ZhbHVlLCBwcm9jZXNzVmFsdWUgKz0gc3VmZml4LCBvcHRzLmlzTmVnYXRpdmUgJiYgKHByb2Nlc3NWYWx1ZSA9IG9wdHMubmVnYXRpb25TeW1ib2wuZnJvbnQgKyBwcm9jZXNzVmFsdWUsIFxuICAgICAgICAgICAgICAgICAgICBwcm9jZXNzVmFsdWUgKz0gb3B0cy5uZWdhdGlvblN5bWJvbC5iYWNrKSwgcHJvY2Vzc1ZhbHVlID0gcHJvY2Vzc1ZhbHVlLnNwbGl0KFwiXCIpLCBcbiAgICAgICAgICAgICAgICAgICAgY2hhckF0UG9zICE9PSB1bmRlZmluZWQpIGlmIChjaGFyQXRQb3MgIT09IG9wdHMucmFkaXhQb2ludCAmJiBjaGFyQXRQb3MgIT09IG9wdHMubmVnYXRpb25TeW1ib2wuZnJvbnQgJiYgY2hhckF0UG9zICE9PSBvcHRzLm5lZ2F0aW9uU3ltYm9sLmJhY2spIChjYXJldFBvcyA9ICQuaW5BcnJheShcIj9cIiwgcHJvY2Vzc1ZhbHVlKSkgPiAtMSA/IHByb2Nlc3NWYWx1ZVtjYXJldFBvc10gPSBjaGFyQXRQb3MgOiBjYXJldFBvcyA9IGN1cnJlbnRSZXN1bHQuY2FyZXQgfHwgMDsgZWxzZSBpZiAoY2hhckF0UG9zID09PSBvcHRzLnJhZGl4UG9pbnQgfHwgY2hhckF0UG9zID09PSBvcHRzLm5lZ2F0aW9uU3ltYm9sLmZyb250IHx8IGNoYXJBdFBvcyA9PT0gb3B0cy5uZWdhdGlvblN5bWJvbC5iYWNrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgbmV3Q2FyZXRQb3MgPSAkLmluQXJyYXkoY2hhckF0UG9zLCBwcm9jZXNzVmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgLTEgIT09IG5ld0NhcmV0UG9zICYmIChjYXJldFBvcyA9IG5ld0NhcmV0UG9zKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBvcHRzLm51bWVyaWNJbnB1dCAmJiAoY2FyZXRQb3MgPSBwcm9jZXNzVmFsdWUubGVuZ3RoIC0gY2FyZXRQb3MgLSAxLCBwcm9jZXNzVmFsdWUgPSBwcm9jZXNzVmFsdWUucmV2ZXJzZSgpKTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHJzbHQgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXJldDogY2hhckF0UG9zID09PSB1bmRlZmluZWQgfHwgY3VycmVudFJlc3VsdC5wb3MgIT09IHVuZGVmaW5lZCA/IGNhcmV0UG9zICsgKG9wdHMubnVtZXJpY0lucHV0ID8gLTEgOiAxKSA6IGNhcmV0UG9zLFxuICAgICAgICAgICAgICAgICAgICAgICAgYnVmZmVyOiBwcm9jZXNzVmFsdWUsXG4gICAgICAgICAgICAgICAgICAgICAgICByZWZyZXNoRnJvbUJ1ZmZlcjogY3VycmVudFJlc3VsdC5kb3Bvc3QgfHwgYnVmZmVyLmpvaW4oXCJcIikgIT09IHByb2Nlc3NWYWx1ZS5qb2luKFwiXCIpXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByc2x0LnJlZnJlc2hGcm9tQnVmZmVyID8gcnNsdCA6IGN1cnJlbnRSZXN1bHQ7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBvbkJlZm9yZVdyaXRlOiBmdW5jdGlvbihlLCBidWZmZXIsIGNhcmV0UG9zLCBvcHRzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlKSBzd2l0Y2ggKGUudHlwZSkge1xuICAgICAgICAgICAgICAgICAgICAgIGNhc2UgXCJrZXlkb3duXCI6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gb3B0cy5wb3N0VmFsaWRhdGlvbihidWZmZXIsIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXJldDogY2FyZXRQb3MsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZG9wb3N0OiAhMFxuICAgICAgICAgICAgICAgICAgICAgICAgfSwgb3B0cyk7XG5cbiAgICAgICAgICAgICAgICAgICAgICBjYXNlIFwiYmx1clwiOlxuICAgICAgICAgICAgICAgICAgICAgIGNhc2UgXCJjaGVja3ZhbFwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHVubWFza2VkO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGZ1bmN0aW9uKG9wdHMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcHRzLnBhcnNlTWluTWF4T3B0aW9ucyA9PT0gdW5kZWZpbmVkICYmIChudWxsICE9PSBvcHRzLm1pbiAmJiAob3B0cy5taW4gPSBvcHRzLm1pbi50b1N0cmluZygpLnJlcGxhY2UobmV3IFJlZ0V4cChJbnB1dG1hc2suZXNjYXBlUmVnZXgob3B0cy5ncm91cFNlcGFyYXRvciksIFwiZ1wiKSwgXCJcIiksIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiLFwiID09PSBvcHRzLnJhZGl4UG9pbnQgJiYgKG9wdHMubWluID0gb3B0cy5taW4ucmVwbGFjZShvcHRzLnJhZGl4UG9pbnQsIFwiLlwiKSksIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9wdHMubWluID0gaXNGaW5pdGUob3B0cy5taW4pID8gcGFyc2VGbG9hdChvcHRzLm1pbikgOiBOYU4sIGlzTmFOKG9wdHMubWluKSAmJiAob3B0cy5taW4gPSBOdW1iZXIuTUlOX1ZBTFVFKSksIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG51bGwgIT09IG9wdHMubWF4ICYmIChvcHRzLm1heCA9IG9wdHMubWF4LnRvU3RyaW5nKCkucmVwbGFjZShuZXcgUmVnRXhwKElucHV0bWFzay5lc2NhcGVSZWdleChvcHRzLmdyb3VwU2VwYXJhdG9yKSwgXCJnXCIpLCBcIlwiKSwgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXCIsXCIgPT09IG9wdHMucmFkaXhQb2ludCAmJiAob3B0cy5tYXggPSBvcHRzLm1heC5yZXBsYWNlKG9wdHMucmFkaXhQb2ludCwgXCIuXCIpKSwgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb3B0cy5tYXggPSBpc0Zpbml0ZShvcHRzLm1heCkgPyBwYXJzZUZsb2F0KG9wdHMubWF4KSA6IE5hTiwgaXNOYU4ob3B0cy5tYXgpICYmIChvcHRzLm1heCA9IE51bWJlci5NQVhfVkFMVUUpKSwgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb3B0cy5wYXJzZU1pbk1heE9wdGlvbnMgPSBcImRvbmVcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KG9wdHMpLCBudWxsICE9PSBvcHRzLm1pbiB8fCBudWxsICE9PSBvcHRzLm1heCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh1bm1hc2tlZCA9IG9wdHMub25Vbk1hc2soYnVmZmVyLmpvaW4oXCJcIiksIHVuZGVmaW5lZCwgJC5leHRlbmQoe30sIG9wdHMsIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5tYXNrQXNOdW1iZXI6ICEwXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSkpLCBudWxsICE9PSBvcHRzLm1pbiAmJiB1bm1hc2tlZCA8IG9wdHMubWluKSByZXR1cm4gb3B0cy5pc05lZ2F0aXZlID0gb3B0cy5taW4gPCAwLCBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcHRzLnBvc3RWYWxpZGF0aW9uKG9wdHMubWluLnRvU3RyaW5nKCkucmVwbGFjZShcIi5cIiwgb3B0cy5yYWRpeFBvaW50KS5zcGxpdChcIlwiKSwge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXJldDogY2FyZXRQb3MsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvcG9zdDogITAsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyOiBcIjBcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sIG9wdHMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChudWxsICE9PSBvcHRzLm1heCAmJiB1bm1hc2tlZCA+IG9wdHMubWF4KSByZXR1cm4gb3B0cy5pc05lZ2F0aXZlID0gb3B0cy5tYXggPCAwLCBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcHRzLnBvc3RWYWxpZGF0aW9uKG9wdHMubWF4LnRvU3RyaW5nKCkucmVwbGFjZShcIi5cIiwgb3B0cy5yYWRpeFBvaW50KS5zcGxpdChcIlwiKSwge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXJldDogY2FyZXRQb3MsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvcG9zdDogITAsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyOiBcIjBcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sIG9wdHMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG9wdHMucG9zdFZhbGlkYXRpb24oYnVmZmVyLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FyZXQ6IGNhcmV0UG9zLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyOiBcIjBcIixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudDogXCJibHVyXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIH0sIG9wdHMpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgY2FzZSBcIl9jaGVja3ZhbFwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXJldDogY2FyZXRQb3NcbiAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHJlZ2V4OiB7XG4gICAgICAgICAgICAgICAgICAgIGludGVnZXJQYXJ0OiBmdW5jdGlvbihvcHRzLCBlbXB0eUNoZWNrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZW1wdHlDaGVjayA/IG5ldyBSZWdFeHAoXCJbXCIgKyBJbnB1dG1hc2suZXNjYXBlUmVnZXgob3B0cy5uZWdhdGlvblN5bWJvbC5mcm9udCkgKyBcIitdP1wiKSA6IG5ldyBSZWdFeHAoXCJbXCIgKyBJbnB1dG1hc2suZXNjYXBlUmVnZXgob3B0cy5uZWdhdGlvblN5bWJvbC5mcm9udCkgKyBcIitdP1xcXFxkK1wiKTtcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgaW50ZWdlck5QYXJ0OiBmdW5jdGlvbihvcHRzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IFJlZ0V4cChcIltcXFxcZFwiICsgSW5wdXRtYXNrLmVzY2FwZVJlZ2V4KG9wdHMuZ3JvdXBTZXBhcmF0b3IpICsgSW5wdXRtYXNrLmVzY2FwZVJlZ2V4KG9wdHMucGxhY2Vob2xkZXIuY2hhckF0KDApKSArIFwiXStcIik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGRlZmluaXRpb25zOiB7XG4gICAgICAgICAgICAgICAgICAgIFwiflwiOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YWxpZGF0b3I6IGZ1bmN0aW9uKGNocnMsIG1hc2tzZXQsIHBvcywgc3RyaWN0LCBvcHRzLCBpc1NlbGVjdGlvbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBpc1ZhbGlkID0gc3RyaWN0ID8gbmV3IFJlZ0V4cChcIlswLTlcIiArIElucHV0bWFzay5lc2NhcGVSZWdleChvcHRzLmdyb3VwU2VwYXJhdG9yKSArIFwiXVwiKS50ZXN0KGNocnMpIDogbmV3IFJlZ0V4cChcIlswLTldXCIpLnRlc3QoY2hycyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCEwID09PSBpc1ZhbGlkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghMCAhPT0gb3B0cy5udW1lcmljSW5wdXQgJiYgbWFza3NldC52YWxpZFBvc2l0aW9uc1twb3NdICE9PSB1bmRlZmluZWQgJiYgXCJ+XCIgPT09IG1hc2tzZXQudmFsaWRQb3NpdGlvbnNbcG9zXS5tYXRjaC5kZWYgJiYgIWlzU2VsZWN0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgcHJvY2Vzc1ZhbHVlID0gbWFza3NldC5idWZmZXIuam9pbihcIlwiKSwgcHZSYWRpeFNwbGl0ID0gKHByb2Nlc3NWYWx1ZSA9IChwcm9jZXNzVmFsdWUgPSBwcm9jZXNzVmFsdWUucmVwbGFjZShuZXcgUmVnRXhwKFwiWy1cIiArIElucHV0bWFzay5lc2NhcGVSZWdleChvcHRzLm5lZ2F0aW9uU3ltYm9sLmZyb250KSArIFwiXVwiLCBcImdcIiksIFwiXCIpKS5yZXBsYWNlKG5ldyBSZWdFeHAoSW5wdXRtYXNrLmVzY2FwZVJlZ2V4KG9wdHMubmVnYXRpb25TeW1ib2wuYmFjaykgKyBcIiRcIiksIFwiXCIpKS5zcGxpdChvcHRzLnJhZGl4UG9pbnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHZSYWRpeFNwbGl0Lmxlbmd0aCA+IDEgJiYgKHB2UmFkaXhTcGxpdFsxXSA9IHB2UmFkaXhTcGxpdFsxXS5yZXBsYWNlKC8wL2csIG9wdHMucGxhY2Vob2xkZXIuY2hhckF0KDApKSksIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCIwXCIgPT09IHB2UmFkaXhTcGxpdFswXSAmJiAocHZSYWRpeFNwbGl0WzBdID0gcHZSYWRpeFNwbGl0WzBdLnJlcGxhY2UoLzAvZywgb3B0cy5wbGFjZWhvbGRlci5jaGFyQXQoMCkpKSwgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9jZXNzVmFsdWUgPSBwdlJhZGl4U3BsaXRbMF0gKyBvcHRzLnJhZGl4UG9pbnQgKyBwdlJhZGl4U3BsaXRbMV0gfHwgXCJcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBidWZmZXJUZW1wbGF0ZSA9IG1hc2tzZXQuX2J1ZmZlci5qb2luKFwiXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChwcm9jZXNzVmFsdWUgPT09IG9wdHMucmFkaXhQb2ludCAmJiAocHJvY2Vzc1ZhbHVlID0gYnVmZmVyVGVtcGxhdGUpOyBudWxsID09PSBwcm9jZXNzVmFsdWUubWF0Y2goSW5wdXRtYXNrLmVzY2FwZVJlZ2V4KGJ1ZmZlclRlbXBsYXRlKSArIFwiJFwiKTsgKSBidWZmZXJUZW1wbGF0ZSA9IGJ1ZmZlclRlbXBsYXRlLnNsaWNlKDEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXNWYWxpZCA9IChwcm9jZXNzVmFsdWUgPSAocHJvY2Vzc1ZhbHVlID0gcHJvY2Vzc1ZhbHVlLnJlcGxhY2UoYnVmZmVyVGVtcGxhdGUsIFwiXCIpKS5zcGxpdChcIlwiKSlbcG9zXSA9PT0gdW5kZWZpbmVkID8ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvczogcG9zLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZTogcG9zXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IDoge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvczogcG9zXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHN0cmljdCB8fCBjaHJzICE9PSBvcHRzLnJhZGl4UG9pbnQgfHwgbWFza3NldC52YWxpZFBvc2l0aW9uc1twb3MgLSAxXSAhPT0gdW5kZWZpbmVkIHx8IChtYXNrc2V0LmJ1ZmZlcltwb3NdID0gXCIwXCIsIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzVmFsaWQgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvczogcG9zICsgMVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBpc1ZhbGlkO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhcmRpbmFsaXR5OiAxXG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIFwiK1wiOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YWxpZGF0b3I6IGZ1bmN0aW9uKGNocnMsIG1hc2tzZXQsIHBvcywgc3RyaWN0LCBvcHRzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG9wdHMuYWxsb3dNaW51cyAmJiAoXCItXCIgPT09IGNocnMgfHwgY2hycyA9PT0gb3B0cy5uZWdhdGlvblN5bWJvbC5mcm9udCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgY2FyZGluYWxpdHk6IDEsXG4gICAgICAgICAgICAgICAgICAgICAgICBwbGFjZWhvbGRlcjogXCJcIlxuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICBcIi1cIjoge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFsaWRhdG9yOiBmdW5jdGlvbihjaHJzLCBtYXNrc2V0LCBwb3MsIHN0cmljdCwgb3B0cykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBvcHRzLmFsbG93TWludXMgJiYgY2hycyA9PT0gb3B0cy5uZWdhdGlvblN5bWJvbC5iYWNrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhcmRpbmFsaXR5OiAxLFxuICAgICAgICAgICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI6IFwiXCJcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgXCI6XCI6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhbGlkYXRvcjogZnVuY3Rpb24oY2hycywgbWFza3NldCwgcG9zLCBzdHJpY3QsIG9wdHMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgcmFkaXggPSBcIltcIiArIElucHV0bWFzay5lc2NhcGVSZWdleChvcHRzLnJhZGl4UG9pbnQpICsgXCJdXCIsIGlzVmFsaWQgPSBuZXcgUmVnRXhwKHJhZGl4KS50ZXN0KGNocnMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBpc1ZhbGlkICYmIG1hc2tzZXQudmFsaWRQb3NpdGlvbnNbcG9zXSAmJiBtYXNrc2V0LnZhbGlkUG9zaXRpb25zW3Bvc10ubWF0Y2gucGxhY2Vob2xkZXIgPT09IG9wdHMucmFkaXhQb2ludCAmJiAoaXNWYWxpZCA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FyZXQ6IHBvcyArIDFcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KSwgaXNWYWxpZDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICBjYXJkaW5hbGl0eTogMSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyOiBmdW5jdGlvbihvcHRzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG9wdHMucmFkaXhQb2ludDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgb25Vbk1hc2s6IGZ1bmN0aW9uKG1hc2tlZFZhbHVlLCB1bm1hc2tlZFZhbHVlLCBvcHRzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChcIlwiID09PSB1bm1hc2tlZFZhbHVlICYmICEwID09PSBvcHRzLm51bGxhYmxlKSByZXR1cm4gdW5tYXNrZWRWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHByb2Nlc3NWYWx1ZSA9IG1hc2tlZFZhbHVlLnJlcGxhY2Uob3B0cy5wcmVmaXgsIFwiXCIpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcHJvY2Vzc1ZhbHVlID0gcHJvY2Vzc1ZhbHVlLnJlcGxhY2Uob3B0cy5zdWZmaXgsIFwiXCIpLCBwcm9jZXNzVmFsdWUgPSBwcm9jZXNzVmFsdWUucmVwbGFjZShuZXcgUmVnRXhwKElucHV0bWFzay5lc2NhcGVSZWdleChvcHRzLmdyb3VwU2VwYXJhdG9yKSwgXCJnXCIpLCBcIlwiKSwgXG4gICAgICAgICAgICAgICAgICAgIFwiXCIgIT09IG9wdHMucGxhY2Vob2xkZXIuY2hhckF0KDApICYmIChwcm9jZXNzVmFsdWUgPSBwcm9jZXNzVmFsdWUucmVwbGFjZShuZXcgUmVnRXhwKG9wdHMucGxhY2Vob2xkZXIuY2hhckF0KDApLCBcImdcIiksIFwiMFwiKSksIFxuICAgICAgICAgICAgICAgICAgICBvcHRzLnVubWFza0FzTnVtYmVyID8gKFwiXCIgIT09IG9wdHMucmFkaXhQb2ludCAmJiAtMSAhPT0gcHJvY2Vzc1ZhbHVlLmluZGV4T2Yob3B0cy5yYWRpeFBvaW50KSAmJiAocHJvY2Vzc1ZhbHVlID0gcHJvY2Vzc1ZhbHVlLnJlcGxhY2UoSW5wdXRtYXNrLmVzY2FwZVJlZ2V4LmNhbGwodGhpcywgb3B0cy5yYWRpeFBvaW50KSwgXCIuXCIpKSwgXG4gICAgICAgICAgICAgICAgICAgIHByb2Nlc3NWYWx1ZSA9IHByb2Nlc3NWYWx1ZS5yZXBsYWNlKG5ldyBSZWdFeHAoXCJeXCIgKyBJbnB1dG1hc2suZXNjYXBlUmVnZXgob3B0cy5uZWdhdGlvblN5bWJvbC5mcm9udCkpLCBcIi1cIiksIFxuICAgICAgICAgICAgICAgICAgICBwcm9jZXNzVmFsdWUgPSBwcm9jZXNzVmFsdWUucmVwbGFjZShuZXcgUmVnRXhwKElucHV0bWFzay5lc2NhcGVSZWdleChvcHRzLm5lZ2F0aW9uU3ltYm9sLmJhY2spICsgXCIkXCIpLCBcIlwiKSwgXG4gICAgICAgICAgICAgICAgICAgIE51bWJlcihwcm9jZXNzVmFsdWUpKSA6IHByb2Nlc3NWYWx1ZTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGlzQ29tcGxldGU6IGZ1bmN0aW9uKGJ1ZmZlciwgb3B0cykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbWFza2VkVmFsdWUgPSBidWZmZXIuam9pbihcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGJ1ZmZlci5zbGljZSgpLmpvaW4oXCJcIikgIT09IG1hc2tlZFZhbHVlKSByZXR1cm4gITE7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwcm9jZXNzVmFsdWUgPSBtYXNrZWRWYWx1ZS5yZXBsYWNlKG9wdHMucHJlZml4LCBcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHByb2Nlc3NWYWx1ZSA9IHByb2Nlc3NWYWx1ZS5yZXBsYWNlKG9wdHMuc3VmZml4LCBcIlwiKSwgcHJvY2Vzc1ZhbHVlID0gcHJvY2Vzc1ZhbHVlLnJlcGxhY2UobmV3IFJlZ0V4cChJbnB1dG1hc2suZXNjYXBlUmVnZXgob3B0cy5ncm91cFNlcGFyYXRvciksIFwiZ1wiKSwgXCJcIiksIFxuICAgICAgICAgICAgICAgICAgICBcIixcIiA9PT0gb3B0cy5yYWRpeFBvaW50ICYmIChwcm9jZXNzVmFsdWUgPSBwcm9jZXNzVmFsdWUucmVwbGFjZShJbnB1dG1hc2suZXNjYXBlUmVnZXgob3B0cy5yYWRpeFBvaW50KSwgXCIuXCIpKSwgXG4gICAgICAgICAgICAgICAgICAgIGlzRmluaXRlKHByb2Nlc3NWYWx1ZSk7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBvbkJlZm9yZU1hc2s6IGZ1bmN0aW9uKGluaXRpYWxWYWx1ZSwgb3B0cykge1xuICAgICAgICAgICAgICAgICAgICBpZiAob3B0cy5pc05lZ2F0aXZlID0gdW5kZWZpbmVkLCBpbml0aWFsVmFsdWUgPSBpbml0aWFsVmFsdWUudG9TdHJpbmcoKS5jaGFyQXQoaW5pdGlhbFZhbHVlLmxlbmd0aCAtIDEpID09PSBvcHRzLnJhZGl4UG9pbnQgPyBpbml0aWFsVmFsdWUudG9TdHJpbmcoKS5zdWJzdHIoMCwgaW5pdGlhbFZhbHVlLmxlbmd0aCAtIDEpIDogaW5pdGlhbFZhbHVlLnRvU3RyaW5nKCksIFxuICAgICAgICAgICAgICAgICAgICBcIlwiICE9PSBvcHRzLnJhZGl4UG9pbnQgJiYgaXNGaW5pdGUoaW5pdGlhbFZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHZzID0gaW5pdGlhbFZhbHVlLnNwbGl0KFwiLlwiKSwgZ3JvdXBTaXplID0gXCJcIiAhPT0gb3B0cy5ncm91cFNlcGFyYXRvciA/IHBhcnNlSW50KG9wdHMuZ3JvdXBTaXplKSA6IDA7XG4gICAgICAgICAgICAgICAgICAgICAgICAyID09PSB2cy5sZW5ndGggJiYgKHZzWzBdLmxlbmd0aCA+IGdyb3VwU2l6ZSB8fCB2c1sxXS5sZW5ndGggPiBncm91cFNpemUgfHwgdnNbMF0ubGVuZ3RoIDw9IGdyb3VwU2l6ZSAmJiB2c1sxXS5sZW5ndGggPCBncm91cFNpemUpICYmIChpbml0aWFsVmFsdWUgPSBpbml0aWFsVmFsdWUucmVwbGFjZShcIi5cIiwgb3B0cy5yYWRpeFBvaW50KSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdmFyIGtvbW1hTWF0Y2hlcyA9IGluaXRpYWxWYWx1ZS5tYXRjaCgvLC9nKSwgZG90TWF0Y2hlcyA9IGluaXRpYWxWYWx1ZS5tYXRjaCgvXFwuL2cpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaW5pdGlhbFZhbHVlID0gZG90TWF0Y2hlcyAmJiBrb21tYU1hdGNoZXMgPyBkb3RNYXRjaGVzLmxlbmd0aCA+IGtvbW1hTWF0Y2hlcy5sZW5ndGggPyAoaW5pdGlhbFZhbHVlID0gaW5pdGlhbFZhbHVlLnJlcGxhY2UoL1xcLi9nLCBcIlwiKSkucmVwbGFjZShcIixcIiwgb3B0cy5yYWRpeFBvaW50KSA6IGtvbW1hTWF0Y2hlcy5sZW5ndGggPiBkb3RNYXRjaGVzLmxlbmd0aCA/IChpbml0aWFsVmFsdWUgPSBpbml0aWFsVmFsdWUucmVwbGFjZSgvLC9nLCBcIlwiKSkucmVwbGFjZShcIi5cIiwgb3B0cy5yYWRpeFBvaW50KSA6IGluaXRpYWxWYWx1ZS5pbmRleE9mKFwiLlwiKSA8IGluaXRpYWxWYWx1ZS5pbmRleE9mKFwiLFwiKSA/IGluaXRpYWxWYWx1ZS5yZXBsYWNlKC9cXC4vZywgXCJcIikgOiBpbml0aWFsVmFsdWUucmVwbGFjZSgvLC9nLCBcIlwiKSA6IGluaXRpYWxWYWx1ZS5yZXBsYWNlKG5ldyBSZWdFeHAoSW5wdXRtYXNrLmVzY2FwZVJlZ2V4KG9wdHMuZ3JvdXBTZXBhcmF0b3IpLCBcImdcIiksIFwiXCIpLCBcbiAgICAgICAgICAgICAgICAgICAgMCA9PT0gb3B0cy5kaWdpdHMgJiYgKC0xICE9PSBpbml0aWFsVmFsdWUuaW5kZXhPZihcIi5cIikgPyBpbml0aWFsVmFsdWUgPSBpbml0aWFsVmFsdWUuc3Vic3RyaW5nKDAsIGluaXRpYWxWYWx1ZS5pbmRleE9mKFwiLlwiKSkgOiAtMSAhPT0gaW5pdGlhbFZhbHVlLmluZGV4T2YoXCIsXCIpICYmIChpbml0aWFsVmFsdWUgPSBpbml0aWFsVmFsdWUuc3Vic3RyaW5nKDAsIGluaXRpYWxWYWx1ZS5pbmRleE9mKFwiLFwiKSkpKSwgXG4gICAgICAgICAgICAgICAgICAgIFwiXCIgIT09IG9wdHMucmFkaXhQb2ludCAmJiBpc0Zpbml0ZShvcHRzLmRpZ2l0cykgJiYgLTEgIT09IGluaXRpYWxWYWx1ZS5pbmRleE9mKG9wdHMucmFkaXhQb2ludCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBkZWNQYXJ0ID0gaW5pdGlhbFZhbHVlLnNwbGl0KG9wdHMucmFkaXhQb2ludClbMV0ubWF0Y2gobmV3IFJlZ0V4cChcIlxcXFxkKlwiKSlbMF07XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocGFyc2VJbnQob3B0cy5kaWdpdHMpIDwgZGVjUGFydC50b1N0cmluZygpLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBkaWdpdHNGYWN0b3IgPSBNYXRoLnBvdygxMCwgcGFyc2VJbnQob3B0cy5kaWdpdHMpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbml0aWFsVmFsdWUgPSBpbml0aWFsVmFsdWUucmVwbGFjZShJbnB1dG1hc2suZXNjYXBlUmVnZXgob3B0cy5yYWRpeFBvaW50KSwgXCIuXCIpLCBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbml0aWFsVmFsdWUgPSAoaW5pdGlhbFZhbHVlID0gTWF0aC5yb3VuZChwYXJzZUZsb2F0KGluaXRpYWxWYWx1ZSkgKiBkaWdpdHNGYWN0b3IpIC8gZGlnaXRzRmFjdG9yKS50b1N0cmluZygpLnJlcGxhY2UoXCIuXCIsIG9wdHMucmFkaXhQb2ludCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGluaXRpYWxWYWx1ZTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGNhbkNsZWFyUG9zaXRpb246IGZ1bmN0aW9uKG1hc2tzZXQsIHBvc2l0aW9uLCBsdnAsIHN0cmljdCwgb3B0cykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgdnAgPSBtYXNrc2V0LnZhbGlkUG9zaXRpb25zW3Bvc2l0aW9uXSwgY2FuQ2xlYXIgPSB2cC5pbnB1dCAhPT0gb3B0cy5yYWRpeFBvaW50IHx8IG51bGwgIT09IG1hc2tzZXQudmFsaWRQb3NpdGlvbnNbcG9zaXRpb25dLm1hdGNoLmZuICYmICExID09PSBvcHRzLmRlY2ltYWxQcm90ZWN0IHx8IHZwLmlucHV0ID09PSBvcHRzLnJhZGl4UG9pbnQgJiYgbWFza3NldC52YWxpZFBvc2l0aW9uc1twb3NpdGlvbiArIDFdICYmIG51bGwgPT09IG1hc2tzZXQudmFsaWRQb3NpdGlvbnNbcG9zaXRpb24gKyAxXS5tYXRjaC5mbiB8fCBpc0Zpbml0ZSh2cC5pbnB1dCkgfHwgcG9zaXRpb24gPT09IGx2cCB8fCB2cC5pbnB1dCA9PT0gb3B0cy5ncm91cFNlcGFyYXRvciB8fCB2cC5pbnB1dCA9PT0gb3B0cy5uZWdhdGlvblN5bWJvbC5mcm9udCB8fCB2cC5pbnB1dCA9PT0gb3B0cy5uZWdhdGlvblN5bWJvbC5iYWNrO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gIWNhbkNsZWFyIHx8IFwiK1wiICE9PSB2cC5tYXRjaC5uYXRpdmVEZWYgJiYgXCItXCIgIT09IHZwLm1hdGNoLm5hdGl2ZURlZiB8fCAob3B0cy5pc05lZ2F0aXZlID0gITEpLCBcbiAgICAgICAgICAgICAgICAgICAgY2FuQ2xlYXI7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBvbktleURvd246IGZ1bmN0aW9uKGUsIGJ1ZmZlciwgY2FyZXRQb3MsIG9wdHMpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyICRpbnB1dCA9ICQodGhpcyk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlLmN0cmxLZXkpIHN3aXRjaCAoZS5rZXlDb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgY2FzZSBJbnB1dG1hc2sua2V5Q29kZS5VUDpcbiAgICAgICAgICAgICAgICAgICAgICAgICRpbnB1dC52YWwocGFyc2VGbG9hdCh0aGlzLmlucHV0bWFzay51bm1hc2tlZHZhbHVlKCkpICsgcGFyc2VJbnQob3B0cy5zdGVwKSksICRpbnB1dC50cmlnZ2VyKFwic2V0dmFsdWVcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgICAgICAgICAgIGNhc2UgSW5wdXRtYXNrLmtleUNvZGUuRE9XTjpcbiAgICAgICAgICAgICAgICAgICAgICAgICRpbnB1dC52YWwocGFyc2VGbG9hdCh0aGlzLmlucHV0bWFzay51bm1hc2tlZHZhbHVlKCkpIC0gcGFyc2VJbnQob3B0cy5zdGVwKSksICRpbnB1dC50cmlnZ2VyKFwic2V0dmFsdWVcIik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgY3VycmVuY3k6IHtcbiAgICAgICAgICAgICAgICBwcmVmaXg6IFwiJCBcIixcbiAgICAgICAgICAgICAgICBncm91cFNlcGFyYXRvcjogXCIsXCIsXG4gICAgICAgICAgICAgICAgYWxpYXM6IFwibnVtZXJpY1wiLFxuICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyOiBcIjBcIixcbiAgICAgICAgICAgICAgICBhdXRvR3JvdXA6ICEwLFxuICAgICAgICAgICAgICAgIGRpZ2l0czogMixcbiAgICAgICAgICAgICAgICBkaWdpdHNPcHRpb25hbDogITEsXG4gICAgICAgICAgICAgICAgY2xlYXJNYXNrT25Mb3N0Rm9jdXM6ICExXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZGVjaW1hbDoge1xuICAgICAgICAgICAgICAgIGFsaWFzOiBcIm51bWVyaWNcIlxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGludGVnZXI6IHtcbiAgICAgICAgICAgICAgICBhbGlhczogXCJudW1lcmljXCIsXG4gICAgICAgICAgICAgICAgZGlnaXRzOiAwLFxuICAgICAgICAgICAgICAgIHJhZGl4UG9pbnQ6IFwiXCJcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBwZXJjZW50YWdlOiB7XG4gICAgICAgICAgICAgICAgYWxpYXM6IFwibnVtZXJpY1wiLFxuICAgICAgICAgICAgICAgIGRpZ2l0czogMixcbiAgICAgICAgICAgICAgICBkaWdpdHNPcHRpb25hbDogITAsXG4gICAgICAgICAgICAgICAgcmFkaXhQb2ludDogXCIuXCIsXG4gICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI6IFwiMFwiLFxuICAgICAgICAgICAgICAgIGF1dG9Hcm91cDogITEsXG4gICAgICAgICAgICAgICAgbWluOiAwLFxuICAgICAgICAgICAgICAgIG1heDogMTAwLFxuICAgICAgICAgICAgICAgIHN1ZmZpeDogXCIgJVwiLFxuICAgICAgICAgICAgICAgIGFsbG93TWludXM6ICExXG4gICAgICAgICAgICB9XG4gICAgICAgIH0pLCBJbnB1dG1hc2s7XG4gICAgfSk7XG59LCBmdW5jdGlvbihtb2R1bGUsIGV4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pIHtcbiAgICBcInVzZSBzdHJpY3RcIjtcbiAgICB2YXIgX19XRUJQQUNLX0FNRF9ERUZJTkVfRkFDVE9SWV9fLCBfX1dFQlBBQ0tfQU1EX0RFRklORV9BUlJBWV9fLCBfX1dFQlBBQ0tfQU1EX0RFRklORV9SRVNVTFRfXztcbiAgICBcImZ1bmN0aW9uXCIgPT0gdHlwZW9mIFN5bWJvbCAmJiBTeW1ib2wuaXRlcmF0b3I7XG4gICAgIWZ1bmN0aW9uKGZhY3RvcnkpIHtcbiAgICAgICAgX19XRUJQQUNLX0FNRF9ERUZJTkVfQVJSQVlfXyA9IFsgX193ZWJwYWNrX3JlcXVpcmVfXygwKSwgX193ZWJwYWNrX3JlcXVpcmVfXygxKSBdLCBcbiAgICAgICAgdm9pZCAwICE9PSAoX19XRUJQQUNLX0FNRF9ERUZJTkVfUkVTVUxUX18gPSBcImZ1bmN0aW9uXCIgPT0gdHlwZW9mIChfX1dFQlBBQ0tfQU1EX0RFRklORV9GQUNUT1JZX18gPSBmYWN0b3J5KSA/IF9fV0VCUEFDS19BTURfREVGSU5FX0ZBQ1RPUllfXy5hcHBseShleHBvcnRzLCBfX1dFQlBBQ0tfQU1EX0RFRklORV9BUlJBWV9fKSA6IF9fV0VCUEFDS19BTURfREVGSU5FX0ZBQ1RPUllfXykgJiYgKG1vZHVsZS5leHBvcnRzID0gX19XRUJQQUNLX0FNRF9ERUZJTkVfUkVTVUxUX18pO1xuICAgIH0oZnVuY3Rpb24oJCwgSW5wdXRtYXNrKSB7XG4gICAgICAgIGZ1bmN0aW9uIG1hc2tTb3J0KGEsIGIpIHtcbiAgICAgICAgICAgIHZhciBtYXNrYSA9IChhLm1hc2sgfHwgYSkucmVwbGFjZSgvIy9nLCBcIjlcIikucmVwbGFjZSgvXFwpLywgXCI5XCIpLnJlcGxhY2UoL1srKCkjLV0vZywgXCJcIiksIG1hc2tiID0gKGIubWFzayB8fCBiKS5yZXBsYWNlKC8jL2csIFwiOVwiKS5yZXBsYWNlKC9cXCkvLCBcIjlcIikucmVwbGFjZSgvWysoKSMtXS9nLCBcIlwiKSwgbWFza2FzID0gKGEubWFzayB8fCBhKS5zcGxpdChcIiNcIilbMF0sIG1hc2ticyA9IChiLm1hc2sgfHwgYikuc3BsaXQoXCIjXCIpWzBdO1xuICAgICAgICAgICAgcmV0dXJuIDAgPT09IG1hc2ticy5pbmRleE9mKG1hc2thcykgPyAtMSA6IDAgPT09IG1hc2thcy5pbmRleE9mKG1hc2ticykgPyAxIDogbWFza2EubG9jYWxlQ29tcGFyZShtYXNrYik7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGFuYWx5c2VNYXNrQmFzZSA9IElucHV0bWFzay5wcm90b3R5cGUuYW5hbHlzZU1hc2s7XG4gICAgICAgIHJldHVybiBJbnB1dG1hc2sucHJvdG90eXBlLmFuYWx5c2VNYXNrID0gZnVuY3Rpb24obWFzaywgcmVnZXhNYXNrLCBvcHRzKSB7XG4gICAgICAgICAgICBmdW5jdGlvbiByZWR1Y2VWYXJpYXRpb25zKG1hc2tzLCBwcmV2aW91c1ZhcmlhdGlvbiwgcHJldmlvdXNtYXNrR3JvdXApIHtcbiAgICAgICAgICAgICAgICBwcmV2aW91c1ZhcmlhdGlvbiA9IHByZXZpb3VzVmFyaWF0aW9uIHx8IFwiXCIsIHByZXZpb3VzbWFza0dyb3VwID0gcHJldmlvdXNtYXNrR3JvdXAgfHwgbWFza0dyb3VwcywgXG4gICAgICAgICAgICAgICAgXCJcIiAhPT0gcHJldmlvdXNWYXJpYXRpb24gJiYgKHByZXZpb3VzbWFza0dyb3VwW3ByZXZpb3VzVmFyaWF0aW9uXSA9IHt9KTtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciB2YXJpYXRpb24gPSBcIlwiLCBtYXNrR3JvdXAgPSBwcmV2aW91c21hc2tHcm91cFtwcmV2aW91c1ZhcmlhdGlvbl0gfHwgcHJldmlvdXNtYXNrR3JvdXAsIGkgPSBtYXNrcy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgbWFza0dyb3VwW3ZhcmlhdGlvbiA9IChtYXNrID0gbWFza3NbaV0ubWFzayB8fCBtYXNrc1tpXSkuc3Vic3RyKDAsIDEpXSA9IG1hc2tHcm91cFt2YXJpYXRpb25dIHx8IFtdLCBcbiAgICAgICAgICAgICAgICBtYXNrR3JvdXBbdmFyaWF0aW9uXS51bnNoaWZ0KG1hc2suc3Vic3RyKDEpKSwgbWFza3Muc3BsaWNlKGksIDEpO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIG5keCBpbiBtYXNrR3JvdXApIG1hc2tHcm91cFtuZHhdLmxlbmd0aCA+IDUwMCAmJiByZWR1Y2VWYXJpYXRpb25zKG1hc2tHcm91cFtuZHhdLnNsaWNlKCksIG5keCwgbWFza0dyb3VwKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlYnVpbGQobWFza0dyb3VwKSB7XG4gICAgICAgICAgICAgICAgdmFyIG1hc2sgPSBcIlwiLCBzdWJtYXNrcyA9IFtdO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIG5keCBpbiBtYXNrR3JvdXApICQuaXNBcnJheShtYXNrR3JvdXBbbmR4XSkgPyAxID09PSBtYXNrR3JvdXBbbmR4XS5sZW5ndGggPyBzdWJtYXNrcy5wdXNoKG5keCArIG1hc2tHcm91cFtuZHhdKSA6IHN1Ym1hc2tzLnB1c2gobmR4ICsgb3B0cy5ncm91cG1hcmtlci5zdGFydCArIG1hc2tHcm91cFtuZHhdLmpvaW4ob3B0cy5ncm91cG1hcmtlci5lbmQgKyBvcHRzLmFsdGVybmF0b3JtYXJrZXIgKyBvcHRzLmdyb3VwbWFya2VyLnN0YXJ0KSArIG9wdHMuZ3JvdXBtYXJrZXIuZW5kKSA6IHN1Ym1hc2tzLnB1c2gobmR4ICsgcmVidWlsZChtYXNrR3JvdXBbbmR4XSkpO1xuICAgICAgICAgICAgICAgIHJldHVybiAxID09PSBzdWJtYXNrcy5sZW5ndGggPyBtYXNrICs9IHN1Ym1hc2tzWzBdIDogbWFzayArPSBvcHRzLmdyb3VwbWFya2VyLnN0YXJ0ICsgc3VibWFza3Muam9pbihvcHRzLmdyb3VwbWFya2VyLmVuZCArIG9wdHMuYWx0ZXJuYXRvcm1hcmtlciArIG9wdHMuZ3JvdXBtYXJrZXIuc3RhcnQpICsgb3B0cy5ncm91cG1hcmtlci5lbmQsIFxuICAgICAgICAgICAgICAgIG1hc2s7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgbWFza0dyb3VwcyA9IHt9O1xuICAgICAgICAgICAgcmV0dXJuIG9wdHMucGhvbmVDb2RlcyAmJiAob3B0cy5waG9uZUNvZGVzICYmIG9wdHMucGhvbmVDb2Rlcy5sZW5ndGggPiAxZTMgJiYgKHJlZHVjZVZhcmlhdGlvbnMoKG1hc2sgPSBtYXNrLnN1YnN0cigxLCBtYXNrLmxlbmd0aCAtIDIpKS5zcGxpdChvcHRzLmdyb3VwbWFya2VyLmVuZCArIG9wdHMuYWx0ZXJuYXRvcm1hcmtlciArIG9wdHMuZ3JvdXBtYXJrZXIuc3RhcnQpKSwgXG4gICAgICAgICAgICBtYXNrID0gcmVidWlsZChtYXNrR3JvdXBzKSksIG1hc2sgPSBtYXNrLnJlcGxhY2UoLzkvZywgXCJcXFxcOVwiKSksIGFuYWx5c2VNYXNrQmFzZS5jYWxsKHRoaXMsIG1hc2ssIHJlZ2V4TWFzaywgb3B0cyk7XG4gICAgICAgIH0sIElucHV0bWFzay5leHRlbmRBbGlhc2VzKHtcbiAgICAgICAgICAgIGFic3RyYWN0cGhvbmU6IHtcbiAgICAgICAgICAgICAgICBncm91cG1hcmtlcjoge1xuICAgICAgICAgICAgICAgICAgICBzdGFydDogXCI8XCIsXG4gICAgICAgICAgICAgICAgICAgIGVuZDogXCI+XCJcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGNvdW50cnljb2RlOiBcIlwiLFxuICAgICAgICAgICAgICAgIHBob25lQ29kZXM6IFtdLFxuICAgICAgICAgICAgICAgIG1hc2s6IGZ1bmN0aW9uKG9wdHMpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG9wdHMuZGVmaW5pdGlvbnMgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBcIiNcIjogSW5wdXRtYXNrLnByb3RvdHlwZS5kZWZpbml0aW9uc1s5XVxuICAgICAgICAgICAgICAgICAgICB9LCBvcHRzLnBob25lQ29kZXMuc29ydChtYXNrU29ydCk7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBrZWVwU3RhdGljOiAhMCxcbiAgICAgICAgICAgICAgICBvbkJlZm9yZU1hc2s6IGZ1bmN0aW9uKHZhbHVlLCBvcHRzKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwcm9jZXNzZWRWYWx1ZSA9IHZhbHVlLnJlcGxhY2UoL14wezEsMn0vLCBcIlwiKS5yZXBsYWNlKC9bXFxzXS9nLCBcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIChwcm9jZXNzZWRWYWx1ZS5pbmRleE9mKG9wdHMuY291bnRyeWNvZGUpID4gMSB8fCAtMSA9PT0gcHJvY2Vzc2VkVmFsdWUuaW5kZXhPZihvcHRzLmNvdW50cnljb2RlKSkgJiYgKHByb2Nlc3NlZFZhbHVlID0gXCIrXCIgKyBvcHRzLmNvdW50cnljb2RlICsgcHJvY2Vzc2VkVmFsdWUpLCBcbiAgICAgICAgICAgICAgICAgICAgcHJvY2Vzc2VkVmFsdWU7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBvblVuTWFzazogZnVuY3Rpb24obWFza2VkVmFsdWUsIHVubWFza2VkVmFsdWUsIG9wdHMpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG1hc2tlZFZhbHVlLnJlcGxhY2UoL1soKSMtXS9nLCBcIlwiKTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGlucHV0bW9kZTogXCJ0ZWxcIlxuICAgICAgICAgICAgfVxuICAgICAgICB9KSwgSW5wdXRtYXNrO1xuICAgIH0pO1xufSwgZnVuY3Rpb24obW9kdWxlLCBleHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSB7XG4gICAgXCJ1c2Ugc3RyaWN0XCI7XG4gICAgdmFyIF9fV0VCUEFDS19BTURfREVGSU5FX0ZBQ1RPUllfXywgX19XRUJQQUNLX0FNRF9ERUZJTkVfQVJSQVlfXywgX19XRUJQQUNLX0FNRF9ERUZJTkVfUkVTVUxUX187XG4gICAgXCJmdW5jdGlvblwiID09IHR5cGVvZiBTeW1ib2wgJiYgU3ltYm9sLml0ZXJhdG9yO1xuICAgICFmdW5jdGlvbihmYWN0b3J5KSB7XG4gICAgICAgIF9fV0VCUEFDS19BTURfREVGSU5FX0FSUkFZX18gPSBbIF9fd2VicGFja19yZXF1aXJlX18oMCksIF9fd2VicGFja19yZXF1aXJlX18oMSkgXSwgXG4gICAgICAgIHZvaWQgMCAhPT0gKF9fV0VCUEFDS19BTURfREVGSU5FX1JFU1VMVF9fID0gXCJmdW5jdGlvblwiID09IHR5cGVvZiAoX19XRUJQQUNLX0FNRF9ERUZJTkVfRkFDVE9SWV9fID0gZmFjdG9yeSkgPyBfX1dFQlBBQ0tfQU1EX0RFRklORV9GQUNUT1JZX18uYXBwbHkoZXhwb3J0cywgX19XRUJQQUNLX0FNRF9ERUZJTkVfQVJSQVlfXykgOiBfX1dFQlBBQ0tfQU1EX0RFRklORV9GQUNUT1JZX18pICYmIChtb2R1bGUuZXhwb3J0cyA9IF9fV0VCUEFDS19BTURfREVGSU5FX1JFU1VMVF9fKTtcbiAgICB9KGZ1bmN0aW9uKCQsIElucHV0bWFzaykge1xuICAgICAgICByZXR1cm4gSW5wdXRtYXNrLmV4dGVuZEFsaWFzZXMoe1xuICAgICAgICAgICAgUmVnZXg6IHtcbiAgICAgICAgICAgICAgICBtYXNrOiBcInJcIixcbiAgICAgICAgICAgICAgICBncmVlZHk6ICExLFxuICAgICAgICAgICAgICAgIHJlcGVhdDogXCIqXCIsXG4gICAgICAgICAgICAgICAgcmVnZXg6IG51bGwsXG4gICAgICAgICAgICAgICAgcmVnZXhUb2tlbnM6IG51bGwsXG4gICAgICAgICAgICAgICAgdG9rZW5pemVyOiAvXFxbXFxeP10/KD86W15cXFxcXFxdXSt8XFxcXFtcXFNcXHNdPykqXT98XFxcXCg/OjAoPzpbMC0zXVswLTddezAsMn18WzQtN11bMC03XT8pP3xbMS05XVswLTldKnx4WzAtOUEtRmEtZl17Mn18dVswLTlBLUZhLWZdezR9fGNbQS1aYS16XXxbXFxTXFxzXT8pfFxcKCg/OlxcP1s6PSFdPyk/fCg/Ols/KitdfFxce1swLTldKyg/OixbMC05XSopP1xcfSlcXD8/fFteLj8qK14ke1soKXxcXFxcXSt8Li9nLFxuICAgICAgICAgICAgICAgIHF1YW50aWZpZXJGaWx0ZXI6IC9bMC05XStbXixdLyxcbiAgICAgICAgICAgICAgICBpc0NvbXBsZXRlOiBmdW5jdGlvbihidWZmZXIsIG9wdHMpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBSZWdFeHAob3B0cy5yZWdleCwgb3B0cy5jYXNpbmcgPyBcImlcIiA6IFwiXCIpLnRlc3QoYnVmZmVyLmpvaW4oXCJcIikpO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgZGVmaW5pdGlvbnM6IHtcbiAgICAgICAgICAgICAgICAgICAgcjoge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFsaWRhdG9yOiBmdW5jdGlvbihjaHJzLCBtYXNrc2V0LCBwb3MsIHN0cmljdCwgb3B0cykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uIFJlZ2V4VG9rZW4oaXNHcm91cCwgaXNRdWFudGlmaWVyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubWF0Y2hlcyA9IFtdLCB0aGlzLmlzR3JvdXAgPSBpc0dyb3VwIHx8ICExLCB0aGlzLmlzUXVhbnRpZmllciA9IGlzUXVhbnRpZmllciB8fCAhMSwgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucXVhbnRpZmllciA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbjogMSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heDogMVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LCB0aGlzLnJlcGVhdGVyUGFydCA9IHZvaWQgMDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZnVuY3Rpb24gdmFsaWRhdGVSZWdleFRva2VuKHRva2VuLCBmcm9tR3JvdXApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGlzdmFsaWQgPSAhMTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZnJvbUdyb3VwICYmIChyZWdleFBhcnQgKz0gXCIoXCIsIG9wZW5Hcm91cENvdW50KyspO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBtbmR4ID0gMDsgbW5keCA8IHRva2VuLm1hdGNoZXMubGVuZ3RoOyBtbmR4KyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBtYXRjaFRva2VuID0gdG9rZW4ubWF0Y2hlc1ttbmR4XTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghMCA9PT0gbWF0Y2hUb2tlbi5pc0dyb3VwKSBpc3ZhbGlkID0gdmFsaWRhdGVSZWdleFRva2VuKG1hdGNoVG9rZW4sICEwKTsgZWxzZSBpZiAoITAgPT09IG1hdGNoVG9rZW4uaXNRdWFudGlmaWVyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNycm50bmR4ID0gJC5pbkFycmF5KG1hdGNoVG9rZW4sIHRva2VuLm1hdGNoZXMpLCBtYXRjaEdyb3VwID0gdG9rZW4ubWF0Y2hlc1tjcnJudG5keCAtIDFdLCByZWdleFBhcnRCYWsgPSByZWdleFBhcnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzTmFOKG1hdGNoVG9rZW4ucXVhbnRpZmllci5tYXgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoO21hdGNoVG9rZW4ucmVwZWF0ZXJQYXJ0ICYmIG1hdGNoVG9rZW4ucmVwZWF0ZXJQYXJ0ICE9PSByZWdleFBhcnQgJiYgbWF0Y2hUb2tlbi5yZXBlYXRlclBhcnQubGVuZ3RoID4gcmVnZXhQYXJ0Lmxlbmd0aCAmJiAhKGlzdmFsaWQgPSB2YWxpZGF0ZVJlZ2V4VG9rZW4obWF0Y2hHcm91cCwgITApKTsgKSA7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChpc3ZhbGlkID0gaXN2YWxpZCB8fCB2YWxpZGF0ZVJlZ2V4VG9rZW4obWF0Y2hHcm91cCwgITApKSAmJiAobWF0Y2hUb2tlbi5yZXBlYXRlclBhcnQgPSByZWdleFBhcnQpLCBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVnZXhQYXJ0ID0gcmVnZXhQYXJ0QmFrICsgbWF0Y2hUb2tlbi5xdWFudGlmaWVyLm1heDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMCwgcW0gPSBtYXRjaFRva2VuLnF1YW50aWZpZXIubWF4IC0gMTsgaSA8IHFtICYmICEoaXN2YWxpZCA9IHZhbGlkYXRlUmVnZXhUb2tlbihtYXRjaEdyb3VwLCAhMCkpOyBpKyspIDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVnZXhQYXJ0ID0gcmVnZXhQYXJ0QmFrICsgXCJ7XCIgKyBtYXRjaFRva2VuLnF1YW50aWZpZXIubWluICsgXCIsXCIgKyBtYXRjaFRva2VuLnF1YW50aWZpZXIubWF4ICsgXCJ9XCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2b2lkIDAgIT09IG1hdGNoVG9rZW4ubWF0Y2hlcykgZm9yICh2YXIgayA9IDA7IGsgPCBtYXRjaFRva2VuLmxlbmd0aCAmJiAhKGlzdmFsaWQgPSB2YWxpZGF0ZVJlZ2V4VG9rZW4obWF0Y2hUb2tlbltrXSwgZnJvbUdyb3VwKSk7IGsrKykgOyBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgdGVzdEV4cDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoXCJbXCIgPT0gbWF0Y2hUb2tlbi5jaGFyQXQoMCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGVzdEV4cCA9IHJlZ2V4UGFydCwgdGVzdEV4cCArPSBtYXRjaFRva2VuO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGogPSAwOyBqIDwgb3Blbkdyb3VwQ291bnQ7IGorKykgdGVzdEV4cCArPSBcIilcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXN2YWxpZCA9IChleHAgPSBuZXcgUmVnRXhwKFwiXihcIiArIHRlc3RFeHAgKyBcIikkXCIsIG9wdHMuY2FzaW5nID8gXCJpXCIgOiBcIlwiKSkudGVzdChidWZmZXJTdHIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBmb3IgKHZhciBsID0gMCwgdGwgPSBtYXRjaFRva2VuLmxlbmd0aDsgbCA8IHRsOyBsKyspIGlmIChcIlxcXFxcIiAhPT0gbWF0Y2hUb2tlbi5jaGFyQXQobCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGVzdEV4cCA9IHJlZ2V4UGFydCwgdGVzdEV4cCA9ICh0ZXN0RXhwICs9IG1hdGNoVG9rZW4uc3Vic3RyKDAsIGwgKyAxKSkucmVwbGFjZSgvXFx8JC8sIFwiXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IG9wZW5Hcm91cENvdW50OyBqKyspIHRlc3RFeHAgKz0gXCIpXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBleHAgPSBuZXcgUmVnRXhwKFwiXihcIiArIHRlc3RFeHAgKyBcIikkXCIsIG9wdHMuY2FzaW5nID8gXCJpXCIgOiBcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzdmFsaWQgPSBleHAudGVzdChidWZmZXJTdHIpKSBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVnZXhQYXJ0ICs9IG1hdGNoVG9rZW47XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXN2YWxpZCkgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZyb21Hcm91cCAmJiAocmVnZXhQYXJ0ICs9IFwiKVwiLCBvcGVuR3JvdXBDb3VudC0tKSwgaXN2YWxpZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGJ1ZmZlclN0ciwgZ3JvdXBUb2tlbiwgY2J1ZmZlciA9IG1hc2tzZXQuYnVmZmVyLnNsaWNlKCksIHJlZ2V4UGFydCA9IFwiXCIsIGlzVmFsaWQgPSAhMSwgb3Blbkdyb3VwQ291bnQgPSAwO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG51bGwgPT09IG9wdHMucmVnZXhUb2tlbnMgJiYgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBtYXRjaCwgbSwgY3VycmVudFRva2VuID0gbmV3IFJlZ2V4VG9rZW4oKSwgb3Blbmdyb3VwcyA9IFtdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKG9wdHMucmVnZXhUb2tlbnMgPSBbXTsgbWF0Y2ggPSBvcHRzLnRva2VuaXplci5leGVjKG9wdHMucmVnZXgpOyApIHN3aXRjaCAoKG0gPSBtYXRjaFswXSkuY2hhckF0KDApKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBcIihcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9wZW5ncm91cHMucHVzaChuZXcgUmVnZXhUb2tlbighMCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFwiKVwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXBUb2tlbiA9IG9wZW5ncm91cHMucG9wKCksIG9wZW5ncm91cHMubGVuZ3RoID4gMCA/IG9wZW5ncm91cHNbb3Blbmdyb3Vwcy5sZW5ndGggLSAxXS5tYXRjaGVzLnB1c2goZ3JvdXBUb2tlbikgOiBjdXJyZW50VG9rZW4ubWF0Y2hlcy5wdXNoKGdyb3VwVG9rZW4pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFwie1wiOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgXCIrXCI6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBcIipcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBxdWFudGlmaWVyVG9rZW4gPSBuZXcgUmVnZXhUb2tlbighMSwgITApLCBtcSA9IChtID0gbS5yZXBsYWNlKC9be31dL2csIFwiXCIpKS5zcGxpdChcIixcIiksIG1xMCA9IGlzTmFOKG1xWzBdKSA/IG1xWzBdIDogcGFyc2VJbnQobXFbMF0pLCBtcTEgPSAxID09PSBtcS5sZW5ndGggPyBtcTAgOiBpc05hTihtcVsxXSkgPyBtcVsxXSA6IHBhcnNlSW50KG1xWzFdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChxdWFudGlmaWVyVG9rZW4ucXVhbnRpZmllciA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW46IG1xMCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXg6IG1xMVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSwgb3Blbmdyb3Vwcy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG1hdGNoZXMgPSBvcGVuZ3JvdXBzW29wZW5ncm91cHMubGVuZ3RoIC0gMV0ubWF0Y2hlcztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAobWF0Y2ggPSBtYXRjaGVzLnBvcCgpKS5pc0dyb3VwIHx8ICgoZ3JvdXBUb2tlbiA9IG5ldyBSZWdleFRva2VuKCEwKSkubWF0Y2hlcy5wdXNoKG1hdGNoKSwgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2ggPSBncm91cFRva2VuKSwgbWF0Y2hlcy5wdXNoKG1hdGNoKSwgbWF0Y2hlcy5wdXNoKHF1YW50aWZpZXJUb2tlbik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgKG1hdGNoID0gY3VycmVudFRva2VuLm1hdGNoZXMucG9wKCkpLmlzR3JvdXAgfHwgKChncm91cFRva2VuID0gbmV3IFJlZ2V4VG9rZW4oITApKS5tYXRjaGVzLnB1c2gobWF0Y2gpLCBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoID0gZ3JvdXBUb2tlbiksIGN1cnJlbnRUb2tlbi5tYXRjaGVzLnB1c2gobWF0Y2gpLCBjdXJyZW50VG9rZW4ubWF0Y2hlcy5wdXNoKHF1YW50aWZpZXJUb2tlbik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcGVuZ3JvdXBzLmxlbmd0aCA+IDAgPyBvcGVuZ3JvdXBzW29wZW5ncm91cHMubGVuZ3RoIC0gMV0ubWF0Y2hlcy5wdXNoKG0pIDogY3VycmVudFRva2VuLm1hdGNoZXMucHVzaChtKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50VG9rZW4ubWF0Y2hlcy5sZW5ndGggPiAwICYmIG9wdHMucmVnZXhUb2tlbnMucHVzaChjdXJyZW50VG9rZW4pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0oKSwgY2J1ZmZlci5zcGxpY2UocG9zLCAwLCBjaHJzKSwgYnVmZmVyU3RyID0gY2J1ZmZlci5qb2luKFwiXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgb3B0cy5yZWdleFRva2Vucy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgcmVnZXhUb2tlbiA9IG9wdHMucmVnZXhUb2tlbnNbaV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc1ZhbGlkID0gdmFsaWRhdGVSZWdleFRva2VuKHJlZ2V4VG9rZW4sIHJlZ2V4VG9rZW4uaXNHcm91cCkpIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gaXNWYWxpZDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICBjYXJkaW5hbGl0eTogMVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9KSwgSW5wdXRtYXNrO1xuICAgIH0pO1xufSwgZnVuY3Rpb24obW9kdWxlLCBleHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSB7XG4gICAgXCJ1c2Ugc3RyaWN0XCI7XG4gICAgdmFyIF9fV0VCUEFDS19BTURfREVGSU5FX0ZBQ1RPUllfXywgX19XRUJQQUNLX0FNRF9ERUZJTkVfQVJSQVlfXywgX19XRUJQQUNLX0FNRF9ERUZJTkVfUkVTVUxUX18sIF90eXBlb2YgPSBcImZ1bmN0aW9uXCIgPT0gdHlwZW9mIFN5bWJvbCAmJiBcInN5bWJvbFwiID09IHR5cGVvZiBTeW1ib2wuaXRlcmF0b3IgPyBmdW5jdGlvbihvYmopIHtcbiAgICAgICAgcmV0dXJuIHR5cGVvZiBvYmo7XG4gICAgfSA6IGZ1bmN0aW9uKG9iaikge1xuICAgICAgICByZXR1cm4gb2JqICYmIFwiZnVuY3Rpb25cIiA9PSB0eXBlb2YgU3ltYm9sICYmIG9iai5jb25zdHJ1Y3RvciA9PT0gU3ltYm9sICYmIG9iaiAhPT0gU3ltYm9sLnByb3RvdHlwZSA/IFwic3ltYm9sXCIgOiB0eXBlb2Ygb2JqO1xuICAgIH07XG4gICAgIWZ1bmN0aW9uKGZhY3RvcnkpIHtcbiAgICAgICAgX19XRUJQQUNLX0FNRF9ERUZJTkVfQVJSQVlfXyA9IFsgX193ZWJwYWNrX3JlcXVpcmVfXygyKSwgX193ZWJwYWNrX3JlcXVpcmVfXygxKSBdLCBcbiAgICAgICAgdm9pZCAwICE9PSAoX19XRUJQQUNLX0FNRF9ERUZJTkVfUkVTVUxUX18gPSBcImZ1bmN0aW9uXCIgPT0gdHlwZW9mIChfX1dFQlBBQ0tfQU1EX0RFRklORV9GQUNUT1JZX18gPSBmYWN0b3J5KSA/IF9fV0VCUEFDS19BTURfREVGSU5FX0ZBQ1RPUllfXy5hcHBseShleHBvcnRzLCBfX1dFQlBBQ0tfQU1EX0RFRklORV9BUlJBWV9fKSA6IF9fV0VCUEFDS19BTURfREVGSU5FX0ZBQ1RPUllfXykgJiYgKG1vZHVsZS5leHBvcnRzID0gX19XRUJQQUNLX0FNRF9ERUZJTkVfUkVTVUxUX18pO1xuICAgIH0oZnVuY3Rpb24oJCwgSW5wdXRtYXNrKSB7XG4gICAgICAgIHJldHVybiB2b2lkIDAgPT09ICQuZm4uaW5wdXRtYXNrICYmICgkLmZuLmlucHV0bWFzayA9IGZ1bmN0aW9uKGZuLCBvcHRpb25zKSB7XG4gICAgICAgICAgICB2YXIgbnB0bWFzaywgaW5wdXQgPSB0aGlzWzBdO1xuICAgICAgICAgICAgaWYgKHZvaWQgMCA9PT0gb3B0aW9ucyAmJiAob3B0aW9ucyA9IHt9KSwgXCJzdHJpbmdcIiA9PSB0eXBlb2YgZm4pIHN3aXRjaCAoZm4pIHtcbiAgICAgICAgICAgICAgY2FzZSBcInVubWFza2VkdmFsdWVcIjpcbiAgICAgICAgICAgICAgICByZXR1cm4gaW5wdXQgJiYgaW5wdXQuaW5wdXRtYXNrID8gaW5wdXQuaW5wdXRtYXNrLnVubWFza2VkdmFsdWUoKSA6ICQoaW5wdXQpLnZhbCgpO1xuXG4gICAgICAgICAgICAgIGNhc2UgXCJyZW1vdmVcIjpcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5lYWNoKGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmlucHV0bWFzayAmJiB0aGlzLmlucHV0bWFzay5yZW1vdmUoKTtcbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICBjYXNlIFwiZ2V0ZW1wdHltYXNrXCI6XG4gICAgICAgICAgICAgICAgcmV0dXJuIGlucHV0ICYmIGlucHV0LmlucHV0bWFzayA/IGlucHV0LmlucHV0bWFzay5nZXRlbXB0eW1hc2soKSA6IFwiXCI7XG5cbiAgICAgICAgICAgICAgY2FzZSBcImhhc01hc2tlZFZhbHVlXCI6XG4gICAgICAgICAgICAgICAgcmV0dXJuICEoIWlucHV0IHx8ICFpbnB1dC5pbnB1dG1hc2spICYmIGlucHV0LmlucHV0bWFzay5oYXNNYXNrZWRWYWx1ZSgpO1xuXG4gICAgICAgICAgICAgIGNhc2UgXCJpc0NvbXBsZXRlXCI6XG4gICAgICAgICAgICAgICAgcmV0dXJuICFpbnB1dCB8fCAhaW5wdXQuaW5wdXRtYXNrIHx8IGlucHV0LmlucHV0bWFzay5pc0NvbXBsZXRlKCk7XG5cbiAgICAgICAgICAgICAgY2FzZSBcImdldG1ldGFkYXRhXCI6XG4gICAgICAgICAgICAgICAgcmV0dXJuIGlucHV0ICYmIGlucHV0LmlucHV0bWFzayA/IGlucHV0LmlucHV0bWFzay5nZXRtZXRhZGF0YSgpIDogdm9pZCAwO1xuXG4gICAgICAgICAgICAgIGNhc2UgXCJzZXR2YWx1ZVwiOlxuICAgICAgICAgICAgICAgICQoaW5wdXQpLnZhbChvcHRpb25zKSwgaW5wdXQgJiYgdm9pZCAwID09PSBpbnB1dC5pbnB1dG1hc2sgJiYgJChpbnB1dCkudHJpZ2dlckhhbmRsZXIoXCJzZXR2YWx1ZVwiKTtcbiAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgICBjYXNlIFwib3B0aW9uXCI6XG4gICAgICAgICAgICAgICAgaWYgKFwic3RyaW5nXCIgIT0gdHlwZW9mIG9wdGlvbnMpIHJldHVybiB0aGlzLmVhY2goZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh2b2lkIDAgIT09IHRoaXMuaW5wdXRtYXNrKSByZXR1cm4gdGhpcy5pbnB1dG1hc2sub3B0aW9uKG9wdGlvbnMpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIGlmIChpbnB1dCAmJiB2b2lkIDAgIT09IGlucHV0LmlucHV0bWFzaykgcmV0dXJuIGlucHV0LmlucHV0bWFzay5vcHRpb24ob3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICByZXR1cm4gb3B0aW9ucy5hbGlhcyA9IGZuLCBucHRtYXNrID0gbmV3IElucHV0bWFzayhvcHRpb25zKSwgdGhpcy5lYWNoKGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICBucHRtYXNrLm1hc2sodGhpcyk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGlmIChcIm9iamVjdFwiID09ICh2b2lkIDAgPT09IGZuID8gXCJ1bmRlZmluZWRcIiA6IF90eXBlb2YoZm4pKSkgcmV0dXJuIG5wdG1hc2sgPSBuZXcgSW5wdXRtYXNrKGZuKSwgXG4gICAgICAgICAgICAgICAgdm9pZCAwID09PSBmbi5tYXNrICYmIHZvaWQgMCA9PT0gZm4uYWxpYXMgPyB0aGlzLmVhY2goZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh2b2lkIDAgIT09IHRoaXMuaW5wdXRtYXNrKSByZXR1cm4gdGhpcy5pbnB1dG1hc2sub3B0aW9uKGZuKTtcbiAgICAgICAgICAgICAgICAgICAgbnB0bWFzay5tYXNrKHRoaXMpO1xuICAgICAgICAgICAgICAgIH0pIDogdGhpcy5lYWNoKGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICBucHRtYXNrLm1hc2sodGhpcyk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgaWYgKHZvaWQgMCA9PT0gZm4pIHJldHVybiB0aGlzLmVhY2goZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgIChucHRtYXNrID0gbmV3IElucHV0bWFzayhvcHRpb25zKSkubWFzayh0aGlzKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSksICQuZm4uaW5wdXRtYXNrO1xuICAgIH0pO1xufSBdKTsiLCIoIGZ1bmN0aW9uKCBmYWN0b3J5ICkge1xuXHRpZiAoIHR5cGVvZiBkZWZpbmUgPT09IFwiZnVuY3Rpb25cIiAmJiBkZWZpbmUuYW1kICkge1xuXG5cdFx0Ly8gQU1ELiBSZWdpc3RlciBhcyBhbiBhbm9ueW1vdXMgbW9kdWxlLlxuXHRcdGRlZmluZSggWyBcImpxdWVyeVwiIF0sIGZhY3RvcnkgKTtcblx0fSBlbHNlIHtcblxuXHRcdC8vIEJyb3dzZXIgZ2xvYmFsc1xuXHRcdGZhY3RvcnkoIGpRdWVyeSApO1xuXHR9XG59ICggZnVuY3Rpb24oICQgKSB7XG5cbiQudWkgPSAkLnVpIHx8IHt9O1xuXG5yZXR1cm4gJC51aS52ZXJzaW9uID0gXCIxLjEyLjFcIjtcblxufSApICk7XG4iLCIvKiFcbiAqIGpRdWVyeSBVSSBQb3NpdGlvbiAxLjEyLjFcbiAqIGh0dHA6Ly9qcXVlcnl1aS5jb21cbiAqXG4gKiBDb3B5cmlnaHQgalF1ZXJ5IEZvdW5kYXRpb24gYW5kIG90aGVyIGNvbnRyaWJ1dG9yc1xuICogUmVsZWFzZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlLlxuICogaHR0cDovL2pxdWVyeS5vcmcvbGljZW5zZVxuICpcbiAqIGh0dHA6Ly9hcGkuanF1ZXJ5dWkuY29tL3Bvc2l0aW9uL1xuICovXG5cbi8vPj5sYWJlbDogUG9zaXRpb25cbi8vPj5ncm91cDogQ29yZVxuLy8+PmRlc2NyaXB0aW9uOiBQb3NpdGlvbnMgZWxlbWVudHMgcmVsYXRpdmUgdG8gb3RoZXIgZWxlbWVudHMuXG4vLz4+ZG9jczogaHR0cDovL2FwaS5qcXVlcnl1aS5jb20vcG9zaXRpb24vXG4vLz4+ZGVtb3M6IGh0dHA6Ly9qcXVlcnl1aS5jb20vcG9zaXRpb24vXG5cbiggZnVuY3Rpb24oIGZhY3RvcnkgKSB7XG5cdGlmICggdHlwZW9mIGRlZmluZSA9PT0gXCJmdW5jdGlvblwiICYmIGRlZmluZS5hbWQgKSB7XG5cblx0XHQvLyBBTUQuIFJlZ2lzdGVyIGFzIGFuIGFub255bW91cyBtb2R1bGUuXG5cdFx0ZGVmaW5lKCBbIFwianF1ZXJ5XCIsIFwiLi92ZXJzaW9uXCIgXSwgZmFjdG9yeSApO1xuXHR9IGVsc2Uge1xuXG5cdFx0Ly8gQnJvd3NlciBnbG9iYWxzXG5cdFx0ZmFjdG9yeSggalF1ZXJ5ICk7XG5cdH1cbn0oIGZ1bmN0aW9uKCAkICkge1xuKCBmdW5jdGlvbigpIHtcbnZhciBjYWNoZWRTY3JvbGxiYXJXaWR0aCxcblx0bWF4ID0gTWF0aC5tYXgsXG5cdGFicyA9IE1hdGguYWJzLFxuXHRyaG9yaXpvbnRhbCA9IC9sZWZ0fGNlbnRlcnxyaWdodC8sXG5cdHJ2ZXJ0aWNhbCA9IC90b3B8Y2VudGVyfGJvdHRvbS8sXG5cdHJvZmZzZXQgPSAvW1xcK1xcLV1cXGQrKFxcLltcXGRdKyk/JT8vLFxuXHRycG9zaXRpb24gPSAvXlxcdysvLFxuXHRycGVyY2VudCA9IC8lJC8sXG5cdF9wb3NpdGlvbiA9ICQuZm4ucG9zaXRpb247XG5cbmZ1bmN0aW9uIGdldE9mZnNldHMoIG9mZnNldHMsIHdpZHRoLCBoZWlnaHQgKSB7XG5cdHJldHVybiBbXG5cdFx0cGFyc2VGbG9hdCggb2Zmc2V0c1sgMCBdICkgKiAoIHJwZXJjZW50LnRlc3QoIG9mZnNldHNbIDAgXSApID8gd2lkdGggLyAxMDAgOiAxICksXG5cdFx0cGFyc2VGbG9hdCggb2Zmc2V0c1sgMSBdICkgKiAoIHJwZXJjZW50LnRlc3QoIG9mZnNldHNbIDEgXSApID8gaGVpZ2h0IC8gMTAwIDogMSApXG5cdF07XG59XG5cbmZ1bmN0aW9uIHBhcnNlQ3NzKCBlbGVtZW50LCBwcm9wZXJ0eSApIHtcblx0cmV0dXJuIHBhcnNlSW50KCAkLmNzcyggZWxlbWVudCwgcHJvcGVydHkgKSwgMTAgKSB8fCAwO1xufVxuXG5mdW5jdGlvbiBnZXREaW1lbnNpb25zKCBlbGVtICkge1xuXHR2YXIgcmF3ID0gZWxlbVsgMCBdO1xuXHRpZiAoIHJhdy5ub2RlVHlwZSA9PT0gOSApIHtcblx0XHRyZXR1cm4ge1xuXHRcdFx0d2lkdGg6IGVsZW0ud2lkdGgoKSxcblx0XHRcdGhlaWdodDogZWxlbS5oZWlnaHQoKSxcblx0XHRcdG9mZnNldDogeyB0b3A6IDAsIGxlZnQ6IDAgfVxuXHRcdH07XG5cdH1cblx0aWYgKCAkLmlzV2luZG93KCByYXcgKSApIHtcblx0XHRyZXR1cm4ge1xuXHRcdFx0d2lkdGg6IGVsZW0ud2lkdGgoKSxcblx0XHRcdGhlaWdodDogZWxlbS5oZWlnaHQoKSxcblx0XHRcdG9mZnNldDogeyB0b3A6IGVsZW0uc2Nyb2xsVG9wKCksIGxlZnQ6IGVsZW0uc2Nyb2xsTGVmdCgpIH1cblx0XHR9O1xuXHR9XG5cdGlmICggcmF3LnByZXZlbnREZWZhdWx0ICkge1xuXHRcdHJldHVybiB7XG5cdFx0XHR3aWR0aDogMCxcblx0XHRcdGhlaWdodDogMCxcblx0XHRcdG9mZnNldDogeyB0b3A6IHJhdy5wYWdlWSwgbGVmdDogcmF3LnBhZ2VYIH1cblx0XHR9O1xuXHR9XG5cdHJldHVybiB7XG5cdFx0d2lkdGg6IGVsZW0ub3V0ZXJXaWR0aCgpLFxuXHRcdGhlaWdodDogZWxlbS5vdXRlckhlaWdodCgpLFxuXHRcdG9mZnNldDogZWxlbS5vZmZzZXQoKVxuXHR9O1xufVxuXG4kLnBvc2l0aW9uID0ge1xuXHRzY3JvbGxiYXJXaWR0aDogZnVuY3Rpb24oKSB7XG5cdFx0aWYgKCBjYWNoZWRTY3JvbGxiYXJXaWR0aCAhPT0gdW5kZWZpbmVkICkge1xuXHRcdFx0cmV0dXJuIGNhY2hlZFNjcm9sbGJhcldpZHRoO1xuXHRcdH1cblx0XHR2YXIgdzEsIHcyLFxuXHRcdFx0ZGl2ID0gJCggXCI8ZGl2IFwiICtcblx0XHRcdFx0XCJzdHlsZT0nZGlzcGxheTpibG9jaztwb3NpdGlvbjphYnNvbHV0ZTt3aWR0aDo1MHB4O2hlaWdodDo1MHB4O292ZXJmbG93OmhpZGRlbjsnPlwiICtcblx0XHRcdFx0XCI8ZGl2IHN0eWxlPSdoZWlnaHQ6MTAwcHg7d2lkdGg6YXV0bzsnPjwvZGl2PjwvZGl2PlwiICksXG5cdFx0XHRpbm5lckRpdiA9IGRpdi5jaGlsZHJlbigpWyAwIF07XG5cblx0XHQkKCBcImJvZHlcIiApLmFwcGVuZCggZGl2ICk7XG5cdFx0dzEgPSBpbm5lckRpdi5vZmZzZXRXaWR0aDtcblx0XHRkaXYuY3NzKCBcIm92ZXJmbG93XCIsIFwic2Nyb2xsXCIgKTtcblxuXHRcdHcyID0gaW5uZXJEaXYub2Zmc2V0V2lkdGg7XG5cblx0XHRpZiAoIHcxID09PSB3MiApIHtcblx0XHRcdHcyID0gZGl2WyAwIF0uY2xpZW50V2lkdGg7XG5cdFx0fVxuXG5cdFx0ZGl2LnJlbW92ZSgpO1xuXG5cdFx0cmV0dXJuICggY2FjaGVkU2Nyb2xsYmFyV2lkdGggPSB3MSAtIHcyICk7XG5cdH0sXG5cdGdldFNjcm9sbEluZm86IGZ1bmN0aW9uKCB3aXRoaW4gKSB7XG5cdFx0dmFyIG92ZXJmbG93WCA9IHdpdGhpbi5pc1dpbmRvdyB8fCB3aXRoaW4uaXNEb2N1bWVudCA/IFwiXCIgOlxuXHRcdFx0XHR3aXRoaW4uZWxlbWVudC5jc3MoIFwib3ZlcmZsb3cteFwiICksXG5cdFx0XHRvdmVyZmxvd1kgPSB3aXRoaW4uaXNXaW5kb3cgfHwgd2l0aGluLmlzRG9jdW1lbnQgPyBcIlwiIDpcblx0XHRcdFx0d2l0aGluLmVsZW1lbnQuY3NzKCBcIm92ZXJmbG93LXlcIiApLFxuXHRcdFx0aGFzT3ZlcmZsb3dYID0gb3ZlcmZsb3dYID09PSBcInNjcm9sbFwiIHx8XG5cdFx0XHRcdCggb3ZlcmZsb3dYID09PSBcImF1dG9cIiAmJiB3aXRoaW4ud2lkdGggPCB3aXRoaW4uZWxlbWVudFsgMCBdLnNjcm9sbFdpZHRoICksXG5cdFx0XHRoYXNPdmVyZmxvd1kgPSBvdmVyZmxvd1kgPT09IFwic2Nyb2xsXCIgfHxcblx0XHRcdFx0KCBvdmVyZmxvd1kgPT09IFwiYXV0b1wiICYmIHdpdGhpbi5oZWlnaHQgPCB3aXRoaW4uZWxlbWVudFsgMCBdLnNjcm9sbEhlaWdodCApO1xuXHRcdHJldHVybiB7XG5cdFx0XHR3aWR0aDogaGFzT3ZlcmZsb3dZID8gJC5wb3NpdGlvbi5zY3JvbGxiYXJXaWR0aCgpIDogMCxcblx0XHRcdGhlaWdodDogaGFzT3ZlcmZsb3dYID8gJC5wb3NpdGlvbi5zY3JvbGxiYXJXaWR0aCgpIDogMFxuXHRcdH07XG5cdH0sXG5cdGdldFdpdGhpbkluZm86IGZ1bmN0aW9uKCBlbGVtZW50ICkge1xuXHRcdHZhciB3aXRoaW5FbGVtZW50ID0gJCggZWxlbWVudCB8fCB3aW5kb3cgKSxcblx0XHRcdGlzV2luZG93ID0gJC5pc1dpbmRvdyggd2l0aGluRWxlbWVudFsgMCBdICksXG5cdFx0XHRpc0RvY3VtZW50ID0gISF3aXRoaW5FbGVtZW50WyAwIF0gJiYgd2l0aGluRWxlbWVudFsgMCBdLm5vZGVUeXBlID09PSA5LFxuXHRcdFx0aGFzT2Zmc2V0ID0gIWlzV2luZG93ICYmICFpc0RvY3VtZW50O1xuXHRcdHJldHVybiB7XG5cdFx0XHRlbGVtZW50OiB3aXRoaW5FbGVtZW50LFxuXHRcdFx0aXNXaW5kb3c6IGlzV2luZG93LFxuXHRcdFx0aXNEb2N1bWVudDogaXNEb2N1bWVudCxcblx0XHRcdG9mZnNldDogaGFzT2Zmc2V0ID8gJCggZWxlbWVudCApLm9mZnNldCgpIDogeyBsZWZ0OiAwLCB0b3A6IDAgfSxcblx0XHRcdHNjcm9sbExlZnQ6IHdpdGhpbkVsZW1lbnQuc2Nyb2xsTGVmdCgpLFxuXHRcdFx0c2Nyb2xsVG9wOiB3aXRoaW5FbGVtZW50LnNjcm9sbFRvcCgpLFxuXHRcdFx0d2lkdGg6IHdpdGhpbkVsZW1lbnQub3V0ZXJXaWR0aCgpLFxuXHRcdFx0aGVpZ2h0OiB3aXRoaW5FbGVtZW50Lm91dGVySGVpZ2h0KClcblx0XHR9O1xuXHR9XG59O1xuXG4kLmZuLnBvc2l0aW9uID0gZnVuY3Rpb24oIG9wdGlvbnMgKSB7XG5cdGlmICggIW9wdGlvbnMgfHwgIW9wdGlvbnMub2YgKSB7XG5cdFx0cmV0dXJuIF9wb3NpdGlvbi5hcHBseSggdGhpcywgYXJndW1lbnRzICk7XG5cdH1cblxuXHQvLyBNYWtlIGEgY29weSwgd2UgZG9uJ3Qgd2FudCB0byBtb2RpZnkgYXJndW1lbnRzXG5cdG9wdGlvbnMgPSAkLmV4dGVuZCgge30sIG9wdGlvbnMgKTtcblxuXHR2YXIgYXRPZmZzZXQsIHRhcmdldFdpZHRoLCB0YXJnZXRIZWlnaHQsIHRhcmdldE9mZnNldCwgYmFzZVBvc2l0aW9uLCBkaW1lbnNpb25zLFxuXHRcdHRhcmdldCA9ICQoIG9wdGlvbnMub2YgKSxcblx0XHR3aXRoaW4gPSAkLnBvc2l0aW9uLmdldFdpdGhpbkluZm8oIG9wdGlvbnMud2l0aGluICksXG5cdFx0c2Nyb2xsSW5mbyA9ICQucG9zaXRpb24uZ2V0U2Nyb2xsSW5mbyggd2l0aGluICksXG5cdFx0Y29sbGlzaW9uID0gKCBvcHRpb25zLmNvbGxpc2lvbiB8fCBcImZsaXBcIiApLnNwbGl0KCBcIiBcIiApLFxuXHRcdG9mZnNldHMgPSB7fTtcblxuXHRkaW1lbnNpb25zID0gZ2V0RGltZW5zaW9ucyggdGFyZ2V0ICk7XG5cdGlmICggdGFyZ2V0WyAwIF0ucHJldmVudERlZmF1bHQgKSB7XG5cblx0XHQvLyBGb3JjZSBsZWZ0IHRvcCB0byBhbGxvdyBmbGlwcGluZ1xuXHRcdG9wdGlvbnMuYXQgPSBcImxlZnQgdG9wXCI7XG5cdH1cblx0dGFyZ2V0V2lkdGggPSBkaW1lbnNpb25zLndpZHRoO1xuXHR0YXJnZXRIZWlnaHQgPSBkaW1lbnNpb25zLmhlaWdodDtcblx0dGFyZ2V0T2Zmc2V0ID0gZGltZW5zaW9ucy5vZmZzZXQ7XG5cblx0Ly8gQ2xvbmUgdG8gcmV1c2Ugb3JpZ2luYWwgdGFyZ2V0T2Zmc2V0IGxhdGVyXG5cdGJhc2VQb3NpdGlvbiA9ICQuZXh0ZW5kKCB7fSwgdGFyZ2V0T2Zmc2V0ICk7XG5cblx0Ly8gRm9yY2UgbXkgYW5kIGF0IHRvIGhhdmUgdmFsaWQgaG9yaXpvbnRhbCBhbmQgdmVydGljYWwgcG9zaXRpb25zXG5cdC8vIGlmIGEgdmFsdWUgaXMgbWlzc2luZyBvciBpbnZhbGlkLCBpdCB3aWxsIGJlIGNvbnZlcnRlZCB0byBjZW50ZXJcblx0JC5lYWNoKCBbIFwibXlcIiwgXCJhdFwiIF0sIGZ1bmN0aW9uKCkge1xuXHRcdHZhciBwb3MgPSAoIG9wdGlvbnNbIHRoaXMgXSB8fCBcIlwiICkuc3BsaXQoIFwiIFwiICksXG5cdFx0XHRob3Jpem9udGFsT2Zmc2V0LFxuXHRcdFx0dmVydGljYWxPZmZzZXQ7XG5cblx0XHRpZiAoIHBvcy5sZW5ndGggPT09IDEgKSB7XG5cdFx0XHRwb3MgPSByaG9yaXpvbnRhbC50ZXN0KCBwb3NbIDAgXSApID9cblx0XHRcdFx0cG9zLmNvbmNhdCggWyBcImNlbnRlclwiIF0gKSA6XG5cdFx0XHRcdHJ2ZXJ0aWNhbC50ZXN0KCBwb3NbIDAgXSApID9cblx0XHRcdFx0XHRbIFwiY2VudGVyXCIgXS5jb25jYXQoIHBvcyApIDpcblx0XHRcdFx0XHRbIFwiY2VudGVyXCIsIFwiY2VudGVyXCIgXTtcblx0XHR9XG5cdFx0cG9zWyAwIF0gPSByaG9yaXpvbnRhbC50ZXN0KCBwb3NbIDAgXSApID8gcG9zWyAwIF0gOiBcImNlbnRlclwiO1xuXHRcdHBvc1sgMSBdID0gcnZlcnRpY2FsLnRlc3QoIHBvc1sgMSBdICkgPyBwb3NbIDEgXSA6IFwiY2VudGVyXCI7XG5cblx0XHQvLyBDYWxjdWxhdGUgb2Zmc2V0c1xuXHRcdGhvcml6b250YWxPZmZzZXQgPSByb2Zmc2V0LmV4ZWMoIHBvc1sgMCBdICk7XG5cdFx0dmVydGljYWxPZmZzZXQgPSByb2Zmc2V0LmV4ZWMoIHBvc1sgMSBdICk7XG5cdFx0b2Zmc2V0c1sgdGhpcyBdID0gW1xuXHRcdFx0aG9yaXpvbnRhbE9mZnNldCA/IGhvcml6b250YWxPZmZzZXRbIDAgXSA6IDAsXG5cdFx0XHR2ZXJ0aWNhbE9mZnNldCA/IHZlcnRpY2FsT2Zmc2V0WyAwIF0gOiAwXG5cdFx0XTtcblxuXHRcdC8vIFJlZHVjZSB0byBqdXN0IHRoZSBwb3NpdGlvbnMgd2l0aG91dCB0aGUgb2Zmc2V0c1xuXHRcdG9wdGlvbnNbIHRoaXMgXSA9IFtcblx0XHRcdHJwb3NpdGlvbi5leGVjKCBwb3NbIDAgXSApWyAwIF0sXG5cdFx0XHRycG9zaXRpb24uZXhlYyggcG9zWyAxIF0gKVsgMCBdXG5cdFx0XTtcblx0fSApO1xuXG5cdC8vIE5vcm1hbGl6ZSBjb2xsaXNpb24gb3B0aW9uXG5cdGlmICggY29sbGlzaW9uLmxlbmd0aCA9PT0gMSApIHtcblx0XHRjb2xsaXNpb25bIDEgXSA9IGNvbGxpc2lvblsgMCBdO1xuXHR9XG5cblx0aWYgKCBvcHRpb25zLmF0WyAwIF0gPT09IFwicmlnaHRcIiApIHtcblx0XHRiYXNlUG9zaXRpb24ubGVmdCArPSB0YXJnZXRXaWR0aDtcblx0fSBlbHNlIGlmICggb3B0aW9ucy5hdFsgMCBdID09PSBcImNlbnRlclwiICkge1xuXHRcdGJhc2VQb3NpdGlvbi5sZWZ0ICs9IHRhcmdldFdpZHRoIC8gMjtcblx0fVxuXG5cdGlmICggb3B0aW9ucy5hdFsgMSBdID09PSBcImJvdHRvbVwiICkge1xuXHRcdGJhc2VQb3NpdGlvbi50b3AgKz0gdGFyZ2V0SGVpZ2h0O1xuXHR9IGVsc2UgaWYgKCBvcHRpb25zLmF0WyAxIF0gPT09IFwiY2VudGVyXCIgKSB7XG5cdFx0YmFzZVBvc2l0aW9uLnRvcCArPSB0YXJnZXRIZWlnaHQgLyAyO1xuXHR9XG5cblx0YXRPZmZzZXQgPSBnZXRPZmZzZXRzKCBvZmZzZXRzLmF0LCB0YXJnZXRXaWR0aCwgdGFyZ2V0SGVpZ2h0ICk7XG5cdGJhc2VQb3NpdGlvbi5sZWZ0ICs9IGF0T2Zmc2V0WyAwIF07XG5cdGJhc2VQb3NpdGlvbi50b3AgKz0gYXRPZmZzZXRbIDEgXTtcblxuXHRyZXR1cm4gdGhpcy5lYWNoKCBmdW5jdGlvbigpIHtcblx0XHR2YXIgY29sbGlzaW9uUG9zaXRpb24sIHVzaW5nLFxuXHRcdFx0ZWxlbSA9ICQoIHRoaXMgKSxcblx0XHRcdGVsZW1XaWR0aCA9IGVsZW0ub3V0ZXJXaWR0aCgpLFxuXHRcdFx0ZWxlbUhlaWdodCA9IGVsZW0ub3V0ZXJIZWlnaHQoKSxcblx0XHRcdG1hcmdpbkxlZnQgPSBwYXJzZUNzcyggdGhpcywgXCJtYXJnaW5MZWZ0XCIgKSxcblx0XHRcdG1hcmdpblRvcCA9IHBhcnNlQ3NzKCB0aGlzLCBcIm1hcmdpblRvcFwiICksXG5cdFx0XHRjb2xsaXNpb25XaWR0aCA9IGVsZW1XaWR0aCArIG1hcmdpbkxlZnQgKyBwYXJzZUNzcyggdGhpcywgXCJtYXJnaW5SaWdodFwiICkgK1xuXHRcdFx0XHRzY3JvbGxJbmZvLndpZHRoLFxuXHRcdFx0Y29sbGlzaW9uSGVpZ2h0ID0gZWxlbUhlaWdodCArIG1hcmdpblRvcCArIHBhcnNlQ3NzKCB0aGlzLCBcIm1hcmdpbkJvdHRvbVwiICkgK1xuXHRcdFx0XHRzY3JvbGxJbmZvLmhlaWdodCxcblx0XHRcdHBvc2l0aW9uID0gJC5leHRlbmQoIHt9LCBiYXNlUG9zaXRpb24gKSxcblx0XHRcdG15T2Zmc2V0ID0gZ2V0T2Zmc2V0cyggb2Zmc2V0cy5teSwgZWxlbS5vdXRlcldpZHRoKCksIGVsZW0ub3V0ZXJIZWlnaHQoKSApO1xuXG5cdFx0aWYgKCBvcHRpb25zLm15WyAwIF0gPT09IFwicmlnaHRcIiApIHtcblx0XHRcdHBvc2l0aW9uLmxlZnQgLT0gZWxlbVdpZHRoO1xuXHRcdH0gZWxzZSBpZiAoIG9wdGlvbnMubXlbIDAgXSA9PT0gXCJjZW50ZXJcIiApIHtcblx0XHRcdHBvc2l0aW9uLmxlZnQgLT0gZWxlbVdpZHRoIC8gMjtcblx0XHR9XG5cblx0XHRpZiAoIG9wdGlvbnMubXlbIDEgXSA9PT0gXCJib3R0b21cIiApIHtcblx0XHRcdHBvc2l0aW9uLnRvcCAtPSBlbGVtSGVpZ2h0O1xuXHRcdH0gZWxzZSBpZiAoIG9wdGlvbnMubXlbIDEgXSA9PT0gXCJjZW50ZXJcIiApIHtcblx0XHRcdHBvc2l0aW9uLnRvcCAtPSBlbGVtSGVpZ2h0IC8gMjtcblx0XHR9XG5cblx0XHRwb3NpdGlvbi5sZWZ0ICs9IG15T2Zmc2V0WyAwIF07XG5cdFx0cG9zaXRpb24udG9wICs9IG15T2Zmc2V0WyAxIF07XG5cblx0XHRjb2xsaXNpb25Qb3NpdGlvbiA9IHtcblx0XHRcdG1hcmdpbkxlZnQ6IG1hcmdpbkxlZnQsXG5cdFx0XHRtYXJnaW5Ub3A6IG1hcmdpblRvcFxuXHRcdH07XG5cblx0XHQkLmVhY2goIFsgXCJsZWZ0XCIsIFwidG9wXCIgXSwgZnVuY3Rpb24oIGksIGRpciApIHtcblx0XHRcdGlmICggJC51aS5wb3NpdGlvblsgY29sbGlzaW9uWyBpIF0gXSApIHtcblx0XHRcdFx0JC51aS5wb3NpdGlvblsgY29sbGlzaW9uWyBpIF0gXVsgZGlyIF0oIHBvc2l0aW9uLCB7XG5cdFx0XHRcdFx0dGFyZ2V0V2lkdGg6IHRhcmdldFdpZHRoLFxuXHRcdFx0XHRcdHRhcmdldEhlaWdodDogdGFyZ2V0SGVpZ2h0LFxuXHRcdFx0XHRcdGVsZW1XaWR0aDogZWxlbVdpZHRoLFxuXHRcdFx0XHRcdGVsZW1IZWlnaHQ6IGVsZW1IZWlnaHQsXG5cdFx0XHRcdFx0Y29sbGlzaW9uUG9zaXRpb246IGNvbGxpc2lvblBvc2l0aW9uLFxuXHRcdFx0XHRcdGNvbGxpc2lvbldpZHRoOiBjb2xsaXNpb25XaWR0aCxcblx0XHRcdFx0XHRjb2xsaXNpb25IZWlnaHQ6IGNvbGxpc2lvbkhlaWdodCxcblx0XHRcdFx0XHRvZmZzZXQ6IFsgYXRPZmZzZXRbIDAgXSArIG15T2Zmc2V0WyAwIF0sIGF0T2Zmc2V0IFsgMSBdICsgbXlPZmZzZXRbIDEgXSBdLFxuXHRcdFx0XHRcdG15OiBvcHRpb25zLm15LFxuXHRcdFx0XHRcdGF0OiBvcHRpb25zLmF0LFxuXHRcdFx0XHRcdHdpdGhpbjogd2l0aGluLFxuXHRcdFx0XHRcdGVsZW06IGVsZW1cblx0XHRcdFx0fSApO1xuXHRcdFx0fVxuXHRcdH0gKTtcblxuXHRcdGlmICggb3B0aW9ucy51c2luZyApIHtcblxuXHRcdFx0Ly8gQWRkcyBmZWVkYmFjayBhcyBzZWNvbmQgYXJndW1lbnQgdG8gdXNpbmcgY2FsbGJhY2ssIGlmIHByZXNlbnRcblx0XHRcdHVzaW5nID0gZnVuY3Rpb24oIHByb3BzICkge1xuXHRcdFx0XHR2YXIgbGVmdCA9IHRhcmdldE9mZnNldC5sZWZ0IC0gcG9zaXRpb24ubGVmdCxcblx0XHRcdFx0XHRyaWdodCA9IGxlZnQgKyB0YXJnZXRXaWR0aCAtIGVsZW1XaWR0aCxcblx0XHRcdFx0XHR0b3AgPSB0YXJnZXRPZmZzZXQudG9wIC0gcG9zaXRpb24udG9wLFxuXHRcdFx0XHRcdGJvdHRvbSA9IHRvcCArIHRhcmdldEhlaWdodCAtIGVsZW1IZWlnaHQsXG5cdFx0XHRcdFx0ZmVlZGJhY2sgPSB7XG5cdFx0XHRcdFx0XHR0YXJnZXQ6IHtcblx0XHRcdFx0XHRcdFx0ZWxlbWVudDogdGFyZ2V0LFxuXHRcdFx0XHRcdFx0XHRsZWZ0OiB0YXJnZXRPZmZzZXQubGVmdCxcblx0XHRcdFx0XHRcdFx0dG9wOiB0YXJnZXRPZmZzZXQudG9wLFxuXHRcdFx0XHRcdFx0XHR3aWR0aDogdGFyZ2V0V2lkdGgsXG5cdFx0XHRcdFx0XHRcdGhlaWdodDogdGFyZ2V0SGVpZ2h0XG5cdFx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdFx0ZWxlbWVudDoge1xuXHRcdFx0XHRcdFx0XHRlbGVtZW50OiBlbGVtLFxuXHRcdFx0XHRcdFx0XHRsZWZ0OiBwb3NpdGlvbi5sZWZ0LFxuXHRcdFx0XHRcdFx0XHR0b3A6IHBvc2l0aW9uLnRvcCxcblx0XHRcdFx0XHRcdFx0d2lkdGg6IGVsZW1XaWR0aCxcblx0XHRcdFx0XHRcdFx0aGVpZ2h0OiBlbGVtSGVpZ2h0XG5cdFx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdFx0aG9yaXpvbnRhbDogcmlnaHQgPCAwID8gXCJsZWZ0XCIgOiBsZWZ0ID4gMCA/IFwicmlnaHRcIiA6IFwiY2VudGVyXCIsXG5cdFx0XHRcdFx0XHR2ZXJ0aWNhbDogYm90dG9tIDwgMCA/IFwidG9wXCIgOiB0b3AgPiAwID8gXCJib3R0b21cIiA6IFwibWlkZGxlXCJcblx0XHRcdFx0XHR9O1xuXHRcdFx0XHRpZiAoIHRhcmdldFdpZHRoIDwgZWxlbVdpZHRoICYmIGFicyggbGVmdCArIHJpZ2h0ICkgPCB0YXJnZXRXaWR0aCApIHtcblx0XHRcdFx0XHRmZWVkYmFjay5ob3Jpem9udGFsID0gXCJjZW50ZXJcIjtcblx0XHRcdFx0fVxuXHRcdFx0XHRpZiAoIHRhcmdldEhlaWdodCA8IGVsZW1IZWlnaHQgJiYgYWJzKCB0b3AgKyBib3R0b20gKSA8IHRhcmdldEhlaWdodCApIHtcblx0XHRcdFx0XHRmZWVkYmFjay52ZXJ0aWNhbCA9IFwibWlkZGxlXCI7XG5cdFx0XHRcdH1cblx0XHRcdFx0aWYgKCBtYXgoIGFicyggbGVmdCApLCBhYnMoIHJpZ2h0ICkgKSA+IG1heCggYWJzKCB0b3AgKSwgYWJzKCBib3R0b20gKSApICkge1xuXHRcdFx0XHRcdGZlZWRiYWNrLmltcG9ydGFudCA9IFwiaG9yaXpvbnRhbFwiO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdGZlZWRiYWNrLmltcG9ydGFudCA9IFwidmVydGljYWxcIjtcblx0XHRcdFx0fVxuXHRcdFx0XHRvcHRpb25zLnVzaW5nLmNhbGwoIHRoaXMsIHByb3BzLCBmZWVkYmFjayApO1xuXHRcdFx0fTtcblx0XHR9XG5cblx0XHRlbGVtLm9mZnNldCggJC5leHRlbmQoIHBvc2l0aW9uLCB7IHVzaW5nOiB1c2luZyB9ICkgKTtcblx0fSApO1xufTtcblxuJC51aS5wb3NpdGlvbiA9IHtcblx0Zml0OiB7XG5cdFx0bGVmdDogZnVuY3Rpb24oIHBvc2l0aW9uLCBkYXRhICkge1xuXHRcdFx0dmFyIHdpdGhpbiA9IGRhdGEud2l0aGluLFxuXHRcdFx0XHR3aXRoaW5PZmZzZXQgPSB3aXRoaW4uaXNXaW5kb3cgPyB3aXRoaW4uc2Nyb2xsTGVmdCA6IHdpdGhpbi5vZmZzZXQubGVmdCxcblx0XHRcdFx0b3V0ZXJXaWR0aCA9IHdpdGhpbi53aWR0aCxcblx0XHRcdFx0Y29sbGlzaW9uUG9zTGVmdCA9IHBvc2l0aW9uLmxlZnQgLSBkYXRhLmNvbGxpc2lvblBvc2l0aW9uLm1hcmdpbkxlZnQsXG5cdFx0XHRcdG92ZXJMZWZ0ID0gd2l0aGluT2Zmc2V0IC0gY29sbGlzaW9uUG9zTGVmdCxcblx0XHRcdFx0b3ZlclJpZ2h0ID0gY29sbGlzaW9uUG9zTGVmdCArIGRhdGEuY29sbGlzaW9uV2lkdGggLSBvdXRlcldpZHRoIC0gd2l0aGluT2Zmc2V0LFxuXHRcdFx0XHRuZXdPdmVyUmlnaHQ7XG5cblx0XHRcdC8vIEVsZW1lbnQgaXMgd2lkZXIgdGhhbiB3aXRoaW5cblx0XHRcdGlmICggZGF0YS5jb2xsaXNpb25XaWR0aCA+IG91dGVyV2lkdGggKSB7XG5cblx0XHRcdFx0Ly8gRWxlbWVudCBpcyBpbml0aWFsbHkgb3ZlciB0aGUgbGVmdCBzaWRlIG9mIHdpdGhpblxuXHRcdFx0XHRpZiAoIG92ZXJMZWZ0ID4gMCAmJiBvdmVyUmlnaHQgPD0gMCApIHtcblx0XHRcdFx0XHRuZXdPdmVyUmlnaHQgPSBwb3NpdGlvbi5sZWZ0ICsgb3ZlckxlZnQgKyBkYXRhLmNvbGxpc2lvbldpZHRoIC0gb3V0ZXJXaWR0aCAtXG5cdFx0XHRcdFx0XHR3aXRoaW5PZmZzZXQ7XG5cdFx0XHRcdFx0cG9zaXRpb24ubGVmdCArPSBvdmVyTGVmdCAtIG5ld092ZXJSaWdodDtcblxuXHRcdFx0XHQvLyBFbGVtZW50IGlzIGluaXRpYWxseSBvdmVyIHJpZ2h0IHNpZGUgb2Ygd2l0aGluXG5cdFx0XHRcdH0gZWxzZSBpZiAoIG92ZXJSaWdodCA+IDAgJiYgb3ZlckxlZnQgPD0gMCApIHtcblx0XHRcdFx0XHRwb3NpdGlvbi5sZWZ0ID0gd2l0aGluT2Zmc2V0O1xuXG5cdFx0XHRcdC8vIEVsZW1lbnQgaXMgaW5pdGlhbGx5IG92ZXIgYm90aCBsZWZ0IGFuZCByaWdodCBzaWRlcyBvZiB3aXRoaW5cblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRpZiAoIG92ZXJMZWZ0ID4gb3ZlclJpZ2h0ICkge1xuXHRcdFx0XHRcdFx0cG9zaXRpb24ubGVmdCA9IHdpdGhpbk9mZnNldCArIG91dGVyV2lkdGggLSBkYXRhLmNvbGxpc2lvbldpZHRoO1xuXHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRwb3NpdGlvbi5sZWZ0ID0gd2l0aGluT2Zmc2V0O1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXG5cdFx0XHQvLyBUb28gZmFyIGxlZnQgLT4gYWxpZ24gd2l0aCBsZWZ0IGVkZ2Vcblx0XHRcdH0gZWxzZSBpZiAoIG92ZXJMZWZ0ID4gMCApIHtcblx0XHRcdFx0cG9zaXRpb24ubGVmdCArPSBvdmVyTGVmdDtcblxuXHRcdFx0Ly8gVG9vIGZhciByaWdodCAtPiBhbGlnbiB3aXRoIHJpZ2h0IGVkZ2Vcblx0XHRcdH0gZWxzZSBpZiAoIG92ZXJSaWdodCA+IDAgKSB7XG5cdFx0XHRcdHBvc2l0aW9uLmxlZnQgLT0gb3ZlclJpZ2h0O1xuXG5cdFx0XHQvLyBBZGp1c3QgYmFzZWQgb24gcG9zaXRpb24gYW5kIG1hcmdpblxuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0cG9zaXRpb24ubGVmdCA9IG1heCggcG9zaXRpb24ubGVmdCAtIGNvbGxpc2lvblBvc0xlZnQsIHBvc2l0aW9uLmxlZnQgKTtcblx0XHRcdH1cblx0XHR9LFxuXHRcdHRvcDogZnVuY3Rpb24oIHBvc2l0aW9uLCBkYXRhICkge1xuXHRcdFx0dmFyIHdpdGhpbiA9IGRhdGEud2l0aGluLFxuXHRcdFx0XHR3aXRoaW5PZmZzZXQgPSB3aXRoaW4uaXNXaW5kb3cgPyB3aXRoaW4uc2Nyb2xsVG9wIDogd2l0aGluLm9mZnNldC50b3AsXG5cdFx0XHRcdG91dGVySGVpZ2h0ID0gZGF0YS53aXRoaW4uaGVpZ2h0LFxuXHRcdFx0XHRjb2xsaXNpb25Qb3NUb3AgPSBwb3NpdGlvbi50b3AgLSBkYXRhLmNvbGxpc2lvblBvc2l0aW9uLm1hcmdpblRvcCxcblx0XHRcdFx0b3ZlclRvcCA9IHdpdGhpbk9mZnNldCAtIGNvbGxpc2lvblBvc1RvcCxcblx0XHRcdFx0b3ZlckJvdHRvbSA9IGNvbGxpc2lvblBvc1RvcCArIGRhdGEuY29sbGlzaW9uSGVpZ2h0IC0gb3V0ZXJIZWlnaHQgLSB3aXRoaW5PZmZzZXQsXG5cdFx0XHRcdG5ld092ZXJCb3R0b207XG5cblx0XHRcdC8vIEVsZW1lbnQgaXMgdGFsbGVyIHRoYW4gd2l0aGluXG5cdFx0XHRpZiAoIGRhdGEuY29sbGlzaW9uSGVpZ2h0ID4gb3V0ZXJIZWlnaHQgKSB7XG5cblx0XHRcdFx0Ly8gRWxlbWVudCBpcyBpbml0aWFsbHkgb3ZlciB0aGUgdG9wIG9mIHdpdGhpblxuXHRcdFx0XHRpZiAoIG92ZXJUb3AgPiAwICYmIG92ZXJCb3R0b20gPD0gMCApIHtcblx0XHRcdFx0XHRuZXdPdmVyQm90dG9tID0gcG9zaXRpb24udG9wICsgb3ZlclRvcCArIGRhdGEuY29sbGlzaW9uSGVpZ2h0IC0gb3V0ZXJIZWlnaHQgLVxuXHRcdFx0XHRcdFx0d2l0aGluT2Zmc2V0O1xuXHRcdFx0XHRcdHBvc2l0aW9uLnRvcCArPSBvdmVyVG9wIC0gbmV3T3ZlckJvdHRvbTtcblxuXHRcdFx0XHQvLyBFbGVtZW50IGlzIGluaXRpYWxseSBvdmVyIGJvdHRvbSBvZiB3aXRoaW5cblx0XHRcdFx0fSBlbHNlIGlmICggb3ZlckJvdHRvbSA+IDAgJiYgb3ZlclRvcCA8PSAwICkge1xuXHRcdFx0XHRcdHBvc2l0aW9uLnRvcCA9IHdpdGhpbk9mZnNldDtcblxuXHRcdFx0XHQvLyBFbGVtZW50IGlzIGluaXRpYWxseSBvdmVyIGJvdGggdG9wIGFuZCBib3R0b20gb2Ygd2l0aGluXG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0aWYgKCBvdmVyVG9wID4gb3ZlckJvdHRvbSApIHtcblx0XHRcdFx0XHRcdHBvc2l0aW9uLnRvcCA9IHdpdGhpbk9mZnNldCArIG91dGVySGVpZ2h0IC0gZGF0YS5jb2xsaXNpb25IZWlnaHQ7XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdHBvc2l0aW9uLnRvcCA9IHdpdGhpbk9mZnNldDtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblxuXHRcdFx0Ly8gVG9vIGZhciB1cCAtPiBhbGlnbiB3aXRoIHRvcFxuXHRcdFx0fSBlbHNlIGlmICggb3ZlclRvcCA+IDAgKSB7XG5cdFx0XHRcdHBvc2l0aW9uLnRvcCArPSBvdmVyVG9wO1xuXG5cdFx0XHQvLyBUb28gZmFyIGRvd24gLT4gYWxpZ24gd2l0aCBib3R0b20gZWRnZVxuXHRcdFx0fSBlbHNlIGlmICggb3ZlckJvdHRvbSA+IDAgKSB7XG5cdFx0XHRcdHBvc2l0aW9uLnRvcCAtPSBvdmVyQm90dG9tO1xuXG5cdFx0XHQvLyBBZGp1c3QgYmFzZWQgb24gcG9zaXRpb24gYW5kIG1hcmdpblxuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0cG9zaXRpb24udG9wID0gbWF4KCBwb3NpdGlvbi50b3AgLSBjb2xsaXNpb25Qb3NUb3AsIHBvc2l0aW9uLnRvcCApO1xuXHRcdFx0fVxuXHRcdH1cblx0fSxcblx0ZmxpcDoge1xuXHRcdGxlZnQ6IGZ1bmN0aW9uKCBwb3NpdGlvbiwgZGF0YSApIHtcblx0XHRcdHZhciB3aXRoaW4gPSBkYXRhLndpdGhpbixcblx0XHRcdFx0d2l0aGluT2Zmc2V0ID0gd2l0aGluLm9mZnNldC5sZWZ0ICsgd2l0aGluLnNjcm9sbExlZnQsXG5cdFx0XHRcdG91dGVyV2lkdGggPSB3aXRoaW4ud2lkdGgsXG5cdFx0XHRcdG9mZnNldExlZnQgPSB3aXRoaW4uaXNXaW5kb3cgPyB3aXRoaW4uc2Nyb2xsTGVmdCA6IHdpdGhpbi5vZmZzZXQubGVmdCxcblx0XHRcdFx0Y29sbGlzaW9uUG9zTGVmdCA9IHBvc2l0aW9uLmxlZnQgLSBkYXRhLmNvbGxpc2lvblBvc2l0aW9uLm1hcmdpbkxlZnQsXG5cdFx0XHRcdG92ZXJMZWZ0ID0gY29sbGlzaW9uUG9zTGVmdCAtIG9mZnNldExlZnQsXG5cdFx0XHRcdG92ZXJSaWdodCA9IGNvbGxpc2lvblBvc0xlZnQgKyBkYXRhLmNvbGxpc2lvbldpZHRoIC0gb3V0ZXJXaWR0aCAtIG9mZnNldExlZnQsXG5cdFx0XHRcdG15T2Zmc2V0ID0gZGF0YS5teVsgMCBdID09PSBcImxlZnRcIiA/XG5cdFx0XHRcdFx0LWRhdGEuZWxlbVdpZHRoIDpcblx0XHRcdFx0XHRkYXRhLm15WyAwIF0gPT09IFwicmlnaHRcIiA/XG5cdFx0XHRcdFx0XHRkYXRhLmVsZW1XaWR0aCA6XG5cdFx0XHRcdFx0XHQwLFxuXHRcdFx0XHRhdE9mZnNldCA9IGRhdGEuYXRbIDAgXSA9PT0gXCJsZWZ0XCIgP1xuXHRcdFx0XHRcdGRhdGEudGFyZ2V0V2lkdGggOlxuXHRcdFx0XHRcdGRhdGEuYXRbIDAgXSA9PT0gXCJyaWdodFwiID9cblx0XHRcdFx0XHRcdC1kYXRhLnRhcmdldFdpZHRoIDpcblx0XHRcdFx0XHRcdDAsXG5cdFx0XHRcdG9mZnNldCA9IC0yICogZGF0YS5vZmZzZXRbIDAgXSxcblx0XHRcdFx0bmV3T3ZlclJpZ2h0LFxuXHRcdFx0XHRuZXdPdmVyTGVmdDtcblxuXHRcdFx0aWYgKCBvdmVyTGVmdCA8IDAgKSB7XG5cdFx0XHRcdG5ld092ZXJSaWdodCA9IHBvc2l0aW9uLmxlZnQgKyBteU9mZnNldCArIGF0T2Zmc2V0ICsgb2Zmc2V0ICsgZGF0YS5jb2xsaXNpb25XaWR0aCAtXG5cdFx0XHRcdFx0b3V0ZXJXaWR0aCAtIHdpdGhpbk9mZnNldDtcblx0XHRcdFx0aWYgKCBuZXdPdmVyUmlnaHQgPCAwIHx8IG5ld092ZXJSaWdodCA8IGFicyggb3ZlckxlZnQgKSApIHtcblx0XHRcdFx0XHRwb3NpdGlvbi5sZWZ0ICs9IG15T2Zmc2V0ICsgYXRPZmZzZXQgKyBvZmZzZXQ7XG5cdFx0XHRcdH1cblx0XHRcdH0gZWxzZSBpZiAoIG92ZXJSaWdodCA+IDAgKSB7XG5cdFx0XHRcdG5ld092ZXJMZWZ0ID0gcG9zaXRpb24ubGVmdCAtIGRhdGEuY29sbGlzaW9uUG9zaXRpb24ubWFyZ2luTGVmdCArIG15T2Zmc2V0ICtcblx0XHRcdFx0XHRhdE9mZnNldCArIG9mZnNldCAtIG9mZnNldExlZnQ7XG5cdFx0XHRcdGlmICggbmV3T3ZlckxlZnQgPiAwIHx8IGFicyggbmV3T3ZlckxlZnQgKSA8IG92ZXJSaWdodCApIHtcblx0XHRcdFx0XHRwb3NpdGlvbi5sZWZ0ICs9IG15T2Zmc2V0ICsgYXRPZmZzZXQgKyBvZmZzZXQ7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9LFxuXHRcdHRvcDogZnVuY3Rpb24oIHBvc2l0aW9uLCBkYXRhICkge1xuXHRcdFx0dmFyIHdpdGhpbiA9IGRhdGEud2l0aGluLFxuXHRcdFx0XHR3aXRoaW5PZmZzZXQgPSB3aXRoaW4ub2Zmc2V0LnRvcCArIHdpdGhpbi5zY3JvbGxUb3AsXG5cdFx0XHRcdG91dGVySGVpZ2h0ID0gd2l0aGluLmhlaWdodCxcblx0XHRcdFx0b2Zmc2V0VG9wID0gd2l0aGluLmlzV2luZG93ID8gd2l0aGluLnNjcm9sbFRvcCA6IHdpdGhpbi5vZmZzZXQudG9wLFxuXHRcdFx0XHRjb2xsaXNpb25Qb3NUb3AgPSBwb3NpdGlvbi50b3AgLSBkYXRhLmNvbGxpc2lvblBvc2l0aW9uLm1hcmdpblRvcCxcblx0XHRcdFx0b3ZlclRvcCA9IGNvbGxpc2lvblBvc1RvcCAtIG9mZnNldFRvcCxcblx0XHRcdFx0b3ZlckJvdHRvbSA9IGNvbGxpc2lvblBvc1RvcCArIGRhdGEuY29sbGlzaW9uSGVpZ2h0IC0gb3V0ZXJIZWlnaHQgLSBvZmZzZXRUb3AsXG5cdFx0XHRcdHRvcCA9IGRhdGEubXlbIDEgXSA9PT0gXCJ0b3BcIixcblx0XHRcdFx0bXlPZmZzZXQgPSB0b3AgP1xuXHRcdFx0XHRcdC1kYXRhLmVsZW1IZWlnaHQgOlxuXHRcdFx0XHRcdGRhdGEubXlbIDEgXSA9PT0gXCJib3R0b21cIiA/XG5cdFx0XHRcdFx0XHRkYXRhLmVsZW1IZWlnaHQgOlxuXHRcdFx0XHRcdFx0MCxcblx0XHRcdFx0YXRPZmZzZXQgPSBkYXRhLmF0WyAxIF0gPT09IFwidG9wXCIgP1xuXHRcdFx0XHRcdGRhdGEudGFyZ2V0SGVpZ2h0IDpcblx0XHRcdFx0XHRkYXRhLmF0WyAxIF0gPT09IFwiYm90dG9tXCIgP1xuXHRcdFx0XHRcdFx0LWRhdGEudGFyZ2V0SGVpZ2h0IDpcblx0XHRcdFx0XHRcdDAsXG5cdFx0XHRcdG9mZnNldCA9IC0yICogZGF0YS5vZmZzZXRbIDEgXSxcblx0XHRcdFx0bmV3T3ZlclRvcCxcblx0XHRcdFx0bmV3T3ZlckJvdHRvbTtcblx0XHRcdGlmICggb3ZlclRvcCA8IDAgKSB7XG5cdFx0XHRcdG5ld092ZXJCb3R0b20gPSBwb3NpdGlvbi50b3AgKyBteU9mZnNldCArIGF0T2Zmc2V0ICsgb2Zmc2V0ICsgZGF0YS5jb2xsaXNpb25IZWlnaHQgLVxuXHRcdFx0XHRcdG91dGVySGVpZ2h0IC0gd2l0aGluT2Zmc2V0O1xuXHRcdFx0XHRpZiAoIG5ld092ZXJCb3R0b20gPCAwIHx8IG5ld092ZXJCb3R0b20gPCBhYnMoIG92ZXJUb3AgKSApIHtcblx0XHRcdFx0XHRwb3NpdGlvbi50b3AgKz0gbXlPZmZzZXQgKyBhdE9mZnNldCArIG9mZnNldDtcblx0XHRcdFx0fVxuXHRcdFx0fSBlbHNlIGlmICggb3ZlckJvdHRvbSA+IDAgKSB7XG5cdFx0XHRcdG5ld092ZXJUb3AgPSBwb3NpdGlvbi50b3AgLSBkYXRhLmNvbGxpc2lvblBvc2l0aW9uLm1hcmdpblRvcCArIG15T2Zmc2V0ICsgYXRPZmZzZXQgK1xuXHRcdFx0XHRcdG9mZnNldCAtIG9mZnNldFRvcDtcblx0XHRcdFx0aWYgKCBuZXdPdmVyVG9wID4gMCB8fCBhYnMoIG5ld092ZXJUb3AgKSA8IG92ZXJCb3R0b20gKSB7XG5cdFx0XHRcdFx0cG9zaXRpb24udG9wICs9IG15T2Zmc2V0ICsgYXRPZmZzZXQgKyBvZmZzZXQ7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdH0sXG5cdGZsaXBmaXQ6IHtcblx0XHRsZWZ0OiBmdW5jdGlvbigpIHtcblx0XHRcdCQudWkucG9zaXRpb24uZmxpcC5sZWZ0LmFwcGx5KCB0aGlzLCBhcmd1bWVudHMgKTtcblx0XHRcdCQudWkucG9zaXRpb24uZml0LmxlZnQuYXBwbHkoIHRoaXMsIGFyZ3VtZW50cyApO1xuXHRcdH0sXG5cdFx0dG9wOiBmdW5jdGlvbigpIHtcblx0XHRcdCQudWkucG9zaXRpb24uZmxpcC50b3AuYXBwbHkoIHRoaXMsIGFyZ3VtZW50cyApO1xuXHRcdFx0JC51aS5wb3NpdGlvbi5maXQudG9wLmFwcGx5KCB0aGlzLCBhcmd1bWVudHMgKTtcblx0XHR9XG5cdH1cbn07XG5cbn0gKSgpO1xuXG5yZXR1cm4gJC51aS5wb3NpdGlvbjtcblxufSApICk7XG4iLCI7LyohIHNob3dkb3duIHYgMS44LjYgLSAyMi0xMi0yMDE3ICovXHJcbihmdW5jdGlvbigpe1xyXG4vKipcbiAqIENyZWF0ZWQgYnkgVGl2aWUgb24gMTMtMDctMjAxNS5cbiAqL1xuXG5mdW5jdGlvbiBnZXREZWZhdWx0T3B0cyAoc2ltcGxlKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICB2YXIgZGVmYXVsdE9wdGlvbnMgPSB7XG4gICAgb21pdEV4dHJhV0xJbkNvZGVCbG9ja3M6IHtcbiAgICAgIGRlZmF1bHRWYWx1ZTogZmFsc2UsXG4gICAgICBkZXNjcmliZTogJ09taXQgdGhlIGRlZmF1bHQgZXh0cmEgd2hpdGVsaW5lIGFkZGVkIHRvIGNvZGUgYmxvY2tzJyxcbiAgICAgIHR5cGU6ICdib29sZWFuJ1xuICAgIH0sXG4gICAgbm9IZWFkZXJJZDoge1xuICAgICAgZGVmYXVsdFZhbHVlOiBmYWxzZSxcbiAgICAgIGRlc2NyaWJlOiAnVHVybiBvbi9vZmYgZ2VuZXJhdGVkIGhlYWRlciBpZCcsXG4gICAgICB0eXBlOiAnYm9vbGVhbidcbiAgICB9LFxuICAgIHByZWZpeEhlYWRlcklkOiB7XG4gICAgICBkZWZhdWx0VmFsdWU6IGZhbHNlLFxuICAgICAgZGVzY3JpYmU6ICdBZGQgYSBwcmVmaXggdG8gdGhlIGdlbmVyYXRlZCBoZWFkZXIgaWRzLiBQYXNzaW5nIGEgc3RyaW5nIHdpbGwgcHJlZml4IHRoYXQgc3RyaW5nIHRvIHRoZSBoZWFkZXIgaWQuIFNldHRpbmcgdG8gdHJ1ZSB3aWxsIGFkZCBhIGdlbmVyaWMgXFwnc2VjdGlvbi1cXCcgcHJlZml4JyxcbiAgICAgIHR5cGU6ICdzdHJpbmcnXG4gICAgfSxcbiAgICByYXdQcmVmaXhIZWFkZXJJZDoge1xuICAgICAgZGVmYXVsdFZhbHVlOiBmYWxzZSxcbiAgICAgIGRlc2NyaWJlOiAnU2V0dGluZyB0aGlzIG9wdGlvbiB0byB0cnVlIHdpbGwgcHJldmVudCBzaG93ZG93biBmcm9tIG1vZGlmeWluZyB0aGUgcHJlZml4LiBUaGlzIG1pZ2h0IHJlc3VsdCBpbiBtYWxmb3JtZWQgSURzIChpZiwgZm9yIGluc3RhbmNlLCB0aGUgXCIgY2hhciBpcyB1c2VkIGluIHRoZSBwcmVmaXgpJyxcbiAgICAgIHR5cGU6ICdib29sZWFuJ1xuICAgIH0sXG4gICAgZ2hDb21wYXRpYmxlSGVhZGVySWQ6IHtcbiAgICAgIGRlZmF1bHRWYWx1ZTogZmFsc2UsXG4gICAgICBkZXNjcmliZTogJ0dlbmVyYXRlIGhlYWRlciBpZHMgY29tcGF0aWJsZSB3aXRoIGdpdGh1YiBzdHlsZSAoc3BhY2VzIGFyZSByZXBsYWNlZCB3aXRoIGRhc2hlcywgYSBidW5jaCBvZiBub24gYWxwaGFudW1lcmljIGNoYXJzIGFyZSByZW1vdmVkKScsXG4gICAgICB0eXBlOiAnYm9vbGVhbidcbiAgICB9LFxuICAgIHJhd0hlYWRlcklkOiB7XG4gICAgICBkZWZhdWx0VmFsdWU6IGZhbHNlLFxuICAgICAgZGVzY3JpYmU6ICdSZW1vdmUgb25seSBzcGFjZXMsIFxcJyBhbmQgXCIgZnJvbSBnZW5lcmF0ZWQgaGVhZGVyIGlkcyAoaW5jbHVkaW5nIHByZWZpeGVzKSwgcmVwbGFjaW5nIHRoZW0gd2l0aCBkYXNoZXMgKC0pLiBXQVJOSU5HOiBUaGlzIG1pZ2h0IHJlc3VsdCBpbiBtYWxmb3JtZWQgaWRzJyxcbiAgICAgIHR5cGU6ICdib29sZWFuJ1xuICAgIH0sXG4gICAgaGVhZGVyTGV2ZWxTdGFydDoge1xuICAgICAgZGVmYXVsdFZhbHVlOiBmYWxzZSxcbiAgICAgIGRlc2NyaWJlOiAnVGhlIGhlYWRlciBibG9ja3MgbGV2ZWwgc3RhcnQnLFxuICAgICAgdHlwZTogJ2ludGVnZXInXG4gICAgfSxcbiAgICBwYXJzZUltZ0RpbWVuc2lvbnM6IHtcbiAgICAgIGRlZmF1bHRWYWx1ZTogZmFsc2UsXG4gICAgICBkZXNjcmliZTogJ1R1cm4gb24vb2ZmIGltYWdlIGRpbWVuc2lvbiBwYXJzaW5nJyxcbiAgICAgIHR5cGU6ICdib29sZWFuJ1xuICAgIH0sXG4gICAgc2ltcGxpZmllZEF1dG9MaW5rOiB7XG4gICAgICBkZWZhdWx0VmFsdWU6IGZhbHNlLFxuICAgICAgZGVzY3JpYmU6ICdUdXJuIG9uL29mZiBHRk0gYXV0b2xpbmsgc3R5bGUnLFxuICAgICAgdHlwZTogJ2Jvb2xlYW4nXG4gICAgfSxcbiAgICBleGNsdWRlVHJhaWxpbmdQdW5jdHVhdGlvbkZyb21VUkxzOiB7XG4gICAgICBkZWZhdWx0VmFsdWU6IGZhbHNlLFxuICAgICAgZGVzY3JpYmU6ICdFeGNsdWRlcyB0cmFpbGluZyBwdW5jdHVhdGlvbiBmcm9tIGxpbmtzIGdlbmVyYXRlZCB3aXRoIGF1dG9MaW5raW5nJyxcbiAgICAgIHR5cGU6ICdib29sZWFuJ1xuICAgIH0sXG4gICAgbGl0ZXJhbE1pZFdvcmRVbmRlcnNjb3Jlczoge1xuICAgICAgZGVmYXVsdFZhbHVlOiBmYWxzZSxcbiAgICAgIGRlc2NyaWJlOiAnUGFyc2UgbWlkd29yZCB1bmRlcnNjb3JlcyBhcyBsaXRlcmFsIHVuZGVyc2NvcmVzJyxcbiAgICAgIHR5cGU6ICdib29sZWFuJ1xuICAgIH0sXG4gICAgbGl0ZXJhbE1pZFdvcmRBc3Rlcmlza3M6IHtcbiAgICAgIGRlZmF1bHRWYWx1ZTogZmFsc2UsXG4gICAgICBkZXNjcmliZTogJ1BhcnNlIG1pZHdvcmQgYXN0ZXJpc2tzIGFzIGxpdGVyYWwgYXN0ZXJpc2tzJyxcbiAgICAgIHR5cGU6ICdib29sZWFuJ1xuICAgIH0sXG4gICAgc3RyaWtldGhyb3VnaDoge1xuICAgICAgZGVmYXVsdFZhbHVlOiBmYWxzZSxcbiAgICAgIGRlc2NyaWJlOiAnVHVybiBvbi9vZmYgc3RyaWtldGhyb3VnaCBzdXBwb3J0JyxcbiAgICAgIHR5cGU6ICdib29sZWFuJ1xuICAgIH0sXG4gICAgdGFibGVzOiB7XG4gICAgICBkZWZhdWx0VmFsdWU6IGZhbHNlLFxuICAgICAgZGVzY3JpYmU6ICdUdXJuIG9uL29mZiB0YWJsZXMgc3VwcG9ydCcsXG4gICAgICB0eXBlOiAnYm9vbGVhbidcbiAgICB9LFxuICAgIHRhYmxlc0hlYWRlcklkOiB7XG4gICAgICBkZWZhdWx0VmFsdWU6IGZhbHNlLFxuICAgICAgZGVzY3JpYmU6ICdBZGQgYW4gaWQgdG8gdGFibGUgaGVhZGVycycsXG4gICAgICB0eXBlOiAnYm9vbGVhbidcbiAgICB9LFxuICAgIGdoQ29kZUJsb2Nrczoge1xuICAgICAgZGVmYXVsdFZhbHVlOiB0cnVlLFxuICAgICAgZGVzY3JpYmU6ICdUdXJuIG9uL29mZiBHRk0gZmVuY2VkIGNvZGUgYmxvY2tzIHN1cHBvcnQnLFxuICAgICAgdHlwZTogJ2Jvb2xlYW4nXG4gICAgfSxcbiAgICB0YXNrbGlzdHM6IHtcbiAgICAgIGRlZmF1bHRWYWx1ZTogZmFsc2UsXG4gICAgICBkZXNjcmliZTogJ1R1cm4gb24vb2ZmIEdGTSB0YXNrbGlzdCBzdXBwb3J0JyxcbiAgICAgIHR5cGU6ICdib29sZWFuJ1xuICAgIH0sXG4gICAgc21vb3RoTGl2ZVByZXZpZXc6IHtcbiAgICAgIGRlZmF1bHRWYWx1ZTogZmFsc2UsXG4gICAgICBkZXNjcmliZTogJ1ByZXZlbnRzIHdlaXJkIGVmZmVjdHMgaW4gbGl2ZSBwcmV2aWV3cyBkdWUgdG8gaW5jb21wbGV0ZSBpbnB1dCcsXG4gICAgICB0eXBlOiAnYm9vbGVhbidcbiAgICB9LFxuICAgIHNtYXJ0SW5kZW50YXRpb25GaXg6IHtcbiAgICAgIGRlZmF1bHRWYWx1ZTogZmFsc2UsXG4gICAgICBkZXNjcmlwdGlvbjogJ1RyaWVzIHRvIHNtYXJ0bHkgZml4IGluZGVudGF0aW9uIGluIGVzNiBzdHJpbmdzJyxcbiAgICAgIHR5cGU6ICdib29sZWFuJ1xuICAgIH0sXG4gICAgZGlzYWJsZUZvcmNlZDRTcGFjZXNJbmRlbnRlZFN1Ymxpc3RzOiB7XG4gICAgICBkZWZhdWx0VmFsdWU6IGZhbHNlLFxuICAgICAgZGVzY3JpcHRpb246ICdEaXNhYmxlcyB0aGUgcmVxdWlyZW1lbnQgb2YgaW5kZW50aW5nIG5lc3RlZCBzdWJsaXN0cyBieSA0IHNwYWNlcycsXG4gICAgICB0eXBlOiAnYm9vbGVhbidcbiAgICB9LFxuICAgIHNpbXBsZUxpbmVCcmVha3M6IHtcbiAgICAgIGRlZmF1bHRWYWx1ZTogZmFsc2UsXG4gICAgICBkZXNjcmlwdGlvbjogJ1BhcnNlcyBzaW1wbGUgbGluZSBicmVha3MgYXMgPGJyPiAoR0ZNIFN0eWxlKScsXG4gICAgICB0eXBlOiAnYm9vbGVhbidcbiAgICB9LFxuICAgIHJlcXVpcmVTcGFjZUJlZm9yZUhlYWRpbmdUZXh0OiB7XG4gICAgICBkZWZhdWx0VmFsdWU6IGZhbHNlLFxuICAgICAgZGVzY3JpcHRpb246ICdNYWtlcyBhZGRpbmcgYSBzcGFjZSBiZXR3ZWVuIGAjYCBhbmQgdGhlIGhlYWRlciB0ZXh0IG1hbmRhdG9yeSAoR0ZNIFN0eWxlKScsXG4gICAgICB0eXBlOiAnYm9vbGVhbidcbiAgICB9LFxuICAgIGdoTWVudGlvbnM6IHtcbiAgICAgIGRlZmF1bHRWYWx1ZTogZmFsc2UsXG4gICAgICBkZXNjcmlwdGlvbjogJ0VuYWJsZXMgZ2l0aHViIEBtZW50aW9ucycsXG4gICAgICB0eXBlOiAnYm9vbGVhbidcbiAgICB9LFxuICAgIGdoTWVudGlvbnNMaW5rOiB7XG4gICAgICBkZWZhdWx0VmFsdWU6ICdodHRwczovL2dpdGh1Yi5jb20ve3V9JyxcbiAgICAgIGRlc2NyaXB0aW9uOiAnQ2hhbmdlcyB0aGUgbGluayBnZW5lcmF0ZWQgYnkgQG1lbnRpb25zLiBPbmx5IGFwcGxpZXMgaWYgZ2hNZW50aW9ucyBvcHRpb24gaXMgZW5hYmxlZC4nLFxuICAgICAgdHlwZTogJ3N0cmluZydcbiAgICB9LFxuICAgIGVuY29kZUVtYWlsczoge1xuICAgICAgZGVmYXVsdFZhbHVlOiB0cnVlLFxuICAgICAgZGVzY3JpcHRpb246ICdFbmNvZGUgZS1tYWlsIGFkZHJlc3NlcyB0aHJvdWdoIHRoZSB1c2Ugb2YgQ2hhcmFjdGVyIEVudGl0aWVzLCB0cmFuc2Zvcm1pbmcgQVNDSUkgZS1tYWlsIGFkZHJlc3NlcyBpbnRvIGl0cyBlcXVpdmFsZW50IGRlY2ltYWwgZW50aXRpZXMnLFxuICAgICAgdHlwZTogJ2Jvb2xlYW4nXG4gICAgfSxcbiAgICBvcGVuTGlua3NJbk5ld1dpbmRvdzoge1xuICAgICAgZGVmYXVsdFZhbHVlOiBmYWxzZSxcbiAgICAgIGRlc2NyaXB0aW9uOiAnT3BlbiBhbGwgbGlua3MgaW4gbmV3IHdpbmRvd3MnLFxuICAgICAgdHlwZTogJ2Jvb2xlYW4nXG4gICAgfSxcbiAgICBiYWNrc2xhc2hFc2NhcGVzSFRNTFRhZ3M6IHtcbiAgICAgIGRlZmF1bHRWYWx1ZTogZmFsc2UsXG4gICAgICBkZXNjcmlwdGlvbjogJ1N1cHBvcnQgZm9yIEhUTUwgVGFnIGVzY2FwaW5nLiBleDogXFw8ZGl2PmZvb1xcPC9kaXY+JyxcbiAgICAgIHR5cGU6ICdib29sZWFuJ1xuICAgIH0sXG4gICAgZW1vamk6IHtcbiAgICAgIGRlZmF1bHRWYWx1ZTogZmFsc2UsXG4gICAgICBkZXNjcmlwdGlvbjogJ0VuYWJsZSBlbW9qaSBzdXBwb3J0LiBFeDogYHRoaXMgaXMgYSA6c21pbGU6IGVtb2ppYCcsXG4gICAgICB0eXBlOiAnYm9vbGVhbidcbiAgICB9LFxuICAgIHVuZGVybGluZToge1xuICAgICAgZGVmYXVsdFZhbHVlOiBmYWxzZSxcbiAgICAgIGRlc2NyaXB0aW9uOiAnRW5hYmxlIHN1cHBvcnQgZm9yIHVuZGVybGluZS4gU3ludGF4IGlzIGRvdWJsZSBvciB0cmlwbGUgdW5kZXJzY29yZXM6IGBfX3VuZGVybGluZSB3b3JkX19gLiBXaXRoIHRoaXMgb3B0aW9uIGVuYWJsZWQsIHVuZGVyc2NvcmVzIG5vIGxvbmdlciBwYXJzZXMgaW50byBgPGVtPmAgYW5kIGA8c3Ryb25nPmAnLFxuICAgICAgdHlwZTogJ2Jvb2xlYW4nXG4gICAgfSxcbiAgICBjb21wbGV0ZUhUTUxEb2N1bWVudDoge1xuICAgICAgZGVmYXVsdFZhbHVlOiBmYWxzZSxcbiAgICAgIGRlc2NyaXB0aW9uOiAnT3V0cHV0cyBhIGNvbXBsZXRlIGh0bWwgZG9jdW1lbnQsIGluY2x1ZGluZyBgPGh0bWw+YCwgYDxoZWFkPmAgYW5kIGA8Ym9keT5gIHRhZ3MnLFxuICAgICAgdHlwZTogJ2Jvb2xlYW4nXG4gICAgfSxcbiAgICBtZXRhZGF0YToge1xuICAgICAgZGVmYXVsdFZhbHVlOiBmYWxzZSxcbiAgICAgIGRlc2NyaXB0aW9uOiAnRW5hYmxlIHN1cHBvcnQgZm9yIGRvY3VtZW50IG1ldGFkYXRhIChkZWZpbmVkIGF0IHRoZSB0b3Agb2YgdGhlIGRvY3VtZW50IGJldHdlZW4gYMKrwqvCq2AgYW5kIGDCu8K7wrtgIG9yIGJldHdlZW4gYC0tLWAgYW5kIGAtLS1gKS4nLFxuICAgICAgdHlwZTogJ2Jvb2xlYW4nXG4gICAgfSxcbiAgICBzcGxpdEFkamFjZW50QmxvY2txdW90ZXM6IHtcbiAgICAgIGRlZmF1bHRWYWx1ZTogZmFsc2UsXG4gICAgICBkZXNjcmlwdGlvbjogJ1NwbGl0IGFkamFjZW50IGJsb2NrcXVvdGUgYmxvY2tzJyxcbiAgICAgIHR5cGU6ICdib29sZWFuJ1xuICAgIH1cbiAgfTtcbiAgaWYgKHNpbXBsZSA9PT0gZmFsc2UpIHtcbiAgICByZXR1cm4gSlNPTi5wYXJzZShKU09OLnN0cmluZ2lmeShkZWZhdWx0T3B0aW9ucykpO1xuICB9XG4gIHZhciByZXQgPSB7fTtcbiAgZm9yICh2YXIgb3B0IGluIGRlZmF1bHRPcHRpb25zKSB7XG4gICAgaWYgKGRlZmF1bHRPcHRpb25zLmhhc093blByb3BlcnR5KG9wdCkpIHtcbiAgICAgIHJldFtvcHRdID0gZGVmYXVsdE9wdGlvbnNbb3B0XS5kZWZhdWx0VmFsdWU7XG4gICAgfVxuICB9XG4gIHJldHVybiByZXQ7XG59XG5cbmZ1bmN0aW9uIGFsbE9wdGlvbnNPbiAoKSB7XG4gICd1c2Ugc3RyaWN0JztcbiAgdmFyIG9wdGlvbnMgPSBnZXREZWZhdWx0T3B0cyh0cnVlKSxcbiAgICAgIHJldCA9IHt9O1xuICBmb3IgKHZhciBvcHQgaW4gb3B0aW9ucykge1xuICAgIGlmIChvcHRpb25zLmhhc093blByb3BlcnR5KG9wdCkpIHtcbiAgICAgIHJldFtvcHRdID0gdHJ1ZTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHJldDtcbn1cblxyXG4vKipcbiAqIENyZWF0ZWQgYnkgVGl2aWUgb24gMDYtMDEtMjAxNS5cbiAqL1xuXG4vLyBQcml2YXRlIHByb3BlcnRpZXNcbnZhciBzaG93ZG93biA9IHt9LFxuICAgIHBhcnNlcnMgPSB7fSxcbiAgICBleHRlbnNpb25zID0ge30sXG4gICAgZ2xvYmFsT3B0aW9ucyA9IGdldERlZmF1bHRPcHRzKHRydWUpLFxuICAgIHNldEZsYXZvciA9ICd2YW5pbGxhJyxcbiAgICBmbGF2b3IgPSB7XG4gICAgICBnaXRodWI6IHtcbiAgICAgICAgb21pdEV4dHJhV0xJbkNvZGVCbG9ja3M6ICAgICAgICAgICAgICB0cnVlLFxuICAgICAgICBzaW1wbGlmaWVkQXV0b0xpbms6ICAgICAgICAgICAgICAgICAgIHRydWUsXG4gICAgICAgIGV4Y2x1ZGVUcmFpbGluZ1B1bmN0dWF0aW9uRnJvbVVSTHM6ICAgdHJ1ZSxcbiAgICAgICAgbGl0ZXJhbE1pZFdvcmRVbmRlcnNjb3JlczogICAgICAgICAgICB0cnVlLFxuICAgICAgICBzdHJpa2V0aHJvdWdoOiAgICAgICAgICAgICAgICAgICAgICAgIHRydWUsXG4gICAgICAgIHRhYmxlczogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJ1ZSxcbiAgICAgICAgdGFibGVzSGVhZGVySWQ6ICAgICAgICAgICAgICAgICAgICAgICB0cnVlLFxuICAgICAgICBnaENvZGVCbG9ja3M6ICAgICAgICAgICAgICAgICAgICAgICAgIHRydWUsXG4gICAgICAgIHRhc2tsaXN0czogICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJ1ZSxcbiAgICAgICAgZGlzYWJsZUZvcmNlZDRTcGFjZXNJbmRlbnRlZFN1Ymxpc3RzOiB0cnVlLFxuICAgICAgICBzaW1wbGVMaW5lQnJlYWtzOiAgICAgICAgICAgICAgICAgICAgIHRydWUsXG4gICAgICAgIHJlcXVpcmVTcGFjZUJlZm9yZUhlYWRpbmdUZXh0OiAgICAgICAgdHJ1ZSxcbiAgICAgICAgZ2hDb21wYXRpYmxlSGVhZGVySWQ6ICAgICAgICAgICAgICAgICB0cnVlLFxuICAgICAgICBnaE1lbnRpb25zOiAgICAgICAgICAgICAgICAgICAgICAgICAgIHRydWUsXG4gICAgICAgIGJhY2tzbGFzaEVzY2FwZXNIVE1MVGFnczogICAgICAgICAgICAgdHJ1ZSxcbiAgICAgICAgZW1vamk6ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cnVlLFxuICAgICAgICBzcGxpdEFkamFjZW50QmxvY2txdW90ZXM6ICAgICAgICAgICAgIHRydWVcbiAgICAgIH0sXG4gICAgICBvcmlnaW5hbDoge1xuICAgICAgICBub0hlYWRlcklkOiAgICAgICAgICAgICAgICAgICAgICAgICAgIHRydWUsXG4gICAgICAgIGdoQ29kZUJsb2NrczogICAgICAgICAgICAgICAgICAgICAgICAgZmFsc2VcbiAgICAgIH0sXG4gICAgICBnaG9zdDoge1xuICAgICAgICBvbWl0RXh0cmFXTEluQ29kZUJsb2NrczogICAgICAgICAgICAgIHRydWUsXG4gICAgICAgIHBhcnNlSW1nRGltZW5zaW9uczogICAgICAgICAgICAgICAgICAgdHJ1ZSxcbiAgICAgICAgc2ltcGxpZmllZEF1dG9MaW5rOiAgICAgICAgICAgICAgICAgICB0cnVlLFxuICAgICAgICBleGNsdWRlVHJhaWxpbmdQdW5jdHVhdGlvbkZyb21VUkxzOiAgIHRydWUsXG4gICAgICAgIGxpdGVyYWxNaWRXb3JkVW5kZXJzY29yZXM6ICAgICAgICAgICAgdHJ1ZSxcbiAgICAgICAgc3RyaWtldGhyb3VnaDogICAgICAgICAgICAgICAgICAgICAgICB0cnVlLFxuICAgICAgICB0YWJsZXM6ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRydWUsXG4gICAgICAgIHRhYmxlc0hlYWRlcklkOiAgICAgICAgICAgICAgICAgICAgICAgdHJ1ZSxcbiAgICAgICAgZ2hDb2RlQmxvY2tzOiAgICAgICAgICAgICAgICAgICAgICAgICB0cnVlLFxuICAgICAgICB0YXNrbGlzdHM6ICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRydWUsXG4gICAgICAgIHNtb290aExpdmVQcmV2aWV3OiAgICAgICAgICAgICAgICAgICAgdHJ1ZSxcbiAgICAgICAgc2ltcGxlTGluZUJyZWFrczogICAgICAgICAgICAgICAgICAgICB0cnVlLFxuICAgICAgICByZXF1aXJlU3BhY2VCZWZvcmVIZWFkaW5nVGV4dDogICAgICAgIHRydWUsXG4gICAgICAgIGdoTWVudGlvbnM6ICAgICAgICAgICAgICAgICAgICAgICAgICAgZmFsc2UsXG4gICAgICAgIGVuY29kZUVtYWlsczogICAgICAgICAgICAgICAgICAgICAgICAgdHJ1ZVxuICAgICAgfSxcbiAgICAgIHZhbmlsbGE6IGdldERlZmF1bHRPcHRzKHRydWUpLFxuICAgICAgYWxsT246IGFsbE9wdGlvbnNPbigpXG4gICAgfTtcblxuLyoqXG4gKiBoZWxwZXIgbmFtZXNwYWNlXG4gKiBAdHlwZSB7e319XG4gKi9cbnNob3dkb3duLmhlbHBlciA9IHt9O1xuXG4vKipcbiAqIFRPRE8gTEVHQUNZIFNVUFBPUlQgQ09ERVxuICogQHR5cGUge3t9fVxuICovXG5zaG93ZG93bi5leHRlbnNpb25zID0ge307XG5cbi8qKlxuICogU2V0IGEgZ2xvYmFsIG9wdGlvblxuICogQHN0YXRpY1xuICogQHBhcmFtIHtzdHJpbmd9IGtleVxuICogQHBhcmFtIHsqfSB2YWx1ZVxuICogQHJldHVybnMge3Nob3dkb3dufVxuICovXG5zaG93ZG93bi5zZXRPcHRpb24gPSBmdW5jdGlvbiAoa2V5LCB2YWx1ZSkge1xuICAndXNlIHN0cmljdCc7XG4gIGdsb2JhbE9wdGlvbnNba2V5XSA9IHZhbHVlO1xuICByZXR1cm4gdGhpcztcbn07XG5cbi8qKlxuICogR2V0IGEgZ2xvYmFsIG9wdGlvblxuICogQHN0YXRpY1xuICogQHBhcmFtIHtzdHJpbmd9IGtleVxuICogQHJldHVybnMgeyp9XG4gKi9cbnNob3dkb3duLmdldE9wdGlvbiA9IGZ1bmN0aW9uIChrZXkpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuICByZXR1cm4gZ2xvYmFsT3B0aW9uc1trZXldO1xufTtcblxuLyoqXG4gKiBHZXQgdGhlIGdsb2JhbCBvcHRpb25zXG4gKiBAc3RhdGljXG4gKiBAcmV0dXJucyB7e319XG4gKi9cbnNob3dkb3duLmdldE9wdGlvbnMgPSBmdW5jdGlvbiAoKSB7XG4gICd1c2Ugc3RyaWN0JztcbiAgcmV0dXJuIGdsb2JhbE9wdGlvbnM7XG59O1xuXG4vKipcbiAqIFJlc2V0IGdsb2JhbCBvcHRpb25zIHRvIHRoZSBkZWZhdWx0IHZhbHVlc1xuICogQHN0YXRpY1xuICovXG5zaG93ZG93bi5yZXNldE9wdGlvbnMgPSBmdW5jdGlvbiAoKSB7XG4gICd1c2Ugc3RyaWN0JztcbiAgZ2xvYmFsT3B0aW9ucyA9IGdldERlZmF1bHRPcHRzKHRydWUpO1xufTtcblxuLyoqXG4gKiBTZXQgdGhlIGZsYXZvciBzaG93ZG93biBzaG91bGQgdXNlIGFzIGRlZmF1bHRcbiAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lXG4gKi9cbnNob3dkb3duLnNldEZsYXZvciA9IGZ1bmN0aW9uIChuYW1lKSB7XG4gICd1c2Ugc3RyaWN0JztcbiAgaWYgKCFmbGF2b3IuaGFzT3duUHJvcGVydHkobmFtZSkpIHtcbiAgICB0aHJvdyBFcnJvcihuYW1lICsgJyBmbGF2b3Igd2FzIG5vdCBmb3VuZCcpO1xuICB9XG4gIHNob3dkb3duLnJlc2V0T3B0aW9ucygpO1xuICB2YXIgcHJlc2V0ID0gZmxhdm9yW25hbWVdO1xuICBzZXRGbGF2b3IgPSBuYW1lO1xuICBmb3IgKHZhciBvcHRpb24gaW4gcHJlc2V0KSB7XG4gICAgaWYgKHByZXNldC5oYXNPd25Qcm9wZXJ0eShvcHRpb24pKSB7XG4gICAgICBnbG9iYWxPcHRpb25zW29wdGlvbl0gPSBwcmVzZXRbb3B0aW9uXTtcbiAgICB9XG4gIH1cbn07XG5cbi8qKlxuICogR2V0IHRoZSBjdXJyZW50bHkgc2V0IGZsYXZvclxuICogQHJldHVybnMge3N0cmluZ31cbiAqL1xuc2hvd2Rvd24uZ2V0Rmxhdm9yID0gZnVuY3Rpb24gKCkge1xuICAndXNlIHN0cmljdCc7XG4gIHJldHVybiBzZXRGbGF2b3I7XG59O1xuXG4vKipcbiAqIEdldCB0aGUgb3B0aW9ucyBvZiBhIHNwZWNpZmllZCBmbGF2b3IuIFJldHVybnMgdW5kZWZpbmVkIGlmIHRoZSBmbGF2b3Igd2FzIG5vdCBmb3VuZFxuICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgTmFtZSBvZiB0aGUgZmxhdm9yXG4gKiBAcmV0dXJucyB7e318dW5kZWZpbmVkfVxuICovXG5zaG93ZG93bi5nZXRGbGF2b3JPcHRpb25zID0gZnVuY3Rpb24gKG5hbWUpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuICBpZiAoZmxhdm9yLmhhc093blByb3BlcnR5KG5hbWUpKSB7XG4gICAgcmV0dXJuIGZsYXZvcltuYW1lXTtcbiAgfVxufTtcblxuLyoqXG4gKiBHZXQgdGhlIGRlZmF1bHQgb3B0aW9uc1xuICogQHN0YXRpY1xuICogQHBhcmFtIHtib29sZWFufSBbc2ltcGxlPXRydWVdXG4gKiBAcmV0dXJucyB7e319XG4gKi9cbnNob3dkb3duLmdldERlZmF1bHRPcHRpb25zID0gZnVuY3Rpb24gKHNpbXBsZSkge1xuICAndXNlIHN0cmljdCc7XG4gIHJldHVybiBnZXREZWZhdWx0T3B0cyhzaW1wbGUpO1xufTtcblxuLyoqXG4gKiBHZXQgb3Igc2V0IGEgc3ViUGFyc2VyXG4gKlxuICogc3ViUGFyc2VyKG5hbWUpICAgICAgIC0gR2V0IGEgcmVnaXN0ZXJlZCBzdWJQYXJzZXJcbiAqIHN1YlBhcnNlcihuYW1lLCBmdW5jKSAtIFJlZ2lzdGVyIGEgc3ViUGFyc2VyXG4gKiBAc3RhdGljXG4gKiBAcGFyYW0ge3N0cmluZ30gbmFtZVxuICogQHBhcmFtIHtmdW5jdGlvbn0gW2Z1bmNdXG4gKiBAcmV0dXJucyB7Kn1cbiAqL1xuc2hvd2Rvd24uc3ViUGFyc2VyID0gZnVuY3Rpb24gKG5hbWUsIGZ1bmMpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuICBpZiAoc2hvd2Rvd24uaGVscGVyLmlzU3RyaW5nKG5hbWUpKSB7XG4gICAgaWYgKHR5cGVvZiBmdW5jICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgcGFyc2Vyc1tuYW1lXSA9IGZ1bmM7XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmIChwYXJzZXJzLmhhc093blByb3BlcnR5KG5hbWUpKSB7XG4gICAgICAgIHJldHVybiBwYXJzZXJzW25hbWVdO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgRXJyb3IoJ1N1YlBhcnNlciBuYW1lZCAnICsgbmFtZSArICcgbm90IHJlZ2lzdGVyZWQhJyk7XG4gICAgICB9XG4gICAgfVxuICB9XG59O1xuXG4vKipcbiAqIEdldHMgb3IgcmVnaXN0ZXJzIGFuIGV4dGVuc2lvblxuICogQHN0YXRpY1xuICogQHBhcmFtIHtzdHJpbmd9IG5hbWVcbiAqIEBwYXJhbSB7b2JqZWN0fGZ1bmN0aW9uPX0gZXh0XG4gKiBAcmV0dXJucyB7Kn1cbiAqL1xuc2hvd2Rvd24uZXh0ZW5zaW9uID0gZnVuY3Rpb24gKG5hbWUsIGV4dCkge1xuICAndXNlIHN0cmljdCc7XG5cbiAgaWYgKCFzaG93ZG93bi5oZWxwZXIuaXNTdHJpbmcobmFtZSkpIHtcbiAgICB0aHJvdyBFcnJvcignRXh0ZW5zaW9uIFxcJ25hbWVcXCcgbXVzdCBiZSBhIHN0cmluZycpO1xuICB9XG5cbiAgbmFtZSA9IHNob3dkb3duLmhlbHBlci5zdGRFeHROYW1lKG5hbWUpO1xuXG4gIC8vIEdldHRlclxuICBpZiAoc2hvd2Rvd24uaGVscGVyLmlzVW5kZWZpbmVkKGV4dCkpIHtcbiAgICBpZiAoIWV4dGVuc2lvbnMuaGFzT3duUHJvcGVydHkobmFtZSkpIHtcbiAgICAgIHRocm93IEVycm9yKCdFeHRlbnNpb24gbmFtZWQgJyArIG5hbWUgKyAnIGlzIG5vdCByZWdpc3RlcmVkIScpO1xuICAgIH1cbiAgICByZXR1cm4gZXh0ZW5zaW9uc1tuYW1lXTtcblxuICAgIC8vIFNldHRlclxuICB9IGVsc2Uge1xuICAgIC8vIEV4cGFuZCBleHRlbnNpb24gaWYgaXQncyB3cmFwcGVkIGluIGEgZnVuY3Rpb25cbiAgICBpZiAodHlwZW9mIGV4dCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgZXh0ID0gZXh0KCk7XG4gICAgfVxuXG4gICAgLy8gRW5zdXJlIGV4dGVuc2lvbiBpcyBhbiBhcnJheVxuICAgIGlmICghc2hvd2Rvd24uaGVscGVyLmlzQXJyYXkoZXh0KSkge1xuICAgICAgZXh0ID0gW2V4dF07XG4gICAgfVxuXG4gICAgdmFyIHZhbGlkRXh0ZW5zaW9uID0gdmFsaWRhdGUoZXh0LCBuYW1lKTtcblxuICAgIGlmICh2YWxpZEV4dGVuc2lvbi52YWxpZCkge1xuICAgICAgZXh0ZW5zaW9uc1tuYW1lXSA9IGV4dDtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgRXJyb3IodmFsaWRFeHRlbnNpb24uZXJyb3IpO1xuICAgIH1cbiAgfVxufTtcblxuLyoqXG4gKiBHZXRzIGFsbCBleHRlbnNpb25zIHJlZ2lzdGVyZWRcbiAqIEByZXR1cm5zIHt7fX1cbiAqL1xuc2hvd2Rvd24uZ2V0QWxsRXh0ZW5zaW9ucyA9IGZ1bmN0aW9uICgpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuICByZXR1cm4gZXh0ZW5zaW9ucztcbn07XG5cbi8qKlxuICogUmVtb3ZlIGFuIGV4dGVuc2lvblxuICogQHBhcmFtIHtzdHJpbmd9IG5hbWVcbiAqL1xuc2hvd2Rvd24ucmVtb3ZlRXh0ZW5zaW9uID0gZnVuY3Rpb24gKG5hbWUpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuICBkZWxldGUgZXh0ZW5zaW9uc1tuYW1lXTtcbn07XG5cbi8qKlxuICogUmVtb3ZlcyBhbGwgZXh0ZW5zaW9uc1xuICovXG5zaG93ZG93bi5yZXNldEV4dGVuc2lvbnMgPSBmdW5jdGlvbiAoKSB7XG4gICd1c2Ugc3RyaWN0JztcbiAgZXh0ZW5zaW9ucyA9IHt9O1xufTtcblxuLyoqXG4gKiBWYWxpZGF0ZSBleHRlbnNpb25cbiAqIEBwYXJhbSB7YXJyYXl9IGV4dGVuc2lvblxuICogQHBhcmFtIHtzdHJpbmd9IG5hbWVcbiAqIEByZXR1cm5zIHt7dmFsaWQ6IGJvb2xlYW4sIGVycm9yOiBzdHJpbmd9fVxuICovXG5mdW5jdGlvbiB2YWxpZGF0ZSAoZXh0ZW5zaW9uLCBuYW1lKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICB2YXIgZXJyTXNnID0gKG5hbWUpID8gJ0Vycm9yIGluICcgKyBuYW1lICsgJyBleHRlbnNpb24tPicgOiAnRXJyb3IgaW4gdW5uYW1lZCBleHRlbnNpb24nLFxuICAgICAgcmV0ID0ge1xuICAgICAgICB2YWxpZDogdHJ1ZSxcbiAgICAgICAgZXJyb3I6ICcnXG4gICAgICB9O1xuXG4gIGlmICghc2hvd2Rvd24uaGVscGVyLmlzQXJyYXkoZXh0ZW5zaW9uKSkge1xuICAgIGV4dGVuc2lvbiA9IFtleHRlbnNpb25dO1xuICB9XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBleHRlbnNpb24ubGVuZ3RoOyArK2kpIHtcbiAgICB2YXIgYmFzZU1zZyA9IGVyck1zZyArICcgc3ViLWV4dGVuc2lvbiAnICsgaSArICc6ICcsXG4gICAgICAgIGV4dCA9IGV4dGVuc2lvbltpXTtcbiAgICBpZiAodHlwZW9mIGV4dCAhPT0gJ29iamVjdCcpIHtcbiAgICAgIHJldC52YWxpZCA9IGZhbHNlO1xuICAgICAgcmV0LmVycm9yID0gYmFzZU1zZyArICdtdXN0IGJlIGFuIG9iamVjdCwgYnV0ICcgKyB0eXBlb2YgZXh0ICsgJyBnaXZlbic7XG4gICAgICByZXR1cm4gcmV0O1xuICAgIH1cblxuICAgIGlmICghc2hvd2Rvd24uaGVscGVyLmlzU3RyaW5nKGV4dC50eXBlKSkge1xuICAgICAgcmV0LnZhbGlkID0gZmFsc2U7XG4gICAgICByZXQuZXJyb3IgPSBiYXNlTXNnICsgJ3Byb3BlcnR5IFwidHlwZVwiIG11c3QgYmUgYSBzdHJpbmcsIGJ1dCAnICsgdHlwZW9mIGV4dC50eXBlICsgJyBnaXZlbic7XG4gICAgICByZXR1cm4gcmV0O1xuICAgIH1cblxuICAgIHZhciB0eXBlID0gZXh0LnR5cGUgPSBleHQudHlwZS50b0xvd2VyQ2FzZSgpO1xuXG4gICAgLy8gbm9ybWFsaXplIGV4dGVuc2lvbiB0eXBlXG4gICAgaWYgKHR5cGUgPT09ICdsYW5ndWFnZScpIHtcbiAgICAgIHR5cGUgPSBleHQudHlwZSA9ICdsYW5nJztcbiAgICB9XG5cbiAgICBpZiAodHlwZSA9PT0gJ2h0bWwnKSB7XG4gICAgICB0eXBlID0gZXh0LnR5cGUgPSAnb3V0cHV0JztcbiAgICB9XG5cbiAgICBpZiAodHlwZSAhPT0gJ2xhbmcnICYmIHR5cGUgIT09ICdvdXRwdXQnICYmIHR5cGUgIT09ICdsaXN0ZW5lcicpIHtcbiAgICAgIHJldC52YWxpZCA9IGZhbHNlO1xuICAgICAgcmV0LmVycm9yID0gYmFzZU1zZyArICd0eXBlICcgKyB0eXBlICsgJyBpcyBub3QgcmVjb2duaXplZC4gVmFsaWQgdmFsdWVzOiBcImxhbmcvbGFuZ3VhZ2VcIiwgXCJvdXRwdXQvaHRtbFwiIG9yIFwibGlzdGVuZXJcIic7XG4gICAgICByZXR1cm4gcmV0O1xuICAgIH1cblxuICAgIGlmICh0eXBlID09PSAnbGlzdGVuZXInKSB7XG4gICAgICBpZiAoc2hvd2Rvd24uaGVscGVyLmlzVW5kZWZpbmVkKGV4dC5saXN0ZW5lcnMpKSB7XG4gICAgICAgIHJldC52YWxpZCA9IGZhbHNlO1xuICAgICAgICByZXQuZXJyb3IgPSBiYXNlTXNnICsgJy4gRXh0ZW5zaW9ucyBvZiB0eXBlIFwibGlzdGVuZXJcIiBtdXN0IGhhdmUgYSBwcm9wZXJ0eSBjYWxsZWQgXCJsaXN0ZW5lcnNcIic7XG4gICAgICAgIHJldHVybiByZXQ7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmIChzaG93ZG93bi5oZWxwZXIuaXNVbmRlZmluZWQoZXh0LmZpbHRlcikgJiYgc2hvd2Rvd24uaGVscGVyLmlzVW5kZWZpbmVkKGV4dC5yZWdleCkpIHtcbiAgICAgICAgcmV0LnZhbGlkID0gZmFsc2U7XG4gICAgICAgIHJldC5lcnJvciA9IGJhc2VNc2cgKyB0eXBlICsgJyBleHRlbnNpb25zIG11c3QgZGVmaW5lIGVpdGhlciBhIFwicmVnZXhcIiBwcm9wZXJ0eSBvciBhIFwiZmlsdGVyXCIgbWV0aG9kJztcbiAgICAgICAgcmV0dXJuIHJldDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoZXh0Lmxpc3RlbmVycykge1xuICAgICAgaWYgKHR5cGVvZiBleHQubGlzdGVuZXJzICE9PSAnb2JqZWN0Jykge1xuICAgICAgICByZXQudmFsaWQgPSBmYWxzZTtcbiAgICAgICAgcmV0LmVycm9yID0gYmFzZU1zZyArICdcImxpc3RlbmVyc1wiIHByb3BlcnR5IG11c3QgYmUgYW4gb2JqZWN0IGJ1dCAnICsgdHlwZW9mIGV4dC5saXN0ZW5lcnMgKyAnIGdpdmVuJztcbiAgICAgICAgcmV0dXJuIHJldDtcbiAgICAgIH1cbiAgICAgIGZvciAodmFyIGxuIGluIGV4dC5saXN0ZW5lcnMpIHtcbiAgICAgICAgaWYgKGV4dC5saXN0ZW5lcnMuaGFzT3duUHJvcGVydHkobG4pKSB7XG4gICAgICAgICAgaWYgKHR5cGVvZiBleHQubGlzdGVuZXJzW2xuXSAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgcmV0LnZhbGlkID0gZmFsc2U7XG4gICAgICAgICAgICByZXQuZXJyb3IgPSBiYXNlTXNnICsgJ1wibGlzdGVuZXJzXCIgcHJvcGVydHkgbXVzdCBiZSBhbiBoYXNoIG9mIFtldmVudCBuYW1lXTogW2NhbGxiYWNrXS4gbGlzdGVuZXJzLicgKyBsbiArXG4gICAgICAgICAgICAgICcgbXVzdCBiZSBhIGZ1bmN0aW9uIGJ1dCAnICsgdHlwZW9mIGV4dC5saXN0ZW5lcnNbbG5dICsgJyBnaXZlbic7XG4gICAgICAgICAgICByZXR1cm4gcmV0O1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChleHQuZmlsdGVyKSB7XG4gICAgICBpZiAodHlwZW9mIGV4dC5maWx0ZXIgIT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgcmV0LnZhbGlkID0gZmFsc2U7XG4gICAgICAgIHJldC5lcnJvciA9IGJhc2VNc2cgKyAnXCJmaWx0ZXJcIiBtdXN0IGJlIGEgZnVuY3Rpb24sIGJ1dCAnICsgdHlwZW9mIGV4dC5maWx0ZXIgKyAnIGdpdmVuJztcbiAgICAgICAgcmV0dXJuIHJldDtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKGV4dC5yZWdleCkge1xuICAgICAgaWYgKHNob3dkb3duLmhlbHBlci5pc1N0cmluZyhleHQucmVnZXgpKSB7XG4gICAgICAgIGV4dC5yZWdleCA9IG5ldyBSZWdFeHAoZXh0LnJlZ2V4LCAnZycpO1xuICAgICAgfVxuICAgICAgaWYgKCEoZXh0LnJlZ2V4IGluc3RhbmNlb2YgUmVnRXhwKSkge1xuICAgICAgICByZXQudmFsaWQgPSBmYWxzZTtcbiAgICAgICAgcmV0LmVycm9yID0gYmFzZU1zZyArICdcInJlZ2V4XCIgcHJvcGVydHkgbXVzdCBlaXRoZXIgYmUgYSBzdHJpbmcgb3IgYSBSZWdFeHAgb2JqZWN0LCBidXQgJyArIHR5cGVvZiBleHQucmVnZXggKyAnIGdpdmVuJztcbiAgICAgICAgcmV0dXJuIHJldDtcbiAgICAgIH1cbiAgICAgIGlmIChzaG93ZG93bi5oZWxwZXIuaXNVbmRlZmluZWQoZXh0LnJlcGxhY2UpKSB7XG4gICAgICAgIHJldC52YWxpZCA9IGZhbHNlO1xuICAgICAgICByZXQuZXJyb3IgPSBiYXNlTXNnICsgJ1wicmVnZXhcIiBleHRlbnNpb25zIG11c3QgaW1wbGVtZW50IGEgcmVwbGFjZSBzdHJpbmcgb3IgZnVuY3Rpb24nO1xuICAgICAgICByZXR1cm4gcmV0O1xuICAgICAgfVxuICAgIH1cbiAgfVxuICByZXR1cm4gcmV0O1xufVxuXG4vKipcbiAqIFZhbGlkYXRlIGV4dGVuc2lvblxuICogQHBhcmFtIHtvYmplY3R9IGV4dFxuICogQHJldHVybnMge2Jvb2xlYW59XG4gKi9cbnNob3dkb3duLnZhbGlkYXRlRXh0ZW5zaW9uID0gZnVuY3Rpb24gKGV4dCkge1xuICAndXNlIHN0cmljdCc7XG5cbiAgdmFyIHZhbGlkYXRlRXh0ZW5zaW9uID0gdmFsaWRhdGUoZXh0LCBudWxsKTtcbiAgaWYgKCF2YWxpZGF0ZUV4dGVuc2lvbi52YWxpZCkge1xuICAgIGNvbnNvbGUud2Fybih2YWxpZGF0ZUV4dGVuc2lvbi5lcnJvcik7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIHJldHVybiB0cnVlO1xufTtcblxyXG4vKipcbiAqIHNob3dkb3duanMgaGVscGVyIGZ1bmN0aW9uc1xuICovXG5cbmlmICghc2hvd2Rvd24uaGFzT3duUHJvcGVydHkoJ2hlbHBlcicpKSB7XG4gIHNob3dkb3duLmhlbHBlciA9IHt9O1xufVxuXG4vKipcbiAqIENoZWNrIGlmIHZhciBpcyBzdHJpbmdcbiAqIEBzdGF0aWNcbiAqIEBwYXJhbSB7c3RyaW5nfSBhXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAqL1xuc2hvd2Rvd24uaGVscGVyLmlzU3RyaW5nID0gZnVuY3Rpb24gKGEpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuICByZXR1cm4gKHR5cGVvZiBhID09PSAnc3RyaW5nJyB8fCBhIGluc3RhbmNlb2YgU3RyaW5nKTtcbn07XG5cbi8qKlxuICogQ2hlY2sgaWYgdmFyIGlzIGEgZnVuY3Rpb25cbiAqIEBzdGF0aWNcbiAqIEBwYXJhbSB7Kn0gYVxuICogQHJldHVybnMge2Jvb2xlYW59XG4gKi9cbnNob3dkb3duLmhlbHBlci5pc0Z1bmN0aW9uID0gZnVuY3Rpb24gKGEpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuICB2YXIgZ2V0VHlwZSA9IHt9O1xuICByZXR1cm4gYSAmJiBnZXRUeXBlLnRvU3RyaW5nLmNhbGwoYSkgPT09ICdbb2JqZWN0IEZ1bmN0aW9uXSc7XG59O1xuXG4vKipcbiAqIGlzQXJyYXkgaGVscGVyIGZ1bmN0aW9uXG4gKiBAc3RhdGljXG4gKiBAcGFyYW0geyp9IGFcbiAqIEByZXR1cm5zIHtib29sZWFufVxuICovXG5zaG93ZG93bi5oZWxwZXIuaXNBcnJheSA9IGZ1bmN0aW9uIChhKSB7XG4gICd1c2Ugc3RyaWN0JztcbiAgcmV0dXJuIEFycmF5LmlzQXJyYXkoYSk7XG59O1xuXG4vKipcbiAqIENoZWNrIGlmIHZhbHVlIGlzIHVuZGVmaW5lZFxuICogQHN0YXRpY1xuICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBgdW5kZWZpbmVkYCwgZWxzZSBgZmFsc2VgLlxuICovXG5zaG93ZG93bi5oZWxwZXIuaXNVbmRlZmluZWQgPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAndW5kZWZpbmVkJztcbn07XG5cbi8qKlxuICogRm9yRWFjaCBoZWxwZXIgZnVuY3Rpb25cbiAqIEl0ZXJhdGVzIG92ZXIgQXJyYXlzIGFuZCBPYmplY3RzIChvd24gcHJvcGVydGllcyBvbmx5KVxuICogQHN0YXRpY1xuICogQHBhcmFtIHsqfSBvYmpcbiAqIEBwYXJhbSB7ZnVuY3Rpb259IGNhbGxiYWNrIEFjY2VwdHMgMyBwYXJhbXM6IDEuIHZhbHVlLCAyLiBrZXksIDMuIHRoZSBvcmlnaW5hbCBhcnJheS9vYmplY3RcbiAqL1xuc2hvd2Rvd24uaGVscGVyLmZvckVhY2ggPSBmdW5jdGlvbiAob2JqLCBjYWxsYmFjaykge1xuICAndXNlIHN0cmljdCc7XG4gIC8vIGNoZWNrIGlmIG9iaiBpcyBkZWZpbmVkXG4gIGlmIChzaG93ZG93bi5oZWxwZXIuaXNVbmRlZmluZWQob2JqKSkge1xuICAgIHRocm93IG5ldyBFcnJvcignb2JqIHBhcmFtIGlzIHJlcXVpcmVkJyk7XG4gIH1cblxuICBpZiAoc2hvd2Rvd24uaGVscGVyLmlzVW5kZWZpbmVkKGNhbGxiYWNrKSkge1xuICAgIHRocm93IG5ldyBFcnJvcignY2FsbGJhY2sgcGFyYW0gaXMgcmVxdWlyZWQnKTtcbiAgfVxuXG4gIGlmICghc2hvd2Rvd24uaGVscGVyLmlzRnVuY3Rpb24oY2FsbGJhY2spKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdjYWxsYmFjayBwYXJhbSBtdXN0IGJlIGEgZnVuY3Rpb24vY2xvc3VyZScpO1xuICB9XG5cbiAgaWYgKHR5cGVvZiBvYmouZm9yRWFjaCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgIG9iai5mb3JFYWNoKGNhbGxiYWNrKTtcbiAgfSBlbHNlIGlmIChzaG93ZG93bi5oZWxwZXIuaXNBcnJheShvYmopKSB7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBvYmoubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNhbGxiYWNrKG9ialtpXSwgaSwgb2JqKTtcbiAgICB9XG4gIH0gZWxzZSBpZiAodHlwZW9mIChvYmopID09PSAnb2JqZWN0Jykge1xuICAgIGZvciAodmFyIHByb3AgaW4gb2JqKSB7XG4gICAgICBpZiAob2JqLmhhc093blByb3BlcnR5KHByb3ApKSB7XG4gICAgICAgIGNhbGxiYWNrKG9ialtwcm9wXSwgcHJvcCwgb2JqKTtcbiAgICAgIH1cbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdvYmogZG9lcyBub3Qgc2VlbSB0byBiZSBhbiBhcnJheSBvciBhbiBpdGVyYWJsZSBvYmplY3QnKTtcbiAgfVxufTtcblxuLyoqXG4gKiBTdGFuZGFyZGlkaXplIGV4dGVuc2lvbiBuYW1lXG4gKiBAc3RhdGljXG4gKiBAcGFyYW0ge3N0cmluZ30gcyBleHRlbnNpb24gbmFtZVxuICogQHJldHVybnMge3N0cmluZ31cbiAqL1xuc2hvd2Rvd24uaGVscGVyLnN0ZEV4dE5hbWUgPSBmdW5jdGlvbiAocykge1xuICAndXNlIHN0cmljdCc7XG4gIHJldHVybiBzLnJlcGxhY2UoL1tfPyorXFwvXFxcXC5eLV0vZywgJycpLnJlcGxhY2UoL1xccy9nLCAnJykudG9Mb3dlckNhc2UoKTtcbn07XG5cbmZ1bmN0aW9uIGVzY2FwZUNoYXJhY3RlcnNDYWxsYmFjayAod2hvbGVNYXRjaCwgbTEpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuICB2YXIgY2hhckNvZGVUb0VzY2FwZSA9IG0xLmNoYXJDb2RlQXQoMCk7XG4gIHJldHVybiAnwqhFJyArIGNoYXJDb2RlVG9Fc2NhcGUgKyAnRSc7XG59XG5cbi8qKlxuICogQ2FsbGJhY2sgdXNlZCB0byBlc2NhcGUgY2hhcmFjdGVycyB3aGVuIHBhc3NpbmcgdGhyb3VnaCBTdHJpbmcucmVwbGFjZVxuICogQHN0YXRpY1xuICogQHBhcmFtIHtzdHJpbmd9IHdob2xlTWF0Y2hcbiAqIEBwYXJhbSB7c3RyaW5nfSBtMVxuICogQHJldHVybnMge3N0cmluZ31cbiAqL1xuc2hvd2Rvd24uaGVscGVyLmVzY2FwZUNoYXJhY3RlcnNDYWxsYmFjayA9IGVzY2FwZUNoYXJhY3RlcnNDYWxsYmFjaztcblxuLyoqXG4gKiBFc2NhcGUgY2hhcmFjdGVycyBpbiBhIHN0cmluZ1xuICogQHN0YXRpY1xuICogQHBhcmFtIHtzdHJpbmd9IHRleHRcbiAqIEBwYXJhbSB7c3RyaW5nfSBjaGFyc1RvRXNjYXBlXG4gKiBAcGFyYW0ge2Jvb2xlYW59IGFmdGVyQmFja3NsYXNoXG4gKiBAcmV0dXJucyB7WE1MfHN0cmluZ3x2b2lkfCp9XG4gKi9cbnNob3dkb3duLmhlbHBlci5lc2NhcGVDaGFyYWN0ZXJzID0gZnVuY3Rpb24gKHRleHQsIGNoYXJzVG9Fc2NhcGUsIGFmdGVyQmFja3NsYXNoKSB7XG4gICd1c2Ugc3RyaWN0JztcbiAgLy8gRmlyc3Qgd2UgaGF2ZSB0byBlc2NhcGUgdGhlIGVzY2FwZSBjaGFyYWN0ZXJzIHNvIHRoYXRcbiAgLy8gd2UgY2FuIGJ1aWxkIGEgY2hhcmFjdGVyIGNsYXNzIG91dCBvZiB0aGVtXG4gIHZhciByZWdleFN0cmluZyA9ICcoWycgKyBjaGFyc1RvRXNjYXBlLnJlcGxhY2UoLyhbXFxbXFxdXFxcXF0pL2csICdcXFxcJDEnKSArICddKSc7XG5cbiAgaWYgKGFmdGVyQmFja3NsYXNoKSB7XG4gICAgcmVnZXhTdHJpbmcgPSAnXFxcXFxcXFwnICsgcmVnZXhTdHJpbmc7XG4gIH1cblxuICB2YXIgcmVnZXggPSBuZXcgUmVnRXhwKHJlZ2V4U3RyaW5nLCAnZycpO1xuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKHJlZ2V4LCBlc2NhcGVDaGFyYWN0ZXJzQ2FsbGJhY2spO1xuXG4gIHJldHVybiB0ZXh0O1xufTtcblxudmFyIHJneEZpbmRNYXRjaFBvcyA9IGZ1bmN0aW9uIChzdHIsIGxlZnQsIHJpZ2h0LCBmbGFncykge1xuICAndXNlIHN0cmljdCc7XG4gIHZhciBmID0gZmxhZ3MgfHwgJycsXG4gICAgICBnID0gZi5pbmRleE9mKCdnJykgPiAtMSxcbiAgICAgIHggPSBuZXcgUmVnRXhwKGxlZnQgKyAnfCcgKyByaWdodCwgJ2cnICsgZi5yZXBsYWNlKC9nL2csICcnKSksXG4gICAgICBsID0gbmV3IFJlZ0V4cChsZWZ0LCBmLnJlcGxhY2UoL2cvZywgJycpKSxcbiAgICAgIHBvcyA9IFtdLFxuICAgICAgdCwgcywgbSwgc3RhcnQsIGVuZDtcblxuICBkbyB7XG4gICAgdCA9IDA7XG4gICAgd2hpbGUgKChtID0geC5leGVjKHN0cikpKSB7XG4gICAgICBpZiAobC50ZXN0KG1bMF0pKSB7XG4gICAgICAgIGlmICghKHQrKykpIHtcbiAgICAgICAgICBzID0geC5sYXN0SW5kZXg7XG4gICAgICAgICAgc3RhcnQgPSBzIC0gbVswXS5sZW5ndGg7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAodCkge1xuICAgICAgICBpZiAoIS0tdCkge1xuICAgICAgICAgIGVuZCA9IG0uaW5kZXggKyBtWzBdLmxlbmd0aDtcbiAgICAgICAgICB2YXIgb2JqID0ge1xuICAgICAgICAgICAgbGVmdDoge3N0YXJ0OiBzdGFydCwgZW5kOiBzfSxcbiAgICAgICAgICAgIG1hdGNoOiB7c3RhcnQ6IHMsIGVuZDogbS5pbmRleH0sXG4gICAgICAgICAgICByaWdodDoge3N0YXJ0OiBtLmluZGV4LCBlbmQ6IGVuZH0sXG4gICAgICAgICAgICB3aG9sZU1hdGNoOiB7c3RhcnQ6IHN0YXJ0LCBlbmQ6IGVuZH1cbiAgICAgICAgICB9O1xuICAgICAgICAgIHBvcy5wdXNoKG9iaik7XG4gICAgICAgICAgaWYgKCFnKSB7XG4gICAgICAgICAgICByZXR1cm4gcG9zO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfSB3aGlsZSAodCAmJiAoeC5sYXN0SW5kZXggPSBzKSk7XG5cbiAgcmV0dXJuIHBvcztcbn07XG5cbi8qKlxuICogbWF0Y2hSZWN1cnNpdmVSZWdFeHBcbiAqXG4gKiAoYykgMjAwNyBTdGV2ZW4gTGV2aXRoYW4gPHN0ZXZlbmxldml0aGFuLmNvbT5cbiAqIE1JVCBMaWNlbnNlXG4gKlxuICogQWNjZXB0cyBhIHN0cmluZyB0byBzZWFyY2gsIGEgbGVmdCBhbmQgcmlnaHQgZm9ybWF0IGRlbGltaXRlclxuICogYXMgcmVnZXggcGF0dGVybnMsIGFuZCBvcHRpb25hbCByZWdleCBmbGFncy4gUmV0dXJucyBhbiBhcnJheVxuICogb2YgbWF0Y2hlcywgYWxsb3dpbmcgbmVzdGVkIGluc3RhbmNlcyBvZiBsZWZ0L3JpZ2h0IGRlbGltaXRlcnMuXG4gKiBVc2UgdGhlIFwiZ1wiIGZsYWcgdG8gcmV0dXJuIGFsbCBtYXRjaGVzLCBvdGhlcndpc2Ugb25seSB0aGVcbiAqIGZpcnN0IGlzIHJldHVybmVkLiBCZSBjYXJlZnVsIHRvIGVuc3VyZSB0aGF0IHRoZSBsZWZ0IGFuZFxuICogcmlnaHQgZm9ybWF0IGRlbGltaXRlcnMgcHJvZHVjZSBtdXR1YWxseSBleGNsdXNpdmUgbWF0Y2hlcy5cbiAqIEJhY2tyZWZlcmVuY2VzIGFyZSBub3Qgc3VwcG9ydGVkIHdpdGhpbiB0aGUgcmlnaHQgZGVsaW1pdGVyXG4gKiBkdWUgdG8gaG93IGl0IGlzIGludGVybmFsbHkgY29tYmluZWQgd2l0aCB0aGUgbGVmdCBkZWxpbWl0ZXIuXG4gKiBXaGVuIG1hdGNoaW5nIHN0cmluZ3Mgd2hvc2UgZm9ybWF0IGRlbGltaXRlcnMgYXJlIHVuYmFsYW5jZWRcbiAqIHRvIHRoZSBsZWZ0IG9yIHJpZ2h0LCB0aGUgb3V0cHV0IGlzIGludGVudGlvbmFsbHkgYXMgYVxuICogY29udmVudGlvbmFsIHJlZ2V4IGxpYnJhcnkgd2l0aCByZWN1cnNpb24gc3VwcG9ydCB3b3VsZFxuICogcHJvZHVjZSwgZS5nLiBcIjw8eD5cIiBhbmQgXCI8eD4+XCIgYm90aCBwcm9kdWNlIFtcInhcIl0gd2hlbiB1c2luZ1xuICogXCI8XCIgYW5kIFwiPlwiIGFzIHRoZSBkZWxpbWl0ZXJzIChib3RoIHN0cmluZ3MgY29udGFpbiBhIHNpbmdsZSxcbiAqIGJhbGFuY2VkIGluc3RhbmNlIG9mIFwiPHg+XCIpLlxuICpcbiAqIGV4YW1wbGVzOlxuICogbWF0Y2hSZWN1cnNpdmVSZWdFeHAoXCJ0ZXN0XCIsIFwiXFxcXChcIiwgXCJcXFxcKVwiKVxuICogcmV0dXJuczogW11cbiAqIG1hdGNoUmVjdXJzaXZlUmVnRXhwKFwiPHQ8PGU+PjxzPj50PD5cIiwgXCI8XCIsIFwiPlwiLCBcImdcIilcbiAqIHJldHVybnM6IFtcInQ8PGU+PjxzPlwiLCBcIlwiXVxuICogbWF0Y2hSZWN1cnNpdmVSZWdFeHAoXCI8ZGl2IGlkPVxcXCJ4XFxcIj50ZXN0PC9kaXY+XCIsIFwiPGRpdlxcXFxiW14+XSo+XCIsIFwiPC9kaXY+XCIsIFwiZ2lcIilcbiAqIHJldHVybnM6IFtcInRlc3RcIl1cbiAqL1xuc2hvd2Rvd24uaGVscGVyLm1hdGNoUmVjdXJzaXZlUmVnRXhwID0gZnVuY3Rpb24gKHN0ciwgbGVmdCwgcmlnaHQsIGZsYWdzKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICB2YXIgbWF0Y2hQb3MgPSByZ3hGaW5kTWF0Y2hQb3MgKHN0ciwgbGVmdCwgcmlnaHQsIGZsYWdzKSxcbiAgICAgIHJlc3VsdHMgPSBbXTtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IG1hdGNoUG9zLmxlbmd0aDsgKytpKSB7XG4gICAgcmVzdWx0cy5wdXNoKFtcbiAgICAgIHN0ci5zbGljZShtYXRjaFBvc1tpXS53aG9sZU1hdGNoLnN0YXJ0LCBtYXRjaFBvc1tpXS53aG9sZU1hdGNoLmVuZCksXG4gICAgICBzdHIuc2xpY2UobWF0Y2hQb3NbaV0ubWF0Y2guc3RhcnQsIG1hdGNoUG9zW2ldLm1hdGNoLmVuZCksXG4gICAgICBzdHIuc2xpY2UobWF0Y2hQb3NbaV0ubGVmdC5zdGFydCwgbWF0Y2hQb3NbaV0ubGVmdC5lbmQpLFxuICAgICAgc3RyLnNsaWNlKG1hdGNoUG9zW2ldLnJpZ2h0LnN0YXJ0LCBtYXRjaFBvc1tpXS5yaWdodC5lbmQpXG4gICAgXSk7XG4gIH1cbiAgcmV0dXJuIHJlc3VsdHM7XG59O1xuXG4vKipcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gc3RyXG4gKiBAcGFyYW0ge3N0cmluZ3xmdW5jdGlvbn0gcmVwbGFjZW1lbnRcbiAqIEBwYXJhbSB7c3RyaW5nfSBsZWZ0XG4gKiBAcGFyYW0ge3N0cmluZ30gcmlnaHRcbiAqIEBwYXJhbSB7c3RyaW5nfSBmbGFnc1xuICogQHJldHVybnMge3N0cmluZ31cbiAqL1xuc2hvd2Rvd24uaGVscGVyLnJlcGxhY2VSZWN1cnNpdmVSZWdFeHAgPSBmdW5jdGlvbiAoc3RyLCByZXBsYWNlbWVudCwgbGVmdCwgcmlnaHQsIGZsYWdzKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICBpZiAoIXNob3dkb3duLmhlbHBlci5pc0Z1bmN0aW9uKHJlcGxhY2VtZW50KSkge1xuICAgIHZhciByZXBTdHIgPSByZXBsYWNlbWVudDtcbiAgICByZXBsYWNlbWVudCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiByZXBTdHI7XG4gICAgfTtcbiAgfVxuXG4gIHZhciBtYXRjaFBvcyA9IHJneEZpbmRNYXRjaFBvcyhzdHIsIGxlZnQsIHJpZ2h0LCBmbGFncyksXG4gICAgICBmaW5hbFN0ciA9IHN0cixcbiAgICAgIGxuZyA9IG1hdGNoUG9zLmxlbmd0aDtcblxuICBpZiAobG5nID4gMCkge1xuICAgIHZhciBiaXRzID0gW107XG4gICAgaWYgKG1hdGNoUG9zWzBdLndob2xlTWF0Y2guc3RhcnQgIT09IDApIHtcbiAgICAgIGJpdHMucHVzaChzdHIuc2xpY2UoMCwgbWF0Y2hQb3NbMF0ud2hvbGVNYXRjaC5zdGFydCkpO1xuICAgIH1cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxuZzsgKytpKSB7XG4gICAgICBiaXRzLnB1c2goXG4gICAgICAgIHJlcGxhY2VtZW50KFxuICAgICAgICAgIHN0ci5zbGljZShtYXRjaFBvc1tpXS53aG9sZU1hdGNoLnN0YXJ0LCBtYXRjaFBvc1tpXS53aG9sZU1hdGNoLmVuZCksXG4gICAgICAgICAgc3RyLnNsaWNlKG1hdGNoUG9zW2ldLm1hdGNoLnN0YXJ0LCBtYXRjaFBvc1tpXS5tYXRjaC5lbmQpLFxuICAgICAgICAgIHN0ci5zbGljZShtYXRjaFBvc1tpXS5sZWZ0LnN0YXJ0LCBtYXRjaFBvc1tpXS5sZWZ0LmVuZCksXG4gICAgICAgICAgc3RyLnNsaWNlKG1hdGNoUG9zW2ldLnJpZ2h0LnN0YXJ0LCBtYXRjaFBvc1tpXS5yaWdodC5lbmQpXG4gICAgICAgIClcbiAgICAgICk7XG4gICAgICBpZiAoaSA8IGxuZyAtIDEpIHtcbiAgICAgICAgYml0cy5wdXNoKHN0ci5zbGljZShtYXRjaFBvc1tpXS53aG9sZU1hdGNoLmVuZCwgbWF0Y2hQb3NbaSArIDFdLndob2xlTWF0Y2guc3RhcnQpKTtcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKG1hdGNoUG9zW2xuZyAtIDFdLndob2xlTWF0Y2guZW5kIDwgc3RyLmxlbmd0aCkge1xuICAgICAgYml0cy5wdXNoKHN0ci5zbGljZShtYXRjaFBvc1tsbmcgLSAxXS53aG9sZU1hdGNoLmVuZCkpO1xuICAgIH1cbiAgICBmaW5hbFN0ciA9IGJpdHMuam9pbignJyk7XG4gIH1cbiAgcmV0dXJuIGZpbmFsU3RyO1xufTtcblxuLyoqXG4gKiBSZXR1cm5zIHRoZSBpbmRleCB3aXRoaW4gdGhlIHBhc3NlZCBTdHJpbmcgb2JqZWN0IG9mIHRoZSBmaXJzdCBvY2N1cnJlbmNlIG9mIHRoZSBzcGVjaWZpZWQgcmVnZXgsXG4gKiBzdGFydGluZyB0aGUgc2VhcmNoIGF0IGZyb21JbmRleC4gUmV0dXJucyAtMSBpZiB0aGUgdmFsdWUgaXMgbm90IGZvdW5kLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBzdHIgc3RyaW5nIHRvIHNlYXJjaFxuICogQHBhcmFtIHtSZWdFeHB9IHJlZ2V4IFJlZ3VsYXIgZXhwcmVzc2lvbiB0byBzZWFyY2hcbiAqIEBwYXJhbSB7aW50fSBbZnJvbUluZGV4ID0gMF0gSW5kZXggdG8gc3RhcnQgdGhlIHNlYXJjaFxuICogQHJldHVybnMge051bWJlcn1cbiAqIEB0aHJvd3MgSW52YWxpZEFyZ3VtZW50RXJyb3JcbiAqL1xuc2hvd2Rvd24uaGVscGVyLnJlZ2V4SW5kZXhPZiA9IGZ1bmN0aW9uIChzdHIsIHJlZ2V4LCBmcm9tSW5kZXgpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuICBpZiAoIXNob3dkb3duLmhlbHBlci5pc1N0cmluZyhzdHIpKSB7XG4gICAgdGhyb3cgJ0ludmFsaWRBcmd1bWVudEVycm9yOiBmaXJzdCBwYXJhbWV0ZXIgb2Ygc2hvd2Rvd24uaGVscGVyLnJlZ2V4SW5kZXhPZiBmdW5jdGlvbiBtdXN0IGJlIGEgc3RyaW5nJztcbiAgfVxuICBpZiAocmVnZXggaW5zdGFuY2VvZiBSZWdFeHAgPT09IGZhbHNlKSB7XG4gICAgdGhyb3cgJ0ludmFsaWRBcmd1bWVudEVycm9yOiBzZWNvbmQgcGFyYW1ldGVyIG9mIHNob3dkb3duLmhlbHBlci5yZWdleEluZGV4T2YgZnVuY3Rpb24gbXVzdCBiZSBhbiBpbnN0YW5jZSBvZiBSZWdFeHAnO1xuICB9XG4gIHZhciBpbmRleE9mID0gc3RyLnN1YnN0cmluZyhmcm9tSW5kZXggfHwgMCkuc2VhcmNoKHJlZ2V4KTtcbiAgcmV0dXJuIChpbmRleE9mID49IDApID8gKGluZGV4T2YgKyAoZnJvbUluZGV4IHx8IDApKSA6IGluZGV4T2Y7XG59O1xuXG4vKipcbiAqIFNwbGl0cyB0aGUgcGFzc2VkIHN0cmluZyBvYmplY3QgYXQgdGhlIGRlZmluZWQgaW5kZXgsIGFuZCByZXR1cm5zIGFuIGFycmF5IGNvbXBvc2VkIG9mIHRoZSB0d28gc3Vic3RyaW5nc1xuICogQHBhcmFtIHtzdHJpbmd9IHN0ciBzdHJpbmcgdG8gc3BsaXRcbiAqIEBwYXJhbSB7aW50fSBpbmRleCBpbmRleCB0byBzcGxpdCBzdHJpbmcgYXRcbiAqIEByZXR1cm5zIHtbc3RyaW5nLHN0cmluZ119XG4gKiBAdGhyb3dzIEludmFsaWRBcmd1bWVudEVycm9yXG4gKi9cbnNob3dkb3duLmhlbHBlci5zcGxpdEF0SW5kZXggPSBmdW5jdGlvbiAoc3RyLCBpbmRleCkge1xuICAndXNlIHN0cmljdCc7XG4gIGlmICghc2hvd2Rvd24uaGVscGVyLmlzU3RyaW5nKHN0cikpIHtcbiAgICB0aHJvdyAnSW52YWxpZEFyZ3VtZW50RXJyb3I6IGZpcnN0IHBhcmFtZXRlciBvZiBzaG93ZG93bi5oZWxwZXIucmVnZXhJbmRleE9mIGZ1bmN0aW9uIG11c3QgYmUgYSBzdHJpbmcnO1xuICB9XG4gIHJldHVybiBbc3RyLnN1YnN0cmluZygwLCBpbmRleCksIHN0ci5zdWJzdHJpbmcoaW5kZXgpXTtcbn07XG5cbi8qKlxuICogT2JmdXNjYXRlIGFuIGUtbWFpbCBhZGRyZXNzIHRocm91Z2ggdGhlIHVzZSBvZiBDaGFyYWN0ZXIgRW50aXRpZXMsXG4gKiB0cmFuc2Zvcm1pbmcgQVNDSUkgY2hhcmFjdGVycyBpbnRvIHRoZWlyIGVxdWl2YWxlbnQgZGVjaW1hbCBvciBoZXggZW50aXRpZXMuXG4gKlxuICogU2luY2UgaXQgaGFzIGEgcmFuZG9tIGNvbXBvbmVudCwgc3Vic2VxdWVudCBjYWxscyB0byB0aGlzIGZ1bmN0aW9uIHByb2R1Y2UgZGlmZmVyZW50IHJlc3VsdHNcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gbWFpbFxuICogQHJldHVybnMge3N0cmluZ31cbiAqL1xuc2hvd2Rvd24uaGVscGVyLmVuY29kZUVtYWlsQWRkcmVzcyA9IGZ1bmN0aW9uIChtYWlsKSB7XG4gICd1c2Ugc3RyaWN0JztcbiAgdmFyIGVuY29kZSA9IFtcbiAgICBmdW5jdGlvbiAoY2gpIHtcbiAgICAgIHJldHVybiAnJiMnICsgY2guY2hhckNvZGVBdCgwKSArICc7JztcbiAgICB9LFxuICAgIGZ1bmN0aW9uIChjaCkge1xuICAgICAgcmV0dXJuICcmI3gnICsgY2guY2hhckNvZGVBdCgwKS50b1N0cmluZygxNikgKyAnOyc7XG4gICAgfSxcbiAgICBmdW5jdGlvbiAoY2gpIHtcbiAgICAgIHJldHVybiBjaDtcbiAgICB9XG4gIF07XG5cbiAgbWFpbCA9IG1haWwucmVwbGFjZSgvLi9nLCBmdW5jdGlvbiAoY2gpIHtcbiAgICBpZiAoY2ggPT09ICdAJykge1xuICAgICAgLy8gdGhpcyAqbXVzdCogYmUgZW5jb2RlZC4gSSBpbnNpc3QuXG4gICAgICBjaCA9IGVuY29kZVtNYXRoLmZsb29yKE1hdGgucmFuZG9tKCkgKiAyKV0oY2gpO1xuICAgIH0gZWxzZSB7XG4gICAgICB2YXIgciA9IE1hdGgucmFuZG9tKCk7XG4gICAgICAvLyByb3VnaGx5IDEwJSByYXcsIDQ1JSBoZXgsIDQ1JSBkZWNcbiAgICAgIGNoID0gKFxuICAgICAgICByID4gMC45ID8gZW5jb2RlWzJdKGNoKSA6IHIgPiAwLjQ1ID8gZW5jb2RlWzFdKGNoKSA6IGVuY29kZVswXShjaClcbiAgICAgICk7XG4gICAgfVxuICAgIHJldHVybiBjaDtcbiAgfSk7XG5cbiAgcmV0dXJuIG1haWw7XG59O1xuXG4vKipcbiAqIFBPTFlGSUxMU1xuICovXG4vLyB1c2UgdGhpcyBpbnN0ZWFkIG9mIGJ1aWx0aW4gaXMgdW5kZWZpbmVkIGZvciBJRTggY29tcGF0aWJpbGl0eVxuaWYgKHR5cGVvZihjb25zb2xlKSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgY29uc29sZSA9IHtcbiAgICB3YXJuOiBmdW5jdGlvbiAobXNnKSB7XG4gICAgICAndXNlIHN0cmljdCc7XG4gICAgICBhbGVydChtc2cpO1xuICAgIH0sXG4gICAgbG9nOiBmdW5jdGlvbiAobXNnKSB7XG4gICAgICAndXNlIHN0cmljdCc7XG4gICAgICBhbGVydChtc2cpO1xuICAgIH0sXG4gICAgZXJyb3I6IGZ1bmN0aW9uIChtc2cpIHtcbiAgICAgICd1c2Ugc3RyaWN0JztcbiAgICAgIHRocm93IG1zZztcbiAgICB9XG4gIH07XG59XG5cbi8qKlxuICogQ29tbW9uIHJlZ2V4ZXMuXG4gKiBXZSBkZWNsYXJlIHNvbWUgY29tbW9uIHJlZ2V4ZXMgdG8gaW1wcm92ZSBwZXJmb3JtYW5jZVxuICovXG5zaG93ZG93bi5oZWxwZXIucmVnZXhlcyA9IHtcbiAgYXN0ZXJpc2tEYXNoQW5kQ29sb246IC8oWypfOn5dKS9nXG59O1xuXG4vKipcbiAqIEVNT0pJUyBMSVNUXG4gKi9cbnNob3dkb3duLmhlbHBlci5lbW9qaXMgPSB7XG4gICcrMSc6J1xcdWQ4M2RcXHVkYzRkJyxcbiAgJy0xJzonXFx1ZDgzZFxcdWRjNGUnLFxuICAnMTAwJzonXFx1ZDgzZFxcdWRjYWYnLFxuICAnMTIzNCc6J1xcdWQ4M2RcXHVkZDIyJyxcbiAgJzFzdF9wbGFjZV9tZWRhbCc6J1xcdWQ4M2VcXHVkZDQ3JyxcbiAgJzJuZF9wbGFjZV9tZWRhbCc6J1xcdWQ4M2VcXHVkZDQ4JyxcbiAgJzNyZF9wbGFjZV9tZWRhbCc6J1xcdWQ4M2VcXHVkZDQ5JyxcbiAgJzhiYWxsJzonXFx1ZDgzY1xcdWRmYjEnLFxuICAnYSc6J1xcdWQ4M2NcXHVkZDcwXFx1ZmUwZicsXG4gICdhYic6J1xcdWQ4M2NcXHVkZDhlJyxcbiAgJ2FiYyc6J1xcdWQ4M2RcXHVkZDI0JyxcbiAgJ2FiY2QnOidcXHVkODNkXFx1ZGQyMScsXG4gICdhY2NlcHQnOidcXHVkODNjXFx1ZGU1MScsXG4gICdhZXJpYWxfdHJhbXdheSc6J1xcdWQ4M2RcXHVkZWExJyxcbiAgJ2FpcnBsYW5lJzonXFx1MjcwOFxcdWZlMGYnLFxuICAnYWxhcm1fY2xvY2snOidcXHUyM2YwJyxcbiAgJ2FsZW1iaWMnOidcXHUyNjk3XFx1ZmUwZicsXG4gICdhbGllbic6J1xcdWQ4M2RcXHVkYzdkJyxcbiAgJ2FtYnVsYW5jZSc6J1xcdWQ4M2RcXHVkZTkxJyxcbiAgJ2FtcGhvcmEnOidcXHVkODNjXFx1ZGZmYScsXG4gICdhbmNob3InOidcXHUyNjkzXFx1ZmUwZicsXG4gICdhbmdlbCc6J1xcdWQ4M2RcXHVkYzdjJyxcbiAgJ2FuZ2VyJzonXFx1ZDgzZFxcdWRjYTInLFxuICAnYW5ncnknOidcXHVkODNkXFx1ZGUyMCcsXG4gICdhbmd1aXNoZWQnOidcXHVkODNkXFx1ZGUyNycsXG4gICdhbnQnOidcXHVkODNkXFx1ZGMxYycsXG4gICdhcHBsZSc6J1xcdWQ4M2NcXHVkZjRlJyxcbiAgJ2FxdWFyaXVzJzonXFx1MjY1MlxcdWZlMGYnLFxuICAnYXJpZXMnOidcXHUyNjQ4XFx1ZmUwZicsXG4gICdhcnJvd19iYWNrd2FyZCc6J1xcdTI1YzBcXHVmZTBmJyxcbiAgJ2Fycm93X2RvdWJsZV9kb3duJzonXFx1MjNlYycsXG4gICdhcnJvd19kb3VibGVfdXAnOidcXHUyM2ViJyxcbiAgJ2Fycm93X2Rvd24nOidcXHUyYjA3XFx1ZmUwZicsXG4gICdhcnJvd19kb3duX3NtYWxsJzonXFx1ZDgzZFxcdWRkM2QnLFxuICAnYXJyb3dfZm9yd2FyZCc6J1xcdTI1YjZcXHVmZTBmJyxcbiAgJ2Fycm93X2hlYWRpbmdfZG93bic6J1xcdTI5MzVcXHVmZTBmJyxcbiAgJ2Fycm93X2hlYWRpbmdfdXAnOidcXHUyOTM0XFx1ZmUwZicsXG4gICdhcnJvd19sZWZ0JzonXFx1MmIwNVxcdWZlMGYnLFxuICAnYXJyb3dfbG93ZXJfbGVmdCc6J1xcdTIxOTlcXHVmZTBmJyxcbiAgJ2Fycm93X2xvd2VyX3JpZ2h0JzonXFx1MjE5OFxcdWZlMGYnLFxuICAnYXJyb3dfcmlnaHQnOidcXHUyN2ExXFx1ZmUwZicsXG4gICdhcnJvd19yaWdodF9ob29rJzonXFx1MjFhYVxcdWZlMGYnLFxuICAnYXJyb3dfdXAnOidcXHUyYjA2XFx1ZmUwZicsXG4gICdhcnJvd191cF9kb3duJzonXFx1MjE5NVxcdWZlMGYnLFxuICAnYXJyb3dfdXBfc21hbGwnOidcXHVkODNkXFx1ZGQzYycsXG4gICdhcnJvd191cHBlcl9sZWZ0JzonXFx1MjE5NlxcdWZlMGYnLFxuICAnYXJyb3dfdXBwZXJfcmlnaHQnOidcXHUyMTk3XFx1ZmUwZicsXG4gICdhcnJvd3NfY2xvY2t3aXNlJzonXFx1ZDgzZFxcdWRkMDMnLFxuICAnYXJyb3dzX2NvdW50ZXJjbG9ja3dpc2UnOidcXHVkODNkXFx1ZGQwNCcsXG4gICdhcnQnOidcXHVkODNjXFx1ZGZhOCcsXG4gICdhcnRpY3VsYXRlZF9sb3JyeSc6J1xcdWQ4M2RcXHVkZTliJyxcbiAgJ2FydGlmaWNpYWxfc2F0ZWxsaXRlJzonXFx1ZDgzZFxcdWRlZjAnLFxuICAnYXN0b25pc2hlZCc6J1xcdWQ4M2RcXHVkZTMyJyxcbiAgJ2F0aGxldGljX3Nob2UnOidcXHVkODNkXFx1ZGM1ZicsXG4gICdhdG0nOidcXHVkODNjXFx1ZGZlNycsXG4gICdhdG9tX3N5bWJvbCc6J1xcdTI2OWJcXHVmZTBmJyxcbiAgJ2F2b2NhZG8nOidcXHVkODNlXFx1ZGQ1MScsXG4gICdiJzonXFx1ZDgzY1xcdWRkNzFcXHVmZTBmJyxcbiAgJ2JhYnknOidcXHVkODNkXFx1ZGM3NicsXG4gICdiYWJ5X2JvdHRsZSc6J1xcdWQ4M2NcXHVkZjdjJyxcbiAgJ2JhYnlfY2hpY2snOidcXHVkODNkXFx1ZGMyNCcsXG4gICdiYWJ5X3N5bWJvbCc6J1xcdWQ4M2RcXHVkZWJjJyxcbiAgJ2JhY2snOidcXHVkODNkXFx1ZGQxOScsXG4gICdiYWNvbic6J1xcdWQ4M2VcXHVkZDUzJyxcbiAgJ2JhZG1pbnRvbic6J1xcdWQ4M2NcXHVkZmY4JyxcbiAgJ2JhZ2dhZ2VfY2xhaW0nOidcXHVkODNkXFx1ZGVjNCcsXG4gICdiYWd1ZXR0ZV9icmVhZCc6J1xcdWQ4M2VcXHVkZDU2JyxcbiAgJ2JhbGFuY2Vfc2NhbGUnOidcXHUyNjk2XFx1ZmUwZicsXG4gICdiYWxsb29uJzonXFx1ZDgzY1xcdWRmODgnLFxuICAnYmFsbG90X2JveCc6J1xcdWQ4M2RcXHVkZGYzJyxcbiAgJ2JhbGxvdF9ib3hfd2l0aF9jaGVjayc6J1xcdTI2MTFcXHVmZTBmJyxcbiAgJ2JhbWJvbyc6J1xcdWQ4M2NcXHVkZjhkJyxcbiAgJ2JhbmFuYSc6J1xcdWQ4M2NcXHVkZjRjJyxcbiAgJ2JhbmdiYW5nJzonXFx1MjAzY1xcdWZlMGYnLFxuICAnYmFuayc6J1xcdWQ4M2NcXHVkZmU2JyxcbiAgJ2Jhcl9jaGFydCc6J1xcdWQ4M2RcXHVkY2NhJyxcbiAgJ2JhcmJlcic6J1xcdWQ4M2RcXHVkYzg4JyxcbiAgJ2Jhc2ViYWxsJzonXFx1MjZiZVxcdWZlMGYnLFxuICAnYmFza2V0YmFsbCc6J1xcdWQ4M2NcXHVkZmMwJyxcbiAgJ2Jhc2tldGJhbGxfbWFuJzonXFx1MjZmOVxcdWZlMGYnLFxuICAnYmFza2V0YmFsbF93b21hbic6J1xcdTI2ZjlcXHVmZTBmJnp3ajtcXHUyNjQwXFx1ZmUwZicsXG4gICdiYXQnOidcXHVkODNlXFx1ZGQ4NycsXG4gICdiYXRoJzonXFx1ZDgzZFxcdWRlYzAnLFxuICAnYmF0aHR1Yic6J1xcdWQ4M2RcXHVkZWMxJyxcbiAgJ2JhdHRlcnknOidcXHVkODNkXFx1ZGQwYicsXG4gICdiZWFjaF91bWJyZWxsYSc6J1xcdWQ4M2NcXHVkZmQ2JyxcbiAgJ2JlYXInOidcXHVkODNkXFx1ZGMzYicsXG4gICdiZWQnOidcXHVkODNkXFx1ZGVjZicsXG4gICdiZWUnOidcXHVkODNkXFx1ZGMxZCcsXG4gICdiZWVyJzonXFx1ZDgzY1xcdWRmN2EnLFxuICAnYmVlcnMnOidcXHVkODNjXFx1ZGY3YicsXG4gICdiZWV0bGUnOidcXHVkODNkXFx1ZGMxZScsXG4gICdiZWdpbm5lcic6J1xcdWQ4M2RcXHVkZDMwJyxcbiAgJ2JlbGwnOidcXHVkODNkXFx1ZGQxNCcsXG4gICdiZWxsaG9wX2JlbGwnOidcXHVkODNkXFx1ZGVjZScsXG4gICdiZW50byc6J1xcdWQ4M2NcXHVkZjcxJyxcbiAgJ2Jpa2luZ19tYW4nOidcXHVkODNkXFx1ZGViNCcsXG4gICdiaWtlJzonXFx1ZDgzZFxcdWRlYjInLFxuICAnYmlraW5nX3dvbWFuJzonXFx1ZDgzZFxcdWRlYjQmendqO1xcdTI2NDBcXHVmZTBmJyxcbiAgJ2Jpa2luaSc6J1xcdWQ4M2RcXHVkYzU5JyxcbiAgJ2Jpb2hhemFyZCc6J1xcdTI2MjNcXHVmZTBmJyxcbiAgJ2JpcmQnOidcXHVkODNkXFx1ZGMyNicsXG4gICdiaXJ0aGRheSc6J1xcdWQ4M2NcXHVkZjgyJyxcbiAgJ2JsYWNrX2NpcmNsZSc6J1xcdTI2YWJcXHVmZTBmJyxcbiAgJ2JsYWNrX2ZsYWcnOidcXHVkODNjXFx1ZGZmNCcsXG4gICdibGFja19oZWFydCc6J1xcdWQ4M2RcXHVkZGE0JyxcbiAgJ2JsYWNrX2pva2VyJzonXFx1ZDgzY1xcdWRjY2YnLFxuICAnYmxhY2tfbGFyZ2Vfc3F1YXJlJzonXFx1MmIxYlxcdWZlMGYnLFxuICAnYmxhY2tfbWVkaXVtX3NtYWxsX3NxdWFyZSc6J1xcdTI1ZmVcXHVmZTBmJyxcbiAgJ2JsYWNrX21lZGl1bV9zcXVhcmUnOidcXHUyNWZjXFx1ZmUwZicsXG4gICdibGFja19uaWInOidcXHUyNzEyXFx1ZmUwZicsXG4gICdibGFja19zbWFsbF9zcXVhcmUnOidcXHUyNWFhXFx1ZmUwZicsXG4gICdibGFja19zcXVhcmVfYnV0dG9uJzonXFx1ZDgzZFxcdWRkMzInLFxuICAnYmxvbmRlX21hbic6J1xcdWQ4M2RcXHVkYzcxJyxcbiAgJ2Jsb25kZV93b21hbic6J1xcdWQ4M2RcXHVkYzcxJnp3ajtcXHUyNjQwXFx1ZmUwZicsXG4gICdibG9zc29tJzonXFx1ZDgzY1xcdWRmM2MnLFxuICAnYmxvd2Zpc2gnOidcXHVkODNkXFx1ZGMyMScsXG4gICdibHVlX2Jvb2snOidcXHVkODNkXFx1ZGNkOCcsXG4gICdibHVlX2Nhcic6J1xcdWQ4M2RcXHVkZTk5JyxcbiAgJ2JsdWVfaGVhcnQnOidcXHVkODNkXFx1ZGM5OScsXG4gICdibHVzaCc6J1xcdWQ4M2RcXHVkZTBhJyxcbiAgJ2JvYXInOidcXHVkODNkXFx1ZGMxNycsXG4gICdib2F0JzonXFx1MjZmNVxcdWZlMGYnLFxuICAnYm9tYic6J1xcdWQ4M2RcXHVkY2EzJyxcbiAgJ2Jvb2snOidcXHVkODNkXFx1ZGNkNicsXG4gICdib29rbWFyayc6J1xcdWQ4M2RcXHVkZDE2JyxcbiAgJ2Jvb2ttYXJrX3RhYnMnOidcXHVkODNkXFx1ZGNkMScsXG4gICdib29rcyc6J1xcdWQ4M2RcXHVkY2RhJyxcbiAgJ2Jvb20nOidcXHVkODNkXFx1ZGNhNScsXG4gICdib290JzonXFx1ZDgzZFxcdWRjNjInLFxuICAnYm91cXVldCc6J1xcdWQ4M2RcXHVkYzkwJyxcbiAgJ2Jvd2luZ19tYW4nOidcXHVkODNkXFx1ZGU0NycsXG4gICdib3dfYW5kX2Fycm93JzonXFx1ZDgzY1xcdWRmZjknLFxuICAnYm93aW5nX3dvbWFuJzonXFx1ZDgzZFxcdWRlNDcmendqO1xcdTI2NDBcXHVmZTBmJyxcbiAgJ2Jvd2xpbmcnOidcXHVkODNjXFx1ZGZiMycsXG4gICdib3hpbmdfZ2xvdmUnOidcXHVkODNlXFx1ZGQ0YScsXG4gICdib3knOidcXHVkODNkXFx1ZGM2NicsXG4gICdicmVhZCc6J1xcdWQ4M2NcXHVkZjVlJyxcbiAgJ2JyaWRlX3dpdGhfdmVpbCc6J1xcdWQ4M2RcXHVkYzcwJyxcbiAgJ2JyaWRnZV9hdF9uaWdodCc6J1xcdWQ4M2NcXHVkZjA5JyxcbiAgJ2JyaWVmY2FzZSc6J1xcdWQ4M2RcXHVkY2JjJyxcbiAgJ2Jyb2tlbl9oZWFydCc6J1xcdWQ4M2RcXHVkYzk0JyxcbiAgJ2J1Zyc6J1xcdWQ4M2RcXHVkYzFiJyxcbiAgJ2J1aWxkaW5nX2NvbnN0cnVjdGlvbic6J1xcdWQ4M2NcXHVkZmQ3JyxcbiAgJ2J1bGInOidcXHVkODNkXFx1ZGNhMScsXG4gICdidWxsZXR0cmFpbl9mcm9udCc6J1xcdWQ4M2RcXHVkZTg1JyxcbiAgJ2J1bGxldHRyYWluX3NpZGUnOidcXHVkODNkXFx1ZGU4NCcsXG4gICdidXJyaXRvJzonXFx1ZDgzY1xcdWRmMmYnLFxuICAnYnVzJzonXFx1ZDgzZFxcdWRlOGMnLFxuICAnYnVzaW5lc3Nfc3VpdF9sZXZpdGF0aW5nJzonXFx1ZDgzZFxcdWRkNzQnLFxuICAnYnVzc3RvcCc6J1xcdWQ4M2RcXHVkZThmJyxcbiAgJ2J1c3RfaW5fc2lsaG91ZXR0ZSc6J1xcdWQ4M2RcXHVkYzY0JyxcbiAgJ2J1c3RzX2luX3NpbGhvdWV0dGUnOidcXHVkODNkXFx1ZGM2NScsXG4gICdidXR0ZXJmbHknOidcXHVkODNlXFx1ZGQ4YicsXG4gICdjYWN0dXMnOidcXHVkODNjXFx1ZGYzNScsXG4gICdjYWtlJzonXFx1ZDgzY1xcdWRmNzAnLFxuICAnY2FsZW5kYXInOidcXHVkODNkXFx1ZGNjNicsXG4gICdjYWxsX21lX2hhbmQnOidcXHVkODNlXFx1ZGQxOScsXG4gICdjYWxsaW5nJzonXFx1ZDgzZFxcdWRjZjInLFxuICAnY2FtZWwnOidcXHVkODNkXFx1ZGMyYicsXG4gICdjYW1lcmEnOidcXHVkODNkXFx1ZGNmNycsXG4gICdjYW1lcmFfZmxhc2gnOidcXHVkODNkXFx1ZGNmOCcsXG4gICdjYW1waW5nJzonXFx1ZDgzY1xcdWRmZDUnLFxuICAnY2FuY2VyJzonXFx1MjY0YlxcdWZlMGYnLFxuICAnY2FuZGxlJzonXFx1ZDgzZFxcdWRkNmYnLFxuICAnY2FuZHknOidcXHVkODNjXFx1ZGY2YycsXG4gICdjYW5vZSc6J1xcdWQ4M2RcXHVkZWY2JyxcbiAgJ2NhcGl0YWxfYWJjZCc6J1xcdWQ4M2RcXHVkZDIwJyxcbiAgJ2NhcHJpY29ybic6J1xcdTI2NTFcXHVmZTBmJyxcbiAgJ2Nhcic6J1xcdWQ4M2RcXHVkZTk3JyxcbiAgJ2NhcmRfZmlsZV9ib3gnOidcXHVkODNkXFx1ZGRjMycsXG4gICdjYXJkX2luZGV4JzonXFx1ZDgzZFxcdWRjYzcnLFxuICAnY2FyZF9pbmRleF9kaXZpZGVycyc6J1xcdWQ4M2RcXHVkZGMyJyxcbiAgJ2Nhcm91c2VsX2hvcnNlJzonXFx1ZDgzY1xcdWRmYTAnLFxuICAnY2Fycm90JzonXFx1ZDgzZVxcdWRkNTUnLFxuICAnY2F0JzonXFx1ZDgzZFxcdWRjMzEnLFxuICAnY2F0Mic6J1xcdWQ4M2RcXHVkYzA4JyxcbiAgJ2NkJzonXFx1ZDgzZFxcdWRjYmYnLFxuICAnY2hhaW5zJzonXFx1MjZkMycsXG4gICdjaGFtcGFnbmUnOidcXHVkODNjXFx1ZGY3ZScsXG4gICdjaGFydCc6J1xcdWQ4M2RcXHVkY2I5JyxcbiAgJ2NoYXJ0X3dpdGhfZG93bndhcmRzX3RyZW5kJzonXFx1ZDgzZFxcdWRjYzknLFxuICAnY2hhcnRfd2l0aF91cHdhcmRzX3RyZW5kJzonXFx1ZDgzZFxcdWRjYzgnLFxuICAnY2hlY2tlcmVkX2ZsYWcnOidcXHVkODNjXFx1ZGZjMScsXG4gICdjaGVlc2UnOidcXHVkODNlXFx1ZGRjMCcsXG4gICdjaGVycmllcyc6J1xcdWQ4M2NcXHVkZjUyJyxcbiAgJ2NoZXJyeV9ibG9zc29tJzonXFx1ZDgzY1xcdWRmMzgnLFxuICAnY2hlc3RudXQnOidcXHVkODNjXFx1ZGYzMCcsXG4gICdjaGlja2VuJzonXFx1ZDgzZFxcdWRjMTQnLFxuICAnY2hpbGRyZW5fY3Jvc3NpbmcnOidcXHVkODNkXFx1ZGViOCcsXG4gICdjaGlwbXVuayc6J1xcdWQ4M2RcXHVkYzNmJyxcbiAgJ2Nob2NvbGF0ZV9iYXInOidcXHVkODNjXFx1ZGY2YicsXG4gICdjaHJpc3RtYXNfdHJlZSc6J1xcdWQ4M2NcXHVkZjg0JyxcbiAgJ2NodXJjaCc6J1xcdTI2ZWFcXHVmZTBmJyxcbiAgJ2NpbmVtYSc6J1xcdWQ4M2NcXHVkZmE2JyxcbiAgJ2NpcmN1c190ZW50JzonXFx1ZDgzY1xcdWRmYWEnLFxuICAnY2l0eV9zdW5yaXNlJzonXFx1ZDgzY1xcdWRmMDcnLFxuICAnY2l0eV9zdW5zZXQnOidcXHVkODNjXFx1ZGYwNicsXG4gICdjaXR5c2NhcGUnOidcXHVkODNjXFx1ZGZkOScsXG4gICdjbCc6J1xcdWQ4M2NcXHVkZDkxJyxcbiAgJ2NsYW1wJzonXFx1ZDgzZFxcdWRkZGMnLFxuICAnY2xhcCc6J1xcdWQ4M2RcXHVkYzRmJyxcbiAgJ2NsYXBwZXInOidcXHVkODNjXFx1ZGZhYycsXG4gICdjbGFzc2ljYWxfYnVpbGRpbmcnOidcXHVkODNjXFx1ZGZkYicsXG4gICdjbGlua2luZ19nbGFzc2VzJzonXFx1ZDgzZVxcdWRkNDInLFxuICAnY2xpcGJvYXJkJzonXFx1ZDgzZFxcdWRjY2InLFxuICAnY2xvY2sxJzonXFx1ZDgzZFxcdWRkNTAnLFxuICAnY2xvY2sxMCc6J1xcdWQ4M2RcXHVkZDU5JyxcbiAgJ2Nsb2NrMTAzMCc6J1xcdWQ4M2RcXHVkZDY1JyxcbiAgJ2Nsb2NrMTEnOidcXHVkODNkXFx1ZGQ1YScsXG4gICdjbG9jazExMzAnOidcXHVkODNkXFx1ZGQ2NicsXG4gICdjbG9jazEyJzonXFx1ZDgzZFxcdWRkNWInLFxuICAnY2xvY2sxMjMwJzonXFx1ZDgzZFxcdWRkNjcnLFxuICAnY2xvY2sxMzAnOidcXHVkODNkXFx1ZGQ1YycsXG4gICdjbG9jazInOidcXHVkODNkXFx1ZGQ1MScsXG4gICdjbG9jazIzMCc6J1xcdWQ4M2RcXHVkZDVkJyxcbiAgJ2Nsb2NrMyc6J1xcdWQ4M2RcXHVkZDUyJyxcbiAgJ2Nsb2NrMzMwJzonXFx1ZDgzZFxcdWRkNWUnLFxuICAnY2xvY2s0JzonXFx1ZDgzZFxcdWRkNTMnLFxuICAnY2xvY2s0MzAnOidcXHVkODNkXFx1ZGQ1ZicsXG4gICdjbG9jazUnOidcXHVkODNkXFx1ZGQ1NCcsXG4gICdjbG9jazUzMCc6J1xcdWQ4M2RcXHVkZDYwJyxcbiAgJ2Nsb2NrNic6J1xcdWQ4M2RcXHVkZDU1JyxcbiAgJ2Nsb2NrNjMwJzonXFx1ZDgzZFxcdWRkNjEnLFxuICAnY2xvY2s3JzonXFx1ZDgzZFxcdWRkNTYnLFxuICAnY2xvY2s3MzAnOidcXHVkODNkXFx1ZGQ2MicsXG4gICdjbG9jazgnOidcXHVkODNkXFx1ZGQ1NycsXG4gICdjbG9jazgzMCc6J1xcdWQ4M2RcXHVkZDYzJyxcbiAgJ2Nsb2NrOSc6J1xcdWQ4M2RcXHVkZDU4JyxcbiAgJ2Nsb2NrOTMwJzonXFx1ZDgzZFxcdWRkNjQnLFxuICAnY2xvc2VkX2Jvb2snOidcXHVkODNkXFx1ZGNkNScsXG4gICdjbG9zZWRfbG9ja193aXRoX2tleSc6J1xcdWQ4M2RcXHVkZDEwJyxcbiAgJ2Nsb3NlZF91bWJyZWxsYSc6J1xcdWQ4M2NcXHVkZjAyJyxcbiAgJ2Nsb3VkJzonXFx1MjYwMVxcdWZlMGYnLFxuICAnY2xvdWRfd2l0aF9saWdodG5pbmcnOidcXHVkODNjXFx1ZGYyOScsXG4gICdjbG91ZF93aXRoX2xpZ2h0bmluZ19hbmRfcmFpbic6J1xcdTI2YzgnLFxuICAnY2xvdWRfd2l0aF9yYWluJzonXFx1ZDgzY1xcdWRmMjcnLFxuICAnY2xvdWRfd2l0aF9zbm93JzonXFx1ZDgzY1xcdWRmMjgnLFxuICAnY2xvd25fZmFjZSc6J1xcdWQ4M2VcXHVkZDIxJyxcbiAgJ2NsdWJzJzonXFx1MjY2M1xcdWZlMGYnLFxuICAnY29ja3RhaWwnOidcXHVkODNjXFx1ZGY3OCcsXG4gICdjb2ZmZWUnOidcXHUyNjE1XFx1ZmUwZicsXG4gICdjb2ZmaW4nOidcXHUyNmIwXFx1ZmUwZicsXG4gICdjb2xkX3N3ZWF0JzonXFx1ZDgzZFxcdWRlMzAnLFxuICAnY29tZXQnOidcXHUyNjA0XFx1ZmUwZicsXG4gICdjb21wdXRlcic6J1xcdWQ4M2RcXHVkY2JiJyxcbiAgJ2NvbXB1dGVyX21vdXNlJzonXFx1ZDgzZFxcdWRkYjEnLFxuICAnY29uZmV0dGlfYmFsbCc6J1xcdWQ4M2NcXHVkZjhhJyxcbiAgJ2NvbmZvdW5kZWQnOidcXHVkODNkXFx1ZGUxNicsXG4gICdjb25mdXNlZCc6J1xcdWQ4M2RcXHVkZTE1JyxcbiAgJ2NvbmdyYXR1bGF0aW9ucyc6J1xcdTMyOTdcXHVmZTBmJyxcbiAgJ2NvbnN0cnVjdGlvbic6J1xcdWQ4M2RcXHVkZWE3JyxcbiAgJ2NvbnN0cnVjdGlvbl93b3JrZXJfbWFuJzonXFx1ZDgzZFxcdWRjNzcnLFxuICAnY29uc3RydWN0aW9uX3dvcmtlcl93b21hbic6J1xcdWQ4M2RcXHVkYzc3Jnp3ajtcXHUyNjQwXFx1ZmUwZicsXG4gICdjb250cm9sX2tub2JzJzonXFx1ZDgzY1xcdWRmOWInLFxuICAnY29udmVuaWVuY2Vfc3RvcmUnOidcXHVkODNjXFx1ZGZlYScsXG4gICdjb29raWUnOidcXHVkODNjXFx1ZGY2YScsXG4gICdjb29sJzonXFx1ZDgzY1xcdWRkOTInLFxuICAncG9saWNlbWFuJzonXFx1ZDgzZFxcdWRjNmUnLFxuICAnY29weXJpZ2h0JzonXFx1MDBhOVxcdWZlMGYnLFxuICAnY29ybic6J1xcdWQ4M2NcXHVkZjNkJyxcbiAgJ2NvdWNoX2FuZF9sYW1wJzonXFx1ZDgzZFxcdWRlY2InLFxuICAnY291cGxlJzonXFx1ZDgzZFxcdWRjNmInLFxuICAnY291cGxlX3dpdGhfaGVhcnRfd29tYW5fbWFuJzonXFx1ZDgzZFxcdWRjOTEnLFxuICAnY291cGxlX3dpdGhfaGVhcnRfbWFuX21hbic6J1xcdWQ4M2RcXHVkYzY4Jnp3ajtcXHUyNzY0XFx1ZmUwZiZ6d2o7XFx1ZDgzZFxcdWRjNjgnLFxuICAnY291cGxlX3dpdGhfaGVhcnRfd29tYW5fd29tYW4nOidcXHVkODNkXFx1ZGM2OSZ6d2o7XFx1Mjc2NFxcdWZlMGYmendqO1xcdWQ4M2RcXHVkYzY5JyxcbiAgJ2NvdXBsZWtpc3NfbWFuX21hbic6J1xcdWQ4M2RcXHVkYzY4Jnp3ajtcXHUyNzY0XFx1ZmUwZiZ6d2o7XFx1ZDgzZFxcdWRjOGImendqO1xcdWQ4M2RcXHVkYzY4JyxcbiAgJ2NvdXBsZWtpc3NfbWFuX3dvbWFuJzonXFx1ZDgzZFxcdWRjOGYnLFxuICAnY291cGxla2lzc193b21hbl93b21hbic6J1xcdWQ4M2RcXHVkYzY5Jnp3ajtcXHUyNzY0XFx1ZmUwZiZ6d2o7XFx1ZDgzZFxcdWRjOGImendqO1xcdWQ4M2RcXHVkYzY5JyxcbiAgJ2Nvdyc6J1xcdWQ4M2RcXHVkYzJlJyxcbiAgJ2NvdzInOidcXHVkODNkXFx1ZGMwNCcsXG4gICdjb3dib3lfaGF0X2ZhY2UnOidcXHVkODNlXFx1ZGQyMCcsXG4gICdjcmFiJzonXFx1ZDgzZVxcdWRkODAnLFxuICAnY3JheW9uJzonXFx1ZDgzZFxcdWRkOGQnLFxuICAnY3JlZGl0X2NhcmQnOidcXHVkODNkXFx1ZGNiMycsXG4gICdjcmVzY2VudF9tb29uJzonXFx1ZDgzY1xcdWRmMTknLFxuICAnY3JpY2tldCc6J1xcdWQ4M2NcXHVkZmNmJyxcbiAgJ2Nyb2NvZGlsZSc6J1xcdWQ4M2RcXHVkYzBhJyxcbiAgJ2Nyb2lzc2FudCc6J1xcdWQ4M2VcXHVkZDUwJyxcbiAgJ2Nyb3NzZWRfZmluZ2Vycyc6J1xcdWQ4M2VcXHVkZDFlJyxcbiAgJ2Nyb3NzZWRfZmxhZ3MnOidcXHVkODNjXFx1ZGY4YycsXG4gICdjcm9zc2VkX3N3b3Jkcyc6J1xcdTI2OTRcXHVmZTBmJyxcbiAgJ2Nyb3duJzonXFx1ZDgzZFxcdWRjNTEnLFxuICAnY3J5JzonXFx1ZDgzZFxcdWRlMjInLFxuICAnY3J5aW5nX2NhdF9mYWNlJzonXFx1ZDgzZFxcdWRlM2YnLFxuICAnY3J5c3RhbF9iYWxsJzonXFx1ZDgzZFxcdWRkMmUnLFxuICAnY3VjdW1iZXInOidcXHVkODNlXFx1ZGQ1MicsXG4gICdjdXBpZCc6J1xcdWQ4M2RcXHVkYzk4JyxcbiAgJ2N1cmx5X2xvb3AnOidcXHUyN2IwJyxcbiAgJ2N1cnJlbmN5X2V4Y2hhbmdlJzonXFx1ZDgzZFxcdWRjYjEnLFxuICAnY3VycnknOidcXHVkODNjXFx1ZGY1YicsXG4gICdjdXN0YXJkJzonXFx1ZDgzY1xcdWRmNmUnLFxuICAnY3VzdG9tcyc6J1xcdWQ4M2RcXHVkZWMzJyxcbiAgJ2N5Y2xvbmUnOidcXHVkODNjXFx1ZGYwMCcsXG4gICdkYWdnZXInOidcXHVkODNkXFx1ZGRlMScsXG4gICdkYW5jZXInOidcXHVkODNkXFx1ZGM4MycsXG4gICdkYW5jaW5nX3dvbWVuJzonXFx1ZDgzZFxcdWRjNmYnLFxuICAnZGFuY2luZ19tZW4nOidcXHVkODNkXFx1ZGM2ZiZ6d2o7XFx1MjY0MlxcdWZlMGYnLFxuICAnZGFuZ28nOidcXHVkODNjXFx1ZGY2MScsXG4gICdkYXJrX3N1bmdsYXNzZXMnOidcXHVkODNkXFx1ZGQ3NicsXG4gICdkYXJ0JzonXFx1ZDgzY1xcdWRmYWYnLFxuICAnZGFzaCc6J1xcdWQ4M2RcXHVkY2E4JyxcbiAgJ2RhdGUnOidcXHVkODNkXFx1ZGNjNScsXG4gICdkZWNpZHVvdXNfdHJlZSc6J1xcdWQ4M2NcXHVkZjMzJyxcbiAgJ2RlZXInOidcXHVkODNlXFx1ZGQ4YycsXG4gICdkZXBhcnRtZW50X3N0b3JlJzonXFx1ZDgzY1xcdWRmZWMnLFxuICAnZGVyZWxpY3RfaG91c2UnOidcXHVkODNjXFx1ZGZkYScsXG4gICdkZXNlcnQnOidcXHVkODNjXFx1ZGZkYycsXG4gICdkZXNlcnRfaXNsYW5kJzonXFx1ZDgzY1xcdWRmZGQnLFxuICAnZGVza3RvcF9jb21wdXRlcic6J1xcdWQ4M2RcXHVkZGE1JyxcbiAgJ21hbGVfZGV0ZWN0aXZlJzonXFx1ZDgzZFxcdWRkNzVcXHVmZTBmJyxcbiAgJ2RpYW1vbmRfc2hhcGVfd2l0aF9hX2RvdF9pbnNpZGUnOidcXHVkODNkXFx1ZGNhMCcsXG4gICdkaWFtb25kcyc6J1xcdTI2NjZcXHVmZTBmJyxcbiAgJ2Rpc2FwcG9pbnRlZCc6J1xcdWQ4M2RcXHVkZTFlJyxcbiAgJ2Rpc2FwcG9pbnRlZF9yZWxpZXZlZCc6J1xcdWQ4M2RcXHVkZTI1JyxcbiAgJ2Rpenp5JzonXFx1ZDgzZFxcdWRjYWInLFxuICAnZGl6enlfZmFjZSc6J1xcdWQ4M2RcXHVkZTM1JyxcbiAgJ2RvX25vdF9saXR0ZXInOidcXHVkODNkXFx1ZGVhZicsXG4gICdkb2cnOidcXHVkODNkXFx1ZGMzNicsXG4gICdkb2cyJzonXFx1ZDgzZFxcdWRjMTUnLFxuICAnZG9sbGFyJzonXFx1ZDgzZFxcdWRjYjUnLFxuICAnZG9sbHMnOidcXHVkODNjXFx1ZGY4ZScsXG4gICdkb2xwaGluJzonXFx1ZDgzZFxcdWRjMmMnLFxuICAnZG9vcic6J1xcdWQ4M2RcXHVkZWFhJyxcbiAgJ2RvdWdobnV0JzonXFx1ZDgzY1xcdWRmNjknLFxuICAnZG92ZSc6J1xcdWQ4M2RcXHVkZDRhJyxcbiAgJ2RyYWdvbic6J1xcdWQ4M2RcXHVkYzA5JyxcbiAgJ2RyYWdvbl9mYWNlJzonXFx1ZDgzZFxcdWRjMzInLFxuICAnZHJlc3MnOidcXHVkODNkXFx1ZGM1NycsXG4gICdkcm9tZWRhcnlfY2FtZWwnOidcXHVkODNkXFx1ZGMyYScsXG4gICdkcm9vbGluZ19mYWNlJzonXFx1ZDgzZVxcdWRkMjQnLFxuICAnZHJvcGxldCc6J1xcdWQ4M2RcXHVkY2E3JyxcbiAgJ2RydW0nOidcXHVkODNlXFx1ZGQ0MScsXG4gICdkdWNrJzonXFx1ZDgzZVxcdWRkODYnLFxuICAnZHZkJzonXFx1ZDgzZFxcdWRjYzAnLFxuICAnZS1tYWlsJzonXFx1ZDgzZFxcdWRjZTcnLFxuICAnZWFnbGUnOidcXHVkODNlXFx1ZGQ4NScsXG4gICdlYXInOidcXHVkODNkXFx1ZGM0MicsXG4gICdlYXJfb2ZfcmljZSc6J1xcdWQ4M2NcXHVkZjNlJyxcbiAgJ2VhcnRoX2FmcmljYSc6J1xcdWQ4M2NcXHVkZjBkJyxcbiAgJ2VhcnRoX2FtZXJpY2FzJzonXFx1ZDgzY1xcdWRmMGUnLFxuICAnZWFydGhfYXNpYSc6J1xcdWQ4M2NcXHVkZjBmJyxcbiAgJ2VnZyc6J1xcdWQ4M2VcXHVkZDVhJyxcbiAgJ2VnZ3BsYW50JzonXFx1ZDgzY1xcdWRmNDYnLFxuICAnZWlnaHRfcG9pbnRlZF9ibGFja19zdGFyJzonXFx1MjczNFxcdWZlMGYnLFxuICAnZWlnaHRfc3Bva2VkX2FzdGVyaXNrJzonXFx1MjczM1xcdWZlMGYnLFxuICAnZWxlY3RyaWNfcGx1Zyc6J1xcdWQ4M2RcXHVkZDBjJyxcbiAgJ2VsZXBoYW50JzonXFx1ZDgzZFxcdWRjMTgnLFxuICAnZW1haWwnOidcXHUyNzA5XFx1ZmUwZicsXG4gICdlbmQnOidcXHVkODNkXFx1ZGQxYScsXG4gICdlbnZlbG9wZV93aXRoX2Fycm93JzonXFx1ZDgzZFxcdWRjZTknLFxuICAnZXVybyc6J1xcdWQ4M2RcXHVkY2I2JyxcbiAgJ2V1cm9wZWFuX2Nhc3RsZSc6J1xcdWQ4M2NcXHVkZmYwJyxcbiAgJ2V1cm9wZWFuX3Bvc3Rfb2ZmaWNlJzonXFx1ZDgzY1xcdWRmZTQnLFxuICAnZXZlcmdyZWVuX3RyZWUnOidcXHVkODNjXFx1ZGYzMicsXG4gICdleGNsYW1hdGlvbic6J1xcdTI3NTdcXHVmZTBmJyxcbiAgJ2V4cHJlc3Npb25sZXNzJzonXFx1ZDgzZFxcdWRlMTEnLFxuICAnZXllJzonXFx1ZDgzZFxcdWRjNDEnLFxuICAnZXllX3NwZWVjaF9idWJibGUnOidcXHVkODNkXFx1ZGM0MSZ6d2o7XFx1ZDgzZFxcdWRkZTgnLFxuICAnZXllZ2xhc3Nlcyc6J1xcdWQ4M2RcXHVkYzUzJyxcbiAgJ2V5ZXMnOidcXHVkODNkXFx1ZGM0MCcsXG4gICdmYWNlX3dpdGhfaGVhZF9iYW5kYWdlJzonXFx1ZDgzZVxcdWRkMTUnLFxuICAnZmFjZV93aXRoX3RoZXJtb21ldGVyJzonXFx1ZDgzZVxcdWRkMTInLFxuICAnZmlzdF9vbmNvbWluZyc6J1xcdWQ4M2RcXHVkYzRhJyxcbiAgJ2ZhY3RvcnknOidcXHVkODNjXFx1ZGZlZCcsXG4gICdmYWxsZW5fbGVhZic6J1xcdWQ4M2NcXHVkZjQyJyxcbiAgJ2ZhbWlseV9tYW5fd29tYW5fYm95JzonXFx1ZDgzZFxcdWRjNmEnLFxuICAnZmFtaWx5X21hbl9ib3knOidcXHVkODNkXFx1ZGM2OCZ6d2o7XFx1ZDgzZFxcdWRjNjYnLFxuICAnZmFtaWx5X21hbl9ib3lfYm95JzonXFx1ZDgzZFxcdWRjNjgmendqO1xcdWQ4M2RcXHVkYzY2Jnp3ajtcXHVkODNkXFx1ZGM2NicsXG4gICdmYW1pbHlfbWFuX2dpcmwnOidcXHVkODNkXFx1ZGM2OCZ6d2o7XFx1ZDgzZFxcdWRjNjcnLFxuICAnZmFtaWx5X21hbl9naXJsX2JveSc6J1xcdWQ4M2RcXHVkYzY4Jnp3ajtcXHVkODNkXFx1ZGM2NyZ6d2o7XFx1ZDgzZFxcdWRjNjYnLFxuICAnZmFtaWx5X21hbl9naXJsX2dpcmwnOidcXHVkODNkXFx1ZGM2OCZ6d2o7XFx1ZDgzZFxcdWRjNjcmendqO1xcdWQ4M2RcXHVkYzY3JyxcbiAgJ2ZhbWlseV9tYW5fbWFuX2JveSc6J1xcdWQ4M2RcXHVkYzY4Jnp3ajtcXHVkODNkXFx1ZGM2OCZ6d2o7XFx1ZDgzZFxcdWRjNjYnLFxuICAnZmFtaWx5X21hbl9tYW5fYm95X2JveSc6J1xcdWQ4M2RcXHVkYzY4Jnp3ajtcXHVkODNkXFx1ZGM2OCZ6d2o7XFx1ZDgzZFxcdWRjNjYmendqO1xcdWQ4M2RcXHVkYzY2JyxcbiAgJ2ZhbWlseV9tYW5fbWFuX2dpcmwnOidcXHVkODNkXFx1ZGM2OCZ6d2o7XFx1ZDgzZFxcdWRjNjgmendqO1xcdWQ4M2RcXHVkYzY3JyxcbiAgJ2ZhbWlseV9tYW5fbWFuX2dpcmxfYm95JzonXFx1ZDgzZFxcdWRjNjgmendqO1xcdWQ4M2RcXHVkYzY4Jnp3ajtcXHVkODNkXFx1ZGM2NyZ6d2o7XFx1ZDgzZFxcdWRjNjYnLFxuICAnZmFtaWx5X21hbl9tYW5fZ2lybF9naXJsJzonXFx1ZDgzZFxcdWRjNjgmendqO1xcdWQ4M2RcXHVkYzY4Jnp3ajtcXHVkODNkXFx1ZGM2NyZ6d2o7XFx1ZDgzZFxcdWRjNjcnLFxuICAnZmFtaWx5X21hbl93b21hbl9ib3lfYm95JzonXFx1ZDgzZFxcdWRjNjgmendqO1xcdWQ4M2RcXHVkYzY5Jnp3ajtcXHVkODNkXFx1ZGM2NiZ6d2o7XFx1ZDgzZFxcdWRjNjYnLFxuICAnZmFtaWx5X21hbl93b21hbl9naXJsJzonXFx1ZDgzZFxcdWRjNjgmendqO1xcdWQ4M2RcXHVkYzY5Jnp3ajtcXHVkODNkXFx1ZGM2NycsXG4gICdmYW1pbHlfbWFuX3dvbWFuX2dpcmxfYm95JzonXFx1ZDgzZFxcdWRjNjgmendqO1xcdWQ4M2RcXHVkYzY5Jnp3ajtcXHVkODNkXFx1ZGM2NyZ6d2o7XFx1ZDgzZFxcdWRjNjYnLFxuICAnZmFtaWx5X21hbl93b21hbl9naXJsX2dpcmwnOidcXHVkODNkXFx1ZGM2OCZ6d2o7XFx1ZDgzZFxcdWRjNjkmendqO1xcdWQ4M2RcXHVkYzY3Jnp3ajtcXHVkODNkXFx1ZGM2NycsXG4gICdmYW1pbHlfd29tYW5fYm95JzonXFx1ZDgzZFxcdWRjNjkmendqO1xcdWQ4M2RcXHVkYzY2JyxcbiAgJ2ZhbWlseV93b21hbl9ib3lfYm95JzonXFx1ZDgzZFxcdWRjNjkmendqO1xcdWQ4M2RcXHVkYzY2Jnp3ajtcXHVkODNkXFx1ZGM2NicsXG4gICdmYW1pbHlfd29tYW5fZ2lybCc6J1xcdWQ4M2RcXHVkYzY5Jnp3ajtcXHVkODNkXFx1ZGM2NycsXG4gICdmYW1pbHlfd29tYW5fZ2lybF9ib3knOidcXHVkODNkXFx1ZGM2OSZ6d2o7XFx1ZDgzZFxcdWRjNjcmendqO1xcdWQ4M2RcXHVkYzY2JyxcbiAgJ2ZhbWlseV93b21hbl9naXJsX2dpcmwnOidcXHVkODNkXFx1ZGM2OSZ6d2o7XFx1ZDgzZFxcdWRjNjcmendqO1xcdWQ4M2RcXHVkYzY3JyxcbiAgJ2ZhbWlseV93b21hbl93b21hbl9ib3knOidcXHVkODNkXFx1ZGM2OSZ6d2o7XFx1ZDgzZFxcdWRjNjkmendqO1xcdWQ4M2RcXHVkYzY2JyxcbiAgJ2ZhbWlseV93b21hbl93b21hbl9ib3lfYm95JzonXFx1ZDgzZFxcdWRjNjkmendqO1xcdWQ4M2RcXHVkYzY5Jnp3ajtcXHVkODNkXFx1ZGM2NiZ6d2o7XFx1ZDgzZFxcdWRjNjYnLFxuICAnZmFtaWx5X3dvbWFuX3dvbWFuX2dpcmwnOidcXHVkODNkXFx1ZGM2OSZ6d2o7XFx1ZDgzZFxcdWRjNjkmendqO1xcdWQ4M2RcXHVkYzY3JyxcbiAgJ2ZhbWlseV93b21hbl93b21hbl9naXJsX2JveSc6J1xcdWQ4M2RcXHVkYzY5Jnp3ajtcXHVkODNkXFx1ZGM2OSZ6d2o7XFx1ZDgzZFxcdWRjNjcmendqO1xcdWQ4M2RcXHVkYzY2JyxcbiAgJ2ZhbWlseV93b21hbl93b21hbl9naXJsX2dpcmwnOidcXHVkODNkXFx1ZGM2OSZ6d2o7XFx1ZDgzZFxcdWRjNjkmendqO1xcdWQ4M2RcXHVkYzY3Jnp3ajtcXHVkODNkXFx1ZGM2NycsXG4gICdmYXN0X2ZvcndhcmQnOidcXHUyM2U5JyxcbiAgJ2ZheCc6J1xcdWQ4M2RcXHVkY2UwJyxcbiAgJ2ZlYXJmdWwnOidcXHVkODNkXFx1ZGUyOCcsXG4gICdmZWV0JzonXFx1ZDgzZFxcdWRjM2UnLFxuICAnZmVtYWxlX2RldGVjdGl2ZSc6J1xcdWQ4M2RcXHVkZDc1XFx1ZmUwZiZ6d2o7XFx1MjY0MFxcdWZlMGYnLFxuICAnZmVycmlzX3doZWVsJzonXFx1ZDgzY1xcdWRmYTEnLFxuICAnZmVycnknOidcXHUyNmY0JyxcbiAgJ2ZpZWxkX2hvY2tleSc6J1xcdWQ4M2NcXHVkZmQxJyxcbiAgJ2ZpbGVfY2FiaW5ldCc6J1xcdWQ4M2RcXHVkZGM0JyxcbiAgJ2ZpbGVfZm9sZGVyJzonXFx1ZDgzZFxcdWRjYzEnLFxuICAnZmlsbV9wcm9qZWN0b3InOidcXHVkODNkXFx1ZGNmZCcsXG4gICdmaWxtX3N0cmlwJzonXFx1ZDgzY1xcdWRmOWUnLFxuICAnZmlyZSc6J1xcdWQ4M2RcXHVkZDI1JyxcbiAgJ2ZpcmVfZW5naW5lJzonXFx1ZDgzZFxcdWRlOTInLFxuICAnZmlyZXdvcmtzJzonXFx1ZDgzY1xcdWRmODYnLFxuICAnZmlyc3RfcXVhcnRlcl9tb29uJzonXFx1ZDgzY1xcdWRmMTMnLFxuICAnZmlyc3RfcXVhcnRlcl9tb29uX3dpdGhfZmFjZSc6J1xcdWQ4M2NcXHVkZjFiJyxcbiAgJ2Zpc2gnOidcXHVkODNkXFx1ZGMxZicsXG4gICdmaXNoX2Nha2UnOidcXHVkODNjXFx1ZGY2NScsXG4gICdmaXNoaW5nX3BvbGVfYW5kX2Zpc2gnOidcXHVkODNjXFx1ZGZhMycsXG4gICdmaXN0X3JhaXNlZCc6J1xcdTI3MGEnLFxuICAnZmlzdF9sZWZ0JzonXFx1ZDgzZVxcdWRkMWInLFxuICAnZmlzdF9yaWdodCc6J1xcdWQ4M2VcXHVkZDFjJyxcbiAgJ2ZsYWdzJzonXFx1ZDgzY1xcdWRmOGYnLFxuICAnZmxhc2hsaWdodCc6J1xcdWQ4M2RcXHVkZDI2JyxcbiAgJ2ZsZXVyX2RlX2xpcyc6J1xcdTI2OWNcXHVmZTBmJyxcbiAgJ2ZsaWdodF9hcnJpdmFsJzonXFx1ZDgzZFxcdWRlZWMnLFxuICAnZmxpZ2h0X2RlcGFydHVyZSc6J1xcdWQ4M2RcXHVkZWViJyxcbiAgJ2Zsb3BweV9kaXNrJzonXFx1ZDgzZFxcdWRjYmUnLFxuICAnZmxvd2VyX3BsYXlpbmdfY2FyZHMnOidcXHVkODNjXFx1ZGZiNCcsXG4gICdmbHVzaGVkJzonXFx1ZDgzZFxcdWRlMzMnLFxuICAnZm9nJzonXFx1ZDgzY1xcdWRmMmInLFxuICAnZm9nZ3knOidcXHVkODNjXFx1ZGYwMScsXG4gICdmb290YmFsbCc6J1xcdWQ4M2NcXHVkZmM4JyxcbiAgJ2Zvb3RwcmludHMnOidcXHVkODNkXFx1ZGM2MycsXG4gICdmb3JrX2FuZF9rbmlmZSc6J1xcdWQ4M2NcXHVkZjc0JyxcbiAgJ2ZvdW50YWluJzonXFx1MjZmMlxcdWZlMGYnLFxuICAnZm91bnRhaW5fcGVuJzonXFx1ZDgzZFxcdWRkOGInLFxuICAnZm91cl9sZWFmX2Nsb3Zlcic6J1xcdWQ4M2NcXHVkZjQwJyxcbiAgJ2ZveF9mYWNlJzonXFx1ZDgzZVxcdWRkOGEnLFxuICAnZnJhbWVkX3BpY3R1cmUnOidcXHVkODNkXFx1ZGRiYycsXG4gICdmcmVlJzonXFx1ZDgzY1xcdWRkOTMnLFxuICAnZnJpZWRfZWdnJzonXFx1ZDgzY1xcdWRmNzMnLFxuICAnZnJpZWRfc2hyaW1wJzonXFx1ZDgzY1xcdWRmNjQnLFxuICAnZnJpZXMnOidcXHVkODNjXFx1ZGY1ZicsXG4gICdmcm9nJzonXFx1ZDgzZFxcdWRjMzgnLFxuICAnZnJvd25pbmcnOidcXHVkODNkXFx1ZGUyNicsXG4gICdmcm93bmluZ19mYWNlJzonXFx1MjYzOVxcdWZlMGYnLFxuICAnZnJvd25pbmdfbWFuJzonXFx1ZDgzZFxcdWRlNGQmendqO1xcdTI2NDJcXHVmZTBmJyxcbiAgJ2Zyb3duaW5nX3dvbWFuJzonXFx1ZDgzZFxcdWRlNGQnLFxuICAnbWlkZGxlX2Zpbmdlcic6J1xcdWQ4M2RcXHVkZDk1JyxcbiAgJ2Z1ZWxwdW1wJzonXFx1MjZmZFxcdWZlMGYnLFxuICAnZnVsbF9tb29uJzonXFx1ZDgzY1xcdWRmMTUnLFxuICAnZnVsbF9tb29uX3dpdGhfZmFjZSc6J1xcdWQ4M2NcXHVkZjFkJyxcbiAgJ2Z1bmVyYWxfdXJuJzonXFx1MjZiMVxcdWZlMGYnLFxuICAnZ2FtZV9kaWUnOidcXHVkODNjXFx1ZGZiMicsXG4gICdnZWFyJzonXFx1MjY5OVxcdWZlMGYnLFxuICAnZ2VtJzonXFx1ZDgzZFxcdWRjOGUnLFxuICAnZ2VtaW5pJzonXFx1MjY0YVxcdWZlMGYnLFxuICAnZ2hvc3QnOidcXHVkODNkXFx1ZGM3YicsXG4gICdnaWZ0JzonXFx1ZDgzY1xcdWRmODEnLFxuICAnZ2lmdF9oZWFydCc6J1xcdWQ4M2RcXHVkYzlkJyxcbiAgJ2dpcmwnOidcXHVkODNkXFx1ZGM2NycsXG4gICdnbG9iZV93aXRoX21lcmlkaWFucyc6J1xcdWQ4M2NcXHVkZjEwJyxcbiAgJ2dvYWxfbmV0JzonXFx1ZDgzZVxcdWRkNDUnLFxuICAnZ29hdCc6J1xcdWQ4M2RcXHVkYzEwJyxcbiAgJ2dvbGYnOidcXHUyNmYzXFx1ZmUwZicsXG4gICdnb2xmaW5nX21hbic6J1xcdWQ4M2NcXHVkZmNjXFx1ZmUwZicsXG4gICdnb2xmaW5nX3dvbWFuJzonXFx1ZDgzY1xcdWRmY2NcXHVmZTBmJnp3ajtcXHUyNjQwXFx1ZmUwZicsXG4gICdnb3JpbGxhJzonXFx1ZDgzZVxcdWRkOGQnLFxuICAnZ3JhcGVzJzonXFx1ZDgzY1xcdWRmNDcnLFxuICAnZ3JlZW5fYXBwbGUnOidcXHVkODNjXFx1ZGY0ZicsXG4gICdncmVlbl9ib29rJzonXFx1ZDgzZFxcdWRjZDcnLFxuICAnZ3JlZW5faGVhcnQnOidcXHVkODNkXFx1ZGM5YScsXG4gICdncmVlbl9zYWxhZCc6J1xcdWQ4M2VcXHVkZDU3JyxcbiAgJ2dyZXlfZXhjbGFtYXRpb24nOidcXHUyNzU1JyxcbiAgJ2dyZXlfcXVlc3Rpb24nOidcXHUyNzU0JyxcbiAgJ2dyaW1hY2luZyc6J1xcdWQ4M2RcXHVkZTJjJyxcbiAgJ2dyaW4nOidcXHVkODNkXFx1ZGUwMScsXG4gICdncmlubmluZyc6J1xcdWQ4M2RcXHVkZTAwJyxcbiAgJ2d1YXJkc21hbic6J1xcdWQ4M2RcXHVkYzgyJyxcbiAgJ2d1YXJkc3dvbWFuJzonXFx1ZDgzZFxcdWRjODImendqO1xcdTI2NDBcXHVmZTBmJyxcbiAgJ2d1aXRhcic6J1xcdWQ4M2NcXHVkZmI4JyxcbiAgJ2d1bic6J1xcdWQ4M2RcXHVkZDJiJyxcbiAgJ2hhaXJjdXRfd29tYW4nOidcXHVkODNkXFx1ZGM4NycsXG4gICdoYWlyY3V0X21hbic6J1xcdWQ4M2RcXHVkYzg3Jnp3ajtcXHUyNjQyXFx1ZmUwZicsXG4gICdoYW1idXJnZXInOidcXHVkODNjXFx1ZGY1NCcsXG4gICdoYW1tZXInOidcXHVkODNkXFx1ZGQyOCcsXG4gICdoYW1tZXJfYW5kX3BpY2snOidcXHUyNjkyJyxcbiAgJ2hhbW1lcl9hbmRfd3JlbmNoJzonXFx1ZDgzZFxcdWRlZTAnLFxuICAnaGFtc3Rlcic6J1xcdWQ4M2RcXHVkYzM5JyxcbiAgJ2hhbmQnOidcXHUyNzBiJyxcbiAgJ2hhbmRiYWcnOidcXHVkODNkXFx1ZGM1YycsXG4gICdoYW5kc2hha2UnOidcXHVkODNlXFx1ZGQxZCcsXG4gICdoYW5rZXknOidcXHVkODNkXFx1ZGNhOScsXG4gICdoYXRjaGVkX2NoaWNrJzonXFx1ZDgzZFxcdWRjMjUnLFxuICAnaGF0Y2hpbmdfY2hpY2snOidcXHVkODNkXFx1ZGMyMycsXG4gICdoZWFkcGhvbmVzJzonXFx1ZDgzY1xcdWRmYTcnLFxuICAnaGVhcl9ub19ldmlsJzonXFx1ZDgzZFxcdWRlNDknLFxuICAnaGVhcnQnOidcXHUyNzY0XFx1ZmUwZicsXG4gICdoZWFydF9kZWNvcmF0aW9uJzonXFx1ZDgzZFxcdWRjOWYnLFxuICAnaGVhcnRfZXllcyc6J1xcdWQ4M2RcXHVkZTBkJyxcbiAgJ2hlYXJ0X2V5ZXNfY2F0JzonXFx1ZDgzZFxcdWRlM2InLFxuICAnaGVhcnRiZWF0JzonXFx1ZDgzZFxcdWRjOTMnLFxuICAnaGVhcnRwdWxzZSc6J1xcdWQ4M2RcXHVkYzk3JyxcbiAgJ2hlYXJ0cyc6J1xcdTI2NjVcXHVmZTBmJyxcbiAgJ2hlYXZ5X2NoZWNrX21hcmsnOidcXHUyNzE0XFx1ZmUwZicsXG4gICdoZWF2eV9kaXZpc2lvbl9zaWduJzonXFx1Mjc5NycsXG4gICdoZWF2eV9kb2xsYXJfc2lnbic6J1xcdWQ4M2RcXHVkY2IyJyxcbiAgJ2hlYXZ5X2hlYXJ0X2V4Y2xhbWF0aW9uJzonXFx1Mjc2M1xcdWZlMGYnLFxuICAnaGVhdnlfbWludXNfc2lnbic6J1xcdTI3OTYnLFxuICAnaGVhdnlfbXVsdGlwbGljYXRpb25feCc6J1xcdTI3MTZcXHVmZTBmJyxcbiAgJ2hlYXZ5X3BsdXNfc2lnbic6J1xcdTI3OTUnLFxuICAnaGVsaWNvcHRlcic6J1xcdWQ4M2RcXHVkZTgxJyxcbiAgJ2hlcmInOidcXHVkODNjXFx1ZGYzZicsXG4gICdoaWJpc2N1cyc6J1xcdWQ4M2NcXHVkZjNhJyxcbiAgJ2hpZ2hfYnJpZ2h0bmVzcyc6J1xcdWQ4M2RcXHVkZDA2JyxcbiAgJ2hpZ2hfaGVlbCc6J1xcdWQ4M2RcXHVkYzYwJyxcbiAgJ2hvY2hvJzonXFx1ZDgzZFxcdWRkMmEnLFxuICAnaG9sZSc6J1xcdWQ4M2RcXHVkZDczJyxcbiAgJ2hvbmV5X3BvdCc6J1xcdWQ4M2NcXHVkZjZmJyxcbiAgJ2hvcnNlJzonXFx1ZDgzZFxcdWRjMzQnLFxuICAnaG9yc2VfcmFjaW5nJzonXFx1ZDgzY1xcdWRmYzcnLFxuICAnaG9zcGl0YWwnOidcXHVkODNjXFx1ZGZlNScsXG4gICdob3RfcGVwcGVyJzonXFx1ZDgzY1xcdWRmMzYnLFxuICAnaG90ZG9nJzonXFx1ZDgzY1xcdWRmMmQnLFxuICAnaG90ZWwnOidcXHVkODNjXFx1ZGZlOCcsXG4gICdob3RzcHJpbmdzJzonXFx1MjY2OFxcdWZlMGYnLFxuICAnaG91cmdsYXNzJzonXFx1MjMxYlxcdWZlMGYnLFxuICAnaG91cmdsYXNzX2Zsb3dpbmdfc2FuZCc6J1xcdTIzZjMnLFxuICAnaG91c2UnOidcXHVkODNjXFx1ZGZlMCcsXG4gICdob3VzZV93aXRoX2dhcmRlbic6J1xcdWQ4M2NcXHVkZmUxJyxcbiAgJ2hvdXNlcyc6J1xcdWQ4M2NcXHVkZmQ4JyxcbiAgJ2h1Z3MnOidcXHVkODNlXFx1ZGQxNycsXG4gICdodXNoZWQnOidcXHVkODNkXFx1ZGUyZicsXG4gICdpY2VfY3JlYW0nOidcXHVkODNjXFx1ZGY2OCcsXG4gICdpY2VfaG9ja2V5JzonXFx1ZDgzY1xcdWRmZDInLFxuICAnaWNlX3NrYXRlJzonXFx1MjZmOCcsXG4gICdpY2VjcmVhbSc6J1xcdWQ4M2NcXHVkZjY2JyxcbiAgJ2lkJzonXFx1ZDgzY1xcdWRkOTQnLFxuICAnaWRlb2dyYXBoX2FkdmFudGFnZSc6J1xcdWQ4M2NcXHVkZTUwJyxcbiAgJ2ltcCc6J1xcdWQ4M2RcXHVkYzdmJyxcbiAgJ2luYm94X3RyYXknOidcXHVkODNkXFx1ZGNlNScsXG4gICdpbmNvbWluZ19lbnZlbG9wZSc6J1xcdWQ4M2RcXHVkY2U4JyxcbiAgJ3RpcHBpbmdfaGFuZF93b21hbic6J1xcdWQ4M2RcXHVkYzgxJyxcbiAgJ2luZm9ybWF0aW9uX3NvdXJjZSc6J1xcdTIxMzlcXHVmZTBmJyxcbiAgJ2lubm9jZW50JzonXFx1ZDgzZFxcdWRlMDcnLFxuICAnaW50ZXJyb2JhbmcnOidcXHUyMDQ5XFx1ZmUwZicsXG4gICdpcGhvbmUnOidcXHVkODNkXFx1ZGNmMScsXG4gICdpemFrYXlhX2xhbnRlcm4nOidcXHVkODNjXFx1ZGZlZScsXG4gICdqYWNrX29fbGFudGVybic6J1xcdWQ4M2NcXHVkZjgzJyxcbiAgJ2phcGFuJzonXFx1ZDgzZFxcdWRkZmUnLFxuICAnamFwYW5lc2VfY2FzdGxlJzonXFx1ZDgzY1xcdWRmZWYnLFxuICAnamFwYW5lc2VfZ29ibGluJzonXFx1ZDgzZFxcdWRjN2EnLFxuICAnamFwYW5lc2Vfb2dyZSc6J1xcdWQ4M2RcXHVkYzc5JyxcbiAgJ2plYW5zJzonXFx1ZDgzZFxcdWRjNTYnLFxuICAnam95JzonXFx1ZDgzZFxcdWRlMDInLFxuICAnam95X2NhdCc6J1xcdWQ4M2RcXHVkZTM5JyxcbiAgJ2pveXN0aWNrJzonXFx1ZDgzZFxcdWRkNzknLFxuICAna2FhYmEnOidcXHVkODNkXFx1ZGQ0YicsXG4gICdrZXknOidcXHVkODNkXFx1ZGQxMScsXG4gICdrZXlib2FyZCc6J1xcdTIzMjhcXHVmZTBmJyxcbiAgJ2tleWNhcF90ZW4nOidcXHVkODNkXFx1ZGQxZicsXG4gICdraWNrX3Njb290ZXInOidcXHVkODNkXFx1ZGVmNCcsXG4gICdraW1vbm8nOidcXHVkODNkXFx1ZGM1OCcsXG4gICdraXNzJzonXFx1ZDgzZFxcdWRjOGInLFxuICAna2lzc2luZyc6J1xcdWQ4M2RcXHVkZTE3JyxcbiAgJ2tpc3NpbmdfY2F0JzonXFx1ZDgzZFxcdWRlM2QnLFxuICAna2lzc2luZ19jbG9zZWRfZXllcyc6J1xcdWQ4M2RcXHVkZTFhJyxcbiAgJ2tpc3NpbmdfaGVhcnQnOidcXHVkODNkXFx1ZGUxOCcsXG4gICdraXNzaW5nX3NtaWxpbmdfZXllcyc6J1xcdWQ4M2RcXHVkZTE5JyxcbiAgJ2tpd2lfZnJ1aXQnOidcXHVkODNlXFx1ZGQ1ZCcsXG4gICdrb2FsYSc6J1xcdWQ4M2RcXHVkYzI4JyxcbiAgJ2tva28nOidcXHVkODNjXFx1ZGUwMScsXG4gICdsYWJlbCc6J1xcdWQ4M2NcXHVkZmY3JyxcbiAgJ2xhcmdlX2JsdWVfY2lyY2xlJzonXFx1ZDgzZFxcdWRkMzUnLFxuICAnbGFyZ2VfYmx1ZV9kaWFtb25kJzonXFx1ZDgzZFxcdWRkMzcnLFxuICAnbGFyZ2Vfb3JhbmdlX2RpYW1vbmQnOidcXHVkODNkXFx1ZGQzNicsXG4gICdsYXN0X3F1YXJ0ZXJfbW9vbic6J1xcdWQ4M2NcXHVkZjE3JyxcbiAgJ2xhc3RfcXVhcnRlcl9tb29uX3dpdGhfZmFjZSc6J1xcdWQ4M2NcXHVkZjFjJyxcbiAgJ2xhdGluX2Nyb3NzJzonXFx1MjcxZFxcdWZlMGYnLFxuICAnbGF1Z2hpbmcnOidcXHVkODNkXFx1ZGUwNicsXG4gICdsZWF2ZXMnOidcXHVkODNjXFx1ZGY0MycsXG4gICdsZWRnZXInOidcXHVkODNkXFx1ZGNkMicsXG4gICdsZWZ0X2x1Z2dhZ2UnOidcXHVkODNkXFx1ZGVjNScsXG4gICdsZWZ0X3JpZ2h0X2Fycm93JzonXFx1MjE5NFxcdWZlMGYnLFxuICAnbGVmdHdhcmRzX2Fycm93X3dpdGhfaG9vayc6J1xcdTIxYTlcXHVmZTBmJyxcbiAgJ2xlbW9uJzonXFx1ZDgzY1xcdWRmNGInLFxuICAnbGVvJzonXFx1MjY0Y1xcdWZlMGYnLFxuICAnbGVvcGFyZCc6J1xcdWQ4M2RcXHVkYzA2JyxcbiAgJ2xldmVsX3NsaWRlcic6J1xcdWQ4M2NcXHVkZjlhJyxcbiAgJ2xpYnJhJzonXFx1MjY0ZVxcdWZlMGYnLFxuICAnbGlnaHRfcmFpbCc6J1xcdWQ4M2RcXHVkZTg4JyxcbiAgJ2xpbmsnOidcXHVkODNkXFx1ZGQxNycsXG4gICdsaW9uJzonXFx1ZDgzZVxcdWRkODEnLFxuICAnbGlwcyc6J1xcdWQ4M2RcXHVkYzQ0JyxcbiAgJ2xpcHN0aWNrJzonXFx1ZDgzZFxcdWRjODQnLFxuICAnbGl6YXJkJzonXFx1ZDgzZVxcdWRkOGUnLFxuICAnbG9jayc6J1xcdWQ4M2RcXHVkZDEyJyxcbiAgJ2xvY2tfd2l0aF9pbmtfcGVuJzonXFx1ZDgzZFxcdWRkMGYnLFxuICAnbG9sbGlwb3AnOidcXHVkODNjXFx1ZGY2ZCcsXG4gICdsb29wJzonXFx1MjdiZicsXG4gICdsb3VkX3NvdW5kJzonXFx1ZDgzZFxcdWRkMGEnLFxuICAnbG91ZHNwZWFrZXInOidcXHVkODNkXFx1ZGNlMicsXG4gICdsb3ZlX2hvdGVsJzonXFx1ZDgzY1xcdWRmZTknLFxuICAnbG92ZV9sZXR0ZXInOidcXHVkODNkXFx1ZGM4YycsXG4gICdsb3dfYnJpZ2h0bmVzcyc6J1xcdWQ4M2RcXHVkZDA1JyxcbiAgJ2x5aW5nX2ZhY2UnOidcXHVkODNlXFx1ZGQyNScsXG4gICdtJzonXFx1MjRjMlxcdWZlMGYnLFxuICAnbWFnJzonXFx1ZDgzZFxcdWRkMGQnLFxuICAnbWFnX3JpZ2h0JzonXFx1ZDgzZFxcdWRkMGUnLFxuICAnbWFoam9uZyc6J1xcdWQ4M2NcXHVkYzA0XFx1ZmUwZicsXG4gICdtYWlsYm94JzonXFx1ZDgzZFxcdWRjZWInLFxuICAnbWFpbGJveF9jbG9zZWQnOidcXHVkODNkXFx1ZGNlYScsXG4gICdtYWlsYm94X3dpdGhfbWFpbCc6J1xcdWQ4M2RcXHVkY2VjJyxcbiAgJ21haWxib3hfd2l0aF9ub19tYWlsJzonXFx1ZDgzZFxcdWRjZWQnLFxuICAnbWFuJzonXFx1ZDgzZFxcdWRjNjgnLFxuICAnbWFuX2FydGlzdCc6J1xcdWQ4M2RcXHVkYzY4Jnp3ajtcXHVkODNjXFx1ZGZhOCcsXG4gICdtYW5fYXN0cm9uYXV0JzonXFx1ZDgzZFxcdWRjNjgmendqO1xcdWQ4M2RcXHVkZTgwJyxcbiAgJ21hbl9jYXJ0d2hlZWxpbmcnOidcXHVkODNlXFx1ZGQzOCZ6d2o7XFx1MjY0MlxcdWZlMGYnLFxuICAnbWFuX2Nvb2snOidcXHVkODNkXFx1ZGM2OCZ6d2o7XFx1ZDgzY1xcdWRmNzMnLFxuICAnbWFuX2RhbmNpbmcnOidcXHVkODNkXFx1ZGQ3YScsXG4gICdtYW5fZmFjZXBhbG1pbmcnOidcXHVkODNlXFx1ZGQyNiZ6d2o7XFx1MjY0MlxcdWZlMGYnLFxuICAnbWFuX2ZhY3Rvcnlfd29ya2VyJzonXFx1ZDgzZFxcdWRjNjgmendqO1xcdWQ4M2NcXHVkZmVkJyxcbiAgJ21hbl9mYXJtZXInOidcXHVkODNkXFx1ZGM2OCZ6d2o7XFx1ZDgzY1xcdWRmM2UnLFxuICAnbWFuX2ZpcmVmaWdodGVyJzonXFx1ZDgzZFxcdWRjNjgmendqO1xcdWQ4M2RcXHVkZTkyJyxcbiAgJ21hbl9oZWFsdGhfd29ya2VyJzonXFx1ZDgzZFxcdWRjNjgmendqO1xcdTI2OTVcXHVmZTBmJyxcbiAgJ21hbl9pbl90dXhlZG8nOidcXHVkODNlXFx1ZGQzNScsXG4gICdtYW5fanVkZ2UnOidcXHVkODNkXFx1ZGM2OCZ6d2o7XFx1MjY5NlxcdWZlMGYnLFxuICAnbWFuX2p1Z2dsaW5nJzonXFx1ZDgzZVxcdWRkMzkmendqO1xcdTI2NDJcXHVmZTBmJyxcbiAgJ21hbl9tZWNoYW5pYyc6J1xcdWQ4M2RcXHVkYzY4Jnp3ajtcXHVkODNkXFx1ZGQyNycsXG4gICdtYW5fb2ZmaWNlX3dvcmtlcic6J1xcdWQ4M2RcXHVkYzY4Jnp3ajtcXHVkODNkXFx1ZGNiYycsXG4gICdtYW5fcGlsb3QnOidcXHVkODNkXFx1ZGM2OCZ6d2o7XFx1MjcwOFxcdWZlMGYnLFxuICAnbWFuX3BsYXlpbmdfaGFuZGJhbGwnOidcXHVkODNlXFx1ZGQzZSZ6d2o7XFx1MjY0MlxcdWZlMGYnLFxuICAnbWFuX3BsYXlpbmdfd2F0ZXJfcG9sbyc6J1xcdWQ4M2VcXHVkZDNkJnp3ajtcXHUyNjQyXFx1ZmUwZicsXG4gICdtYW5fc2NpZW50aXN0JzonXFx1ZDgzZFxcdWRjNjgmendqO1xcdWQ4M2RcXHVkZDJjJyxcbiAgJ21hbl9zaHJ1Z2dpbmcnOidcXHVkODNlXFx1ZGQzNyZ6d2o7XFx1MjY0MlxcdWZlMGYnLFxuICAnbWFuX3Npbmdlcic6J1xcdWQ4M2RcXHVkYzY4Jnp3ajtcXHVkODNjXFx1ZGZhNCcsXG4gICdtYW5fc3R1ZGVudCc6J1xcdWQ4M2RcXHVkYzY4Jnp3ajtcXHVkODNjXFx1ZGY5MycsXG4gICdtYW5fdGVhY2hlcic6J1xcdWQ4M2RcXHVkYzY4Jnp3ajtcXHVkODNjXFx1ZGZlYicsXG4gICdtYW5fdGVjaG5vbG9naXN0JzonXFx1ZDgzZFxcdWRjNjgmendqO1xcdWQ4M2RcXHVkY2JiJyxcbiAgJ21hbl93aXRoX2d1YV9waV9tYW8nOidcXHVkODNkXFx1ZGM3MicsXG4gICdtYW5fd2l0aF90dXJiYW4nOidcXHVkODNkXFx1ZGM3MycsXG4gICd0YW5nZXJpbmUnOidcXHVkODNjXFx1ZGY0YScsXG4gICdtYW5zX3Nob2UnOidcXHVkODNkXFx1ZGM1ZScsXG4gICdtYW50ZWxwaWVjZV9jbG9jayc6J1xcdWQ4M2RcXHVkZDcwJyxcbiAgJ21hcGxlX2xlYWYnOidcXHVkODNjXFx1ZGY0MScsXG4gICdtYXJ0aWFsX2FydHNfdW5pZm9ybSc6J1xcdWQ4M2VcXHVkZDRiJyxcbiAgJ21hc2snOidcXHVkODNkXFx1ZGUzNycsXG4gICdtYXNzYWdlX3dvbWFuJzonXFx1ZDgzZFxcdWRjODYnLFxuICAnbWFzc2FnZV9tYW4nOidcXHVkODNkXFx1ZGM4NiZ6d2o7XFx1MjY0MlxcdWZlMGYnLFxuICAnbWVhdF9vbl9ib25lJzonXFx1ZDgzY1xcdWRmNTYnLFxuICAnbWVkYWxfbWlsaXRhcnknOidcXHVkODNjXFx1ZGY5NicsXG4gICdtZWRhbF9zcG9ydHMnOidcXHVkODNjXFx1ZGZjNScsXG4gICdtZWdhJzonXFx1ZDgzZFxcdWRjZTMnLFxuICAnbWVsb24nOidcXHVkODNjXFx1ZGY0OCcsXG4gICdtZW1vJzonXFx1ZDgzZFxcdWRjZGQnLFxuICAnbWVuX3dyZXN0bGluZyc6J1xcdWQ4M2VcXHVkZDNjJnp3ajtcXHUyNjQyXFx1ZmUwZicsXG4gICdtZW5vcmFoJzonXFx1ZDgzZFxcdWRkNGUnLFxuICAnbWVucyc6J1xcdWQ4M2RcXHVkZWI5JyxcbiAgJ21ldGFsJzonXFx1ZDgzZVxcdWRkMTgnLFxuICAnbWV0cm8nOidcXHVkODNkXFx1ZGU4NycsXG4gICdtaWNyb3Bob25lJzonXFx1ZDgzY1xcdWRmYTQnLFxuICAnbWljcm9zY29wZSc6J1xcdWQ4M2RcXHVkZDJjJyxcbiAgJ21pbGtfZ2xhc3MnOidcXHVkODNlXFx1ZGQ1YicsXG4gICdtaWxreV93YXknOidcXHVkODNjXFx1ZGYwYycsXG4gICdtaW5pYnVzJzonXFx1ZDgzZFxcdWRlOTAnLFxuICAnbWluaWRpc2MnOidcXHVkODNkXFx1ZGNiZCcsXG4gICdtb2JpbGVfcGhvbmVfb2ZmJzonXFx1ZDgzZFxcdWRjZjQnLFxuICAnbW9uZXlfbW91dGhfZmFjZSc6J1xcdWQ4M2VcXHVkZDExJyxcbiAgJ21vbmV5X3dpdGhfd2luZ3MnOidcXHVkODNkXFx1ZGNiOCcsXG4gICdtb25leWJhZyc6J1xcdWQ4M2RcXHVkY2IwJyxcbiAgJ21vbmtleSc6J1xcdWQ4M2RcXHVkYzEyJyxcbiAgJ21vbmtleV9mYWNlJzonXFx1ZDgzZFxcdWRjMzUnLFxuICAnbW9ub3JhaWwnOidcXHVkODNkXFx1ZGU5ZCcsXG4gICdtb29uJzonXFx1ZDgzY1xcdWRmMTQnLFxuICAnbW9ydGFyX2JvYXJkJzonXFx1ZDgzY1xcdWRmOTMnLFxuICAnbW9zcXVlJzonXFx1ZDgzZFxcdWRkNGMnLFxuICAnbW90b3JfYm9hdCc6J1xcdWQ4M2RcXHVkZWU1JyxcbiAgJ21vdG9yX3Njb290ZXInOidcXHVkODNkXFx1ZGVmNScsXG4gICdtb3RvcmN5Y2xlJzonXFx1ZDgzY1xcdWRmY2QnLFxuICAnbW90b3J3YXknOidcXHVkODNkXFx1ZGVlMycsXG4gICdtb3VudF9mdWppJzonXFx1ZDgzZFxcdWRkZmInLFxuICAnbW91bnRhaW4nOidcXHUyNmYwJyxcbiAgJ21vdW50YWluX2Jpa2luZ19tYW4nOidcXHVkODNkXFx1ZGViNScsXG4gICdtb3VudGFpbl9iaWtpbmdfd29tYW4nOidcXHVkODNkXFx1ZGViNSZ6d2o7XFx1MjY0MFxcdWZlMGYnLFxuICAnbW91bnRhaW5fY2FibGV3YXknOidcXHVkODNkXFx1ZGVhMCcsXG4gICdtb3VudGFpbl9yYWlsd2F5JzonXFx1ZDgzZFxcdWRlOWUnLFxuICAnbW91bnRhaW5fc25vdyc6J1xcdWQ4M2NcXHVkZmQ0JyxcbiAgJ21vdXNlJzonXFx1ZDgzZFxcdWRjMmQnLFxuICAnbW91c2UyJzonXFx1ZDgzZFxcdWRjMDEnLFxuICAnbW92aWVfY2FtZXJhJzonXFx1ZDgzY1xcdWRmYTUnLFxuICAnbW95YWknOidcXHVkODNkXFx1ZGRmZicsXG4gICdtcnNfY2xhdXMnOidcXHVkODNlXFx1ZGQzNicsXG4gICdtdXNjbGUnOidcXHVkODNkXFx1ZGNhYScsXG4gICdtdXNocm9vbSc6J1xcdWQ4M2NcXHVkZjQ0JyxcbiAgJ211c2ljYWxfa2V5Ym9hcmQnOidcXHVkODNjXFx1ZGZiOScsXG4gICdtdXNpY2FsX25vdGUnOidcXHVkODNjXFx1ZGZiNScsXG4gICdtdXNpY2FsX3Njb3JlJzonXFx1ZDgzY1xcdWRmYmMnLFxuICAnbXV0ZSc6J1xcdWQ4M2RcXHVkZDA3JyxcbiAgJ25haWxfY2FyZSc6J1xcdWQ4M2RcXHVkYzg1JyxcbiAgJ25hbWVfYmFkZ2UnOidcXHVkODNkXFx1ZGNkYicsXG4gICduYXRpb25hbF9wYXJrJzonXFx1ZDgzY1xcdWRmZGUnLFxuICAnbmF1c2VhdGVkX2ZhY2UnOidcXHVkODNlXFx1ZGQyMicsXG4gICduZWNrdGllJzonXFx1ZDgzZFxcdWRjNTQnLFxuICAnbmVnYXRpdmVfc3F1YXJlZF9jcm9zc19tYXJrJzonXFx1Mjc0ZScsXG4gICduZXJkX2ZhY2UnOidcXHVkODNlXFx1ZGQxMycsXG4gICduZXV0cmFsX2ZhY2UnOidcXHVkODNkXFx1ZGUxMCcsXG4gICduZXcnOidcXHVkODNjXFx1ZGQ5NScsXG4gICduZXdfbW9vbic6J1xcdWQ4M2NcXHVkZjExJyxcbiAgJ25ld19tb29uX3dpdGhfZmFjZSc6J1xcdWQ4M2NcXHVkZjFhJyxcbiAgJ25ld3NwYXBlcic6J1xcdWQ4M2RcXHVkY2YwJyxcbiAgJ25ld3NwYXBlcl9yb2xsJzonXFx1ZDgzZFxcdWRkZGUnLFxuICAnbmV4dF90cmFja19idXR0b24nOidcXHUyM2VkJyxcbiAgJ25nJzonXFx1ZDgzY1xcdWRkOTYnLFxuICAnbm9fZ29vZF9tYW4nOidcXHVkODNkXFx1ZGU0NSZ6d2o7XFx1MjY0MlxcdWZlMGYnLFxuICAnbm9fZ29vZF93b21hbic6J1xcdWQ4M2RcXHVkZTQ1JyxcbiAgJ25pZ2h0X3dpdGhfc3RhcnMnOidcXHVkODNjXFx1ZGYwMycsXG4gICdub19iZWxsJzonXFx1ZDgzZFxcdWRkMTUnLFxuICAnbm9fYmljeWNsZXMnOidcXHVkODNkXFx1ZGViMycsXG4gICdub19lbnRyeSc6J1xcdTI2ZDRcXHVmZTBmJyxcbiAgJ25vX2VudHJ5X3NpZ24nOidcXHVkODNkXFx1ZGVhYicsXG4gICdub19tb2JpbGVfcGhvbmVzJzonXFx1ZDgzZFxcdWRjZjUnLFxuICAnbm9fbW91dGgnOidcXHVkODNkXFx1ZGUzNicsXG4gICdub19wZWRlc3RyaWFucyc6J1xcdWQ4M2RcXHVkZWI3JyxcbiAgJ25vX3Ntb2tpbmcnOidcXHVkODNkXFx1ZGVhZCcsXG4gICdub24tcG90YWJsZV93YXRlcic6J1xcdWQ4M2RcXHVkZWIxJyxcbiAgJ25vc2UnOidcXHVkODNkXFx1ZGM0MycsXG4gICdub3RlYm9vayc6J1xcdWQ4M2RcXHVkY2QzJyxcbiAgJ25vdGVib29rX3dpdGhfZGVjb3JhdGl2ZV9jb3Zlcic6J1xcdWQ4M2RcXHVkY2Q0JyxcbiAgJ25vdGVzJzonXFx1ZDgzY1xcdWRmYjYnLFxuICAnbnV0X2FuZF9ib2x0JzonXFx1ZDgzZFxcdWRkMjknLFxuICAnbyc6J1xcdTJiNTVcXHVmZTBmJyxcbiAgJ28yJzonXFx1ZDgzY1xcdWRkN2VcXHVmZTBmJyxcbiAgJ29jZWFuJzonXFx1ZDgzY1xcdWRmMGEnLFxuICAnb2N0b3B1cyc6J1xcdWQ4M2RcXHVkYzE5JyxcbiAgJ29kZW4nOidcXHVkODNjXFx1ZGY2MicsXG4gICdvZmZpY2UnOidcXHVkODNjXFx1ZGZlMicsXG4gICdvaWxfZHJ1bSc6J1xcdWQ4M2RcXHVkZWUyJyxcbiAgJ29rJzonXFx1ZDgzY1xcdWRkOTcnLFxuICAnb2tfaGFuZCc6J1xcdWQ4M2RcXHVkYzRjJyxcbiAgJ29rX21hbic6J1xcdWQ4M2RcXHVkZTQ2Jnp3ajtcXHUyNjQyXFx1ZmUwZicsXG4gICdva193b21hbic6J1xcdWQ4M2RcXHVkZTQ2JyxcbiAgJ29sZF9rZXknOidcXHVkODNkXFx1ZGRkZCcsXG4gICdvbGRlcl9tYW4nOidcXHVkODNkXFx1ZGM3NCcsXG4gICdvbGRlcl93b21hbic6J1xcdWQ4M2RcXHVkYzc1JyxcbiAgJ29tJzonXFx1ZDgzZFxcdWRkNDknLFxuICAnb24nOidcXHVkODNkXFx1ZGQxYicsXG4gICdvbmNvbWluZ19hdXRvbW9iaWxlJzonXFx1ZDgzZFxcdWRlOTgnLFxuICAnb25jb21pbmdfYnVzJzonXFx1ZDgzZFxcdWRlOGQnLFxuICAnb25jb21pbmdfcG9saWNlX2Nhcic6J1xcdWQ4M2RcXHVkZTk0JyxcbiAgJ29uY29taW5nX3RheGknOidcXHVkODNkXFx1ZGU5NicsXG4gICdvcGVuX2ZpbGVfZm9sZGVyJzonXFx1ZDgzZFxcdWRjYzInLFxuICAnb3Blbl9oYW5kcyc6J1xcdWQ4M2RcXHVkYzUwJyxcbiAgJ29wZW5fbW91dGgnOidcXHVkODNkXFx1ZGUyZScsXG4gICdvcGVuX3VtYnJlbGxhJzonXFx1MjYwMlxcdWZlMGYnLFxuICAnb3BoaXVjaHVzJzonXFx1MjZjZScsXG4gICdvcmFuZ2VfYm9vayc6J1xcdWQ4M2RcXHVkY2Q5JyxcbiAgJ29ydGhvZG94X2Nyb3NzJzonXFx1MjYyNlxcdWZlMGYnLFxuICAnb3V0Ym94X3RyYXknOidcXHVkODNkXFx1ZGNlNCcsXG4gICdvd2wnOidcXHVkODNlXFx1ZGQ4OScsXG4gICdveCc6J1xcdWQ4M2RcXHVkYzAyJyxcbiAgJ3BhY2thZ2UnOidcXHVkODNkXFx1ZGNlNicsXG4gICdwYWdlX2ZhY2luZ191cCc6J1xcdWQ4M2RcXHVkY2M0JyxcbiAgJ3BhZ2Vfd2l0aF9jdXJsJzonXFx1ZDgzZFxcdWRjYzMnLFxuICAncGFnZXInOidcXHVkODNkXFx1ZGNkZicsXG4gICdwYWludGJydXNoJzonXFx1ZDgzZFxcdWRkOGMnLFxuICAncGFsbV90cmVlJzonXFx1ZDgzY1xcdWRmMzQnLFxuICAncGFuY2FrZXMnOidcXHVkODNlXFx1ZGQ1ZScsXG4gICdwYW5kYV9mYWNlJzonXFx1ZDgzZFxcdWRjM2MnLFxuICAncGFwZXJjbGlwJzonXFx1ZDgzZFxcdWRjY2UnLFxuICAncGFwZXJjbGlwcyc6J1xcdWQ4M2RcXHVkZDg3JyxcbiAgJ3BhcmFzb2xfb25fZ3JvdW5kJzonXFx1MjZmMScsXG4gICdwYXJraW5nJzonXFx1ZDgzY1xcdWRkN2ZcXHVmZTBmJyxcbiAgJ3BhcnRfYWx0ZXJuYXRpb25fbWFyayc6J1xcdTMwM2RcXHVmZTBmJyxcbiAgJ3BhcnRseV9zdW5ueSc6J1xcdTI2YzVcXHVmZTBmJyxcbiAgJ3Bhc3Nlbmdlcl9zaGlwJzonXFx1ZDgzZFxcdWRlZjMnLFxuICAncGFzc3BvcnRfY29udHJvbCc6J1xcdWQ4M2RcXHVkZWMyJyxcbiAgJ3BhdXNlX2J1dHRvbic6J1xcdTIzZjgnLFxuICAncGVhY2Vfc3ltYm9sJzonXFx1MjYyZVxcdWZlMGYnLFxuICAncGVhY2gnOidcXHVkODNjXFx1ZGY1MScsXG4gICdwZWFudXRzJzonXFx1ZDgzZVxcdWRkNWMnLFxuICAncGVhcic6J1xcdWQ4M2NcXHVkZjUwJyxcbiAgJ3Blbic6J1xcdWQ4M2RcXHVkZDhhJyxcbiAgJ3BlbmNpbDInOidcXHUyNzBmXFx1ZmUwZicsXG4gICdwZW5ndWluJzonXFx1ZDgzZFxcdWRjMjcnLFxuICAncGVuc2l2ZSc6J1xcdWQ4M2RcXHVkZTE0JyxcbiAgJ3BlcmZvcm1pbmdfYXJ0cyc6J1xcdWQ4M2NcXHVkZmFkJyxcbiAgJ3BlcnNldmVyZSc6J1xcdWQ4M2RcXHVkZTIzJyxcbiAgJ3BlcnNvbl9mZW5jaW5nJzonXFx1ZDgzZVxcdWRkM2EnLFxuICAncG91dGluZ193b21hbic6J1xcdWQ4M2RcXHVkZTRlJyxcbiAgJ3Bob25lJzonXFx1MjYwZVxcdWZlMGYnLFxuICAncGljayc6J1xcdTI2Y2YnLFxuICAncGlnJzonXFx1ZDgzZFxcdWRjMzcnLFxuICAncGlnMic6J1xcdWQ4M2RcXHVkYzE2JyxcbiAgJ3BpZ19ub3NlJzonXFx1ZDgzZFxcdWRjM2QnLFxuICAncGlsbCc6J1xcdWQ4M2RcXHVkYzhhJyxcbiAgJ3BpbmVhcHBsZSc6J1xcdWQ4M2NcXHVkZjRkJyxcbiAgJ3BpbmdfcG9uZyc6J1xcdWQ4M2NcXHVkZmQzJyxcbiAgJ3Bpc2Nlcyc6J1xcdTI2NTNcXHVmZTBmJyxcbiAgJ3BpenphJzonXFx1ZDgzY1xcdWRmNTUnLFxuICAncGxhY2Vfb2Zfd29yc2hpcCc6J1xcdWQ4M2RcXHVkZWQwJyxcbiAgJ3BsYXRlX3dpdGhfY3V0bGVyeSc6J1xcdWQ4M2NcXHVkZjdkJyxcbiAgJ3BsYXlfb3JfcGF1c2VfYnV0dG9uJzonXFx1MjNlZicsXG4gICdwb2ludF9kb3duJzonXFx1ZDgzZFxcdWRjNDcnLFxuICAncG9pbnRfbGVmdCc6J1xcdWQ4M2RcXHVkYzQ4JyxcbiAgJ3BvaW50X3JpZ2h0JzonXFx1ZDgzZFxcdWRjNDknLFxuICAncG9pbnRfdXAnOidcXHUyNjFkXFx1ZmUwZicsXG4gICdwb2ludF91cF8yJzonXFx1ZDgzZFxcdWRjNDYnLFxuICAncG9saWNlX2Nhcic6J1xcdWQ4M2RcXHVkZTkzJyxcbiAgJ3BvbGljZXdvbWFuJzonXFx1ZDgzZFxcdWRjNmUmendqO1xcdTI2NDBcXHVmZTBmJyxcbiAgJ3Bvb2RsZSc6J1xcdWQ4M2RcXHVkYzI5JyxcbiAgJ3BvcGNvcm4nOidcXHVkODNjXFx1ZGY3ZicsXG4gICdwb3N0X29mZmljZSc6J1xcdWQ4M2NcXHVkZmUzJyxcbiAgJ3Bvc3RhbF9ob3JuJzonXFx1ZDgzZFxcdWRjZWYnLFxuICAncG9zdGJveCc6J1xcdWQ4M2RcXHVkY2VlJyxcbiAgJ3BvdGFibGVfd2F0ZXInOidcXHVkODNkXFx1ZGViMCcsXG4gICdwb3RhdG8nOidcXHVkODNlXFx1ZGQ1NCcsXG4gICdwb3VjaCc6J1xcdWQ4M2RcXHVkYzVkJyxcbiAgJ3BvdWx0cnlfbGVnJzonXFx1ZDgzY1xcdWRmNTcnLFxuICAncG91bmQnOidcXHVkODNkXFx1ZGNiNycsXG4gICdyYWdlJzonXFx1ZDgzZFxcdWRlMjEnLFxuICAncG91dGluZ19jYXQnOidcXHVkODNkXFx1ZGUzZScsXG4gICdwb3V0aW5nX21hbic6J1xcdWQ4M2RcXHVkZTRlJnp3ajtcXHUyNjQyXFx1ZmUwZicsXG4gICdwcmF5JzonXFx1ZDgzZFxcdWRlNGYnLFxuICAncHJheWVyX2JlYWRzJzonXFx1ZDgzZFxcdWRjZmYnLFxuICAncHJlZ25hbnRfd29tYW4nOidcXHVkODNlXFx1ZGQzMCcsXG4gICdwcmV2aW91c190cmFja19idXR0b24nOidcXHUyM2VlJyxcbiAgJ3ByaW5jZSc6J1xcdWQ4M2VcXHVkZDM0JyxcbiAgJ3ByaW5jZXNzJzonXFx1ZDgzZFxcdWRjNzgnLFxuICAncHJpbnRlcic6J1xcdWQ4M2RcXHVkZGE4JyxcbiAgJ3B1cnBsZV9oZWFydCc6J1xcdWQ4M2RcXHVkYzljJyxcbiAgJ3B1cnNlJzonXFx1ZDgzZFxcdWRjNWInLFxuICAncHVzaHBpbic6J1xcdWQ4M2RcXHVkY2NjJyxcbiAgJ3B1dF9saXR0ZXJfaW5faXRzX3BsYWNlJzonXFx1ZDgzZFxcdWRlYWUnLFxuICAncXVlc3Rpb24nOidcXHUyNzUzJyxcbiAgJ3JhYmJpdCc6J1xcdWQ4M2RcXHVkYzMwJyxcbiAgJ3JhYmJpdDInOidcXHVkODNkXFx1ZGMwNycsXG4gICdyYWNlaG9yc2UnOidcXHVkODNkXFx1ZGMwZScsXG4gICdyYWNpbmdfY2FyJzonXFx1ZDgzY1xcdWRmY2UnLFxuICAncmFkaW8nOidcXHVkODNkXFx1ZGNmYicsXG4gICdyYWRpb19idXR0b24nOidcXHVkODNkXFx1ZGQxOCcsXG4gICdyYWRpb2FjdGl2ZSc6J1xcdTI2MjJcXHVmZTBmJyxcbiAgJ3JhaWx3YXlfY2FyJzonXFx1ZDgzZFxcdWRlODMnLFxuICAncmFpbHdheV90cmFjayc6J1xcdWQ4M2RcXHVkZWU0JyxcbiAgJ3JhaW5ib3cnOidcXHVkODNjXFx1ZGYwOCcsXG4gICdyYWluYm93X2ZsYWcnOidcXHVkODNjXFx1ZGZmM1xcdWZlMGYmendqO1xcdWQ4M2NcXHVkZjA4JyxcbiAgJ3JhaXNlZF9iYWNrX29mX2hhbmQnOidcXHVkODNlXFx1ZGQxYScsXG4gICdyYWlzZWRfaGFuZF93aXRoX2ZpbmdlcnNfc3BsYXllZCc6J1xcdWQ4M2RcXHVkZDkwJyxcbiAgJ3JhaXNlZF9oYW5kcyc6J1xcdWQ4M2RcXHVkZTRjJyxcbiAgJ3JhaXNpbmdfaGFuZF93b21hbic6J1xcdWQ4M2RcXHVkZTRiJyxcbiAgJ3JhaXNpbmdfaGFuZF9tYW4nOidcXHVkODNkXFx1ZGU0YiZ6d2o7XFx1MjY0MlxcdWZlMGYnLFxuICAncmFtJzonXFx1ZDgzZFxcdWRjMGYnLFxuICAncmFtZW4nOidcXHVkODNjXFx1ZGY1YycsXG4gICdyYXQnOidcXHVkODNkXFx1ZGMwMCcsXG4gICdyZWNvcmRfYnV0dG9uJzonXFx1MjNmYScsXG4gICdyZWN5Y2xlJzonXFx1MjY3YlxcdWZlMGYnLFxuICAncmVkX2NpcmNsZSc6J1xcdWQ4M2RcXHVkZDM0JyxcbiAgJ3JlZ2lzdGVyZWQnOidcXHUwMGFlXFx1ZmUwZicsXG4gICdyZWxheGVkJzonXFx1MjYzYVxcdWZlMGYnLFxuICAncmVsaWV2ZWQnOidcXHVkODNkXFx1ZGUwYycsXG4gICdyZW1pbmRlcl9yaWJib24nOidcXHVkODNjXFx1ZGY5NycsXG4gICdyZXBlYXQnOidcXHVkODNkXFx1ZGQwMScsXG4gICdyZXBlYXRfb25lJzonXFx1ZDgzZFxcdWRkMDInLFxuICAncmVzY3VlX3dvcmtlcl9oZWxtZXQnOidcXHUyNmQxJyxcbiAgJ3Jlc3Ryb29tJzonXFx1ZDgzZFxcdWRlYmInLFxuICAncmV2b2x2aW5nX2hlYXJ0cyc6J1xcdWQ4M2RcXHVkYzllJyxcbiAgJ3Jld2luZCc6J1xcdTIzZWEnLFxuICAncmhpbm9jZXJvcyc6J1xcdWQ4M2VcXHVkZDhmJyxcbiAgJ3JpYmJvbic6J1xcdWQ4M2NcXHVkZjgwJyxcbiAgJ3JpY2UnOidcXHVkODNjXFx1ZGY1YScsXG4gICdyaWNlX2JhbGwnOidcXHVkODNjXFx1ZGY1OScsXG4gICdyaWNlX2NyYWNrZXInOidcXHVkODNjXFx1ZGY1OCcsXG4gICdyaWNlX3NjZW5lJzonXFx1ZDgzY1xcdWRmOTEnLFxuICAncmlnaHRfYW5nZXJfYnViYmxlJzonXFx1ZDgzZFxcdWRkZWYnLFxuICAncmluZyc6J1xcdWQ4M2RcXHVkYzhkJyxcbiAgJ3JvYm90JzonXFx1ZDgzZVxcdWRkMTYnLFxuICAncm9ja2V0JzonXFx1ZDgzZFxcdWRlODAnLFxuICAncm9mbCc6J1xcdWQ4M2VcXHVkZDIzJyxcbiAgJ3JvbGxfZXllcyc6J1xcdWQ4M2RcXHVkZTQ0JyxcbiAgJ3JvbGxlcl9jb2FzdGVyJzonXFx1ZDgzY1xcdWRmYTInLFxuICAncm9vc3Rlcic6J1xcdWQ4M2RcXHVkYzEzJyxcbiAgJ3Jvc2UnOidcXHVkODNjXFx1ZGYzOScsXG4gICdyb3NldHRlJzonXFx1ZDgzY1xcdWRmZjUnLFxuICAncm90YXRpbmdfbGlnaHQnOidcXHVkODNkXFx1ZGVhOCcsXG4gICdyb3VuZF9wdXNocGluJzonXFx1ZDgzZFxcdWRjY2QnLFxuICAncm93aW5nX21hbic6J1xcdWQ4M2RcXHVkZWEzJyxcbiAgJ3Jvd2luZ193b21hbic6J1xcdWQ4M2RcXHVkZWEzJnp3ajtcXHUyNjQwXFx1ZmUwZicsXG4gICdydWdieV9mb290YmFsbCc6J1xcdWQ4M2NcXHVkZmM5JyxcbiAgJ3J1bm5pbmdfbWFuJzonXFx1ZDgzY1xcdWRmYzMnLFxuICAncnVubmluZ19zaGlydF93aXRoX3Nhc2gnOidcXHVkODNjXFx1ZGZiZCcsXG4gICdydW5uaW5nX3dvbWFuJzonXFx1ZDgzY1xcdWRmYzMmendqO1xcdTI2NDBcXHVmZTBmJyxcbiAgJ3NhJzonXFx1ZDgzY1xcdWRlMDJcXHVmZTBmJyxcbiAgJ3NhZ2l0dGFyaXVzJzonXFx1MjY1MFxcdWZlMGYnLFxuICAnc2FrZSc6J1xcdWQ4M2NcXHVkZjc2JyxcbiAgJ3NhbmRhbCc6J1xcdWQ4M2RcXHVkYzYxJyxcbiAgJ3NhbnRhJzonXFx1ZDgzY1xcdWRmODUnLFxuICAnc2F0ZWxsaXRlJzonXFx1ZDgzZFxcdWRjZTEnLFxuICAnc2F4b3Bob25lJzonXFx1ZDgzY1xcdWRmYjcnLFxuICAnc2Nob29sJzonXFx1ZDgzY1xcdWRmZWInLFxuICAnc2Nob29sX3NhdGNoZWwnOidcXHVkODNjXFx1ZGY5MicsXG4gICdzY2lzc29ycyc6J1xcdTI3MDJcXHVmZTBmJyxcbiAgJ3Njb3JwaW9uJzonXFx1ZDgzZVxcdWRkODInLFxuICAnc2NvcnBpdXMnOidcXHUyNjRmXFx1ZmUwZicsXG4gICdzY3JlYW0nOidcXHVkODNkXFx1ZGUzMScsXG4gICdzY3JlYW1fY2F0JzonXFx1ZDgzZFxcdWRlNDAnLFxuICAnc2Nyb2xsJzonXFx1ZDgzZFxcdWRjZGMnLFxuICAnc2VhdCc6J1xcdWQ4M2RcXHVkY2JhJyxcbiAgJ3NlY3JldCc6J1xcdTMyOTlcXHVmZTBmJyxcbiAgJ3NlZV9ub19ldmlsJzonXFx1ZDgzZFxcdWRlNDgnLFxuICAnc2VlZGxpbmcnOidcXHVkODNjXFx1ZGYzMScsXG4gICdzZWxmaWUnOidcXHVkODNlXFx1ZGQzMycsXG4gICdzaGFsbG93X3Bhbl9vZl9mb29kJzonXFx1ZDgzZVxcdWRkNTgnLFxuICAnc2hhbXJvY2snOidcXHUyNjE4XFx1ZmUwZicsXG4gICdzaGFyayc6J1xcdWQ4M2VcXHVkZDg4JyxcbiAgJ3NoYXZlZF9pY2UnOidcXHVkODNjXFx1ZGY2NycsXG4gICdzaGVlcCc6J1xcdWQ4M2RcXHVkYzExJyxcbiAgJ3NoZWxsJzonXFx1ZDgzZFxcdWRjMWEnLFxuICAnc2hpZWxkJzonXFx1ZDgzZFxcdWRlZTEnLFxuICAnc2hpbnRvX3NocmluZSc6J1xcdTI2ZTknLFxuICAnc2hpcCc6J1xcdWQ4M2RcXHVkZWEyJyxcbiAgJ3NoaXJ0JzonXFx1ZDgzZFxcdWRjNTUnLFxuICAnc2hvcHBpbmcnOidcXHVkODNkXFx1ZGVjZCcsXG4gICdzaG9wcGluZ19jYXJ0JzonXFx1ZDgzZFxcdWRlZDInLFxuICAnc2hvd2VyJzonXFx1ZDgzZFxcdWRlYmYnLFxuICAnc2hyaW1wJzonXFx1ZDgzZVxcdWRkOTAnLFxuICAnc2lnbmFsX3N0cmVuZ3RoJzonXFx1ZDgzZFxcdWRjZjYnLFxuICAnc2l4X3BvaW50ZWRfc3Rhcic6J1xcdWQ4M2RcXHVkZDJmJyxcbiAgJ3NraSc6J1xcdWQ4M2NcXHVkZmJmJyxcbiAgJ3NraWVyJzonXFx1MjZmNycsXG4gICdza3VsbCc6J1xcdWQ4M2RcXHVkYzgwJyxcbiAgJ3NrdWxsX2FuZF9jcm9zc2JvbmVzJzonXFx1MjYyMFxcdWZlMGYnLFxuICAnc2xlZXBpbmcnOidcXHVkODNkXFx1ZGUzNCcsXG4gICdzbGVlcGluZ19iZWQnOidcXHVkODNkXFx1ZGVjYycsXG4gICdzbGVlcHknOidcXHVkODNkXFx1ZGUyYScsXG4gICdzbGlnaHRseV9mcm93bmluZ19mYWNlJzonXFx1ZDgzZFxcdWRlNDEnLFxuICAnc2xpZ2h0bHlfc21pbGluZ19mYWNlJzonXFx1ZDgzZFxcdWRlNDInLFxuICAnc2xvdF9tYWNoaW5lJzonXFx1ZDgzY1xcdWRmYjAnLFxuICAnc21hbGxfYWlycGxhbmUnOidcXHVkODNkXFx1ZGVlOScsXG4gICdzbWFsbF9ibHVlX2RpYW1vbmQnOidcXHVkODNkXFx1ZGQzOScsXG4gICdzbWFsbF9vcmFuZ2VfZGlhbW9uZCc6J1xcdWQ4M2RcXHVkZDM4JyxcbiAgJ3NtYWxsX3JlZF90cmlhbmdsZSc6J1xcdWQ4M2RcXHVkZDNhJyxcbiAgJ3NtYWxsX3JlZF90cmlhbmdsZV9kb3duJzonXFx1ZDgzZFxcdWRkM2InLFxuICAnc21pbGUnOidcXHVkODNkXFx1ZGUwNCcsXG4gICdzbWlsZV9jYXQnOidcXHVkODNkXFx1ZGUzOCcsXG4gICdzbWlsZXknOidcXHVkODNkXFx1ZGUwMycsXG4gICdzbWlsZXlfY2F0JzonXFx1ZDgzZFxcdWRlM2EnLFxuICAnc21pbGluZ19pbXAnOidcXHVkODNkXFx1ZGUwOCcsXG4gICdzbWlyayc6J1xcdWQ4M2RcXHVkZTBmJyxcbiAgJ3NtaXJrX2NhdCc6J1xcdWQ4M2RcXHVkZTNjJyxcbiAgJ3Ntb2tpbmcnOidcXHVkODNkXFx1ZGVhYycsXG4gICdzbmFpbCc6J1xcdWQ4M2RcXHVkYzBjJyxcbiAgJ3NuYWtlJzonXFx1ZDgzZFxcdWRjMGQnLFxuICAnc25lZXppbmdfZmFjZSc6J1xcdWQ4M2VcXHVkZDI3JyxcbiAgJ3Nub3dib2FyZGVyJzonXFx1ZDgzY1xcdWRmYzInLFxuICAnc25vd2ZsYWtlJzonXFx1Mjc0NFxcdWZlMGYnLFxuICAnc25vd21hbic6J1xcdTI2YzRcXHVmZTBmJyxcbiAgJ3Nub3dtYW5fd2l0aF9zbm93JzonXFx1MjYwM1xcdWZlMGYnLFxuICAnc29iJzonXFx1ZDgzZFxcdWRlMmQnLFxuICAnc29jY2VyJzonXFx1MjZiZFxcdWZlMGYnLFxuICAnc29vbic6J1xcdWQ4M2RcXHVkZDFjJyxcbiAgJ3Nvcyc6J1xcdWQ4M2NcXHVkZDk4JyxcbiAgJ3NvdW5kJzonXFx1ZDgzZFxcdWRkMDknLFxuICAnc3BhY2VfaW52YWRlcic6J1xcdWQ4M2RcXHVkYzdlJyxcbiAgJ3NwYWRlcyc6J1xcdTI2NjBcXHVmZTBmJyxcbiAgJ3NwYWdoZXR0aSc6J1xcdWQ4M2NcXHVkZjVkJyxcbiAgJ3NwYXJrbGUnOidcXHUyNzQ3XFx1ZmUwZicsXG4gICdzcGFya2xlcic6J1xcdWQ4M2NcXHVkZjg3JyxcbiAgJ3NwYXJrbGVzJzonXFx1MjcyOCcsXG4gICdzcGFya2xpbmdfaGVhcnQnOidcXHVkODNkXFx1ZGM5NicsXG4gICdzcGVha19ub19ldmlsJzonXFx1ZDgzZFxcdWRlNGEnLFxuICAnc3BlYWtlcic6J1xcdWQ4M2RcXHVkZDA4JyxcbiAgJ3NwZWFraW5nX2hlYWQnOidcXHVkODNkXFx1ZGRlMycsXG4gICdzcGVlY2hfYmFsbG9vbic6J1xcdWQ4M2RcXHVkY2FjJyxcbiAgJ3NwZWVkYm9hdCc6J1xcdWQ4M2RcXHVkZWE0JyxcbiAgJ3NwaWRlcic6J1xcdWQ4M2RcXHVkZDc3JyxcbiAgJ3NwaWRlcl93ZWInOidcXHVkODNkXFx1ZGQ3OCcsXG4gICdzcGlyYWxfY2FsZW5kYXInOidcXHVkODNkXFx1ZGRkMycsXG4gICdzcGlyYWxfbm90ZXBhZCc6J1xcdWQ4M2RcXHVkZGQyJyxcbiAgJ3Nwb29uJzonXFx1ZDgzZVxcdWRkNDQnLFxuICAnc3F1aWQnOidcXHVkODNlXFx1ZGQ5MScsXG4gICdzdGFkaXVtJzonXFx1ZDgzY1xcdWRmZGYnLFxuICAnc3Rhcic6J1xcdTJiNTBcXHVmZTBmJyxcbiAgJ3N0YXIyJzonXFx1ZDgzY1xcdWRmMWYnLFxuICAnc3Rhcl9hbmRfY3Jlc2NlbnQnOidcXHUyNjJhXFx1ZmUwZicsXG4gICdzdGFyX29mX2RhdmlkJzonXFx1MjcyMVxcdWZlMGYnLFxuICAnc3RhcnMnOidcXHVkODNjXFx1ZGYyMCcsXG4gICdzdGF0aW9uJzonXFx1ZDgzZFxcdWRlODknLFxuICAnc3RhdHVlX29mX2xpYmVydHknOidcXHVkODNkXFx1ZGRmZCcsXG4gICdzdGVhbV9sb2NvbW90aXZlJzonXFx1ZDgzZFxcdWRlODInLFxuICAnc3Rldyc6J1xcdWQ4M2NcXHVkZjcyJyxcbiAgJ3N0b3BfYnV0dG9uJzonXFx1MjNmOScsXG4gICdzdG9wX3NpZ24nOidcXHVkODNkXFx1ZGVkMScsXG4gICdzdG9wd2F0Y2gnOidcXHUyM2YxJyxcbiAgJ3N0cmFpZ2h0X3J1bGVyJzonXFx1ZDgzZFxcdWRjY2YnLFxuICAnc3RyYXdiZXJyeSc6J1xcdWQ4M2NcXHVkZjUzJyxcbiAgJ3N0dWNrX291dF90b25ndWUnOidcXHVkODNkXFx1ZGUxYicsXG4gICdzdHVja19vdXRfdG9uZ3VlX2Nsb3NlZF9leWVzJzonXFx1ZDgzZFxcdWRlMWQnLFxuICAnc3R1Y2tfb3V0X3Rvbmd1ZV93aW5raW5nX2V5ZSc6J1xcdWQ4M2RcXHVkZTFjJyxcbiAgJ3N0dWRpb19taWNyb3Bob25lJzonXFx1ZDgzY1xcdWRmOTknLFxuICAnc3R1ZmZlZF9mbGF0YnJlYWQnOidcXHVkODNlXFx1ZGQ1OScsXG4gICdzdW5fYmVoaW5kX2xhcmdlX2Nsb3VkJzonXFx1ZDgzY1xcdWRmMjUnLFxuICAnc3VuX2JlaGluZF9yYWluX2Nsb3VkJzonXFx1ZDgzY1xcdWRmMjYnLFxuICAnc3VuX2JlaGluZF9zbWFsbF9jbG91ZCc6J1xcdWQ4M2NcXHVkZjI0JyxcbiAgJ3N1bl93aXRoX2ZhY2UnOidcXHVkODNjXFx1ZGYxZScsXG4gICdzdW5mbG93ZXInOidcXHVkODNjXFx1ZGYzYicsXG4gICdzdW5nbGFzc2VzJzonXFx1ZDgzZFxcdWRlMGUnLFxuICAnc3VubnknOidcXHUyNjAwXFx1ZmUwZicsXG4gICdzdW5yaXNlJzonXFx1ZDgzY1xcdWRmMDUnLFxuICAnc3VucmlzZV9vdmVyX21vdW50YWlucyc6J1xcdWQ4M2NcXHVkZjA0JyxcbiAgJ3N1cmZpbmdfbWFuJzonXFx1ZDgzY1xcdWRmYzQnLFxuICAnc3VyZmluZ193b21hbic6J1xcdWQ4M2NcXHVkZmM0Jnp3ajtcXHUyNjQwXFx1ZmUwZicsXG4gICdzdXNoaSc6J1xcdWQ4M2NcXHVkZjYzJyxcbiAgJ3N1c3BlbnNpb25fcmFpbHdheSc6J1xcdWQ4M2RcXHVkZTlmJyxcbiAgJ3N3ZWF0JzonXFx1ZDgzZFxcdWRlMTMnLFxuICAnc3dlYXRfZHJvcHMnOidcXHVkODNkXFx1ZGNhNicsXG4gICdzd2VhdF9zbWlsZSc6J1xcdWQ4M2RcXHVkZTA1JyxcbiAgJ3N3ZWV0X3BvdGF0byc6J1xcdWQ4M2NcXHVkZjYwJyxcbiAgJ3N3aW1taW5nX21hbic6J1xcdWQ4M2NcXHVkZmNhJyxcbiAgJ3N3aW1taW5nX3dvbWFuJzonXFx1ZDgzY1xcdWRmY2EmendqO1xcdTI2NDBcXHVmZTBmJyxcbiAgJ3N5bWJvbHMnOidcXHVkODNkXFx1ZGQyMycsXG4gICdzeW5hZ29ndWUnOidcXHVkODNkXFx1ZGQ0ZCcsXG4gICdzeXJpbmdlJzonXFx1ZDgzZFxcdWRjODknLFxuICAndGFjbyc6J1xcdWQ4M2NcXHVkZjJlJyxcbiAgJ3RhZGEnOidcXHVkODNjXFx1ZGY4OScsXG4gICd0YW5hYmF0YV90cmVlJzonXFx1ZDgzY1xcdWRmOGInLFxuICAndGF1cnVzJzonXFx1MjY0OVxcdWZlMGYnLFxuICAndGF4aSc6J1xcdWQ4M2RcXHVkZTk1JyxcbiAgJ3RlYSc6J1xcdWQ4M2NcXHVkZjc1JyxcbiAgJ3RlbGVwaG9uZV9yZWNlaXZlcic6J1xcdWQ4M2RcXHVkY2RlJyxcbiAgJ3RlbGVzY29wZSc6J1xcdWQ4M2RcXHVkZDJkJyxcbiAgJ3Rlbm5pcyc6J1xcdWQ4M2NcXHVkZmJlJyxcbiAgJ3RlbnQnOidcXHUyNmZhXFx1ZmUwZicsXG4gICd0aGVybW9tZXRlcic6J1xcdWQ4M2NcXHVkZjIxJyxcbiAgJ3RoaW5raW5nJzonXFx1ZDgzZVxcdWRkMTQnLFxuICAndGhvdWdodF9iYWxsb29uJzonXFx1ZDgzZFxcdWRjYWQnLFxuICAndGlja2V0JzonXFx1ZDgzY1xcdWRmYWInLFxuICAndGlja2V0cyc6J1xcdWQ4M2NcXHVkZjlmJyxcbiAgJ3RpZ2VyJzonXFx1ZDgzZFxcdWRjMmYnLFxuICAndGlnZXIyJzonXFx1ZDgzZFxcdWRjMDUnLFxuICAndGltZXJfY2xvY2snOidcXHUyM2YyJyxcbiAgJ3RpcHBpbmdfaGFuZF9tYW4nOidcXHVkODNkXFx1ZGM4MSZ6d2o7XFx1MjY0MlxcdWZlMGYnLFxuICAndGlyZWRfZmFjZSc6J1xcdWQ4M2RcXHVkZTJiJyxcbiAgJ3RtJzonXFx1MjEyMlxcdWZlMGYnLFxuICAndG9pbGV0JzonXFx1ZDgzZFxcdWRlYmQnLFxuICAndG9reW9fdG93ZXInOidcXHVkODNkXFx1ZGRmYycsXG4gICd0b21hdG8nOidcXHVkODNjXFx1ZGY0NScsXG4gICd0b25ndWUnOidcXHVkODNkXFx1ZGM0NScsXG4gICd0b3AnOidcXHVkODNkXFx1ZGQxZCcsXG4gICd0b3BoYXQnOidcXHVkODNjXFx1ZGZhOScsXG4gICd0b3JuYWRvJzonXFx1ZDgzY1xcdWRmMmEnLFxuICAndHJhY2tiYWxsJzonXFx1ZDgzZFxcdWRkYjInLFxuICAndHJhY3Rvcic6J1xcdWQ4M2RcXHVkZTljJyxcbiAgJ3RyYWZmaWNfbGlnaHQnOidcXHVkODNkXFx1ZGVhNScsXG4gICd0cmFpbic6J1xcdWQ4M2RcXHVkZThiJyxcbiAgJ3RyYWluMic6J1xcdWQ4M2RcXHVkZTg2JyxcbiAgJ3RyYW0nOidcXHVkODNkXFx1ZGU4YScsXG4gICd0cmlhbmd1bGFyX2ZsYWdfb25fcG9zdCc6J1xcdWQ4M2RcXHVkZWE5JyxcbiAgJ3RyaWFuZ3VsYXJfcnVsZXInOidcXHVkODNkXFx1ZGNkMCcsXG4gICd0cmlkZW50JzonXFx1ZDgzZFxcdWRkMzEnLFxuICAndHJpdW1waCc6J1xcdWQ4M2RcXHVkZTI0JyxcbiAgJ3Ryb2xsZXlidXMnOidcXHVkODNkXFx1ZGU4ZScsXG4gICd0cm9waHknOidcXHVkODNjXFx1ZGZjNicsXG4gICd0cm9waWNhbF9kcmluayc6J1xcdWQ4M2NcXHVkZjc5JyxcbiAgJ3Ryb3BpY2FsX2Zpc2gnOidcXHVkODNkXFx1ZGMyMCcsXG4gICd0cnVjayc6J1xcdWQ4M2RcXHVkZTlhJyxcbiAgJ3RydW1wZXQnOidcXHVkODNjXFx1ZGZiYScsXG4gICd0dWxpcCc6J1xcdWQ4M2NcXHVkZjM3JyxcbiAgJ3R1bWJsZXJfZ2xhc3MnOidcXHVkODNlXFx1ZGQ0MycsXG4gICd0dXJrZXknOidcXHVkODNlXFx1ZGQ4MycsXG4gICd0dXJ0bGUnOidcXHVkODNkXFx1ZGMyMicsXG4gICd0dic6J1xcdWQ4M2RcXHVkY2ZhJyxcbiAgJ3R3aXN0ZWRfcmlnaHR3YXJkc19hcnJvd3MnOidcXHVkODNkXFx1ZGQwMCcsXG4gICd0d29faGVhcnRzJzonXFx1ZDgzZFxcdWRjOTUnLFxuICAndHdvX21lbl9ob2xkaW5nX2hhbmRzJzonXFx1ZDgzZFxcdWRjNmMnLFxuICAndHdvX3dvbWVuX2hvbGRpbmdfaGFuZHMnOidcXHVkODNkXFx1ZGM2ZCcsXG4gICd1NTI3Mic6J1xcdWQ4M2NcXHVkZTM5JyxcbiAgJ3U1NDA4JzonXFx1ZDgzY1xcdWRlMzQnLFxuICAndTU1YjYnOidcXHVkODNjXFx1ZGUzYScsXG4gICd1NjMwNyc6J1xcdWQ4M2NcXHVkZTJmXFx1ZmUwZicsXG4gICd1NjcwOCc6J1xcdWQ4M2NcXHVkZTM3XFx1ZmUwZicsXG4gICd1NjcwOSc6J1xcdWQ4M2NcXHVkZTM2JyxcbiAgJ3U2ZTgwJzonXFx1ZDgzY1xcdWRlMzUnLFxuICAndTcxMjEnOidcXHVkODNjXFx1ZGUxYVxcdWZlMGYnLFxuICAndTc1MzMnOidcXHVkODNjXFx1ZGUzOCcsXG4gICd1Nzk4MSc6J1xcdWQ4M2NcXHVkZTMyJyxcbiAgJ3U3YTdhJzonXFx1ZDgzY1xcdWRlMzMnLFxuICAndW1icmVsbGEnOidcXHUyNjE0XFx1ZmUwZicsXG4gICd1bmFtdXNlZCc6J1xcdWQ4M2RcXHVkZTEyJyxcbiAgJ3VuZGVyYWdlJzonXFx1ZDgzZFxcdWRkMWUnLFxuICAndW5pY29ybic6J1xcdWQ4M2VcXHVkZDg0JyxcbiAgJ3VubG9jayc6J1xcdWQ4M2RcXHVkZDEzJyxcbiAgJ3VwJzonXFx1ZDgzY1xcdWRkOTknLFxuICAndXBzaWRlX2Rvd25fZmFjZSc6J1xcdWQ4M2RcXHVkZTQzJyxcbiAgJ3YnOidcXHUyNzBjXFx1ZmUwZicsXG4gICd2ZXJ0aWNhbF90cmFmZmljX2xpZ2h0JzonXFx1ZDgzZFxcdWRlYTYnLFxuICAndmhzJzonXFx1ZDgzZFxcdWRjZmMnLFxuICAndmlicmF0aW9uX21vZGUnOidcXHVkODNkXFx1ZGNmMycsXG4gICd2aWRlb19jYW1lcmEnOidcXHVkODNkXFx1ZGNmOScsXG4gICd2aWRlb19nYW1lJzonXFx1ZDgzY1xcdWRmYWUnLFxuICAndmlvbGluJzonXFx1ZDgzY1xcdWRmYmInLFxuICAndmlyZ28nOidcXHUyNjRkXFx1ZmUwZicsXG4gICd2b2xjYW5vJzonXFx1ZDgzY1xcdWRmMGInLFxuICAndm9sbGV5YmFsbCc6J1xcdWQ4M2NcXHVkZmQwJyxcbiAgJ3ZzJzonXFx1ZDgzY1xcdWRkOWEnLFxuICAndnVsY2FuX3NhbHV0ZSc6J1xcdWQ4M2RcXHVkZDk2JyxcbiAgJ3dhbGtpbmdfbWFuJzonXFx1ZDgzZFxcdWRlYjYnLFxuICAnd2Fsa2luZ193b21hbic6J1xcdWQ4M2RcXHVkZWI2Jnp3ajtcXHUyNjQwXFx1ZmUwZicsXG4gICd3YW5pbmdfY3Jlc2NlbnRfbW9vbic6J1xcdWQ4M2NcXHVkZjE4JyxcbiAgJ3dhbmluZ19naWJib3VzX21vb24nOidcXHVkODNjXFx1ZGYxNicsXG4gICd3YXJuaW5nJzonXFx1MjZhMFxcdWZlMGYnLFxuICAnd2FzdGViYXNrZXQnOidcXHVkODNkXFx1ZGRkMScsXG4gICd3YXRjaCc6J1xcdTIzMWFcXHVmZTBmJyxcbiAgJ3dhdGVyX2J1ZmZhbG8nOidcXHVkODNkXFx1ZGMwMycsXG4gICd3YXRlcm1lbG9uJzonXFx1ZDgzY1xcdWRmNDknLFxuICAnd2F2ZSc6J1xcdWQ4M2RcXHVkYzRiJyxcbiAgJ3dhdnlfZGFzaCc6J1xcdTMwMzBcXHVmZTBmJyxcbiAgJ3dheGluZ19jcmVzY2VudF9tb29uJzonXFx1ZDgzY1xcdWRmMTInLFxuICAnd2MnOidcXHVkODNkXFx1ZGViZScsXG4gICd3ZWFyeSc6J1xcdWQ4M2RcXHVkZTI5JyxcbiAgJ3dlZGRpbmcnOidcXHVkODNkXFx1ZGM5MicsXG4gICd3ZWlnaHRfbGlmdGluZ19tYW4nOidcXHVkODNjXFx1ZGZjYlxcdWZlMGYnLFxuICAnd2VpZ2h0X2xpZnRpbmdfd29tYW4nOidcXHVkODNjXFx1ZGZjYlxcdWZlMGYmendqO1xcdTI2NDBcXHVmZTBmJyxcbiAgJ3doYWxlJzonXFx1ZDgzZFxcdWRjMzMnLFxuICAnd2hhbGUyJzonXFx1ZDgzZFxcdWRjMGInLFxuICAnd2hlZWxfb2ZfZGhhcm1hJzonXFx1MjYzOFxcdWZlMGYnLFxuICAnd2hlZWxjaGFpcic6J1xcdTI2N2ZcXHVmZTBmJyxcbiAgJ3doaXRlX2NoZWNrX21hcmsnOidcXHUyNzA1JyxcbiAgJ3doaXRlX2NpcmNsZSc6J1xcdTI2YWFcXHVmZTBmJyxcbiAgJ3doaXRlX2ZsYWcnOidcXHVkODNjXFx1ZGZmM1xcdWZlMGYnLFxuICAnd2hpdGVfZmxvd2VyJzonXFx1ZDgzZFxcdWRjYWUnLFxuICAnd2hpdGVfbGFyZ2Vfc3F1YXJlJzonXFx1MmIxY1xcdWZlMGYnLFxuICAnd2hpdGVfbWVkaXVtX3NtYWxsX3NxdWFyZSc6J1xcdTI1ZmRcXHVmZTBmJyxcbiAgJ3doaXRlX21lZGl1bV9zcXVhcmUnOidcXHUyNWZiXFx1ZmUwZicsXG4gICd3aGl0ZV9zbWFsbF9zcXVhcmUnOidcXHUyNWFiXFx1ZmUwZicsXG4gICd3aGl0ZV9zcXVhcmVfYnV0dG9uJzonXFx1ZDgzZFxcdWRkMzMnLFxuICAnd2lsdGVkX2Zsb3dlcic6J1xcdWQ4M2VcXHVkZDQwJyxcbiAgJ3dpbmRfY2hpbWUnOidcXHVkODNjXFx1ZGY5MCcsXG4gICd3aW5kX2ZhY2UnOidcXHVkODNjXFx1ZGYyYycsXG4gICd3aW5lX2dsYXNzJzonXFx1ZDgzY1xcdWRmNzcnLFxuICAnd2luayc6J1xcdWQ4M2RcXHVkZTA5JyxcbiAgJ3dvbGYnOidcXHVkODNkXFx1ZGMzYScsXG4gICd3b21hbic6J1xcdWQ4M2RcXHVkYzY5JyxcbiAgJ3dvbWFuX2FydGlzdCc6J1xcdWQ4M2RcXHVkYzY5Jnp3ajtcXHVkODNjXFx1ZGZhOCcsXG4gICd3b21hbl9hc3Ryb25hdXQnOidcXHVkODNkXFx1ZGM2OSZ6d2o7XFx1ZDgzZFxcdWRlODAnLFxuICAnd29tYW5fY2FydHdoZWVsaW5nJzonXFx1ZDgzZVxcdWRkMzgmendqO1xcdTI2NDBcXHVmZTBmJyxcbiAgJ3dvbWFuX2Nvb2snOidcXHVkODNkXFx1ZGM2OSZ6d2o7XFx1ZDgzY1xcdWRmNzMnLFxuICAnd29tYW5fZmFjZXBhbG1pbmcnOidcXHVkODNlXFx1ZGQyNiZ6d2o7XFx1MjY0MFxcdWZlMGYnLFxuICAnd29tYW5fZmFjdG9yeV93b3JrZXInOidcXHVkODNkXFx1ZGM2OSZ6d2o7XFx1ZDgzY1xcdWRmZWQnLFxuICAnd29tYW5fZmFybWVyJzonXFx1ZDgzZFxcdWRjNjkmendqO1xcdWQ4M2NcXHVkZjNlJyxcbiAgJ3dvbWFuX2ZpcmVmaWdodGVyJzonXFx1ZDgzZFxcdWRjNjkmendqO1xcdWQ4M2RcXHVkZTkyJyxcbiAgJ3dvbWFuX2hlYWx0aF93b3JrZXInOidcXHVkODNkXFx1ZGM2OSZ6d2o7XFx1MjY5NVxcdWZlMGYnLFxuICAnd29tYW5fanVkZ2UnOidcXHVkODNkXFx1ZGM2OSZ6d2o7XFx1MjY5NlxcdWZlMGYnLFxuICAnd29tYW5fanVnZ2xpbmcnOidcXHVkODNlXFx1ZGQzOSZ6d2o7XFx1MjY0MFxcdWZlMGYnLFxuICAnd29tYW5fbWVjaGFuaWMnOidcXHVkODNkXFx1ZGM2OSZ6d2o7XFx1ZDgzZFxcdWRkMjcnLFxuICAnd29tYW5fb2ZmaWNlX3dvcmtlcic6J1xcdWQ4M2RcXHVkYzY5Jnp3ajtcXHVkODNkXFx1ZGNiYycsXG4gICd3b21hbl9waWxvdCc6J1xcdWQ4M2RcXHVkYzY5Jnp3ajtcXHUyNzA4XFx1ZmUwZicsXG4gICd3b21hbl9wbGF5aW5nX2hhbmRiYWxsJzonXFx1ZDgzZVxcdWRkM2UmendqO1xcdTI2NDBcXHVmZTBmJyxcbiAgJ3dvbWFuX3BsYXlpbmdfd2F0ZXJfcG9sbyc6J1xcdWQ4M2VcXHVkZDNkJnp3ajtcXHUyNjQwXFx1ZmUwZicsXG4gICd3b21hbl9zY2llbnRpc3QnOidcXHVkODNkXFx1ZGM2OSZ6d2o7XFx1ZDgzZFxcdWRkMmMnLFxuICAnd29tYW5fc2hydWdnaW5nJzonXFx1ZDgzZVxcdWRkMzcmendqO1xcdTI2NDBcXHVmZTBmJyxcbiAgJ3dvbWFuX3Npbmdlcic6J1xcdWQ4M2RcXHVkYzY5Jnp3ajtcXHVkODNjXFx1ZGZhNCcsXG4gICd3b21hbl9zdHVkZW50JzonXFx1ZDgzZFxcdWRjNjkmendqO1xcdWQ4M2NcXHVkZjkzJyxcbiAgJ3dvbWFuX3RlYWNoZXInOidcXHVkODNkXFx1ZGM2OSZ6d2o7XFx1ZDgzY1xcdWRmZWInLFxuICAnd29tYW5fdGVjaG5vbG9naXN0JzonXFx1ZDgzZFxcdWRjNjkmendqO1xcdWQ4M2RcXHVkY2JiJyxcbiAgJ3dvbWFuX3dpdGhfdHVyYmFuJzonXFx1ZDgzZFxcdWRjNzMmendqO1xcdTI2NDBcXHVmZTBmJyxcbiAgJ3dvbWFuc19jbG90aGVzJzonXFx1ZDgzZFxcdWRjNWEnLFxuICAnd29tYW5zX2hhdCc6J1xcdWQ4M2RcXHVkYzUyJyxcbiAgJ3dvbWVuX3dyZXN0bGluZyc6J1xcdWQ4M2VcXHVkZDNjJnp3ajtcXHUyNjQwXFx1ZmUwZicsXG4gICd3b21lbnMnOidcXHVkODNkXFx1ZGViYScsXG4gICd3b3JsZF9tYXAnOidcXHVkODNkXFx1ZGRmYScsXG4gICd3b3JyaWVkJzonXFx1ZDgzZFxcdWRlMWYnLFxuICAnd3JlbmNoJzonXFx1ZDgzZFxcdWRkMjcnLFxuICAnd3JpdGluZ19oYW5kJzonXFx1MjcwZFxcdWZlMGYnLFxuICAneCc6J1xcdTI3NGMnLFxuICAneWVsbG93X2hlYXJ0JzonXFx1ZDgzZFxcdWRjOWInLFxuICAneWVuJzonXFx1ZDgzZFxcdWRjYjQnLFxuICAneWluX3lhbmcnOidcXHUyNjJmXFx1ZmUwZicsXG4gICd5dW0nOidcXHVkODNkXFx1ZGUwYicsXG4gICd6YXAnOidcXHUyNmExXFx1ZmUwZicsXG4gICd6aXBwZXJfbW91dGhfZmFjZSc6J1xcdWQ4M2VcXHVkZDEwJyxcbiAgJ3p6eic6J1xcdWQ4M2RcXHVkY2E0JyxcblxuICAvKiBzcGVjaWFsIGVtb2ppcyA6UCAqL1xuICAnb2N0b2NhdCc6ICAnPGltZyB3aWR0aD1cIjIwXCIgaGVpZ2h0PVwiMjBcIiBhbGlnbj1cImFic21pZGRsZVwiIHNyYz1cImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBRUFBQUFCQUNBWUFBQUNxYVhIZUFBQU93VWxFUVZSNDJ1VmJDVnlPNlJiUG1uMHN3OWdaUzBhWk80eTVHVEVVRTJPYnhqWmpyYkhFSlZ5M3NXUzVwa2FXeGpMRWtDVkRTYlNnRkxkRVNhV1NMSVZVU0lpNGt2YjlmODk1dmkvemJiUit5WjMzOS90Ym51OTluL2VjLzNPZTg1eHpudWZWMENqREJhQWR3WnF3bnpDSjBGWGpIVjcwL2k4SjVvUURoQ0ZWOGNKZHExYXR3cXhacytEczdJejQrSGhxd2dYQ0xFTE5LbEs2RzJFajRlNmxTNWV3WmNzV3pKZ3hBK2ZPbldOWkZxdnp4VDF2M2JvRi9xY3NCZzBhaFAzNzk2T3dzSkFGV0tZdUlxamZQb1M5Y1hGeFdMNThPYnAwNlNJbmg1YVdGci8vampvSldMbHUzVG9sQW9yUnVYTm43Tnk1azRXNFNwZ2o4MXhyZ2o1aExtRUQ0UkRobE5SeWdnbEJoQURDU2FrcFd4Rk1DSG9FVFVKVHdyWUhEeDdBMU5UMGplOW5QSHo0a04vZlhsMEVlSTBhTmVxdEFqQjY5KzROUHo4L0ZzU2RsWHZ5NUFuOC9mMWhaMmNIQ3dzTEdCc2JZL1RvMGNKeTlQVDBNR0RBQUF3ZVBCaEdSa2JDbE5lc1dZT0RCdzhpT0RnWU9UazUzTS9kOWV2WG8yN2R1aVcrKzhpUkkzei9aSFVSRU5PalI0OFNoU2pHdUhIamhISjE2dFFwOVRPS2FOV3FsWktwdncxTUhsdVFPcFN2azVlWGg1WXRXNVpibWFyQXZIbnptSUJkNmlDZ1huWjJOcG8xYTFhdENXQWZ3WTVTSFFUVUtDb3FRb2NPSGFvMUFlYm1IQkpnaTdwOFFCRFA2ZXBNd0tGRHZNREFXRjBFTExTMXRhM1dCTnk5ZTVjSk1GSVhBZHZ0N2Uyck5RSERodzluQXY1RCtLS3lsVjl5OCtiTkNpMXBWWVdaTTJjeUNmYVZUY0Rkc3F6SDd4cEJRUnhjd3F5eWxMZGk1L0srS00vUTBkRmhBcUlyaTRCbjFUMEFVZ1ZwZG1oWVVlVkhuRDU5K3IxVG5qRjI3RmdtNEhoRkNUaG9ZbUx5WGhMUW9FR0Q0bVJLc3lJRTNPclpzK2Q3U1FDREN5WmNOU3F2OGsxZXZYb0ZUVTNOVXIrd3pVY2ZZcVJCZjh5Yi9DMld6Zm9CRm9URjA4ZkJkTUlJVEREOENzUDEra0wzMHg3UTZkWVpIN2RyamZaMGY0ZldMZEcxUTF0ODFxTUxCdlRSd2VqQi9UQmwxQkRNbnpRR1MyZE14S281azdGczlpU1kvakFhQnZSOFBjMjZwWmFIMDJxdUxaU1hnTzZ4c2JHbGVsR25saTF3WktjVk1xTjhnS2NSd0l0cmYrSy9WQjk1ZG9YYUx3T0pJVlN6T1UvKzJSZTVrVjdJdXV5SnJJaFR5THQ2bW16dExCQlBOWkxIb1VBeTlmRThVdko4aWt4Zmo4UHdKUFFFckplWWxrcXVUWnMyTVFGTHlrdUFOZ2MvSmIya24zWjNaTWFRVXJteHdPMXp5QW83Z2ZSQUo2UmZPSXlNRUZka1hqNUY4QlRLNWx6eFF2NjEweWk4UWNGYXRJOGdRb0NJSzd4K2hvandSbmFFNUg0SlRpRWo5UGpyL3JKRHFjWnluOWI0b3Z1NDVMWWJkV3ZYZXF0c1hNSGlTbFo1Q2VnUkV4UHoxaGQ4M1BZajVQT28wUWluWHlMRmc0OGhuWlRPaVExRHpyMUlaRWFlUVJvSm4wSEtaSVI3bEEya2ZIclFVZXJYSFRseDRaTCtybmpqRlJHUkdlWUI1TVVqMkduYlcrWGJ1SkZycDFoZVhnSTZKQ1ltdnZVRk4xeDNBZWszU1drYXBSQVhNZUpGR1M4Z2UyWGZ1b2cwdG9heWtFRDNNcGs4K3NoT2src3Y2OFk1MFY5V3VLZXdCS3Q1MDk0bzM5YXRXL21SZjVXWGdJWVpHUmxvM0xpeHlzNG5qNkE2WjFZTWNxUkNwd1U0b3VEbFV5SGsvUUEvaE50dFIyNVdsdmgvWnRoSlVzaWw5QVRRL2F4a1licUV6RGdmTDBUcy94MzUrYUx5VEVTN0lZMzZRNncvK1E0L3RQNnd1VW9aOSs3ZHk3ZWJWbVFaak8vYXRhdkt6bjMyckFkZVhrZDZLQ2tYZEF4WjEzeUZjTEZudlBENzN6ckRWcnNkVHM2ZWdnS1N1U2pqT1JIa1VHb0MwaTg2SXljNlFQUVg3ZXFNblRvZFlOdXpIVTR2bm9zaWFpdE1TVVNhdndNeTZkM0l2RVVyelZpVk1ycTV1WEVYNHl0Q2dMKyt2cjVTeDdWcjFjSURYMGRLa1FKZmozN1JzM2p3MXNCeGt3bHdHRDRBeDMrY2lOMWZhQ0hXNzZ4UVJGZ0FPY2pTRU1Ca0llMHg4bkx6Y2V6N2tUZzhSaC91eHVPeFIvY1RKSVNGU2ZxN2VBVHBaQ2s4Q0FmWExWRkp3SVVMWEhuSG9Jb1FZTHR3NFVLbGpwczJhb2dYUWNRdWVmL1hBaU1ES1krUzREaHlFRndwRG5DajlmK0FmbDhFYmJXUlRBTmFBZGlobFlvQU1uOGFaenlOdVlPRFgvZUQyOVR2UkgvN3YrcU44SDI3SmRPQXlXUWZRUTc0eFBhZlZSTEFQb3g5V1VsSzZoSUdFZ3g0ZjAwS2cySmN2SGhScWVQNkZJd2tuWGVteWVuLzJnTElJZUMvQ1lrNDlNMEF1RTR4Z3R1MHNUaGc4QVVDTjYyVEV1QmRSZ0pvMlkrS3hoOUQvazU5U1Fpd0g5UUhvYnQzU0FrNEtTR0E0b1dqbTFZcXlWaThVNlNvajR5T3JITS9qVEF5S1ZieS9QbnpJb05pOEwrTDRlWGxwWG9GY0xjVGdjMXJBbElTa0plWER4ZUsyQTZQMWhkVHdJNm1RUFRKRStXYkFsbkp5RTdQaE5PM1EzQmtyS0dZV3R4ZkhNa2ttUUxPMGlsd0E3K3ZYcUFrbjY2dXJ0QkxVWjlpSGZtMzBOQlFhUEFmMTY1ZEEwZDl2UDJVbEpTRXAwK2Y0dkhqeDNqMDZKSDRlK3JVcVVvdmNObXlHa2lORWtMd2tsWHNCRytlY01VT25mYllvZDFlbUc1dWJvRktKOGpQRlZEMGwwZEJVSHFvUERIcFFlUUViMHFjNEZVSGUzS0FiWVVUOUpnekRid09GTDVNZk4wZlhrWGhKNVB4U3ZMdDJMRkQxQWg1dTR6MVlKMTRsNHFuQmU4djNyaHhBeno0UEFWRzhuTEhpdklQMGRIUmlJaUlRR1JrcEVnbXJsNjlDbFcxUUJNalE3TERXOGhtVStSUkk2OWNrSklraEw3amZSSkJtNjJSK1RKVllxNmgwamhCUnNsc2l2cWVuVDJNRi83T3lJNzBWbWtGaFduUEphUzZPeVBrdDQzSXljcVI5RWZXbEg3SkRRVVVUdU5oQ0hSN0tlOVljUnAvNWNvVm9RUHJjdm55WlVSRlJZbUJabExTMGtSOE1WTEQyOXNibnA2ZThQSHhRVUJBZ0NnbjhZTzhFM3o3OW0zQkdLZVZjK2JNa1h1Qlp0MDZTQTEyRi9GNUdvMGdSNEM4SEJhbFBaTVBYS0w4bFFLaFBBcUYrZjk3S1hGeU54NkhRc29Qc3NoSi9rbUFwMlRLa0pMSVNwWHZqeXhOaE1ZY0RWTE9FTytsUERpOEI1bWFtaXBrWngxWUY5WXBKQ1JFckF5K3ZyNUNaOVpkV0FCaERHRVlZVEJoQU9GejNnNG5mTUplbE5DYmtOQ3BVeWU1RjAzNG12eElQaTEvRk0relFDdzBrNUI5TzBpRXI1a1JYa3FoTUpPVmY5TlhJSGp0VDdobWF5bVNvQnpLRVRpbWtBdUZwYUYxZGt3STlSY21JWWFYdjNCSlhvR0N1eUlnazVXcGVmUG1LQ2dvWUs0NlNtWC9SS29MNjlTZmwwV3VGRWwxSGxtV0pYRTV6NldtVFp2S0p4eG14a0lRM0F1VTVBUGs2TklDajRoUlQ2ZUlUVEVFenFXazU1SEhQanozY3hKaE5GNWN4ZU5UOWtqMmNSRFRRakVrenBEdGp5eUNpYzVsNWZFQTd1U0hGRWVmUjVwUHNhaHJiMkI5UWtJQ0ZIZUo1MUh1bmtkTElnMFZMWTBCRktkTHdsbFZIcDRkSHl2c3QzUXVFaWlqdTIxdkEvK1Zaa2lsdUlLdDRJM1JJZldYUTRRZ0tVeGtuaTQ3TEpXVVAzUG1qSG8yUnhWSStDZWJtS0pQNkVpRkRWdXJ4VWdtRXhlNVBIbG5QQWtuOHc0UXFXNjJOQ1ZtWW9wb3ppZDVIMENJOVJLRTIxZ2dKZUFZRWVNbmZpdE9uUm41WENmZ2VKK1ZUb3NXUVU4TU9jNlpFMGNxblVtNGZ2MTY1U3JQQlZIQ2ZNSTRUb3dVZm1PZnNJY2RKaDkya0JXbVVjUDZHRHQ4RURaYnpJZmZINXR4My9ld1NGanc1TEtrME1FRkVrWmVuREJqZ2V3N1lpb2c1YnJrdCtRcmtudkptaElwNEFwdy9BMWJWcGpoRy8wdjVkN1ZybDA3Yk51MlRlbFVTcVVvejh1STNaNDlPRXRCQXkrVGRQMUNxS3R3SHp2UVV4eGdUSnMyVGVYNWdkcTFhME9iU21DamgrakIrTnV2UmFtTDErM2xzNzdIQ2lwMXJUU2RKUDVlTm5NaXpLbmRqTUxvSDQyRzRidGhYK0Z6SFMzVVZWRUM2OWV2SDM3OTlWZUtNWEpacmxXS2NsVUdBWjVqeG94QjAyWk5zTmx4SDc0YWFnQkhaeWV4OTg2SGxWVGN6eUdtSTU4aDRDakwydG9hNDhlUEZ4c1VQRW90V3JRb2MwR1QwL0MyYmR1aVk4ZU80SVNNY3hMZW9PRlloUzZxbTJFcG9aRzY1am1iditkUFN5UlpsdDVRZlZqdnRYMTlBT0ZOTCthREZOSTRtMGVGYzlIbzVPUmthR3RybDVrQVZwNkRNT2s4OGVmRWpMZSsrWmhjbFp3SFRKSEVIYnM0WU9DbUxqMjY0NWZkdnduVEs0MnpvWHRhRUh3TkRRM0xYZFptNXlhZDMvMnIrZ1FtRHNSbklGNUtBbGRYNnpkc2dHL0dHOEY0NFZ6Y3UzZVAyeTFLNkdQcjJyVnJLMXpibno1OU9yL0xvYW9KQ1BaNGtDWnNqdzlHRUNMNzlPbURqOXEyd2IrMzIwQzMvNWZnUFFPNlZyemgrZnBjRHF4WHIxNmxiSEJ3Z2taWG02b2tZSnIwRUNNclg1dnJhaUoxbEFyRWpyRW56V3VPcWVtaVlqOXNwR2QyZWU0NzhYa2lQc0pha21KODNxQTA1LzhxWE51ckpGTGl1blhyaHBvMWE2THhCMDJ3eUhJRlpwb3ZnT0h3WWZqWjBoSzJsSDV1MnJ3WjVzdVdZdjV5Y3lVbG1qUnBnbDY5ZWltbHJGeTNrd3VveU92WHIxOWZybTNSb2tWTXdQWjNUWUM1N0U2eFZxK2U2S3pWRFNhTC9vRXA4MlpoOEloaFdMakdBcC9wOW9YNXVqVktCTmpZMk1EVjFWV3V6ZDNkWGFUZXNtMmJpVVF1Wjh1MjhlbFNQbUtyOGE0dmRvZzhHbkpwY1QxTjFLSFV1QmJ0MGpTZ1d1R2J6SmgzbVZoaDJUWUhCd2R4akZhMmpWY1pudlBWbFFCT0xYZFpXbHFXMlpGeE5ZWVZsbTA3ZlBnd0FnTUQ1ZHI0T0Q1SGVITEZGeE0rTzQyREd0WGhJa0ZhTVFsY1VqSXpNMFAzN3QxUm8wWU5wWlBqUEpjVks3U09qbzV5YlU1T1RxSUFvMGdBaDk3VmxnQVpJajRsOFBuNFdGYU82NG9jdVhHNnpKdERiTXF5U25DN0lnRjh1cHRMVnJKdHExZXZGdVdxYWsrQTRqNGk0VE5wbHRpSjhMUGlORkZGd05HalJ5V0Z5ZmVkQUZVbnkvam9la2tFdUxpNEtLMENmeWtDZUZua2l1MWZsZ0JlRnRsMy9EOFNzTWJLeWtwT2lmdjM3eXNSY1B6NGNWSEtVaVNBOHd3TmRSOS9WVE1CU2g5WThTNE5mMnFuU0lDaUJiRHpWQ1JnOXV6WlRNQys5NGtBdjZGRGg4b3B3UnNWSFBqSXRubDRlRUR4SE5MS2xTdEZYVisyamF2US9NMVNwWmUrMUtBNEw0RzdXREc1N2ZTbS9PVWJYaXFHMGV3QUZZT2VZY040ZndaaHZMa3AyeTR0ZnRyeGNsdGRsZi93K2ZQbjRxTkd4VENZVTJtNm5yUnUzVnF1blQvRW9pdVp2dzZUVFpIcHl1Tk5tRWFOR3NuZFAzZnUzT0pBcTFOMUpPQUhEbXlLaGVWdE5QNE9rRTJjclVMUkFXN2Z2bDIwRXl5THkyNGE4cCsvN1dJU0ZpeFlJTUx0NHQ4MmJOaFFZalhxWFJFZ1BxM2o3NG1sWDNBbVNMOEUxZU9QSUJYbnVWVDVPc1ZacHVMbk9NZU9IZU43dmlmd2lZaFl6aEM1SXB3bE9YajFRWFdkQm15L1hXVS9YK1VxTVpmS0J3NGNLQW9iSFBsSmxaZTloNnRPdSs3Y3VTTjJkZzBNRE1TU3laVXBtWHZhU0QrY3JxL3h2bDBrOUJUQ1JhN3FFUHErNVQ0dDZmZkY1MldWVitmMVA2enlMRzMwYnNVNEFBQUFBRWxGVGtTdVFtQ0NcIj4nLFxuICAnc2hvd2Rvd24nOiAnPGltZyB3aWR0aD1cIjIwXCIgaGVpZ2h0PVwiMjBcIiBhbGlnbj1cImFic21pZGRsZVwiIHNyYz1cImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBRUFBQUFCQUNBWUFBQUNxYVhIZUFBQUFDWEJJV1hNQUFBc1RBQUFMRXdFQW1wd1lBQUFLVDJsRFExQlFhRzkwYjNOb2IzQWdTVU5ESUhCeWIyWnBiR1VBQUhqYW5WTm5WRlBwRmozMzN2UkNTNGlBbEV0dlVoVUlJRkpDaTRBVWtTWXFJUWtRU29naG9ka1ZVY0VSUlVVRUc4aWdpQU9Pam9DTUZWRXNESW9LMkFma0lhS09nNk9JaXNyNzRYdWphOWE4OStiTi9yWFhQdWVzODUyenp3ZkFDQXlXU0ROUk5ZQU1xVUllRWVDRHg4VEc0ZVF1UUlFS0pIQUFFQWl6WkNGei9TTUJBUGgrUER3cklzQUh2Z0FCZU5NTENBREFUWnZBTUJ5SC93L3FRcGxjQVlDRUFjQjBrVGhMQ0lBVUFFQjZqa0ttQUVCR0FZQ2RtQ1pUQUtBRUFHRExZMkxqQUZBdEFHQW5mK2JUQUlDZCtKbDdBUUJibENFVkFhQ1JBQ0FUWlloRUFHZzdBS3pQVm9wRkFGZ3dBQlJtUzhRNUFOZ3RBREJKVjJaSUFMQzNBTURPRUF1eUFBZ01BREJSaUlVcEFBUjdBR0RJSXlONEFJU1pBQlJHOGxjODhTdXVFT2NxQUFCNG1iSTh1U1E1UllGYkNDMXhCMWRYTGg0b3pra1hLeFEyWVFKaG1rQXV3bm1aR1RLQk5BL2c4OHdBQUtDUkZSSGdnL1A5ZU00T3JzN09ObzYyRGw4dDZyOEcveUppWXVQKzVjK3JjRUFBQU9GMGZ0SCtMQyt6R29BN0JvQnQvcUlsN2dSb1hndWdkZmVMWnJJUFFMVUFvT25hVi9OdytINDhQRVdoa0xuWjJlWGs1TmhLeEVKYlljcFhmZjVud2wvQVYvMXMrWDQ4L1BmMTRMN2lKSUV5WFlGSEJQamd3c3owVEtVY3o1SUpoR0xjNW85SC9MY0wvL3dkMHlMRVNXSzVXQ29VNDFFU2NZNUVtb3p6TXFVaWlVS1NLY1VsMHY5azR0OHMrd00rM3pVQXNHbytBWHVSTGFoZFl3UDJTeWNRV0hUQTR2Y0FBUEs3YjhIVUtBZ0RnR2lENGM5My8rOC8vVWVnSlFDQVprbVNjUUFBWGtRa0xsVEtzei9IQ0FBQVJLQ0JLckJCRy9UQkdDekFCaHpCQmR6QkMveGdOb1JDSk1UQ1FoQkNDbVNBSEhKZ0theUNRaWlHemJBZEttQXYxRUFkTk1CUmFJYVRjQTR1d2xXNERqMXdEL3BoQ0o3QktMeUJDUVJCeUFnVFlTSGFpQUZpaWxnampnZ1htWVg0SWNGSUJCS0xKQ0RKaUJSUklrdVJOVWd4VW9wVUlGVklIZkk5Y2dJNWgxeEd1cEU3eUFBeWd2eUd2RWN4bElHeVVUM1VETFZEdWFnM0dvUkdvZ3ZRWkhReG1vOFdvSnZRY3JRYVBZdzJvZWZRcTJnUDJvOCtROGN3d09nWUJ6UEViREF1eHNOQ3NUZ3NDWk5qeTdFaXJBeXJ4aHF3VnF3RHU0bjFZOCt4ZHdRU2dVWEFDVFlFZDBJZ1lSNUJTRmhNV0U3WVNLZ2dIQ1EwRWRvSk53a0RoRkhDSnlLVHFFdTBKcm9SK2NRWVlqSXhoMWhJTENQV0VvOFRMeEI3aUVQRU55UVNpVU15SjdtUUFrbXhwRlRTRXRKRzBtNVNJK2tzcVpzMFNCb2prOG5hWkd1eUJ6bVVMQ0FyeUlYa25lVEQ1RFBrRytRaDhsc0tuV0pBY2FUNFUrSW9Vc3BxU2hubEVPVTA1UVpsbURKQlZhT2FVdDJvb1ZRUk5ZOWFRcTJodGxLdlVZZW9FelIxbWpuTmd4WkpTNld0b3BYVEdtZ1hhUGRwcitoMHVoSGRsUjVPbDlCWDBzdnBSK2lYNkFQMGR3d05oaFdEeDRobktCbWJHQWNZWnhsM0dLK1lUS1laMDRzWngxUXdOekhybU9lWkQ1bHZWVmdxdGlwOEZaSEtDcFZLbFNhVkd5b3ZWS21xcHFyZXFndFY4MVhMVkkrcFhsTjlya1pWTTFQanFRblVscXRWcXAxUTYxTWJVMmVwTzZpSHFtZW9iMVEvcEg1Wi9Za0dXY05NdzA5RHBGR2dzVi9qdk1ZZ0MyTVpzM2dzSVdzTnE0WjFnVFhFSnJITjJYeDJLcnVZL1IyN2l6MnFxYUU1UXpOS00xZXpVdk9VWmo4SDQ1aHgrSngwVGdubktLZVg4MzZLM2hUdktlSXBHNlkwVExreFpWeHJxcGFYbGxpclNLdFJxMGZydlRhdTdhZWRwcjFGdTFuN2dRNUJ4MG9uWENkSFo0L09CWjNuVTlsVDNhY0tweFpOUFRyMXJpNnFhNlVib2J0RWQ3OXVwKzZZbnI1ZWdKNU1iNmZlZWIzbitoeDlMLzFVL1czNnAvVkhERmdHc3d3a0J0c016aGc4eFRWeGJ6d2RMOGZiOFZGRFhjTkFRNlZobFdHWDRZU1J1ZEU4bzlWR2pVWVBqR25HWE9NazQyM0diY2FqSmdZbUlTWkxUZXBON3BwU1RibW1LYVk3VER0TXg4M016YUxOMXBrMW16MHgxekxubStlYjE1dmZ0MkJhZUZvc3RxaTJ1R1ZKc3VSYXBsbnV0cnh1aFZvNVdhVllWVnBkczBhdG5hMGwxcnV0dTZjUnA3bE9rMDZybnRabnc3RHh0c20ycWJjWnNPWFlCdHV1dG0yMmZXRm5ZaGRudDhXdXcrNlR2Wk45dW4yTi9UMEhEWWZaRHFzZFdoMStjN1J5RkRwV090NmF6cHp1UDMzRjlKYnBMMmRZenhEUDJEUGp0aFBMS2NScG5WT2IwMGRuRjJlNWM0UHppSXVKUzRMTExwYytMcHNieHQzSXZlUktkUFZ4WGVGNjB2V2RtN09id3UybzI2L3VOdTVwN29mY244dzBueW1lV1ROejBNUElRK0JSNWRFL0M1K1ZNR3Zmckg1UFEwK0JaN1huSXk5akw1RlhyZGV3dDZWM3F2ZGg3eGMrOWo1eW4rTSs0enczM2pMZVdWL01OOEMzeUxmTFQ4TnZubCtGMzBOL0kvOWsvM3IvMFFDbmdDVUJad09KZ1VHQld3TDcrSHA4SWIrT1B6cmJaZmF5MmUxQmpLQzVRUlZCajRLdGd1WEJyU0ZveU95UXJTSDM1NWpPa2M1cERvVlFmdWpXMEFkaDVtR0x3MzRNSjRXSGhWZUdQNDV3aUZnYTBUR1hOWGZSM0VOejMwVDZSSlpFM3B0bk1VODVyeTFLTlNvK3FpNXFQTm8zdWpTNlA4WXVabG5NMVZpZFdFbHNTeHc1TGlxdU5tNXN2dC84N2ZPSDRwM2lDK043RjVndnlGMXdlYUhPd3ZTRnB4YXBMaElzT3BaQVRJaE9PSlR3UVJBcXFCYU1KZklUZHlXT0NubkNIY0puSWkvUk50R0kyRU5jS2g1TzhrZ3FUWHFTN0pHOE5Ya2t4VE9sTE9XNWhDZXBrTHhNRFV6ZG16cWVGcHAySUcweVBUcTlNWU9Ta1pCeFFxb2hUWk8yWitwbjVtWjJ5NnhsaGJMK3hXNkx0eThlbFFmSmE3T1FyQVZaTFFxMlFxYm9WRm9vMXlvSHNtZGxWMmEvelluS09aYXJuaXZON2N5enl0dVFONXp2bi8vdEVzSVM0WksycFlaTFZ5MGRXT2E5ckdvNXNqeHhlZHNLNHhVRks0WldCcXc4dUlxMkttM1ZUNnZ0VjVldWZyMG1lazFyZ1Y3QnlvTEJ0UUZyNnd0VkN1V0ZmZXZjMSsxZFQxZ3ZXZCsxWWZxR25ScytGWW1LcmhUYkY1Y1ZmOWdvM0hqbEc0ZHZ5citaM0pTMHFhdkV1V1RQWnRKbTZlYmVMWjViRHBhcWwrYVhEbTROMmRxMERkOVd0TzMxOWtYYkw1Zk5LTnU3ZzdaRHVhTy9QTGk4WmFmSnpzMDdQMVNrVlBSVStsUTI3dExkdFdIWCtHN1I3aHQ3dlBZMDdOWGJXN3ozL1Q3SnZ0dFZBVlZOMVdiVlpmdEorN1AzUDY2SnF1bjRsdnR0WGExT2JYSHR4d1BTQS8wSEl3NjIxN25VMVIzU1BWUlNqOVlyNjBjT3h4KysvcDN2ZHkwTk5nMVZqWnpHNGlOd1JIbms2ZmNKMy9jZURUcmFkb3g3ck9FSDB4OTJIV2NkTDJwQ212S2FScHRUbXZ0YllsdTZUOHcrMGRicTNucjhSOXNmRDV3MFBGbDVTdk5VeVduYTZZTFRrMmZ5ejR5ZGxaMTlmaTc1M0dEYm9yWjc1MlBPMzJvUGIrKzZFSFRoMGtYL2krYzd2RHZPWFBLNGRQS3kyK1VUVjdoWG1xODZYMjNxZE9vOC9wUFRUOGU3bkx1YXJybGNhN251ZXIyMWUyYjM2UnVlTjg3ZDlMMTU4UmIvMXRXZU9UM2R2Zk42Yi9mRjkvWGZGdDErY2lmOXpzdTcyWGNuN3EyOFQ3eGY5RUR0UWRsRDNZZlZQMXYrM05qdjNIOXF3SGVnODlIY1IvY0doWVBQL3BIMWp3OURCWStaajh1R0RZYnJuamcrT1RuaVAzTDk2ZnluUTg5a3p5YWVGLzZpL3N1dUZ4WXZmdmpWNjlmTzBaalJvWmZ5bDVPL2JYeWwvZXJBNnhtdjI4YkN4aDYreVhnek1WNzBWdnZ0d1hmY2R4M3ZvOThQVCtSOElIOG8vMmo1c2ZWVDBLZjdreG1Uay84RUE1anovR016TGRzQUFFQ3RhVlJZZEZoTlREcGpiMjB1WVdSdlltVXVlRzF3QUFBQUFBQThQM2h3WVdOclpYUWdZbVZuYVc0OUl1Kzd2eUlnYVdROUlsYzFUVEJOY0VObGFHbEllbkpsVTNwT1ZHTjZhMk01WkNJL1BnbzhlRHA0YlhCdFpYUmhJSGh0Ykc1ek9uZzlJbUZrYjJKbE9tNXpPbTFsZEdFdklpQjRPbmh0Y0hSclBTSkJaRzlpWlNCWVRWQWdRMjl5WlNBMUxqWXRZekEyTnlBM09TNHhOVGMzTkRjc0lESXdNVFV2TURNdk16QXRNak02TkRBNk5ESWdJQ0FnSUNBZ0lDSStDaUFnSUR4eVpHWTZVa1JHSUhodGJHNXpPbkprWmowaWFIUjBjRG92TDNkM2R5NTNNeTV2Y21jdk1UazVPUzh3TWk4eU1pMXlaR1l0YzNsdWRHRjRMVzV6SXlJK0NpQWdJQ0FnSUR4eVpHWTZSR1Z6WTNKcGNIUnBiMjRnY21SbU9tRmliM1YwUFNJaUNpQWdJQ0FnSUNBZ0lDQWdJSGh0Ykc1ek9uaHRjRDBpYUhSMGNEb3ZMMjV6TG1Ga2IySmxMbU52YlM5NFlYQXZNUzR3THlJS0lDQWdJQ0FnSUNBZ0lDQWdlRzFzYm5NNmNHaHZkRzl6YUc5d1BTSm9kSFJ3T2k4dmJuTXVZV1J2WW1VdVkyOXRMM0JvYjNSdmMyaHZjQzh4TGpBdklnb2dJQ0FnSUNBZ0lDQWdJQ0I0Yld4dWN6cGtZejBpYUhSMGNEb3ZMM0IxY213dWIzSm5MMlJqTDJWc1pXMWxiblJ6THpFdU1TOGlDaUFnSUNBZ0lDQWdJQ0FnSUhodGJHNXpPbmh0Y0UxTlBTSm9kSFJ3T2k4dmJuTXVZV1J2WW1VdVkyOXRMM2hoY0M4eExqQXZiVzB2SWdvZ0lDQWdJQ0FnSUNBZ0lDQjRiV3h1Y3pwemRFVjJkRDBpYUhSMGNEb3ZMMjV6TG1Ga2IySmxMbU52YlM5NFlYQXZNUzR3TDNOVWVYQmxMMUpsYzI5MWNtTmxSWFpsYm5Raklnb2dJQ0FnSUNBZ0lDQWdJQ0I0Yld4dWN6cHpkRkpsWmowaWFIUjBjRG92TDI1ekxtRmtiMkpsTG1OdmJTOTRZWEF2TVM0d0wzTlVlWEJsTDFKbGMyOTFjbU5sVW1WbUl5SUtJQ0FnSUNBZ0lDQWdJQ0FnZUcxc2JuTTZkR2xtWmowaWFIUjBjRG92TDI1ekxtRmtiMkpsTG1OdmJTOTBhV1ptTHpFdU1DOGlDaUFnSUNBZ0lDQWdJQ0FnSUhodGJHNXpPbVY0YVdZOUltaDBkSEE2THk5dWN5NWhaRzlpWlM1amIyMHZaWGhwWmk4eExqQXZJajRLSUNBZ0lDQWdJQ0FnUEhodGNEcERjbVZoZEc5eVZHOXZiRDVCWkc5aVpTQlFhRzkwYjNOb2IzQWdRME1nTWpBeE5TQW9WMmx1Wkc5M2N5azhMM2h0Y0RwRGNtVmhkRzl5Vkc5dmJENEtJQ0FnSUNBZ0lDQWdQSGh0Y0RwRGNtVmhkR1ZFWVhSbFBqSXdNVFV0TURFdE1UVlVNakU2TURFNk1UbGFQQzk0YlhBNlEzSmxZWFJsUkdGMFpUNEtJQ0FnSUNBZ0lDQWdQSGh0Y0RwTlpYUmhaR0YwWVVSaGRHVStNakF4TnkweE1DMHlORlF4TXpvek1Ub3pNQ3N3TVRvd01Ed3ZlRzF3T2sxbGRHRmtZWFJoUkdGMFpUNEtJQ0FnSUNBZ0lDQWdQSGh0Y0RwTmIyUnBabmxFWVhSbFBqSXdNVGN0TVRBdE1qUlVNVE02TXpFNk16QXJNREU2TURBOEwzaHRjRHBOYjJScFpubEVZWFJsUGdvZ0lDQWdJQ0FnSUNBOGNHaHZkRzl6YUc5d09rTnZiRzl5VFc5a1pUNHpQQzl3YUc5MGIzTm9iM0E2UTI5c2IzSk5iMlJsUGdvZ0lDQWdJQ0FnSUNBOGNHaHZkRzl6YUc5d09rbERRMUJ5YjJacGJHVStjMUpIUWlCSlJVTTJNVGsyTmkweUxqRThMM0JvYjNSdmMyaHZjRHBKUTBOUWNtOW1hV3hsUGdvZ0lDQWdJQ0FnSUNBOGNHaHZkRzl6YUc5d09sUmxlSFJNWVhsbGNuTStDaUFnSUNBZ0lDQWdJQ0FnSUR4eVpHWTZRbUZuUGdvZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0E4Y21SbU9teHBJSEprWmpwd1lYSnpaVlI1Y0dVOUlsSmxjMjkxY21ObElqNEtJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdQSEJvYjNSdmMyaHZjRHBNWVhsbGNrNWhiV1UrVXlBdFBDOXdhRzkwYjNOb2IzQTZUR0Y1WlhKT1lXMWxQZ29nSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0E4Y0dodmRHOXphRzl3T2t4aGVXVnlWR1Y0ZEQ1VElDMDhMM0JvYjNSdmMyaHZjRHBNWVhsbGNsUmxlSFErQ2lBZ0lDQWdJQ0FnSUNBZ0lDQWdJRHd2Y21SbU9teHBQZ29nSUNBZ0lDQWdJQ0FnSUNBOEwzSmtaanBDWVdjK0NpQWdJQ0FnSUNBZ0lEd3ZjR2h2ZEc5emFHOXdPbFJsZUhSTVlYbGxjbk0rQ2lBZ0lDQWdJQ0FnSUR4a1l6cG1iM0p0WVhRK2FXMWhaMlV2Y0c1blBDOWtZenBtYjNKdFlYUStDaUFnSUNBZ0lDQWdJRHg0YlhCTlRUcEpibk4wWVc1alpVbEVQbmh0Y0M1cGFXUTZOMk5rTXpReE56Y3RPV1l5WmkweU5EUmlMV0V5WWpRdE16VTFNekprWTJZMU1XSmlQQzk0YlhCTlRUcEpibk4wWVc1alpVbEVQZ29nSUNBZ0lDQWdJQ0E4ZUcxd1RVMDZSRzlqZFcxbGJuUkpSRDVoWkc5aVpUcGtiMk5wWkRwd2FHOTBiM05vYjNBNk0yRTFZemd4WW1ZdFlqaGlOeTB4TVdVM0xUazBORGt0WVRRMk16ZGxaakprTmpNelBDOTRiWEJOVFRwRWIyTjFiV1Z1ZEVsRVBnb2dJQ0FnSUNBZ0lDQThlRzF3VFUwNlQzSnBaMmx1WVd4RWIyTjFiV1Z1ZEVsRVBuaHRjQzVrYVdRNk5qQkROVUZGTmpWR05qbERSVFF4TVRrME5VRTROVFZGTTBKRFFUZEZSVUk4TDNodGNFMU5Pazl5YVdkcGJtRnNSRzlqZFcxbGJuUkpSRDRLSUNBZ0lDQWdJQ0FnUEhodGNFMU5Pa2hwYzNSdmNuaytDaUFnSUNBZ0lDQWdJQ0FnSUR4eVpHWTZVMlZ4UGdvZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0E4Y21SbU9teHBJSEprWmpwd1lYSnpaVlI1Y0dVOUlsSmxjMjkxY21ObElqNEtJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdQSE4wUlhaME9tRmpkR2x2Ymo1amNtVmhkR1ZrUEM5emRFVjJkRHBoWTNScGIyNCtDaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJRHh6ZEVWMmREcHBibk4wWVc1alpVbEVQbmh0Y0M1cGFXUTZOakJETlVGRk5qVkdOamxEUlRReE1UazBOVUU0TlRWRk0wSkRRVGRGUlVJOEwzTjBSWFowT21sdWMzUmhibU5sU1VRK0NpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lEeHpkRVYyZERwM2FHVnVQakl3TVRVdE1ERXRNVFZVTWpFNk1ERTZNVGxhUEM5emRFVjJkRHAzYUdWdVBnb2dJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQThjM1JGZG5RNmMyOW1kSGRoY21WQloyVnVkRDVCWkc5aVpTQlFhRzkwYjNOb2IzQWdRMU0ySUNoWGFXNWtiM2R6S1R3dmMzUkZkblE2YzI5bWRIZGhjbVZCWjJWdWRENEtJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ1BDOXlaR1k2YkdrK0NpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUR4eVpHWTZiR2tnY21SbU9uQmhjbk5sVkhsd1pUMGlVbVZ6YjNWeVkyVWlQZ29nSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0E4YzNSRmRuUTZZV04wYVc5dVBuTmhkbVZrUEM5emRFVjJkRHBoWTNScGIyNCtDaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJRHh6ZEVWMmREcHBibk4wWVc1alpVbEVQbmh0Y0M1cGFXUTZPRFpqTmpCa01HUXRPR1kwWXkwMVpUUmxMV0V3TWpRdE9ESTRaV1F5TlRJd1pEYzNQQzl6ZEVWMmREcHBibk4wWVc1alpVbEVQZ29nSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0E4YzNSRmRuUTZkMmhsYmo0eU1ERTNMVEV3TFRJMFZERXpPak14T2pNd0t6QXhPakF3UEM5emRFVjJkRHAzYUdWdVBnb2dJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQThjM1JGZG5RNmMyOW1kSGRoY21WQloyVnVkRDVCWkc5aVpTQlFhRzkwYjNOb2IzQWdRME1nTWpBeE5TQW9WMmx1Wkc5M2N5azhMM04wUlhaME9uTnZablIzWVhKbFFXZGxiblErQ2lBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUR4emRFVjJkRHBqYUdGdVoyVmtQaTg4TDNOMFJYWjBPbU5vWVc1blpXUStDaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lEd3ZjbVJtT214cFBnb2dJQ0FnSUNBZ0lDQWdJQ0FnSUNBOGNtUm1PbXhwSUhKa1pqcHdZWEp6WlZSNWNHVTlJbEpsYzI5MWNtTmxJajRLSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnUEhOMFJYWjBPbUZqZEdsdmJqNWpiMjUyWlhKMFpXUThMM04wUlhaME9tRmpkR2x2Ymo0S0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ1BITjBSWFowT25CaGNtRnRaWFJsY25NK1puSnZiU0JoY0hCc2FXTmhkR2x2Ymk5MmJtUXVZV1J2WW1VdWNHaHZkRzl6YUc5d0lIUnZJR2x0WVdkbEwzQnVaend2YzNSRmRuUTZjR0Z5WVcxbGRHVnljejRLSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdQQzl5WkdZNmJHaytDaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lEeHlaR1k2YkdrZ2NtUm1PbkJoY25ObFZIbHdaVDBpVW1WemIzVnlZMlVpUGdvZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBOGMzUkZkblE2WVdOMGFXOXVQbVJsY21sMlpXUThMM04wUlhaME9tRmpkR2x2Ymo0S0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ1BITjBSWFowT25CaGNtRnRaWFJsY25NK1kyOXVkbVZ5ZEdWa0lHWnliMjBnWVhCd2JHbGpZWFJwYjI0dmRtNWtMbUZrYjJKbExuQm9iM1J2YzJodmNDQjBieUJwYldGblpTOXdibWM4TDNOMFJYWjBPbkJoY21GdFpYUmxjbk0rQ2lBZ0lDQWdJQ0FnSUNBZ0lDQWdJRHd2Y21SbU9teHBQZ29nSUNBZ0lDQWdJQ0FnSUNBZ0lDQThjbVJtT214cElISmtaanB3WVhKelpWUjVjR1U5SWxKbGMyOTFjbU5sSWo0S0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ1BITjBSWFowT21GamRHbHZiajV6WVhabFpEd3ZjM1JGZG5RNllXTjBhVzl1UGdvZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBOGMzUkZkblE2YVc1emRHRnVZMlZKUkQ1NGJYQXVhV2xrT2pkalpETTBNVGMzTFRsbU1tWXRNalEwWWkxaE1tSTBMVE0xTlRNeVpHTm1OVEZpWWp3dmMzUkZkblE2YVc1emRHRnVZMlZKUkQ0S0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ1BITjBSWFowT25kb1pXNCtNakF4TnkweE1DMHlORlF4TXpvek1Ub3pNQ3N3TVRvd01Ed3ZjM1JGZG5RNmQyaGxiajRLSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnUEhOMFJYWjBPbk52Wm5SM1lYSmxRV2RsYm5RK1FXUnZZbVVnVUdodmRHOXphRzl3SUVORElESXdNVFVnS0ZkcGJtUnZkM01wUEM5emRFVjJkRHB6YjJaMGQyRnlaVUZuWlc1MFBnb2dJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQThjM1JGZG5RNlkyaGhibWRsWkQ0dlBDOXpkRVYyZERwamFHRnVaMlZrUGdvZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0E4TDNKa1pqcHNhVDRLSUNBZ0lDQWdJQ0FnSUNBZ1BDOXlaR1k2VTJWeFBnb2dJQ0FnSUNBZ0lDQThMM2h0Y0UxTk9raHBjM1J2Y25rK0NpQWdJQ0FnSUNBZ0lEeDRiWEJOVFRwRVpYSnBkbVZrUm5KdmJTQnlaR1k2Y0dGeWMyVlVlWEJsUFNKU1pYTnZkWEpqWlNJK0NpQWdJQ0FnSUNBZ0lDQWdJRHh6ZEZKbFpqcHBibk4wWVc1alpVbEVQbmh0Y0M1cGFXUTZPRFpqTmpCa01HUXRPR1kwWXkwMVpUUmxMV0V3TWpRdE9ESTRaV1F5TlRJd1pEYzNQQzl6ZEZKbFpqcHBibk4wWVc1alpVbEVQZ29nSUNBZ0lDQWdJQ0FnSUNBOGMzUlNaV1k2Wkc5amRXMWxiblJKUkQ1NGJYQXVaR2xrT2pZd1F6VkJSVFkxUmpZNVEwVTBNVEU1TkRWQk9EVTFSVE5DUTBFM1JVVkNQQzl6ZEZKbFpqcGtiMk4xYldWdWRFbEVQZ29nSUNBZ0lDQWdJQ0FnSUNBOGMzUlNaV1k2YjNKcFoybHVZV3hFYjJOMWJXVnVkRWxFUG5odGNDNWthV1E2TmpCRE5VRkZOalZHTmpsRFJUUXhNVGswTlVFNE5UVkZNMEpEUVRkRlJVSThMM04wVW1WbU9tOXlhV2RwYm1Gc1JHOWpkVzFsYm5SSlJENEtJQ0FnSUNBZ0lDQWdQQzk0YlhCTlRUcEVaWEpwZG1Wa1JuSnZiVDRLSUNBZ0lDQWdJQ0FnUEhScFptWTZUM0pwWlc1MFlYUnBiMjQrTVR3dmRHbG1aanBQY21sbGJuUmhkR2x2Ymo0S0lDQWdJQ0FnSUNBZ1BIUnBabVk2V0ZKbGMyOXNkWFJwYjI0K056SXdNREF3THpFd01EQXdQQzkwYVdabU9saFNaWE52YkhWMGFXOXVQZ29nSUNBZ0lDQWdJQ0E4ZEdsbVpqcFpVbVZ6YjJ4MWRHbHZiajQzTWpBd01EQXZNVEF3TURBOEwzUnBabVk2V1ZKbGMyOXNkWFJwYjI0K0NpQWdJQ0FnSUNBZ0lEeDBhV1ptT2xKbGMyOXNkWFJwYjI1VmJtbDBQakk4TDNScFptWTZVbVZ6YjJ4MWRHbHZibFZ1YVhRK0NpQWdJQ0FnSUNBZ0lEeGxlR2xtT2tOdmJHOXlVM0JoWTJVK01Ud3ZaWGhwWmpwRGIyeHZjbE53WVdObFBnb2dJQ0FnSUNBZ0lDQThaWGhwWmpwUWFYaGxiRmhFYVcxbGJuTnBiMjQrTmpROEwyVjRhV1k2VUdsNFpXeFlSR2x0Wlc1emFXOXVQZ29nSUNBZ0lDQWdJQ0E4WlhocFpqcFFhWGhsYkZsRWFXMWxibk5wYjI0K05qUThMMlY0YVdZNlVHbDRaV3haUkdsdFpXNXphVzl1UGdvZ0lDQWdJQ0E4TDNKa1pqcEVaWE5qY21sd2RHbHZiajRLSUNBZ1BDOXlaR1k2VWtSR1BnbzhMM2c2ZUcxd2JXVjBZVDRLSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUFvZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0NpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQUtJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQW9nSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnQ2lBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBS0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lBb2dJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdDaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FLSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUFvZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0NpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQUtJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQW9nSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnQ2lBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBS0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lBb2dJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdDaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FLSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUFvZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0NpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQUtJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQW9nSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnQ2lBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBS0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lBb2dJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdDaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FLSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUFvZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0NpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQUtJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQW9nSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnQ2lBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBS0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lBb2dJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdDaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FLSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUFvZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0NpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQUtJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQW9nSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnQ2lBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBS0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lBb2dJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdDaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FLSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUFvZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0NpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQUtJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQW9nSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnQ2lBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBS0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lBb2dJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdDaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FLSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUFvZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0NpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQUtJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQW9nSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnQ2lBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBS0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lBb2dJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdDaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FLSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUFvZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0NpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQUtJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQW9nSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnQ2lBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBS0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lBb2dJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdDaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FLSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUFvZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0NpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQUtJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQW9nSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnQ2lBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBS0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lBb2dJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdDaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FLSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUFvZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0NpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQUtJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQW9nSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnQ2lBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBS0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lBb2dJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdDaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FLSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUFvZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0NpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQUtJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQW9nSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnQ2lBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBS0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lBb2dJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdDaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FLSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUFvZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0NpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQUtJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQW9nSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnQ2lBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBS0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lBb2dJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdDaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FLSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUFvZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0NpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQUtJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQW9nSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnQ2lBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBS0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lBb2dJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdDaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FLSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUFvZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0NpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQUtQRDk0Y0dGamEyVjBJR1Z1WkQwaWR5SS9Qc2U3YnpjQUFBQWdZMGhTVFFBQWVpVUFBSUNEQUFENS93QUFnT2tBQUhVd0FBRHFZQUFBT3BnQUFCZHZrbC9GUmdBQUExSkpSRUZVZU5yc20xK09tbEFVaHorYWVTOWR3WmdnSm4xQW5SVU1PNmpwQmdaWFVMdUMyaFdVV1VHWkJUU3hLeWl1b0E0bWZVQk1uQjA0SzVnKzlEaWhSQkhseWgvbEpMd0lYTGdmOTl4enp1OWV0WmVYRnk3WjNuRGgxZ0JvQUZ5NFhlVnRRTk8wek5jYXBtVURmVUJQbkZvQmZoUUdxNklCYUhtandENEFobWs1d0FENGtLRzVKOENOd3NBRmFIZTZEdkE5Y2Mwd0NnT3Y4Z0RrYTN2QTlSSE5QZ28wRDdoTm5KdEdZV0JYeGdWMmRINE1mTW5SUkErWTFXSU8yTko1Ri9pa29LbTN0WXNDaG1rTkZIVytmbUhRTUMxZGZIYVhQUVAzd00xeU1kYzJCL0FPR0FMVFdvYkJtSTFTaHUwVUdDd1g4M1h5UkJRR2F3SG50VHRkRzVnVU5meFZ1NENUTnFOdjYvd1dHTDdrQ2MrMUFtQ1lWaXNsM0kyeWRENEdZWlVDczdJam9MWHJ4SEl4OXc5dExBcURDZkJ3RHJYQVk0NTd4K2NBb0NmdXdSR2pZRlVuQUdrK1BzalI3czhEbjFWZUxXQ1lWbHBEdytWaXZqVkhTSHQrdTlQVkpiekd6WlhRV1RrQWt6MFYzMWZBVFVhRXNqVkpsUUJzNEZlR2N0ZUxnemdiQUFMQkErNHkzdm9BZUpMOG5BMEFIZkNsbk0xcW0xSGhuWVVpZENTRStLenZTU0pVVHdBeENPTWNwZkVUTUZZcGZSVUtJQWJDRmhDM09USkpKd3FEV1MwQnhFRDBKWjRQaml4MVAyK0UwbG9DU01Cd3lLNFMveGMxb2pCd2FnOGdNVTg0Y3ZUS0dnbWxBWWhuZ3UxTzl4QVh1VkU1SjFRQ1FDejNid0h1SHZkUXVpNVFLUUF4RU82ZUVLcHNGQ2dUUlNYa3Zkb3hTbEJNQ3hoSkpiZ3JyYlpSdEhDaVNoTjBwUkI2UGVRM2NrQncySzBvS1hNQlZZSklQK052aDlxdWxGaXZHb0J0MWxMUXhvd1QyeWtCWENmbmhaSWdsZ1lBQ1dtcVhRditiYWlvQllDZWlDUUhtK1FFZzFPN1JoRjdoTzRPaFNBaGNKS1NGVTdxQkdBRHdaZXFNTXVYbjZUVUJ3OHFsYU1yaXJOYjRMZGhXbFArU1dEK2NqRmZ4VHB1UzJHVXBpaytvM2pGU0VrcWJKaVduMFAwT01TR3FsV2lPdTBUdkQrRlJIWktBRStvVytjZlJtRXdxbHNlc0pKRUpzOHk5MVFxUCs5VUw2bHFFdHoyZ3B1TkVZNXNtOXNJSGxuMkRSYTJhRktHSnRpWGtaRU1pV3RnVnZSS1VTVUZrU0t0MlM3ZkFHZ0FYTFlwbVFRWGYzNk1VQ2hUWmRVYTJ1OC9ya3ZQQTZUejMwcjRlSDN5YmNCUzVnSjZTYU5YYithQUJrQTFBTXhLZW5jbEJaTFcvSGU0Y1lFR3dFWGIzd0VBU2VsZXhrNkxJSUlBQUFBQVNVVk9SSzVDWUlJPVwiPidcbn07XG5cclxuLyoqXG4gKiBDcmVhdGVkIGJ5IEVzdGV2YW8gb24gMzEtMDUtMjAxNS5cbiAqL1xuXG4vKipcbiAqIFNob3dkb3duIENvbnZlcnRlciBjbGFzc1xuICogQGNsYXNzXG4gKiBAcGFyYW0ge29iamVjdH0gW2NvbnZlcnRlck9wdGlvbnNdXG4gKiBAcmV0dXJucyB7Q29udmVydGVyfVxuICovXG5zaG93ZG93bi5Db252ZXJ0ZXIgPSBmdW5jdGlvbiAoY29udmVydGVyT3B0aW9ucykge1xuICAndXNlIHN0cmljdCc7XG5cbiAgdmFyXG4gICAgICAvKipcbiAgICAgICAqIE9wdGlvbnMgdXNlZCBieSB0aGlzIGNvbnZlcnRlclxuICAgICAgICogQHByaXZhdGVcbiAgICAgICAqIEB0eXBlIHt7fX1cbiAgICAgICAqL1xuICAgICAgb3B0aW9ucyA9IHt9LFxuXG4gICAgICAvKipcbiAgICAgICAqIExhbmd1YWdlIGV4dGVuc2lvbnMgdXNlZCBieSB0aGlzIGNvbnZlcnRlclxuICAgICAgICogQHByaXZhdGVcbiAgICAgICAqIEB0eXBlIHtBcnJheX1cbiAgICAgICAqL1xuICAgICAgbGFuZ0V4dGVuc2lvbnMgPSBbXSxcblxuICAgICAgLyoqXG4gICAgICAgKiBPdXRwdXQgbW9kaWZpZXJzIGV4dGVuc2lvbnMgdXNlZCBieSB0aGlzIGNvbnZlcnRlclxuICAgICAgICogQHByaXZhdGVcbiAgICAgICAqIEB0eXBlIHtBcnJheX1cbiAgICAgICAqL1xuICAgICAgb3V0cHV0TW9kaWZpZXJzID0gW10sXG5cbiAgICAgIC8qKlxuICAgICAgICogRXZlbnQgbGlzdGVuZXJzXG4gICAgICAgKiBAcHJpdmF0ZVxuICAgICAgICogQHR5cGUge3t9fVxuICAgICAgICovXG4gICAgICBsaXN0ZW5lcnMgPSB7fSxcblxuICAgICAgLyoqXG4gICAgICAgKiBUaGUgZmxhdm9yIHNldCBpbiB0aGlzIGNvbnZlcnRlclxuICAgICAgICovXG4gICAgICBzZXRDb252Rmxhdm9yID0gc2V0Rmxhdm9yLFxuXG4gICAgLyoqXG4gICAgICogTWV0YWRhdGEgb2YgdGhlIGRvY3VtZW50XG4gICAgICogQHR5cGUge3twYXJzZWQ6IHt9LCByYXc6IHN0cmluZywgZm9ybWF0OiBzdHJpbmd9fVxuICAgICAqL1xuICAgICAgbWV0YWRhdGEgPSB7XG4gICAgICAgIHBhcnNlZDoge30sXG4gICAgICAgIHJhdzogJycsXG4gICAgICAgIGZvcm1hdDogJydcbiAgICAgIH07XG5cbiAgX2NvbnN0cnVjdG9yKCk7XG5cbiAgLyoqXG4gICAqIENvbnZlcnRlciBjb25zdHJ1Y3RvclxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgZnVuY3Rpb24gX2NvbnN0cnVjdG9yICgpIHtcbiAgICBjb252ZXJ0ZXJPcHRpb25zID0gY29udmVydGVyT3B0aW9ucyB8fCB7fTtcblxuICAgIGZvciAodmFyIGdPcHQgaW4gZ2xvYmFsT3B0aW9ucykge1xuICAgICAgaWYgKGdsb2JhbE9wdGlvbnMuaGFzT3duUHJvcGVydHkoZ09wdCkpIHtcbiAgICAgICAgb3B0aW9uc1tnT3B0XSA9IGdsb2JhbE9wdGlvbnNbZ09wdF07XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gTWVyZ2Ugb3B0aW9uc1xuICAgIGlmICh0eXBlb2YgY29udmVydGVyT3B0aW9ucyA9PT0gJ29iamVjdCcpIHtcbiAgICAgIGZvciAodmFyIG9wdCBpbiBjb252ZXJ0ZXJPcHRpb25zKSB7XG4gICAgICAgIGlmIChjb252ZXJ0ZXJPcHRpb25zLmhhc093blByb3BlcnR5KG9wdCkpIHtcbiAgICAgICAgICBvcHRpb25zW29wdF0gPSBjb252ZXJ0ZXJPcHRpb25zW29wdF07XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgRXJyb3IoJ0NvbnZlcnRlciBleHBlY3RzIHRoZSBwYXNzZWQgcGFyYW1ldGVyIHRvIGJlIGFuIG9iamVjdCwgYnV0ICcgKyB0eXBlb2YgY29udmVydGVyT3B0aW9ucyArXG4gICAgICAnIHdhcyBwYXNzZWQgaW5zdGVhZC4nKTtcbiAgICB9XG5cbiAgICBpZiAob3B0aW9ucy5leHRlbnNpb25zKSB7XG4gICAgICBzaG93ZG93bi5oZWxwZXIuZm9yRWFjaChvcHRpb25zLmV4dGVuc2lvbnMsIF9wYXJzZUV4dGVuc2lvbik7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFBhcnNlIGV4dGVuc2lvblxuICAgKiBAcGFyYW0geyp9IGV4dFxuICAgKiBAcGFyYW0ge3N0cmluZ30gW25hbWU9JyddXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBmdW5jdGlvbiBfcGFyc2VFeHRlbnNpb24gKGV4dCwgbmFtZSkge1xuXG4gICAgbmFtZSA9IG5hbWUgfHwgbnVsbDtcbiAgICAvLyBJZiBpdCdzIGEgc3RyaW5nLCB0aGUgZXh0ZW5zaW9uIHdhcyBwcmV2aW91c2x5IGxvYWRlZFxuICAgIGlmIChzaG93ZG93bi5oZWxwZXIuaXNTdHJpbmcoZXh0KSkge1xuICAgICAgZXh0ID0gc2hvd2Rvd24uaGVscGVyLnN0ZEV4dE5hbWUoZXh0KTtcbiAgICAgIG5hbWUgPSBleHQ7XG5cbiAgICAgIC8vIExFR0FDWV9TVVBQT1JUIENPREVcbiAgICAgIGlmIChzaG93ZG93bi5leHRlbnNpb25zW2V4dF0pIHtcbiAgICAgICAgY29uc29sZS53YXJuKCdERVBSRUNBVElPTiBXQVJOSU5HOiAnICsgZXh0ICsgJyBpcyBhbiBvbGQgZXh0ZW5zaW9uIHRoYXQgdXNlcyBhIGRlcHJlY2F0ZWQgbG9hZGluZyBtZXRob2QuJyArXG4gICAgICAgICAgJ1BsZWFzZSBpbmZvcm0gdGhlIGRldmVsb3BlciB0aGF0IHRoZSBleHRlbnNpb24gc2hvdWxkIGJlIHVwZGF0ZWQhJyk7XG4gICAgICAgIGxlZ2FjeUV4dGVuc2lvbkxvYWRpbmcoc2hvd2Rvd24uZXh0ZW5zaW9uc1tleHRdLCBleHQpO1xuICAgICAgICByZXR1cm47XG4gICAgICAvLyBFTkQgTEVHQUNZIFNVUFBPUlQgQ09ERVxuXG4gICAgICB9IGVsc2UgaWYgKCFzaG93ZG93bi5oZWxwZXIuaXNVbmRlZmluZWQoZXh0ZW5zaW9uc1tleHRdKSkge1xuICAgICAgICBleHQgPSBleHRlbnNpb25zW2V4dF07XG5cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IEVycm9yKCdFeHRlbnNpb24gXCInICsgZXh0ICsgJ1wiIGNvdWxkIG5vdCBiZSBsb2FkZWQuIEl0IHdhcyBlaXRoZXIgbm90IGZvdW5kIG9yIGlzIG5vdCBhIHZhbGlkIGV4dGVuc2lvbi4nKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAodHlwZW9mIGV4dCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgZXh0ID0gZXh0KCk7XG4gICAgfVxuXG4gICAgaWYgKCFzaG93ZG93bi5oZWxwZXIuaXNBcnJheShleHQpKSB7XG4gICAgICBleHQgPSBbZXh0XTtcbiAgICB9XG5cbiAgICB2YXIgdmFsaWRFeHQgPSB2YWxpZGF0ZShleHQsIG5hbWUpO1xuICAgIGlmICghdmFsaWRFeHQudmFsaWQpIHtcbiAgICAgIHRocm93IEVycm9yKHZhbGlkRXh0LmVycm9yKTtcbiAgICB9XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGV4dC5sZW5ndGg7ICsraSkge1xuICAgICAgc3dpdGNoIChleHRbaV0udHlwZSkge1xuXG4gICAgICAgIGNhc2UgJ2xhbmcnOlxuICAgICAgICAgIGxhbmdFeHRlbnNpb25zLnB1c2goZXh0W2ldKTtcbiAgICAgICAgICBicmVhaztcblxuICAgICAgICBjYXNlICdvdXRwdXQnOlxuICAgICAgICAgIG91dHB1dE1vZGlmaWVycy5wdXNoKGV4dFtpXSk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICBpZiAoZXh0W2ldLmhhc093blByb3BlcnR5KCdsaXN0ZW5lcnMnKSkge1xuICAgICAgICBmb3IgKHZhciBsbiBpbiBleHRbaV0ubGlzdGVuZXJzKSB7XG4gICAgICAgICAgaWYgKGV4dFtpXS5saXN0ZW5lcnMuaGFzT3duUHJvcGVydHkobG4pKSB7XG4gICAgICAgICAgICBsaXN0ZW4obG4sIGV4dFtpXS5saXN0ZW5lcnNbbG5dKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgfVxuXG4gIC8qKlxuICAgKiBMRUdBQ1lfU1VQUE9SVFxuICAgKiBAcGFyYW0geyp9IGV4dFxuICAgKiBAcGFyYW0ge3N0cmluZ30gbmFtZVxuICAgKi9cbiAgZnVuY3Rpb24gbGVnYWN5RXh0ZW5zaW9uTG9hZGluZyAoZXh0LCBuYW1lKSB7XG4gICAgaWYgKHR5cGVvZiBleHQgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgIGV4dCA9IGV4dChuZXcgc2hvd2Rvd24uQ29udmVydGVyKCkpO1xuICAgIH1cbiAgICBpZiAoIXNob3dkb3duLmhlbHBlci5pc0FycmF5KGV4dCkpIHtcbiAgICAgIGV4dCA9IFtleHRdO1xuICAgIH1cbiAgICB2YXIgdmFsaWQgPSB2YWxpZGF0ZShleHQsIG5hbWUpO1xuXG4gICAgaWYgKCF2YWxpZC52YWxpZCkge1xuICAgICAgdGhyb3cgRXJyb3IodmFsaWQuZXJyb3IpO1xuICAgIH1cblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZXh0Lmxlbmd0aDsgKytpKSB7XG4gICAgICBzd2l0Y2ggKGV4dFtpXS50eXBlKSB7XG4gICAgICAgIGNhc2UgJ2xhbmcnOlxuICAgICAgICAgIGxhbmdFeHRlbnNpb25zLnB1c2goZXh0W2ldKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnb3V0cHV0JzpcbiAgICAgICAgICBvdXRwdXRNb2RpZmllcnMucHVzaChleHRbaV0pO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBkZWZhdWx0Oi8vIHNob3VsZCBuZXZlciByZWFjaCBoZXJlXG4gICAgICAgICAgdGhyb3cgRXJyb3IoJ0V4dGVuc2lvbiBsb2FkZXIgZXJyb3I6IFR5cGUgdW5yZWNvZ25pemVkISEhJyk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIExpc3RlbiB0byBhbiBldmVudFxuICAgKiBAcGFyYW0ge3N0cmluZ30gbmFtZVxuICAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBjYWxsYmFja1xuICAgKi9cbiAgZnVuY3Rpb24gbGlzdGVuIChuYW1lLCBjYWxsYmFjaykge1xuICAgIGlmICghc2hvd2Rvd24uaGVscGVyLmlzU3RyaW5nKG5hbWUpKSB7XG4gICAgICB0aHJvdyBFcnJvcignSW52YWxpZCBhcmd1bWVudCBpbiBjb252ZXJ0ZXIubGlzdGVuKCkgbWV0aG9kOiBuYW1lIG11c3QgYmUgYSBzdHJpbmcsIGJ1dCAnICsgdHlwZW9mIG5hbWUgKyAnIGdpdmVuJyk7XG4gICAgfVxuXG4gICAgaWYgKHR5cGVvZiBjYWxsYmFjayAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgdGhyb3cgRXJyb3IoJ0ludmFsaWQgYXJndW1lbnQgaW4gY29udmVydGVyLmxpc3RlbigpIG1ldGhvZDogY2FsbGJhY2sgbXVzdCBiZSBhIGZ1bmN0aW9uLCBidXQgJyArIHR5cGVvZiBjYWxsYmFjayArICcgZ2l2ZW4nKTtcbiAgICB9XG5cbiAgICBpZiAoIWxpc3RlbmVycy5oYXNPd25Qcm9wZXJ0eShuYW1lKSkge1xuICAgICAgbGlzdGVuZXJzW25hbWVdID0gW107XG4gICAgfVxuICAgIGxpc3RlbmVyc1tuYW1lXS5wdXNoKGNhbGxiYWNrKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHJUcmltSW5wdXRUZXh0ICh0ZXh0KSB7XG4gICAgdmFyIHJzcCA9IHRleHQubWF0Y2goL15cXHMqLylbMF0ubGVuZ3RoLFxuICAgICAgICByZ3ggPSBuZXcgUmVnRXhwKCdeXFxcXHN7MCwnICsgcnNwICsgJ30nLCAnZ20nKTtcbiAgICByZXR1cm4gdGV4dC5yZXBsYWNlKHJneCwgJycpO1xuICB9XG5cbiAgLyoqXG4gICAqIERpc3BhdGNoIGFuIGV2ZW50XG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBldnROYW1lIEV2ZW50IG5hbWVcbiAgICogQHBhcmFtIHtzdHJpbmd9IHRleHQgVGV4dFxuICAgKiBAcGFyYW0ge3t9fSBvcHRpb25zIENvbnZlcnRlciBPcHRpb25zXG4gICAqIEBwYXJhbSB7e319IGdsb2JhbHNcbiAgICogQHJldHVybnMge3N0cmluZ31cbiAgICovXG4gIHRoaXMuX2Rpc3BhdGNoID0gZnVuY3Rpb24gZGlzcGF0Y2ggKGV2dE5hbWUsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpIHtcbiAgICBpZiAobGlzdGVuZXJzLmhhc093blByb3BlcnR5KGV2dE5hbWUpKSB7XG4gICAgICBmb3IgKHZhciBlaSA9IDA7IGVpIDwgbGlzdGVuZXJzW2V2dE5hbWVdLmxlbmd0aDsgKytlaSkge1xuICAgICAgICB2YXIgblRleHQgPSBsaXN0ZW5lcnNbZXZ0TmFtZV1bZWldKGV2dE5hbWUsIHRleHQsIHRoaXMsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICAgICAgICBpZiAoblRleHQgJiYgdHlwZW9mIG5UZXh0ICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgIHRleHQgPSBuVGV4dDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdGV4dDtcbiAgfTtcblxuICAvKipcbiAgICogTGlzdGVuIHRvIGFuIGV2ZW50XG4gICAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lXG4gICAqIEBwYXJhbSB7ZnVuY3Rpb259IGNhbGxiYWNrXG4gICAqIEByZXR1cm5zIHtzaG93ZG93bi5Db252ZXJ0ZXJ9XG4gICAqL1xuICB0aGlzLmxpc3RlbiA9IGZ1bmN0aW9uIChuYW1lLCBjYWxsYmFjaykge1xuICAgIGxpc3RlbihuYW1lLCBjYWxsYmFjayk7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH07XG5cbiAgLyoqXG4gICAqIENvbnZlcnRzIGEgbWFya2Rvd24gc3RyaW5nIGludG8gSFRNTFxuICAgKiBAcGFyYW0ge3N0cmluZ30gdGV4dFxuICAgKiBAcmV0dXJucyB7Kn1cbiAgICovXG4gIHRoaXMubWFrZUh0bWwgPSBmdW5jdGlvbiAodGV4dCkge1xuICAgIC8vY2hlY2sgaWYgdGV4dCBpcyBub3QgZmFsc3lcbiAgICBpZiAoIXRleHQpIHtcbiAgICAgIHJldHVybiB0ZXh0O1xuICAgIH1cblxuICAgIHZhciBnbG9iYWxzID0ge1xuICAgICAgZ0h0bWxCbG9ja3M6ICAgICBbXSxcbiAgICAgIGdIdG1sTWRCbG9ja3M6ICAgW10sXG4gICAgICBnSHRtbFNwYW5zOiAgICAgIFtdLFxuICAgICAgZ1VybHM6ICAgICAgICAgICB7fSxcbiAgICAgIGdUaXRsZXM6ICAgICAgICAge30sXG4gICAgICBnRGltZW5zaW9uczogICAgIHt9LFxuICAgICAgZ0xpc3RMZXZlbDogICAgICAwLFxuICAgICAgaGFzaExpbmtDb3VudHM6ICB7fSxcbiAgICAgIGxhbmdFeHRlbnNpb25zOiAgbGFuZ0V4dGVuc2lvbnMsXG4gICAgICBvdXRwdXRNb2RpZmllcnM6IG91dHB1dE1vZGlmaWVycyxcbiAgICAgIGNvbnZlcnRlcjogICAgICAgdGhpcyxcbiAgICAgIGdoQ29kZUJsb2NrczogICAgW10sXG4gICAgICBtZXRhZGF0YToge1xuICAgICAgICBwYXJzZWQ6IHt9LFxuICAgICAgICByYXc6ICcnLFxuICAgICAgICBmb3JtYXQ6ICcnXG4gICAgICB9XG4gICAgfTtcblxuICAgIC8vIFRoaXMgbGV0cyB1cyB1c2UgwqggdHJlbWEgYXMgYW4gZXNjYXBlIGNoYXIgdG8gYXZvaWQgbWQ1IGhhc2hlc1xuICAgIC8vIFRoZSBjaG9pY2Ugb2YgY2hhcmFjdGVyIGlzIGFyYml0cmFyeTsgYW55dGhpbmcgdGhhdCBpc24ndFxuICAgIC8vIG1hZ2ljIGluIE1hcmtkb3duIHdpbGwgd29yay5cbiAgICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC/CqC9nLCAnwqhUJyk7XG5cbiAgICAvLyBSZXBsYWNlICQgd2l0aCDCqERcbiAgICAvLyBSZWdFeHAgaW50ZXJwcmV0cyAkIGFzIGEgc3BlY2lhbCBjaGFyYWN0ZXJcbiAgICAvLyB3aGVuIGl0J3MgaW4gYSByZXBsYWNlbWVudCBzdHJpbmdcbiAgICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC9cXCQvZywgJ8KoRCcpO1xuXG4gICAgLy8gU3RhbmRhcmRpemUgbGluZSBlbmRpbmdzXG4gICAgdGV4dCA9IHRleHQucmVwbGFjZSgvXFxyXFxuL2csICdcXG4nKTsgLy8gRE9TIHRvIFVuaXhcbiAgICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC9cXHIvZywgJ1xcbicpOyAvLyBNYWMgdG8gVW5peFxuXG4gICAgLy8gU3RhcmRhcmRpemUgbGluZSBzcGFjZXMgKG5ic3AgY2F1c2VzIHRyb3VibGUgaW4gb2xkZXIgYnJvd3NlcnMgYW5kIHNvbWUgcmVnZXggZmxhdm9ycylcbiAgICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC9cXHUwMEEwL2csICcgJyk7XG5cbiAgICBpZiAob3B0aW9ucy5zbWFydEluZGVudGF0aW9uRml4KSB7XG4gICAgICB0ZXh0ID0gclRyaW1JbnB1dFRleHQodGV4dCk7XG4gICAgfVxuXG4gICAgLy8gTWFrZSBzdXJlIHRleHQgYmVnaW5zIGFuZCBlbmRzIHdpdGggYSBjb3VwbGUgb2YgbmV3bGluZXM6XG4gICAgdGV4dCA9ICdcXG5cXG4nICsgdGV4dCArICdcXG5cXG4nO1xuXG4gICAgLy8gZGV0YWJcbiAgICB0ZXh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdkZXRhYicpKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuXG4gICAgLyoqXG4gICAgICogU3RyaXAgYW55IGxpbmVzIGNvbnNpc3Rpbmcgb25seSBvZiBzcGFjZXMgYW5kIHRhYnMuXG4gICAgICogVGhpcyBtYWtlcyBzdWJzZXF1ZW50IHJlZ2V4cyBlYXNpZXIgdG8gd3JpdGUsIGJlY2F1c2Ugd2UgY2FuXG4gICAgICogbWF0Y2ggY29uc2VjdXRpdmUgYmxhbmsgbGluZXMgd2l0aCAvXFxuKy8gaW5zdGVhZCBvZiBzb21ldGhpbmdcbiAgICAgKiBjb250b3J0ZWQgbGlrZSAvWyBcXHRdKlxcbisvXG4gICAgICovXG4gICAgdGV4dCA9IHRleHQucmVwbGFjZSgvXlsgXFx0XSskL21nLCAnJyk7XG5cbiAgICAvL3J1biBsYW5ndWFnZUV4dGVuc2lvbnNcbiAgICBzaG93ZG93bi5oZWxwZXIuZm9yRWFjaChsYW5nRXh0ZW5zaW9ucywgZnVuY3Rpb24gKGV4dCkge1xuICAgICAgdGV4dCA9IHNob3dkb3duLnN1YlBhcnNlcigncnVuRXh0ZW5zaW9uJykoZXh0LCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgICB9KTtcblxuICAgIC8vIHJ1biB0aGUgc3ViIHBhcnNlcnNcbiAgICB0ZXh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdtZXRhZGF0YScpKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICAgIHRleHQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ2hhc2hQcmVDb2RlVGFncycpKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICAgIHRleHQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ2dpdGh1YkNvZGVCbG9ja3MnKSh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgICB0ZXh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdoYXNoSFRNTEJsb2NrcycpKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICAgIHRleHQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ2hhc2hDb2RlVGFncycpKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICAgIHRleHQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ3N0cmlwTGlua0RlZmluaXRpb25zJykodGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gICAgdGV4dCA9IHNob3dkb3duLnN1YlBhcnNlcignYmxvY2tHYW11dCcpKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICAgIHRleHQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ3VuaGFzaEhUTUxTcGFucycpKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICAgIHRleHQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ3VuZXNjYXBlU3BlY2lhbENoYXJzJykodGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG5cbiAgICAvLyBhdHRhY2tsYWI6IFJlc3RvcmUgZG9sbGFyIHNpZ25zXG4gICAgdGV4dCA9IHRleHQucmVwbGFjZSgvwqhEL2csICckJCcpO1xuXG4gICAgLy8gYXR0YWNrbGFiOiBSZXN0b3JlIHRyZW1hc1xuICAgIHRleHQgPSB0ZXh0LnJlcGxhY2UoL8KoVC9nLCAnwqgnKTtcblxuICAgIC8vIHJlbmRlciBhIGNvbXBsZXRlIGh0bWwgZG9jdW1lbnQgaW5zdGVhZCBvZiBhIHBhcnRpYWwgaWYgdGhlIG9wdGlvbiBpcyBlbmFibGVkXG4gICAgdGV4dCA9IHNob3dkb3duLnN1YlBhcnNlcignY29tcGxldGVIVE1MRG9jdW1lbnQnKSh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcblxuICAgIC8vIFJ1biBvdXRwdXQgbW9kaWZpZXJzXG4gICAgc2hvd2Rvd24uaGVscGVyLmZvckVhY2gob3V0cHV0TW9kaWZpZXJzLCBmdW5jdGlvbiAoZXh0KSB7XG4gICAgICB0ZXh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdydW5FeHRlbnNpb24nKShleHQsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICAgIH0pO1xuXG4gICAgLy8gdXBkYXRlIG1ldGFkYXRhXG4gICAgbWV0YWRhdGEgPSBnbG9iYWxzLm1ldGFkYXRhO1xuICAgIHJldHVybiB0ZXh0O1xuICB9O1xuXG4gIC8qKlxuICAgKiBTZXQgYW4gb3B0aW9uIG9mIHRoaXMgQ29udmVydGVyIGluc3RhbmNlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBrZXlcbiAgICogQHBhcmFtIHsqfSB2YWx1ZVxuICAgKi9cbiAgdGhpcy5zZXRPcHRpb24gPSBmdW5jdGlvbiAoa2V5LCB2YWx1ZSkge1xuICAgIG9wdGlvbnNba2V5XSA9IHZhbHVlO1xuICB9O1xuXG4gIC8qKlxuICAgKiBHZXQgdGhlIG9wdGlvbiBvZiB0aGlzIENvbnZlcnRlciBpbnN0YW5jZVxuICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5XG4gICAqIEByZXR1cm5zIHsqfVxuICAgKi9cbiAgdGhpcy5nZXRPcHRpb24gPSBmdW5jdGlvbiAoa2V5KSB7XG4gICAgcmV0dXJuIG9wdGlvbnNba2V5XTtcbiAgfTtcblxuICAvKipcbiAgICogR2V0IHRoZSBvcHRpb25zIG9mIHRoaXMgQ29udmVydGVyIGluc3RhbmNlXG4gICAqIEByZXR1cm5zIHt7fX1cbiAgICovXG4gIHRoaXMuZ2V0T3B0aW9ucyA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gb3B0aW9ucztcbiAgfTtcblxuICAvKipcbiAgICogQWRkIGV4dGVuc2lvbiB0byBUSElTIGNvbnZlcnRlclxuICAgKiBAcGFyYW0ge3t9fSBleHRlbnNpb25cbiAgICogQHBhcmFtIHtzdHJpbmd9IFtuYW1lPW51bGxdXG4gICAqL1xuICB0aGlzLmFkZEV4dGVuc2lvbiA9IGZ1bmN0aW9uIChleHRlbnNpb24sIG5hbWUpIHtcbiAgICBuYW1lID0gbmFtZSB8fCBudWxsO1xuICAgIF9wYXJzZUV4dGVuc2lvbihleHRlbnNpb24sIG5hbWUpO1xuICB9O1xuXG4gIC8qKlxuICAgKiBVc2UgYSBnbG9iYWwgcmVnaXN0ZXJlZCBleHRlbnNpb24gd2l0aCBUSElTIGNvbnZlcnRlclxuICAgKiBAcGFyYW0ge3N0cmluZ30gZXh0ZW5zaW9uTmFtZSBOYW1lIG9mIHRoZSBwcmV2aW91c2x5IHJlZ2lzdGVyZWQgZXh0ZW5zaW9uXG4gICAqL1xuICB0aGlzLnVzZUV4dGVuc2lvbiA9IGZ1bmN0aW9uIChleHRlbnNpb25OYW1lKSB7XG4gICAgX3BhcnNlRXh0ZW5zaW9uKGV4dGVuc2lvbk5hbWUpO1xuICB9O1xuXG4gIC8qKlxuICAgKiBTZXQgdGhlIGZsYXZvciBUSElTIGNvbnZlcnRlciBzaG91bGQgdXNlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lXG4gICAqL1xuICB0aGlzLnNldEZsYXZvciA9IGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgaWYgKCFmbGF2b3IuaGFzT3duUHJvcGVydHkobmFtZSkpIHtcbiAgICAgIHRocm93IEVycm9yKG5hbWUgKyAnIGZsYXZvciB3YXMgbm90IGZvdW5kJyk7XG4gICAgfVxuICAgIHZhciBwcmVzZXQgPSBmbGF2b3JbbmFtZV07XG4gICAgc2V0Q29udkZsYXZvciA9IG5hbWU7XG4gICAgZm9yICh2YXIgb3B0aW9uIGluIHByZXNldCkge1xuICAgICAgaWYgKHByZXNldC5oYXNPd25Qcm9wZXJ0eShvcHRpb24pKSB7XG4gICAgICAgIG9wdGlvbnNbb3B0aW9uXSA9IHByZXNldFtvcHRpb25dO1xuICAgICAgfVxuICAgIH1cbiAgfTtcblxuICAvKipcbiAgICogR2V0IHRoZSBjdXJyZW50bHkgc2V0IGZsYXZvciBvZiB0aGlzIGNvbnZlcnRlclxuICAgKiBAcmV0dXJucyB7c3RyaW5nfVxuICAgKi9cbiAgdGhpcy5nZXRGbGF2b3IgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHNldENvbnZGbGF2b3I7XG4gIH07XG5cbiAgLyoqXG4gICAqIFJlbW92ZSBhbiBleHRlbnNpb24gZnJvbSBUSElTIGNvbnZlcnRlci5cbiAgICogTm90ZTogVGhpcyBpcyBhIGNvc3RseSBvcGVyYXRpb24uIEl0J3MgYmV0dGVyIHRvIGluaXRpYWxpemUgYSBuZXcgY29udmVydGVyXG4gICAqIGFuZCBzcGVjaWZ5IHRoZSBleHRlbnNpb25zIHlvdSB3aXNoIHRvIHVzZVxuICAgKiBAcGFyYW0ge0FycmF5fSBleHRlbnNpb25cbiAgICovXG4gIHRoaXMucmVtb3ZlRXh0ZW5zaW9uID0gZnVuY3Rpb24gKGV4dGVuc2lvbikge1xuICAgIGlmICghc2hvd2Rvd24uaGVscGVyLmlzQXJyYXkoZXh0ZW5zaW9uKSkge1xuICAgICAgZXh0ZW5zaW9uID0gW2V4dGVuc2lvbl07XG4gICAgfVxuICAgIGZvciAodmFyIGEgPSAwOyBhIDwgZXh0ZW5zaW9uLmxlbmd0aDsgKythKSB7XG4gICAgICB2YXIgZXh0ID0gZXh0ZW5zaW9uW2FdO1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsYW5nRXh0ZW5zaW9ucy5sZW5ndGg7ICsraSkge1xuICAgICAgICBpZiAobGFuZ0V4dGVuc2lvbnNbaV0gPT09IGV4dCkge1xuICAgICAgICAgIGxhbmdFeHRlbnNpb25zW2ldLnNwbGljZShpLCAxKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgZm9yICh2YXIgaWkgPSAwOyBpaSA8IG91dHB1dE1vZGlmaWVycy5sZW5ndGg7ICsraSkge1xuICAgICAgICBpZiAob3V0cHV0TW9kaWZpZXJzW2lpXSA9PT0gZXh0KSB7XG4gICAgICAgICAgb3V0cHV0TW9kaWZpZXJzW2lpXS5zcGxpY2UoaSwgMSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH07XG5cbiAgLyoqXG4gICAqIEdldCBhbGwgZXh0ZW5zaW9uIG9mIFRISVMgY29udmVydGVyXG4gICAqIEByZXR1cm5zIHt7bGFuZ3VhZ2U6IEFycmF5LCBvdXRwdXQ6IEFycmF5fX1cbiAgICovXG4gIHRoaXMuZ2V0QWxsRXh0ZW5zaW9ucyA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4ge1xuICAgICAgbGFuZ3VhZ2U6IGxhbmdFeHRlbnNpb25zLFxuICAgICAgb3V0cHV0OiBvdXRwdXRNb2RpZmllcnNcbiAgICB9O1xuICB9O1xuXG4gIC8qKlxuICAgKiBHZXQgdGhlIG1ldGFkYXRhIG9mIHRoZSBwcmV2aW91c2x5IHBhcnNlZCBkb2N1bWVudFxuICAgKiBAcGFyYW0gcmF3XG4gICAqIEByZXR1cm5zIHtzdHJpbmd8e319XG4gICAqL1xuICB0aGlzLmdldE1ldGFkYXRhID0gZnVuY3Rpb24gKHJhdykge1xuICAgIGlmIChyYXcpIHtcbiAgICAgIHJldHVybiBtZXRhZGF0YS5yYXc7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBtZXRhZGF0YS5wYXJzZWQ7XG4gICAgfVxuICB9O1xuXG4gIC8qKlxuICAgKiBHZXQgdGhlIG1ldGFkYXRhIGZvcm1hdCBvZiB0aGUgcHJldmlvdXNseSBwYXJzZWQgZG9jdW1lbnRcbiAgICogQHJldHVybnMge3N0cmluZ31cbiAgICovXG4gIHRoaXMuZ2V0TWV0YWRhdGFGb3JtYXQgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIG1ldGFkYXRhLmZvcm1hdDtcbiAgfTtcblxuICAvKipcbiAgICogUHJpdmF0ZTogc2V0IGEgc2luZ2xlIGtleSwgdmFsdWUgbWV0YWRhdGEgcGFpclxuICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5XG4gICAqIEBwYXJhbSB7c3RyaW5nfSB2YWx1ZVxuICAgKi9cbiAgdGhpcy5fc2V0TWV0YWRhdGFQYWlyID0gZnVuY3Rpb24gKGtleSwgdmFsdWUpIHtcbiAgICBtZXRhZGF0YS5wYXJzZWRba2V5XSA9IHZhbHVlO1xuICB9O1xuXG4gIC8qKlxuICAgKiBQcml2YXRlOiBzZXQgbWV0YWRhdGEgZm9ybWF0XG4gICAqIEBwYXJhbSB7c3RyaW5nfSBmb3JtYXRcbiAgICovXG4gIHRoaXMuX3NldE1ldGFkYXRhRm9ybWF0ID0gZnVuY3Rpb24gKGZvcm1hdCkge1xuICAgIG1ldGFkYXRhLmZvcm1hdCA9IGZvcm1hdDtcbiAgfTtcblxuICAvKipcbiAgICogUHJpdmF0ZTogc2V0IG1ldGFkYXRhIHJhdyB0ZXh0XG4gICAqIEBwYXJhbSB7c3RyaW5nfSByYXdcbiAgICovXG4gIHRoaXMuX3NldE1ldGFkYXRhUmF3ID0gZnVuY3Rpb24gKHJhdykge1xuICAgIG1ldGFkYXRhLnJhdyA9IHJhdztcbiAgfTtcbn07XG5cclxuLyoqXG4gKiBUdXJuIE1hcmtkb3duIGxpbmsgc2hvcnRjdXRzIGludG8gWEhUTUwgPGE+IHRhZ3MuXG4gKi9cbnNob3dkb3duLnN1YlBhcnNlcignYW5jaG9ycycsIGZ1bmN0aW9uICh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCdhbmNob3JzLmJlZm9yZScsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuXG4gIHZhciB3cml0ZUFuY2hvclRhZyA9IGZ1bmN0aW9uICh3aG9sZU1hdGNoLCBsaW5rVGV4dCwgbGlua0lkLCB1cmwsIG01LCBtNiwgdGl0bGUpIHtcbiAgICBpZiAoc2hvd2Rvd24uaGVscGVyLmlzVW5kZWZpbmVkKHRpdGxlKSkge1xuICAgICAgdGl0bGUgPSAnJztcbiAgICB9XG4gICAgbGlua0lkID0gbGlua0lkLnRvTG93ZXJDYXNlKCk7XG5cbiAgICAvLyBTcGVjaWFsIGNhc2UgZm9yIGV4cGxpY2l0IGVtcHR5IHVybFxuICAgIGlmICh3aG9sZU1hdGNoLnNlYXJjaCgvXFwoPD9cXHMqPj8gPyhbJ1wiXS4qWydcIl0pP1xcKSQvbSkgPiAtMSkge1xuICAgICAgdXJsID0gJyc7XG4gICAgfSBlbHNlIGlmICghdXJsKSB7XG4gICAgICBpZiAoIWxpbmtJZCkge1xuICAgICAgICAvLyBsb3dlci1jYXNlIGFuZCB0dXJuIGVtYmVkZGVkIG5ld2xpbmVzIGludG8gc3BhY2VzXG4gICAgICAgIGxpbmtJZCA9IGxpbmtUZXh0LnRvTG93ZXJDYXNlKCkucmVwbGFjZSgvID9cXG4vZywgJyAnKTtcbiAgICAgIH1cbiAgICAgIHVybCA9ICcjJyArIGxpbmtJZDtcblxuICAgICAgaWYgKCFzaG93ZG93bi5oZWxwZXIuaXNVbmRlZmluZWQoZ2xvYmFscy5nVXJsc1tsaW5rSWRdKSkge1xuICAgICAgICB1cmwgPSBnbG9iYWxzLmdVcmxzW2xpbmtJZF07XG4gICAgICAgIGlmICghc2hvd2Rvd24uaGVscGVyLmlzVW5kZWZpbmVkKGdsb2JhbHMuZ1RpdGxlc1tsaW5rSWRdKSkge1xuICAgICAgICAgIHRpdGxlID0gZ2xvYmFscy5nVGl0bGVzW2xpbmtJZF07XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiB3aG9sZU1hdGNoO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vdXJsID0gc2hvd2Rvd24uaGVscGVyLmVzY2FwZUNoYXJhY3RlcnModXJsLCAnKl8nLCBmYWxzZSk7IC8vIHJlcGxhY2VkIGxpbmUgdG8gaW1wcm92ZSBwZXJmb3JtYW5jZVxuICAgIHVybCA9IHVybC5yZXBsYWNlKHNob3dkb3duLmhlbHBlci5yZWdleGVzLmFzdGVyaXNrRGFzaEFuZENvbG9uLCBzaG93ZG93bi5oZWxwZXIuZXNjYXBlQ2hhcmFjdGVyc0NhbGxiYWNrKTtcblxuICAgIHZhciByZXN1bHQgPSAnPGEgaHJlZj1cIicgKyB1cmwgKyAnXCInO1xuXG4gICAgaWYgKHRpdGxlICE9PSAnJyAmJiB0aXRsZSAhPT0gbnVsbCkge1xuICAgICAgdGl0bGUgPSB0aXRsZS5yZXBsYWNlKC9cIi9nLCAnJnF1b3Q7Jyk7XG4gICAgICAvL3RpdGxlID0gc2hvd2Rvd24uaGVscGVyLmVzY2FwZUNoYXJhY3RlcnModGl0bGUsICcqXycsIGZhbHNlKTsgLy8gcmVwbGFjZWQgbGluZSB0byBpbXByb3ZlIHBlcmZvcm1hbmNlXG4gICAgICB0aXRsZSA9IHRpdGxlLnJlcGxhY2Uoc2hvd2Rvd24uaGVscGVyLnJlZ2V4ZXMuYXN0ZXJpc2tEYXNoQW5kQ29sb24sIHNob3dkb3duLmhlbHBlci5lc2NhcGVDaGFyYWN0ZXJzQ2FsbGJhY2spO1xuICAgICAgcmVzdWx0ICs9ICcgdGl0bGU9XCInICsgdGl0bGUgKyAnXCInO1xuICAgIH1cblxuICAgIC8vIG9wdGlvbkxpbmtzSW5OZXdXaW5kb3cgb25seSBhcHBsaWVzXG4gICAgLy8gdG8gZXh0ZXJuYWwgbGlua3MuIEhhc2ggbGlua3MgKCMpIG9wZW4gaW4gc2FtZSBwYWdlXG4gICAgaWYgKG9wdGlvbnMub3BlbkxpbmtzSW5OZXdXaW5kb3cgJiYgIS9eIy8udGVzdCh1cmwpKSB7XG4gICAgICAvLyBlc2NhcGVkIF9cbiAgICAgIHJlc3VsdCArPSAnIHRhcmdldD1cIsKoRTk1RWJsYW5rXCInO1xuICAgIH1cblxuICAgIHJlc3VsdCArPSAnPicgKyBsaW5rVGV4dCArICc8L2E+JztcblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH07XG5cbiAgLy8gRmlyc3QsIGhhbmRsZSByZWZlcmVuY2Utc3R5bGUgbGlua3M6IFtsaW5rIHRleHRdIFtpZF1cbiAgdGV4dCA9IHRleHQucmVwbGFjZSgvXFxbKCg/OlxcW1teXFxdXSpdfFteXFxbXFxdXSkqKV0gPyg/OlxcbiAqKT9cXFsoLio/KV0oKSgpKCkoKS9nLCB3cml0ZUFuY2hvclRhZyk7XG5cbiAgLy8gTmV4dCwgaW5saW5lLXN0eWxlIGxpbmtzOiBbbGluayB0ZXh0XSh1cmwgXCJvcHRpb25hbCB0aXRsZVwiKVxuICAvLyBjYXNlcyB3aXRoIGNyYXp5IHVybHMgbGlrZSAuL2ltYWdlL2NhdDEpLnBuZ1xuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC9cXFsoKD86XFxbW15cXF1dKl18W15cXFtcXF1dKSopXSgpWyBcXHRdKlxcKFsgXFx0XT88KFtePl0qKT4oPzpbIFxcdF0qKChbXCInXSkoW15cIl0qPylcXDUpKT9bIFxcdF0/XFwpL2csXG4gICAgd3JpdGVBbmNob3JUYWcpO1xuXG4gIC8vIG5vcm1hbCBjYXNlc1xuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC9cXFsoKD86XFxbW15cXF1dKl18W15cXFtcXF1dKSopXSgpWyBcXHRdKlxcKFsgXFx0XT88PyhbXFxTXSs/KD86XFwoW1xcU10qP1xcKVtcXFNdKj8pPyk+Pyg/OlsgXFx0XSooKFtcIiddKShbXlwiXSo/KVxcNSkpP1sgXFx0XT9cXCkvZyxcbiAgICAgICAgICAgICAgICAgICAgICB3cml0ZUFuY2hvclRhZyk7XG5cbiAgLy8gaGFuZGxlIHJlZmVyZW5jZS1zdHlsZSBzaG9ydGN1dHM6IFtsaW5rIHRleHRdXG4gIC8vIFRoZXNlIG11c3QgY29tZSBsYXN0IGluIGNhc2UgeW91J3ZlIGFsc28gZ290IFtsaW5rIHRlc3RdWzFdXG4gIC8vIG9yIFtsaW5rIHRlc3RdKC9mb28pXG4gIHRleHQgPSB0ZXh0LnJlcGxhY2UoL1xcWyhbXlxcW1xcXV0rKV0oKSgpKCkoKSgpL2csIHdyaXRlQW5jaG9yVGFnKTtcblxuICAvLyBMYXN0bHkgaGFuZGxlIEdpdGh1Yk1lbnRpb25zIGlmIG9wdGlvbiBpcyBlbmFibGVkXG4gIGlmIChvcHRpb25zLmdoTWVudGlvbnMpIHtcbiAgICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC8oXnxcXHMpKFxcXFwpPyhAKFthLXpcXGRcXC1dKykpKD89Wy4hPzssW1xcXSgpXXxcXHN8JCkvZ21pLCBmdW5jdGlvbiAod20sIHN0LCBlc2NhcGUsIG1lbnRpb25zLCB1c2VybmFtZSkge1xuICAgICAgaWYgKGVzY2FwZSA9PT0gJ1xcXFwnKSB7XG4gICAgICAgIHJldHVybiBzdCArIG1lbnRpb25zO1xuICAgICAgfVxuXG4gICAgICAvL2NoZWNrIGlmIG9wdGlvbnMuZ2hNZW50aW9uc0xpbmsgaXMgYSBzdHJpbmdcbiAgICAgIGlmICghc2hvd2Rvd24uaGVscGVyLmlzU3RyaW5nKG9wdGlvbnMuZ2hNZW50aW9uc0xpbmspKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignZ2hNZW50aW9uc0xpbmsgb3B0aW9uIG11c3QgYmUgYSBzdHJpbmcnKTtcbiAgICAgIH1cbiAgICAgIHZhciBsbmsgPSBvcHRpb25zLmdoTWVudGlvbnNMaW5rLnJlcGxhY2UoL1xce3V9L2csIHVzZXJuYW1lKSxcbiAgICAgICAgICB0YXJnZXQgPSAnJztcbiAgICAgIGlmIChvcHRpb25zLm9wZW5MaW5rc0luTmV3V2luZG93KSB7XG4gICAgICAgIHRhcmdldCA9ICcgdGFyZ2V0PVwiwqhFOTVFYmxhbmtcIic7XG4gICAgICB9XG4gICAgICByZXR1cm4gc3QgKyAnPGEgaHJlZj1cIicgKyBsbmsgKyAnXCInICsgdGFyZ2V0ICsgJz4nICsgbWVudGlvbnMgKyAnPC9hPic7XG4gICAgfSk7XG4gIH1cblxuICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCdhbmNob3JzLmFmdGVyJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gIHJldHVybiB0ZXh0O1xufSk7XG5cclxuLy8gdXJsIGFsbG93ZWQgY2hhcnMgW2EtelxcZF8ufjovPyNbXUAhJCYnKCkqKyw7PS1dXG5cbnZhciBzaW1wbGVVUkxSZWdleCAgPSAvKFsqfl9dK3xcXGIpKCgoaHR0cHM/fGZ0cHxkaWN0KTpcXC9cXC98d3d3XFwuKVteJ1wiPlxcc10rP1xcLlteJ1wiPlxcc10rPykoKShcXDEpPyg/PVxcc3wkKSg/IVtcIjw+XSkvZ2ksXG4gICAgc2ltcGxlVVJMUmVnZXgyID0gLyhbKn5fXSt8XFxiKSgoKGh0dHBzP3xmdHB8ZGljdCk6XFwvXFwvfHd3d1xcLilbXidcIj5cXHNdK1xcLlteJ1wiPlxcc10rPykoWy4hPywoKVxcW1xcXV0pPyhcXDEpPyg/PVxcc3wkKSg/IVtcIjw+XSkvZ2ksXG4gICAgZGVsaW1VcmxSZWdleCAgID0gLygpPCgoKGh0dHBzP3xmdHB8ZGljdCk6XFwvXFwvfHd3d1xcLilbXidcIj5cXHNdKykoKT4oKS9naSxcbiAgICBzaW1wbGVNYWlsUmVnZXggPSAvKF58XFxzKSg/Om1haWx0bzopPyhbQS1aYS16MC05ISMkJSYnKistLz0/Xl9ge3x9fi5dK0BbLWEtejAtOV0rKFxcLlstYS16MC05XSspKlxcLlthLXpdKykoPz0kfFxccykvZ21pLFxuICAgIGRlbGltTWFpbFJlZ2V4ICA9IC88KCkoPzptYWlsdG86KT8oWy0uXFx3XStAWy1hLXowLTldKyhcXC5bLWEtejAtOV0rKSpcXC5bYS16XSspPi9naSxcblxuICAgIHJlcGxhY2VMaW5rID0gZnVuY3Rpb24gKG9wdGlvbnMpIHtcbiAgICAgICd1c2Ugc3RyaWN0JztcbiAgICAgIHJldHVybiBmdW5jdGlvbiAod20sIGxlYWRpbmdNYWdpY0NoYXJzLCBsaW5rLCBtMiwgbTMsIHRyYWlsaW5nUHVuY3R1YXRpb24sIHRyYWlsaW5nTWFnaWNDaGFycykge1xuICAgICAgICBsaW5rID0gbGluay5yZXBsYWNlKHNob3dkb3duLmhlbHBlci5yZWdleGVzLmFzdGVyaXNrRGFzaEFuZENvbG9uLCBzaG93ZG93bi5oZWxwZXIuZXNjYXBlQ2hhcmFjdGVyc0NhbGxiYWNrKTtcbiAgICAgICAgdmFyIGxua1R4dCA9IGxpbmssXG4gICAgICAgICAgICBhcHBlbmQgPSAnJyxcbiAgICAgICAgICAgIHRhcmdldCA9ICcnLFxuICAgICAgICAgICAgbG1jICAgID0gbGVhZGluZ01hZ2ljQ2hhcnMgfHwgJycsXG4gICAgICAgICAgICB0bWMgICAgPSB0cmFpbGluZ01hZ2ljQ2hhcnMgfHwgJyc7XG4gICAgICAgIGlmICgvXnd3d1xcLi9pLnRlc3QobGluaykpIHtcbiAgICAgICAgICBsaW5rID0gbGluay5yZXBsYWNlKC9ed3d3XFwuL2ksICdodHRwOi8vd3d3LicpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChvcHRpb25zLmV4Y2x1ZGVUcmFpbGluZ1B1bmN0dWF0aW9uRnJvbVVSTHMgJiYgdHJhaWxpbmdQdW5jdHVhdGlvbikge1xuICAgICAgICAgIGFwcGVuZCA9IHRyYWlsaW5nUHVuY3R1YXRpb247XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG9wdGlvbnMub3BlbkxpbmtzSW5OZXdXaW5kb3cpIHtcbiAgICAgICAgICB0YXJnZXQgPSAnIHRhcmdldD1cIsKoRTk1RWJsYW5rXCInO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBsbWMgKyAnPGEgaHJlZj1cIicgKyBsaW5rICsgJ1wiJyArIHRhcmdldCArICc+JyArIGxua1R4dCArICc8L2E+JyArIGFwcGVuZCArIHRtYztcbiAgICAgIH07XG4gICAgfSxcblxuICAgIHJlcGxhY2VNYWlsID0gZnVuY3Rpb24gKG9wdGlvbnMsIGdsb2JhbHMpIHtcbiAgICAgICd1c2Ugc3RyaWN0JztcbiAgICAgIHJldHVybiBmdW5jdGlvbiAod2hvbGVNYXRjaCwgYiwgbWFpbCkge1xuICAgICAgICB2YXIgaHJlZiA9ICdtYWlsdG86JztcbiAgICAgICAgYiA9IGIgfHwgJyc7XG4gICAgICAgIG1haWwgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ3VuZXNjYXBlU3BlY2lhbENoYXJzJykobWFpbCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gICAgICAgIGlmIChvcHRpb25zLmVuY29kZUVtYWlscykge1xuICAgICAgICAgIGhyZWYgPSBzaG93ZG93bi5oZWxwZXIuZW5jb2RlRW1haWxBZGRyZXNzKGhyZWYgKyBtYWlsKTtcbiAgICAgICAgICBtYWlsID0gc2hvd2Rvd24uaGVscGVyLmVuY29kZUVtYWlsQWRkcmVzcyhtYWlsKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBocmVmID0gaHJlZiArIG1haWw7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGIgKyAnPGEgaHJlZj1cIicgKyBocmVmICsgJ1wiPicgKyBtYWlsICsgJzwvYT4nO1xuICAgICAgfTtcbiAgICB9O1xuXG5zaG93ZG93bi5zdWJQYXJzZXIoJ2F1dG9MaW5rcycsIGZ1bmN0aW9uICh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCdhdXRvTGlua3MuYmVmb3JlJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG5cbiAgdGV4dCA9IHRleHQucmVwbGFjZShkZWxpbVVybFJlZ2V4LCByZXBsYWNlTGluayhvcHRpb25zKSk7XG4gIHRleHQgPSB0ZXh0LnJlcGxhY2UoZGVsaW1NYWlsUmVnZXgsIHJlcGxhY2VNYWlsKG9wdGlvbnMsIGdsb2JhbHMpKTtcblxuICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCdhdXRvTGlua3MuYWZ0ZXInLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcblxuICByZXR1cm4gdGV4dDtcbn0pO1xuXG5zaG93ZG93bi5zdWJQYXJzZXIoJ3NpbXBsaWZpZWRBdXRvTGlua3MnLCBmdW5jdGlvbiAodGV4dCwgb3B0aW9ucywgZ2xvYmFscykge1xuICAndXNlIHN0cmljdCc7XG5cbiAgaWYgKCFvcHRpb25zLnNpbXBsaWZpZWRBdXRvTGluaykge1xuICAgIHJldHVybiB0ZXh0O1xuICB9XG5cbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgnc2ltcGxpZmllZEF1dG9MaW5rcy5iZWZvcmUnLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcblxuICBpZiAob3B0aW9ucy5leGNsdWRlVHJhaWxpbmdQdW5jdHVhdGlvbkZyb21VUkxzKSB7XG4gICAgdGV4dCA9IHRleHQucmVwbGFjZShzaW1wbGVVUkxSZWdleDIsIHJlcGxhY2VMaW5rKG9wdGlvbnMpKTtcbiAgfSBlbHNlIHtcbiAgICB0ZXh0ID0gdGV4dC5yZXBsYWNlKHNpbXBsZVVSTFJlZ2V4LCByZXBsYWNlTGluayhvcHRpb25zKSk7XG4gIH1cbiAgdGV4dCA9IHRleHQucmVwbGFjZShzaW1wbGVNYWlsUmVnZXgsIHJlcGxhY2VNYWlsKG9wdGlvbnMsIGdsb2JhbHMpKTtcblxuICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCdzaW1wbGlmaWVkQXV0b0xpbmtzLmFmdGVyJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG5cbiAgcmV0dXJuIHRleHQ7XG59KTtcblxyXG4vKipcbiAqIFRoZXNlIGFyZSBhbGwgdGhlIHRyYW5zZm9ybWF0aW9ucyB0aGF0IGZvcm0gYmxvY2stbGV2ZWxcbiAqIHRhZ3MgbGlrZSBwYXJhZ3JhcGhzLCBoZWFkZXJzLCBhbmQgbGlzdCBpdGVtcy5cbiAqL1xuc2hvd2Rvd24uc3ViUGFyc2VyKCdibG9ja0dhbXV0JywgZnVuY3Rpb24gKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuXG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ2Jsb2NrR2FtdXQuYmVmb3JlJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG5cbiAgLy8gd2UgcGFyc2UgYmxvY2txdW90ZXMgZmlyc3Qgc28gdGhhdCB3ZSBjYW4gaGF2ZSBoZWFkaW5ncyBhbmQgaHJzXG4gIC8vIGluc2lkZSBibG9ja3F1b3Rlc1xuICB0ZXh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdibG9ja1F1b3RlcycpKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICB0ZXh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdoZWFkZXJzJykodGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG5cbiAgLy8gRG8gSG9yaXpvbnRhbCBSdWxlczpcbiAgdGV4dCA9IHNob3dkb3duLnN1YlBhcnNlcignaG9yaXpvbnRhbFJ1bGUnKSh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcblxuICB0ZXh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdsaXN0cycpKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICB0ZXh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdjb2RlQmxvY2tzJykodGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gIHRleHQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ3RhYmxlcycpKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuXG4gIC8vIFdlIGFscmVhZHkgcmFuIF9IYXNoSFRNTEJsb2NrcygpIGJlZm9yZSwgaW4gTWFya2Rvd24oKSwgYnV0IHRoYXRcbiAgLy8gd2FzIHRvIGVzY2FwZSByYXcgSFRNTCBpbiB0aGUgb3JpZ2luYWwgTWFya2Rvd24gc291cmNlLiBUaGlzIHRpbWUsXG4gIC8vIHdlJ3JlIGVzY2FwaW5nIHRoZSBtYXJrdXAgd2UndmUganVzdCBjcmVhdGVkLCBzbyB0aGF0IHdlIGRvbid0IHdyYXBcbiAgLy8gPHA+IHRhZ3MgYXJvdW5kIGJsb2NrLWxldmVsIHRhZ3MuXG4gIHRleHQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ2hhc2hIVE1MQmxvY2tzJykodGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gIHRleHQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ3BhcmFncmFwaHMnKSh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcblxuICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCdibG9ja0dhbXV0LmFmdGVyJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG5cbiAgcmV0dXJuIHRleHQ7XG59KTtcblxyXG5zaG93ZG93bi5zdWJQYXJzZXIoJ2Jsb2NrUXVvdGVzJywgZnVuY3Rpb24gKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuXG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ2Jsb2NrUXVvdGVzLmJlZm9yZScsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuXG4gIC8vIGFkZCBhIGNvdXBsZSBleHRyYSBsaW5lcyBhZnRlciB0aGUgdGV4dCBhbmQgZW5kdGV4dCBtYXJrXG4gIHRleHQgPSB0ZXh0ICsgJ1xcblxcbic7XG5cbiAgdmFyIHJneCA9IC8oXiB7MCwzfT5bIFxcdF0/LitcXG4oLitcXG4pKlxcbiopKy9nbTtcblxuICBpZiAob3B0aW9ucy5zcGxpdEFkamFjZW50QmxvY2txdW90ZXMpIHtcbiAgICByZ3ggPSAvXiB7MCwzfT5bXFxzXFxTXSo/KD86XFxuXFxuKS9nbTtcbiAgfVxuXG4gIHRleHQgPSB0ZXh0LnJlcGxhY2Uocmd4LCBmdW5jdGlvbiAoYnEpIHtcbiAgICAvLyBhdHRhY2tsYWI6IGhhY2sgYXJvdW5kIEtvbnF1ZXJvciAzLjUuNCBidWc6XG4gICAgLy8gXCItLS0tLS0tLS0tYnVnXCIucmVwbGFjZSgvXi0vZyxcIlwiKSA9PSBcImJ1Z1wiXG4gICAgYnEgPSBicS5yZXBsYWNlKC9eWyBcXHRdKj5bIFxcdF0/L2dtLCAnJyk7IC8vIHRyaW0gb25lIGxldmVsIG9mIHF1b3RpbmdcblxuICAgIC8vIGF0dGFja2xhYjogY2xlYW4gdXAgaGFja1xuICAgIGJxID0gYnEucmVwbGFjZSgvwqgwL2csICcnKTtcblxuICAgIGJxID0gYnEucmVwbGFjZSgvXlsgXFx0XSskL2dtLCAnJyk7IC8vIHRyaW0gd2hpdGVzcGFjZS1vbmx5IGxpbmVzXG4gICAgYnEgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ2dpdGh1YkNvZGVCbG9ja3MnKShicSwgb3B0aW9ucywgZ2xvYmFscyk7XG4gICAgYnEgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ2Jsb2NrR2FtdXQnKShicSwgb3B0aW9ucywgZ2xvYmFscyk7IC8vIHJlY3Vyc2VcblxuICAgIGJxID0gYnEucmVwbGFjZSgvKF58XFxuKS9nLCAnJDEgICcpO1xuICAgIC8vIFRoZXNlIGxlYWRpbmcgc3BhY2VzIHNjcmV3IHdpdGggPHByZT4gY29udGVudCwgc28gd2UgbmVlZCB0byBmaXggdGhhdDpcbiAgICBicSA9IGJxLnJlcGxhY2UoLyhcXHMqPHByZT5bXlxccl0rPzxcXC9wcmU+KS9nbSwgZnVuY3Rpb24gKHdob2xlTWF0Y2gsIG0xKSB7XG4gICAgICB2YXIgcHJlID0gbTE7XG4gICAgICAvLyBhdHRhY2tsYWI6IGhhY2sgYXJvdW5kIEtvbnF1ZXJvciAzLjUuNCBidWc6XG4gICAgICBwcmUgPSBwcmUucmVwbGFjZSgvXiAgL21nLCAnwqgwJyk7XG4gICAgICBwcmUgPSBwcmUucmVwbGFjZSgvwqgwL2csICcnKTtcbiAgICAgIHJldHVybiBwcmU7XG4gICAgfSk7XG5cbiAgICByZXR1cm4gc2hvd2Rvd24uc3ViUGFyc2VyKCdoYXNoQmxvY2snKSgnPGJsb2NrcXVvdGU+XFxuJyArIGJxICsgJ1xcbjwvYmxvY2txdW90ZT4nLCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgfSk7XG5cbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgnYmxvY2tRdW90ZXMuYWZ0ZXInLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgcmV0dXJuIHRleHQ7XG59KTtcblxyXG4vKipcbiAqIFByb2Nlc3MgTWFya2Rvd24gYDxwcmU+PGNvZGU+YCBibG9ja3MuXG4gKi9cbnNob3dkb3duLnN1YlBhcnNlcignY29kZUJsb2NrcycsIGZ1bmN0aW9uICh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCdjb2RlQmxvY2tzLmJlZm9yZScsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuXG4gIC8vIHNlbnRpbmVsIHdvcmthcm91bmRzIGZvciBsYWNrIG9mIFxcQSBhbmQgXFxaLCBzYWZhcmlcXGtodG1sIGJ1Z1xuICB0ZXh0ICs9ICfCqDAnO1xuXG4gIHZhciBwYXR0ZXJuID0gLyg/OlxcblxcbnxeKSgoPzooPzpbIF17NH18XFx0KS4qXFxuKykrKShcXG4qWyBdezAsM31bXiBcXHRcXG5dfCg/PcKoMCkpL2c7XG4gIHRleHQgPSB0ZXh0LnJlcGxhY2UocGF0dGVybiwgZnVuY3Rpb24gKHdob2xlTWF0Y2gsIG0xLCBtMikge1xuICAgIHZhciBjb2RlYmxvY2sgPSBtMSxcbiAgICAgICAgbmV4dENoYXIgPSBtMixcbiAgICAgICAgZW5kID0gJ1xcbic7XG5cbiAgICBjb2RlYmxvY2sgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ291dGRlbnQnKShjb2RlYmxvY2ssIG9wdGlvbnMsIGdsb2JhbHMpO1xuICAgIGNvZGVibG9jayA9IHNob3dkb3duLnN1YlBhcnNlcignZW5jb2RlQ29kZScpKGNvZGVibG9jaywgb3B0aW9ucywgZ2xvYmFscyk7XG4gICAgY29kZWJsb2NrID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdkZXRhYicpKGNvZGVibG9jaywgb3B0aW9ucywgZ2xvYmFscyk7XG4gICAgY29kZWJsb2NrID0gY29kZWJsb2NrLnJlcGxhY2UoL15cXG4rL2csICcnKTsgLy8gdHJpbSBsZWFkaW5nIG5ld2xpbmVzXG4gICAgY29kZWJsb2NrID0gY29kZWJsb2NrLnJlcGxhY2UoL1xcbiskL2csICcnKTsgLy8gdHJpbSB0cmFpbGluZyBuZXdsaW5lc1xuXG4gICAgaWYgKG9wdGlvbnMub21pdEV4dHJhV0xJbkNvZGVCbG9ja3MpIHtcbiAgICAgIGVuZCA9ICcnO1xuICAgIH1cblxuICAgIGNvZGVibG9jayA9ICc8cHJlPjxjb2RlPicgKyBjb2RlYmxvY2sgKyBlbmQgKyAnPC9jb2RlPjwvcHJlPic7XG5cbiAgICByZXR1cm4gc2hvd2Rvd24uc3ViUGFyc2VyKCdoYXNoQmxvY2snKShjb2RlYmxvY2ssIG9wdGlvbnMsIGdsb2JhbHMpICsgbmV4dENoYXI7XG4gIH0pO1xuXG4gIC8vIHN0cmlwIHNlbnRpbmVsXG4gIHRleHQgPSB0ZXh0LnJlcGxhY2UoL8KoMC8sICcnKTtcblxuICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCdjb2RlQmxvY2tzLmFmdGVyJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gIHJldHVybiB0ZXh0O1xufSk7XG5cclxuLyoqXG4gKlxuICogICAqICBCYWNrdGljayBxdW90ZXMgYXJlIHVzZWQgZm9yIDxjb2RlPjwvY29kZT4gc3BhbnMuXG4gKlxuICogICAqICBZb3UgY2FuIHVzZSBtdWx0aXBsZSBiYWNrdGlja3MgYXMgdGhlIGRlbGltaXRlcnMgaWYgeW91IHdhbnQgdG9cbiAqICAgICBpbmNsdWRlIGxpdGVyYWwgYmFja3RpY2tzIGluIHRoZSBjb2RlIHNwYW4uIFNvLCB0aGlzIGlucHV0OlxuICpcbiAqICAgICAgICAgSnVzdCB0eXBlIGBgZm9vIGBiYXJgIGJhemBgIGF0IHRoZSBwcm9tcHQuXG4gKlxuICogICAgICAgV2lsbCB0cmFuc2xhdGUgdG86XG4gKlxuICogICAgICAgICA8cD5KdXN0IHR5cGUgPGNvZGU+Zm9vIGBiYXJgIGJhejwvY29kZT4gYXQgdGhlIHByb21wdC48L3A+XG4gKlxuICogICAgVGhlcmUncyBubyBhcmJpdHJhcnkgbGltaXQgdG8gdGhlIG51bWJlciBvZiBiYWNrdGlja3MgeW91XG4gKiAgICBjYW4gdXNlIGFzIGRlbGltdGVycy4gSWYgeW91IG5lZWQgdGhyZWUgY29uc2VjdXRpdmUgYmFja3RpY2tzXG4gKiAgICBpbiB5b3VyIGNvZGUsIHVzZSBmb3VyIGZvciBkZWxpbWl0ZXJzLCBldGMuXG4gKlxuICogICogIFlvdSBjYW4gdXNlIHNwYWNlcyB0byBnZXQgbGl0ZXJhbCBiYWNrdGlja3MgYXQgdGhlIGVkZ2VzOlxuICpcbiAqICAgICAgICAgLi4uIHR5cGUgYGAgYGJhcmAgYGAgLi4uXG4gKlxuICogICAgICAgVHVybnMgdG86XG4gKlxuICogICAgICAgICAuLi4gdHlwZSA8Y29kZT5gYmFyYDwvY29kZT4gLi4uXG4gKi9cbnNob3dkb3duLnN1YlBhcnNlcignY29kZVNwYW5zJywgZnVuY3Rpb24gKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuXG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ2NvZGVTcGFucy5iZWZvcmUnLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcblxuICBpZiAodHlwZW9mKHRleHQpID09PSAndW5kZWZpbmVkJykge1xuICAgIHRleHQgPSAnJztcbiAgfVxuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC8oXnxbXlxcXFxdKShgKykoW15cXHJdKj9bXmBdKVxcMig/IWApL2dtLFxuICAgIGZ1bmN0aW9uICh3aG9sZU1hdGNoLCBtMSwgbTIsIG0zKSB7XG4gICAgICB2YXIgYyA9IG0zO1xuICAgICAgYyA9IGMucmVwbGFjZSgvXihbIFxcdF0qKS9nLCAnJyk7XHQvLyBsZWFkaW5nIHdoaXRlc3BhY2VcbiAgICAgIGMgPSBjLnJlcGxhY2UoL1sgXFx0XSokL2csICcnKTtcdC8vIHRyYWlsaW5nIHdoaXRlc3BhY2VcbiAgICAgIGMgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ2VuY29kZUNvZGUnKShjLCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgICAgIGMgPSBtMSArICc8Y29kZT4nICsgYyArICc8L2NvZGU+JztcbiAgICAgIGMgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ2hhc2hIVE1MU3BhbnMnKShjLCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgICAgIHJldHVybiBjO1xuICAgIH1cbiAgKTtcblxuICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCdjb2RlU3BhbnMuYWZ0ZXInLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgcmV0dXJuIHRleHQ7XG59KTtcblxyXG4vKipcbiAqIFR1cm4gTWFya2Rvd24gbGluayBzaG9ydGN1dHMgaW50byBYSFRNTCA8YT4gdGFncy5cbiAqL1xuc2hvd2Rvd24uc3ViUGFyc2VyKCdjb21wbGV0ZUhUTUxEb2N1bWVudCcsIGZ1bmN0aW9uICh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICBpZiAoIW9wdGlvbnMuY29tcGxldGVIVE1MRG9jdW1lbnQpIHtcbiAgICByZXR1cm4gdGV4dDtcbiAgfVxuXG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ2NvbXBsZXRlSFRNTERvY3VtZW50LmJlZm9yZScsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuXG4gIHZhciBkb2N0eXBlID0gJ2h0bWwnLFxuICAgICAgZG9jdHlwZVBhcnNlZCA9ICc8IURPQ1RZUEUgSFRNTD5cXG4nLFxuICAgICAgdGl0bGUgPSAnJyxcbiAgICAgIGNoYXJzZXQgPSAnPG1ldGEgY2hhcnNldD1cInV0Zi04XCI+XFxuJyxcbiAgICAgIGxhbmcgPSAnJyxcbiAgICAgIG1ldGFkYXRhID0gJyc7XG5cbiAgaWYgKHR5cGVvZiBnbG9iYWxzLm1ldGFkYXRhLnBhcnNlZC5kb2N0eXBlICE9PSAndW5kZWZpbmVkJykge1xuICAgIGRvY3R5cGVQYXJzZWQgPSAnPCFET0NUWVBFICcgKyAgZ2xvYmFscy5tZXRhZGF0YS5wYXJzZWQuZG9jdHlwZSArICc+XFxuJztcbiAgICBkb2N0eXBlID0gZ2xvYmFscy5tZXRhZGF0YS5wYXJzZWQuZG9jdHlwZS50b1N0cmluZygpLnRvTG93ZXJDYXNlKCk7XG4gICAgaWYgKGRvY3R5cGUgPT09ICdodG1sJyB8fCBkb2N0eXBlID09PSAnaHRtbDUnKSB7XG4gICAgICBjaGFyc2V0ID0gJzxtZXRhIGNoYXJzZXQ9XCJ1dGYtOFwiPic7XG4gICAgfVxuICB9XG5cbiAgZm9yICh2YXIgbWV0YSBpbiBnbG9iYWxzLm1ldGFkYXRhLnBhcnNlZCkge1xuICAgIGlmIChnbG9iYWxzLm1ldGFkYXRhLnBhcnNlZC5oYXNPd25Qcm9wZXJ0eShtZXRhKSkge1xuICAgICAgc3dpdGNoIChtZXRhLnRvTG93ZXJDYXNlKCkpIHtcbiAgICAgICAgY2FzZSAnZG9jdHlwZSc6XG4gICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgY2FzZSAndGl0bGUnOlxuICAgICAgICAgIHRpdGxlID0gJzx0aXRsZT4nICsgIGdsb2JhbHMubWV0YWRhdGEucGFyc2VkLnRpdGxlICsgJzwvdGl0bGU+XFxuJztcbiAgICAgICAgICBicmVhaztcblxuICAgICAgICBjYXNlICdjaGFyc2V0JzpcbiAgICAgICAgICBpZiAoZG9jdHlwZSA9PT0gJ2h0bWwnIHx8IGRvY3R5cGUgPT09ICdodG1sNScpIHtcbiAgICAgICAgICAgIGNoYXJzZXQgPSAnPG1ldGEgY2hhcnNldD1cIicgKyBnbG9iYWxzLm1ldGFkYXRhLnBhcnNlZC5jaGFyc2V0ICsgJ1wiPlxcbic7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNoYXJzZXQgPSAnPG1ldGEgbmFtZT1cImNoYXJzZXRcIiBjb250ZW50PVwiJyArIGdsb2JhbHMubWV0YWRhdGEucGFyc2VkLmNoYXJzZXQgKyAnXCI+XFxuJztcbiAgICAgICAgICB9XG4gICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgY2FzZSAnbGFuZ3VhZ2UnOlxuICAgICAgICBjYXNlICdsYW5nJzpcbiAgICAgICAgICBsYW5nID0gJyBsYW5nPVwiJyArIGdsb2JhbHMubWV0YWRhdGEucGFyc2VkW21ldGFdICsgJ1wiJztcbiAgICAgICAgICBtZXRhZGF0YSArPSAnPG1ldGEgbmFtZT1cIicgKyBtZXRhICsgJ1wiIGNvbnRlbnQ9XCInICsgZ2xvYmFscy5tZXRhZGF0YS5wYXJzZWRbbWV0YV0gKyAnXCI+XFxuJztcbiAgICAgICAgICBicmVhaztcblxuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgIG1ldGFkYXRhICs9ICc8bWV0YSBuYW1lPVwiJyArIG1ldGEgKyAnXCIgY29udGVudD1cIicgKyBnbG9iYWxzLm1ldGFkYXRhLnBhcnNlZFttZXRhXSArICdcIj5cXG4nO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHRleHQgPSBkb2N0eXBlUGFyc2VkICsgJzxodG1sJyArIGxhbmcgKyAnPlxcbjxoZWFkPlxcbicgKyB0aXRsZSArIGNoYXJzZXQgKyBtZXRhZGF0YSArICc8L2hlYWQ+XFxuPGJvZHk+XFxuJyArIHRleHQudHJpbSgpICsgJ1xcbjwvYm9keT5cXG48L2h0bWw+JztcblxuICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCdjb21wbGV0ZUhUTUxEb2N1bWVudC5hZnRlcicsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICByZXR1cm4gdGV4dDtcbn0pO1xuXHJcbi8qKlxuICogQ29udmVydCBhbGwgdGFicyB0byBzcGFjZXNcbiAqL1xuc2hvd2Rvd24uc3ViUGFyc2VyKCdkZXRhYicsIGZ1bmN0aW9uICh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKSB7XG4gICd1c2Ugc3RyaWN0JztcbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgnZGV0YWIuYmVmb3JlJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG5cbiAgLy8gZXhwYW5kIGZpcnN0IG4tMSB0YWJzXG4gIHRleHQgPSB0ZXh0LnJlcGxhY2UoL1xcdCg/PVxcdCkvZywgJyAgICAnKTsgLy8gZ190YWJfd2lkdGhcblxuICAvLyByZXBsYWNlIHRoZSBudGggd2l0aCB0d28gc2VudGluZWxzXG4gIHRleHQgPSB0ZXh0LnJlcGxhY2UoL1xcdC9nLCAnwqhBwqhCJyk7XG5cbiAgLy8gdXNlIHRoZSBzZW50aW5lbCB0byBhbmNob3Igb3VyIHJlZ2V4IHNvIGl0IGRvZXNuJ3QgZXhwbG9kZVxuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC/CqEIoLis/KcKoQS9nLCBmdW5jdGlvbiAod2hvbGVNYXRjaCwgbTEpIHtcbiAgICB2YXIgbGVhZGluZ1RleHQgPSBtMSxcbiAgICAgICAgbnVtU3BhY2VzID0gNCAtIGxlYWRpbmdUZXh0Lmxlbmd0aCAlIDQ7ICAvLyBnX3RhYl93aWR0aFxuXG4gICAgLy8gdGhlcmUgKm11c3QqIGJlIGEgYmV0dGVyIHdheSB0byBkbyB0aGlzOlxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbnVtU3BhY2VzOyBpKyspIHtcbiAgICAgIGxlYWRpbmdUZXh0ICs9ICcgJztcbiAgICB9XG5cbiAgICByZXR1cm4gbGVhZGluZ1RleHQ7XG4gIH0pO1xuXG4gIC8vIGNsZWFuIHVwIHNlbnRpbmVsc1xuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC/CqEEvZywgJyAgICAnKTsgIC8vIGdfdGFiX3dpZHRoXG4gIHRleHQgPSB0ZXh0LnJlcGxhY2UoL8KoQi9nLCAnJyk7XG5cbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgnZGV0YWIuYWZ0ZXInLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgcmV0dXJuIHRleHQ7XG59KTtcblxyXG5zaG93ZG93bi5zdWJQYXJzZXIoJ2VsbGlwc2lzJywgZnVuY3Rpb24gKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuXG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ2VsbGlwc2lzLmJlZm9yZScsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuXG4gIHRleHQgPSB0ZXh0LnJlcGxhY2UoL1xcLlxcLlxcLi9nLCAn4oCmJyk7XG5cbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgnZWxsaXBzaXMuYWZ0ZXInLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcblxuICByZXR1cm4gdGV4dDtcbn0pO1xuXHJcbi8qKlxuICogVGhlc2UgYXJlIGFsbCB0aGUgdHJhbnNmb3JtYXRpb25zIHRoYXQgb2NjdXIgKndpdGhpbiogYmxvY2stbGV2ZWxcbiAqIHRhZ3MgbGlrZSBwYXJhZ3JhcGhzLCBoZWFkZXJzLCBhbmQgbGlzdCBpdGVtcy5cbiAqL1xuc2hvd2Rvd24uc3ViUGFyc2VyKCdlbW9qaScsIGZ1bmN0aW9uICh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICBpZiAoIW9wdGlvbnMuZW1vamkpIHtcbiAgICByZXR1cm4gdGV4dDtcbiAgfVxuXG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ2Vtb2ppLmJlZm9yZScsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuXG4gIHZhciBlbW9qaVJneCA9IC86KFtcXFNdKz8pOi9nO1xuXG4gIHRleHQgPSB0ZXh0LnJlcGxhY2UoZW1vamlSZ3gsIGZ1bmN0aW9uICh3bSwgZW1vamlDb2RlKSB7XG4gICAgaWYgKHNob3dkb3duLmhlbHBlci5lbW9qaXMuaGFzT3duUHJvcGVydHkoZW1vamlDb2RlKSkge1xuICAgICAgcmV0dXJuIHNob3dkb3duLmhlbHBlci5lbW9qaXNbZW1vamlDb2RlXTtcbiAgICB9XG4gICAgcmV0dXJuIHdtO1xuICB9KTtcblxuICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCdlbW9qaS5hZnRlcicsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuXG4gIHJldHVybiB0ZXh0O1xufSk7XG5cclxuLyoqXG4gKiBTbWFydCBwcm9jZXNzaW5nIGZvciBhbXBlcnNhbmRzIGFuZCBhbmdsZSBicmFja2V0cyB0aGF0IG5lZWQgdG8gYmUgZW5jb2RlZC5cbiAqL1xuc2hvd2Rvd24uc3ViUGFyc2VyKCdlbmNvZGVBbXBzQW5kQW5nbGVzJywgZnVuY3Rpb24gKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCdlbmNvZGVBbXBzQW5kQW5nbGVzLmJlZm9yZScsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuXG4gIC8vIEFtcGVyc2FuZC1lbmNvZGluZyBiYXNlZCBlbnRpcmVseSBvbiBOYXQgSXJvbnMncyBBbXB1dGF0b3IgTVQgcGx1Z2luOlxuICAvLyBodHRwOi8vYnVtcHBvLm5ldC9wcm9qZWN0cy9hbXB1dGF0b3IvXG4gIHRleHQgPSB0ZXh0LnJlcGxhY2UoLyYoPyEjP1t4WF0/KD86WzAtOWEtZkEtRl0rfFxcdyspOykvZywgJyZhbXA7Jyk7XG5cbiAgLy8gRW5jb2RlIG5ha2VkIDwnc1xuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC88KD8hW2EtelxcLz8kIV0pL2dpLCAnJmx0OycpO1xuXG4gIC8vIEVuY29kZSA8XG4gIHRleHQgPSB0ZXh0LnJlcGxhY2UoLzwvZywgJyZsdDsnKTtcblxuICAvLyBFbmNvZGUgPlxuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC8+L2csICcmZ3Q7Jyk7XG5cbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgnZW5jb2RlQW1wc0FuZEFuZ2xlcy5hZnRlcicsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICByZXR1cm4gdGV4dDtcbn0pO1xuXHJcbi8qKlxuICogUmV0dXJucyB0aGUgc3RyaW5nLCB3aXRoIGFmdGVyIHByb2Nlc3NpbmcgdGhlIGZvbGxvd2luZyBiYWNrc2xhc2ggZXNjYXBlIHNlcXVlbmNlcy5cbiAqXG4gKiBhdHRhY2tsYWI6IFRoZSBwb2xpdGUgd2F5IHRvIGRvIHRoaXMgaXMgd2l0aCB0aGUgbmV3IGVzY2FwZUNoYXJhY3RlcnMoKSBmdW5jdGlvbjpcbiAqXG4gKiAgICB0ZXh0ID0gZXNjYXBlQ2hhcmFjdGVycyh0ZXh0LFwiXFxcXFwiLHRydWUpO1xuICogICAgdGV4dCA9IGVzY2FwZUNoYXJhY3RlcnModGV4dCxcImAqX3t9W10oKT4jKy0uIVwiLHRydWUpO1xuICpcbiAqIC4uLmJ1dCB3ZSdyZSBzaWRlc3RlcHBpbmcgaXRzIHVzZSBvZiB0aGUgKHNsb3cpIFJlZ0V4cCBjb25zdHJ1Y3RvclxuICogYXMgYW4gb3B0aW1pemF0aW9uIGZvciBGaXJlZm94LiAgVGhpcyBmdW5jdGlvbiBnZXRzIGNhbGxlZCBhIExPVC5cbiAqL1xuc2hvd2Rvd24uc3ViUGFyc2VyKCdlbmNvZGVCYWNrc2xhc2hFc2NhcGVzJywgZnVuY3Rpb24gKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCdlbmNvZGVCYWNrc2xhc2hFc2NhcGVzLmJlZm9yZScsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuXG4gIHRleHQgPSB0ZXh0LnJlcGxhY2UoL1xcXFwoXFxcXCkvZywgc2hvd2Rvd24uaGVscGVyLmVzY2FwZUNoYXJhY3RlcnNDYWxsYmFjayk7XG4gIHRleHQgPSB0ZXh0LnJlcGxhY2UoL1xcXFwoW2AqX3t9XFxbXFxdKCk+IysuIX49fC1dKS9nLCBzaG93ZG93bi5oZWxwZXIuZXNjYXBlQ2hhcmFjdGVyc0NhbGxiYWNrKTtcblxuICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCdlbmNvZGVCYWNrc2xhc2hFc2NhcGVzLmFmdGVyJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gIHJldHVybiB0ZXh0O1xufSk7XG5cclxuLyoqXG4gKiBFbmNvZGUvZXNjYXBlIGNlcnRhaW4gY2hhcmFjdGVycyBpbnNpZGUgTWFya2Rvd24gY29kZSBydW5zLlxuICogVGhlIHBvaW50IGlzIHRoYXQgaW4gY29kZSwgdGhlc2UgY2hhcmFjdGVycyBhcmUgbGl0ZXJhbHMsXG4gKiBhbmQgbG9zZSB0aGVpciBzcGVjaWFsIE1hcmtkb3duIG1lYW5pbmdzLlxuICovXG5zaG93ZG93bi5zdWJQYXJzZXIoJ2VuY29kZUNvZGUnLCBmdW5jdGlvbiAodGV4dCwgb3B0aW9ucywgZ2xvYmFscykge1xuICAndXNlIHN0cmljdCc7XG5cbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgnZW5jb2RlQ29kZS5iZWZvcmUnLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcblxuICAvLyBFbmNvZGUgYWxsIGFtcGVyc2FuZHM7IEhUTUwgZW50aXRpZXMgYXJlIG5vdFxuICAvLyBlbnRpdGllcyB3aXRoaW4gYSBNYXJrZG93biBjb2RlIHNwYW4uXG4gIHRleHQgPSB0ZXh0XG4gICAgLnJlcGxhY2UoLyYvZywgJyZhbXA7JylcbiAgLy8gRG8gdGhlIGFuZ2xlIGJyYWNrZXQgc29uZyBhbmQgZGFuY2U6XG4gICAgLnJlcGxhY2UoLzwvZywgJyZsdDsnKVxuICAgIC5yZXBsYWNlKC8+L2csICcmZ3Q7JylcbiAgLy8gTm93LCBlc2NhcGUgY2hhcmFjdGVycyB0aGF0IGFyZSBtYWdpYyBpbiBNYXJrZG93bjpcbiAgICAucmVwbGFjZSgvKFsqX3t9XFxbXFxdXFxcXD1+LV0pL2csIHNob3dkb3duLmhlbHBlci5lc2NhcGVDaGFyYWN0ZXJzQ2FsbGJhY2spO1xuXG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ2VuY29kZUNvZGUuYWZ0ZXInLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgcmV0dXJuIHRleHQ7XG59KTtcblxyXG4vKipcbiAqIFdpdGhpbiB0YWdzIC0tIG1lYW5pbmcgYmV0d2VlbiA8IGFuZCA+IC0tIGVuY29kZSBbXFwgYCAqIF8gfiA9XSBzbyB0aGV5XG4gKiBkb24ndCBjb25mbGljdCB3aXRoIHRoZWlyIHVzZSBpbiBNYXJrZG93biBmb3IgY29kZSwgaXRhbGljcyBhbmQgc3Ryb25nLlxuICovXG5zaG93ZG93bi5zdWJQYXJzZXIoJ2VzY2FwZVNwZWNpYWxDaGFyc1dpdGhpblRhZ0F0dHJpYnV0ZXMnLCBmdW5jdGlvbiAodGV4dCwgb3B0aW9ucywgZ2xvYmFscykge1xuICAndXNlIHN0cmljdCc7XG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ2VzY2FwZVNwZWNpYWxDaGFyc1dpdGhpblRhZ0F0dHJpYnV0ZXMuYmVmb3JlJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG5cbiAgLy8gQnVpbGQgYSByZWdleCB0byBmaW5kIEhUTUwgdGFncy5cbiAgdmFyIHRhZ3MgICAgID0gLzxcXC8/W2EtelxcZF86LV0rKD86W1xcc10rW1xcc1xcU10rPyk/Pi9naSxcbiAgICAgIGNvbW1lbnRzID0gLzwhKC0tKD86KD86W14+LV18LVtePl0pKD86W14tXXwtW14tXSkqKS0tKT4vZ2k7XG5cbiAgdGV4dCA9IHRleHQucmVwbGFjZSh0YWdzLCBmdW5jdGlvbiAod2hvbGVNYXRjaCkge1xuICAgIHJldHVybiB3aG9sZU1hdGNoXG4gICAgICAucmVwbGFjZSgvKC4pPFxcLz9jb2RlPig/PS4pL2csICckMWAnKVxuICAgICAgLnJlcGxhY2UoLyhbXFxcXGAqX349fF0pL2csIHNob3dkb3duLmhlbHBlci5lc2NhcGVDaGFyYWN0ZXJzQ2FsbGJhY2spO1xuICB9KTtcblxuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKGNvbW1lbnRzLCBmdW5jdGlvbiAod2hvbGVNYXRjaCkge1xuICAgIHJldHVybiB3aG9sZU1hdGNoXG4gICAgICAucmVwbGFjZSgvKFtcXFxcYCpffj18XSkvZywgc2hvd2Rvd24uaGVscGVyLmVzY2FwZUNoYXJhY3RlcnNDYWxsYmFjayk7XG4gIH0pO1xuXG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ2VzY2FwZVNwZWNpYWxDaGFyc1dpdGhpblRhZ0F0dHJpYnV0ZXMuYWZ0ZXInLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgcmV0dXJuIHRleHQ7XG59KTtcblxyXG4vKipcbiAqIEhhbmRsZSBnaXRodWIgY29kZWJsb2NrcyBwcmlvciB0byBydW5uaW5nIEhhc2hIVE1MIHNvIHRoYXRcbiAqIEhUTUwgY29udGFpbmVkIHdpdGhpbiB0aGUgY29kZWJsb2NrIGdldHMgZXNjYXBlZCBwcm9wZXJseVxuICogRXhhbXBsZTpcbiAqIGBgYHJ1YnlcbiAqICAgICBkZWYgaGVsbG9fd29ybGQoeClcbiAqICAgICAgIHB1dHMgXCJIZWxsbywgI3t4fVwiXG4gKiAgICAgZW5kXG4gKiBgYGBcbiAqL1xuc2hvd2Rvd24uc3ViUGFyc2VyKCdnaXRodWJDb2RlQmxvY2tzJywgZnVuY3Rpb24gKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuXG4gIC8vIGVhcmx5IGV4aXQgaWYgb3B0aW9uIGlzIG5vdCBlbmFibGVkXG4gIGlmICghb3B0aW9ucy5naENvZGVCbG9ja3MpIHtcbiAgICByZXR1cm4gdGV4dDtcbiAgfVxuXG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ2dpdGh1YkNvZGVCbG9ja3MuYmVmb3JlJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG5cbiAgdGV4dCArPSAnwqgwJztcblxuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC8oPzpefFxcbikoYGBgK3x+fn4rKShbXlxcc2B+XSopXFxuKFtcXHNcXFNdKj8pXFxuXFwxL2csIGZ1bmN0aW9uICh3aG9sZU1hdGNoLCBkZWxpbSwgbGFuZ3VhZ2UsIGNvZGVibG9jaykge1xuICAgIHZhciBlbmQgPSAob3B0aW9ucy5vbWl0RXh0cmFXTEluQ29kZUJsb2NrcykgPyAnJyA6ICdcXG4nO1xuXG4gICAgLy8gRmlyc3QgcGFyc2UgdGhlIGdpdGh1YiBjb2RlIGJsb2NrXG4gICAgY29kZWJsb2NrID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdlbmNvZGVDb2RlJykoY29kZWJsb2NrLCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgICBjb2RlYmxvY2sgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ2RldGFiJykoY29kZWJsb2NrLCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgICBjb2RlYmxvY2sgPSBjb2RlYmxvY2sucmVwbGFjZSgvXlxcbisvZywgJycpOyAvLyB0cmltIGxlYWRpbmcgbmV3bGluZXNcbiAgICBjb2RlYmxvY2sgPSBjb2RlYmxvY2sucmVwbGFjZSgvXFxuKyQvZywgJycpOyAvLyB0cmltIHRyYWlsaW5nIHdoaXRlc3BhY2VcblxuICAgIGNvZGVibG9jayA9ICc8cHJlPjxjb2RlJyArIChsYW5ndWFnZSA/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/XFxuL2csICcgJyk7XG4gICAgICB9XG4gICAgICB1cmwgPSAnIycgKyBsaW5rSWQ7XG5cbiAgICAgIGlmICghc2hvd2Rvd24uaGVscGVyLmlzVW5kZWZpbmVkKGdVcmxzW2xpbmtJZF0pKSB7XG4gICAgICAgIHVybCA9IGdVcmxzW2xpbmtJZF07XG4gICAgICAgIGlmICghc2hvd2Rvd24uaGVscGVyLmlzVW5kZWZpbmVkKGdUaXRsZXNbbGlua0lkXSkpIHtcbiAgICAgICAgICB0aXRsZSA9IGdUaXRsZXNbbGlua0lkXTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIXNob3dkb3duLmhlbHBlci5pc1VuZGVmaW5lZChnRGltc1tsaW5rSWRdKSkge1xuICAgICAgICAgIHdpZHRoID0gZ0RpbXNbbGlua0lkXS53aWR0aDtcbiAgICAgICAgICBoZWlnaHQgPSBnRGltc1tsaW5rSWRdLmhlaWdodDtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIHdob2xlTWF0Y2g7XG4gICAgICB9XG4gICAgfVxuXG4gICAgYWx0VGV4dCA9IGFsdFRleHRcbiAgICAgIC5yZXBsYWNlKC9cIi9nLCAnJnF1b3Q7JylcbiAgICAvL2FsdFRleHQgPSBzaG93ZG93bi5oZWxwZXIuZXNjYXBlQ2hhcmFjdGVycyhhbHRUZXh0LCAnKl8nLCBmYWxzZSk7XG4gICAgICAucmVwbGFjZShzaG93ZG93bi5oZWxwZXIucmVnZXhlcy5hc3Rlcmlza0Rhc2hBbmRDb2xvbiwgc2hvd2Rvd24uaGVscGVyLmVzY2FwZUNoYXJhY3RlcnNDYWxsYmFjayk7XG4gICAgLy91cmwgPSBzaG93ZG93bi5oZWxwZXIuZXNjYXBlQ2hhcmFjdGVycyh1cmwsICcqXycsIGZhbHNlKTtcbiAgICB1cmwgPSB1cmwucmVwbGFjZShzaG93ZG93bi5oZWxwZXIucmVnZXhlcy5hc3Rlcmlza0Rhc2hBbmRDb2xvbiwgc2hvd2Rvd24uaGVscGVyLmVzY2FwZUNoYXJhY3RlcnNDYWxsYmFjayk7XG4gICAgdmFyIHJlc3VsdCA9ICc8aW1nIHNyYz1cIicgKyB1cmwgKyAnXCIgYWx0PVwiJyArIGFsdFRleHQgKyAnXCInO1xuXG4gICAgaWYgKHRpdGxlKSB7XG4gICAgICB0aXRsZSA9IHRpdGxlXG4gICAgICAgIC5yZXBsYWNlKC9cIi9nLCAnJnF1b3Q7JylcbiAgICAgIC8vdGl0bGUgPSBzaG93ZG93bi5oZWxwZXIuZXNjYXBlQ2hhcmFjdGVycyh0aXRsZSwgJypfJywgZmFsc2UpO1xuICAgICAgICAucmVwbGFjZShzaG93ZG93bi5oZWxwZXIucmVnZXhlcy5hc3Rlcmlza0Rhc2hBbmRDb2xvbiwgc2hvd2Rvd24uaGVscGVyLmVzY2FwZUNoYXJhY3RlcnNDYWxsYmFjayk7XG4gICAgICByZXN1bHQgKz0gJyB0aXRsZT1cIicgKyB0aXRsZSArICdcIic7XG4gICAgfVxuXG4gICAgaWYgKHdpZHRoICYmIGhlaWdodCkge1xuICAgICAgd2lkdGggID0gKHdpZHRoID09PSAnKicpID8gJ2F1dG8nIDogd2lkdGg7XG4gICAgICBoZWlnaHQgPSAoaGVpZ2h0ID09PSAnKicpID8gJ2F1dG8nIDogaGVpZ2h0O1xuXG4gICAgICByZXN1bHQgKz0gJyB3aWR0aD1cIicgKyB3aWR0aCArICdcIic7XG4gICAgICByZXN1bHQgKz0gJyBoZWlnaHQ9XCInICsgaGVpZ2h0ICsgJ1wiJztcbiAgICB9XG5cbiAgICByZXN1bHQgKz0gJyAvPic7XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgLy8gRmlyc3QsIGhhbmRsZSByZWZlcmVuY2Utc3R5bGUgbGFiZWxlZCBpbWFnZXM6ICFbYWx0IHRleHRdW2lkXVxuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKHJlZmVyZW5jZVJlZ0V4cCwgd3JpdGVJbWFnZVRhZyk7XG5cbiAgLy8gTmV4dCwgaGFuZGxlIGlubGluZSBpbWFnZXM6ICAhW2FsdCB0ZXh0XSh1cmwgPTx3aWR0aD54PGhlaWdodD4gXCJvcHRpb25hbCB0aXRsZVwiKVxuXG4gIC8vIGJhc2U2NCBlbmNvZGVkIGltYWdlc1xuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKGJhc2U2NFJlZ0V4cCwgd3JpdGVJbWFnZVRhZ0Jhc2U2NCk7XG5cbiAgLy8gY2FzZXMgd2l0aCBjcmF6eSB1cmxzIGxpa2UgLi9pbWFnZS9jYXQxKS5wbmdcbiAgdGV4dCA9IHRleHQucmVwbGFjZShjcmF6eVJlZ0V4cCwgd3JpdGVJbWFnZVRhZyk7XG5cbiAgLy8gbm9ybWFsIGNhc2VzXG4gIHRleHQgPSB0ZXh0LnJlcGxhY2UoaW5saW5lUmVnRXhwLCB3cml0ZUltYWdlVGFnKTtcblxuICAvLyBoYW5kbGUgcmVmZXJlbmNlLXN0eWxlIHNob3J0Y3V0czogIVtpbWcgdGV4dF1cbiAgdGV4dCA9IHRleHQucmVwbGFjZShyZWZTaG9ydGN1dFJlZ0V4cCwgd3JpdGVJbWFnZVRhZyk7XG5cbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgnaW1hZ2VzLmFmdGVyJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gIHJldHVybiB0ZXh0O1xufSk7XG5cclxuc2hvd2Rvd24uc3ViUGFyc2VyKCdpdGFsaWNzQW5kQm9sZCcsIGZ1bmN0aW9uICh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCdpdGFsaWNzQW5kQm9sZC5iZWZvcmUnLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcblxuICAvLyBpdCdzIGZhc3RlciB0byBoYXZlIDMgc2VwYXJhdGUgcmVnZXhlcyBmb3IgZWFjaCBjYXNlIHRoYW4gaGF2ZSBqdXN0IG9uZVxuICAvLyBiZWNhdXNlIG9mIGJhY2t0cmFjaW5nLCBpbiBzb21lIGNhc2VzLCBpdCBjb3VsZCBsZWFkIHRvIGFuIGV4cG9uZW50aWFsIGVmZmVjdFxuICAvLyBjYWxsZWQgXCJjYXRhc3Ryb3BoaWMgYmFja3RyYWNlXCIuIE9taW5vdXMhXG5cbiAgZnVuY3Rpb24gcGFyc2VJbnNpZGUgKHR4dCwgbGVmdCwgcmlnaHQpIHtcbiAgICAvKlxuICAgIGlmIChvcHRpb25zLnNpbXBsaWZpZWRBdXRvTGluaykge1xuICAgICAgdHh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdzaW1wbGlmaWVkQXV0b0xpbmtzJykodHh0LCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgICB9XG4gICAgKi9cbiAgICByZXR1cm4gbGVmdCArIHR4dCArIHJpZ2h0O1xuICB9XG5cbiAgLy8gUGFyc2UgdW5kZXJzY29yZXNcbiAgaWYgKG9wdGlvbnMubGl0ZXJhbE1pZFdvcmRVbmRlcnNjb3Jlcykge1xuICAgIHRleHQgPSB0ZXh0LnJlcGxhY2UoL1xcYl9fXyhcXFNbXFxzXFxTXSopX19fXFxiL2csIGZ1bmN0aW9uICh3bSwgdHh0KSB7XG4gICAgICByZXR1cm4gcGFyc2VJbnNpZGUgKHR4dCwgJzxzdHJvbmc+PGVtPicsICc8L2VtPjwvc3Ryb25nPicpO1xuICAgIH0pO1xuICAgIHRleHQgPSB0ZXh0LnJlcGxhY2UoL1xcYl9fKFxcU1tcXHNcXFNdKilfX1xcYi9nLCBmdW5jdGlvbiAod20sIHR4dCkge1xuICAgICAgcmV0dXJuIHBhcnNlSW5zaWRlICh0eHQsICc8c3Ryb25nPicsICc8L3N0cm9uZz4nKTtcbiAgICB9KTtcbiAgICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC9cXGJfKFxcU1tcXHNcXFNdKj8pX1xcYi9nLCBmdW5jdGlvbiAod20sIHR4dCkge1xuICAgICAgcmV0dXJuIHBhcnNlSW5zaWRlICh0eHQsICc8ZW0+JywgJzwvZW0+Jyk7XG4gICAgfSk7XG4gIH0gZWxzZSB7XG4gICAgdGV4dCA9IHRleHQucmVwbGFjZSgvX19fKFxcU1tcXHNcXFNdKj8pX19fL2csIGZ1bmN0aW9uICh3bSwgbSkge1xuICAgICAgcmV0dXJuICgvXFxTJC8udGVzdChtKSkgPyBwYXJzZUluc2lkZSAobSwgJzxzdHJvbmc+PGVtPicsICc8L2VtPjwvc3Ryb25nPicpIDogd207XG4gICAgfSk7XG4gICAgdGV4dCA9IHRleHQucmVwbGFjZSgvX18oXFxTW1xcc1xcU10qPylfXy9nLCBmdW5jdGlvbiAod20sIG0pIHtcbiAgICAgIHJldHVybiAoL1xcUyQvLnRlc3QobSkpID8gcGFyc2VJbnNpZGUgKG0sICc8c3Ryb25nPicsICc8L3N0cm9uZz4nKSA6IHdtO1xuICAgIH0pO1xuICAgIHRleHQgPSB0ZXh0LnJlcGxhY2UoL18oW15cXHNfXVtcXHNcXFNdKj8pXy9nLCBmdW5jdGlvbiAod20sIG0pIHtcbiAgICAgIC8vICEvXl9bXl9dLy50ZXN0KG0pIC0gdGVzdCBpZiBpdCBkb2Vzbid0IHN0YXJ0IHdpdGggX18gKHNpbmNlIGl0IHNlZW1zIHJlZHVuZGFudCwgd2UgcmVtb3ZlZCBpdClcbiAgICAgIHJldHVybiAoL1xcUyQvLnRlc3QobSkpID8gcGFyc2VJbnNpZGUgKG0sICc8ZW0+JywgJzwvZW0+JykgOiB3bTtcbiAgICB9KTtcbiAgfVxuXG4gIC8vIE5vdyBwYXJzZSBhc3Rlcmlza3NcbiAgaWYgKG9wdGlvbnMubGl0ZXJhbE1pZFdvcmRBc3Rlcmlza3MpIHtcbiAgICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC8oW14qXXxeKVxcQlxcKlxcKlxcKihcXFNbXFxzXFxTXSs/KVxcKlxcKlxcKlxcQig/IVxcKikvZywgZnVuY3Rpb24gKHdtLCBsZWFkLCB0eHQpIHtcbiAgICAgIHJldHVybiBwYXJzZUluc2lkZSAodHh0LCBsZWFkICsgJzxzdHJvbmc+PGVtPicsICc8L2VtPjwvc3Ryb25nPicpO1xuICAgIH0pO1xuICAgIHRleHQgPSB0ZXh0LnJlcGxhY2UoLyhbXipdfF4pXFxCXFwqXFwqKFxcU1tcXHNcXFNdKz8pXFwqXFwqXFxCKD8hXFwqKS9nLCBmdW5jdGlvbiAod20sIGxlYWQsIHR4dCkge1xuICAgICAgcmV0dXJuIHBhcnNlSW5zaWRlICh0eHQsIGxlYWQgKyAnPHN0cm9uZz4nLCAnPC9zdHJvbmc+Jyk7XG4gICAgfSk7XG4gICAgdGV4dCA9IHRleHQucmVwbGFjZSgvKFteKl18XilcXEJcXCooXFxTW1xcc1xcU10rPylcXCpcXEIoPyFcXCopL2csIGZ1bmN0aW9uICh3bSwgbGVhZCwgdHh0KSB7XG4gICAgICByZXR1cm4gcGFyc2VJbnNpZGUgKHR4dCwgbGVhZCArICc8ZW0+JywgJzwvZW0+Jyk7XG4gICAgfSk7XG4gIH0gZWxzZSB7XG4gICAgdGV4dCA9IHRleHQucmVwbGFjZSgvXFwqXFwqXFwqKFxcU1tcXHNcXFNdKj8pXFwqXFwqXFwqL2csIGZ1bmN0aW9uICh3bSwgbSkge1xuICAgICAgcmV0dXJuICgvXFxTJC8udGVzdChtKSkgPyBwYXJzZUluc2lkZSAobSwgJzxzdHJvbmc+PGVtPicsICc8L2VtPjwvc3Ryb25nPicpIDogd207XG4gICAgfSk7XG4gICAgdGV4dCA9IHRleHQucmVwbGFjZSgvXFwqXFwqKFxcU1tcXHNcXFNdKj8pXFwqXFwqL2csIGZ1bmN0aW9uICh3bSwgbSkge1xuICAgICAgcmV0dXJuICgvXFxTJC8udGVzdChtKSkgPyBwYXJzZUluc2lkZSAobSwgJzxzdHJvbmc+JywgJzwvc3Ryb25nPicpIDogd207XG4gICAgfSk7XG4gICAgdGV4dCA9IHRleHQucmVwbGFjZSgvXFwqKFteXFxzKl1bXFxzXFxTXSo/KVxcKi9nLCBmdW5jdGlvbiAod20sIG0pIHtcbiAgICAgIC8vICEvXlxcKlteKl0vLnRlc3QobSkgLSB0ZXN0IGlmIGl0IGRvZXNuJ3Qgc3RhcnQgd2l0aCAqKiAoc2luY2UgaXQgc2VlbXMgcmVkdW5kYW50LCB3ZSByZW1vdmVkIGl0KVxuICAgICAgcmV0dXJuICgvXFxTJC8udGVzdChtKSkgPyBwYXJzZUluc2lkZSAobSwgJzxlbT4nLCAnPC9lbT4nKSA6IHdtO1xuICAgIH0pO1xuICB9XG5cblxuICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCdpdGFsaWNzQW5kQm9sZC5hZnRlcicsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICByZXR1cm4gdGV4dDtcbn0pO1xuXHJcbi8qKlxuICogRm9ybSBIVE1MIG9yZGVyZWQgKG51bWJlcmVkKSBhbmQgdW5vcmRlcmVkIChidWxsZXRlZCkgbGlzdHMuXG4gKi9cbnNob3dkb3duLnN1YlBhcnNlcignbGlzdHMnLCBmdW5jdGlvbiAodGV4dCwgb3B0aW9ucywgZ2xvYmFscykge1xuICAndXNlIHN0cmljdCc7XG5cbiAgLyoqXG4gICAqIFByb2Nlc3MgdGhlIGNvbnRlbnRzIG9mIGEgc2luZ2xlIG9yZGVyZWQgb3IgdW5vcmRlcmVkIGxpc3QsIHNwbGl0dGluZyBpdFxuICAgKiBpbnRvIGluZGl2aWR1YWwgbGlzdCBpdGVtcy5cbiAgICogQHBhcmFtIHtzdHJpbmd9IGxpc3RTdHJcbiAgICogQHBhcmFtIHtib29sZWFufSB0cmltVHJhaWxpbmdcbiAgICogQHJldHVybnMge3N0cmluZ31cbiAgICovXG4gIGZ1bmN0aW9uIHByb2Nlc3NMaXN0SXRlbXMgKGxpc3RTdHIsIHRyaW1UcmFpbGluZykge1xuICAgIC8vIFRoZSAkZ19saXN0X2xldmVsIGdsb2JhbCBrZWVwcyB0cmFjayBvZiB3aGVuIHdlJ3JlIGluc2lkZSBhIGxpc3QuXG4gICAgLy8gRWFjaCB0aW1lIHdlIGVudGVyIGEgbGlzdCwgd2UgaW5jcmVtZW50IGl0OyB3aGVuIHdlIGxlYXZlIGEgbGlzdCxcbiAgICAvLyB3ZSBkZWNyZW1lbnQuIElmIGl0J3MgemVybywgd2UncmUgbm90IGluIGEgbGlzdCBhbnltb3JlLlxuICAgIC8vXG4gICAgLy8gV2UgZG8gdGhpcyBiZWNhdXNlIHdoZW4gd2UncmUgbm90IGluc2lkZSBhIGxpc3QsIHdlIHdhbnQgdG8gdHJlYXRcbiAgICAvLyBzb21ldGhpbmcgbGlrZSB0aGlzOlxuICAgIC8vXG4gICAgLy8gICAgSSByZWNvbW1lbmQgdXBncmFkaW5nIHRvIHZlcnNpb25cbiAgICAvLyAgICA4LiBPb3BzLCBub3cgdGhpcyBsaW5lIGlzIHRyZWF0ZWRcbiAgICAvLyAgICBhcyBhIHN1Yi1saXN0LlxuICAgIC8vXG4gICAgLy8gQXMgYSBzaW5nbGUgcGFyYWdyYXBoLCBkZXNwaXRlIHRoZSBmYWN0IHRoYXQgdGhlIHNlY29uZCBsaW5lIHN0YXJ0c1xuICAgIC8vIHdpdGggYSBkaWdpdC1wZXJpb2Qtc3BhY2Ugc2VxdWVuY2UuXG4gICAgLy9cbiAgICAvLyBXaGVyZWFzIHdoZW4gd2UncmUgaW5zaWRlIGEgbGlzdCAob3Igc3ViLWxpc3QpLCB0aGF0IGxpbmUgd2lsbCBiZVxuICAgIC8vIHRyZWF0ZWQgYXMgdGhlIHN0YXJ0IG9mIGEgc3ViLWxpc3QuIFdoYXQgYSBrbHVkZ2UsIGh1aD8gVGhpcyBpc1xuICAgIC8vIGFuIGFzcGVjdCBvZiBNYXJrZG93bidzIHN5bnRheCB0aGF0J3MgaGFyZCB0byBwYXJzZSBwZXJmZWN0bHlcbiAgICAvLyB3aXRob3V0IHJlc29ydGluZyB0byBtaW5kLXJlYWRpbmcuIFBlcmhhcHMgdGhlIHNvbHV0aW9uIGlzIHRvXG4gICAgLy8gY2hhbmdlIHRoZSBzeW50YXggcnVsZXMgc3VjaCB0aGF0IHN1Yi1saXN0cyBtdXN0IHN0YXJ0IHdpdGggYVxuICAgIC8vIHN0YXJ0aW5nIGNhcmRpbmFsIG51bWJlcjsgZS5nLiBcIjEuXCIgb3IgXCJhLlwiLlxuICAgIGdsb2JhbHMuZ0xpc3RMZXZlbCsrO1xuXG4gICAgLy8gdHJpbSB0cmFpbGluZyBibGFuayBsaW5lczpcbiAgICBsaXN0U3RyID0gbGlzdFN0ci5yZXBsYWNlKC9cXG57Mix9JC8sICdcXG4nKTtcblxuICAgIC8vIGF0dGFja2xhYjogYWRkIHNlbnRpbmVsIHRvIGVtdWxhdGUgXFx6XG4gICAgbGlzdFN0ciArPSAnwqgwJztcblxuICAgIHZhciByZ3ggPSAvKFxcbik/KF4gezAsM30pKFsqKy1dfFxcZCtbLl0pWyBcXHRdKygoXFxbKHh8WHwgKT9dKT9bIFxcdF0qW15cXHJdKz8oXFxuezEsMn0pKSg/PVxcbioowqgwfCB7MCwzfShbKistXXxcXGQrWy5dKVsgXFx0XSspKS9nbSxcbiAgICAgICAgaXNQYXJhZ3JhcGhlZCA9ICgvXFxuWyBcXHRdKlxcbig/IcKoMCkvLnRlc3QobGlzdFN0cikpO1xuXG4gICAgLy8gU2luY2UgdmVyc2lvbiAxLjUsIG5lc3Rpbmcgc3VibGlzdHMgcmVxdWlyZXMgNCBzcGFjZXMgKG9yIDEgdGFiKSBpbmRlbnRhdGlvbixcbiAgICAvLyB3aGljaCBpcyBhIHN5bnRheCBicmVha2luZyBjaGFuZ2VcbiAgICAvLyBhY3RpdmF0aW5nIHRoaXMgb3B0aW9uIHJldmVydHMgdG8gb2xkIGJlaGF2aW9yXG4gICAgaWYgKG9wdGlvbnMuZGlzYWJsZUZvcmNlZDRTcGFjZXNJbmRlbnRlZFN1Ymxpc3RzKSB7XG4gICAgICByZ3ggPSAvKFxcbik/KF4gezAsM30pKFsqKy1dfFxcZCtbLl0pWyBcXHRdKygoXFxbKHh8WHwgKT9dKT9bIFxcdF0qW15cXHJdKz8oXFxuezEsMn0pKSg/PVxcbioowqgwfFxcMihbKistXXxcXGQrWy5dKVsgXFx0XSspKS9nbTtcbiAgICB9XG5cbiAgICBsaXN0U3RyID0gbGlzdFN0ci5yZXBsYWNlKHJneCwgZnVuY3Rpb24gKHdob2xlTWF0Y2gsIG0xLCBtMiwgbTMsIG00LCB0YXNrYnRuLCBjaGVja2VkKSB7XG4gICAgICBjaGVja2VkID0gKGNoZWNrZWQgJiYgY2hlY2tlZC50cmltKCkgIT09ICcnKTtcblxuICAgICAgdmFyIGl0ZW0gPSBzaG93ZG93bi5zdWJQYXJzZXIoJ291dGRlbnQnKShtNCwgb3B0aW9ucywgZ2xvYmFscyksXG4gICAgICAgICAgYnVsbGV0U3R5bGUgPSAnJztcblxuICAgICAgLy8gU3VwcG9ydCBmb3IgZ2l0aHViIHRhc2tsaXN0c1xuICAgICAgaWYgKHRhc2tidG4gJiYgb3B0aW9ucy50YXNrbGlzdHMpIHtcbiAgICAgICAgYnVsbGV0U3R5bGUgPSAnIGNsYXNzPVwidGFzay1saXN0LWl0ZW1cIiBzdHlsZT1cImxpc3Qtc3R5bGUtdHlwZTogbm9uZTtcIic7XG4gICAgICAgIGl0ZW0gPSBpdGVtLnJlcGxhY2UoL15bIFxcdF0qXFxbKHh8WHwgKT9dL20sIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICB2YXIgb3RwID0gJzxpbnB1dCB0eXBlPVwiY2hlY2tib3hcIiBkaXNhYmxlZCBzdHlsZT1cIm1hcmdpbjogMHB4IDAuMzVlbSAwLjI1ZW0gLTEuNmVtOyB2ZXJ0aWNhbC1hbGlnbjogbWlkZGxlO1wiJztcbiAgICAgICAgICBpZiAoY2hlY2tlZCkge1xuICAgICAgICAgICAgb3RwICs9ICcgY2hlY2tlZCc7XG4gICAgICAgICAgfVxuICAgICAgICAgIG90cCArPSAnPic7XG4gICAgICAgICAgcmV0dXJuIG90cDtcbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICAgIC8vIElTU1VFICMzMTJcbiAgICAgIC8vIFRoaXMgaW5wdXQ6IC0gLSAtIGFcbiAgICAgIC8vIGNhdXNlcyB0cm91YmxlIHRvIHRoZSBwYXJzZXIsIHNpbmNlIGl0IGludGVycHJldHMgaXQgYXM6XG4gICAgICAvLyA8dWw+PGxpPjxsaT48bGk+YTwvbGk+PC9saT48L2xpPjwvdWw+XG4gICAgICAvLyBpbnN0ZWFkIG9mOlxuICAgICAgLy8gPHVsPjxsaT4tIC0gYTwvbGk+PC91bD5cbiAgICAgIC8vIFNvLCB0byBwcmV2ZW50IGl0LCB3ZSB3aWxsIHB1dCBhIG1hcmtlciAowqhBKWluIHRoZSBiZWdpbm5pbmcgb2YgdGhlIGxpbmVcbiAgICAgIC8vIEtpbmQgb2YgaGFja2lzaC9tb25rZXkgcGF0Y2hpbmcsIGJ1dCBzZWVtcyBtb3JlIGVmZmVjdGl2ZSB0aGFuIG92ZXJjb21wbGljYXRpbmcgdGhlIGxpc3QgcGFyc2VyXG4gICAgICBpdGVtID0gaXRlbS5yZXBsYWNlKC9eKFstKitdfFxcZFxcLilbIFxcdF0rW1xcU1xcbiBdKi9nLCBmdW5jdGlvbiAod20yKSB7XG4gICAgICAgIHJldHVybiAnwqhBJyArIHdtMjtcbiAgICAgIH0pO1xuXG4gICAgICAvLyBtMSAtIExlYWRpbmcgbGluZSBvclxuICAgICAgLy8gSGFzIGEgZG91YmxlIHJldHVybiAobXVsdGkgcGFyYWdyYXBoKSBvclxuICAgICAgLy8gSGFzIHN1Ymxpc3RcbiAgICAgIGlmIChtMSB8fCAoaXRlbS5zZWFyY2goL1xcbnsyLH0vKSA+IC0xKSkge1xuICAgICAgICBpdGVtID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdnaXRodWJDb2RlQmxvY2tzJykoaXRlbSwgb3B0aW9ucywgZ2xvYmFscyk7XG4gICAgICAgIGl0ZW0gPSBzaG93ZG93bi5zdWJQYXJzZXIoJ2Jsb2NrR2FtdXQnKShpdGVtLCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIFJlY3Vyc2lvbiBmb3Igc3ViLWxpc3RzOlxuICAgICAgICBpdGVtID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdsaXN0cycpKGl0ZW0sIG9wdGlvbnMsIGdsb2JhbHMpO1xuICAgICAgICBpdGVtID0gaXRlbS5yZXBsYWNlKC9cXG4kLywgJycpOyAvLyBjaG9tcChpdGVtKVxuICAgICAgICBpdGVtID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdoYXNoSFRNTEJsb2NrcycpKGl0ZW0sIG9wdGlvbnMsIGdsb2JhbHMpO1xuXG4gICAgICAgIC8vIENvbGFwc2UgZG91YmxlIGxpbmVicmVha3NcbiAgICAgICAgaXRlbSA9IGl0ZW0ucmVwbGFjZSgvXFxuXFxuKy9nLCAnXFxuXFxuJyk7XG4gICAgICAgIGlmIChpc1BhcmFncmFwaGVkKSB7XG4gICAgICAgICAgaXRlbSA9IHNob3dkb3duLnN1YlBhcnNlcigncGFyYWdyYXBocycpKGl0ZW0sIG9wdGlvbnMsIGdsb2JhbHMpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGl0ZW0gPSBzaG93ZG93bi5zdWJQYXJzZXIoJ3NwYW5HYW11dCcpKGl0ZW0sIG9wdGlvbnMsIGdsb2JhbHMpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIC8vIG5vdyB3ZSBuZWVkIHRvIHJlbW92ZSB0aGUgbWFya2VyICjCqEEpXG4gICAgICBpdGVtID0gaXRlbS5yZXBsYWNlKCfCqEEnLCAnJyk7XG4gICAgICAvLyB3ZSBjYW4gZmluYWxseSB3cmFwIHRoZSBsaW5lIGluIGxpc3QgaXRlbSB0YWdzXG4gICAgICBpdGVtID0gICc8bGknICsgYnVsbGV0U3R5bGUgKyAnPicgKyBpdGVtICsgJzwvbGk+XFxuJztcblxuICAgICAgcmV0dXJuIGl0ZW07XG4gICAgfSk7XG5cbiAgICAvLyBhdHRhY2tsYWI6IHN0cmlwIHNlbnRpbmVsXG4gICAgbGlzdFN0ciA9IGxpc3RTdHIucmVwbGFjZSgvwqgwL2csICcnKTtcblxuICAgIGdsb2JhbHMuZ0xpc3RMZXZlbC0tO1xuXG4gICAgaWYgKHRyaW1UcmFpbGluZykge1xuICAgICAgbGlzdFN0ciA9IGxpc3RTdHIucmVwbGFjZSgvXFxzKyQvLCAnJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGxpc3RTdHI7XG4gIH1cblxuICBmdW5jdGlvbiBzdHlsZVN0YXJ0TnVtYmVyIChsaXN0LCBsaXN0VHlwZSkge1xuICAgIC8vIGNoZWNrIGlmIG9sIGFuZCBzdGFydHMgYnkgYSBudW1iZXIgZGlmZmVyZW50IHRoYW4gMVxuICAgIGlmIChsaXN0VHlwZSA9PT0gJ29sJykge1xuICAgICAgdmFyIHJlcyA9IGxpc3QubWF0Y2goL14gKihcXGQrKVxcLi8pO1xuICAgICAgaWYgKHJlcyAmJiByZXNbMV0gIT09ICcxJykge1xuICAgICAgICByZXR1cm4gJyBzdGFydD1cIicgKyByZXNbMV0gKyAnXCInO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gJyc7XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2sgYW5kIHBhcnNlIGNvbnNlY3V0aXZlIGxpc3RzIChiZXR0ZXIgZml4IGZvciBpc3N1ZSAjMTQyKVxuICAgKiBAcGFyYW0ge3N0cmluZ30gbGlzdFxuICAgKiBAcGFyYW0ge3N0cmluZ30gbGlzdFR5cGVcbiAgICogQHBhcmFtIHtib29sZWFufSB0cmltVHJhaWxpbmdcbiAgICogQHJldHVybnMge3N0cmluZ31cbiAgICovXG4gIGZ1bmN0aW9uIHBhcnNlQ29uc2VjdXRpdmVMaXN0cyAobGlzdCwgbGlzdFR5cGUsIHRyaW1UcmFpbGluZykge1xuICAgIC8vIGNoZWNrIGlmIHdlIGNhdWdodCAyIG9yIG1vcmUgY29uc2VjdXRpdmUgbGlzdHMgYnkgbWlzdGFrZVxuICAgIC8vIHdlIHVzZSB0aGUgY291bnRlclJneCwgbWVhbmluZyBpZiBsaXN0VHlwZSBpcyBVTCB3ZSBsb29rIGZvciBPTCBhbmQgdmljZSB2ZXJzYVxuICAgIHZhciBvbFJneCA9IChvcHRpb25zLmRpc2FibGVGb3JjZWQ0U3BhY2VzSW5kZW50ZWRTdWJsaXN0cykgPyAvXiA/XFxkK1xcLlsgXFx0XS9nbSA6IC9eIHswLDN9XFxkK1xcLlsgXFx0XS9nbSxcbiAgICAgICAgdWxSZ3ggPSAob3B0aW9ucy5kaXNhYmxlRm9yY2VkNFNwYWNlc0luZGVudGVkU3VibGlzdHMpID8gL14gP1sqKy1dWyBcXHRdL2dtIDogL14gezAsM31bKistXVsgXFx0XS9nbSxcbiAgICAgICAgY291bnRlclJ4ZyA9IChsaXN0VHlwZSA9PT0gJ3VsJykgPyBvbFJneCA6IHVsUmd4LFxuICAgICAgICByZXN1bHQgPSAnJztcblxuICAgIGlmIChsaXN0LnNlYXJjaChjb3VudGVyUnhnKSAhPT0gLTEpIHtcbiAgICAgIChmdW5jdGlvbiBwYXJzZUNMICh0eHQpIHtcbiAgICAgICAgdmFyIHBvcyA9IHR4dC5zZWFyY2goY291bnRlclJ4ZyksXG4gICAgICAgICAgICBzdHlsZSA9IHN0eWxlU3RhcnROdW1iZXIobGlzdCwgbGlzdFR5cGUpO1xuICAgICAgICBpZiAocG9zICE9PSAtMSkge1xuICAgICAgICAgIC8vIHNsaWNlXG4gICAgICAgICAgcmVzdWx0ICs9ICdcXG5cXG48JyArIGxpc3RUeXBlICsgc3R5bGUgKyAnPlxcbicgKyBwcm9jZXNzTGlzdEl0ZW1zKHR4dC5zbGljZSgwLCBwb3MpLCAhIXRyaW1UcmFpbGluZykgKyAnPC8nICsgbGlzdFR5cGUgKyAnPlxcbic7XG5cbiAgICAgICAgICAvLyBpbnZlcnQgY291bnRlclR5cGUgYW5kIGxpc3RUeXBlXG4gICAgICAgICAgbGlzdFR5cGUgPSAobGlzdFR5cGUgPT09ICd1bCcpID8gJ29sJyA6ICd1bCc7XG4gICAgICAgICAgY291bnRlclJ4ZyA9IChsaXN0VHlwZSA9PT0gJ3VsJykgPyBvbFJneCA6IHVsUmd4O1xuXG4gICAgICAgICAgLy9yZWN1cnNlXG4gICAgICAgICAgcGFyc2VDTCh0eHQuc2xpY2UocG9zKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmVzdWx0ICs9ICdcXG5cXG48JyArIGxpc3RUeXBlICsgc3R5bGUgKyAnPlxcbicgKyBwcm9jZXNzTGlzdEl0ZW1zKHR4dCwgISF0cmltVHJhaWxpbmcpICsgJzwvJyArIGxpc3RUeXBlICsgJz5cXG4nO1xuICAgICAgICB9XG4gICAgICB9KShsaXN0KTtcbiAgICB9IGVsc2Uge1xuICAgICAgdmFyIHN0eWxlID0gc3R5bGVTdGFydE51bWJlcihsaXN0LCBsaXN0VHlwZSk7XG4gICAgICByZXN1bHQgPSAnXFxuXFxuPCcgKyBsaXN0VHlwZSArIHN0eWxlICsgJz5cXG4nICsgcHJvY2Vzc0xpc3RJdGVtcyhsaXN0LCAhIXRyaW1UcmFpbGluZykgKyAnPC8nICsgbGlzdFR5cGUgKyAnPlxcbic7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIC8qKiBTdGFydCBvZiBsaXN0IHBhcnNpbmcgKiovXG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ2xpc3RzLmJlZm9yZScsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICAvLyBhZGQgc2VudGluZWwgdG8gaGFjayBhcm91bmQga2h0bWwvc2FmYXJpIGJ1ZzpcbiAgLy8gaHR0cDovL2J1Z3Mud2Via2l0Lm9yZy9zaG93X2J1Zy5jZ2k/aWQ9MTEyMzFcbiAgdGV4dCArPSAnwqgwJztcblxuICBpZiAoZ2xvYmFscy5nTGlzdExldmVsKSB7XG4gICAgdGV4dCA9IHRleHQucmVwbGFjZSgvXigoIHswLDN9KFsqKy1dfFxcZCtbLl0pWyBcXHRdKylbXlxccl0rPyjCqDB8XFxuezIsfSg/PVxcUykoPyFbIFxcdF0qKD86WyorLV18XFxkK1suXSlbIFxcdF0rKSkpL2dtLFxuICAgICAgZnVuY3Rpb24gKHdob2xlTWF0Y2gsIGxpc3QsIG0yKSB7XG4gICAgICAgIHZhciBsaXN0VHlwZSA9IChtMi5zZWFyY2goL1sqKy1dL2cpID4gLTEpID8gJ3VsJyA6ICdvbCc7XG4gICAgICAgIHJldHVybiBwYXJzZUNvbnNlY3V0aXZlTGlzdHMobGlzdCwgbGlzdFR5cGUsIHRydWUpO1xuICAgICAgfVxuICAgICk7XG4gIH0gZWxzZSB7XG4gICAgdGV4dCA9IHRleHQucmVwbGFjZSgvKFxcblxcbnxeXFxuPykoKCB7MCwzfShbKistXXxcXGQrWy5dKVsgXFx0XSspW15cXHJdKz8owqgwfFxcbnsyLH0oPz1cXFMpKD8hWyBcXHRdKig/OlsqKy1dfFxcZCtbLl0pWyBcXHRdKykpKS9nbSxcbiAgICAgIGZ1bmN0aW9uICh3aG9sZU1hdGNoLCBtMSwgbGlzdCwgbTMpIHtcbiAgICAgICAgdmFyIGxpc3RUeXBlID0gKG0zLnNlYXJjaCgvWyorLV0vZykgPiAtMSkgPyAndWwnIDogJ29sJztcbiAgICAgICAgcmV0dXJuIHBhcnNlQ29uc2VjdXRpdmVMaXN0cyhsaXN0LCBsaXN0VHlwZSwgZmFsc2UpO1xuICAgICAgfVxuICAgICk7XG4gIH1cblxuICAvLyBzdHJpcCBzZW50aW5lbFxuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC/CqDAvLCAnJyk7XG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ2xpc3RzLmFmdGVyJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gIHJldHVybiB0ZXh0O1xufSk7XG5cclxuLyoqXG4gKiBQYXJzZSBtZXRhZGF0YSBhdCB0aGUgdG9wIG9mIHRoZSBkb2N1bWVudFxuICovXG5zaG93ZG93bi5zdWJQYXJzZXIoJ21ldGFkYXRhJywgZnVuY3Rpb24gKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuXG4gIGlmICghb3B0aW9ucy5tZXRhZGF0YSkge1xuICAgIHJldHVybiB0ZXh0O1xuICB9XG5cbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgnbWV0YWRhdGEuYmVmb3JlJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG5cbiAgZnVuY3Rpb24gcGFyc2VNZXRhZGF0YUNvbnRlbnRzIChjb250ZW50KSB7XG4gICAgLy8gcmF3IGlzIHJhdyBzbyBpdCdzIG5vdCBjaGFuZ2VkIGluIGFueSB3YXlcbiAgICBnbG9iYWxzLm1ldGFkYXRhLnJhdyA9IGNvbnRlbnQ7XG5cbiAgICAvLyBlc2NhcGUgY2hhcnMgZm9yYmlkZGVuIGluIGh0bWwgYXR0cmlidXRlc1xuICAgIC8vIGRvdWJsZSBxdW90ZXNcbiAgICBjb250ZW50ID0gY29udGVudFxuICAgICAgLy8gYW1wZXJzYW5kIGZpcnN0XG4gICAgICAucmVwbGFjZSgvJi9nLCAnJmFtcDsnKVxuICAgICAgLy8gZG91YmxlIHF1b3Rlc1xuICAgICAgLnJlcGxhY2UoL1wiL2csICcmcXVvdDsnKTtcblxuICAgIGNvbnRlbnQgPSBjb250ZW50LnJlcGxhY2UoL1xcbiB7NH0vZywgJyAnKTtcbiAgICBjb250ZW50LnJlcGxhY2UoL14oW1xcUyBdKyk6ICsoW1xcc1xcU10rPykkL2dtLCBmdW5jdGlvbiAod20sIGtleSwgdmFsdWUpIHtcbiAgICAgIGdsb2JhbHMubWV0YWRhdGEucGFyc2VkW2tleV0gPSB2YWx1ZTtcbiAgICAgIHJldHVybiAnJztcbiAgICB9KTtcbiAgfVxuXG4gIHRleHQgPSB0ZXh0LnJlcGxhY2UoL15cXHMqwqvCq8KrKyhcXFMqPylcXG4oW1xcc1xcU10rPylcXG7Cu8K7wrsrXFxuLywgZnVuY3Rpb24gKHdob2xlbWF0Y2gsIGZvcm1hdCwgY29udGVudCkge1xuICAgIHBhcnNlTWV0YWRhdGFDb250ZW50cyhjb250ZW50KTtcbiAgICByZXR1cm4gJ8KoTSc7XG4gIH0pO1xuXG4gIHRleHQgPSB0ZXh0LnJlcGxhY2UoL15cXHMqLS0tKyhcXFMqPylcXG4oW1xcc1xcU10rPylcXG4tLS0rXFxuLywgZnVuY3Rpb24gKHdob2xlbWF0Y2gsIGZvcm1hdCwgY29udGVudCkge1xuICAgIGlmIChmb3JtYXQpIHtcbiAgICAgIGdsb2JhbHMubWV0YWRhdGEuZm9ybWF0ID0gZm9ybWF0O1xuICAgIH1cbiAgICBwYXJzZU1ldGFkYXRhQ29udGVudHMoY29udGVudCk7XG4gICAgcmV0dXJuICfCqE0nO1xuICB9KTtcblxuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC/CqE0vZywgJycpO1xuXG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ21ldGFkYXRhLmFmdGVyJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gIHJldHVybiB0ZXh0O1xufSk7XG5cclxuLyoqXG4gKiBSZW1vdmUgb25lIGxldmVsIG9mIGxpbmUtbGVhZGluZyB0YWJzIG9yIHNwYWNlc1xuICovXG5zaG93ZG93bi5zdWJQYXJzZXIoJ291dGRlbnQnLCBmdW5jdGlvbiAodGV4dCwgb3B0aW9ucywgZ2xvYmFscykge1xuICAndXNlIHN0cmljdCc7XG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ291dGRlbnQuYmVmb3JlJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG5cbiAgLy8gYXR0YWNrbGFiOiBoYWNrIGFyb3VuZCBLb25xdWVyb3IgMy41LjQgYnVnOlxuICAvLyBcIi0tLS0tLS0tLS1idWdcIi5yZXBsYWNlKC9eLS9nLFwiXCIpID09IFwiYnVnXCJcbiAgdGV4dCA9IHRleHQucmVwbGFjZSgvXihcXHR8WyBdezEsNH0pL2dtLCAnwqgwJyk7IC8vIGF0dGFja2xhYjogZ190YWJfd2lkdGhcblxuICAvLyBhdHRhY2tsYWI6IGNsZWFuIHVwIGhhY2tcbiAgdGV4dCA9IHRleHQucmVwbGFjZSgvwqgwL2csICcnKTtcblxuICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCdvdXRkZW50LmFmdGVyJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gIHJldHVybiB0ZXh0O1xufSk7XG5cclxuLyoqXG4gKlxuICovXG5zaG93ZG93bi5zdWJQYXJzZXIoJ3BhcmFncmFwaHMnLCBmdW5jdGlvbiAodGV4dCwgb3B0aW9ucywgZ2xvYmFscykge1xuICAndXNlIHN0cmljdCc7XG5cbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgncGFyYWdyYXBocy5iZWZvcmUnLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgLy8gU3RyaXAgbGVhZGluZyBhbmQgdHJhaWxpbmcgbGluZXM6XG4gIHRleHQgPSB0ZXh0LnJlcGxhY2UoL15cXG4rL2csICcnKTtcbiAgdGV4dCA9IHRleHQucmVwbGFjZSgvXFxuKyQvZywgJycpO1xuXG4gIHZhciBncmFmcyA9IHRleHQuc3BsaXQoL1xcbnsyLH0vZyksXG4gICAgICBncmFmc091dCA9IFtdLFxuICAgICAgZW5kID0gZ3JhZnMubGVuZ3RoOyAvLyBXcmFwIDxwPiB0YWdzXG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBlbmQ7IGkrKykge1xuICAgIHZhciBzdHIgPSBncmFmc1tpXTtcbiAgICAvLyBpZiB0aGlzIGlzIGFuIEhUTUwgbWFya2VyLCBjb3B5IGl0XG4gICAgaWYgKHN0ci5zZWFyY2goL8KoKEt8RykoXFxkKylcXDEvZykgPj0gMCkge1xuICAgICAgZ3JhZnNPdXQucHVzaChzdHIpO1xuXG4gICAgLy8gdGVzdCBmb3IgcHJlc2VuY2Ugb2YgY2hhcmFjdGVycyB0byBwcmV2ZW50IGVtcHR5IGxpbmVzIGJlaW5nIHBhcnNlZFxuICAgIC8vIGFzIHBhcmFncmFwaHMgKHJlc3VsdGluZyBpbiB1bmRlc2lyZWQgZXh0cmEgZW1wdHkgcGFyYWdyYXBocylcbiAgICB9IGVsc2UgaWYgKHN0ci5zZWFyY2goL1xcUy8pID49IDApIHtcbiAgICAgIHN0ciA9IHNob3dkb3duLnN1YlBhcnNlcignc3BhbkdhbXV0Jykoc3RyLCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgICAgIHN0ciA9IHN0ci5yZXBsYWNlKC9eKFsgXFx0XSopL2csICc8cD4nKTtcbiAgICAgIHN0ciArPSAnPC9wPic7XG4gICAgICBncmFmc091dC5wdXNoKHN0cik7XG4gICAgfVxuICB9XG5cbiAgLyoqIFVuaGFzaGlmeSBIVE1MIGJsb2NrcyAqL1xuICBlbmQgPSBncmFmc091dC5sZW5ndGg7XG4gIGZvciAoaSA9IDA7IGkgPCBlbmQ7IGkrKykge1xuICAgIHZhciBibG9ja1RleHQgPSAnJyxcbiAgICAgICAgZ3JhZnNPdXRJdCA9IGdyYWZzT3V0W2ldLFxuICAgICAgICBjb2RlRmxhZyA9IGZhbHNlO1xuICAgIC8vIGlmIHRoaXMgaXMgYSBtYXJrZXIgZm9yIGFuIGh0bWwgYmxvY2suLi5cbiAgICAvLyB1c2UgUmVnRXhwLnRlc3QgaW5zdGVhZCBvZiBzdHJpbmcuc2VhcmNoIGJlY2F1c2Ugb2YgUU1MIGJ1Z1xuICAgIHdoaWxlICgvwqgoS3xHKShcXGQrKVxcMS8udGVzdChncmFmc091dEl0KSkge1xuICAgICAgdmFyIGRlbGltID0gUmVnRXhwLiQxLFxuICAgICAgICAgIG51bSAgID0gUmVnRXhwLiQyO1xuXG4gICAgICBpZiAoZGVsaW0gPT09ICdLJykge1xuICAgICAgICBibG9ja1RleHQgPSBnbG9iYWxzLmdIdG1sQmxvY2tzW251bV07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyB3ZSBuZWVkIHRvIGNoZWNrIGlmIGdoQmxvY2sgaXMgYSBmYWxzZSBwb3NpdGl2ZVxuICAgICAgICBpZiAoY29kZUZsYWcpIHtcbiAgICAgICAgICAvLyB1c2UgZW5jb2RlZCB2ZXJzaW9uIG9mIGFsbCB0ZXh0XG4gICAgICAgICAgYmxvY2tUZXh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdlbmNvZGVDb2RlJykoZ2xvYmFscy5naENvZGVCbG9ja3NbbnVtXS50ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBibG9ja1RleHQgPSBnbG9iYWxzLmdoQ29kZUJsb2Nrc1tudW1dLmNvZGVibG9jaztcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgYmxvY2tUZXh0ID0gYmxvY2tUZXh0LnJlcGxhY2UoL1xcJC9nLCAnJCQkJCcpOyAvLyBFc2NhcGUgYW55IGRvbGxhciBzaWduc1xuXG4gICAgICBncmFmc091dEl0ID0gZ3JhZnNPdXRJdC5yZXBsYWNlKC8oXFxuXFxuKT/CqChLfEcpXFxkK1xcMihcXG5cXG4pPy8sIGJsb2NrVGV4dCk7XG4gICAgICAvLyBDaGVjayBpZiBncmFmc091dEl0IGlzIGEgcHJlLT5jb2RlXG4gICAgICBpZiAoL148cHJlXFxiW14+XSo+XFxzKjxjb2RlXFxiW14+XSo+Ly50ZXN0KGdyYWZzT3V0SXQpKSB7XG4gICAgICAgIGNvZGVGbGFnID0gdHJ1ZTtcbiAgICAgIH1cbiAgICB9XG4gICAgZ3JhZnNPdXRbaV0gPSBncmFmc091dEl0O1xuICB9XG4gIHRleHQgPSBncmFmc091dC5qb2luKCdcXG4nKTtcbiAgLy8gU3RyaXAgbGVhZGluZyBhbmQgdHJhaWxpbmcgbGluZXM6XG4gIHRleHQgPSB0ZXh0LnJlcGxhY2UoL15cXG4rL2csICcnKTtcbiAgdGV4dCA9IHRleHQucmVwbGFjZSgvXFxuKyQvZywgJycpO1xuICByZXR1cm4gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCdwYXJhZ3JhcGhzLmFmdGVyJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG59KTtcblxyXG4vKipcbiAqIFJ1biBleHRlbnNpb25cbiAqL1xuc2hvd2Rvd24uc3ViUGFyc2VyKCdydW5FeHRlbnNpb24nLCBmdW5jdGlvbiAoZXh0LCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICBpZiAoZXh0LmZpbHRlcikge1xuICAgIHRleHQgPSBleHQuZmlsdGVyKHRleHQsIGdsb2JhbHMuY29udmVydGVyLCBvcHRpb25zKTtcblxuICB9IGVsc2UgaWYgKGV4dC5yZWdleCkge1xuICAgIC8vIFRPRE8gcmVtb3ZlIHRoaXMgd2hlbiBvbGQgZXh0ZW5zaW9uIGxvYWRpbmcgbWVjaGFuaXNtIGlzIGRlcHJlY2F0ZWRcbiAgICB2YXIgcmUgPSBleHQucmVnZXg7XG4gICAgaWYgKCEocmUgaW5zdGFuY2VvZiBSZWdFeHApKSB7XG4gICAgICByZSA9IG5ldyBSZWdFeHAocmUsICdnJyk7XG4gICAgfVxuICAgIHRleHQgPSB0ZXh0LnJlcGxhY2UocmUsIGV4dC5yZXBsYWNlKTtcbiAgfVxuXG4gIHJldHVybiB0ZXh0O1xufSk7XG5cclxuLyoqXG4gKiBUaGVzZSBhcmUgYWxsIHRoZSB0cmFuc2Zvcm1hdGlvbnMgdGhhdCBvY2N1ciAqd2l0aGluKiBibG9jay1sZXZlbFxuICogdGFncyBsaWtlIHBhcmFncmFwaHMsIGhlYWRlcnMsIGFuZCBsaXN0IGl0ZW1zLlxuICovXG5zaG93ZG93bi5zdWJQYXJzZXIoJ3NwYW5HYW11dCcsIGZ1bmN0aW9uICh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCdzcGFuR2FtdXQuYmVmb3JlJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gIHRleHQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ2NvZGVTcGFucycpKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICB0ZXh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdlc2NhcGVTcGVjaWFsQ2hhcnNXaXRoaW5UYWdBdHRyaWJ1dGVzJykodGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gIHRleHQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ2VuY29kZUJhY2tzbGFzaEVzY2FwZXMnKSh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcblxuICAvLyBQcm9jZXNzIGFuY2hvciBhbmQgaW1hZ2UgdGFncy4gSW1hZ2VzIG11c3QgY29tZSBmaXJzdCxcbiAgLy8gYmVjYXVzZSAhW2Zvb11bZl0gbG9va3MgbGlrZSBhbiBhbmNob3IuXG4gIHRleHQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ2ltYWdlcycpKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICB0ZXh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdhbmNob3JzJykodGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG5cbiAgLy8gTWFrZSBsaW5rcyBvdXQgb2YgdGhpbmdzIGxpa2UgYDxodHRwOi8vZXhhbXBsZS5jb20vPmBcbiAgLy8gTXVzdCBjb21lIGFmdGVyIGFuY2hvcnMsIGJlY2F1c2UgeW91IGNhbiB1c2UgPCBhbmQgPlxuICAvLyBkZWxpbWl0ZXJzIGluIGlubGluZSBsaW5rcyBsaWtlIFt0aGlzXSg8dXJsPikuXG4gIHRleHQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ2F1dG9MaW5rcycpKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICB0ZXh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdzaW1wbGlmaWVkQXV0b0xpbmtzJykodGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gIHRleHQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ2Vtb2ppJykodGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gIHRleHQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ3VuZGVybGluZScpKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICB0ZXh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdpdGFsaWNzQW5kQm9sZCcpKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICB0ZXh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdzdHJpa2V0aHJvdWdoJykodGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gIHRleHQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ2VsbGlwc2lzJykodGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG5cbiAgLy8gd2UgbmVlZCB0byBoYXNoIEhUTUwgdGFncyBpbnNpZGUgc3BhbnNcbiAgdGV4dCA9IHNob3dkb3duLnN1YlBhcnNlcignaGFzaEhUTUxTcGFucycpKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuXG4gIC8vIG5vdyB3ZSBlbmNvZGUgYW1wcyBhbmQgYW5nbGVzXG4gIHRleHQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ2VuY29kZUFtcHNBbmRBbmdsZXMnKSh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcblxuICAvLyBEbyBoYXJkIGJyZWFrc1xuICBpZiAob3B0aW9ucy5zaW1wbGVMaW5lQnJlYWtzKSB7XG4gICAgLy8gR0ZNIHN0eWxlIGhhcmQgYnJlYWtzXG4gICAgLy8gb25seSBhZGQgbGluZSBicmVha3MgaWYgdGhlIHRleHQgZG9lcyBub3QgY29udGFpbiBhIGJsb2NrIChzcGVjaWFsIGNhc2UgZm9yIGxpc3RzKVxuICAgIGlmICghL1xcblxcbsKoSy8udGVzdCh0ZXh0KSkge1xuICAgICAgdGV4dCA9IHRleHQucmVwbGFjZSgvXFxuKy9nLCAnPGJyIC8+XFxuJyk7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIC8vIFZhbmlsbGEgaGFyZCBicmVha3NcbiAgICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC8gICtcXG4vZywgJzxiciAvPlxcbicpO1xuICB9XG5cbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgnc3BhbkdhbXV0LmFmdGVyJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gIHJldHVybiB0ZXh0O1xufSk7XG5cclxuc2hvd2Rvd24uc3ViUGFyc2VyKCdzdHJpa2V0aHJvdWdoJywgZnVuY3Rpb24gKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuXG4gIGZ1bmN0aW9uIHBhcnNlSW5zaWRlICh0eHQpIHtcbiAgICBpZiAob3B0aW9ucy5zaW1wbGlmaWVkQXV0b0xpbmspIHtcbiAgICAgIHR4dCA9IHNob3dkb3duLnN1YlBhcnNlcignc2ltcGxpZmllZEF1dG9MaW5rcycpKHR4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gICAgfVxuICAgIHJldHVybiAnPGRlbD4nICsgdHh0ICsgJzwvZGVsPic7XG4gIH1cblxuICBpZiAob3B0aW9ucy5zdHJpa2V0aHJvdWdoKSB7XG4gICAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgnc3RyaWtldGhyb3VnaC5iZWZvcmUnLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC8oPzp+KXsyfShbXFxzXFxTXSs/KSg/On4pezJ9L2csIGZ1bmN0aW9uICh3bSwgdHh0KSB7IHJldHVybiBwYXJzZUluc2lkZSh0eHQpOyB9KTtcbiAgICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCdzdHJpa2V0aHJvdWdoLmFmdGVyJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gIH1cblxuICByZXR1cm4gdGV4dDtcbn0pO1xuXHJcbi8qKlxuICogU3RyaXBzIGxpbmsgZGVmaW5pdGlvbnMgZnJvbSB0ZXh0LCBzdG9yZXMgdGhlIFVSTHMgYW5kIHRpdGxlcyBpblxuICogaGFzaCByZWZlcmVuY2VzLlxuICogTGluayBkZWZzIGFyZSBpbiB0aGUgZm9ybTogXltpZF06IHVybCBcIm9wdGlvbmFsIHRpdGxlXCJcbiAqL1xuc2hvd2Rvd24uc3ViUGFyc2VyKCdzdHJpcExpbmtEZWZpbml0aW9ucycsIGZ1bmN0aW9uICh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICB2YXIgcmVnZXggICAgICAgPSAvXiB7MCwzfVxcWyguKyldOlsgXFx0XSpcXG4/WyBcXHRdKjw/KFtePlxcc10rKT4/KD86ID0oWypcXGRdK1tBLVphLXolXXswLDR9KXgoWypcXGRdK1tBLVphLXolXXswLDR9KSk/WyBcXHRdKlxcbj9bIFxcdF0qKD86KFxcbiopW1wifCcoXSguKz8pW1wifCcpXVsgXFx0XSopPyg/Olxcbit8KD89wqgwKSkvZ20sXG4gICAgICBiYXNlNjRSZWdleCA9IC9eIHswLDN9XFxbKC4rKV06WyBcXHRdKlxcbj9bIFxcdF0qPD8oZGF0YTouKz9cXC8uKz87YmFzZTY0LFtBLVphLXowLTkrLz1cXG5dKz8pPj8oPzogPShbKlxcZF0rW0EtWmEteiVdezAsNH0peChbKlxcZF0rW0EtWmEteiVdezAsNH0pKT9bIFxcdF0qXFxuP1sgXFx0XSooPzooXFxuKilbXCJ8JyhdKC4rPylbXCJ8JyldWyBcXHRdKik/KD86XFxuXFxufCg/PcKoMCl8KD89XFxuXFxbKSkvZ207XG5cbiAgLy8gYXR0YWNrbGFiOiBzZW50aW5lbCB3b3JrYXJvdW5kcyBmb3IgbGFjayBvZiBcXEEgYW5kIFxcWiwgc2FmYXJpXFxraHRtbCBidWdcbiAgdGV4dCArPSAnwqgwJztcblxuICB2YXIgcmVwbGFjZUZ1bmMgPSBmdW5jdGlvbiAod2hvbGVNYXRjaCwgbGlua0lkLCB1cmwsIHdpZHRoLCBoZWlnaHQsIGJsYW5rTGluZXMsIHRpdGxlKSB7XG4gICAgbGlua0lkID0gbGlua0lkLnRvTG93ZXJDYXNlKCk7XG4gICAgaWYgKHVybC5tYXRjaCgvXmRhdGE6Lis/XFwvLis/O2Jhc2U2NCwvKSkge1xuICAgICAgLy8gcmVtb3ZlIG5ld2xpbmVzXG4gICAgICBnbG9iYWxzLmdVcmxzW2xpbmtJZF0gPSB1cmwucmVwbGFjZSgvXFxzL2csICcnKTtcbiAgICB9IGVsc2Uge1xuICAgICAgZ2xvYmFscy5nVXJsc1tsaW5rSWRdID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdlbmNvZGVBbXBzQW5kQW5nbGVzJykodXJsLCBvcHRpb25zLCBnbG9iYWxzKTsgIC8vIExpbmsgSURzIGFyZSBjYXNlLWluc2Vuc2l0aXZlXG4gICAgfVxuXG4gICAgaWYgKGJsYW5rTGluZXMpIHtcbiAgICAgIC8vIE9vcHMsIGZvdW5kIGJsYW5rIGxpbmVzLCBzbyBpdCdzIG5vdCBhIHRpdGxlLlxuICAgICAgLy8gUHV0IGJhY2sgdGhlIHBhcmVudGhldGljYWwgc3RhdGVtZW50IHdlIHN0b2xlLlxuICAgICAgcmV0dXJuIGJsYW5rTGluZXMgKyB0aXRsZTtcblxuICAgIH0gZWxzZSB7XG4gICAgICBpZiAodGl0bGUpIHtcbiAgICAgICAgZ2xvYmFscy5nVGl0bGVzW2xpbmtJZF0gPSB0aXRsZS5yZXBsYWNlKC9cInwnL2csICcmcXVvdDsnKTtcbiAgICAgIH1cbiAgICAgIGlmIChvcHRpb25zLnBhcnNlSW1nRGltZW5zaW9ucyAmJiB3aWR0aCAmJiBoZWlnaHQpIHtcbiAgICAgICAgZ2xvYmFscy5nRGltZW5zaW9uc1tsaW5rSWRdID0ge1xuICAgICAgICAgIHdpZHRoOiAgd2lkdGgsXG4gICAgICAgICAgaGVpZ2h0OiBoZWlnaHRcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICB9XG4gICAgLy8gQ29tcGxldGVseSByZW1vdmUgdGhlIGRlZmluaXRpb24gZnJvbSB0aGUgdGV4dFxuICAgIHJldHVybiAnJztcbiAgfTtcblxuICAvLyBmaXJzdCB3ZSB0cnkgdG8gZmluZCBiYXNlNjQgbGluayByZWZlcmVuY2VzXG4gIHRleHQgPSB0ZXh0LnJlcGxhY2UoYmFzZTY0UmVnZXgsIHJlcGxhY2VGdW5jKTtcblxuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKHJlZ2V4LCByZXBsYWNlRnVuYyk7XG5cbiAgLy8gYXR0YWNrbGFiOiBzdHJpcCBzZW50aW5lbFxuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC/CqDAvLCAnJyk7XG5cbiAgcmV0dXJuIHRleHQ7XG59KTtcblxyXG5zaG93ZG93bi5zdWJQYXJzZXIoJ3RhYmxlcycsIGZ1bmN0aW9uICh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICBpZiAoIW9wdGlvbnMudGFibGVzKSB7XG4gICAgcmV0dXJuIHRleHQ7XG4gIH1cblxuICB2YXIgdGFibGVSZ3ggICAgICAgPSAvXiB7MCwzfVxcfD8uK1xcfC4rXFxuIHswLDN9XFx8P1sgXFx0XSo6P1sgXFx0XSooPzpbLT1dKXsyLH1bIFxcdF0qOj9bIFxcdF0qXFx8WyBcXHRdKjo/WyBcXHRdKig/OlstPV0pezIsfVtcXHNcXFNdKz8oPzpcXG5cXG58wqgwKS9nbSxcbiAgICAvL3NpbmdlQ29sVGJsUmd4ID0gL14gezAsM31cXHwuK1xcfFxcbiB7MCwzfVxcfFsgXFx0XSo6P1sgXFx0XSooPzpbLT1dKXsyLH1bIFxcdF0qOj9bIFxcdF0qXFx8WyBcXHRdKlxcbig/OiB7MCwzfVxcfC4rXFx8XFxuKSsoPzpcXG5cXG58wqgwKS9nbTtcbiAgICAgIHNpbmdlQ29sVGJsUmd4ID0gL14gezAsM31cXHwuK1xcfFsgXFx0XSpcXG4gezAsM31cXHxbIFxcdF0qOj9bIFxcdF0qKD86Wy09XSl7Mix9WyBcXHRdKjo/WyBcXHRdKlxcfFsgXFx0XSpcXG4oIHswLDN9XFx8LitcXHxbIFxcdF0qXFxuKSooPzpcXG58wqgwKS9nbTtcblxuICBmdW5jdGlvbiBwYXJzZVN0eWxlcyAoc0xpbmUpIHtcbiAgICBpZiAoL146WyBcXHRdKi0tKiQvLnRlc3Qoc0xpbmUpKSB7XG4gICAgICByZXR1cm4gJyBzdHlsZT1cInRleHQtYWxpZ246bGVmdDtcIic7XG4gICAgfSBlbHNlIGlmICgvXi0tKlsgXFx0XSo6WyBcXHRdKiQvLnRlc3Qoc0xpbmUpKSB7XG4gICAgICByZXR1cm4gJyBzdHlsZT1cInRleHQtYWxpZ246cmlnaHQ7XCInO1xuICAgIH0gZWxzZSBpZiAoL146WyBcXHRdKi0tKlsgXFx0XSo6JC8udGVzdChzTGluZSkpIHtcbiAgICAgIHJldHVybiAnIHN0eWxlPVwidGV4dC1hbGlnbjpjZW50ZXI7XCInO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gJyc7XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gcGFyc2VIZWFkZXJzIChoZWFkZXIsIHN0eWxlKSB7XG4gICAgdmFyIGlkID0gJyc7XG4gICAgaGVhZGVyID0gaGVhZGVyLnRyaW0oKTtcbiAgICAvLyBzdXBwb3J0IGJvdGggdGFibGVzSGVhZGVySWQgYW5kIHRhYmxlSGVhZGVySWQgZHVlIHRvIGVycm9yIGluIGRvY3VtZW50YXRpb24gc28gd2UgZG9uJ3QgYnJlYWsgYmFja3dhcmRzIGNvbXBhdGliaWxpdHlcbiAgICBpZiAob3B0aW9ucy50YWJsZXNIZWFkZXJJZCB8fCBvcHRpb25zLnRhYmxlSGVhZGVySWQpIHtcbiAgICAgIGlkID0gJyBpZD1cIicgKyBoZWFkZXIucmVwbGFjZSgvIC9nLCAnXycpLnRvTG93ZXJDYXNlKCkgKyAnXCInO1xuICAgIH1cbiAgICBoZWFkZXIgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ3NwYW5HYW11dCcpKGhlYWRlciwgb3B0aW9ucywgZ2xvYmFscyk7XG5cbiAgICByZXR1cm4gJzx0aCcgKyBpZCArIHN0eWxlICsgJz4nICsgaGVhZGVyICsgJzwvdGg+XFxuJztcbiAgfVxuXG4gIGZ1bmN0aW9uIHBhcnNlQ2VsbHMgKGNlbGwsIHN0eWxlKSB7XG4gICAgdmFyIHN1YlRleHQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ3NwYW5HYW11dCcpKGNlbGwsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICAgIHJldHVybiAnPHRkJyArIHN0eWxlICsgJz4nICsgc3ViVGV4dCArICc8L3RkPlxcbic7XG4gIH1cblxuICBmdW5jdGlvbiBidWlsZFRhYmxlIChoZWFkZXJzLCBjZWxscykge1xuICAgIHZhciB0YiA9ICc8dGFibGU+XFxuPHRoZWFkPlxcbjx0cj5cXG4nLFxuICAgICAgICB0YmxMZ24gPSBoZWFkZXJzLmxlbmd0aDtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGJsTGduOyArK2kpIHtcbiAgICAgIHRiICs9IGhlYWRlcnNbaV07XG4gICAgfVxuICAgIHRiICs9ICc8L3RyPlxcbjwvdGhlYWQ+XFxuPHRib2R5Plxcbic7XG5cbiAgICBmb3IgKGkgPSAwOyBpIDwgY2VsbHMubGVuZ3RoOyArK2kpIHtcbiAgICAgIHRiICs9ICc8dHI+XFxuJztcbiAgICAgIGZvciAodmFyIGlpID0gMDsgaWkgPCB0YmxMZ247ICsraWkpIHtcbiAgICAgICAgdGIgKz0gY2VsbHNbaV1baWldO1xuICAgICAgfVxuICAgICAgdGIgKz0gJzwvdHI+XFxuJztcbiAgICB9XG4gICAgdGIgKz0gJzwvdGJvZHk+XFxuPC90YWJsZT5cXG4nO1xuICAgIHJldHVybiB0YjtcbiAgfVxuXG4gIGZ1bmN0aW9uIHBhcnNlVGFibGUgKHJhd1RhYmxlKSB7XG4gICAgdmFyIGksIHRhYmxlTGluZXMgPSByYXdUYWJsZS5zcGxpdCgnXFxuJyk7XG5cbiAgICBmb3IgKGkgPSAwOyBpIDwgdGFibGVMaW5lcy5sZW5ndGg7ICsraSkge1xuICAgICAgLy8gc3RyaXAgd3JvbmcgZmlyc3QgYW5kIGxhc3QgY29sdW1uIGlmIHdyYXBwZWQgdGFibGVzIGFyZSB1c2VkXG4gICAgICBpZiAoL14gezAsM31cXHwvLnRlc3QodGFibGVMaW5lc1tpXSkpIHtcbiAgICAgICAgdGFibGVMaW5lc1tpXSA9IHRhYmxlTGluZXNbaV0ucmVwbGFjZSgvXiB7MCwzfVxcfC8sICcnKTtcbiAgICAgIH1cbiAgICAgIGlmICgvXFx8WyBcXHRdKiQvLnRlc3QodGFibGVMaW5lc1tpXSkpIHtcbiAgICAgICAgdGFibGVMaW5lc1tpXSA9IHRhYmxlTGluZXNbaV0ucmVwbGFjZSgvXFx8WyBcXHRdKiQvLCAnJyk7XG4gICAgICB9XG4gICAgICAvLyBwYXJzZSBjb2RlIHNwYW5zIGZpcnN0LCBidXQgd2Ugb25seSBzdXBwb3J0IG9uZSBsaW5lIGNvZGUgc3BhbnNcbiAgICAgIHRhYmxlTGluZXNbaV0gPSBzaG93ZG93bi5zdWJQYXJzZXIoJ2NvZGVTcGFucycpKHRhYmxlTGluZXNbaV0sIG9wdGlvbnMsIGdsb2JhbHMpO1xuICAgIH1cblxuICAgIHZhciByYXdIZWFkZXJzID0gdGFibGVMaW5lc1swXS5zcGxpdCgnfCcpLm1hcChmdW5jdGlvbiAocykgeyByZXR1cm4gcy50cmltKCk7fSksXG4gICAgICAgIHJhd1N0eWxlcyA9IHRhYmxlTGluZXNbMV0uc3BsaXQoJ3wnKS5tYXAoZnVuY3Rpb24gKHMpIHsgcmV0dXJuIHMudHJpbSgpO30pLFxuICAgICAgICByYXdDZWxscyA9IFtdLFxuICAgICAgICBoZWFkZXJzID0gW10sXG4gICAgICAgIHN0eWxlcyA9IFtdLFxuICAgICAgICBjZWxscyA9IFtdO1xuXG4gICAgdGFibGVMaW5lcy5zaGlmdCgpO1xuICAgIHRhYmxlTGluZXMuc2hpZnQoKTtcblxuICAgIGZvciAoaSA9IDA7IGkgPCB0YWJsZUxpbmVzLmxlbmd0aDsgKytpKSB7XG4gICAgICBpZiAodGFibGVMaW5lc1tpXS50cmltKCkgPT09ICcnKSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgcmF3Q2VsbHMucHVzaChcbiAgICAgICAgdGFibGVMaW5lc1tpXVxuICAgICAgICAgIC5zcGxpdCgnfCcpXG4gICAgICAgICAgLm1hcChmdW5jdGlvbiAocykge1xuICAgICAgICAgICAgcmV0dXJuIHMudHJpbSgpO1xuICAgICAgICAgIH0pXG4gICAgICApO1xuICAgIH1cblxuICAgIGlmIChyYXdIZWFkZXJzLmxlbmd0aCA8IHJhd1N0eWxlcy5sZW5ndGgpIHtcbiAgICAgIHJldHVybiByYXdUYWJsZTtcbiAgICB9XG5cbiAgICBmb3IgKGkgPSAwOyBpIDwgcmF3U3R5bGVzLmxlbmd0aDsgKytpKSB7XG4gICAgICBzdHlsZXMucHVzaChwYXJzZVN0eWxlcyhyYXdTdHlsZXNbaV0pKTtcbiAgICB9XG5cbiAgICBmb3IgKGkgPSAwOyBpIDwgcmF3SGVhZGVycy5sZW5ndGg7ICsraSkge1xuICAgICAgaWYgKHNob3dkb3duLmhlbHBlci5pc1VuZGVmaW5lZChzdHlsZXNbaV0pKSB7XG4gICAgICAgIHN0eWxlc1tpXSA9ICcnO1xuICAgICAgfVxuICAgICAgaGVhZGVycy5wdXNoKHBhcnNlSGVhZGVycyhyYXdIZWFkZXJzW2ldLCBzdHlsZXNbaV0pKTtcbiAgICB9XG5cbiAgICBmb3IgKGkgPSAwOyBpIDwgcmF3Q2VsbHMubGVuZ3RoOyArK2kpIHtcbiAgICAgIHZhciByb3cgPSBbXTtcbiAgICAgIGZvciAodmFyIGlpID0gMDsgaWkgPCBoZWFkZXJzLmxlbmd0aDsgKytpaSkge1xuICAgICAgICBpZiAoc2hvd2Rvd24uaGVscGVyLmlzVW5kZWZpbmVkKHJhd0NlbGxzW2ldW2lpXSkpIHtcblxuICAgICAgICB9XG4gICAgICAgIHJvdy5wdXNoKHBhcnNlQ2VsbHMocmF3Q2VsbHNbaV1baWldLCBzdHlsZXNbaWldKSk7XG4gICAgICB9XG4gICAgICBjZWxscy5wdXNoKHJvdyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGJ1aWxkVGFibGUoaGVhZGVycywgY2VsbHMpO1xuICB9XG5cbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgndGFibGVzLmJlZm9yZScsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuXG4gIC8vIGZpbmQgZXNjYXBlZCBwaXBlIGNoYXJhY3RlcnNcbiAgdGV4dCA9IHRleHQucmVwbGFjZSgvXFxcXChcXHwpL2csIHNob3dkb3duLmhlbHBlci5lc2NhcGVDaGFyYWN0ZXJzQ2FsbGJhY2spO1xuXG4gIC8vIHBhcnNlIG11bHRpIGNvbHVtbiB0YWJsZXNcbiAgdGV4dCA9IHRleHQucmVwbGFjZSh0YWJsZVJneCwgcGFyc2VUYWJsZSk7XG5cbiAgLy8gcGFyc2Ugb25lIGNvbHVtbiB0YWJsZXNcbiAgdGV4dCA9IHRleHQucmVwbGFjZShzaW5nZUNvbFRibFJneCwgcGFyc2VUYWJsZSk7XG5cbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgndGFibGVzLmFmdGVyJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG5cbiAgcmV0dXJuIHRleHQ7XG59KTtcblxyXG5zaG93ZG93bi5zdWJQYXJzZXIoJ3VuZGVybGluZScsIGZ1bmN0aW9uICh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICBpZiAoIW9wdGlvbnMudW5kZXJsaW5lKSB7XG4gICAgcmV0dXJuIHRleHQ7XG4gIH1cblxuICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCd1bmRlcmxpbmUuYmVmb3JlJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG5cbiAgaWYgKG9wdGlvbnMubGl0ZXJhbE1pZFdvcmRVbmRlcnNjb3Jlcykge1xuICAgIHRleHQgPSB0ZXh0LnJlcGxhY2UoL1xcYl8/X18oXFxTW1xcc1xcU10qKV9fXz9cXGIvZywgZnVuY3Rpb24gKHdtLCB0eHQpIHtcbiAgICAgIHJldHVybiAnPHU+JyArIHR4dCArICc8L3U+JztcbiAgICB9KTtcbiAgfSBlbHNlIHtcbiAgICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC9fP19fKFxcU1tcXHNcXFNdKj8pX19fPy9nLCBmdW5jdGlvbiAod20sIG0pIHtcbiAgICAgIHJldHVybiAoL1xcUyQvLnRlc3QobSkpID8gJzx1PicgKyBtICsgJzwvdT4nIDogd207XG4gICAgfSk7XG4gIH1cblxuICAvLyBlc2NhcGUgcmVtYWluaW5nIHVuZGVyc2NvcmVzIHRvIHByZXZlbnQgdGhlbSBiZWluZyBwYXJzZWQgYnkgaXRhbGljIGFuZCBib2xkXG4gIHRleHQgPSB0ZXh0LnJlcGxhY2UoLyhfKS9nLCBzaG93ZG93bi5oZWxwZXIuZXNjYXBlQ2hhcmFjdGVyc0NhbGxiYWNrKTtcblxuICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCd1bmRlcmxpbmUuYWZ0ZXInLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcblxuICByZXR1cm4gdGV4dDtcbn0pO1xuXHJcbi8qKlxuICogU3dhcCBiYWNrIGluIGFsbCB0aGUgc3BlY2lhbCBjaGFyYWN0ZXJzIHdlJ3ZlIGhpZGRlbi5cbiAqL1xuc2hvd2Rvd24uc3ViUGFyc2VyKCd1bmVzY2FwZVNwZWNpYWxDaGFycycsIGZ1bmN0aW9uICh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKSB7XG4gICd1c2Ugc3RyaWN0JztcbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgndW5lc2NhcGVTcGVjaWFsQ2hhcnMuYmVmb3JlJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG5cbiAgdGV4dCA9IHRleHQucmVwbGFjZSgvwqhFKFxcZCspRS9nLCBmdW5jdGlvbiAod2hvbGVNYXRjaCwgbTEpIHtcbiAgICB2YXIgY2hhckNvZGVUb1JlcGxhY2UgPSBwYXJzZUludChtMSk7XG4gICAgcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUoY2hhckNvZGVUb1JlcGxhY2UpO1xuICB9KTtcblxuICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCd1bmVzY2FwZVNwZWNpYWxDaGFycy5hZnRlcicsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICByZXR1cm4gdGV4dDtcbn0pO1xuXHJcbnZhciByb290ID0gdGhpcztcblxuLy8gQU1EIExvYWRlclxuaWYgKHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCkge1xuICBkZWZpbmUoZnVuY3Rpb24gKCkge1xuICAgICd1c2Ugc3RyaWN0JztcbiAgICByZXR1cm4gc2hvd2Rvd247XG4gIH0pO1xuXG4vLyBDb21tb25KUy9ub2RlSlMgTG9hZGVyXG59IGVsc2UgaWYgKHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnICYmIG1vZHVsZS5leHBvcnRzKSB7XG4gIG1vZHVsZS5leHBvcnRzID0gc2hvd2Rvd247XG5cbi8vIFJlZ3VsYXIgQnJvd3NlciBsb2FkZXJcbn0gZWxzZSB7XG4gIHJvb3Quc2hvd2Rvd24gPSBzaG93ZG93bjtcbn1cbn0pLmNhbGwodGhpcyk7XHJcblxuLy8jIHNvdXJjZU1hcHBpbmdVUkw9c2hvd2Rvd24uanMubWFwXHJcbiIsIi8vIFJlbGVhc2VkIHVuZGVyIE1JVCBsaWNlbnNlXG4vLyBDb3B5cmlnaHQgKGMpIDIwMDktMjAxMCBEb21pbmljIEJhZ2dvdHRcbi8vIENvcHlyaWdodCAoYykgMjAwOS0yMDEwIEFzaCBCZXJsaW5cbi8vIENvcHlyaWdodCAoYykgMjAxMSBDaHJpc3RvcGggRG9ybiA8Y2hyaXN0b3BoQGNocmlzdG9waGRvcm4uY29tPiAoaHR0cDovL3d3dy5jaHJpc3RvcGhkb3JuLmNvbSlcblxuLypqc2hpbnQgYnJvd3Nlcjp0cnVlLCBkZXZlbDp0cnVlICovXG5cbihmdW5jdGlvbiggZXhwb3NlICkge1xuXG4vKipcbiAqICBjbGFzcyBNYXJrZG93blxuICpcbiAqICBNYXJrZG93biBwcm9jZXNzaW5nIGluIEphdmFzY3JpcHQgZG9uZSByaWdodC4gV2UgaGF2ZSB2ZXJ5IHBhcnRpY3VsYXIgdmlld3NcbiAqICBvbiB3aGF0IGNvbnN0aXR1dGVzICdyaWdodCcgd2hpY2ggaW5jbHVkZTpcbiAqXG4gKiAgLSBwcm9kdWNlcyB3ZWxsLWZvcm1lZCBIVE1MICh0aGlzIG1lYW5zIHRoYXQgZW0gYW5kIHN0cm9uZyBuZXN0aW5nIGlzXG4gKiAgICBpbXBvcnRhbnQpXG4gKlxuICogIC0gaGFzIGFuIGludGVybWVkaWF0ZSByZXByZXNlbnRhdGlvbiB0byBhbGxvdyBwcm9jZXNzaW5nIG9mIHBhcnNlZCBkYXRhIChXZVxuICogICAgaW4gZmFjdCBoYXZlIHR3bywgYm90aCBhcyBbSnNvbk1MXTogYSBtYXJrZG93biB0cmVlIGFuZCBhbiBIVE1MIHRyZWUpLlxuICpcbiAqICAtIGlzIGVhc2lseSBleHRlbnNpYmxlIHRvIGFkZCBuZXcgZGlhbGVjdHMgd2l0aG91dCBoYXZpbmcgdG8gcmV3cml0ZSB0aGVcbiAqICAgIGVudGlyZSBwYXJzaW5nIG1lY2hhbmljc1xuICpcbiAqICAtIGhhcyBhIGdvb2QgdGVzdCBzdWl0ZVxuICpcbiAqICBUaGlzIGltcGxlbWVudGF0aW9uIGZ1bGZpbGxzIGFsbCBvZiB0aGVzZSAoZXhjZXB0IHRoYXQgdGhlIHRlc3Qgc3VpdGUgY291bGRcbiAqICBkbyB3aXRoIGV4cGFuZGluZyB0byBhdXRvbWF0aWNhbGx5IHJ1biBhbGwgdGhlIGZpeHR1cmVzIGZyb20gb3RoZXIgTWFya2Rvd25cbiAqICBpbXBsZW1lbnRhdGlvbnMuKVxuICpcbiAqICAjIyMjIyBJbnRlcm1lZGlhdGUgUmVwcmVzZW50YXRpb25cbiAqXG4gKiAgKlRPRE8qIFRhbGsgYWJvdXQgdGhpcyA6KSBJdHMgSnNvbk1MLCBidXQgZG9jdW1lbnQgdGhlIG5vZGUgbmFtZXMgd2UgdXNlLlxuICpcbiAqICBbSnNvbk1MXTogaHR0cDovL2pzb25tbC5vcmcvIFwiSlNPTiBNYXJrdXAgTGFuZ3VhZ2VcIlxuICoqL1xudmFyIE1hcmtkb3duID0gZXhwb3NlLk1hcmtkb3duID0gZnVuY3Rpb24oZGlhbGVjdCkge1xuICBzd2l0Y2ggKHR5cGVvZiBkaWFsZWN0KSB7XG4gICAgY2FzZSBcInVuZGVmaW5lZFwiOlxuICAgICAgdGhpcy5kaWFsZWN0ID0gTWFya2Rvd24uZGlhbGVjdHMuR3J1YmVyO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSBcIm9iamVjdFwiOlxuICAgICAgdGhpcy5kaWFsZWN0ID0gZGlhbGVjdDtcbiAgICAgIGJyZWFrO1xuICAgIGRlZmF1bHQ6XG4gICAgICBpZiAoIGRpYWxlY3QgaW4gTWFya2Rvd24uZGlhbGVjdHMgKSB7XG4gICAgICAgIHRoaXMuZGlhbGVjdCA9IE1hcmtkb3duLmRpYWxlY3RzW2RpYWxlY3RdO1xuICAgICAgfVxuICAgICAgZWxzZSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIlVua25vd24gTWFya2Rvd24gZGlhbGVjdCAnXCIgKyBTdHJpbmcoZGlhbGVjdCkgKyBcIidcIik7XG4gICAgICB9XG4gICAgICBicmVhaztcbiAgfVxuICB0aGlzLmVtX3N0YXRlID0gW107XG4gIHRoaXMuc3Ryb25nX3N0YXRlID0gW107XG4gIHRoaXMuZGVidWdfaW5kZW50ID0gXCJcIjtcbn07XG5cbi8qKlxuICogIHBhcnNlKCBtYXJrZG93biwgW2RpYWxlY3RdICkgLT4gSnNvbk1MXG4gKiAgLSBtYXJrZG93biAoU3RyaW5nKTogbWFya2Rvd24gc3RyaW5nIHRvIHBhcnNlXG4gKiAgLSBkaWFsZWN0IChTdHJpbmcgfCBEaWFsZWN0KTogdGhlIGRpYWxlY3QgdG8gdXNlLCBkZWZhdWx0cyB0byBncnViZXJcbiAqXG4gKiAgUGFyc2UgYG1hcmtkb3duYCBhbmQgcmV0dXJuIGEgbWFya2Rvd24gZG9jdW1lbnQgYXMgYSBNYXJrZG93bi5Kc29uTUwgdHJlZS5cbiAqKi9cbmV4cG9zZS5wYXJzZSA9IGZ1bmN0aW9uKCBzb3VyY2UsIGRpYWxlY3QgKSB7XG4gIC8vIGRpYWxlY3Qgd2lsbCBkZWZhdWx0IGlmIHVuZGVmaW5lZFxuICB2YXIgbWQgPSBuZXcgTWFya2Rvd24oIGRpYWxlY3QgKTtcbiAgcmV0dXJuIG1kLnRvVHJlZSggc291cmNlICk7XG59O1xuXG4vKipcbiAqICB0b0hUTUwoIG1hcmtkb3duLCBbZGlhbGVjdF0gICkgLT4gU3RyaW5nXG4gKiAgdG9IVE1MKCBtZF90cmVlICkgLT4gU3RyaW5nXG4gKiAgLSBtYXJrZG93biAoU3RyaW5nKTogbWFya2Rvd24gc3RyaW5nIHRvIHBhcnNlXG4gKiAgLSBtZF90cmVlIChNYXJrZG93bi5Kc29uTUwpOiBwYXJzZWQgbWFya2Rvd24gdHJlZVxuICpcbiAqICBUYWtlIG1hcmtkb3duIChlaXRoZXIgYXMgYSBzdHJpbmcgb3IgYXMgYSBKc29uTUwgdHJlZSkgYW5kIHJ1biBpdCB0aHJvdWdoXG4gKiAgW1t0b0hUTUxUcmVlXV0gdGhlbiB0dXJuIGl0IGludG8gYSB3ZWxsLWZvcm1hdGVkIEhUTUwgZnJhZ21lbnQuXG4gKiovXG5leHBvc2UudG9IVE1MID0gZnVuY3Rpb24gdG9IVE1MKCBzb3VyY2UgLCBkaWFsZWN0ICwgb3B0aW9ucyApIHtcbiAgdmFyIGlucHV0ID0gZXhwb3NlLnRvSFRNTFRyZWUoIHNvdXJjZSAsIGRpYWxlY3QgLCBvcHRpb25zICk7XG5cbiAgcmV0dXJuIGV4cG9zZS5yZW5kZXJKc29uTUwoIGlucHV0ICk7XG59O1xuXG4vKipcbiAqICB0b0hUTUxUcmVlKCBtYXJrZG93biwgW2RpYWxlY3RdICkgLT4gSnNvbk1MXG4gKiAgdG9IVE1MVHJlZSggbWRfdHJlZSApIC0+IEpzb25NTFxuICogIC0gbWFya2Rvd24gKFN0cmluZyk6IG1hcmtkb3duIHN0cmluZyB0byBwYXJzZVxuICogIC0gZGlhbGVjdCAoU3RyaW5nIHwgRGlhbGVjdCk6IHRoZSBkaWFsZWN0IHRvIHVzZSwgZGVmYXVsdHMgdG8gZ3J1YmVyXG4gKiAgLSBtZF90cmVlIChNYXJrZG93bi5Kc29uTUwpOiBwYXJzZWQgbWFya2Rvd24gdHJlZVxuICpcbiAqICBUdXJuIG1hcmtkb3duIGludG8gSFRNTCwgcmVwcmVzZW50ZWQgYXMgYSBKc29uTUwgdHJlZS4gSWYgYSBzdHJpbmcgaXMgZ2l2ZW5cbiAqICB0byB0aGlzIGZ1bmN0aW9uLCBpdCBpcyBmaXJzdCBwYXJzZWQgaW50byBhIG1hcmtkb3duIHRyZWUgYnkgY2FsbGluZ1xuICogIFtbcGFyc2VdXS5cbiAqKi9cbmV4cG9zZS50b0hUTUxUcmVlID0gZnVuY3Rpb24gdG9IVE1MVHJlZSggaW5wdXQsIGRpYWxlY3QgLCBvcHRpb25zICkge1xuICAvLyBjb252ZXJ0IHN0cmluZyBpbnB1dCB0byBhbiBNRCB0cmVlXG4gIGlmICggdHlwZW9mIGlucHV0ID09PVwic3RyaW5nXCIgKSBpbnB1dCA9IHRoaXMucGFyc2UoIGlucHV0LCBkaWFsZWN0ICk7XG5cbiAgLy8gTm93IGNvbnZlcnQgdGhlIE1EIHRyZWUgdG8gYW4gSFRNTCB0cmVlXG5cbiAgLy8gcmVtb3ZlIHJlZmVyZW5jZXMgZnJvbSB0aGUgdHJlZVxuICB2YXIgYXR0cnMgPSBleHRyYWN0X2F0dHIoIGlucHV0ICksXG4gICAgICByZWZzID0ge307XG5cbiAgaWYgKCBhdHRycyAmJiBhdHRycy5yZWZlcmVuY2VzICkge1xuICAgIHJlZnMgPSBhdHRycy5yZWZlcmVuY2VzO1xuICB9XG5cbiAgdmFyIGh0bWwgPSBjb252ZXJ0X3RyZWVfdG9faHRtbCggaW5wdXQsIHJlZnMgLCBvcHRpb25zICk7XG4gIG1lcmdlX3RleHRfbm9kZXMoIGh0bWwgKTtcbiAgcmV0dXJuIGh0bWw7XG59O1xuXG4vLyBGb3IgU3BpZGVybW9ua2V5IGJhc2VkIGVuZ2luZXNcbmZ1bmN0aW9uIG1rX2Jsb2NrX3RvU291cmNlKCkge1xuICByZXR1cm4gXCJNYXJrZG93bi5ta19ibG9jayggXCIgK1xuICAgICAgICAgIHVuZXZhbCh0aGlzLnRvU3RyaW5nKCkpICtcbiAgICAgICAgICBcIiwgXCIgK1xuICAgICAgICAgIHVuZXZhbCh0aGlzLnRyYWlsaW5nKSArXG4gICAgICAgICAgXCIsIFwiICtcbiAgICAgICAgICB1bmV2YWwodGhpcy5saW5lTnVtYmVyKSArXG4gICAgICAgICAgXCIgKVwiO1xufVxuXG4vLyBub2RlXG5mdW5jdGlvbiBta19ibG9ja19pbnNwZWN0KCkge1xuICB2YXIgdXRpbCA9IHJlcXVpcmUoXCJ1dGlsXCIpO1xuICByZXR1cm4gXCJNYXJrZG93bi5ta19ibG9jayggXCIgK1xuICAgICAgICAgIHV0aWwuaW5zcGVjdCh0aGlzLnRvU3RyaW5nKCkpICtcbiAgICAgICAgICBcIiwgXCIgK1xuICAgICAgICAgIHV0aWwuaW5zcGVjdCh0aGlzLnRyYWlsaW5nKSArXG4gICAgICAgICAgXCIsIFwiICtcbiAgICAgICAgICB1dGlsLmluc3BlY3QodGhpcy5saW5lTnVtYmVyKSArXG4gICAgICAgICAgXCIgKVwiO1xuXG59XG5cbnZhciBta19ibG9jayA9IE1hcmtkb3duLm1rX2Jsb2NrID0gZnVuY3Rpb24oYmxvY2ssIHRyYWlsLCBsaW5lKSB7XG4gIC8vIEJlIGhlbHBmdWwgZm9yIGRlZmF1bHQgY2FzZSBpbiB0ZXN0cy5cbiAgaWYgKCBhcmd1bWVudHMubGVuZ3RoID09IDEgKSB0cmFpbCA9IFwiXFxuXFxuXCI7XG5cbiAgdmFyIHMgPSBuZXcgU3RyaW5nKGJsb2NrKTtcbiAgcy50cmFpbGluZyA9IHRyYWlsO1xuICAvLyBUbyBtYWtlIGl0IGNsZWFyIGl0cyBub3QganVzdCBhIHN0cmluZ1xuICBzLmluc3BlY3QgPSBta19ibG9ja19pbnNwZWN0O1xuICBzLnRvU291cmNlID0gbWtfYmxvY2tfdG9Tb3VyY2U7XG5cbiAgaWYgKCBsaW5lICE9IHVuZGVmaW5lZCApXG4gICAgcy5saW5lTnVtYmVyID0gbGluZTtcblxuICByZXR1cm4gcztcbn07XG5cbmZ1bmN0aW9uIGNvdW50X2xpbmVzKCBzdHIgKSB7XG4gIHZhciBuID0gMCwgaSA9IC0xO1xuICB3aGlsZSAoICggaSA9IHN0ci5pbmRleE9mKFwiXFxuXCIsIGkgKyAxKSApICE9PSAtMSApIG4rKztcbiAgcmV0dXJuIG47XG59XG5cbi8vIEludGVybmFsIC0gc3BsaXQgc291cmNlIGludG8gcm91Z2ggYmxvY2tzXG5NYXJrZG93bi5wcm90b3R5cGUuc3BsaXRfYmxvY2tzID0gZnVuY3Rpb24gc3BsaXRCbG9ja3MoIGlucHV0LCBzdGFydExpbmUgKSB7XG4gIGlucHV0ID0gaW5wdXQucmVwbGFjZSgvKFxcclxcbnxcXG58XFxyKS9nLCBcIlxcblwiKTtcbiAgLy8gW1xcc1xcU10gbWF0Y2hlcyBfYW55dGhpbmdfIChuZXdsaW5lIG9yIHNwYWNlKVxuICAvLyBbXl0gaXMgZXF1aXZhbGVudCBidXQgZG9lc24ndCB3b3JrIGluIElFcy5cbiAgdmFyIHJlID0gLyhbXFxzXFxTXSs/KSgkfFxcbiN8XFxuKD86XFxzKlxcbnwkKSspL2csXG4gICAgICBibG9ja3MgPSBbXSxcbiAgICAgIG07XG5cbiAgdmFyIGxpbmVfbm8gPSAxO1xuXG4gIGlmICggKCBtID0gL14oXFxzKlxcbikvLmV4ZWMoaW5wdXQpICkgIT0gbnVsbCApIHtcbiAgICAvLyBza2lwIChidXQgY291bnQpIGxlYWRpbmcgYmxhbmsgbGluZXNcbiAgICBsaW5lX25vICs9IGNvdW50X2xpbmVzKCBtWzBdICk7XG4gICAgcmUubGFzdEluZGV4ID0gbVswXS5sZW5ndGg7XG4gIH1cblxuICB3aGlsZSAoICggbSA9IHJlLmV4ZWMoaW5wdXQpICkgIT09IG51bGwgKSB7XG4gICAgaWYgKG1bMl0gPT0gXCJcXG4jXCIpIHtcbiAgICAgIG1bMl0gPSBcIlxcblwiO1xuICAgICAgcmUubGFzdEluZGV4LS07XG4gICAgfVxuICAgIGJsb2Nrcy5wdXNoKCBta19ibG9jayggbVsxXSwgbVsyXSwgbGluZV9ubyApICk7XG4gICAgbGluZV9ubyArPSBjb3VudF9saW5lcyggbVswXSApO1xuICB9XG5cbiAgcmV0dXJuIGJsb2Nrcztcbn07XG5cbi8qKlxuICogIE1hcmtkb3duI3Byb2Nlc3NCbG9jayggYmxvY2ssIG5leHQgKSAtPiB1bmRlZmluZWQgfCBbIEpzb25NTCwgLi4uIF1cbiAqICAtIGJsb2NrIChTdHJpbmcpOiB0aGUgYmxvY2sgdG8gcHJvY2Vzc1xuICogIC0gbmV4dCAoQXJyYXkpOiB0aGUgZm9sbG93aW5nIGJsb2Nrc1xuICpcbiAqIFByb2Nlc3MgYGJsb2NrYCBhbmQgcmV0dXJuIGFuIGFycmF5IG9mIEpzb25NTCBub2RlcyByZXByZXNlbnRpbmcgYGJsb2NrYC5cbiAqXG4gKiBJdCBkb2VzIHRoaXMgYnkgYXNraW5nIGVhY2ggYmxvY2sgbGV2ZWwgZnVuY3Rpb24gaW4gdGhlIGRpYWxlY3QgdG8gcHJvY2Vzc1xuICogdGhlIGJsb2NrIHVudGlsIG9uZSBjYW4uIFN1Y2Nlc2Z1bCBoYW5kbGluZyBpcyBpbmRpY2F0ZWQgYnkgcmV0dXJuaW5nIGFuXG4gKiBhcnJheSAod2l0aCB6ZXJvIG9yIG1vcmUgSnNvbk1MIG5vZGVzKSwgZmFpbHVyZSBieSBhIGZhbHNlIHZhbHVlLlxuICpcbiAqIEJsb2NrcyBoYW5kbGVycyBhcmUgcmVzcG9uc2libGUgZm9yIGNhbGxpbmcgW1tNYXJrZG93biNwcm9jZXNzSW5saW5lXV1cbiAqIHRoZW1zZWx2ZXMgYXMgYXBwcm9wcmlhdGUuXG4gKlxuICogSWYgdGhlIGJsb2NrcyB3ZXJlIHNwbGl0IGluY29ycmVjdGx5IG9yIGFkamFjZW50IGJsb2NrcyBuZWVkIGNvbGxhcHNpbmcgeW91XG4gKiBjYW4gYWRqdXN0IGBuZXh0YCBpbiBwbGFjZSB1c2luZyBzaGlmdC9zcGxpY2UgZXRjLlxuICpcbiAqIElmIGFueSBvZiB0aGlzIGRlZmF1bHQgYmVoYXZpb3VyIGlzIG5vdCByaWdodCBmb3IgdGhlIGRpYWxlY3QsIHlvdSBjYW5cbiAqIGRlZmluZSBhIGBfX2NhbGxfX2AgbWV0aG9kIG9uIHRoZSBkaWFsZWN0IHRoYXQgd2lsbCBnZXQgaW52b2tlZCB0byBoYW5kbGVcbiAqIHRoZSBibG9jayBwcm9jZXNzaW5nLlxuICovXG5NYXJrZG93bi5wcm90b3R5cGUucHJvY2Vzc0Jsb2NrID0gZnVuY3Rpb24gcHJvY2Vzc0Jsb2NrKCBibG9jaywgbmV4dCApIHtcbiAgdmFyIGNicyA9IHRoaXMuZGlhbGVjdC5ibG9jayxcbiAgICAgIG9yZCA9IGNicy5fX29yZGVyX187XG5cbiAgaWYgKCBcIl9fY2FsbF9fXCIgaW4gY2JzICkge1xuICAgIHJldHVybiBjYnMuX19jYWxsX18uY2FsbCh0aGlzLCBibG9jaywgbmV4dCk7XG4gIH1cblxuICBmb3IgKCB2YXIgaSA9IDA7IGkgPCBvcmQubGVuZ3RoOyBpKysgKSB7XG4gICAgLy9EOnRoaXMuZGVidWcoIFwiVGVzdGluZ1wiLCBvcmRbaV0gKTtcbiAgICB2YXIgcmVzID0gY2JzWyBvcmRbaV0gXS5jYWxsKCB0aGlzLCBibG9jaywgbmV4dCApO1xuICAgIGlmICggcmVzICkge1xuICAgICAgLy9EOnRoaXMuZGVidWcoXCIgIG1hdGNoZWRcIik7XG4gICAgICBpZiAoICFpc0FycmF5KHJlcykgfHwgKCByZXMubGVuZ3RoID4gMCAmJiAhKCBpc0FycmF5KHJlc1swXSkgKSApIClcbiAgICAgICAgdGhpcy5kZWJ1ZyhvcmRbaV0sIFwiZGlkbid0IHJldHVybiBhIHByb3BlciBhcnJheVwiKTtcbiAgICAgIC8vRDp0aGlzLmRlYnVnKCBcIlwiICk7XG4gICAgICByZXR1cm4gcmVzO1xuICAgIH1cbiAgfVxuXG4gIC8vIFVob2ghIG5vIG1hdGNoISBTaG91bGQgd2UgdGhyb3cgYW4gZXJyb3I/XG4gIHJldHVybiBbXTtcbn07XG5cbk1hcmtkb3duLnByb3RvdHlwZS5wcm9jZXNzSW5saW5lID0gZnVuY3Rpb24gcHJvY2Vzc0lubGluZSggYmxvY2sgKSB7XG4gIHJldHVybiB0aGlzLmRpYWxlY3QuaW5saW5lLl9fY2FsbF9fLmNhbGwoIHRoaXMsIFN0cmluZyggYmxvY2sgKSApO1xufTtcblxuLyoqXG4gKiAgTWFya2Rvd24jdG9UcmVlKCBzb3VyY2UgKSAtPiBKc29uTUxcbiAqICAtIHNvdXJjZSAoU3RyaW5nKTogbWFya2Rvd24gc291cmNlIHRvIHBhcnNlXG4gKlxuICogIFBhcnNlIGBzb3VyY2VgIGludG8gYSBKc29uTUwgdHJlZSByZXByZXNlbnRpbmcgdGhlIG1hcmtkb3duIGRvY3VtZW50LlxuICoqL1xuLy8gY3VzdG9tX3RyZWUgbWVhbnMgc2V0IHRoaXMudHJlZSB0byBgY3VzdG9tX3RyZWVgIGFuZCByZXN0b3JlIG9sZCB2YWx1ZSBvbiByZXR1cm5cbk1hcmtkb3duLnByb3RvdHlwZS50b1RyZWUgPSBmdW5jdGlvbiB0b1RyZWUoIHNvdXJjZSwgY3VzdG9tX3Jvb3QgKSB7XG4gIHZhciBibG9ja3MgPSBzb3VyY2UgaW5zdGFuY2VvZiBBcnJheSA/IHNvdXJjZSA6IHRoaXMuc3BsaXRfYmxvY2tzKCBzb3VyY2UgKTtcblxuICAvLyBNYWtlIHRyZWUgYSBtZW1iZXIgdmFyaWFibGUgc28gaXRzIGVhc2llciB0byBtZXNzIHdpdGggaW4gZXh0ZW5zaW9uc1xuICB2YXIgb2xkX3RyZWUgPSB0aGlzLnRyZWU7XG4gIHRyeSB7XG4gICAgdGhpcy50cmVlID0gY3VzdG9tX3Jvb3QgfHwgdGhpcy50cmVlIHx8IFsgXCJtYXJrZG93blwiIF07XG5cbiAgICBibG9ja3M6XG4gICAgd2hpbGUgKCBibG9ja3MubGVuZ3RoICkge1xuICAgICAgdmFyIGIgPSB0aGlzLnByb2Nlc3NCbG9jayggYmxvY2tzLnNoaWZ0KCksIGJsb2NrcyApO1xuXG4gICAgICAvLyBSZWZlcmVuY2UgYmxvY2tzIGFuZCB0aGUgbGlrZSB3b24ndCByZXR1cm4gYW55IGNvbnRlbnRcbiAgICAgIGlmICggIWIubGVuZ3RoICkgY29udGludWUgYmxvY2tzO1xuXG4gICAgICB0aGlzLnRyZWUucHVzaC5hcHBseSggdGhpcy50cmVlLCBiICk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLnRyZWU7XG4gIH1cbiAgZmluYWxseSB7XG4gICAgaWYgKCBjdXN0b21fcm9vdCApIHtcbiAgICAgIHRoaXMudHJlZSA9IG9sZF90cmVlO1xuICAgIH1cbiAgfVxufTtcblxuLy8gTm9vcCBieSBkZWZhdWx0XG5NYXJrZG93bi5wcm90b3R5cGUuZGVidWcgPSBmdW5jdGlvbiAoKSB7XG4gIHZhciBhcmdzID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoIGFyZ3VtZW50cyk7XG4gIGFyZ3MudW5zaGlmdCh0aGlzLmRlYnVnX2luZGVudCk7XG4gIGlmICggdHlwZW9mIHByaW50ICE9PSBcInVuZGVmaW5lZFwiIClcbiAgICAgIHByaW50LmFwcGx5KCBwcmludCwgYXJncyApO1xuICBpZiAoIHR5cGVvZiBjb25zb2xlICE9PSBcInVuZGVmaW5lZFwiICYmIHR5cGVvZiBjb25zb2xlLmxvZyAhPT0gXCJ1bmRlZmluZWRcIiApXG4gICAgICBjb25zb2xlLmxvZy5hcHBseSggbnVsbCwgYXJncyApO1xufVxuXG5NYXJrZG93bi5wcm90b3R5cGUubG9vcF9yZV9vdmVyX2Jsb2NrID0gZnVuY3Rpb24oIHJlLCBibG9jaywgY2IgKSB7XG4gIC8vIERvbnQgdXNlIC9nIHJlZ2V4cHMgd2l0aCB0aGlzXG4gIHZhciBtLFxuICAgICAgYiA9IGJsb2NrLnZhbHVlT2YoKTtcblxuICB3aGlsZSAoIGIubGVuZ3RoICYmIChtID0gcmUuZXhlYyhiKSApICE9IG51bGwgKSB7XG4gICAgYiA9IGIuc3Vic3RyKCBtWzBdLmxlbmd0aCApO1xuICAgIGNiLmNhbGwodGhpcywgbSk7XG4gIH1cbiAgcmV0dXJuIGI7XG59O1xuXG4vKipcbiAqIE1hcmtkb3duLmRpYWxlY3RzXG4gKlxuICogTmFtZXNwYWNlIG9mIGJ1aWx0LWluIGRpYWxlY3RzLlxuICoqL1xuTWFya2Rvd24uZGlhbGVjdHMgPSB7fTtcblxuLyoqXG4gKiBNYXJrZG93bi5kaWFsZWN0cy5HcnViZXJcbiAqXG4gKiBUaGUgZGVmYXVsdCBkaWFsZWN0IHRoYXQgZm9sbG93cyB0aGUgcnVsZXMgc2V0IG91dCBieSBKb2huIEdydWJlcidzXG4gKiBtYXJrZG93bi5wbCBhcyBjbG9zZWx5IGFzIHBvc3NpYmxlLiBXZWxsIGFjdHVhbGx5IHdlIGZvbGxvdyB0aGUgYmVoYXZpb3VyIG9mXG4gKiB0aGF0IHNjcmlwdCB3aGljaCBpbiBzb21lIHBsYWNlcyBpcyBub3QgZXhhY3RseSB3aGF0IHRoZSBzeW50YXggd2ViIHBhZ2VcbiAqIHNheXMuXG4gKiovXG5NYXJrZG93bi5kaWFsZWN0cy5HcnViZXIgPSB7XG4gIGJsb2NrOiB7XG4gICAgYXR4SGVhZGVyOiBmdW5jdGlvbiBhdHhIZWFkZXIoIGJsb2NrLCBuZXh0ICkge1xuICAgICAgdmFyIG0gPSBibG9jay5tYXRjaCggL14oI3sxLDZ9KVxccyooLio/KVxccyojKlxccyooPzpcXG58JCkvICk7XG5cbiAgICAgIGlmICggIW0gKSByZXR1cm4gdW5kZWZpbmVkO1xuXG4gICAgICB2YXIgaGVhZGVyID0gWyBcImhlYWRlclwiLCB7IGxldmVsOiBtWyAxIF0ubGVuZ3RoIH0gXTtcbiAgICAgIEFycmF5LnByb3RvdHlwZS5wdXNoLmFwcGx5KGhlYWRlciwgdGhpcy5wcm9jZXNzSW5saW5lKG1bIDIgXSkpO1xuXG4gICAgICBpZiAoIG1bMF0ubGVuZ3RoIDwgYmxvY2subGVuZ3RoIClcbiAgICAgICAgbmV4dC51bnNoaWZ0KCBta19ibG9jayggYmxvY2suc3Vic3RyKCBtWzBdLmxlbmd0aCApLCBibG9jay50cmFpbGluZywgYmxvY2subGluZU51bWJlciArIDIgKSApO1xuXG4gICAgICByZXR1cm4gWyBoZWFkZXIgXTtcbiAgICB9LFxuXG4gICAgc2V0ZXh0SGVhZGVyOiBmdW5jdGlvbiBzZXRleHRIZWFkZXIoIGJsb2NrLCBuZXh0ICkge1xuICAgICAgdmFyIG0gPSBibG9jay5tYXRjaCggL14oLiopXFxuKFstPV0pXFwyXFwyKyg/OlxcbnwkKS8gKTtcblxuICAgICAgaWYgKCAhbSApIHJldHVybiB1bmRlZmluZWQ7XG5cbiAgICAgIHZhciBsZXZlbCA9ICggbVsgMiBdID09PSBcIj1cIiApID8gMSA6IDI7XG4gICAgICB2YXIgaGVhZGVyID0gWyBcImhlYWRlclwiLCB7IGxldmVsIDogbGV2ZWwgfSwgbVsgMSBdIF07XG5cbiAgICAgIGlmICggbVswXS5sZW5ndGggPCBibG9jay5sZW5ndGggKVxuICAgICAgICBuZXh0LnVuc2hpZnQoIG1rX2Jsb2NrKCBibG9jay5zdWJzdHIoIG1bMF0ubGVuZ3RoICksIGJsb2NrLnRyYWlsaW5nLCBibG9jay5saW5lTnVtYmVyICsgMiApICk7XG5cbiAgICAgIHJldHVybiBbIGhlYWRlciBdO1xuICAgIH0sXG5cbiAgICBjb2RlOiBmdW5jdGlvbiBjb2RlKCBibG9jaywgbmV4dCApIHtcbiAgICAgIC8vIHwgICAgRm9vXG4gICAgICAvLyB8YmFyXG4gICAgICAvLyBzaG91bGQgYmUgYSBjb2RlIGJsb2NrIGZvbGxvd2VkIGJ5IGEgcGFyYWdyYXBoLiBGdW5cbiAgICAgIC8vXG4gICAgICAvLyBUaGVyZSBtaWdodCBhbHNvIGJlIGFkamFjZW50IGNvZGUgYmxvY2sgdG8gbWVyZ2UuXG5cbiAgICAgIHZhciByZXQgPSBbXSxcbiAgICAgICAgICByZSA9IC9eKD86IHswLDN9XFx0fCB7NH0pKC4qKVxcbj8vLFxuICAgICAgICAgIGxpbmVzO1xuXG4gICAgICAvLyA0IHNwYWNlcyArIGNvbnRlbnRcbiAgICAgIGlmICggIWJsb2NrLm1hdGNoKCByZSApICkgcmV0dXJuIHVuZGVmaW5lZDtcblxuICAgICAgYmxvY2tfc2VhcmNoOlxuICAgICAgZG8ge1xuICAgICAgICAvLyBOb3cgcHVsbCBvdXQgdGhlIHJlc3Qgb2YgdGhlIGxpbmVzXG4gICAgICAgIHZhciBiID0gdGhpcy5sb29wX3JlX292ZXJfYmxvY2soXG4gICAgICAgICAgICAgICAgICByZSwgYmxvY2sudmFsdWVPZigpLCBmdW5jdGlvbiggbSApIHsgcmV0LnB1c2goIG1bMV0gKTsgfSApO1xuXG4gICAgICAgIGlmICggYi5sZW5ndGggKSB7XG4gICAgICAgICAgLy8gQ2FzZSBhbGx1ZGVkIHRvIGluIGZpcnN0IGNvbW1lbnQuIHB1c2ggaXQgYmFjayBvbiBhcyBhIG5ldyBibG9ja1xuICAgICAgICAgIG5leHQudW5zaGlmdCggbWtfYmxvY2soYiwgYmxvY2sudHJhaWxpbmcpICk7XG4gICAgICAgICAgYnJlYWsgYmxvY2tfc2VhcmNoO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKCBuZXh0Lmxlbmd0aCApIHtcbiAgICAgICAgICAvLyBDaGVjayB0aGUgbmV4dCBibG9jayAtIGl0IG1pZ2h0IGJlIGNvZGUgdG9vXG4gICAgICAgICAgaWYgKCAhbmV4dFswXS5tYXRjaCggcmUgKSApIGJyZWFrIGJsb2NrX3NlYXJjaDtcblxuICAgICAgICAgIC8vIFB1bGwgaG93IGhvdyBtYW55IGJsYW5rcyBsaW5lcyBmb2xsb3cgLSBtaW51cyB0d28gdG8gYWNjb3VudCBmb3IgLmpvaW5cbiAgICAgICAgICByZXQucHVzaCAoIGJsb2NrLnRyYWlsaW5nLnJlcGxhY2UoL1teXFxuXS9nLCBcIlwiKS5zdWJzdHJpbmcoMikgKTtcblxuICAgICAgICAgIGJsb2NrID0gbmV4dC5zaGlmdCgpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgIGJyZWFrIGJsb2NrX3NlYXJjaDtcbiAgICAgICAgfVxuICAgICAgfSB3aGlsZSAoIHRydWUgKTtcblxuICAgICAgcmV0dXJuIFsgWyBcImNvZGVfYmxvY2tcIiwgcmV0LmpvaW4oXCJcXG5cIikgXSBdO1xuICAgIH0sXG5cbiAgICBob3JpelJ1bGU6IGZ1bmN0aW9uIGhvcml6UnVsZSggYmxvY2ssIG5leHQgKSB7XG4gICAgICAvLyB0aGlzIG5lZWRzIHRvIGZpbmQgYW55IGhyIGluIHRoZSBibG9jayB0byBoYW5kbGUgYWJ1dHRpbmcgYmxvY2tzXG4gICAgICB2YXIgbSA9IGJsb2NrLm1hdGNoKCAvXig/OihbXFxzXFxTXSo/KVxcbik/WyBcXHRdKihbLV8qXSkoPzpbIFxcdF0qXFwyKXsyLH1bIFxcdF0qKD86XFxuKFtcXHNcXFNdKikpPyQvICk7XG5cbiAgICAgIGlmICggIW0gKSB7XG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICB9XG5cbiAgICAgIHZhciBqc29ubWwgPSBbIFsgXCJoclwiIF0gXTtcblxuICAgICAgLy8gaWYgdGhlcmUncyBhIGxlYWRpbmcgYWJ1dHRpbmcgYmxvY2ssIHByb2Nlc3MgaXRcbiAgICAgIGlmICggbVsgMSBdICkge1xuICAgICAgICBqc29ubWwudW5zaGlmdC5hcHBseSgganNvbm1sLCB0aGlzLnByb2Nlc3NCbG9jayggbVsgMSBdLCBbXSApICk7XG4gICAgICB9XG5cbiAgICAgIC8vIGlmIHRoZXJlJ3MgYSB0cmFpbGluZyBhYnV0dGluZyBibG9jaywgc3RpY2sgaXQgaW50byBuZXh0XG4gICAgICBpZiAoIG1bIDMgXSApIHtcbiAgICAgICAgbmV4dC51bnNoaWZ0KCBta19ibG9jayggbVsgMyBdICkgKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGpzb25tbDtcbiAgICB9LFxuXG4gICAgLy8gVGhlcmUgYXJlIHR3byB0eXBlcyBvZiBsaXN0cy4gVGlnaHQgYW5kIGxvb3NlLiBUaWdodCBsaXN0cyBoYXZlIG5vIHdoaXRlc3BhY2VcbiAgICAvLyBiZXR3ZWVuIHRoZSBpdGVtcyAoYW5kIHJlc3VsdCBpbiB0ZXh0IGp1c3QgaW4gdGhlIDxsaT4pIGFuZCBsb29zZSBsaXN0cyxcbiAgICAvLyB3aGljaCBoYXZlIGFuIGVtcHR5IGxpbmUgYmV0d2VlbiBsaXN0IGl0ZW1zLCByZXN1bHRpbmcgaW4gKG9uZSBvciBtb3JlKVxuICAgIC8vIHBhcmFncmFwaHMgaW5zaWRlIHRoZSA8bGk+LlxuICAgIC8vXG4gICAgLy8gVGhlcmUgYXJlIGFsbCBzb3J0cyB3ZWlyZCBlZGdlIGNhc2VzIGFib3V0IHRoZSBvcmlnaW5hbCBtYXJrZG93bi5wbCdzXG4gICAgLy8gaGFuZGxpbmcgb2YgbGlzdHM6XG4gICAgLy9cbiAgICAvLyAqIE5lc3RlZCBsaXN0cyBhcmUgc3VwcG9zZWQgdG8gYmUgaW5kZW50ZWQgYnkgZm91ciBjaGFycyBwZXIgbGV2ZWwuIEJ1dFxuICAgIC8vICAgaWYgdGhleSBhcmVuJ3QsIHlvdSBjYW4gZ2V0IGEgbmVzdGVkIGxpc3QgYnkgaW5kZW50aW5nIGJ5IGxlc3MgdGhhblxuICAgIC8vICAgZm91ciBzbyBsb25nIGFzIHRoZSBpbmRlbnQgZG9lc24ndCBtYXRjaCBhbiBpbmRlbnQgb2YgYW4gZXhpc3RpbmcgbGlzdFxuICAgIC8vICAgaXRlbSBpbiB0aGUgJ25lc3Qgc3RhY2snLlxuICAgIC8vXG4gICAgLy8gKiBUaGUgdHlwZSBvZiB0aGUgbGlzdCAoYnVsbGV0IG9yIG51bWJlcikgaXMgY29udHJvbGxlZCBqdXN0IGJ5IHRoZVxuICAgIC8vICAgIGZpcnN0IGl0ZW0gYXQgdGhlIGluZGVudC4gU3Vic2VxdWVudCBjaGFuZ2VzIGFyZSBpZ25vcmVkIHVubGVzcyB0aGV5XG4gICAgLy8gICAgYXJlIGZvciBuZXN0ZWQgbGlzdHNcbiAgICAvL1xuICAgIGxpc3RzOiAoZnVuY3Rpb24oICkge1xuICAgICAgLy8gVXNlIGEgY2xvc3VyZSB0byBoaWRlIGEgZmV3IHZhcmlhYmxlcy5cbiAgICAgIHZhciBhbnlfbGlzdCA9IFwiWyorLV18XFxcXGQrXFxcXC5cIixcbiAgICAgICAgICBidWxsZXRfbGlzdCA9IC9bKistXS8sXG4gICAgICAgICAgbnVtYmVyX2xpc3QgPSAvXFxkK1xcLi8sXG4gICAgICAgICAgLy8gQ2FwdHVyZSBsZWFkaW5nIGluZGVudCBhcyBpdCBtYXR0ZXJzIGZvciBkZXRlcm1pbmluZyBuZXN0ZWQgbGlzdHMuXG4gICAgICAgICAgaXNfbGlzdF9yZSA9IG5ldyBSZWdFeHAoIFwiXiggezAsM30pKFwiICsgYW55X2xpc3QgKyBcIilbIFxcdF0rXCIgKSxcbiAgICAgICAgICBpbmRlbnRfcmUgPSBcIig/OiB7MCwzfVxcXFx0fCB7NH0pXCI7XG5cbiAgICAgIC8vIFRPRE86IENhY2hlIHRoaXMgcmVnZXhwIGZvciBjZXJ0YWluIGRlcHRocy5cbiAgICAgIC8vIENyZWF0ZSBhIHJlZ2V4cCBzdWl0YWJsZSBmb3IgbWF0Y2hpbmcgYW4gbGkgZm9yIGEgZ2l2ZW4gc3RhY2sgZGVwdGhcbiAgICAgIGZ1bmN0aW9uIHJlZ2V4X2Zvcl9kZXB0aCggZGVwdGggKSB7XG5cbiAgICAgICAgcmV0dXJuIG5ldyBSZWdFeHAoXG4gICAgICAgICAgLy8gbVsxXSA9IGluZGVudCwgbVsyXSA9IGxpc3RfdHlwZVxuICAgICAgICAgIFwiKD86XihcIiArIGluZGVudF9yZSArIFwiezAsXCIgKyBkZXB0aCArIFwifSB7MCwzfSkoXCIgKyBhbnlfbGlzdCArIFwiKVxcXFxzKyl8XCIgK1xuICAgICAgICAgIC8vIG1bM10gPSBjb250XG4gICAgICAgICAgXCIoXlwiICsgaW5kZW50X3JlICsgXCJ7MCxcIiArIChkZXB0aC0xKSArIFwifVsgXXswLDR9KVwiXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICBmdW5jdGlvbiBleHBhbmRfdGFiKCBpbnB1dCApIHtcbiAgICAgICAgcmV0dXJuIGlucHV0LnJlcGxhY2UoIC8gezAsM31cXHQvZywgXCIgICAgXCIgKTtcbiAgICAgIH1cblxuICAgICAgLy8gQWRkIGlubGluZSBjb250ZW50IGBpbmxpbmVgIHRvIGBsaWAuIGlubGluZSBjb21lcyBmcm9tIHByb2Nlc3NJbmxpbmVcbiAgICAgIC8vIHNvIGlzIGFuIGFycmF5IG9mIGNvbnRlbnRcbiAgICAgIGZ1bmN0aW9uIGFkZChsaSwgbG9vc2UsIGlubGluZSwgbmwpIHtcbiAgICAgICAgaWYgKCBsb29zZSApIHtcbiAgICAgICAgICBsaS5wdXNoKCBbIFwicGFyYVwiIF0uY29uY2F0KGlubGluZSkgKTtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgLy8gSG1tbSwgc2hvdWxkIHRoaXMgYmUgYW55IGJsb2NrIGxldmVsIGVsZW1lbnQgb3IganVzdCBwYXJhcz9cbiAgICAgICAgdmFyIGFkZF90byA9IGxpW2xpLmxlbmd0aCAtMV0gaW5zdGFuY2VvZiBBcnJheSAmJiBsaVtsaS5sZW5ndGggLSAxXVswXSA9PSBcInBhcmFcIlxuICAgICAgICAgICAgICAgICAgID8gbGlbbGkubGVuZ3RoIC0xXVxuICAgICAgICAgICAgICAgICAgIDogbGk7XG5cbiAgICAgICAgLy8gSWYgdGhlcmUgaXMgYWxyZWFkeSBzb21lIGNvbnRlbnQgaW4gdGhpcyBsaXN0LCBhZGQgdGhlIG5ldyBsaW5lIGluXG4gICAgICAgIGlmICggbmwgJiYgbGkubGVuZ3RoID4gMSApIGlubGluZS51bnNoaWZ0KG5sKTtcblxuICAgICAgICBmb3IgKCB2YXIgaSA9IDA7IGkgPCBpbmxpbmUubGVuZ3RoOyBpKysgKSB7XG4gICAgICAgICAgdmFyIHdoYXQgPSBpbmxpbmVbaV0sXG4gICAgICAgICAgICAgIGlzX3N0ciA9IHR5cGVvZiB3aGF0ID09IFwic3RyaW5nXCI7XG4gICAgICAgICAgaWYgKCBpc19zdHIgJiYgYWRkX3RvLmxlbmd0aCA+IDEgJiYgdHlwZW9mIGFkZF90b1thZGRfdG8ubGVuZ3RoLTFdID09IFwic3RyaW5nXCIgKSB7XG4gICAgICAgICAgICBhZGRfdG9bIGFkZF90by5sZW5ndGgtMSBdICs9IHdoYXQ7XG4gICAgICAgICAgfVxuICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgYWRkX3RvLnB1c2goIHdoYXQgKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLy8gY29udGFpbmVkIG1lYW5zIGhhdmUgYW4gaW5kZW50IGdyZWF0ZXIgdGhhbiB0aGUgY3VycmVudCBvbmUuIE9uXG4gICAgICAvLyAqZXZlcnkqIGxpbmUgaW4gdGhlIGJsb2NrXG4gICAgICBmdW5jdGlvbiBnZXRfY29udGFpbmVkX2Jsb2NrcyggZGVwdGgsIGJsb2NrcyApIHtcblxuICAgICAgICB2YXIgcmUgPSBuZXcgUmVnRXhwKCBcIl4oXCIgKyBpbmRlbnRfcmUgKyBcIntcIiArIGRlcHRoICsgXCJ9Lio/XFxcXG4/KSokXCIgKSxcbiAgICAgICAgICAgIHJlcGxhY2UgPSBuZXcgUmVnRXhwKFwiXlwiICsgaW5kZW50X3JlICsgXCJ7XCIgKyBkZXB0aCArIFwifVwiLCBcImdtXCIpLFxuICAgICAgICAgICAgcmV0ID0gW107XG5cbiAgICAgICAgd2hpbGUgKCBibG9ja3MubGVuZ3RoID4gMCApIHtcbiAgICAgICAgICBpZiAoIHJlLmV4ZWMoIGJsb2Nrc1swXSApICkge1xuICAgICAgICAgICAgdmFyIGIgPSBibG9ja3Muc2hpZnQoKSxcbiAgICAgICAgICAgICAgICAvLyBOb3cgcmVtb3ZlIHRoYXQgaW5kZW50XG4gICAgICAgICAgICAgICAgeCA9IGIucmVwbGFjZSggcmVwbGFjZSwgXCJcIik7XG5cbiAgICAgICAgICAgIHJldC5wdXNoKCBta19ibG9jayggeCwgYi50cmFpbGluZywgYi5saW5lTnVtYmVyICkgKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJldDtcbiAgICAgIH1cblxuICAgICAgLy8gcGFzc2VkIHRvIHN0YWNrLmZvckVhY2ggdG8gdHVybiBsaXN0IGl0ZW1zIHVwIHRoZSBzdGFjayBpbnRvIHBhcmFzXG4gICAgICBmdW5jdGlvbiBwYXJhZ3JhcGhpZnkocywgaSwgc3RhY2spIHtcbiAgICAgICAgdmFyIGxpc3QgPSBzLmxpc3Q7XG4gICAgICAgIHZhciBsYXN0X2xpID0gbGlzdFtsaXN0Lmxlbmd0aC0xXTtcblxuICAgICAgICBpZiAoIGxhc3RfbGlbMV0gaW5zdGFuY2VvZiBBcnJheSAmJiBsYXN0X2xpWzFdWzBdID09IFwicGFyYVwiICkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIGkgKyAxID09IHN0YWNrLmxlbmd0aCApIHtcbiAgICAgICAgICAvLyBMYXN0IHN0YWNrIGZyYW1lXG4gICAgICAgICAgLy8gS2VlcCB0aGUgc2FtZSBhcnJheSwgYnV0IHJlcGxhY2UgdGhlIGNvbnRlbnRzXG4gICAgICAgICAgbGFzdF9saS5wdXNoKCBbXCJwYXJhXCJdLmNvbmNhdCggbGFzdF9saS5zcGxpY2UoMSwgbGFzdF9saS5sZW5ndGggLSAxKSApICk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgdmFyIHN1Ymxpc3QgPSBsYXN0X2xpLnBvcCgpO1xuICAgICAgICAgIGxhc3RfbGkucHVzaCggW1wicGFyYVwiXS5jb25jYXQoIGxhc3RfbGkuc3BsaWNlKDEsIGxhc3RfbGkubGVuZ3RoIC0gMSkgKSwgc3VibGlzdCApO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIC8vIFRoZSBtYXRjaGVyIGZ1bmN0aW9uXG4gICAgICByZXR1cm4gZnVuY3Rpb24oIGJsb2NrLCBuZXh0ICkge1xuICAgICAgICB2YXIgbSA9IGJsb2NrLm1hdGNoKCBpc19saXN0X3JlICk7XG4gICAgICAgIGlmICggIW0gKSByZXR1cm4gdW5kZWZpbmVkO1xuXG4gICAgICAgIGZ1bmN0aW9uIG1ha2VfbGlzdCggbSApIHtcbiAgICAgICAgICB2YXIgbGlzdCA9IGJ1bGxldF9saXN0LmV4ZWMoIG1bMl0gKVxuICAgICAgICAgICAgICAgICAgID8gW1wiYnVsbGV0bGlzdFwiXVxuICAgICAgICAgICAgICAgICAgIDogW1wibnVtYmVybGlzdFwiXTtcblxuICAgICAgICAgIHN0YWNrLnB1c2goIHsgbGlzdDogbGlzdCwgaW5kZW50OiBtWzFdIH0gKTtcbiAgICAgICAgICByZXR1cm4gbGlzdDtcbiAgICAgICAgfVxuXG5cbiAgICAgICAgdmFyIHN0YWNrID0gW10sIC8vIFN0YWNrIG9mIGxpc3RzIGZvciBuZXN0aW5nLlxuICAgICAgICAgICAgbGlzdCA9IG1ha2VfbGlzdCggbSApLFxuICAgICAgICAgICAgbGFzdF9saSxcbiAgICAgICAgICAgIGxvb3NlID0gZmFsc2UsXG4gICAgICAgICAgICByZXQgPSBbIHN0YWNrWzBdLmxpc3QgXSxcbiAgICAgICAgICAgIGk7XG5cbiAgICAgICAgLy8gTG9vcCB0byBzZWFyY2ggb3ZlciBibG9jayBsb29raW5nIGZvciBpbm5lciBibG9jayBlbGVtZW50cyBhbmQgbG9vc2UgbGlzdHNcbiAgICAgICAgbG9vc2Vfc2VhcmNoOlxuICAgICAgICB3aGlsZSAoIHRydWUgKSB7XG4gICAgICAgICAgLy8gU3BsaXQgaW50byBsaW5lcyBwcmVzZXJ2aW5nIG5ldyBsaW5lcyBhdCBlbmQgb2YgbGluZVxuICAgICAgICAgIHZhciBsaW5lcyA9IGJsb2NrLnNwbGl0KCAvKD89XFxuKS8gKTtcblxuICAgICAgICAgIC8vIFdlIGhhdmUgdG8gZ3JhYiBhbGwgbGluZXMgZm9yIGEgbGkgYW5kIGNhbGwgcHJvY2Vzc0lubGluZSBvbiB0aGVtXG4gICAgICAgICAgLy8gb25jZSBhcyB0aGVyZSBhcmUgc29tZSBpbmxpbmUgdGhpbmdzIHRoYXQgY2FuIHNwYW4gbGluZXMuXG4gICAgICAgICAgdmFyIGxpX2FjY3VtdWxhdGUgPSBcIlwiO1xuXG4gICAgICAgICAgLy8gTG9vcCBvdmVyIHRoZSBsaW5lcyBpbiB0aGlzIGJsb2NrIGxvb2tpbmcgZm9yIHRpZ2h0IGxpc3RzLlxuICAgICAgICAgIHRpZ2h0X3NlYXJjaDpcbiAgICAgICAgICBmb3IgKCB2YXIgbGluZV9ubyA9IDA7IGxpbmVfbm8gPCBsaW5lcy5sZW5ndGg7IGxpbmVfbm8rKyApIHtcbiAgICAgICAgICAgIHZhciBubCA9IFwiXCIsXG4gICAgICAgICAgICAgICAgbCA9IGxpbmVzW2xpbmVfbm9dLnJlcGxhY2UoL15cXG4vLCBmdW5jdGlvbihuKSB7IG5sID0gbjsgcmV0dXJuIFwiXCI7IH0pO1xuXG4gICAgICAgICAgICAvLyBUT0RPOiByZWFsbHkgc2hvdWxkIGNhY2hlIHRoaXNcbiAgICAgICAgICAgIHZhciBsaW5lX3JlID0gcmVnZXhfZm9yX2RlcHRoKCBzdGFjay5sZW5ndGggKTtcblxuICAgICAgICAgICAgbSA9IGwubWF0Y2goIGxpbmVfcmUgKTtcbiAgICAgICAgICAgIC8vcHJpbnQoIFwibGluZTpcIiwgdW5ldmFsKGwpLCBcIlxcbmxpbmUgbWF0Y2g6XCIsIHVuZXZhbChtKSApO1xuXG4gICAgICAgICAgICAvLyBXZSBoYXZlIGEgbGlzdCBpdGVtXG4gICAgICAgICAgICBpZiAoIG1bMV0gIT09IHVuZGVmaW5lZCApIHtcbiAgICAgICAgICAgICAgLy8gUHJvY2VzcyB0aGUgcHJldmlvdXMgbGlzdCBpdGVtLCBpZiBhbnlcbiAgICAgICAgICAgICAgaWYgKCBsaV9hY2N1bXVsYXRlLmxlbmd0aCApIHtcbiAgICAgICAgICAgICAgICBhZGQoIGxhc3RfbGksIGxvb3NlLCB0aGlzLnByb2Nlc3NJbmxpbmUoIGxpX2FjY3VtdWxhdGUgKSwgbmwgKTtcbiAgICAgICAgICAgICAgICAvLyBMb29zZSBtb2RlIHdpbGwgaGF2ZSBiZWVuIGRlYWx0IHdpdGguIFJlc2V0IGl0XG4gICAgICAgICAgICAgICAgbG9vc2UgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICBsaV9hY2N1bXVsYXRlID0gXCJcIjtcbiAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgIG1bMV0gPSBleHBhbmRfdGFiKCBtWzFdICk7XG4gICAgICAgICAgICAgIHZhciB3YW50ZWRfZGVwdGggPSBNYXRoLmZsb29yKG1bMV0ubGVuZ3RoLzQpKzE7XG4gICAgICAgICAgICAgIC8vcHJpbnQoIFwid2FudDpcIiwgd2FudGVkX2RlcHRoLCBcInN0YWNrOlwiLCBzdGFjay5sZW5ndGgpO1xuICAgICAgICAgICAgICBpZiAoIHdhbnRlZF9kZXB0aCA+IHN0YWNrLmxlbmd0aCApIHtcbiAgICAgICAgICAgICAgICAvLyBEZWVwIGVub3VnaCBmb3IgYSBuZXN0ZWQgbGlzdCBvdXRyaWdodFxuICAgICAgICAgICAgICAgIC8vcHJpbnQgKCBcIm5ldyBuZXN0ZWQgbGlzdFwiICk7XG4gICAgICAgICAgICAgICAgbGlzdCA9IG1ha2VfbGlzdCggbSApO1xuICAgICAgICAgICAgICAgIGxhc3RfbGkucHVzaCggbGlzdCApO1xuICAgICAgICAgICAgICAgIGxhc3RfbGkgPSBsaXN0WzFdID0gWyBcImxpc3RpdGVtXCIgXTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyBXZSBhcmVuJ3QgZGVlcCBlbm91Z2ggdG8gYmUgc3RyaWN0bHkgYSBuZXcgbGV2ZWwuIFRoaXMgaXNcbiAgICAgICAgICAgICAgICAvLyB3aGVyZSBNZC5wbCBnb2VzIG51dHMuIElmIHRoZSBpbmRlbnQgbWF0Y2hlcyBhIGxldmVsIGluIHRoZVxuICAgICAgICAgICAgICAgIC8vIHN0YWNrLCBwdXQgaXQgdGhlcmUsIGVsc2UgcHV0IGl0IG9uZSBkZWVwZXIgdGhlbiB0aGVcbiAgICAgICAgICAgICAgICAvLyB3YW50ZWRfZGVwdGggZGVzZXJ2ZXMuXG4gICAgICAgICAgICAgICAgdmFyIGZvdW5kID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgZm9yICggaSA9IDA7IGkgPCBzdGFjay5sZW5ndGg7IGkrKyApIHtcbiAgICAgICAgICAgICAgICAgIGlmICggc3RhY2tbIGkgXS5pbmRlbnQgIT0gbVsxXSApIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgbGlzdCA9IHN0YWNrWyBpIF0ubGlzdDtcbiAgICAgICAgICAgICAgICAgIHN0YWNrLnNwbGljZSggaSsxLCBzdGFjay5sZW5ndGggLSAoaSsxKSApO1xuICAgICAgICAgICAgICAgICAgZm91bmQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCFmb3VuZCkge1xuICAgICAgICAgICAgICAgICAgLy9wcmludChcIm5vdCBmb3VuZC4gbDpcIiwgdW5ldmFsKGwpKTtcbiAgICAgICAgICAgICAgICAgIHdhbnRlZF9kZXB0aCsrO1xuICAgICAgICAgICAgICAgICAgaWYgKCB3YW50ZWRfZGVwdGggPD0gc3RhY2subGVuZ3RoICkge1xuICAgICAgICAgICAgICAgICAgICBzdGFjay5zcGxpY2Uod2FudGVkX2RlcHRoLCBzdGFjay5sZW5ndGggLSB3YW50ZWRfZGVwdGgpO1xuICAgICAgICAgICAgICAgICAgICAvL3ByaW50KFwiRGVzaXJlZCBkZXB0aCBub3dcIiwgd2FudGVkX2RlcHRoLCBcInN0YWNrOlwiLCBzdGFjay5sZW5ndGgpO1xuICAgICAgICAgICAgICAgICAgICBsaXN0ID0gc3RhY2tbd2FudGVkX2RlcHRoLTFdLmxpc3Q7XG4gICAgICAgICAgICAgICAgICAgIC8vcHJpbnQoXCJsaXN0OlwiLCB1bmV2YWwobGlzdCkgKTtcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAvL3ByaW50IChcIm1hZGUgbmV3IHN0YWNrIGZvciBtZXNzeSBpbmRlbnRcIik7XG4gICAgICAgICAgICAgICAgICAgIGxpc3QgPSBtYWtlX2xpc3QobSk7XG4gICAgICAgICAgICAgICAgICAgIGxhc3RfbGkucHVzaChsaXN0KTtcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvL3ByaW50KCB1bmV2YWwobGlzdCksIFwibGFzdFwiLCBsaXN0ID09PSBzdGFja1tzdGFjay5sZW5ndGgtMV0ubGlzdCApO1xuICAgICAgICAgICAgICAgIGxhc3RfbGkgPSBbIFwibGlzdGl0ZW1cIiBdO1xuICAgICAgICAgICAgICAgIGxpc3QucHVzaChsYXN0X2xpKTtcbiAgICAgICAgICAgICAgfSAvLyBlbmQgZGVwdGggb2Ygc2hlbmVnYWluc1xuICAgICAgICAgICAgICBubCA9IFwiXCI7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEFkZCBjb250ZW50XG4gICAgICAgICAgICBpZiAoIGwubGVuZ3RoID4gbVswXS5sZW5ndGggKSB7XG4gICAgICAgICAgICAgIGxpX2FjY3VtdWxhdGUgKz0gbmwgKyBsLnN1YnN0ciggbVswXS5sZW5ndGggKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IC8vIHRpZ2h0X3NlYXJjaFxuXG4gICAgICAgICAgaWYgKCBsaV9hY2N1bXVsYXRlLmxlbmd0aCApIHtcbiAgICAgICAgICAgIGFkZCggbGFzdF9saSwgbG9vc2UsIHRoaXMucHJvY2Vzc0lubGluZSggbGlfYWNjdW11bGF0ZSApLCBubCApO1xuICAgICAgICAgICAgLy8gTG9vc2UgbW9kZSB3aWxsIGhhdmUgYmVlbiBkZWFsdCB3aXRoLiBSZXNldCBpdFxuICAgICAgICAgICAgbG9vc2UgPSBmYWxzZTtcbiAgICAgICAgICAgIGxpX2FjY3VtdWxhdGUgPSBcIlwiO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIC8vIExvb2sgYXQgdGhlIG5leHQgYmxvY2sgLSB3ZSBtaWdodCBoYXZlIGEgbG9vc2UgbGlzdC4gT3IgYW4gZXh0cmFcbiAgICAgICAgICAvLyBwYXJhZ3JhcGggZm9yIHRoZSBjdXJyZW50IGxpXG4gICAgICAgICAgdmFyIGNvbnRhaW5lZCA9IGdldF9jb250YWluZWRfYmxvY2tzKCBzdGFjay5sZW5ndGgsIG5leHQgKTtcblxuICAgICAgICAgIC8vIERlYWwgd2l0aCBjb2RlIGJsb2NrcyBvciBwcm9wZXJseSBuZXN0ZWQgbGlzdHNcbiAgICAgICAgICBpZiAoIGNvbnRhaW5lZC5sZW5ndGggPiAwICkge1xuICAgICAgICAgICAgLy8gTWFrZSBzdXJlIGFsbCBsaXN0aXRlbXMgdXAgdGhlIHN0YWNrIGFyZSBwYXJhZ3JhcGhzXG4gICAgICAgICAgICBmb3JFYWNoKCBzdGFjaywgcGFyYWdyYXBoaWZ5LCB0aGlzKTtcblxuICAgICAgICAgICAgbGFzdF9saS5wdXNoLmFwcGx5KCBsYXN0X2xpLCB0aGlzLnRvVHJlZSggY29udGFpbmVkLCBbXSApICk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgdmFyIG5leHRfYmxvY2sgPSBuZXh0WzBdICYmIG5leHRbMF0udmFsdWVPZigpIHx8IFwiXCI7XG5cbiAgICAgICAgICBpZiAoIG5leHRfYmxvY2subWF0Y2goaXNfbGlzdF9yZSkgfHwgbmV4dF9ibG9jay5tYXRjaCggL14gLyApICkge1xuICAgICAgICAgICAgYmxvY2sgPSBuZXh0LnNoaWZ0KCk7XG5cbiAgICAgICAgICAgIC8vIENoZWNrIGZvciBhbiBIUiBmb2xsb3dpbmcgYSBsaXN0OiBmZWF0dXJlcy9saXN0cy9ocl9hYnV0dGluZ1xuICAgICAgICAgICAgdmFyIGhyID0gdGhpcy5kaWFsZWN0LmJsb2NrLmhvcml6UnVsZSggYmxvY2ssIG5leHQgKTtcblxuICAgICAgICAgICAgaWYgKCBociApIHtcbiAgICAgICAgICAgICAgcmV0LnB1c2guYXBwbHkocmV0LCBocik7XG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBNYWtlIHN1cmUgYWxsIGxpc3RpdGVtcyB1cCB0aGUgc3RhY2sgYXJlIHBhcmFncmFwaHNcbiAgICAgICAgICAgIGZvckVhY2goIHN0YWNrLCBwYXJhZ3JhcGhpZnksIHRoaXMpO1xuXG4gICAgICAgICAgICBsb29zZSA9IHRydWU7XG4gICAgICAgICAgICBjb250aW51ZSBsb29zZV9zZWFyY2g7XG4gICAgICAgICAgfVxuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9IC8vIGxvb3NlX3NlYXJjaFxuXG4gICAgICAgIHJldHVybiByZXQ7XG4gICAgICB9O1xuICAgIH0pKCksXG5cbiAgICBibG9ja3F1b3RlOiBmdW5jdGlvbiBibG9ja3F1b3RlKCBibG9jaywgbmV4dCApIHtcbiAgICAgIGlmICggIWJsb2NrLm1hdGNoKCAvXj4vbSApIClcbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcblxuICAgICAgdmFyIGpzb25tbCA9IFtdO1xuXG4gICAgICAvLyBzZXBhcmF0ZSBvdXQgdGhlIGxlYWRpbmcgYWJ1dHRpbmcgYmxvY2ssIGlmIGFueS4gSS5lLiBpbiB0aGlzIGNhc2U6XG4gICAgICAvL1xuICAgICAgLy8gIGFcbiAgICAgIC8vICA+IGJcbiAgICAgIC8vXG4gICAgICBpZiAoIGJsb2NrWyAwIF0gIT0gXCI+XCIgKSB7XG4gICAgICAgIHZhciBsaW5lcyA9IGJsb2NrLnNwbGl0KCAvXFxuLyApLFxuICAgICAgICAgICAgcHJldiA9IFtdLFxuICAgICAgICAgICAgbGluZV9ubyA9IGJsb2NrLmxpbmVOdW1iZXI7XG5cbiAgICAgICAgLy8ga2VlcCBzaGlmdGluZyBsaW5lcyB1bnRpbCB5b3UgZmluZCBhIGNyb3RjaGV0XG4gICAgICAgIHdoaWxlICggbGluZXMubGVuZ3RoICYmIGxpbmVzWyAwIF1bIDAgXSAhPSBcIj5cIiApIHtcbiAgICAgICAgICAgIHByZXYucHVzaCggbGluZXMuc2hpZnQoKSApO1xuICAgICAgICAgICAgbGluZV9ubysrO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGFidXR0aW5nID0gbWtfYmxvY2soIHByZXYuam9pbiggXCJcXG5cIiApLCBcIlxcblwiLCBibG9jay5saW5lTnVtYmVyICk7XG4gICAgICAgIGpzb25tbC5wdXNoLmFwcGx5KCBqc29ubWwsIHRoaXMucHJvY2Vzc0Jsb2NrKCBhYnV0dGluZywgW10gKSApO1xuICAgICAgICAvLyByZWFzc2VtYmxlIG5ldyBibG9jayBvZiBqdXN0IGJsb2NrIHF1b3RlcyFcbiAgICAgICAgYmxvY2sgPSBta19ibG9jayggbGluZXMuam9pbiggXCJcXG5cIiApLCBibG9jay50cmFpbGluZywgbGluZV9ubyApO1xuICAgICAgfVxuXG5cbiAgICAgIC8vIGlmIHRoZSBuZXh0IGJsb2NrIGlzIGFsc28gYSBibG9ja3F1b3RlIG1lcmdlIGl0IGluXG4gICAgICB3aGlsZSAoIG5leHQubGVuZ3RoICYmIG5leHRbIDAgXVsgMCBdID09IFwiPlwiICkge1xuICAgICAgICB2YXIgYiA9IG5leHQuc2hpZnQoKTtcbiAgICAgICAgYmxvY2sgPSBta19ibG9jayggYmxvY2sgKyBibG9jay50cmFpbGluZyArIGIsIGIudHJhaWxpbmcsIGJsb2NrLmxpbmVOdW1iZXIgKTtcbiAgICAgIH1cblxuICAgICAgLy8gU3RyaXAgb2ZmIHRoZSBsZWFkaW5nIFwiPiBcIiBhbmQgcmUtcHJvY2VzcyBhcyBhIGJsb2NrLlxuICAgICAgdmFyIGlucHV0ID0gYmxvY2sucmVwbGFjZSggL14+ID8vZ20sIFwiXCIgKSxcbiAgICAgICAgICBvbGRfdHJlZSA9IHRoaXMudHJlZSxcbiAgICAgICAgICBwcm9jZXNzZWRCbG9jayA9IHRoaXMudG9UcmVlKCBpbnB1dCwgWyBcImJsb2NrcXVvdGVcIiBdICksXG4gICAgICAgICAgYXR0ciA9IGV4dHJhY3RfYXR0ciggcHJvY2Vzc2VkQmxvY2sgKTtcblxuICAgICAgLy8gSWYgYW55IGxpbmsgcmVmZXJlbmNlcyB3ZXJlIGZvdW5kIGdldCByaWQgb2YgdGhlbVxuICAgICAgaWYgKCBhdHRyICYmIGF0dHIucmVmZXJlbmNlcyApIHtcbiAgICAgICAgZGVsZXRlIGF0dHIucmVmZXJlbmNlcztcbiAgICAgICAgLy8gQW5kIHRoZW4gcmVtb3ZlIHRoZSBhdHRyaWJ1dGUgb2JqZWN0IGlmIGl0J3MgZW1wdHlcbiAgICAgICAgaWYgKCBpc0VtcHR5KCBhdHRyICkgKSB7XG4gICAgICAgICAgcHJvY2Vzc2VkQmxvY2suc3BsaWNlKCAxLCAxICk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAganNvbm1sLnB1c2goIHByb2Nlc3NlZEJsb2NrICk7XG4gICAgICByZXR1cm4ganNvbm1sO1xuICAgIH0sXG5cbiAgICByZWZlcmVuY2VEZWZuOiBmdW5jdGlvbiByZWZlcmVuY2VEZWZuKCBibG9jaywgbmV4dCkge1xuICAgICAgdmFyIHJlID0gL15cXHMqXFxbKC4qPylcXF06XFxzKihcXFMrKSg/OlxccysoPzooWydcIl0pKC4qPylcXDN8XFwoKC4qPylcXCkpKT9cXG4/LztcbiAgICAgIC8vIGludGVyZXN0aW5nIG1hdGNoZXMgYXJlIFsgLCByZWZfaWQsIHVybCwgLCB0aXRsZSwgdGl0bGUgXVxuXG4gICAgICBpZiAoICFibG9jay5tYXRjaChyZSkgKVxuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuXG4gICAgICAvLyBtYWtlIGFuIGF0dHJpYnV0ZSBub2RlIGlmIGl0IGRvZXNuJ3QgZXhpc3RcbiAgICAgIGlmICggIWV4dHJhY3RfYXR0ciggdGhpcy50cmVlICkgKSB7XG4gICAgICAgIHRoaXMudHJlZS5zcGxpY2UoIDEsIDAsIHt9ICk7XG4gICAgICB9XG5cbiAgICAgIHZhciBhdHRycyA9IGV4dHJhY3RfYXR0ciggdGhpcy50cmVlICk7XG5cbiAgICAgIC8vIG1ha2UgYSByZWZlcmVuY2VzIGhhc2ggaWYgaXQgZG9lc24ndCBleGlzdFxuICAgICAgaWYgKCBhdHRycy5yZWZlcmVuY2VzID09PSB1bmRlZmluZWQgKSB7XG4gICAgICAgIGF0dHJzLnJlZmVyZW5jZXMgPSB7fTtcbiAgICAgIH1cblxuICAgICAgdmFyIGIgPSB0aGlzLmxvb3BfcmVfb3Zlcl9ibG9jayhyZSwgYmxvY2ssIGZ1bmN0aW9uKCBtICkge1xuXG4gICAgICAgIGlmICggbVsyXSAmJiBtWzJdWzBdID09IFwiPFwiICYmIG1bMl1bbVsyXS5sZW5ndGgtMV0gPT0gXCI+XCIgKVxuICAgICAgICAgIG1bMl0gPSBtWzJdLnN1YnN0cmluZyggMSwgbVsyXS5sZW5ndGggLSAxICk7XG5cbiAgICAgICAgdmFyIHJlZiA9IGF0dHJzLnJlZmVyZW5jZXNbIG1bMV0udG9Mb3dlckNhc2UoKSBdID0ge1xuICAgICAgICAgIGhyZWY6IG1bMl1cbiAgICAgICAgfTtcblxuICAgICAgICBpZiAoIG1bNF0gIT09IHVuZGVmaW5lZCApXG4gICAgICAgICAgcmVmLnRpdGxlID0gbVs0XTtcbiAgICAgICAgZWxzZSBpZiAoIG1bNV0gIT09IHVuZGVmaW5lZCApXG4gICAgICAgICAgcmVmLnRpdGxlID0gbVs1XTtcblxuICAgICAgfSApO1xuXG4gICAgICBpZiAoIGIubGVuZ3RoIClcbiAgICAgICAgbmV4dC51bnNoaWZ0KCBta19ibG9jayggYiwgYmxvY2sudHJhaWxpbmcgKSApO1xuXG4gICAgICByZXR1cm4gW107XG4gICAgfSxcblxuICAgIHBhcmE6IGZ1bmN0aW9uIHBhcmEoIGJsb2NrLCBuZXh0ICkge1xuICAgICAgLy8gZXZlcnl0aGluZydzIGEgcGFyYSFcbiAgICAgIHJldHVybiBbIFtcInBhcmFcIl0uY29uY2F0KCB0aGlzLnByb2Nlc3NJbmxpbmUoIGJsb2NrICkgKSBdO1xuICAgIH1cbiAgfVxufTtcblxuTWFya2Rvd24uZGlhbGVjdHMuR3J1YmVyLmlubGluZSA9IHtcblxuICAgIF9fb25lRWxlbWVudF9fOiBmdW5jdGlvbiBvbmVFbGVtZW50KCB0ZXh0LCBwYXR0ZXJuc19vcl9yZSwgcHJldmlvdXNfbm9kZXMgKSB7XG4gICAgICB2YXIgbSxcbiAgICAgICAgICByZXMsXG4gICAgICAgICAgbGFzdEluZGV4ID0gMDtcblxuICAgICAgcGF0dGVybnNfb3JfcmUgPSBwYXR0ZXJuc19vcl9yZSB8fCB0aGlzLmRpYWxlY3QuaW5saW5lLl9fcGF0dGVybnNfXztcbiAgICAgIHZhciByZSA9IG5ldyBSZWdFeHAoIFwiKFtcXFxcc1xcXFxTXSo/KShcIiArIChwYXR0ZXJuc19vcl9yZS5zb3VyY2UgfHwgcGF0dGVybnNfb3JfcmUpICsgXCIpXCIgKTtcblxuICAgICAgbSA9IHJlLmV4ZWMoIHRleHQgKTtcbiAgICAgIGlmICghbSkge1xuICAgICAgICAvLyBKdXN0IGJvcmluZyB0ZXh0XG4gICAgICAgIHJldHVybiBbIHRleHQubGVuZ3RoLCB0ZXh0IF07XG4gICAgICB9XG4gICAgICBlbHNlIGlmICggbVsxXSApIHtcbiAgICAgICAgLy8gU29tZSB1bi1pbnRlcmVzdGluZyB0ZXh0IG1hdGNoZWQuIFJldHVybiB0aGF0IGZpcnN0XG4gICAgICAgIHJldHVybiBbIG1bMV0ubGVuZ3RoLCBtWzFdIF07XG4gICAgICB9XG5cbiAgICAgIHZhciByZXM7XG4gICAgICBpZiAoIG1bMl0gaW4gdGhpcy5kaWFsZWN0LmlubGluZSApIHtcbiAgICAgICAgcmVzID0gdGhpcy5kaWFsZWN0LmlubGluZVsgbVsyXSBdLmNhbGwoXG4gICAgICAgICAgICAgICAgICB0aGlzLFxuICAgICAgICAgICAgICAgICAgdGV4dC5zdWJzdHIoIG0uaW5kZXggKSwgbSwgcHJldmlvdXNfbm9kZXMgfHwgW10gKTtcbiAgICAgIH1cbiAgICAgIC8vIERlZmF1bHQgZm9yIG5vdyB0byBtYWtlIGRldiBlYXNpZXIuIGp1c3Qgc2x1cnAgc3BlY2lhbCBhbmQgb3V0cHV0IGl0LlxuICAgICAgcmVzID0gcmVzIHx8IFsgbVsyXS5sZW5ndGgsIG1bMl0gXTtcbiAgICAgIHJldHVybiByZXM7XG4gICAgfSxcblxuICAgIF9fY2FsbF9fOiBmdW5jdGlvbiBpbmxpbmUoIHRleHQsIHBhdHRlcm5zICkge1xuXG4gICAgICB2YXIgb3V0ID0gW10sXG4gICAgICAgICAgcmVzO1xuXG4gICAgICBmdW5jdGlvbiBhZGQoeCkge1xuICAgICAgICAvL0Q6c2VsZi5kZWJ1ZyhcIiAgYWRkaW5nIG91dHB1dFwiLCB1bmV2YWwoeCkpO1xuICAgICAgICBpZiAoIHR5cGVvZiB4ID09IFwic3RyaW5nXCIgJiYgdHlwZW9mIG91dFtvdXQubGVuZ3RoLTFdID09IFwic3RyaW5nXCIgKVxuICAgICAgICAgIG91dFsgb3V0Lmxlbmd0aC0xIF0gKz0geDtcbiAgICAgICAgZWxzZVxuICAgICAgICAgIG91dC5wdXNoKHgpO1xuICAgICAgfVxuXG4gICAgICB3aGlsZSAoIHRleHQubGVuZ3RoID4gMCApIHtcbiAgICAgICAgcmVzID0gdGhpcy5kaWFsZWN0LmlubGluZS5fX29uZUVsZW1lbnRfXy5jYWxsKHRoaXMsIHRleHQsIHBhdHRlcm5zLCBvdXQgKTtcbiAgICAgICAgdGV4dCA9IHRleHQuc3Vic3RyKCByZXMuc2hpZnQoKSApO1xuICAgICAgICBmb3JFYWNoKHJlcywgYWRkIClcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIG91dDtcbiAgICB9LFxuXG4gICAgLy8gVGhlc2UgY2hhcmFjdGVycyBhcmUgaW50ZXJzdGluZyBlbHNld2hlcmUsIHNvIGhhdmUgcnVsZXMgZm9yIHRoZW0gc28gdGhhdFxuICAgIC8vIGNodW5rcyBvZiBwbGFpbiB0ZXh0IGJsb2NrcyBkb24ndCBpbmNsdWRlIHRoZW1cbiAgICBcIl1cIjogZnVuY3Rpb24gKCkge30sXG4gICAgXCJ9XCI6IGZ1bmN0aW9uICgpIHt9LFxuXG4gICAgX19lc2NhcGVfXyA6IC9eXFxcXFtcXFxcYFxcKl97fVxcW1xcXSgpI1xcKy4hXFwtXS8sXG5cbiAgICBcIlxcXFxcIjogZnVuY3Rpb24gZXNjYXBlZCggdGV4dCApIHtcbiAgICAgIC8vIFsgbGVuZ3RoIG9mIGlucHV0IHByb2Nlc3NlZCwgbm9kZS9jaGlsZHJlbiB0byBhZGQuLi4gXVxuICAgICAgLy8gT25seSBlc2FjYXBlOiBcXCBgICogXyB7IH0gWyBdICggKSAjICogKyAtIC4gIVxuICAgICAgaWYgKCB0aGlzLmRpYWxlY3QuaW5saW5lLl9fZXNjYXBlX18uZXhlYyggdGV4dCApIClcbiAgICAgICAgcmV0dXJuIFsgMiwgdGV4dC5jaGFyQXQoIDEgKSBdO1xuICAgICAgZWxzZVxuICAgICAgICAvLyBOb3QgYW4gZXNhY3BlXG4gICAgICAgIHJldHVybiBbIDEsIFwiXFxcXFwiIF07XG4gICAgfSxcblxuICAgIFwiIVtcIjogZnVuY3Rpb24gaW1hZ2UoIHRleHQgKSB7XG5cbiAgICAgIC8vIFVubGlrZSBpbWFnZXMsIGFsdCB0ZXh0IGlzIHBsYWluIHRleHQgb25seS4gbm8gb3RoZXIgZWxlbWVudHMgYXJlXG4gICAgICAvLyBhbGxvd2VkIGluIHRoZXJlXG5cbiAgICAgIC8vICFbQWx0IHRleHRdKC9wYXRoL3RvL2ltZy5qcGcgXCJPcHRpb25hbCB0aXRsZVwiKVxuICAgICAgLy8gICAgICAxICAgICAgICAgIDIgICAgICAgICAgICAzICAgICAgIDQgICAgICAgICA8LS0tIGNhcHR1cmVzXG4gICAgICB2YXIgbSA9IHRleHQubWF0Y2goIC9eIVxcWyguKj8pXFxdWyBcXHRdKlxcKFsgXFx0XSooW15cIildKj8pKD86WyBcXHRdKyhbXCInXSkoLio/KVxcMyk/WyBcXHRdKlxcKS8gKTtcblxuICAgICAgaWYgKCBtICkge1xuICAgICAgICBpZiAoIG1bMl0gJiYgbVsyXVswXSA9PSBcIjxcIiAmJiBtWzJdW21bMl0ubGVuZ3RoLTFdID09IFwiPlwiIClcbiAgICAgICAgICBtWzJdID0gbVsyXS5zdWJzdHJpbmcoIDEsIG1bMl0ubGVuZ3RoIC0gMSApO1xuXG4gICAgICAgIG1bMl0gPSB0aGlzLmRpYWxlY3QuaW5saW5lLl9fY2FsbF9fLmNhbGwoIHRoaXMsIG1bMl0sIC9cXFxcLyApWzBdO1xuXG4gICAgICAgIHZhciBhdHRycyA9IHsgYWx0OiBtWzFdLCBocmVmOiBtWzJdIHx8IFwiXCIgfTtcbiAgICAgICAgaWYgKCBtWzRdICE9PSB1bmRlZmluZWQpXG4gICAgICAgICAgYXR0cnMudGl0bGUgPSBtWzRdO1xuXG4gICAgICAgIHJldHVybiBbIG1bMF0ubGVuZ3RoLCBbIFwiaW1nXCIsIGF0dHJzIF0gXTtcbiAgICAgIH1cblxuICAgICAgLy8gIVtBbHQgdGV4dF1baWRdXG4gICAgICBtID0gdGV4dC5tYXRjaCggL14hXFxbKC4qPylcXF1bIFxcdF0qXFxbKC4qPylcXF0vICk7XG5cbiAgICAgIGlmICggbSApIHtcbiAgICAgICAgLy8gV2UgY2FuJ3QgY2hlY2sgaWYgdGhlIHJlZmVyZW5jZSBpcyBrbm93biBoZXJlIGFzIGl0IGxpa2VseSB3b250IGJlXG4gICAgICAgIC8vIGZvdW5kIHRpbGwgYWZ0ZXIuIENoZWNrIGl0IGluIG1kIHRyZWUtPmhtdGwgdHJlZSBjb252ZXJzaW9uXG4gICAgICAgIHJldHVybiBbIG1bMF0ubGVuZ3RoLCBbIFwiaW1nX3JlZlwiLCB7IGFsdDogbVsxXSwgcmVmOiBtWzJdLnRvTG93ZXJDYXNlKCksIG9yaWdpbmFsOiBtWzBdIH0gXSBdO1xuICAgICAgfVxuXG4gICAgICAvLyBKdXN0IGNvbnN1bWUgdGhlICchWydcbiAgICAgIHJldHVybiBbIDIsIFwiIVtcIiBdO1xuICAgIH0sXG5cbiAgICBcIltcIjogZnVuY3Rpb24gbGluayggdGV4dCApIHtcblxuICAgICAgdmFyIG9yaWcgPSBTdHJpbmcodGV4dCk7XG4gICAgICAvLyBJbmxpbmUgY29udGVudCBpcyBwb3NzaWJsZSBpbnNpZGUgYGxpbmsgdGV4dGBcbiAgICAgIHZhciByZXMgPSBNYXJrZG93bi5EaWFsZWN0SGVscGVycy5pbmxpbmVfdW50aWxfY2hhci5jYWxsKCB0aGlzLCB0ZXh0LnN1YnN0cigxKSwgXCJdXCIgKTtcblxuICAgICAgLy8gTm8gY2xvc2luZyAnXScgZm91bmQuIEp1c3QgY29uc3VtZSB0aGUgW1xuICAgICAgaWYgKCAhcmVzICkgcmV0dXJuIFsgMSwgXCJbXCIgXTtcblxuICAgICAgdmFyIGNvbnN1bWVkID0gMSArIHJlc1sgMCBdLFxuICAgICAgICAgIGNoaWxkcmVuID0gcmVzWyAxIF0sXG4gICAgICAgICAgbGluayxcbiAgICAgICAgICBhdHRycztcblxuICAgICAgLy8gQXQgdGhpcyBwb2ludCB0aGUgZmlyc3QgWy4uLl0gaGFzIGJlZW4gcGFyc2VkLiBTZWUgd2hhdCBmb2xsb3dzIHRvIGZpbmRcbiAgICAgIC8vIG91dCB3aGljaCBraW5kIG9mIGxpbmsgd2UgYXJlIChyZWZlcmVuY2Ugb3IgZGlyZWN0IHVybClcbiAgICAgIHRleHQgPSB0ZXh0LnN1YnN0ciggY29uc3VtZWQgKTtcblxuICAgICAgLy8gW2xpbmsgdGV4dF0oL3BhdGgvdG8vaW1nLmpwZyBcIk9wdGlvbmFsIHRpdGxlXCIpXG4gICAgICAvLyAgICAgICAgICAgICAgICAgMSAgICAgICAgICAgIDIgICAgICAgMyAgICAgICAgIDwtLS0gY2FwdHVyZXNcbiAgICAgIC8vIFRoaXMgd2lsbCBjYXB0dXJlIHVwIHRvIHRoZSBsYXN0IHBhcmVuIGluIHRoZSBibG9jay4gV2UgdGhlbiBwdWxsXG4gICAgICAvLyBiYWNrIGJhc2VkIG9uIGlmIHRoZXJlIGEgbWF0Y2hpbmcgb25lcyBpbiB0aGUgdXJsXG4gICAgICAvLyAgICAoW2hlcmVdKC91cmwvKHRlc3QpKVxuICAgICAgLy8gVGhlIHBhcmVucyBoYXZlIHRvIGJlIGJhbGFuY2VkXG4gICAgICB2YXIgbSA9IHRleHQubWF0Y2goIC9eXFxzKlxcKFsgXFx0XSooW15cIiddKikoPzpbIFxcdF0rKFtcIiddKSguKj8pXFwyKT9bIFxcdF0qXFwpLyApO1xuICAgICAgaWYgKCBtICkge1xuICAgICAgICB2YXIgdXJsID0gbVsxXTtcbiAgICAgICAgY29uc3VtZWQgKz0gbVswXS5sZW5ndGg7XG5cbiAgICAgICAgaWYgKCB1cmwgJiYgdXJsWzBdID09IFwiPFwiICYmIHVybFt1cmwubGVuZ3RoLTFdID09IFwiPlwiIClcbiAgICAgICAgICB1cmwgPSB1cmwuc3Vic3RyaW5nKCAxLCB1cmwubGVuZ3RoIC0gMSApO1xuXG4gICAgICAgIC8vIElmIHRoZXJlIGlzIGEgdGl0bGUgd2UgZG9uJ3QgaGF2ZSB0byB3b3JyeSBhYm91dCBwYXJlbnMgaW4gdGhlIHVybFxuICAgICAgICBpZiAoICFtWzNdICkge1xuICAgICAgICAgIHZhciBvcGVuX3BhcmVucyA9IDE7IC8vIE9uZSBvcGVuIHRoYXQgaXNuJ3QgaW4gdGhlIGNhcHR1cmVcbiAgICAgICAgICBmb3IgKCB2YXIgbGVuID0gMDsgbGVuIDwgdXJsLmxlbmd0aDsgbGVuKysgKSB7XG4gICAgICAgICAgICBzd2l0Y2ggKCB1cmxbbGVuXSApIHtcbiAgICAgICAgICAgIGNhc2UgXCIoXCI6XG4gICAgICAgICAgICAgIG9wZW5fcGFyZW5zKys7XG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBcIilcIjpcbiAgICAgICAgICAgICAgaWYgKCAtLW9wZW5fcGFyZW5zID09IDApIHtcbiAgICAgICAgICAgICAgICBjb25zdW1lZCAtPSB1cmwubGVuZ3RoIC0gbGVuO1xuICAgICAgICAgICAgICAgIHVybCA9IHVybC5zdWJzdHJpbmcoMCwgbGVuKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBQcm9jZXNzIGVzY2FwZXMgb25seVxuICAgICAgICB1cmwgPSB0aGlzLmRpYWxlY3QuaW5saW5lLl9fY2FsbF9fLmNhbGwoIHRoaXMsIHVybCwgL1xcXFwvIClbMF07XG5cbiAgICAgICAgYXR0cnMgPSB7IGhyZWY6IHVybCB8fCBcIlwiIH07XG4gICAgICAgIGlmICggbVszXSAhPT0gdW5kZWZpbmVkKVxuICAgICAgICAgIGF0dHJzLnRpdGxlID0gbVszXTtcblxuICAgICAgICBsaW5rID0gWyBcImxpbmtcIiwgYXR0cnMgXS5jb25jYXQoIGNoaWxkcmVuICk7XG4gICAgICAgIHJldHVybiBbIGNvbnN1bWVkLCBsaW5rIF07XG4gICAgICB9XG5cbiAgICAgIC8vIFtBbHQgdGV4dF1baWRdXG4gICAgICAvLyBbQWx0IHRleHRdIFtpZF1cbiAgICAgIG0gPSB0ZXh0Lm1hdGNoKCAvXlxccypcXFsoLio/KVxcXS8gKTtcblxuICAgICAgaWYgKCBtICkge1xuXG4gICAgICAgIGNvbnN1bWVkICs9IG1bIDAgXS5sZW5ndGg7XG5cbiAgICAgICAgLy8gW2xpbmtzXVtdIHVzZXMgbGlua3MgYXMgaXRzIHJlZmVyZW5jZVxuICAgICAgICBhdHRycyA9IHsgcmVmOiAoIG1bIDEgXSB8fCBTdHJpbmcoY2hpbGRyZW4pICkudG9Mb3dlckNhc2UoKSwgIG9yaWdpbmFsOiBvcmlnLnN1YnN0ciggMCwgY29uc3VtZWQgKSB9O1xuXG4gICAgICAgIGxpbmsgPSBbIFwibGlua19yZWZcIiwgYXR0cnMgXS5jb25jYXQoIGNoaWxkcmVuICk7XG5cbiAgICAgICAgLy8gV2UgY2FuJ3QgY2hlY2sgaWYgdGhlIHJlZmVyZW5jZSBpcyBrbm93biBoZXJlIGFzIGl0IGxpa2VseSB3b250IGJlXG4gICAgICAgIC8vIGZvdW5kIHRpbGwgYWZ0ZXIuIENoZWNrIGl0IGluIG1kIHRyZWUtPmhtdGwgdHJlZSBjb252ZXJzaW9uLlxuICAgICAgICAvLyBTdG9yZSB0aGUgb3JpZ2luYWwgc28gdGhhdCBjb252ZXJzaW9uIGNhbiByZXZlcnQgaWYgdGhlIHJlZiBpc24ndCBmb3VuZC5cbiAgICAgICAgcmV0dXJuIFsgY29uc3VtZWQsIGxpbmsgXTtcbiAgICAgIH1cblxuICAgICAgLy8gW2lkXVxuICAgICAgLy8gT25seSBpZiBpZCBpcyBwbGFpbiAobm8gZm9ybWF0dGluZy4pXG4gICAgICBpZiAoIGNoaWxkcmVuLmxlbmd0aCA9PSAxICYmIHR5cGVvZiBjaGlsZHJlblswXSA9PSBcInN0cmluZ1wiICkge1xuXG4gICAgICAgIGF0dHJzID0geyByZWY6IGNoaWxkcmVuWzBdLnRvTG93ZXJDYXNlKCksICBvcmlnaW5hbDogb3JpZy5zdWJzdHIoIDAsIGNvbnN1bWVkICkgfTtcbiAgICAgICAgbGluayA9IFsgXCJsaW5rX3JlZlwiLCBhdHRycywgY2hpbGRyZW5bMF0gXTtcbiAgICAgICAgcmV0dXJuIFsgY29uc3VtZWQsIGxpbmsgXTtcbiAgICAgIH1cblxuICAgICAgLy8gSnVzdCBjb25zdW1lIHRoZSBcIltcIlxuICAgICAgcmV0dXJuIFsgMSwgXCJbXCIgXTtcbiAgICB9LFxuXG5cbiAgICBcIjxcIjogZnVuY3Rpb24gYXV0b0xpbmsoIHRleHQgKSB7XG4gICAgICB2YXIgbTtcblxuICAgICAgaWYgKCAoIG0gPSB0ZXh0Lm1hdGNoKCAvXjwoPzooKGh0dHBzP3xmdHB8bWFpbHRvKTpbXj5dKyl8KC4qP0AuKj9cXC5bYS16QS1aXSspKT4vICkgKSAhPSBudWxsICkge1xuICAgICAgICBpZiAoIG1bM10gKSB7XG4gICAgICAgICAgcmV0dXJuIFsgbVswXS5sZW5ndGgsIFsgXCJsaW5rXCIsIHsgaHJlZjogXCJtYWlsdG86XCIgKyBtWzNdIH0sIG1bM10gXSBdO1xuXG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoIG1bMl0gPT0gXCJtYWlsdG9cIiApIHtcbiAgICAgICAgICByZXR1cm4gWyBtWzBdLmxlbmd0aCwgWyBcImxpbmtcIiwgeyBocmVmOiBtWzFdIH0sIG1bMV0uc3Vic3RyKFwibWFpbHRvOlwiLmxlbmd0aCApIF0gXTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlXG4gICAgICAgICAgcmV0dXJuIFsgbVswXS5sZW5ndGgsIFsgXCJsaW5rXCIsIHsgaHJlZjogbVsxXSB9LCBtWzFdIF0gXTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIFsgMSwgXCI8XCIgXTtcbiAgICB9LFxuXG4gICAgXCJgXCI6IGZ1bmN0aW9uIGlubGluZUNvZGUoIHRleHQgKSB7XG4gICAgICAvLyBJbmxpbmUgY29kZSBibG9jay4gYXMgbWFueSBiYWNrdGlja3MgYXMgeW91IGxpa2UgdG8gc3RhcnQgaXRcbiAgICAgIC8vIEFsd2F5cyBza2lwIG92ZXIgdGhlIG9wZW5pbmcgdGlja3MuXG4gICAgICB2YXIgbSA9IHRleHQubWF0Y2goIC8oYCspKChbXFxzXFxTXSo/KVxcMSkvICk7XG5cbiAgICAgIGlmICggbSAmJiBtWzJdIClcbiAgICAgICAgcmV0dXJuIFsgbVsxXS5sZW5ndGggKyBtWzJdLmxlbmd0aCwgWyBcImlubGluZWNvZGVcIiwgbVszXSBdIF07XG4gICAgICBlbHNlIHtcbiAgICAgICAgLy8gVE9ETzogTm8gbWF0Y2hpbmcgZW5kIGNvZGUgZm91bmQgLSB3YXJuIVxuICAgICAgICByZXR1cm4gWyAxLCBcImBcIiBdO1xuICAgICAgfVxuICAgIH0sXG5cbiAgICBcIiAgXFxuXCI6IGZ1bmN0aW9uIGxpbmVCcmVhayggdGV4dCApIHtcbiAgICAgIHJldHVybiBbIDMsIFsgXCJsaW5lYnJlYWtcIiBdIF07XG4gICAgfVxuXG59O1xuXG4vLyBNZXRhIEhlbHBlci9nZW5lcmF0b3IgbWV0aG9kIGZvciBlbSBhbmQgc3Ryb25nIGhhbmRsaW5nXG5mdW5jdGlvbiBzdHJvbmdfZW0oIHRhZywgbWQgKSB7XG5cbiAgdmFyIHN0YXRlX3Nsb3QgPSB0YWcgKyBcIl9zdGF0ZVwiLFxuICAgICAgb3RoZXJfc2xvdCA9IHRhZyA9PSBcInN0cm9uZ1wiID8gXCJlbV9zdGF0ZVwiIDogXCJzdHJvbmdfc3RhdGVcIjtcblxuICBmdW5jdGlvbiBDbG9zZVRhZyhsZW4pIHtcbiAgICB0aGlzLmxlbl9hZnRlciA9IGxlbjtcbiAgICB0aGlzLm5hbWUgPSBcImNsb3NlX1wiICsgbWQ7XG4gIH1cblxuICByZXR1cm4gZnVuY3Rpb24gKCB0ZXh0LCBvcmlnX21hdGNoICkge1xuXG4gICAgaWYgKCB0aGlzW3N0YXRlX3Nsb3RdWzBdID09IG1kICkge1xuICAgICAgLy8gTW9zdCByZWNlbnQgZW0gaXMgb2YgdGhpcyB0eXBlXG4gICAgICAvL0Q6dGhpcy5kZWJ1ZyhcImNsb3NpbmdcIiwgbWQpO1xuICAgICAgdGhpc1tzdGF0ZV9zbG90XS5zaGlmdCgpO1xuXG4gICAgICAvLyBcIkNvbnN1bWVcIiBldmVyeXRoaW5nIHRvIGdvIGJhY2sgdG8gdGhlIHJlY3J1c2lvbiBpbiB0aGUgZWxzZS1ibG9jayBiZWxvd1xuICAgICAgcmV0dXJuWyB0ZXh0Lmxlbmd0aCwgbmV3IENsb3NlVGFnKHRleHQubGVuZ3RoLW1kLmxlbmd0aCkgXTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAvLyBTdG9yZSBhIGNsb25lIG9mIHRoZSBlbS9zdHJvbmcgc3RhdGVzXG4gICAgICB2YXIgb3RoZXIgPSB0aGlzW290aGVyX3Nsb3RdLnNsaWNlKCksXG4gICAgICAgICAgc3RhdGUgPSB0aGlzW3N0YXRlX3Nsb3RdLnNsaWNlKCk7XG5cbiAgICAgIHRoaXNbc3RhdGVfc2xvdF0udW5zaGlmdChtZCk7XG5cbiAgICAgIC8vRDp0aGlzLmRlYnVnX2luZGVudCArPSBcIiAgXCI7XG5cbiAgICAgIC8vIFJlY3Vyc2VcbiAgICAgIHZhciByZXMgPSB0aGlzLnByb2Nlc3NJbmxpbmUoIHRleHQuc3Vic3RyKCBtZC5sZW5ndGggKSApO1xuICAgICAgLy9EOnRoaXMuZGVidWdfaW5kZW50ID0gdGhpcy5kZWJ1Z19pbmRlbnQuc3Vic3RyKDIpO1xuXG4gICAgICB2YXIgbGFzdCA9IHJlc1tyZXMubGVuZ3RoIC0gMV07XG5cbiAgICAgIC8vRDp0aGlzLmRlYnVnKFwicHJvY2Vzc0lubGluZSBmcm9tXCIsIHRhZyArIFwiOiBcIiwgdW5ldmFsKCByZXMgKSApO1xuXG4gICAgICB2YXIgY2hlY2sgPSB0aGlzW3N0YXRlX3Nsb3RdLnNoaWZ0KCk7XG4gICAgICBpZiAoIGxhc3QgaW5zdGFuY2VvZiBDbG9zZVRhZyApIHtcbiAgICAgICAgcmVzLnBvcCgpO1xuICAgICAgICAvLyBXZSBtYXRjaGVkISBIdXp6YWguXG4gICAgICAgIHZhciBjb25zdW1lZCA9IHRleHQubGVuZ3RoIC0gbGFzdC5sZW5fYWZ0ZXI7XG4gICAgICAgIHJldHVybiBbIGNvbnN1bWVkLCBbIHRhZyBdLmNvbmNhdChyZXMpIF07XG4gICAgICB9XG4gICAgICBlbHNlIHtcbiAgICAgICAgLy8gUmVzdG9yZSB0aGUgc3RhdGUgb2YgdGhlIG90aGVyIGtpbmQuIFdlIG1pZ2h0IGhhdmUgbWlzdGFrZW5seSBjbG9zZWQgaXQuXG4gICAgICAgIHRoaXNbb3RoZXJfc2xvdF0gPSBvdGhlcjtcbiAgICAgICAgdGhpc1tzdGF0ZV9zbG90XSA9IHN0YXRlO1xuXG4gICAgICAgIC8vIFdlIGNhbid0IHJldXNlIHRoZSBwcm9jZXNzZWQgcmVzdWx0IGFzIGl0IGNvdWxkIGhhdmUgd3JvbmcgcGFyc2luZyBjb250ZXh0cyBpbiBpdC5cbiAgICAgICAgcmV0dXJuIFsgbWQubGVuZ3RoLCBtZCBdO1xuICAgICAgfVxuICAgIH1cbiAgfTsgLy8gRW5kIHJldHVybmVkIGZ1bmN0aW9uXG59XG5cbk1hcmtkb3duLmRpYWxlY3RzLkdydWJlci5pbmxpbmVbXCIqKlwiXSA9IHN0cm9uZ19lbShcInN0cm9uZ1wiLCBcIioqXCIpO1xuTWFya2Rvd24uZGlhbGVjdHMuR3J1YmVyLmlubGluZVtcIl9fXCJdID0gc3Ryb25nX2VtKFwic3Ryb25nXCIsIFwiX19cIik7XG5NYXJrZG93bi5kaWFsZWN0cy5HcnViZXIuaW5saW5lW1wiKlwiXSAgPSBzdHJvbmdfZW0oXCJlbVwiLCBcIipcIik7XG5NYXJrZG93bi5kaWFsZWN0cy5HcnViZXIuaW5saW5lW1wiX1wiXSAgPSBzdHJvbmdfZW0oXCJlbVwiLCBcIl9cIik7XG5cblxuLy8gQnVpbGQgZGVmYXVsdCBvcmRlciBmcm9tIGluc2VydGlvbiBvcmRlci5cbk1hcmtkb3duLmJ1aWxkQmxvY2tPcmRlciA9IGZ1bmN0aW9uKGQpIHtcbiAgdmFyIG9yZCA9IFtdO1xuICBmb3IgKCB2YXIgaSBpbiBkICkge1xuICAgIGlmICggaSA9PSBcIl9fb3JkZXJfX1wiIHx8IGkgPT0gXCJfX2NhbGxfX1wiICkgY29udGludWU7XG4gICAgb3JkLnB1c2goIGkgKTtcbiAgfVxuICBkLl9fb3JkZXJfXyA9IG9yZDtcbn07XG5cbi8vIEJ1aWxkIHBhdHRlcm5zIGZvciBpbmxpbmUgbWF0Y2hlclxuTWFya2Rvd24uYnVpbGRJbmxpbmVQYXR0ZXJucyA9IGZ1bmN0aW9uKGQpIHtcbiAgdmFyIHBhdHRlcm5zID0gW107XG5cbiAgZm9yICggdmFyIGkgaW4gZCApIHtcbiAgICAvLyBfX2Zvb19fIGlzIHJlc2VydmVkIGFuZCBub3QgYSBwYXR0ZXJuXG4gICAgaWYgKCBpLm1hdGNoKCAvXl9fLipfXyQvKSApIGNvbnRpbnVlO1xuICAgIHZhciBsID0gaS5yZXBsYWNlKCAvKFtcXFxcLiorP3woKVxcW1xcXXt9XSkvZywgXCJcXFxcJDFcIiApXG4gICAgICAgICAgICAgLnJlcGxhY2UoIC9cXG4vLCBcIlxcXFxuXCIgKTtcbiAgICBwYXR0ZXJucy5wdXNoKCBpLmxlbmd0aCA9PSAxID8gbCA6IFwiKD86XCIgKyBsICsgXCIpXCIgKTtcbiAgfVxuXG4gIHBhdHRlcm5zID0gcGF0dGVybnMuam9pbihcInxcIik7XG4gIGQuX19wYXR0ZXJuc19fID0gcGF0dGVybnM7XG4gIC8vcHJpbnQoXCJwYXR0ZXJuczpcIiwgdW5ldmFsKCBwYXR0ZXJucyApICk7XG5cbiAgdmFyIGZuID0gZC5fX2NhbGxfXztcbiAgZC5fX2NhbGxfXyA9IGZ1bmN0aW9uKHRleHQsIHBhdHRlcm4pIHtcbiAgICBpZiAoIHBhdHRlcm4gIT0gdW5kZWZpbmVkICkge1xuICAgICAgcmV0dXJuIGZuLmNhbGwodGhpcywgdGV4dCwgcGF0dGVybik7XG4gICAgfVxuICAgIGVsc2VcbiAgICB7XG4gICAgICByZXR1cm4gZm4uY2FsbCh0aGlzLCB0ZXh0LCBwYXR0ZXJucyk7XG4gICAgfVxuICB9O1xufTtcblxuTWFya2Rvd24uRGlhbGVjdEhlbHBlcnMgPSB7fTtcbk1hcmtkb3duLkRpYWxlY3RIZWxwZXJzLmlubGluZV91bnRpbF9jaGFyID0gZnVuY3Rpb24oIHRleHQsIHdhbnQgKSB7XG4gIHZhciBjb25zdW1lZCA9IDAsXG4gICAgICBub2RlcyA9IFtdO1xuXG4gIHdoaWxlICggdHJ1ZSApIHtcbiAgICBpZiAoIHRleHQuY2hhckF0KCBjb25zdW1lZCApID09IHdhbnQgKSB7XG4gICAgICAvLyBGb3VuZCB0aGUgY2hhcmFjdGVyIHdlIHdlcmUgbG9va2luZyBmb3JcbiAgICAgIGNvbnN1bWVkKys7XG4gICAgICByZXR1cm4gWyBjb25zdW1lZCwgbm9kZXMgXTtcbiAgICB9XG5cbiAgICBpZiAoIGNvbnN1bWVkID49IHRleHQubGVuZ3RoICkge1xuICAgICAgLy8gTm8gY2xvc2luZyBjaGFyIGZvdW5kLiBBYm9ydC5cbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHZhciByZXMgPSB0aGlzLmRpYWxlY3QuaW5saW5lLl9fb25lRWxlbWVudF9fLmNhbGwodGhpcywgdGV4dC5zdWJzdHIoIGNvbnN1bWVkICkgKTtcbiAgICBjb25zdW1lZCArPSByZXNbIDAgXTtcbiAgICAvLyBBZGQgYW55IHJldHVybmVkIG5vZGVzLlxuICAgIG5vZGVzLnB1c2guYXBwbHkoIG5vZGVzLCByZXMuc2xpY2UoIDEgKSApO1xuICB9XG59XG5cbi8vIEhlbHBlciBmdW5jdGlvbiB0byBtYWtlIHN1Yi1jbGFzc2luZyBhIGRpYWxlY3QgZWFzaWVyXG5NYXJrZG93bi5zdWJjbGFzc0RpYWxlY3QgPSBmdW5jdGlvbiggZCApIHtcbiAgZnVuY3Rpb24gQmxvY2soKSB7fVxuICBCbG9jay5wcm90b3R5cGUgPSBkLmJsb2NrO1xuICBmdW5jdGlvbiBJbmxpbmUoKSB7fVxuICBJbmxpbmUucHJvdG90eXBlID0gZC5pbmxpbmU7XG5cbiAgcmV0dXJuIHsgYmxvY2s6IG5ldyBCbG9jaygpLCBpbmxpbmU6IG5ldyBJbmxpbmUoKSB9O1xufTtcblxuTWFya2Rvd24uYnVpbGRCbG9ja09yZGVyICggTWFya2Rvd24uZGlhbGVjdHMuR3J1YmVyLmJsb2NrICk7XG5NYXJrZG93bi5idWlsZElubGluZVBhdHRlcm5zKCBNYXJrZG93bi5kaWFsZWN0cy5HcnViZXIuaW5saW5lICk7XG5cbk1hcmtkb3duLmRpYWxlY3RzLk1hcnVrdSA9IE1hcmtkb3duLnN1YmNsYXNzRGlhbGVjdCggTWFya2Rvd24uZGlhbGVjdHMuR3J1YmVyICk7XG5cbk1hcmtkb3duLmRpYWxlY3RzLk1hcnVrdS5wcm9jZXNzTWV0YUhhc2ggPSBmdW5jdGlvbiBwcm9jZXNzTWV0YUhhc2goIG1ldGFfc3RyaW5nICkge1xuICB2YXIgbWV0YSA9IHNwbGl0X21ldGFfaGFzaCggbWV0YV9zdHJpbmcgKSxcbiAgICAgIGF0dHIgPSB7fTtcblxuICBmb3IgKCB2YXIgaSA9IDA7IGkgPCBtZXRhLmxlbmd0aDsgKytpICkge1xuICAgIC8vIGlkOiAjZm9vXG4gICAgaWYgKCAvXiMvLnRlc3QoIG1ldGFbIGkgXSApICkge1xuICAgICAgYXR0ci5pZCA9IG1ldGFbIGkgXS5zdWJzdHJpbmcoIDEgKTtcbiAgICB9XG4gICAgLy8gY2xhc3M6IC5mb29cbiAgICBlbHNlIGlmICggL15cXC4vLnRlc3QoIG1ldGFbIGkgXSApICkge1xuICAgICAgLy8gaWYgY2xhc3MgYWxyZWFkeSBleGlzdHMsIGFwcGVuZCB0aGUgbmV3IG9uZVxuICAgICAgaWYgKCBhdHRyW1wiY2xhc3NcIl0gKSB7XG4gICAgICAgIGF0dHJbXCJjbGFzc1wiXSA9IGF0dHJbXCJjbGFzc1wiXSArIG1ldGFbIGkgXS5yZXBsYWNlKCAvLi8sIFwiIFwiICk7XG4gICAgICB9XG4gICAgICBlbHNlIHtcbiAgICAgICAgYXR0cltcImNsYXNzXCJdID0gbWV0YVsgaSBdLnN1YnN0cmluZyggMSApO1xuICAgICAgfVxuICAgIH1cbiAgICAvLyBhdHRyaWJ1dGU6IGZvbz1iYXJcbiAgICBlbHNlIGlmICggL1xcPS8udGVzdCggbWV0YVsgaSBdICkgKSB7XG4gICAgICB2YXIgcyA9IG1ldGFbIGkgXS5zcGxpdCggL1xcPS8gKTtcbiAgICAgIGF0dHJbIHNbIDAgXSBdID0gc1sgMSBdO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBhdHRyO1xufVxuXG5mdW5jdGlvbiBzcGxpdF9tZXRhX2hhc2goIG1ldGFfc3RyaW5nICkge1xuICB2YXIgbWV0YSA9IG1ldGFfc3RyaW5nLnNwbGl0KCBcIlwiICksXG4gICAgICBwYXJ0cyA9IFsgXCJcIiBdLFxuICAgICAgaW5fcXVvdGVzID0gZmFsc2U7XG5cbiAgd2hpbGUgKCBtZXRhLmxlbmd0aCApIHtcbiAgICB2YXIgbGV0dGVyID0gbWV0YS5zaGlmdCgpO1xuICAgIHN3aXRjaCAoIGxldHRlciApIHtcbiAgICAgIGNhc2UgXCIgXCIgOlxuICAgICAgICAvLyBpZiB3ZSdyZSBpbiBhIHF1b3RlZCBzZWN0aW9uLCBrZWVwIGl0XG4gICAgICAgIGlmICggaW5fcXVvdGVzICkge1xuICAgICAgICAgIHBhcnRzWyBwYXJ0cy5sZW5ndGggLSAxIF0gKz0gbGV0dGVyO1xuICAgICAgICB9XG4gICAgICAgIC8vIG90aGVyd2lzZSBtYWtlIGEgbmV3IHBhcnRcbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgcGFydHMucHVzaCggXCJcIiApO1xuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBcIidcIiA6XG4gICAgICBjYXNlICdcIicgOlxuICAgICAgICAvLyByZXZlcnNlIHRoZSBxdW90ZXMgYW5kIG1vdmUgc3RyYWlnaHQgb25cbiAgICAgICAgaW5fcXVvdGVzID0gIWluX3F1b3RlcztcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIFwiXFxcXFwiIDpcbiAgICAgICAgLy8gc2hpZnQgb2ZmIHRoZSBuZXh0IGxldHRlciB0byBiZSB1c2VkIHN0cmFpZ2h0IGF3YXkuXG4gICAgICAgIC8vIGl0IHdhcyBlc2NhcGVkIHNvIHdlJ2xsIGtlZXAgaXQgd2hhdGV2ZXIgaXQgaXNcbiAgICAgICAgbGV0dGVyID0gbWV0YS5zaGlmdCgpO1xuICAgICAgZGVmYXVsdCA6XG4gICAgICAgIHBhcnRzWyBwYXJ0cy5sZW5ndGggLSAxIF0gKz0gbGV0dGVyO1xuICAgICAgICBicmVhaztcbiAgICB9XG4gIH1cblxuICByZXR1cm4gcGFydHM7XG59XG5cbk1hcmtkb3duLmRpYWxlY3RzLk1hcnVrdS5ibG9jay5kb2N1bWVudF9tZXRhID0gZnVuY3Rpb24gZG9jdW1lbnRfbWV0YSggYmxvY2ssIG5leHQgKSB7XG4gIC8vIHdlJ3JlIG9ubHkgaW50ZXJlc3RlZCBpbiB0aGUgZmlyc3QgYmxvY2tcbiAgaWYgKCBibG9jay5saW5lTnVtYmVyID4gMSApIHJldHVybiB1bmRlZmluZWQ7XG5cbiAgLy8gZG9jdW1lbnRfbWV0YSBibG9ja3MgY29uc2lzdCBvZiBvbmUgb3IgbW9yZSBsaW5lcyBvZiBgS2V5OiBWYWx1ZVxcbmBcbiAgaWYgKCAhIGJsb2NrLm1hdGNoKCAvXig/Olxcdys6LipcXG4pKlxcdys6LiokLyApICkgcmV0dXJuIHVuZGVmaW5lZDtcblxuICAvLyBtYWtlIGFuIGF0dHJpYnV0ZSBub2RlIGlmIGl0IGRvZXNuJ3QgZXhpc3RcbiAgaWYgKCAhZXh0cmFjdF9hdHRyKCB0aGlzLnRyZWUgKSApIHtcbiAgICB0aGlzLnRyZWUuc3BsaWNlKCAxLCAwLCB7fSApO1xuICB9XG5cbiAgdmFyIHBhaXJzID0gYmxvY2suc3BsaXQoIC9cXG4vICk7XG4gIGZvciAoIHAgaW4gcGFpcnMgKSB7XG4gICAgdmFyIG0gPSBwYWlyc1sgcCBdLm1hdGNoKCAvKFxcdyspOlxccyooLiopJC8gKSxcbiAgICAgICAga2V5ID0gbVsgMSBdLnRvTG93ZXJDYXNlKCksXG4gICAgICAgIHZhbHVlID0gbVsgMiBdO1xuXG4gICAgdGhpcy50cmVlWyAxIF1bIGtleSBdID0gdmFsdWU7XG4gIH1cblxuICAvLyBkb2N1bWVudF9tZXRhIHByb2R1Y2VzIG5vIGNvbnRlbnQhXG4gIHJldHVybiBbXTtcbn07XG5cbk1hcmtkb3duLmRpYWxlY3RzLk1hcnVrdS5ibG9jay5ibG9ja19tZXRhID0gZnVuY3Rpb24gYmxvY2tfbWV0YSggYmxvY2ssIG5leHQgKSB7XG4gIC8vIGNoZWNrIGlmIHRoZSBsYXN0IGxpbmUgb2YgdGhlIGJsb2NrIGlzIGFuIG1ldGEgaGFzaFxuICB2YXIgbSA9IGJsb2NrLm1hdGNoKCAvKF58XFxuKSB7MCwzfVxcezpcXHMqKCg/OlxcXFxcXH18W15cXH1dKSopXFxzKlxcfSQvICk7XG4gIGlmICggIW0gKSByZXR1cm4gdW5kZWZpbmVkO1xuXG4gIC8vIHByb2Nlc3MgdGhlIG1ldGEgaGFzaFxuICB2YXIgYXR0ciA9IHRoaXMuZGlhbGVjdC5wcm9jZXNzTWV0YUhhc2goIG1bIDIgXSApO1xuXG4gIHZhciBoYXNoO1xuXG4gIC8vIGlmIHdlIG1hdGNoZWQgXiB0aGVuIHdlIG5lZWQgdG8gYXBwbHkgbWV0YSB0byB0aGUgcHJldmlvdXMgYmxvY2tcbiAgaWYgKCBtWyAxIF0gPT09IFwiXCIgKSB7XG4gICAgdmFyIG5vZGUgPSB0aGlzLnRyZWVbIHRoaXMudHJlZS5sZW5ndGggLSAxIF07XG4gICAgaGFzaCA9IGV4dHJhY3RfYXR0ciggbm9kZSApO1xuXG4gICAgLy8gaWYgdGhlIG5vZGUgaXMgYSBzdHJpbmcgKHJhdGhlciB0aGFuIEpzb25NTCksIGJhaWxcbiAgICBpZiAoIHR5cGVvZiBub2RlID09PSBcInN0cmluZ1wiICkgcmV0dXJuIHVuZGVmaW5lZDtcblxuICAgIC8vIGNyZWF0ZSB0aGUgYXR0cmlidXRlIGhhc2ggaWYgaXQgZG9lc24ndCBleGlzdFxuICAgIGlmICggIWhhc2ggKSB7XG4gICAgICBoYXNoID0ge307XG4gICAgICBub2RlLnNwbGljZSggMSwgMCwgaGFzaCApO1xuICAgIH1cblxuICAgIC8vIGFkZCB0aGUgYXR0cmlidXRlcyBpblxuICAgIGZvciAoIGEgaW4gYXR0ciApIHtcbiAgICAgIGhhc2hbIGEgXSA9IGF0dHJbIGEgXTtcbiAgICB9XG5cbiAgICAvLyByZXR1cm4gbm90aGluZyBzbyB0aGUgbWV0YSBoYXNoIGlzIHJlbW92ZWRcbiAgICByZXR1cm4gW107XG4gIH1cblxuICAvLyBwdWxsIHRoZSBtZXRhIGhhc2ggb2ZmIHRoZSBibG9jayBhbmQgcHJvY2VzcyB3aGF0J3MgbGVmdFxuICB2YXIgYiA9IGJsb2NrLnJlcGxhY2UoIC9cXG4uKiQvLCBcIlwiICksXG4gICAgICByZXN1bHQgPSB0aGlzLnByb2Nlc3NCbG9jayggYiwgW10gKTtcblxuICAvLyBnZXQgb3IgbWFrZSB0aGUgYXR0cmlidXRlcyBoYXNoXG4gIGhhc2ggPSBleHRyYWN0X2F0dHIoIHJlc3VsdFsgMCBdICk7XG4gIGlmICggIWhhc2ggKSB7XG4gICAgaGFzaCA9IHt9O1xuICAgIHJlc3VsdFsgMCBdLnNwbGljZSggMSwgMCwgaGFzaCApO1xuICB9XG5cbiAgLy8gYXR0YWNoIHRoZSBhdHRyaWJ1dGVzIHRvIHRoZSBibG9ja1xuICBmb3IgKCBhIGluIGF0dHIgKSB7XG4gICAgaGFzaFsgYSBdID0gYXR0clsgYSBdO1xuICB9XG5cbiAgcmV0dXJuIHJlc3VsdDtcbn07XG5cbk1hcmtkb3duLmRpYWxlY3RzLk1hcnVrdS5ibG9jay5kZWZpbml0aW9uX2xpc3QgPSBmdW5jdGlvbiBkZWZpbml0aW9uX2xpc3QoIGJsb2NrLCBuZXh0ICkge1xuICAvLyBvbmUgb3IgbW9yZSB0ZXJtcyBmb2xsb3dlZCBieSBvbmUgb3IgbW9yZSBkZWZpbml0aW9ucywgaW4gYSBzaW5nbGUgYmxvY2tcbiAgdmFyIHRpZ2h0ID0gL14oKD86W15cXHM6XS4qXFxuKSspOlxccysoW1xcc1xcU10rKSQvLFxuICAgICAgbGlzdCA9IFsgXCJkbFwiIF0sXG4gICAgICBpLCBtO1xuXG4gIC8vIHNlZSBpZiB3ZSdyZSBkZWFsaW5nIHdpdGggYSB0aWdodCBvciBsb29zZSBibG9ja1xuICBpZiAoICggbSA9IGJsb2NrLm1hdGNoKCB0aWdodCApICkgKSB7XG4gICAgLy8gcHVsbCBzdWJzZXF1ZW50IHRpZ2h0IERMIGJsb2NrcyBvdXQgb2YgYG5leHRgXG4gICAgdmFyIGJsb2NrcyA9IFsgYmxvY2sgXTtcbiAgICB3aGlsZSAoIG5leHQubGVuZ3RoICYmIHRpZ2h0LmV4ZWMoIG5leHRbIDAgXSApICkge1xuICAgICAgYmxvY2tzLnB1c2goIG5leHQuc2hpZnQoKSApO1xuICAgIH1cblxuICAgIGZvciAoIHZhciBiID0gMDsgYiA8IGJsb2Nrcy5sZW5ndGg7ICsrYiApIHtcbiAgICAgIHZhciBtID0gYmxvY2tzWyBiIF0ubWF0Y2goIHRpZ2h0ICksXG4gICAgICAgICAgdGVybXMgPSBtWyAxIF0ucmVwbGFjZSggL1xcbiQvLCBcIlwiICkuc3BsaXQoIC9cXG4vICksXG4gICAgICAgICAgZGVmbnMgPSBtWyAyIF0uc3BsaXQoIC9cXG46XFxzKy8gKTtcblxuICAgICAgLy8gcHJpbnQoIHVuZXZhbCggbSApICk7XG5cbiAgICAgIGZvciAoIGkgPSAwOyBpIDwgdGVybXMubGVuZ3RoOyArK2kgKSB7XG4gICAgICAgIGxpc3QucHVzaCggWyBcImR0XCIsIHRlcm1zWyBpIF0gXSApO1xuICAgICAgfVxuXG4gICAgICBmb3IgKCBpID0gMDsgaSA8IGRlZm5zLmxlbmd0aDsgKytpICkge1xuICAgICAgICAvLyBydW4gaW5saW5lIHByb2Nlc3Npbmcgb3ZlciB0aGUgZGVmaW5pdGlvblxuICAgICAgICBsaXN0LnB1c2goIFsgXCJkZFwiIF0uY29uY2F0KCB0aGlzLnByb2Nlc3NJbmxpbmUoIGRlZm5zWyBpIF0ucmVwbGFjZSggLyhcXG4pXFxzKy8sIFwiJDFcIiApICkgKSApO1xuICAgICAgfVxuICAgIH1cbiAgfVxuICBlbHNlIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG5cbiAgcmV0dXJuIFsgbGlzdCBdO1xufTtcblxuLy8gc3BsaXRzIG9uIHVuZXNjYXBlZCBpbnN0YW5jZXMgb2YgQGNoLiBJZiBAY2ggaXMgbm90IGEgY2hhcmFjdGVyIHRoZSByZXN1bHRcbi8vIGNhbiBiZSB1bnByZWRpY3RhYmxlXG5cbk1hcmtkb3duLmRpYWxlY3RzLk1hcnVrdS5ibG9jay50YWJsZSA9IGZ1bmN0aW9uIHRhYmxlIChibG9jaywgbmV4dCkge1xuXG4gICAgdmFyIF9zcGxpdF9vbl91bmVzY2FwZWQgPSBmdW5jdGlvbihzLCBjaCkge1xuICAgICAgICBjaCA9IGNoIHx8ICdcXFxccyc7XG4gICAgICAgIGlmIChjaC5tYXRjaCgvXltcXFxcfFxcW1xcXXt9PyouK14kXSQvKSkgeyBjaCA9ICdcXFxcJyArIGNoOyB9XG4gICAgICAgIHZhciByZXMgPSBbIF0sXG4gICAgICAgICAgICByID0gbmV3IFJlZ0V4cCgnXigoPzpcXFxcXFxcXC58W15cXFxcXFxcXCcgKyBjaCArICddKSopJyArIGNoICsgJyguKiknKSxcbiAgICAgICAgICAgIG07XG4gICAgICAgIHdoaWxlKG0gPSBzLm1hdGNoKHIpKSB7XG4gICAgICAgICAgICByZXMucHVzaChtWzFdKTtcbiAgICAgICAgICAgIHMgPSBtWzJdO1xuICAgICAgICB9XG4gICAgICAgIHJlcy5wdXNoKHMpO1xuICAgICAgICByZXR1cm4gcmVzO1xuICAgIH1cblxuICAgIHZhciBsZWFkaW5nX3BpcGUgPSAvXiB7MCwzfVxcfCguKylcXG4gezAsM31cXHxcXHMqKFtcXC06XStbXFwtfCA6XSopXFxuKCg/OlxccypcXHwuKig/OlxcbnwkKSkqKSg/PVxcbnwkKS8sXG4gICAgICAgIC8vIGZpbmQgYXQgbGVhc3QgYW4gdW5lc2NhcGVkIHBpcGUgaW4gZWFjaCBsaW5lXG4gICAgICAgIG5vX2xlYWRpbmdfcGlwZSA9IC9eIHswLDN9KFxcUyg/OlxcXFwufFteXFxcXHxdKSpcXHwuKilcXG4gezAsM30oW1xcLTpdK1xccypcXHxbXFwtfCA6XSopXFxuKCg/Oig/OlxcXFwufFteXFxcXHxdKSpcXHwuKig/OlxcbnwkKSkqKSg/PVxcbnwkKS8sXG4gICAgICAgIGksIG07XG4gICAgaWYgKG0gPSBibG9jay5tYXRjaChsZWFkaW5nX3BpcGUpKSB7XG4gICAgICAgIC8vIHJlbW92ZSBsZWFkaW5nIHBpcGVzIGluIGNvbnRlbnRzXG4gICAgICAgIC8vIChoZWFkZXIgYW5kIGhvcml6b250YWwgcnVsZSBhbHJlYWR5IGhhdmUgdGhlIGxlYWRpbmcgcGlwZSBsZWZ0IG91dClcbiAgICAgICAgbVszXSA9IG1bM10ucmVwbGFjZSgvXlxccypcXHwvZ20sICcnKTtcbiAgICB9IGVsc2UgaWYgKCEgKCBtID0gYmxvY2subWF0Y2gobm9fbGVhZGluZ19waXBlKSkpIHtcbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICB2YXIgdGFibGUgPSBbIFwidGFibGVcIiwgWyBcInRoZWFkXCIsIFsgXCJ0clwiIF0gXSwgWyBcInRib2R5XCIgXSBdO1xuXG4gICAgLy8gcmVtb3ZlIHRyYWlsaW5nIHBpcGVzLCB0aGVuIHNwbGl0IG9uIHBpcGVzXG4gICAgLy8gKG5vIGVzY2FwZWQgcGlwZXMgYXJlIGFsbG93ZWQgaW4gaG9yaXpvbnRhbCBydWxlKVxuICAgIG1bMl0gPSBtWzJdLnJlcGxhY2UoL1xcfFxccyokLywgJycpLnNwbGl0KCd8Jyk7XG5cbiAgICAvLyBwcm9jZXNzIGFsaWdubWVudFxuICAgIHZhciBodG1sX2F0dHJzID0gWyBdO1xuICAgIGZvckVhY2ggKG1bMl0sIGZ1bmN0aW9uIChzKSB7XG4gICAgICAgIGlmIChzLm1hdGNoKC9eXFxzKi0rOlxccyokLykpICAgICAgIGh0bWxfYXR0cnMucHVzaCh7YWxpZ246IFwicmlnaHRcIn0pO1xuICAgICAgICBlbHNlIGlmIChzLm1hdGNoKC9eXFxzKjotK1xccyokLykpICBodG1sX2F0dHJzLnB1c2goe2FsaWduOiBcImxlZnRcIn0pO1xuICAgICAgICBlbHNlIGlmIChzLm1hdGNoKC9eXFxzKjotKzpcXHMqJC8pKSBodG1sX2F0dHJzLnB1c2goe2FsaWduOiBcImNlbnRlclwifSk7XG4gICAgICAgIGVsc2UgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBodG1sX2F0dHJzLnB1c2goe30pO1xuICAgIH0pO1xuXG4gICAgLy8gbm93IGZvciB0aGUgaGVhZGVyLCBhdm9pZCBlc2NhcGVkIHBpcGVzXG4gICAgbVsxXSA9IF9zcGxpdF9vbl91bmVzY2FwZWQobVsxXS5yZXBsYWNlKC9cXHxcXHMqJC8sICcnKSwgJ3wnKTtcbiAgICBmb3IgKGkgPSAwOyBpIDwgbVsxXS5sZW5ndGg7IGkrKykge1xuICAgICAgICB0YWJsZVsxXVsxXS5wdXNoKFsndGgnLCBodG1sX2F0dHJzW2ldIHx8IHt9XS5jb25jYXQoXG4gICAgICAgICAgICB0aGlzLnByb2Nlc3NJbmxpbmUobVsxXVtpXS50cmltKCkpKSk7XG4gICAgfVxuXG4gICAgLy8gbm93IGZvciBib2R5IGNvbnRlbnRzXG4gICAgZm9yRWFjaCAobVszXS5yZXBsYWNlKC9cXHxcXHMqJC9tZywgJycpLnNwbGl0KCdcXG4nKSwgZnVuY3Rpb24gKHJvdykge1xuICAgICAgICB2YXIgaHRtbF9yb3cgPSBbJ3RyJ107XG4gICAgICAgIHJvdyA9IF9zcGxpdF9vbl91bmVzY2FwZWQocm93LCAnfCcpO1xuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgcm93Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBodG1sX3Jvdy5wdXNoKFsndGQnLCBodG1sX2F0dHJzW2ldIHx8IHt9XS5jb25jYXQodGhpcy5wcm9jZXNzSW5saW5lKHJvd1tpXS50cmltKCkpKSk7XG4gICAgICAgIH1cbiAgICAgICAgdGFibGVbMl0ucHVzaChodG1sX3Jvdyk7XG4gICAgfSwgdGhpcyk7XG5cbiAgICByZXR1cm4gW3RhYmxlXTtcbn1cblxuTWFya2Rvd24uZGlhbGVjdHMuTWFydWt1LmlubGluZVsgXCJ7OlwiIF0gPSBmdW5jdGlvbiBpbmxpbmVfbWV0YSggdGV4dCwgbWF0Y2hlcywgb3V0ICkge1xuICBpZiAoICFvdXQubGVuZ3RoICkge1xuICAgIHJldHVybiBbIDIsIFwiezpcIiBdO1xuICB9XG5cbiAgLy8gZ2V0IHRoZSBwcmVjZWVkaW5nIGVsZW1lbnRcbiAgdmFyIGJlZm9yZSA9IG91dFsgb3V0Lmxlbmd0aCAtIDEgXTtcblxuICBpZiAoIHR5cGVvZiBiZWZvcmUgPT09IFwic3RyaW5nXCIgKSB7XG4gICAgcmV0dXJuIFsgMiwgXCJ7OlwiIF07XG4gIH1cblxuICAvLyBtYXRjaCBhIG1ldGEgaGFzaFxuICB2YXIgbSA9IHRleHQubWF0Y2goIC9eXFx7OlxccyooKD86XFxcXFxcfXxbXlxcfV0pKilcXHMqXFx9LyApO1xuXG4gIC8vIG5vIG1hdGNoLCBmYWxzZSBhbGFybVxuICBpZiAoICFtICkge1xuICAgIHJldHVybiBbIDIsIFwiezpcIiBdO1xuICB9XG5cbiAgLy8gYXR0YWNoIHRoZSBhdHRyaWJ1dGVzIHRvIHRoZSBwcmVjZWVkaW5nIGVsZW1lbnRcbiAgdmFyIG1ldGEgPSB0aGlzLmRpYWxlY3QucHJvY2Vzc01ldGFIYXNoKCBtWyAxIF0gKSxcbiAgICAgIGF0dHIgPSBleHRyYWN0X2F0dHIoIGJlZm9yZSApO1xuXG4gIGlmICggIWF0dHIgKSB7XG4gICAgYXR0ciA9IHt9O1xuICAgIGJlZm9yZS5zcGxpY2UoIDEsIDAsIGF0dHIgKTtcbiAgfVxuXG4gIGZvciAoIHZhciBrIGluIG1ldGEgKSB7XG4gICAgYXR0clsgayBdID0gbWV0YVsgayBdO1xuICB9XG5cbiAgLy8gY3V0IG91dCB0aGUgc3RyaW5nIGFuZCByZXBsYWNlIGl0IHdpdGggbm90aGluZ1xuICByZXR1cm4gWyBtWyAwIF0ubGVuZ3RoLCBcIlwiIF07XG59O1xuXG5NYXJrZG93bi5kaWFsZWN0cy5NYXJ1a3UuaW5saW5lLl9fZXNjYXBlX18gPSAvXlxcXFxbXFxcXGBcXCpfe31cXFtcXF0oKSNcXCsuIVxcLXw6XS87XG5cbk1hcmtkb3duLmJ1aWxkQmxvY2tPcmRlciAoIE1hcmtkb3duLmRpYWxlY3RzLk1hcnVrdS5ibG9jayApO1xuTWFya2Rvd24uYnVpbGRJbmxpbmVQYXR0ZXJucyggTWFya2Rvd24uZGlhbGVjdHMuTWFydWt1LmlubGluZSApO1xuXG52YXIgaXNBcnJheSA9IEFycmF5LmlzQXJyYXkgfHwgZnVuY3Rpb24ob2JqKSB7XG4gIHJldHVybiBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwob2JqKSA9PSBcIltvYmplY3QgQXJyYXldXCI7XG59O1xuXG52YXIgZm9yRWFjaDtcbi8vIERvbid0IG1lc3Mgd2l0aCBBcnJheS5wcm90b3R5cGUuIEl0cyBub3QgZnJpZW5kbHlcbmlmICggQXJyYXkucHJvdG90eXBlLmZvckVhY2ggKSB7XG4gIGZvckVhY2ggPSBmdW5jdGlvbiggYXJyLCBjYiwgdGhpc3AgKSB7XG4gICAgcmV0dXJuIGFyci5mb3JFYWNoKCBjYiwgdGhpc3AgKTtcbiAgfTtcbn1cbmVsc2Uge1xuICBmb3JFYWNoID0gZnVuY3Rpb24oYXJyLCBjYiwgdGhpc3ApIHtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFyci5sZW5ndGg7IGkrKykge1xuICAgICAgY2IuY2FsbCh0aGlzcCB8fCBhcnIsIGFycltpXSwgaSwgYXJyKTtcbiAgICB9XG4gIH1cbn1cblxudmFyIGlzRW1wdHkgPSBmdW5jdGlvbiggb2JqICkge1xuICBmb3IgKCB2YXIga2V5IGluIG9iaiApIHtcbiAgICBpZiAoIGhhc093blByb3BlcnR5LmNhbGwoIG9iaiwga2V5ICkgKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRydWU7XG59XG5cbmZ1bmN0aW9uIGV4dHJhY3RfYXR0cigganNvbm1sICkge1xuICByZXR1cm4gaXNBcnJheShqc29ubWwpXG4gICAgICAmJiBqc29ubWwubGVuZ3RoID4gMVxuICAgICAgJiYgdHlwZW9mIGpzb25tbFsgMSBdID09PSBcIm9iamVjdFwiXG4gICAgICAmJiAhKCBpc0FycmF5KGpzb25tbFsgMSBdKSApXG4gICAgICA/IGpzb25tbFsgMSBdXG4gICAgICA6IHVuZGVmaW5lZDtcbn1cblxuXG5cbi8qKlxuICogIHJlbmRlckpzb25NTCgganNvbm1sWywgb3B0aW9uc10gKSAtPiBTdHJpbmdcbiAqICAtIGpzb25tbCAoQXJyYXkpOiBKc29uTUwgYXJyYXkgdG8gcmVuZGVyIHRvIFhNTFxuICogIC0gb3B0aW9ucyAoT2JqZWN0KTogb3B0aW9uc1xuICpcbiAqICBDb252ZXJ0cyB0aGUgZ2l2ZW4gSnNvbk1MIGludG8gd2VsbC1mb3JtZWQgWE1MLlxuICpcbiAqICBUaGUgb3B0aW9ucyBjdXJyZW50bHkgdW5kZXJzdG9vZCBhcmU6XG4gKlxuICogIC0gcm9vdCAoQm9vbGVhbik6IHdldGhlciBvciBub3QgdGhlIHJvb3Qgbm9kZSBzaG91bGQgYmUgaW5jbHVkZWQgaW4gdGhlXG4gKiAgICBvdXRwdXQsIG9yIGp1c3QgaXRzIGNoaWxkcmVuLiBUaGUgZGVmYXVsdCBgZmFsc2VgIGlzIHRvIG5vdCBpbmNsdWRlIHRoZVxuICogICAgcm9vdCBpdHNlbGYuXG4gKi9cbmV4cG9zZS5yZW5kZXJKc29uTUwgPSBmdW5jdGlvbigganNvbm1sLCBvcHRpb25zICkge1xuICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcbiAgLy8gaW5jbHVkZSB0aGUgcm9vdCBlbGVtZW50IGluIHRoZSByZW5kZXJlZCBvdXRwdXQ/XG4gIG9wdGlvbnMucm9vdCA9IG9wdGlvbnMucm9vdCB8fCBmYWxzZTtcblxuICB2YXIgY29udGVudCA9IFtdO1xuXG4gIGlmICggb3B0aW9ucy5yb290ICkge1xuICAgIGNvbnRlbnQucHVzaCggcmVuZGVyX3RyZWUoIGpzb25tbCApICk7XG4gIH1cbiAgZWxzZSB7XG4gICAganNvbm1sLnNoaWZ0KCk7IC8vIGdldCByaWQgb2YgdGhlIHRhZ1xuICAgIGlmICgganNvbm1sLmxlbmd0aCAmJiB0eXBlb2YganNvbm1sWyAwIF0gPT09IFwib2JqZWN0XCIgJiYgISgganNvbm1sWyAwIF0gaW5zdGFuY2VvZiBBcnJheSApICkge1xuICAgICAganNvbm1sLnNoaWZ0KCk7IC8vIGdldCByaWQgb2YgdGhlIGF0dHJpYnV0ZXNcbiAgICB9XG5cbiAgICB3aGlsZSAoIGpzb25tbC5sZW5ndGggKSB7XG4gICAgICBjb250ZW50LnB1c2goIHJlbmRlcl90cmVlKCBqc29ubWwuc2hpZnQoKSApICk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGNvbnRlbnQuam9pbiggXCJcXG5cXG5cIiApO1xufTtcblxuZnVuY3Rpb24gZXNjYXBlSFRNTCggdGV4dCApIHtcbiAgcmV0dXJuIHRleHQucmVwbGFjZSggLyYvZywgXCImYW1wO1wiIClcbiAgICAgICAgICAgICAucmVwbGFjZSggLzwvZywgXCImbHQ7XCIgKVxuICAgICAgICAgICAgIC5yZXBsYWNlKCAvPi9nLCBcIiZndDtcIiApXG4gICAgICAgICAgICAgLnJlcGxhY2UoIC9cIi9nLCBcIiZxdW90O1wiIClcbiAgICAgICAgICAgICAucmVwbGFjZSggLycvZywgXCImIzM5O1wiICk7XG59XG5cbmZ1bmN0aW9uIHJlbmRlcl90cmVlKCBqc29ubWwgKSB7XG4gIC8vIGJhc2ljIGNhc2VcbiAgaWYgKCB0eXBlb2YganNvbm1sID09PSBcInN0cmluZ1wiICkge1xuICAgIHJldHVybiBlc2NhcGVIVE1MKCBqc29ubWwgKTtcbiAgfVxuXG4gIHZhciB0YWcgPSBqc29ubWwuc2hpZnQoKSxcbiAgICAgIGF0dHJpYnV0ZXMgPSB7fSxcbiAgICAgIGNvbnRlbnQgPSBbXTtcblxuICBpZiAoIGpzb25tbC5sZW5ndGggJiYgdHlwZW9mIGpzb25tbFsgMCBdID09PSBcIm9iamVjdFwiICYmICEoIGpzb25tbFsgMCBdIGluc3RhbmNlb2YgQXJyYXkgKSApIHtcbiAgICBhdHRyaWJ1dGVzID0ganNvbm1sLnNoaWZ0KCk7XG4gIH1cblxuICB3aGlsZSAoIGpzb25tbC5sZW5ndGggKSB7XG4gICAgY29udGVudC5wdXNoKCByZW5kZXJfdHJlZSgganNvbm1sLnNoaWZ0KCkgKSApO1xuICB9XG5cbiAgdmFyIHRhZ19hdHRycyA9IFwiXCI7XG4gIGZvciAoIHZhciBhIGluIGF0dHJpYnV0ZXMgKSB7XG4gICAgdGFnX2F0dHJzICs9IFwiIFwiICsgYSArICc9XCInICsgZXNjYXBlSFRNTCggYXR0cmlidXRlc1sgYSBdICkgKyAnXCInO1xuICB9XG5cbiAgLy8gYmUgY2FyZWZ1bCBhYm91dCBhZGRpbmcgd2hpdGVzcGFjZSBoZXJlIGZvciBpbmxpbmUgZWxlbWVudHNcbiAgaWYgKCB0YWcgPT0gXCJpbWdcIiB8fCB0YWcgPT0gXCJiclwiIHx8IHRhZyA9PSBcImhyXCIgKSB7XG4gICAgcmV0dXJuIFwiPFwiKyB0YWcgKyB0YWdfYXR0cnMgKyBcIi8+XCI7XG4gIH1cbiAgZWxzZSB7XG4gICAgcmV0dXJuIFwiPFwiKyB0YWcgKyB0YWdfYXR0cnMgKyBcIj5cIiArIGNvbnRlbnQuam9pbiggXCJcIiApICsgXCI8L1wiICsgdGFnICsgXCI+XCI7XG4gIH1cbn1cblxuZnVuY3Rpb24gY29udmVydF90cmVlX3RvX2h0bWwoIHRyZWUsIHJlZmVyZW5jZXMsIG9wdGlvbnMgKSB7XG4gIHZhciBpO1xuICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcblxuICAvLyBzaGFsbG93IGNsb25lXG4gIHZhciBqc29ubWwgPSB0cmVlLnNsaWNlKCAwICk7XG5cbiAgaWYgKCB0eXBlb2Ygb3B0aW9ucy5wcmVwcm9jZXNzVHJlZU5vZGUgPT09IFwiZnVuY3Rpb25cIiApIHtcbiAgICAgIGpzb25tbCA9IG9wdGlvbnMucHJlcHJvY2Vzc1RyZWVOb2RlKGpzb25tbCwgcmVmZXJlbmNlcyk7XG4gIH1cblxuICAvLyBDbG9uZSBhdHRyaWJ1dGVzIGlmIHRoZXkgZXhpc3RcbiAgdmFyIGF0dHJzID0gZXh0cmFjdF9hdHRyKCBqc29ubWwgKTtcbiAgaWYgKCBhdHRycyApIHtcbiAgICBqc29ubWxbIDEgXSA9IHt9O1xuICAgIGZvciAoIGkgaW4gYXR0cnMgKSB7XG4gICAgICBqc29ubWxbIDEgXVsgaSBdID0gYXR0cnNbIGkgXTtcbiAgICB9XG4gICAgYXR0cnMgPSBqc29ubWxbIDEgXTtcbiAgfVxuXG4gIC8vIGJhc2ljIGNhc2VcbiAgaWYgKCB0eXBlb2YganNvbm1sID09PSBcInN0cmluZ1wiICkge1xuICAgIHJldHVybiBqc29ubWw7XG4gIH1cblxuICAvLyBjb252ZXJ0IHRoaXMgbm9kZVxuICBzd2l0Y2ggKCBqc29ubWxbIDAgXSApIHtcbiAgICBjYXNlIFwiaGVhZGVyXCI6XG4gICAgICBqc29ubWxbIDAgXSA9IFwiaFwiICsganNvbm1sWyAxIF0ubGV2ZWw7XG4gICAgICBkZWxldGUganNvbm1sWyAxIF0ubGV2ZWw7XG4gICAgICBicmVhaztcbiAgICBjYXNlIFwiYnVsbGV0bGlzdFwiOlxuICAgICAganNvbm1sWyAwIF0gPSBcInVsXCI7XG4gICAgICBicmVhaztcbiAgICBjYXNlIFwibnVtYmVybGlzdFwiOlxuICAgICAganNvbm1sWyAwIF0gPSBcIm9sXCI7XG4gICAgICBicmVhaztcbiAgICBjYXNlIFwibGlzdGl0ZW1cIjpcbiAgICAgIGpzb25tbFsgMCBdID0gXCJsaVwiO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSBcInBhcmFcIjpcbiAgICAgIGpzb25tbFsgMCBdID0gXCJwXCI7XG4gICAgICBicmVhaztcbiAgICBjYXNlIFwibWFya2Rvd25cIjpcbiAgICAgIGpzb25tbFsgMCBdID0gXCJodG1sXCI7XG4gICAgICBpZiAoIGF0dHJzICkgZGVsZXRlIGF0dHJzLnJlZmVyZW5jZXM7XG4gICAgICBicmVhaztcbiAgICBjYXNlIFwiY29kZV9ibG9ja1wiOlxuICAgICAganNvbm1sWyAwIF0gPSBcInByZVwiO1xuICAgICAgaSA9IGF0dHJzID8gMiA6IDE7XG4gICAgICB2YXIgY29kZSA9IFsgXCJjb2RlXCIgXTtcbiAgICAgIGNvZGUucHVzaC5hcHBseSggY29kZSwganNvbm1sLnNwbGljZSggaSwganNvbm1sLmxlbmd0aCAtIGkgKSApO1xuICAgICAganNvbm1sWyBpIF0gPSBjb2RlO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSBcImlubGluZWNvZGVcIjpcbiAgICAgIGpzb25tbFsgMCBdID0gXCJjb2RlXCI7XG4gICAgICBicmVhaztcbiAgICBjYXNlIFwiaW1nXCI6XG4gICAgICBqc29ubWxbIDEgXS5zcmMgPSBqc29ubWxbIDEgXS5ocmVmO1xuICAgICAgZGVsZXRlIGpzb25tbFsgMSBdLmhyZWY7XG4gICAgICBicmVhaztcbiAgICBjYXNlIFwibGluZWJyZWFrXCI6XG4gICAgICBqc29ubWxbIDAgXSA9IFwiYnJcIjtcbiAgICBicmVhaztcbiAgICBjYXNlIFwibGlua1wiOlxuICAgICAganNvbm1sWyAwIF0gPSBcImFcIjtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgXCJsaW5rX3JlZlwiOlxuICAgICAganNvbm1sWyAwIF0gPSBcImFcIjtcblxuICAgICAgLy8gZ3JhYiB0aGlzIHJlZiBhbmQgY2xlYW4gdXAgdGhlIGF0dHJpYnV0ZSBub2RlXG4gICAgICB2YXIgcmVmID0gcmVmZXJlbmNlc1sgYXR0cnMucmVmIF07XG5cbiAgICAgIC8vIGlmIHRoZSByZWZlcmVuY2UgZXhpc3RzLCBtYWtlIHRoZSBsaW5rXG4gICAgICBpZiAoIHJlZiApIHtcbiAgICAgICAgZGVsZXRlIGF0dHJzLnJlZjtcblxuICAgICAgICAvLyBhZGQgaW4gdGhlIGhyZWYgYW5kIHRpdGxlLCBpZiBwcmVzZW50XG4gICAgICAgIGF0dHJzLmhyZWYgPSByZWYuaHJlZjtcbiAgICAgICAgaWYgKCByZWYudGl0bGUgKSB7XG4gICAgICAgICAgYXR0cnMudGl0bGUgPSByZWYudGl0bGU7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBnZXQgcmlkIG9mIHRoZSB1bm5lZWRlZCBvcmlnaW5hbCB0ZXh0XG4gICAgICAgIGRlbGV0ZSBhdHRycy5vcmlnaW5hbDtcbiAgICAgIH1cbiAgICAgIC8vIHRoZSByZWZlcmVuY2UgZG9lc24ndCBleGlzdCwgc28gcmV2ZXJ0IHRvIHBsYWluIHRleHRcbiAgICAgIGVsc2Uge1xuICAgICAgICByZXR1cm4gYXR0cnMub3JpZ2luYWw7XG4gICAgICB9XG4gICAgICBicmVhaztcbiAgICBjYXNlIFwiaW1nX3JlZlwiOlxuICAgICAganNvbm1sWyAwIF0gPSBcImltZ1wiO1xuXG4gICAgICAvLyBncmFiIHRoaXMgcmVmIGFuZCBjbGVhbiB1cCB0aGUgYXR0cmlidXRlIG5vZGVcbiAgICAgIHZhciByZWYgPSByZWZlcmVuY2VzWyBhdHRycy5yZWYgXTtcblxuICAgICAgLy8gaWYgdGhlIHJlZmVyZW5jZSBleGlzdHMsIG1ha2UgdGhlIGxpbmtcbiAgICAgIGlmICggcmVmICkge1xuICAgICAgICBkZWxldGUgYXR0cnMucmVmO1xuXG4gICAgICAgIC8vIGFkZCBpbiB0aGUgaHJlZiBhbmQgdGl0bGUsIGlmIHByZXNlbnRcbiAgICAgICAgYXR0cnMuc3JjID0gcmVmLmhyZWY7XG4gICAgICAgIGlmICggcmVmLnRpdGxlICkge1xuICAgICAgICAgIGF0dHJzLnRpdGxlID0gcmVmLnRpdGxlO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gZ2V0IHJpZCBvZiB0aGUgdW5uZWVkZWQgb3JpZ2luYWwgdGV4dFxuICAgICAgICBkZWxldGUgYXR0cnMub3JpZ2luYWw7XG4gICAgICB9XG4gICAgICAvLyB0aGUgcmVmZXJlbmNlIGRvZXNuJ3QgZXhpc3QsIHNvIHJldmVydCB0byBwbGFpbiB0ZXh0XG4gICAgICBlbHNlIHtcbiAgICAgICAgcmV0dXJuIGF0dHJzLm9yaWdpbmFsO1xuICAgICAgfVxuICAgICAgYnJlYWs7XG4gIH1cblxuICAvLyBjb252ZXJ0IGFsbCB0aGUgY2hpbGRyZW5cbiAgaSA9IDE7XG5cbiAgLy8gZGVhbCB3aXRoIHRoZSBhdHRyaWJ1dGUgbm9kZSwgaWYgaXQgZXhpc3RzXG4gIGlmICggYXR0cnMgKSB7XG4gICAgLy8gaWYgdGhlcmUgYXJlIGtleXMsIHNraXAgb3ZlciBpdFxuICAgIGZvciAoIHZhciBrZXkgaW4ganNvbm1sWyAxIF0gKSB7XG4gICAgICAgIGkgPSAyO1xuICAgICAgICBicmVhaztcbiAgICB9XG4gICAgLy8gaWYgdGhlcmUgYXJlbid0LCByZW1vdmUgaXRcbiAgICBpZiAoIGkgPT09IDEgKSB7XG4gICAgICBqc29ubWwuc3BsaWNlKCBpLCAxICk7XG4gICAgfVxuICB9XG5cbiAgZm9yICggOyBpIDwganNvbm1sLmxlbmd0aDsgKytpICkge1xuICAgIGpzb25tbFsgaSBdID0gY29udmVydF90cmVlX3RvX2h0bWwoIGpzb25tbFsgaSBdLCByZWZlcmVuY2VzLCBvcHRpb25zICk7XG4gIH1cblxuICByZXR1cm4ganNvbm1sO1xufVxuXG5cbi8vIG1lcmdlcyBhZGphY2VudCB0ZXh0IG5vZGVzIGludG8gYSBzaW5nbGUgbm9kZVxuZnVuY3Rpb24gbWVyZ2VfdGV4dF9ub2RlcygganNvbm1sICkge1xuICAvLyBza2lwIHRoZSB0YWcgbmFtZSBhbmQgYXR0cmlidXRlIGhhc2hcbiAgdmFyIGkgPSBleHRyYWN0X2F0dHIoIGpzb25tbCApID8gMiA6IDE7XG5cbiAgd2hpbGUgKCBpIDwganNvbm1sLmxlbmd0aCApIHtcbiAgICAvLyBpZiBpdCdzIGEgc3RyaW5nIGNoZWNrIHRoZSBuZXh0IGl0ZW0gdG9vXG4gICAgaWYgKCB0eXBlb2YganNvbm1sWyBpIF0gPT09IFwic3RyaW5nXCIgKSB7XG4gICAgICBpZiAoIGkgKyAxIDwganNvbm1sLmxlbmd0aCAmJiB0eXBlb2YganNvbm1sWyBpICsgMSBdID09PSBcInN0cmluZ1wiICkge1xuICAgICAgICAvLyBtZXJnZSB0aGUgc2Vjb25kIHN0cmluZyBpbnRvIHRoZSBmaXJzdCBhbmQgcmVtb3ZlIGl0XG4gICAgICAgIGpzb25tbFsgaSBdICs9IGpzb25tbC5zcGxpY2UoIGkgKyAxLCAxIClbIDAgXTtcbiAgICAgIH1cbiAgICAgIGVsc2Uge1xuICAgICAgICArK2k7XG4gICAgICB9XG4gICAgfVxuICAgIC8vIGlmIGl0J3Mgbm90IGEgc3RyaW5nIHJlY3Vyc2VcbiAgICBlbHNlIHtcbiAgICAgIG1lcmdlX3RleHRfbm9kZXMoIGpzb25tbFsgaSBdICk7XG4gICAgICArK2k7XG4gICAgfVxuICB9XG59XG5cbn0gKSggKGZ1bmN0aW9uKCkge1xuICBpZiAoIHR5cGVvZiBleHBvcnRzID09PSBcInVuZGVmaW5lZFwiICkge1xuICAgIHdpbmRvdy5tYXJrZG93biA9IHt9O1xuICAgIHJldHVybiB3aW5kb3cubWFya2Rvd247XG4gIH1cbiAgZWxzZSB7XG4gICAgcmV0dXJuIGV4cG9ydHM7XG4gIH1cbn0gKSgpICk7XG4iLCIoZnVuY3Rpb24oZil7aWYodHlwZW9mIGV4cG9ydHM9PT1cIm9iamVjdFwiJiZ0eXBlb2YgbW9kdWxlIT09XCJ1bmRlZmluZWRcIil7bW9kdWxlLmV4cG9ydHM9ZigpfWVsc2UgaWYodHlwZW9mIGRlZmluZT09PVwiZnVuY3Rpb25cIiYmZGVmaW5lLmFtZCl7ZGVmaW5lKFtdLGYpfWVsc2V7dmFyIGc7aWYodHlwZW9mIHdpbmRvdyE9PVwidW5kZWZpbmVkXCIpe2c9d2luZG93fWVsc2UgaWYodHlwZW9mIGdsb2JhbCE9PVwidW5kZWZpbmVkXCIpe2c9Z2xvYmFsfWVsc2UgaWYodHlwZW9mIHNlbGYhPT1cInVuZGVmaW5lZFwiKXtnPXNlbGZ9ZWxzZXtnPXRoaXN9Zy50b01hcmtkb3duID0gZigpfX0pKGZ1bmN0aW9uKCl7dmFyIGRlZmluZSxtb2R1bGUsZXhwb3J0cztyZXR1cm4gKGZ1bmN0aW9uIGUodCxuLHIpe2Z1bmN0aW9uIHMobyx1KXtpZighbltvXSl7aWYoIXRbb10pe3ZhciBhPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7aWYoIXUmJmEpcmV0dXJuIGEobywhMCk7aWYoaSlyZXR1cm4gaShvLCEwKTt2YXIgZj1uZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiK28rXCInXCIpO3Rocm93IGYuY29kZT1cIk1PRFVMRV9OT1RfRk9VTkRcIixmfXZhciBsPW5bb109e2V4cG9ydHM6e319O3Rbb11bMF0uY2FsbChsLmV4cG9ydHMsZnVuY3Rpb24oZSl7dmFyIG49dFtvXVsxXVtlXTtyZXR1cm4gcyhuP246ZSl9LGwsbC5leHBvcnRzLGUsdCxuLHIpfXJldHVybiBuW29dLmV4cG9ydHN9dmFyIGk9dHlwZW9mIHJlcXVpcmU9PVwiZnVuY3Rpb25cIiYmcmVxdWlyZTtmb3IodmFyIG89MDtvPHIubGVuZ3RoO28rKylzKHJbb10pO3JldHVybiBzfSkoezE6W2Z1bmN0aW9uKHJlcXVpcmUsbW9kdWxlLGV4cG9ydHMpe1xuLypcbiAqIHRvLW1hcmtkb3duIC0gYW4gSFRNTCB0byBNYXJrZG93biBjb252ZXJ0ZXJcbiAqXG4gKiBDb3B5cmlnaHQgMjAxMSssIERvbSBDaHJpc3RpZVxuICogTGljZW5jZWQgdW5kZXIgdGhlIE1JVCBsaWNlbmNlXG4gKlxuICovXG5cbid1c2Ugc3RyaWN0J1xuXG52YXIgdG9NYXJrZG93blxudmFyIGNvbnZlcnRlcnNcbnZhciBtZENvbnZlcnRlcnMgPSByZXF1aXJlKCcuL2xpYi9tZC1jb252ZXJ0ZXJzJylcbnZhciBnZm1Db252ZXJ0ZXJzID0gcmVxdWlyZSgnLi9saWIvZ2ZtLWNvbnZlcnRlcnMnKVxudmFyIEh0bWxQYXJzZXIgPSByZXF1aXJlKCcuL2xpYi9odG1sLXBhcnNlcicpXG52YXIgY29sbGFwc2UgPSByZXF1aXJlKCdjb2xsYXBzZS13aGl0ZXNwYWNlJylcblxuLypcbiAqIFV0aWxpdGllc1xuICovXG5cbnZhciBibG9ja3MgPSBbJ2FkZHJlc3MnLCAnYXJ0aWNsZScsICdhc2lkZScsICdhdWRpbycsICdibG9ja3F1b3RlJywgJ2JvZHknLFxuICAnY2FudmFzJywgJ2NlbnRlcicsICdkZCcsICdkaXInLCAnZGl2JywgJ2RsJywgJ2R0JywgJ2ZpZWxkc2V0JywgJ2ZpZ2NhcHRpb24nLFxuICAnZmlndXJlJywgJ2Zvb3RlcicsICdmb3JtJywgJ2ZyYW1lc2V0JywgJ2gxJywgJ2gyJywgJ2gzJywgJ2g0JywgJ2g1JywgJ2g2JyxcbiAgJ2hlYWRlcicsICdoZ3JvdXAnLCAnaHInLCAnaHRtbCcsICdpc2luZGV4JywgJ2xpJywgJ21haW4nLCAnbWVudScsICduYXYnLFxuICAnbm9mcmFtZXMnLCAnbm9zY3JpcHQnLCAnb2wnLCAnb3V0cHV0JywgJ3AnLCAncHJlJywgJ3NlY3Rpb24nLCAndGFibGUnLFxuICAndGJvZHknLCAndGQnLCAndGZvb3QnLCAndGgnLCAndGhlYWQnLCAndHInLCAndWwnXG5dXG5cbmZ1bmN0aW9uIGlzQmxvY2sgKG5vZGUpIHtcbiAgcmV0dXJuIGJsb2Nrcy5pbmRleE9mKG5vZGUubm9kZU5hbWUudG9Mb3dlckNhc2UoKSkgIT09IC0xXG59XG5cbnZhciB2b2lkcyA9IFtcbiAgJ2FyZWEnLCAnYmFzZScsICdicicsICdjb2wnLCAnY29tbWFuZCcsICdlbWJlZCcsICdocicsICdpbWcnLCAnaW5wdXQnLFxuICAna2V5Z2VuJywgJ2xpbmsnLCAnbWV0YScsICdwYXJhbScsICdzb3VyY2UnLCAndHJhY2snLCAnd2JyJ1xuXVxuXG5mdW5jdGlvbiBpc1ZvaWQgKG5vZGUpIHtcbiAgcmV0dXJuIHZvaWRzLmluZGV4T2Yobm9kZS5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpKSAhPT0gLTFcbn1cblxuZnVuY3Rpb24gaHRtbFRvRG9tIChzdHJpbmcpIHtcbiAgdmFyIHRyZWUgPSBuZXcgSHRtbFBhcnNlcigpLnBhcnNlRnJvbVN0cmluZyhzdHJpbmcsICd0ZXh0L2h0bWwnKVxuICBjb2xsYXBzZSh0cmVlLmRvY3VtZW50RWxlbWVudCwgaXNCbG9jaylcbiAgcmV0dXJuIHRyZWVcbn1cblxuLypcbiAqIEZsYXR0ZW5zIERPTSB0cmVlIGludG8gc2luZ2xlIGFycmF5XG4gKi9cblxuZnVuY3Rpb24gYmZzT3JkZXIgKG5vZGUpIHtcbiAgdmFyIGlucXVldWUgPSBbbm9kZV1cbiAgdmFyIG91dHF1ZXVlID0gW11cbiAgdmFyIGVsZW1cbiAgdmFyIGNoaWxkcmVuXG4gIHZhciBpXG5cbiAgd2hpbGUgKGlucXVldWUubGVuZ3RoID4gMCkge1xuICAgIGVsZW0gPSBpbnF1ZXVlLnNoaWZ0KClcbiAgICBvdXRxdWV1ZS5wdXNoKGVsZW0pXG4gICAgY2hpbGRyZW4gPSBlbGVtLmNoaWxkTm9kZXNcbiAgICBmb3IgKGkgPSAwOyBpIDwgY2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgIGlmIChjaGlsZHJlbltpXS5ub2RlVHlwZSA9PT0gMSkgaW5xdWV1ZS5wdXNoKGNoaWxkcmVuW2ldKVxuICAgIH1cbiAgfVxuICBvdXRxdWV1ZS5zaGlmdCgpXG4gIHJldHVybiBvdXRxdWV1ZVxufVxuXG4vKlxuICogQ29udHJ1Y3RzIGEgTWFya2Rvd24gc3RyaW5nIG9mIHJlcGxhY2VtZW50IHRleHQgZm9yIGEgZ2l2ZW4gbm9kZVxuICovXG5cbmZ1bmN0aW9uIGdldENvbnRlbnQgKG5vZGUpIHtcbiAgdmFyIHRleHQgPSAnJ1xuICBmb3IgKHZhciBpID0gMDsgaSA8IG5vZGUuY2hpbGROb2Rlcy5sZW5ndGg7IGkrKykge1xuICAgIGlmIChub2RlLmNoaWxkTm9kZXNbaV0ubm9kZVR5cGUgPT09IDEpIHtcbiAgICAgIHRleHQgKz0gbm9kZS5jaGlsZE5vZGVzW2ldLl9yZXBsYWNlbWVudFxuICAgIH0gZWxzZSBpZiAobm9kZS5jaGlsZE5vZGVzW2ldLm5vZGVUeXBlID09PSAzKSB7XG4gICAgICB0ZXh0ICs9IG5vZGUuY2hpbGROb2Rlc1tpXS5kYXRhXG4gICAgfSBlbHNlIGNvbnRpbnVlXG4gIH1cbiAgcmV0dXJuIHRleHRcbn1cblxuLypcbiAqIFJldHVybnMgdGhlIEhUTUwgc3RyaW5nIG9mIGFuIGVsZW1lbnQgd2l0aCBpdHMgY29udGVudHMgY29udmVydGVkXG4gKi9cblxuZnVuY3Rpb24gb3V0ZXIgKG5vZGUsIGNvbnRlbnQpIHtcbiAgcmV0dXJuIG5vZGUuY2xvbmVOb2RlKGZhbHNlKS5vdXRlckhUTUwucmVwbGFjZSgnPjwnLCAnPicgKyBjb250ZW50ICsgJzwnKVxufVxuXG5mdW5jdGlvbiBjYW5Db252ZXJ0IChub2RlLCBmaWx0ZXIpIHtcbiAgaWYgKHR5cGVvZiBmaWx0ZXIgPT09ICdzdHJpbmcnKSB7XG4gICAgcmV0dXJuIGZpbHRlciA9PT0gbm9kZS5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpXG4gIH1cbiAgaWYgKEFycmF5LmlzQXJyYXkoZmlsdGVyKSkge1xuICAgIHJldHVybiBmaWx0ZXIuaW5kZXhPZihub2RlLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCkpICE9PSAtMVxuICB9IGVsc2UgaWYgKHR5cGVvZiBmaWx0ZXIgPT09ICdmdW5jdGlvbicpIHtcbiAgICByZXR1cm4gZmlsdGVyLmNhbGwodG9NYXJrZG93biwgbm9kZSlcbiAgfSBlbHNlIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdgZmlsdGVyYCBuZWVkcyB0byBiZSBhIHN0cmluZywgYXJyYXksIG9yIGZ1bmN0aW9uJylcbiAgfVxufVxuXG5mdW5jdGlvbiBpc0ZsYW5rZWRCeVdoaXRlc3BhY2UgKHNpZGUsIG5vZGUpIHtcbiAgdmFyIHNpYmxpbmdcbiAgdmFyIHJlZ0V4cFxuICB2YXIgaXNGbGFua2VkXG5cbiAgaWYgKHNpZGUgPT09ICdsZWZ0Jykge1xuICAgIHNpYmxpbmcgPSBub2RlLnByZXZpb3VzU2libGluZ1xuICAgIHJlZ0V4cCA9IC8gJC9cbiAgfSBlbHNlIHtcbiAgICBzaWJsaW5nID0gbm9kZS5uZXh0U2libGluZ1xuICAgIHJlZ0V4cCA9IC9eIC9cbiAgfVxuXG4gIGlmIChzaWJsaW5nKSB7XG4gICAgaWYgKHNpYmxpbmcubm9kZVR5cGUgPT09IDMpIHtcbiAgICAgIGlzRmxhbmtlZCA9IHJlZ0V4cC50ZXN0KHNpYmxpbmcubm9kZVZhbHVlKVxuICAgIH0gZWxzZSBpZiAoc2libGluZy5ub2RlVHlwZSA9PT0gMSAmJiAhaXNCbG9jayhzaWJsaW5nKSkge1xuICAgICAgaXNGbGFua2VkID0gcmVnRXhwLnRlc3Qoc2libGluZy50ZXh0Q29udGVudClcbiAgICB9XG4gIH1cbiAgcmV0dXJuIGlzRmxhbmtlZFxufVxuXG5mdW5jdGlvbiBmbGFua2luZ1doaXRlc3BhY2UgKG5vZGUsIGNvbnRlbnQpIHtcbiAgdmFyIGxlYWRpbmcgPSAnJ1xuICB2YXIgdHJhaWxpbmcgPSAnJ1xuXG4gIGlmICghaXNCbG9jayhub2RlKSkge1xuICAgIHZhciBoYXNMZWFkaW5nID0gL15bIFxcclxcblxcdF0vLnRlc3QoY29udGVudClcbiAgICB2YXIgaGFzVHJhaWxpbmcgPSAvWyBcXHJcXG5cXHRdJC8udGVzdChjb250ZW50KVxuXG4gICAgaWYgKGhhc0xlYWRpbmcgJiYgIWlzRmxhbmtlZEJ5V2hpdGVzcGFjZSgnbGVmdCcsIG5vZGUpKSB7XG4gICAgICBsZWFkaW5nID0gJyAnXG4gICAgfVxuICAgIGlmIChoYXNUcmFpbGluZyAmJiAhaXNGbGFua2VkQnlXaGl0ZXNwYWNlKCdyaWdodCcsIG5vZGUpKSB7XG4gICAgICB0cmFpbGluZyA9ICcgJ1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB7IGxlYWRpbmc6IGxlYWRpbmcsIHRyYWlsaW5nOiB0cmFpbGluZyB9XG59XG5cbi8qXG4gKiBGaW5kcyBhIE1hcmtkb3duIGNvbnZlcnRlciwgZ2V0cyB0aGUgcmVwbGFjZW1lbnQsIGFuZCBzZXRzIGl0IG9uXG4gKiBgX3JlcGxhY2VtZW50YFxuICovXG5cbmZ1bmN0aW9uIHByb2Nlc3MgKG5vZGUpIHtcbiAgdmFyIHJlcGxhY2VtZW50XG4gIHZhciBjb250ZW50ID0gZ2V0Q29udGVudChub2RlKVxuXG4gIC8vIFJlbW92ZSBibGFuayBub2Rlc1xuICBpZiAoIWlzVm9pZChub2RlKSAmJiAhL0F8VEh8VEQvLnRlc3Qobm9kZS5ub2RlTmFtZSkgJiYgL15cXHMqJC9pLnRlc3QoY29udGVudCkpIHtcbiAgICBub2RlLl9yZXBsYWNlbWVudCA9ICcnXG4gICAgcmV0dXJuXG4gIH1cblxuICBmb3IgKHZhciBpID0gMDsgaSA8IGNvbnZlcnRlcnMubGVuZ3RoOyBpKyspIHtcbiAgICB2YXIgY29udmVydGVyID0gY29udmVydGVyc1tpXVxuXG4gICAgaWYgKGNhbkNvbnZlcnQobm9kZSwgY29udmVydGVyLmZpbHRlcikpIHtcbiAgICAgIGlmICh0eXBlb2YgY29udmVydGVyLnJlcGxhY2VtZW50ICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXG4gICAgICAgICAgJ2ByZXBsYWNlbWVudGAgbmVlZHMgdG8gYmUgYSBmdW5jdGlvbiB0aGF0IHJldHVybnMgYSBzdHJpbmcnXG4gICAgICAgIClcbiAgICAgIH1cblxuICAgICAgdmFyIHdoaXRlc3BhY2UgPSBmbGFua2luZ1doaXRlc3BhY2Uobm9kZSwgY29udGVudClcblxuICAgICAgaWYgKHdoaXRlc3BhY2UubGVhZGluZyB8fCB3aGl0ZXNwYWNlLnRyYWlsaW5nKSB7XG4gICAgICAgIGNvbnRlbnQgPSBjb250ZW50LnRyaW0oKVxuICAgICAgfVxuICAgICAgcmVwbGFjZW1lbnQgPSB3aGl0ZXNwYWNlLmxlYWRpbmcgK1xuICAgICAgICBjb252ZXJ0ZXIucmVwbGFjZW1lbnQuY2FsbCh0b01hcmtkb3duLCBjb250ZW50LCBub2RlKSArXG4gICAgICAgIHdoaXRlc3BhY2UudHJhaWxpbmdcbiAgICAgIGJyZWFrXG4gICAgfVxuICB9XG5cbiAgbm9kZS5fcmVwbGFjZW1lbnQgPSByZXBsYWNlbWVudFxufVxuXG50b01hcmtkb3duID0gZnVuY3Rpb24gKGlucHV0LCBvcHRpb25zKSB7XG4gIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9XG5cbiAgaWYgKHR5cGVvZiBpbnB1dCAhPT0gJ3N0cmluZycpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKGlucHV0ICsgJyBpcyBub3QgYSBzdHJpbmcnKVxuICB9XG5cbiAgaWYgKGlucHV0ID09PSAnJykge1xuICAgIHJldHVybiAnJ1xuICB9XG5cbiAgLy8gRXNjYXBlIHBvdGVudGlhbCBvbCB0cmlnZ2Vyc1xuICBpbnB1dCA9IGlucHV0LnJlcGxhY2UoLyhcXGQrKVxcLiAvZywgJyQxXFxcXC4gJylcblxuICB2YXIgY2xvbmUgPSBodG1sVG9Eb20oaW5wdXQpLmJvZHlcbiAgdmFyIG5vZGVzID0gYmZzT3JkZXIoY2xvbmUpXG4gIHZhciBvdXRwdXRcblxuICBjb252ZXJ0ZXJzID0gbWRDb252ZXJ0ZXJzLnNsaWNlKDApXG4gIGlmIChvcHRpb25zLmdmbSkge1xuICAgIGNvbnZlcnRlcnMgPSBnZm1Db252ZXJ0ZXJzLmNvbmNhdChjb252ZXJ0ZXJzKVxuICB9XG5cbiAgaWYgKG9wdGlvbnMuY29udmVydGVycykge1xuICAgIGNvbnZlcnRlcnMgPSBvcHRpb25zLmNvbnZlcnRlcnMuY29uY2F0KGNvbnZlcnRlcnMpXG4gIH1cblxuICAvLyBQcm9jZXNzIHRocm91Z2ggbm9kZXMgaW4gcmV2ZXJzZSAoc28gZGVlcGVzdCBjaGlsZCBlbGVtZW50cyBhcmUgZmlyc3QpLlxuICBmb3IgKHZhciBpID0gbm9kZXMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICBwcm9jZXNzKG5vZGVzW2ldKVxuICB9XG4gIG91dHB1dCA9IGdldENvbnRlbnQoY2xvbmUpXG5cbiAgcmV0dXJuIG91dHB1dC5yZXBsYWNlKC9eW1xcdFxcclxcbl0rfFtcXHRcXHJcXG5cXHNdKyQvZywgJycpXG4gICAgLnJlcGxhY2UoL1xcblxccytcXG4vZywgJ1xcblxcbicpXG4gICAgLnJlcGxhY2UoL1xcbnszLH0vZywgJ1xcblxcbicpXG59XG5cbnRvTWFya2Rvd24uaXNCbG9jayA9IGlzQmxvY2tcbnRvTWFya2Rvd24uaXNWb2lkID0gaXNWb2lkXG50b01hcmtkb3duLm91dGVyID0gb3V0ZXJcblxubW9kdWxlLmV4cG9ydHMgPSB0b01hcmtkb3duXG5cbn0se1wiLi9saWIvZ2ZtLWNvbnZlcnRlcnNcIjoyLFwiLi9saWIvaHRtbC1wYXJzZXJcIjozLFwiLi9saWIvbWQtY29udmVydGVyc1wiOjQsXCJjb2xsYXBzZS13aGl0ZXNwYWNlXCI6N31dLDI6W2Z1bmN0aW9uKHJlcXVpcmUsbW9kdWxlLGV4cG9ydHMpe1xuJ3VzZSBzdHJpY3QnXG5cbmZ1bmN0aW9uIGNlbGwgKGNvbnRlbnQsIG5vZGUpIHtcbiAgdmFyIGluZGV4ID0gQXJyYXkucHJvdG90eXBlLmluZGV4T2YuY2FsbChub2RlLnBhcmVudE5vZGUuY2hpbGROb2Rlcywgbm9kZSlcbiAgdmFyIHByZWZpeCA9ICcgJ1xuICBpZiAoaW5kZXggPT09IDApIHByZWZpeCA9ICd8ICdcbiAgcmV0dXJuIHByZWZpeCArIGNvbnRlbnQgKyAnIHwnXG59XG5cbnZhciBoaWdobGlnaHRSZWdFeCA9IC9oaWdobGlnaHQgaGlnaGxpZ2h0LShcXFMrKS9cblxubW9kdWxlLmV4cG9ydHMgPSBbXG4gIHtcbiAgICBmaWx0ZXI6ICdicicsXG4gICAgcmVwbGFjZW1lbnQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiAnXFxuJ1xuICAgIH1cbiAgfSxcbiAge1xuICAgIGZpbHRlcjogWydkZWwnLCAncycsICdzdHJpa2UnXSxcbiAgICByZXBsYWNlbWVudDogZnVuY3Rpb24gKGNvbnRlbnQpIHtcbiAgICAgIHJldHVybiAnfn4nICsgY29udGVudCArICd+fidcbiAgICB9XG4gIH0sXG5cbiAge1xuICAgIGZpbHRlcjogZnVuY3Rpb24gKG5vZGUpIHtcbiAgICAgIHJldHVybiBub2RlLnR5cGUgPT09ICdjaGVja2JveCcgJiYgbm9kZS5wYXJlbnROb2RlLm5vZGVOYW1lID09PSAnTEknXG4gICAgfSxcbiAgICByZXBsYWNlbWVudDogZnVuY3Rpb24gKGNvbnRlbnQsIG5vZGUpIHtcbiAgICAgIHJldHVybiAobm9kZS5jaGVja2VkID8gJ1t4XScgOiAnWyBdJykgKyAnICdcbiAgICB9XG4gIH0sXG5cbiAge1xuICAgIGZpbHRlcjogWyd0aCcsICd0ZCddLFxuICAgIHJlcGxhY2VtZW50OiBmdW5jdGlvbiAoY29udGVudCwgbm9kZSkge1xuICAgICAgcmV0dXJuIGNlbGwoY29udGVudCwgbm9kZSlcbiAgICB9XG4gIH0sXG5cbiAge1xuICAgIGZpbHRlcjogJ3RyJyxcbiAgICByZXBsYWNlbWVudDogZnVuY3Rpb24gKGNvbnRlbnQsIG5vZGUpIHtcbiAgICAgIHZhciBib3JkZXJDZWxscyA9ICcnXG4gICAgICB2YXIgYWxpZ25NYXAgPSB7IGxlZnQ6ICc6LS0nLCByaWdodDogJy0tOicsIGNlbnRlcjogJzotOicgfVxuXG4gICAgICBpZiAobm9kZS5wYXJlbnROb2RlLm5vZGVOYW1lID09PSAnVEhFQUQnKSB7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbm9kZS5jaGlsZE5vZGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgdmFyIGFsaWduID0gbm9kZS5jaGlsZE5vZGVzW2ldLmF0dHJpYnV0ZXMuYWxpZ25cbiAgICAgICAgICB2YXIgYm9yZGVyID0gJy0tLSdcblxuICAgICAgICAgIGlmIChhbGlnbikgYm9yZGVyID0gYWxpZ25NYXBbYWxpZ24udmFsdWVdIHx8IGJvcmRlclxuXG4gICAgICAgICAgYm9yZGVyQ2VsbHMgKz0gY2VsbChib3JkZXIsIG5vZGUuY2hpbGROb2Rlc1tpXSlcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuICdcXG4nICsgY29udGVudCArIChib3JkZXJDZWxscyA/ICdcXG4nICsgYm9yZGVyQ2VsbHMgOiAnJylcbiAgICB9XG4gIH0sXG5cbiAge1xuICAgIGZpbHRlcjogJ3RhYmxlJyxcbiAgICByZXBsYWNlbWVudDogZnVuY3Rpb24gKGNvbnRlbnQpIHtcbiAgICAgIHJldHVybiAnXFxuXFxuJyArIGNvbnRlbnQgKyAnXFxuXFxuJ1xuICAgIH1cbiAgfSxcblxuICB7XG4gICAgZmlsdGVyOiBbJ3RoZWFkJywgJ3Rib2R5JywgJ3Rmb290J10sXG4gICAgcmVwbGFjZW1lbnQ6IGZ1bmN0aW9uIChjb250ZW50KSB7XG4gICAgICByZXR1cm4gY29udGVudFxuICAgIH1cbiAgfSxcblxuICAvLyBGZW5jZWQgY29kZSBibG9ja3NcbiAge1xuICAgIGZpbHRlcjogZnVuY3Rpb24gKG5vZGUpIHtcbiAgICAgIHJldHVybiBub2RlLm5vZGVOYW1lID09PSAnUFJFJyAmJlxuICAgICAgbm9kZS5maXJzdENoaWxkICYmXG4gICAgICBub2RlLmZpcnN0Q2hpbGQubm9kZU5hbWUgPT09ICdDT0RFJ1xuICAgIH0sXG4gICAgcmVwbGFjZW1lbnQ6IGZ1bmN0aW9uIChjb250ZW50LCBub2RlKSB7XG4gICAgICByZXR1cm4gJ1xcblxcbmBgYFxcbicgKyBub2RlLmZpcnN0Q2hpbGQudGV4dENvbnRlbnQgKyAnXFxuYGBgXFxuXFxuJ1xuICAgIH1cbiAgfSxcblxuICAvLyBTeW50YXgtaGlnaGxpZ2h0ZWQgY29kZSBibG9ja3NcbiAge1xuICAgIGZpbHRlcjogZnVuY3Rpb24gKG5vZGUpIHtcbiAgICAgIHJldHVybiBub2RlLm5vZGVOYW1lID09PSAnUFJFJyAmJlxuICAgICAgbm9kZS5wYXJlbnROb2RlLm5vZGVOYW1lID09PSAnRElWJyAmJlxuICAgICAgaGlnaGxpZ2h0UmVnRXgudGVzdChub2RlLnBhcmVudE5vZGUuY2xhc3NOYW1lKVxuICAgIH0sXG4gICAgcmVwbGFjZW1lbnQ6IGZ1bmN0aW9uIChjb250ZW50LCBub2RlKSB7XG4gICAgICB2YXIgbGFuZ3VhZ2UgPSBub2RlLnBhcmVudE5vZGUuY2xhc3NOYW1lLm1hdGNoKGhpZ2hsaWdodFJlZ0V4KVsxXVxuICAgICAgcmV0dXJuICdcXG5cXG5gYGAnICsgbGFuZ3VhZ2UgKyAnXFxuJyArIG5vZGUudGV4dENvbnRlbnQgKyAnXFxuYGBgXFxuXFxuJ1xuICAgIH1cbiAgfSxcblxuICB7XG4gICAgZmlsdGVyOiBmdW5jdGlvbiAobm9kZSkge1xuICAgICAgcmV0dXJuIG5vZGUubm9kZU5hbWUgPT09ICdESVYnICYmXG4gICAgICBoaWdobGlnaHRSZWdFeC50ZXN0KG5vZGUuY2xhc3NOYW1lKVxuICAgIH0sXG4gICAgcmVwbGFjZW1lbnQ6IGZ1bmN0aW9uIChjb250ZW50KSB7XG4gICAgICByZXR1cm4gJ1xcblxcbicgKyBjb250ZW50ICsgJ1xcblxcbidcbiAgICB9XG4gIH1cbl1cblxufSx7fV0sMzpbZnVuY3Rpb24ocmVxdWlyZSxtb2R1bGUsZXhwb3J0cyl7XG4vKlxuICogU2V0IHVwIHdpbmRvdyBmb3IgTm9kZS5qc1xuICovXG5cbnZhciBfd2luZG93ID0gKHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnID8gd2luZG93IDogdGhpcylcblxuLypcbiAqIFBhcnNpbmcgSFRNTCBzdHJpbmdzXG4gKi9cblxuZnVuY3Rpb24gY2FuUGFyc2VIdG1sTmF0aXZlbHkgKCkge1xuICB2YXIgUGFyc2VyID0gX3dpbmRvdy5ET01QYXJzZXJcbiAgdmFyIGNhblBhcnNlID0gZmFsc2VcblxuICAvLyBBZGFwdGVkIGZyb20gaHR0cHM6Ly9naXN0LmdpdGh1Yi5jb20vMTEyOTAzMVxuICAvLyBGaXJlZm94L09wZXJhL0lFIHRocm93IGVycm9ycyBvbiB1bnN1cHBvcnRlZCB0eXBlc1xuICB0cnkge1xuICAgIC8vIFdlYktpdCByZXR1cm5zIG51bGwgb24gdW5zdXBwb3J0ZWQgdHlwZXNcbiAgICBpZiAobmV3IFBhcnNlcigpLnBhcnNlRnJvbVN0cmluZygnJywgJ3RleHQvaHRtbCcpKSB7XG4gICAgICBjYW5QYXJzZSA9IHRydWVcbiAgICB9XG4gIH0gY2F0Y2ggKGUpIHt9XG5cbiAgcmV0dXJuIGNhblBhcnNlXG59XG5cbmZ1bmN0aW9uIGNyZWF0ZUh0bWxQYXJzZXIgKCkge1xuICB2YXIgUGFyc2VyID0gZnVuY3Rpb24gKCkge31cblxuICAvLyBGb3IgTm9kZS5qcyBlbnZpcm9ubWVudHNcbiAgaWYgKHR5cGVvZiBkb2N1bWVudCA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICB2YXIganNkb20gPSByZXF1aXJlKCdqc2RvbScpXG4gICAgUGFyc2VyLnByb3RvdHlwZS5wYXJzZUZyb21TdHJpbmcgPSBmdW5jdGlvbiAoc3RyaW5nKSB7XG4gICAgICByZXR1cm4ganNkb20uanNkb20oc3RyaW5nLCB7XG4gICAgICAgIGZlYXR1cmVzOiB7XG4gICAgICAgICAgRmV0Y2hFeHRlcm5hbFJlc291cmNlczogW10sXG4gICAgICAgICAgUHJvY2Vzc0V4dGVybmFsUmVzb3VyY2VzOiBmYWxzZVxuICAgICAgICB9XG4gICAgICB9KVxuICAgIH1cbiAgfSBlbHNlIHtcbiAgICBpZiAoIXNob3VsZFVzZUFjdGl2ZVgoKSkge1xuICAgICAgUGFyc2VyLnByb3RvdHlwZS5wYXJzZUZyb21TdHJpbmcgPSBmdW5jdGlvbiAoc3RyaW5nKSB7XG4gICAgICAgIHZhciBkb2MgPSBkb2N1bWVudC5pbXBsZW1lbnRhdGlvbi5jcmVhdGVIVE1MRG9jdW1lbnQoJycpXG4gICAgICAgIGRvYy5vcGVuKClcbiAgICAgICAgZG9jLndyaXRlKHN0cmluZylcbiAgICAgICAgZG9jLmNsb3NlKClcbiAgICAgICAgcmV0dXJuIGRvY1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBQYXJzZXIucHJvdG90eXBlLnBhcnNlRnJvbVN0cmluZyA9IGZ1bmN0aW9uIChzdHJpbmcpIHtcbiAgICAgICAgdmFyIGRvYyA9IG5ldyB3aW5kb3cuQWN0aXZlWE9iamVjdCgnaHRtbGZpbGUnKVxuICAgICAgICBkb2MuZGVzaWduTW9kZSA9ICdvbicgLy8gZGlzYWJsZSBvbi1wYWdlIHNjcmlwdHNcbiAgICAgICAgZG9jLm9wZW4oKVxuICAgICAgICBkb2Mud3JpdGUoc3RyaW5nKVxuICAgICAgICBkb2MuY2xvc2UoKVxuICAgICAgICByZXR1cm4gZG9jXG4gICAgICB9XG4gICAgfVxuICB9XG4gIHJldHVybiBQYXJzZXJcbn1cblxuZnVuY3Rpb24gc2hvdWxkVXNlQWN0aXZlWCAoKSB7XG4gIHZhciB1c2VBY3RpdmVYID0gZmFsc2VcblxuICB0cnkge1xuICAgIGRvY3VtZW50LmltcGxlbWVudGF0aW9uLmNyZWF0ZUhUTUxEb2N1bWVudCgnJykub3BlbigpXG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBpZiAod2luZG93LkFjdGl2ZVhPYmplY3QpIHVzZUFjdGl2ZVggPSB0cnVlXG4gIH1cblxuICByZXR1cm4gdXNlQWN0aXZlWFxufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGNhblBhcnNlSHRtbE5hdGl2ZWx5KCkgPyBfd2luZG93LkRPTVBhcnNlciA6IGNyZWF0ZUh0bWxQYXJzZXIoKVxuXG59LHtcImpzZG9tXCI6Nn1dLDQ6W2Z1bmN0aW9uKHJlcXVpcmUsbW9kdWxlLGV4cG9ydHMpe1xuJ3VzZSBzdHJpY3QnXG5cbm1vZHVsZS5leHBvcnRzID0gW1xuICB7XG4gICAgZmlsdGVyOiAncCcsXG4gICAgcmVwbGFjZW1lbnQ6IGZ1bmN0aW9uIChjb250ZW50KSB7XG4gICAgICByZXR1cm4gJ1xcblxcbicgKyBjb250ZW50ICsgJ1xcblxcbidcbiAgICB9XG4gIH0sXG5cbiAge1xuICAgIGZpbHRlcjogJ2JyJyxcbiAgICByZXBsYWNlbWVudDogZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuICcgIFxcbidcbiAgICB9XG4gIH0sXG5cbiAge1xuICAgIGZpbHRlcjogWydoMScsICdoMicsICdoMycsICdoNCcsICdoNScsICdoNiddLFxuICAgIHJlcGxhY2VtZW50OiBmdW5jdGlvbiAoY29udGVudCwgbm9kZSkge1xuICAgICAgdmFyIGhMZXZlbCA9IG5vZGUubm9kZU5hbWUuY2hhckF0KDEpXG4gICAgICB2YXIgaFByZWZpeCA9ICcnXG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGhMZXZlbDsgaSsrKSB7XG4gICAgICAgIGhQcmVmaXggKz0gJyMnXG4gICAgICB9XG4gICAgICByZXR1cm4gJ1xcblxcbicgKyBoUHJlZml4ICsgJyAnICsgY29udGVudCArICdcXG5cXG4nXG4gICAgfVxuICB9LFxuXG4gIHtcbiAgICBmaWx0ZXI6ICdocicsXG4gICAgcmVwbGFjZW1lbnQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiAnXFxuXFxuKiAqICpcXG5cXG4nXG4gICAgfVxuICB9LFxuXG4gIHtcbiAgICBmaWx0ZXI6IFsnZW0nLCAnaSddLFxuICAgIHJlcGxhY2VtZW50OiBmdW5jdGlvbiAoY29udGVudCkge1xuICAgICAgcmV0dXJuICdfJyArIGNvbnRlbnQgKyAnXydcbiAgICB9XG4gIH0sXG5cbiAge1xuICAgIGZpbHRlcjogWydzdHJvbmcnLCAnYiddLFxuICAgIHJlcGxhY2VtZW50OiBmdW5jdGlvbiAoY29udGVudCkge1xuICAgICAgcmV0dXJuICcqKicgKyBjb250ZW50ICsgJyoqJ1xuICAgIH1cbiAgfSxcblxuICAvLyBJbmxpbmUgY29kZVxuICB7XG4gICAgZmlsdGVyOiBmdW5jdGlvbiAobm9kZSkge1xuICAgICAgdmFyIGhhc1NpYmxpbmdzID0gbm9kZS5wcmV2aW91c1NpYmxpbmcgfHwgbm9kZS5uZXh0U2libGluZ1xuICAgICAgdmFyIGlzQ29kZUJsb2NrID0gbm9kZS5wYXJlbnROb2RlLm5vZGVOYW1lID09PSAnUFJFJyAmJiAhaGFzU2libGluZ3NcblxuICAgICAgcmV0dXJuIG5vZGUubm9kZU5hbWUgPT09ICdDT0RFJyAmJiAhaXNDb2RlQmxvY2tcbiAgICB9LFxuICAgIHJlcGxhY2VtZW50OiBmdW5jdGlvbiAoY29udGVudCkge1xuICAgICAgcmV0dXJuICdgJyArIGNvbnRlbnQgKyAnYCdcbiAgICB9XG4gIH0sXG5cbiAge1xuICAgIGZpbHRlcjogZnVuY3Rpb24gKG5vZGUpIHtcbiAgICAgIHJldHVybiBub2RlLm5vZGVOYW1lID09PSAnQScgJiYgbm9kZS5nZXRBdHRyaWJ1dGUoJ2hyZWYnKVxuICAgIH0sXG4gICAgcmVwbGFjZW1lbnQ6IGZ1bmN0aW9uIChjb250ZW50LCBub2RlKSB7XG4gICAgICB2YXIgdGl0bGVQYXJ0ID0gbm9kZS50aXRsZSA/ICcgXCInICsgbm9kZS50aXRsZSArICdcIicgOiAnJ1xuICAgICAgcmV0dXJuICdbJyArIGNvbnRlbnQgKyAnXSgnICsgbm9kZS5nZXRBdHRyaWJ1dGUoJ2hyZWYnKSArIHRpdGxlUGFydCArICcpJ1xuICAgIH1cbiAgfSxcblxuICB7XG4gICAgZmlsdGVyOiAnaW1nJyxcbiAgICByZXBsYWNlbWVudDogZnVuY3Rpb24gKGNvbnRlbnQsIG5vZGUpIHtcbiAgICAgIHZhciBhbHQgPSBub2RlLmFsdCB8fCAnJ1xuICAgICAgdmFyIHNyYyA9IG5vZGUuZ2V0QXR0cmlidXRlKCdzcmMnKSB8fCAnJ1xuICAgICAgdmFyIHRpdGxlID0gbm9kZS50aXRsZSB8fCAnJ1xuICAgICAgdmFyIHRpdGxlUGFydCA9IHRpdGxlID8gJyBcIicgKyB0aXRsZSArICdcIicgOiAnJ1xuICAgICAgcmV0dXJuIHNyYyA/ICchWycgKyBhbHQgKyAnXScgKyAnKCcgKyBzcmMgKyB0aXRsZVBhcnQgKyAnKScgOiAnJ1xuICAgIH1cbiAgfSxcblxuICAvLyBDb2RlIGJsb2Nrc1xuICB7XG4gICAgZmlsdGVyOiBmdW5jdGlvbiAobm9kZSkge1xuICAgICAgcmV0dXJuIG5vZGUubm9kZU5hbWUgPT09ICdQUkUnICYmIG5vZGUuZmlyc3RDaGlsZC5ub2RlTmFtZSA9PT0gJ0NPREUnXG4gICAgfSxcbiAgICByZXBsYWNlbWVudDogZnVuY3Rpb24gKGNvbnRlbnQsIG5vZGUpIHtcbiAgICAgIHJldHVybiAnXFxuXFxuICAgICcgKyBub2RlLmZpcnN0Q2hpbGQudGV4dENvbnRlbnQucmVwbGFjZSgvXFxuL2csICdcXG4gICAgJykgKyAnXFxuXFxuJ1xuICAgIH1cbiAgfSxcblxuICB7XG4gICAgZmlsdGVyOiAnYmxvY2txdW90ZScsXG4gICAgcmVwbGFjZW1lbnQ6IGZ1bmN0aW9uIChjb250ZW50KSB7XG4gICAgICBjb250ZW50ID0gY29udGVudC50cmltKClcbiAgICAgIGNvbnRlbnQgPSBjb250ZW50LnJlcGxhY2UoL1xcbnszLH0vZywgJ1xcblxcbicpXG4gICAgICBjb250ZW50ID0gY29udGVudC5yZXBsYWNlKC9eL2dtLCAnPiAnKVxuICAgICAgcmV0dXJuICdcXG5cXG4nICsgY29udGVudCArICdcXG5cXG4nXG4gICAgfVxuICB9LFxuXG4gIHtcbiAgICBmaWx0ZXI6ICdsaScsXG4gICAgcmVwbGFjZW1lbnQ6IGZ1bmN0aW9uIChjb250ZW50LCBub2RlKSB7XG4gICAgICBjb250ZW50ID0gY29udGVudC5yZXBsYWNlKC9eXFxzKy8sICcnKS5yZXBsYWNlKC9cXG4vZ20sICdcXG4gICAgJylcbiAgICAgIHZhciBwcmVmaXggPSAnKiAgICdcbiAgICAgIHZhciBwYXJlbnQgPSBub2RlLnBhcmVudE5vZGVcbiAgICAgIHZhciBpbmRleCA9IEFycmF5LnByb3RvdHlwZS5pbmRleE9mLmNhbGwocGFyZW50LmNoaWxkcmVuLCBub2RlKSArIDFcblxuICAgICAgcHJlZml4ID0gL29sL2kudGVzdChwYXJlbnQubm9kZU5hbWUpID8gaW5kZXggKyAnLiAgJyA6ICcqICAgJ1xuICAgICAgcmV0dXJuIHByZWZpeCArIGNvbnRlbnRcbiAgICB9XG4gIH0sXG5cbiAge1xuICAgIGZpbHRlcjogWyd1bCcsICdvbCddLFxuICAgIHJlcGxhY2VtZW50OiBmdW5jdGlvbiAoY29udGVudCwgbm9kZSkge1xuICAgICAgdmFyIHN0cmluZ3MgPSBbXVxuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBub2RlLmNoaWxkTm9kZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgc3RyaW5ncy5wdXNoKG5vZGUuY2hpbGROb2Rlc1tpXS5fcmVwbGFjZW1lbnQpXG4gICAgICB9XG5cbiAgICAgIGlmICgvbGkvaS50ZXN0KG5vZGUucGFyZW50Tm9kZS5ub2RlTmFtZSkpIHtcbiAgICAgICAgcmV0dXJuICdcXG4nICsgc3RyaW5ncy5qb2luKCdcXG4nKVxuICAgICAgfVxuICAgICAgcmV0dXJuICdcXG5cXG4nICsgc3RyaW5ncy5qb2luKCdcXG4nKSArICdcXG5cXG4nXG4gICAgfVxuICB9LFxuXG4gIHtcbiAgICBmaWx0ZXI6IGZ1bmN0aW9uIChub2RlKSB7XG4gICAgICByZXR1cm4gdGhpcy5pc0Jsb2NrKG5vZGUpXG4gICAgfSxcbiAgICByZXBsYWNlbWVudDogZnVuY3Rpb24gKGNvbnRlbnQsIG5vZGUpIHtcbiAgICAgIHJldHVybiAnXFxuXFxuJyArIHRoaXMub3V0ZXIobm9kZSwgY29udGVudCkgKyAnXFxuXFxuJ1xuICAgIH1cbiAgfSxcblxuICAvLyBBbnl0aGluZyBlbHNlIVxuICB7XG4gICAgZmlsdGVyOiBmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gdHJ1ZVxuICAgIH0sXG4gICAgcmVwbGFjZW1lbnQ6IGZ1bmN0aW9uIChjb250ZW50LCBub2RlKSB7XG4gICAgICByZXR1cm4gdGhpcy5vdXRlcihub2RlLCBjb250ZW50KVxuICAgIH1cbiAgfVxuXVxuXG59LHt9XSw1OltmdW5jdGlvbihyZXF1aXJlLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuICogVGhpcyBmaWxlIGF1dG9tYXRpY2FsbHkgZ2VuZXJhdGVkIGZyb20gYGJ1aWxkLmpzYC5cbiAqIERvIG5vdCBtYW51YWxseSBlZGl0LlxuICovXG5cbm1vZHVsZS5leHBvcnRzID0gW1xuICBcImFkZHJlc3NcIixcbiAgXCJhcnRpY2xlXCIsXG4gIFwiYXNpZGVcIixcbiAgXCJhdWRpb1wiLFxuICBcImJsb2NrcXVvdGVcIixcbiAgXCJjYW52YXNcIixcbiAgXCJkZFwiLFxuICBcImRpdlwiLFxuICBcImRsXCIsXG4gIFwiZmllbGRzZXRcIixcbiAgXCJmaWdjYXB0aW9uXCIsXG4gIFwiZmlndXJlXCIsXG4gIFwiZm9vdGVyXCIsXG4gIFwiZm9ybVwiLFxuICBcImgxXCIsXG4gIFwiaDJcIixcbiAgXCJoM1wiLFxuICBcImg0XCIsXG4gIFwiaDVcIixcbiAgXCJoNlwiLFxuICBcImhlYWRlclwiLFxuICBcImhncm91cFwiLFxuICBcImhyXCIsXG4gIFwibWFpblwiLFxuICBcIm5hdlwiLFxuICBcIm5vc2NyaXB0XCIsXG4gIFwib2xcIixcbiAgXCJvdXRwdXRcIixcbiAgXCJwXCIsXG4gIFwicHJlXCIsXG4gIFwic2VjdGlvblwiLFxuICBcInRhYmxlXCIsXG4gIFwidGZvb3RcIixcbiAgXCJ1bFwiLFxuICBcInZpZGVvXCJcbl07XG5cbn0se31dLDY6W2Z1bmN0aW9uKHJlcXVpcmUsbW9kdWxlLGV4cG9ydHMpe1xuXG59LHt9XSw3OltmdW5jdGlvbihyZXF1aXJlLG1vZHVsZSxleHBvcnRzKXtcbid1c2Ugc3RyaWN0JztcblxudmFyIHZvaWRFbGVtZW50cyA9IHJlcXVpcmUoJ3ZvaWQtZWxlbWVudHMnKTtcbk9iamVjdC5rZXlzKHZvaWRFbGVtZW50cykuZm9yRWFjaChmdW5jdGlvbiAobmFtZSkge1xuICB2b2lkRWxlbWVudHNbbmFtZS50b1VwcGVyQ2FzZSgpXSA9IDE7XG59KTtcblxudmFyIGJsb2NrRWxlbWVudHMgPSB7fTtcbnJlcXVpcmUoJ2Jsb2NrLWVsZW1lbnRzJykuZm9yRWFjaChmdW5jdGlvbiAobmFtZSkge1xuICBibG9ja0VsZW1lbnRzW25hbWUudG9VcHBlckNhc2UoKV0gPSAxO1xufSk7XG5cbi8qKlxuICogaXNCbG9ja0VsZW0obm9kZSkgZGV0ZXJtaW5lcyBpZiB0aGUgZ2l2ZW4gbm9kZSBpcyBhIGJsb2NrIGVsZW1lbnQuXG4gKlxuICogQHBhcmFtIHtOb2RlfSBub2RlXG4gKiBAcmV0dXJuIHtCb29sZWFufVxuICovXG5mdW5jdGlvbiBpc0Jsb2NrRWxlbShub2RlKSB7XG4gIHJldHVybiAhIShub2RlICYmIGJsb2NrRWxlbWVudHNbbm9kZS5ub2RlTmFtZV0pO1xufVxuXG4vKipcbiAqIGlzVm9pZChub2RlKSBkZXRlcm1pbmVzIGlmIHRoZSBnaXZlbiBub2RlIGlzIGEgdm9pZCBlbGVtZW50LlxuICpcbiAqIEBwYXJhbSB7Tm9kZX0gbm9kZVxuICogQHJldHVybiB7Qm9vbGVhbn1cbiAqL1xuZnVuY3Rpb24gaXNWb2lkKG5vZGUpIHtcbiAgcmV0dXJuICEhKG5vZGUgJiYgdm9pZEVsZW1lbnRzW25vZGUubm9kZU5hbWVdKTtcbn1cblxuLyoqXG4gKiB3aGl0ZXNwYWNlKGVsZW0gWywgaXNCbG9ja10pIHJlbW92ZXMgZXh0cmFuZW91cyB3aGl0ZXNwYWNlIGZyb20gYW5cbiAqIHRoZSBnaXZlbiBlbGVtZW50LiBUaGUgZnVuY3Rpb24gaXNCbG9jayBtYXkgb3B0aW9uYWxseSBiZSBwYXNzZWQgaW5cbiAqIHRvIGRldGVybWluZSB3aGV0aGVyIG9yIG5vdCBhbiBlbGVtZW50IGlzIGEgYmxvY2sgZWxlbWVudDsgaWYgbm9uZVxuICogaXMgcHJvdmlkZWQsIGRlZmF1bHRzIHRvIHVzaW5nIHRoZSBsaXN0IG9mIGJsb2NrIGVsZW1lbnRzIHByb3ZpZGVkXG4gKiBieSB0aGUgYGJsb2NrLWVsZW1lbnRzYCBtb2R1bGUuXG4gKlxuICogQHBhcmFtIHtOb2RlfSBlbGVtXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBibG9ja1Rlc3RcbiAqL1xuZnVuY3Rpb24gY29sbGFwc2VXaGl0ZXNwYWNlKGVsZW0sIGlzQmxvY2spIHtcbiAgaWYgKCFlbGVtLmZpcnN0Q2hpbGQgfHwgZWxlbS5ub2RlTmFtZSA9PT0gJ1BSRScpIHJldHVybjtcblxuICBpZiAodHlwZW9mIGlzQmxvY2sgIT09ICdmdW5jdGlvbicpIHtcbiAgICBpc0Jsb2NrID0gaXNCbG9ja0VsZW07XG4gIH1cblxuICB2YXIgcHJldlRleHQgPSBudWxsO1xuICB2YXIgcHJldlZvaWQgPSBmYWxzZTtcblxuICB2YXIgcHJldiA9IG51bGw7XG4gIHZhciBub2RlID0gbmV4dChwcmV2LCBlbGVtKTtcblxuICB3aGlsZSAobm9kZSAhPT0gZWxlbSkge1xuICAgIGlmIChub2RlLm5vZGVUeXBlID09PSAzKSB7XG4gICAgICAvLyBOb2RlLlRFWFRfTk9ERVxuICAgICAgdmFyIHRleHQgPSBub2RlLmRhdGEucmVwbGFjZSgvWyBcXHJcXG5cXHRdKy9nLCAnICcpO1xuXG4gICAgICBpZiAoKCFwcmV2VGV4dCB8fCAvICQvLnRlc3QocHJldlRleHQuZGF0YSkpICYmICFwcmV2Vm9pZCAmJiB0ZXh0WzBdID09PSAnICcpIHtcbiAgICAgICAgdGV4dCA9IHRleHQuc3Vic3RyKDEpO1xuICAgICAgfVxuXG4gICAgICAvLyBgdGV4dGAgbWlnaHQgYmUgZW1wdHkgYXQgdGhpcyBwb2ludC5cbiAgICAgIGlmICghdGV4dCkge1xuICAgICAgICBub2RlID0gcmVtb3ZlKG5vZGUpO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgbm9kZS5kYXRhID0gdGV4dDtcbiAgICAgIHByZXZUZXh0ID0gbm9kZTtcbiAgICB9IGVsc2UgaWYgKG5vZGUubm9kZVR5cGUgPT09IDEpIHtcbiAgICAgIC8vIE5vZGUuRUxFTUVOVF9OT0RFXG4gICAgICBpZiAoaXNCbG9jayhub2RlKSB8fCBub2RlLm5vZGVOYW1lID09PSAnQlInKSB7XG4gICAgICAgIGlmIChwcmV2VGV4dCkge1xuICAgICAgICAgIHByZXZUZXh0LmRhdGEgPSBwcmV2VGV4dC5kYXRhLnJlcGxhY2UoLyAkLywgJycpO1xuICAgICAgICB9XG5cbiAgICAgICAgcHJldlRleHQgPSBudWxsO1xuICAgICAgICBwcmV2Vm9pZCA9IGZhbHNlO1xuICAgICAgfSBlbHNlIGlmIChpc1ZvaWQobm9kZSkpIHtcbiAgICAgICAgLy8gQXZvaWQgdHJpbW1pbmcgc3BhY2UgYXJvdW5kIG5vbi1ibG9jaywgbm9uLUJSIHZvaWQgZWxlbWVudHMuXG4gICAgICAgIHByZXZUZXh0ID0gbnVsbDtcbiAgICAgICAgcHJldlZvaWQgPSB0cnVlO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBub2RlID0gcmVtb3ZlKG5vZGUpO1xuICAgICAgY29udGludWU7XG4gICAgfVxuXG4gICAgdmFyIG5leHROb2RlID0gbmV4dChwcmV2LCBub2RlKTtcbiAgICBwcmV2ID0gbm9kZTtcbiAgICBub2RlID0gbmV4dE5vZGU7XG4gIH1cblxuICBpZiAocHJldlRleHQpIHtcbiAgICBwcmV2VGV4dC5kYXRhID0gcHJldlRleHQuZGF0YS5yZXBsYWNlKC8gJC8sICcnKTtcbiAgICBpZiAoIXByZXZUZXh0LmRhdGEpIHtcbiAgICAgIHJlbW92ZShwcmV2VGV4dCk7XG4gICAgfVxuICB9XG59XG5cbi8qKlxuICogcmVtb3ZlKG5vZGUpIHJlbW92ZXMgdGhlIGdpdmVuIG5vZGUgZnJvbSB0aGUgRE9NIGFuZCByZXR1cm5zIHRoZVxuICogbmV4dCBub2RlIGluIHRoZSBzZXF1ZW5jZS5cbiAqXG4gKiBAcGFyYW0ge05vZGV9IG5vZGVcbiAqIEByZXR1cm4ge05vZGV9IG5vZGVcbiAqL1xuZnVuY3Rpb24gcmVtb3ZlKG5vZGUpIHtcbiAgdmFyIG5leHQgPSBub2RlLm5leHRTaWJsaW5nIHx8IG5vZGUucGFyZW50Tm9kZTtcblxuICBub2RlLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQobm9kZSk7XG5cbiAgcmV0dXJuIG5leHQ7XG59XG5cbi8qKlxuICogbmV4dChwcmV2LCBjdXJyZW50KSByZXR1cm5zIHRoZSBuZXh0IG5vZGUgaW4gdGhlIHNlcXVlbmNlLCBnaXZlbiB0aGVcbiAqIGN1cnJlbnQgYW5kIHByZXZpb3VzIG5vZGVzLlxuICpcbiAqIEBwYXJhbSB7Tm9kZX0gcHJldlxuICogQHBhcmFtIHtOb2RlfSBjdXJyZW50XG4gKiBAcmV0dXJuIHtOb2RlfVxuICovXG5mdW5jdGlvbiBuZXh0KHByZXYsIGN1cnJlbnQpIHtcbiAgaWYgKHByZXYgJiYgcHJldi5wYXJlbnROb2RlID09PSBjdXJyZW50IHx8IGN1cnJlbnQubm9kZU5hbWUgPT09ICdQUkUnKSB7XG4gICAgcmV0dXJuIGN1cnJlbnQubmV4dFNpYmxpbmcgfHwgY3VycmVudC5wYXJlbnROb2RlO1xuICB9XG5cbiAgcmV0dXJuIGN1cnJlbnQuZmlyc3RDaGlsZCB8fCBjdXJyZW50Lm5leHRTaWJsaW5nIHx8IGN1cnJlbnQucGFyZW50Tm9kZTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBjb2xsYXBzZVdoaXRlc3BhY2U7XG5cbn0se1wiYmxvY2stZWxlbWVudHNcIjo1LFwidm9pZC1lbGVtZW50c1wiOjh9XSw4OltmdW5jdGlvbihyZXF1aXJlLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuICogVGhpcyBmaWxlIGF1dG9tYXRpY2FsbHkgZ2VuZXJhdGVkIGZyb20gYHByZS1wdWJsaXNoLmpzYC5cbiAqIERvIG5vdCBtYW51YWxseSBlZGl0LlxuICovXG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICBcImFyZWFcIjogdHJ1ZSxcbiAgXCJiYXNlXCI6IHRydWUsXG4gIFwiYnJcIjogdHJ1ZSxcbiAgXCJjb2xcIjogdHJ1ZSxcbiAgXCJlbWJlZFwiOiB0cnVlLFxuICBcImhyXCI6IHRydWUsXG4gIFwiaW1nXCI6IHRydWUsXG4gIFwiaW5wdXRcIjogdHJ1ZSxcbiAgXCJrZXlnZW5cIjogdHJ1ZSxcbiAgXCJsaW5rXCI6IHRydWUsXG4gIFwibWVudWl0ZW1cIjogdHJ1ZSxcbiAgXCJtZXRhXCI6IHRydWUsXG4gIFwicGFyYW1cIjogdHJ1ZSxcbiAgXCJzb3VyY2VcIjogdHJ1ZSxcbiAgXCJ0cmFja1wiOiB0cnVlLFxuICBcIndiclwiOiB0cnVlXG59O1xuXG59LHt9XX0se30sWzFdKSgxKVxufSk7IiwiLyogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKiBib290c3RyYXAtbWFya2Rvd24uanMgdjIuMTAuMFxuICogaHR0cDovL2dpdGh1Yi5jb20vdG9vcGF5L2Jvb3RzdHJhcC1tYXJrZG93blxuICogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKiBDb3B5cmlnaHQgMjAxMy0yMDE2IFRhdWZhbiBBZGl0eWFcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0gKi9cblxuKGZ1bmN0aW9uKGZhY3Rvcnkpe1xuICAgIGlmICh0eXBlb2YgZGVmaW5lID09PSBcImZ1bmN0aW9uXCIgJiYgZGVmaW5lLmFtZCkge1xuICAgICAgICAvL1JlcXVpcmVKU1xuICAgICAgICBkZWZpbmUoW1wianF1ZXJ5XCJdLCBmYWN0b3J5KTtcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0Jykge1xuICAgICAgICAvL0JhY2tib25lLmpzXG4gICAgICAgIGZhY3RvcnkocmVxdWlyZSgnanF1ZXJ5JykpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIC8vSnF1ZXJ5IHBsdWdpblxuICAgICAgICBmYWN0b3J5KGpRdWVyeSk7XG4gICAgfVxufShmdW5jdGlvbigkKXtcbiAgXCJ1c2Ugc3RyaWN0XCI7IC8vIGpzaGludCA7XztcblxuICAvKiBNQVJLRE9XTiBDTEFTUyBERUZJTklUSU9OXG4gICAqID09PT09PT09PT09PT09PT09PT09PT09PT09ICovXG5cbiAgdmFyIE1hcmtkb3duID0gZnVuY3Rpb24gKGVsZW1lbnQsIG9wdGlvbnMpIHtcbiAgICAvLyBAVE9ETyA6IHJlbW92ZSB0aGlzIEJDIG9uIG5leHQgbWFqb3IgcmVsZWFzZVxuICAgIC8vIEBzZWUgOiBodHRwczovL2dpdGh1Yi5jb20vdG9vcGF5L2Jvb3RzdHJhcC1tYXJrZG93bi9pc3N1ZXMvMTA5XG4gICAgdmFyIG9wdHMgPSBbJ2F1dG9mb2N1cycsICdzYXZhYmxlJywgJ2hpZGVhYmxlJywgJ3dpZHRoJywgXG4gICAgICAnaGVpZ2h0JywgJ3Jlc2l6ZScsICdpY29ubGlicmFyeScsICdsYW5ndWFnZScsIFxuICAgICAgJ2Zvb3RlcicsICdmdWxsc2NyZWVuJywgJ2hpZGRlbkJ1dHRvbnMnLCAnZGlzYWJsZWRCdXR0b25zJ107XG4gICAgJC5lYWNoKG9wdHMsZnVuY3Rpb24oXywgb3B0KXtcbiAgICAgIGlmICh0eXBlb2YgJChlbGVtZW50KS5kYXRhKG9wdCkgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIG9wdGlvbnMgPSB0eXBlb2Ygb3B0aW9ucyA9PSAnb2JqZWN0JyA/IG9wdGlvbnMgOiB7fVxuICAgICAgICBvcHRpb25zW29wdF0gPSAkKGVsZW1lbnQpLmRhdGEob3B0KVxuICAgICAgfVxuICAgIH0pO1xuICAgIC8vIEVuZCBCQ1xuXG4gICAgLy8gQ2xhc3MgUHJvcGVydGllc1xuICAgIHRoaXMuJG5zICAgICAgICAgICA9ICdib290c3RyYXAtbWFya2Rvd24nO1xuICAgIHRoaXMuJGVsZW1lbnQgICAgICA9ICQoZWxlbWVudCk7XG4gICAgdGhpcy4kZWRpdGFibGUgICAgID0ge2VsOm51bGwsIHR5cGU6bnVsbCxhdHRyS2V5czpbXSwgYXR0clZhbHVlczpbXSwgY29udGVudDpudWxsfTtcbiAgICB0aGlzLiRvcHRpb25zICAgICAgPSAkLmV4dGVuZCh0cnVlLCB7fSwgJC5mbi5tYXJrZG93bi5kZWZhdWx0cywgb3B0aW9ucywgdGhpcy4kZWxlbWVudC5kYXRhKCdvcHRpb25zJykpO1xuICAgIHRoaXMuJG9sZENvbnRlbnQgICA9IG51bGw7XG4gICAgdGhpcy4kaXNQcmV2aWV3ICAgID0gZmFsc2U7XG4gICAgdGhpcy4kaXNGdWxsc2NyZWVuID0gZmFsc2U7XG4gICAgdGhpcy4kZWRpdG9yICAgICAgID0gbnVsbDtcbiAgICB0aGlzLiR0ZXh0YXJlYSAgICAgPSBudWxsO1xuICAgIHRoaXMuJGhhbmRsZXIgICAgICA9IFtdO1xuICAgIHRoaXMuJGNhbGxiYWNrICAgICA9IFtdO1xuICAgIHRoaXMuJG5leHRUYWIgICAgICA9IFtdO1xuXG4gICAgdGhpcy5zaG93RWRpdG9yKCk7XG4gIH07XG5cbiAgTWFya2Rvd24ucHJvdG90eXBlID0ge1xuXG4gICAgY29uc3RydWN0b3I6IE1hcmtkb3duXG5cbiAgLCBfX2FsdGVyQnV0dG9uczogZnVuY3Rpb24obmFtZSxhbHRlcikge1xuICAgICAgdmFyIGhhbmRsZXIgPSB0aGlzLiRoYW5kbGVyLCBpc0FsbCA9IChuYW1lID09ICdhbGwnKSx0aGF0ID0gdGhpcztcblxuICAgICAgJC5lYWNoKGhhbmRsZXIsZnVuY3Rpb24oayx2KSB7XG4gICAgICAgIHZhciBoYWx0ID0gdHJ1ZTtcbiAgICAgICAgaWYgKGlzQWxsKSB7XG4gICAgICAgICAgaGFsdCA9IGZhbHNlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGhhbHQgPSB2LmluZGV4T2YobmFtZSkgPCAwO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGhhbHQgPT09IGZhbHNlKSB7XG4gICAgICAgICAgYWx0ZXIodGhhdC4kZWRpdG9yLmZpbmQoJ2J1dHRvbltkYXRhLWhhbmRsZXI9XCInK3YrJ1wiXScpKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuXG4gICwgX19idWlsZEJ1dHRvbnM6IGZ1bmN0aW9uKGJ1dHRvbnNBcnJheSwgY29udGFpbmVyKSB7XG4gICAgICB2YXIgaSxcbiAgICAgICAgICBucyA9IHRoaXMuJG5zLFxuICAgICAgICAgIGhhbmRsZXIgPSB0aGlzLiRoYW5kbGVyLFxuICAgICAgICAgIGNhbGxiYWNrID0gdGhpcy4kY2FsbGJhY2s7XG5cbiAgICAgIGZvciAoaT0wO2k8YnV0dG9uc0FycmF5Lmxlbmd0aDtpKyspIHtcbiAgICAgICAgLy8gQnVpbGQgZWFjaCBncm91cCBjb250YWluZXJcbiAgICAgICAgdmFyIHksIGJ0bkdyb3VwcyA9IGJ1dHRvbnNBcnJheVtpXTtcbiAgICAgICAgZm9yICh5PTA7eTxidG5Hcm91cHMubGVuZ3RoO3krKykge1xuICAgICAgICAgIC8vIEJ1aWxkIGVhY2ggYnV0dG9uIGdyb3VwXG4gICAgICAgICAgdmFyIHosXG4gICAgICAgICAgICAgIGJ1dHRvbnMgPSBidG5Hcm91cHNbeV0uZGF0YSxcbiAgICAgICAgICAgICAgYnRuR3JvdXBDb250YWluZXIgPSAkKCc8ZGl2Lz4nLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnY2xhc3MnOiAnYnRuLWdyb3VwJ1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgZm9yICh6PTA7ejxidXR0b25zLmxlbmd0aDt6KyspIHtcbiAgICAgICAgICAgIHZhciBidXR0b24gPSBidXR0b25zW3pdLFxuICAgICAgICAgICAgICAgIGJ1dHRvbkNvbnRhaW5lciwgYnV0dG9uSWNvbkNvbnRhaW5lcixcbiAgICAgICAgICAgICAgICBidXR0b25IYW5kbGVyID0gbnMrJy0nK2J1dHRvbi5uYW1lLFxuICAgICAgICAgICAgICAgIGJ1dHRvbkljb24gPSB0aGlzLl9fZ2V0SWNvbihidXR0b24uaWNvbiksXG4gICAgICAgICAgICAgICAgYnRuVGV4dCA9IGJ1dHRvbi5idG5UZXh0ID8gYnV0dG9uLmJ0blRleHQgOiAnJyxcbiAgICAgICAgICAgICAgICBidG5DbGFzcyA9IGJ1dHRvbi5idG5DbGFzcyA/IGJ1dHRvbi5idG5DbGFzcyA6ICdidG4nLFxuICAgICAgICAgICAgICAgIHRhYkluZGV4ID0gYnV0dG9uLnRhYkluZGV4ID8gYnV0dG9uLnRhYkluZGV4IDogJy0xJyxcbiAgICAgICAgICAgICAgICBob3RrZXkgPSB0eXBlb2YgYnV0dG9uLmhvdGtleSAhPT0gJ3VuZGVmaW5lZCcgPyBidXR0b24uaG90a2V5IDogJycsXG4gICAgICAgICAgICAgICAgaG90a2V5Q2FwdGlvbiA9IHR5cGVvZiBqUXVlcnkuaG90a2V5cyAhPT0gJ3VuZGVmaW5lZCcgJiYgaG90a2V5ICE9PSAnJyA/ICcgKCcraG90a2V5KycpJyA6ICcnO1xuXG4gICAgICAgICAgICAvLyBDb25zdHJ1Y3QgdGhlIGJ1dHRvbiBvYmplY3RcbiAgICAgICAgICAgIGJ1dHRvbkNvbnRhaW5lciA9ICQoJzxidXR0b24+PC9idXR0b24+Jyk7XG4gICAgICAgICAgICBidXR0b25Db250YWluZXIudGV4dCgnICcgKyB0aGlzLl9fbG9jYWxpemUoYnRuVGV4dCkpLmFkZENsYXNzKCdidG4tZGVmYXVsdCBidG4tc20nKS5hZGRDbGFzcyhidG5DbGFzcyk7XG4gICAgICAgICAgICBpZihidG5DbGFzcy5tYXRjaCgvYnRuXFwtKHByaW1hcnl8c3VjY2Vzc3xpbmZvfHdhcm5pbmd8ZGFuZ2VyfGxpbmspLykpe1xuICAgICAgICAgICAgICAgIGJ1dHRvbkNvbnRhaW5lci5yZW1vdmVDbGFzcygnYnRuLWRlZmF1bHQnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJ1dHRvbkNvbnRhaW5lci5hdHRyKHtcbiAgICAgICAgICAgICAgICAndHlwZSc6ICdidXR0b24nLFxuICAgICAgICAgICAgICAgICd0aXRsZSc6IHRoaXMuX19sb2NhbGl6ZShidXR0b24udGl0bGUpICsgaG90a2V5Q2FwdGlvbixcbiAgICAgICAgICAgICAgICAndGFiaW5kZXgnOiB0YWJJbmRleCxcbiAgICAgICAgICAgICAgICAnZGF0YS1wcm92aWRlcic6IG5zLFxuICAgICAgICAgICAgICAgICdkYXRhLWhhbmRsZXInOiBidXR0b25IYW5kbGVyLFxuICAgICAgICAgICAgICAgICdkYXRhLWhvdGtleSc6IGhvdGtleVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBpZiAoYnV0dG9uLnRvZ2dsZSA9PT0gdHJ1ZSl7XG4gICAgICAgICAgICAgIGJ1dHRvbkNvbnRhaW5lci5hdHRyKCdkYXRhLXRvZ2dsZScsICdidXR0b24nKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJ1dHRvbkljb25Db250YWluZXIgPSAkKCc8c3Bhbi8+Jyk7XG4gICAgICAgICAgICBidXR0b25JY29uQ29udGFpbmVyLmFkZENsYXNzKGJ1dHRvbkljb24pO1xuICAgICAgICAgICAgYnV0dG9uSWNvbkNvbnRhaW5lci5wcmVwZW5kVG8oYnV0dG9uQ29udGFpbmVyKTtcblxuICAgICAgICAgICAgLy8gQXR0YWNoIHRoZSBidXR0b24gb2JqZWN0XG4gICAgICAgICAgICBidG5Hcm91cENvbnRhaW5lci5hcHBlbmQoYnV0dG9uQ29udGFpbmVyKTtcblxuICAgICAgICAgICAgLy8gUmVnaXN0ZXIgaGFuZGxlciBhbmQgY2FsbGJhY2tcbiAgICAgICAgICAgIGhhbmRsZXIucHVzaChidXR0b25IYW5kbGVyKTtcbiAgICAgICAgICAgIGNhbGxiYWNrLnB1c2goYnV0dG9uLmNhbGxiYWNrKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICAvLyBBdHRhY2ggdGhlIGJ1dHRvbiBncm91cCBpbnRvIGNvbnRhaW5lciBkb21cbiAgICAgICAgICBjb250YWluZXIuYXBwZW5kKGJ0bkdyb3VwQ29udGFpbmVyKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gY29udGFpbmVyO1xuICAgIH1cbiAgLCBfX3NldExpc3RlbmVyOiBmdW5jdGlvbigpIHtcbiAgICAgIC8vIFNldCBzaXplIGFuZCByZXNpemFibGUgUHJvcGVydGllc1xuICAgICAgdmFyIGhhc1Jvd3MgPSB0eXBlb2YgdGhpcy4kdGV4dGFyZWEuYXR0cigncm93cycpICE9PSAndW5kZWZpbmVkJyxcbiAgICAgICAgICBtYXhSb3dzID0gdGhpcy4kdGV4dGFyZWEudmFsKCkuc3BsaXQoXCJcXG5cIikubGVuZ3RoID4gNSA/IHRoaXMuJHRleHRhcmVhLnZhbCgpLnNwbGl0KFwiXFxuXCIpLmxlbmd0aCA6ICc1JyxcbiAgICAgICAgICByb3dzVmFsID0gaGFzUm93cyA/IHRoaXMuJHRleHRhcmVhLmF0dHIoJ3Jvd3MnKSA6IG1heFJvd3M7XG5cbiAgICAgIHRoaXMuJHRleHRhcmVhLmF0dHIoJ3Jvd3MnLHJvd3NWYWwpO1xuICAgICAgaWYgKHRoaXMuJG9wdGlvbnMucmVzaXplKSB7XG4gICAgICAgIHRoaXMuJHRleHRhcmVhLmNzcygncmVzaXplJyx0aGlzLiRvcHRpb25zLnJlc2l6ZSk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuJHRleHRhcmVhLm9uKHtcbiAgICAgICAgICAnZm9jdXMnIDogJC5wcm94eSh0aGlzLmZvY3VzLCB0aGlzKSxcbiAgICAgICAgICAna2V5dXAnIDogJC5wcm94eSh0aGlzLmtleXVwLCB0aGlzKSxcbiAgICAgICAgICAnY2hhbmdlJyA6ICQucHJveHkodGhpcy5jaGFuZ2UsIHRoaXMpLFxuICAgICAgICAgICdzZWxlY3QnIDogJC5wcm94eSh0aGlzLnNlbGVjdCwgdGhpcylcbiAgICAgIH0pO1xuXG4gICAgICBpZiAodGhpcy5ldmVudFN1cHBvcnRlZCgna2V5ZG93bicpKSB7XG4gICAgICAgIHRoaXMuJHRleHRhcmVhLm9uKCdrZXlkb3duJywgJC5wcm94eSh0aGlzLmtleWRvd24sIHRoaXMpKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHRoaXMuZXZlbnRTdXBwb3J0ZWQoJ2tleXByZXNzJykpIHtcbiAgICAgICAgdGhpcy4kdGV4dGFyZWEub24oJ2tleXByZXNzJywgJC5wcm94eSh0aGlzLmtleXByZXNzLCB0aGlzKSlcbiAgICAgIH1cblxuICAgICAgLy8gUmUtYXR0YWNoIG1hcmtkb3duIGRhdGFcbiAgICAgIHRoaXMuJHRleHRhcmVhLmRhdGEoJ21hcmtkb3duJyx0aGlzKTtcbiAgICB9XG5cbiAgLCBfX2hhbmRsZTogZnVuY3Rpb24oZSkge1xuICAgICAgdmFyIHRhcmdldCA9ICQoZS5jdXJyZW50VGFyZ2V0KSxcbiAgICAgICAgICBoYW5kbGVyID0gdGhpcy4kaGFuZGxlcixcbiAgICAgICAgICBjYWxsYmFjayA9IHRoaXMuJGNhbGxiYWNrLFxuICAgICAgICAgIGhhbmRsZXJOYW1lID0gdGFyZ2V0LmF0dHIoJ2RhdGEtaGFuZGxlcicpLFxuICAgICAgICAgIGNhbGxiYWNrSW5kZXggPSBoYW5kbGVyLmluZGV4T2YoaGFuZGxlck5hbWUpLFxuICAgICAgICAgIGNhbGxiYWNrSGFuZGxlciA9IGNhbGxiYWNrW2NhbGxiYWNrSW5kZXhdO1xuXG4gICAgICAvLyBUcmlnZ2VyIHRoZSBmb2N1c2luXG4gICAgICAkKGUuY3VycmVudFRhcmdldCkuZm9jdXMoKTtcblxuICAgICAgY2FsbGJhY2tIYW5kbGVyKHRoaXMpO1xuXG4gICAgICAvLyBUcmlnZ2VyIG9uQ2hhbmdlIGZvciBlYWNoIGJ1dHRvbiBoYW5kbGVcbiAgICAgIHRoaXMuY2hhbmdlKHRoaXMpO1xuXG4gICAgICAvLyBVbmxlc3MgaXQgd2FzIHRoZSBzYXZlIGhhbmRsZXIsXG4gICAgICAvLyBmb2N1c2luIHRoZSB0ZXh0YXJlYVxuICAgICAgaWYgKGhhbmRsZXJOYW1lLmluZGV4T2YoJ2NtZFNhdmUnKSA8IDApIHtcbiAgICAgICAgdGhpcy4kdGV4dGFyZWEuZm9jdXMoKTtcbiAgICAgIH1cblxuICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIH1cblxuICAsIF9fbG9jYWxpemU6IGZ1bmN0aW9uKHN0cmluZykge1xuICAgICAgdmFyIG1lc3NhZ2VzID0gJC5mbi5tYXJrZG93bi5tZXNzYWdlcyxcbiAgICAgICAgICBsYW5ndWFnZSA9IHRoaXMuJG9wdGlvbnMubGFuZ3VhZ2U7XG4gICAgICBpZiAoXG4gICAgICAgIHR5cGVvZiBtZXNzYWdlcyAhPT0gJ3VuZGVmaW5lZCcgJiZcbiAgICAgICAgdHlwZW9mIG1lc3NhZ2VzW2xhbmd1YWdlXSAhPT0gJ3VuZGVmaW5lZCcgJiZcbiAgICAgICAgdHlwZW9mIG1lc3NhZ2VzW2xhbmd1YWdlXVtzdHJpbmddICE9PSAndW5kZWZpbmVkJ1xuICAgICAgKSB7XG4gICAgICAgIHJldHVybiBtZXNzYWdlc1tsYW5ndWFnZV1bc3RyaW5nXTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBzdHJpbmc7XG4gICAgfVxuXG4gICwgX19nZXRJY29uOiBmdW5jdGlvbihzcmMpIHtcbiAgICByZXR1cm4gdHlwZW9mIHNyYyA9PSAnb2JqZWN0JyA/IHNyY1t0aGlzLiRvcHRpb25zLmljb25saWJyYXJ5XSA6IHNyYztcbiAgfVxuXG4gICwgc2V0RnVsbHNjcmVlbjogZnVuY3Rpb24obW9kZSkge1xuICAgIHZhciAkZWRpdG9yID0gdGhpcy4kZWRpdG9yLFxuICAgICAgICAkdGV4dGFyZWEgPSB0aGlzLiR0ZXh0YXJlYTtcblxuICAgIGlmIChtb2RlID09PSB0cnVlKSB7XG4gICAgICAkZWRpdG9yLmFkZENsYXNzKCdtZC1mdWxsc2NyZWVuLW1vZGUnKTtcbiAgICAgICQoJ2JvZHknKS5hZGRDbGFzcygnbWQtbm9vdmVyZmxvdycpO1xuICAgICAgdGhpcy4kb3B0aW9ucy5vbkZ1bGxzY3JlZW4odGhpcyk7XG4gICAgfSBlbHNlIHtcbiAgICAgICRlZGl0b3IucmVtb3ZlQ2xhc3MoJ21kLWZ1bGxzY3JlZW4tbW9kZScpO1xuICAgICAgJCgnYm9keScpLnJlbW92ZUNsYXNzKCdtZC1ub292ZXJmbG93Jyk7XG5cbiAgICAgIGlmICh0aGlzLiRpc1ByZXZpZXcgPT0gdHJ1ZSkgdGhpcy5oaWRlUHJldmlldygpLnNob3dQcmV2aWV3KClcbiAgICB9XG5cbiAgICB0aGlzLiRpc0Z1bGxzY3JlZW4gPSBtb2RlO1xuICAgICR0ZXh0YXJlYS5mb2N1cygpO1xuICB9XG5cbiAgLCBzaG93RWRpdG9yOiBmdW5jdGlvbigpIHtcbiAgICAgIHZhciBpbnN0YW5jZSA9IHRoaXMsXG4gICAgICAgICAgdGV4dGFyZWEsXG4gICAgICAgICAgbnMgPSB0aGlzLiRucyxcbiAgICAgICAgICBjb250YWluZXIgPSB0aGlzLiRlbGVtZW50LFxuICAgICAgICAgIG9yaWdpbmFsSGVpZ3RoID0gY29udGFpbmVyLmNzcygnaGVpZ2h0JyksXG4gICAgICAgICAgb3JpZ2luYWxXaWR0aCA9IGNvbnRhaW5lci5jc3MoJ3dpZHRoJyksXG4gICAgICAgICAgZWRpdGFibGUgPSB0aGlzLiRlZGl0YWJsZSxcbiAgICAgICAgICBoYW5kbGVyID0gdGhpcy4kaGFuZGxlcixcbiAgICAgICAgICBjYWxsYmFjayA9IHRoaXMuJGNhbGxiYWNrLFxuICAgICAgICAgIG9wdGlvbnMgPSB0aGlzLiRvcHRpb25zLFxuICAgICAgICAgIGVkaXRvciA9ICQoICc8ZGl2Lz4nLCB7XG4gICAgICAgICAgICAgICAgICAgICAgJ2NsYXNzJzogJ21kLWVkaXRvcicsXG4gICAgICAgICAgICAgICAgICAgICAgY2xpY2s6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5zdGFuY2UuZm9jdXMoKTtcbiAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAvLyBQcmVwYXJlIHRoZSBlZGl0b3JcbiAgICAgIGlmICh0aGlzLiRlZGl0b3IgPT09IG51bGwpIHtcbiAgICAgICAgLy8gQ3JlYXRlIHRoZSBwYW5lbFxuICAgICAgICB2YXIgZWRpdG9ySGVhZGVyID0gJCgnPGRpdi8+Jywge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdjbGFzcyc6ICdtZC1oZWFkZXIgYnRuLXRvb2xiYXInXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gTWVyZ2UgdGhlIG1haW4gJiBhZGRpdGlvbmFsIGJ1dHRvbiBncm91cHMgdG9nZXRoZXJcbiAgICAgICAgdmFyIGFsbEJ0bkdyb3VwcyA9IFtdO1xuICAgICAgICBpZiAob3B0aW9ucy5idXR0b25zLmxlbmd0aCA+IDApIGFsbEJ0bkdyb3VwcyA9IGFsbEJ0bkdyb3Vwcy5jb25jYXQob3B0aW9ucy5idXR0b25zWzBdKTtcbiAgICAgICAgaWYgKG9wdGlvbnMuYWRkaXRpb25hbEJ1dHRvbnMubGVuZ3RoID4gMCkge1xuICAgICAgICAgIC8vIGl0ZXJhdGUgdGhlIGFkZGl0aW9uYWwgYnV0dG9uIGdyb3Vwc1xuICAgICAgICAgICQuZWFjaChvcHRpb25zLmFkZGl0aW9uYWxCdXR0b25zWzBdLCBmdW5jdGlvbihpZHgsIGJ1dHRvbkdyb3VwKXtcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgLy8gc2VlIGlmIHRoZSBncm91cCBuYW1lIG9mIHRoZSBhZGRpb25hbCBncm91cCBtYXRjaGVzIGFuIGV4aXN0aW5nIGdyb3VwXG4gICAgICAgICAgICB2YXIgbWF0Y2hpbmdHcm91cHMgPSAkLmdyZXAoYWxsQnRuR3JvdXBzLCBmdW5jdGlvbihhbGxCdXR0b25Hcm91cCwgYWxsSWR4KXtcbiAgICAgICAgICAgICAgcmV0dXJuIGFsbEJ1dHRvbkdyb3VwLm5hbWUgPT09IGJ1dHRvbkdyb3VwLm5hbWU7XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgLy8gaWYgaXQgbWF0Y2hlcyBhZGQgdGhlIGFkZGlvbmFsIGJ1dHRvbnMgdG8gdGhhdCBncm91cCwgaWYgbm90IGp1c3QgYWRkIGl0IHRvIHRoZSBhbGwgYnV0dG9ucyBncm91cFxuICAgICAgICAgICAgaWYobWF0Y2hpbmdHcm91cHMubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICBtYXRjaGluZ0dyb3Vwc1swXS5kYXRhID0gbWF0Y2hpbmdHcm91cHNbMF0uZGF0YS5jb25jYXQoYnV0dG9uR3JvdXAuZGF0YSk7XG4gICAgICAgICAgICB9IGVsc2UgeyAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgIGFsbEJ0bkdyb3Vwcy5wdXNoKG9wdGlvbnMuYWRkaXRpb25hbEJ1dHRvbnNbMF1baWR4XSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICB9KTtcbiAgICAgICAgfSBcblxuICAgICAgICAvLyBSZWR1Y2UgYW5kL29yIHJlb3JkZXIgdGhlIGJ1dHRvbiBncm91cHNcbiAgICAgICAgaWYgKG9wdGlvbnMucmVvcmRlckJ1dHRvbkdyb3Vwcy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgYWxsQnRuR3JvdXBzID0gYWxsQnRuR3JvdXBzXG4gICAgICAgICAgICAgIC5maWx0ZXIoZnVuY3Rpb24oYnRuR3JvdXApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gb3B0aW9ucy5yZW9yZGVyQnV0dG9uR3JvdXBzLmluZGV4T2YoYnRuR3JvdXAubmFtZSkgPiAtMTtcbiAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgLnNvcnQoZnVuY3Rpb24oYSwgYikge1xuICAgICAgICAgICAgICAgIGlmIChvcHRpb25zLnJlb3JkZXJCdXR0b25Hcm91cHMuaW5kZXhPZihhLm5hbWUpIDwgb3B0aW9ucy5yZW9yZGVyQnV0dG9uR3JvdXBzLmluZGV4T2YoYi5uYW1lKSkgcmV0dXJuIC0xO1xuICAgICAgICAgICAgICAgIGlmIChvcHRpb25zLnJlb3JkZXJCdXR0b25Hcm91cHMuaW5kZXhPZihhLm5hbWUpID4gb3B0aW9ucy5yZW9yZGVyQnV0dG9uR3JvdXBzLmluZGV4T2YoYi5uYW1lKSkgcmV0dXJuIDE7XG4gICAgICAgICAgICAgICAgcmV0dXJuIDA7XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQnVpbGQgdGhlIGJ1dHRvbnNcbiAgICAgICAgaWYgKGFsbEJ0bkdyb3Vwcy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgZWRpdG9ySGVhZGVyID0gdGhpcy5fX2J1aWxkQnV0dG9ucyhbYWxsQnRuR3JvdXBzXSwgZWRpdG9ySGVhZGVyKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChvcHRpb25zLmZ1bGxzY3JlZW4uZW5hYmxlKSB7XG4gICAgICAgICAgZWRpdG9ySGVhZGVyLmFwcGVuZCgnPGRpdiBjbGFzcz1cIm1kLWNvbnRyb2xzXCI+PGEgY2xhc3M9XCJtZC1jb250cm9sIG1kLWNvbnRyb2wtZnVsbHNjcmVlblwiIGhyZWY9XCIjXCI+PHNwYW4gY2xhc3M9XCInK3RoaXMuX19nZXRJY29uKG9wdGlvbnMuZnVsbHNjcmVlbi5pY29ucy5mdWxsc2NyZWVuT24pKydcIj48L3NwYW4+PC9hPjwvZGl2PicpLm9uKCdjbGljaycsICcubWQtY29udHJvbC1mdWxsc2NyZWVuJywgZnVuY3Rpb24oZSkge1xuICAgICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAgIGluc3RhbmNlLnNldEZ1bGxzY3JlZW4odHJ1ZSk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICBlZGl0b3IuYXBwZW5kKGVkaXRvckhlYWRlcik7XG5cbiAgICAgICAgLy8gV3JhcCB0aGUgdGV4dGFyZWFcbiAgICAgICAgaWYgKGNvbnRhaW5lci5pcygndGV4dGFyZWEnKSkge1xuICAgICAgICAgIGNvbnRhaW5lci5iZWZvcmUoZWRpdG9yKTtcbiAgICAgICAgICB0ZXh0YXJlYSA9IGNvbnRhaW5lcjtcbiAgICAgICAgICB0ZXh0YXJlYS5hZGRDbGFzcygnbWQtaW5wdXQnKTtcbiAgICAgICAgICBlZGl0b3IuYXBwZW5kKHRleHRhcmVhKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB2YXIgcmF3Q29udGVudCA9ICh0eXBlb2YgdG9NYXJrZG93biA9PSAnZnVuY3Rpb24nKSA/IHRvTWFya2Rvd24oY29udGFpbmVyLmh0bWwoKSkgOiBjb250YWluZXIuaHRtbCgpLFxuICAgICAgICAgICAgICBjdXJyZW50Q29udGVudCA9ICQudHJpbShyYXdDb250ZW50KTtcblxuICAgICAgICAgIC8vIFRoaXMgaXMgc29tZSBhcmJpdHJhcnkgY29udGVudCB0aGF0IGNvdWxkIGJlIGVkaXRlZFxuICAgICAgICAgIHRleHRhcmVhID0gJCgnPHRleHRhcmVhLz4nLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICdjbGFzcyc6ICdtZC1pbnB1dCcsXG4gICAgICAgICAgICAgICAgICAgICAgICd2YWwnIDogY3VycmVudENvbnRlbnRcbiAgICAgICAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgIGVkaXRvci5hcHBlbmQodGV4dGFyZWEpO1xuXG4gICAgICAgICAgLy8gU2F2ZSB0aGUgZWRpdGFibGVcbiAgICAgICAgICBlZGl0YWJsZS5lbCA9IGNvbnRhaW5lcjtcbiAgICAgICAgICBlZGl0YWJsZS50eXBlID0gY29udGFpbmVyLnByb3AoJ3RhZ05hbWUnKS50b0xvd2VyQ2FzZSgpO1xuICAgICAgICAgIGVkaXRhYmxlLmNvbnRlbnQgPSBjb250YWluZXIuaHRtbCgpO1xuXG4gICAgICAgICAgJChjb250YWluZXJbMF0uYXR0cmlidXRlcykuZWFjaChmdW5jdGlvbigpe1xuICAgICAgICAgICAgZWRpdGFibGUuYXR0cktleXMucHVzaCh0aGlzLm5vZGVOYW1lKTtcbiAgICAgICAgICAgIGVkaXRhYmxlLmF0dHJWYWx1ZXMucHVzaCh0aGlzLm5vZGVWYWx1ZSk7XG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICAvLyBTZXQgZWRpdG9yIHRvIGJsb2NrZWQgdGhlIG9yaWdpbmFsIGNvbnRhaW5lclxuICAgICAgICAgIGNvbnRhaW5lci5yZXBsYWNlV2l0aChlZGl0b3IpO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGVkaXRvckZvb3RlciA9ICQoJzxkaXYvPicsIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICdjbGFzcyc6ICdtZC1mb290ZXInXG4gICAgICAgICAgICAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICBjcmVhdGVGb290ZXIgPSBmYWxzZSxcbiAgICAgICAgICAgIGZvb3RlciA9ICcnO1xuICAgICAgICAvLyBDcmVhdGUgdGhlIGZvb3RlciBpZiBzYXZhYmxlXG4gICAgICAgIGlmIChvcHRpb25zLnNhdmFibGUpIHtcbiAgICAgICAgICBjcmVhdGVGb290ZXIgPSB0cnVlO1xuICAgICAgICAgIHZhciBzYXZlSGFuZGxlciA9ICdjbWRTYXZlJztcblxuICAgICAgICAgIC8vIFJlZ2lzdGVyIGhhbmRsZXIgYW5kIGNhbGxiYWNrXG4gICAgICAgICAgaGFuZGxlci5wdXNoKHNhdmVIYW5kbGVyKTtcbiAgICAgICAgICBjYWxsYmFjay5wdXNoKG9wdGlvbnMub25TYXZlKTtcblxuICAgICAgICAgIGVkaXRvckZvb3Rlci5hcHBlbmQoJzxidXR0b24gY2xhc3M9XCJidG4gYnRuLXN1Y2Nlc3NcIiBkYXRhLXByb3ZpZGVyPVwiJ1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKyBuc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKyAnXCIgZGF0YS1oYW5kbGVyPVwiJ1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKyBzYXZlSGFuZGxlclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKyAnXCI+PGkgY2xhc3M9XCJpY29uIGljb24td2hpdGUgaWNvbi1va1wiPjwvaT4gJ1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKyB0aGlzLl9fbG9jYWxpemUoJ1NhdmUnKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKyAnPC9idXR0b24+Jyk7XG5cblxuICAgICAgICB9XG5cbiAgICAgICAgZm9vdGVyID0gdHlwZW9mIG9wdGlvbnMuZm9vdGVyID09PSAnZnVuY3Rpb24nID8gb3B0aW9ucy5mb290ZXIodGhpcykgOiBvcHRpb25zLmZvb3RlcjtcblxuICAgICAgICBpZiAoJC50cmltKGZvb3RlcikgIT09ICcnKSB7XG4gICAgICAgICAgY3JlYXRlRm9vdGVyID0gdHJ1ZTtcbiAgICAgICAgICBlZGl0b3JGb290ZXIuYXBwZW5kKGZvb3Rlcik7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoY3JlYXRlRm9vdGVyKSBlZGl0b3IuYXBwZW5kKGVkaXRvckZvb3Rlcik7XG5cbiAgICAgICAgLy8gU2V0IHdpZHRoXG4gICAgICAgIGlmIChvcHRpb25zLndpZHRoICYmIG9wdGlvbnMud2lkdGggIT09ICdpbmhlcml0Jykge1xuICAgICAgICAgIGlmIChqUXVlcnkuaXNOdW1lcmljKG9wdGlvbnMud2lkdGgpKSB7XG4gICAgICAgICAgICBlZGl0b3IuY3NzKCdkaXNwbGF5JywgJ3RhYmxlJyk7XG4gICAgICAgICAgICB0ZXh0YXJlYS5jc3MoJ3dpZHRoJywgb3B0aW9ucy53aWR0aCArICdweCcpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBlZGl0b3IuYWRkQ2xhc3Mob3B0aW9ucy53aWR0aCk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gU2V0IGhlaWdodFxuICAgICAgICBpZiAob3B0aW9ucy5oZWlnaHQgJiYgb3B0aW9ucy5oZWlnaHQgIT09ICdpbmhlcml0Jykge1xuICAgICAgICAgIGlmIChqUXVlcnkuaXNOdW1lcmljKG9wdGlvbnMuaGVpZ2h0KSkge1xuICAgICAgICAgICAgdmFyIGhlaWdodCA9IG9wdGlvbnMuaGVpZ2h0O1xuICAgICAgICAgICAgaWYgKGVkaXRvckhlYWRlcikgaGVpZ2h0ID0gTWF0aC5tYXgoMCwgaGVpZ2h0IC0gZWRpdG9ySGVhZGVyLm91dGVySGVpZ2h0KCkpO1xuICAgICAgICAgICAgaWYgKGVkaXRvckZvb3RlcikgaGVpZ2h0ID0gTWF0aC5tYXgoMCwgaGVpZ2h0IC0gZWRpdG9yRm9vdGVyLm91dGVySGVpZ2h0KCkpO1xuICAgICAgICAgICAgdGV4dGFyZWEuY3NzKCdoZWlnaHQnLCBoZWlnaHQgKyAncHgnKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZWRpdG9yLmFkZENsYXNzKG9wdGlvbnMuaGVpZ2h0KTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBSZWZlcmVuY2VcbiAgICAgICAgdGhpcy4kZWRpdG9yICAgICA9IGVkaXRvcjtcbiAgICAgICAgdGhpcy4kdGV4dGFyZWEgICA9IHRleHRhcmVhO1xuICAgICAgICB0aGlzLiRlZGl0YWJsZSAgID0gZWRpdGFibGU7XG4gICAgICAgIHRoaXMuJG9sZENvbnRlbnQgPSB0aGlzLmdldENvbnRlbnQoKTtcblxuICAgICAgICB0aGlzLl9fc2V0TGlzdGVuZXIoKTtcblxuICAgICAgICAvLyBTZXQgZWRpdG9yIGF0dHJpYnV0ZXMsIGRhdGEgc2hvcnQtaGFuZCBBUEkgYW5kIGxpc3RlbmVyXG4gICAgICAgIHRoaXMuJGVkaXRvci5hdHRyKCdpZCcsKG5ldyBEYXRlKCkpLmdldFRpbWUoKSk7XG4gICAgICAgIHRoaXMuJGVkaXRvci5vbignY2xpY2snLCAnW2RhdGEtcHJvdmlkZXI9XCJib290c3RyYXAtbWFya2Rvd25cIl0nLCAkLnByb3h5KHRoaXMuX19oYW5kbGUsIHRoaXMpKTtcblxuICAgICAgICBpZiAodGhpcy4kZWxlbWVudC5pcygnOmRpc2FibGVkJykgfHwgdGhpcy4kZWxlbWVudC5pcygnW3JlYWRvbmx5XScpKSB7XG4gICAgICAgICAgdGhpcy4kZWRpdG9yLmFkZENsYXNzKCdtZC1lZGl0b3ItZGlzYWJsZWQnKTtcbiAgICAgICAgICB0aGlzLmRpc2FibGVCdXR0b25zKCdhbGwnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLmV2ZW50U3VwcG9ydGVkKCdrZXlkb3duJykgJiYgdHlwZW9mIGpRdWVyeS5ob3RrZXlzID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgIGVkaXRvckhlYWRlci5maW5kKCdbZGF0YS1wcm92aWRlcj1cImJvb3RzdHJhcC1tYXJrZG93blwiXScpLmVhY2goZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICB2YXIgJGJ1dHRvbiA9ICQodGhpcyksXG4gICAgICAgICAgICAgICAgaG90a2V5ID0gJGJ1dHRvbi5hdHRyKCdkYXRhLWhvdGtleScpO1xuICAgICAgICAgICAgaWYgKGhvdGtleS50b0xvd2VyQ2FzZSgpICE9PSAnJykge1xuICAgICAgICAgICAgICB0ZXh0YXJlYS5iaW5kKCdrZXlkb3duJywgaG90a2V5LCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAkYnV0dG9uLnRyaWdnZXIoJ2NsaWNrJyk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChvcHRpb25zLmluaXRpYWxzdGF0ZSA9PT0gJ3ByZXZpZXcnKSB7XG4gICAgICAgICAgdGhpcy5zaG93UHJldmlldygpO1xuICAgICAgICB9IGVsc2UgaWYgKG9wdGlvbnMuaW5pdGlhbHN0YXRlID09PSAnZnVsbHNjcmVlbicgJiYgb3B0aW9ucy5mdWxsc2NyZWVuLmVuYWJsZSkge1xuICAgICAgICAgIHRoaXMuc2V0RnVsbHNjcmVlbih0cnVlKTtcbiAgICAgICAgfVxuXG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLiRlZGl0b3Iuc2hvdygpO1xuICAgICAgfVxuXG4gICAgICBpZiAob3B0aW9ucy5hdXRvZm9jdXMpIHtcbiAgICAgICAgdGhpcy4kdGV4dGFyZWEuZm9jdXMoKTtcbiAgICAgICAgdGhpcy4kZWRpdG9yLmFkZENsYXNzKCdhY3RpdmUnKTtcbiAgICAgIH1cblxuICAgICAgaWYgKG9wdGlvbnMuZnVsbHNjcmVlbi5lbmFibGUgJiYgb3B0aW9ucy5mdWxsc2NyZWVuICE9PSBmYWxzZSkge1xuICAgICAgICB0aGlzLiRlZGl0b3IuYXBwZW5kKCc8ZGl2IGNsYXNzPVwibWQtZnVsbHNjcmVlbi1jb250cm9sc1wiPidcbiAgICAgICAgICAgICAgICAgICAgICAgICsgJzxhIGhyZWY9XCIjXCIgY2xhc3M9XCJleGl0LWZ1bGxzY3JlZW5cIiB0aXRsZT1cIkV4aXQgZnVsbHNjcmVlblwiPjxzcGFuIGNsYXNzPVwiJyArIHRoaXMuX19nZXRJY29uKG9wdGlvbnMuZnVsbHNjcmVlbi5pY29ucy5mdWxsc2NyZWVuT2ZmKSArICdcIj4nXG4gICAgICAgICAgICAgICAgICAgICAgICArICc8L3NwYW4+PC9hPidcbiAgICAgICAgICAgICAgICAgICAgICAgICsgJzwvZGl2PicpO1xuICAgICAgICB0aGlzLiRlZGl0b3Iub24oJ2NsaWNrJywgJy5leGl0LWZ1bGxzY3JlZW4nLCBmdW5jdGlvbihlKSB7XG4gICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgIGluc3RhbmNlLnNldEZ1bGxzY3JlZW4oZmFsc2UpO1xuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgLy8gaGlkZSBoaWRkZW4gYnV0dG9ucyBmcm9tIG9wdGlvbnNcbiAgICAgIHRoaXMuaGlkZUJ1dHRvbnMob3B0aW9ucy5oaWRkZW5CdXR0b25zKTtcblxuICAgICAgLy8gZGlzYWJsZSBkaXNhYmxlZCBidXR0b25zIGZyb20gb3B0aW9uc1xuICAgICAgdGhpcy5kaXNhYmxlQnV0dG9ucyhvcHRpb25zLmRpc2FibGVkQnV0dG9ucyk7XG5cbiAgICAgIC8vIFRyaWdnZXIgdGhlIG9uU2hvdyBob29rXG4gICAgICBvcHRpb25zLm9uU2hvdyh0aGlzKTtcblxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICwgcGFyc2VDb250ZW50OiBmdW5jdGlvbih2YWwpIHtcbiAgICAgIHZhciBjb250ZW50O1xuXG4gICAgICAvLyBwYXJzZSB3aXRoIHN1cHBvcnRlZCBtYXJrZG93biBwYXJzZXJcbiAgICAgIHZhciB2YWwgPSB2YWwgfHwgdGhpcy4kdGV4dGFyZWEudmFsKCk7XG5cbiAgICAgIGlmICh0aGlzLiRvcHRpb25zLnBhcnNlcikge1xuICAgICAgICBjb250ZW50ID0gdGhpcy4kb3B0aW9ucy5wYXJzZXIodmFsKTtcbiAgICAgIH0gZWxzZSBpZiAodHlwZW9mIG1hcmtkb3duID09ICdvYmplY3QnKSB7XG4gICAgICAgIGNvbnRlbnQgPSBtYXJrZG93bi50b0hUTUwodmFsKTtcbiAgICAgIH0gZWxzZSBpZiAodHlwZW9mIG1hcmtlZCA9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIGNvbnRlbnQgPSBtYXJrZWQodmFsKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnRlbnQgPSB2YWw7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBjb250ZW50O1xuICAgIH1cblxuICAsIHNob3dQcmV2aWV3OiBmdW5jdGlvbigpIHtcbiAgICAgIHZhciBvcHRpb25zID0gdGhpcy4kb3B0aW9ucyxcbiAgICAgICAgICBjb250YWluZXIgPSB0aGlzLiR0ZXh0YXJlYSxcbiAgICAgICAgICBhZnRlckNvbnRhaW5lciA9IGNvbnRhaW5lci5uZXh0KCksXG4gICAgICAgICAgcmVwbGFjZW1lbnRDb250YWluZXIgPSAkKCc8ZGl2Lz4nLHsnY2xhc3MnOidtZC1wcmV2aWV3JywnZGF0YS1wcm92aWRlcic6J21hcmtkb3duLXByZXZpZXcnfSksXG4gICAgICAgICAgY29udGVudCxcbiAgICAgICAgICBjYWxsYmFja0NvbnRlbnQ7XG5cbiAgICAgIGlmICh0aGlzLiRpc1ByZXZpZXcgPT0gdHJ1ZSkge1xuICAgICAgICAvLyBBdm9pZCBzZXF1ZW5jZWQgZWxlbWVudCBjcmVhdGlvbiBvbiBtaXNzdXNlZCBzY2VuYXJpb1xuICAgICAgICAvLyBAc2VlIGh0dHBzOi8vZ2l0aHViLmNvbS90b29wYXkvYm9vdHN0cmFwLW1hcmtkb3duL2lzc3Vlcy8xNzBcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICB9XG4gICAgICBcbiAgICAgIC8vIEdpdmUgZmxhZyB0aGF0IHRlbGwgdGhlIGVkaXRvciBlbnRlciBwcmV2aWV3IG1vZGVcbiAgICAgIHRoaXMuJGlzUHJldmlldyA9IHRydWU7XG4gICAgICAvLyBEaXNhYmxlIGFsbCBidXR0b25zXG4gICAgICB0aGlzLmRpc2FibGVCdXR0b25zKCdhbGwnKS5lbmFibGVCdXR0b25zKCdjbWRQcmV2aWV3Jyk7XG5cbiAgICAgIC8vIFRyeSB0byBnZXQgdGhlIGNvbnRlbnQgZnJvbSBjYWxsYmFja1xuICAgICAgY2FsbGJhY2tDb250ZW50ID0gb3B0aW9ucy5vblByZXZpZXcodGhpcyk7XG4gICAgICAvLyBTZXQgdGhlIGNvbnRlbnQgYmFzZWQgZnJvbSB0aGUgY2FsbGJhY2sgY29udGVudCBpZiBzdHJpbmcgb3RoZXJ3aXNlIHBhcnNlIHZhbHVlIGZyb20gdGV4dGFyZWFcbiAgICAgIGNvbnRlbnQgPSB0eXBlb2YgY2FsbGJhY2tDb250ZW50ID09ICdzdHJpbmcnID8gY2FsbGJhY2tDb250ZW50IDogdGhpcy5wYXJzZUNvbnRlbnQoKTtcblxuICAgICAgLy8gQnVpbGQgcHJldmlldyBlbGVtZW50XG4gICAgICByZXBsYWNlbWVudENvbnRhaW5lci5odG1sKGNvbnRlbnQpO1xuXG4gICAgICBpZiAoYWZ0ZXJDb250YWluZXIgJiYgYWZ0ZXJDb250YWluZXIuYXR0cignY2xhc3MnKSA9PSAnbWQtZm9vdGVyJykge1xuICAgICAgICAvLyBJZiB0aGVyZSBpcyBmb290ZXIgZWxlbWVudCwgaW5zZXJ0IHRoZSBwcmV2aWV3IGNvbnRhaW5lciBiZWZvcmUgaXRcbiAgICAgICAgcmVwbGFjZW1lbnRDb250YWluZXIuaW5zZXJ0QmVmb3JlKGFmdGVyQ29udGFpbmVyKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIE90aGVyd2lzZSwganVzdCBhcHBlbmQgaXQgYWZ0ZXIgdGV4dGFyZWFcbiAgICAgICAgY29udGFpbmVyLnBhcmVudCgpLmFwcGVuZChyZXBsYWNlbWVudENvbnRhaW5lcik7XG4gICAgICB9XG5cbiAgICAgIC8vIFNldCB0aGUgcHJldmlldyBlbGVtZW50IGRpbWVuc2lvbnNcbiAgICAgIHJlcGxhY2VtZW50Q29udGFpbmVyLmNzcyh7XG4gICAgICAgIHdpZHRoOiBjb250YWluZXIub3V0ZXJXaWR0aCgpICsgJ3B4JyxcbiAgICAgICAgaGVpZ2h0OiBjb250YWluZXIub3V0ZXJIZWlnaHQoKSArICdweCdcbiAgICAgIH0pO1xuXG4gICAgICBpZiAodGhpcy4kb3B0aW9ucy5yZXNpemUpIHtcbiAgICAgICAgcmVwbGFjZW1lbnRDb250YWluZXIuY3NzKCdyZXNpemUnLHRoaXMuJG9wdGlvbnMucmVzaXplKTtcbiAgICAgIH1cblxuICAgICAgLy8gSGlkZSB0aGUgbGFzdC1hY3RpdmUgdGV4dGFyZWFcbiAgICAgIGNvbnRhaW5lci5oaWRlKCk7XG5cbiAgICAgIC8vIEF0dGFjaCB0aGUgZWRpdG9yIGluc3RhbmNlc1xuICAgICAgcmVwbGFjZW1lbnRDb250YWluZXIuZGF0YSgnbWFya2Rvd24nLHRoaXMpO1xuXG4gICAgICBpZiAodGhpcy4kZWxlbWVudC5pcygnOmRpc2FibGVkJykgfHwgdGhpcy4kZWxlbWVudC5pcygnW3JlYWRvbmx5XScpKSB7XG4gICAgICAgIHRoaXMuJGVkaXRvci5hZGRDbGFzcygnbWQtZWRpdG9yLWRpc2FibGVkJyk7XG4gICAgICAgIHRoaXMuZGlzYWJsZUJ1dHRvbnMoJ2FsbCcpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgLCBoaWRlUHJldmlldzogZnVuY3Rpb24oKSB7XG4gICAgICAvLyBHaXZlIGZsYWcgdGhhdCB0ZWxsIHRoZSBlZGl0b3IgcXVpdCBwcmV2aWV3IG1vZGVcbiAgICAgIHRoaXMuJGlzUHJldmlldyA9IGZhbHNlO1xuXG4gICAgICAvLyBPYnRhaW4gdGhlIHByZXZpZXcgY29udGFpbmVyXG4gICAgICB2YXIgY29udGFpbmVyID0gdGhpcy4kZWRpdG9yLmZpbmQoJ2RpdltkYXRhLXByb3ZpZGVyPVwibWFya2Rvd24tcHJldmlld1wiXScpO1xuXG4gICAgICAvLyBSZW1vdmUgdGhlIHByZXZpZXcgY29udGFpbmVyXG4gICAgICBjb250YWluZXIucmVtb3ZlKCk7XG5cbiAgICAgIC8vIEVuYWJsZSBhbGwgYnV0dG9uc1xuICAgICAgdGhpcy5lbmFibGVCdXR0b25zKCdhbGwnKTtcbiAgICAgIC8vIERpc2FibGUgY29uZmlndXJlZCBkaXNhYmxlZCBidXR0b25zXG4gICAgICB0aGlzLmRpc2FibGVCdXR0b25zKHRoaXMuJG9wdGlvbnMuZGlzYWJsZWRCdXR0b25zKTtcblxuICAgICAgLy8gQmFjayB0byB0aGUgZWRpdG9yXG4gICAgICB0aGlzLiR0ZXh0YXJlYS5zaG93KCk7XG4gICAgICB0aGlzLl9fc2V0TGlzdGVuZXIoKTtcblxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICwgaXNEaXJ0eTogZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gdGhpcy4kb2xkQ29udGVudCAhPSB0aGlzLmdldENvbnRlbnQoKTtcbiAgICB9XG5cbiAgLCBnZXRDb250ZW50OiBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiB0aGlzLiR0ZXh0YXJlYS52YWwoKTtcbiAgICB9XG5cbiAgLCBzZXRDb250ZW50OiBmdW5jdGlvbihjb250ZW50KSB7XG4gICAgICB0aGlzLiR0ZXh0YXJlYS52YWwoY29udGVudCk7XG5cbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAsIGZpbmRTZWxlY3Rpb246IGZ1bmN0aW9uKGNodW5rKSB7XG4gICAgdmFyIGNvbnRlbnQgPSB0aGlzLmdldENvbnRlbnQoKSwgc3RhcnRDaHVua1Bvc2l0aW9uO1xuXG4gICAgaWYgKHN0YXJ0Q2h1bmtQb3NpdGlvbiA9IGNvbnRlbnQuaW5kZXhPZihjaHVuayksIHN0YXJ0Q2h1bmtQb3NpdGlvbiA+PSAwICYmIGNodW5rLmxlbmd0aCA+IDApIHtcbiAgICAgIHZhciBvbGRTZWxlY3Rpb24gPSB0aGlzLmdldFNlbGVjdGlvbigpLCBzZWxlY3Rpb247XG5cbiAgICAgIHRoaXMuc2V0U2VsZWN0aW9uKHN0YXJ0Q2h1bmtQb3NpdGlvbixzdGFydENodW5rUG9zaXRpb24rY2h1bmsubGVuZ3RoKTtcbiAgICAgIHNlbGVjdGlvbiA9IHRoaXMuZ2V0U2VsZWN0aW9uKCk7XG5cbiAgICAgIHRoaXMuc2V0U2VsZWN0aW9uKG9sZFNlbGVjdGlvbi5zdGFydCxvbGRTZWxlY3Rpb24uZW5kKTtcblxuICAgICAgcmV0dXJuIHNlbGVjdGlvbjtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICB9XG5cbiAgLCBnZXRTZWxlY3Rpb246IGZ1bmN0aW9uKCkge1xuXG4gICAgICB2YXIgZSA9IHRoaXMuJHRleHRhcmVhWzBdO1xuXG4gICAgICByZXR1cm4gKFxuXG4gICAgICAgICAgKCdzZWxlY3Rpb25TdGFydCcgaW4gZSAmJiBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgdmFyIGwgPSBlLnNlbGVjdGlvbkVuZCAtIGUuc2VsZWN0aW9uU3RhcnQ7XG4gICAgICAgICAgICAgIHJldHVybiB7IHN0YXJ0OiBlLnNlbGVjdGlvblN0YXJ0LCBlbmQ6IGUuc2VsZWN0aW9uRW5kLCBsZW5ndGg6IGwsIHRleHQ6IGUudmFsdWUuc3Vic3RyKGUuc2VsZWN0aW9uU3RhcnQsIGwpIH07XG4gICAgICAgICAgfSkgfHxcblxuICAgICAgICAgIC8qIGJyb3dzZXIgbm90IHN1cHBvcnRlZCAqL1xuICAgICAgICAgIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgfVxuXG4gICAgICApKCk7XG5cbiAgICB9XG5cbiAgLCBzZXRTZWxlY3Rpb246IGZ1bmN0aW9uKHN0YXJ0LGVuZCkge1xuXG4gICAgICB2YXIgZSA9IHRoaXMuJHRleHRhcmVhWzBdO1xuXG4gICAgICByZXR1cm4gKFxuXG4gICAgICAgICAgKCdzZWxlY3Rpb25TdGFydCcgaW4gZSAmJiBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgZS5zZWxlY3Rpb25TdGFydCA9IHN0YXJ0O1xuICAgICAgICAgICAgICBlLnNlbGVjdGlvbkVuZCA9IGVuZDtcbiAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH0pIHx8XG5cbiAgICAgICAgICAvKiBicm93c2VyIG5vdCBzdXBwb3J0ZWQgKi9cbiAgICAgICAgICBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgIH1cblxuICAgICAgKSgpO1xuXG4gICAgfVxuXG4gICwgcmVwbGFjZVNlbGVjdGlvbjogZnVuY3Rpb24odGV4dCkge1xuXG4gICAgICB2YXIgZSA9IHRoaXMuJHRleHRhcmVhWzBdO1xuXG4gICAgICByZXR1cm4gKFxuXG4gICAgICAgICAgKCdzZWxlY3Rpb25TdGFydCcgaW4gZSAmJiBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgZS52YWx1ZSA9IGUudmFsdWUuc3Vic3RyKDAsIGUuc2VsZWN0aW9uU3RhcnQpICsgdGV4dCArIGUudmFsdWUuc3Vic3RyKGUuc2VsZWN0aW9uRW5kLCBlLnZhbHVlLmxlbmd0aCk7XG4gICAgICAgICAgICAgIC8vIFNldCBjdXJzb3IgdG8gdGhlIGxhc3QgcmVwbGFjZW1lbnQgZW5kXG4gICAgICAgICAgICAgIGUuc2VsZWN0aW9uU3RhcnQgPSBlLnZhbHVlLmxlbmd0aDtcbiAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgfSkgfHxcblxuICAgICAgICAgIC8qIGJyb3dzZXIgbm90IHN1cHBvcnRlZCAqL1xuICAgICAgICAgIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICBlLnZhbHVlICs9IHRleHQ7XG4gICAgICAgICAgICAgIHJldHVybiBqUXVlcnkoZSk7XG4gICAgICAgICAgfVxuXG4gICAgICApKCk7XG4gICAgfVxuXG4gICwgZ2V0TmV4dFRhYjogZnVuY3Rpb24oKSB7XG4gICAgICAvLyBTaGlmdCB0aGUgbmV4dFRhYlxuICAgICAgaWYgKHRoaXMuJG5leHRUYWIubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdmFyIG5leHRUYWIsIHRhYiA9IHRoaXMuJG5leHRUYWIuc2hpZnQoKTtcblxuICAgICAgICBpZiAodHlwZW9mIHRhYiA9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgbmV4dFRhYiA9IHRhYigpO1xuICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiB0YWIgPT0gJ29iamVjdCcgJiYgdGFiLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICBuZXh0VGFiID0gdGFiO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIG5leHRUYWI7XG4gICAgICB9XG4gICAgfVxuXG4gICwgc2V0TmV4dFRhYjogZnVuY3Rpb24oc3RhcnQsZW5kKSB7XG4gICAgICAvLyBQdXNoIG5ldyBzZWxlY3Rpb24gaW50byBuZXh0VGFiIGNvbGxlY3Rpb25zXG4gICAgICBpZiAodHlwZW9mIHN0YXJ0ID09ICdzdHJpbmcnKSB7XG4gICAgICAgIHZhciB0aGF0ID0gdGhpcztcbiAgICAgICAgdGhpcy4kbmV4dFRhYi5wdXNoKGZ1bmN0aW9uKCl7XG4gICAgICAgICAgcmV0dXJuIHRoYXQuZmluZFNlbGVjdGlvbihzdGFydCk7XG4gICAgICAgIH0pO1xuICAgICAgfSBlbHNlIGlmICh0eXBlb2Ygc3RhcnQgPT0gJ251bWJlcicgJiYgdHlwZW9mIGVuZCA9PSAnbnVtYmVyJykge1xuICAgICAgICB2YXIgb2xkU2VsZWN0aW9uID0gdGhpcy5nZXRTZWxlY3Rpb24oKTtcblxuICAgICAgICB0aGlzLnNldFNlbGVjdGlvbihzdGFydCxlbmQpO1xuICAgICAgICB0aGlzLiRuZXh0VGFiLnB1c2godGhpcy5nZXRTZWxlY3Rpb24oKSk7XG5cbiAgICAgICAgdGhpcy5zZXRTZWxlY3Rpb24ob2xkU2VsZWN0aW9uLnN0YXJ0LG9sZFNlbGVjdGlvbi5lbmQpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICwgX19wYXJzZUJ1dHRvbk5hbWVQYXJhbTogZnVuY3Rpb24gKG5hbWVzKSB7XG4gICAgICByZXR1cm4gdHlwZW9mIG5hbWVzID09ICdzdHJpbmcnID9cbiAgICAgICAgICAgICAgICAgICAgICBuYW1lcy5zcGxpdCgnICcpIDpcbiAgICAgICAgICAgICAgICAgICAgICBuYW1lcztcblxuICAgIH1cblxuICAsIGVuYWJsZUJ1dHRvbnM6IGZ1bmN0aW9uKG5hbWUpIHtcbiAgICAgIHZhciBidXR0b25zID0gdGhpcy5fX3BhcnNlQnV0dG9uTmFtZVBhcmFtKG5hbWUpLFxuICAgICAgICB0aGF0ID0gdGhpcztcblxuICAgICAgJC5lYWNoKGJ1dHRvbnMsIGZ1bmN0aW9uKGksIHYpIHtcbiAgICAgICAgdGhhdC5fX2FsdGVyQnV0dG9ucyhidXR0b25zW2ldLCBmdW5jdGlvbiAoZWwpIHtcbiAgICAgICAgICBlbC5yZW1vdmVBdHRyKCdkaXNhYmxlZCcpO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuXG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgLCBkaXNhYmxlQnV0dG9uczogZnVuY3Rpb24obmFtZSkge1xuICAgICAgdmFyIGJ1dHRvbnMgPSB0aGlzLl9fcGFyc2VCdXR0b25OYW1lUGFyYW0obmFtZSksXG4gICAgICAgIHRoYXQgPSB0aGlzO1xuXG4gICAgICAkLmVhY2goYnV0dG9ucywgZnVuY3Rpb24oaSwgdikge1xuICAgICAgICB0aGF0Ll9fYWx0ZXJCdXR0b25zKGJ1dHRvbnNbaV0sIGZ1bmN0aW9uIChlbCkge1xuICAgICAgICAgIGVsLmF0dHIoJ2Rpc2FibGVkJywnZGlzYWJsZWQnKTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcblxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICwgaGlkZUJ1dHRvbnM6IGZ1bmN0aW9uKG5hbWUpIHtcbiAgICAgIHZhciBidXR0b25zID0gdGhpcy5fX3BhcnNlQnV0dG9uTmFtZVBhcmFtKG5hbWUpLFxuICAgICAgICB0aGF0ID0gdGhpcztcblxuICAgICAgJC5lYWNoKGJ1dHRvbnMsIGZ1bmN0aW9uKGksIHYpIHtcbiAgICAgICAgdGhhdC5fX2FsdGVyQnV0dG9ucyhidXR0b25zW2ldLCBmdW5jdGlvbiAoZWwpIHtcbiAgICAgICAgICBlbC5hZGRDbGFzcygnaGlkZGVuJyk7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG5cbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAsIHNob3dCdXR0b25zOiBmdW5jdGlvbihuYW1lKSB7XG4gICAgICB2YXIgYnV0dG9ucyA9IHRoaXMuX19wYXJzZUJ1dHRvbk5hbWVQYXJhbShuYW1lKSxcbiAgICAgICAgdGhhdCA9IHRoaXM7XG5cbiAgICAgICQuZWFjaChidXR0b25zLCBmdW5jdGlvbihpLCB2KSB7XG4gICAgICAgIHRoYXQuX19hbHRlckJ1dHRvbnMoYnV0dG9uc1tpXSwgZnVuY3Rpb24gKGVsKSB7XG4gICAgICAgICAgZWwucmVtb3ZlQ2xhc3MoJ2hpZGRlbicpO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuXG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgLCBldmVudFN1cHBvcnRlZDogZnVuY3Rpb24oZXZlbnROYW1lKSB7XG4gICAgICB2YXIgaXNTdXBwb3J0ZWQgPSBldmVudE5hbWUgaW4gdGhpcy4kZWxlbWVudDtcbiAgICAgIGlmICghaXNTdXBwb3J0ZWQpIHtcbiAgICAgICAgdGhpcy4kZWxlbWVudC5zZXRBdHRyaWJ1dGUoZXZlbnROYW1lLCAncmV0dXJuOycpO1xuICAgICAgICBpc1N1cHBvcnRlZCA9IHR5cGVvZiB0aGlzLiRlbGVtZW50W2V2ZW50TmFtZV0gPT09ICdmdW5jdGlvbic7XG4gICAgICB9XG4gICAgICByZXR1cm4gaXNTdXBwb3J0ZWQ7XG4gICAgfVxuXG4gICwga2V5dXA6IGZ1bmN0aW9uIChlKSB7XG4gICAgICB2YXIgYmxvY2tlZCA9IGZhbHNlO1xuICAgICAgc3dpdGNoKGUua2V5Q29kZSkge1xuICAgICAgICBjYXNlIDQwOiAvLyBkb3duIGFycm93XG4gICAgICAgIGNhc2UgMzg6IC8vIHVwIGFycm93XG4gICAgICAgIGNhc2UgMTY6IC8vIHNoaWZ0XG4gICAgICAgIGNhc2UgMTc6IC8vIGN0cmxcbiAgICAgICAgY2FzZSAxODogLy8gYWx0XG4gICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgY2FzZSA5OiAvLyB0YWJcbiAgICAgICAgICB2YXIgbmV4dFRhYjtcbiAgICAgICAgICBpZiAobmV4dFRhYiA9IHRoaXMuZ2V0TmV4dFRhYigpLG5leHRUYWIgIT09IG51bGwpIHtcbiAgICAgICAgICAgIC8vIEdldCB0aGUgbmV4dFRhYiBpZiBleGlzdHNcbiAgICAgICAgICAgIHZhciB0aGF0ID0gdGhpcztcbiAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKXtcbiAgICAgICAgICAgICAgdGhhdC5zZXRTZWxlY3Rpb24obmV4dFRhYi5zdGFydCxuZXh0VGFiLmVuZCk7XG4gICAgICAgICAgICB9LDUwMCk7XG5cbiAgICAgICAgICAgIGJsb2NrZWQgPSB0cnVlO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBUaGUgbmV4dCB0YWIgbWVtb3J5IGNvbnRhaW5zIG5vdGhpbmcuLi5cbiAgICAgICAgICAgIC8vIGNoZWNrIHRoZSBjdXJzb3IgcG9zaXRpb24gdG8gZGV0ZXJtaW5lIHRhYiBhY3Rpb25cbiAgICAgICAgICAgIHZhciBjdXJzb3IgPSB0aGlzLmdldFNlbGVjdGlvbigpO1xuXG4gICAgICAgICAgICBpZiAoY3Vyc29yLnN0YXJ0ID09IGN1cnNvci5lbmQgJiYgY3Vyc29yLmVuZCA9PSB0aGlzLmdldENvbnRlbnQoKS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgLy8gVGhlIGN1cnNvciBhbHJlYWR5IHJlYWNoIHRoZSBlbmQgb2YgdGhlIGNvbnRlbnRcbiAgICAgICAgICAgICAgYmxvY2tlZCA9IGZhbHNlO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgLy8gUHV0IHRoZSBjdXJzb3IgdG8gdGhlIGVuZFxuICAgICAgICAgICAgICB0aGlzLnNldFNlbGVjdGlvbih0aGlzLmdldENvbnRlbnQoKS5sZW5ndGgsdGhpcy5nZXRDb250ZW50KCkubGVuZ3RoKTtcblxuICAgICAgICAgICAgICBibG9ja2VkID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG5cbiAgICAgICAgICBicmVhaztcblxuICAgICAgICBjYXNlIDEzOiAvLyBlbnRlclxuICAgICAgICAgIGJsb2NrZWQgPSBmYWxzZTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAyNzogLy8gZXNjYXBlXG4gICAgICAgICAgaWYgKHRoaXMuJGlzRnVsbHNjcmVlbikgdGhpcy5zZXRGdWxsc2NyZWVuKGZhbHNlKTtcbiAgICAgICAgICBibG9ja2VkID0gZmFsc2U7XG4gICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICBibG9ja2VkID0gZmFsc2U7XG4gICAgICB9XG5cbiAgICAgIGlmIChibG9ja2VkKSB7XG4gICAgICAgIGUuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy4kb3B0aW9ucy5vbkNoYW5nZSh0aGlzKTtcbiAgICB9XG5cbiAgLCBjaGFuZ2U6IGZ1bmN0aW9uKGUpIHtcbiAgICAgIHRoaXMuJG9wdGlvbnMub25DaGFuZ2UodGhpcyk7XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gICwgc2VsZWN0OiBmdW5jdGlvbiAoZSkge1xuICAgICAgdGhpcy4kb3B0aW9ucy5vblNlbGVjdCh0aGlzKTtcbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgLCBmb2N1czogZnVuY3Rpb24gKGUpIHtcbiAgICAgIHZhciBvcHRpb25zID0gdGhpcy4kb3B0aW9ucyxcbiAgICAgICAgICBpc0hpZGVhYmxlID0gb3B0aW9ucy5oaWRlYWJsZSxcbiAgICAgICAgICBlZGl0b3IgPSB0aGlzLiRlZGl0b3I7XG5cbiAgICAgIGVkaXRvci5hZGRDbGFzcygnYWN0aXZlJyk7XG5cbiAgICAgIC8vIEJsdXIgb3RoZXIgbWFya2Rvd24ocylcbiAgICAgICQoZG9jdW1lbnQpLmZpbmQoJy5tZC1lZGl0b3InKS5lYWNoKGZ1bmN0aW9uKCl7XG4gICAgICAgIGlmICgkKHRoaXMpLmF0dHIoJ2lkJykgIT09IGVkaXRvci5hdHRyKCdpZCcpKSB7XG4gICAgICAgICAgdmFyIGF0dGFjaGVkTWFya2Rvd247XG5cbiAgICAgICAgICBpZiAoYXR0YWNoZWRNYXJrZG93biA9ICQodGhpcykuZmluZCgndGV4dGFyZWEnKS5kYXRhKCdtYXJrZG93bicpLFxuICAgICAgICAgICAgICBhdHRhY2hlZE1hcmtkb3duID09PSBudWxsKSB7XG4gICAgICAgICAgICAgIGF0dGFjaGVkTWFya2Rvd24gPSAkKHRoaXMpLmZpbmQoJ2RpdltkYXRhLXByb3ZpZGVyPVwibWFya2Rvd24tcHJldmlld1wiXScpLmRhdGEoJ21hcmtkb3duJyk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKGF0dGFjaGVkTWFya2Rvd24pIHtcbiAgICAgICAgICAgIGF0dGFjaGVkTWFya2Rvd24uYmx1cigpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSk7XG5cbiAgICAgIC8vIFRyaWdnZXIgdGhlIG9uRm9jdXMgaG9va1xuICAgICAgb3B0aW9ucy5vbkZvY3VzKHRoaXMpO1xuXG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgLCBibHVyOiBmdW5jdGlvbiAoZSkge1xuICAgICAgdmFyIG9wdGlvbnMgPSB0aGlzLiRvcHRpb25zLFxuICAgICAgICAgIGlzSGlkZWFibGUgPSBvcHRpb25zLmhpZGVhYmxlLFxuICAgICAgICAgIGVkaXRvciA9IHRoaXMuJGVkaXRvcixcbiAgICAgICAgICBlZGl0YWJsZSA9IHRoaXMuJGVkaXRhYmxlO1xuXG4gICAgICBpZiAoZWRpdG9yLmhhc0NsYXNzKCdhY3RpdmUnKSB8fCB0aGlzLiRlbGVtZW50LnBhcmVudCgpLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICBlZGl0b3IucmVtb3ZlQ2xhc3MoJ2FjdGl2ZScpO1xuXG4gICAgICAgIGlmIChpc0hpZGVhYmxlKSB7XG4gICAgICAgICAgLy8gQ2hlY2sgZm9yIGVkaXRhYmxlIGVsZW1lbnRzXG4gICAgICAgICAgaWYgKGVkaXRhYmxlLmVsICE9PSBudWxsKSB7XG4gICAgICAgICAgICAvLyBCdWlsZCB0aGUgb3JpZ2luYWwgZWxlbWVudFxuICAgICAgICAgICAgdmFyIG9sZEVsZW1lbnQgPSAkKCc8JytlZGl0YWJsZS50eXBlKycvPicpLFxuICAgICAgICAgICAgICAgIGNvbnRlbnQgPSB0aGlzLmdldENvbnRlbnQoKSxcbiAgICAgICAgICAgICAgICBjdXJyZW50Q29udGVudCA9IHRoaXMucGFyc2VDb250ZW50KGNvbnRlbnQpO1xuXG4gICAgICAgICAgICAkKGVkaXRhYmxlLmF0dHJLZXlzKS5lYWNoKGZ1bmN0aW9uKGssdikge1xuICAgICAgICAgICAgICBvbGRFbGVtZW50LmF0dHIoZWRpdGFibGUuYXR0cktleXNba10sZWRpdGFibGUuYXR0clZhbHVlc1trXSk7XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgLy8gR2V0IHRoZSBlZGl0b3IgY29udGVudFxuICAgICAgICAgICAgb2xkRWxlbWVudC5odG1sKGN1cnJlbnRDb250ZW50KTtcblxuICAgICAgICAgICAgZWRpdG9yLnJlcGxhY2VXaXRoKG9sZEVsZW1lbnQpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBlZGl0b3IuaGlkZSgpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFRyaWdnZXIgdGhlIG9uQmx1ciBob29rXG4gICAgICAgIG9wdGlvbnMub25CbHVyKHRoaXMpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgfTtcblxuIC8qIE1BUktET1dOIFBMVUdJTiBERUZJTklUSU9OXG4gICogPT09PT09PT09PT09PT09PT09PT09PT09PT0gKi9cblxuICB2YXIgb2xkID0gJC5mbi5tYXJrZG93bjtcblxuICAkLmZuLm1hcmtkb3duID0gZnVuY3Rpb24gKG9wdGlvbikge1xuICAgIHJldHVybiB0aGlzLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgdmFyICR0aGlzID0gJCh0aGlzKVxuICAgICAgICAsIGRhdGEgPSAkdGhpcy5kYXRhKCdtYXJrZG93bicpXG4gICAgICAgICwgb3B0aW9ucyA9IHR5cGVvZiBvcHRpb24gPT0gJ29iamVjdCcgJiYgb3B0aW9uO1xuICAgICAgaWYgKCFkYXRhKSAkdGhpcy5kYXRhKCdtYXJrZG93bicsIChkYXRhID0gbmV3IE1hcmtkb3duKHRoaXMsIG9wdGlvbnMpKSlcbiAgICB9KVxuICB9O1xuXG4gICQuZm4ubWFya2Rvd24ubWVzc2FnZXMgPSB7fTtcblxuICAkLmZuLm1hcmtkb3duLmRlZmF1bHRzID0ge1xuICAgIC8qIEVkaXRvciBQcm9wZXJ0aWVzICovXG4gICAgYXV0b2ZvY3VzOiBmYWxzZSxcbiAgICBoaWRlYWJsZTogZmFsc2UsXG4gICAgc2F2YWJsZTogZmFsc2UsXG4gICAgd2lkdGg6ICdpbmhlcml0JyxcbiAgICBoZWlnaHQ6ICdpbmhlcml0JyxcbiAgICByZXNpemU6ICdub25lJyxcbiAgICBpY29ubGlicmFyeTogJ2dseXBoJyxcbiAgICBsYW5ndWFnZTogJ2VuJyxcbiAgICBpbml0aWFsc3RhdGU6ICdlZGl0b3InLFxuICAgIHBhcnNlcjogbnVsbCxcblxuICAgIC8qIEJ1dHRvbnMgUHJvcGVydGllcyAqL1xuICAgIGJ1dHRvbnM6IFtcbiAgICAgIFt7XG4gICAgICAgIG5hbWU6ICdncm91cEZvbnQnLFxuICAgICAgICBkYXRhOiBbe1xuICAgICAgICAgIG5hbWU6ICdjbWRCb2xkJyxcbiAgICAgICAgICBob3RrZXk6ICdDdHJsK0InLFxuICAgICAgICAgIHRpdGxlOiAnQm9sZCcsXG4gICAgICAgICAgaWNvbjogeyBnbHlwaDogJ2dseXBoaWNvbiBnbHlwaGljb24tYm9sZCcsIGZhOiAnZmEgZmEtYm9sZCcsICdmYS0zJzogJ2ljb24tYm9sZCcgfSxcbiAgICAgICAgICBjYWxsYmFjazogZnVuY3Rpb24oZSl7XG4gICAgICAgICAgICAvLyBHaXZlL3JlbW92ZSAqKiBzdXJyb3VuZCB0aGUgc2VsZWN0aW9uXG4gICAgICAgICAgICB2YXIgY2h1bmssIGN1cnNvciwgc2VsZWN0ZWQgPSBlLmdldFNlbGVjdGlvbigpLCBjb250ZW50ID0gZS5nZXRDb250ZW50KCk7XG5cbiAgICAgICAgICAgIGlmIChzZWxlY3RlZC5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgLy8gR2l2ZSBleHRyYSB3b3JkXG4gICAgICAgICAgICAgIGNodW5rID0gZS5fX2xvY2FsaXplKCdzdHJvbmcgdGV4dCcpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgY2h1bmsgPSBzZWxlY3RlZC50ZXh0O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyB0cmFuc2Zvcm0gc2VsZWN0aW9uIGFuZCBzZXQgdGhlIGN1cnNvciBpbnRvIGNodW5rZWQgdGV4dFxuICAgICAgICAgICAgaWYgKGNvbnRlbnQuc3Vic3RyKHNlbGVjdGVkLnN0YXJ0LTIsMikgPT09ICcqKidcbiAgICAgICAgICAgICAgICAmJiBjb250ZW50LnN1YnN0cihzZWxlY3RlZC5lbmQsMikgPT09ICcqKicgKSB7XG4gICAgICAgICAgICAgIGUuc2V0U2VsZWN0aW9uKHNlbGVjdGVkLnN0YXJ0LTIsc2VsZWN0ZWQuZW5kKzIpO1xuICAgICAgICAgICAgICBlLnJlcGxhY2VTZWxlY3Rpb24oY2h1bmspO1xuICAgICAgICAgICAgICBjdXJzb3IgPSBzZWxlY3RlZC5zdGFydC0yO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgZS5yZXBsYWNlU2VsZWN0aW9uKCcqKicrY2h1bmsrJyoqJyk7XG4gICAgICAgICAgICAgIGN1cnNvciA9IHNlbGVjdGVkLnN0YXJ0KzI7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFNldCB0aGUgY3Vyc29yXG4gICAgICAgICAgICBlLnNldFNlbGVjdGlvbihjdXJzb3IsY3Vyc29yK2NodW5rLmxlbmd0aCk7XG4gICAgICAgICAgfVxuICAgICAgICB9LHtcbiAgICAgICAgICBuYW1lOiAnY21kSXRhbGljJyxcbiAgICAgICAgICB0aXRsZTogJ0l0YWxpYycsXG4gICAgICAgICAgaG90a2V5OiAnQ3RybCtJJyxcbiAgICAgICAgICBpY29uOiB7IGdseXBoOiAnZ2x5cGhpY29uIGdseXBoaWNvbi1pdGFsaWMnLCBmYTogJ2ZhIGZhLWl0YWxpYycsICdmYS0zJzogJ2ljb24taXRhbGljJyB9LFxuICAgICAgICAgIGNhbGxiYWNrOiBmdW5jdGlvbihlKXtcbiAgICAgICAgICAgIC8vIEdpdmUvcmVtb3ZlICogc3Vycm91bmQgdGhlIHNlbGVjdGlvblxuICAgICAgICAgICAgdmFyIGNodW5rLCBjdXJzb3IsIHNlbGVjdGVkID0gZS5nZXRTZWxlY3Rpb24oKSwgY29udGVudCA9IGUuZ2V0Q29udGVudCgpO1xuXG4gICAgICAgICAgICBpZiAoc2VsZWN0ZWQubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgIC8vIEdpdmUgZXh0cmEgd29yZFxuICAgICAgICAgICAgICBjaHVuayA9IGUuX19sb2NhbGl6ZSgnZW1waGFzaXplZCB0ZXh0Jyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBjaHVuayA9IHNlbGVjdGVkLnRleHQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIHRyYW5zZm9ybSBzZWxlY3Rpb24gYW5kIHNldCB0aGUgY3Vyc29yIGludG8gY2h1bmtlZCB0ZXh0XG4gICAgICAgICAgICBpZiAoY29udGVudC5zdWJzdHIoc2VsZWN0ZWQuc3RhcnQtMSwxKSA9PT0gJ18nXG4gICAgICAgICAgICAgICAgJiYgY29udGVudC5zdWJzdHIoc2VsZWN0ZWQuZW5kLDEpID09PSAnXycgKSB7XG4gICAgICAgICAgICAgIGUuc2V0U2VsZWN0aW9uKHNlbGVjdGVkLnN0YXJ0LTEsc2VsZWN0ZWQuZW5kKzEpO1xuICAgICAgICAgICAgICBlLnJlcGxhY2VTZWxlY3Rpb24oY2h1bmspO1xuICAgICAgICAgICAgICBjdXJzb3IgPSBzZWxlY3RlZC5zdGFydC0xO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgZS5yZXBsYWNlU2VsZWN0aW9uKCdfJytjaHVuaysnXycpO1xuICAgICAgICAgICAgICBjdXJzb3IgPSBzZWxlY3RlZC5zdGFydCsxO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBTZXQgdGhlIGN1cnNvclxuICAgICAgICAgICAgZS5zZXRTZWxlY3Rpb24oY3Vyc29yLGN1cnNvcitjaHVuay5sZW5ndGgpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSx7XG4gICAgICAgICAgbmFtZTogJ2NtZEhlYWRpbmcnLFxuICAgICAgICAgIHRpdGxlOiAnSGVhZGluZycsXG4gICAgICAgICAgaG90a2V5OiAnQ3RybCtIJyxcbiAgICAgICAgICBpY29uOiB7IGdseXBoOiAnZ2x5cGhpY29uIGdseXBoaWNvbi1oZWFkZXInLCBmYTogJ2ZhIGZhLWhlYWRlcicsICdmYS0zJzogJ2ljb24tZm9udCcgfSxcbiAgICAgICAgICBjYWxsYmFjazogZnVuY3Rpb24oZSl7XG4gICAgICAgICAgICAvLyBBcHBlbmQvcmVtb3ZlICMjIyBzdXJyb3VuZCB0aGUgc2VsZWN0aW9uXG4gICAgICAgICAgICB2YXIgY2h1bmssIGN1cnNvciwgc2VsZWN0ZWQgPSBlLmdldFNlbGVjdGlvbigpLCBjb250ZW50ID0gZS5nZXRDb250ZW50KCksIHBvaW50ZXIsIHByZXZDaGFyO1xuXG4gICAgICAgICAgICBpZiAoc2VsZWN0ZWQubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgIC8vIEdpdmUgZXh0cmEgd29yZFxuICAgICAgICAgICAgICBjaHVuayA9IGUuX19sb2NhbGl6ZSgnaGVhZGluZyB0ZXh0Jyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBjaHVuayA9IHNlbGVjdGVkLnRleHQgKyAnXFxuJztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gdHJhbnNmb3JtIHNlbGVjdGlvbiBhbmQgc2V0IHRoZSBjdXJzb3IgaW50byBjaHVua2VkIHRleHRcbiAgICAgICAgICAgIGlmICgocG9pbnRlciA9IDQsIGNvbnRlbnQuc3Vic3RyKHNlbGVjdGVkLnN0YXJ0LXBvaW50ZXIscG9pbnRlcikgPT09ICcjIyMgJylcbiAgICAgICAgICAgICAgICB8fCAocG9pbnRlciA9IDMsIGNvbnRlbnQuc3Vic3RyKHNlbGVjdGVkLnN0YXJ0LXBvaW50ZXIscG9pbnRlcikgPT09ICcjIyMnKSkge1xuICAgICAgICAgICAgICBlLnNldFNlbGVjdGlvbihzZWxlY3RlZC5zdGFydC1wb2ludGVyLHNlbGVjdGVkLmVuZCk7XG4gICAgICAgICAgICAgIGUucmVwbGFjZVNlbGVjdGlvbihjaHVuayk7XG4gICAgICAgICAgICAgIGN1cnNvciA9IHNlbGVjdGVkLnN0YXJ0LXBvaW50ZXI7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHNlbGVjdGVkLnN0YXJ0ID4gMCAmJiAocHJldkNoYXIgPSBjb250ZW50LnN1YnN0cihzZWxlY3RlZC5zdGFydC0xLDEpLCAhIXByZXZDaGFyICYmIHByZXZDaGFyICE9ICdcXG4nKSkge1xuICAgICAgICAgICAgICBlLnJlcGxhY2VTZWxlY3Rpb24oJ1xcblxcbiMjIyAnK2NodW5rKTtcbiAgICAgICAgICAgICAgY3Vyc29yID0gc2VsZWN0ZWQuc3RhcnQrNjtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIC8vIEVtcHR5IHN0cmluZyBiZWZvcmUgZWxlbWVudFxuICAgICAgICAgICAgICBlLnJlcGxhY2VTZWxlY3Rpb24oJyMjIyAnK2NodW5rKTtcbiAgICAgICAgICAgICAgY3Vyc29yID0gc2VsZWN0ZWQuc3RhcnQrNDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gU2V0IHRoZSBjdXJzb3JcbiAgICAgICAgICAgIGUuc2V0U2VsZWN0aW9uKGN1cnNvcixjdXJzb3IrY2h1bmsubGVuZ3RoKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1dXG4gICAgICB9LHtcbiAgICAgICAgbmFtZTogJ2dyb3VwTGluaycsXG4gICAgICAgIGRhdGE6IFt7XG4gICAgICAgICAgbmFtZTogJ2NtZFVybCcsXG4gICAgICAgICAgdGl0bGU6ICdVUkwvTGluaycsXG4gICAgICAgICAgaG90a2V5OiAnQ3RybCtMJyxcbiAgICAgICAgICBpY29uOiB7IGdseXBoOiAnZ2x5cGhpY29uIGdseXBoaWNvbi1saW5rJywgZmE6ICdmYSBmYS1saW5rJywgJ2ZhLTMnOiAnaWNvbi1saW5rJyB9LFxuICAgICAgICAgIGNhbGxiYWNrOiBmdW5jdGlvbihlKXtcbiAgICAgICAgICAgIC8vIEdpdmUgW10gc3Vycm91bmQgdGhlIHNlbGVjdGlvbiBhbmQgcHJlcGVuZCB0aGUgbGlua1xuICAgICAgICAgICAgdmFyIGNodW5rLCBjdXJzb3IsIHNlbGVjdGVkID0gZS5nZXRTZWxlY3Rpb24oKSwgY29udGVudCA9IGUuZ2V0Q29udGVudCgpLCBsaW5rO1xuXG4gICAgICAgICAgICBpZiAoc2VsZWN0ZWQubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgIC8vIEdpdmUgZXh0cmEgd29yZFxuICAgICAgICAgICAgICBjaHVuayA9IGUuX19sb2NhbGl6ZSgnZW50ZXIgbGluayBkZXNjcmlwdGlvbiBoZXJlJyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBjaHVuayA9IHNlbGVjdGVkLnRleHQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGxpbmsgPSBwcm9tcHQoZS5fX2xvY2FsaXplKCdJbnNlcnQgSHlwZXJsaW5rJyksJ2h0dHA6Ly8nKTtcblxuICAgICAgICAgICAgdmFyIHVybFJlZ2V4ID0gbmV3IFJlZ0V4cCgnXigoaHR0cHxodHRwcyk6Ly98KG1haWx0bzopfCgvLykpW2EtejAtOV0nLCAnaScpO1xuICAgICAgICAgICAgaWYgKGxpbmsgIT09IG51bGwgJiYgbGluayAhPT0gJycgJiYgbGluayAhPT0gJ2h0dHA6Ly8nICYmIHVybFJlZ2V4LnRlc3QobGluaykpIHtcbiAgICAgICAgICAgICAgdmFyIHNhbml0aXplZExpbmsgPSAkKCc8ZGl2PicrbGluaysnPC9kaXY+JykudGV4dCgpO1xuXG4gICAgICAgICAgICAgIC8vIHRyYW5zZm9ybSBzZWxlY3Rpb24gYW5kIHNldCB0aGUgY3Vyc29yIGludG8gY2h1bmtlZCB0ZXh0XG4gICAgICAgICAgICAgIGUucmVwbGFjZVNlbGVjdGlvbignWycrY2h1bmsrJ10oJytzYW5pdGl6ZWRMaW5rKycpJyk7XG4gICAgICAgICAgICAgIGN1cnNvciA9IHNlbGVjdGVkLnN0YXJ0KzE7XG5cbiAgICAgICAgICAgICAgLy8gU2V0IHRoZSBjdXJzb3JcbiAgICAgICAgICAgICAgZS5zZXRTZWxlY3Rpb24oY3Vyc29yLGN1cnNvcitjaHVuay5sZW5ndGgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfSx7XG4gICAgICAgICAgbmFtZTogJ2NtZEltYWdlJyxcbiAgICAgICAgICB0aXRsZTogJ0ltYWdlJyxcbiAgICAgICAgICBob3RrZXk6ICdDdHJsK0cnLFxuICAgICAgICAgIGljb246IHsgZ2x5cGg6ICdnbHlwaGljb24gZ2x5cGhpY29uLXBpY3R1cmUnLCBmYTogJ2ZhIGZhLXBpY3R1cmUtbycsICdmYS0zJzogJ2ljb24tcGljdHVyZScgfSxcbiAgICAgICAgICBjYWxsYmFjazogZnVuY3Rpb24oZSl7XG4gICAgICAgICAgICAvLyBHaXZlICFbXSBzdXJyb3VuZCB0aGUgc2VsZWN0aW9uIGFuZCBwcmVwZW5kIHRoZSBpbWFnZSBsaW5rXG4gICAgICAgICAgICB2YXIgY2h1bmssIGN1cnNvciwgc2VsZWN0ZWQgPSBlLmdldFNlbGVjdGlvbigpLCBjb250ZW50ID0gZS5nZXRDb250ZW50KCksIGxpbms7XG5cbiAgICAgICAgICAgIGlmIChzZWxlY3RlZC5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgLy8gR2l2ZSBleHRyYSB3b3JkXG4gICAgICAgICAgICAgIGNodW5rID0gZS5fX2xvY2FsaXplKCdlbnRlciBpbWFnZSBkZXNjcmlwdGlvbiBoZXJlJyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBjaHVuayA9IHNlbGVjdGVkLnRleHQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGxpbmsgPSBwcm9tcHQoZS5fX2xvY2FsaXplKCdJbnNlcnQgSW1hZ2UgSHlwZXJsaW5rJyksJ2h0dHA6Ly8nKTtcblxuICAgICAgICAgICAgdmFyIHVybFJlZ2V4ID0gbmV3IFJlZ0V4cCgnXigoaHR0cHxodHRwcyk6Ly98KC8vKSlbYS16MC05XScsICdpJyk7XG4gICAgICAgICAgICBpZiAobGluayAhPT0gbnVsbCAmJiBsaW5rICE9PSAnJyAmJiBsaW5rICE9PSAnaHR0cDovLycgJiYgdXJsUmVnZXgudGVzdChsaW5rKSkge1xuICAgICAgICAgICAgICB2YXIgc2FuaXRpemVkTGluayA9ICQoJzxkaXY+JytsaW5rKyc8L2Rpdj4nKS50ZXh0KCk7XG5cbiAgICAgICAgICAgICAgLy8gdHJhbnNmb3JtIHNlbGVjdGlvbiBhbmQgc2V0IHRoZSBjdXJzb3IgaW50byBjaHVua2VkIHRleHRcbiAgICAgICAgICAgICAgZS5yZXBsYWNlU2VsZWN0aW9uKCchWycrY2h1bmsrJ10oJytzYW5pdGl6ZWRMaW5rKycgXCInK2UuX19sb2NhbGl6ZSgnZW50ZXIgaW1hZ2UgdGl0bGUgaGVyZScpKydcIiknKTtcbiAgICAgICAgICAgICAgY3Vyc29yID0gc2VsZWN0ZWQuc3RhcnQrMjtcblxuICAgICAgICAgICAgICAvLyBTZXQgdGhlIG5leHQgdGFiXG4gICAgICAgICAgICAgIGUuc2V0TmV4dFRhYihlLl9fbG9jYWxpemUoJ2VudGVyIGltYWdlIHRpdGxlIGhlcmUnKSk7XG5cbiAgICAgICAgICAgICAgLy8gU2V0IHRoZSBjdXJzb3JcbiAgICAgICAgICAgICAgZS5zZXRTZWxlY3Rpb24oY3Vyc29yLGN1cnNvcitjaHVuay5sZW5ndGgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfV1cbiAgICAgIH0se1xuICAgICAgICBuYW1lOiAnZ3JvdXBNaXNjJyxcbiAgICAgICAgZGF0YTogW3tcbiAgICAgICAgICBuYW1lOiAnY21kTGlzdCcsXG4gICAgICAgICAgaG90a2V5OiAnQ3RybCtVJyxcbiAgICAgICAgICB0aXRsZTogJ1Vub3JkZXJlZCBMaXN0JyxcbiAgICAgICAgICBpY29uOiB7IGdseXBoOiAnZ2x5cGhpY29uIGdseXBoaWNvbi1saXN0JywgZmE6ICdmYSBmYS1saXN0JywgJ2ZhLTMnOiAnaWNvbi1saXN0LXVsJyB9LFxuICAgICAgICAgIGNhbGxiYWNrOiBmdW5jdGlvbihlKXtcbiAgICAgICAgICAgIC8vIFByZXBlbmQvR2l2ZSAtIHN1cnJvdW5kIHRoZSBzZWxlY3Rpb25cbiAgICAgICAgICAgIHZhciBjaHVuaywgY3Vyc29yLCBzZWxlY3RlZCA9IGUuZ2V0U2VsZWN0aW9uKCksIGNvbnRlbnQgPSBlLmdldENvbnRlbnQoKTtcblxuICAgICAgICAgICAgLy8gdHJhbnNmb3JtIHNlbGVjdGlvbiBhbmQgc2V0IHRoZSBjdXJzb3IgaW50byBjaHVua2VkIHRleHRcbiAgICAgICAgICAgIGlmIChzZWxlY3RlZC5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgLy8gR2l2ZSBleHRyYSB3b3JkXG4gICAgICAgICAgICAgIGNodW5rID0gZS5fX2xvY2FsaXplKCdsaXN0IHRleHQgaGVyZScpO1xuXG4gICAgICAgICAgICAgIGUucmVwbGFjZVNlbGVjdGlvbignLSAnK2NodW5rKTtcbiAgICAgICAgICAgICAgLy8gU2V0IHRoZSBjdXJzb3JcbiAgICAgICAgICAgICAgY3Vyc29yID0gc2VsZWN0ZWQuc3RhcnQrMjtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIGlmIChzZWxlY3RlZC50ZXh0LmluZGV4T2YoJ1xcbicpIDwgMCkge1xuICAgICAgICAgICAgICAgIGNodW5rID0gc2VsZWN0ZWQudGV4dDtcblxuICAgICAgICAgICAgICAgIGUucmVwbGFjZVNlbGVjdGlvbignLSAnK2NodW5rKTtcblxuICAgICAgICAgICAgICAgIC8vIFNldCB0aGUgY3Vyc29yXG4gICAgICAgICAgICAgICAgY3Vyc29yID0gc2VsZWN0ZWQuc3RhcnQrMjtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB2YXIgbGlzdCA9IFtdO1xuXG4gICAgICAgICAgICAgICAgbGlzdCA9IHNlbGVjdGVkLnRleHQuc3BsaXQoJ1xcbicpO1xuICAgICAgICAgICAgICAgIGNodW5rID0gbGlzdFswXTtcblxuICAgICAgICAgICAgICAgICQuZWFjaChsaXN0LGZ1bmN0aW9uKGssdikge1xuICAgICAgICAgICAgICAgICAgbGlzdFtrXSA9ICctICcrdjtcbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgIGUucmVwbGFjZVNlbGVjdGlvbignXFxuXFxuJytsaXN0LmpvaW4oJ1xcbicpKTtcblxuICAgICAgICAgICAgICAgIC8vIFNldCB0aGUgY3Vyc29yXG4gICAgICAgICAgICAgICAgY3Vyc29yID0gc2VsZWN0ZWQuc3RhcnQrNDtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBTZXQgdGhlIGN1cnNvclxuICAgICAgICAgICAgZS5zZXRTZWxlY3Rpb24oY3Vyc29yLGN1cnNvcitjaHVuay5sZW5ndGgpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIG5hbWU6ICdjbWRMaXN0TycsXG4gICAgICAgICAgaG90a2V5OiAnQ3RybCtPJyxcbiAgICAgICAgICB0aXRsZTogJ09yZGVyZWQgTGlzdCcsXG4gICAgICAgICAgaWNvbjogeyBnbHlwaDogJ2dseXBoaWNvbiBnbHlwaGljb24tdGgtbGlzdCcsIGZhOiAnZmEgZmEtbGlzdC1vbCcsICdmYS0zJzogJ2ljb24tbGlzdC1vbCcgfSxcbiAgICAgICAgICBjYWxsYmFjazogZnVuY3Rpb24oZSkge1xuXG4gICAgICAgICAgICAvLyBQcmVwZW5kL0dpdmUgLSBzdXJyb3VuZCB0aGUgc2VsZWN0aW9uXG4gICAgICAgICAgICB2YXIgY2h1bmssIGN1cnNvciwgc2VsZWN0ZWQgPSBlLmdldFNlbGVjdGlvbigpLCBjb250ZW50ID0gZS5nZXRDb250ZW50KCk7XG5cbiAgICAgICAgICAgIC8vIHRyYW5zZm9ybSBzZWxlY3Rpb24gYW5kIHNldCB0aGUgY3Vyc29yIGludG8gY2h1bmtlZCB0ZXh0XG4gICAgICAgICAgICBpZiAoc2VsZWN0ZWQubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgIC8vIEdpdmUgZXh0cmEgd29yZFxuICAgICAgICAgICAgICBjaHVuayA9IGUuX19sb2NhbGl6ZSgnbGlzdCB0ZXh0IGhlcmUnKTtcbiAgICAgICAgICAgICAgZS5yZXBsYWNlU2VsZWN0aW9uKCcxLiAnK2NodW5rKTtcbiAgICAgICAgICAgICAgLy8gU2V0IHRoZSBjdXJzb3JcbiAgICAgICAgICAgICAgY3Vyc29yID0gc2VsZWN0ZWQuc3RhcnQrMztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIGlmIChzZWxlY3RlZC50ZXh0LmluZGV4T2YoJ1xcbicpIDwgMCkge1xuICAgICAgICAgICAgICAgIGNodW5rID0gc2VsZWN0ZWQudGV4dDtcblxuICAgICAgICAgICAgICAgIGUucmVwbGFjZVNlbGVjdGlvbignMS4gJytjaHVuayk7XG5cbiAgICAgICAgICAgICAgICAvLyBTZXQgdGhlIGN1cnNvclxuICAgICAgICAgICAgICAgIGN1cnNvciA9IHNlbGVjdGVkLnN0YXJ0KzM7XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdmFyIGxpc3QgPSBbXTtcblxuICAgICAgICAgICAgICAgIGxpc3QgPSBzZWxlY3RlZC50ZXh0LnNwbGl0KCdcXG4nKTtcbiAgICAgICAgICAgICAgICBjaHVuayA9IGxpc3RbMF07XG5cbiAgICAgICAgICAgICAgICAkLmVhY2gobGlzdCxmdW5jdGlvbihrLHYpIHtcbiAgICAgICAgICAgICAgICAgIGxpc3Rba10gPSAnMS4gJyt2O1xuICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgZS5yZXBsYWNlU2VsZWN0aW9uKCdcXG5cXG4nK2xpc3Quam9pbignXFxuJykpO1xuXG4gICAgICAgICAgICAgICAgLy8gU2V0IHRoZSBjdXJzb3JcbiAgICAgICAgICAgICAgICBjdXJzb3IgPSBzZWxlY3RlZC5zdGFydCs1O1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFNldCB0aGUgY3Vyc29yXG4gICAgICAgICAgICBlLnNldFNlbGVjdGlvbihjdXJzb3IsY3Vyc29yK2NodW5rLmxlbmd0aCk7XG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgbmFtZTogJ2NtZENvZGUnLFxuICAgICAgICAgIGhvdGtleTogJ0N0cmwrSycsXG4gICAgICAgICAgdGl0bGU6ICdDb2RlJyxcbiAgICAgICAgICBpY29uOiB7IGdseXBoOiAnZ2x5cGhpY29uIGdseXBoaWNvbi1hc3RlcmlzaycsIGZhOiAnZmEgZmEtY29kZScsICdmYS0zJzogJ2ljb24tY29kZScgfSxcbiAgICAgICAgICBjYWxsYmFjazogZnVuY3Rpb24oZSkge1xuICAgICAgICAgICAgLy8gR2l2ZS9yZW1vdmUgKiogc3Vycm91bmQgdGhlIHNlbGVjdGlvblxuICAgICAgICAgICAgdmFyIGNodW5rLCBjdXJzb3IsIHNlbGVjdGVkID0gZS5nZXRTZWxlY3Rpb24oKSwgY29udGVudCA9IGUuZ2V0Q29udGVudCgpO1xuXG4gICAgICAgICAgICBpZiAoc2VsZWN0ZWQubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgIC8vIEdpdmUgZXh0cmEgd29yZFxuICAgICAgICAgICAgICBjaHVuayA9IGUuX19sb2NhbGl6ZSgnY29kZSB0ZXh0IGhlcmUnKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIGNodW5rID0gc2VsZWN0ZWQudGV4dDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gdHJhbnNmb3JtIHNlbGVjdGlvbiBhbmQgc2V0IHRoZSBjdXJzb3IgaW50byBjaHVua2VkIHRleHRcbiAgICAgICAgICAgIGlmIChjb250ZW50LnN1YnN0cihzZWxlY3RlZC5zdGFydC00LDQpID09PSAnYGBgXFxuJ1xuICAgICAgICAgICAgICAgICYmIGNvbnRlbnQuc3Vic3RyKHNlbGVjdGVkLmVuZCw0KSA9PT0gJ1xcbmBgYCcpIHtcbiAgICAgICAgICAgICAgZS5zZXRTZWxlY3Rpb24oc2VsZWN0ZWQuc3RhcnQtNCwgc2VsZWN0ZWQuZW5kKzQpO1xuICAgICAgICAgICAgICBlLnJlcGxhY2VTZWxlY3Rpb24oY2h1bmspO1xuICAgICAgICAgICAgICBjdXJzb3IgPSBzZWxlY3RlZC5zdGFydC00O1xuICAgICAgICAgICAgfSBlbHNlIGlmIChjb250ZW50LnN1YnN0cihzZWxlY3RlZC5zdGFydC0xLDEpID09PSAnYCdcbiAgICAgICAgICAgICAgICAmJiBjb250ZW50LnN1YnN0cihzZWxlY3RlZC5lbmQsMSkgPT09ICdgJykge1xuICAgICAgICAgICAgICBlLnNldFNlbGVjdGlvbihzZWxlY3RlZC5zdGFydC0xLHNlbGVjdGVkLmVuZCsxKTtcbiAgICAgICAgICAgICAgZS5yZXBsYWNlU2VsZWN0aW9uKGNodW5rKTtcbiAgICAgICAgICAgICAgY3Vyc29yID0gc2VsZWN0ZWQuc3RhcnQtMTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoY29udGVudC5pbmRleE9mKCdcXG4nKSA+IC0xKSB7XG4gICAgICAgICAgICAgIGUucmVwbGFjZVNlbGVjdGlvbignYGBgXFxuJytjaHVuaysnXFxuYGBgJyk7XG4gICAgICAgICAgICAgIGN1cnNvciA9IHNlbGVjdGVkLnN0YXJ0KzQ7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBlLnJlcGxhY2VTZWxlY3Rpb24oJ2AnK2NodW5rKydgJyk7XG4gICAgICAgICAgICAgIGN1cnNvciA9IHNlbGVjdGVkLnN0YXJ0KzE7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFNldCB0aGUgY3Vyc29yXG4gICAgICAgICAgICBlLnNldFNlbGVjdGlvbihjdXJzb3IsY3Vyc29yK2NodW5rLmxlbmd0aCk7XG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgbmFtZTogJ2NtZFF1b3RlJyxcbiAgICAgICAgICBob3RrZXk6ICdDdHJsK1EnLFxuICAgICAgICAgIHRpdGxlOiAnUXVvdGUnLFxuICAgICAgICAgIGljb246IHsgZ2x5cGg6ICdnbHlwaGljb24gZ2x5cGhpY29uLWNvbW1lbnQnLCBmYTogJ2ZhIGZhLXF1b3RlLWxlZnQnLCAnZmEtMyc6ICdpY29uLXF1b3RlLWxlZnQnIH0sXG4gICAgICAgICAgY2FsbGJhY2s6IGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgICAgIC8vIFByZXBlbmQvR2l2ZSAtIHN1cnJvdW5kIHRoZSBzZWxlY3Rpb25cbiAgICAgICAgICAgIHZhciBjaHVuaywgY3Vyc29yLCBzZWxlY3RlZCA9IGUuZ2V0U2VsZWN0aW9uKCksIGNvbnRlbnQgPSBlLmdldENvbnRlbnQoKTtcblxuICAgICAgICAgICAgLy8gdHJhbnNmb3JtIHNlbGVjdGlvbiBhbmQgc2V0IHRoZSBjdXJzb3IgaW50byBjaHVua2VkIHRleHRcbiAgICAgICAgICAgIGlmIChzZWxlY3RlZC5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgLy8gR2l2ZSBleHRyYSB3b3JkXG4gICAgICAgICAgICAgIGNodW5rID0gZS5fX2xvY2FsaXplKCdxdW90ZSBoZXJlJyk7XG5cbiAgICAgICAgICAgICAgZS5yZXBsYWNlU2VsZWN0aW9uKCc+ICcrY2h1bmspO1xuXG4gICAgICAgICAgICAgIC8vIFNldCB0aGUgY3Vyc29yXG4gICAgICAgICAgICAgIGN1cnNvciA9IHNlbGVjdGVkLnN0YXJ0KzI7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBpZiAoc2VsZWN0ZWQudGV4dC5pbmRleE9mKCdcXG4nKSA8IDApIHtcbiAgICAgICAgICAgICAgICBjaHVuayA9IHNlbGVjdGVkLnRleHQ7XG5cbiAgICAgICAgICAgICAgICBlLnJlcGxhY2VTZWxlY3Rpb24oJz4gJytjaHVuayk7XG5cbiAgICAgICAgICAgICAgICAvLyBTZXQgdGhlIGN1cnNvclxuICAgICAgICAgICAgICAgIGN1cnNvciA9IHNlbGVjdGVkLnN0YXJ0KzI7XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdmFyIGxpc3QgPSBbXTtcblxuICAgICAgICAgICAgICAgIGxpc3QgPSBzZWxlY3RlZC50ZXh0LnNwbGl0KCdcXG4nKTtcbiAgICAgICAgICAgICAgICBjaHVuayA9IGxpc3RbMF07XG5cbiAgICAgICAgICAgICAgICAkLmVhY2gobGlzdCxmdW5jdGlvbihrLHYpIHtcbiAgICAgICAgICAgICAgICAgIGxpc3Rba10gPSAnPiAnK3Y7XG4gICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICBlLnJlcGxhY2VTZWxlY3Rpb24oJ1xcblxcbicrbGlzdC5qb2luKCdcXG4nKSk7XG5cbiAgICAgICAgICAgICAgICAvLyBTZXQgdGhlIGN1cnNvclxuICAgICAgICAgICAgICAgIGN1cnNvciA9IHNlbGVjdGVkLnN0YXJ0KzQ7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gU2V0IHRoZSBjdXJzb3JcbiAgICAgICAgICAgIGUuc2V0U2VsZWN0aW9uKGN1cnNvcixjdXJzb3IrY2h1bmsubGVuZ3RoKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1dXG4gICAgICB9LHtcbiAgICAgICAgbmFtZTogJ2dyb3VwVXRpbCcsXG4gICAgICAgIGRhdGE6IFt7XG4gICAgICAgICAgbmFtZTogJ2NtZFByZXZpZXcnLFxuICAgICAgICAgIHRvZ2dsZTogdHJ1ZSxcbiAgICAgICAgICBob3RrZXk6ICdDdHJsK1AnLFxuICAgICAgICAgIHRpdGxlOiAnUHJldmlldycsXG4gICAgICAgICAgYnRuVGV4dDogJ1ByZXZpZXcnLFxuICAgICAgICAgIGJ0bkNsYXNzOiAnYnRuIGJ0bi1wcmltYXJ5IGJ0bi1zbScsXG4gICAgICAgICAgaWNvbjogeyBnbHlwaDogJ2dseXBoaWNvbiBnbHlwaGljb24tc2VhcmNoJywgZmE6ICdmYSBmYS1zZWFyY2gnLCAnZmEtMyc6ICdpY29uLXNlYXJjaCcgfSxcbiAgICAgICAgICBjYWxsYmFjazogZnVuY3Rpb24oZSl7XG4gICAgICAgICAgICAvLyBDaGVjayB0aGUgcHJldmlldyBtb2RlIGFuZCB0b2dnbGUgYmFzZWQgb24gdGhpcyBmbGFnXG4gICAgICAgICAgICB2YXIgaXNQcmV2aWV3ID0gZS4kaXNQcmV2aWV3LGNvbnRlbnQ7XG5cbiAgICAgICAgICAgIGlmIChpc1ByZXZpZXcgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICAgIC8vIEdpdmUgZmxhZyB0aGF0IHRlbGwgdGhlIGVkaXRvciBlbnRlciBwcmV2aWV3IG1vZGVcbiAgICAgICAgICAgICAgZS5zaG93UHJldmlldygpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgZS5oaWRlUHJldmlldygpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfV1cbiAgICAgIH1dXG4gICAgXSxcbiAgICBhZGRpdGlvbmFsQnV0dG9uczpbXSwgLy8gUGxhY2UgdG8gaG9vayBtb3JlIGJ1dHRvbnMgYnkgY29kZVxuICAgIHJlb3JkZXJCdXR0b25Hcm91cHM6W10sXG4gICAgaGlkZGVuQnV0dG9uczpbXSwgLy8gRGVmYXVsdCBoaWRkZW4gYnV0dG9uc1xuICAgIGRpc2FibGVkQnV0dG9uczpbXSwgLy8gRGVmYXVsdCBkaXNhYmxlZCBidXR0b25zXG4gICAgZm9vdGVyOiAnJyxcbiAgICBmdWxsc2NyZWVuOiB7XG4gICAgICBlbmFibGU6IHRydWUsXG4gICAgICBpY29uczoge1xuICAgICAgICBmdWxsc2NyZWVuT246IHtcbiAgICAgICAgICBmYTogJ2ZhIGZhLWV4cGFuZCcsXG4gICAgICAgICAgZ2x5cGg6ICdnbHlwaGljb24gZ2x5cGhpY29uLWZ1bGxzY3JlZW4nLFxuICAgICAgICAgICdmYS0zJzogJ2ljb24tcmVzaXplLWZ1bGwnXG4gICAgICAgIH0sXG4gICAgICAgIGZ1bGxzY3JlZW5PZmY6IHtcbiAgICAgICAgICBmYTogJ2ZhIGZhLWNvbXByZXNzJyxcbiAgICAgICAgICBnbHlwaDogJ2dseXBoaWNvbiBnbHlwaGljb24tZnVsbHNjcmVlbicsXG4gICAgICAgICAgJ2ZhLTMnOiAnaWNvbi1yZXNpemUtc21hbGwnXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9LFxuXG4gICAgLyogRXZlbnRzIGhvb2sgKi9cbiAgICBvblNob3c6IGZ1bmN0aW9uIChlKSB7fSxcbiAgICBvblByZXZpZXc6IGZ1bmN0aW9uIChlKSB7fSxcbiAgICBvblNhdmU6IGZ1bmN0aW9uIChlKSB7fSxcbiAgICBvbkJsdXI6IGZ1bmN0aW9uIChlKSB7fSxcbiAgICBvbkZvY3VzOiBmdW5jdGlvbiAoZSkge30sXG4gICAgb25DaGFuZ2U6IGZ1bmN0aW9uKGUpIHt9LFxuICAgIG9uRnVsbHNjcmVlbjogZnVuY3Rpb24oZSkge30sXG4gICAgb25TZWxlY3Q6IGZ1bmN0aW9uIChlKSB7fVxuICB9O1xuXG4gICQuZm4ubWFya2Rvd24uQ29uc3RydWN0b3IgPSBNYXJrZG93bjtcblxuXG4gLyogTUFSS0RPV04gTk8gQ09ORkxJQ1RcbiAgKiA9PT09PT09PT09PT09PT09PT09PSAqL1xuXG4gICQuZm4ubWFya2Rvd24ubm9Db25mbGljdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAkLmZuLm1hcmtkb3duID0gb2xkO1xuICAgIHJldHVybiB0aGlzO1xuICB9O1xuXG4gIC8qIE1BUktET1dOIEdMT0JBTCBGVU5DVElPTiAmIERBVEEtQVBJXG4gICogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09ICovXG4gIHZhciBpbml0TWFya2Rvd24gPSBmdW5jdGlvbihlbCkge1xuICAgIHZhciAkdGhpcyA9IGVsO1xuXG4gICAgaWYgKCR0aGlzLmRhdGEoJ21hcmtkb3duJykpIHtcbiAgICAgICR0aGlzLmRhdGEoJ21hcmtkb3duJykuc2hvd0VkaXRvcigpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgICR0aGlzLm1hcmtkb3duKClcbiAgfTtcblxuICB2YXIgYmx1ck5vbkZvY3VzZWQgPSBmdW5jdGlvbihlKSB7XG4gICAgdmFyICRhY3RpdmVFbGVtZW50ID0gJChkb2N1bWVudC5hY3RpdmVFbGVtZW50KTtcblxuICAgIC8vIEJsdXIgZXZlbnRcbiAgICAkKGRvY3VtZW50KS5maW5kKCcubWQtZWRpdG9yJykuZWFjaChmdW5jdGlvbigpe1xuICAgICAgdmFyICR0aGlzICAgICAgICAgICAgPSAkKHRoaXMpLFxuICAgICAgICAgIGZvY3VzZWQgICAgICAgICAgPSAkYWN0aXZlRWxlbWVudC5jbG9zZXN0KCcubWQtZWRpdG9yJylbMF0gPT09IHRoaXMsXG4gICAgICAgICAgYXR0YWNoZWRNYXJrZG93biA9ICR0aGlzLmZpbmQoJ3RleHRhcmVhJykuZGF0YSgnbWFya2Rvd24nKSB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkdGhpcy5maW5kKCdkaXZbZGF0YS1wcm92aWRlcj1cIm1hcmtkb3duLXByZXZpZXdcIl0nKS5kYXRhKCdtYXJrZG93bicpO1xuXG4gICAgICBpZiAoYXR0YWNoZWRNYXJrZG93biAmJiAhZm9jdXNlZCkge1xuICAgICAgICBhdHRhY2hlZE1hcmtkb3duLmJsdXIoKTtcbiAgICAgIH1cbiAgICB9KVxuICB9O1xuXG4gICQoZG9jdW1lbnQpXG4gICAgLm9uKCdjbGljay5tYXJrZG93bi5kYXRhLWFwaScsICdbZGF0YS1wcm92aWRlPVwibWFya2Rvd24tZWRpdGFibGVcIl0nLCBmdW5jdGlvbiAoZSkge1xuICAgICAgaW5pdE1hcmtkb3duKCQodGhpcykpO1xuICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIH0pXG4gICAgLm9uKCdjbGljayBmb2N1c2luJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgIGJsdXJOb25Gb2N1c2VkKGUpO1xuICAgIH0pXG4gICAgLnJlYWR5KGZ1bmN0aW9uKCl7XG4gICAgICAkKCd0ZXh0YXJlYVtkYXRhLXByb3ZpZGU9XCJtYXJrZG93blwiXScpLmVhY2goZnVuY3Rpb24oKXtcbiAgICAgICAgaW5pdE1hcmtkb3duKCQodGhpcykpO1xuICAgICAgfSlcbiAgICB9KTtcblxufSkpO1xuIiwiLypcbiAqIEFyYWJpYyB0cmFuc2xhdGlvbiBmb3IgYm9vdHN0cmFwLW1hcmtkb3duXG4gKiBHZW9yZ2UgQWphbSA8Z2VvcmdlLmVqYWFtQGdtYWlsLmNvbT5cbiAqL1xuKGZ1bmN0aW9uICgkKSB7XG4gICQuZm4ubWFya2Rvd24ubWVzc2FnZXMubmwgPSB7XG4gICAgJ0JvbGQnOiBcIti62KfZhdmCXCIsXG4gICAgJ0l0YWxpYyc6IFwi2YXYp9im2YRcIixcbiAgICAnSGVhZGluZyc6IFwi2LnZhtmI2KfZhlwiLFxuICAgICdVUkwvTGluayc6IFwiVVJML9ix2KfYqNi3XCIsXG4gICAgJ0ltYWdlJzogXCLYtdmI2LHYqVwiLFxuICAgICdMaXN0JzogXCLZgtin2KbZhdipXCIsXG4gICAgJ1ByZXZpZXcnOiBcItin2LPYqti52LHYp9i2XCIsXG4gICAgJ3N0cm9uZyB0ZXh0JzogXCLZhti1INi62KfZhdmCXCIsXG4gICAgJ2VtcGhhc2l6ZWQgdGV4dCc6IFwi2YbYtSDZh9in2YVcIixcbiAgICAnaGVhZGluZyB0ZXh0JzogXCLYp9mE2LnZhtmI2KfZhlwiLFxuICAgICdlbnRlciBsaW5rIGRlc2NyaXB0aW9uIGhlcmUnOiBcItin2K/YrtmEINmI2LXZgSDYp9mE2LHYp9io2Lcg2YfZhtinXCIsXG4gICAgJ0luc2VydCBIeXBlcmxpbmsnOiBcItin2K/YrtmEINin2YTYsdin2KjYtyDZh9mG2KdcIixcbiAgICAnZW50ZXIgaW1hZ2UgZGVzY3JpcHRpb24gaGVyZSc6IFwi2KfYr9iu2YQg2YjYtdmBINin2YTYtdmI2LHYqSDZh9mG2KdcIixcbiAgICAnSW5zZXJ0IEltYWdlIEh5cGVybGluayc6IFwi2KfYr9iu2YQg2LHYp9io2Lcg2KfZhNi12YjYsdipINmH2YbYp1wiLFxuICAgICdlbnRlciBpbWFnZSB0aXRsZSBoZXJlJzogXCLYp9iv2K7ZhCDYudmG2YjYp9mGINin2YTYtdmI2LHYqSDZh9mG2KdcIixcbiAgICAnbGlzdCB0ZXh0IGhlcmUnOiBcItin2YPYqtioINin2YTZhti1INmH2YbYp1wiXG4gIH07XG59KGpRdWVyeSkpO1xuIiwiLyoqXG4gKiBDemVjaCB0cmFuc2xhdGlvbiBmb3IgYm9vdHN0cmFwLW1hcmtkb3duXG4gKiBWw610IEthYmVsZSA8dml0QGthYmVsZS5tZT5cbiAqL1xuKGZ1bmN0aW9uICgkKSB7XG4gICQuZm4ubWFya2Rvd24ubWVzc2FnZXMuY3MgPSB7XG4gICAgJ0JvbGQnOiBcIlR1xI1uxJtcIixcbiAgICAnSXRhbGljJzogXCJLdXJ6w612YVwiLFxuICAgICdIZWFkaW5nJzogXCJOYWRwaXNcIixcbiAgICAnVVJML0xpbmsnOiBcIlVSTC9PZGthelwiLFxuICAgICdJbWFnZSc6IFwiT2Jyw6F6ZWtcIixcbiAgICAnVW5vcmRlcmVkIExpc3QnOiBcIlNlem5hbVwiLFxuICAgICdPcmRlcmVkIExpc3QnOiBcIlNlxZlhemVuw70gc2V6bmFtXCIsXG4gICAgJ0NvZGUnOiBcIsOac2VrIGvDs2R1XCIsXG4gICAgJ1F1b3RlJzogXCJDaXRhY2VcIixcbiAgICAnUHJldmlldyc6IFwiTsOhaGxlZFwiLFxuICAgICdzdHJvbmcgdGV4dCc6IFwidHXEjW7DvSB0ZXh0XCIsXG4gICAgJ2VtcGhhc2l6ZWQgdGV4dCc6IFwiemTFr3Jhem7Em27DvSB0ZXh0XCIsXG4gICAgJ2hlYWRpbmcgdGV4dCc6IFwidGV4dCBuYWRwaXN1XCIsXG4gICAgJ2VudGVyIGxpbmsgZGVzY3JpcHRpb24gaGVyZSc6IFwic2VtIHZsb8W+IHBvcGlzIG9ka2F6dVwiLFxuICAgICdJbnNlcnQgSHlwZXJsaW5rJzogXCJWbG/Fvml0IEh5cGVybGlua1wiLFxuICAgICdlbnRlciBpbWFnZSBkZXNjcmlwdGlvbiBoZXJlJzogXCJzZW0gdmxvxb4gcG9waXMgb2Jyw6F6a3VcIixcbiAgICAnSW5zZXJ0IEltYWdlIEh5cGVybGluayc6IFwiVmxvxb4gYWRyZXN1IG9icsOhemt1XCIsXG4gICAgJ2VudGVyIGltYWdlIHRpdGxlIGhlcmUnOiBcInNlbSB2bG/FviBwb3BpcyBvYnLDoXprdVwiLFxuICAgICdsaXN0IHRleHQgaGVyZSc6IFwicG9sb8W+a2Egc2V6bmFtdVwiXG4gIH07XG59KGpRdWVyeSkpO1xuIiwiLyoqXG4gKiBEYW5pc2ggdHJhbnNsYXRpb24gZm9yIGJvb3RzdHJhcC1tYXJrZG93blxuICogRGFuIFN0b3JtIDxzdG9ybUBjYXRhbHlzdGNvZGUubmV0PlxuICovXG4oZnVuY3Rpb24gKCQpIHtcbiAgJC5mbi5tYXJrZG93bi5tZXNzYWdlcy5uYiA9IHtcbiAgICAnQm9sZCc6ICdGZWQnLFxuICAgICdJdGFsaWMnOiAnS3Vyc2l2JyxcbiAgICAnSGVhZGluZyc6ICdPdmVyc2tyaWZ0JyxcbiAgICAnVVJML0xpbmsnOiAnVVJML0xpbmsnLFxuICAgICdJbWFnZSc6ICdCaWxsZWRlJyxcbiAgICAnTGlzdCc6ICdMaXN0ZScsXG4gICAgJ1ByZXZpZXcnOiAnRm9yaMOlbmRzdmlzbmluZycsXG4gICAgJ3N0cm9uZyB0ZXh0JzogJ3N0w6ZyayB0ZWtzdCcsXG4gICAgJ2VtcGhhc2l6ZWQgdGV4dCc6ICdmcmVtaMOmdmV0IHRla3N0JyxcbiAgICAnaGVhZGluZyB0ZXh0JzogJ292ZXJza3JpZnQgdGVrc3QnLFxuICAgICdlbnRlciBsaW5rIGRlc2NyaXB0aW9uIGhlcmUnOiAnU2tyaXYgbGluayBiZXNrcml2ZWxzZSBoZXInLFxuICAgICdJbnNlcnQgSHlwZXJsaW5rJzogJ0luZHPDpnQgbGluaycsXG4gICAgJ2VudGVyIGltYWdlIGRlc2NyaXB0aW9uIGhlcmUnOiAnSW5kc8OmdCBiaWxsZWRlIGJlc2tyaXZlbHNlIGhlcicsXG4gICAgJ0luc2VydCBJbWFnZSBIeXBlcmxpbmsnOiAnSW5kc8OmdCBiaWxsZWRlIGxpbmsnLFxuICAgICdlbnRlciBpbWFnZSB0aXRsZSBoZXJlJzogJ0luZHPDpnQgYmlsbGVkZSB0aXRlbCcsXG4gICAgJ2xpc3QgdGV4dCBoZXJlJzogJ0luZHPDpnQgbGlzdGUgdGVrc3QgaGVyJyxcbiAgICAncXVvdGUgaGVyZSc6ICdJbmRzw6Z0IGNpdGF0IGhlcicsXG4gICAgJ2NvZGUgdGV4dCBoZXJlJzogJ0luZHPDpnQga29kZSBoZXInXG4gIH07XG59KGpRdWVyeSkpO1xuIiwiLyoqXG4gKiBHZXJtYW4gdHJhbnNsYXRpb24gZm9yIGJvb3RzdHJhcC1tYXJrZG93blxuICogVG9iaWFzIE5pdHNjaGUgPHRvYmlhcy1uaXRzY2hlQGdteC5uZXQ+XG4gKi9cbihmdW5jdGlvbiAoJCkge1xuICAkLmZuLm1hcmtkb3duLm1lc3NhZ2VzLmRlID0ge1xuICAgICdCb2xkJzogXCJGZXR0XCIsXG4gICAgJ0l0YWxpYyc6IFwiS3Vyc2l2XCIsXG4gICAgJ0hlYWRpbmcnOiBcIsOcYmVyc2NocmlmdFwiLFxuICAgICdVUkwvTGluayc6IFwiTGluayBoaW56dWbDvGdlblwiLFxuICAgICdJbWFnZSc6IFwiQmlsZCBoaW56dWbDvGdlblwiLFxuICAgICdVbm9yZGVyZWQgTGlzdCc6IFwiVW5udW1tZXJpZXJ0ZSBMaXN0ZVwiLFxuICAgICdPcmRlcmVkIExpc3QnOiBcIk51bW1lcmllcnRlIExpc3RlXCIsXG4gICAgJ0NvZGUnOiBcIlF1ZWxsdGV4dFwiLFxuICAgICdRdW90ZSc6IFwiWml0YXRcIixcbiAgICAnUHJldmlldyc6IFwiVm9yc2NoYXVcIixcbiAgICAnc3Ryb25nIHRleHQnOiBcIlNlaHIgYmV0b250ZXIgVGV4dFwiLFxuICAgICdlbXBoYXNpemVkIHRleHQnOiBcIkJldG9udGVyIFRleHRcIixcbiAgICAnaGVhZGluZyB0ZXh0JzogXCLDnGJlcnNjaHJpZnQgVGV4dFwiLFxuICAgICdlbnRlciBsaW5rIGRlc2NyaXB0aW9uIGhlcmUnOiBcIkxpbmtiZXNjaHJlaWJ1bmdcIixcbiAgICAnSW5zZXJ0IEh5cGVybGluayc6IFwiVVJMXCIsXG4gICAgJ2VudGVyIGltYWdlIGRlc2NyaXB0aW9uIGhlcmUnOiBcIkJpbGRiZXNjaHJlaWJ1bmdcIixcbiAgICAnSW5zZXJ0IEltYWdlIEh5cGVybGluayc6IFwiQmlsZC1VUkxcIixcbiAgICAnZW50ZXIgaW1hZ2UgdGl0bGUgaGVyZSc6IFwiVGl0ZWwgZGVzIEJpbGRlc1wiLFxuICAgICdsaXN0IHRleHQgaGVyZSc6IFwiQXVmesOkaGx1bmdzLVRleHRcIlxuICB9O1xufShqUXVlcnkpKTtcbiIsIi8qKlxuICogU3BhbmlzaCB0cmFuc2xhdGlvbiBmb3IgYm9vdHN0cmFwLW1hcmtkb3duXG4gKiBieSBMZWFuZHJvIFBvYmxldCA8bGVhbmRyb2RyaG91c2VAZ21haWwuY29tPlxuICovXG47KGZ1bmN0aW9uKCQpe1xuICAkLmZuLm1hcmtkb3duLm1lc3NhZ2VzWydlcyddID0ge1xuICAgICdCb2xkJzogXCJOZWdyaXRhXCIsXG4gICAgJ0l0YWxpYyc6IFwiSXTDoWxpY2FcIixcbiAgICAnSGVhZGluZyc6IFwiVMOtdHVsb1wiLFxuICAgICdVUkwvTGluayc6IFwiSW5zZXJ0ZSB1biBsaW5rXCIsXG4gICAgJ0ltYWdlJzogXCJJbnNlcnRlIHVuYSBpbWFnZW5cIixcbiAgICAnTGlzdCc6IFwiTGlzdGEgZGUgaXRlbXNcIixcbiAgICAnUHJldmlldyc6IFwiUHJldmlzdWFsaXphclwiLFxuICAgICdzdHJvbmcgdGV4dCc6IFwidGV4dG8gaW1wb3J0YW50ZVwiLFxuICAgICdlbXBoYXNpemVkIHRleHQnOiBcInRleHRvIGNvbiDDqW5mYXNpc1wiLFxuICAgICdoZWFkaW5nIHRleHQnOiBcInRleHRvIHRpdHVsYXJcIixcbiAgICAnZW50ZXIgbGluayBkZXNjcmlwdGlvbiBoZXJlJzogXCJkZXNjcmlwY2nDs24gZGVsIGxpbmtcIixcbiAgICAnSW5zZXJ0IEh5cGVybGluayc6IFwiSW5zZXJ0ZSB1biBoaXBlcnbDrW5jdWxvXCIsXG4gICAgJ2VudGVyIGltYWdlIGRlc2NyaXB0aW9uIGhlcmUnOiBcImRlc2NyaXBjacOzbiBkZSBsYSBpbWFnZW5cIixcbiAgICAnSW5zZXJ0IEltYWdlIEh5cGVybGluayc6IFwiSW5zZXJ0ZSB1bmEgaW1hZ2VuIGNvbiB1biBoaXBlcnbDrW5jdWxvXCIsXG4gICAgJ2VudGVyIGltYWdlIHRpdGxlIGhlcmUnOiBcIkluc2VydGUgdW5hIGltYWdlbiBjb24gdMOtdHVsb1wiLFxuICAgICdsaXN0IHRleHQgaGVyZSc6IFwibGlzdGEgY29uIHRleHRvXCJcbiAgfTtcbn0oalF1ZXJ5KSk7XG4iLCIvKipcbiAqIFBlcnNpYW4oRmFyc2kpIHRyYW5zbGF0aW9uIGZvciBib290c3RyYXAtbWFya2Rvd25cbiAqIFNhamFkIERlaHNoaXJpIDxQZWxha3dlYi5pcj5cbiAqL1xuKGZ1bmN0aW9uICgkKSB7XG4gICQuZm4ubWFya2Rvd24ubWVzc2FnZXMuZmEgPSB7XG4gICAgJ0JvbGQnOiBcItiq2YjZvtixXCIsXG4gICAgJ0l0YWxpYyc6IFwi2YXZiNix2KhcIixcbiAgICAnSGVhZGluZyc6IFwi2LnZhtmI2KfZhlwiLFxuICAgICdVUkwvTGluayc6IFwi2b7bjNmI2YbYr1wiLFxuICAgICdJbWFnZSc6IFwi2KrYtdmI24zYsVwiLFxuICAgICdMaXN0JzogXCLZgdmH2LHYs9iqXCIsXG4gICAgJ1ByZXZpZXcnOiBcItm+24zYtCDZhtmF2KfbjNi0XCIsXG4gICAgJ3N0cm9uZyB0ZXh0JzogXCLZhdiq2YYg2LbYrtuM2YVcIixcbiAgICAnZW1waGFzaXplZCB0ZXh0JzogXCLZhtmI2LTYqtmHINiq2KfaqduM2K/bjFwiLFxuICAgICdoZWFkaW5nIHRleHQnOiBcIti52YbZiNin2YZcIixcbiAgICAnZW50ZXIgbGluayBkZXNjcmlwdGlvbiBoZXJlJzogXCLYqtmI2LbbjNit2KfYqiDZvtuM2YjZhtivINix2Kcg2KjZhtmI24zYs9uM2K8uXCIsXG4gICAgJ0luc2VydCBIeXBlcmxpbmsnOiBcItm+24zZiNmG2K8g2LHYpyDYr9ix2Kwg2YbZhdin24zbjNivOlwiLFxuICAgICdlbnRlciBpbWFnZSBkZXNjcmlwdGlvbiBoZXJlJzogXCLYqtmI2LbbjNit24wg2KjYsdin24wg2KrYtdmI24wg2KjZhtmI24zYs9uM2K8uXCIsXG4gICAgJ0luc2VydCBJbWFnZSBIeXBlcmxpbmsnOiBcItii2K/YsdizINiq2LXZiNuM2LEg2LHYpyDYqNmG2YjbjNiz24zYry5cIixcbiAgICAnZW50ZXIgaW1hZ2UgdGl0bGUgaGVyZSc6IFwi2LnZhtmI2KfZhiDYqti12YjbjNixINix2Kcg2KfbjNmG2KzYpyDYqNmG2YjbjNiz24zYr1wiLFxuICAgICdsaXN0IHRleHQgaGVyZSc6IFwi2YXYrdmEINmF2KrZhiDZgdmH2LHYs9iqXCJcbiAgfTtcbn0oalF1ZXJ5KSk7XG4iLCIvKipcbiAqIEZyZW5jaCB0cmFuc2xhdGlvbiBmb3IgYm9vdHN0cmFwLW1hcmtkb3duXG4gKiBCZW5vw650IEJvdXJnZW9pcyA8YmllcmRva0BnbWFpbC5jb20+XG4gKi9cbihmdW5jdGlvbiAoJCkge1xuICAkLmZuLm1hcmtkb3duLm1lc3NhZ2VzLmZyID0ge1xuICAgICdCb2xkJzogXCJHcmFzXCIsXG4gICAgJ0l0YWxpYyc6IFwiSXRhbGlxdWVcIixcbiAgICAnSGVhZGluZyc6IFwiVGl0cmVcIixcbiAgICAnVVJML0xpbmsnOiBcIkluc8OpcmVyIHVuIGxpZW4gSFRUUFwiLFxuICAgICdJbWFnZSc6IFwiSW5zw6lyZXIgdW5lIGltYWdlXCIsXG4gICAgJ0xpc3QnOiBcIkxpc3RlIMOgIHB1Y2VzXCIsXG4gICAgJ1ByZXZpZXcnOiBcIlByw6l2aXN1YWxpc2VyXCIsXG4gICAgJ3N0cm9uZyB0ZXh0JzogXCJ0ZXh0ZSBpbXBvcnRhbnRcIixcbiAgICAnZW1waGFzaXplZCB0ZXh0JzogXCJ0ZXh0ZSBlbiBpdGFsaXF1ZVwiLFxuICAgICdoZWFkaW5nIHRleHQnOiBcInRleHRlIGQnZW50w6p0ZVwiLFxuICAgICdlbnRlciBsaW5rIGRlc2NyaXB0aW9uIGhlcmUnOiBcImVudHJleiBsYSBkZXNjcmlwdGlvbiBkdSBsaWVuIGljaVwiLFxuICAgICdJbnNlcnQgSHlwZXJsaW5rJzogXCJJbnPDqXJleiBsZSBsaWVuIGh5cGVydGV4dGVcIixcbiAgICAnZW50ZXIgaW1hZ2UgZGVzY3JpcHRpb24gaGVyZSc6IFwiZW50cmV6IGxhIGRlc2NyaXB0aW9uIGRlIGwnaW1hZ2UgaWNpXCIsXG4gICAgJ0luc2VydCBJbWFnZSBIeXBlcmxpbmsnOiBcIkluc8OpcmV6IGxlIGxpZW4gaHlwZXJ0ZXh0ZSBkZSBsJ2ltYWdlXCIsXG4gICAgJ2VudGVyIGltYWdlIHRpdGxlIGhlcmUnOiBcImVudHJleiBsZSB0aXRyZSBkZSBsJ2ltYWdlIGljaVwiLFxuICAgICdsaXN0IHRleHQgaGVyZSc6IFwidGV4dGUgw6AgcHVjZSBpY2lcIixcbiAgICAnU2F2ZSc6IFwiU2F1dmVnYXJkZXJcIixcbiAgICAnT3JkZXJlZCBMaXN0JzogXCJMaXN0ZSBvcmRvbm7DqWVcIixcbiAgICAnVW5vcmRlcmVkIExpc3QnOiBcIkxpc3RlIGTDqXNvcmRvbm7DqWVcIixcbiAgICAnUXVvdGUnOiBcIkNpdGF0aW9uXCIsXG4gICAgJ3F1b3RlIGhlcmUnOiBcIlZvdHJlIGNpdGF0aW9uXCIsXG4gICAgJ0NvZGUnOiBcIkNvZGVcIixcbiAgICAnY29kZSB0ZXh0IGhlcmUnOiBcIsOpY3JpcmUgZHUgY29kZSBpY2lcIlxuICB9O1xufShqUXVlcnkpKTtcbiIsIi8qKlxuICogSmFwYW5lc2UgdHJhbnNsYXRpb24gZm9yIGJvb3RzdHJhcC1tYXJrZG93blxuICogS2VudGEgTXVyYWthbWkgPGtudG1ya21AZ21haWwuY29tPlxuICovXG4oZnVuY3Rpb24gKCQpIHtcbiAgJC5mbi5tYXJrZG93bi5tZXNzYWdlc1snamEnXSA9IHtcbiAgICAnQm9sZCc6IFwi5aSq5a2XXCIsXG4gICAgJ0l0YWxpYyc6IFwi5pac5L2TXCIsXG4gICAgJ0hlYWRpbmcnOiBcIuimi+WHuuOBl1wiLFxuICAgICdVUkwvTGluayc6IFwi44Oq44Oz44KvXCIsXG4gICAgJ0ltYWdlJzogXCLnlLvlg49cIixcbiAgICAnVW5vcmRlcmVkIExpc3QnOiBcIuODquOCueODiFwiLFxuICAgICdPcmRlcmVkIExpc3QnOiBcIuaVsOWtl+ODquOCueODiFwiLFxuICAgICdDb2RlJzogXCLjgrPjg7zjg4lcIixcbiAgICAnUXVvdGUnOiBcIuW8leeUqFwiLFxuICAgICdQcmV2aWV3JzogXCLjg5fjg6zjg5Pjg6Xjg7xcIixcbiAgICAnc3Ryb25nIHRleHQnOiBcIuWkquWtl1wiLFxuICAgICdlbXBoYXNpemVkIHRleHQnOiBcIuW8t+iqv1wiLFxuICAgICdoZWFkaW5nIHRleHQnOiBcIuimi+WHuuOBl1wiLFxuICAgICdlbnRlciBsaW5rIGRlc2NyaXB0aW9uIGhlcmUnOiBcIuODquODs+OCr+iqrOaYjlwiLFxuICAgICdJbnNlcnQgSHlwZXJsaW5rJzogXCLjg6rjg7Pjgq/mjL/lhaVcIixcbiAgICAnZW50ZXIgaW1hZ2UgZGVzY3JpcHRpb24gaGVyZSc6IFwi55S75YOP6Kqs5piOXCIsXG4gICAgJ0luc2VydCBJbWFnZSBIeXBlcmxpbmsnOiBcIueUu+WDj+aMv+WFpVwiLFxuICAgICdlbnRlciBpbWFnZSB0aXRsZSBoZXJlJzogXCLnlLvlg4/jgr/jgqTjg4jjg6tcIixcbiAgICAnbGlzdCB0ZXh0IGhlcmUnOiBcIuODquOCueODiOaMv+WFpVwiLFxuICAgICdjb2RlIHRleHQgaGVyZSc6IFwi44Kz44O844OJXCIsXG4gICAgJ3F1b3RlIGhlcmUnOiBcIuW8leeUqOaMv+WFpVwiXG4gIH07XG59KGpRdWVyeSkpO1xuIiwiLyoqXG4gKyAqIEtvcmVhbiB0cmFuc2xhdGlvbiBmb3IgYm9vdHN0cmFwLW1hcmtkb3duXG4gKyAqIFdvb25nQmkgS2ltIDxzc2luc3NAZ21haWwuY29tPlxuICsgKi9cbjsoZnVuY3Rpb24oJCl7XG4gICQuZm4ubWFya2Rvd24ubWVzc2FnZXNbJ2tyJ10gPSB7XG4gICAgJ0JvbGQnOiBcIuynhO2VmOqyjFwiLFxuICAgICdJdGFsaWMnOiBcIuydtO2DpOumreyytFwiLFxuICAgICdIZWFkaW5nJzogXCLrqLjrpqzquIBcIixcbiAgICAnVVJML0xpbmsnOiBcIuunge2BrOyjvOyGjFwiLFxuICAgICdJbWFnZSc6IFwi7J2066+47KeAXCIsXG4gICAgJ0xpc3QnOiBcIuumrOyKpO2KuFwiLFxuICAgICdQcmV2aWV3JzogXCLrr7jrpqzrs7TquLBcIixcbiAgICAnc3Ryb25nIHRleHQnOiBcIuqwle2VnCDqsJXsobAg7YWN7Iqk7Yq4XCIsXG4gICAgJ2VtcGhhc2l6ZWQgdGV4dCc6IFwi6rCV7KGwIO2FjeyKpO2KuFwiLFxuICAgICdoZWFkaW5nIHRleHQnOiBcIuuouOumrOq4gCDthY3siqTtirhcIixcbiAgICAnZW50ZXIgbGluayBkZXNjcmlwdGlvbiBoZXJlJzogXCLsl6zquLDsl5Ag66eB7YGs7J2YIOyEpOuqheydhCDsoIHsnLzshLjsmpRcIixcbiAgICAnSW5zZXJ0IEh5cGVybGluayc6IFwi7ZWY7J207Y2866eB7YGsIOyCveyehVwiLFxuICAgICdlbnRlciBpbWFnZSBkZXNjcmlwdGlvbiBoZXJlJzogXCLsl6zquLDshLgg7J2066+47KeAIOyEpOuqheydhCDsoIHsnLzshLjsmpRcIixcbiAgICAnSW5zZXJ0IEltYWdlIEh5cGVybGluayc6IFwi7J2066+47KeAIOunge2BrCDsgr3snoVcIixcbiAgICAnZW50ZXIgaW1hZ2UgdGl0bGUgaGVyZSc6IFwi7Jes6riw7JeQIOydtOuvuOyngCDsoJzrqqnsnYQg7KCB7Jy87IS47JqUXCIsXG4gICAgJ2xpc3QgdGV4dCBoZXJlJzogXCLrpqzsiqTtirgg7YWN7Iqk7Yq4XCJcbiAgfTtcbn0oalF1ZXJ5KSk7XG4iLCIvKipcbiAqIE5vcndlZ2lhbiBib2ttw6VsIHRyYW5zbGF0aW9uIGZvciBib290c3RyYXAtbWFya2Rvd25cbiAqIFRvYmlhcyBCb2h3YWxsaSA8aGlAZnV0aHIuaW8+XG4gKi9cbihmdW5jdGlvbiAoJCkge1xuICAkLmZuLm1hcmtkb3duLm1lc3NhZ2VzLm5iID0ge1xuICAgICdCb2xkJzogJ0ZldCcsXG4gICAgJ0l0YWxpYyc6ICdLdXJzaXYnLFxuICAgICdIZWFkaW5nJzogJ092ZXJza3JpZnQnLFxuICAgICdVUkwvTGluayc6ICdVUkwvTGVua2UnLFxuICAgICdJbWFnZSc6ICdCaWxkZScsXG4gICAgJ0xpc3QnOiAnTGlzdGUnLFxuICAgICdQcmV2aWV3JzogJ0ZvcmjDpW5kc3Zpc25pbmcnLFxuICAgICdzdHJvbmcgdGV4dCc6ICdzdGVyayB0ZWtzdCcsXG4gICAgJ2VtcGhhc2l6ZWQgdGV4dCc6ICdzdHJla2V0IHRla3N0JyxcbiAgICAnaGVhZGluZyB0ZXh0JzogJ292ZXJza3JpZnRlbiB0ZWtzdCcsXG4gICAgJ2VudGVyIGxpbmsgZGVzY3JpcHRpb24gaGVyZSc6ICdTa3JpdiBsaW5rZW4gYmVza3JpdmVsc2UgaGVyJyxcbiAgICAnSW5zZXJ0IEh5cGVybGluayc6ICdTZXR0IGlubiBsZW5rZScsXG4gICAgJ2VudGVyIGltYWdlIGRlc2NyaXB0aW9uIGhlcmUnOiAnQW5naSBiaWxkZWJlc2tyaXZlbHNlIGhlcicsXG4gICAgJ0luc2VydCBJbWFnZSBIeXBlcmxpbmsnOiAnU2V0dCBpbm4gbGVua2UgZm9yIGJpbGRlJyxcbiAgICAnZW50ZXIgaW1hZ2UgdGl0bGUgaGVyZSc6ICdBbmdpIGJpbGRldGl0dGVsIGhlcicsXG4gICAgJ2xpc3QgdGV4dCBoZXJlJzogJ2xpc3RlIHRla3N0IGhlcidcbiAgfTtcbn0oalF1ZXJ5KSk7XG4iLCIvKipcbiAqIER1dGNoIHRyYW5zbGF0aW9uIGZvciBib290c3RyYXAtbWFya2Rvd25cbiAqIEplcm9lbiBUaG9yYSA8amVyb2VudGhvcmFAZ21haWwuY29tPlxuICovXG4oZnVuY3Rpb24gKCQpIHtcbiAgJC5mbi5tYXJrZG93bi5tZXNzYWdlcy5ubCA9IHtcbiAgICAnQm9sZCc6IFwiVmV0XCIsXG4gICAgJ0l0YWxpYyc6IFwiQ3Vyc2llZlwiLFxuICAgICdIZWFkaW5nJzogXCJUaXRlbFwiLFxuICAgICdVUkwvTGluayc6IFwiVVJML0xpbmtcIixcbiAgICAnSW1hZ2UnOiBcIkFmYmVlbGRpbmdcIixcbiAgICAnTGlzdCc6IFwiTGlqc3RcIixcbiAgICAnUHJldmlldyc6IFwiVm9vcmJlZWxkXCIsXG4gICAgJ3N0cm9uZyB0ZXh0JzogXCJ2ZXQgZ2VkcnVrdGUgdGVrc3RcIixcbiAgICAnZW1waGFzaXplZCB0ZXh0JzogXCJzY2h1aW4gZ2VkcnVrdGUgdGVrc3RcIixcbiAgICAnaGVhZGluZyB0ZXh0JzogXCJUaXRlbFwiLFxuICAgICdlbnRlciBsaW5rIGRlc2NyaXB0aW9uIGhlcmUnOiBcIlZvZXIgZWVuIGxpbmsgYmVzY2hyaWp2aW5nIGluXCIsXG4gICAgJ0luc2VydCBIeXBlcmxpbmsnOiBcIlZvZXIgZWVuIGh0dHAgbGluayBpblwiLFxuICAgICdlbnRlciBpbWFnZSBkZXNjcmlwdGlvbiBoZXJlJzogXCJWb2VyIGVlbiBhZmJlZWxkaW5nIGJlc2NocmlqdmluZyBpblwiLFxuICAgICdJbnNlcnQgSW1hZ2UgSHlwZXJsaW5rJzogXCJWb2VyIGVlbiBhZmJlZWxkaW5nIGxpbmsgaW5cIixcbiAgICAnZW50ZXIgaW1hZ2UgdGl0bGUgaGVyZSc6IFwiVm9lciBkZSBhZmJlZWxkaW5nIHRpdGVsIGluXCIsXG4gICAgJ2xpc3QgdGV4dCBoZXJlJzogXCJsaWpzdCBpdGVtXCJcbiAgfTtcbn0oalF1ZXJ5KSk7XG4iLCIvKipcbiAqIFBvbGlzaCB0cmFuc2xhdGlvbiBmb3IgYm9vdHN0cmFwLW1hcmtkb3duXG4gKiBNYXJlayBLYXB1dFxuICovXG4oZnVuY3Rpb24gKCQpIHtcbiAgJC5mbi5tYXJrZG93bi5tZXNzYWdlcy5wbCA9IHtcbiAgICAnQm9sZCc6IFwiUG9ncnViaWVuaWVcIixcbiAgICAnSXRhbGljJzogXCJLdXJzeXdhXCIsXG4gICAgJ0hlYWRpbmcnOiBcIk5hZ8WCw7N3ZWtcIixcbiAgICAnVVJML0xpbmsnOiBcIldzdGF3IGxpbmtcIixcbiAgICAnSW1hZ2UnOiBcIldzdGF3IG9icmF6ZWtcIixcbiAgICAnVW5vcmRlcmVkIExpc3QnOiBcIkxpc3RhIHB1bmt0b3dhbmFcIixcbiAgICAnT3JkZXJlZCBMaXN0JzogXCJMaXN0YSBudW1lcm93YW5hXCIsXG4gICAgJ0NvZGUnOiBcIktvZCDFunLDs2TFgm93eVwiLFxuICAgICdRdW90ZSc6IFwiQ3l0YXRcIixcbiAgICAnUHJldmlldyc6IFwiUG9kZ2zEhWRcIixcbiAgICAnc3Ryb25nIHRleHQnOiBcInBvZ3J1YmlvbnkgdGVrc3RcIixcbiAgICAnZW1waGFzaXplZCB0ZXh0JzogXCJwb2NoeWxvbnkgdGVrc3RcIixcbiAgICAnaGVhZGluZyB0ZXh0JzogXCJuYWfFgsOzd2VrXCIsXG4gICAgJ2VudGVyIGxpbmsgZGVzY3JpcHRpb24gaGVyZSc6IFwib3BpcyBsaW5rYVwiLFxuICAgICdJbnNlcnQgSHlwZXJsaW5rJzogXCJXc3RhdyBsaW5rXCIsXG4gICAgJ2VudGVyIGltYWdlIGRlc2NyaXB0aW9uIGhlcmUnOiBcIm9waXMgb2JyYXprYVwiLFxuICAgICdJbnNlcnQgSW1hZ2UgSHlwZXJsaW5rJzogXCJXc3RhdyBvYnJhemVrXCIsXG4gICAgJ2VudGVyIGltYWdlIHRpdGxlIGhlcmUnOiBcInR5dHXFgiBvYnJhemthXCIsXG4gICAgJ2xpc3QgdGV4dCBoZXJlJzogXCJsaXN0YVwiXG4gIH07XG59KGpRdWVyeSkpO1xuIiwiLyoqXG4gKiBTbG92ZW5pYW4gdHJhbnNsYXRpb24gZm9yIGJvb3RzdHJhcC1tYXJrZG93blxuICogRGF2b3IgUGFkb3ZhbiA8ZGF2b3IucGFkb3ZhbkBnbWFpbC5jb20+XG4gKi9cbihmdW5jdGlvbiAoJCkge1xuICAkLmZuLm1hcmtkb3duLm1lc3NhZ2VzLnNsID0ge1xuICAgICdCb2xkJzogXCJPZGViZWxqZW5vXCIsXG4gICAgJ0l0YWxpYyc6IFwiUG/FoWV2bm9cIixcbiAgICAnSGVhZGluZyc6IFwiTmFzbG92XCIsXG4gICAgJ1VSTC9MaW5rJzogXCJQb3ZlemF2YVwiLFxuICAgICdJbWFnZSc6IFwiU2xpa2FcIixcbiAgICAnVW5vcmRlcmVkIExpc3QnOiBcIk5ldXJlamVuIHNlem5hbVwiLFxuICAgICdPcmRlcmVkIExpc3QnOiBcIlVyZWplbiBzZXpuYW1cIixcbiAgICAnQ29kZSc6IFwiS29kYVwiLFxuICAgICdRdW90ZSc6IFwiQ2l0YXRcIixcbiAgICAnUHJldmlldyc6IFwiUHJlZG9nbGVkXCIsXG4gICAgJ3N0cm9uZyB0ZXh0JzogXCJvZGViZWxqZW5vIGJlc2VkaWxvXCIsXG4gICAgJ2VtcGhhc2l6ZWQgdGV4dCc6IFwicG/FoWV2bm8gYmVzZWRpbG9cIixcbiAgICAnaGVhZGluZyB0ZXh0JzogXCJuYXNsb3ZcIixcbiAgICAnZW50ZXIgbGluayBkZXNjcmlwdGlvbiBoZXJlJzogXCJvcGlzIHBvdmV6YXZlXCIsXG4gICAgJ0luc2VydCBIeXBlcmxpbmsnOiBcIlZzdGF2aSBwb3ZlemF2b1wiLFxuICAgICdlbnRlciBpbWFnZSBkZXNjcmlwdGlvbiBoZXJlJzogXCJvcGlzIHNsaWtlXCIsXG4gICAgJ0luc2VydCBJbWFnZSBIeXBlcmxpbmsnOiBcIlZzdGF2aSBwb3ZlemF2byBkbyBzbGlrZVwiLFxuICAgICdlbnRlciBpbWFnZSB0aXRsZSBoZXJlJzogXCJuYXNsb3Ygc2xpa2VcIixcbiAgICAnbGlzdCB0ZXh0IGhlcmUnOiBcInNlem5hbVwiXG4gIH07XG59KGpRdWVyeSkpO1xuIiwiLyoqXG4gKiBTd2VkaXNoIHRyYW5zbGF0aW9uIGZvciBib290c3RyYXAtbWFya2Rvd25cbiAqIFRvYmlhcyBCb2h3YWxsaSA8aGlAZnV0aHIuaW8+XG4gKi9cbihmdW5jdGlvbiAoJCkge1xuICAkLmZuLm1hcmtkb3duLm1lc3NhZ2VzLnN2ID0ge1xuICAgICdCb2xkJzogJ0ZldCcsXG4gICAgJ0l0YWxpYyc6ICdLdXJzaXYnLFxuICAgICdIZWFkaW5nJzogJ1J1YnJpaycsXG4gICAgJ1VSTC9MaW5rJzogJ1VSTC9Mw6RuaycsXG4gICAgJ0ltYWdlJzogJ0JpbGQnLFxuICAgICdMaXN0JzogJ0xpc3RhJyxcbiAgICAnUHJldmlldyc6ICdGw7ZyaGFuZHNncmFuc2thJyxcbiAgICAnc3Ryb25nIHRleHQnOiAnZmV0IHRleHQnLFxuICAgICdlbXBoYXNpemVkIHRleHQnOiAnw7Z2ZXJzdHJ1a2VuIHRleHQnLFxuICAgICdoZWFkaW5nIHRleHQnOiAnUnVicmlrJyxcbiAgICAnZW50ZXIgbGluayBkZXNjcmlwdGlvbiBoZXJlJzogJ0FuZ2UgbMOkbmsgYmVza3Jpdm5pbmcgaMOkcicsXG4gICAgJ0luc2VydCBIeXBlcmxpbmsnOiAnU8OkdHQgaW4gbMOkbmsnLFxuICAgICdlbnRlciBpbWFnZSBkZXNjcmlwdGlvbiBoZXJlJzogJ0FuZ2UgYmlsZCBiZXNrcml2bmluZyBow6RyJyxcbiAgICAnSW5zZXJ0IEltYWdlIEh5cGVybGluayc6ICdTw6R0dCBpbiBsw6RuayBmw7ZyIGJpbGQnLFxuICAgICdlbnRlciBpbWFnZSB0aXRsZSBoZXJlJzogJ0FuZ2UgYmlsZCBydWJyaWsgaMOkcicsXG4gICAgJ2xpc3QgdGV4dCBoZXJlJzogJ2xpc3QgdGV4dCdcbiAgfTtcbn0oalF1ZXJ5KSk7XG4iLCIvKipcbiAqIFR1cmtpc2ggdHJhbnNsYXRpb24gZm9yIGJvb3RzdHJhcC1tYXJrZG93blxuICogU2Vya2FuIEFsZ3VyIDxpbmZvQHdwYWRhbWkuY29tPlxuICovXG4oZnVuY3Rpb24gKCQpIHtcbiAgJC5mbi5tYXJrZG93bi5tZXNzYWdlcy50ciA9IHtcbiAgICAnQm9sZCc6IFwiS2FsxLFuXCIsXG4gICAgJ0l0YWxpYyc6IFwixLB0YWxpa1wiLFxuICAgICdIZWFkaW5nJzogXCJCYcWfbMSxa1wiLFxuICAgICdVUkwvTGluayc6IFwiTGluayBla2xlXCIsXG4gICAgJ0ltYWdlJzogXCJSZXNpbSBla2xlXCIsXG4gICAgJ0xpc3QnOiBcIkxpc3RlIE9sdcWfdHVydW5cIixcbiAgICAnUHJldmlldyc6IFwiw5ZuaXpsZW1lXCIsXG4gICAgJ3N0cm9uZyB0ZXh0JzogXCJrYWzEsW4geWF6xLFcIixcbiAgICAnZW1waGFzaXplZCB0ZXh0JzogXCJpdGFsaWsgeWF6xLFcIixcbiAgICAnaGVhZGluZyB0ZXh0JzogXCJCYcWfbMSxayBZYXrEsXPEsVwiLFxuICAgICdlbnRlciBsaW5rIGRlc2NyaXB0aW9uIGhlcmUnOiBcIkxpbmsgYcOnxLFrbGFtYXPEsW7EsSBidXJheWEgZ2lyaW5cIixcbiAgICAnSW5zZXJ0IEh5cGVybGluayc6IFwixLBudGVybmV0IGFkcmVzaSBnaXJpblwiLFxuICAgICdlbnRlciBpbWFnZSBkZXNjcmlwdGlvbiBoZXJlJzogXCJyZXNpbSBhw6fEsWtsYW1hc8SxbsSxIGJ1cmF5YSBla2xleWluXCIsXG4gICAgJ0luc2VydCBJbWFnZSBIeXBlcmxpbmsnOiBcIlJlc2ltIGxpbmtpbmkgZWtsZXlpblwiLFxuICAgICdlbnRlciBpbWFnZSB0aXRsZSBoZXJlJzogXCJyZXNpbSBiYcWfbMSxxJ/EsW7EsSBidXJheWEgZWtsZXlpblwiLFxuICAgICdsaXN0IHRleHQgaGVyZSc6IFwibGlzdGUgeWF6xLFzxLFcIixcbiAgICAnU2F2ZScgOiBcIktheWRldFwiLFxuICAgICdPcmRlcmVkIExpc3QnIDogXCJOdW1hcmFsxLEgTGlzdGVcIixcbiAgICAnVW5vcmRlcmVkIExpc3QnIDogXCJNYWRkZSBpbWxpIGxpc3RlXCIsXG4gICAgJ1F1b3RlJyA6IFwiQWzEsW50xLFcIixcbiAgICAncXVvdGUgaGVyZScgOiBcImFsxLFudMSxecSxIGJ1cmF5YSBla2xleWluXCIsXG4gICAgJ0NvZGUnIDogXCJLb2RcIixcbiAgICAnY29kZSB0ZXh0IGhlcmUnIDogXCJrb2R1IGJ1cmF5YSBla2xleWluXCJcbiAgfTtcbn0oalF1ZXJ5KSk7XG4iLCIvKipcbiAqIENoaW5lc2UgdHJhbnNsYXRpb24gZm9yIGJvb3RzdHJhcC1tYXJrZG93blxuICogYmVuaGFpbGUgPGRlbmdoYWllckAxNjMuY29tPlxuICovXG4oZnVuY3Rpb24gKCQpIHtcbiAgJC5mbi5tYXJrZG93bi5tZXNzYWdlcy56aCA9IHtcbiAgICAnQm9sZCc6IFwi57KX5L2TXCIsXG4gICAgJ0l0YWxpYyc6IFwi5pac5L2TXCIsXG4gICAgJ0hlYWRpbmcnOiBcIuagh+mimFwiLFxuICAgICdVUkwvTGluayc6IFwi6ZO+5o6lXCIsXG4gICAgJ0ltYWdlJzogXCLlm77niYdcIixcbiAgICAnTGlzdCc6IFwi5YiX6KGoXCIsXG4gICAgJ1Vub3JkZXJlZCBMaXN0JzogXCLml6Dluo/liJfooahcIixcbiAgICAnT3JkZXJlZCBMaXN0JzogXCLmnInluo/liJfooahcIixcbiAgICAnQ29kZSc6IFwi5Luj56CBXCIsXG4gICAgJ1F1b3RlJzogXCLlvJXnlKhcIixcbiAgICAnUHJldmlldyc6IFwi6aKE6KeIXCIsXG4gICAgJ3N0cm9uZyB0ZXh0JzogXCLnspfkvZNcIixcbiAgICAnZW1waGFzaXplZCB0ZXh0JzogXCLlvLrosINcIixcbiAgICAnaGVhZGluZyB0ZXh0JzogXCLmoIfpophcIixcbiAgICAnZW50ZXIgbGluayBkZXNjcmlwdGlvbiBoZXJlJzogXCLovpPlhaXpk77mjqXor7TmmI5cIixcbiAgICAnSW5zZXJ0IEh5cGVybGluayc6IFwiVVJM5Zyw5Z2AXCIsXG4gICAgJ2VudGVyIGltYWdlIGRlc2NyaXB0aW9uIGhlcmUnOiBcIui+k+WFpeWbvueJh+ivtOaYjlwiLFxuICAgICdJbnNlcnQgSW1hZ2UgSHlwZXJsaW5rJzogXCLlm77niYdVUkzlnLDlnYBcIixcbiAgICAnZW50ZXIgaW1hZ2UgdGl0bGUgaGVyZSc6IFwi5Zyo6L+Z6YeM6L6T5YWl5Zu+54mH5qCH6aKYXCIsXG4gICAgJ2xpc3QgdGV4dCBoZXJlJzogXCLov5nph4zmmK/liJfooajmlofmnKxcIixcbiAgICAnY29kZSB0ZXh0IGhlcmUnOiBcIui/memHjOi+k+WFpeS7o+eggVwiLFxuICAgICdxdW90ZSBoZXJlJzogXCLov5nph4zovpPlhaXlvJXnlKjmlofmnKxcIlxuXG5cbiAgfTtcbn0oalF1ZXJ5KSk7XG4iLCIoZnVuY3Rpb24gZGVmaW5lTXVzdGFjaGUoZ2xvYmFsLGZhY3Rvcnkpe2lmKHR5cGVvZiBleHBvcnRzPT09XCJvYmplY3RcIiYmZXhwb3J0cyYmdHlwZW9mIGV4cG9ydHMubm9kZU5hbWUhPT1cInN0cmluZ1wiKXtmYWN0b3J5KGV4cG9ydHMpfWVsc2UgaWYodHlwZW9mIGRlZmluZT09PVwiZnVuY3Rpb25cIiYmZGVmaW5lLmFtZCl7ZGVmaW5lKFtcImV4cG9ydHNcIl0sZmFjdG9yeSl9ZWxzZXtnbG9iYWwuTXVzdGFjaGU9e307ZmFjdG9yeShnbG9iYWwuTXVzdGFjaGUpfX0pKHRoaXMsZnVuY3Rpb24gbXVzdGFjaGVGYWN0b3J5KG11c3RhY2hlKXt2YXIgb2JqZWN0VG9TdHJpbmc9T2JqZWN0LnByb3RvdHlwZS50b1N0cmluZzt2YXIgaXNBcnJheT1BcnJheS5pc0FycmF5fHxmdW5jdGlvbiBpc0FycmF5UG9seWZpbGwob2JqZWN0KXtyZXR1cm4gb2JqZWN0VG9TdHJpbmcuY2FsbChvYmplY3QpPT09XCJbb2JqZWN0IEFycmF5XVwifTtmdW5jdGlvbiBpc0Z1bmN0aW9uKG9iamVjdCl7cmV0dXJuIHR5cGVvZiBvYmplY3Q9PT1cImZ1bmN0aW9uXCJ9ZnVuY3Rpb24gdHlwZVN0cihvYmope3JldHVybiBpc0FycmF5KG9iaik/XCJhcnJheVwiOnR5cGVvZiBvYmp9ZnVuY3Rpb24gZXNjYXBlUmVnRXhwKHN0cmluZyl7cmV0dXJuIHN0cmluZy5yZXBsYWNlKC9bXFwtXFxbXFxde30oKSorPy4sXFxcXFxcXiR8I1xcc10vZyxcIlxcXFwkJlwiKX1mdW5jdGlvbiBoYXNQcm9wZXJ0eShvYmoscHJvcE5hbWUpe3JldHVybiBvYmohPW51bGwmJnR5cGVvZiBvYmo9PT1cIm9iamVjdFwiJiZwcm9wTmFtZSBpbiBvYmp9dmFyIHJlZ0V4cFRlc3Q9UmVnRXhwLnByb3RvdHlwZS50ZXN0O2Z1bmN0aW9uIHRlc3RSZWdFeHAocmUsc3RyaW5nKXtyZXR1cm4gcmVnRXhwVGVzdC5jYWxsKHJlLHN0cmluZyl9dmFyIG5vblNwYWNlUmU9L1xcUy87ZnVuY3Rpb24gaXNXaGl0ZXNwYWNlKHN0cmluZyl7cmV0dXJuIXRlc3RSZWdFeHAobm9uU3BhY2VSZSxzdHJpbmcpfXZhciBlbnRpdHlNYXA9e1wiJlwiOlwiJmFtcDtcIixcIjxcIjpcIiZsdDtcIixcIj5cIjpcIiZndDtcIiwnXCInOlwiJnF1b3Q7XCIsXCInXCI6XCImIzM5O1wiLFwiL1wiOlwiJiN4MkY7XCIsXCJgXCI6XCImI3g2MDtcIixcIj1cIjpcIiYjeDNEO1wifTtmdW5jdGlvbiBlc2NhcGVIdG1sKHN0cmluZyl7cmV0dXJuIFN0cmluZyhzdHJpbmcpLnJlcGxhY2UoL1smPD5cIidgPVxcL10vZyxmdW5jdGlvbiBmcm9tRW50aXR5TWFwKHMpe3JldHVybiBlbnRpdHlNYXBbc119KX12YXIgd2hpdGVSZT0vXFxzKi87dmFyIHNwYWNlUmU9L1xccysvO3ZhciBlcXVhbHNSZT0vXFxzKj0vO3ZhciBjdXJseVJlPS9cXHMqXFx9Lzt2YXIgdGFnUmU9LyN8XFxefFxcL3w+fFxce3wmfD18IS87ZnVuY3Rpb24gcGFyc2VUZW1wbGF0ZSh0ZW1wbGF0ZSx0YWdzKXtpZighdGVtcGxhdGUpcmV0dXJuW107dmFyIHNlY3Rpb25zPVtdO3ZhciB0b2tlbnM9W107dmFyIHNwYWNlcz1bXTt2YXIgaGFzVGFnPWZhbHNlO3ZhciBub25TcGFjZT1mYWxzZTtmdW5jdGlvbiBzdHJpcFNwYWNlKCl7aWYoaGFzVGFnJiYhbm9uU3BhY2Upe3doaWxlKHNwYWNlcy5sZW5ndGgpZGVsZXRlIHRva2Vuc1tzcGFjZXMucG9wKCldfWVsc2V7c3BhY2VzPVtdfWhhc1RhZz1mYWxzZTtub25TcGFjZT1mYWxzZX12YXIgb3BlbmluZ1RhZ1JlLGNsb3NpbmdUYWdSZSxjbG9zaW5nQ3VybHlSZTtmdW5jdGlvbiBjb21waWxlVGFncyh0YWdzVG9Db21waWxlKXtpZih0eXBlb2YgdGFnc1RvQ29tcGlsZT09PVwic3RyaW5nXCIpdGFnc1RvQ29tcGlsZT10YWdzVG9Db21waWxlLnNwbGl0KHNwYWNlUmUsMik7aWYoIWlzQXJyYXkodGFnc1RvQ29tcGlsZSl8fHRhZ3NUb0NvbXBpbGUubGVuZ3RoIT09Mil0aHJvdyBuZXcgRXJyb3IoXCJJbnZhbGlkIHRhZ3M6IFwiK3RhZ3NUb0NvbXBpbGUpO29wZW5pbmdUYWdSZT1uZXcgUmVnRXhwKGVzY2FwZVJlZ0V4cCh0YWdzVG9Db21waWxlWzBdKStcIlxcXFxzKlwiKTtjbG9zaW5nVGFnUmU9bmV3IFJlZ0V4cChcIlxcXFxzKlwiK2VzY2FwZVJlZ0V4cCh0YWdzVG9Db21waWxlWzFdKSk7Y2xvc2luZ0N1cmx5UmU9bmV3IFJlZ0V4cChcIlxcXFxzKlwiK2VzY2FwZVJlZ0V4cChcIn1cIit0YWdzVG9Db21waWxlWzFdKSl9Y29tcGlsZVRhZ3ModGFnc3x8bXVzdGFjaGUudGFncyk7dmFyIHNjYW5uZXI9bmV3IFNjYW5uZXIodGVtcGxhdGUpO3ZhciBzdGFydCx0eXBlLHZhbHVlLGNocix0b2tlbixvcGVuU2VjdGlvbjt3aGlsZSghc2Nhbm5lci5lb3MoKSl7c3RhcnQ9c2Nhbm5lci5wb3M7dmFsdWU9c2Nhbm5lci5zY2FuVW50aWwob3BlbmluZ1RhZ1JlKTtpZih2YWx1ZSl7Zm9yKHZhciBpPTAsdmFsdWVMZW5ndGg9dmFsdWUubGVuZ3RoO2k8dmFsdWVMZW5ndGg7KytpKXtjaHI9dmFsdWUuY2hhckF0KGkpO2lmKGlzV2hpdGVzcGFjZShjaHIpKXtzcGFjZXMucHVzaCh0b2tlbnMubGVuZ3RoKX1lbHNle25vblNwYWNlPXRydWV9dG9rZW5zLnB1c2goW1widGV4dFwiLGNocixzdGFydCxzdGFydCsxXSk7c3RhcnQrPTE7aWYoY2hyPT09XCJcXG5cIilzdHJpcFNwYWNlKCl9fWlmKCFzY2FubmVyLnNjYW4ob3BlbmluZ1RhZ1JlKSlicmVhaztoYXNUYWc9dHJ1ZTt0eXBlPXNjYW5uZXIuc2Nhbih0YWdSZSl8fFwibmFtZVwiO3NjYW5uZXIuc2Nhbih3aGl0ZVJlKTtpZih0eXBlPT09XCI9XCIpe3ZhbHVlPXNjYW5uZXIuc2NhblVudGlsKGVxdWFsc1JlKTtzY2FubmVyLnNjYW4oZXF1YWxzUmUpO3NjYW5uZXIuc2NhblVudGlsKGNsb3NpbmdUYWdSZSl9ZWxzZSBpZih0eXBlPT09XCJ7XCIpe3ZhbHVlPXNjYW5uZXIuc2NhblVudGlsKGNsb3NpbmdDdXJseVJlKTtzY2FubmVyLnNjYW4oY3VybHlSZSk7c2Nhbm5lci5zY2FuVW50aWwoY2xvc2luZ1RhZ1JlKTt0eXBlPVwiJlwifWVsc2V7dmFsdWU9c2Nhbm5lci5zY2FuVW50aWwoY2xvc2luZ1RhZ1JlKX1pZighc2Nhbm5lci5zY2FuKGNsb3NpbmdUYWdSZSkpdGhyb3cgbmV3IEVycm9yKFwiVW5jbG9zZWQgdGFnIGF0IFwiK3NjYW5uZXIucG9zKTt0b2tlbj1bdHlwZSx2YWx1ZSxzdGFydCxzY2FubmVyLnBvc107dG9rZW5zLnB1c2godG9rZW4pO2lmKHR5cGU9PT1cIiNcInx8dHlwZT09PVwiXlwiKXtzZWN0aW9ucy5wdXNoKHRva2VuKX1lbHNlIGlmKHR5cGU9PT1cIi9cIil7b3BlblNlY3Rpb249c2VjdGlvbnMucG9wKCk7aWYoIW9wZW5TZWN0aW9uKXRocm93IG5ldyBFcnJvcignVW5vcGVuZWQgc2VjdGlvbiBcIicrdmFsdWUrJ1wiIGF0ICcrc3RhcnQpO2lmKG9wZW5TZWN0aW9uWzFdIT09dmFsdWUpdGhyb3cgbmV3IEVycm9yKCdVbmNsb3NlZCBzZWN0aW9uIFwiJytvcGVuU2VjdGlvblsxXSsnXCIgYXQgJytzdGFydCl9ZWxzZSBpZih0eXBlPT09XCJuYW1lXCJ8fHR5cGU9PT1cIntcInx8dHlwZT09PVwiJlwiKXtub25TcGFjZT10cnVlfWVsc2UgaWYodHlwZT09PVwiPVwiKXtjb21waWxlVGFncyh2YWx1ZSl9fW9wZW5TZWN0aW9uPXNlY3Rpb25zLnBvcCgpO2lmKG9wZW5TZWN0aW9uKXRocm93IG5ldyBFcnJvcignVW5jbG9zZWQgc2VjdGlvbiBcIicrb3BlblNlY3Rpb25bMV0rJ1wiIGF0ICcrc2Nhbm5lci5wb3MpO3JldHVybiBuZXN0VG9rZW5zKHNxdWFzaFRva2Vucyh0b2tlbnMpKX1mdW5jdGlvbiBzcXVhc2hUb2tlbnModG9rZW5zKXt2YXIgc3F1YXNoZWRUb2tlbnM9W107dmFyIHRva2VuLGxhc3RUb2tlbjtmb3IodmFyIGk9MCxudW1Ub2tlbnM9dG9rZW5zLmxlbmd0aDtpPG51bVRva2VuczsrK2kpe3Rva2VuPXRva2Vuc1tpXTtpZih0b2tlbil7aWYodG9rZW5bMF09PT1cInRleHRcIiYmbGFzdFRva2VuJiZsYXN0VG9rZW5bMF09PT1cInRleHRcIil7bGFzdFRva2VuWzFdKz10b2tlblsxXTtsYXN0VG9rZW5bM109dG9rZW5bM119ZWxzZXtzcXVhc2hlZFRva2Vucy5wdXNoKHRva2VuKTtsYXN0VG9rZW49dG9rZW59fX1yZXR1cm4gc3F1YXNoZWRUb2tlbnN9ZnVuY3Rpb24gbmVzdFRva2Vucyh0b2tlbnMpe3ZhciBuZXN0ZWRUb2tlbnM9W107dmFyIGNvbGxlY3Rvcj1uZXN0ZWRUb2tlbnM7dmFyIHNlY3Rpb25zPVtdO3ZhciB0b2tlbixzZWN0aW9uO2Zvcih2YXIgaT0wLG51bVRva2Vucz10b2tlbnMubGVuZ3RoO2k8bnVtVG9rZW5zOysraSl7dG9rZW49dG9rZW5zW2ldO3N3aXRjaCh0b2tlblswXSl7Y2FzZVwiI1wiOmNhc2VcIl5cIjpjb2xsZWN0b3IucHVzaCh0b2tlbik7c2VjdGlvbnMucHVzaCh0b2tlbik7Y29sbGVjdG9yPXRva2VuWzRdPVtdO2JyZWFrO2Nhc2VcIi9cIjpzZWN0aW9uPXNlY3Rpb25zLnBvcCgpO3NlY3Rpb25bNV09dG9rZW5bMl07Y29sbGVjdG9yPXNlY3Rpb25zLmxlbmd0aD4wP3NlY3Rpb25zW3NlY3Rpb25zLmxlbmd0aC0xXVs0XTpuZXN0ZWRUb2tlbnM7YnJlYWs7ZGVmYXVsdDpjb2xsZWN0b3IucHVzaCh0b2tlbil9fXJldHVybiBuZXN0ZWRUb2tlbnN9ZnVuY3Rpb24gU2Nhbm5lcihzdHJpbmcpe3RoaXMuc3RyaW5nPXN0cmluZzt0aGlzLnRhaWw9c3RyaW5nO3RoaXMucG9zPTB9U2Nhbm5lci5wcm90b3R5cGUuZW9zPWZ1bmN0aW9uIGVvcygpe3JldHVybiB0aGlzLnRhaWw9PT1cIlwifTtTY2FubmVyLnByb3RvdHlwZS5zY2FuPWZ1bmN0aW9uIHNjYW4ocmUpe3ZhciBtYXRjaD10aGlzLnRhaWwubWF0Y2gocmUpO2lmKCFtYXRjaHx8bWF0Y2guaW5kZXghPT0wKXJldHVyblwiXCI7dmFyIHN0cmluZz1tYXRjaFswXTt0aGlzLnRhaWw9dGhpcy50YWlsLnN1YnN0cmluZyhzdHJpbmcubGVuZ3RoKTt0aGlzLnBvcys9c3RyaW5nLmxlbmd0aDtyZXR1cm4gc3RyaW5nfTtTY2FubmVyLnByb3RvdHlwZS5zY2FuVW50aWw9ZnVuY3Rpb24gc2NhblVudGlsKHJlKXt2YXIgaW5kZXg9dGhpcy50YWlsLnNlYXJjaChyZSksbWF0Y2g7c3dpdGNoKGluZGV4KXtjYXNlLTE6bWF0Y2g9dGhpcy50YWlsO3RoaXMudGFpbD1cIlwiO2JyZWFrO2Nhc2UgMDptYXRjaD1cIlwiO2JyZWFrO2RlZmF1bHQ6bWF0Y2g9dGhpcy50YWlsLnN1YnN0cmluZygwLGluZGV4KTt0aGlzLnRhaWw9dGhpcy50YWlsLnN1YnN0cmluZyhpbmRleCl9dGhpcy5wb3MrPW1hdGNoLmxlbmd0aDtyZXR1cm4gbWF0Y2h9O2Z1bmN0aW9uIENvbnRleHQodmlldyxwYXJlbnRDb250ZXh0KXt0aGlzLnZpZXc9dmlldzt0aGlzLmNhY2hlPXtcIi5cIjp0aGlzLnZpZXd9O3RoaXMucGFyZW50PXBhcmVudENvbnRleHR9Q29udGV4dC5wcm90b3R5cGUucHVzaD1mdW5jdGlvbiBwdXNoKHZpZXcpe3JldHVybiBuZXcgQ29udGV4dCh2aWV3LHRoaXMpfTtDb250ZXh0LnByb3RvdHlwZS5sb29rdXA9ZnVuY3Rpb24gbG9va3VwKG5hbWUpe3ZhciBjYWNoZT10aGlzLmNhY2hlO3ZhciB2YWx1ZTtpZihjYWNoZS5oYXNPd25Qcm9wZXJ0eShuYW1lKSl7dmFsdWU9Y2FjaGVbbmFtZV19ZWxzZXt2YXIgY29udGV4dD10aGlzLG5hbWVzLGluZGV4LGxvb2t1cEhpdD1mYWxzZTt3aGlsZShjb250ZXh0KXtpZihuYW1lLmluZGV4T2YoXCIuXCIpPjApe3ZhbHVlPWNvbnRleHQudmlldztuYW1lcz1uYW1lLnNwbGl0KFwiLlwiKTtpbmRleD0wO3doaWxlKHZhbHVlIT1udWxsJiZpbmRleDxuYW1lcy5sZW5ndGgpe2lmKGluZGV4PT09bmFtZXMubGVuZ3RoLTEpbG9va3VwSGl0PWhhc1Byb3BlcnR5KHZhbHVlLG5hbWVzW2luZGV4XSk7dmFsdWU9dmFsdWVbbmFtZXNbaW5kZXgrK11dfX1lbHNle3ZhbHVlPWNvbnRleHQudmlld1tuYW1lXTtsb29rdXBIaXQ9aGFzUHJvcGVydHkoY29udGV4dC52aWV3LG5hbWUpfWlmKGxvb2t1cEhpdClicmVhaztjb250ZXh0PWNvbnRleHQucGFyZW50fWNhY2hlW25hbWVdPXZhbHVlfWlmKGlzRnVuY3Rpb24odmFsdWUpKXZhbHVlPXZhbHVlLmNhbGwodGhpcy52aWV3KTtyZXR1cm4gdmFsdWV9O2Z1bmN0aW9uIFdyaXRlcigpe3RoaXMuY2FjaGU9e319V3JpdGVyLnByb3RvdHlwZS5jbGVhckNhY2hlPWZ1bmN0aW9uIGNsZWFyQ2FjaGUoKXt0aGlzLmNhY2hlPXt9fTtXcml0ZXIucHJvdG90eXBlLnBhcnNlPWZ1bmN0aW9uIHBhcnNlKHRlbXBsYXRlLHRhZ3Mpe3ZhciBjYWNoZT10aGlzLmNhY2hlO3ZhciB0b2tlbnM9Y2FjaGVbdGVtcGxhdGVdO2lmKHRva2Vucz09bnVsbCl0b2tlbnM9Y2FjaGVbdGVtcGxhdGVdPXBhcnNlVGVtcGxhdGUodGVtcGxhdGUsdGFncyk7cmV0dXJuIHRva2Vuc307V3JpdGVyLnByb3RvdHlwZS5yZW5kZXI9ZnVuY3Rpb24gcmVuZGVyKHRlbXBsYXRlLHZpZXcscGFydGlhbHMpe3ZhciB0b2tlbnM9dGhpcy5wYXJzZSh0ZW1wbGF0ZSk7dmFyIGNvbnRleHQ9dmlldyBpbnN0YW5jZW9mIENvbnRleHQ/dmlldzpuZXcgQ29udGV4dCh2aWV3KTtyZXR1cm4gdGhpcy5yZW5kZXJUb2tlbnModG9rZW5zLGNvbnRleHQscGFydGlhbHMsdGVtcGxhdGUpfTtXcml0ZXIucHJvdG90eXBlLnJlbmRlclRva2Vucz1mdW5jdGlvbiByZW5kZXJUb2tlbnModG9rZW5zLGNvbnRleHQscGFydGlhbHMsb3JpZ2luYWxUZW1wbGF0ZSl7dmFyIGJ1ZmZlcj1cIlwiO3ZhciB0b2tlbixzeW1ib2wsdmFsdWU7Zm9yKHZhciBpPTAsbnVtVG9rZW5zPXRva2Vucy5sZW5ndGg7aTxudW1Ub2tlbnM7KytpKXt2YWx1ZT11bmRlZmluZWQ7dG9rZW49dG9rZW5zW2ldO3N5bWJvbD10b2tlblswXTtpZihzeW1ib2w9PT1cIiNcIil2YWx1ZT10aGlzLnJlbmRlclNlY3Rpb24odG9rZW4sY29udGV4dCxwYXJ0aWFscyxvcmlnaW5hbFRlbXBsYXRlKTtlbHNlIGlmKHN5bWJvbD09PVwiXlwiKXZhbHVlPXRoaXMucmVuZGVySW52ZXJ0ZWQodG9rZW4sY29udGV4dCxwYXJ0aWFscyxvcmlnaW5hbFRlbXBsYXRlKTtlbHNlIGlmKHN5bWJvbD09PVwiPlwiKXZhbHVlPXRoaXMucmVuZGVyUGFydGlhbCh0b2tlbixjb250ZXh0LHBhcnRpYWxzLG9yaWdpbmFsVGVtcGxhdGUpO2Vsc2UgaWYoc3ltYm9sPT09XCImXCIpdmFsdWU9dGhpcy51bmVzY2FwZWRWYWx1ZSh0b2tlbixjb250ZXh0KTtlbHNlIGlmKHN5bWJvbD09PVwibmFtZVwiKXZhbHVlPXRoaXMuZXNjYXBlZFZhbHVlKHRva2VuLGNvbnRleHQpO2Vsc2UgaWYoc3ltYm9sPT09XCJ0ZXh0XCIpdmFsdWU9dGhpcy5yYXdWYWx1ZSh0b2tlbik7aWYodmFsdWUhPT11bmRlZmluZWQpYnVmZmVyKz12YWx1ZX1yZXR1cm4gYnVmZmVyfTtXcml0ZXIucHJvdG90eXBlLnJlbmRlclNlY3Rpb249ZnVuY3Rpb24gcmVuZGVyU2VjdGlvbih0b2tlbixjb250ZXh0LHBhcnRpYWxzLG9yaWdpbmFsVGVtcGxhdGUpe3ZhciBzZWxmPXRoaXM7dmFyIGJ1ZmZlcj1cIlwiO3ZhciB2YWx1ZT1jb250ZXh0Lmxvb2t1cCh0b2tlblsxXSk7ZnVuY3Rpb24gc3ViUmVuZGVyKHRlbXBsYXRlKXtyZXR1cm4gc2VsZi5yZW5kZXIodGVtcGxhdGUsY29udGV4dCxwYXJ0aWFscyl9aWYoIXZhbHVlKXJldHVybjtpZihpc0FycmF5KHZhbHVlKSl7Zm9yKHZhciBqPTAsdmFsdWVMZW5ndGg9dmFsdWUubGVuZ3RoO2o8dmFsdWVMZW5ndGg7KytqKXtidWZmZXIrPXRoaXMucmVuZGVyVG9rZW5zKHRva2VuWzRdLGNvbnRleHQucHVzaCh2YWx1ZVtqXSkscGFydGlhbHMsb3JpZ2luYWxUZW1wbGF0ZSl9fWVsc2UgaWYodHlwZW9mIHZhbHVlPT09XCJvYmplY3RcInx8dHlwZW9mIHZhbHVlPT09XCJzdHJpbmdcInx8dHlwZW9mIHZhbHVlPT09XCJudW1iZXJcIil7YnVmZmVyKz10aGlzLnJlbmRlclRva2Vucyh0b2tlbls0XSxjb250ZXh0LnB1c2godmFsdWUpLHBhcnRpYWxzLG9yaWdpbmFsVGVtcGxhdGUpfWVsc2UgaWYoaXNGdW5jdGlvbih2YWx1ZSkpe2lmKHR5cGVvZiBvcmlnaW5hbFRlbXBsYXRlIT09XCJzdHJpbmdcIil0aHJvdyBuZXcgRXJyb3IoXCJDYW5ub3QgdXNlIGhpZ2hlci1vcmRlciBzZWN0aW9ucyB3aXRob3V0IHRoZSBvcmlnaW5hbCB0ZW1wbGF0ZVwiKTt2YWx1ZT12YWx1ZS5jYWxsKGNvbnRleHQudmlldyxvcmlnaW5hbFRlbXBsYXRlLnNsaWNlKHRva2VuWzNdLHRva2VuWzVdKSxzdWJSZW5kZXIpO2lmKHZhbHVlIT1udWxsKWJ1ZmZlcis9dmFsdWV9ZWxzZXtidWZmZXIrPXRoaXMucmVuZGVyVG9rZW5zKHRva2VuWzRdLGNvbnRleHQscGFydGlhbHMsb3JpZ2luYWxUZW1wbGF0ZSl9cmV0dXJuIGJ1ZmZlcn07V3JpdGVyLnByb3RvdHlwZS5yZW5kZXJJbnZlcnRlZD1mdW5jdGlvbiByZW5kZXJJbnZlcnRlZCh0b2tlbixjb250ZXh0LHBhcnRpYWxzLG9yaWdpbmFsVGVtcGxhdGUpe3ZhciB2YWx1ZT1jb250ZXh0Lmxvb2t1cCh0b2tlblsxXSk7aWYoIXZhbHVlfHxpc0FycmF5KHZhbHVlKSYmdmFsdWUubGVuZ3RoPT09MClyZXR1cm4gdGhpcy5yZW5kZXJUb2tlbnModG9rZW5bNF0sY29udGV4dCxwYXJ0aWFscyxvcmlnaW5hbFRlbXBsYXRlKX07V3JpdGVyLnByb3RvdHlwZS5yZW5kZXJQYXJ0aWFsPWZ1bmN0aW9uIHJlbmRlclBhcnRpYWwodG9rZW4sY29udGV4dCxwYXJ0aWFscyl7aWYoIXBhcnRpYWxzKXJldHVybjt2YXIgdmFsdWU9aXNGdW5jdGlvbihwYXJ0aWFscyk/cGFydGlhbHModG9rZW5bMV0pOnBhcnRpYWxzW3Rva2VuWzFdXTtpZih2YWx1ZSE9bnVsbClyZXR1cm4gdGhpcy5yZW5kZXJUb2tlbnModGhpcy5wYXJzZSh2YWx1ZSksY29udGV4dCxwYXJ0aWFscyx2YWx1ZSl9O1dyaXRlci5wcm90b3R5cGUudW5lc2NhcGVkVmFsdWU9ZnVuY3Rpb24gdW5lc2NhcGVkVmFsdWUodG9rZW4sY29udGV4dCl7dmFyIHZhbHVlPWNvbnRleHQubG9va3VwKHRva2VuWzFdKTtpZih2YWx1ZSE9bnVsbClyZXR1cm4gdmFsdWV9O1dyaXRlci5wcm90b3R5cGUuZXNjYXBlZFZhbHVlPWZ1bmN0aW9uIGVzY2FwZWRWYWx1ZSh0b2tlbixjb250ZXh0KXt2YXIgdmFsdWU9Y29udGV4dC5sb29rdXAodG9rZW5bMV0pO2lmKHZhbHVlIT1udWxsKXJldHVybiBtdXN0YWNoZS5lc2NhcGUodmFsdWUpfTtXcml0ZXIucHJvdG90eXBlLnJhd1ZhbHVlPWZ1bmN0aW9uIHJhd1ZhbHVlKHRva2VuKXtyZXR1cm4gdG9rZW5bMV19O211c3RhY2hlLm5hbWU9XCJtdXN0YWNoZS5qc1wiO211c3RhY2hlLnZlcnNpb249XCIyLjMuMFwiO211c3RhY2hlLnRhZ3M9W1wie3tcIixcIn19XCJdO3ZhciBkZWZhdWx0V3JpdGVyPW5ldyBXcml0ZXI7bXVzdGFjaGUuY2xlYXJDYWNoZT1mdW5jdGlvbiBjbGVhckNhY2hlKCl7cmV0dXJuIGRlZmF1bHRXcml0ZXIuY2xlYXJDYWNoZSgpfTttdXN0YWNoZS5wYXJzZT1mdW5jdGlvbiBwYXJzZSh0ZW1wbGF0ZSx0YWdzKXtyZXR1cm4gZGVmYXVsdFdyaXRlci5wYXJzZSh0ZW1wbGF0ZSx0YWdzKX07bXVzdGFjaGUucmVuZGVyPWZ1bmN0aW9uIHJlbmRlcih0ZW1wbGF0ZSx2aWV3LHBhcnRpYWxzKXtpZih0eXBlb2YgdGVtcGxhdGUhPT1cInN0cmluZ1wiKXt0aHJvdyBuZXcgVHlwZUVycm9yKCdJbnZhbGlkIHRlbXBsYXRlISBUZW1wbGF0ZSBzaG91bGQgYmUgYSBcInN0cmluZ1wiICcrJ2J1dCBcIicrdHlwZVN0cih0ZW1wbGF0ZSkrJ1wiIHdhcyBnaXZlbiBhcyB0aGUgZmlyc3QgJytcImFyZ3VtZW50IGZvciBtdXN0YWNoZSNyZW5kZXIodGVtcGxhdGUsIHZpZXcsIHBhcnRpYWxzKVwiKX1yZXR1cm4gZGVmYXVsdFdyaXRlci5yZW5kZXIodGVtcGxhdGUsdmlldyxwYXJ0aWFscyl9O211c3RhY2hlLnRvX2h0bWw9ZnVuY3Rpb24gdG9faHRtbCh0ZW1wbGF0ZSx2aWV3LHBhcnRpYWxzLHNlbmQpe3ZhciByZXN1bHQ9bXVzdGFjaGUucmVuZGVyKHRlbXBsYXRlLHZpZXcscGFydGlhbHMpO2lmKGlzRnVuY3Rpb24oc2VuZCkpe3NlbmQocmVzdWx0KX1lbHNle3JldHVybiByZXN1bHR9fTttdXN0YWNoZS5lc2NhcGU9ZXNjYXBlSHRtbDttdXN0YWNoZS5TY2FubmVyPVNjYW5uZXI7bXVzdGFjaGUuQ29udGV4dD1Db250ZXh0O211c3RhY2hlLldyaXRlcj1Xcml0ZXI7cmV0dXJuIG11c3RhY2hlfSk7XG4iLCIvKiFcbipcbiogIENvcHlyaWdodCAyMDE2IFlhbm4gTWFzc2FyZCAoaHR0cHM6Ly9naXRodWIuY29tL3lhbWFzcykgYW5kIG90aGVyIGNvbnRyaWJ1dG9yc1xuKlxuKiAgTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiogIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiogIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuKlxuKiAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4qXG4qICBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4qICBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4qICBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiogIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiogIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuKlxuKi9cbihmdW5jdGlvbiAoZmFjdG9yeSkge1xuICAgIGlmICh0eXBlb2YgbW9kdWxlID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBtb2R1bGUuZXhwb3J0cyA9PT0gXCJvYmplY3RcIikge1xuICAgICAgICB2YXIgdiA9IGZhY3RvcnkocmVxdWlyZSwgZXhwb3J0cyk7XG4gICAgICAgIGlmICh2ICE9PSB1bmRlZmluZWQpIG1vZHVsZS5leHBvcnRzID0gdjtcbiAgICB9XG4gICAgZWxzZSBpZiAodHlwZW9mIGRlZmluZSA9PT0gXCJmdW5jdGlvblwiICYmIGRlZmluZS5hbWQpIHtcbiAgICAgICAgZGVmaW5lKFtcInJlcXVpcmVcIiwgXCJleHBvcnRzXCIsIFwianF1ZXJ5XCIsIFwibGV2ZW5zaHRlaW5cIl0sIGZhY3RvcnkpO1xuICAgIH0gZWxzZSB7ICAgd2luZG93LlRyaXZpYWxDb21wb25lbnRzID0gd2luZG93LlRyaXZpYWxDb21wb25lbnRzIHx8IHt9OyAgZmFjdG9yeShmdW5jdGlvbihuYW1lKSB7ICAgIGlmIChuYW1lID09PSBcImpxdWVyeVwiKSB7ICAgICAgcmV0dXJuIHdpbmRvdy5qUXVlcnk7ICAgIH0gZWxzZSBpZiAobmFtZSA9PT0gXCJsZXZlbnNodGVpblwiKSB7ICAgICAgcmV0dXJuIHdpbmRvdy5MZXZlbnNodGVpbjsgICAgfSBlbHNlIGlmIChuYW1lID09PSBcIm1vbWVudFwiKSB7ICAgICAgcmV0dXJuIHdpbmRvdy5tb21lbnQ7ICAgIH0gZWxzZSBpZiAobmFtZSA9PT0gXCJtdXN0YWNoZVwiKSB7ICAgICAgcmV0dXJuIHdpbmRvdy5NdXN0YWNoZTsgICAgfSBlbHNlIHsgICAgICByZXR1cm4gd2luZG93LlRyaXZpYWxDb21wb25lbnRzOyAgICB9ICB9LCB3aW5kb3cuVHJpdmlhbENvbXBvbmVudHMpO31cbn0pKGZ1bmN0aW9uIChyZXF1aXJlLCBleHBvcnRzKSB7XG4gICAgXCJ1c2Ugc3RyaWN0XCI7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuICAgIHZhciAkID0gcmVxdWlyZShcImpxdWVyeVwiKTtcbiAgICB2YXIgTGV2ZW5zaHRlaW4gPSByZXF1aXJlKFwibGV2ZW5zaHRlaW5cIik7XG4gICAgZXhwb3J0cy5rZXlDb2RlcyA9IHtcbiAgICAgICAgYmFja3NwYWNlOiA4LFxuICAgICAgICB0YWI6IDksXG4gICAgICAgIGVudGVyOiAxMyxcbiAgICAgICAgc2hpZnQ6IDE2LFxuICAgICAgICBjdHJsOiAxNyxcbiAgICAgICAgYWx0OiAxOCxcbiAgICAgICAgcGF1c2U6IDE5LFxuICAgICAgICBjYXBzX2xvY2s6IDIwLFxuICAgICAgICBlc2NhcGU6IDI3LFxuICAgICAgICBzcGFjZTogMzIsXG4gICAgICAgIHBhZ2VfdXA6IDMzLFxuICAgICAgICBwYWdlX2Rvd246IDM0LFxuICAgICAgICBlbmQ6IDM1LFxuICAgICAgICBob21lOiAzNixcbiAgICAgICAgbGVmdF9hcnJvdzogMzcsXG4gICAgICAgIHVwX2Fycm93OiAzOCxcbiAgICAgICAgcmlnaHRfYXJyb3c6IDM5LFxuICAgICAgICBkb3duX2Fycm93OiA0MCxcbiAgICAgICAgaW5zZXJ0OiA0NSxcbiAgICAgICAgXCJkZWxldGVcIjogNDYsXG4gICAgICAgIGxlZnRfd2luZG93X2tleTogOTEsXG4gICAgICAgIHJpZ2h0X3dpbmRvd19rZXk6IDkyLFxuICAgICAgICBzZWxlY3Rfa2V5OiA5MyxcbiAgICAgICAgbnVtX2xvY2s6IDE0NCxcbiAgICAgICAgc2Nyb2xsX2xvY2s6IDE0NSxcbiAgICAgICAgc3BlY2lhbEtleXM6IFs4LCA5LCAxMywgMTYsIDE3LCAxOCwgMTksIDIwLCAyNywgMzMsIDM0LCAzNSwgMzYsIDM3LCAzOCwgMzksIDQwLCA0NSwgNDYsIDkxLCA5MiwgOTMsIDE0NCwgMTQ1XSxcbiAgICAgICAgbnVtYmVyS2V5czogWzQ4LCA0OSwgNTAsIDUxLCA1MiwgNTMsIDU0LCA1NSwgNTYsIDU3LCA5NiwgOTcsIDk4LCA5OSwgMTAwLCAxMDEsIDEwMiwgMTAzLCAxMDQsIDEwNV0sXG4gICAgICAgIGlzU3BlY2lhbEtleTogZnVuY3Rpb24gKGtleUNvZGUpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnNwZWNpYWxLZXlzLmluZGV4T2Yoa2V5Q29kZSkgIT0gLTE7XG4gICAgICAgIH0sXG4gICAgICAgIGlzRGlnaXRLZXk6IGZ1bmN0aW9uIChrZXlDb2RlKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5udW1iZXJLZXlzLmluZGV4T2Yoa2V5Q29kZSkgIT0gLTE7XG4gICAgICAgIH0sXG4gICAgICAgIGlzTW9kaWZpZXJLZXk6IGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICByZXR1cm4gW2V4cG9ydHMua2V5Q29kZXMuc2hpZnQsIGV4cG9ydHMua2V5Q29kZXMuY2Fwc19sb2NrLCBleHBvcnRzLmtleUNvZGVzLmFsdCwgZXhwb3J0cy5rZXlDb2Rlcy5jdHJsLCBleHBvcnRzLmtleUNvZGVzLmxlZnRfd2luZG93X2tleSwgZXhwb3J0cy5rZXlDb2Rlcy5yaWdodF93aW5kb3dfa2V5XVxuICAgICAgICAgICAgICAgIC5pbmRleE9mKGUud2hpY2gpICE9IC0xO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBleHBvcnRzLkRFRkFVTFRfVEVNUExBVEVTID0ge1xuICAgICAgICBpbWFnZTJMaW5lc1RlbXBsYXRlOiAnPGRpdiBjbGFzcz1cInRyLXRlbXBsYXRlLWltYWdlLTItbGluZXNcIj4nICtcbiAgICAgICAgICAgICcgIDxkaXYgY2xhc3M9XCJpbWctd3JhcHBlclwiIHN0eWxlPVwiYmFja2dyb3VuZC1pbWFnZTogdXJsKHt7aW1hZ2VVcmx9fSlcIj48L2Rpdj4nICtcbiAgICAgICAgICAgICcgIDxkaXYgY2xhc3M9XCJjb250ZW50LXdyYXBwZXIgdHItZWRpdG9yLWFyZWFcIj4gJyArXG4gICAgICAgICAgICAnICAgIDxkaXYgY2xhc3M9XCJtYWluLWxpbmVcIj57e2Rpc3BsYXlWYWx1ZX19PC9kaXY+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+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLmxpc3RCb3guaGlnaGxpZ2h0VGV4dE1hdGNoZXMocXVlcnlTdHJpbmcpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLmxpc3RCb3guaGlnaGxpZ2h0TmV4dEVudHJ5KGhpZ2hsaWdodERpcmVjdGlvbik7XG4gICAgICAgICAgICAgICAgICAgIGlmIChfdGhpcy5pc0Ryb3BEb3duT3Blbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMub3BlbkRyb3BEb3duKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsVW5pdEJveC5wcm90b3R5cGUuZmlyZVNlbGVjdGVkRW50cnlDaGFuZ2VkRXZlbnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB0aGlzLm9uU2VsZWN0ZWRFbnRyeUNoYW5nZWQuZmlyZSh0aGlzLnNlbGVjdGVkRW50cnkpO1xuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsVW5pdEJveC5wcm90b3R5cGUuZmlyZUNoYW5nZUV2ZW50cyA9IGZ1bmN0aW9uIChvcmlnaW5hbEV2ZW50KSB7XG4gICAgICAgICAgICB0aGlzLiRvcmlnaW5hbElucHV0LnRyaWdnZXIoXCJjaGFuZ2VcIik7XG4gICAgICAgICAgICB0aGlzLm9uQ2hhbmdlLmZpcmUoe1xuICAgICAgICAgICAgICAgIHVuaXQ6IHRoaXMuc2VsZWN0ZWRFbnRyeSAhPSBudWxsID8gdGhpcy5zZWxlY3RlZEVudHJ5W3RoaXMuY29uZmlnLnVuaXRWYWx1ZVByb3BlcnR5XSA6IG51bGwsXG4gICAgICAgICAgICAgICAgdW5pdEVudHJ5OiB0aGlzLnNlbGVjdGVkRW50cnksXG4gICAgICAgICAgICAgICAgYW1vdW50OiB0aGlzLmdldEFtb3VudCgpLFxuICAgICAgICAgICAgICAgIGFtb3VudEFzRmxvYXRpbmdQb2ludE51bWJlcjogcGFyc2VGbG9hdCh0aGlzLmZvcm1hdEFtb3VudCh0aGlzLmdldEFtb3VudCgpLCB0aGlzLmNvbmZpZy5kZWNpbWFsUHJlY2lzaW9uLCB0aGlzLmNvbmZpZy5kZWNpbWFsU2VwYXJhdG9yLCB0aGlzLmNvbmZpZy50aG91c2FuZHNTZXBhcmF0b3IpKVxuICAgICAgICAgICAgfSwgb3JpZ2luYWxFdmVudCk7XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxVbml0Qm94LnByb3RvdHlwZS5zZXRTZWxlY3RlZEVudHJ5ID0gZnVuY3Rpb24gKGVudHJ5LCBmaXJlRXZlbnQsIG9yaWdpbmFsRXZlbnQpIHtcbiAgICAgICAgICAgIHRoaXMuc2VsZWN0ZWRFbnRyeSA9IGVudHJ5O1xuICAgICAgICAgICAgdmFyICRzZWxlY3RlZEVudHJ5ID0gJCh0aGlzLmNvbmZpZy5zZWxlY3RlZEVudHJ5UmVuZGVyaW5nRnVuY3Rpb24oZW50cnkpKVxuICAgICAgICAgICAgICAgIC5hZGRDbGFzcyhcInRyLWNvbWJvYm94LWVudHJ5XCIpO1xuICAgICAgICAgICAgdGhpcy4kc2VsZWN0ZWRFbnRyeVdyYXBwZXIuZW1wdHkoKS5hcHBlbmQoJHNlbGVjdGVkRW50cnkpO1xuICAgICAgICAgICAgdGhpcy5jbGVhbnVwRWRpdG9yVmFsdWUoKTtcbiAgICAgICAgICAgIHRoaXMudXBkYXRlT3JpZ2luYWxJbnB1dFZhbHVlKCk7XG4gICAgICAgICAgICBpZiAoIXRoaXMuJGVkaXRvci5pcyhcIjpmb2N1c1wiKSkge1xuICAgICAgICAgICAgICAgIHRoaXMuZm9ybWF0RWRpdG9yVmFsdWUoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChmaXJlRXZlbnQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmZpcmVTZWxlY3RlZEVudHJ5Q2hhbmdlZEV2ZW50KCk7XG4gICAgICAgICAgICAgICAgdGhpcy5maXJlQ2hhbmdlRXZlbnRzKG9yaWdpbmFsRXZlbnQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsVW5pdEJveC5wcm90b3R5cGUuZm9ybWF0RWRpdG9yVmFsdWUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB0aGlzLiRlZGl0b3IudmFsKHRoaXMuZm9ybWF0QW1vdW50KHRoaXMuZ2V0QW1vdW50KCksIHRoaXMuY29uZmlnLmRlY2ltYWxQcmVjaXNpb24sIHRoaXMuY29uZmlnLmRlY2ltYWxTZXBhcmF0b3IsIHRoaXMuY29uZmlnLnRob3VzYW5kc1NlcGFyYXRvcikpO1xuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsVW5pdEJveC5wcm90b3R5cGUuY2xlYW51cEVkaXRvclZhbHVlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgaWYgKHRoaXMuJGVkaXRvci52YWwoKSkge1xuICAgICAgICAgICAgICAgIHRoaXMuJGVkaXRvci52YWwodGhpcy5nZXRFZGl0b3JWYWx1ZU51bWJlclBhcnQodHJ1ZSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsVW5pdEJveC5wcm90b3R5cGUuZm9ybWF0QW1vdW50ID0gZnVuY3Rpb24gKGludGVnZXJOdW1iZXIsIHByZWNpc2lvbiwgZGVjaW1hbFNlcGFyYXRvciwgdGhvdXNhbmRzU2VwYXJhdG9yKSB7XG4gICAgICAgICAgICBpZiAoaW50ZWdlck51bWJlciA9PSBudWxsIHx8IGlzTmFOKGludGVnZXJOdW1iZXIpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFwiXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgYW1vdW50QXNTdHJpbmcgPSBcIlwiICsgaW50ZWdlck51bWJlcjtcbiAgICAgICAgICAgIGlmIChhbW91bnRBc1N0cmluZy5sZW5ndGggPD0gcHJlY2lzaW9uKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIDAgKyBkZWNpbWFsU2VwYXJhdG9yICsgbmV3IEFycmF5KHByZWNpc2lvbiAtIGFtb3VudEFzU3RyaW5nLmxlbmd0aCArIDEpLmpvaW4oXCIwXCIpICsgYW1vdW50QXNTdHJpbmc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB2YXIgaW50ZWdlclBhcnQgPSBhbW91bnRBc1N0cmluZy5zdWJzdHJpbmcoMCwgYW1vdW50QXNTdHJpbmcubGVuZ3RoIC0gcHJlY2lzaW9uKTtcbiAgICAgICAgICAgICAgICB2YXIgZm9ybWF0dGVkSW50ZWdlclBhcnQgPSBpbnRlZ2VyUGFydC5yZXBsYWNlKC9cXEIoPz0oXFxkezN9KSsoPyFcXGQpKS9nLCB0aG91c2FuZHNTZXBhcmF0b3IpO1xuICAgICAgICAgICAgICAgIHZhciBmcmFjdGlvbmFsUGFydCA9IGFtb3VudEFzU3RyaW5nLnN1YnN0cihhbW91bnRBc1N0cmluZy5sZW5ndGggLSBwcmVjaXNpb24sIHByZWNpc2lvbik7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZvcm1hdHRlZEludGVnZXJQYXJ0ICsgZGVjaW1hbFNlcGFyYXRvciArIGZyYWN0aW9uYWxQYXJ0O1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsVW5pdEJveC5wcm90b3R5cGUucmVwb3NpdGlvbkRyb3BEb3duID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgICAgIHRoaXMuJGRyb3BEb3duXG4gICAgICAgICAgICAgICAgLnNob3coKVxuICAgICAgICAgICAgICAgIC5wb3NpdGlvbih7XG4gICAgICAgICAgICAgICAgbXk6IFwibGVmdCB0b3BcIixcbiAgICAgICAgICAgICAgICBhdDogXCJsZWZ0IGJvdHRvbVwiLFxuICAgICAgICAgICAgICAgIG9mOiB0aGlzLiR1bml0Qm94LFxuICAgICAgICAgICAgICAgIGNvbGxpc2lvbjogXCJmbGlwXCIsXG4gICAgICAgICAgICAgICAgdXNpbmc6IGZ1bmN0aW9uIChjYWxjdWxhdGVkUG9zaXRpb24sIGluZm8pIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGluZm8udmVydGljYWwgPT09IFwidG9wXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLiR1bml0Qm94LnJlbW92ZUNsYXNzKFwiZHJvcGRvd24tZmxpcHBlZFwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLiRkcm9wRG93bi5yZW1vdmVDbGFzcyhcImZsaXBwZWRcIik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy4kdW5pdEJveC5hZGRDbGFzcyhcImRyb3Bkb3duLWZsaXBwZWRcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy4kZHJvcERvd24uYWRkQ2xhc3MoXCJmbGlwcGVkXCIpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLiRkcm9wRG93bi5jc3Moe1xuICAgICAgICAgICAgICAgICAgICAgICAgbGVmdDogY2FsY3VsYXRlZFBvc2l0aW9uLmxlZnQgKyAncHgnLFxuICAgICAgICAgICAgICAgICAgICAgICAgdG9wOiBjYWxjdWxhdGVkUG9zaXRpb24udG9wICsgJ3B4J1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC53aWR0aCh0aGlzLiR1bml0Qm94LndpZHRoKCkpO1xuICAgICAgICB9O1xuICAgICAgICA7XG4gICAgICAgIFRyaXZpYWxVbml0Qm94LnByb3RvdHlwZS5vcGVuRHJvcERvd24gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB0aGlzLiR1bml0Qm94LmFkZENsYXNzKFwib3BlblwiKTtcbiAgICAgICAgICAgIHRoaXMucmVwb3NpdGlvbkRyb3BEb3duKCk7XG4gICAgICAgICAgICB0aGlzLmlzRHJvcERvd25PcGVuID0gdHJ1ZTtcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFVuaXRCb3gucHJvdG90eXBlLmNsb3NlRHJvcERvd24gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB0aGlzLiR1bml0Qm94LnJlbW92ZUNsYXNzKFwib3BlblwiKTtcbiAgICAgICAgICAgIHRoaXMuJGRyb3BEb3duLmhpZGUoKTtcbiAgICAgICAgICAgIHRoaXMuaXNEcm9wRG93bk9wZW4gPSBmYWxzZTtcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFVuaXRCb3gucHJvdG90eXBlLnVwZGF0ZU9yaWdpbmFsSW5wdXRWYWx1ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLmNvbmZpZy51bml0RGlzcGxheVBvc2l0aW9uID09PSAnbGVmdCcpIHtcbiAgICAgICAgICAgICAgICB0aGlzLiRvcmlnaW5hbElucHV0LnZhbCgodGhpcy5zZWxlY3RlZEVudHJ5ID8gdGhpcy5zZWxlY3RlZEVudHJ5W3RoaXMuY29uZmlnLnVuaXRWYWx1ZVByb3BlcnR5XSA6ICcnKSArIHRoaXMuZm9ybWF0QW1vdW50KHRoaXMuZ2V0QW1vdW50KCksIHRoaXMuY29uZmlnLmRlY2ltYWxQcmVjaXNpb24sIHRoaXMuY29uZmlnLmRlY2ltYWxTZXBhcmF0b3IsICcnKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLiRvcmlnaW5hbElucHV0LnZhbCh0aGlzLmZvcm1hdEFtb3VudCh0aGlzLmdldEFtb3VudCgpLCB0aGlzLmNvbmZpZy5kZWNpbWFsUHJlY2lzaW9uLCB0aGlzLmNvbmZpZy5kZWNpbWFsU2VwYXJhdG9yLCAnJykgKyAodGhpcy5zZWxlY3RlZEVudHJ5ID8gdGhpcy5zZWxlY3RlZEVudHJ5W3RoaXMuY29uZmlnLnVuaXRWYWx1ZVByb3BlcnR5XSA6ICcnKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxVbml0Qm94LnByb3RvdHlwZS5nZXRBbW91bnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgZWRpdG9yVmFsdWVOdW1iZXJQYXJ0ID0gdGhpcy5nZXRFZGl0b3JWYWx1ZU51bWJlclBhcnQoZmFsc2UpO1xuICAgICAgICAgICAgaWYgKGVkaXRvclZhbHVlTnVtYmVyUGFydC5sZW5ndGggPT09IDAgJiYgdGhpcy5jb25maWcuYWxsb3dOdWxsQW1vdW50KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChlZGl0b3JWYWx1ZU51bWJlclBhcnQubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcGFyc2VJbnQodGhpcy5nZXRFZGl0b3JWYWx1ZU51bWJlclBhcnQodHJ1ZSkucmVwbGFjZSgvXFxEL2csIFwiXCIpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFVuaXRCb3gucHJvdG90eXBlLmlzRHJvcERvd25OZWVkZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5lZGl0aW5nTW9kZSA9PSAnZWRpdGFibGUnICYmICh0aGlzLmNvbmZpZy5lbnRyaWVzICYmIHRoaXMuY29uZmlnLmVudHJpZXMubGVuZ3RoID4gMCB8fCAhdGhpcy51c2luZ0RlZmF1bHRRdWVyeUZ1bmN0aW9uIHx8IHRoaXMuY29uZmlnLnNob3dUcmlnZ2VyKTtcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFVuaXRCb3gucHJvdG90eXBlLnNldEVkaXRpbmdNb2RlID0gZnVuY3Rpb24gKG5ld0VkaXRpbmdNb2RlKSB7XG4gICAgICAgICAgICB0aGlzLmVkaXRpbmdNb2RlID0gbmV3RWRpdGluZ01vZGU7XG4gICAgICAgICAgICB0aGlzLiR1bml0Qm94LnJlbW92ZUNsYXNzKFwiZWRpdGFibGUgcmVhZG9ubHkgZGlzYWJsZWRcIikuYWRkQ2xhc3ModGhpcy5lZGl0aW5nTW9kZSk7XG4gICAgICAgICAgICB0aGlzLiRlZGl0b3IucHJvcChcInJlYWRvbmx5XCIsIG5ld0VkaXRpbmdNb2RlICE9PSBcImVkaXRhYmxlXCIpO1xuICAgICAgICAgICAgdGhpcy4kZWRpdG9yLmF0dHIoXCJ0YWJpbmRleFwiLCBuZXdFZGl0aW5nTW9kZSA9PT0gXCJlZGl0YWJsZVwiID8gdGhpcy4kb3JpZ2luYWxJbnB1dC5hdHRyKFwidGFiaW5kZXhcIikgOiBcIi0xXCIpO1xuICAgICAgICAgICAgaWYgKHRoaXMuaXNEcm9wRG93bk5lZWRlZCgpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy4kZHJvcERvd24uYXBwZW5kVG8odGhpcy4kZHJvcERvd25UYXJnZXRFbGVtZW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFVuaXRCb3gucHJvdG90eXBlLnNlbGVjdFVuaXQgPSBmdW5jdGlvbiAodW5pdElkZW50aWZpZXIpIHtcbiAgICAgICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgICAgICB0aGlzLnNldFNlbGVjdGVkRW50cnkodGhpcy5lbnRyaWVzLmZpbHRlcihmdW5jdGlvbiAoZW50cnkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZW50cnlbX3RoaXMuY29uZmlnLnVuaXRJZFByb3BlcnR5XSA9PT0gdW5pdElkZW50aWZpZXI7XG4gICAgICAgICAgICB9KVswXSwgZmFsc2UsIG51bGwpO1xuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsVW5pdEJveC5wcm90b3R5cGUudXBkYXRlRW50cmllcyA9IGZ1bmN0aW9uIChuZXdFbnRyaWVzKSB7XG4gICAgICAgICAgICB0aGlzLmVudHJpZXMgPSBuZXdFbnRyaWVzO1xuICAgICAgICAgICAgdGhpcy4kc3Bpbm5lcnMucmVtb3ZlKCk7XG4gICAgICAgICAgICB0aGlzLiRzcGlubmVycyA9ICQoKTtcbiAgICAgICAgICAgIHRoaXMubGlzdEJveC51cGRhdGVFbnRyaWVzKG5ld0VudHJpZXMpO1xuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsVW5pdEJveC5wcm90b3R5cGUuZ2V0U2VsZWN0ZWRFbnRyeSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnNlbGVjdGVkRW50cnkgPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdmFyIHNlbGVjdGVkRW50cnlUb1JldHVybiA9ICQuZXh0ZW5kKHt9LCB0aGlzLnNlbGVjdGVkRW50cnkpO1xuICAgICAgICAgICAgICAgIHNlbGVjdGVkRW50cnlUb1JldHVybi5fdHJFbnRyeUVsZW1lbnQgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHNlbGVjdGVkRW50cnlUb1JldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFVuaXRCb3gucHJvdG90eXBlLnNldEFtb3VudCA9IGZ1bmN0aW9uIChhbW91bnQpIHtcbiAgICAgICAgICAgIGlmIChhbW91bnQgIT0gbnVsbCAmJiBhbW91bnQgIT09IE1hdGguZmxvb3IoYW1vdW50KSkge1xuICAgICAgICAgICAgICAgIHRocm93IFwiVHJpdmlhbFVuaXRCb3g6IFlvdSBtdXN0IHNwZWNpZnkgYW4gaW50ZWdlciBhbW91bnQhXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoYW1vdW50ID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5jb25maWcuYWxsb3dOdWxsQW1vdW50KSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuJGVkaXRvci52YWwoXCJcIik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLiRlZGl0b3IudmFsKHRoaXMuZm9ybWF0QW1vdW50KDAsIHRoaXMuY29uZmlnLmRlY2ltYWxQcmVjaXNpb24sIHRoaXMuY29uZmlnLmRlY2ltYWxTZXBhcmF0b3IsICcnKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAodGhpcy4kZWRpdG9yLmlzKFwiOmZvY3VzXCIpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy4kZWRpdG9yLnZhbCh0aGlzLmZvcm1hdEFtb3VudChhbW91bnQsIHRoaXMuY29uZmlnLmRlY2ltYWxQcmVjaXNpb24sIHRoaXMuY29uZmlnLmRlY2ltYWxTZXBhcmF0b3IsICcnKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLiRlZGl0b3IudmFsKHRoaXMuZm9ybWF0QW1vdW50KGFtb3VudCwgdGhpcy5jb25maWcuZGVjaW1hbFByZWNpc2lvbiwgdGhpcy5jb25maWcuZGVjaW1hbFNlcGFyYXRvciwgdGhpcy5jb25maWcudGhvdXNhbmRzU2VwYXJhdG9yKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIDtcbiAgICAgICAgVHJpdmlhbFVuaXRCb3gucHJvdG90eXBlLmZvY3VzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdGhpcy4kZWRpdG9yLnNlbGVjdCgpO1xuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsVW5pdEJveC5wcm90b3R5cGUuZ2V0RWRpdG9yID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuJGVkaXRvclswXTtcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFVuaXRCb3gucHJvdG90eXBlLmRlc3Ryb3kgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB0aGlzLiRvcmlnaW5hbElucHV0LnJlbW92ZUNsYXNzKCd0ci1vcmlnaW5hbC1pbnB1dCcpLmluc2VydEJlZm9yZSh0aGlzLiR1bml0Qm94KTtcbiAgICAgICAgICAgIHRoaXMuJHVuaXRCb3gucmVtb3ZlKCk7XG4gICAgICAgICAgICB0aGlzLiRkcm9wRG93bi5yZW1vdmUoKTtcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFVuaXRCb3gucHJvdG90eXBlLmdldE1haW5Eb21FbGVtZW50ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuJHVuaXRCb3hbMF07XG4gICAgICAgIH07XG4gICAgICAgIHJldHVybiBUcml2aWFsVW5pdEJveDtcbiAgICB9KCkpO1xuICAgIGV4cG9ydHMuVHJpdmlhbFVuaXRCb3ggPSBUcml2aWFsVW5pdEJveDtcbn0pO1xuXG5cbihmdW5jdGlvbiAoZmFjdG9yeSkge1xuICAgIGlmICh0eXBlb2YgbW9kdWxlID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBtb2R1bGUuZXhwb3J0cyA9PT0gXCJvYmplY3RcIikge1xuICAgICAgICB2YXIgdiA9IGZhY3RvcnkocmVxdWlyZSwgZXhwb3J0cyk7XG4gICAgICAgIGlmICh2ICE9PSB1bmRlZmluZWQpIG1vZHVsZS5leHBvcnRzID0gdjtcbiAgICB9XG4gICAgZWxzZSBpZiAodHlwZW9mIGRlZmluZSA9PT0gXCJmdW5jdGlvblwiICYmIGRlZmluZS5hbWQpIHtcbiAgICAgICAgZGVmaW5lKFtcInJlcXVpcmVcIiwgXCJleHBvcnRzXCIsIFwianF1ZXJ5XCIsIFwiLi9Ucml2aWFsQ29yZVwiXSwgZmFjdG9yeSk7XG4gICAgfSBlbHNlIHsgICB3aW5kb3cuVHJpdmlhbENvbXBvbmVudHMgPSB3aW5kb3cuVHJpdmlhbENvbXBvbmVudHMgfHwge307ICBmYWN0b3J5KGZ1bmN0aW9uKG5hbWUpIHsgICAgaWYgKG5hbWUgPT09IFwianF1ZXJ5XCIpIHsgICAgICByZXR1cm4gd2luZG93LmpRdWVyeTsgICAgfSBlbHNlIGlmIChuYW1lID09PSBcImxldmVuc2h0ZWluXCIpIHsgICAgICByZXR1cm4gd2luZG93LkxldmVuc2h0ZWluOyAgICB9IGVsc2UgaWYgKG5hbWUgPT09IFwibW9tZW50XCIpIHsgICAgICByZXR1cm4gd2luZG93Lm1vbWVudDsgICAgfSBlbHNlIGlmIChuYW1lID09PSBcIm11c3RhY2hlXCIpIHsgICAgICByZXR1cm4gd2luZG93Lk11c3RhY2hlOyAgICB9IGVsc2UgeyAgICAgIHJldHVybiB3aW5kb3cuVHJpdmlhbENvbXBvbmVudHM7ICAgIH0gIH0sIHdpbmRvdy5Ucml2aWFsQ29tcG9uZW50cyk7fVxufSkoZnVuY3Rpb24gKHJlcXVpcmUsIGV4cG9ydHMpIHtcbiAgICBcInVzZSBzdHJpY3RcIjtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG4gICAgdmFyIGpRdWVyeSA9IHJlcXVpcmUoXCJqcXVlcnlcIik7XG4gICAgdmFyIFRyaXZpYWxDb3JlXzEgPSByZXF1aXJlKFwiLi9Ucml2aWFsQ29yZVwiKTtcbiAgICAoZnVuY3Rpb24gKCQpIHtcbiAgICAgICAgJC5leHByW1wiOlwiXS5jb250YWluc0lnbm9yZUNhc2UgPSAkLmV4cHIuY3JlYXRlUHNldWRvKGZ1bmN0aW9uIChhcmcpIHtcbiAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbiAoZWxlbSkge1xuICAgICAgICAgICAgICAgIHJldHVybiAkKGVsZW0pLnRleHQoKS50b1VwcGVyQ2FzZSgpLmluZGV4T2YoYXJnLnRvVXBwZXJDYXNlKCkpID49IDA7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9KTtcbiAgICB9KShqUXVlcnkpO1xuICAgIChmdW5jdGlvbiAoJCkge1xuICAgICAgICB2YXIgaXNJRTExID0gISh3aW5kb3cuQWN0aXZlWE9iamVjdCkgJiYgXCJBY3RpdmVYT2JqZWN0XCIgaW4gd2luZG93O1xuICAgICAgICBmdW5jdGlvbiBub3JtYWxpemVGb3JJRTExKG5vZGUpIHtcbiAgICAgICAgICAgIGlmICghbm9kZSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChub2RlLm5vZGVUeXBlID09IDMpIHtcbiAgICAgICAgICAgICAgICB3aGlsZSAobm9kZS5uZXh0U2libGluZyAmJiBub2RlLm5leHRTaWJsaW5nLm5vZGVUeXBlID09IDMpIHtcbiAgICAgICAgICAgICAgICAgICAgbm9kZS5ub2RlVmFsdWUgKz0gbm9kZS5uZXh0U2libGluZy5ub2RlVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgIG5vZGUucGFyZW50Tm9kZS5yZW1vdmVDaGlsZChub2RlLm5leHRTaWJsaW5nKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBub3JtYWxpemVGb3JJRTExKG5vZGUuZmlyc3RDaGlsZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBub3JtYWxpemVGb3JJRTExKG5vZGUubmV4dFNpYmxpbmcpO1xuICAgICAgICB9XG4gICAgICAgICQuZm4udHJpdmlhbEhpZ2hsaWdodCA9IGZ1bmN0aW9uIChzZWFyY2hTdHJpbmcsIG9wdGlvbnMpIHtcbiAgICAgICAgICAgIG9wdGlvbnMgPSAkLmV4dGVuZCh7XG4gICAgICAgICAgICAgICAgaGlnaGxpZ2h0Q2xhc3NOYW1lOiAndHItaGlnaGxpZ2h0ZWQtdGV4dCcsXG4gICAgICAgICAgICAgICAgbWF0Y2hpbmdNb2RlOiAnY29udGFpbnMnLFxuICAgICAgICAgICAgICAgIGlnbm9yZUNhc2U6IHRydWUsXG4gICAgICAgICAgICAgICAgbWF4TGV2ZW5zaHRlaW5EaXN0YW5jZTogM1xuICAgICAgICAgICAgfSwgb3B0aW9ucyk7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5maW5kKCcqJykuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgdmFyICR0aGlzID0gJCh0aGlzKTtcbiAgICAgICAgICAgICAgICAkdGhpcy5maW5kKCcuJyArIG9wdGlvbnMuaGlnaGxpZ2h0Q2xhc3NOYW1lKS5jb250ZW50cygpLnVud3JhcCgpO1xuICAgICAgICAgICAgICAgIGlmIChpc0lFMTEpIHtcbiAgICAgICAgICAgICAgICAgICAgbm9ybWFsaXplRm9ySUUxMSh0aGlzKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMubm9ybWFsaXplKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChzZWFyY2hTdHJpbmcgJiYgc2VhcmNoU3RyaW5nICE9PSAnJykge1xuICAgICAgICAgICAgICAgICAgICAkdGhpcy5jb250ZW50cygpLmZpbHRlcihmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5ub2RlVHlwZSA9PSAzICYmIFRyaXZpYWxDb3JlXzEudHJpdmlhbE1hdGNoKHRoaXMubm9kZVZhbHVlLCBzZWFyY2hTdHJpbmcsIG9wdGlvbnMpLmxlbmd0aCA+IDA7XG4gICAgICAgICAgICAgICAgICAgIH0pLnJlcGxhY2VXaXRoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBvbGROb2RlVmFsdWUgPSAodGhpcy5ub2RlVmFsdWUgfHwgXCJcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZVZhbHVlID0gXCJcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBtYXRjaGVzID0gVHJpdmlhbENvcmVfMS50cml2aWFsTWF0Y2godGhpcy5ub2RlVmFsdWUsIHNlYXJjaFN0cmluZywgb3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgb2xkTWF0Y2hFbmQgPSAwO1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBtYXRjaGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG1hdGNoID0gbWF0Y2hlc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdOb2RlVmFsdWUgKz0gdGhpcy5ub2RlVmFsdWUuc3Vic3RyaW5nKG9sZE1hdGNoRW5kLCBtYXRjaC5zdGFydCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZVZhbHVlICs9IFwiPHNwYW4gY2xhc3M9XFxcIlwiICsgb3B0aW9ucy5oaWdobGlnaHRDbGFzc05hbWUgKyBcIlxcXCI+XCIgKyBvbGROb2RlVmFsdWUuc3Vic3RyKG1hdGNoLnN0YXJ0LCBtYXRjaC5sZW5ndGgpICsgXCI8L3NwYW4+XCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb2xkTWF0Y2hFbmQgPSBtYXRjaC5zdGFydCArIG1hdGNoLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIG5ld05vZGVWYWx1ZSArPSBvbGROb2RlVmFsdWUuc3Vic3RyaW5nKG9sZE1hdGNoRW5kLCBvbGROb2RlVmFsdWUubGVuZ3RoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXdOb2RlVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9O1xuICAgIH0oalF1ZXJ5KSk7XG59KTtcblxuIl19
    </code></pre>    <br/>
        <br/>
        <div id="right-banner">
                </div>
        <div id="left-banner">
                </div>
    <div class='clear'></div>
        <aside class="related-items">
            <section>
                <div class="panel panel-primary">
                    <div class="panel-heading margin-bottom">Related Artifacts</div>
                    <div class="">
                        <a title='This artifact is from the group mysql' class='btn btn-default btn-xs small-margin-bottom ellipsis sidebar-btn' href='/artifacts/mysql/mysql-connector-java' ><i class="fa fa-arrow-circle-right" aria-hidden="true"></i> mysql-connector-java <small class='group-info' >mysql</small></a><br/><a title='This artifact is from the group com.github.codedrinker' class='btn btn-default btn-xs small-margin-bottom ellipsis sidebar-btn' href='/artifacts/com.github.codedrinker/facebook-messenger' ><i class="fa fa-arrow-circle-right" aria-hidden="true"></i> facebook-messenger <small class='group-info' >com.github.codedrinker</small></a><br/><a title='This artifact is from the group org.seleniumhq.selenium' class='btn btn-default btn-xs small-margin-bottom ellipsis sidebar-btn' href='/artifacts/org.seleniumhq.selenium/selenium-java' ><i class="fa fa-arrow-circle-right" aria-hidden="true"></i> selenium-java <small class='group-info' >org.seleniumhq.selenium</small></a><br/><a title='This artifact is from the group com.github.sola92' class='btn btn-default btn-xs small-margin-bottom ellipsis sidebar-btn' href='/artifacts/com.github.sola92/instagram-java' ><i class="fa fa-arrow-circle-right" aria-hidden="true"></i> instagram-java <small class='group-info' >com.github.sola92</small></a><br/><a title='This artifact is from the group com.google.code.gson' class='btn btn-default btn-xs small-margin-bottom ellipsis sidebar-btn' href='/artifacts/com.google.code.gson/gson' ><i class="fa fa-arrow-circle-right" aria-hidden="true"></i> gson <small class='group-info' >com.google.code.gson</small></a><br/><a title='This artifact is from the group org.apache.poi' class='btn btn-default btn-xs small-margin-bottom ellipsis sidebar-btn' href='/artifacts/org.apache.poi/poi' ><i class="fa fa-arrow-circle-right" aria-hidden="true"></i> poi <small class='group-info' >org.apache.poi</small></a><br/><a title='This artifact is from the group org.apache.httpcomponents' class='btn btn-default btn-xs small-margin-bottom ellipsis sidebar-btn' href='/artifacts/org.apache.httpcomponents/httpclient' ><i class="fa fa-arrow-circle-right" aria-hidden="true"></i> httpclient <small class='group-info' >org.apache.httpcomponents</small></a><br/><a title='This artifact is from the group org.json' class='btn btn-default btn-xs small-margin-bottom ellipsis sidebar-btn' href='/artifacts/org.json/json' ><i class="fa fa-arrow-circle-right" aria-hidden="true"></i> json <small class='group-info' >org.json</small></a><br/><a title='This artifact is from the group com.google.code.facebook-java-api' class='btn btn-default btn-xs small-margin-bottom ellipsis sidebar-btn' href='/artifacts/com.google.code.facebook-java-api/facebook-java-api' ><i class="fa fa-arrow-circle-right" aria-hidden="true"></i> facebook-java-api <small class='group-info' >com.google.code.facebook-java-api</small></a><br/><a title='This artifact is from the group org.apache.poi' class='btn btn-default btn-xs small-margin-bottom ellipsis sidebar-btn' href='/artifacts/org.apache.poi/poi-ooxml' ><i class="fa fa-arrow-circle-right" aria-hidden="true"></i> poi-ooxml <small class='group-info' >org.apache.poi</small></a><br/><a title='This artifact is from the group com.fasterxml.jackson.core' class='btn btn-default btn-xs small-margin-bottom ellipsis sidebar-btn' href='/artifacts/com.fasterxml.jackson.core/jackson-databind' ><i class="fa fa-arrow-circle-right" aria-hidden="true"></i> jackson-databind <small class='group-info' >com.fasterxml.jackson.core</small></a><br/><a title='This artifact is from the group junit' class='btn btn-default btn-xs small-margin-bottom ellipsis sidebar-btn' href='/artifacts/junit/junit' ><i class="fa fa-arrow-circle-right" aria-hidden="true"></i> junit <small class='group-info' >junit</small></a><br/><a title='This artifact is from the group org.primefaces' class='btn btn-default btn-xs small-margin-bottom ellipsis sidebar-btn' href='/artifacts/org.primefaces/primefaces' ><i class="fa fa-arrow-circle-right" aria-hidden="true"></i> primefaces <small class='group-info' >org.primefaces</small></a><br/><a title='This artifact is from the group com.github.noraui' class='btn btn-default btn-xs small-margin-bottom ellipsis sidebar-btn' href='/artifacts/com.github.noraui/ojdbc7' ><i class="fa fa-arrow-circle-right" aria-hidden="true"></i> ojdbc7 <small class='group-info' >com.github.noraui</small></a><br/><a title='This artifact is from the group com.jfoenix' class='btn btn-default btn-xs small-margin-bottom ellipsis sidebar-btn' href='/artifacts/com.jfoenix/jfoenix' ><i class="fa fa-arrow-circle-right" aria-hidden="true"></i> jfoenix <small class='group-info' >com.jfoenix</small></a><br/><a title='This artifact is from the group org.testng' class='btn btn-default btn-xs small-margin-bottom ellipsis sidebar-btn' href='/artifacts/org.testng/testng' ><i class="fa fa-arrow-circle-right" aria-hidden="true"></i> testng <small class='group-info' >org.testng</small></a><br/><a title='This artifact is from the group com.googlecode.json-simple' class='btn btn-default btn-xs small-margin-bottom ellipsis sidebar-btn' href='/artifacts/com.googlecode.json-simple/json-simple' ><i class="fa fa-arrow-circle-right" aria-hidden="true"></i> json-simple <small class='group-info' >com.googlecode.json-simple</small></a><br/><a title='This artifact is from the group org.seleniumhq.selenium' class='btn btn-default btn-xs small-margin-bottom ellipsis sidebar-btn' href='/artifacts/org.seleniumhq.selenium/selenium-server' ><i class="fa fa-arrow-circle-right" aria-hidden="true"></i> selenium-server <small class='group-info' >org.seleniumhq.selenium</small></a><br/><a title='This artifact is from the group com.itextpdf' class='btn btn-default btn-xs small-margin-bottom ellipsis sidebar-btn' href='/artifacts/com.itextpdf/itextpdf' ><i class="fa fa-arrow-circle-right" aria-hidden="true"></i> itextpdf <small class='group-info' >com.itextpdf</small></a><br/><a title='This artifact is from the group org.springframework' class='btn btn-default btn-xs small-margin-bottom ellipsis sidebar-btn' href='/artifacts/org.springframework/spring-core' ><i class="fa fa-arrow-circle-right" aria-hidden="true"></i> spring-core <small class='group-info' >org.springframework</small></a><br/>                </div>
                </div>
            </section>
            <section>
                <div class="panel panel-primary">
                    <div class="panel-heading margin-bottom">Related Groups</div>
                    <div class="">
                        <a class='btn btn-default btn-xs small-margin-bottom ellipsis sidebar-btn' href='/artifacts/org.springframework' ><i class="fa fa-arrow-circle-right" aria-hidden="true"></i> org.springframework</a><br/><a class='btn btn-default btn-xs small-margin-bottom ellipsis sidebar-btn' href='/artifacts/org.apache.poi' ><i class="fa fa-arrow-circle-right" aria-hidden="true"></i> org.apache.poi</a><br/><a class='btn btn-default btn-xs small-margin-bottom ellipsis sidebar-btn' href='/artifacts/org.hibernate' ><i class="fa fa-arrow-circle-right" aria-hidden="true"></i> org.hibernate</a><br/><a class='btn btn-default btn-xs small-margin-bottom ellipsis sidebar-btn' href='/artifacts/org.springframework.boot' ><i class="fa fa-arrow-circle-right" aria-hidden="true"></i> org.springframework.boot</a><br/><a class='btn btn-default btn-xs small-margin-bottom ellipsis sidebar-btn' href='/artifacts/com.fasterxml.jackson.core' ><i class="fa fa-arrow-circle-right" aria-hidden="true"></i> com.fasterxml.jackson.core</a><br/><a class='btn btn-default btn-xs small-margin-bottom ellipsis sidebar-btn' href='/artifacts/com.itextpdf' ><i class="fa fa-arrow-circle-right" aria-hidden="true"></i> com.itextpdf</a><br/><a class='btn btn-default btn-xs small-margin-bottom ellipsis sidebar-btn' href='/artifacts/org.seleniumhq.selenium' ><i class="fa fa-arrow-circle-right" aria-hidden="true"></i> org.seleniumhq.selenium</a><br/><a class='btn btn-default btn-xs small-margin-bottom ellipsis sidebar-btn' href='/artifacts/mysql' ><i class="fa fa-arrow-circle-right" aria-hidden="true"></i> mysql</a><br/><a class='btn btn-default btn-xs small-margin-bottom ellipsis sidebar-btn' href='/artifacts/org.finos.legend.engine' ><i class="fa fa-arrow-circle-right" aria-hidden="true"></i> org.finos.legend.engine</a><br/><a class='btn btn-default btn-xs small-margin-bottom ellipsis sidebar-btn' href='/artifacts/org.apache.httpcomponents' ><i class="fa fa-arrow-circle-right" aria-hidden="true"></i> org.apache.httpcomponents</a><br/><a class='btn btn-default btn-xs small-margin-bottom ellipsis sidebar-btn' href='/artifacts/org.apache.logging.log4j' ><i class="fa fa-arrow-circle-right" aria-hidden="true"></i> org.apache.logging.log4j</a><br/><a class='btn btn-default btn-xs small-margin-bottom ellipsis sidebar-btn' href='/artifacts/org.openjfx' ><i class="fa fa-arrow-circle-right" aria-hidden="true"></i> org.openjfx</a><br/><a class='btn btn-default btn-xs small-margin-bottom ellipsis sidebar-btn' href='/artifacts/org.apache.commons' ><i class="fa fa-arrow-circle-right" aria-hidden="true"></i> org.apache.commons</a><br/><a class='btn btn-default btn-xs small-margin-bottom ellipsis sidebar-btn' href='/artifacts/org.json' ><i class="fa fa-arrow-circle-right" aria-hidden="true"></i> org.json</a><br/><a class='btn btn-default btn-xs small-margin-bottom ellipsis sidebar-btn' href='/artifacts/com.google.guava' ><i class="fa fa-arrow-circle-right" aria-hidden="true"></i> com.google.guava</a><br/><a class='btn btn-default btn-xs small-margin-bottom ellipsis sidebar-btn' href='/artifacts/com.google.zxing' ><i class="fa fa-arrow-circle-right" aria-hidden="true"></i> com.google.zxing</a><br/><a class='btn btn-default btn-xs small-margin-bottom ellipsis sidebar-btn' href='/artifacts/net.sf.jasperreports' ><i class="fa fa-arrow-circle-right" aria-hidden="true"></i> net.sf.jasperreports</a><br/><a class='btn btn-default btn-xs small-margin-bottom ellipsis sidebar-btn' href='/artifacts/javax.xml.bind' ><i class="fa fa-arrow-circle-right" aria-hidden="true"></i> javax.xml.bind</a><br/><a class='btn btn-default btn-xs small-margin-bottom ellipsis sidebar-btn' href='/artifacts/ojdbc' ><i class="fa fa-arrow-circle-right" aria-hidden="true"></i> ojdbc</a><br/><a class='btn btn-default btn-xs small-margin-bottom ellipsis sidebar-btn' href='/artifacts/com.google.code.facebook-java-api' ><i class="fa fa-arrow-circle-right" aria-hidden="true"></i> com.google.code.facebook-java-api</a><br/>                </div>
                </div>
            </section>
        </aside>
        <div class='clear'></div>
    </main>
    </div>
    <br/><br/>
        <div class="align-center">&copy; 2015 - 2024 <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>