UNPKG

@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
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==