@plait/draw 0.54.0 → 0.55.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 (48) hide show
  1. package/constants/geometry.d.ts +22 -0
  2. package/engines/basic-shapes/circle.d.ts +8 -0
  3. package/engines/basic-shapes/cloud.d.ts +2 -0
  4. package/engines/flowchart/off-page.d.ts +4 -0
  5. package/engines/flowchart/or.d.ts +2 -0
  6. package/engines/flowchart/predefined-process.d.ts +2 -0
  7. package/engines/flowchart/summing-junction.d.ts +2 -0
  8. package/esm2022/constants/geometry.mjs +12 -2
  9. package/esm2022/engines/basic-shapes/circle.mjs +51 -0
  10. package/esm2022/engines/basic-shapes/cloud.mjs +57 -0
  11. package/esm2022/engines/basic-shapes/ellipse.mjs +3 -41
  12. package/esm2022/engines/flowchart/off-page.mjs +32 -0
  13. package/esm2022/engines/flowchart/or.mjs +25 -0
  14. package/esm2022/engines/flowchart/predefined-process.mjs +47 -0
  15. package/esm2022/engines/flowchart/summing-junction.mjs +28 -0
  16. package/esm2022/engines/index.mjs +12 -2
  17. package/esm2022/geometry.component.mjs +7 -8
  18. package/esm2022/image.component.mjs +6 -7
  19. package/esm2022/interfaces/element.mjs +2 -1
  20. package/esm2022/interfaces/geometry.mjs +6 -1
  21. package/esm2022/line.component.mjs +8 -9
  22. package/esm2022/plugins/with-draw-fragment.mjs +7 -7
  23. package/esm2022/plugins/with-draw-hotkey.mjs +1 -1
  24. package/esm2022/plugins/with-draw-resize.mjs +23 -23
  25. package/esm2022/plugins/with-draw-rotate.mjs +127 -0
  26. package/esm2022/plugins/with-draw.mjs +3 -2
  27. package/esm2022/plugins/with-geometry-create.mjs +21 -5
  28. package/esm2022/plugins/with-geometry-resize.mjs +15 -14
  29. package/esm2022/plugins/with-line-auto-complete.mjs +4 -3
  30. package/esm2022/utils/geometry.mjs +5 -2
  31. package/esm2022/utils/line/line-basic.mjs +6 -3
  32. package/esm2022/utils/position/geometry.mjs +10 -2
  33. package/esm2022/utils/snap-resizing.mjs +185 -0
  34. package/esm2022/utils/style/stroke.mjs +9 -2
  35. package/fesm2022/plait-draw.mjs +1126 -942
  36. package/fesm2022/plait-draw.mjs.map +1 -1
  37. package/geometry.component.d.ts +2 -3
  38. package/image.component.d.ts +2 -3
  39. package/interfaces/element.d.ts +2 -1
  40. package/interfaces/geometry.d.ts +7 -2
  41. package/line.component.d.ts +2 -3
  42. package/package.json +1 -1
  43. package/plugins/with-draw-resize.d.ts +3 -5
  44. package/plugins/with-draw-rotate.d.ts +2 -0
  45. package/utils/position/geometry.d.ts +6 -0
  46. package/utils/snap-resizing.d.ts +25 -0
  47. package/esm2022/utils/resize-snap.mjs +0 -361
  48. package/utils/resize-snap.d.ts +0 -49
@@ -1,4 +1,4 @@
1
- import { ChangeDetectorRef, OnDestroy, OnInit, ViewContainerRef } from '@angular/core';
1
+ import { ChangeDetectorRef, OnDestroy, OnInit } from '@angular/core';
2
2
  import { PlaitBoard, PlaitPluginElementContext, OnContextChanged } from '@plait/core';
3
3
  import { Subject } from 'rxjs';
4
4
  import { PlaitGeometry } from './interfaces/geometry';
@@ -8,14 +8,13 @@ import { ActiveGenerator, CommonPluginElement } from '@plait/common';
8
8
  import { LineAutoCompleteGenerator } from './generators/line-auto-complete.generator';
9
9
  import * as i0 from "@angular/core";
