@plait/draw 0.53.0 → 0.54.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/constants/geometry.d.ts +3 -1
  2. package/esm2022/constants/geometry.mjs +4 -2
  3. package/esm2022/generators/line-auto-complete.generator.mjs +1 -1
  4. package/esm2022/interfaces/index.mjs +2 -2
  5. package/esm2022/plugins/with-draw-fragment.mjs +1 -1
  6. package/esm2022/plugins/with-draw-resize.mjs +56 -9
  7. package/esm2022/plugins/with-draw.mjs +4 -4
  8. package/esm2022/plugins/with-geometry-resize.mjs +7 -14
  9. package/esm2022/plugins/with-line-auto-complete-reaction.mjs +2 -2
  10. package/esm2022/plugins/with-line-auto-complete.mjs +15 -14
  11. package/esm2022/plugins/with-line-bound-reaction.mjs +19 -21
  12. package/esm2022/plugins/with-line-create.mjs +4 -4
  13. package/esm2022/plugins/with-line-resize.mjs +11 -12
  14. package/esm2022/transforms/line.mjs +4 -4
  15. package/esm2022/utils/geometry.mjs +31 -22
  16. package/esm2022/utils/hit.mjs +26 -26
  17. package/esm2022/utils/line/elbow.mjs +11 -6
  18. package/esm2022/utils/line/line-basic.mjs +21 -29
  19. package/esm2022/utils/line/line-common.mjs +3 -3
  20. package/esm2022/utils/line/line-resize.mjs +2 -2
  21. package/esm2022/utils/position/geometry.mjs +51 -21
  22. package/esm2022/utils/resize-snap.mjs +361 -0
  23. package/esm2022/utils/shape.mjs +2 -2
  24. package/fesm2022/plait-draw.mjs +432 -344
  25. package/fesm2022/plait-draw.mjs.map +1 -1
  26. package/generators/line-auto-complete.generator.d.ts +3 -3
  27. package/interfaces/index.d.ts +2 -2
  28. package/package.json +1 -1
  29. package/plugins/with-draw-fragment.d.ts +2 -2
  30. package/plugins/with-draw-resize.d.ts +6 -0
  31. package/utils/geometry.d.ts +7 -4
  32. package/utils/hit.d.ts +3 -1
  33. package/utils/line/elbow.d.ts +3 -0
  34. package/utils/line/line-basic.d.ts +4 -4
  35. package/utils/position/geometry.d.ts +10 -2
  36. package/utils/resize-snap.d.ts +49 -0
  37. package/utils/shape.d.ts +2 -2
  38. package/esm2022/utils/resize-align-reaction.mjs +0 -316
  39. package/esm2022/utils/resize-align.mjs +0 -37
  40. package/utils/resize-align-reaction.d.ts +0 -42
  41. package/utils/resize-align.d.ts +0 -8
@@ -1,12 +1,12 @@
1
1
  import { PlaitBoard } from '@plait/core';
2
- import { PlaitGeometry, PlaitShape } from '../interfaces';
2
+ import { PlaitGeometry, PlaitShapeElement } from '../interfaces';
3
3
  import { ActiveGeneratorExtraData, Generator } from '@plait/common';
