@libs-ui/services-grid-layout 0.2.357-19
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.
- package/README.md +109 -0
- package/canvas/grid-layout-canvas.component.d.ts +107 -0
- package/defines/gridster-config.define.d.ts +21 -0
- package/esm2022/canvas/grid-layout-canvas.component.mjs +193 -0
- package/esm2022/defines/gridster-config.define.mjs +123 -0
- package/esm2022/grid-layout.service.mjs +433 -0
- package/esm2022/index.mjs +10 -0
- package/esm2022/interfaces/grid-layout.interface.mjs +2 -0
- package/esm2022/libs-ui-services-grid-layout.mjs +5 -0
- package/esm2022/tree.service.mjs +180 -0
- package/fesm2022/libs-ui-services-grid-layout.mjs +933 -0
- package/fesm2022/libs-ui-services-grid-layout.mjs.map +1 -0
- package/grid-layout.service.d.ts +157 -0
- package/index.d.ts +3 -0
- package/interfaces/grid-layout.interface.d.ts +171 -0
- package/package.json +29 -0
- package/tree.service.d.ts +59 -0
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import { Injectable } from '@angular/core';
|
|
2
|
+
import { uuid } from '@libs-ui/utils';
|
|
3
|
+
import * as i0 from "@angular/core";
|
|
4
|
+
/**
|
|
5
|
+
* Thao tác trên cây khối: tìm, thêm, xoá, dồn khít, chặn lồng cấp quá sâu.
|
|
6
|
+
*
|
|
7
|
+
* 🔴 NỘI BỘ thư viện — không xuất ra ngoài. Nơi dùng đi qua `LibsUiGridLayoutService`, ở đó mỗi
|
|
8
|
+
* thao tác sửa bố cục vừa vẽ lại vừa bắn `outChange` đúng MỘT lần. Các hàm ở đây cố tình KHÔNG tự
|
|
9
|
+
* vẽ lại: để chúng tự gọi thì mỗi thao tác vẽ hai lượt và bắn hai sự kiện (người dùng chốt
|
|
10
|
+
* 28/08/2026: "đặt đúng các điểm mà làm cho layout có thể thay đổi thôi").
|
|
11
|
+
*/
|
|
12
|
+
export class LibsUiGridLayoutTreeService {
|
|
13
|
+
findById(node, id) {
|
|
14
|
+
if (node.id === id) {
|
|
15
|
+
return node;
|
|
16
|
+
}
|
|
17
|
+
for (const child of node.children ?? []) {
|
|
18
|
+
const found = this.findById(child, id);
|
|
19
|
+
if (found) {
|
|
20
|
+
return found;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return undefined;
|
|
24
|
+
}
|
|
25
|
+
findParent(node, id) {
|
|
26
|
+
for (const child of node.children ?? []) {
|
|
27
|
+
if (child.id === id) {
|
|
28
|
+
return node;
|
|
29
|
+
}
|
|
30
|
+
const found = this.findParent(child, id);
|
|
31
|
+
if (found) {
|
|
32
|
+
return found;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return undefined;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Thêm khối vào cuối một container. Thư viện tự sinh `id` và tự đặt `x` · `y` xuống hàng trống.
|
|
39
|
+
*
|
|
40
|
+
* @returns khối vừa tạo (kèm `id` vừa sinh), hoặc `undefined` khi không tìm thấy container.
|
|
41
|
+
*/
|
|
42
|
+
addChild(root, parentId, item) {
|
|
43
|
+
const parent = this.findById(root, parentId);
|
|
44
|
+
if (!parent) {
|
|
45
|
+
return undefined;
|
|
46
|
+
}
|
|
47
|
+
parent.children = parent.children ?? [];
|
|
48
|
+
// 🔴 Thư viện tự sinh `id`. Đây là mã máy dùng để tra cứu, không phải thứ người dùng nghĩ ra —
|
|
49
|
+
// bắt họ tự đặt là mời họ tạo trùng, mà trùng id thì `findById` trả nhầm khối và cả cây hỏng
|
|
50
|
+
// im lặng (người dùng chốt 28/08/2026).
|
|
51
|
+
const node = { ...item, id: item.id ?? uuid(), x: 0, y: this.nextFreeRow(parent.children) };
|
|
52
|
+
parent.children.push(node);
|
|
53
|
+
// Trả về khối vừa tạo để nơi dùng biết `id` thư viện vừa sinh.
|
|
54
|
+
return node;
|
|
55
|
+
}
|
|
56
|
+
/** Xoá một khối khỏi cây. Không cho xoá gốc. */
|
|
57
|
+
removeById(root, id) {
|
|
58
|
+
if (root.id === id) {
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
const parent = this.findParent(root, id);
|
|
62
|
+
if (!parent?.children) {
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
parent.children = parent.children.filter((item) => item.id !== id);
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Chuyển một khối đơn thành CONTAINER: nội dung cũ trở thành khối con đầu tiên.
|
|
70
|
+
*
|
|
71
|
+
* Không mất dữ liệu — `data` của khối được mang theo xuống khối con.
|
|
72
|
+
*
|
|
73
|
+
* @returns `false` khi không tìm thấy khối, hoặc khối đã là container rồi.
|
|
74
|
+
*/
|
|
75
|
+
toContainer(root, id, colCount) {
|
|
76
|
+
const node = this.findById(root, id);
|
|
77
|
+
if (!node || (node.children?.length ?? 0) > 0) {
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
node.children = [{ ...node, id: uuid(), x: 0, y: 0, cols: colCount, rows: 4, children: [] }];
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Chuyển một CONTAINER về khối đơn: các khối con được NÂNG lên cấp trên, không bị xoá.
|
|
85
|
+
*
|
|
86
|
+
* @returns `false` khi không tìm thấy khối, hoặc khối vốn không phải container.
|
|
87
|
+
*/
|
|
88
|
+
toSingle(root, id) {
|
|
89
|
+
const node = this.findById(root, id);
|
|
90
|
+
if (!node || (node.children?.length ?? 0) === 0) {
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
const parent = this.findParent(root, id);
|
|
94
|
+
for (const child of node.children ?? []) {
|
|
95
|
+
parent?.children?.push({ ...child, cols: node.cols, rows: 2 });
|
|
96
|
+
}
|
|
97
|
+
node.children = [];
|
|
98
|
+
return true;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Làm phẳng mọi container lồng vượt trần.
|
|
102
|
+
*
|
|
103
|
+
* 🔴 Cần thiết vì bố cục ĐÃ LƯU không đi qua luật chặn nào của giao diện. Một bản lưu cũ — sinh
|
|
104
|
+
* trước khi có trần, hoặc do thao tác lỗi — vẫn nạp thẳng vào và hiện container lồng container.
|
|
105
|
+
* Container vượt trần bị hạ thành khối thường, con của nó nâng lên cấp trên: KHÔNG mất dữ liệu.
|
|
106
|
+
*
|
|
107
|
+
* @returns số container đã làm phẳng
|
|
108
|
+
*/
|
|
109
|
+
flattenOverDepthContainers(node, maxDepth) {
|
|
110
|
+
return this.walkFlatten(node, 0, maxDepth);
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Dồn khối khít lên trên theo thứ tự đọc, lấp hết chỗ trống.
|
|
114
|
+
*
|
|
115
|
+
* 🔴 KHÔNG sửa `node.rows` của container. Chiều cao container tính theo đơn vị hàng của lưới CHA,
|
|
116
|
+
* còn `currentRow` đếm theo đơn vị hàng của lưới CON — trộn hai thang đo là container phình lên
|
|
117
|
+
* gấp mấy lần.
|
|
118
|
+
*/
|
|
119
|
+
compact(node, colCount) {
|
|
120
|
+
this.walkCompact(node, colCount);
|
|
121
|
+
}
|
|
122
|
+
walkCompact(node, colCount) {
|
|
123
|
+
const children = node.children;
|
|
124
|
+
if (!children?.length) {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
const inReadingOrder = [...children].sort((a, b) => a.y - b.y || a.x - b.x);
|
|
128
|
+
let currentRow = 0;
|
|
129
|
+
let usedCols = 0;
|
|
130
|
+
let tallestInRow = 0;
|
|
131
|
+
for (const item of inReadingOrder) {
|
|
132
|
+
const width = Math.min(item.cols, colCount);
|
|
133
|
+
if (usedCols > 0 && usedCols + width > colCount) {
|
|
134
|
+
currentRow += tallestInRow;
|
|
135
|
+
usedCols = 0;
|
|
136
|
+
tallestInRow = 0;
|
|
137
|
+
}
|
|
138
|
+
item.x = usedCols;
|
|
139
|
+
item.y = currentRow;
|
|
140
|
+
item.cols = width;
|
|
141
|
+
usedCols += width;
|
|
142
|
+
tallestInRow = Math.max(tallestInRow, item.rows);
|
|
143
|
+
if ((item.children?.length ?? 0) > 0) {
|
|
144
|
+
this.walkCompact(item, colCount);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
walkFlatten(node, containerDepth, maxDepth) {
|
|
149
|
+
const children = node.children;
|
|
150
|
+
if (!children?.length) {
|
|
151
|
+
return 0;
|
|
152
|
+
}
|
|
153
|
+
let fixedCount = 0;
|
|
154
|
+
const result = [];
|
|
155
|
+
for (const child of children) {
|
|
156
|
+
const isContainer = (child.children?.length ?? 0) > 0;
|
|
157
|
+
if (isContainer && containerDepth >= maxDepth) {
|
|
158
|
+
fixedCount += 1;
|
|
159
|
+
for (const item of child.children ?? []) {
|
|
160
|
+
fixedCount += this.walkFlatten(item, containerDepth, maxDepth);
|
|
161
|
+
result.push(item);
|
|
162
|
+
}
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
fixedCount += this.walkFlatten(child, isContainer ? containerDepth + 1 : containerDepth, maxDepth);
|
|
166
|
+
result.push(child);
|
|
167
|
+
}
|
|
168
|
+
node.children = result;
|
|
169
|
+
return fixedCount;
|
|
170
|
+
}
|
|
171
|
+
nextFreeRow(children) {
|
|
172
|
+
return children.reduce((max, child) => Math.max(max, child.y + child.rows), 0);
|
|
173
|
+
}
|
|
174
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: LibsUiGridLayoutTreeService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
175
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: LibsUiGridLayoutTreeService });
|
|
176
|
+
}
|
|
177
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: LibsUiGridLayoutTreeService, decorators: [{
|
|
178
|
+
type: Injectable
|
|
179
|
+
}] });
|
|
180
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJlZS5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vbGlicy11aS9zZXJ2aWNlcy9ncmlkLWxheW91dC9zcmMvdHJlZS5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDM0MsT0FBTyxFQUFFLElBQUksRUFBRSxNQUFNLGdCQUFnQixDQUFDOztBQUd0Qzs7Ozs7OztHQU9HO0FBRUgsTUFBTSxPQUFPLDJCQUEyQjtJQUN0QyxRQUFRLENBQUMsSUFBdUIsRUFBRSxFQUFVO1FBQzFDLElBQUksSUFBSSxDQUFDLEVBQUUsS0FBSyxFQUFFLEVBQUUsQ0FBQztZQUNuQixPQUFPLElBQUksQ0FBQztRQUNkLENBQUM7UUFFRCxLQUFLLE1BQU0sS0FBSyxJQUFJLElBQUksQ0FBQyxRQUFRLElBQUksRUFBRSxFQUFFLENBQUM7WUFDeEMsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUM7WUFFdkMsSUFBSSxLQUFLLEVBQUUsQ0FBQztnQkFDVixPQUFPLEtBQUssQ0FBQztZQUNmLENBQUM7UUFDSCxDQUFDO1FBRUQsT0FBTyxTQUFTLENBQUM7SUFDbkIsQ0FBQztJQUVELFVBQVUsQ0FBQyxJQUF1QixFQUFFLEVBQVU7UUFDNUMsS0FBSyxNQUFNLEtBQUssSUFBSSxJQUFJLENBQUMsUUFBUSxJQUFJLEVBQUUsRUFBRSxDQUFDO1lBQ3hDLElBQUksS0FBSyxDQUFDLEVBQUUsS0FBSyxFQUFFLEVBQUUsQ0FBQztnQkFDcEIsT0FBTyxJQUFJLENBQUM7WUFDZCxDQUFDO1lBRUQsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUM7WUFFekMsSUFBSSxLQUFLLEVBQUUsQ0FBQztnQkFDVixPQUFPLEtBQUssQ0FBQztZQUNmLENBQUM7UUFDSCxDQUFDO1FBRUQsT0FBTyxTQUFTLENBQUM7SUFDbkIsQ0FBQztJQUVEOzs7O09BSUc7SUFDSCxRQUFRLENBQUMsSUFBdUIsRUFBRSxRQUFnQixFQUFFLElBQTBCO1FBQzVFLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLFFBQVEsQ0FBQyxDQUFDO1FBRTdDLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUNaLE9BQU8sU0FBUyxDQUFDO1FBQ25CLENBQUM7UUFFRCxNQUFNLENBQUMsUUFBUSxHQUFHLE1BQU0sQ0FBQyxRQUFRLElBQUksRUFBRSxDQUFDO1FBQ3hDLCtGQUErRjtRQUMvRiw2RkFBNkY7UUFDN0Ysd0NBQXdDO1FBQ3hDLE1BQU0sSUFBSSxHQUFzQixFQUFFLEdBQUcsSUFBSSxFQUFFLEVBQUUsRUFBRSxJQUFJLENBQUMsRUFBRSxJQUFJLElBQUksRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLElBQUksQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUM7UUFFL0csTUFBTSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7UUFFM0IsK0RBQStEO1FBQy9ELE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUVELGdEQUFnRDtJQUNoRCxVQUFVLENBQUMsSUFBdUIsRUFBRSxFQUFVO1FBQzVDLElBQUksSUFBSSxDQUFDLEVBQUUsS0FBSyxFQUFFLEVBQUUsQ0FBQztZQUNuQixPQUFPLEtBQUssQ0FBQztRQUNmLENBQUM7UUFFRCxNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsQ0FBQztRQUV6QyxJQUFJLENBQUMsTUFBTSxFQUFFLFFBQVEsRUFBRSxDQUFDO1lBQ3RCLE9BQU8sS0FBSyxDQUFDO1FBQ2YsQ0FBQztRQUVELE1BQU0sQ0FBQyxRQUFRLEdBQUcsTUFBTSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7UUFFbkUsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBRUQ7Ozs7OztPQU1HO0lBQ0gsV0FBVyxDQUFDLElBQXVCLEVBQUUsRUFBVSxFQUFFLFFBQWdCO1FBQy9ELE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBRXJDLElBQUksQ0FBQyxJQUFJLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLE1BQU0sSUFBSSxDQUFDLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUM5QyxPQUFPLEtBQUssQ0FBQztRQUNmLENBQUM7UUFFRCxJQUFJLENBQUMsUUFBUSxHQUFHLENBQUMsRUFBRSxHQUFHLElBQUksRUFBRSxFQUFFLEVBQUUsSUFBSSxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFLENBQUMsRUFBRSxRQUFRLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQztRQUU3RixPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsUUFBUSxDQUFDLElBQXVCLEVBQUUsRUFBVTtRQUMxQyxNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsQ0FBQztRQUVyQyxJQUFJLENBQUMsSUFBSSxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRSxNQUFNLElBQUksQ0FBQyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUM7WUFDaEQsT0FBTyxLQUFLLENBQUM7UUFDZixDQUFDO1FBRUQsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFFekMsS0FBSyxNQUFNLEtBQUssSUFBSSxJQUFJLENBQUMsUUFBUSxJQUFJLEVBQUUsRUFBRSxDQUFDO1lBQ3hDLE1BQU0sRUFBRSxRQUFRLEVBQUUsSUFBSSxDQUFDLEVBQUUsR0FBRyxLQUFLLEVBQUUsSUFBSSxFQUFFLElBQUksQ0FBQyxJQUFJLEVBQUUsSUFBSSxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDakUsQ0FBQztRQUVELElBQUksQ0FBQyxRQUFRLEdBQUcsRUFBRSxDQUFDO1FBRW5CLE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUVEOzs7Ozs7OztPQVFHO0lBQ0gsMEJBQTBCLENBQUMsSUFBdUIsRUFBRSxRQUFnQjtRQUNsRSxPQUFPLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxFQUFFLENBQUMsRUFBRSxRQUFRLENBQUMsQ0FBQztJQUM3QyxDQUFDO0lBRUQ7Ozs7OztPQU1HO0lBQ0gsT0FBTyxDQUFDLElBQXVCLEVBQUUsUUFBZ0I7UUFDL0MsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLEVBQUUsUUFBUSxDQUFDLENBQUM7SUFDbkMsQ0FBQztJQUVPLFdBQVcsQ0FBQyxJQUF1QixFQUFFLFFBQWdCO1FBQzNELE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUM7UUFFL0IsSUFBSSxDQUFDLFFBQVEsRUFBRSxNQUFNLEVBQUUsQ0FBQztZQUN0QixPQUFPO1FBQ1QsQ0FBQztRQUVELE1BQU0sY0FBYyxHQUFHLENBQUMsR0FBRyxRQUFRLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDNUUsSUFBSSxVQUFVLEdBQUcsQ0FBQyxDQUFDO1FBQ25CLElBQUksUUFBUSxHQUFHLENBQUMsQ0FBQztRQUNqQixJQUFJLFlBQVksR0FBRyxDQUFDLENBQUM7UUFFckIsS0FBSyxNQUFNLElBQUksSUFBSSxjQUFjLEVBQUUsQ0FBQztZQUNsQyxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsUUFBUSxDQUFDLENBQUM7WUFFNUMsSUFBSSxRQUFRLEdBQUcsQ0FBQyxJQUFJLFFBQVEsR0FBRyxLQUFLLEdBQUcsUUFBUSxFQUFFLENBQUM7Z0JBQ2hELFVBQVUsSUFBSSxZQUFZLENBQUM7Z0JBQzNCLFFBQVEsR0FBRyxDQUFDLENBQUM7Z0JBQ2IsWUFBWSxHQUFHLENBQUMsQ0FBQztZQUNuQixDQUFDO1lBRUQsSUFBSSxDQUFDLENBQUMsR0FBRyxRQUFRLENBQUM7WUFDbEIsSUFBSSxDQUFDLENBQUMsR0FBRyxVQUFVLENBQUM7WUFDcEIsSUFBSSxDQUFDLElBQUksR0FBRyxLQUFLLENBQUM7WUFDbEIsUUFBUSxJQUFJLEtBQUssQ0FBQztZQUNsQixZQUFZLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxZQUFZLEVBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBRWpELElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLE1BQU0sSUFBSSxDQUFDLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztnQkFDckMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLEVBQUUsUUFBUSxDQUFDLENBQUM7WUFDbkMsQ0FBQztRQUNILENBQUM7SUFDSCxDQUFDO0lBRU8sV0FBVyxDQUFDLElBQXVCLEVBQUUsY0FBc0IsRUFBRSxRQUFnQjtRQUNuRixNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDO1FBRS9CLElBQUksQ0FBQyxRQUFRLEVBQUUsTUFBTSxFQUFFLENBQUM7WUFDdEIsT0FBTyxDQUFDLENBQUM7UUFDWCxDQUFDO1FBRUQsSUFBSSxVQUFVLEdBQUcsQ0FBQyxDQUFDO1FBQ25CLE1BQU0sTUFBTSxHQUE2QixFQUFFLENBQUM7UUFFNUMsS0FBSyxNQUFNLEtBQUssSUFBSSxRQUFRLEVBQUUsQ0FBQztZQUM3QixNQUFNLFdBQVcsR0FBRyxDQUFDLEtBQUssQ0FBQyxRQUFRLEVBQUUsTUFBTSxJQUFJLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUV0RCxJQUFJLFdBQVcsSUFBSSxjQUFjLElBQUksUUFBUSxFQUFFLENBQUM7Z0JBQzlDLFVBQVUsSUFBSSxDQUFDLENBQUM7Z0JBRWhCLEtBQUssTUFBTSxJQUFJLElBQUksS0FBSyxDQUFDLFFBQVEsSUFBSSxFQUFFLEVBQUUsQ0FBQztvQkFDeEMsVUFBVSxJQUFJLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxFQUFFLGNBQWMsRUFBRSxRQUFRLENBQUMsQ0FBQztvQkFDL0QsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztnQkFDcEIsQ0FBQztnQkFFRCxTQUFTO1lBQ1gsQ0FBQztZQUVELFVBQVUsSUFBSSxJQUFJLENBQUMsV0FBVyxDQUFDLEtBQUssRUFBRSxXQUFXLENBQUMsQ0FBQyxDQUFDLGNBQWMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLGNBQWMsRUFBRSxRQUFRLENBQUMsQ0FBQztZQUNuRyxNQUFNLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ3JCLENBQUM7UUFFRCxJQUFJLENBQUMsUUFBUSxHQUFHLE1BQU0sQ0FBQztRQUV2QixPQUFPLFVBQVUsQ0FBQztJQUNwQixDQUFDO0lBRU8sV0FBVyxDQUFDLFFBQWtDO1FBQ3BELE9BQU8sUUFBUSxDQUFDLE1BQU0sQ0FBQyxDQUFDLEdBQUcsRUFBRSxLQUFLLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLEtBQUssQ0FBQyxDQUFDLEdBQUcsS0FBSyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ2pGLENBQUM7d0dBaE5VLDJCQUEyQjs0R0FBM0IsMkJBQTJCOzs0RkFBM0IsMkJBQTJCO2tCQUR2QyxVQUFVIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0YWJsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgdXVpZCB9IGZyb20gJ0BsaWJzLXVpL3V0aWxzJztcbmltcG9ydCB7IFRfZ3JpZExheW91dF9uZXdOb2RlLCBUX2dyaWRMYXlvdXRfbm9kZSB9IGZyb20gJy4vaW50ZXJmYWNlcy9ncmlkLWxheW91dC5pbnRlcmZhY2UnO1xuXG4vKipcbiAqIFRoYW8gdMOhYyB0csOqbiBjw6J5IGto4buRaTogdMOsbSwgdGjDqm0sIHhvw6EsIGThu5NuIGtow610LCBjaOG6t24gbOG7k25nIGPhuqVwIHF1w6Egc8OidS5cbiAqXG4gKiDwn5S0IE7hu5hJIELhu5ggdGjGsCB2aeG7h24g4oCUIGtow7RuZyB4deG6pXQgcmEgbmdvw6BpLiBOxqFpIGTDuW5nIMSRaSBxdWEgYExpYnNVaUdyaWRMYXlvdXRTZXJ2aWNlYCwg4bufIMSRw7MgbeG7l2lcbiAqIHRoYW8gdMOhYyBz4butYSBi4buRIGPhu6VjIHbhu6thIHbhur0gbOG6oWkgduG7q2EgYuG6r24gYG91dENoYW5nZWAgxJHDum5nIE3hu5hUIGzhuqduLiBDw6FjIGjDoG0g4bufIMSRw6J5IGPhu5EgdMOsbmggS0jDlE5HIHThu7FcbiAqIHbhur0gbOG6oWk6IMSR4buDIGNow7puZyB04buxIGfhu41pIHRow6wgbeG7l2kgdGhhbyB0w6FjIHbhur0gaGFpIGzGsOG7o3QgdsOgIGLhuq9uIGhhaSBz4buxIGtp4buHbiAobmfGsOG7nWkgZMO5bmcgY2jhu5F0XG4gKiAyOC8wOC8yMDI2OiBcIsSR4bq3dCDEkcO6bmcgY8OhYyDEkWnhu4NtIG3DoCBsw6BtIGNobyBsYXlvdXQgY8OzIHRo4buDIHRoYXkgxJHhu5VpIHRow7RpXCIpLlxuICovXG5ASW5qZWN0YWJsZSgpXG5leHBvcnQgY2xhc3MgTGlic1VpR3JpZExheW91dFRyZWVTZXJ2aWNlIHtcbiAgZmluZEJ5SWQobm9kZTogVF9ncmlkTGF5b3V0X25vZGUsIGlkOiBzdHJpbmcpOiBUX2dyaWRMYXlvdXRfbm9kZSB8IHVuZGVmaW5lZCB7XG4gICAgaWYgKG5vZGUuaWQgPT09IGlkKSB7XG4gICAgICByZXR1cm4gbm9kZTtcbiAgICB9XG5cbiAgICBmb3IgKGNvbnN0IGNoaWxkIG9mIG5vZGUuY2hpbGRyZW4gPz8gW10pIHtcbiAgICAgIGNvbnN0IGZvdW5kID0gdGhpcy5maW5kQnlJZChjaGlsZCwgaWQpO1xuXG4gICAgICBpZiAoZm91bmQpIHtcbiAgICAgICAgcmV0dXJuIGZvdW5kO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cblxuICBmaW5kUGFyZW50KG5vZGU6IFRfZ3JpZExheW91dF9ub2RlLCBpZDogc3RyaW5nKTogVF9ncmlkTGF5b3V0X25vZGUgfCB1bmRlZmluZWQge1xuICAgIGZvciAoY29uc3QgY2hpbGQgb2Ygbm9kZS5jaGlsZHJlbiA/PyBbXSkge1xuICAgICAgaWYgKGNoaWxkLmlkID09PSBpZCkge1xuICAgICAgICByZXR1cm4gbm9kZTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgZm91bmQgPSB0aGlzLmZpbmRQYXJlbnQoY2hpbGQsIGlkKTtcblxuICAgICAgaWYgKGZvdW5kKSB7XG4gICAgICAgIHJldHVybiBmb3VuZDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG5cbiAgLyoqXG4gICAqIFRow6ptIGto4buRaSB2w6BvIGN14buRaSBt4buZdCBjb250YWluZXIuIFRoxrAgdmnhu4duIHThu7Egc2luaCBgaWRgIHbDoCB04buxIMSR4bq3dCBgeGAgwrcgYHlgIHh14buRbmcgaMOgbmcgdHLhu5FuZy5cbiAgICpcbiAgICogQHJldHVybnMga2jhu5FpIHbhu6thIHThuqFvIChrw6htIGBpZGAgduG7q2Egc2luaCksIGhv4bq3YyBgdW5kZWZpbmVkYCBraGkga2jDtG5nIHTDrG0gdGjhuqV5IGNvbnRhaW5lci5cbiAgICovXG4gIGFkZENoaWxkKHJvb3Q6IFRfZ3JpZExheW91dF9ub2RlLCBwYXJlbnRJZDogc3RyaW5nLCBpdGVtOiBUX2dyaWRMYXlvdXRfbmV3Tm9kZSk6IFRfZ3JpZExheW91dF9ub2RlIHwgdW5kZWZpbmVkIHtcbiAgICBjb25zdCBwYXJlbnQgPSB0aGlzLmZpbmRCeUlkKHJvb3QsIHBhcmVudElkKTtcblxuICAgIGlmICghcGFyZW50KSB7XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIHBhcmVudC5jaGlsZHJlbiA9IHBhcmVudC5jaGlsZHJlbiA/PyBbXTtcbiAgICAvLyDwn5S0IFRoxrAgdmnhu4duIHThu7Egc2luaCBgaWRgLiDEkMOieSBsw6AgbcOjIG3DoXkgZMO5bmcgxJHhu4MgdHJhIGPhu6l1LCBraMO0bmcgcGjhuqNpIHRo4bupIG5nxrDhu51pIGTDuW5nIG5naMSpIHJhIOKAlFxuICAgIC8vIGLhuq90IGjhu40gdOG7sSDEkeG6t3QgbMOgIG3hu51pIGjhu40gdOG6oW8gdHLDuW5nLCBtw6AgdHLDuW5nIGlkIHRow6wgYGZpbmRCeUlkYCB0cuG6oyBuaOG6p20ga2jhu5FpIHbDoCBj4bqjIGPDonkgaOG7j25nXG4gICAgLy8gaW0gbOG6t25nIChuZ8aw4budaSBkw7luZyBjaOG7kXQgMjgvMDgvMjAyNikuXG4gICAgY29uc3Qgbm9kZTogVF9ncmlkTGF5b3V0X25vZGUgPSB7IC4uLml0ZW0sIGlkOiBpdGVtLmlkID8/IHV1aWQoKSwgeDogMCwgeTogdGhpcy5uZXh0RnJlZVJvdyhwYXJlbnQuY2hpbGRyZW4pIH07XG5cbiAgICBwYXJlbnQuY2hpbGRyZW4ucHVzaChub2RlKTtcblxuICAgIC8vIFRy4bqjIHbhu4Ega2jhu5FpIHbhu6thIHThuqFvIMSR4buDIG7GoWkgZMO5bmcgYmnhur90IGBpZGAgdGjGsCB2aeG7h24gduG7q2Egc2luaC5cbiAgICByZXR1cm4gbm9kZTtcbiAgfVxuXG4gIC8qKiBYb8OhIG3hu5l0IGto4buRaSBraOG7j2kgY8OieS4gS2jDtG5nIGNobyB4b8OhIGfhu5FjLiAqL1xuICByZW1vdmVCeUlkKHJvb3Q6IFRfZ3JpZExheW91dF9ub2RlLCBpZDogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgaWYgKHJvb3QuaWQgPT09IGlkKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgY29uc3QgcGFyZW50ID0gdGhpcy5maW5kUGFyZW50KHJvb3QsIGlkKTtcblxuICAgIGlmICghcGFyZW50Py5jaGlsZHJlbikge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHBhcmVudC5jaGlsZHJlbiA9IHBhcmVudC5jaGlsZHJlbi5maWx0ZXIoKGl0ZW0pID0+IGl0ZW0uaWQgIT09IGlkKTtcblxuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgLyoqXG4gICAqIENodXnhu4NuIG3hu5l0IGto4buRaSDEkcahbiB0aMOgbmggQ09OVEFJTkVSOiBu4buZaSBkdW5nIGPFqSB0cuG7nyB0aMOgbmgga2jhu5FpIGNvbiDEkeG6p3UgdGnDqm4uXG4gICAqXG4gICAqIEtow7RuZyBt4bqldCBk4buvIGxp4buHdSDigJQgYGRhdGFgIGPhu6dhIGto4buRaSDEkcaw4bujYyBtYW5nIHRoZW8geHXhu5FuZyBraOG7kWkgY29uLlxuICAgKlxuICAgKiBAcmV0dXJucyBgZmFsc2VgIGtoaSBraMO0bmcgdMOsbSB0aOG6pXkga2jhu5FpLCBob+G6t2Mga2jhu5FpIMSRw6MgbMOgIGNvbnRhaW5lciBy4buTaS5cbiAgICovXG4gIHRvQ29udGFpbmVyKHJvb3Q6IFRfZ3JpZExheW91dF9ub2RlLCBpZDogc3RyaW5nLCBjb2xDb3VudDogbnVtYmVyKTogYm9vbGVhbiB7XG4gICAgY29uc3Qgbm9kZSA9IHRoaXMuZmluZEJ5SWQocm9vdCwgaWQpO1xuXG4gICAgaWYgKCFub2RlIHx8IChub2RlLmNoaWxkcmVuPy5sZW5ndGggPz8gMCkgPiAwKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgbm9kZS5jaGlsZHJlbiA9IFt7IC4uLm5vZGUsIGlkOiB1dWlkKCksIHg6IDAsIHk6IDAsIGNvbHM6IGNvbENvdW50LCByb3dzOiA0LCBjaGlsZHJlbjogW10gfV07XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDaHV54buDbiBt4buZdCBDT05UQUlORVIgduG7gSBraOG7kWkgxJHGoW46IGPDoWMga2jhu5FpIGNvbiDEkcaw4bujYyBOw4JORyBsw6puIGPhuqVwIHRyw6puLCBraMO0bmcgYuG7iyB4b8OhLlxuICAgKlxuICAgKiBAcmV0dXJucyBgZmFsc2VgIGtoaSBraMO0bmcgdMOsbSB0aOG6pXkga2jhu5FpLCBob+G6t2Mga2jhu5FpIHbhu5FuIGtow7RuZyBwaOG6o2kgY29udGFpbmVyLlxuICAgKi9cbiAgdG9TaW5nbGUocm9vdDogVF9ncmlkTGF5b3V0X25vZGUsIGlkOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICBjb25zdCBub2RlID0gdGhpcy5maW5kQnlJZChyb290LCBpZCk7XG5cbiAgICBpZiAoIW5vZGUgfHwgKG5vZGUuY2hpbGRyZW4/Lmxlbmd0aCA/PyAwKSA9PT0gMCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGNvbnN0IHBhcmVudCA9IHRoaXMuZmluZFBhcmVudChyb290LCBpZCk7XG5cbiAgICBmb3IgKGNvbnN0IGNoaWxkIG9mIG5vZGUuY2hpbGRyZW4gPz8gW10pIHtcbiAgICAgIHBhcmVudD8uY2hpbGRyZW4/LnB1c2goeyAuLi5jaGlsZCwgY29sczogbm9kZS5jb2xzLCByb3dzOiAyIH0pO1xuICAgIH1cblxuICAgIG5vZGUuY2hpbGRyZW4gPSBbXTtcblxuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgLyoqXG4gICAqIEzDoG0gcGjhurNuZyBt4buNaSBjb250YWluZXIgbOG7k25nIHbGsOG7o3QgdHLhuqduLlxuICAgKlxuICAgKiDwn5S0IEPhuqduIHRoaeG6v3QgdsOsIGLhu5EgY+G7pWMgxJDDgyBMxq9VIGtow7RuZyDEkWkgcXVhIGx14bqtdCBjaOG6t24gbsOgbyBj4bunYSBnaWFvIGRp4buHbi4gTeG7mXQgYuG6o24gbMawdSBjxakg4oCUIHNpbmhcbiAgICogdHLGsOG7m2Mga2hpIGPDsyB0cuG6p24sIGhv4bq3YyBkbyB0aGFvIHTDoWMgbOG7l2kg4oCUIHbhuqtuIG7huqFwIHRo4bqzbmcgdsOgbyB2w6AgaGnhu4duIGNvbnRhaW5lciBs4buTbmcgY29udGFpbmVyLlxuICAgKiBDb250YWluZXIgdsaw4bujdCB0cuG6p24gYuG7iyBo4bqhIHRow6BuaCBraOG7kWkgdGjGsOG7nW5nLCBjb24gY+G7p2EgbsOzIG7Dom5nIGzDqm4gY+G6pXAgdHLDqm46IEtIw5RORyBt4bqldCBk4buvIGxp4buHdS5cbiAgICpcbiAgICogQHJldHVybnMgc+G7kSBjb250YWluZXIgxJHDoyBsw6BtIHBo4bqzbmdcbiAgICovXG4gIGZsYXR0ZW5PdmVyRGVwdGhDb250YWluZXJzKG5vZGU6IFRfZ3JpZExheW91dF9ub2RlLCBtYXhEZXB0aDogbnVtYmVyKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy53YWxrRmxhdHRlbihub2RlLCAwLCBtYXhEZXB0aCk7XG4gIH1cblxuICAvKipcbiAgICogROG7k24ga2jhu5FpIGtow610IGzDqm4gdHLDqm4gdGhlbyB0aOG7qSB04buxIMSR4buNYywgbOG6pXAgaOG6v3QgY2jhu5cgdHLhu5FuZy5cbiAgICpcbiAgICog8J+UtCBLSMOUTkcgc+G7rWEgYG5vZGUucm93c2AgY+G7p2EgY29udGFpbmVyLiBDaGnhu4F1IGNhbyBjb250YWluZXIgdMOtbmggdGhlbyDEkcahbiB24buLIGjDoG5nIGPhu6dhIGzGsOG7m2kgQ0hBLFxuICAgKiBjw7JuIGBjdXJyZW50Um93YCDEkeG6v20gdGhlbyDEkcahbiB24buLIGjDoG5nIGPhu6dhIGzGsOG7m2kgQ09OIOKAlCB0cuG7mW4gaGFpIHRoYW5nIMSRbyBsw6AgY29udGFpbmVyIHBow6xuaCBsw6puXG4gICAqIGfhuqVwIG3huqV5IGzhuqduLlxuICAgKi9cbiAgY29tcGFjdChub2RlOiBUX2dyaWRMYXlvdXRfbm9kZSwgY29sQ291bnQ6IG51bWJlcik6IHZvaWQge1xuICAgIHRoaXMud2Fsa0NvbXBhY3Qobm9kZSwgY29sQ291bnQpO1xuICB9XG5cbiAgcHJpdmF0ZSB3YWxrQ29tcGFjdChub2RlOiBUX2dyaWRMYXlvdXRfbm9kZSwgY29sQ291bnQ6IG51bWJlcik6IHZvaWQge1xuICAgIGNvbnN0IGNoaWxkcmVuID0gbm9kZS5jaGlsZHJlbjtcblxuICAgIGlmICghY2hpbGRyZW4/Lmxlbmd0aCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IGluUmVhZGluZ09yZGVyID0gWy4uLmNoaWxkcmVuXS5zb3J0KChhLCBiKSA9PiBhLnkgLSBiLnkgfHwgYS54IC0gYi54KTtcbiAgICBsZXQgY3VycmVudFJvdyA9IDA7XG4gICAgbGV0IHVzZWRDb2xzID0gMDtcbiAgICBsZXQgdGFsbGVzdEluUm93ID0gMDtcblxuICAgIGZvciAoY29uc3QgaXRlbSBvZiBpblJlYWRpbmdPcmRlcikge1xuICAgICAgY29uc3Qgd2lkdGggPSBNYXRoLm1pbihpdGVtLmNvbHMsIGNvbENvdW50KTtcblxuICAgICAgaWYgKHVzZWRDb2xzID4gMCAmJiB1c2VkQ29scyArIHdpZHRoID4gY29sQ291bnQpIHtcbiAgICAgICAgY3VycmVudFJvdyArPSB0YWxsZXN0SW5Sb3c7XG4gICAgICAgIHVzZWRDb2xzID0gMDtcbiAgICAgICAgdGFsbGVzdEluUm93ID0gMDtcbiAgICAgIH1cblxuICAgICAgaXRlbS54ID0gdXNlZENvbHM7XG4gICAgICBpdGVtLnkgPSBjdXJyZW50Um93O1xuICAgICAgaXRlbS5jb2xzID0gd2lkdGg7XG4gICAgICB1c2VkQ29scyArPSB3aWR0aDtcbiAgICAgIHRhbGxlc3RJblJvdyA9IE1hdGgubWF4KHRhbGxlc3RJblJvdywgaXRlbS5yb3dzKTtcblxuICAgICAgaWYgKChpdGVtLmNoaWxkcmVuPy5sZW5ndGggPz8gMCkgPiAwKSB7XG4gICAgICAgIHRoaXMud2Fsa0NvbXBhY3QoaXRlbSwgY29sQ291bnQpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgd2Fsa0ZsYXR0ZW4obm9kZTogVF9ncmlkTGF5b3V0X25vZGUsIGNvbnRhaW5lckRlcHRoOiBudW1iZXIsIG1heERlcHRoOiBudW1iZXIpOiBudW1iZXIge1xuICAgIGNvbnN0IGNoaWxkcmVuID0gbm9kZS5jaGlsZHJlbjtcblxuICAgIGlmICghY2hpbGRyZW4/Lmxlbmd0aCkge1xuICAgICAgcmV0dXJuIDA7XG4gICAgfVxuXG4gICAgbGV0IGZpeGVkQ291bnQgPSAwO1xuICAgIGNvbnN0IHJlc3VsdDogQXJyYXk8VF9ncmlkTGF5b3V0X25vZGU+ID0gW107XG5cbiAgICBmb3IgKGNvbnN0IGNoaWxkIG9mIGNoaWxkcmVuKSB7XG4gICAgICBjb25zdCBpc0NvbnRhaW5lciA9IChjaGlsZC5jaGlsZHJlbj8ubGVuZ3RoID8/IDApID4gMDtcblxuICAgICAgaWYgKGlzQ29udGFpbmVyICYmIGNvbnRhaW5lckRlcHRoID49IG1heERlcHRoKSB7XG4gICAgICAgIGZpeGVkQ291bnQgKz0gMTtcblxuICAgICAgICBmb3IgKGNvbnN0IGl0ZW0gb2YgY2hpbGQuY2hpbGRyZW4gPz8gW10pIHtcbiAgICAgICAgICBmaXhlZENvdW50ICs9IHRoaXMud2Fsa0ZsYXR0ZW4oaXRlbSwgY29udGFpbmVyRGVwdGgsIG1heERlcHRoKTtcbiAgICAgICAgICByZXN1bHQucHVzaChpdGVtKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICBmaXhlZENvdW50ICs9IHRoaXMud2Fsa0ZsYXR0ZW4oY2hpbGQsIGlzQ29udGFpbmVyID8gY29udGFpbmVyRGVwdGggKyAxIDogY29udGFpbmVyRGVwdGgsIG1heERlcHRoKTtcbiAgICAgIHJlc3VsdC5wdXNoKGNoaWxkKTtcbiAgICB9XG5cbiAgICBub2RlLmNoaWxkcmVuID0gcmVzdWx0O1xuXG4gICAgcmV0dXJuIGZpeGVkQ291bnQ7XG4gIH1cblxuICBwcml2YXRlIG5leHRGcmVlUm93KGNoaWxkcmVuOiBBcnJheTxUX2dyaWRMYXlvdXRfbm9kZT4pOiBudW1iZXIge1xuICAgIHJldHVybiBjaGlsZHJlbi5yZWR1Y2UoKG1heCwgY2hpbGQpID0+IE1hdGgubWF4KG1heCwgY2hpbGQueSArIGNoaWxkLnJvd3MpLCAwKTtcbiAgfVxufVxuIl19
|