@libs-ui/components-spreadsheet 0.2.356-43

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.
@@ -0,0 +1,869 @@
1
+ import { ChangeDetectionStrategy, Component, NgZone, effect, inject, input, output, signal, untracked, viewChild } from '@angular/core';
2
+ import { LocaleType, Univer, UniverInstanceType } from '@univerjs/core';
3
+ import { defaultTheme } from '@univerjs/design';
4
+ import { UniverDocsPlugin } from '@univerjs/docs';
5
+ import { UniverDocsUIPlugin } from '@univerjs/docs-ui';
6
+ import { UniverFormulaEnginePlugin } from '@univerjs/engine-formula';
7
+ import { UniverRenderEnginePlugin } from '@univerjs/engine-render';
8
+ import { FUniver } from '@univerjs/facade';
9
+ import { InsertColMutation, MoveColsMutation, RemoveColMutation, UniverSheetsPlugin } from '@univerjs/sheets';
10
+ import { UniverSheetsFormulaPlugin } from '@univerjs/sheets-formula';
11
+ import { UniverSheetsFormulaUIPlugin } from '@univerjs/sheets-formula-ui';
12
+ import { UniverSheetsNumfmtPlugin } from '@univerjs/sheets-numfmt';
13
+ import { UniverSheetsUIPlugin } from '@univerjs/sheets-ui';
14
+ import { UniverUIPlugin } from '@univerjs/ui';
15
+ import { univerLocaleEn, univerLocaleVi } from './spreadsheet.locale';
16
+ import { injectCustomDateFormats, syncActiveNumfmtHighlight } from './spreadsheet.numfmt';
17
+ import { applyMappingIndicators, stripMappingIndicators } from './spreadsheet.indicator';
18
+ import * as i0 from "@angular/core";
19
+ // Bộ đếm tạo class scope duy nhất cho mỗi instance spreadsheet (dùng cho <style> chỉnh width toolbar).
20
+ let spreadsheetInstanceCount = 0;
21
+ export class LibsUiComponentsSpreadsheetComponent {
22
+ univer = null;
23
+ univerAPI = null;
24
+ columnClickDisposable = null;
25
+ formatDisposable = null;
26
+ columnOpDisposable = null;
27
+ numfmtObserver = null;
28
+ toolbarResizeObserver = null;
29
+ // <style> riêng cho instance: pin width container đo qua CSS rule (React re-render KHÔNG strip được →
30
+ // tránh vòng lặp oscillation giữa set-inline-width và React strip gây kẹt ⋮). Xem registerToolbarWidthSync.
31
+ toolbarStyleEl = null;
32
+ toolbarScopeClass = `libs-ui-spreadsheet-tb-${(spreadsheetInstanceCount += 1)}`;
33
+ numfmtClickDisposable = null;
34
+ lastRangeSnapshot = null;
35
+ pendingNumfmtPattern = null;
36
+ // true CHỈ khi user bấm nút Confirm trong panel numfmt → giữ format; Cancel/X/click-ngoài = false → revert.
37
+ numfmtConfirmed = false;
38
+ // Snapshot numfmt từng ô của vùng chọn tại thời điểm mở panel — dùng khôi phục chính xác khi Cancel.
39
+ originalCellFormats = null;
40
+ numfmtPanelOpen = false;
41
+ // true khi luồng Date custom đang hoạt động (đã inject option ngày). CHỈ khi đó component mới
42
+ // can thiệp confirm/revert; các Type khác (Số, Tiền tệ, %, Text…) do Univer tự xử lý → không đụng vào.
43
+ numfmtDateActive = false;
44
+ // Đồng bộ lại panel Date (label + highlight + auto-apply) theo vùng chọn mới khi user đổi cột lúc panel mở.
45
+ numfmtResync = null;
46
+ listenEnabled = false;
47
+ listenEnableTimer = null;
48
+ // Defer initial empty-workbook init to allow parent's ngAfterViewInit to call loadData
49
+ // first (cancelling the empty init), avoiding a race with Univer's async React renders.
50
+ pendingInitTimer = null;
51
+ numfmtCleanup = null;
52
+ pendingReadyCb = null;
53
+ // Snapshot đã-decorate gần nhất — làm baseline để diff (style id ổn định 'h'/'m', không bị
54
+ // ảnh hưởng bởi style id tự sinh sau mỗi facade setValue). Dùng cho re-apply incremental.
55
+ lastDecorated = null;
56
+ readyObserver = null;
57
+ // Cache controller numfmt nội bộ của Univer (giữ _previewPattern). Tìm 1 lần qua injector.
58
+ // CONVENTION-EXCEPT: any — NumfmtController không export khỏi @univerjs/sheets-numfmt
59
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
60
+ numfmtController = null;
61
+ activeCellFormat = signal('General');
62
+ activeCellRef = signal('');
63
+ showToolbar = signal(true);
64
+ showSheetTabs = signal(true);
65
+ // Ngôn ngữ đang hiển thị thực tế. Khởi tạo từ input `locale` trong ngAfterViewInit,
66
+ // sau đó đổi runtime qua setLocale() (kéo theo reinit để Univer render lại UI).
67
+ activeLocale = signal('vi');
68
+ /** Ngôn ngữ khởi tạo của spreadsheet. Đổi runtime dùng FunctionControl.setLocale(). */
69
+ locale = input('vi');
70
+ /** Cấu hình ẩn / vô hiệu hoá toolbar items. Thay đổi sẽ reinit toàn bộ Univer. */
71
+ toolbarMenuConfig = input({
72
+ // 'sheet.command.numfmt.set.currency': { hidden: true },
73
+ // 'sheet.command.numfmt.add.decimal.command': { hidden: true },
74
+ // 'sheet.command.numfmt.subtract.decimal.command': { hidden: true },
75
+ // 'sheet.command.numfmt.set.percent': { hidden: true },
76
+ 'sheet.command.set-once-format-painter': { hidden: true },
77
+ 'sheet.command.set-text-rotation': { hidden: true },
78
+ 'sheet.command.set-range-font-family': { hidden: true },
79
+ 'sheet.command.set-border-basic': { hidden: true },
80
+ 'sheet.command.add-worksheet-merge': { hidden: true },
81
+ 'sheet.command.add-worksheet-merge-all': { hidden: true },
82
+ 'sheet.command.add-worksheet-merge-vertical': { hidden: true },
83
+ 'sheet.command.add-worksheet-merge-horizontal': { hidden: true },
84
+ 'sheet.command.remove-worksheet-merge': { hidden: true },
85
+ });
86
+ /**
87
+ * Cấu hình highlight cột đã map (style / prefix / scope sheet).
88
+ * Truyền config này = "bật" luồng auto: component sẽ TỰ áp indicator khi load/reset,
89
+ * TỰ gỡ khi save, và TỰ vẽ lại mỗi khi `mappingTargets` đổi. Bỏ trống = spreadsheet thường.
90
+ */
91
+ mappingIndicatorConfig = input();
92
+ /** Danh sách cột cần highlight (`{ sheetId, colIndex }`). Đổi runtime → tự vẽ lại header. */
93
+ mappingTargets = input([]);
94
+ outColumnDblClick = output();
95
+ /**
96
+ * Phát khi user insert / remove / move cột (kể cả chọn nhiều cột, và cả undo/redo).
97
+ * Consumer dùng `remapColumnIndexes(mappings, $event)` để dịch lại mảng mapping bên ngoài
98
+ * cho khớp vị trí mới — tránh lệch khi chèn/xóa cột ở giữa.
99
+ */
100
+ outColumnStructureChange = output();
101
+ containerRef = viewChild('containerRef');
102
+ ngZone = inject(NgZone);
103
+ constructor() {
104
+ // Auto re-apply: chỉ chạy khi đã bật config + Univer đã khởi tạo. Lần đầu (chưa init) tự bỏ qua.
105
+ effect(() => {
106
+ this.mappingTargets();
107
+ this.mappingIndicatorConfig();
108
+ untracked(() => this.reapplyIndicators());
109
+ });
110
+ }
111
+ ngAfterViewInit() {
112
+ this.activeLocale.set(this.locale());
113
+ this.pendingInitTimer = setTimeout(() => {
114
+ this.pendingInitTimer = null;
115
+ this.initUniver(this.buildEmptyWorkbook());
116
+ });
117
+ }
118
+ get FunctionControl() {
119
+ return {
120
+ loadData: (data) => this.loadData(data),
121
+ saveData: () => this.saveData(),
122
+ getActiveSheetInfo: () => this.getActiveSheetInfo(),
123
+ getColumnNumfmt: (sheetId, colIndex) => this.getColumnNumfmt(sheetId, colIndex),
124
+ extractAllColumnFormats: (snapshot) => this.extractAllColumnFormats(snapshot),
125
+ toggleToolbar: () => this.toggleToolbar(),
126
+ toggleSheetTabs: () => this.toggleSheetTabs(),
127
+ reset: (data) => this.reset(data),
128
+ executeCommand: (commandId, params) => this.executeCommand(commandId, params),
129
+ applyNumfmt: (row, col, numRows, numCols, pattern) => this.applyNumfmt(row, col, numRows, numCols, pattern),
130
+ scheduleOnReady: (cb) => {
131
+ this.pendingReadyCb = cb;
132
+ },
133
+ setLocale: (locale) => this.setLocale(locale),
134
+ activeCellRef: this.activeCellRef,
135
+ activeCellFormat: this.activeCellFormat,
136
+ showToolbar: this.showToolbar,
137
+ showSheetTabs: this.showSheetTabs,
138
+ locale: this.activeLocale.asReadonly(),
139
+ };
140
+ }
141
+ setLocale(locale) {
142
+ if (locale === this.activeLocale())
143
+ return;
144
+ this.activeLocale.set(locale);
145
+ this.reinitUniver();
146
+ }
147
+ loadData(data) {
148
+ const decorated = this.decorateSnapshot(data);
149
+ if (this.pendingInitTimer !== null) {
150
+ clearTimeout(this.pendingInitTimer);
151
+ this.pendingInitTimer = null;
152
+ this.initUniver(decorated);
153
+ return;
154
+ }
155
+ this.destroyUniver();
156
+ setTimeout(() => this.initUniver(decorated));
157
+ }
158
+ /** Snapshot thô từ Univer (CÓ thể còn indicator). Dùng nội bộ cho re-apply. */
159
+ saveRaw() {
160
+ return (this.univerAPI?.getActiveWorkbook()?.save() ?? {});
161
+ }
162
+ /** Snapshot trả cho consumer — tự gỡ indicator nếu luồng auto đang bật. */
163
+ saveData() {
164
+ const config = this.mappingIndicatorConfig();
165
+ if (!config)
166
+ return this.saveRaw();
167
+ return stripMappingIndicators(this.saveRaw(), config);
168
+ }
169
+ /** Áp indicator vào snapshot trước khi load — chỉ khi luồng auto đang bật. Lưu baseline để diff. */
170
+ decorateSnapshot(data) {
171
+ const config = this.mappingIndicatorConfig();
172
+ if (!config)
173
+ return data;
174
+ const decorated = applyMappingIndicators(data, this.mappingTargets(), config);
175
+ this.lastDecorated = decorated;
176
+ return decorated;
177
+ }
178
+ /**
179
+ * Vẽ lại indicator KHÔNG reinit Univer: tính snapshot đích rồi CHỈ ghi đè đúng các ô header
180
+ * khác so với baseline trước đó (style + prefix + width) lên instance live qua facade.
181
+ * Diff theo baseline (style id ổn định 'h'/'m') → chỉ các cột vừa map/bỏ map mới được vẽ lại.
182
+ */
183
+ reapplyIndicators() {
184
+ const config = this.mappingIndicatorConfig();
185
+ const wb = this.univerAPI?.getActiveWorkbook();
186
+ const prev = this.lastDecorated;
187
+ if (!config || !wb || !prev)
188
+ return;
189
+ const next = applyMappingIndicators(this.saveRaw(), this.mappingTargets(), config);
190
+ this.lastDecorated = next;
191
+ const headerKey = String(config.headerRowIndex ?? 0);
192
+ const headerRow = Number(headerKey);
193
+ const stylesNext = (next['styles'] ?? {});
194
+ const sheetsNext = (next['sheets'] ?? {});
195
+ const sheetsPrev = (prev['sheets'] ?? {});
196
+ for (const sheetId of Object.keys(sheetsNext)) {
197
+ const ws = wb.getSheetBySheetId(sheetId);
198
+ if (!ws)
199
+ continue;
200
+ const nextRow = sheetsNext[sheetId]?.cellData?.[headerKey] ?? {};
201
+ const prevRow = sheetsPrev[sheetId]?.cellData?.[headerKey] ?? {};
202
+ const colData = sheetsNext[sheetId]?.columnData ?? {};
203
+ for (const colKey of Object.keys(nextRow)) {
204
+ const cellNext = nextRow[colKey];
205
+ const cellPrev = prevRow[colKey];
206
+ // Ô không đổi cả value lẫn style → bỏ qua (mấu chốt: chỉ vẽ lại cột vừa map/bỏ map).
207
+ if (!cellNext || (cellNext.v === cellPrev?.v && cellNext.s === cellPrev?.s))
208
+ continue;
209
+ const style = (typeof cellNext.s === 'string' ? stylesNext[cellNext.s] : cellNext.s);
210
+ const cell = { v: cellNext.v, s: style };
211
+ void ws.getRange(headerRow, Number(colKey)).setValue(cell);
212
+ const width = colData[colKey]?.w;
213
+ if (typeof width === 'number')
214
+ void ws.setColumnWidth(Number(colKey), width);
215
+ }
216
+ }
217
+ }
218
+ toggleToolbar() {
219
+ this.showToolbar.update((v) => !v);
220
+ this.reinitUniver();
221
+ }
222
+ toggleSheetTabs() {
223
+ this.showSheetTabs.update((v) => !v);
224
+ this.reinitUniver();
225
+ }
226
+ reset(data) {
227
+ this.destroyUniver();
228
+ this.initUniver(this.decorateSnapshot(data ?? this.buildEmptyWorkbook()));
229
+ }
230
+ executeCommand(commandId, params) {
231
+ // CONVENTION-EXCEPT: any — FUniver.executeCommand không expose typing
232
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
233
+ void this.univerAPI?.executeCommand?.(commandId, params);
234
+ }
235
+ applyNumfmt(row, col, numRows, numCols, pattern) {
236
+ // CONVENTION-EXCEPT: any — FWorkbook.getId / FWorksheet.getSheetId not exposed in public types
237
+ // Note: FRange.setNumberFormat() has a Univer facade bug — it builds `values` but never passes
238
+ // them to executeCommand. We call the command directly with the correct params instead.
239
+ // FWorkbook uses getId() (not getUnitId()) and FWorksheet uses getSheetId() for subUnitId.
240
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
241
+ const wb = this.univerAPI?.getActiveWorkbook();
242
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
243
+ const ws = wb?.getActiveSheet?.();
244
+ if (!wb || !ws)
245
+ return;
246
+ const unitId = (wb.getId?.() ?? '');
247
+ const subUnitId = (ws.getSheetId?.() ?? '');
248
+ const values = [];
249
+ for (let r = row; r < row + numRows; r++) {
250
+ for (let c = col; c < col + numCols; c++) {
251
+ values.push({ pattern, row: r, col: c });
252
+ }
253
+ }
254
+ this.executeCommand('sheet.command.numfmt.set.numfmt', { unitId, subUnitId, values });
255
+ }
256
+ getActiveSheetInfo() {
257
+ // CONVENTION-EXCEPT: any — FWorksheet public types chưa expose getSheetId/getName
258
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
259
+ const sheet = this.univerAPI?.getActiveWorkbook()?.getActiveSheet();
260
+ if (!sheet)
261
+ return null;
262
+ return {
263
+ sheetId: (sheet.getSheetId?.() ?? ''),
264
+ sheetName: (sheet.getSheetName?.() ?? sheet.getName?.() ?? ''),
265
+ };
266
+ }
267
+ /** Đọc numfmt pattern của một cell từ workbook snapshot. */
268
+ readCellNumfmt(sheetId, row, col) {
269
+ try {
270
+ // CONVENTION-EXCEPT: any — FWorkbook.save() không expose typing
271
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
272
+ const ss = this.univerAPI?.getActiveWorkbook()?.save();
273
+ const styles = ss?.styles;
274
+ const cells = ss?.sheets?.[sheetId]?.cellData;
275
+ const styleId = cells?.[String(row)]?.[String(col)]?.s;
276
+ if (!styleId || !styles)
277
+ return 'General';
278
+ return styles[styleId]?.n?.pattern ?? styles[styleId]?.nf?.pattern ?? 'General';
279
+ }
280
+ catch {
281
+ return 'General';
282
+ }
283
+ }
284
+ /** Đọc giá trị số (Excel serial) của một ô; null nếu ô rỗng/không phải số. */
285
+ readCellValue(sheetId, row, col) {
286
+ try {
287
+ // CONVENTION-EXCEPT: any — FWorkbook.save() không expose typing
288
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
289
+ const ss = this.univerAPI?.getActiveWorkbook()?.save();
290
+ const cells = ss?.sheets?.[sheetId]?.cellData;
291
+ const value = cells?.[String(row)]?.[String(col)]?.v;
292
+ return typeof value === 'number' && isFinite(value) ? value : null;
293
+ }
294
+ catch {
295
+ return null;
296
+ }
297
+ }
298
+ getColumnNumfmt(sheetId, colIndex) {
299
+ for (const row of [1, 2, 3]) {
300
+ const pattern = this.readCellNumfmt(sheetId, row, colIndex);
301
+ if (pattern !== 'General')
302
+ return pattern;
303
+ }
304
+ return 'General';
305
+ }
306
+ /** Chụp numfmt gốc từng ô của vùng chọn (giới hạn 500 dòng như applyFormat) để Cancel khôi phục đúng. */
307
+ captureRangeNumfmt(snap) {
308
+ if (!snap)
309
+ return null;
310
+ const values = [];
311
+ const maxRow = Math.min(snap.endRow, snap.startRow + 499);
312
+ for (let r = snap.startRow; r <= maxRow; r++) {
313
+ for (let c = snap.startColumn; c <= snap.endColumn; c++) {
314
+ values.push({ pattern: this.readCellNumfmt(snap.subUnitId, r, c), row: r, col: c });
315
+ }
316
+ }
317
+ return values.length ? values : null;
318
+ }
319
+ extractAllColumnFormats(snapshot) {
320
+ const styles = snapshot['styles'];
321
+ const sheets = snapshot['sheets'];
322
+ const order = snapshot['sheetOrder'];
323
+ if (!styles || !sheets)
324
+ return [];
325
+ const results = [];
326
+ const seen = new Set();
327
+ for (const sheetId of order ?? Object.keys(sheets)) {
328
+ const sheetData = sheets[sheetId];
329
+ if (!sheetData?.cellData)
330
+ continue;
331
+ const sheetName = sheetData.name ?? sheetId;
332
+ const headerRow = sheetData.cellData['0'] ?? {};
333
+ for (const rowKey of ['1', '2', '3']) {
334
+ const row = sheetData.cellData[rowKey];
335
+ if (!row)
336
+ continue;
337
+ for (const colKey of Object.keys(row)) {
338
+ const key = `${sheetId}:${colKey}`;
339
+ if (seen.has(key))
340
+ continue;
341
+ const styleId = row[colKey]?.s;
342
+ if (!styleId)
343
+ continue;
344
+ const pattern = styles[styleId]?.n?.pattern ?? styles[styleId]?.nf?.pattern;
345
+ if (!pattern)
346
+ continue;
347
+ seen.add(key);
348
+ const colIndex = parseInt(colKey, 10);
349
+ const colLetter = this.toColLetter(colIndex);
350
+ const headerV = headerRow[colKey]?.v;
351
+ results.push({
352
+ sheet: sheetName,
353
+ col: colLetter,
354
+ colIndex,
355
+ header: headerV ? String(headerV) : colLetter,
356
+ numfmt: pattern,
357
+ });
358
+ }
359
+ }
360
+ }
361
+ return results;
362
+ }
363
+ toColLetter(index) {
364
+ let result = '';
365
+ let n = index;
366
+ do {
367
+ result = String.fromCharCode(65 + (n % 26)) + result;
368
+ n = Math.floor(n / 26) - 1;
369
+ } while (n >= 0);
370
+ return result;
371
+ }
372
+ buildEmptyWorkbook() {
373
+ return {
374
+ id: 'workbook-default',
375
+ locale: this.resolveLocaleType(),
376
+ name: 'Sheet',
377
+ sheetOrder: ['sheet1'],
378
+ appVersion: '3.0.0-alpha',
379
+ sheets: {
380
+ sheet1: { id: 'sheet1', name: 'Sheet1', rowCount: 30, columnCount: 26, cellData: {} },
381
+ },
382
+ };
383
+ }
384
+ resolveLocaleType() {
385
+ return this.activeLocale() === 'vi' ? LocaleType.VI_VN : LocaleType.EN_US;
386
+ }
387
+ registerColumnClickListener() {
388
+ const wrapper = this.containerRef()?.nativeElement;
389
+ if (!wrapper)
390
+ return;
391
+ this.listenEnableTimer = setTimeout(() => {
392
+ this.listenEnabled = true;
393
+ }, 600);
394
+ const handleDblClick = (event) => {
395
+ if (!this.listenEnabled)
396
+ return;
397
+ if (event.target.tagName !== 'CANVAS')
398
+ return;
399
+ setTimeout(() => {
400
+ this.ngZone.run(() => {
401
+ const range = this.univerAPI?.getActiveWorkbook()?.getActiveSheet()?.getActiveRange();
402
+ if (!range)
403
+ return;
404
+ const { startRow, endRow, startColumn, rangeType } = range.getRange();
405
+ const isColHeader = rangeType === 2 || (startRow === 0 && endRow >= 29);
406
+ const isFirstRow = startRow === 0 && endRow === 0;
407
+ if (!isColHeader && !isFirstRow)
408
+ return;
409
+ this.outColumnDblClick.emit(startColumn);
410
+ });
411
+ }, 50);
412
+ };
413
+ wrapper.addEventListener('dblclick', handleDblClick);
414
+ this.columnClickDisposable = { dispose: () => wrapper.removeEventListener('dblclick', handleDblClick) };
415
+ }
416
+ /**
417
+ * Lắng nghe MUTATION cột (insert/remove/move) — mức mutation để bắt cả undo/redo, một lần/thao tác.
418
+ * Chuẩn hoá thành `T_columnStructureChange` rồi phát ra ngoài cho consumer remap mapping.
419
+ */
420
+ registerColumnOpListener() {
421
+ // CONVENTION-EXCEPT: any — FUniver.onCommandExecuted / commandInfo không expose trong public types
422
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
423
+ const api = this.univerAPI;
424
+ if (typeof api?.onCommandExecuted !== 'function')
425
+ return;
426
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
427
+ this.columnOpDisposable = api.onCommandExecuted((commandInfo) => {
428
+ const change = this.toColumnStructureChange(commandInfo?.id, commandInfo?.params);
429
+ if (change)
430
+ this.ngZone.run(() => this.outColumnStructureChange.emit(change));
431
+ });
432
+ }
433
+ toColumnStructureChange(id, params) {
434
+ const p = params;
435
+ const sheetId = p?.subUnitId ?? '';
436
+ if (id === InsertColMutation.id || id === RemoveColMutation.id) {
437
+ if (!p?.range)
438
+ return null;
439
+ const type = id === InsertColMutation.id ? 'insert' : 'remove';
440
+ return { sheetId, type, startColumn: p.range.startColumn, count: p.range.endColumn - p.range.startColumn + 1 };
441
+ }
442
+ if (id === MoveColsMutation.id) {
443
+ if (!p?.sourceRange || !p?.targetRange)
444
+ return null;
445
+ return {
446
+ sheetId,
447
+ type: 'move',
448
+ startColumn: p.sourceRange.startColumn,
449
+ count: p.sourceRange.endColumn - p.sourceRange.startColumn + 1,
450
+ toColumn: p.targetRange.startColumn,
451
+ };
452
+ }
453
+ return null;
454
+ }
455
+ registerFormatListener() {
456
+ // CONVENTION-EXCEPT: any — FUniver.onCommandExecuted / commandInfo không expose trong public types
457
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
458
+ const api = this.univerAPI;
459
+ if (typeof api?.onCommandExecuted !== 'function')
460
+ return;
461
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
462
+ this.formatDisposable = api.onCommandExecuted((commandInfo) => {
463
+ this.ngZone.run(() => {
464
+ if (commandInfo?.id === 'sheet.operation.open.numfmt.panel') {
465
+ this.numfmtPanelOpen = true;
466
+ this.numfmtConfirmed = false; // reset cờ — phiên mới mặc định chưa Confirm
467
+ this.numfmtDateActive = false; // chưa chọn Type=Date → chưa kích hoạt luồng custom
468
+ // Lưu numfmt gốc từng ô để Cancel khôi phục đúng (vùng chọn có thể nhiều format khác nhau)
469
+ this.originalCellFormats = this.captureRangeNumfmt(this.lastRangeSnapshot);
470
+ // Chỉ bật observer khi panel mở (tránh chạy liên tục theo mọi mutation toàn trang)
471
+ this.numfmtObserver?.observe(document.body, { childList: true, subtree: true });
472
+ // Reopen: Univer hiện lại panel cũ bằng CSS (không mutation) → observer không fire. Chủ động
473
+ // thử inject sau 1 nhịp để bắt trường hợp list ngày đã sẵn trong DOM tái dùng.
474
+ setTimeout(() => {
475
+ if (this.numfmtPanelOpen)
476
+ this.processNumfmtPanel();
477
+ }, 60);
478
+ return;
479
+ }
480
+ if (commandInfo?.id === 'sheet.operation.close.numfmt.panel') {
481
+ this.numfmtPanelOpen = false;
482
+ // Tắt observer khi đóng (perf). KHÔNG gỡ listener: Univer tái dùng DOM panel, gỡ sẽ làm
483
+ // option chết khi mở lại. cleanup chạy trước lần inject mới (DOM mới) hoặc khi destroy.
484
+ this.numfmtObserver?.disconnect();
485
+ // Univer TÁI DÙNG DOM panel khi reopen (nhớ cả Type=Date) → guard data-custom-dates còn sót sẽ
486
+ // chặn re-inject ở lần mở sau, khiến highlight stale + dateActive=false (mất revert). Xoá guard
487
+ // để lần mở kế tiếp inject lại + resync highlight/auto-apply theo cột hiện tại.
488
+ document.querySelector('.numfmt-panel ul.univer-select-list')?.removeAttribute('data-custom-dates');
489
+ // Chỉ khi bấm CONFIRM (numfmtConfirmed=true) mới GIỮ pattern đã chọn cho cả vùng.
490
+ // Cancel / X / click-ngoài đều KHÔNG set cờ → KHÔI PHỤC numfmt GỐC TỪNG Ô (đã chụp khi mở panel).
491
+ const dateActive = this.numfmtDateActive;
492
+ const confirmed = this.numfmtConfirmed;
493
+ const pending = this.pendingNumfmtPattern;
494
+ const originalCells = this.originalCellFormats;
495
+ this.numfmtConfirmed = false;
496
+ this.pendingNumfmtPattern = null;
497
+ this.originalCellFormats = null;
498
+ this.numfmtDateActive = false;
499
+ // Type khác Date (Số/Tiền tệ/%/Text…) do Univer tự apply/cancel → KHÔNG can thiệp,
500
+ // nếu không sẽ revert nhầm format mà user vừa áp qua luồng native của Univer.
501
+ if (!dateActive) {
502
+ this.clearNumfmtPreview();
503
+ return;
504
+ }
505
+ const snap = this.lastRangeSnapshot;
506
+ if (!snap)
507
+ return;
508
+ let values;
509
+ if (confirmed && pending) {
510
+ values = [];
511
+ for (let r = snap.startRow; r <= Math.min(snap.endRow, snap.startRow + 499); r++) {
512
+ for (let c = snap.startColumn; c <= snap.endColumn; c++) {
513
+ values.push({ pattern: pending, row: r, col: c });
514
+ }
515
+ }
516
+ }
517
+ else if (!confirmed && originalCells) {
518
+ values = originalCells;
519
+ }
520
+ else {
521
+ return;
522
+ }
523
+ if (!values.length)
524
+ return;
525
+ // CONVENTION-EXCEPT: any — FUniver.executeCommand không expose typing
526
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
527
+ void this.univerAPI?.executeCommand?.('sheet.command.numfmt.set.numfmt', {
528
+ unitId: snap.unitId,
529
+ subUnitId: snap.subUnitId,
530
+ values,
531
+ });
532
+ this.clearNumfmtPreview();
533
+ return;
534
+ }
535
+ // Khi panel đang mở: CHỈ user đổi vùng chọn trên grid (set-selections) mới được cập nhật snapshot
536
+ // để re-target panel sang cột/cell mới. Command nội bộ panel (numfmt.set, mutation…) KHÔNG đụng snapshot.
537
+ const isUserSelection = commandInfo?.id === 'sheet.operation.set-selections';
538
+ if (this.numfmtPanelOpen && !isUserSelection)
539
+ return;
540
+ const wb = this.univerAPI?.getActiveWorkbook();
541
+ const ws = wb?.getActiveSheet();
542
+ const range = ws?.getActiveRange();
543
+ if (!range || !wb || !ws)
544
+ return;
545
+ const rangeData = range.getRange();
546
+ this.activeCellRef.set(`${this.toColLetter(rangeData.startColumn)}${rangeData.startRow + 1}`);
547
+ // CONVENTION-EXCEPT: any — FWorkbook.getId / FWorksheet.getSheetId chưa expose trong types
548
+ /* eslint-disable @typescript-eslint/no-explicit-any */
549
+ const wbAny = wb;
550
+ const wsAny = ws;
551
+ /* eslint-enable @typescript-eslint/no-explicit-any */
552
+ this.lastRangeSnapshot = {
553
+ unitId: (wbAny.getId?.() ?? wbAny.getUnitId?.() ?? ''),
554
+ subUnitId: (wsAny.getSheetId?.() ?? wsAny.getUnitId?.() ?? ''),
555
+ startRow: rangeData.startRow,
556
+ endRow: rangeData.endRow,
557
+ startColumn: rangeData.startColumn,
558
+ endColumn: rangeData.endColumn,
559
+ };
560
+ // CONVENTION-EXCEPT: any — FRange.getCellStyleData chưa expose trong types
561
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
562
+ const rangeAny = range;
563
+ const style = rangeAny.getCellStyleData?.();
564
+ const numFmt = style?.n?.pattern ?? style?.nf?.pattern;
565
+ this.activeCellFormat.set(numFmt && numFmt !== '0' ? numFmt : 'General');
566
+ // User đổi vùng chọn LÚC panel Date đang mở → tích luỹ numfmt gốc của vùng mới (để Cancel
567
+ // revert đúng mọi ô đã chạm) rồi đồng bộ lại panel (label + highlight + auto-apply) theo cột mới.
568
+ if (this.numfmtPanelOpen && this.numfmtDateActive) {
569
+ this.mergeOriginalCellFormats(this.captureRangeNumfmt(this.lastRangeSnapshot));
570
+ this.numfmtResync?.();
571
+ }
572
+ });
573
+ });
574
+ }
575
+ /** Gộp numfmt gốc của vùng vừa chọn vào snapshot revert, giữ giá trị GỐC ĐẦU TIÊN cho mỗi ô. */
576
+ mergeOriginalCellFormats(extra) {
577
+ if (!extra)
578
+ return;
579
+ if (!this.originalCellFormats) {
580
+ this.originalCellFormats = extra;
581
+ return;
582
+ }
583
+ const seen = new Set(this.originalCellFormats.map((v) => `${v.row}:${v.col}`));
584
+ for (const cell of extra) {
585
+ if (seen.has(`${cell.row}:${cell.col}`))
586
+ continue;
587
+ this.originalCellFormats.push(cell);
588
+ }
589
+ }
590
+ /**
591
+ * Xoá live-preview overlay của Univer numfmt panel.
592
+ *
593
+ * Khi panel numfmt mở, `NumfmtController._previewPattern` được Univer dùng để vẽ đè
594
+ * (preview) lên hiển thị thật của vùng chọn. Vì các option date custom ghi numfmt
595
+ * trực tiếp vào model (không đi qua panel gốc của Univer), preview này không bao giờ
596
+ * khớp model → cột không đổi hiển thị ngay. Set `_previewPattern = null` + force re-render
597
+ * (`_forceUpdate`) để canvas vẽ đúng giá trị model tức thì.
598
+ *
599
+ * NumfmtController không export khỏi `@univerjs/sheets-numfmt` nên phải tìm instance
600
+ * qua injector của Univer (cache lại sau lần đầu).
601
+ */
602
+ clearNumfmtPreview() {
603
+ const controller = this.resolveNumfmtController();
604
+ if (!controller)
605
+ return;
606
+ if (controller._previewPattern != null)
607
+ controller._previewPattern = null;
608
+ // LUÔN force re-render: numfmt vừa áp vào model cần vẽ lại canvas ngay (kể cả khi không có preview).
609
+ controller._forceUpdate?.();
610
+ }
611
+ // CONVENTION-EXCEPT: any — truy cập injector + NumfmtController nội bộ của Univer (không có public API)
612
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
613
+ resolveNumfmtController() {
614
+ if (this.numfmtController)
615
+ return this.numfmtController;
616
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
617
+ const injector = this.univer?.__getInjector?.();
618
+ if (!injector)
619
+ return null;
620
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
621
+ const scanMap = (map) => {
622
+ if (!(map instanceof Map))
623
+ return null;
624
+ for (const value of map.values()) {
625
+ const candidates = Array.isArray(value) ? value : [value];
626
+ for (const candidate of candidates) {
627
+ const instance = candidate?.instance !== undefined ? candidate.instance : candidate;
628
+ if (instance && typeof instance === 'object' && '_previewPattern' in instance)
629
+ return instance;
630
+ }
631
+ }
632
+ return null;
633
+ };
634
+ // Các instance của redi nằm trong Map lồng 1 cấp (vd injector.resolvedDependencyCollection.resolvedDependencies)
635
+ for (const key of Object.keys(injector)) {
636
+ const value = injector[key];
637
+ let found = scanMap(value);
638
+ if (!found && value && typeof value === 'object') {
639
+ for (const nestedKey of Object.keys(value)) {
640
+ found = scanMap(value[nestedKey]);
641
+ if (found)
642
+ break;
643
+ }
644
+ }
645
+ if (found) {
646
+ this.numfmtController = found;
647
+ return found;
648
+ }
649
+ }
650
+ return null;
651
+ }
652
+ /**
653
+ * Tạo observer để inject option ngày custom + highlight khi panel numfmt render.
654
+ * Observer CHỈ được bật/tắt theo vòng đời panel (xem open/close.numfmt.panel handler) để
655
+ * không chạy liên tục theo mọi mutation DOM toàn trang.
656
+ */
657
+ registerNumfmtDropdownObserver() {
658
+ this.numfmtObserver = new MutationObserver(() => this.processNumfmtPanel());
659
+ }
660
+ /**
661
+ * Thử inject option ngày custom + highlight cho panel numfmt hiện tại.
662
+ * Gọi từ 2 nguồn: (1) MutationObserver khi Univer render list ngày; (2) trực tiếp lúc mở panel —
663
+ * vì Univer TÁI DÙNG DOM panel khi reopen (hiện lại bằng CSS, không phát sinh mutation) nên observer
664
+ * không kích hoạt, phải chủ động gọi để re-inject + resync theo cột hiện tại.
665
+ */
666
+ processNumfmtPanel() {
667
+ syncActiveNumfmtHighlight();
668
+ const result = injectCustomDateFormats(() => this.lastRangeSnapshot,
669
+ // CONVENTION-EXCEPT: any — FUniver.executeCommand không expose typing
670
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
671
+ (cmdId, params) => void this.univerAPI.executeCommand?.(cmdId, params), (pattern) => {
672
+ this.pendingNumfmtPattern = pattern;
673
+ }, () => {
674
+ const snap = this.lastRangeSnapshot;
675
+ if (!snap)
676
+ return this.activeCellFormat();
677
+ // Quét vài dòng đầu của vùng chọn, bỏ qua header/General để lấy format ĐẠI DIỆN của dữ liệu.
678
+ // Khi chọn cả cột, startRow = 0 là header (thường General) → nếu chỉ đọc dòng đó sẽ highlight sai option.
679
+ const maxScan = Math.min(snap.endRow, snap.startRow + 4);
680
+ for (let r = snap.startRow; r <= maxScan; r++) {
681
+ const fmt = this.readCellNumfmt(snap.subUnitId, r, snap.startColumn);
682
+ if (fmt !== 'General')
683
+ return fmt;
684
+ }
685
+ return this.activeCellFormat();
686
+ }, () => this.clearNumfmtPreview(), () => {
687
+ // Giá trị thực của ô đại diện (dòng dữ liệu đầu có số) → label option khớp dữ liệu cột.
688
+ const snap = this.lastRangeSnapshot;
689
+ if (!snap)
690
+ return null;
691
+ const maxScan = Math.min(snap.endRow, snap.startRow + 4);
692
+ for (let r = snap.startRow; r <= maxScan; r++) {
693
+ const value = this.readCellValue(snap.subUnitId, r, snap.startColumn);
694
+ if (value !== null)
695
+ return value;
696
+ }
697
+ return null;
698
+ }, () => {
699
+ this.numfmtConfirmed = true;
700
+ });
701
+ // result chỉ truthy khi THỰC SỰ inject trên 1 listContainer Date mới (guard data-custom-dates chặn
702
+ // các lần gọi thừa). Gỡ listener của lần inject trước trước khi giữ cleanup mới → tránh tích tụ.
703
+ // Đồng thời lưu resync để re-target panel khi user đổi cột, và đánh dấu luồng Date đang hoạt động.
704
+ if (result) {
705
+ this.numfmtCleanup?.();
706
+ this.numfmtCleanup = result.cleanup;
707
+ this.numfmtResync = result.resync;
708
+ this.numfmtDateActive = true;
709
+ }
710
+ }
711
+ initUniver(data) {
712
+ const wrapper = this.containerRef()?.nativeElement;
713
+ if (!wrapper)
714
+ return;
715
+ wrapper.replaceChildren();
716
+ const container = document.createElement('div');
717
+ container.style.cssText = 'width:100%;height:100%';
718
+ wrapper.appendChild(container);
719
+ const univer = new Univer({
720
+ locale: this.resolveLocaleType(),
721
+ locales: {
722
+ [LocaleType.EN_US]: univerLocaleEn,
723
+ [LocaleType.VI_VN]: univerLocaleVi,
724
+ },
725
+ theme: defaultTheme,
726
+ });
727
+ this.univer = univer;
728
+ univer.registerPlugin(UniverRenderEnginePlugin);
729
+ univer.registerPlugin(UniverFormulaEnginePlugin);
730
+ univer.registerPlugin(UniverUIPlugin, { container, header: this.showToolbar(), footer: this.showSheetTabs() });
731
+ univer.registerPlugin(UniverDocsPlugin, { hasScroll: false });
732
+ univer.registerPlugin(UniverDocsUIPlugin);
733
+ univer.registerPlugin(UniverSheetsPlugin);
734
+ univer.registerPlugin(UniverSheetsUIPlugin, { menu: this.toolbarMenuConfig() });
735
+ univer.registerPlugin(UniverSheetsNumfmtPlugin);
736
+ univer.registerPlugin(UniverSheetsFormulaPlugin);
737
+ univer.registerPlugin(UniverSheetsFormulaUIPlugin);
738
+ univer.createUnit(UniverInstanceType.UNIVER_SHEET, data);
739
+ this.univerAPI = FUniver.newAPI(univer);
740
+ if (this.pendingReadyCb) {
741
+ // Wait for .more-numfmt-type to appear in DOM — this signals that UniverSheetsUIPlugin
742
+ // has fully rendered the toolbar and UniverSheetsNumfmtPlugin's INumfmtModel is ready.
743
+ const wrapper = this.containerRef()?.nativeElement;
744
+ if (wrapper) {
745
+ this.readyObserver = new MutationObserver(() => {
746
+ if (!wrapper.querySelector('.more-numfmt-type'))
747
+ return;
748
+ this.readyObserver?.disconnect();
749
+ this.readyObserver = null;
750
+ const cb = this.pendingReadyCb;
751
+ this.pendingReadyCb = null;
752
+ cb?.();
753
+ });
754
+ this.readyObserver.observe(wrapper, { childList: true, subtree: true });
755
+ }
756
+ }
757
+ this.registerColumnClickListener();
758
+ this.registerColumnOpListener();
759
+ this.registerFormatListener();
760
+ this.registerNumfmtDropdownObserver();
761
+ this.registerToolbarWidthSync();
762
+ this.registerNumfmtClickInterceptor();
763
+ }
764
+ /**
765
+ * Khắc phục lỗi toolbar collapse sai (gom item vào menu ⋮ dù còn khoảng trắng).
766
+ *
767
+ * Univer (component Ribbon) quyết định overflow bằng 1 container ĐO off-screen (con trực tiếp của
768
+ * header, position:absolute). Thuật toán: `total = 90; cho mỗi ITEM total += item.clientWidth + 8;
769
+ * nếu total > measuringContainer.clientWidth → collapse item`. Công thức này OVER-COUNT 2 chỗ:
770
+ * • +90px reserve cho nút ⋮ (cộng kể cả khi không cần collapse).
771
+ * • +8px MỖI item, trong khi khoảng cách (gap) thực tế chỉ nằm giữa các GROUP.
772
+ * Nếu set bề rộng container đo = đúng headerW thì `total` (vd 961) > headerW (vd 900) → Univer tưởng
773
+ * tràn và gom item vào ⋮ dù content thật chỉ ~829px (còn ~70px trống).
774
+ *
775
+ * Fix (triệt để, không phụ thuộc timing): pin bề rộng container ĐO = HẰNG SỐ rất lớn qua CSS RULE trong
776
+ * 1 <style> riêng. Khi đó `total` của Univer KHÔNG BAO GIỜ vượt → KHÔNG gom item vào ⋮ → luôn hiển thị
777
+ * ĐỦ option (đúng yêu cầu). Vì sao chọn cách này thay vì khớp width = headerW:
778
+ * • Thuật toán Univer over-count (90 reserve ⋮ + 8px/item) → khớp sát headerW vẫn collapse sai khi còn chỗ.
779
+ * • ResizeObserver của Univer hay KẸT STALE: 1 transient lúc load (icon/font làm item rộng nhất thời) đặt
780
+ * collapsedIds rồi KHÔNG re-fire → kẹt ⋮ vĩnh viễn dù sau đó còn chỗ (đúng triệu chứng reload luôn ⋮).
781
+ * • Set inline lại bị React re-render strip → oscillation. CSS rule !important React không strip được.
782
+ * Container đo vốn off-screen (position:absolute, opacity:0) nên width khổng lồ hoàn toàn vô hình. Khi
783
+ * vùng chứa quá hẹp (hiếm với spreadsheet) toolbar cuộn ngang — xem SCSS `.univer-toolbar` overflow-x.
784
+ */
785
+ registerToolbarWidthSync() {
786
+ const wrapper = this.containerRef()?.nativeElement;
787
+ if (!wrapper)
788
+ return;
789
+ wrapper.classList.add(this.toolbarScopeClass);
790
+ const styleEl = document.createElement('style');
791
+ this.toolbarStyleEl = styleEl;
792
+ styleEl.textContent = `.${this.toolbarScopeClass} .univer-workbench-container-header > .univer-toolbar-container{width:100000px !important;max-width:none !important;}`;
793
+ document.head.appendChild(styleEl);
794
+ }
795
+ registerNumfmtClickInterceptor() {
796
+ const clickHandler = (e) => {
797
+ const target = e.target;
798
+ if (target.closest('.numfmt-panel') ?? target.closest('.more-numfmt-type-options'))
799
+ return;
800
+ const numfmtText = target.closest('.more-numfmt-type');
801
+ const numfmtSelect = target.closest('.univer-toolbar-item-select');
802
+ const isNumfmtBtn = numfmtText ?? (numfmtSelect?.querySelector('.more-numfmt-type') ? numfmtSelect : null);
803
+ if (!isNumfmtBtn)
804
+ return;
805
+ e.preventDefault();
806
+ e.stopPropagation();
807
+ this.executeCommand('sheet.operation.open.numfmt.panel', undefined);
808
+ };
809
+ document.body.addEventListener('click', clickHandler, true);
810
+ this.numfmtClickDisposable = { dispose: () => document.body.removeEventListener('click', clickHandler, true) };
811
+ }
812
+ destroyUniver() {
813
+ if (this.pendingInitTimer !== null) {
814
+ clearTimeout(this.pendingInitTimer);
815
+ this.pendingInitTimer = null;
816
+ }
817
+ this.columnClickDisposable?.dispose();
818
+ this.columnClickDisposable = null;
819
+ this.columnOpDisposable?.dispose();
820
+ this.columnOpDisposable = null;
821
+ this.formatDisposable?.dispose();
822
+ this.formatDisposable = null;
823
+ this.numfmtObserver?.disconnect();
824
+ this.numfmtObserver = null;
825
+ this.toolbarResizeObserver?.disconnect();
826
+ this.toolbarResizeObserver = null;
827
+ this.toolbarStyleEl?.remove();
828
+ this.toolbarStyleEl = null;
829
+ this.numfmtClickDisposable?.dispose();
830
+ this.numfmtClickDisposable = null;
831
+ this.numfmtCleanup?.();
832
+ this.numfmtCleanup = null;
833
+ this.numfmtResync = null;
834
+ this.numfmtDateActive = false;
835
+ this.readyObserver?.disconnect();
836
+ this.readyObserver = null;
837
+ this.activeCellFormat.set('General');
838
+ this.activeCellRef.set('');
839
+ this.lastRangeSnapshot = null;
840
+ this.pendingNumfmtPattern = null;
841
+ this.numfmtConfirmed = false;
842
+ this.originalCellFormats = null;
843
+ this.numfmtPanelOpen = false;
844
+ this.listenEnabled = false;
845
+ if (this.listenEnableTimer !== null) {
846
+ clearTimeout(this.listenEnableTimer);
847
+ this.listenEnableTimer = null;
848
+ }
849
+ this.numfmtController = null;
850
+ this.univer?.dispose();
851
+ this.univer = null;
852
+ this.univerAPI = null;
853
+ }
854
+ reinitUniver() {
855
+ const currentData = this.univerAPI?.getActiveWorkbook()?.save();
856
+ this.destroyUniver();
857
+ setTimeout(() => this.initUniver(currentData ?? this.buildEmptyWorkbook()));
858
+ }
859
+ ngOnDestroy() {
860
+ this.destroyUniver();
861
+ }
862
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: LibsUiComponentsSpreadsheetComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
863
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "18.2.14", type: LibsUiComponentsSpreadsheetComponent, isStandalone: true, selector: "libs_ui-components-spreadsheet", inputs: { locale: { classPropertyName: "locale", publicName: "locale", isSignal: true, isRequired: false, transformFunction: null }, toolbarMenuConfig: { classPropertyName: "toolbarMenuConfig", publicName: "toolbarMenuConfig", isSignal: true, isRequired: false, transformFunction: null }, mappingIndicatorConfig: { classPropertyName: "mappingIndicatorConfig", publicName: "mappingIndicatorConfig", isSignal: true, isRequired: false, transformFunction: null }, mappingTargets: { classPropertyName: "mappingTargets", publicName: "mappingTargets", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { outColumnDblClick: "outColumnDblClick", outColumnStructureChange: "outColumnStructureChange" }, viewQueries: [{ propertyName: "containerRef", first: true, predicate: ["containerRef"], descendants: true, isSignal: true }], ngImport: i0, template: "<div #containerRef class=\"libs-ui-components-spreadsheet-container\"></div>\n", styles: ["@charset \"UTF-8\";:host{display:block;width:100%;height:100%}.libs-ui-components-spreadsheet-container{width:100%;height:100%}::ng-deep .univer-toolbar-container{flex-grow:1!important;margin:0!important}::ng-deep .univer-toolbar{overflow-x:auto}::ng-deep .univer-toolbar>.univer-toolbar-container{justify-content:flex-start!important;flex-shrink:0!important}::ng-deep .univer-toolbar-more-container{display:flex!important;flex-wrap:wrap!important;gap:8px!important;width:max-content!important;max-width:320px!important;padding:8px!important}::ng-deep .univer-toolbar-more-container .univer-toolbar-group{flex-shrink:0!important}::ng-deep .univer-select-dropdown .univer-select-item[title=\"Custom Format\"]{display:none!important}::ng-deep .numfmt-panel{padding:0 4px}::ng-deep .univer-custom-format-title{margin-top:12px!important;font-size:11px!important;font-weight:700!important;color:#8c8c8c!important;text-transform:uppercase!important;letter-spacing:.5px!important}::ng-deep .univer-custom-format-input{margin-top:6px!important}::ng-deep .univer-custom-format-input input,::ng-deep .univer-custom-format-input textarea{font-family:SFMono-Regular,Consolas,monospace!important;font-size:12px!important;border-radius:6px!important}::ng-deep .univer-custom-format-history-list{margin-top:6px!important;padding:4px!important;border:1.5px solid #f0f0f0!important;border-radius:8px!important;max-height:260px!important;overflow-y:auto!important;background:#fafafa!important;scrollbar-width:thin;scrollbar-color:#d9d9d9 transparent}::ng-deep .univer-custom-format-history-list::-webkit-scrollbar{width:4px}::ng-deep .univer-custom-format-history-list::-webkit-scrollbar-thumb{background:#d9d9d9;border-radius:4px}::ng-deep .univer-custom-format-history-list-item{padding:5px 8px!important;border-radius:6px!important;gap:8px!important;transition:all .12s;border-bottom:1px solid transparent!important}::ng-deep .univer-custom-format-history-list-item:hover{background:#e6f4ff!important}::ng-deep .univer-custom-format-history-list-item:hover>span:last-child,::ng-deep .univer-custom-format-history-list-item:hover>div:last-child{color:#1677ff!important}::ng-deep .univer-custom-format-history-list-item>span:not(.univer-custom-format-history-list-item-icon-wrap),::ng-deep .univer-custom-format-history-list-item>div:not(.univer-custom-format-history-list-item-icon-wrap){font-family:SFMono-Regular,Consolas,monospace!important;font-size:11px!important;color:#434343!important;overflow:hidden!important;text-overflow:ellipsis!important;white-space:nowrap!important;max-width:240px!important}::ng-deep .univer-custom-format-history-list-item-icon-wrap{flex-shrink:0!important;opacity:.6}::ng-deep .univer-custom-format-des{margin-top:6px!important;font-size:11px!important;line-height:1.5!important;color:#8c8c8c!important;padding:6px 8px!important;background:#f5f5f5!important;border-radius:6px!important;border-left:3px solid #d9d9d9!important}::ng-deep .univer-numfmt-custom-item{position:relative!important;padding:5px 8px!important;border-radius:6px!important;font-family:SFMono-Regular,Consolas,monospace!important;font-size:12px!important;color:#434343!important;cursor:pointer!important;transition:background .12s,color .12s;display:block!important;border-left:3px solid transparent}::ng-deep .univer-numfmt-custom-item:hover{background:#f0f5ff!important;color:#1677ff!important;border-left-color:#1677ff!important}::ng-deep .univer-numfmt-custom-item.univer-numfmt-active{background:#e6f4ff!important;color:#1677ff!important;font-weight:600!important;padding-left:24px!important;border-left:3px solid #1677ff!important}::ng-deep .univer-numfmt-custom-item.univer-numfmt-active:before{content:\"\\2713\";position:absolute;left:7px;top:50%;transform:translateY(-50%);font-size:10px;font-weight:700;color:#1677ff;line-height:1}::ng-deep .numfmt-panel li.univer-select-list-item.univer-select-list-item-select:not(.univer-numfmt-custom-item){background:#e6f4ff!important;border-left:3px solid #1677ff!important;border-radius:6px!important}::ng-deep .numfmt-panel li.univer-select-list-item.univer-select-list-item-select:not(.univer-numfmt-custom-item) a{color:#1677ff!important}::ng-deep .numfmt-panel li.univer-select-list-item.univer-select-list-item-select:not(.univer-numfmt-custom-item) .univer-select-list-item-icon{color:#1677ff!important}::ng-deep .more-numfmt-type{cursor:pointer;font-size:0!important;display:inline-flex;align-items:center;line-height:1}::ng-deep .more-numfmt-type:before{content:\"\";display:inline-block;width:31px;height:18px;background-color:currentColor;mask:url(\"data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2034%2020'%3E%3Ctext%20x='0'%20y='15'%20font-size='13'%20font-weight='700'%20fill='black'%20font-family='Arial,sans-serif'%3E123%3C/text%3E%3Ctext%20x='20'%20y='8'%20font-size='7'%20font-weight='700'%20fill='black'%20font-family='Arial,sans-serif'%3E%25%3C/text%3E%3Ctext%20x='27'%20y='8'%20font-size='7'%20font-weight='700'%20fill='black'%20font-family='Arial,sans-serif'%3E$%3C/text%3E%3Ccircle%20cx='26.5'%20cy='15'%20r='3.4'%20fill='none'%20stroke='black'%20stroke-width='1.1'/%3E%3Cpath%20d='M26.5%2013.2v1.8l1.2.9'%20fill='none'%20stroke='black'%20stroke-width='1.1'%20stroke-linecap='round'%20stroke-linejoin='round'/%3E%3C/svg%3E\") no-repeat center/contain;-webkit-mask:url(\"data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2034%2020'%3E%3Ctext%20x='0'%20y='15'%20font-size='13'%20font-weight='700'%20fill='black'%20font-family='Arial,sans-serif'%3E123%3C/text%3E%3Ctext%20x='20'%20y='8'%20font-size='7'%20font-weight='700'%20fill='black'%20font-family='Arial,sans-serif'%3E%25%3C/text%3E%3Ctext%20x='27'%20y='8'%20font-size='7'%20font-weight='700'%20fill='black'%20font-family='Arial,sans-serif'%3E$%3C/text%3E%3Ccircle%20cx='26.5'%20cy='15'%20r='3.4'%20fill='none'%20stroke='black'%20stroke-width='1.1'/%3E%3Cpath%20d='M26.5%2013.2v1.8l1.2.9'%20fill='none'%20stroke='black'%20stroke-width='1.1'%20stroke-linecap='round'%20stroke-linejoin='round'/%3E%3C/svg%3E\") no-repeat center/contain}::ng-deep .univer-toolbar-item-select:has(.more-numfmt-type):hover{background-color:rgb(var(--grey-100));border-radius:var(--border-radius-base)}::ng-deep .univer-toolbar-item-select:has(.more-numfmt-type) .more-numfmt-type,::ng-deep .univer-toolbar-item-select:has(.more-numfmt-type) .univer-toolbar-item-select-arrow{background-color:transparent!important}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
864
+ }
865
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: LibsUiComponentsSpreadsheetComponent, decorators: [{
866
+ type: Component,
867
+ args: [{ selector: 'libs_ui-components-spreadsheet', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div #containerRef class=\"libs-ui-components-spreadsheet-container\"></div>\n", styles: ["@charset \"UTF-8\";:host{display:block;width:100%;height:100%}.libs-ui-components-spreadsheet-container{width:100%;height:100%}::ng-deep .univer-toolbar-container{flex-grow:1!important;margin:0!important}::ng-deep .univer-toolbar{overflow-x:auto}::ng-deep .univer-toolbar>.univer-toolbar-container{justify-content:flex-start!important;flex-shrink:0!important}::ng-deep .univer-toolbar-more-container{display:flex!important;flex-wrap:wrap!important;gap:8px!important;width:max-content!important;max-width:320px!important;padding:8px!important}::ng-deep .univer-toolbar-more-container .univer-toolbar-group{flex-shrink:0!important}::ng-deep .univer-select-dropdown .univer-select-item[title=\"Custom Format\"]{display:none!important}::ng-deep .numfmt-panel{padding:0 4px}::ng-deep .univer-custom-format-title{margin-top:12px!important;font-size:11px!important;font-weight:700!important;color:#8c8c8c!important;text-transform:uppercase!important;letter-spacing:.5px!important}::ng-deep .univer-custom-format-input{margin-top:6px!important}::ng-deep .univer-custom-format-input input,::ng-deep .univer-custom-format-input textarea{font-family:SFMono-Regular,Consolas,monospace!important;font-size:12px!important;border-radius:6px!important}::ng-deep .univer-custom-format-history-list{margin-top:6px!important;padding:4px!important;border:1.5px solid #f0f0f0!important;border-radius:8px!important;max-height:260px!important;overflow-y:auto!important;background:#fafafa!important;scrollbar-width:thin;scrollbar-color:#d9d9d9 transparent}::ng-deep .univer-custom-format-history-list::-webkit-scrollbar{width:4px}::ng-deep .univer-custom-format-history-list::-webkit-scrollbar-thumb{background:#d9d9d9;border-radius:4px}::ng-deep .univer-custom-format-history-list-item{padding:5px 8px!important;border-radius:6px!important;gap:8px!important;transition:all .12s;border-bottom:1px solid transparent!important}::ng-deep .univer-custom-format-history-list-item:hover{background:#e6f4ff!important}::ng-deep .univer-custom-format-history-list-item:hover>span:last-child,::ng-deep .univer-custom-format-history-list-item:hover>div:last-child{color:#1677ff!important}::ng-deep .univer-custom-format-history-list-item>span:not(.univer-custom-format-history-list-item-icon-wrap),::ng-deep .univer-custom-format-history-list-item>div:not(.univer-custom-format-history-list-item-icon-wrap){font-family:SFMono-Regular,Consolas,monospace!important;font-size:11px!important;color:#434343!important;overflow:hidden!important;text-overflow:ellipsis!important;white-space:nowrap!important;max-width:240px!important}::ng-deep .univer-custom-format-history-list-item-icon-wrap{flex-shrink:0!important;opacity:.6}::ng-deep .univer-custom-format-des{margin-top:6px!important;font-size:11px!important;line-height:1.5!important;color:#8c8c8c!important;padding:6px 8px!important;background:#f5f5f5!important;border-radius:6px!important;border-left:3px solid #d9d9d9!important}::ng-deep .univer-numfmt-custom-item{position:relative!important;padding:5px 8px!important;border-radius:6px!important;font-family:SFMono-Regular,Consolas,monospace!important;font-size:12px!important;color:#434343!important;cursor:pointer!important;transition:background .12s,color .12s;display:block!important;border-left:3px solid transparent}::ng-deep .univer-numfmt-custom-item:hover{background:#f0f5ff!important;color:#1677ff!important;border-left-color:#1677ff!important}::ng-deep .univer-numfmt-custom-item.univer-numfmt-active{background:#e6f4ff!important;color:#1677ff!important;font-weight:600!important;padding-left:24px!important;border-left:3px solid #1677ff!important}::ng-deep .univer-numfmt-custom-item.univer-numfmt-active:before{content:\"\\2713\";position:absolute;left:7px;top:50%;transform:translateY(-50%);font-size:10px;font-weight:700;color:#1677ff;line-height:1}::ng-deep .numfmt-panel li.univer-select-list-item.univer-select-list-item-select:not(.univer-numfmt-custom-item){background:#e6f4ff!important;border-left:3px solid #1677ff!important;border-radius:6px!important}::ng-deep .numfmt-panel li.univer-select-list-item.univer-select-list-item-select:not(.univer-numfmt-custom-item) a{color:#1677ff!important}::ng-deep .numfmt-panel li.univer-select-list-item.univer-select-list-item-select:not(.univer-numfmt-custom-item) .univer-select-list-item-icon{color:#1677ff!important}::ng-deep .more-numfmt-type{cursor:pointer;font-size:0!important;display:inline-flex;align-items:center;line-height:1}::ng-deep .more-numfmt-type:before{content:\"\";display:inline-block;width:31px;height:18px;background-color:currentColor;mask:url(\"data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2034%2020'%3E%3Ctext%20x='0'%20y='15'%20font-size='13'%20font-weight='700'%20fill='black'%20font-family='Arial,sans-serif'%3E123%3C/text%3E%3Ctext%20x='20'%20y='8'%20font-size='7'%20font-weight='700'%20fill='black'%20font-family='Arial,sans-serif'%3E%25%3C/text%3E%3Ctext%20x='27'%20y='8'%20font-size='7'%20font-weight='700'%20fill='black'%20font-family='Arial,sans-serif'%3E$%3C/text%3E%3Ccircle%20cx='26.5'%20cy='15'%20r='3.4'%20fill='none'%20stroke='black'%20stroke-width='1.1'/%3E%3Cpath%20d='M26.5%2013.2v1.8l1.2.9'%20fill='none'%20stroke='black'%20stroke-width='1.1'%20stroke-linecap='round'%20stroke-linejoin='round'/%3E%3C/svg%3E\") no-repeat center/contain;-webkit-mask:url(\"data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2034%2020'%3E%3Ctext%20x='0'%20y='15'%20font-size='13'%20font-weight='700'%20fill='black'%20font-family='Arial,sans-serif'%3E123%3C/text%3E%3Ctext%20x='20'%20y='8'%20font-size='7'%20font-weight='700'%20fill='black'%20font-family='Arial,sans-serif'%3E%25%3C/text%3E%3Ctext%20x='27'%20y='8'%20font-size='7'%20font-weight='700'%20fill='black'%20font-family='Arial,sans-serif'%3E$%3C/text%3E%3Ccircle%20cx='26.5'%20cy='15'%20r='3.4'%20fill='none'%20stroke='black'%20stroke-width='1.1'/%3E%3Cpath%20d='M26.5%2013.2v1.8l1.2.9'%20fill='none'%20stroke='black'%20stroke-width='1.1'%20stroke-linecap='round'%20stroke-linejoin='round'/%3E%3C/svg%3E\") no-repeat center/contain}::ng-deep .univer-toolbar-item-select:has(.more-numfmt-type):hover{background-color:rgb(var(--grey-100));border-radius:var(--border-radius-base)}::ng-deep .univer-toolbar-item-select:has(.more-numfmt-type) .more-numfmt-type,::ng-deep .univer-toolbar-item-select:has(.more-numfmt-type) .univer-toolbar-item-select-arrow{background-color:transparent!important}\n"] }]
868
+ }], ctorParameters: () => [] });
869
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3ByZWFkc2hlZXQuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vbGlicy11aS9jb21wb25lbnRzL3NwcmVhZHNoZWV0L3NyYy9zcHJlYWRzaGVldC5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi9saWJzLXVpL2NvbXBvbmVudHMvc3ByZWFkc2hlZXQvc3JjL3NwcmVhZHNoZWV0LmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBaUIsdUJBQXVCLEVBQUUsU0FBUyxFQUFjLE1BQU0sRUFBYSxNQUFNLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLFNBQVMsRUFBRSxTQUFTLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDOUssT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUV4RSxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDaEQsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDbEQsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDdkQsT0FBTyxFQUFFLHlCQUF5QixFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDckUsT0FBTyxFQUFFLHdCQUF3QixFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDbkUsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBQzNDLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxnQkFBZ0IsRUFBRSxpQkFBaUIsRUFBRSxrQkFBa0IsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBQzlHLE9BQU8sRUFBRSx5QkFBeUIsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQ3JFLE9BQU8sRUFBRSwyQkFBMkIsRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBQzFFLE9BQU8s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cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQWZ0ZXJWaWV3SW5pdCwgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksIENvbXBvbmVudCwgRWxlbWVudFJlZiwgTmdab25lLCBPbkRlc3Ryb3ksIGVmZmVjdCwgaW5qZWN0LCBpbnB1dCwgb3V0cHV0LCBzaWduYWwsIHVudHJhY2tlZCwgdmlld0NoaWxkIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBMb2NhbGVUeXBlLCBVbml2ZXIsIFVuaXZlckluc3RhbmNlVHlwZSB9IGZyb20gJ0B1bml2ZXJqcy9jb3JlJztcbmltcG9ydCB0eXBlIHsgQ2VsbFZhbHVlLCBJQ2VsbERhdGEsIElTdHlsZURhdGEgfSBmcm9tICdAdW5pdmVyanMvY29yZSc7XG5pbXBvcnQgeyBkZWZhdWx0VGhlbWUgfSBmcm9tICdAdW5pdmVyanMvZGVzaWduJztcbmltcG9ydCB7IFVuaXZlckRvY3NQbHVnaW4gfSBmcm9tICdAdW5pdmVyanMvZG9jcyc7XG5pbXBvcnQgeyBVbml2ZXJEb2NzVUlQbHVnaW4gfSBmcm9tICdAdW5pdmVyanMvZG9jcy11aSc7XG5pbXBvcnQgeyBVbml2ZXJGb3JtdWxhRW5naW5lUGx1Z2luIH0gZnJvbSAnQHVuaXZlcmpzL2VuZ2luZS1mb3JtdWxhJztcbmltcG9ydCB7IFVuaXZlclJlbmRlckVuZ2luZVBsdWdpbiB9IGZyb20gJ0B1bml2ZXJqcy9lbmdpbmUtcmVuZGVyJztcbmltcG9ydCB7IEZVbml2ZXIgfSBmcm9tICdAdW5pdmVyanMvZmFjYWRlJztcbmltcG9ydCB7IEluc2VydENvbE11dGF0aW9uLCBNb3ZlQ29sc011dGF0aW9uLCBSZW1vdmVDb2xNdXRhdGlvbiwgVW5pdmVyU2hlZXRzUGx1Z2luIH0gZnJvbSAnQHVuaXZlcmpzL3NoZWV0cyc7XG5pbXBvcnQgeyBVbml2ZXJTaGVldHNGb3JtdWxhUGx1Z2luIH0gZnJvbSAnQHVuaXZlcmpzL3NoZWV0cy1mb3JtdWxhJztcbmltcG9ydCB7IFVuaXZlclNoZWV0c0Zvcm11bGFVSVBsdWdpbiB9IGZyb20gJ0B1bml2ZXJqcy9zaGVldHMtZm9ybXVsYS11aSc7XG5pbXBvcnQgeyBVbml2ZXJTaGVldHNOdW1mbXRQbHVnaW4gfSBmcm9tICdAdW5pdmVyanMvc2hlZXRzLW51bWZtdCc7XG5pbXBvcnQgeyBVbml2ZXJTaGVldHNVSVBsdWdpbiB9IGZyb20gJ0B1bml2ZXJqcy9zaGVldHMtdWknO1xuaW1wb3J0IHsgVW5pdmVyVUlQbHVnaW4gfSBmcm9tICdAdW5pdmVyanMvdWknO1xuaW1wb3J0IHsgdW5pdmVyTG9jYWxlRW4sIHVuaXZlckxvY2FsZVZpIH0gZnJvbSAnLi9zcHJlYWRzaGVldC5sb2NhbGUnO1xuaW1wb3J0IHsgaW5qZWN0Q3VzdG9tRGF0ZUZvcm1hdHMsIHN5bmNBY3RpdmVOdW1mbXRIaWdobGlnaHQgfSBmcm9tICcuL3NwcmVhZHNoZWV0Lm51bWZtdCc7XG5pbXBvcnQgeyBhcHBseU1hcHBpbmdJbmRpY2F0b3JzLCBzdHJpcE1hcHBpbmdJbmRpY2F0b3JzIH0gZnJvbSAnLi9zcHJlYWRzaGVldC5pbmRpY2F0b3InO1xuaW1wb3J0IHR5cGUgeyBUX2NvbHVtblN0cnVjdHVyZUNoYW5nZSwgVF9pbmRpY2F0b3JUYXJnZXQsIFRfbWFwcGluZ0luZGljYXRvckNvbmZpZyB9IGZyb20gJy4vc3ByZWFkc2hlZXQuaW5kaWNhdG9yJztcbmltcG9ydCB0eXBlIHsgVF9jZWxsRm9ybWF0UmVzdWx0LCBUX3JhbmdlU25hcHNob3QsIFRfc3ByZWFkc2hlZXRfbG9jYWxlLCBUX3Rvb2xiYXJfbWVudV9jb25maWcgfSBmcm9tICcuL3NwcmVhZHNoZWV0LnR5cGUnO1xuXG4vLyBC4buZIMSR4bq/bSB04bqhbyBjbGFzcyBzY29wZSBkdXkgbmjhuqV0IGNobyBt4buXaSBpbnN0YW5jZSBzcHJlYWRzaGVldCAoZMO5bmcgY2hvIDxzdHlsZT4gY2jhu4luaCB3aWR0aCB0b29sYmFyKS5cbmxldCBzcHJlYWRzaGVldEluc3RhbmNlQ291bnQgPSAwO1xuXG5AQ29tcG9uZW50KHtcbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEBhbmd1bGFyLWVzbGludC9jb21wb25lbnQtc2VsZWN0b3JcbiAgc2VsZWN0b3I6ICdsaWJzX3VpLWNvbXBvbmVudHMtc3ByZWFkc2hlZXQnLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcbiAgdGVtcGxhdGVVcmw6ICcuL3NwcmVhZHNoZWV0LmNvbXBvbmVudC5odG1sJyxcbiAgc3R5bGVVcmw6ICcuL3NwcmVhZHNoZWV0LmNvbXBvbmVudC5zY3NzJyxcbn0pXG5leHBvcnQgY2xhc3MgTGlic1VpQ29tcG9uZW50c1NwcmVhZHNoZWV0Q29tcG9uZW50IGltcGxlbWVudHMgQWZ0ZXJWaWV3SW5pdCwgT25EZXN0cm95IHtcbiAgcHJpdmF0ZSB1bml2ZXI6IFVuaXZlciB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIHVuaXZlckFQSTogRlVuaXZlciB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIGNvbHVtbkNsaWNrRGlzcG9zYWJsZTogeyBkaXNwb3NlOiAoKSA9PiB2b2lkIH0gfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBmb3JtYXREaXNwb3NhYmxlOiB7IGRpc3Bvc2U6ICgpID0+IHZvaWQgfSB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIGNvbHVtbk9wRGlzcG9zYWJsZTogeyBkaXNwb3NlOiAoKSA9PiB2b2lkIH0gfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBudW1mbXRPYnNlcnZlcjogTXV0YXRpb25PYnNlcnZlciB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIHRvb2xiYXJSZXNpemVPYnNlcnZlcjogUmVzaXplT2JzZXJ2ZXIgfCBudWxsID0gbnVsbDtcbiAgLy8gPHN0eWxlPiByacOqbmcgY2hvIGluc3RhbmNlOiBwaW4gd2lkdGggY29udGFpbmVyIMSRbyBxdWEgQ1NTIHJ1bGUgKFJlYWN0IHJlLXJlbmRlciBLSMOUTkcgc3RyaXAgxJHGsOG7o2Mg4oaSXG4gIC8vIHRyw6FuaCB2w7JuZyBs4bq3cCBvc2NpbGxhdGlvbiBnaeG7r2Egc2V0LWlubGluZS13aWR0aCB2w6AgUmVhY3Qgc3RyaXAgZ8OieSBr4bq5dCDii64pLiBYZW0gcmVnaXN0ZXJUb29sYmFyV2lkdGhTeW5jLlxuICBwcml2YXRlIHRvb2xiYXJTdHlsZUVsOiBIVE1MU3R5bGVFbGVtZW50IHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgcmVhZG9ubHkgdG9vbGJhclNjb3BlQ2xhc3MgPSBgbGlicy11aS1zcHJlYWRzaGVldC10Yi0keyhzcHJlYWRzaGVldEluc3RhbmNlQ291bnQgKz0gMSl9YDtcbiAgcHJpdmF0ZSBudW1mbXRDbGlja0Rpc3Bvc2FibGU6IHsgZGlzcG9zZTogKCkgPT4gdm9pZCB9IHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgbGFzdFJhbmdlU25hcHNob3Q6IFRfcmFuZ2VTbmFwc2hvdCB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIHBlbmRpbmdOdW1mbXRQYXR0ZXJuOiBzdHJpbmcgfCBudWxsID0gbnVsbDtcbiAgLy8gdHJ1ZSBDSOG7iCBraGkgdXNlciBi4bqlbSBuw7p0IENvbmZpcm0gdHJvbmcgcGFuZWwgbnVtZm10IOKGkiBnaeG7ryBmb3JtYXQ7IENhbmNlbC9YL2NsaWNrLW5nb8OgaSA9IGZhbHNlIOKGkiByZXZlcnQuXG4gIHByaXZhdGUgbnVtZm10Q29uZmlybWVkID0gZmFsc2U7XG4gIC8vIFNuYXBzaG90IG51bWZtdCB04burbmcgw7QgY+G7p2EgdsO5bmcgY2jhu41uIHThuqFpIHRo4budaSDEkWnhu4NtIG3hu58gcGFuZWwg4oCUIGTDuW5nIGtow7RpIHBo4bulYyBjaMOtbmggeMOhYyBraGkgQ2FuY2VsLlxuICBwcml2YXRlIG9yaWdpbmFsQ2VsbEZvcm1hdHM6IHsgcGF0dGVybjogc3RyaW5nOyByb3c6IG51bWJlcjsgY29sOiBudW1iZXIgfVtdIHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgbnVtZm10UGFuZWxPcGVuID0gZmFsc2U7XG4gIC8vIHRydWUga2hpIGx14buTbmcgRGF0ZSBjdXN0b20gxJFhbmcgaG/huqF0IMSR4buZbmcgKMSRw6MgaW5qZWN0IG9wdGlvbiBuZ8OgeSkuIENI4buIIGtoaSDEkcOzIGNvbXBvbmVudCBt4bubaVxuICAvLyBjYW4gdGhp4buHcCBjb25maXJtL3JldmVydDsgY8OhYyBUeXBlIGtow6FjIChT4buRLCBUaeG7gW4gdOG7hywgJSwgVGV4dOKApikgZG8gVW5pdmVyIHThu7EgeOG7rSBsw70g4oaSIGtow7RuZyDEkeG7pW5nIHbDoG8uXG4gIHByaXZhdGUgbnVtZm10RGF0ZUFjdGl2ZSA9IGZhbHNlO1xuICAvLyDEkOG7k25nIGLhu5kgbOG6oWkgcGFuZWwgRGF0ZSAobGFiZWwgKyBoaWdobGlnaHQgKyBhdXRvLWFwcGx5KSB0aGVvIHbDuW5nIGNo4buNbiBt4bubaSBraGkgdXNlciDEkeG7lWkgY+G7mXQgbMO6YyBwYW5lbCBt4bufLlxuICBwcml2YXRlIG51bWZtdFJlc3luYzogKCgpID0+IHZvaWQpIHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgbGlzdGVuRW5hYmxlZCA9IGZhbHNlO1xuICBwcml2YXRlIGxpc3RlbkVuYWJsZVRpbWVyOiBSZXR1cm5UeXBlPHR5cGVvZiBzZXRUaW1lb3V0PiB8IG51bGwgPSBudWxsO1xuICAvLyBEZWZlciBpbml0aWFsIGVtcHR5LXdvcmtib29rIGluaXQgdG8gYWxsb3cgcGFyZW50J3MgbmdBZnRlclZpZXdJbml0IHRvIGNhbGwgbG9hZERhdGFcbiAgLy8gZmlyc3QgKGNhbmNlbGxpbmcgdGhlIGVtcHR5IGluaXQpLCBhdm9pZGluZyBhIHJhY2Ugd2l0aCBVbml2ZXIncyBhc3luYyBSZWFjdCByZW5kZXJzLlxuICBwcml2YXRlIHBlbmRpbmdJbml0VGltZXI6IFJldHVyblR5cGU8dHlwZW9mIHNldFRpbWVvdXQ+IHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgbnVtZm10Q2xlYW51cDogKCgpID0+IHZvaWQpIHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgcGVuZGluZ1JlYWR5Q2I6ICgoKSA9PiB2b2lkKSB8IG51bGwgPSBudWxsO1xuICAvLyBTbmFwc2hvdCDEkcOjLWRlY29yYXRlIGfhuqduIG5o4bqldCDigJQgbMOgbSBiYXNlbGluZSDEkeG7gyBkaWZmIChzdHlsZSBpZCDhu5VuIMSR4buLbmggJ2gnLydtJywga2jDtG5nIGLhu4tcbiAgLy8g4bqjbmggaMaw4bufbmcgYuG7n2kgc3R5bGUgaWQgdOG7sSBzaW5oIHNhdSBt4buXaSBmYWNhZGUgc2V0VmFsdWUpLiBEw7luZyBjaG8gcmUtYXBwbHkgaW5jcmVtZW50YWwuXG4gIHByaXZhdGUgbGFzdERlY29yYXRlZDogUmVjb3JkPHN0cmluZywgdW5rbm93bj4gfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSByZWFkeU9ic2VydmVyOiBNdXRhdGlvbk9ic2VydmVyIHwgbnVsbCA9IG51bGw7XG4gIC8vIENhY2hlIGNvbnRyb2xsZXIgbnVtZm10IG7hu5lpIGLhu5kgY+G7p2EgVW5pdmVyIChnaeG7ryBfcHJldmlld1BhdHRlcm4pLiBUw6xtIDEgbOG6p24gcXVhIGluamVjdG9yLlxuICAvLyBDT05WRU5USU9OLUVYQ0VQVDogYW55IOKAlCBOdW1mbXRDb250cm9sbGVyIGtow7RuZyBleHBvcnQga2jhu49pIEB1bml2ZXJqcy9zaGVldHMtbnVtZm10XG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55XG4gIHByaXZhdGUgbnVtZm10Q29udHJvbGxlcjogYW55ID0gbnVsbDtcblxuICBwcml2YXRlIHJlYWRvbmx5IGFjdGl2ZUNlbGxGb3JtYXQgPSBzaWduYWwoJ0dlbmVyYWwnKTtcbiAgcHJpdmF0ZSByZWFkb25seSBhY3RpdmVDZWxsUmVmID0gc2lnbmFsKCcnKTtcbiAgcHJpdmF0ZSByZWFkb25seSBzaG93VG9vbGJhciA9IHNpZ25hbCh0cnVlKTtcbiAgcHJpdmF0ZSByZWFkb25seSBzaG93U2hlZXRUYWJzID0gc2lnbmFsKHRydWUpO1xuICAvLyBOZ8O0biBuZ+G7ryDEkWFuZyBoaeG7g24gdGjhu4sgdGjhu7FjIHThur8uIEto4bufaSB04bqhbyB04burIGlucHV0IGBsb2NhbGVgIHRyb25nIG5nQWZ0ZXJWaWV3SW5pdCxcbiAgLy8gc2F1IMSRw7MgxJHhu5VpIHJ1bnRpbWUgcXVhIHNldExvY2FsZSgpIChrw6lvIHRoZW8gcmVpbml0IMSR4buDIFVuaXZlciByZW5kZXIgbOG6oWkgVUkpLlxuICBwcml2YXRlIHJlYWRvbmx5IGFjdGl2ZUxvY2FsZSA9IHNpZ25hbDxUX3NwcmVhZHNoZWV0X2xvY2FsZT4oJ3ZpJyk7XG5cbiAgLyoqIE5nw7RuIG5n4buvIGto4bufaSB04bqhbyBj4bunYSBzcHJlYWRzaGVldC4gxJDhu5VpIHJ1bnRpbWUgZMO5bmcgRnVuY3Rpb25Db250cm9sLnNldExvY2FsZSgpLiAqL1xuICByZWFkb25seSBsb2NhbGUgPSBpbnB1dDxUX3NwcmVhZHNoZWV0X2xvY2FsZT4oJ3ZpJyk7XG5cbiAgLyoqIEPhuqV1IGjDrG5oIOG6qW4gLyB2w7QgaGnhu4d1IGhvw6EgdG9vbGJhciBpdGVtcy4gVGhheSDEkeG7lWkgc+G6vSByZWluaXQgdG/DoG4gYuG7mSBVbml2ZXIuICovXG4gIHJlYWRvbmx5IHRvb2xiYXJNZW51Q29uZmlnID0gaW5wdXQ8VF90b29sYmFyX21lbnVfY29uZmlnPih7XG4gICAgLy8gJ3NoZWV0LmNvbW1hbmQubnVtZm10LnNldC5jdXJyZW5jeSc6IHsgaGlkZGVuOiB0cnVlIH0sXG4gICAgLy8gJ3NoZWV0LmNvbW1hbmQubnVtZm10LmFkZC5kZWNpbWFsLmNvbW1hbmQnOiB7IGhpZGRlbjogdHJ1ZSB9LFxuICAgIC8vICdzaGVldC5jb21tYW5kLm51bWZtdC5zdWJ0cmFjdC5kZWNpbWFsLmNvbW1hbmQnOiB7IGhpZGRlbjogdHJ1ZSB9LFxuICAgIC8vICdzaGVldC5jb21tYW5kLm51bWZtdC5zZXQucGVyY2VudCc6IHsgaGlkZGVuOiB0cnVlIH0sXG4gICAgJ3NoZWV0LmNvbW1hbmQuc2V0LW9uY2UtZm9ybWF0LXBhaW50ZXInOiB7IGhpZGRlbjogdHJ1ZSB9LFxuICAgICdzaGVldC5jb21tYW5kLnNldC10ZXh0LXJvdGF0aW9uJzogeyBoaWRkZW46IHRydWUgfSxcbiAgICAnc2hlZXQuY29tbWFuZC5zZXQtcmFuZ2UtZm9udC1mYW1pbHknOiB7IGhpZGRlbjogdHJ1ZSB9LFxuICAgICdzaGVldC5jb21tYW5kLnNldC1ib3JkZXItYmFzaWMnOiB7IGhpZGRlbjogdHJ1ZSB9LFxuICAgICdzaGVldC5jb21tYW5kLmFkZC13b3Jrc2hlZXQtbWVyZ2UnOiB7IGhpZGRlbjogdHJ1ZSB9LFxuICAgICdzaGVldC5jb21tYW5kLmFkZC13b3Jrc2hlZXQtbWVyZ2UtYWxsJzogeyBoaWRkZW46IHRydWUgfSxcbiAgICAnc2hlZXQuY29tbWFuZC5hZGQtd29ya3NoZWV0LW1lcmdlLXZlcnRpY2FsJzogeyBoaWRkZW46IHRydWUgfSxcbiAgICAnc2hlZXQuY29tbWFuZC5hZGQtd29ya3NoZWV0LW1lcmdlLWhvcml6b250YWwnOiB7IGhpZGRlbjogdHJ1ZSB9LFxuICAgICdzaGVldC5jb21tYW5kLnJlbW92ZS13b3Jrc2hlZXQtbWVyZ2UnOiB7IGhpZGRlbjogdHJ1ZSB9LFxuICB9KTtcblxuICAvKipcbiAgICogQ+G6pXUgaMOsbmggaGlnaGxpZ2h0IGPhu5l0IMSRw6MgbWFwIChzdHlsZSAvIHByZWZpeCAvIHNjb3BlIHNoZWV0KS5cbiAgICogVHJ1eeG7gW4gY29uZmlnIG7DoHkgPSBcImLhuq10XCIgbHXhu5NuZyBhdXRvOiBjb21wb25lbnQgc+G6vSBU4buwIMOhcCBpbmRpY2F0b3Iga2hpIGxvYWQvcmVzZXQsXG4gICAqIFThu7AgZ+G7oSBraGkgc2F2ZSwgdsOgIFThu7AgduG6vSBs4bqhaSBt4buXaSBraGkgYG1hcHBpbmdUYXJnZXRzYCDEkeG7lWkuIELhu48gdHLhu5FuZyA9IHNwcmVhZHNoZWV0IHRoxrDhu51uZy5cbiAgICovXG4gIHJlYWRvbmx5IG1hcHBpbmdJbmRpY2F0b3JDb25maWcgPSBpbnB1dDxUX21hcHBpbmdJbmRpY2F0b3JDb25maWc+KCk7XG5cbiAgLyoqIERhbmggc8OhY2ggY+G7mXQgY+G6p24gaGlnaGxpZ2h0IChgeyBzaGVldElkLCBjb2xJbmRleCB9YCkuIMSQ4buVaSBydW50aW1lIOKGkiB04buxIHbhur0gbOG6oWkgaGVhZGVyLiAqL1xuICByZWFkb25seSBtYXBwaW5nVGFyZ2V0cyA9IGlucHV0PFRfaW5kaWNhdG9yVGFyZ2V0W10+KFtdKTtcblxuICByZWFkb25seSBvdXRDb2x1bW5EYmxDbGljayA9IG91dHB1dDxudW1iZXI+KCk7XG5cbiAgLyoqXG4gICAqIFBow6F0IGtoaSB1c2VyIGluc2VydCAvIHJlbW92ZSAvIG1vdmUgY+G7mXQgKGvhu4MgY+G6oyBjaOG7jW4gbmhp4buBdSBj4buZdCwgdsOgIGPhuqMgdW5kby9yZWRvKS5cbiAgICogQ29uc3VtZXIgZMO5bmcgYHJlbWFwQ29sdW1uSW5kZXhlcyhtYXBwaW5ncywgJGV2ZW50KWAgxJHhu4MgZOG7i2NoIGzhuqFpIG3huqNuZyBtYXBwaW5nIGLDqm4gbmdvw6BpXG4gICAqIGNobyBraOG7m3AgduG7iyB0csOtIG3hu5tpIOKAlCB0csOhbmggbOG7h2NoIGtoaSBjaMOobi94w7NhIGPhu5l0IOG7nyBnaeG7r2EuXG4gICAqL1xuICByZWFkb25seSBvdXRDb2x1bW5TdHJ1Y3R1cmVDaGFuZ2UgPSBvdXRwdXQ8VF9jb2x1bW5TdHJ1Y3R1cmVDaGFuZ2U+KCk7XG5cbiAgcHJpdmF0ZSByZWFkb25seSBjb250YWluZXJSZWYgPSB2aWV3Q2hpbGQ8RWxlbWVudFJlZj4oJ2NvbnRhaW5lclJlZicpO1xuICBwcml2YXRlIHJlYWRvbmx5IG5nWm9uZSA9IGluamVjdChOZ1pvbmUpO1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIC8vIEF1dG8gcmUtYXBwbHk6IGNo4buJIGNo4bqheSBraGkgxJHDoyBi4bqtdCBjb25maWcgKyBVbml2ZXIgxJHDoyBraOG7n2kgdOG6oW8uIEzhuqduIMSR4bqndSAoY2jGsGEgaW5pdCkgdOG7sSBi4buPIHF1YS5cbiAgICBlZmZlY3QoKCkgPT4ge1xuICAgICAgdGhpcy5tYXBwaW5nVGFyZ2V0cygpO1xuICAgICAgdGhpcy5tYXBwaW5nSW5kaWNhdG9yQ29uZmlnKCk7XG4gICAgICB1bnRyYWNrZWQoKCkgPT4gdGhpcy5yZWFwcGx5SW5kaWNhdG9ycygpKTtcbiAgICB9KTtcbiAgfVxuXG4gIG5nQWZ0ZXJWaWV3SW5pdCgpIHtcbiAgICB0aGlzLmFjdGl2ZUxvY2FsZS5zZXQodGhpcy5sb2NhbGUoKSk7XG4gICAgdGhpcy5wZW5kaW5nSW5pdFRpbWVyID0gc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICB0aGlzLnBlbmRpbmdJbml0VGltZXIgPSBudWxsO1xuICAgICAgdGhpcy5pbml0VW5pdmVyKHRoaXMuYnVpbGRFbXB0eVdvcmtib29rKCkpO1xuICAgIH0pO1xuICB9XG5cbiAgZ2V0IEZ1bmN0aW9uQ29udHJvbCgpIHtcbiAgICByZXR1cm4ge1xuICAgICAgbG9hZERhdGE6IChkYXRhOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPikgPT4gdGhpcy5sb2FkRGF0YShkYXRhKSxcbiAgICAgIHNhdmVEYXRhOiAoKSA9PiB0aGlzLnNhdmVEYXRhKCksXG4gICAgICBnZXRBY3RpdmVTaGVldEluZm86ICgpID0+IHRoaXMuZ2V0QWN0aXZlU2hlZXRJbmZvKCksXG4gICAgICBnZXRDb2x1bW5OdW1mbXQ6IChzaGVldElkOiBzdHJpbmcsIGNvbEluZGV4OiBudW1iZXIpID0+IHRoaXMuZ2V0Q29sdW1uTnVtZm10KHNoZWV0SWQsIGNvbEluZGV4KSxcbiAgICAgIGV4dHJhY3RBbGxDb2x1bW5Gb3JtYXRzOiAoc25hcHNob3Q6IFJlY29yZDxzdHJpbmcsIHVua25vd24+KSA9PiB0aGlzLmV4dHJhY3RBbGxDb2x1bW5Gb3JtYXRzKHNuYXBzaG90KSxcbiAgICAgIHRvZ2dsZVRvb2xiYXI6ICgpID0+IHRoaXMudG9nZ2xlVG9vbGJhcigpLFxuICAgICAgdG9nZ2xlU2hlZXRUYWJzOiAoKSA9PiB0aGlzLnRvZ2dsZVNoZWV0VGFicygpLFxuICAgICAgcmVzZXQ6IChkYXRhPzogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pID0+IHRoaXMucmVzZXQoZGF0YSksXG4gICAgICBleGVjdXRlQ29tbWFuZDogKGNvbW1hbmRJZDogc3RyaW5nLCBwYXJhbXM6IHVua25vd24pID0+IHRoaXMuZXhlY3V0ZUNvbW1hbmQoY29tbWFuZElkLCBwYXJhbXMpLFxuICAgICAgYXBwbHlOdW1mbXQ6IChyb3c6IG51bWJlciwgY29sOiBudW1iZXIsIG51bVJvd3M6IG51bWJlciwgbnVtQ29sczogbnVtYmVyLCBwYXR0ZXJuOiBzdHJpbmcpID0+IHRoaXMuYXBwbHlOdW1mbXQocm93LCBjb2wsIG51bVJvd3MsIG51bUNvbHMsIHBhdHRlcm4pLFxuICAgICAgc2NoZWR1bGVPblJlYWR5OiAoY2I6ICgpID0+IHZvaWQpID0+IHtcbiAgICAgICAgdGhpcy5wZW5kaW5nUmVhZHlDYiA9IGNiO1xuICAgICAgfSxcbiAgICAgIHNldExvY2FsZTogKGxvY2FsZTogVF9zcHJlYWRzaGVldF9sb2NhbGUpID0+IHRoaXMuc2V0TG9jYWxlKGxvY2FsZSksXG4gICAgICBhY3RpdmVDZWxsUmVmOiB0aGlzLmFjdGl2ZUNlbGxSZWYsXG4gICAgICBhY3RpdmVDZWxsRm9ybWF0OiB0aGlzLmFjdGl2ZUNlbGxGb3JtYXQsXG4gICAgICBzaG93VG9vbGJhcjogdGhpcy5zaG93VG9vbGJhcixcbiAgICAgIHNob3dTaGVldFRhYnM6IHRoaXMuc2hvd1NoZWV0VGFicyxcbiAgICAgIGxvY2FsZTogdGhpcy5hY3RpdmVMb2NhbGUuYXNSZWFkb25seSgpLFxuICAgIH07XG4gIH1cblxuICBwcml2YXRlIHNldExvY2FsZShsb2NhbGU6IFRfc3ByZWFkc2hlZXRfbG9jYWxlKSB7XG4gICAgaWYgKGxvY2FsZSA9PT0gdGhpcy5hY3RpdmVMb2NhbGUoKSkgcmV0dXJuO1xuICAgIHRoaXMuYWN0aXZlTG9jYWxlLnNldChsb2NhbGUpO1xuICAgIHRoaXMucmVpbml0VW5pdmVyKCk7XG4gIH1cblxuICBwcml2YXRlIGxvYWREYXRhKGRhdGE6IFJlY29yZDxzdHJpbmcsIHVua25vd24+KSB7XG4gICAgY29uc3QgZGVjb3JhdGVkID0gdGhpcy5kZWNvcmF0ZVNuYXBzaG90KGRhdGEpO1xuICAgIGlmICh0aGlzLnBlbmRpbmdJbml0VGltZXIgIT09IG51bGwpIHtcbiAgICAgIGNsZWFyVGltZW91dCh0aGlzLnBlbmRpbmdJbml0VGltZXIpO1xuICAgICAgdGhpcy5wZW5kaW5nSW5pdFRpbWVyID0gbnVsbDtcbiAgICAgIHRoaXMuaW5pdFVuaXZlcihkZWNvcmF0ZWQpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aGlzLmRlc3Ryb3lVbml2ZXIoKTtcbiAgICBzZXRUaW1lb3V0KCgpID0+IHRoaXMuaW5pdFVuaXZlcihkZWNvcmF0ZWQpKTtcbiAgfVxuXG4gIC8qKiBTbmFwc2hvdCB0aMO0IHThu6sgVW5pdmVyIChDw5MgdGjhu4MgY8OybiBpbmRpY2F0b3IpLiBEw7luZyBu4buZaSBi4buZIGNobyByZS1hcHBseS4gKi9cbiAgcHJpdmF0ZSBzYXZlUmF3KCk6IFJlY29yZDxzdHJpbmcsIHVua25vd24+IHtcbiAgICByZXR1cm4gKHRoaXMudW5pdmVyQVBJPy5nZXRBY3RpdmVXb3JrYm9vaygpPy5zYXZlKCkgPz8ge30pIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICB9XG5cbiAgLyoqIFNuYXBzaG90IHRy4bqjIGNobyBjb25zdW1lciDigJQgdOG7sSBn4buhIGluZGljYXRvciBu4bq/dSBsdeG7k25nIGF1dG8gxJFhbmcgYuG6rXQuICovXG4gIHByaXZhdGUgc2F2ZURhdGEoKTogUmVjb3JkPHN0cmluZywgdW5rbm93bj4ge1xuICAgIGNvbnN0IGNvbmZpZyA9IHRoaXMubWFwcGluZ0luZGljYXRvckNvbmZpZygpO1xuICAgIGlmICghY29uZmlnKSByZXR1cm4gdGhpcy5zYXZlUmF3KCk7XG4gICAgcmV0dXJuIHN0cmlwTWFwcGluZ0luZGljYXRvcnModGhpcy5zYXZlUmF3KCksIGNvbmZpZyk7XG4gIH1cblxuICAvKiogw4FwIGluZGljYXRvciB2w6BvIHNuYXBzaG90IHRyxrDhu5tjIGtoaSBsb2FkIOKAlCBjaOG7iSBraGkgbHXhu5NuZyBhdXRvIMSRYW5nIGLhuq10LiBMxrB1IGJhc2VsaW5lIMSR4buDIGRpZmYuICovXG4gIHByaXZhdGUgZGVjb3JhdGVTbmFwc2hvdChkYXRhOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik6IFJlY29yZDxzdHJpbmcsIHVua25vd24+IHtcbiAgICBjb25zdCBjb25maWcgPSB0aGlzLm1hcHBpbmdJbmRpY2F0b3JDb25maWcoKTtcbiAgICBpZiAoIWNvbmZpZykgcmV0dXJuIGRhdGE7XG4gICAgY29uc3QgZGVjb3JhdGVkID0gYXBwbHlNYXBwaW5nSW5kaWNhdG9ycyhkYXRhLCB0aGlzLm1hcHBpbmdUYXJnZXRzKCksIGNvbmZpZyk7XG4gICAgdGhpcy5sYXN0RGVjb3JhdGVkID0gZGVjb3JhdGVkO1xuICAgIHJldHVybiBkZWNvcmF0ZWQ7XG4gIH1cblxuICAvKipcbiAgICogVuG6vSBs4bqhaSBpbmRpY2F0b3IgS0jDlE5HIHJlaW5pdCBVbml2ZXI6IHTDrW5oIHNuYXBzaG90IMSRw61jaCBy4buTaSBDSOG7iCBnaGkgxJHDqCDEkcO6bmcgY8OhYyDDtCBoZWFkZXJcbiAgICoga2jDoWMgc28gduG7m2kgYmFzZWxpbmUgdHLGsOG7m2MgxJHDsyAoc3R5bGUgKyBwcmVmaXggKyB3aWR0aCkgbMOqbiBpbnN0YW5jZSBsaXZlIHF1YSBmYWNhZGUuXG4gICAqIERpZmYgdGhlbyBiYXNlbGluZSAoc3R5bGUgaWQg4buVbiDEkeG7i25oICdoJy8nbScpIOKGkiBjaOG7iSBjw6FjIGPhu5l0IHbhu6thIG1hcC9i4buPIG1hcCBt4bubaSDEkcaw4bujYyB24bq9IGzhuqFpLlxuICAgKi9cbiAgcHJpdmF0ZSByZWFwcGx5SW5kaWNhdG9ycygpIHtcbiAgICBjb25zdCBjb25maWcgPSB0aGlzLm1hcHBpbmdJbmRpY2F0b3JDb25maWcoKTtcbiAgICBjb25zdCB3YiA9IHRoaXMudW5pdmVyQVBJPy5nZXRBY3RpdmVXb3JrYm9vaygpO1xuICAgIGNvbnN0IHByZXYgPSB0aGlzLmxhc3REZWNvcmF0ZWQ7XG4gICAgaWYgKCFjb25maWcgfHwgIXdiIHx8ICFwcmV2KSByZXR1cm47XG5cbiAgICBjb25zdCBuZXh0ID0gYXBwbHlNYXBwaW5nSW5kaWNhdG9ycyh0aGlzLnNhdmVSYXcoKSwgdGhpcy5tYXBwaW5nVGFyZ2V0cygpLCBjb25maWcpO1xuICAgIHRoaXMubGFzdERlY29yYXRlZCA9IG5leHQ7XG5cbiAgICB0eXBlIFRfY2VsbCA9IHsgdj86IHVua25vd247IHM/OiB1bmtub3duIH07XG4gICAgdHlwZSBUX3NoZWV0ID0geyBjZWxsRGF0YT86IFJlY29yZDxzdHJpbmcsIFJlY29yZDxzdHJpbmcsIFRfY2VsbD4+OyBjb2x1bW5EYXRhPzogUmVjb3JkPHN0cmluZywgeyB3PzogbnVtYmVyIH0+IH07XG4gICAgY29uc3QgaGVhZGVyS2V5ID0gU3RyaW5nKGNvbmZpZy5oZWFkZXJSb3dJbmRleCA/PyAwKTtcbiAgICBjb25zdCBoZWFkZXJSb3cgPSBOdW1iZXIoaGVhZGVyS2V5KTtcbiAgICBjb25zdCBzdHlsZXNOZXh0ID0gKG5leHRbJ3N0eWxlcyddID8/IHt9KSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgICBjb25zdCBzaGVldHNOZXh0ID0gKG5leHRbJ3NoZWV0cyddID8/IHt9KSBhcyBSZWNvcmQ8c3RyaW5nLCBUX3NoZWV0PjtcbiAgICBjb25zdCBzaGVldHNQcmV2ID0gKHByZXZbJ3NoZWV0cyddID8/IHt9KSBhcyBSZWNvcmQ8c3RyaW5nLCBUX3NoZWV0PjtcblxuICAgIGZvciAoY29uc3Qgc2hlZXRJZCBvZiBPYmplY3Qua2V5cyhzaGVldHNOZXh0KSkge1xuICAgICAgY29uc3Qgd3MgPSB3Yi5nZXRTaGVldEJ5U2hlZXRJZChzaGVldElkKTtcbiAgICAgIGlmICghd3MpIGNvbnRpbnVlO1xuICAgICAgY29uc3QgbmV4dFJvdyA9IHNoZWV0c05leHRbc2hlZXRJZF0/LmNlbGxEYXRhPy5baGVhZGVyS2V5XSA/PyB7fTtcbiAgICAgIGNvbnN0IHByZXZSb3cgPSBzaGVldHNQcmV2W3NoZWV0SWRdPy5jZWxsRGF0YT8uW2hlYWRlcktleV0gPz8ge307XG4gICAgICBjb25zdCBjb2xEYXRhID0gc2hlZXRzTmV4dFtzaGVldElkXT8uY29sdW1uRGF0YSA/PyB7fTtcbiAgICAgIGZvciAoY29uc3QgY29sS2V5IG9mIE9iamVjdC5rZXlzKG5leHRSb3cpKSB7XG4gICAgICAgIGNvbnN0IGNlbGxOZXh0ID0gbmV4dFJvd1tjb2xLZXldO1xuICAgICAgICBjb25zdCBjZWxsUHJldiA9IHByZXZSb3dbY29sS2V5XTtcbiAgICAgICAgLy8gw5Qga2jDtG5nIMSR4buVaSBj4bqjIHZhbHVlIGzhuqtuIHN0eWxlIOKGkiBi4buPIHF1YSAobeG6pXUgY2jhu5F0OiBjaOG7iSB24bq9IGzhuqFpIGPhu5l0IHbhu6thIG1hcC9i4buPIG1hcCkuXG4gICAgICAgIGlmICghY2VsbE5leHQgfHwgKGNlbGxOZXh0LnYgPT09IGNlbGxQcmV2Py52ICYmIGNlbGxOZXh0LnMgPT09IGNlbGxQcmV2Py5zKSkgY29udGludWU7XG4gICAgICAgIGNvbnN0IHN0eWxlID0gKHR5cGVvZiBjZWxsTmV4dC5zID09PSAnc3RyaW5nJyA/IHN0eWxlc05leHRbY2VsbE5leHQuc10gOiBjZWxsTmV4dC5zKSBhcyBJU3R5bGVEYXRhO1xuICAgICAgICBjb25zdCBjZWxsOiBJQ2VsbERhdGEgPSB7IHY6IGNlbGxOZXh0LnYgYXMgQ2VsbFZhbHVlLCBzOiBzdHlsZSB9O1xuICAgICAgICB2b2lkIHdzLmdldFJhbmdlKGhlYWRlclJvdywgTnVtYmVyKGNvbEtleSkpLnNldFZhbHVlKGNlbGwpO1xuICAgICAgICBjb25zdCB3aWR0aCA9IGNvbERhdGFbY29sS2V5XT8udztcbiAgICAgICAgaWYgKHR5cGVvZiB3aWR0aCA9PT0gJ251bWJlcicpIHZvaWQgd3Muc2V0Q29sdW1uV2lkdGgoTnVtYmVyKGNvbEtleSksIHdpZHRoKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHRvZ2dsZVRvb2xiYXIoKSB7XG4gICAgdGhpcy5zaG93VG9vbGJhci51cGRhdGUoKHYpID0+ICF2KTtcbiAgICB0aGlzLnJlaW5pdFVuaXZlcigpO1xuICB9XG5cbiAgcHJpdmF0ZSB0b2dnbGVTaGVldFRhYnMoKSB7XG4gICAgdGhpcy5zaG93U2hlZXRUYWJzLnVwZGF0ZSgodikgPT4gIXYpO1xuICAgIHRoaXMucmVpbml0VW5pdmVyKCk7XG4gIH1cblxuICBwcml2YXRlIHJlc2V0KGRhdGE/OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPikge1xuICAgIHRoaXMuZGVzdHJveVVuaXZlcigpO1xuICAgIHRoaXMuaW5pdFVuaXZlcih0aGlzLmRlY29yYXRlU25hcHNob3QoZGF0YSA/PyB0aGlzLmJ1aWxkRW1wdHlXb3JrYm9vaygpKSk7XG4gIH1cblxuICBwcml2YXRlIGV4ZWN1dGVDb21tYW5kKGNvbW1hbmRJZDogc3RyaW5nLCBwYXJhbXM6IHVua25vd24pIHtcbiAgICAvLyBDT05WRU5USU9OLUVYQ0VQVDogYW55IOKAlCBGVW5pdmVyLmV4ZWN1dGVDb21tYW5kIGtow7RuZyBleHBvc2UgdHlwaW5nXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnlcbiAgICB2b2lkICh0aGlzLnVuaXZlckFQSSBhcyBhbnkpPy5leGVjdXRlQ29tbWFuZD8uKGNvbW1hbmRJZCwgcGFyYW1zKTtcbiAgfVxuXG4gIHByaXZhdGUgYXBwbHlOdW1mbXQocm93OiBudW1iZXIsIGNvbDogbnVtYmVyLCBudW1Sb3dzOiBudW1iZXIsIG51bUNvbHM6IG51bWJlciwgcGF0dGVybjogc3RyaW5nKSB7XG4gICAgLy8gQ09OVkVOVElPTi1FWENFUFQ6IGFueSDigJQgRldvcmtib29rLmdldElkIC8gRldvcmtzaGVldC5nZXRTaGVldElkIG5vdCBleHBvc2VkIGluIHB1YmxpYyB0eXBlc1xuICAgIC8vIE5vdGU6IEZSYW5nZS5zZXROdW1iZXJGb3JtYXQoKSBoYXMgYSBVbml2ZXIgZmFjYWRlIGJ1ZyDigJQgaXQgYnVpbGRzIGB2YWx1ZXNgIGJ1dCBuZXZlciBwYXNzZXNcbiAgICAvLyB0aGVtIHRvIGV4ZWN1dGVDb21tYW5kLiBXZSBjYWxsIHRoZSBjb21tYW5kIGRpcmVjdGx5IHdpdGggdGhlIGNvcnJlY3QgcGFyYW1zIGluc3RlYWQuXG4gICAgLy8gRldvcmtib29rIHVzZXMgZ2V0SWQoKSAobm90IGdldFVuaXRJZCgpKSBhbmQgRldvcmtzaGVldCB1c2VzIGdldFNoZWV0SWQoKSBmb3Igc3ViVW5pdElkLlxuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55XG4gICAgY29uc3Qgd2IgPSB0aGlzLnVuaXZlckFQST8uZ2V0QWN0aXZlV29ya2Jvb2soKSBhcyBhbnk7XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnlcbiAgICBjb25zdCB3cyA9IHdiPy5nZXRBY3RpdmVTaGVldD8uKCkgYXMgYW55O1xuICAgIGlmICghd2IgfHwgIXdzKSByZXR1cm47XG4gICAgY29uc3QgdW5pdElkID0gKHdiLmdldElkPy4oKSA/PyAnJykgYXMgc3RyaW5nO1xuICAgIGNvbnN0IHN1YlVuaXRJZCA9ICh3cy5nZXRTaGVldElkPy4oKSA/PyAnJykgYXMgc3RyaW5nO1xuICAgIGNvbnN0IHZhbHVlczogeyBwYXR0ZXJuOiBzdHJpbmc7IHJvdzogbnVtYmVyOyBjb2w6IG51bWJlciB9W10gPSBbXTtcbiAgICBmb3IgKGxldCByID0gcm93OyByIDwgcm93ICsgbnVtUm93czsgcisrKSB7XG4gICAgICBmb3IgKGxldCBjID0gY29sOyBjIDwgY29sICsgbnVtQ29sczsgYysrKSB7XG4gICAgICAgIHZhbHVlcy5wdXNoKHsgcGF0dGVybiwgcm93OiByLCBjb2w6IGMgfSk7XG4gICAgICB9XG4gICAgfVxuICAgIHRoaXMuZXhlY3V0ZUNvbW1hbmQoJ3NoZWV0LmNvbW1hbmQubnVtZm10LnNldC5udW1mbXQnLCB7IHVuaXRJZCwgc3ViVW5pdElkLCB2YWx1ZXMgfSk7XG4gIH1cblxuICBwcml2YXRlIGdldEFjdGl2ZVNoZWV0SW5mbygpOiB7IHNoZWV0SWQ6IHN0cmluZzsgc2hlZXROYW1lOiBzdHJpbmcgfSB8IG51bGwge1xuICAgIC8vIENPTlZFTlRJT04tRVhDRVBUOiBhbnkg4oCUIEZXb3Jrc2hlZXQgcHVibGljIHR5cGVzIGNoxrBhIGV4cG9zZSBnZXRTaGVldElkL2dldE5hbWVcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxuICAgIGNvbnN0IHNoZWV0ID0gdGhpcy51bml2ZXJBUEk/LmdldEFjdGl2ZVdvcmtib29rKCk/LmdldEFjdGl2ZVNoZWV0KCkgYXMgYW55O1xuICAgIGlmICghc2hlZXQpIHJldHVybiBudWxsO1xuICAgIHJldHVybiB7XG4gICAgICBzaGVldElkOiAoc2hlZXQuZ2V0U2hlZXRJZD8uKCkgPz8gJycpIGFzIHN0cmluZyxcbiAgICAgIHNoZWV0TmFtZTogKHNoZWV0LmdldFNoZWV0TmFtZT8uKCkgPz8gc2hlZXQuZ2V0TmFtZT8uKCkgPz8gJycpIGFzIHN0cmluZyxcbiAgICB9O1xuICB9XG5cbiAgLyoqIMSQ4buNYyBudW1mbXQgcGF0dGVybiBj4bunYSBt4buZdCBjZWxsIHThu6sgd29ya2Jvb2sgc25hcHNob3QuICovXG4gIHByaXZhdGUgcmVhZENlbGxOdW1mbXQoc2hlZXRJZDogc3RyaW5nLCByb3c6IG51bWJlciwgY29sOiBudW1iZXIpOiBzdHJpbmcge1xuICAgIHRyeSB7XG4gICAgICAvLyBDT05WRU5USU9OLUVYQ0VQVDogYW55IOKAlCBGV29ya2Jvb2suc2F2ZSgpIGtow7RuZyBleHBvc2UgdHlwaW5nXG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxuICAgICAgY29uc3Qgc3MgPSB0aGlzLnVuaXZlckFQST8uZ2V0QWN0aXZlV29ya2Jvb2soKT8uc2F2ZSgpIGFzIGFueTtcbiAgICAgIHR5cGUgU3R5bGVFbnRyeSA9IHsgbj86IHsgcGF0dGVybj86IHN0cmluZyB9OyBuZj86IHsgcGF0dGVybj86IHN0cmluZyB9IH07XG4gICAgICBjb25zdCBzdHlsZXMgPSBzcz8uc3R5bGVzIGFzIFJlY29yZDxzdHJpbmcsIFN0eWxlRW50cnk+IHwgdW5kZWZpbmVkO1xuICAgICAgY29uc3QgY2VsbHMgPSAoc3M/LnNoZWV0cyBhcyBSZWNvcmQ8c3RyaW5nLCB7IGNlbGxEYXRhPzogUmVjb3JkPHN0cmluZywgUmVjb3JkPHN0cmluZywgeyBzPzogc3RyaW5nIH0+PiB9Pik/LltzaGVldElkXT8uY2VsbERhdGE7XG4gICAgICBjb25zdCBzdHlsZUlkID0gY2VsbHM/LltTdHJpbmcocm93KV0/LltTdHJpbmcoY29sKV0/LnM7XG4gICAgICBpZiAoIXN0eWxlSWQgfHwgIXN0eWxlcykgcmV0dXJuICdHZW5lcmFsJztcbiAgICAgIHJldHVybiBzdHlsZXNbc3R5bGVJZF0/Lm4/LnBhdHRlcm4gPz8gc3R5bGVzW3N0eWxlSWRdPy5uZj8ucGF0dGVybiA/PyAnR2VuZXJhbCc7XG4gICAgfSBjYXRjaCB7XG4gICAgICByZXR1cm4gJ0dlbmVyYWwnO1xuICAgIH1cbiAgfVxuXG4gIC8qKiDEkOG7jWMgZ2nDoSB0cuG7iyBz4buRIChFeGNlbCBzZXJpYWwpIGPhu6dhIG3hu5l0IMO0OyBudWxsIG7hur91IMO0IHLhu5duZy9raMO0bmcgcGjhuqNpIHPhu5EuICovXG4gIHByaXZhdGUgcmVhZENlbGxWYWx1ZShzaGVldElkOiBzdHJpbmcsIHJvdzogbnVtYmVyLCBjb2w6IG51bWJlcik6IG51bWJlciB8IG51bGwge1xuICAgIHRyeSB7XG4gICAgICAvLyBDT05WRU5USU9OLUVYQ0VQVDogYW55IOKAlCBGV29ya2Jvb2suc2F2ZSgpIGtow7RuZyBleHBvc2UgdHlwaW5nXG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxuICAgICAgY29uc3Qgc3MgPSB0aGlzLnVuaXZlckFQST8uZ2V0QWN0aXZlV29ya2Jvb2soKT8uc2F2ZSgpIGFzIGFueTtcbiAgICAgIGNvbnN0IGNlbGxzID0gKHNzPy5zaGVldHMgYXMgUmVjb3JkPHN0cmluZywgeyBjZWxsRGF0YT86IFJlY29yZDxzdHJpbmcsIFJlY29yZDxzdHJpbmcsIHsgdj86IHVua25vd24gfT4+IH0+KT8uW3NoZWV0SWRdPy5jZWxsRGF0YTtcbiAgICAgIGNvbnN0IHZhbHVlID0gY2VsbHM/LltTdHJpbmcocm93KV0/LltTdHJpbmcoY29sKV0/LnY7XG4gICAgICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJyAmJiBpc0Zpbml0ZSh2YWx1ZSkgPyB2YWx1ZSA6IG51bGw7XG4gICAgfSBjYXRjaCB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGdldENvbHVtbk51bWZtdChzaGVldElkOiBzdHJpbmcsIGNvbEluZGV4OiBudW1iZXIpOiBzdHJpbmcge1xuICAgIGZvciAoY29uc3Qgcm93IG9mIFsxLCAyLCAzXSkge1xuICAgICAgY29uc3QgcGF0dGVybiA9IHRoaXMucmVhZENlbGxOdW1mbXQoc2hlZXRJZCwgcm93LCBjb2xJbmRleCk7XG4gICAgICBpZiAocGF0dGVybiAhPT0gJ0dlbmVyYWwnKSByZXR1cm4gcGF0dGVybjtcbiAgICB9XG4gICAgcmV0dXJuICdHZW5lcmFsJztcbiAgfVxuXG4gIC8qKiBDaOG7pXAgbnVtZm10IGfhu5FjIHThu6tuZyDDtCBj4bunYSB2w7luZyBjaOG7jW4gKGdp4bubaSBo4bqhbiA1MDAgZMOybmcgbmjGsCBhcHBseUZvcm1hdCkgxJHhu4MgQ2FuY2VsIGtow7RpIHBo4bulYyDEkcO6bmcuICovXG4gIHByaXZhdGUgY2FwdHVyZVJhbmdlTnVtZm10KHNuYXA6IFRfcmFuZ2VTbmFwc2hvdCB8IG51bGwpOiB7IHBhdHRlcm46IHN0cmluZzsgcm93OiBudW1iZXI7IGNvbDogbnVtYmVyIH1bXSB8IG51bGwge1xuICAgIGlmICghc25hcCkgcmV0dXJuIG51bGw7XG4gICAgY29uc3QgdmFsdWVzOiB7IHBhdHRlcm46IHN0cmluZzsgcm93OiBudW1iZXI7IGNvbDogbnVtYmVyIH1bXSA9IFtdO1xuICAgIGNvbnN0IG1heFJvdyA9IE1hdGgubWluKHNuYXAuZW5kUm93LCBzbmFwLnN0YXJ0Um93ICsgNDk5KTtcbiAgICBmb3IgKGxldCByID0gc25hcC5zdGFydFJvdzsgciA8PSBtYXhSb3c7IHIrKykge1xuICAgICAgZm9yIChsZXQgYyA9IHNuYXAuc3RhcnRDb2x1bW47IGMgPD0gc25hcC5lbmRDb2x1bW47IGMrKykge1xuICAgICAgICB2YWx1ZXMucHVzaCh7IHBhdHRlcm46IHRoaXMucmVhZENlbGxOdW1mbXQoc25hcC5zdWJVbml0SWQsIHIsIGMpLCByb3c6IHIsIGNvbDogYyB9KTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHZhbHVlcy5sZW5ndGggPyB2YWx1ZXMgOiBudWxsO1xuICB9XG5cbiAgcHJpdmF0ZSBleHRyYWN0QWxsQ29sdW1uRm9ybWF0cyhzbmFwc2hvdDogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pOiBUX2NlbGxGb3JtYXRSZXN1bHRbXSB7XG4gICAgdHlwZSBTdHlsZUVudHJ5ID0geyBuPzogeyBwYXR0ZXJuPzogc3RyaW5nIH07IG5mPzogeyBwYXR0ZXJuPzogc3RyaW5nIH0gfTtcbiAgICB0eXBlIFN0eWxlTWFwID0gUmVjb3JkPHN0cmluZywgU3R5bGVFbnRyeT47XG4gICAgdHlwZSBTaGVldE1hcCA9IFJlY29yZDxzdHJpbmcsIHsgbmFtZT86IHN0cmluZzsgY2VsbERhdGE/OiBSZWNvcmQ8c3RyaW5nLCBSZWNvcmQ8c3RyaW5nLCB7IHM/OiBzdHJpbmc7IHY/OiB1bmtub3duIH0+PiB9PjtcblxuICAgIGNvbnN0IHN0eWxlcyA9IHNuYXBzaG90WydzdHlsZXMnXSBhcyBTdHlsZU1hcCB8IHVuZGVmaW5lZDtcbiAgICBjb25zdCBzaGVldHMgPSBzbmFwc2hvdFsnc2hlZXRzJ10gYXMgU2hlZXRNYXAgfCB1bmRlZmluZWQ7XG4gICAgY29uc3Qgb3JkZXIgPSBzbmFwc2hvdFsnc2hlZXRPcmRlciddIGFzIHN0cmluZ1tdIHwgdW5kZWZpbmVkO1xuICAgIGlmICghc3R5bGVzIHx8ICFzaGVldHMpIHJldHVybiBbXTtcblxuICAgIGNvbnN0IHJlc3VsdHM6IFRfY2VsbEZvcm1hdFJlc3VsdFtdID0gW107XG4gICAgY29uc3Qgc2VlbiA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuXG4gICAgZm9yIChjb25zdCBzaGVldElkIG9mIG9yZGVyID8/IE9iamVjdC5rZXlzKHNoZWV0cykpIHtcbiAgICAgIGNvbnN0IHNoZWV0RGF0YSA9IHNoZWV0c1tzaGVldElkXTtcbiAgICAgIGlmICghc2hlZXREYXRhPy5jZWxsRGF0YSkgY29udGludWU7XG5cbiAgICAgIGNvbnN0IHNoZWV0TmFtZSA9IHNoZWV0RGF0YS5uYW1lID8/IHNoZWV0SWQ7XG4gICAgICBjb25zdCBoZWFkZXJSb3cgPSBzaGVldERhdGEuY2VsbERhdGFbJzAnXSA/PyB7fTtcblxuICAgICAgZm9yIChjb25zdCByb3dLZXkgb2YgWycxJywgJzInLCAnMyddKSB7XG4gICAgICAgIGNvbnN0IHJvdyA9IHNoZWV0RGF0YS5jZWxsRGF0YVtyb3dLZXldO1xuICAgICAgICBpZiAoIXJvdykgY29udGludWU7XG5cbiAgICAgICAgZm9yIChjb25zdCBjb2xLZXkgb2YgT2JqZWN0LmtleXMocm93KSkge1xuICAgICAgICAgIGNvbnN0IGtleSA9IGAke3NoZWV0SWR9OiR7Y29sS2V5fWA7XG4gICAgICAgICAgaWYgKHNlZW4uaGFzKGtleSkpIGNvbnRpbnVlO1xuXG4gICAgICAgICAgY29uc3Qgc3R5bGVJZCA9IHJvd1tjb2xLZXldPy5zO1xuICAgICAgICAgIGlmICghc3R5bGVJZCkgY29udGludWU7XG5cbiAgICAgICAgICBjb25zdCBwYXR0ZXJuID0gc3R5bGVzW3N0eWxlSWRdPy5uPy5wYXR0ZXJuID8/IHN0eWxlc1tzdHlsZUlkXT8ubmY/LnBhdHRlcm47XG4gICAgICAgICAgaWYgKCFwYXR0ZXJuKSBjb250aW51ZTtcblxuICAgICAgICAgIHNlZW4uYWRkKGtleSk7XG4gICAgICAgICAgY29uc3QgY29sSW5kZXggPSBwYXJzZUludChjb2xLZXksIDEwKTtcbiAgICAgICAgICBjb25zdCBjb2xMZXR0ZXIgPSB0aGlzLnRvQ29sTGV0dGVyKGNvbEluZGV4KTtcbiAgICAgICAgICBjb25zdCBoZWFkZXJWID0gaGVhZGVyUm93W2NvbEtleV0/LnY7XG5cbiAgICAgICAgICByZXN1bHRzLnB1c2goe1xuICAgICAgICAgICAgc2hlZXQ6IHNoZWV0TmFtZSxcbiAgICAgICAgICAgIGNvbDogY29sTGV0dGVyLFxuICAgICAgICAgICAgY29sSW5kZXgsXG4gICAgICAgICAgICBoZWFkZXI6IGhlYWRlclYgPyBTdHJpbmcoaGVhZGVyVikgOiBjb2xMZXR0ZXIsXG4gICAgICAgICAgICBudW1mbXQ6IHBhdHRlcm4sXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdHM7XG4gIH1cblxuICBwcml2YXRlIHRvQ29sTGV0dGVyKGluZGV4OiBudW1iZXIpOiBzdHJpbmcge1xuICAgIGxldCByZXN1bHQgPSAnJztcbiAgICBsZXQgbiA9IGluZGV4O1xuICAgIGRvIHtcbiAgICAgIHJlc3VsdCA9IFN0cmluZy5mcm9tQ2hhckNvZGUoNjUgKyAobiAlIDI2KSkgKyByZXN1bHQ7XG4gICAgICBuID0gTWF0aC5mbG9vcihuIC8gMjYpIC0gMTtcbiAgICB9IHdoaWxlIChuID49IDApO1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICBwcml2YXRlIGJ1aWxkRW1wdHlXb3JrYm9vaygpOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGlkOiAnd29ya2Jvb2stZGVmYXVsdCcsXG4gICAgICBsb2NhbGU6IHRoaXMucmVzb2x2ZUxvY2FsZVR5cGUoKSxcbiAgICAgIG5hbWU6ICdTaGVldCcsXG4gICAgICBzaGVldE9yZGVyOiBbJ3NoZWV0MSddLFxuICAgICAgYXBwVmVyc2lvbjogJzMuMC4wLWFscGhhJyxcbiAgICAgIHNoZWV0czoge1xuICAgICAgICBzaGVldDE6IHsgaWQ6ICdzaGVldDEnLCBuYW1lOiAnU2hlZXQxJywgcm93Q291bnQ6IDMwLCBjb2x1bW5Db3VudDogMjYsIGNlbGxEYXRhOiB7fSB9LFxuICAgICAgfSxcbiAgICB9O1xuICB9XG5cbiAgcHJpdmF0ZSByZXNvbHZlTG9jYWxlVHlwZSgpOiBMb2NhbGVUeXBlIHtcbiAgICByZXR1cm4gdGhpcy5hY3RpdmVMb2NhbGUoKSA9PT0gJ3ZpJyA/IExvY2FsZVR5cGUuVklfVk4gOiBMb2NhbGVUeXBlLkVOX1VTO1xuICB9XG5cbiAgcHJpdmF0ZSByZWdpc3RlckNvbHVtbkNsaWNrTGlzdGVuZXIoKSB7XG4gICAgY29uc3Qgd3JhcHBlciA9IHRoaXMuY29udGFpbmVyUmVmKCk/Lm5hdGl2ZUVsZW1lbnQgYXMgSFRNTEVsZW1lbnQgfCB1bmRlZmluZWQ7XG4gICAgaWYgKCF3cmFwcGVyKSByZXR1cm47XG5cbiAgICB0aGlzLmxpc3RlbkVuYWJsZVRpbWVyID0gc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICB0aGlzLmxpc3RlbkVuYWJsZWQgPSB0cnVlO1xuICAgIH0sIDYwMCk7XG5cbiAgICBjb25zdCBoYW5kbGVEYmxDbGljayA9IChldmVudDogTW91c2VFdmVudCkgPT4ge1xuICAgICAgaWYgKCF0aGlzLmxpc3RlbkVuYWJsZWQpIHJldHVybjtcbiAgICAgIGlmICgoZXZlbnQudGFyZ2V0IGFzIEhUTUxFbGVtZW50KS50YWdOYW1lICE9PSAnQ0FOVkFTJykgcmV0dXJuO1xuXG4gICAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgdGhpcy5uZ1pvbmUucnVuKCgpID0+IHtcbiAgICAgICAgICBjb25zdCByYW5nZSA9IHRoaXMudW5pdmVyQVBJPy5nZXRBY3RpdmVXb3JrYm9vaygpPy5nZXRBY3RpdmVTaGVldCgpPy5nZXRBY3RpdmVSYW5nZSgpO1xuICAgICAgICAgIGlmICghcmFuZ2UpIHJldHVybjtcblxuICAgICAgICAgIGNvbnN0IHsgc3RhcnRSb3csIGVuZFJvdywgc3RhcnRDb2x1bW4sIHJhbmdlVHlwZSB9ID0gcmFuZ2UuZ2V0UmFuZ2UoKTtcbiAgICAgICAgICBjb25zdCBpc0NvbEhlYWRlciA9IHJhbmdlVHlwZSA9PT0gMiB8fCAoc3RhcnRSb3cgPT09IDAgJiYgZW5kUm93ID49IDI5KTtcbiAgICAgICAgICBjb25zdCBpc0ZpcnN0Um93ID0gc3RhcnRSb3cgPT09IDAgJiYgZW5kUm93ID09PSAwO1xuXG4gICAgICAgICAgaWYgKCFpc0NvbEhlYWRlciAmJiAhaXNGaXJzdFJvdykgcmV0dXJuO1xuICAgICAgICAgIHRoaXMub3V0Q29sdW1uRGJsQ2xpY2suZW1pdChzdGFydENvbHVtbik7XG4gICAgICAgIH0pO1xuICAgICAgfSwgNTApO1xuICAgIH07XG5cbiAgICB3cmFwcGVyLmFkZEV2ZW50TGlzdGVuZXIoJ2RibGNsaWNrJywgaGFuZGxlRGJsQ2xpY2spO1xuICAgIHRoaXMuY29sdW1uQ2xpY2tEaXNwb3NhYmxlID0geyBkaXNwb3NlOiAoKSA9PiB3cmFwcGVyLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2RibGNsaWNrJywgaGFuZGxlRGJsQ2xpY2spIH07XG4gIH1cblxuICAvKipcbiAgICogTOG6r25nIG5naGUgTVVUQVRJT04gY+G7mXQgKGluc2VydC9yZW1vdmUvbW92ZSkg4oCUIG3hu6ljIG11dGF0aW9uIMSR4buDIGLhuq90IGPhuqMgdW5kby9yZWRvLCBt4buZdCBs4bqnbi90aGFvIHTDoWMuXG4gICAqIENodeG6qW4gaG/DoSB0aMOgbmggYFRfY29sdW1uU3RydWN0dXJlQ2hhbmdlYCBy4buTaSBwaMOhdCByYSBuZ2/DoGkgY2hvIGNvbnN1bWVyIHJlbWFwIG1hcHBpbmcuXG4gICAqL1xuICBwcml2YXRlIHJlZ2lzdGVyQ29sdW1uT3BMaXN0ZW5lcigpIHtcbiAgICAvLyBDT05WRU5USU9OLUVYQ0VQVDogYW55IOKAlCBGVW5pdmVyLm9uQ29tbWFuZEV4ZWN1dGVkIC8gY29tbWFuZEluZm8ga2jDtG5nIGV4cG9zZSB0cm9uZyBwdWJsaWMgdHlwZXNcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxuICAgIGNvbnN0IGFwaSA9IHRoaXMudW5pdmVyQVBJIGFzIGFueTtcbiAgICBpZiAodHlwZW9mIGFwaT8ub25Db21tYW5kRXhlY3V0ZWQgIT09ICdmdW5jdGlvbicpIHJldHVybjtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxuICAgIHRoaXMuY29sdW1uT3BEaXNwb3NhYmxlID0gYXBpLm9uQ29tbWFuZEV4ZWN1dGVkKChjb21tYW5kSW5mbzogYW55KSA9PiB7XG4gICAgICBjb25zdCBjaGFuZ2UgPSB0aGlzLnRvQ29sdW1uU3RydWN0dXJlQ2hhbmdlKGNvbW1hbmRJbmZvPy5pZCwgY29tbWFuZEluZm8/LnBhcmFtcyk7XG4gICAgICBpZiAoY2hhbmdlKSB0aGlzLm5nWm9uZS5ydW4oKCkgPT4gdGhpcy5vdXRDb2x1bW5TdHJ1Y3R1cmVDaGFuZ2UuZW1pdChjaGFuZ2UpKTtcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgdG9Db2x1bW5TdHJ1Y3R1cmVDaGFuZ2UoaWQ6IHVua25vd24sIHBhcmFtczogdW5rbm93bik6IFRfY29sdW1uU3RydWN0dXJlQ2hhbmdlIHwgbnVsbCB7XG4gICAgdHlwZSBUX3JhbmdlID0geyBzdGFydENvbHVtbjogbnVtYmVyOyBlbmRDb2x1bW46IG51bWJlciB9O1xuICAgIHR5cGUgVF9jb2xQYXJhbXMgPSB7IHN1YlVuaXRJZD86IHN0cmluZzsgcmFuZ2U/OiBUX3JhbmdlOyBzb3VyY2VSYW5nZT86IFRfcmFuZ2U7IHRhcmdldFJhbmdlPzogVF9yYW5nZSB9O1xuICAgIGNvbnN0IHAgPSBwYXJhbXMgYXMgVF9jb2xQYXJhbXMgfCB1bmRlZmluZWQ7XG4gICAgY29uc3Qgc2hlZXRJZCA9IHA/LnN1YlVuaXRJZCA/PyAnJztcblxuICAgIGlmIChpZCA9PT0gSW5zZXJ0Q29sTXV0YXRpb24uaWQgfHwgaWQgPT09IFJlbW92ZUNvbE11dGF0aW9uLmlkKSB7XG4gICAgICBpZiAoIXA/LnJhbmdlKSByZXR1cm4gbnVsbDtcbiAgICAgIGNvbnN0IHR5cGUgPSBpZCA9PT0gSW5zZXJ0Q29sTXV0YXRpb24uaWQgPyAnaW5zZXJ0JyA6ICdyZW1vdmUnO1xuICAgICAgcmV0dXJuIHsgc2hlZXRJZCwgdHlwZSwgc3RhcnRDb2x1bW46IHAucmFuZ2Uuc3RhcnRDb2x1bW4sIGNvdW50OiBwLnJhbmdlLmVuZENvbHVtbiAtIHAucmFuZ2Uuc3RhcnRDb2x1bW4gKyAxIH07XG4gICAgfVxuICAgIGlmIChpZCA9PT0gTW92ZUNvbHNNdXRhdGlvbi5pZCkge1xuICAgICAgaWYgKCFwPy5zb3VyY2VSYW5nZSB8fCAhcD8udGFyZ2V0UmFuZ2UpIHJldHVybiBudWxsO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgc2hlZXRJZCxcbiAgICAgICAgdHlwZTogJ21vdmUnLFxuICAgICAgICBzdGFydENvbHVtbjogcC5zb3VyY2VSYW5nZS5zdGFydENvbHVtbixcbiAgICAgICAgY291bnQ6IHAuc291cmNlUmFuZ2UuZW5kQ29sdW1uIC0gcC5zb3VyY2VSYW5nZS5zdGFydENvbHVtbiArIDEsXG4gICAgICAgIHRvQ29sdW1uOiBwLnRhcmdldFJhbmdlLnN0YXJ0Q29sdW1uLFxuICAgICAgfTtcbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBwcml2YXRlIHJlZ2lzdGVyRm9ybWF0TGlzdGVuZXIoKSB7XG4gICAgLy8gQ09OVkVOVElPTi1FWENFUFQ6IGFueSDigJQgRlVuaXZlci5vbkNvbW1hbmRFeGVjdXRlZCAvIGNvbW1hbmRJbmZvIGtow7RuZyBleHBvc2UgdHJvbmcgcHVibGljIHR5cGVzXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnlcbiAgICBjb25zdCBhcGkgPSB0aGlzLnVuaXZlckFQSSBhcyBhbnk7XG4gICAgaWYgKHR5cGVvZiBhcGk/Lm9uQ29tbWFuZEV4ZWN1dGVkICE9PSAnZnVuY3Rpb24nKSByZXR1cm47XG5cbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxuICAgIHRoaXMuZm9ybWF0RGlzcG9zYWJsZSA9IGFwaS5vbkNvbW1hbmRFeGVjdXRlZCgoY29tbWFuZEluZm86IGFueSkgPT4ge1xuICAgICAgdGhpcy5uZ1pvbmUucnVuKCgpID0+IHtcbiAgICAgICAgaWYgKGNvbW1hbmRJbmZvPy5pZCA9PT0gJ3NoZWV0Lm9wZXJhdGlvbi5vcGVuLm51bWZtdC5wYW5lbCcpIHtcbiAgICAgICAgICB0aGlzLm51bWZtdFBhbmVsT3BlbiA9IHRydWU7XG4gICAgICAgICAgdGhpcy5udW1mbXRDb25maXJtZWQgPSBmYWxzZTsgLy8gcmVzZXQgY+G7nSDigJQgcGhpw6puIG3hu5tpIG3hurdjIMSR4buLbmggY2jGsGEgQ29uZmlybVxuICAgICAgICAgIHRoaXMubnVtZm10RGF0ZUFjdGl2ZSA9IGZhbHNlOyAvLyBjaMawYSBjaOG7jW4gVHlwZT1EYXRlIOKGkiBjaMawYSBrw61jaCBob+G6oXQgbHXhu5NuZyBjdXN0b21cbiAgICAgICAgICAvLyBMxrB1IG51bWZtdCBn4buRYyB04burbmcgw7QgxJHhu4MgQ2FuY2VsIGtow7RpIHBo4bulYyDEkcO6bmcgKHbDuW5nIGNo4buNbiBjw7MgdGjhu4Mgbmhp4buBdSBmb3JtYXQga2jDoWMgbmhhdSlcbiAgICAgICAgICB0aGlzLm9yaWdpbmFsQ2VsbEZvcm1hdHMgPSB0aGlzLmNhcHR1cmVSYW5nZU51bWZtdCh0aGlzLmxhc3RSYW5nZVNuYXBzaG90KTtcbiAgICAgICAgICAvLyBDaOG7iSBi4bqtdCBvYnNlcnZlciBraGkgcGFuZWwgbeG7nyAodHLDoW5oIGNo4bqheSBsacOqbiB04bulYyB0aGVvIG3hu41pIG11dGF0aW9uIHRvw6BuIHRyYW5nKVxuICAgICAgICAgIHRoaXMubnVtZm10T2JzZXJ2ZXI/Lm9ic2VydmUoZG9jdW1lbnQuYm9keSwgeyBjaGlsZExpc3Q6IHRydWUsIHN1YnRyZWU6IHRydWUgfSk7XG4gICAgICAgICAgLy8gUmVvcGVuOiBVbml2ZXIgaGnhu4duIGzhuqFpIHBhbmVsIGPFqSBi4bqxbmcgQ1NTIChraMO0bmcgbXV0YXRpb24pIOKGkiBvYnNlcnZlciBraMO0bmcgZmlyZS4gQ2jhu6cgxJHhu5luZ1xuICAgICAgICAgIC8vIHRo4butIGluamVjdCBzYXUgMSBuaOG7i3AgxJHhu4MgYuG6r3QgdHLGsOG7nW5nIGjhu6NwIGxpc3QgbmfDoHkgxJHDoyBz4bq1biB0cm9uZyBET00gdMOhaSBkw7luZy5cbiAgICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgICAgIGlmICh0aGlzLm51bWZtdFBhbmVsT3BlbikgdGhpcy5wcm9jZXNzTnVtZm10UGFuZWwoKTtcbiAgICAgICAgICB9LCA2MCk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGNvbW1hbmRJbmZvPy5pZCA9PT0gJ3NoZWV0Lm9wZXJhdGlvbi5jbG9zZS5udW1mbXQucGFuZWwnKSB7XG4gICAgICAgICAgdGhpcy5udW1mbXRQYW5lbE9wZW4gPSBmYWxzZTtcbiAgICAgICAgICAvLyBU4bqvdCBvYnNlcnZlciBraGkgxJHDs25nIChwZXJmKS4gS0jDlE5HIGfhu6EgbGlzdGVuZXI6IFVuaXZlciB0w6FpIGTDuW5nIERPTSBwYW5lbCwgZ+G7oSBz4bq9IGzDoG1cbiAgICAgICAgICAvLyBvcHRpb24gY2jhur90IGtoaSBt4bufIGzhuqFpLiBjbGVhbnVwIGNo4bqheSB0csaw4bubYyBs4bqnbiBpbmplY3QgbeG7m2kgKERPTSBt4bubaSkgaG/hurdjIGtoaSBkZXN0cm95LlxuICAgICAgICAgIHRoaXMubnVtZm10T2JzZXJ2ZXI/LmRpc2Nvbm5lY3QoKTtcbiAgICAgICAgICAvLyBVbml2ZXIgVMOBSSBEw5lORyBET00gcGFuZWwga2hpIHJlb3BlbiAobmjhu5sgY+G6oyBUeXBlPURhdGUpIOKGkiBndWFyZCBkYXRhLWN1c3RvbS1kYXRlcyBjw7JuIHPDs3Qgc+G6vVxuICAgICAgICAgIC8vIGNo4bq3biByZS1pbmplY3Qg4bufIGzhuqduIG3hu58gc2F1LCBraGnhur9uIGhpZ2hsaWdodCBzdGFsZSArIGRhdGVBY3RpdmU9ZmFsc2UgKG3huqV0IHJldmVydCkuIFhvw6EgZ3VhcmRcbiAgICAgICAgICAvLyDEkeG7gyBs4bqnbiBt4bufIGvhur8gdGnhur9wIGluamVjdCBs4bqhaSArIHJlc3luYyBoaWdobGlnaHQvYXV0by1hcHBseSB0aGVvIGPhu5l0IGhp4buHbiB04bqhaS5cbiAgICAgICAgICBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCcubnVtZm10LXBhbmVsIHVsLnVuaXZlci1zZWxlY3QtbGlzdCcpPy5yZW1vdmVBdHRyaWJ1dGUoJ2RhdGEtY3VzdG9tLWRhdGVzJyk7XG4gICAgICAgICAgLy8gQ2jhu4kga2hpIGLhuqVtIENPTkZJUk0gKG51bWZtdENvbmZpcm1lZD10cnVlKSBt4bubaSBHSeG7riBwYXR0ZXJuIMSRw6MgY2jhu41uIGNobyBj4bqjIHbDuW5nLlxuICAgICAgICAgIC8vIENhbmNlbCAvIFggLyBjbGljay1uZ2/DoGkgxJHhu4F1IEtIw5RORyBzZXQgY+G7nSDihpIgS0jDlEkgUEjhu6RDIG51bWZtdCBH4buQQyBU4buqTkcgw5QgKMSRw6MgY2jhu6VwIGtoaSBt4bufIHBhbmVsKS5cbiAgICAgICAgICBjb25zdCBkYXRlQWN0aXZlID0gdGhpcy5udW1mbXREYXRlQWN0aXZlO1xuICAgICAgICAgIGNvbnN0IGNvbmZpcm1lZCA9IHRoaXMubnVtZm10Q29uZmlybWVkO1xuICAgICAgICAgIGNvbnN0IHBlbmRpbmcgPSB0aGlzLnBlbmRpbmdOdW1mbXRQYXR0ZXJuO1xuICAgICAgICAgIGNvbnN0IG9yaWdpbmFsQ2VsbHMgPSB0aGlzLm9yaWdpbmFsQ2VsbEZvcm1hdHM7XG4gICAgICAgICAgdGhpcy5udW1mbXRDb25maXJtZWQgPSBmYWxzZTtcbiAgICAgICAgICB0aGlzLnBlbmRpbmdOdW1mbXRQYXR0ZXJuID0gbnVsbDtcbiAgICAgICAgICB0aGlzLm9yaWdpbmFsQ2VsbEZvcm1hdHMgPSBudWxsO1xuICAgICAgICAgIHRoaXMubnVtZm10RGF0ZUFjdGl2ZSA9IGZhbHNlO1xuXG4gICAgICAgICAgLy8gVHlwZSBraMOhYyBEYXRlIChT4buRL1Rp4buBbiB04buHLyUvVGV4dOKApikgZG8gVW5pdmVyIHThu7EgYXBwbHkvY2FuY2VsIOKGkiBLSMOUTkcgY2FuIHRoaeG7h3AsXG4gICAgICAgICAgLy8gbuG6v3Uga2jDtG5nIHPhur0gcmV2ZXJ0IG5o4bqnbSBmb3JtYXQgbcOgIHVzZXIgduG7q2Egw6FwIHF1YSBsdeG7k25nIG5hdGl2ZSBj4bunYSBVbml2ZXIuXG4gICAgICAgICAgaWYgKCFkYXRlQWN0aXZlKSB7XG4gICAgICAgICAgICB0aGlzLmNsZWFyTnVtZm10UHJldmlldygpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGNvbnN0IHNuYXAgPSB0aGlzLmxhc3RSYW5nZVNuYXBzaG90O1xuICAgICAgICAgIGlmICghc25hcCkgcmV0dXJuO1xuXG4gICAgICAgICAgbGV0IHZhbHVlczogeyBwYXR0ZXJuOiBzdHJpbmc7IHJvdzogbnVtYmVyOyBjb2w6IG51bWJlciB9W107XG4gICAgICAgICAgaWYgKGNvbmZpcm1lZCAmJiBwZW5kaW5nKSB7XG4gICAgICAgICAgICB2YWx1ZXMgPSBbXTtcbiAgICAgICAgICAgIGZvciAobGV0IHIgPSBzbmFwLnN0YXJ0Um93OyByIDw9IE1hdGgubWluKHNuYXAuZW5kUm93LCBzbmFwLnN0YXJ0Um93ICsgNDk5KTsgcisrKSB7XG4gICAgICAgICAgICAgIGZvciAobGV0IGMgPSBzbmFwLnN0YXJ0Q29sdW1uOyBjIDw9IHNuYXAuZW5kQ29sdW1uOyBjKyspIHtcbiAgICAgICAgICAgICAgICB2YWx1ZXMucHVzaCh7IHBhdHRlcm46IHBlbmRpbmcsIHJvdzogciwgY29sOiBjIH0pO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIGlmICghY29uZmlybWVkICYmIG9yaWdpbmFsQ2VsbHMpIHtcbiAgICAgICAgICAgIHZhbHVlcyA9IG9yaWdpbmFsQ2VsbHM7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKCF2YWx1ZXMubGVuZ3RoKSByZXR1cm47XG4gICAgICAgICAgLy8gQ09OVkVOVElPTi1FWENFUFQ6IGFueSDigJQgRlVuaXZlci5leGVjdXRlQ29tbWFuZCBraMO0bmcgZXhwb3NlIHR5cGluZ1xuICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55XG4gICAgICAgICAgdm9pZCAodGhpcy51bml2ZXJBUEkgYXMgYW55KT8uZXhlY3V0ZUNvbW1hbmQ/Lignc2hlZXQuY29tbWFuZC5udW1mbXQuc2V0Lm51bWZtdCcsIHtcbiAgICAgICAgICAgIHVuaXRJZDogc25hcC51bml0SWQsXG4gICAgICAgICAgICBzdWJVbml0SWQ6IHNuYXAuc3ViVW5pdElkLFxuICAgICAgICAgICAgdmFsdWVzLFxuICAgICAgICAgIH0pO1xuICAgICAgICAgIHRoaXMuY2xlYXJOdW1mbXRQcmV2aWV3KCk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gS2hpIHBhbmVsIMSRYW5nIG3hu586IENI4buIIHVzZXIgxJHhu5VpIHbDuW5nIGNo4buNbiB0csOqbiBncmlkIChzZXQtc2VsZWN0aW9ucykgbeG7m2kgxJHGsOG7o2MgY+G6rXAgbmjhuq10IHNuYXBzaG90XG4gICAgICAgIC8vIMSR4buDIHJlLXRhcmdldCBwYW5lbCBzYW5nIGPhu5l0L2NlbGwgbeG7m2kuIENvbW1hbmQgbuG7mWkgYuG7mSBwYW5lbCAobnVtZm10LnNldCwgbXV0YXRpb27igKYpIEtIw5RORyDEkeG7pW5nIHNuYXBzaG90LlxuICAgICAgICBjb25zdCBpc1VzZXJTZWxlY3Rpb24gPSBjb21tYW5kSW5mbz8uaWQgPT09ICdzaGVldC5vcGVyYXRpb24uc2V0LXNlbGVjdGlvbnMnO1xuICAgICAgICBpZiAodGhpcy5udW1mbXRQYW5lbE9wZW4gJiYgIWlzVXNlclNlbGVjdGlvbikgcmV0dXJuO1xuXG4gICAgICAgIGNvbnN0IHdiID0gdGhpcy51bml2ZXJBUEk/LmdldEFjdGl2ZVdvcmtib29rKCk7XG4gICAgICAgIGNvbnN0IHdzID0gd2I/LmdldEFjdGl2ZVNoZWV0KCk7XG4gICAgICAgIGNvbnN0IHJhbmdlID0gd3M/LmdldEFjdGl2ZVJhbmdlKCk7XG4gICAgICAgIGlmICghcmFuZ2UgfHwgIXdiIHx8ICF3cykgcmV0dXJuO1xuXG4gICAgICAgIGNvbnN0IHJhbmdlRGF0YSA9IHJhbmdlLmdldFJhbmdlKCk7XG4gICAgICAgIHRoaXMuYWN0aXZlQ2VsbFJlZi5zZXQoYCR7dGhpcy50b0NvbExldHRlcihyYW5nZURhdGEuc3RhcnRDb2x1bW4pfSR7cmFuZ2VEYXRhLnN0YXJ0Um93ICsgMX1gKTtcblxuICAgICAgICAvLyBDT05WRU5USU9OLUVYQ0VQVDogYW55IOKAlCBGV29ya2Jvb2suZ2V0SWQgLyBGV29ya3NoZWV0LmdldFNoZWV0SWQgY2jGsGEgZXhwb3NlIHRyb25nIHR5cGVzXG4gICAgICAgIC8qIGVzbGludC1kaXNhYmxlIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnkgKi9cbiAgICAgICAgY29uc3Qgd2JBbnkgPSB3YiBhcyBhbnk7XG4gICAgICAgIGNvbnN0IHdzQW55ID0gd3MgYXMgYW55O1xuICAgICAgICAvKiBlc2xpbnQtZW5hYmxlIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnkgKi9cbiAgICAgICAgdGhpcy5sYXN0UmFuZ2VTbmFwc2hvdCA9IHtcbiAgICAgICAgICB1bml0SWQ6ICh3YkFueS5nZXRJZD8uKCkgPz8gd2JBbnkuZ2V0VW5pdElkPy4oKSA/PyAnJykgYXMgc3RyaW5nLFxuICAgICAgICAgIHN1YlVuaXRJZDogKHdzQW55LmdldFNoZWV0SWQ/LigpID8/IHdzQW55LmdldFVuaXRJZD8uKCkgPz8gJycpIGFzIHN0cmluZyxcbiAgICAgICAgICBzdGFydFJvdzogcmFuZ2VEYXRhLnN0YXJ0Um93LFxuICAgICAgICAgIGVuZFJvdzogcmFuZ2VEYXRhLmVuZFJvdyxcbiAgICAgICAgICBzdGFydENvbHVtbjogcmFuZ2VEYXRhLnN0YXJ0Q29sdW1uLFxuICAgICAgICAgIGVuZENvbHVtbjogcmFuZ2VEYXRhLmVuZENvbHVtbixcbiAgICAgICAgfTtcblxuICAgICAgICAvLyBDT05WRU5USU9OLUVYQ0VQVDogYW55IOKAlCBGUmFuZ2UuZ2V0Q2VsbFN0eWxlRGF0YSBjaMawYSBleHBvc2UgdHJvbmcgdHlwZXNcbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnlcbiAgICAgICAgY29uc3QgcmFuZ2VBbnkgPSByYW5nZSBhcyBhbnk7XG4gICAgICAgIGNvbnN0IHN0eWxlID0gcmFuZ2VBbnkuZ2V0Q2VsbFN0eWxlRGF0YT8uKCk7XG4gICAgICAgIGNvbnN0IG51bUZtdCA9IHN0eWxlPy5uPy5wYXR0ZXJuID8/IHN0eWxlPy5uZj8ucGF0dGVybjtcbiAgICAgICAgdGhpcy5hY3RpdmVDZWxsRm9ybWF0LnNldChudW1GbXQgJiYgbnVtRm10ICE9PSAnMCcgPyBudW1GbXQgOiAnR2VuZXJhbCcpO1xuXG4gICAgICAgIC8vIFVzZXIgxJHhu5VpIHbDuW5nIGNo4buNbiBMw5pDIHBhbmVsIERhdGUgxJFhbmcgbeG7nyDihpIgdMOtY2ggbHXhu7kgbnVtZm10IGfhu5FjIGPhu6dhIHbDuW5nIG3hu5tpICjEkeG7gyBDYW5jZWxcbiAgICAgICAgLy8gcmV2ZXJ0IMSRw7puZyBt4buNaSDDtCDEkcOjIGNo4bqhbSkgcuG7k2kgxJHhu5NuZyBi4buZIGzhuqFpIHBhbmVsIChsYWJlbCArIGhpZ2hsaWdodCArIGF1dG8tYXBwbHkpIHRoZW8gY+G7mXQgbeG7m2kuXG4gICAgICAgIGlmICh0aGlzLm51bWZtdFBhbmVsT3BlbiAmJiB0aGlzLm51bWZtdERhdGVBY3RpdmUpIHtcbiAgICAgICAgICB0aGlzLm1lcmdlT3JpZ2luYWxDZWxsRm9ybWF0cyh0aGlzLmNhcHR1cmVSYW5nZU51bWZtdCh0aGlzLmxhc3RSYW5nZVNuYXBzaG90KSk7XG4gICAgICAgICAgdGhpcy5udW1mbXRSZXN5bmM/LigpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKiBH4buZcCBudW1mbXQgZ+G7kWMgY+G7p2EgdsO5bmcgduG7q2EgY2jhu41uIHbDoG8gc25hcHNob3QgcmV2ZXJ0LCBnaeG7ryBnacOhIHRy4buLIEfhu5BDIMSQ4bqmVSBUScOKTiBjaG8gbeG7l2kgw7QuICovXG4gIHByaXZhdGUgbWVyZ2VPcmlnaW5hbENlbGxGb3JtYXRzKGV4dHJhOiB7IHBhdHRlcm46IHN0cmluZzsgcm93OiBudW1iZXI7IGNvbDogbnVtYmVyIH1bXSB8IG51bGwpIHtcbiAgICBpZiAoIWV4dHJhKSByZXR1cm47XG4gICAgaWYgKCF0aGlzLm9yaWdpbmFsQ2VsbEZvcm1hdHMpIHtcbiAgICAgIHRoaXMub3JpZ2luYWxDZWxsRm9ybWF0cyA9IGV4dHJhO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCBzZWVuID0gbmV3IFNldCh0aGlzLm9yaWdpbmFsQ2VsbEZvcm1hdHMubWFwKCh2KSA9PiBgJHt2LnJvd306JHt2LmNvbH1gKSk7XG4gICAgZm9yIChjb25zdCBjZWxsIG9mIGV4dHJhKSB7XG4gICAgICBpZiAoc2Vlbi5oYXMoYCR7Y2VsbC5yb3d9OiR7Y2VsbC5jb2x9YCkpIGNvbnRpbnVlO1xuICAgICAgdGhpcy5vcmlnaW5hbENlbGxGb3JtYXRzLnB1c2goY2VsbCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFhvw6EgbGl2ZS1wcmV2aWV3IG92ZXJsYXkgY+G7p2EgVW5pdmVyIG51bWZtdCBwYW5lbC5cbiAgICpcbiAgICogS2hpIHBhbmVsIG51bWZtdCBt4bufLCBgTnVtZm10Q29udHJvbGxlci5fcHJldmlld1BhdHRlcm5gIMSRxrDhu6NjIFVuaXZlciBkw7luZyDEkeG7gyB24bq9IMSRw6hcbiAgICogKHByZXZpZXcpIGzDqm4gaGnhu4NuIHRo4buLIHRo4bqtdCBj4bunYSB2w7luZyBjaOG7jW4uIFbDrCBjw6FjIG9wdGlvbiBkYXRlIGN1c3RvbSBnaGkgbnVtZm10XG4gICAqIHRy4buxYyB0aeG6v3AgdsOgbyBtb2RlbCAoa2jDtG5nIMSRaSBxdWEgcGFuZWwgZ+G7kWMgY+G7p2EgVW5pdmVyKSwgcHJldmlldyBuw6B5IGtow7RuZyBiYW8gZ2nhu51cbiAgICoga2jhu5twIG1vZGVsIOKGkiBj4buZdCBraMO0bmcgxJHhu5VpIGhp4buDbiB0aOG7iyBuZ2F5LiBTZXQgYF9wcmV2aWV3UGF0dGVybiA9IG51bGxgICsgZm9yY2UgcmUtcmVuZGVyXG4gICAqIChgX2ZvcmNlVXBkYXRlYCkgxJHhu4MgY2FudmFzIHbhur0gxJHDum5nIGdpw6EgdHLhu4sgbW9kZWwgdOG7qWMgdGjDrC5cbiAgICpcbiAgICogTnVtZm10Q29udHJvbGxlciBraMO0bmcgZXhwb3J0IGto4buPaSBgQHVuaXZlcmpzL3NoZWV0cy1udW1mbXRgIG7Dqm4gcGjhuqNpIHTDrG0gaW5zdGFuY2VcbiAgICogcXVhIGluamVjdG9yIGPhu6dhIFVuaXZlciAoY2FjaGUgbOG6oWkgc2F1IGzhuqduIMSR4bqndSkuXG4gICAqL1xuICBwcml2YXRlIGNsZWFyTnVtZm10UHJldmlldygpIHtcbiAgICBjb25zdCBjb250cm9sbGVyID0gdGhpcy5yZXNvbHZlTnVtZm10Q29udHJvbGxlcigpO1xuICAgIGlmICghY29udHJvbGxlcikgcmV0dXJuO1xuICAgIGlmIChjb250cm9sbGVyLl9wcmV2aWV3UGF0dGVybiAhPSBudWxsKSBjb250cm9sbGVyLl9wcmV2aWV3UGF0dGVybiA9IG51bGw7XG4gICAgLy8gTFXDlE4gZm9yY2UgcmUtcmVuZGVyOiBudW1mbXQgduG7q2Egw6FwIHbDoG8gbW9kZWwgY+G6p24gduG6vSBs4bqhaSBjYW52YXMgbmdheSAoa+G7gyBj4bqjIGtoaSBraMO0bmcgY8OzIHByZXZpZXcpLlxuICAgIGNvbnRyb2xsZXIuX2ZvcmNlVXBkYXRlPy4oKTtcbiAgfVxuXG4gIC8vIENPTlZFTlRJT04tRVhDRVBUOiBhbnkg4oCUIHRydXkgY+G6rXAgaW5qZWN0b3IgKyBOdW1mbXRDb250cm9sbGVyIG7hu5lpIGLhu5kgY+G7p2EgVW5pdmVyIChraMO0bmcgY8OzIHB1YmxpYyBBUEkpXG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55XG4gIHByaXZhdGUgcmVzb2x2ZU51bWZtdENvbnRyb2xsZXIoKTogYW55IHtcbiAgICBpZiAodGhpcy5udW1mbXRDb250cm9sbGVyKSByZXR1cm4gdGhpcy5udW1mbXRDb250cm9sbGVyO1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55XG4gICAgY29uc3QgaW5qZWN0b3IgPSAodGhpcy51bml2ZXIgYXMgYW55KT8uX19nZXRJbmplY3Rvcj8uKCk7XG4gICAgaWYgKCFpbmplY3RvcikgcmV0dXJuIG51bGw7XG5cbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxuICAgIGNvbnN0IHNjYW5NYXAgPSAobWFwOiB1bmtub3duKTogYW55ID0+IHtcbiAgICAgIGlmICghKG1hcCBpbnN0YW5jZW9mIE1hcCkpIHJldHVybiBudWxsO1xuICAgICAgZm9yIChjb25zdCB2YWx1ZSBvZiBtYXAudmFsdWVzKCkpIHtcbiAgICAgICAgY29uc3QgY2FuZGlkYXRlcyA9IEFycmF5LmlzQXJyYXkodmFsdWUpID8gdmFsdWUgOiBbdmFsdWVdO1xuICAgICAgICBmb3IgKGNvbnN0IGNhbmRpZGF0ZSBvZiBjYW5kaWRhdGVzKSB7XG4gICAgICAgICAgY29uc3QgaW5zdGFuY2UgPSBjYW5kaWRhdGU/Lmluc3RhbmNlICE9PSB1bmRlZmluZWQgPyBjYW5kaWRhdGUuaW5zdGFuY2UgOiBjYW5kaWRhdGU7XG4gICAgICAgICAgaWYgKGluc3RhbmNlICYmIHR5cGVvZiBpbnN0YW5jZSA9PT0gJ29iamVjdCcgJiYgJ19wcmV2aWV3UGF0dGVybicgaW4gaW5zdGFuY2UpIHJldHVybiBpbnN0YW5jZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfTtcblxuICAgIC8vIEPDoWMgaW5zdGFuY2UgY+G7p2EgcmVkaSBu4bqxbSB0cm9uZyBNYXAgbOG7k25nIDEgY+G6pXAgKHZkIGluamVjdG9yLnJlc29sdmVkRGVwZW5kZW5jeUNvbGxlY3Rpb24ucmVzb2x2ZWREZXBlbmRlbmNpZXMpXG4gICAgZm9yIChjb25zdCBrZXkgb2YgT2JqZWN0LmtleXMoaW5qZWN0b3IpKSB7XG4gICAgICBjb25zdCB2YWx1ZSA9IGluamVjdG9yW2tleV07XG4gICAgICBsZXQgZm91bmQgPSBzY2FuTWFwKHZhbHVlKTtcbiAgICAgIGlmICghZm91bmQgJiYgdmFsdWUgJiYgdHlwZW9mIHZhbHVlID09PSAnb2JqZWN0Jykge1xuICAgICAgICBmb3IgKGNvbnN0IG5lc3RlZEtleSBvZiBPYmplY3Qua2V5cyh2YWx1ZSkpIHtcbiAgICAgICAgICBmb3VuZCA9IHNjYW5NYXAodmFsdWVbbmVzdGVkS2V5XSk7XG4gICAgICAgICAgaWYgKGZvdW5kKSBicmVhaztcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKGZvdW5kKSB7XG4gICAgICAgIHRoaXMubnVtZm10Q29udHJvbGxlciA9IGZvdW5kO1xuICAgICAgICByZXR1cm4gZm91bmQ7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgLyoqXG4gICAqIFThuqFvIG9ic2VydmVyIMSR4buDIGluamVjdCBvcHRpb24gbmfDoHkgY3VzdG9tICsgaGlnaGxpZ2h0IGtoaSBwYW5lbCBudW1mbXQgcmVuZGVyLlxuICAgKiBPYnNlcnZlciBDSOG7iCDEkcaw4bujYyBi4bqtdC904bqvdCB0aGVvIHbDsm5nIMSR4budaSBwYW5lbCAoeGVtIG9wZW4vY2xvc2UubnVtZm10LnBhbmVsIGhhbmRsZXIpIMSR4buDXG4gICAqIGtow7RuZyBjaOG6oXkgbGnDqm4gdOG7pWMgdGhlbyBt4buNaSBtdXRhdGlvbiBET00gdG/DoG4gdHJhbmcuXG4gICAqL1xuICBwcml2YXRlIHJlZ2lzdGVyTnVtZm10RHJvcGRvd25PYnNlcnZlcigpIHtcbiAgICB0aGlzLm51bWZtdE9ic2VydmVyID0gbmV3IE11dGF0aW9uT2JzZXJ2ZXIoKCkgPT4gdGhpcy5wcm9jZXNzTnVtZm10UGFuZWwoKSk7XG4gIH1cblxuICAvKipcbiAgICogVGjhu60gaW5qZWN0IG9wdGlvbiBuZ8OgeSBjdXN0b20gKyBoaWdobGlnaHQgY2hvIHBhbmVsIG51bWZtdCBoaeG7h24gdOG6oWkuXG4gICAqIEfhu41pIHThu6sgMiBuZ3Xhu5NuOiAoMSkgTXV0YXRpb25PYnNlcnZlciBraGkgVW5pdmVyIHJlbmRlciBsaXN0IG5nw6B5OyAoMikgdHLhu7FjIHRp4bq/cCBsw7pjIG3hu58gcGFuZWwg4oCUXG4gICAqIHbDrCBVbml2ZXIgVMOBSSBEw5lORyBET00gcGFuZWwga2hpIHJlb3BlbiAoaGnhu4duIGzhuqFpIGLhurFuZyBDU1MsIGtow7RuZyBwaMOhdCBzaW5oIG11dGF0aW9uKSBuw6puIG9ic2VydmVyXG4gICAqIGtow7RuZyBrw61jaCBob+G6oXQsIHBo4bqjaSBjaOG7pyDEkeG7mW5nIGfhu41pIMSR4buDIHJlLWluamVjdCArIHJlc3luYyB0aGVvIGPhu5l0IGhp4buHbiB04bqhaS5cbiAgICovXG4gIHByaXZhdGUgcHJvY2Vzc051bWZtdFBhbmVsKCkge1xuICAgIHN5bmNBY3RpdmVOdW1mbXRIaWdobGlnaHQoKTtcbiAgICBjb25zdCByZXN1bHQgPSBpbmplY3RDdXN0b21EYXRlRm9ybWF0cyhcbiAgICAgICAgKCkgPT4gdGhpcy5sYXN0UmFuZ2VTbmFwc2hvdCxcbiAgICAgICAgLy8gQ09OVkVOVElPTi1FWENFUFQ6IGFueSDigJQgRlVuaXZlci5leGVjdXRlQ29tbWFuZCBraMO0bmcgZXhwb3NlIHR5cGluZ1xuICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxuICAgICAgICAoY21kSWQsIHBhcmFtcykgPT4gdm9pZCAodGhpcy51bml2ZXJBUEkgYXMgYW55KS5leGVjdXRlQ29tbWFuZD8uKGNtZElkLCBwYXJhbXMpLFxuICAgICAgICAocGF0dGVybikgPT4ge1xuICAgICAgICAgIHRoaXMucGVuZGluZ051bWZtdFBhdHRlcm4gPSBwYXR0ZXJuO1xuICAgICAgICB9LFxuICAgICAgICAoKSA9PiB7XG4gICAgICAgICAgY29uc3Qgc25hcCA9IHRoaXMubGFzdFJhbmdlU25hcHNob3Q7XG4gICAgICAgICAgaWYgKCFzbmFwKSByZXR1cm4gdGhpcy5hY3RpdmVDZWxsRm9ybWF0KCk7XG4gICAgICAgICAgLy8gUXXDqXQgdsOgaSBkw7JuZyDEkeG6p3UgY+G7p2EgdsO5bmcgY2jhu41uLCBi4buPIHF1YSBoZWFkZXIvR2VuZXJhbCDEkeG7gyBs4bqleSBmb3JtYXQgxJDhuqBJIERJ4buGTiBj4bunYSBk4buvIGxp4buHdS5cbiAgICAgICAgICAvLyBLaGkgY2jhu41uIGPhuqMgY+G7mXQsIHN0YXJ0Um93ID0gMCBsw6AgaGVhZGVyICh0aMaw4budbmcgR2VuZXJhbCkg4oaSIG7hur91IGNo4buJIMSR4buNYyBkw7JuZyDEkcOzIHPhur0gaGlnaGxpZ2h0IHNhaSBvcHRpb24uXG4gICAgICAgICAgY29uc3QgbWF4U2NhbiA9IE1hdGgubWluKHNuYXAuZW5kUm93LCBzbmFwLnN0YXJ0Um93ICsgNCk7XG4gICAgICAgICAgZm9yIChsZXQgciA9IHNuYXAuc3RhcnRSb3c7IHIgPD0gbWF4U2NhbjsgcisrKSB7XG4gICAgICAgICAgICBjb25zdCBmbXQgPSB0aGlzLnJlYWRDZWxsTnVtZm10KHNuYXAuc3ViVW5pdElkLCByLCBzbmFwLnN0YXJ0Q29sdW1uKTtcbiAgICAgICAgICAgIGlmIChmbXQgIT09ICdHZW5lcmFsJykgcmV0dXJuIGZtdDtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIHRoaXMuYWN0aXZlQ2VsbEZvcm1hdCgpO1xuICAgICAgICB9LFxuICAgICAgICAoKSA9PiB0aGlzLmNsZWFyTnVtZm10UHJldmlldygpLFxuICAgICAgICAoKSA9PiB7XG4gICAgICAgICAgLy8gR2nDoSB0cuG7iyB0aOG7sWMgY+G7p2Egw7QgxJHhuqFpIGRp4buHbiAoZMOybmcgZOG7ryBsaeG7h3UgxJHhuqd1IGPDsyBz4buRKSDihpIgbGFiZWwgb3B0aW9uIGto4bubcCBk4buvIGxp4buHdSBj4buZdC5cbiAgICAgICAgICBjb25zdCBzbmFwID0gdGhpcy5sYXN0UmFuZ2VTbmFwc2hvdDtcbiAgICAgICAgICBpZiAoIXNuYXApIHJldHVybiBudWxsO1xuICAgICAgICAgIGNvbnN0IG1heFNjYW4gPSBNYXRoLm1pbihzbmFwLmVuZFJvdywgc25hcC5zdGFydFJvdyArIDQpO1xuICAgICAgICAgIGZvciAobGV0IHIgPSBzbmFwLnN0YXJ0Um93OyByIDw9IG1heFNjYW47IHIrKykge1xuICAgICAgICAgICAgY29uc3QgdmFsdWUgPSB0aGlzLnJlYWRDZWxsVmFsdWUoc25hcC5zdWJVbml0SWQsIHIsIHNuYXAuc3RhcnRDb2x1bW4pO1xuICAgICAgICAgICAgaWYgKHZhbHVlICE9PSBudWxsKSByZXR1cm4gdmFsdWU7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9LFxuICAgICAgICAoKSA9PiB7XG4gICAgICAgICAgdGhpcy5udW1mbXRDb25maXJtZWQgPSB0cnVlO1xuICAgICAgICB9XG4gICAgICApO1xuICAgICAgLy8gcmVzdWx0IGNo4buJIHRydXRoeSBraGkgVEjhu7BDIFPhu7AgaW5qZWN0IHRyw6puIDEgbGlzdENvbnRhaW5lciBEYXRlIG3hu5tpIChndWFyZCBkYXRhLWN1c3RvbS1kYXRlcyBjaOG6t25cbiAgICAgIC8vIGPDoWMgbOG6p24gZ+G7jWkgdGjhu6thKS4gR+G7oSBsaXN0ZW5lciBj4bunYSBs4bqnbiBpbmplY3QgdHLGsOG7m2MgdHLGsOG7m2Mga2hpIGdp4buvIGNsZWFudXAgbeG7m2kg4oaSIHRyw6FuaCB0w61jaCB04bulLlxuICAgICAgLy8gxJDhu5NuZyB0aOG7nWkgbMawdSByZXN5bmMgxJHhu4MgcmUtdGFyZ2V0IHBhbmVsIGtoaSB1c2VyIMSR4buVaSBj4buZdCwgdsOgIMSRw6FuaCBk4bqldSBsdeG7k25nIERhdGUgxJFhbmcgaG/huqF0IMSR4buZbmcuXG4gICAgaWYgKHJlc3VsdCkge1xuICAgICAgdGhpcy5udW1mbXRDbGVhbnVwPy4oKTtcbiAgICAgIHRoaXMubnVtZm10Q2xlYW51cCA9IHJlc3VsdC5jbGVhbnVwO1xuICAgICAgdGhpcy5udW1mbXRSZXN5bmMgPSByZXN1bHQucmVzeW5jO1xuICAgICAgdGhpcy5udW1mbXREYXRlQWN0aXZlID0gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGluaXRVbml2ZXIoZGF0YTogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pIHtcbiAgICBjb25zdCB3cmFwcGVyID0gdGhpcy5jb250YWluZXJSZWYoKT8ubmF0aXZlRWxlbWVudCBhcyBIVE1MRWxlbWVudCB8IHVuZGVmaW5lZDtcbiAgICBpZiAoIXdyYXBwZXIpIHJldHVybjtcblxuICAgIHdyYXBwZXIucmVwbGFjZUNoaWxkcmVuKCk7XG4gICAgY29uc3QgY29udGFpbmVyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgY29udGFpbmVyLnN0eWxlLmNzc1RleHQgPSAnd2lkdGg6MTAwJTtoZWlnaHQ6MTAwJSc7XG4gICAgd3JhcHBlci5hcHBlbmRDaGlsZChjb250YWluZXIpO1xuXG4gICAgY29uc3QgdW5pdmVyID0gbmV3IFVuaXZlcih7XG4gICAgICBsb2NhbGU6IHRoaXMucmVzb2x2ZUxvY2FsZVR5cGUoKSxcbiAgICAgIGxvY2FsZXM6IHtcbiAgICAgICAgW0xvY2FsZVR5cGUuRU5fVVNdOiB1bml2ZXJMb2NhbGVFbixcbiAgICAgICAgW0xvY2FsZVR5cGUuVklfVk5dOiB1bml2ZXJMb2NhbGVWaSxcbiAgICAgIH0sXG4gICAgICB0aGVtZTogZGVmYXVsdFRoZW1lLFxuICAgIH0pO1xuICAgIHRoaXMudW5pdmVyID0gdW5pdmVyO1xuXG4gICAgdW5pdmVyLnJlZ2lzdGVyUGx1Z2luKFVuaXZlclJlbmRlckVuZ2luZVBsdWdpbik7XG4gICAgdW5pdmVyLnJlZ2lzdGVyUGx1Z2luKFVuaXZlckZvcm11bGFFbmdpbmVQbHVnaW4pO1xuICAgIHVuaXZlci5yZWdpc3RlclBsdWdpbihVbml2ZXJVSVBsdWdpbiwgeyBjb250YWluZXIsIGhlYWRlcjogdGhpcy5zaG93VG9vbGJhcigpLCBmb290ZXI6IHRoaXMuc2hvd1NoZWV0VGFicygpIH0pO1xuICAgIHVuaXZlci5yZWdpc3RlclBsdWdpbihVbml2ZXJEb2NzUGx1Z2luLCB7IGhhc1Njcm9sbDogZmFsc2UgfSk7XG4gICAgdW5pdmVyLnJlZ2lzdGVyUGx1Z2luKFVuaXZlckRvY3NVSVBsdWdpbik7XG4gICAgdW5pdmVyLnJlZ2lzdGVyUGx1Z2luKFVuaXZlclNoZWV0c1BsdWdpbik7XG4gICAgdW5pdmVyLnJlZ2lzdGVyUGx1Z2luKFVuaXZlclNoZWV0c1VJUGx1Z2luLCB7IG1lbnU6IHRoaXMudG9vbGJhck1lbnVDb25maWcoKSB9KTtcbiAgICB1bml2ZXIucmVnaXN0ZXJQbHVnaW4oVW5pdmVyU2hlZXRzTnVtZm10UGx1Z2luKTtcbiAgICB1bml2ZXIucmVnaXN0ZXJQbHVnaW4oVW5pdmVyU2hlZXRzRm9ybXVsYVBsdWdpbik7XG4gICAgdW5pdmVyLnJlZ2lzdGVyUGx1Z2luKFVuaXZlclNoZWV0c0Zvcm11bGFVSVBsdWdpbik7XG4gICAgdW5pdmVyLmNyZWF0ZVVuaXQoVW5pdmVySW5zdGFuY2VUeXBlLlVOSVZFUl9TSEVFVCwgZGF0YSk7XG5cbiAgICB0aGlzLnVuaXZlckFQSSA9IEZVbml2ZXIubmV3QVBJKHVuaXZlcik7XG4gICAgaWYgKHRoaXMucGVuZGluZ1JlYWR5Q2IpIHtcbiAgICAgIC8vIFdhaXQgZm9yIC5tb3JlLW51bWZtdC10eXBlIHRvIGFwcGVhciBpbiBET00g4oCUIHRoaXMgc2lnbmFscyB0aGF0IFVuaXZlclNoZWV0c1VJUGx1Z2luXG4gICAgICAvLyBoYXMgZnVsbHkgcmVuZGVyZWQgdGhlIHRvb2xiYXIgYW5kIFVuaXZlclNoZWV0c051bWZtdFBsdWdpbidzIElOdW1mbXRNb2RlbCBpcyByZWFkeS5cbiAgICAgIGNvbnN0IHdyYXBwZXIgPSB0aGlzLmNvbnRhaW5lclJlZigpPy5uYXRpdmVFbGVtZW50IGFzIEhUTUxFbGVtZW50IHwgdW5kZWZpbmVkO1xuICAgICAgaWYgKHdyYXBwZXIpIHtcbiAgICAgICAgdGhpcy5yZWFkeU9ic2VydmVyID0gbmV3IE11dGF0aW9uT2JzZXJ2ZXIoKCkgPT4ge1xuICAgICAgICAgIGlmICghd3JhcHBlci5xdWVyeVNlbGVjdG9yKCcubW9yZS1udW1mbXQtdHlwZScpKSByZXR1cm47XG4gICAgICAgICAgdGhpcy5yZWFkeU9ic2VydmVyPy5kaXNjb25uZWN0KCk7XG4gICAgICAgICAgdGhpcy5yZWFkeU9ic2VydmVyID0gbnVsbDtcbiAgICAgICAgICBjb25zdCBjYiA9IHRoaXMucGVuZGluZ1JlYWR5Q2I7XG4gICAgICAgICAgdGhpcy5wZW5kaW5nUmVhZHlDYiA9IG51bGw7XG4gICAgICAgICAgY2I/LigpO1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5yZWFkeU9ic2VydmVyLm9ic2VydmUod3JhcHBlciwgeyBjaGlsZExpc3Q6IHRydWUsIHN1YnRyZWU6IHRydWUgfSk7XG4gICAgICB9XG4gICAgfVxuICAgIHRoaXMucmVnaXN0ZXJDb2x1bW5DbGlja0xpc3RlbmVyKCk7XG4gICAgdGhpcy5yZWdpc3RlckNvbHVtbk9wTGlzdGVuZXIoKTtcbiAgICB0aGlzLnJlZ2lzdGVyRm9ybWF0TGlzdGVuZXIoKTtcbiAgICB0aGlzLnJlZ2lzdGVyTnVtZm10RHJvcGRvd25PYnNlcnZlcigpO1xuICAgIHRoaXMucmVnaXN0ZXJUb29sYmFyV2lkdGhTeW5jKCk7XG4gICAgdGhpcy5yZWdpc3Rlck51bWZtdENsaWNrSW50ZXJjZXB0b3IoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBLaOG6r2MgcGjhu6VjIGzhu5dpIHRvb2xiYXIgY29sbGFwc2Ugc2FpIChnb20gaXRlbSB2w6BvIG1lbnUg4ouuIGTDuSBjw7JuIGtob+G6o25nIHRy4bqvbmcpLlxuICAgKlxuICAgKiBVbml2ZXIgKGNvbXBvbmVudCBSaWJib24pIHF1eeG6v3QgxJHhu4tuaCBvdmVyZmxvdyBi4bqxbmcgMSBjb250YWluZXIgxJBPIG9mZi1zY3JlZW4gKGNvbiB0cuG7sWMgdGnhur9wIGPhu6dhXG4gICAqIGhlYWRlciwgcG9zaXRpb246YWJzb2x1dGUpLiBUaHXhuq10IHRvw6FuOiBgdG90YWwgPSA5MDsgY2hvIG3hu5dpIElURU0gdG90YWwgKz0gaXRlbS5jbGllbnRXaWR0aCArIDg7XG4gICAqIG7hur91IHRvdGFsID4gbWVhc3VyaW5nQ29udGFpbmVyLmNsaWVudFdpZHRoIOKGkiBjb2xsYXBzZSBpdGVtYC4gQ8O0bmcgdGjhu6ljIG7DoHkgT1ZFUi1DT1VOVCAyIGNo4buXOlxuICAgKiAgIOKAoiArOTBweCByZXNlcnZlIGNobyBuw7p0IOKLriAoY+G7mW5nIGvhu4MgY+G6oyBraGkga2jDtG5nIGPhuqduIGNvbGxhcHNlKS5cbiAgICogICDigKIgKzhweCBN4buWSSBpdGVtLCB0cm9uZyBraGkga2hv4bqjbmcgY8OhY2ggKGdhcCkgdGjhu7FjIHThur8gY2jhu4kgbuG6sW0gZ2nhu69hIGPDoWMgR1JPVVAuXG4gICAqIE7hur91IHNldCBi4buBIHLhu5luZyBjb250YWluZXIgxJFvID0gxJHDum5nIGhlYWRlclcgdGjDrCBgdG90YWxgICh2ZCA5NjEpID4gaGVhZGVyVyAodmQgOTAwKSDihpIgVW5pdmVyIHTGsOG7n25nXG4gICAqIHRyw6BuIHbDoCBnb20gaXRlbSB2w6BvIOKLriBkw7kgY29udGVudCB0aOG6rXQgY2jhu4kgfjgyOXB4IChjw7JuIH43MHB4IHRy4buRbmcpLlxuICAgKlxuICAgKiBGaXggKHRyaeG7h3QgxJHhu4MsIGtow7RuZyBwaOG7pSB0aHXhu5ljIHRpbWluZyk6IHBpbiBi4buBIHLhu5luZyBjb250YWluZXIgxJBPID0gSOG6sE5HIFPhu5AgcuG6pXQgbOG7m24gcXVhIENTUyBSVUxFIHRyb25nXG4gICAqIDEgPHN0eWxlPiByacOqbmcuIEtoaSDEkcOzIGB0b3RhbGAgY+G7p2EgVW5pdmVyIEtIw5RORyBCQU8gR0nhu5wgdsaw4bujdCDihpIgS0jDlE5HIGdvbSBpdGVtIHbDoG8g4ouuIOKGkiBsdcO0biBoaeG7g24gdGjhu4tcbiAgICogxJDhu6Ygb3B0aW9uICjEkcO6bmcgecOqdSBj4bqndSkuIFbDrCBzYW8gY2jhu41uIGPDoWNoIG7DoHkgdGhheSB2w6wga2jhu5twIHdpZHRoID0gaGVhZGVyVzpcbiAgICogICDigKIgVGh14bqtdCB0b8OhbiBVbml2ZXIgb3Zlci1jb3VudCAoOTAgcmVzZXJ2ZSDii64gKyA4cHgvaXRlbSkg4oaSIGto4bubcCBzw6F0IGhlYWRlclcgduG6q24gY29sbGFwc2Ugc2FpIGtoaSBjw7JuIGNo4buXLlxuICAgKiAgIOKAoiBSZXNpemVPYnNlcnZlciBj4bunYSBVbml2ZXIgaGF5IEvhurhUIFNUQUxFOiAxIHRyYW5zaWVudCBsw7pjIGxvYWQgKGljb24vZm9udCBsw6BtIGl0ZW0gcuG7mW5nIG5o4bqldCB0aOG7nWkpIMSR4bq3dFxuICAgKiAgICAgY29sbGFwc2VkSWRzIHLhu5NpIEtIw5RORyByZS1maXJlIOKGkiBr4bq5dCDii64gdsSpbmggdmnhu4VuIGTDuSBzYXUgxJHDsyBjw7JuIGNo4buXICjEkcO6bmcgdHJp4buHdSBjaOG7qW5nIHJlbG9hZCBsdcO0biDii64pLlxuICAgKiAgIOKAoiBTZXQgaW5saW5lIGzhuqFpIGLhu4sgUmVhY3QgcmUtcmVuZGVyIHN0cmlwIOKGkiBvc2NpbGxhdGlvbi4gQ1NTIHJ1bGUgIWltcG9ydGFudCBSZWFjdCBraMO0bmcgc3RyaXAgxJHGsOG7o2MuXG4gICAqIENvbnRhaW5lciDEkW8gduG7kW4gb2ZmLXNjcmVlbiAocG9zaXRpb246YWJzb2x1dGUsIG9wYWNpdHk6MCkgbsOqbiB3aWR0aCBraOG7lW5nIGzhu5MgaG/DoG4gdG/DoG4gdsO0IGjDrG5oLiBLaGlcbiAgICogdsO5bmcgY2jhu6lhIHF1w6EgaOG6uXAgKGhp4bq/bSB24bubaSBzcHJlYWRzaGVldCkgdG9vbGJhciBjdeG7mW4gbmdhbmcg4oCUIHhlbSBTQ1NTIGAudW5pdmVyLXRvb2xiYXJgIG92ZXJmbG93LXguXG4gICAqL1xuICBwcml2YXRlIHJlZ2lzdGVyVG9vbGJhcldpZHRoU3luYygpIHtcbiAgICBjb25zdCB3cmFwcGVyID0gdGhpcy5jb250YWluZXJSZWYoKT8ubmF0aXZlRWxlbWVudCBhcyBIVE1MRWxlbWVudCB8IHVuZGVmaW5lZDtcbiAgICBpZiAoIXdyYXBwZXIpIHJldHVybjtcbiAgICB3cmFwcGVyLmNsYXNzTGlzdC5hZGQodGhpcy50b29sYmFyU2NvcGVDbGFzcyk7XG4gICAgY29uc3Qgc3R5bGVFbCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3N0eWxlJyk7XG4gICAgdGhpcy50b29sYmFyU3R5bGVFbCA9IHN0eWxlRWw7XG4gICAgc3R5bGVFbC50ZXh0Q29udGVudCA9IGAuJHt0aGlzLnRvb2xiYXJTY29wZUNsYXNzfSAudW5pdmVyLXdvcmtiZW5jaC1jb250YWluZXItaGVhZGVyID4gLnVuaXZlci10b29sYmFyLWNvbnRhaW5lcnt3aWR0aDoxMDAwMDBweCAhaW1wb3J0YW50O21heC13aWR0aDpub25lICFpbXBvcnRhbnQ7fWA7XG4gICAgZG9jdW1lbnQuaGVhZC5hcHBlbmRDaGlsZChzdHlsZUVsKTtcbiAgfVxuXG4gIHByaXZhdGUgcmVnaXN0ZXJOdW1mbXRDbGlja0ludGVyY2VwdG9yKCkge1xuICAgIGNvbnN0IGNsaWNrSGFuZGxlciA9IChlOiBNb3VzZUV2ZW50KSA9PiB7XG4gICAgICBjb25zdCB0YXJnZXQgPSBlLnRhcmdldCBhcyBIVE1MRWxlbWVudDtcbiAgICAgIGlmICh0YXJnZXQuY2xvc2VzdCgnLm51bWZtdC1wYW5lbCcpID8/IHRhcmdldC5jbG9zZXN0KCcubW9yZS1udW1mbXQtdHlwZS1vcHRpb25zJykpIHJldHVybjtcblxuICAgICAgY29uc3QgbnVtZm10VGV4dCA9IHRhcmdldC5jbG9zZXN0KCcubW9yZS1udW1mbXQtdHlwZScpIGFzIEhUTUxFbGVtZW50IHwgbnVsbDtcbiAgICAgIGNvbnN0IG51bWZtdFNlbGVjdCA9IHRhcmdldC5jbG9zZXN0KCcudW5pdmVyLXRvb2xiYXItaXRlbS1zZWxlY3QnKSBhcyBIVE1MRWxlbWVudCB8IG51bGw7XG4gICAgICBjb25zdCBpc051bWZtdEJ0biA9IG51bWZtdFRleHQgPz8gKG51bWZtdFNlbGVjdD8ucXVlcnlTZWxlY3RvcignLm1vcmUtbnVtZm10LXR5cGUnKSA/IG51bWZtdFNlbGVjdCA6IG51bGwpO1xuXG4gICAgICBpZiAoIWlzTnVtZm10QnRuKSByZXR1cm47XG4gICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICBlLnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgdGhpcy5leGVjdXRlQ29tbWFuZCgnc2hlZXQub3BlcmF0aW9uLm9wZW4ubnVtZm10LnBhbmVsJywgdW5kZWZpbmVkKTtcbiAgICB9O1xuXG4gICAgZG9jdW1lbnQuYm9keS5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIGNsaWNrSGFuZGxlciwgdHJ1ZSk7XG4gICAgdGhpcy5udW1mbXRDbGlja0Rpc3Bvc2FibGUgPSB7IGRpc3Bvc2U6ICgpID0+IGRvY3VtZW50LmJvZHkucmVtb3ZlRXZlbnRMaXN0ZW5lcignY2xpY2snLCBjbGlja0hhbmRsZXIsIHRydWUpIH07XG4gIH1cblxuICBwcml2YXRlIGRlc3Ryb3lVbml2ZXIoKSB7XG4gICAgaWYgKHRoaXMucGVuZGluZ0luaXRUaW1lciAhPT0gbnVsbCkge1xuICAgICAgY2xlYXJUaW1lb3V0KHRoaXMucGVuZGluZ0luaXRUaW1lcik7XG4gICAgICB0aGlzLnBlbmRpbmdJbml0VGltZXIgPSBudWxsO1xuICAgIH1cbiAgICB0aGlzLmNvbHVtbkNsaWNrRGlzcG9zYWJsZT8uZGlzcG9zZSgpO1xuICAgIHRoaXMuY29sdW1uQ2xpY2tEaXNwb3NhYmxlID0gbnVsbDtcbiAgICB0aGlzLmNvbHVtbk9wRGlzcG9zYWJsZT8uZGlzcG9zZSgpO1xuICAgIHRoaXMuY29sdW1uT3BEaXNwb3NhYmxlID0gbnVsbDtcbiAgICB0aGlzLmZvcm1hdERpc3Bvc2FibGU/LmRpc3Bvc2UoKTtcbiAgICB0aGlzLmZvcm1hdERpc3Bvc2FibGUgPSBudWxsO1xuICAgIHRoaXMubnVtZm10T2JzZXJ2ZXI/LmRpc2Nvbm5lY3QoKTtcbiAgICB0aGlzLm51bWZtdE9ic2VydmVyID0gbnVsbDtcbiAgICB0aGlzLnRvb2xiYXJSZXNpemVPYnNlcnZlcj8uZGlzY29ubmVjdCgpO1xuICAgIHRoaXMudG9vbGJhclJlc2l6ZU9ic2VydmVyID0gbnVsbDtcbiAgICB0aGlzLnRvb2xiYXJTdHlsZUVsPy5yZW1vdmUoKTtcbiAgICB0aGlzLnRvb2xiYXJTdHlsZUVsID0gbnVsbDtcbiAgICB0aGlzLm51bWZtdENsaWNrRGlzcG9zYWJsZT8uZGlzcG9zZSgpO1xuICAgIHRoaXMubnVtZm10Q2xpY2tEaXNwb3NhYmxlID0gbnVsbDtcbiAgICB0aGlzLm51bWZtdENsZWFudXA/LigpO1xuICAgIHRoaXMubnVtZm10Q2xlYW51cCA9IG51bGw7XG4gICAgdGhpcy5udW1mbXRSZXN5bmMgPSBudWxsO1xuICAgIHRoaXMubnVtZm10RGF0ZUFjdGl2ZSA9IGZhbHNlO1xuICAgIHRoaXMucmVhZHlPYnNlcnZlcj8uZGlzY29ubmVjdCgpO1xuICAgIHRoaXMucmVhZHlPYnNlcnZlciA9IG51bGw7XG4gICAgdGhpcy5hY3RpdmVDZWxsRm9ybWF0LnNldCgnR2VuZXJhbCcpO1xuICAgIHRoaXMuYWN0aXZlQ2VsbFJlZi5zZXQoJycpO1xuICAgIHRoaXMubGFzdFJhbmdlU25hcHNob3QgPSBudWxsO1xuICAgIHRoaXMucGVuZGluZ051bWZtdFBhdHRlcm4gPSBudWxsO1xuICAgIHRoaXMubnVtZm10Q29uZmlybWVkID0gZmFsc2U7XG4gICAgdGhpcy5vcmlnaW5hbENlbGxGb3JtYXRzID0gbnVsbDtcbiAgICB0aGlzLm51bWZtdFBhbmVsT3BlbiA9IGZhbHNlO1xuICAgIHRoaXMubGlzdGVuRW5hYmxlZCA9IGZhbHNlO1xuICAgIGlmICh0aGlzLmxpc3RlbkVuYWJsZVRpbWVyICE9PSBudWxsKSB7XG4gICAgICBjbGVhclRpbWVvdXQodGhpcy5saXN0ZW5FbmFibGVUaW1lcik7XG4gICAgICB0aGlzLmxpc3RlbkVuYWJsZVRpbWVyID0gbnVsbDtcbiAgICB9XG4gICAgdGhpcy5udW1mbXRDb250cm9sbGVyID0gbnVsbDtcbiAgICB0aGlzLnVuaXZlcj8uZGlzcG9zZSgpO1xuICAgIHRoaXMudW5pdmVyID0gbnVsbDtcbiAgICB0aGlzLnVuaXZlckFQSSA9IG51bGw7XG4gIH1cblxuICBwcml2YXRlIHJlaW5pdFVuaXZlcigpIHtcbiAgICBjb25zdCBjdXJyZW50RGF0YSA9IHRoaXMudW5pdmVyQVBJPy5nZXRBY3RpdmVXb3JrYm9vaygpPy5zYXZlKCkgYXMgdW5rbm93biBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiB8IHVuZGVmaW5lZDtcbiAgICB0aGlzLmRlc3Ryb3lVbml2ZXIoKTtcbiAgICBzZXRUaW1lb3V0KCgpID0+IHRoaXMuaW5pdFVuaXZlcihjdXJyZW50RGF0YSA/PyB0aGlzLmJ1aWxkRW1wdHlXb3JrYm9vaygpKSk7XG4gIH1cblxuICBuZ09uRGVzdHJveSgpIHtcbiAgICB0aGlzLmRlc3Ryb3lVbml2ZXIoKTtcbiAgfVxufVxuIiwiPGRpdiAjY29udGFpbmVyUmVmIGNsYXNzPVwibGlicy11aS1jb21wb25lbnRzLXNwcmVhZHNoZWV0LWNvbnRhaW5lclwiPjwvZGl2PlxuIl19