@swimlane/ngx-datatable 19.0.0 → 20.0.0-alpha-1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -1
- package/esm2020/lib/components/body/body-cell.component.mjs +432 -0
- package/esm2020/lib/components/body/body-group-header-template.directive.mjs +16 -0
- package/esm2020/lib/components/body/body-group-header.directive.mjs +62 -0
- package/esm2020/lib/components/body/body-row-wrapper.component.mjs +140 -0
- package/esm2020/lib/components/body/body-row.component.mjs +262 -0
- package/esm2020/lib/components/body/body.component.mjs +863 -0
- package/esm2020/lib/components/body/progress-bar.component.mjs +27 -0
- package/esm2020/lib/components/body/scroller.component.mjs +91 -0
- package/esm2020/lib/components/body/selection.component.mjs +150 -0
- package/esm2020/lib/components/body/summary/summary-row.component.mjs +105 -0
- package/esm2020/lib/components/columns/column-cell.directive.mjs +14 -0
- package/esm2020/lib/components/columns/column-header.directive.mjs +14 -0
- package/esm2020/lib/components/columns/column.directive.mjs +98 -0
- package/esm2020/lib/components/columns/tree.directive.mjs +14 -0
- package/esm2020/lib/components/datatable.component.mjs +1008 -0
- package/esm2020/lib/components/footer/footer-template.directive.mjs +14 -0
- package/esm2020/lib/components/footer/footer.component.mjs +128 -0
- package/esm2020/lib/components/footer/footer.directive.mjs +35 -0
- package/esm2020/lib/components/footer/pager.component.mjs +181 -0
- package/esm2020/lib/components/header/header-cell.component.mjs +243 -0
- package/esm2020/lib/components/header/header.component.mjs +376 -0
- package/esm2020/lib/components/row-detail/row-detail-template.directive.mjs +16 -0
- package/esm2020/lib/components/row-detail/row-detail.directive.mjs +63 -0
- package/esm2020/lib/directives/draggable.directive.mjs +108 -0
- package/esm2020/lib/directives/long-press.directive.mjs +117 -0
- package/esm2020/lib/directives/orderable.directive.mjs +136 -0
- package/esm2020/lib/directives/resizeable.directive.mjs +93 -0
- package/esm2020/lib/directives/visibility.directive.mjs +63 -0
- package/esm2020/lib/events.mjs +7 -0
- package/esm2020/lib/ngx-datatable.module.mjs +139 -0
- package/esm2020/lib/services/column-changes.service.mjs +24 -0
- package/esm2020/lib/services/dimensions-helper.service.mjs +17 -0
- package/esm2020/lib/services/scrollbar-helper.service.mjs +37 -0
- package/esm2020/lib/types/click.type.mjs +6 -0
- package/esm2020/lib/types/column-mode.type.mjs +7 -0
- package/esm2020/lib/types/contextmenu.type.mjs +6 -0
- package/esm2020/lib/types/selection.type.mjs +9 -0
- package/esm2020/lib/types/sort-direction.type.mjs +6 -0
- package/esm2020/lib/types/sort-prop-dir.type.mjs +2 -0
- package/esm2020/lib/types/sort.type.mjs +6 -0
- package/esm2020/lib/types/table-column.type.mjs +2 -0
- package/esm2020/lib/utils/camel-case.mjs +28 -0
- package/esm2020/lib/utils/column-helper.mjs +95 -0
- package/esm2020/lib/utils/column-prop-getters.mjs +96 -0
- package/esm2020/lib/utils/column.mjs +69 -0
- package/esm2020/lib/utils/elm-from-point.mjs +38 -0
- package/esm2020/lib/utils/id.mjs +8 -0
- package/esm2020/lib/utils/keys.mjs +10 -0
- package/esm2020/lib/utils/math.mjs +146 -0
- package/esm2020/lib/utils/prefixes.mjs +38 -0
- package/esm2020/lib/utils/row-height-cache.mjs +138 -0
- package/esm2020/lib/utils/selection.mjs +40 -0
- package/esm2020/lib/utils/sort.mjs +127 -0
- package/esm2020/lib/utils/throttle.mjs +60 -0
- package/esm2020/lib/utils/translate.mjs +25 -0
- package/esm2020/lib/utils/tree.mjs +103 -0
- package/{esm2015/public-api.js → esm2020/public-api.mjs} +1 -1
- package/{esm2015/swimlane-ngx-datatable.js → esm2020/swimlane-ngx-datatable.mjs} +1 -1
- package/fesm2015/{swimlane-ngx-datatable.js → swimlane-ngx-datatable.mjs} +4104 -3337
- package/fesm2015/swimlane-ngx-datatable.mjs.map +1 -0
- package/fesm2020/swimlane-ngx-datatable.mjs +5974 -0
- package/fesm2020/swimlane-ngx-datatable.mjs.map +1 -0
- package/lib/components/body/body-cell.component.d.ts +3 -0
- package/lib/components/body/body-group-header-template.directive.d.ts +3 -0
- package/lib/components/body/body-group-header.directive.d.ts +3 -0
- package/lib/components/body/body-row-wrapper.component.d.ts +3 -0
- package/lib/components/body/body-row.component.d.ts +3 -0
- package/lib/components/body/body.component.d.ts +3 -0
- package/lib/components/body/progress-bar.component.d.ts +3 -0
- package/lib/components/body/scroller.component.d.ts +3 -0
- package/lib/components/body/selection.component.d.ts +3 -0
- package/lib/components/body/summary/summary-row.component.d.ts +3 -0
- package/lib/components/columns/column-cell.directive.d.ts +3 -0
- package/lib/components/columns/column-header.directive.d.ts +3 -0
- package/lib/components/columns/column.directive.d.ts +3 -0
- package/lib/components/columns/tree.directive.d.ts +3 -0
- package/lib/components/datatable.component.d.ts +3 -0
- package/lib/components/footer/footer-template.directive.d.ts +3 -0
- package/lib/components/footer/footer.component.d.ts +3 -0
- package/lib/components/footer/footer.directive.d.ts +3 -0
- package/lib/components/footer/pager.component.d.ts +3 -0
- package/lib/components/header/header-cell.component.d.ts +3 -0
- package/lib/components/header/header.component.d.ts +3 -0
- package/lib/components/row-detail/row-detail-template.directive.d.ts +3 -0
- package/lib/components/row-detail/row-detail.directive.d.ts +3 -0
- package/lib/directives/draggable.directive.d.ts +3 -0
- package/lib/directives/long-press.directive.d.ts +3 -0
- package/lib/directives/orderable.directive.d.ts +3 -0
- package/lib/directives/resizeable.directive.d.ts +3 -0
- package/lib/directives/visibility.directive.d.ts +3 -0
- package/lib/ngx-datatable.module.d.ts +33 -0
- package/lib/services/column-changes.service.d.ts +3 -0
- package/lib/services/dimensions-helper.service.d.ts +3 -0
- package/lib/services/scrollbar-helper.service.d.ts +3 -0
- package/package.json +24 -12
- package/swimlane-ngx-datatable.d.ts +1 -0
- package/bundles/swimlane-ngx-datatable.umd.js +0 -5876
- package/bundles/swimlane-ngx-datatable.umd.js.map +0 -1
- package/bundles/swimlane-ngx-datatable.umd.min.js +0 -2
- package/bundles/swimlane-ngx-datatable.umd.min.js.map +0 -1
- package/esm2015/lib/components/body/body-cell.component.js +0 -361
- package/esm2015/lib/components/body/body-group-header-template.directive.js +0 -15
- package/esm2015/lib/components/body/body-group-header.directive.js +0 -54
- package/esm2015/lib/components/body/body-row-wrapper.component.js +0 -106
- package/esm2015/lib/components/body/body-row.component.js +0 -212
- package/esm2015/lib/components/body/body.component.js +0 -713
- package/esm2015/lib/components/body/progress-bar.component.js +0 -17
- package/esm2015/lib/components/body/scroller.component.js +0 -83
- package/esm2015/lib/components/body/selection.component.js +0 -140
- package/esm2015/lib/components/body/summary/summary-row.component.js +0 -81
- package/esm2015/lib/components/columns/column-cell.directive.js +0 -13
- package/esm2015/lib/components/columns/column-header.directive.js +0 -13
- package/esm2015/lib/components/columns/column.directive.js +0 -65
- package/esm2015/lib/components/columns/tree.directive.js +0 -13
- package/esm2015/lib/components/datatable.component.js +0 -925
- package/esm2015/lib/components/footer/footer-template.directive.js +0 -13
- package/esm2015/lib/components/footer/footer.component.js +0 -75
- package/esm2015/lib/components/footer/footer.directive.js +0 -22
- package/esm2015/lib/components/footer/pager.component.js +0 -136
- package/esm2015/lib/components/header/header-cell.component.js +0 -191
- package/esm2015/lib/components/header/header.component.js +0 -295
- package/esm2015/lib/components/row-detail/row-detail-template.directive.js +0 -15
- package/esm2015/lib/components/row-detail/row-detail.directive.js +0 -55
- package/esm2015/lib/directives/draggable.directive.js +0 -102
- package/esm2015/lib/directives/long-press.directive.js +0 -103
- package/esm2015/lib/directives/orderable.directive.js +0 -131
- package/esm2015/lib/directives/resizeable.directive.js +0 -89
- package/esm2015/lib/directives/visibility.directive.js +0 -62
- package/esm2015/lib/events.js +0 -7
- package/esm2015/lib/ngx-datatable.module.js +0 -96
- package/esm2015/lib/services/column-changes.service.js +0 -21
- package/esm2015/lib/services/dimensions-helper.service.js +0 -14
- package/esm2015/lib/services/scrollbar-helper.service.js +0 -34
- package/esm2015/lib/types/click.type.js +0 -6
- package/esm2015/lib/types/column-mode.type.js +0 -7
- package/esm2015/lib/types/contextmenu.type.js +0 -6
- package/esm2015/lib/types/selection.type.js +0 -9
- package/esm2015/lib/types/sort-direction.type.js +0 -6
- package/esm2015/lib/types/sort-prop-dir.type.js +0 -2
- package/esm2015/lib/types/sort.type.js +0 -6
- package/esm2015/lib/types/table-column.type.js +0 -2
- package/esm2015/lib/utils/camel-case.js +0 -28
- package/esm2015/lib/utils/column-helper.js +0 -95
- package/esm2015/lib/utils/column-prop-getters.js +0 -96
- package/esm2015/lib/utils/column.js +0 -69
- package/esm2015/lib/utils/elm-from-point.js +0 -38
- package/esm2015/lib/utils/id.js +0 -8
- package/esm2015/lib/utils/keys.js +0 -10
- package/esm2015/lib/utils/math.js +0 -146
- package/esm2015/lib/utils/prefixes.js +0 -40
- package/esm2015/lib/utils/row-height-cache.js +0 -138
- package/esm2015/lib/utils/selection.js +0 -40
- package/esm2015/lib/utils/sort.js +0 -127
- package/esm2015/lib/utils/throttle.js +0 -60
- package/esm2015/lib/utils/translate.js +0 -25
- package/esm2015/lib/utils/tree.js +0 -103
- package/fesm2015/swimlane-ngx-datatable.js.map +0 -1
- package/swimlane-ngx-datatable.metadata.json +0 -1
|
@@ -1,713 +0,0 @@
|
|
|
1
|
-
import { Component, Output, EventEmitter, Input, HostBinding, ChangeDetectorRef, ViewChild, ChangeDetectionStrategy } from '@angular/core';
|
|
2
|
-
import { ScrollerComponent } from './scroller.component';
|
|
3
|
-
import { columnsByPin, columnGroupWidths } from '../../utils/column';
|
|
4
|
-
import { RowHeightCache } from '../../utils/row-height-cache';
|
|
5
|
-
import { translateXY } from '../../utils/translate';
|
|
6
|
-
export class DataTableBodyComponent {
|
|
7
|
-
/**
|
|
8
|
-
* Creates an instance of DataTableBodyComponent.
|
|
9
|
-
*/
|
|
10
|
-
constructor(cd) {
|
|
11
|
-
this.cd = cd;
|
|
12
|
-
this.selected = [];
|
|
13
|
-
this.scroll = new EventEmitter();
|
|
14
|
-
this.page = new EventEmitter();
|
|
15
|
-
this.activate = new EventEmitter();
|
|
16
|
-
this.select = new EventEmitter();
|
|
17
|
-
this.detailToggle = new EventEmitter();
|
|
18
|
-
this.rowContextmenu = new EventEmitter(false);
|
|
19
|
-
this.treeAction = new EventEmitter();
|
|
20
|
-
this.rowHeightsCache = new RowHeightCache();
|
|
21
|
-
this.temp = [];
|
|
22
|
-
this.offsetY = 0;
|
|
23
|
-
this.indexes = {};
|
|
24
|
-
this.rowIndexes = new WeakMap();
|
|
25
|
-
this.rowExpansions = [];
|
|
26
|
-
/**
|
|
27
|
-
* Get the height of the detail row.
|
|
28
|
-
*/
|
|
29
|
-
this.getDetailRowHeight = (row, index) => {
|
|
30
|
-
if (!this.rowDetail) {
|
|
31
|
-
return 0;
|
|
32
|
-
}
|
|
33
|
-
const rowHeight = this.rowDetail.rowHeight;
|
|
34
|
-
return typeof rowHeight === 'function' ? rowHeight(row, index) : rowHeight;
|
|
35
|
-
};
|
|
36
|
-
// declare fn here so we can get access to the `this` property
|
|
37
|
-
this.rowTrackingFn = (index, row) => {
|
|
38
|
-
const idx = this.getRowIndex(row);
|
|
39
|
-
if (this.trackByProp) {
|
|
40
|
-
return row[this.trackByProp];
|
|
41
|
-
}
|
|
42
|
-
else {
|
|
43
|
-
return idx;
|
|
44
|
-
}
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
set pageSize(val) {
|
|
48
|
-
this._pageSize = val;
|
|
49
|
-
this.recalcLayout();
|
|
50
|
-
}
|
|
51
|
-
get pageSize() {
|
|
52
|
-
return this._pageSize;
|
|
53
|
-
}
|
|
54
|
-
set rows(val) {
|
|
55
|
-
this._rows = val;
|
|
56
|
-
this.recalcLayout();
|
|
57
|
-
}
|
|
58
|
-
get rows() {
|
|
59
|
-
return this._rows;
|
|
60
|
-
}
|
|
61
|
-
set columns(val) {
|
|
62
|
-
this._columns = val;
|
|
63
|
-
const colsByPin = columnsByPin(val);
|
|
64
|
-
this.columnGroupWidths = columnGroupWidths(colsByPin, val);
|
|
65
|
-
}
|
|
66
|
-
get columns() {
|
|
67
|
-
return this._columns;
|
|
68
|
-
}
|
|
69
|
-
set offset(val) {
|
|
70
|
-
this._offset = val;
|
|
71
|
-
if (!this.scrollbarV || (this.scrollbarV && !this.virtualization))
|
|
72
|
-
this.recalcLayout();
|
|
73
|
-
}
|
|
74
|
-
get offset() {
|
|
75
|
-
return this._offset;
|
|
76
|
-
}
|
|
77
|
-
set rowCount(val) {
|
|
78
|
-
this._rowCount = val;
|
|
79
|
-
this.recalcLayout();
|
|
80
|
-
}
|
|
81
|
-
get rowCount() {
|
|
82
|
-
return this._rowCount;
|
|
83
|
-
}
|
|
84
|
-
get bodyWidth() {
|
|
85
|
-
if (this.scrollbarH) {
|
|
86
|
-
return this.innerWidth + 'px';
|
|
87
|
-
}
|
|
88
|
-
else {
|
|
89
|
-
return '100%';
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
set bodyHeight(val) {
|
|
93
|
-
if (this.scrollbarV) {
|
|
94
|
-
this._bodyHeight = val + 'px';
|
|
95
|
-
}
|
|
96
|
-
else {
|
|
97
|
-
this._bodyHeight = 'auto';
|
|
98
|
-
}
|
|
99
|
-
this.recalcLayout();
|
|
100
|
-
}
|
|
101
|
-
get bodyHeight() {
|
|
102
|
-
return this._bodyHeight;
|
|
103
|
-
}
|
|
104
|
-
/**
|
|
105
|
-
* Returns if selection is enabled.
|
|
106
|
-
*/
|
|
107
|
-
get selectEnabled() {
|
|
108
|
-
return !!this.selectionType;
|
|
109
|
-
}
|
|
110
|
-
/**
|
|
111
|
-
* Property that would calculate the height of scroll bar
|
|
112
|
-
* based on the row heights cache for virtual scroll and virtualization. Other scenarios
|
|
113
|
-
* calculate scroll height automatically (as height will be undefined).
|
|
114
|
-
*/
|
|
115
|
-
get scrollHeight() {
|
|
116
|
-
if (this.scrollbarV && this.virtualization && this.rowCount) {
|
|
117
|
-
return this.rowHeightsCache.query(this.rowCount - 1);
|
|
118
|
-
}
|
|
119
|
-
// avoid TS7030: Not all code paths return a value.
|
|
120
|
-
return undefined;
|
|
121
|
-
}
|
|
122
|
-
/**
|
|
123
|
-
* Called after the constructor, initializing input properties
|
|
124
|
-
*/
|
|
125
|
-
ngOnInit() {
|
|
126
|
-
if (this.rowDetail) {
|
|
127
|
-
this.listener = this.rowDetail.toggle.subscribe(({ type, value }) => {
|
|
128
|
-
if (type === 'row') {
|
|
129
|
-
this.toggleRowExpansion(value);
|
|
130
|
-
}
|
|
131
|
-
if (type === 'all') {
|
|
132
|
-
this.toggleAllRows(value);
|
|
133
|
-
}
|
|
134
|
-
// Refresh rows after toggle
|
|
135
|
-
// Fixes #883
|
|
136
|
-
this.updateIndexes();
|
|
137
|
-
this.updateRows();
|
|
138
|
-
this.cd.markForCheck();
|
|
139
|
-
});
|
|
140
|
-
}
|
|
141
|
-
if (this.groupHeader) {
|
|
142
|
-
this.listener = this.groupHeader.toggle.subscribe(({ type, value }) => {
|
|
143
|
-
if (type === 'group') {
|
|
144
|
-
this.toggleRowExpansion(value);
|
|
145
|
-
}
|
|
146
|
-
if (type === 'all') {
|
|
147
|
-
this.toggleAllRows(value);
|
|
148
|
-
}
|
|
149
|
-
// Refresh rows after toggle
|
|
150
|
-
// Fixes #883
|
|
151
|
-
this.updateIndexes();
|
|
152
|
-
this.updateRows();
|
|
153
|
-
this.cd.markForCheck();
|
|
154
|
-
});
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
/**
|
|
158
|
-
* Called once, before the instance is destroyed.
|
|
159
|
-
*/
|
|
160
|
-
ngOnDestroy() {
|
|
161
|
-
if (this.rowDetail || this.groupHeader) {
|
|
162
|
-
this.listener.unsubscribe();
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
/**
|
|
166
|
-
* Updates the Y offset given a new offset.
|
|
167
|
-
*/
|
|
168
|
-
updateOffsetY(offset) {
|
|
169
|
-
// scroller is missing on empty table
|
|
170
|
-
if (!this.scroller) {
|
|
171
|
-
return;
|
|
172
|
-
}
|
|
173
|
-
if (this.scrollbarV && this.virtualization && offset) {
|
|
174
|
-
// First get the row Index that we need to move to.
|
|
175
|
-
const rowIndex = this.pageSize * offset;
|
|
176
|
-
offset = this.rowHeightsCache.query(rowIndex - 1);
|
|
177
|
-
}
|
|
178
|
-
else if (this.scrollbarV && !this.virtualization) {
|
|
179
|
-
offset = 0;
|
|
180
|
-
}
|
|
181
|
-
this.scroller.setOffset(offset || 0);
|
|
182
|
-
}
|
|
183
|
-
/**
|
|
184
|
-
* Body was scrolled, this is mainly useful for
|
|
185
|
-
* when a user is server-side pagination via virtual scroll.
|
|
186
|
-
*/
|
|
187
|
-
onBodyScroll(event) {
|
|
188
|
-
const scrollYPos = event.scrollYPos;
|
|
189
|
-
const scrollXPos = event.scrollXPos;
|
|
190
|
-
// if scroll change, trigger update
|
|
191
|
-
// this is mainly used for header cell positions
|
|
192
|
-
if (this.offsetY !== scrollYPos || this.offsetX !== scrollXPos) {
|
|
193
|
-
this.scroll.emit({
|
|
194
|
-
offsetY: scrollYPos,
|
|
195
|
-
offsetX: scrollXPos
|
|
196
|
-
});
|
|
197
|
-
}
|
|
198
|
-
this.offsetY = scrollYPos;
|
|
199
|
-
this.offsetX = scrollXPos;
|
|
200
|
-
this.updateIndexes();
|
|
201
|
-
this.updatePage(event.direction);
|
|
202
|
-
this.updateRows();
|
|
203
|
-
}
|
|
204
|
-
/**
|
|
205
|
-
* Updates the page given a direction.
|
|
206
|
-
*/
|
|
207
|
-
updatePage(direction) {
|
|
208
|
-
let offset = this.indexes.first / this.pageSize;
|
|
209
|
-
if (direction === 'up') {
|
|
210
|
-
offset = Math.ceil(offset);
|
|
211
|
-
}
|
|
212
|
-
else if (direction === 'down') {
|
|
213
|
-
offset = Math.floor(offset);
|
|
214
|
-
}
|
|
215
|
-
if (direction !== undefined && !isNaN(offset)) {
|
|
216
|
-
this.page.emit({ offset });
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
/**
|
|
220
|
-
* Updates the rows in the view port
|
|
221
|
-
*/
|
|
222
|
-
updateRows() {
|
|
223
|
-
const { first, last } = this.indexes;
|
|
224
|
-
let rowIndex = first;
|
|
225
|
-
let idx = 0;
|
|
226
|
-
const temp = [];
|
|
227
|
-
// if grouprowsby has been specified treat row paging
|
|
228
|
-
// parameters as group paging parameters ie if limit 10 has been
|
|
229
|
-
// specified treat it as 10 groups rather than 10 rows
|
|
230
|
-
if (this.groupedRows) {
|
|
231
|
-
let maxRowsPerGroup = 3;
|
|
232
|
-
// if there is only one group set the maximum number of
|
|
233
|
-
// rows per group the same as the total number of rows
|
|
234
|
-
if (this.groupedRows.length === 1) {
|
|
235
|
-
maxRowsPerGroup = this.groupedRows[0].value.length;
|
|
236
|
-
}
|
|
237
|
-
while (rowIndex < last && rowIndex < this.groupedRows.length) {
|
|
238
|
-
// Add the groups into this page
|
|
239
|
-
const group = this.groupedRows[rowIndex];
|
|
240
|
-
this.rowIndexes.set(group, rowIndex);
|
|
241
|
-
if (group.value) {
|
|
242
|
-
// add indexes for each group item
|
|
243
|
-
group.value.forEach((g, i) => {
|
|
244
|
-
const _idx = `${rowIndex}-${i}`;
|
|
245
|
-
this.rowIndexes.set(g, _idx);
|
|
246
|
-
});
|
|
247
|
-
}
|
|
248
|
-
temp[idx] = group;
|
|
249
|
-
idx++;
|
|
250
|
-
// Group index in this context
|
|
251
|
-
rowIndex++;
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
else {
|
|
255
|
-
while (rowIndex < last && rowIndex < this.rowCount) {
|
|
256
|
-
const row = this.rows[rowIndex];
|
|
257
|
-
if (row) {
|
|
258
|
-
// add indexes for each row
|
|
259
|
-
this.rowIndexes.set(row, rowIndex);
|
|
260
|
-
temp[idx] = row;
|
|
261
|
-
}
|
|
262
|
-
idx++;
|
|
263
|
-
rowIndex++;
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
this.temp = temp;
|
|
267
|
-
}
|
|
268
|
-
/**
|
|
269
|
-
* Get the row height
|
|
270
|
-
*/
|
|
271
|
-
getRowHeight(row) {
|
|
272
|
-
// if its a function return it
|
|
273
|
-
if (typeof this.rowHeight === 'function') {
|
|
274
|
-
return this.rowHeight(row);
|
|
275
|
-
}
|
|
276
|
-
return this.rowHeight;
|
|
277
|
-
}
|
|
278
|
-
/**
|
|
279
|
-
* @param group the group with all rows
|
|
280
|
-
*/
|
|
281
|
-
getGroupHeight(group) {
|
|
282
|
-
let rowHeight = 0;
|
|
283
|
-
if (group.value) {
|
|
284
|
-
for (let index = 0; index < group.value.length; index++) {
|
|
285
|
-
rowHeight += this.getRowAndDetailHeight(group.value[index]);
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
return rowHeight;
|
|
289
|
-
}
|
|
290
|
-
/**
|
|
291
|
-
* Calculate row height based on the expanded state of the row.
|
|
292
|
-
*/
|
|
293
|
-
getRowAndDetailHeight(row) {
|
|
294
|
-
let rowHeight = this.getRowHeight(row);
|
|
295
|
-
const expanded = this.getRowExpanded(row);
|
|
296
|
-
// Adding detail row height if its expanded.
|
|
297
|
-
if (expanded) {
|
|
298
|
-
rowHeight += this.getDetailRowHeight(row);
|
|
299
|
-
}
|
|
300
|
-
return rowHeight;
|
|
301
|
-
}
|
|
302
|
-
/**
|
|
303
|
-
* Calculates the styles for the row so that the rows can be moved in 2D space
|
|
304
|
-
* during virtual scroll inside the DOM. In the below case the Y position is
|
|
305
|
-
* manipulated. As an example, if the height of row 0 is 30 px and row 1 is
|
|
306
|
-
* 100 px then following styles are generated:
|
|
307
|
-
*
|
|
308
|
-
* transform: translate3d(0px, 0px, 0px); -> row0
|
|
309
|
-
* transform: translate3d(0px, 30px, 0px); -> row1
|
|
310
|
-
* transform: translate3d(0px, 130px, 0px); -> row2
|
|
311
|
-
*
|
|
312
|
-
* Row heights have to be calculated based on the row heights cache as we wont
|
|
313
|
-
* be able to determine which row is of what height before hand. In the above
|
|
314
|
-
* case the positionY of the translate3d for row2 would be the sum of all the
|
|
315
|
-
* heights of the rows before it (i.e. row0 and row1).
|
|
316
|
-
*
|
|
317
|
-
* @param rows the row that needs to be placed in the 2D space.
|
|
318
|
-
* @returns the CSS3 style to be applied
|
|
319
|
-
*
|
|
320
|
-
* @memberOf DataTableBodyComponent
|
|
321
|
-
*/
|
|
322
|
-
getRowsStyles(rows) {
|
|
323
|
-
const styles = {};
|
|
324
|
-
// only add styles for the group if there is a group
|
|
325
|
-
if (this.groupedRows) {
|
|
326
|
-
styles.width = this.columnGroupWidths.total;
|
|
327
|
-
}
|
|
328
|
-
if (this.scrollbarV && this.virtualization) {
|
|
329
|
-
let idx = 0;
|
|
330
|
-
if (this.groupedRows) {
|
|
331
|
-
// Get the latest row rowindex in a group
|
|
332
|
-
const row = rows[rows.length - 1];
|
|
333
|
-
idx = row ? this.getRowIndex(row) : 0;
|
|
334
|
-
}
|
|
335
|
-
else {
|
|
336
|
-
idx = this.getRowIndex(rows);
|
|
337
|
-
}
|
|
338
|
-
// const pos = idx * rowHeight;
|
|
339
|
-
// The position of this row would be the sum of all row heights
|
|
340
|
-
// until the previous row position.
|
|
341
|
-
const pos = this.rowHeightsCache.query(idx - 1);
|
|
342
|
-
translateXY(styles, 0, pos);
|
|
343
|
-
}
|
|
344
|
-
return styles;
|
|
345
|
-
}
|
|
346
|
-
/**
|
|
347
|
-
* Calculate bottom summary row offset for scrollbar mode.
|
|
348
|
-
* For more information about cache and offset calculation
|
|
349
|
-
* see description for `getRowsStyles` method
|
|
350
|
-
*
|
|
351
|
-
* @returns the CSS3 style to be applied
|
|
352
|
-
*
|
|
353
|
-
* @memberOf DataTableBodyComponent
|
|
354
|
-
*/
|
|
355
|
-
getBottomSummaryRowStyles() {
|
|
356
|
-
if (!this.scrollbarV || !this.rows || !this.rows.length) {
|
|
357
|
-
return null;
|
|
358
|
-
}
|
|
359
|
-
const styles = { position: 'absolute' };
|
|
360
|
-
const pos = this.rowHeightsCache.query(this.rows.length - 1);
|
|
361
|
-
translateXY(styles, 0, pos);
|
|
362
|
-
return styles;
|
|
363
|
-
}
|
|
364
|
-
/**
|
|
365
|
-
* Hides the loading indicator
|
|
366
|
-
*/
|
|
367
|
-
hideIndicator() {
|
|
368
|
-
setTimeout(() => (this.loadingIndicator = false), 500);
|
|
369
|
-
}
|
|
370
|
-
/**
|
|
371
|
-
* Updates the index of the rows in the viewport
|
|
372
|
-
*/
|
|
373
|
-
updateIndexes() {
|
|
374
|
-
let first = 0;
|
|
375
|
-
let last = 0;
|
|
376
|
-
if (this.scrollbarV) {
|
|
377
|
-
if (this.virtualization) {
|
|
378
|
-
// Calculation of the first and last indexes will be based on where the
|
|
379
|
-
// scrollY position would be at. The last index would be the one
|
|
380
|
-
// that shows up inside the view port the last.
|
|
381
|
-
const height = parseInt(this.bodyHeight, 0);
|
|
382
|
-
first = this.rowHeightsCache.getRowIndex(this.offsetY);
|
|
383
|
-
last = this.rowHeightsCache.getRowIndex(height + this.offsetY) + 1;
|
|
384
|
-
}
|
|
385
|
-
else {
|
|
386
|
-
// If virtual rows are not needed
|
|
387
|
-
// We render all in one go
|
|
388
|
-
first = 0;
|
|
389
|
-
last = this.rowCount;
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
else {
|
|
393
|
-
// The server is handling paging and will pass an array that begins with the
|
|
394
|
-
// element at a specified offset. first should always be 0 with external paging.
|
|
395
|
-
if (!this.externalPaging) {
|
|
396
|
-
first = Math.max(this.offset * this.pageSize, 0);
|
|
397
|
-
}
|
|
398
|
-
last = Math.min(first + this.pageSize, this.rowCount);
|
|
399
|
-
}
|
|
400
|
-
this.indexes = { first, last };
|
|
401
|
-
}
|
|
402
|
-
/**
|
|
403
|
-
* Refreshes the full Row Height cache. Should be used
|
|
404
|
-
* when the entire row array state has changed.
|
|
405
|
-
*/
|
|
406
|
-
refreshRowHeightCache() {
|
|
407
|
-
if (!this.scrollbarV || (this.scrollbarV && !this.virtualization)) {
|
|
408
|
-
return;
|
|
409
|
-
}
|
|
410
|
-
// clear the previous row height cache if already present.
|
|
411
|
-
// this is useful during sorts, filters where the state of the
|
|
412
|
-
// rows array is changed.
|
|
413
|
-
this.rowHeightsCache.clearCache();
|
|
414
|
-
// Initialize the tree only if there are rows inside the tree.
|
|
415
|
-
if (this.rows && this.rows.length) {
|
|
416
|
-
const rowExpansions = new Set();
|
|
417
|
-
for (const row of this.rows) {
|
|
418
|
-
if (this.getRowExpanded(row)) {
|
|
419
|
-
rowExpansions.add(row);
|
|
420
|
-
}
|
|
421
|
-
}
|
|
422
|
-
this.rowHeightsCache.initCache({
|
|
423
|
-
rows: this.rows,
|
|
424
|
-
rowHeight: this.rowHeight,
|
|
425
|
-
detailRowHeight: this.getDetailRowHeight,
|
|
426
|
-
externalVirtual: this.scrollbarV && this.externalPaging,
|
|
427
|
-
rowCount: this.rowCount,
|
|
428
|
-
rowIndexes: this.rowIndexes,
|
|
429
|
-
rowExpansions
|
|
430
|
-
});
|
|
431
|
-
}
|
|
432
|
-
}
|
|
433
|
-
/**
|
|
434
|
-
* Gets the index for the view port
|
|
435
|
-
*/
|
|
436
|
-
getAdjustedViewPortIndex() {
|
|
437
|
-
// Capture the row index of the first row that is visible on the viewport.
|
|
438
|
-
// If the scroll bar is just below the row which is highlighted then make that as the
|
|
439
|
-
// first index.
|
|
440
|
-
const viewPortFirstRowIndex = this.indexes.first;
|
|
441
|
-
if (this.scrollbarV && this.virtualization) {
|
|
442
|
-
const offsetScroll = this.rowHeightsCache.query(viewPortFirstRowIndex - 1);
|
|
443
|
-
return offsetScroll <= this.offsetY ? viewPortFirstRowIndex - 1 : viewPortFirstRowIndex;
|
|
444
|
-
}
|
|
445
|
-
return viewPortFirstRowIndex;
|
|
446
|
-
}
|
|
447
|
-
/**
|
|
448
|
-
* Toggle the Expansion of the row i.e. if the row is expanded then it will
|
|
449
|
-
* collapse and vice versa. Note that the expanded status is stored as
|
|
450
|
-
* a part of the row object itself as we have to preserve the expanded row
|
|
451
|
-
* status in case of sorting and filtering of the row set.
|
|
452
|
-
*/
|
|
453
|
-
toggleRowExpansion(row) {
|
|
454
|
-
// Capture the row index of the first row that is visible on the viewport.
|
|
455
|
-
const viewPortFirstRowIndex = this.getAdjustedViewPortIndex();
|
|
456
|
-
const rowExpandedIdx = this.getRowExpandedIdx(row, this.rowExpansions);
|
|
457
|
-
const expanded = rowExpandedIdx > -1;
|
|
458
|
-
// If the detailRowHeight is auto --> only in case of non-virtualized scroll
|
|
459
|
-
if (this.scrollbarV && this.virtualization) {
|
|
460
|
-
const detailRowHeight = this.getDetailRowHeight(row) * (expanded ? -1 : 1);
|
|
461
|
-
// const idx = this.rowIndexes.get(row) || 0;
|
|
462
|
-
const idx = this.getRowIndex(row);
|
|
463
|
-
this.rowHeightsCache.update(idx, detailRowHeight);
|
|
464
|
-
}
|
|
465
|
-
// Update the toggled row and update thive nevere heights in the cache.
|
|
466
|
-
if (expanded) {
|
|
467
|
-
this.rowExpansions.splice(rowExpandedIdx, 1);
|
|
468
|
-
}
|
|
469
|
-
else {
|
|
470
|
-
this.rowExpansions.push(row);
|
|
471
|
-
}
|
|
472
|
-
this.detailToggle.emit({
|
|
473
|
-
rows: [row],
|
|
474
|
-
currentIndex: viewPortFirstRowIndex
|
|
475
|
-
});
|
|
476
|
-
}
|
|
477
|
-
/**
|
|
478
|
-
* Expand/Collapse all the rows no matter what their state is.
|
|
479
|
-
*/
|
|
480
|
-
toggleAllRows(expanded) {
|
|
481
|
-
// clear prev expansions
|
|
482
|
-
this.rowExpansions = [];
|
|
483
|
-
// Capture the row index of the first row that is visible on the viewport.
|
|
484
|
-
const viewPortFirstRowIndex = this.getAdjustedViewPortIndex();
|
|
485
|
-
if (expanded) {
|
|
486
|
-
for (const row of this.rows) {
|
|
487
|
-
this.rowExpansions.push(row);
|
|
488
|
-
}
|
|
489
|
-
}
|
|
490
|
-
if (this.scrollbarV) {
|
|
491
|
-
// Refresh the full row heights cache since every row was affected.
|
|
492
|
-
this.recalcLayout();
|
|
493
|
-
}
|
|
494
|
-
// Emit all rows that have been expanded.
|
|
495
|
-
this.detailToggle.emit({
|
|
496
|
-
rows: this.rows,
|
|
497
|
-
currentIndex: viewPortFirstRowIndex
|
|
498
|
-
});
|
|
499
|
-
}
|
|
500
|
-
/**
|
|
501
|
-
* Recalculates the table
|
|
502
|
-
*/
|
|
503
|
-
recalcLayout() {
|
|
504
|
-
this.refreshRowHeightCache();
|
|
505
|
-
this.updateIndexes();
|
|
506
|
-
this.updateRows();
|
|
507
|
-
}
|
|
508
|
-
/**
|
|
509
|
-
* Tracks the column
|
|
510
|
-
*/
|
|
511
|
-
columnTrackingFn(index, column) {
|
|
512
|
-
return column.$$id;
|
|
513
|
-
}
|
|
514
|
-
/**
|
|
515
|
-
* Gets the row pinning group styles
|
|
516
|
-
*/
|
|
517
|
-
stylesByGroup(group) {
|
|
518
|
-
const widths = this.columnGroupWidths;
|
|
519
|
-
const offsetX = this.offsetX;
|
|
520
|
-
const styles = {
|
|
521
|
-
width: `${widths[group]}px`
|
|
522
|
-
};
|
|
523
|
-
if (group === 'left') {
|
|
524
|
-
translateXY(styles, offsetX, 0);
|
|
525
|
-
}
|
|
526
|
-
else if (group === 'right') {
|
|
527
|
-
const bodyWidth = parseInt(this.innerWidth + '', 0);
|
|
528
|
-
const totalDiff = widths.total - bodyWidth;
|
|
529
|
-
const offsetDiff = totalDiff - offsetX;
|
|
530
|
-
const offset = offsetDiff * -1;
|
|
531
|
-
translateXY(styles, offset, 0);
|
|
532
|
-
}
|
|
533
|
-
return styles;
|
|
534
|
-
}
|
|
535
|
-
/**
|
|
536
|
-
* Returns if the row was expanded and set default row expansion when row expansion is empty
|
|
537
|
-
*/
|
|
538
|
-
getRowExpanded(row) {
|
|
539
|
-
if (this.rowExpansions.length === 0 && this.groupExpansionDefault) {
|
|
540
|
-
for (const group of this.groupedRows) {
|
|
541
|
-
this.rowExpansions.push(group);
|
|
542
|
-
}
|
|
543
|
-
}
|
|
544
|
-
return this.getRowExpandedIdx(row, this.rowExpansions) > -1;
|
|
545
|
-
}
|
|
546
|
-
getRowExpandedIdx(row, expanded) {
|
|
547
|
-
if (!expanded || !expanded.length)
|
|
548
|
-
return -1;
|
|
549
|
-
const rowId = this.rowIdentity(row);
|
|
550
|
-
return expanded.findIndex(r => {
|
|
551
|
-
const id = this.rowIdentity(r);
|
|
552
|
-
return id === rowId;
|
|
553
|
-
});
|
|
554
|
-
}
|
|
555
|
-
/**
|
|
556
|
-
* Gets the row index given a row
|
|
557
|
-
*/
|
|
558
|
-
getRowIndex(row) {
|
|
559
|
-
return this.rowIndexes.get(row) || 0;
|
|
560
|
-
}
|
|
561
|
-
onTreeAction(row) {
|
|
562
|
-
this.treeAction.emit({ row });
|
|
563
|
-
}
|
|
564
|
-
}
|
|
565
|
-
DataTableBodyComponent.decorators = [
|
|
566
|
-
{ type: Component, args: [{
|
|
567
|
-
selector: 'datatable-body',
|
|
568
|
-
template: `
|
|
569
|
-
<datatable-progress *ngIf="loadingIndicator"> </datatable-progress>
|
|
570
|
-
<datatable-selection
|
|
571
|
-
#selector
|
|
572
|
-
[selected]="selected"
|
|
573
|
-
[rows]="rows"
|
|
574
|
-
[selectCheck]="selectCheck"
|
|
575
|
-
[selectEnabled]="selectEnabled"
|
|
576
|
-
[selectionType]="selectionType"
|
|
577
|
-
[rowIdentity]="rowIdentity"
|
|
578
|
-
(select)="select.emit($event)"
|
|
579
|
-
(activate)="activate.emit($event)"
|
|
580
|
-
>
|
|
581
|
-
<datatable-scroller
|
|
582
|
-
*ngIf="rows?.length"
|
|
583
|
-
[scrollbarV]="scrollbarV"
|
|
584
|
-
[scrollbarH]="scrollbarH"
|
|
585
|
-
[scrollHeight]="scrollHeight"
|
|
586
|
-
[scrollWidth]="columnGroupWidths?.total"
|
|
587
|
-
(scroll)="onBodyScroll($event)"
|
|
588
|
-
>
|
|
589
|
-
<datatable-summary-row
|
|
590
|
-
*ngIf="summaryRow && summaryPosition === 'top'"
|
|
591
|
-
[rowHeight]="summaryHeight"
|
|
592
|
-
[offsetX]="offsetX"
|
|
593
|
-
[innerWidth]="innerWidth"
|
|
594
|
-
[rows]="rows"
|
|
595
|
-
[columns]="columns"
|
|
596
|
-
>
|
|
597
|
-
</datatable-summary-row>
|
|
598
|
-
<datatable-row-wrapper
|
|
599
|
-
[groupedRows]="groupedRows"
|
|
600
|
-
*ngFor="let group of temp; let i = index; trackBy: rowTrackingFn"
|
|
601
|
-
[innerWidth]="innerWidth"
|
|
602
|
-
[ngStyle]="getRowsStyles(group)"
|
|
603
|
-
[rowDetail]="rowDetail"
|
|
604
|
-
[groupHeader]="groupHeader"
|
|
605
|
-
[offsetX]="offsetX"
|
|
606
|
-
[detailRowHeight]="getDetailRowHeight(group && group[i], i)"
|
|
607
|
-
[row]="group"
|
|
608
|
-
[expanded]="getRowExpanded(group)"
|
|
609
|
-
[rowIndex]="getRowIndex(group && group[i])"
|
|
610
|
-
(rowContextmenu)="rowContextmenu.emit($event)"
|
|
611
|
-
>
|
|
612
|
-
<datatable-body-row
|
|
613
|
-
*ngIf="!groupedRows; else groupedRowsTemplate"
|
|
614
|
-
tabindex="-1"
|
|
615
|
-
[isSelected]="selector.getRowSelected(group)"
|
|
616
|
-
[innerWidth]="innerWidth"
|
|
617
|
-
[offsetX]="offsetX"
|
|
618
|
-
[columns]="columns"
|
|
619
|
-
[rowHeight]="getRowHeight(group)"
|
|
620
|
-
[row]="group"
|
|
621
|
-
[rowIndex]="getRowIndex(group)"
|
|
622
|
-
[expanded]="getRowExpanded(group)"
|
|
623
|
-
[rowClass]="rowClass"
|
|
624
|
-
[displayCheck]="displayCheck"
|
|
625
|
-
[treeStatus]="group && group.treeStatus"
|
|
626
|
-
(treeAction)="onTreeAction(group)"
|
|
627
|
-
(activate)="selector.onActivate($event, indexes.first + i)"
|
|
628
|
-
>
|
|
629
|
-
</datatable-body-row>
|
|
630
|
-
<ng-template #groupedRowsTemplate>
|
|
631
|
-
<datatable-body-row
|
|
632
|
-
*ngFor="let row of group.value; let i = index; trackBy: rowTrackingFn"
|
|
633
|
-
tabindex="-1"
|
|
634
|
-
[isSelected]="selector.getRowSelected(row)"
|
|
635
|
-
[innerWidth]="innerWidth"
|
|
636
|
-
[offsetX]="offsetX"
|
|
637
|
-
[columns]="columns"
|
|
638
|
-
[rowHeight]="getRowHeight(row)"
|
|
639
|
-
[row]="row"
|
|
640
|
-
[group]="group.value"
|
|
641
|
-
[rowIndex]="getRowIndex(row)"
|
|
642
|
-
[expanded]="getRowExpanded(row)"
|
|
643
|
-
[rowClass]="rowClass"
|
|
644
|
-
(activate)="selector.onActivate($event, i)"
|
|
645
|
-
>
|
|
646
|
-
</datatable-body-row>
|
|
647
|
-
</ng-template>
|
|
648
|
-
</datatable-row-wrapper>
|
|
649
|
-
<datatable-summary-row
|
|
650
|
-
*ngIf="summaryRow && summaryPosition === 'bottom'"
|
|
651
|
-
[ngStyle]="getBottomSummaryRowStyles()"
|
|
652
|
-
[rowHeight]="summaryHeight"
|
|
653
|
-
[offsetX]="offsetX"
|
|
654
|
-
[innerWidth]="innerWidth"
|
|
655
|
-
[rows]="rows"
|
|
656
|
-
[columns]="columns"
|
|
657
|
-
>
|
|
658
|
-
</datatable-summary-row>
|
|
659
|
-
</datatable-scroller>
|
|
660
|
-
<div class="empty-row" *ngIf="!rows?.length && !loadingIndicator" [innerHTML]="emptyMessage"></div>
|
|
661
|
-
</datatable-selection>
|
|
662
|
-
`,
|
|
663
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
664
|
-
host: {
|
|
665
|
-
class: 'datatable-body'
|
|
666
|
-
}
|
|
667
|
-
},] }
|
|
668
|
-
];
|
|
669
|
-
DataTableBodyComponent.ctorParameters = () => [
|
|
670
|
-
{ type: ChangeDetectorRef }
|
|
671
|
-
];
|
|
672
|
-
DataTableBodyComponent.propDecorators = {
|
|
673
|
-
scrollbarV: [{ type: Input }],
|
|
674
|
-
scrollbarH: [{ type: Input }],
|
|
675
|
-
loadingIndicator: [{ type: Input }],
|
|
676
|
-
externalPaging: [{ type: Input }],
|
|
677
|
-
rowHeight: [{ type: Input }],
|
|
678
|
-
offsetX: [{ type: Input }],
|
|
679
|
-
emptyMessage: [{ type: Input }],
|
|
680
|
-
selectionType: [{ type: Input }],
|
|
681
|
-
selected: [{ type: Input }],
|
|
682
|
-
rowIdentity: [{ type: Input }],
|
|
683
|
-
rowDetail: [{ type: Input }],
|
|
684
|
-
groupHeader: [{ type: Input }],
|
|
685
|
-
selectCheck: [{ type: Input }],
|
|
686
|
-
displayCheck: [{ type: Input }],
|
|
687
|
-
trackByProp: [{ type: Input }],
|
|
688
|
-
rowClass: [{ type: Input }],
|
|
689
|
-
groupedRows: [{ type: Input }],
|
|
690
|
-
groupExpansionDefault: [{ type: Input }],
|
|
691
|
-
innerWidth: [{ type: Input }],
|
|
692
|
-
groupRowsBy: [{ type: Input }],
|
|
693
|
-
virtualization: [{ type: Input }],
|
|
694
|
-
summaryRow: [{ type: Input }],
|
|
695
|
-
summaryPosition: [{ type: Input }],
|
|
696
|
-
summaryHeight: [{ type: Input }],
|
|
697
|
-
pageSize: [{ type: Input }],
|
|
698
|
-
rows: [{ type: Input }],
|
|
699
|
-
columns: [{ type: Input }],
|
|
700
|
-
offset: [{ type: Input }],
|
|
701
|
-
rowCount: [{ type: Input }],
|
|
702
|
-
bodyWidth: [{ type: HostBinding, args: ['style.width',] }],
|
|
703
|
-
bodyHeight: [{ type: Input }, { type: HostBinding, args: ['style.height',] }],
|
|
704
|
-
scroll: [{ type: Output }],
|
|
705
|
-
page: [{ type: Output }],
|
|
706
|
-
activate: [{ type: Output }],
|
|
707
|
-
select: [{ type: Output }],
|
|
708
|
-
detailToggle: [{ type: Output }],
|
|
709
|
-
rowContextmenu: [{ type: Output }],
|
|
710
|
-
treeAction: [{ type: Output }],
|
|
711
|
-
scroller: [{ type: ViewChild, args: [ScrollerComponent,] }]
|
|
712
|
-
};
|
|
713
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYm9keS5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiLi4vLi4vLi4vLi4vcHJvamVjdHMvc3dpbWxhbmUvbmd4LWRhdGF0YWJsZS9zcmMvIiwic291cmNlcyI6WyJsaWIvY29tcG9uZW50cy9ib2R5L2JvZHkuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCxTQUFTLEVBQ1QsTUFBTSxFQUNOLFlBQVksRUFDWixLQUFLLEVBQ0wsV0FBVyxFQUNYLGlCQUFpQixFQUNqQixTQUFTLEVBR1QsdUJBQXVCLEVBQ3hCLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBRXpELE9BQU8sRUFBRSxZQUFZLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUNyRSxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sOEJBQThCLENBQUM7QUFDOUQsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBd0dwRCxNQUFNLE9BQU8sc0JBQXNCO0lBaUpqQzs7T0FFRztJQUNILFlBQW9CLEVBQXFCO1FBQXJCLE9BQUUsR0FBRixFQUFFLENBQW1CO1FBM0loQyxhQUFRLEdBQVUsRUFBRSxDQUFDO1FBd0ZwQixXQUFNLEdBQXNCLElBQUksWUFBWSxFQUFFLENBQUM7UUFDL0MsU0FBSSxHQUFzQixJQUFJLFlBQVksRUFBRSxDQUFDO1FBQzdDLGFBQVEsR0FBc0IsSUFBSSxZQUFZLEVBQUUsQ0FBQztRQUNqRCxXQUFNLEdBQXNCLElBQUksWUFBWSxFQUFFLENBQUM7UUFDL0MsaUJBQVksR0FBc0IsSUFBSSxZQUFZLEVBQUUsQ0FBQztRQUNyRCxtQkFBYyxHQUFHLElBQUksWUFBWSxDQUFrQyxLQUFLLENBQUMsQ0FBQztRQUMxRSxlQUFVLEdBQXNCLElBQUksWUFBWSxFQUFFLENBQUM7UUF3QjdELG9CQUFlLEdBQW1CLElBQUksY0FBYyxFQUFFLENBQUM7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S0FBSzswQkFDTCxLQUFLO3VCQUNMLEtBQUs7MEJBQ0wsS0FBSztvQ0FDTCxLQUFLO3lCQUNMLEtBQUs7MEJBQ0wsS0FBSzs2QkFDTCxLQUFLO3lCQUNMLEtBQUs7OEJBQ0wsS0FBSzs0QkFDTCxLQUFLO3VCQUVMLEtBQUs7bUJBU0wsS0FBSztzQkFTTCxLQUFLO3FCQVVMLEtBQUs7dUJBU0wsS0FBSzt3QkFTTCxXQUFXLFNBQUMsYUFBYTt5QkFTekIsS0FBSyxZQUNMLFdBQVcsU0FBQyxjQUFjO3FCQWUxQixNQUFNO21CQUNOLE1BQU07dUJBQ04sTUFBTTtxQkFDTixNQUFNOzJCQUNOLE1BQU07NkJBQ04sTUFBTTt5QkFDTixNQUFNO3VCQUVOLFNBQVMsU0FBQyxpQkFBaUIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBDb21wb25lbnQsXG4gIE91dHB1dCxcbiAgRXZlbnRFbWl0dGVyLFxuICBJbnB1dCxcbiAgSG9zdEJpbmRpbmcsXG4gIENoYW5nZURldGVjdG9yUmVmLFxuICBWaWV3Q2hpbGQsXG4gIE9uSW5pdCxcbiAgT25EZXN0cm95LFxuICBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneVxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IFNjcm9sbGVyQ29tcG9uZW50IH0gZnJvbSAnLi9zY3JvbGxlci5jb21wb25lbnQnO1xuaW1wb3J0IHsgU2VsZWN0aW9uVHlwZSB9IGZyb20gJy4uLy4uL3R5cGVzL3NlbGVjdGlvbi50eXBlJztcbmltcG9ydCB7IGNvbHVtbnNCeVBpbiwgY29sdW1uR3JvdXBXaWR0aHMgfSBmcm9tICcuLi8uLi91dGlscy9jb2x1bW4nO1xuaW1wb3J0IHsgUm93SGVpZ2h0Q2FjaGUgfSBmcm9tICcuLi8uLi91dGlscy9yb3ctaGVpZ2h0LWNhY2hlJztcbmltcG9ydCB7IHRyYW5zbGF0ZVhZIH0gZnJvbSAnLi4vLi4vdXRpbHMvdHJhbnNsYXRlJztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnZGF0YXRhYmxlLWJvZHknLFxuICB0ZW1wbGF0ZTogYFxuICAgIDxkYXRhdGFibGUtcHJvZ3Jlc3MgKm5nSWY9XCJsb2FkaW5nSW5kaWNhdG9yXCI+IDwvZGF0YXRhYmxlLXByb2dyZXNzPlxuICAgIDxkYXRhdGFibGUtc2VsZWN0aW9uXG4gICAgICAjc2VsZWN0b3JcbiAgICAgIFtzZWxlY3RlZF09XCJzZWxlY3RlZFwiXG4gICAgICBbcm93c109XCJyb3dzXCJcbiAgICAgIFtzZWxlY3RDaGVja109XCJzZWxlY3RDaGVja1wiXG4gICAgICBbc2VsZWN0RW5hYmxlZF09XCJzZWxlY3RFbmFibGVkXCJcbiAgICAgIFtzZWxlY3Rpb25UeXBlXT1cInNlbGVjdGlvblR5cGVcIlxuICAgICAgW3Jvd0lkZW50aXR5XT1cInJvd0lkZW50aXR5XCJcbiAgICAgIChzZWxlY3QpPVwic2VsZWN0LmVtaXQoJGV2ZW50KVwiXG4gICAgICAoYWN0aXZhdGUpPVwiYWN0aXZhdGUuZW1pdCgkZXZlbnQpXCJcbiAgICA+XG4gICAgICA8ZGF0YXRhYmxlLXNjcm9sbGVyXG4gICAgICAgICpuZ0lmPVwicm93cz8ubGVuZ3RoXCJcbiAgICAgICAgW3Njcm9sbGJhclZdPVwic2Nyb2xsYmFyVlwiXG4gICAgICAgIFtzY3JvbGxiYXJIXT1cInNjcm9sbGJhckhcIlxuICAgICAgICBbc2Nyb2xsSGVpZ2h0XT1cInNjcm9sbEhlaWdodFwiXG4gICAgICAgIFtzY3JvbGxXaWR0aF09XCJjb2x1bW5Hcm91cFdpZHRocz8udG90YWxcIlxuICAgICAgICAoc2Nyb2xsKT1cIm9uQm9keVNjcm9sbCgkZXZlbnQpXCJcbiAgICAgID5cbiAgICAgICAgPGRhdGF0YWJsZS1zdW1tYXJ5LXJvd1xuICAgICAgICAgICpuZ0lmPVwic3VtbWFyeVJvdyAmJiBzdW1tYXJ5UG9zaXRpb24gPT09ICd0b3AnXCJcbiAgICAgICAgICBbcm93SGVpZ2h0XT1cInN1bW1hcnlIZWlnaHRcIlxuICAgICAgICAgIFtvZmZzZXRYXT1cIm9mZnNldFhcIlxuICAgICAgICAgIFtpbm5lcldpZHRoXT1cImlubmVyV2lkdGhcIlxuICAgICAgICAgIFtyb3dzXT1cInJvd3NcIlxuICAgICAgICAgIFtjb2x1bW5zXT1cImNvbHVtbnNcIlxuICAgICAgICA+XG4gICAgICAgIDwvZGF0YXRhYmxlLXN1bW1hcnktcm93PlxuICAgICAgICA8ZGF0YXRhYmxlLXJvdy13cmFwcGVyXG4gICAgICAgICAgW2dyb3VwZWRSb3dzXT1cImdyb3VwZWRSb3dzXCJcbiAgICAgICAgICAqbmdGb3I9XCJsZXQgZ3JvdXAgb2YgdGVtcDsgbGV0IGkgPSBpbmRleDsgdHJhY2tCeTogcm93VHJhY2tpbmdGblwiXG4gICAgICAgICAgW2lubmVyV2lkdGhdPVwiaW5uZXJXaWR0aFwiXG4gICAgICAgICAgW25nU3R5bGVdPVwiZ2V0Um93c1N0eWxlcyhncm91cClcIlxuICAgICAgICAgIFtyb3dEZXRhaWxdPVwicm93RGV0YWlsXCJcbiAgICAgICAgICBbZ3JvdXBIZWFkZXJdPVwiZ3JvdXBIZWFkZXJcIlxuICAgICAgICAgIFtvZmZzZXRYXT1cIm9mZnNldFhcIlxuICAgICAgICAgIFtkZXRhaWxSb3dIZWlnaHRdPVwiZ2V0RGV0YWlsUm93SGVpZ2h0KGdyb3VwICYmIGdyb3VwW2ldLCBpKVwiXG4gICAgICAgICAgW3Jvd109XCJncm91cFwiXG4gICAgICAgICAgW2V4cGFuZGVkXT1cImdldFJvd0V4cGFuZGVkKGdyb3VwKVwiXG4gICAgICAgICAgW3Jvd0luZGV4XT1cImdldFJvd0luZGV4KGdyb3VwICYmIGdyb3VwW2ldKVwiXG4gICAgICAgICAgKHJvd0NvbnRleHRtZW51KT1cInJvd0NvbnRleHRtZW51LmVtaXQoJGV2ZW50KVwiXG4gICAgICAgID5cbiAgICAgICAgICA8ZGF0YXRhYmxlLWJvZHktcm93XG4gICAgICAgICAgICAqbmdJZj1cIiFncm91cGVkUm93czsgZWxzZSBncm91cGVkUm93c1RlbXBsYXRlXCJcbiAgICAgICAgICAgIHRhYmluZGV4PVwiLTFcIlxuICAgICAgICAgICAgW2lzU2VsZWN0ZWRdPVwic2VsZWN0b3IuZ2V0Um93U2VsZWN0ZWQoZ3JvdXApXCJcbiAgICAgICAgICAgIFtpbm5lcldpZHRoXT1cImlubmVyV2lkdGhcIlxuICAgICAgICAgICAgW29mZnNldFhdPVwib2Zmc2V0WFwiXG4gICAgICAgICAgICBbY29sdW1uc109XCJjb2x1bW5zXCJcbiAgICAgICAgICAgIFtyb3dIZWlnaHRdPVwiZ2V0Um93SGVpZ2h0KGdyb3VwKVwiXG4gICAgICAgICAgICBbcm93XT1cImdyb3VwXCJcbiAgICAgICAgICAgIFtyb3dJbmRleF09XCJnZXRSb3dJbmRleChncm91cClcIlxuICAgICAgICAgICAgW2V4cGFuZGVkXT1cImdldFJvd0V4cGFuZGVkKGdyb3VwKVwiXG4gICAgICAgICAgICBbcm93Q2xhc3NdPVwicm93Q2xhc3NcIlxuICAgICAgICAgICAgW2Rpc3BsYXlDaGVja109XCJkaXNwbGF5Q2hlY2tcIlxuICAgICAgICAgICAgW3RyZWVTdGF0dXNdPVwiZ3JvdXAgJiYgZ3JvdXAudHJlZVN0YXR1c1wiXG4gICAgICAgICAgICAodHJlZUFjdGlvbik9XCJvblRyZWVBY3Rpb24oZ3JvdXApXCJcbiAgICAgICAgICAgIChhY3RpdmF0ZSk9XCJzZWxlY3Rvci5vbkFjdGl2YXRlKCRldmVudCwgaW5kZXhlcy5maXJzdCArIGkpXCJcbiAgICAgICAgICA+XG4gICAgICAgICAgPC9kYXRhdGFibGUtYm9keS1yb3c+XG4gICAgICAgICAgPG5nLXRlbXBsYXRlICNncm91cGVkUm93c1RlbXBsYXRlPlxuICAgICAgICAgICAgPGRhdGF0YWJsZS1ib2R5LXJvd1xuICAgICAgICAgICAgICAqbmdGb3I9XCJsZXQgcm93IG9mIGdyb3VwLnZhbHVlOyBsZXQgaSA9IGluZGV4OyB0cmFja0J5OiByb3dUcmFja2luZ0ZuXCJcbiAgICAgICAgICAgICAgdGFiaW5kZXg9XCItMVwiXG4gICAgICAgICAgICAgIFtpc1NlbGVjdGVkXT1cInNlbGVjdG9yLmdldFJvd1NlbGVjdGVkKHJvdylcIlxuICAgICAgICAgICAgICBbaW5uZXJXaWR0aF09XCJpbm5lcldpZHRoXCJcbiAgICAgICAgICAgICAgW29mZnNldFhdPVwib2Zmc2V0WFwiXG4gICAgICAgICAgICAgIFtjb2x1bW5zXT1cImNvbHVtbnNcIlxuICAgICAgICAgICAgICBbcm93SGVpZ2h0XT1cImdldFJvd0hlaWdodChyb3cpXCJcbiAgICAgICAgICAgICAgW3Jvd109XCJyb3dcIlxuICAgICAgICAgICAgICBbZ3JvdXBdPVwiZ3JvdXAudmFsdWVcIlxuICAgICAgICAgICAgICBbcm93SW5kZXhdPVwiZ2V0Um93SW5kZXgocm93KVwiXG4gICAgICAgICAgICAgIFtleHBhbmRlZF09XCJnZXRSb3dFeHBhbmRlZChyb3cpXCJcbiAgICAgICAgICAgICAgW3Jvd0NsYXNzXT1cInJvd0NsYXNzXCJcbiAgICAgICAgICAgICAgKGFjdGl2YXRlKT1cInNlbGVjdG9yLm9uQWN0aXZhdGUoJGV2ZW50LCBpKVwiXG4gICAgICAgICAgICA+XG4gICAgICAgICAgICA8L2RhdGF0YWJsZS1ib2R5LXJvdz5cbiAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICA8L2RhdGF0YWJsZS1yb3ctd3JhcHBlcj5cbiAgICAgICAgPGRhdGF0YWJsZS1zdW1tYXJ5LXJvd1xuICAgICAgICAgICpuZ0lmPVwic3VtbWFyeVJvdyAmJiBzdW1tYXJ5UG9zaXRpb24gPT09ICdib3R0b20nXCJcbiAgICAgICAgICBbbmdTdHlsZV09XCJnZXRCb3R0b21TdW1tYXJ5Um93U3R5bGVzKClcIlxuICAgICAgICAgIFtyb3dIZWlnaHRdPVwic3VtbWFyeUhlaWdodFwiXG4gICAgICAgICAgW29mZnNldFhdPVwib2Zmc2V0WFwiXG4gICAgICAgICAgW2lubmVyV2lkdGhdPVwiaW5uZXJXaWR0aFwiXG4gICAgICAgICAgW3Jvd3NdPVwicm93c1wiXG4gICAgICAgICAgW2NvbHVtbnNdPVwiY29sdW1uc1wiXG4gICAgICAgID5cbiAgICAgICAgPC9kYXRhdGFibGUtc3VtbWFyeS1yb3c+XG4gICAgICA8L2RhdGF0YWJsZS1zY3JvbGxlcj5cbiAgICAgIDxkaXYgY2xhc3M9XCJlbXB0eS1yb3dcIiAqbmdJZj1cIiFyb3dzPy5sZW5ndGggJiYgIWxvYWRpbmdJbmRpY2F0b3JcIiBbaW5uZXJIVE1MXT1cImVtcHR5TWVzc2FnZVwiPjwvZGl2PlxuICAgIDwvZGF0YXRhYmxlLXNlbGVjdGlvbj5cbiAgYCxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gIGhvc3Q6IHtcbiAgICBjbGFzczogJ2RhdGF0YWJsZS1ib2R5J1xuICB9XG59KVxuZXhwb3J0IGNsYXNzIERhdGFUYWJsZUJvZHlDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQsIE9uRGVzdHJveSB7XG4gIEBJbnB1dCgpIHNjcm9sbGJhclY6IGJvb2xlYW47XG4gIEBJbnB1dCgpIHNjcm9sbGJhckg6IGJvb2xlYW47XG4gIEBJbnB1dCgpIGxvYWRpbmdJbmRpY2F0b3I6IGJvb2xlYW47XG4gIEBJbnB1dCgpIGV4dGVybmFsUGFnaW5nOiBib29sZWFuO1xuICBASW5wdXQoKSByb3dIZWlnaHQ6IG51bWJlciB8ICdhdXRvJyB8ICgocm93PzogYW55KSA9PiBudW1iZXIpO1xuICBASW5wdXQoKSBvZmZzZXRYOiBudW1iZXI7XG4gIEBJbnB1dCgpIGVtcHR5TWVzc2FnZTogc3RyaW5nO1xuICBASW5wdXQoKSBzZWxlY3Rpb25UeXBlOiBTZWxlY3Rpb25UeXBlO1xuICBASW5wdXQoKSBzZWxlY3RlZDogYW55W10gPSBbXTtcbiAgQElucHV0KCkgcm93SWRlbnRpdHk6IGFueTtcbiAgQElucHV0KCkgcm93RGV0YWlsOiBhbnk7XG4gIEBJbnB1dCgpIGdyb3VwSGVhZGVyOiBhbnk7XG4gIEBJbnB1dCgpIHNlbGVjdENoZWNrOiBhbnk7XG4gIEBJbnB1dCgpIGRpc3BsYXlDaGVjazogYW55O1xuICBASW5wdXQoKSB0cmFja0J5UHJvcDogc3RyaW5nO1xuICBASW5wdXQoKSByb3dDbGFzczogYW55O1xuICBASW5wdXQoKSBncm91cGVkUm93czogYW55O1xuICBASW5wdXQoKSBncm91cEV4cGFuc2lvbkRlZmF1bHQ6IGJvb2xlYW47XG4gIEBJbnB1dCgpIGlubmVyV2lkdGg6IG51bWJlcjtcbiAgQElucHV0KCkgZ3JvdXBSb3dzQnk6IHN0cmluZztcbiAgQElucHV0KCkgdmlydHVhbGl6YXRpb246IGJvb2xlYW47XG4gIEBJbnB1dCgpIHN1bW1hcnlSb3c6IGJvb2xlYW47XG4gIEBJbnB1dCgpIHN1bW1hcnlQb3NpdGlvbjogc3RyaW5nO1xuICBASW5wdXQoKSBzdW1tYXJ5SGVpZ2h0OiBudW1iZXI7XG5cbiAgQElucHV0KCkgc2V0IHBhZ2VTaXplKHZhbDogbnVtYmVyKSB7XG4gICAgdGhpcy5fcGFnZVNpemUgPSB2YWw7XG4gICAgdGhpcy5yZWNhbGNMYXlvdXQoKTtcbiAgfVxuXG4gIGdldCBwYWdlU2l6ZSgpOiBudW1iZXIge1xuICAgIHJldHVybiB0aGlzLl9wYWdlU2l6ZTtcbiAgfVxuXG4gIEBJbnB1dCgpIHNldCByb3dzKHZhbDogYW55W10pIHtcbiAgICB0aGlzLl9yb3dzID0gdmFsO1xuICAgIHRoaXMucmVjYWxjTGF5b3V0KCk7XG4gIH1cblxuICBnZXQgcm93cygpOiBhbnlbXSB7XG4gICAgcmV0dXJuIHRoaXMuX3Jvd3M7XG4gIH1cblxuICBASW5wdXQoKSBzZXQgY29sdW1ucyh2YWw6IGFueVtdKSB7XG4gICAgdGhpcy5fY29sdW1ucyA9IHZhbDtcbiAgICBjb25zdCBjb2xzQnlQaW4gPSBjb2x1bW5zQnlQaW4odmFsKTtcbiAgICB0aGlzLmNvbHVtbkdyb3VwV2lkdGhzID0gY29sdW1uR3JvdXBXaWR0aHMoY29sc0J5UGluLCB2YWwpO1xuICB9XG5cbiAgZ2V0IGNvbHVtbnMoKTogYW55W10ge1xuICAgIHJldHVybiB0aGlzLl9jb2x1bW5zO1xuICB9XG5cbiAgQElucHV0KCkgc2V0IG9mZnNldCh2YWw6IG51bWJlcikge1xuICAgIHRoaXMuX29mZnNldCA9IHZhbDtcbiAgICBpZiAoIXRoaXMuc2Nyb2xsYmFyViB8fCAodGhpcy5zY3JvbGxiYXJWICYmICF0aGlzLnZpcnR1YWxpemF0aW9uKSkgdGhpcy5yZWNhbGNMYXlvdXQoKTtcbiAgfVxuXG4gIGdldCBvZmZzZXQoKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5fb2Zmc2V0O1xuICB9XG5cbiAgQElucHV0KCkgc2V0IHJvd0NvdW50KHZhbDogbnVtYmVyKSB7XG4gICAgdGhpcy5fcm93Q291bnQgPSB2YWw7XG4gICAgdGhpcy5yZWNhbGNMYXlvdXQoKTtcbiAgfVxuXG4gIGdldCByb3dDb3VudCgpOiBudW1iZXIge1xuICAgIHJldHVybiB0aGlzLl9yb3dDb3VudDtcbiAgfVxuXG4gIEBIb3N0QmluZGluZygnc3R5bGUud2lkdGgnKVxuICBnZXQgYm9keVdpZHRoKCk6IHN0cmluZyB7XG4gICAgaWYgKHRoaXMuc2Nyb2xsYmFySCkge1xuICAgICAgcmV0dXJuIHRoaXMuaW5uZXJXaWR0aCArICdweCc7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiAnMTAwJSc7XG4gICAgfVxuICB9XG5cbiAgQElucHV0KClcbiAgQEhvc3RCaW5kaW5nKCdzdHlsZS5oZWlnaHQnKVxuICBzZXQgYm9keUhlaWdodCh2YWwpIHtcbiAgICBpZiAodGhpcy5zY3JvbGxiYXJWKSB7XG4gICAgICB0aGlzLl9ib2R5SGVpZ2h0ID0gdmFsICsgJ3B4JztcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5fYm9keUhlaWdodCA9ICdhdXRvJztcbiAgICB9XG5cbiAgICB0aGlzLnJlY2FsY0xheW91dCgpO1xuICB9XG5cbiAgZ2V0IGJvZHlIZWlnaHQoKSB7XG4gICAgcmV0dXJuIHRoaXMuX2JvZHlIZWlnaHQ7XG4gIH1cblxuICBAT3V0cHV0KCkgc2Nyb2xsOiBFdmVudEVtaXR0ZXI8YW55PiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgQE91dHB1dCgpIHBhZ2U6IEV2ZW50RW1pdHRlcjxhbnk+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuICBAT3V0cHV0KCkgYWN0aXZhdGU6IEV2ZW50RW1pdHRlcjxhbnk+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuICBAT3V0cHV0KCkgc2VsZWN0OiBFdmVudEVtaXR0ZXI8YW55PiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgQE91dHB1dCgpIGRldGFpbFRvZ2dsZTogRXZlbnRFbWl0dGVyPGFueT4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gIEBPdXRwdXQoKSByb3dDb250ZXh0bWVudSA9IG5ldyBFdmVudEVtaXR0ZXI8eyBldmVudDogTW91c2VFdmVudDsgcm93OiBhbnkgfT4oZmFsc2UpO1xuICBAT3V0cHV0KCkgdHJlZUFjdGlvbjogRXZlbnRFbWl0dGVyPGFueT4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgQFZpZXdDaGlsZChTY3JvbGxlckNvbXBvbmVudCkgc2Nyb2xsZXI6IFNjcm9sbGVyQ29tcG9uZW50O1xuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGlmIHNlbGVjdGlvbiBpcyBlbmFibGVkLlxuICAgKi9cbiAgZ2V0IHNlbGVjdEVuYWJsZWQoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuICEhdGhpcy5zZWxlY3Rpb25UeXBlO1xuICB9XG5cbiAgLyoqXG4gICAqIFByb3BlcnR5IHRoYXQgd291bGQgY2FsY3VsYXRlIHRoZSBoZWlnaHQgb2Ygc2Nyb2xsIGJhclxuICAgKiBiYXNlZCBvbiB0aGUgcm93IGhlaWdodHMgY2FjaGUgZm9yIHZpcnR1YWwgc2Nyb2xsIGFuZCB2aXJ0dWFsaXphdGlvbi4gT3RoZXIgc2NlbmFyaW9zXG4gICAqIGNhbGN1bGF0ZSBzY3JvbGwgaGVpZ2h0IGF1dG9tYXRpY2FsbHkgKGFzIGhlaWdodCB3aWxsIGJlIHVuZGVmaW5lZCkuXG4gICAqL1xuICBnZXQgc2Nyb2xsSGVpZ2h0KCk6IG51bWJlciB8IHVuZGVmaW5lZCB7XG4gICAgaWYgKHRoaXMuc2Nyb2xsYmFyViAmJiB0aGlzLnZpcnR1YWxpemF0aW9uICYmIHRoaXMucm93Q291bnQpIHtcbiAgICAgIHJldHVybiB0aGlzLnJvd0hlaWdodHNDYWNoZS5xdWVyeSh0aGlzLnJvd0NvdW50IC0gMSk7XG4gICAgfVxuICAgIC8vIGF2b2lkIFRTNzAzMDogTm90IGFsbCBjb2RlIHBhdGhzIHJldHVybiBhIHZhbHVlLlxuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cblxuICByb3dIZWlnaHRzQ2FjaGU6IFJvd0hlaWdodENhY2hlID0gbmV3IFJvd0hlaWdodENhY2hlKCk7XG4gIHRlbXA6IGFueVtdID0gW107XG4gIG9mZnNldFkgPSAwO1xuICBpbmRleGVzOiBhbnkgPSB7fTtcbiAgY29sdW1uR3JvdXBXaWR0aHM6IGFueTtcbiAgY29sdW1uR3JvdXBXaWR0aHNXaXRob3V0R3JvdXA6IGFueTtcbiAgcm93VHJhY2tpbmdGbjogYW55O1xuICBsaXN0ZW5lcjogYW55O1xuICByb3dJbmRleGVzOiBhbnkgPSBuZXcgV2Vha01hcDxhbnksIHN0cmluZz4oKTtcbiAgcm93RXhwYW5zaW9uczogYW55W10gPSBbXTtcblxuICBfcm93czogYW55W107XG4gIF9ib2R5SGVpZ2h0OiBhbnk7XG4gIF9jb2x1bW5zOiBhbnlbXTtcbiAgX3Jvd0NvdW50OiBudW1iZXI7XG4gIF9vZmZzZXQ6IG51bWJlcjtcbiAgX3BhZ2VTaXplOiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYW4gaW5zdGFuY2Ugb2YgRGF0YVRhYmxlQm9keUNvbXBvbmVudC5cbiAgICovXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgY2Q6IENoYW5nZURldGVjdG9yUmVmKSB7XG4gICAgLy8gZGVjbGFyZSBmbiBoZXJlIHNvIHdlIGNhbiBnZXQgYWNjZXNzIHRvIHRoZSBgdGhpc2AgcHJvcGVydHlcbiAgICB0aGlzLnJvd1RyYWNraW5nRm4gPSAoaW5kZXg6IG51bWJlciwgcm93OiBhbnkpOiBhbnkgPT4ge1xuICAgICAgY29uc3QgaWR4ID0gdGhpcy5nZXRSb3dJbmRleChyb3cpO1xuICAgICAgaWYgKHRoaXMudHJhY2tCeVByb3ApIHtcbiAgICAgICAgcmV0dXJuIHJvd1t0aGlzLnRyYWNrQnlQcm9wXTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBpZHg7XG4gICAgICB9XG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDYWxsZWQgYWZ0ZXIgdGhlIGNvbnN0cnVjdG9yLCBpbml0aWFsaXppbmcgaW5wdXQgcHJvcGVydGllc1xuICAgKi9cbiAgbmdPbkluaXQoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMucm93RGV0YWlsKSB7XG4gICAgICB0aGlzLmxpc3RlbmVyID0gdGhpcy5yb3dEZXRhaWwudG9nZ2xlLnN1YnNjcmliZSgoeyB0eXBlLCB2YWx1ZSB9OiB7IHR5cGU6IHN0cmluZzsgdmFsdWU6IGFueSB9KSA9PiB7XG4gICAgICAgIGlmICh0eXBlID09PSAncm93Jykge1xuICAgICAgICAgIHRoaXMudG9nZ2xlUm93RXhwYW5zaW9uKHZhbHVlKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZSA9PT0gJ2FsbCcpIHtcbiAgICAgICAgICB0aGlzLnRvZ2dsZUFsbFJvd3ModmFsdWUpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gUmVmcmVzaCByb3dzIGFmdGVyIHRvZ2dsZVxuICAgICAgICAvLyBGaXhlcyAjODgzXG4gICAgICAgIHRoaXMudXBkYXRlSW5kZXhlcygpO1xuICAgICAgICB0aGlzLnVwZGF0ZVJvd3MoKTtcbiAgICAgICAgdGhpcy5jZC5tYXJrRm9yQ2hlY2soKTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGlmICh0aGlzLmdyb3VwSGVhZGVyKSB7XG4gICAgICB0aGlzLmxpc3RlbmVyID0gdGhpcy5ncm91cEhlYWRlci50b2dnbGUuc3Vic2NyaWJlKCh7IHR5cGUsIHZhbHVlIH06IHsgdHlwZTogc3RyaW5nOyB2YWx1ZTogYW55IH0pID0+IHtcbiAgICAgICAgaWYgKHR5cGUgPT09ICdncm91cCcpIHtcbiAgICAgICAgICB0aGlzLnRvZ2dsZVJvd0V4cGFuc2lvbih2YWx1ZSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGUgPT09ICdhbGwnKSB7XG4gICAgICAgICAgdGhpcy50b2dnbGVBbGxSb3dzKHZhbHVlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFJlZnJlc2ggcm93cyBhZnRlciB0b2dnbGVcbiAgICAgICAgLy8gRml4ZXMgIzg4M1xuICAgICAgICB0aGlzLnVwZGF0ZUluZGV4ZXMoKTtcbiAgICAgICAgdGhpcy51cGRhdGVSb3dzKCk7XG4gICAgICAgIHRoaXMuY2QubWFya0ZvckNoZWNrKCk7XG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQ2FsbGVkIG9uY2UsIGJlZm9yZSB0aGUgaW5zdGFuY2UgaXMgZGVzdHJveWVkLlxuICAgKi9cbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgaWYgKHRoaXMucm93RGV0YWlsIHx8IHRoaXMuZ3JvdXBIZWFkZXIpIHtcbiAgICAgIHRoaXMubGlzdGVuZXIudW5zdWJzY3JpYmUoKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVXBkYXRlcyB0aGUgWSBvZmZzZXQgZ2l2ZW4gYSBuZXcgb2Zmc2V0LlxuICAgKi9cbiAgdXBkYXRlT2Zmc2V0WShvZmZzZXQ/OiBudW1iZXIpOiB2b2lkIHtcbiAgICAvLyBzY3JvbGxlciBpcyBtaXNzaW5nIG9uIGVtcHR5IHRhYmxlXG4gICAgaWYgKCF0aGlzLnNjcm9sbGVyKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuc2Nyb2xsYmFyViAmJiB0aGlzLnZpcnR1YWxpemF0aW9uICYmIG9mZnNldCkge1xuICAgICAgLy8gRmlyc3QgZ2V0IHRoZSByb3cgSW5kZXggdGhhdCB3ZSBuZWVkIHRvIG1vdmUgdG8uXG4gICAgICBjb25zdCByb3dJbmRleCA9IHRoaXMucGFnZVNpemUgKiBvZmZzZXQ7XG4gICAgICBvZmZzZXQgPSB0aGlzLnJvd0hlaWdodHNDYWNoZS5xdWVyeShyb3dJbmRleCAtIDEpO1xuICAgIH0gZWxzZSBpZiAodGhpcy5zY3JvbGxiYXJWICYmICF0aGlzLnZpcnR1YWxpemF0aW9uKSB7XG4gICAgICBvZmZzZXQgPSAwO1xuICAgIH1cblxuICAgIHRoaXMuc2Nyb2xsZXIuc2V0T2Zmc2V0KG9mZnNldCB8fCAwKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBCb2R5IHdhcyBzY3JvbGxlZCwgdGhpcyBpcyBtYWlubHkgdXNlZnVsIGZvclxuICAgKiB3aGVuIGEgdXNlciBpcyBzZXJ2ZXItc2lkZSBwYWdpbmF0aW9uIHZpYSB2aXJ0dWFsIHNjcm9sbC5cbiAgICovXG4gIG9uQm9keVNjcm9sbChldmVudDogYW55KTogdm9pZCB7XG4gICAgY29uc3Qgc2Nyb2xsWVBvczogbnVtYmVyID0gZXZlbnQuc2Nyb2xsWVBvcztcbiAgICBjb25zdCBzY3JvbGxYUG9zOiBudW1iZXIgPSBldmVudC5zY3JvbGxYUG9zO1xuXG4gICAgLy8gaWYgc2Nyb2xsIGNoYW5nZSwgdHJpZ2dlciB1cGRhdGVcbiAgICAvLyB0aGlzIGlzIG1haW5seSB1c2VkIGZvciBoZWFkZXIgY2VsbCBwb3NpdGlvbnNcbiAgICBpZiAodGhpcy5vZmZzZXRZICE9PSBzY3JvbGxZUG9zIHx8IHRoaXMub2Zmc2V0WCAhPT0gc2Nyb2xsWFBvcykge1xuICAgICAgdGhpcy5zY3JvbGwuZW1pdCh7XG4gICAgICAgIG9mZnNldFk6IHNjcm9sbFlQb3MsXG4gICAgICAgIG9mZnNldFg6IHNjcm9sbFhQb3NcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHRoaXMub2Zmc2V0WSA9IHNjcm9sbFlQb3M7XG4gICAgdGhpcy5vZmZzZXRYID0gc2Nyb2xsWFBvcztcblxuICAgIHRoaXMudXBkYXRlSW5kZXhlcygpO1xuICAgIHRoaXMudXBkYXRlUGFnZShldmVudC5kaXJlY3Rpb24pO1xuICAgIHRoaXMudXBkYXRlUm93cygpO1xuICB9XG5cbiAgLyoqXG4gICAqIFVwZGF0ZXMgdGhlIHBhZ2UgZ2l2ZW4gYSBkaXJlY3Rpb24uXG4gICAqL1xuICB1cGRhdGVQYWdlKGRpcmVjdGlvbjogc3RyaW5nKTogdm9pZCB7XG4gICAgbGV0IG9mZnNldCA9IHRoaXMuaW5kZXhlcy5maXJzdCAvIHRoaXMucGFnZVNpemU7XG5cbiAgICBpZiAoZGlyZWN0aW9uID09PSAndXAnKSB7XG4gICAgICBvZmZzZXQgPSBNYXRoLmNlaWwob2Zmc2V0KTtcbiAgICB9IGVsc2UgaWYgKGRpcmVjdGlvbiA9PT0gJ2Rvd24nKSB7XG4gICAgICBvZmZzZXQgPSBNYXRoLmZsb29yKG9mZnNldCk7XG4gICAgfVxuXG4gICAgaWYgKGRpcmVjdGlvbiAhPT0gdW5kZWZpbmVkICYmICFpc05hTihvZmZzZXQpKSB7XG4gICAgICB0aGlzLnBhZ2UuZW1pdCh7IG9mZnNldCB9KTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVXBkYXRlcyB0aGUgcm93cyBpbiB0aGUgdmlldyBwb3J0XG4gICAqL1xuICB1cGRhdGVSb3dzKCk6IHZvaWQge1xuICAgIGNvbnN0IHsgZmlyc3QsIGxhc3QgfSA9IHRoaXMuaW5kZXhlcztcbiAgICBsZXQgcm93SW5kZXggPSBmaXJzdDtcbiAgICBsZXQgaWR4ID0gMDtcbiAgICBjb25zdCB0ZW1wOiBhbnlbXSA9IFtdO1xuXG4gICAgLy8gaWYgZ3JvdXByb3dzYnkgaGFzIGJlZW4gc3BlY2lmaWVkIHRyZWF0IHJvdyBwYWdpbmdcbiAgICAvLyBwYXJhbWV0ZXJzIGFzIGdyb3VwIHBhZ2luZyBwYXJhbWV0ZXJzIGllIGlmIGxpbWl0IDEwIGhhcyBiZWVuXG4gICAgLy8gc3BlY2lmaWVkIHRyZWF0IGl0IGFzIDEwIGdyb3VwcyByYXRoZXIgdGhhbiAxMCByb3dzXG4gICAgaWYgKHRoaXMuZ3JvdXBlZFJvd3MpIHtcbiAgICAgIGxldCBtYXhSb3dzUGVyR3JvdXAgPSAzO1xuICAgICAgLy8gaWYgdGhlcmUgaXMgb25seSBvbmUgZ3JvdXAgc2V0IHRoZSBtYXhpbXVtIG51bWJlciBvZlxuICAgICAgLy8gcm93cyBwZXIgZ3JvdXAgdGhlIHNhbWUgYXMgdGhlIHRvdGFsIG51bWJlciBvZiByb3dzXG4gICAgICBpZiAodGhpcy5ncm91cGVkUm93cy5sZW5ndGggPT09IDEpIHtcbiAgICAgICAgbWF4Um93c1Blckdyb3VwID0gdGhpcy5ncm91cGVkUm93c1swXS52YWx1ZS5sZW5ndGg7XG4gICAgICB9XG5cbiAgICAgIHdoaWxlIChyb3dJbmRleCA8IGxhc3QgJiYgcm93SW5kZXggPCB0aGlzLmdyb3VwZWRSb3dzLmxlbmd0aCkge1xuICAgICAgICAvLyBBZGQgdGhlIGdyb3VwcyBpbnRvIHRoaXMgcGFnZVxuICAgICAgICBjb25zdCBncm91cCA9IHRoaXMuZ3JvdXBlZFJvd3Nbcm93SW5kZXhdO1xuICAgICAgICB0aGlzLnJvd0luZGV4ZXMuc2V0KGdyb3VwLCByb3dJbmRleCk7XG5cbiAgICAgICAgaWYgKGdyb3VwLnZhbHVlKSB7XG4gICAgICAgICAgLy8gYWRkIGluZGV4ZXMgZm9yIGVhY2ggZ3JvdXAgaXRlbVxuICAgICAgICAgIGdyb3VwLnZhbHVlLmZvckVhY2goKGc6IGFueSwgaTogbnVtYmVyKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBfaWR4ID0gYCR7cm93SW5kZXh9LSR7aX1gO1xuICAgICAgICAgICAgdGhpcy5yb3dJbmRleGVzLnNldChnLCBfaWR4KTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICB0ZW1wW2lkeF0gPSBncm91cDtcbiAgICAgICAgaWR4Kys7XG5cbiAgICAgICAgLy8gR3JvdXAgaW5kZXggaW4gdGhpcyBjb250ZXh0XG4gICAgICAgIHJvd0luZGV4Kys7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHdoaWxlIChyb3dJbmRleCA8IGxhc3QgJiYgcm93SW5kZXggPCB0aGlzLnJvd0NvdW50KSB7XG4gICAgICAgIGNvbnN0IHJvdyA9IHRoaXMucm93c1tyb3dJbmRleF07XG5cbiAgICAgICAgaWYgKHJvdykge1xuICAgICAgICAgIC8vIGFkZCBpbmRleGVzIGZvciBlYWNoIHJvd1xuICAgICAgICAgIHRoaXMucm93SW5kZXhlcy5zZXQocm93LCByb3dJbmRleCk7XG4gICAgICAgICAgdGVtcFtpZHhdID0gcm93O1xuICAgICAgICB9XG5cbiAgICAgICAgaWR4Kys7XG4gICAgICAgIHJvd0luZGV4Kys7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhpcy50ZW1wID0gdGVtcDtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgdGhlIHJvdyBoZWlnaHRcbiAgICovXG4gIGdldFJvd0hlaWdodChyb3c6IGFueSk6IG51bWJlciB7XG4gICAgLy8gaWYgaXRzIGEgZnVuY3Rpb24gcmV0dXJuIGl0XG4gICAgaWYgKHR5cGVvZiB0aGlzLnJvd0hlaWdodCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgcmV0dXJuIHRoaXMucm93SGVpZ2h0KHJvdyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMucm93SGVpZ2h0IGFzIG51bWJlcjtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0gZ3JvdXAgdGhlIGdyb3VwIHdpdGggYWxsIHJvd3NcbiAgICovXG4gIGdldEdyb3VwSGVpZ2h0KGdyb3VwOiBhbnkpOiBudW1iZXIge1xuICAgIGxldCByb3dIZWlnaHQgPSAwO1xuXG4gICAgaWYgKGdyb3VwLnZhbHVlKSB7XG4gICAgICBmb3IgKGxldCBpbmRleCA9IDA7IGluZGV4IDwgZ3JvdXAudmFsdWUubGVuZ3RoOyBpbmRleCsrKSB7XG4gICAgICAgIHJvd0hlaWdodCArPSB0aGlzLmdldFJvd0FuZERldGFpbEhlaWdodChncm91cC52YWx1ZVtpbmRleF0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiByb3dIZWlnaHQ7XG4gIH1cblxuICAvKipcbiAgICogQ2FsY3VsYXRlIHJvdyBoZWlnaHQgYmFzZWQgb24gdGhlIGV4cGFuZGVkIHN0YXRlIG9mIHRoZSByb3cuXG4gICAqL1xuICBnZXRSb3dBbmREZXRhaWxIZWlnaHQocm93OiBhbnkpOiBudW1iZXIge1xuICAgIGxldCByb3dIZWlnaHQgPSB0aGlzLmdldFJvd0hlaWdodChyb3cpO1xuICAgIGNvbnN0IGV4cGFuZGVkID0gdGhpcy5nZXRSb3dFeHBhbmRlZChyb3cpO1xuXG4gICAgLy8gQWRkaW5nIGRldGFpbCByb3cgaGVpZ2h0IGlmIGl0cyBleHBhbmRlZC5cbiAgICBpZiAoZXhwYW5kZWQpIHtcbiAgICAgIHJvd0hlaWdodCArPSB0aGlzLmdldERldGFpbFJvd0hlaWdodChyb3cpO1xuICAgIH1cblxuICAgIHJldHVybiByb3dIZWlnaHQ7XG4gIH1cblxuICAvKipcbiAgICogR2V0IHRoZSBoZWlnaHQgb2YgdGhlIGRldGFpbCByb3cuXG4gICAqL1xuICBnZXREZXRhaWxSb3dIZWlnaHQgPSAocm93PzogYW55LCBpbmRleD86IGFueSk6IG51bWJlciA9PiB7XG4gICAgaWYgKCF0aGlzLnJvd0RldGFpbCkge1xuICAgICAgcmV0dXJuIDA7XG4gICAgfVxuICAgIGNvbnN0IHJvd0hlaWdodCA9IHRoaXMucm93RGV0YWlsLnJvd0hlaWdodDtcbiAgICByZXR1cm4gdHlwZW9mIHJvd0hlaWdodCA9PT0gJ2Z1bmN0aW9uJyA/IHJvd0hlaWdodChyb3csIGluZGV4KSA6IChyb3dIZWlnaHQgYXMgbnVtYmVyKTtcbiAgfTtcblxuICAvKipcbiAgICogQ2FsY3VsYXRlcyB0aGUgc3R5bGVzIGZvciB0aGUgcm93IHNvIHRoYXQgdGhlIHJvd3MgY2FuIGJlIG1vdmVkIGluIDJEIHNwYWNlXG4gICAqIGR1cmluZyB2aXJ0dWFsIHNjcm9sbCBpbnNpZGUgdGhlIERPTS4gICBJbiB0aGUgYmVsb3cgY2FzZSB0aGUgWSBwb3NpdGlvbiBpc1xuICAgKiBtYW5pcHVsYXRlZC4gICBBcyBhbiBleGFtcGxlLCBpZiB0aGUgaGVpZ2h0IG9mIHJvdyAwIGlzIDMwIHB4IGFuZCByb3cgMSBpc1xuICAgKiAxMDAgcHggdGhlbiBmb2xsb3dpbmcgc3R5bGVzIGFyZSBnZW5lcmF0ZWQ6XG4gICAqXG4gICAqIHRyYW5zZm9ybTogdHJhbnNsYXRlM2QoMHB4LCAwcHgsIDBweCk7ICAgIC0+ICByb3cwXG4gICAqIHRyYW5zZm9ybTogdHJhbnNsYXRlM2QoMHB4LCAzMHB4LCAwcHgpOyAgIC0+ICByb3cxXG4gICAqIHRyYW5zZm9ybTogdHJhbnNsYXRlM2QoMHB4LCAxMzBweCwgMHB4KTsgIC0+ICByb3cyXG4gICAqXG4gICAqIFJvdyBoZWlnaHRzIGhhdmUgdG8gYmUgY2FsY3VsYXRlZCBiYXNlZCBvbiB0aGUgcm93IGhlaWdodHMgY2FjaGUgYXMgd2Ugd29udFxuICAgKiBiZSBhYmxlIHRvIGRldGVybWluZSB3aGljaCByb3cgaXMgb2Ygd2hhdCBoZWlnaHQgYmVmb3JlIGhhbmQuICBJbiB0aGUgYWJvdmVcbiAgICogY2FzZSB0aGUgcG9zaXRpb25ZIG9mIHRoZSB0cmFuc2xhdGUzZCBmb3Igcm93MiB3b3VsZCBiZSB0aGUgc3VtIG9mIGFsbCB0aGVcbiAgICogaGVpZ2h0cyBvZiB0aGUgcm93cyBiZWZvcmUgaXQgKGkuZS4gcm93MCBhbmQgcm93MSkuXG4gICAqXG4gICAqIEBwYXJhbSByb3dzIHRoZSByb3cgdGhhdCBuZWVkcyB0byBiZSBwbGFjZWQgaW4gdGhlIDJEIHNwYWNlLlxuICAgKiBAcmV0dXJucyB0aGUgQ1NTMyBzdHlsZSB0byBiZSBhcHBsaWVkXG4gICAqXG4gICAqIEBtZW1iZXJPZiBEYXRhVGFibGVCb2R5Q29tcG9uZW50XG4gICAqL1xuICBnZXRSb3dzU3R5bGVzKHJvd3M6IGFueSk6IGFueSB7XG4gICAgY29uc3Qgc3R5bGVzOiBhbnkgPSB7fTtcblxuICAgIC8vIG9ubHkgYWRkIHN0eWxlcyBmb3IgdGhlIGdyb3VwIGlmIHRoZXJlIGlzIGEgZ3JvdXBcbiAgICBpZiAodGhpcy5ncm91cGVkUm93cykge1xuICAgICAgc3R5bGVzLndpZHRoID0gdGhpcy5jb2x1bW5Hcm91cFdpZHRocy50b3RhbDtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5zY3JvbGxiYXJWICYmIHRoaXMudmlydHVhbGl6YXRpb24pIHtcbiAgICAgIGxldCBpZHggPSAwO1xuXG4gICAgICBpZiAodGhpcy5ncm91cGVkUm93cykge1xuICAgICAgICAvLyBHZXQgdGhlIGxhdGVzdCByb3cgcm93aW5kZXggaW4gYSBncm91cFxuICAgICAgICBjb25zdCByb3cgPSByb3dzW3Jvd3MubGVuZ3RoIC0gMV07XG4gICAgICAgIGlkeCA9IHJvdyA/IHRoaXMuZ2V0Um93SW5kZXgocm93KSA6IDA7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpZHggPSB0aGlzLmdldFJvd0luZGV4KHJvd3MpO1xuICAgICAgfVxuXG4gICAgICAvLyBjb25zdCBwb3MgPSBpZHggKiByb3dIZWlnaHQ7XG4gICAgICAvLyBUaGUgcG9zaXRpb24gb2YgdGhpcyByb3cgd291bGQgYmUgdGhlIHN1bSBvZiBhbGwgcm93IGhlaWdodHNcbiAgICAgIC8vIHVudGlsIHRoZSBwcmV2aW91cyByb3cgcG9zaXRpb24uXG4gICAgICBjb25zdCBwb3MgPSB0aGlzLnJvd0hlaWdodHNDYWNoZS5xdWVyeShpZHggLSAxKTtcblxuICAgICAgdHJhbnNsYXRlWFkoc3R5bGVzLCAwLCBwb3MpO1xuICAgIH1cblxuICAgIHJldHVybiBzdHlsZXM7XG4gIH1cblxuICAvKipcbiAgICogQ2FsY3VsYXRlIGJvdHRvbSBzdW1tYXJ5IHJvdyBvZmZzZXQgZm9yIHNjcm9sbGJhciBtb2RlLlxuICAgKiBGb3IgbW9yZSBpbmZvcm1hdGlvbiBhYm91dCBjYWNoZSBhbmQgb2Zmc2V0IGNhbGN1bGF0aW9uXG4gICAqIHNlZSBkZXNjcmlwdGlvbiBmb3IgYGdldFJvd3NTdHlsZXNgIG1ldGhvZFxuICAgKlxuICAgKiBAcmV0dXJucyB0aGUgQ1NTMyBzdHlsZSB0byBiZSBhcHBsaWVkXG4gICAqXG4gICAqIEBtZW1iZXJPZiBEYXRhVGFibGVCb2R5Q29tcG9uZW50XG4gICAqL1xuICBnZXRCb3R0b21TdW1tYXJ5Um93U3R5bGVzKCk6IGFueSB7XG4gICAgaWYgKCF0aGlzLnNjcm9sbGJhclYgfHwgIXRoaXMucm93cyB8fCAhdGhpcy5yb3dzLmxlbmd0aCkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgY29uc3Qgc3R5bGVzID0geyBwb3NpdGlvbjogJ2Fic29sdXRlJyB9O1xuICAgIGNvbnN0IHBvcyA9IHRoaXMucm93SGVpZ2h0c0NhY2hlLnF1ZXJ5KHRoaXMucm93cy5sZW5ndGggLSAxKTtcblxuICAgIHRyYW5zbGF0ZVhZKHN0eWxlcywgMCwgcG9zKTtcblxuICAgIHJldHVybiBzdHlsZXM7XG4gIH1cblxuICAvKipcbiAgICogSGlkZXMgdGhlIGxvYWRpbmcgaW5kaWNhdG9yXG4gICAqL1xuICBoaWRlSW5kaWNhdG9yKCk6IHZvaWQge1xuICAgIHNldFRpbWVvdXQoKCkgPT4gKHRoaXMubG9hZGluZ0luZGljYXRvciA9IGZhbHNlKSwgNTAwKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBVcGRhdGVzIHRoZSBpbmRleCBvZiB0aGUgcm93cyBpbiB0aGUgdmlld3BvcnRcbiAgICovXG4gIHVwZGF0ZUluZGV4ZXMoKTogdm9pZCB7XG4gICAgbGV0IGZpcnN0ID0gMDtcbiAgICBsZXQgbGFzdCA9IDA7XG5cbiAgICBpZiAodGhpcy5zY3JvbGxiYXJWKSB7XG4gICAgICBpZiAodGhpcy52aXJ0dWFsaXphdGlvbikge1xuICAgICAgICAvLyBDYWxjdWxhdGlvbiBvZiB0aGUgZmlyc3QgYW5kIGxhc3QgaW5kZXhlcyB3aWxsIGJlIGJhc2VkIG9uIHdoZXJlIHRoZVxuICAgICAgICAvLyBzY3JvbGxZIHBvc2l0aW9uIHdvdWxkIGJlIGF0LiAgVGhlIGxhc3QgaW5kZXggd291bGQgYmUgdGhlIG9uZVxuICAgICAgICAvLyB0aGF0IHNob3dzIHVwIGluc2lkZSB0aGUgdmlldyBwb3J0IHRoZSBsYXN0LlxuICAgICAgICBjb25zdCBoZWlnaHQgPSBwYXJzZUludCh0aGlzLmJvZHlIZWlnaHQsIDApO1xuICAgICAgICBmaXJzdCA9IHRoaXMucm93SGVpZ2h0c0NhY2hlLmdldFJvd0luZGV4KHRoaXMub2Zmc2V0WSk7XG4gICAgICAgIGxhc3QgPSB0aGlzLnJvd0hlaWdodHNDYWNoZS5nZXRSb3dJbmRleChoZWlnaHQgKyB0aGlzLm9mZnNldFkpICsgMTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIElmIHZpcnR1YWwgcm93cyBhcmUgbm90IG5lZWRlZFxuICAgICAgICAvLyBXZSByZW5kZXIgYWxsIGluIG9uZSBnb1xuICAgICAgICBmaXJzdCA9IDA7XG4gICAgICAgIGxhc3QgPSB0aGlzLnJvd0NvdW50O1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAvLyBUaGUgc2VydmVyIGlzIGhhbmRsaW5nIHBhZ2luZyBhbmQgd2lsbCBwYXNzIGFuIGFycmF5IHRoYXQgYmVnaW5zIHdpdGggdGhlXG4gICAgICAvLyBlbGVtZW50IGF0IGEgc3BlY2lmaWVkIG9mZnNldC4gIGZpcnN0IHNob3VsZCBhbHdheXMgYmUgMCB3aXRoIGV4dGVybmFsIHBhZ2luZy5cbiAgICAgIGlmICghdGhpcy5leHRlcm5hbFBhZ2luZykge1xuICAgICAgICBmaXJzdCA9IE1hdGgubWF4KHRoaXMub2Zmc2V0ICogdGhpcy5wYWdlU2l6ZSwgMCk7XG4gICAgICB9XG4gICAgICBsYXN0ID0gTWF0aC5taW4oZmlyc3QgKyB0aGlzLnBhZ2VTaXplLCB0aGlzLnJvd0NvdW50KTtcbiAgICB9XG5cbiAgICB0aGlzLmluZGV4ZXMgPSB7IGZpcnN0LCBsYXN0IH07XG4gIH1cblxuICAvKipcbiAgICogUmVmcmVzaGVzIHRoZSBmdWxsIFJvdyBIZWlnaHQgY2FjaGUuICBTaG91bGQgYmUgdXNlZFxuICAgKiB3aGVuIHRoZSBlbnRpcmUgcm93IGFycmF5IHN0YXRlIGhhcyBjaGFuZ2VkLlxuICAgKi9cbiAgcmVmcmVzaFJvd0hlaWdodENhY2hlKCk6IHZvaWQge1xuICAgIGlmICghdGhpcy5zY3JvbGxiYXJWIHx8ICh0aGlzLnNjcm9sbGJhclYgJiYgIXRoaXMudmlydHVhbGl6YXRpb24pKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gY2xlYXIgdGhlIHByZXZpb3VzIHJvdyBoZWlnaHQgY2FjaGUgaWYgYWxyZWFkeSBwcmVzZW50LlxuICAgIC8vIHRoaXMgaXMgdXNlZnVsIGR1cmluZyBzb3J0cywgZmlsdGVycyB3aGVyZSB0aGUgc3RhdGUgb2YgdGhlXG4gICAgLy8gcm93cyBhcnJheSBpcyBjaGFuZ2VkLlxuICAgIHRoaXMucm93SGVpZ2h0c0NhY2hlLmNsZWFyQ2FjaGUoKTtcblxuICAgIC8vIEluaXRpYWxpemUgdGhlIHRyZWUgb25seSBpZiB0aGVyZSBhcmUgcm93cyBpbnNpZGUgdGhlIHRyZWUuXG4gICAgaWYgKHRoaXMucm93cyAmJiB0aGlzLnJvd3MubGVuZ3RoKSB7XG4gICAgICBjb25zdCByb3dFeHBhbnNpb25zID0gbmV3IFNldCgpO1xuICAgICAgZm9yIChjb25zdCByb3cgb2YgdGhpcy5yb3dzKSB7XG4gICAgICAgIGlmICh0aGlzLmdldFJvd0V4cGFuZGVkKHJvdykpIHtcbiAgICAgICAgICByb3dFeHBhbnNpb25zLmFkZChyb3cpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHRoaXMucm93SGVpZ2h0c0NhY2hlLmluaXRDYWNoZSh7XG4gICAgICAgIHJvd3M6IHRoaXMucm93cyxcbiAgICAgICAgcm93SGVpZ2h0OiB0aGlzLnJvd0hlaWdodCxcbiAgICAgICAgZGV0YWlsUm93SGVpZ2h0OiB0aGlzLmdldERldGFpbFJvd0hlaWdodCxcbiAgICAgICAgZXh0ZXJuYWxWaXJ0dWFsOiB0aGlzLnNjcm9sbGJhclYgJiYgdGhpcy5leHRlcm5hbFBhZ2luZyxcbiAgICAgICAgcm93Q291bnQ6IHRoaXMucm93Q291bnQsXG4gICAgICAgIHJvd0luZGV4ZXM6IHRoaXMucm93SW5kZXhlcyxcbiAgICAgICAgcm93RXhwYW5zaW9uc1xuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgdGhlIGluZGV4IGZvciB0aGUgdmlldyBwb3J0XG4gICAqL1xuICBnZXRBZGp1c3RlZFZpZXdQb3J0SW5kZXgoKTogbnVtYmVyIHtcbiAgICAvLyBDYXB0dXJlIHRoZSByb3cgaW5kZXggb2YgdGhlIGZpcnN0IHJvdyB0aGF0IGlzIHZpc2libGUgb24gdGhlIHZpZXdwb3J0LlxuICAgIC8vIElmIHRoZSBzY3JvbGwgYmFyIGlzIGp1c3QgYmVsb3cgdGhlIHJvdyB3aGljaCBpcyBoaWdobGlnaHRlZCB0aGVuIG1ha2UgdGhhdCBhcyB0aGVcbiAgICAvLyBmaXJzdCBpbmRleC5cbiAgICBjb25zdCB2aWV3UG9ydEZpcnN0Um93SW5kZXggPSB0aGlzLmluZGV4ZXMuZmlyc3Q7XG5cbiAgICBpZiAodGhpcy5zY3JvbGxiYXJWICYmIHRoaXMudmlydHVhbGl6YXRpb24pIHtcbiAgICAgIGNvbnN0IG9mZnNldFNjcm9sbCA9IHRoaXMucm93SGVpZ2h0c0NhY2hlLnF1ZXJ5KHZpZXdQb3J0Rmlyc3RSb3dJbmRleCAtIDEpO1xuICAgICAgcmV0dXJuIG9mZnNldFNjcm9sbCA8PSB0aGlzLm9mZnNldFkgPyB2aWV3UG9ydEZpcnN0Um93SW5kZXggLSAxIDogdmlld1BvcnRGaXJzdFJvd0luZGV4O1xuICAgIH1cblxuICAgIHJldHVybiB2aWV3UG9ydEZpcnN0Um93SW5kZXg7XG4gIH1cblxuICAvKipcbiAgICogVG9nZ2xlIHRoZSBFeHBhbnNpb24gb2YgdGhlIHJvdyBpLmUuIGlmIHRoZSByb3cgaXMgZXhwYW5kZWQgdGhlbiBpdCB3aWxsXG4gICAqIGNvbGxhcHNlIGFuZCB2aWNlIHZlcnNhLiAgIE5vdGUgdGhhdCB0aGUgZXhwYW5kZWQgc3RhdHVzIGlzIHN0b3JlZCBhc1xuICAgKiBhIHBhcnQgb2YgdGhlIHJvdyBvYmplY3QgaXRzZWxmIGFzIHdlIGhhdmUgdG8gcHJlc2VydmUgdGhlIGV4cGFuZGVkIHJvd1xuICAgKiBzdGF0dXMgaW4gY2FzZSBvZiBzb3J0aW5nIGFuZCBmaWx0ZXJpbmcgb2YgdGhlIHJvdyBzZXQuXG4gICAqL1xuICB0b2dnbGVSb3dFeHBhbnNpb24ocm93OiBhbnkpOiB2b2lkIHtcbiAgICAvLyBDYXB0dXJlIHRoZSByb3cgaW5kZXggb2YgdGhlIGZpcnN0IHJvdyB0aGF0IGlzIHZpc2libGUgb24gdGhlIHZpZXdwb3J0LlxuICAgIGNvbnN0IHZpZXdQb3J0Rmlyc3RSb3dJbmRleCA9IHRoaXMuZ2V0QWRqdXN0ZWRWaWV3UG9ydEluZGV4KCk7XG4gICAgY29uc3Qgcm93RXhwYW5kZWRJZHggPSB0aGlzLmdldFJvd0V4cGFuZGVkSWR4KHJvdywgdGhpcy5yb3dFeHBhbnNpb25zKTtcbiAgICBjb25zdCBleHBhbmRlZCA9IHJvd0V4cGFuZGVkSWR4ID4gLTE7XG5cbiAgICAvLyBJZiB0aGUgZGV0YWlsUm93SGVpZ2h0IGlzIGF1dG8gLS0+IG9ubHkgaW4gY2FzZSBvZiBub24tdmlydHVhbGl6ZWQgc2Nyb2xsXG4gICAgaWYgKHRoaXMuc2Nyb2xsYmFyViAmJiB0aGlzLnZpcnR1YWxpemF0aW9uKSB7XG4gICAgICBjb25zdCBkZXRhaWxSb3dIZWlnaHQgPSB0aGlzLmdldERldGFpbFJvd0hlaWdodChyb3cpICogKGV4cGFuZGVkID8gLTEgOiAxKTtcbiAgICAgIC8vIGNvbnN0IGlkeCA9IHRoaXMucm93SW5kZXhlcy5nZXQocm93KSB8fCAwO1xuICAgICAgY29uc3QgaWR4ID0gdGhpcy5nZXRSb3dJbmRleChyb3cpO1xuICAgICAgdGhpcy5yb3dIZWlnaHRzQ2FjaGUudXBkYXRlKGlkeCwgZGV0YWlsUm93SGVpZ2h0KTtcbiAgICB9XG5cbiAgICAvLyBVcGRhdGUgdGhlIHRvZ2dsZWQgcm93IGFuZCB1cGRhdGUgdGhpdmUgbmV2ZXJlIGhlaWdodHMgaW4gdGhlIGNhY2hlLlxuICAgIGlmIChleHBhbmRlZCkge1xuICAgICAgdGhpcy5yb3dFeHBhbnNpb25zLnNwbGljZShyb3dFeHBhbmRlZElkeCwgMSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMucm93RXhwYW5zaW9ucy5wdXNoKHJvdyk7XG4gICAgfVxuXG4gICAgdGhpcy5kZXRhaWxUb2dnbGUuZW1pdCh7XG4gICAgICByb3dzOiBbcm93XSxcbiAgICAgIGN1cnJlbnRJbmRleDogdmlld1BvcnRGaXJzdFJvd0luZGV4XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogRXhwYW5kL0NvbGxhcHNlIGFsbCB0aGUgcm93cyBubyBtYXR0ZXIgd2hhdCB0aGVpciBzdGF0ZSBpcy5cbiAgICovXG4gIHRvZ2dsZUFsbFJvd3MoZXhwYW5kZWQ6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICAvLyBjbGVhciBwcmV2IGV4cGFuc2lvbnNcbiAgICB0aGlzLnJvd0V4cGFuc2lvbnMgPSBbXTtcblxuICAgIC8vIENhcHR1cmUgdGhlIHJvdyBpbmRleCBvZiB0aGUgZmlyc3Qgcm93IHRoYXQgaXMgdmlzaWJsZSBvbiB0aGUgdmlld3BvcnQuXG4gICAgY29uc3Qgdmlld1BvcnRGaXJzdFJvd0luZGV4ID0gdGhpcy5nZXRBZGp1c3RlZFZpZXdQb3J0SW5kZXgoKTtcblxuICAgIGlmIChleHBhbmRlZCkge1xuICAgICAgZm9yIChjb25zdCByb3cgb2YgdGhpcy5yb3dzKSB7XG4gICAgICAgIHRoaXMucm93RXhwYW5zaW9ucy5wdXNoKHJvdyk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuc2Nyb2xsYmFyVikge1xuICAgICAgLy8gUmVmcmVzaCB0aGUgZnVsbCByb3cgaGVpZ2h0cyBjYWNoZSBzaW5jZSBldmVyeSByb3cgd2FzIGFmZmVjdGVkLlxuICAgICAgdGhpcy5yZWNhbGNMYXlvdXQoKTtcbiAgICB9XG5cbiAgICAvLyBFbWl0IGFsbCByb3dzIHRoYXQgaGF2ZSBiZWVuIGV4cGFuZGVkLlxuICAgIHRoaXMuZGV0YWlsVG9nZ2xlLmVtaXQoe1xuICAgICAgcm93czogdGhpcy5yb3dzLFxuICAgICAgY3VycmVudEluZGV4OiB2aWV3UG9ydEZpcnN0Um93SW5kZXhcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZWNhbGN1bGF0ZXMgdGhlIHRhYmxlXG4gICAqL1xuICByZWNhbGNMYXlvdXQoKTogdm9pZCB7XG4gICAgdGhpcy5yZWZyZXNoUm93SGVpZ2h0Q2FjaGUoKTtcbiAgICB0aGlzLnVwZGF0ZUluZGV4ZXMoKTtcbiAgICB0aGlzLnVwZGF0ZVJvd3MoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUcmFja3MgdGhlIGNvbHVtblxuICAgKi9cbiAgY29sdW1uVHJhY2tpbmdGbihpbmRleDogbnVtYmVyLCBjb2x1bW46IGFueSk6IGFueSB7XG4gICAgcmV0dXJuIGNvbHVtbi4kJGlkO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgdGhlIHJvdyBwaW5uaW5nIGdyb3VwIHN0eWxlc1xuICAgKi9cbiAgc3R5bGVzQnlHcm91cChncm91cDogc3RyaW5nKSB7XG4gICAgY29uc3Qgd2lkdGhzID0gdGhpcy5jb2x1bW5Hcm91cFdpZHRocztcbiAgICBjb25zdCBvZmZzZXRYID0gdGhpcy5vZmZzZXRYO1xuXG4gICAgY29uc3Qgc3R5bGVzID0ge1xuICAgICAgd2lkdGg6IGAke3dpZHRoc1tncm91cF19cHhgXG4gICAgfTtcblxuICAgIGlmIChncm91cCA9PT0gJ2xlZnQnKSB7XG4gICAgICB0cmFuc2xhdGVYWShzdHlsZXMsIG9mZnNldFgsIDApO1xuICAgIH0gZWxzZSBpZiAoZ3JvdXAgPT09ICdyaWdodCcpIHtcbiAgICAgIGNvbnN0IGJvZHlXaWR0aCA9IHBhcnNlSW50KHRoaXMuaW5uZXJXaWR0aCArICcnLCAwKTtcbiAgICAgIGNvbnN0IHRvdGFsRGlmZiA9IHdpZHRocy50b3RhbCAtIGJvZHlXaWR0aDtcbiAgICAgIGNvbnN0IG9mZnNldERpZmYgPSB0b3RhbERpZmYgLSBvZmZzZXRYO1xuICAgICAgY29uc3Qgb2Zmc2V0ID0gb2Zmc2V0RGlmZiAqIC0xO1xuICAgICAgdHJhbnNsYXRlWFkoc3R5bGVzLCBvZmZzZXQsIDApO1xuICAgIH1cblxuICAgIHJldHVybiBzdHlsZXM7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBpZiB0aGUgcm93IHdhcyBleHBhbmRlZCBhbmQgc2V0IGRlZmF1bHQgcm93IGV4cGFuc2lvbiB3aGVuIHJvdyBleHBhbnNpb24gaXMgZW1wdHlcbiAgICovXG4gIGdldFJvd0V4cGFuZGVkKHJvdzogYW55KTogYm9vbGVhbiB7XG4gICAgaWYgKHRoaXMucm93RXhwYW5zaW9ucy5sZW5ndGggPT09IDAgJiYgdGhpcy5ncm91cEV4cGFuc2lvbkRlZmF1bHQpIHtcbiAgICAgIGZvciAoY29uc3QgZ3JvdXAgb2YgdGhpcy5ncm91cGVkUm93cykge1xuICAgICAgICB0aGlzLnJvd0V4cGFuc2lvbnMucHVzaChncm91cCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuZ2V0Um93RXhwYW5kZWRJZHgocm93LCB0aGlzLnJvd0V4cGFuc2lvbnMpID4gLTE7XG4gIH1cblxuICBnZXRSb3dFeHBhbmRlZElkeChyb3c6IGFueSwgZXhwYW5kZWQ6IGFueVtdKTogbnVtYmVyIHtcbiAgICBpZiAoIWV4cGFuZGVkIHx8ICFleHBhbmRlZC5sZW5ndGgpIHJldHVybiAtMTtcblxuICAgIGNvbnN0IHJvd0lkID0gdGhpcy5yb3dJZGVudGl0eShyb3cpO1xuICAgIHJldHVybiBleHBhbmRlZC5maW5kSW5kZXgociA9PiB7XG4gICAgICBjb25zdCBpZCA9IHRoaXMucm93SWRlbnRpdHkocik7XG4gICAgICByZXR1cm4gaWQgPT09IHJvd0lkO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgdGhlIHJvdyBpbmRleCBnaXZlbiBhIHJvd1xuICAgKi9cbiAgZ2V0Um93SW5kZXgocm93OiBhbnkpOiBudW1iZXIge1xuICAgIHJldHVybiB0aGlzLnJvd0luZGV4ZXMuZ2V0KHJvdykgfHwgMDtcbiAgfVxuXG4gIG9uVHJlZUFjdGlvbihyb3c6IGFueSkge1xuICAgIHRoaXMudHJlZUFjdGlvbi5lbWl0KHsgcm93IH0pO1xuICB9XG59XG4iXX0=
|