4
- export declare class LineAutoCompleteGenerator extends Generator<PlaitShape, ActiveGeneratorExtraData> {
4
+ export declare class LineAutoCompleteGenerator extends Generator<PlaitShapeElement, ActiveGeneratorExtraData> {
5
5
  board: PlaitBoard;
6
6
  autoCompleteG: SVGGElement;
7
7
  hoverElement: SVGGElement | null;
8
8
  constructor(board: PlaitBoard);
9
- canDraw(element: PlaitShape, data: ActiveGeneratorExtraData): boolean;
9
+ canDraw(element: PlaitShapeElement, data: ActiveGeneratorExtraData): boolean;
10
10
  draw(element: PlaitGeometry, data: ActiveGeneratorExtraData): SVGGElement;
11
11
  removeAutoCompleteG(index: number): void;
12
12
  recoverAutoCompleteG(): void;
@@ -7,14 +7,14 @@ export * from './geometry';
7
7
  export * from './text';
8
8
  export * from './element';
9
9
  export type PlaitDrawElement = PlaitGeometry | PlaitLine | PlaitImage;
10
- export type PlaitShape = PlaitGeometry | PlaitImage;
10
+ export type PlaitShapeElement = PlaitGeometry | PlaitImage;
11
11
  export declare const PlaitDrawElement: {
12
12
  isGeometry: (value: any) => value is PlaitGeometry;
13
13
  isLine: (value: any) => value is PlaitLine;
14
14
  isText: (value: any) => value is PlaitText;
15
15
  isImage: (value: any) => value is PlaitImage;
16
16
  isDrawElement: (value: any) => value is PlaitDrawElement;
17
- isShape: (value: any) => value is PlaitShape;
17
+ isShapeElement: (value: any) => value is PlaitShapeElement;
18
18
  isBasicShape: (value: any) => boolean;
19
19
  isFlowchart: (value: any) => boolean;
20
20
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plait/draw",
3
- "version": "0.53.0",
3
+ "version": "0.54.0",
4
4
  "peerDependencies": {
5
5
  "@angular/common": "^17.2.4",
6
6
  "@angular/core": "^17.2.4",
@@ -1,4 +1,4 @@
1
1
  import { PlaitBoard } from '@plait/core';
2
- import { PlaitLine, PlaitShape } from '../interfaces';
2
+ import { PlaitLine, PlaitShapeElement } from '../interfaces';
3
3
  export declare const withDrawFragment: (baseBoard: PlaitBoard) => PlaitBoard;
4
- export declare const getBoundedLineElements: (board: PlaitBoard, plaitShapes: PlaitShape[]) => PlaitLine[];
4
+ export declare const getBoundedLineElements: (board: PlaitBoard, plaitShapes: PlaitShapeElement[]) => PlaitLine[];
@@ -17,3 +17,9 @@ export declare const getResizeZoom: (resizeState: ResizeState, resizeOriginPoint
17
17
  yZoom: number;
18
18
  };
19
19
  export declare const movePointByZoomAndOriginPoint: (p: Point, resizeOriginPoint: Point, xZoom: number, yZoom: number) => Point;
20
+ /**
21
+ * 1. Rotate 90°
22
+ * 2. Scale based on the rotated points
23
+ * 3. Reverse rotate the scaled points by 90°
24
+ */
25
+ export declare const getResizePointsByOtherwiseAxis: (board: PlaitBoard, points: Point[], resizeOriginPoint: Point, xZoom: number, yZoom: number) => Point[];
@@ -4,7 +4,7 @@ import { Alignment, CustomText } from '@plait/text';
4
4
  import { Element } from 'slate';
5
5
  import { DrawPointerType } from '../constants';
6
6
  import { Options } from 'roughjs/bin/core';
7
- import { PlaitShape } from '../interfaces';
7
+ import { PlaitShapeElement } from '../interfaces';
8
8
  export type GeometryStyleOptions = Pick<PlaitGeometry, 'fill' | 'strokeColor' | 'strokeWidth'>;
9
9
  export type TextProperties = Partial<CustomText> & {
10
10
  align?: Alignment;
@@ -17,9 +17,12 @@ export declare const getTextRectangle: (element: PlaitGeometry) => {
17
17
  x: number;
18
18
  y: number;
19
19
  };
20
- export declare const drawBoundMask: (board: PlaitBoard, element: PlaitGeometry) => SVGGElement;
20
+ export declare const drawBoundReaction: (board: PlaitBoard, element: PlaitGeometry, options?: {
21
+ hasMask: boolean;
22
+ hasConnector: boolean;
23
+ }) => SVGGElement;
21
24
  export declare const drawGeometry: (board: PlaitBoard, outerRectangle: RectangleClient, shape: GeometryShapes, options: Options) => SVGGElement;
22
- export declare const getNearestPoint: (element: PlaitShape, point: Point) => Point;
25
+ export declare const getNearestPoint: (element: PlaitShapeElement, point: Point) => Point;
23
26
  export declare const getCenterPointsOnPolygon: (points: Point[]) => Point[];
24
27
  export declare const getDefaultFlowchartProperty: (symbol: FlowchartSymbols) => {
25
28
  width: number;
@@ -41,7 +44,7 @@ export declare const getDefaultFlowchartProperty: (symbol: FlowchartSymbols) =>
41
44
  height: number;
42
45
  };
43
46
  export declare const createDefaultFlowchart: (point: Point) => (PlaitGeometry | import("../interfaces").PlaitLine)[];
44
- export declare const getAutoCompletePoints: (element: PlaitShape) => [Point, Point, Point, Point];
47
+ export declare const getAutoCompletePoints: (element: PlaitShapeElement) => [Point, Point, Point, Point];
45
48
  export declare const getHitIndexOfAutoCompletePoint: (movingPoint: Point, points: Point[]) => number;
46
49
  export declare const getDrawDefaultStrokeColor: (theme: ThemeColorMode) => string;
47
50
  export declare const getFlowchartDefaultFill: (theme: ThemeColorMode) => string;
package/utils/hit.d.ts CHANGED
@@ -1,9 +1,11 @@
1
1
  import { PlaitElement, Selection, PlaitBoard, Point } from '@plait/core';
2
- import { PlaitGeometry, PlaitLine } from '../interfaces';
2
+ import { PlaitGeometry, PlaitLine, PlaitShapeElement } from '../interfaces';
3
3
  export declare const isTextExceedingBounds: (geometry: PlaitGeometry) => boolean;
4
4
  export declare const isHitLineText: (board: PlaitBoard, element: PlaitLine, point: Point) => boolean;
5
5
  export declare const isHitPolyLine: (pathPoints: Point[], point: Point) => boolean;
6
6
  export declare const isHitLine: (board: PlaitBoard, element: PlaitLine, point: Point) => boolean;
7
7
  export declare const isRectangleHitDrawElement: (board: PlaitBoard, element: PlaitElement, selection: Selection) => boolean | null;
8
8
  export declare const isHitDrawElement: (board: PlaitBoard, element: PlaitElement, point: Point) => boolean | null;
9
+ export declare const isHitEdgeOfShape: (board: PlaitBoard, element: PlaitShapeElement, point: Point, hitDistanceBuffer: number) => boolean;
10
+ export declare const isInsideOfShape: (board: PlaitBoard, element: PlaitShapeElement, point: Point, hitDistanceBuffer: number) => boolean;
9
11
  export declare const isHitElementInside: (board: PlaitBoard, element: PlaitElement, point: Point) => boolean | null;
@@ -1,5 +1,8 @@
1
1
  import { Point, PlaitBoard, RectangleClient } from '@plait/core';
2
+ import { ElbowLineRouteOptions } from '@plait/common';
2
3
  import { LineHandleRefPair, PlaitLine } from '../../interfaces';
4
+ export declare const isSelfLoop: (element: PlaitLine) => boolean | "" | undefined;
5
+ export declare const isUseDefaultOrthogonalRoute: (element: PlaitLine, options: ElbowLineRouteOptions) => boolean;
3
6
  export declare const getElbowPoints: (board: PlaitBoard, element: PlaitLine) => Point[];
4
7
  export declare const getNextSourceAndTargetPoints: (board: PlaitBoard, element: PlaitLine) => Point[];
5
8
  export declare const getSourceAndTargetRectangle: (board: PlaitBoard, element: PlaitLine, handleRefPair: LineHandleRefPair) => {
@@ -1,13 +1,13 @@
1
1
  import { Point, PlaitBoard, RectangleClient } from '@plait/core';
2
- import { LineHandle, LineShape, LineText, PlaitLine, PlaitShape } from '../../interfaces';
2
+ import { LineHandle, LineShape, LineText, PlaitLine, PlaitShapeElement } from '../../interfaces';
3
3
  export declare const createLineElement: (shape: LineShape, points: [Point, Point], source: LineHandle, target: LineHandle, texts?: LineText[], options?: Pick<PlaitLine, 'strokeColor' | 'strokeWidth'>) => PlaitLine;
4
4
  export declare const getLinePoints: (board: PlaitBoard, element: PlaitLine) => Point[];
5
5
  export declare const getCurvePoints: (board: PlaitBoard, element: PlaitLine) => Point[];
6
6
  export declare function getMiddlePoints(board: PlaitBoard, element: PlaitLine): Point[];
7
7
  export declare const drawLine: (board: PlaitBoard, element: PlaitLine) => SVGGElement;
8
- export declare const getConnectionByNearestPoint: (board: PlaitBoard, point: Point, hitElement: PlaitShape) => Point;
9
- export declare const getHitConnectorPoint: (point: Point, hitElement: PlaitShape, rectangle: RectangleClient) => Point | undefined;
8
+ export declare const getHitConnection: (board: PlaitBoard, point: Point, hitElement: PlaitShapeElement) => Point;
9
+ export declare const getHitConnectorPoint: (point: Point, hitElement: PlaitShapeElement) => Point | undefined;
10
10
  export declare const getLineTextRectangle: (board: PlaitBoard, element: PlaitLine, index: number) => RectangleClient;
11
11
  export declare const getLines: (board: PlaitBoard) => PlaitLine[];
12
12
  export declare const Q2C: (points: Point[]) => Point[];
13
- export declare const handleLineCreating: (board: PlaitBoard, lineShape: LineShape, sourcePoint: Point, movingPoint: Point, sourceElement: PlaitShape | null, lineShapeG: SVGGElement) => PlaitLine;
13
+ export declare const handleLineCreating: (board: PlaitBoard, lineShape: LineShape, sourcePoint: Point, movingPoint: Point, sourceElement: PlaitShapeElement | null, lineShapeG: SVGGElement) => PlaitLine;
@@ -1,5 +1,5 @@
1
1
  import { PlaitBoard, Point, RectangleClient } from '@plait/core';
2
- import { PlaitGeometry } from '../../interfaces';
2
+ import { PlaitGeometry, PlaitShapeElement } from '../../interfaces';
3
3
  export declare const getHitRectangleResizeHandleRef: (board: PlaitBoard, rectangle: RectangleClient, point: Point, angle?: number) => {
4
4
  rectangle: {
5
5
  x: number;
@@ -10,4 +10,12 @@ export declare const getHitRectangleResizeHandleRef: (board: PlaitBoard, rectang
10
10
  handle: import("@plait/common").ResizeHandle;
11
11
  cursorClass: import("@plait/core").ResizeCursorClass;
12
12
  } | undefined;
13
- export declare const getHitOutlineGeometry: (board: PlaitBoard, point: Point, offset?: number) => PlaitGeometry | null;
13
+ export declare const getSnappingGeometry: (board: PlaitBoard, point: Point) => PlaitGeometry | null;
14
+ export declare const getSnappingRef: (board: PlaitBoard, hitElement: PlaitShapeElement, point: Point) => {
15
+ isHitEdge: boolean;
16
+ isHitConnector: boolean;
17
+ connectorPoint: Point | undefined;
18
+ edgePoint: Point;
19
+ };
20
+ export declare const getHitGeometry: (board: PlaitBoard, point: Point, offset?: number) => PlaitGeometry | null;
21
+ export declare const traverseDrawShapes: (board: PlaitBoard, callback: (element: PlaitShapeElement) => void) => void;
@@ -0,0 +1,49 @@
1
+ import { ResizeRef, ResizeState } from '@plait/common';
2
+ import { DirectionFactors, PlaitBoard, PlaitElement, Point, RectangleClient } from '@plait/core';
3
+ import { PlaitDrawElement } from '../interfaces';
4
+ export declare const debugGenerator: import("@plait/core").DebugGenerator;
5
+ export interface ResizeAlignDelta {
6
+ deltaX: number;
7
+ deltaY: number;
8
+ }
9
+ export interface SnapRef extends ResizeAlignDelta {
10
+ xZoom: number;
11
+ yZoom: number;
12
+ activePoints: Point[];
13
+ }
14
+ export interface ResizeSnapRef extends SnapRef {
15
+ alignG: SVGGElement;
16
+ }
17
+ export interface ResizeSnapOptions {
18
+ resizeState: ResizeState;
19
+ resizeOriginPoints: Point[];
20
+ activeRectangle: RectangleClient;
21
+ directionFactors: DirectionFactors;
22
+ originPoint: Point;
23
+ handlePoint: Point;
24
+ isFromCorner: boolean;
25
+ isAspectRatio: boolean;
26
+ }
27
+ type TripleAlignAxis = [number, number, number];
28
+ export declare class ResizeSnapReaction {
29
+ private board;
30
+ private activeElements;
31
+ alignRectangles: RectangleClient[];
32
+ angle: number;
33
+ constructor(board: PlaitBoard, activeElements: PlaitElement[]);
34
+ getAlignRectangle(): RectangleClient[];
35
+ getSnapRef(resizeAlignDelta: ResizeAlignDelta, resizeSnapOptions: ResizeSnapOptions): SnapRef;
36
+ getEqualLineDelta(resizeSnapOptions: ResizeSnapOptions): ResizeAlignDelta;
37
+ drawEqualLines(activePoints: Point[], resizeSnapOptions: ResizeSnapOptions): SVGGElement;
38
+ getAlignLineDelta(resizeSnapOptions: ResizeSnapOptions): ResizeAlignDelta;
39
+ drawAlignLines(activePoints: Point[], resizeSnapOptions: ResizeSnapOptions): SVGGElement;
40
+ handleResizeSnap(resizeSnapOptions: ResizeSnapOptions): ResizeSnapRef;
41
+ }
42
+ export declare const getTripleAlignAxis: (rectangle: RectangleClient, isHorizontal: boolean) => TripleAlignAxis;
43
+ export declare const isAlign: (axis: number, rectangle: RectangleClient, isHorizontal: boolean) => boolean;
44
+ export declare const getClosestDelta: (axis: number, rectangle: RectangleClient, isHorizontal: boolean) => number;
45
+ export declare function getResizeSnapRef(board: PlaitBoard, resizeRef: ResizeRef<PlaitDrawElement | PlaitDrawElement[]>, resizeState: ResizeState, resizeOriginPointAndHandlePoint: {
46
+ originPoint: Point;
47
+ handlePoint: Point;
48
+ }, isAspectRatio: boolean, isFromCorner: boolean): ResizeSnapRef;
49
+ export {};
package/utils/shape.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- import { PlaitShape } from '../interfaces';
2
- export declare const getShape: (value: PlaitShape) => import("../interfaces").GeometryShapes;
1
+ import { PlaitShapeElement } from '../interfaces';
2
+ export declare const getElementShape: (value: PlaitShapeElement) => import("../interfaces").GeometryShapes;
@@ -1,316 +0,0 @@
1
- import { PlaitBoard, Point, RectangleClient, SELECTION_BORDER_COLOR, createG, findElements } from '@plait/core';
2
- import { getResizeZoom, movePointByZoomAndOriginPoint } from '../plugins/with-draw-resize';
3
- const ALIGN_TOLERANCE = 2;
4
- const EQUAL_SPACING = 10;
5
- const ALIGN_SPACING = 24;
6
- export class ResizeAlignReaction {
7
- constructor(board, activeElements) {
8
- this.board = board;
9
- this.activeElements = activeElements;
10
- this.alignRectangles = this.getAlignRectangle();
11
- }
12
- getAlignRectangle() {
13
- const elements = findElements(this.board, {
14
- match: element => this.board.isAlign(element) && !this.activeElements.some(item => item.id === element.id),
15
- recursion: () => false,
16
- isReverse: false
17
- });
18
- return elements.map(item => this.board.getRectangle(item));
19
- }
20
- getAlignLineRef(resizeAlignDelta, resizeAlignOptions) {
21
- const { deltaX, deltaY } = resizeAlignDelta;
22
- const { resizeState, originPoint, handlePoint, isFromCorner, isAspectRatio, resizeOriginPoints } = resizeAlignOptions;
23
- const newResizeState = {
24
- ...resizeState,
25
- endPoint: [resizeState.endPoint[0] + deltaX, resizeState.endPoint[1] + deltaY]
26
- };
27
- const { xZoom, yZoom } = getResizeZoom(newResizeState, originPoint, handlePoint, isFromCorner, isAspectRatio);
28
- const activePoints = resizeOriginPoints.map(p => {
29
- return movePointByZoomAndOriginPoint(p, originPoint, xZoom, yZoom);
30
- });
31
- return {
32
- deltaX,
33
- deltaY,
34
- xZoom,
35
- yZoom,
36
- activePoints
37
- };
38
- }
39
- getEqualLineDelta(resizeAlignOptions) {
40
- let equalLineDelta = {
41
- deltaX: 0,
42
- deltaY: 0
43
- };
44
- const { isAspectRatio, activeRectangle } = resizeAlignOptions;
45
- const widthAlignRectangle = this.alignRectangles.find(item => Math.abs(item.width - activeRectangle.width) < ALIGN_TOLERANCE);
46
- if (widthAlignRectangle) {
47
- const deltaWidth = widthAlignRectangle.width - activeRectangle.width;
48
- equalLineDelta.deltaX = deltaWidth * resizeAlignOptions.directionFactors[0];
49
- if (isAspectRatio) {
50
- const deltaHeight = deltaWidth / (activeRectangle.width / activeRectangle.height);
51
- equalLineDelta.deltaY = deltaHeight * resizeAlignOptions.directionFactors[1];
52
- return equalLineDelta;
53
- }
54
- }
55
- const heightAlignRectangle = this.alignRectangles.find(item => Math.abs(item.height - activeRectangle.height) < ALIGN_TOLERANCE);
56
- if (heightAlignRectangle) {
57
- const deltaHeight = heightAlignRectangle.height - activeRectangle.height;
58
- equalLineDelta.deltaY = deltaHeight * resizeAlignOptions.directionFactors[1];
59
- if (isAspectRatio) {
60
- const deltaWidth = deltaHeight * (activeRectangle.width / activeRectangle.height);
61
- equalLineDelta.deltaX = deltaWidth * resizeAlignOptions.directionFactors[0];
62
- return equalLineDelta;
63
- }
64
- }
65
- return equalLineDelta;
66
- }
67
- drawEqualLines(activePoints, resizeAlignOptions) {
68
- let widthEqualPoints = [];
69
- let heightEqualPoints = [];
70
- const drawHorizontalLine = resizeAlignOptions.directionFactors[0] !== 0 || resizeAlignOptions.isAspectRatio;
71
- const drawVerticalLine = resizeAlignOptions.directionFactors[1] !== 0 || resizeAlignOptions.isAspectRatio;
72
- const activeRectangle = RectangleClient.getRectangleByPoints(activePoints);
73
- for (let alignRectangle of this.alignRectangles) {
74
- if (activeRectangle.width === alignRectangle.width && drawHorizontalLine) {
75
- widthEqualPoints.push(getEqualLinePoints(alignRectangle, true));
76
- }
77
- if (activeRectangle.height === alignRectangle.height && drawVerticalLine) {
78
- heightEqualPoints.push(getEqualLinePoints(alignRectangle, false));
79
- }
80
- }
81
- if (widthEqualPoints.length && drawHorizontalLine) {
82
- widthEqualPoints.push(getEqualLinePoints(activeRectangle, true));
83
- }
84
- if (heightEqualPoints.length && drawVerticalLine) {
85
- heightEqualPoints.push(getEqualLinePoints(activeRectangle, false));
86
- }
87
- const equalLinePoints = [...widthEqualPoints, ...heightEqualPoints];
88
- return drawEqualLines(this.board, equalLinePoints);
89
- }
90
- getAlignLineDelta(resizeAlignOptions) {
91
- let alignLineDelta = {
92
- deltaX: 0,
93
- deltaY: 0
94
- };
95
- const { isAspectRatio, activeRectangle, directionFactors } = resizeAlignOptions;
96
- const drawHorizontal = directionFactors[0] !== 0 || isAspectRatio;
97
- const drawVertical = directionFactors[1] !== 0 || isAspectRatio;
98
- if (drawHorizontal) {
99
- const xAlignAxis = getTripleAlignAxis(activeRectangle, true);
100
- const alignX = directionFactors[0] === -1 ? xAlignAxis[0] : xAlignAxis[2];
101
- const deltaX = getMinAlignDelta(this.alignRectangles, alignX, true);
102
- if (Math.abs(deltaX) < ALIGN_TOLERANCE) {
103
- alignLineDelta.deltaX = deltaX;
104
- if (alignLineDelta.deltaX !== 0 && isAspectRatio) {
105
- alignLineDelta.deltaY = alignLineDelta.deltaX / (activeRectangle.width / activeRectangle.height);
106
- return alignLineDelta;
107
- }
108
- }
109
- }
110
- if (drawVertical) {
111
- const yAlignAxis = getTripleAlignAxis(activeRectangle, false);
112
- const alignY = directionFactors[1] === -1 ? yAlignAxis[0] : yAlignAxis[2];
113
- const deltaY = getMinAlignDelta(this.alignRectangles, alignY, false);
114
- if (Math.abs(deltaY) < ALIGN_TOLERANCE) {
115
- alignLineDelta.deltaY = deltaY;
116
- if (alignLineDelta.deltaY !== 0 && isAspectRatio) {
117
- alignLineDelta.deltaX = alignLineDelta.deltaY * (activeRectangle.width / activeRectangle.height);
118
- return alignLineDelta;
119
- }
120
- }
121
- }
122
- return alignLineDelta;
123
- }
124
- drawAlignLines(activePoints, resizeAlignOptions) {
125
- let alignLinePoints = [];
126
- const activeRectangle = RectangleClient.getRectangleByPoints(activePoints);
127
- const alignAxisX = getTripleAlignAxis(activeRectangle, true);
128
- const alignAxisY = getTripleAlignAxis(activeRectangle, false);
129
- const alignLineRefs = [
130
- {
131
- axis: alignAxisX[0],
132
- isHorizontal: true,
133
- alignRectangles: []
134
- },
135
- {
136
- axis: alignAxisX[2],
137
- isHorizontal: true,
138
- alignRectangles: []
139
- },
140
- {
141
- axis: alignAxisY[0],
142
- isHorizontal: false,
143
- alignRectangles: []
144
- },
145
- {
146
- axis: alignAxisY[2],
147
- isHorizontal: false,
148
- alignRectangles: []
149
- }
150
- ];
151
- const setAlignLine = (axis, alignRectangle, isHorizontal) => {
152
- const boundingRectangle = RectangleClient.inflate(RectangleClient.getBoundingRectangle([activeRectangle, alignRectangle]), ALIGN_SPACING);
153
- if (isHorizontal) {
154
- const pointStart = [axis, boundingRectangle.y];
155
- const pointEnd = [axis, boundingRectangle.y + boundingRectangle.height];
156
- alignLinePoints.push([pointStart, pointEnd]);
157
- }
158
- else {
159
- const pointStart = [boundingRectangle.x, axis];
160
- const pointEnd = [boundingRectangle.x + boundingRectangle.width, axis];
161
- alignLinePoints.push([pointStart, pointEnd]);
162
- }
163
- };
164
- const { isAspectRatio, directionFactors } = resizeAlignOptions;
165
- const drawHorizontal = directionFactors[0] !== 0 || isAspectRatio;
166
- const drawVertical = directionFactors[1] !== 0 || isAspectRatio;
167
- for (let index = 0; index < this.alignRectangles.length; index++) {
168
- const element = this.alignRectangles[index];
169
- if (isAlign(alignLineRefs[0].axis, element, alignLineRefs[0].isHorizontal)) {
170
- alignLineRefs[0].alignRectangles.push(element);
171
- }
172
- if (isAlign(alignLineRefs[1].axis, element, alignLineRefs[1].isHorizontal)) {
173
- alignLineRefs[1].alignRectangles.push(element);
174
- }
175
- if (isAlign(alignLineRefs[2].axis, element, alignLineRefs[2].isHorizontal)) {
176
- alignLineRefs[2].alignRectangles.push(element);
177
- }
178
- if (isAlign(alignLineRefs[3].axis, element, alignLineRefs[3].isHorizontal)) {
179
- alignLineRefs[3].alignRectangles.push(element);
180
- }
181
- }
182
- if (drawHorizontal && alignLineRefs[0].alignRectangles.length) {
183
- const leftRectangle = alignLineRefs[0].alignRectangles.length === 1
184
- ? alignLineRefs[0].alignRectangles[0]
185
- : getNearestAlignRectangle(alignLineRefs[0].alignRectangles, activeRectangle);
186
- setAlignLine(alignLineRefs[0].axis, leftRectangle, alignLineRefs[0].isHorizontal);
187
- }
188
- if (drawHorizontal && alignLineRefs[1].alignRectangles.length) {
189
- const rightRectangle = alignLineRefs[1].alignRectangles.length === 1
190
- ? alignLineRefs[1].alignRectangles[0]
191
- : getNearestAlignRectangle(alignLineRefs[1].alignRectangles, activeRectangle);
192
- setAlignLine(alignLineRefs[1].axis, rightRectangle, alignLineRefs[1].isHorizontal);
193
- }
194
- if (drawVertical && alignLineRefs[2].alignRectangles.length) {
195
- const topRectangle = alignLineRefs[2].alignRectangles.length === 1
196
- ? alignLineRefs[2].alignRectangles[0]
197
- : getNearestAlignRectangle(alignLineRefs[2].alignRectangles, activeRectangle);
198
- setAlignLine(alignLineRefs[2].axis, topRectangle, alignLineRefs[2].isHorizontal);
199
- }
200
- if (drawVertical && alignLineRefs[3].alignRectangles.length) {
201
- const bottomRectangle = alignLineRefs[3].alignRectangles.length === 1
202
- ? alignLineRefs[3].alignRectangles[0]
203
- : getNearestAlignRectangle(alignLineRefs[3].alignRectangles, activeRectangle);
204
- setAlignLine(alignLineRefs[3].axis, bottomRectangle, alignLineRefs[3].isHorizontal);
205
- }
206
- return drawAlignLines(this.board, alignLinePoints);
207
- }
208
- handleResizeAlign(resizeAlignOptions) {
209
- const alignG = createG();
210
- let alignLineDelta = this.getEqualLineDelta(resizeAlignOptions);
211
- if (alignLineDelta.deltaX === 0 && alignLineDelta.deltaY === 0) {
212
- alignLineDelta = this.getAlignLineDelta(resizeAlignOptions);
213
- }
214
- const equalLineRef = this.getAlignLineRef(alignLineDelta, resizeAlignOptions);
215
- const equalLinesG = this.drawEqualLines(equalLineRef.activePoints, resizeAlignOptions);
216
- const alignLinesG = this.drawAlignLines(equalLineRef.activePoints, resizeAlignOptions);
217
- alignG.append(equalLinesG, alignLinesG);
218
- return { ...equalLineRef, alignG };
219
- }
220
- }
221
- function getBarPoint(point, isHorizontal) {
222
- return isHorizontal
223
- ? [
224
- [point[0], point[1] - 4],
225
- [point[0], point[1] + 4]
226
- ]
227
- : [
228
- [point[0] - 4, point[1]],
229
- [point[0] + 4, point[1]]
230
- ];
231
- }
232
- function getEqualLinePoints(rectangle, isHorizontal) {
233
- return isHorizontal
234
- ? [
235
- [rectangle.x, rectangle.y - EQUAL_SPACING],
236
- [rectangle.x + rectangle.width, rectangle.y - EQUAL_SPACING]
237
- ]
238
- : [
239
- [rectangle.x - EQUAL_SPACING, rectangle.y],
240
- [rectangle.x - EQUAL_SPACING, rectangle.y + rectangle.height]
241
- ];
242
- }
243
- function drawEqualLines(board, lines) {
244
- const g = createG();
245
- lines.forEach(line => {
246
- if (!line.length)
247
- return;
248
- const yAlign = PlaitBoard.getRoughSVG(board).line(line[0][0], line[0][1], line[1][0], line[1][1], {
249
- stroke: SELECTION_BORDER_COLOR,
250
- strokeWidth: 1
251
- });
252
- g.appendChild(yAlign);
253
- line.forEach(point => {
254
- const barPoint = getBarPoint(point, !!Point.isHorizontal(line[0], line[1]));
255
- const bar = PlaitBoard.getRoughSVG(board).line(barPoint[0][0], barPoint[0][1], barPoint[1][0], barPoint[1][1], {
256
- stroke: SELECTION_BORDER_COLOR,
257
- strokeWidth: 1
258
- });
259
- g.appendChild(bar);
260
- });
261
- });
262
- return g;
263
- }
264
- function drawAlignLines(board, lines) {
265
- const g = createG();
266
- lines.forEach(points => {
267
- if (!points.length)
268
- return;
269
- const xAlign = PlaitBoard.getRoughSVG(board).line(points[0][0], points[0][1], points[1][0], points[1][1], {
270
- stroke: SELECTION_BORDER_COLOR,
271
- strokeWidth: 1,
272
- strokeLineDash: [4, 4]
273
- });
274
- g.appendChild(xAlign);
275
- });
276
- return g;
277
- }
278
- export const getTripleAlignAxis = (rectangle, isHorizontal) => {
279
- const axis = isHorizontal ? 'x' : 'y';
280
- const side = isHorizontal ? 'width' : 'height';
281
- return [rectangle[axis], rectangle[axis] + rectangle[side] / 2, rectangle[axis] + rectangle[side]];
282
- };
283
- export const isAlign = (axis, rectangle, isHorizontal) => {
284
- const alignAxis = getTripleAlignAxis(rectangle, isHorizontal);
285
- return alignAxis.includes(axis);
286
- };
287
- export const getClosestDelta = (axis, rectangle, isHorizontal) => {
288
- const alignAxis = getTripleAlignAxis(rectangle, isHorizontal);
289
- const deltas = alignAxis.map(item => item - axis);
290
- const absDeltas = deltas.map(item => Math.abs(item));
291
- const index = absDeltas.indexOf(Math.min(...absDeltas));
292
- return deltas[index];
293
- };
294
- function getMinAlignDelta(alignRectangles, axis, isHorizontal) {
295
- let delta = ALIGN_TOLERANCE;
296
- alignRectangles.forEach(item => {
297
- const distance = getClosestDelta(axis, item, isHorizontal);
298
- if (Math.abs(distance) < Math.abs(delta)) {
299
- delta = distance;
300
- }
301
- });
302
- return delta;
303
- }
304
- function getNearestAlignRectangle(alignRectangles, activeRectangle) {
305
- let minDistance = Infinity;
306
- let nearestRectangle = alignRectangles[0];
307
- alignRectangles.forEach(item => {
308
- const distance = Math.sqrt(Math.pow(activeRectangle.x - item.x, 2) + Math.pow(activeRectangle.y - item.y, 2));
309
- if (distance < minDistance) {
310
- minDistance = distance;
311
- nearestRectangle = item;
312
- }
313
- });
314
- return nearestRectangle;
315
- }
316
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVzaXplLWFsaWduLXJlYWN0aW9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vcGFja2FnZXMvZHJhdy9zcmMvdXRpbHMvcmVzaXplLWFsaWduLXJlYWN0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sRUFFSCxVQUFVLEVBRVYsS0FBSyxFQUNMLGVBQWUsRUFDZixzQkFBc0IsRUFDdEIsT0FBTyxFQUNQLFlBQVksRUFDZixNQUFNLGFBQWEsQ0FBQztBQUNyQixPQUFPLEVBQUUsYUFBYSxFQUFFLDZCQUE2QixFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFvQzNGLE1BQU0sZUFBZSxHQUFHLENBQUMsQ0FBQztBQUUxQixNQUFNLGFBQWEsR0FBRyxFQUFFLENBQUM7QUFFekIsTUFBTSxhQUFhLEdBQUcsRUFBRSxDQUFDO0FBRXpCLE1BQU0sT0FBTyxtQkFBbUI7SUFHNUIsWUFBb0IsS0FBaUIsRUFBVSxjQUE4QjtRQUF6RCxVQUFLLEdBQUwsS0FBSyxDQUFZO1FBQVUsbUJBQWMsR0FBZCxjQUFjLENBQWdCO1FBQ3pFLElBQUksQ0FBQyxlQUFlLEdBQUcsSUFBSSxDQUFDLGlCQUFpQixFQUFFLENBQUM7SUFDcEQsQ0FBQztJQUVELGlCQUFpQjtRQUNiLE1BQU0sUUFBUSxHQUFHLFlBQVksQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFO1lBQ3RDLEtBQUssRUFBRSxPQUFPLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsRUFBRSxLQUFLLE9BQU8sQ0FBQyxFQUFFLENBQUM7WUFDMUcsU0FBUyxFQUFFLEdBQUcsRUFBRSxDQUFDLEtBQUs7WUFDdEIsU0FBUyxFQUFFLEtBQUs7U0FDbkIsQ0FBQyxDQUFDO1FBQ0gsT0FBTyxRQUFRLENB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QUFFLENBQUM7WUFDekIsV0FBVyxHQUFHLFFBQVEsQ0FBQztZQUN2QixnQkFBZ0IsR0FBRyxJQUFJLENBQUM7UUFDNUIsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0lBQ0gsT0FBTyxnQkFBZ0IsQ0FBQztBQUM1QixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgUmVzaXplU3RhdGUgfSBmcm9tICdAcGxhaXQvY29tbW9uJztcbmltcG9ydCB7XG4gICAgRGlyZWN0aW9uRmFjdG9ycyxcbiAgICBQbGFpdEJvYXJkLFxuICAgIFBsYWl0RWxlbWVudCxcbiAgICBQb2ludCxcbiAgICBSZWN0YW5nbGVDbGllbnQsXG4gICAgU0VMRUNUSU9OX0JPUkRFUl9DT0xPUixcbiAgICBjcmVhdGVHLFxuICAgIGZpbmRFbGVtZW50c1xufSBmcm9tICdAcGxhaXQvY29yZSc7XG5pbXBvcnQgeyBnZXRSZXNpemVab29tLCBtb3ZlUG9pbnRCeVpvb21BbmRPcmlnaW5Qb2ludCB9IGZyb20gJy4uL3BsdWdpbnMvd2l0aC1kcmF3LXJlc2l6ZSc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgUmVzaXplQWxpZ25EZWx0YSB7XG4gICAgZGVsdGFYOiBudW1iZXI7XG4gICAgZGVsdGFZOiBudW1iZXI7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQWxpZ25MaW5lUmVmIGV4dGVuZHMgUmVzaXplQWxpZ25EZWx0YSB7XG4gICAgeFpvb206IG51bWJlcjtcbiAgICB5Wm9vbTogbnVtYmVyO1xuICAgIGFjdGl2ZVBvaW50czogUG9pbnRbXTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBSZXNpemVBbGlnblJlZiBleHRlbmRzIEFsaWduTGluZVJlZiB7XG4gICAgYWxpZ25HOiBTVkdHRWxlbWVudDtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBSZXNpemVBbGlnbk9wdGlvbnMge1xuICAgIHJlc2l6ZVN0YXRlOiBSZXNpemVTdGF0ZTtcbiAgICByZXNpemVPcmlnaW5Qb2ludHM6IFBvaW50W107XG4gICAgYWN0aXZlUmVjdGFuZ2xlOiBSZWN0YW5nbGVDbGllbnQ7XG4gICAgZGlyZWN0aW9uRmFjdG9yczogRGlyZWN0aW9uRmFjdG9ycztcbiAgICBvcmlnaW5Qb2ludDogUG9pbnQ7XG4gICAgaGFuZGxlUG9pbnQ6IFBvaW50O1xuICAgIGlzRnJvbUNvcm5lcjogYm9vbGVhbjtcbiAgICBpc0FzcGVjdFJhdGlvOiBib29sZWFuO1xufVxuXG50eXBlIFRyaXBsZUFsaWduQXhpcyA9IFtudW1iZXIsIG51bWJlciwgbnVtYmVyXTtcblxudHlwZSBEcmF3QWxpZ25MaW5lUmVmID0ge1xuICAgIGF4aXM6IG51bWJlcjtcbiAgICBpc0hvcml6b250YWw6IGJvb2xlYW47XG4gICAgYWxpZ25SZWN0YW5nbGVzOiBSZWN0YW5nbGVDbGllbnRbXTtcbn07XG5cbmNvbnN0IEFMSUdOX1RPTEVSQU5DRSA9IDI7XG5cbmNvbnN0IEVRVUFMX1NQQUNJTkcgPSAxMDtcblxuY29uc3QgQUxJR05fU1BBQ0lORyA9IDI0O1xuXG5leHBvcnQgY2xhc3MgUmVzaXplQWxpZ25SZWFjdGlvbiB7XG4gICAgYWxpZ25SZWN0YW5nbGVzOiBSZWN0YW5nbGVDbGllbnRbXTtcblxuICAgIGNvbnN0cnVjdG9yKHByaXZhdGUgYm9hcmQ6IFBsYWl0Qm9hcmQsIHByaXZhdGUgYWN0aXZlRWxlbWVudHM6IFBsYWl0RWxlbWVudFtdKSB7XG4gICAgICAgIHRoaXMuYWxpZ25SZWN0YW5nbGVzID0gdGhpcy5nZXRBbGlnblJlY3RhbmdsZSgpO1xuICAgIH1cblxuICAgIGdldEFsaWduUmVjdGFuZ2xlKCkge1xuICAgICAgICBjb25zdCBlbGVtZW50cyA9IGZpbmRFbGVtZW50cyh0aGlzLmJvYXJkLCB7XG4gICAgICAgICAgICBtYXRjaDogZWxlbWVudCA9PiB0aGlzLmJvYXJkLmlzQWxpZ24oZWxlbWVudCkgJiYgIXRoaXMuYWN0aXZlRWxlbWVudHMuc29tZShpdGVtID0+IGl0ZW0uaWQgPT09IGVsZW1lbnQuaWQpLFxuICAgICAgICAgICAgcmVjdXJzaW9uOiAoKSA9PiBmYWxzZSxcbiAgICAgICAgICAgIGlzUmV2ZXJzZTogZmFsc2VcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBlbGVtZW50cy5tYXAoaXRlbSA9PiB0aGlzLmJvYXJkLmdldFJlY3RhbmdsZShpdGVtKSEpO1xuICAgIH1cblxuICAgIGdldEFsaWduTGluZVJlZihyZXNpemVBbGlnbkRlbHRhOiBSZXNpemVBbGlnbkRlbHRhLCByZXNpemVBbGlnbk9wdGlvbnM6IFJlc2l6ZUFsaWduT3B0aW9ucyk6IEFsaWduTGluZVJlZiB7XG4gICAgICAgIGNvbnN0IHsgZGVsdGFYLCBkZWx0YVkgfSA9IHJlc2l6ZUFsaWduRGVsdGE7XG4gICAgICAgIGNvbnN0IHsgcmVzaXplU3RhdGUsIG9yaWdpblBvaW50LCBoYW5kbGVQb2ludCwgaXNGcm9tQ29ybmVyLCBpc0FzcGVjdFJhdGlvLCByZXNpemVPcmlnaW5Qb2ludHMgfSA9IHJlc2l6ZUFsaWduT3B0aW9ucztcbiAgICAgICAgY29uc3QgbmV3UmVzaXplU3RhdGU6IFJlc2l6ZVN0YXRlID0ge1xuICAgICAgICAgICAgLi4ucmVzaXplU3RhdGUsXG4gICAgICAgICAgICBlbmRQb2ludDogW3Jlc2l6ZVN0YXRlLmVuZFBvaW50WzBdICsgZGVsdGFYLCByZXNpemVTdGF0ZS5lbmRQb2ludFsxXSArIGRlbHRhWV1cbiAgICAgICAgfTtcbiAgICAgICAgY29uc3QgeyB4Wm9vbSwgeVpvb20gfSA9IGdldFJlc2l6ZVpvb20obmV3UmVzaXplU3RhdGUsIG9yaWdpblBvaW50LCBoYW5kbGVQb2ludCwgaXNGcm9tQ29ybmVyLCBpc0FzcGVjdFJhdGlvKTtcbiAgICAgICAgY29uc3QgYWN0aXZlUG9pbnRzID0gcmVzaXplT3JpZ2luUG9pbnRzLm1hcChwID0+IHtcbiAgICAgICAgICAgIHJldHVybiBtb3ZlUG9pbnRCeVpvb21BbmRPcmlnaW5Qb2ludChwLCBvcmlnaW5Qb2ludCwgeFpvb20sIHlab29tKTtcbiAgICAgICAgfSkgYXMgW1BvaW50LCBQb2ludF07XG5cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGRlbHRhWCxcbiAgICAgICAgICAgIGRlbHRhWSxcbiAgICAgICAgICAgIHhab29tLFxuICAgICAgICAgICAgeVpvb20sXG4gICAgICAgICAgICBhY3RpdmVQb2ludHNcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBnZXRFcXVhbExpbmVEZWx0YShyZXNpemVBbGlnbk9wdGlvbnM6IFJlc2l6ZUFsaWduT3B0aW9ucykge1xuICAgICAgICBsZXQgZXF1YWxMaW5lRGVsdGE6IFJlc2l6ZUFsaWduRGVsdGEgPSB7XG4gICAgICAgICAgICBkZWx0YVg6IDAsXG4gICAgICAgICAgICBkZWx0YVk6IDBcbiAgICAgICAgfTtcbiAgICAgICAgY29uc3QgeyBpc0FzcGVjdFJhdGlvLCBhY3RpdmVSZWN0YW5nbGUgfSA9IHJlc2l6ZUFsaWduT3B0aW9ucztcbiAgICAgICAgY29uc3Qgd2lkdGhBbGlnblJlY3RhbmdsZSA9IHRoaXMuYWxpZ25SZWN0YW5nbGVzLmZpbmQoaXRlbSA9PiBNYXRoLmFicyhpdGVtLndpZHRoIC0gYWN0aXZlUmVjdGFuZ2xlLndpZHRoKSA8IEFMSUdOX1RPTEVSQU5DRSk7XG4gICAgICAgIGlmICh3aWR0aEFsaWduUmVjdGFuZ2xlKSB7XG4gICAgICAgICAgICBjb25zdCBkZWx0YVdpZHRoID0gd2lkdGhBbGlnblJlY3RhbmdsZS53aWR0aCAtIGFjdGl2ZVJlY3RhbmdsZS53aWR0aDtcbiAgICAgICAgICAgIGVxdWFsTGluZURlbHRhLmRlbHRhWCA9IGRlbHRhV2lkdGggKiByZXNpemVBbGlnbk9wdGlvbnMuZGlyZWN0aW9uRmFjdG9yc1swXTtcbiAgICAgICAgICAgIGlmIChpc0FzcGVjdFJhdGlvKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgZGVsdGFIZWlnaHQgPSBkZWx0YVdpZHRoIC8gKGFjdGl2ZVJlY3RhbmdsZS53aWR0aCAvIGFjdGl2ZVJlY3RhbmdsZS5oZWlnaHQpO1xuICAgICAgICAgICAgICAgIGVxdWFsTGluZURlbHRhLmRlbHRhWSA9IGRlbHRhSGVpZ2h0ICogcmVzaXplQWxpZ25PcHRpb25zLmRpcmVjdGlvbkZhY3RvcnNbMV07XG4gICAgICAgICAgICAgICAgcmV0dXJuIGVxdWFsTGluZURlbHRhO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGhlaWdodEFsaWduUmVjdGFuZ2xlID0gdGhpcy5hbGlnblJlY3RhbmdsZXMuZmluZChpdGVtID0+IE1hdGguYWJzKGl0ZW0uaGVpZ2h0IC0gYWN0aXZlUmVjdGFuZ2xlLmhlaWdodCkgPCBBTElHTl9UT0xFUkFOQ0UpO1xuICAgICAgICBpZiAoaGVpZ2h0QWxpZ25SZWN0YW5nbGUpIHtcbiAgICAgICAgICAgIGNvbnN0IGRlbHRhSGVpZ2h0ID0gaGVpZ2h0QWxpZ25SZWN0YW5nbGUuaGVpZ2h0IC0gYWN0aXZlUmVjdGFuZ2xlLmhlaWdodDtcbiAgICAgICAgICAgIGVxdWFsTGluZURlbHRhLmRlbHRhWSA9IGRlbHRhSGVpZ2h0ICogcmVzaXplQWxpZ25PcHRpb25zLmRpcmVjdGlvbkZhY3RvcnNbMV07XG4gICAgICAgICAgICBpZiAoaXNBc3BlY3RSYXRpbykge1xuICAgICAgICAgICAgICAgIGNvbnN0IGRlbHRhV2lkdGggPSBkZWx0YUhlaWdodCAqIChhY3RpdmVSZWN0YW5nbGUud2lkdGggLyBhY3RpdmVSZWN0YW5nbGUuaGVpZ2h0KTtcbiAgICAgICAgICAgICAgICBlcXVhbExpbmVEZWx0YS5kZWx0YVggPSBkZWx0YVdpZHRoICogcmVzaXplQWxpZ25PcHRpb25zLmRpcmVjdGlvbkZhY3RvcnNbMF07XG4gICAgICAgICAgICAgICAgcmV0dXJuIGVxdWFsTGluZURlbHRhO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBlcXVhbExpbmVEZWx0YTtcbiAgICB9XG5cbiAgICBkcmF3RXF1YWxMaW5lcyhhY3RpdmVQb2ludHM6IFBvaW50W10sIHJlc2l6ZUFsaWduT3B0aW9uczogUmVzaXplQWxpZ25PcHRpb25zKSB7XG4gICAgICAgIGxldCB3aWR0aEVxdWFsUG9pbnRzID0gW107XG4gICAgICAgIGxldCBoZWlnaHRFcXVhbFBvaW50cyA9IFtdO1xuXG4gICAgICAgIGNvbnN0IGRyYXdIb3Jpem9udGFsTGluZSA9IHJlc2l6ZUFsaWduT3B0aW9ucy5kaXJlY3Rpb25GYWN0b3JzWzBdICE9PSAwIHx8IHJlc2l6ZUFsaWduT3B0aW9ucy5pc0FzcGVjdFJhdGlvO1xuICAgICAgICBjb25zdCBkcmF3VmVydGljYWxMaW5lID0gcmVzaXplQWxpZ25PcHRpb25zLmRpcmVjdGlvbkZhY3RvcnNbMV0gIT09IDAgfHwgcmVzaXplQWxpZ25PcHRpb25zLmlzQXNwZWN0UmF0aW87XG5cbiAgICAgICAgY29uc3QgYWN0aXZlUmVjdGFuZ2xlID0gUmVjdGFuZ2xlQ2xpZW50LmdldFJlY3RhbmdsZUJ5UG9pbnRzKGFjdGl2ZVBvaW50cyk7XG4gICAgICAgIGZvciAobGV0IGFsaWduUmVjdGFuZ2xlIG9mIHRoaXMuYWxpZ25SZWN0YW5nbGVzKSB7XG4gICAgICAgICAgICBpZiAoYWN0aXZlUmVjdGFuZ2xlLndpZHRoID09PSBhbGlnblJlY3RhbmdsZS53aWR0aCAmJiBkcmF3SG9yaXpvbnRhbExpbmUpIHtcbiAgICAgICAgICAgICAgICB3aWR0aEVxdWFsUG9pbnRzLnB1c2goZ2V0RXF1YWxMaW5lUG9pbnRzKGFsaWduUmVjdGFuZ2xlLCB0cnVlKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoYWN0aXZlUmVjdGFuZ2xlLmhlaWdodCA9PT0gYWxpZ25SZWN0YW5nbGUuaGVpZ2h0ICYmIGRyYXdWZXJ0aWNhbExpbmUpIHtcbiAgICAgICAgICAgICAgICBoZWlnaHRFcXVhbFBvaW50cy5wdXNoKGdldEVxdWFsTGluZVBvaW50cyhhbGlnblJlY3RhbmdsZSwgZmFsc2UpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAod2lkdGhFcXVhbFBvaW50cy5sZW5ndGggJiYgZHJhd0hvcml6b250YWxMaW5lKSB7XG4gICAgICAgICAgICB3aWR0aEVxdWFsUG9pbnRzLnB1c2goZ2V0RXF1YWxMaW5lUG9pbnRzKGFjdGl2ZVJlY3RhbmdsZSwgdHJ1ZSkpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChoZWlnaHRFcXVhbFBvaW50cy5sZW5ndGggJiYgZHJhd1ZlcnRpY2FsTGluZSkge1xuICAgICAgICAgICAgaGVpZ2h0RXF1YWxQb2ludHMucHVzaChnZXRFcXVhbExpbmVQb2ludHMoYWN0aXZlUmVjdGFuZ2xlLCBmYWxzZSkpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgZXF1YWxMaW5lUG9pbnRzID0gWy4uLndpZHRoRXF1YWxQb2ludHMsIC4uLmhlaWdodEVxdWFsUG9pbnRzXTtcbiAgICAgICAgcmV0dXJuIGRyYXdFcXVhbExpbmVzKHRoaXMuYm9hcmQsIGVxdWFsTGluZVBvaW50cyk7XG4gICAgfVxuXG4gICAgZ2V0QWxpZ25MaW5lRGVsdGEocmVzaXplQWxpZ25PcHRpb25zOiBSZXNpemVBbGlnbk9wdGlvbnMpIHtcbiAgICAgICAgbGV0IGFsaWduTGluZURlbHRhOiBSZXNpemVBbGlnbkRlbHRhID0ge1xuICAgICAgICAgICAgZGVsdGFYOiAwLFxuICAgICAgICAgICAgZGVsdGFZOiAwXG4gICAgICAgIH07XG4gICAgICAgIGNvbnN0IHsgaXNBc3BlY3RSYXRpbywgYWN0aXZlUmVjdGFuZ2xlLCBkaXJlY3Rpb25GYWN0b3JzIH0gPSByZXNpemVBbGlnbk9wdGlvbnM7XG4gICAgICAgIGNvbnN0IGRyYXdIb3Jpem9udGFsID0gZGlyZWN0aW9uRmFjdG9yc1swXSAhPT0gMCB8fCBpc0FzcGVjdFJhdGlvO1xuICAgICAgICBjb25zdCBkcmF3VmVydGljYWwgPSBkaXJlY3Rpb25GYWN0b3JzWzFdICE9PSAwIHx8IGlzQXNwZWN0UmF0aW87XG5cbiAgICAgICAgaWYgKGRyYXdIb3Jpem9udGFsKSB7XG4gICAgICAgICAgICBjb25zdCB4QWxpZ25BeGlzID0gZ2V0VHJpcGxlQWxpZ25BeGlzKGFjdGl2ZVJlY3RhbmdsZSwgdHJ1ZSk7XG4gICAgICAgICAgICBjb25zdCBhbGlnblggPSBkaXJlY3Rpb25GYWN0b3JzWzBdID09PSAtMSA/IHhBbGlnbkF4aXNbMF0gOiB4QWxpZ25BeGlzWzJdO1xuICAgICAgICAgICAgY29uc3QgZGVsdGFYID0gZ2V0TWluQWxpZ25EZWx0YSh0aGlzLmFsaWduUmVjdGFuZ2xlcywgYWxpZ25YLCB0cnVlKTtcbiAgICAgICAgICAgIGlmIChNYXRoLmFicyhkZWx0YVgpIDwgQUxJR05fVE9MRVJBTkNFKSB7XG4gICAgICAgICAgICAgICAgYWxpZ25MaW5lRGVsdGEuZGVsdGFYID0gZGVsdGFYO1xuICAgICAgICAgICAgICAgIGlmIChhbGlnbkxpbmVEZWx0YS5kZWx0YVggIT09IDAgJiYgaXNBc3BlY3RSYXRpbykge1xuICAgICAgICAgICAgICAgICAgICBhbGlnbkxpbmVEZWx0YS5kZWx0YVkgPSBhbGlnbkxpbmVEZWx0YS5kZWx0YVggLyAoYWN0aXZlUmVjdGFuZ2xlLndpZHRoIC8gYWN0aXZlUmVjdGFuZ2xlLmhlaWdodCk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBhbGlnbkxpbmVEZWx0YTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZHJhd1ZlcnRpY2FsKSB7XG4gICAgICAgICAgICBjb25zdCB5QWxpZ25BeGlzID0gZ2V0VHJpcGxlQWxpZ25BeGlzKGFjdGl2ZVJlY3RhbmdsZSwgZmFsc2UpO1xuICAgICAgICAgICAgY29uc3QgYWxpZ25ZID0gZGlyZWN0aW9uRmFjdG9yc1sxXSA9PT0gLTEgPyB5QWxpZ25BeGlzWzBdIDogeUFsaWduQXhpc1syXTtcbiAgICAgICAgICAgIGNvbnN0IGRlbHRhWSA9IGdldE1pbkFsaWduRGVsdGEodGhpcy5hbGlnblJlY3RhbmdsZXMsIGFsaWduWSwgZmFsc2UpO1xuICAgICAgICAgICAgaWYgKE1hdGguYWJzKGRlbHRhWSkgPCBBTElHTl9UT0xFUkFOQ0UpIHtcbiAgICAgICAgICAgICAgICBhbGlnbkxpbmVEZWx0YS5kZWx0YVkgPSBkZWx0YVk7XG4gICAgICAgICAgICAgICAgaWYgKGFsaWduTGluZURlbHRhLmRlbHRhWSAhPT0gMCAmJiBpc0FzcGVjdFJhdGlvKSB7XG4gICAgICAgICAgICAgICAgICAgIGFsaWduTGluZURlbHRhLmRlbHRhWCA9IGFsaWduTGluZURlbHRhLmRlbHRhWSAqIChhY3RpdmVSZWN0YW5nbGUud2lkdGggLyBhY3RpdmVSZWN0YW5nbGUuaGVpZ2h0KTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGFsaWduTGluZURlbHRhO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBhbGlnbkxpbmVEZWx0YTtcbiAgICB9XG5cbiAgICBkcmF3QWxpZ25MaW5lcyhhY3RpdmVQb2ludHM6IFBvaW50W10sIHJlc2l6ZUFsaWduT3B0aW9uczogUmVzaXplQWxpZ25PcHRpb25zKSB7XG4gICAgICAgIGxldCBhbGlnbkxpbmVQb2ludHM6IFtQb2ludCwgUG9pbnRdW10gPSBbXTtcbiAgICAgICAgY29uc3QgYWN0aXZlUmVjdGFuZ2xlID0gUmVjdGFuZ2xlQ2xpZW50LmdldFJlY3RhbmdsZUJ5UG9pbnRzKGFjdGl2ZVBvaW50cyk7XG4gICAgICAgIGNvbnN0IGFsaWduQXhpc1ggPSBnZXRUcmlwbGVBbGlnbkF4aXMoYWN0aXZlUmVjdGFuZ2xlLCB0cnVlKTtcbiAgICAgICAgY29uc3QgYWxpZ25BeGlzWSA9IGdldFRyaXBsZUFsaWduQXhpcyhhY3RpdmVSZWN0YW5nbGUsIGZhbHNlKTtcbiAgICAgICAgY29uc3QgYWxpZ25MaW5lUmVmczogRHJhd0FsaWduTGluZVJlZltdID0gW1xuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIGF4aXM6IGFsaWduQXhpc1hbMF0sXG4gICAgICAgICAgICAgICAgaXNIb3Jpem9udGFsOiB0cnVlLFxuICAgICAgICAgICAgICAgIGFsaWduUmVjdGFuZ2xlczogW11cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgYXhpczogYWxpZ25BeGlzWFsyXSxcbiAgICAgICAgICAgICAgICBpc0hvcml6b250YWw6IHRydWUsXG4gICAgICAgICAgICAgICAgYWxpZ25SZWN0YW5nbGVzOiBbXVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBheGlzOiBhbGlnbkF4aXNZWzBdLFxuICAgICAgICAgICAgICAgIGlzSG9yaXpvbnRhbDogZmFsc2UsXG4gICAgICAgICAgICAgICAgYWxpZ25SZWN0YW5nbGVzOiBbXVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBheGlzOiBhbGlnbkF4aXNZWzJdLFxuICAgICAgICAgICAgICAgIGlzSG9yaXpvbnRhbDogZmFsc2UsXG4gICAgICAgICAgICAgICAgYWxpZ25SZWN0YW5nbGVzOiBbXVxuICAgICAgICAgICAgfVxuICAgICAgICBdO1xuICAgICAgICBjb25zdCBzZXRBbGlnbkxpbmUgPSAoYXhpczogbnVtYmVyLCBhbGlnblJlY3RhbmdsZTogUmVjdGFuZ2xlQ2xpZW50LCBpc0hvcml6b250YWw6IGJvb2xlYW4pID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGJvdW5kaW5nUmVjdGFuZ2xlID0gUmVjdGFuZ2xlQ2xpZW50LmluZmxhdGUoXG4gICAgICAgICAgICAgICAgUmVjdGFuZ2xlQ2xpZW50LmdldEJvdW5kaW5nUmVjdGFuZ2xlKFthY3RpdmVSZWN0YW5nbGUsIGFsaWduUmVjdGFuZ2xlXSksXG4gICAgICAgICAgICAgICAgQUxJR05fU1BBQ0lOR1xuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGlmIChpc0hvcml6b250YWwpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBwb2ludFN0YXJ0ID0gW2F4aXMsIGJvdW5kaW5nUmVjdGFuZ2xlLnldIGFzIFBvaW50O1xuICAgICAgICAgICAgICAgIGNvbnN0IHBvaW50RW5kID0gW2F4aXMsIGJvdW5kaW5nUmVjdGFuZ2xlLnkgKyBib3VuZGluZ1JlY3RhbmdsZS5oZWlnaHRdIGFzIFBvaW50O1xuICAgICAgICAgICAgICAgIGFsaWduTGluZVBvaW50cy5wdXNoKFtwb2ludFN0YXJ0LCBwb2ludEVuZF0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zdCBwb2ludFN0YXJ0ID0gW2JvdW5kaW5nUmVjdGFuZ2xlLngsIGF4aXNdIGFzIFBvaW50O1xuICAgICAgICAgICAgICAgIGNvbnN0IHBvaW50RW5kID0gW2JvdW5kaW5nUmVjdGFuZ2xlLnggKyBib3VuZGluZ1JlY3RhbmdsZS53aWR0aCwgYXhpc10gYXMgUG9pbnQ7XG4gICAgICAgICAgICAgICAgYWxpZ25MaW5lUG9pbnRzLnB1c2goW3BvaW50U3RhcnQsIHBvaW50RW5kXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgY29uc3QgeyBpc0FzcGVjdFJhdGlvLCBkaXJlY3Rpb25GYWN0b3JzIH0gPSByZXNpemVBbGlnbk9wdGlvbnM7XG4gICAgICAgIGNvbnN0IGRyYXdIb3Jpem9udGFsID0gZGlyZWN0aW9uRmFjdG9yc1swXSAhPT0gMCB8fCBpc0FzcGVjdFJhdGlvO1xuICAgICAgICBjb25zdCBkcmF3VmVydGljYWwgPSBkaXJlY3Rpb25GYWN0b3JzWzFdICE9PSAwIHx8IGlzQXNwZWN0UmF0aW87XG5cbiAgICAgICAgZm9yIChsZXQgaW5kZXggPSAwOyBpbmRleCA8IHRoaXMuYWxpZ25SZWN0YW5nbGVzLmxlbmd0aDsgaW5kZXgrKykge1xuICAgICAgICAgICAgY29uc3QgZWxlbWVudCA9IHRoaXMuYWxpZ25SZWN0YW5nbGVzW2luZGV4XTtcbiAgICAgICAgICAgIGlmIChpc0FsaWduKGFsaWduTGluZVJlZnNbMF0uYXhpcywgZWxlbWVudCwgYWxpZ25MaW5lUmVmc1swXS5pc0hvcml6b250YWwpKSB7XG4gICAgICAgICAgICAgICAgYWxpZ25MaW5lUmVmc1swXS5hbGlnblJlY3RhbmdsZXMucHVzaChlbGVtZW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChpc0FsaWduKGFsaWduTGluZVJlZnNbMV0uYXhpcywgZWxlbWVudCwgYWxpZ25MaW5lUmVmc1sxXS5pc0hvcml6b250YWwpKSB7XG4gICAgICAgICAgICAgICAgYWxpZ25MaW5lUmVmc1sxXS5hbGlnblJlY3RhbmdsZXMucHVzaChlbGVtZW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChpc0FsaWduKGFsaWduTGluZVJlZnNbMl0uYXhpcywgZWxlbWVudCwgYWxpZ25MaW5lUmVmc1syXS5pc0hvcml6b250YWwpKSB7XG4gICAgICAgICAgICAgICAgYWxpZ25MaW5lUmVmc1syXS5hbGlnblJlY3RhbmdsZXMucHVzaChlbGVtZW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChpc0FsaWduKGFsaWduTGluZVJlZnNbM10uYXhpcywgZWxlbWVudCwgYWxpZ25MaW5lUmVmc1szXS5pc0hvcml6b250YWwpKSB7XG4gICAgICAgICAgICAgICAgYWxpZ25MaW5lUmVmc1szXS5hbGlnblJlY3RhbmdsZXMucHVzaChlbGVtZW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChkcmF3SG9yaXpvbnRhbCAmJiBhbGlnbkxpbmVSZWZzWzBdLmFsaWduUmVjdGFuZ2xlcy5sZW5ndGgpIHtcbiAgICAgICAgICAgIGNvbnN0IGxlZnRSZWN0YW5nbGUgPVxuICAgICAgICAgICAgICAgIGFsaWduTGluZVJlZnNbMF0uYWxpZ25SZWN0YW5nbGVzLmxlbmd0aCA9PT0gMVxuICAgICAgICAgICAgICAgICAgICA/IGFsaWduTGluZVJlZnNbMF0uYWxpZ25SZWN0YW5nbGVzWzBdXG4gICAgICAgICAgICAgICAgICAgIDogZ2V0TmVhcmVzdEFsaWduUmVjdGFuZ2xlKGFsaWduTGluZVJlZnNbMF0uYWxpZ25SZWN0YW5nbGVzLCBhY3RpdmVSZWN0YW5nbGUpO1xuICAgICAgICAgICAgc2V0QWxpZ25MaW5lKGFsaWduTGluZVJlZnNbMF0uYXhpcywgbGVmdFJlY3RhbmdsZSwgYWxpZ25MaW5lUmVmc1swXS5pc0hvcml6b250YWwpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGRyYXdIb3Jpem9udGFsICYmIGFsaWduTGluZVJlZnNbMV0uYWxpZ25SZWN0YW5nbGVzLmxlbmd0aCkge1xuICAgICAgICAgICAgY29uc3QgcmlnaHRSZWN0YW5nbGUgPVxuICAgICAgICAgICAgICAgIGFsaWduTGluZVJlZnNbMV0uYWxpZ25SZWN0YW5nbGVzLmxlbmd0aCA9PT0gMVxuICAgICAgICAgICAgICAgICAgICA/IGFsaWduTGluZVJlZnNbMV0uYWxpZ25SZWN0YW5nbGVzWzBdXG4gICAgICAgICAgICAgICAgICAgIDogZ2V0TmVhcmVzdEFsaWduUmVjdGFuZ2xlKGFsaWduTGluZVJlZnNbMV0uYWxpZ25SZWN0YW5nbGVzLCBhY3RpdmVSZWN0YW5nbGUpO1xuICAgICAgICAgICAgc2V0QWxpZ25MaW5lKGFsaWduTGluZVJlZnNbMV0uYXhpcywgcmlnaHRSZWN0YW5nbGUsIGFsaWduTGluZVJlZnNbMV0uaXNIb3Jpem9udGFsKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChkcmF3VmVydGljYWwgJiYgYWxpZ25MaW5lUmVmc1syXS5hbGlnblJlY3RhbmdsZXMubGVuZ3RoKSB7XG4gICAgICAgICAgICBjb25zdCB0b3BSZWN0YW5nbGUgPVxuICAgICAgICAgICAgICAgIGFsaWduTGluZVJlZnNbMl0uYWxpZ25SZWN0YW5nbGVzLmxlbmd0aCA9PT0gMVxuICAgICAgICAgICAgICAgICAgICA/IGFsaWduTGluZVJlZnNbMl0uYWxpZ25SZWN0YW5nbGVzWzBdXG4gICAgICAgICAgICAgICAgICAgIDogZ2V0TmVhcmVzdEFsaWduUmVjdGFuZ2xlKGFsaWduTGluZVJlZnNbMl0uYWxpZ25SZWN0YW5nbGVzLCBhY3RpdmVSZWN0YW5nbGUpO1xuICAgICAgICAgICAgc2V0QWxpZ25MaW5lKGFsaWduTGluZVJlZnNbMl0uYXhpcywgdG9wUmVjdGFuZ2xlLCBhbGlnbkxpbmVSZWZzWzJdLmlzSG9yaXpvbnRhbCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZHJhd1ZlcnRpY2FsICYmIGFsaWduTGluZVJlZnNbM10uYWxpZ25SZWN0YW5nbGVzLmxlbmd0aCkge1xuICAgICAgICAgICAgY29uc3QgYm90dG9tUmVjdGFuZ2xlID1cbiAgICAgICAgICAgICAgICBhbGlnbkxpbmVSZWZzWzNdLmFsaWduUmVjdGFuZ2xlcy5sZW5ndGggPT09IDFcbiAgICAgICAgICAgICAgICAgICAgPyBhbGlnbkxpbmVSZWZzWzNdLmFsaWduUmVjdGFuZ2xlc1swXVxuICAgICAgICAgICAgICAgICAgICA6IGdldE5lYXJlc3RBbGlnblJlY3RhbmdsZShhbGlnbkxpbmVSZWZzWzNdLmFsaWduUmVjdGFuZ2xlcywgYWN0aXZlUmVjdGFuZ2xlKTtcbiAgICAgICAgICAgIHNldEFsaWduTGluZShhbGlnbkxpbmVSZWZzWzNdLmF4aXMsIGJvdHRvbVJlY3RhbmdsZSwgYWxpZ25MaW5lUmVmc1szXS5pc0hvcml6b250YWwpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGRyYXdBbGlnbkxpbmVzKHRoaXMuYm9hcmQsIGFsaWduTGluZVBvaW50cyk7XG4gICAgfVxuXG4gICAgaGFuZGxlUmVzaXplQWxpZ24ocmVzaXplQWxpZ25PcHRpb25zOiBSZXNpemVBbGlnbk9wdGlvbnMpOiBSZXNpemVBbGlnblJlZiB7XG4gICAgICAgIGNvbnN0IGFsaWduRyA9IGNyZWF0ZUcoKTtcbiAgICAgICAgbGV0IGFsaWduTGluZURlbHRhID0gdGhpcy5nZXRFcXVhbExpbmVEZWx0YShyZXNpemVBbGlnbk9wdGlvbnMpO1xuICAgICAgICBpZiAoYWxpZ25MaW5lRGVsdGEuZGVsdGFYID09PSAwICYmIGFsaWduTGluZURlbHRhLmRlbHRhWSA9PT0gMCkge1xuICAgICAgICAgICAgYWxpZ25MaW5lRGVsdGEgPSB0aGlzLmdldEFsaWduTGluZURlbHRhKHJlc2l6ZUFsaWduT3B0aW9ucyk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgZXF1YWxMaW5lUmVmID0gdGhpcy5nZXRBbGlnbkxpbmVSZWYoYWxpZ25MaW5lRGVsdGEsIHJlc2l6ZUFsaWduT3B0aW9ucyk7XG4gICAgICAgIGNvbnN0IGVxdWFsTGluZXNHID0gdGhpcy5kcmF3RXF1YWxMaW5lcyhlcXVhbExpbmVSZWYuYWN0aXZlUG9pbnRzLCByZXNpemVBbGlnbk9wdGlvbnMpO1xuICAgICAgICBjb25zdCBhbGlnbkxpbmVzRyA9IHRoaXMuZHJhd0FsaWduTGluZXMoZXF1YWxMaW5lUmVmLmFjdGl2ZVBvaW50cywgcmVzaXplQWxpZ25PcHRpb25zKTtcbiAgICAgICAgYWxpZ25HLmFwcGVuZChlcXVhbExpbmVzRywgYWxpZ25MaW5lc0cpO1xuICAgICAgICByZXR1cm4geyAuLi5lcXVhbExpbmVSZWYsIGFsaWduRyB9O1xuICAgIH1cbn1cblxuZnVuY3Rpb24gZ2V0QmFyUG9pbnQocG9pbnQ6IFBvaW50LCBpc0hvcml6b250YWw6IGJvb2xlYW4pIHtcbiAgICByZXR1cm4gaXNIb3Jpem9udGFsXG4gICAgICAgID8gW1xuICAgICAgICAgICAgICBbcG9pbnRbMF0sIHBvaW50WzFdIC0gNF0sXG4gICAgICAgICAgICAgIFtwb2ludFswXSwgcG9pbnRbMV0gKyA0XVxuICAgICAgICAgIF1cbiAgICAgICAgOiBbXG4gICAgICAgICAgICAgIFtwb2ludFswXSAtIDQsIHBvaW50WzFdXSxcbiAgICAgICAgICAgICAgW3BvaW50WzBdICsgNCwgcG9pbnRbMV1dXG4gICAgICAgICAgXTtcbn1cblxuZnVuY3Rpb24gZ2V0RXF1YWxMaW5lUG9pbnRzKHJlY3RhbmdsZTogUmVjdGFuZ2xlQ2xpZW50LCBpc0hvcml6b250YWw6IGJvb2xlYW4pOiBQb2ludFtdIHtcbiAgICByZXR1cm4gaXNIb3Jpem9udGFsXG4gICAgICAgID8gW1xuICAgICAgICAgICAgICBbcmVjdGFuZ2xlLngsIHJlY3RhbmdsZS55IC0gRVFVQUxfU1BBQ0lOR10sXG4gICAgICAgICAgICAgIFtyZWN0YW5nbGUueCArIHJlY3RhbmdsZS53aWR0aCwgcmVjdGFuZ2xlLnkgLSBFUVVBTF9TUEFDSU5HXVxuICAgICAgICAgIF1cbiAgICAgICAgOiBbXG4gICAgICAgICAgICAgIFtyZWN0YW5nbGUueCAtIEVRVUFMX1NQQUNJTkcsIHJlY3RhbmdsZS55XSxcbiAgICAgICAgICAgICAgW3JlY3RhbmdsZS54IC0gRVFVQUxfU1BBQ0lORywgcmVjdGFuZ2xlLnkgKyByZWN0YW5nbGUuaGVpZ2h0XVxuICAgICAgICAgIF07XG59XG5cbmZ1bmN0aW9uIGRyYXdFcXVhbExpbmVzKGJvYXJkOiBQbGFpdEJvYXJkLCBsaW5lczogUG9pbnRbXVtdKSB7XG4gICAgY29uc3QgZyA9IGNyZWF0ZUcoKTtcbiAgICBsaW5lcy5mb3JFYWNoKGxpbmUgPT4ge1xuICAgICAgICBpZiAoIWxpbmUubGVuZ3RoKSByZXR1cm47XG4gICAgICAgIGNvbnN0IHlBbGlnbiA9IFBsYWl0Qm9hcmQuZ2V0Um91Z2hTVkcoYm9hcmQpLmxpbmUobGluZVswXVswXSwgbGluZVswXVsxXSwgbGluZVsxXVswXSwgbGluZVsxXVsxXSwge1xuICAgICAgICAgICAgc3Ryb2tlOiBTRUxFQ1RJT05fQk9SREVSX0NPTE9SLFxuICAgICAgICAgICAgc3Ryb2tlV2lkdGg6IDFcbiAgICAgICAgfSk7XG4gICAgICAgIGcuYXBwZW5kQ2hpbGQoeUFsaWduKTtcbiAgICAgICAgbGluZS5mb3JFYWNoKHBvaW50ID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGJhclBvaW50ID0gZ2V0QmFyUG9pbnQocG9pbnQsICEhUG9pbnQuaXNIb3Jpem9udGFsKGxpbmVbMF0sIGxpbmVbMV0pKTtcbiAgICAgICAgICAgIGNvbnN0IGJhciA9IFBsYWl0Qm9hcmQuZ2V0Um91Z2hTVkcoYm9hcmQpLmxpbmUoYmFyUG9pbnRbMF1bMF0sIGJhclBvaW50WzBdWzFdLCBiYXJQb2ludFsxXVswXSwgYmFyUG9pbnRbMV1bMV0sIHtcbiAgICAgICAgICAgICAgICBzdHJva2U6IFNFTEVDVElPTl9CT1JERVJfQ09MT1IsXG4gICAgICAgICAgICAgICAgc3Ryb2tlV2lkdGg6IDFcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgZy5hcHBlbmRDaGlsZChiYXIpO1xuICAgICAgICB9KTtcbiAgICB9KTtcbiAgICByZXR1cm4gZztcbn1cblxuZnVuY3Rpb24gZHJhd0FsaWduTGluZXMoYm9hcmQ6IFBsYWl0Qm9hcmQsIGxpbmVzOiBbUG9pbnQsIFBvaW50XVtdKSB7XG4gICAgY29uc3QgZyA9IGNyZWF0ZUcoKTtcbiAgICBsaW5lcy5mb3JFYWNoKHBvaW50cyA9PiB7XG4gICAgICAgIGlmICghcG9pbnRzLmxlbmd0aCkgcmV0dXJuO1xuICAgICAgICBjb25zdCB4QWxpZ24gPSBQbGFpdEJvYXJkLmdldFJvdWdoU1ZHKGJvYXJkKS5saW5lKHBvaW50c1swXVswXSwgcG9pbnRzWzBdWzFdLCBwb2ludHNbMV1bMF0sIHBvaW50c1sxXVsxXSwge1xuICAgICAgICAgICAgc3Ryb2tlOiBTRUxFQ1RJT05fQk9SREVSX0NPTE9SLFxuICAgICAgICAgICAgc3Ryb2tlV2lkdGg6IDEsXG4gICAgICAgICAgICBzdHJva2VMaW5lRGFzaDogWzQsIDRdXG4gICAgICAgIH0pO1xuICAgICAgICBnLmFwcGVuZENoaWxkKHhBbGlnbik7XG4gICAgfSk7XG4gICAgcmV0dXJuIGc7XG59XG5cbmV4cG9ydCBjb25zdCBnZXRUcmlwbGVBbGlnbkF4aXMgPSAocmVjdGFuZ2xlOiBSZWN0YW5nbGVDbGllbnQsIGlzSG9yaXpvbnRhbDogYm9vbGVhbik6IFRyaXBsZUFsaWduQXhpcyA9PiB7XG4gICAgY29uc3QgYXhpcyA9IGlzSG9yaXpvbnRhbCA/ICd4JyA6ICd5JztcbiAgICBjb25zdCBzaWRlID0gaXNIb3Jpem9udGFsID8gJ3dpZHRoJyA6ICdoZWlnaHQnO1xuICAgIHJldHVybiBbcmVjdGFuZ2xlW2F4aXNdLCByZWN0YW5nbGVbYXhpc10gKyByZWN0YW5nbGVbc2lkZV0gLyAyLCByZWN0YW5nbGVbYXhpc10gKyByZWN0YW5nbGVbc2lkZV1dO1xufTtcblxuZXhwb3J0IGNvbnN0IGlzQWxpZ24gPSAoYXhpczogbnVtYmVyLCByZWN0YW5nbGU6IFJlY3RhbmdsZUNsaWVudCwgaXNIb3Jpem9udGFsOiBib29sZWFuKSA9PiB7XG4gICAgY29uc3QgYWxpZ25BeGlzID0gZ2V0VHJpcGxlQWxpZ25BeGlzKHJlY3RhbmdsZSwgaXNIb3Jpem9udGFsKTtcbiAgICByZXR1cm4gYWxpZ25BeGlzLmluY2x1ZGVzKGF4aXMpO1xufTtcblxuZXhwb3J0IGNvbnN0IGdldENsb3Nlc3REZWx0YSA9IChheGlzOiBudW1iZXIsIHJlY3RhbmdsZTogUmVjdGFuZ2xlQ2xpZW50LCBpc0hvcml6b250YWw6IGJvb2xlYW4pID0+IHtcbiAgICBjb25zdCBhbGlnbkF4aXMgPSBnZXRUcmlwbGVBbGlnbkF4aXMocmVjdGFuZ2xlLCBpc0hvcml6b250YWwpO1xuICAgIGNvbnN0IGRlbHRhcyA9IGFsaWduQXhpcy5tYXAoaXRlbSA9PiBpdGVtIC0gYXhpcyk7XG4gICAgY29uc3QgYWJzRGVsdGFzID0gZGVsdGFzLm1hcChpdGVtID0+IE1hdGguYWJzKGl0ZW0pKTtcbiAgICBjb25zdCBpbmRleCA9IGFic0RlbHRhcy5pbmRleE9mKE1hdGgubWluKC4uLmFic0RlbHRhcykpO1xuICAgIHJldHVybiBkZWx0YXNbaW5kZXhdO1xufTtcblxuZnVuY3Rpb24gZ2V0TWluQWxpZ25EZWx0YShhbGlnblJlY3RhbmdsZXM6IFJlY3RhbmdsZUNsaWVudFtdLCBheGlzOiBudW1iZXIsIGlzSG9yaXpvbnRhbDogYm9vbGVhbikge1xuICAgIGxldCBkZWx0YSA9IEFMSUdOX1RPTEVSQU5DRTtcblxuICAgIGFsaWduUmVjdGFuZ2xlcy5mb3JFYWNoKGl0ZW0gPT4ge1xuICAgICAgICBjb25zdCBkaXN0YW5jZSA9IGdldENsb3Nlc3REZWx0YShheGlzLCBpdGVtLCBpc0hvcml6b250YWwpO1xuICAgICAgICBpZiAoTWF0aC5hYnMoZGlzdGFuY2UpIDwgTWF0aC5hYnMoZGVsdGEpKSB7XG4gICAgICAgICAgICBkZWx0YSA9IGRpc3RhbmNlO1xuICAgICAgICB9XG4gICAgfSk7XG4gICAgcmV0dXJuIGRlbHRhO1xufVxuXG5mdW5jdGlvbiBnZXROZWFyZXN0QWxpZ25SZWN0YW5nbGUoYWxpZ25SZWN0YW5nbGVzOiBSZWN0YW5nbGVDbGllbnRbXSwgYWN0aXZlUmVjdGFuZ2xlOiBSZWN0YW5nbGVDbGllbnQpIHtcbiAgICBsZXQgbWluRGlzdGFuY2UgPSBJbmZpbml0eTtcbiAgICBsZXQgbmVhcmVzdFJlY3RhbmdsZSA9IGFsaWduUmVjdGFuZ2xlc1swXTtcblxuICAgIGFsaWduUmVjdGFuZ2xlcy5mb3JFYWNoKGl0ZW0gPT4ge1xuICAgICAgICBjb25zdCBkaXN0YW5jZSA9IE1hdGguc3FydChNYXRoLnBvdyhhY3RpdmVSZWN0YW5nbGUueCAtIGl0ZW0ueCwgMikgKyBNYXRoLnBvdyhhY3RpdmVSZWN0YW5nbGUueSAtIGl0ZW0ueSwgMikpO1xuICAgICAgICBpZiAoZGlzdGFuY2UgPCBtaW5EaXN0YW5jZSkge1xuICAgICAgICAgICAgbWluRGlzdGFuY2UgPSBkaXN0YW5jZTtcbiAgICAgICAgICAgIG5lYXJlc3RSZWN0YW5nbGUgPSBpdGVtO1xuICAgICAgICB9XG4gICAgfSk7XG4gICAgcmV0dXJuIG5lYXJlc3RSZWN0YW5nbGU7XG59XG4iXX0=