10
10
  export declare class GeometryComponent extends CommonPluginElement<PlaitGeometry, PlaitBoard> implements OnInit, OnDestroy, OnContextChanged<PlaitGeometry, PlaitBoard> {
11
- private viewContainerRef;
12
11
  protected cdr: ChangeDetectorRef;
13
12
  destroy$: Subject<void>;
14
13
  activeGenerator: ActiveGenerator<PlaitGeometry>;
15
14
  lineAutoCompleteGenerator: LineAutoCompleteGenerator;
16
15
  shapeGenerator: GeometryShapeGenerator;
17
16
  get textManage(): TextManage;
18
- constructor(viewContainerRef: ViewContainerRef, cdr: ChangeDetectorRef);
17
+ constructor(cdr: ChangeDetectorRef);
19
18
  initializeGenerator(): void;
20
19
  ngOnInit(): void;
21
20
  onContextChanged(value: PlaitPluginElementContext<PlaitGeometry, PlaitBoard>, previous: PlaitPluginElementContext<PlaitGeometry, PlaitBoard>): void;
@@ -1,4 +1,4 @@
1
- import { ChangeDetectorRef, OnDestroy, OnInit, ViewContainerRef } from '@angular/core';
1
+ import { ChangeDetectorRef, OnDestroy, OnInit } from '@angular/core';
2
2
  import { PlaitBoard, PlaitPluginElementContext, OnContextChanged } from '@plait/core';
3
3
  import { Subject } from 'rxjs';
4
4
  import { CommonPluginElement, ImageGenerator } from '@plait/common';
@@ -6,13 +6,12 @@ import { PlaitImage } from './interfaces/image';
6
6
  import { LineAutoCompleteGenerator } from './generators/line-auto-complete.generator';
7
7
  import * as i0 from "@angular/core";
8
8
  export declare class ImageComponent extends CommonPluginElement<PlaitImage, PlaitBoard> implements OnInit, OnDestroy, OnContextChanged<PlaitImage, PlaitBoard> {
9
- private viewContainerRef;
10
9
  protected cdr: ChangeDetectorRef;
11
10
  destroy$: Subject<void>;
12
11
  get activeGenerator(): import("@plait/common").ActiveGenerator<import("@plait/core").PlaitElement>;
13
12
  imageGenerator: ImageGenerator<PlaitImage>;
14
13
  lineAutoCompleteGenerator: LineAutoCompleteGenerator;
15
- constructor(viewContainerRef: ViewContainerRef, cdr: ChangeDetectorRef);
14
+ constructor(cdr: ChangeDetectorRef);
16
15
  initializeGenerator(): void;
17
16
  ngOnInit(): void;
18
17
  onContextChanged(value: PlaitPluginElementContext<PlaitImage, PlaitBoard>, previous: PlaitPluginElementContext<PlaitImage, PlaitBoard>): void;
@@ -1,6 +1,7 @@
1
1
  export declare enum StrokeStyle {
2
2
  solid = "solid",
3
- dashed = "dashed"
3
+ dashed = "dashed",
4
+ dotted = "dotted"
4
5
  }
5
6
  export declare enum MemorizeKey {
6
7
  basicShape = "basicShape",
@@ -22,7 +22,8 @@ export declare enum BasicShapes {
22
22
  processArrow = "processArrow",
23
23
  twoWayArrow = "twoWayArrow",
24
24
  comment = "comment",
25
- roundComment = "roundComment"
25
+ roundComment = "roundComment",
26
+ cloud = "cloud"
26
27
  }
27
28
  export declare enum FlowchartSymbols {
28
29
  process = "process",
@@ -35,7 +36,11 @@ export declare enum FlowchartSymbols {
35
36
  manualLoop = "manualLoop",
36
37
  merge = "merge",
37
38
  delay = "delay",
38
- storedData = "storedData"
39
+ storedData = "storedData",
40
+ or = "or",
41
+ summingJunction = "summingJunction",
42
+ predefinedProcess = "predefinedProcess",
43
+ offPage = "offPage"
39
44
  }
40
45
  export type GeometryShapes = BasicShapes | FlowchartSymbols;
41
46
  export interface PlaitGeometry extends PlaitElement {
@@ -1,4 +1,4 @@
1
- import { ChangeDetectorRef, OnDestroy, OnInit, ViewContainerRef } from '@angular/core';
1
+ import { ChangeDetectorRef, OnDestroy, OnInit } from '@angular/core';
2
2
  import { PlaitBoard, PlaitPluginElementContext, OnContextChanged } from '@plait/core';
3
3
  import { Subject } from 'rxjs';
4
4
  import { LineText, PlaitGeometry, PlaitLine } from './interfaces';
@@ -12,13 +12,12 @@ interface BoundedElements {
12
12
  target?: PlaitGeometry;
13
13
  }
14
14
  export declare class LineComponent extends CommonPluginElement<PlaitLine, PlaitBoard> implements OnInit, OnDestroy, OnContextChanged<PlaitLine, PlaitBoard> {
15
- private viewContainerRef;
16
15
  protected cdr: ChangeDetectorRef;
17
16
  destroy$: Subject<void>;
18
17
  shapeGenerator: LineShapeGenerator;
19
18
  activeGenerator: LineActiveGenerator;
20
19
  boundedElements: BoundedElements;
21
- constructor(viewContainerRef: ViewContainerRef, cdr: ChangeDetectorRef);
20
+ constructor(cdr: ChangeDetectorRef);
22
21
  initializeGenerator(): void;
23
22
  ngOnInit(): void;
24
23
  getBoundedElements(): BoundedElements;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plait/draw",
3
- "version": "0.54.0",
3
+ "version": "0.55.0",
4
4
  "peerDependencies": {
5
5
  "@angular/common": "^17.2.4",
6
6
  "@angular/core": "^17.2.4",
@@ -1,6 +1,4 @@
1
- import { ResizeRef, ResizeState } from '@plait/common';
2
- import { PlaitBoard, Point } from '@plait/core';
3
- import { PlaitDrawElement } from '../interfaces';
1
+ import { PlaitBoard, Point, RectangleClient } from '@plait/core';
4
2
  export interface BulkRotationRef {
5
3
  angle: number;
6
4
  offsetX: number;
@@ -8,11 +6,11 @@ export interface BulkRotationRef {
8
6
  newCenterPoint: Point;
9
7
  }
10
8
  export declare function withDrawResize(board: PlaitBoard): PlaitBoard;
11
- export declare const getResizeOriginPointAndHandlePoint: (board: PlaitBoard, resizeRef: ResizeRef<PlaitDrawElement | PlaitDrawElement[]>) => {
9
+ export declare const getResizeOriginPointAndHandlePoint: (board: PlaitBoard, handleIndex: number, rectangle: RectangleClient) => {
12
10
  originPoint: Point;
13
11
  handlePoint: Point;
14
12
  };
15
- export declare const getResizeZoom: (resizeState: ResizeState, resizeOriginPoint: Point, resizeHandlePoint: Point, isFromCorner: boolean, isAspectRatio: boolean) => {
13
+ export declare const getResizeZoom: (resizeStartAndEnd: [Point, Point], resizeOriginPoint: Point, resizeHandlePoint: Point, isFromCorner: boolean, isAspectRatio: boolean) => {
16
14
  xZoom: number;
17
15
  yZoom: number;
18
16
  };
@@ -0,0 +1,2 @@
1
+ import { PlaitBoard } from '@plait/core';
2
+ export declare const withDrawRotate: (board: PlaitBoard) => PlaitBoard;
@@ -19,3 +19,9 @@ export declare const getSnappingRef: (board: PlaitBoard, hitElement: PlaitShapeE
19
19
  };
20
20
  export declare const getHitGeometry: (board: PlaitBoard, point: Point, offset?: number) => PlaitGeometry | null;
21
21
  export declare const traverseDrawShapes: (board: PlaitBoard, callback: (element: PlaitShapeElement) => void) => void;
22
+ export declare const getRotateHandleRectangle: (rectangle: RectangleClient) => {
23
+ x: number;
24
+ y: number;
25
+ width: number;
26
+ height: number;
27
+ };
@@ -0,0 +1,25 @@
1
+ import { ResizeRef, ResizeState } from '@plait/common';
2
+ import { DirectionFactors, PlaitBoard, PlaitElement, Point, RectangleClient, SnapRef } from '@plait/core';
3
+ import { PlaitDrawElement } from '../interfaces';
4
+ export declare const debugGenerator: import("@plait/core").DebugGenerator;
5
+ export interface ResizeSnapRef extends SnapRef {
6
+ xZoom: number;
7
+ yZoom: number;
8
+ activePoints: Point[];
9
+ }
10
+ export interface ResizeSnapOptions {
11
+ resizePoints: Point[];
12
+ activeRectangle: RectangleClient;
13
+ directionFactors: DirectionFactors;
14
+ isFromCorner: boolean;
15
+ isAspectRatio: boolean;
16
+ resizeOriginPoint?: Point[];
17
+ originPoint?: Point;
18
+ handlePoint?: Point;
19
+ isCreate?: boolean;
20
+ }
21
+ export declare function getSnapResizingRefOptions(board: PlaitBoard, resizeRef: ResizeRef<PlaitDrawElement | PlaitDrawElement[]>, resizeState: ResizeState, resizeOriginPointAndHandlePoint: {
22
+ originPoint: Point;
23
+ handlePoint: Point;
24
+ }, isAspectRatio: boolean, isFromCorner: boolean): ResizeSnapOptions;
25
+ export declare function getSnapResizingRef(board: PlaitBoard, activeElements: PlaitElement[], resizeSnapOptions: ResizeSnapOptions): ResizeSnapRef;
@@ -1,361 +0,0 @@
1
- import { getDirectionFactorByDirectionComponent, getUnitVectorByPointAndPoint, resetPointsAfterResize } from '@plait/common';
2
- import { PlaitBoard, Point, RectangleClient, SELECTION_BORDER_COLOR, createDebugGenerator, createG, findElements, getSelectionAngle, getRectangleByAngle, getRectangleByElements } from '@plait/core';
3
- import { getResizeZoom, movePointByZoomAndOriginPoint } from '../plugins/with-draw-resize';
4
- const debugKey = 'debug:plait:align-for-geometry';
5
- export const debugGenerator = createDebugGenerator(debugKey);
6
- const ALIGN_TOLERANCE = 2;
7
- const EQUAL_SPACING = 10;
8
- const ALIGN_SPACING = 24;
9
- export class ResizeSnapReaction {
10
- constructor(board, activeElements) {
11
- this.board = board;
12
- this.activeElements = activeElements;
13
- this.alignRectangles = this.getAlignRectangle();
14
- this.angle = getSelectionAngle(activeElements);
15
- }
16
- getAlignRectangle() {
17
- const elements = findElements(this.board, {
18
- match: element => this.board.isAlign(element) && !this.activeElements.some(item => item.id === element.id),
19
- recursion: () => false,
20
- isReverse: false
21
- });
22
- return elements.map(item => getRectangleByAngle(this.board.getRectangle(item), item.angle) || this.board.getRectangle(item));
23
- }
24
- getSnapRef(resizeAlignDelta, resizeSnapOptions) {
25
- const { deltaX, deltaY } = resizeAlignDelta;
26
- const { resizeState, originPoint, handlePoint, isFromCorner, isAspectRatio, resizeOriginPoints } = resizeSnapOptions;
27
- const newResizeState = {
28
- ...resizeState,
29
- endPoint: [resizeState.endPoint[0] + deltaX, resizeState.endPoint[1] + deltaY]
30
- };
31
- const { xZoom, yZoom } = getResizeZoom(newResizeState, originPoint, handlePoint, isFromCorner, isAspectRatio);
32
- let activePoints = resizeOriginPoints.map(p => {
33
- return movePointByZoomAndOriginPoint(p, originPoint, xZoom, yZoom);
34
- });
35
- if (this.angle) {
36
- activePoints = resetPointsAfterResize(RectangleClient.getRectangleByPoints(resizeOriginPoints), RectangleClient.getRectangleByPoints(activePoints), RectangleClient.getCenterPoint(RectangleClient.getRectangleByPoints(resizeOriginPoints)), RectangleClient.getCenterPoint(RectangleClient.getRectangleByPoints(activePoints)), this.angle);
37
- }
38
- return {
39
- deltaX,
40
- deltaY,
41
- xZoom,
42
- yZoom,
43
- activePoints
44
- };
45
- }
46
- getEqualLineDelta(resizeSnapOptions) {
47
- let equalLineDelta = {
48
- deltaX: 0,
49
- deltaY: 0
50
- };
51
- const { isAspectRatio, activeRectangle } = resizeSnapOptions;
52
- const widthAlignRectangle = this.alignRectangles.find(item => Math.abs(item.width - activeRectangle.width) < ALIGN_TOLERANCE);
53
- if (widthAlignRectangle) {
54
- const deltaWidth = widthAlignRectangle.width - activeRectangle.width;
55
- equalLineDelta.deltaX = deltaWidth * resizeSnapOptions.directionFactors[0];
56
- if (isAspectRatio) {
57
- const deltaHeight = deltaWidth / (activeRectangle.width / activeRectangle.height);
58
- equalLineDelta.deltaY = deltaHeight * resizeSnapOptions.directionFactors[1];
59
- return equalLineDelta;
60
- }
61
- }
62
- const heightAlignRectangle = this.alignRectangles.find(item => Math.abs(item.height - activeRectangle.height) < ALIGN_TOLERANCE);
63
- if (heightAlignRectangle) {
64
- const deltaHeight = heightAlignRectangle.height - activeRectangle.height;
65
- equalLineDelta.deltaY = deltaHeight * resizeSnapOptions.directionFactors[1];
66
- if (isAspectRatio) {
67
- const deltaWidth = deltaHeight * (activeRectangle.width / activeRectangle.height);
68
- equalLineDelta.deltaX = deltaWidth * resizeSnapOptions.directionFactors[0];
69
- return equalLineDelta;
70
- }
71
- }
72
- return equalLineDelta;
73
- }
74
- drawEqualLines(activePoints, resizeSnapOptions) {
75
- let widthEqualPoints = [];
76
- let heightEqualPoints = [];
77
- const drawHorizontalLine = resizeSnapOptions.directionFactors[0] !== 0 || resizeSnapOptions.isAspectRatio;
78
- const drawVerticalLine = resizeSnapOptions.directionFactors[1] !== 0 || resizeSnapOptions.isAspectRatio;
79
- const activeRectangle = getRectangleByAngle(RectangleClient.getRectangleByPoints(activePoints), this.angle) ||
80
- RectangleClient.getRectangleByPoints(activePoints);
81
- for (let alignRectangle of this.alignRectangles) {
82
- if (activeRectangle.width === alignRectangle.width && drawHorizontalLine) {
83
- widthEqualPoints.push(getEqualLinePoints(alignRectangle, true));
84
- }
85
- if (activeRectangle.height === alignRectangle.height && drawVerticalLine) {
86
- heightEqualPoints.push(getEqualLinePoints(alignRectangle, false));
87
- }
88
- }
89
- if (widthEqualPoints.length && drawHorizontalLine) {
90
- widthEqualPoints.push(getEqualLinePoints(activeRectangle, true));
91
- }
92
- if (heightEqualPoints.length && drawVerticalLine) {
93
- heightEqualPoints.push(getEqualLinePoints(activeRectangle, false));
94
- }
95
- const equalLinePoints = [...widthEqualPoints, ...heightEqualPoints];
96
- return drawEqualLines(this.board, equalLinePoints);
97
- }
98
- getAlignLineDelta(resizeSnapOptions) {
99
- let alignLineDelta = {
100
- deltaX: 0,
101
- deltaY: 0
102
- };
103
- const { isAspectRatio, activeRectangle, directionFactors } = resizeSnapOptions;
104
- const drawHorizontal = directionFactors[0] !== 0 || isAspectRatio;
105
- const drawVertical = directionFactors[1] !== 0 || isAspectRatio;
106
- if (drawHorizontal) {
107
- const xAlignAxis = getTripleAlignAxis(activeRectangle, true);
108
- const alignX = directionFactors[0] === -1 ? xAlignAxis[0] : xAlignAxis[2];
109
- const deltaX = getMinAlignDelta(this.alignRectangles, alignX, true);
110
- if (Math.abs(deltaX) < ALIGN_TOLERANCE) {
111
- alignLineDelta.deltaX = deltaX;
112
- if (alignLineDelta.deltaX !== 0 && isAspectRatio) {
113
- alignLineDelta.deltaY = alignLineDelta.deltaX / (activeRectangle.width / activeRectangle.height);
114
- return alignLineDelta;
115
- }
116
- }
117
- }
118
- if (drawVertical) {
119
- const yAlignAxis = getTripleAlignAxis(activeRectangle, false);
120
- const alignY = directionFactors[1] === -1 ? yAlignAxis[0] : yAlignAxis[2];
121
- const deltaY = getMinAlignDelta(this.alignRectangles, alignY, false);
122
- if (Math.abs(deltaY) < ALIGN_TOLERANCE) {
123
- alignLineDelta.deltaY = deltaY;
124
- if (alignLineDelta.deltaY !== 0 && isAspectRatio) {
125
- alignLineDelta.deltaX = alignLineDelta.deltaY * (activeRectangle.width / activeRectangle.height);
126
- return alignLineDelta;
127
- }
128
- }
129
- }
130
- return alignLineDelta;
131
- }
132
- drawAlignLines(activePoints, resizeSnapOptions) {
133
- debugGenerator.isDebug() && debugGenerator.clear();
134
- let alignLinePoints = [];
135
- const activeRectangle = getRectangleByAngle(RectangleClient.getRectangleByPoints(activePoints), this.angle) ||
136
- RectangleClient.getRectangleByPoints(activePoints);
137
- debugGenerator.isDebug() && debugGenerator.drawRectangle(this.board, activeRectangle, { stroke: 'green' });
138
- const alignAxisX = getTripleAlignAxis(activeRectangle, true);
139
- const alignAxisY = getTripleAlignAxis(activeRectangle, false);
140
- const alignLineRefs = [
141
- {
142
- axis: alignAxisX[0],
143
- isHorizontal: true,
144
- alignRectangles: []
145
- },
146
- {
147
- axis: alignAxisX[2],
148
- isHorizontal: true,
149
- alignRectangles: []
150
- },
151
- {
152
- axis: alignAxisY[0],
153
- isHorizontal: false,
154
- alignRectangles: []
155
- },
156
- {
157
- axis: alignAxisY[2],
158
- isHorizontal: false,
159
- alignRectangles: []
160
- }
161
- ];
162
- const setAlignLine = (axis, alignRectangle, isHorizontal) => {
163
- const boundingRectangle = RectangleClient.inflate(RectangleClient.getBoundingRectangle([activeRectangle, alignRectangle]), ALIGN_SPACING);
164
- if (isHorizontal) {
165
- const pointStart = [axis, boundingRectangle.y];
166
- const pointEnd = [axis, boundingRectangle.y + boundingRectangle.height];
167
- alignLinePoints.push([pointStart, pointEnd]);
168
- }
169
- else {
170
- const pointStart = [boundingRectangle.x, axis];
171
- const pointEnd = [boundingRectangle.x + boundingRectangle.width, axis];
172
- alignLinePoints.push([pointStart, pointEnd]);
173
- }
174
- };
175
- const { isAspectRatio, directionFactors } = resizeSnapOptions;
176
- const drawHorizontal = directionFactors[0] !== 0 || isAspectRatio;
177
- const drawVertical = directionFactors[1] !== 0 || isAspectRatio;
178
- for (let index = 0; index < this.alignRectangles.length; index++) {
179
- const element = this.alignRectangles[index];
180
- debugGenerator.isDebug() && debugGenerator.drawRectangle(this.board, element);
181
- if (isAlign(alignLineRefs[0].axis, element, alignLineRefs[0].isHorizontal)) {
182
- alignLineRefs[0].alignRectangles.push(element);
183
- }
184
- if (isAlign(alignLineRefs[1].axis, element, alignLineRefs[1].isHorizontal)) {
185
- alignLineRefs[1].alignRectangles.push(element);
186
- }
187
- if (isAlign(alignLineRefs[2].axis, element, alignLineRefs[2].isHorizontal)) {
188
- alignLineRefs[2].alignRectangles.push(element);
189
- }
190
- if (isAlign(alignLineRefs[3].axis, element, alignLineRefs[3].isHorizontal)) {
191
- alignLineRefs[3].alignRectangles.push(element);
192
- }
193
- }
194
- if (drawHorizontal && alignLineRefs[0].alignRectangles.length) {
195
- const leftRectangle = alignLineRefs[0].alignRectangles.length === 1
196
- ? alignLineRefs[0].alignRectangles[0]
197
- : getNearestAlignRectangle(alignLineRefs[0].alignRectangles, activeRectangle);
198
- setAlignLine(alignLineRefs[0].axis, leftRectangle, alignLineRefs[0].isHorizontal);
199
- }
200
- if (drawHorizontal && alignLineRefs[1].alignRectangles.length) {
201
- const rightRectangle = alignLineRefs[1].alignRectangles.length === 1
202
- ? alignLineRefs[1].alignRectangles[0]
203
- : getNearestAlignRectangle(alignLineRefs[1].alignRectangles, activeRectangle);
204
- setAlignLine(alignLineRefs[1].axis, rightRectangle, alignLineRefs[1].isHorizontal);
205
- }
206
- if (drawVertical && alignLineRefs[2].alignRectangles.length) {
207
- const topRectangle = alignLineRefs[2].alignRectangles.length === 1
208
- ? alignLineRefs[2].alignRectangles[0]
209
- : getNearestAlignRectangle(alignLineRefs[2].alignRectangles, activeRectangle);
210
- setAlignLine(alignLineRefs[2].axis, topRectangle, alignLineRefs[2].isHorizontal);
211
- }
212
- if (drawVertical && alignLineRefs[3].alignRectangles.length) {
213
- const bottomRectangle = alignLineRefs[3].alignRectangles.length === 1
214
- ? alignLineRefs[3].alignRectangles[0]
215
- : getNearestAlignRectangle(alignLineRefs[3].alignRectangles, activeRectangle);
216
- setAlignLine(alignLineRefs[3].axis, bottomRectangle, alignLineRefs[3].isHorizontal);
217
- }
218
- return drawAlignLines(this.board, alignLinePoints);
219
- }
220
- handleResizeSnap(resizeSnapOptions) {
221
- const alignG = createG();
222
- let alignLineDelta = this.getEqualLineDelta(resizeSnapOptions);
223
- if (alignLineDelta.deltaX === 0 && alignLineDelta.deltaY === 0) {
224
- alignLineDelta = this.getAlignLineDelta(resizeSnapOptions);
225
- }
226
- const equalLineRef = this.getSnapRef(alignLineDelta, resizeSnapOptions);
227
- const equalLinesG = this.drawEqualLines(equalLineRef.activePoints, resizeSnapOptions);
228
- const alignLinesG = this.drawAlignLines(equalLineRef.activePoints, resizeSnapOptions);
229
- alignG.append(equalLinesG, alignLinesG);
230
- return { ...equalLineRef, alignG };
231
- }
232
- }
233
- function getBarPoint(point, isHorizontal) {
234
- return isHorizontal
235
- ? [
236
- [point[0], point[1] - 4],
237
- [point[0], point[1] + 4]
238
- ]
239
- : [
240
- [point[0] - 4, point[1]],
241
- [point[0] + 4, point[1]]
242
- ];
243
- }
244
- function getEqualLinePoints(rectangle, isHorizontal) {
245
- return isHorizontal
246
- ? [
247
- [rectangle.x, rectangle.y - EQUAL_SPACING],
248
- [rectangle.x + rectangle.width, rectangle.y - EQUAL_SPACING]
249
- ]
250
- : [
251
- [rectangle.x - EQUAL_SPACING, rectangle.y],
252
- [rectangle.x - EQUAL_SPACING, rectangle.y + rectangle.height]
253
- ];
254
- }
255
- function drawEqualLines(board, lines) {
256
- const g = createG();
257
- lines.forEach(line => {
258
- if (!line.length)
259
- return;
260
- const yAlign = PlaitBoard.getRoughSVG(board).line(line[0][0], line[0][1], line[1][0], line[1][1], {
261
- stroke: SELECTION_BORDER_COLOR,
262
- strokeWidth: 1
263
- });
264
- g.appendChild(yAlign);
265
- line.forEach(point => {
266
- const barPoint = getBarPoint(point, !!Point.isHorizontal(line[0], line[1]));
267
- const bar = PlaitBoard.getRoughSVG(board).line(barPoint[0][0], barPoint[0][1], barPoint[1][0], barPoint[1][1], {
268
- stroke: SELECTION_BORDER_COLOR,
269
- strokeWidth: 1
270
- });
271
- g.appendChild(bar);
272
- });
273
- });
274
- return g;
275
- }
276
- function drawAlignLines(board, lines) {
277
- const g = createG();
278
- lines.forEach(points => {
279
- if (!points.length)
280
- return;
281
- const xAlign = PlaitBoard.getRoughSVG(board).line(points[0][0], points[0][1], points[1][0], points[1][1], {
282
- stroke: SELECTION_BORDER_COLOR,
283
- strokeWidth: 1,
284
- strokeLineDash: [4, 4]
285
- });
286
- g.appendChild(xAlign);
287
- });
288
- return g;
289
- }
290
- export const getTripleAlignAxis = (rectangle, isHorizontal) => {
291
- const axis = isHorizontal ? 'x' : 'y';
292
- const side = isHorizontal ? 'width' : 'height';
293
- return [rectangle[axis], rectangle[axis] + rectangle[side] / 2, rectangle[axis] + rectangle[side]];
294
- };
295
- export const isAlign = (axis, rectangle, isHorizontal) => {
296
- const alignAxis = getTripleAlignAxis(rectangle, isHorizontal);
297
- return alignAxis.includes(axis);
298
- };
299
- export const getClosestDelta = (axis, rectangle, isHorizontal) => {
300
- const alignAxis = getTripleAlignAxis(rectangle, isHorizontal);
301
- const deltas = alignAxis.map(item => item - axis);
302
- const absDeltas = deltas.map(item => Math.abs(item));
303
- const index = absDeltas.indexOf(Math.min(...absDeltas));
304
- return deltas[index];
305
- };
306
- function getMinAlignDelta(alignRectangles, axis, isHorizontal) {
307
- let delta = ALIGN_TOLERANCE;
308
- alignRectangles.forEach(item => {
309
- const distance = getClosestDelta(axis, item, isHorizontal);
310
- if (Math.abs(distance) < Math.abs(delta)) {
311
- delta = distance;
312
- }
313
- });
314
- return delta;
315
- }
316
- function getNearestAlignRectangle(alignRectangles, activeRectangle) {
317
- let minDistance = Infinity;
318
- let nearestRectangle = alignRectangles[0];
319
- alignRectangles.forEach(item => {
320
- const distance = Math.sqrt(Math.pow(activeRectangle.x - item.x, 2) + Math.pow(activeRectangle.y - item.y, 2));
321
- if (distance < minDistance) {
322
- minDistance = distance;
323
- nearestRectangle = item;
324
- }
325
- });
326
- return nearestRectangle;
327
- }
328
- export function getResizeSnapRef(board, resizeRef, resizeState, resizeOriginPointAndHandlePoint, isAspectRatio, isFromCorner) {
329
- const { originPoint, handlePoint } = resizeOriginPointAndHandlePoint;
330
- const { xZoom, yZoom } = getResizeZoom(resizeState, originPoint, handlePoint, isFromCorner, isAspectRatio);
331
- let activeElements;
332
- let resizeOriginPoints = [];
333
- if (Array.isArray(resizeRef.element)) {
334
- activeElements = resizeRef.element;
335
- const rectangle = getRectangleByElements(board, resizeRef.element, false);
336
- resizeOriginPoints = RectangleClient.getPoints(rectangle);
337
- }
338
- else {
339
- activeElements = [resizeRef.element];
340
- resizeOriginPoints = resizeRef.element.points;
341
- }
342
- const points = resizeOriginPoints.map(p => {
343
- return movePointByZoomAndOriginPoint(p, originPoint, xZoom, yZoom);
344
- });
345
- const activeRectangle = getRectangleByAngle(RectangleClient.getRectangleByPoints(points), getSelectionAngle(activeElements)) ||
346
- RectangleClient.getRectangleByPoints(points);
347
- const resizeSnapReaction = new ResizeSnapReaction(board, activeElements);
348
- const resizeHandlePoint = movePointByZoomAndOriginPoint(handlePoint, originPoint, xZoom, yZoom);
349
- const [x, y] = getUnitVectorByPointAndPoint(originPoint, resizeHandlePoint);
350
- return resizeSnapReaction.handleResizeSnap({
351
- resizeState,
352
- resizeOriginPoints,
353
- activeRectangle,
354
- originPoint,
355
- handlePoint,
356
- directionFactors: [getDirectionFactorByDirectionComponent(x), getDirectionFactorByDirectionComponent(y)],
357
- isAspectRatio,
358
- isFromCorner
359
- });
360
- }
361
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVzaXplLXNuYXAuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wYWNrYWdlcy9kcmF3L3NyYy91dGlscy9yZXNpemUtc25hcC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBR0gsc0NBQXNDLEVBQ3RDLDRCQUE0QixFQUM1QixzQkFBc0IsRUFDekIsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUVILFVBQVUsRUFFVixLQUFLLEVBQ0wsZUFBZSxFQUNmLHNCQUFzQixFQUN0QixvQkFBb0IsRUFDcEIsT0FBTyxFQUNQLFlBQVksRUFDWixpQkFBaUIsRUFDakIsbUJBQW1CLEVBQ25CLHNCQUFzQixFQUN6QixNQUFNLGFBQWEsQ0FBQztBQUNyQixPQUFPLEVBQUUsYUFBYSxFQUFFLDZCQUE2QixFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFHM0YsTUFBTSxRQUFRLEdBQUcsZ0NBQWdDLENBQUM7QUFDbEQsTUFBTSxDQUFDLE1BQU0sY0FBYyxHQUFHLG9CQUFvQixDQUFDLFFBQVEsQ0FBQyxDQUFDO0FBb0M3RCxNQUFNLGVBQWUsR0FBRyxDQUFDLENBQUM7QUFFMUIsTUFBTSxhQUFhLEdBQUcsRUFBRSxDQUFDO0FBRXpCLE1BQU0sYUFBYSxHQUFHLEVBQUUsQ0FBQztBQUV6QixNQUFNLE9BQU8sa0JBQWtCO0lBSzNCLFlBQW9CLEtBQWlCLEVBQVUsY0FBOEI7UUFBekQsVUFBSyxHQUFMLEtBQUssQ0FBWTtRQUFVLG1CQUFjLEdBQWQsY0FBYyxDQUFnQjtRQUN6RSxJQUFJLENBQUMsZUFBZSxHQUFHLElBQUksQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO1FBQ2hELElBQUksQ0FBQyxLQUFLLEdBQUcsaUJBQWlCLENBQUMsY0FBYyxDQUFDLENBQUM7SUFDbkQsQ0FBQztJQUVELGlCQUFpQjtRQUNiLE1BQU0sUUFBUSxHQUFHLFlBQVksQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFO1lBQ3RDLEtBQUssRUFBRSxPQUFP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QU8sQ0FBQyxNQUFNLENBQUM7SUFDbEQsQ0FBQztJQUVELE1BQU0sTUFBTSxHQUFHLGtCQUFrQixDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRTtRQUN0QyxPQUFPLDZCQUE2QixDQUFDLENBQUMsRUFBRSxXQUFXLEVBQUUsS0FBSyxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQ3ZFLENBQUMsQ0FBbUIsQ0FBQztJQUNyQixNQUFNLGVBQWUsR0FDakIsbUJBQW1CLENBQUMsZUFBZSxDQUFDLG9CQUFvQixDQUFDLE1BQU0sQ0FBQyxFQUFFLGlCQUFpQixDQUFDLGNBQWMsQ0FBQyxDQUFDO1FBQ3BHLGVBQWUsQ0FBQyxvQkFBb0IsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUVqRCxNQUFNLGtCQUFrQixHQUFHLElBQUksa0JBQWtCLENBQUMsS0FBSyxFQUFFLGNBQWMsQ0FBQyxDQUFDO0lBQ3pFLE1BQU0saUJBQWlCLEdBQUcsNkJBQTZCLENBQUMsV0FBVyxFQUFFLFdBQVcsRUFBRSxLQUFLLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFDaEcsTUFBTSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsR0FBRyw0QkFBNEIsQ0FBQyxXQUFXLEVBQUUsaUJBQWlCLENBQUMsQ0FBQztJQUU1RSxPQUFPLGtCQUFrQixDQUFDLGdCQUFnQixDQUFDO1FBQ3ZDLFdBQVc7UUFDWCxrQkFBa0I7UUFDbEIsZUFBZTtRQUNmLFdBQVc7UUFDWCxXQUFXO1FBQ1gsZ0JBQWdCLEVBQUUsQ0FBQyxzQ0FBc0MsQ0FBQyxDQUFDLENBQUMsRUFBRSxzQ0FBc0MsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUN4RyxhQUFhO1FBQ2IsWUFBWTtLQUNmLENBQUMsQ0FBQztBQUNQLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICAgIFJlc2l6ZVJlZixcbiAgICBSZXNpemVTdGF0ZSxcbiAgICBnZXREaXJlY3Rpb25GYWN0b3JCeURpcmVjdGlvbkNvbXBvbmVudCxcbiAgICBnZXRVbml0VmVjdG9yQnlQb2ludEFuZFBvaW50LFxuICAgIHJlc2V0UG9pbnRzQWZ0ZXJSZXNpemVcbn0gZnJvbSAnQHBsYWl0L2NvbW1vbic7XG5pbXBvcnQge1xuICAgIERpcmVjdGlvbkZhY3RvcnMsXG4gICAgUGxhaXRCb2FyZCxcbiAgICBQbGFpdEVsZW1lbnQsXG4gICAgUG9pbnQsXG4gICAgUmVjdGFuZ2xlQ2xpZW50LFxuICAgIFNFTEVDVElPTl9CT1JERVJfQ09MT1IsXG4gICAgY3JlYXRlRGVidWdHZW5lcmF0b3IsXG4gICAgY3JlYXRlRyxcbiAgICBmaW5kRWxlbWVudHMsXG4gICAgZ2V0U2VsZWN0aW9uQW5nbGUsXG4gICAgZ2V0UmVjdGFuZ2xlQnlBbmdsZSxcbiAgICBnZXRSZWN0YW5nbGVCeUVsZW1lbnRzXG59IGZyb20gJ0BwbGFpdC9jb3JlJztcbmltcG9ydCB7IGdldFJlc2l6ZVpvb20sIG1vdmVQb2ludEJ5Wm9vbUFuZE9yaWdpblBvaW50IH0gZnJvbSAnLi4vcGx1Z2lucy93aXRoLWRyYXctcmVzaXplJztcbmltcG9ydCB7IFBsYWl0RHJhd0VsZW1lbnQgfSBmcm9tICcuLi9pbnRlcmZhY2VzJztcblxuY29uc3QgZGVidWdLZXkgPSAnZGVidWc6cGxhaXQ6YWxpZ24tZm9yLWdlb21ldHJ5JztcbmV4cG9ydCBjb25zdCBkZWJ1Z0dlbmVyYXRvciA9IGNyZWF0ZURlYnVnR2VuZXJhdG9yKGRlYnVnS2V5KTtcblxuZXhwb3J0IGludGVyZmFjZSBSZXNpemVBbGlnbkRlbHRhIHtcbiAgICBkZWx0YVg6IG51bWJlcjtcbiAgICBkZWx0YVk6IG51bWJlcjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBTbmFwUmVmIGV4dGVuZHMgUmVzaXplQWxpZ25EZWx0YSB7XG4gICAgeFpvb206IG51bWJlcjtcbiAgICB5Wm9vbTogbnVtYmVyO1xuICAgIGFjdGl2ZVBvaW50czogUG9pbnRbXTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBSZXNpemVTbmFwUmVmIGV4dGVuZHMgU25hcFJlZiB7XG4gICAgYWxpZ25HOiBTVkdHRWxlbWVudDtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBSZXNpemVTbmFwT3B0aW9ucyB7XG4gICAgcmVzaXplU3RhdGU6IFJlc2l6ZVN0YXRlO1xuICAgIHJlc2l6ZU9yaWdpblBvaW50czogUG9pbnRbXTtcbiAgICBhY3RpdmVSZWN0YW5nbGU6IFJlY3RhbmdsZUNsaWVudDtcbiAgICBkaXJlY3Rpb25GYWN0b3JzOiBEaXJlY3Rpb25GYWN0b3JzO1xuICAgIG9yaWdpblBvaW50OiBQb2ludDtcbiAgICBoYW5kbGVQb2ludDogUG9pbnQ7XG4gICAgaXNGcm9tQ29ybmVyOiBib29sZWFuO1xuICAgIGlzQXNwZWN0UmF0aW86IGJvb2xlYW47XG59XG5cbnR5cGUgVHJpcGxlQWxpZ25BeGlzID0gW251bWJlciwgbnVtYmVyLCBudW1iZXJdO1xuXG50eXBlIERyYXdBbGlnbkxpbmVSZWYgPSB7XG4gICAgYXhpczogbnVtYmVyO1xuICAgIGlzSG9yaXpvbnRhbDogYm9vbGVhbjtcbiAgICBhbGlnblJlY3RhbmdsZXM6IFJlY3RhbmdsZUNsaWVudFtdO1xufTtcblxuY29uc3QgQUxJR05fVE9MRVJBTkNFID0gMjtcblxuY29uc3QgRVFVQUxfU1BBQ0lORyA9IDEwO1xuXG5jb25zdCBBTElHTl9TUEFDSU5HID0gMjQ7XG5cbmV4cG9ydCBjbGFzcyBSZXNpemVTbmFwUmVhY3Rpb24ge1xuICAgIGFsaWduUmVjdGFuZ2xlczogUmVjdGFuZ2xlQ2xpZW50W107XG5cbiAgICBhbmdsZTogbnVtYmVyO1xuXG4gICAgY29uc3RydWN0b3IocHJpdmF0ZSBib2FyZDogUGxhaXRCb2FyZCwgcHJpdmF0ZSBhY3RpdmVFbGVtZW50czogUGxhaXRFbGVtZW50W10pIHtcbiAgICAgICAgdGhpcy5hbGlnblJlY3RhbmdsZXMgPSB0aGlzLmdldEFsaWduUmVjdGFuZ2xlKCk7XG4gICAgICAgIHRoaXMuYW5nbGUgPSBnZXRTZWxlY3Rpb25BbmdsZShhY3RpdmVFbGVtZW50cyk7XG4gICAgfVxuXG4gICAgZ2V0QWxpZ25SZWN0YW5nbGUoKSB7XG4gICAgICAgIGNvbnN0IGVsZW1lbnRzID0gZmluZEVsZW1lbnRzKHRoaXMuYm9hcmQsIHtcbiAgICAgICAgICAgIG1hdGNoOiBlbGVtZW50ID0+IHRoaXMuYm9hcmQuaXNBbGlnbihlbGVtZW50KSAmJiAhdGhpcy5hY3RpdmVFbGVtZW50cy5zb21lKGl0ZW0gPT4gaXRlbS5pZCA9PT0gZWxlbWVudC5pZCksXG4gICAgICAgICAgICByZWN1cnNpb246ICgpID0+IGZhbHNlLFxuICAgICAgICAgICAgaXNSZXZlcnNlOiBmYWxzZVxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIGVsZW1lbnRzLm1hcChpdGVtID0+IGdldFJlY3RhbmdsZUJ5QW5nbGUodGhpcy5ib2FyZC5nZXRSZWN0YW5nbGUoaXRlbSkhLCBpdGVtLmFuZ2xlKSB8fCB0aGlzLmJvYXJkLmdldFJlY3RhbmdsZShpdGVtKSEpO1xuICAgIH1cblxuICAgIGdldFNuYXBSZWYocmVzaXplQWxpZ25EZWx0YTogUmVzaXplQWxpZ25EZWx0YSwgcmVzaXplU25hcE9wdGlvbnM6IFJlc2l6ZVNuYXBPcHRpb25zKTogU25hcFJlZiB7XG4gICAgICAgIGNvbnN0IHsgZGVsdGFYLCBkZWx0YVkgfSA9IHJlc2l6ZUFsaWduRGVsdGE7XG4gICAgICAgIGNvbnN0IHsgcmVzaXplU3RhdGUsIG9yaWdpblBvaW50LCBoYW5kbGVQb2ludCwgaXNGcm9tQ29ybmVyLCBpc0FzcGVjdFJhdGlvLCByZXNpemVPcmlnaW5Qb2ludHMgfSA9IHJlc2l6ZVNuYXBPcHRpb25zO1xuICAgICAgICBjb25zdCBuZXdSZXNpemVTdGF0ZTogUmVzaXplU3RhdGUgPSB7XG4gICAgICAgICAgICAuLi5yZXNpemVTdGF0ZSxcbiAgICAgICAgICAgIGVuZFBvaW50OiBbcmVzaXplU3RhdGUuZW5kUG9pbnRbMF0gKyBkZWx0YVgsIHJlc2l6ZVN0YXRlLmVuZFBvaW50WzFdICsgZGVsdGFZXVxuICAgICAgICB9O1xuICAgICAgICBjb25zdCB7IHhab29tLCB5Wm9vbSB9ID0gZ2V0UmVzaXplWm9vbShuZXdSZXNpemVTdGF0ZSwgb3JpZ2luUG9pbnQsIGhhbmRsZVBvaW50LCBpc0Zyb21Db3JuZXIsIGlzQXNwZWN0UmF0aW8pO1xuICAgICAgICBsZXQgYWN0aXZlUG9pbnRzID0gcmVzaXplT3JpZ2luUG9pbnRzLm1hcChwID0+IHtcbiAgICAgICAgICAgIHJldHVybiBtb3ZlUG9pbnRCeVpvb21BbmRPcmlnaW5Qb2ludChwLCBvcmlnaW5Qb2ludCwgeFpvb20sIHlab29tKTtcbiAgICAgICAgfSkgYXMgW1BvaW50LCBQb2ludF07XG5cbiAgICAgICAgaWYgKHRoaXMuYW5nbGUpIHtcbiAgICAgICAgICAgIGFjdGl2ZVBvaW50cyA9IHJlc2V0UG9pbnRzQWZ0ZXJSZXNpemUoXG4gICAgICAgICAgICAgICAgUmVjdGFuZ2xlQ2xpZW50LmdldFJlY3RhbmdsZUJ5UG9pbnRzKHJlc2l6ZU9yaWdpblBvaW50cyksXG4gICAgICAgICAgICAgICAgUmVjdGFuZ2xlQ2xpZW50LmdldFJlY3RhbmdsZUJ5UG9pbnRzKGFjdGl2ZVBvaW50cyksXG4gICAgICAgICAgICAgICAgUmVjdGFuZ2xlQ2xpZW50LmdldENlbnRlclBvaW50KFJlY3RhbmdsZUNsaWVudC5nZXRSZWN0YW5nbGVCeVBvaW50cyhyZXNpemVPcmlnaW5Qb2ludHMpKSxcbiAgICAgICAgICAgICAgICBSZWN0YW5nbGVDbGllbnQuZ2V0Q2VudGVyUG9pbnQoUmVjdGFuZ2xlQ2xpZW50LmdldFJlY3RhbmdsZUJ5UG9pbnRzKGFjdGl2ZVBvaW50cykpLFxuICAgICAgICAgICAgICAgIHRoaXMuYW5nbGVcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgZGVsdGFYLFxuICAgICAgICAgICAgZGVsdGFZLFxuICAgICAgICAgICAgeFpvb20sXG4gICAgICAgICAgICB5Wm9vbSxcbiAgICAgICAgICAgIGFjdGl2ZVBvaW50c1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIGdldEVxdWFsTGluZURlbHRhKHJlc2l6ZVNuYXBPcHRpb25zOiBSZXNpemVTbmFwT3B0aW9ucykge1xuICAgICAgICBsZXQgZXF1YWxMaW5lRGVsdGE6IFJlc2l6ZUFsaWduRGVsdGEgPSB7XG4gICAgICAgICAgICBkZWx0YVg6IDAsXG4gICAgICAgICAgICBkZWx0YVk6IDBcbiAgICAgICAgfTtcbiAgICAgICAgY29uc3QgeyBpc0FzcGVjdFJhdGlvLCBhY3RpdmVSZWN0YW5nbGUgfSA9IHJlc2l6ZVNuYXBPcHRpb25zO1xuICAgICAgICBjb25zdCB3aWR0aEFsaWduUmVjdGFuZ2xlID0gdGhpcy5hbGlnblJlY3RhbmdsZXMuZmluZChpdGVtID0+IE1hdGguYWJzKGl0ZW0ud2lkdGggLSBhY3RpdmVSZWN0YW5nbGUud2lkdGgpIDwgQUxJR05fVE9MRVJBTkNFKTtcbiAgICAgICAgaWYgKHdpZHRoQWxpZ25SZWN0YW5nbGUpIHtcbiAgICAgICAgICAgIGNvbnN0IGRlbHRhV2lkdGggPSB3aWR0aEFsaWduUmVjdGFuZ2xlLndpZHRoIC0gYWN0aXZlUmVjdGFuZ2xlLndpZHRoO1xuICAgICAgICAgICAgZXF1YWxMaW5lRGVsdGEuZGVsdGFYID0gZGVsdGFXaWR0aCAqIHJlc2l6ZVNuYXBPcHRpb25zLmRpcmVjdGlvbkZhY3RvcnNbMF07XG4gICAgICAgICAgICBpZiAoaXNBc3BlY3RSYXRpbykge1xuICAgICAgICAgICAgICAgIGNvbnN0IGRlbHRhSGVpZ2h0ID0gZGVsdGFXaWR0aCAvIChhY3RpdmVSZWN0YW5nbGUud2lkdGggLyBhY3RpdmVSZWN0YW5nbGUuaGVpZ2h0KTtcbiAgICAgICAgICAgICAgICBlcXVhbExpbmVEZWx0YS5kZWx0YVkgPSBkZWx0YUhlaWdodCAqIHJlc2l6ZVNuYXBPcHRpb25zLmRpcmVjdGlvbkZhY3RvcnNbMV07XG4gICAgICAgICAgICAgICAgcmV0dXJuIGVxdWFsTGluZURlbHRhO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGhlaWdodEFsaWduUmVjdGFuZ2xlID0gdGhpcy5hbGlnblJlY3RhbmdsZXMuZmluZChpdGVtID0+IE1hdGguYWJzKGl0ZW0uaGVpZ2h0IC0gYWN0aXZlUmVjdGFuZ2xlLmhlaWdodCkgPCBBTElHTl9UT0xFUkFOQ0UpO1xuICAgICAgICBpZiAoaGVpZ2h0QWxpZ25SZWN0YW5nbGUpIHtcbiAgICAgICAgICAgIGNvbnN0IGRlbHRhSGVpZ2h0ID0gaGVpZ2h0QWxpZ25SZWN0YW5nbGUuaGVpZ2h0IC0gYWN0aXZlUmVjdGFuZ2xlLmhlaWdodDtcbiAgICAgICAgICAgIGVxdWFsTGluZURlbHRhLmRlbHRhWSA9IGRlbHRhSGVpZ2h0ICogcmVzaXplU25hcE9wdGlvbnMuZGlyZWN0aW9uRmFjdG9yc1sxXTtcbiAgICAgICAgICAgIGlmIChpc0FzcGVjdFJhdGlvKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgZGVsdGFXaWR0aCA9IGRlbHRhSGVpZ2h0ICogKGFjdGl2ZVJlY3RhbmdsZS53aWR0aCAvIGFjdGl2ZVJlY3RhbmdsZS5oZWlnaHQpO1xuICAgICAgICAgICAgICAgIGVxdWFsTGluZURlbHRhLmRlbHRhWCA9IGRlbHRhV2lkdGggKiByZXNpemVTbmFwT3B0aW9ucy5kaXJlY3Rpb25GYWN0b3JzWzBdO1xuICAgICAgICAgICAgICAgIHJldHVybiBlcXVhbExpbmVEZWx0YTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZXF1YWxMaW5lRGVsdGE7XG4gICAgfVxuXG4gICAgZHJhd0VxdWFsTGluZXMoYWN0aXZlUG9pbnRzOiBQb2ludFtdLCByZXNpemVTbmFwT3B0aW9uczogUmVzaXplU25hcE9wdGlvbnMpIHtcbiAgICAgICAgbGV0IHdpZHRoRXF1YWxQb2ludHMgPSBbXTtcbiAgICAgICAgbGV0IGhlaWdodEVxdWFsUG9pbnRzID0gW107XG5cbiAgICAgICAgY29uc3QgZHJhd0hvcml6b250YWxMaW5lID0gcmVzaXplU25hcE9wdGlvbnMuZGlyZWN0aW9uRmFjdG9yc1swXSAhPT0gMCB8fCByZXNpemVTbmFwT3B0aW9ucy5pc0FzcGVjdFJhdGlvO1xuICAgICAgICBjb25zdCBkcmF3VmVydGljYWxMaW5lID0gcmVzaXplU25hcE9wdGlvbnMuZGlyZWN0aW9uRmFjdG9yc1sxXSAhPT0gMCB8fCByZXNpemVTbmFwT3B0aW9ucy5pc0FzcGVjdFJhdGlvO1xuICAgICAgICBjb25zdCBhY3RpdmVSZWN0YW5nbGUgPVxuICAgICAgICAgICAgZ2V0UmVjdGFuZ2xlQnlBbmdsZShSZWN0YW5nbGVDbGllbnQuZ2V0UmVjdGFuZ2xlQnlQb2ludHMoYWN0aXZlUG9pbnRzKSwgdGhpcy5hbmdsZSkgfHxcbiAgICAgICAgICAgIFJlY3RhbmdsZUNsaWVudC5nZXRSZWN0YW5nbGVCeVBvaW50cyhhY3RpdmVQb2ludHMpO1xuICAgICAgICBmb3IgKGxldCBhbGlnblJlY3RhbmdsZSBvZiB0aGlzLmFsaWduUmVjdGFuZ2xlcykge1xuICAgICAgICAgICAgaWYgKGFjdGl2ZVJlY3RhbmdsZS53aWR0aCA9PT0gYWxpZ25SZWN0YW5nbGUud2lkdGggJiYgZHJhd0hvcml6b250YWxMaW5lKSB7XG4gICAgICAgICAgICAgICAgd2lkdGhFcXVhbFBvaW50cy5wdXNoKGdldEVxdWFsTGluZVBvaW50cyhhbGlnblJlY3RhbmdsZSwgdHJ1ZSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGFjdGl2ZVJlY3RhbmdsZS5oZWlnaHQgPT09IGFsaWduUmVjdGFuZ2xlLmhlaWdodCAmJiBkcmF3VmVydGljYWxMaW5lKSB7XG4gICAgICAgICAgICAgICAgaGVpZ2h0RXF1YWxQb2ludHMucHVzaChnZXRFcXVhbExpbmVQb2ludHMoYWxpZ25SZWN0YW5nbGUsIGZhbHNlKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHdpZHRoRXF1YWxQb2ludHMubGVuZ3RoICYmIGRyYXdIb3Jpem9udGFsTGluZSkge1xuICAgICAgICAgICAgd2lkdGhFcXVhbFBvaW50cy5wdXNoKGdldEVxdWFsTGluZVBvaW50cyhhY3RpdmVSZWN0YW5nbGUsIHRydWUpKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaGVpZ2h0RXF1YWxQb2ludHMubGVuZ3RoICYmIGRyYXdWZXJ0aWNhbExpbmUpIHtcbiAgICAgICAgICAgIGhlaWdodEVxdWFsUG9pbnRzLnB1c2goZ2V0RXF1YWxMaW5lUG9pbnRzKGFjdGl2ZVJlY3RhbmdsZSwgZmFsc2UpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGVxdWFsTGluZVBvaW50cyA9IFsuLi53aWR0aEVxdWFsUG9pbnRzLCAuLi5oZWlnaHRFcXVhbFBvaW50c107XG4gICAgICAgIHJldHVybiBkcmF3RXF1YWxMaW5lcyh0aGlzLmJvYXJkLCBlcXVhbExpbmVQb2ludHMpO1xuICAgIH1cblxuICAgIGdldEFsaWduTGluZURlbHRhKHJlc2l6ZVNuYXBPcHRpb25zOiBSZXNpemVTbmFwT3B0aW9ucykge1xuICAgICAgICBsZXQgYWxpZ25MaW5lRGVsdGE6IFJlc2l6ZUFsaWduRGVsdGEgPSB7XG4gICAgICAgICAgICBkZWx0YVg6IDAsXG4gICAgICAgICAgICBkZWx0YVk6IDBcbiAgICAgICAgfTtcbiAgICAgICAgY29uc3QgeyBpc0FzcGVjdFJhdGlvLCBhY3RpdmVSZWN0YW5nbGUsIGRpcmVjdGlvbkZhY3RvcnMgfSA9IHJlc2l6ZVNuYXBPcHRpb25zO1xuICAgICAgICBjb25zdCBkcmF3SG9yaXpvbnRhbCA9IGRpcmVjdGlvbkZhY3RvcnNbMF0gIT09IDAgfHwgaXNBc3BlY3RSYXRpbztcbiAgICAgICAgY29uc3QgZHJhd1ZlcnRpY2FsID0gZGlyZWN0aW9uRmFjdG9yc1sxXSAhPT0gMCB8fCBpc0FzcGVjdFJhdGlvO1xuXG4gICAgICAgIGlmIChkcmF3SG9yaXpvbnRhbCkge1xuICAgICAgICAgICAgY29uc3QgeEFsaWduQXhpcyA9IGdldFRyaXBsZUFsaWduQXhpcyhhY3RpdmVSZWN0YW5nbGUsIHRydWUpO1xuICAgICAgICAgICAgY29uc3QgYWxpZ25YID0gZGlyZWN0aW9uRmFjdG9yc1swXSA9PT0gLTEgPyB4QWxpZ25BeGlzWzBdIDogeEFsaWduQXhpc1syXTtcbiAgICAgICAgICAgIGNvbnN0IGRlbHRhWCA9IGdldE1pbkFsaWduRGVsdGEodGhpcy5hbGlnblJlY3RhbmdsZXMsIGFsaWduWCwgdHJ1ZSk7XG4gICAgICAgICAgICBpZiAoTWF0aC5hYnMoZGVsdGFYKSA8IEFMSUdOX1RPTEVSQU5DRSkge1xuICAgICAgICAgICAgICAgIGFsaWduTGluZURlbHRhLmRlbHRhWCA9IGRlbHRhWDtcbiAgICAgICAgICAgICAgICBpZiAoYWxpZ25MaW5lRGVsdGEuZGVsdGFYICE9PSAwICYmIGlzQXNwZWN0UmF0aW8pIHtcbiAgICAgICAgICAgICAgICAgICAgYWxpZ25MaW5lRGVsdGEuZGVsdGFZID0gYWxpZ25MaW5lRGVsdGEuZGVsdGFYIC8gKGFjdGl2ZVJlY3RhbmdsZS53aWR0aCAvIGFjdGl2ZVJlY3RhbmdsZS5oZWlnaHQpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gYWxpZ25MaW5lRGVsdGE7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGRyYXdWZXJ0aWNhbCkge1xuICAgICAgICAgICAgY29uc3QgeUFsaWduQXhpcyA9IGdldFRyaXBsZUFsaWduQXhpcyhhY3RpdmVSZWN0YW5nbGUsIGZhbHNlKTtcbiAgICAgICAgICAgIGNvbnN0IGFsaWduWSA9IGRpcmVjdGlvbkZhY3RvcnNbMV0gPT09IC0xID8geUFsaWduQXhpc1swXSA6IHlBbGlnbkF4aXNbMl07XG4gICAgICAgICAgICBjb25zdCBkZWx0YVkgPSBnZXRNaW5BbGlnbkRlbHRhKHRoaXMuYWxpZ25SZWN0YW5nbGVzLCBhbGlnblksIGZhbHNlKTtcbiAgICAgICAgICAgIGlmIChNYXRoLmFicyhkZWx0YVkpIDwgQUxJR05fVE9MRVJBTkNFKSB7XG4gICAgICAgICAgICAgICAgYWxpZ25MaW5lRGVsdGEuZGVsdGFZID0gZGVsdGFZO1xuICAgICAgICAgICAgICAgIGlmIChhbGlnbkxpbmVEZWx0YS5kZWx0YVkgIT09IDAgJiYgaXNBc3BlY3RSYXRpbykge1xuICAgICAgICAgICAgICAgICAgICBhbGlnbkxpbmVEZWx0YS5kZWx0YVggPSBhbGlnbkxpbmVEZWx0YS5kZWx0YVkgKiAoYWN0aXZlUmVjdGFuZ2xlLndpZHRoIC8gYWN0aXZlUmVjdGFuZ2xlLmhlaWdodCk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBhbGlnbkxpbmVEZWx0YTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gYWxpZ25MaW5lRGVsdGE7XG4gICAgfVxuXG4gICAgZHJhd0FsaWduTGluZXMoYWN0aXZlUG9pbnRzOiBQb2ludFtdLCByZXNpemVTbmFwT3B0aW9uczogUmVzaXplU25hcE9wdGlvbnMpIHtcbiAgICAgICAgZGVidWdHZW5lcmF0b3IuaXNEZWJ1ZygpICYmIGRlYnVnR2VuZXJhdG9yLmNsZWFyKCk7XG4gICAgICAgIGxldCBhbGlnbkxpbmVQb2ludHM6IFtQb2ludCwgUG9pbnRdW10gPSBbXTtcbiAgICAgICAgY29uc3QgYWN0aXZlUmVjdGFuZ2xlID1cbiAgICAgICAgICAgIGdldFJlY3RhbmdsZUJ5QW5nbGUoUmVjdGFuZ2xlQ2xpZW50LmdldFJlY3RhbmdsZUJ5UG9pbnRzKGFjdGl2ZVBvaW50cyksIHRoaXMuYW5nbGUpIHx8XG4gICAgICAgICAgICBSZWN0YW5nbGVDbGllbnQuZ2V0UmVjdGFuZ2xlQnlQb2ludHMoYWN0aXZlUG9pbnRzKTtcbiAgICAgICAgZGVidWdHZW5lcmF0b3IuaXNEZWJ1ZygpICYmIGRlYnVnR2VuZXJhdG9yLmRyYXdSZWN0YW5nbGUodGhpcy5ib2FyZCwgYWN0aXZlUmVjdGFuZ2xlLCB7IHN0cm9rZTogJ2dyZWVuJyB9KTtcbiAgICAgICAgY29uc3QgYWxpZ25BeGlzWCA9IGdldFRyaXBsZUFsaWduQXhpcyhhY3RpdmVSZWN0YW5nbGUsIHRydWUpO1xuICAgICAgICBjb25zdCBhbGlnbkF4aXNZID0gZ2V0VHJpcGxlQWxpZ25BeGlzKGFjdGl2ZVJlY3RhbmdsZSwgZmFsc2UpO1xuICAgICAgICBjb25zdCBhbGlnbkxpbmVSZWZzOiBEcmF3QWxpZ25MaW5lUmVmW10gPSBbXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgYXhpczogYWxpZ25BeGlzWFswXSxcbiAgICAgICAgICAgICAgICBpc0hvcml6b250YWw6IHRydWUsXG4gICAgICAgICAgICAgICAgYWxpZ25SZWN0YW5nbGVzOiBbXVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBheGlzOiBhbGlnbkF4aXNYWzJdLFxuICAgICAgICAgICAgICAgIGlzSG9yaXpvbnRhbDogdHJ1ZSxcbiAgICAgICAgICAgICAgICBhbGlnblJlY3RhbmdsZXM6IFtdXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIGF4aXM6IGFsaWduQXhpc1lbMF0sXG4gICAgICAgICAgICAgICAgaXNIb3Jpem9udGFsOiBmYWxzZSxcbiAgICAgICAgICAgICAgICBhbGlnblJlY3RhbmdsZXM6IFtdXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIGF4aXM6IGFsaWduQXhpc1lbMl0sXG4gICAgICAgICAgICAgICAgaXNIb3Jpem9udGFsOiBmYWxzZSxcbiAgICAgICAgICAgICAgICBhbGlnblJlY3RhbmdsZXM6IFtdXG4gICAgICAgICAgICB9XG4gICAgICAgIF07XG4gICAgICAgIGNvbnN0IHNldEFsaWduTGluZSA9IChheGlzOiBudW1iZXIsIGFsaWduUmVjdGFuZ2xlOiBSZWN0YW5nbGVDbGllbnQsIGlzSG9yaXpvbnRhbDogYm9vbGVhbikgPT4ge1xuICAgICAgICAgICAgY29uc3QgYm91bmRpbmdSZWN0YW5nbGUgPSBSZWN0YW5nbGVDbGllbnQuaW5mbGF0ZShcbiAgICAgICAgICAgICAgICBSZWN0YW5nbGVDbGllbnQuZ2V0Qm91bmRpbmdSZWN0YW5nbGUoW2FjdGl2ZVJlY3RhbmdsZSwgYWxpZ25SZWN0YW5nbGVdKSxcbiAgICAgICAgICAgICAgICBBTElHTl9TUEFDSU5HXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgaWYgKGlzSG9yaXpvbnRhbCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IHBvaW50U3RhcnQgPSBbYXhpcywgYm91bmRpbmdSZWN0YW5nbGUueV0gYXMgUG9pbnQ7XG4gICAgICAgICAgICAgICAgY29uc3QgcG9pbnRFbmQgPSBbYXhpcywgYm91bmRpbmdSZWN0YW5nbGUueSArIGJvdW5kaW5nUmVjdGFuZ2xlLmhlaWdodF0gYXMgUG9pbnQ7XG4gICAgICAgICAgICAgICAgYWxpZ25MaW5lUG9pbnRzLnB1c2goW3BvaW50U3RhcnQsIHBvaW50RW5kXSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnN0IHBvaW50U3RhcnQgPSBbYm91bmRpbmdSZWN0YW5nbGUueCwgYXhpc10gYXMgUG9pbnQ7XG4gICAgICAgICAgICAgICAgY29uc3QgcG9pbnRFbmQgPSBbYm91bmRpbmdSZWN0YW5nbGUueCArIGJvdW5kaW5nUmVjdGFuZ2xlLndpZHRoLCBheGlzXSBhcyBQb2ludDtcbiAgICAgICAgICAgICAgICBhbGlnbkxpbmVQb2ludHMucHVzaChbcG9pbnRTdGFydCwgcG9pbnRFbmRdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICBjb25zdCB7IGlzQXNwZWN0UmF0aW8sIGRpcmVjdGlvbkZhY3RvcnMgfSA9IHJlc2l6ZVNuYXBPcHRpb25zO1xuICAgICAgICBjb25zdCBkcmF3SG9yaXpvbnRhbCA9IGRpcmVjdGlvbkZhY3RvcnNbMF0gIT09IDAgfHwgaXNBc3BlY3RSYXRpbztcbiAgICAgICAgY29uc3QgZHJhd1ZlcnRpY2FsID0gZGlyZWN0aW9uRmFjdG9yc1sxXSAhPT0gMCB8fCBpc0FzcGVjdFJhdGlvO1xuXG4gICAgICAgIGZvciAobGV0IGluZGV4ID0gMDsgaW5kZXggPCB0aGlzLmFsaWduUmVjdGFuZ2xlcy5sZW5ndGg7IGluZGV4KyspIHtcbiAgICAgICAgICAgIGNvbnN0IGVsZW1lbnQgPSB0aGlzLmFsaWduUmVjdGFuZ2xlc1tpbmRleF07XG4gICAgICAgICAgICBkZWJ1Z0dlbmVyYXRvci5pc0RlYnVnKCkgJiYgZGVidWdHZW5lcmF0b3IuZHJhd1JlY3RhbmdsZSh0aGlzLmJvYXJkLCBlbGVtZW50KTtcblxuICAgICAgICAgICAgaWYgKGlzQWxpZ24oYWxpZ25MaW5lUmVmc1swXS5heGlzLCBlbGVtZW50LCBhbGlnbkxpbmVSZWZzWzBdLmlzSG9yaXpvbnRhbCkpIHtcbiAgICAgICAgICAgICAgICBhbGlnbkxpbmVSZWZzWzBdLmFsaWduUmVjdGFuZ2xlcy5wdXNoKGVsZW1lbnQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGlzQWxpZ24oYWxpZ25MaW5lUmVmc1sxXS5heGlzLCBlbGVtZW50LCBhbGlnbkxpbmVSZWZzWzFdLmlzSG9yaXpvbnRhbCkpIHtcbiAgICAgICAgICAgICAgICBhbGlnbkxpbmVSZWZzWzFdLmFsaWduUmVjdGFuZ2xlcy5wdXNoKGVsZW1lbnQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGlzQWxpZ24oYWxpZ25MaW5lUmVmc1syXS5heGlzLCBlbGVtZW50LCBhbGlnbkxpbmVSZWZzWzJdLmlzSG9yaXpvbnRhbCkpIHtcbiAgICAgICAgICAgICAgICBhbGlnbkxpbmVSZWZzWzJdLmFsaWduUmVjdGFuZ2xlcy5wdXNoKGVsZW1lbnQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGlzQWxpZ24oYWxpZ25MaW5lUmVmc1szXS5heGlzLCBlbGVtZW50LCBhbGlnbkxpbmVSZWZzWzNdLmlzSG9yaXpvbnRhbCkpIHtcbiAgICAgICAgICAgICAgICBhbGlnbkxpbmVSZWZzWzNdLmFsaWduUmVjdGFuZ2xlcy5wdXNoKGVsZW1lbnQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGRyYXdIb3Jpem9udGFsICYmIGFsaWduTGluZVJlZnNbMF0uYWxpZ25SZWN0YW5nbGVzLmxlbmd0aCkge1xuICAgICAgICAgICAgY29uc3QgbGVmdFJlY3RhbmdsZSA9XG4gICAgICAgICAgICAgICAgYWxpZ25MaW5lUmVmc1swXS5hbGlnblJlY3RhbmdsZXMubGVuZ3RoID09PSAxXG4gICAgICAgICAgICAgICAgICAgID8gYWxpZ25MaW5lUmVmc1swXS5hbGlnblJlY3RhbmdsZXNbMF1cbiAgICAgICAgICAgICAgICAgICAgOiBnZXROZWFyZXN0QWxpZ25SZWN0YW5nbGUoYWxpZ25MaW5lUmVmc1swXS5hbGlnblJlY3RhbmdsZXMsIGFjdGl2ZVJlY3RhbmdsZSk7XG4gICAgICAgICAgICBzZXRBbGlnbkxpbmUoYWxpZ25MaW5lUmVmc1swXS5heGlzLCBsZWZ0UmVjdGFuZ2xlLCBhbGlnbkxpbmVSZWZzWzBdLmlzSG9yaXpvbnRhbCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZHJhd0hvcml6b250YWwgJiYgYWxpZ25MaW5lUmVmc1sxXS5hbGlnblJlY3RhbmdsZXMubGVuZ3RoKSB7XG4gICAgICAgICAgICBjb25zdCByaWdodFJlY3RhbmdsZSA9XG4gICAgICAgICAgICAgICAgYWxpZ25MaW5lUmVmc1sxXS5hbGlnblJlY3RhbmdsZXMubGVuZ3RoID09PSAxXG4gICAgICAgICAgICAgICAgICAgID8gYWxpZ25MaW5lUmVmc1sxXS5hbGlnblJlY3RhbmdsZXNbMF1cbiAgICAgICAgICAgICAgICAgICAgOiBnZXROZWFyZXN0QWxpZ25SZWN0YW5nbGUoYWxpZ25MaW5lUmVmc1sxXS5hbGlnblJlY3RhbmdsZXMsIGFjdGl2ZVJlY3RhbmdsZSk7XG4gICAgICAgICAgICBzZXRBbGlnbkxpbmUoYWxpZ25MaW5lUmVmc1sxXS5heGlzLCByaWdodFJlY3RhbmdsZSwgYWxpZ25MaW5lUmVmc1sxXS5pc0hvcml6b250YWwpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGRyYXdWZXJ0aWNhbCAmJiBhbGlnbkxpbmVSZWZzWzJdLmFsaWduUmVjdGFuZ2xlcy5sZW5ndGgpIHtcbiAgICAgICAgICAgIGNvbnN0IHRvcFJlY3RhbmdsZSA9XG4gICAgICAgICAgICAgICAgYWxpZ25MaW5lUmVmc1syXS5hbGlnblJlY3RhbmdsZXMubGVuZ3RoID09PSAxXG4gICAgICAgICAgICAgICAgICAgID8gYWxpZ25MaW5lUmVmc1syXS5hbGlnblJlY3RhbmdsZXNbMF1cbiAgICAgICAgICAgICAgICAgICAgOiBnZXROZWFyZXN0QWxpZ25SZWN0YW5nbGUoYWxpZ25MaW5lUmVmc1syXS5hbGlnblJlY3RhbmdsZXMsIGFjdGl2ZVJlY3RhbmdsZSk7XG4gICAgICAgICAgICBzZXRBbGlnbkxpbmUoYWxpZ25MaW5lUmVmc1syXS5heGlzLCB0b3BSZWN0YW5nbGUsIGFsaWduTGluZVJlZnNbMl0uaXNIb3Jpem9udGFsKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChkcmF3VmVydGljYWwgJiYgYWxpZ25MaW5lUmVmc1szXS5hbGlnblJlY3RhbmdsZXMubGVuZ3RoKSB7XG4gICAgICAgICAgICBjb25zdCBib3R0b21SZWN0YW5nbGUgPVxuICAgICAgICAgICAgICAgIGFsaWduTGluZVJlZnNbM10uYWxpZ25SZWN0YW5nbGVzLmxlbmd0aCA9PT0gMVxuICAgICAgICAgICAgICAgICAgICA/IGFsaWduTGluZVJlZnNbM10uYWxpZ25SZWN0YW5nbGVzWzBdXG4gICAgICAgICAgICAgICAgICAgIDogZ2V0TmVhcmVzdEFsaWduUmVjdGFuZ2xlKGFsaWduTGluZVJlZnNbM10uYWxpZ25SZWN0YW5nbGVzLCBhY3RpdmVSZWN0YW5nbGUpO1xuICAgICAgICAgICAgc2V0QWxpZ25MaW5lKGFsaWduTGluZVJlZnNbM10uYXhpcywgYm90dG9tUmVjdGFuZ2xlLCBhbGlnbkxpbmVSZWZzWzNdLmlzSG9yaXpvbnRhbCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gZHJhd0FsaWduTGluZXModGhpcy5ib2FyZCwgYWxpZ25MaW5lUG9pbnRzKTtcbiAgICB9XG5cbiAgICBoYW5kbGVSZXNpemVTbmFwKHJlc2l6ZVNuYXBPcHRpb25zOiBSZXNpemVTbmFwT3B0aW9ucyk6IFJlc2l6ZVNuYXBSZWYge1xuICAgICAgICBjb25zdCBhbGlnbkcgPSBjcmVhdGVHKCk7XG4gICAgICAgIGxldCBhbGlnbkxpbmVEZWx0YSA9IHRoaXMuZ2V0RXF1YWxMaW5lRGVsdGEocmVzaXplU25hcE9wdGlvbnMpO1xuICAgICAgICBpZiAoYWxpZ25MaW5lRGVsdGEuZGVsdGFYID09PSAwICYmIGFsaWduTGluZURlbHRhLmRlbHRhWSA9PT0gMCkge1xuICAgICAgICAgICAgYWxpZ25MaW5lRGVsdGEgPSB0aGlzLmdldEFsaWduTGluZURlbHRhKHJlc2l6ZVNuYXBPcHRpb25zKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBlcXVhbExpbmVSZWYgPSB0aGlzLmdldFNuYXBSZWYoYWxpZ25MaW5lRGVsdGEsIHJlc2l6ZVNuYXBPcHRpb25zKTtcbiAgICAgICAgY29uc3QgZXF1YWxMaW5lc0cgPSB0aGlzLmRyYXdFcXVhbExpbmVzKGVxdWFsTGluZVJlZi5hY3RpdmVQb2ludHMsIHJlc2l6ZVNuYXBPcHRpb25zKTtcbiAgICAgICAgY29uc3QgYWxpZ25MaW5lc0cgPSB0aGlzLmRyYXdBbGlnbkxpbmVzKGVxdWFsTGluZVJlZi5hY3RpdmVQb2ludHMsIHJlc2l6ZVNuYXBPcHRpb25zKTtcbiAgICAgICAgYWxpZ25HLmFwcGVuZChlcXVhbExpbmVzRywgYWxpZ25MaW5lc0cpO1xuICAgICAgICByZXR1cm4geyAuLi5lcXVhbExpbmVSZWYsIGFsaWduRyB9O1xuICAgIH1cbn1cblxuZnVuY3Rpb24gZ2V0QmFyUG9pbnQocG9pbnQ6IFBvaW50LCBpc0hvcml6b250YWw6IGJvb2xlYW4pIHtcbiAgICByZXR1cm4gaXNIb3Jpem9udGFsXG4gICAgICAgID8gW1xuICAgICAgICAgICAgICBbcG9pbnRbMF0sIHBvaW50WzFdIC0gNF0sXG4gICAgICAgICAgICAgIFtwb2ludFswXSwgcG9pbnRbMV0gKyA0XVxuICAgICAgICAgIF1cbiAgICAgICAgOiBbXG4gICAgICAgICAgICAgIFtwb2ludFswXSAtIDQsIHBvaW50WzFdXSxcbiAgICAgICAgICAgICAgW3BvaW50WzBdICsgNCwgcG9pbnRbMV1dXG4gICAgICAgICAgXTtcbn1cblxuZnVuY3Rpb24gZ2V0RXF1YWxMaW5lUG9pbnRzKHJlY3RhbmdsZTogUmVjdGFuZ2xlQ2xpZW50LCBpc0hvcml6b250YWw6IGJvb2xlYW4pOiBQb2ludFtdIHtcbiAgICByZXR1cm4gaXNIb3Jpem9udGFsXG4gICAgICAgID8gW1xuICAgICAgICAgICAgICBbcmVjdGFuZ2xlLngsIHJlY3RhbmdsZS55IC0gRVFVQUxfU1BBQ0lOR10sXG4gICAgICAgICAgICAgIFtyZWN0YW5nbGUueCArIHJlY3RhbmdsZS53aWR0aCwgcmVjdGFuZ2xlLnkgLSBFUVVBTF9TUEFDSU5HXVxuICAgICAgICAgIF1cbiAgICAgICAgOiBbXG4gICAgICAgICAgICAgIFtyZWN0YW5nbGUueCAtIEVRVUFMX1NQQUNJTkcsIHJlY3RhbmdsZS55XSxcbiAgICAgICAgICAgICAgW3JlY3RhbmdsZS54IC0gRVFVQUxfU1BBQ0lORywgcmVjdGFuZ2xlLnkgKyByZWN0YW5nbGUuaGVpZ2h0XVxuICAgICAgICAgIF07XG59XG5cbmZ1bmN0aW9uIGRyYXdFcXVhbExpbmVzKGJvYXJkOiBQbGFpdEJvYXJkLCBsaW5lczogUG9pbnRbXVtdKSB7XG4gICAgY29uc3QgZyA9IGNyZWF0ZUcoKTtcbiAgICBsaW5lcy5mb3JFYWNoKGxpbmUgPT4ge1xuICAgICAgICBpZiAoIWxpbmUubGVuZ3RoKSByZXR1cm47XG4gICAgICAgIGNvbnN0IHlBbGlnbiA9IFBsYWl0Qm9hcmQuZ2V0Um91Z2hTVkcoYm9hcmQpLmxpbmUobGluZVswXVswXSwgbGluZVswXVsxXSwgbGluZVsxXVswXSwgbGluZVsxXVsxXSwge1xuICAgICAgICAgICAgc3Ryb2tlOiBTRUxFQ1RJT05fQk9SREVSX0NPTE9SLFxuICAgICAgICAgICAgc3Ryb2tlV2lkdGg6IDFcbiAgICAgICAgfSk7XG4gICAgICAgIGcuYXBwZW5kQ2hpbGQoeUFsaWduKTtcbiAgICAgICAgbGluZS5mb3JFYWNoKHBvaW50ID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGJhclBvaW50ID0gZ2V0QmFyUG9pbnQocG9pbnQsICEhUG9pbnQuaXNIb3Jpem9udGFsKGxpbmVbMF0sIGxpbmVbMV0pKTtcbiAgICAgICAgICAgIGNvbnN0IGJhciA9IFBsYWl0Qm9hcmQuZ2V0Um91Z2hTVkcoYm9hcmQpLmxpbmUoYmFyUG9pbnRbMF1bMF0sIGJhclBvaW50WzBdWzFdLCBiYXJQb2ludFsxXVswXSwgYmFyUG9pbnRbMV1bMV0sIHtcbiAgICAgICAgICAgICAgICBzdHJva2U6IFNFTEVDVElPTl9CT1JERVJfQ09MT1IsXG4gICAgICAgICAgICAgICAgc3Ryb2tlV2lkdGg6IDFcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgZy5hcHBlbmRDaGlsZChiYXIpO1xuICAgICAgICB9KTtcbiAgICB9KTtcbiAgICByZXR1cm4gZztcbn1cblxuZnVuY3Rpb24gZHJhd0FsaWduTGluZXMoYm9hcmQ6IFBsYWl0Qm9hcmQsIGxpbmVzOiBbUG9pbnQsIFBvaW50XVtdKSB7XG4gICAgY29uc3QgZyA9IGNyZWF0ZUcoKTtcbiAgICBsaW5lcy5mb3JFYWNoKHBvaW50cyA9PiB7XG4gICAgICAgIGlmICghcG9pbnRzLmxlbmd0aCkgcmV0dXJuO1xuICAgICAgICBjb25zdCB4QWxpZ24gPSBQbGFpdEJvYXJkLmdldFJvdWdoU1ZHKGJvYXJkKS5saW5lKHBvaW50c1swXVswXSwgcG9pbnRzWzBdWzFdLCBwb2ludHNbMV1bMF0sIHBvaW50c1sxXVsxXSwge1xuICAgICAgICAgICAgc3Ryb2tlOiBTRUxFQ1RJT05fQk9SREVSX0NPTE9SLFxuICAgICAgICAgICAgc3Ryb2tlV2lkdGg6IDEsXG4gICAgICAgICAgICBzdHJva2VMaW5lRGFzaDogWzQsIDRdXG4gICAgICAgIH0pO1xuICAgICAgICBnLmFwcGVuZENoaWxkKHhBbGlnbik7XG4gICAgfSk7XG4gICAgcmV0dXJuIGc7XG59XG5cbmV4cG9ydCBjb25zdCBnZXRUcmlwbGVBbGlnbkF4aXMgPSAocmVjdGFuZ2xlOiBSZWN0YW5nbGVDbGllbnQsIGlzSG9yaXpvbnRhbDogYm9vbGVhbik6IFRyaXBsZUFsaWduQXhpcyA9PiB7XG4gICAgY29uc3QgYXhpcyA9IGlzSG9yaXpvbnRhbCA/ICd4JyA6ICd5JztcbiAgICBjb25zdCBzaWRlID0gaXNIb3Jpem9udGFsID8gJ3dpZHRoJyA6ICdoZWlnaHQnO1xuICAgIHJldHVybiBbcmVjdGFuZ2xlW2F4aXNdLCByZWN0YW5nbGVbYXhpc10gKyByZWN0YW5nbGVbc2lkZV0gLyAyLCByZWN0YW5nbGVbYXhpc10gKyByZWN0YW5nbGVbc2lkZV1dO1xufTtcblxuZXhwb3J0IGNvbnN0IGlzQWxpZ24gPSAoYXhpczogbnVtYmVyLCByZWN0YW5nbGU6IFJlY3RhbmdsZUNsaWVudCwgaXNIb3Jpem9udGFsOiBib29sZWFuKSA9PiB7XG4gICAgY29uc3QgYWxpZ25BeGlzID0gZ2V0VHJpcGxlQWxpZ25BeGlzKHJlY3RhbmdsZSwgaXNIb3Jpem9udGFsKTtcbiAgICByZXR1cm4gYWxpZ25BeGlzLmluY2x1ZGVzKGF4aXMpO1xufTtcblxuZXhwb3J0IGNvbnN0IGdldENsb3Nlc3REZWx0YSA9IChheGlzOiBudW1iZXIsIHJlY3RhbmdsZTogUmVjdGFuZ2xlQ2xpZW50LCBpc0hvcml6b250YWw6IGJvb2xlYW4pID0+IHtcbiAgICBjb25zdCBhbGlnbkF4aXMgPSBnZXRUcmlwbGVBbGlnbkF4aXMocmVjdGFuZ2xlLCBpc0hvcml6b250YWwpO1xuICAgIGNvbnN0IGRlbHRhcyA9IGFsaWduQXhpcy5tYXAoaXRlbSA9PiBpdGVtIC0gYXhpcyk7XG4gICAgY29uc3QgYWJzRGVsdGFzID0gZGVsdGFzLm1hcChpdGVtID0+IE1hdGguYWJzKGl0ZW0pKTtcbiAgICBjb25zdCBpbmRleCA9IGFic0RlbHRhcy5pbmRleE9mKE1hdGgubWluKC4uLmFic0RlbHRhcykpO1xuICAgIHJldHVybiBkZWx0YXNbaW5kZXhdO1xufTtcblxuZnVuY3Rpb24gZ2V0TWluQWxpZ25EZWx0YShhbGlnblJlY3RhbmdsZXM6IFJlY3RhbmdsZUNsaWVudFtdLCBheGlzOiBudW1iZXIsIGlzSG9yaXpvbnRhbDogYm9vbGVhbikge1xuICAgIGxldCBkZWx0YSA9IEFMSUdOX1RPTEVSQU5DRTtcblxuICAgIGFsaWduUmVjdGFuZ2xlcy5mb3JFYWNoKGl0ZW0gPT4ge1xuICAgICAgICBjb25zdCBkaXN0YW5jZSA9IGdldENsb3Nlc3REZWx0YShheGlzLCBpdGVtLCBpc0hvcml6b250YWwpO1xuICAgICAgICBpZiAoTWF0aC5hYnMoZGlzdGFuY2UpIDwgTWF0aC5hYnMoZGVsdGEpKSB7XG4gICAgICAgICAgICBkZWx0YSA9IGRpc3RhbmNlO1xuICAgICAgICB9XG4gICAgfSk7XG4gICAgcmV0dXJuIGRlbHRhO1xufVxuXG5mdW5jdGlvbiBnZXROZWFyZXN0QWxpZ25SZWN0YW5nbGUoYWxpZ25SZWN0YW5nbGVzOiBSZWN0YW5nbGVDbGllbnRbXSwgYWN0aXZlUmVjdGFuZ2xlOiBSZWN0YW5nbGVDbGllbnQpIHtcbiAgICBsZXQgbWluRGlzdGFuY2UgPSBJbmZpbml0eTtcbiAgICBsZXQgbmVhcmVzdFJlY3RhbmdsZSA9IGFsaWduUmVjdGFuZ2xlc1swXTtcblxuICAgIGFsaWduUmVjdGFuZ2xlcy5mb3JFYWNoKGl0ZW0gPT4ge1xuICAgICAgICBjb25zdCBkaXN0YW5jZSA9IE1hdGguc3FydChNYXRoLnBvdyhhY3RpdmVSZWN0YW5nbGUueCAtIGl0ZW0ueCwgMikgKyBNYXRoLnBvdyhhY3RpdmVSZWN0YW5nbGUueSAtIGl0ZW0ueSwgMikpO1xuICAgICAgICBpZiAoZGlzdGFuY2UgPCBtaW5EaXN0YW5jZSkge1xuICAgICAgICAgICAgbWluRGlzdGFuY2UgPSBkaXN0YW5jZTtcbiAgICAgICAgICAgIG5lYXJlc3RSZWN0YW5nbGUgPSBpdGVtO1xuICAgICAgICB9XG4gICAgfSk7XG4gICAgcmV0dXJuIG5lYXJlc3RSZWN0YW5nbGU7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRSZXNpemVTbmFwUmVmKFxuICAgIGJvYXJkOiBQbGFpdEJvYXJkLFxuICAgIHJlc2l6ZVJlZjogUmVzaXplUmVmPFBsYWl0RHJhd0VsZW1lbnQgfCBQbGFpdERyYXdFbGVtZW50W10+LFxuICAgIHJlc2l6ZVN0YXRlOiBSZXNpemVTdGF0ZSxcbiAgICByZXNpemVPcmlnaW5Qb2ludEFuZEhhbmRsZVBvaW50OiB7XG4gICAgICAgIG9yaWdpblBvaW50OiBQb2ludDtcbiAgICAgICAgaGFuZGxlUG9pbnQ6IFBvaW50O1xuICAgIH0sXG4gICAgaXNBc3BlY3RSYXRpbzogYm9vbGVhbixcbiAgICBpc0Zyb21Db3JuZXI6IGJvb2xlYW5cbik6IFJlc2l6ZVNuYXBSZWYge1xuICAgIGNvbnN0IHsgb3JpZ2luUG9pbnQsIGhhbmRsZVBvaW50IH0gPSByZXNpemVPcmlnaW5Qb2ludEFuZEhhbmRsZVBvaW50O1xuICAgIGNvbnN0IHsgeFpvb20sIHlab29tIH0gPSBnZXRSZXNpemVab29tKHJlc2l6ZVN0YXRlLCBvcmlnaW5Qb2ludCwgaGFuZGxlUG9pbnQsIGlzRnJvbUNvcm5lciwgaXNBc3BlY3RSYXRpbyk7XG5cbiAgICBsZXQgYWN0aXZlRWxlbWVudHM6IFBsYWl0RWxlbWVudFtdO1xuICAgIGxldCByZXNpemVPcmlnaW5Qb2ludHM6IFBvaW50W10gPSBbXTtcbiAgICBpZiAoQXJyYXkuaXNBcnJheShyZXNpemVSZWYuZWxlbWVudCkpIHtcbiAgICAgICAgYWN0aXZlRWxlbWVudHMgPSByZXNpemVSZWYuZWxlbWVudDtcbiAgICAgICAgY29uc3QgcmVjdGFuZ2xlID0gZ2V0UmVjdGFuZ2xlQnlFbGVtZW50cyhib2FyZCwgcmVzaXplUmVmLmVsZW1lbnQsIGZhbHNlKTtcbiAgICAgICAgcmVzaXplT3JpZ2luUG9pbnRzID0gUmVjdGFuZ2xlQ2xpZW50LmdldFBvaW50cyhyZWN0YW5nbGUpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGFjdGl2ZUVsZW1lbnRzID0gW3Jlc2l6ZVJlZi5lbGVtZW50XTtcbiAgICAgICAgcmVzaXplT3JpZ2luUG9pbnRzID0gcmVzaXplUmVmLmVsZW1lbnQucG9pbnRzO1xuICAgIH1cblxuICAgIGNvbnN0IHBvaW50cyA9IHJlc2l6ZU9yaWdpblBvaW50cy5tYXAocCA9PiB7XG4gICAgICAgIHJldHVybiBtb3ZlUG9pbnRCeVpvb21BbmRPcmlnaW5Qb2ludChwLCBvcmlnaW5Qb2ludCwgeFpvb20sIHlab29tKTtcbiAgICB9KSBhcyBbUG9pbnQsIFBvaW50XTtcbiAgICBjb25zdCBhY3RpdmVSZWN0YW5nbGUgPVxuICAgICAgICBnZXRSZWN0YW5nbGVCeUFuZ2xlKFJlY3RhbmdsZUNsaWVudC5nZXRSZWN0YW5nbGVCeVBvaW50cyhwb2ludHMpLCBnZXRTZWxlY3Rpb25BbmdsZShhY3RpdmVFbGVtZW50cykpIHx8XG4gICAgICAgIFJlY3RhbmdsZUNsaWVudC5nZXRSZWN0YW5nbGVCeVBvaW50cyhwb2ludHMpO1xuXG4gICAgY29uc3QgcmVzaXplU25hcFJlYWN0aW9uID0gbmV3IFJlc2l6ZVNuYXBSZWFjdGlvbihib2FyZCwgYWN0aXZlRWxlbWVudHMpO1xuICAgIGNvbnN0IHJlc2l6ZUhhbmRsZVBvaW50ID0gbW92ZVBvaW50Qnlab29tQW5kT3JpZ2luUG9pbnQoaGFuZGxlUG9pbnQsIG9yaWdpblBvaW50LCB4Wm9vbSwgeVpvb20pO1xuICAgIGNvbnN0IFt4LCB5XSA9IGdldFVuaXRWZWN0b3JCeVBvaW50QW5kUG9pbnQob3JpZ2luUG9pbnQsIHJlc2l6ZUhhbmRsZVBvaW50KTtcblxuICAgIHJldHVybiByZXNpemVTbmFwUmVhY3Rpb24uaGFuZGxlUmVzaXplU25hcCh7XG4gICAgICAgIHJlc2l6ZVN0YXRlLFxuICAgICAgICByZXNpemVPcmlnaW5Qb2ludHMsXG4gICAgICAgIGFjdGl2ZVJlY3RhbmdsZSxcbiAgICAgICAgb3JpZ2luUG9pbnQsXG4gICAgICAgIGhhbmRsZVBvaW50LFxuICAgICAgICBkaXJlY3Rpb25GYWN0b3JzOiBbZ2V0RGlyZWN0aW9uRmFjdG9yQnlEaXJlY3Rpb25Db21wb25lbnQoeCksIGdldERpcmVjdGlvbkZhY3RvckJ5RGlyZWN0aW9uQ29tcG9uZW50KHkpXSxcbiAgICAgICAgaXNBc3BlY3RSYXRpbyxcbiAgICAgICAgaXNGcm9tQ29ybmVyXG4gICAgfSk7XG59XG4iXX0=