@alauda-fe/common
Version:
Alauda frontend team common codes.
471 lines • 61.7 kB
JavaScript
/* eslint-disable sonar/no-redundant-optional */
/* eslint-disable sonarjs/no-duplicate-string */
const DEBUG = false;
/**
* Return the bottom coordinate of the layout.
*
* @param {Array} layout Layout array.
* @return {Number} Bottom coordinate.
*/
export function bottom(layout) {
let max = 0;
let bottomY;
for (let i = 0, len = layout.length; i < len; i++) {
bottomY = layout[i].y + layout[i].h;
if (bottomY > max) {
max = bottomY;
}
}
return max;
}
export function cloneLayout(layout) {
const newLayout = Array.from({ length: layout.length });
for (let i = 0, len = layout.length; i < len; i++) {
newLayout[i] = cloneLayoutItem(layout[i]);
}
return newLayout;
}
// Fast path to cloning, since this is monomorphic
/** NOTE: This code has been modified from the original source */
export function cloneLayoutItem(layoutItem) {
const clonedLayoutItem = {
w: layoutItem.w,
h: layoutItem.h,
x: layoutItem.x,
y: layoutItem.y,
id: layoutItem.id,
moved: !!layoutItem.moved,
static: !!layoutItem.static,
};
if (layoutItem.minW !== undefined) {
clonedLayoutItem.minW = layoutItem.minW;
}
if (layoutItem.maxW !== undefined) {
clonedLayoutItem.maxW = layoutItem.maxW;
}
if (layoutItem.minH !== undefined) {
clonedLayoutItem.minH = layoutItem.minH;
}
if (layoutItem.maxH !== undefined) {
clonedLayoutItem.maxH = layoutItem.maxH;
}
// These can be null
if (layoutItem.isDraggable !== undefined) {
clonedLayoutItem.isDraggable = layoutItem.isDraggable;
}
if (layoutItem.isResizable !== undefined) {
clonedLayoutItem.isResizable = layoutItem.isResizable;
}
return clonedLayoutItem;
}
/**
* Given two layout items, check if they collide.
*/
export function collides(l1, l2) {
if (l1.id === l2.id) {
return false;
} // same element
if (l1.x + l1.w <= l2.x) {
return false;
} // l1 is left of l2
if (l1.x >= l2.x + l2.w) {
return false;
} // l1 is right of l2
if (l1.y + l1.h <= l2.y) {
return false;
} // l1 is above l2
if (l1.y >= l2.y + l2.h) {
return false;
} // l1 is below l2
return true; // boxes overlap
}
/**
* Given a layout, compact it. This involves going down each y coordinate and removing gaps
* between items.
*
* @param {Array} layout Layout.
* @param {Boolean} verticalCompact Whether or not to compact the layout
* vertically.
* @return {Array} Compacted Layout.
*/
export function compact(layout, compactType, cols) {
// Statics go in the compareWith array right away so items flow around them.
const compareWith = getStatics(layout);
// We go through the items by row and column.
const sorted = sortLayoutItems(layout, compactType);
// Holding for new items.
const out = Array.from({ length: layout.length });
for (let i = 0, len = sorted.length; i < len; i++) {
let l = cloneLayoutItem(sorted[i]);
// Don't move static elements
if (!l.static) {
l = compactItem(compareWith, l, compactType, cols, sorted);
// Add to comparison array. We only collide with items before this one.
// Statics are already in this array.
compareWith.push(l);
}
// Add to output array to make sure they still come out in the right order.
out[layout.indexOf(sorted[i])] = l;
// Clear moved flag, if it exists.
l.moved = false;
}
return out;
}
const heightWidth = { x: 'w', y: 'h' };
/**
* Before moving item down, it will check if the movement will cause collisions and move those items down before.
*/
function resolveCompactionCollision(layout, item, moveToCoord, axis) {
const sizeProp = heightWidth[axis];
item[axis] += 1;
const itemIndex = layout.map(layoutItem => layoutItem.id).indexOf(item.id);
// Go through each item we collide with.
for (let i = itemIndex + 1; i < layout.length; i++) {
const otherItem = layout[i];
// Ignore static items
if (otherItem.static) {
continue;
}
// Optimization: we can break early if we know we're past this el
// We can do this b/c it's a sorted layout
if (otherItem.y > item.y + item.h) {
break;
}
if (collides(item, otherItem)) {
resolveCompactionCollision(layout, otherItem,
// @ts-ignore
moveToCoord + item[sizeProp], axis);
}
}
item[axis] = moveToCoord;
}
/**
* Compact an item in the layout.
*/
export function compactItem(compareWith, l, compactType, cols, fullLayout) {
const compactV = compactType === 'vertical';
const compactH = compactType === 'horizontal';
if (compactV) {
// Bottom 'y' possible is the bottom of the layout.
// This allows you to do nice stuff like specify {y: Infinity}
// This is here because the layout must be sorted in order to get the correct bottom `y`.
l.y = Math.min(bottom(compareWith), l.y);
// Move the element up as far as it can go without colliding.
while (l.y > 0 && !getFirstCollision(compareWith, l)) {
l.y--;
}
}
else if (compactH) {
l.y = Math.min(bottom(compareWith), l.y);
// Move the element left as far as it can go without colliding.
while (l.x > 0 && !getFirstCollision(compareWith, l)) {
l.x--;
}
}
// Move it down, and keep moving it down if it's colliding.
let collides;
while ((collides = getFirstCollision(compareWith, l))) {
if (compactH) {
resolveCompactionCollision(fullLayout, l, collides.x + collides.w, 'x');
}
else {
resolveCompactionCollision(fullLayout, l, collides.y + collides.h, 'y');
}
// Since we can't grow without bounds horizontally, if we've overflown, let's move it down and try again.
if (compactH && l.x + l.w > cols) {
l.x = cols - l.w;
l.y++;
}
}
return l;
}
/**
* Given a layout, make sure all elements fit within its bounds.
*
* @param {Array} layout Layout array.
* @param {Number} bounds Number of columns.
*/
export function correctBounds(layout, bounds) {
const collidesWith = getStatics(layout);
for (let i = 0, len = layout.length; i < len; i++) {
const l = layout[i];
// Overflows right
if (l.x + l.w > bounds.cols) {
l.x = bounds.cols - l.w;
}
// Overflows left
if (l.x < 0) {
l.x = 0;
l.w = bounds.cols;
}
if (l.static) {
// If this is static and collides with other statics, we must move it down.
// We have to do something nicer than just letting them overlap.
while (getFirstCollision(collidesWith, l)) {
l.y++;
}
}
else {
collidesWith.push(l);
}
}
return layout;
}
/**
* Get a layout item by ID. Used so we can override later on if necessary.
*
* @param {Array} layout Layout array.
* @param {String} id ID
* @return {LayoutItem} Item at ID.
*/
export function getLayoutItem(layout, id) {
for (let i = 0, len = layout.length; i < len; i++) {
if (layout[i].id === id) {
return layout[i];
}
}
return null;
}
/**
* Returns the first item this layout collides with.
* It doesn't appear to matter which order we approach this from, although
* perhaps that is the wrong thing to do.
*
* @param {Object} layoutItem Layout item.
* @return {Object|undefined} A colliding layout item, or undefined.
*/
export function getFirstCollision(layout, layoutItem) {
for (let i = 0, len = layout.length; i < len; i++) {
if (collides(layout[i], layoutItem)) {
return layout[i];
}
}
return null;
}
export function getAllCollisions(layout, layoutItem) {
return layout.filter(l => collides(l, layoutItem));
}
/**
* Get all static elements.
* @param {Array} layout Array of layout objects.
* @return {Array} Array of static layout items..
*/
export function getStatics(layout) {
return layout.filter(l => l.static);
}
/**
* Move an element. Responsible for doing cascading movements of other elements.
*
* @param {Array} layout Full layout to modify.
* @param {LayoutItem} l element to move.
* @param {Number} [x] X position in grid units.
* @param {Number} [y] Y position in grid units.
*/
export function moveElement(layout, l, x, y, isUserAction, preventCollision, compactType, cols) {
// If this is static and not explicitly enabled as draggable,
// no move is possible, so we can short-circuit this immediately.
if (l.static && l.isDraggable !== true) {
return layout;
}
// Short-circuit if nothing to do.
if (l.y === y && l.x === x) {
return layout;
}
log(`Moving element ${l.id} to [${String(x)},${String(y)}] from [${l.x},${l.y}]`);
const oldX = l.x;
const oldY = l.y;
// This is quite a bit faster than extending the object
if (typeof x === 'number') {
l.x = x;
}
if (typeof y === 'number') {
l.y = y;
}
l.moved = true;
// If this collides with anything, move it.
// When doing this comparison, we have to sort the items we compare with
// to ensure, in the case of multiple collisions, that we're getting the
// nearest collision.
let sorted = sortLayoutItems(layout, compactType);
const movingUp = compactType === 'vertical' && typeof y === 'number'
? oldY >= y
: compactType === 'horizontal' && typeof x === 'number'
? oldX >= x
: false;
if (movingUp) {
sorted = sorted.reverse();
}
const collisions = getAllCollisions(sorted, l);
// There was a collision; abort
if (preventCollision && collisions.length) {
log(`Collision prevented on ${l.id}, reverting.`);
l.x = oldX;
l.y = oldY;
l.moved = false;
return layout;
}
// Move each item that collides away from this element.
for (let i = 0, len = collisions.length; i < len; i++) {
const collision = collisions[i];
log(`Resolving collision between ${l.id} at [${l.x},${l.y}] and ${collision.id} at [${collision.x},${collision.y}]`);
// Short circuit so we can't infinite loop
if (collision.moved) {
continue;
}
// Don't move static items - we have to move *this* element away
layout = collision.static
? moveElementAwayFromCollision(layout, collision, l, isUserAction, compactType, cols)
: moveElementAwayFromCollision(layout, l, collision, isUserAction, compactType, cols);
}
return layout;
}
/**
* This is where the magic needs to happen - given a collision, move an element away from the collision.
* We attempt to move it up if there's room, otherwise it goes below.
*
* @param {Array} layout Full layout to modify.
* @param {LayoutItem} collidesWith Layout item we're colliding with.
* @param {LayoutItem} itemToMove Layout item we're moving.
*/
export function moveElementAwayFromCollision(layout, collidesWith, itemToMove, isUserAction, compactType, cols) {
const compactH = compactType === 'horizontal';
// Compact vertically if not set to horizontal
const compactV = compactType !== 'horizontal';
const preventCollision = collidesWith.static; // we're already colliding (not for static items)
// If there is enough space above the collision to put this element, move it there.
// We only do this on the main collision as this can get funky in cascades and cause
// unwanted swapping behavior.
if (isUserAction) {
// Reset isUserAction flag because we're not in the main collision anymore.
isUserAction = false;
// Make a mock item so we don't modify the item here, only modify in moveElement.
const fakeItem = {
x: compactH ? Math.max(collidesWith.x - itemToMove.w, 0) : itemToMove.x,
y: compactV ? Math.max(collidesWith.y - itemToMove.h, 0) : itemToMove.y,
w: itemToMove.w,
h: itemToMove.h,
id: '-1',
};
// No collision? If so, we can go up there; otherwise, we'll end up moving down as normal
if (!getFirstCollision(layout, fakeItem)) {
log(`Doing reverse collision on ${itemToMove.id} up to [${fakeItem.x},${fakeItem.y}].`);
return moveElement(layout, itemToMove, compactH ? fakeItem.x : undefined, compactV ? fakeItem.y : undefined, isUserAction, preventCollision, compactType, cols);
}
}
return moveElement(layout, itemToMove, compactH ? itemToMove.x + 1 : undefined, compactV ? itemToMove.y + 1 : undefined, isUserAction, preventCollision, compactType, cols);
}
/**
* Helper to convert a number to a percentage string.
*
* @param {Number} num Any number
* @return {String} That number as a percentage.
*/
export function percent(num) {
return num * 100 + '%';
}
export function setTransform({ top, left, width, height }) {
// Replace unit-less items with px
const translate = `translate(${left}px,${top}px)`;
return {
transform: translate,
WebkitTransform: translate,
MozTransform: translate,
msTransform: translate,
OTransform: translate,
width: `${width}px`,
height: `${height}px`,
position: 'absolute',
};
}
export function setTopLeft({ top, left, width, height }) {
return {
top: `${top}px`,
left: `${left}px`,
width: `${width}px`,
height: `${height}px`,
position: 'absolute',
};
}
/**
* Get layout items sorted from top left to right and down.
*
* @return {Array} Array of layout objects.
* @return {Array} Layout, sorted static items first.
*/
export function sortLayoutItems(layout, compactType) {
if (compactType === 'horizontal') {
return sortLayoutItemsByColRow(layout);
}
return sortLayoutItemsByRowCol(layout);
}
export function sortLayoutItemsByRowCol(layout) {
return [].concat(layout).sort(function (a, b) {
if (a.y > b.y || (a.y === b.y && a.x > b.x)) {
return 1;
}
if (a.y === b.y && a.x === b.x) {
// Without this, we can get different sort results in IE vs. Chrome/FF
return 0;
}
return -1;
});
}
export function sortLayoutItemsByColRow(layout) {
return [].concat(layout).sort(function (a, b) {
if (a.x > b.x || (a.x === b.x && a.y > b.y)) {
return 1;
}
return -1;
});
}
/**
* Validate a layout. Throws errors.
*
* @param {Array} layout Array of layout items.
* @param {String} [contextName] Context name for errors.
* @throw {Error} Validation error.
*/
export function validateLayout(layout, contextName = 'Layout') {
const subProps = ['x', 'y', 'w', 'h'];
if (!Array.isArray(layout)) {
throw new TypeError(contextName + ' must be an array!');
}
for (let i = 0, len = layout.length; i < len; i++) {
const item = layout[i];
for (const subProp of subProps) {
// @ts-ignore
if (typeof item[subProp] !== 'number') {
throw new TypeError('ReactGridLayout: ' +
contextName +
'[' +
i +
'].' +
subProp +
' must be a number!');
}
}
if (item.id && typeof item.id !== 'string') {
throw new Error('ReactGridLayout: ' + contextName + '[' + i + '].i must be a string!');
}
if (item.static !== undefined && typeof item.static !== 'boolean') {
throw new Error('ReactGridLayout: ' +
contextName +
'[' +
i +
'].static must be a boolean!');
}
}
}
// Flow can't really figure this out, so we just use Object
export function autoBindHandlers(el, fns) {
// @ts-ignore
fns.forEach(key => (el[key] = el[key].bind(el)));
}
function log(...args) {
if (!DEBUG) {
return;
}
// eslint-disable-next-line no-console
console.log(...args);
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVhY3QtZ3JpZC1sYXlvdXQudXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9saWJzL2NvbW1vbi9zcmMvZ3JpZC1sYXlvdXQvdXRpbHMvcmVhY3QtZ3JpZC1sYXlvdXQudXRpbHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsZ0RBQWdEO0FBQ2hELGdEQUFnRDtBQTBGaEQsTUFBTSxLQUFLLEdBQUcsS0FBSyxDQUFDO0FBRXBCOzs7OztHQUtHO0FBQ0gsTUFBTSxVQUFVLE1BQU0sQ0FBQyxNQUFjO0lBQ25DLElBQUksR0FBRyxHQUFHLENBQUMsQ0FBQztJQUNaLElBQUksT0FBTyxDQUFDO0lBQ1osS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsR0FBRyxHQUFHLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQyxHQUFHLEdBQUcsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO1FBQ2xELE9BQU8sR0FBRyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDcEMsSUFBSSxPQUFPLEdBQUcsR0FBRyxFQUFFLENBQUM7WUFDbEIsR0FBRyxHQUFHLE9BQU8sQ0FBQztRQUNoQixDQUFDO0lBQ0gsQ0FBQztJQUNELE9BQU8sR0FBRyxDQUFDO0FBQ2IsQ0FBQztBQUVELE1BQU0sVUFBVSxXQUFXLENBQUMsTUFBYztJQUN4QyxNQUFNLFNBQVMsR0FBRyxLQUFLLENBQUMsSUFBSSxDQUFDLEVBQUUsTUFBTSxFQUFFLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBVyxDQUFDO0lBQ2xFLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLEdBQUcsR0FBRyxNQUFNLENBQUMsTUFBTSxFQUFFLENBQUMsR0FBRyxHQUFHLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQztRQUNsRCxTQUFTLENBQUMsQ0FBQyxDQUFDLEdBQUcsZUFBZSxDQUFD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R0FBRyxHQUFHLEdBQUcsQ0FBQyxHQUFHLHVCQUF1QixDQUN0RSxDQUFDO1FBQ0osQ0FBQztRQUNELElBQUksSUFBSSxDQUFDLE1BQU0sS0FBSyxTQUFTLElBQUksT0FBTyxJQUFJLENBQUMsTUFBTSxLQUFLLFNBQVMsRUFBRSxDQUFDO1lBQ2xFLE1BQU0sSUFBSSxLQUFLLENBQ2IsbUJBQW1CO2dCQUNqQixXQUFXO2dCQUNYLEdBQUc7Z0JBQ0gsQ0FBQztnQkFDRCw2QkFBNkIsQ0FDaEMsQ0FBQztRQUNKLENBQUM7SUFDSCxDQUFDO0FBQ0gsQ0FBQztBQUVELDJEQUEyRDtBQUMzRCxNQUFNLFVBQVUsZ0JBQWdCLENBQUMsRUFBVSxFQUFFLEdBQWE7SUFDeEQsYUFBYTtJQUNiLEdBQUcsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUNuRCxDQUFDO0FBRUQsU0FBUyxHQUFHLENBQUMsR0FBRyxJQUFlO0lBQzdCLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUNYLE9BQU87SUFDVCxDQUFDO0lBQ0Qsc0NBQXNDO0lBQ3RDLE9BQU8sQ0FBQyxHQUFHLENBQUMsR0FBRyxJQUFJLENBQUMsQ0FBQztBQUN2QixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyogZXNsaW50LWRpc2FibGUgc29uYXIvbm8tcmVkdW5kYW50LW9wdGlvbmFsICovXG4vKiBlc2xpbnQtZGlzYWJsZSBzb25hcmpzL25vLWR1cGxpY2F0ZS1zdHJpbmcgKi9cblxuLyogZXNsaW50LWRpc2FibGUgc29uYXJqcy9jb2duaXRpdmUtY29tcGxleGl0eSAqL1xuLyogZXNsaW50LWRpc2FibGUgc29uYXJqcy9wcmVmZXItc2luZ2xlLWJvb2xlYW4tcmV0dXJuICovXG4vKiBlc2xpbnQtZGlzYWJsZSBAdHlwZXNjcmlwdC1lc2xpbnQvYmFuLXR5cGVzICovXG4vKiBlc2xpbnQtZGlzYWJsZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW5zYWZlLWNhbGwgKi9cblxuLy8gVGhlc2UgdXRpbHMgZm9yayBmcm9tIDogaHR0cHM6Ly9naXRodWIuY29tL1NUUk1ML3JlYWN0LWdyaWQtbGF5b3V0LlxuLy8gTk9URTogLS0tLS0tLT4gRG8gbm90IG1vZGlmeSB0aGlzIGZpbGUgZm9yIGVhc3kgbWFpbnRlbmFuY2UgISEhIDwtLS0tLS0tXG4vLyBXZSBvbmx5IGFkZCBlc2xpbnQtZGlzYWJsZS90cy1pZ25vcmUgdG8gaWdub3JlIHVubmVjZXNzYXJ5IGNoYW5nZXNcblxuZXhwb3J0IGludGVyZmFjZSBMYXlvdXRJdGVtIHtcbiAgdzogbnVtYmVyO1xuICBoOiBudW1iZXI7XG4gIHg6IG51bWJlcjtcbiAgeTogbnVtYmVyO1xuICBpZDogc3RyaW5nO1xuICBtaW5XPzogbnVtYmVyO1xuICBtaW5IPzogbnVtYmVyO1xuICBtYXhXPzogbnVtYmVyO1xuICBtYXhIPzogbnVtYmVyO1xuICBtb3ZlZD86IGJvb2xlYW47XG4gIHN0YXRpYz86IGJvb2xlYW47XG4gIGlzRHJhZ2dhYmxlPzogYm9vbGVhbiB8IG51bGwgfCB1bmRlZmluZWQ7XG4gIGlzUmVzaXphYmxlPzogYm9vbGVhbiB8IG51bGwgfCB1bmRlZmluZWQ7XG59XG5leHBvcnQgdHlwZSBMYXlvdXQgPSBMYXlvdXRJdGVtW107XG5leHBvcnQgaW50ZXJmYWNlIFBvc2l0aW9uIHtcbiAgbGVmdDogbnVtYmVyO1xuICB0b3A6IG51bWJlcjtcbiAgd2lkdGg6IG51bWJlcjtcbiAgaGVpZ2h0OiBudW1iZXI7XG59XG5leHBvcnQgaW50ZXJmYWNlIFJlYWN0RHJhZ2dhYmxlQ2FsbGJhY2tEYXRhIHtcbiAgbm9kZTogSFRNTEVsZW1lbnQ7XG4gIHg/OiBudW1iZXI7XG4gIHk/OiBudW1iZXI7XG4gIGRlbHRhWDogbnVtYmVyO1xuICBkZWx0YVk6IG51bWJlcjtcbiAgbGFzdFg/OiBudW1iZXI7XG4gIGxhc3RZPzogbnVtYmVyO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFBhcnRpYWxQb3NpdGlvbiB7XG4gIGxlZnQ6IG51bWJlcjtcbiAgdG9wOiBudW1iZXI7XG59XG5leHBvcnQgaW50ZXJmYWNlIERyb3BwaW5nUG9zaXRpb24ge1xuICB4OiBudW1iZXI7XG4gIHk6IG51bWJlcjtcbiAgZTogRXZlbnQ7XG59XG5leHBvcnQgaW50ZXJmYWNlIFNpemUge1xuICB3aWR0aDogbnVtYmVyO1xuICBoZWlnaHQ6IG51bWJlcjtcbn1cbmV4cG9ydCBpbnRlcmZhY2UgR3JpZERyYWdFdmVudCB7XG4gIGU6IEV2ZW50O1xuICBub2RlOiBIVE1MRWxlbWVudDtcbiAgbmV3UG9zaXRpb246IFBhcnRpYWxQb3NpdGlvbjtcbn1cbmV4cG9ydCBpbnRlcmZhY2UgR3JpZFJlc2l6ZUV2ZW50IHtcbiAgZTogRXZlbnQ7XG4gIG5vZGU6IEhUTUxFbGVtZW50O1xuICBzaXplOiBTaXplO1xufVxuZXhwb3J0IHR5cGUgRHJhZ092ZXJFdmVudCA9IE1vdXNlRXZlbnQgJiB7XG4gIG5hdGl2ZUV2ZW50OiB7XG4gICAgbGF5ZXJYOiBudW1iZXI7XG4gICAgbGF5ZXJZOiBudW1iZXI7XG4gICAgdGFyZ2V0OiB7XG4gICAgICBjbGFzc05hbWU6IFN0cmluZztcbiAgICB9O1xuICB9O1xufTtcblxuLy8gdHlwZSBSRWwgPSBSZWFjdEVsZW1lbnQ8YW55Pjtcbi8vIGV4cG9ydCB0eXBlIFJlYWN0Q2hpbGRyZW4gPSBSZWFjdENoaWxkcmVuQXJyYXk8UkVsPjtcblxuLy8gQWxsIGNhbGxiYWNrcyBhcmUgb2YgdGhlIHNpZ25hdHVyZSAobGF5b3V0LCBvbGRJdGVtLCBuZXdJdGVtLCBwbGFjZWhvbGRlciwgZSkuXG5leHBvcnQgdHlwZSBFdmVudENhbGxiYWNrID0gKFxuICBhcmcwOiBMYXlvdXQsXG4gIG9sZEl0ZW06IExheW91dEl0ZW0gfCBudWxsIHwgdW5kZWZpbmVkLFxuICBuZXdJdGVtOiBMYXlvdXRJdGVtIHwgbnVsbCB8IHVuZGVmaW5lZCxcbiAgcGxhY2Vob2xkZXI6IExheW91dEl0ZW0gfCBudWxsIHwgdW5kZWZpbmVkLFxuICBhcmc0OiBFdmVudCxcbiAgYXJnNTogSFRNTEVsZW1lbnQgfCBudWxsIHwgdW5kZWZpbmVkLFxuKSA9PiB2b2lkO1xuZXhwb3J0IHR5cGUgQ29tcGFjdFR5cGUgPSAoJ2hvcml6b250YWwnIHwgJ3ZlcnRpY2FsJykgfCBudWxsIHwgdW5kZWZpbmVkO1xuXG5jb25zdCBERUJVRyA9IGZhbHNlO1xuXG4vKipcbiAqIFJldHVybiB0aGUgYm90dG9tIGNvb3JkaW5hdGUgb2YgdGhlIGxheW91dC5cbiAqXG4gKiBAcGFyYW0gIHtBcnJheX0gbGF5b3V0IExheW91dCBhcnJheS5cbiAqIEByZXR1cm4ge051bWJlcn0gICAgICAgQm90dG9tIGNvb3JkaW5hdGUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBib3R0b20obGF5b3V0OiBMYXlvdXQpOiBudW1iZXIge1xuICBsZXQgbWF4ID0gMDtcbiAgbGV0IGJvdHRvbVk7XG4gIGZvciAobGV0IGkgPSAwLCBsZW4gPSBsYXlvdXQubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcbiAgICBib3R0b21ZID0gbGF5b3V0W2ldLnkgKyBsYXlvdXRbaV0uaDtcbiAgICBpZiAoYm90dG9tWSA+IG1heCkge1xuICAgICAgbWF4ID0gYm90dG9tWTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIG1heDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNsb25lTGF5b3V0KGxheW91dDogTGF5b3V0KTogTGF5b3V0IHtcbiAgY29uc3QgbmV3TGF5b3V0ID0gQXJyYXkuZnJvbSh7IGxlbmd0aDogbGF5b3V0Lmxlbmd0aCB9KSBhcyBMYXlvdXQ7XG4gIGZvciAobGV0IGkgPSAwLCBsZW4gPSBsYXlvdXQubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcbiAgICBuZXdMYXlvdXRbaV0gPSBjbG9uZUxheW91dEl0ZW0obGF5b3V0W2ldKTtcbiAgfVxuICByZXR1cm4gbmV3TGF5b3V0O1xufVxuXG4vLyBGYXN0IHBhdGggdG8gY2xvbmluZywgc2luY2UgdGhpcyBpcyBtb25vbW9ycGhpY1xuLyoqIE5PVEU6IFRoaXMgY29kZSBoYXMgYmVlbiBtb2RpZmllZCBmcm9tIHRoZSBvcmlnaW5hbCBzb3VyY2UgKi9cbmV4cG9ydCBmdW5jdGlvbiBjbG9uZUxheW91dEl0ZW0obGF5b3V0SXRlbTogTGF5b3V0SXRlbSk6IExheW91dEl0ZW0ge1xuICBjb25zdCBjbG9uZWRMYXlvdXRJdGVtOiBMYXlvdXRJdGVtID0ge1xuICAgIHc6IGxheW91dEl0ZW0udyxcbiAgICBoOiBsYXlvdXRJdGVtLmgsXG4gICAgeDogbGF5b3V0SXRlbS54LFxuICAgIHk6IGxheW91dEl0ZW0ueSxcbiAgICBpZDogbGF5b3V0SXRlbS5pZCxcbiAgICBtb3ZlZDogISFsYXlvdXRJdGVtLm1vdmVkLFxuICAgIHN0YXRpYzogISFsYXlvdXRJdGVtLnN0YXRpYyxcbiAgfTtcblxuICBpZiAobGF5b3V0SXRlbS5taW5XICE9PSB1bmRlZmluZWQpIHtcbiAgICBjbG9uZWRMYXlvdXRJdGVtLm1pblcgPSBsYXlvdXRJdGVtLm1pblc7XG4gIH1cbiAgaWYgKGxheW91dEl0ZW0ubWF4VyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgY2xvbmVkTGF5b3V0SXRlbS5tYXhXID0gbGF5b3V0SXRlbS5tYXhXO1xuICB9XG4gIGlmIChsYXlvdXRJdGVtLm1pbkggIT09IHVuZGVmaW5lZCkge1xuICAgIGNsb25lZExheW91dEl0ZW0ubWluSCA9IGxheW91dEl0ZW0ubWluSDtcbiAgfVxuICBpZiAobGF5b3V0SXRlbS5tYXhIICE9PSB1bmRlZmluZWQpIHtcbiAgICBjbG9uZWRMYXlvdXRJdGVtLm1heEggPSBsYXlvdXRJdGVtLm1heEg7XG4gIH1cbiAgLy8gVGhlc2UgY2FuIGJlIG51bGxcbiAgaWYgKGxheW91dEl0ZW0uaXNEcmFnZ2FibGUgIT09IHVuZGVmaW5lZCkge1xuICAgIGNsb25lZExheW91dEl0ZW0uaXNEcmFnZ2FibGUgPSBsYXlvdXRJdGVtLmlzRHJhZ2dhYmxlO1xuICB9XG4gIGlmIChsYXlvdXRJdGVtLmlzUmVzaXphYmxlICE9PSB1bmRlZmluZWQpIHtcbiAgICBjbG9uZWRMYXlvdXRJdGVtLmlzUmVzaXphYmxlID0gbGF5b3V0SXRlbS5pc1Jlc2l6YWJsZTtcbiAgfVxuXG4gIHJldHVybiBjbG9uZWRMYXlvdXRJdGVtO1xufVxuXG4vKipcbiAqIEdpdmVuIHR3byBsYXlvdXQgaXRlbXMsIGNoZWNrIGlmIHRoZXkgY29sbGlkZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNvbGxpZGVzKGwxOiBMYXlvdXRJdGVtLCBsMjogTGF5b3V0SXRlbSk6IGJvb2xlYW4ge1xuICBpZiAobDEuaWQgPT09IGwyLmlkKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9IC8vIHNhbWUgZWxlbWVudFxuICBpZiAobDEueCArIGwxLncgPD0gbDIueCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfSAvLyBsMSBpcyBsZWZ0IG9mIGwyXG4gIGlmIChsMS54ID49IGwyLnggKyBsMi53KSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9IC8vIGwxIGlzIHJpZ2h0IG9mIGwyXG4gIGlmIChsMS55ICsgbDEuaCA8PSBsMi55KSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9IC8vIGwxIGlzIGFib3ZlIGwyXG4gIGlmIChsMS55ID49IGwyLnkgKyBsMi5oKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9IC8vIGwxIGlzIGJlbG93IGwyXG4gIHJldHVybiB0cnVlOyAvLyBib3hlcyBvdmVybGFwXG59XG5cbi8qKlxuICogR2l2ZW4gYSBsYXlvdXQsIGNvbXBhY3QgaXQuIFRoaXMgaW52b2x2ZXMgZ29pbmcgZG93biBlYWNoIHkgY29vcmRpbmF0ZSBhbmQgcmVtb3ZpbmcgZ2Fwc1xuICogYmV0d2VlbiBpdGVtcy5cbiAqXG4gKiBAcGFyYW0gIHtBcnJheX0gbGF5b3V0IExheW91dC5cbiAqIEBwYXJhbSAge0Jvb2xlYW59IHZlcnRpY2FsQ29tcGFjdCBXaGV0aGVyIG9yIG5vdCB0byBjb21wYWN0IHRoZSBsYXlvdXRcbiAqICAgdmVydGljYWxseS5cbiAqIEByZXR1cm4ge0FycmF5fSAgICAgICBDb21wYWN0ZWQgTGF5b3V0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gY29tcGFjdChcbiAgbGF5b3V0OiBMYXlvdXQsXG4gIGNvbXBhY3RUeXBlOiBDb21wYWN0VHlwZSxcbiAgY29sczogbnVtYmVyLFxuKTogTGF5b3V0IHtcbiAgLy8gU3RhdGljcyBnbyBpbiB0aGUgY29tcGFyZVdpdGggYXJyYXkgcmlnaHQgYXdheSBzbyBpdGVtcyBmbG93IGFyb3VuZCB0aGVtLlxuICBjb25zdCBjb21wYXJlV2l0aCA9IGdldFN0YXRpY3MobGF5b3V0KTtcbiAgLy8gV2UgZ28gdGhyb3VnaCB0aGUgaXRlbXMgYnkgcm93IGFuZCBjb2x1bW4uXG4gIGNvbnN0IHNvcnRlZCA9IHNvcnRMYXlvdXRJdGVtcyhsYXlvdXQsIGNvbXBhY3RUeXBlKTtcbiAgLy8gSG9sZGluZyBmb3IgbmV3IGl0ZW1zLlxuICBjb25zdCBvdXQgPSBBcnJheS5mcm9tKHsgbGVuZ3RoOiBsYXlvdXQubGVuZ3RoIH0pO1xuXG4gIGZvciAobGV0IGkgPSAwLCBsZW4gPSBzb3J0ZWQubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcbiAgICBsZXQgbCA9IGNsb25lTGF5b3V0SXRlbShzb3J0ZWRbaV0pO1xuXG4gICAgLy8gRG9uJ3QgbW92ZSBzdGF0aWMgZWxlbWVudHNcbiAgICBpZiAoIWwuc3RhdGljKSB7XG4gICAgICBsID0gY29tcGFjdEl0ZW0oY29tcGFyZVdpdGgsIGwsIGNvbXBhY3RUeXBlLCBjb2xzLCBzb3J0ZWQpO1xuXG4gICAgICAvLyBBZGQgdG8gY29tcGFyaXNvbiBhcnJheS4gV2Ugb25seSBjb2xsaWRlIHdpdGggaXRlbXMgYmVmb3JlIHRoaXMgb25lLlxuICAgICAgLy8gU3RhdGljcyBhcmUgYWxyZWFkeSBpbiB0aGlzIGFycmF5LlxuICAgICAgY29tcGFyZVdpdGgucHVzaChsKTtcbiAgICB9XG5cbiAgICAvLyBBZGQgdG8gb3V0cHV0IGFycmF5IHRvIG1ha2Ugc3VyZSB0aGV5IHN0aWxsIGNvbWUgb3V0IGluIHRoZSByaWdodCBvcmRlci5cbiAgICBvdXRbbGF5b3V0LmluZGV4T2Yoc29ydGVkW2ldKV0gPSBsO1xuXG4gICAgLy8gQ2xlYXIgbW92ZWQgZmxhZywgaWYgaXQgZXhpc3RzLlxuICAgIGwubW92ZWQgPSBmYWxzZTtcbiAgfVxuXG4gIHJldHVybiBvdXQgYXMgTGF5b3V0O1xufVxuXG5jb25zdCBoZWlnaHRXaWR0aCA9IHsgeDogJ3cnLCB5OiAnaCcgfTtcblxuLyoqXG4gKiBCZWZvcmUgbW92aW5nIGl0ZW0gZG93biwgaXQgd2lsbCBjaGVjayBpZiB0aGUgbW92ZW1lbnQgd2lsbCBjYXVzZSBjb2xsaXNpb25zIGFuZCBtb3ZlIHRob3NlIGl0ZW1zIGRvd24gYmVmb3JlLlxuICovXG5mdW5jdGlvbiByZXNvbHZlQ29tcGFjdGlvbkNvbGxpc2lvbihcbiAgbGF5b3V0OiBMYXlvdXQsXG4gIGl0ZW06IExheW91dEl0ZW0sXG4gIG1vdmVUb0Nvb3JkOiBudW1iZXIsXG4gIGF4aXM6ICd4JyB8ICd5Jyxcbikge1xuICBjb25zdCBzaXplUHJvcCA9IGhlaWdodFdpZHRoW2F4aXNdO1xuICBpdGVtW2F4aXNdICs9IDE7XG4gIGNvbnN0IGl0ZW1JbmRleCA9IGxheW91dC5tYXAobGF5b3V0SXRlbSA9PiBsYXlvdXRJdGVtLmlkKS5pbmRleE9mKGl0ZW0uaWQpO1xuXG4gIC8vIEdvIHRocm91Z2ggZWFjaCBpdGVtIHdlIGNvbGxpZGUgd2l0aC5cbiAgZm9yIChsZXQgaSA9IGl0ZW1JbmRleCArIDE7IGkgPCBsYXlvdXQubGVuZ3RoOyBpKyspIHtcbiAgICBjb25zdCBvdGhlckl0ZW0gPSBsYXlvdXRbaV07XG4gICAgLy8gSWdub3JlIHN0YXRpYyBpdGVtc1xuICAgIGlmIChvdGhlckl0ZW0uc3RhdGljKSB7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG5cbiAgICAvLyBPcHRpbWl6YXRpb246IHdlIGNhbiBicmVhayBlYXJseSBpZiB3ZSBrbm93IHdlJ3JlIHBhc3QgdGhpcyBlbFxuICAgIC8vIFdlIGNhbiBkbyB0aGlzIGIvYyBpdCdzIGEgc29ydGVkIGxheW91dFxuICAgIGlmIChvdGhlckl0ZW0ueSA+IGl0ZW0ueSArIGl0ZW0uaCkge1xuICAgICAgYnJlYWs7XG4gICAgfVxuXG4gICAgaWYgKGNvbGxpZGVzKGl0ZW0sIG90aGVySXRlbSkpIHtcbiAgICAgIHJlc29sdmVDb21wYWN0aW9uQ29sbGlzaW9uKFxuICAgICAgICBsYXlvdXQsXG4gICAgICAgIG90aGVySXRlbSxcbiAgICAgICAgLy8gQHRzLWlnbm9yZVxuICAgICAgICBtb3ZlVG9Db29yZCArIGl0ZW1bc2l6ZVByb3BdLFxuICAgICAgICBheGlzLFxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICBpdGVtW2F4aXNdID0gbW92ZVRvQ29vcmQ7XG59XG5cbi8qKlxuICogQ29tcGFjdCBhbiBpdGVtIGluIHRoZSBsYXlvdXQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjb21wYWN0SXRlbShcbiAgY29tcGFyZVdpdGg6IExheW91dCxcbiAgbDogTGF5b3V0SXRlbSxcbiAgY29tcGFjdFR5cGU6IENvbXBhY3RUeXBlLFxuICBjb2xzOiBudW1iZXIsXG4gIGZ1bGxMYXlvdXQ6IExheW91dCxcbik6IExheW91dEl0ZW0ge1xuICBjb25zdCBjb21wYWN0ViA9IGNvbXBhY3RUeXBlID09PSAndmVydGljYWwnO1xuICBjb25zdCBjb21wYWN0SCA9IGNvbXBhY3RUeXBlID09PSAnaG9yaXpvbnRhbCc7XG4gIGlmIChjb21wYWN0Vikge1xuICAgIC8vIEJvdHRvbSAneScgcG9zc2libGUgaXMgdGhlIGJvdHRvbSBvZiB0aGUgbGF5b3V0LlxuICAgIC8vIFRoaXMgYWxsb3dzIHlvdSB0byBkbyBuaWNlIHN0dWZmIGxpa2Ugc3BlY2lmeSB7eTogSW5maW5pdHl9XG4gICAgLy8gVGhpcyBpcyBoZXJlIGJlY2F1c2UgdGhlIGxheW91dCBtdXN0IGJlIHNvcnRlZCBpbiBvcmRlciB0byBnZXQgdGhlIGNvcnJlY3QgYm90dG9tIGB5YC5cbiAgICBsLnkgPSBNYXRoLm1pbihib3R0b20oY29tcGFyZVdpdGgpLCBsLnkpO1xuICAgIC8vIE1vdmUgdGhlIGVsZW1lbnQgdXAgYXMgZmFyIGFzIGl0IGNhbiBnbyB3aXRob3V0IGNvbGxpZGluZy5cbiAgICB3aGlsZSAobC55ID4gMCAmJiAhZ2V0Rmlyc3RDb2xsaXNpb24oY29tcGFyZVdpdGgsIGwpKSB7XG4gICAgICBsLnktLTtcbiAgICB9XG4gIH0gZWxzZSBpZiAoY29tcGFjdEgpIHtcbiAgICBsLnkgPSBNYXRoLm1pbihib3R0b20oY29tcGFyZVdpdGgpLCBsLnkpO1xuICAgIC8vIE1vdmUgdGhlIGVsZW1lbnQgbGVmdCBhcyBmYXIgYXMgaXQgY2FuIGdvIHdpdGhvdXQgY29sbGlkaW5nLlxuICAgIHdoaWxlIChsLnggPiAwICYmICFnZXRGaXJzdENvbGxpc2lvbihjb21wYXJlV2l0aCwgbCkpIHtcbiAgICAgIGwueC0tO1xuICAgIH1cbiAgfVxuXG4gIC8vIE1vdmUgaXQgZG93biwgYW5kIGtlZXAgbW92aW5nIGl0IGRvd24gaWYgaXQncyBjb2xsaWRpbmcuXG4gIGxldCBjb2xsaWRlcztcbiAgd2hpbGUgKChjb2xsaWRlcyA9IGdldEZpcnN0Q29sbGlzaW9uKGNvbXBhcmVXaXRoLCBsKSkpIHtcbiAgICBpZiAoY29tcGFjdEgpIHtcbiAgICAgIHJlc29sdmVDb21wYWN0aW9uQ29sbGlzaW9uKGZ1bGxMYXlvdXQsIGwsIGNvbGxpZGVzLnggKyBjb2xsaWRlcy53LCAneCcpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXNvbHZlQ29tcGFjdGlvbkNvbGxpc2lvbihmdWxsTGF5b3V0LCBsLCBjb2xsaWRlcy55ICsgY29sbGlkZXMuaCwgJ3knKTtcbiAgICB9XG4gICAgLy8gU2luY2Ugd2UgY2FuJ3QgZ3JvdyB3aXRob3V0IGJvdW5kcyBob3Jpem9udGFsbHksIGlmIHdlJ3ZlIG92ZXJmbG93biwgbGV0J3MgbW92ZSBpdCBkb3duIGFuZCB0cnkgYWdhaW4uXG4gICAgaWYgKGNvbXBhY3RIICYmIGwueCArIGwudyA+IGNvbHMpIHtcbiAgICAgIGwueCA9IGNvbHMgLSBsLnc7XG4gICAgICBsLnkrKztcbiAgICB9XG4gIH1cbiAgcmV0dXJuIGw7XG59XG5cbi8qKlxuICogR2l2ZW4gYSBsYXlvdXQsIG1ha2Ugc3VyZSBhbGwgZWxlbWVudHMgZml0IHdpdGhpbiBpdHMgYm91bmRzLlxuICpcbiAqIEBwYXJhbSAge0FycmF5fSBsYXlvdXQgTGF5b3V0IGFycmF5LlxuICogQHBhcmFtICB7TnVtYmVyfSBib3VuZHMgTnVtYmVyIG9mIGNvbHVtbnMuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjb3JyZWN0Qm91bmRzKFxuICBsYXlvdXQ6IExheW91dCxcbiAgYm91bmRzOiB7IGNvbHM6IG51bWJlciB9LFxuKTogTGF5b3V0IHtcbiAgY29uc3QgY29sbGlkZXNXaXRoID0gZ2V0U3RhdGljcyhsYXlvdXQpO1xuICBmb3IgKGxldCBpID0gMCwgbGVuID0gbGF5b3V0Lmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgY29uc3QgbCA9IGxheW91dFtpXTtcbiAgICAvLyBPdmVyZmxvd3MgcmlnaHRcbiAgICBpZiAobC54ICsgbC53ID4gYm91bmRzLmNvbHMpIHtcbiAgICAgIGwueCA9IGJvdW5kcy5jb2xzIC0gbC53O1xuICAgIH1cbiAgICAvLyBPdmVyZmxvd3MgbGVmdFxuICAgIGlmIChsLnggPCAwKSB7XG4gICAgICBsLnggPSAwO1xuICAgICAgbC53ID0gYm91bmRzLmNvbHM7XG4gICAgfVxuICAgIGlmIChsLnN0YXRpYykge1xuICAgICAgLy8gSWYgdGhpcyBpcyBzdGF0aWMgYW5kIGNvbGxpZGVzIHdpdGggb3RoZXIgc3RhdGljcywgd2UgbXVzdCBtb3ZlIGl0IGRvd24uXG4gICAgICAvLyBXZSBoYXZlIHRvIGRvIHNvbWV0aGluZyBuaWNlciB0aGFuIGp1c3QgbGV0dGluZyB0aGVtIG92ZXJsYXAuXG4gICAgICB3aGlsZSAoZ2V0Rmlyc3RDb2xsaXNpb24oY29sbGlkZXNXaXRoLCBsKSkge1xuICAgICAgICBsLnkrKztcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgY29sbGlkZXNXaXRoLnB1c2gobCk7XG4gICAgfVxuICB9XG4gIHJldHVybiBsYXlvdXQ7XG59XG5cbi8qKlxuICogR2V0IGEgbGF5b3V0IGl0ZW0gYnkgSUQuIFVzZWQgc28gd2UgY2FuIG92ZXJyaWRlIGxhdGVyIG9uIGlmIG5lY2Vzc2FyeS5cbiAqXG4gKiBAcGFyYW0gIHtBcnJheX0gIGxheW91dCBMYXlvdXQgYXJyYXkuXG4gKiBAcGFyYW0gIHtTdHJpbmd9IGlkICAgICBJRFxuICogQHJldHVybiB7TGF5b3V0SXRlbX0gICAgSXRlbSBhdCBJRC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldExheW91dEl0ZW0oXG4gIGxheW91dDogTGF5b3V0LFxuICBpZDogc3RyaW5nLFxuKTogTGF5b3V0SXRlbSB8IG51bGwgfCB1bmRlZmluZWQge1xuICBmb3IgKGxldCBpID0gMCwgbGVuID0gbGF5b3V0Lmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgaWYgKGxheW91dFtpXS5pZCA9PT0gaWQpIHtcbiAgICAgIHJldHVybiBsYXlvdXRbaV07XG4gICAgfVxuICB9XG4gIHJldHVybiBudWxsO1xufVxuXG4vKipcbiAqIFJldHVybnMgdGhlIGZpcnN0IGl0ZW0gdGhpcyBsYXlvdXQgY29sbGlkZXMgd2l0aC5cbiAqIEl0IGRvZXNuJ3QgYXBwZWFyIHRvIG1hdHRlciB3aGljaCBvcmRlciB3ZSBhcHByb2FjaCB0aGlzIGZyb20sIGFsdGhvdWdoXG4gKiBwZXJoYXBzIHRoYXQgaXMgdGhlIHdyb25nIHRoaW5nIHRvIGRvLlxuICpcbiAqIEBwYXJhbSAge09iamVjdH0gbGF5b3V0SXRlbSBMYXlvdXQgaXRlbS5cbiAqIEByZXR1cm4ge09iamVjdHx1bmRlZmluZWR9ICBBIGNvbGxpZGluZyBsYXlvdXQgaXRlbSwgb3IgdW5kZWZpbmVkLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0Rmlyc3RDb2xsaXNpb24oXG4gIGxheW91dDogTGF5b3V0LFxuICBsYXlvdXRJdGVtOiBMYXlvdXRJdGVtLFxuKTogTGF5b3V0SXRlbSB8IG51bGwgfCB1bmRlZmluZWQge1xuICBmb3IgKGxldCBpID0gMCwgbGVuID0gbGF5b3V0Lmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgaWYgKGNvbGxpZGVzKGxheW91dFtpXSwgbGF5b3V0SXRlbSkpIHtcbiAgICAgIHJldHVybiBsYXlvdXRbaV07XG4gICAgfVxuICB9XG4gIHJldHVybiBudWxsO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0QWxsQ29sbGlzaW9ucyhcbiAgbGF5b3V0OiBMYXlvdXQsXG4gIGxheW91dEl0ZW06IExheW91dEl0ZW0sXG4pOiBMYXlvdXRJdGVtW10ge1xuICByZXR1cm4gbGF5b3V0LmZpbHRlcihsID0+IGNvbGxpZGVzKGwsIGxheW91dEl0ZW0pKTtcbn1cblxuLyoqXG4gKiBHZXQgYWxsIHN0YXRpYyBlbGVtZW50cy5cbiAqIEBwYXJhbSAge0FycmF5fSBsYXlvdXQgQXJyYXkgb2YgbGF5b3V0IG9iamVjdHMuXG4gKiBAcmV0dXJuIHtBcnJheX0gICAgICAgIEFycmF5IG9mIHN0YXRpYyBsYXlvdXQgaXRlbXMuLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0U3RhdGljcyhsYXlvdXQ6IExheW91dCk6IExheW91dEl0ZW1bXSB7XG4gIHJldHVybiBsYXlvdXQuZmlsdGVyKGwgPT4gbC5zdGF0aWMpO1xufVxuXG4vKipcbiAqIE1vdmUgYW4gZWxlbWVudC4gUm