extra-array
Version:
An [array] is a collection of values, stored contiguously.<br>
2,945 lines • 280 kB
JavaScript
import { IDENTITY, COMPARE } from "@nodef/extra-function";
import { mod } from "@nodef/extra-math";
// #endregion
// #region METHODS
// ===============
// #region HELPERS
// ---------------
/** Convert an iterable to set. */ function toSet(x, fm = null) {
if (!fm) return new Set(x);
const a = new Set();
let i = -1;
for (const v of x)a.add(fm(v, ++i, x));
return a;
}
// #endregion
// #region GENERATE
// ----------------
/**
* Generate array from given number range.
* @param v start number
* @param V end number, excluding
* @param dv step size [1]
* @returns [v, v+dv, v+2dv, ...]
*/ export function fromRange(v, V, dv = 1) {
const n = (V - v) / dv, a = [];
for(let i = 0; i < n; ++i, v += dv)a.push(v);
return a;
}
/**
* Generate array from repeated function invocation.
* @param fn function
* @param n number of values
* @returns [fn(), fn(), ...]
*/ export function fromInvocation(fn, n) {
const a = [];
for(let i = 0; i < n; ++i)a.push(fn());
return a;
}
export { fromInvocation as fromCall };
/**
* Generate array from repeated function application.
* @param fm map function (v, i)
* @param v start value
* @param n number of values
* @returns [v, fm(v), fm(fm(v)), ...]
*/ export function fromApplication(fm, v, n) {
const a = [];
if (n !== 0) a.push(v);
for(let i = 1; i !== n; ++i)a.push(v = fm(v, i, null));
return a;
}
export { fromApplication as fromApply };
/**
* Convert an iterable to array.
* @param x an iterable
* @returns x as array
*/ export function fromIterable(x) {
return [
...x
];
}
export { fromIterable as from };
/**
* Convert an iterable to array!
* @param x an iterable (updatable if array!)
* @returns x as array
*/ export function fromIterable$(x) {
return Array.isArray(x) ? x : [
...x
];
}
export { fromIterable$ as from$ };
// #endregion
// #region CLONE
// -------------
/**
* Shallow clone an array.
* @param x an array
* @returns shallow clone of x
*/ export function shallowClone(x) {
return x.slice();
}
export { shallowClone as clone };
/**
* Deep clone an array.
* @param x an array
* @returns deep clone of x
*/ export function deepClone(x) {
return structuredClone(x);
}
// #endregion
// #region ABOUT
// -------------
/**
* Check if value is an array.
* @param v a value
* @returns v is an array?
*/ export function is(v) {
return Array.isArray(v);
}
/**
* Obtain all indices.
* @param x an array
* @returns [0, 1, ..., |x|-1]
*/ export function keys(x) {
return [
...x.keys()
];
}
/**
* List all indices.
* @param x an array
* @returns 0, 1, ..., |x|-1
*/ export function ikeys(x) {
return x.keys();
}
/**
* Get all values.
* @param x an array
* @returns [v₀, v₁, ...] | vᵢ = x[i]
*/ export function values(x) {
return x.slice();
}
/**
* List all values.
* @param x an array
* @returns v₀, v₁, ... | vᵢ = x[i]
*/ export function ivalues(x) {
return x.values();
}
/**
* Obtain all index-value pairs.
* @param x an array
* @returns [[0, v₀], [1, v₁], ...] | vᵢ = x[i]
*/ export function entries(x) {
return [
...x.entries()
];
}
/**
* List all index-value pairs.
* @param x an array
* @returns [0, v₀], [1, v₁], ... | vᵢ = x[i]
*/ export function ientries(x) {
return x.entries();
}
// #endregion
// #region INDEX
// -------------
/**
* Get zero-based index for an element in array.
* @param x an array
* @param i ±index
* @returns i' | x[i'] = x[i]; i' ∈ [0, |x|]
*/ export function index(x, i) {
const X = x.length;
return i >= 0 ? Math.min(i, X) : Math.max(X + i, 0);
}
/**
* Get zero-based index range for part of array.
* @param x an array
* @param i begin ±index [0]
* @param I end ±index (exclusive) [|x|]
* @returns [i', I'] | i' ≤ I'; i', I' ∈ [0, |x|]
*/ export function indexRange(x, i = 0, I = x.length) {
const X = x.length;
i = i >= 0 ? Math.min(i, X) : Math.max(X + i, 0);
I = I >= 0 ? Math.min(I, X) : Math.max(X + I, 0);
return [
i,
Math.max(i, I)
];
}
// #endregion
// #region LENGTH
// --------------
/**
* Check if an array is empty.
* @param x an array
* @returns |x| = 0?
*/ export function isEmpty(x) {
return x.length === 0;
}
/**
* Find the length of an array.
* @param x an array
* @param i begin ±index [0]
* @param I end ±index (exclusive) [X]
* @returns |x[i..I]|
*/ export function length(x, i = 0, I = x.length) {
[i, I] = indexRange(x, i, I);
return I - i;
}
export { length as size };
/**
* Resize an array to given length!
* @param x an array
* @param n new length
* @param vd default value
* @returns resized x
*/ export function resize$(x, n, vd) {
const X = x.length;
x.length = n;
if (n > X) x.fill(vd, X);
return x;
}
/**
* Remove all elements from an array!
* @param x an array (updated!)
* @returns cleared x
*/ export function clear$(x) {
x.length = 0;
return x;
}
// #endregion
// #region GET/SET
// ---------------
/**
* Get value at index.
* @param x an array
* @param i index
* @returns x[i]
*/ export function get(x, i) {
return x[index(x, i)];
}
export { get as at };
// Get values at index range.
// export {slice as getRange};
/**
* Get values at indices.
* @param x an array
* @param is indices
* @returns [x[i₀], x[i₁], ...] | [i₀, i₁, ...] = is
*/ export function getAll(x, is) {
return is.map((i)=>get(x, i));
}
/**
* Get value at path in a nested array.
* @param x a nested array
* @param p path
* @returns x[i₀][i₁][...] | [i₀, i₁, ...] = p
*/ export function getPath(x, p) {
let a = x;
for (const i of p)a = is(a) ? get(a, i) : undefined;
return a;
}
/**
* Check if nested array has a path.
* @param x a nested array
* @param p path
* @returns x[i₀][i₁][...] exists? | [i₀, i₁, ...] = p
*/ export function hasPath(x, p) {
let a = x;
for (const i of p){
if (!is(a)) return false;
a = get(a, i);
}
return true;
}
/**
* Set value at index.
* @param x an array
* @param i index
* @param v value
* @returns x' | x' = x; x'[i] = v
*/ export function set(x, i, v) {
return set$(x.slice(), i, v);
}
export { set as with };
/**
* Set value at index!
* @param x an array (updated!)
* @param i index
* @param v value
* @returns x | x[i] = v
*/ export function set$(x, i, v) {
x[index(x, i)] = v;
return x;
}
// TODO: setRange$()
// TODO: setAll$()
/**
* Set value at path in a nested array!
* @param x a nested array (updated!)
* @param p path
* @param v value
* @returns x | x[i₀][i₁][...] = v; [i₀, i₁, ...] = p
*/ export function setPath$(x, p, v) {
const y = getPath(x, p.slice(0, -1));
if (is(y)) set$(y, last(p), v);
return x;
}
/**
* Exchange two values.
* @param x an array
* @param i an index
* @param j another index
* @returns x' | x' = x; x'[i] = x[j]; x'[j] = x[i]
*/ export function swap(x, i, j) {
return swap$(x.slice(), i, j);
}
/**
* Exchange two values!
* @param x an array (updated!)
* @param i an index
* @param j another index
* @returns x | x[i] ⇔ x[j]
*/ export function swap$(x, i, j) {
i = index(x, i);
j = index(x, j);
const t = x[i];
x[i] = x[j];
x[j] = t;
return x;
}
/**
* Exchange two values!
* @param x an array (updated!)
* @param i an +ve index
* @param j another +ve index
* @returns x | x[i] ⇔ x[j]
*/ function swapRaw$(x, i, j) {
const t = x[i];
x[i] = x[j];
x[j] = t;
return x;
}
// NOTE: May also be called swapUnchecked$().
/**
* Exchange two ranges of values.
* @param x an array
* @param i begin index of first range
* @param I end index of first range (exclusive)
* @param j begin index of second range
* @param J end index of second range (exclusive)
* @returns x' | x' = x; x'[i..I] = x[j..J]; x'[j..J] = x[i..I]
*/ export function swapRanges(x, i, I, j, J) {
[i, I] = indexRange(x, i, I);
[j, J] = indexRange(x, j, J);
if (j < i) [i, I, j, J] = [
j,
J,
i,
I
];
if (j < I) return x.slice(); // Skip if ranges overlap!
return x.slice(0, i).concat(x.slice(j, J), x.slice(i, j), x.slice(I));
}
/**
* Exchange two ranges of values!
* @param x an array (updated!)
* @param i begin index of first range
* @param I end index of first range (exclusive)
* @param j begin index of second range
* @param J end index of second range (exclusive)
* @returns x | x[i..I] ⇔ x[j..J]
*/ export function swapRanges$(x, i, I, j, J) {
[i, I] = indexRange(x, i, I);
[j, J] = indexRange(x, j, J);
if (j < i) [i, I, j, J] = [
j,
J,
i,
I
];
if (j < I) return x; // Skip if ranges overlap!
const t = x.slice(i, I);
x.splice(i, I - i, ...x.slice(j, J));
x.splice(j, J - j, ...t);
return x;
}
// TODO: swapAll$()
/**
* Remove value at index.
* @param x an array
* @param i index
* @returns x[0..i] ⧺ x[i+1..]
*/ export function remove(x, i) {
i = index(x, i);
return x.slice(0, i).concat(x.slice(i + 1));
}
/**
* Remove value at index!
* @param x an array (updated!)
* @param i index
* @returns x \\: [i]
*/ export function remove$(x, i) {
x.splice(i, 1);
return x;
}
/**
* Remove value at path in a nested array!
* @param x a nested array (updated!)
* @param p path
* @returns x \\: [i₀][i₁][...] | [i₀, i₁, ...] = p
*/ export function removePath$(x, p) {
const y = getPath(x, p.slice(0, -1));
if (is(y)) y.splice(last(p), 1);
return x;
}
// #endregion
// #region SORT
// ------------
/**
* Examine if array is sorted.
* @param x an array
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns x is sorted?
*/ export function isSorted(x, fc = null, fm = null) {
return searchUnsortedValue(x, fc, fm) === -1;
}
/**
* Examine if array has an unsorted value.
* @param x an array
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns x is not sorted?
*/ export function hasUnsortedValue(x, fc = null, fm = null) {
return searchUnsortedValue(x, fc, fm) >= 0;
}
/**
* Find first index of an unsorted value.
* @param x an array
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns index of first unsorted value, -1 if sorted
*/ export function searchUnsortedValue(x, fc = null, fm = null) {
fc = fc || COMPARE;
fm = fm || IDENTITY;
const X = x.length;
if (X <= 1) return -1;
let w0 = fm(x[0], 0, x);
for(let i = 1; i < X; ++i){
const w = fm(x[i], i, x);
if (fc(w0, w) > 0) return i;
w0 = w;
}
return -1;
}
/**
* Arrange values in order.
* @param x an array
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @param fs swap function (x, i, j)
* @returns x' | x' = x; x'[i] ≤ x'[j] ∀ i ≤ j
*/ export function sort(x, fc = null, fm = null, fs = null) {
return sort$(x.slice(), fc, fm, fs);
}
export { sort as toSorted };
/**
* Arrange values in order!
* @param x an array (updated!)
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @param fs swap function (x, i, j)
* @returns x | x[i] ≤ x[j] ∀ i ≤ j
*/ export function sort$(x, fc = null, fm = null, fs = null) {
fc = fc || COMPARE;
if (!fm && !fs) return x.sort(fc);
const X = x.length;
fm = fm || IDENTITY;
fs = fs || swapRaw$;
return rangedPartialIntroSort$(x, 0, X, X, fc, fm, fs);
}
/**
* Arrange a range of values in order.
* @param x an array
* @param i begin index
* @param I end index (exclusive)
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @param fs swap function (x, i, j)
* @returns x' | x' = x; x'[i] ≤ x'[j] ∀ i ≤ j
*/ export function rangedSort(x, i, I, fc = null, fm = null, fs = null) {
return rangedSort$(x.slice(), i, I, fc, fm, fs);
}
/**
* Arrange a range of values in order!
* @param x an array (updated!)
* @param i begin index
* @param I end index (exclusive)
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @param fs swap function (x, i, j)
* @returns x | x[i] ≤ x[j] ∀ i ≤ j
*/ export function rangedSort$(x, i, I, fc = null, fm = null, fs = null) {
fc = fc || COMPARE;
fm = fm || IDENTITY;
fs = fs || swapRaw$;
[i, I] = indexRange(x, i, I);
return rangedPartialIntroSort$(x, i, I, I - i, fc, fm, fs);
}
/**
* Partially arrange values in order.
* @param x an array
* @param n minimum number of values to sort
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @param fs swap function (x, i, j)
* @returns x' | x' = x; x'[i] ≤ x'[j] ∀ i ≤ j
*/ export function partialSort(x, n, fc = null, fm = null, fs = null) {
return partialSort$(x.slice(), n, fc, fm, fs);
}
/**
* Partially arrange values in order!
* @param x an array (updated!)
* @param n minimum number of values to sort
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @param fs swap function (x, i, j)
* @returns x | x[i] ≤ x[j] ∀ i ≤ j
*/ export function partialSort$(x, n, fc = null, fm = null, fs = null) {
return rangedPartialSort$(x, 0, x.length, n, fc, fm, fs);
}
/**
* Partially arrange a range of values in order.
* @param x an array
* @param i begin index
* @param I end index (exclusive)
* @param n minimum number of values to sort
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @param fs swap function (x, i, j)
* @returns x' | x' = x; x'[i] ≤ x'[j] ∀ i ≤ j
*/ export function rangedPartialSort(x, i, I, n, fc = null, fm = null, fs = null) {
return rangedPartialSort$(x.slice(), i, I, n, fc, fm, fs);
}
/**
* Partially arrange a range of values in order!
* @param x an array (updated!)
* @param i begin index
* @param I end index (exclusive)
* @param n minimum number of values to sort
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @param fs swap function (x, i, j)
* @returns x | x[i] ≤ x[j] ∀ i ≤ j
*/ export function rangedPartialSort$(x, i, I, n, fc = null, fm = null, fs = null) {
fc = fc || COMPARE;
fm = fm || IDENTITY;
fs = fs || swapRaw$;
[i, I] = indexRange(x, i, I);
return rangedPartialIntroSort$(x, i, I, n, fc, fm, fs);
}
/**
* Partially arrange values in order!
* @param x an array (updated!)
* @param i begin index
* @param I end index (exclusive)
* @param n minimum number of values to sort
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @param fs swap function (x, i, j)
* @returns x | x[i] ≤ x[j] ∀ i ≤ j
*/ function rangedPartialIntroSort$(x, i, I, n, fc, fm, fs) {
const d = Math.floor(Math.log2(I - i) * 2); // Maximum depth of recursion
const s = 16; // When to switch to insertion sort
return rangedPartialIntroSortDo$(x, i, I, d, s, n, fc, fm, fs);
}
// Partially arrange a range of values in order with hybrid quick sort, heap sort, and insertion sort.
function rangedPartialIntroSortDo$(x, i, I, d, s, n, fc, fm, fs) {
if (n <= 0 || I - i <= 1) return x; // Nothing to sort
if (I - i <= s) return rangedPartialInsertionSort$(x, i, I, n, fc, fm, fs); // Insertion sort
if (d <= 0) return rangedPartialHeapSort$(x, i, I, n, fc, fm, fs); // Heap sort
let p = i + Math.floor((I - i) * Math.random()); // Choose pivot
p = rangedQuickSortPartition$(x, i, I, p, fc, fm, fs); // Partition array
rangedPartialIntroSortDo$(x, i, p, d, s, Math.min(p - i, n), fc, fm, fs); // Sort left part
rangedPartialIntroSortDo$(x, p + 1, I, d, s, Math.min(I - p - 1, n), fc, fm, fs); // Sort right part
return x;
}
/**
* Partially arrange a range of values in order!
* @param x an array (updated!)
* @param i begin index
* @param I end index (exclusive)
* @param n minimum number of values to sort
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @param fs swap function (x, i, j)
* @returns x | x[i] ≤ x[j] ∀ i ≤ j
*/ function _rangedPartialQuickSort$(x, i, I, n, fc, fm, fs) {
if (n <= 0 || I - i <= 1) return x; // Nothing to sort
let p = i + Math.floor((I - i) * Math.random()); // Choose pivot
p = rangedQuickSortPartition$(x, i, I, p, fc, fm, fs); // Partition array
_rangedPartialQuickSort$(x, i, p, Math.min(p - i, n), fc, fm, fs); // Sort left part
_rangedPartialQuickSort$(x, p + 1, I, Math.min(I - p - 1, n), fc, fm, fs); // Sort right part
return x;
}
// TODO: Make this a generic function.
// Partition the array into two parts, such that values in the first part are less than values in the second part.
function rangedQuickSortPartition$(x, i, I, p, fc, fm, fs) {
const wp = fm(x[p], p, x); // Pivot value
let j = i - 1; // Last index of values ≤ pivot
fs(x, p, I - 1); // Move pivot to end
for(let k = i; k < I - 1; ++k){
const wk = fm(x[k], k, x);
if (fc(wk, wp) > 0) continue;
fs(x, ++j, k); // Move value ≤ pivot to left
}
fs(x, ++j, I - 1); // Move pivot to middle
return j; // Return pivot index
}
/**
* Partially arrange a range of values in order!
* @param x an array (updated!)
* @param i begin index
* @param I end index (exclusive)
* @param n minimum number of values to sort
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @param fs swap function (x, i, j)
* @returns x | x[i] ≤ x[j] ∀ i ≤ j
*/ function rangedPartialHeapSort$(x, i, I, n, fc, fm, fs) {
rangedBuildReverseMinHeap$(x, i, I, fc, fm, fs);
for(const r = I - 1; n > 0 && i < I; ++i, --n){
fs(x, i, r); // Move root to the beginning
rangedReverseMinHeapify$(x, i + 1, I, r, fc, fm, fs); // Rebuild heap
}
return x;
}
// Build a reverse min-heap from a range of values, where root node is the smallest and placed at the end.
function rangedBuildReverseMinHeap$(x, i, I, fc, fm, fs) {
for(let r = I - Math.floor((I - i) / 2); r < I; ++r)rangedReverseMinHeapify$(x, i, I, r, fc, fm, fs);
}
/**
* Reverse min-heapify a range of values, such that root node is the smallest and placed at the end.
* @param x an array (updated!)
* @param i begin index
* @param I end index (exclusive)
* @param r root index
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @param fs swap function (x, i, j)
*/ function rangedReverseMinHeapify$(x, i, I, r, fc, fm, fs) {
let s = r; // Index of smallest value
const lt = 2 * r - I; // Left child, reverse of lt = 2*r+1
const rt = lt - 1; // Right child, reverse of rt = 2*r+2
if (lt >= i && fc(fm(x[lt], lt, x), fm(x[s], s, x)) < 0) s = lt; // Left child is smaller?
if (rt >= i && fc(fm(x[rt], rt, x), fm(x[s], s, x)) < 0) s = rt; // Right child is smaller?
if (s !== r) {
fs(x, s, r); // Swap root with smallest
rangedReverseMinHeapify$(x, i, I, s, fc, fm, fs); // Rebuild heap
}
}
// Build a max-heap from a range of values, where root node is the smallest and placed at the beginning.
function rangedBuildMaxHeap$(x, i, I, fc, fm, fs) {
for(let r = i + Math.floor((I - i) / 2) - 1; r >= i; --r)rangedMaxHeapify$(x, i, I, r, fc, fm, fs);
}
/**
* Max-heapify a range of values, such that root node is the largest and placed at the beginning.
* @param x an array (updated!)
* @param i begin index
* @param I end index (exclusive)
* @param r root index
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @param fs swap function (x, i, j)
*/ function rangedMaxHeapify$(x, i, I, r, fc, fm, fs) {
let s = r; // Index of largest value
const lt = 2 * r - i + 1; // Left child, like lt = 2*r+1
const rt = lt + 1; // Right child, like rt = 2*r+2
if (lt < I && fc(fm(x[lt], lt, x), fm(x[s], s, x)) > 0) s = lt; // Left child is larger?
if (rt < I && fc(fm(x[rt], rt, x), fm(x[s], s, x)) > 0) s = rt; // Right child is larger?
if (s !== r) {
fs(x, s, r); // Swap root with largest
rangedMaxHeapify$(x, i, I, s, fc, fm, fs); // Rebuild heap
}
}
/**
* Partially arrange a range of values in order!
* @param x an array (updated!)
* @param i begin index
* @param I end index (exclusive)
* @param n minimum number of values to sort (ignored)
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @param fs swap function (x, i, j)
* @returns x | x[i] ≤ x[j] ∀ i ≤ j
*/ function rangedPartialInsertionSort$(x, i, I, n, fc, fm, fs) {
// NOTE: Insertion sort does not support partial sorting, so we ignore n.
if (fs === swapRaw$) return rangedPartialInsertionSortSwapless$(x, i, I, n, fc, fm, fs);
else return rangedPartialInsertionSortSwap$(x, i, I, n, fc, fm, fs);
}
// Sort a range of values in order with swap-enabled version of insertion sort.
function rangedPartialInsertionSortSwap$(x, i, I, _n, fc, fm, fs) {
for(let j = i + 1; j < I; ++j){
const key = x[j];
const wkey = fm(key, j, x);
for(let k = j - 1; k >= i && fc(fm(x[k], k, x), wkey) > 0; --k)fs(x, k, k + 1);
}
return x;
}
// Sort a range of values in order with swapless version of insertion sort.
function rangedPartialInsertionSortSwapless$(x, i, I, _n, fc, fm, _fs) {
for(let j = i + 1; j < I; ++j){
const key = x[j];
const wkey = fm(key, j, x);
let k = j - 1;
for(; k >= i && fc(fm(x[k], k, x), wkey) > 0; --k)x[k + 1] = x[k];
x[k + 1] = key;
}
return x;
}
/**
* Partially arrange a range of values in order!
* @param x an array (updated!)
* @param i begin index
* @param I end index (exclusive)
* @param n minimum number of values to sort
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @param fs swap function (x, i, j)
* @returns x | x[i] ≤ x[j] ∀ i ≤ j
*/ function _rangedPartialSelectionSort$(x, i, I, n, fc, fm, fs) {
for(let j = i; n > 0 && j < I; ++j, --n){
let l = j;
let wl = fm(x[l], l, x);
for(let k = j + 1; k < I; ++k){
const wk = fm(x[k], k, x);
if (fc(wl, wk) > 0) {
l = k;
wl = wk;
}
}
fs(x, j, l);
}
return x;
}
// #endregion
// #region MINIMUM/MAXIMUM
// -----------------------
/**
* Find first smallest value.
* @param x an array
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns v | v ≤ vᵢ; vᵢ ∈ x
*/ export function minimum(x, fc = null, fm = null) {
const i = searchMinimumValue(x, fc, fm);
return x[i];
}
export { minimum as min };
/**
* Find first smallest entry.
* @param x an array
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns [min_index, min_value]
*/ export function minimumEntry(x, fc = null, fm = null) {
const i = searchMinimumValue(x, fc, fm);
return [
i,
x[i]
];
}
export { minimumEntry as minEntry };
/**
* Find first largest value.
* @param x an array
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns v | v ≥ vᵢ; vᵢ ∈ x
*/ export function maximum(x, fc = null, fm = null) {
const i = searchMaximumValue(x, fc, fm);
return x[i];
}
export { maximum as max };
/**
* Find first largest entry.
* @param x an array
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns [max_index, max_value]
*/ export function maximumEntry(x, fc = null, fm = null) {
const i = searchMaximumValue(x, fc, fm);
return [
i,
x[i]
];
}
export { maximumEntry as maxEntry };
/**
* Find smallest and largest values.
* @param x an array
* @param fc compare function (a, b)
* @param fm map function (v, i, 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 an array
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns [min_entry, max_entry]
*/ export function rangeEntries(x, fc = null, fm = null) {
fc = fc || COMPARE;
fm = fm || IDENTITY;
const X = x.length;
if (X === 0) return [
[
-1,
undefined
],
[
-1,
undefined
]
];
let v = x[0], w = fm(v, 0, x);
let mi = 0, mv = v, mw = w;
let ni = 0, nv = v, nw = w;
for(let i = 1; i < X; ++i){
v = x[i];
w = fm(v, i, x);
if (fc(w, mw) < 0) {
mi = i;
mv = v;
mw = w;
}
if (fc(w, nw) > 0) {
ni = i;
nv = v;
nw = w;
}
}
return [
[
mi,
mv
],
[
ni,
nv
]
];
}
/**
* Find smallest values.
* @param x an array
* @param n number of values
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns n smallest values in ascending order
*/ export function minimums(x, n, fc = null, fm = null) {
const is = searchMinimumValues(x, n, fc, fm);
return is.map((i)=>x[i]);
}
/**
* Find smallest entries.
* @param x an array
* @param n number of values
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns n smallest entries in ascending order
*/ export function minimumEntries(x, n, fc = null, fm = null) {
const is = searchMinimumValues(x, n, fc, fm);
return is.map((i)=>[
i,
x[i]
]);
}
/**
* Find largest values.
* @param x an array
* @param n number of values
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns n largest values in descending order
*/ export function maximums(x, n, fc = null, fm = null) {
const is = searchMaximumValues(x, n, fc, fm);
return is.map((i)=>x[i]);
}
/**
* Find largest entries.
* @param x an array
* @param n number of values
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns n largest entries in descending order
*/ export function maximumEntries(x, n, fc = null, fm = null) {
const is = searchMaximumValues(x, n, fc, fm);
return is.map((i)=>[
i,
x[i]
]);
}
/**
* Find first index of minimum value.
* @param x an array
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns first index of minimum value, -1 if empty
*/ export function searchMinimumValue(x, fc = null, fm = null) {
fc = fc || COMPARE;
fm = fm || IDENTITY;
const X = x.length;
if (X === 0) return -1;
let mi = 0, mw = fm(x[0], 0, x);
for(let i = 1; i < X; ++i){
const w = fm(x[i], i, x);
if (fc(w, mw) < 0) {
mi = i;
mw = w;
}
}
return mi;
}
/**
* Find first index of maximum value.
* @param x an array
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns first index of maximum value, -1 if empty
*/ export function searchMaximumValue(x, fc = null, fm = null) {
fc = fc || COMPARE;
fm = fm || IDENTITY;
const X = x.length;
if (X === 0) return -1;
let ni = 0, nw = fm(x[0], 0, x);
for(let i = 1; i < X; ++i){
const w = fm(x[i], i, x);
if (fc(w, nw) > 0) {
ni = i;
nw = w;
}
}
return ni;
}
/**
* Find indices of minimum values.
* @param x an array
* @param n number of values
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns indices of minimum values in ascending order
*/ export function searchMinimumValues(x, n, fc = null, fm = null) {
fc = fc || COMPARE;
fm = fm || IDENTITY;
const X = x.length;
// Create a max heap of indices.
const IH = Math.min(n, X);
const ih = fromRange(0, IH);
rangedBuildMaxHeap$(ih, 0, IH, fc, (i)=>fm(x[i], i, x), swapRaw$);
let wr = fm(x[ih[0]], ih[0], x);
// Search for minimum values, and update heap.
for(let i = n; i < X; ++i){
const w = fm(x[i], i, x);
if (fc(w, wr) >= 0) continue;
ih[0] = i;
rangedMaxHeapify$(ih, 0, IH, 0, fc, (i)=>fm(x[i], i, x), swapRaw$);
wr = fm(x[ih[0]], ih[0], x);
}
// Sort max heap in ascending order.
ih.sort((i, j)=>fc(fm(x[i], i, x), fm(x[j], j, x)));
return ih;
}
/**
* Find indices of maximum values.
* @param x an array
* @param n number of values
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns indices of maximum values in descending order
*/ export function searchMaximumValues(x, n, fc = null, fm = null) {
fc = fc || COMPARE;
const fd = (a, b)=>-fc(a, b);
return searchMinimumValues(x, n, fd, fm);
}
// #endregion
// #region COMPARE
// ---------------
/**
* Examine if two arrays are equal.
* @param x an array
* @param y another array
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns x = y?
*/ export function isEqual(x, y, fc = null, fm = null) {
const X = x.length, Y = y.length;
return X === Y && compare(x, y, fc, fm) === 0;
}
/**
* Compare two arrays (lexicographically).
* @param x an array
* @param y another array
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns x<y: -ve, x=y: 0, x>y: +ve
*/ export function compare(x, y, fc = null, fm = null) {
fc = fc || COMPARE;
fm = fm || IDENTITY;
const X = x.length;
const Y = y.length;
for(let i = 0, I = Math.min(X, Y); i < I; ++i){
const wx = fm(x[i], i, x);
const wy = fm(y[i], i, y);
const c = fc(wx, wy);
if (c !== 0) return c;
}
return Math.sign(X - Y);
}
// #endregion
// #region PART
// ------------
/**
* Get first value.
* @param x an array
* @param vd default value
* @returns x[0] || vd
*/ export function head(x, vd) {
return x.length > 0 ? x[0] : vd;
}
export { head as front };
export { head as first };
/**
* Get values except first.
* @param x an array
* @returns x[1..|x|]
*/ export function tail(x) {
return x.slice(1);
}
/**
* Get values except last.
* @param x an array
* @returns x[0..|x|-1]
*/ export function init(x) {
return x.slice(0, -1);
}
/**
* Get last value.
* @param x an array
* @param vd default value
* @returns x[|x|-1] || vd
*/ export function last(x, vd) {
return x.length > 0 ? x[x.length - 1] : vd;
}
export { last as back };
/**
* Get values from middle.
* @param x an array
* @param i begin index
* @param n number of values [1]
* @returns x[i..i+n]
*/ export function middle(x, i, n = 1) {
i = index(x, i);
n = Math.max(n, 0);
return x.slice(i, i + n);
}
/**
* Get part of an array.
* @param x an array
* @param i begin index [0]
* @param I end index [|x|]
* @returns x[i..I]
*/ export function slice(x, i = 0, I = x.length) {
return x.slice(i, I);
}
/**
* Get part of an array!
* @param x an array (updated!)
* @param i begin index [0]
* @param I end index [|x|]
* @returns x = x[i..I]
*/ export function slice$(x, i = 0, I = x.length) {
x.copyWithin(0, i, I);
x.length = length(x, i, I);
return x;
}
// #endregion
// #region SEARCH VALUE
// --------------------
/**
* Check if array has a value.
* @param x an array
* @param v search value
* @param i begin index [0]
* @returns v ∈ x[i..]?
*/ export function includes(x, v, i = 0) {
return x.includes(v, i);
}
/**
* Examine if array has a value.
* @param x an array
* @param v search value
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns v ∈ x?
*/ export function hasValue(x, v, fc = null, fm = null) {
return searchValue(x, v, fc, fm) >= 0;
}
/**
* Find first index of a value.
* @param x an array
* @param v search value
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns first index of value, -1 if not found
*/ export function searchValue(x, v, fc = null, fm = null) {
fc = fc || COMPARE;
fm = fm || IDENTITY;
const w = fm(v, 0, null);
let i = -1;
for (const vx of x){
const wx = fm(vx, ++i, x);
if (fc(wx, w) === 0) return i;
}
return -1;
}
/**
* Find last index of a value.
* @param x an array
* @param v search value
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns last index of value, -1 if not found
*/ export function searchValueRight(x, v, fc = null, fm = null) {
fc = fc || COMPARE;
fm = fm || IDENTITY;
const w = fm(v, 0, null);
for(let i = x.length - 1; i >= 0; --i){
const wx = fm(x[i], i, x);
if (fc(wx, w) === 0) return i;
}
return -1;
}
/**
* Find indices of value.
* @param x an array
* @param v search value
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns indices of value
*/ export function searchValueAll(x, v, fc = null, fm = null) {
fc = fc || COMPARE;
fm = fm || IDENTITY;
const w = fm(v, 0, null);
let i = -1;
const a = [];
for (const vx of x){
const wx = fm(vx, ++i, x);
if (fc(wx, w) === 0) a.push(i);
}
return a;
}
/**
* Find first index of an adjacent duplicate value.
* @param x an array
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns index of first adjacent duplicate value, -1 if none
*/ export function searchAdjacentDuplicateValue(x, fc = null, fm = null) {
fc = fc || COMPARE;
fm = fm || IDENTITY;
const X = x.length;
if (X <= 1) return -1;
let w0 = fm(x[0], 0, x);
for(let i = 1; i < X; ++i){
const w = fm(x[i], i, x);
if (fc(w0, w) === 0) return i;
w0 = w;
}
return -1;
}
export { searchAdjacentDuplicateValue as searchAdjacentDuplicate };
/**
* Find first index where two arrays differ.
* @param x an array
* @param y another array
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns first index where x[i] ≠ y[i], or -1
*/ export function searchMismatchedValue(x, y, fc = null, fm = null) {
fc = fc || COMPARE;
fm = fm || IDENTITY;
const X = x.length;
const Y = y.length;
const I = Math.min(X, Y);
for(let i = 0; i < I; ++i){
const wx = fm(x[i], i, x);
const wy = fm(y[i], i, y);
if (fc(wx, wy) !== 0) return i;
}
return X === Y ? -1 : I;
}
export { searchMismatchedValue as searchMismatch };
// #endregion
// #region ARRANGEMENTS
// --------------------
/**
* Examine if array starts with a prefix.
* @param x an array
* @param y search prefix
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns x[0..|y|] = y?
*/ export function hasPrefix(x, y, fc = null, fm = null) {
const Y = y.length;
return Y === 0 || compare(x.slice(0, Y), y, fc, fm) === 0;
}
export { hasPrefix as startsWith };
/**
* Examine if array ends with a suffix.
* @param x an array
* @param y search suffix
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns x[|x|-|y|..] = y?
*/ export function hasSuffix(x, y, fc = null, fm = null) {
const Y = y.length;
return Y === 0 || compare(x.slice(-Y), y, fc, fm) === 0;
}
export { hasSuffix as endsWith };
/**
* Examine if array contains an infix.
* @param x an array
* @param y search infix
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns x[i..I] = y for some i, I?
*/ export function hasInfix(x, y, fc = null, fm = null) {
return searchInfix(x, y, fc, fm) >= 0;
}
/**
* Examine if array has a subsequence.
* @param x an array
* @param y search subsequence
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns x[i₀] ⧺ x[i₁] ⧺ ... = y, for some i₀, i₁, ...? | i₀ < i₁ < ...
*/ export function hasSubsequence(x, y, fc = null, fm = null) {
return searchSubsequence(x, y, fc, fm) >= 0;
}
/**
* Examine if array has a permutation.
* @param x an array
* @param y search permutation
* @param fc map function (v, i, x)
* @param fm compare function (a, b)
* @returns x contains a shuffled version of y?
*/ export function hasPermutation(x, y, fc = null, fm = null) {
const x1 = fm ? x.map(fm) : x.slice();
const y1 = fm ? y.map(fm) : y.slice();
return hasSubsequence(x1.sort(), y1.sort(), fc);
// return hasSubsequence<T|U>(x1.sort(), y1.sort(), fc, fm);
}
/**
* Obtain all possible prefixes.
* @param x an array
* @param n number of values [-1 ⇒ any]
* @returns [[], x[..1], x[..2], ...] if n<0; [x[..n]] otherwise
*/ export function prefixes(x, n = -1) {
return [
...iprefixes(x, n)
];
}
/**
* List all possible prefixes.
* @param x an array
* @param n number of values [-1 ⇒ any]
* @returns [], x[..1], x[..2], ... if n<0; x[..n] otherwise
*/ export function* iprefixes(x, n = -1) {
const X = x.length;
if (n > X) return;
if (n >= 0) {
yield x.slice(0, n);
return;
}
for(let i = 0; i <= X; ++i)yield x.slice(0, i);
}
/**
* Obtain all possible suffixes.
* @param x an array
* @param n number of values [-1 ⇒ any]
* @returns [x[0..], x[1..], x[2..], ...] if n<0; [x[-n..]] otherwise
*/ export function suffixes(x, n = -1) {
return [
...isuffixes(x, n)
];
}
/**
* List all possible suffixes.
* @param x an array
* @param n number of values [-1 ⇒ any]
* @returns x[0..], x[1..], x[2..], ... if n<0; x[-n..] otherwise
*/ export function* isuffixes(x, n = -1) {
const X = x.length;
if (n > X) return;
if (n >= 0) {
yield x.slice(x.length - n);
return;
}
for(let i = 0; i <= X; ++i)yield x.slice(i);
}
/**
* Obtain all possible infixes.
* @param x an array
* @param n number of values [-1 ⇒ any]
* @returns [[], x[0..1], x[0..2], ..., x[1..2], ...] if n<0; [only of length n] otherwise
*/ export function infixes(x, n = -1) {
return [
...iinfixes(x, n)
];
}
/**
* List all possible infixes.
* @param x an array
* @param n number of values [-1 ⇒ any]
* @returns [], x[0..1], x[0..2], ..., x[1..2], ... if n<0; only of length n otherwise
*/ export function iinfixes(x, n = -1) {
if (n >= 0) return infixesFixed(x, n);
else return infixesAll(x);
}
function* infixesFixed(x, n) {
const X = x.length;
if (n > X) return;
if (n === 0) {
yield [];
return;
}
for(let i = 0, I = X - n + 1; i < I; ++i)yield x.slice(i, i + n);
}
function* infixesAll(x) {
const X = x.length;
yield [];
for(let i = 0; i < X; ++i){
for(let j = i + 1; j <= X; ++j)yield x.slice(i, j);
}
}
/**
* Obtain all possible subsequences.
* @param x an array
* @param n number of values [-1 ⇒ any]
* @returns [elements selected by bit from 0..2^|x|] if n<0; [only of length n] otherwise
*/ export function subsequences(x, n = -1) {
return [
...isubsequences(x, n)
];
}
/**
* List all possible subsequences.
* @param x an array
* @param n number of values [-1 ⇒ any]
* @returns elements selected by bit from 0..2^|x| if n<0; only of length n otherwise
*/ export function* isubsequences(x, n = -1) {
const X = x.length;
if (n > X) return;
if (n === X) {
yield x;
return;
}
if (n === 0 || X === 0) {
yield [];
return;
}
const y = x.slice(0, -1);
yield* isubsequences(y, n);
for (const s of isubsequences(y, n - 1)){
s.push(x[X - 1]);
yield s;
}
}
/**
* Obtain all possible permutations.
* @param x an array
* @param n number of values [-1 ⇒ any]
* @returns [[], arrangements of length 1, of length 2, ...] if n<0; [only of length n] otherwise
*/ export function permutations(x, n = -1) {
return [
...ipermutations(x, n)
];
}
/**
* List all possible permutations.
* @param x an array
* @param n number of values [-1 ⇒ any]
* @returns [], arrangements of length 1, of length 2, ... if n<0; only of length n otherwise
*/ export function* ipermutations(x, n = -1) {
const X = x.length;
if (n > X) return;
let i = n < 0 ? 0 : n;
const I = n < 0 ? X : n;
for(; i <= I; ++i)yield* ipermutationsFixed(x, i);
}
function* ipermutationsFixed(x, n) {
const X = x.length;
if (X === 0 || n === 0) {
yield [];
return;
}
for(let i = 0; i < X; ++i){
const y = splice(x, i, 1);
for (const p of ipermutationsFixed(y, n - 1))yield [
x[i],
...p
];
}
}
/**
* Find first index of an infix.
* @param x an array
* @param y search infix
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns first i | x[i..i+|y|] = y else -1
*/ export function searchInfix(x, y, fc = null, fm = null) {
fc = fc || COMPARE;
fm = fm || IDENTITY;
const X = x.length, Y = y.length;
for(let i = 0; i <= X - Y; ++i)if (isInfixAt(x, y, i, fc, fm)) return i;
return -1;
}
/**
* Find last index of an infix.
* @param x an array
* @param y search infix
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns first i | x[i..i+|y|] = y else -1
*/ export function searchInfixRight(x, y, fc = null, fm = null) {
fc = fc || COMPARE;
fm = fm || IDENTITY;
const X = x.length, Y = y.length;
for(let i = X - Y; i >= 0; --i)if (isInfixAt(x, y, i, fc, fm)) return i;
return -1;
}
/**
* Find indices of an infix.
* @param x an array
* @param y search infix
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns i₀, i₁, ... | x[j..j+|y|] = y; j ∈ [i₀, i₁, ...]
*/ export function searchInfixAll(x, y, fc = null, fm = null) {
fc = fc || COMPARE;
fm = fm || IDENTITY;
const X = x.length, Y = y.length, a = [];
for(let i = 0; i <= X - Y; ++i)if (isInfixAt(x, y, i, fc, fm)) a.push(i);
return a;
}
function isInfixAt(x, y, i, fc, fm) {
const Y = y.length;
for(let j = 0; j < Y; ++j){
const wx = fm(x[i + j], i + j, x);
const wy = fm(y[j], j, y);
if (fc(wx, wy) !== 0) return false;
}
return true;
}
/**
* Find first index of a subsequence.
* @param x an array
* @param y search subsequence
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns begin index of subsequence, -1 if not found
*/ export function searchSubsequence(x, y, fc = null, fm = null) {
fc = fc || COMPARE;
fm = fm || IDENTITY;
const y1 = [
...y
].map(fm), Y = y1.length;
let a = -1, i = -1, j = 0;
for (const vx of x){
const wx = fm(vx, ++i, x);
if (fc(wx, y1[j]) !== 0) continue;
if (a < 0) a = i;
if (++j >= Y) return a;
}
return -1;
}
// #endregion
// #region RANDOM ARRANGEMENTS
// ---------------------------
/**
* Pick an arbitrary value.
* @param x an array
* @param fr random number generator ([0, 1))
* @returns x[i] | i ∈ 0..|x|
*/ export function randomValue(x, fr = Math.random) {
fr = fr || Math.random;
const i = Math.floor(fr() * x.length);
return x[i];
}
export { randomValue as value }; // DEPRECATED
/**
* Pick an arbitrary prefix.
* @param x an array
* @param n number of values [-1 ⇒ any]
* @param fr random number generator ([0, 1))
* @returns x[..i] if n<0; x[..n] otherwise | i ∈ 0..|x|
*/ export function randomPrefix(x, n = -1, fr = Math.random) {
fr = fr || Math.random;
const X = x.length;
if (n > X) return null;
n = n >= 0 ? n : Math.floor((X + 1) * fr());
return x.slice(0, n);
}
export { randomPrefix as prefix }; // DEPRECATED
/**
* Pick an arbitrary suffix.
* @param x an array
* @param n number of values [-1 ⇒ any]
* @param fr random number generator ([0, 1))
* @returns x[|x|-i..] if n<0; x[|x|-n..] otherwise | i ∈ 0..|x|
*/ export function randomSuffix(x, n = -1, fr = Math.random) {
const X = x.length;
if (n > X) return null;
n = n >= 0 ? n : Math.floor((X + 1) * fr());
return x.slice(X - n);
}
export { randomSuffix as suffix }; // DEPRECATED
/**
* Pick an arbitrary infix.
* @param x an array
* @param n number of values [-1 ⇒ any]
* @param fr random number generator ([0, 1))
* @returns x[i..j] if n<0; x[i..i+n] otherwise | i, j ∈ 0..|x|
*/ export function randomInfix(x, n = -1, fr = Math.random) {
const X = x.length;
if (n > X) return null;
n = n >= 0 ? n : randomInfixLength(X, fr());
const i = Math.floor((X + 1 - n) * fr());
return x.slice(i, i + n);
}
export { randomInfix as infix }; // DEPRECATED
// Not all infix lengths are equally proable.
function randomInfixLength(X, r) {
const C = 0.5 * X * (X + 1) + 1;
const n = 0.5 * Math.sqrt(1 + 8 * r * C) - 0.5;
return X + 1 - Math.floor(n + 1);
}
/**
* Pick an arbitrary subsequence.
* @param x an array
* @param n number of values [-1 ⇒ any]
* @param fr random number generator ([0, 1))
* @returns x[i, j, ...] | [i, j, ...] = is; |is| = |x| if n<0 else n
*/ export function randomSubsequence(x, n = -1, fr = Math.random) {
const X = x.length;
if (n > X) return null;
if (n >= 0) return randomSubsequenceFixed(x, n, fr);
else return randomSubsequenceAll(x, fr);
}
export { randomSubsequence as subsequence }; // DEPRECATED
function randomSubsequenceFixed(x, n, fr) {
const is = fromRange(0, x.length);
randomPermutation$(is, n, fr).sort();
return getAll(x, is);
}
function randomSubsequenceAll(x, fr) {
const a = [];
for (const v of x)if (fr() < 0.5) a.push(v);
return a;
}
/**
* Pick an arbitrary permutation.
* @param x an array
* @param n number of values [-1 ⇒ any]
* @param fr random number generator ([0, 1))
* @returns x' | x' = x; values are randomly shuffled
*/ export function randomPermutation(x, n = -1, fr = Math.random) {
const X = x.length;
if (n > X) return null;
return randomPermutation$(x.slice(), n, fr);
}
export { randomPermutation as permutation }; // DEPRECATED
/**
* Pick an arbitrary permutation!
* @param x an array (updated!)
* @param n number of values [-1 ⇒ any]
* @param fr random number generator ([0, 1))
* @returns x | values are randomly shuffled
*/ export function randomPermutation$(x, n = -1, fr = Math.random) {
fr = fr || Math.random;
const X = x.length;
if (n > X) return x;
n = n >= 0 ? n : Math.floor((X + 1) * fr());
for(let i = 0; i < n; ++i){
const j = i + Math.floor((X - i) * fr());
const t = x[i];
x[i] = x[j];
x[j] = t;
}
x.length = n;
return x;
}
export { randomPermutation$ as permutation$ }; // DEPRECATED
export { randomPermutation$ as permute$ };
export { randomPermutation$ as shuffle$ };
// - https://en.wikipedia.org/wiki/Fisher–Yates_shuffle
// #endregion
// #region FIND
// ------------
/**
* Find first value passing a test.
* @param x an array
* @param ft test function (v, i, x)
* @returns first v | ft(v) = true; v ∈ x
*/ export function find(x, ft) {
return x.find(ft);
}
/**
* Find last value passing a test.
* @param x an array
* @param ft test function (v, i, x)
* @returns last v | ft(v) = true; v ∈ x
*/ export function findRight(x, ft) {
for(let i = x.length - 1; i >= 0; --i)if (ft(x[i], i, x)) return x[i];
return undefined;
}
// #endregion
// #region TAKE/DROP
// -----------------
/**
* Keep first n values only.
* @param x an array
* @param n number of values [1]
* @returns x[0..n]
*/ export function take(x, n = 1) {
n = Math.max(n, 0);
return x.slice(0, n);
}
export { take as left };
/**
* Keep last n values only.
* @param x an array
* @param n number of values [1]
* @returns x[0..n]
*/ export function takeRight(x, n = 1) {
const X = x.length;
n = Math.min(Math.max(n, 0), X);
return x.slice(X - n);
}
export { takeRight as right };
/**
* Keep values from left, while a test passes.
* @param x an array
* @param ft test function (v, i, x)
* @returns x[0..T-1] | ft(x[i]) = true ∀ i ∈ [0, T-1] & ft(x[T]) = false
*/ export function takeWhile(x, ft) {
return x.slice(0, scanWhile(x, ft));
}
/**
* Keep values from right, while a test passes.
* @param x an array
* @param ft test function (v, i, x)
* @returns x[T..] | ft(x[i]) = true ∀ i ∈ [T, |x|-1] & ft(x[T-1]) = false
*/ export function takeWhileRight(x, ft) {
return x.slice(scanWhileRight(x, ft));
}
/**
* Discard first n values only.
* @param x an array
* @param n number of values [1]
* @returns x[n..]
*/ export function drop(x, n = 1) {
n = Math.max(n, 0);
return x.slice(n);
}
/**
* Discard last n values only.
* @param x an array
* @param n number of values [1]
* @returns x[0..-n]
*/ export function dropRight(x, n = 1) {
const X = x.length;
n = Math.min(Math.max(n, 0), X);
return x.slice(0, X - n);
}
/**
* Discard values from left, while a test passes.
* @param x an array
* @param ft test function (v, i, x)
* @returns x[T..] | ft(x[i]) = true ∀ i ∈ [0, T-1] & ft(x[T]) = false
*/ export function dropWhile(x, ft) {
return x.slice(scanWhile(x, ft));
}
/**
* Discard values from right, while a test passes.
* @param x an array
* @param ft test function (v, i, x)
* @returns x[0..T-1] | ft(x[i]) = true ∀ i ∈ [T, |x|-1] & ft(x[T-1]) = false
*/ export function dropWhileRight(x, ft) {
return x.slice(0, scanWhileRight(x, ft));
}
// #endregion
// #region SCAN
// ------------
/**
* Scan from left, while a test passes.
* @param x an array
* @param ft test function (v, i, x)
* @returns first index where test fails
*/ export function scanWhile(x, ft) {
let i = -1;
for (const v of x)if (!ft(v, ++i, x)) return i;
return ++i;
}
/**
* Scan from right, while a test passes.
* @param x an array
* @param ft test function (v, i, x)
* @returns first index where test passes till end
*/ export function scanWhileRight(x, ft) {
let i = x.length - 1;
for(; i >= 0; --i)if (!ft(x[i], i, x)) break;
return ++i;
}
/**
* Scan from left, until a test passes.
* @param x an array
* @param ft test function (v, i, x)
* @returns first index where test passes
*/ export function scanUntil(x, ft) {
let i = -1;
for (const v of x)if (ft(v, ++i, x)) return i;
return ++i;
}
/**
* Scan from right, until a test passes.
* @param x an array
* @param ft test function (v, i, x)
* @returns first index where test fails till end
*/ export function scanUntilRight(x, ft) {
let i = x.length - 1;
for(; i >= 0; --i)if (ft(x[i], i, x)) break;
return ++i;
}
// #endregion
// #region SEARCH
// --------------
/**
* Find first index of a value.
* @param x an array
* @param v search value
* @param i begin index [0]
* @returns index of v in x[i..] if found else -1
*/ export function indexOf(x, v, i = 0) {
return x.indexOf(v, i);
}
/**
* Find last index of a value.
* @param x an array
* @param v search value
* @param i begin index [|x|-1]
* @returns last index of v in x[0..i] if found else -1
*/ export function lastIndexOf(x, v, i = x.length - 1) {
return x.lastIndexOf(v, i);
}
/**
* Find index of first value passing a test.
* @param x an array
* @param ft test function (v, i, x)
* @returns first index of value, -1 if not found
*/ export function search(x, ft) {
return x.findIndex(ft);
}
export { search as findIndex };
/**
* Find index of last value passing a test.
* @param x an array
* @param ft test function (v, i, x)
* @returns last index of value, -1 if not found
*/ export function searchRight(x, ft) {
for(let i = x.length - 1; i >= 0; --i)if (ft(x[i], i, x)) return i;
return -1;
}
export { searchRight as findLastIndex };
/**
* Find indices of values passing a test.
* @param x an array
* @param ft test function (v, i, x)
* @returns indices of value
*/ export function searchAll(x, ft) {
let i = -1;
const a = [];
for (const v of x)if (ft(v, ++i, x)) a.push(i);
return a;
}
// #endregion
// #region FUNCTIONAL
// ------------------
/**
* Call a function for each value.
* @param x an array
* @param fp process function (v, i, x)
*/ export function forEach(x, fp) {
x.forEach(fp);
}
/**
* Examine if any value satisfies a test.
* @param x an array
* @param ft test function (v, i, x)
* @returns true if ft(vᵢ) = true for some vᵢ ∈ x
*/ export function some(x, ft = null) {
if (ft) return x.some(ft);
else return someBoolean(x);
}
export { some as anyOf };
function someBoolean(x) {
const I = x.length;
for(let i = 0; i < I; ++i)if (x[i]) return true;
return false;
}
/**
* Examine if all values satisfy a test.
* @param x an array
* @param ft test function (v, i, x)
* @returns true if ft(vᵢ) = true for all vᵢ ∈ x
*/ export function every(x, ft = null) {
if (ft) return x.every(ft);
else return everyBoolean(x);
}
export { every as allOf };
function everyBoolean(x) {
const I = x.length;
for(let i = 0; i < I; ++i)if (!x[i]) return false;
return true;
}
/**
* Transform values of an array.
* @param x an array
* @param fm map function (v, i, x)
* @returns [fm(v₀), fm(v₁), ...] | vᵢ ∈ x
*/ export function map(x, fm) {
return x.map(fm);
}
/**
* Transform values of an array!
* @param x an array (updated!)
* @param fm map function (v, i, x)
* @returns x = [fm(v₀), fm(v₁), ...]; vᵢ ∈ x
*/ export function map$(x, fm) {
const I = x.length;
for(let i = 0; i < I; ++i)x[i] = fm(x[i], i, x);
return x;
}
/**
* Reduce values of array to a single value.
* @param x an array
* @param fr reduce function (acc, v, i, 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) {
const init = arguments.length <= 2;
return init ? x.reduce(fr) : x.reduce(fr, acc);
}
/**
* Reduce values from right, to a single value.
* @param x an array
* @param fr reduce function (acc, v, i, x)
* @param acc initial value
* @returns fr(fr(acc, vₓ₋₀), vₓ₋₁)... | fr(acc, vₓ₋₀) = vₓ₋₀ if acc not given
*/ export function reduceRight(x, fr, acc) {
let init = arguments.length <= 2;
for(let i = x.length - 1; i >= 0; --i){
if (init) {
acc = x[i];
init = false;
} else acc = fr(acc, x[i], i, x);
}
return acc;
}
/**
* Keep values which pass a test.
* @param x an array
* @param ft test function (v, i, x)
* @returns [v₀, v₁, ...] | ft(vᵢ) = true; vᵢ ∈ x
*/ export function filter(x, ft) {
return x.filter(ft);
}
export { filter as findAll };
/**
* Keep values which pass a test!
* @param x an array (updated!)
* @param ft test function (v, i, x)
* @returns x = [v₀, v₁, ...] | ft(vᵢ) = true; vᵢ ∈ x
*/ export function filter$(x, ft) {
const I = x.length;
let j = 0;
for(let i = 0; i < I; ++i)if (ft(x[i], i, x)) x[j++] = x[i];
x.length = j;
return x;
}
/**
* Keep values at given indices.
* @param x an array
* @param is indices
* @returns v₀, v₁, ... | vᵢ = x[i]; i ∈ is
*/ export function filterAt(x, is) {
const X = x.length;
const a = [];
for (const i of is)if (i >= 0 && i < X) a.push(x[i]);
return a;
}
/**
* Discard values which pass a test.
* @param x an array
* @param ft test function (v, i, x)
* @returns [v₀, v₁, ...] | ft(vᵢ) = false; vᵢ ∈ x
*/ export function reject(x, ft) {
let i = -1;
const a = [];
for (const v of x)if (!ft(v, ++i, x)) a.push(v);
return a;
}
/**
* Discard values which pass a test!
* @param x an array (updated!)
* @param ft test function (v, i, x)
* @returns x = [v₀, v₁, ...] | ft(vᵢ) = false; vᵢ ∈ x
*/ export function reject$(x, ft) {
const I = x.length;
let j = 0;
for(let i = 0; i < I; ++i)if (!ft(x[i], i, x)) x[j++] = x[i];
x.length = j;
return x;
}
/**
* Discard values at given indices.
* @param x an array
* @param is indices
* @returns [v₀, v₁, ...] | vᵢ = x[i]; i ∉ is
*/ export function rejectAt(x, is) {
let i = -1;
const a = [];
for (const v of x)if (!is.includes(++i)) a.push(v);
return a;
}
// #endregion
// #region FLATTEN
// ---------------
/**
* Flatten nested array to given depth.
* @param x a nested array
* @param n maximum depth [-1 ⇒ all]
* @param fm map function (v, i, x)
* @param ft flatten test function (v, i, x) [is]
* @returns flat iterable
*/ export function flat(x, n = -1, fm = null, ft = null) {
fm = fm || IDENTITY;
ft = ft || is;
return flatTo$([], x, n, fm, ft);
}
function flatTo$(a, x, n, fm, ft) {
let i = -1;
for (const v of x){
const w = fm(v, ++i, x);
if (n !== 0 && ft(w, i, x)) flatTo$(a, v, n - 1, fm, ft);
else a.push(w);
}
return a;
}
/**
* Flatten nested array, based on map function.
* @param x an array
* @param fm map function (v, i, x)
* @param ft flatten test function (v, i, x) [is]
* @returns flat iterable
*/ export function flatMap(x, fm = null, ft = null) {
fm = fm || IDENTITY;
ft = ft || is;
let i = -1;
const a = [];
for (const v of x){
const w = fm(v, ++i, x);
if (ft(w, i, x)) concat$(a, w);
else a.push(w);
}
return a;
}
// #endregion
// #region PREFIX SUM
// ------------------
/**
* Perform exclusive prefix scan from left to right.
* @param x an array
* @param fr reduce function (acc, v, i, x)
* @param acc initial value
* @returns [acc, fr(acc, v₀), fr(fr(acc, v₀), v₁)...]
*/ export function exclusiveScan(x, fr, acc) {
const a = [];
const I = x.length;
for(let i = 0; i < I; ++i){
a.push(acc);
acc = fr(acc, x[i], i, x);
}
return a;
}
/**
* Perform exclusive prefix scan from left to right!
* @param x an array (updated!)
* @param fr reduce function (acc, v, i, x)
* @param acc initial value
* @returns x = [acc, fr(acc, v₀), fr(fr(acc, v₀), v₁)...]
*/ export function exclusiveScan$(x, fr, acc) {
const I = x.length;
for(let i = 0; i < I; ++i){
const v = x[i];
x[i] = acc;
acc = fr(acc, v, i, x);
}
return x;
}
/**
* Perform inclusive prefix scan from left to right.
* @param x an array
* @param fr reduce function (acc, v, i, x)
* @param acc initial value
* @returns [fr(acc, v₀), fr(fr(acc, v₀), v₁)...]
*/ export function inclusiveScan(x, fr, acc) {
let init = arguments.length <= 2;
const a = [];
const I = x.length;
for(let i = 0; i < I; ++i){
acc = init ? x[i] : fr(acc, x[i], i, x);
a.push(acc);
init = false;
}
return a;
}
export { inclusiveScan as accumulate };
/**
* Perform inclusive prefix scan from left to right!
* @param x an array (updated!)
* @param fr reduce function (acc, v, i, x)
* @param acc initial value
* @returns x = [fr(acc, v₀), fr(fr(acc, v₀), v₁)...]
*/ export function inclusiveScan$(x, fr, acc) {
const I = x.length;
for(let i = 0; i < I; ++i)acc = x[i] = fr(acc, x[i], i, x);
return x;
}
/**
* Combine adjacent values of an array.
* @param x an array
* @param fc combine function (u, v)
* @param acc initial value
* @returns [fc(acc, v₀), fc(v₀, v₁)...] | vᵢ ∈ x
*/ export function adjacentCombine(x, fc, acc) {
const a = [];
if (x.length > 0) a.push(fc(acc, x[0]));
const I = x.length;
for(let i = 1; i < I; ++i)a.push(fc(x[i - 1], x[i]));
return a;
}
// adjacentMap()?
/**
* Combine adjacent values of an array!
* @param x an array (updated!)
* @param fc combine function (u, v)
* @param acc initial value
* @returns x = [fc(acc, v₀), fc(v₀, v₁)...] | vᵢ ∈ x
*/ export function adjacentCombine$(x, fc, acc) {
const X = x.length;
if (X === 0) return x;
let v = x[0];
x[0] = fc(acc, v);
for(let i = 1; i < X; ++i){
const w = x[i];
x[i] = fc(v, w);
v = w;
}
return x;
}
// #endregion
// #region COMBINE
// ---------------
/**
* Place a separator between every value.
* @param x an array
* @param v separator
* @returns [x[0], v, x[1], v, ..., x[|x|-1]]
*/ export function intersperse(x, v) {
const a = [];
let i = -1;
for (const u of x){
if (++i > 0) a.push(v);
a.push(u);
}
return a;
}
/**
* Estimate new values between existing ones.
* @param x an array
* @param fc combine function (a, b)
* @returns [x[0], fc(x[0], x[1]), x[1], fc(x[1], x[2]), ..., x[|x|-1]]
*/ export function interpolate(x, fc) {
const a = [];
let u = undefined;
let i = -1;
for (const v of x){
if (++i > 0) a.push(fc(u, v));
a.push(u = v);
}
return a;
}
/**
* Place values of an array between another.
* @param x an array
* @param y another array
* @param m number of values from x [1]
* @param n number of values from y [1]
* @param s step size for x [m]
* @param t step size for y [n]
* @returns x[0..m] ⧺ y[0..n] ⧺ x[s..s+m] ⧺ y[t..t+n] ⧺ ... ⧺ x[k*s..|x|-1] | k ∈ W
*/ export function intermix(x, y, m = 1, n = 1, s = m, t = n) {
const X = x.length;
const Y = y.length;
const a = [];
m = Math.max(m, 0);
n = Math.max(n, 0);
s = Math.max(s, 1);
t = Math.max(t, 1);
for(let i = 0, j = 0; i < X; i += s){
if (i > 0) {
for(let k = j, K = k + n; k < K; ++k)a.push(y[k % Y]);
j += t;
}
concat$(a, x.slice(i, i + m));
}
return a;
}
/**
* Place values from iterables alternately.
* @param xs arrays
* @returns [x₀[0], x₁[0], ..., x₀[1], x₁[0], ...] | [x₀, x₁, ...] = xs
*/ export function interleave(xs) {
const a = [];
for(let i = 0;; ++i){
let n = 0;
for (const x of xs)if (i < x.length) {
a.push(x[i]);
++n;
}
if (n === 0) break;
}
return a;
}
/**
* Combine values from arrays.
* @param xs arrays
* @param fm map function (vs, i)
* @param fe end function (dones) [some]
* @param vd default value
* @returns [fm([x₀[0], x₁[0], ...]), fm([x₀[1], x₁[1], ...]), ...]
*/ export function zip(xs, fm = null, fe = null, vd) {
fm = fm || IDENTITY;
fe = fe || some;
const X = xs.length, a = [];
if (X === 0) return a;
const ds = new Array(X).fill(false);
const ls = xs.map((x)=>x.length);
for(let i = 0;; ++i){
const vs = [];
for(let j = 0; j < X; ++j){
ds[j] = i >= ls[j];
vs[j] = ds[j] ? vd : xs[j][i];
}
if (fe(ds)) break;
a.push(fm(vs, i, null));
}
return a;
}
// TODO: zip2()?
// #endregion
// #region MANIPULATION
// --------------------
/**
* Fill with given value.
* @param x an array
* @param v value
* @param i begin index [0]
* @param I end index [|x|]
* @returns x' | x' = x; x'[i..I] = v
*/ export function fill(x, v, i = 0, I = x.length) {
return x.slice().fill(v, i, I);
}
/**
* Fill with given value!
* @param x an array (updated!)
* @param v value
* @param i begin index [0]
* @param I end index [|x|]
* @returns x | x[i..I] = v
*/ export function fill$(x, v, i = 0, I = x.length) {
return x.fill(v, i, I);
}
/**
* Add value to the end.
* @param x an array
* @param vs values to add
* @returns x ⧺ vs
*/ export function push(x, ...vs) {
return x.concat(vs);
}
export { push as pushBack };
export { push as append };
/**
* Add values to the end!
* @param x an array (updated!)
* @param vs values to add
* @returns x = x ⧺ vs
*/ export function push$(x, ...vs) {
x.push(...vs);
return x;
}
export { push$ as pushBack$ };
export { push$ as append$ };
/**
* Remove last value.
* @param x an array
* @returns x[0..|x|-1]
*/ export function pop(x) {
return x.slice(0, -1);
}
export { pop as popBack };
/**
* Remove last value!
* @param x an array (updated!)
* @returns x = x[0..|x|-1]
*/ export function pop$(x) {
x.pop();
return x;
}
export { pop as popBack$ };
/**
* Remove first value.
* @param x an array
* @returns x[1..]
*/ export function shift(x) {
return x.slice(1);
}
export { shift as popFront };
/**
* Remove first value!
* @param x an array (updated!)
* @returns x = x[1..]
*/ export function shift$(x) {
x.shift();
return x;
}
export { shift$ as popFront$ };
/**
* Add values to the start.
* @param x an array
* @param vs values to add
* @returns vs ⧺ x
*/ export function unshift(x, ...vs) {
return concat$(vs, x);
}
export { unshift as pushFront };
export { unshift as prepend };
/**
* Add values to the start!
* @param x an array (updated!)
* @param vs values to add
* @returns x = vs ⧺ x
*/ export function unshift$(x, ...vs) {
x.unshift(...vs);
return x;
}
export { unshift$ as pushFront$ };
export { unshift$ as prepend$ };
/**
* Copy part of array to another.
* @param x target array
* @param y source array
* @param j write index [0]
* @param i read begin index [0]
* @param I read end index [|x|]
* @returns x[0..j] ⧺ y[i..I] ⧺ x[j+I-i..]
*/ export function copy(x, y, j = 0, i = 0, I = y.length) {
return copy$(x.slice(), y, j, i, I);
}
/**
* Copy part of array to another!
* @param x target array (updated!)
* @param y source array
* @param j write index [0]
* @param i read begin index [0]
* @param I read end index [|x|]
* @returns x = x[0..j] ⧺ y[i..I] ⧺ x[j+I-i..]
*/ export function copy$(x, y, j = 0, i = 0, I = y.length) {
j = index(x, j);
[i, I] = indexRange(y, i, I);
for(; i < I; ++i, ++j)x[j] = y[i];
return x;
}
/**
* Copy part of array within.
* @param x an array
* @param j write index [0]
* @param i read begin index [0]
* @param I read end index [|x|]
* @returns x[0..j] ⧺ x[i..I] ⧺ x[j+I-i..]
*/ export function copyWithin(x, j = 0, i = 0, I = x.length) {
return x.slice().copyWithin(j, i, I);
}
/**
* Copy part of array within!
* @param x an array (updated!)
* @param j write index [0]
* @param i read begin index [0]
* @param I read end index [|x|]
* @returns x = x[0..j] ⧺ x[i..I] ⧺ x[j+I-i..]
*/ export function copyWithin$(x, j = 0, i = 0, I = x.length) {
return x.copyWithin(j, i, I);
}
/**
* Move part of array within.
* @param x an array
* @param j write index [0]
* @param i read begin index [0]
* @param I read end index [|x|]
* @returns x[0..j] ⧺ x[i..I] ⧺ x[j..i] ⧺ x[I..]
*/ export function moveWithin(x, j = 0, i = 0, I = x.length) {
j = index(x, j);
[i, I] = indexRange(x, i, I);
if (j < i) return movePart(x, j, i, I);
else return movePart(x, i, I, j);
}
function movePart(x, i, j, k) {
return x.slice(0, i).concat(x.slice(j, k), x.slice(i, j), x.slice(k));
}
/**
* Move part of array within!
* @param x an array (updated!)
* @param j write ±index [0]
* @param i read begin ±index [0]
* @param I read end ±index [|x|]
* @returns x = x[0..j] ⧺ x[i..I] ⧺ x[j..i] ⧺ x[I..]
*/ export function moveWithin$(x, j = 0, i = 0, I = x.length) {
j = index(x, j);
[i, I] = indexRange(x, i, I);
const p = x.slice(i, I), P = p.length;
if (j < i) x.copyWithin(j + P, j, i);
else x.copyWithin(i, I, j);
return copy$(x, p, j < i ? j : j - P);
}
// DOUBT: Are negative indices any helpful (other than basic shortcuts)?
// DOUBT: It is not easy to use a negative index supporting function from another negative index supporting function.
// DOUBT: Seems to me they are only complicating implementation of algorithms, and should be removed.
/**
* Remove or replace existing values.
* @param x an array
* @param i remove ±index
* @param n number of values to remove [rest]
* @param vs values to insert
* @returns x[0..i] ⧺ vs ⧺ x[i+n..]
*/ export function splice(x, i, n = x.length, ...vs) {
i = index(x, i);
n = Math.max(n, 0);
return concat$(x.slice(0, i), vs, x.slice(i + n));
}
export { splice as toSpliced };
/**
* Remove or replace existing values!
* @param x an array (updated!)
* @param i remove ±index
* @param n number of values to remove [rest]
* @param vs values to insert
* @returns x = x[0..i] ⧺ vs ⧺ x[i+n..]
*/ export function splice$(x, i, n = x.length, ...vs) {
x.splice(i, n, ...vs);
return x;
}
// #endregion
// #region COUNT/PARTITION
// -----------------------
/**
* Count values which satisfy a test.
* @param x an array
* @param ft test function (v, i, x)
* @returns Σtᵢ | tᵢ = 1 if ft(vᵢ) else 0; vᵢ ∈ x
*/ export function count(x, ft) {
let i = -1, a = 0;
for (const v of x)if (ft(v, ++i, x)) ++a;
return a;
}
/**
* Count occurrences of each distinct value.
* @param x an array
* @param fm map function (v, i, x)
* @returns Map \{value ⇒ count\}
*/ export function countEach(x, fm = null) {
fm = fm || IDENTITY;
let i = -1;
const a = new Map();
for (const v of x){
const w = fm(v, ++i, x);
a.set(w, (a.get(w) || 0) + 1);
}
return a;
}
export { countEach as countAs }; // DEPRECATED
/**
* Segregate values by test result.
* @param x an array
* @param ft test function (v, i, x)
* @returns [satisfies, doesnt]
*/ export function partition(x, ft) {
const t = [], f = [];
let i = -1;
for (const v of x){
if (ft(v, ++i, x)) t.push(v);
else f.push(v);
}
return [
t,
f
];
}
/**
* Segregate each distinct value.
* @param x an array
* @param fm map function (v, i, x)
* @returns Map \{key ⇒ values\}
*/ export function partitionEach(x, fm = null) {
fm = fm || IDENTITY;
let i = -1;
const a = new Map();
for (const v of x){
const w = fm(v, ++i, x);
if (!a.has(w)) a.set(w, []);
a.get(w).push(v);
}
return a;
}
export { partitionEach as groupToMap };
export { partitionEach as partitionAs }; // DEPRECATED
// #endregion
// #region SPLITS
// --------------
/**
* Break array considering test as separator.
* @param x an array
* @param ft test function (v, i, x)
* @returns [x[j..k], x[l..m], ...] | ft(x[i]) = true; i = 0..j / k..l / ...
*/ export function split(x, ft) {
let i = -1;
const a = [];
let b = [];
for (const v of x){
if (!ft(v, ++i, x)) b.push(v);
else if (b.length) {
a.push(b);
b = [];
}
}
if (b.length) a.push(b);
return a;
}
/**
* Break array considering indices as separator.
* @param x an array
* @param is indices (sorted)
* @returns [x[j..k], x[l..m], ...] | ft(x[i]) = true; i = 0..j / k..l / ...; i ∈ is
*/ export function splitAt(x, is) {
let i = -1;
const a = [];
let b = [];
for (const v of x){
if (!is.includes(++i)) b.push(v);
else if (b.length) {
a.push(b);
b = [];
}
}
if (b.length) a.push(b);
return a;
}
/**
* Break array when test passes.
* @param x an array
* @param ft test function (v, i, x)
* @returns [x[0..j], x[j..k], ...] | ft(x[i]) = true; i = j, k, ...
*/ export function cut(x, ft) {
let j = 0;
const a = [];
const I = x.length;
for(let i = 0; i < I; ++i){
if (!ft(x[i], i, x)) continue;
a.push(x.slice(j, i));
j = i;
}
a.push(x.slice(j));
return a;
}
/**
* Break array after test passes.
* @param x an array
* @param ft test function (v, i, x)
* @returns [x[0..j+1], x[j+1..k], ...] | ft(x[i]) = true; i = j, k, ...
*/ export function cutRight(x, ft) {
let j = 0;
const a = [];
const I = x.length;
for(let i = 0; i < I; ++i){
if (!ft(x[i], i, x)) continue;
a.push(x.slice(j, i + 1));
j = i + 1;
}
a.push(x.slice(j));
return a;
}
/**
* Break array at given indices.
* @param x an array
* @param is split ±indices (left to right)
* @returns [x[0..j], x[j..k], ...] | ft(x[i]) = true; i = j, k, ...; i ∈ is
*/ export function cutAt(x, is) {
const X = x.length;
let j = 0;
const a = [];
for (let i of is){
i = i < 0 ? X + i : i;
a.push(x.slice(j, i));
j = Math.max(j, i);
}
a.push(x.slice(j));
return a;
}
/**
* Break array after given indices.
* @param x an array
* @param is split ±indices (left to right)
* @returns [x[0..j+1], x[j+1..k], ...] | ft(x[i]) = true; i = j, k, ...; i ∈ is
*/ export function cutAtRight(x, is) {
const X = x.length;
let j = 0;
const a = [];
for (let i of is){
i = i < 0 ? X + i : i;
a.push(x.slice(j, i + 1));
j = Math.max(j, i + 1);
}
a.push(x.slice(j));
return a;
}
/**
* Keep similar values together and in order.
* @param x an array
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns [x[0..k], x[k..l], ...] | fc(x[i], x[j]) = 0; i, j = 0..k / k..l / ...
*/ export function group(x, fc = null, fm = null) {
fc = fc || COMPARE;
fm = fm || IDENTITY;
const a = [];
let b = [];
let u = undefined, i = -1;
for (const v of x){
const w = fm(v, ++i, x);
if (i === 0 || fc(u, w) === 0) b.push(v);
else {
a.push(b);
b = [
v
];
}
u = w;
}
a.push(b);
return a;
}
/**
* Break array into chunks of given size.
* @param x an array
* @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 a = [];
if (n < 0) return a;
s = Math.max(s, 1);
const I = x.length;
for(let i = 0; i < I; i += s)a.push(x.slice(i, i + n));
return a;
}
// #endregion
// #region CONCAT/JOIN
// -------------------
/**
* Append values from arrays.
* @param xs arrays
* @returns x₀ ⧺ x₁ ⧺ ... | [x₀, x₁, ...] = xs
*/ export function concat(...xs) {
return [].concat(...xs);
}
/**
* Append values from arrays!
* @param x an array (updated!)
* @param ys arrays to append
* @returns x = x ⧺ y₀ ⧺ y₁ ⧺ ...] | [y₀, y₁, ...] = ys
*/ export function concat$(x, ...ys) {
for (const y of ys)x.push(...y);
return x;
}
/**
* Join values together into a string.
* @param x an array
* @param sep separator [,]
* @returns "$\{v₀\}$\{sep\}$\{v₁\}..." | vᵢ ∈ x
*/ export function join(x, sep = ",") {
return x.join(sep);
}
// #endregion
// #region REARRANGE
// -----------------
/**
* Obtain values that cycle through array.
* @param x an array
* @param i begin ±index [0]
* @param n number of values [|x|]
*/ export function cycle(x, i = 0, n = x.length) {
const X = x.length;
if (n <= 0 || X === 0) return [];
i = mod(i, X);
const a = x.slice(i, i + n);
n -= a.length;
const M = Math.floor(n / X);
for(let m = 0; m < M; ++m)concat$(a, x);
return concat$(a, x.slice(0, n % X));
}
/**
* Repeat an array given times.
* @param x an array
* @param n times [1]
* @returns x ⧺ x ⧺ ...(n times)
*/ export function repeat(x, n = 1) {
const a = [];
for(; n > 0; --n)concat$(a, x);
return a;
}
/**
* Reverse the values.
* @param x an array
* @returns [x[|x|-1], x[|x|-2], ..., x[1], x[0]]
*/ export function reverse(x) {
return x.slice().reverse();
}
export { reverse as toReversed };
/**
* Reverse the values!
* @param x an array (updated!)
* @returns x = [x[|x|-1], x[|x|-2], ..., x[1], x[0]]
*/ export function reverse$(x) {
return x.reverse();
}
/**
* Rotate values in array.
* @param x an array
* @param n rotate amount (+ve: left, -ve: right) [0]
* @returns x[n..] ⧺ x[0..n]
*/ export function rotate(x, n = 0) {
n = mod(n, x.length);
return concat$(x.slice(n), x.slice(0, n));
}
/**
* Rotate values in array!
* @param x an array (updated!)
* @param n rotate amount (+ve: left, -ve: right) [0]
* @returns x = x[n..] ⧺ x[0..n]
*/ export function rotate$(x, n = 0) {
n = mod(n, x.length);
const y = x.slice(0, n);
x.copyWithin(0, n);
return copy$(x, y, x.length - n);
}
// #endregion
// #region SET OPERATIONS
// ------------------------
/**
* Examine if there are no duplicate values.
* @param x an array
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns ∀ vᵢ, vⱼ ∈ x, is vᵢ ≠ vⱼ?
*/ export function isUnique(x, fc = null, fm = null) {
if (fc) return isUniqueDual(x, fc, fm);
else return isUniqueMap(x, fm);
}
function isUniqueMap(x, fm = null) {
fm = fm || IDENTITY;
const s = new Set();
let i = -1;
for (const v of x){
const w = fm(v, ++i, x);
if (s.has(w)) return false;
s.add(w);
}
return true;
}
function isUniqueDual(x, fc = null, fm = null) {
fc = fc || COMPARE;
fm = fm || IDENTITY;
const x1 = [
...x
].map(fm);
for (const wx of x1){
for (const wy of x1)if (fc(wx, wy) === 0) return false;
}
return true;
}
/**
* Examine if arrays have no value in common.
* @param x an array
* @param y another array
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns x ∩ y = Φ?
*/ export function isDisjoint(x, y, fc = null, fm = null) {
if (fc) return isDisjointDual(x, y, fc, fm);
else return isDisjointMap(x, y, fm);
}
function isDisjointMap(x, y, fm = null) {
fm = fm || IDENTITY;
const s = toSet(y, fm);
let i = -1;
for (const v of x){
const w = fm(v, ++i, x);
if (s.has(w)) return false;
}
return true;
}
function isDisjointDual(x, y, fc = null, fm = null) {
fc = fc || COMPARE;
fm = fm || IDENTITY;
const y1 = [
...y
].map(fm);
let i = -1;
for (const vx of x){
const wx = fm(vx, ++i, x);
for (const wy of y1)if (fc(wx, wy) === 0) return false;
}
return true;
}
/**
* Remove duplicate values.
* @param x an array
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns v₀, v₁, ... | vᵢ ∈ x; vᵢ ≠ vⱼ ∀ i, j
*/ export function unique(x, fc = null, fm = null) {
if (fc) return uniqueDual(x, fc, fm);
else return uniqueMap(x, fm);
}
function uniqueMap(x, fm = null) {
fm = fm || IDENTITY;
const s = new Set();
let i = -1;
const a = [];
for (const v of x){
const w = fm(v, ++i, x);
if (s.has(w)) continue;
s.add(w);
a.push(v);
}
return a;
}
function uniqueDual(x, fc = null, fm = null) {
fc = fc || COMPARE;
fm = fm || IDENTITY;
let i = -1;
const s = [], a = [];
x: for (const vx of x){
const wx = fm(vx, ++i, x);
for (const ws of s)if (fc(ws, wx) === 0) continue x;
s.push(wx);
a.push(vx);
}
return a;
}
/**
* Obtain values present in any array.
* @param x an array
* @param y another array
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns x ∪ y = \{v | v ∈ x or v ∈ y\}
*/ export function union(x, y, fc = null, fm = null) {
return union$(x.slice(), y, fc, fm);
}
/**
* Obtain values present in any array!
* @param x an array (updated!)
* @param y another array
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns x = x ∪ y = \{v | v ∈ x or v ∈ y\}
*/ export function union$(x, y, fc = null, fm = null) {
if (fc) return unionDual$(x, y, fc, fm);
else return unionMap$(x, y, fm);
}
function unionMap$(x, y, fm = null) {
fm = fm || IDENTITY;
const s = toSet(x, fm);
let i = -1;
for (const vy of y){
const wy = fm(vy, ++i, y);
if (!s.has(wy)) x.push(vy);
}
return x;
}
function unionDual$(x, y, fc = null, fm = null) {
fc = fc || COMPARE;
fm = fm || IDENTITY;
const x1 = x.map(fm);
let i = -1;
y: for (const vy of y){
const wy = fm(vy, ++i, y);
for (const wx of x1)if (fc(wx, wy) === 0) continue y;
x.push(vy);
}
return x;
}
/**
* Obtain values present in both arrays.
* @param x an array
* @param y another array
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns x ∩ y = \{v | v ∈ x, v ∈ y\}
*/ export function intersection(x, y, fc = null, fm = null) {
if (fc) return intersectionDual(x, y, fc, fm);
else return intersectionMap(x, y, fm);
}
function intersectionMap(x, y, fm = null) {
fm = fm || IDENTITY;
const s = toSet(y, fm);
let i = -1;
const a = [];
for (const vx of x){
const wx = fm(vx, ++i, x);
if (s.has(wx)) a.push(vx);
}
return a;
}
function intersectionDual(x, y, fc = null, fm = null) {
fc = fc || COMPARE;
fm = fm || IDENTITY;
const y1 = [
...y
].map(fm);
let i = -1;
const a = [];
x: for (const vx of x){
const wx = fm(vx, ++i, x);
for (const wy of y1)if (fc(wx, wy) === 0) {
a.push(vx);
continue x;
}
}
return a;
}
/**
* Obtain values not present in another array.
* @param x an array
* @param y another array
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns x - y = \{v | v ∈ x, v ∉ y\}
*/ export function difference(x, y, fc = null, fm = null) {
if (fc) return differenceDual(x, y, fc, fm);
else return differenceMap(x, y, fm);
}
function differenceMap(x, y, fm = null) {
fm = fm || IDENTITY;
const s = toSet(y, fm);
let i = -1;
const a = [];
for (const vx of x){
const wx = fm(vx, ++i, x);
if (!s.has(wx)) a.push(vx);
}
return a;
}
function differenceDual(x, y, fc = null, fm = null) {
fc = fc || COMPARE;
fm = fm || IDENTITY;
const y1 = [
...y
].map(fm);
let i = -1;
const a = [];
x: for (const vx of x){
const wx = fm(vx, ++i, x);
for (const wy of y1)if (fc(wx, wy) === 0) continue x;
a.push(vx);
}
return a;
}
/**
* Obtain values not present in both arrays.
* @param x an array
* @param y another array
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns x-y ∪ y-x
*/ export function symmetricDifference(x, y, fc = null, fm = null) {
const x0 = fromIterable$(x);
const y0 = fromIterable$(y);
const ax = difference(x0, y0, fc, fm);
const ay = difference(y0, x0, fc, fm);
return concat$(ax, ay);
}
/**
* Obtain cartesian product of arrays.
* @param xs arrays
* @param fm map function (vs, i)
* @returns x₀ × x₁ × ... = \{[v₀, v₁, ...] | v₀ ∈ x₀, v₁ ∈ x₁, ...] \}
*/ export function cartesianProduct(xs, fm = null) {
fm = fm || IDENTITY;
const XS = xs.length;
const a = [];
if (XS === 0) return a;
const is = new Array(XS).fill(0);
const ls = xs.map((x)=>x.length);
if (ls.some((l)=>l === 0)) return a;
for(let i = 0;; ++i){
const vs = [];
for(let j = 0; j < XS; ++j)vs.push(xs[j][is[j]]);
a.push(fm(vs, i, null));
let r = XS - 1;
for(; r >= 0; --r){
if (++is[r] < ls[r]) break;
is[r] = 0;
}
if (r < 0) break;
}
return a;
} // #endregion
// #endregion
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImZpbGU6Ly8vaG9tZS9ydW5uZXIvd29yay9leHRyYS1hcnJheS9leHRyYS1hcnJheS9pbmRleC50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge0lERU5USVRZLCBDT01QQVJFfSBmcm9tIFwiQG5vZGVmL2V4dHJhLWZ1bmN0aW9uXCI7XG5pbXBvcnQge21vZH0gZnJvbSBcIkBub2RlZi9leHRyYS1tYXRoXCI7XG5cblxuXG5cbi8vICNyZWdpb24gVFlQRVNcbi8vID09PT09PT09PT09PT1cblxuLyoqIEVudHJpZXMgaXMgYW4gYXJyYXkgb2YgaW5kZXgtdmFsdWUgcGFpcnMsIHdpdGggdW5pcXVlIGluZGljZXMuICovXG5leHBvcnQgdHlwZSBFbnRyaWVzPFQ+ID0gW251bWJlciwgVF1bXTtcbi8qKiBJRW50cmllcyBpcyBhIGxpc3Qgb2YgaW5kZXgtdmFsdWUgcGFpcnMsIHdpdGggdW5pcXVlIGluZGljZXMuICovXG5leHBvcnQgdHlwZSBJRW50cmllczxUPiA9IEl0ZXJhYmxlPFtudW1iZXIsIFRdPjtcblxuXG4vKiogTGlzdHMgaXMgYSBwYWlyIG9mIGluZGV4IGFycmF5IGFuZCB2YWx1ZSBhcnJheSwgd2l0aCB1bmlxdWUgaW5kaWNlcy4gKi9cbmV4cG9ydCB0eXBlIExpc3RzPFQ+ID0gW251bWJlcltdLCBUW11dO1xuLyoqIElMaXN0cyBpcyBhIHBhaXIgb2YgaW5kZXggaXRlcmFibGUgbGlzdCBhbmQgdmFsdWUgaXRlcmFibGUgbGlzdCwgd2l0aCB1bmlxdWUgaW5kaWNlcy4gKi9cbmV4cG9ydCB0eXBlIElMaXN0czxUPiA9IFtJdGVyYWJsZTxudW1iZXI+LCBJdGVyYWJsZTxUPl07XG5cblxuLyoqXG4gKiBIYW5kbGUgcmVhZGluZyBvZiBhIHNpbmdsZSB2YWx1ZS5cbiAqIEByZXR1cm5zIHZhbHVlXG4gKi9cbmV4cG9ydCB0eXBlIFJlYWRGdW5jdGlvbjxUPiA9ICgpID0+IFQ7XG5cblxuLyoqXG4gKiBIYW5kbGUgY29tYmluaW5nIG9mIHR3byB2YWx1ZXMuXG4gKiBAcGFyYW0gYSBhIHZhbHVlXG4gKiBAcGFyYW0gYiBhbm90aGVyIHZhbHVlXG4gKiBAcmV0dXJucyBjb21iaW5lZCB2YWx1ZVxuICovXG5leHBvcnQgdHlwZSBDb21iaW5lRnVuY3Rpb248VD4gPSAoYTogVCwgYjogVCkgPT4gVDtcblxuXG4vKipcbiAqIEhhbmRsZSBjb21wYXJpc29uIG9mIHR3byB2YWx1ZXMuXG4gKiBAcGFyYW0gYSBhIHZhbHVlXG4gKiBAcGFyYW0gYiBhbm90aGVyIHZhbHVlXG4gKiBAcmV0dXJucyBhPGI6IC12ZSwgYT1iOiAwLCBhPmI6ICt2ZVxuICovXG5leHBvcnQgdHlwZSBDb21wYXJlRnVuY3Rpb248VD4gPSAoYTogVCwgYjogVCkgPT4gbnVtYmVyO1xuXG5cbi8qKlxuICogSGFuZGxlIHByb2Nlc3Npbmcgb2YgdmFsdWVzIGluIGFuIGFycmF5LlxuICogQHBhcmFtIHYgdmFsdWUgaW4gYXJyYXlcbiAqIEBwYXJhbSBpIGluZGV4IG9mIHZhbHVlIGluIGFycmF5XG4gKiBAcGFyYW0geCBhcnJheSBjb250YWluaW5nIHRoZSB2YWx1ZVxuICovXG5leHBvcnQgdHlwZSBQcm9jZXNzRnVuY3Rpb248VD4gPSAodjogVCwgaTogbnVtYmVyLCB4OiBUW10gfCBudWxsKSA9PiB2b2lkO1xuXG5cbi8qKlxuICogSGFuZGxlIHNlbGVjdGlvbiBvZiB2YWx1ZXMgaW4gYW4gYXJyYXkuXG4gKiBAcGFyYW0gdiB2YWx1ZSBpbiBhcnJheVxuICogQHBhcmFtIGkgaW5kZXggb2YgdmFsdWUgaW4gYXJyYXlcbiAqIEBwYXJhbSB4IGFycmF5IGNvbnRhaW5pbmcgdGhlIHZhbHVlXG4gKiBAcmV0dXJucyBzZWxlY3RlZD9cbiAqL1xuZXhwb3J0IHR5cGUgVGVzdEZ1bmN0aW9uPFQ+ID0gKHY6IFQsIGk6IG51bWJlciwgeDogVFtdIHwgbnVsbCkgPT4gYm9vbGVhbjtcblxuXG4vKipcbiAqIEhhbmRsZSB0cmFuc2Zvcm1hdGlvbiBvZiBhIHZhbHVlIHRvIGFub3RoZXIuXG4gKiBAcGFyYW0gdiB2YWx1ZSBpbiBhcnJheVxuICogQHBhcmFtIGkgaW5kZXggb2YgdmFsdWUgaW4gYXJyYXlcbiAqIEBwYXJhbSB4IGFycmF5IGNvbnRhaW5pbmcgdGhlIHZhbHVlXG4gKiBAcmV0dXJucyB0cmFuc2Zvcm1lZCB2YWx1ZVxuICovXG5leHBvcnQgdHlwZSBNYXBGdW5jdGlvbjxULCBVPiA9ICh2OiBULCBpOiBudW1iZXIsIHg6IFRbXSB8IG51bGwpID0+IFU7XG5cblxuLyoqXG4gKiBIYW5kbGUgcmVkdWN0aW9uIG9mIG11bHRpcGxlIHZhbHVlcyBpbnRvIGEgc2luZ2xlIHZhbHVlLlxuICogQHBhcmFtIGFjYyBhY2N1bXVsYXRvciAodGVtcG9yYXJ5IHJlc3VsdClcbiAqIEBwYXJhbSB2IHZhbHVlIGluIGFycmF5XG4gKiBAcGFyYW0gaSBpbmRleCBvZiB2YWx1ZSBpbiBhcnJheVxuICogQHBhcmFtIHggYXJyYXkgY29udGFpbmluZyB0aGUgdmFsdWVcbiAqIEByZXR1cm5zIHJlZHVjZWQgdmFsdWVcbiAqL1xuZXhwb3J0IHR5cGUgUmVkdWNlRnVuY3Rpb248VCwgVT4gPSAoYWNjOiBVLCB2OiBULCBpOiBudW1iZXIsIHg6IFRbXSB8IG51bGwpID0+IFU7XG5cblxuLyoqXG4gKiBIYW5kbGUgZW5kaW5nIG9mIGEgY29tYmluZWQgYXJyYXkuXG4gKiBAcGFyYW0gZG9uZXMgaeG1l8qwIGFycmF5IGRvbmU/XG4gKiBAcmV0dXJucyBjb21iaW5lZCBhcnJheSBkb25lP1xuICovXG5leHBvcnQgdHlwZSBFbmRGdW5jdGlvbiA9IChkb25lczogYm9vbGVhbltdKSA9PiBib29sZWFuO1xuXG5cbi8qKlxuICogSGFuZGxlIHN3YXBwaW5nIG9mIHR3byB2YWx1ZXMgaW4gYW4gYXJyYXkuXG4gKiBAcGFyYW0geCBhbiBhcnJheSAodXBkYXRlZCEpXG4gKiBAcGFyYW0gaSBhbiBpbmRleFxuICogQHBhcmFtIGogYW5vdGhlciBpbmRleFxuICogQHJldHVybnMgeCB8IHhbaV0g4oeUIHhbal1cbiAqL1xuZXhwb3J0IHR5cGUgU3dhcEZ1bmN0aW9uPFQ+ID0gKHg6IFRbXSwgaTogbnVtYmVyLCBqOiBudW1iZXIpID0+IFRbXTtcbi8vICNlbmRyZWdpb25cblxuXG5cblxuLy8gI3JlZ2lvbiBNRVRIT0RTXG4vLyA9PT09PT09PT09PT09PT1cblxuLy8gI3JlZ2lvbiBIRUxQRVJTXG4vLyAtLS0tLS0tLS0tLS0tLS1cblxuLyoqIENvbnZlcnQgYW4gaXRlcmFibGUgdG8gc2V0LiAqL1xuZnVuY3Rpb24gdG9TZXQ8VCwgVT1UPih4OiBUW10sIGZtOiBNYXBGdW5jdGlvbjxULCBVPiB8IG51bGw9bnVsbCk6IFNldDxUfFU+IHtcbiAgaWYgKCFmbSkgcmV0dXJuIG5ldyBTZXQoeCk7XG4gIGNvbnN0IGEgPSBuZXcgU2V0PFU+KCk7IGxldCBpID0gLTE7XG4gIGZvciAoY29uc3QgdiBvZiB4KVxuICAgIGEuYWRkKGZtKHYsICsraSwgeCkpO1xuICByZXR1cm4gYTtcbn1cbi8vICNlbmRyZWdpb25cblxuXG5cblxuLy8gI3JlZ2lvbiBHRU5FUkFURVxuLy8gLS0tLS0tLS0tLS0tLS0tLVxuXG4vKipcbiAqIEdlbmVyYXRlIGFycmF5IGZyb20gZ2l2ZW4gbnVtYmVyIHJhbmdlLlxuICogQHBhcmFtIHYgc3RhcnQgbnVtYmVyXG4gKiBAcGFyYW0gViBlbmQgbnVtYmVyLCBleGNsdWRpbmdcbiAqIEBwYXJhbSBkdiBzdGVwIHNpemUgWzFdXG4gKiBAcmV0dXJucyBbdiwgditkdiwgdisyZHYsIC4uLl1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGZyb21SYW5nZSh2OiBudW1iZXIsIFY6IG51bWJlciwgZHY6IG51bWJlcj0xKTogbnVtYmVyW10ge1xuICBjb25zdCBuID0gKFYgLSB2KS9kdiwgYSA9IFtdO1xuICBmb3IgKGxldCBpPTA7IGk8bjsgKytpLCB2Kz1kdilcbiAgICBhLnB1c2godik7XG4gIHJldHVybiBhO1xufVxuXG5cbi8qKlxuICogR2VuZXJhdGUgYXJyYXkgZnJvbSByZXBlYXRlZCBmdW5jdGlvbiBpbnZvY2F0aW9uLlxuICogQHBhcmFtIGZuIGZ1bmN0aW9uXG4gKiBAcGFyYW0gbiBudW1iZXIgb2YgdmFsdWVzXG4gKiBAcmV0dXJucyBbZm4oKSwgZm4oKSwgLi4uXVxuICovXG5leHBvcnQgZnVuY3Rpb24gZnJvbUludm9jYXRpb248VD4oZm46ICgpID0+IFQsIG46IG51bWJlcik6IFRbXSB7XG4gIGNvbnN0IGEgPSBbXTtcbiAgZm9yIChsZXQgaT0wOyBpPG47ICsraSlcbiAgICBhLnB1c2goZm4oKSk7XG4gIHJldHVybiBhO1xufVxuZXhwb3J0IHtmcm9tSW52b2NhdGlvbiBhcyBmcm9tQ2FsbH07XG5cblxuLyoqXG4gKiBHZW5lcmF0ZSBhcnJheSBmcm9tIHJlcGVhdGVkIGZ1bmN0aW9uIGFwcGxpY2F0aW9uLlxuICogQHBhcmFtIGZtIG1hcCBmdW5jdGlvbiAodiwgaSlcbiAqIEBwYXJhbSB2IHN0YXJ0IHZhbHVlXG4gKiBAcGFyYW0gbiBudW1iZXIgb2YgdmFsdWVzXG4gKiBAcmV0dXJucyBbdiwgZm0odiksIGZtKGZtKHYpKSwgLi4uXVxuICovXG5leHBvcnQgZnVuY3Rpb24gZnJvbUFwcGxpY2F0aW9uPFQ+KGZtOiBNYXBGdW5jdGlvbjxULCBUPiwgdjogVCwgbjogbnVtYmVyKTogVFtdIHtcbiAgY29uc3QgYSA9IFtdO1xuICBpZiAobiE9PTApIGEucHVzaCh2KTtcbiAgZm9yIChsZXQgaT0xOyBpIT09bjsgKytpKVxuICAgIGEucHVzaCh2ID0gZm0odiwgaSwgbnVsbCkpO1xuICByZXR1cm4gYTtcbn1cbmV4cG9ydCB7ZnJvbUFwcGxpY2F0aW9uIGFzIGZyb21BcHBseX07XG5cblxuLyoqXG4gKiBDb252ZXJ0IGFuIGl0ZXJhYmxlIHRvIGFycmF5LlxuICogQHBhcmFtIHggYW4gaXRlcmFibGVcbiAqIEByZXR1cm5zIHggYXMgYXJyYXlcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGZyb21JdGVyYWJsZTxUPih4OiBJdGVyYWJsZTxUPik6IFRbXSB7XG4gIHJldHVybiBbLi4ueF07XG59XG5leHBvcnQge2Zyb21JdGVyYWJsZSBhcyBmcm9tfTtcblxuXG4vKipcbiAqIENvbnZlcnQgYW4gaXRlcmFibGUgdG8gYXJyYXkhXG4gKiBAcGFyYW0geCBhbiBpdGVyYWJsZSAodXBkYXRhYmxlIGlmIGFycmF5ISlcbiAqIEByZXR1cm5zIHggYXMgYXJyYXlcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGZyb21JdGVyYWJsZSQ8VD4oeDogSXRlcmFibGU8VD4pOiBUW10ge1xuICByZXR1cm4gQXJyYXkuaXNBcnJheSh4KT8geCA6IFsuLi54XTtcbn1cbmV4cG9ydCB7ZnJvbUl0ZXJhYmxlJCBhcyBmcm9tJH07XG4vLyAjZW5kcmVnaW9uXG5cblxuXG5cbi8vICNyZWdpb24gQ0xPTkVcbi8vIC0tLS0tLS0tLS0tLS1cblxuLyoqXG4gKiBTaGFsbG93IGNsb25lIGFuIGFycmF5LlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEByZXR1cm5zIHNoYWxsb3cgY2xvbmUgb2YgeFxuICovXG5leHBvcnQgZnVuY3Rpb24gc2hhbGxvd0Nsb25lPFQ+KHg6IFRbXSk6IFRbXSB7XG4gIHJldHVybiB4LnNsaWNlKCk7XG59XG5leHBvcnQge3NoYWxsb3dDbG9uZSBhcyBjbG9uZX07XG5cblxuLyoqXG4gKiBEZWVwIGNsb25lIGFuIGFycmF5LlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEByZXR1cm5zIGRlZXAgY2xvbmUgb2YgeFxuICovXG5leHBvcnQgZnVuY3Rpb24gZGVlcENsb25lPFQ+KHg6IFRbXSk6IFRbXSB7XG4gIHJldHVybiBzdHJ1Y3R1cmVkQ2xvbmUoeCk7XG59XG4vLyAjZW5kcmVnaW9uXG5cblxuXG5cbi8vICNyZWdpb24gQUJPVVRcbi8vIC0tLS0tLS0tLS0tLS1cblxuLyoqXG4gKiBDaGVjayBpZiB2YWx1ZSBpcyBhbiBhcnJheS5cbiAqIEBwYXJhbSB2IGEgdmFsdWVcbiAqIEByZXR1cm5zIHYgaXMgYW4gYXJyYXk/XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpcyh2OiB1bmtub3duKTogdiBpcyB1bmtub3duW10ge1xuICByZXR1cm4gQXJyYXkuaXNBcnJheSh2KTtcbn1cblxuXG4vKipcbiAqIE9idGFpbiBhbGwgaW5kaWNlcy5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcmV0dXJucyBbMCwgMSwgLi4uLCB8eHwtMV1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGtleXM8VD4oeDogVFtdKTogbnVtYmVyW10ge1xuICByZXR1cm4gWy4uLngua2V5cygpXTtcbn1cblxuXG4vKipcbiAqIExpc3QgYWxsIGluZGljZXMuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHJldHVybnMgMCwgMSwgLi4uLCB8eHwtMVxuICovXG5leHBvcnQgZnVuY3Rpb24gaWtleXM8VD4oeDogVFtdKTogSXRlcmFibGVJdGVyYXRvcjxudW1iZXI+IHtcbiAgcmV0dXJuIHgua2V5cygpO1xufVxuXG5cbi8qKlxuICogR2V0IGFsbCB2YWx1ZXMuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHJldHVybnMgW3bigoAsIHbigoEsIC4uLl0gfCB24bWiID0geFtpXVxuICovXG5leHBvcnQgZnVuY3Rpb24gdmFsdWVzPFQ+KHg6IFRbXSk6IFRbXSB7XG4gIHJldHVybiB4LnNsaWNlKCk7XG59XG5cblxuLyoqXG4gKiBMaXN0IGFsbCB2YWx1ZXMuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHJldHVybnMgduKCgCwgduKCgSwgLi4uIHwgduG1oiA9IHhbaV1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGl2YWx1ZXM8VD4oeDogVFtdKTogSXRlcmFibGVJdGVyYXRvcjxUPiB7XG4gIHJldHVybiB4LnZhbHVlcygpO1xufVxuXG5cbi8qKlxuICogT2J0YWluIGFsbCBpbmRleC12YWx1ZSBwYWlycy5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcmV0dXJucyBbWzAsIHbigoBdLCBbMSwgduKCgV0sIC4uLl0gfCB24bWiID0geFtpXVxuICovXG5leHBvcnQgZnVuY3Rpb24gZW50cmllczxUPih4OiBUW10pOiBFbnRyaWVzPFQ+IHtcbiAgcmV0dXJuIFsuLi54LmVudHJpZXMoKV07XG59XG5cblxuLyoqXG4gKiBMaXN0IGFsbCBpbmRleC12YWx1ZSBwYWlycy5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcmV0dXJucyBbMCwgduKCgF0sIFsxLCB24oKBXSwgLi4uIHwgduG1oiA9IHhbaV1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGllbnRyaWVzPFQ+KHg6IFRbXSk6IElFbnRyaWVzPFQ+IHtcbiAgcmV0dXJuIHguZW50cmllcygpO1xufVxuLy8gI2VuZHJlZ2lvblxuXG5cblxuXG4vLyAjcmVnaW9uIElOREVYXG4vLyAtLS0tLS0tLS0tLS0tXG5cbi8qKlxuICogR2V0IHplcm8tYmFzZWQgaW5kZXggZm9yIGFuIGVsZW1lbnQgaW4gYXJyYXkuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIGkgwrFpbmRleFxuICogQHJldHVybnMgaScgfCB4W2knXSA9IHhbaV07IGknIOKIiCBbMCwgfHh8XVxuICovXG5leHBvcnQgZnVuY3Rpb24gaW5kZXg8VD4oeDogVFtdLCBpOiBudW1iZXIpOiBudW1iZXIge1xuICBjb25zdCBYID0geC5sZW5ndGg7XG4gIHJldHVybiBpPj0wPyBNYXRoLm1pbihpLCBYKSA6IE1hdGgubWF4KFgraSwgMCk7XG59XG5cblxuLyoqXG4gKiBHZXQgemVyby1iYXNlZCBpbmRleCByYW5nZSBmb3IgcGFydCBvZiBhcnJheS5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gaSBiZWdpbiDCsWluZGV4IFswXVxuICogQHBhcmFtIEkgZW5kIMKxaW5kZXggKGV4Y2x1c2l2ZSkgW3x4fF1cbiAqIEByZXR1cm5zIFtpJywgSSddIHwgaScg4omkIEknOyBpJywgSScg4oiIIFswLCB8eHxdXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpbmRleFJhbmdlPFQ+KHg6IFRbXSwgaTogbnVtYmVyPTAsIEk6IG51bWJlcj14Lmxlbmd0aCk6IFtudW1iZXIsIG51bWJlcl0ge1xuICBjb25zdCBYID0geC5sZW5ndGg7XG4gIGkgPSBpPj0wPyBNYXRoLm1pbihpLCBYKSA6IE1hdGgubWF4KFgraSwgMCk7XG4gIEkgPSBJPj0wPyBNYXRoLm1pbihJLCBYKSA6IE1hdGgubWF4KFgrSSwgMCk7XG4gIHJldHVybiBbaSwgTWF0aC5tYXgoaSwgSSldO1xufVxuLy8gI2VuZHJlZ2lvblxuXG5cblxuXG4vLyAjcmVnaW9uIExFTkdUSFxuLy8gLS0tLS0tLS0tLS0tLS1cblxuLyoqXG4gKiBDaGVjayBpZiBhbiBhcnJheSBpcyBlbXB0eS5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcmV0dXJucyB8eHwgPSAwP1xuICovXG5leHBvcnQgZnVuY3Rpb24gaXNFbXB0eTxUPih4OiBUW10pOiBib29sZWFuIHtcbiAgcmV0dXJuIHgubGVuZ3RoPT09MDtcbn1cblxuXG4vKipcbiAqIEZpbmQgdGhlIGxlbmd0aCBvZiBhbiBhcnJheS5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gaSBiZWdpbiDCsWluZGV4IFswXVxuICogQHBhcmFtIEkgZW5kIMKxaW5kZXggKGV4Y2x1c2l2ZSkgW1hdXG4gKiBAcmV0dXJucyB8eFtpLi5JXXxcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGxlbmd0aDxUPih4OiBUW10sIGk6IG51bWJlcj0wLCBJOiBudW1iZXI9eC5sZW5ndGgpOiBudW1iZXIge1xuICBbaSwgSV0gPSBpbmRleFJhbmdlKHgsIGksIEkpO1xuICByZXR1cm4gSS1pO1xufVxuZXhwb3J0IHtsZW5ndGggYXMgc2l6ZX07XG5cblxuLyoqXG4gKiBSZXNpemUgYW4gYXJyYXkgdG8gZ2l2ZW4gbGVuZ3RoIVxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSBuIG5ldyBsZW5ndGhcbiAqIEBwYXJhbSB2ZCBkZWZhdWx0IHZhbHVlXG4gKiBAcmV0dXJucyByZXNpemVkIHhcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlc2l6ZSQ8VD4oeDogVFtdLCBuOiBudW1iZXIsIHZkOiBUKTogVFtdIHtcbiAgY29uc3QgWCA9IHgubGVuZ3RoOyB4Lmxlbmd0aCA9IG47XG4gIGlmIChuPlgpIHguZmlsbCh2ZCwgWCk7XG4gIHJldHVybiB4O1xufVxuXG5cbi8qKlxuICogUmVtb3ZlIGFsbCBlbGVtZW50cyBmcm9tIGFuIGFycmF5IVxuICogQHBhcmFtIHggYW4gYXJyYXkgKHVwZGF0ZWQhKVxuICogQHJldHVybnMgY2xlYXJlZCB4XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjbGVhciQ8VD4oeDogVFtdKTogVFtdIHtcbiAgeC5sZW5ndGggPSAwO1xuICByZXR1cm4geDtcbn1cbi8vICNlbmRyZWdpb25cblxuXG5cblxuLy8gI3JlZ2lvbiBHRVQvU0VUXG4vLyAtLS0tLS0tLS0tLS0tLS1cblxuLyoqXG4gKiBHZXQgdmFsdWUgYXQgaW5kZXguXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIGkgaW5kZXhcbiAqIEByZXR1cm5zIHhbaV1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldDxUPih4OiBUW10sIGk6IG51bWJlcik6IFQge1xuICByZXR1cm4geFtpbmRleCh4LCBpKV07XG59XG5leHBvcnQge2dldCBhcyBhdH07XG5cblxuLy8gR2V0IHZhbHVlcyBhdCBpbmRleCByYW5nZS5cbi8vIGV4cG9ydCB7c2xpY2UgYXMgZ2V0UmFuZ2V9O1xuXG5cbi8qKlxuICogR2V0IHZhbHVlcyBhdCBpbmRpY2VzLlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSBpcyBpbmRpY2VzXG4gKiBAcmV0dXJucyBbeFtp4oKAXSwgeFtp4oKBXSwgLi4uXSB8IFtp4oKALCBp4oKBLCAuLi5dID0gaXNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldEFsbDxUPih4OiBUW10sIGlzOiBudW1iZXJbXSk6IFRbXSB7XG4gIHJldHVybiBpcy5tYXAoaSA9PiBnZXQoeCwgaSkpO1xufVxuXG5cbi8qKlxuICogR2V0IHZhbHVlIGF0IHBhdGggaW4gYSBuZXN0ZWQgYXJyYXkuXG4gKiBAcGFyYW0geCBhIG5lc3RlZCBhcnJheVxuICogQHBhcmFtIHAgcGF0aFxuICogQHJldHVybnMgeFtp4oKAXVtp4oKBXVsuLi5dIHwgW2nigoAsIGnigoEsIC4uLl0gPSBwXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRQYXRoKHg6IHVua25vd25bXSwgcDogbnVtYmVyW10pOiB1bmtub3duIHtcbiAgbGV0IGE6IHVua25vd24gfCB1bmRlZmluZWQgPSB4O1xuICBmb3IgKGNvbnN0IGkgb2YgcClcbiAgICBhID0gaXMoYSk/IGdldChhLCBpKSA6IHVuZGVmaW5lZDtcbiAgcmV0dXJuIGE7XG59XG5cblxuLyoqXG4gKiBDaGVjayBpZiBuZXN0ZWQgYXJyYXkgaGFzIGEgcGF0aC5cbiAqIEBwYXJhbSB4IGEgbmVzdGVkIGFycmF5XG4gKiBAcGFyYW0gcCBwYXRoXG4gKiBAcmV0dXJucyB4W2nigoBdW2nigoFdWy4uLl0gZXhpc3RzPyB8IFtp4oKALCBp4oKBLCAuLi5dID0gcFxuICovXG5leHBvcnQgZnVuY3Rpb24gaGFzUGF0aCh4OiB1bmtub3duW10sIHA6IG51bWJlcltdKTogYm9vbGVhbiB7XG4gIGxldCBhOiB1bmtub3duIHwgdW5kZWZpbmVkID0geDtcbiAgZm9yIChjb25zdCBpIG9mIHApIHtcbiAgICBpZiAoIWlzKGEpKSByZXR1cm4gZmFsc2U7XG4gICAgYSA9IGdldChhLCBpKTtcbiAgfVxuICByZXR1cm4gdHJ1ZTtcbn1cblxuXG4vKipcbiAqIFNldCB2YWx1ZSBhdCBpbmRleC5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gaSBpbmRleFxuICogQHBhcmFtIHYgdmFsdWVcbiAqIEByZXR1cm5zIHgnIHwgeCcgPSB4OyB4J1tpXSA9IHZcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNldDxUPih4OiBUW10sIGk6IG51bWJlciwgdjogVCk6IFRbXSB7XG4gIHJldHVybiBzZXQkKHguc2xpY2UoKSwgaSwgdik7XG59XG5leHBvcnQge3NldCBhcyB3aXRofTtcblxuXG4vKipcbiAqIFNldCB2YWx1ZSBhdCBpbmRleCFcbiAqIEBwYXJhbSB4IGFuIGFycmF5ICh1cGRhdGVkISlcbiAqIEBwYXJhbSBpIGluZGV4XG4gKiBAcGFyYW0gdiB2YWx1ZVxuICogQHJldHVybnMgeCB8IHhbaV0gPSB2XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzZXQkPFQ+KHg6IFRbXSwgaTogbnVtYmVyLCB2OiBUKTogVFtdIHtcbiAgeFtpbmRleCh4LCBpKV0gPSB2O1xuICByZXR1cm4geDtcbn1cblxuXG4vLyBUT0RPOiBzZXRSYW5nZSQoKVxuLy8gVE9ETzogc2V0QWxsJCgpXG5cblxuLyoqXG4gKiBTZXQgdmFsdWUgYXQgcGF0aCBpbiBhIG5lc3RlZCBhcnJheSFcbiAqIEBwYXJhbSB4IGEgbmVzdGVkIGFycmF5ICh1cGRhdGVkISlcbiAqIEBwYXJhbSBwIHBhdGhcbiAqIEBwYXJhbSB2IHZhbHVlXG4gKiBAcmV0dXJucyB4IHwgeFtp4oKAXVtp4oKBXVsuLi5dID0gdjsgW2nigoAsIGnigoEsIC4uLl0gPSBwXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzZXRQYXRoJCh4OiB1bmtub3duW10sIHA6IG51bWJlcltdLCB2OiB1bmtub3duKTogdW5rbm93bltdIHtcbiAgY29uc3QgeSA9IGdldFBhdGgoeCwgcC5zbGljZSgwLCAtMSkpO1xuICBpZiAoaXMoeSkpIHNldCQoeSwgbGFzdChwKSBhcyBudW1iZXIsIHYpO1xuICByZXR1cm4geDtcbn1cblxuXG4vKipcbiAqIEV4Y2hhbmdlIHR3byB2YWx1ZXMuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIGkgYW4gaW5kZXhcbiAqIEBwYXJhbSBqIGFub3RoZXIgaW5kZXhcbiAqIEByZXR1cm5zIHgnIHwgeCcgPSB4OyB4J1tpXSA9IHhbal07IHgnW2pdID0geFtpXVxuICovXG5leHBvcnQgZnVuY3Rpb24gc3dhcDxUPih4OiBUW10sIGk6IG51bWJlciwgajogbnVtYmVyKTogVFtdIHtcbiAgcmV0dXJuIHN3YXAkKHguc2xpY2UoKSwgaSwgaik7XG59XG5cblxuLyoqXG4gKiBFeGNoYW5nZSB0d28gdmFsdWVzIVxuICogQHBhcmFtIHggYW4gYXJyYXkgKHVwZGF0ZWQhKVxuICogQHBhcmFtIGkgYW4gaW5kZXhcbiAqIEBwYXJhbSBqIGFub3RoZXIgaW5kZXhcbiAqIEByZXR1cm5zIHggfCB4W2ldIOKHlCB4W2pdXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzd2FwJDxUPih4OiBUW10sIGk6IG51bWJlciwgajogbnVtYmVyKTogVFtdIHtcbiAgaSA9IGluZGV4KHgsIGkpOyBqID0gaW5kZXgoeCwgaik7XG4gIGNvbnN0IHQgPSB4W2ldOyB4W2ldID0geFtqXTsgeFtqXSA9IHQ7XG4gIHJldHVybiB4O1xufVxuXG5cbi8qKlxuICogRXhjaGFuZ2UgdHdvIHZhbHVlcyFcbiAqIEBwYXJhbSB4IGFuIGFycmF5ICh1cGRhdGVkISlcbiAqIEBwYXJhbSBpIGFuICt2ZSBpbmRleFxuICogQHBhcmFtIGogYW5vdGhlciArdmUgaW5kZXhcbiAqIEByZXR1cm5zIHggfCB4W2ldIOKHlCB4W2pdXG4gKi9cbmZ1bmN0aW9uIHN3YXBSYXckPFQ+KHg6IFRbXSwgaTogbnVtYmVyLCBqOiBudW1iZXIpOiBUW10ge1xuICBjb25zdCB0ID0geFtpXTsgeFtpXSA9IHhbal07IHhbal0gPSB0O1xuICByZXR1cm4geDtcbn1cbi8vIE5PVEU6IE1heSBhbHNvIGJlIGNhbGxlZCBzd2FwVW5jaGVja2VkJCgpLlxuXG5cbi8qKlxuICogRXhjaGFuZ2UgdHdvIHJhbmdlcyBvZiB2YWx1ZXMuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIGkgYmVnaW4gaW5kZXggb2YgZmlyc3QgcmFuZ2VcbiAqIEBwYXJhbSBJIGVuZCBpbmRleCBvZiBmaXJzdCByYW5nZSAoZXhjbHVzaXZlKVxuICogQHBhcmFtIGogYmVnaW4gaW5kZXggb2Ygc2Vjb25kIHJhbmdlXG4gKiBAcGFyYW0gSiBlbmQgaW5kZXggb2Ygc2Vjb25kIHJhbmdlIChleGNsdXNpdmUpXG4gKiBAcmV0dXJucyB4JyB8IHgnID0geDsgeCdbaS4uSV0gPSB4W2ouLkpdOyB4J1tqLi5KXSA9IHhbaS4uSV1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHN3YXBSYW5nZXM8VD4oeDogVFtdLCBpOiBudW1iZXIsIEk6IG51bWJlciwgajogbnVtYmVyLCBKOiBudW1iZXIpOiBUW10ge1xuICBbaSwgSV0gPSBpbmRleFJhbmdlKHgsIGksIEkpO1xuICBbaiwgSl0gPSBpbmRleFJhbmdlKHgsIGosIEopO1xuICBpZiAoajxpKSBbaSwgSSwgaiwgSl0gPSBbaiwgSiwgaSwgSV07XG4gIGlmIChqPEkpIHJldHVybiB4LnNsaWNlKCk7ICAvLyBTa2lwIGlmIHJhbmdlcyBvdmVybGFwIVxuICByZXR1cm4geC5zbGljZSgwLCBpKS5jb25jYXQoeC5zbGljZShqLCBKKSwgeC5zbGljZShpLCBqKSwgeC5zbGljZShJKSk7XG59XG5cblxuLyoqXG4gKiBFeGNoYW5nZSB0d28gcmFuZ2VzIG9mIHZhbHVlcyFcbiAqIEBwYXJhbSB4IGFuIGFycmF5ICh1cGRhdGVkISlcbiAqIEBwYXJhbSBpIGJlZ2luIGluZGV4IG9mIGZpcnN0IHJhbmdlXG4gKiBAcGFyYW0gSSBlbmQgaW5kZXggb2YgZmlyc3QgcmFuZ2UgKGV4Y2x1c2l2ZSlcbiAqIEBwYXJhbSBqIGJlZ2luIGluZGV4IG9mIHNlY29uZCByYW5nZVxuICogQHBhcmFtIEogZW5kIGluZGV4IG9mIHNlY29uZCByYW5nZSAoZXhjbHVzaXZlKVxuICogQHJldHVybnMgeCB8IHhbaS4uSV0g4oeUIHhbai4uSl1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHN3YXBSYW5nZXMkPFQ+KHg6IFRbXSwgaTogbnVtYmVyLCBJOiBudW1iZXIsIGo6IG51bWJlciwgSjogbnVtYmVyKTogVFtdIHtcbiAgW2ksIEldID0gaW5kZXhSYW5nZSh4LCBpLCBJKTtcbiAgW2osIEpdID0gaW5kZXhSYW5nZSh4LCBqLCBKKTtcbiAgaWYgKGo8aSkgW2ksIEksIGosIEpdID0gW2osIEosIGksIEldO1xuICBpZiAoajxJKSByZXR1cm4geDsgIC8vIFNraXAgaWYgcmFuZ2VzIG92ZXJsYXAhXG4gIGNvbnN0IHQgPSB4LnNsaWNlKGksIEkpO1xuICB4LnNwbGljZShpLCBJLWksIC4uLnguc2xpY2UoaiwgSikpO1xuICB4LnNwbGljZShqLCBKLWosIC4uLnQpO1xuICByZXR1cm4geDtcbn1cbi8vIFRPRE86IHN3YXBBbGwkKClcblxuXG4vKipcbiAqIFJlbW92ZSB2YWx1ZSBhdCBpbmRleC5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gaSBpbmRleFxuICogQHJldHVybnMgeFswLi5pXSDip7ogeFtpKzEuLl1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlbW92ZTxUPih4OiBUW10sIGk6IG51bWJlcik6IFRbXSB7XG4gIGkgPSBpbmRleCh4LCBpKTtcbiAgcmV0dXJuIHguc2xpY2UoMCwgaSkuY29uY2F0KHguc2xpY2UoaSsxKSk7XG59XG5cblxuLyoqXG4gKiBSZW1vdmUgdmFsdWUgYXQgaW5kZXghXG4gKiBAcGFyYW0geCBhbiBhcnJheSAodXBkYXRlZCEpXG4gKiBAcGFyYW0gaSBpbmRleFxuICogQHJldHVybnMgeCBcXFxcOiBbaV1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlbW92ZSQ8VD4oeDogVFtdLCBpOiBudW1iZXIpOiBUW10ge1xuICB4LnNwbGljZShpLCAxKTtcbiAgcmV0dXJuIHg7XG59XG5cblxuLyoqXG4gKiBSZW1vdmUgdmFsdWUgYXQgcGF0aCBpbiBhIG5lc3RlZCBhcnJheSFcbiAqIEBwYXJhbSB4IGEgbmVzdGVkIGFycmF5ICh1cGRhdGVkISlcbiAqIEBwYXJhbSBwIHBhdGhcbiAqIEByZXR1cm5zIHggXFxcXDogW2nigoBdW2nigoFdWy4uLl0gfCBbaeKCgCwgaeKCgSwgLi4uXSA9IHBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlbW92ZVBhdGgkKHg6IHVua25vd25bXSwgcDogbnVtYmVyW10pOiB1bmtub3duW10ge1xuICBjb25zdCB5ID0gZ2V0UGF0aCh4LCBwLnNsaWNlKDAsIC0xKSk7XG4gIGlmIChpcyh5KSkgeS5zcGxpY2UobGFzdChwKSBhcyBudW1iZXIsIDEpO1xuICByZXR1cm4geDtcbn1cbi8vICNlbmRyZWdpb25cblxuXG5cblxuLy8gI3JlZ2lvbiBTT1JUXG4vLyAtLS0tLS0tLS0tLS1cblxuLyoqXG4gKiBFeGFtaW5lIGlmIGFycmF5IGlzIHNvcnRlZC5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gZmMgY29tcGFyZSBmdW5jdGlvbiAoYSwgYilcbiAqIEBwYXJhbSBmbSBtYXAgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcmV0dXJucyB4IGlzIHNvcnRlZD9cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzU29ydGVkPFQsIFU9VD4oeDogVFtdLCBmYzogQ29tcGFyZUZ1bmN0aW9uPFR8VT4gfCBudWxsPW51bGwsIGZtOiBNYXBGdW5jdGlvbjxULCBUfFU+IHwgbnVsbD1udWxsKTogYm9vbGVhbiB7XG4gIHJldHVybiBzZWFyY2hVbnNvcnRlZFZhbHVlKHgsIGZjLCBmbSkgPT09IC0xO1xufVxuXG5cbi8qKlxuICogRXhhbWluZSBpZiBhcnJheSBoYXMgYW4gdW5zb3J0ZWQgdmFsdWUuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIGZjIGNvbXBhcmUgZnVuY3Rpb24gKGEsIGIpXG4gKiBAcGFyYW0gZm0gbWFwIGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHJldHVybnMgeCBpcyBub3Qgc29ydGVkP1xuICovXG5leHBvcnQgZnVuY3Rpb24gaGFzVW5zb3J0ZWRWYWx1ZTxULCBVPVQ+KHg6IFRbXSwgZmM6IENvbXBhcmVGdW5jdGlvbjxUfFU+IHwgbnVsbD1udWxsLCBmbTogTWFwRnVuY3Rpb248VCwgVHxVPiB8IG51bGw9bnVsbCk6IGJvb2xlYW4ge1xuICByZXR1cm4gc2VhcmNoVW5zb3J0ZWRWYWx1ZSh4LCBmYywgZm0pID49IDA7XG59XG5cblxuLyoqXG4gKiBGaW5kIGZpcnN0IGluZGV4IG9mIGFuIHVuc29ydGVkIHZhbHVlLlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSBmYyBjb21wYXJlIGZ1bmN0aW9uIChhLCBiKVxuICogQHBhcmFtIGZtIG1hcCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEByZXR1cm5zIGluZGV4IG9mIGZpcnN0IHVuc29ydGVkIHZhbHVlLCAtMSBpZiBzb3J0ZWRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNlYXJjaFVuc29ydGVkVmFsdWU8VCwgVT1UPih4OiBUW10sIGZjOiBDb21wYXJlRnVuY3Rpb248VHxVPiB8IG51bGw9bnVsbCwgZm06IE1hcEZ1bmN0aW9uPFQsIFR8VT4gfCBudWxsPW51bGwpOiBudW1iZXIge1xuICBmYyA9IGZjIHx8IENPTVBBUkU7XG4gIGZtID0gZm0gfHwgSURFTlRJVFk7XG4gIGNvbnN0IFggID0geC5sZW5ndGg7XG4gIGlmIChYPD0xKSByZXR1cm4gLTE7XG4gIGxldCB3MCA9IGZtKHhbMF0sIDAsIHgpO1xuICBmb3IgKGxldCBpPTE7IGk8WDsgKytpKSB7XG4gICAgY29uc3QgdyA9IGZtKHhbaV0sIGksIHgpO1xuICAgIGlmIChmYyh3MCwgdyk+MCkgcmV0dXJuIGk7XG4gICAgdzAgPSB3O1xuICB9XG4gIHJldHVybiAtMTtcbn1cblxuXG4vKipcbiAqIEFycmFuZ2UgdmFsdWVzIGluIG9yZGVyLlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSBmYyBjb21wYXJlIGZ1bmN0aW9uIChhLCBiKVxuICogQHBhcmFtIGZtIG1hcCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEBwYXJhbSBmcyBzd2FwIGZ1bmN0aW9uICh4LCBpLCBqKVxuICogQHJldHVybnMgeCcgfCB4JyA9IHg7IHgnW2ldIOKJpCB4J1tqXSDiiIAgaSDiiaQgalxuICovXG5leHBvcnQgZnVuY3Rpb24gc29ydDxULCBVPVQ+KHg6IFRbXSwgZmM6IENvbXBhcmVGdW5jdGlvbjxUfFU+IHwgbnVsbD1udWxsLCBmbTogTWFwRnVuY3Rpb248VCwgVHxVPiB8IG51bGw9bnVsbCwgZnM6IFN3YXBGdW5jdGlvbjxUPiB8IG51bGw9bnVsbCk6IFRbXSB7XG4gIHJldHVybiBzb3J0JCh4LnNsaWNlKCksIGZjLCBmbSwgZnMpO1xufVxuZXhwb3J0IHtzb3J0IGFzIHRvU29ydGVkfTtcblxuXG4vKipcbiAqIEFycmFuZ2UgdmFsdWVzIGluIG9yZGVyIVxuICogQHBhcmFtIHggYW4gYXJyYXkgKHVwZGF0ZWQhKVxuICogQHBhcmFtIGZjIGNvbXBhcmUgZnVuY3Rpb24gKGEsIGIpXG4gKiBAcGFyYW0gZm0gbWFwIGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHBhcmFtIGZzIHN3YXAgZnVuY3Rpb24gKHgsIGksIGopXG4gKiBAcmV0dXJucyB4IHwgeFtpXSDiiaQgeFtqXSDiiIAgaSDiiaQgalxuICovXG5leHBvcnQgZnVuY3Rpb24gc29ydCQ8VCwgVT1UPih4OiBUW10sIGZjOiBDb21wYXJlRnVuY3Rpb248VHxVPiB8IG51bGw9bnVsbCwgZm06IE1hcEZ1bmN0aW9uPFQsIFR8VT4gfCBudWxsPW51bGwsIGZzOiBTd2FwRnVuY3Rpb248VD4gfCBudWxsPW51bGwpOiBUW10ge1xuICBmYyA9IGZjIHx8IENPTVBBUkU7XG4gIGlmICghZm0gJiYgIWZzKSByZXR1cm4geC5zb3J0KGZjKTtcbiAgY29uc3QgWCAgPSB4Lmxlbmd0aDtcbiAgZm0gPSBmbSB8fCBJREVOVElUWTtcbiAgZnMgPSBmcyB8fCBzd2FwUmF3JDtcbiAgcmV0dXJuIHJhbmdlZFBhcnRpYWxJbnRyb1NvcnQkKHgsIDAsIFgsIFgsIGZjLCBmbSwgZnMpO1xufVxuXG5cbi8qKlxuICogQXJyYW5nZSBhIHJhbmdlIG9mIHZhbHVlcyBpbiBvcmRlci5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gaSBiZWdpbiBpbmRleFxuICogQHBhcmFtIEkgZW5kIGluZGV4IChleGNsdXNpdmUpXG4gKiBAcGFyYW0gZmMgY29tcGFyZSBmdW5jdGlvbiAoYSwgYilcbiAqIEBwYXJhbSBmbSBtYXAgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcGFyYW0gZnMgc3dhcCBmdW5jdGlvbiAoeCwgaSwgailcbiAqIEByZXR1cm5zIHgnIHwgeCcgPSB4OyB4J1tpXSDiiaQgeCdbal0g4oiAIGkg4omkIGpcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJhbmdlZFNvcnQ8VCwgVT1UPih4OiBUW10sIGk6IG51bWJlciwgSTogbnVtYmVyLCBmYzogQ29tcGFyZUZ1bmN0aW9uPFR8VT4gfCBudWxsPW51bGwsIGZtOiBNYXBGdW5jdGlvbjxULCBUfFU+IHwgbnVsbD1udWxsLCBmczogU3dhcEZ1bmN0aW9uPFQ+IHwgbnVsbD1udWxsKTogVFtdIHtcbiAgcmV0dXJuIHJhbmdlZFNvcnQkKHguc2xpY2UoKSwgaSwgSSwgZmMsIGZtLCBmcyk7XG59XG5cblxuLyoqXG4gKiBBcnJhbmdlIGEgcmFuZ2Ugb2YgdmFsdWVzIGluIG9yZGVyIVxuICogQHBhcmFtIHggYW4gYXJyYXkgKHVwZGF0ZWQhKVxuICogQHBhcmFtIGkgYmVnaW4gaW5kZXhcbiAqIEBwYXJhbSBJIGVuZCBpbmRleCAoZXhjbHVzaXZlKVxuICogQHBhcmFtIGZjIGNvbXBhcmUgZnVuY3Rpb24gKGEsIGIpXG4gKiBAcGFyYW0gZm0gbWFwIGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHBhcmFtIGZzIHN3YXAgZnVuY3Rpb24gKHgsIGksIGopXG4gKiBAcmV0dXJucyB4IHwgeFtpXSDiiaQgeFtqXSDiiIAgaSDiiaQgalxuICovXG5leHBvcnQgZnVuY3Rpb24gcmFuZ2VkU29ydCQ8VCwgVT1UPih4OiBUW10sIGk6IG51bWJlciwgSTogbnVtYmVyLCBmYzogQ29tcGFyZUZ1bmN0aW9uPFR8VT4gfCBudWxsPW51bGwsIGZtOiBNYXBGdW5jdGlvbjxULCBUfFU+IHwgbnVsbD1udWxsLCBmczogU3dhcEZ1bmN0aW9uPFQ+IHwgbnVsbD1udWxsKTogVFtdIHtcbiAgZmMgPSBmYyB8fCBDT01QQVJFO1xuICBmbSA9IGZtIHx8IElERU5USVRZO1xuICBmcyA9IGZzIHx8IHN3YXBSYXckO1xuICBbaSwgSV0gPSBpbmRleFJhbmdlKHgsIGksIEkpO1xuICByZXR1cm4gcmFuZ2VkUGFydGlhbEludHJvU29ydCQoeCwgaSwgSSwgSS1pLCBmYywgZm0sIGZzKTtcbn1cblxuXG4vKipcbiAqIFBhcnRpYWxseSBhcnJhbmdlIHZhbHVlcyBpbiBvcmRlci5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gbiBtaW5pbXVtIG51bWJlciBvZiB2YWx1ZXMgdG8gc29ydFxuICogQHBhcmFtIGZjIGNvbXBhcmUgZnVuY3Rpb24gKGEsIGIpXG4gKiBAcGFyYW0gZm0gbWFwIGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHBhcmFtIGZzIHN3YXAgZnVuY3Rpb24gKHgsIGksIGopXG4gKiBAcmV0dXJucyB4JyB8IHgnID0geDsgeCdbaV0g4omkIHgnW2pdIOKIgCBpIOKJpCBqXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwYXJ0aWFsU29ydDxULCBVPVQ+KHg6IFRbXSwgbjogbnVtYmVyLCBmYzogQ29tcGFyZUZ1bmN0aW9uPFR8VT4gfCBudWxsPW51bGwsIGZtOiBNYXBGdW5jdGlvbjxULCBUfFU+IHwgbnVsbD1udWxsLCBmczogU3dhcEZ1bmN0aW9uPFQ+IHwgbnVsbD1udWxsKTogVFtdIHtcbiAgcmV0dXJuIHBhcnRpYWxTb3J0JCh4LnNsaWNlKCksIG4sIGZjLCBmbSwgZnMpO1xufVxuXG5cbi8qKlxuICogUGFydGlhbGx5IGFycmFuZ2UgdmFsdWVzIGluIG9yZGVyIVxuICogQHBhcmFtIHggYW4gYXJyYXkgKHVwZGF0ZWQhKVxuICogQHBhcmFtIG4gbWluaW11bSBudW1iZXIgb2YgdmFsdWVzIHRvIHNvcnRcbiAqIEBwYXJhbSBmYyBjb21wYXJlIGZ1bmN0aW9uIChhLCBiKVxuICogQHBhcmFtIGZtIG1hcCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEBwYXJhbSBmcyBzd2FwIGZ1bmN0aW9uICh4LCBpLCBqKVxuICogQHJldHVybnMgeCB8IHhbaV0g4omkIHhbal0g4oiAIGkg4omkIGpcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHBhcnRpYWxTb3J0JDxULCBVPVQ+KHg6IFRbXSwgbjogbnVtYmVyLCBmYzogQ29tcGFyZUZ1bmN0aW9uPFR8VT4gfCBudWxsPW51bGwsIGZtOiBNYXBGdW5jdGlvbjxULCBUfFU+IHwgbnVsbD1udWxsLCBmczogU3dhcEZ1bmN0aW9uPFQ+IHwgbnVsbD1udWxsKTogVFtdIHtcbiAgcmV0dXJuIHJhbmdlZFBhcnRpYWxTb3J0JCh4LCAwLCB4Lmxlbmd0aCwgbiwgZmMsIGZtLCBmcyk7XG59XG5cblxuLyoqXG4gKiBQYXJ0aWFsbHkgYXJyYW5nZSBhIHJhbmdlIG9mIHZhbHVlcyBpbiBvcmRlci5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gaSBiZWdpbiBpbmRleFxuICogQHBhcmFtIEkgZW5kIGluZGV4IChleGNsdXNpdmUpXG4gKiBAcGFyYW0gbiBtaW5pbXVtIG51bWJlciBvZiB2YWx1ZXMgdG8gc29ydFxuICogQHBhcmFtIGZjIGNvbXBhcmUgZnVuY3Rpb24gKGEsIGIpXG4gKiBAcGFyYW0gZm0gbWFwIGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHBhcmFtIGZzIHN3YXAgZnVuY3Rpb24gKHgsIGksIGopXG4gKiBAcmV0dXJucyB4JyB8IHgnID0geDsgeCdbaV0g4omkIHgnW2pdIOKIgCBpIOKJpCBqXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByYW5nZWRQYXJ0aWFsU29ydDxULCBVPVQ+KHg6IFRbXSwgaTogbnVtYmVyLCBJOiBudW1iZXIsIG46IG51bWJlciwgZmM6IENvbXBhcmVGdW5jdGlvbjxUfFU+IHwgbnVsbD1udWxsLCBmbTogTWFwRnVuY3Rpb248VCwgVHxVPiB8IG51bGw9bnVsbCwgZnM6IFN3YXBGdW5jdGlvbjxUPiB8IG51bGw9bnVsbCk6IFRbXSB7XG4gIHJldHVybiByYW5nZWRQYXJ0aWFsU29ydCQoeC5zbGljZSgpLCBpLCBJLCBuLCBmYywgZm0sIGZzKTtcbn1cblxuXG4vKipcbiAqIFBhcnRpYWxseSBhcnJhbmdlIGEgcmFuZ2Ugb2YgdmFsdWVzIGluIG9yZGVyIVxuICogQHBhcmFtIHggYW4gYXJyYXkgKHVwZGF0ZWQhKVxuICogQHBhcmFtIGkgYmVnaW4gaW5kZXhcbiAqIEBwYXJhbSBJIGVuZCBpbmRleCAoZXhjbHVzaXZlKVxuICogQHBhcmFtIG4gbWluaW11bSBudW1iZXIgb2YgdmFsdWVzIHRvIHNvcnRcbiAqIEBwYXJhbSBmYyBjb21wYXJlIGZ1bmN0aW9uIChhLCBiKVxuICogQHBhcmFtIGZtIG1hcCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEBwYXJhbSBmcyBzd2FwIGZ1bmN0aW9uICh4LCBpLCBqKVxuICogQHJldHVybnMgeCB8IHhbaV0g4omkIHhbal0g4oiAIGkg4omkIGpcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJhbmdlZFBhcnRpYWxTb3J0JDxULCBVPVQ+KHg6IFRbXSwgaTogbnVtYmVyLCBJOiBudW1iZXIsIG46IG51bWJlciwgZmM6IENvbXBhcmVGdW5jdGlvbjxUfFU+IHwgbnVsbD1udWxsLCBmbTogTWFwRnVuY3Rpb248VCwgVHxVPiB8IG51bGw9bnVsbCwgZnM6IFN3YXBGdW5jdGlvbjxUPiB8IG51bGw9bnVsbCk6IFRbXSB7XG4gIGZjID0gZmMgfHwgQ09NUEFSRTtcbiAgZm0gPSBmbSB8fCBJREVOVElUWTtcbiAgZnMgPSBmcyB8fCBzd2FwUmF3JDtcbiAgW2ksIEldID0gaW5kZXhSYW5nZSh4LCBpLCBJKTtcbiAgcmV0dXJuIHJhbmdlZFBhcnRpYWxJbnRyb1NvcnQkKHgsIGksIEksIG4sIGZjLCBmbSwgZnMpO1xufVxuXG5cbi8qKlxuICogUGFydGlhbGx5IGFycmFuZ2UgdmFsdWVzIGluIG9yZGVyIVxuICogQHBhcmFtIHggYW4gYXJyYXkgKHVwZGF0ZWQhKVxuICogQHBhcmFtIGkgYmVnaW4gaW5kZXhcbiAqIEBwYXJhbSBJIGVuZCBpbmRleCAoZXhjbHVzaXZlKVxuICogQHBhcmFtIG4gbWluaW11bSBudW1iZXIgb2YgdmFsdWVzIHRvIHNvcnRcbiAqIEBwYXJhbSBmYyBjb21wYXJlIGZ1bmN0aW9uIChhLCBiKVxuICogQHBhcmFtIGZtIG1hcCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEBwYXJhbSBmcyBzd2FwIGZ1bmN0aW9uICh4LCBpLCBqKVxuICogQHJldHVybnMgeCB8IHhbaV0g4omkIHhbal0g4oiAIGkg4omkIGpcbiAqL1xuZnVuY3Rpb24gcmFuZ2VkUGFydGlhbEludHJvU29ydCQ8VCwgVT1UPih4OiBUW10sIGk6IG51bWJlciwgSTogbnVtYmVyLCBuOiBudW1iZXIsIGZjOiBDb21wYXJlRnVuY3Rpb248VHxVPiwgZm06IE1hcEZ1bmN0aW9uPFQsIFR8VT4sIGZzOiBTd2FwRnVuY3Rpb248VD4pOiBUW10ge1xuICBjb25zdCBkID0gTWF0aC5mbG9vcihNYXRoLmxvZzIoSS1pKSoyKTsgIC8vIE1heGltdW0gZGVwdGggb2YgcmVjdXJzaW9uXG4gIGNvbnN0IHMgPSAxNjsgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2hlbiB0byBzd2l0Y2ggdG8gaW5zZXJ0aW9uIHNvcnRcbiAgcmV0dXJuIHJhbmdlZFBhcnRpYWxJbnRyb1NvcnREbyQoeCwgaSwgSSwgZCwgcywgbiwgZmMsIGZtLCBmcyk7XG59XG5cblxuLy8gUGFydGlhbGx5IGFycmFuZ2UgYSByYW5nZSBvZiB2YWx1ZXMgaW4gb3JkZXIgd2l0aCBoeWJyaWQgcXVpY2sgc29ydCwgaGVhcCBzb3J0LCBhbmQgaW5zZXJ0aW9uIHNvcnQuXG5mdW5jdGlvbiByYW5nZWRQYXJ0aWFsSW50cm9Tb3J0RG8kPFQsIFU9VD4oeDogVFtdLCBpOiBudW1iZXIsIEk6IG51bWJlciwgZDogbnVtYmVyLCBzOiBudW1iZXIsIG46IG51bWJlciwgZmM6IENvbXBhcmVGdW5jdGlvbjxUfFU+LCBmbTogTWFwRnVuY3Rpb248VCwgVHxVPiwgZnM6IFN3YXBGdW5jdGlvbjxUPik6IFRbXSB7XG4gIGlmIChuPD0wIHx8IEktaTw9MSkgcmV0dXJuIHg7ICAgICAgICAgICAgICAgICAgICAgLy8gTm90aGluZyB0byBzb3J0XG4gIGlmIChJLWk8PXMpIHJldHVybiByYW5nZWRQYXJ0aWFsSW5zZXJ0aW9uU29ydCQoeCwgaSwgSSwgbiwgZmMsIGZtLCBmcyk7ICAvLyBJbnNlcnRpb24gc29ydFxuICBpZiAoZDw9MCkgICByZXR1cm4gcmFuZ2VkUGFydGlhbEhlYXBTb3J0JCh4LCBpLCBJLCBuLCBmYywgZm0sIGZzKTsgICAgICAgLy8gSGVhcCBzb3J0XG4gIGxldCBwID0gaSArIE1hdGguZmxvb3IoKEktaSkqTWF0aC5yYW5kb20oKSk7ICAgICAgICAgICAgLy8gQ2hvb3NlIHBpdm90XG4gIHAgPSByYW5nZWRRdWlja1NvcnRQYXJ0aXRpb24kKHgsIGksIEksIHAsIGZjLCBmbSwgZnMpOyAgLy8gUGFydGl0aW9uIGFycmF5XG4gIHJhbmdlZFBhcnRpYWxJbnRyb1NvcnREbyQoeCwgaSwgICBwLCBkLCBzLCBNYXRoLm1pbihwLWksIG4pLCAgIGZjLCBmbSwgZnMpOyAgLy8gU29ydCBsZWZ0IHBhcnRcbiAgcmFuZ2VkUGFydGlhbEludHJvU29ydERvJCh4LCBwKzEsIEksIGQsIHMsIE1hdGgubWluKEktcC0xLCBuKSwgZmMsIGZtLCBmcyk7ICAvLyBTb3J0IHJpZ2h0IHBhcnRcbiAgcmV0dXJuIHg7XG59XG5cblxuLyoqXG4gKiBQYXJ0aWFsbHkgYXJyYW5nZSBhIHJhbmdlIG9mIHZhbHVlcyBpbiBvcmRlciFcbiAqIEBwYXJhbSB4IGFuIGFycmF5ICh1cGRhdGVkISlcbiAqIEBwYXJhbSBpIGJlZ2luIGluZGV4XG4gKiBAcGFyYW0gSSBlbmQgaW5kZXggKGV4Y2x1c2l2ZSlcbiAqIEBwYXJhbSBuIG1pbmltdW0gbnVtYmVyIG9mIHZhbHVlcyB0byBzb3J0XG4gKiBAcGFyYW0gZmMgY29tcGFyZSBmdW5jdGlvbiAoYSwgYilcbiAqIEBwYXJhbSBmbSBtYXAgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcGFyYW0gZnMgc3dhcCBmdW5jdGlvbiAoeCwgaSwgailcbiAqIEByZXR1cm5zIHggfCB4W2ldIOKJpCB4W2pdIOKIgCBpIOKJpCBqXG4gKi9cbmZ1bmN0aW9uIF9yYW5nZWRQYXJ0aWFsUXVpY2tTb3J0JDxULCBVPVQ+KHg6IFRbXSwgaTogbnVtYmVyLCBJOiBudW1iZXIsIG46IG51bWJlciwgZmM6IENvbXBhcmVGdW5jdGlvbjxUfFU+LCBmbTogTWFwRnVuY3Rpb248VCwgVHxVPiwgZnM6IFN3YXBGdW5jdGlvbjxUPik6IFRbXSB7XG4gIGlmIChuPD0wIHx8IEktaTw9MSkgcmV0dXJuIHg7ICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE5vdGhpbmcgdG8gc29ydFxuICBsZXQgcCA9IGkgKyBNYXRoLmZsb29yKChJLWkpKk1hdGgucmFuZG9tKCkpOyAgICAgICAgICAgIC8vIENob29zZSBwaXZvdFxuICBwID0gcmFuZ2VkUXVpY2tTb3J0UGFydGl0aW9uJCh4LCBpLCBJLCBwLCBmYywgZm0sIGZzKTsgIC8vIFBhcnRpdGlvbiBhcnJheVxuICBfcmFuZ2VkUGFydGlhbFF1aWNrU29ydCQoeCwgaSwgICBwLCBNYXRoLm1pbihwLWksIG4pLCAgIGZjLCBmbSwgZnMpOyAgLy8gU29ydCBsZWZ0IHBhcnRcbiAgX3JhbmdlZFBhcnRpYWxRdWlja1NvcnQkKHgsIHArMSwgSSwgTWF0aC5taW4oSS1wLTEsIG4pLCBmYywgZm0sIGZzKTsgIC8vIFNvcnQgcmlnaHQgcGFydFxuICByZXR1cm4geDtcbn1cblxuXG4vLyBUT0RPOiBNYWtlIHRoaXMgYSBnZW5lcmljIGZ1bmN0aW9uLlxuLy8gUGFydGl0aW9uIHRoZSBhcnJheSBpbnRvIHR3byBwYXJ0cywgc3VjaCB0aGF0IHZhbHVlcyBpbiB0aGUgZmlyc3QgcGFydCBhcmUgbGVzcyB0aGFuIHZhbHVlcyBpbiB0aGUgc2Vjb25kIHBhcnQuXG5mdW5jdGlvbiByYW5nZWRRdWlja1NvcnRQYXJ0aXRpb24kPFQsIFU9VD4oeDogVFtdLCBpOiBudW1iZXIsIEk6IG51bWJlciwgcDogbnVtYmVyLCBmYzogQ29tcGFyZUZ1bmN0aW9uPFR8VT4sIGZtOiBNYXBGdW5jdGlvbjxULCBUfFU+LCBmczogU3dhcEZ1bmN0aW9uPFQ+KTogbnVtYmVyIHtcbiAgY29uc3Qgd3AgPSBmbSh4W3BdLCBwLCB4KTsgIC8vIFBpdm90IHZhbHVlXG4gIGxldCBqICA9IGktMTsgICAvLyBMYXN0IGluZGV4IG9mIHZhbHVlcyDiiaQgcGl2b3RcbiAgZnMoeCwgcCwgSS0xKTsgIC8vIE1vdmUgcGl2b3QgdG8gZW5kXG4gIGZvciAobGV0IGs9aTsgazxJLTE7ICsraykge1xuICAgIGNvbnN0IHdrID0gZm0oeFtrXSwgaywgeCk7XG4gICAgaWYgKGZjKHdrLCB3cCkgPiAwKSBjb250aW51ZTtcbiAgICBmcyh4LCArK2osIGspOyAgLy8gTW92ZSB2YWx1ZSDiiaQgcGl2b3QgdG8gbGVmdFxuICB9XG4gIGZzKHgsICsraiwgSS0xKTsgIC8vIE1vdmUgcGl2b3QgdG8gbWlkZGxlXG4gIHJldHVybiBqOyAgLy8gUmV0dXJuIHBpdm90IGluZGV4XG59XG5cblxuLyoqXG4gKiBQYXJ0aWFsbHkgYXJyYW5nZSBhIHJhbmdlIG9mIHZhbHVlcyBpbiBvcmRlciFcbiAqIEBwYXJhbSB4IGFuIGFycmF5ICh1cGRhdGVkISlcbiAqIEBwYXJhbSBpIGJlZ2luIGluZGV4XG4gKiBAcGFyYW0gSSBlbmQgaW5kZXggKGV4Y2x1c2l2ZSlcbiAqIEBwYXJhbSBuIG1pbmltdW0gbnVtYmVyIG9mIHZhbHVlcyB0byBzb3J0XG4gKiBAcGFyYW0gZmMgY29tcGFyZSBmdW5jdGlvbiAoYSwgYilcbiAqIEBwYXJhbSBmbSBtYXAgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcGFyYW0gZnMgc3dhcCBmdW5jdGlvbiAoeCwgaSwgailcbiAqIEByZXR1cm5zIHggfCB4W2ldIOKJpCB4W2pdIOKIgCBpIOKJpCBqXG4gKi9cbmZ1bmN0aW9uIHJhbmdlZFBhcnRpYWxIZWFwU29ydCQ8VCwgVT1UPih4OiBUW10sIGk6IG51bWJlciwgSTogbnVtYmVyLCBuOiBudW1iZXIsIGZjOiBDb21wYXJlRnVuY3Rpb248VHxVPiwgZm06IE1hcEZ1bmN0aW9uPFQsIFR8VT4sIGZzOiBTd2FwRnVuY3Rpb248VD4pOiBUW10ge1xuICByYW5nZWRCdWlsZFJldmVyc2VNaW5IZWFwJCh4LCBpLCBJLCBmYywgZm0sIGZzKTtcbiAgZm9yIChjb25zdCByPUktMTsgbj4wICYmIGk8STsgKytpLCAtLW4pIHtcbiAgICBmcyh4LCBpLCByKTsgIC8vIE1vdmUgcm9vdCB0byB0aGUgYmVnaW5uaW5nXG4gICAgcmFuZ2VkUmV2ZXJzZU1pbkhlYXBpZnkkKHgsIGkrMSwgSSwgciwgZmMsIGZtLCBmcyk7ICAvLyBSZWJ1aWxkIGhlYXBcbiAgfVxuICByZXR1cm4geDtcbn1cblxuXG4vLyBCdWlsZCBhIHJldmVyc2UgbWluLWhlYXAgZnJvbSBhIHJhbmdlIG9mIHZhbHVlcywgd2hlcmUgcm9vdCBub2RlIGlzIHRoZSBzbWFsbGVzdCBhbmQgcGxhY2VkIGF0IHRoZSBlbmQuXG5mdW5jdGlvbiByYW5nZWRCdWlsZFJldmVyc2VNaW5IZWFwJDxULCBVPVQ+KHg6IFRbXSwgaTogbnVtYmVyLCBJOiBudW1iZXIsIGZjOiBDb21wYXJlRnVuY3Rpb248VHxVPiwgZm06IE1hcEZ1bmN0aW9uPFQsIFR8VT4sIGZzOiBTd2FwRnVuY3Rpb248VD4pOiB2b2lkIHtcbiAgZm9yIChsZXQgcj1JLU1hdGguZmxvb3IoKEktaSkvMik7IHI8STsgKytyKSAgLy8gUmV2ZXJzZSBvZiByID0gWC8yLTEgLi4gMFxuICAgIHJhbmdlZFJldmVyc2VNaW5IZWFwaWZ5JCh4LCBpLCBJLCByLCBmYywgZm0sIGZzKTtcbn1cblxuXG4vKipcbiAqIFJldmVyc2UgbWluLWhlYXBpZnkgYSByYW5nZSBvZiB2YWx1ZXMsIHN1Y2ggdGhhdCByb290IG5vZGUgaXMgdGhlIHNtYWxsZXN0IGFuZCBwbGFjZWQgYXQgdGhlIGVuZC5cbiAqIEBwYXJhbSB4IGFuIGFycmF5ICh1cGRhdGVkISlcbiAqIEBwYXJhbSBpIGJlZ2luIGluZGV4XG4gKiBAcGFyYW0gSSBlbmQgaW5kZXggKGV4Y2x1c2l2ZSlcbiAqIEBwYXJhbSByIHJvb3QgaW5kZXhcbiAqIEBwYXJhbSBmYyBjb21wYXJlIGZ1bmN0aW9uIChhLCBiKVxuICogQHBhcmFtIGZtIG1hcCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEBwYXJhbSBmcyBzd2FwIGZ1bmN0aW9uICh4LCBpLCBqKVxuICovXG5mdW5jdGlvbiByYW5nZWRSZXZlcnNlTWluSGVhcGlmeSQ8VCwgVT1UPih4OiBUW10sIGk6IG51bWJlciwgSTogbnVtYmVyLCByOiBudW1iZXIsIGZjOiBDb21wYXJlRnVuY3Rpb248VHxVPiwgZm06IE1hcEZ1bmN0aW9uPFQsIFR8VT4sIGZzOiBTd2FwRnVuY3Rpb248VD4pOiB2b2lkIHtcbiAgbGV0IHMgID0gcjsgICAgICAgICAvLyBJbmRleCBvZiBzbWFsbGVzdCB2YWx1ZVxuICBjb25zdCBsdCA9IDIqciAtIEk7ICAgLy8gTGVmdCBjaGlsZCwgIHJldmVyc2Ugb2YgbHQgPSAyKnIrMVxuICBjb25zdCBydCA9IGx0ICAtIDE7ICAgLy8gUmlnaHQgY2hpbGQsIHJldmVyc2Ugb2YgcnQgPSAyKnIrMlxuICBpZiAobHQ+PWkgJiYgZmMoZm0oeFtsdF0sIGx0LCB4KSwgZm0oeFtzXSwgcywgeCkpIDwgMCkgcyA9IGx0OyAgLy8gTGVmdCBjaGlsZCBpcyBzbWFsbGVyP1xuICBpZiAocnQ+PWkgJiYgZmMoZm0oeFtydF0sIHJ0LCB4KSwgZm0oeFtzXSwgcywgeCkpIDwgMCkgcyA9IHJ0OyAgLy8gUmlnaHQgY2hpbGQgaXMgc21hbGxlcj9cbiAgaWYgKHMgIT09IHIpIHsgICAgIC8vIFNtYWxsZXN0IGlzIG5vdCByb290P1xuICAgIGZzKHgsIHMsIHIpOyAgICAgLy8gU3dhcCByb290IHdpdGggc21hbGxlc3RcbiAgICByYW5nZWRSZXZlcnNlTWluSGVhcGlmeSQoeCwgaSwgSSwgcywgZmMsIGZtLCBmcyk7ICAvLyBSZWJ1aWxkIGhlYXBcbiAgfVxufVxuXG5cbi8vIEJ1aWxkIGEgbWF4LWhlYXAgZnJvbSBhIHJhbmdlIG9mIHZhbHVlcywgd2hlcmUgcm9vdCBub2RlIGlzIHRoZSBzbWFsbGVzdCBhbmQgcGxhY2VkIGF0IHRoZSBiZWdpbm5pbmcuXG5mdW5jdGlvbiByYW5nZWRCdWlsZE1heEhlYXAkPFQsIFU9VD4oeDogVFtdLCBpOiBudW1iZXIsIEk6IG51bWJlciwgZmM6IENvbXBhcmVGdW5jdGlvbjxUfFU+LCBmbTogTWFwRnVuY3Rpb248VCwgVHxVPiwgZnM6IFN3YXBGdW5jdGlvbjxUPik6IHZvaWQge1xuICBmb3IgKGxldCByPWkrTWF0aC5mbG9vcigoSS1pKS8yKS0xOyByPj1pOyAtLXIpXG4gICAgcmFuZ2VkTWF4SGVhcGlmeSQoeCwgaSwgSSwgciwgZmMsIGZtLCBmcyk7XG59XG5cblxuLyoqXG4gKiBNYXgtaGVhcGlmeSBhIHJhbmdlIG9mIHZhbHVlcywgc3VjaCB0aGF0IHJvb3Qgbm9kZSBpcyB0aGUgbGFyZ2VzdCBhbmQgcGxhY2VkIGF0IHRoZSBiZWdpbm5pbmcuXG4gKiBAcGFyYW0geCBhbiBhcnJheSAodXBkYXRlZCEpXG4gKiBAcGFyYW0gaSBiZWdpbiBpbmRleFxuICogQHBhcmFtIEkgZW5kIGluZGV4IChleGNsdXNpdmUpXG4gKiBAcGFyYW0gciByb290IGluZGV4XG4gKiBAcGFyYW0gZmMgY29tcGFyZSBmdW5jdGlvbiAoYSwgYilcbiAqIEBwYXJhbSBmbSBtYXAgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcGFyYW0gZnMgc3dhcCBmdW5jdGlvbiAoeCwgaSwgailcbiAqL1xuZnVuY3Rpb24gcmFuZ2VkTWF4SGVhcGlmeSQ8VCwgVT1UPih4OiBUW10sIGk6IG51bWJlciwgSTogbnVtYmVyLCByOiBudW1iZXIsIGZjOiBDb21wYXJlRnVuY3Rpb248VHxVPiwgZm06IE1hcEZ1bmN0aW9uPFQsIFR8VT4sIGZzOiBTd2FwRnVuY3Rpb248VD4pOiB2b2lkIHtcbiAgbGV0IHMgID0gcjsgICAgICAgICAvLyBJbmRleCBvZiBsYXJnZXN0IHZhbHVlXG4gIGNvbnN0IGx0ID0gMipyIC0gaSArIDE7ICAvLyBMZWZ0IGNoaWxkLCAgbGlrZSBsdCA9IDIqcisxXG4gIGNvbnN0IHJ0ID0gbHQgICsgMTsgICAgICAvLyBSaWdodCBjaGlsZCwgbGlrZSBydCA9IDIqcisyXG4gIGlmIChsdDxJICYmIGZjKGZtKHhbbHRdLCBsdCwgeCksIGZtKHhbc10sIHMsIHgpKSA+IDApIHMgPSBsdDsgIC8vIExlZnQgY2hpbGQgIGlzIGxhcmdlcj9cbiAgaWYgKHJ0PEkgJiYgZmMoZm0oeFtydF0sIHJ0LCB4KSwgZm0oeFtzXSwgcywgeCkpID4gMCkgcyA9IHJ0OyAgLy8gUmlnaHQgY2hpbGQgaXMgbGFyZ2VyP1xuICBpZiAocyAhPT0gcikgeyAgICAgLy8gTGFyZ2VzdCBpcyBub3Qgcm9vdD9cbiAgICBmcyh4LCBzLCByKTsgICAgIC8vIFN3YXAgcm9vdCB3aXRoIGxhcmdlc3RcbiAgICByYW5nZWRNYXhIZWFwaWZ5JCh4LCBpLCBJLCBzLCBmYywgZm0sIGZzKTsgIC8vIFJlYnVpbGQgaGVhcFxuICB9XG59XG5cblxuLyoqXG4gKiBQYXJ0aWFsbHkgYXJyYW5nZSBhIHJhbmdlIG9mIHZhbHVlcyBpbiBvcmRlciFcbiAqIEBwYXJhbSB4IGFuIGFycmF5ICh1cGRhdGVkISlcbiAqIEBwYXJhbSBpIGJlZ2luIGluZGV4XG4gKiBAcGFyYW0gSSBlbmQgaW5kZXggKGV4Y2x1c2l2ZSlcbiAqIEBwYXJhbSBuIG1pbmltdW0gbnVtYmVyIG9mIHZhbHVlcyB0byBzb3J0IChpZ25vcmVkKVxuICogQHBhcmFtIGZjIGNvbXBhcmUgZnVuY3Rpb24gKGEsIGIpXG4gKiBAcGFyYW0gZm0gbWFwIGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHBhcmFtIGZzIHN3YXAgZnVuY3Rpb24gKHgsIGksIGopXG4gKiBAcmV0dXJucyB4IHwgeFtpXSDiiaQgeFtqXSDiiIAgaSDiiaQgalxuICovXG5mdW5jdGlvbiByYW5nZWRQYXJ0aWFsSW5zZXJ0aW9uU29ydCQ8VCwgVT1UPih4OiBUW10sIGk6IG51bWJlciwgSTogbnVtYmVyLCBuOiBudW1iZXIsIGZjOiBDb21wYXJlRnVuY3Rpb248VHxVPiwgZm06IE1hcEZ1bmN0aW9uPFQsIFR8VT4sIGZzOiBTd2FwRnVuY3Rpb248VD4pOiBUW10ge1xuICAvLyBOT1RFOiBJbnNlcnRpb24gc29ydCBkb2VzIG5vdCBzdXBwb3J0IHBhcnRpYWwgc29ydGluZywgc28gd2UgaWdub3JlIG4uXG4gIGlmIChmcz09PXN3YXBSYXckKSByZXR1cm4gcmFuZ2VkUGFydGlhbEluc2VydGlvblNvcnRTd2FwbGVzcyQoeCwgaSwgSSwgbiwgZmMsIGZtLCBmcyk7XG4gIGVsc2UgICAgICAgICAgICAgICByZXR1cm4gcmFuZ2VkUGFydGlhbEluc2VydGlvblNvcnRTd2FwJCAgICAoeCwgaSwgSSwgbiwgZmMsIGZtLCBmcyk7XG59XG5cblxuLy8gU29ydCBhIHJhbmdlIG9mIHZhbHVlcyBpbiBvcmRlciB3aXRoIHN3YXAtZW5hYmxlZCB2ZXJzaW9uIG9mIGluc2VydGlvbiBzb3J0LlxuZnVuY3Rpb24gcmFuZ2VkUGFydGlhbEluc2VydGlvblNvcnRTd2FwJDxULCBVPVQ+KHg6IFRbXSwgaTogbnVtYmVyLCBJOiBudW1iZXIsIF9uOiBudW1iZXIsIGZjOiBDb21wYXJlRnVuY3Rpb248VHxVPiwgZm06IE1hcEZ1bmN0aW9uPFQsIFR8VT4sIGZzOiBTd2FwRnVuY3Rpb248VD4pOiBUW10ge1xuICBmb3IgKGxldCBqPWkrMTsgajxJOyArK2opIHtcbiAgICBjb25zdCBrZXkgID0geFtqXTtcbiAgICBjb25zdCB3a2V5ID0gZm0oa2V5LCBqLCB4KTtcbiAgICBmb3IgKGxldCBrPWotMTsgaz49aSAmJiBmYyhmbSh4W2tdLCBrLCB4KSwgd2tleSk+MDsgLS1rKVxuICAgICAgZnMoeCwgaywgaysxKTtcbiAgfVxuICByZXR1cm4geDtcbn1cblxuXG4vLyBTb3J0IGEgcmFuZ2Ugb2YgdmFsdWVzIGluIG9yZGVyIHdpdGggc3dhcGxlc3MgdmVyc2lvbiBvZiBpbnNlcnRpb24gc29ydC5cbmZ1bmN0aW9uIHJhbmdlZFBhcnRpYWxJbnNlcnRpb25Tb3J0U3dhcGxlc3MkPFQsIFU9VD4oeDogVFtdLCBpOiBudW1iZXIsIEk6IG51bWJlciwgX246IG51bWJlciwgZmM6IENvbXBhcmVGdW5jdGlvbjxUfFU+LCBmbTogTWFwRnVuY3Rpb248VCwgVHxVPiwgX2ZzOiBTd2FwRnVuY3Rpb248VD4pOiBUW10ge1xuICBmb3IgKGxldCBqPWkrMTsgajxJOyArK2opIHtcbiAgICBjb25zdCBrZXkgID0geFtqXTtcbiAgICBjb25zdCB3a2V5ID0gZm0oa2V5LCBqLCB4KTtcbiAgICBsZXQgayA9IGotMTtcbiAgICBmb3IgKDsgaz49aSAmJiBmYyhmbSh4W2tdLCBrLCB4KSwgd2tleSk+MDsgLS1rKVxuICAgICAgeFtrKzFdID0geFtrXTtcbiAgICB4W2srMV0gPSBrZXk7XG4gIH1cbiAgcmV0dXJuIHg7XG59XG5cblxuLyoqXG4gKiBQYXJ0aWFsbHkgYXJyYW5nZSBhIHJhbmdlIG9mIHZhbHVlcyBpbiBvcmRlciFcbiAqIEBwYXJhbSB4IGFuIGFycmF5ICh1cGRhdGVkISlcbiAqIEBwYXJhbSBpIGJlZ2luIGluZGV4XG4gKiBAcGFyYW0gSSBlbmQgaW5kZXggKGV4Y2x1c2l2ZSlcbiAqIEBwYXJhbSBuIG1pbmltdW0gbnVtYmVyIG9mIHZhbHVlcyB0byBzb3J0XG4gKiBAcGFyYW0gZmMgY29tcGFyZSBmdW5jdGlvbiAoYSwgYilcbiAqIEBwYXJhbSBmbSBtYXAgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcGFyYW0gZnMgc3dhcCBmdW5jdGlvbiAoeCwgaSwgailcbiAqIEByZXR1cm5zIHggfCB4W2ldIOKJpCB4W2pdIOKIgCBpIOKJpCBqXG4gKi9cbmZ1bmN0aW9uIF9yYW5nZWRQYXJ0aWFsU2VsZWN0aW9uU29ydCQ8VCwgVT1UPih4OiBUW10sIGk6IG51bWJlciwgSTogbnVtYmVyLCBuOiBudW1iZXIsIGZjOiBDb21wYXJlRnVuY3Rpb248VHxVPiwgZm06IE1hcEZ1bmN0aW9uPFQsIFR8VT4sIGZzOiBTd2FwRnVuY3Rpb248VD4pOiBUW10ge1xuICBmb3IgKGxldCBqPWk7IG4+MCAmJiBqPEk7ICsraiwgLS1uKSB7XG4gICAgbGV0IGwgID0gajtcbiAgICBsZXQgd2wgPSBmbSh4W2xdLCBsLCB4KTtcbiAgICBmb3IgKGxldCBrPWorMTsgazxJOyArK2spIHtcbiAgICAgIGNvbnN0IHdrID0gZm0oeFtrXSwgaywgeCk7XG4gICAgICBpZiAoZmMod2wsIHdrKSA+IDApIHsgbCA9IGs7IHdsID0gd2s7IH1cbiAgICB9XG4gICAgZnMoeCwgaiwgbCk7XG4gIH1cbiAgcmV0dXJuIHg7XG59XG4vLyAjZW5kcmVnaW9uXG5cblxuXG5cbi8vICNyZWdpb24gTUlOSU1VTS9NQVhJTVVNXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4vKipcbiAqIEZpbmQgZmlyc3Qgc21hbGxlc3QgdmFsdWUuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIGZjIGNvbXBhcmUgZnVuY3Rpb24gKGEsIGIpXG4gKiBAcGFyYW0gZm0gbWFwIGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHJldHVybnMgdiB8IHYg4omkIHbhtaI7IHbhtaIg4oiIIHhcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1pbmltdW08VCwgVT1UPih4OiBUW10sIGZjOiBDb21wYXJlRnVuY3Rpb248VHxVPiB8IG51bGw9bnVsbCwgZm06IE1hcEZ1bmN0aW9uPFQsIFR8VT4gfCBudWxsPW51bGwpOiBUIHtcbiAgY29uc3QgaSA9IHNlYXJjaE1pbmltdW1WYWx1ZSh4LCBmYywgZm0pO1xuICByZXR1cm4geFtpXTtcbn1cbmV4cG9ydCB7bWluaW11bSBhcyBtaW59O1xuXG5cbi8qKlxuICogRmluZCBmaXJzdCBzbWFsbGVzdCBlbnRyeS5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gZmMgY29tcGFyZSBmdW5jdGlvbiAoYSwgYilcbiAqIEBwYXJhbSBmbSBtYXAgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcmV0dXJucyBbbWluX2luZGV4LCBtaW5fdmFsdWVdXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBtaW5pbXVtRW50cnk8VCwgVT1UPih4OiBUW10sIGZjOiBDb21wYXJlRnVuY3Rpb248VHxVPiB8IG51bGw9bnVsbCwgZm06IE1hcEZ1bmN0aW9uPFQsIFR8VT4gfCBudWxsPW51bGwpOiBbbnVtYmVyLCBUXSB7XG4gIGNvbnN0IGkgPSBzZWFyY2hNaW5pbXVtVmFsdWUoeCwgZmMsIGZtKTtcbiAgcmV0dXJuIFtpLCB4W2ldXTtcbn1cbmV4cG9ydCB7bWluaW11bUVudHJ5IGFzIG1pbkVudHJ5fTtcblxuXG4vKipcbiAqIEZpbmQgZmlyc3QgbGFyZ2VzdCB2YWx1ZS5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gZmMgY29tcGFyZSBmdW5jdGlvbiAoYSwgYilcbiAqIEBwYXJhbSBmbSBtYXAgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcmV0dXJucyB2IHwgdiDiiaUgduG1ojsgduG1oiDiiIggeFxuICovXG5leHBvcnQgZnVuY3Rpb24gbWF4aW11bTxULCBVPVQ+KHg6IFRbXSwgZmM6IENvbXBhcmVGdW5jdGlvbjxUfFU+IHwgbnVsbD1udWxsLCBmbTogTWFwRnVuY3Rpb248VCwgVHxVPiB8IG51bGw9bnVsbCk6IFQge1xuICBjb25zdCBpID0gc2VhcmNoTWF4aW11bVZhbHVlKHgsIGZjLCBmbSk7XG4gIHJldHVybiB4W2ldO1xufVxuZXhwb3J0IHttYXhpbXVtIGFzIG1heH07XG5cblxuLyoqXG4gKiBGaW5kIGZpcnN0IGxhcmdlc3QgZW50cnkuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIGZjIGNvbXBhcmUgZnVuY3Rpb24gKGEsIGIpXG4gKiBAcGFyYW0gZm0gbWFwIGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHJldHVybnMgW21heF9pbmRleCwgbWF4X3ZhbHVlXVxuICovXG5leHBvcnQgZnVuY3Rpb24gbWF4aW11bUVudHJ5PFQsIFU9VD4oeDogVFtdLCBmYzogQ29tcGFyZUZ1bmN0aW9uPFR8VT4gfCBudWxsPW51bGwsIGZtOiBNYXBGdW5jdGlvbjxULCBUfFU+IHwgbnVsbD1udWxsKTogW251bWJlciwgVF0ge1xuICBjb25zdCBpID0gc2VhcmNoTWF4aW11bVZhbHVlKHgsIGZjLCBmbSk7XG4gIHJldHVybiBbaSwgeFtpXV07XG59XG5leHBvcnQge21heGltdW1FbnRyeSBhcyBtYXhFbnRyeX07XG5cblxuLyoqXG4gKiBGaW5kIHNtYWxsZXN0IGFuZCBsYXJnZXN0IHZhbHVlcy5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gZmMgY29tcGFyZSBmdW5jdGlvbiAoYSwgYilcbiAqIEBwYXJhbSBmbSBtYXAgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcmV0dXJucyBbbWluX3ZhbHVlLCBtYXhfdmFsdWVdXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByYW5nZTxULCBVPVQ+KHg6IFRbXSwgZmM6IENvbXBhcmVGdW5jdGlvbjxUfFU+IHwgbnVsbD1udWxsLCBmbTogTWFwRnVuY3Rpb248VCwgVHxVPiB8IG51bGw9bnVsbCk6IFtUIHwgdW5kZWZpbmVkLCBUIHwgdW5kZWZpbmVkXSB7XG4gIGNvbnN0IFthLCBiXSA9IHJhbmdlRW50cmllcyh4LCBmYywgZm0pO1xuICByZXR1cm4gW2FbMV0sIGJbMV1dO1xufVxuXG5cbi8qKlxuICogRmluZCBzbWFsbGVzdCBhbmQgbGFyZ2VzdCBlbnRyaWVzLlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSBmYyBjb21wYXJlIGZ1bmN0aW9uIChhLCBiKVxuICogQHBhcmFtIGZtIG1hcCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEByZXR1cm5zIFttaW5fZW50cnksIG1heF9lbnRyeV1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJhbmdlRW50cmllczxULCBVPVQ+KHg6IFRbXSwgZmM6IENvbXBhcmVGdW5jdGlvbjxUfFU+IHwgbnVsbD1udWxsLCBmbTogTWFwRnVuY3Rpb248VCwgVHxVPiB8IG51bGw9bnVsbCk6IFtbbnVtYmVyLCBUIHwgdW5kZWZpbmVkXSwgW251bWJlciwgVCB8IHVuZGVmaW5lZF1dIHtcbiAgZmMgPSBmYyB8fCBDT01QQVJFO1xuICBmbSA9IGZtIHx8IElERU5USVRZO1xuICBjb25zdCBYICA9IHgubGVuZ3RoO1xuICBpZiAoWD09PTApIHJldHVybiBbWy0xLCB1bmRlZmluZWRdLCBbLTEsIHVuZGVmaW5lZF1dO1xuICBsZXQgdiAgPSB4WzBdLCB3ID0gZm0odiwgMCwgeCk7XG4gIGxldCBtaSA9IDAsIG12ID0gdiwgbXcgPSB3O1xuICBsZXQgbmkgPSAwLCBudiA9IHYsIG53ID0gdztcbiAgZm9yIChsZXQgaT0xOyBpPFg7ICsraSkge1xuICAgIHYgPSB4W2ldOyB3ID0gZm0odiwgaSwgeCk7XG4gICAgaWYgKGZjKHcsIG13KTwwKSB7IG1pID0gaTsgbXYgPSB2OyBtdyA9IHc7IH1cbiAgICBpZiAoZmModywgbncpPjApIHsgbmkgPSBpOyBudiA9IHY7IG53ID0gdzsgfVxuICB9XG4gIHJldHVybiBbW21pLCBtdl0sIFtuaSwgbnZdXTtcbn1cblxuXG4vKipcbiAqIEZpbmQgc21hbGxlc3QgdmFsdWVzLlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSBuIG51bWJlciBvZiB2YWx1ZXNcbiAqIEBwYXJhbSBmYyBjb21wYXJlIGZ1bmN0aW9uIChhLCBiKVxuICogQHBhcmFtIGZtIG1hcCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEByZXR1cm5zIG4gc21hbGxlc3QgdmFsdWVzIGluIGFzY2VuZGluZyBvcmRlclxuICovXG5leHBvcnQgZnVuY3Rpb24gbWluaW11bXM8VCwgVT1UPih4OiBUW10sIG46IG51bWJlciwgZmM6IENvbXBhcmVGdW5jdGlvbjxudW1iZXJ8VHxVPiB8IG51bGw9bnVsbCwgZm06IE1hcEZ1bmN0aW9uPFQsIFR8VT4gfCBudWxsPW51bGwpOiBUW10ge1xuICBjb25zdCBpcyA9IHNlYXJjaE1pbmltdW1WYWx1ZXMoeCwgbiwgZmMsIGZtKTtcbiAgcmV0dXJuIGlzLm1hcChpID0+IHhbaV0pO1xufVxuXG5cbi8qKlxuICogRmluZCBzbWFsbGVzdCBlbnRyaWVzLlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSBuIG51bWJlciBvZiB2YWx1ZXNcbiAqIEBwYXJhbSBmYyBjb21wYXJlIGZ1bmN0aW9uIChhLCBiKVxuICogQHBhcmFtIGZtIG1hcCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEByZXR1cm5zIG4gc21hbGxlc3QgZW50cmllcyBpbiBhc2NlbmRpbmcgb3JkZXJcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1pbmltdW1FbnRyaWVzPFQsIFU9VD4oeDogVFtdLCBuOiBudW1iZXIsIGZjOiBDb21wYXJlRnVuY3Rpb248bnVtYmVyfFR8VT4gfCBudWxsPW51bGwsIGZtOiBNYXBGdW5jdGlvbjxULCBUfFU+IHwgbnVsbD1udWxsKTogW251bWJlciwgVF1bXSB7XG4gIGNvbnN0IGlzID0gc2VhcmNoTWluaW11bVZhbHVlcyh4LCBuLCBmYywgZm0pO1xuICByZXR1cm4gaXMubWFwKGkgPT4gW2ksIHhbaV1dKTtcbn1cblxuXG4vKipcbiAqIEZpbmQgbGFyZ2VzdCB2YWx1ZXMuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIG4gbnVtYmVyIG9mIHZhbHVlc1xuICogQHBhcmFtIGZjIGNvbXBhcmUgZnVuY3Rpb24gKGEsIGIpXG4gKiBAcGFyYW0gZm0gbWFwIGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHJldHVybnMgbiBsYXJnZXN0IHZhbHVlcyBpbiBkZXNjZW5kaW5nIG9yZGVyXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBtYXhpbXVtczxULCBVPVQ+KHg6IFRbXSwgbjogbnVtYmVyLCBmYzogQ29tcGFyZUZ1bmN0aW9uPG51bWJlcnxUfFU+IHwgbnVsbD1udWxsLCBmbTogTWFwRnVuY3Rpb248VCwgVHxVPiB8IG51bGw9bnVsbCk6IFRbXSB7XG4gIGNvbnN0IGlzID0gc2VhcmNoTWF4aW11bVZhbHVlcyh4LCBuLCBmYywgZm0pO1xuICByZXR1cm4gaXMubWFwKGkgPT4geFtpXSk7XG59XG5cblxuLyoqXG4gKiBGaW5kIGxhcmdlc3QgZW50cmllcy5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gbiBudW1iZXIgb2YgdmFsdWVzXG4gKiBAcGFyYW0gZmMgY29tcGFyZSBmdW5jdGlvbiAoYSwgYilcbiAqIEBwYXJhbSBmbSBtYXAgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcmV0dXJucyBuIGxhcmdlc3QgZW50cmllcyBpbiBkZXNjZW5kaW5nIG9yZGVyXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBtYXhpbXVtRW50cmllczxULCBVPVQ+KHg6IFRbXSwgbjogbnVtYmVyLCBmYzogQ29tcGFyZUZ1bmN0aW9uPG51bWJlcnxUfFU+IHwgbnVsbD1udWxsLCBmbTogTWFwRnVuY3Rpb248VCwgVHxVPiB8IG51bGw9bnVsbCk6IFtudW1iZXIsIFRdW10ge1xuICBjb25zdCBpcyA9IHNlYXJjaE1heGltdW1WYWx1ZXMoeCwgbiwgZmMsIGZtKTtcbiAgcmV0dXJuIGlzLm1hcChpID0+IFtpLCB4W2ldXSk7XG59XG5cblxuLyoqXG4gKiBGaW5kIGZpcnN0IGluZGV4IG9mIG1pbmltdW0gdmFsdWUuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIGZjIGNvbXBhcmUgZnVuY3Rpb24gKGEsIGIpXG4gKiBAcGFyYW0gZm0gbWFwIGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHJldHVybnMgZmlyc3QgaW5kZXggb2YgbWluaW11bSB2YWx1ZSwgLTEgaWYgZW1wdHlcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNlYXJjaE1pbmltdW1WYWx1ZTxULCBVPVQ+KHg6IFRbXSwgZmM6IENvbXBhcmVGdW5jdGlvbjxUfFU+IHwgbnVsbD1udWxsLCBmbTogTWFwRnVuY3Rpb248VCwgVHxVPiB8IG51bGw9bnVsbCk6IG51bWJlciB7XG4gIGZjID0gZmMgfHwgQ09NUEFSRTtcbiAgZm0gPSBmbSB8fCBJREVOVElUWTtcbiAgY29uc3QgWCAgPSB4Lmxlbmd0aDtcbiAgaWYgKFg9PT0wKSByZXR1cm4gLTE7XG4gIGxldCBtaSA9IDAsIG13ID0gZm0oeFswXSwgMCwgeCk7XG4gIGZvciAobGV0IGk9MTsgaTxYOyArK2kpIHtcbiAgICBjb25zdCB3ID0gZm0oeFtpXSwgaSwgeCk7XG4gICAgaWYgKGZjKHcsIG13KTwwKSB7IG1pID0gaTsgbXcgPSB3OyB9XG4gIH1cbiAgcmV0dXJuIG1pO1xufVxuXG5cbi8qKlxuICogRmluZCBmaXJzdCBpbmRleCBvZiBtYXhpbXVtIHZhbHVlLlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSBmYyBjb21wYXJlIGZ1bmN0aW9uIChhLCBiKVxuICogQHBhcmFtIGZtIG1hcCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEByZXR1cm5zIGZpcnN0IGluZGV4IG9mIG1heGltdW0gdmFsdWUsIC0xIGlmIGVtcHR5XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzZWFyY2hNYXhpbXVtVmFsdWU8VCwgVT1UPih4OiBUW10sIGZjOiBDb21wYXJlRnVuY3Rpb248VHxVPiB8IG51bGw9bnVsbCwgZm06IE1hcEZ1bmN0aW9uPFQsIFR8VT4gfCBudWxsPW51bGwpOiBudW1iZXIge1xuICBmYyA9IGZjIHx8IENPTVBBUkU7XG4gIGZtID0gZm0gfHwgSURFTlRJVFk7XG4gIGNvbnN0IFggID0geC5sZW5ndGg7XG4gIGlmIChYPT09MCkgcmV0dXJuIC0xO1xuICBsZXQgbmkgPSAwLCBudyA9IGZtKHhbMF0sIDAsIHgpO1xuICBmb3IgKGxldCBpPTE7IGk8WDsgKytpKSB7XG4gICAgY29uc3QgdyA9IGZtKHhbaV0sIGksIHgpO1xuICAgIGlmIChmYyh3LCBudyk+MCkgeyBuaSA9IGk7IG53ID0gdzsgfVxuICB9XG4gIHJldHVybiBuaTtcbn1cblxuXG4vKipcbiAqIEZpbmQgaW5kaWNlcyBvZiBtaW5pbXVtIHZhbHVlcy5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gbiBudW1iZXIgb2YgdmFsdWVzXG4gKiBAcGFyYW0gZmMgY29tcGFyZSBmdW5jdGlvbiAoYSwgYilcbiAqIEBwYXJhbSBmbSBtYXAgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcmV0dXJucyBpbmRpY2VzIG9mIG1pbmltdW0gdmFsdWVzIGluIGFzY2VuZGluZyBvcmRlclxuICovXG5leHBvcnQgZnVuY3Rpb24gc2VhcmNoTWluaW11bVZhbHVlczxULCBVPVQ+KHg6IFRbXSwgbjogbnVtYmVyLCBmYzogQ29tcGFyZUZ1bmN0aW9uPG51bWJlcnxUfFU+IHwgbnVsbD1udWxsLCBmbTogTWFwRnVuY3Rpb248VCwgVHxVPiB8IG51bGw9bnVsbCk6IG51bWJlcltdIHtcbiAgZmMgPSBmYyB8fCBDT01QQVJFO1xuICBmbSA9IGZtIHx8IElERU5USVRZO1xuICBjb25zdCBYICA9IHgubGVuZ3RoO1xuICAvLyBDcmVhdGUgYSBtYXggaGVhcCBvZiBpbmRpY2VzLlxuICBjb25zdCBJSCA9IE1hdGgubWluKG4sIFgpO1xuICBjb25zdCBpaCA9IGZyb21SYW5nZSgwLCBJSCk7XG4gIHJhbmdlZEJ1aWxkTWF4SGVhcCQoaWgsIDAsIElILCBmYywgaSA9PiBmbSh4W2ldLCBpLCB4KSwgc3dhcFJhdyQpO1xuICBsZXQgd3IgPSBmbSh4W2loWzBdXSwgaWhbMF0sIHgpO1xuICAvLyBTZWFyY2ggZm9yIG1pbmltdW0gdmFsdWVzLCBhbmQgdXBkYXRlIGhlYXAuXG4gIGZvciAobGV0IGk9bjsgaTxYOyArK2kpIHtcbiAgICBjb25zdCB3ID0gZm0oeFtpXSwgaSwgeCk7XG4gICAgaWYgKGZjKHcsIHdyKSA+PSAwKSBjb250aW51ZTtcbiAgICBpaFswXSA9IGk7XG4gICAgcmFuZ2VkTWF4SGVhcGlmeSQoaWgsIDAsIElILCAwLCBmYywgaSA9PiBmbSh4W2ldLCBpLCB4KSwgc3dhcFJhdyQpO1xuICAgIHdyID0gZm0oeFtpaFswXV0sIGloWzBdLCB4KTtcbiAgfVxuICAvLyBTb3J0IG1heCBoZWFwIGluIGFzY2VuZGluZyBvcmRlci5cbiAgaWguc29ydCgoaSwgaikgPT4gZmMoZm0oeFtpXSwgaSwgeCksIGZtKHhbal0sIGosIHgpKSk7XG4gIHJldHVybiBpaDtcbn1cblxuXG4vKipcbiAqIEZpbmQgaW5kaWNlcyBvZiBtYXhpbXVtIHZhbHVlcy5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gbiBudW1iZXIgb2YgdmFsdWVzXG4gKiBAcGFyYW0gZmMgY29tcGFyZSBmdW5jdGlvbiAoYSwgYilcbiAqIEBwYXJhbSBmbSBtYXAgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcmV0dXJucyBpbmRpY2VzIG9mIG1heGltdW0gdmFsdWVzIGluIGRlc2NlbmRpbmcgb3JkZXJcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNlYXJjaE1heGltdW1WYWx1ZXM8VCwgVT1UPih4OiBUW10sIG46IG51bWJlciwgZmM6IENvbXBhcmVGdW5jdGlvbjxudW1iZXJ8VHxVPiB8IG51bGw9bnVsbCwgZm06IE1hcEZ1bmN0aW9uPFQsIFR8VT4gfCBudWxsPW51bGwpOiBudW1iZXJbXSB7XG4gIGZjID0gZmMgfHwgQ09NUEFSRTtcbiAgY29uc3QgZmQgPSAoYTogbnVtYmVyfFR8VSwgYjogbnVtYmVyfFR8VSkgPT4gLWZjKGEsIGIpO1xuICByZXR1cm4gc2VhcmNoTWluaW11bVZhbHVlcyh4LCBuLCBmZCwgZm0pO1xufVxuLy8gI2VuZHJlZ2lvblxuXG5cblxuXG4vLyAjcmVnaW9uIENPTVBBUkVcbi8vIC0tLS0tLS0tLS0tLS0tLVxuXG4vKipcbiAqIEV4YW1pbmUgaWYgdHdvIGFycmF5cyBhcmUgZXF1YWwuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIHkgYW5vdGhlciBhcnJheVxuICogQHBhcmFtIGZjIGNvbXBhcmUgZnVuY3Rpb24gKGEsIGIpXG4gKiBAcGFyYW0gZm0gbWFwIGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHJldHVybnMgeCA9IHk/XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc0VxdWFsPFQsIFU9VD4oeDogVFtdLCB5OiBUW10sIGZjOiBDb21wYXJlRnVuY3Rpb248VHxVPiB8IG51bGw9bnVsbCwgZm06IE1hcEZ1bmN0aW9uPFQsIFR8VT4gfCBudWxsPW51bGwpOiBib29sZWFuIHtcbiAgY29uc3QgWCA9IHgubGVuZ3RoLCBZID0geS5sZW5ndGg7XG4gIHJldHVybiBYPT09WSAmJiBjb21wYXJlKHgsIHksIGZjLCBmbSk9PT0wO1xufVxuXG5cbi8qKlxuICogQ29tcGFyZSB0d28gYXJyYXlzIChsZXhpY29ncmFwaGljYWxseSkuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIHkgYW5vdGhlciBhcnJheVxuICogQHBhcmFtIGZjIGNvbXBhcmUgZnVuY3Rpb24gKGEsIGIpXG4gKiBAcGFyYW0gZm0gbWFwIGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHJldHVybnMgeDx5OiAtdmUsIHg9eTogMCwgeD55OiArdmVcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNvbXBhcmU8VCwgVT1UPih4OiBUW10sIHk6IFRbXSwgZmM6IENvbXBhcmVGdW5jdGlvbjxUfFU+IHwgbnVsbD1udWxsLCBmbTogTWFwRnVuY3Rpb248VCwgVHxVPiB8IG51bGw9bnVsbCk6IG51bWJlciB7XG4gIGZjID0gZmMgfHwgQ09NUEFSRTtcbiAgZm0gPSBmbSB8fCBJREVOVElUWTtcbiAgY29uc3QgWCAgPSB4Lmxlbmd0aDtcbiAgY29uc3QgWSAgPSB5Lmxlbmd0aDtcbiAgZm9yIChsZXQgaT0wLCBJPU1hdGgubWluKFgsIFkpOyBpPEk7ICsraSkge1xuICAgIGNvbnN0IHd4ID0gZm0oeFtpXSwgaSwgeCk7XG4gICAgY29uc3Qgd3kgPSBmbSh5W2ldLCBpLCB5KTtcbiAgICBjb25zdCBjICA9IGZjKHd4LCB3eSk7XG4gICAgaWYgKGMhPT0wKSByZXR1cm4gYztcbiAgfVxuICByZXR1cm4gTWF0aC5zaWduKFgtWSk7XG59XG4vLyAjZW5kcmVnaW9uXG5cblxuXG5cbi8vICNyZWdpb24gUEFSVFxuLy8gLS0tLS0tLS0tLS0tXG5cbi8qKlxuICogR2V0IGZpcnN0IHZhbHVlLlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSB2ZCBkZWZhdWx0IHZhbHVlXG4gKiBAcmV0dXJucyB4WzBdIHx8IHZkXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBoZWFkPFQ+KHg6IFRbXSwgdmQ/OiBUKTogVCB8IHVuZGVmaW5lZCB7XG4gIHJldHVybiB4Lmxlbmd0aD4wPyB4WzBdIDogdmQ7XG59XG5leHBvcnQge2hlYWQgYXMgZnJvbnR9O1xuZXhwb3J0IHtoZWFkIGFzIGZpcnN0fTtcblxuXG4vKipcbiAqIEdldCB2YWx1ZXMgZXhjZXB0IGZpcnN0LlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEByZXR1cm5zIHhbMS4ufHh8XVxuICovXG5leHBvcnQgZnVuY3Rpb24gdGFpbDxUPih4OiBUW10pOiBUW10ge1xuICByZXR1cm4geC5zbGljZSgxKTtcbn1cblxuXG4vKipcbiAqIEdldCB2YWx1ZXMgZXhjZXB0IGxhc3QuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHJldHVybnMgeFswLi58eHwtMV1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGluaXQ8VD4oeDogVFtdKTogVFtdIHtcbiAgcmV0dXJuIHguc2xpY2UoMCwgLTEpO1xufVxuXG5cbi8qKlxuICogR2V0IGxhc3QgdmFsdWUuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIHZkIGRlZmF1bHQgdmFsdWVcbiAqIEByZXR1cm5zIHhbfHh8LTFdIHx8IHZkXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBsYXN0PFQ+KHg6IFRbXSwgdmQ/OiBUKTogVCB8IHVuZGVmaW5lZCB7XG4gIHJldHVybiB4Lmxlbmd0aD4wPyB4W3gubGVuZ3RoLTFdIDogdmQ7XG59XG5leHBvcnQge2xhc3QgYXMgYmFja307XG5cblxuLyoqXG4gKiBHZXQgdmFsdWVzIGZyb20gbWlkZGxlLlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSBpIGJlZ2luIGluZGV4XG4gKiBAcGFyYW0gbiBudW1iZXIgb2YgdmFsdWVzIFsxXVxuICogQHJldHVybnMgeFtpLi5pK25dXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBtaWRkbGU8VD4oeDogVFtdLCBpOiBudW1iZXIsIG46IG51bWJlcj0xKTogVFtdIHtcbiAgaSA9IGluZGV4KHgsIGkpO1xuICBuID0gTWF0aC5tYXgobiwgMCk7XG4gIHJldHVybiB4LnNsaWNlKGksIGkrbik7XG59XG5cblxuLyoqXG4gKiBHZXQgcGFydCBvZiBhbiBhcnJheS5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gaSBiZWdpbiBpbmRleCBbMF1cbiAqIEBwYXJhbSBJIGVuZCBpbmRleCBbfHh8XVxuICogQHJldHVybnMgeFtpLi5JXVxuICovXG5leHBvcnQgZnVuY3Rpb24gc2xpY2U8VD4oeDogVFtdLCBpOiBudW1iZXI9MCwgSTogbnVtYmVyPXgubGVuZ3RoKTogVFtdIHtcbiAgcmV0dXJuIHguc2xpY2UoaSwgSSk7XG59XG5cblxuLyoqXG4gKiBHZXQgcGFydCBvZiBhbiBhcnJheSFcbiAqIEBwYXJhbSB4IGFuIGFycmF5ICh1cGRhdGVkISlcbiAqIEBwYXJhbSBpIGJlZ2luIGluZGV4IFswXVxuICogQHBhcmFtIEkgZW5kIGluZGV4IFt8eHxdXG4gKiBAcmV0dXJucyB4ID0geFtpLi5JXVxuICovXG5leHBvcnQgZnVuY3Rpb24gc2xpY2UkPFQ+KHg6IFRbXSwgaTogbnVtYmVyPTAsIEk6IG51bWJlcj14Lmxlbmd0aCk6IFRbXSB7XG4gIHguY29weVdpdGhpbigwLCBpLCBJKTtcbiAgeC5sZW5ndGggPSBsZW5ndGgoeCwgaSwgSSk7XG4gIHJldHVybiB4O1xufVxuLy8gI2VuZHJlZ2lvblxuXG5cblxuXG4vLyAjcmVnaW9uIFNFQVJDSCBWQUxVRVxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuLyoqXG4gKiBDaGVjayBpZiBhcnJheSBoYXMgYSB2YWx1ZS5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gdiBzZWFyY2ggdmFsdWVcbiAqIEBwYXJhbSBpIGJlZ2luIGluZGV4IFswXVxuICogQHJldHVybnMgdiDiiIggeFtpLi5dP1xuICovXG5leHBvcnQgZnVuY3Rpb24gaW5jbHVkZXM8VD4oeDogVFtdLCB2OiBULCBpOiBudW1iZXI9MCk6IGJvb2xlYW4ge1xuICByZXR1cm4geC5pbmNsdWRlcyh2LCBpKTtcbn1cblxuXG4vKipcbiAqIEV4YW1pbmUgaWYgYXJyYXkgaGFzIGEgdmFsdWUuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIHYgc2VhcmNoIHZhbHVlXG4gKiBAcGFyYW0gZmMgY29tcGFyZSBmdW5jdGlvbiAoYSwgYilcbiAqIEBwYXJhbSBmbSBtYXAgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcmV0dXJucyB2IOKIiCB4P1xuICovXG5leHBvcnQgZnVuY3Rpb24gaGFzVmFsdWU8VCwgVT1UPih4OiBUW10sIHY6IFQsIGZjOiBDb21wYXJlRnVuY3Rpb248VHxVPiB8IG51bGw9bnVsbCwgZm06IE1hcEZ1bmN0aW9uPFQsIFR8VT4gfCBudWxsPW51bGwpOiBib29sZWFuIHtcbiAgcmV0dXJuIHNlYXJjaFZhbHVlKHgsIHYsIGZjLCBmbSkgPj0gMDtcbn1cblxuXG4vKipcbiAqIEZpbmQgZmlyc3QgaW5kZXggb2YgYSB2YWx1ZS5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gdiBzZWFyY2ggdmFsdWVcbiAqIEBwYXJhbSBmYyBjb21wYXJlIGZ1bmN0aW9uIChhLCBiKVxuICogQHBhcmFtIGZtIG1hcCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEByZXR1cm5zIGZpcnN0IGluZGV4IG9mIHZhbHVlLCAtMSBpZiBub3QgZm91bmRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNlYXJjaFZhbHVlPFQsIFU9VD4oeDogVFtdLCB2OiBULCBmYzogQ29tcGFyZUZ1bmN0aW9uPFR8VT4gfCBudWxsPW51bGwsIGZtOiBNYXBGdW5jdGlvbjxULCBUfFU+IHwgbnVsbD1udWxsKTogbnVtYmVyIHtcbiAgZmMgPSBmYyB8fCBDT01QQVJFO1xuICBmbSA9IGZtIHx8IElERU5USVRZO1xuICBjb25zdCB3ICA9IGZtKHYsIDAsIG51bGwpOyBsZXQgaSA9IC0xO1xuICBmb3IgKGNvbnN0IHZ4IG9mIHgpIHtcbiAgICBjb25zdCB3eCA9IGZtKHZ4LCArK2ksIHgpO1xuICAgIGlmIChmYyh3eCwgdyk9PT0wKSByZXR1cm4gaTtcbiAgfVxuICByZXR1cm4gLTE7XG59XG5cblxuLyoqXG4gKiBGaW5kIGxhc3QgaW5kZXggb2YgYSB2YWx1ZS5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gdiBzZWFyY2ggdmFsdWVcbiAqIEBwYXJhbSBmYyBjb21wYXJlIGZ1bmN0aW9uIChhLCBiKVxuICogQHBhcmFtIGZtIG1hcCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEByZXR1cm5zIGxhc3QgaW5kZXggb2YgdmFsdWUsIC0xIGlmIG5vdCBmb3VuZFxuICovXG5leHBvcnQgZnVuY3Rpb24gc2VhcmNoVmFsdWVSaWdodDxULCBVPVQ+KHg6IFRbXSwgdjogVCwgZmM6IENvbXBhcmVGdW5jdGlvbjxUfFU+IHwgbnVsbD1udWxsLCBmbTogTWFwRnVuY3Rpb248VCwgVHxVPiB8IG51bGw9bnVsbCk6IG51bWJlciB7XG4gIGZjID0gZmMgfHwgQ09NUEFSRTtcbiAgZm0gPSBmbSB8fCBJREVOVElUWTtcbiAgY29uc3QgdyA9IGZtKHYsIDAsIG51bGwpO1xuICBmb3IgKGxldCBpPXgubGVuZ3RoLTE7IGk+PTA7IC0taSkge1xuICAgIGNvbnN0IHd4ID0gZm0oeFtpXSwgaSwgeCk7XG4gICAgaWYgKGZjKHd4LCB3KT09PTApIHJldHVybiBpO1xuICB9XG4gIHJldHVybiAtMTtcbn1cblxuXG4vKipcbiAqIEZpbmQgaW5kaWNlcyBvZiB2YWx1ZS5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gdiBzZWFyY2ggdmFsdWVcbiAqIEBwYXJhbSBmYyBjb21wYXJlIGZ1bmN0aW9uIChhLCBiKVxuICogQHBhcmFtIGZtIG1hcCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEByZXR1cm5zIGluZGljZXMgb2YgdmFsdWVcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNlYXJjaFZhbHVlQWxsPFQsIFU9VD4oeDogVFtdLCB2OiBULCBmYzogQ29tcGFyZUZ1bmN0aW9uPFR8VT4gfCBudWxsPW51bGwsIGZtOiBNYXBGdW5jdGlvbjxULCBUfFU+IHwgbnVsbD1udWxsKTogbnVtYmVyW10ge1xuICBmYyA9IGZjIHx8IENPTVBBUkU7XG4gIGZtID0gZm0gfHwgSURFTlRJVFk7XG4gIGNvbnN0IHcgPSBmbSh2LCAwLCBudWxsKTtcbiAgbGV0IGkgPSAtMTsgY29uc3QgYSA9IFtdO1xuICBmb3IgKGNvbnN0IHZ4IG9mIHgpIHtcbiAgICBjb25zdCB3eCA9IGZtKHZ4LCArK2ksIHgpO1xuICAgIGlmIChmYyh3eCwgdyk9PT0wKSBhLnB1c2goaSk7XG4gIH1cbiAgcmV0dXJuIGE7XG59XG5cblxuLyoqXG4gKiBGaW5kIGZpcnN0IGluZGV4IG9mIGFuIGFkamFjZW50IGR1cGxpY2F0ZSB2YWx1ZS5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gZmMgY29tcGFyZSBmdW5jdGlvbiAoYSwgYilcbiAqIEBwYXJhbSBmbSBtYXAgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcmV0dXJucyBpbmRleCBvZiBmaXJzdCBhZGphY2VudCBkdXBsaWNhdGUgdmFsdWUsIC0xIGlmIG5vbmVcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNlYXJjaEFkamFjZW50RHVwbGljYXRlVmFsdWU8VCwgVT1UPih4OiBUW10sIGZjOiBDb21wYXJlRnVuY3Rpb248VHxVPiB8IG51bGw9bnVsbCwgZm06IE1hcEZ1bmN0aW9uPFQsIFR8VT4gfCBudWxsPW51bGwpOiBudW1iZXIge1xuICBmYyA9IGZjIHx8IENPTVBBUkU7XG4gIGZtID0gZm0gfHwgSURFTlRJVFk7XG4gIGNvbnN0IFggID0geC5sZW5ndGg7XG4gIGlmIChYPD0xKSByZXR1cm4gLTE7XG4gIGxldCB3MCA9IGZtKHhbMF0sIDAsIHgpO1xuICBmb3IgKGxldCBpPTE7IGk8WDsgKytpKSB7XG4gICAgY29uc3QgdyA9IGZtKHhbaV0sIGksIHgpO1xuICAgIGlmIChmYyh3MCwgdyk9PT0wKSByZXR1cm4gaTtcbiAgICB3MCA9IHc7XG4gIH1cbiAgcmV0dXJuIC0xO1xufVxuZXhwb3J0IHtzZWFyY2hBZGphY2VudER1cGxpY2F0ZVZhbHVlIGFzIHNlYXJjaEFkamFjZW50RHVwbGljYXRlfTtcblxuXG4vKipcbiAqIEZpbmQgZmlyc3QgaW5kZXggd2hlcmUgdHdvIGFycmF5cyBkaWZmZXIuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIHkgYW5vdGhlciBhcnJheVxuICogQHBhcmFtIGZjIGNvbXBhcmUgZnVuY3Rpb24gKGEsIGIpXG4gKiBAcGFyYW0gZm0gbWFwIGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHJldHVybnMgZmlyc3QgaW5kZXggd2hlcmUgeFtpXSDiiaAgeVtpXSwgb3IgLTFcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNlYXJjaE1pc21hdGNoZWRWYWx1ZTxULCBVPVQ+KHg6IFRbXSwgeTogVFtdLCBmYzogQ29tcGFyZUZ1bmN0aW9uPFR8VT4gfCBudWxsPW51bGwsIGZtOiBNYXBGdW5jdGlvbjxULCBUfFU+IHwgbnVsbD1udWxsKTogbnVtYmVyIHtcbiAgZmMgPSBmYyB8fCBDT01QQVJFO1xuICBmbSA9IGZtIHx8IElERU5USVRZO1xuICBjb25zdCBYID0geC5sZW5ndGg7XG4gIGNvbnN0IFkgPSB5Lmxlbmd0aDtcbiAgY29uc3QgSSA9IE1hdGgubWluKFgsIFkpO1xuICBmb3IgKGxldCBpPTA7IGk8STsgKytpKSB7XG4gICAgY29uc3Qgd3ggPSBmbSh4W2ldLCBpLCB4KTtcbiAgICBjb25zdCB3eSA9IGZtKHlbaV0sIGksIHkpO1xuICAgIGlmIChmYyh3eCwgd3kpIT09MCkgcmV0dXJuIGk7XG4gIH1cbiAgcmV0dXJuIFg9PT1ZPyAtMSA6IEk7XG59XG5leHBvcnQge3NlYXJjaE1pc21hdGNoZWRWYWx1ZSBhcyBzZWFyY2hNaXNtYXRjaH07XG4vLyAjZW5kcmVnaW9uXG5cblxuXG5cbi8vICNyZWdpb24gQVJSQU5HRU1FTlRTXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4vKipcbiAqIEV4YW1pbmUgaWYgYXJyYXkgc3RhcnRzIHdpdGggYSBwcmVmaXguXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIHkgc2VhcmNoIHByZWZpeFxuICogQHBhcmFtIGZjIGNvbXBhcmUgZnVuY3Rpb24gKGEsIGIpXG4gKiBAcGFyYW0gZm0gbWFwIGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHJldHVybnMgeFswLi58eXxdID0geT9cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGhhc1ByZWZpeDxULCBVPVQ+KHg6IFRbXSwgeTogVFtdLCBmYzogQ29tcGFyZUZ1bmN0aW9uPFR8VT4gfCBudWxsPW51bGwsIGZtOiBNYXBGdW5jdGlvbjxULCBUfFU+IHwgbnVsbD1udWxsKTogYm9vbGVhbiB7XG4gIGNvbnN0IFkgPSB5Lmxlbmd0aDtcbiAgcmV0dXJuIFk9PT0wIHx8IGNvbXBhcmUoeC5zbGljZSgwLCBZKSwgeSwgZmMsIGZtKT09PTA7XG59XG5leHBvcnQge2hhc1ByZWZpeCBhcyBzdGFydHNXaXRofTtcblxuXG4vKipcbiAqIEV4YW1pbmUgaWYgYXJyYXkgZW5kcyB3aXRoIGEgc3VmZml4LlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSB5IHNlYXJjaCBzdWZmaXhcbiAqIEBwYXJhbSBmYyBjb21wYXJlIGZ1bmN0aW9uIChhLCBiKVxuICogQHBhcmFtIGZtIG1hcCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEByZXR1cm5zIHhbfHh8LXx5fC4uXSA9IHk/XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBoYXNTdWZmaXg8VCwgVT1UPih4OiBUW10sIHk6IFRbXSwgZmM6IENvbXBhcmVGdW5jdGlvbjxUfFU+IHwgbnVsbD1udWxsLCBmbTogTWFwRnVuY3Rpb248VCwgVHxVPiB8IG51bGw9bnVsbCk6IGJvb2xlYW4ge1xuICBjb25zdCBZID0geS5sZW5ndGg7XG4gIHJldHVybiBZPT09MCB8fCBjb21wYXJlKHguc2xpY2UoLVkpLCB5LCBmYywgZm0pPT09MDtcbn1cbmV4cG9ydCB7aGFzU3VmZml4IGFzIGVuZHNXaXRofTtcblxuXG4vKipcbiAqIEV4YW1pbmUgaWYgYXJyYXkgY29udGFpbnMgYW4gaW5maXguXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIHkgc2VhcmNoIGluZml4XG4gKiBAcGFyYW0gZmMgY29tcGFyZSBmdW5jdGlvbiAoYSwgYilcbiAqIEBwYXJhbSBmbSBtYXAgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcmV0dXJucyB4W2kuLkldID0geSBmb3Igc29tZSBpLCBJP1xuICovXG5leHBvcnQgZnVuY3Rpb24gaGFzSW5maXg8VCwgVT1UPih4OiBUW10sIHk6IFRbXSwgZmM6IENvbXBhcmVGdW5jdGlvbjxUfFU+IHwgbnVsbD1udWxsLCBmbTogTWFwRnVuY3Rpb248VCwgVHxVPiB8IG51bGw9bnVsbCk6IGJvb2xlYW4ge1xuICByZXR1cm4gc2VhcmNoSW5maXgoeCwgeSwgZmMsIGZtKSA+PSAwO1xufVxuXG5cbi8qKlxuICogRXhhbWluZSBpZiBhcnJheSBoYXMgYSBzdWJzZXF1ZW5jZS5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0geSBzZWFyY2ggc3Vic2VxdWVuY2VcbiAqIEBwYXJhbSBmYyBjb21wYXJlIGZ1bmN0aW9uIChhLCBiKVxuICogQHBhcmFtIGZtIG1hcCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEByZXR1cm5zIHhbaeKCgF0g4qe6IHhbaeKCgV0g4qe6IC4uLiA9IHksIGZvciBzb21lIGnigoAsIGnigoEsIC4uLj8gfCBp4oKAIDwgaeKCgSA8IC4uLlxuICovXG5leHBvcnQgZnVuY3Rpb24gaGFzU3Vic2VxdWVuY2U8VCwgVT1UPih4OiBUW10sIHk6IFRbXSwgZmM6IENvbXBhcmVGdW5jdGlvbjxUfFU+IHwgbnVsbD1udWxsLCBmbTogTWFwRnVuY3Rpb248VCwgVHxVPiB8IG51bGw9bnVsbCk6IGJvb2xlYW4ge1xuICByZXR1cm4gc2VhcmNoU3Vic2VxdWVuY2UoeCwgeSwgZmMsIGZtKSA+PSAwO1xufVxuXG5cbi8qKlxuICogRXhhbWluZSBpZiBhcnJheSBoYXMgYSBwZXJtdXRhdGlvbi5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0geSBzZWFyY2ggcGVybXV0YXRpb25cbiAqIEBwYXJhbSBmYyBtYXAgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcGFyYW0gZm0gY29tcGFyZSBmdW5jdGlvbiAoYSwgYilcbiAqIEByZXR1cm5zIHggY29udGFpbnMgYSBzaHVmZmxlZCB2ZXJzaW9uIG9mIHk/XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBoYXNQZXJtdXRhdGlvbjxULCBVPVQ+KHg6IFRbXSwgeTogVFtdLCBmYzogQ29tcGFyZUZ1bmN0aW9uPFR8VT4gfCBudWxsPW51bGwsIGZtOiBNYXBGdW5jdGlvbjxULCBUfFU+IHwgbnVsbD1udWxsKTogYm9vbGVhbiB7XG4gIGNvbnN0IHgxID0gZm0/IHgubWFwKGZtKSA6IHguc2xpY2UoKTtcbiAgY29uc3QgeTEgPSBmbT8geS5tYXAoZm0pIDogeS5zbGljZSgpO1xuICByZXR1cm4gaGFzU3Vic2VxdWVuY2U8VHxVPih4MS5zb3J0KCksIHkxLnNvcnQoKSwgZmMpO1xuICAvLyByZXR1cm4gaGFzU3Vic2VxdWVuY2U8VHxVPih4MS5zb3J0KCksIHkxLnNvcnQoKSwgZmMsIGZtKTtcbn1cblxuXG4vKipcbiAqIE9idGFpbiBhbGwgcG9zc2libGUgcHJlZml4ZXMuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIG4gbnVtYmVyIG9mIHZhbHVlcyBbLTEg4oeSIGFueV1cbiAqIEByZXR1cm5zIFtbXSwgeFsuLjFdLCB4Wy4uMl0sIC4uLl0gaWYgbjwwOyBbeFsuLm5dXSBvdGhlcndpc2VcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHByZWZpeGVzPFQ+KHg6IFRbXSwgbjogbnVtYmVyPS0xKTogVFtdW10ge1xuICByZXR1cm4gWy4uLmlwcmVmaXhlcyh4LCBuKV07XG59XG5cblxuLyoqXG4gKiBMaXN0IGFsbCBwb3NzaWJsZSBwcmVmaXhlcy5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gbiBudW1iZXIgb2YgdmFsdWVzIFstMSDih5IgYW55XVxuICogQHJldHVybnMgW10sIHhbLi4xXSwgeFsuLjJdLCAuLi4gaWYgbjwwOyB4Wy4ubl0gb3RoZXJ3aXNlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiogaXByZWZpeGVzPFQ+KHg6IFRbXSwgbjogbnVtYmVyPS0xKTogSXRlcmFibGVJdGVyYXRvcjxUW10+IHtcbiAgY29uc3QgWCA9IHgubGVuZ3RoO1xuICBpZiAobj5YKSAgcmV0dXJuO1xuICBpZiAobj49MCkgeyB5aWVsZCB4LnNsaWNlKDAsIG4pOyByZXR1cm47IH1cbiAgZm9yIChsZXQgaT0wOyBpPD1YOyArK2kpXG4gICAgeWllbGQgeC5zbGljZSgwLCBpKTtcbn1cblxuXG4vKipcbiAqIE9idGFpbiBhbGwgcG9zc2libGUgc3VmZml4ZXMuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIG4gbnVtYmVyIG9mIHZhbHVlcyBbLTEg4oeSIGFueV1cbiAqIEByZXR1cm5zIFt4WzAuLl0sIHhbMS4uXSwgeFsyLi5dLCAuLi5dIGlmIG48MDsgW3hbLW4uLl1dIG90aGVyd2lzZVxuICovXG5leHBvcnQgZnVuY3Rpb24gc3VmZml4ZXM8VD4oeDogVFtdLCBuOiBudW1iZXI9LTEpOiBUW11bXSB7XG4gIHJldHVybiBbLi4uaXN1ZmZpeGVzKHgsIG4pXTtcbn1cblxuXG4vKipcbiAqIExpc3QgYWxsIHBvc3NpYmxlIHN1ZmZpeGVzLlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSBuIG51bWJlciBvZiB2YWx1ZXMgWy0xIOKHkiBhbnldXG4gKiBAcmV0dXJucyB4WzAuLl0sIHhbMS4uXSwgeFsyLi5dLCAuLi4gaWYgbjwwOyB4Wy1uLi5dIG90aGVyd2lzZVxuICovXG5leHBvcnQgZnVuY3Rpb24qIGlzdWZmaXhlczxUPih4OiBUW10sIG46IG51bWJlcj0tMSk6IEl0ZXJhYmxlSXRlcmF0b3I8VFtdPiB7XG4gIGNvbnN0IFggPSB4Lmxlbmd0aDtcbiAgaWYgKG4+WCkgIHJldHVybjtcbiAgaWYgKG4+PTApIHsgeWllbGQgeC5zbGljZSh4Lmxlbmd0aCAtIG4pOyByZXR1cm47IH1cbiAgZm9yIChsZXQgaT0wOyBpPD1YOyArK2kpXG4gICAgeWllbGQgeC5zbGljZShpKTtcbn1cblxuXG4vKipcbiAqIE9idGFpbiBhbGwgcG9zc2libGUgaW5maXhlcy5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gbiBudW1iZXIgb2YgdmFsdWVzIFstMSDih5IgYW55XVxuICogQHJldHVybnMgW1tdLCB4WzAuLjFdLCB4WzAuLjJdLCAuLi4sIHhbMS4uMl0sIC4uLl0gaWYgbjwwOyBbb25seSBvZiBsZW5ndGggbl0gb3RoZXJ3aXNlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpbmZpeGVzPFQ+KHg6IFRbXSwgbjogbnVtYmVyPS0xKTogVFtdW10ge1xuICByZXR1cm4gWy4uLmlpbmZpeGVzKHgsIG4pXTtcbn1cblxuXG4vKipcbiAqIExpc3QgYWxsIHBvc3NpYmxlIGluZml4ZXMuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIG4gbnVtYmVyIG9mIHZhbHVlcyBbLTEg4oeSIGFueV1cbiAqIEByZXR1cm5zIFtdLCB4WzAuLjFdLCB4WzAuLjJdLCAuLi4sIHhbMS4uMl0sIC4uLiBpZiBuPDA7IG9ubHkgb2YgbGVuZ3RoIG4gb3RoZXJ3aXNlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpaW5maXhlczxUPih4OiBUW10sIG46IG51bWJlcj0tMSk6IEl0ZXJhYmxlSXRlcmF0b3I8VFtdPiB7XG4gIGlmIChuPj0wKSByZXR1cm4gaW5maXhlc0ZpeGVkKHgsIG4pO1xuICBlbHNlICAgICAgcmV0dXJuIGluZml4ZXNBbGwoeCk7XG59XG5cbmZ1bmN0aW9uKiBpbmZpeGVzRml4ZWQ8VD4oeDogVFtdLCBuOiBudW1iZXIpOiBJdGVyYWJsZUl0ZXJhdG9yPFRbXT4ge1xuICBjb25zdCBYID0geC5sZW5ndGg7XG4gIGlmIChuPlgpICAgcmV0dXJuO1xuICBpZiAobj09PTApIHsgeWllbGQgW107IHJldHVybjsgfVxuICBmb3IgKGxldCBpPTAsIEk9WC1uKzE7IGk8STsgKytpKVxuICAgIHlpZWxkIHguc2xpY2UoaSwgaStuKTtcbn1cblxuZnVuY3Rpb24qIGluZml4ZXNBbGw8VD4oeDogVFtdKTogSXRlcmFibGVJdGVyYXRvcjxUW10+IHtcbiAgY29uc3QgWCA9IHgubGVuZ3RoOyB5aWVsZCBbXTtcbiAgZm9yIChsZXQgaT0wOyBpPFg7ICsraSkge1xuICAgIGZvciAobGV0IGo9aSsxOyBqPD1YOyArK2opXG4gICAgICB5aWVsZCB4LnNsaWNlKGksIGopO1xuICB9XG59XG5cblxuLyoqXG4gKiBPYnRhaW4gYWxsIHBvc3NpYmxlIHN1YnNlcXVlbmNlcy5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gbiBudW1iZXIgb2YgdmFsdWVzIFstMSDih5IgYW55XVxuICogQHJldHVybnMgW2VsZW1lbnRzIHNlbGVjdGVkIGJ5IGJpdCBmcm9tIDAuLjJefHh8XSBpZiBuPDA7IFtvbmx5IG9mIGxlbmd0aCBuXSBvdGhlcndpc2VcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHN1YnNlcXVlbmNlczxUPih4OiBUW10sIG46IG51bWJlcj0tMSk6IFRbXVtdIHtcbiAgcmV0dXJuIFsuLi5pc3Vic2VxdWVuY2VzKHgsIG4pXTtcbn1cblxuXG4vKipcbiAqIExpc3QgYWxsIHBvc3NpYmxlIHN1YnNlcXVlbmNlcy5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gbiBudW1iZXIgb2YgdmFsdWVzIFstMSDih5IgYW55XVxuICogQHJldHVybnMgZWxlbWVudHMgc2VsZWN0ZWQgYnkgYml0IGZyb20gMC4uMl58eHwgaWYgbjwwOyBvbmx5IG9mIGxlbmd0aCBuIG90aGVyd2lzZVxuICovXG5leHBvcnQgZnVuY3Rpb24qIGlzdWJzZXF1ZW5jZXM8VD4oeDogVFtdLCBuOiBudW1iZXI9LTEpOiBJdGVyYWJsZUl0ZXJhdG9yPFRbXT4ge1xuICBjb25zdCBYID0geC5sZW5ndGg7XG4gIGlmIChuPlgpIHJldHVybjtcbiAgaWYgKG49PT1YKSAgICAgICAgICB7IHlpZWxkIHg7ICByZXR1cm47IH1cbiAgaWYgKG49PT0wIHx8IFg9PT0wKSB7IHlpZWxkIFtdOyByZXR1cm47IH1cbiAgY29uc3QgeSA9IHguc2xpY2UoMCwgLTEpO1xuICB5aWVsZCogaXN1YnNlcXVlbmNlcyh5LCBuKTtcbiAgZm9yIChjb25zdCBzIG9mIGlzdWJzZXF1ZW5jZXMoeSwgbi0xKSkge1xuICAgIHMucHVzaCh4W1gtMV0pO1xuICAgIHlpZWxkIHM7XG4gIH1cbn1cblxuXG4vKipcbiAqIE9idGFpbiBhbGwgcG9zc2libGUgcGVybXV0YXRpb25zLlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSBuIG51bWJlciBvZiB2YWx1ZXMgWy0xIOKHkiBhbnldXG4gKiBAcmV0dXJucyBbW10sIGFycmFuZ2VtZW50cyBvZiBsZW5ndGggMSwgb2YgbGVuZ3RoIDIsIC4uLl0gaWYgbjwwOyBbb25seSBvZiBsZW5ndGggbl0gb3RoZXJ3aXNlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwZXJtdXRhdGlvbnM8VD4oeDogVFtdLCBuOiBudW1iZXI9LTEpOiBUW11bXSB7XG4gIHJldHVybiBbLi4uaXBlcm11dGF0aW9ucyh4LCBuKV07XG59XG5cblxuLyoqXG4gKiBMaXN0IGFsbCBwb3NzaWJsZSBwZXJtdXRhdGlvbnMuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIG4gbnVtYmVyIG9mIHZhbHVlcyBbLTEg4oeSIGFueV1cbiAqIEByZXR1cm5zIFtdLCBhcnJhbmdlbWVudHMgb2YgbGVuZ3RoIDEsIG9mIGxlbmd0aCAyLCAuLi4gaWYgbjwwOyBvbmx5IG9mIGxlbmd0aCBuIG90aGVyd2lzZVxuICovXG5leHBvcnQgZnVuY3Rpb24qIGlwZXJtdXRhdGlvbnM8VD4oeDogVFtdLCBuOiBudW1iZXI9LTEpOiBJdGVyYWJsZUl0ZXJhdG9yPFRbXT4ge1xuICBjb25zdCBYID0geC5sZW5ndGg7XG4gIGlmIChuPlgpIHJldHVybjtcbiAgbGV0ICAgaSA9IG48MD8gMCA6IG47XG4gIGNvbnN0IEkgPSBuPDA/IFggOiBuXG4gIGZvciAoOyBpPD1JOyArK2kpXG4gICAgeWllbGQqIGlwZXJtdXRhdGlvbnNGaXhlZCh4LCBpKTtcbn1cblxuZnVuY3Rpb24qIGlwZXJtdXRhdGlvbnNGaXhlZDxUPih4OiBUW10sIG46IG51bWJlcik6IEl0ZXJhYmxlSXRlcmF0b3I8VFtdPiB7XG4gIGNvbnN0IFggPSB4Lmxlbmd0aDtcbiAgaWYgKFg9PT0wIHx8IG49PT0wKSB7IHlpZWxkIFtdOyByZXR1cm47IH1cbiAgZm9yIChsZXQgaT0wOyBpPFg7ICsraSkge1xuICAgIGNvbnN0IHkgPSBzcGxpY2UoeCwgaSwgMSk7XG4gICAgZm9yIChjb25zdCBwIG9mIGlwZXJtdXRhdGlvbnNGaXhlZCh5LCBuLTEpKVxuICAgICAgeWllbGQgW3hbaV0sIC4uLnBdO1xuICB9XG59XG5cblxuLyoqXG4gKiBGaW5kIGZpcnN0IGluZGV4IG9mIGFuIGluZml4LlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSB5IHNlYXJjaCBpbmZpeFxuICogQHBhcmFtIGZjIGNvbXBhcmUgZnVuY3Rpb24gKGEsIGIpXG4gKiBAcGFyYW0gZm0gbWFwIGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHJldHVybnMgZmlyc3QgaSB8IHhbaS4uaSt8eXxdID0geSBlbHNlIC0xXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzZWFyY2hJbmZpeDxULCBVPVQ+KHg6IFRbXSwgeTogVFtdLCBmYzogQ29tcGFyZUZ1bmN0aW9uPFR8VT4gfCBudWxsPW51bGwsIGZtOiBNYXBGdW5jdGlvbjxULCBUfFU+IHwgbnVsbD1udWxsKTogbnVtYmVyIHtcbiAgZmMgPSBmYyB8fCBDT01QQVJFO1xuICBmbSA9IGZtIHx8IElERU5USVRZO1xuICBjb25zdCBYID0geC5sZW5ndGgsIFkgPSB5Lmxlbmd0aDtcbiAgZm9yIChsZXQgaT0wOyBpPD1YLVk7ICsraSlcbiAgICBpZiAoaXNJbmZpeEF0KHgsIHksIGksIGZjLCBmbSkpIHJldHVybiBpO1xuICByZXR1cm4gLTE7XG59XG5cblxuLyoqXG4gKiBGaW5kIGxhc3QgaW5kZXggb2YgYW4gaW5maXguXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIHkgc2VhcmNoIGluZml4XG4gKiBAcGFyYW0gZmMgY29tcGFyZSBmdW5jdGlvbiAoYSwgYilcbiAqIEBwYXJhbSBmbSBtYXAgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcmV0dXJucyBmaXJzdCBpIHwgeFtpLi5pK3x5fF0gPSB5IGVsc2UgLTFcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNlYXJjaEluZml4UmlnaHQ8VCwgVT1UPih4OiBUW10sIHk6IFRbXSwgZmM6IENvbXBhcmVGdW5jdGlvbjxUfFU+IHwgbnVsbD1udWxsLCBmbTogTWFwRnVuY3Rpb248VCwgVHxVPiB8IG51bGw9bnVsbCk6IG51bWJlciB7XG4gIGZjID0gZmMgfHwgQ09NUEFSRTtcbiAgZm0gPSBmbSB8fCBJREVOVElUWTtcbiAgY29uc3QgWCA9IHgubGVuZ3RoLCBZID0geS5sZW5ndGg7XG4gIGZvciAobGV0IGk9WC1ZOyBpPj0wOyAtLWkpXG4gICAgaWYgKGlzSW5maXhBdCh4LCB5LCBpLCBmYywgZm0pKSByZXR1cm4gaTtcbiAgcmV0dXJuIC0xO1xufVxuXG5cbi8qKlxuICogRmluZCBpbmRpY2VzIG9mIGFuIGluZml4LlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSB5IHNlYXJjaCBpbmZpeFxuICogQHBhcmFtIGZjIGNvbXBhcmUgZnVuY3Rpb24gKGEsIGIpXG4gKiBAcGFyYW0gZm0gbWFwIGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHJldHVybnMgaeKCgCwgaeKCgSwgLi4uIHwgeFtqLi5qK3x5fF0gPSB5OyBqIOKIiCBbaeKCgCwgaeKCgSwgLi4uXVxuICovXG5leHBvcnQgZnVuY3Rpb24gc2VhcmNoSW5maXhBbGw8VCwgVT1UPih4OiBUW10sIHk6IFRbXSwgZmM6IENvbXBhcmVGdW5jdGlvbjxUfFU+IHwgbnVsbD1udWxsLCBmbTogTWFwRnVuY3Rpb248VCwgVHxVPiB8IG51bGw9bnVsbCk6IG51bWJlcltdIHtcbiAgZmMgPSBmYyB8fCBDT01QQVJFO1xuICBmbSA9IGZtIHx8IElERU5USVRZO1xuICBjb25zdCBYID0geC5sZW5ndGgsIFkgPSB5Lmxlbmd0aCwgYSA9IFtdO1xuICBmb3IgKGxldCBpPTA7IGk8PVgtWTsgKytpKVxuICAgIGlmIChpc0luZml4QXQoeCwgeSwgaSwgZmMsIGZtKSkgYS5wdXNoKGkpO1xuICByZXR1cm4gYTtcbn1cblxuXG5mdW5jdGlvbiBpc0luZml4QXQ8VCwgVT1UPih4OiBUW10sIHk6IFRbXSwgaTogbnVtYmVyLCBmYzogQ29tcGFyZUZ1bmN0aW9uPFR8VT4sIGZtOiBNYXBGdW5jdGlvbjxULCBUfFU+KTogYm9vbGVhbiB7XG4gIGNvbnN0IFkgPSB5Lmxlbmd0aDtcbiAgZm9yIChsZXQgaj0wOyBqPFk7ICsraikge1xuICAgIGNvbnN0IHd4ID0gZm0oeFtpK2pdLCBpK2osIHgpO1xuICAgIGNvbnN0IHd5ID0gZm0oeVtqXSwgaiwgeSk7XG4gICAgaWYgKGZjKHd4LCB3eSkhPT0wKSByZXR1cm4gZmFsc2U7XG4gIH1cbiAgcmV0dXJuIHRydWU7XG59XG5cblxuLyoqXG4gKiBGaW5kIGZpcnN0IGluZGV4IG9mIGEgc3Vic2VxdWVuY2UuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIHkgc2VhcmNoIHN1YnNlcXVlbmNlXG4gKiBAcGFyYW0gZmMgY29tcGFyZSBmdW5jdGlvbiAoYSwgYilcbiAqIEBwYXJhbSBmbSBtYXAgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcmV0dXJucyBiZWdpbiBpbmRleCBvZiBzdWJzZXF1ZW5jZSwgLTEgaWYgbm90IGZvdW5kXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzZWFyY2hTdWJzZXF1ZW5jZTxULCBVPVQ+KHg6IFRbXSwgeTogVFtdLCBmYzogQ29tcGFyZUZ1bmN0aW9uPFR8VT4gfCBudWxsPW51bGwsIGZtOiBNYXBGdW5jdGlvbjxULCBUfFU+IHwgbnVsbD1udWxsKTogbnVtYmVyIHtcbiAgZmMgPSBmYyB8fCBDT01QQVJFO1xuICBmbSA9IGZtIHx8IElERU5USVRZO1xuICBjb25zdCB5MSA9IFsuLi55XS5tYXAoZm0pLCBZID0geTEubGVuZ3RoO1xuICBsZXQgYSA9IC0xLCBpID0gLTEsIGogPSAwO1xuICBmb3IgKGNvbnN0IHZ4IG9mIHgpIHtcbiAgICBjb25zdCB3eCA9IGZtKHZ4LCArK2ksIHgpO1xuICAgIGlmIChmYyh3eCwgeTFbal0pIT09MCkgY29udGludWU7XG4gICAgaWYgKGE8MCkgYSA9IGk7XG4gICAgaWYgKCsraj49WSkgcmV0dXJuIGE7XG4gIH1cbiAgcmV0dXJuIC0xO1xufVxuLy8gI2VuZHJlZ2lvblxuXG5cblxuXG4vLyAjcmVnaW9uIFJBTkRPTSBBUlJBTkdFTUVOVFNcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4vKipcbiAqIFBpY2sgYW4gYXJiaXRyYXJ5IHZhbHVlLlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSBmciByYW5kb20gbnVtYmVyIGdlbmVyYXRvciAoWzAsIDEpKVxuICogQHJldHVybnMgeFtpXSB8IGkg4oiIIDAuLnx4fFxuICovXG5leHBvcnQgZnVuY3Rpb24gcmFuZG9tVmFsdWU8VD4oeDogVFtdLCBmcjogUmVhZEZ1bmN0aW9uPG51bWJlcj4gfCBudWxsPU1hdGgucmFuZG9tKTogVCB7XG4gIGZyID0gZnIgfHwgTWF0aC5yYW5kb207XG4gIGNvbnN0IGkgPSBNYXRoLmZsb29yKGZyKCkgKiB4Lmxlbmd0aCk7XG4gIHJldHVybiB4W2ldO1xufVxuZXhwb3J0IHtyYW5kb21WYWx1ZSBhcyB2YWx1ZX07ICAvLyBERVBSRUNBVEVEXG5cblxuLyoqXG4gKiBQaWNrIGFuIGFyYml0cmFyeSBwcmVmaXguXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIG4gbnVtYmVyIG9mIHZhbHVlcyBbLTEg4oeSIGFueV1cbiAqIEBwYXJhbSBmciByYW5kb20gbnVtYmVyIGdlbmVyYXRvciAoWzAsIDEpKVxuICogQHJldHVybnMgeFsuLmldIGlmIG48MDsgeFsuLm5dIG90aGVyd2lzZSB8IGkg4oiIIDAuLnx4fFxuICovXG5leHBvcnQgZnVuY3Rpb24gcmFuZG9tUHJlZml4PFQ+KHg6IFRbXSwgbjogbnVtYmVyPS0xLCBmcjogUmVhZEZ1bmN0aW9uPG51bWJlcj4gfCBudWxsPU1hdGgucmFuZG9tKTogVFtdIHwgbnVsbCB7XG4gIGZyID0gZnIgfHwgTWF0aC5yYW5kb207XG4gIGNvbnN0IFggPSB4Lmxlbmd0aDtcbiAgaWYgKG4+WCkgcmV0dXJuIG51bGw7XG4gIG4gPSBuPj0wPyBuIDogTWF0aC5mbG9vcigoWCsxKSpmcigpKTtcbiAgcmV0dXJuIHguc2xpY2UoMCwgbik7XG59XG5leHBvcnQge3JhbmRvbVByZWZpeCBhcyBwcmVmaXh9OyAgLy8gREVQUkVDQVRFRFxuXG5cbi8qKlxuICogUGljayBhbiBhcmJpdHJhcnkgc3VmZml4LlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSBuIG51bWJlciBvZiB2YWx1ZXMgWy0xIOKHkiBhbnldXG4gKiBAcGFyYW0gZnIgcmFuZG9tIG51bWJlciBnZW5lcmF0b3IgKFswLCAxKSlcbiAqIEByZXR1cm5zIHhbfHh8LWkuLl0gaWYgbjwwOyB4W3x4fC1uLi5dIG90aGVyd2lzZSB8IGkg4oiIIDAuLnx4fFxuICovXG5leHBvcnQgZnVuY3Rpb24gcmFuZG9tU3VmZml4PFQ+KHg6IFRbXSwgbjogbnVtYmVyPS0xLCBmcjogUmVhZEZ1bmN0aW9uPG51bWJlcj4gfCBudWxsPU1hdGgucmFuZG9tKTogVFtdIHwgbnVsbCB7XG4gIGNvbnN0IFggPSB4Lmxlbmd0aDtcbiAgaWYgKG4+WCkgcmV0dXJuIG51bGw7XG4gIG4gPSBuPj0wPyBuIDogTWF0aC5mbG9vcigoWCsxKSooZnIgYXMgUmVhZEZ1bmN0aW9uPG51bWJlcj4pKCkpO1xuICByZXR1cm4geC5zbGljZShYLW4pO1xufVxuZXhwb3J0IHtyYW5kb21TdWZmaXggYXMgc3VmZml4fTsgIC8vIERFUFJFQ0FURURcblxuXG4vKipcbiAqIFBpY2sgYW4gYXJiaXRyYXJ5IGluZml4LlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSBuIG51bWJlciBvZiB2YWx1ZXMgWy0xIOKHkiBhbnldXG4gKiBAcGFyYW0gZnIgcmFuZG9tIG51bWJlciBnZW5lcmF0b3IgKFswLCAxKSlcbiAqIEByZXR1cm5zIHhbaS4ual0gaWYgbjwwOyB4W2kuLmkrbl0gb3RoZXJ3aXNlIHwgaSwgaiDiiIggMC4ufHh8XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByYW5kb21JbmZpeDxUPih4OiBUW10sIG46IG51bWJlcj0tMSwgZnI6IFJlYWRGdW5jdGlvbjxudW1iZXI+IHwgbnVsbD1NYXRoLnJhbmRvbSk6IFRbXSB8IG51bGwge1xuICBjb25zdCBYID0geC5sZW5ndGg7XG4gIGlmIChuPlgpIHJldHVybiBudWxsO1xuICBuID0gbj49MD8gbiA6IHJhbmRvbUluZml4TGVuZ3RoKFgsIChmciBhcyBSZWFkRnVuY3Rpb248bnVtYmVyPikoKSk7XG4gIGNvbnN0IGkgPSBNYXRoLmZsb29yKChYKzEtbikqKGZyIGFzIFJlYWRGdW5jdGlvbjxudW1iZXI+KSgpKTtcbiAgcmV0dXJuIHguc2xpY2UoaSwgaStuKTtcbn1cbmV4cG9ydCB7cmFuZG9tSW5maXggYXMgaW5maXh9OyAgLy8gREVQUkVDQVRFRFxuXG4vLyBOb3QgYWxsIGluZml4IGxlbmd0aHMgYXJlIGVxdWFsbHkgcHJvYWJsZS5cbmZ1bmN0aW9uIHJhbmRvbUluZml4TGVuZ3RoKFg6IG51bWJlciwgcjogbnVtYmVyKTogbnVtYmVyIHtcbiAgY29uc3QgQyA9IDAuNSAqIFgqKFgrMSkgKyAxO1xuICBjb25zdCBuID0gMC41ICogTWF0aC5zcXJ0KDEgKyA4KnIqQykgLSAwLjU7XG4gIHJldHVybiBYKzEgIC0gTWF0aC5mbG9vcihuKzEpO1xufVxuXG5cbi8qKlxuICogUGljayBhbiBhcmJpdHJhcnkgc3Vic2VxdWVuY2UuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIG4gbnVtYmVyIG9mIHZhbHVlcyBbLTEg4oeSIGFueV1cbiAqIEBwYXJhbSBmciByYW5kb20gbnVtYmVyIGdlbmVyYXRvciAoWzAsIDEpKVxuICogQHJldHVybnMgeFtpLCBqLCAuLi5dIHwgW2ksIGosIC4uLl0gPSBpczsgfGlzfCA9IHx4fCBpZiBuPDAgZWxzZSBuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByYW5kb21TdWJzZXF1ZW5jZTxUPih4OiBUW10sIG46IG51bWJlcj0tMSwgZnI6IFJlYWRGdW5jdGlvbjxudW1iZXI+IHwgbnVsbD1NYXRoLnJhbmRvbSk6IFRbXSB8IG51bGwge1xuICBjb25zdCBYID0geC5sZW5ndGg7XG4gIGlmIChuPlgpICByZXR1cm4gbnVsbDtcbiAgaWYgKG4+PTApIHJldHVybiByYW5kb21TdWJzZXF1ZW5jZUZpeGVkKHgsIG4sIGZyIGFzIFJlYWRGdW5jdGlvbjxudW1iZXI+KTtcbiAgZWxzZSAgICAgIHJldHVybiByYW5kb21TdWJzZXF1ZW5jZUFsbCh4LCBmciBhcyBSZWFkRnVuY3Rpb248bnVtYmVyPik7XG59XG5leHBvcnQge3JhbmRvbVN1YnNlcXVlbmNlIGFzIHN1YnNlcXVlbmNlfTsgIC8vIERFUFJFQ0FURURcblxuZnVuY3Rpb24gcmFuZG9tU3Vic2VxdWVuY2VGaXhlZDxUPih4OiBUW10sIG46IG51bWJlciwgZnI6IFJlYWRGdW5jdGlvbjxudW1iZXI+KTogVFtdIHtcbiAgY29uc3QgaXMgPSBmcm9tUmFuZ2UoMCwgeC5sZW5ndGgpO1xuICByYW5kb21QZXJtdXRhdGlvbiQoaXMsIG4sIGZyKS5zb3J0KCk7XG4gIHJldHVybiBnZXRBbGwoeCwgaXMpO1xufVxuXG5mdW5jdGlvbiByYW5kb21TdWJzZXF1ZW5jZUFsbDxUPih4OiBUW10sIGZyOiBSZWFkRnVuY3Rpb248bnVtYmVyPik6IFRbXSB7XG4gIGNvbnN0IGE6IFRbXSA9IFtdO1xuICBmb3IgKGNvbnN0IHYgb2YgeClcbiAgICBpZiAoZnIoKTwwLjUpIGEucHVzaCh2KTtcbiAgcmV0dXJuIGE7XG59XG5cblxuLyoqXG4gKiBQaWNrIGFuIGFyYml0cmFyeSBwZXJtdXRhdGlvbi5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gbiBudW1iZXIgb2YgdmFsdWVzIFstMSDih5IgYW55XVxuICogQHBhcmFtIGZyIHJhbmRvbSBudW1iZXIgZ2VuZXJhdG9yIChbMCwgMSkpXG4gKiBAcmV0dXJucyB4JyB8IHgnID0geDsgdmFsdWVzIGFyZSByYW5kb21seSBzaHVmZmxlZFxuICovXG5leHBvcnQgZnVuY3Rpb24gcmFuZG9tUGVybXV0YXRpb248VD4oeDogVFtdLCBuOiBudW1iZXI9LTEsIGZyOiBSZWFkRnVuY3Rpb248bnVtYmVyPiB8IG51bGw9TWF0aC5yYW5kb20pOiBUW10gfCBudWxsIHtcbiAgY29uc3QgWCA9IHgubGVuZ3RoO1xuICBpZiAobj5YKSByZXR1cm4gbnVsbDtcbiAgcmV0dXJuIHJhbmRvbVBlcm11dGF0aW9uJCh4LnNsaWNlKCksIG4sIGZyKTtcbn1cbmV4cG9ydCB7cmFuZG9tUGVybXV0YXRpb24gYXMgcGVybXV0YXRpb259OyAgLy8gREVQUkVDQVRFRFxuXG5cbi8qKlxuICogUGljayBhbiBhcmJpdHJhcnkgcGVybXV0YXRpb24hXG4gKiBAcGFyYW0geCBhbiBhcnJheSAodXBkYXRlZCEpXG4gKiBAcGFyYW0gbiBudW1iZXIgb2YgdmFsdWVzIFstMSDih5IgYW55XVxuICogQHBhcmFtIGZyIHJhbmRvbSBudW1iZXIgZ2VuZXJhdG9yIChbMCwgMSkpXG4gKiBAcmV0dXJucyB4IHwgdmFsdWVzIGFyZSByYW5kb21seSBzaHVmZmxlZFxuICovXG5leHBvcnQgZnVuY3Rpb24gcmFuZG9tUGVybXV0YXRpb24kPFQ+KHg6IFRbXSwgbjogbnVtYmVyPS0xLCBmcjogUmVhZEZ1bmN0aW9uPG51bWJlcj4gfCBudWxsPU1hdGgucmFuZG9tKTogVFtdIHtcbiAgZnIgPSBmciB8fCBNYXRoLnJhbmRvbTtcbiAgY29uc3QgWCA9IHgubGVuZ3RoO1xuICBpZiAobj5YKSByZXR1cm4geDtcbiAgbiA9IG4+PTA/IG4gOiBNYXRoLmZsb29yKChYKzEpKmZyKCkpO1xuICBmb3IgKGxldCBpPTA7IGk8bjsgKytpKSB7XG4gICAgY29uc3QgaiA9IGkgKyBNYXRoLmZsb29yKChYLWkpKmZyKCkpO1xuICAgIGNvbnN0IHQgPSB4W2ldOyB4W2ldID0geFtqXTsgeFtqXSA9IHQ7XG4gIH1cbiAgeC5sZW5ndGggPSBuO1xuICByZXR1cm4geDtcbn1cbmV4cG9ydCB7cmFuZG9tUGVybXV0YXRpb24kIGFzIHBlcm11dGF0aW9uJH07ICAvLyBERVBSRUNBVEVEXG5leHBvcnQge3JhbmRvbVBlcm11dGF0aW9uJCBhcyBwZXJtdXRlJH07XG5leHBvcnQge3JhbmRvbVBlcm11dGF0aW9uJCBhcyBzaHVmZmxlJH07XG4vLyAtIGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0Zpc2hlcuKAk1lhdGVzX3NodWZmbGVcbi8vICNlbmRyZWdpb25cblxuXG5cblxuLy8gI3JlZ2lvbiBGSU5EXG4vLyAtLS0tLS0tLS0tLS1cblxuLyoqXG4gKiBGaW5kIGZpcnN0IHZhbHVlIHBhc3NpbmcgYSB0ZXN0LlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSBmdCB0ZXN0IGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHJldHVybnMgZmlyc3QgdiB8IGZ0KHYpID0gdHJ1ZTsgdiDiiIggeFxuICovXG5leHBvcnQgZnVuY3Rpb24gZmluZDxUPih4OiBUW10sIGZ0OiBUZXN0RnVuY3Rpb248VD4pOiBUIHtcbiAgcmV0dXJuIHguZmluZChmdCkgYXMgVDtcbn1cblxuXG4vKipcbiAqIEZpbmQgbGFzdCB2YWx1ZSBwYXNzaW5nIGEgdGVzdC5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gZnQgdGVzdCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEByZXR1cm5zIGxhc3QgdiB8IGZ0KHYpID0gdHJ1ZTsgdiDiiIggeFxuICovXG5leHBvcnQgZnVuY3Rpb24gZmluZFJpZ2h0PFQ+KHg6IFRbXSwgZnQ6IFRlc3RGdW5jdGlvbjxUPik6IFQge1xuICBmb3IgKGxldCBpPXgubGVuZ3RoLTE7IGk+PTA7IC0taSlcbiAgICBpZiAoZnQoeFtpXSwgaSwgeCkpIHJldHVybiB4W2ldO1xuICByZXR1cm4gdW5kZWZpbmVkIGFzIHVua25vd24gYXMgVDtcbn1cbi8vICNlbmRyZWdpb25cblxuXG5cblxuLy8gI3JlZ2lvbiBUQUtFL0RST1Bcbi8vIC0tLS0tLS0tLS0tLS0tLS0tXG5cbi8qKlxuICogS2VlcCBmaXJzdCBuIHZhbHVlcyBvbmx5LlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSBuIG51bWJlciBvZiB2YWx1ZXMgWzFdXG4gKiBAcmV0dXJucyB4WzAuLm5dXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0YWtlPFQ+KHg6IFRbXSwgbjogbnVtYmVyPTEpOiBUW10ge1xuICBuID0gTWF0aC5tYXgobiwgMCk7XG4gIHJldHVybiB4LnNsaWNlKDAsIG4pO1xufVxuZXhwb3J0IHt0YWtlIGFzIGxlZnR9O1xuXG5cbi8qKlxuICogS2VlcCBsYXN0IG4gdmFsdWVzIG9ubHkuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIG4gbnVtYmVyIG9mIHZhbHVlcyBbMV1cbiAqIEByZXR1cm5zIHhbMC4ubl1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRha2VSaWdodDxUPih4OiBUW10sIG46IG51bWJlcj0xKTogVFtdIHtcbiAgY29uc3QgWCA9IHgubGVuZ3RoO1xuICBuID0gTWF0aC5taW4oTWF0aC5tYXgobiwgMCksIFgpO1xuICByZXR1cm4geC5zbGljZShYLW4pO1xufVxuZXhwb3J0IHt0YWtlUmlnaHQgYXMgcmlnaHR9O1xuXG5cbi8qKlxuICogS2VlcCB2YWx1ZXMgZnJvbSBsZWZ0LCB3aGlsZSBhIHRlc3QgcGFzc2VzLlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSBmdCB0ZXN0IGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHJldHVybnMgeFswLi5ULTFdIHwgZnQoeFtpXSkgPSB0cnVlIOKIgCBpIOKIiCBbMCwgVC0xXSAmIGZ0KHhbVF0pID0gZmFsc2VcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRha2VXaGlsZTxUPih4OiBUW10sIGZ0OiBUZXN0RnVuY3Rpb248VD4pOiBUW10ge1xuICByZXR1cm4geC5zbGljZSgwLCBzY2FuV2hpbGUoeCwgZnQpKTtcbn1cblxuXG4vKipcbiAqIEtlZXAgdmFsdWVzIGZyb20gcmlnaHQsIHdoaWxlIGEgdGVzdCBwYXNzZXMuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIGZ0IHRlc3QgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcmV0dXJucyB4W1QuLl0gfCBmdCh4W2ldKSA9IHRydWUg4oiAIGkg4oiIIFtULCB8eHwtMV0gJiBmdCh4W1QtMV0pID0gZmFsc2VcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRha2VXaGlsZVJpZ2h0PFQ+KHg6IFRbXSwgZnQ6IFRlc3RGdW5jdGlvbjxUPik6IFRbXSB7XG4gIHJldHVybiB4LnNsaWNlKHNjYW5XaGlsZVJpZ2h0KHgsIGZ0KSk7XG59XG5cblxuLyoqXG4gKiBEaXNjYXJkIGZpcnN0IG4gdmFsdWVzIG9ubHkuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIG4gbnVtYmVyIG9mIHZhbHVlcyBbMV1cbiAqIEByZXR1cm5zIHhbbi4uXVxuICovXG5leHBvcnQgZnVuY3Rpb24gZHJvcDxUPih4OiBUW10sIG46IG51bWJlcj0xKTogVFtdIHtcbiAgbiA9IE1hdGgubWF4KG4sIDApO1xuICByZXR1cm4geC5zbGljZShuKTtcbn1cblxuXG4vKipcbiAqIERpc2NhcmQgbGFzdCBuIHZhbHVlcyBvbmx5LlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSBuIG51bWJlciBvZiB2YWx1ZXMgWzFdXG4gKiBAcmV0dXJucyB4WzAuLi1uXVxuICovXG5leHBvcnQgZnVuY3Rpb24gZHJvcFJpZ2h0PFQ+KHg6IFRbXSwgbjogbnVtYmVyPTEpOiBUW10ge1xuICBjb25zdCBYID0geC5sZW5ndGg7XG4gIG4gPSBNYXRoLm1pbihNYXRoLm1heChuLCAwKSwgWCk7XG4gIHJldHVybiB4LnNsaWNlKDAsIFgtbik7XG59XG5cblxuLyoqXG4gKiBEaXNjYXJkIHZhbHVlcyBmcm9tIGxlZnQsIHdoaWxlIGEgdGVzdCBwYXNzZXMuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIGZ0IHRlc3QgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcmV0dXJucyB4W1QuLl0gfCBmdCh4W2ldKSA9IHRydWUg4oiAIGkg4oiIIFswLCBULTFdICYgZnQoeFtUXSkgPSBmYWxzZVxuICovXG5leHBvcnQgZnVuY3Rpb24gZHJvcFdoaWxlPFQ+KHg6IFRbXSwgZnQ6IFRlc3RGdW5jdGlvbjxUPik6IFRbXSB7XG4gIHJldHVybiB4LnNsaWNlKHNjYW5XaGlsZSh4LCBmdCkpO1xufVxuXG5cbi8qKlxuICogRGlzY2FyZCB2YWx1ZXMgZnJvbSByaWdodCwgd2hpbGUgYSB0ZXN0IHBhc3Nlcy5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gZnQgdGVzdCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEByZXR1cm5zIHhbMC4uVC0xXSB8IGZ0KHhbaV0pID0gdHJ1ZSDiiIAgaSDiiIggW1QsIHx4fC0xXSAmIGZ0KHhbVC0xXSkgPSBmYWxzZVxuICovXG5leHBvcnQgZnVuY3Rpb24gZHJvcFdoaWxlUmlnaHQ8VD4oeDogVFtdLCBmdDogVGVzdEZ1bmN0aW9uPFQ+KTogVFtdIHtcbiAgcmV0dXJuIHguc2xpY2UoMCwgc2NhbldoaWxlUmlnaHQoeCwgZnQpKTtcbn1cbi8vICNlbmRyZWdpb25cblxuXG5cblxuLy8gI3JlZ2lvbiBTQ0FOXG4vLyAtLS0tLS0tLS0tLS1cblxuLyoqXG4gKiBTY2FuIGZyb20gbGVmdCwgd2hpbGUgYSB0ZXN0IHBhc3Nlcy5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gZnQgdGVzdCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEByZXR1cm5zIGZpcnN0IGluZGV4IHdoZXJlIHRlc3QgZmFpbHNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNjYW5XaGlsZTxUPih4OiBUW10sIGZ0OiBUZXN0RnVuY3Rpb248VD4pOiBudW1iZXIge1xuICBsZXQgaSA9IC0xO1xuICBmb3IgKGNvbnN0IHYgb2YgeClcbiAgICBpZiAoIWZ0KHYsICsraSwgeCkpIHJldHVybiBpO1xuICByZXR1cm4gKytpO1xufVxuXG5cbi8qKlxuICogU2NhbiBmcm9tIHJpZ2h0LCB3aGlsZSBhIHRlc3QgcGFzc2VzLlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSBmdCB0ZXN0IGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHJldHVybnMgZmlyc3QgaW5kZXggd2hlcmUgdGVzdCBwYXNzZXMgdGlsbCBlbmRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNjYW5XaGlsZVJpZ2h0PFQ+KHg6IFRbXSwgZnQ6IFRlc3RGdW5jdGlvbjxUPik6IG51bWJlciB7XG4gIGxldCBpID0geC5sZW5ndGgtMTtcbiAgZm9yICg7IGk+PTA7IC0taSlcbiAgICBpZiAoIWZ0KHhbaV0sIGksIHgpKSBicmVhaztcbiAgcmV0dXJuICsraTtcbn1cblxuXG4vKipcbiAqIFNjYW4gZnJvbSBsZWZ0LCB1bnRpbCBhIHRlc3QgcGFzc2VzLlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSBmdCB0ZXN0IGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHJldHVybnMgZmlyc3QgaW5kZXggd2hlcmUgdGVzdCBwYXNzZXNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNjYW5VbnRpbDxUPih4OiBUW10sIGZ0OiBUZXN0RnVuY3Rpb248VD4pOiBudW1iZXIge1xuICBsZXQgaSA9IC0xO1xuICBmb3IgKGNvbnN0IHYgb2YgeClcbiAgICBpZiAoZnQodiwgKytpLCB4KSkgcmV0dXJuIGk7XG4gIHJldHVybiArK2k7XG59XG5cblxuLyoqXG4gKiBTY2FuIGZyb20gcmlnaHQsIHVudGlsIGEgdGVzdCBwYXNzZXMuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIGZ0IHRlc3QgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcmV0dXJucyBmaXJzdCBpbmRleCB3aGVyZSB0ZXN0IGZhaWxzIHRpbGwgZW5kXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzY2FuVW50aWxSaWdodDxUPih4OiBUW10sIGZ0OiBUZXN0RnVuY3Rpb248VD4pOiBudW1iZXIge1xuICBsZXQgaSA9IHgubGVuZ3RoLTE7XG4gIGZvciAoOyBpPj0wOyAtLWkpXG4gICAgaWYgKGZ0KHhbaV0sIGksIHgpKSBicmVhaztcbiAgcmV0dXJuICsraTtcbn1cbi8vICNlbmRyZWdpb25cblxuXG5cblxuLy8gI3JlZ2lvbiBTRUFSQ0hcbi8vIC0tLS0tLS0tLS0tLS0tXG5cbi8qKlxuICogRmluZCBmaXJzdCBpbmRleCBvZiBhIHZhbHVlLlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSB2IHNlYXJjaCB2YWx1ZVxuICogQHBhcmFtIGkgYmVnaW4gaW5kZXggWzBdXG4gKiBAcmV0dXJucyBpbmRleCBvZiB2IGluIHhbaS4uXSBpZiBmb3VuZCBlbHNlIC0xXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpbmRleE9mPFQ+KHg6IFRbXSwgdjogVCwgaTogbnVtYmVyPTApOiBudW1iZXIge1xuICByZXR1cm4geC5pbmRleE9mKHYsIGkpO1xufVxuXG5cbi8qKlxuICogRmluZCBsYXN0IGluZGV4IG9mIGEgdmFsdWUuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIHYgc2VhcmNoIHZhbHVlXG4gKiBAcGFyYW0gaSBiZWdpbiBpbmRleCBbfHh8LTFdXG4gKiBAcmV0dXJucyBsYXN0IGluZGV4IG9mIHYgaW4geFswLi5pXSBpZiBmb3VuZCBlbHNlIC0xXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBsYXN0SW5kZXhPZjxUPih4OiBUW10sIHY6IFQsIGk6IG51bWJlcj14Lmxlbmd0aC0xKTogbnVtYmVyIHtcbiAgcmV0dXJuIHgubGFzdEluZGV4T2YodiwgaSk7XG59XG5cblxuLyoqXG4gKiBGaW5kIGluZGV4IG9mIGZpcnN0IHZhbHVlIHBhc3NpbmcgYSB0ZXN0LlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSBmdCB0ZXN0IGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHJldHVybnMgZmlyc3QgaW5kZXggb2YgdmFsdWUsIC0xIGlmIG5vdCBmb3VuZFxuICovXG5leHBvcnQgZnVuY3Rpb24gc2VhcmNoPFQ+KHg6IFRbXSwgZnQ6IFRlc3RGdW5jdGlvbjxUPik6IG51bWJlciB7XG4gIHJldHVybiB4LmZpbmRJbmRleChmdCk7XG59XG5leHBvcnQge3NlYXJjaCBhcyBmaW5kSW5kZXh9O1xuXG5cbi8qKlxuICogRmluZCBpbmRleCBvZiBsYXN0IHZhbHVlIHBhc3NpbmcgYSB0ZXN0LlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSBmdCB0ZXN0IGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHJldHVybnMgbGFzdCBpbmRleCBvZiB2YWx1ZSwgLTEgaWYgbm90IGZvdW5kXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzZWFyY2hSaWdodDxUPih4OiBUW10sIGZ0OiBUZXN0RnVuY3Rpb248VD4pOiBudW1iZXIge1xuICBmb3IgKGxldCBpPXgubGVuZ3RoLTE7IGk+PTA7IC0taSlcbiAgICBpZiAoZnQoeFtpXSwgaSwgeCkpIHJldHVybiBpO1xuICByZXR1cm4gLTE7XG59XG5leHBvcnQge3NlYXJjaFJpZ2h0IGFzIGZpbmRMYXN0SW5kZXh9O1xuXG5cbi8qKlxuICogRmluZCBpbmRpY2VzIG9mIHZhbHVlcyBwYXNzaW5nIGEgdGVzdC5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gZnQgdGVzdCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEByZXR1cm5zIGluZGljZXMgb2YgdmFsdWVcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNlYXJjaEFsbDxUPih4OiBUW10sIGZ0OiBUZXN0RnVuY3Rpb248VD4pOiBudW1iZXJbXSB7XG4gIGxldCBpID0gLTE7XG4gIGNvbnN0IGE6IG51bWJlcltdID0gW107XG4gIGZvciAoY29uc3QgdiBvZiB4KVxuICAgIGlmIChmdCh2LCArK2ksIHgpKSBhLnB1c2goaSk7XG4gIHJldHVybiBhO1xufVxuLy8gI2VuZHJlZ2lvblxuXG5cblxuXG4vLyAjcmVnaW9uIEZVTkNUSU9OQUxcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLVxuXG4vKipcbiAqIENhbGwgYSBmdW5jdGlvbiBmb3IgZWFjaCB2YWx1ZS5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gZnAgcHJvY2VzcyBmdW5jdGlvbiAodiwgaSwgeClcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGZvckVhY2g8VD4oeDogVFtdLCBmcDogUHJvY2Vzc0Z1bmN0aW9uPFQ+KTogdm9pZCB7XG4gIHguZm9yRWFjaChmcCk7XG59XG5cblxuLyoqXG4gKiBFeGFtaW5lIGlmIGFueSB2YWx1ZSBzYXRpc2ZpZXMgYSB0ZXN0LlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSBmdCB0ZXN0IGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHJldHVybnMgdHJ1ZSBpZiBmdCh24bWiKSA9IHRydWUgZm9yIHNvbWUgduG1oiDiiIggeFxuICovXG5leHBvcnQgZnVuY3Rpb24gc29tZTxUPih4OiBUW10sIGZ0OiBUZXN0RnVuY3Rpb248VD4gfCBudWxsPW51bGwpOiBib29sZWFuIHtcbiAgaWYgKGZ0KSByZXR1cm4geC5zb21lKGZ0KTtcbiAgZWxzZSAgICByZXR1cm4gc29tZUJvb2xlYW4oeCk7XG59XG5leHBvcnQge3NvbWUgYXMgYW55T2Z9O1xuXG5mdW5jdGlvbiBzb21lQm9vbGVhbjxUPih4OiBUW10pOiBib29sZWFuIHtcbiAgY29uc3QgSSA9IHgubGVuZ3RoO1xuICBmb3IgKGxldCBpPTA7IGk8STsgKytpKVxuICAgIGlmICh4W2ldKSByZXR1cm4gdHJ1ZTtcbiAgcmV0dXJuIGZhbHNlO1xufVxuXG5cbi8qKlxuICogRXhhbWluZSBpZiBhbGwgdmFsdWVzIHNhdGlzZnkgYSB0ZXN0LlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSBmdCB0ZXN0IGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHJldHVybnMgdHJ1ZSBpZiBmdCh24bWiKSA9IHRydWUgZm9yIGFsbCB24bWiIOKIiCB4XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBldmVyeTxUPih4OiBUW10sIGZ0OiBUZXN0RnVuY3Rpb248VD4gfCBudWxsPW51bGwpOiBib29sZWFuIHtcbiAgaWYgKGZ0KSByZXR1cm4geC5ldmVyeShmdCk7XG4gIGVsc2UgICAgcmV0dXJuIGV2ZXJ5Qm9vbGVhbih4KTtcbn1cbmV4cG9ydCB7ZXZlcnkgYXMgYWxsT2Z9O1xuXG5mdW5jdGlvbiBldmVyeUJvb2xlYW48VD4oeDogVFtdKTogYm9vbGVhbiB7XG4gIGNvbnN0IEkgPSB4Lmxlbmd0aDtcbiAgZm9yIChsZXQgaT0wOyBpPEk7ICsraSlcbiAgICBpZiAoIXhbaV0pIHJldHVybiBmYWxzZTtcbiAgcmV0dXJuIHRydWU7XG59XG5cblxuLyoqXG4gKiBUcmFuc2Zvcm0gdmFsdWVzIG9mIGFuIGFycmF5LlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSBmbSBtYXAgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcmV0dXJucyBbZm0oduKCgCksIGZtKHbigoEpLCAuLi5dIHwgduG1oiDiiIggeFxuICovXG5leHBvcnQgZnVuY3Rpb24gbWFwPFQsIFU9VD4oeDogVFtdLCBmbTogTWFwRnVuY3Rpb248VCwgVHxVPik6IChUfFUpW10ge1xuICByZXR1cm4geC5tYXAoZm0pO1xufVxuXG5cbi8qKlxuICogVHJhbnNmb3JtIHZhbHVlcyBvZiBhbiBhcnJheSFcbiAqIEBwYXJhbSB4IGFuIGFycmF5ICh1cGRhdGVkISlcbiAqIEBwYXJhbSBmbSBtYXAgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcmV0dXJucyB4ID0gW2ZtKHbigoApLCBmbSh24oKBKSwgLi4uXTsgduG1oiDiiIggeFxuICovXG5leHBvcnQgZnVuY3Rpb24gbWFwJDxUPih4OiBUW10sIGZtOiBNYXBGdW5jdGlvbjxULCBUPik6IFRbXSB7XG4gIGNvbnN0IEkgPSB4Lmxlbmd0aDtcbiAgZm9yIChsZXQgaT0wOyBpPEk7ICsraSlcbiAgICB4W2ldID0gZm0oeFtpXSwgaSwgeCk7XG4gIHJldHVybiB4O1xufVxuXG5cbi8qKlxuICogUmVkdWNlIHZhbHVlcyBvZiBhcnJheSB0byBhIHNpbmdsZSB2YWx1ZS5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gZnIgcmVkdWNlIGZ1bmN0aW9uIChhY2MsIHYsIGksIHgpXG4gKiBAcGFyYW0gYWNjIGluaXRpYWwgdmFsdWVcbiAqIEByZXR1cm5zIGZyKGZyKGFjYywgduKCgCksIHbigoEpLi4uIHwgZnIoYWNjLCB24oKAKSA9IHbigoAgaWYgYWNjIG5vdCBnaXZlblxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVkdWNlPFQsIFU9VD4oeDogVFtdLCBmcjogUmVkdWNlRnVuY3Rpb248VCwgVHxVPiwgYWNjPzogVHxVKTogVHxVIHtcbiAgY29uc3QgaW5pdCA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMjtcbiAgcmV0dXJuIGluaXQ/IHgucmVkdWNlKGZyIGFzIFJlZHVjZUZ1bmN0aW9uPFQsIFQ+KSA6IHgucmVkdWNlKGZyIGFzIFJlZHVjZUZ1bmN0aW9uPFQsIFQ+LCBhY2MgYXMgVCk7XG59XG5cblxuLyoqXG4gKiBSZWR1Y2UgdmFsdWVzIGZyb20gcmlnaHQsIHRvIGEgc2luZ2xlIHZhbHVlLlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSBmciByZWR1Y2UgZnVuY3Rpb24gKGFjYywgdiwgaSwgeClcbiAqIEBwYXJhbSBhY2MgaW5pdGlhbCB2YWx1ZVxuICogQHJldHVybnMgZnIoZnIoYWNjLCB24oKT4oKL4oKAKSwgduKCk+KCi+KCgSkuLi4gfCBmcihhY2MsIHbigpPigovigoApID0gduKCk+KCi+KCgCBpZiBhY2Mgbm90IGdpdmVuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZWR1Y2VSaWdodDxULCBVPVQ+KHg6IFRbXSwgZnI6IFJlZHVjZUZ1bmN0aW9uPFQsIFR8VT4sIGFjYz86IFR8VSk6IFR8VSB7XG4gIGxldCBpbml0ID0gYXJndW1lbnRzLmxlbmd0aCA8PSAyO1xuICBmb3IgKGxldCBpPXgubGVuZ3RoLTE7IGk+PTA7IC0taSkge1xuICAgIGlmIChpbml0KSAgeyBhY2MgPSB4W2ldOyBpbml0ID0gZmFsc2U7IH1cbiAgICBlbHNlIGFjYyA9IGZyKGFjYyBhcyBUIHwgVSwgeFtpXSwgaSwgeCk7XG4gIH1cbiAgcmV0dXJuIGFjYyBhcyBUIHwgVTtcbn1cblxuXG4vKipcbiAqIEtlZXAgdmFsdWVzIHdoaWNoIHBhc3MgYSB0ZXN0LlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSBmdCB0ZXN0IGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHJldHVybnMgW3bigoAsIHbigoEsIC4uLl0gfCBmdCh24bWiKSA9IHRydWU7IHbhtaIg4oiIIHhcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGZpbHRlcjxUPih4OiBUW10sIGZ0OiBUZXN0RnVuY3Rpb248VD4pOiBUW10ge1xuICByZXR1cm4geC5maWx0ZXIoZnQpO1xufVxuZXhwb3J0IHtmaWx0ZXIgYXMgZmluZEFsbH07XG5cblxuLyoqXG4gKiBLZWVwIHZhbHVlcyB3aGljaCBwYXNzIGEgdGVzdCFcbiAqIEBwYXJhbSB4IGFuIGFycmF5ICh1cGRhdGVkISlcbiAqIEBwYXJhbSBmdCB0ZXN0IGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHJldHVybnMgeCA9IFt24oKALCB24oKBLCAuLi5dIHwgZnQoduG1oikgPSB0cnVlOyB24bWiIOKIiCB4XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmaWx0ZXIkPFQ+KHg6IFRbXSwgZnQ6IFRlc3RGdW5jdGlvbjxUPik6IFRbXSB7XG4gIGNvbnN0IEkgPSB4Lmxlbmd0aDtcbiAgbGV0IGogPSAwO1xuICBmb3IgKGxldCBpPTA7IGk8STsgKytpKVxuICAgIGlmIChmdCh4W2ldLCBpLCB4KSkgeFtqKytdID0geFtpXTtcbiAgeC5sZW5ndGggPSBqO1xuICByZXR1cm4geDtcbn1cblxuXG4vKipcbiAqIEtlZXAgdmFsdWVzIGF0IGdpdmVuIGluZGljZXMuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIGlzIGluZGljZXNcbiAqIEByZXR1cm5zIHbigoAsIHbigoEsIC4uLiB8IHbhtaIgPSB4W2ldOyBpIOKIiCBpc1xuICovXG5leHBvcnQgZnVuY3Rpb24gZmlsdGVyQXQ8VD4oeDogVFtdLCBpczogbnVtYmVyW10pOiBUW10ge1xuICBjb25zdCBYID0geC5sZW5ndGg7XG4gIGNvbnN0IGE6IFRbXSA9IFtdO1xuICBmb3IgKGNvbnN0IGkgb2YgaXMpXG4gICAgaWYgKGk+PTAgJiYgaTxYKSBhLnB1c2goeFtpXSk7XG4gIHJldHVybiBhO1xufVxuXG5cbi8qKlxuICogRGlzY2FyZCB2YWx1ZXMgd2hpY2ggcGFzcyBhIHRlc3QuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIGZ0IHRlc3QgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcmV0dXJucyBbduKCgCwgduKCgSwgLi4uXSB8IGZ0KHbhtaIpID0gZmFsc2U7IHbhtaIg4oiIIHhcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlamVjdDxUPih4OiBUW10sIGZ0OiBUZXN0RnVuY3Rpb248VD4pOiBUW10ge1xuICBsZXQgaSA9IC0xO1xuICBjb25zdCBhOiBUW10gPSBbXTtcbiAgZm9yIChjb25zdCB2IG9mIHgpXG4gICAgaWYgKCFmdCh2LCArK2ksIHgpKSBhLnB1c2godik7XG4gIHJldHVybiBhO1xufVxuXG5cbi8qKlxuICogRGlzY2FyZCB2YWx1ZXMgd2hpY2ggcGFzcyBhIHRlc3QhXG4gKiBAcGFyYW0geCBhbiBhcnJheSAodXBkYXRlZCEpXG4gKiBAcGFyYW0gZnQgdGVzdCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEByZXR1cm5zIHggPSBbduKCgCwgduKCgSwgLi4uXSB8IGZ0KHbhtaIpID0gZmFsc2U7IHbhtaIg4oiIIHhcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlamVjdCQ8VD4oeDogVFtdLCBmdDogVGVzdEZ1bmN0aW9uPFQ+KTogVFtdIHtcbiAgY29uc3QgSSA9IHgubGVuZ3RoO1xuICBsZXQgaiA9IDA7XG4gIGZvciAobGV0IGk9MDsgaTxJOyArK2kpXG4gICAgaWYgKCFmdCh4W2ldLCBpLCB4KSkgeFtqKytdID0geFtpXTtcbiAgeC5sZW5ndGggPSBqO1xuICByZXR1cm4geDtcbn1cblxuXG4vKipcbiAqIERpc2NhcmQgdmFsdWVzIGF0IGdpdmVuIGluZGljZXMuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIGlzIGluZGljZXNcbiAqIEByZXR1cm5zIFt24oKALCB24oKBLCAuLi5dIHwgduG1oiA9IHhbaV07IGkg4oiJIGlzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZWplY3RBdDxUPih4OiBUW10sIGlzOiBudW1iZXJbXSk6IFRbXSB7XG4gIGxldCBpID0gLTE7XG4gIGNvbnN0IGE6IFRbXSA9IFtdO1xuICBmb3IgKGNvbnN0IHYgb2YgeClcbiAgICBpZiAoIWlzLmluY2x1ZGVzKCsraSkpIGEucHVzaCh2KTtcbiAgcmV0dXJuIGE7XG59XG4vLyAjZW5kcmVnaW9uXG5cblxuXG5cbi8vICNyZWdpb24gRkxBVFRFTlxuLy8gLS0tLS0tLS0tLS0tLS0tXG5cbi8qKlxuICogRmxhdHRlbiBuZXN0ZWQgYXJyYXkgdG8gZ2l2ZW4gZGVwdGguXG4gKiBAcGFyYW0geCBhIG5lc3RlZCBhcnJheVxuICogQHBhcmFtIG4gbWF4aW11bSBkZXB0aCBbLTEg4oeSIGFsbF1cbiAqIEBwYXJhbSBmbSBtYXAgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcGFyYW0gZnQgZmxhdHRlbiB0ZXN0IGZ1bmN0aW9uICh2LCBpLCB4KSBbaXNdXG4gKiBAcmV0dXJucyBmbGF0IGl0ZXJhYmxlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmbGF0KHg6IHVua25vd25bXSwgbjogbnVtYmVyPS0xLCBmbTogTWFwRnVuY3Rpb248dW5rbm93biwgdW5rbm93bj4gfCBudWxsPW51bGwsIGZ0OiBUZXN0RnVuY3Rpb248dW5rbm93bj4gfCBudWxsPW51bGwpOiB1bmtub3duW10ge1xuICBmbSA9IGZtIHx8IElERU5USVRZO1xuICBmdCA9IGZ0IHx8IGlzO1xuICByZXR1cm4gZmxhdFRvJChbXSwgeCwgbiwgZm0sIGZ0KTtcbn1cblxuZnVuY3Rpb24gZmxhdFRvJChhOiB1bmtub3duW10sIHg6IHVua25vd25bXSwgbjogbnVtYmVyLCBmbTogTWFwRnVuY3Rpb248dW5rbm93biwgdW5rbm93bj4sIGZ0OiBUZXN0RnVuY3Rpb248dW5rbm93bj4pOiB1bmtub3duW10ge1xuICBsZXQgaSA9IC0xO1xuICBmb3IgKGNvbnN0IHYgb2YgeCkge1xuICAgIGNvbnN0IHcgPSBmbSh2LCArK2ksIHgpO1xuICAgIGlmIChuIT09MCAmJiBmdCh3LCBpLCB4KSkgZmxhdFRvJChhLCB2IGFzIHVua25vd25bXSwgbi0xLCBmbSwgZnQpO1xuICAgIGVsc2UgYS5wdXNoKHcpO1xuICB9XG4gIHJldHVybiBhO1xufVxuXG5cbi8qKlxuICogRmxhdHRlbiBuZXN0ZWQgYXJyYXksIGJhc2VkIG9uIG1hcCBmdW5jdGlvbi5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gZm0gbWFwIGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHBhcmFtIGZ0IGZsYXR0ZW4gdGVzdCBmdW5jdGlvbiAodiwgaSwgeCkgW2lzXVxuICogQHJldHVybnMgZmxhdCBpdGVyYWJsZVxuICovXG5leHBvcnQgZnVuY3Rpb24gZmxhdE1hcCh4OiB1bmtub3duW10sIGZtOiBNYXBGdW5jdGlvbjx1bmtub3duLCB1bmtub3duPiB8IG51bGw9bnVsbCwgZnQ6IFRlc3RGdW5jdGlvbjx1bmtub3duPiB8IG51bGw9bnVsbCk6IHVua25vd25bXSB7XG4gIGZtID0gZm0gfHwgSURFTlRJVFk7XG4gIGZ0ID0gZnQgfHwgaXM7XG4gIGxldCBpID0gLTE7XG4gIGNvbnN0IGE6IHVua25vd25bXSA9IFtdO1xuICBmb3IgKGNvbnN0IHYgb2YgeCkge1xuICAgIGNvbnN0IHcgPSBmbSh2LCArK2ksIHgpO1xuICAgIGlmIChmdCh3LCBpLCB4KSkgY29uY2F0JChhLCB3IGFzIEl0ZXJhYmxlPHVua25vd24+KTtcbiAgICBlbHNlIGEucHVzaCh3KTtcbiAgfVxuICByZXR1cm4gYTtcbn1cbi8vICNlbmRyZWdpb25cblxuXG5cblxuLy8gI3JlZ2lvbiBQUkVGSVggU1VNXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS1cblxuLyoqXG4gKiBQZXJmb3JtIGV4Y2x1c2l2ZSBwcmVmaXggc2NhbiBmcm9tIGxlZnQgdG8gcmlnaHQuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIGZyIHJlZHVjZSBmdW5jdGlvbiAoYWNjLCB2LCBpLCB4KVxuICogQHBhcmFtIGFjYyBpbml0aWFsIHZhbHVlXG4gKiBAcmV0dXJucyBbYWNjLCBmcihhY2MsIHbigoApLCBmcihmcihhY2MsIHbigoApLCB24oKBKS4uLl1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGV4Y2x1c2l2ZVNjYW48VCwgVT1UPih4OiBUW10sIGZyOiBSZWR1Y2VGdW5jdGlvbjxULCBUfFU+LCBhY2M6IFR8VSk6IChUfFUpW10ge1xuICBjb25zdCBhOiAoVHxVKVtdID0gW107XG4gIGNvbnN0IEkgPSB4Lmxlbmd0aDtcbiAgZm9yIChsZXQgaT0wOyBpPEk7ICsraSkge1xuICAgIGEucHVzaChhY2MpO1xuICAgIGFjYyA9IGZyKGFjYywgeFtpXSwgaSwgeCk7XG4gIH1cbiAgcmV0dXJuIGE7XG59XG5cblxuLyoqXG4gKiBQZXJmb3JtIGV4Y2x1c2l2ZSBwcmVmaXggc2NhbiBmcm9tIGxlZnQgdG8gcmlnaHQhXG4gKiBAcGFyYW0geCBhbiBhcnJheSAodXBkYXRlZCEpXG4gKiBAcGFyYW0gZnIgcmVkdWNlIGZ1bmN0aW9uIChhY2MsIHYsIGksIHgpXG4gKiBAcGFyYW0gYWNjIGluaXRpYWwgdmFsdWVcbiAqIEByZXR1cm5zIHggPSBbYWNjLCBmcihhY2MsIHbigoApLCBmcihmcihhY2MsIHbigoApLCB24oKBKS4uLl1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGV4Y2x1c2l2ZVNjYW4kPFQ+KHg6IFRbXSwgZnI6IFJlZHVjZUZ1bmN0aW9uPFQsIFQ+LCBhY2M6IFQpOiBUW10ge1xuICBjb25zdCBJID0geC5sZW5ndGg7XG4gIGZvciAobGV0IGk9MDsgaTxJOyArK2kpIHtcbiAgICBjb25zdCB2ID0geFtpXTtcbiAgICB4W2ldID0gYWNjO1xuICAgIGFjYyA9IGZyKGFjYywgdiwgaSwgeCk7XG4gIH1cbiAgcmV0dXJuIHg7XG59XG5cblxuLyoqXG4gKiBQZXJmb3JtIGluY2x1c2l2ZSBwcmVmaXggc2NhbiBmcm9tIGxlZnQgdG8gcmlnaHQuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIGZyIHJlZHVjZSBmdW5jdGlvbiAoYWNjLCB2LCBpLCB4KVxuICogQHBhcmFtIGFjYyBpbml0aWFsIHZhbHVlXG4gKiBAcmV0dXJucyBbZnIoYWNjLCB24oKAKSwgZnIoZnIoYWNjLCB24oKAKSwgduKCgSkuLi5dXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpbmNsdXNpdmVTY2FuPFQsIFU9VD4oeDogVFtdLCBmcjogUmVkdWNlRnVuY3Rpb248VCwgVHxVPiwgYWNjPzogVHxVKTogKFR8VSlbXSB7XG4gIGxldCBpbml0ID0gYXJndW1lbnRzLmxlbmd0aCA8PSAyO1xuICBjb25zdCBhOiAoVHxVKVtdID0gW107XG4gIGNvbnN0IEkgPSB4Lmxlbmd0aDtcbiAgZm9yIChsZXQgaT0wOyBpPEk7ICsraSkge1xuICAgIGFjYyA9IGluaXQ/IHhbaV0gOiBmcihhY2MgYXMgVHxVLCB4W2ldLCBpLCB4KTtcbiAgICBhLnB1c2goYWNjKTtcbiAgICBpbml0ID0gZmFsc2U7XG4gIH1cbiAgcmV0dXJuIGE7XG59XG5leHBvcnQge2luY2x1c2l2ZVNjYW4gYXMgYWNjdW11bGF0ZX07XG5cblxuLyoqXG4gKiBQZXJmb3JtIGluY2x1c2l2ZSBwcmVmaXggc2NhbiBmcm9tIGxlZnQgdG8gcmlnaHQhXG4gKiBAcGFyYW0geCBhbiBhcnJheSAodXBkYXRlZCEpXG4gKiBAcGFyYW0gZnIgcmVkdWNlIGZ1bmN0aW9uIChhY2MsIHYsIGksIHgpXG4gKiBAcGFyYW0gYWNjIGluaXRpYWwgdmFsdWVcbiAqIEByZXR1cm5zIHggPSBbZnIoYWNjLCB24oKAKSwgZnIoZnIoYWNjLCB24oKAKSwgduKCgSkuLi5dXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpbmNsdXNpdmVTY2FuJDxUPih4OiBUW10sIGZyOiBSZWR1Y2VGdW5jdGlvbjxULCBUPiwgYWNjOiBUKTogVFtdIHtcbiAgY29uc3QgSSA9IHgubGVuZ3RoO1xuICBmb3IgKGxldCBpPTA7IGk8STsgKytpKVxuICAgIGFjYyA9IHhbaV0gPSBmcihhY2MsIHhbaV0sIGksIHgpO1xuICByZXR1cm4geDtcbn1cblxuXG4vKipcbiAqIENvbWJpbmUgYWRqYWNlbnQgdmFsdWVzIG9mIGFuIGFycmF5LlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSBmYyBjb21iaW5lIGZ1bmN0aW9uICh1LCB2KVxuICogQHBhcmFtIGFjYyBpbml0aWFsIHZhbHVlXG4gKiBAcmV0dXJucyBbZmMoYWNjLCB24oKAKSwgZmModuKCgCwgduKCgSkuLi5dIHwgduG1oiDiiIggeFxuICovXG5leHBvcnQgZnVuY3Rpb24gYWRqYWNlbnRDb21iaW5lPFQ+KHg6IFRbXSwgZmM6IENvbWJpbmVGdW5jdGlvbjxUPiwgYWNjOiBUKTogVFtdIHtcbiAgY29uc3QgYTogVFtdID0gW107XG4gIGlmICh4Lmxlbmd0aD4wKSBhLnB1c2goZmMoYWNjLCB4WzBdKSk7XG4gIGNvbnN0IEkgPSB4Lmxlbmd0aDtcbiAgZm9yIChsZXQgaT0xOyBpPEk7ICsraSlcbiAgICBhLnB1c2goZmMoeFtpLTFdLCB4W2ldKSk7XG4gIHJldHVybiBhO1xufVxuLy8gYWRqYWNlbnRNYXAoKT9cblxuXG4vKipcbiAqIENvbWJpbmUgYWRqYWNlbnQgdmFsdWVzIG9mIGFuIGFycmF5IVxuICogQHBhcmFtIHggYW4gYXJyYXkgKHVwZGF0ZWQhKVxuICogQHBhcmFtIGZjIGNvbWJpbmUgZnVuY3Rpb24gKHUsIHYpXG4gKiBAcGFyYW0gYWNjIGluaXRpYWwgdmFsdWVcbiAqIEByZXR1cm5zIHggPSBbZmMoYWNjLCB24oKAKSwgZmModuKCgCwgduKCgSkuLi5dIHwgduG1oiDiiIggeFxuICovXG5leHBvcnQgZnVuY3Rpb24gYWRqYWNlbnRDb21iaW5lJDxUPih4OiBUW10sIGZjOiBDb21iaW5lRnVuY3Rpb248VD4sIGFjYzogVCk6IFRbXSB7XG4gIGNvbnN0IFggPSB4Lmxlbmd0aDtcbiAgaWYgKFg9PT0wKSByZXR1cm4geDtcbiAgbGV0IHYgPSB4WzBdO1xuICB4WzBdICA9IGZjKGFjYywgdik7XG4gIGZvciAobGV0IGk9MTsgaTxYOyArK2kpIHtcbiAgICBjb25zdCB3ID0geFtpXTtcbiAgICB4W2ldICA9IGZjKHYsIHcpO1xuICAgIHYgPSB3O1xuICB9XG4gIHJldHVybiB4O1xufVxuLy8gI2VuZHJlZ2lvblxuXG5cblxuXG4vLyAjcmVnaW9uIENPTUJJTkVcbi8vIC0tLS0tLS0tLS0tLS0tLVxuXG4vKipcbiAqIFBsYWNlIGEgc2VwYXJhdG9yIGJldHdlZW4gZXZlcnkgdmFsdWUuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIHYgc2VwYXJhdG9yXG4gKiBAcmV0dXJucyBbeFswXSwgdiwgeFsxXSwgdiwgLi4uLCB4W3x4fC0xXV1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGludGVyc3BlcnNlPFQ+KHg6IFRbXSwgdjogVCk6IFRbXSB7XG4gIGNvbnN0IGE6IFRbXSA9IFtdOyBsZXQgaSA9IC0xO1xuICBmb3IgKGNvbnN0IHUgb2YgeCkge1xuICAgIGlmICgrK2k+MCkgYS5wdXNoKHYpO1xuICAgIGEucHVzaCh1KTtcbiAgfVxuICByZXR1cm4gYTtcbn1cblxuXG4vKipcbiAqIEVzdGltYXRlIG5ldyB2YWx1ZXMgYmV0d2VlbiBleGlzdGluZyBvbmVzLlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSBmYyBjb21iaW5lIGZ1bmN0aW9uIChhLCBiKVxuICogQHJldHVybnMgW3hbMF0sIGZjKHhbMF0sIHhbMV0pLCB4WzFdLCBmYyh4WzFdLCB4WzJdKSwgLi4uLCB4W3x4fC0xXV1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGludGVycG9sYXRlPFQ+KHg6IFRbXSwgZmM6IENvbWJpbmVGdW5jdGlvbjxUPik6IFRbXSB7XG4gIGNvbnN0IGEgPSBbXTtcbiAgbGV0IHU6IFQgPSB1bmRlZmluZWQgYXMgVDtcbiAgbGV0IGkgPSAtMTtcbiAgZm9yIChjb25zdCB2IG9mIHgpIHtcbiAgICBpZiAoKytpPjApIGEucHVzaChmYyh1LCB2KSk7XG4gICAgYS5wdXNoKHUgPSB2KTtcbiAgfVxuICByZXR1cm4gYTtcbn1cblxuXG4vKipcbiAqIFBsYWNlIHZhbHVlcyBvZiBhbiBhcnJheSBiZXR3ZWVuIGFub3RoZXIuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIHkgYW5vdGhlciBhcnJheVxuICogQHBhcmFtIG0gbnVtYmVyIG9mIHZhbHVlcyBmcm9tIHggWzFdXG4gKiBAcGFyYW0gbiBudW1iZXIgb2YgdmFsdWVzIGZyb20geSBbMV1cbiAqIEBwYXJhbSBzIHN0ZXAgc2l6ZSBmb3IgeCBbbV1cbiAqIEBwYXJhbSB0IHN0ZXAgc2l6ZSBmb3IgeSBbbl1cbiAqIEByZXR1cm5zIHhbMC4ubV0g4qe6IHlbMC4ubl0g4qe6IHhbcy4ucyttXSDip7ogeVt0Li50K25dIOKnuiAuLi4g4qe6IHhbaypzLi58eHwtMV0gfCBrIOKIiCBXXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpbnRlcm1peDxUPih4OiBUW10sIHk6IFRbXSwgbTogbnVtYmVyPTEsIG46IG51bWJlcj0xLCBzOiBudW1iZXI9bSwgdDogbnVtYmVyPW4pOiBUW10ge1xuICBjb25zdCBYID0geC5sZW5ndGg7XG4gIGNvbnN0IFkgPSB5Lmxlbmd0aDtcbiAgY29uc3QgYTogVFtdID0gW107XG4gIG0gPSBNYXRoLm1heChtLCAwKTtcbiAgbiA9IE1hdGgubWF4KG4sIDApO1xuICBzID0gTWF0aC5tYXgocywgMSk7XG4gIHQgPSBNYXRoLm1heCh0LCAxKTtcbiAgZm9yIChsZXQgaT0wLCBqPTA7IGk8WDsgaSs9cykge1xuICAgIGlmIChpPjApIHtcbiAgICAgIGZvciAobGV0IGs9aiwgSz1rK247IGs8SzsgKytrKVxuICAgICAgICBhLnB1c2goeVtrICUgWV0pO1xuICAgICAgaiArPSB0O1xuICAgIH1cbiAgICBjb25jYXQkKGEsIHguc2xpY2UoaSwgaSttKSk7XG4gIH1cbiAgcmV0dXJuIGE7XG59XG5cblxuLyoqXG4gKiBQbGFjZSB2YWx1ZXMgZnJvbSBpdGVyYWJsZXMgYWx0ZXJuYXRlbHkuXG4gKiBAcGFyYW0geHMgYXJyYXlzXG4gKiBAcmV0dXJucyBbeOKCgFswXSwgeOKCgVswXSwgLi4uLCB44oKAWzFdLCB44oKBWzBdLCAuLi5dIHwgW3jigoAsIHjigoEsIC4uLl0gPSB4c1xuICovXG5leHBvcnQgZnVuY3Rpb24gaW50ZXJsZWF2ZTxUPih4czogVFtdW10pOiBUW10ge1xuICBjb25zdCBhOiBUW10gPSBbXTtcbiAgZm9yIChsZXQgaT0wOzsgKytpKSB7XG4gICAgbGV0IG4gPSAwO1xuICAgIGZvciAoY29uc3QgeCBvZiB4cylcbiAgICAgIGlmIChpPHgubGVuZ3RoKSB7IGEucHVzaCh4W2ldKTsgKytuOyB9XG4gICAgaWYgKG49PT0wKSBicmVhaztcbiAgfVxuICByZXR1cm4gYTtcbn1cblxuXG4vKipcbiAqIENvbWJpbmUgdmFsdWVzIGZyb20gYXJyYXlzLlxuICogQHBhcmFtIHhzIGFycmF5c1xuICogQHBhcmFtIGZtIG1hcCBmdW5jdGlvbiAodnMsIGkpXG4gKiBAcGFyYW0gZmUgZW5kIGZ1bmN0aW9uIChkb25lcykgW3NvbWVdXG4gKiBAcGFyYW0gdmQgZGVmYXVsdCB2YWx1ZVxuICogQHJldHVybnMgW2ZtKFt44oKAWzBdLCB44oKBWzBdLCAuLi5dKSwgZm0oW3jigoBbMV0sIHjigoFbMV0sIC4uLl0pLCAuLi5dXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB6aXA8VCwgVT1UW10+KHhzOiBUW11bXSwgZm06IE1hcEZ1bmN0aW9uPFRbXSwgVFtdfFU+IHwgbnVsbD1udWxsLCBmZTogRW5kRnVuY3Rpb24gfCBudWxsPW51bGwsIHZkPzogVCk6IChUW118VSlbXSB7XG4gIGZtID0gZm0gfHwgSURFTlRJVFk7XG4gIGZlID0gZmUgfHwgc29tZSBhcyBFbmRGdW5jdGlvbjtcbiAgY29uc3QgWCA9IHhzLmxlbmd0aCwgYTogKFRbXXxVKVtdID0gW107XG4gIGlmIChYPT09MCkgcmV0dXJuIGE7XG4gIGNvbnN0IGRzID0gbmV3IEFycmF5KFgpLmZpbGwoZmFsc2UpO1xuICBjb25zdCBscyA9IHhzLm1hcCh4ID0+IHgubGVuZ3RoKTtcbiAgZm9yIChsZXQgaT0wOzsgKytpKSB7XG4gICAgY29uc3QgdnM6IFRbXSA9IFtdO1xuICAgIGZvciAobGV0IGo9MDsgajxYOyArK2opIHtcbiAgICAgIGRzW2pdID0gaT49bHNbal07XG4gICAgICB2c1tqXSA9IGRzW2pdPyB2ZCBhcyBUIDogeHNbal1baV07XG4gICAgfVxuICAgIGlmIChmZShkcykpIGJyZWFrO1xuICAgIGEucHVzaChmbSh2cywgaSwgbnVsbCkpO1xuICB9XG4gIHJldHVybiBhO1xufVxuXG5cbi8vIFRPRE86IHppcDIoKT9cbi8vICNlbmRyZWdpb25cblxuXG5cblxuLy8gI3JlZ2lvbiBNQU5JUFVMQVRJT05cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbi8qKlxuICogRmlsbCB3aXRoIGdpdmVuIHZhbHVlLlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSB2IHZhbHVlXG4gKiBAcGFyYW0gaSBiZWdpbiBpbmRleCBbMF1cbiAqIEBwYXJhbSBJIGVuZCBpbmRleCBbfHh8XVxuICogQHJldHVybnMgeCcgfCB4JyA9IHg7IHgnW2kuLkldID0gdlxuICovXG5leHBvcnQgZnVuY3Rpb24gZmlsbDxUPih4OiBUW10sIHY6IFQsIGk6IG51bWJlcj0wLCBJOiBudW1iZXI9eC5sZW5ndGgpOiBUW10ge1xuICByZXR1cm4geC5zbGljZSgpLmZpbGwodiwgaSwgSSk7XG59XG5cblxuLyoqXG4gKiBGaWxsIHdpdGggZ2l2ZW4gdmFsdWUhXG4gKiBAcGFyYW0geCBhbiBhcnJheSAodXBkYXRlZCEpXG4gKiBAcGFyYW0gdiB2YWx1ZVxuICogQHBhcmFtIGkgYmVnaW4gaW5kZXggWzBdXG4gKiBAcGFyYW0gSSBlbmQgaW5kZXggW3x4fF1cbiAqIEByZXR1cm5zIHggfCB4W2kuLkldID0gdlxuICovXG5leHBvcnQgZnVuY3Rpb24gZmlsbCQ8VD4oeDogVFtdLCB2OiBULCBpOiBudW1iZXI9MCwgSTogbnVtYmVyPXgubGVuZ3RoKTogVFtdIHtcbiAgcmV0dXJuIHguZmlsbCh2LCBpLCBJKTtcbn1cblxuXG4vKipcbiAqIEFkZCB2YWx1ZSB0byB0aGUgZW5kLlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSB2cyB2YWx1ZXMgdG8gYWRkXG4gKiBAcmV0dXJucyB4IOKnuiB2c1xuICovXG5leHBvcnQgZnVuY3Rpb24gcHVzaDxUPih4OiBUW10sIC4uLnZzOiBUW10pOiBUW10ge1xuICByZXR1cm4geC5jb25jYXQodnMpO1xufVxuZXhwb3J0IHtwdXNoIGFzIHB1c2hCYWNrfTtcbmV4cG9ydCB7cHVzaCBhcyBhcHBlbmR9O1xuXG5cbi8qKlxuICogQWRkIHZhbHVlcyB0byB0aGUgZW5kIVxuICogQHBhcmFtIHggYW4gYXJyYXkgKHVwZGF0ZWQhKVxuICogQHBhcmFtIHZzIHZhbHVlcyB0byBhZGRcbiAqIEByZXR1cm5zIHggPSB4IOKnuiB2c1xuICovXG5leHBvcnQgZnVuY3Rpb24gcHVzaCQ8VD4oeDogVFtdLCAuLi52czogVFtdKTogVFtdIHtcbiAgeC5wdXNoKC4uLnZzKTtcbiAgcmV0dXJuIHg7XG59XG5leHBvcnQge3B1c2gkIGFzIHB1c2hCYWNrJH07XG5leHBvcnQge3B1c2gkIGFzIGFwcGVuZCR9O1xuXG5cbi8qKlxuICogUmVtb3ZlIGxhc3QgdmFsdWUuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHJldHVybnMgeFswLi58eHwtMV1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHBvcDxUPih4OiBUW10pOiBUW10ge1xuICByZXR1cm4geC5zbGljZSgwLCAtMSk7XG59XG5leHBvcnQge3BvcCBhcyBwb3BCYWNrfTtcblxuXG4vKipcbiAqIFJlbW92ZSBsYXN0IHZhbHVlIVxuICogQHBhcmFtIHggYW4gYXJyYXkgKHVwZGF0ZWQhKVxuICogQHJldHVybnMgeCA9IHhbMC4ufHh8LTFdXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwb3AkPFQ+KHg6IFRbXSk6IFRbXSB7XG4gIHgucG9wKCk7XG4gIHJldHVybiB4O1xufVxuZXhwb3J0IHtwb3AgYXMgcG9wQmFjayR9O1xuXG5cbi8qKlxuICogUmVtb3ZlIGZpcnN0IHZhbHVlLlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEByZXR1cm5zIHhbMS4uXVxuICovXG5leHBvcnQgZnVuY3Rpb24gc2hpZnQ8VD4oeDogVFtdKTogVFtdIHtcbiAgcmV0dXJuIHguc2xpY2UoMSk7XG59XG5leHBvcnQge3NoaWZ0IGFzIHBvcEZyb250fTtcblxuXG4vKipcbiAqIFJlbW92ZSBmaXJzdCB2YWx1ZSFcbiAqIEBwYXJhbSB4IGFuIGFycmF5ICh1cGRhdGVkISlcbiAqIEByZXR1cm5zIHggPSB4WzEuLl1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNoaWZ0JDxUPih4OiBUW10pOiBUW10ge1xuICB4LnNoaWZ0KCk7XG4gIHJldHVybiB4O1xufVxuZXhwb3J0IHtzaGlmdCQgYXMgcG9wRnJvbnQkfTtcblxuXG4vKipcbiAqIEFkZCB2YWx1ZXMgdG8gdGhlIHN0YXJ0LlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSB2cyB2YWx1ZXMgdG8gYWRkXG4gKiBAcmV0dXJucyB2cyDip7ogeFxuICovXG5leHBvcnQgZnVuY3Rpb24gdW5zaGlmdDxUPih4OiBJdGVyYWJsZTxUPiwgLi4udnM6IFRbXSk6IFRbXSB7XG4gIHJldHVybiBjb25jYXQkKHZzLCB4KTtcbn1cbmV4cG9ydCB7dW5zaGlmdCBhcyBwdXNoRnJvbnR9O1xuZXhwb3J0IHt1bnNoaWZ0IGFzIHByZXBlbmR9O1xuXG5cbi8qKlxuICogQWRkIHZhbHVlcyB0byB0aGUgc3RhcnQhXG4gKiBAcGFyYW0geCBhbiBhcnJheSAodXBkYXRlZCEpXG4gKiBAcGFyYW0gdnMgdmFsdWVzIHRvIGFkZFxuICogQHJldHVybnMgeCA9IHZzIOKnuiB4XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB1bnNoaWZ0JDxUPih4OiBUW10sIC4uLnZzOiBUW10pOiBUW10ge1xuICB4LnVuc2hpZnQoLi4udnMpO1xuICByZXR1cm4geDtcbn1cbmV4cG9ydCB7dW5zaGlmdCQgYXMgcHVzaEZyb250JH07XG5leHBvcnQge3Vuc2hpZnQkIGFzIHByZXBlbmQkfTtcblxuXG4vKipcbiAqIENvcHkgcGFydCBvZiBhcnJheSB0byBhbm90aGVyLlxuICogQHBhcmFtIHggdGFyZ2V0IGFycmF5XG4gKiBAcGFyYW0geSBzb3VyY2UgYXJyYXlcbiAqIEBwYXJhbSBqIHdyaXRlIGluZGV4IFswXVxuICogQHBhcmFtIGkgcmVhZCBiZWdpbiBpbmRleCBbMF1cbiAqIEBwYXJhbSBJIHJlYWQgZW5kIGluZGV4IFt8eHxdXG4gKiBAcmV0dXJucyB4WzAuLmpdIOKnuiB5W2kuLkldIOKnuiB4W2orSS1pLi5dXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjb3B5PFQ+KHg6IFRbXSwgeTogVFtdLCBqOiBudW1iZXI9MCwgaTogbnVtYmVyPTAsIEk6IG51bWJlcj15Lmxlbmd0aCk6IFRbXSB7XG4gIHJldHVybiBjb3B5JCh4LnNsaWNlKCksIHksIGosIGksIEkpO1xufVxuXG5cbi8qKlxuICogQ29weSBwYXJ0IG9mIGFycmF5IHRvIGFub3RoZXIhXG4gKiBAcGFyYW0geCB0YXJnZXQgYXJyYXkgKHVwZGF0ZWQhKVxuICogQHBhcmFtIHkgc291cmNlIGFycmF5XG4gKiBAcGFyYW0gaiB3cml0ZSBpbmRleCBbMF1cbiAqIEBwYXJhbSBpIHJlYWQgYmVnaW4gaW5kZXggWzBdXG4gKiBAcGFyYW0gSSByZWFkIGVuZCBpbmRleCBbfHh8XVxuICogQHJldHVybnMgeCA9IHhbMC4ual0g4qe6IHlbaS4uSV0g4qe6IHhbaitJLWkuLl1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNvcHkkPFQ+KHg6IFRbXSwgeTogVFtdLCBqOiBudW1iZXI9MCwgaTogbnVtYmVyPTAsIEk6IG51bWJlcj15Lmxlbmd0aCk6IFRbXSB7XG4gIGogPSBpbmRleCh4LCBqKTtcbiAgW2ksIEldID0gaW5kZXhSYW5nZSh5LCBpLCBJKTtcbiAgZm9yICg7IGk8STsgKytpLCArK2opXG4gICAgeFtqXSA9IHlbaV07XG4gIHJldHVybiB4O1xufVxuXG5cbi8qKlxuICogQ29weSBwYXJ0IG9mIGFycmF5IHdpdGhpbi5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gaiB3cml0ZSBpbmRleCBbMF1cbiAqIEBwYXJhbSBpIHJlYWQgYmVnaW4gaW5kZXggWzBdXG4gKiBAcGFyYW0gSSByZWFkIGVuZCBpbmRleCBbfHh8XVxuICogQHJldHVybnMgeFswLi5qXSDip7ogeFtpLi5JXSDip7ogeFtqK0ktaS4uXVxuICovXG5leHBvcnQgZnVuY3Rpb24gY29weVdpdGhpbjxUPih4OiBUW10sIGo6IG51bWJlcj0wLCBpOiBudW1iZXI9MCwgSTogbnVtYmVyPXgubGVuZ3RoKTogVFtdIHtcbiAgcmV0dXJuIHguc2xpY2UoKS5jb3B5V2l0aGluKGosIGksIEkpO1xufVxuXG5cbi8qKlxuICogQ29weSBwYXJ0IG9mIGFycmF5IHdpdGhpbiFcbiAqIEBwYXJhbSB4IGFuIGFycmF5ICh1cGRhdGVkISlcbiAqIEBwYXJhbSBqIHdyaXRlIGluZGV4IFswXVxuICogQHBhcmFtIGkgcmVhZCBiZWdpbiBpbmRleCBbMF1cbiAqIEBwYXJhbSBJIHJlYWQgZW5kIGluZGV4IFt8eHxdXG4gKiBAcmV0dXJucyB4ID0geFswLi5qXSDip7ogeFtpLi5JXSDip7ogeFtqK0ktaS4uXVxuICovXG5leHBvcnQgZnVuY3Rpb24gY29weVdpdGhpbiQ8VD4oeDogVFtdLCBqOiBudW1iZXI9MCwgaTogbnVtYmVyPTAsIEk6IG51bWJlcj14Lmxlbmd0aCk6IFRbXSB7XG4gIHJldHVybiB4LmNvcHlXaXRoaW4oaiwgaSwgSSk7XG59XG5cblxuLyoqXG4gKiBNb3ZlIHBhcnQgb2YgYXJyYXkgd2l0aGluLlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSBqIHdyaXRlIGluZGV4IFswXVxuICogQHBhcmFtIGkgcmVhZCBiZWdpbiBpbmRleCBbMF1cbiAqIEBwYXJhbSBJIHJlYWQgZW5kIGluZGV4IFt8eHxdXG4gKiBAcmV0dXJucyB4WzAuLmpdIOKnuiB4W2kuLkldIOKnuiB4W2ouLmldIOKnuiB4W0kuLl1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1vdmVXaXRoaW48VD4oeDogVFtdLCBqOiBudW1iZXI9MCwgaTogbnVtYmVyPTAsIEk6IG51bWJlcj14Lmxlbmd0aCk6IFRbXSB7XG4gIGogPSBpbmRleCh4LCBqKTtcbiAgW2ksIEldID0gaW5kZXhSYW5nZSh4LCBpLCBJKTtcbiAgaWYgKGo8aSkgcmV0dXJuIG1vdmVQYXJ0KHgsIGosIGksIEkpO1xuICBlbHNlICAgICByZXR1cm4gbW92ZVBhcnQoeCwgaSwgSSwgaik7XG59XG5cbmZ1bmN0aW9uIG1vdmVQYXJ0PFQ+KHg6IFRbXSwgaTogbnVtYmVyLCBqOiBudW1iZXIsIGs6IG51bWJlcik6IFRbXSB7XG4gIHJldHVybiB4LnNsaWNlKDAsIGkpLmNvbmNhdChcbiAgICB4LnNsaWNlKGosIGspLFxuICAgIHguc2xpY2UoaSwgaiksXG4gICAgeC5zbGljZShrKVxuICApO1xufVxuXG5cbi8qKlxuICogTW92ZSBwYXJ0IG9mIGFycmF5IHdpdGhpbiFcbiAqIEBwYXJhbSB4IGFuIGFycmF5ICh1cGRhdGVkISlcbiAqIEBwYXJhbSBqIHdyaXRlIMKxaW5kZXggWzBdXG4gKiBAcGFyYW0gaSByZWFkIGJlZ2luIMKxaW5kZXggWzBdXG4gKiBAcGFyYW0gSSByZWFkIGVuZCDCsWluZGV4IFt8eHxdXG4gKiBAcmV0dXJucyB4ID0geFswLi5qXSDip7ogeFtpLi5JXSDip7ogeFtqLi5pXSDip7ogeFtJLi5dXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBtb3ZlV2l0aGluJDxUPih4OiBUW10sIGo6IG51bWJlcj0wLCBpOiBudW1iZXI9MCwgSTogbnVtYmVyPXgubGVuZ3RoKTogVFtdIHtcbiAgaiA9IGluZGV4KHgsIGopO1xuICBbaSwgSV0gPSBpbmRleFJhbmdlKHgsIGksIEkpO1xuICBjb25zdCBwID0gIHguc2xpY2UoaSwgSSksIFAgPSBwLmxlbmd0aDtcbiAgaWYgKGo8aSkgeC5jb3B5V2l0aGluKGorUCwgaiwgaSk7XG4gIGVsc2UgICAgIHguY29weVdpdGhpbihpLCAgIEksIGopO1xuICByZXR1cm4gY29weSQoeCwgcCwgajxpPyBqIDogai1QKTtcbn1cbi8vIERPVUJUOiBBcmUgbmVnYXRpdmUgaW5kaWNlcyBhbnkgaGVscGZ1bCAob3RoZXIgdGhhbiBiYXNpYyBzaG9ydGN1dHMpP1xuLy8gRE9VQlQ6IEl0IGlzIG5vdCBlYXN5IHRvIHVzZSBhIG5lZ2F0aXZlIGluZGV4IHN1cHBvcnRpbmcgZnVuY3Rpb24gZnJvbSBhbm90aGVyIG5lZ2F0aXZlIGluZGV4IHN1cHBvcnRpbmcgZnVuY3Rpb24uXG4vLyBET1VCVDogU2VlbXMgdG8gbWUgdGhleSBhcmUgb25seSBjb21wbGljYXRpbmcgaW1wbGVtZW50YXRpb24gb2YgYWxnb3JpdGhtcywgYW5kIHNob3VsZCBiZSByZW1vdmVkLlxuXG5cbi8qKlxuICogUmVtb3ZlIG9yIHJlcGxhY2UgZXhpc3RpbmcgdmFsdWVzLlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSBpIHJlbW92ZSDCsWluZGV4XG4gKiBAcGFyYW0gbiBudW1iZXIgb2YgdmFsdWVzIHRvIHJlbW92ZSBbcmVzdF1cbiAqIEBwYXJhbSB2cyB2YWx1ZXMgdG8gaW5zZXJ0XG4gKiBAcmV0dXJucyB4WzAuLmldIOKnuiB2cyDip7ogeFtpK24uLl1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNwbGljZTxUPih4OiBUW10sIGk6IG51bWJlciwgbjogbnVtYmVyPXgubGVuZ3RoLCAuLi52czogVFtdKTogVFtdIHtcbiAgaSA9IGluZGV4KHgsIGkpO1xuICBuID0gTWF0aC5tYXgobiwgMCk7XG4gIHJldHVybiBjb25jYXQkKHguc2xpY2UoMCwgaSksIHZzLCB4LnNsaWNlKGkrbikpO1xufVxuZXhwb3J0IHtzcGxpY2UgYXMgdG9TcGxpY2VkfTtcblxuXG4vKipcbiAqIFJlbW92ZSBvciByZXBsYWNlIGV4aXN0aW5nIHZhbHVlcyFcbiAqIEBwYXJhbSB4IGFuIGFycmF5ICh1cGRhdGVkISlcbiAqIEBwYXJhbSBpIHJlbW92ZSDCsWluZGV4XG4gKiBAcGFyYW0gbiBudW1iZXIgb2YgdmFsdWVzIHRvIHJlbW92ZSBbcmVzdF1cbiAqIEBwYXJhbSB2cyB2YWx1ZXMgdG8gaW5zZXJ0XG4gKiBAcmV0dXJucyB4ID0geFswLi5pXSDip7ogdnMg4qe6IHhbaStuLi5dXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzcGxpY2UkPFQ+KHg6IFRbXSwgaTogbnVtYmVyLCBuOiBudW1iZXI9eC5sZW5ndGgsIC4uLnZzOiBUW10pOiBUW10ge1xuICB4LnNwbGljZShpLCBuLCAuLi52cyk7XG4gIHJldHVybiB4O1xufVxuLy8gI2VuZHJlZ2lvblxuXG5cblxuXG4vLyAjcmVnaW9uIENPVU5UL1BBUlRJVElPTlxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuLyoqXG4gKiBDb3VudCB2YWx1ZXMgd2hpY2ggc2F0aXNmeSBhIHRlc3QuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIGZ0IHRlc3QgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcmV0dXJucyDOo3ThtaIgfCB04bWiID0gMSBpZiBmdCh24bWiKSBlbHNlIDA7IHbhtaIg4oiIIHhcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNvdW50PFQ+KHg6IFRbXSwgZnQ6IFRlc3RGdW5jdGlvbjxUPik6IG51bWJlciB7XG4gIGxldCBpID0gLTEsIGEgPSAwO1xuICBmb3IgKGNvbnN0IHYgb2YgeClcbiAgICBpZiAoZnQodiwgKytpLCB4KSkgKythO1xuICByZXR1cm4gYTtcbn1cblxuXG4vKipcbiAqIENvdW50IG9jY3VycmVuY2VzIG9mIGVhY2ggZGlzdGluY3QgdmFsdWUuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIGZtIG1hcCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEByZXR1cm5zIE1hcCBcXHt2YWx1ZSDih5IgY291bnRcXH1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNvdW50RWFjaDxULCBVPVQ+KHg6IFRbXSwgZm06IE1hcEZ1bmN0aW9uPFQsIFR8VT4gfCBudWxsPW51bGwpOiBNYXA8VHxVLCBudW1iZXI+IHtcbiAgZm0gPSBmbSB8fCBJREVOVElUWTtcbiAgbGV0IGkgID0gLTE7IGNvbnN0IGEgPSBuZXcgTWFwKCk7XG4gIGZvciAoY29uc3QgdiBvZiB4KSB7XG4gICAgY29uc3QgdyA9IGZtKHYsICsraSwgeCk7XG4gICAgYS5zZXQodywgKGEuZ2V0KHcpIHx8IDApICsgMSk7XG4gIH1cbiAgcmV0dXJuIGE7XG59XG5leHBvcnQge2NvdW50RWFjaCBhcyBjb3VudEFzfTsgIC8vIERFUFJFQ0FURURcblxuXG4vKipcbiAqIFNlZ3JlZ2F0ZSB2YWx1ZXMgYnkgdGVzdCByZXN1bHQuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIGZ0IHRlc3QgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcmV0dXJucyBbc2F0aXNmaWVzLCBkb2VzbnRdXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwYXJ0aXRpb248VD4oeDogVFtdLCBmdDogVGVzdEZ1bmN0aW9uPFQ+KTogW1RbXSwgVFtdXSB7XG4gIGNvbnN0IHQ6IFRbXSA9IFtdLCBmOiBUW10gPSBbXTtcbiAgbGV0IGkgPSAtMTtcbiAgZm9yIChjb25zdCB2IG9mIHgpIHtcbiAgICBpZiAoZnQodiwgKytpLCB4KSkgdC5wdXNoKHYpO1xuICAgIGVsc2UgZi5wdXNoKHYpO1xuICB9XG4gIHJldHVybiBbdCwgZl07XG59XG5cblxuLyoqXG4gKiBTZWdyZWdhdGUgZWFjaCBkaXN0aW5jdCB2YWx1ZS5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gZm0gbWFwIGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHJldHVybnMgTWFwIFxce2tleSDih5IgdmFsdWVzXFx9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwYXJ0aXRpb25FYWNoPFQsIFU9VD4oeDogVFtdLCBmbTogTWFwRnVuY3Rpb248VCwgVHxVPiB8IG51bGw9bnVsbCk6IE1hcDxUfFUsIFRbXT4ge1xuICBmbSA9IGZtIHx8IElERU5USVRZO1xuICBsZXQgaSAgPSAtMTsgY29uc3QgYSA9IG5ldyBNYXA8VHxVLCBUW10+KCk7XG4gIGZvciAoY29uc3QgdiBvZiB4KSB7XG4gICAgY29uc3QgdyA9IGZtKHYsICsraSwgeCk7XG4gICAgaWYgKCFhLmhhcyh3KSkgYS5zZXQodywgW10pO1xuICAgIGEuZ2V0KHcpIS5wdXNoKHYpO1xuICB9XG4gIHJldHVybiBhO1xufVxuZXhwb3J0IHtwYXJ0aXRpb25FYWNoIGFzIGdyb3VwVG9NYXB9O1xuZXhwb3J0IHtwYXJ0aXRpb25FYWNoIGFzIHBhcnRpdGlvbkFzfTsgICAgLy8gREVQUkVDQVRFRFxuLy8gI2VuZHJlZ2lvblxuXG5cblxuXG4vLyAjcmVnaW9uIFNQTElUU1xuLy8gLS0tLS0tLS0tLS0tLS1cblxuLyoqXG4gKiBCcmVhayBhcnJheSBjb25zaWRlcmluZyB0ZXN0IGFzIHNlcGFyYXRvci5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gZnQgdGVzdCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEByZXR1cm5zIFt4W2ouLmtdLCB4W2wuLm1dLCAuLi5dIHwgZnQoeFtpXSkgPSB0cnVlOyBpID0gMC4uaiAvIGsuLmwgLyAuLi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNwbGl0PFQ+KHg6IFRbXSwgZnQ6IFRlc3RGdW5jdGlvbjxUPik6IFRbXVtdIHtcbiAgbGV0IGkgPSAtMTtcbiAgY29uc3QgYTogVFtdW10gPSBbXTtcbiAgbGV0IGI6IFRbXSA9IFtdO1xuICBmb3IgKGNvbnN0IHYgb2YgeCkge1xuICAgIGlmICghZnQodiwgKytpLCB4KSkgIGIucHVzaCh2KTtcbiAgICBlbHNlIGlmIChiLmxlbmd0aCkgeyBhLnB1c2goYik7IGIgPSBbXTsgfVxuICB9XG4gIGlmIChiLmxlbmd0aCkgYS5wdXNoKGIpO1xuICByZXR1cm4gYTtcbn1cblxuXG4vKipcbiAqIEJyZWFrIGFycmF5IGNvbnNpZGVyaW5nIGluZGljZXMgYXMgc2VwYXJhdG9yLlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSBpcyBpbmRpY2VzIChzb3J0ZWQpXG4gKiBAcmV0dXJucyBbeFtqLi5rXSwgeFtsLi5tXSwgLi4uXSB8IGZ0KHhbaV0pID0gdHJ1ZTsgaSA9IDAuLmogLyBrLi5sIC8gLi4uOyBpIOKIiCBpc1xuICovXG5leHBvcnQgZnVuY3Rpb24gc3BsaXRBdDxUPih4OiBUW10sIGlzOiBudW1iZXJbXSk6IFRbXVtdIHtcbiAgbGV0IGkgPSAtMTtcbiAgY29uc3QgYTogVFtdW10gPSBbXTtcbiAgbGV0IGI6IFRbXSA9IFtdO1xuICBmb3IgKGNvbnN0IHYgb2YgeCkge1xuICAgIGlmICghaXMuaW5jbHVkZXMoKytpKSkgYi5wdXNoKHYpO1xuICAgIGVsc2UgaWYoYi5sZW5ndGgpICAgIHsgYS5wdXNoKGIpOyBiID0gW107IH1cbiAgfVxuICBpZiAoYi5sZW5ndGgpIGEucHVzaChiKTtcbiAgcmV0dXJuIGE7XG59XG5cblxuLyoqXG4gKiBCcmVhayBhcnJheSB3aGVuIHRlc3QgcGFzc2VzLlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSBmdCB0ZXN0IGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHJldHVybnMgW3hbMC4ual0sIHhbai4ua10sIC4uLl0gfCBmdCh4W2ldKSA9IHRydWU7IGkgPSBqLCBrLCAuLi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGN1dDxUPih4OiBUW10sIGZ0OiBUZXN0RnVuY3Rpb248VD4pOiBUW11bXSB7XG4gIGxldCBqID0gMDsgY29uc3QgYSA9IFtdO1xuICBjb25zdCBJID0geC5sZW5ndGg7XG4gIGZvciAobGV0IGk9MDsgaTxJOyArK2kpIHtcbiAgICBpZiAoIWZ0KHhbaV0sIGksIHgpKSBjb250aW51ZTtcbiAgICBhLnB1c2goeC5zbGljZShqLCBpKSk7XG4gICAgaiA9IGk7XG4gIH1cbiAgYS5wdXNoKHguc2xpY2UoaikpO1xuICByZXR1cm4gYTtcbn1cblxuXG4vKipcbiAqIEJyZWFrIGFycmF5IGFmdGVyIHRlc3QgcGFzc2VzLlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSBmdCB0ZXN0IGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHJldHVybnMgW3hbMC4uaisxXSwgeFtqKzEuLmtdLCAuLi5dIHwgZnQoeFtpXSkgPSB0cnVlOyBpID0gaiwgaywgLi4uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjdXRSaWdodDxUPih4OiBUW10sIGZ0OiBUZXN0RnVuY3Rpb248VD4pOiBUW11bXSB7XG4gIGxldCBqID0gMDsgY29uc3QgYSA9IFtdO1xuICBjb25zdCBJID0geC5sZW5ndGg7XG4gIGZvciAobGV0IGk9MDsgaTxJOyArK2kpIHtcbiAgICBpZiAoIWZ0KHhbaV0sIGksIHgpKSBjb250aW51ZTtcbiAgICBhLnB1c2goeC5zbGljZShqLCBpKzEpKTtcbiAgICBqID0gaSsxO1xuICB9XG4gIGEucHVzaCh4LnNsaWNlKGopKTtcbiAgcmV0dXJuIGE7XG59XG5cblxuLyoqXG4gKiBCcmVhayBhcnJheSBhdCBnaXZlbiBpbmRpY2VzLlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSBpcyBzcGxpdCDCsWluZGljZXMgKGxlZnQgdG8gcmlnaHQpXG4gKiBAcmV0dXJucyBbeFswLi5qXSwgeFtqLi5rXSwgLi4uXSB8IGZ0KHhbaV0pID0gdHJ1ZTsgaSA9IGosIGssIC4uLjsgaSDiiIggaXNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGN1dEF0PFQ+KHg6IFRbXSwgaXM6IG51bWJlcltdKTogVFtdW10ge1xuICBjb25zdCBYID0geC5sZW5ndGg7XG4gIGxldCBqID0gMDsgY29uc3QgYSA9IFtdO1xuICBmb3IgKGxldCBpIG9mIGlzKSB7XG4gICAgaSA9IGk8MD8gWCtpIDogaTtcbiAgICBhLnB1c2goeC5zbGljZShqLCBpKSk7XG4gICAgaiA9IE1hdGgubWF4KGosIGkpO1xuICB9XG4gIGEucHVzaCh4LnNsaWNlKGopKTtcbiAgcmV0dXJuIGE7XG59XG5cblxuLyoqXG4gKiBCcmVhayBhcnJheSBhZnRlciBnaXZlbiBpbmRpY2VzLlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSBpcyBzcGxpdCDCsWluZGljZXMgKGxlZnQgdG8gcmlnaHQpXG4gKiBAcmV0dXJucyBbeFswLi5qKzFdLCB4W2orMS4ua10sIC4uLl0gfCBmdCh4W2ldKSA9IHRydWU7IGkgPSBqLCBrLCAuLi47IGkg4oiIIGlzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjdXRBdFJpZ2h0PFQ+KHg6IFRbXSwgaXM6IG51bWJlcltdKTogVFtdW10ge1xuICBjb25zdCBYID0geC5sZW5ndGg7XG4gIGxldCBqID0gMDsgY29uc3QgYSA9IFtdO1xuICBmb3IgKGxldCBpIG9mIGlzKSB7XG4gICAgaSA9IGk8MD8gWCtpIDogaTtcbiAgICBhLnB1c2goeC5zbGljZShqLCBpKzEpKTtcbiAgICBqID0gTWF0aC5tYXgoaiwgaSsxKTtcbiAgfVxuICBhLnB1c2goeC5zbGljZShqKSk7XG4gIHJldHVybiBhO1xufVxuXG5cbi8qKlxuICogS2VlcCBzaW1pbGFyIHZhbHVlcyB0b2dldGhlciBhbmQgaW4gb3JkZXIuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIGZjIGNvbXBhcmUgZnVuY3Rpb24gKGEsIGIpXG4gKiBAcGFyYW0gZm0gbWFwIGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHJldHVybnMgW3hbMC4ua10sIHhbay4ubF0sIC4uLl0gfCBmYyh4W2ldLCB4W2pdKSA9IDA7IGksIGogPSAwLi5rIC8gay4ubCAvIC4uLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZ3JvdXA8VCwgVT1UPih4OiBUW10sIGZjOiBDb21wYXJlRnVuY3Rpb248VHxVPiB8IG51bGw9bnVsbCwgZm06IE1hcEZ1bmN0aW9uPFQsIFR8VT4gfCBudWxsPW51bGwpOiBUW11bXSB7XG4gIGZjID0gZmMgfHwgQ09NUEFSRTtcbiAgZm0gPSBmbSB8fCBJREVOVElUWTtcbiAgY29uc3QgYTogVFtdW10gPSBbXTtcbiAgbGV0IGI6IFRbXSA9IFtdO1xuICBsZXQgdTogVHxVID0gdW5kZWZpbmVkIGFzIFQsIGkgPSAtMTtcbiAgZm9yIChjb25zdCB2IG9mIHgpIHtcbiAgICBjb25zdCB3ID0gZm0odiwgKytpLCB4KTtcbiAgICBpZiAoaT09PTAgfHwgZmModSwgdyk9PT0wKSBiLnB1c2godik7XG4gICAgZWxzZSB7IGEucHVzaChiKTsgYiA9IFt2XTsgfVxuICAgIHUgPSB3O1xuICB9XG4gIGEucHVzaChiKTtcbiAgcmV0dXJuIGE7XG59XG5cblxuLyoqXG4gKiBCcmVhayBhcnJheSBpbnRvIGNodW5rcyBvZiBnaXZlbiBzaXplLlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSBuIGNodW5rIHNpemUgWzFdXG4gKiBAcGFyYW0gcyBjaHVuayBzdGVwIFtuXVxuICogQHJldHVybnMgeFswLi5uXSDip7ogeFtzLi5zK25dIOKnuiB4WzJzLi4ycytuXSDip7ogLi4uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjaHVuazxUPih4OiBUW10sIG46IG51bWJlcj0xLCBzOiBudW1iZXI9bik6IFRbXVtdIHtcbiAgY29uc3QgYTogVFtdW10gPSBbXTtcbiAgaWYgKG48MCkgcmV0dXJuIGE7XG4gIHMgPSBNYXRoLm1heChzLCAxKTtcbiAgY29uc3QgSSA9IHgubGVuZ3RoO1xuICBmb3IgKGxldCBpPTA7IGk8STsgaSs9cylcbiAgICBhLnB1c2goeC5zbGljZShpLCBpK24pKTtcbiAgcmV0dXJuIGE7XG59XG4vLyAjZW5kcmVnaW9uXG5cblxuXG5cbi8vICNyZWdpb24gQ09OQ0FUL0pPSU5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS1cblxuLyoqXG4gKiBBcHBlbmQgdmFsdWVzIGZyb20gYXJyYXlzLlxuICogQHBhcmFtIHhzIGFycmF5c1xuICogQHJldHVybnMgeOKCgCDip7ogeOKCgSDip7ogLi4uIHwgW3jigoAsIHjigoEsIC4uLl0gPSB4c1xuICovXG5leHBvcnQgZnVuY3Rpb24gY29uY2F0PFQ+KC4uLnhzOiBUW11bXSk6IFRbXSB7XG4gIHJldHVybiAoW10gYXMgVFtdKS5jb25jYXQoLi4ueHMpO1xufVxuXG5cbi8qKlxuICogQXBwZW5kIHZhbHVlcyBmcm9tIGFycmF5cyFcbiAqIEBwYXJhbSB4IGFuIGFycmF5ICh1cGRhdGVkISlcbiAqIEBwYXJhbSB5cyBhcnJheXMgdG8gYXBwZW5kXG4gKiBAcmV0dXJucyB4ID0geCDip7ogeeKCgCDip7ogeeKCgSDip7ogLi4uXSB8IFt54oKALCB54oKBLCAuLi5dID0geXNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNvbmNhdCQ8VD4oeDogVFtdLCAuLi55czogSXRlcmFibGU8VD5bXSk6IFRbXSB7XG4gIGZvciAoY29uc3QgeSBvZiB5cylcbiAgICB4LnB1c2goLi4ueSk7XG4gIHJldHVybiB4O1xufVxuXG5cbi8qKlxuICogSm9pbiB2YWx1ZXMgdG9nZXRoZXIgaW50byBhIHN0cmluZy5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gc2VwIHNlcGFyYXRvciBbLF1cbiAqIEByZXR1cm5zIFwiJFxce3bigoBcXH0kXFx7c2VwXFx9JFxce3bigoFcXH0uLi5cIiB8IHbhtaIg4oiIIHhcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGpvaW48VD4oeDogVFtdLCBzZXA6IHN0cmluZz1cIixcIik6IHN0cmluZyB7XG4gIHJldHVybiB4LmpvaW4oc2VwKTtcbn1cbi8vICNlbmRyZWdpb25cblxuXG5cblxuLy8gI3JlZ2lvbiBSRUFSUkFOR0Vcbi8vIC0tLS0tLS0tLS0tLS0tLS0tXG5cbi8qKlxuICogT2J0YWluIHZhbHVlcyB0aGF0IGN5Y2xlIHRocm91Z2ggYXJyYXkuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIGkgYmVnaW4gwrFpbmRleCBbMF1cbiAqIEBwYXJhbSBuIG51bWJlciBvZiB2YWx1ZXMgW3x4fF1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGN5Y2xlPFQ+KHg6IFRbXSwgaTogbnVtYmVyPTAsIG46IG51bWJlcj14Lmxlbmd0aCk6IFRbXSB7XG4gIGNvbnN0IFggPSB4Lmxlbmd0aDtcbiAgaWYgKG48PTAgfHwgWD09PTApIHJldHVybiBbXTtcbiAgaSA9IG1vZChpLCBYKTtcbiAgY29uc3QgYSA9IHguc2xpY2UoaSwgaStuKTtcbiAgbiAtPSBhLmxlbmd0aDtcbiAgY29uc3QgTSA9IE1hdGguZmxvb3Iobi9YKTtcbiAgZm9yIChsZXQgbT0wOyBtPE07ICsrbSlcbiAgICBjb25jYXQkKGEsIHgpO1xuICByZXR1cm4gY29uY2F0JChhLCB4LnNsaWNlKDAsIG4gJSBYKSk7XG59XG5cblxuLyoqXG4gKiBSZXBlYXQgYW4gYXJyYXkgZ2l2ZW4gdGltZXMuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIG4gdGltZXMgWzFdXG4gKiBAcmV0dXJucyB4IOKnuiB4IOKnuiAuLi4obiB0aW1lcylcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlcGVhdDxUPih4OiBUW10sIG46IG51bWJlcj0xKTogVFtdIHtcbiAgY29uc3QgYTogVFtdID0gW107XG4gIGZvciAoOyBuPjA7IC0tbilcbiAgICBjb25jYXQkKGEsIHgpO1xuICByZXR1cm4gYTtcbn1cblxuXG4vKipcbiAqIFJldmVyc2UgdGhlIHZhbHVlcy5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcmV0dXJucyBbeFt8eHwtMV0sIHhbfHh8LTJdLCAuLi4sIHhbMV0sIHhbMF1dXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZXZlcnNlPFQ+KHg6IFRbXSk6IFRbXSB7XG4gIHJldHVybiB4LnNsaWNlKCkucmV2ZXJzZSgpO1xufVxuZXhwb3J0IHtyZXZlcnNlIGFzIHRvUmV2ZXJzZWR9O1xuXG5cbi8qKlxuICogUmV2ZXJzZSB0aGUgdmFsdWVzIVxuICogQHBhcmFtIHggYW4gYXJyYXkgKHVwZGF0ZWQhKVxuICogQHJldHVybnMgeCA9IFt4W3x4fC0xXSwgeFt8eHwtMl0sIC4uLiwgeFsxXSwgeFswXV1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJldmVyc2UkPFQ+KHg6IFRbXSk6IFRbXSB7XG4gIHJldHVybiB4LnJldmVyc2UoKTtcbn1cblxuXG4vKipcbiAqIFJvdGF0ZSB2YWx1ZXMgaW4gYXJyYXkuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIG4gcm90YXRlIGFtb3VudCAoK3ZlOiBsZWZ0LCAtdmU6IHJpZ2h0KSBbMF1cbiAqIEByZXR1cm5zIHhbbi4uXSDip7ogeFswLi5uXVxuICovXG5leHBvcnQgZnVuY3Rpb24gcm90YXRlPFQ+KHg6IFRbXSwgbjogbnVtYmVyPTApOiBUW10ge1xuICBuID0gbW9kKG4sIHgubGVuZ3RoKTtcbiAgcmV0dXJuIGNvbmNhdCQoeC5zbGljZShuKSwgeC5zbGljZSgwLCBuKSk7XG59XG5cblxuLyoqXG4gKiBSb3RhdGUgdmFsdWVzIGluIGFycmF5IVxuICogQHBhcmFtIHggYW4gYXJyYXkgKHVwZGF0ZWQhKVxuICogQHBhcmFtIG4gcm90YXRlIGFtb3VudCAoK3ZlOiBsZWZ0LCAtdmU6IHJpZ2h0KSBbMF1cbiAqIEByZXR1cm5zIHggPSB4W24uLl0g4qe6IHhbMC4ubl1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJvdGF0ZSQ8VD4oeDogVFtdLCBuOiBudW1iZXI9MCk6IFRbXSB7XG4gIG4gPSBtb2QobiwgeC5sZW5ndGgpO1xuICBjb25zdCB5ID0geC5zbGljZSgwLCBuKTtcbiAgeC5jb3B5V2l0aGluKDAsIG4pO1xuICByZXR1cm4gY29weSQoeCwgeSwgeC5sZW5ndGgtbik7XG59XG4vLyAjZW5kcmVnaW9uXG5cblxuXG5cbi8vICNyZWdpb24gU0VUIE9QRVJBVElPTlNcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4vKipcbiAqIEV4YW1pbmUgaWYgdGhlcmUgYXJlIG5vIGR1cGxpY2F0ZSB2YWx1ZXMuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIGZjIGNvbXBhcmUgZnVuY3Rpb24gKGEsIGIpXG4gKiBAcGFyYW0gZm0gbWFwIGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHJldHVybnMg4oiAIHbhtaIsIHbisbwg4oiIIHgsIGlzIHbhtaIg4omgIHbisbw/XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc1VuaXF1ZTxULCBVPVQ+KHg6IFRbXSwgZmM6IENvbXBhcmVGdW5jdGlvbjxUfFU+IHwgbnVsbD1udWxsLCBmbTogTWFwRnVuY3Rpb248VCwgVHxVPiB8IG51bGw9bnVsbCk6IGJvb2xlYW4ge1xuICBpZiAoZmMpIHJldHVybiBpc1VuaXF1ZUR1YWwoeCwgZmMsIGZtKTtcbiAgZWxzZSAgICByZXR1cm4gaXNVbmlxdWVNYXAgKHgsIGZtKTtcbn1cblxuZnVuY3Rpb24gaXNVbmlxdWVNYXA8VCwgVT1UPih4OiBUW10sIGZtOiBNYXBGdW5jdGlvbjxULCBUfFU+IHwgbnVsbD1udWxsKTogYm9vbGVhbiB7XG4gIGZtID0gZm0gfHwgSURFTlRJVFk7XG4gIGNvbnN0IHMgID0gbmV3IFNldCgpOyBsZXQgaSA9IC0xO1xuICBmb3IgKGNvbnN0IHYgb2YgeCkge1xuICAgIGNvbnN0IHcgPSBmbSh2LCArK2ksIHgpO1xuICAgIGlmIChzLmhhcyh3KSkgcmV0dXJuIGZhbHNlO1xuICAgIHMuYWRkKHcpO1xuICB9XG4gIHJldHVybiB0cnVlO1xufVxuXG5mdW5jdGlvbiBpc1VuaXF1ZUR1YWw8VCwgVT1UPih4OiBUW10sIGZjOiBDb21wYXJlRnVuY3Rpb248VHxVPiB8IG51bGw9bnVsbCwgZm06IE1hcEZ1bmN0aW9uPFQsIFR8VT4gfCBudWxsPW51bGwpOiBib29sZWFuIHtcbiAgZmMgPSBmYyB8fCBDT01QQVJFO1xuICBmbSA9IGZtIHx8IElERU5USVRZO1xuICBjb25zdCB4MSA9IFsuLi54XS5tYXAoZm0pO1xuICBmb3IgKGNvbnN0IHd4IG9mIHgxKSB7XG4gICAgZm9yIChjb25zdCB3eSBvZiB4MSlcbiAgICAgIGlmIChmYyh3eCwgd3kpPT09MCkgcmV0dXJuIGZhbHNlO1xuICB9XG4gIHJldHVybiB0cnVlO1xufVxuXG5cbi8qKlxuICogRXhhbWluZSBpZiBhcnJheXMgaGF2ZSBubyB2YWx1ZSBpbiBjb21tb24uXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIHkgYW5vdGhlciBhcnJheVxuICogQHBhcmFtIGZjIGNvbXBhcmUgZnVuY3Rpb24gKGEsIGIpXG4gKiBAcGFyYW0gZm0gbWFwIGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHJldHVybnMgeCDiiKkgeSA9IM6mP1xuICovXG5leHBvcnQgZnVuY3Rpb24gaXNEaXNqb2ludDxULCBVPVQ+KHg6IFRbXSwgeTogVFtdLCBmYzogQ29tcGFyZUZ1bmN0aW9uPFR8VT4gfCBudWxsPW51bGwsIGZtOiBNYXBGdW5jdGlvbjxULCBUfFU+IHwgbnVsbD1udWxsKTogYm9vbGVhbiB7XG4gIGlmIChmYykgcmV0dXJuIGlzRGlzam9pbnREdWFsKHgsIHksIGZjLCBmbSk7XG4gIGVsc2UgICAgcmV0dXJuIGlzRGlzam9pbnRNYXAgKHgsIHksIGZtKTtcbn1cblxuZnVuY3Rpb24gaXNEaXNqb2ludE1hcDxULCBVPVQ+KHg6IFRbXSwgeTogVFtdLCBmbTogTWFwRnVuY3Rpb248VCwgVHxVPiB8IG51bGw9bnVsbCk6IGJvb2xlYW4ge1xuICBmbSA9IGZtIHx8IElERU5USVRZO1xuICBjb25zdCBzICA9IHRvU2V0KHksIGZtKTsgbGV0IGkgPSAtMTtcbiAgZm9yIChjb25zdCB2IG9mIHgpIHtcbiAgICBjb25zdCB3ID0gZm0odiwgKytpLCB4KTtcbiAgICBpZiAocy5oYXModykpIHJldHVybiBmYWxzZTtcbiAgfVxuICByZXR1cm4gdHJ1ZTtcbn1cblxuZnVuY3Rpb24gaXNEaXNqb2ludER1YWw8VCwgVT1UPih4OiBUW10sIHk6IFRbXSwgZmM6IENvbXBhcmVGdW5jdGlvbjxUfFU+IHwgbnVsbD1udWxsLCBmbTogTWFwRnVuY3Rpb248VCwgVHxVPiB8IG51bGw9bnVsbCk6IGJvb2xlYW4ge1xuICBmYyA9IGZjIHx8IENPTVBBUkU7XG4gIGZtID0gZm0gfHwgSURFTlRJVFk7XG4gIGNvbnN0IHkxID0gWy4uLnldLm1hcChmbSk7IGxldCBpID0gLTE7XG4gIGZvciAoY29uc3Qgdnggb2YgeCkge1xuICAgIGNvbnN0IHd4ID0gZm0odngsICsraSwgeCk7XG4gICAgZm9yIChjb25zdCB3eSBvZiB5MSlcbiAgICAgIGlmIChmYyh3eCwgd3kpPT09MCkgcmV0dXJuIGZhbHNlO1xuICB9XG4gIHJldHVybiB0cnVlO1xufVxuXG5cbi8qKlxuICogUmVtb3ZlIGR1cGxpY2F0ZSB2YWx1ZXMuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIGZjIGNvbXBhcmUgZnVuY3Rpb24gKGEsIGIpXG4gKiBAcGFyYW0gZm0gbWFwIGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHJldHVybnMgduKCgCwgduKCgSwgLi4uIHwgduG1oiDiiIggeDsgduG1oiDiiaAgduKxvCDiiIAgaSwgalxuICovXG5leHBvcnQgZnVuY3Rpb24gdW5pcXVlPFQsIFU9VD4oeDogVFtdLCBmYzogQ29tcGFyZUZ1bmN0aW9uPFR8VT4gfCBudWxsPW51bGwsIGZtOiBNYXBGdW5jdGlvbjxULCBUfFU+IHwgbnVsbD1udWxsKTogVFtdIHtcbiAgaWYgKGZjKSByZXR1cm4gdW5pcXVlRHVhbCh4LCBmYywgZm0pO1xuICBlbHNlICAgIHJldHVybiB1bmlxdWVNYXAgKHgsIGZtKTtcbn1cblxuZnVuY3Rpb24gdW5pcXVlTWFwPFQsIFU9VD4oeDogVFtdLCBmbTogTWFwRnVuY3Rpb248VCwgVHxVPiB8IG51bGw9bnVsbCk6IFRbXSB7XG4gIGZtID0gZm0gfHwgSURFTlRJVFk7XG4gIGNvbnN0IHMgID0gbmV3IFNldCgpO1xuICBsZXQgaSAgPSAtMTsgY29uc3QgYSA9IFtdO1xuICBmb3IgKGNvbnN0IHYgb2YgeCkge1xuICAgIGNvbnN0IHcgPSBmbSh2LCArK2ksIHgpO1xuICAgIGlmIChzLmhhcyh3KSkgY29udGludWU7XG4gICAgcy5hZGQodyk7IGEucHVzaCh2KTtcbiAgfVxuICByZXR1cm4gYTtcbn1cblxuZnVuY3Rpb24gdW5pcXVlRHVhbDxULCBVPVQ+KHg6IFRbXSwgZmM6IENvbXBhcmVGdW5jdGlvbjxUfFU+IHwgbnVsbD1udWxsLCBmbTogTWFwRnVuY3Rpb248VCwgVHxVPiB8IG51bGw9bnVsbCk6IFRbXSB7XG4gIGZjID0gZmMgfHwgQ09NUEFSRTtcbiAgZm0gPSBmbSB8fCBJREVOVElUWTtcbiAgbGV0IGkgID0gLTE7IGNvbnN0IHMgPSBbXSwgYSA9IFtdO1xuICB4OiBmb3IgKGNvbnN0IHZ4IG9mIHgpIHtcbiAgICBjb25zdCB3eCA9IGZtKHZ4LCArK2ksIHgpO1xuICAgIGZvciAoY29uc3Qgd3Mgb2YgcylcbiAgICAgIGlmIChmYyh3cywgd3gpPT09MCkgY29udGludWUgeDtcbiAgICBzLnB1c2god3gpOyBhLnB1c2godngpO1xuICB9XG4gIHJldHVybiBhO1xufVxuXG5cbi8qKlxuICogT2J0YWluIHZhbHVlcyBwcmVzZW50IGluIGFueSBhcnJheS5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0geSBhbm90aGVyIGFycmF5XG4gKiBAcGFyYW0gZmMgY29tcGFyZSBmdW5jdGlvbiAoYSwgYilcbiAqIEBwYXJhbSBmbSBtYXAgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcmV0dXJucyB4IOKIqiB5ID0gXFx7diB8IHYg4oiIIHggb3IgdiDiiIggeVxcfVxuICovXG5leHBvcnQgZnVuY3Rpb24gdW5pb248VCwgVT1UPih4OiBUW10sIHk6IFRbXSwgZmM6IENvbXBhcmVGdW5jdGlvbjxUfFU+IHwgbnVsbD1udWxsLCBmbTogTWFwRnVuY3Rpb248VCwgVHxVPiB8IG51bGw9bnVsbCk6IFRbXSB7XG4gIHJldHVybiB1bmlvbiQoeC5zbGljZSgpLCB5LCBmYywgZm0pO1xufVxuXG5cbi8qKlxuICogT2J0YWluIHZhbHVlcyBwcmVzZW50IGluIGFueSBhcnJheSFcbiAqIEBwYXJhbSB4IGFuIGFycmF5ICh1cGRhdGVkISlcbiAqIEBwYXJhbSB5IGFub3RoZXIgYXJyYXlcbiAqIEBwYXJhbSBmYyBjb21wYXJlIGZ1bmN0aW9uIChhLCBiKVxuICogQHBhcmFtIGZtIG1hcCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEByZXR1cm5zIHggPSB4IOKIqiB5ID0gXFx7diB8IHYg4oiIIHggb3IgdiDiiIggeVxcfVxuICovXG5leHBvcnQgZnVuY3Rpb24gdW5pb24kPFQsIFU9VD4oeDogVFtdLCB5OiBUW10sIGZjOiBDb21wYXJlRnVuY3Rpb248VHxVPiB8IG51bGw9bnVsbCwgZm06IE1hcEZ1bmN0aW9uPFQsIFR8VT4gfCBudWxsPW51bGwpOiBUW10ge1xuICBpZiAoZmMpIHJldHVybiB1bmlvbkR1YWwkKHgsIHksIGZjLCBmbSk7XG4gIGVsc2UgICAgcmV0dXJuIHVuaW9uTWFwJCAoeCwgeSwgZm0pO1xufVxuXG5mdW5jdGlvbiB1bmlvbk1hcCQ8VCwgVT1UPih4OiBUW10sIHk6IFRbXSwgZm06IE1hcEZ1bmN0aW9uPFQsIFR8VT4gfCBudWxsPW51bGwpOiBUW10ge1xuICBmbSA9IGZtIHx8IElERU5USVRZO1xuICBjb25zdCBzICA9IHRvU2V0KHgsIGZtKTsgbGV0IGkgPSAtMTtcbiAgZm9yIChjb25zdCB2eSBvZiB5KSB7XG4gICAgY29uc3Qgd3kgPSBmbSh2eSwgKytpLCB5KTtcbiAgICBpZiAoIXMuaGFzKHd5KSkgeC5wdXNoKHZ5KTtcbiAgfVxuICByZXR1cm4geDtcbn1cblxuZnVuY3Rpb24gdW5pb25EdWFsJDxULCBVPVQ+KHg6IFRbXSwgeTogVFtdLCBmYzogQ29tcGFyZUZ1bmN0aW9uPFR8VT4gfCBudWxsPW51bGwsIGZtOiBNYXBGdW5jdGlvbjxULCBUfFU+IHwgbnVsbD1udWxsKTogVFtdIHtcbiAgZmMgPSBmYyB8fCBDT01QQVJFO1xuICBmbSA9IGZtIHx8IElERU5USVRZO1xuICBjb25zdCB4MSA9IHgubWFwKGZtKTsgbGV0IGkgPSAtMTtcbiAgeTogZm9yIChjb25zdCB2eSBvZiB5KSB7XG4gICAgY29uc3Qgd3kgPSBmbSh2eSwgKytpLCB5KTtcbiAgICBmb3IgKGNvbnN0IHd4IG9mIHgxKVxuICAgICAgaWYgKGZjKHd4LCB3eSk9PT0wKSBjb250aW51ZSB5O1xuICAgIHgucHVzaCh2eSk7XG4gIH1cbiAgcmV0dXJuIHg7XG59XG5cblxuLyoqXG4gKiBPYnRhaW4gdmFsdWVzIHByZXNlbnQgaW4gYm90aCBhcnJheXMuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIHkgYW5vdGhlciBhcnJheVxuICogQHBhcmFtIGZjIGNvbXBhcmUgZnVuY3Rpb24gKGEsIGIpXG4gKiBAcGFyYW0gZm0gbWFwIGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHJldHVybnMgeCDiiKkgeSA9IFxce3YgfCB2IOKIiCB4LCB2IOKIiCB5XFx9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpbnRlcnNlY3Rpb248VCwgVT1UPih4OiBUW10sIHk6IFRbXSwgZmM6IENvbXBhcmVGdW5jdGlvbjxUfFU+IHwgbnVsbD1udWxsLCBmbTogTWFwRnVuY3Rpb248VCwgVHxVPiB8IG51bGw9bnVsbCk6IFRbXSB7XG4gIGlmIChmYykgcmV0dXJuIGludGVyc2VjdGlvbkR1YWwoeCwgeSwgZmMsIGZtKTtcbiAgZWxzZSAgICByZXR1cm4gaW50ZXJzZWN0aW9uTWFwICh4LCB5LCBmbSk7XG59XG5cbmZ1bmN0aW9uIGludGVyc2VjdGlvbk1hcDxULCBVPVQ+KHg6IFRbXSwgeTogVFtdLCBmbTogTWFwRnVuY3Rpb248VCwgVHxVPiB8IG51bGw9bnVsbCk6IFRbXSB7XG4gIGZtID0gZm0gfHwgSURFTlRJVFk7XG4gIGNvbnN0IHMgID0gdG9TZXQoeSwgZm0pO1xuICBsZXQgaSAgPSAtMTsgY29uc3QgYSA9IFtdO1xuICBmb3IgKGNvbnN0IHZ4IG9mIHgpIHtcbiAgICBjb25zdCB3eCA9IGZtKHZ4LCArK2ksIHgpO1xuICAgIGlmIChzLmhhcyh3eCkpIGEucHVzaCh2eCk7XG4gIH1cbiAgcmV0dXJuIGE7XG59XG5cbmZ1bmN0aW9uIGludGVyc2VjdGlvbkR1YWw8VCwgVT1UPih4OiBUW10sIHk6IFRbXSwgZmM6IENvbXBhcmVGdW5jdGlvbjxUfFU+IHwgbnVsbD1udWxsLCBmbTogTWFwRnVuY3Rpb248VCwgVHxVPiB8IG51bGw9bnVsbCk6IFRbXSB7XG4gIGZjID0gZmMgfHwgQ09NUEFSRTtcbiAgZm0gPSBmbSB8fCBJREVOVElUWTtcbiAgY29uc3QgeTEgPSBbLi4ueV0ubWFwKGZtKTtcbiAgbGV0IGkgID0gLTE7IGNvbnN0IGEgPSBbXTtcbiAgeDogZm9yIChjb25zdCB2eCBvZiB4KSB7XG4gICAgY29uc3Qgd3ggPSBmbSh2eCwgKytpLCB4KTtcbiAgICBmb3IgKGNvbnN0IHd5IG9mIHkxKVxuICAgICAgaWYgKGZjKHd4LCB3eSk9PT0wKSB7IGEucHVzaCh2eCk7IGNvbnRpbnVlIHg7IH1cbiAgfVxuICByZXR1cm4gYTtcbn1cblxuXG4vKipcbiAqIE9idGFpbiB2YWx1ZXMgbm90IHByZXNlbnQgaW4gYW5vdGhlciBhcnJheS5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0geSBhbm90aGVyIGFycmF5XG4gKiBAcGFyYW0gZmMgY29tcGFyZSBmdW5jdGlvbiAoYSwgYilcbiAqIEBwYXJhbSBmbSBtYXAgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcmV0dXJucyB4IC0geSA9IFxce3YgfCB2IOKIiCB4LCB2IOKIiSB5XFx9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBkaWZmZXJlbmNlPFQsIFU9VD4oeDogVFtdLCB5OiBUW10sIGZjOiBDb21wYXJlRnVuY3Rpb248VHxVPiB8IG51bGw9bnVsbCwgZm06IE1hcEZ1bmN0aW9uPFQsIFR8VT4gfCBudWxsPW51bGwpOiBUW10ge1xuICBpZiAoZmMpIHJldHVybiBkaWZmZXJlbmNlRHVhbCh4LCB5LCBmYywgZm0pO1xuICBlbHNlICAgIHJldHVybiBkaWZmZXJlbmNlTWFwICh4LCB5LCBmbSk7XG59XG5cbmZ1bmN0aW9uIGRpZmZlcmVuY2VNYXA8VCwgVT1UPih4OiBUW10sIHk6IFRbXSwgZm06IE1hcEZ1bmN0aW9uPFQsIFR8VT4gfCBudWxsPW51bGwpOiBUW10ge1xuICBmbSA9IGZtIHx8IElERU5USVRZO1xuICBjb25zdCBzICA9IHRvU2V0KHksIGZtKTtcbiAgbGV0IGkgID0gLTE7IGNvbnN0IGEgPSBbXTtcbiAgZm9yIChjb25zdCB2eCBvZiB4KSB7XG4gICAgY29uc3Qgd3ggPSBmbSh2eCwgKytpLCB4KTtcbiAgICBpZiAoIXMuaGFzKHd4KSkgYS5wdXNoKHZ4KTtcbiAgfVxuICByZXR1cm4gYTtcbn1cblxuZnVuY3Rpb24gZGlmZmVyZW5jZUR1YWw8VCwgVT1UPih4OiBUW10sIHk6IFRbXSwgZmM6IENvbXBhcmVGdW5jdGlvbjxUfFU+IHwgbnVsbD1udWxsLCBmbTogTWFwRnVuY3Rpb248VCwgVHxVPiB8IG51bGw9bnVsbCk6IFRbXSB7XG4gIGZjID0gZmMgfHwgQ09NUEFSRTtcbiAgZm0gPSBmbSB8fCBJREVOVElUWTtcbiAgY29uc3QgeTEgPSBbLi4ueV0ubWFwKGZtKTtcbiAgbGV0IGkgID0gLTE7IGNvbnN0IGEgID0gW107XG4gIHg6IGZvciAoY29uc3Qgdnggb2YgeCkge1xuICAgIGNvbnN0IHd4ID0gZm0odngsICsraSwgeCk7XG4gICAgZm9yIChjb25zdCB3eSBvZiB5MSlcbiAgICAgIGlmIChmYyh3eCwgd3kpPT09MCkgY29udGludWUgeDtcbiAgICBhLnB1c2godngpO1xuICB9XG4gIHJldHVybiBhO1xufVxuXG5cbi8qKlxuICogT2J0YWluIHZhbHVlcyBub3QgcHJlc2VudCBpbiBib3RoIGFycmF5cy5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0geSBhbm90aGVyIGFycmF5XG4gKiBAcGFyYW0gZmMgY29tcGFyZSBmdW5jdGlvbiAoYSwgYilcbiAqIEBwYXJhbSBmbSBtYXAgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcmV0dXJucyB4LXkg4oiqIHkteFxuICovXG5leHBvcnQgZnVuY3Rpb24gc3ltbWV0cmljRGlmZmVyZW5jZTxULCBVPVQ+KHg6IFRbXSwgeTogVFtdLCBmYzogQ29tcGFyZUZ1bmN0aW9uPFR8VT4gfCBudWxsPW51bGwsIGZtOiBNYXBGdW5jdGlvbjxULCBUfFU+IHwgbnVsbD1udWxsKTogVFtdIHtcbiAgY29uc3QgeDAgPSBmcm9tSXRlcmFibGUkKHgpO1xuICBjb25zdCB5MCA9IGZyb21JdGVyYWJsZSQoeSk7XG4gIGNvbnN0IGF4ID0gZGlmZmVyZW5jZSh4MCwgeTAsIGZjLCBmbSk7XG4gIGNvbnN0IGF5ID0gZGlmZmVyZW5jZSh5MCwgeDAsIGZjLCBmbSk7XG4gIHJldHVybiBjb25jYXQkKGF4LCBheSk7XG59XG5cblxuLyoqXG4gKiBPYnRhaW4gY2FydGVzaWFuIHByb2R1Y3Qgb2YgYXJyYXlzLlxuICogQHBhcmFtIHhzIGFycmF5c1xuICogQHBhcmFtIGZtIG1hcCBmdW5jdGlvbiAodnMsIGkpXG4gKiBAcmV0dXJucyB44oKAIMOXIHjigoEgw5cgLi4uID0gXFx7W3bigoAsIHbigoEsIC4uLl0gfCB24oKAIOKIiCB44oKALCB24oKBIOKIiCB44oKBLCAuLi5dIFxcfVxuICovXG5leHBvcnQgZnVuY3Rpb24gY2FydGVzaWFuUHJvZHVjdDxULCBVPVQ+KHhzOiBUW11bXSwgZm06IE1hcEZ1bmN0aW9uPFRbXSwgVFtdfFU+IHwgbnVsbD1udWxsKTogKFRbXXxVKVtdIHtcbiAgZm0gPSBmbSB8fCBJREVOVElUWTtcbiAgY29uc3QgWFMgPSB4cy5sZW5ndGg7XG4gIGNvbnN0IGE6IChUW118VSlbXSA9IFtdO1xuICBpZiAoWFM9PT0wKSByZXR1cm4gYTtcbiAgY29uc3QgaXMgPSBuZXcgQXJyYXkoWFMpLmZpbGwoMCk7XG4gIGNvbnN0IGxzID0geHMubWFwKHggPT4geC5sZW5ndGgpO1xuICBpZiAobHMuc29tZShsID0+IGw9PT0wKSkgcmV0dXJuIGE7XG4gIGZvciAobGV0IGk9MDs7ICsraSkge1xuICAgIGNvbnN0IHZzOiBUW10gPSBbXTtcbiAgICBmb3IgKGxldCBqPTA7IGo8WFM7ICsrailcbiAgICAgIHZzLnB1c2goeHNbal1baXNbal1dKTtcbiAgICBhLnB1c2goZm0odnMsIGksIG51bGwpKTtcbiAgICBsZXQgciA9IFhTLTE7XG4gICAgZm9yICg7IHI+PTA7IC0tcikge1xuICAgICAgaWYgKCsraXNbcl08bHNbcl0pIGJyZWFrO1xuICAgICAgaXNbcl0gPSAwO1xuICAgIH1cbiAgICBpZiAocjwwKSBicmVhaztcbiAgfVxuICByZXR1cm4gYTtcbn1cbi8vICNlbmRyZWdpb25cbi8vICNlbmRyZWdpb25cbiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxTQUFRLFFBQVEsRUFBRSxPQUFPLFFBQU8sd0JBQXdCO0FBQ3hELFNBQVEsR0FBRyxRQUFPLG9CQUFvQjtBQXFHdEMsYUFBYTtBQUtiLGtCQUFrQjtBQUNsQixrQkFBa0I7QUFFbEIsa0JBQWtCO0FBQ2xCLGtCQUFrQjtBQUVsQixnQ0FBZ0MsR0FDaEMsU0FBUyxNQUFjLENBQU0sRUFBRSxLQUE2QixJQUFJO0VBQzlELElBQUksQ0FBQyxJQUFJLE9BQU8sSUFBSSxJQUFJO0VBQ3hCLE1BQU0sSUFBSSxJQUFJO0VBQVUsSUFBSSxJQUFJLENBQUM7RUFDakMsS0FBSyxNQUFNLEtBQUssRUFDZCxFQUFFLEdBQUcsQ0FBQyxHQUFHLEdBQUcsRUFBRSxHQUFHO0VBQ25CLE9BQU87QUFDVDtBQUNBLGFBQWE7QUFLYixtQkFBbUI7QUFDbkIsbUJBQW1CO0FBRW5COzs7Ozs7Q0FNQyxHQUNELE9BQU8sU0FBUyxVQUFVLENBQVMsRUFBRSxDQUFTLEVBQUUsS0FBVyxDQUFDO0VBQzFELE1BQU0sSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFFLElBQUksSUFBSSxFQUFFO0VBQzVCLElBQUssSUFBSSxJQUFFLEdBQUcsSUFBRSxHQUFHLEVBQUUsR0FBRyxLQUFHLEdBQ3pCLEVBQUUsSUFBSSxDQUFDO0VBQ1QsT0FBTztBQUNUO0FBR0E7Ozs7O0NBS0MsR0FDRCxPQUFPLFNBQVMsZUFBa0IsRUFBVyxFQUFFLENBQVM7RUFDdEQsTUFBTSxJQUFJLEVBQUU7RUFDWixJQUFLLElBQUksSUFBRSxHQUFHLElBQUUsR0FBRyxFQUFFLEVBQ25CLEVBQUUsSUFBSSxDQUFDO0VBQ1QsT0FBTztBQUNUO0FBQ0EsU0FBUSxrQkFBa0IsUUFBUSxHQUFFO0FBR3BDOzs7Ozs7Q0FNQyxHQUNELE9BQU8sU0FBUyxnQkFBbUIsRUFBcUIsRUFBRSxDQUFJLEVBQUUsQ0FBUztFQUN2RSxNQUFNLElBQUksRUFBRTtFQUNaLElBQUksTUFBSSxHQUFHLEVBQUUsSUFBSSxDQUFDO0VBQ2xCLElBQUssSUFBSSxJQUFFLEdBQUcsTUFBSSxHQUFHLEVBQUUsRUFDckIsRUFBRSxJQUFJLENBQUMsSUFBSSxHQUFHLEdBQUcsR0FBRztFQUN0QixPQUFPO0FBQ1Q7QUFDQSxTQUFRLG1CQUFtQixTQUFTLEdBQUU7QUFHdEM7Ozs7Q0FJQyxHQUNELE9BQU8sU0FBUyxhQUFnQixDQUFjO0VBQzVDLE9BQU87T0FBSTtHQUFFO0FBQ2Y7QUFDQSxTQUFRLGdCQUFnQixJQUFJLEdBQUU7QUFHOUI7Ozs7Q0FJQyxHQUNELE9BQU8sU0FBUyxjQUFpQixDQUFjO0VBQzdDLE9BQU8sTUFBTSxPQUFPLENBQUMsS0FBSSxJQUFJO09BQUk7R0FBRTtBQUNyQztBQUNBLFNBQVEsaUJBQWlCLEtBQUssR0FBRTtBQUNoQyxhQUFhO0FBS2IsZ0JBQWdCO0FBQ2hCLGdCQUFnQjtBQUVoQjs7OztDQUlDLEdBQ0QsT0FBTyxTQUFTLGFBQWdCLENBQU07RUFDcEMsT0FBTyxFQUFFLEtBQUs7QUFDaEI7QUFDQSxTQUFRLGdCQUFnQixLQUFLLEdBQUU7QUFHL0I7Ozs7Q0FJQyxHQUNELE9BQU8sU0FBUyxVQUFhLENBQU07RUFDakMsT0FBTyxnQkFBZ0I7QUFDekI7QUFDQSxhQUFhO0FBS2IsZ0JBQWdCO0FBQ2hCLGdCQUFnQjtBQUVoQjs7OztDQUlDLEdBQ0QsT0FBTyxTQUFTLEdBQUcsQ0FBVTtFQUMzQixPQUFPLE1BQU0sT0FBTyxDQUFDO0FBQ3ZCO0FBR0E7Ozs7Q0FJQyxHQUNELE9BQU8sU0FBUyxLQUFRLENBQU07RUFDNUIsT0FBTztPQUFJLEVBQUUsSUFBSTtHQUFHO0FBQ3RCO0FBR0E7Ozs7Q0FJQyxHQUNELE9BQU8sU0FBUyxNQUFTLENBQU07RUFDN0IsT0FBTyxFQUFFLElBQUk7QUFDZjtBQUdBOzs7O0NBSUMsR0FDRCxPQUFPLFNBQVMsT0FBVSxDQUFNO0VBQzlCLE9BQU8sRUFBRSxLQUFLO0FBQ2hCO0FBR0E7Ozs7Q0FJQyxHQUNELE9BQU8sU0FBUyxRQUFXLENBQU07RUFDL0IsT0FBTyxFQUFFLE1BQU07QUFDakI7QUFHQTs7OztDQUlDLEdBQ0QsT0FBTyxTQUFTLFFBQVcsQ0FBTTtFQUMvQixPQUFPO09BQUksRUFBRSxPQUFPO0dBQUc7QUFDekI7QUFHQTs7OztDQUlDLEdBQ0QsT0FBTyxTQUFTLFNBQVksQ0FBTTtFQUNoQyxPQUFPLEVBQUUsT0FBTztBQUNsQjtBQUNBLGFBQWE7QUFLYixnQkFBZ0I7QUFDaEIsZ0JBQWdCO0FBRWhCOzs7OztDQUtDLEdBQ0QsT0FBTyxTQUFTLE1BQVMsQ0FBTSxFQUFFLENBQVM7RUFDeEMsTUFBTSxJQUFJLEVBQUUsTUFBTTtFQUNsQixPQUFPLEtBQUcsSUFBRyxLQUFLLEdBQUcsQ0FBQyxHQUFHLEtBQUssS0FBSyxHQUFHLENBQUMsSUFBRSxHQUFHO0FBQzlDO0FBR0E7Ozs7OztDQU1DLEdBQ0QsT0FBTyxTQUFTLFdBQWMsQ0FBTSxFQUFFLElBQVUsQ0FBQyxFQUFFLElBQVUsRUFBRSxNQUFNO0VBQ25FLE1BQU0sSUFBSSxFQUFFLE1BQU07RUFDbEIsSUFBSSxLQUFHLElBQUcsS0FBSyxHQUFHLENBQUMsR0FBRyxLQUFLLEtBQUssR0FBRyxDQUFDLElBQUUsR0FBRztFQUN6QyxJQUFJLEtBQUcsSUFBRyxLQUFLLEdBQUcsQ0FBQyxHQUFHLEtBQUssS0FBSyxHQUFHLENBQUMsSUFBRSxHQUFHO0VBQ3pDLE9BQU87SUFBQztJQUFHLEtBQUssR0FBRyxDQUFDLEdBQUc7R0FBRztBQUM1QjtBQUNBLGFBQWE7QUFLYixpQkFBaUI7QUFDakIsaUJBQWlCO0FBRWpCOzs7O0NBSUMsR0FDRCxPQUFPLFNBQVMsUUFBVyxDQUFNO0VBQy9CLE9BQU8sRUFBRSxNQUFNLEtBQUc7QUFDcEI7QUFHQTs7Ozs7O0NBTUMsR0FDRCxPQUFPLFNBQVMsT0FBVSxDQUFNLEVBQUUsSUFBVSxDQUFDLEVBQUUsSUFBVSxFQUFFLE1BQU07RUFDL0QsQ0FBQyxHQUFHLEVBQUUsR0FBRyxXQUFXLEdBQUcsR0FBRztFQUMxQixPQUFPLElBQUU7QUFDWDtBQUNBLFNBQVEsVUFBVSxJQUFJLEdBQUU7QUFHeEI7Ozs7OztDQU1DLEdBQ0QsT0FBTyxTQUFTLFFBQVcsQ0FBTSxFQUFFLENBQVMsRUFBRSxFQUFLO0VBQ2pELE1BQU0sSUFBSSxFQUFFLE1BQU07RUFBRSxFQUFFLE1BQU0sR0FBRztFQUMvQixJQUFJLElBQUUsR0FBRyxFQUFFLElBQUksQ0FBQyxJQUFJO0VBQ3BCLE9BQU87QUFDVDtBQUdBOzs7O0NBSUMsR0FDRCxPQUFPLFNBQVMsT0FBVSxDQUFNO0VBQzlCLEVBQUUsTUFBTSxHQUFHO0VBQ1gsT0FBTztBQUNUO0FBQ0EsYUFBYTtBQUtiLGtCQUFrQjtBQUNsQixrQkFBa0I7QUFFbEI7Ozs7O0NBS0MsR0FDRCxPQUFPLFNBQVMsSUFBTyxDQUFNLEVBQUUsQ0FBUztFQUN0QyxPQUFPLENBQUMsQ0FBQyxNQUFNLEdBQUcsR0FBRztBQUN2QjtBQUNBLFNBQVEsT0FBTyxFQUFFLEdBQUU7QUFHbkIsNkJBQTZCO0FBQzdCLDhCQUE4QjtBQUc5Qjs7Ozs7Q0FLQyxHQUNELE9BQU8sU0FBUyxPQUFVLENBQU0sRUFBRSxFQUFZO0VBQzVDLE9BQU8sR0FBRyxHQUFHLENBQUMsQ0FBQSxJQUFLLElBQUksR0FBRztBQUM1QjtBQUdBOzs7OztDQUtDLEdBQ0QsT0FBTyxTQUFTLFFBQVEsQ0FBWSxFQUFFLENBQVc7RUFDL0MsSUFBSSxJQUF5QjtFQUM3QixLQUFLLE1BQU0sS0FBSyxFQUNkLElBQUksR0FBRyxLQUFJLElBQUksR0FBRyxLQUFLO0VBQ3pCLE9BQU87QUFDVDtBQUdBOzs7OztDQUtDLEdBQ0QsT0FBTyxTQUFTLFFBQVEsQ0FBWSxFQUFFLENBQVc7RUFDL0MsSUFBSSxJQUF5QjtFQUM3QixLQUFLLE1BQU0sS0FBSyxFQUFHO0lBQ2pCLElBQUksQ0FBQyxHQUFHLElBQUksT0FBTztJQUNuQixJQUFJLElBQUksR0FBRztFQUNiO0VBQ0EsT0FBTztBQUNUO0FBR0E7Ozs7OztDQU1DLEdBQ0QsT0FBTyxTQUFTLElBQU8sQ0FBTSxFQUFFLENBQVMsRUFBRSxDQUFJO0VBQzVDLE9BQU8sS0FBSyxFQUFFLEtBQUssSUFBSSxHQUFHO0FBQzVCO0FBQ0EsU0FBUSxPQUFPLElBQUksR0FBRTtBQUdyQjs7Ozs7O0NBTUMsR0FDRCxPQUFPLFNBQVMsS0FBUSxDQUFNLEVBQUUsQ0FBUyxFQUFFLENBQUk7RUFDN0MsQ0FBQyxDQUFDLE1BQU0sR0FBRyxHQUFHLEdBQUc7RUFDakIsT0FBTztBQUNUO0FBR0Esb0JBQW9CO0FBQ3BCLGtCQUFrQjtBQUdsQjs7Ozs7O0NBTUMsR0FDRCxPQUFPLFNBQVMsU0FBUyxDQUFZLEVBQUUsQ0FBVyxFQUFFLENBQVU7RUFDNUQsTUFBTSxJQUFJLFFBQVEsR0FBRyxFQUFFLEtBQUssQ0FBQyxHQUFHLENBQUM7RUFDakMsSUFBSSxHQUFHLElBQUksS0FBSyxHQUFHLEtBQUssSUFBYztFQUN0QyxPQUFPO0FBQ1Q7QUFHQTs7Ozs7O0NBTUMsR0FDRCxPQUFPLFNBQVMsS0FBUSxDQUFNLEVBQUUsQ0FBUyxFQUFFLENBQVM7RUFDbEQsT0FBTyxNQUFNLEVBQUUsS0FBSyxJQUFJLEdBQUc7QUFDN0I7QUFHQTs7Ozs7O0NBTUMsR0FDRCxPQUFPLFNBQVMsTUFBUyxDQUFNLEVBQUUsQ0FBUyxFQUFFLENBQVM7RUFDbkQsSUFBSSxNQUFNLEdBQUc7RUFBSSxJQUFJLE1BQU0sR0FBRztFQUM5QixNQUFNLElBQUksQ0FBQyxDQUFDLEVBQUU7RUFBRSxDQUFDLENBQUMsRUFBRSxHQUFHLENBQUMsQ0FBQyxFQUFFO0VBQUUsQ0FBQyxDQUFDLEVBQUUsR0FBRztFQUNwQyxPQUFPO0FBQ1Q7QUFHQTs7Ozs7O0NBTUMsR0FDRCxTQUFTLFNBQVksQ0FBTSxFQUFFLENBQVMsRUFBRSxDQUFTO0VBQy9DLE1BQU0sSUFBSSxDQUFDLENBQUMsRUFBRTtFQUFFLENBQUMsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFDLEVBQUU7RUFBRSxDQUFDLENBQUMsRUFBRSxHQUFHO0VBQ3BDLE9BQU87QUFDVDtBQUNBLDZDQUE2QztBQUc3Qzs7Ozs7Ozs7Q0FRQyxHQUNELE9BQU8sU0FBUyxXQUFjLENBQU0sRUFBRSxDQUFTLEVBQUUsQ0FBUyxFQUFFLENBQVMsRUFBRSxDQUFTO0VBQzlFLENBQUMsR0FBRyxFQUFFLEdBQUcsV0FBVyxHQUFHLEdBQUc7RUFDMUIsQ0FBQyxHQUFHLEVBQUUsR0FBRyxXQUFXLEdBQUcsR0FBRztFQUMxQixJQUFJLElBQUUsR0FBRyxDQUFDLEdBQUcsR0FBRyxHQUFHLEVBQUUsR0FBRztJQUFDO0lBQUc7SUFBRztJQUFHO0dBQUU7RUFDcEMsSUFBSSxJQUFFLEdBQUcsT0FBTyxFQUFFLEtBQUssSUFBSywwQkFBMEI7RUFDdEQsT0FBTyxFQUFFLEtBQUssQ0FBQyxHQUFHLEdBQUcsTUFBTSxDQUFDLEVBQUUsS0FBSyxDQUFDLEdBQUcsSUFBSSxFQUFFLEtBQUssQ0FBQyxHQUFHLElBQUksRUFBRSxLQUFLLENBQUM7QUFDcEU7QUFHQTs7Ozs7Ozs7Q0FRQyxHQUNELE9BQU8sU0FBUyxZQUFlLENBQU0sRUFBRSxDQUFTLEVBQUUsQ0FBUyxFQUFFLENBQVMsRUFBRSxDQUFTO0VBQy9FLENBQUMsR0FBRyxFQUFFLEdBQUcsV0FBVyxHQUFHLEdBQUc7RUFDMUIsQ0FBQyxHQUFHLEVBQUUsR0FBRyxXQUFXLEdBQUcsR0FBRztFQUMxQixJQUFJLElBQUUsR0FBRyxDQUFDLEdBQUcsR0FBRyxHQUFHLEVBQUUsR0FBRztJQUFDO0lBQUc7SUFBRztJQUFHO0dBQUU7RUFDcEMsSUFBSSxJQUFFLEdBQUcsT0FBTyxHQUFJLDBCQUEwQjtFQUM5QyxNQUFNLElBQUksRUFBRSxLQUFLLENBQUMsR0FBRztFQUNyQixFQUFFLE1BQU0sQ0FBQyxHQUFHLElBQUUsTUFBTSxFQUFFLEtBQUssQ0FBQyxHQUFHO0VBQy9CLEVBQUUsTUFBTSxDQUFDLEdBQUcsSUFBRSxNQUFNO0VBQ3BCLE9BQU87QUFDVDtBQUNBLG1CQUFtQjtBQUduQjs7Ozs7Q0FLQyxHQUNELE9BQU8sU0FBUyxPQUFVLENBQU0sRUFBRSxDQUFTO0VBQ3pDLElBQUksTUFBTSxHQUFHO0VBQ2IsT0FBTyxFQUFFLEtBQUssQ0FBQyxHQUFHLEdBQUcsTUFBTSxDQUFDLEVBQUUsS0FBSyxDQUFDLElBQUU7QUFDeEM7QUFHQTs7Ozs7Q0FLQyxHQUNELE9BQU8sU0FBUyxRQUFXLENBQU0sRUFBRSxDQUFTO0VBQzFDLEVBQUUsTUFBTSxDQUFDLEdBQUc7RUFDWixPQUFPO0FBQ1Q7QUFHQTs7Ozs7Q0FLQyxHQUNELE9BQU8sU0FBUyxZQUFZLENBQVksRUFBRSxDQUFXO0VBQ25ELE1BQU0sSUFBSSxRQUFRLEdBQUcsRUFBRSxLQUFLLENBQUMsR0FBRyxDQUFDO0VBQ2pDLElBQUksR0FBRyxJQUFJLEVBQUUsTUFBTSxDQUFDLEtBQUssSUFBYztFQUN2QyxPQUFPO0FBQ1Q7QUFDQSxhQUFhO0FBS2IsZUFBZTtBQUNmLGVBQWU7QUFFZjs7Ozs7O0NBTUMsR0FDRCxPQUFPLFNBQVMsU0FBaUIsQ0FBTSxFQUFFLEtBQWdDLElBQUksRUFBRSxLQUErQixJQUFJO0VBQ2hILE9BQU8sb0JBQW9CLEdBQUcsSUFBSSxRQUFRLENBQUM7QUFDN0M7QUFHQTs7Ozs7O0NBTUMsR0FDRCxPQUFPLFNBQVMsaUJBQXlCLENBQU0sRUFBRSxLQUFnQyxJQUFJLEVBQUUsS0FBK0IsSUFBSTtFQUN4SCxPQUFPLG9CQUFvQixHQUFHLElBQUksT0FBTztBQUMzQztBQUdBOzs7Ozs7Q0FNQyxHQUNELE9BQU8sU0FBUyxvQkFBNEIsQ0FBTSxFQUFFLEtBQWdDLElBQUksRUFBRSxLQUErQixJQUFJO0VBQzNILEtBQUssTUFBTTtFQUNYLEtBQUssTUFBTTtFQUNYLE1BQU0sSUFBSyxFQUFFLE1BQU07RUFDbkIsSUFBSSxLQUFHLEdBQUcsT0FBTyxDQUFDO0VBQ2xCLElBQUksS0FBSyxHQUFHLENBQUMsQ0FBQyxFQUFFLEVBQUUsR0FBRztFQUNyQixJQUFLLElBQUksSUFBRSxHQUFHLElBQUUsR0FBRyxFQUFFLEVBQUc7SUFDdEIsTUFBTSxJQUFJLEdBQUcsQ0FBQyxDQUFDLEVBQUUsRUFBRSxHQUFHO0lBQ3RCLElBQUksR0FBRyxJQUFJLEtBQUcsR0FBRyxPQUFPO0lBQ3hCLEtBQUs7RUFDUDtFQUNBLE9BQU8sQ0FBQztBQUNWO0FBR0E7Ozs7Ozs7Q0FPQyxHQUNELE9BQU8sU0FBUyxLQUFhLENBQU0sRUFBRSxLQUFnQyxJQUFJLEVBQUUsS0FBK0IsSUFBSSxFQUFFLEtBQTJCLElBQUk7RUFDN0ksT0FBTyxNQUFNLEVBQUUsS0FBSyxJQUFJLElBQUksSUFBSTtBQUNsQztBQUNBLFNBQVEsUUFBUSxRQUFRLEdBQUU7QUFHMUI7Ozs7Ozs7Q0FPQyxHQUNELE9BQU8sU0FBUyxNQUFjLENBQU0sRUFBRSxLQUFnQyxJQUFJLEVBQUUsS0FBK0IsSUFBSSxFQUFFLEtBQTJCLElBQUk7RUFDOUksS0FBSyxNQUFNO0VBQ1gsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLE9BQU8sRUFBRSxJQUFJLENBQUM7RUFDOUIsTUFBTSxJQUFLLEVBQUUsTUFBTTtFQUNuQixLQUFLLE1BQU07RUFDWCxLQUFLLE1BQU07RUFDWCxPQUFPLHdCQUF3QixHQUFHLEdBQUcsR0FBRyxHQUFHLElBQUksSUFBSTtBQUNyRDtBQUdBOzs7Ozs7Ozs7Q0FTQyxHQUNELE9BQU8sU0FBUyxXQUFtQixDQUFNLEVBQUUsQ0FBUyxFQUFFLENBQVMsRUFBRSxLQUFnQyxJQUFJLEVBQUUsS0FBK0IsSUFBSSxFQUFFLEtBQTJCLElBQUk7RUFDekssT0FBTyxZQUFZLEVBQUUsS0FBSyxJQUFJLEdBQUcsR0FBRyxJQUFJLElBQUk7QUFDOUM7QUFHQTs7Ozs7Ozs7O0NBU0MsR0FDRCxPQUFPLFNBQVMsWUFBb0IsQ0FBTSxFQUFFLENBQVMsRUFBRSxDQUFTLEVBQUUsS0FBZ0MsSUFBSSxFQUFFLEtBQStCLElBQUksRUFBRSxLQUEyQixJQUFJO0VBQzFLLEtBQUssTUFBTTtFQUNYLEtBQUssTUFBTTtFQUNYLEtBQUssTUFBTTtFQUNYLENBQUMsR0FBRyxFQUFFLEdBQUcsV0FBVyxHQUFHLEdBQUc7RUFDMUIsT0FBTyx3QkFBd0IsR0FBRyxHQUFHLEdBQUcsSUFBRSxHQUFHLElBQUksSUFBSTtBQUN2RDtBQUdBOzs7Ozs7OztDQVFDLEdBQ0QsT0FBTyxTQUFTLFlBQW9CLENBQU0sRUFBRSxDQUFTLEVBQUUsS0FBZ0MsSUFBSSxFQUFFLEtBQStCLElBQUksRUFBRSxLQUEyQixJQUFJO0VBQy9KLE9BQU8sYUFBYSxFQUFFLEtBQUssSUFBSSxHQUFHLElBQUksSUFBSTtBQUM1QztBQUdBOzs7Ozs7OztDQVFDLEdBQ0QsT0FBTyxTQUFTLGFBQXFCLENBQU0sRUFBRSxDQUFTLEVBQUUsS0FBZ0MsSUFBSSxFQUFFLEtBQStCLElBQUksRUFBRSxLQUEyQixJQUFJO0VBQ2hLLE9BQU8sbUJBQW1CLEdBQUcsR0FBRyxFQUFFLE1BQU0sRUFBRSxHQUFHLElBQUksSUFBSTtBQUN2RDtBQUdBOzs7Ozs7Ozs7O0NBVUMsR0FDRCxPQUFPLFNBQVMsa0JBQTBCLENBQU0sRUFBRSxDQUFTLEVBQUUsQ0FBUyxFQUFFLENBQVMsRUFBRSxLQUFnQyxJQUFJLEVBQUUsS0FBK0IsSUFBSSxFQUFFLEtBQTJCLElBQUk7RUFDM0wsT0FBTyxtQkFBbUIsRUFBRSxLQUFLLElBQUksR0FBRyxHQUFHLEdBQUcsSUFBSSxJQUFJO0FBQ3hEO0FBR0E7Ozs7Ozs7Ozs7Q0FVQyxHQUNELE9BQU8sU0FBUyxtQkFBMkIsQ0FBTSxFQUFFLENBQVMsRUFBRSxDQUFTLEVBQUUsQ0FBUyxFQUFFLEtBQWdDLElBQUksRUFBRSxLQUErQixJQUFJLEVBQUUsS0FBMkIsSUFBSTtFQUM1TCxLQUFLLE1BQU07RUFDWCxLQUFLLE1BQU07RUFDWCxLQUFLLE1BQU07RUFDWCxDQUFDLEdBQUcsRUFBRSxHQUFHLFdBQVcsR0FBRyxHQUFHO0VBQzFCLE9BQU8sd0JBQXdCLEdBQUcsR0FBRyxHQUFHLEdBQUcsSUFBSSxJQUFJO0FBQ3JEO0FBR0E7Ozs7Ozs7Ozs7Q0FVQyxHQUNELFNBQVMsd0JBQWdDLENBQU0sRUFBRSxDQUFTLEVBQUUsQ0FBUyxFQUFFLENBQVMsRUFBRSxFQUF3QixFQUFFLEVBQXVCLEVBQUUsRUFBbUI7RUFDdEosTUFBTSxJQUFJLEtBQUssS0FBSyxDQUFDLEtBQUssSUFBSSxDQUFDLElBQUUsS0FBRyxJQUFLLDZCQUE2QjtFQUN0RSxNQUFNLElBQUksSUFBK0IsbUNBQW1DO0VBQzVFLE9BQU8sMEJBQTBCLEdBQUcsR0FBRyxHQUFHLEdBQUcsR0FBRyxHQUFHLElBQUksSUFBSTtBQUM3RDtBQUdBLHNHQUFzRztBQUN0RyxTQUFTLDBCQUFrQyxDQUFNLEVBQUUsQ0FBUyxFQUFFLENBQVMsRUFBRSxDQUFTLEVBQUUsQ0FBUyxFQUFFLENBQVMsRUFBRSxFQUF3QixFQUFFLEVBQXVCLEVBQUUsRUFBbUI7RUFDOUssSUFBSSxLQUFHLEtBQUssSUFBRSxLQUFHLEdBQUcsT0FBTyxHQUF1QixrQkFBa0I7RUFDcEUsSUFBSSxJQUFFLEtBQUcsR0FBRyxPQUFPLDRCQUE0QixHQUFHLEdBQUcsR0FBRyxHQUFHLElBQUksSUFBSSxLQUFNLGlCQUFpQjtFQUMxRixJQUFJLEtBQUcsR0FBSyxPQUFPLHVCQUF1QixHQUFHLEdBQUcsR0FBRyxHQUFHLElBQUksSUFBSSxLQUFXLFlBQVk7RUFDckYsSUFBSSxJQUFJLElBQUksS0FBSyxLQUFLLENBQUMsQ0FBQyxJQUFFLENBQUMsSUFBRSxLQUFLLE1BQU0sS0FBZ0IsZUFBZTtFQUN2RSxJQUFJLDBCQUEwQixHQUFHLEdBQUcsR0FBRyxHQUFHLElBQUksSUFBSSxLQUFNLGtCQUFrQjtFQUMxRSwwQkFBMEIsR0FBRyxHQUFLLEdBQUcsR0FBRyxHQUFHLEtBQUssR0FBRyxDQUFDLElBQUUsR0FBRyxJQUFNLElBQUksSUFBSSxLQUFNLGlCQUFpQjtFQUM5RiwwQkFBMEIsR0FBRyxJQUFFLEdBQUcsR0FBRyxHQUFHLEdBQUcsS0FBSyxHQUFHLENBQUMsSUFBRSxJQUFFLEdBQUcsSUFBSSxJQUFJLElBQUksS0FBTSxrQkFBa0I7RUFDL0YsT0FBTztBQUNUO0FBR0E7Ozs7Ozs7Ozs7Q0FVQyxHQUNELFNBQVMseUJBQWlDLENBQU0sRUFBRSxDQUFTLEVBQUUsQ0FBUyxFQUFFLENBQVMsRUFBRSxFQUF3QixFQUFFLEVBQXVCLEVBQUUsRUFBbUI7RUFDdkosSUFBSSxLQUFHLEtBQUssSUFBRSxLQUFHLEdBQUcsT0FBTyxHQUEyQixrQkFBa0I7RUFDeEUsSUFBSSxJQUFJLElBQUksS0FBSyxLQUFLLENBQUMsQ0FBQyxJQUFFLENBQUMsSUFBRSxLQUFLLE1BQU0sS0FBZ0IsZUFBZTtFQUN2RSxJQUFJLDBCQUEwQixHQUFHLEdBQUcsR0FBRyxHQUFHLElBQUksSUFBSSxLQUFNLGtCQUFrQjtFQUMxRSx5QkFBeUIsR0FBRyxHQUFLLEdBQUcsS0FBSyxHQUFHLENBQUMsSUFBRSxHQUFHLElBQU0sSUFBSSxJQUFJLEtBQU0saUJBQWlCO0VBQ3ZGLHlCQUF5QixHQUFHLElBQUUsR0FBRyxHQUFHLEtBQUssR0FBRyxDQUFDLElBQUUsSUFBRSxHQUFHLElBQUksSUFBSSxJQUFJLEtBQU0sa0JBQWtCO0VBQ3hGLE9BQU87QUFDVDtBQUdBLHNDQUFzQztBQUN0QyxrSEFBa0g7QUFDbEgsU0FBUywwQkFBa0MsQ0FBTSxFQUFFLENBQVMsRUFBRSxDQUFTLEVBQUUsQ0FBUyxFQUFFLEVBQXdCLEVBQUUsRUFBdUIsRUFBRSxFQUFtQjtFQUN4SixNQUFNLEtBQUssR0FBRyxDQUFDLENBQUMsRUFBRSxFQUFFLEdBQUcsSUFBSyxjQUFjO0VBQzFDLElBQUksSUFBSyxJQUFFLEdBQUssK0JBQStCO0VBQy9DLEdBQUcsR0FBRyxHQUFHLElBQUUsSUFBSyxvQkFBb0I7RUFDcEMsSUFBSyxJQUFJLElBQUUsR0FBRyxJQUFFLElBQUUsR0FBRyxFQUFFLEVBQUc7SUFDeEIsTUFBTSxLQUFLLEdBQUcsQ0FBQyxDQUFDLEVBQUUsRUFBRSxHQUFHO0lBQ3ZCLElBQUksR0FBRyxJQUFJLE1BQU0sR0FBRztJQUNwQixHQUFHLEdBQUcsRUFBRSxHQUFHLElBQUssNkJBQTZCO0VBQy9DO0VBQ0EsR0FBRyxHQUFHLEVBQUUsR0FBRyxJQUFFLElBQUssdUJBQXVCO0VBQ3pDLE9BQU8sR0FBSSxxQkFBcUI7QUFDbEM7QUFHQTs7Ozs7Ozs7OztDQVVDLEdBQ0QsU0FBUyx1QkFBK0IsQ0FBTSxFQUFFLENBQVMsRUFBRSxDQUFTLEVBQUUsQ0FBUyxFQUFFLEVBQXdCLEVBQUUsRUFBdUIsRUFBRSxFQUFtQjtFQUNySiwyQkFBMkIsR0FBRyxHQUFHLEdBQUcsSUFBSSxJQUFJO0VBQzVDLElBQUssTUFBTSxJQUFFLElBQUUsR0FBRyxJQUFFLEtBQUssSUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEVBQUc7SUFDdEMsR0FBRyxHQUFHLEdBQUcsSUFBSyw2QkFBNkI7SUFDM0MseUJBQXlCLEdBQUcsSUFBRSxHQUFHLEdBQUcsR0FBRyxJQUFJLElBQUksS0FBTSxlQUFlO0VBQ3RFO0VBQ0EsT0FBTztBQUNUO0FBR0EsMEdBQTBHO0FBQzFHLFNBQVMsMkJBQW1DLENBQU0sRUFBRSxDQUFTLEVBQUUsQ0FBUyxFQUFFLEVBQXdCLEVBQUUsRUFBdUIsRUFBRSxFQUFtQjtFQUM5SSxJQUFLLElBQUksSUFBRSxJQUFFLEtBQUssS0FBSyxDQUFDLENBQUMsSUFBRSxDQUFDLElBQUUsSUFBSSxJQUFFLEdBQUcsRUFBRSxFQUN2Qyx5QkFBeUIsR0FBRyxHQUFHLEdBQUcsR0FBRyxJQUFJLElBQUk7QUFDakQ7QUFHQTs7Ozs7Ozs7O0NBU0MsR0FDRCxTQUFTLHlCQUFpQyxDQUFNLEVBQUUsQ0FBUyxFQUFFLENBQVMsRUFBRSxDQUFTLEVBQUUsRUFBd0IsRUFBRSxFQUF1QixFQUFFLEVBQW1CO0VBQ3ZKLElBQUksSUFBSyxHQUFXLDBCQUEwQjtFQUM5QyxNQUFNLEtBQUssSUFBRSxJQUFJLEdBQUsscUNBQXFDO0VBQzNELE1BQU0sS0FBSyxLQUFNLEdBQUsscUNBQXFDO0VBQzNELElBQUksTUFBSSxLQUFLLEdBQUcsR0FBRyxDQUFDLENBQUMsR0FBRyxFQUFFLElBQUksSUFBSSxHQUFHLENBQUMsQ0FBQyxFQUFFLEVBQUUsR0FBRyxNQUFNLEdBQUcsSUFBSSxJQUFLLHlCQUF5QjtFQUN6RixJQUFJLE1BQUksS0FBSyxHQUFHLEdBQUcsQ0FBQyxDQUFDLEdBQUcsRUFBRSxJQUFJLElBQUksR0FBRyxDQUFDLENBQUMsRUFBRSxFQUFFLEdBQUcsTUFBTSxHQUFHLElBQUksSUFBSywwQkFBMEI7RUFDMUYsSUFBSSxNQUFNLEdBQUc7SUFDWCxHQUFHLEdBQUcsR0FBRyxJQUFRLDBCQUEwQjtJQUMzQyx5QkFBeUIsR0FBRyxHQUFHLEdBQUcsR0FBRyxJQUFJLElBQUksS0FBTSxlQUFlO0VBQ3BFO0FBQ0Y7QUFHQSx3R0FBd0c7QUFDeEcsU0FBUyxvQkFBNEIsQ0FBTSxFQUFFLENBQVMsRUFBRSxDQUFTLEVBQUUsRUFBd0IsRUFBRSxFQUF1QixFQUFFLEVBQW1CO0VBQ3ZJLElBQUssSUFBSSxJQUFFLElBQUUsS0FBSyxLQUFLLENBQUMsQ0FBQyxJQUFFLENBQUMsSUFBRSxLQUFHLEdBQUcsS0FBRyxHQUFHLEVBQUUsRUFDMUMsa0JBQWtCLEdBQUcsR0FBRyxHQUFHLEdBQUcsSUFBSSxJQUFJO0FBQzFDO0FBR0E7Ozs7Ozs7OztDQVNDLEdBQ0QsU0FBUyxrQkFBMEIsQ0FBTSxFQUFFLENBQVMsRUFBRSxDQUFTLEVBQUUsQ0FBUyxFQUFFLEVBQXdCLEVBQUUsRUFBdUIsRUFBRSxFQUFtQjtFQUNoSixJQUFJLElBQUssR0FBVyx5QkFBeUI7RUFDN0MsTUFBTSxLQUFLLElBQUUsSUFBSSxJQUFJLEdBQUksK0JBQStCO0VBQ3hELE1BQU0sS0FBSyxLQUFNLEdBQVEsK0JBQStCO0VBQ3hELElBQUksS0FBRyxLQUFLLEdBQUcsR0FBRyxDQUFDLENBQUMsR0FBRyxFQUFFLElBQUksSUFBSSxHQUFHLENBQUMsQ0FBQyxFQUFFLEVBQUUsR0FBRyxNQUFNLEdBQUcsSUFBSSxJQUFLLHlCQUF5QjtFQUN4RixJQUFJLEtBQUcsS0FBSyxHQUFHLEdBQUcsQ0FBQyxDQUFDLEdBQUcsRUFBRSxJQUFJLElBQUksR0FBRyxDQUFDLENBQUMsRUFBRSxFQUFFLEdBQUcsTUFBTSxHQUFHLElBQUksSUFBSyx5QkFBeUI7RUFDeEYsSUFBSSxNQUFNLEdBQUc7SUFDWCxHQUFHLEdBQUcsR0FBRyxJQUFRLHlCQUF5QjtJQUMxQyxrQkFBa0IsR0FBRyxHQUFHLEdBQUcsR0FBRyxJQUFJLElBQUksS0FBTSxlQUFlO0VBQzdEO0FBQ0Y7QUFHQTs7Ozs7Ozs7OztDQVVDLEdBQ0QsU0FBUyw0QkFBb0MsQ0FBTSxFQUFFLENBQVMsRUFBRSxDQUFTLEVBQUUsQ0FBUyxFQUFFLEVBQXdCLEVBQUUsRUFBdUIsRUFBRSxFQUFtQjtFQUMxSix5RUFBeUU7RUFDekUsSUFBSSxPQUFLLFVBQVUsT0FBTyxvQ0FBb0MsR0FBRyxHQUFHLEdBQUcsR0FBRyxJQUFJLElBQUk7T0FDL0QsT0FBTyxnQ0FBb0MsR0FBRyxHQUFHLEdBQUcsR0FBRyxJQUFJLElBQUk7QUFDcEY7QUFHQSwrRUFBK0U7QUFDL0UsU0FBUyxnQ0FBd0MsQ0FBTSxFQUFFLENBQVMsRUFBRSxDQUFTLEVBQUUsRUFBVSxFQUFFLEVBQXdCLEVBQUUsRUFBdUIsRUFBRSxFQUFtQjtFQUMvSixJQUFLLElBQUksSUFBRSxJQUFFLEdBQUcsSUFBRSxHQUFHLEVBQUUsRUFBRztJQUN4QixNQUFNLE1BQU8sQ0FBQyxDQUFDLEVBQUU7SUFDakIsTUFBTSxPQUFPLEdBQUcsS0FBSyxHQUFHO0lBQ3hCLElBQUssSUFBSSxJQUFFLElBQUUsR0FBRyxLQUFHLEtBQUssR0FBRyxHQUFHLENBQUMsQ0FBQyxFQUFFLEVBQUUsR0FBRyxJQUFJLFFBQU0sR0FBRyxFQUFFLEVBQ3BELEdBQUcsR0FBRyxHQUFHLElBQUU7RUFDZjtFQUNBLE9BQU87QUFDVDtBQUdBLDJFQUEyRTtBQUMzRSxTQUFTLG9DQUE0QyxDQUFNLEVBQUUsQ0FBUyxFQUFFLENBQVMsRUFBRSxFQUFVLEVBQUUsRUFBd0IsRUFBRSxFQUF1QixFQUFFLEdBQW9CO0VBQ3BLLElBQUssSUFBSSxJQUFFLElBQUUsR0FBRyxJQUFFLEdBQUcsRUFBRSxFQUFHO0lBQ3hCLE1BQU0sTUFBTyxDQUFDLENBQUMsRUFBRTtJQUNqQixNQUFNLE9BQU8sR0FBRyxLQUFLLEdBQUc7SUFDeEIsSUFBSSxJQUFJLElBQUU7SUFDVixNQUFPLEtBQUcsS0FBSyxHQUFHLEdBQUcsQ0FBQyxDQUFDLEVBQUUsRUFBRSxHQUFHLElBQUksUUFBTSxHQUFHLEVBQUUsRUFDM0MsQ0FBQyxDQUFDLElBQUUsRUFBRSxHQUFHLENBQUMsQ0FBQyxFQUFFO0lBQ2YsQ0FBQyxDQUFDLElBQUUsRUFBRSxHQUFHO0VBQ1g7RUFDQSxPQUFPO0FBQ1Q7QUFHQTs7Ozs7Ozs7OztDQVVDLEdBQ0QsU0FBUyw2QkFBcUMsQ0FBTSxFQUFFLENBQVMsRUFBRSxDQUFTLEVBQUUsQ0FBUyxFQUFFLEVBQXdCLEVBQUUsRUFBdUIsRUFBRSxFQUFtQjtFQUMzSixJQUFLLElBQUksSUFBRSxHQUFHLElBQUUsS0FBSyxJQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsRUFBRztJQUNsQyxJQUFJLElBQUs7SUFDVCxJQUFJLEtBQUssR0FBRyxDQUFDLENBQUMsRUFBRSxFQUFFLEdBQUc7SUFDckIsSUFBSyxJQUFJLElBQUUsSUFBRSxHQUFHLElBQUUsR0FBRyxFQUFFLEVBQUc7TUFDeEIsTUFBTSxLQUFLLEdBQUcsQ0FBQyxDQUFDLEVBQUUsRUFBRSxHQUFHO01BQ3ZCLElBQUksR0FBRyxJQUFJLE1BQU0sR0FBRztRQUFFLElBQUk7UUFBRyxLQUFLO01BQUk7SUFDeEM7SUFDQSxHQUFHLEdBQUcsR0FBRztFQUNYO0VBQ0EsT0FBTztBQUNUO0FBQ0EsYUFBYTtBQUtiLDBCQUEwQjtBQUMxQiwwQkFBMEI7QUFFMUI7Ozs7OztDQU1DLEdBQ0QsT0FBTyxTQUFTLFFBQWdCLENBQU0sRUFBRSxLQUFnQyxJQUFJLEVBQUUsS0FBK0IsSUFBSTtFQUMvRyxNQUFNLElBQUksbUJBQW1CLEdBQUcsSUFBSTtFQUNwQyxPQUFPLENBQUMsQ0FBQyxFQUFFO0FBQ2I7QUFDQSxTQUFRLFdBQVcsR0FBRyxHQUFFO0FBR3hCOzs7Ozs7Q0FNQyxHQUNELE9BQU8sU0FBUyxhQUFxQixDQUFNLEVBQUUsS0FBZ0MsSUFBSSxFQUFFLEtBQStCLElBQUk7RUFDcEgsTUFBTSxJQUFJLG1CQUFtQixHQUFHLElBQUk7RUFDcEMsT0FBTztJQUFDO0lBQUcsQ0FBQyxDQUFDLEVBQUU7R0FBQztBQUNsQjtBQUNBLFNBQVEsZ0JBQWdCLFFBQVEsR0FBRTtBQUdsQzs7Ozs7O0NBTUMsR0FDRCxPQUFPLFNBQVMsUUFBZ0IsQ0FBTSxFQUFFLEtBQWdDLElBQUksRUFBRSxLQUErQixJQUFJO0VBQy9HLE1BQU0sSUFBSSxtQkFBbUIsR0FBRyxJQUFJO0VBQ3BDLE9BQU8sQ0FBQyxDQUFDLEVBQUU7QUFDYjtBQUNBLFNBQVEsV0FBVyxHQUFHLEdBQUU7QUFHeEI7Ozs7OztDQU1DLEdBQ0QsT0FBTyxTQUFTLGFBQXFCLENBQU0sRUFBRSxLQUFnQyxJQUFJLEVBQUUsS0FBK0IsSUFBSTtFQUNwSCxNQUFNLElBQUksbUJBQW1CLEdBQUcsSUFBSTtFQUNwQyxPQUFPO0lBQUM7SUFBRyxDQUFDLENBQUMsRUFBRTtHQUFDO0FBQ2xCO0FBQ0EsU0FBUSxnQkFBZ0IsUUFBUSxHQUFFO0FBR2xDOzs7Ozs7Q0FNQyxHQUNELE9BQU8sU0FBUyxNQUFjLENBQU0sRUFBRSxLQUFnQyxJQUFJLEVBQUUsS0FBK0IsSUFBSTtFQUM3RyxNQUFNLENBQUMsR0FBRyxFQUFFLEdBQUcsYUFBYSxHQUFHLElBQUk7RUFDbkMsT0FBTztJQUFDLENBQUMsQ0FBQyxFQUFFO0lBQUUsQ0FBQyxDQUFDLEVBQUU7R0FBQztBQUNyQjtBQUdBOzs7Ozs7Q0FNQyxHQUNELE9BQU8sU0FBUyxhQUFxQixDQUFNLEVBQUUsS0FBZ0MsSUFBSSxFQUFFLEtBQStCLElBQUk7RUFDcEgsS0FBSyxNQUFNO0VBQ1gsS0FBSyxNQUFNO0VBQ1gsTUFBTSxJQUFLLEVBQUUsTUFBTTtFQUNuQixJQUFJLE1BQUksR0FBRyxPQUFPO0lBQUM7TUFBQyxDQUFDO01BQUc7S0FBVTtJQUFFO01BQUMsQ0FBQztNQUFHO0tBQVU7R0FBQztFQUNwRCxJQUFJLElBQUssQ0FBQyxDQUFDLEVBQUUsRUFBRSxJQUFJLEdBQUcsR0FBRyxHQUFHO0VBQzVCLElBQUksS0FBSyxHQUFHLEtBQUssR0FBRyxLQUFLO0VBQ3pCLElBQUksS0FBSyxHQUFHLEtBQUssR0FBRyxLQUFLO0VBQ3pCLElBQUssSUFBSSxJQUFFLEdBQUcsSUFBRSxHQUFHLEVBQUUsRUFBRztJQUN0QixJQUFJLENBQUMsQ0FBQyxFQUFFO0lBQUUsSUFBSSxHQUFHLEdBQUcsR0FBRztJQUN2QixJQUFJLEdBQUcsR0FBRyxNQUFJLEdBQUc7TUFBRSxLQUFLO01BQUcsS0FBSztNQUFHLEtBQUs7SUFBRztJQUMzQyxJQUFJLEdBQUcsR0FBRyxNQUFJLEdBQUc7TUFBRSxLQUFLO01BQUcsS0FBSztNQUFHLEtBQUs7SUFBRztFQUM3QztFQUNBLE9BQU87SUFBQztNQUFDO01BQUk7S0FBRztJQUFFO01BQUM7TUFBSTtLQUFHO0dBQUM7QUFDN0I7QUFHQTs7Ozs7OztDQU9DLEdBQ0QsT0FBTyxTQUFTLFNBQWlCLENBQU0sRUFBRSxDQUFTLEVBQUUsS0FBdUMsSUFBSSxFQUFFLEtBQStCLElBQUk7RUFDbEksTUFBTSxLQUFLLG9CQUFvQixHQUFHLEdBQUcsSUFBSTtFQUN6QyxPQUFPLEdBQUcsR0FBRyxDQUFDLENBQUEsSUFBSyxDQUFDLENBQUMsRUFBRTtBQUN6QjtBQUdBOzs7Ozs7O0NBT0MsR0FDRCxPQUFPLFNBQVMsZUFBdUIsQ0FBTSxFQUFFLENBQVMsRUFBRSxLQUF1QyxJQUFJLEVBQUUsS0FBK0IsSUFBSTtFQUN4SSxNQUFNLEtBQUssb0JBQW9CLEdBQUcsR0FBRyxJQUFJO0VBQ3pDLE9BQU8sR0FBRyxHQUFHLENBQUMsQ0FBQSxJQUFLO01BQUM7TUFBRyxDQUFDLENBQUMsRUFBRTtLQUFDO0FBQzlCO0FBR0E7Ozs7Ozs7Q0FPQyxHQUNELE9BQU8sU0FBUyxTQUFpQixDQUFNLEVBQUUsQ0FBUyxFQUFFLEtBQXVDLElBQUksRUFBRSxLQUErQixJQUFJO0VBQ2xJLE1BQU0sS0FBSyxvQkFBb0IsR0FBRyxHQUFHLElBQUk7RUFDekMsT0FBTyxHQUFHLEdBQUcsQ0FBQyxDQUFBLElBQUssQ0FBQyxDQUFDLEVBQUU7QUFDekI7QUFHQTs7Ozs7OztDQU9DLEdBQ0QsT0FBTyxTQUFTLGVBQXVCLENBQU0sRUFBRSxDQUFTLEVBQUUsS0FBdUMsSUFBSSxFQUFFLEtBQStCLElBQUk7RUFDeEksTUFBTSxLQUFLLG9CQUFvQixHQUFHLEdBQUcsSUFBSTtFQUN6QyxPQUFPLEdBQUcsR0FBRyxDQUFDLENBQUEsSUFBSztNQUFDO01BQUcsQ0FBQyxDQUFDLEVBQUU7S0FBQztBQUM5QjtBQUdBOzs7Ozs7Q0FNQyxHQUNELE9BQU8sU0FBUyxtQkFBMkIsQ0FBTSxFQUFFLEtBQWdDLElBQUksRUFBRSxLQUErQixJQUFJO0VBQzFILEtBQUssTUFBTTtFQUNYLEtBQUssTUFBTTtFQUNYLE1BQU0sSUFBSyxFQUFFLE1BQU07RUFDbkIsSUFBSSxNQUFJLEdBQUcsT0FBTyxDQUFDO0VBQ25CLElBQUksS0FBSyxHQUFHLEtBQUssR0FBRyxDQUFDLENBQUMsRUFBRSxFQUFFLEdBQUc7RUFDN0IsSUFBSyxJQUFJLElBQUUsR0FBRyxJQUFFLEdBQUcsRUFBRSxFQUFHO0lBQ3RCLE1BQU0sSUFBSSxHQUFHLENBQUMsQ0FBQyxFQUFFLEVBQUUsR0FBRztJQUN0QixJQUFJLEdBQUcsR0FBRyxNQUFJLEdBQUc7TUFBRSxLQUFLO01BQUcsS0FBSztJQUFHO0VBQ3JDO0VBQ0EsT0FBTztBQUNUO0FBR0E7Ozs7OztDQU1DLEdBQ0QsT0FBTyxTQUFTLG1CQUEyQixDQUFNLEVBQUUsS0FBZ0MsSUFBSSxFQUFFLEtBQStCLElBQUk7RUFDMUgsS0FBSyxNQUFNO0VBQ1gsS0FBSyxNQUFNO0VBQ1gsTUFBTSxJQUFLLEVBQUUsTUFBTTtFQUNuQixJQUFJLE1BQUksR0FBRyxPQUFPLENBQUM7RUFDbkIsSUFBSSxLQUFLLEdBQUcsS0FBSyxHQUFHLENBQUMsQ0FBQyxFQUFFLEVBQUUsR0FBRztFQUM3QixJQUFLLElBQUksSUFBRSxHQUFHLElBQUUsR0FBRyxFQUFFLEVBQUc7SUFDdEIsTUFBTSxJQUFJLEdBQUcsQ0FBQyxDQUFDLEVBQUUsRUFBRSxHQUFHO0lBQ3RCLElBQUksR0FBRyxHQUFHLE1BQUksR0FBRztNQUFFLEtBQUs7TUFBRyxLQUFLO0lBQUc7RUFDckM7RUFDQSxPQUFPO0FBQ1Q7QUFHQTs7Ozs7OztDQU9DLEdBQ0QsT0FBTyxTQUFTLG9CQUE0QixDQUFNLEVBQUUsQ0FBUyxFQUFFLEtBQXVDLElBQUksRUFBRSxLQUErQixJQUFJO0VBQzdJLEtBQUssTUFBTTtFQUNYLEtBQUssTUFBTTtFQUNYLE1BQU0sSUFBSyxFQUFFLE1BQU07RUFDbkIsZ0NBQWdDO0VBQ2hDLE1BQU0sS0FBSyxLQUFLLEdBQUcsQ0FBQyxHQUFHO0VBQ3ZCLE1BQU0sS0FBSyxVQUFVLEdBQUc7RUFDeEIsb0JBQW9CLElBQUksR0FBRyxJQUFJLElBQUksQ0FBQSxJQUFLLEdBQUcsQ0FBQyxDQUFDLEVBQUUsRUFBRSxHQUFHLElBQUk7RUFDeEQsSUFBSSxLQUFLLEdBQUcsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsRUFBRSxFQUFFO0VBQzdCLDhDQUE4QztFQUM5QyxJQUFLLElBQUksSUFBRSxHQUFHLElBQUUsR0FBRyxFQUFFLEVBQUc7SUFDdEIsTUFBTSxJQUFJLEdBQUcsQ0FBQyxDQUFDLEVBQUUsRUFBRSxHQUFHO0lBQ3RCLElBQUksR0FBRyxHQUFHLE9BQU8sR0FBRztJQUNwQixFQUFFLENBQUMsRUFBRSxHQUFHO0lBQ1Isa0JBQWtCLElBQUksR0FBRyxJQUFJLEdBQUcsSUFBSSxDQUFBLElBQUssR0FBRyxDQUFDLENBQUMsRUFBRSxFQUFFLEdBQUcsSUFBSTtJQUN6RCxLQUFLLEdBQUcsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsRUFBRSxFQUFFO0VBQzNCO0VBQ0Esb0NBQW9DO0VBQ3BDLEdBQUcsSUFBSSxDQUFDLENBQUMsR0FBRyxJQUFNLEdBQUcsR0FBRyxDQUFDLENBQUMsRUFBRSxFQUFFLEdBQUcsSUFBSSxHQUFHLENBQUMsQ0FBQyxFQUFFLEVBQUUsR0FBRztFQUNqRCxPQUFPO0FBQ1Q7QUFHQTs7Ozs7OztDQU9DLEdBQ0QsT0FBTyxTQUFTLG9CQUE0QixDQUFNLEVBQUUsQ0FBUyxFQUFFLEtBQXVDLElBQUksRUFBRSxLQUErQixJQUFJO0VBQzdJLEtBQUssTUFBTTtFQUNYLE1BQU0sS0FBSyxDQUFDLEdBQWUsSUFBa0IsQ0FBQyxHQUFHLEdBQUc7RUFDcEQsT0FBTyxvQkFBb0IsR0FBRyxHQUFHLElBQUk7QUFDdkM7QUFDQSxhQUFhO0FBS2Isa0JBQWtCO0FBQ2xCLGtCQUFrQjtBQUVsQjs7Ozs7OztDQU9DLEdBQ0QsT0FBTyxTQUFTLFFBQWdCLENBQU0sRUFBRSxDQUFNLEVBQUUsS0FBZ0MsSUFBSSxFQUFFLEtBQStCLElBQUk7RUFDdkgsTUFBTSxJQUFJLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxNQUFNO0VBQ2hDLE9BQU8sTUFBSSxLQUFLLFFBQVEsR0FBRyxHQUFHLElBQUksUUFBTTtBQUMxQztBQUdBOzs7Ozs7O0NBT0MsR0FDRCxPQUFPLFNBQVMsUUFBZ0IsQ0FBTSxFQUFFLENBQU0sRUFBRSxLQUFnQyxJQUFJLEVBQUUsS0FBK0IsSUFBSTtFQUN2SCxLQUFLLE1BQU07RUFDWCxLQUFLLE1BQU07RUFDWCxNQUFNLElBQUssRUFBRSxNQUFNO0VBQ25CLE1BQU0sSUFBSyxFQUFFLE1BQU07RUFDbkIsSUFBSyxJQUFJLElBQUUsR0FBRyxJQUFFLEtBQUssR0FBRyxDQUFDLEdBQUcsSUFBSSxJQUFFLEdBQUcsRUFBRSxFQUFHO0lBQ3hDLE1BQU0sS0FBSyxHQUFHLENBQUMsQ0FBQyxFQUFFLEVBQUUsR0FBRztJQUN2QixNQUFNLEtBQUssR0FBRyxDQUFDLENBQUMsRUFBRSxFQUFFLEdBQUc7SUFDdkIsTUFBTSxJQUFLLEdBQUcsSUFBSTtJQUNsQixJQUFJLE1BQUksR0FBRyxPQUFPO0VBQ3BCO0VBQ0EsT0FBTyxLQUFLLElBQUksQ0FBQyxJQUFFO0FBQ3JCO0FBQ0EsYUFBYTtBQUtiLGVBQWU7QUFDZixlQUFlO0FBRWY7Ozs7O0NBS0MsR0FDRCxPQUFPLFNBQVMsS0FBUSxDQUFNLEVBQUUsRUFBTTtFQUNwQyxPQUFPLEVBQUUsTUFBTSxHQUFDLElBQUcsQ0FBQyxDQUFDLEVBQUUsR0FBRztBQUM1QjtBQUNBLFNBQVEsUUFBUSxLQUFLLEdBQUU7QUFDdkIsU0FBUSxRQUFRLEtBQUssR0FBRTtBQUd2Qjs7OztDQUlDLEdBQ0QsT0FBTyxTQUFTLEtBQVEsQ0FBTTtFQUM1QixPQUFPLEVBQUUsS0FBSyxDQUFDO0FBQ2pCO0FBR0E7Ozs7Q0FJQyxHQUNELE9BQU8sU0FBUyxLQUFRLENBQU07RUFDNUIsT0FBTyxFQUFFLEtBQUssQ0FBQyxHQUFHLENBQUM7QUFDckI7QUFHQTs7Ozs7Q0FLQyxHQUNELE9BQU8sU0FBUyxLQUFRLENBQU0sRUFBRSxFQUFNO0VBQ3BDLE9BQU8sRUFBRSxNQUFNLEdBQUMsSUFBRyxDQUFDLENBQUMsRUFBRSxNQUFNLEdBQUMsRUFBRSxHQUFHO0FBQ3JDO0FBQ0EsU0FBUSxRQUFRLElBQUksR0FBRTtBQUd0Qjs7Ozs7O0NBTUMsR0FDRCxPQUFPLFNBQVMsT0FBVSxDQUFNLEVBQUUsQ0FBUyxFQUFFLElBQVUsQ0FBQztFQUN0RCxJQUFJLE1BQU0sR0FBRztFQUNiLElBQUksS0FBSyxHQUFHLENBQUMsR0FBRztFQUNoQixPQUFPLEVBQUUsS0FBSyxDQUFDLEdBQUcsSUFBRTtBQUN0QjtBQUdBOzs7Ozs7Q0FNQyxHQUNELE9BQU8sU0FBUyxNQUFTLENBQU0sRUFBRSxJQUFVLENBQUMsRUFBRSxJQUFVLEVBQUUsTUFBTTtFQUM5RCxPQUFPLEVBQUUsS0FBSyxDQUFDLEdBQUc7QUFDcEI7QUFHQTs7Ozs7O0NBTUMsR0FDRCxPQUFPLFNBQVMsT0FBVSxDQUFNLEVBQUUsSUFBVSxDQUFDLEVBQUUsSUFBVSxFQUFFLE1BQU07RUFDL0QsRUFBRSxVQUFVLENBQUMsR0FBRyxHQUFHO0VBQ25CLEVBQUUsTUFBTSxHQUFHLE9BQU8sR0FBRyxHQUFHO0VBQ3hCLE9BQU87QUFDVDtBQUNBLGFBQWE7QUFLYix1QkFBdUI7QUFDdkIsdUJBQXVCO0FBRXZCOzs7Ozs7Q0FNQyxHQUNELE9BQU8sU0FBUyxTQUFZLENBQU0sRUFBRSxDQUFJLEVBQUUsSUFBVSxDQUFDO0VBQ25ELE9BQU8sRUFBRSxRQUFRLENBQUMsR0FBRztBQUN2QjtBQUdBOzs7Ozs7O0NBT0MsR0FDRCxPQUFPLFNBQVMsU0FBaUIsQ0FBTSxFQUFFLENBQUksRUFBRSxLQUFnQyxJQUFJLEVBQUUsS0FBK0IsSUFBSTtFQUN0SCxPQUFPLFlBQVksR0FBRyxHQUFHLElBQUksT0FBTztBQUN0QztBQUdBOzs7Ozs7O0NBT0MsR0FDRCxPQUFPLFNBQVMsWUFBb0IsQ0FBTSxFQUFFLENBQUksRUFBRSxLQUFnQyxJQUFJLEVBQUUsS0FBK0IsSUFBSTtFQUN6SCxLQUFLLE1BQU07RUFDWCxLQUFLLE1BQU07RUFDWCxNQUFNLElBQUssR0FBRyxHQUFHLEdBQUc7RUFBTyxJQUFJLElBQUksQ0FBQztFQUNwQyxLQUFLLE1BQU0sTUFBTSxFQUFHO0lBQ2xCLE1BQU0sS0FBSyxHQUFHLElBQUksRUFBRSxHQUFHO0lBQ3ZCLElBQUksR0FBRyxJQUFJLE9BQUssR0FBRyxPQUFPO0VBQzVCO0VBQ0EsT0FBTyxDQUFDO0FBQ1Y7QUFHQTs7Ozs7OztDQU9DLEdBQ0QsT0FBTyxTQUFTLGlCQUF5QixDQUFNLEVBQUUsQ0FBSSxFQUFFLEtBQWdDLElBQUksRUFBRSxLQUErQixJQUFJO0VBQzlILEtBQUssTUFBTTtFQUNYLEtBQUssTUFBTTtFQUNYLE1BQU0sSUFBSSxHQUFHLEdBQUcsR0FBRztFQUNuQixJQUFLLElBQUksSUFBRSxFQUFFLE1BQU0sR0FBQyxHQUFHLEtBQUcsR0FBRyxFQUFFLEVBQUc7SUFDaEMsTUFBTSxLQUFLLEdBQUcsQ0FBQyxDQUFDLEVBQUUsRUFBRSxHQUFHO0lBQ3ZCLElBQUksR0FBRyxJQUFJLE9BQUssR0FBRyxPQUFPO0VBQzVCO0VBQ0EsT0FBTyxDQUFDO0FBQ1Y7QUFHQTs7Ozs7OztDQU9DLEdBQ0QsT0FBTyxTQUFTLGVBQXVCLENBQU0sRUFBRSxDQUFJLEVBQUUsS0FBZ0MsSUFBSSxFQUFFLEtBQStCLElBQUk7RUFDNUgsS0FBSyxNQUFNO0VBQ1gsS0FBSyxNQUFNO0VBQ1gsTUFBTSxJQUFJLEdBQUcsR0FBRyxHQUFHO0VBQ25CLElBQUksSUFBSSxDQUFDO0VBQUcsTUFBTSxJQUFJLEVBQUU7RUFDeEIsS0FBSyxNQUFNLE1BQU0sRUFBRztJQUNsQixNQUFNLEtBQUssR0FBRyxJQUFJLEVBQUUsR0FBRztJQUN2QixJQUFJLEdBQUcsSUFBSSxPQUFLLEdBQUcsRUFBRSxJQUFJLENBQUM7RUFDNUI7RUFDQSxPQUFPO0FBQ1Q7QUFHQTs7Ozs7O0NBTUMsR0FDRCxPQUFPLFNBQVMsNkJBQXFDLENBQU0sRUFBRSxLQUFnQyxJQUFJLEVBQUUsS0FBK0IsSUFBSTtFQUNwSSxLQUFLLE1BQU07RUFDWCxLQUFLLE1BQU07RUFDWCxNQUFNLElBQUssRUFBRSxNQUFNO0VBQ25CLElBQUksS0FBRyxHQUFHLE9BQU8sQ0FBQztFQUNsQixJQUFJLEtBQUssR0FBRyxDQUFDLENBQUMsRUFBRSxFQUFFLEdBQUc7RUFDckIsSUFBSyxJQUFJLElBQUUsR0FBRyxJQUFFLEdBQUcsRUFBRSxFQUFHO0lBQ3RCLE1BQU0sSUFBSSxHQUFHLENBQUMsQ0FBQyxFQUFFLEVBQUUsR0FBRztJQUN0QixJQUFJLEdBQUcsSUFBSSxPQUFLLEdBQUcsT0FBTztJQUMxQixLQUFLO0VBQ1A7RUFDQSxPQUFPLENBQUM7QUFDVjtBQUNBLFNBQVEsZ0NBQWdDLHVCQUF1QixHQUFFO0FBR2pFOzs7Ozs7O0NBT0MsR0FDRCxPQUFPLFNBQVMsc0JBQThCLENBQU0sRUFBRSxDQUFNLEVBQUUsS0FBZ0MsSUFBSSxFQUFFLEtBQStCLElBQUk7RUFDckksS0FBSyxNQUFNO0VBQ1gsS0FBSyxNQUFNO0VBQ1gsTUFBTSxJQUFJLEVBQUUsTUFBTTtFQUNsQixNQUFNLElBQUksRUFBRSxNQUFNO0VBQ2xCLE1BQU0sSUFBSSxLQUFLLEdBQUcsQ0FBQyxHQUFHO0VBQ3RCLElBQUssSUFBSSxJQUFFLEdBQUcsSUFBRSxHQUFHLEVBQUUsRUFBRztJQUN0QixNQUFNLEtBQUssR0FBRyxDQUFDLENBQUMsRUFBRSxFQUFFLEdBQUc7SUFDdkIsTUFBTSxLQUFLLEdBQUcsQ0FBQyxDQUFDLEVBQUUsRUFBRSxHQUFHO0lBQ3ZCLElBQUksR0FBRyxJQUFJLFFBQU0sR0FBRyxPQUFPO0VBQzdCO0VBQ0EsT0FBTyxNQUFJLElBQUcsQ0FBQyxJQUFJO0FBQ3JCO0FBQ0EsU0FBUSx5QkFBeUIsY0FBYyxHQUFFO0FBQ2pELGFBQWE7QUFLYix1QkFBdUI7QUFDdkIsdUJBQXVCO0FBRXZCOzs7Ozs7O0NBT0MsR0FDRCxPQUFPLFNBQVMsVUFBa0IsQ0FBTSxFQUFFLENBQU0sRUFBRSxLQUFnQyxJQUFJLEVBQUUsS0FBK0IsSUFBSTtFQUN6SCxNQUFNLElBQUksRUFBRSxNQUFNO0VBQ2xCLE9BQU8sTUFBSSxLQUFLLFFBQVEsRUFBRSxLQUFLLENBQUMsR0FBRyxJQUFJLEdBQUcsSUFBSSxRQUFNO0FBQ3REO0FBQ0EsU0FBUSxhQUFhLFVBQVUsR0FBRTtBQUdqQzs7Ozs7OztDQU9DLEdBQ0QsT0FBTyxTQUFTLFVBQWtCLENBQU0sRUFBRSxDQUFNLEVBQUUsS0FBZ0MsSUFBSSxFQUFFLEtBQStCLElBQUk7RUFDekgsTUFBTSxJQUFJLEVBQUUsTUFBTTtFQUNsQixPQUFPLE1BQUksS0FBSyxRQUFRLEVBQUUsS0FBSyxDQUFDLENBQUMsSUFBSSxHQUFHLElBQUksUUFBTTtBQUNwRDtBQUNBLFNBQVEsYUFBYSxRQUFRLEdBQUU7QUFHL0I7Ozs7Ozs7Q0FPQyxHQUNELE9BQU8sU0FBUyxTQUFpQixDQUFNLEVBQUUsQ0FBTSxFQUFFLEtBQWdDLElBQUksRUFBRSxLQUErQixJQUFJO0VBQ3hILE9BQU8sWUFBWSxHQUFHLEdBQUcsSUFBSSxPQUFPO0FBQ3RDO0FBR0E7Ozs7Ozs7Q0FPQyxHQUNELE9BQU8sU0FBUyxlQUF1QixDQUFNLEVBQUUsQ0FBTSxFQUFFLEtBQWdDLElBQUksRUFBRSxLQUErQixJQUFJO0VBQzlILE9BQU8sa0JBQWtCLEdBQUcsR0FBRyxJQUFJLE9BQU87QUFDNUM7QUFHQTs7Ozs7OztDQU9DLEdBQ0QsT0FBTyxTQUFTLGVBQXVCLENBQU0sRUFBRSxDQUFNLEVBQUUsS0FBZ0MsSUFBSSxFQUFFLEtBQStCLElBQUk7RUFDOUgsTUFBTSxLQUFLLEtBQUksRUFBRSxHQUFHLENBQUMsTUFBTSxFQUFFLEtBQUs7RUFDbEMsTUFBTSxLQUFLLEtBQUksRUFBRSxHQUFHLENBQUMsTUFBTSxFQUFFLEtBQUs7RUFDbEMsT0FBTyxlQUFvQixHQUFHLElBQUksSUFBSSxHQUFHLElBQUksSUFBSTtBQUNqRCw0REFBNEQ7QUFDOUQ7QUFHQTs7Ozs7Q0FLQyxHQUNELE9BQU8sU0FBUyxTQUFZLENBQU0sRUFBRSxJQUFVLENBQUMsQ0FBQztFQUM5QyxPQUFPO09BQUksVUFBVSxHQUFHO0dBQUc7QUFDN0I7QUFHQTs7Ozs7Q0FLQyxHQUNELE9BQU8sVUFBVSxVQUFhLENBQU0sRUFBRSxJQUFVLENBQUMsQ0FBQztFQUNoRCxNQUFNLElBQUksRUFBRSxNQUFNO0VBQ2xCLElBQUksSUFBRSxHQUFJO0VBQ1YsSUFBSSxLQUFHLEdBQUc7SUFBRSxNQUFNLEVBQUUsS0FBSyxDQUFDLEdBQUc7SUFBSTtFQUFRO0VBQ3pDLElBQUssSUFBSSxJQUFFLEdBQUcsS0FBRyxHQUFHLEVBQUUsRUFDcEIsTUFBTSxFQUFFLEtBQUssQ0FBQyxHQUFHO0FBQ3JCO0FBR0E7Ozs7O0NBS0MsR0FDRCxPQUFPLFNBQVMsU0FBWSxDQUFNLEVBQUUsSUFBVSxDQUFDLENBQUM7RUFDOUMsT0FBTztPQUFJLFVBQVUsR0FBRztHQUFHO0FBQzdCO0FBR0E7Ozs7O0NBS0MsR0FDRCxPQUFPLFVBQVUsVUFBYSxDQUFNLEVBQUUsSUFBVSxDQUFDLENBQUM7RUFDaEQsTUFBTSxJQUFJLEVBQUUsTUFBTTtFQUNsQixJQUFJLElBQUUsR0FBSTtFQUNWLElBQUksS0FBRyxHQUFHO0lBQUUsTUFBTSxFQUFFLEtBQUssQ0FBQyxFQUFFLE1BQU0sR0FBRztJQUFJO0VBQVE7RUFDakQsSUFBSyxJQUFJLElBQUUsR0FBRyxLQUFHLEdBQUcsRUFBRSxFQUNwQixNQUFNLEVBQUUsS0FBSyxDQUFDO0FBQ2xCO0FBR0E7Ozs7O0NBS0MsR0FDRCxPQUFPLFNBQVMsUUFBVyxDQUFNLEVBQUUsSUFBVSxDQUFDLENBQUM7RUFDN0MsT0FBTztPQUFJLFNBQVMsR0FBRztHQUFHO0FBQzVCO0FBR0E7Ozs7O0NBS0MsR0FDRCxPQUFPLFNBQVMsU0FBWSxDQUFNLEVBQUUsSUFBVSxDQUFDLENBQUM7RUFDOUMsSUFBSSxLQUFHLEdBQUcsT0FBTyxhQUFhLEdBQUc7T0FDdkIsT0FBTyxXQUFXO0FBQzlCO0FBRUEsVUFBVSxhQUFnQixDQUFNLEVBQUUsQ0FBUztFQUN6QyxNQUFNLElBQUksRUFBRSxNQUFNO0VBQ2xCLElBQUksSUFBRSxHQUFLO0VBQ1gsSUFBSSxNQUFJLEdBQUc7SUFBRSxNQUFNLEVBQUU7SUFBRTtFQUFRO0VBQy9CLElBQUssSUFBSSxJQUFFLEdBQUcsSUFBRSxJQUFFLElBQUUsR0FBRyxJQUFFLEdBQUcsRUFBRSxFQUM1QixNQUFNLEVBQUUsS0FBSyxDQUFDLEdBQUcsSUFBRTtBQUN2QjtBQUVBLFVBQVUsV0FBYyxDQUFNO0VBQzVCLE1BQU0sSUFBSSxFQUFFLE1BQU07RUFBRSxNQUFNLEVBQUU7RUFDNUIsSUFBSyxJQUFJLElBQUUsR0FBRyxJQUFFLEdBQUcsRUFBRSxFQUFHO0lBQ3RCLElBQUssSUFBSSxJQUFFLElBQUUsR0FBRyxLQUFHLEdBQUcsRUFBRSxFQUN0QixNQUFNLEVBQUUsS0FBSyxDQUFDLEdBQUc7RUFDckI7QUFDRjtBQUdBOzs7OztDQUtDLEdBQ0QsT0FBTyxTQUFTLGFBQWdCLENBQU0sRUFBRSxJQUFVLENBQUMsQ0FBQztFQUNsRCxPQUFPO09BQUksY0FBYyxHQUFHO0dBQUc7QUFDakM7QUFHQTs7Ozs7Q0FLQyxHQUNELE9BQU8sVUFBVSxjQUFpQixDQUFNLEVBQUUsSUFBVSxDQUFDLENBQUM7RUFDcEQsTUFBTSxJQUFJLEVBQUUsTUFBTTtFQUNsQixJQUFJLElBQUUsR0FBRztFQUNULElBQUksTUFBSSxHQUFZO0lBQUUsTUFBTTtJQUFJO0VBQVE7RUFDeEMsSUFBSSxNQUFJLEtBQUssTUFBSSxHQUFHO0lBQUUsTUFBTSxFQUFFO0lBQUU7RUFBUTtFQUN4QyxNQUFNLElBQUksRUFBRSxLQUFLLENBQUMsR0FBRyxDQUFDO0VBQ3RCLE9BQU8sY0FBYyxHQUFHO0VBQ3hCLEtBQUssTUFBTSxLQUFLLGNBQWMsR0FBRyxJQUFFLEdBQUk7SUFDckMsRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDLElBQUUsRUFBRTtJQUNiLE1BQU07RUFDUjtBQUNGO0FBR0E7Ozs7O0NBS0MsR0FDRCxPQUFPLFNBQVMsYUFBZ0IsQ0FBTSxFQUFFLElBQVUsQ0FBQyxDQUFDO0VBQ2xELE9BQU87T0FBSSxjQUFjLEdBQUc7R0FBRztBQUNqQztBQUdBOzs7OztDQUtDLEdBQ0QsT0FBTyxVQUFVLGNBQWlCLENBQU0sRUFBRSxJQUFVLENBQUMsQ0FBQztFQUNwRCxNQUFNLElBQUksRUFBRSxNQUFNO0VBQ2xCLElBQUksSUFBRSxHQUFHO0VBQ1QsSUFBTSxJQUFJLElBQUUsSUFBRyxJQUFJO0VBQ25CLE1BQU0sSUFBSSxJQUFFLElBQUcsSUFBSTtFQUNuQixNQUFPLEtBQUcsR0FBRyxFQUFFLEVBQ2IsT0FBTyxtQkFBbUIsR0FBRztBQUNqQztBQUVBLFVBQVUsbUJBQXNCLENBQU0sRUFBRSxDQUFTO0VBQy9DLE1BQU0sSUFBSSxFQUFFLE1BQU07RUFDbEIsSUFBSSxNQUFJLEtBQUssTUFBSSxHQUFHO0lBQUUsTUFBTSxFQUFFO0lBQUU7RUFBUTtFQUN4QyxJQUFLLElBQUksSUFBRSxHQUFHLElBQUUsR0FBRyxFQUFFLEVBQUc7SUFDdEIsTUFBTSxJQUFJLE9BQU8sR0FBRyxHQUFHO0lBQ3ZCLEtBQUssTUFBTSxLQUFLLG1CQUFtQixHQUFHLElBQUUsR0FDdEMsTUFBTTtNQUFDLENBQUMsQ0FBQyxFQUFFO1NBQUs7S0FBRTtFQUN0QjtBQUNGO0FBR0E7Ozs7Ozs7Q0FPQyxHQUNELE9BQU8sU0FBUyxZQUFvQixDQUFNLEVBQUUsQ0FBTSxFQUFFLEtBQWdDLElBQUksRUFBRSxLQUErQixJQUFJO0VBQzNILEtBQUssTUFBTTtFQUNYLEtBQUssTUFBTTtFQUNYLE1BQU0sSUFBSSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsTUFBTTtFQUNoQyxJQUFLLElBQUksSUFBRSxHQUFHLEtBQUcsSUFBRSxHQUFHLEVBQUUsRUFDdEIsSUFBSSxVQUFVLEdBQUcsR0FBRyxHQUFHLElBQUksS0FBSyxPQUFPO0VBQ3pDLE9BQU8sQ0FBQztBQUNWO0FBR0E7Ozs7Ozs7Q0FPQyxHQUNELE9BQU8sU0FBUyxpQkFBeUIsQ0FBTSxFQUFFLENBQU0sRUFBRSxLQUFnQyxJQUFJLEVBQUUsS0FBK0IsSUFBSTtFQUNoSSxLQUFLLE1BQU07RUFDWCxLQUFLLE1BQU07RUFDWCxNQUFNLElBQUksRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLE1BQU07RUFDaEMsSUFBSyxJQUFJLElBQUUsSUFBRSxHQUFHLEtBQUcsR0FBRyxFQUFFLEVBQ3RCLElBQUksVUFBVSxHQUFHLEdBQUcsR0FBRyxJQUFJLEtBQUssT0FBTztFQUN6QyxPQUFPLENBQUM7QUFDVjtBQUdBOzs7Ozs7O0NBT0MsR0FDRCxPQUFPLFNBQVMsZUFBdUIsQ0FBTSxFQUFFLENBQU0sRUFBRSxLQUFnQyxJQUFJLEVBQUUsS0FBK0IsSUFBSTtFQUM5SCxLQUFLLE1BQU07RUFDWCxLQUFLLE1BQU07RUFDWCxNQUFNLElBQUksRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUU7RUFDeEMsSUFBSyxJQUFJLElBQUUsR0FBRyxLQUFHLElBQUUsR0FBRyxFQUFFLEVBQ3RCLElBQUksVUFBVSxHQUFHLEdBQUcsR0FBRyxJQUFJLEtBQUssRUFBRSxJQUFJLENBQUM7RUFDekMsT0FBTztBQUNUO0FBR0EsU0FBUyxVQUFrQixDQUFNLEVBQUUsQ0FBTSxFQUFFLENBQVMsRUFBRSxFQUF3QixFQUFFLEVBQXVCO0VBQ3JHLE1BQU0sSUFBSSxFQUFFLE1BQU07RUFDbEIsSUFBSyxJQUFJLElBQUUsR0FBRyxJQUFFLEdBQUcsRUFBRSxFQUFHO0lBQ3RCLE1BQU0sS0FBSyxHQUFHLENBQUMsQ0FBQyxJQUFFLEVBQUUsRUFBRSxJQUFFLEdBQUc7SUFDM0IsTUFBTSxLQUFLLEdBQUcsQ0FBQyxDQUFDLEVBQUUsRUFBRSxHQUFHO0lBQ3ZCLElBQUksR0FBRyxJQUFJLFFBQU0sR0FBRyxPQUFPO0VBQzdCO0VBQ0EsT0FBTztBQUNUO0FBR0E7Ozs7Ozs7Q0FPQyxHQUNELE9BQU8sU0FBUyxrQkFBMEIsQ0FBTSxFQUFFLENBQU0sRUFBRSxLQUFnQyxJQUFJLEVBQUUsS0FBK0IsSUFBSTtFQUNqSSxLQUFLLE1BQU07RUFDWCxLQUFLLE1BQU07RUFDWCxNQUFNLEtBQUs7T0FBSTtHQUFFLENBQUMsR0FBRyxDQUFDLEtBQUssSUFBSSxHQUFHLE1BQU07RUFDeEMsSUFBSSxJQUFJLENBQUMsR0FBRyxJQUFJLENBQUMsR0FBRyxJQUFJO0VBQ3hCLEtBQUssTUFBTSxNQUFNLEVBQUc7SUFDbEIsTUFBTSxLQUFLLEdBQUcsSUFBSSxFQUFFLEdBQUc7SUFDdkIsSUFBSSxHQUFHLElBQUksRUFBRSxDQUFDLEVBQUUsTUFBSSxHQUFHO0lBQ3ZCLElBQUksSUFBRSxHQUFHLElBQUk7SUFDYixJQUFJLEVBQUUsS0FBRyxHQUFHLE9BQU87RUFDckI7RUFDQSxPQUFPLENBQUM7QUFDVjtBQUNBLGFBQWE7QUFLYiw4QkFBOEI7QUFDOUIsOEJBQThCO0FBRTlCOzs7OztDQUtDLEdBQ0QsT0FBTyxTQUFTLFlBQWUsQ0FBTSxFQUFFLEtBQWdDLEtBQUssTUFBTTtFQUNoRixLQUFLLE1BQU0sS0FBSyxNQUFNO0VBQ3RCLE1BQU0sSUFBSSxLQUFLLEtBQUssQ0FBQyxPQUFPLEVBQUUsTUFBTTtFQUNwQyxPQUFPLENBQUMsQ0FBQyxFQUFFO0FBQ2I7QUFDQSxTQUFRLGVBQWUsS0FBSyxHQUFFLENBQUUsYUFBYTtBQUc3Qzs7Ozs7O0NBTUMsR0FDRCxPQUFPLFNBQVMsYUFBZ0IsQ0FBTSxFQUFFLElBQVUsQ0FBQyxDQUFDLEVBQUUsS0FBZ0MsS0FBSyxNQUFNO0VBQy9GLEtBQUssTUFBTSxLQUFLLE1BQU07RUFDdEIsTUFBTSxJQUFJLEVBQUUsTUFBTTtFQUNsQixJQUFJLElBQUUsR0FBRyxPQUFPO0VBQ2hCLElBQUksS0FBRyxJQUFHLElBQUksS0FBSyxLQUFLLENBQUMsQ0FBQyxJQUFFLENBQUMsSUFBRTtFQUMvQixPQUFPLEVBQUUsS0FBSyxDQUFDLEdBQUc7QUFDcEI7QUFDQSxTQUFRLGdCQUFnQixNQUFNLEdBQUUsQ0FBRSxhQUFhO0FBRy9DOzs7Ozs7Q0FNQyxHQUNELE9BQU8sU0FBUyxhQUFnQixDQUFNLEVBQUUsSUFBVSxDQUFDLENBQUMsRUFBRSxLQUFnQyxLQUFLLE1BQU07RUFDL0YsTUFBTSxJQUFJLEVBQUUsTUFBTTtFQUNsQixJQUFJLElBQUUsR0FBRyxPQUFPO0VBQ2hCLElBQUksS0FBRyxJQUFHLElBQUksS0FBSyxLQUFLLENBQUMsQ0FBQyxJQUFFLENBQUMsSUFBRSxBQUFDO0VBQ2hDLE9BQU8sRUFBRSxLQUFLLENBQUMsSUFBRTtBQUNuQjtBQUNBLFNBQVEsZ0JBQWdCLE1BQU0sR0FBRSxDQUFFLGFBQWE7QUFHL0M7Ozs7OztDQU1DLEdBQ0QsT0FBTyxTQUFTLFlBQWUsQ0FBTSxFQUFFLElBQVUsQ0FBQyxDQUFDLEVBQUUsS0FBZ0MsS0FBSyxNQUFNO0VBQzlGLE1BQU0sSUFBSSxFQUFFLE1BQU07RUFDbEIsSUFBSSxJQUFFLEdBQUcsT0FBTztFQUNoQixJQUFJLEtBQUcsSUFBRyxJQUFJLGtCQUFrQixHQUFHLEFBQUM7RUFDcEMsTUFBTSxJQUFJLEtBQUssS0FBSyxDQUFDLENBQUMsSUFBRSxJQUFFLENBQUMsSUFBRSxBQUFDO0VBQzlCLE9BQU8sRUFBRSxLQUFLLENBQUMsR0FBRyxJQUFFO0FBQ3RCO0FBQ0EsU0FBUSxlQUFlLEtBQUssR0FBRSxDQUFFLGFBQWE7QUFFN0MsNkNBQTZDO0FBQzdDLFNBQVMsa0JBQWtCLENBQVMsRUFBRSxDQUFTO0VBQzdDLE1BQU0sSUFBSSxNQUFNLElBQUUsQ0FBQyxJQUFFLENBQUMsSUFBSTtFQUMxQixNQUFNLElBQUksTUFBTSxLQUFLLElBQUksQ0FBQyxJQUFJLElBQUUsSUFBRSxLQUFLO0VBQ3ZDLE9BQU8sSUFBRSxJQUFLLEtBQUssS0FBSyxDQUFDLElBQUU7QUFDN0I7QUFHQTs7Ozs7O0NBTUMsR0FDRCxPQUFPLFNBQVMsa0JBQXFCLENBQU0sRUFBRSxJQUFVLENBQUMsQ0FBQyxFQUFFLEtBQWdDLEtBQUssTUFBTTtFQUNwRyxNQUFNLElBQUksRUFBRSxNQUFNO0VBQ2xCLElBQUksSUFBRSxHQUFJLE9BQU87RUFDakIsSUFBSSxLQUFHLEdBQUcsT0FBTyx1QkFBdUIsR0FBRyxHQUFHO09BQ3BDLE9BQU8scUJBQXFCLEdBQUc7QUFDM0M7QUFDQSxTQUFRLHFCQUFxQixXQUFXLEdBQUUsQ0FBRSxhQUFhO0FBRXpELFNBQVMsdUJBQTBCLENBQU0sRUFBRSxDQUFTLEVBQUUsRUFBd0I7RUFDNUUsTUFBTSxLQUFLLFVBQVUsR0FBRyxFQUFFLE1BQU07RUFDaEMsbUJBQW1CLElBQUksR0FBRyxJQUFJLElBQUk7RUFDbEMsT0FBTyxPQUFPLEdBQUc7QUFDbkI7QUFFQSxTQUFTLHFCQUF3QixDQUFNLEVBQUUsRUFBd0I7RUFDL0QsTUFBTSxJQUFTLEVBQUU7RUFDakIsS0FBSyxNQUFNLEtBQUssRUFDZCxJQUFJLE9BQUssS0FBSyxFQUFFLElBQUksQ0FBQztFQUN2QixPQUFPO0FBQ1Q7QUFHQTs7Ozs7O0NBTUMsR0FDRCxPQUFPLFNBQVMsa0JBQXFCLENBQU0sRUFBRSxJQUFVLENBQUMsQ0FBQyxFQUFFLEtBQWdDLEtBQUssTUFBTTtFQUNwRyxNQUFNLElBQUksRUFBRSxNQUFNO0VBQ2xCLElBQUksSUFBRSxHQUFHLE9BQU87RUFDaEIsT0FBTyxtQkFBbUIsRUFBRSxLQUFLLElBQUksR0FBRztBQUMxQztBQUNBLFNBQVEscUJBQXFCLFdBQVcsR0FBRSxDQUFFLGFBQWE7QUFHekQ7Ozs7OztDQU1DLEdBQ0QsT0FBTyxTQUFTLG1CQUFzQixDQUFNLEVBQUUsSUFBVSxDQUFDLENBQUMsRUFBRSxLQUFnQyxLQUFLLE1BQU07RUFDckcsS0FBSyxNQUFNLEtBQUssTUFBTTtFQUN0QixNQUFNLElBQUksRUFBRSxNQUFNO0VBQ2xCLElBQUksSUFBRSxHQUFHLE9BQU87RUFDaEIsSUFBSSxLQUFHLElBQUcsSUFBSSxLQUFLLEtBQUssQ0FBQyxDQUFDLElBQUUsQ0FBQyxJQUFFO0VBQy9CLElBQUssSUFBSSxJQUFFLEdBQUcsSUFBRSxHQUFHLEVBQUUsRUFBRztJQUN0QixNQUFNLElBQUksSUFBSSxLQUFLLEtBQUssQ0FBQyxDQUFDLElBQUUsQ0FBQyxJQUFFO0lBQy9CLE1BQU0sSUFBSSxDQUFDLENBQUMsRUFBRTtJQUFFLENBQUMsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFDLEVBQUU7SUFBRSxDQUFDLENBQUMsRUFBRSxHQUFHO0VBQ3RDO0VBQ0EsRUFBRSxNQUFNLEdBQUc7RUFDWCxPQUFPO0FBQ1Q7QUFDQSxTQUFRLHNCQUFzQixZQUFZLEdBQUUsQ0FBRSxhQUFhO0FBQzNELFNBQVEsc0JBQXNCLFFBQVEsR0FBRTtBQUN4QyxTQUFRLHNCQUFzQixRQUFRLEdBQUU7QUFDeEMsdURBQXVEO0FBQ3ZELGFBQWE7QUFLYixlQUFlO0FBQ2YsZUFBZTtBQUVmOzs7OztDQUtDLEdBQ0QsT0FBTyxTQUFTLEtBQVEsQ0FBTSxFQUFFLEVBQW1CO0VBQ2pELE9BQU8sRUFBRSxJQUFJLENBQUM7QUFDaEI7QUFHQTs7Ozs7Q0FLQyxHQUNELE9BQU8sU0FBUyxVQUFhLENBQU0sRUFBRSxFQUFtQjtFQUN0RCxJQUFLLElBQUksSUFBRSxFQUFFLE1BQU0sR0FBQyxHQUFHLEtBQUcsR0FBRyxFQUFFLEVBQzdCLElBQUksR0FBRyxDQUFDLENBQUMsRUFBRSxFQUFFLEdBQUcsSUFBSSxPQUFPLENBQUMsQ0FBQyxFQUFFO0VBQ2pDLE9BQU87QUFDVDtBQUNBLGFBQWE7QUFLYixvQkFBb0I7QUFDcEIsb0JBQW9CO0FBRXBCOzs7OztDQUtDLEdBQ0QsT0FBTyxTQUFTLEtBQVEsQ0FBTSxFQUFFLElBQVUsQ0FBQztFQUN6QyxJQUFJLEtBQUssR0FBRyxDQUFDLEdBQUc7RUFDaEIsT0FBTyxFQUFFLEtBQUssQ0FBQyxHQUFHO0FBQ3BCO0FBQ0EsU0FBUSxRQUFRLElBQUksR0FBRTtBQUd0Qjs7Ozs7Q0FLQyxHQUNELE9BQU8sU0FBUyxVQUFhLENBQU0sRUFBRSxJQUFVLENBQUM7RUFDOUMsTUFBTSxJQUFJLEVBQUUsTUFBTTtFQUNsQixJQUFJLEtBQUssR0FBRyxDQUFDLEtBQUssR0FBRyxDQUFDLEdBQUcsSUFBSTtFQUM3QixPQUFPLEVBQUUsS0FBSyxDQUFDLElBQUU7QUFDbkI7QUFDQSxTQUFRLGFBQWEsS0FBSyxHQUFFO0FBRzVCOzs7OztDQUtDLEdBQ0QsT0FBTyxTQUFTLFVBQWEsQ0FBTSxFQUFFLEVBQW1CO0VBQ3RELE9BQU8sRUFBRSxLQUFLLENBQUMsR0FBRyxVQUFVLEdBQUc7QUFDakM7QUFHQTs7Ozs7Q0FLQyxHQUNELE9BQU8sU0FBUyxlQUFrQixDQUFNLEVBQUUsRUFBbUI7RUFDM0QsT0FBTyxFQUFFLEtBQUssQ0FBQyxlQUFlLEdBQUc7QUFDbkM7QUFHQTs7Ozs7Q0FLQyxHQUNELE9BQU8sU0FBUyxLQUFRLENBQU0sRUFBRSxJQUFVLENBQUM7RUFDekMsSUFBSSxLQUFLLEdBQUcsQ0FBQyxHQUFHO0VBQ2hCLE9BQU8sRUFBRSxLQUFLLENBQUM7QUFDakI7QUFHQTs7Ozs7Q0FLQyxHQUNELE9BQU8sU0FBUyxVQUFhLENBQU0sRUFBRSxJQUFVLENBQUM7RUFDOUMsTUFBTSxJQUFJLEVBQUUsTUFBTTtFQUNsQixJQUFJLEtBQUssR0FBRyxDQUFDLEtBQUssR0FBRyxDQUFDLEdBQUcsSUFBSTtFQUM3QixPQUFPLEVBQUUsS0FBSyxDQUFDLEdBQUcsSUFBRTtBQUN0QjtBQUdBOzs7OztDQUtDLEdBQ0QsT0FBTyxTQUFTLFVBQWEsQ0FBTSxFQUFFLEVBQW1CO0VBQ3RELE9BQU8sRUFBRSxLQUFLLENBQUMsVUFBVSxHQUFHO0FBQzlCO0FBR0E7Ozs7O0NBS0MsR0FDRCxPQUFPLFNBQVMsZUFBa0IsQ0FBTSxFQUFFLEVBQW1CO0VBQzNELE9BQU8sRUFBRSxLQUFLLENBQUMsR0FBRyxlQUFlLEdBQUc7QUFDdEM7QUFDQSxhQUFhO0FBS2IsZUFBZTtBQUNmLGVBQWU7QUFFZjs7Ozs7Q0FLQyxHQUNELE9BQU8sU0FBUyxVQUFhLENBQU0sRUFBRSxFQUFtQjtFQUN0RCxJQUFJLElBQUksQ0FBQztFQUNULEtBQUssTUFBTSxLQUFLLEVBQ2QsSUFBSSxDQUFDLEdBQUcsR0FBRyxFQUFFLEdBQUcsSUFBSSxPQUFPO0VBQzdCLE9BQU8sRUFBRTtBQUNYO0FBR0E7Ozs7O0NBS0MsR0FDRCxPQUFPLFNBQVMsZUFBa0IsQ0FBTSxFQUFFLEVBQW1CO0VBQzNELElBQUksSUFBSSxFQUFFLE1BQU0sR0FBQztFQUNqQixNQUFPLEtBQUcsR0FBRyxFQUFFLEVBQ2IsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsRUFBRSxHQUFHLElBQUk7RUFDdkIsT0FBTyxFQUFFO0FBQ1g7QUFHQTs7Ozs7Q0FLQyxHQUNELE9BQU8sU0FBUyxVQUFhLENBQU0sRUFBRSxFQUFtQjtFQUN0RCxJQUFJLElBQUksQ0FBQztFQUNULEtBQUssTUFBTSxLQUFLLEVBQ2QsSUFBSSxHQUFHLEdBQUcsRUFBRSxHQUFHLElBQUksT0FBTztFQUM1QixPQUFPLEVBQUU7QUFDWDtBQUdBOzs7OztDQUtDLEdBQ0QsT0FBTyxTQUFTLGVBQWtCLENBQU0sRUFBRSxFQUFtQjtFQUMzRCxJQUFJLElBQUksRUFBRSxNQUFNLEdBQUM7RUFDakIsTUFBTyxLQUFHLEdBQUcsRUFBRSxFQUNiLElBQUksR0FBRyxDQUFDLENBQUMsRUFBRSxFQUFFLEdBQUcsSUFBSTtFQUN0QixPQUFPLEVBQUU7QUFDWDtBQUNBLGFBQWE7QUFLYixpQkFBaUI7QUFDakIsaUJBQWlCO0FBRWpCOzs7Ozs7Q0FNQyxHQUNELE9BQU8sU0FBUyxRQUFXLENBQU0sRUFBRSxDQUFJLEVBQUUsSUFBVSxDQUFDO0VBQ2xELE9BQU8sRUFBRSxPQUFPLENBQUMsR0FBRztBQUN0QjtBQUdBOzs7Ozs7Q0FNQyxHQUNELE9BQU8sU0FBUyxZQUFlLENBQU0sRUFBRSxDQUFJLEVBQUUsSUFBVSxFQUFFLE1BQU0sR0FBQyxDQUFDO0VBQy9ELE9BQU8sRUFBRSxXQUFXLENBQUMsR0FBRztBQUMxQjtBQUdBOzs7OztDQUtDLEdBQ0QsT0FBTyxTQUFTLE9BQVUsQ0FBTSxFQUFFLEVBQW1CO0VBQ25ELE9BQU8sRUFBRSxTQUFTLENBQUM7QUFDckI7QUFDQSxTQUFRLFVBQVUsU0FBUyxHQUFFO0FBRzdCOzs7OztDQUtDLEdBQ0QsT0FBTyxTQUFTLFlBQWUsQ0FBTSxFQUFFLEVBQW1CO0VBQ3hELElBQUssSUFBSSxJQUFFLEVBQUUsTUFBTSxHQUFDLEdBQUcsS0FBRyxHQUFHLEVBQUUsRUFDN0IsSUFBSSxHQUFHLENBQUMsQ0FBQyxFQUFFLEVBQUUsR0FBRyxJQUFJLE9BQU87RUFDN0IsT0FBTyxDQUFDO0FBQ1Y7QUFDQSxTQUFRLGVBQWUsYUFBYSxHQUFFO0FBR3RDOzs7OztDQUtDLEdBQ0QsT0FBTyxTQUFTLFVBQWEsQ0FBTSxFQUFFLEVBQW1CO0VBQ3RELElBQUksSUFBSSxDQUFDO0VBQ1QsTUFBTSxJQUFjLEVBQUU7RUFDdEIsS0FBSyxNQUFNLEtBQUssRUFDZCxJQUFJLEdBQUcsR0FBRyxFQUFFLEdBQUcsSUFBSSxFQUFFLElBQUksQ0FBQztFQUM1QixPQUFPO0FBQ1Q7QUFDQSxhQUFhO0FBS2IscUJBQXFCO0FBQ3JCLHFCQUFxQjtBQUVyQjs7OztDQUlDLEdBQ0QsT0FBTyxTQUFTLFFBQVcsQ0FBTSxFQUFFLEVBQXNCO0VBQ3ZELEVBQUUsT0FBTyxDQUFDO0FBQ1o7QUFHQTs7Ozs7Q0FLQyxHQUNELE9BQU8sU0FBUyxLQUFRLENBQU0sRUFBRSxLQUEyQixJQUFJO0VBQzdELElBQUksSUFBSSxPQUFPLEVBQUUsSUFBSSxDQUFDO09BQ2QsT0FBTyxZQUFZO0FBQzdCO0FBQ0EsU0FBUSxRQUFRLEtBQUssR0FBRTtBQUV2QixTQUFTLFlBQWUsQ0FBTTtFQUM1QixNQUFNLElBQUksRUFBRSxNQUFNO0VBQ2xCLElBQUssSUFBSSxJQUFFLEdBQUcsSUFBRSxHQUFHLEVBQUUsRUFDbkIsSUFBSSxDQUFDLENBQUMsRUFBRSxFQUFFLE9BQU87RUFDbkIsT0FBTztBQUNUO0FBR0E7Ozs7O0NBS0MsR0FDRCxPQUFPLFNBQVMsTUFBUyxDQUFNLEVBQUUsS0FBMkIsSUFBSTtFQUM5RCxJQUFJLElBQUksT0FBTyxFQUFFLEtBQUssQ0FBQztPQUNmLE9BQU8sYUFBYTtBQUM5QjtBQUNBLFNBQVEsU0FBUyxLQUFLLEdBQUU7QUFFeEIsU0FBUyxhQUFnQixDQUFNO0VBQzdCLE1BQU0sSUFBSSxFQUFFLE1BQU07RUFDbEIsSUFBSyxJQUFJLElBQUUsR0FBRyxJQUFFLEdBQUcsRUFBRSxFQUNuQixJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxPQUFPO0VBQ3BCLE9BQU87QUFDVDtBQUdBOzs7OztDQUtDLEdBQ0QsT0FBTyxTQUFTLElBQVksQ0FBTSxFQUFFLEVBQXVCO0VBQ3pELE9BQU8sRUFBRSxHQUFHLENBQUM7QUFDZjtBQUdBOzs7OztDQUtDLEdBQ0QsT0FBTyxTQUFTLEtBQVEsQ0FBTSxFQUFFLEVBQXFCO0VBQ25ELE1BQU0sSUFBSSxFQUFFLE1BQU07RUFDbEIsSUFBSyxJQUFJLElBQUUsR0FBRyxJQUFFLEdBQUcsRUFBRSxFQUNuQixDQUFDLENBQUMsRUFBRSxHQUFHLEdBQUcsQ0FBQyxDQUFDLEVBQUUsRUFBRSxHQUFHO0VBQ3JCLE9BQU87QUFDVDtBQUdBOzs7Ozs7Q0FNQyxHQUNELE9BQU8sU0FBUyxPQUFlLENBQU0sRUFBRSxFQUEwQixFQUFFLEdBQVM7RUFDMUUsTUFBTSxPQUFPLFVBQVUsTUFBTSxJQUFJO0VBQ2pDLE9BQU8sT0FBTSxFQUFFLE1BQU0sQ0FBQyxNQUE4QixFQUFFLE1BQU0sQ0FBQyxJQUE0QjtBQUMzRjtBQUdBOzs7Ozs7Q0FNQyxHQUNELE9BQU8sU0FBUyxZQUFvQixDQUFNLEVBQUUsRUFBMEIsRUFBRSxHQUFTO0VBQy9FLElBQUksT0FBTyxVQUFVLE1BQU0sSUFBSTtFQUMvQixJQUFLLElBQUksSUFBRSxFQUFFLE1BQU0sR0FBQyxHQUFHLEtBQUcsR0FBRyxFQUFFLEVBQUc7SUFDaEMsSUFBSSxNQUFPO01BQUUsTUFBTSxDQUFDLENBQUMsRUFBRTtNQUFFLE9BQU87SUFBTyxPQUNsQyxNQUFNLEdBQUcsS0FBYyxDQUFDLENBQUMsRUFBRSxFQUFFLEdBQUc7RUFDdkM7RUFDQSxPQUFPO0FBQ1Q7QUFHQTs7Ozs7Q0FLQyxHQUNELE9BQU8sU0FBUyxPQUFVLENBQU0sRUFBRSxFQUFtQjtFQUNuRCxPQUFPLEVBQUUsTUFBTSxDQUFDO0FBQ2xCO0FBQ0EsU0FBUSxVQUFVLE9BQU8sR0FBRTtBQUczQjs7Ozs7Q0FLQyxHQUNELE9BQU8sU0FBUyxRQUFXLENBQU0sRUFBRSxFQUFtQjtFQUNwRCxNQUFNLElBQUksRUFBRSxNQUFNO0VBQ2xCLElBQUksSUFBSTtFQUNSLElBQUssSUFBSSxJQUFFLEdBQUcsSUFBRSxHQUFHLEVBQUUsRUFDbkIsSUFBSSxHQUFHLENBQUMsQ0FBQyxFQUFFLEVBQUUsR0FBRyxJQUFJLENBQUMsQ0FBQyxJQUFJLEdBQUcsQ0FBQyxDQUFDLEVBQUU7RUFDbkMsRUFBRSxNQUFNLEdBQUc7RUFDWCxPQUFPO0FBQ1Q7QUFHQTs7Ozs7Q0FLQyxHQUNELE9BQU8sU0FBUyxTQUFZLENBQU0sRUFBRSxFQUFZO0VBQzlDLE1BQU0sSUFBSSxFQUFFLE1BQU07RUFDbEIsTUFBTSxJQUFTLEVBQUU7RUFDakIsS0FBSyxNQUFNLEtBQUssR0FDZCxJQUFJLEtBQUcsS0FBSyxJQUFFLEdBQUcsRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUU7RUFDOUIsT0FBTztBQUNUO0FBR0E7Ozs7O0NBS0MsR0FDRCxPQUFPLFNBQVMsT0FBVSxDQUFNLEVBQUUsRUFBbUI7RUFDbkQsSUFBSSxJQUFJLENBQUM7RUFDVCxNQUFNLElBQVMsRUFBRTtFQUNqQixLQUFLLE1BQU0sS0FBSyxFQUNkLElBQUksQ0FBQyxHQUFHLEdBQUcsRUFBRSxHQUFHLElBQUksRUFBRSxJQUFJLENBQUM7RUFDN0IsT0FBTztBQUNUO0FBR0E7Ozs7O0NBS0MsR0FDRCxPQUFPLFNBQVMsUUFBVyxDQUFNLEVBQUUsRUFBbUI7RUFDcEQsTUFBTSxJQUFJLEVBQUUsTUFBTTtFQUNsQixJQUFJLElBQUk7RUFDUixJQUFLLElBQUksSUFBRSxHQUFHLElBQUUsR0FBRyxFQUFFLEVBQ25CLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLEVBQUUsR0FBRyxJQUFJLENBQUMsQ0FBQyxJQUFJLEdBQUcsQ0FBQyxDQUFDLEVBQUU7RUFDcEMsRUFBRSxNQUFNLEdBQUc7RUFDWCxPQUFPO0FBQ1Q7QUFHQTs7Ozs7Q0FLQyxHQUNELE9BQU8sU0FBUyxTQUFZLENBQU0sRUFBRSxFQUFZO0VBQzlDLElBQUksSUFBSSxDQUFDO0VBQ1QsTUFBTSxJQUFTLEVBQUU7RUFDakIsS0FBSyxNQUFNLEtBQUssRUFDZCxJQUFJLENBQUMsR0FBRyxRQUFRLENBQUMsRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDO0VBQ2hDLE9BQU87QUFDVDtBQUNBLGFBQWE7QUFLYixrQkFBa0I7QUFDbEIsa0JBQWtCO0FBRWxCOzs7Ozs7O0NBT0MsR0FDRCxPQUFPLFNBQVMsS0FBSyxDQUFZLEVBQUUsSUFBVSxDQUFDLENBQUMsRUFBRSxLQUF5QyxJQUFJLEVBQUUsS0FBaUMsSUFBSTtFQUNuSSxLQUFLLE1BQU07RUFDWCxLQUFLLE1BQU07RUFDWCxPQUFPLFFBQVEsRUFBRSxFQUFFLEdBQUcsR0FBRyxJQUFJO0FBQy9CO0FBRUEsU0FBUyxRQUFRLENBQVksRUFBRSxDQUFZLEVBQUUsQ0FBUyxFQUFFLEVBQWlDLEVBQUUsRUFBeUI7RUFDbEgsSUFBSSxJQUFJLENBQUM7RUFDVCxLQUFLLE1BQU0sS0FBSyxFQUFHO0lBQ2pCLE1BQU0sSUFBSSxHQUFHLEdBQUcsRUFBRSxHQUFHO0lBQ3JCLElBQUksTUFBSSxLQUFLLEdBQUcsR0FBRyxHQUFHLElBQUksUUFBUSxHQUFHLEdBQWdCLElBQUUsR0FBRyxJQUFJO1NBQ3pELEVBQUUsSUFBSSxDQUFDO0VBQ2Q7RUFDQSxPQUFPO0FBQ1Q7QUFHQTs7Ozs7O0NBTUMsR0FDRCxPQUFPLFNBQVMsUUFBUSxDQUFZLEVBQUUsS0FBeUMsSUFBSSxFQUFFLEtBQWlDLElBQUk7RUFDeEgsS0FBSyxNQUFNO0VBQ1gsS0FBSyxNQUFNO0VBQ1gsSUFBSSxJQUFJLENBQUM7RUFDVCxNQUFNLElBQWUsRUFBRTtFQUN2QixLQUFLLE1BQU0sS0FBSyxFQUFHO0lBQ2pCLE1BQU0sSUFBSSxHQUFHLEdBQUcsRUFBRSxHQUFHO0lBQ3JCLElBQUksR0FBRyxHQUFHLEdBQUcsSUFBSSxRQUFRLEdBQUc7U0FDdkIsRUFBRSxJQUFJLENBQUM7RUFDZDtFQUNBLE9BQU87QUFDVDtBQUNBLGFBQWE7QUFLYixxQkFBcUI7QUFDckIscUJBQXFCO0FBRXJCOzs7Ozs7Q0FNQyxHQUNELE9BQU8sU0FBUyxjQUFzQixDQUFNLEVBQUUsRUFBMEIsRUFBRSxHQUFRO0VBQ2hGLE1BQU0sSUFBYSxFQUFFO0VBQ3JCLE1BQU0sSUFBSSxFQUFFLE1BQU07RUFDbEIsSUFBSyxJQUFJLElBQUUsR0FBRyxJQUFFLEdBQUcsRUFBRSxFQUFHO0lBQ3RCLEVBQUUsSUFBSSxDQUFDO0lBQ1AsTUFBTSxHQUFHLEtBQUssQ0FBQyxDQUFDLEVBQUUsRUFBRSxHQUFHO0VBQ3pCO0VBQ0EsT0FBTztBQUNUO0FBR0E7Ozs7OztDQU1DLEdBQ0QsT0FBTyxTQUFTLGVBQWtCLENBQU0sRUFBRSxFQUF3QixFQUFFLEdBQU07RUFDeEUsTUFBTSxJQUFJLEVBQUUsTUFBTTtFQUNsQixJQUFLLElBQUksSUFBRSxHQUFHLElBQUUsR0FBRyxFQUFFLEVBQUc7SUFDdEIsTUFBTSxJQUFJLENBQUMsQ0FBQyxFQUFFO0lBQ2QsQ0FBQyxDQUFDLEVBQUUsR0FBRztJQUNQLE1BQU0sR0FBRyxLQUFLLEdBQUcsR0FBRztFQUN0QjtFQUNBLE9BQU87QUFDVDtBQUdBOzs7Ozs7Q0FNQyxHQUNELE9BQU8sU0FBUyxjQUFzQixDQUFNLEVBQUUsRUFBMEIsRUFBRSxHQUFTO0VBQ2pGLElBQUksT0FBTyxVQUFVLE1BQU0sSUFBSTtFQUMvQixNQUFNLElBQWEsRUFBRTtFQUNyQixNQUFNLElBQUksRUFBRSxNQUFNO0VBQ2xCLElBQUssSUFBSSxJQUFFLEdBQUcsSUFBRSxHQUFHLEVBQUUsRUFBRztJQUN0QixNQUFNLE9BQU0sQ0FBQyxDQUFDLEVBQUUsR0FBRyxHQUFHLEtBQVksQ0FBQyxDQUFDLEVBQUUsRUFBRSxHQUFHO0lBQzNDLEVBQUUsSUFBSSxDQUFDO0lBQ1AsT0FBTztFQUNUO0VBQ0EsT0FBTztBQUNUO0FBQ0EsU0FBUSxpQkFBaUIsVUFBVSxHQUFFO0FBR3JDOzs7Ozs7Q0FNQyxHQUNELE9BQU8sU0FBUyxlQUFrQixDQUFNLEVBQUUsRUFBd0IsRUFBRSxHQUFNO0VBQ3hFLE1BQU0sSUFBSSxFQUFFLE1BQU07RUFDbEIsSUFBSyxJQUFJLElBQUUsR0FBRyxJQUFFLEdBQUcsRUFBRSxFQUNuQixNQUFNLENBQUMsQ0FBQyxFQUFFLEdBQUcsR0FBRyxLQUFLLENBQUMsQ0FBQyxFQUFFLEVBQUUsR0FBRztFQUNoQyxPQUFPO0FBQ1Q7QUFHQTs7Ozs7O0NBTUMsR0FDRCxPQUFPLFNBQVMsZ0JBQW1CLENBQU0sRUFBRSxFQUFzQixFQUFFLEdBQU07RUFDdkUsTUFBTSxJQUFTLEVBQUU7RUFDakIsSUFBSSxFQUFFLE1BQU0sR0FBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUMsRUFBRTtFQUNuQyxNQUFNLElBQUksRUFBRSxNQUFNO0VBQ2xCLElBQUssSUFBSSxJQUFFLEdBQUcsSUFBRSxHQUFHLEVBQUUsRUFDbkIsRUFBRSxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDLEVBQUU7RUFDeEIsT0FBTztBQUNUO0FBQ0EsaUJBQWlCO0FBR2pCOzs7Ozs7Q0FNQyxHQUNELE9BQU8sU0FBUyxpQkFBb0IsQ0FBTSxFQUFFLEVBQXNCLEVBQUUsR0FBTTtFQUN4RSxNQUFNLElBQUksRUFBRSxNQUFNO0VBQ2xCLElBQUksTUFBSSxHQUFHLE9BQU87RUFDbEIsSUFBSSxJQUFJLENBQUMsQ0FBQyxFQUFFO0VBQ1osQ0FBQyxDQUFDLEVBQUUsR0FBSSxHQUFHLEtBQUs7RUFDaEIsSUFBSyxJQUFJLElBQUUsR0FBRyxJQUFFLEdBQUcsRUFBRSxFQUFHO0lBQ3RCLE1BQU0sSUFBSSxDQUFDLENBQUMsRUFBRTtJQUNkLENBQUMsQ0FBQyxFQUFFLEdBQUksR0FBRyxHQUFHO0lBQ2QsSUFBSTtFQUNOO0VBQ0EsT0FBTztBQUNUO0FBQ0EsYUFBYTtBQUtiLGtCQUFrQjtBQUNsQixrQkFBa0I7QUFFbEI7Ozs7O0NBS0MsR0FDRCxPQUFPLFNBQVMsWUFBZSxDQUFNLEVBQUUsQ0FBSTtFQUN6QyxNQUFNLElBQVMsRUFBRTtFQUFFLElBQUksSUFBSSxDQUFDO0VBQzVCLEtBQUssTUFBTSxLQUFLLEVBQUc7SUFDakIsSUFBSSxFQUFFLElBQUUsR0FBRyxFQUFFLElBQUksQ0FBQztJQUNsQixFQUFFLElBQUksQ0FBQztFQUNUO0VBQ0EsT0FBTztBQUNUO0FBR0E7Ozs7O0NBS0MsR0FDRCxPQUFPLFNBQVMsWUFBZSxDQUFNLEVBQUUsRUFBc0I7RUFDM0QsTUFBTSxJQUFJLEVBQUU7RUFDWixJQUFJLElBQU87RUFDWCxJQUFJLElBQUksQ0FBQztFQUNULEtBQUssTUFBTSxLQUFLLEVBQUc7SUFDakIsSUFBSSxFQUFFLElBQUUsR0FBRyxFQUFFLElBQUksQ0FBQyxHQUFHLEdBQUc7SUFDeEIsRUFBRSxJQUFJLENBQUMsSUFBSTtFQUNiO0VBQ0EsT0FBTztBQUNUO0FBR0E7Ozs7Ozs7OztDQVNDLEdBQ0QsT0FBTyxTQUFTLFNBQVksQ0FBTSxFQUFFLENBQU0sRUFBRSxJQUFVLENBQUMsRUFBRSxJQUFVLENBQUMsRUFBRSxJQUFVLENBQUMsRUFBRSxJQUFVLENBQUM7RUFDNUYsTUFBTSxJQUFJLEVBQUUsTUFBTTtFQUNsQixNQUFNLElBQUksRUFBRSxNQUFNO0VBQ2xCLE1BQU0sSUFBUyxFQUFFO0VBQ2pCLElBQUksS0FBSyxHQUFHLENBQUMsR0FBRztFQUNoQixJQUFJLEtBQUssR0FBRyxDQUFDLEdBQUc7RUFDaEIsSUFBSSxLQUFLLEdBQUcsQ0FBQyxHQUFHO0VBQ2hCLElBQUksS0FBSyxHQUFHLENBQUMsR0FBRztFQUNoQixJQUFLLElBQUksSUFBRSxHQUFHLElBQUUsR0FBRyxJQUFFLEdBQUcsS0FBRyxFQUFHO0lBQzVCLElBQUksSUFBRSxHQUFHO01BQ1AsSUFBSyxJQUFJLElBQUUsR0FBRyxJQUFFLElBQUUsR0FBRyxJQUFFLEdBQUcsRUFBRSxFQUMxQixFQUFFLElBQUksQ0FBQyxDQUFDLENBQUMsSUFBSSxFQUFFO01BQ2pCLEtBQUs7SUFDUDtJQUNBLFFBQVEsR0FBRyxFQUFFLEtBQUssQ0FBQyxHQUFHLElBQUU7RUFDMUI7RUFDQSxPQUFPO0FBQ1Q7QUFHQTs7OztDQUlDLEdBQ0QsT0FBTyxTQUFTLFdBQWMsRUFBUztFQUNyQyxNQUFNLElBQVMsRUFBRTtFQUNqQixJQUFLLElBQUksSUFBRSxJQUFJLEVBQUUsRUFBRztJQUNsQixJQUFJLElBQUk7SUFDUixLQUFLLE1BQU0sS0FBSyxHQUNkLElBQUksSUFBRSxFQUFFLE1BQU0sRUFBRTtNQUFFLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFO01BQUcsRUFBRTtJQUFHO0lBQ3ZDLElBQUksTUFBSSxHQUFHO0VBQ2I7RUFDQSxPQUFPO0FBQ1Q7QUFHQTs7Ozs7OztDQU9DLEdBQ0QsT0FBTyxTQUFTLElBQWMsRUFBUyxFQUFFLEtBQW1DLElBQUksRUFBRSxLQUF1QixJQUFJLEVBQUUsRUFBTTtFQUNuSCxLQUFLLE1BQU07RUFDWCxLQUFLLE1BQU07RUFDWCxNQUFNLElBQUksR0FBRyxNQUFNLEVBQUUsSUFBZSxFQUFFO0VBQ3RDLElBQUksTUFBSSxHQUFHLE9BQU87RUFDbEIsTUFBTSxLQUFLLElBQUksTUFBTSxHQUFHLElBQUksQ0FBQztFQUM3QixNQUFNLEtBQUssR0FBRyxHQUFHLENBQUMsQ0FBQSxJQUFLLEVBQUUsTUFBTTtFQUMvQixJQUFLLElBQUksSUFBRSxJQUFJLEVBQUUsRUFBRztJQUNsQixNQUFNLEtBQVUsRUFBRTtJQUNsQixJQUFLLElBQUksSUFBRSxHQUFHLElBQUUsR0FBRyxFQUFFLEVBQUc7TUFDdEIsRUFBRSxDQUFDLEVBQUUsR0FBRyxLQUFHLEVBQUUsQ0FBQyxFQUFFO01BQ2hCLEVBQUUsQ0FBQyxFQUFFLEdBQUcsRUFBRSxDQUFDLEVBQUUsR0FBRSxLQUFVLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRTtJQUNuQztJQUNBLElBQUksR0FBRyxLQUFLO0lBQ1osRUFBRSxJQUFJLENBQUMsR0FBRyxJQUFJLEdBQUc7RUFDbkI7RUFDQSxPQUFPO0FBQ1Q7QUFHQSxnQkFBZ0I7QUFDaEIsYUFBYTtBQUtiLHVCQUF1QjtBQUN2Qix1QkFBdUI7QUFFdkI7Ozs7Ozs7Q0FPQyxHQUNELE9BQU8sU0FBUyxLQUFRLENBQU0sRUFBRSxDQUFJLEVBQUUsSUFBVSxDQUFDLEVBQUUsSUFBVSxFQUFFLE1BQU07RUFDbkUsT0FBTyxFQUFFLEtBQUssR0FBRyxJQUFJLENBQUMsR0FBRyxHQUFHO0FBQzlCO0FBR0E7Ozs7Ozs7Q0FPQyxHQUNELE9BQU8sU0FBUyxNQUFTLENBQU0sRUFBRSxDQUFJLEVBQUUsSUFBVSxDQUFDLEVBQUUsSUFBVSxFQUFFLE1BQU07RUFDcEUsT0FBTyxFQUFFLElBQUksQ0FBQyxHQUFHLEdBQUc7QUFDdEI7QUFHQTs7Ozs7Q0FLQyxHQUNELE9BQU8sU0FBUyxLQUFRLENBQU0sRUFBRSxHQUFHLEVBQU87RUFDeEMsT0FBTyxFQUFFLE1BQU0sQ0FBQztBQUNsQjtBQUNBLFNBQVEsUUFBUSxRQUFRLEdBQUU7QUFDMUIsU0FBUSxRQUFRLE1BQU0sR0FBRTtBQUd4Qjs7Ozs7Q0FLQyxHQUNELE9BQU8sU0FBUyxNQUFTLENBQU0sRUFBRSxHQUFHLEVBQU87RUFDekMsRUFBRSxJQUFJLElBQUk7RUFDVixPQUFPO0FBQ1Q7QUFDQSxTQUFRLFNBQVMsU0FBUyxHQUFFO0FBQzVCLFNBQVEsU0FBUyxPQUFPLEdBQUU7QUFHMUI7Ozs7Q0FJQyxHQUNELE9BQU8sU0FBUyxJQUFPLENBQU07RUFDM0IsT0FBTyxFQUFFLEtBQUssQ0FBQyxHQUFHLENBQUM7QUFDckI7QUFDQSxTQUFRLE9BQU8sT0FBTyxHQUFFO0FBR3hCOzs7O0NBSUMsR0FDRCxPQUFPLFNBQVMsS0FBUSxDQUFNO0VBQzVCLEVBQUUsR0FBRztFQUNMLE9BQU87QUFDVDtBQUNBLFNBQVEsT0FBTyxRQUFRLEdBQUU7QUFHekI7Ozs7Q0FJQyxHQUNELE9BQU8sU0FBUyxNQUFTLENBQU07RUFDN0IsT0FBTyxFQUFFLEtBQUssQ0FBQztBQUNqQjtBQUNBLFNBQVEsU0FBUyxRQUFRLEdBQUU7QUFHM0I7Ozs7Q0FJQyxHQUNELE9BQU8sU0FBUyxPQUFVLENBQU07RUFDOUIsRUFBRSxLQUFLO0VBQ1AsT0FBTztBQUNUO0FBQ0EsU0FBUSxVQUFVLFNBQVMsR0FBRTtBQUc3Qjs7Ozs7Q0FLQyxHQUNELE9BQU8sU0FBUyxRQUFXLENBQWMsRUFBRSxHQUFHLEVBQU87RUFDbkQsT0FBTyxRQUFRLElBQUk7QUFDckI7QUFDQSxTQUFRLFdBQVcsU0FBUyxHQUFFO0FBQzlCLFNBQVEsV0FBVyxPQUFPLEdBQUU7QUFHNUI7Ozs7O0NBS0MsR0FDRCxPQUFPLFNBQVMsU0FBWSxDQUFNLEVBQUUsR0FBRyxFQUFPO0VBQzVDLEVBQUUsT0FBTyxJQUFJO0VBQ2IsT0FBTztBQUNUO0FBQ0EsU0FBUSxZQUFZLFVBQVUsR0FBRTtBQUNoQyxTQUFRLFlBQVksUUFBUSxHQUFFO0FBRzlCOzs7Ozs7OztDQVFDLEdBQ0QsT0FBTyxTQUFTLEtBQVEsQ0FBTSxFQUFFLENBQU0sRUFBRSxJQUFVLENBQUMsRUFBRSxJQUFVLENBQUMsRUFBRSxJQUFVLEVBQUUsTUFBTTtFQUNsRixPQUFPLE1BQU0sRUFBRSxLQUFLLElBQUksR0FBRyxHQUFHLEdBQUc7QUFDbkM7QUFHQTs7Ozs7Ozs7Q0FRQyxHQUNELE9BQU8sU0FBUyxNQUFTLENBQU0sRUFBRSxDQUFNLEVBQUUsSUFBVSxDQUFDLEVBQUUsSUFBVSxDQUFDLEVBQUUsSUFBVSxFQUFFLE1BQU07RUFDbkYsSUFBSSxNQUFNLEdBQUc7RUFDYixDQUFDLEdBQUcsRUFBRSxHQUFHLFdBQVcsR0FBRyxHQUFHO0VBQzFCLE1BQU8sSUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEVBQ2pCLENBQUMsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFDLEVBQUU7RUFDYixPQUFPO0FBQ1Q7QUFHQTs7Ozs7OztDQU9DLEdBQ0QsT0FBTyxTQUFTLFdBQWMsQ0FBTSxFQUFFLElBQVUsQ0FBQyxFQUFFLElBQVUsQ0FBQyxFQUFFLElBQVUsRUFBRSxNQUFNO0VBQ2hGLE9BQU8sRUFBRSxLQUFLLEdBQUcsVUFBVSxDQUFDLEdBQUcsR0FBRztBQUNwQztBQUdBOzs7Ozs7O0NBT0MsR0FDRCxPQUFPLFNBQVMsWUFBZSxDQUFNLEVBQUUsSUFBVSxDQUFDLEVBQUUsSUFBVSxDQUFDLEVBQUUsSUFBVSxFQUFFLE1BQU07RUFDakYsT0FBTyxFQUFFLFVBQVUsQ0FBQyxHQUFHLEdBQUc7QUFDNUI7QUFHQTs7Ozs7OztDQU9DLEdBQ0QsT0FBTyxTQUFTLFdBQWMsQ0FBTSxFQUFFLElBQVUsQ0FBQyxFQUFFLElBQVUsQ0FBQyxFQUFFLElBQVUsRUFBRSxNQUFNO0VBQ2hGLElBQUksTUFBTSxHQUFHO0VBQ2IsQ0FBQyxHQUFHLEVBQUUsR0FBRyxXQUFXLEdBQUcsR0FBRztFQUMxQixJQUFJLElBQUUsR0FBRyxPQUFPLFNBQVMsR0FBRyxHQUFHLEdBQUc7T0FDekIsT0FBTyxTQUFTLEdBQUcsR0FBRyxHQUFHO0FBQ3BDO0FBRUEsU0FBUyxTQUFZLENBQU0sRUFBRSxDQUFTLEVBQUUsQ0FBUyxFQUFFLENBQVM7RUFDMUQsT0FBTyxFQUFFLEtBQUssQ0FBQyxHQUFHLEdBQUcsTUFBTSxDQUN6QixFQUFFLEtBQUssQ0FBQyxHQUFHLElBQ1gsRUFBRSxLQUFLLENBQUMsR0FBRyxJQUNYLEVBQUUsS0FBSyxDQUFDO0FBRVo7QUFHQTs7Ozs7OztDQU9DLEdBQ0QsT0FBTyxTQUFTLFlBQWUsQ0FBTSxFQUFFLElBQVUsQ0FBQyxFQUFFLElBQVUsQ0FBQyxFQUFFLElBQVUsRUFBRSxNQUFNO0VBQ2pGLElBQUksTUFBTSxHQUFHO0VBQ2IsQ0FBQyxHQUFHLEVBQUUsR0FBRyxXQUFXLEdBQUcsR0FBRztFQUMxQixNQUFNLElBQUssRUFBRSxLQUFLLENBQUMsR0FBRyxJQUFJLElBQUksRUFBRSxNQUFNO0VBQ3RDLElBQUksSUFBRSxHQUFHLEVBQUUsVUFBVSxDQUFDLElBQUUsR0FBRyxHQUFHO09BQ3JCLEVBQUUsVUFBVSxDQUFDLEdBQUssR0FBRztFQUM5QixPQUFPLE1BQU0sR0FBRyxHQUFHLElBQUUsSUFBRyxJQUFJLElBQUU7QUFDaEM7QUFDQSx3RUFBd0U7QUFDeEUscUhBQXFIO0FBQ3JILHFHQUFxRztBQUdyRzs7Ozs7OztDQU9DLEdBQ0QsT0FBTyxTQUFTLE9BQVUsQ0FBTSxFQUFFLENBQVMsRUFBRSxJQUFVLEVBQUUsTUFBTSxFQUFFLEdBQUcsRUFBTztFQUN6RSxJQUFJLE1BQU0sR0FBRztFQUNiLElBQUksS0FBSyxHQUFHLENBQUMsR0FBRztFQUNoQixPQUFPLFFBQVEsRUFBRSxLQUFLLENBQUMsR0FBRyxJQUFJLElBQUksRUFBRSxLQUFLLENBQUMsSUFBRTtBQUM5QztBQUNBLFNBQVEsVUFBVSxTQUFTLEdBQUU7QUFHN0I7Ozs7Ozs7Q0FPQyxHQUNELE9BQU8sU0FBUyxRQUFXLENBQU0sRUFBRSxDQUFTLEVBQUUsSUFBVSxFQUFFLE1BQU0sRUFBRSxHQUFHLEVBQU87RUFDMUUsRUFBRSxNQUFNLENBQUMsR0FBRyxNQUFNO0VBQ2xCLE9BQU87QUFDVDtBQUNBLGFBQWE7QUFLYiwwQkFBMEI7QUFDMUIsMEJBQTBCO0FBRTFCOzs7OztDQUtDLEdBQ0QsT0FBTyxTQUFTLE1BQVMsQ0FBTSxFQUFFLEVBQW1CO0VBQ2xELElBQUksSUFBSSxDQUFDLEdBQUcsSUFBSTtFQUNoQixLQUFLLE1BQU0sS0FBSyxFQUNkLElBQUksR0FBRyxHQUFHLEVBQUUsR0FBRyxJQUFJLEVBQUU7RUFDdkIsT0FBTztBQUNUO0FBR0E7Ozs7O0NBS0MsR0FDRCxPQUFPLFNBQVMsVUFBa0IsQ0FBTSxFQUFFLEtBQStCLElBQUk7RUFDM0UsS0FBSyxNQUFNO0VBQ1gsSUFBSSxJQUFLLENBQUM7RUFBRyxNQUFNLElBQUksSUFBSTtFQUMzQixLQUFLLE1BQU0sS0FBSyxFQUFHO0lBQ2pCLE1BQU0sSUFBSSxHQUFHLEdBQUcsRUFBRSxHQUFHO0lBQ3JCLEVBQUUsR0FBRyxDQUFDLEdBQUcsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxNQUFNLENBQUMsSUFBSTtFQUM3QjtFQUNBLE9BQU87QUFDVDtBQUNBLFNBQVEsYUFBYSxPQUFPLEdBQUUsQ0FBRSxhQUFhO0FBRzdDOzs7OztDQUtDLEdBQ0QsT0FBTyxTQUFTLFVBQWEsQ0FBTSxFQUFFLEVBQW1CO0VBQ3RELE1BQU0sSUFBUyxFQUFFLEVBQUUsSUFBUyxFQUFFO0VBQzlCLElBQUksSUFBSSxDQUFDO0VBQ1QsS0FBSyxNQUFNLEtBQUssRUFBRztJQUNqQixJQUFJLEdBQUcsR0FBRyxFQUFFLEdBQUcsSUFBSSxFQUFFLElBQUksQ0FBQztTQUNyQixFQUFFLElBQUksQ0FBQztFQUNkO0VBQ0EsT0FBTztJQUFDO0lBQUc7R0FBRTtBQUNmO0FBR0E7Ozs7O0NBS0MsR0FDRCxPQUFPLFNBQVMsY0FBc0IsQ0FBTSxFQUFFLEtBQStCLElBQUk7RUFDL0UsS0FBSyxNQUFNO0VBQ1gsSUFBSSxJQUFLLENBQUM7RUFBRyxNQUFNLElBQUksSUFBSTtFQUMzQixLQUFLLE1BQU0sS0FBSyxFQUFHO0lBQ2pCLE1BQU0sSUFBSSxHQUFHLEdBQUcsRUFBRSxHQUFHO0lBQ3JCLElBQUksQ0FBQyxFQUFFLEdBQUcsQ0FBQyxJQUFJLEVBQUUsR0FBRyxDQUFDLEdBQUcsRUFBRTtJQUMxQixFQUFFLEdBQUcsQ0FBQyxHQUFJLElBQUksQ0FBQztFQUNqQjtFQUNBLE9BQU87QUFDVDtBQUNBLFNBQVEsaUJBQWlCLFVBQVUsR0FBRTtBQUNyQyxTQUFRLGlCQUFpQixXQUFXLEdBQUUsQ0FBSSxhQUFhO0FBQ3ZELGFBQWE7QUFLYixpQkFBaUI7QUFDakIsaUJBQWlCO0FBRWpCOzs7OztDQUtDLEdBQ0QsT0FBTyxTQUFTLE1BQVMsQ0FBTSxFQUFFLEVBQW1CO0VBQ2xELElBQUksSUFBSSxDQUFDO0VBQ1QsTUFBTSxJQUFXLEVBQUU7RUFDbkIsSUFBSSxJQUFTLEVBQUU7RUFDZixLQUFLLE1BQU0sS0FBSyxFQUFHO0lBQ2pCLElBQUksQ0FBQyxHQUFHLEdBQUcsRUFBRSxHQUFHLElBQUssRUFBRSxJQUFJLENBQUM7U0FDdkIsSUFBSSxFQUFFLE1BQU0sRUFBRTtNQUFFLEVBQUUsSUFBSSxDQUFDO01BQUksSUFBSSxFQUFFO0lBQUU7RUFDMUM7RUFDQSxJQUFJLEVBQUUsTUFBTSxFQUFFLEVBQUUsSUFBSSxDQUFDO0VBQ3JCLE9BQU87QUFDVDtBQUdBOzs7OztDQUtDLEdBQ0QsT0FBTyxTQUFTLFFBQVcsQ0FBTSxFQUFFLEVBQVk7RUFDN0MsSUFBSSxJQUFJLENBQUM7RUFDVCxNQUFNLElBQVcsRUFBRTtFQUNuQixJQUFJLElBQVMsRUFBRTtFQUNmLEtBQUssTUFBTSxLQUFLLEVBQUc7SUFDakIsSUFBSSxDQUFDLEdBQUcsUUFBUSxDQUFDLEVBQUUsSUFBSSxFQUFFLElBQUksQ0FBQztTQUN6QixJQUFHLEVBQUUsTUFBTSxFQUFLO01BQUUsRUFBRSxJQUFJLENBQUM7TUFBSSxJQUFJLEVBQUU7SUFBRTtFQUM1QztFQUNBLElBQUksRUFBRSxNQUFNLEVBQUUsRUFBRSxJQUFJLENBQUM7RUFDckIsT0FBTztBQUNUO0FBR0E7Ozs7O0NBS0MsR0FDRCxPQUFPLFNBQVMsSUFBTyxDQUFNLEVBQUUsRUFBbUI7RUFDaEQsSUFBSSxJQUFJO0VBQUcsTUFBTSxJQUFJLEVBQUU7RUFDdkIsTUFBTSxJQUFJLEVBQUUsTUFBTTtFQUNsQixJQUFLLElBQUksSUFBRSxHQUFHLElBQUUsR0FBRyxFQUFFLEVBQUc7SUFDdEIsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsRUFBRSxHQUFHLElBQUk7SUFDckIsRUFBRSxJQUFJLENBQUMsRUFBRSxLQUFLLENBQUMsR0FBRztJQUNsQixJQUFJO0VBQ047RUFDQSxFQUFFLElBQUksQ0FBQyxFQUFFLEtBQUssQ0FBQztFQUNmLE9BQU87QUFDVDtBQUdBOzs7OztDQUtDLEdBQ0QsT0FBTyxTQUFTLFNBQVksQ0FBTSxFQUFFLEVBQW1CO0VBQ3JELElBQUksSUFBSTtFQUFHLE1BQU0sSUFBSSxFQUFFO0VBQ3ZCLE1BQU0sSUFBSSxFQUFFLE1BQU07RUFDbEIsSUFBSyxJQUFJLElBQUUsR0FBRyxJQUFFLEdBQUcsRUFBRSxFQUFHO0lBQ3RCLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLEVBQUUsR0FBRyxJQUFJO0lBQ3JCLEVBQUUsSUFBSSxDQUFDLEVBQUUsS0FBSyxDQUFDLEdBQUcsSUFBRTtJQUNwQixJQUFJLElBQUU7RUFDUjtFQUNBLEVBQUUsSUFBSSxDQUFDLEVBQUUsS0FBSyxDQUFDO0VBQ2YsT0FBTztBQUNUO0FBR0E7Ozs7O0NBS0MsR0FDRCxPQUFPLFNBQVMsTUFBUyxDQUFNLEVBQUUsRUFBWTtFQUMzQyxNQUFNLElBQUksRUFBRSxNQUFNO0VBQ2xCLElBQUksSUFBSTtFQUFHLE1BQU0sSUFBSSxFQUFFO0VBQ3ZCLEtBQUssSUFBSSxLQUFLLEdBQUk7SUFDaEIsSUFBSSxJQUFFLElBQUcsSUFBRSxJQUFJO0lBQ2YsRUFBRSxJQUFJLENBQUMsRUFBRSxLQUFLLENBQUMsR0FBRztJQUNsQixJQUFJLEtBQUssR0FBRyxDQUFDLEdBQUc7RUFDbEI7RUFDQSxFQUFFLElBQUksQ0FBQyxFQUFFLEtBQUssQ0FBQztFQUNmLE9BQU87QUFDVDtBQUdBOzs7OztDQUtDLEdBQ0QsT0FBTyxTQUFTLFdBQWMsQ0FBTSxFQUFFLEVBQVk7RUFDaEQsTUFBTSxJQUFJLEVBQUUsTUFBTTtFQUNsQixJQUFJLElBQUk7RUFBRyxNQUFNLElBQUksRUFBRTtFQUN2QixLQUFLLElBQUksS0FBSyxHQUFJO0lBQ2hCLElBQUksSUFBRSxJQUFHLElBQUUsSUFBSTtJQUNmLEVBQUUsSUFBSSxDQUFDLEVBQUUsS0FBSyxDQUFDLEdBQUcsSUFBRTtJQUNwQixJQUFJLEtBQUssR0FBRyxDQUFDLEdBQUcsSUFBRTtFQUNwQjtFQUNBLEVBQUUsSUFBSSxDQUFDLEVBQUUsS0FBSyxDQUFDO0VBQ2YsT0FBTztBQUNUO0FBR0E7Ozs7OztDQU1DLEdBQ0QsT0FBTyxTQUFTLE1BQWMsQ0FBTSxFQUFFLEtBQWdDLElBQUksRUFBRSxLQUErQixJQUFJO0VBQzdHLEtBQUssTUFBTTtFQUNYLEtBQUssTUFBTTtFQUNYLE1BQU0sSUFBVyxFQUFFO0VBQ25CLElBQUksSUFBUyxFQUFFO0VBQ2YsSUFBSSxJQUFTLFdBQWdCLElBQUksQ0FBQztFQUNsQyxLQUFLLE1BQU0sS0FBSyxFQUFHO0lBQ2pCLE1BQU0sSUFBSSxHQUFHLEdBQUcsRUFBRSxHQUFHO0lBQ3JCLElBQUksTUFBSSxLQUFLLEdBQUcsR0FBRyxPQUFLLEdBQUcsRUFBRSxJQUFJLENBQUM7U0FDN0I7TUFBRSxFQUFFLElBQUksQ0FBQztNQUFJLElBQUk7UUFBQztPQUFFO0lBQUU7SUFDM0IsSUFBSTtFQUNOO0VBQ0EsRUFBRSxJQUFJLENBQUM7RUFDUCxPQUFPO0FBQ1Q7QUFHQTs7Ozs7O0NBTUMsR0FDRCxPQUFPLFNBQVMsTUFBUyxDQUFNLEVBQUUsSUFBVSxDQUFDLEVBQUUsSUFBVSxDQUFDO0VBQ3ZELE1BQU0sSUFBVyxFQUFFO0VBQ25CLElBQUksSUFBRSxHQUFHLE9BQU87RUFDaEIsSUFBSSxLQUFLLEdBQUcsQ0FBQyxHQUFHO0VBQ2hCLE1BQU0sSUFBSSxFQUFFLE1BQU07RUFDbEIsSUFBSyxJQUFJLElBQUUsR0FBRyxJQUFFLEdBQUcsS0FBRyxFQUNwQixFQUFFLElBQUksQ0FBQyxFQUFFLEtBQUssQ0FBQyxHQUFHLElBQUU7RUFDdEIsT0FBTztBQUNUO0FBQ0EsYUFBYTtBQUtiLHNCQUFzQjtBQUN0QixzQkFBc0I7QUFFdEI7Ozs7Q0FJQyxHQUNELE9BQU8sU0FBUyxPQUFVLEdBQUcsRUFBUztFQUNwQyxPQUFPLEFBQUMsRUFBRSxDQUFTLE1BQU0sSUFBSTtBQUMvQjtBQUdBOzs7OztDQUtDLEdBQ0QsT0FBTyxTQUFTLFFBQVcsQ0FBTSxFQUFFLEdBQUcsRUFBaUI7RUFDckQsS0FBSyxNQUFNLEtBQUssR0FDZCxFQUFFLElBQUksSUFBSTtFQUNaLE9BQU87QUFDVDtBQUdBOzs7OztDQUtDLEdBQ0QsT0FBTyxTQUFTLEtBQVEsQ0FBTSxFQUFFLE1BQVksR0FBRztFQUM3QyxPQUFPLEVBQUUsSUFBSSxDQUFDO0FBQ2hCO0FBQ0EsYUFBYTtBQUtiLG9CQUFvQjtBQUNwQixvQkFBb0I7QUFFcEI7Ozs7O0NBS0MsR0FDRCxPQUFPLFNBQVMsTUFBUyxDQUFNLEVBQUUsSUFBVSxDQUFDLEVBQUUsSUFBVSxFQUFFLE1BQU07RUFDOUQsTUFBTSxJQUFJLEVBQUUsTUFBTTtFQUNsQixJQUFJLEtBQUcsS0FBSyxNQUFJLEdBQUcsT0FBTyxFQUFFO0VBQzVCLElBQUksSUFBSSxHQUFHO0VBQ1gsTUFBTSxJQUFJLEVBQUUsS0FBSyxDQUFDLEdBQUcsSUFBRTtFQUN2QixLQUFLLEVBQUUsTUFBTTtFQUNiLE1BQU0sSUFBSSxLQUFLLEtBQUssQ0FBQyxJQUFFO0VBQ3ZCLElBQUssSUFBSSxJQUFFLEdBQUcsSUFBRSxHQUFHLEVBQUUsRUFDbkIsUUFBUSxHQUFHO0VBQ2IsT0FBTyxRQUFRLEdBQUcsRUFBRSxLQUFLLENBQUMsR0FBRyxJQUFJO0FBQ25DO0FBR0E7Ozs7O0NBS0MsR0FDRCxPQUFPLFNBQVMsT0FBVSxDQUFNLEVBQUUsSUFBVSxDQUFDO0VBQzNDLE1BQU0sSUFBUyxFQUFFO0VBQ2pCLE1BQU8sSUFBRSxHQUFHLEVBQUUsRUFDWixRQUFRLEdBQUc7RUFDYixPQUFPO0FBQ1Q7QUFHQTs7OztDQUlDLEdBQ0QsT0FBTyxTQUFTLFFBQVcsQ0FBTTtFQUMvQixPQUFPLEVBQUUsS0FBSyxHQUFHLE9BQU87QUFDMUI7QUFDQSxTQUFRLFdBQVcsVUFBVSxHQUFFO0FBRy9COzs7O0NBSUMsR0FDRCxPQUFPLFNBQVMsU0FBWSxDQUFNO0VBQ2hDLE9BQU8sRUFBRSxPQUFPO0FBQ2xCO0FBR0E7Ozs7O0NBS0MsR0FDRCxPQUFPLFNBQVMsT0FBVSxDQUFNLEVBQUUsSUFBVSxDQUFDO0VBQzNDLElBQUksSUFBSSxHQUFHLEVBQUUsTUFBTTtFQUNuQixPQUFPLFFBQVEsRUFBRSxLQUFLLENBQUMsSUFBSSxFQUFFLEtBQUssQ0FBQyxHQUFHO0FBQ3hDO0FBR0E7Ozs7O0NBS0MsR0FDRCxPQUFPLFNBQVMsUUFBVyxDQUFNLEVBQUUsSUFBVSxDQUFDO0VBQzVDLElBQUksSUFBSSxHQUFHLEVBQUUsTUFBTTtFQUNuQixNQUFNLElBQUksRUFBRSxLQUFLLENBQUMsR0FBRztFQUNyQixFQUFFLFVBQVUsQ0FBQyxHQUFHO0VBQ2hCLE9BQU8sTUFBTSxHQUFHLEdBQUcsRUFBRSxNQUFNLEdBQUM7QUFDOUI7QUFDQSxhQUFhO0FBS2IseUJBQXlCO0FBQ3pCLDJCQUEyQjtBQUUzQjs7Ozs7O0NBTUMsR0FDRCxPQUFPLFNBQVMsU0FBaUIsQ0FBTSxFQUFFLEtBQWdDLElBQUksRUFBRSxLQUErQixJQUFJO0VBQ2hILElBQUksSUFBSSxPQUFPLGFBQWEsR0FBRyxJQUFJO09BQzNCLE9BQU8sWUFBYSxHQUFHO0FBQ2pDO0FBRUEsU0FBUyxZQUFvQixDQUFNLEVBQUUsS0FBK0IsSUFBSTtFQUN0RSxLQUFLLE1BQU07RUFDWCxNQUFNLElBQUssSUFBSTtFQUFPLElBQUksSUFBSSxDQUFDO0VBQy9CLEtBQUssTUFBTSxLQUFLLEVBQUc7SUFDakIsTUFBTSxJQUFJLEdBQUcsR0FBRyxFQUFFLEdBQUc7SUFDckIsSUFBSSxFQUFFLEdBQUcsQ0FBQyxJQUFJLE9BQU87SUFDckIsRUFBRSxHQUFHLENBQUM7RUFDUjtFQUNBLE9BQU87QUFDVDtBQUVBLFNBQVMsYUFBcUIsQ0FBTSxFQUFFLEtBQWdDLElBQUksRUFBRSxLQUErQixJQUFJO0VBQzdHLEtBQUssTUFBTTtFQUNYLEtBQUssTUFBTTtFQUNYLE1BQU0sS0FBSztPQUFJO0dBQUUsQ0FBQyxHQUFHLENBQUM7RUFDdEIsS0FBSyxNQUFNLE1BQU0sR0FBSTtJQUNuQixLQUFLLE1BQU0sTUFBTSxHQUNmLElBQUksR0FBRyxJQUFJLFFBQU0sR0FBRyxPQUFPO0VBQy9CO0VBQ0EsT0FBTztBQUNUO0FBR0E7Ozs7Ozs7Q0FPQyxHQUNELE9BQU8sU0FBUyxXQUFtQixDQUFNLEVBQUUsQ0FBTSxFQUFFLEtBQWdDLElBQUksRUFBRSxLQUErQixJQUFJO0VBQzFILElBQUksSUFBSSxPQUFPLGVBQWUsR0FBRyxHQUFHLElBQUk7T0FDaEMsT0FBTyxjQUFlLEdBQUcsR0FBRztBQUN0QztBQUVBLFNBQVMsY0FBc0IsQ0FBTSxFQUFFLENBQU0sRUFBRSxLQUErQixJQUFJO0VBQ2hGLEtBQUssTUFBTTtFQUNYLE1BQU0sSUFBSyxNQUFNLEdBQUc7RUFBSyxJQUFJLElBQUksQ0FBQztFQUNsQyxLQUFLLE1BQU0sS0FBSyxFQUFHO0lBQ2pCLE1BQU0sSUFBSSxHQUFHLEdBQUcsRUFBRSxHQUFHO0lBQ3JCLElBQUksRUFBRSxHQUFHLENBQUMsSUFBSSxPQUFPO0VBQ3ZCO0VBQ0EsT0FBTztBQUNUO0FBRUEsU0FBUyxlQUF1QixDQUFNLEVBQUUsQ0FBTSxFQUFFLEtBQWdDLElBQUksRUFBRSxLQUErQixJQUFJO0VBQ3ZILEtBQUssTUFBTTtFQUNYLEtBQUssTUFBTTtFQUNYLE1BQU0sS0FBSztPQUFJO0dBQUUsQ0FBQyxHQUFHLENBQUM7RUFBSyxJQUFJLElBQUksQ0FBQztFQUNwQyxLQUFLLE1BQU0sTUFBTSxFQUFHO0lBQ2xCLE1BQU0sS0FBSyxHQUFHLElBQUksRUFBRSxHQUFHO0lBQ3ZCLEtBQUssTUFBTSxNQUFNLEdBQ2YsSUFBSSxHQUFHLElBQUksUUFBTSxHQUFHLE9BQU87RUFDL0I7RUFDQSxPQUFPO0FBQ1Q7QUFHQTs7Ozs7O0NBTUMsR0FDRCxPQUFPLFNBQVMsT0FBZSxDQUFNLEVBQUUsS0FBZ0MsSUFBSSxFQUFFLEtBQStCLElBQUk7RUFDOUcsSUFBSSxJQUFJLE9BQU8sV0FBVyxHQUFHLElBQUk7T0FDekIsT0FBTyxVQUFXLEdBQUc7QUFDL0I7QUFFQSxTQUFTLFVBQWtCLENBQU0sRUFBRSxLQUErQixJQUFJO0VBQ3BFLEtBQUssTUFBTTtFQUNYLE1BQU0sSUFBSyxJQUFJO0VBQ2YsSUFBSSxJQUFLLENBQUM7RUFBRyxNQUFNLElBQUksRUFBRTtFQUN6QixLQUFLLE1BQU0sS0FBSyxFQUFHO0lBQ2pCLE1BQU0sSUFBSSxHQUFHLEdBQUcsRUFBRSxHQUFHO0lBQ3JCLElBQUksRUFBRSxHQUFHLENBQUMsSUFBSTtJQUNkLEVBQUUsR0FBRyxDQUFDO0lBQUksRUFBRSxJQUFJLENBQUM7RUFDbkI7RUFDQSxPQUFPO0FBQ1Q7QUFFQSxTQUFTLFdBQW1CLENBQU0sRUFBRSxLQUFnQyxJQUFJLEVBQUUsS0FBK0IsSUFBSTtFQUMzRyxLQUFLLE1BQU07RUFDWCxLQUFLLE1BQU07RUFDWCxJQUFJLElBQUssQ0FBQztFQUFHLE1BQU0sSUFBSSxFQUFFLEVBQUUsSUFBSSxFQUFFO0VBQ2pDLEdBQUcsS0FBSyxNQUFNLE1BQU0sRUFBRztJQUNyQixNQUFNLEtBQUssR0FBRyxJQUFJLEVBQUUsR0FBRztJQUN2QixLQUFLLE1BQU0sTUFBTSxFQUNmLElBQUksR0FBRyxJQUFJLFFBQU0sR0FBRyxTQUFTO0lBQy9CLEVBQUUsSUFBSSxDQUFDO0lBQUssRUFBRSxJQUFJLENBQUM7RUFDckI7RUFDQSxPQUFPO0FBQ1Q7QUFHQTs7Ozs7OztDQU9DLEdBQ0QsT0FBTyxTQUFTLE1BQWMsQ0FBTSxFQUFFLENBQU0sRUFBRSxLQUFnQyxJQUFJLEVBQUUsS0FBK0IsSUFBSTtFQUNySCxPQUFPLE9BQU8sRUFBRSxLQUFLLElBQUksR0FBRyxJQUFJO0FBQ2xDO0FBR0E7Ozs7Ozs7Q0FPQyxHQUNELE9BQU8sU0FBUyxPQUFlLENBQU0sRUFBRSxDQUFNLEVBQUUsS0FBZ0MsSUFBSSxFQUFFLEtBQStCLElBQUk7RUFDdEgsSUFBSSxJQUFJLE9BQU8sV0FBVyxHQUFHLEdBQUcsSUFBSTtPQUM1QixPQUFPLFVBQVcsR0FBRyxHQUFHO0FBQ2xDO0FBRUEsU0FBUyxVQUFrQixDQUFNLEVBQUUsQ0FBTSxFQUFFLEtBQStCLElBQUk7RUFDNUUsS0FBSyxNQUFNO0VBQ1gsTUFBTSxJQUFLLE1BQU0sR0FBRztFQUFLLElBQUksSUFBSSxDQUFDO0VBQ2xDLEtBQUssTUFBTSxNQUFNLEVBQUc7SUFDbEIsTUFBTSxLQUFLLEdBQUcsSUFBSSxFQUFFLEdBQUc7SUFDdkIsSUFBSSxDQUFDLEVBQUUsR0FBRyxDQUFDLEtBQUssRUFBRSxJQUFJLENBQUM7RUFDekI7RUFDQSxPQUFPO0FBQ1Q7QUFFQSxTQUFTLFdBQW1CLENBQU0sRUFBRSxDQUFNLEVBQUUsS0FBZ0MsSUFBSSxFQUFFLEtBQStCLElBQUk7RUFDbkgsS0FBSyxNQUFNO0VBQ1gsS0FBSyxNQUFNO0VBQ1gsTUFBTSxLQUFLLEVBQUUsR0FBRyxDQUFDO0VBQUssSUFBSSxJQUFJLENBQUM7RUFDL0IsR0FBRyxLQUFLLE1BQU0sTUFBTSxFQUFHO0lBQ3JCLE1BQU0sS0FBSyxHQUFHLElBQUksRUFBRSxHQUFHO0lBQ3ZCLEtBQUssTUFBTSxNQUFNLEdBQ2YsSUFBSSxHQUFHLElBQUksUUFBTSxHQUFHLFNBQVM7SUFDL0IsRUFBRSxJQUFJLENBQUM7RUFDVDtFQUNBLE9BQU87QUFDVDtBQUdBOzs7Ozs7O0NBT0MsR0FDRCxPQUFPLFNBQVMsYUFBcUIsQ0FBTSxFQUFFLENBQU0sRUFBRSxLQUFnQyxJQUFJLEVBQUUsS0FBK0IsSUFBSTtFQUM1SCxJQUFJLElBQUksT0FBTyxpQkFBaUIsR0FBRyxHQUFHLElBQUk7T0FDbEMsT0FBTyxnQkFBaUIsR0FBRyxHQUFHO0FBQ3hDO0FBRUEsU0FBUyxnQkFBd0IsQ0FBTSxFQUFFLENBQU0sRUFBRSxLQUErQixJQUFJO0VBQ2xGLEtBQUssTUFBTTtFQUNYLE1BQU0sSUFBSyxNQUFNLEdBQUc7RUFDcEIsSUFBSSxJQUFLLENBQUM7RUFBRyxNQUFNLElBQUksRUFBRTtFQUN6QixLQUFLLE1BQU0sTUFBTSxFQUFHO0lBQ2xCLE1BQU0sS0FBSyxHQUFHLElBQUksRUFBRSxHQUFHO0lBQ3ZCLElBQUksRUFBRSxHQUFHLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQztFQUN4QjtFQUNBLE9BQU87QUFDVDtBQUVBLFNBQVMsaUJBQXlCLENBQU0sRUFBRSxDQUFNLEVBQUUsS0FBZ0MsSUFBSSxFQUFFLEtBQStCLElBQUk7RUFDekgsS0FBSyxNQUFNO0VBQ1gsS0FBSyxNQUFNO0VBQ1gsTUFBTSxLQUFLO09BQUk7R0FBRSxDQUFDLEdBQUcsQ0FBQztFQUN0QixJQUFJLElBQUssQ0FBQztFQUFHLE1BQU0sSUFBSSxFQUFFO0VBQ3pCLEdBQUcsS0FBSyxNQUFNLE1BQU0sRUFBRztJQUNyQixNQUFNLEtBQUssR0FBRyxJQUFJLEVBQUUsR0FBRztJQUN2QixLQUFLLE1BQU0sTUFBTSxHQUNmLElBQUksR0FBRyxJQUFJLFFBQU0sR0FBRztNQUFFLEVBQUUsSUFBSSxDQUFDO01BQUssU0FBUztJQUFHO0VBQ2xEO0VBQ0EsT0FBTztBQUNUO0FBR0E7Ozs7Ozs7Q0FPQyxHQUNELE9BQU8sU0FBUyxXQUFtQixDQUFNLEVBQUUsQ0FBTSxFQUFFLEtBQWdDLElBQUksRUFBRSxLQUErQixJQUFJO0VBQzFILElBQUksSUFBSSxPQUFPLGVBQWUsR0FBRyxHQUFHLElBQUk7T0FDaEMsT0FBTyxjQUFlLEdBQUcsR0FBRztBQUN0QztBQUVBLFNBQVMsY0FBc0IsQ0FBTSxFQUFFLENBQU0sRUFBRSxLQUErQixJQUFJO0VBQ2hGLEtBQUssTUFBTTtFQUNYLE1BQU0sSUFBSyxNQUFNLEdBQUc7RUFDcEIsSUFBSSxJQUFLLENBQUM7RUFBRyxNQUFNLElBQUksRUFBRTtFQUN6QixLQUFLLE1BQU0sTUFBTSxFQUFHO0lBQ2xCLE1BQU0sS0FBSyxHQUFHLElBQUksRUFBRSxHQUFHO0lBQ3ZCLElBQUksQ0FBQyxFQUFFLEdBQUcsQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDO0VBQ3pCO0VBQ0EsT0FBTztBQUNUO0FBRUEsU0FBUyxlQUF1QixDQUFNLEVBQUUsQ0FBTSxFQUFFLEtBQWdDLElBQUksRUFBRSxLQUErQixJQUFJO0VBQ3ZILEtBQUssTUFBTTtFQUNYLEtBQUssTUFBTTtFQUNYLE1BQU0sS0FBSztPQUFJO0dBQUUsQ0FBQyxHQUFHLENBQUM7RUFDdEIsSUFBSSxJQUFLLENBQUM7RUFBRyxNQUFNLElBQUssRUFBRTtFQUMxQixHQUFHLEtBQUssTUFBTSxNQUFNLEVBQUc7SUFDckIsTUFBTSxLQUFLLEdBQUcsSUFBSSxFQUFFLEdBQUc7SUFDdkIsS0FBSyxNQUFNLE1BQU0sR0FDZixJQUFJLEdBQUcsSUFBSSxRQUFNLEdBQUcsU0FBUztJQUMvQixFQUFFLElBQUksQ0FBQztFQUNUO0VBQ0EsT0FBTztBQUNUO0FBR0E7Ozs7Ozs7Q0FPQyxHQUNELE9BQU8sU0FBUyxvQkFBNEIsQ0FBTSxFQUFFLENBQU0sRUFBRSxLQUFnQyxJQUFJLEVBQUUsS0FBK0IsSUFBSTtFQUNuSSxNQUFNLEtBQUssY0FBYztFQUN6QixNQUFNLEtBQUssY0FBYztFQUN6QixNQUFNLEtBQUssV0FBVyxJQUFJLElBQUksSUFBSTtFQUNsQyxNQUFNLEtBQUssV0FBVyxJQUFJLElBQUksSUFBSTtFQUNsQyxPQUFPLFFBQVEsSUFBSTtBQUNyQjtBQUdBOzs7OztDQUtDLEdBQ0QsT0FBTyxTQUFTLGlCQUF5QixFQUFTLEVBQUUsS0FBbUMsSUFBSTtFQUN6RixLQUFLLE1BQU07RUFDWCxNQUFNLEtBQUssR0FBRyxNQUFNO0VBQ3BCLE1BQU0sSUFBZSxFQUFFO0VBQ3ZCLElBQUksT0FBSyxHQUFHLE9BQU87RUFDbkIsTUFBTSxLQUFLLElBQUksTUFBTSxJQUFJLElBQUksQ0FBQztFQUM5QixNQUFNLEtBQUssR0FBRyxHQUFHLENBQUMsQ0FBQSxJQUFLLEVBQUUsTUFBTTtFQUMvQixJQUFJLEdBQUcsSUFBSSxDQUFDLENBQUEsSUFBSyxNQUFJLElBQUksT0FBTztFQUNoQyxJQUFLLElBQUksSUFBRSxJQUFJLEVBQUUsRUFBRztJQUNsQixNQUFNLEtBQVUsRUFBRTtJQUNsQixJQUFLLElBQUksSUFBRSxHQUFHLElBQUUsSUFBSSxFQUFFLEVBQ3BCLEdBQUcsSUFBSSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQztJQUN0QixFQUFFLElBQUksQ0FBQyxHQUFHLElBQUksR0FBRztJQUNqQixJQUFJLElBQUksS0FBRztJQUNYLE1BQU8sS0FBRyxHQUFHLEVBQUUsRUFBRztNQUNoQixJQUFJLEVBQUUsRUFBRSxDQUFDLEVBQUUsR0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFO01BQ25CLEVBQUUsQ0FBQyxFQUFFLEdBQUc7SUFDVjtJQUNBLElBQUksSUFBRSxHQUFHO0VBQ1g7RUFDQSxPQUFPO0FBQ1QsRUFDQSxhQUFhO0NBQ2IsYUFBYSJ9