UNPKG

extra-string

Version:

A [string] is a sequence of characters.

1,964 lines 173 kB
//#region CONSTANTS
/** Decimal digits 0-9. */ export const DIGITS = "0123456789";
/** Octal digits 0-7. */ export const OCT_DIGITS = "01234567";
/** Hexadecimal digits 0-9, A-F, a-f. */ export const HEX_DIGITS = "0123456789ABCDEFabcdef";
/** English letters A-Z. */ export const UPPERCASE = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
/** English letters a-z. */ export const LOWERCASE = "abcdefghijklmnopqrstuvwxyz";
/** Combination of uppercase, lowercase english letters. */ export const LETTERS = UPPERCASE + LOWERCASE;
/** Punctuation symbols (ASCII). */ export const PUNCTUATION = "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~";
/** The string "\t\n\x0b\x0c\r ". */ export const WHITESPACE = "\t\n\x0b\x0c\r ";
/** Combination of digits, letters, punctuation, and whitespace (ASCII). */ export const PRINTABLE = DIGITS + LETTERS + PUNCTUATION + WHITESPACE;
/** Minimum unicode code point. */ export const MIN_CODE_POINT = 0x000000;
/** Maximum unicode code point. */ export const MAX_CODE_POINT = 0x10FFFF;
//#endregion
//#region UTILITY FUNCTIONS
/**
 * Return the same (first) value.
 * @param v a value
 * @returns v
 */ function IDENTITY(v) {
  return v;
}
function mod(x, y) {
  return x - y * Math.floor(x / y);
}
//#endregion
//#region BUILT-IN
//#region GENERATE
/**
 * Get characters whose UTF-16 code units are given.
 * @param codes UTF-16 code units
 * @returns characters
 */ export function fromCharCode(...codes) {
  return String.fromCharCode(...codes);
}
/**
 * Get characters whose unicode code points are given.
 * @param codes unicode code points
 * @returns characters
 */ export function fromCodePoint(...codes) {
  return String.fromCodePoint(...codes);
}
/**
 * Combine multiple values into a string.
 * @param values values
 * @returns combined string
 */ export function concat(...values) {
  return "".concat(...values);
}
/**
 * Repeat string given number of times.
 * @param x a string
 * @param times number of times
 * @returns repeated string
 */ export function repeat(x, times) {
  return x.repeat(times);
}
//#endregion
//#region ABOUT
/**
 * Get primitive value of string object.
 * @param x a string object
 * @returns primitive value
 */ export function valueOf(x) {
  return x.valueOf();
}
/**
 * Get length of string.
 * @param x a string
 * @returns length of string
 */ export function length(x) {
  return x.length;
}
export { length as size };
// TODO: countCharacters ([...str].length)
// - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/length
/**
 * Get character at given index in string.
 * @param x a string
 * @param at character index
 * @return character
 */ export function charAt(x, at) {
  return x.charAt(at);
}
// TODO: Getting whole characters (non-BMP, surrogate pairs)
// - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/charAt
/**
 * Get UTF-16 code unit of a character in string.
 * @param x a string
 * @param at character index
 * @returns UTF-16 code unit
 */ export function charCodeAt(x, at) {
  return x.charCodeAt(at);
}
// TODO: Getting whole characters (non-BMP, surrogate pairs)
// - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/charCodeAt
/**
 * Get unicode code point of a character in string.
 * @param x a string
 * @param at character index
 * @returns unicode code point
 */ export function codePointAt(x, at) {
  return x.codePointAt(at);
}
//#endregion
//#region COMPARE
/**
 * Compare two strings in the current or given locale.
 * @param x a string
 * @param y another string
 * @param locales language or locale tag(s)
 * @param options comparison options
 * @returns x<y: -ve, x=y: 0, x>y: +ve
 * @example
 * ```javascript
 * xstring.localeCompare('abra', 'bulbasaur');
 * // → -1
 *
 * xstring.localeCompare('bulbasaur', 'bulbasaur');
 * // → 0
 *
 * xstring.localeCompare('charmeleon', 'bulbasaur');
 * // → 1
 * ```
 */ export function localeCompare(x, y, locales, options) {
  return x.localeCompare(y, locales, options);
}
//#endregion
//#region SEARCH
/**
 * Check if string has a given infix.
 * @param x a string
 * @param infix infix to look for
 * @param start start index [0]
 * @returns has infix?
 */ export function includes(x, infix, start) {
  return x.includes(infix, start);
}
/**
 * Check if string has a given prefix.
 * @param x a string
 * @param prefix prefix to look for
 * @param start start index [0]
 * @returns has prefix?
 */ export function startsWith(x, prefix, start) {
  return x.startsWith(prefix, start);
}
/**
 * Check if string has a given suffix.
 * @param x a string
 * @param suffix suffix to look for
 * @param end end index [end]
 * @returns has suffix?
 */ export function endsWith(x, suffix, end) {
  return x.endsWith(suffix, end);
}
/**
 * Get first index of a given infix in string.
 * @param x a string
 * @param infix infix to look for
 * @param start start index [0]
 * @returns first index of infix
 */ export function indexOf(x, infix, start) {
  return x.indexOf(infix, start);
}
/**
 * Get last index of a given infix in string.
 * @param x a string
 * @param infix infix to look for
 * @param rstart reverse start index [end-1]
 * @returns last index of infix
 */ export function lastIndexOf(x, infix, rstart) {
  return x.lastIndexOf(infix, rstart);
}
/**
 * Get first index of regular expression match in string.
 * @param x a string
 * @param regexp regular expression
 * @returns first index of match
 */ export function search(x, regexp) {
  return x.search(regexp);
}
/**
 * Get results of matching string with regular expression.
 * @param x a string
 * @param regexp regular expression
 * @returns /g: all matches, else: match with capturing groups or null
 */ export function match(x, regexp) {
  return x.match(regexp);
}
/**
 * Get detailed results of matching string with regular expression.
 * @param x a string
 * @param regexp regular expression (with /g)
 * @returns match with capturing groups ...
 */ export function matchAll(x, regexp) {
  return x.matchAll(regexp);
}
//#endregion
//#region CONVERT
/**
 * Get string representation of string.
 * @param x a string
 * @returns string representation
 */ export function toString(x) {
  return x.toString();
}
//#endregion
//#region PART
/**
 * Extract section of string.
 * @param x a string
 * @param start start index (-ve ⇒ from right) [0]
 * @param end end index (-ve ⇒ from right) [end]
 * @returns section of string
 */ export function slice(x, start, end) {
  return x.slice(start, end);
}
/**
 * Extract section of string.
 * @param x a string
 * @param start start index (-ve ⇒ 0) [0]
 * @param end end index (-ve ⇒ 0) [end]
 * @returns section of string
 */ export function substring(x, start, end) {
  return x.substring(start, end);
}
/**
 * Split string by a given separator into substrings.
 * @param x a string
 * @param separator separator string or regular expression
 * @param limit maximum number of substrings
 * @returns substrings
 */ export function split(x, separator, limit) {
  return x.split(separator, limit);
}
// splitBy(x: string, separator: function, limit?: number): string[]?
//#endregion
//#region WHITESPACE
/**
 * Remove whitespace from begining of string.
 * @param x a string
 * @returns trimmed string
 */ export function trimStart(x) {
  return x.trimStart();
}
/**
 * Remove whitespace from end of string.
 * @param x a string
 * @returns trimmed string
 */ export function trimEnd(x) {
  return x.trimEnd();
}
/**
 * Remove whitespace from begining and end of string.
 * @param x a string
 * @returns trimmed string
 */ export function trim(x) {
  return x.trim();
}
/**
 * Pad start of string to fit a desired length.
 * @param x a string
 * @param length desired length
 * @param padding pad with [ ]
 * @returns padded string
 */ export function padStart(x, length, padding = " ") {
  return x.padStart(length, padding);
}
/**
 * Pad end of string to fit a desired length.
 * @param x a string
 * @param length desired length
 * @param padding pad with [ ]
 * @returns padded string
 */ export function padEnd(x, length, padding = " ") {
  return x.padEnd(length, padding);
}
//#endregion
//#region TRANSFORM (CASE)
/**
 * Convert string to upper case.
 * @param x a string
 * @returns upper cased string
 */ export function toUpperCase(x) {
  return x.toUpperCase();
}
/**
 * Convert string to upper case, as per locale-specific case mappings.
 * @param x a string
 * @param locales BCP 47 language tag(s)
 * @returns upper cased string
 */ export function toLocaleUpperCase(x, locales) {
  return x.toLocaleUpperCase(locales);
}
/**
 * Convert string to lower case.
 * @param x a string
 * @returns lower cased string
 */ export function toLowerCase(x) {
  return x.toLowerCase();
}
/**
 * Convert string to lower case, as per locale-specific case mappings.
 * @param x a string
 * @param locales BCP 47 language tag(s)
 * @returns lower cased string
 */ export function toLocaleLowerCase(x, locales) {
  return x.toLocaleLowerCase(locales);
}
export function replace(x, pattern, replacement) {
  return x.replace(pattern, replacement);
}
// export function replaceAll(x: string, org: string, to: string): string {
//   return x.replaceAll(org, to);
// }
/**
 * Normalize string by given form, as per Unicode Standard Annex #15.
 * @param x a string
 * @param form normalization form (NFC, NFD, NFKC, NFKD)
 * @returns normalized string
 */ export function normalize(x, form) {
  return x.normalize(form);
}
//#endregion
//#endregion
//#region BUILT-IN (ARRAY)
//#region GENERATE
/**
 * Create string from arguments, like `Array.of()`.
 * @param args arguments
 * @returns p + q + ... | [p, q, ...] = args
 * @example
 * ```javascript
 * xstring.of('a', 1);
 * // → 'a1'
 *
 * xstring.of(1, 2);
 * // → '12'
 *
 * xstring.of();
 * // → ''
 * ```
 */ export function of(...args) {
  let a = "";
  for(let i = 0, I = args.length; i < I; i++)a += args[i];
  return a;
}
/**
 * Create string from iterable, like `Array.from()`.
 * @param xs list of strings (iterable)
 * @param fm map function (x, i)
 * @param ths this argument
 * @returns p + q + ... | [p, q, ...] = xs
 * @example
 * ```javascript
 * xstring.from(['a', 'b']);
 * // → 'ab'
 *
 * xstring.from('abc', (v) => String.fromCharCode(v.charCodeAt()+1));
 * // → 'bcd'
 *
 * xstring.from(new Set().add('a').add('b'));
 * // → 'ab'
 *
 * xstring.from(new Map().set('a', 1).set('b', 2));
 * // → 'a,1b,2'
 * ```
 */ export function from(xs, fm, ths) {
  let a = "", i = 0;
  for (const x of xs){
    a += fm ? fm.call(ths, x, i) : x;
    i++;
  }
  return a;
}
//#endregion
//#region ABOUT
/**
 * Get keys of string, like `Array.keys()`.
 * @param x a string
 * @returns 0, 1, ...
 * @example
 * ```javascript
 * xstring.keys('ash');
 * // → [0, 1, 2]
 *
 * xstring.keys('');
 * // → []
 * ```
 */ function* _keys(x) {
  let i = 0;
  for (const _c of x)yield i++;
}
/**
 * Get characters of string, like `Array.values()`.
 * @param x a string
 * @returns x[0], x[1], ...
 */ function* _values(x) {
  for (const c of x)yield c;
}
// export {values as characters};
/**
 * Get entries of string, like `Array.entries()`.
 * @param x a string
 * @returns [0, x[0]], [1, x[1]], ...
 * @example
 * ```javascript
 * xstring.entries('ship');
 * // → [[0, 's'], [1, 'h'], [2, 'i'], [3, 'p']]
 *
 * xstring.entries('');
 * // → []
 * ```
 */ function* _entries(x) {
  let i = 0;
  for (const c of x)yield [
    i++,
    c
  ];
}
//#endregion
//#region TRANSFORM
/**
 * Remove/replace characters in a string.
 * @param x a string
 * @param start start index
 * @param remove number of characters to remove
 * @param add substring to add
 * @returns x[0:i] + add + x[i+r] | i = start, r = remove
 */ export function splice(x, start, remove = 0, add = "") {
  return x.slice(0, start) + add + x.slice(start + remove);
}
/**
 * Reverse a string.
 * @param x a string
 * @returns reversed string
 */ export function reverse(x) {
  return [
    ...x
  ].reverse().join("");
}
/**
 * Arrange characters in an order.
 * @param x a string
 * @param fc compare function (a, b)
 */ export function sort(x, fc) {
  return [
    ...x
  ].sort(fc).join("");
}
/**
 * Filter characters which pass a test.
 * @param x a string
 * @param ft test function (v, i, x)
 * @param ths this argument
 * @returns characters which pass the test
 * @example
 * ```javascript
 * xstring.filter('g00df00d', (v) => v<='f');
 * // → '00df00d'
 *
 * xstring.filter('badfood', (v) => v<='f');
 * // → 'badfd'
 *
 * xstring.filter('', (v) => v<='f');
 * // → ''
 * ```
 */ export function filter(x, ft, ths) {
  let a = "", i = 0;
  for (const c of x)if (ft.call(ths, c, i++, x)) a += c;
  return a;
}
//#endregion
//#endregion
//#region CUSTOM
//#region GENERATE
/** A buffer containing only spaces, for `spaces()`. */ const SPACE_BUFFER = " ".repeat(1024);
/**
 * Get a string of spaces.
 * @param n number of spaces
 * @returns string of spaces
 * @example
 * ```javascript
 * xstring.spaces(4);
 * // → '    '
 *
 * xstring.spaces(6);
 * // → '      '
 *
 * xstring.spaces(0);
 * // → ''
 *
 * xstring.spaces(-1);
 * // → ''
 * ```
 */ export function spaces(n) {
  const S = SPACE_BUFFER.length;
  if (n < S) return SPACE_BUFFER.slice(0, n);
  return SPACE_BUFFER.repeat(n / S) + " ".repeat(n % S);
}
//#endregion
//#region ABOUT
/**
 * Check if value is a string.
 * @param v a value
 * @returns whether value is a string
 * @example
 * ```javascript
 * xstring.is('panini');
 * // → true
 *
 * xstring.is("valmiki");
 * // → true
 *
 * xstring.is(String('vyasa'));
 * // → true
 *
 * xstring.is({shakespeare: 'literature'});
 * // → false
 *
 * xstring.is(71811313518);
 * // → false (what's this?)
 *
 * xstring.is();
 * // → false
 * ```
 */ export function is(v) {
  return typeof v === "string";
}
/**
 * Check if string is empty.
 * @param x a string
 * @returns whether string is empty
 */ export function isEmpty(x) {
  return x.length === 0;
}
/**
 * Check if string is a character.
 * @param x a string
 * @returns whether string is a character
 */ export function isCharacter(x) {
  return x.length === 1;
}
/**
 * Get non-negative index within string.
 * @param x a string
 * @param at character index
 * @returns +ve index
 */ export function index(x, at) {
  // Can be rewritten with a math/number function?
  if (at < 0) return Math.max(0, x.length + at);
  return Math.min(at, x.length);
}
/**
 * Get non-negative index range within string.
 * @param x a string
 * @param start start index
 * @param end end index
 * @returns +ve index range [start, end]
 */ export function indexRange(x, start, end) {
  // Can be rewritten with a math/number function?
  start = index(x, start);
  end = index(x, end);
  return [
    Math.min(start, end),
    Math.max(start, end)
  ];
}
/**
 * Get unicode code point range of string.
 * @param x a string
 * @returns code point range [min, max]
 */ export function codePointRange(x) {
  let min = MAX_CODE_POINT;
  let max = MIN_CODE_POINT;
  for (const c of x){
    const v = c.codePointAt(0);
    min = Math.min(min, v);
    max = Math.max(max, v);
  }
  return [
    min,
    max
  ];
}
//#endregion
//#region COMPARE
/**
 * Compare two strings.
 * @param x a string
 * @param y another string
 * @returns x<y: -ve, x=y: 0, x>y: +ve
 */ export function compare(x, y) {
  return x < y ? -1 : x > y ? 1 : 0;
}
/**
 * Check if two strings are equal.
 * @param x a string
 * @param y another string
 * @returns x=y?
 */ export function isEqual(x, y) {
  return x === y;
}
//#endregion
//#region SEARCH
// Check if string has a given prefix.
export { startsWith as isPrefix };
// Check if string has a given suffix.
export { endsWith as isSuffix };
// Check if string has a given infix.
export { includes as isInfix };
//#endregion
//#region PART
/**
 * Get character at a given index in string.
 * @param x a string
 * @param at character index (-ve ⇒ from right)
 * @returns x[i] | i = at
 */ export function get(x, at) {
  return x.charAt(at >= 0 ? at : x.length + at);
}
export { get as at };
/**
 * Get characters at indices.
 * @param x a string
 * @param ats character indices (-ve ⇒ from right)
 * @returns x[i] + x[j] + ... | [i, j, ...] = ats
 */ export function getAll(x, ats) {
  let a = "";
  for (const at of ats)a += get(x, at);
  return a;
}
/**
 * Write a substring at specified index in string.
 * @param x a string
 * @param at write index (-ve ⇒ from right)
 * @param write substring to write
 * @returns x[0:i] + w + x[i+|w|:] | i = at, w = write
 */ export function set(x, at, write) {
  return x.slice(0, at) + write + x.slice(at + write.length);
}
/**
 * Get leftmost part of string.
 * @param x a string
 * @param count number of characters [1]
 * @returns x[0:n] | n = count
 * @example
 * ```javascript
 * xstring.begin('Thai Sweet Chilli Sauce', 4);
 * // → 'Thai'
 *
 * xstring.begin('Thai Sweet Chilli Sauce', 10);
 * // → 'Thai Sweet'
 *
 * xstring.begin('Thai Sweet Chilli Sauce', 80);
 * // → 'Thai Sweet Chilli Sauce'
 *
 * xstring.begin('Thai Sweet Chilli Sauce', -1);
 * // → ''
 * ```
 */ export function begin(x, count = 1) {
  return x.slice(0, count);
}
export { begin as prefix };
export { begin as left };
/**
 * Get a portion of string from middle.
 * @param x a string
 * @param start start index
 * @param count number of characters [1]
 * @returns x[i:i+n] | i = start, n = count
 * @example
 * ```javascript
 * xstring.mid('Thai Sweet Chilli Sauce', 5, 5);
 * // → 'Sweet'
 *
 * xstring.mid('Thai Sweet Chilli Sauce', 5, 12);
 * // → 'Sweet Chilli'
 *
 * xstring.mid('Thai Sweet Chilli Sauce', 5);
 * // → 'Sweet Chilli Sauce'
 *
 * xstring.mid('Thai Sweet Chilli Sauce', 5, -1);
 * // → ''
 *
 * xstring.mid('Thai Sweet Chilli Sauce', -5);
 * // → 'Sauce'
 * ```
 */ export function middle(x, start, count = 1) {
  return x.slice(start, start + count);
}
export { middle as infix };
/**
 * Get rightmost part of string.
 * @param x a string
 * @param count number of characters [1]
 * @returns x[|x|-n:] | n = count
 * @example
 * ```javascript
 * xstring.end('Thai Sweet Chilli Sauce', 5);
 * // → 'Sauce'
 *
 * xstring.end('Thai Sweet Chilli Sauce', 12);
 * // → 'Chilli Sauce'
 *
 * xstring.end('Thai Sweet Chilli Sauce', 80);
 * // → 'Thai Sweet Chilli Sauce'
 *
 * xstring.end('Thai Sweet Chilli Sauce', -1);
 * // → ''
 * ```
 */ export function end(x, count = 1) {
  return x.slice(x.length - count);
}
export { end as suffix };
export { end as right };
//#endregion
//#region PART (TODO)
// import {chunk as arrayChunk} from "extra-array";
/**
 * Break string into chunks of given size.
 * @param x a string
 * @param n chunk size (1)
 * @param s chunk step (n)
 */ // function chunk(x: string, n: number=1, s: number=n): string[] {
//   return arrayChunk(x as any, n, s) as any;
// }
// import {infixes as arrayInfixes} from "extra-array";
/**
 * Lists all possible infixes.
 * @param x a string
 * @param n number of values (-1 ⇒ any)
 */ // function infixes(x: string, n: number=-1): IterableIterator<string> {
//   return arrayInfixes(x as any, n) as any;
// }
// import {prefixes as arrayPrefixes} from "extra-array";
/**
 * Lists all possible prefixes.
 * @param x a string
 * @param n number of values (-1 ⇒ any)
 */ // function prefixes(x: string, n: number=-1): IterableIterator<string> {
//   return arrayPrefixes(x as any, n) as any;
// }
// import {suffixes as arraySuffixes} from "extra-array";
/**
 * Lists all possible suffixes.
 * @param x a string
 * @param n number of values (-1 ⇒ any)
 */ // function suffixes(x: string, n: number=-1): IterableIterator<string> {
//   return arraySuffixes(x as any, n) as any;
// }
//#endregion
//#region SEARCH
// Get length of longest string in an iterable.
function maxLength(xs) {
  let a = 0;
  for (const x of xs)a = Math.max(a, x.length);
  return a;
}
/**
 * Get set-listed symbol at specified index in string.
 * @param x a string
 * @param set set of symbols
 * @param i start index [0]
 * @param L max symbol length [0 ⇒ unspecified]
 * @example
 * ```javascript
 * xstring.symbolAt('rho+pi', new Set().add('pi').add('rho').add('+').add('-'), 0);
 * // → 'rho'
 *
 * xstring.symbolAt('rho+pi', new Set().add('pi').add('rho').add('+').add('-'), 2);
 * // → undefined (no match at 2)
 *
 * xstring.symbolAt('rho+pi', new Set().add('pi').add('rho').add('+').add('-'), 3);
 * // → '+'
 *
 * xstring.symbolAt('rho+pi', new Set(['pi', 'rho', '+', '-']), 4, 3);
 * // → 'pi' (longest symbol='rho')
 * ```
 */ function _symbolAt(x, set, i = 0, L = 0) {
  if (L === 0) L = maxLength(set);
  for(let l = L; l > 0; l--){
    const sym = x.substring(i, i + l);
    if (set.has(sym)) return sym;
  }
  return null;
}
/**
 * Get the longest common infix between strings.
 * @param x a string
 * @param y another string
 * @returns longest common infix
 * @example
 * ```javascript
 * xstring.longestCommonInfix('mangala', 'mangalyaan');
 * // → 'mangal'
 *
 * xstring.longestCommonInfix('easter', 'tertiary');
 * // → 'ter'
 *
 * xstring.longestCommonInfix('dismiss', 'mississipi');
 * // → 'miss'
 * ```
 */ export function longestCommonInfix(x, y) {
  let ai = 0, al = 0;
  for(let i = 0, I = x.length; i < I; i++){
    for(let j = 0, J = y.length, l = 0; j < J; j++){
      l = x[i + l] === y[j] ? l + 1 : 0;
      if (l > al) {
        ai = j - l + 1;
        al = l;
      }
    }
  }
  return y.substring(ai, ai + al);
}
/**
 * Get the longest common prefix of strings.
 * @param x a string
 * @param y another string
 * @returns longest common prefix
 * @example
 * ```javascript
 * xstring.longestCommonPrefix('peacock', 'peahen');
 * // → 'pea'
 *
 * xstring.longestCommonPrefix('inception', 'interstellar');
 * // → 'in'
 *
 * xstring.longestCommonPrefix('mars', 'tars');
 * // → ''
 * ```
 */ export function longestCommonPrefix(x, y) {
  let i = 0;
  for(const I = Math.min(x.length, y.length); i < I; i++)if (x[i] !== y[i]) break;
  return x.substring(0, i);
}
/**
 * Get the longest common suffix of strings.
 * @param x a string
 * @param y another string
 * @returns longest common suffix
 * @example
 * ```javascript
 * xstring.longestCommonSuffix('peacock', 'hancock');
 * // → 'cock'
 *
 * xstring.longestCommonSuffix('mars', 'tars');
 * // → 'ars'
 *
 * xstring.longestCommonSuffix('chief', 'master');
 * // → ''
 * ```
 */ export function longestCommonSuffix(x, y) {
  let i = x.length - 1;
  for(let j = y.length - 1; i >= 0 && j >= 0; i--, j--)if (x[i] !== y[j]) break;
  return x.substring(i + 1);
}
/**
 * Get the longest uncommon infixes of strings.
 * @param x a string
 * @param y another string
 * @returns [infix1, infix2]
 * @example
 * ```javascript
 * xstring.longestUncommonInfixes('rollcage', 'ridecage');
 * // → ['oll', 'ide']
 *
 * xstring.longestUncommonInfixes('riverbed', 'roverbed');
 * // → ['i', 'o']
 *
 * xstring.longestUncommonInfixes('chocolatier', 'engineer');
 * // → ['chocolati', 'engine']
 * ```
 */ export function longestUncommonInfixes(x, y) {
  const X = x.length, Y = y.length;
  const i = longestCommonPrefix(x, y).length;
  const j = longestCommonSuffix(x, y).length;
  return [
    x.substring(i, X - j),
    y.substring(i, Y - j)
  ];
}
//#endregion
//#region TRANSFORM (SUPER/SUBSCRIPT)
/** Superscript characters that can be transformed to baseline with `SUPERSCRIPT_TARGET`. */ const SUPERSCRIPT_SOURCE = "⁰¹²³⁴⁵⁶⁷⁸⁹⁺⁻⁼⁽⁾ᵝᵞᵟᶿᶥᵠᵡᴬᴮᴰᴱᴳᴴᴵᴶᴷᴸᴹᴺᴼᴾᴿᵀᵁⱽᵂᶦᶫᶰᶸᵃᵇᶜᵈᵉᶠᵍʰⁱʲᵏˡᵐⁿᵒᵖʳˢᵗᵘᵛʷˣʸᶻ";
/** Baseline characters that can be transformed from superscript with `SUPERSCRIPT_SOURCE`. */ const SUPERSCRIPT_TARGET = "0123456789+-=()βγδθιφχABDEGHIJKLMNOPRTUVWILNUabcdefghijklmnoprstuvwxyz";
/** Subscript characters that can be transformed to baseline with `SUBSCRIPT_TARGET`. */ const SUBSCRIPT_SOURCE = "₀₁₂₃₄₅₆₇₈₉₊₋₌₍₎ₔᵦᵧᵨᵩᵪₐₑₕᵢⱼₖₗₘₙₒₚᵣₛₜᵤᵥₓ";
/** Baseline characters that can be transformed from subscript with `SUBSCRIPT_TARGET`. */ const SUBSCRIPT_TARGET = "0123456789+-=()əβγρφχaehijklmnoprstuvx";
function toBaselineDirect(x) {
  let a = "";
  for (let c of x){
    const j = SUPERSCRIPT_SOURCE.indexOf(c);
    const k = SUBSCRIPT_SOURCE.indexOf(c);
    if (j >= 0) c = SUPERSCRIPT_TARGET[j];
    if (k >= 0) c = SUPERSCRIPT_TARGET[k];
    a += c;
  }
  return a;
}
function toBaselineIndirect(x, fsup, fsub) {
  let a = "", i = 0, t = 0;
  let tmp = "", mode = 0;
  fsup = fsup || IDENTITY;
  fsub = fsub || IDENTITY;
  for (const c of x){
    t = tmp.length;
    const j = SUPERSCRIPT_SOURCE.indexOf(c);
    const k = SUBSCRIPT_SOURCE.indexOf(c);
    const m = (j >= 0 ? 1 : 0) + (k >= 0 ? 2 : 0);
    if (m !== mode && t) a += mode === 0 ? tmp : mode === 1 ? fsup(tmp, i - t) : fsub(tmp, i - t);
    tmp += m === 0 ? c : m === 1 ? SUPERSCRIPT_TARGET[j] : SUBSCRIPT_TARGET[k];
    mode = m;
    i++;
  }
  if (tmp) a += mode === 0 ? tmp : mode === 1 ? fsup(tmp, i - t) : fsub(tmp, i - t);
  return a;
}
/**
 * Convert a string to baseline characters (limited support).
 * @param x a string
 * @param fsup map function for superscript characters (v, i, x)
 * @param fsub map function for subscript characters (v, i, x)
 * @returns baselined string
 * @example
 * ```javascript
 * xstring.toBaseline('ax²+bx+c');
 * // → 'ax2+bx+c'
 *
 * xstring.toBaseline('H₂SO₄ beaker');
 * // → 'H2SO4 beaker'
 *
 * xstring.toBaseline('6.626 x 10⁻³⁴', ['^']);
 * // → '6.626 x 10^-34'
 *
 * xstring.toBaseline('1010₂', null, [' (base-', ')']);
 * // → '1010 (base-2)'
 * ```
 */ export function toBaseline(x, fsup = null, fsub = null) {
  if (!fsup && !fsub) return toBaselineDirect(x);
  return toBaselineIndirect(x, fsup || IDENTITY, fsub || IDENTITY);
}
/** Superscript ASCII characters after space (32). */ const SUPERSCRIPT_LOOKUP = "        ⁽⁾ ⁺ ⁻  ⁰¹²³⁴⁵⁶⁷⁸⁹   ⁼   ᴬᴮ ᴰᴱ ᴳᴴᴵᴶᴷᴸᴹᴺᴼᴾ ᴿ ᵀᵁ ᵂ         ᵃᵇᶜᵈᵉᶠᵍʰⁱʲᵏˡᵐⁿᵒᵖ ʳˢᵗᵘᵛʷˣʸᶻ     ";
/**
 * Convert a string to superscript characters (limited support).
 * @param x a string
 * @returns superscripted characters
 * @example
 * ```javascript
 * xstring.toSuperscript('hello world');
 * // → 'ʰᵉˡˡᵒ ʷᵒʳˡᵈ'
 *
 * xstring.toSuperscript('DECCAN PLATEAU');
 * // → 'ᴰᴱCCᴬᴺ ᴾᴸᴬᵀᴱᴬᵁ'
 *
 * '6.626 x 10' + xstring.toSuperscript('-34');
 * // → '6.626 x 10⁻³⁴' (Planck's constant)
 * ```
 */ export function toSuperscript(x) {
  let a = "";
  for (const c of x){
    const d = SUPERSCRIPT_LOOKUP[c.charCodeAt(0) - 32] || " ";
    a += d === " " ? c : d;
  }
  return a;
}
/** Subscript ASCII characters after space (32). */ const SUBSCRIPT_LOOKUP = "        ₍₎ ₊ ₋  ₀₁₂₃₄₅₆₇₈₉   ₌                                   ₐ   ₑ  ₕᵢⱼₖₗₘₙₒₚ ᵣₛₜᵤᵥ ₓ       ";
/**
 * Convert a string to superscript characters (limited support).
 * @param x a string
 * @returns superscripted characters
 * @example
 * ```javascript
 * xstring.toSubscript('hello world');
 * // → 'ₕₑₗₗₒ wₒᵣₗd'
 *
 * xstring.toSubscript('DECCAN PLATEAU');
 * // → 'DECCAN PLATEAU'
 *
 * 'KNO' + xstring.toSubscript('3');
 * // → 'KNO₃' (Potassium Nitrate)
 * ```
 */ export function toSubscript(x) {
  let a = "";
  for (const c of x){
    const d = SUBSCRIPT_LOOKUP[c.charCodeAt(0) - 32] || " ";
    a += d === " " ? c : d;
  }
  return a;
}
//#endregion
//#region TRANSFORM (CASE)
// Convert only the first letter of a string to upper-case, remaining lower-case.
function toBeginUpperCase(x) {
  return x.slice(0, 1).toUpperCase() + x.slice(1).toLowerCase();
}
// Convert only the first letter of a string to upper-case, remaining as-is.
function toBeginUpperAnyCase(x) {
  return x.slice(0, 1).toUpperCase() + x.slice(1);
}
// Convert only the first letter of a string to lower-case, remaining as-is.
function toBeginLowerAnyCase(x) {
  return x.slice(0, 1).toUpperCase() + x.slice(1);
}
// Convert only the first and last letters of a string to upper-case, remaining lower-case.
function toBorderUpperCase(x) {
  if (x.length <= 2) return x.toUpperCase();
  return x.slice(0, 1).toUpperCase() + x.slice(1, -1).toLowerCase() + x.slice(-1).toUpperCase();
}
/**
 * Split a string into words, after de-casing it.
 * @param x a string
 * @param re word seperator pattern [/[^0-9A-Za-z]+/g]
 * @returns words in the string
 * @example
 * ```javascript
 * xstring.toWords('Malwa Plateau');
 * // → ['Malwa', 'Plateau']
 *
 * xstring.toWords('::chota::nagpur::');
 * // → ['chota', 'nagpur']
 *
 * xstring.toWords('deccan___plateau');
 * // → ['deccan', 'plateau']
 *
 * xstring.toWords('westernGhats');
 * // → ['western', 'Ghats']
 *
 * xstring.toWords('parseURLToJSON');
 * // → ['parse', 'URL', 'To', 'JSON']
 */ export function toWords(x, re = null) {
  const words = [];
  const tokens = x.split(re || /[^0-9A-Za-z]+/g).filter(IDENTITY);
  for (const token of tokens){
    const re = /[A-Z]+/g;
    let m = null, i = 0;
    while((m = re.exec(token)) != null){
      if (i !== m.index) words.push(token.slice(i, m.index));
      if (m[0].length === 1 || m.index + m[0].length === token.length) i = m.index;
      else {
        words.push(token.slice(m.index, m.index + m[0].length - 1));
        i = m.index + m[0].length - 1;
      }
    }
    if (i !== token.length) words.push(token.slice(i));
  }
  return words;
}
// NOTE: Shouldn't this be called splitWords() or splitIntoWords() or splitIntoTokens()?
/**
 * Convert a string to title-case.
 * @param x a string
 * @param re word seperator pattern [/[^0-9A-Za-z]+/g]
 * @returns Title Case
 * @example
 * ```javascript
 * xstring.toTitleCase('Geminid meteor shower');
 * // → 'Geminid Meteor Shower'
 *
 * xstring.toTitleCase('deccan___plateau');
 * // → 'Deccan Plateau'
 *
 * xstring.toTitleCase('parseURLToJSON', null, '_');
 * // → 'Parse_URL_To_JSON'
 * ```
 */ export function toTitleCase(x, re = null, sep = " ") {
  return toWords(x, re).map(toBeginUpperCase).join(sep);
}
/**
 * Convert a string to kebab-case.
 * @param x a string
 * @param re word seperator pattern [/[^0-9A-Za-z]+/g]
 * @param sep separator to join with [-]
 * @returns kebab-case | kebab<join>case
 */ export function toKebabCase(x, re = null, sep = "-") {
  const words = x.split(re || /[^0-9A-Za-z]+/g).filter(IDENTITY);
  for(let i = 0, I = words.length; i < I; ++i){
    words[i] = words[i].replace(/[A-Z]+/g, (m, off)=>m.length === 1 || off + m.length === words[i].length ? sep + m : sep + m.slice(0, -1) + sep + m.slice(-1));
    if (words[i].startsWith(sep)) words[i] = words[i].slice(sep.length);
  }
  return words.join(sep).toLowerCase();
}
/**
 * Convert a string to snake-case.
 * @param x a string
 * @param re word seperator pattern [/[^0-9A-Za-z]+/g]
 * @returns snake_case
 * @example
 * ```javascript
 * xstring.toSnakeCase('Malwa Plateau');
 * // → 'malwa_plateau'
 *
 * xstring.toSnakeCase('::chota::nagpur::', '-');
 * // → 'chota-nagpur'
 *
 * xstring.toSnakeCase('deccan___plateau', '.', '_');
 * // → 'deccan.plateau'
 * ```
 */ export function toSnakeCase(x, re = null) {
  return toKebabCase(x, re, "_");
}
/**
 * Convert a string to camel-case.
 * @param x a string
 * @param re word seperator pattern [/[^0-9A-Za-z]+/g]
 * @param upper upper camel case?
 * @returns camelCase | CamelCase
 * @example
 * ```javascript
 * xstring.toCamelCase('Western Ghats');
 * // → 'westernGhats'
 *
 * xstring.toCamelCase('cardamom--hills', 1);
 * // → 'CardamomHills'
 *
 * xstring.toCamelCase('EAstErn__ghAts', 1, '_');
 * // → 'EasternGhats'
 * ```
 */ export function toCamelCase(x, re = null, upper = false) {
  let a = "";
  const words = x.split(re || /[^0-9A-Za-z]+/g).filter(IDENTITY);
  for (const w of words)a += toBeginUpperAnyCase(w.replace(/[A-Z]+/g, toBorderUpperCase));
  return upper ? a : toBeginLowerAnyCase(a);
}
/**
 * Convert a string to pascal-case.
 * @param x a string
 * @param re word seperator pattern [/[^0-9A-Za-z]+/g]
 * @returns PascalCase
 */ export function toPascalCase(x, re = null) {
  return toCamelCase(x, re, true);
}
/**
 * Convert a string to slug-case (URL-friendly kebab-case).
 * @param x a string
 * @param re word separator pattern [/[^0-9A-Za-z]+/g]
 * @param sep separator to join with [-]
 * @returns slug-case | slug<join>case
 */ export function toSlugCase(x, re = null, sep = "-") {
  x = x.normalize("NFKD").replace(/[\u0300-\u036f]/g, ""); // Remove accents
  // deno-lint-ignore no-control-regex
  return toKebabCase(x.replace(/[^\x00-\x7F]/g, ""), re, sep); // Remove non-ASCII chars
}
export { toSlugCase as slugify };
//#endregion
//#region TRANSFORM
/**
 * Get characters that cycle through string.
 * @param x a string
 * @param start start index
 * @param count number of characters [length]
 */ export function cycle(x, start, count = x.length) {
  if (!x || count <= 0) return "";
  let a = x.slice(start, start + count);
  count -= a.length; // start = index(x, start);
  const M = Math.floor(count / x.length);
  for(let m = 0; m < M; m++)a += x;
  return a += x.slice(0, count % x.length);
}
/**
 * Rotate characters in string.
 * @param x a string
 * @param n rotate amount (+ve: left, -ve: right)
 */ export function rotate(x, n) {
  const i = mod(n, x.length);
  return x.slice(i) + x.slice(0, i);
}
// function replacePrefix(str, pre, rep) {
//   return str.startsWith(pre)? rep+str.substr(pre.length):str;
// }
// replacePrefix('tinman', 'tin', 'gun');
// // 'gunman'
// replacePrefix('muscleman', 'cle', 'cled');
// // 'muscleman' (not prefix)
// replacePrefix('-1.6022e-19', '-', '');
// // '1.6022e-19'
// function replaceSuffix(str, suf, rep) {
//   return str.endsWith(suf)? str.substr(0, str.length-suf.length)+rep:str;
// }
// replaceSuffix('tinman', 'man', 'woman');
// // 'tinwoman'
// replaceSuffix('muscleman', 'cle', 'cled');
// // 'muscleman'
// replaceSuffix('laughed', 'ed', '');
// // 'laugh'
// function* unique<T, U=T>(x: Iterable<T>, fc: compareFn<T|U>=null, fm: mapFn<T, T|U>=null): IterableIterator<T> {
//   yield* union([], x, fc, fm);
// }
// swapRange()
// import {cutAt as arrayCut} from "extra-array";
/**
 * Breaks string at given indices.
 * @param x a string
 * @param is split indices (sorted)
 */ // function cut(x: string, is: Iterable<number>): string[] {
//   return arrayCut(x as any, is as any) as any;
// }
// import {cutAtRight as arrayCutRight} from "extra-array";
/**
 * Breaks string after given indices.
 * @param x a string
 * @param is split indices (sorted)
 */ // function cutRight(x: string, is: Iterable<number>): string[] {
//   return arrayCutRight(x as any, is as any) as any;
// }
// function unionCompare(x: string, y: string, fn: any=null): string {
//   // let fn = fn||cmp;
//   let s = new Set<string>();
//   let a = x;
//   y: for(let v of y) {
//     for(let u of x)
//       if(fn(u, v)===0) continue y;
//     for(let u of s)
//       if(fn(u, v)===0) continue y;
//     a += v; s.add(v);
//   }
//   return a;
// }
// function unionMap(x: string, y: string, fn: any=null): string {
//   // let fn = fn||id;
//   let s = new Set();
//   let a = "", i = -1, j = -1;
//   for(let u of x) {
//     let u1 = fn(u, ++i, x);
//     s.add(u1); a += u;
//   }
//   for(let v of y) {
//     let v1 = fn(v, ++j, y);
//     if(!s.has(v1)) { s.add(v1); a += v; }
//   }
//   return a;
// }
// function unionDual(x: string, y: string, fc: any=null, fm: any=null): string {
//   // let fc = fc||cmp, fm = fm||id;
//   let s = new Set<string>();
//   let a = x, j = -1;
//   y: for(let v of y) {
//     let v1 = fm(v, ++j, y);
//     let i = -1;
//     for(let u of x) {
//       let u1 = fm(u, ++i, x);
//       if(fc(u1, v1)===0) continue y;
//     }
//     let i = -1;
//     for(let u of s) {
//       let u1 = fm(u, ++i, y);
//       if(fc(u1, v1)===0) continue y;
//     }
//     a += v; s.add(v);
//   }
//   return a;
// }
/**
 * Gives characters present in any string.
 * @param x a string
 * @param y another string
 * @param fc compare function (a, b)
 * @param fm map function (v, i, x)
 */ // function union(x: string, y: string, fc: any=null, fm: any=null): string {
//   if(fc) return unionDual(x, y, fc, fm);
//   else return unionMap(x, y, fm);
// }
//#endregion
//#region NGRAMS
/**
 * Get n-grams of a string.
 * @param x a string
 * @param n n-gram length
 * @returns [x[0:n], x[1:n+1], ...]
 * @example
 * ```javascript
 * xstring.ngrams('card', 2);
 * // → ['ca', 'ar', 'rd']
 *
 * xstring.ngrams('triple-h', 3);
 * // → ['tri', 'rip', 'ipl', 'ple', 'le-', 'e-h']
 *
 * xstring.ngrams('brocklesner', 10);
 * // → ['brocklesne', 'rocklesner']
 * ```
 */ export function ngrams(x, n) {
  const a = [];
  for(let i = 0, I = x.length - n + 1; i < I; i++)a[i] = x.substring(i, i + n);
  return a;
}
/**
 * Find unique n-grams of a string.
 * @param x a string
 * @param n n-gram length
 * @returns Set \{gᵢ\} | gᵢ = iᵗʰ n-gram
 */ export function uniqueNgrams(x, n) {
  const a = new Set();
  for(let i = 0, I = x.length - n + 1; i < I; i++)a.add(x.substring(i, i + n));
  return a;
}
/**
 * Count the total number of n-grams of a string.
 * @param x a string
 * @param n n-gram length
 * @returns |gᵢ| | gᵢ = iᵗʰ n-gram
 */ export function countNgrams(x, n) {
  return Math.max(0, x.length - n + 1);
}
/**
 * Count the total number of unique n-grams of a string.
 * @param x a string
 * @param n n-gram length
 * @returns |Set \{gᵢ\}| | gᵢ = iᵗʰ n-gram
 */ export function countUniqueNgrams(x, n) {
  return uniqueNgrams(x, n).size;
}
/**
 * Count each n-gram of a string.
 * @param x a string
 * @param n n-gram length
 * @returns Map \{gᵢ: count(gᵢ)\} | gᵢ = iᵗʰ n-gram
 */ export function countEachNgram(x, n) {
  const a = new Map();
  for(let i = 0, I = x.length - n + 1; i < I; i++){
    const g = x.substring(i, i + n);
    a.set(g, (a.get(g) || 0) + 1);
  }
  return a;
}
/**
 * Get matching n-grams between strings.
 * @param x a string
 * @param y another string
 * @param n n-gram length
 * @returns [gᵢ] | gᵢ = iᵗʰ matching n-gram
 * @example
 * ```javascript
 * xstring.matchingNgrams('worm', 'storm', 2);
 * // → ['or', 'rm']
 *
 * xstring.matchingNgrams('astronaut', 'astronomer', 3);
 * // → ['ast', 'str', 'tro', 'ron']
 *
 * xstring.matchingNgrams('coconut', 'cotton', 2);
 * // → ['co', 'on']
 * ```
 */ export function matchingNgrams(x, y, n) {
  const gs = countEachNgram(x, n), a = [];
  for(let i = 0, I = y.length - n + 1; i < I; i++){
    const g = y.substring(i, i + n);
    const c = gs.get(g) || 0;
    if (c) {
      a.push(g);
      gs.set(g, c - 1);
    }
  }
  return a;
}
/**
 * Get unique matching n-grams between strings.
 * @param x a string
 * @param y another string
 * @param n n-gram length
 * @returns Set \{gᵢ\} | gᵢ = iᵗʰ unique matching n-gram
 */ export function uniqueMatchingNgrams(x, y, n) {
  const a = new Set();
  const gs = uniqueNgrams(x, n);
  for(let i = 0, I = y.length - n + 1; i < I; i++){
    const g = y.substring(i, i + n);
    if (gs.has(g)) a.add(g);
  }
  return a;
}
/**
 * Count the total number of matching n-grams between strings.
 * @param x a string
 * @param y another string
 * @param n n-gram length
 * @returns |[gᵢ]| | gᵢ = iᵗʰ matching n-gram
 * @example
 * ```javascript
 * xstring.countMatchingNgrams('worm', 'storm', 2);
 * // → 2 ('or', 'rm')
 *
 * xstring.countMatchingNgrams('astronaut', 'astronomer', 3);
 * // → 4 ('ast', 'str', 'tro', 'ron')
 *
 * xstring.countMatchingNgrams('coconut', 'cotton', 2);
 * // → 2 ('co', 'on')
 * ```
 */ export function countMatchingNgrams(x, y, n) {
  const gs = countEachNgram(x, n);
  let a = 0;
  for(let i = 0, I = y.length - n + 1; i < I; i++){
    const g = y.substring(i, i + n);
    const c = gs.get(g) || 0;
    if (c) {
      a++;
      gs.set(g, c - 1);
    }
  }
  return a;
}
/**
 * Count each matching n-gram between strings.
 * @param x a string
 * @param y another string
 * @param n n-gram length
 * @returns Map \{gᵢ: count(gᵢ)\} | gᵢ = iᵗʰ matching n-gram
 */ export function countEachMatchingNgram(x, y, n) {
  const a = new Map();
  const gs = countEachNgram(x, n);
  for(let i = 0, I = y.length - n + 1; i < I; i++){
    const g = y.substring(i, i + n);
    const c = gs.get(g) || 0;
    if (c) {
      a.set(g, (a.get(g) || 0) + 1);
      gs.set(g, c - 1);
    }
  }
  return a;
}
/**
 * Count the total number of unique matching n-grams between strings.
 * @param x a string
 * @param y another string
 * @param n n-gram length
 * @returns |Set \{gᵢ\}| | gᵢ = iᵗʰ unique matching n-gram
 */ export function countUniqueMatchingNgrams(x, y, n) {
  const gs = uniqueNgrams(x, n);
  let a = 0;
  for(let i = 0, I = y.length - n + 1; i < I; i++){
    const g = y.substring(i, i + n);
    if (gs.has(g)) {
      a++;
      gs.delete(g);
    }
  }
  return a;
}
//#endregion
//#region DISTANCE
/**
 * Get euclidean distance between strings.
 * @param x a string
 * @param y another string
 * @returns euclidean distance
 * @example
 * ```javascript
 * xstring.euclideanDistance('a', 'b');
 * // → 1
 *
 * xstring.euclideanDistance('logo', 'pogo');
 * // → 4
 *
 * xstring.euclideanDistance('doctor', 'broker');
 * // → 18.384776310850235
 * ```
 */ export function euclideanDistance(x, y) {
  let a = 0;
  for(let i = 0, I = Math.max(x.length, y.length); i < I; i++){
    const d = (x.codePointAt(i) || 0) - (y.codePointAt(i) || 0);
    a += d * d;
  }
  return Math.sqrt(a);
}
// normalizedEuclideanDistance()?
/**
 * Get hamming distance between strings.
 * @param x a string
 * @param y another string
 * @returns hamming distance
 * @example
 * ```javascript
 * xstring.hammingDistance('rowan', 'raven');
 * // → 3
 *
 * xstring.hammingDistance('atkinson', 'atkinson');
 * // → 0
 *
 * xstring.hammingDistance('bean', 'green');
 * // → NaN (strings are of different length)
 * ```
 */ export function hammingDistance(x, y) {
  let a = 0;
  for(let i = 0, I = Math.max(x.length, y.length); i < I; i++)if (x.charAt(i) !== y.charAt(i)) a++;
  return a;
}
/**
 * Get jaccard index between strings.
 * @param x a string
 * @param y another string
 * @param n n-gram length
 * @returns |X ∩ Y|/|X ∪ Y| | X,Y = n-grams of x,y
 * @example
 * ```javascript
 * xstring.jaccardIndex('pocket', 'pocket');
 * // → 1
 *
 * xstring.jaccardIndex('monster', 'rocket');
 * // → 0
 *
 * xstring.jaccardIndex('pikachu', 'raichu', 3);
 * // → 0.125
 * ```
 */ export function jaccardIndex(x, y, n) {
  const gx = countNgrams(x, n);
  const gy = countNgrams(y, n);
  const g = countMatchingNgrams(x, y, n);
  return gx + gy ? g / (gx + gy - g) : 1;
}
/**
 * Get jaccard distance between strings.
 * @param x a string
 * @param y another string
 * @param n n-gram length
 * @returns 1 - jaccardIndex(x, y)
 * @example
 * ```javascript
 * xstring.jaccardDistance('pocket', 'pocket');
 * // → 0
 *
 * xstring.jaccardDistance('monster', 'rocket');
 * // → 1
 *
 * xstring.jaccardDistance('pikachu', 'raichu', 3);
 * // → 0.875
 * ```
 */ export function jaccardDistance(x, y, n) {
  return 1 - jaccardIndex(x, y, n);
}
/**
 * Get Sørensen-Dice index between strings.
 * @param x a string
 * @param y another string
 * @param n n-gram length
 * @returns 2|X ∩ Y|/(|X| + |Y|) | X,Y = n-grams of x,y
 * @example
 * ```javascript
 * xstring.sorensenDiceIndex('pocket', 'pocket');
 * // → 1
 *
 * xstring.sorensenDiceIndex('monster', 'rocket');
 * // → 0
 *
 * xstring.sorensenDiceIndex('pikachu', 'raichu', 3);
 * // → 0.2222222222222222
 * ```
 */ export function sorensenDiceIndex(x, y, n) {
  const gx = countNgrams(x, n);
  const gy = countNgrams(y, n);
  const g = countMatchingNgrams(x, y, n);
  return gx + gy ? 2 * g / (gx + gy) : 1;
}
/**
 * Get Sørensen-Dice distance between strings.
 * @param x a string
 * @param y another string
 * @param n n-gram length
 * @returns 1 - sorensenDiceIndex(x, y)
 * @example
 * ```javascript
 * xstring.sorensenDiceDistance('pocket', 'pocket');
 * // → 0
 *
 * xstring.sorensenDiceDistance('monster', 'rocket');
 * // → 1
 *
 * xstring.sorensenDiceDistance('pikachu', 'raichu', 3);
 * // → 0.7777777777777778
 * ```
 */ export function sorensenDiceDistance(x, y, n) {
  return 1 - sorensenDiceIndex(x, y, n);
}
/**
 * Get Tversky index between strings.
 * @param x a string
 * @param y another string
 * @param n n-gram length
 * @param a alpha [1]
 * @param b beta [1]
 * @returns |X ∩ Y|/(|X ∩ Y| + α|X \ Y| + β|Y \ X|) | X,Y = n-grams of x,y
 * @example
 * ```javascript
 * xstring.tverskyIndex('pocket', 'pocket');
 * // → 1
 *
 * xstring.tverskyIndex('monster', 'rocket');
 * // → 0
 *
 * xstring.tverskyIndex('pikachu', 'raichu', 0.2, 0.4, 3);
 * // → 0.3333333333333333
 * ```
 */ export function tverskyIndex(x, y, n, a = 1, b = 1) {
  const gx = countNgrams(x, n);
  const gy = countNgrams(y, n);
  const g = countMatchingNgrams(x, y, n);
  return gx + gy ? g / (g + a * (gx - g) + b * (gy - g)) : 1;
}
/**
 * Get Tversky distance between strings.
 * @param x a string
 * @param y another string
 * @param n n-gram length
 * @param a alpha [1]
 * @param b beta [1]
 * @returns 1 - tverskyIndex(x, y)
 * @example
 * ```javascript
 * xstring.tverskyDistance('pocket', 'pocket');
 * // → 0
 *
 * xstring.tverskyDistance('monster', 'rocket');
 * // → 1
 *
 * xstring.tverskyDistance('pikachu', 'raichu', 0.2, 0.4, 3);
 * // → 0.6666666666666667
 * ```
 */ export function tverskyDistance(x, y, n, a = 1, b = 1) {
  return 1 - tverskyIndex(x, y, n, a, b);
}
/**
 * Get matching characters between strings, within a specified distance.
 * @param x a string
 * @param y another string
 * @param d maximum distance between matching characters
 * @returns [matching characters in x, matching characters in y]
 */ function rangedMatches(x, y, d) {
  // 1. Prepare strike-off buffer
  let mx = "", my = "";
  const by = Array.from(y);
  // 2. Get matches in first string
  for(let i = 0, I = x.length; i < I; i++){
    let j = by.lastIndexOf(x.charAt(i), i);
    if (j < 0 || i - j > d) j = by.indexOf(x.charAt(i), i + 1);
    if (j < 0 || j - i > d) continue;
    mx += x.charAt(i);
    by[j] = null;
  }
  // 3. Get matches in second string
  for(let j = 0, J = y.length; j < J; j++)if (by[j] == null) my += y.charAt(j);
  return [
    mx,
    my
  ];
}
// countRangedMatches()?
/**
 * Get Jaro similarity between strings.
 * @param x a string
 * @param y another string
 * @returns (m/|x| + m/|y| + (m-t)/m)/3 | m = # matches, t = # transpositions
 * @example
 * ```javascript
 * xstring.jaroSimilarity('no', 'match');
 * // → 0
 *
 * xstring.jaroSimilarity('teapot', 'teapot');
 * // → 1
 *
 * xstring.jaroSimilarity('jellyfish', 'smellyfish');
 * // → 0.8962962962962964
 * ```
 */ export function jaroSimilarity(x, y) {
  const X = x.length, Y = y.length;
  const d = Math.floor(Math.max(X, Y) / 2) - 1;
  const [mx, my] = rangedMatches(x, y, d), m = mx.length;
  const t = hammingDistance(mx, my) / 2;
  return m ? (m / X + m / Y + (m - t) / m) / 3 : 0;
}
/**
 * Get Jaro distance between strings.
 * @param x a string
 * @param y another string
 * @returns 1 - jaroSimilarity(x, y)
 * @example
 * ```javascript
 * xstring.jaroDistance('no', 'match');
 * // → 1
 *
 * xstring.jaroDistance('teapot', 'teapot');
 * // → 0
 *
 * xstring.jaroDistance('jellyfish', 'smellyfish');
 * // → 0.10370370370370363
 * ```
 */ export function jaroDistance(x, y) {
  return 1 - jaroSimilarity(x, y);
}
/**
 * Get Jaro-Winkler similarity between strings.
 * @param x a string
 * @param y another string
 * @param p scaling factor for common prefix (0.1 - 0.25) [0.1]
 * @returns simⱼ + ℓp(1 - simⱼ) | simⱼ = jaro similarity, ℓ = |longest common prefix|
 * @example
 * ```javascript
 * xstring.jaroWinklerSimilarity('no', 'match');
 * // → 0
 *
 * xstring.jaroWinklerSimilarity('teapot', 'teapot');
 * // → 1
 *
 * xstring.jaroWinklerSimilarity('jelly', 'jellyfish');
 * // → 0.9111111111111111
 * ```
 */ export function jaroWinklerSimilarity(x, y, p = 0.1) {
  const s = jaroSimilarity(x, y);
  const l = longestCommonPrefix(x, y.substring(0, 4)).length;
  return s + l * p * (1 - s);
}
/**
 * Get Jaro-Winkler distance between strings.
 * @param x a string
 * @param y another string
 * @param p scaling factor for common prefix (0.1 - 0.25) [0.1]
 * @returns 1 - jaroWinklerSimilarity(x, y)
 * @example
 * ```javascript
 * xstring.jaroWinklerDistance('no', 'match');
 * // → 1
 *
 * xstring.jaroWinklerDistance('teapot', 'teapot');
 * // → 0
 *
 * xstring.jaroWinklerDistance('jelly', 'jellyfish');
 * // → 0.0888888888888889
 * ```
 */ export function jaroWinklerDistance(x, y, p = 0.1) {
  return 1 - jaroWinklerSimilarity(x, y, p);
}
/**
 * Get Levenshtein distance between strings.
 * @param x a string
 * @param y another string
 * @param ins insertion cost [1]
 * @param del deletion cost [1]
 * @param sub substitution cost [1]
 * @returns levenshtein distance
 * @example
 * ```javascript
 * xstring.levenshteinDistance('hareram', 'hareram');
 * // → 0
 *
 * xstring.levenshteinDistance('church', 'torch');
 * // → 3
 *
 * xstring.levenshteinDistance('mr. bean', 'ben 10', 1, 0.1, 1);
 * // → 3.5
 * ```
 */ export function levenshteinDistance(x, y, ins = 1, del = 1, sub = 1) {
  // 1. Remove common prefix, suffix
  const infixes = longestUncommonInfixes(x, y);
  x = infixes[0];
  y = infixes[1];
  const X = x.length, Y = y.length;
  // 2. Get distance in 1st row
  const d0 = [], d1 = [];
  for(let j = 0, v = 0; j <= Y; v += ins)d0[j++] = v;
  // 3. Get distance in remaining rows
  for(let i = 1; i <= X; i++){
    // a. Get distance in 1st column
    const di = i & 1 ? d1 : d0;
    const dh = i & 1 ? d0 : d1;
    di[0] = dh[0] + del;
    // b. Get distance of remaining columns
    for(let j = 1; j <= Y; j++){
      const cost = x[i - 1] === y[j - 1] ? 0 : sub;
      di[j] = Math.min(dh[j] + del, di[j - 1] + ins, dh[j - 1] + cost);
    }
  }
  return (X & 1 ? d1 : d0)[Y];
}
/**
 * Get Damerau–Levenshtein distance between strings.
 * @param x a string
 * @param y another string
 * @param ins insertion cost [1]
 * @param del deletion cost [1]
 * @param sub substitution cost [1]
 * @param tra transposition cost [1]
 * @returns damerau–levenshtein distance
 * @example
 * ```javascript
 * xstring.damerauLevenshteinDistance('gnu', 'gun');
 * // → 1
 *
 * xstring.damerauLevenshteinDistance('software', 'softwear');
 * // → 2
 *
 * xstring.damerauLevenshteinDistance('level field', 'lvele feidl', 1, 1, 1, 0.1);
 * // → 0.4
 * ```
 */ export function damerauLevenshteinDistance(x, y, ins = 1, del = 1, sub = 1, tra = 1) {
  // 1. Remove common prefix, suffix
  const infixes = longestUncommonInfixes(x, y);
  x = infixes[0];
  y = infixes[1];
  const X = x.length, Y = y.length;
  const I = X + 2, J = Y + 2, L = X + Y;
  // 2. Prepare 1st 2 rows
  const d0 = [
    L
  ], d1 = [
    L
  ];
  const d = [
    d0,
    d1
  ], da = new Map();
  for(let j = 1, v = 0; j < J; j++, v += ins){
    d0[j] = L;
    d1[j] = v;
  }
  // 3. Prepare remaining rows
  for(let i = 2; i < I; i++){
    // a. Prepare 1st 2 columns
    let db = 0;
    const dh = d[i - 1];
    const di = [
      L,
      dh[1] + del
    ];
    d[i] = di;
    // b. Prepare remaining columns
    for(let j = 2; j < J; j++){
      const k = da.get(y[j - 2]) || 0, l = db;
      let cost = sub;
      if (x[i - 2] === y[j - 2]) {
        db = j - 1;
        cost = 0;
      }
      di[j] = Math.min(di[j - 1] + ins, dh[j] + del, dh[j - 1] + cost, d[k][l] + (i - k - 2) + tra + (j - l - 2));
    }
    da.set(x[i - 2], i - 1);
  }
  return d[X + 1][Y + 1];
} //#endregion
 //#endregion
 //#region TODO
 // function mapReplace(str, map) {
 //   for(let [k, v] of map)
 //     str = str.replace(k, v);
 //   return str;
 // }
 // mapReplace('alpha beta', new Map().set('alpha', 'α').set('beta', 'β'));
 // // 'α β'
 // mapReplace('gamma DELTA', new Map().set('gamma', 'γ').set('delta', 'δ'));
 // // 'γ DELTA'
 // mapReplace('Epsilon ZETA', new Map().set(/epsilon/gi, 'ε').set(/zeta/gi, 'ζ'));
 // // 'ε ζ'
 // function mapReplacePrefix(str, map, l=0) {
 //   // 1. get max prefix length
 //   if(!l) for(let k of map.keys()) {
 //     l = l<k.length? k.length:l;
 //   }
 //   // 2. replace prefix
 //   for(let i=l; i; i--) {
 //     let k = str.substr(0, i);
 //     if(map.has(k)) return map.get(k)+str.substr(i);
 //   }
 //   return str;
 // }
 // mapReplacePrefix('dishonoured', new Map([['dis', ''], ['un', ''], ['in', '']]));
 // // 'honoured'
 // mapReplacePrefix('dishonoured', new Map([['honour', 'respect'], ['flatter', 'mock']]));
 // // 'dishonoured' (only prefix)
 // mapReplacePrefix('dishonoured', new Map([['dis', 'redis'], ['redis', 'super']]), 5);
 // // 'redishonoured' (only once)
 // function mapReplaceSuffix(str, map, l=0) {
 //   // 1. get max suffix length
 //   if(!l) for(let k of map.keys()) {
 //     l = l<k.length? k.length:l;
 //   }
 //   // 2. replace suffix
 //   for(let i=l; i; i--) {
 //     let k = str.substr(-i);
 //     if(map.has(k)) return str.substr(0, str.length-i)+map.get(k);
 //   }
 //   return str;
 // }
 // mapReplaceSuffix('ender', new Map([['er', ''], ['ing', ''], ['ed', '']]));
 // // 'end
 // mapReplaceSuffix('ender', new Map([['end', 'right'], ['start', 'left']]));
 // // 'ender' (only suffix)
 // mapReplaceSuffix('ender', new Map([['er', ' game'], ['game', 'play']]), 4);
 // // 'end game' (only once)
 // function objectReplace(str, obj) {
 //   for(let k in obj)
 //     str = str.replace(k, obj[k]);
 //   return str;
 // }
 // objectReplace('alpha beta', {'alpha': 'α', 'beta': 'β'});
 // // 'α β'
 // objectReplace('gamma DELTA', {'gamma': 'γ', 'delta': 'δ'});
 // // 'γ DELTA'
 // objectReplace('Epsilon ZETA'.toLowerCase(), {'epsilon': 'ε', 'zeta': 'ζ'});
 // // 'ε ζ'
 // function objectReplacePrefix(str, obj, l=0) {
 //   // 1. get max prefix length
 //   if(!l) for(let k in obj) {
 //     l = l<k.length? k.length:l;
 //   }
 //   // 2. replace prefix
 //   for(let i=l; i; i--)  {
 //     // let k = str.substr(0, i);
 //     if(obj[k]!=null) return obj[k]+str.substr(i);
 //   }
 //   return str;
 // }
 // objectReplacePrefix('dishonoured', {'dis': '', 'un': '', 'in': ''});
 // // 'honoured'
 // objectReplacePrefix('dishonoured', {'honour': 'respect', 'flatter': 'mock'});
 // // 'dishonoured' (only prefix)
 // objectReplacePrefix('dishonoured', {'dis': 'redis', 'redis': 'super'}, 5);
 // // 'redishonoured' (only once)
 // function objectReplaceSuffix(str, obj, l=0) {
 //   // 1. get max suffix length
 //   if(!l) for(let k in obj) {
 //     l = l<k.length? k.length:l;
 //   }
 //   // 2. replace suffix
 //   for(let i=l; i; i--) {
 //     // let k = str.substr(-i);
 //     if(obj[k]!=null) return str.substr(0, str.length-i)+obj[k];
 //   }
 //   return str;
 // }
 // reduceRight('abc', (acc, v) => acc+v);
 // // 'cba'
 // reduceRight('123', (acc, v) => acc+v, '-');
 // // '-321'
 // reduceRight('a', (acc, v) => acc+v);
 // // 'a'
 // reduceRight('', (acc, v) => acc+v);
 // // undefined
 // find('badd0g', (v) => v>'f');
 // // 'g'
 // find('badcab', (v) => v>'f');
 // // undefined
 // find('', (v) => v>'f');
 // // undefined
 // findIndex('badd0g', (v) => v>'f');
 // // 5
 // findIndex('badcab', (v) => v>'f');
 // // -1
 // findIndex('', (v) => v>'f');
 // // -1
 // every('badf00d', (v) => v<='f');
 // // true
 // every('g00df00d', (v) => v<='f');
 // // false
 // every('', (v) => v<='f');
 // // true
 // xstring.euclideanDistance('a', 'b');
 // // → 0.000015259021896696422 (normalized distance between 1 character code)
 //
 // xstring.euclideanDistance('logo', 'pogo');
 // // → 0.00006103608758678569
 //
 // xstring.euclideanDistance('doctor', 'broker');
 // // → 0.00028053370429312937
 // chr(65); // 'A'
 // chr(97); // 'a'
 // asc('A');     // 65
 // asc('aA');    // 97
 // asc('aA', 1); // 65
 //#endregion
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImZpbGU6Ly8vaG9tZS9ydW5uZXIvd29yay9leHRyYS1zdHJpbmcvZXh0cmEtc3RyaW5nL2luZGV4LnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8vI3JlZ2lvbiBDT05TVEFOVFNcbi8qKiBEZWNpbWFsIGRpZ2l0cyAwLTkuICovXG5leHBvcnQgY29uc3QgRElHSVRTOiBzdHJpbmcgICAgID0gXCIwMTIzNDU2Nzg5XCI7XG4vKiogT2N0YWwgZGlnaXRzIDAtNy4gKi9cbmV4cG9ydCBjb25zdCBPQ1RfRElHSVRTOiBzdHJpbmcgPSBcIjAxMjM0NTY3XCI7XG4vKiogSGV4YWRlY2ltYWwgZGlnaXRzIDAtOSwgQS1GLCBhLWYuICovXG5leHBvcnQgY29uc3QgSEVYX0RJR0lUUzogc3RyaW5nID0gXCIwMTIzNDU2Nzg5QUJDREVGYWJjZGVmXCI7XG5cbi8qKiBFbmdsaXNoIGxldHRlcnMgQS1aLiAqL1xuZXhwb3J0IGNvbnN0IFVQUEVSQ0FTRTogc3RyaW5nID0gXCJBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWlwiO1xuLyoqIEVuZ2xpc2ggbGV0dGVycyBhLXouICovXG5leHBvcnQgY29uc3QgTE9XRVJDQVNFOiBzdHJpbmcgPSBcImFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6XCI7XG4vKiogQ29tYmluYXRpb24gb2YgdXBwZXJjYXNlLCBsb3dlcmNhc2UgZW5nbGlzaCBsZXR0ZXJzLiAqL1xuZXhwb3J0IGNvbnN0IExFVFRFUlM6IHN0cmluZyA9IFVQUEVSQ0FTRSArIExPV0VSQ0FTRTtcblxuLyoqIFB1bmN0dWF0aW9uIHN5bWJvbHMgKEFTQ0lJKS4gKi9cbmV4cG9ydCBjb25zdCBQVU5DVFVBVElPTjogc3RyaW5nID0gXCIhXFxcIiMkJSYnKCkqKywtLi86Ozw9Pj9AW1xcXFxdXl9ge3x9flwiO1xuLyoqIFRoZSBzdHJpbmcgXCJcXHRcXG5cXHgwYlxceDBjXFxyIFwiLiAqL1xuZXhwb3J0IGNvbnN0IFdISVRFU1BBQ0U6IHN0cmluZyAgPSBcIlxcdFxcblxceDBiXFx4MGNcXHIgXCI7XG5cbi8qKiBDb21iaW5hdGlvbiBvZiBkaWdpdHMsIGxldHRlcnMsIHB1bmN0dWF0aW9uLCBhbmQgd2hpdGVzcGFjZSAoQVNDSUkpLiAqL1xuZXhwb3J0IGNvbnN0IFBSSU5UQUJMRTogc3RyaW5nID0gRElHSVRTICsgTEVUVEVSUyArIFBVTkNUVUFUSU9OICsgV0hJVEVTUEFDRTtcblxuLyoqIE1pbmltdW0gdW5pY29kZSBjb2RlIHBvaW50LiAqL1xuZXhwb3J0IGNvbnN0IE1JTl9DT0RFX1BPSU5UOiBudW1iZXIgPSAweDAwMDAwMDtcbi8qKiBNYXhpbXVtIHVuaWNvZGUgY29kZSBwb2ludC4gKi9cbmV4cG9ydCBjb25zdCBNQVhfQ09ERV9QT0lOVDogbnVtYmVyID0gMHgxMEZGRkY7XG4vLyNlbmRyZWdpb25cblxuXG5cblxuLy8jcmVnaW9uIFVUSUxJVFkgRlVOQ1RJT05TXG4vKipcbiAqIFJldHVybiB0aGUgc2FtZSAoZmlyc3QpIHZhbHVlLlxuICogQHBhcmFtIHYgYSB2YWx1ZVxuICogQHJldHVybnMgdlxuICovXG5mdW5jdGlvbiBJREVOVElUWTxUPih2OiBUKTogVCB7XG4gIHJldHVybiB2O1xufVxuXG5cbmZ1bmN0aW9uIG1vZCh4OiBudW1iZXIsIHk6IG51bWJlcik6IG51bWJlciB7XG4gIHJldHVybiB4IC0geSAqIE1hdGguZmxvb3IoeC95KTtcbn1cbi8vI2VuZHJlZ2lvblxuXG5cblxuXG4vLyNyZWdpb24gQlVJTFQtSU5cbi8vI3JlZ2lvbiBHRU5FUkFURVxuLyoqXG4gKiBHZXQgY2hhcmFjdGVycyB3aG9zZSBVVEYtMTYgY29kZSB1bml0cyBhcmUgZ2l2ZW4uXG4gKiBAcGFyYW0gY29kZXMgVVRGLTE2IGNvZGUgdW5pdHNcbiAqIEByZXR1cm5zIGNoYXJhY3RlcnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGZyb21DaGFyQ29kZSguLi5jb2RlczogbnVtYmVyW10pOiBzdHJpbmcge1xuICByZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZSguLi5jb2Rlcyk7XG59XG5cblxuLyoqXG4gKiBHZXQgY2hhcmFjdGVycyB3aG9zZSB1bmljb2RlIGNvZGUgcG9pbnRzIGFyZSBnaXZlbi5cbiAqIEBwYXJhbSBjb2RlcyB1bmljb2RlIGNvZGUgcG9pbnRzXG4gKiBAcmV0dXJucyBjaGFyYWN0ZXJzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmcm9tQ29kZVBvaW50KC4uLmNvZGVzOiBudW1iZXJbXSk6IHN0cmluZyB7XG4gIHJldHVybiBTdHJpbmcuZnJvbUNvZGVQb2ludCguLi5jb2Rlcyk7XG59XG5cblxuLyoqXG4gKiBDb21iaW5lIG11bHRpcGxlIHZhbHVlcyBpbnRvIGEgc3RyaW5nLlxuICogQHBhcmFtIHZhbHVlcyB2YWx1ZXNcbiAqIEByZXR1cm5zIGNvbWJpbmVkIHN0cmluZ1xuICovXG5leHBvcnQgZnVuY3Rpb24gY29uY2F0KC4uLnZhbHVlczogdW5rbm93bltdKTogc3RyaW5nIHtcbiAgcmV0dXJuIFwiXCIuY29uY2F0KC4uLnZhbHVlcyBhcyBzdHJpbmdbXSk7XG59XG5cblxuLyoqXG4gKiBSZXBlYXQgc3RyaW5nIGdpdmVuIG51bWJlciBvZiB0aW1lcy5cbiAqIEBwYXJhbSB4IGEgc3RyaW5nXG4gKiBAcGFyYW0gdGltZXMgbnVtYmVyIG9mIHRpbWVzXG4gKiBAcmV0dXJucyByZXBlYXRlZCBzdHJpbmdcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlcGVhdCh4OiBzdHJpbmcsIHRpbWVzOiBudW1iZXIpOiBzdHJpbmcge1xuICByZXR1cm4geC5yZXBlYXQodGltZXMpO1xufVxuLy8jZW5kcmVnaW9uXG5cblxuXG5cbi8vI3JlZ2lvbiBBQk9VVFxuLyoqXG4gKiBHZXQgcHJpbWl0aXZlIHZhbHVlIG9mIHN0cmluZyBvYmplY3QuXG4gKiBAcGFyYW0geCBhIHN0cmluZyBvYmplY3RcbiAqIEByZXR1cm5zIHByaW1pdGl2ZSB2YWx1ZVxuICovXG5leHBvcnQgZnVuY3Rpb24gdmFsdWVPZih4OiBzdHJpbmcpOiBzdHJpbmcge1xuICByZXR1cm4geC52YWx1ZU9mKCk7XG59XG5cblxuLyoqXG4gKiBHZXQgbGVuZ3RoIG9mIHN0cmluZy5cbiAqIEBwYXJhbSB4IGEgc3RyaW5nXG4gKiBAcmV0dXJucyBsZW5ndGggb2Ygc3RyaW5nXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBsZW5ndGgoeDogc3RyaW5nKTogbnVtYmVyIHtcbiAgcmV0dXJuIHgubGVuZ3RoO1xufVxuZXhwb3J0IHtsZW5ndGggYXMgc2l6ZX07XG4vLyBUT0RPOiBjb3VudENoYXJhY3RlcnMgKFsuLi5zdHJdLmxlbmd0aClcbi8vIC0gaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvSmF2YVNjcmlwdC9SZWZlcmVuY2UvR2xvYmFsX09iamVjdHMvU3RyaW5nL2xlbmd0aFxuXG5cbi8qKlxuICogR2V0IGNoYXJhY3RlciBhdCBnaXZlbiBpbmRleCBpbiBzdHJpbmcuXG4gKiBAcGFyYW0geCBhIHN0cmluZ1xuICogQHBhcmFtIGF0IGNoYXJhY3RlciBpbmRleFxuICogQHJldHVybiBjaGFyYWN0ZXJcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNoYXJBdCh4OiBzdHJpbmcsIGF0OiBudW1iZXIpOiBzdHJpbmcge1xuICByZXR1cm4geC5jaGFyQXQoYXQpO1xufVxuLy8gVE9ETzogR2V0dGluZyB3aG9sZSBjaGFyYWN0ZXJzIChub24tQk1QLCBzdXJyb2dhdGUgcGFpcnMpXG4vLyAtIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0phdmFTY3JpcHQvUmVmZXJlbmNlL0dsb2JhbF9PYmplY3RzL1N0cmluZy9jaGFyQXRcblxuXG4vKipcbiAqIEdldCBVVEYtMTYgY29kZSB1bml0IG9mIGEgY2hhcmFjdGVyIGluIHN0cmluZy5cbiAqIEBwYXJhbSB4IGEgc3RyaW5nXG4gKiBAcGFyYW0gYXQgY2hhcmFjdGVyIGluZGV4XG4gKiBAcmV0dXJucyBVVEYtMTYgY29kZSB1bml0XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjaGFyQ29kZUF0KHg6IHN0cmluZywgYXQ6IG51bWJlcik6IG51bWJlciB7XG4gIHJldHVybiB4LmNoYXJDb2RlQXQoYXQpO1xufVxuLy8gVE9ETzogR2V0dGluZyB3aG9sZSBjaGFyYWN0ZXJzIChub24tQk1QLCBzdXJyb2dhdGUgcGFpcnMpXG4vLyAtIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0phdmFTY3JpcHQvUmVmZXJlbmNlL0dsb2JhbF9PYmplY3RzL1N0cmluZy9jaGFyQ29kZUF0XG5cblxuLyoqXG4gKiBHZXQgdW5pY29kZSBjb2RlIHBvaW50IG9mIGEgY2hhcmFjdGVyIGluIHN0cmluZy5cbiAqIEBwYXJhbSB4IGEgc3RyaW5nXG4gKiBAcGFyYW0gYXQgY2hhcmFjdGVyIGluZGV4XG4gKiBAcmV0dXJucyB1bmljb2RlIGNvZGUgcG9pbnRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNvZGVQb2ludEF0KHg6IHN0cmluZywgYXQ6IG51bWJlcik6IG51bWJlciB8IHVuZGVmaW5lZCB7XG4gIHJldHVybiB4LmNvZGVQb2ludEF0KGF0KTtcbn1cbi8vI2VuZHJlZ2lvblxuXG5cblxuXG4vLyNyZWdpb24gQ09NUEFSRVxuLyoqXG4gKiBDb21wYXJlIHR3byBzdHJpbmdzIGluIHRoZSBjdXJyZW50IG9yIGdpdmVuIGxvY2FsZS5cbiAqIEBwYXJhbSB4IGEgc3RyaW5nXG4gKiBAcGFyYW0geSBhbm90aGVyIHN0cmluZ1xuICogQHBhcmFtIGxvY2FsZXMgbGFuZ3VhZ2Ugb3IgbG9jYWxlIHRhZyhzKVxuICogQHBhcmFtIG9wdGlvbnMgY29tcGFyaXNvbiBvcHRpb25zXG4gKiBAcmV0dXJucyB4PHk6IC12ZSwgeD15OiAwLCB4Pnk6ICt2ZVxuICogQGV4YW1wbGVcbiAqIGBgYGphdmFzY3JpcHRcbiAqIHhzdHJpbmcubG9jYWxlQ29tcGFyZSgnYWJyYScsICdidWxiYXNhdXInKTtcbiAqIC8vIOKGkiAtMVxuICpcbiAqIHhzdHJpbmcubG9jYWxlQ29tcGFyZSgnYnVsYmFzYXVyJywgJ2J1bGJhc2F1cicpO1xuICogLy8g4oaSIDBcbiAqXG4gKiB4c3RyaW5nLmxvY2FsZUNvbXBhcmUoJ2NoYXJtZWxlb24nLCAnYnVsYmFzYXVyJyk7XG4gKiAvLyDihpIgMVxuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBsb2NhbGVDb21wYXJlKHg6IHN0cmluZywgeTogc3RyaW5nLCBsb2NhbGVzPzogc3RyaW5nIHwgc3RyaW5nW10sIG9wdGlvbnM/OiBJbnRsLkNvbGxhdG9yT3B0aW9ucyk6IG51bWJlciB7XG4gIHJldHVybiB4LmxvY2FsZUNvbXBhcmUoeSwgbG9jYWxlcywgb3B0aW9ucyk7XG59XG4vLyNlbmRyZWdpb25cblxuXG5cblxuLy8jcmVnaW9uIFNFQVJDSFxuLyoqXG4gKiBDaGVjayBpZiBzdHJpbmcgaGFzIGEgZ2l2ZW4gaW5maXguXG4gKiBAcGFyYW0geCBhIHN0cmluZ1xuICogQHBhcmFtIGluZml4IGluZml4IHRvIGxvb2sgZm9yXG4gKiBAcGFyYW0gc3RhcnQgc3RhcnQgaW5kZXggWzBdXG4gKiBAcmV0dXJucyBoYXMgaW5maXg/XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpbmNsdWRlcyh4OiBzdHJpbmcsIGluZml4OiBzdHJpbmcsIHN0YXJ0PzogbnVtYmVyKTogYm9vbGVhbiB7XG4gIHJldHVybiB4LmluY2x1ZGVzKGluZml4LCBzdGFydCk7XG59XG5cblxuLyoqXG4gKiBDaGVjayBpZiBzdHJpbmcgaGFzIGEgZ2l2ZW4gcHJlZml4LlxuICogQHBhcmFtIHggYSBzdHJpbmdcbiAqIEBwYXJhbSBwcmVmaXggcHJlZml4IHRvIGxvb2sgZm9yXG4gKiBAcGFyYW0gc3RhcnQgc3RhcnQgaW5kZXggWzBdXG4gKiBAcmV0dXJucyBoYXMgcHJlZml4P1xuICovXG5leHBvcnQgZnVuY3Rpb24gc3RhcnRzV2l0aCh4OiBzdHJpbmcsIHByZWZpeDogc3RyaW5nLCBzdGFydD86IG51bWJlcik6IGJvb2xlYW4ge1xuICByZXR1cm4geC5zdGFydHNXaXRoKHByZWZpeCwgc3RhcnQpO1xufVxuXG5cbi8qKlxuICogQ2hlY2sgaWYgc3RyaW5nIGhhcyBhIGdpdmVuIHN1ZmZpeC5cbiAqIEBwYXJhbSB4IGEgc3RyaW5nXG4gKiBAcGFyYW0gc3VmZml4IHN1ZmZpeCB0byBsb29rIGZvclxuICogQHBhcmFtIGVuZCBlbmQgaW5kZXggW2VuZF1cbiAqIEByZXR1cm5zIGhhcyBzdWZmaXg/XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBlbmRzV2l0aCh4OiBzdHJpbmcsIHN1ZmZpeDogc3RyaW5nLCBlbmQ/OiBudW1iZXIpOiBib29sZWFuIHtcbiAgcmV0dXJuIHguZW5kc1dpdGgoc3VmZml4LCBlbmQpO1xufVxuXG5cbi8qKlxuICogR2V0IGZpcnN0IGluZGV4IG9mIGEgZ2l2ZW4gaW5maXggaW4gc3RyaW5nLlxuICogQHBhcmFtIHggYSBzdHJpbmdcbiAqIEBwYXJhbSBpbmZpeCBpbmZpeCB0byBsb29rIGZvclxuICogQHBhcmFtIHN0YXJ0IHN0YXJ0IGluZGV4IFswXVxuICogQHJldHVybnMgZmlyc3QgaW5kZXggb2YgaW5maXhcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGluZGV4T2YoeDogc3RyaW5nLCBpbmZpeDogc3RyaW5nLCBzdGFydD86IG51bWJlcik6IG51bWJlciB7XG4gIHJldHVybiB4LmluZGV4T2YoaW5maXgsIHN0YXJ0KTtcbn1cblxuXG4vKipcbiAqIEdldCBsYXN0IGluZGV4IG9mIGEgZ2l2ZW4gaW5maXggaW4gc3RyaW5nLlxuICogQHBhcmFtIHggYSBzdHJpbmdcbiAqIEBwYXJhbSBpbmZpeCBpbmZpeCB0byBsb29rIGZvclxuICogQHBhcmFtIHJzdGFydCByZXZlcnNlIHN0YXJ0IGluZGV4IFtlbmQtMV1cbiAqIEByZXR1cm5zIGxhc3QgaW5kZXggb2YgaW5maXhcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGxhc3RJbmRleE9mKHg6IHN0cmluZywgaW5maXg6IHN0cmluZywgcnN0YXJ0PzogbnVtYmVyKTogbnVtYmVyIHtcbiAgcmV0dXJuIHgubGFzdEluZGV4T2YoaW5maXgsIHJzdGFydCk7XG59XG5cblxuLyoqXG4gKiBHZXQgZmlyc3QgaW5kZXggb2YgcmVndWxhciBleHByZXNzaW9uIG1hdGNoIGluIHN0cmluZy5cbiAqIEBwYXJhbSB4IGEgc3RyaW5nXG4gKiBAcGFyYW0gcmVnZXhwIHJlZ3VsYXIgZXhwcmVzc2lvblxuICogQHJldHVybnMgZmlyc3QgaW5kZXggb2YgbWF0Y2hcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNlYXJjaCh4OiBzdHJpbmcsIHJlZ2V4cDogc3RyaW5nIHwgUmVnRXhwKTogbnVtYmVyIHtcbiAgcmV0dXJuIHguc2VhcmNoKHJlZ2V4cCk7XG59XG5cblxuLyoqXG4gKiBHZXQgcmVzdWx0cyBvZiBtYXRjaGluZyBzdHJpbmcgd2l0aCByZWd1bGFyIGV4cHJlc3Npb24uXG4gKiBAcGFyYW0geCBhIHN0cmluZ1xuICogQHBhcmFtIHJlZ2V4cCByZWd1bGFyIGV4cHJlc3Npb25cbiAqIEByZXR1cm5zIC9nOiBhbGwgbWF0Y2hlcywgZWxzZTogbWF0Y2ggd2l0aCBjYXB0dXJpbmcgZ3JvdXBzIG9yIG51bGxcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1hdGNoKHg6IHN0cmluZywgcmVnZXhwOiBzdHJpbmcgfCBSZWdFeHApOiBSZWdFeHBNYXRjaEFycmF5IHwgbnVsbCB7XG4gIHJldHVybiB4Lm1hdGNoKHJlZ2V4cCk7XG59XG5cblxuLyoqXG4gKiBHZXQgZGV0YWlsZWQgcmVzdWx0cyBvZiBtYXRjaGluZyBzdHJpbmcgd2l0aCByZWd1bGFyIGV4cHJlc3Npb24uXG4gKiBAcGFyYW0geCBhIHN0cmluZ1xuICogQHBhcmFtIHJlZ2V4cCByZWd1bGFyIGV4cHJlc3Npb24gKHdpdGggL2cpXG4gKiBAcmV0dXJucyBtYXRjaCB3aXRoIGNhcHR1cmluZyBncm91cHMgLi4uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBtYXRjaEFsbCh4OiBzdHJpbmcsIHJlZ2V4cDogUmVnRXhwKTogSXRlcmFibGVJdGVyYXRvcjxSZWdFeHBNYXRjaEFycmF5PiB7XG4gIHJldHVybiB4Lm1hdGNoQWxsKHJlZ2V4cCk7XG59XG4vLyNlbmRyZWdpb25cblxuXG5cblxuLy8jcmVnaW9uIENPTlZFUlRcbi8qKlxuICogR2V0IHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiBzdHJpbmcuXG4gKiBAcGFyYW0geCBhIHN0cmluZ1xuICogQHJldHVybnMgc3RyaW5nIHJlcHJlc2VudGF0aW9uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0b1N0cmluZyh4OiBzdHJpbmcpOiBzdHJpbmcge1xuICByZXR1cm4geC50b1N0cmluZygpO1xufVxuLy8jZW5kcmVnaW9uXG5cblxuXG5cbi8vI3JlZ2lvbiBQQVJUXG4vKipcbiAqIEV4dHJhY3Qgc2VjdGlvbiBvZiBzdHJpbmcuXG4gKiBAcGFyYW0geCBhIHN0cmluZ1xuICogQHBhcmFtIHN0YXJ0IHN0YXJ0IGluZGV4ICgtdmUg4oeSIGZyb20gcmlnaHQpIFswXVxuICogQHBhcmFtIGVuZCBlbmQgaW5kZXggKC12ZSDih5IgZnJvbSByaWdodCkgW2VuZF1cbiAqIEByZXR1cm5zIHNlY3Rpb24gb2Ygc3RyaW5nXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzbGljZSh4OiBzdHJpbmcsIHN0YXJ0PzogbnVtYmVyLCBlbmQ/OiBudW1iZXIpOiBzdHJpbmcge1xuICByZXR1cm4geC5zbGljZShzdGFydCwgZW5kKTtcbn1cblxuXG4vKipcbiAqIEV4dHJhY3Qgc2VjdGlvbiBvZiBzdHJpbmcuXG4gKiBAcGFyYW0geCBhIHN0cmluZ1xuICogQHBhcmFtIHN0YXJ0IHN0YXJ0IGluZGV4ICgtdmUg4oeSIDApIFswXVxuICogQHBhcmFtIGVuZCBlbmQgaW5kZXggKC12ZSDih5IgMCkgW2VuZF1cbiAqIEByZXR1cm5zIHNlY3Rpb24gb2Ygc3RyaW5nXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzdWJzdHJpbmcoeDogc3RyaW5nLCBzdGFydDogbnVtYmVyLCBlbmQ/OiBudW1iZXIpOiBzdHJpbmcge1xuICByZXR1cm4geC5zdWJzdHJpbmcoc3RhcnQsIGVuZCk7XG59XG5cblxuLyoqXG4gKiBTcGxpdCBzdHJpbmcgYnkgYSBnaXZlbiBzZXBhcmF0b3IgaW50byBzdWJzdHJpbmdzLlxuICogQHBhcmFtIHggYSBzdHJpbmdcbiAqIEBwYXJhbSBzZXBhcmF0b3Igc2VwYXJhdG9yIHN0cmluZyBvciByZWd1bGFyIGV4cHJlc3Npb25cbiAqIEBwYXJhbSBsaW1pdCBtYXhpbXVtIG51bWJlciBvZiBzdWJzdHJpbmdzXG4gKiBAcmV0dXJucyBzdWJzdHJpbmdzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzcGxpdCh4OiBzdHJpbmcsIHNlcGFyYXRvcj86IHN0cmluZyB8IFJlZ0V4cCwgbGltaXQ/OiBudW1iZXIpOiBzdHJpbmdbXSB7XG4gIHJldHVybiB4LnNwbGl0KHNlcGFyYXRvciBhcyBzdHJpbmcgfCBSZWdFeHAsIGxpbWl0KTtcbn1cbi8vIHNwbGl0QnkoeDogc3RyaW5nLCBzZXBhcmF0b3I6IGZ1bmN0aW9uLCBsaW1pdD86IG51bWJlcik6IHN0cmluZ1tdP1xuLy8jZW5kcmVnaW9uXG5cblxuXG5cbi8vI3JlZ2lvbiBXSElURVNQQUNFXG4vKipcbiAqIFJlbW92ZSB3aGl0ZXNwYWNlIGZyb20gYmVnaW5pbmcgb2Ygc3RyaW5nLlxuICogQHBhcmFtIHggYSBzdHJpbmdcbiAqIEByZXR1cm5zIHRyaW1tZWQgc3RyaW5nXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0cmltU3RhcnQoeDogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIHgudHJpbVN0YXJ0KCk7XG59XG5cblxuLyoqXG4gKiBSZW1vdmUgd2hpdGVzcGFjZSBmcm9tIGVuZCBvZiBzdHJpbmcuXG4gKiBAcGFyYW0geCBhIHN0cmluZ1xuICogQHJldHVybnMgdHJpbW1lZCBzdHJpbmdcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRyaW1FbmQoeDogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIHgudHJpbUVuZCgpO1xufVxuXG5cbi8qKlxuICogUmVtb3ZlIHdoaXRlc3BhY2UgZnJvbSBiZWdpbmluZyBhbmQgZW5kIG9mIHN0cmluZy5cbiAqIEBwYXJhbSB4IGEgc3RyaW5nXG4gKiBAcmV0dXJucyB0cmltbWVkIHN0cmluZ1xuICovXG5leHBvcnQgZnVuY3Rpb24gdHJpbSh4OiBzdHJpbmcpOiBzdHJpbmcge1xuICByZXR1cm4geC50cmltKCk7XG59XG5cblxuLyoqXG4gKiBQYWQgc3RhcnQgb2Ygc3RyaW5nIHRvIGZpdCBhIGRlc2lyZWQgbGVuZ3RoLlxuICogQHBhcmFtIHggYSBzdHJpbmdcbiAqIEBwYXJhbSBsZW5ndGggZGVzaXJlZCBsZW5ndGhcbiAqIEBwYXJhbSBwYWRkaW5nIHBhZCB3aXRoIFsgXVxuICogQHJldHVybnMgcGFkZGVkIHN0cmluZ1xuICovXG5leHBvcnQgZnVuY3Rpb24gcGFkU3RhcnQoeDogc3RyaW5nLCBsZW5ndGg6IG51bWJlciwgcGFkZGluZzogc3RyaW5nPVwiIFwiKTogc3RyaW5nIHtcbiAgcmV0dXJuIHgucGFkU3RhcnQobGVuZ3RoLCBwYWRkaW5nKTtcbn1cblxuXG4vKipcbiAqIFBhZCBlbmQgb2Ygc3RyaW5nIHRvIGZpdCBhIGRlc2lyZWQgbGVuZ3RoLlxuICogQHBhcmFtIHggYSBzdHJpbmdcbiAqIEBwYXJhbSBsZW5ndGggZGVzaXJlZCBsZW5ndGhcbiAqIEBwYXJhbSBwYWRkaW5nIHBhZCB3aXRoIFsgXVxuICogQHJldHVybnMgcGFkZGVkIHN0cmluZ1xuICovXG4gZXhwb3J0IGZ1bmN0aW9uIHBhZEVuZCh4OiBzdHJpbmcsIGxlbmd0aDogbnVtYmVyLCBwYWRkaW5nOiBzdHJpbmc9XCIgXCIpOiBzdHJpbmcge1xuICByZXR1cm4geC5wYWRFbmQobGVuZ3RoLCBwYWRkaW5nKTtcbn1cbi8vI2VuZHJlZ2lvblxuXG5cblxuXG4vLyNyZWdpb24gVFJBTlNGT1JNIChDQVNFKVxuLyoqXG4gKiBDb252ZXJ0IHN0cmluZyB0byB1cHBlciBjYXNlLlxuICogQHBhcmFtIHggYSBzdHJpbmdcbiAqIEByZXR1cm5zIHVwcGVyIGNhc2VkIHN0cmluZ1xuICovXG5leHBvcnQgZnVuY3Rpb24gdG9VcHBlckNhc2UoeDogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIHgudG9VcHBlckNhc2UoKTtcbn1cblxuXG4vKipcbiAqIENvbnZlcnQgc3RyaW5nIHRvIHVwcGVyIGNhc2UsIGFzIHBlciBsb2NhbGUtc3BlY2lmaWMgY2FzZSBtYXBwaW5ncy5cbiAqIEBwYXJhbSB4IGEgc3RyaW5nXG4gKiBAcGFyYW0gbG9jYWxlcyBCQ1AgNDcgbGFuZ3VhZ2UgdGFnKHMpXG4gKiBAcmV0dXJucyB1cHBlciBjYXNlZCBzdHJpbmdcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRvTG9jYWxlVXBwZXJDYXNlKHg6IHN0cmluZywgbG9jYWxlcz86IHN0cmluZyB8IHN0cmluZ1tdKTogc3RyaW5nIHtcbiAgcmV0dXJuIHgudG9Mb2NhbGVVcHBlckNhc2UobG9jYWxlcyk7XG59XG5cblxuLyoqXG4gKiBDb252ZXJ0IHN0cmluZyB0byBsb3dlciBjYXNlLlxuICogQHBhcmFtIHggYSBzdHJpbmdcbiAqIEByZXR1cm5zIGxvd2VyIGNhc2VkIHN0cmluZ1xuICovXG5leHBvcnQgZnVuY3Rpb24gdG9Mb3dlckNhc2UoeDogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIHgudG9Mb3dlckNhc2UoKTtcbn1cblxuXG4vKipcbiAqIENvbnZlcnQgc3RyaW5nIHRvIGxvd2VyIGNhc2UsIGFzIHBlciBsb2NhbGUtc3BlY2lmaWMgY2FzZSBtYXBwaW5ncy5cbiAqIEBwYXJhbSB4IGEgc3RyaW5nXG4gKiBAcGFyYW0gbG9jYWxlcyBCQ1AgNDcgbGFuZ3VhZ2UgdGFnKHMpXG4gKiBAcmV0dXJucyBsb3dlciBjYXNlZCBzdHJpbmdcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRvTG9jYWxlTG93ZXJDYXNlKHg6IHN0cmluZywgbG9jYWxlcz86IHN0cmluZyB8IHN0cmluZ1tdKTogc3RyaW5nIHtcbiAgcmV0dXJuIHgudG9Mb2NhbGVMb3dlckNhc2UobG9jYWxlcyk7XG59XG4vLyNlbmRyZWdpb25cblxuXG5cblxuLy8jcmVnaW9uIFRSQU5TRk9STVxuLyoqIEhhbmRsZSByZXBsYWNlbWVudCBvZiBtYXRjaGVkIHN0cmluZyBhbmQgcGFyYW1ldGVycyB3aXRoIGFub3RoZXIgc3RyaW5nLiAqL1xuZXhwb3J0IHR5cGUgUmVwbGFjZUZ1bmN0aW9uID0gKHN1YnN0cmluZzogc3RyaW5nLCAuLi5hcmdzOiB1bmtub3duW10pID0+IHN0cmluZztcblxuLyoqXG4gKiBSZXBsYWNlIGZpcnN0IG1hdGNoIG9mIGdpdmVuIHBhdHRlcm4gYnkgcmVwbGFjZW1lbnQuXG4gKiBAcGFyYW0geCBhIHN0cmluZ1xuICogQHBhcmFtIHBhdHRlcm4gc3Vic3RyaW5nIHRvIG1hdGNoXG4gKiBAcGFyYW0gcmVwbGFjZW1lbnQgcmVwbGFjZW1lbnQgc3Vic3RyaW5nXG4gKiBAcmV0dXJucyByZXBsYWNlZCBzdHJpbmdcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlcGxhY2UoeDogc3RyaW5nLCBwYXR0ZXJuOiBzdHJpbmcsIHJlcGxhY2VtZW50OiBzdHJpbmcpOiBzdHJpbmc7XG5cbi8qKlxuICogUmVwbGFjZSBmaXJzdCBvciBhbGwgbWF0Y2hlcyBvZiBnaXZlbiBwYXR0ZXJuIGJ5IHJlcGxhY2VtZW50LlxuICogQHBhcmFtIHggYSBzdHJpbmdcbiAqIEBwYXJhbSBwYXR0ZXJuIHBhdHRlcm4gdG8gbWF0Y2hcbiAqIEBwYXJhbSByZXBsYWNlbWVudCByZXBsYWNlbWVudCBzdWJzdHJpbmcgb3IgcmVwbGFjZXJcbiAqIEByZXR1cm5zIHJlcGxhY2VkIHN0cmluZ1xuICovXG5leHBvcnQgZnVuY3Rpb24gcmVwbGFjZSh4OiBzdHJpbmcsIHBhdHRlcm46IHN0cmluZyB8IFJlZ0V4cCwgcmVwbGFjZW1lbnQ6IHN0cmluZyB8IFJlcGxhY2VGdW5jdGlvbik6IHN0cmluZztcblxuZXhwb3J0IGZ1bmN0aW9uIHJlcGxhY2UoeDogc3RyaW5nLCBwYXR0ZXJuOiBzdHJpbmcgfCBSZWdFeHAsIHJlcGxhY2VtZW50OiBzdHJpbmcgfCBSZXBsYWNlRnVuY3Rpb24pOiBzdHJpbmcge1xuICByZXR1cm4geC5yZXBsYWNlKHBhdHRlcm4sIHJlcGxhY2VtZW50IGFzIHN0cmluZyk7XG59XG5cblxuLy8gZXhwb3J0IGZ1bmN0aW9uIHJlcGxhY2VBbGwoeDogc3RyaW5nLCBvcmc6IHN0cmluZywgdG86IHN0cmluZyk6IHN0cmluZyB7XG4vLyAgIHJldHVybiB4LnJlcGxhY2VBbGwob3JnLCB0byk7XG4vLyB9XG5cblxuLyoqXG4gKiBOb3JtYWxpemUgc3RyaW5nIGJ5IGdpdmVuIGZvcm0sIGFzIHBlciBVbmljb2RlIFN0YW5kYXJkIEFubmV4ICMxNS5cbiAqIEBwYXJhbSB4IGEgc3RyaW5nXG4gKiBAcGFyYW0gZm9ybSBub3JtYWxpemF0aW9uIGZvcm0gKE5GQywgTkZELCBORktDLCBORktEKVxuICogQHJldHVybnMgbm9ybWFsaXplZCBzdHJpbmdcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG5vcm1hbGl6ZSh4OiBzdHJpbmcsIGZvcm0/OiBzdHJpbmcpOiBzdHJpbmcge1xuICByZXR1cm4geC5ub3JtYWxpemUoZm9ybSk7XG59XG4vLyNlbmRyZWdpb25cbi8vI2VuZHJlZ2lvblxuXG5cblxuXG4vLyNyZWdpb24gQlVJTFQtSU4gKEFSUkFZKVxuLy8jcmVnaW9uIEdFTkVSQVRFXG4vKipcbiAqIENyZWF0ZSBzdHJpbmcgZnJvbSBhcmd1bWVudHMsIGxpa2UgYEFycmF5Lm9mKClgLlxuICogQHBhcmFtIGFyZ3MgYXJndW1lbnRzXG4gKiBAcmV0dXJucyBwICsgcSArIC4uLiB8IFtwLCBxLCAuLi5dID0gYXJnc1xuICogQGV4YW1wbGVcbiAqIGBgYGphdmFzY3JpcHRcbiAqIHhzdHJpbmcub2YoJ2EnLCAxKTtcbiAqIC8vIOKGkiAnYTEnXG4gKlxuICogeHN0cmluZy5vZigxLCAyKTtcbiAqIC8vIOKGkiAnMTInXG4gKlxuICogeHN0cmluZy5vZigpO1xuICogLy8g4oaSICcnXG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG9mKC4uLmFyZ3M6IHN0cmluZ1tdKTogc3RyaW5nIHtcbiAgbGV0IGEgPSBcIlwiO1xuICBmb3IgKGxldCBpPTAsIEk9YXJncy5sZW5ndGg7IGk8STsgaSsrKVxuICAgIGEgKz0gYXJnc1tpXTtcbiAgcmV0dXJuIGE7XG59XG5cblxuLyoqXG4gKiBIYW5kbGUgdHJhbnNmb3JtYXRpb24gb2YgYSBzdWJzdHJpbmcgKG9yIGNoYXJhY3RlcikgdG8gYW5vdGhlci5cbiAqIEBwYXJhbSB2IGEgc3Vic3RyaW5nIChvciBjaGFyYWN0ZXIpXG4gKiBAcGFyYW0gaSBpbmRleCBvZiBzdWJzdHJpbmdcbiAqIEBwYXJhbSB4IHN0cmluZyBjb250YWluaW5nIHRoZSBzdWJzdHJpbmdcbiAqIEByZXR1cm5zIHRyYW5zZm9ybWVkIHN1YnN0cmluZ1xuICovXG5leHBvcnQgdHlwZSBNYXBGdW5jdGlvbiA9ICh2OiBzdHJpbmcsIGk6IG51bWJlciwgeD86IHN0cmluZykgPT4gc3RyaW5nO1xuXG4vKipcbiAqIENyZWF0ZSBzdHJpbmcgZnJvbSBpdGVyYWJsZSwgbGlrZSBgQXJyYXkuZnJvbSgpYC5cbiAqIEBwYXJhbSB4cyBsaXN0IG9mIHN0cmluZ3MgKGl0ZXJhYmxlKVxuICogQHBhcmFtIGZtIG1hcCBmdW5jdGlvbiAoeCwgaSlcbiAqIEBwYXJhbSB0aHMgdGhpcyBhcmd1bWVudFxuICogQHJldHVybnMgcCArIHEgKyAuLi4gfCBbcCwgcSwgLi4uXSA9IHhzXG4gKiBAZXhhbXBsZVxuICogYGBgamF2YXNjcmlwdFxuICogeHN0cmluZy5mcm9tKFsnYScsICdiJ10pO1xuICogLy8g4oaSICdhYidcbiAqXG4gKiB4c3RyaW5nLmZyb20oJ2FiYycsICh2KSA9PiBTdHJpbmcuZnJvbUNoYXJDb2RlKHYuY2hhckNvZGVBdCgpKzEpKTtcbiAqIC8vIOKGkiAnYmNkJ1xuICpcbiAqIHhzdHJpbmcuZnJvbShuZXcgU2V0KCkuYWRkKCdhJykuYWRkKCdiJykpO1xuICogLy8g4oaSICdhYidcbiAqXG4gKiB4c3RyaW5nLmZyb20obmV3IE1hcCgpLnNldCgnYScsIDEpLnNldCgnYicsIDIpKTtcbiAqIC8vIOKGkiAnYSwxYiwyJ1xuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmcm9tKHhzOiBJdGVyYWJsZTxzdHJpbmc+LCBmbT86IE1hcEZ1bmN0aW9uLCB0aHM/OiB1bmtub3duKTogc3RyaW5nIHtcbiAgbGV0IGEgPSBcIlwiLCBpID0gMDtcbiAgZm9yIChjb25zdCB4IG9mIHhzKSB7XG4gICAgYSArPSBmbT8gZm0uY2FsbCh0aHMsIHgsIGkpIDogeDtcbiAgICBpKys7XG4gIH1cbiAgcmV0dXJuIGE7XG59XG4vLyNlbmRyZWdpb25cblxuXG5cblxuLy8jcmVnaW9uIEFCT1VUXG4vKipcbiAqIEdldCBrZXlzIG9mIHN0cmluZywgbGlrZSBgQXJyYXkua2V5cygpYC5cbiAqIEBwYXJhbSB4IGEgc3RyaW5nXG4gKiBAcmV0dXJucyAwLCAxLCAuLi5cbiAqIEBleGFtcGxlXG4gKiBgYGBqYXZhc2NyaXB0XG4gKiB4c3RyaW5nLmtleXMoJ2FzaCcpO1xuICogLy8g4oaSIFswLCAxLCAyXVxuICpcbiAqIHhzdHJpbmcua2V5cygnJyk7XG4gKiAvLyDihpIgW11cbiAqIGBgYFxuICovXG5mdW5jdGlvbiogX2tleXMoeDogc3RyaW5nKTogSXRlcmFibGVJdGVyYXRvcjxudW1iZXI+IHtcbiAgbGV0IGkgPSAwO1xuICBmb3IgKGNvbnN0IF9jIG9mIHgpXG4gICAgeWllbGQgaSsrO1xufVxuXG5cbi8qKlxuICogR2V0IGNoYXJhY3RlcnMgb2Ygc3RyaW5nLCBsaWtlIGBBcnJheS52YWx1ZXMoKWAuXG4gKiBAcGFyYW0geCBhIHN0cmluZ1xuICogQHJldHVybnMgeFswXSwgeFsxXSwgLi4uXG4gKi9cbmZ1bmN0aW9uKiBfdmFsdWVzKHg6IHN0cmluZyk6IEl0ZXJhYmxlSXRlcmF0b3I8c3RyaW5nPiB7XG4gIGZvciAoY29uc3QgYyBvZiB4KVxuICAgIHlpZWxkIGM7XG59XG4vLyBleHBvcnQge3ZhbHVlcyBhcyBjaGFyYWN0ZXJzfTtcblxuXG4vKipcbiAqIEdldCBlbnRyaWVzIG9mIHN0cmluZywgbGlrZSBgQXJyYXkuZW50cmllcygpYC5cbiAqIEBwYXJhbSB4IGEgc3RyaW5nXG4gKiBAcmV0dXJucyBbMCwgeFswXV0sIFsxLCB4WzFdXSwgLi4uXG4gKiBAZXhhbXBsZVxuICogYGBgamF2YXNjcmlwdFxuICogeHN0cmluZy5lbnRyaWVzKCdzaGlwJyk7XG4gKiAvLyDihpIgW1swLCAncyddLCBbMSwgJ2gnXSwgWzIsICdpJ10sIFszLCAncCddXVxuICpcbiAqIHhzdHJpbmcuZW50cmllcygnJyk7XG4gKiAvLyDihpIgW11cbiAqIGBgYFxuICovXG5mdW5jdGlvbiogX2VudHJpZXMoeDogc3RyaW5nKTogSXRlcmFibGVJdGVyYXRvcjxbbnVtYmVyLCBzdHJpbmddPiB7XG4gIGxldCBpID0gMDtcbiAgZm9yIChjb25zdCBjIG9mIHgpXG4gICAgeWllbGQgW2krKywgY107XG59XG4vLyNlbmRyZWdpb25cblxuXG5cblxuLy8jcmVnaW9uIFRSQU5TRk9STVxuLyoqXG4gKiBSZW1vdmUvcmVwbGFjZSBjaGFyYWN0ZXJzIGluIGEgc3RyaW5nLlxuICogQHBhcmFtIHggYSBzdHJpbmdcbiAqIEBwYXJhbSBzdGFydCBzdGFydCBpbmRleFxuICogQHBhcmFtIHJlbW92ZSBudW1iZXIgb2YgY2hhcmFjdGVycyB0byByZW1vdmVcbiAqIEBwYXJhbSBhZGQgc3Vic3RyaW5nIHRvIGFkZFxuICogQHJldHVybnMgeFswOmldICsgYWRkICsgeFtpK3JdIHwgaSA9IHN0YXJ0LCByID0gcmVtb3ZlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzcGxpY2UoeDogc3RyaW5nLCBzdGFydDogbnVtYmVyLCByZW1vdmU6IG51bWJlcj0wLCBhZGQ6IHN0cmluZz1cIlwiKTogc3RyaW5nIHtcbiAgcmV0dXJuIHguc2xpY2UoMCwgc3RhcnQpICsgYWRkICsgeC5zbGljZShzdGFydCtyZW1vdmUpO1xufVxuXG5cbi8qKlxuICogUmV2ZXJzZSBhIHN0cmluZy5cbiAqIEBwYXJhbSB4IGEgc3RyaW5nXG4gKiBAcmV0dXJucyByZXZlcnNlZCBzdHJpbmdcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJldmVyc2UoeDogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIFsuLi54XS5yZXZlcnNlKCkuam9pbihcIlwiKTtcbn1cbi8vIC0gaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9hLzk1OTAwNC8xNDEzMjU5XG4vLyAtIGh0dHBzOi8vZ2l0aHViLmNvbS9tYXRoaWFzYnluZW5zL2VzcmV2ZXJcblxuXG4vKipcbiAqIEhhbmRsZSBjb21wYXJpc29uIG9mIHR3byBzdHJpbmdzLlxuICogQHBhcmFtIGEgYSBzdHJpbmdcbiAqIEBwYXJhbSBiIGFub3RoZXIgc3RyaW5nXG4gKiBAcmV0dXJucyB4PHk6IC12ZSwgeD15OiAwLCB4Pnk6ICt2ZVxuICovXG5leHBvcnQgdHlwZSBDb21wYXJlRnVuY3Rpb24gPSAoYTogc3RyaW5nLCBiOiBzdHJpbmcpID0+IG51bWJlcjtcblxuLyoqXG4gKiBBcnJhbmdlIGNoYXJhY3RlcnMgaW4gYW4gb3JkZXIuXG4gKiBAcGFyYW0geCBhIHN0cmluZ1xuICogQHBhcmFtIGZjIGNvbXBhcmUgZnVuY3Rpb24gKGEsIGIpXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzb3J0KHg6IHN0cmluZywgZmM/OiBDb21wYXJlRnVuY3Rpb24pOiBzdHJpbmcge1xuICByZXR1cm4gWy4uLnhdLnNvcnQoZmMpLmpvaW4oXCJcIik7XG59XG4vLyNlbmRyZWdpb25cblxuXG5cblxuLy8jcmVnaW9uIEZVTkNUSU9OQUxcbi8qKlxuICogSGFuZGxlIHNlbGVjdGlvbiBvZiBhIHN1YnN0cmluZyAob3IgY2hhcmFjdGVyKSBpbiBzdHJpbmcuXG4gKiBAcGFyYW0gdiBhIHN1YnN0cmluZyAob3IgY2hhcmFjdGVyKVxuICogQHBhcmFtIGkgaW5kZXggb2Ygc3Vic3RyaW5nIGluIHN0cmluZ1xuICogQHBhcmFtIHggc3RyaW5nIGNvbnRhaW5pbmcgdGhlIHN1YnN0cmluZ1xuICogQHJldHVybnMgd2hldGhlciBpdCBpcyBzZWxlY3RlZFxuICovXG5leHBvcnQgdHlwZSBUZXN0RnVuY3Rpb24gPSAodjogc3RyaW5nLCBpOiBudW1iZXIsIHg6IHN0cmluZykgPT4gYm9vbGVhbjtcblxuLyoqXG4gKiBGaWx0ZXIgY2hhcmFjdGVycyB3aGljaCBwYXNzIGEgdGVzdC5cbiAqIEBwYXJhbSB4IGEgc3RyaW5nXG4gKiBAcGFyYW0gZnQgdGVzdCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEBwYXJhbSB0aHMgdGhpcyBhcmd1bWVudFxuICogQHJldHVybnMgY2hhcmFjdGVycyB3aGljaCBwYXNzIHRoZSB0ZXN0XG4gKiBAZXhhbXBsZVxuICogYGBgamF2YXNjcmlwdFxuICogeHN0cmluZy5maWx0ZXIoJ2cwMGRmMDBkJywgKHYpID0+IHY8PSdmJyk7XG4gKiAvLyDihpIgJzAwZGYwMGQnXG4gKlxuICogeHN0cmluZy5maWx0ZXIoJ2JhZGZvb2QnLCAodikgPT4gdjw9J2YnKTtcbiAqIC8vIOKGkiAnYmFkZmQnXG4gKlxuICogeHN0cmluZy5maWx0ZXIoJycsICh2KSA9PiB2PD0nZicpO1xuICogLy8g4oaSICcnXG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGZpbHRlcih4OiBzdHJpbmcsIGZ0OiBUZXN0RnVuY3Rpb24sIHRocz86IHVua25vd24pOiBzdHJpbmcge1xuICBsZXQgYSA9IFwiXCIsIGkgPSAwO1xuICBmb3IgKGNvbnN0IGMgb2YgeClcbiAgICBpZiAoZnQuY2FsbCh0aHMsIGMsIGkrKywgeCkpIGEgKz0gYztcbiAgcmV0dXJuIGE7XG59XG4vLyNlbmRyZWdpb25cbi8vI2VuZHJlZ2lvblxuXG5cblxuXG4vLyNyZWdpb24gQ1VTVE9NXG4vLyNyZWdpb24gR0VORVJBVEVcbi8qKiBBIGJ1ZmZlciBjb250YWluaW5nIG9ubHkgc3BhY2VzLCBmb3IgYHNwYWNlcygpYC4gKi9cbmNvbnN0IFNQQUNFX0JVRkZFUjogc3RyaW5nID0gXCIgXCIucmVwZWF0KDEwMjQpO1xuXG4vKipcbiAqIEdldCBhIHN0cmluZyBvZiBzcGFjZXMuXG4gKiBAcGFyYW0gbiBudW1iZXIgb2Ygc3BhY2VzXG4gKiBAcmV0dXJucyBzdHJpbmcgb2Ygc3BhY2VzXG4gKiBAZXhhbXBsZVxuICogYGBgamF2YXNjcmlwdFxuICogeHN0cmluZy5zcGFjZXMoNCk7XG4gKiAvLyDihpIgJyAgICAnXG4gKlxuICogeHN0cmluZy5zcGFjZXMoNik7XG4gKiAvLyDihpIgJyAgICAgICdcbiAqXG4gKiB4c3RyaW5nLnNwYWNlcygwKTtcbiAqIC8vIOKGkiAnJ1xuICpcbiAqIHhzdHJpbmcuc3BhY2VzKC0xKTtcbiAqIC8vIOKGkiAnJ1xuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzcGFjZXMobjogbnVtYmVyKTogc3RyaW5nIHtcbiAgY29uc3QgUyA9IFNQQUNFX0JVRkZFUi5sZW5ndGg7XG4gIGlmIChuPFMpIHJldHVybiBTUEFDRV9CVUZGRVIuc2xpY2UoMCwgbik7XG4gIHJldHVybiBTUEFDRV9CVUZGRVIucmVwZWF0KG4vUykgKyBcIiBcIi5yZXBlYXQobiVTKTtcbn1cbi8vI2VuZHJlZ2lvblxuXG5cblxuXG4vLyNyZWdpb24gQUJPVVRcbi8qKlxuICogQ2hlY2sgaWYgdmFsdWUgaXMgYSBzdHJpbmcuXG4gKiBAcGFyYW0gdiBhIHZhbHVlXG4gKiBAcmV0dXJucyB3aGV0aGVyIHZhbHVlIGlzIGEgc3RyaW5nXG4gKiBAZXhhbXBsZVxuICogYGBgamF2YXNjcmlwdFxuICogeHN0cmluZy5pcygncGFuaW5pJyk7XG4gKiAvLyDihpIgdHJ1ZVxuICpcbiAqIHhzdHJpbmcuaXMoXCJ2YWxtaWtpXCIpO1xuICogLy8g4oaSIHRydWVcbiAqXG4gKiB4c3RyaW5nLmlzKFN0cmluZygndnlhc2EnKSk7XG4gKiAvLyDihpIgdHJ1ZVxuICpcbiAqIHhzdHJpbmcuaXMoe3NoYWtlc3BlYXJlOiAnbGl0ZXJhdHVyZSd9KTtcbiAqIC8vIOKGkiBmYWxzZVxuICpcbiAqIHhzdHJpbmcuaXMoNzE4MTEzMTM1MTgpO1xuICogLy8g4oaSIGZhbHNlICh3aGF0J3MgdGhpcz8pXG4gKlxuICogeHN0cmluZy5pcygpO1xuICogLy8g4oaSIGZhbHNlXG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzKHY6IHVua25vd24pOiBib29sZWFuIHtcbiAgcmV0dXJuIHR5cGVvZiB2PT09XCJzdHJpbmdcIjtcbn1cblxuXG4vKipcbiAqIENoZWNrIGlmIHN0cmluZyBpcyBlbXB0eS5cbiAqIEBwYXJhbSB4IGEgc3RyaW5nXG4gKiBAcmV0dXJucyB3aGV0aGVyIHN0cmluZyBpcyBlbXB0eVxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNFbXB0eSh4OiBzdHJpbmcpOiBib29sZWFuIHtcbiAgcmV0dXJuIHgubGVuZ3RoPT09MDtcbn1cblxuXG4vKipcbiAqIENoZWNrIGlmIHN0cmluZyBpcyBhIGNoYXJhY3Rlci5cbiAqIEBwYXJhbSB4IGEgc3RyaW5nXG4gKiBAcmV0dXJucyB3aGV0aGVyIHN0cmluZyBpcyBhIGNoYXJhY3RlclxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNDaGFyYWN0ZXIoeDogc3RyaW5nKTogYm9vbGVhbiB7XG4gIHJldHVybiB4Lmxlbmd0aD09PTE7XG59XG5cblxuLyoqXG4gKiBHZXQgbm9uLW5lZ2F0aXZlIGluZGV4IHdpdGhpbiBzdHJpbmcuXG4gKiBAcGFyYW0geCBhIHN0cmluZ1xuICogQHBhcmFtIGF0IGNoYXJhY3RlciBpbmRleFxuICogQHJldHVybnMgK3ZlIGluZGV4XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpbmRleCh4OiBzdHJpbmcsIGF0OiBudW1iZXIpOiBudW1iZXIge1xuICAvLyBDYW4gYmUgcmV3cml0dGVuIHdpdGggYSBtYXRoL251bWJlciBmdW5jdGlvbj9cbiAgaWYgKGF0PDApIHJldHVybiBNYXRoLm1heCgwLCB4Lmxlbmd0aCArIGF0KTtcbiAgcmV0dXJuIE1hdGgubWluKGF0LCB4Lmxlbmd0aCk7XG59XG5cblxuLyoqXG4gKiBHZXQgbm9uLW5lZ2F0aXZlIGluZGV4IHJhbmdlIHdpdGhpbiBzdHJpbmcuXG4gKiBAcGFyYW0geCBhIHN0cmluZ1xuICogQHBhcmFtIHN0YXJ0IHN0YXJ0IGluZGV4XG4gKiBAcGFyYW0gZW5kIGVuZCBpbmRleFxuICogQHJldHVybnMgK3ZlIGluZGV4IHJhbmdlIFtzdGFydCwgZW5kXVxuICovXG5leHBvcnQgZnVuY3Rpb24gaW5kZXhSYW5nZSh4OiBzdHJpbmcsIHN0YXJ0OiBudW1iZXIsIGVuZDogbnVtYmVyKTogW251bWJlciwgbnVtYmVyXSB7XG4gIC8vIENhbiBiZSByZXdyaXR0ZW4gd2l0aCBhIG1hdGgvbnVtYmVyIGZ1bmN0aW9uP1xuICBzdGFydCA9IGluZGV4KHgsIHN0YXJ0KTtcbiAgZW5kICAgPSBpbmRleCh4LCBlbmQpO1xuICByZXR1cm4gW01hdGgubWluKHN0YXJ0LCBlbmQpLCBNYXRoLm1heChzdGFydCwgZW5kKV07XG59XG5cblxuLyoqXG4gKiBHZXQgdW5pY29kZSBjb2RlIHBvaW50IHJhbmdlIG9mIHN0cmluZy5cbiAqIEBwYXJhbSB4IGEgc3RyaW5nXG4gKiBAcmV0dXJucyBjb2RlIHBvaW50IHJhbmdlIFttaW4sIG1heF1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNvZGVQb2ludFJhbmdlKHg6IHN0cmluZyk6IFtudW1iZXIsIG51bWJlcl0ge1xuICBsZXQgbWluID0gTUFYX0NPREVfUE9JTlQ7XG4gIGxldCBtYXggPSBNSU5fQ09ERV9QT0lOVDtcbiAgZm9yIChjb25zdCBjIG9mIHgpIHtcbiAgICBjb25zdCB2ID0gYy5jb2RlUG9pbnRBdCgwKSBhcyBudW1iZXI7XG4gICAgbWluID0gTWF0aC5taW4obWluLCB2KTtcbiAgICBtYXggPSBNYXRoLm1heChtYXgsIHYpO1xuICB9XG4gIHJldHVybiBbbWluLCBtYXhdO1xufVxuLy8jZW5kcmVnaW9uXG5cblxuXG5cbi8vI3JlZ2lvbiBDT01QQVJFXG4vKipcbiAqIENvbXBhcmUgdHdvIHN0cmluZ3MuXG4gKiBAcGFyYW0geCBhIHN0cmluZ1xuICogQHBhcmFtIHkgYW5vdGhlciBzdHJpbmdcbiAqIEByZXR1cm5zIHg8eTogLXZlLCB4PXk6IDAsIHg+eTogK3ZlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjb21wYXJlKHg6IHN0cmluZywgeTogc3RyaW5nKTogbnVtYmVyIHtcbiAgcmV0dXJuIHg8eT8gLTEgOiAoeD55PyAxIDogMCk7XG59XG5cblxuLyoqXG4gKiBDaGVjayBpZiB0d28gc3RyaW5ncyBhcmUgZXF1YWwuXG4gKiBAcGFyYW0geCBhIHN0cmluZ1xuICogQHBhcmFtIHkgYW5vdGhlciBzdHJpbmdcbiAqIEByZXR1cm5zIHg9eT9cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzRXF1YWwoeDogc3RyaW5nLCB5OiBzdHJpbmcpOiBib29sZWFuIHtcbiAgcmV0dXJuIHg9PT15O1xufVxuLy8jZW5kcmVnaW9uXG5cblxuXG5cbi8vI3JlZ2lvbiBTRUFSQ0hcbi8vIENoZWNrIGlmIHN0cmluZyBoYXMgYSBnaXZlbiBwcmVmaXguXG5leHBvcnQge3N0YXJ0c1dpdGggYXMgaXNQcmVmaXh9O1xuLy8gQ2hlY2sgaWYgc3RyaW5nIGhhcyBhIGdpdmVuIHN1ZmZpeC5cbmV4cG9ydCB7ZW5kc1dpdGggICBhcyBpc1N1ZmZpeH07XG4vLyBDaGVjayBpZiBzdHJpbmcgaGFzIGEgZ2l2ZW4gaW5maXguXG5leHBvcnQge2luY2x1ZGVzICAgYXMgaXNJbmZpeH07XG4vLyNlbmRyZWdpb25cblxuXG5cblxuLy8jcmVnaW9uIFBBUlRcbi8qKlxuICogR2V0IGNoYXJhY3RlciBhdCBhIGdpdmVuIGluZGV4IGluIHN0cmluZy5cbiAqIEBwYXJhbSB4IGEgc3RyaW5nXG4gKiBAcGFyYW0gYXQgY2hhcmFjdGVyIGluZGV4ICgtdmUg4oeSIGZyb20gcmlnaHQpXG4gKiBAcmV0dXJucyB4W2ldIHwgaSA9IGF0XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXQoeDogc3RyaW5nLCBhdDogbnVtYmVyKTogc3RyaW5nIHtcbiAgcmV0dXJuIHguY2hhckF0KGF0Pj0wPyBhdCA6IHgubGVuZ3RoK2F0KTtcbn1cbmV4cG9ydCB7Z2V0IGFzIGF0fTtcblxuXG4vKipcbiAqIEdldCBjaGFyYWN0ZXJzIGF0IGluZGljZXMuXG4gKiBAcGFyYW0geCBhIHN0cmluZ1xuICogQHBhcmFtIGF0cyBjaGFyYWN0ZXIgaW5kaWNlcyAoLXZlIOKHkiBmcm9tIHJpZ2h0KVxuICogQHJldHVybnMgeFtpXSArIHhbal0gKyAuLi4gfCBbaSwgaiwgLi4uXSA9IGF0c1xuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0QWxsKHg6IHN0cmluZywgYXRzOiBJdGVyYWJsZTxudW1iZXI+KTogc3RyaW5nIHtcbiAgbGV0IGEgPSBcIlwiO1xuICBmb3IgKGNvbnN0IGF0IG9mIGF0cylcbiAgICBhICs9IGdldCh4LCBhdCk7XG4gIHJldHVybiBhO1xufVxuXG5cbi8qKlxuICogV3JpdGUgYSBzdWJzdHJpbmcgYXQgc3BlY2lmaWVkIGluZGV4IGluIHN0cmluZy5cbiAqIEBwYXJhbSB4IGEgc3RyaW5nXG4gKiBAcGFyYW0gYXQgd3JpdGUgaW5kZXggKC12ZSDih5IgZnJvbSByaWdodClcbiAqIEBwYXJhbSB3cml0ZSBzdWJzdHJpbmcgdG8gd3JpdGVcbiAqIEByZXR1cm5zIHhbMDppXSArIHcgKyB4W2krfHd8Ol0gfCBpID0gYXQsIHcgPSB3cml0ZVxuICovXG5leHBvcnQgZnVuY3Rpb24gc2V0KHg6IHN0cmluZywgYXQ6IG51bWJlciwgd3JpdGU6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiB4LnNsaWNlKDAsIGF0KSArIHdyaXRlICsgeC5zbGljZShhdCt3cml0ZS5sZW5ndGgpO1xufVxuXG5cbi8qKlxuICogR2V0IGxlZnRtb3N0IHBhcnQgb2Ygc3RyaW5nLlxuICogQHBhcmFtIHggYSBzdHJpbmdcbiAqIEBwYXJhbSBjb3VudCBudW1iZXIgb2YgY2hhcmFjdGVycyBbMV1cbiAqIEByZXR1cm5zIHhbMDpuXSB8IG4gPSBjb3VudFxuICogQGV4YW1wbGVcbiAqIGBgYGphdmFzY3JpcHRcbiAqIHhzdHJpbmcuYmVnaW4oJ1RoYWkgU3dlZXQgQ2hpbGxpIFNhdWNlJywgNCk7XG4gKiAvLyDihpIgJ1RoYWknXG4gKlxuICogeHN0cmluZy5iZWdpbignVGhhaSBTd2VldCBDaGlsbGkgU2F1Y2UnLCAxMCk7XG4gKiAvLyDihpIgJ1RoYWkgU3dlZXQnXG4gKlxuICogeHN0cmluZy5iZWdpbignVGhhaSBTd2VldCBDaGlsbGkgU2F1Y2UnLCA4MCk7XG4gKiAvLyDihpIgJ1RoYWkgU3dlZXQgQ2hpbGxpIFNhdWNlJ1xuICpcbiAqIHhzdHJpbmcuYmVnaW4oJ1RoYWkgU3dlZXQgQ2hpbGxpIFNhdWNlJywgLTEpO1xuICogLy8g4oaSICcnXG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGJlZ2luKHg6IHN0cmluZywgY291bnQ6IG51bWJlcj0xKTogc3RyaW5nIHtcbiAgcmV0dXJuIHguc2xpY2UoMCwgY291bnQpO1xufVxuZXhwb3J0IHtiZWdpbiBhcyBwcmVmaXh9O1xuZXhwb3J0IHtiZWdpbiBhcyBsZWZ0fTtcblxuXG4vKipcbiAqIEdldCBhIHBvcnRpb24gb2Ygc3RyaW5nIGZyb20gbWlkZGxlLlxuICogQHBhcmFtIHggYSBzdHJpbmdcbiAqIEBwYXJhbSBzdGFydCBzdGFydCBpbmRleFxuICogQHBhcmFtIGNvdW50IG51bWJlciBvZiBjaGFyYWN0ZXJzIFsxXVxuICogQHJldHVybnMgeFtpOmkrbl0gfCBpID0gc3RhcnQsIG4gPSBjb3VudFxuICogQGV4YW1wbGVcbiAqIGBgYGphdmFzY3JpcHRcbiAqIHhzdHJpbmcubWlkKCdUaGFpIFN3ZWV0IENoaWxsaSBTYXVjZScsIDUsIDUpO1xuICogLy8g4oaSICdTd2VldCdcbiAqXG4gKiB4c3RyaW5nLm1pZCgnVGhhaSBTd2VldCBDaGlsbGkgU2F1Y2UnLCA1LCAxMik7XG4gKiAvLyDihpIgJ1N3ZWV0IENoaWxsaSdcbiAqXG4gKiB4c3RyaW5nLm1pZCgnVGhhaSBTd2VldCBDaGlsbGkgU2F1Y2UnLCA1KTtcbiAqIC8vIOKGkiAnU3dlZXQgQ2hpbGxpIFNhdWNlJ1xuICpcbiAqIHhzdHJpbmcubWlkKCdUaGFpIFN3ZWV0IENoaWxsaSBTYXVjZScsIDUsIC0xKTtcbiAqIC8vIOKGkiAnJ1xuICpcbiAqIHhzdHJpbmcubWlkKCdUaGFpIFN3ZWV0IENoaWxsaSBTYXVjZScsIC01KTtcbiAqIC8vIOKGkiAnU2F1Y2UnXG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1pZGRsZSh4OiBzdHJpbmcsIHN0YXJ0OiBudW1iZXIsIGNvdW50OiBudW1iZXI9MSk6IHN0cmluZyB7XG4gIHJldHVybiB4LnNsaWNlKHN0YXJ0LCBzdGFydCtjb3VudCk7XG59XG5leHBvcnQge21pZGRsZSBhcyBpbmZpeH07XG5cblxuLyoqXG4gKiBHZXQgcmlnaHRtb3N0IHBhcnQgb2Ygc3RyaW5nLlxuICogQHBhcmFtIHggYSBzdHJpbmdcbiAqIEBwYXJhbSBjb3VudCBudW1iZXIgb2YgY2hhcmFjdGVycyBbMV1cbiAqIEByZXR1cm5zIHhbfHh8LW46XSB8IG4gPSBjb3VudFxuICogQGV4YW1wbGVcbiAqIGBgYGphdmFzY3JpcHRcbiAqIHhzdHJpbmcuZW5kKCdUaGFpIFN3ZWV0IENoaWxsaSBTYXVjZScsIDUpO1xuICogLy8g4oaSICdTYXVjZSdcbiAqXG4gKiB4c3RyaW5nLmVuZCgnVGhhaSBTd2VldCBDaGlsbGkgU2F1Y2UnLCAxMik7XG4gKiAvLyDihpIgJ0NoaWxsaSBTYXVjZSdcbiAqXG4gKiB4c3RyaW5nLmVuZCgnVGhhaSBTd2VldCBDaGlsbGkgU2F1Y2UnLCA4MCk7XG4gKiAvLyDihpIgJ1RoYWkgU3dlZXQgQ2hpbGxpIFNhdWNlJ1xuICpcbiAqIHhzdHJpbmcuZW5kKCdUaGFpIFN3ZWV0IENoaWxsaSBTYXVjZScsIC0xKTtcbiAqIC8vIOKGkiAnJ1xuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBlbmQoeDogc3RyaW5nLCBjb3VudDogbnVtYmVyPTEpOiBzdHJpbmcge1xuICByZXR1cm4geC5zbGljZSh4Lmxlbmd0aC1jb3VudCk7XG59XG5leHBvcnQge2VuZCBhcyBzdWZmaXh9O1xuZXhwb3J0IHtlbmQgYXMgcmlnaHR9O1xuLy8jZW5kcmVnaW9uXG5cblxuXG5cbi8vI3JlZ2lvbiBQQVJUIChUT0RPKVxuLy8gaW1wb3J0IHtjaHVuayBhcyBhcnJheUNodW5rfSBmcm9tIFwiZXh0cmEtYXJyYXlcIjtcblxuLyoqXG4gKiBCcmVhayBzdHJpbmcgaW50byBjaHVua3Mgb2YgZ2l2ZW4gc2l6ZS5cbiAqIEBwYXJhbSB4IGEgc3RyaW5nXG4gKiBAcGFyYW0gbiBjaHVuayBzaXplICgxKVxuICogQHBhcmFtIHMgY2h1bmsgc3RlcCAobilcbiAqL1xuLy8gZnVuY3Rpb24gY2h1bmsoeDogc3RyaW5nLCBuOiBudW1iZXI9MSwgczogbnVtYmVyPW4pOiBzdHJpbmdbXSB7XG4vLyAgIHJldHVybiBhcnJheUNodW5rKHggYXMgYW55LCBuLCBzKSBhcyBhbnk7XG4vLyB9XG5cblxuLy8gaW1wb3J0IHtpbmZpeGVzIGFzIGFycmF5SW5maXhlc30gZnJvbSBcImV4dHJhLWFycmF5XCI7XG5cbi8qKlxuICogTGlzdHMgYWxsIHBvc3NpYmxlIGluZml4ZXMuXG4gKiBAcGFyYW0geCBhIHN0cmluZ1xuICogQHBhcmFtIG4gbnVtYmVyIG9mIHZhbHVlcyAoLTEg4oeSIGFueSlcbiAqL1xuLy8gZnVuY3Rpb24gaW5maXhlcyh4OiBzdHJpbmcsIG46IG51bWJlcj0tMSk6IEl0ZXJhYmxlSXRlcmF0b3I8c3RyaW5nPiB7XG4vLyAgIHJldHVybiBhcnJheUluZml4ZXMoeCBhcyBhbnksIG4pIGFzIGFueTtcbi8vIH1cblxuXG4vLyBpbXBvcnQge3ByZWZpeGVzIGFzIGFycmF5UHJlZml4ZXN9IGZyb20gXCJleHRyYS1hcnJheVwiO1xuXG4vKipcbiAqIExpc3RzIGFsbCBwb3NzaWJsZSBwcmVmaXhlcy5cbiAqIEBwYXJhbSB4IGEgc3RyaW5nXG4gKiBAcGFyYW0gbiBudW1iZXIgb2YgdmFsdWVzICgtMSDih5IgYW55KVxuICovXG4vLyBmdW5jdGlvbiBwcmVmaXhlcyh4OiBzdHJpbmcsIG46IG51bWJlcj0tMSk6IEl0ZXJhYmxlSXRlcmF0b3I8c3RyaW5nPiB7XG4vLyAgIHJldHVybiBhcnJheVByZWZpeGVzKHggYXMgYW55LCBuKSBhcyBhbnk7XG4vLyB9XG5cblxuLy8gaW1wb3J0IHtzdWZmaXhlcyBhcyBhcnJheVN1ZmZpeGVzfSBmcm9tIFwiZXh0cmEtYXJyYXlcIjtcblxuLyoqXG4gKiBMaXN0cyBhbGwgcG9zc2libGUgc3VmZml4ZXMuXG4gKiBAcGFyYW0geCBhIHN0cmluZ1xuICogQHBhcmFtIG4gbnVtYmVyIG9mIHZhbHVlcyAoLTEg4oeSIGFueSlcbiAqL1xuLy8gZnVuY3Rpb24gc3VmZml4ZXMoeDogc3RyaW5nLCBuOiBudW1iZXI9LTEpOiBJdGVyYWJsZUl0ZXJhdG9yPHN0cmluZz4ge1xuLy8gICByZXR1cm4gYXJyYXlTdWZmaXhlcyh4IGFzIGFueSwgbikgYXMgYW55O1xuLy8gfVxuLy8jZW5kcmVnaW9uXG5cblxuXG5cbi8vI3JlZ2lvbiBTRUFSQ0hcbi8vIEdldCBsZW5ndGggb2YgbG9uZ2VzdCBzdHJpbmcgaW4gYW4gaXRlcmFibGUuXG5mdW5jdGlvbiBtYXhMZW5ndGgoeHM6IEl0ZXJhYmxlPHN0cmluZz4pOiBudW1iZXIge1xuICBsZXQgYSA9IDA7XG4gIGZvciAoY29uc3QgeCBvZiB4cylcbiAgICBhID0gTWF0aC5tYXgoYSwgeC5sZW5ndGgpO1xuICByZXR1cm4gYTtcbn1cblxuLyoqXG4gKiBHZXQgc2V0LWxpc3RlZCBzeW1ib2wgYXQgc3BlY2lmaWVkIGluZGV4IGluIHN0cmluZy5cbiAqIEBwYXJhbSB4IGEgc3RyaW5nXG4gKiBAcGFyYW0gc2V0IHNldCBvZiBzeW1ib2xzXG4gKiBAcGFyYW0gaSBzdGFydCBpbmRleCBbMF1cbiAqIEBwYXJhbSBMIG1heCBzeW1ib2wgbGVuZ3RoIFswIOKHkiB1bnNwZWNpZmllZF1cbiAqIEBleGFtcGxlXG4gKiBgYGBqYXZhc2NyaXB0XG4gKiB4c3RyaW5nLnN5bWJvbEF0KCdyaG8rcGknLCBuZXcgU2V0KCkuYWRkKCdwaScpLmFkZCgncmhvJykuYWRkKCcrJykuYWRkKCctJyksIDApO1xuICogLy8g4oaSICdyaG8nXG4gKlxuICogeHN0cmluZy5zeW1ib2xBdCgncmhvK3BpJywgbmV3IFNldCgpLmFkZCgncGknKS5hZGQoJ3JobycpLmFkZCgnKycpLmFkZCgnLScpLCAyKTtcbiAqIC8vIOKGkiB1bmRlZmluZWQgKG5vIG1hdGNoIGF0IDIpXG4gKlxuICogeHN0cmluZy5zeW1ib2xBdCgncmhvK3BpJywgbmV3IFNldCgpLmFkZCgncGknKS5hZGQoJ3JobycpLmFkZCgnKycpLmFkZCgnLScpLCAzKTtcbiAqIC8vIOKGkiAnKydcbiAqXG4gKiB4c3RyaW5nLnN5bWJvbEF0KCdyaG8rcGknLCBuZXcgU2V0KFsncGknLCAncmhvJywgJysnLCAnLSddKSwgNCwgMyk7XG4gKiAvLyDihpIgJ3BpJyAobG9uZ2VzdCBzeW1ib2w9J3JobycpXG4gKiBgYGBcbiAqL1xuZnVuY3Rpb24gX3N5bWJvbEF0KHg6IHN0cmluZywgc2V0OiBTZXQ8c3RyaW5nPiwgaTogbnVtYmVyID0gMCwgTDogbnVtYmVyID0gMCkge1xuICBpZiAoTD09PTApIEwgPSBtYXhMZW5ndGgoc2V0KTtcbiAgZm9yIChsZXQgbD1MOyBsPjA7IGwtLSkge1xuICAgIGNvbnN0IHN5bSA9IHguc3Vic3RyaW5nKGksIGkrbCk7XG4gICAgaWYgKHNldC5oYXMoc3ltKSkgcmV0dXJuIHN5bTtcbiAgfVxuICByZXR1cm4gbnVsbDtcbn1cblxuXG4vKipcbiAqIEdldCB0aGUgbG9uZ2VzdCBjb21tb24gaW5maXggYmV0d2VlbiBzdHJpbmdzLlxuICogQHBhcmFtIHggYSBzdHJpbmdcbiAqIEBwYXJhbSB5IGFub3RoZXIgc3RyaW5nXG4gKiBAcmV0dXJucyBsb25nZXN0IGNvbW1vbiBpbmZpeFxuICogQGV4YW1wbGVcbiAqIGBgYGphdmFzY3JpcHRcbiAqIHhzdHJpbmcubG9uZ2VzdENvbW1vbkluZml4KCdtYW5nYWxhJywgJ21hbmdhbHlhYW4nKTtcbiAqIC8vIOKGkiAnbWFuZ2FsJ1xuICpcbiAqIHhzdHJpbmcubG9uZ2VzdENvbW1vbkluZml4KCdlYXN0ZXInLCAndGVydGlhcnknKTtcbiAqIC8vIOKGkiAndGVyJ1xuICpcbiAqIHhzdHJpbmcubG9uZ2VzdENvbW1vbkluZml4KCdkaXNtaXNzJywgJ21pc3Npc3NpcGknKTtcbiAqIC8vIOKGkiAnbWlzcydcbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gbG9uZ2VzdENvbW1vbkluZml4KHg6IHN0cmluZywgeTogc3RyaW5nKTogc3RyaW5nIHtcbiAgbGV0IGFpID0gMCwgYWwgPSAwO1xuICBmb3IgKGxldCBpPTAsIEk9eC5sZW5ndGg7IGk8STsgaSsrKSB7XG4gICAgZm9yIChsZXQgaj0wLCBKPXkubGVuZ3RoLCBsPTA7IGo8SjsgaisrKSB7XG4gICAgICBsID0geFtpK2xdPT09eVtqXT8gbCsxIDogMDtcbiAgICAgIGlmIChsPmFsKSB7IGFpID0gai1sKzE7IGFsID0gbDsgfVxuICAgIH1cbiAgfVxuICByZXR1cm4geS5zdWJzdHJpbmcoYWksIGFpK2FsKTtcbn1cblxuXG4vKipcbiAqIEdldCB0aGUgbG9uZ2VzdCBjb21tb24gcHJlZml4IG9mIHN0cmluZ3MuXG4gKiBAcGFyYW0geCBhIHN0cmluZ1xuICogQHBhcmFtIHkgYW5vdGhlciBzdHJpbmdcbiAqIEByZXR1cm5zIGxvbmdlc3QgY29tbW9uIHByZWZpeFxuICogQGV4YW1wbGVcbiAqIGBgYGphdmFzY3JpcHRcbiAqIHhzdHJpbmcubG9uZ2VzdENvbW1vblByZWZpeCgncGVhY29jaycsICdwZWFoZW4nKTtcbiAqIC8vIOKGkiAncGVhJ1xuICpcbiAqIHhzdHJpbmcubG9uZ2VzdENvbW1vblByZWZpeCgnaW5jZXB0aW9uJywgJ2ludGVyc3RlbGxhcicpO1xuICogLy8g4oaSICdpbidcbiAqXG4gKiB4c3RyaW5nLmxvbmdlc3RDb21tb25QcmVmaXgoJ21hcnMnLCAndGFycycpO1xuICogLy8g4oaSICcnXG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGxvbmdlc3RDb21tb25QcmVmaXgoeDogc3RyaW5nLCB5OiBzdHJpbmcpOiBzdHJpbmcge1xuICBsZXQgaSA9IDA7XG4gIGZvciAoY29uc3QgST1NYXRoLm1pbih4Lmxlbmd0aCwgeS5sZW5ndGgpOyBpPEk7IGkrKylcbiAgICBpZiAoeFtpXSE9PXlbaV0pIGJyZWFrO1xuICByZXR1cm4geC5zdWJzdHJpbmcoMCwgaSk7XG59XG5cblxuLyoqXG4gKiBHZXQgdGhlIGxvbmdlc3QgY29tbW9uIHN1ZmZpeCBvZiBzdHJpbmdzLlxuICogQHBhcmFtIHggYSBzdHJpbmdcbiAqIEBwYXJhbSB5IGFub3RoZXIgc3RyaW5nXG4gKiBAcmV0dXJucyBsb25nZXN0IGNvbW1vbiBzdWZmaXhcbiAqIEBleGFtcGxlXG4gKiBgYGBqYXZhc2NyaXB0XG4gKiB4c3RyaW5nLmxvbmdlc3RDb21tb25TdWZmaXgoJ3BlYWNvY2snLCAnaGFuY29jaycpO1xuICogLy8g4oaSICdjb2NrJ1xuICpcbiAqIHhzdHJpbmcubG9uZ2VzdENvbW1vblN1ZmZpeCgnbWFycycsICd0YXJzJyk7XG4gKiAvLyDihpIgJ2FycydcbiAqXG4gKiB4c3RyaW5nLmxvbmdlc3RDb21tb25TdWZmaXgoJ2NoaWVmJywgJ21hc3RlcicpO1xuICogLy8g4oaSICcnXG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGxvbmdlc3RDb21tb25TdWZmaXgoeDogc3RyaW5nLCB5OiBzdHJpbmcpOiBzdHJpbmcge1xuICBsZXQgaSA9IHgubGVuZ3RoLTE7XG4gIGZvciAobGV0IGo9eS5sZW5ndGgtMTsgaT49MCAmJiBqPj0wOyBpLS0sIGotLSlcbiAgICBpZiAoeFtpXSE9PXlbal0pIGJyZWFrO1xuICByZXR1cm4geC5zdWJzdHJpbmcoaSsxKTtcbn1cblxuXG4vKipcbiAqIEdldCB0aGUgbG9uZ2VzdCB1bmNvbW1vbiBpbmZpeGVzIG9mIHN0cmluZ3MuXG4gKiBAcGFyYW0geCBhIHN0cmluZ1xuICogQHBhcmFtIHkgYW5vdGhlciBzdHJpbmdcbiAqIEByZXR1cm5zIFtpbmZpeDEsIGluZml4Ml1cbiAqIEBleGFtcGxlXG4gKiBgYGBqYXZhc2NyaXB0XG4gKiB4c3RyaW5nLmxvbmdlc3RVbmNvbW1vbkluZml4ZXMoJ3JvbGxjYWdlJywgJ3JpZGVjYWdlJyk7XG4gKiAvLyDihpIgWydvbGwnLCAnaWRlJ11cbiAqXG4gKiB4c3RyaW5nLmxvbmdlc3RVbmNvbW1vbkluZml4ZXMoJ3JpdmVyYmVkJywgJ3JvdmVyYmVkJyk7XG4gKiAvLyDihpIgWydpJywgJ28nXVxuICpcbiAqIHhzdHJpbmcubG9uZ2VzdFVuY29tbW9uSW5maXhlcygnY2hvY29sYXRpZXInLCAnZW5naW5lZXInKTtcbiAqIC8vIOKGkiBbJ2Nob2NvbGF0aScsICdlbmdpbmUnXVxuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBsb25nZXN0VW5jb21tb25JbmZpeGVzKHg6IHN0cmluZywgeTogc3RyaW5nKTogW3N0cmluZywgc3RyaW5nXSB7XG4gIGNvbnN0IFggPSB4Lmxlbmd0aCwgWSA9IHkubGVuZ3RoO1xuICBjb25zdCBpID0gbG9uZ2VzdENvbW1vblByZWZpeCh4LCB5KS5sZW5ndGg7XG4gIGNvbnN0IGogPSBsb25nZXN0Q29tbW9uU3VmZml4KHgsIHkpLmxlbmd0aDtcbiAgcmV0dXJuIFt4LnN1YnN0cmluZyhpLCBYLWopLCB5LnN1YnN0cmluZyhpLCBZLWopXTtcbn1cbi8vI2VuZHJlZ2lvblxuXG5cblxuXG4vLyNyZWdpb24gVFJBTlNGT1JNIChTVVBFUi9TVUJTQ1JJUFQpXG4vKiogU3VwZXJzY3JpcHQgY2hhcmFjdGVycyB0aGF0IGNhbiBiZSB0cmFuc2Zvcm1lZCB0byBiYXNlbGluZSB3aXRoIGBTVVBFUlNDUklQVF9UQVJHRVRgLiAqL1xuY29uc3QgU1VQRVJTQ1JJUFRfU09VUkNFID0gXCLigbDCucKywrPigbTigbXigbbigbfigbjigbnigbrigbvigbzigb3igb7htZ3htZ7htZ/htr/htqXhtaDhtaHhtKzhtK7htLDhtLHhtLPhtLThtLXhtLbhtLfhtLjhtLnhtLrhtLzhtL7htL/htYDhtYHisb3htYLhtqbhtqvhtrDhtrjhtYPhtYfhtpzhtYjhtYnhtqDhtY3KsOKBscqy4bWPy6HhtZDigb/htZLhtZbKs8ui4bWX4bWY4bWbyrfLo8q44ba7XCI7XG4vKiogQmFzZWxpbmUgY2hhcmFjdGVycyB0aGF0IGNhbiBiZSB0cmFuc2Zvcm1lZCBmcm9tIHN1cGVyc2NyaXB0IHdpdGggYFNVUEVSU0NSSVBUX1NPVVJDRWAuICovXG5jb25zdCBTVVBFUlNDUklQVF9UQVJHRVQgPSBcIjAxMjM0NTY3ODkrLT0oKc6yzrPOtM64zrnPhs+HQUJERUdISUpLTE1OT1BSVFVWV0lMTlVhYmNkZWZnaGlqa2xtbm9wcnN0dXZ3eHl6XCI7XG4vKiogU3Vic2NyaXB0IGNoYXJhY3RlcnMgdGhhdCBjYW4gYmUgdHJhbnNmb3JtZWQgdG8gYmFzZWxpbmUgd2l0aCBgU1VCU0NSSVBUX1RBUkdFVGAuICovXG5jb25zdCBTVUJTQ1JJUFRfU09VUkNFICAgPSBcIuKCgOKCgeKCguKCg+KChOKCheKChuKCh+KCiOKCieKCiuKCi+KCjOKCjeKCjuKClOG1puG1p+G1qOG1qeG1quKCkOKCkeKCleG1ouKxvOKCluKCl+KCmOKCmeKCkuKCmuG1o+KCm+KCnOG1pOG1peKCk1wiO1xuLyoqIEJhc2VsaW5lIGNoYXJhY3RlcnMgdGhhdCBjYW4gYmUgdHJhbnNmb3JtZWQgZnJvbSBzdWJzY3JpcHQgd2l0aCBgU1VCU0NSSVBUX1RBUkdFVGAuICovXG5jb25zdCBTVUJTQ1JJUFRfVEFSR0VUICAgPSBcIjAxMjM0NTY3ODkrLT0oKcmZzrLOs8+Bz4bPh2FlaGlqa2xtbm9wcnN0dXZ4XCI7XG5cbmZ1bmN0aW9uIHRvQmFzZWxpbmVEaXJlY3QoeDogc3RyaW5nKTogc3RyaW5nIHtcbiAgbGV0IGEgPSBcIlwiO1xuICBmb3IgKGxldCBjIG9mIHgpIHtcbiAgICBjb25zdCBqID0gU1VQRVJTQ1JJUFRfU09VUkNFLmluZGV4T2YoYyk7XG4gICAgY29uc3QgayA9IFNVQlNDUklQVF9TT1VSQ0UuaW5kZXhPZihjKTtcbiAgICBpZiAoaj49MCkgYyA9IFNVUEVSU0NSSVBUX1RBUkdFVFtqXTtcbiAgICBpZiAoaz49MCkgYyA9IFNVUEVSU0NSSVBUX1RBUkdFVFtrXTtcbiAgICBhICs9IGM7XG4gIH1cbiAgcmV0dXJuIGE7XG59XG5cbmZ1bmN0aW9uIHRvQmFzZWxpbmVJbmRpcmVjdCh4OiBzdHJpbmcsIGZzdXA6IE1hcEZ1bmN0aW9uLCBmc3ViOiBNYXBGdW5jdGlvbik6IHN0cmluZyB7XG4gIGxldCBhICAgPSBcIlwiLCBpID0gMCwgdCA9IDA7XG4gIGxldCB0bXAgPSBcIlwiLCBtb2RlID0gMDtcbiAgZnN1cCA9IGZzdXAgfHwgSURFTlRJVFk7XG4gIGZzdWIgPSBmc3ViIHx8IElERU5USVRZO1xuICBmb3IgKGNvbnN0IGMgb2YgeCkge1xuICAgIHQgPSB0bXAubGVuZ3RoO1xuICAgIGNvbnN0IGogPSBTVVBFUlNDUklQVF9TT1VSQ0UuaW5kZXhPZihjKTtcbiAgICBjb25zdCBrID0gU1VCU0NSSVBUX1NPVVJDRS5pbmRleE9mKGMpO1xuICAgIGNvbnN0IG0gPSAoaj49MD8gMTowKSArIChrPj0wPyAyOjApO1xuICAgIGlmIChtIT09bW9kZSAmJiB0KSBhICs9IG1vZGU9PT0wPyB0bXAgOiAobW9kZT09PTE/IGZzdXAodG1wLCBpLXQpIDogZnN1Yih0bXAsIGktdCkpO1xuICAgIHRtcCArPSBtPT09MD8gYyA6IChtPT09MT8gU1VQRVJTQ1JJUFRfVEFSR0VUW2pdIDogU1VCU0NSSVBUX1RBUkdFVFtrXSk7XG4gICAgbW9kZSA9IG07IGkrKztcbiAgfVxuICBpZiAodG1wKSBhICs9IG1vZGU9PT0wPyB0bXAgOiAobW9kZT09PTE/IGZzdXAodG1wLCBpLXQpIDogZnN1Yih0bXAsIGktdCkpO1xuICByZXR1cm4gYTtcbn1cblxuLyoqXG4gKiBDb252ZXJ0IGEgc3RyaW5nIHRvIGJhc2VsaW5lIGNoYXJhY3RlcnMgKGxpbWl0ZWQgc3VwcG9ydCkuXG4gKiBAcGFyYW0geCBhIHN0cmluZ1xuICogQHBhcmFtIGZzdXAgbWFwIGZ1bmN0aW9uIGZvciBzdXBlcnNjcmlwdCBjaGFyYWN0ZXJzICh2LCBpLCB4KVxuICogQHBhcmFtIGZzdWIgbWFwIGZ1bmN0aW9uIGZvciBzdWJzY3JpcHQgY2hhcmFjdGVycyAodiwgaSwgeClcbiAqIEByZXR1cm5zIGJhc2VsaW5lZCBzdHJpbmdcbiAqIEBleGFtcGxlXG4gKiBgYGBqYXZhc2NyaXB0XG4gKiB4c3RyaW5nLnRvQmFzZWxpbmUoJ2F4wrIrYngrYycpO1xuICogLy8g4oaSICdheDIrYngrYydcbiAqXG4gKiB4c3RyaW5nLnRvQmFzZWxpbmUoJ0jigoJTT+KChCBiZWFrZXInKTtcbiAqIC8vIOKGkiAnSDJTTzQgYmVha2VyJ1xuICpcbiAqIHhzdHJpbmcudG9CYXNlbGluZSgnNi42MjYgeCAxMOKBu8Kz4oG0JywgWydeJ10pO1xuICogLy8g4oaSICc2LjYyNiB4IDEwXi0zNCdcbiAqXG4gKiB4c3RyaW5nLnRvQmFzZWxpbmUoJzEwMTDigoInLCBudWxsLCBbJyAoYmFzZS0nLCAnKSddKTtcbiAqIC8vIOKGkiAnMTAxMCAoYmFzZS0yKSdcbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gdG9CYXNlbGluZSh4OiBzdHJpbmcsIGZzdXA6IE1hcEZ1bmN0aW9uIHwgbnVsbD1udWxsLCBmc3ViOiBNYXBGdW5jdGlvbiB8IG51bGw9bnVsbCk6IHN0cmluZyB7XG4gIGlmICghZnN1cCAmJiAhZnN1YikgcmV0dXJuIHRvQmFzZWxpbmVEaXJlY3QoeCk7XG4gIHJldHVybiB0b0Jhc2VsaW5lSW5kaXJlY3QoeCwgZnN1cCB8fCBJREVOVElUWSwgZnN1YiB8fCBJREVOVElUWSk7XG59XG5cblxuLyoqIFN1cGVyc2NyaXB0IEFTQ0lJIGNoYXJhY3RlcnMgYWZ0ZXIgc3BhY2UgKDMyKS4gKi9cbmNvbnN0IFNVUEVSU0NSSVBUX0xPT0tVUCA9IFwiICAgICAgICDigb3igb4g4oG6IOKBuyAg4oGwwrnCssKz4oG04oG14oG24oG34oG44oG5ICAg4oG8ICAg4bSs4bSuIOG0sOG0sSDhtLPhtLThtLXhtLbhtLfhtLjhtLnhtLrhtLzhtL4g4bS/IOG1gOG1gSDhtYIgICAgICAgICDhtYPhtYfhtpzhtYjhtYnhtqDhtY3KsOKBscqy4bWPy6HhtZDigb/htZLhtZYgyrPLouG1l+G1mOG1m8q3y6PKuOG2uyAgICAgXCI7XG5cbi8qKlxuICogQ29udmVydCBhIHN0cmluZyB0byBzdXBlcnNjcmlwdCBjaGFyYWN0ZXJzIChsaW1pdGVkIHN1cHBvcnQpLlxuICogQHBhcmFtIHggYSBzdHJpbmdcbiAqIEByZXR1cm5zIHN1cGVyc2NyaXB0ZWQgY2hhcmFjdGVyc1xuICogQGV4YW1wbGVcbiAqIGBgYGphdmFzY3JpcHRcbiAqIHhzdHJpbmcudG9TdXBlcnNjcmlwdCgnaGVsbG8gd29ybGQnKTtcbiAqIC8vIOKGkiAnyrDhtYnLocuh4bWSIMq34bWSyrPLoeG1iCdcbiAqXG4gKiB4c3RyaW5nLnRvU3VwZXJzY3JpcHQoJ0RFQ0NBTiBQTEFURUFVJyk7XG4gKiAvLyDihpIgJ+G0sOG0sUND4bSs4bS6IOG0vuG0uOG0rOG1gOG0seG0rOG1gSdcbiAqXG4gKiAnNi42MjYgeCAxMCcgKyB4c3RyaW5nLnRvU3VwZXJzY3JpcHQoJy0zNCcpO1xuICogLy8g4oaSICc2LjYyNiB4IDEw4oG7wrPigbQnIChQbGFuY2sncyBjb25zdGFudClcbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gdG9TdXBlcnNjcmlwdCh4OiBzdHJpbmcpOiBzdHJpbmcge1xuICBsZXQgYSA9IFwiXCI7XG4gIGZvciAoY29uc3QgYyBvZiB4KSB7XG4gICAgY29uc3QgZCA9IFNVUEVSU0NSSVBUX0xPT0tVUFtjLmNoYXJDb2RlQXQoMCkgLSAzMl0gfHwgXCIgXCI7XG4gICAgYSArPSBkPT09XCIgXCI/IGMgOiBkO1xuICB9XG4gIHJldHVybiBhO1xufVxuXG5cbi8qKiBTdWJzY3JpcHQgQVNDSUkgY2hhcmFjdGVycyBhZnRlciBzcGFjZSAoMzIpLiAqL1xuY29uc3QgU1VCU0NSSVBUX0xPT0tVUCA9IFwiICAgICAgICDigo3igo4g4oKKIOKCiyAg4oKA4oKB4oKC4oKD4oKE4oKF4oKG4oKH4oKI4oKJICAg4oKMICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICDigpAgICDigpEgIOKCleG1ouKxvOKCluKCl+KCmOKCmeKCkuKCmiDhtaPigpvigpzhtaThtaUg4oKTICAgICAgIFwiO1xuXG4vKipcbiAqIENvbnZlcnQgYSBzdHJpbmcgdG8gc3VwZXJzY3JpcHQgY2hhcmFjdGVycyAobGltaXRlZCBzdXBwb3J0KS5cbiAqIEBwYXJhbSB4IGEgc3RyaW5nXG4gKiBAcmV0dXJucyBzdXBlcnNjcmlwdGVkIGNoYXJhY3RlcnNcbiAqIEBleGFtcGxlXG4gKiBgYGBqYXZhc2NyaXB0XG4gKiB4c3RyaW5nLnRvU3Vic2NyaXB0KCdoZWxsbyB3b3JsZCcpO1xuICogLy8g4oaSICfigpXigpHigpfigpfigpIgd+KCkuG1o+KCl2QnXG4gKlxuICogeHN0cmluZy50b1N1YnNjcmlwdCgnREVDQ0FOIFBMQVRFQVUnKTtcbiAqIC8vIOKGkiAnREVDQ0FOIFBMQVRFQVUnXG4gKlxuICogJ0tOTycgKyB4c3RyaW5nLnRvU3Vic2NyaXB0KCczJyk7XG4gKiAvLyDihpIgJ0tOT+KCgycgKFBvdGFzc2l1bSBOaXRyYXRlKVxuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0b1N1YnNjcmlwdCh4OiBzdHJpbmcpOiBzdHJpbmcge1xuICBsZXQgYSA9IFwiXCI7XG4gIGZvciAoY29uc3QgYyBvZiB4KSB7XG4gICAgY29uc3QgZCA9IFNVQlNDUklQVF9MT09LVVBbYy5jaGFyQ29kZUF0KDApIC0gMzJdIHx8IFwiIFwiO1xuICAgIGEgKz0gZD09PVwiIFwiPyBjIDogZDtcbiAgfVxuICByZXR1cm4gYTtcbn1cbi8vI2VuZHJlZ2lvblxuXG5cblxuXG4vLyNyZWdpb24gVFJBTlNGT1JNIChDQVNFKVxuLy8gQ29udmVydCBvbmx5IHRoZSBmaXJzdCBsZXR0ZXIgb2YgYSBzdHJpbmcgdG8gdXBwZXItY2FzZSwgcmVtYWluaW5nIGxvd2VyLWNhc2UuXG5mdW5jdGlvbiB0b0JlZ2luVXBwZXJDYXNlKHg6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiB4LnNsaWNlKDAsIDEpLnRvVXBwZXJDYXNlKCkgKyB4LnNsaWNlKDEpLnRvTG93ZXJDYXNlKCk7XG59XG5cbi8vIENvbnZlcnQgb25seSB0aGUgZmlyc3QgbGV0dGVyIG9mIGEgc3RyaW5nIHRvIHVwcGVyLWNhc2UsIHJlbWFpbmluZyBhcy1pcy5cbmZ1bmN0aW9uIHRvQmVnaW5VcHBlckFueUNhc2UoeDogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIHguc2xpY2UoMCwgMSkudG9VcHBlckNhc2UoKSArIHguc2xpY2UoMSk7XG59XG5cbi8vIENvbnZlcnQgb25seSB0aGUgZmlyc3QgbGV0dGVyIG9mIGEgc3RyaW5nIHRvIGxvd2VyLWNhc2UsIHJlbWFpbmluZyBhcy1pcy5cbmZ1bmN0aW9uIHRvQmVnaW5Mb3dlckFueUNhc2UoeDogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIHguc2xpY2UoMCwgMSkudG9VcHBlckNhc2UoKSArIHguc2xpY2UoMSk7XG59XG5cbi8vIENvbnZlcnQgb25seSB0aGUgZmlyc3QgYW5kIGxhc3QgbGV0dGVycyBvZiBhIHN0cmluZyB0byB1cHBlci1jYXNlLCByZW1haW5pbmcgbG93ZXItY2FzZS5cbmZ1bmN0aW9uIHRvQm9yZGVyVXBwZXJDYXNlKHg6IHN0cmluZyk6IHN0cmluZyB7XG4gIGlmICh4Lmxlbmd0aDw9MikgcmV0dXJuIHgudG9VcHBlckNhc2UoKTtcbiAgcmV0dXJuIHguc2xpY2UoMCwgMSkudG9VcHBlckNhc2UoKSArIHguc2xpY2UoMSwgLTEpLnRvTG93ZXJDYXNlKCkgKyB4LnNsaWNlKC0xKS50b1VwcGVyQ2FzZSgpO1xufVxuXG5cbi8qKlxuICogU3BsaXQgYSBzdHJpbmcgaW50byB3b3JkcywgYWZ0ZXIgZGUtY2FzaW5nIGl0LlxuICogQHBhcmFtIHggYSBzdHJpbmdcbiAqIEBwYXJhbSByZSB3b3JkIHNlcGVyYXRvciBwYXR0ZXJuIFsvW14wLTlBLVphLXpdKy9nXVxuICogQHJldHVybnMgd29yZHMgaW4gdGhlIHN0cmluZ1xuICogQGV4YW1wbGVcbiAqIGBgYGphdmFzY3JpcHRcbiAqIHhzdHJpbmcudG9Xb3JkcygnTWFsd2EgUGxhdGVhdScpO1xuICogLy8g4oaSIFsnTWFsd2EnLCAnUGxhdGVhdSddXG4gKlxuICogeHN0cmluZy50b1dvcmRzKCc6OmNob3RhOjpuYWdwdXI6OicpO1xuICogLy8g4oaSIFsnY2hvdGEnLCAnbmFncHVyJ11cbiAqXG4gKiB4c3RyaW5nLnRvV29yZHMoJ2RlY2Nhbl9fX3BsYXRlYXUnKTtcbiAqIC8vIOKGkiBbJ2RlY2NhbicsICdwbGF0ZWF1J11cbiAqXG4gKiB4c3RyaW5nLnRvV29yZHMoJ3dlc3Rlcm5HaGF0cycpO1xuICogLy8g4oaSIFsnd2VzdGVybicsICdHaGF0cyddXG4gKlxuICogeHN0cmluZy50b1dvcmRzKCdwYXJzZVVSTFRvSlNPTicpO1xuICogLy8g4oaSIFsncGFyc2UnLCAnVVJMJywgJ1RvJywgJ0pTT04nXVxuICovXG5leHBvcnQgZnVuY3Rpb24gdG9Xb3Jkcyh4OiBzdHJpbmcsIHJlOiBSZWdFeHAgfCBudWxsPW51bGwpOiBzdHJpbmdbXSB7XG4gIGNvbnN0IHdvcmRzICA9IFtdO1xuICBjb25zdCB0b2tlbnMgPSB4LnNwbGl0KHJlIHx8IC9bXjAtOUEtWmEtel0rL2cpLmZpbHRlcihJREVOVElUWSk7XG4gIGZvciAoY29uc3QgdG9rZW4gb2YgdG9rZW5zKSB7XG4gICAgY29uc3QgcmUgPSAvW0EtWl0rL2c7XG4gICAgbGV0IG0gPSBudWxsLCBpID0gMDtcbiAgICB3aGlsZSAoKG0gPSByZS5leGVjKHRva2VuKSkgIT0gbnVsbCkge1xuICAgICAgaWYgKGkhPT1tLmluZGV4KSB3b3Jkcy5wdXNoKHRva2VuLnNsaWNlKGksIG0uaW5kZXgpKTtcbiAgICAgIGlmIChtWzBdLmxlbmd0aD09PTEgfHwgbS5pbmRleCArIG1bMF0ubGVuZ3RoID09PSB0b2tlbi5sZW5ndGgpIGkgPSBtLmluZGV4O1xuICAgICAgZWxzZSB7IHdvcmRzLnB1c2godG9rZW4uc2xpY2UobS5pbmRleCwgbS5pbmRleCArIG1bMF0ubGVuZ3RoIC0gMSkpOyBpID0gbS5pbmRleCArIG1bMF0ubGVuZ3RoIC0gMTsgfVxuICAgIH1cbiAgICBpZiAoaSE9PXRva2VuLmxlbmd0aCkgd29yZHMucHVzaCh0b2tlbi5zbGljZShpKSk7XG4gIH1cbiAgcmV0dXJuIHdvcmRzO1xufVxuLy8gTk9URTogU2hvdWxkbid0IHRoaXMgYmUgY2FsbGVkIHNwbGl0V29yZHMoKSBvciBzcGxpdEludG9Xb3JkcygpIG9yIHNwbGl0SW50b1Rva2VucygpP1xuXG5cbi8qKlxuICogQ29udmVydCBhIHN0cmluZyB0byB0aXRsZS1jYXNlLlxuICogQHBhcmFtIHggYSBzdHJpbmdcbiAqIEBwYXJhbSByZSB3b3JkIHNlcGVyYXRvciBwYXR0ZXJuIFsvW14wLTlBLVphLXpdKy9nXVxuICogQHJldHVybnMgVGl0bGUgQ2FzZVxuICogQGV4YW1wbGVcbiAqIGBgYGphdmFzY3JpcHRcbiAqIHhzdHJpbmcudG9UaXRsZUNhc2UoJ0dlbWluaWQgbWV0ZW9yIHNob3dlcicpO1xuICogLy8g4oaSICdHZW1pbmlkIE1ldGVvciBTaG93ZXInXG4gKlxuICogeHN0cmluZy50b1RpdGxlQ2FzZSgnZGVjY2FuX19fcGxhdGVhdScpO1xuICogLy8g4oaSICdEZWNjYW4gUGxhdGVhdSdcbiAqXG4gKiB4c3RyaW5nLnRvVGl0bGVDYXNlKCdwYXJzZVVSTFRvSlNPTicsIG51bGwsICdfJyk7XG4gKiAvLyDihpIgJ1BhcnNlX1VSTF9Ub19KU09OJ1xuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0b1RpdGxlQ2FzZSh4OiBzdHJpbmcsIHJlOiBSZWdFeHAgfCBudWxsPW51bGwsIHNlcD1cIiBcIik6IHN0cmluZyB7XG4gIHJldHVybiB0b1dvcmRzKHgsIHJlKS5tYXAodG9CZWdpblVwcGVyQ2FzZSkuam9pbihzZXApO1xufVxuXG5cbi8qKlxuICogQ29udmVydCBhIHN0cmluZyB0byBrZWJhYi1jYXNlLlxuICogQHBhcmFtIHggYSBzdHJpbmdcbiAqIEBwYXJhbSByZSB3b3JkIHNlcGVyYXRvciBwYXR0ZXJuIFsvW14wLTlBLVphLXpdKy9nXVxuICogQHBhcmFtIHNlcCBzZXBhcmF0b3IgdG8gam9pbiB3aXRoIFstXVxuICogQHJldHVybnMga2ViYWItY2FzZSB8IGtlYmFiPGpvaW4+Y2FzZVxuICovXG5leHBvcnQgZnVuY3Rpb24gdG9LZWJhYkNhc2UoeDogc3RyaW5nLCByZTogUmVnRXhwIHwgbnVsbD1udWxsLCBzZXA6IHN0cmluZz1cIi1cIik6IHN0cmluZyB7XG4gIGNvbnN0IHdvcmRzID0geC5zcGxpdChyZSB8fCAvW14wLTlBLVphLXpdKy9nKS5maWx0ZXIoSURFTlRJVFkpO1xuICBmb3IgKGxldCBpPTAsIEk9d29yZHMubGVuZ3RoOyBpPEk7ICsraSkge1xuICAgIHdvcmRzW2ldID0gd29yZHNbaV0ucmVwbGFjZSgvW0EtWl0rL2csIChtLCBvZmYpID0+IG0ubGVuZ3RoPT09MSB8fCBvZmYgKyBtLmxlbmd0aD09PXdvcmRzW2ldLmxlbmd0aD8gc2VwICsgbSA6IHNlcCArIG0uc2xpY2UoMCwgLTEpICsgc2VwICsgbS5zbGljZSgtMSkpO1xuICAgIGlmICh3b3Jkc1tpXS5zdGFydHNXaXRoKHNlcCkpIHdvcmRzW2ldID0gd29yZHNbaV0uc2xpY2Uoc2VwLmxlbmd0aCk7XG4gIH1cbiAgcmV0dXJuIHdvcmRzLmpvaW4oc2VwKS50b0xvd2VyQ2FzZSgpO1xufVxuXG5cbi8qKlxuICogQ29udmVydCBhIHN0cmluZyB0byBzbmFrZS1jYXNlLlxuICogQHBhcmFtIHggYSBzdHJpbmdcbiAqIEBwYXJhbSByZSB3b3JkIHNlcGVyYXRvciBwYXR0ZXJuIFsvW14wLTlBLVphLXpdKy9nXVxuICogQHJldHVybnMgc25ha2VfY2FzZVxuICogQGV4YW1wbGVcbiAqIGBgYGphdmFzY3JpcHRcbiAqIHhzdHJpbmcudG9TbmFrZUNhc2UoJ01hbHdhIFBsYXRlYXUnKTtcbiAqIC8vIOKGkiAnbWFsd2FfcGxhdGVhdSdcbiAqXG4gKiB4c3RyaW5nLnRvU25ha2VDYXNlKCc6OmNob3RhOjpuYWdwdXI6OicsICctJyk7XG4gKiAvLyDihpIgJ2Nob3RhLW5hZ3B1cidcbiAqXG4gKiB4c3RyaW5nLnRvU25ha2VDYXNlKCdkZWNjYW5fX19wbGF0ZWF1JywgJy4nLCAnXycpO1xuICogLy8g4oaSICdkZWNjYW4ucGxhdGVhdSdcbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gdG9TbmFrZUNhc2UoeDogc3RyaW5nLCByZTogUmVnRXhwIHwgbnVsbD1udWxsKTogc3RyaW5nIHtcbiAgcmV0dXJuIHRvS2ViYWJDYXNlKHgsIHJlLCBcIl9cIik7XG59XG5cblxuLyoqXG4gKiBDb252ZXJ0IGEgc3RyaW5nIHRvIGNhbWVsLWNhc2UuXG4gKiBAcGFyYW0geCBhIHN0cmluZ1xuICogQHBhcmFtIHJlIHdvcmQgc2VwZXJhdG9yIHBhdHRlcm4gWy9bXjAtOUEtWmEtel0rL2ddXG4gKiBAcGFyYW0gdXBwZXIgdXBwZXIgY2FtZWwgY2FzZT9cbiAqIEByZXR1cm5zIGNhbWVsQ2FzZSB8IENhbWVsQ2FzZVxuICogQGV4YW1wbGVcbiAqIGBgYGphdmFzY3JpcHRcbiAqIHhzdHJpbmcudG9DYW1lbENhc2UoJ1dlc3Rlcm4gR2hhdHMnKTtcbiAqIC8vIOKGkiAnd2VzdGVybkdoYXRzJ1xuICpcbiAqIHhzdHJpbmcudG9DYW1lbENhc2UoJ2NhcmRhbW9tLS1oaWxscycsIDEpO1xuICogLy8g4oaSICdDYXJkYW1vbUhpbGxzJ1xuICpcbiAqIHhzdHJpbmcudG9DYW1lbENhc2UoJ0VBc3RFcm5fX2doQXRzJywgMSwgJ18nKTtcbiAqIC8vIOKGkiAnRWFzdGVybkdoYXRzJ1xuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0b0NhbWVsQ2FzZSh4OiBzdHJpbmcsIHJlOiBSZWdFeHAgfCBudWxsPW51bGwsIHVwcGVyOiBib29sZWFuPWZhbHNlKTogc3RyaW5nIHtcbiAgbGV0IGEgPSBcIlwiOyBjb25zdCB3b3JkcyA9IHguc3BsaXQocmUgfHwgL1teMC05QS1aYS16XSsvZykuZmlsdGVyKElERU5USVRZKTtcbiAgZm9yIChjb25zdCB3IG9mIHdvcmRzKVxuICAgIGEgKz0gdG9CZWdpblVwcGVyQW55Q2FzZSh3LnJlcGxhY2UoL1tBLVpdKy9nLCB0b0JvcmRlclVwcGVyQ2FzZSkpO1xuICByZXR1cm4gdXBwZXI/IGEgOiB0b0JlZ2luTG93ZXJBbnlDYXNlKGEpO1xufVxuXG5cbi8qKlxuICogQ29udmVydCBhIHN0cmluZyB0byBwYXNjYWwtY2FzZS5cbiAqIEBwYXJhbSB4IGEgc3RyaW5nXG4gKiBAcGFyYW0gcmUgd29yZCBzZXBlcmF0b3IgcGF0dGVybiBbL1teMC05QS1aYS16XSsvZ11cbiAqIEByZXR1cm5zIFBhc2NhbENhc2VcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRvUGFzY2FsQ2FzZSh4OiBzdHJpbmcsIHJlOiBSZWdFeHAgfCBudWxsPW51bGwpOiBzdHJpbmcge1xuICByZXR1cm4gdG9DYW1lbENhc2UoeCwgcmUsIHRydWUpO1xufVxuXG5cbi8qKlxuICogQ29udmVydCBhIHN0cmluZyB0byBzbHVnLWNhc2UgKFVSTC1mcmllbmRseSBrZWJhYi1jYXNlKS5cbiAqIEBwYXJhbSB4IGEgc3RyaW5nXG4gKiBAcGFyYW0gcmUgd29yZCBzZXBhcmF0b3IgcGF0dGVybiBbL1teMC05QS1aYS16XSsvZ11cbiAqIEBwYXJhbSBzZXAgc2VwYXJhdG9yIHRvIGpvaW4gd2l0aCBbLV1cbiAqIEByZXR1cm5zIHNsdWctY2FzZSB8IHNsdWc8am9pbj5jYXNlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0b1NsdWdDYXNlKHg6IHN0cmluZywgcmU6IFJlZ0V4cCB8IG51bGwgPSBudWxsLCBzZXA6IHN0cmluZyA9IFwiLVwiKTogc3RyaW5nIHtcbiAgeCA9IHgubm9ybWFsaXplKFwiTkZLRFwiKS5yZXBsYWNlKC9bXFx1MDMwMC1cXHUwMzZmXS9nLCBcIlwiKTsgLy8gUmVtb3ZlIGFjY2VudHNcbiAgLy8gZGVuby1saW50LWlnbm9yZSBuby1jb250cm9sLXJlZ2V4XG4gIHJldHVybiB0b0tlYmFiQ2FzZSh4LnJlcGxhY2UoL1teXFx4MDAtXFx4N0ZdL2csIFwiXCIpLCByZSwgc2VwKTsgLy8gUmVtb3ZlIG5vbi1BU0NJSSBjaGFyc1xufVxuZXhwb3J0IHt0b1NsdWdDYXNlIGFzIHNsdWdpZnl9O1xuLy8jZW5kcmVnaW9uXG5cblxuXG5cblxuLy8jcmVnaW9uIFRSQU5TRk9STVxuLyoqXG4gKiBHZXQgY2hhcmFjdGVycyB0aGF0IGN5Y2xlIHRocm91Z2ggc3RyaW5nLlxuICogQHBhcmFtIHggYSBzdHJpbmdcbiAqIEBwYXJhbSBzdGFydCBzdGFydCBpbmRleFxuICogQHBhcmFtIGNvdW50IG51bWJlciBvZiBjaGFyYWN0ZXJzIFtsZW5ndGhdXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjeWNsZSh4OiBzdHJpbmcsIHN0YXJ0OiBudW1iZXIsIGNvdW50OiBudW1iZXI9eC5sZW5ndGgpOiBzdHJpbmcge1xuICBpZiAoIXggfHwgY291bnQ8PTApIHJldHVybiBcIlwiO1xuICBsZXQgYSA9IHguc2xpY2Uoc3RhcnQsIHN0YXJ0ICsgY291bnQpO1xuICBjb3VudCAgLT0gYS5sZW5ndGg7ICAvLyBzdGFydCA9IGluZGV4KHgsIHN0YXJ0KTtcbiAgY29uc3QgTSA9IE1hdGguZmxvb3IoY291bnQgLyB4Lmxlbmd0aCk7XG4gIGZvciAobGV0IG09MDsgbTxNOyBtKyspXG4gICAgYSArPSB4O1xuICByZXR1cm4gYSArPSB4LnNsaWNlKDAsIGNvdW50ICUgeC5sZW5ndGgpO1xufVxuXG5cbi8qKlxuICogUm90YXRlIGNoYXJhY3RlcnMgaW4gc3RyaW5nLlxuICogQHBhcmFtIHggYSBzdHJpbmdcbiAqIEBwYXJhbSBuIHJvdGF0ZSBhbW91bnQgKCt2ZTogbGVmdCwgLXZlOiByaWdodClcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJvdGF0ZSh4OiBzdHJpbmcsIG46IG51bWJlcik6IHN0cmluZyB7XG4gIGNvbnN0IGkgPSBtb2QobiwgeC5sZW5ndGgpO1xuICByZXR1cm4geC5zbGljZShpKSArIHguc2xpY2UoMCwgaSk7XG59XG5cblxuLy8gZnVuY3Rpb24gcmVwbGFjZVByZWZpeChzdHIsIHByZSwgcmVwKSB7XG4vLyAgIHJldHVybiBzdHIuc3RhcnRzV2l0aChwcmUpPyByZXArc3RyLnN1YnN0cihwcmUubGVuZ3RoKTpzdHI7XG4vLyB9XG4vLyByZXBsYWNlUHJlZml4KCd0aW5tYW4nLCAndGluJywgJ2d1bicpO1xuLy8gLy8gJ2d1bm1hbidcbi8vIHJlcGxhY2VQcmVmaXgoJ211c2NsZW1hbicsICdjbGUnLCAnY2xlZCcpO1xuLy8gLy8gJ211c2NsZW1hbicgKG5vdCBwcmVmaXgpXG4vLyByZXBsYWNlUHJlZml4KCctMS42MDIyZS0xOScsICctJywgJycpO1xuLy8gLy8gJzEuNjAyMmUtMTknXG5cbi8vIGZ1bmN0aW9uIHJlcGxhY2VTdWZmaXgoc3RyLCBzdWYsIHJlcCkge1xuLy8gICByZXR1cm4gc3RyLmVuZHNXaXRoKHN1Zik/IHN0ci5zdWJzdHIoMCwgc3RyLmxlbmd0aC1zdWYubGVuZ3RoKStyZXA6c3RyO1xuLy8gfVxuLy8gcmVwbGFjZVN1ZmZpeCgndGlubWFuJywgJ21hbicsICd3b21hbicpO1xuLy8gLy8gJ3RpbndvbWFuJ1xuLy8gcmVwbGFjZVN1ZmZpeCgnbXVzY2xlbWFuJywgJ2NsZScsICdjbGVkJyk7XG4vLyAvLyAnbXVzY2xlbWFuJ1xuLy8gcmVwbGFjZVN1ZmZpeCgnbGF1Z2hlZCcsICdlZCcsICcnKTtcbi8vIC8vICdsYXVnaCdcblxuLy8gZnVuY3Rpb24qIHVuaXF1ZTxULCBVPVQ+KHg6IEl0ZXJhYmxlPFQ+LCBmYzogY29tcGFyZUZuPFR8VT49bnVsbCwgZm06IG1hcEZuPFQsIFR8VT49bnVsbCk6IEl0ZXJhYmxlSXRlcmF0b3I8VD4ge1xuLy8gICB5aWVsZCogdW5pb24oW10sIHgsIGZjLCBmbSk7XG4vLyB9XG5cbi8vIHN3YXBSYW5nZSgpXG5cbi8vIGltcG9ydCB7Y3V0QXQgYXMgYXJyYXlDdXR9IGZyb20gXCJleHRyYS1hcnJheVwiO1xuXG4vKipcbiAqIEJyZWFrcyBzdHJpbmcgYXQgZ2l2ZW4gaW5kaWNlcy5cbiAqIEBwYXJhbSB4IGEgc3RyaW5nXG4gKiBAcGFyYW0gaXMgc3BsaXQgaW5kaWNlcyAoc29ydGVkKVxuICovXG4vLyBmdW5jdGlvbiBjdXQoeDogc3RyaW5nLCBpczogSXRlcmFibGU8bnVtYmVyPik6IHN0cmluZ1tdIHtcbi8vICAgcmV0dXJuIGFycmF5Q3V0KHggYXMgYW55LCBpcyBhcyBhbnkpIGFzIGFueTtcbi8vIH1cblxuLy8gaW1wb3J0IHtjdXRBdFJpZ2h0IGFzIGFycmF5Q3V0UmlnaHR9IGZyb20gXCJleHRyYS1hcnJheVwiO1xuXG4vKipcbiAqIEJyZWFrcyBzdHJpbmcgYWZ0ZXIgZ2l2ZW4gaW5kaWNlcy5cbiAqIEBwYXJhbSB4IGEgc3RyaW5nXG4gKiBAcGFyYW0gaXMgc3BsaXQgaW5kaWNlcyAoc29ydGVkKVxuICovXG4vLyBmdW5jdGlvbiBjdXRSaWdodCh4OiBzdHJpbmcsIGlzOiBJdGVyYWJsZTxudW1iZXI+KTogc3RyaW5nW10ge1xuLy8gICByZXR1cm4gYXJyYXlDdXRSaWdodCh4IGFzIGFueSwgaXMgYXMgYW55KSBhcyBhbnk7XG4vLyB9XG5cbi8vIGZ1bmN0aW9uIHVuaW9uQ29tcGFyZSh4OiBzdHJpbmcsIHk6IHN0cmluZywgZm46IGFueT1udWxsKTogc3RyaW5nIHtcbi8vICAgLy8gbGV0IGZuID0gZm58fGNtcDtcbi8vICAgbGV0IHMgPSBuZXcgU2V0PHN0cmluZz4oKTtcbi8vICAgbGV0IGEgPSB4O1xuLy8gICB5OiBmb3IobGV0IHYgb2YgeSkge1xuLy8gICAgIGZvcihsZXQgdSBvZiB4KVxuLy8gICAgICAgaWYoZm4odSwgdik9PT0wKSBjb250aW51ZSB5O1xuLy8gICAgIGZvcihsZXQgdSBvZiBzKVxuLy8gICAgICAgaWYoZm4odSwgdik9PT0wKSBjb250aW51ZSB5O1xuLy8gICAgIGEgKz0gdjsgcy5hZGQodik7XG4vLyAgIH1cbi8vICAgcmV0dXJuIGE7XG4vLyB9XG5cbi8vIGZ1bmN0aW9uIHVuaW9uTWFwKHg6IHN0cmluZywgeTogc3RyaW5nLCBmbjogYW55PW51bGwpOiBzdHJpbmcge1xuLy8gICAvLyBsZXQgZm4gPSBmbnx8aWQ7XG4vLyAgIGxldCBzID0gbmV3IFNldCgpO1xuLy8gICBsZXQgYSA9IFwiXCIsIGkgPSAtMSwgaiA9IC0xO1xuLy8gICBmb3IobGV0IHUgb2YgeCkge1xuLy8gICAgIGxldCB1MSA9IGZuKHUsICsraSwgeCk7XG4vLyAgICAgcy5hZGQodTEpOyBhICs9IHU7XG4vLyAgIH1cbi8vICAgZm9yKGxldCB2IG9mIHkpIHtcbi8vICAgICBsZXQgdjEgPSBmbih2LCArK2osIHkpO1xuLy8gICAgIGlmKCFzLmhhcyh2MSkpIHsgcy5hZGQodjEpOyBhICs9IHY7IH1cbi8vICAgfVxuLy8gICByZXR1cm4gYTtcbi8vIH1cblxuLy8gZnVuY3Rpb24gdW5pb25EdWFsKHg6IHN0cmluZywgeTogc3RyaW5nLCBmYzogYW55PW51bGwsIGZtOiBhbnk9bnVsbCk6IHN0cmluZyB7XG4vLyAgIC8vIGxldCBmYyA9IGZjfHxjbXAsIGZtID0gZm18fGlkO1xuLy8gICBsZXQgcyA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuLy8gICBsZXQgYSA9IHgsIGogPSAtMTtcbi8vICAgeTogZm9yKGxldCB2IG9mIHkpIHtcbi8vICAgICBsZXQgdjEgPSBmbSh2LCArK2osIHkpO1xuLy8gICAgIGxldCBpID0gLTE7XG4vLyAgICAgZm9yKGxldCB1IG9mIHgpIHtcbi8vICAgICAgIGxldCB1MSA9IGZtKHUsICsraSwgeCk7XG4vLyAgICAgICBpZihmYyh1MSwgdjEpPT09MCkgY29udGludWUgeTtcbi8vICAgICB9XG4vLyAgICAgbGV0IGkgPSAtMTtcbi8vICAgICBmb3IobGV0IHUgb2Ygcykge1xuLy8gICAgICAgbGV0IHUxID0gZm0odSwgKytpLCB5KTtcbi8vICAgICAgIGlmKGZjKHUxLCB2MSk9PT0wKSBjb250aW51ZSB5O1xuLy8gICAgIH1cbi8vICAgICBhICs9IHY7IHMuYWRkKHYpO1xuLy8gICB9XG4vLyAgIHJldHVybiBhO1xuLy8gfVxuXG4vKipcbiAqIEdpdmVzIGNoYXJhY3RlcnMgcHJlc2VudCBpbiBhbnkgc3RyaW5nLlxuICogQHBhcmFtIHggYSBzdHJpbmdcbiAqIEBwYXJhbSB5IGFub3RoZXIgc3RyaW5nXG4gKiBAcGFyYW0gZmMgY29tcGFyZSBmdW5jdGlvbiAoYSwgYilcbiAqIEBwYXJhbSBmbSBtYXAgZnVuY3Rpb24gKHYsIGksIHgpXG4gKi9cbi8vIGZ1bmN0aW9uIHVuaW9uKHg6IHN0cmluZywgeTogc3RyaW5nLCBmYzogYW55PW51bGwsIGZtOiBhbnk9bnVsbCk6IHN0cmluZyB7XG4vLyAgIGlmKGZjKSByZXR1cm4gdW5pb25EdWFsKHgsIHksIGZjLCBmbSk7XG4vLyAgIGVsc2UgcmV0dXJuIHVuaW9uTWFwKHgsIHksIGZtKTtcbi8vIH1cbi8vI2VuZHJlZ2lvblxuXG5cblxuLy8jcmVnaW9uIE5HUkFNU1xuLyoqXG4gKiBHZXQgbi1ncmFtcyBvZiBhIHN0cmluZy5cbiAqIEBwYXJhbSB4IGEgc3RyaW5nXG4gKiBAcGFyYW0gbiBuLWdyYW0gbGVuZ3RoXG4gKiBAcmV0dXJucyBbeFswOm5dLCB4WzE6bisxXSwgLi4uXVxuICogQGV4YW1wbGVcbiAqIGBgYGphdmFzY3JpcHRcbiAqIHhzdHJpbmcubmdyYW1zKCdjYXJkJywgMik7XG4gKiAvLyDihpIgWydjYScsICdhcicsICdyZCddXG4gKlxuICogeHN0cmluZy5uZ3JhbXMoJ3RyaXBsZS1oJywgMyk7XG4gKiAvLyDihpIgWyd0cmknLCAncmlwJywgJ2lwbCcsICdwbGUnLCAnbGUtJywgJ2UtaCddXG4gKlxuICogeHN0cmluZy5uZ3JhbXMoJ2Jyb2NrbGVzbmVyJywgMTApO1xuICogLy8g4oaSIFsnYnJvY2tsZXNuZScsICdyb2NrbGVzbmVyJ11cbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gbmdyYW1zKHg6IHN0cmluZywgbjogbnVtYmVyKTogc3RyaW5nW10ge1xuICBjb25zdCBhID0gW107XG4gIGZvciAobGV0IGk9MCwgST14Lmxlbmd0aC1uKzE7IGk8STsgaSsrKVxuICAgIGFbaV0gPSB4LnN1YnN0cmluZyhpLCBpK24pO1xuICByZXR1cm4gYTtcbn1cblxuXG4vKipcbiAqIEZpbmQgdW5pcXVlIG4tZ3JhbXMgb2YgYSBzdHJpbmcuXG4gKiBAcGFyYW0geCBhIHN0cmluZ1xuICogQHBhcmFtIG4gbi1ncmFtIGxlbmd0aFxuICogQHJldHVybnMgU2V0IFxce2fhtaJcXH0gfCBn4bWiID0gaeG1l8qwIG4tZ3JhbVxuICovXG5leHBvcnQgZnVuY3Rpb24gdW5pcXVlTmdyYW1zKHg6IHN0cmluZywgbjogbnVtYmVyKTogU2V0PHN0cmluZz4ge1xuICBjb25zdCBhOiBTZXQ8c3RyaW5nPiA9IG5ldyBTZXQoKTtcbiAgZm9yIChsZXQgaT0wLCBJPXgubGVuZ3RoLW4rMTsgaTxJOyBpKyspXG4gICAgYS5hZGQoeC5zdWJzdHJpbmcoaSwgaStuKSk7XG4gIHJldHVybiBhO1xufVxuXG5cbi8qKlxuICogQ291bnQgdGhlIHRvdGFsIG51bWJlciBvZiBuLWdyYW1zIG9mIGEgc3RyaW5nLlxuICogQHBhcmFtIHggYSBzdHJpbmdcbiAqIEBwYXJhbSBuIG4tZ3JhbSBsZW5ndGhcbiAqIEByZXR1cm5zIHxn4bWifCB8IGfhtaIgPSBp4bWXyrAgbi1ncmFtXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjb3VudE5ncmFtcyh4OiBzdHJpbmcsIG46IG51bWJlcik6IG51bWJlciB7XG4gIHJldHVybiBNYXRoLm1heCgwLCB4Lmxlbmd0aC1uKzEpO1xufVxuXG5cbi8qKlxuICogQ291bnQgdGhlIHRvdGFsIG51bWJlciBvZiB1bmlxdWUgbi1ncmFtcyBvZiBhIHN0cmluZy5cbiAqIEBwYXJhbSB4IGEgc3RyaW5nXG4gKiBAcGFyYW0gbiBuLWdyYW0gbGVuZ3RoXG4gKiBAcmV0dXJucyB8U2V0IFxce2fhtaJcXH18IHwgZ+G1oiA9IGnhtZfKsCBuLWdyYW1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNvdW50VW5pcXVlTmdyYW1zKHg6IHN0cmluZywgbjogbnVtYmVyKTogbnVtYmVyIHtcbiAgcmV0dXJuIHVuaXF1ZU5ncmFtcyh4LCBuKS5zaXplO1xufVxuXG5cbi8qKlxuICogQ291bnQgZWFjaCBuLWdyYW0gb2YgYSBzdHJpbmcuXG4gKiBAcGFyYW0geCBhIHN0cmluZ1xuICogQHBhcmFtIG4gbi1ncmFtIGxlbmd0aFxuICogQHJldHVybnMgTWFwIFxce2fhtaI6IGNvdW50KGfhtaIpXFx9IHwgZ+G1oiA9IGnhtZfKsCBuLWdyYW1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNvdW50RWFjaE5ncmFtKHg6IHN0cmluZywgbjogbnVtYmVyKTogTWFwPHN0cmluZywgbnVtYmVyPiB7XG4gIGNvbnN0IGE6IE1hcDxzdHJpbmcsIG51bWJlcj4gPSBuZXcgTWFwKCk7XG4gIGZvciAobGV0IGk9MCwgST14Lmxlbmd0aC1uKzE7IGk8STsgaSsrKSB7XG4gICAgY29uc3QgZyA9IHguc3Vic3RyaW5nKGksIGkrbik7XG4gICAgYS5zZXQoZywgKGEuZ2V0KGcpIHx8IDApICsgMSk7XG4gIH1cbiAgcmV0dXJuIGE7XG59XG5cblxuLyoqXG4gKiBHZXQgbWF0Y2hpbmcgbi1ncmFtcyBiZXR3ZWVuIHN0cmluZ3MuXG4gKiBAcGFyYW0geCBhIHN0cmluZ1xuICogQHBhcmFtIHkgYW5vdGhlciBzdHJpbmdcbiAqIEBwYXJhbSBuIG4tZ3JhbSBsZW5ndGhcbiAqIEByZXR1cm5zIFtn4bWiXSB8IGfhtaIgPSBp4bWXyrAgbWF0Y2hpbmcgbi1ncmFtXG4gKiBAZXhhbXBsZVxuICogYGBgamF2YXNjcmlwdFxuICogeHN0cmluZy5tYXRjaGluZ05ncmFtcygnd29ybScsICdzdG9ybScsIDIpO1xuICogLy8g4oaSIFsnb3InLCAncm0nXVxuICpcbiAqIHhzdHJpbmcubWF0Y2hpbmdOZ3JhbXMoJ2FzdHJvbmF1dCcsICdhc3Ryb25vbWVyJywgMyk7XG4gKiAvLyDihpIgWydhc3QnLCAnc3RyJywgJ3RybycsICdyb24nXVxuICpcbiAqIHhzdHJpbmcubWF0Y2hpbmdOZ3JhbXMoJ2NvY29udXQnLCAnY290dG9uJywgMik7XG4gKiAvLyDihpIgWydjbycsICdvbiddXG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1hdGNoaW5nTmdyYW1zKHg6IHN0cmluZywgeTogc3RyaW5nLCBuOiBudW1iZXIpOiBzdHJpbmdbXSB7XG4gIGNvbnN0IGdzID0gY291bnRFYWNoTmdyYW0oeCwgbiksIGEgPSBbXTtcbiAgZm9yIChsZXQgaT0wLCBJPXkubGVuZ3RoLW4rMTsgaTxJOyBpKyspIHtcbiAgICBjb25zdCBnID0geS5zdWJzdHJpbmcoaSwgaStuKTtcbiAgICBjb25zdCBjID0gZ3MuZ2V0KGcpIHx8IDA7XG4gICAgaWYgKGMpIHsgYS5wdXNoKGcpOyBncy5zZXQoZywgYy0xKTsgfVxuICB9XG4gIHJldHVybiBhO1xufVxuXG5cbi8qKlxuICogR2V0IHVuaXF1ZSBtYXRjaGluZyBuLWdyYW1zIGJldHdlZW4gc3RyaW5ncy5cbiAqIEBwYXJhbSB4IGEgc3RyaW5nXG4gKiBAcGFyYW0geSBhbm90aGVyIHN0cmluZ1xuICogQHBhcmFtIG4gbi1ncmFtIGxlbmd0aFxuICogQHJldHVybnMgU2V0IFxce2fhtaJcXH0gfCBn4bWiID0gaeG1l8qwIHVuaXF1ZSBtYXRjaGluZyBuLWdyYW1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHVuaXF1ZU1hdGNoaW5nTmdyYW1zKHg6IHN0cmluZywgeTogc3RyaW5nLCBuOiBudW1iZXIpOiBTZXQ8c3RyaW5nPiB7XG4gIGNvbnN0IGE6IFNldDxzdHJpbmc+ID0gbmV3IFNldCgpO1xuICBjb25zdCBncyA9IHVuaXF1ZU5ncmFtcyh4LCBuKTtcbiAgZm9yIChsZXQgaT0wLCBJPXkubGVuZ3RoLW4rMTsgaTxJOyBpKyspIHtcbiAgICBjb25zdCBnID0geS5zdWJzdHJpbmcoaSwgaStuKTtcbiAgICBpZiAoZ3MuaGFzKGcpKSBhLmFkZChnKTtcbiAgfVxuICByZXR1cm4gYTtcbn1cblxuXG4vKipcbiAqIENvdW50IHRoZSB0b3RhbCBudW1iZXIgb2YgbWF0Y2hpbmcgbi1ncmFtcyBiZXR3ZWVuIHN0cmluZ3MuXG4gKiBAcGFyYW0geCBhIHN0cmluZ1xuICogQHBhcmFtIHkgYW5vdGhlciBzdHJpbmdcbiAqIEBwYXJhbSBuIG4tZ3JhbSBsZW5ndGhcbiAqIEByZXR1cm5zIHxbZ+G1ol18IHwgZ+G1oiA9IGnhtZfKsCBtYXRjaGluZyBuLWdyYW1cbiAqIEBleGFtcGxlXG4gKiBgYGBqYXZhc2NyaXB0XG4gKiB4c3RyaW5nLmNvdW50TWF0Y2hpbmdOZ3JhbXMoJ3dvcm0nLCAnc3Rvcm0nLCAyKTtcbiAqIC8vIOKGkiAyICgnb3InLCAncm0nKVxuICpcbiAqIHhzdHJpbmcuY291bnRNYXRjaGluZ05ncmFtcygnYXN0cm9uYXV0JywgJ2FzdHJvbm9tZXInLCAzKTtcbiAqIC8vIOKGkiA0ICgnYXN0JywgJ3N0cicsICd0cm8nLCAncm9uJylcbiAqXG4gKiB4c3RyaW5nLmNvdW50TWF0Y2hpbmdOZ3JhbXMoJ2NvY29udXQnLCAnY290dG9uJywgMik7XG4gKiAvLyDihpIgMiAoJ2NvJywgJ29uJylcbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gY291bnRNYXRjaGluZ05ncmFtcyh4OiBzdHJpbmcsIHk6IHN0cmluZywgbjogbnVtYmVyKTogbnVtYmVyIHtcbiAgY29uc3QgZ3MgPSBjb3VudEVhY2hOZ3JhbSh4LCBuKTsgbGV0IGEgPSAwO1xuICBmb3IgKGxldCBpPTAsIEk9eS5sZW5ndGgtbisxOyBpPEk7IGkrKykge1xuICAgIGNvbnN0IGcgPSB5LnN1YnN0cmluZyhpLCBpK24pO1xuICAgIGNvbnN0IGMgPSBncy5nZXQoZykgfHwgMDtcbiAgICBpZiAoYykgeyBhKys7IGdzLnNldChnLCBjLTEpOyB9XG4gIH1cbiAgcmV0dXJuIGE7XG59XG5cblxuLyoqXG4gKiBDb3VudCBlYWNoIG1hdGNoaW5nIG4tZ3JhbSBiZXR3ZWVuIHN0cmluZ3MuXG4gKiBAcGFyYW0geCBhIHN0cmluZ1xuICogQHBhcmFtIHkgYW5vdGhlciBzdHJpbmdcbiAqIEBwYXJhbSBuIG4tZ3JhbSBsZW5ndGhcbiAqIEByZXR1cm5zIE1hcCBcXHtn4bWiOiBjb3VudChn4bWiKVxcfSB8IGfhtaIgPSBp4bWXyrAgbWF0Y2hpbmcgbi1ncmFtXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjb3VudEVhY2hNYXRjaGluZ05ncmFtKHg6IHN0cmluZywgeTogc3RyaW5nLCBuOiBudW1iZXIpOiBNYXA8c3RyaW5nLCBudW1iZXI+IHtcbiAgY29uc3QgYTogTWFwPHN0cmluZywgbnVtYmVyPiA9IG5ldyBNYXAoKTtcbiAgY29uc3QgZ3MgPSBjb3VudEVhY2hOZ3JhbSh4LCBuKTtcbiAgZm9yIChsZXQgaT0wLCBJPXkubGVuZ3RoLW4rMTsgaTxJOyBpKyspIHtcbiAgICBjb25zdCBnID0geS5zdWJzdHJpbmcoaSwgaStuKTtcbiAgICBjb25zdCBjID0gZ3MuZ2V0KGcpIHx8IDA7XG4gICAgaWYgKGMpIHsgYS5zZXQoZywgKGEuZ2V0KGcpIHx8IDApICsgMSk7IGdzLnNldChnLCBjLTEpOyB9XG4gIH1cbiAgcmV0dXJuIGE7XG59XG5cblxuLyoqXG4gKiBDb3VudCB0aGUgdG90YWwgbnVtYmVyIG9mIHVuaXF1ZSBtYXRjaGluZyBuLWdyYW1zIGJldHdlZW4gc3RyaW5ncy5cbiAqIEBwYXJhbSB4IGEgc3RyaW5nXG4gKiBAcGFyYW0geSBhbm90aGVyIHN0cmluZ1xuICogQHBhcmFtIG4gbi1ncmFtIGxlbmd0aFxuICogQHJldHVybnMgfFNldCBcXHtn4bWiXFx9fCB8IGfhtaIgPSBp4bWXyrAgdW5pcXVlIG1hdGNoaW5nIG4tZ3JhbVxuICovXG4gZXhwb3J0IGZ1bmN0aW9uIGNvdW50VW5pcXVlTWF0Y2hpbmdOZ3JhbXMoeDogc3RyaW5nLCB5OiBzdHJpbmcsIG46IG51bWJlcik6IG51bWJlciB7XG4gIGNvbnN0IGdzID0gdW5pcXVlTmdyYW1zKHgsIG4pOyBsZXQgYSA9IDA7XG4gIGZvciAobGV0IGk9MCwgST15Lmxlbmd0aC1uKzE7IGk8STsgaSsrKSB7XG4gICAgY29uc3QgZyA9IHkuc3Vic3RyaW5nKGksIGkrbik7XG4gICAgaWYgKGdzLmhhcyhnKSkgeyBhKys7IGdzLmRlbGV0ZShnKTsgfVxuICB9XG4gIHJldHVybiBhO1xufVxuLy8jZW5kcmVnaW9uXG5cblxuXG5cbi8vI3JlZ2lvbiBESVNUQU5DRVxuLyoqXG4gKiBHZXQgZXVjbGlkZWFuIGRpc3RhbmNlIGJldHdlZW4gc3RyaW5ncy5cbiAqIEBwYXJhbSB4IGEgc3RyaW5nXG4gKiBAcGFyYW0geSBhbm90aGVyIHN0cmluZ1xuICogQHJldHVybnMgZXVjbGlkZWFuIGRpc3RhbmNlXG4gKiBAZXhhbXBsZVxuICogYGBgamF2YXNjcmlwdFxuICogeHN0cmluZy5ldWNsaWRlYW5EaXN0YW5jZSgnYScsICdiJyk7XG4gKiAvLyDihpIgMVxuICpcbiAqIHhzdHJpbmcuZXVjbGlkZWFuRGlzdGFuY2UoJ2xvZ28nLCAncG9nbycpO1xuICogLy8g4oaSIDRcbiAqXG4gKiB4c3RyaW5nLmV1Y2xpZGVhbkRpc3RhbmNlKCdkb2N0b3InLCAnYnJva2VyJyk7XG4gKiAvLyDihpIgMTguMzg0Nzc2MzEwODUwMjM1XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGV1Y2xpZGVhbkRpc3RhbmNlKHg6IHN0cmluZywgeTogc3RyaW5nKTogbnVtYmVyIHtcbiAgbGV0IGEgPSAwO1xuICBmb3IgKGxldCBpPTAsIEk9TWF0aC5tYXgoeC5sZW5ndGgsIHkubGVuZ3RoKTsgaTxJOyBpKyspIHtcbiAgICBjb25zdCBkID0gKHguY29kZVBvaW50QXQoaSkgfHwgMCkgLSAoeS5jb2RlUG9pbnRBdChpKSB8fCAwKTtcbiAgICBhICs9IGQgKiBkO1xuICB9XG4gIHJldHVybiBNYXRoLnNxcnQoYSk7XG59XG4vLyBub3JtYWxpemVkRXVjbGlkZWFuRGlzdGFuY2UoKT9cblxuXG4vKipcbiAqIEdldCBoYW1taW5nIGRpc3RhbmNlIGJldHdlZW4gc3RyaW5ncy5cbiAqIEBwYXJhbSB4IGEgc3RyaW5nXG4gKiBAcGFyYW0geSBhbm90aGVyIHN0cmluZ1xuICogQHJldHVybnMgaGFtbWluZyBkaXN0YW5jZVxuICogQGV4YW1wbGVcbiAqIGBgYGphdmFzY3JpcHRcbiAqIHhzdHJpbmcuaGFtbWluZ0Rpc3RhbmNlKCdyb3dhbicsICdyYXZlbicpO1xuICogLy8g4oaSIDNcbiAqXG4gKiB4c3RyaW5nLmhhbW1pbmdEaXN0YW5jZSgnYXRraW5zb24nLCAnYXRraW5zb24nKTtcbiAqIC8vIOKGkiAwXG4gKlxuICogeHN0cmluZy5oYW1taW5nRGlzdGFuY2UoJ2JlYW4nLCAnZ3JlZW4nKTtcbiAqIC8vIOKGkiBOYU4gKHN0cmluZ3MgYXJlIG9mIGRpZmZlcmVudCBsZW5ndGgpXG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGhhbW1pbmdEaXN0YW5jZSh4OiBzdHJpbmcsIHk6IHN0cmluZyk6IG51bWJlciB7XG4gIGxldCBhID0gMDtcbiAgZm9yIChsZXQgaT0wLCBJPU1hdGgubWF4KHgubGVuZ3RoLCB5Lmxlbmd0aCk7IGk8STsgaSsrKVxuICAgIGlmICh4LmNoYXJBdChpKSAhPT0geS5jaGFyQXQoaSkpIGErKztcbiAgcmV0dXJuIGE7XG59XG5cblxuLyoqXG4gKiBHZXQgamFjY2FyZCBpbmRleCBiZXR3ZWVuIHN0cmluZ3MuXG4gKiBAcGFyYW0geCBhIHN0cmluZ1xuICogQHBhcmFtIHkgYW5vdGhlciBzdHJpbmdcbiAqIEBwYXJhbSBuIG4tZ3JhbSBsZW5ndGhcbiAqIEByZXR1cm5zIHxYIOKIqSBZfC98WCDiiKogWXwgfCBYLFkgPSBuLWdyYW1zIG9mIHgseVxuICogQGV4YW1wbGVcbiAqIGBgYGphdmFzY3JpcHRcbiAqIHhzdHJpbmcuamFjY2FyZEluZGV4KCdwb2NrZXQnLCAncG9ja2V0Jyk7XG4gKiAvLyDihpIgMVxuICpcbiAqIHhzdHJpbmcuamFjY2FyZEluZGV4KCdtb25zdGVyJywgJ3JvY2tldCcpO1xuICogLy8g4oaSIDBcbiAqXG4gKiB4c3RyaW5nLmphY2NhcmRJbmRleCgncGlrYWNodScsICdyYWljaHUnLCAzKTtcbiAqIC8vIOKGkiAwLjEyNVxuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBqYWNjYXJkSW5kZXgoeDogc3RyaW5nLCB5OiBzdHJpbmcsIG46IG51bWJlcik6IG51bWJlciB7XG4gIGNvbnN0IGd4ID0gY291bnROZ3JhbXMoeCwgbik7XG4gIGNvbnN0IGd5ID0gY291bnROZ3JhbXMoeSwgbik7XG4gIGNvbnN0IGcgID0gY291bnRNYXRjaGluZ05ncmFtcyh4LCB5LCBuKTtcbiAgcmV0dXJuIGd4K2d5PyBnLyhneCtneS1nKSA6IDE7XG59XG5cblxuLyoqXG4gKiBHZXQgamFjY2FyZCBkaXN0YW5jZSBiZXR3ZWVuIHN0cmluZ3MuXG4gKiBAcGFyYW0geCBhIHN0cmluZ1xuICogQHBhcmFtIHkgYW5vdGhlciBzdHJpbmdcbiAqIEBwYXJhbSBuIG4tZ3JhbSBsZW5ndGhcbiAqIEByZXR1cm5zIDEgLSBqYWNjYXJkSW5kZXgoeCwgeSlcbiAqIEBleGFtcGxlXG4gKiBgYGBqYXZhc2NyaXB0XG4gKiB4c3RyaW5nLmphY2NhcmREaXN0YW5jZSgncG9ja2V0JywgJ3BvY2tldCcpO1xuICogLy8g4oaSIDBcbiAqXG4gKiB4c3RyaW5nLmphY2NhcmREaXN0YW5jZSgnbW9uc3RlcicsICdyb2NrZXQnKTtcbiAqIC8vIOKGkiAxXG4gKlxuICogeHN0cmluZy5qYWNjYXJkRGlzdGFuY2UoJ3Bpa2FjaHUnLCAncmFpY2h1JywgMyk7XG4gKiAvLyDihpIgMC44NzVcbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gamFjY2FyZERpc3RhbmNlKHg6IHN0cmluZywgeTogc3RyaW5nLCBuOiBudW1iZXIpOiBudW1iZXIge1xuICByZXR1cm4gMSAtIGphY2NhcmRJbmRleCh4LCB5LCBuKTtcbn1cblxuXG4vKipcbiAqIEdldCBTw7hyZW5zZW4tRGljZSBpbmRleCBiZXR3ZWVuIHN0cmluZ3MuXG4gKiBAcGFyYW0geCBhIHN0cmluZ1xuICogQHBhcmFtIHkgYW5vdGhlciBzdHJpbmdcbiAqIEBwYXJhbSBuIG4tZ3JhbSBsZW5ndGhcbiAqIEByZXR1cm5zIDJ8WCDiiKkgWXwvKHxYfCArIHxZfCkgfCBYLFkgPSBuLWdyYW1zIG9mIHgseVxuICogQGV4YW1wbGVcbiAqIGBgYGphdmFzY3JpcHRcbiAqIHhzdHJpbmcuc29yZW5zZW5EaWNlSW5kZXgoJ3BvY2tldCcsICdwb2NrZXQnKTtcbiAqIC8vIOKGkiAxXG4gKlxuICogeHN0cmluZy5zb3JlbnNlbkRpY2VJbmRleCgnbW9uc3RlcicsICdyb2NrZXQnKTtcbiAqIC8vIOKGkiAwXG4gKlxuICogeHN0cmluZy5zb3JlbnNlbkRpY2VJbmRleCgncGlrYWNodScsICdyYWljaHUnLCAzKTtcbiAqIC8vIOKGkiAwLjIyMjIyMjIyMjIyMjIyMjJcbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gc29yZW5zZW5EaWNlSW5kZXgoeDogc3RyaW5nLCB5OiBzdHJpbmcsIG46IG51bWJlcik6IG51bWJlciB7XG4gIGNvbnN0IGd4ID0gY291bnROZ3JhbXMoeCwgbik7XG4gIGNvbnN0IGd5ID0gY291bnROZ3JhbXMoeSwgbik7XG4gIGNvbnN0IGcgID0gY291bnRNYXRjaGluZ05ncmFtcyh4LCB5LCBuKTtcbiAgcmV0dXJuIGd4K2d5PyAoMipnKS8oZ3grZ3kpIDogMTtcbn1cblxuXG4vKipcbiAqIEdldCBTw7hyZW5zZW4tRGljZSBkaXN0YW5jZSBiZXR3ZWVuIHN0cmluZ3MuXG4gKiBAcGFyYW0geCBhIHN0cmluZ1xuICogQHBhcmFtIHkgYW5vdGhlciBzdHJpbmdcbiAqIEBwYXJhbSBuIG4tZ3JhbSBsZW5ndGhcbiAqIEByZXR1cm5zIDEgLSBzb3JlbnNlbkRpY2VJbmRleCh4LCB5KVxuICogQGV4YW1wbGVcbiAqIGBgYGphdmFzY3JpcHRcbiAqIHhzdHJpbmcuc29yZW5zZW5EaWNlRGlzdGFuY2UoJ3BvY2tldCcsICdwb2NrZXQnKTtcbiAqIC8vIOKGkiAwXG4gKlxuICogeHN0cmluZy5zb3JlbnNlbkRpY2VEaXN0YW5jZSgnbW9uc3RlcicsICdyb2NrZXQnKTtcbiAqIC8vIOKGkiAxXG4gKlxuICogeHN0cmluZy5zb3JlbnNlbkRpY2VEaXN0YW5jZSgncGlrYWNodScsICdyYWljaHUnLCAzKTtcbiAqIC8vIOKGkiAwLjc3Nzc3Nzc3Nzc3Nzc3NzhcbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gc29yZW5zZW5EaWNlRGlzdGFuY2UoeDogc3RyaW5nLCB5OiBzdHJpbmcsIG46IG51bWJlcik6IG51bWJlciB7XG4gIHJldHVybiAxIC0gc29yZW5zZW5EaWNlSW5kZXgoeCwgeSwgbik7XG59XG5cblxuLyoqXG4gKiBHZXQgVHZlcnNreSBpbmRleCBiZXR3ZWVuIHN0cmluZ3MuXG4gKiBAcGFyYW0geCBhIHN0cmluZ1xuICogQHBhcmFtIHkgYW5vdGhlciBzdHJpbmdcbiAqIEBwYXJhbSBuIG4tZ3JhbSBsZW5ndGhcbiAqIEBwYXJhbSBhIGFscGhhIFsxXVxuICogQHBhcmFtIGIgYmV0YSBbMV1cbiAqIEByZXR1cm5zIHxYIOKIqSBZfC8ofFgg4oipIFl8ICsgzrF8WCBcXCBZfCArIM6yfFkgXFwgWHwpIHwgWCxZID0gbi1ncmFtcyBvZiB4LHlcbiAqIEBleGFtcGxlXG4gKiBgYGBqYXZhc2NyaXB0XG4gKiB4c3RyaW5nLnR2ZXJza3lJbmRleCgncG9ja2V0JywgJ3BvY2tldCcpO1xuICogLy8g4oaSIDFcbiAqXG4gKiB4c3RyaW5nLnR2ZXJza3lJbmRleCgnbW9uc3RlcicsICdyb2NrZXQnKTtcbiAqIC8vIOKGkiAwXG4gKlxuICogeHN0cmluZy50dmVyc2t5SW5kZXgoJ3Bpa2FjaHUnLCAncmFpY2h1JywgMC4yLCAwLjQsIDMpO1xuICogLy8g4oaSIDAuMzMzMzMzMzMzMzMzMzMzM1xuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0dmVyc2t5SW5kZXgoeDogc3RyaW5nLCB5OiBzdHJpbmcsIG46IG51bWJlciwgYTogbnVtYmVyPTEsIGI6IG51bWJlcj0xKTogbnVtYmVyIHtcbiAgY29uc3QgZ3ggPSBjb3VudE5ncmFtcyh4LCBuKTtcbiAgY29uc3QgZ3kgPSBjb3VudE5ncmFtcyh5LCBuKTtcbiAgY29uc3QgZyAgPSBjb3VudE1hdGNoaW5nTmdyYW1zKHgsIHksIG4pO1xuICByZXR1cm4gZ3grZ3k/IGcvKGcgKyBhKihneC1nKSArIGIqKGd5LWcpKSA6IDE7XG59XG5cblxuLyoqXG4gKiBHZXQgVHZlcnNreSBkaXN0YW5jZSBiZXR3ZWVuIHN0cmluZ3MuXG4gKiBAcGFyYW0geCBhIHN0cmluZ1xuICogQHBhcmFtIHkgYW5vdGhlciBzdHJpbmdcbiAqIEBwYXJhbSBuIG4tZ3JhbSBsZW5ndGhcbiAqIEBwYXJhbSBhIGFscGhhIFsxXVxuICogQHBhcmFtIGIgYmV0YSBbMV1cbiAqIEByZXR1cm5zIDEgLSB0dmVyc2t5SW5kZXgoeCwgeSlcbiAqIEBleGFtcGxlXG4gKiBgYGBqYXZhc2NyaXB0XG4gKiB4c3RyaW5nLnR2ZXJza3lEaXN0YW5jZSgncG9ja2V0JywgJ3BvY2tldCcpO1xuICogLy8g4oaSIDBcbiAqXG4gKiB4c3RyaW5nLnR2ZXJza3lEaXN0YW5jZSgnbW9uc3RlcicsICdyb2NrZXQnKTtcbiAqIC8vIOKGkiAxXG4gKlxuICogeHN0cmluZy50dmVyc2t5RGlzdGFuY2UoJ3Bpa2FjaHUnLCAncmFpY2h1JywgMC4yLCAwLjQsIDMpO1xuICogLy8g4oaSIDAuNjY2NjY2NjY2NjY2NjY2N1xuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0dmVyc2t5RGlzdGFuY2UoeDogc3RyaW5nLCB5OiBzdHJpbmcsIG46IG51bWJlciwgYTogbnVtYmVyPTEsIGI6IG51bWJlcj0xKTogbnVtYmVyIHtcbiAgcmV0dXJuIDEgLSB0dmVyc2t5SW5kZXgoeCwgeSwgbiwgYSwgYik7XG59XG5cblxuLyoqXG4gKiBHZXQgbWF0Y2hpbmcgY2hhcmFjdGVycyBiZXR3ZWVuIHN0cmluZ3MsIHdpdGhpbiBhIHNwZWNpZmllZCBkaXN0YW5jZS5cbiAqIEBwYXJhbSB4IGEgc3RyaW5nXG4gKiBAcGFyYW0geSBhbm90aGVyIHN0cmluZ1xuICogQHBhcmFtIGQgbWF4aW11bSBkaXN0YW5jZSBiZXR3ZWVuIG1hdGNoaW5nIGNoYXJhY3RlcnNcbiAqIEByZXR1cm5zIFttYXRjaGluZyBjaGFyYWN0ZXJzIGluIHgsIG1hdGNoaW5nIGNoYXJhY3RlcnMgaW4geV1cbiAqL1xuZnVuY3Rpb24gcmFuZ2VkTWF0Y2hlcyh4OiBzdHJpbmcsIHk6IHN0cmluZywgZDogbnVtYmVyKTogW3N0cmluZywgc3RyaW5nXSB7XG4gIC8vIDEuIFByZXBhcmUgc3RyaWtlLW9mZiBidWZmZXJcbiAgbGV0IG14ID0gXCJcIiwgbXkgPSBcIlwiO1xuICBjb25zdCBieTogKHN0cmluZyB8IG51bGwpW10gPSBBcnJheS5mcm9tKHkpO1xuICAvLyAyLiBHZXQgbWF0Y2hlcyBpbiBmaXJzdCBzdHJpbmdcbiAgZm9yIChsZXQgaT0wLCBJPXgubGVuZ3RoOyBpPEk7IGkrKykge1xuICAgIGxldCBqID0gYnkubGFzdEluZGV4T2YoeC5jaGFyQXQoaSksIGkpO1xuICAgIGlmIChqPDAgfHwgaS1qPmQpIGogPSBieS5pbmRleE9mKHguY2hhckF0KGkpLCBpKzEpO1xuICAgIGlmIChqPDAgfHwgai1pPmQpIGNvbnRpbnVlO1xuICAgIG14ICs9IHguY2hhckF0KGkpO1xuICAgIGJ5W2pdID0gbnVsbDtcbiAgfVxuICAvLyAzLiBHZXQgbWF0Y2hlcyBpbiBzZWNvbmQgc3RyaW5nXG4gIGZvciAobGV0IGo9MCwgSj15Lmxlbmd0aDsgajxKOyBqKyspXG4gICAgaWYgKGJ5W2pdPT1udWxsKSBteSArPSB5LmNoYXJBdChqKTtcbiAgcmV0dXJuIFtteCwgbXldO1xufVxuLy8gY291bnRSYW5nZWRNYXRjaGVzKCk/XG5cblxuLyoqXG4gKiBHZXQgSmFybyBzaW1pbGFyaXR5IGJldHdlZW4gc3RyaW5ncy5cbiAqIEBwYXJhbSB4IGEgc3RyaW5nXG4gKiBAcGFyYW0geSBhbm90aGVyIHN0cmluZ1xuICogQHJldHVybnMgKG0vfHh8ICsgbS98eXwgKyAobS10KS9tKS8zIHwgbSA9ICMgbWF0Y2hlcywgdCA9ICMgdHJhbnNwb3NpdGlvbnNcbiAqIEBleGFtcGxlXG4gKiBgYGBqYXZhc2NyaXB0XG4gKiB4c3RyaW5nLmphcm9TaW1pbGFyaXR5KCdubycsICdtYXRjaCcpO1xuICogLy8g4oaSIDBcbiAqXG4gKiB4c3RyaW5nLmphcm9TaW1pbGFyaXR5KCd0ZWFwb3QnLCAndGVhcG90Jyk7XG4gKiAvLyDihpIgMVxuICpcbiAqIHhzdHJpbmcuamFyb1NpbWlsYXJpdHkoJ2plbGx5ZmlzaCcsICdzbWVsbHlmaXNoJyk7XG4gKiAvLyDihpIgMC44OTYyOTYyOTYyOTYyOTY0XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGphcm9TaW1pbGFyaXR5KHg6IHN0cmluZywgeTogc3RyaW5nKTogbnVtYmVyIHtcbiAgY29uc3QgWCA9IHgubGVuZ3RoLCBZID0geS5sZW5ndGg7XG4gIGNvbnN0IGQgPSBNYXRoLmZsb29yKE1hdGgubWF4KFgsIFkpLzIpIC0gMTtcbiAgY29uc3QgW214LCBteV0gPSByYW5nZWRNYXRjaGVzKHgsIHksIGQpLCBtID0gbXgubGVuZ3RoO1xuICBjb25zdCB0ID0gaGFtbWluZ0Rpc3RhbmNlKG14LCBteSkvMjtcbiAgcmV0dXJuIG0/IChtL1ggKyBtL1kgKyAobS10KS9tKS8zIDogMDtcbn1cblxuXG4vKipcbiAqIEdldCBKYXJvIGRpc3RhbmNlIGJldHdlZW4gc3RyaW5ncy5cbiAqIEBwYXJhbSB4IGEgc3RyaW5nXG4gKiBAcGFyYW0geSBhbm90aGVyIHN0cmluZ1xuICogQHJldHVybnMgMSAtIGphcm9TaW1pbGFyaXR5KHgsIHkpXG4gKiBAZXhhbXBsZVxuICogYGBgamF2YXNjcmlwdFxuICogeHN0cmluZy5qYXJvRGlzdGFuY2UoJ25vJywgJ21hdGNoJyk7XG4gKiAvLyDihpIgMVxuICpcbiAqIHhzdHJpbmcuamFyb0Rpc3RhbmNlKCd0ZWFwb3QnLCAndGVhcG90Jyk7XG4gKiAvLyDihpIgMFxuICpcbiAqIHhzdHJpbmcuamFyb0Rpc3RhbmNlKCdqZWxseWZpc2gnLCAnc21lbGx5ZmlzaCcpO1xuICogLy8g4oaSIDAuMTAzNzAzNzAzNzAzNzAzNjNcbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gamFyb0Rpc3RhbmNlKHg6IHN0cmluZywgeTogc3RyaW5nKTogbnVtYmVyIHtcbiAgcmV0dXJuIDEgLSBqYXJvU2ltaWxhcml0eSh4LCB5KTtcbn1cblxuXG4vKipcbiAqIEdldCBKYXJvLVdpbmtsZXIgc2ltaWxhcml0eSBiZXR3ZWVuIHN0cmluZ3MuXG4gKiBAcGFyYW0geCBhIHN0cmluZ1xuICogQHBhcmFtIHkgYW5vdGhlciBzdHJpbmdcbiAqIEBwYXJhbSBwIHNjYWxpbmcgZmFjdG9yIGZvciBjb21tb24gcHJlZml4ICgwLjEgLSAwLjI1KSBbMC4xXVxuICogQHJldHVybnMgc2lt4rG8ICsg4oSTcCgxIC0gc2lt4rG8KSB8IHNpbeKxvCA9IGphcm8gc2ltaWxhcml0eSwg4oSTID0gfGxvbmdlc3QgY29tbW9uIHByZWZpeHxcbiAqIEBleGFtcGxlXG4gKiBgYGBqYXZhc2NyaXB0XG4gKiB4c3RyaW5nLmphcm9XaW5rbGVyU2ltaWxhcml0eSgnbm8nLCAnbWF0Y2gnKTtcbiAqIC8vIOKGkiAwXG4gKlxuICogeHN0cmluZy5qYXJvV2lua2xlclNpbWlsYXJpdHkoJ3RlYXBvdCcsICd0ZWFwb3QnKTtcbiAqIC8vIOKGkiAxXG4gKlxuICogeHN0cmluZy5qYXJvV2lua2xlclNpbWlsYXJpdHkoJ2plbGx5JywgJ2plbGx5ZmlzaCcpO1xuICogLy8g4oaSIDAuOTExMTExMTExMTExMTExMVxuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBqYXJvV2lua2xlclNpbWlsYXJpdHkoeDogc3RyaW5nLCB5OiBzdHJpbmcsIHA6IG51bWJlcj0wLjEpOiBudW1iZXIge1xuICBjb25zdCBzID0gamFyb1NpbWlsYXJpdHkoeCwgeSk7XG4gIGNvbnN0IGwgPSBsb25nZXN0Q29tbW9uUHJlZml4KHgsIHkuc3Vic3RyaW5nKDAsIDQpKS5sZW5ndGg7XG4gIHJldHVybiBzICsgbCpwKigxIC0gcyk7XG59XG5cblxuLyoqXG4gKiBHZXQgSmFyby1XaW5rbGVyIGRpc3RhbmNlIGJldHdlZW4gc3RyaW5ncy5cbiAqIEBwYXJhbSB4IGEgc3RyaW5nXG4gKiBAcGFyYW0geSBhbm90aGVyIHN0cmluZ1xuICogQHBhcmFtIHAgc2NhbGluZyBmYWN0b3IgZm9yIGNvbW1vbiBwcmVmaXggKDAuMSAtIDAuMjUpIFswLjFdXG4gKiBAcmV0dXJucyAxIC0gamFyb1dpbmtsZXJTaW1pbGFyaXR5KHgsIHkpXG4gKiBAZXhhbXBsZVxuICogYGBgamF2YXNjcmlwdFxuICogeHN0cmluZy5qYXJvV2lua2xlckRpc3RhbmNlKCdubycsICdtYXRjaCcpO1xuICogLy8g4oaSIDFcbiAqXG4gKiB4c3RyaW5nLmphcm9XaW5rbGVyRGlzdGFuY2UoJ3RlYXBvdCcsICd0ZWFwb3QnKTtcbiAqIC8vIOKGkiAwXG4gKlxuICogeHN0cmluZy5qYXJvV2lua2xlckRpc3RhbmNlKCdqZWxseScsICdqZWxseWZpc2gnKTtcbiAqIC8vIOKGkiAwLjA4ODg4ODg4ODg4ODg4ODlcbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gamFyb1dpbmtsZXJEaXN0YW5jZSh4OiBzdHJpbmcsIHk6IHN0cmluZywgcDogbnVtYmVyPTAuMSk6IG51bWJlciB7XG4gIHJldHVybiAxIC0gamFyb1dpbmtsZXJTaW1pbGFyaXR5KHgsIHksIHApO1xufVxuXG5cbi8qKlxuICogR2V0IExldmVuc2h0ZWluIGRpc3RhbmNlIGJldHdlZW4gc3RyaW5ncy5cbiAqIEBwYXJhbSB4IGEgc3RyaW5nXG4gKiBAcGFyYW0geSBhbm90aGVyIHN0cmluZ1xuICogQHBhcmFtIGlucyBpbnNlcnRpb24gY29zdCBbMV1cbiAqIEBwYXJhbSBkZWwgZGVsZXRpb24gY29zdCBbMV1cbiAqIEBwYXJhbSBzdWIgc3Vic3RpdHV0aW9uIGNvc3QgWzFdXG4gKiBAcmV0dXJucyBsZXZlbnNodGVpbiBkaXN0YW5jZVxuICogQGV4YW1wbGVcbiAqIGBgYGphdmFzY3JpcHRcbiAqIHhzdHJpbmcubGV2ZW5zaHRlaW5EaXN0YW5jZSgnaGFyZXJhbScsICdoYXJlcmFtJyk7XG4gKiAvLyDihpIgMFxuICpcbiAqIHhzdHJpbmcubGV2ZW5zaHRlaW5EaXN0YW5jZSgnY2h1cmNoJywgJ3RvcmNoJyk7XG4gKiAvLyDihpIgM1xuICpcbiAqIHhzdHJpbmcubGV2ZW5zaHRlaW5EaXN0YW5jZSgnbXIuIGJlYW4nLCAnYmVuIDEwJywgMSwgMC4xLCAxKTtcbiAqIC8vIOKGkiAzLjVcbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gbGV2ZW5zaHRlaW5EaXN0YW5jZSh4OiBzdHJpbmcsIHk6IHN0cmluZywgaW5zOiBudW1iZXI9MSwgZGVsOiBudW1iZXI9MSwgc3ViOiBudW1iZXI9MSk6IG51bWJlciB7XG4gIC8vIDEuIFJlbW92ZSBjb21tb24gcHJlZml4LCBzdWZmaXhcbiAgY29uc3QgaW5maXhlcyA9IGxvbmdlc3RVbmNvbW1vbkluZml4ZXMoeCwgeSk7XG4gIHggPSBpbmZpeGVzWzBdOyB5ID0gaW5maXhlc1sxXTtcbiAgY29uc3QgWCA9IHgubGVuZ3RoLCBZID0geS5sZW5ndGg7XG4gIC8vIDIuIEdldCBkaXN0YW5jZSBpbiAxc3Qgcm93XG4gIGNvbnN0IGQwOiBudW1iZXJbXSA9IFtdLCBkMTogbnVtYmVyW10gPSBbXTtcbiAgZm9yIChsZXQgaj0wLCB2PTA7IGo8PVk7IHYrPWlucylcbiAgICBkMFtqKytdID0gdjtcbiAgLy8gMy4gR2V0IGRpc3RhbmNlIGluIHJlbWFpbmluZyByb3dzXG4gIGZvciAobGV0IGk9MTsgaTw9WDsgaSsrKSB7XG4gICAgLy8gYS4gR2V0IGRpc3RhbmNlIGluIDFzdCBjb2x1bW5cbiAgICBjb25zdCBkaSA9IGkgJiAxPyBkMSA6IGQwO1xuICAgIGNvbnN0IGRoID0gaSAmIDE/IGQwIDogZDE7XG4gICAgZGlbMF0gID0gZGhbMF0gKyBkZWw7XG4gICAgLy8gYi4gR2V0IGRpc3RhbmNlIG9mIHJlbWFpbmluZyBjb2x1bW5zXG4gICAgZm9yIChsZXQgaj0xOyBqPD1ZOyBqKyspIHtcbiAgICAgIGNvbnN0IGNvc3QgPSB4W2ktMV09PT15W2otMV0/IDAgOiBzdWI7XG4gICAgICBkaVtqXSA9IE1hdGgubWluKGRoW2pdK2RlbCwgZGlbai0xXStpbnMsIGRoW2otMV0rY29zdCk7XG4gICAgfVxuICB9XG4gIHJldHVybiAoWCAmIDE/IGQxIDogZDApW1ldO1xufVxuXG5cbi8qKlxuICogR2V0IERhbWVyYXXigJNMZXZlbnNodGVpbiBkaXN0YW5jZSBiZXR3ZWVuIHN0cmluZ3MuXG4gKiBAcGFyYW0geCBhIHN0cmluZ1xuICogQHBhcmFtIHkgYW5vdGhlciBzdHJpbmdcbiAqIEBwYXJhbSBpbnMgaW5zZXJ0aW9uIGNvc3QgWzFdXG4gKiBAcGFyYW0gZGVsIGRlbGV0aW9uIGNvc3QgWzFdXG4gKiBAcGFyYW0gc3ViIHN1YnN0aXR1dGlvbiBjb3N0IFsxXVxuICogQHBhcmFtIHRyYSB0cmFuc3Bvc2l0aW9uIGNvc3QgWzFdXG4gKiBAcmV0dXJucyBkYW1lcmF14oCTbGV2ZW5zaHRlaW4gZGlzdGFuY2VcbiAqIEBleGFtcGxlXG4gKiBgYGBqYXZhc2NyaXB0XG4gKiB4c3RyaW5nLmRhbWVyYXVMZXZlbnNodGVpbkRpc3RhbmNlKCdnbnUnLCAnZ3VuJyk7XG4gKiAvLyDihpIgMVxuICpcbiAqIHhzdHJpbmcuZGFtZXJhdUxldmVuc2h0ZWluRGlzdGFuY2UoJ3NvZnR3YXJlJywgJ3NvZnR3ZWFyJyk7XG4gKiAvLyDihpIgMlxuICpcbiAqIHhzdHJpbmcuZGFtZXJhdUxldmVuc2h0ZWluRGlzdGFuY2UoJ2xldmVsIGZpZWxkJywgJ2x2ZWxlIGZlaWRsJywgMSwgMSwgMSwgMC4xKTtcbiAqIC8vIOKGkiAwLjRcbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gZGFtZXJhdUxldmVuc2h0ZWluRGlzdGFuY2UoeDogc3RyaW5nLCB5OiBzdHJpbmcsIGluczogbnVtYmVyPTEsIGRlbDogbnVtYmVyPTEsIHN1YjogbnVtYmVyPTEsIHRyYTogbnVtYmVyPTEpOiBudW1iZXIge1xuICAvLyAxLiBSZW1vdmUgY29tbW9uIHByZWZpeCwgc3VmZml4XG4gIGNvbnN0IGluZml4ZXMgPSBsb25nZXN0VW5jb21tb25JbmZpeGVzKHgsIHkpO1xuICB4ID0gaW5maXhlc1swXTsgeSA9IGluZml4ZXNbMV07XG4gIGNvbnN0IFggPSB4Lmxlbmd0aCwgWSA9IHkubGVuZ3RoXG4gIGNvbnN0IEkgPSBYKzIsIEogPSBZKzIsIEwgPSBYK1k7XG4gIC8vIDIuIFByZXBhcmUgMXN0IDIgcm93c1xuICBjb25zdCBkMCA9IFtMXSwgZDEgPSBbTF07XG4gIGNvbnN0IGQgID0gW2QwLCBkMV0sIGRhID0gbmV3IE1hcCgpO1xuICBmb3IgKGxldCBqPTEsIHY9MDsgajxKOyBqKyssIHYrPWlucykge1xuICAgIGQwW2pdID0gTDtcbiAgICBkMVtqXSA9IHY7XG4gIH1cbiAgLy8gMy4gUHJlcGFyZSByZW1haW5pbmcgcm93c1xuICBmb3IgKGxldCBpPTI7IGk8STsgaSsrKSB7XG4gICAgLy8gYS4gUHJlcGFyZSAxc3QgMiBjb2x1bW5zXG4gICAgbGV0IGRiID0gMDsgY29uc3QgZGggPSBkW2ktMV07XG4gICAgY29uc3QgZGkgPSBbTCwgZGhbMV0rZGVsXTtcbiAgICBkW2ldID0gZGk7XG4gICAgLy8gYi4gUHJlcGFyZSByZW1haW5pbmcgY29sdW1uc1xuICAgIGZvciAobGV0IGo9MjsgajxKOyBqKyspIHtcbiAgICAgIGNvbnN0IGsgPSBkYS5nZXQoeVtqLTJdKXx8MCwgbCA9IGRiOyBsZXQgY29zdCA9IHN1YjtcbiAgICAgIGlmICh4W2ktMl09PT15W2otMl0pIHsgZGIgPSBqLTE7IGNvc3QgPSAwOyB9XG4gICAgICBkaVtqXSA9IE1hdGgubWluKGRpW2otMV0raW5zLCBkaFtqXStkZWwsIGRoW2otMV0rY29zdCwgZFtrXVtsXSsoaS1rLTIpK3RyYSsoai1sLTIpKTtcbiAgICB9XG4gICAgZGEuc2V0KHhbaS0yXSwgaS0xKTtcbiAgfVxuICByZXR1cm4gZFtYKzFdW1krMV07XG59XG4vLyNlbmRyZWdpb25cbi8vI2VuZHJlZ2lvblxuXG5cblxuXG4vLyNyZWdpb24gVE9ET1xuLy8gZnVuY3Rpb24gbWFwUmVwbGFjZShzdHIsIG1hcCkge1xuLy8gICBmb3IobGV0IFtrLCB2XSBvZiBtYXApXG4vLyAgICAgc3RyID0gc3RyLnJlcGxhY2Uoaywgdik7XG4vLyAgIHJldHVybiBzdHI7XG4vLyB9XG4vLyBtYXBSZXBsYWNlKCdhbHBoYSBiZXRhJywgbmV3IE1hcCgpLnNldCgnYWxwaGEnLCAnzrEnKS5zZXQoJ2JldGEnLCAnzrInKSk7XG4vLyAvLyAnzrEgzrInXG4vLyBtYXBSZXBsYWNlKCdnYW1tYSBERUxUQScsIG5ldyBNYXAoKS5zZXQoJ2dhbW1hJywgJ86zJykuc2V0KCdkZWx0YScsICfOtCcpKTtcbi8vIC8vICfOsyBERUxUQSdcbi8vIG1hcFJlcGxhY2UoJ0Vwc2lsb24gWkVUQScsIG5ldyBNYXAoKS5zZXQoL2Vwc2lsb24vZ2ksICfOtScpLnNldCgvemV0YS9naSwgJ862JykpO1xuLy8gLy8gJ861IM62J1xuXG5cbi8vIGZ1bmN0aW9uIG1hcFJlcGxhY2VQcmVmaXgoc3RyLCBtYXAsIGw9MCkge1xuLy8gICAvLyAxLiBnZXQgbWF4IHByZWZpeCBsZW5ndGhcbi8vICAgaWYoIWwpIGZvcihsZXQgayBvZiBtYXAua2V5cygpKSB7XG4vLyAgICAgbCA9IGw8ay5sZW5ndGg/IGsubGVuZ3RoOmw7XG4vLyAgIH1cbi8vICAgLy8gMi4gcmVwbGFjZSBwcmVmaXhcbi8vICAgZm9yKGxldCBpPWw7IGk7IGktLSkge1xuLy8gICAgIGxldCBrID0gc3RyLnN1YnN0cigwLCBpKTtcbi8vICAgICBpZihtYXAuaGFzKGspKSByZXR1cm4gbWFwLmdldChrKStzdHIuc3Vic3RyKGkpO1xuLy8gICB9XG4vLyAgIHJldHVybiBzdHI7XG4vLyB9XG4vLyBtYXBSZXBsYWNlUHJlZml4KCdkaXNob25vdXJlZCcsIG5ldyBNYXAoW1snZGlzJywgJyddLCBbJ3VuJywgJyddLCBbJ2luJywgJyddXSkpO1xuLy8gLy8gJ2hvbm91cmVkJ1xuLy8gbWFwUmVwbGFjZVByZWZpeCgnZGlzaG9ub3VyZWQnLCBuZXcgTWFwKFtbJ2hvbm91cicsICdyZXNwZWN0J10sIFsnZmxhdHRlcicsICdtb2NrJ11dKSk7XG4vLyAvLyAnZGlzaG9ub3VyZWQnIChvbmx5IHByZWZpeClcbi8vIG1hcFJlcGxhY2VQcmVmaXgoJ2Rpc2hvbm91cmVkJywgbmV3IE1hcChbWydkaXMnLCAncmVkaXMnXSwgWydyZWRpcycsICdzdXBlciddXSksIDUpO1xuLy8gLy8gJ3JlZGlzaG9ub3VyZWQnIChvbmx5IG9uY2UpXG5cblxuLy8gZnVuY3Rpb24gbWFwUmVwbGFjZVN1ZmZpeChzdHIsIG1hcCwgbD0wKSB7XG4vLyAgIC8vIDEuIGdldCBtYXggc3VmZml4IGxlbmd0aFxuLy8gICBpZighbCkgZm9yKGxldCBrIG9mIG1hcC5rZXlzKCkpIHtcbi8vICAgICBsID0gbDxrLmxlbmd0aD8gay5sZW5ndGg6bDtcbi8vICAgfVxuLy8gICAvLyAyLiByZXBsYWNlIHN1ZmZpeFxuLy8gICBmb3IobGV0IGk9bDsgaTsgaS0tKSB7XG4vLyAgICAgbGV0IGsgPSBzdHIuc3Vic3RyKC1pKTtcbi8vICAgICBpZihtYXAuaGFzKGspKSByZXR1cm4gc3RyLnN1YnN0cigwLCBzdHIubGVuZ3RoLWkpK21hcC5nZXQoayk7XG4vLyAgIH1cbi8vICAgcmV0dXJuIHN0cjtcbi8vIH1cbi8vIG1hcFJlcGxhY2VTdWZmaXgoJ2VuZGVyJywgbmV3IE1hcChbWydlcicsICcnXSwgWydpbmcnLCAnJ10sIFsnZWQnLCAnJ11dKSk7XG4vLyAvLyAnZW5kXG4vLyBtYXBSZXBsYWNlU3VmZml4KCdlbmRlcicsIG5ldyBNYXAoW1snZW5kJywgJ3JpZ2h0J10sIFsnc3RhcnQnLCAnbGVmdCddXSkpO1xuLy8gLy8gJ2VuZGVyJyAob25seSBzdWZmaXgpXG4vLyBtYXBSZXBsYWNlU3VmZml4KCdlbmRlcicsIG5ldyBNYXAoW1snZXInLCAnIGdhbWUnXSwgWydnYW1lJywgJ3BsYXknXV0pLCA0KTtcbi8vIC8vICdlbmQgZ2FtZScgKG9ubHkgb25jZSlcblxuXG4vLyBmdW5jdGlvbiBvYmplY3RSZXBsYWNlKHN0ciwgb2JqKSB7XG4vLyAgIGZvcihsZXQgayBpbiBvYmopXG4vLyAgICAgc3RyID0gc3RyLnJlcGxhY2Uoaywgb2JqW2tdKTtcbi8vICAgcmV0dXJuIHN0cjtcbi8vIH1cbi8vIG9iamVjdFJlcGxhY2UoJ2FscGhhIGJldGEnLCB7J2FscGhhJzogJ86xJywgJ2JldGEnOiAnzrInfSk7XG4vLyAvLyAnzrEgzrInXG4vLyBvYmplY3RSZXBsYWNlKCdnYW1tYSBERUxUQScsIHsnZ2FtbWEnOiAnzrMnLCAnZGVsdGEnOiAnzrQnfSk7XG4vLyAvLyAnzrMgREVMVEEnXG4vLyBvYmplY3RSZXBsYWNlKCdFcHNpbG9uIFpFVEEnLnRvTG93ZXJDYXNlKCksIHsnZXBzaWxvbic6ICfOtScsICd6ZXRhJzogJ862J30pO1xuLy8gLy8gJ861IM62J1xuXG5cbi8vIGZ1bmN0aW9uIG9iamVjdFJlcGxhY2VQcmVmaXgoc3RyLCBvYmosIGw9MCkge1xuLy8gICAvLyAxLiBnZXQgbWF4IHByZWZpeCBsZW5ndGhcbi8vICAgaWYoIWwpIGZvcihsZXQgayBpbiBvYmopIHtcbi8vICAgICBsID0gbDxrLmxlbmd0aD8gay5sZW5ndGg6bDtcbi8vICAgfVxuLy8gICAvLyAyLiByZXBsYWNlIHByZWZpeFxuLy8gICBmb3IobGV0IGk9bDsgaTsgaS0tKSAge1xuLy8gICAgIC8vIGxldCBrID0gc3RyLnN1YnN0cigwLCBpKTtcbi8vICAgICBpZihvYmpba10hPW51bGwpIHJldHVybiBvYmpba10rc3RyLnN1YnN0cihpKTtcbi8vICAgfVxuLy8gICByZXR1cm4gc3RyO1xuLy8gfVxuLy8gb2JqZWN0UmVwbGFjZVByZWZpeCgnZGlzaG9ub3VyZWQnLCB7J2Rpcyc6ICcnLCAndW4nOiAnJywgJ2luJzogJyd9KTtcbi8vIC8vICdob25vdXJlZCdcbi8vIG9iamVjdFJlcGxhY2VQcmVmaXgoJ2Rpc2hvbm91cmVkJywgeydob25vdXInOiAncmVzcGVjdCcsICdmbGF0dGVyJzogJ21vY2snfSk7XG4vLyAvLyAnZGlzaG9ub3VyZWQnIChvbmx5IHByZWZpeClcbi8vIG9iamVjdFJlcGxhY2VQcmVmaXgoJ2Rpc2hvbm91cmVkJywgeydkaXMnOiAncmVkaXMnLCAncmVkaXMnOiAnc3VwZXInfSwgNSk7XG4vLyAvLyAncmVkaXNob25vdXJlZCcgKG9ubHkgb25jZSlcblxuXG4vLyBmdW5jdGlvbiBvYmplY3RSZXBsYWNlU3VmZml4KHN0ciwgb2JqLCBsPTApIHtcbi8vICAgLy8gMS4gZ2V0IG1heCBzdWZmaXggbGVuZ3RoXG4vLyAgIGlmKCFsKSBmb3IobGV0IGsgaW4gb2JqKSB7XG4vLyAgICAgbCA9IGw8ay5sZW5ndGg/IGsubGVuZ3RoOmw7XG4vLyAgIH1cbi8vICAgLy8gMi4gcmVwbGFjZSBzdWZmaXhcbi8vICAgZm9yKGxldCBpPWw7IGk7IGktLSkge1xuLy8gICAgIC8vIGxldCBrID0gc3RyLnN1YnN0cigtaSk7XG4vLyAgICAgaWYob2JqW2tdIT1udWxsKSByZXR1cm4gc3RyLnN1YnN0cigwLCBzdHIubGVuZ3RoLWkpK29ialtrXTtcbi8vICAgfVxuLy8gICByZXR1cm4gc3RyO1xuLy8gfVxuXG5cbi8vIHJlZHVjZVJpZ2h0KCdhYmMnLCAoYWNjLCB2KSA9PiBhY2Mrdik7XG4vLyAvLyAnY2JhJ1xuLy8gcmVkdWNlUmlnaHQoJzEyMycsIChhY2MsIHYpID0+IGFjYyt2LCAnLScpO1xuLy8gLy8gJy0zMjEnXG4vLyByZWR1Y2VSaWdodCgnYScsIChhY2MsIHYpID0+IGFjYyt2KTtcbi8vIC8vICdhJ1xuLy8gcmVkdWNlUmlnaHQoJycsIChhY2MsIHYpID0+IGFjYyt2KTtcbi8vIC8vIHVuZGVmaW5lZFxuXG5cbi8vIGZpbmQoJ2JhZGQwZycsICh2KSA9PiB2PidmJyk7XG4vLyAvLyAnZydcbi8vIGZpbmQoJ2JhZGNhYicsICh2KSA9PiB2PidmJyk7XG4vLyAvLyB1bmRlZmluZWRcbi8vIGZpbmQoJycsICh2KSA9PiB2PidmJyk7XG4vLyAvLyB1bmRlZmluZWRcblxuXG4vLyBmaW5kSW5kZXgoJ2JhZGQwZycsICh2KSA9PiB2PidmJyk7XG4vLyAvLyA1XG4vLyBmaW5kSW5kZXgoJ2JhZGNhYicsICh2KSA9PiB2PidmJyk7XG4vLyAvLyAtMVxuLy8gZmluZEluZGV4KCcnLCAodikgPT4gdj4nZicpO1xuLy8gLy8gLTFcblxuXG4vLyBldmVyeSgnYmFkZjAwZCcsICh2KSA9PiB2PD0nZicpO1xuLy8gLy8gdHJ1ZVxuLy8gZXZlcnkoJ2cwMGRmMDBkJywgKHYpID0+IHY8PSdmJyk7XG4vLyAvLyBmYWxzZVxuLy8gZXZlcnkoJycsICh2KSA9PiB2PD0nZicpO1xuLy8gLy8gdHJ1ZVxuXG5cbi8vIHhzdHJpbmcuZXVjbGlkZWFuRGlzdGFuY2UoJ2EnLCAnYicpO1xuLy8gLy8g4oaSIDAuMDAwMDE1MjU5MDIxODk2Njk2NDIyIChub3JtYWxpemVkIGRpc3RhbmNlIGJldHdlZW4gMSBjaGFyYWN0ZXIgY29kZSlcbi8vXG4vLyB4c3RyaW5nLmV1Y2xpZGVhbkRpc3RhbmNlKCdsb2dvJywgJ3BvZ28nKTtcbi8vIC8vIOKGkiAwLjAwMDA2MTAzNjA4NzU4Njc4NTY5XG4vL1xuLy8geHN0cmluZy5ldWNsaWRlYW5EaXN0YW5jZSgnZG9jdG9yJywgJ2Jyb2tlcicpO1xuLy8gLy8g4oaSIDAuMDAwMjgwNTMzNzA0MjkzMTI5MzdcblxuXG4vLyBjaHIoNjUpOyAvLyAnQSdcbi8vIGNocig5Nyk7IC8vICdhJ1xuXG5cbi8vIGFzYygnQScpOyAgICAgLy8gNjVcbi8vIGFzYygnYUEnKTsgICAgLy8gOTdcbi8vIGFzYygnYUEnLCAxKTsgLy8gNjVcbi8vI2VuZHJlZ2lvblxuIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLG1CQUFtQjtBQUNuQix3QkFBd0IsR0FDeEIsT0FBTyxNQUFNLFNBQXFCLGFBQWE7QUFDL0Msc0JBQXNCLEdBQ3RCLE9BQU8sTUFBTSxhQUFxQixXQUFXO0FBQzdDLHNDQUFzQyxHQUN0QyxPQUFPLE1BQU0sYUFBcUIseUJBQXlCO0FBRTNELHlCQUF5QixHQUN6QixPQUFPLE1BQU0sWUFBb0IsNkJBQTZCO0FBQzlELHlCQUF5QixHQUN6QixPQUFPLE1BQU0sWUFBb0IsNkJBQTZCO0FBQzlELHlEQUF5RCxHQUN6RCxPQUFPLE1BQU0sVUFBa0IsWUFBWSxVQUFVO0FBRXJELGlDQUFpQyxHQUNqQyxPQUFPLE1BQU0sY0FBc0IscUNBQXFDO0FBQ3hFLGtDQUFrQyxHQUNsQyxPQUFPLE1BQU0sYUFBc0Isa0JBQWtCO0FBRXJELHlFQUF5RSxHQUN6RSxPQUFPLE1BQU0sWUFBb0IsU0FBUyxVQUFVLGNBQWMsV0FBVztBQUU3RSxnQ0FBZ0MsR0FDaEMsT0FBTyxNQUFNLGlCQUF5QixTQUFTO0FBQy9DLGdDQUFnQyxHQUNoQyxPQUFPLE1BQU0saUJBQXlCLFNBQVM7QUFDL0MsWUFBWTtBQUtaLDJCQUEyQjtBQUMzQjs7OztDQUlDLEdBQ0QsU0FBUyxTQUFZLENBQUk7RUFDdkIsT0FBTztBQUNUO0FBR0EsU0FBUyxJQUFJLENBQVMsRUFBRSxDQUFTO0VBQy9CLE9BQU8sSUFBSSxJQUFJLEtBQUssS0FBSyxDQUFDLElBQUU7QUFDOUI7QUFDQSxZQUFZO0FBS1osa0JBQWtCO0FBQ2xCLGtCQUFrQjtBQUNsQjs7OztDQUlDLEdBQ0QsT0FBTyxTQUFTLGFBQWEsR0FBRyxLQUFlO0VBQzdDLE9BQU8sT0FBTyxZQUFZLElBQUk7QUFDaEM7QUFHQTs7OztDQUlDLEdBQ0QsT0FBTyxTQUFTLGNBQWMsR0FBRyxLQUFlO0VBQzlDLE9BQU8sT0FBTyxhQUFhLElBQUk7QUFDakM7QUFHQTs7OztDQUlDLEdBQ0QsT0FBTyxTQUFTLE9BQU8sR0FBRyxNQUFpQjtFQUN6QyxPQUFPLEdBQUcsTUFBTSxJQUFJO0FBQ3RCO0FBR0E7Ozs7O0NBS0MsR0FDRCxPQUFPLFNBQVMsT0FBTyxDQUFTLEVBQUUsS0FBYTtFQUM3QyxPQUFPLEVBQUUsTUFBTSxDQUFDO0FBQ2xCO0FBQ0EsWUFBWTtBQUtaLGVBQWU7QUFDZjs7OztDQUlDLEdBQ0QsT0FBTyxTQUFTLFFBQVEsQ0FBUztFQUMvQixPQUFPLEVBQUUsT0FBTztBQUNsQjtBQUdBOzs7O0NBSUMsR0FDRCxPQUFPLFNBQVMsT0FBTyxDQUFTO0VBQzlCLE9BQU8sRUFBRSxNQUFNO0FBQ2pCO0FBQ0EsU0FBUSxVQUFVLElBQUksR0FBRTtBQUN4QiwwQ0FBMEM7QUFDMUMsbUdBQW1HO0FBR25HOzs7OztDQUtDLEdBQ0QsT0FBTyxTQUFTLE9BQU8sQ0FBUyxFQUFFLEVBQVU7RUFDMUMsT0FBTyxFQUFFLE1BQU0sQ0FBQztBQUNsQjtBQUNBLDREQUE0RDtBQUM1RCxtR0FBbUc7QUFHbkc7Ozs7O0NBS0MsR0FDRCxPQUFPLFNBQVMsV0FBVyxDQUFTLEVBQUUsRUFBVTtFQUM5QyxPQUFPLEVBQUUsVUFBVSxDQUFDO0FBQ3RCO0FBQ0EsNERBQTREO0FBQzVELHVHQUF1RztBQUd2Rzs7Ozs7Q0FLQyxHQUNELE9BQU8sU0FBUyxZQUFZLENBQVMsRUFBRSxFQUFVO0VBQy9DLE9BQU8sRUFBRSxXQUFXLENBQUM7QUFDdkI7QUFDQSxZQUFZO0FBS1osaUJBQWlCO0FBQ2pCOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Q0FrQkMsR0FDRCxPQUFPLFNBQVMsY0FBYyxDQUFTLEVBQUUsQ0FBUyxFQUFFLE9BQTJCLEVBQUUsT0FBOEI7RUFDN0csT0FBTyxFQUFFLGFBQWEsQ0FBQyxHQUFHLFNBQVM7QUFDckM7QUFDQSxZQUFZO0FBS1osZ0JBQWdCO0FBQ2hCOzs7Ozs7Q0FNQyxHQUNELE9BQU8sU0FBUyxTQUFTLENBQVMsRUFBRSxLQUFhLEVBQUUsS0FBYztFQUMvRCxPQUFPLEVBQUUsUUFBUSxDQUFDLE9BQU87QUFDM0I7QUFHQTs7Ozs7O0NBTUMsR0FDRCxPQUFPLFNBQVMsV0FBVyxDQUFTLEVBQUUsTUFBYyxFQUFFLEtBQWM7RUFDbEUsT0FBTyxFQUFFLFVBQVUsQ0FBQyxRQUFRO0FBQzlCO0FBR0E7Ozs7OztDQU1DLEdBQ0QsT0FBTyxTQUFTLFNBQVMsQ0FBUyxFQUFFLE1BQWMsRUFBRSxHQUFZO0VBQzlELE9BQU8sRUFBRSxRQUFRLENBQUMsUUFBUTtBQUM1QjtBQUdBOzs7Ozs7Q0FNQyxHQUNELE9BQU8sU0FBUyxRQUFRLENBQVMsRUFBRSxLQUFhLEVBQUUsS0FBYztFQUM5RCxPQUFPLEVBQUUsT0FBTyxDQUFDLE9BQU87QUFDMUI7QUFHQTs7Ozs7O0NBTUMsR0FDRCxPQUFPLFNBQVMsWUFBWSxDQUFTLEVBQUUsS0FBYSxFQUFFLE1BQWU7RUFDbkUsT0FBTyxFQUFFLFdBQVcsQ0FBQyxPQUFPO0FBQzlCO0FBR0E7Ozs7O0NBS0MsR0FDRCxPQUFPLFNBQVMsT0FBTyxDQUFTLEVBQUUsTUFBdUI7RUFDdkQsT0FBTyxFQUFFLE1BQU0sQ0FBQztBQUNsQjtBQUdBOzs7OztDQUtDLEdBQ0QsT0FBTyxTQUFTLE1BQU0sQ0FBUyxFQUFFLE1BQXVCO0VBQ3RELE9BQU8sRUFBRSxLQUFLLENBQUM7QUFDakI7QUFHQTs7Ozs7Q0FLQyxHQUNELE9BQU8sU0FBUyxTQUFTLENBQVMsRUFBRSxNQUFjO0VBQ2hELE9BQU8sRUFBRSxRQUFRLENBQUM7QUFDcEI7QUFDQSxZQUFZO0FBS1osaUJBQWlCO0FBQ2pCOzs7O0NBSUMsR0FDRCxPQUFPLFNBQVMsU0FBUyxDQUFTO0VBQ2hDLE9BQU8sRUFBRSxRQUFRO0FBQ25CO0FBQ0EsWUFBWTtBQUtaLGNBQWM7QUFDZDs7Ozs7O0NBTUMsR0FDRCxPQUFPLFNBQVMsTUFBTSxDQUFTLEVBQUUsS0FBYyxFQUFFLEdBQVk7RUFDM0QsT0FBTyxFQUFFLEtBQUssQ0FBQyxPQUFPO0FBQ3hCO0FBR0E7Ozs7OztDQU1DLEdBQ0QsT0FBTyxTQUFTLFVBQVUsQ0FBUyxFQUFFLEtBQWEsRUFBRSxHQUFZO0VBQzlELE9BQU8sRUFBRSxTQUFTLENBQUMsT0FBTztBQUM1QjtBQUdBOzs7Ozs7Q0FNQyxHQUNELE9BQU8sU0FBUyxNQUFNLENBQVMsRUFBRSxTQUEyQixFQUFFLEtBQWM7RUFDMUUsT0FBTyxFQUFFLEtBQUssQ0FBQyxXQUE4QjtBQUMvQztBQUNBLHFFQUFxRTtBQUNyRSxZQUFZO0FBS1osb0JBQW9CO0FBQ3BCOzs7O0NBSUMsR0FDRCxPQUFPLFNBQVMsVUFBVSxDQUFTO0VBQ2pDLE9BQU8sRUFBRSxTQUFTO0FBQ3BCO0FBR0E7Ozs7Q0FJQyxHQUNELE9BQU8sU0FBUyxRQUFRLENBQVM7RUFDL0IsT0FBTyxFQUFFLE9BQU87QUFDbEI7QUFHQTs7OztDQUlDLEdBQ0QsT0FBTyxTQUFTLEtBQUssQ0FBUztFQUM1QixPQUFPLEVBQUUsSUFBSTtBQUNmO0FBR0E7Ozs7OztDQU1DLEdBQ0QsT0FBTyxTQUFTLFNBQVMsQ0FBUyxFQUFFLE1BQWMsRUFBRSxVQUFnQixHQUFHO0VBQ3JFLE9BQU8sRUFBRSxRQUFRLENBQUMsUUFBUTtBQUM1QjtBQUdBOzs7Ozs7Q0FNQyxHQUNBLE9BQU8sU0FBUyxPQUFPLENBQVMsRUFBRSxNQUFjLEVBQUUsVUFBZ0IsR0FBRztFQUNwRSxPQUFPLEVBQUUsTUFBTSxDQUFDLFFBQVE7QUFDMUI7QUFDQSxZQUFZO0FBS1osMEJBQTBCO0FBQzFCOzs7O0NBSUMsR0FDRCxPQUFPLFNBQVMsWUFBWSxDQUFTO0VBQ25DLE9BQU8sRUFBRSxXQUFXO0FBQ3RCO0FBR0E7Ozs7O0NBS0MsR0FDRCxPQUFPLFNBQVMsa0JBQWtCLENBQVMsRUFBRSxPQUEyQjtFQUN0RSxPQUFPLEVBQUUsaUJBQWlCLENBQUM7QUFDN0I7QUFHQTs7OztDQUlDLEdBQ0QsT0FBTyxTQUFTLFlBQVksQ0FBUztFQUNuQyxPQUFPLEVBQUUsV0FBVztBQUN0QjtBQUdBOzs7OztDQUtDLEdBQ0QsT0FBTyxTQUFTLGtCQUFrQixDQUFTLEVBQUUsT0FBMkI7RUFDdEUsT0FBTyxFQUFFLGlCQUFpQixDQUFDO0FBQzdCO0FBNEJBLE9BQU8sU0FBUyxRQUFRLENBQVMsRUFBRSxPQUF3QixFQUFFLFdBQXFDO0VBQ2hHLE9BQU8sRUFBRSxPQUFPLENBQUMsU0FBUztBQUM1QjtBQUdBLDJFQUEyRTtBQUMzRSxrQ0FBa0M7QUFDbEMsSUFBSTtBQUdKOzs7OztDQUtDLEdBQ0QsT0FBTyxTQUFTLFVBQVUsQ0FBUyxFQUFFLElBQWE7RUFDaEQsT0FBTyxFQUFFLFNBQVMsQ0FBQztBQUNyQjtBQUNBLFlBQVk7QUFDWixZQUFZO0FBS1osMEJBQTBCO0FBQzFCLGtCQUFrQjtBQUNsQjs7Ozs7Ozs7Ozs7Ozs7O0NBZUMsR0FDRCxPQUFPLFNBQVMsR0FBRyxHQUFHLElBQWM7RUFDbEMsSUFBSSxJQUFJO0VBQ1IsSUFBSyxJQUFJLElBQUUsR0FBRyxJQUFFLEtBQUssTUFBTSxFQUFFLElBQUUsR0FBRyxJQUNoQyxLQUFLLElBQUksQ0FBQyxFQUFFO0VBQ2QsT0FBTztBQUNUO0FBWUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0NBb0JDLEdBQ0QsT0FBTyxTQUFTLEtBQUssRUFBb0IsRUFBRSxFQUFnQixFQUFFLEdBQWE7RUFDeEUsSUFBSSxJQUFJLElBQUksSUFBSTtFQUNoQixLQUFLLE1BQU0sS0FBSyxHQUFJO0lBQ2xCLEtBQUssS0FBSSxHQUFHLElBQUksQ0FBQyxLQUFLLEdBQUcsS0FBSztJQUM5QjtFQUNGO0VBQ0EsT0FBTztBQUNUO0FBQ0EsWUFBWTtBQUtaLGVBQWU7QUFDZjs7Ozs7Ozs7Ozs7O0NBWUMsR0FDRCxVQUFVLE1BQU0sQ0FBUztFQUN2QixJQUFJLElBQUk7RUFDUixLQUFLLE1BQU0sTUFBTSxFQUNmLE1BQU07QUFDVjtBQUdBOzs7O0NBSUMsR0FDRCxVQUFVLFFBQVEsQ0FBUztFQUN6QixLQUFLLE1BQU0sS0FBSyxFQUNkLE1BQU07QUFDVjtBQUNBLGlDQUFpQztBQUdqQzs7Ozs7Ozs7Ozs7O0NBWUMsR0FDRCxVQUFVLFNBQVMsQ0FBUztFQUMxQixJQUFJLElBQUk7RUFDUixLQUFLLE1BQU0sS0FBSyxFQUNkLE1BQU07SUFBQztJQUFLO0dBQUU7QUFDbEI7QUFDQSxZQUFZO0FBS1osbUJBQW1CO0FBQ25COzs7Ozs7O0NBT0MsR0FDRCxPQUFPLFNBQVMsT0FBTyxDQUFTLEVBQUUsS0FBYSxFQUFFLFNBQWUsQ0FBQyxFQUFFLE1BQVksRUFBRTtFQUMvRSxPQUFPLEVBQUUsS0FBSyxDQUFDLEdBQUcsU0FBUyxNQUFNLEVBQUUsS0FBSyxDQUFDLFFBQU07QUFDakQ7QUFHQTs7OztDQUlDLEdBQ0QsT0FBTyxTQUFTLFFBQVEsQ0FBUztFQUMvQixPQUFPO09BQUk7R0FBRSxDQUFDLE9BQU8sR0FBRyxJQUFJLENBQUM7QUFDL0I7QUFhQTs7OztDQUlDLEdBQ0QsT0FBTyxTQUFTLEtBQUssQ0FBUyxFQUFFLEVBQW9CO0VBQ2xELE9BQU87T0FBSTtHQUFFLENBQUMsSUFBSSxDQUFDLElBQUksSUFBSSxDQUFDO0FBQzlCO0FBZ0JBOzs7Ozs7Ozs7Ozs7Ozs7OztDQWlCQyxHQUNELE9BQU8sU0FBUyxPQUFPLENBQVMsRUFBRSxFQUFnQixFQUFFLEdBQWE7RUFDL0QsSUFBSSxJQUFJLElBQUksSUFBSTtFQUNoQixLQUFLLE1BQU0sS0FBSyxFQUNkLElBQUksR0FBRyxJQUFJLENBQUMsS0FBSyxHQUFHLEtBQUssSUFBSSxLQUFLO0VBQ3BDLE9BQU87QUFDVDtBQUNBLFlBQVk7QUFDWixZQUFZO0FBS1osZ0JBQWdCO0FBQ2hCLGtCQUFrQjtBQUNsQixxREFBcUQsR0FDckQsTUFBTSxlQUF1QixJQUFJLE1BQU0sQ0FBQztBQUV4Qzs7Ozs7Ozs7Ozs7Ozs7Ozs7O0NBa0JDLEdBQ0QsT0FBTyxTQUFTLE9BQU8sQ0FBUztFQUM5QixNQUFNLElBQUksYUFBYSxNQUFNO0VBQzdCLElBQUksSUFBRSxHQUFHLE9BQU8sYUFBYSxLQUFLLENBQUMsR0FBRztFQUN0QyxPQUFPLGFBQWEsTUFBTSxDQUFDLElBQUUsS0FBSyxJQUFJLE1BQU0sQ0FBQyxJQUFFO0FBQ2pEO0FBQ0EsWUFBWTtBQUtaLGVBQWU7QUFDZjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0NBd0JDLEdBQ0QsT0FBTyxTQUFTLEdBQUcsQ0FBVTtFQUMzQixPQUFPLE9BQU8sTUFBSTtBQUNwQjtBQUdBOzs7O0NBSUMsR0FDRCxPQUFPLFNBQVMsUUFBUSxDQUFTO0VBQy9CLE9BQU8sRUFBRSxNQUFNLEtBQUc7QUFDcEI7QUFHQTs7OztDQUlDLEdBQ0QsT0FBTyxTQUFTLFlBQVksQ0FBUztFQUNuQyxPQUFPLEVBQUUsTUFBTSxLQUFHO0FBQ3BCO0FBR0E7Ozs7O0NBS0MsR0FDRCxPQUFPLFNBQVMsTUFBTSxDQUFTLEVBQUUsRUFBVTtFQUN6QyxnREFBZ0Q7RUFDaEQsSUFBSSxLQUFHLEdBQUcsT0FBTyxLQUFLLEdBQUcsQ0FBQyxHQUFHLEVBQUUsTUFBTSxHQUFHO0VBQ3hDLE9BQU8sS0FBSyxHQUFHLENBQUMsSUFBSSxFQUFFLE1BQU07QUFDOUI7QUFHQTs7Ozs7O0NBTUMsR0FDRCxPQUFPLFNBQVMsV0FBVyxDQUFTLEVBQUUsS0FBYSxFQUFFLEdBQVc7RUFDOUQsZ0RBQWdEO0VBQ2hELFFBQVEsTUFBTSxHQUFHO0VBQ2pCLE1BQVEsTUFBTSxHQUFHO0VBQ2pCLE9BQU87SUFBQyxLQUFLLEdBQUcsQ0FBQyxPQUFPO0lBQU0sS0FBSyxHQUFHLENBQUMsT0FBTztHQUFLO0FBQ3JEO0FBR0E7Ozs7Q0FJQyxHQUNELE9BQU8sU0FBUyxlQUFlLENBQVM7RUFDdEMsSUFBSSxNQUFNO0VBQ1YsSUFBSSxNQUFNO0VBQ1YsS0FBSyxNQUFNLEtBQUssRUFBRztJQUNqQixNQUFNLElBQUksRUFBRSxXQUFXLENBQUM7SUFDeEIsTUFBTSxLQUFLLEdBQUcsQ0FBQyxLQUFLO0lBQ3BCLE1BQU0sS0FBSyxHQUFHLENBQUMsS0FBSztFQUN0QjtFQUNBLE9BQU87SUFBQztJQUFLO0dBQUk7QUFDbkI7QUFDQSxZQUFZO0FBS1osaUJBQWlCO0FBQ2pCOzs7OztDQUtDLEdBQ0QsT0FBTyxTQUFTLFFBQVEsQ0FBUyxFQUFFLENBQVM7RUFDMUMsT0FBTyxJQUFFLElBQUcsQ0FBQyxJQUFLLElBQUUsSUFBRyxJQUFJO0FBQzdCO0FBR0E7Ozs7O0NBS0MsR0FDRCxPQUFPLFNBQVMsUUFBUSxDQUFTLEVBQUUsQ0FBUztFQUMxQyxPQUFPLE1BQUk7QUFDYjtBQUNBLFlBQVk7QUFLWixnQkFBZ0I7QUFDaEIsc0NBQXNDO0FBQ3RDLFNBQVEsY0FBYyxRQUFRLEdBQUU7QUFDaEMsc0NBQXNDO0FBQ3RDLFNBQVEsWUFBYyxRQUFRLEdBQUU7QUFDaEMscUNBQXFDO0FBQ3JDLFNBQVEsWUFBYyxPQUFPLEdBQUU7QUFDL0IsWUFBWTtBQUtaLGNBQWM7QUFDZDs7Ozs7Q0FLQyxHQUNELE9BQU8sU0FBUyxJQUFJLENBQVMsRUFBRSxFQUFVO0VBQ3ZDLE9BQU8sRUFBRSxNQUFNLENBQUMsTUFBSSxJQUFHLEtBQUssRUFBRSxNQUFNLEdBQUM7QUFDdkM7QUFDQSxTQUFRLE9BQU8sRUFBRSxHQUFFO0FBR25COzs7OztDQUtDLEdBQ0QsT0FBTyxTQUFTLE9BQU8sQ0FBUyxFQUFFLEdBQXFCO0VBQ3JELElBQUksSUFBSTtFQUNSLEtBQUssTUFBTSxNQUFNLElBQ2YsS0FBSyxJQUFJLEdBQUc7RUFDZCxPQUFPO0FBQ1Q7QUFHQTs7Ozs7O0NBTUMsR0FDRCxPQUFPLFNBQVMsSUFBSSxDQUFTLEVBQUUsRUFBVSxFQUFFLEtBQWE7RUFDdEQsT0FBTyxFQUFFLEtBQUssQ0FBQyxHQUFHLE1BQU0sUUFBUSxFQUFFLEtBQUssQ0FBQyxLQUFHLE1BQU0sTUFBTTtBQUN6RDtBQUdBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7O0NBbUJDLEdBQ0QsT0FBTyxTQUFTLE1BQU0sQ0FBUyxFQUFFLFFBQWMsQ0FBQztFQUM5QyxPQUFPLEVBQUUsS0FBSyxDQUFDLEdBQUc7QUFDcEI7QUFDQSxTQUFRLFNBQVMsTUFBTSxHQUFFO0FBQ3pCLFNBQVEsU0FBUyxJQUFJLEdBQUU7QUFHdkI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0NBdUJDLEdBQ0QsT0FBTyxTQUFTLE9BQU8sQ0FBUyxFQUFFLEtBQWEsRUFBRSxRQUFjLENBQUM7RUFDOUQsT0FBTyxFQUFFLEtBQUssQ0FBQyxPQUFPLFFBQU07QUFDOUI7QUFDQSxTQUFRLFVBQVUsS0FBSyxHQUFFO0FBR3pCOzs7Ozs7Ozs7Ozs7Ozs7Ozs7O0NBbUJDLEdBQ0QsT0FBTyxTQUFTLElBQUksQ0FBUyxFQUFFLFFBQWMsQ0FBQztFQUM1QyxPQUFPLEVBQUUsS0FBSyxDQUFDLEVBQUUsTUFBTSxHQUFDO0FBQzFCO0FBQ0EsU0FBUSxPQUFPLE1BQU0sR0FBRTtBQUN2QixTQUFRLE9BQU8sS0FBSyxHQUFFO0FBQ3RCLFlBQVk7QUFLWixxQkFBcUI7QUFDckIsbURBQW1EO0FBRW5EOzs7OztDQUtDLEdBQ0Qsa0VBQWtFO0FBQ2xFLDhDQUE4QztBQUM5QyxJQUFJO0FBR0osdURBQXVEO0FBRXZEOzs7O0NBSUMsR0FDRCx3RUFBd0U7QUFDeEUsNkNBQTZDO0FBQzdDLElBQUk7QUFHSix5REFBeUQ7QUFFekQ7Ozs7Q0FJQyxHQUNELHlFQUF5RTtBQUN6RSw4Q0FBOEM7QUFDOUMsSUFBSTtBQUdKLHlEQUF5RDtBQUV6RDs7OztDQUlDLEdBQ0QseUVBQXlFO0FBQ3pFLDhDQUE4QztBQUM5QyxJQUFJO0FBQ0osWUFBWTtBQUtaLGdCQUFnQjtBQUNoQiwrQ0FBK0M7QUFDL0MsU0FBUyxVQUFVLEVBQW9CO0VBQ3JDLElBQUksSUFBSTtFQUNSLEtBQUssTUFBTSxLQUFLLEdBQ2QsSUFBSSxLQUFLLEdBQUcsQ0FBQyxHQUFHLEVBQUUsTUFBTTtFQUMxQixPQUFPO0FBQ1Q7QUFFQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Q0FvQkMsR0FDRCxTQUFTLFVBQVUsQ0FBUyxFQUFFLEdBQWdCLEVBQUUsSUFBWSxDQUFDLEVBQUUsSUFBWSxDQUFDO0VBQzFFLElBQUksTUFBSSxHQUFHLElBQUksVUFBVTtFQUN6QixJQUFLLElBQUksSUFBRSxHQUFHLElBQUUsR0FBRyxJQUFLO0lBQ3RCLE1BQU0sTUFBTSxFQUFFLFNBQVMsQ0FBQyxHQUFHLElBQUU7SUFDN0IsSUFBSSxJQUFJLEdBQUcsQ0FBQyxNQUFNLE9BQU87RUFDM0I7RUFDQSxPQUFPO0FBQ1Q7QUFHQTs7Ozs7Ozs7Ozs7Ozs7OztDQWdCQyxHQUNELE9BQU8sU0FBUyxtQkFBbUIsQ0FBUyxFQUFFLENBQVM7RUFDckQsSUFBSSxLQUFLLEdBQUcsS0FBSztFQUNqQixJQUFLLElBQUksSUFBRSxHQUFHLElBQUUsRUFBRSxNQUFNLEVBQUUsSUFBRSxHQUFHLElBQUs7SUFDbEMsSUFBSyxJQUFJLElBQUUsR0FBRyxJQUFFLEVBQUUsTUFBTSxFQUFFLElBQUUsR0FBRyxJQUFFLEdBQUcsSUFBSztNQUN2QyxJQUFJLENBQUMsQ0FBQyxJQUFFLEVBQUUsS0FBRyxDQUFDLENBQUMsRUFBRSxHQUFFLElBQUUsSUFBSTtNQUN6QixJQUFJLElBQUUsSUFBSTtRQUFFLEtBQUssSUFBRSxJQUFFO1FBQUcsS0FBSztNQUFHO0lBQ2xDO0VBQ0Y7RUFDQSxPQUFPLEVBQUUsU0FBUyxDQUFDLElBQUksS0FBRztBQUM1QjtBQUdBOzs7Ozs7Ozs7Ozs7Ozs7O0NBZ0JDLEdBQ0QsT0FBTyxTQUFTLG9CQUFvQixDQUFTLEVBQUUsQ0FBUztFQUN0RCxJQUFJLElBQUk7RUFDUixJQUFLLE1BQU0sSUFBRSxLQUFLLEdBQUcsQ0FBQyxFQUFFLE1BQU0sRUFBRSxFQUFFLE1BQU0sR0FBRyxJQUFFLEdBQUcsSUFDOUMsSUFBSSxDQUFDLENBQUMsRUFBRSxLQUFHLENBQUMsQ0FBQyxFQUFFLEVBQUU7RUFDbkIsT0FBTyxFQUFFLFNBQVMsQ0FBQyxHQUFHO0FBQ3hCO0FBR0E7Ozs7Ozs7Ozs7Ozs7Ozs7Q0FnQkMsR0FDRCxPQUFPLFNBQVMsb0JBQW9CLENBQVMsRUFBRSxDQUFTO0VBQ3RELElBQUksSUFBSSxFQUFFLE1BQU0sR0FBQztFQUNqQixJQUFLLElBQUksSUFBRSxFQUFFLE1BQU0sR0FBQyxHQUFHLEtBQUcsS0FBSyxLQUFHLEdBQUcsS0FBSyxJQUN4QyxJQUFJLENBQUMsQ0FBQyxFQUFFLEtBQUcsQ0FBQyxDQUFDLEVBQUUsRUFBRTtFQUNuQixPQUFPLEVBQUUsU0FBUyxDQUFDLElBQUU7QUFDdkI7QUFHQTs7Ozs7Ozs7Ozs7Ozs7OztDQWdCQyxHQUNELE9BQU8sU0FBUyx1QkFBdUIsQ0FBUyxFQUFFLENBQVM7RUFDekQsTUFBTSxJQUFJLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxNQUFNO0VBQ2hDLE1BQU0sSUFBSSxvQkFBb0IsR0FBRyxHQUFHLE1BQU07RUFDMUMsTUFBTSxJQUFJLG9CQUFvQixHQUFHLEdBQUcsTUFBTTtFQUMxQyxPQUFPO0lBQUMsRUFBRSxTQUFTLENBQUMsR0FBRyxJQUFFO0lBQUksRUFBRSxTQUFTLENBQUMsR0FBRyxJQUFFO0dBQUc7QUFDbkQ7QUFDQSxZQUFZO0FBS1oscUNBQXFDO0FBQ3JDLDBGQUEwRixHQUMxRixNQUFNLHFCQUFxQjtBQUMzQiw0RkFBNEYsR0FDNUYsTUFBTSxxQkFBcUI7QUFDM0Isc0ZBQXNGLEdBQ3RGLE1BQU0sbUJBQXFCO0FBQzNCLHdGQUF3RixHQUN4RixNQUFNLG1CQUFxQjtBQUUzQixTQUFTLGlCQUFpQixDQUFTO0VBQ2pDLElBQUksSUFBSTtFQUNSLEtBQUssSUFBSSxLQUFLLEVBQUc7SUFDZixNQUFNLElBQUksbUJBQW1CLE9BQU8sQ0FBQztJQUNyQyxNQUFNLElBQUksaUJBQWlCLE9BQU8sQ0FBQztJQUNuQyxJQUFJLEtBQUcsR0FBRyxJQUFJLGtCQUFrQixDQUFDLEVBQUU7SUFDbkMsSUFBSSxLQUFHLEdBQUcsSUFBSSxrQkFBa0IsQ0FBQyxFQUFFO0lBQ25DLEtBQUs7RUFDUDtFQUNBLE9BQU87QUFDVDtBQUVBLFNBQVMsbUJBQW1CLENBQVMsRUFBRSxJQUFpQixFQUFFLElBQWlCO0VBQ3pFLElBQUksSUFBTSxJQUFJLElBQUksR0FBRyxJQUFJO0VBQ3pCLElBQUksTUFBTSxJQUFJLE9BQU87RUFDckIsT0FBTyxRQUFRO0VBQ2YsT0FBTyxRQUFRO0VBQ2YsS0FBSyxNQUFNLEtBQUssRUFBRztJQUNqQixJQUFJLElBQUksTUFBTTtJQUNkLE1BQU0sSUFBSSxtQkFBbUIsT0FBTyxDQUFDO0lBQ3JDLE1BQU0sSUFBSSxpQkFBaUIsT0FBTyxDQUFDO0lBQ25DLE1BQU0sSUFBSSxDQUFDLEtBQUcsSUFBRyxJQUFFLENBQUMsSUFBSSxDQUFDLEtBQUcsSUFBRyxJQUFFLENBQUM7SUFDbEMsSUFBSSxNQUFJLFFBQVEsR0FBRyxLQUFLLFNBQU8sSUFBRyxNQUFPLFNBQU8sSUFBRyxLQUFLLEtBQUssSUFBRSxLQUFLLEtBQUssS0FBSyxJQUFFO0lBQ2hGLE9BQU8sTUFBSSxJQUFHLElBQUssTUFBSSxJQUFHLGtCQUFrQixDQUFDLEVBQUUsR0FBRyxnQkFBZ0IsQ0FBQyxFQUFFO0lBQ3JFLE9BQU87SUFBRztFQUNaO0VBQ0EsSUFBSSxLQUFLLEtBQUssU0FBTyxJQUFHLE1BQU8sU0FBTyxJQUFHLEtBQUssS0FBSyxJQUFFLEtBQUssS0FBSyxLQUFLLElBQUU7RUFDdEUsT0FBTztBQUNUO0FBRUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0NBb0JDLEdBQ0QsT0FBTyxTQUFTLFdBQVcsQ0FBUyxFQUFFLE9BQXlCLElBQUksRUFBRSxPQUF5QixJQUFJO0VBQ2hHLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxPQUFPLGlCQUFpQjtFQUM1QyxPQUFPLG1CQUFtQixHQUFHLFFBQVEsVUFBVSxRQUFRO0FBQ3pEO0FBR0EsbURBQW1ELEdBQ25ELE1BQU0scUJBQXFCO0FBRTNCOzs7Ozs7Ozs7Ozs7Ozs7Q0FlQyxHQUNELE9BQU8sU0FBUyxjQUFjLENBQVM7RUFDckMsSUFBSSxJQUFJO0VBQ1IsS0FBSyxNQUFNLEtBQUssRUFBRztJQUNqQixNQUFNLElBQUksa0JBQWtCLENBQUMsRUFBRSxVQUFVLENBQUMsS0FBSyxHQUFHLElBQUk7SUFDdEQsS0FBSyxNQUFJLE1BQUssSUFBSTtFQUNwQjtFQUNBLE9BQU87QUFDVDtBQUdBLGlEQUFpRCxHQUNqRCxNQUFNLG1CQUFtQjtBQUV6Qjs7Ozs7Ozs7Ozs7Ozs7O0NBZUMsR0FDRCxPQUFPLFNBQVMsWUFBWSxDQUFTO0VBQ25DLElBQUksSUFBSTtFQUNSLEtBQUssTUFBTSxLQUFLLEVBQUc7SUFDakIsTUFBTSxJQUFJLGdCQUFnQixDQUFDLEVBQUUsVUFBVSxDQUFDLEtBQUssR0FBRyxJQUFJO0lBQ3BELEtBQUssTUFBSSxNQUFLLElBQUk7RUFDcEI7RUFDQSxPQUFPO0FBQ1Q7QUFDQSxZQUFZO0FBS1osMEJBQTBCO0FBQzFCLGlGQUFpRjtBQUNqRixTQUFTLGlCQUFpQixDQUFTO0VBQ2pDLE9BQU8sRUFBRSxLQUFLLENBQUMsR0FBRyxHQUFHLFdBQVcsS0FBSyxFQUFFLEtBQUssQ0FBQyxHQUFHLFdBQVc7QUFDN0Q7QUFFQSw0RUFBNEU7QUFDNUUsU0FBUyxvQkFBb0IsQ0FBUztFQUNwQyxPQUFPLEVBQUUsS0FBSyxDQUFDLEdBQUcsR0FBRyxXQUFXLEtBQUssRUFBRSxLQUFLLENBQUM7QUFDL0M7QUFFQSw0RUFBNEU7QUFDNUUsU0FBUyxvQkFBb0IsQ0FBUztFQUNwQyxPQUFPLEVBQUUsS0FBSyxDQUFDLEdBQUcsR0FBRyxXQUFXLEtBQUssRUFBRSxLQUFLLENBQUM7QUFDL0M7QUFFQSwyRkFBMkY7QUFDM0YsU0FBUyxrQkFBa0IsQ0FBUztFQUNsQyxJQUFJLEVBQUUsTUFBTSxJQUFFLEdBQUcsT0FBTyxFQUFFLFdBQVc7RUFDckMsT0FBTyxFQUFFLEtBQUssQ0FBQyxHQUFHLEdBQUcsV0FBVyxLQUFLLEVBQUUsS0FBSyxDQUFDLEdBQUcsQ0FBQyxHQUFHLFdBQVcsS0FBSyxFQUFFLEtBQUssQ0FBQyxDQUFDLEdBQUcsV0FBVztBQUM3RjtBQUdBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Q0FxQkMsR0FDRCxPQUFPLFNBQVMsUUFBUSxDQUFTLEVBQUUsS0FBa0IsSUFBSTtFQUN2RCxNQUFNLFFBQVMsRUFBRTtFQUNqQixNQUFNLFNBQVMsRUFBRSxLQUFLLENBQUMsTUFBTSxrQkFBa0IsTUFBTSxDQUFDO0VBQ3RELEtBQUssTUFBTSxTQUFTLE9BQVE7SUFDMUIsTUFBTSxLQUFLO0lBQ1gsSUFBSSxJQUFJLE1BQU0sSUFBSTtJQUNsQixNQUFPLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQyxNQUFNLEtBQUssS0FBTTtNQUNuQyxJQUFJLE1BQUksRUFBRSxLQUFLLEVBQUUsTUFBTSxJQUFJLENBQUMsTUFBTSxLQUFLLENBQUMsR0FBRyxFQUFFLEtBQUs7TUFDbEQsSUFBSSxDQUFDLENBQUMsRUFBRSxDQUFDLE1BQU0sS0FBRyxLQUFLLEVBQUUsS0FBSyxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUMsTUFBTSxLQUFLLE1BQU0sTUFBTSxFQUFFLElBQUksRUFBRSxLQUFLO1dBQ3JFO1FBQUUsTUFBTSxJQUFJLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRSxLQUFLLEVBQUUsRUFBRSxLQUFLLEdBQUcsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxNQUFNLEdBQUc7UUFBSyxJQUFJLEVBQUUsS0FBSyxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUMsTUFBTSxHQUFHO01BQUc7SUFDckc7SUFDQSxJQUFJLE1BQUksTUFBTSxNQUFNLEVBQUUsTUFBTSxJQUFJLENBQUMsTUFBTSxLQUFLLENBQUM7RUFDL0M7RUFDQSxPQUFPO0FBQ1Q7QUFDQSx3RkFBd0Y7QUFHeEY7Ozs7Ozs7Ozs7Ozs7Ozs7Q0FnQkMsR0FDRCxPQUFPLFNBQVMsWUFBWSxDQUFTLEVBQUUsS0FBa0IsSUFBSSxFQUFFLE1BQUksR0FBRztFQUNwRSxPQUFPLFFBQVEsR0FBRyxJQUFJLEdBQUcsQ0FBQyxrQkFBa0IsSUFBSSxDQUFDO0FBQ25EO0FBR0E7Ozs7OztDQU1DLEdBQ0QsT0FBTyxTQUFTLFlBQVksQ0FBUyxFQUFFLEtBQWtCLElBQUksRUFBRSxNQUFZLEdBQUc7RUFDNUUsTUFBTSxRQUFRLEVBQUUsS0FBSyxDQUFDLE1BQU0sa0JBQWtCLE1BQU0sQ0FBQztFQUNyRCxJQUFLLElBQUksSUFBRSxHQUFHLElBQUUsTUFBTSxNQUFNLEVBQUUsSUFBRSxHQUFHLEVBQUUsRUFBRztJQUN0QyxLQUFLLENBQUMsRUFBRSxHQUFHLEtBQUssQ0FBQyxFQUFFLENBQUMsT0FBTyxDQUFDLFdBQVcsQ0FBQyxHQUFHLE1BQVEsRUFBRSxNQUFNLEtBQUcsS0FBSyxNQUFNLEVBQUUsTUFBTSxLQUFHLEtBQUssQ0FBQyxFQUFFLENBQUMsTUFBTSxHQUFFLE1BQU0sSUFBSSxNQUFNLEVBQUUsS0FBSyxDQUFDLEdBQUcsQ0FBQyxLQUFLLE1BQU0sRUFBRSxLQUFLLENBQUMsQ0FBQztJQUNySixJQUFJLEtBQUssQ0FBQyxFQUFFLENBQUMsVUFBVSxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUUsR0FBRyxLQUFLLENBQUMsRUFBRSxDQUFDLEtBQUssQ0FBQyxJQUFJLE1BQU07RUFDcEU7RUFDQSxPQUFPLE1BQU0sSUFBSSxDQUFDLEtBQUssV0FBVztBQUNwQztBQUdBOzs7Ozs7Ozs7Ozs7Ozs7O0NBZ0JDLEdBQ0QsT0FBTyxTQUFTLFlBQVksQ0FBUyxFQUFFLEtBQWtCLElBQUk7RUFDM0QsT0FBTyxZQUFZLEdBQUcsSUFBSTtBQUM1QjtBQUdBOzs7Ozs7Ozs7Ozs7Ozs7OztDQWlCQyxHQUNELE9BQU8sU0FBUyxZQUFZLENBQVMsRUFBRSxLQUFrQixJQUFJLEVBQUUsUUFBZSxLQUFLO0VBQ2pGLElBQUksSUFBSTtFQUFJLE1BQU0sUUFBUSxFQUFFLEtBQUssQ0FBQyxNQUFNLGtCQUFrQixNQUFNLENBQUM7RUFDakUsS0FBSyxNQUFNLEtBQUssTUFDZCxLQUFLLG9CQUFvQixFQUFFLE9BQU8sQ0FBQyxXQUFXO0VBQ2hELE9BQU8sUUFBTyxJQUFJLG9CQUFvQjtBQUN4QztBQUdBOzs7OztDQUtDLEdBQ0QsT0FBTyxTQUFTLGFBQWEsQ0FBUyxFQUFFLEtBQWtCLElBQUk7RUFDNUQsT0FBTyxZQUFZLEdBQUcsSUFBSTtBQUM1QjtBQUdBOzs7Ozs7Q0FNQyxHQUNELE9BQU8sU0FBUyxXQUFXLENBQVMsRUFBRSxLQUFvQixJQUFJLEVBQUUsTUFBYyxHQUFHO0VBQy9FLElBQUksRUFBRSxTQUFTLENBQUMsUUFBUSxPQUFPLENBQUMsb0JBQW9CLEtBQUssaUJBQWlCO0VBQzFFLG9DQUFvQztFQUNwQyxPQUFPLFlBQVksRUFBRSxPQUFPLENBQUMsaUJBQWlCLEtBQUssSUFBSSxNQUFNLHlCQUF5QjtBQUN4RjtBQUNBLFNBQVEsY0FBYyxPQUFPLEdBQUU7QUFDL0IsWUFBWTtBQU1aLG1CQUFtQjtBQUNuQjs7Ozs7Q0FLQyxHQUNELE9BQU8sU0FBUyxNQUFNLENBQVMsRUFBRSxLQUFhLEVBQUUsUUFBYyxFQUFFLE1BQU07RUFDcEUsSUFBSSxDQUFDLEtBQUssU0FBTyxHQUFHLE9BQU87RUFDM0IsSUFBSSxJQUFJLEVBQUUsS0FBSyxDQUFDLE9BQU8sUUFBUTtFQUMvQixTQUFVLEVBQUUsTUFBTSxFQUFHLDJCQUEyQjtFQUNoRCxNQUFNLElBQUksS0FBSyxLQUFLLENBQUMsUUFBUSxFQUFFLE1BQU07RUFDckMsSUFBSyxJQUFJLElBQUUsR0FBRyxJQUFFLEdBQUcsSUFDakIsS0FBSztFQUNQLE9BQU8sS0FBSyxFQUFFLEtBQUssQ0FBQyxHQUFHLFFBQVEsRUFBRSxNQUFNO0FBQ3pDO0FBR0E7Ozs7Q0FJQyxHQUNELE9BQU8sU0FBUyxPQUFPLENBQVMsRUFBRSxDQUFTO0VBQ3pDLE1BQU0sSUFBSSxJQUFJLEdBQUcsRUFBRSxNQUFNO0VBQ3pCLE9BQU8sRUFBRSxLQUFLLENBQUMsS0FBSyxFQUFFLEtBQUssQ0FBQyxHQUFHO0FBQ2pDO0FBR0EsMENBQTBDO0FBQzFDLGdFQUFnRTtBQUNoRSxJQUFJO0FBQ0oseUNBQXlDO0FBQ3pDLGNBQWM7QUFDZCw2Q0FBNkM7QUFDN0MsOEJBQThCO0FBQzlCLHlDQUF5QztBQUN6QyxrQkFBa0I7QUFFbEIsMENBQTBDO0FBQzFDLDRFQUE0RTtBQUM1RSxJQUFJO0FBQ0osMkNBQTJDO0FBQzNDLGdCQUFnQjtBQUNoQiw2Q0FBNkM7QUFDN0MsaUJBQWlCO0FBQ2pCLHNDQUFzQztBQUN0QyxhQUFhO0FBRWIsbUhBQW1IO0FBQ25ILGlDQUFpQztBQUNqQyxJQUFJO0FBRUosY0FBYztBQUVkLGlEQUFpRDtBQUVqRDs7OztDQUlDLEdBQ0QsNERBQTREO0FBQzVELGlEQUFpRDtBQUNqRCxJQUFJO0FBRUosMkRBQTJEO0FBRTNEOzs7O0NBSUMsR0FDRCxpRUFBaUU7QUFDakUsc0RBQXNEO0FBQ3RELElBQUk7QUFFSixzRUFBc0U7QUFDdEUseUJBQXlCO0FBQ3pCLCtCQUErQjtBQUMvQixlQUFlO0FBQ2YseUJBQXlCO0FBQ3pCLHNCQUFzQjtBQUN0QixxQ0FBcUM7QUFDckMsc0JBQXNCO0FBQ3RCLHFDQUFxQztBQUNyQyx3QkFBd0I7QUFDeEIsTUFBTTtBQUNOLGNBQWM7QUFDZCxJQUFJO0FBRUosa0VBQWtFO0FBQ2xFLHdCQUF3QjtBQUN4Qix1QkFBdUI7QUFDdkIsZ0NBQWdDO0FBQ2hDLHNCQUFzQjtBQUN0Qiw4QkFBOEI7QUFDOUIseUJBQXlCO0FBQ3pCLE1BQU07QUFDTixzQkFBc0I7QUFDdEIsOEJBQThCO0FBQzlCLDRDQUE0QztBQUM1QyxNQUFNO0FBQ04sY0FBYztBQUNkLElBQUk7QUFFSixpRkFBaUY7QUFDakYsc0NBQXNDO0FBQ3RDLCtCQUErQjtBQUMvQix1QkFBdUI7QUFDdkIseUJBQXlCO0FBQ3pCLDhCQUE4QjtBQUM5QixrQkFBa0I7QUFDbEIsd0JBQXdCO0FBQ3hCLGdDQUFnQztBQUNoQyx1Q0FBdUM7QUFDdkMsUUFBUTtBQUNSLGtCQUFrQjtBQUNsQix3QkFBd0I7QUFDeEIsZ0NBQWdDO0FBQ2hDLHVDQUF1QztBQUN2QyxRQUFRO0FBQ1Isd0JBQXdCO0FBQ3hCLE1BQU07QUFDTixjQUFjO0FBQ2QsSUFBSTtBQUVKOzs7Ozs7Q0FNQyxHQUNELDZFQUE2RTtBQUM3RSwyQ0FBMkM7QUFDM0Msb0NBQW9DO0FBQ3BDLElBQUk7QUFDSixZQUFZO0FBSVosZ0JBQWdCO0FBQ2hCOzs7Ozs7Ozs7Ozs7Ozs7O0NBZ0JDLEdBQ0QsT0FBTyxTQUFTLE9BQU8sQ0FBUyxFQUFFLENBQVM7RUFDekMsTUFBTSxJQUFJLEVBQUU7RUFDWixJQUFLLElBQUksSUFBRSxHQUFHLElBQUUsRUFBRSxNQUFNLEdBQUMsSUFBRSxHQUFHLElBQUUsR0FBRyxJQUNqQyxDQUFDLENBQUMsRUFBRSxHQUFHLEVBQUUsU0FBUyxDQUFDLEdBQUcsSUFBRTtFQUMxQixPQUFPO0FBQ1Q7QUFHQTs7Ozs7Q0FLQyxHQUNELE9BQU8sU0FBUyxhQUFhLENBQVMsRUFBRSxDQUFTO0VBQy9DLE1BQU0sSUFBaUIsSUFBSTtFQUMzQixJQUFLLElBQUksSUFBRSxHQUFHLElBQUUsRUFBRSxNQUFNLEdBQUMsSUFBRSxHQUFHLElBQUUsR0FBRyxJQUNqQyxFQUFFLEdBQUcsQ0FBQyxFQUFFLFNBQVMsQ0FBQyxHQUFHLElBQUU7RUFDekIsT0FBTztBQUNUO0FBR0E7Ozs7O0NBS0MsR0FDRCxPQUFPLFNBQVMsWUFBWSxDQUFTLEVBQUUsQ0FBUztFQUM5QyxPQUFPLEtBQUssR0FBRyxDQUFDLEdBQUcsRUFBRSxNQUFNLEdBQUMsSUFBRTtBQUNoQztBQUdBOzs7OztDQUtDLEdBQ0QsT0FBTyxTQUFTLGtCQUFrQixDQUFTLEVBQUUsQ0FBUztFQUNwRCxPQUFPLGFBQWEsR0FBRyxHQUFHLElBQUk7QUFDaEM7QUFHQTs7Ozs7Q0FLQyxHQUNELE9BQU8sU0FBUyxlQUFlLENBQVMsRUFBRSxDQUFTO0VBQ2pELE1BQU0sSUFBeUIsSUFBSTtFQUNuQyxJQUFLLElBQUksSUFBRSxHQUFHLElBQUUsRUFBRSxNQUFNLEdBQUMsSUFBRSxHQUFHLElBQUUsR0FBRyxJQUFLO0lBQ3RDLE1BQU0sSUFBSSxFQUFFLFNBQVMsQ0FBQyxHQUFHLElBQUU7SUFDM0IsRUFBRSxHQUFHLENBQUMsR0FBRyxDQUFDLEVBQUUsR0FBRyxDQUFDLE1BQU0sQ0FBQyxJQUFJO0VBQzdCO0VBQ0EsT0FBTztBQUNUO0FBR0E7Ozs7Ozs7Ozs7Ozs7Ozs7O0NBaUJDLEdBQ0QsT0FBTyxTQUFTLGVBQWUsQ0FBUyxFQUFFLENBQVMsRUFBRSxDQUFTO0VBQzVELE1BQU0sS0FBSyxlQUFlLEdBQUcsSUFBSSxJQUFJLEVBQUU7RUFDdkMsSUFBSyxJQUFJLElBQUUsR0FBRyxJQUFFLEVBQUUsTUFBTSxHQUFDLElBQUUsR0FBRyxJQUFFLEdBQUcsSUFBSztJQUN0QyxNQUFNLElBQUksRUFBRSxTQUFTLENBQUMsR0FBRyxJQUFFO0lBQzNCLE1BQU0sSUFBSSxHQUFHLEdBQUcsQ0FBQyxNQUFNO0lBQ3ZCLElBQUksR0FBRztNQUFFLEVBQUUsSUFBSSxDQUFDO01BQUksR0FBRyxHQUFHLENBQUMsR0FBRyxJQUFFO0lBQUk7RUFDdEM7RUFDQSxPQUFPO0FBQ1Q7QUFHQTs7Ozs7O0NBTUMsR0FDRCxPQUFPLFNBQVMscUJBQXFCLENBQVMsRUFBRSxDQUFTLEVBQUUsQ0FBUztFQUNsRSxNQUFNLElBQWlCLElBQUk7RUFDM0IsTUFBTSxLQUFLLGFBQWEsR0FBRztFQUMzQixJQUFLLElBQUksSUFBRSxHQUFHLElBQUUsRUFBRSxNQUFNLEdBQUMsSUFBRSxHQUFHLElBQUUsR0FBRyxJQUFLO0lBQ3RDLE1BQU0sSUFBSSxFQUFFLFNBQVMsQ0FBQyxHQUFHLElBQUU7SUFDM0IsSUFBSSxHQUFHLEdBQUcsQ0FBQyxJQUFJLEVBQUUsR0FBRyxDQUFDO0VBQ3ZCO0VBQ0EsT0FBTztBQUNUO0FBR0E7Ozs7Ozs7Ozs7Ozs7Ozs7O0NBaUJDLEdBQ0QsT0FBTyxTQUFTLG9CQUFvQixDQUFTLEVBQUUsQ0FBUyxFQUFFLENBQVM7RUFDakUsTUFBTSxLQUFLLGVBQWUsR0FBRztFQUFJLElBQUksSUFBSTtFQUN6QyxJQUFLLElBQUksSUFBRSxHQUFHLElBQUUsRUFBRSxNQUFNLEdBQUMsSUFBRSxHQUFHLElBQUUsR0FBRyxJQUFLO0lBQ3RDLE1BQU0sSUFBSSxFQUFFLFNBQVMsQ0FBQyxHQUFHLElBQUU7SUFDM0IsTUFBTSxJQUFJLEdBQUcsR0FBRyxDQUFDLE1BQU07SUFDdkIsSUFBSSxHQUFHO01BQUU7TUFBSyxHQUFHLEdBQUcsQ0FBQyxHQUFHLElBQUU7SUFBSTtFQUNoQztFQUNBLE9BQU87QUFDVDtBQUdBOzs7Ozs7Q0FNQyxHQUNELE9BQU8sU0FBUyx1QkFBdUIsQ0FBUyxFQUFFLENBQVMsRUFBRSxDQUFTO0VBQ3BFLE1BQU0sSUFBeUIsSUFBSTtFQUNuQyxNQUFNLEtBQUssZUFBZSxHQUFHO0VBQzdCLElBQUssSUFBSSxJQUFFLEdBQUcsSUFBRSxFQUFFLE1BQU0sR0FBQyxJQUFFLEdBQUcsSUFBRSxHQUFHLElBQUs7SUFDdEMsTUFBTSxJQUFJLEVBQUUsU0FBUyxDQUFDLEdBQUcsSUFBRTtJQUMzQixNQUFNLElBQUksR0FBRyxHQUFHLENBQUMsTUFBTTtJQUN2QixJQUFJLEdBQUc7TUFBRSxFQUFFLEdBQUcsQ0FBQyxHQUFHLENBQUMsRUFBRSxHQUFHLENBQUMsTUFBTSxDQUFDLElBQUk7TUFBSSxHQUFHLEdBQUcsQ0FBQyxHQUFHLElBQUU7SUFBSTtFQUMxRDtFQUNBLE9BQU87QUFDVDtBQUdBOzs7Ozs7Q0FNQyxHQUNBLE9BQU8sU0FBUywwQkFBMEIsQ0FBUyxFQUFFLENBQVMsRUFBRSxDQUFTO0VBQ3hFLE1BQU0sS0FBSyxhQUFhLEdBQUc7RUFBSSxJQUFJLElBQUk7RUFDdkMsSUFBSyxJQUFJLElBQUUsR0FBRyxJQUFFLEVBQUUsTUFBTSxHQUFDLElBQUUsR0FBRyxJQUFFLEdBQUcsSUFBSztJQUN0QyxNQUFNLElBQUksRUFBRSxTQUFTLENBQUMsR0FBRyxJQUFFO0lBQzNCLElBQUksR0FBRyxHQUFHLENBQUMsSUFBSTtNQUFFO01BQUssR0FBRyxNQUFNLENBQUM7SUFBSTtFQUN0QztFQUNBLE9BQU87QUFDVDtBQUNBLFlBQVk7QUFLWixrQkFBa0I7QUFDbEI7Ozs7Ozs7Ozs7Ozs7Ozs7Q0FnQkMsR0FDRCxPQUFPLFNBQVMsa0JBQWtCLENBQVMsRUFBRSxDQUFTO0VBQ3BELElBQUksSUFBSTtFQUNSLElBQUssSUFBSSxJQUFFLEdBQUcsSUFBRSxLQUFLLEdBQUcsQ0FBQyxFQUFFLE1BQU0sRUFBRSxFQUFFLE1BQU0sR0FBRyxJQUFFLEdBQUcsSUFBSztJQUN0RCxNQUFNLElBQUksQ0FBQyxFQUFFLFdBQVcsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEVBQUUsV0FBVyxDQUFDLE1BQU0sQ0FBQztJQUMxRCxLQUFLLElBQUk7RUFDWDtFQUNBLE9BQU8sS0FBSyxJQUFJLENBQUM7QUFDbkI7QUFDQSxpQ0FBaUM7QUFHakM7Ozs7Ozs7Ozs7Ozs7Ozs7Q0FnQkMsR0FDRCxPQUFPLFNBQVMsZ0JBQWdCLENBQVMsRUFBRSxDQUFTO0VBQ2xELElBQUksSUFBSTtFQUNSLElBQUssSUFBSSxJQUFFLEdBQUcsSUFBRSxLQUFLLEdBQUcsQ0FBQyxFQUFFLE1BQU0sRUFBRSxFQUFFLE1BQU0sR0FBRyxJQUFFLEdBQUcsSUFDakQsSUFBSSxFQUFFLE1BQU0sQ0FBQyxPQUFPLEVBQUUsTUFBTSxDQUFDLElBQUk7RUFDbkMsT0FBTztBQUNUO0FBR0E7Ozs7Ozs7Ozs7Ozs7Ozs7O0NBaUJDLEdBQ0QsT0FBTyxTQUFTLGFBQWEsQ0FBUyxFQUFFLENBQVMsRUFBRSxDQUFTO0VBQzFELE1BQU0sS0FBSyxZQUFZLEdBQUc7RUFDMUIsTUFBTSxLQUFLLFlBQVksR0FBRztFQUMxQixNQUFNLElBQUssb0JBQW9CLEdBQUcsR0FBRztFQUNyQyxPQUFPLEtBQUcsS0FBSSxJQUFFLENBQUMsS0FBRyxLQUFHLENBQUMsSUFBSTtBQUM5QjtBQUdBOzs7Ozs7Ozs7Ozs7Ozs7OztDQWlCQyxHQUNELE9BQU8sU0FBUyxnQkFBZ0IsQ0FBUyxFQUFFLENBQVMsRUFBRSxDQUFTO0VBQzdELE9BQU8sSUFBSSxhQUFhLEdBQUcsR0FBRztBQUNoQztBQUdBOzs7Ozs7Ozs7Ozs7Ozs7OztDQWlCQyxHQUNELE9BQU8sU0FBUyxrQkFBa0IsQ0FBUyxFQUFFLENBQVMsRUFBRSxDQUFTO0VBQy9ELE1BQU0sS0FBSyxZQUFZLEdBQUc7RUFDMUIsTUFBTSxLQUFLLFlBQVksR0FBRztFQUMxQixNQUFNLElBQUssb0JBQW9CLEdBQUcsR0FBRztFQUNyQyxPQUFPLEtBQUcsS0FBSSxBQUFDLElBQUUsSUFBRyxDQUFDLEtBQUcsRUFBRSxJQUFJO0FBQ2hDO0FBR0E7Ozs7Ozs7Ozs7Ozs7Ozs7O0NBaUJDLEdBQ0QsT0FBTyxTQUFTLHFCQUFxQixDQUFTLEVBQUUsQ0FBUyxFQUFFLENBQVM7RUFDbEUsT0FBTyxJQUFJLGtCQUFrQixHQUFHLEdBQUc7QUFDckM7QUFHQTs7Ozs7Ozs7Ozs7Ozs7Ozs7OztDQW1CQyxHQUNELE9BQU8sU0FBUyxhQUFhLENBQVMsRUFBRSxDQUFTLEVBQUUsQ0FBUyxFQUFFLElBQVUsQ0FBQyxFQUFFLElBQVUsQ0FBQztFQUNwRixNQUFNLEtBQUssWUFBWSxHQUFHO0VBQzFCLE1BQU0sS0FBSyxZQUFZLEdBQUc7RUFDMUIsTUFBTSxJQUFLLG9CQUFvQixHQUFHLEdBQUc7RUFDckMsT0FBTyxLQUFHLEtBQUksSUFBRSxDQUFDLElBQUksSUFBRSxDQUFDLEtBQUcsQ0FBQyxJQUFJLElBQUUsQ0FBQyxLQUFHLENBQUMsQ0FBQyxJQUFJO0FBQzlDO0FBR0E7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Q0FtQkMsR0FDRCxPQUFPLFNBQVMsZ0JBQWdCLENBQVMsRUFBRSxDQUFTLEVBQUUsQ0FBUyxFQUFFLElBQVUsQ0FBQyxFQUFFLElBQVUsQ0FBQztFQUN2RixPQUFPLElBQUksYUFBYSxHQUFHLEdBQUcsR0FBRyxHQUFHO0FBQ3RDO0FBR0E7Ozs7OztDQU1DLEdBQ0QsU0FBUyxjQUFjLENBQVMsRUFBRSxDQUFTLEVBQUUsQ0FBUztFQUNwRCwrQkFBK0I7RUFDL0IsSUFBSSxLQUFLLElBQUksS0FBSztFQUNsQixNQUFNLEtBQXdCLE1BQU0sSUFBSSxDQUFDO0VBQ3pDLGlDQUFpQztFQUNqQyxJQUFLLElBQUksSUFBRSxHQUFHLElBQUUsRUFBRSxNQUFNLEVBQUUsSUFBRSxHQUFHLElBQUs7SUFDbEMsSUFBSSxJQUFJLEdBQUcsV0FBVyxDQUFDLEVBQUUsTUFBTSxDQUFDLElBQUk7SUFDcEMsSUFBSSxJQUFFLEtBQUssSUFBRSxJQUFFLEdBQUcsSUFBSSxHQUFHLE9BQU8sQ0FBQyxFQUFFLE1BQU0sQ0FBQyxJQUFJLElBQUU7SUFDaEQsSUFBSSxJQUFFLEtBQUssSUFBRSxJQUFFLEdBQUc7SUFDbEIsTUFBTSxFQUFFLE1BQU0sQ0FBQztJQUNmLEVBQUUsQ0FBQyxFQUFFLEdBQUc7RUFDVjtFQUNBLGtDQUFrQztFQUNsQyxJQUFLLElBQUksSUFBRSxHQUFHLElBQUUsRUFBRSxNQUFNLEVBQUUsSUFBRSxHQUFHLElBQzdCLElBQUksRUFBRSxDQUFDLEVBQUUsSUFBRSxNQUFNLE1BQU0sRUFBRSxNQUFNLENBQUM7RUFDbEMsT0FBTztJQUFDO0lBQUk7R0FBRztBQUNqQjtBQUNBLHdCQUF3QjtBQUd4Qjs7Ozs7Ozs7Ozs7Ozs7OztDQWdCQyxHQUNELE9BQU8sU0FBUyxlQUFlLENBQVMsRUFBRSxDQUFTO0VBQ2pELE1BQU0sSUFBSSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsTUFBTTtFQUNoQyxNQUFNLElBQUksS0FBSyxLQUFLLENBQUMsS0FBSyxHQUFHLENBQUMsR0FBRyxLQUFHLEtBQUs7RUFDekMsTUFBTSxDQUFDLElBQUksR0FBRyxHQUFHLGNBQWMsR0FBRyxHQUFHLElBQUksSUFBSSxHQUFHLE1BQU07RUFDdEQsTUFBTSxJQUFJLGdCQUFnQixJQUFJLE1BQUk7RUFDbEMsT0FBTyxJQUFHLENBQUMsSUFBRSxJQUFJLElBQUUsSUFBSSxDQUFDLElBQUUsQ0FBQyxJQUFFLENBQUMsSUFBRSxJQUFJO0FBQ3RDO0FBR0E7Ozs7Ozs7Ozs7Ozs7Ozs7Q0FnQkMsR0FDRCxPQUFPLFNBQVMsYUFBYSxDQUFTLEVBQUUsQ0FBUztFQUMvQyxPQUFPLElBQUksZUFBZSxHQUFHO0FBQy9CO0FBR0E7Ozs7Ozs7Ozs7Ozs7Ozs7O0NBaUJDLEdBQ0QsT0FBTyxTQUFTLHNCQUFzQixDQUFTLEVBQUUsQ0FBUyxFQUFFLElBQVUsR0FBRztFQUN2RSxNQUFNLElBQUksZUFBZSxHQUFHO0VBQzVCLE1BQU0sSUFBSSxvQkFBb0IsR0FBRyxFQUFFLFNBQVMsQ0FBQyxHQUFHLElBQUksTUFBTTtFQUMxRCxPQUFPLElBQUksSUFBRSxJQUFFLENBQUMsSUFBSSxDQUFDO0FBQ3ZCO0FBR0E7Ozs7Ozs7Ozs7Ozs7Ozs7O0NBaUJDLEdBQ0QsT0FBTyxTQUFTLG9CQUFvQixDQUFTLEVBQUUsQ0FBUyxFQUFFLElBQVUsR0FBRztFQUNyRSxPQUFPLElBQUksc0JBQXNCLEdBQUcsR0FBRztBQUN6QztBQUdBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7O0NBbUJDLEdBQ0QsT0FBTyxTQUFTLG9CQUFvQixDQUFTLEVBQUUsQ0FBUyxFQUFFLE1BQVksQ0FBQyxFQUFFLE1BQVksQ0FBQyxFQUFFLE1BQVksQ0FBQztFQUNuRyxrQ0FBa0M7RUFDbEMsTUFBTSxVQUFVLHVCQUF1QixHQUFHO0VBQzFDLElBQUksT0FBTyxDQUFDLEVBQUU7RUFBRSxJQUFJLE9BQU8sQ0FBQyxFQUFFO0VBQzlCLE1BQU0sSUFBSSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsTUFBTTtFQUNoQyw2QkFBNkI7RUFDN0IsTUFBTSxLQUFlLEVBQUUsRUFBRSxLQUFlLEVBQUU7RUFDMUMsSUFBSyxJQUFJLElBQUUsR0FBRyxJQUFFLEdBQUcsS0FBRyxHQUFHLEtBQUcsSUFDMUIsRUFBRSxDQUFDLElBQUksR0FBRztFQUNaLG9DQUFvQztFQUNwQyxJQUFLLElBQUksSUFBRSxHQUFHLEtBQUcsR0FBRyxJQUFLO0lBQ3ZCLGdDQUFnQztJQUNoQyxNQUFNLEtBQUssSUFBSSxJQUFHLEtBQUs7SUFDdkIsTUFBTSxLQUFLLElBQUksSUFBRyxLQUFLO0lBQ3ZCLEVBQUUsQ0FBQyxFQUFFLEdBQUksRUFBRSxDQUFDLEVBQUUsR0FBRztJQUNqQix1Q0FBdUM7SUFDdkMsSUFBSyxJQUFJLElBQUUsR0FBRyxLQUFHLEdBQUcsSUFBSztNQUN2QixNQUFNLE9BQU8sQ0FBQyxDQUFDLElBQUUsRUFBRSxLQUFHLENBQUMsQ0FBQyxJQUFFLEVBQUUsR0FBRSxJQUFJO01BQ2xDLEVBQUUsQ0FBQyxFQUFFLEdBQUcsS0FBSyxHQUFHLENBQUMsRUFBRSxDQUFDLEVBQUUsR0FBQyxLQUFLLEVBQUUsQ0FBQyxJQUFFLEVBQUUsR0FBQyxLQUFLLEVBQUUsQ0FBQyxJQUFFLEVBQUUsR0FBQztJQUNuRDtFQUNGO0VBQ0EsT0FBTyxDQUFDLElBQUksSUFBRyxLQUFLLEVBQUUsQ0FBQyxDQUFDLEVBQUU7QUFDNUI7QUFHQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Q0FvQkMsR0FDRCxPQUFPLFNBQVMsMkJBQTJCLENBQVMsRUFBRSxDQUFTLEVBQUUsTUFBWSxDQUFDLEVBQUUsTUFBWSxDQUFDLEVBQUUsTUFBWSxDQUFDLEVBQUUsTUFBWSxDQUFDO0VBQ3pILGtDQUFrQztFQUNsQyxNQUFNLFVBQVUsdUJBQXVCLEdBQUc7RUFDMUMsSUFBSSxPQUFPLENBQUMsRUFBRTtFQUFFLElBQUksT0FBTyxDQUFDLEVBQUU7RUFDOUIsTUFBTSxJQUFJLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxNQUFNO0VBQ2hDLE1BQU0sSUFBSSxJQUFFLEdBQUcsSUFBSSxJQUFFLEdBQUcsSUFBSSxJQUFFO0VBQzlCLHdCQUF3QjtFQUN4QixNQUFNLEtBQUs7SUFBQztHQUFFLEVBQUUsS0FBSztJQUFDO0dBQUU7RUFDeEIsTUFBTSxJQUFLO0lBQUM7SUFBSTtHQUFHLEVBQUUsS0FBSyxJQUFJO0VBQzlCLElBQUssSUFBSSxJQUFFLEdBQUcsSUFBRSxHQUFHLElBQUUsR0FBRyxLQUFLLEtBQUcsSUFBSztJQUNuQyxFQUFFLENBQUMsRUFBRSxHQUFHO0lBQ1IsRUFBRSxDQUFDLEVBQUUsR0FBRztFQUNWO0VBQ0EsNEJBQTRCO0VBQzVCLElBQUssSUFBSSxJQUFFLEdBQUcsSUFBRSxHQUFHLElBQUs7SUFDdEIsMkJBQTJCO0lBQzNCLElBQUksS0FBSztJQUFHLE1BQU0sS0FBSyxDQUFDLENBQUMsSUFBRSxFQUFFO0lBQzdCLE1BQU0sS0FBSztNQUFDO01BQUcsRUFBRSxDQUFDLEVBQUUsR0FBQztLQUFJO0lBQ3pCLENBQUMsQ0FBQyxFQUFFLEdBQUc7SUFDUCwrQkFBK0I7SUFDL0IsSUFBSyxJQUFJLElBQUUsR0FBRyxJQUFFLEdBQUcsSUFBSztNQUN0QixNQUFNLElBQUksR0FBRyxHQUFHLENBQUMsQ0FBQyxDQUFDLElBQUUsRUFBRSxLQUFHLEdBQUcsSUFBSTtNQUFJLElBQUksT0FBTztNQUNoRCxJQUFJLENBQUMsQ0FBQyxJQUFFLEVBQUUsS0FBRyxDQUFDLENBQUMsSUFBRSxFQUFFLEVBQUU7UUFBRSxLQUFLLElBQUU7UUFBRyxPQUFPO01BQUc7TUFDM0MsRUFBRSxDQUFDLEVBQUUsR0FBRyxLQUFLLEdBQUcsQ0FBQyxFQUFFLENBQUMsSUFBRSxFQUFFLEdBQUMsS0FBSyxFQUFFLENBQUMsRUFBRSxHQUFDLEtBQUssRUFBRSxDQUFDLElBQUUsRUFBRSxHQUFDLE1BQU0sQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxJQUFFLElBQUUsQ0FBQyxJQUFFLE1BQUksQ0FBQyxJQUFFLElBQUUsQ0FBQztJQUNuRjtJQUNBLEdBQUcsR0FBRyxDQUFDLENBQUMsQ0FBQyxJQUFFLEVBQUUsRUFBRSxJQUFFO0VBQ25CO0VBQ0EsT0FBTyxDQUFDLENBQUMsSUFBRSxFQUFFLENBQUMsSUFBRSxFQUFFO0FBQ3BCLEVBQ0EsWUFBWTtDQUNaLFlBQVk7Q0FLWixjQUFjO0NBQ2Qsa0NBQWtDO0NBQ2xDLDJCQUEyQjtDQUMzQiwrQkFBK0I7Q0FDL0IsZ0JBQWdCO0NBQ2hCLElBQUk7Q0FDSiwwRUFBMEU7Q0FDMUUsV0FBVztDQUNYLDRFQUE0RTtDQUM1RSxlQUFlO0NBQ2Ysa0ZBQWtGO0NBQ2xGLFdBQVc7Q0FHWCw2Q0FBNkM7Q0FDN0MsZ0NBQWdDO0NBQ2hDLHNDQUFzQztDQUN0QyxrQ0FBa0M7Q0FDbEMsTUFBTTtDQUNOLHlCQUF5QjtDQUN6QiwyQkFBMkI7Q0FDM0IsZ0NBQWdDO0NBQ2hDLHNEQUFzRDtDQUN0RCxNQUFNO0NBQ04sZ0JBQWdCO0NBQ2hCLElBQUk7Q0FDSixtRkFBbUY7Q0FDbkYsZ0JBQWdCO0NBQ2hCLDBGQUEwRjtDQUMxRixpQ0FBaUM7Q0FDakMsdUZBQXVGO0NBQ3ZGLGlDQUFpQztDQUdqQyw2Q0FBNkM7Q0FDN0MsZ0NBQWdDO0NBQ2hDLHNDQUFzQztDQUN0QyxrQ0FBa0M7Q0FDbEMsTUFBTTtDQUNOLHlCQUF5QjtDQUN6QiwyQkFBMkI7Q0FDM0IsOEJBQThCO0NBQzlCLG9FQUFvRTtDQUNwRSxNQUFNO0NBQ04sZ0JBQWdCO0NBQ2hCLElBQUk7Q0FDSiw2RUFBNkU7Q0FDN0UsVUFBVTtDQUNWLDZFQUE2RTtDQUM3RSwyQkFBMkI7Q0FDM0IsOEVBQThFO0NBQzlFLDRCQUE0QjtDQUc1QixxQ0FBcUM7Q0FDckMsc0JBQXNCO0NBQ3RCLG9DQUFvQztDQUNwQyxnQkFBZ0I7Q0FDaEIsSUFBSTtDQUNKLDREQUE0RDtDQUM1RCxXQUFXO0NBQ1gsOERBQThEO0NBQzlELGVBQWU7Q0FDZiw4RUFBOEU7Q0FDOUUsV0FBVztDQUdYLGdEQUFnRDtDQUNoRCxnQ0FBZ0M7Q0FDaEMsK0JBQStCO0NBQy9CLGtDQUFrQztDQUNsQyxNQUFNO0NBQ04seUJBQXlCO0NBQ3pCLDRCQUE0QjtDQUM1QixtQ0FBbUM7Q0FDbkMsb0RBQW9EO0NBQ3BELE1BQU07Q0FDTixnQkFBZ0I7Q0FDaEIsSUFBSTtDQUNKLHVFQUF1RTtDQUN2RSxnQkFBZ0I7Q0FDaEIsZ0ZBQWdGO0NBQ2hGLGlDQUFpQztDQUNqQyw2RUFBNkU7Q0FDN0UsaUNBQWlDO0NBR2pDLGdEQUFnRDtDQUNoRCxnQ0FBZ0M7Q0FDaEMsK0JBQStCO0NBQy9CLGtDQUFrQztDQUNsQyxNQUFNO0NBQ04seUJBQXlCO0NBQ3pCLDJCQUEyQjtDQUMzQixpQ0FBaUM7Q0FDakMsa0VBQWtFO0NBQ2xFLE1BQU07Q0FDTixnQkFBZ0I7Q0FDaEIsSUFBSTtDQUdKLHlDQUF5QztDQUN6QyxXQUFXO0NBQ1gsOENBQThDO0NBQzlDLFlBQVk7Q0FDWix1Q0FBdUM7Q0FDdkMsU0FBUztDQUNULHNDQUFzQztDQUN0QyxlQUFlO0NBR2YsZ0NBQWdDO0NBQ2hDLFNBQVM7Q0FDVCxnQ0FBZ0M7Q0FDaEMsZUFBZTtDQUNmLDBCQUEwQjtDQUMxQixlQUFlO0NBR2YscUNBQXFDO0NBQ3JDLE9BQU87Q0FDUCxxQ0FBcUM7Q0FDckMsUUFBUTtDQUNSLCtCQUErQjtDQUMvQixRQUFRO0NBR1IsbUNBQW1DO0NBQ25DLFVBQVU7Q0FDVixvQ0FBb0M7Q0FDcEMsV0FBVztDQUNYLDRCQUE0QjtDQUM1QixVQUFVO0NBR1YsdUNBQXVDO0NBQ3ZDLDhFQUE4RTtDQUM5RSxFQUFFO0NBQ0YsNkNBQTZDO0NBQzdDLDhCQUE4QjtDQUM5QixFQUFFO0NBQ0YsaURBQWlEO0NBQ2pELDhCQUE4QjtDQUc5QixrQkFBa0I7Q0FDbEIsa0JBQWtCO0NBR2xCLHNCQUFzQjtDQUN0QixzQkFBc0I7Q0FDdEIsc0JBQXNCO0NBQ3RCLFlBQVkifQ==