UNPKG

extra-map

Version:

A group of functions for working with Maps.<br>

1,031 lines • 95.5 kB
import { IDENTITY, COMPARE } from "@nodef/extra-function";
import { last as arrayLast, some as arraySome, subsequences as arraySubsequences, randomValue as arrayRandomValue, randomSubsequence as arrayRandomSubsequence } from "@nodef/extra-array";
// METHODS
// =======
// ABOUT
// -----
/**
 * Check if value is a map.
 * @param v value
 * @returns v is a map?
 */ export function is(v) {
  return v instanceof Map;
}
/**
 * List all keys.
 * @param x a map
 * @returns k₀, k₁, ... | [kᵢ, vᵢ] ∈ x
 */ export function keys(x) {
  return x.keys();
}
/**
 * List all values.
 * @param x a map
 * @returns v₀, v₁, ... | [kᵢ, vᵢ] ∈ x
 */ export function values(x) {
  return x.values();
}
/**
 * List all key-value pairs.
 * @param x a map
 * @returns [k₀, v₀], [k₁, v₁], ... | [kᵢ, vᵢ] ∈ x
 */ export function entries(x) {
  return x.entries();
}
// GENERATE
// --------
/**
 * Convert entries to map.
 * @param x entries
 * @returns x as map
 */ export function from(x) {
  return new Map(x);
}
export { from as fromEntries };
/**
 * Convert entries to map.
 * @param x entries (updateable is map!)
 * @returns x as map
 */ export function from$(x) {
  return x instanceof Map ? x : new Map(x);
}
export { from$ as fromEntries$ };
/**
 * Convert lists to map.
 * @param x lists, i.e. [keys, values]
 * @returns x as map
 */ export function fromLists(x) {
  const [ks, vs] = x;
  const iv = vs[Symbol.iterator]();
  const a = new Map();
  for (const k of ks)a.set(k, iv.next().value);
  return a;
}
/**
 * Create a map from keys.
 * @param x keys
 * @param fm map function for values (v, i, x)
 * @returns x as map
 */ export function fromKeys(x, fm = null) {
  fm = fm || IDENTITY;
  const a = new Map();
  let i = -1;
  for (const k of x)a.set(k, fm(k, ++i, x));
  return a;
}
/**
 * Create a map from values.
 * @param x values
 * @param fm map function for keys (v, i, x)
 * @returns x as map
 */ export function fromValues(x, fm = null) {
  fm = fm || IDENTITY;
  const a = new Map();
  let i = -1;
  for (const v of x)a.set(fm(v, ++i, x), v);
  return a;
}
// COMPARE
// -------
/**
 * Compare two maps.
 * @param x a map
 * @param y another map
 * @param fc compare function (a, b)
 * @param fm map function (v, k, x)
 * @returns x=y: 0, otherwise: -ve/+ve
 */ export function compare(x, y, fc = null, fm = null) {
  fc = fc || COMPARE;
  fm = fm || IDENTITY;
  const ks = unionKeys(x, y);
  for (const k of ks){
    if (!x.has(k)) return -1;
    if (!y.has(k)) return 1;
    const vx = fm(x.get(k), k, x);
    const vy = fm(y.get(k), k, y);
    const c = fc(vx, vy);
    if (c !== 0) return c;
  }
  return 0;
}
/**
 * Check if two maps are equal.
 * @param x a map
 * @param y another map
 * @param fc compare function (a, b)
 * @param fm map function (v, k, x)
 * @returns x = y?
 */ export function isEqual(x, y, fc = null, fm = null) {
  return x.size === y.size && compare(x, y, fc, fm) === 0;
}
// SIZE
// ----
/**
 * Find the size of a map.
 * @param x a map
 * @returns |x|
 */ export function size(x) {
  return x.size;
}
export { size as length };
/**
 * Check if a map is empty.
 * @param x a map
 * @returns |x| = 0?
 */ export function isEmpty(x) {
  return x.size === 0;
}
// GET/SET
// -------
/**
 * Get value at key.
 * @param x a map
 * @param k key
 * @returns x[k]
 */ export function get(x, k) {
  return x.get(k);
}
/**
 * Get values at keys.
 * @param x a map
 * @param ks keys
 * @returns [x[k₀], x[k₁], ...] | [k₀, k₁, ...] = ks
 */ export function getAll(x, ks) {
  return ks.map((k)=>x.get(k));
}
/**
 * Get value at path in a nested map.
 * @param x a nested map
 * @param p path
 * @returns x[k₀][k₁][...] | [k₀, k₁, ...] = p
 */ export function getPath(x, p) {
  let xany = x;
  for (const k of p)xany = is(xany) ? xany.get(k) : undefined;
  return xany;
}
/**
 * Check if nested map has a path.
 * @param x a nested map
 * @param p path
 * @returns x[k₀][k₁][...] exists? | [k₀, k₁, ...] = p
 */ export function hasPath(x, p) {
  let xany = x;
  for (const k of p){
    if (!is(xany)) return false;
    xany = xany.get(k);
  }
  return true;
}
/**
 * Set value at key.
 * @param x a map
 * @param k key
 * @param v value
 * @returns x' | x' = x; x'[k] = v
 */ export function set(x, k, v) {
  return new Map(x).set(k, v);
}
/**
 * Set value at key.
 * @param x a map (updated)
 * @param k key
 * @param v value
 * @returns x | x[k] = v
 */ export function set$(x, k, v) {
  return x.set(k, v);
}
/**
 * Set value at path in a nested map.
 * @param x a nested map (updated)
 * @param p path
 * @param v value
 * @returns x | x[k₀][k₁][...] = v; [k₀, k₁, ...] = p
 */ export function setPath$(x, p, v) {
  const y = getPath(x, p.slice(0, -1));
  if (is(y)) y.set(arrayLast(p), v);
  return x;
}
/**
 * Exchange two values.
 * @param x a map
 * @param k a key
 * @param l another key
 * @returns x' | x' = x; x'[k] = x[l]; x'[l] = x[k]
 */ export function swap(x, k, l) {
  return swap$(new Map(x), k, l);
}
/**
 * Exchange two values.
 * @param x a map (updated)
 * @param k a key
 * @param l another key
 * @returns x | x[i] ↔ x[j]
 */ export function swap$(x, k, l) {
  const t = x.get(k);
  x.set(k, x.get(l));
  x.set(l, t);
  return x;
}
/**
 * Remove value at key.
 * @param x a map
 * @param k key
 * @returns x \\: [k]
 */ export function remove(x, k) {
  return remove$(new Map(x), k);
}
/**
 * Remove value at key.
 * @param x a map (updated)
 * @param k key
 * @returns x = x \\: [k]
 */ export function remove$(x, k) {
  x.delete(k);
  return x;
}
/**
 * Remove value at path in a nested map.
 * @param x a nested map (updated)
 * @param p path
 * @returns x = x \\: [k₀][k₁][...] | [k₀, k₁, ...] = p
 */ export function removePath$(x, p) {
  const y = getPath(x, p.slice(0, -1));
  if (is(y)) y.delete(arrayLast(p));
  return x;
}
// PROPERTY
// --------
/**
 * Count values which satisfy a test.
 * @param x a map
 * @param ft test function (v, k, x)
 * @returns Σtᵢ | tᵢ = 1 if ft(vᵢ) else 0; [kᵢ, vᵢ] ∈ x
 */ export function count(x, ft) {
  let a = 0;
  for (const [k, v] of x)if (ft(v, k, x)) ++a;
  return a;
}
/**
 * Count occurrences of values.
 * @param x a map
 * @param fm map function (v, k, x)
 * @returns Map \{value ⇒ count\}
 */ export function countAs(x, fm = null) {
  fm = fm || IDENTITY;
  const a = new Map();
  for (const [k, v] of x){
    const w = fm(v, k, x);
    const n = a.get(w) || 0;
    a.set(w, n + 1);
  }
  return a;
}
/**
 * Find smallest value.
 * @param x a map
 * @param fc compare function (a, b)
 * @param fm map function (v, k, x)
 * @returns v | v ≤ vᵢ; [kᵢ, vᵢ] ∈ x
 */ export function min(x, fc = null, fm = null) {
  return rangeEntries(x, fc, fm)[0][1];
}
/**
 * Find smallest entry.
 * @param x a map
 * @param fc compare function (a, b)
 * @param fm map function (v, k, x)
 * @returns [min_key, min_value]
 */ export function minEntry(x, fc = null, fm = null) {
  return rangeEntries(x, fc, fm)[0];
}
/**
 * Find largest value.
 * @param x a map
 * @param fc compare function (a, b)
 * @param fm map function (v, k, x)
 * @returns v | v ≥ vᵢ; [kᵢ, vᵢ] ∈ x
 */ export function max(x, fc = null, fm = null) {
  return rangeEntries(x, fc, fm)[1][1];
}
/**
 * Find largest entry.
 * @param x a map
 * @param fc compare function (a, b)
 * @param fm map function (v, k, x)
 * @returns [max_key, max_value]
 */ export function maxEntry(x, fc = null, fm = null) {
  return rangeEntries(x, fc, fm)[1];
}
/**
 * Find smallest and largest values.
 * @param x a map
 * @param fc compare function (a, b)
 * @param fm map function (v, k, x)
 * @returns [min_value, max_value]
 */ export function range(x, fc = null, fm = null) {
  const [a, b] = rangeEntries(x, fc, fm);
  return [
    a[1],
    b[1]
  ];
}
/**
 * Find smallest and largest entries.
 * @param x a map
 * @param fc compare function (a, b)
 * @param fm map function (v, k, x)
 * @returns [min_entry, max_entry]
 */ export function rangeEntries(x, fc = null, fm = null) {
  fc = fc || COMPARE;
  fm = fm || IDENTITY;
  let mk, mu, mv;
  let nk, nu, nv;
  let i = 0;
  for (const [k, u] of x){
    const v = fm(u, k, x);
    if (i === 0 || fc(v, mv) < 0) {
      mk = k;
      mu = u;
      mv = v;
    }
    if (i === 0 || fc(v, nv) > 0) {
      nk = k;
      nu = u;
      nv = v;
    }
    ++i;
  }
  return [
    [
      mk,
      mu
    ],
    [
      nk,
      nu
    ]
  ];
}
// PART
// ----
/**
 * Get first entry from map (default order).
 * @param x a map
 * @param ed default entry
 * @returns [k₀, v₀] if x ≠ Φ else ed | [k₀, v₀] ∈ x
 */ export function head(x, ed = [
  undefined,
  undefined
]) {
  for (const e of x)return e;
  return ed;
}
/**
 * Get a map without its first entry (default order).
 * @param x a map
 * @returns x \\ \{[k₀, v₀]\} if x ≠ Φ else x | [k₀, v₀] ∈ x
 */ export function tail(x) {
  return drop(x, 1);
}
/**
 * Keep first n entries only (default order).
 * @param x a map
 * @param n number of entries [1]
 * @returns \{[k₀, v₀], [k₁, v₁], ...\} | [kᵢ, vᵢ] ∈ x and |\{[k₀, v₀], [k₁, v₁], ...\}| ≤ n
 */ export function take(x, n = 1) {
  const a = new Map();
  let i = -1;
  for (const [k, v] of x){
    if (++i >= n) break;
    a.set(k, v);
  }
  return a;
}
/**
 * Keep first n entries only (default order).
 * @param x a map (updated)
 * @param n number of entries [1]
 * @returns x = \{[k₀, v₀], [k₁, v₁], ...\} | [kᵢ, vᵢ] ∈ x and |\{[k₀, v₀], [k₁, v₁], ...\}| ≤ n
 */ export function take$(x, n = 1) {
  let i = -1;
  for (const k of x.keys())if (++i >= n) x.delete(k);
  return x;
}
/**
 * Remove first n entries (default order).
 * @param x a map
 * @param n number of entries [1]
 * @returns \{[kₙ, vₙ], [kₙ₊₁, vₙ₊₁], ...\} | [kᵢ, vᵢ] ∈ x and |\{[kₙ, vₙ], [kₙ₊₁, vₙ₊₁], ...\}| ≤ max(|x| - n, 0)
 */ export function drop(x, n = 1) {
  const a = new Map();
  let i = -1;
  for (const [k, v] of x)if (++i >= n) a.set(k, v);
  return a;
}
/**
 * Remove first n entries (default order).
 * @param x a map (updated)
 * @param n number of entries [1]
 * @returns x = \{[kₙ, vₙ], [kₙ₊₁, vₙ₊₁], ...\} | [kᵢ, vᵢ] ∈ x and |\{[kₙ, vₙ], [kₙ₊₁, vₙ₊₁], ...\}| ≤ max(|x| - n, 0)
 */ export function drop$(x, n = 1) {
  let i = -1;
  for (const k of x.keys()){
    if (++i >= n) break;
    x.delete(k);
  }
  return x;
}
// ARRANGEMENTS
// ------------
/**
 * List all possible subsets.
 * @param x a map
 * @param n number of entries [-1 ⇒ any]
 * @returns entries selected by bit from 0..2^|x| if n<0; only of length n otherwise
 */ export function* subsets(x, n = -1) {
  for (const ks of arraySubsequences([
    ...x.keys()
  ], n))yield filterAt(x, ks);
}
/**
 * Pick an arbitrary key.
 * @param x a map
 * @param fr random number generator ([0, 1))
 * @returns kᵢ | [kᵢ, vᵢ] ∈ x
 */ export function randomKey(x, fr = Math.random) {
  return arrayRandomValue([
    ...x.keys()
  ], fr);
}
export { randomKey as key };
/**
 * Pick an arbitrary entry.
 * @param x a map
 * @param fr random number generator ([0, 1))
 * @returns [kᵢ, vᵢ] | [kᵢ, vᵢ] ∈ x
 */ export function randomEntry(x, fr = Math.random) {
  return arrayRandomValue([
    ...x
  ], fr);
}
export { randomEntry as entry };
/**
 * Pick an arbitrary subset.
 * @param x a map
 * @param n number of entries [-1 ⇒ any]
 * @param fr random number generator ([0, 1))
 * @returns \{[kᵢ, vᵢ], [kⱼ, vⱼ], ...\} | [kᵢ, vᵢ], [kⱼ, vⱼ], ... ∈ x; |\{[kᵢ, vᵢ], [kⱼ, vⱼ], ...\}| = |x| if n<0 else n
 */ export function randomSubset(x, n = -1, fr = Math.random) {
  const ks = arrayRandomSubsequence([
    ...x.keys()
  ], n, fr);
  return filterAt(x, ks);
}
export { randomSubset as subset };
// FIND
// ----
/**
 * Check if map has a key.
 * @param x a map
 * @param k search key
 * @returns [k, *] ∈ x?
 */ export function has(x, k) {
  return x.has(k);
}
export { has as hasKey };
/**
 * Check if map has a value.
 * @param x a map
 * @param v search value
 * @param fc compare function (a, b)
 * @param fm map function (v, k, x)
 * @returns [*, v] ∈ x?
 */ export function hasValue(x, v, fc = null, fm = null) {
  return searchValue(x, v, fc, fm) !== undefined;
}
/**
 * Check if map has an entry.
 * @param x a map
 * @param e search entry ([k, v])
 * @param fc compare function (a, b)
 * @param fm map function (v, k, x)
 * @returns [k, v] ∈ x? | [k, v] = e
 */ export function hasEntry(x, e, fc = null, fm = null) {
  fc = fc || COMPARE;
  fm = fm || IDENTITY;
  const [k, v] = e;
  return x.has(k) && fc(fm(x.get(k), k, x), v) === 0;
}
/**
 * Check if map has a subset.
 * @param x a map
 * @param y search subset
 * @param fc compare function (a, b)
 * @param fm map function (v, k, x)
 * @returns y ⊆ x?
 */ export function hasSubset(x, y, fc = null, fm = null) {
  fc = fc || COMPARE;
  fm = fm || IDENTITY;
  for (const [k, v] of y){
    if (!x.has(k)) return false;
    const wx = fm(x.get(k), k, x);
    const wy = fm(v, k, y);
    if (fc(wx, wy) !== 0) return false;
  }
  return true;
}
/**
 * Find first value passing a test (default order).
 * @param x a map
 * @param ft test function (v, k, x)
 * @returns first v | ft(v) = true; [k, v] ∈ x
 */ export function find(x, ft) {
  for (const [k, v] of x)if (ft(v, k, x)) return v;
}
/**
 * Find values passing a test.
 * @param x a map
 * @param ft test function (v, k, x)
 * @returns [v₀, v₁, ...] | ft(vᵢ) = true; [kᵢ, vᵢ] ∈ x
 */ export function findAll(x, ft) {
  const a = [];
  for (const [k, v] of x)if (ft(v, k, x)) a.push(v);
  return a;
}
/**
 * Find key of an entry passing a test.
 * @param x a map
 * @param ft test function (v, k, x)
 * @returns key of entry
 */ export function search(x, ft) {
  for (const [k, v] of x)if (ft(v, k, x)) return k;
}
/**
 * Find keys of entries passing a test.
 * @param x a map
 * @param ft test function (v, k, x)
 * @returns keys of entries
 */ export function searchAll(x, ft) {
  const a = [];
  for (const [k, v] of x)if (ft(v, k, x)) a.push(k);
  return a;
}
/**
 * Find a key with given value.
 * @param x a map
 * @param v search value
 * @param fc compare function (a, b)
 * @param fm map function (v, k, x)
 * @returns key of value
 */ export function searchValue(x, v, fc = null, fm = null) {
  fc = fc || COMPARE;
  fm = fm || IDENTITY;
  const w = fm(v, null, null);
  for (const [k, u] of x){
    const wx = fm(u, k, x);
    if (fc(wx, w) === 0) return k;
  }
}
/**
 * Find keys with given value.
 * @param x a map
 * @param v search value
 * @param fc compare function (a, b)
 * @param fm map function (v, k, x)
 * @returns keys of value
 */ export function searchValueAll(x, v, fc = null, fm = null) {
  fc = fc || COMPARE;
  fm = fm || IDENTITY;
  const w = fm(v, null, null), a = [];
  for (const [k, u] of x){
    const wx = fm(u, k, x);
    if (fc(wx, w) === 0) a.push(k);
  }
  return a;
}
// FUNCTIONAL
// ----------
/**
 * Call a function for each value.
 * @param x a map
 * @param fp process function (v, k, x)
 */ export function forEach(x, fp) {
  for (const [k, v] of x)fp(v, k, x);
}
/**
 * Check if any value satisfies a test.
 * @param x a map
 * @param ft test function (v, k, x)
 * @returns true if ft(vᵢ) = true for some [kᵢ, vᵢ] ∈ x
 */ export function some(x, ft) {
  for (const [k, v] of x)if (ft(v, k, x)) return true;
  return false;
}
/**
 * Check if all values satisfy a test.
 * @param x a map
 * @param ft test function (v, k, x)
 * @returns true if ft(vᵢ) = true for all [kᵢ, vᵢ] ∈ x
 */ export function every(x, ft) {
  for (const [k, v] of x)if (!ft(v, k, x)) return false;
  return true;
}
/**
 * Transform values of a map.
 * @param x a map
 * @param fm map function (v, k, x)
 * @returns \{[k₀, fm(v₀)], [k₁, fm(v₁)], ...\} | [kᵢ, vᵢ] ∈ x
 */ export function map(x, fm) {
  const a = new Map();
  for (const [k, v] of x)a.set(k, fm(v, k, x));
  return a;
}
/**
 * Transform values of a map.
 * @param x a map (updated)
 * @param fm map function (v, k, x)
 * @returns x = \{[k₀, fm(v₀)], [k₁, fm(v₁)], ...\} | [kᵢ, vᵢ] ∈ x
 */ export function map$(x, fm) {
  for (const [k, v] of x)x.set(k, fm(v, k, x));
  return x;
}
/**
 * Reduce values of set to a single value.
 * @param x a map
 * @param fr reduce function (acc, v, k, x)
 * @param acc initial value
 * @returns fr(fr(acc, v₀), v₁)... | fr(acc, v₀) = v₀ if acc not given
 */ export function reduce(x, fr, acc) {
  let init = arguments.length <= 2;
  for (const [k, v] of x){
    if (init) {
      acc = v;
      init = false;
    } else acc = fr(acc, v, k, x);
  }
  return acc;
}
/**
 * Keep entries which pass a test.
 * @param x a map
 * @param ft test function (v, k, x)
 * @returns \{[k₀, v₀], [k₁, v₁], ...\} | ft(vᵢ) = true; [kᵢ, vᵢ] ∈ x
 */ export function filter(x, ft) {
  const a = new Map();
  for (const [k, v] of x)if (ft(v, k, x)) a.set(k, v);
  return a;
}
/**
 * Keep entries which pass a test.
 * @param x an map (updated)
 * @param ft test function (v, k, x)
 * @returns x = \{[k₀, v₀], [k₁, v₁], ...\} | ft(vᵢ) = true; [kᵢ, vᵢ] ∈ x
 */ export function filter$(x, ft) {
  for (const [k, v] of x)if (!ft(v, k, x)) x.delete(k);
  return x;
}
/**
 * Keep values at given keys.
 * @param x a map
 * @param ks keys
 * @returns \{[k₀, v₀], [k₁, v₁], ...\} | kᵢ ∈ ks; [kᵢ, vᵢ] ∈ x
 */ export function filterAt(x, ks) {
  const a = new Map();
  for (const k of ks)a.set(k, x.get(k));
  return a;
}
/**
 * Keep values at given keys.
 * @param x a map (updated)
 * @param ks keys
 * @returns x = \{[k₀, v₀], [k₁, v₁], ...\} | kᵢ ∈ ks; [kᵢ, vᵢ] ∈ x
 */ export function filterAt$(x, ks) {
  for (const k of x.keys())if (!ks.includes(k)) x.delete(k);
  return x;
}
/**
 * Discard entries which pass a test.
 * @param x a map
 * @param ft test function (v, k, x)
 * @returns \{[k₀, v₀], [k₁, v₁], ...\} | ft(vᵢ) = false; [kᵢ, vᵢ] ∈ x
 */ export function reject(x, ft) {
  const a = new Map();
  for (const [k, v] of x)if (!ft(v, k, x)) a.set(k, v);
  return a;
}
/**
 * Discard entries which pass a test.
 * @param x a map (updated)
 * @param ft test function (v, k, x)
 * @returns x = \{[k₀, v₀], [k₁, v₁], ...\} | ft(vᵢ) = false; [kᵢ, vᵢ] ∈ x
 */ export function reject$(x, ft) {
  for (const [k, v] of x)if (ft(v, k, x)) x.delete(k);
  return x;
}
/**
 * Discard values at given keys.
 * @param x a map
 * @param ks keys
 * @returns \{[k₀, v₀], [k₁, v₁], ...\} | kᵢ ∉ ks; [kᵢ, vᵢ] ∈ x
 */ export function rejectAt(x, ks) {
  return rejectAt$(new Map(x), ks);
}
/**
 * Discard values at given keys.
 * @param x a map (updated)
 * @param ks keys
 * @returns x = \{[k₀, v₀], [k₁, v₁], ...\} | kᵢ ∉ ks; [kᵢ, vᵢ] ∈ x
 */ export function rejectAt$(x, ks) {
  for (const k of ks)x.delete(k);
  return x;
}
/**
 * Flatten nested map to given depth.
 * @param x a nested map
 * @param n maximum depth [-1 ⇒ all]
 * @param fm map function (v, k, x)
 * @param ft test function for flatten (v, k, x) [is]
 * @returns flat map
 */ export function flat(x, n = -1, fm = null, ft = null) {
  fm = fm || IDENTITY;
  ft = ft || is;
  return flatTo$(new Map(), x, n, fm, ft);
}
function flatTo$(a, x, n, fm, ft) {
  for (const [k, v] of x){
    const w = fm(v, k, x);
    if (n !== 0 && ft(w, k, x)) flatTo$(a, w, n - 1, fm, ft);
    else a.set(k, w);
  }
  return a;
}
/**
 * Flatten nested map, based on map function.
 * @param x a nested map
 * @param fm map function (v, k, x)
 * @param ft test function for flatten (v, k, x) [is]
 * @returns flat map
 */ export function flatMap(x, fm = null, ft = null) {
  fm = fm || IDENTITY;
  ft = ft || is;
  const a = new Map();
  for (const [k, v] of x){
    const w = fm(v, k, x);
    if (ft(w, k, x)) concat$(a, w);
    else a.set(k, w);
  }
  return a;
}
/**
 * Combine matching entries from maps.
 * @param xs maps
 * @param fm map function (vs, k)
 * @param fe end function (dones) [array.some]
 * @param vd default value
 * @returns [fm([x₀[k₀], x₁[k₀], ...]), fm([x₀[k₁], x₁[k₁], ...]), ...]
 */ export function zip(xs, fm = null, fe = null, vd) {
  fm = fm || IDENTITY;
  fe = fe || arraySome;
  const ks = unionKeys(...xs), a = new Map();
  for (const k of ks){
    const ds = xs.map((x)=>!x.has(k));
    if (fe(ds)) break;
    const vs = xs.map((x)=>!x.has(k) ? vd : x.get(k));
    a.set(k, fm(vs, k, null));
  }
  return a;
}
// MANIPULATION
// ------------
/**
 * Segregate entries by test result.
 * @param x a map
 * @param ft test function (v, k, x)
 * @returns [satisfies, doesnt]
 */ export function partition(x, ft) {
  const t = new Map();
  const f = new Map();
  for (const [k, v] of x){
    if (ft(v, k, x)) t.set(k, v);
    else f.set(k, v);
  }
  return [
    t,
    f
  ];
}
/**
 * Segregate entries by similarity.
 * @param x a map
 * @param fm map function (v, k, x)
 * @returns Map \{key ⇒ values\}
 */ export function partitionAs(x, fm) {
  fm = fm || IDENTITY;
  const a = new Map();
  for (const [k, v] of x){
    const w = fm(v, k, x);
    if (!a.has(w)) a.set(w, new Map());
    a.get(w).set(k, v);
  }
  return a;
}
/**
 * Break map into chunks of given size.
 * @param x a map
 * @param n chunk size [1]
 * @param s chunk step [n]
 * @returns [x[0..n], x[s..s+n], x[2s..2s+n], ...]
 */ export function chunk(x, n = 1, s = n) {
  const ks = [
    ...x.keys()
  ], a = [];
  const I = ks.length;
  for(let i = 0; i < I; i += s)a.push(filterAt(x, ks.slice(i, i + n)));
  return a;
}
// COMBINE
// -------
/**
 * Append entries from maps, preferring last.
 * @param xs maps
 * @returns x₀ ∪ x₁ ∪ ... | [x₀, x₁, ...] = xs
 */ export function concat(...xs) {
  return concat$(new Map(), ...xs);
}
/**
 * Append entries from maps, preferring last.
 * @param x a map (updated)
 * @param ys other maps
 * @returns x = x ∪ y₀ ∪ y₁ ∪ ... | [y₀, y₁, ...] = ys
 */ export function concat$(x, ...ys) {
  for (const y of ys){
    for (const [k, v] of y)x.set(k, v);
  }
  return x;
}
/**
 * Join entries together into a string.
 * @param x a map
 * @param sep separator [,]
 * @param asc associator [=]
 * @returns "$\{k₀\}=$\{v₀\},$\{k₁\}=$\{v₁\}..." | [kᵢ, vᵢ] ∈ x
 */ export function join(x, sep = ",", asc = "=") {
  let a = "";
  for (const [k, v] of x)a += k + asc + v + sep;
  return a.slice(0, -sep.length);
}
// SET OPERATIONS
// --------------
/**
 * Check if maps have no common keys.
 * @param x a map
 * @param y another map
 * @returns x ∩ y = Φ?
 */ export function isDisjoint(x, y) {
  for (const [k] of y)if (x.has(k)) return false;
  return true;
}
/**
 * Obtain keys present in any map.
 * @param xs maps
 * @returns [k₀, k₁, ...] | [kᵢ, vᵢ] ∈ x₀ ∪ x₁, ...; [x₀, x₁, ...] = xs
 */ export function unionKeys(...xs) {
  const a = new Set();
  for (const x of xs){
    for (const [k] of x)a.add(k);
  }
  return a;
}
/**
 * Obtain entries present in any map.
 * @param x a map
 * @param y another map
 * @param fc combine function (a, b)
 * @returns x ∪ y = \{[kᵢ, vᵢ] | [kᵢ, vᵢ] ∈ x or [kᵢ, vᵢ] ∈ y\}
 */ export function union(x, y, fc = null) {
  return union$(new Map(x), y, fc);
}
/**
 * Obtain entries present in any map.
 * @param x a map (updated)
 * @param y another map
 * @param fc combine function (a, b)
 * @returns x = x ∪ y = \{[kᵢ, vᵢ] | [kᵢ, vᵢ] ∈ x or [kᵢ, vᵢ] ∈ y\}
 */ export function union$(x, y, fc = null) {
  fc = fc || IDENTITY;
  for (const [k, v] of y){
    if (!x.has(k)) x.set(k, v);
    else x.set(k, fc(x.get(k), v));
  }
  return x;
}
/**
 * Obtain keys present in all maps.
 * @param xs maps
 * @returns [k₀, k₁, ...] | [kᵢ, vᵢ] ∈ x₀ ∩ x₁, ...; [x₀, x₁, ...] = xs
 */ export function intersectionKeys(...xs) {
  const a = new Set();
  if (xs.length === 0) return a;
  const x = xs[0], ys = xs.slice(1);
  LOOPX: for (const k of x.keys()){
    for (const y of ys)if (!y.has(k)) continue LOOPX;
    a.add(k);
  }
  return a;
}
/**
 * Obtain entries present in both maps.
 * @param x a map
 * @param y another map
 * @param fc combine function (a, b)
 * @returns x ∩ y = \{[kᵢ, vᵢ] | [kᵢ, vᵢ] ∈ x and [kᵢ, vᵢ] ∈ y\}
 */ export function intersection(x, y, fc = null) {
  fc = fc || IDENTITY;
  const a = new Map();
  for (const [k, v] of y)if (x.has(k)) a.set(k, fc(x.get(k), v));
  return a;
}
/**
 * Obtain entries present in both maps.
 * @param x a map (updated)
 * @param y another map
 * @param fc combine function (a, b)
 * @returns x = x ∩ y = \{[kᵢ, vᵢ] | [kᵢ, vᵢ] ∈ x and [kᵢ, vᵢ] ∈ y\}
 */ export function intersection$(x, y, fc = null) {
  fc = fc || IDENTITY;
  const ks = [];
  for (const [k, u] of [
    ...x
  ]){
    if (!y.has(k)) ks.push(k);
    x.set(k, fc(u, y.get(k)));
  }
  return rejectAt$(x, ks);
}
/**
 * Obtain entries not present in another map.
 * @param x a map
 * @param y another map
 * @returns x - y = \{[kᵢ, vᵢ] | [kᵢ, vᵢ] ∈ x, [kᵢ, *] ∉ y\}
 */ export function difference(x, y) {
  return difference$(new Map(x), y);
}
/**
 * Obtain entries not present in another map.
 * @param x a map (updated)
 * @param y another map
 * @returns x = x - y = \{[kᵢ, vᵢ] | [kᵢ, vᵢ] ∈ x, [kᵢ, *] ∉ y\}
 */ export function difference$(x, y) {
  for (const [k] of y)x.delete(k);
  return x;
}
/**
 * Obtain entries not present in both maps.
 * @param x a map
 * @param y another map
 * @returns x-y ∪ y-x
 */ export function symmetricDifference(x, y) {
  return symmetricDifference$(new Map(x), y);
}
/**
 * Obtain entries not present in both maps.
 * @param x a map (updated)
 * @param y another map
 * @returns x = x-y ∪ y-x
 */ export function symmetricDifference$(x, y) {
  for (const [k, v] of y){
    if (x.has(k)) x.delete(k);
    else x.set(k, v);
  }
  return x;
}
/**
 * List cartesian product of maps.
 * @param xs maps
 * @param fm map function (vs, i)
 * @returns x₀ × x₁ × ... = \{\{[k₀, v₀], [k₁, v₁], ...\} | [k₀, v₀] ∈ x₀, [k₁, v₁] ∈ x₁, ...]\}
 */ export function* cartesianProduct(xs, fm = null) {
  fm = fm || IDENTITY;
  const XS = xs.length;
  const kx = xs.map((x)=>[
      ...x.keys()
    ]);
  const ls = kx.map((ks)=>ks.length);
  const is = kx.map((_ks)=>0);
  for(let j = 0;; ++j){
    const a = new Map();
    for(let n = 0; n < XS; ++n){
      const i = is[n], x = xs[n];
      const ks = kx[n], k = ks[i];
      a.set(k, x.get(k));
    }
    yield fm(a, j, null);
    let r = XS - 1;
    for(; r >= 0; --r){
      if (++is[r] < ls[r]) break;
      is[r] = 0;
    }
    if (r < 0) break;
  }
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImZpbGU6Ly8vaG9tZS9ydW5uZXIvd29yay9leHRyYS1tYXAvZXh0cmEtbWFwL2luZGV4LnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIElERU5USVRZLFxuICBDT01QQVJFLFxufSBmcm9tIFwiQG5vZGVmL2V4dHJhLWZ1bmN0aW9uXCI7XG5pbXBvcnQgdHlwZSB7XG4gIE1hcEZ1bmN0aW9uIGFzIEl0ZXJhYmxlTWFwRnVuY3Rpb24sXG59IGZyb20gXCJAbm9kZWYvZXh0cmEtaXRlcmFibGVcIjtcbmltcG9ydCB7XG4gIGxhc3QgICAgICAgICBhcyBhcnJheUxhc3QsXG4gIHNvbWUgICAgICAgICBhcyBhcnJheVNvbWUsXG4gIHN1YnNlcXVlbmNlcyBhcyBhcnJheVN1YnNlcXVlbmNlcyxcbiAgcmFuZG9tVmFsdWUgIGFzIGFycmF5UmFuZG9tVmFsdWUsXG4gIHJhbmRvbVN1YnNlcXVlbmNlIGFzIGFycmF5UmFuZG9tU3Vic2VxdWVuY2UsXG59IGZyb20gXCJAbm9kZWYvZXh0cmEtYXJyYXlcIjtcblxuXG5cblxuLy8gVFlQRVNcbi8vID09PT09XG5cbi8qKiBFbnRyaWVzIGlzIGEgbGlzdCBvZiBrZXktdmFsdWUgcGFpcnMsIHdpdGggdW5pcXVlIGtleXMuICovXG5leHBvcnQgdHlwZSBFbnRyaWVzPEssIFY+ID0gSXRlcmFibGU8W0ssIFZdPjtcblxuXG4vKiogTGlzdHMgaXMgYSBwYWlyIG9mIGtleSBsaXN0IGFuZCB2YWx1ZSBsaXN0LCB3aXRoIHVuaXF1ZSBrZXlzLiAqL1xuZXhwb3J0IHR5cGUgTGlzdHM8SywgVj4gPSBbSXRlcmFibGU8Sz4sIEl0ZXJhYmxlPFY+XTtcblxuXG4vKipcbiAqIEhhbmRsZSByZWFkaW5nIG9mIGEgc2luZ2xlIHZhbHVlLlxuICogQHJldHVybnMgdmFsdWVcbiAqL1xuZXhwb3J0IHR5cGUgUmVhZEZ1bmN0aW9uPFY+ID0gKCkgPT4gVjtcblxuXG4vKipcbiAqIEhhbmRsZSBjb21iaW5pbmcgb2YgdHdvIHZhbHVlcy5cbiAqIEBwYXJhbSBhIGEgdmFsdWVcbiAqIEBwYXJhbSBiIGFub3RoZXIgdmFsdWVcbiAqIEByZXR1cm5zIGNvbWJpbmVkIHZhbHVlXG4gKi9cbmV4cG9ydCB0eXBlIENvbWJpbmVGdW5jdGlvbjxWPiA9IChhOiBWLCBiOiBWKSA9PiBWO1xuXG5cbi8qKlxuICogSGFuZGxlIGNvbXBhcmlzb24gb2YgdHdvIHZhbHVlcy5cbiAqIEBwYXJhbSBhIGEgdmFsdWVcbiAqIEBwYXJhbSBiIGFub3RoZXIgdmFsdWVcbiAqIEByZXR1cm5zIGE8YjogLXZlLCBhPWI6IDAsIGE+YjogK3ZlXG4gKi9cbmV4cG9ydCB0eXBlIENvbXBhcmVGdW5jdGlvbjxWPiA9IChhOiBWLCBiOiBWKSA9PiBudW1iZXI7XG5cblxuLyoqXG4gKiBIYW5kbGUgcHJvY2Vzc2luZyBvZiB2YWx1ZXMgaW4gYSBtYXAuXG4gKiBAcGFyYW0gdiB2YWx1ZSBpbiBtYXBcbiAqIEBwYXJhbSBrIGtleSBvZiB2YWx1ZSBpbiBtYXBcbiAqIEBwYXJhbSB4IG1hcCBjb250YWluaW5nIHRoZSB2YWx1ZVxuICovXG5leHBvcnQgdHlwZSBQcm9jZXNzRnVuY3Rpb248SywgVj4gPSAodjogViwgazogSywgeDogTWFwPEssIFY+KSA9PiB2b2lkO1xuXG5cbi8qKlxuICogSGFuZGxlIHNlbGVjdGlvbiBvZiB2YWx1ZXMgaW4gYSBtYXAuXG4gKiBAcGFyYW0gdiB2YWx1ZSBpbiBtYXBcbiAqIEBwYXJhbSBrIGtleSBvZiB2YWx1ZSBpbiBtYXBcbiAqIEBwYXJhbSB4IG1hcCBjb250YWluaW5nIHRoZSB2YWx1ZVxuICogQHJldHVybnMgc2VsZWN0ZWQ/XG4gKi9cbmV4cG9ydCB0eXBlIFRlc3RGdW5jdGlvbjxLLCBWPiA9ICh2OiBWLCBrOiBLLCB4OiBNYXA8SywgVj4pID0+IGJvb2xlYW47XG5cblxuLyoqXG4gKiBIYW5kbGUgdHJhbnNmb3JtYXRpb24gb2YgYSB2YWx1ZSB0byBhbm90aGVyLlxuICogQHBhcmFtIHYgdmFsdWUgaW4gbWFwXG4gKiBAcGFyYW0gayBrZXkgb2YgdmFsdWUgaW4gbWFwXG4gKiBAcGFyYW0geCBtYXAgY29udGFpbmluZyB0aGUgdmFsdWVcbiAqIEByZXR1cm5zIHRyYW5zZm9ybWVkIHZhbHVlXG4gKi9cbmV4cG9ydCB0eXBlIE1hcEZ1bmN0aW9uPEssIFYsIFc+ID0gKHY6IFYsIGs6IEssIHg6IE1hcDxLLCBWPiB8IG51bGwpID0+IFc7XG5cblxuLyoqXG4gKiBIYW5kbGUgcmVkdWN0aW9uIG9mIG11bHRpcGxlIHZhbHVlcyBpbnRvIGEgc2luZ2xlIHZhbHVlLlxuICogQHBhcmFtIGFjYyBhY2N1bXVsYXRvciAodGVtcG9yYXJ5IHJlc3VsdClcbiAqIEBwYXJhbSB2IHZhbHVlIGluIG1hcFxuICogQHBhcmFtIGsga2V5IG9mIHZhbHVlIGluIG1hcFxuICogQHBhcmFtIHggbWFwIGNvbnRhaW5pbmcgdGhlIHZhbHVlXG4gKiBAcmV0dXJucyByZWR1Y2VkIHZhbHVlXG4gKi9cbmV4cG9ydCB0eXBlIFJlZHVjZUZ1bmN0aW9uPEssIFYsIFc+ID0gKGFjYzogVywgdjogViwgazogSywgeDogTWFwPEssIFY+KSA9PiBXO1xuXG5cbi8qKlxuICogSGFuZGxlIGVuZGluZyBvZiBhIGNvbWJpbmVkIG1hcC5cbiAqIEBwYXJhbSBkb25lcyBp4bWXyrAgbWFwIGRvbmU/XG4gKiBAcmV0dXJucyBjb21iaW5lZCBtYXAgZG9uZT9cbiAqL1xuZXhwb3J0IHR5cGUgRW5kRnVuY3Rpb24gPSAoZG9uZXM6IGJvb2xlYW5bXSkgPT4gYm9vbGVhbjtcblxuXG5cblxuLy8gTUVUSE9EU1xuLy8gPT09PT09PVxuXG4vLyBBQk9VVFxuLy8gLS0tLS1cblxuLyoqXG4gKiBDaGVjayBpZiB2YWx1ZSBpcyBhIG1hcC5cbiAqIEBwYXJhbSB2IHZhbHVlXG4gKiBAcmV0dXJucyB2IGlzIGEgbWFwP1xuICovXG5leHBvcnQgZnVuY3Rpb24gaXModjogdW5rbm93bik6IHYgaXMgTWFwPHVua25vd24sIHVua25vd24+IHtcbiAgcmV0dXJuIHYgaW5zdGFuY2VvZiBNYXA7XG59XG5cblxuLyoqXG4gKiBMaXN0IGFsbCBrZXlzLlxuICogQHBhcmFtIHggYSBtYXBcbiAqIEByZXR1cm5zIGvigoAsIGvigoEsIC4uLiB8IFtr4bWiLCB24bWiXSDiiIggeFxuICovXG5leHBvcnQgZnVuY3Rpb24ga2V5czxLLCBWPih4OiBNYXA8SywgVj4pOiBJdGVyYWJsZUl0ZXJhdG9yPEs+IHtcbiAgcmV0dXJuIHgua2V5cygpO1xufVxuXG5cbi8qKlxuICogTGlzdCBhbGwgdmFsdWVzLlxuICogQHBhcmFtIHggYSBtYXBcbiAqIEByZXR1cm5zIHbigoAsIHbigoEsIC4uLiB8IFtr4bWiLCB24bWiXSDiiIggeFxuICovXG5leHBvcnQgZnVuY3Rpb24gdmFsdWVzPEssIFY+KHg6IE1hcDxLLCBWPik6IEl0ZXJhYmxlSXRlcmF0b3I8Vj4ge1xuICByZXR1cm4geC52YWx1ZXMoKTtcbn1cblxuXG4vKipcbiAqIExpc3QgYWxsIGtleS12YWx1ZSBwYWlycy5cbiAqIEBwYXJhbSB4IGEgbWFwXG4gKiBAcmV0dXJucyBba+KCgCwgduKCgF0sIFtr4oKBLCB24oKBXSwgLi4uIHwgW2vhtaIsIHbhtaJdIOKIiCB4XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBlbnRyaWVzPEssIFY+KHg6IE1hcDxLLCBWPik6IEl0ZXJhYmxlSXRlcmF0b3I8W0ssIFZdPiB7XG4gIHJldHVybiB4LmVudHJpZXMoKTtcbn1cblxuXG5cblxuLy8gR0VORVJBVEVcbi8vIC0tLS0tLS0tXG5cbi8qKlxuICogQ29udmVydCBlbnRyaWVzIHRvIG1hcC5cbiAqIEBwYXJhbSB4IGVudHJpZXNcbiAqIEByZXR1cm5zIHggYXMgbWFwXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmcm9tPEssIFY+KHg6IEVudHJpZXM8SywgVj4pOiBNYXA8SywgVj4ge1xuICByZXR1cm4gbmV3IE1hcCh4KTtcbn1cbmV4cG9ydCB7ZnJvbSBhcyBmcm9tRW50cmllc307XG5cblxuLyoqXG4gKiBDb252ZXJ0IGVudHJpZXMgdG8gbWFwLlxuICogQHBhcmFtIHggZW50cmllcyAodXBkYXRlYWJsZSBpcyBtYXAhKVxuICogQHJldHVybnMgeCBhcyBtYXBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGZyb20kPEssIFY+KHg6IEVudHJpZXM8SywgVj4pOiBNYXA8SywgVj4ge1xuICByZXR1cm4geCBpbnN0YW5jZW9mIE1hcD8geCA6IG5ldyBNYXAoeCk7XG59XG5leHBvcnQge2Zyb20kIGFzIGZyb21FbnRyaWVzJH07XG5cblxuLyoqXG4gKiBDb252ZXJ0IGxpc3RzIHRvIG1hcC5cbiAqIEBwYXJhbSB4IGxpc3RzLCBpLmUuIFtrZXlzLCB2YWx1ZXNdXG4gKiBAcmV0dXJucyB4IGFzIG1hcFxuICovXG5leHBvcnQgZnVuY3Rpb24gZnJvbUxpc3RzPEssIFY+KHg6IExpc3RzPEssIFY+KTogTWFwPEssIFY+IHtcbiAgY29uc3QgW2tzLCB2c10gPSB4O1xuICBjb25zdCBpdiA9IHZzW1N5bWJvbC5pdGVyYXRvcl0oKTtcbiAgY29uc3QgYSAgPSBuZXcgTWFwPEssIFY+KCk7XG4gIGZvciAoY29uc3QgayBvZiBrcylcbiAgICBhLnNldChrLCBpdi5uZXh0KCkudmFsdWUpO1xuICByZXR1cm4gYTtcbn1cblxuXG4vKipcbiAqIENyZWF0ZSBhIG1hcCBmcm9tIGtleXMuXG4gKiBAcGFyYW0geCBrZXlzXG4gKiBAcGFyYW0gZm0gbWFwIGZ1bmN0aW9uIGZvciB2YWx1ZXMgKHYsIGksIHgpXG4gKiBAcmV0dXJucyB4IGFzIG1hcFxuICovXG5leHBvcnQgZnVuY3Rpb24gZnJvbUtleXM8SywgVj1LPih4OiBJdGVyYWJsZTxLPiwgZm06IEl0ZXJhYmxlTWFwRnVuY3Rpb248SywgS3xWPiB8IG51bGw9bnVsbCk6IE1hcDxLLCBLfFY+IHtcbiAgZm0gPSBmbSB8fCBJREVOVElUWTtcbiAgY29uc3QgYSA9IG5ldyBNYXA8SywgS3xWPigpOyBsZXQgaSA9IC0xO1xuICBmb3IgKGNvbnN0IGsgb2YgeClcbiAgICBhLnNldChrLCBmbShrLCArK2ksIHgpKTtcbiAgcmV0dXJuIGE7XG59XG5cblxuLyoqXG4gKiBDcmVhdGUgYSBtYXAgZnJvbSB2YWx1ZXMuXG4gKiBAcGFyYW0geCB2YWx1ZXNcbiAqIEBwYXJhbSBmbSBtYXAgZnVuY3Rpb24gZm9yIGtleXMgKHYsIGksIHgpXG4gKiBAcmV0dXJucyB4IGFzIG1hcFxuICovXG5leHBvcnQgZnVuY3Rpb24gZnJvbVZhbHVlczxWLCBLPVY+KHg6IEl0ZXJhYmxlPFY+LCBmbTogSXRlcmFibGVNYXBGdW5jdGlvbjxWLCBWfEs+IHwgbnVsbD1udWxsKTogTWFwPFZ8SywgVj4ge1xuICBmbSA9IGZtIHx8IElERU5USVRZO1xuICBjb25zdCBhID0gbmV3IE1hcDxWfEssIFY+KCk7IGxldCBpID0gLTE7XG4gIGZvciAoY29uc3QgdiBvZiB4KVxuICAgIGEuc2V0KGZtKHYsICsraSwgeCksIHYpO1xuICByZXR1cm4gYTtcbn1cblxuXG5cblxuLy8gQ09NUEFSRVxuLy8gLS0tLS0tLVxuXG4vKipcbiAqIENvbXBhcmUgdHdvIG1hcHMuXG4gKiBAcGFyYW0geCBhIG1hcFxuICogQHBhcmFtIHkgYW5vdGhlciBtYXBcbiAqIEBwYXJhbSBmYyBjb21wYXJlIGZ1bmN0aW9uIChhLCBiKVxuICogQHBhcmFtIGZtIG1hcCBmdW5jdGlvbiAodiwgaywgeClcbiAqIEByZXR1cm5zIHg9eTogMCwgb3RoZXJ3aXNlOiAtdmUvK3ZlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjb21wYXJlPEssIFYsIFc9Vj4oeDogTWFwPEssIFY+LCB5OiBNYXA8SywgVj4sIGZjOiBDb21wYXJlRnVuY3Rpb248VnxXPiB8IG51bGw9bnVsbCwgZm06IE1hcEZ1bmN0aW9uPEssIFYsIFZ8Vz4gfCBudWxsPW51bGwpOiBudW1iZXIge1xuICBmYyA9IGZjIHx8IENPTVBBUkU7XG4gIGZtID0gZm0gfHwgSURFTlRJVFk7XG4gIGNvbnN0IGtzID0gdW5pb25LZXlzKHgsIHkpO1xuICBmb3IgKGNvbnN0IGsgb2Yga3MpIHtcbiAgICBpZiAoIXguaGFzKGspKSByZXR1cm4gLTE7XG4gICAgaWYgKCF5LmhhcyhrKSkgcmV0dXJuICAxO1xuICAgIGNvbnN0IHZ4ID0gZm0oeC5nZXQoaykgYXMgViwgaywgeCk7XG4gICAgY29uc3QgdnkgPSBmbSh5LmdldChrKSBhcyBWLCBrLCB5KTtcbiAgICBjb25zdCBjICA9IGZjKHZ4LCB2eSk7XG4gICAgaWYgKGMhPT0wKSByZXR1cm4gYztcbiAgfVxuICByZXR1cm4gMDtcbn1cblxuXG4vKipcbiAqIENoZWNrIGlmIHR3byBtYXBzIGFyZSBlcXVhbC5cbiAqIEBwYXJhbSB4IGEgbWFwXG4gKiBAcGFyYW0geSBhbm90aGVyIG1hcFxuICogQHBhcmFtIGZjIGNvbXBhcmUgZnVuY3Rpb24gKGEsIGIpXG4gKiBAcGFyYW0gZm0gbWFwIGZ1bmN0aW9uICh2LCBrLCB4KVxuICogQHJldHVybnMgeCA9IHk/XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc0VxdWFsPEssIFYsIFc9Vj4oeDogTWFwPEssIFY+LCB5OiBNYXA8SywgVj4sIGZjOiBDb21wYXJlRnVuY3Rpb248VnxXPiB8IG51bGw9bnVsbCwgZm06IE1hcEZ1bmN0aW9uPEssIFYsIFZ8Vz4gfCBudWxsPW51bGwpOiBib29sZWFuIHtcbiAgcmV0dXJuIHguc2l6ZT09PXkuc2l6ZSAmJiBjb21wYXJlKHgsIHksIGZjLCBmbSk9PT0wO1xufVxuXG5cblxuXG4vLyBTSVpFXG4vLyAtLS0tXG5cbi8qKlxuICogRmluZCB0aGUgc2l6ZSBvZiBhIG1hcC5cbiAqIEBwYXJhbSB4IGEgbWFwXG4gKiBAcmV0dXJucyB8eHxcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNpemU8SywgVj4oeDogTWFwPEssIFY+KTogbnVtYmVyIHtcbiAgcmV0dXJuIHguc2l6ZTtcbn1cbmV4cG9ydCB7c2l6ZSBhcyBsZW5ndGh9O1xuXG5cbi8qKlxuICogQ2hlY2sgaWYgYSBtYXAgaXMgZW1wdHkuXG4gKiBAcGFyYW0geCBhIG1hcFxuICogQHJldHVybnMgfHh8ID0gMD9cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzRW1wdHk8SywgVj4oeDogTWFwPEssIFY+KTogYm9vbGVhbiB7XG4gIHJldHVybiB4LnNpemU9PT0wO1xufVxuXG5cblxuXG4vLyBHRVQvU0VUXG4vLyAtLS0tLS0tXG5cbi8qKlxuICogR2V0IHZhbHVlIGF0IGtleS5cbiAqIEBwYXJhbSB4IGEgbWFwXG4gKiBAcGFyYW0gayBrZXlcbiAqIEByZXR1cm5zIHhba11cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldDxLLCBWPih4OiBNYXA8SywgVj4sIGs6IEspOiBWIHwgdW5kZWZpbmVkIHtcbiAgcmV0dXJuIHguZ2V0KGspO1xufVxuXG5cbi8qKlxuICogR2V0IHZhbHVlcyBhdCBrZXlzLlxuICogQHBhcmFtIHggYSBtYXBcbiAqIEBwYXJhbSBrcyBrZXlzXG4gKiBAcmV0dXJucyBbeFtr4oKAXSwgeFtr4oKBXSwgLi4uXSB8IFtr4oKALCBr4oKBLCAuLi5dID0ga3NcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldEFsbDxLLCBWPih4OiBNYXA8SywgVj4sIGtzOiBLW10pOiAoViB8IHVuZGVmaW5lZClbXSB7XG4gIHJldHVybiBrcy5tYXAoayA9PiB4LmdldChrKSk7XG59XG5cblxuLyoqXG4gKiBHZXQgdmFsdWUgYXQgcGF0aCBpbiBhIG5lc3RlZCBtYXAuXG4gKiBAcGFyYW0geCBhIG5lc3RlZCBtYXBcbiAqIEBwYXJhbSBwIHBhdGhcbiAqIEByZXR1cm5zIHhba+KCgF1ba+KCgV1bLi4uXSB8IFtr4oKALCBr4oKBLCAuLi5dID0gcFxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0UGF0aDxLPih4OiBNYXA8SywgdW5rbm93bj4sIHA6IEtbXSk6IHVua25vd24ge1xuICBsZXQgeGFueTogdW5rbm93biA9IHg7XG4gIGZvciAoY29uc3QgayBvZiBwKVxuICAgIHhhbnkgPSBpcyh4YW55KT8geGFueS5nZXQoaykgOiB1bmRlZmluZWQ7XG4gIHJldHVybiB4YW55O1xufVxuXG5cbi8qKlxuICogQ2hlY2sgaWYgbmVzdGVkIG1hcCBoYXMgYSBwYXRoLlxuICogQHBhcmFtIHggYSBuZXN0ZWQgbWFwXG4gKiBAcGFyYW0gcCBwYXRoXG4gKiBAcmV0dXJucyB4W2vigoBdW2vigoFdWy4uLl0gZXhpc3RzPyB8IFtr4oKALCBr4oKBLCAuLi5dID0gcFxuICovXG5leHBvcnQgZnVuY3Rpb24gaGFzUGF0aDxLPih4OiBNYXA8SywgdW5rbm93bj4sIHA6IEtbXSk6IGJvb2xlYW4ge1xuICBsZXQgeGFueTogdW5rbm93biA9IHg7XG4gIGZvciAoY29uc3QgayBvZiBwKSB7XG4gICAgaWYgKCFpcyh4YW55KSkgcmV0dXJuIGZhbHNlO1xuICAgIHhhbnkgPSB4YW55LmdldChrKTtcbiAgfVxuICByZXR1cm4gdHJ1ZTtcbn1cblxuXG4vKipcbiAqIFNldCB2YWx1ZSBhdCBrZXkuXG4gKiBAcGFyYW0geCBhIG1hcFxuICogQHBhcmFtIGsga2V5XG4gKiBAcGFyYW0gdiB2YWx1ZVxuICogQHJldHVybnMgeCcgfCB4JyA9IHg7IHgnW2tdID0gdlxuICovXG5leHBvcnQgZnVuY3Rpb24gc2V0PEssIFY+KHg6IEVudHJpZXM8SywgVj4sIGs6IEssIHY6IFYpOiBNYXA8SywgVj4ge1xuICByZXR1cm4gbmV3IE1hcCh4KS5zZXQoaywgdik7XG59XG5cblxuLyoqXG4gKiBTZXQgdmFsdWUgYXQga2V5LlxuICogQHBhcmFtIHggYSBtYXAgKHVwZGF0ZWQpXG4gKiBAcGFyYW0gayBrZXlcbiAqIEBwYXJhbSB2IHZhbHVlXG4gKiBAcmV0dXJucyB4IHwgeFtrXSA9IHZcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNldCQ8SywgVj4oeDogTWFwPEssIFY+LCBrOiBLLCB2OiBWKTogTWFwPEssIFY+IHtcbiAgcmV0dXJuIHguc2V0KGssIHYpO1xufVxuXG5cbi8qKlxuICogU2V0IHZhbHVlIGF0IHBhdGggaW4gYSBuZXN0ZWQgbWFwLlxuICogQHBhcmFtIHggYSBuZXN0ZWQgbWFwICh1cGRhdGVkKVxuICogQHBhcmFtIHAgcGF0aFxuICogQHBhcmFtIHYgdmFsdWVcbiAqIEByZXR1cm5zIHggfCB4W2vigoBdW2vigoFdWy4uLl0gPSB2OyBba+KCgCwga+KCgSwgLi4uXSA9IHBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNldFBhdGgkPEs+KHg6IE1hcDxLLCB1bmtub3duPiwgcDogS1tdLCB2OiB1bmtub3duKTogTWFwPEssIHVua25vd24+IHtcbiAgY29uc3QgeSA9IGdldFBhdGgoeCwgcC5zbGljZSgwLCAtMSkpO1xuICBpZiAoaXMoeSkpIHkuc2V0KGFycmF5TGFzdChwKSwgdik7XG4gIHJldHVybiB4O1xufVxuXG5cbi8qKlxuICogRXhjaGFuZ2UgdHdvIHZhbHVlcy5cbiAqIEBwYXJhbSB4IGEgbWFwXG4gKiBAcGFyYW0gayBhIGtleVxuICogQHBhcmFtIGwgYW5vdGhlciBrZXlcbiAqIEByZXR1cm5zIHgnIHwgeCcgPSB4OyB4J1trXSA9IHhbbF07IHgnW2xdID0geFtrXVxuICovXG5leHBvcnQgZnVuY3Rpb24gc3dhcDxLLCBWPih4OiBFbnRyaWVzPEssIFY+LCBrOiBLLCBsOiBLKTogTWFwPEssIFY+IHtcbiAgcmV0dXJuIHN3YXAkKG5ldyBNYXAoeCksIGssIGwpO1xufVxuXG5cbi8qKlxuICogRXhjaGFuZ2UgdHdvIHZhbHVlcy5cbiAqIEBwYXJhbSB4IGEgbWFwICh1cGRhdGVkKVxuICogQHBhcmFtIGsgYSBrZXlcbiAqIEBwYXJhbSBsIGFub3RoZXIga2V5XG4gKiBAcmV0dXJucyB4IHwgeFtpXSDihpQgeFtqXVxuICovXG5leHBvcnQgZnVuY3Rpb24gc3dhcCQ8SywgVj4oeDogTWFwPEssIFY+LCBrOiBLLCBsOiBLKTogTWFwPEssIFY+IHtcbiAgY29uc3QgdCAgPSB4LmdldChrKTtcbiAgeC5zZXQoaywgeC5nZXQobCkgYXMgVik7XG4gIHguc2V0KGwsIHQgYXMgVik7XG4gIHJldHVybiB4O1xufVxuXG5cbi8qKlxuICogUmVtb3ZlIHZhbHVlIGF0IGtleS5cbiAqIEBwYXJhbSB4IGEgbWFwXG4gKiBAcGFyYW0gayBrZXlcbiAqIEByZXR1cm5zIHggXFxcXDogW2tdXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZW1vdmU8SywgVj4oeDogRW50cmllczxLLCBWPiwgazogSyk6IE1hcDxLLCBWPiB7XG4gIHJldHVybiByZW1vdmUkKG5ldyBNYXAoeCksIGspO1xufVxuXG5cbi8qKlxuICogUmVtb3ZlIHZhbHVlIGF0IGtleS5cbiAqIEBwYXJhbSB4IGEgbWFwICh1cGRhdGVkKVxuICogQHBhcmFtIGsga2V5XG4gKiBAcmV0dXJucyB4ID0geCBcXFxcOiBba11cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlbW92ZSQ8SywgVj4oeDogTWFwPEssIFY+LCBrOiBLKTogTWFwPEssIFY+IHtcbiAgeC5kZWxldGUoayk7XG4gIHJldHVybiB4O1xufVxuXG5cbi8qKlxuICogUmVtb3ZlIHZhbHVlIGF0IHBhdGggaW4gYSBuZXN0ZWQgbWFwLlxuICogQHBhcmFtIHggYSBuZXN0ZWQgbWFwICh1cGRhdGVkKVxuICogQHBhcmFtIHAgcGF0aFxuICogQHJldHVybnMgeCA9IHggXFxcXDogW2vigoBdW2vigoFdWy4uLl0gfCBba+KCgCwga+KCgSwgLi4uXSA9IHBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlbW92ZVBhdGgkPEs+KHg6IE1hcDxLLCB1bmtub3duPiwgcDogS1tdKTogTWFwPEssIHVua25vd24+IHtcbiAgY29uc3QgeSA9IGdldFBhdGgoeCwgcC5zbGljZSgwLCAtMSkpO1xuICBpZiAoaXMoeSkpIHkuZGVsZXRlKGFycmF5TGFzdChwKSk7XG4gIHJldHVybiB4O1xufVxuXG5cblxuXG4vLyBQUk9QRVJUWVxuLy8gLS0tLS0tLS1cblxuLyoqXG4gKiBDb3VudCB2YWx1ZXMgd2hpY2ggc2F0aXNmeSBhIHRlc3QuXG4gKiBAcGFyYW0geCBhIG1hcFxuICogQHBhcmFtIGZ0IHRlc3QgZnVuY3Rpb24gKHYsIGssIHgpXG4gKiBAcmV0dXJucyDOo3ThtaIgfCB04bWiID0gMSBpZiBmdCh24bWiKSBlbHNlIDA7IFtr4bWiLCB24bWiXSDiiIggeFxuICovXG5leHBvcnQgZnVuY3Rpb24gY291bnQ8SywgVj4oeDogTWFwPEssIFY+LCBmdDogVGVzdEZ1bmN0aW9uPEssIFY+KTogbnVtYmVyIHtcbiAgbGV0IGEgPSAwO1xuICBmb3IgKGNvbnN0IFtrLCB2XSBvZiB4KVxuICAgIGlmIChmdCh2LCBrLCB4KSkgKythO1xuICByZXR1cm4gYTtcbn1cblxuXG4vKipcbiAqIENvdW50IG9jY3VycmVuY2VzIG9mIHZhbHVlcy5cbiAqIEBwYXJhbSB4IGEgbWFwXG4gKiBAcGFyYW0gZm0gbWFwIGZ1bmN0aW9uICh2LCBrLCB4KVxuICogQHJldHVybnMgTWFwIFxce3ZhbHVlIOKHkiBjb3VudFxcfVxuICovXG5leHBvcnQgZnVuY3Rpb24gY291bnRBczxLLCBWLCBXPVY+KHg6IE1hcDxLLCBWPiwgZm06IE1hcEZ1bmN0aW9uPEssIFYsIFZ8Vz4gfCBudWxsPW51bGwpOiBNYXA8VnxXLCBudW1iZXI+IHtcbiAgZm0gPSBmbSB8fCBJREVOVElUWTtcbiAgY29uc3QgYSAgPSBuZXcgTWFwKCk7XG4gIGZvciAoY29uc3QgW2ssIHZdIG9mIHgpIHtcbiAgICBjb25zdCB3ID0gZm0odiwgaywgeCk7XG4gICAgY29uc3QgbiA9IGEuZ2V0KHcpIHx8IDA7XG4gICAgYS5zZXQodywgbisxKTtcbiAgfVxuICByZXR1cm4gYTtcbn1cblxuXG4vKipcbiAqIEZpbmQgc21hbGxlc3QgdmFsdWUuXG4gKiBAcGFyYW0geCBhIG1hcFxuICogQHBhcmFtIGZjIGNvbXBhcmUgZnVuY3Rpb24gKGEsIGIpXG4gKiBAcGFyYW0gZm0gbWFwIGZ1bmN0aW9uICh2LCBrLCB4KVxuICogQHJldHVybnMgdiB8IHYg4omkIHbhtaI7IFtr4bWiLCB24bWiXSDiiIggeFxuICovXG5leHBvcnQgZnVuY3Rpb24gbWluPEssIFYsIFc9Vj4oeDogTWFwPEssIFY+LCBmYzogQ29tcGFyZUZ1bmN0aW9uPFZ8Vz4gfCBudWxsPW51bGwsIGZtOiBNYXBGdW5jdGlvbjxLLCBWLCBWfFc+IHwgbnVsbD1udWxsKTogViB7XG4gIHJldHVybiByYW5nZUVudHJpZXMoeCwgZmMsIGZtKVswXVsxXTtcbn1cblxuXG4vKipcbiAqIEZpbmQgc21hbGxlc3QgZW50cnkuXG4gKiBAcGFyYW0geCBhIG1hcFxuICogQHBhcmFtIGZjIGNvbXBhcmUgZnVuY3Rpb24gKGEsIGIpXG4gKiBAcGFyYW0gZm0gbWFwIGZ1bmN0aW9uICh2LCBrLCB4KVxuICogQHJldHVybnMgW21pbl9rZXksIG1pbl92YWx1ZV1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1pbkVudHJ5PEssIFYsIFc9Vj4oeDogTWFwPEssIFY+LCBmYzogQ29tcGFyZUZ1bmN0aW9uPFZ8Vz4gfCBudWxsPW51bGwsIGZtOiBNYXBGdW5jdGlvbjxLLCBWLCBWfFc+IHwgbnVsbD1udWxsKTogW0ssIFZdIHtcbiAgcmV0dXJuIHJhbmdlRW50cmllcyh4LCBmYywgZm0pWzBdO1xufVxuXG5cbi8qKlxuICogRmluZCBsYXJnZXN0IHZhbHVlLlxuICogQHBhcmFtIHggYSBtYXBcbiAqIEBwYXJhbSBmYyBjb21wYXJlIGZ1bmN0aW9uIChhLCBiKVxuICogQHBhcmFtIGZtIG1hcCBmdW5jdGlvbiAodiwgaywgeClcbiAqIEByZXR1cm5zIHYgfCB2IOKJpSB24bWiOyBba+G1oiwgduG1ol0g4oiIIHhcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1heDxLLCBWLCBXPVY+KHg6IE1hcDxLLCBWPiwgZmM6IENvbXBhcmVGdW5jdGlvbjxWfFc+IHwgbnVsbD1udWxsLCBmbTogTWFwRnVuY3Rpb248SywgViwgVnxXPiB8IG51bGw9bnVsbCk6IFYge1xuICByZXR1cm4gcmFuZ2VFbnRyaWVzKHgsIGZjLCBmbSlbMV1bMV07XG59XG5cblxuLyoqXG4gKiBGaW5kIGxhcmdlc3QgZW50cnkuXG4gKiBAcGFyYW0geCBhIG1hcFxuICogQHBhcmFtIGZjIGNvbXBhcmUgZnVuY3Rpb24gKGEsIGIpXG4gKiBAcGFyYW0gZm0gbWFwIGZ1bmN0aW9uICh2LCBrLCB4KVxuICogQHJldHVybnMgW21heF9rZXksIG1heF92YWx1ZV1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1heEVudHJ5PEssIFYsIFc9Vj4oeDogTWFwPEssIFY+LCBmYzogQ29tcGFyZUZ1bmN0aW9uPFZ8Vz4gfCBudWxsPW51bGwsIGZtOiBNYXBGdW5jdGlvbjxLLCBWLCBWfFc+IHwgbnVsbD1udWxsKTogW0ssIFZdIHtcbiAgcmV0dXJuIHJhbmdlRW50cmllcyh4LCBmYywgZm0pWzFdO1xufVxuXG5cbi8qKlxuICogRmluZCBzbWFsbGVzdCBhbmQgbGFyZ2VzdCB2YWx1ZXMuXG4gKiBAcGFyYW0geCBhIG1hcFxuICogQHBhcmFtIGZjIGNvbXBhcmUgZnVuY3Rpb24gKGEsIGIpXG4gKiBAcGFyYW0gZm0gbWFwIGZ1bmN0aW9uICh2LCBrLCB4KVxuICogQHJldHVybnMgW21pbl92YWx1ZSwgbWF4X3ZhbHVlXVxuICovXG5leHBvcnQgZnVuY3Rpb24gcmFuZ2U8SywgViwgVz1WPih4OiBNYXA8SywgVj4sIGZjOiBDb21wYXJlRnVuY3Rpb248VnxXPiB8IG51bGw9bnVsbCwgZm06IE1hcEZ1bmN0aW9uPEssIFYsIFZ8Vz4gfCBudWxsPW51bGwpOiBbViwgVl0ge1xuICBjb25zdCBbYSwgYl0gPSByYW5nZUVudHJpZXMoeCwgZmMsIGZtKTtcbiAgcmV0dXJuIFthWzFdLCBiWzFdXTtcbn1cblxuXG4vKipcbiAqIEZpbmQgc21hbGxlc3QgYW5kIGxhcmdlc3QgZW50cmllcy5cbiAqIEBwYXJhbSB4IGEgbWFwXG4gKiBAcGFyYW0gZmMgY29tcGFyZSBmdW5jdGlvbiAoYSwgYilcbiAqIEBwYXJhbSBmbSBtYXAgZnVuY3Rpb24gKHYsIGssIHgpXG4gKiBAcmV0dXJucyBbbWluX2VudHJ5LCBtYXhfZW50cnldXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByYW5nZUVudHJpZXM8SywgViwgVz1WPih4OiBNYXA8SywgVj4sIGZjOiBDb21wYXJlRnVuY3Rpb248VnxXPiB8IG51bGw9bnVsbCwgZm06IE1hcEZ1bmN0aW9uPEssIFYsIFZ8Vz4gfCBudWxsPW51bGwpOiBbW0ssIFZdLCBbSywgVl1dIHtcbiAgZmMgPSBmYyB8fCBDT01QQVJFO1xuICBmbSA9IGZtIHx8IElERU5USVRZO1xuICBsZXQgbWs6IEsgfCB1bmRlZmluZWQsIG11OiBWIHwgdW5kZWZpbmVkLCBtdjogVnxXIHwgdW5kZWZpbmVkO1xuICBsZXQgbms6IEsgfCB1bmRlZmluZWQsIG51OiBWIHwgdW5kZWZpbmVkLCBudjogVnxXIHwgdW5kZWZpbmVkO1xuICBsZXQgaSA9IDA7XG4gIGZvciAoY29uc3QgW2ssIHVdIG9mIHgpIHtcbiAgICBjb25zdCB2ID0gZm0odSwgaywgeCk7XG4gICAgaWYgKGk9PT0wIHx8IGZjKHYsIG12IGFzIFZ8Vyk8MCkgeyBtayA9IGs7IG11ID0gdTsgbXYgPSB2OyB9XG4gICAgaWYgKGk9PT0wIHx8IGZjKHYsIG52IGFzIFZ8Vyk+MCkgeyBuayA9IGs7IG51ID0gdTsgbnYgPSB2OyB9XG4gICAgKytpO1xuICB9XG4gIHJldHVybiBbW21rIGFzIEssIG11IGFzIFZdLCBbbmsgYXMgSywgbnUgYXMgVl1dO1xufVxuXG5cblxuXG4vLyBQQVJUXG4vLyAtLS0tXG5cbi8qKlxuICogR2V0IGZpcnN0IGVudHJ5IGZyb20gbWFwIChkZWZhdWx0IG9yZGVyKS5cbiAqIEBwYXJhbSB4IGEgbWFwXG4gKiBAcGFyYW0gZWQgZGVmYXVsdCBlbnRyeVxuICogQHJldHVybnMgW2vigoAsIHbigoBdIGlmIHgg4omgIM6mIGVsc2UgZWQgfCBba+KCgCwgduKCgF0g4oiIIHhcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGhlYWQ8SywgVj4oeDogRW50cmllczxLLCBWPiwgZWQ6IFtLIHwgdW5kZWZpbmVkLCBWIHwgdW5kZWZpbmVkXT1bdW5kZWZpbmVkLCB1bmRlZmluZWRdKTogW0sgfCB1bmRlZmluZWQsIFYgfCB1bmRlZmluZWRdIHtcbiAgZm9yIChjb25zdCBlIG9mIHgpXG4gICAgcmV0dXJuIGU7XG4gIHJldHVybiBlZDtcbn1cblxuXG4vKipcbiAqIEdldCBhIG1hcCB3aXRob3V0IGl0cyBmaXJzdCBlbnRyeSAoZGVmYXVsdCBvcmRlcikuXG4gKiBAcGFyYW0geCBhIG1hcFxuICogQHJldHVybnMgeCBcXFxcIFxce1tr4oKALCB24oKAXVxcfSBpZiB4IOKJoCDOpiBlbHNlIHggfCBba+KCgCwgduKCgF0g4oiIIHhcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRhaWw8SywgVj4oeDogTWFwPEssIFY+KTogTWFwPEssIFY+IHtcbiAgcmV0dXJuIGRyb3AoeCwgMSk7XG59XG5cblxuLyoqXG4gKiBLZWVwIGZpcnN0IG4gZW50cmllcyBvbmx5IChkZWZhdWx0IG9yZGVyKS5cbiAqIEBwYXJhbSB4IGEgbWFwXG4gKiBAcGFyYW0gbiBudW1iZXIgb2YgZW50cmllcyBbMV1cbiAqIEByZXR1cm5zIFxce1tr4oKALCB24oKAXSwgW2vigoEsIHbigoFdLCAuLi5cXH0gfCBba+G1oiwgduG1ol0g4oiIIHggYW5kIHxcXHtba+KCgCwgduKCgF0sIFtr4oKBLCB24oKBXSwgLi4uXFx9fCDiiaQgblxuICovXG5leHBvcnQgZnVuY3Rpb24gdGFrZTxLLCBWPih4OiBNYXA8SywgVj4sIG46IG51bWJlcj0xKTogTWFwPEssIFY+IHtcbiAgY29uc3QgYSA9IG5ldyBNYXAoKTsgbGV0IGkgPSAtMTtcbiAgZm9yIChjb25zdCBbaywgdl0gb2YgeCkge1xuICAgIGlmICgrK2k+PW4pIGJyZWFrO1xuICAgIGEuc2V0KGssIHYpO1xuICB9XG4gIHJldHVybiBhO1xufVxuXG5cbi8qKlxuICogS2VlcCBmaXJzdCBuIGVudHJpZXMgb25seSAoZGVmYXVsdCBvcmRlcikuXG4gKiBAcGFyYW0geCBhIG1hcCAodXBkYXRlZClcbiAqIEBwYXJhbSBuIG51bWJlciBvZiBlbnRyaWVzIFsxXVxuICogQHJldHVybnMgeCA9IFxce1tr4oKALCB24oKAXSwgW2vigoEsIHbigoFdLCAuLi5cXH0gfCBba+G1oiwgduG1ol0g4oiIIHggYW5kIHxcXHtba+KCgCwgduKCgF0sIFtr4oKBLCB24oKBXSwgLi4uXFx9fCDiiaQgblxuICovXG5leHBvcnQgZnVuY3Rpb24gdGFrZSQ8SywgVj4oeDogTWFwPEssIFY+LCBuOiBudW1iZXI9MSk6IE1hcDxLLCBWPiB7XG4gIGxldCBpID0gLTE7XG4gIGZvciAoY29uc3QgayBvZiB4LmtleXMoKSlcbiAgICBpZiAoKytpPj1uKSB4LmRlbGV0ZShrKTtcbiAgcmV0dXJuIHg7XG59XG5cblxuLyoqXG4gKiBSZW1vdmUgZmlyc3QgbiBlbnRyaWVzIChkZWZhdWx0IG9yZGVyKS5cbiAqIEBwYXJhbSB4IGEgbWFwXG4gKiBAcGFyYW0gbiBudW1iZXIgb2YgZW50cmllcyBbMV1cbiAqIEByZXR1cm5zIFxce1tr4oKZLCB24oKZXSwgW2vigpnigorigoEsIHbigpnigorigoFdLCAuLi5cXH0gfCBba+G1oiwgduG1ol0g4oiIIHggYW5kIHxcXHtba+KCmSwgduKCmV0sIFtr4oKZ4oKK4oKBLCB24oKZ4oKK4oKBXSwgLi4uXFx9fCDiiaQgbWF4KHx4fCAtIG4sIDApXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBkcm9wPEssIFY+KHg6IE1hcDxLLCBWPiwgbjogbnVtYmVyPTEpOiBNYXA8SywgVj4ge1xuICBjb25zdCBhID0gbmV3IE1hcCgpOyBsZXQgaSA9IC0xO1xuICBmb3IgKGNvbnN0IFtrLCB2XSBvZiB4KVxuICAgIGlmICgrK2k+PW4pIGEuc2V0KGssIHYpO1xuICByZXR1cm4gYTtcbn1cblxuXG4vKipcbiAqIFJlbW92ZSBmaXJzdCBuIGVudHJpZXMgKGRlZmF1bHQgb3JkZXIpLlxuICogQHBhcmFtIHggYSBtYXAgKHVwZGF0ZWQpXG4gKiBAcGFyYW0gbiBudW1iZXIgb2YgZW50cmllcyBbMV1cbiAqIEByZXR1cm5zIHggPSBcXHtba+KCmSwgduKCmV0sIFtr4oKZ4oKK4oKBLCB24oKZ4oKK4oKBXSwgLi4uXFx9IHwgW2vhtaIsIHbhtaJdIOKIiCB4IGFuZCB8XFx7W2vigpksIHbigpldLCBba+KCmeKCiuKCgSwgduKCmeKCiuKCgV0sIC4uLlxcfXwg4omkIG1heCh8eHwgLSBuLCAwKVxuICovXG5leHBvcnQgZnVuY3Rpb24gZHJvcCQ8SywgVj4oeDogTWFwPEssIFY+LCBuOiBudW1iZXI9MSk6IE1hcDxLLCBWPiB7XG4gIGxldCBpID0gLTE7XG4gIGZvciAoY29uc3QgayBvZiB4LmtleXMoKSkge1xuICAgIGlmICgrK2k+PW4pIGJyZWFrO1xuICAgIHguZGVsZXRlKGspO1xuICB9XG4gIHJldHVybiB4O1xufVxuXG5cblxuXG4vLyBBUlJBTkdFTUVOVFNcbi8vIC0tLS0tLS0tLS0tLVxuXG4vKipcbiAqIExpc3QgYWxsIHBvc3NpYmxlIHN1YnNldHMuXG4gKiBAcGFyYW0geCBhIG1hcFxuICogQHBhcmFtIG4gbnVtYmVyIG9mIGVudHJpZXMgWy0xIOKHkiBhbnldXG4gKiBAcmV0dXJucyBlbnRyaWVzIHNlbGVjdGVkIGJ5IGJpdCBmcm9tIDAuLjJefHh8IGlmIG48MDsgb25seSBvZiBsZW5ndGggbiBvdGhlcndpc2VcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uKiBzdWJzZXRzPEssIFY+KHg6IE1hcDxLLCBWPiwgbjogbnVtYmVyPS0xKTogSXRlcmFibGVJdGVyYXRvcjxNYXA8SywgVj4+IHtcbiAgZm9yIChjb25zdCBrcyBvZiBhcnJheVN1YnNlcXVlbmNlcyhbLi4ueC5rZXlzKCldLCBuKSlcbiAgICB5aWVsZCBmaWx0ZXJBdCh4LCBrcyk7XG59XG5cblxuLyoqXG4gKiBQaWNrIGFuIGFyYml0cmFyeSBrZXkuXG4gKiBAcGFyYW0geCBhIG1hcFxuICogQHBhcmFtIGZyIHJhbmRvbSBudW1iZXIgZ2VuZXJhdG9yIChbMCwgMSkpXG4gKiBAcmV0dXJucyBr4bWiIHwgW2vhtaIsIHbhtaJdIOKIiCB4XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByYW5kb21LZXk8SywgVj4oeDogTWFwPEssIFY+LCBmcjogUmVhZEZ1bmN0aW9uPG51bWJlcj49TWF0aC5yYW5kb20pOiBLIHtcbiAgcmV0dXJuIGFycmF5UmFuZG9tVmFsdWUoWy4uLngua2V5cygpXSwgZnIpO1xufVxuZXhwb3J0IHtyYW5kb21LZXkgYXMga2V5fTtcblxuXG4vKipcbiAqIFBpY2sgYW4gYXJiaXRyYXJ5IGVudHJ5LlxuICogQHBhcmFtIHggYSBtYXBcbiAqIEBwYXJhbSBmciByYW5kb20gbnVtYmVyIGdlbmVyYXRvciAoWzAsIDEpKVxuICogQHJldHVybnMgW2vhtaIsIHbhtaJdIHwgW2vhtaIsIHbhtaJdIOKIiCB4XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByYW5kb21FbnRyeTxLLCBWPih4OiBFbnRyaWVzPEssIFY+LCBmcjogUmVhZEZ1bmN0aW9uPG51bWJlcj49TWF0aC5yYW5kb20pOiBbSywgVl0ge1xuICByZXR1cm4gYXJyYXlSYW5kb21WYWx1ZShbLi4ueF0sIGZyKTtcbn1cbmV4cG9ydCB7cmFuZG9tRW50cnkgYXMgZW50cnl9O1xuXG5cbi8qKlxuICogUGljayBhbiBhcmJpdHJhcnkgc3Vic2V0LlxuICogQHBhcmFtIHggYSBtYXBcbiAqIEBwYXJhbSBuIG51bWJlciBvZiBlbnRyaWVzIFstMSDih5IgYW55XVxuICogQHBhcmFtIGZyIHJhbmRvbSBudW1iZXIgZ2VuZXJhdG9yIChbMCwgMSkpXG4gKiBAcmV0dXJucyBcXHtba+G1oiwgduG1ol0sIFtr4rG8LCB24rG8XSwgLi4uXFx9IHwgW2vhtaIsIHbhtaJdLCBba+KxvCwgduKxvF0sIC4uLiDiiIggeDsgfFxce1tr4bWiLCB24bWiXSwgW2visbwsIHbisbxdLCAuLi5cXH18ID0gfHh8IGlmIG48MCBlbHNlIG5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJhbmRvbVN1YnNldDxLLCBWPih4OiBNYXA8SywgVj4sIG46IG51bWJlcj0tMSwgZnI6IFJlYWRGdW5jdGlvbjxudW1iZXI+IHwgbnVsbD1NYXRoLnJhbmRvbSk6IE1hcDxLLCBWPiB7XG4gIGNvbnN0IGtzID0gYXJyYXlSYW5kb21TdWJzZXF1ZW5jZShbLi4ueC5rZXlzKCldLCBuLCBmcik7XG4gIHJldHVybiBmaWx0ZXJBdCh4LCBrcyBhcyBLW10pO1xufVxuZXhwb3J0IHtyYW5kb21TdWJzZXQgYXMgc3Vic2V0fTtcblxuXG5cblxuLy8gRklORFxuLy8gLS0tLVxuXG4vKipcbiAqIENoZWNrIGlmIG1hcCBoYXMgYSBrZXkuXG4gKiBAcGFyYW0geCBhIG1hcFxuICogQHBhcmFtIGsgc2VhcmNoIGtleVxuICogQHJldHVybnMgW2ssICpdIOKIiCB4P1xuICovXG5leHBvcnQgZnVuY3Rpb24gaGFzPEssIFY+KHg6IE1hcDxLLCBWPiwgazogSyk6IGJvb2xlYW4ge1xuICByZXR1cm4geC5oYXMoayk7XG59XG5leHBvcnQge2hhcyBhcyBoYXNLZXl9O1xuXG5cbi8qKlxuICogQ2hlY2sgaWYgbWFwIGhhcyBhIHZhbHVlLlxuICogQHBhcmFtIHggYSBtYXBcbiAqIEBwYXJhbSB2IHNlYXJjaCB2YWx1ZVxuICogQHBhcmFtIGZjIGNvbXBhcmUgZnVuY3Rpb24gKGEsIGIpXG4gKiBAcGFyYW0gZm0gbWFwIGZ1bmN0aW9uICh2LCBrLCB4KVxuICogQHJldHVybnMgWyosIHZdIOKIiCB4P1xuICovXG5leHBvcnQgZnVuY3Rpb24gaGFzVmFsdWU8SywgViwgVz1WPih4OiBNYXA8SywgVj4sIHY6IFYsIGZjOiBDb21wYXJlRnVuY3Rpb248VnxXPiB8IG51bGw9bnVsbCwgZm06IE1hcEZ1bmN0aW9uPEssIFYsIFZ8Vz4gfCBudWxsPW51bGwpOiBib29sZWFuIHtcbiAgcmV0dXJuIHNlYXJjaFZhbHVlKHgsIHYsIGZjLCBmbSkhPT11bmRlZmluZWQ7XG59XG5cblxuLyoqXG4gKiBDaGVjayBpZiBtYXAgaGFzIGFuIGVudHJ5LlxuICogQHBhcmFtIHggYSBtYXBcbiAqIEBwYXJhbSBlIHNlYXJjaCBlbnRyeSAoW2ssIHZdKVxuICogQHBhcmFtIGZjIGNvbXBhcmUgZnVuY3Rpb24gKGEsIGIpXG4gKiBAcGFyYW0gZm0gbWFwIGZ1bmN0aW9uICh2LCBrLCB4KVxuICogQHJldHVybnMgW2ssIHZdIOKIiCB4PyB8IFtrLCB2XSA9IGVcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGhhc0VudHJ5PEssIFYsIFc9Vj4oeDogTWFwPEssIFY+LCBlOiBbSywgVl0sIGZjOiBDb21wYXJlRnVuY3Rpb248VnxXPiB8IG51bGw9bnVsbCwgZm06IE1hcEZ1bmN0aW9uPEssIFYsIFZ8Vz4gfCBudWxsPW51bGwpOiBib29sZWFuIHtcbiAgZmMgPSBmYyB8fCBDT01QQVJFO1xuICBmbSA9IGZtIHx8IElERU5USVRZO1xuICBjb25zdCBbaywgdl0gPSBlO1xuICByZXR1cm4geC5oYXMoaykgJiYgZmMoZm0oeC5nZXQoaykgYXMgViwgaywgeCksIHYpPT09MDtcbn1cblxuXG4vKipcbiAqIENoZWNrIGlmIG1hcCBoYXMgYSBzdWJzZXQuXG4gKiBAcGFyYW0geCBhIG1hcFxuICogQHBhcmFtIHkgc2VhcmNoIHN1YnNldFxuICogQHBhcmFtIGZjIGNvbXBhcmUgZnVuY3Rpb24gKGEsIGIpXG4gKiBAcGFyYW0gZm0gbWFwIGZ1bmN0aW9uICh2LCBrLCB4KVxuICogQHJldHVybnMgeSDiioYgeD9cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGhhc1N1YnNldDxLLCBWLCBXPVY+KHg6IE1hcDxLLCBWPiwgeTogTWFwPEssIFY+LCBmYzogQ29tcGFyZUZ1bmN0aW9uPFZ8Vz4gfCBudWxsPW51bGwsIGZtOiBNYXBGdW5jdGlvbjxLLCBWLCBWfFc+IHwgbnVsbD1udWxsKTogYm9vbGVhbiB7XG4gIGZjID0gZmMgfHwgQ09NUEFSRTtcbiAgZm0gPSBmbSB8fCBJREVOVElUWTtcbiAgZm9yIChjb25zdCBbaywgdl0gb2YgeSkge1xuICAgIGlmICgheC5oYXMoaykpIHJldHVybiBmYWxzZTtcbiAgICBjb25zdCB3eCA9IGZtKHguZ2V0KGspIGFzIFYsIGssIHgpO1xuICAgIGNvbnN0IHd5ID0gZm0odiwgaywgeSk7XG4gICAgaWYgKGZjKHd4LCB3eSkhPT0wKSByZXR1cm4gZmFsc2U7XG4gIH1cbiAgcmV0dXJuIHRydWU7XG59XG5cblxuLyoqXG4gKiBGaW5kIGZpcnN0IHZhbHVlIHBhc3NpbmcgYSB0ZXN0IChkZWZhdWx0IG9yZGVyKS5cbiAqIEBwYXJhbSB4IGEgbWFwXG4gKiBAcGFyYW0gZnQgdGVzdCBmdW5jdGlvbiAodiwgaywgeClcbiAqIEByZXR1cm5zIGZpcnN0IHYgfCBmdCh2KSA9IHRydWU7IFtrLCB2XSDiiIggeFxuICovXG5leHBvcnQgZnVuY3Rpb24gZmluZDxLLCBWPih4OiBNYXA8SywgVj4sIGZ0OiBUZXN0RnVuY3Rpb248SywgVj4pOiBWIHwgdW5kZWZpbmVkIHtcbiAgZm9yIChjb25zdCBbaywgdl0gb2YgeClcbiAgICBpZiAoZnQodiwgaywgeCkpIHJldHVybiB2O1xufVxuXG5cbi8qKlxuICogRmluZCB2YWx1ZXMgcGFzc2luZyBhIHRlc3QuXG4gKiBAcGFyYW0geCBhIG1hcFxuICogQHBhcmFtIGZ0IHRlc3QgZnVuY3Rpb24gKHYsIGssIHgpXG4gKiBAcmV0dXJucyBbduKCgCwgduKCgSwgLi4uXSB8IGZ0KHbhtaIpID0gdHJ1ZTsgW2vhtaIsIHbhtaJdIOKIiCB4XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmaW5kQWxsPEssIFY+KHg6IE1hcDxLLCBWPiwgZnQ6IFRlc3RGdW5jdGlvbjxLLCBWPik6IFZbXSB7XG4gIGNvbnN0IGEgPSBbXTtcbiAgZm9yIChjb25zdCBbaywgdl0gb2YgeClcbiAgICBpZiAoZnQodiwgaywgeCkpIGEucHVzaCh2KTtcbiAgcmV0dXJuIGE7XG59XG5cblxuLyoqXG4gKiBGaW5kIGtleSBvZiBhbiBlbnRyeSBwYXNzaW5nIGEgdGVzdC5cbiAqIEBwYXJhbSB4IGEgbWFwXG4gKiBAcGFyYW0gZnQgdGVzdCBmdW5jdGlvbiAodiwgaywgeClcbiAqIEByZXR1cm5zIGtleSBvZiBlbnRyeVxuICovXG5leHBvcnQgZnVuY3Rpb24gc2VhcmNoPEssIFY+KHg6IE1hcDxLLCBWPiwgZnQ6IFRlc3RGdW5jdGlvbjxLLCBWPik6IEsgfCB1bmRlZmluZWQge1xuICBmb3IgKGNvbnN0IFtrLCB2XSBvZiB4KVxuICAgIGlmIChmdCh2LCBrLCB4KSkgcmV0dXJuIGs7XG59XG5cblxuLyoqXG4gKiBGaW5kIGtleXMgb2YgZW50cmllcyBwYXNzaW5nIGEgdGVzdC5cbiAqIEBwYXJhbSB4IGEgbWFwXG4gKiBAcGFyYW0gZnQgdGVzdCBmdW5jdGlvbiAodiwgaywgeClcbiAqIEByZXR1cm5zIGtleXMgb2YgZW50cmllc1xuICovXG5leHBvcnQgZnVuY3Rpb24gc2VhcmNoQWxsPEssIFY+KHg6IE1hcDxLLCBWPiwgZnQ6IFRlc3RGdW5jdGlvbjxLLCBWPik6IEtbXSB7XG4gIGNvbnN0IGEgPSBbXTtcbiAgZm9yIChjb25zdCBbaywgdl0gb2YgeClcbiAgICBpZiAoZnQodiwgaywgeCkpIGEucHVzaChrKTtcbiAgcmV0dXJuIGE7XG59XG5cblxuLyoqXG4gKiBGaW5kIGEga2V5IHdpdGggZ2l2ZW4gdmFsdWUuXG4gKiBAcGFyYW0geCBhIG1hcFxuICogQHBhcmFtIHYgc2VhcmNoIHZhbHVlXG4gKiBAcGFyYW0gZmMgY29tcGFyZSBmdW5jdGlvbiAoYSwgYilcbiAqIEBwYXJhbSBmbSBtYXAgZnVuY3Rpb24gKHYsIGssIHgpXG4gKiBAcmV0dXJucyBrZXkgb2YgdmFsdWVcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNlYXJjaFZhbHVlPEssIFYsIFc9Vj4oeDogTWFwPEssIFY+LCB2OiBWLCBmYzogQ29tcGFyZUZ1bmN0aW9uPFZ8Vz4gfCBudWxsPW51bGwsIGZtOiBNYXBGdW5jdGlvbjxLLCBWLCBWfFc+IHwgbnVsbD1udWxsKTogSyB8IHVuZGVmaW5lZCB7XG4gIGZjID0gZmMgfHwgQ09NUEFSRTtcbiAgZm0gPSBmbSB8fCBJREVOVElUWTtcbiAgY29uc3QgdyA9IGZtKHYsIG51bGwgYXMgSywgbnVsbCk7XG4gIGZvciAoY29uc3QgW2ssIHVdIG9mIHgpIHtcbiAgICBjb25zdCB3eCA9IGZtKHUsIGssIHgpO1xuICAgIGlmIChmYyh3eCwgdyk9PT0wKSByZXR1cm4gaztcbiAgfVxufVxuXG5cbi8qKlxuICogRmluZCBrZXlzIHdpdGggZ2l2ZW4gdmFsdWUuXG4gKiBAcGFyYW0geCBhIG1hcFxuICogQHBhcmFtIHYgc2VhcmNoIHZhbHVlXG4gKiBAcGFyYW0gZmMgY29tcGFyZSBmdW5jdGlvbiAoYSwgYilcbiAqIEBwYXJhbSBmbSBtYXAgZnVuY3Rpb24gKHYsIGssIHgpXG4gKiBAcmV0dXJucyBrZXlzIG9mIHZhbHVlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzZWFyY2hWYWx1ZUFsbDxLLCBWLCBXPVY+KHg6IE1hcDxLLCBWPiwgdjogViwgZmM6IENvbXBhcmVGdW5jdGlvbjxWfFc+IHwgbnVsbD1udWxsLCBmbTogTWFwRnVuY3Rpb248SywgViwgVnxXPiB8IG51bGw9bnVsbCk6IEtbXSB7XG4gIGZjID0gZmMgfHwgQ09NUEFSRTtcbiAgZm0gPSBmbSB8fCBJREVOVElUWTtcbiAgY29uc3QgdyAgPSBmbSh2LCBudWxsIGFzIEssIG51bGwpLCBhID0gW107XG4gIGZvcihjb25zdCBbaywgdV0gb2YgeCkge1xuICAgIGNvbnN0IHd4ID0gZm0odSwgaywgeCk7XG4gICAgaWYgKGZjKHd4LCB3KT09PTApIGEucHVzaChrKTtcbiAgfVxuICByZXR1cm4gYTtcbn1cblxuXG5cblxuLy8gRlVOQ1RJT05BTFxuLy8gLS0tLS0tLS0tLVxuXG4vKipcbiAqIENhbGwgYSBmdW5jdGlvbiBmb3IgZWFjaCB2YWx1ZS5cbiAqIEBwYXJhbSB4IGEgbWFwXG4gKiBAcGFyYW0gZnAgcHJvY2VzcyBmdW5jdGlvbiAodiwgaywgeClcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGZvckVhY2g8SywgVj4oeDogTWFwPEssIFY+LCBmcDogUHJvY2Vzc0Z1bmN0aW9uPEssIFY+KTogdm9pZCB7XG4gIGZvciAoY29uc3QgW2ssIHZdIG9mIHgpXG4gICAgZnAodiwgaywgeCk7XG59XG5cblxuLyoqXG4gKiBDaGVjayBpZiBhbnkgdmFsdWUgc2F0aXNmaWVzIGEgdGVzdC5cbiAqIEBwYXJhbSB4IGEgbWFwXG4gKiBAcGFyYW0gZnQgdGVzdCBmdW5jdGlvbiAodiwgaywgeClcbiAqIEByZXR1cm5zIHRydWUgaWYgZnQoduG1oikgPSB0cnVlIGZvciBzb21lIFtr4bWiLCB24bWiXSDiiIggeFxuICovXG5leHBvcnQgZnVuY3Rpb24gc29tZTxLLCBWPih4OiBNYXA8SywgVj4sIGZ0OiBUZXN0RnVuY3Rpb248SywgVj4pOiBib29sZWFuIHtcbiAgZm9yIChjb25zdCBbaywgdl0gb2YgeClcbiAgICBpZiAoZnQodiwgaywgeCkpIHJldHVybiB0cnVlO1xuICByZXR1cm4gZmFsc2U7XG59XG5cblxuLyoqXG4gKiBDaGVjayBpZiBhbGwgdmFsdWVzIHNhdGlzZnkgYSB0ZXN0LlxuICogQHBhcmFtIHggYSBtYXBcbiAqIEBwYXJhbSBmdCB0ZXN0IGZ1bmN0aW9uICh2LCBrLCB4KVxuICogQHJldHVybnMgdHJ1ZSBpZiBmdCh24bWiKSA9IHRydWUgZm9yIGFsbCBba+G1oiwgduG1ol0g4oiIIHhcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGV2ZXJ5PEssIFY+KHg6IE1hcDxLLCBWPiwgZnQ6IFRlc3RGdW5jdGlvbjxLLCBWPik6IGJvb2xlYW4ge1xuICBmb3IgKGNvbnN0IFtrLCB2XSBvZiB4KVxuICAgIGlmICghZnQodiwgaywgeCkpIHJldHVybiBmYWxzZTtcbiAgcmV0dXJuIHRydWU7XG59XG5cblxuLyoqXG4gKiBUcmFuc2Zvcm0gdmFsdWVzIG9mIGEgbWFwLlxuICogQHBhcmFtIHggYSBtYXBcbiAqIEBwYXJhbSBmbSBtYXAgZnVuY3Rpb24gKHYsIGssIHgpXG4gKiBAcmV0dXJucyBcXHtba+KCgCwgZm0oduKCgCldLCBba+KCgSwgZm0oduKCgSldLCAuLi5cXH0gfCBba+G1oiwgduG1ol0g4oiIIHhcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1hcDxLLCBWLCBXPVY+KHg6IE1hcDxLLCBWPiwgZm06IE1hcEZ1bmN0aW9uPEssIFYsIFZ8Vz4pOiBNYXA8SywgVnxXPiB7XG4gIGNvbnN0IGEgPSBuZXcgTWFwKCk7XG4gIGZvciAoY29uc3QgW2ssIHZdIG9mIHgpXG4gICAgYS5zZXQoaywgZm0odiwgaywgeCkpO1xuICByZXR1cm4gYTtcbn1cblxuXG4vKipcbiAqIFRyYW5zZm9ybSB2YWx1ZXMgb2YgYSBtYXAuXG4gKiBAcGFyYW0geCBhIG1hcCAodXBkYXRlZClcbiAqIEBwYXJhbSBmbSBtYXAgZnVuY3Rpb24gKHYsIGssIHgpXG4gKiBAcmV0dXJucyB4ID0gXFx7W2vigoAsIGZtKHbigoApXSwgW2vigoEsIGZtKHbigoEpXSwgLi4uXFx9IHwgW2vhtaIsIHbhtaJdIOKIiCB4XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBtYXAkPEssIFY+KHg6IE1hcDxLLCBWPiwgZm06IE1hcEZ1bmN0aW9uPEssIFYsIFY+KTogTWFwPEssIFY+IHtcbiAgZm9yIChjb25zdCBbaywgdl0gb2YgeClcbiAgICB4LnNldChrLCBmbSh2LCBrLCB4KSk7XG4gIHJldHVybiB4O1xufVxuXG5cbi8qKlxuICogUmVkdWNlIHZhbHVlcyBvZiBzZXQgdG8gYSBzaW5nbGUgdmFsdWUuXG4gKiBAcGFyYW0geCBhIG1hcFxuICogQHBhcmFtIGZyIHJlZHVjZSBmdW5jdGlvbiAoYWNjLCB2LCBrLCB4KVxuICogQHBhcmFtIGFjYyBpbml0aWFsIHZhbHVlXG4gKiBAcmV0dXJucyBmcihmcihhY2MsIHbigoApLCB24oKBKS4uLiB8IGZyKGFjYywgduKCgCkgPSB24oKAIGlmIGFjYyBub3QgZ2l2ZW5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlZHVjZTxLLCBWLCBXPVY+KHg6IE1hcDxLLCBWPiwgZnI6IFJlZHVjZUZ1bmN0aW9uPEssIFYsIFZ8Vz4sIGFjYz86IFZ8Vyk6IFZ8VyB7XG4gIGxldCBpbml0ID0gYXJndW1lbnRzLmxlbmd0aCA8PSAyO1xuICBmb3IgKGNvbnN0IFtrLCB2XSBvZiB4KSB7XG4gICAgaWYgKGluaXQpIHsgYWNjID0gdjsgaW5pdCA9IGZhbHNlOyB9XG4gICAgZWxzZSBhY2MgPSBmcihhY2MgYXMgVnxXLCB2LCBrLCB4KTtcbiAgfVxuICByZXR1cm4gYWNjIGFzIFZ8Vztcbn1cblxuXG4vKipcbiAqIEtlZXAgZW50cmllcyB3aGljaCBwYXNzIGEgdGVzdC5cbiAqIEBwYXJhbSB4IGEgbWFwXG4gKiBAcGFyYW0gZnQgdGVzdCBmdW5jdGlvbiAodiwgaywgeClcbiAqIEByZXR1cm5zIFxce1tr4oKALCB24oKAXSwgW2vigoEsIHbigoFdLCAuLi5cXH0gfCBmdCh24bWiKSA9IHRydWU7IFtr4bWiLCB24bWiXSDiiIggeFxuICovXG5leHBvcnQgZnVuY3Rpb24gZmlsdGVyPEssIFY+KHg6IE1hcDxLLCBWPiwgZnQ6IFRlc3RGdW5jdGlvbjxLLCBWPik6IE1hcDxLLCBWPiB7XG4gIGNvbnN0IGEgPSBuZXcgTWFwKCk7XG4gIGZvciAoY29uc3QgW2ssIHZdIG9mIHgpXG4gICAgaWYgKGZ0KHYsIGssIHgpKSBhLnNldChrLCB2KTtcbiAgcmV0dXJuIGE7XG59XG5cblxuLyoqXG4gKiBLZWVwIGVudHJpZXMgd2hpY2ggcGFzcyBhIHRlc3QuXG4gKiBAcGFyYW0geCBhbiBtYXAgKHVwZGF0ZWQpXG4gKiBAcGFyYW0gZnQgdGVzdCBmdW5jdGlvbiAodiwgaywgeClcbiAqIEByZXR1cm5zIHggPSBcXHtba+KCgCwgduKCgF0sIFtr4oKBLCB24oKBXSwgLi4uXFx9IHwgZnQoduG1oikgPSB0cnVlOyBba+G1oiwgduG1ol0g4oiIIHhcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGZpbHRlciQ8SywgVj4oeDogTWFwPEssIFY+LCBmdDogVGVzdEZ1bmN0aW9uPEssIFY+KTogTWFwPEssIFY+IHtcbiAgZm9yIChjb25zdCBbaywgdl0gb2YgeClcbiAgICBpZiAoIWZ0KHYsIGssIHgpKSB4LmRlbGV0ZShrKTtcbiAgcmV0dXJuIHg7XG59XG5cblxuLyoqXG4gKiBLZWVwIHZhbHVlcyBhdCBnaXZlbiBrZXlzLlxuICogQHBhcmFtIHggYSBtYXBcbiAqIEBwYXJhbSBrcyBrZXlzXG4gKiBAcmV0dXJucyBcXHtba+KCgCwgduKCgF0sIFtr4oKBLCB24oKBXSwgLi4uXFx9IHwga+G1oiDiiIgga3M7IFtr4bWiLCB24bWiXSDiiIggeFxuICovXG5leHBvcnQgZnVuY3Rpb24gZmlsdGVyQXQ8SywgVj4oeDogTWFwPEssIFY+LCBrczogS1tdKTogTWFwPEssIFY+IHtcbiAgY29uc3QgYSA9IG5ldyBNYXAoKTtcbiAgZm9yIChjb25zdCBrIG9mIGtzKVxuICAgIGEuc2V0KGssIHguZ2V0KGspKTtcbiAgcmV0dXJuIGE7XG59XG5cblxuLyoqXG4gKiBLZWVwIHZhbHVlcyBhdCBnaXZlbiBrZXlzLlxuICogQHBhcmFtIHggYSBtYXAgKHVwZGF0ZWQpXG4gKiBAcGFyYW0ga3Mga2V5c1xuICogQHJldHVybnMgeCA9IFxce1tr4oKALCB24oKAXSwgW2vigoEsIHbigoFdLCAuLi5cXH0gfCBr4bWiIOKIiCBrczsgW2vhtaIsIHbhtaJdIOKIiCB4XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmaWx0ZXJBdCQ8SywgVj4oeDogTWFwPEssIFY+LCBrczogS1tdKTogTWFwPEssIFY+IHtcbiAgZm9yIChjb25zdCBrIG9mIHgua2V5cygpKVxuICAgIGlmICgha3MuaW5jbHVkZXMoaykpIHguZGVsZXRlKGspO1xuICByZXR1cm4geDtcbn1cblxuXG4vKipcbiAqIERpc2NhcmQgZW50cmllcyB3aGljaCBwYXNzIGEgdGVzdC5cbiAqIEBwYXJhbSB4IGEgbWFwXG4gKiBAcGFyYW0gZnQgdGVzdCBmdW5jdGlvbiAodiwgaywgeClcbiAqIEByZXR1cm5zIFxce1tr4oKALCB24oKAXSwgW2vigoEsIHbigoFdLCAuLi5cXH0gfCBmdCh24bWiKSA9IGZhbHNlOyBba+G1oiwgduG1ol0g4oiIIHhcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlamVjdDxLLCBWPih4OiBNYXA8SywgVj4sIGZ0OiBUZXN0RnVuY3Rpb248SywgVj4pOiBNYXA8SywgVj4ge1xuICBjb25zdCBhID0gbmV3IE1hcCgpO1xuICBmb3IgKGNvbnN0IFtrLCB2XSBvZiB4KVxuICAgIGlmICghZnQodiwgaywgeCkpIGEuc2V0KGssIHYpO1xuICByZXR1cm4gYTtcbn1cblxuXG4vKipcbiAqIERpc2NhcmQgZW50cmllcyB3aGljaCBwYXNzIGEgdGVzdC5cbiAqIEBwYXJhbSB4IGEgbWFwICh1cGRhdGVkKVxuICogQHBhcmFtIGZ0IHRlc3QgZnVuY3Rpb24gKHYsIGssIHgpXG4gKiBAcmV0dXJucyB4ID0gXFx7W2vigoAsIHbigoBdLCBba+KCgSwgduKCgV0sIC4uLlxcfSB8IGZ0KHbhtaIpID0gZmFsc2U7IFtr4bWiLCB24bWiXSDiiIggeFxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVqZWN0JDxLLCBWPih4OiBNYXA8SywgVj4sIGZ0OiBUZXN0RnVuY3Rpb248SywgVj4pOiBNYXA8SywgVj4ge1xuICBmb3IgKGNvbnN0IFtrLCB2XSBvZiB4KVxuICAgIGlmIChmdCh2LCBrLCB4KSkgeC5kZWxldGUoayk7XG4gIHJldHVybiB4O1xufVxuXG5cbi8qKlxuICogRGlzY2FyZCB2YWx1ZXMgYXQgZ2l2ZW4ga2V5cy5cbiAqIEBwYXJhbSB4IGEgbWFwXG4gKiBAcGFyYW0ga3Mga2V5c1xuICogQHJldHVybnMgXFx7W2vigoAsIHbigoBdLCBba+KCgSwgduKCgV0sIC4uLlxcfSB8IGvhtaIg4oiJIGtzOyBba+G1oiwgduG1ol0g4oiIIHhcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlamVjdEF0PEssIFY+KHg6IE1hcDxLLCBWPiwga3M6IEtbXSk6IE1hcDxLLCBWPiB7XG4gIHJldHVybiByZWplY3RBdCQobmV3IE1hcCh4KSwga3MpO1xufVxuXG5cbi8qKlxuICogRGlzY2FyZCB2YWx1ZXMgYXQgZ2l2ZW4ga2V5cy5cbiAqIEBwYXJhbSB4IGEgbWFwICh1cGRhdGVkKVxuICogQHBhcmFtIGtzIGtleXNcbiAqIEByZXR1cm5zIHggPSBcXHtba+KCgCwgduKCgF0sIFtr4oKBLCB24oKBXSwgLi4uXFx9IHwga+G1oiDiiIkga3M7IFtr4bWiLCB24bWiXSDiiIggeFxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVqZWN0QXQkPEssIFY+KHg6IE1hcDxLLCBWPiwga3M6IEtbXSk6IE1hcDxLLCBWPiB7XG4gIGZvciAoY29uc3QgayBvZiBrcylcbiAgICB4LmRlbGV0ZShrKTtcbiAgcmV0dXJuIHg7XG59XG5cblxuLyoqXG4gKiBGbGF0dGVuIG5lc3RlZCBtYXAgdG8gZ2l2ZW4gZGVwdGguXG4gKiBAcGFyYW0geCBhIG5lc3RlZCBtYXBcbiAqIEBwYXJhbSBuIG1heGltdW0gZGVwdGggWy0xIOKHkiBhbGxdXG4gKiBAcGFyYW0gZm0gbWFwIGZ1bmN0aW9uICh2LCBrLCB4KVxuICogQHBhcmFtIGZ0IHRlc3QgZnVuY3Rpb24gZm9yIGZsYXR0ZW4gKHYsIGssIHgpIFtpc11cbiAqIEByZXR1cm5zIGZsYXQgbWFwXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmbGF0PEs+KHg6IE1hcDxLLCB1bmtub3duPiwgbjogbnVtYmVyPS0xLCBmbTogTWFwRnVuY3Rpb248SywgdW5rbm93biwgdW5rbm93bj4gfCBudWxsPW51bGwsIGZ0OiBUZXN0RnVuY3Rpb248SywgdW5rbm93bj4gfCBudWxsPW51bGwpOiBNYXA8SywgdW5rbm93bj4ge1xuICBmbSA9IGZtIHx8IElERU5USVRZO1xuICBmdCA9IGZ0IHx8IGlzO1xuICByZXR1cm4gZmxhdFRvJChuZXcgTWFwKCksIHgsIG4sIGZtLCBmdCk7XG59XG5cbmZ1bmN0aW9uIGZsYXRUbyQ8Sz4oYTogTWFwPEssIHVua25vd24+LCB4OiBNYXA8SywgdW5rbm93bj4sIG46IG51bWJlciwgZm06IE1hcEZ1bmN0aW9uPEssIHVua25vd24sIHVua25vd24+LCBmdDogVGVzdEZ1bmN0aW9uPEssIHVua25vd24+KTogTWFwPEssIHVua25vd24+IHtcbiAgZm9yIChjb25zdCBbaywgdl0gb2YgeCkge1xuICAgIGNvbnN0IHcgPSBmbSh2LCBrLCB4KTtcbiAgICBpZiAobiE9PTAgJiYgZnQodywgaywgeCkpIGZsYXRUbyQoYSwgdyBhcyBNYXA8SywgdW5rbm93bj4sIG4tMSwgZm0sIGZ0KTtcbiAgICBlbHNlIGEuc2V0KGssIHcpO1xuICB9XG4gIHJldHVybiBhO1xufVxuXG5cbi8qKlxuICogRmxhdHRlbiBuZXN0ZWQgbWFwLCBiYXNlZCBvbiBtYXAgZnVuY3Rpb24uXG4gKiBAcGFyYW0geCBhIG5lc3RlZCBtYXBcbiAqIEBwYXJhbSBmbSBtYXAgZnVuY3Rpb24gKHYsIGssIHgpXG4gKiBAcGFyYW0gZnQgdGVzdCBmdW5jdGlvbiBmb3IgZmxhdHRlbiAodiwgaywgeCkgW2lzXVxuICogQHJldHVybnMgZmxhdCBtYXBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGZsYXRNYXA8Sz4oeDogTWFwPEssIHVua25vd24+LCBmbTogTWFwRnVuY3Rpb248SywgdW5rbm93biwgdW5rbm93bj4gfCBudWxsPW51bGwsIGZ0OiBUZXN0RnVuY3Rpb248SywgdW5rbm93bj4gfCBudWxsPW51bGwpOiBNYXA8SywgdW5rbm93bj4ge1xuICBmbSA9IGZtIHx8IElERU5USVRZO1xuICBmdCA9IGZ0IHx8IGlzO1xuICBjb25zdCBhICA9IG5ldyBNYXAoKTtcbiAgZm9yIChjb25zdCBbaywgdl0gb2YgeCkge1xuICAgIGNvbnN0IHcgPSBmbSh2LCBrLCB4KTtcbiAgICBpZiAoZnQodywgaywgeCkpIGNvbmNhdCQoYSwgdyBhcyBNYXA8SywgdW5rbm93bj4pO1xuICAgIGVsc2UgYS5zZXQoaywgdyk7XG4gIH1cbiAgcmV0dXJuIGE7XG59XG5cblxuLyoqXG4gKiBDb21iaW5lIG1hdGNoaW5nIGVudHJpZXMgZnJvbSBtYXBzLlxuICogQHBhcmFtIHhzIG1hcHNcbiAqIEBwYXJhbSBmbSBtYXAgZnVuY3Rpb24gKHZzLCBrKVxuICogQHBhcmFtIGZlIGVuZCBmdW5jdGlvbiAoZG9uZXMpIFthcnJheS5zb21lXVxuICogQHBhcmFtIHZkIGRlZmF1bHQgdmFsdWVcbiAqIEByZXR1cm5zIFtmbShbeOKCgFtr4oKAXSwgeOKCgVtr4oKAXSwgLi4uXSksIGZtKFt44oKAW2vigoFdLCB44oKBW2vigoFdLCAuLi5dKSwgLi4uXVxuICovXG5leHBvcnQgZnVuY3Rpb24gemlwPEssIFYsIFc9Vj4oeHM6IE1hcDxLLCBWPltdLCBmbTogTWFwRnVuY3Rpb248SywgVltdLCBWW118Vz4gfCBudWxsPW51bGwsIGZlOiBFbmRGdW5jdGlvbiB8IG51bGw9bnVsbCwgdmQ/OiBWKTogTWFwPEssIFZbXXxXPiB7XG4gIGZtID0gZm0gfHwgSURFTlRJVFk7XG4gIGZlID0gZmUgfHwgYXJyYXlTb21lIGFzIEVuZEZ1bmN0aW9uO1xuICBjb25zdCBrcyA9IHVuaW9uS2V5cyguLi54cyksIGEgPSBuZXcgTWFwKCk7XG4gIGZvciAoY29uc3QgayBvZiBrcykge1xuICAgIGNvbnN0IGRzID0geHMubWFwKHggPT4gIXguaGFzKGspKTtcbiAgICBpZiAoZmUoZHMpKSBicmVhaztcbiAgICBjb25zdCB2cyA9IHhzLm1hcCh4ID0+ICF4LmhhcyhrKT8gdmQgOiB4LmdldChrKSk7XG4gICAgYS5zZXQoaywgZm0odnMgYXMgVltdLCBrLCBudWxsKSk7XG4gIH1cbiAgcmV0dXJuIGE7XG59XG5cblxuXG5cbi8vIE1BTklQVUxBVElPTlxuLy8gLS0tLS0tLS0tLS0tXG5cbi8qKlxuICogU2VncmVnYXRlIGVudHJpZXMgYnkgdGVzdCByZXN1bHQuXG4gKiBAcGFyYW0geCBhIG1hcFxuICogQHBhcmFtIGZ0IHRlc3QgZnVuY3Rpb24gKHYsIGssIHgpXG4gKiBAcmV0dXJucyBbc2F0aXNmaWVzLCBkb2VzbnRdXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwYXJ0aXRpb248SywgVj4oeDogTWFwPEssIFY+LCBmdDogVGVzdEZ1bmN0aW9uPEssIFY+KTogW01hcDxLLCBWPiwgTWFwPEssIFY+XSB7XG4gIGNvbnN0IHQgPSBuZXcgTWFwKCk7XG4gIGNvbnN0IGYgPSBuZXcgTWFwKCk7XG4gIGZvciAoY29uc3QgW2ssIHZdIG9mIHgpIHtcbiAgICBpZiAoZnQodiwgaywgeCkpIHQuc2V0KGssIHYpO1xuICAgIGVsc2UgZi5zZXQoaywgdik7XG4gIH1cbiAgcmV0dXJuIFt0LCBmXTtcbn1cblxuXG4vKipcbiAqIFNlZ3JlZ2F0ZSBlbnRyaWVzIGJ5IHNpbWlsYXJpdHkuXG4gKiBAcGFyYW0geCBhIG1hcFxuICogQHBhcmFtIGZtIG1hcCBmdW5jdGlvbiAodiwgaywgeClcbiAqIEByZXR1cm5zIE1hcCBcXHtrZXkg4oeSIHZhbHVlc1xcfVxuICovXG5leHBvcnQgZnVuY3Rpb24gcGFydGl0aW9uQXM8SywgViwgVz1WPih4OiBNYXA8SywgVj4sIGZtOiBNYXBGdW5jdGlvbjxLLCBWLCBWfFc+KTogTWFwPFZ8VywgTWFwPEssIFY+PiB7XG4gIGZtID0gZm0gfHwgSURFTlRJVFk7XG4gIGNvbnN0IGEgID0gbmV3IE1hcCgpO1xuICBmb3IgKGNvbnN0IFtrLCB2XSBvZiB4KSB7XG4gICAgY29uc3QgdyA9IGZtKHYsIGssIHgpO1xuICAgIGlmICghYS5oYXModykpIGEuc2V0KHcsIG5ldyBNYXAoKSk7XG4gICAgYS5nZXQodykuc2V0KGssIHYpO1xuICB9XG4gIHJldHVybiBhO1xufVxuXG5cbi8qKlxuICogQnJlYWsgbWFwIGludG8gY2h1bmtzIG9mIGdpdmVuIHNpemUuXG4gKiBAcGFyYW0geCBhIG1hcFxuICogQHBhcmFtIG4gY2h1bmsgc2l6ZSBbMV1cbiAqIEBwYXJhbSBzIGNodW5rIHN0ZXAgW25dXG4gKiBAcmV0dXJucyBbeFswLi5uXSwgeFtzLi5zK25dLCB4WzJzLi4ycytuXSwgLi4uXVxuICovXG5leHBvcnQgZnVuY3Rpb24gY2h1bms8SywgVj4oeDogTWFwPEssIFY+LCBuOiBudW1iZXI9MSwgczogbnVtYmVyPW4pOiBNYXA8SywgVj5bXSB7XG4gIGNvbnN0IGtzID0gWy4uLngua2V5cygpXSwgYSA9IFtdO1xuICBjb25zdCBJICA9IGtzLmxlbmd0aDtcbiAgZm9yIChsZXQgaT0wOyBpPEk7IGkrPXMpXG4gICAgYS5wdXNoKGZpbHRlckF0KHgsIGtzLnNsaWNlKGksIGkrbikpKTtcbiAgcmV0dXJuIGE7XG59XG5cblxuXG5cbi8vIENPTUJJTkVcbi8vIC0tLS0tLS1cblxuLyoqXG4gKiBBcHBlbmQgZW50cmllcyBmcm9tIG1hcHMsIHByZWZlcnJpbmcgbGFzdC5cbiAqIEBwYXJhbSB4cyBtYXBzXG4gKiBAcmV0dXJucyB44oKAIOKIqiB44oKBIOKIqiAuLi4gfCBbeOKCgCwgeOKCgSwgLi4uXSA9IHhzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjb25jYXQ8SywgVj4oLi4ueHM6IEVudHJpZXM8SywgVj5bXSk6IE1hcDxLLCBWPiB7XG4gIHJldHVybiBjb25jYXQkKG5ldyBNYXAoKSwgLi4ueHMpO1xufVxuXG5cbi8qKlxuICogQXBwZW5kIGVudHJpZXMgZnJvbSBtYXBzLCBwcmVmZXJyaW5nIGxhc3QuXG4gKiBAcGFyYW0geCBhIG1hcCAodXBkYXRlZClcbiAqIEBwYXJhbSB5cyBvdGhlciBtYXBzXG4gKiBAcmV0dXJucyB4ID0geCDiiKogeeKCgCDiiKogeeKCgSDiiKogLi4uIHwgW3nigoAsIHnigoEsIC4uLl0gPSB5c1xuICovXG5leHBvcnQgZnVuY3Rpb24gY29uY2F0JDxLLCBWPih4OiBNYXA8SywgVj4sIC4uLnlzOiBFbnRyaWVzPEssIFY+W10pOiBNYXA8SywgVj4ge1xuICBmb3IgKGNvbnN0IHkgb2YgeXMpIHtcbiAgICBmb3IgKGNvbnN0IFtrLCB2XSBvZiB5KVxuICAgICAgeC5zZXQoaywgdik7XG4gIH1cbiAgcmV0dXJuIHg7XG59XG5cblxuLyoqXG4gKiBKb2luIGVudHJpZXMgdG9nZXRoZXIgaW50byBhIHN0cmluZy5cbiAqIEBwYXJhbSB4IGEgbWFwXG4gKiBAcGFyYW0gc2VwIHNlcGFyYXRvciBbLF1cbiAqIEBwYXJhbSBhc2MgYXNzb2NpYXRvciBbPV1cbiAqIEByZXR1cm5zIFwiJFxce2vigoBcXH09JFxce3bigoBcXH0sJFxce2vigoFcXH09JFxce3bigoFcXH0uLi5cIiB8IFtr4bWiLCB24bWiXSDiiIggeFxuICovXG5leHBvcnQgZnVuY3Rpb24gam9pbjxLLCBWPih4OiBFbnRyaWVzPEssIFY+LCBzZXA6IHN0cmluZz1cIixcIiwgYXNjOiBzdHJpbmc9XCI9XCIpOiBzdHJpbmcge1xuICBsZXQgYSA9IFwiXCI7XG4gIGZvciAoY29uc3QgW2ssIHZdIG9mIHgpXG4gICAgYSArPSBrICsgYXNjICsgdiArIHNlcDtcbiAgcmV0dXJuIGEuc2xpY2UoMCwgLXNlcC5sZW5ndGgpO1xufVxuXG5cblxuXG4vLyBTRVQgT1BFUkFUSU9OU1xuLy8gLS0tLS0tLS0tLS0tLS1cblxuLyoqXG4gKiBDaGVjayBpZiBtYXBzIGhhdmUgbm8gY29tbW9uIGtleXMuXG4gKiBAcGFyYW0geCBhIG1hcFxuICogQHBhcmFtIHkgYW5vdGhlciBtYXBcbiAqIEByZXR1cm5zIHgg4oipIHkgPSDOpj9cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzRGlzam9pbnQ8SywgVj4oeDogTWFwPEssIFY+LCB5OiBFbnRyaWVzPEssIFY+KTogYm9vbGVhbiB7XG4gIGZvciAoY29uc3QgW2tdIG9mIHkpXG4gICAgaWYgKHguaGFzKGspKSByZXR1cm4gZmFsc2U7XG4gIHJldHVybiB0cnVlO1xufVxuXG5cbi8qKlxuICogT2J0YWluIGtleXMgcHJlc2VudCBpbiBhbnkgbWFwLlxuICogQHBhcmFtIHhzIG1hcHNcbiAqIEByZXR1cm5zIFtr4oKALCBr4oKBLCAuLi5dIHwgW2vhtaIsIHbhtaJdIOKIiCB44oKAIOKIqiB44oKBLCAuLi47IFt44oKALCB44oKBLCAuLi5dID0geHNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHVuaW9uS2V5czxLLCBWPiguLi54czogRW50cmllczxLLCBWPltdKTogU2V0PEs+IHtcbiAgY29uc3QgYSA9IG5ldyBTZXQ8Sz4oKTtcbiAgZm9yIChjb25zdCB4IG9mIHhzKSB7XG4gICAgZm9yIChjb25zdCBba10gb2YgeClcbiAgICAgIGEuYWRkKGspO1xuICB9XG4gIHJldHVybiBhO1xufVxuXG5cbi8qKlxuICogT2J0YWluIGVudHJpZXMgcHJlc2VudCBpbiBhbnkgbWFwLlxuICogQHBhcmFtIHggYSBtYXBcbiAqIEBwYXJhbSB5IGFub3RoZXIgbWFwXG4gKiBAcGFyYW0gZmMgY29tYmluZSBmdW5jdGlvbiAoYSwgYilcbiAqIEByZXR1cm5zIHgg4oiqIHkgPSBcXHtba+G1oiwgduG1ol0gfCBba+G1oiwgduG1ol0g4oiIIHggb3IgW2vhtaIsIHbhtaJdIOKIiCB5XFx9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB1bmlvbjxLLCBWPih4OiBFbnRyaWVzPEssIFY+LCB5OiBFbnRyaWVzPEssIFY+LCBmYzogQ29tYmluZUZ1bmN0aW9uPFY+IHwgbnVsbD1udWxsKTogTWFwPEssIFY+IHtcbiAgcmV0dXJuIHVuaW9uJChuZXcgTWFwKHgpLCB5LCBmYyk7XG59XG5cblxuXG4vKipcbiAqIE9idGFpbiBlbnRyaWVzIHByZXNlbnQgaW4gYW55IG1hcC5cbiAqIEBwYXJhbSB4IGEgbWFwICh1cGRhdGVkKVxuICogQHBhcmFtIHkgYW5vdGhlciBtYXBcbiAqIEBwYXJhbSBmYyBjb21iaW5lIGZ1bmN0aW9uIChhLCBiKVxuICogQHJldHVybnMgeCA9IHgg4oiqIHkgPSBcXHtba+G1oiwgduG1ol0gfCBba+G1oiwgduG1ol0g4oiIIHggb3IgW2vhtaIsIHbhtaJdIOKIiCB5XFx9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB1bmlvbiQ8SywgVj4oeDogTWFwPEssIFY+LCB5OiBFbnRyaWVzPEssIFY+LCBmYzogQ29tYmluZUZ1bmN0aW9uPFY+IHwgbnVsbD1udWxsKTogTWFwPEssIFY+IHtcbiAgZmMgPSBmYyB8fCBJREVOVElUWTtcbiAgZm9yIChjb25zdCBbaywgdl0gb2YgeSkge1xuICAgIGlmICgheC5oYXMoaykpIHguc2V0KGssIHYpO1xuICAgIGVsc2UgeC5zZXQoaywgZmMoeC5nZXQoaykgYXMgViwgdikpO1xuICB9XG4gIHJldHVybiB4O1xufVxuXG5cbi8qKlxuICogT2J0YWluIGtleXMgcHJlc2VudCBpbiBhbGwgbWFwcy5cbiAqIEBwYXJhbSB4cyBtYXBzXG4gKiBAcmV0dXJucyBba+KCgCwga+KCgSwgLi4uXSB8IFtr4bWiLCB24bWiXSDiiIggeOKCgCDiiKkgeOKCgSwgLi4uOyBbeOKCgCwgeOKCgSwgLi4uXSA9IHhzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpbnRlcnNlY3Rpb25LZXlzPEssIFY+KC4uLnhzOiBNYXA8SywgVj5bXSk6IFNldDxLPiB7XG4gIGNvbnN0IGEgPSBuZXcgU2V0PEs+KCk7XG4gIGlmICh4cy5sZW5ndGg9PT0wKSByZXR1cm4gYTtcbiAgY29uc3QgeCA9IHhzWzBdLCB5cyA9IHhzLnNsaWNlKDEpO1xuICBMT09QWDogZm9yIChjb25zdCBrIG9mIHgua2V5cygpKSB7XG4gICAgZm9yIChjb25zdCB5IG9mIHlzKVxuICAgICAgaWYgKCF5LmhhcyhrKSkgY29udGludWUgTE9PUFg7XG4gICAgYS5hZGQoayk7XG4gIH1cbiAgcmV0dXJuIGE7XG59XG5cblxuLyoqXG4gKiBPYnRhaW4gZW50cmllcyBwcmVzZW50IGluIGJvdGggbWFwcy5cbiAqIEBwYXJhbSB4IGEgbWFwXG4gKiBAcGFyYW0geSBhbm90aGVyIG1hcFxuICogQHBhcmFtIGZjIGNvbWJpbmUgZnVuY3Rpb24gKGEsIGIpXG4gKiBAcmV0dXJucyB4IOKIqSB5ID0gXFx7W2vhtaIsIHbhtaJdIHwgW2vhtaIsIHbhtaJdIOKIiCB4IGFuZCBba+G1oiwgduG1ol0g4oiIIHlcXH1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGludGVyc2VjdGlvbjxLLCBWPih4OiBNYXA8SywgVj4sIHk6IEVudHJpZXM8SywgVj4sIGZjOiBDb21iaW5lRnVuY3Rpb248Vj4gfCBudWxsPW51bGwpOiBNYXA8SywgVj4ge1xuICBmYyA9IGZjIHx8IElERU5USVRZO1xuICBjb25zdCBhICA9IG5ldyBNYXAoKTtcbiAgZm9yIChjb25zdCBbaywgdl0gb2YgeSlcbiAgICBpZiAoeC5oYXMoaykpIGEuc2V0KGssIGZjKHguZ2V0KGspIGFzIFYsIHYpKTtcbiAgcmV0dXJuIGE7XG59XG5cblxuLyoqXG4gKiBPYnRhaW4gZW50cmllcyBwcmVzZW50IGluIGJvdGggbWFwcy5cbiAqIEBwYXJhbSB4IGEgbWFwICh1cGRhdGVkKVxuICogQHBhcmFtIHkgYW5vdGhlciBtYXBcbiAqIEBwYXJhbSBmYyBjb21iaW5lIGZ1bmN0aW9uIChhLCBiKVxuICogQHJldHVybnMgeCA9IHgg4oipIHkgPSBcXHtba+G1oiwgduG1ol0gfCBba+G1oiwgduG1ol0g4oiIIHggYW5kIFtr4bWiLCB24bWiXSDiiIggeVxcfVxuICovXG5leHBvcnQgZnVuY3Rpb24gaW50ZXJzZWN0aW9uJDxLLCBWPih4OiBNYXA8SywgVj4sIHk6IE1hcDxLLCBWPiwgZmM6IENvbWJpbmVGdW5jdGlvbjxWPiB8IG51bGw9bnVsbCk6IE1hcDxLLCBWPiB7XG4gIGZjID0gZmMgfHwgSURFTlRJVFk7IGNvbnN0IGtzOiBLW10gPSBbXTtcbiAgZm9yIChjb25zdCBbaywgdV0gb2YgWy4uLnhdKSB7XG4gICAgaWYgKCF5LmhhcyhrKSkga3MucHVzaChrKTtcbiAgICB4LnNldChrLCBmYyh1LCB5LmdldChrKSBhcyBWKSk7XG4gIH1cbiAgcmV0dXJuIHJlamVjdEF0JCh4LCBrcyk7XG59XG5cblxuLyoqXG4gKiBPYnRhaW4gZW50cmllcyBub3QgcHJlc2VudCBpbiBhbm90aGVyIG1hcC5cbiAqIEBwYXJhbSB4IGEgbWFwXG4gKiBAcGFyYW0geSBhbm90aGVyIG1hcFxuICogQHJldHVybnMgeCAtIHkgPSBcXHtba+G1oiwgduG1ol0gfCBba+G1oiwgduG1ol0g4oiIIHgsIFtr4bWiLCAqXSDiiIkgeVxcfVxuICovXG5leHBvcnQgZnVuY3Rpb24gZGlmZmVyZW5jZTxLLCBWPih4OiBFbnRyaWVzPEssIFY+LCB5OiBFbnRyaWVzPEssIFY+KTogTWFwPEssIFY+IHtcbiAgcmV0dXJuIGRpZmZlcmVuY2UkKG5ldyBNYXAoeCksIHkpO1xufVxuXG5cbi8qKlxuICogT2J0YWluIGVudHJpZXMgbm90IHByZXNlbnQgaW4gYW5vdGhlciBtYXAuXG4gKiBAcGFyYW0geCBhIG1hcCAodXBkYXRlZClcbiAqIEBwYXJhbSB5IGFub3RoZXIgbWFwXG4gKiBAcmV0dXJucyB4ID0geCAtIHkgPSBcXHtba+G1oiwgduG1ol0gfCBba+G1oiwgduG1ol0g4oiIIHgsIFtr4bWiLCAqXSDiiIkgeVxcfVxuICovXG5leHBvcnQgZnVuY3Rpb24gZGlmZmVyZW5jZSQ8SywgVj4oeDogTWFwPEssIFY+LCB5OiBFbnRyaWVzPEssIFY+KTogTWFwPEssIFY+IHtcbiAgZm9yIChjb25zdCBba10gb2YgeSlcbiAgICB4LmRlbGV0ZShrKTtcbiAgcmV0dXJuIHg7XG59XG5cblxuLyoqXG4gKiBPYnRhaW4gZW50cmllcyBub3QgcHJlc2VudCBpbiBib3RoIG1hcHMuXG4gKiBAcGFyYW0geCBhIG1hcFxuICogQHBhcmFtIHkgYW5vdGhlciBtYXBcbiAqIEByZXR1cm5zIHgteSDiiKogeS14XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzeW1tZXRyaWNEaWZmZXJlbmNlPEssIFY+KHg6IEVudHJpZXM8SywgVj4sIHk6IEVudHJpZXM8SywgVj4pOiBNYXA8SywgVj4ge1xuICByZXR1cm4gc3ltbWV0cmljRGlmZmVyZW5jZSQobmV3IE1hcCh4KSwgeSk7XG59XG5cblxuLyoqXG4gKiBPYnRhaW4gZW50cmllcyBub3QgcHJlc2VudCBpbiBib3RoIG1hcHMuXG4gKiBAcGFyYW0geCBhIG1hcCAodXBkYXRlZClcbiAqIEBwYXJhbSB5IGFub3RoZXIgbWFwXG4gKiBAcmV0dXJucyB4ID0geC15IOKIqiB5LXhcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHN5bW1ldHJpY0RpZmZlcmVuY2UkPEssIFY+KHg6IE1hcDxLLCBWPiwgeTogRW50cmllczxLLCBWPik6IE1hcDxLLCBWPiB7XG4gIGZvciAoY29uc3QgW2ssIHZdIG9mIHkpIHtcbiAgICBpZiAoeC5oYXMoaykpIHguZGVsZXRlKGspO1xuICAgIGVsc2UgeC5zZXQoaywgdik7XG4gIH1cbiAgcmV0dXJuIHg7XG59XG5cblxuLyoqXG4gKiBMaXN0IGNhcnRlc2lhbiBwcm9kdWN0IG9mIG1hcHMuXG4gKiBAcGFyYW0geHMgbWFwc1xuICogQHBhcmFtIGZtIG1hcCBmdW5jdGlvbiAodnMsIGkpXG4gKiBAcmV0dXJucyB44oKAIMOXIHjigoEgw5cgLi4uID0gXFx7XFx7W2vigoAsIHbigoBdLCBba+KCgSwgduKCgV0sIC4uLlxcfSB8IFtr4oKALCB24oKAXSDiiIggeOKCgCwgW2vigoEsIHbigoFdIOKIiCB44oKBLCAuLi5dXFx9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiogY2FydGVzaWFuUHJvZHVjdDxLLCBWLCBXPU1hcDxLLCBWPj4oeHM6IE1hcDxLLCBWPltdLCBmbTogTWFwRnVuY3Rpb248bnVtYmVyLCBNYXA8SywgVj4sIE1hcDxLLCBWPnxXPiB8IG51bGw9bnVsbCk6IEl0ZXJhYmxlSXRlcmF0b3I8TWFwPEssIFY+fFc+IHtcbiAgZm0gPSBmbSB8fCBJREVOVElUWTtcbiAgY29uc3QgWFMgPSB4cy5sZW5ndGg7XG4gIGNvbnN0IGt4ID0geHMubWFwKHggPT4gWy4uLngua2V5cygpXSk7XG4gIGNvbnN0IGxzID0ga3gubWFwKGtzID0+IGtzLmxlbmd0aCk7XG4gIGNvbnN0IGlzID0ga3gubWFwKF9rcyA9PiAwKTtcbiAgZm9yIChsZXQgaj0wOzsgKytqKSB7XG4gICAgY29uc3QgYSA9IG5ldyBNYXA8SywgVj4oKTtcbiAgICBmb3IgKGxldCBuPTA7IG48WFM7ICsrbikge1xuICAgICAgY29uc3QgaSAgPSBpc1tuXSwgeCA9IHhzW25dO1xuICAgICAgY29uc3Qga3MgPSBreFtuXSwgayA9IGtzW2ldO1xuICAgICAgYS5zZXQoaywgeC5nZXQoaykgYXMgVik7XG4gICAgfVxuICAgIHlpZWxkIGZtKGEsIGosIG51bGwpO1xuICAgIGxldCByID0gWFMtMTtcbiAgICBmb3IgKDsgcj49MDsgLS1yKSB7XG4gICAgICBpZiAoKytpc1tyXSA8IGxzW3JdKSBicmVhaztcbiAgICAgIGlzW3JdID0gMDtcbiAgICB9XG4gICAgaWYgKHI8MCkgYnJlYWs7XG4gIH1cbn1cbiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxTQUNFLFFBQVEsRUFDUixPQUFPLFFBQ0Ysd0JBQXdCO0FBSS9CLFNBQ0UsUUFBZ0IsU0FBUyxFQUN6QixRQUFnQixTQUFTLEVBQ3pCLGdCQUFnQixpQkFBaUIsRUFDakMsZUFBZ0IsZ0JBQWdCLEVBQ2hDLHFCQUFxQixzQkFBc0IsUUFDdEMscUJBQXFCO0FBMkY1QixVQUFVO0FBQ1YsVUFBVTtBQUVWLFFBQVE7QUFDUixRQUFRO0FBRVI7Ozs7Q0FJQyxHQUNELE9BQU8sU0FBUyxHQUFHLENBQVU7RUFDM0IsT0FBTyxhQUFhO0FBQ3RCO0FBR0E7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