@foblex/flow
Version:
An Angular library designed to simplify the creation and manipulation of dynamic flow. Provides components for flows, nodes, and connections, automating node manipulation and inter-node connections.
142 lines • 28.8 kB
JavaScript
import { PointExtensions } from '@foblex/2d';
import { EFConnectableSide } from '../../../f-connectors';
import { CalculateCenterBetweenPointsHandler, CalculateCenterBetweenPointsRequest } from './calculate-center-between-points';
import { CalculateConnectionCenterHandler, CalculateConnectionCenterRequest } from './calculate-connection-center';
const CONNECTOR_SIDE_POINT = {
[EFConnectableSide.LEFT]: PointExtensions.initialize(-1, 0),
[EFConnectableSide.RIGHT]: PointExtensions.initialize(1, 0),
[EFConnectableSide.TOP]: PointExtensions.initialize(0, -1),
[EFConnectableSide.BOTTOM]: PointExtensions.initialize(0, 1),
[EFConnectableSide.AUTO]: PointExtensions.initialize(0, 0),
};
export class FSegmentPathBuilder {
handle(request) {
const { source, sourceSide, target, targetSide } = request;
const { points, center } = this.getPathPoints(source, sourceSide, target, targetSide, request.offset);
const path = this.buildPath(points, request.radius);
const penultimatePoint = points.length > 1 ? points[points.length - 2] : source;
return { path, connectionCenter: center, penultimatePoint };
}
getPathPoints(source, sourceSide, target, targetSide, offset) {
const sourceDirection = CONNECTOR_SIDE_POINT[sourceSide];
const targetDirection = CONNECTOR_SIDE_POINT[targetSide];
const sourceGap = { x: source.x + sourceDirection.x * offset, y: source.y + sourceDirection.y * offset };
const targetGap = { x: target.x + targetDirection.x * offset, y: target.y + targetDirection.y * offset };
const direction = this.getDirection(sourceGap, sourceSide, targetGap);
const directionAccessor = direction.x !== 0 ? 'x' : 'y';
const currentDirection = direction[directionAccessor];
let points = [];
const sourceGapOffset = PointExtensions.initialize();
const targetGapOffset = PointExtensions.initialize();
const centerBetweenPoints = new CalculateCenterBetweenPointsHandler().handle(new CalculateCenterBetweenPointsRequest(source, target));
if (sourceDirection[directionAccessor] * targetDirection[directionAccessor] === -1) {
const verticalSplit = [
{ x: centerBetweenPoints.x, y: sourceGap.y },
{ x: centerBetweenPoints.x, y: targetGap.y },
];
const horizontalSplit = [
{ x: sourceGap.x, y: centerBetweenPoints.y },
{ x: targetGap.x, y: centerBetweenPoints.y },
];
if (sourceDirection[directionAccessor] === currentDirection) {
points = directionAccessor === 'x' ? verticalSplit : horizontalSplit;
}
else {
points = directionAccessor === 'x' ? horizontalSplit : verticalSplit;
}
}
else {
const sourceTarget = [{ x: sourceGap.x, y: targetGap.y }];
const targetSource = [{ x: targetGap.x, y: sourceGap.y }];
if (directionAccessor === 'x') {
points = sourceDirection.x === currentDirection ? targetSource : sourceTarget;
}
else {
points = sourceDirection.y === currentDirection ? sourceTarget : targetSource;
}
if (sourceSide === targetSide) {
const diff = Math.abs(source[directionAccessor] - target[directionAccessor]);
if (diff <= offset) {
const gapOffset = Math.min(offset - 1, offset - diff);
if (sourceDirection[directionAccessor] === currentDirection) {
sourceGapOffset[directionAccessor] = (sourceGap[directionAccessor] > source[directionAccessor] ? -1 : 1) * gapOffset;
}
else {
targetGapOffset[directionAccessor] = (targetGap[directionAccessor] > target[directionAccessor] ? -1 : 1) * gapOffset;
}
}
}
if (sourceSide !== targetSide) {
const dirAccessorOpposite = directionAccessor === 'x' ? 'y' : 'x';
const isSameDir = sourceDirection[directionAccessor] === targetDirection[dirAccessorOpposite];
const sourceGtTargetOppo = sourceGap[dirAccessorOpposite] > targetGap[dirAccessorOpposite];
const sourceLtTargetOppo = sourceGap[dirAccessorOpposite] < targetGap[dirAccessorOpposite];
const flipSourceTarget = (sourceDirection[directionAccessor] === 1 &&
((!isSameDir && sourceGtTargetOppo) || (isSameDir && sourceLtTargetOppo))) ||
(sourceDirection[directionAccessor] !== 1 &&
((!isSameDir && sourceLtTargetOppo) || (isSameDir && sourceGtTargetOppo)));
if (flipSourceTarget) {
points = directionAccessor === 'x' ? sourceTarget : targetSource;
}
}
}
const pathPoints = [
source,
{ x: sourceGap.x + sourceGapOffset.x, y: sourceGap.y + sourceGapOffset.y },
...points,
{ x: targetGap.x + targetGapOffset.x, y: targetGap.y + targetGapOffset.y },
target,
];
const center = new CalculateConnectionCenterHandler().handle(new CalculateConnectionCenterRequest(pathPoints));
return { points: pathPoints, center: center };
}
getDirection(source, sourceSide, target) {
if (sourceSide === EFConnectableSide.LEFT || sourceSide === EFConnectableSide.RIGHT) {
return source.x < target.x ? PointExtensions.initialize(1, 0) : PointExtensions.initialize(-1, 0);
}
return source.y < target.y ? PointExtensions.initialize(0, 1) : PointExtensions.initialize(0, -1);
}
distance(a, b) {
return Math.sqrt(Math.pow(b.x - a.x, 2) + Math.pow(b.y - a.y, 2));
}
buildPath(points, borderRadius) {
let path = '';
for (let i = 0; i < points.length; i++) {
const p = points[i];
let segment = '';
if (i > 0 && i < points.length - 1) {
segment = this.getBend(points[i - 1], p, points[i + 1], borderRadius);
}
else if (i === points.length - 1) {
segment = this.buildLastLineSegment(i, p);
}
else {
segment = this.buildMoveOrLineSegment(i, p);
}
path += segment;
}
return path;
}
getBend(a, b, c, size) {
const bendSize = Math.min(this.distance(a, b) / 2, this.distance(b, c) / 2, size);
const { x, y } = b;
if ((a.x === x && x === c.x) || (a.y === y && y === c.y)) {
return `L${x} ${y}`;
}
if (a.y === y) {
const xDir = a.x < c.x ? -1 : 1;
const yDir = a.y < c.y ? 1 : -1;
return `L ${x + bendSize * xDir},${y}Q ${x},${y} ${x},${y + bendSize * yDir}`;
}
const xDir = a.x < c.x ? 1 : -1;
const yDir = a.y < c.y ? -1 : 1;
return `L ${x},${y + bendSize * yDir}Q ${x},${y} ${x + bendSize * xDir},${y}`;
}
buildMoveOrLineSegment(index, point) {
return `${index === 0 ? 'M' : 'L'}${point.x} ${point.y}`;
}
buildLastLineSegment(index, point) {
return `L${point.x + 0.0002} ${point.y + 0.0002}`;
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZi1zZWdtZW50LnBhdGgtYnVpbGRlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2YtZmxvdy9zcmMvZi1jb25uZWN0aW9uL2NvbW1vbi9kb21haW4vZi1zZWdtZW50LnBhdGgtYnVpbGRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQVUsZUFBZSxFQUFFLE1BQU0sWUFBWSxDQUFDO0FBQ3JELE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQzFELE9BQU8sRUFDTCxtQ0FBbUMsRUFDbkMsbUNBQW1DLEVBQ3BDLE1BQU0sbUNBQW1DLENBQUM7QUFDM0MsT0FBTyxFQUFFLGdDQUFnQyxFQUFFLGdDQUFnQyxFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFRbkgsTUFBTSxvQkFBb0IsR0FBaUI7SUFFekMsQ0FBRSxpQkFBaUIsQ0FBQyxJQUFJLENBQUUsRUFBRSxlQUFlLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUU3RCxDQUFFLGlCQUFpQixDQUFDLEtBQUssQ0FBRSxFQUFFLGVBQWUsQ0FBQyxVQUFVLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUU3RCxDQUFFLGlCQUFpQixDQUFDLEdBQUcsQ0FBRSxFQUFFLGVBQWUsQ0FBQyxVQUFVLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBRTVELENBQUUsaUJBQWlCLENBQUMsTUFBTSxDQUFFLEVBQUUsZUFBZSxDQUFDLFVBQVUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBRTlELENBQUUsaUJBQWlCLENBQUMsSUFBSSxDQUFFLEVBQUUsZUFBZSxDQUFDLFVBQVUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDO0NBQzdELENBQUM7QUFFRixNQUFNLE9BQU8sbUJBQW1CO0lBRXZCLE1BQU0sQ0FBQyxPQUFtQztRQUMvQyxNQUFNLEVBQUUsTUFBTSxFQUFFLFVB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QztJQUNqRSxDQUFDO0lBRU8sb0JBQW9CLENBQUMsS0FBYSxFQUFFLEtBQWE7UUFDdkQsT0FBTyxJQUFLLEtBQUssQ0FBQyxDQUFDLEdBQUcsTUFBTyxJQUFLLEtBQUssQ0FBQyxDQUFDLEdBQUcsTUFBTyxFQUFFLENBQUM7SUFDeEQsQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSVBvaW50LCBQb2ludEV4dGVuc2lvbnMgfSBmcm9tICdAZm9ibGV4LzJkJztcbmltcG9ydCB7IEVGQ29ubmVjdGFibGVTaWRlIH0gZnJvbSAnLi4vLi4vLi4vZi1jb25uZWN0b3JzJztcbmltcG9ydCB7XG4gIENhbGN1bGF0ZUNlbnRlckJldHdlZW5Qb2ludHNIYW5kbGVyLFxuICBDYWxjdWxhdGVDZW50ZXJCZXR3ZWVuUG9pbnRzUmVxdWVzdFxufSBmcm9tICcuL2NhbGN1bGF0ZS1jZW50ZXItYmV0d2Vlbi1wb2ludHMnO1xuaW1wb3J0IHsgQ2FsY3VsYXRlQ29ubmVjdGlvbkNlbnRlckhhbmRsZXIsIENhbGN1bGF0ZUNvbm5lY3Rpb25DZW50ZXJSZXF1ZXN0IH0gZnJvbSAnLi9jYWxjdWxhdGUtY29ubmVjdGlvbi1jZW50ZXInO1xuaW1wb3J0IHtcbiAgSUZDb25uZWN0aW9uQnVpbGRlcixcbiAgSUZDb25uZWN0aW9uQnVpbGRlclJlcXVlc3QsXG4gIElGQ29ubmVjdGlvbkJ1aWxkZXJSZXNwb25zZVxufSBmcm9tICcuLi8uLi9mLWNvbm5lY3Rpb24tYnVpbGRlcic7XG5pbXBvcnQgeyBJTWFwIH0gZnJvbSAnLi4vLi4vLi4vZG9tYWluJztcblxuY29uc3QgQ09OTkVDVE9SX1NJREVfUE9JTlQ6IElNYXA8SVBvaW50PiA9IHtcblxuICBbIEVGQ29ubmVjdGFibGVTaWRlLkxFRlQgXTogUG9pbnRFeHRlbnNpb25zLmluaXRpYWxpemUoLTEsIDApLFxuXG4gIFsgRUZDb25uZWN0YWJsZVNpZGUuUklHSFQgXTogUG9pbnRFeHRlbnNpb25zLmluaXRpYWxpemUoMSwgMCksXG5cbiAgWyBFRkNvbm5lY3RhYmxlU2lkZS5UT1AgXTogUG9pbnRFeHRlbnNpb25zLmluaXRpYWxpemUoMCwgLTEpLFxuXG4gIFsgRUZDb25uZWN0YWJsZVNpZGUuQk9UVE9NIF06IFBvaW50RXh0ZW5zaW9ucy5pbml0aWFsaXplKDAsIDEpLFxuXG4gIFsgRUZDb25uZWN0YWJsZVNpZGUuQVVUTyBdOiBQb2ludEV4dGVuc2lvbnMuaW5pdGlhbGl6ZSgwLCAwKSxcbn07XG5cbmV4cG9ydCBjbGFzcyBGU2VnbWVudFBhdGhCdWlsZGVyIGltcGxlbWVudHMgSUZDb25uZWN0aW9uQnVpbGRlciB7XG5cbiAgcHVibGljIGhhbmRsZShyZXF1ZXN0OiBJRkNvbm5lY3Rpb25CdWlsZGVyUmVxdWVzdCk6IElGQ29ubmVjdGlvbkJ1aWxkZXJSZXNwb25zZSB7XG4gICAgY29uc3QgeyBzb3VyY2UsIHNvdXJjZVNpZGUsIHRhcmdldCwgdGFyZ2V0U2lkZSB9ID0gcmVxdWVzdDtcblxuICAgIGNvbnN0IHsgcG9pbnRzLCBjZW50ZXIgfSA9IHRoaXMuZ2V0UGF0aFBvaW50cyhcbiAgICAgICAgc291cmNlLFxuICAgICAgICBzb3VyY2VTaWRlLFxuICAgICAgICB0YXJnZXQsXG4gICAgICAgIHRhcmdldFNpZGUsXG4gICAgICAgIHJlcXVlc3Qub2Zmc2V0XG4gICAgKTtcblxuICAgIGNvbnN0IHBhdGggPSB0aGlzLmJ1aWxkUGF0aChwb2ludHMsIHJlcXVlc3QucmFkaXVzKTtcblxuICAgIGNvbnN0IHBlbnVsdGltYXRlUG9pbnQgPSBwb2ludHMubGVuZ3RoID4gMSA/IHBvaW50c1sgcG9pbnRzLmxlbmd0aCAtIDIgXSA6IHNvdXJjZTtcblxuICAgIHJldHVybiB7IHBhdGgsIGNvbm5lY3Rpb25DZW50ZXI6IGNlbnRlciwgcGVudWx0aW1hdGVQb2ludCB9O1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRQYXRoUG9pbnRzKFxuICAgICAgc291cmNlOiBJUG9pbnQsIHNvdXJjZVNpZGU6IEVGQ29ubmVjdGFibGVTaWRlLCB0YXJnZXQ6IElQb2ludCwgdGFyZ2V0U2lkZTogRUZDb25uZWN0YWJsZVNpZGUsIG9mZnNldDogbnVtYmVyXG4gICk6IHsgcG9pbnRzOiBJUG9pbnRbXSwgY2VudGVyOiBJUG9pbnQgfSB7XG5cbiAgICBjb25zdCBzb3VyY2VEaXJlY3Rpb24gPSBDT05ORUNUT1JfU0lERV9QT0lOVFsgc291cmNlU2lkZSBdO1xuICAgIGNvbnN0IHRhcmdldERpcmVjdGlvbiA9IENPTk5FQ1RPUl9TSURFX1BPSU5UWyB0YXJnZXRTaWRlIF07XG5cbiAgICBjb25zdCBzb3VyY2VHYXA6IElQb2ludCA9IHsgeDogc291cmNlLnggKyBzb3VyY2VEaXJlY3Rpb24ueCAqIG9mZnNldCwgeTogc291cmNlLnkgKyBzb3VyY2VEaXJlY3Rpb24ueSAqIG9mZnNldCB9O1xuICAgIGNvbnN0IHRhcmdldEdhcDogSVBvaW50ID0geyB4OiB0YXJnZXQueCArIHRhcmdldERpcmVjdGlvbi54ICogb2Zmc2V0LCB5OiB0YXJnZXQueSArIHRhcmdldERpcmVjdGlvbi55ICogb2Zmc2V0IH07XG5cbiAgICBjb25zdCBkaXJlY3Rpb24gPSB0aGlzLmdldERpcmVjdGlvbihzb3VyY2VHYXAsIHNvdXJjZVNpZGUsIHRhcmdldEdhcCk7XG4gICAgY29uc3QgZGlyZWN0aW9uQWNjZXNzb3IgPSBkaXJlY3Rpb24ueCAhPT0gMCA/ICd4JyA6ICd5JztcbiAgICBjb25zdCBjdXJyZW50RGlyZWN0aW9uID0gZGlyZWN0aW9uWyBkaXJlY3Rpb25BY2Nlc3NvciBdO1xuXG4gICAgbGV0IHBvaW50czogSVBvaW50W10gPSBbXTtcbiAgICBjb25zdCBzb3VyY2VHYXBPZmZzZXQgPSBQb2ludEV4dGVuc2lvbnMuaW5pdGlhbGl6ZSgpO1xuICAgIGNvbnN0IHRhcmdldEdhcE9mZnNldCA9IFBvaW50RXh0ZW5zaW9ucy5pbml0aWFsaXplKCk7XG5cbiAgICBjb25zdCBjZW50ZXJCZXR3ZWVuUG9pbnRzID0gbmV3IENhbGN1bGF0ZUNlbnRlckJldHdlZW5Qb2ludHNIYW5kbGVyKCkuaGFuZGxlKFxuICAgICAgICBuZXcgQ2FsY3VsYXRlQ2VudGVyQmV0d2VlblBvaW50c1JlcXVlc3Qoc291cmNlLCB0YXJnZXQpXG4gICAgKTtcblxuICAgIGlmIChzb3VyY2VEaXJlY3Rpb25bIGRpcmVjdGlvbkFjY2Vzc29yIF0gKiB0YXJnZXREaXJlY3Rpb25bIGRpcmVjdGlvbkFjY2Vzc29yIF0gPT09IC0xKSB7XG4gICAgICBjb25zdCB2ZXJ0aWNhbFNwbGl0OiBJUG9pbnRbXSA9IFtcbiAgICAgICAgeyB4OiBjZW50ZXJCZXR3ZWVuUG9pbnRzLngsIHk6IHNvdXJjZUdhcC55IH0sXG4gICAgICAgIHsgeDogY2VudGVyQmV0d2VlblBvaW50cy54LCB5OiB0YXJnZXRHYXAueSB9LFxuICAgICAgXTtcbiAgICAgIGNvbnN0IGhvcml6b250YWxTcGxpdDogSVBvaW50W10gPSBbXG4gICAgICAgIHsgeDogc291cmNlR2FwLngsIHk6IGNlbnRlckJldHdlZW5Qb2ludHMueSB9LFxuICAgICAgICB7IHg6IHRhcmdldEdhcC54LCB5OiBjZW50ZXJCZXR3ZWVuUG9pbnRzLnkgfSxcbiAgICAgIF07XG5cbiAgICAgIGlmIChzb3VyY2VEaXJlY3Rpb25bIGRpcmVjdGlvbkFjY2Vzc29yIF0gPT09IGN1cnJlbnREaXJlY3Rpb24pIHtcbiAgICAgICAgcG9pbnRzID0gZGlyZWN0aW9uQWNjZXNzb3IgPT09ICd4JyA/IHZlcnRpY2FsU3BsaXQgOiBob3Jpem9udGFsU3BsaXQ7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBwb2ludHMgPSBkaXJlY3Rpb25BY2Nlc3NvciA9PT0gJ3gnID8gaG9yaXpvbnRhbFNwbGl0IDogdmVydGljYWxTcGxpdDtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3Qgc291cmNlVGFyZ2V0OiBJUG9pbnRbXSA9IFsgeyB4OiBzb3VyY2VHYXAueCwgeTogdGFyZ2V0R2FwLnkgfSBdO1xuICAgICAgY29uc3QgdGFyZ2V0U291cmNlOiBJUG9pbnRbXSA9IFsgeyB4OiB0YXJnZXRHYXAueCwgeTogc291cmNlR2FwLnkgfSBdO1xuXG4gICAgICBpZiAoZGlyZWN0aW9uQWNjZXNzb3IgPT09ICd4Jykge1xuICAgICAgICBwb2ludHMgPSBzb3VyY2VEaXJlY3Rpb24ueCA9PT0gY3VycmVudERpcmVjdGlvbiA/IHRhcmdldFNvdXJjZSA6IHNvdXJjZVRhcmdldDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHBvaW50cyA9IHNvdXJjZURpcmVjdGlvbi55ID09PSBjdXJyZW50RGlyZWN0aW9uID8gc291cmNlVGFyZ2V0IDogdGFyZ2V0U291cmNlO1xuICAgICAgfVxuXG4gICAgICBpZiAoc291cmNlU2lkZSA9PT0gdGFyZ2V0U2lkZSkge1xuICAgICAgICBjb25zdCBkaWZmID0gTWF0aC5hYnMoc291cmNlWyBkaXJlY3Rpb25BY2Nlc3NvciBdIC0gdGFyZ2V0WyBkaXJlY3Rpb25BY2Nlc3NvciBdKTtcblxuICAgICAgICBpZiAoZGlmZiA8PSBvZmZzZXQpIHtcbiAgICAgICAgICBjb25zdCBnYXBPZmZzZXQgPSBNYXRoLm1pbihvZmZzZXQgLSAxLCBvZmZzZXQgLSBkaWZmKTtcbiAgICAgICAgICBpZiAoc291cmNlRGlyZWN0aW9uWyBkaXJlY3Rpb25BY2Nlc3NvciBdID09PSBjdXJyZW50RGlyZWN0aW9uKSB7XG4gICAgICAgICAgICBzb3VyY2VHYXBPZmZzZXRbIGRpcmVjdGlvbkFjY2Vzc29yIF0gPSAoc291cmNlR2FwWyBkaXJlY3Rpb25BY2Nlc3NvciBdID4gc291cmNlWyBkaXJlY3Rpb25BY2Nlc3NvciBdID8gLTEgOiAxKSAqIGdhcE9mZnNldDtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGFyZ2V0R2FwT2Zmc2V0WyBkaXJlY3Rpb25BY2Nlc3NvciBdID0gKHRhcmdldEdhcFsgZGlyZWN0aW9uQWNjZXNzb3IgXSA+IHRhcmdldFsgZGlyZWN0aW9uQWNjZXNzb3IgXSA/IC0xIDogMSkgKiBnYXBPZmZzZXQ7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmIChzb3VyY2VTaWRlICE9PSB0YXJnZXRTaWRlKSB7XG4gICAgICAgIGNvbnN0IGRpckFjY2Vzc29yT3Bwb3NpdGUgPSBkaXJlY3Rpb25BY2Nlc3NvciA9PT0gJ3gnID8gJ3knIDogJ3gnO1xuICAgICAgICBjb25zdCBpc1NhbWVEaXIgPSBzb3VyY2VEaXJlY3Rpb25bIGRpcmVjdGlvbkFjY2Vzc29yIF0gPT09IHRhcmdldERpcmVjdGlvblsgZGlyQWNjZXNzb3JPcHBvc2l0ZSBdO1xuICAgICAgICBjb25zdCBzb3VyY2VHdFRhcmdldE9wcG8gPSBzb3VyY2VHYXBbIGRpckFjY2Vzc29yT3Bwb3NpdGUgXSA+IHRhcmdldEdhcFsgZGlyQWNjZXNzb3JPcHBvc2l0ZSBdO1xuICAgICAgICBjb25zdCBzb3VyY2VMdFRhcmdldE9wcG8gPSBzb3VyY2VHYXBbIGRpckFjY2Vzc29yT3Bwb3NpdGUgXSA8IHRhcmdldEdhcFsgZGlyQWNjZXNzb3JPcHBvc2l0ZSBdO1xuICAgICAgICBjb25zdCBmbGlwU291cmNlVGFyZ2V0ID1cbiAgICAgICAgICAgIChzb3VyY2VEaXJlY3Rpb25bIGRpcmVjdGlvbkFjY2Vzc29yIF0gPT09IDEgJiZcbiAgICAgICAgICAgICAgICAoKCFpc1NhbWVEaXIgJiYgc291cmNlR3RUYXJnZXRPcHBvKSB8fCAoaXNTYW1lRGlyICYmIHNvdXJjZUx0VGFyZ2V0T3BwbykpKSB8fFxuICAgICAgICAgICAgKHNvdXJjZURpcmVjdGlvblsgZGlyZWN0aW9uQWNjZXNzb3IgXSAhPT0gMSAmJlxuICAgICAgICAgICAgICAgICgoIWlzU2FtZURpciAmJiBzb3VyY2VMdFRhcmdldE9wcG8pIHx8IChpc1NhbWVEaXIgJiYgc291cmNlR3RUYXJnZXRPcHBvKSkpO1xuXG4gICAgICAgIGlmIChmbGlwU291cmNlVGFyZ2V0KSB7XG4gICAgICAgICAgcG9pbnRzID0gZGlyZWN0aW9uQWNjZXNzb3IgPT09ICd4JyA/IHNvdXJjZVRhcmdldCA6IHRhcmdldFNvdXJjZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IHBhdGhQb2ludHMgPSBbXG4gICAgICBzb3VyY2UsXG4gICAgICB7IHg6IHNvdXJjZUdhcC54ICsgc291cmNlR2FwT2Zmc2V0LngsIHk6IHNvdXJjZUdhcC55ICsgc291cmNlR2FwT2Zmc2V0LnkgfSxcbiAgICAgIC4uLnBvaW50cyxcbiAgICAgIHsgeDogdGFyZ2V0R2FwLnggKyB0YXJnZXRHYXBPZmZzZXQueCwgeTogdGFyZ2V0R2FwLnkgKyB0YXJnZXRHYXBPZmZzZXQueSB9LFxuICAgICAgdGFyZ2V0LFxuICAgIF07XG5cbiAgICBjb25zdCBjZW50ZXIgPSBuZXcgQ2FsY3VsYXRlQ29ubmVjdGlvbkNlbnRlckhhbmRsZXIoKS5oYW5kbGUoXG4gICAgICAgIG5ldyBDYWxjdWxhdGVDb25uZWN0aW9uQ2VudGVyUmVxdWVzdChwYXRoUG9pbnRzKVxuICAgICk7XG5cbiAgICByZXR1cm4geyBwb2ludHM6IHBhdGhQb2ludHMsIGNlbnRlcjogY2VudGVyIH07XG4gIH1cblxuICBwcml2YXRlIGdldERpcmVjdGlvbihzb3VyY2U6IElQb2ludCwgc291cmNlU2lkZTogRUZDb25uZWN0YWJsZVNpZGUsIHRhcmdldDogSVBvaW50KTogSVBvaW50IHtcbiAgICBpZiAoc291cmNlU2lkZSA9PT0gRUZDb25uZWN0YWJsZVNpZGUuTEVGVCB8fCBzb3VyY2VTaWRlID09PSBFRkNvbm5lY3RhYmxlU2lkZS5SSUdIVCkge1xuICAgICAgcmV0dXJuIHNvdXJjZS54IDwgdGFyZ2V0LnggPyBQb2ludEV4dGVuc2lvbnMuaW5pdGlhbGl6ZSgxLCAwKSA6IFBvaW50RXh0ZW5zaW9ucy5pbml0aWFsaXplKC0xLCAwKTtcbiAgICB9XG4gICAgcmV0dXJuIHNvdXJjZS55IDwgdGFyZ2V0LnkgPyBQb2ludEV4dGVuc2lvbnMuaW5pdGlhbGl6ZSgwLCAxKSA6IFBvaW50RXh0ZW5zaW9ucy5pbml0aWFsaXplKDAsIC0xKTtcbiAgfVxuXG4gIHByaXZhdGUgZGlzdGFuY2UoYTogSVBvaW50LCBiOiBJUG9pbnQpOiBudW1iZXIge1xuICAgIHJldHVybiBNYXRoLnNxcnQoTWF0aC5wb3coYi54IC0gYS54LCAyKSArIE1hdGgucG93KGIueSAtIGEueSwgMikpO1xuICB9XG5cbiAgcHJpdmF0ZSBidWlsZFBhdGgocG9pbnRzOiBJUG9pbnRbXSwgYm9yZGVyUmFkaXVzOiBudW1iZXIpOiBzdHJpbmcge1xuICAgIGxldCBwYXRoID0gJyc7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBwb2ludHMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNvbnN0IHAgPSBwb2ludHNbIGkgXTtcbiAgICAgIGxldCBzZWdtZW50ID0gJyc7XG5cbiAgICAgIGlmIChpID4gMCAmJiBpIDwgcG9pbnRzLmxlbmd0aCAtIDEpIHtcbiAgICAgICAgc2VnbWVudCA9IHRoaXMuZ2V0QmVuZChwb2ludHNbIGkgLSAxIF0sIHAsIHBvaW50c1sgaSArIDEgXSwgYm9yZGVyUmFkaXVzKTtcbiAgICAgIH0gZWxzZSBpZiAoaSA9PT0gcG9pbnRzLmxlbmd0aCAtIDEpIHtcbiAgICAgICAgc2VnbWVudCA9IHRoaXMuYnVpbGRMYXN0TGluZVNlZ21lbnQoaSwgcCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzZWdtZW50ID0gdGhpcy5idWlsZE1vdmVPckxpbmVTZWdtZW50KGksIHApO1xuICAgICAgfVxuICAgICAgcGF0aCArPSBzZWdtZW50O1xuICAgIH1cblxuICAgIHJldHVybiBwYXRoO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRCZW5kKGE6IElQb2ludCwgYjogSVBvaW50LCBjOiBJUG9pbnQsIHNpemU6IG51bWJlcik6IHN0cmluZyB7XG4gICAgY29uc3QgYmVuZFNpemUgPSBNYXRoLm1pbih0aGlzLmRpc3RhbmNlKGEsIGIpIC8gMiwgdGhpcy5kaXN0YW5jZShiLCBjKSAvIDIsIHNpemUpO1xuICAgIGNvbnN0IHsgeCwgeSB9ID0gYjtcblxuICAgIGlmICgoYS54ID09PSB4ICYmIHggPT09IGMueCkgfHwgKGEueSA9PT0geSAmJiB5ID09PSBjLnkpKSB7XG4gICAgICByZXR1cm4gYEwkeyB4IH0gJHsgeSB9YDtcbiAgICB9XG5cbiAgICBpZiAoYS55ID09PSB5KSB7XG4gICAgICBjb25zdCB4RGlyID0gYS54IDwgYy54ID8gLTEgOiAxO1xuICAgICAgY29uc3QgeURpciA9IGEueSA8IGMueSA/IDEgOiAtMTtcbiAgICAgIHJldHVybiBgTCAkeyB4ICsgYmVuZFNpemUgKiB4RGlyIH0sJHsgeSB9USAkeyB4IH0sJHsgeSB9ICR7IHggfSwkeyB5ICsgYmVuZFNpemUgKiB5RGlyIH1gO1xuICAgIH1cblxuICAgIGNvbnN0IHhEaXIgPSBhLnggPCBjLnggPyAxIDogLTE7XG4gICAgY29uc3QgeURpciA9IGEueSA8IGMueSA/IC0xIDogMTtcbiAgICByZXR1cm4gYEwgJHsgeCB9LCR7IHkgKyBiZW5kU2l6ZSAqIHlEaXIgfVEgJHsgeCB9LCR7IHkgfSAkeyB4ICsgYmVuZFNpemUgKiB4RGlyIH0sJHsgeSB9YDtcbiAgfVxuXG4gIHByaXZhdGUgYnVpbGRNb3ZlT3JMaW5lU2VnbWVudChpbmRleDogbnVtYmVyLCBwb2ludDogSVBvaW50KTogc3RyaW5nIHtcbiAgICByZXR1cm4gYCR7IGluZGV4ID09PSAwID8gJ00nIDogJ0wnIH0keyBwb2ludC54IH0gJHsgcG9pbnQueSB9YDtcbiAgfVxuXG4gIHByaXZhdGUgYnVpbGRMYXN0TGluZVNlZ21lbnQoaW5kZXg6IG51bWJlciwgcG9pbnQ6IElQb2ludCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIGBMJHsgcG9pbnQueCArIDAuMDAwMiB9ICR7IHBvaW50LnkgKyAwLjAwMDIgfWA7XG4gIH1cbn1cbiJdfQ==