@firestitch/list 13.1.1 → 13.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (159) hide show
  1. package/app/classes/actions-controller.d.ts +20 -20
  2. package/app/classes/columns-controller.d.ts +71 -71
  3. package/app/classes/data-controller.d.ts +91 -91
  4. package/app/classes/external-params-controller.d.ts +32 -32
  5. package/app/classes/index.d.ts +2 -2
  6. package/app/classes/list-controller.d.ts +194 -194
  7. package/app/classes/pagination-controller.d.ts +199 -198
  8. package/app/classes/persistance-controller.d.ts +10 -10
  9. package/app/classes/reorder-controller.d.ts +68 -68
  10. package/app/classes/selection-controller.d.ts +155 -155
  11. package/app/classes/sorting-controller.d.ts +70 -70
  12. package/app/components/body/body.component.d.ts +28 -28
  13. package/app/components/body/row/actions/actions.component.d.ts +36 -36
  14. package/app/components/body/row/cell/cell.component.d.ts +22 -22
  15. package/app/components/body/row/inline-action/inline-action.component.d.ts +13 -13
  16. package/app/components/body/row/menu-action/menu-action.component.d.ts +20 -20
  17. package/app/components/body/row/row.component.d.ts +85 -85
  18. package/app/components/customize-cols/customize-cols.component.d.ts +17 -17
  19. package/app/components/footer/footer-row/footer-cell/footer-cell.component.d.ts +7 -7
  20. package/app/components/footer/footer-row/footer-row.component.d.ts +14 -14
  21. package/app/components/footer/footer.component.d.ts +15 -15
  22. package/app/components/head/head-cell/head-cell.component.d.ts +14 -14
  23. package/app/components/head/head.component.d.ts +49 -49
  24. package/app/components/list/list.component.d.ts +128 -128
  25. package/app/components/loader/loader.component.d.ts +14 -14
  26. package/app/components/manage-saved-filters/manage-saved-filters.component.d.ts +13 -13
  27. package/app/components/pagination/pagination.component.d.ts +14 -14
  28. package/app/components/saved-filters/saved-filters.component.d.ts +15 -15
  29. package/app/components/status/status.component.d.ts +21 -21
  30. package/app/directives/cell/cell.directive.d.ts +8 -8
  31. package/app/directives/column/column.directive.d.ts +37 -37
  32. package/app/directives/content/content.directive.d.ts +5 -5
  33. package/app/directives/content-init/content-init.directive.d.ts +9 -9
  34. package/app/directives/draggable-list/draggable-list.directive.d.ts +95 -95
  35. package/app/directives/draggable-row/draggable-row.directive.d.ts +23 -23
  36. package/app/directives/empty-state/empty-state.directive.d.ts +5 -5
  37. package/app/directives/footer/footer.directive.d.ts +8 -8
  38. package/app/directives/group-expand-trigger/group-expand-trigger.directive.d.ts +10 -10
  39. package/app/directives/group-footer/group-footer.directive.d.ts +6 -6
  40. package/app/directives/group-header/group-header.directive.d.ts +6 -6
  41. package/app/directives/header/header.directive.d.ts +8 -8
  42. package/app/directives/heading/heading.directive.d.ts +5 -5
  43. package/app/directives/heading-container/heading-container.directive.d.ts +5 -5
  44. package/app/directives/index.d.ts +3 -3
  45. package/app/directives/subheading/subheading.directive.d.ts +5 -5
  46. package/app/enums/{button-type.enum.d.ts → action-type.enum.d.ts} +7 -7
  47. package/app/enums/page-change-type.enum.d.ts +4 -4
  48. package/app/enums/pagination-strategy.enum.d.ts +5 -5
  49. package/app/enums/row-type.enum.d.ts +6 -6
  50. package/app/enums/state.enum.d.ts +9 -9
  51. package/app/fs-list.module.d.ts +60 -60
  52. package/app/fs-list.providers.d.ts +3 -3
  53. package/app/interfaces/cellconfig.interface.d.ts +5 -5
  54. package/app/interfaces/column-config.interface.d.ts +2 -2
  55. package/app/interfaces/draggable-list.interface.d.ts +7 -7
  56. package/app/interfaces/external-params.interface.d.ts +13 -13
  57. package/app/interfaces/index.d.ts +4 -4
  58. package/app/interfaces/listconfig.interface.d.ts +252 -249
  59. package/app/interfaces/pagination-state.interface.d.ts +9 -9
  60. package/app/interfaces/pagination.interface.d.ts +13 -13
  61. package/app/interfaces/sorting-change-event.interface.d.ts +4 -4
  62. package/app/models/column-async-attribute.d.ts +5 -5
  63. package/app/models/column-attributes.d.ts +39 -39
  64. package/app/models/column.model.d.ts +61 -61
  65. package/app/models/row/base-row.d.ts +13 -13
  66. package/app/models/row/child-row.d.ts +12 -12
  67. package/app/models/row/group-footer-row.d.ts +10 -10
  68. package/app/models/row/group-row.d.ts +16 -16
  69. package/app/models/row/simple-row.d.ts +5 -5
  70. package/app/models/row-action.model.d.ts +29 -29
  71. package/app/models/row.d.ts +34 -34
  72. package/app/models/styleConfig.model.d.ts +31 -31
  73. package/app/pipes/action-label.d.ts +8 -8
  74. package/app/pipes/index.d.ts +1 -1
  75. package/app/services/group-expand-notifier.service.d.ts +11 -11
  76. package/esm2020/app/classes/actions-controller.mjs +55 -55
  77. package/esm2020/app/classes/columns-controller.mjs +205 -205
  78. package/esm2020/app/classes/data-controller.mjs +366 -366
  79. package/esm2020/app/classes/external-params-controller.mjs +146 -146
  80. package/esm2020/app/classes/index.mjs +3 -3
  81. package/esm2020/app/classes/list-controller.mjs +744 -744
  82. package/esm2020/app/classes/pagination-controller.mjs +491 -478
  83. package/esm2020/app/classes/persistance-controller.mjs +19 -19
  84. package/esm2020/app/classes/reorder-controller.mjs +181 -181
  85. package/esm2020/app/classes/selection-controller.mjs +467 -467
  86. package/esm2020/app/classes/sorting-controller.mjs +201 -201
  87. package/esm2020/app/components/body/body.component.mjs +63 -63
  88. package/esm2020/app/components/body/row/actions/actions.component.mjs +96 -96
  89. package/esm2020/app/components/body/row/cell/cell.component.mjs +107 -107
  90. package/esm2020/app/components/body/row/inline-action/inline-action.component.mjs +32 -32
  91. package/esm2020/app/components/body/row/menu-action/menu-action.component.mjs +45 -45
  92. package/esm2020/app/components/body/row/row.component.mjs +322 -322
  93. package/esm2020/app/components/customize-cols/customize-cols.component.mjs +68 -68
  94. package/esm2020/app/components/footer/footer-row/footer-cell/footer-cell.component.mjs +16 -16
  95. package/esm2020/app/components/footer/footer-row/footer-row.component.mjs +27 -27
  96. package/esm2020/app/components/footer/footer.component.mjs +30 -30
  97. package/esm2020/app/components/head/head-cell/head-cell.component.mjs +29 -29
  98. package/esm2020/app/components/head/head.component.mjs +102 -102
  99. package/esm2020/app/components/list/list.component.mjs +391 -391
  100. package/esm2020/app/components/loader/loader.component.mjs +40 -40
  101. package/esm2020/app/components/manage-saved-filters/manage-saved-filters.component.mjs +76 -76
  102. package/esm2020/app/components/pagination/pagination.component.mjs +37 -37
  103. package/esm2020/app/components/saved-filters/saved-filters.component.mjs +29 -29
  104. package/esm2020/app/components/status/status.component.mjs +66 -66
  105. package/esm2020/app/directives/cell/cell.directive.mjs +18 -18
  106. package/esm2020/app/directives/column/column.directive.mjs +120 -120
  107. package/esm2020/app/directives/content/content.directive.mjs +12 -12
  108. package/esm2020/app/directives/content-init/content-init.directive.mjs +21 -21
  109. package/esm2020/app/directives/draggable-list/draggable-list.directive.mjs +327 -327
  110. package/esm2020/app/directives/draggable-row/draggable-row.directive.mjs +77 -77
  111. package/esm2020/app/directives/empty-state/empty-state.directive.mjs +13 -13
  112. package/esm2020/app/directives/footer/footer.directive.mjs +18 -18
  113. package/esm2020/app/directives/group-expand-trigger/group-expand-trigger.directive.mjs +26 -26
  114. package/esm2020/app/directives/group-footer/group-footer.directive.mjs +13 -13
  115. package/esm2020/app/directives/group-header/group-header.directive.mjs +13 -13
  116. package/esm2020/app/directives/header/header.directive.mjs +18 -18
  117. package/esm2020/app/directives/heading/heading.directive.mjs +13 -13
  118. package/esm2020/app/directives/heading-container/heading-container.directive.mjs +13 -13
  119. package/esm2020/app/directives/index.mjs +4 -4
  120. package/esm2020/app/directives/subheading/subheading.directive.mjs +13 -13
  121. package/esm2020/app/enums/{button-type.enum.mjs → action-type.enum.mjs} +9 -9
  122. package/esm2020/app/enums/page-change-type.enum.mjs +6 -6
  123. package/esm2020/app/enums/pagination-strategy.enum.mjs +7 -7
  124. package/esm2020/app/enums/row-type.enum.mjs +7 -7
  125. package/esm2020/app/enums/state.enum.mjs +11 -11
  126. package/esm2020/app/fs-list.module.mjs +245 -245
  127. package/esm2020/app/fs-list.providers.mjs +4 -4
  128. package/esm2020/app/interfaces/cellconfig.interface.mjs +2 -2
  129. package/esm2020/app/interfaces/column-config.interface.mjs +1 -1
  130. package/esm2020/app/interfaces/draggable-list.interface.mjs +2 -2
  131. package/esm2020/app/interfaces/external-params.interface.mjs +2 -2
  132. package/esm2020/app/interfaces/index.mjs +5 -5
  133. package/esm2020/app/interfaces/listconfig.interface.mjs +2 -2
  134. package/esm2020/app/interfaces/pagination-state.interface.mjs +1 -1
  135. package/esm2020/app/interfaces/pagination.interface.mjs +2 -2
  136. package/esm2020/app/interfaces/sorting-change-event.interface.mjs +2 -2
  137. package/esm2020/app/models/column-async-attribute.mjs +13 -13
  138. package/esm2020/app/models/column-attributes.mjs +131 -131
  139. package/esm2020/app/models/column.model.mjs +163 -163
  140. package/esm2020/app/models/row/base-row.mjs +23 -23
  141. package/esm2020/app/models/row/child-row.mjs +28 -28
  142. package/esm2020/app/models/row/group-footer-row.mjs +20 -20
  143. package/esm2020/app/models/row/group-row.mjs +44 -44
  144. package/esm2020/app/models/row/simple-row.mjs +10 -10
  145. package/esm2020/app/models/row-action.model.mjs +90 -90
  146. package/esm2020/app/models/row.mjs +88 -88
  147. package/esm2020/app/models/styleConfig.model.mjs +75 -75
  148. package/esm2020/app/pipes/action-label.mjs +16 -16
  149. package/esm2020/app/pipes/index.mjs +1 -1
  150. package/esm2020/app/services/group-expand-notifier.service.mjs +26 -26
  151. package/esm2020/firestitch-list.mjs +4 -4
  152. package/esm2020/public_api.mjs +46 -46
  153. package/fesm2015/firestitch-list.mjs +5732 -5723
  154. package/fesm2015/firestitch-list.mjs.map +1 -1
  155. package/fesm2020/firestitch-list.mjs +5722 -5708
  156. package/fesm2020/firestitch-list.mjs.map +1 -1
  157. package/firestitch-list.d.ts +5 -5
  158. package/package.json +1 -1
  159. package/public_api.d.ts +41 -41
@@ -1,745 +1,745 @@
1
- import { ItemType, } from '@firestitch/filter';
2
- import { BehaviorSubject, combineLatest, EMPTY, from, Observable, of, Subject, } from 'rxjs';
3
- import { catchError, debounceTime, map, mapTo, shareReplay, switchMap, take, takeUntil, tap, } from 'rxjs/operators';
4
- import { cloneDeep } from 'lodash-es';
5
- import { PageChangeType } from '../enums/page-change-type.enum';
6
- import { FsListState } from '../enums/state.enum';
7
- import { SortingDirection } from '../models/column.model';
8
- import { RowAction } from '../models/row-action.model';
9
- import { StyleConfig } from '../models/styleConfig.model';
10
- import { ColumnsController } from './columns-controller';
11
- import { DataController } from './data-controller';
12
- import { ExternalParamsController } from './external-params-controller';
13
- import { ActionsController } from './index';
14
- import { PaginationController } from './pagination-controller';
15
- import { SelectionController } from './selection-controller';
16
- import { SortingController } from './sorting-controller';
17
- const showDeletedFilterKey = 'showDeleted';
18
- export class List {
19
- constructor(_el, _config = {}, _fsScroll, _selectionDialog, _router, _route, _persistance, _inDialog) {
20
- this._el = _el;
21
- this._config = _config;
22
- this._fsScroll = _fsScroll;
23
- this._selectionDialog = _selectionDialog;
24
- this._router = _router;
25
- this._route = _route;
26
- this._persistance = _persistance;
27
- this._inDialog = _inDialog;
28
- this.filters = [];
29
- this.paging = new PaginationController();
30
- this.columns = new ColumnsController();
31
- this.actions = new ActionsController();
32
- this.dataController = new DataController();
33
- this.sorting = new SortingController();
34
- this.filterConfig = null;
35
- this.loading$ = new BehaviorSubject(false);
36
- this.fetchComplete$ = new Subject();
37
- this.filtersReady$ = new Subject();
38
- this.status = true;
39
- this.chips = false;
40
- this.filterInput = true;
41
- this.queryParam = false;
42
- this.restoreMode = false;
43
- this.initialFetch = true;
44
- // Empty state
45
- this.emptyStateEnabled = false;
46
- this._destroy$ = new Subject();
47
- this._initialized$ = new BehaviorSubject(false);
48
- this._fetch$ = new Subject();
49
- this._filtersQuery = new BehaviorSubject(null);
50
- this._activeFiltersCount$ = this._filtersQuery
51
- .pipe(map((v) => Object.keys(v).length), shareReplay());
52
- this._initialize(_config);
53
- this._headerConfig = new StyleConfig(_config.header);
54
- this._groupCellConfig = new StyleConfig(_config.cell);
55
- this._cellConfig = new StyleConfig(_config.cell);
56
- this._footerConfig = new StyleConfig(_config.footer);
57
- this._initialized$.next(true);
58
- this.subscribe();
59
- if (this.initialFetch) {
60
- this.dataController.setOperation(FsListState.Load);
61
- this._fetch$.next();
62
- }
63
- }
64
- get fetch$() {
65
- return this._fetch$.asObservable();
66
- }
67
- get hasSavedFilters() {
68
- return !!this.filterConfig.savedFilters;
69
- }
70
- get filtersQuery() {
71
- return this._filtersQuery.getValue();
72
- }
73
- get activeFiltersCount$() {
74
- return this._activeFiltersCount$;
75
- }
76
- get destroy$() {
77
- return this._destroy$;
78
- }
79
- get initialized$() {
80
- return this._initialized$;
81
- }
82
- fetchRemote(query) {
83
- const options = {
84
- state: this.dataController.operation,
85
- };
86
- const result = this.fetchFn(query, options);
87
- return result instanceof Promise ? from(result) : result;
88
- }
89
- // public loadLocal() {
90
- // this.paging.updatePagingManual(this._rows);
91
- // const from = (this.paging.page - 1) * this.paging.limit;
92
- // const to = (this.paging.page === 1) ? this.paging.limit : this.paging.limit * this.paging.page;
93
- // const sliceOfRows = this._rows.slice(from, to);
94
- // this.data$.next(sliceOfRows);
95
- // }
96
- /**
97
- * Transform templates for using
98
- *
99
- * @param templates
100
- */
101
- tranformTemplatesToColumns(templates) {
102
- const defaultConfigs = {
103
- header: this._headerConfig,
104
- groupCell: this._groupCellConfig,
105
- cell: this._cellConfig,
106
- footer: this._footerConfig,
107
- };
108
- this.columns.setDefaults(defaultConfigs);
109
- this.columns.initializeColumns(templates);
110
- // Set sortBy default column
111
- this._updateSortingColumns();
112
- // Default sort by
113
- const externalSorting = this.externalParams.externalSorting;
114
- const initialSortConfig = externalSorting || this._config.sort;
115
- this.sorting.initialSortBy(initialSortConfig);
116
- if (externalSorting && !this.sorting.isDefined) {
117
- this.externalParams.clearSortingParams();
118
- console.warn('Not able to restore persisted sorting params.', externalSorting);
119
- }
120
- this._initFilters();
121
- this._initInfinityScroll();
122
- }
123
- reload() {
124
- this.loading$.next(true);
125
- this.dataController.setOperation(FsListState.Reload);
126
- if (this.fsScrollInstance) {
127
- this.paging.resetPaging();
128
- this.dataController.clearRows();
129
- this.fsScrollInstance.reload();
130
- }
131
- else {
132
- this._fetch$.next();
133
- }
134
- }
135
- /**
136
- * Watch page changes
137
- */
138
- subscribe() {
139
- this.paging.pageChanged$
140
- .pipe(takeUntil(this._destroy$))
141
- .subscribe((event) => {
142
- this.dataController.setOperation(FsListState.PageChange);
143
- // Remove all rows if limits was changed
144
- if (event.type === PageChangeType.LimitChanged && this.paging.hasPageStrategy) {
145
- this.dataController.clearRows();
146
- }
147
- if (this.paging.hasOffsetStrategy) {
148
- this.paging.updatePagination();
149
- if (this.selection) {
150
- this.selection.updateVisibleRecordsCount(this.paging.getVisibleRecords());
151
- this.selection.updateTotalRecordsCount(this.paging.records);
152
- this.selection.pageChanged(this.scrollable);
153
- }
154
- }
155
- if (!this.scrollable && !this.paging.loadMoreEnabled) {
156
- const contains = [].slice.call(document.querySelectorAll('.cdk-overlay-container')).some((overlay) => {
157
- return this._el.nativeElement.contains(overlay);
158
- });
159
- let el = this._el.nativeElement;
160
- if (!contains) {
161
- const rect = this._el.nativeElement.getBoundingClientRect();
162
- if ((Number(rect.top || 0) + window.pageYOffset) < window.innerHeight) {
163
- el = document.body;
164
- }
165
- }
166
- this.fetchComplete$.asObservable()
167
- .pipe(take(1), takeUntil(this._destroy$))
168
- .subscribe((event) => {
169
- if (event?.scrollIntoView ?? true) {
170
- el.scrollIntoView({ behavior: 'smooth' });
171
- }
172
- });
173
- }
174
- this._fetch$.next();
175
- });
176
- this.sorting.sortingChanged$
177
- .pipe(takeUntil(this._destroy$))
178
- .subscribe(() => {
179
- this.dataController.setOperation(FsListState.Sort);
180
- this.paging.page = 1;
181
- if (this.fsScrollInstance) {
182
- this.dataController.clearRows();
183
- this.fsScrollInstance.reload();
184
- }
185
- else {
186
- this._fetch$.next();
187
- }
188
- });
189
- this._listenVisibleColumnChanges();
190
- this._listenRowsRemove();
191
- this._listenFetch();
192
- }
193
- getData(trackBy) {
194
- let rowsData = this.dataController
195
- .visibleRowsData;
196
- if (trackBy) {
197
- rowsData = rowsData
198
- .filter(trackBy);
199
- }
200
- return rowsData
201
- .map((data) => {
202
- return cloneDeep(data);
203
- });
204
- }
205
- hasData(trackBy) {
206
- return this.dataController.visibleRowsData.some(trackBy);
207
- }
208
- /**
209
- * Toggle group mode status
210
- *
211
- * @param value
212
- */
213
- groupEnabled(value) {
214
- if (this.dataController.groupEnabled !== value) {
215
- this.dataController.groupEnabled = value;
216
- // Commented out because Ray wants to change group status in fetch map pipe
217
- // and it triggers extra requests
218
- // this.reload();
219
- }
220
- }
221
- destroy() {
222
- if (this._fsScrollSubscription) {
223
- this._fsScrollSubscription.unsubscribe();
224
- }
225
- if (this.paging) {
226
- this.paging.destroy();
227
- }
228
- if (this.sorting) {
229
- this.sorting.destroy();
230
- }
231
- if (this.selection) {
232
- this.selection.destroy();
233
- }
234
- if (this.filterConfig) {
235
- this.filterConfig = null;
236
- }
237
- if (this.externalParams) {
238
- this.externalParams.destroy();
239
- }
240
- this.columns.destroy();
241
- this._destroy$.next();
242
- this._destroy$.complete();
243
- this.dataController.destroy();
244
- }
245
- /**
246
- * Do initialization of table
247
- *
248
- * @param config
249
- */
250
- _initialize(config) {
251
- this._initVariables(config);
252
- this._initDefaultOptions(config);
253
- this._initRestore();
254
- this._initActions(config.actions);
255
- this._initPaging(config.paging, config.loadMore);
256
- this._initSelection(config.selection, this._selectionDialog);
257
- this._initGroups(config.group);
258
- this._initExternalParamsController();
259
- this._initializeData();
260
- }
261
- _initVariables(config) {
262
- this.autoFocus = config.autoFocus;
263
- this.rowHoverHighlight = config.rowHoverHighlight ?? true;
264
- this.heading = config.heading;
265
- this.trackBy = config.trackBy;
266
- this.subheading = config.subheading;
267
- this.rowActionsRaw = config.rowActions;
268
- this.rowClass = config.rowClass;
269
- this.rowEvents = config.rowEvents;
270
- this.restore = config.restore;
271
- this.persist = config.persist;
272
- this.filters = config.filters ?? [];
273
- this.filterInitCb = config.filterInit;
274
- this.filterChangeCb = config.filterChange;
275
- this.savedFilters = config.savedFilters;
276
- this.scrollable = config.scrollable;
277
- this.noResults = config.noResults;
278
- this.emptyState = config.emptyState;
279
- this.fetchFn = config.fetch;
280
- this.afterFetchFn = config.afterFetch;
281
- this.beforeFetchFn = config.beforeFetch;
282
- this.afterInit = config.afterInit;
283
- this.style = config.style;
284
- this.autoReload = config.autoReload;
285
- this.columns.initConfig(config.column);
286
- }
287
- /**
288
- * Just init options by default it it wasn't specified
289
- *
290
- * @param config
291
- */
292
- _initDefaultOptions(config) {
293
- // We should prevent initial fetch in cases when it will be fetched in any case
294
- // As ex. scrollable or filter will do fetch in any cases
295
- if (config.initialFetch === false || config.scrollable) { // TODO fixme after tsmodel version update
296
- this.initialFetch = false;
297
- }
298
- if (config.status === false) {
299
- this.status = false;
300
- }
301
- if (config.chips) {
302
- this.chips = config.chips;
303
- }
304
- if (config.filterInput === false) {
305
- this.filterInput = false;
306
- }
307
- if (this._inDialog) {
308
- this.queryParam = false;
309
- }
310
- else {
311
- this.queryParam = (config.queryParam === undefined)
312
- ? true
313
- : config.queryParam;
314
- }
315
- if (config.sorts) {
316
- this.sorting.initFakeColumns(config.sorts);
317
- }
318
- if (!config.trackBy) {
319
- this.trackBy = 'id';
320
- }
321
- if (config.afterContentInit) {
322
- this.afterContentInit = () => {
323
- config.afterContentInit(this.paging.query, this.dataController.visibleRows);
324
- };
325
- }
326
- }
327
- /**
328
- * Init restore row action and append Show Deleted option into filters
329
- */
330
- _initRestore() {
331
- if (this.restore) {
332
- const restoreAction = new RowAction({
333
- label: this.restore.menuLabel || 'Restore',
334
- menu: true,
335
- click: (row) => {
336
- this._restoreClick(this.restore.click, row);
337
- },
338
- restore: true,
339
- });
340
- if (!this.rowActionsRaw) {
341
- this.rowActionsRaw = [];
342
- }
343
- this.rowActionsRaw.push(restoreAction);
344
- if (!this.filters) {
345
- this.filters = [];
346
- }
347
- if (this.restore.filter !== false) {
348
- this.filters.push({
349
- name: showDeletedFilterKey,
350
- type: ItemType.Checkbox,
351
- label: this.restore.filterLabel || 'Show Deleted',
352
- });
353
- }
354
- }
355
- }
356
- /**
357
- * Init paging
358
- *
359
- * @param pagingConfig
360
- * @param loadMore
361
- */
362
- _initPaging(pagingConfig, loadMore) {
363
- this.paging.initWithConfig(pagingConfig, loadMore, !!this.scrollable);
364
- }
365
- /**
366
- * Split actions by categories
367
- */
368
- _initActions(actions) {
369
- if (actions) {
370
- this.actions.setActions(actions);
371
- }
372
- this.hasRowActions =
373
- (this.rowActionsRaw && this.rowActionsRaw.length > 0)
374
- || (this.groupActionsRaw && this.groupActionsRaw.length > 0);
375
- }
376
- _initSelection(selectionConfig, selectionDialog) {
377
- if (selectionConfig) {
378
- this.selection = new SelectionController(selectionConfig, this.trackBy, selectionDialog);
379
- this.selection.setRowsCallback(() => this.dataController.visibleRows);
380
- }
381
- }
382
- _initializeData() {
383
- this.dataController.setAdditionalConfigs({
384
- scrollable: !!this.scrollable,
385
- loadMoreEnabled: this.paging.loadMoreEnabled,
386
- });
387
- }
388
- _initGroups(groupConfig) {
389
- if (groupConfig) {
390
- this.dataController.setGroupConfig(groupConfig);
391
- this.groupActionsRaw = groupConfig.actions;
392
- }
393
- }
394
- _initExternalParamsController() {
395
- this.externalParams = new ExternalParamsController(this._router, this._route, this._persistance, this.paging, this.sorting, this.queryParam);
396
- }
397
- /**
398
- * Subscribe to fetch$ event with debounce
399
- */
400
- _listenFetch() {
401
- let fetch$ = this.fetch$;
402
- // Should wait until saved filters not loaded
403
- if (this.filters) {
404
- fetch$ = combineLatest([fetch$, this.filtersReady$])
405
- .pipe(map(([params]) => params));
406
- }
407
- fetch$
408
- .pipe(debounceTime(50), tap(() => {
409
- this.loading$.next(true);
410
- }), tap(() => {
411
- this.selection?.closeSelectionDialog();
412
- }), map((params) => {
413
- let query = { ...this.filtersQuery };
414
- if (this.paging.hasOffsetStrategy && params?.loadOffset) {
415
- query = Object.assign(query, this.paging.loadDeletedOffsetQuery);
416
- }
417
- else {
418
- const allRecordsRangeNeeded = (this.initialFetch
419
- || this.dataController.operation === FsListState.Reload) && this.paging.loadMoreEnabled;
420
- query = allRecordsRangeNeeded ? Object.assign(query, this.paging.loadMoreQuery) : Object.assign(query, this.paging.query);
421
- }
422
- if (this.sorting.sortingColumn) {
423
- Object.assign(query, {
424
- order: `${this.sorting.sortingColumn.name},${this.sorting.sortingColumn.direction}`,
425
- });
426
- }
427
- if (this.columns.configured) {
428
- query = {
429
- ...query,
430
- columns: this.columns.visibleColumnsNames,
431
- };
432
- }
433
- return { params, query };
434
- }), switchMap(({ params, query }) => {
435
- if (this.columns.loadFnConfigured && !this.columns.columnsFetched) {
436
- return this.columns.loadRemoteColumnConfigs()
437
- .pipe(mapTo({ params, query }));
438
- }
439
- return of({ params, query });
440
- }), switchMap(({ params, query }) => {
441
- if (this.beforeFetchFn) {
442
- return this.beforeFetchFn(query)
443
- .pipe(map((beforeFetchQuery) => ({ params, query: beforeFetchQuery })), catchError((error) => {
444
- console.error(error);
445
- return EMPTY;
446
- }));
447
- }
448
- return of({ params, query });
449
- }), switchMap(({ params, query }) => {
450
- const remoteFetch = this.fetchRemote(query)
451
- .pipe(catchError((error) => {
452
- console.error(error);
453
- return EMPTY;
454
- }));
455
- return combineLatest([of({ params, query }), remoteFetch]);
456
- }), catchError((error) => {
457
- console.error(error);
458
- return EMPTY;
459
- }), takeUntil(this._destroy$))
460
- .subscribe(([paramsQuery, response]) => {
461
- this.initialFetch = false;
462
- this._completeFetch(paramsQuery.params, paramsQuery.query, response);
463
- });
464
- }
465
- _listenRowsRemove() {
466
- this.dataController.rowsRemoved$
467
- .pipe(takeUntil(this._destroy$))
468
- .subscribe((rows) => {
469
- if (this.paging.enabled) {
470
- const removedCount = rows.length;
471
- if (this.paging.hasPageStrategy) {
472
- this._noDataPaginationUpdate(removedCount);
473
- }
474
- else {
475
- // Fetch more if has something for fetch
476
- if (this.dataController.hasData || this.paging.hasNextPage) {
477
- this.dataController.setOperation(FsListState.LoadMore);
478
- this.paging.removeRows(removedCount);
479
- this._fetch$.next({ loadOffset: true });
480
- }
481
- else {
482
- this._noDataPaginationUpdate(removedCount);
483
- }
484
- }
485
- }
486
- // Remove from selection
487
- if (this.selection) {
488
- rows.forEach((row) => {
489
- this.selection.removeRow(row.data);
490
- });
491
- }
492
- });
493
- }
494
- /**
495
- * Lister may have originally hidden columns, but visibility of those columns
496
- * can be changed programmaticaly in any time
497
- */
498
- _listenVisibleColumnChanges() {
499
- this.columns.visibleColumns$
500
- .pipe(takeUntil(this._destroy$))
501
- .subscribe(() => {
502
- this._updateSortingColumns();
503
- });
504
- }
505
- _initInfinityScroll() {
506
- if (this.fsScrollInstance) {
507
- return;
508
- }
509
- if (this.scrollable) {
510
- // Scrollable status by default
511
- if (this.scrollable.status === undefined) {
512
- this.scrollable.status = true;
513
- }
514
- this._fsScroll
515
- .component(this.scrollable.name)
516
- .pipe(takeUntil(this._destroy$))
517
- .subscribe((fsScrollInstance) => {
518
- this.fsScrollInstance = fsScrollInstance;
519
- this._fsScrollSubscription = fsScrollInstance
520
- .subscribe(() => {
521
- let startLoading = false;
522
- const operation = this.dataController.operation;
523
- // Initial loading if initialFetch equals false
524
- if (!this.initialFetch
525
- && !this.paging.initialized
526
- && operation !== FsListState.Reload) {
527
- this.dataController.setOperation(FsListState.Load);
528
- startLoading = true;
529
- }
530
- else if (operation === FsListState.Reload ||
531
- operation === FsListState.Filter ||
532
- operation === FsListState.Sort) {
533
- startLoading = true;
534
- }
535
- else if (this.paging.initialized && this.paging.hasNextPage) {
536
- // Loading if content has been scrolled
537
- startLoading = true;
538
- this.dataController.setOperation(FsListState.Load);
539
- this.paging.goNext();
540
- }
541
- if (startLoading) {
542
- this._fetch$.next();
543
- fsScrollInstance.loading();
544
- }
545
- });
546
- this.dataController.remoteRowsChange$
547
- .pipe(takeUntil(this._destroy$))
548
- .subscribe(() => {
549
- fsScrollInstance.loaded();
550
- });
551
- });
552
- }
553
- }
554
- /**
555
- * Update and watch filter changes
556
- */
557
- _initFilters() {
558
- if (this.filterConfig) {
559
- return;
560
- }
561
- const sortValues = this.sorting.makeSortingList();
562
- const sortConfig = this.sorting.sortingColumn
563
- ? { value: this.sorting.sortingColumn.name, direction: this.sorting.sortingColumn.direction }
564
- : null;
565
- // Config
566
- this.filterConfig = {
567
- persist: this.persist,
568
- items: this.filters || [],
569
- savedFilters: this.savedFilters,
570
- // inline: this.inlineFilters,
571
- actions: this.actions.actions,
572
- queryParam: this.queryParam,
573
- autofocus: this.autoFocus,
574
- sorts: sortValues,
575
- sort: sortConfig,
576
- chips: this.chips,
577
- autoReload: this.autoReload,
578
- init: this._filterInit.bind(this),
579
- change: this._filterChange.bind(this),
580
- reload: (this._config.reload ?? true) ? this.reload.bind(this) : null,
581
- sortChange: this._filterSort.bind(this),
582
- };
583
- }
584
- /**
585
- * Callback when Filter has been initialized
586
- *
587
- * @param filters
588
- */
589
- _filterInit(filters) {
590
- if (this.filterInitCb) {
591
- this.filterInitCb(filters);
592
- }
593
- this._filtersQuery.next(filters);
594
- this._checkRestoreFilter();
595
- }
596
- /**
597
- * Callback when Filter has been changed
598
- *
599
- * @param filterQuery
600
- * @param filterSort
601
- */
602
- _filterChange(filterQuery, filterSort) {
603
- if (this.filterChangeCb) {
604
- this.filterChangeCb(filterQuery, filterSort);
605
- }
606
- this._filtersQuery.next(filterQuery);
607
- this.restoreMode = false;
608
- // Restore option
609
- this._checkRestoreFilter();
610
- if (this.restore && this.restore.reload) {
611
- this.reload();
612
- }
613
- this.dataController.setOperation(FsListState.Filter);
614
- // Reset paging for request with correct offset
615
- this.paging.resetPaging();
616
- if (this.fsScrollInstance) {
617
- this.dataController.clearRows();
618
- this.fsScrollInstance.reload();
619
- }
620
- else {
621
- this._fetch$.next();
622
- }
623
- }
624
- _checkRestoreFilter() {
625
- // Restore option
626
- if (this.restore && this.filtersQuery[showDeletedFilterKey]) {
627
- delete this.filtersQuery[showDeletedFilterKey];
628
- Object.assign(this.filtersQuery, this.restore.query);
629
- this.restoreMode = true;
630
- }
631
- }
632
- // Callback when Filter sort has been changed
633
- _filterSort(filterQuery, filterSort) {
634
- if (filterSort) {
635
- this.sorting.sortByColumnWithName(filterSort.value);
636
- const sortDirection = filterSort.direction === 'asc' ? SortingDirection.asc : SortingDirection.desc;
637
- this.sorting.sortDirection(sortDirection);
638
- }
639
- else {
640
- // FIXME need to be refactored...
641
- this.sorting.sortingColumn = undefined;
642
- this.reload();
643
- }
644
- }
645
- _completeFetch(params, query, response) {
646
- if (!this.paging.page) {
647
- this.paging.page = 1;
648
- }
649
- if (response.paging) {
650
- const displayed = (Array.isArray(response.data) && response.data.length) || 0;
651
- this.paging.updatePaging(response.paging, displayed, this.dataController.operation === FsListState.LoadMore);
652
- }
653
- else if (this.paging.enabled) {
654
- console.log('%c FsList Warning ', 'color: white; background-color: #ffcc0b', 'Pagination does not configured properly. ' +
655
- 'Pagination is enabled, but http response does not contain "paging" field. ' +
656
- 'You have to set "paging: false" in config or add "paging" field to response.');
657
- }
658
- /// must be before selection, because seletion use records
659
- this.dataController.setRowsFromResponse(response.data);
660
- ///
661
- this._completeFetchUpdateSelecton(response);
662
- if (this.emptyState?.validate && this.emptyStateTemplate) {
663
- this.emptyStateEnabled = this.emptyState.validate(query, cloneDeep(this.dataController.visibleRowsData));
664
- }
665
- if (this.afterFetchFn) {
666
- this.afterFetchFn(query, this.dataController.visibleRowsData);
667
- }
668
- // case when have removed all results from last page
669
- if (this.dataController.visibleRows.length === 0
670
- && this.paging.page > 1
671
- && this.paging.page > this.paging.pages) {
672
- this.paging.goLast();
673
- }
674
- this.fetchComplete$.next({ scrollIntoView: params?.scrollIntoView });
675
- this.loading$.next(false);
676
- }
677
- _completeFetchUpdateSelecton(response) {
678
- // Update selection params
679
- if (this.selection) {
680
- if (this.paging.enabled) {
681
- this.selection.pageChanged(this.scrollable);
682
- this.selection.updateVisibleRecordsCount(this.paging.getVisibleRecords());
683
- this.selection.updateTotalRecordsCount(this.paging.records);
684
- }
685
- else {
686
- const count = response.paging && response.paging.records
687
- || Array.isArray(response.data) && response.data.length;
688
- this.selection.updateVisibleRecordsCount(count);
689
- this.selection.updateTotalRecordsCount(count);
690
- }
691
- this.selection.selectedRowsIntersection(this.dataController.visibleRowsData);
692
- }
693
- }
694
- /**
695
- * Will do some actions if you removed item and item was last on his own page
696
- *
697
- * Ex: if list has 3 pages and on third page you have only one item. And you just deleted this item.
698
- * You must go to second page, but if it was last page and you can't go back -> just reload
699
- *
700
- * @param deletedCount
701
- */
702
- _noDataPaginationUpdate(deletedCount) {
703
- if (!this.dataController.hasData) {
704
- if (this.paging.page > 1) {
705
- this.paging.goToPage(this.paging.page - 1 || 1);
706
- }
707
- else {
708
- this.reload();
709
- }
710
- }
711
- this.paging.records -= deletedCount;
712
- this.paging.updatePagination();
713
- if (this.dataController.hasData && this.selection) {
714
- this.selection.updateVisibleRecordsCount(this.dataController.visibleRowsCount);
715
- this.selection.updateTotalRecordsCount(this.paging.records);
716
- }
717
- }
718
- /**
719
- * Temporary solution, will do auto subscribe if was returned Observable.
720
- *
721
- * TODO: MOVE THIS PEACE OF CODE TO SPECIAL PLACE
722
- *
723
- * @param restoreClickCallback
724
- * @param row
725
- */
726
- _restoreClick(restoreClickCallback, row) {
727
- const restoreClickResult = restoreClickCallback(row);
728
- if (restoreClickResult instanceof Observable) {
729
- restoreClickResult
730
- .pipe(take(1), takeUntil(this._destroy$))
731
- .subscribe({
732
- next: () => this.reload(),
733
- });
734
- }
735
- }
736
- _updateSortingColumns() {
737
- this.sorting.clearSortableColumns();
738
- this.columns.columns
739
- .filter((column) => column.sortable && column.visible)
740
- .forEach((column) => {
741
- this.sorting.addSortableColumn(column);
742
- });
743
- }
744
- }
1
+ import { ItemType, } from '@firestitch/filter';
2
+ import { BehaviorSubject, combineLatest, EMPTY, from, Observable, of, Subject, } from 'rxjs';
3
+ import { catchError, debounceTime, map, mapTo, shareReplay, switchMap, take, takeUntil, tap, } from 'rxjs/operators';
4
+ import { cloneDeep } from 'lodash-es';
5
+ import { PageChangeType } from '../enums/page-change-type.enum';
6
+ import { FsListState } from '../enums/state.enum';
7
+ import { SortingDirection } from '../models/column.model';
8
+ import { RowAction } from '../models/row-action.model';
9
+ import { StyleConfig } from '../models/styleConfig.model';
10
+ import { ColumnsController } from './columns-controller';
11
+ import { DataController } from './data-controller';
12
+ import { ExternalParamsController } from './external-params-controller';
13
+ import { ActionsController } from './index';
14
+ import { PaginationController } from './pagination-controller';
15
+ import { SelectionController } from './selection-controller';
16
+ import { SortingController } from './sorting-controller';
17
+ const showDeletedFilterKey = 'showDeleted';
18
+ export class List {
19
+ constructor(_el, _config = {}, _fsScroll, _selectionDialog, _router, _route, _persistance, _inDialog) {
20
+ this._el = _el;
21
+ this._config = _config;
22
+ this._fsScroll = _fsScroll;
23
+ this._selectionDialog = _selectionDialog;
24
+ this._router = _router;
25
+ this._route = _route;
26
+ this._persistance = _persistance;
27
+ this._inDialog = _inDialog;
28
+ this.filters = [];
29
+ this.paging = new PaginationController();
30
+ this.columns = new ColumnsController();
31
+ this.actions = new ActionsController();
32
+ this.dataController = new DataController();
33
+ this.sorting = new SortingController();
34
+ this.filterConfig = null;
35
+ this.loading$ = new BehaviorSubject(false);
36
+ this.fetchComplete$ = new Subject();
37
+ this.filtersReady$ = new Subject();
38
+ this.status = true;
39
+ this.chips = false;
40
+ this.filterInput = true;
41
+ this.queryParam = false;
42
+ this.restoreMode = false;
43
+ this.initialFetch = true;
44
+ // Empty state
45
+ this.emptyStateEnabled = false;
46
+ this._destroy$ = new Subject();
47
+ this._initialized$ = new BehaviorSubject(false);
48
+ this._fetch$ = new Subject();
49
+ this._filtersQuery = new BehaviorSubject(null);
50
+ this._activeFiltersCount$ = this._filtersQuery
51
+ .pipe(map((v) => Object.keys(v).length), shareReplay());
52
+ this._initialize(_config);
53
+ this._headerConfig = new StyleConfig(_config.header);
54
+ this._groupCellConfig = new StyleConfig(_config.cell);
55
+ this._cellConfig = new StyleConfig(_config.cell);
56
+ this._footerConfig = new StyleConfig(_config.footer);
57
+ this._initialized$.next(true);
58
+ this.subscribe();
59
+ if (this.initialFetch) {
60
+ this.dataController.setOperation(FsListState.Load);
61
+ this._fetch$.next();
62
+ }
63
+ }
64
+ get fetch$() {
65
+ return this._fetch$.asObservable();
66
+ }
67
+ get hasSavedFilters() {
68
+ return !!this.filterConfig.savedFilters;
69
+ }
70
+ get filtersQuery() {
71
+ return this._filtersQuery.getValue();
72
+ }
73
+ get activeFiltersCount$() {
74
+ return this._activeFiltersCount$;
75
+ }
76
+ get destroy$() {
77
+ return this._destroy$;
78
+ }
79
+ get initialized$() {
80
+ return this._initialized$;
81
+ }
82
+ fetchRemote(query) {
83
+ const options = {
84
+ state: this.dataController.operation,
85
+ };
86
+ const result = this.fetchFn(query, options);
87
+ return result instanceof Promise ? from(result) : result;
88
+ }
89
+ // public loadLocal() {
90
+ // this.paging.updatePagingManual(this._rows);
91
+ // const from = (this.paging.page - 1) * this.paging.limit;
92
+ // const to = (this.paging.page === 1) ? this.paging.limit : this.paging.limit * this.paging.page;
93
+ // const sliceOfRows = this._rows.slice(from, to);
94
+ // this.data$.next(sliceOfRows);
95
+ // }
96
+ /**
97
+ * Transform templates for using
98
+ *
99
+ * @param templates
100
+ */
101
+ tranformTemplatesToColumns(templates) {
102
+ const defaultConfigs = {
103
+ header: this._headerConfig,
104
+ groupCell: this._groupCellConfig,
105
+ cell: this._cellConfig,
106
+ footer: this._footerConfig,
107
+ };
108
+ this.columns.setDefaults(defaultConfigs);
109
+ this.columns.initializeColumns(templates);
110
+ // Set sortBy default column
111
+ this._updateSortingColumns();
112
+ // Default sort by
113
+ const externalSorting = this.externalParams.externalSorting;
114
+ const initialSortConfig = externalSorting || this._config.sort;
115
+ this.sorting.initialSortBy(initialSortConfig);
116
+ if (externalSorting && !this.sorting.isDefined) {
117
+ this.externalParams.clearSortingParams();
118
+ console.warn('Not able to restore persisted sorting params.', externalSorting);
119
+ }
120
+ this._initFilters();
121
+ this._initInfinityScroll();
122
+ }
123
+ reload() {
124
+ this.loading$.next(true);
125
+ this.dataController.setOperation(FsListState.Reload);
126
+ if (this.fsScrollInstance) {
127
+ this.paging.resetPaging();
128
+ this.dataController.clearRows();
129
+ this.fsScrollInstance.reload();
130
+ }
131
+ else {
132
+ this._fetch$.next();
133
+ }
134
+ }
135
+ /**
136
+ * Watch page changes
137
+ */
138
+ subscribe() {
139
+ this.paging.pageChanged$
140
+ .pipe(takeUntil(this._destroy$))
141
+ .subscribe((event) => {
142
+ this.dataController.setOperation(FsListState.PageChange);
143
+ // Remove all rows if limits was changed
144
+ if (event.type === PageChangeType.LimitChanged && this.paging.hasPageStrategy) {
145
+ this.dataController.clearRows();
146
+ }
147
+ if (this.paging.hasOffsetStrategy) {
148
+ this.paging.updatePagination();
149
+ if (this.selection) {
150
+ this.selection.updateVisibleRecordsCount(this.paging.getVisibleRecords());
151
+ this.selection.updateTotalRecordsCount(this.paging.records);
152
+ this.selection.pageChanged(this.scrollable);
153
+ }
154
+ }
155
+ if (!this.scrollable && !this.paging.loadMoreEnabled) {
156
+ const contains = [].slice.call(document.querySelectorAll('.cdk-overlay-container')).some((overlay) => {
157
+ return this._el.nativeElement.contains(overlay);
158
+ });
159
+ let el = this._el.nativeElement;
160
+ if (!contains) {
161
+ const rect = this._el.nativeElement.getBoundingClientRect();
162
+ if ((Number(rect.top || 0) + window.pageYOffset) < window.innerHeight) {
163
+ el = document.body;
164
+ }
165
+ }
166
+ this.fetchComplete$.asObservable()
167
+ .pipe(take(1), takeUntil(this._destroy$))
168
+ .subscribe((event) => {
169
+ if (event?.scrollIntoView ?? true) {
170
+ el.scrollIntoView({ behavior: 'smooth' });
171
+ }
172
+ });
173
+ }
174
+ this._fetch$.next();
175
+ });
176
+ this.sorting.sortingChanged$
177
+ .pipe(takeUntil(this._destroy$))
178
+ .subscribe(() => {
179
+ this.dataController.setOperation(FsListState.Sort);
180
+ this.paging.page = 1;
181
+ if (this.fsScrollInstance) {
182
+ this.dataController.clearRows();
183
+ this.fsScrollInstance.reload();
184
+ }
185
+ else {
186
+ this._fetch$.next();
187
+ }
188
+ });
189
+ this._listenVisibleColumnChanges();
190
+ this._listenRowsRemove();
191
+ this._listenFetch();
192
+ }
193
+ getData(trackBy) {
194
+ let rowsData = this.dataController
195
+ .visibleRowsData;
196
+ if (trackBy) {
197
+ rowsData = rowsData
198
+ .filter(trackBy);
199
+ }
200
+ return rowsData
201
+ .map((data) => {
202
+ return cloneDeep(data);
203
+ });
204
+ }
205
+ hasData(trackBy) {
206
+ return this.dataController.visibleRowsData.some(trackBy);
207
+ }
208
+ /**
209
+ * Toggle group mode status
210
+ *
211
+ * @param value
212
+ */
213
+ groupEnabled(value) {
214
+ if (this.dataController.groupEnabled !== value) {
215
+ this.dataController.groupEnabled = value;
216
+ // Commented out because Ray wants to change group status in fetch map pipe
217
+ // and it triggers extra requests
218
+ // this.reload();
219
+ }
220
+ }
221
+ destroy() {
222
+ if (this._fsScrollSubscription) {
223
+ this._fsScrollSubscription.unsubscribe();
224
+ }
225
+ if (this.paging) {
226
+ this.paging.destroy();
227
+ }
228
+ if (this.sorting) {
229
+ this.sorting.destroy();
230
+ }
231
+ if (this.selection) {
232
+ this.selection.destroy();
233
+ }
234
+ if (this.filterConfig) {
235
+ this.filterConfig = null;
236
+ }
237
+ if (this.externalParams) {
238
+ this.externalParams.destroy();
239
+ }
240
+ this.columns.destroy();
241
+ this._destroy$.next();
242
+ this._destroy$.complete();
243
+ this.dataController.destroy();
244
+ }
245
+ /**
246
+ * Do initialization of table
247
+ *
248
+ * @param config
249
+ */
250
+ _initialize(config) {
251
+ this._initVariables(config);
252
+ this._initDefaultOptions(config);
253
+ this._initRestore();
254
+ this._initActions(config.actions);
255
+ this._initPaging(config.paging, config.loadMore);
256
+ this._initSelection(config.selection, this._selectionDialog);
257
+ this._initGroups(config.group);
258
+ this._initExternalParamsController();
259
+ this._initializeData();
260
+ }
261
+ _initVariables(config) {
262
+ this.autoFocus = config.autoFocus;
263
+ this.rowHoverHighlight = config.rowHoverHighlight ?? true;
264
+ this.heading = config.heading;
265
+ this.trackBy = config.trackBy;
266
+ this.subheading = config.subheading;
267
+ this.rowActionsRaw = config.rowActions;
268
+ this.rowClass = config.rowClass;
269
+ this.rowEvents = config.rowEvents;
270
+ this.restore = config.restore;
271
+ this.persist = config.persist;
272
+ this.filters = config.filters ?? [];
273
+ this.filterInitCb = config.filterInit;
274
+ this.filterChangeCb = config.filterChange;
275
+ this.savedFilters = config.savedFilters;
276
+ this.scrollable = config.scrollable;
277
+ this.noResults = config.noResults;
278
+ this.emptyState = config.emptyState;
279
+ this.fetchFn = config.fetch;
280
+ this.afterFetchFn = config.afterFetch;
281
+ this.beforeFetchFn = config.beforeFetch;
282
+ this.afterInit = config.afterInit;
283
+ this.style = config.style;
284
+ this.autoReload = config.autoReload;
285
+ this.columns.initConfig(config.column);
286
+ }
287
+ /**
288
+ * Just init options by default it it wasn't specified
289
+ *
290
+ * @param config
291
+ */
292
+ _initDefaultOptions(config) {
293
+ // We should prevent initial fetch in cases when it will be fetched in any case
294
+ // As ex. scrollable or filter will do fetch in any cases
295
+ if (config.initialFetch === false || config.scrollable) { // TODO fixme after tsmodel version update
296
+ this.initialFetch = false;
297
+ }
298
+ if (config.status === false) {
299
+ this.status = false;
300
+ }
301
+ if (config.chips) {
302
+ this.chips = config.chips;
303
+ }
304
+ if (config.filterInput === false) {
305
+ this.filterInput = false;
306
+ }
307
+ if (this._inDialog) {
308
+ this.queryParam = false;
309
+ }
310
+ else {
311
+ this.queryParam = (config.queryParam === undefined)
312
+ ? true
313
+ : config.queryParam;
314
+ }
315
+ if (config.sorts) {
316
+ this.sorting.initFakeColumns(config.sorts);
317
+ }
318
+ if (!config.trackBy) {
319
+ this.trackBy = 'id';
320
+ }
321
+ if (config.afterContentInit) {
322
+ this.afterContentInit = () => {
323
+ config.afterContentInit(this.paging.query, this.dataController.visibleRows);
324
+ };
325
+ }
326
+ }
327
+ /**
328
+ * Init restore row action and append Show Deleted option into filters
329
+ */
330
+ _initRestore() {
331
+ if (this.restore) {
332
+ const restoreAction = new RowAction({
333
+ label: this.restore.menuLabel || 'Restore',
334
+ menu: true,
335
+ click: (row) => {
336
+ this._restoreClick(this.restore.click, row);
337
+ },
338
+ restore: true,
339
+ });
340
+ if (!this.rowActionsRaw) {
341
+ this.rowActionsRaw = [];
342
+ }
343
+ this.rowActionsRaw.push(restoreAction);
344
+ if (!this.filters) {
345
+ this.filters = [];
346
+ }
347
+ if (this.restore.filter !== false) {
348
+ this.filters.push({
349
+ name: showDeletedFilterKey,
350
+ type: ItemType.Checkbox,
351
+ label: this.restore.filterLabel || 'Show Deleted',
352
+ });
353
+ }
354
+ }
355
+ }
356
+ /**
357
+ * Init paging
358
+ *
359
+ * @param pagingConfig
360
+ * @param loadMore
361
+ */
362
+ _initPaging(pagingConfig, loadMore) {
363
+ this.paging.initWithConfig(pagingConfig, loadMore, !!this.scrollable);
364
+ }
365
+ /**
366
+ * Split actions by categories
367
+ */
368
+ _initActions(actions) {
369
+ if (actions) {
370
+ this.actions.setActions(actions);
371
+ }
372
+ this.hasRowActions =
373
+ (this.rowActionsRaw && this.rowActionsRaw.length > 0)
374
+ || (this.groupActionsRaw && this.groupActionsRaw.length > 0);
375
+ }
376
+ _initSelection(selectionConfig, selectionDialog) {
377
+ if (selectionConfig) {
378
+ this.selection = new SelectionController(selectionConfig, this.trackBy, selectionDialog);
379
+ this.selection.setRowsCallback(() => this.dataController.visibleRows);
380
+ }
381
+ }
382
+ _initializeData() {
383
+ this.dataController.setAdditionalConfigs({
384
+ scrollable: !!this.scrollable,
385
+ loadMoreEnabled: this.paging.loadMoreEnabled,
386
+ });
387
+ }
388
+ _initGroups(groupConfig) {
389
+ if (groupConfig) {
390
+ this.dataController.setGroupConfig(groupConfig);
391
+ this.groupActionsRaw = groupConfig.actions;
392
+ }
393
+ }
394
+ _initExternalParamsController() {
395
+ this.externalParams = new ExternalParamsController(this._router, this._route, this._persistance, this.paging, this.sorting, this.queryParam);
396
+ }
397
+ /**
398
+ * Subscribe to fetch$ event with debounce
399
+ */
400
+ _listenFetch() {
401
+ let fetch$ = this.fetch$;
402
+ // Should wait until saved filters not loaded
403
+ if (this.filters) {
404
+ fetch$ = combineLatest([fetch$, this.filtersReady$])
405
+ .pipe(map(([params]) => params));
406
+ }
407
+ fetch$
408
+ .pipe(debounceTime(50), tap(() => {
409
+ this.loading$.next(true);
410
+ }), tap(() => {
411
+ this.selection?.closeSelectionDialog();
412
+ }), map((params) => {
413
+ let query = { ...this.filtersQuery };
414
+ if (this.paging.hasOffsetStrategy && params?.loadOffset) {
415
+ query = Object.assign(query, this.paging.loadDeletedOffsetQuery);
416
+ }
417
+ else {
418
+ const allRecordsRangeNeeded = (this.initialFetch
419
+ || this.dataController.operation === FsListState.Reload) && this.paging.loadMoreEnabled;
420
+ query = allRecordsRangeNeeded ? Object.assign(query, this.paging.loadMoreQuery) : Object.assign(query, this.paging.query);
421
+ }
422
+ if (this.sorting.sortingColumn) {
423
+ Object.assign(query, {
424
+ order: `${this.sorting.sortingColumn.name},${this.sorting.sortingColumn.direction}`,
425
+ });
426
+ }
427
+ if (this.columns.configured) {
428
+ query = {
429
+ ...query,
430
+ columns: this.columns.visibleColumnsNames,
431
+ };
432
+ }
433
+ return { params, query };
434
+ }), switchMap(({ params, query }) => {
435
+ if (this.columns.loadFnConfigured && !this.columns.columnsFetched) {
436
+ return this.columns.loadRemoteColumnConfigs()
437
+ .pipe(mapTo({ params, query }));
438
+ }
439
+ return of({ params, query });
440
+ }), switchMap(({ params, query }) => {
441
+ if (this.beforeFetchFn) {
442
+ return this.beforeFetchFn(query)
443
+ .pipe(map((beforeFetchQuery) => ({ params, query: beforeFetchQuery })), catchError((error) => {
444
+ console.error(error);
445
+ return EMPTY;
446
+ }));
447
+ }
448
+ return of({ params, query });
449
+ }), switchMap(({ params, query }) => {
450
+ const remoteFetch = this.fetchRemote(query)
451
+ .pipe(catchError((error) => {
452
+ console.error(error);
453
+ return EMPTY;
454
+ }));
455
+ return combineLatest([of({ params, query }), remoteFetch]);
456
+ }), catchError((error) => {
457
+ console.error(error);
458
+ return EMPTY;
459
+ }), takeUntil(this._destroy$))
460
+ .subscribe(([paramsQuery, response]) => {
461
+ this.initialFetch = false;
462
+ this._completeFetch(paramsQuery.params, paramsQuery.query, response);
463
+ });
464
+ }
465
+ _listenRowsRemove() {
466
+ this.dataController.rowsRemoved$
467
+ .pipe(takeUntil(this._destroy$))
468
+ .subscribe((rows) => {
469
+ if (this.paging.enabled) {
470
+ const removedCount = rows.length;
471
+ if (this.paging.hasPageStrategy) {
472
+ this._noDataPaginationUpdate(removedCount);
473
+ }
474
+ else {
475
+ // Fetch more if has something for fetch
476
+ if (this.dataController.hasData || this.paging.hasNextPage) {
477
+ this.dataController.setOperation(FsListState.LoadMore);
478
+ this.paging.removeRows(removedCount);
479
+ this._fetch$.next({ loadOffset: true });
480
+ }
481
+ else {
482
+ this._noDataPaginationUpdate(removedCount);
483
+ }
484
+ }
485
+ }
486
+ // Remove from selection
487
+ if (this.selection) {
488
+ rows.forEach((row) => {
489
+ this.selection.removeRow(row.data);
490
+ });
491
+ }
492
+ });
493
+ }
494
+ /**
495
+ * Lister may have originally hidden columns, but visibility of those columns
496
+ * can be changed programmaticaly in any time
497
+ */
498
+ _listenVisibleColumnChanges() {
499
+ this.columns.visibleColumns$
500
+ .pipe(takeUntil(this._destroy$))
501
+ .subscribe(() => {
502
+ this._updateSortingColumns();
503
+ });
504
+ }
505
+ _initInfinityScroll() {
506
+ if (this.fsScrollInstance) {
507
+ return;
508
+ }
509
+ if (this.scrollable) {
510
+ // Scrollable status by default
511
+ if (this.scrollable.status === undefined) {
512
+ this.scrollable.status = true;
513
+ }
514
+ this._fsScroll
515
+ .component(this.scrollable.name)
516
+ .pipe(takeUntil(this._destroy$))
517
+ .subscribe((fsScrollInstance) => {
518
+ this.fsScrollInstance = fsScrollInstance;
519
+ this._fsScrollSubscription = fsScrollInstance
520
+ .subscribe(() => {
521
+ let startLoading = false;
522
+ const operation = this.dataController.operation;
523
+ // Initial loading if initialFetch equals false
524
+ if (!this.initialFetch
525
+ && !this.paging.initialized
526
+ && operation !== FsListState.Reload) {
527
+ this.dataController.setOperation(FsListState.Load);
528
+ startLoading = true;
529
+ }
530
+ else if (operation === FsListState.Reload ||
531
+ operation === FsListState.Filter ||
532
+ operation === FsListState.Sort) {
533
+ startLoading = true;
534
+ }
535
+ else if (this.paging.initialized && this.paging.hasNextPage) {
536
+ // Loading if content has been scrolled
537
+ startLoading = true;
538
+ this.dataController.setOperation(FsListState.Load);
539
+ this.paging.goNext();
540
+ }
541
+ if (startLoading) {
542
+ this._fetch$.next();
543
+ fsScrollInstance.loading();
544
+ }
545
+ });
546
+ this.dataController.remoteRowsChange$
547
+ .pipe(takeUntil(this._destroy$))
548
+ .subscribe(() => {
549
+ fsScrollInstance.loaded();
550
+ });
551
+ });
552
+ }
553
+ }
554
+ /**
555
+ * Update and watch filter changes
556
+ */
557
+ _initFilters() {
558
+ if (this.filterConfig) {
559
+ return;
560
+ }
561
+ const sortValues = this.sorting.makeSortingList();
562
+ const sortConfig = this.sorting.sortingColumn
563
+ ? { value: this.sorting.sortingColumn.name, direction: this.sorting.sortingColumn.direction }
564
+ : null;
565
+ // Config
566
+ this.filterConfig = {
567
+ persist: this.persist,
568
+ items: this.filters || [],
569
+ savedFilters: this.savedFilters,
570
+ // inline: this.inlineFilters,
571
+ actions: this.actions.actions,
572
+ queryParam: this.queryParam,
573
+ autofocus: this.autoFocus,
574
+ sorts: sortValues,
575
+ sort: sortConfig,
576
+ chips: this.chips,
577
+ autoReload: this.autoReload,
578
+ init: this._filterInit.bind(this),
579
+ change: this._filterChange.bind(this),
580
+ reload: (this._config.reload ?? true) ? this.reload.bind(this) : null,
581
+ sortChange: this._filterSort.bind(this),
582
+ };
583
+ }
584
+ /**
585
+ * Callback when Filter has been initialized
586
+ *
587
+ * @param filters
588
+ */
589
+ _filterInit(filters) {
590
+ if (this.filterInitCb) {
591
+ this.filterInitCb(filters);
592
+ }
593
+ this._filtersQuery.next(filters);
594
+ this._checkRestoreFilter();
595
+ }
596
+ /**
597
+ * Callback when Filter has been changed
598
+ *
599
+ * @param filterQuery
600
+ * @param filterSort
601
+ */
602
+ _filterChange(filterQuery, filterSort) {
603
+ if (this.filterChangeCb) {
604
+ this.filterChangeCb(filterQuery, filterSort);
605
+ }
606
+ this._filtersQuery.next(filterQuery);
607
+ this.restoreMode = false;
608
+ // Restore option
609
+ this._checkRestoreFilter();
610
+ if (this.restore && this.restore.reload) {
611
+ this.reload();
612
+ }
613
+ this.dataController.setOperation(FsListState.Filter);
614
+ // Reset paging for request with correct offset
615
+ this.paging.resetPaging();
616
+ if (this.fsScrollInstance) {
617
+ this.dataController.clearRows();
618
+ this.fsScrollInstance.reload();
619
+ }
620
+ else {
621
+ this._fetch$.next();
622
+ }
623
+ }
624
+ _checkRestoreFilter() {
625
+ // Restore option
626
+ if (this.restore && this.filtersQuery[showDeletedFilterKey]) {
627
+ delete this.filtersQuery[showDeletedFilterKey];
628
+ Object.assign(this.filtersQuery, this.restore.query);
629
+ this.restoreMode = true;
630
+ }
631
+ }
632
+ // Callback when Filter sort has been changed
633
+ _filterSort(filterQuery, filterSort) {
634
+ if (filterSort) {
635
+ this.sorting.sortByColumnWithName(filterSort.value);
636
+ const sortDirection = filterSort.direction === 'asc' ? SortingDirection.asc : SortingDirection.desc;
637
+ this.sorting.sortDirection(sortDirection);
638
+ }
639
+ else {
640
+ // FIXME need to be refactored...
641
+ this.sorting.sortingColumn = undefined;
642
+ this.reload();
643
+ }
644
+ }
645
+ _completeFetch(params, query, response) {
646
+ if (!this.paging.page) {
647
+ this.paging.page = 1;
648
+ }
649
+ if (response.paging) {
650
+ const displayed = (Array.isArray(response.data) && response.data.length) || 0;
651
+ this.paging.updatePaging(response.paging, displayed, this.dataController.operation === FsListState.LoadMore);
652
+ }
653
+ else if (this.paging.enabled) {
654
+ console.log('%c FsList Warning ', 'color: white; background-color: #ffcc0b', 'Pagination does not configured properly. ' +
655
+ 'Pagination is enabled, but http response does not contain "paging" field. ' +
656
+ 'You have to set "paging: false" in config or add "paging" field to response.');
657
+ }
658
+ /// must be before selection, because seletion use records
659
+ this.dataController.setRowsFromResponse(response.data);
660
+ ///
661
+ this._completeFetchUpdateSelecton(response);
662
+ if (this.emptyState?.validate && this.emptyStateTemplate) {
663
+ this.emptyStateEnabled = this.emptyState.validate(query, cloneDeep(this.dataController.visibleRowsData));
664
+ }
665
+ if (this.afterFetchFn) {
666
+ this.afterFetchFn(query, this.dataController.visibleRowsData);
667
+ }
668
+ // case when have removed all results from last page
669
+ if (this.dataController.visibleRows.length === 0
670
+ && this.paging.page > 1
671
+ && this.paging.page > this.paging.pages) {
672
+ this.paging.goLast();
673
+ }
674
+ this.fetchComplete$.next({ scrollIntoView: params?.scrollIntoView });
675
+ this.loading$.next(false);
676
+ }
677
+ _completeFetchUpdateSelecton(response) {
678
+ // Update selection params
679
+ if (this.selection) {
680
+ if (this.paging.enabled) {
681
+ this.selection.pageChanged(this.scrollable);
682
+ this.selection.updateVisibleRecordsCount(this.paging.getVisibleRecords());
683
+ this.selection.updateTotalRecordsCount(this.paging.records);
684
+ }
685
+ else {
686
+ const count = response.paging && response.paging.records
687
+ || Array.isArray(response.data) && response.data.length;
688
+ this.selection.updateVisibleRecordsCount(count);
689
+ this.selection.updateTotalRecordsCount(count);
690
+ }
691
+ this.selection.selectedRowsIntersection(this.dataController.visibleRowsData);
692
+ }
693
+ }
694
+ /**
695
+ * Will do some actions if you removed item and item was last on his own page
696
+ *
697
+ * Ex: if list has 3 pages and on third page you have only one item. And you just deleted this item.
698
+ * You must go to second page, but if it was last page and you can't go back -> just reload
699
+ *
700
+ * @param deletedCount
701
+ */
702
+ _noDataPaginationUpdate(deletedCount) {
703
+ if (!this.dataController.hasData) {
704
+ if (this.paging.page > 1) {
705
+ this.paging.goToPage(this.paging.page - 1 || 1);
706
+ }
707
+ else {
708
+ this.reload();
709
+ }
710
+ }
711
+ this.paging.records -= deletedCount;
712
+ this.paging.updatePagination();
713
+ if (this.dataController.hasData && this.selection) {
714
+ this.selection.updateVisibleRecordsCount(this.dataController.visibleRowsCount);
715
+ this.selection.updateTotalRecordsCount(this.paging.records);
716
+ }
717
+ }
718
+ /**
719
+ * Temporary solution, will do auto subscribe if was returned Observable.
720
+ *
721
+ * TODO: MOVE THIS PEACE OF CODE TO SPECIAL PLACE
722
+ *
723
+ * @param restoreClickCallback
724
+ * @param row
725
+ */
726
+ _restoreClick(restoreClickCallback, row) {
727
+ const restoreClickResult = restoreClickCallback(row);
728
+ if (restoreClickResult instanceof Observable) {
729
+ restoreClickResult
730
+ .pipe(take(1), takeUntil(this._destroy$))
731
+ .subscribe({
732
+ next: () => this.reload(),
733
+ });
734
+ }
735
+ }
736
+ _updateSortingColumns() {
737
+ this.sorting.clearSortableColumns();
738
+ this.columns.columns
739
+ .filter((column) => column.sortable && column.visible)
740
+ .forEach((column) => {
741
+ this.sorting.addSortableColumn(column);
742
+ });
743
+ }
744
+ }
745
745
  //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGlzdC1jb250cm9sbGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2FwcC9jbGFzc2VzL2xpc3QtY29udHJvbGxlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFHQSxPQUFPLEVBQ2tFLFFBQVEsR0FDaEYsTUFBTSxvQkFBb0IsQ0FBQztBQUk1QixPQUFPLEVBQ0wsZUFBZSxFQUFFLGFBQWEsRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLFVBQVUsRUFBRSxFQUFFLEVBQUUsT0FBTyxHQUNyRSxNQUFNLE1BQU0sQ0FBQztBQUNkLE9BQU8sRUFDTCxVQUFVLEVBQUUsWUFBWSxFQUFFLEdBQUcsRUFBRSxLQUFLLEVBQUUsV0FBVyxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFLEdBQUcsR0FDbkYsTUFBTSxnQkFBZ0IsQ0FBQztBQUV4QixPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBRXRDLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUNoRSxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFzQmxELE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQzFELE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUN2RCxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFFMUQsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDekQsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQ25ELE9BQU8sRUFBRSx3QkFBd0IsRUFBRSxNQUFNLDhCQUE4QixDQUFDO0FBQ3hFLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLFNBQVMsQ0FBQztBQUM1QyxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUUvRCxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUM3RCxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUV6RCxNQUFNLG9CQUFvQixHQUFHLGFBQWEsQ0FBQztBQUczQyxNQUFNLE9BQU8sSUFBSTtJQW1FZixZQUNVLEdBQWUsRUFDZixVQUF3QixFQUFFLEVBQzFCLFNBQTBCLEVBQzFCLGdCQUFpQyxFQUNqQyxPQUFlLEVBQ2YsTUFBc0IsRUFDdEIsWUFBbUMsRUFDbkMsU0FBa0I7UUFQbEIsUUFBRyxHQUFILEdBQUcsQ0FBWTtRQUNmLFlBQU8sR0FBUCxPQUFPLENBQW1CO1FBQzFCLGNBQVMsR0FBVCxTQUFTLENBQWlCO1FBQzFCLHFCQUFnQixHQUFoQixnQkFBZ0IsQ0FBaUI7UUFDakMsWUFBTyxHQUFQLE9BQU8sQ0FBUTtRQUNmLFdBQU0sR0FBTixNQUFNLENBQWdCO1FBQ3RCLGlCQUFZLEdBQVosWUFBWSxDQUF1QjtRQUNuQyxjQUFTLEdBQVQsU0FBUyxDQUFTO1FBOURyQixZQUFPLEdBQUcsRUFBRSxDQUFDO1FBY2IsV0FBTSxHQUFHLElBQUksb0JBQW9CLEVBQUUsQ0FBQztRQUNwQyxZQUFPLEdBQUcsSUFBSSxpQkFBaUIsRUFBRSxDQUFDO1FBQ2xDLFlBQU8sR0FBRyxJQUFJLGlCQUFpQixFQUFFLENBQUM7UUFDbEMsbUJBQWMsR0FBRyxJQUFJLGNBQWMsRUFBRSxDQUFDO1FBQ3RDLFlBQU8sR0FBRyxJQUFJLGlCQUFpQixFQUFFLENBQUM7UUFHbEMsaUJBQVksR0FBaUIsSUFBSSxDQUFDO1FBQ2xDLGFBQVEsR0FBRyxJQUFJLGVBQWUsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUN0QyxtQkFBYyxHQUFHLElBQUksT0FBTyxFQUFnQyxDQUFDO1FBQzdELGtCQUFhLEdBQUcsSUFBSSxPQUFPLEVBQVEsQ0FBQztRQUNwQyxXQUFNLEdBQUcsSUFBSSxDQUFDO1FBQ2QsVUFBSyxHQUFHLEtBQUssQ0FBQztRQUNkLGdCQUFXLEdBQUcsSUFBSSxDQUFDO1FBQ25CLGVBQVUsR0FBRyxLQUFLLENBQUM7UUFDbkIsZ0JBQVcsR0FBRyxLQUFLLENBQUM7UUFHcEIsaUJBQVksR0FBRyxJQUFJLENBQUM7UUFFM0IsY0FBYztRQUNQLHNCQUFpQixHQUFHLEtBQUssQ0FBQztRQUt6QixjQUFTLEdBQUcsSUFBSSxPQUFPLEVBQUUsQ0FBQztRQUMxQixrQkFBYSxHQUFHLElBQUksZUFBZSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQzNDLFlBQU8sR0FBRyxJQUFJLE9BQU8sRUFBa0MsQ0FBQztRQUMvQyxrQkFBYSxHQUFHLElBQUksZUFBZSxDQUFzQixJQUFJLENBQUMsQ0FBQztRQUMvRCx5QkFBb0IsR0FBRyxJQUFJLENBQUMsYUFBYTthQUN2RCxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxFQUFFLFdBQVcsRUFBRSxDQUFDLENBQUM7UUFtQnhELElBQUksQ0FBQyxXQUFXLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDMUIsSUFBSSxDQUFDLGFBQWEsR0FBRyxJQUFJLFdBQVcsQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDckQsSUFBSSxDQUFDLGdCQUFnQixHQUFHLElBQUksV0FBVyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUN0RCxJQUFJLENBQUMsV0FBVyxHQUFHLElBQUksV0FBVyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNqRCxJQUFJLENBQUMsYUFBYSxHQUFHLElBQUksV0FBVyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUNyRCxJQUFJLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUM5QixJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7UUFFakIsSUFBSSxJQUFJLENBQUMsWUFBWSxFQUFFO1lBQ3JCLElBQUksQ0FBQyxjQUFjLENBQUMsWUFBWSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUNuRCxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxDQUFDO1NBQ3JCO0lBQ0gsQ0FBQztJQUVELElBQVcsTUFBTTtRQUNmLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxZQUFZLEVBQUUsQ0FBQztJQUNyQyxDQUFDO0lBRUQsSUFBVyxlQUFlO1FBQ3hCLE9BQU8sQ0FBQyxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsWUFBWSxDQUFDO0lBQzFDLENBQUM7SUFFRCxJQUFXLFlBQVk7UUFDckIsT0FBTyxJQUFJLENBQUMsYUFBYSxDQUFDLFFBQVEsRUFBRSxDQUFDO0lBQ3ZDLENBQUM7SUFFRCxJQUFXLG1CQUFtQjtRQUM1QixPQUFPLElBQUksQ0FBQyxvQkFBb0IsQ0FBQztJQUNuQyxDQUFDO0lBRUQsSUFBVyxRQUFRO1FBQ2pCLE9BQU8sSUFBSSxDQUFDLFNBQVMsQ0FBQztJQUN4QixDQUFDO0lBRUQsSUFBVyxZQUFZO1FBQ3JCLE9BQU8sSUFBSSxDQUFDLGFBQWEsQ0FBQztJQUM1QixDQUFDO0lBRU0sV0FBVyxDQUFDLEtBQUs7UUFDdEIsTUFBTSxPQUFPLEdBQXVCO1lBQ2xDLEtBQUssRUFBRSxJQUFJLENBQUMsY0FBYyxDQUFDLFNBQVM7U0FDckMsQ0FBQztRQUVGLE1BQU0sTUFBTSxHQUFRLElBQUksQ0FBQyxPQUFPLENBQUMsS0FBSyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBRWpELE9BQU8sTUFBTSxZQUFZLE9BQU8sQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUM7SUFDM0QsQ0FBQztJQUVELHVCQUF1QjtJQUN2QixnREFBZ0Q7SUFDaEQsNkRBQTZEO0lBQzdELG9HQUFvRztJQUNwRyxvREFBb0Q7SUFDcEQsa0NBQWtDO0lBQ2xDLElBQUk7SUFFSjs7OztPQUlHO0lBQ0ksMEJBQTBCLENBQUMsU0FBUztRQUN6QyxNQUFNLGNBQWMsR0FBRztZQUNyQixNQUFNLEVBQUUsSUFBSSxDQUFDLGFBQWE7WUFDMUIsU0FBUyxFQUFFLElBQUksQ0FBQyxnQkFBZ0I7WUFDaEMsSUFBSSxFQUFFLElBQUksQ0FBQyxXQUFXO1lBQ3RCLE1BQU0sRUFBRSxJQUFJLENBQUMsYUFBYTtTQUMzQixDQUFDO1FBRUYsSUFBSSxDQUFDLE9BQU8sQ0FBQyxXQUFXLENBQUMsY0FBYyxDQUFDLENBQUM7UUFDekMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxpQkFBaUIsQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUUxQyw0QkFBNEI7UUFDNUIsSUFBSSxDQUFDLHFCQUFxQixFQUFFLENBQUM7UUFFN0Isa0JBQWtCO1FBQ2xCLE1BQU0sZUFBZSxHQUFHLElBQUksQ0FBQyxjQUFjLENBQUMsZUFBZSxDQUFDO1FBQzVELE1BQU0saUJBQWlCLEdBQUcsZUFBZSxJQUFJLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDO1FBQy9ELElBQUksQ0FBQyxPQUFPLENBQUMsYUFBYSxDQUFDLGlCQUFpQixDQUFDLENBQUM7UUFFOUMsSUFBSSxlQUFlLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLFNBQVMsRUFBRTtZQUM5QyxJQUFJLENBQUMsY0FBYyxDQUFDLGtCQUFrQixFQUFFLENBQUM7WUFFekMsT0FBTyxDQUFDLElBQUksQ0FBQywrQ0FBK0MsRUFBRSxlQUFlLENBQUMsQ0FBQztTQUNoRjtRQUVELElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztRQUNwQixJQUFJLENBQUMsbUJBQW1CLEVBQUUsQ0FBQztJQUM3QixDQUFDO0lBRU0sTUFBTTtRQUNYLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBRXpCLElBQUksQ0FBQyxjQUFjLENBQUMsWUFBWSxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUVyRCxJQUFJLElBQUksQ0FBQyxnQkFBZ0IsRUFBRTtZQUN6QixJQUFJLENBQUMsTUFBTSxDQUFDLFdBQVcsRUFBRSxDQUFDO1lBQzFCLElBQUksQ0FBQyxjQUFjLENBQUMsU0FBUyxFQUFFLENBQUM7WUFDaEMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLE1BQU0sRUFBRSxDQUFDO1NBQ2hDO2FBQU07WUFDTCxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxDQUFDO1NBQ3JCO0lBQ0gsQ0FBQztJQUVEOztPQUVHO0lBQ0ksU0FBUztRQUNkLElBQUksQ0FBQyxNQUFNLENBQUMsWUFBWTthQUNyQixJQUFJLENBQ0gsU0FBUyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FDMUI7YUFDQSxTQUFTLENBQUMsQ0FBQyxLQUFpQixFQUFFLEVBQUU7WUFDL0IsSUFBSSxDQUFDLGNBQWMsQ0FBQyxZQUFZLENBQUMsV0FBVyxDQUFDLFVBQVUsQ0FBQyxDQUFDO1lBRXpELHdDQUF3QztZQUN4QyxJQUFJLEtBQUssQ0FBQyxJQUFJLEtBQUssY0FBYyxDQUFDLFlBQVksSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLGVBQWUsRUFBRTtnQkFDN0UsSUFBSSxDQUFDLGNBQWMsQ0FBQyxTQUFTLEVBQUUsQ0FBQzthQUNqQztZQUVELElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxpQkFBaUIsRUFBRTtnQkFDakMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO2dCQUUvQixJQUFJLElBQUksQ0FBQyxTQUFTLEVBQUU7b0JBQ2xCLElBQUksQ0FBQyxTQUFTLENBQUMseUJBQXlCLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxpQkFBaUIsRUFBRSxDQUFDLENBQUM7b0JBQzFFLElBQUksQ0FBQyxTQUFTLENBQUMsdUJBQXVCLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQztvQkFDNUQsSUFBSSxDQUFDLFNBQVMsQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDO2lCQUM3QzthQUNGO1lBRUQsSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLGVBQWUsRUFBRTtnQkFDcEQsTUFBTSxRQUFRLEdBQUcsRUFBRSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLGdCQUFnQixDQUFDLHdCQUF3QixDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxPQUFPLEVBQUUsRUFBRTtvQkFDbkcsT0FBTyxJQUFJLENBQUMsR0FBRyxDQUFDLGFBQWEsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUM7Z0JBQ2xELENBQUMsQ0FBQyxDQUFDO2dCQUVILElBQUksRUFBRSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsYUFBYSxDQUFDO2dCQUVoQyxJQUFJLENBQUMsUUFBUSxFQUFFO29CQUNiLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsYUFBYSxDQUFDLHFCQUFxQixFQUFFLENBQUM7b0JBQzVELElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsSUFBSSxDQUFDLENBQUMsR0FBRyxNQUFNLENBQUMsV0FBVyxDQUFDLEdBQUcsTUFBTSxDQUFDLFdBQVcsRUFBRTt3QkFDckUsRUFBRSxHQUFHLFFBQVEsQ0FBQyxJQUFJLENBQUM7cUJBQ3BCO2lCQUNGO2dCQUVELElBQUksQ0FBQyxjQUFjLENBQUMsWUFBWSxFQUFFO3FCQUMvQixJQUFJLENBQ0gsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUNQLFNBQVMsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQzFCO3FCQUNBLFNBQVMsQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFO29CQUNuQixJQUFHLEtBQUssRUFBRSxjQUFjLElBQUksSUFBSSxFQUFFO3dCQUNoQyxFQUFFLENBQUMsY0FBYyxDQUFDLEVBQUUsUUFBUSxFQUFFLFFBQVEsRUFBRSxDQUFDLENBQUM7cUJBQzNDO2dCQUNILENBQUMsQ0FBQyxDQUFDO2FBQ047WUFFRCxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxDQUFDO1FBQ3RCLENBQUMsQ0FBQyxDQUFDO1FBRUwsSUFBSSxDQUFDLE9BQU8sQ0FBQyxlQUFlO2FBQ3pCLElBQUksQ0FDSCxTQUFTLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUMxQjthQUNBLFNBQVMsQ0FBQyxHQUFHLEVBQUU7WUFDZCxJQUFJLENBQUMsY0FBYyxDQUFDLFlBQVksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDbkQsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLEdBQUcsQ0FBQyxDQUFDO1lBRXJCLElBQUksSUFBSSxDQUFDLGdCQUFnQixFQUFFO2dCQUN6QixJQUFJLENBQUMsY0FBYyxDQUFDLFNBQVMsRUFBRSxDQUFDO2dCQUNoQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsTUFBTSxFQUFFLENBQUM7YUFDaEM7aUJBQU07Z0JBQ0wsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsQ0FBQzthQUNyQjtRQUNILENBQUMsQ0FBQyxDQUFDO1FBRUwsSUFBSSxDQUFDLDJCQUEyQixFQUFFLENBQUM7UUFDbkMsSUFBSSxDQUFDLGlCQUFpQixFQUFFLENBQUM7UUFDekIsSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO0lBQ3RCLENBQUM7SUFFTSxPQUFPLENBQUMsT0FBeUI7UUFDdEMsSUFBSSxRQUFRLEdBQUcsSUFBSSxDQUFDLGNBQWM7YUFDL0IsZUFBZSxDQUFDO1FBRW5CLElBQUksT0FBTyxFQUFFO1lBQ1gsUUFBUSxHQUFHLFFBQVE7aUJBQ2hCLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQztTQUNwQjtRQUVELE9BQU8sUUFBUTthQUNaLEdBQUcsQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFO1lBQ1osT0FBTyxTQUFTLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDekIsQ0FBQyxDQUFDLENBQUM7SUFDUCxDQUFDO0lBRU0sT0FBTyxDQUFDLE9BQXdCO1FBQ3JDLE9BQU8sSUFBSSxDQUFDLGNBQWMsQ0FBQyxlQUFlLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQzNELENBQUM7SUFFRDs7OztPQUlHO0lBQ0ksWUFBWSxDQUFDLEtBQWM7UUFDaEMsSUFBSSxJQUFJLENBQUMsY0FBYyxDQUFDLFlBQVksS0FBSyxLQUFLLEVBQUU7WUFDOUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxZQUFZLEdBQUcsS0FBSyxDQUFDO1lBRXpDLDJFQUEyRTtZQUMzRSxpQ0FBaUM7WUFDakMsaUJBQWlCO1NBQ2xCO0lBQ0gsQ0FBQztJQUVNLE9BQU87UUFDWixJQUFJLElBQUksQ0FBQyxxQkFBcUIsRUFBRTtZQUM5QixJQUFJLENBQUMscUJBQXFCLENBQUMsV0FBVyxFQUFFLENBQUM7U0FDMUM7UUFFRCxJQUFJLElBQUksQ0FBQyxNQUFNLEVBQUU7WUFDZixJQUFJLENBQUMsTUFBTSxDQUFDLE9BQU8sRUFBRSxDQUFDO1NBQ3ZCO1FBRUQsSUFBSSxJQUFJLENBQUMsT0FBTyxFQUFFO1lBQ2hCLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLENBQUM7U0FDeEI7UUFFRCxJQUFJLElBQUksQ0FBQyxTQUFTLEVBQUU7WUFDbEIsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztTQUMxQjtRQUVELElBQUksSUFBSSxDQUFDLFlBQVksRUFBRTtZQUNyQixJQUFJLENBQUMsWUFBWSxHQUFHLElBQUksQ0FBQztTQUMxQjtRQUVELElBQUksSUFBSSxDQUFDLGNBQWMsRUFBRTtZQUN2QixJQUFJLENBQUMsY0FBYyxDQUFDLE9BQU8sRUFBRSxDQUFDO1NBQy9CO1FBRUQsSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUV2QixJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksRUFBRSxDQUFDO1FBQ3RCLElBQUksQ0FBQyxTQUFTLENBQUMsUUFBUSxFQUFFLENBQUM7UUFFMUIsSUFBSSxDQUFDLGNBQWMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztJQUNoQyxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNLLFdBQVcsQ0FBQyxNQUFvQjtRQUN0QyxJQUFJLENBQUMsY0FBYyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQzVCLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUNqQyxJQUFJLENBQUMsWUFBWSxFQUFFLENBQUM7UUFDcEIsSUFBSSxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDbEMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsTUFBTSxFQUFFLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUNqRCxJQUFJLENBQUMsY0FBYyxDQUFDLE1BQU0sQ0FBQyxTQUFTLEVBQUUsSUFBSSxDQUFDLGdCQUFnQixDQUFDLENBQUM7UUFDN0QsSUFBSSxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDL0IsSUFBSSxDQUFDLDZCQUE2QixFQUFFLENBQUM7UUFDckMsSUFBSSxDQUFDLGVBQWUsRUFBRSxDQUFDO0lBQ3pCLENBQUM7SUFFTyxjQUFjLENBQUMsTUFBb0I7UUFDekMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLENBQUMsU0FBUyxDQUFDO1FBQ2xDLElBQUksQ0FBQyxpQkFBaUIsR0FBRyxNQUFNLENBQUMsaUJBQWlCLElBQUksSUFBSSxDQUFDO1FBQzFELElBQUksQ0FBQyxPQUFPLEdBQUcsTUFBTSxDQUFDLE9BQU8sQ0FBQztRQUM5QixJQUFJLENBQUMsT0FBTyxHQUFHLE1BQU0sQ0FBQyxPQUFPLENBQUM7UUFDOUIsSUFBSSxDQUFDLFVBQVUsR0FBRyxNQUFNLENBQUMsVUFBVSxDQUFDO1FBQ3BDLElBQUksQ0FBQyxhQUFhLEdBQUcsTUFBTSxDQUFDLFVBQVUsQ0FBQztRQUN2QyxJQUFJLENBQUMsUUFBUSxHQUFHLE1BQU0sQ0FBQyxRQUFRLENBQUM7UUFDaEMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLENBQUMsU0FBUyxDQUFDO1FBQ2xDLElBQUksQ0FBQyxPQUFPLEdBQUcsTUFBTSxDQUFDLE9BQU8sQ0FBQztRQUM5QixJQUFJLENBQUMsT0FBTyxHQUFHLE1BQU0sQ0FBQyxPQUFPLENBQUM7UUFDOUIsSUFBSSxDQUFDLE9BQU8sR0FBRyxNQUFNLENBQUMsT0FBTyxJQUFJLEVBQUUsQ0FBQztRQUNwQyxJQUFJLENBQUMsWUFBWSxHQUFHLE1BQU0sQ0FBQyxVQUFVLENBQUM7UUFDdEMsSUFBSSxDQUFDLGNBQWMsR0FBRyxNQUFNLENBQUMsWUFBWSxDQUFDO1FBQzFDLElBQUksQ0FBQyxZQUFZLEdBQUcsTUFBTSxDQUFDLFlBQVksQ0FBQztRQUN4QyxJQUFJLENBQUMsVUFBVSxHQUFHLE1BQU0sQ0FBQyxVQUFVLENBQUM7UUFDcEMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLENBQUMsU0FBUyxDQUFDO1FBQ2xDLElBQUksQ0FBQyxVQUFVLEdBQUcsTUFBTSxDQUFDLFVBQVUsQ0FBQztRQUNwQyxJQUFJLENBQUMsT0FBTyxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUM7UUFDNUIsSUFBSSxDQUFDLFlBQVksR0FBRyxNQUFNLENBQUMsVUFBVSxDQUFDO1FBQ3RDLElBQUksQ0FBQyxhQUFhLEdBQUcsTUFBTSxDQUFDLFdBQVcsQ0FBQztRQUN4QyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sQ0FBQyxTQUFTLENBQUM7UUFDbEMsSUFBSSxDQUFDLEtBQUssR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDO1FBQzFCLElBQUksQ0FBQyxVQUFVLEdBQUcsTUFBTSxDQUFDLFVBQVUsQ0FBQztRQUNwQyxJQUFJLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDekMsQ0FBQztJQUVEOzs7O09BSUc7SUFDSyxtQkFBbUIsQ0FBQyxNQUFNO1FBQ2hDLCtFQUErRTtRQUMvRSx5REFBeUQ7UUFDekQsSUFBSSxNQUFNLENBQUMsWUFBWSxLQUFLLEtBQUssSUFBSSxNQUFNLENBQUMsVUFBVSxFQUFFLEVBQUUsMENBQTBDO1lBQ2xHLElBQUksQ0FBQyxZQUFZLEdBQUcsS0FBSyxDQUFDO1NBQzNCO1FBQ0QsSUFBSSxNQUFNLENBQUMsTUFBTSxLQUFLLEtBQUssRUFBRTtZQUMzQixJQUFJLENBQUMsTUFBTSxHQUFHLEtBQUssQ0FBQztTQUNyQjtRQUNELElBQUksTUFBTSxDQUFDLEtBQUssRUFBRTtZQUNoQixJQUFJLENBQUMsS0FBSyxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUM7U0FDM0I7UUFDRCxJQUFJLE1BQU0sQ0FBQyxXQUFXLEtBQUssS0FBSyxFQUFFO1lBQ2hDLElBQUksQ0FBQyxXQUFXLEdBQUcsS0FBSyxDQUFDO1NBQzFCO1FBRUQsSUFBSSxJQUFJLENBQUMsU0FBUyxFQUFFO1lBQ2xCLElBQUksQ0FBQyxVQUFVLEdBQUcsS0FBSyxDQUFDO1NBQ3pCO2FBQU07WUFDTCxJQUFJLENBQUMsVUFBVSxHQUFHLENBQUMsTUFBTSxDQUFDLFVBQVUsS0FBSyxTQUFTLENBQUM7Z0JBQ2pELENBQUMsQ0FBQyxJQUFJO2dCQUNOLENBQUMsQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDO1NBQ3ZCO1FBRUQsSUFBSSxNQUFNLENBQUMsS0FBSyxFQUFFO1lBQ2hCLElBQUksQ0FBQyxPQUFPLENBQUMsZUFBZSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztTQUM1QztRQUNELElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxFQUFFO1lBQ25CLElBQUksQ0FBQyxPQUFPLEdBQUcsSUFBSSxDQUFDO1NBQ3JCO1FBRUQsSUFBSSxNQUFNLENBQUMsZ0JBQWdCLEVBQUU7WUFDM0IsSUFBSSxDQUFDLGdCQUFnQixHQUFHLEdBQUcsRUFBRTtnQkFDM0IsTUFBTSxDQUFDLGdCQUFnQixDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxjQUFjLENBQUMsV0FBVyxDQUFDLENBQUM7WUFDOUUsQ0FBQyxDQUFDO1NBQ0g7SUFDSCxDQUFDO0lBRUQ7O09BRUc7SUFDSyxZQUFZO1FBQ2xCLElBQUksSUFBSSxDQUFDLE9BQU8sRUFBRTtZQUNoQixNQUFNLGFBQWEsR0FBRyxJQUFJLFNBQVMsQ0FBQztnQkFDbEMsS0FBSyxFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsU0FBUyxJQUFJLFNBQVM7Z0JBQzFDLElBQUksRUFBRSxJQUFJO2dCQUNWLEtBQUssRUFBRSxDQUFDLEdBQUcsRUFBRSxFQUFFO29CQUNiLElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLEVBQUUsR0FBRyxDQUFDLENBQUM7Z0JBQzlDLENBQUM7Z0JBQ0QsT0FBTyxFQUFFLElBQUk7YUFDZCxDQUFDLENBQUM7WUFFSCxJQUFJLENBQUMsSUFBSSxDQUFDLGFBQWEsRUFBRTtnQkFDdkIsSUFBSSxDQUFDLGFBQWEsR0FBRyxFQUFFLENBQUM7YUFDekI7WUFFRCxJQUFJLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsQ0FBQztZQUV2QyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRTtnQkFDakIsSUFBSSxDQUFDLE9BQU8sR0FBRyxFQUFFLENBQUM7YUFDbkI7WUFFRCxJQUFJLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxLQUFLLEtBQUssRUFBRTtnQkFDakMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUM7b0JBQ2hCLElBQUksRUFBRSxvQkFBb0I7b0JBQzFCLElBQUksRUFBRSxRQUFRLENBQUMsUUFBUTtvQkFDdkIsS0FBSyxFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsV0FBVyxJQUFJLGNBQWM7aUJBQ2xELENBQUMsQ0FBQzthQUNKO1NBQ0Y7SUFFSCxDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSyxXQUFXLENBQUMsWUFBOEIsRUFBRSxRQUF3QztRQUMxRixJQUFJLENBQUMsTUFBTSxDQUFDLGNBQWMsQ0FBQyxZQUFZLEVBQUUsUUFBUSxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUM7SUFDeEUsQ0FBQztJQUVEOztPQUVHO0lBQ0ssWUFBWSxDQUFDLE9BQU87UUFDMUIsSUFBSSxPQUFPLEVBQUU7WUFDWCxJQUFJLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsQ0FBQztTQUNsQztRQUVELElBQUksQ0FBQyxhQUFhO1lBQ2hCLENBQUMsSUFBSSxDQUFDLGFBQWEsSUFBSSxJQUFJLENBQUMsYUFBYSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUM7bUJBQ2xELENBQUMsSUFBSSxDQUFDLGVBQWUsSUFBSSxJQUFJLENBQUMsZUFBZSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQztJQUNqRSxDQUFDO0lBRU8sY0FBYyxDQUNwQixlQUFzQyxFQUN0QyxlQUFnQztRQUVoQyxJQUFJLGVBQWUsRUFBRTtZQUNuQixJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksbUJBQW1CLENBQUMsZUFBZSxFQUFFLElBQUksQ0FBQyxPQUFPLEVBQUUsZUFBZSxDQUFDLENBQUM7WUFDekYsSUFBSSxDQUFDLFNBQVMsQ0FBQyxlQUFlLENBQUMsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxXQUFXLENBQUMsQ0FBQztTQUN2RTtJQUNILENBQUM7SUFFTyxlQUFlO1FBQ3JCLElBQUksQ0FBQyxjQUFjLENBQUMsb0JBQW9CLENBQUM7WUFDdkMsVUFBVSxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsVUFBVTtZQUM3QixlQUFlLEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxlQUFlO1NBQzdDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFTyxXQUFXLENBQUMsV0FBOEI7UUFDaEQsSUFBSSxXQUFXLEVBQUU7WUFDZixJQUFJLENBQUMsY0FBYyxDQUFDLGNBQWMsQ0FBQyxXQUFXLENBQUMsQ0FBQztZQUNoRCxJQUFJLENBQUMsZUFBZSxHQUFHLFdBQVcsQ0FBQyxPQUFPLENBQUM7U0FDNUM7SUFDSCxDQUFDO0lBRU8sNkJBQTZCO1FBQ25DLElBQUksQ0FBQyxjQUFjLEdBQUcsSUFBSSx3QkFBd0IsQ0FDaEQsSUFBSSxDQUFDLE9BQU8sRUFDWixJQUFJLENBQUMsTUFBTSxFQUNYLElBQUksQ0FBQyxZQUFZLEVBQ2pCLElBQUksQ0FBQyxNQUFNLEVBQ1gsSUFBSSxDQUFDLE9BQU8sRUFDWixJQUFJLENBQUMsVUFBVSxDQUNoQixDQUFDO0lBQ0osQ0FBQztJQUVEOztPQUVHO0lBQ0ssWUFBWTtRQUNsQixJQUFJLE1BQU0sR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDO1FBRXpCLDZDQUE2QztRQUM3QyxJQUFJLElBQUksQ0FBQyxPQUFPLEVBQUU7WUFDaEIsTUFBTSxHQUFHLGFBQWEsQ0FBQyxDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsYUFBYSxDQUFDLENBQUM7aUJBQ2pELElBQUksQ0FDSCxHQUFHLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsQ0FDMUIsQ0FBQztTQUNMO1FBRUQsTUFBTTthQUNILElBQUksQ0FDSCxZQUFZLENBQUMsRUFBRSxDQUFDLEVBQ2hCLEdBQUcsQ0FBQyxHQUFHLEVBQUU7WUFDUCxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUMzQixDQUFDLENBQUMsRUFDRixHQUFHLENBQUMsR0FBRyxFQUFFO1lBQ1AsSUFBSSxDQUFDLFNBQVMsRUFBRSxvQkFBb0IsRUFBRSxDQUFDO1FBQ3pDLENBQUMsQ0FBQyxFQUNGLEdBQUcsQ0FBQyxDQUFDLE1BQStCLEVBQUUsRUFBRTtZQUN0QyxJQUFJLEtBQUssR0FBRyxFQUFFLEdBQUcsSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO1lBRXJDLElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxpQkFBaUIsSUFBSSxNQUFNLEVBQUUsVUFBVSxFQUFFO2dCQUN2RCxLQUFLLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDO2FBQ2xFO2lCQUFNO2dCQUNMLE1BQU0scUJBQXFCLEdBQUcsQ0FBQyxJQUFJLENBQUMsWUFBWTt1QkFDM0MsSUFBSSxDQUFDLGNBQWMsQ0FBQyxTQUFTLEtBQUssV0FBVyxDQUFDLE1BQU0sQ0FDeEQsSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLGVBQWUsQ0FBQztnQkFFakMsS0FBSyxHQUFHLHFCQUFxQixDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO2FBQzNIO1lBRUQsSUFBSSxJQUFJLENBQUMsT0FBTyxDQUFDLGFBQWEsRUFBRTtnQkFDOUIsTUFBTSxDQUFDLE1BQU0sQ0FDWCxLQUFLLEVBQ0w7b0JBQ0UsS0FBSyxFQUFFLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxhQUFhLENBQUMsSUFBSSxJQUFJLElBQUksQ0FBQyxPQUFPLENBQUMsYUFBYSxDQUFDLFNBQVMsRUFBRTtpQkFDcEYsQ0FDRixDQUFDO2FBQ0g7WUFFRCxJQUFJLElBQUksQ0FBQyxPQUFPLENBQUMsVUFBVSxFQUFFO2dCQUMzQixLQUFLLEdBQUc7b0JBQ04sR0FBRyxLQUFLO29CQUNSLE9BQU8sRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLG1CQUFtQjtpQkFDMUMsQ0FBQzthQUNIO1lBRUQsT0FBTyxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsQ0FBQztRQUMzQixDQUFDLENBQUMsRUFDRixTQUFTLENBQUMsQ0FBQyxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsRUFBRSxFQUFFO1lBQzlCLElBQUksSUFBSSxDQUFDLE9BQU8sQ0FBQyxnQkFBZ0IsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsY0FBYyxFQUFFO2dCQUNqRSxPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsdUJBQXVCLEVBQUU7cUJBQzFDLElBQUksQ0FDSCxLQUFLLENBQUMsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FDekIsQ0FBQzthQUNMO1lBRUQsT0FBTyxFQUFFLENBQUMsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQztRQUMvQixDQUFDLENBQUMsRUFDRixTQUFTLENBQUMsQ0FBQyxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsRUFBRSxFQUFFO1lBQzlCLElBQUksSUFBSSxDQUFDLGFBQWEsRUFBRTtnQkFDdEIsT0FBTyxJQUFJLENBQUMsYUFBYSxDQUFDLEtBQUssQ0FBQztxQkFDN0IsSUFBSSxDQUNILEdBQUcsQ0FBQyxDQUFDLGdCQUFnQixFQUFFLEVBQUUsQ0FBQyxDQUFDLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxnQkFBZ0IsRUFBRSxDQUFDLENBQUMsRUFDaEUsVUFBVSxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUU7b0JBQ25CLE9BQU8sQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUM7b0JBRXJCLE9BQU8sS0FBSyxDQUFDO2dCQUNmLENBQUMsQ0FBQyxDQUNILENBQUM7YUFDTDtZQUVELE9BQU8sRUFBRSxDQUFDLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7UUFDL0IsQ0FBQyxDQUFDLEVBQ0YsU0FBUyxDQUFDLENBQUMsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLEVBQUUsRUFBRTtZQUM5QixNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQztpQkFDeEMsSUFBSSxDQUNILFVBQVUsQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFO2dCQUNuQixPQUFPLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDO2dCQUVyQixPQUFPLEtBQUssQ0FBQztZQUNmLENBQUMsQ0FBQyxDQUNILENBQUM7WUFFSixPQUFPLGFBQWEsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsQ0FBQyxFQUFFLFdBQVcsQ0FBQyxDQUFDLENBQUM7UUFDN0QsQ0FBQyxDQUFDLEVBQ0YsVUFBVSxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUU7WUFDbkIsT0FBTyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUVyQixPQUFPLEtBQUssQ0FBQztRQUNmLENBQUMsQ0FBQyxFQUNGLFNBQVMsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQzFCO2FBQ0EsU0FBUyxDQUFDLENBQUMsQ0FBQyxXQUFXLEVBQUUsUUFBUSxDQUFDLEVBQUUsRUFBRTtZQUNyQyxJQUFJLENBQUMsWUFBWSxHQUFHLEtBQUssQ0FBQztZQUMxQixJQUFJLENBQUMsY0FBYyxDQUFDLFdBQVcsQ0FBQyxNQUFNLEVBQUUsV0FBVyxDQUFDLEtBQUssRUFBRSxRQUFRLENBQUMsQ0FBQztRQUN2RSxDQUFDLENBQUMsQ0FBQztJQUNQLENBQUM7SUFFTyxpQkFBaUI7UUFDdkIsSUFBSSxDQUFDLGNBQWMsQ0FBQyxZQUFZO2FBQzdCLElBQUksQ0FDSCxTQUFTLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUMxQjthQUNBLFNBQVMsQ0FBQyxDQUFDLElBQVcsRUFBRSxFQUFFO1lBQ3pCLElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxPQUFPLEVBQUU7Z0JBRXZCLE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUM7Z0JBRWpDLElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxlQUFlLEVBQUU7b0JBQy9CLElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxZQUFZLENBQUMsQ0FBQztpQkFDNUM7cUJBQU07b0JBQ0wsd0NBQXdDO29CQUN4QyxJQUFJLElBQUksQ0FBQyxjQUFjLENBQUMsT0FBTyxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsV0FBVyxFQUFFO3dCQUMxRCxJQUFJLENBQUMsY0FBYyxDQUFDLFlBQVksQ0FBQyxXQUFXLENBQUMsUUFBUSxDQUFDLENBQUM7d0JBRXZELElBQUksQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLFlBQVksQ0FBQyxDQUFDO3dCQUNyQyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxFQUFFLFVBQVUsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO3FCQUN6Qzt5QkFBTTt3QkFDTCxJQUFJLENBQUMsdUJBQXVCLENBQUMsWUFBWSxDQUFDLENBQUM7cUJBQzVDO2lCQUNGO2FBQ0Y7WUFFRCx3QkFBd0I7WUFDeEIsSUFBSSxJQUFJLENBQUMsU0FBUyxFQUFFO2dCQUNsQixJQUFJLENBQUMsT0FBTyxDQUFDLENBQUMsR0FBRyxFQUFFLEVBQUU7b0JBQ25CLElBQUksQ0FBQyxTQUFTLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQztnQkFDckMsQ0FBQyxDQUFDLENBQUM7YUFDSjtRQUNILENBQUMsQ0FBQyxDQUFDO0lBQ1AsQ0FBQztJQUVEOzs7T0FHRztJQUNLLDJCQUEyQjtRQUNqQyxJQUFJLENBQUMsT0FBTyxDQUFDLGVBQWU7YUFDekIsSUFBSSxDQUNILFNBQVMsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQzFCO2FBQ0EsU0FBUyxDQUFDLEdBQUcsRUFBRTtZQUNkLElBQUksQ0FBQyxxQkFBcUIsRUFBRSxDQUFDO1FBQy9CLENBQUMsQ0FBQyxDQUFDO0lBQ1AsQ0FBQztJQUVPLG1CQUFtQjtRQUN6QixJQUFJLElBQUksQ0FBQyxnQkFBZ0IsRUFBRTtZQUN6QixPQUFPO1NBQ1I7UUFFRCxJQUFJLElBQUksQ0FBQyxVQUFVLEVBQUU7WUFDbkIsK0JBQStCO1lBQy9CLElBQUksSUFBSSxDQUFDLFVBQVUsQ0FBQyxNQUFNLEtBQUssU0FBUyxFQUFFO2dCQUN4QyxJQUFJLENBQUMsVUFBVSxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUM7YUFDL0I7WUFHRCxJQUFJLENBQUMsU0FBUztpQkFDWCxTQUFTLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUM7aUJBQy9CLElBQUksQ0FDSCxTQUFTLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUMxQjtpQkFDQSxTQUFTLENBQUMsQ0FBQyxnQkFBa0MsRUFBRSxFQUFFO2dCQUNoRCxJQUFJLENBQUMsZ0JBQWdCLEdBQUcsZ0JBQWdCLENBQUM7Z0JBQ3pDLElBQUksQ0FBQyxxQkFBcUIsR0FBRyxnQkFBZ0I7cUJBQzFDLFNBQVMsQ0FBQyxHQUFHLEVBQUU7b0JBQ2QsSUFBSSxZQUFZLEdBQUcsS0FBSyxDQUFDO29CQUN6QixNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMsY0FBYyxDQUFDLFNBQVMsQ0FBQztvQkFFaEQsK0NBQStDO29CQUMvQyxJQUFJLENBQUMsSUFBSSxDQUFDLFlBQVk7MkJBQ2pCLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxXQUFXOzJCQUN4QixTQUFTLEtBQUssV0FBVyxDQUFDLE1BQU0sRUFDbkM7d0JBRUEsSUFBSSxDQUFDLGNBQWMsQ0FBQyxZQUFZLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxDQUFDO3dCQUNuRCxZQUFZLEdBQUcsSUFBSSxDQUFDO3FCQUVyQjt5QkFBTSxJQUNMLFNBQVMsS0FBSyxXQUFXLENBQUMsTUFBTTt3QkFDaEMsU0FBUyxLQUFLLFdBQVcsQ0FBQyxNQUFNO3dCQUNoQyxTQUFTLEtBQUssV0FBVyxDQUFDLElBQUksRUFDOUI7d0JBQ0EsWUFBWSxHQUFHLElBQUksQ0FBQztxQkFDckI7eUJBQU0sSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLFdBQVcsSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLFdBQVcsRUFBRTt3QkFDN0QsdUNBQXVDO3dCQUN2QyxZQUFZLEdBQUcsSUFBSSxDQUFDO3dCQUNwQixJQUFJLENBQUMsY0FBYyxDQUFDLFlBQVksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLENBQUM7d0JBQ25ELElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxFQUFFLENBQUM7cUJBQ3RCO29CQUVELElBQUksWUFBWSxFQUFFO3dCQUNoQixJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxDQUFDO3dCQUNwQixnQkFBZ0IsQ0FBQyxPQUFPLEVBQUUsQ0FBQztxQkFDNUI7Z0JBQ0gsQ0FBQyxDQUFDLENBQUM7Z0JBRUwsSUFBSSxDQUFDLGNBQWMsQ0FBQyxpQkFBaUI7cUJBQ2xDLElBQUksQ0FDSCxTQUFTLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUMxQjtxQkFDQSxTQUFTLENBQUMsR0FBRyxFQUFFO29CQUNkLGdCQUFnQixDQUFDLE1BQU0sRUFBRSxDQUFDO2dCQUM1QixDQUFDLENBQUMsQ0FBQztZQUNQLENBQUMsQ0FBQyxDQUFDO1NBQ047SUFDSCxDQUFDO0lBRUQ7O09BRUc7SUFDSyxZQUFZO1FBQ2xCLElBQUksSUFBSSxDQUFDLFlBQVksRUFBRTtZQUNyQixPQUFPO1NBQ1I7UUFFRCxNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLGVBQWUsRUFBRSxDQUFDO1FBRWxELE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsYUFBYTtZQUMzQyxDQUFDLENBQUMsRUFBRSxLQUFLLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxhQUFhLENBQUMsSUFBSSxFQUFFLFNBQVMsRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLGFBQWEsQ0FBQyxTQUFTLEVBQUU7WUFDN0YsQ0FBQyxDQUFDLElBQUksQ0FBQztRQUVULFNBQVM7UUFDVCxJQUFJLENBQUMsWUFBWSxHQUFHO1lBQ2xCLE9BQU8sRUFBRSxJQUFJLENBQUMsT0FBTztZQUNyQixLQUFLLEVBQUUsSUFBSSxDQUFDLE9BQU8sSUFBSSxFQUFFO1lBQ3pCLFlBQVksRUFBRSxJQUFJLENBQUMsWUFBWTtZQUMvQiw4QkFBOEI7WUFDOUIsT0FBTyxFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTztZQUM3QixVQUFVLEVBQUUsSUFBSSxDQUFDLFVBQVU7WUFDM0IsU0FBUyxFQUFFLElBQUksQ0FBQyxTQUFTO1lBQ3pCLEtBQUssRUFBRSxVQUFVO1lBQ2pCLElBQUksRUFBRSxVQUFVO1lBQ2hCLEtBQUssRUFBRSxJQUFJLENBQUMsS0FBSztZQUNqQixVQUFVLEVBQUUsSUFBSSxDQUFDLFVBQVU7WUFDM0IsSUFBSSxFQUFFLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQztZQUNqQyxNQUFNLEVBQUUsSUFBSSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDO1lBQ3JDLE1BQU0sRUFBRSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxJQUFJLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSTtZQUNyRSxVQUFVLEVBQUUsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDO1NBQ3hDLENBQUM7SUFDSixDQUFDO0lBRUQ7Ozs7T0FJRztJQUNLLFdBQVcsQ0FBQyxPQUFPO1FBQ3pCLElBQUksSUFBSSxDQUFDLFlBQVksRUFBRTtZQUNyQixJQUFJLENBQUMsWUFBWSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1NBQzVCO1FBRUQsSUFBSSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7UUFFakMsSUFBSSxDQUFDLG1CQUFtQixFQUFFLENBQUM7SUFDN0IsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0ssYUFBYSxDQUFDLFdBQVcsRUFBRSxVQUFVO1FBQzNDLElBQUksSUFBSSxDQUFDLGNBQWMsRUFBRTtZQUN2QixJQUFJLENBQUMsY0FBYyxDQUFDLFdBQVcsRUFBRSxVQUFVLENBQUMsQ0FBQztTQUM5QztRQUVELElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDO1FBRXJDLElBQUksQ0FBQyxXQUFXLEdBQUcsS0FBSyxDQUFDO1FBRXpCLGlCQUFpQjtRQUNqQixJQUFJLENBQUMsbUJBQW1CLEVBQUUsQ0FBQztRQUUzQixJQUFJLElBQUksQ0FBQyxPQUFPLElBQUksSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLEVBQUU7WUFDdkMsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO1NBQ2Y7UUFFRCxJQUFJLENBQUMsY0FBYyxDQUFDLFlBQVksQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLENBQUM7UUFFckQsK0NBQStDO1FBQy9DLElBQUksQ0FBQyxNQUFNLENBQUMsV0FBVyxFQUFFLENBQUM7UUFFMUIsSUFBSSxJQUFJLENBQUMsZ0JBQWdCLEVBQUU7WUFDekIsSUFBSSxDQUFDLGNBQWMsQ0FBQyxTQUFTLEVBQUUsQ0FBQztZQUNoQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsTUFBTSxFQUFFLENBQUM7U0FDaEM7YUFBTTtZQUNMLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxFQUFFLENBQUM7U0FDckI7SUFDSCxDQUFDO0lBRU8sbUJBQW1CO1FBQ3pCLGlCQUFpQjtRQUNqQixJQUFJLElBQUksQ0FBQyxPQUFPLElBQUksSUFBSSxDQUFDLFlBQVksQ0FBQyxvQkFBb0IsQ0FBQyxFQUFFO1lBQzNELE9BQU8sSUFBSSxDQUFDLFlBQVksQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDO1lBRS9DLE1BQU0sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFlBQVksRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBRXJELElBQUksQ0FBQyxXQUFXLEdBQUcsSUFBSSxDQUFDO1NBQ3pCO0lBQ0gsQ0FBQztJQUVELDZDQUE2QztJQUNyQyxXQUFXLENBQUMsV0FBVyxFQUFFLFVBQVU7UUFDekMsSUFBSSxVQUFVLEVBQUU7WUFDZCxJQUFJLENBQUMsT0FBTyxDQUFDLG9CQUFvQixDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUVwRCxNQUFNLGFBQWEsR0FBRyxVQUFVLENBQUMsU0FBUyxLQUFLLEtBQUssQ0FBQyxDQUFDLENBQUMsZ0JBQWdCLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLENBQUM7WUFDcEcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxhQUFhLENBQUMsYUFBYSxDQUFDLENBQUM7U0FDM0M7YUFBTTtZQUNMLGlDQUFpQztZQUNqQyxJQUFJLENBQUMsT0FBTyxDQUFDLGFBQWEsR0FBRyxTQUFTLENBQUM7WUFDdkMsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO1NBQ2Y7SUFDSCxDQUFDO0lBRU8sY0FBYyxDQUFDLE1BQU0sRUFBRSxLQUFLLEVBQUUsUUFBUTtRQUM1QyxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLEVBQUU7WUFDckIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLEdBQUcsQ0FBQyxDQUFDO1NBQ3RCO1FBRUQsSUFBSSxRQUFRLENBQUMsTUFBTSxFQUFFO1lBQ25CLE1BQU0sU0FBUyxHQUFHLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLElBQUksUUFBUSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDOUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxZQUFZLENBQ3RCLFFBQVEsQ0FBQyxNQUFNLEVBQ2YsU0FBUyxFQUNULElBQUksQ0FBQyxjQUFjLENBQUMsU0FBUyxLQUFLLFdBQVcsQ0FBQyxRQUFRLENBQ3ZELENBQUM7U0FDSDthQUFNLElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxPQUFPLEVBQUU7WUFDOUIsT0FBTyxDQUFDLEdBQUcsQ0FDVCxvQkFBb0IsRUFDcEIseUNBQXlDLEVBQ3pDLDJDQUEyQztnQkFDM0MsNEVBQTRFO2dCQUM1RSw4RUFBOEUsQ0FDL0UsQ0FBQztTQUNIO1FBRUQsMERBQTBEO1FBQzFELElBQUksQ0FBQyxjQUFjLENBQUMsbUJBQW1CLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3ZELEdBQUc7UUFFSCxJQUFJLENBQUMsNEJBQTRCLENBQUMsUUFBUSxDQUFDLENBQUM7UUFFNUMsSUFBSSxJQUFJLENBQUMsVUFBVSxFQUFFLFFBQVEsSUFBSSxJQUFJLENBQUMsa0JBQWtCLEVBQUU7WUFDeEQsSUFBSSxDQUFDLGlCQUFpQixHQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDLEtBQUssRUFBRSxTQUFTLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxlQUFlLENBQUMsQ0FBQyxDQUFDO1NBQzFHO1FBRUQsSUFBSSxJQUFJLENBQUMsWUFBWSxFQUFFO1lBQ3JCLElBQUksQ0FBQyxZQUFZLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxjQUFjLENBQUMsZUFBZSxDQUFDLENBQUM7U0FDL0Q7UUFFRCxvREFBb0Q7UUFDcEQsSUFBSSxJQUFJLENBQUMsY0FBYyxDQUFDLFdBQVcsQ0FBQyxNQUFNLEtBQUssQ0FBQztlQUMzQyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksR0FBRyxDQUFDO2VBQ3BCLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxFQUN2QztZQUNBLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxFQUFFLENBQUM7U0FDdEI7UUFFRCxJQUFJLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxFQUFFLGNBQWMsRUFBRSxNQUFNLEVBQUUsY0FBYyxFQUFFLENBQUMsQ0FBQztRQUNyRSxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUM1QixDQUFDO0lBRU8sNEJBQTRCLENBQUMsUUFBUTtRQUMzQywwQkFBMEI7UUFDMUIsSUFBSSxJQUFJLENBQUMsU0FBUyxFQUFFO1lBQ2xCLElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxPQUFPLEVBQUU7Z0JBQ3ZCLElBQUksQ0FBQyxTQUFTLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQztnQkFDNUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyx5QkFBeUIsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLGlCQUFpQixFQUFFLENBQUMsQ0FBQztnQkFDMUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyx1QkFBdUIsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDO2FBQzdEO2lCQUFNO2dCQUNMLE1BQU0sS0FBSyxHQUFHLFFBQVEsQ0FBQyxNQUFNLElBQUksUUFBUSxDQUFDLE1BQU0sQ0FBQyxPQUFPO3VCQUNuRCxLQUFLLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsSUFBSSxRQUFRLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQztnQkFFMUQsSUFBSSxDQUFDLFNBQVMsQ0FBQyx5QkFBeUIsQ0FBQyxLQUFLLENBQUMsQ0FBQztnQkFDaEQsSUFBSSxDQUFDLFNBQVMsQ0FBQyx1QkFBdUIsQ0FBQyxLQUFLLENBQUMsQ0FBQzthQUMvQztZQUVELElBQUksQ0FBQyxTQUFTLENBQUMsd0JBQXdCLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxlQUFlLENBQUMsQ0FBQztTQUM5RTtJQUNILENBQUM7SUFFRDs7Ozs7OztPQU9HO0lBQ0ssdUJBQXVCLENBQUMsWUFBWTtRQUMxQyxJQUFJLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxPQUFPLEVBQUU7WUFDaEMsSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksR0FBRyxDQUFDLEVBQUU7Z0JBQ3hCLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQzthQUNqRDtpQkFBTTtnQkFDTCxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7YUFDZjtTQUNGO1FBRUQsSUFBSSxDQUFDLE1BQU0sQ0FBQyxPQUFPLElBQUksWUFBWSxDQUFDO1FBQ3BDLElBQUksQ0FBQyxNQUFNLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztRQUUvQixJQUFJLElBQUksQ0FBQyxjQUFjLENBQUMsT0FBTyxJQUFJLElBQUksQ0FBQyxTQUFTLEVBQUU7WUFDakQsSUFBSSxDQUFDLFNBQVMsQ0FBQyx5QkFBeUIsQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLGdCQUFnQixDQUFDLENBQUM7WUFDL0UsSUFBSSxDQUFDLFNBQVMsQ0FBQyx1QkFBdUIsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1NBQzdEO0lBQ0gsQ0FBQztJQUVEOzs7Ozs7O09BT0c7SUFDSyxhQUFhLENBQUMsb0JBQW9CLEVBQUUsR0FBRztRQUM3QyxNQUFNLGtCQUFrQixHQUFHLG9CQUFvQixDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBRXJELElBQUksa0JBQWtCLFlBQVksVUFBVSxFQUFFO1lBQzVDLGtCQUFrQjtpQkFDZixJQUFJLENBQ0gsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUNQLFNBQVMsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQzFCO2lCQUNBLFNBQVMsQ0FBQztnQkFDVCxJQUFJLEVBQUUsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRTthQUMxQixDQUFDLENBQUM7U0FDTjtJQUNILENBQUM7SUFFTyxxQkFBcUI7UUFDM0IsSUFBSSxDQUFDLE9BQU8sQ0FBQyxvQkFBb0IsRUFBRSxDQUFDO1FBQ3BDLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTzthQUNqQixNQUFNLENBQUMsQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDLE1BQU0sQ0FBQyxRQUFRLElBQUksTUFBTSxDQUFDLE9BQU8sQ0FBQzthQUNyRCxPQUFPLENBQUMsQ0FBQyxNQUFNLEVBQUUsRUFBRTtZQUNsQixJQUFJLENBQUMsT0FBTyxDQUFDLGlCQUFpQixDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ3pDLENBQUMsQ0FBQyxDQUFDO0lBQ1AsQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRWxlbWVudFJlZiwgVGVtcGxhdGVSZWYgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEFjdGl2YXRlZFJvdXRlLCBSb3V0ZXIgfSBmcm9tICdAYW5ndWxhci9yb3V0ZXInO1xuXG5pbXBvcnQge1xuICBDaGFuZ2VGbiwgRmlsdGVyQ29uZmlnLCBGc0ZpbHRlckF1dG9SZWxvYWQsIElGaWx0ZXJTYXZlZEZpbHRlcnNDb25maWcsIEl0ZW1UeXBlLFxufSBmcm9tICdAZmlyZXN0aXRjaC9maWx0ZXInO1xuaW1wb3J0IHsgRnNTY3JvbGxJbnN0YW5jZSwgRnNTY3JvbGxTZXJ2aWNlIH0gZnJvbSAnQGZpcmVzdGl0Y2gvc2Nyb2xsJztcbmltcG9ydCB7IFNlbGVjdGlvbkRpYWxvZyB9IGZyb20gJ0BmaXJlc3RpdGNoL3NlbGVjdGlvbic7XG5cbmltcG9ydCB7XG4gIEJlaGF2aW9yU3ViamVjdCwgY29tYmluZUxhdGVzdCwgRU1QVFksIGZyb20sIE9ic2VydmFibGUsIG9mLCBTdWJqZWN0LCBTdWJzY3JpcHRpb24sXG59IGZyb20gJ3J4anMnO1xuaW1wb3J0IHtcbiAgY2F0Y2hFcnJvciwgZGVib3VuY2VUaW1lLCBtYXAsIG1hcFRvLCBzaGFyZVJlcGxheSwgc3dpdGNoTWFwLCB0YWtlLCB0YWtlVW50aWwsIHRhcCxcbn0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuXG5pbXBvcnQgeyBjbG9uZURlZXAgfSBmcm9tICdsb2Rhc2gtZXMnO1xuXG5pbXBvcnQgeyBQYWdlQ2hhbmdlVHlwZSB9IGZyb20gJy4uL2VudW1zL3BhZ2UtY2hhbmdlLXR5cGUuZW51bSc7XG5pbXBvcnQgeyBGc0xpc3RTdGF0ZSB9IGZyb20gJy4uL2VudW1zL3N0YXRlLmVudW0nO1xuaW1wb3J0IHtcbiAgRnNMaXN0QWZ0ZXJDb250ZW50SW5pdEZuLFxuICBGc0xpc3RBZnRlckZldGNoRm4sXG4gIEZzTGlzdEFmdGVySW5pdEZuLFxuICBGc0xpc3RCZWZvcmVGZXRjaEZuLFxuICBGc0xpc3RDb25maWcsXG4gIEZzTGlzdEVtcHR5U3RhdGVDb25maWcsXG4gIEZzTGlzdEZldGNoRm4sXG4gIEZzTGlzdEZldGNoT3B0aW9ucyxcbiAgRnNMaXN0RmV0Y2hTdWJzY3JpcHRpb24sXG4gIEZzTGlzdEdyb3VwQ29uZmlnLFxuICBGc0xpc3RMb2FkTW9yZUNvbmZpZyxcbiAgRnNMaXN0Tm9SZXN1bHRzQ29uZmlnLFxuICBGc0xpc3RQZXJzaXRhbmNlLFxuICBGc0xpc3RSZXN0b3JlQ29uZmlnLFxuICBGc0xpc3RTY3JvbGxhYmxlQ29uZmlnLFxuICBGc0xpc3RTZWxlY3Rpb25Db25maWcsXG4gIEZzTGlzdFRyYWNrQnlGbixcbiAgRnNQYWdpbmcsXG4gIFBhZ2VDaGFuZ2UsXG59IGZyb20gJy4uL2ludGVyZmFjZXMnO1xuaW1wb3J0IHsgU29ydGluZ0RpcmVjdGlvbiB9IGZyb20gJy4uL21vZGVscy9jb2x1bW4ubW9kZWwnO1xuaW1wb3J0IHsgUm93QWN0aW9uIH0gZnJvbSAnLi4vbW9kZWxzL3Jvdy1hY3Rpb24ubW9kZWwnO1xuaW1wb3J0IHsgU3R5bGVDb25maWcgfSBmcm9tICcuLi9tb2RlbHMvc3R5bGVDb25maWcubW9kZWwnO1xuXG5pbXBvcnQgeyBDb2x1bW5zQ29udHJvbGxlciB9IGZyb20gJy4vY29sdW1ucy1jb250cm9sbGVyJztcbmltcG9ydCB7IERhdGFDb250cm9sbGVyIH0gZnJvbSAnLi9kYXRhLWNvbnRyb2xsZXInO1xuaW1wb3J0IHsgRXh0ZXJuYWxQYXJhbXNDb250cm9sbGVyIH0gZnJvbSAnLi9leHRlcm5hbC1wYXJhbXMtY29udHJvbGxlcic7XG5pbXBvcnQgeyBBY3Rpb25zQ29udHJvbGxlciB9IGZyb20gJy4vaW5kZXgnO1xuaW1wb3J0IHsgUGFnaW5hdGlvbkNvbnRyb2xsZXIgfSBmcm9tICcuL3BhZ2luYXRpb24tY29udHJvbGxlcic7XG5pbXBvcnQgeyBQZXJzaXN0YW5jZUNvbnRyb2xsZXIgfSBmcm9tICcuL3BlcnNpc3RhbmNlLWNvbnRyb2xsZXInO1xuaW1wb3J0IHsgU2VsZWN0aW9uQ29udHJvbGxlciB9IGZyb20gJy4vc2VsZWN0aW9uLWNvbnRyb2xsZXInO1xuaW1wb3J0IHsgU29ydGluZ0NvbnRyb2xsZXIgfSBmcm9tICcuL3NvcnRpbmctY29udHJvbGxlcic7XG5cbmNvbnN0IHNob3dEZWxldGVkRmlsdGVyS2V5ID0gJ3Nob3dEZWxldGVkJztcblxuXG5leHBvcnQgY2xhc3MgTGlzdCB7XG5cbiAgcHVibGljIGhlYWRpbmc6IHN0cmluZztcbiAgcHVibGljIHRyYWNrQnk6IHN0cmluZztcbiAgcHVibGljIHN1YmhlYWRpbmc6IHN0cmluZztcbiAgcHVibGljIGF1dG9Gb2N1czogYm9vbGVhbjtcbiAgcHVibGljIHJvd0hvdmVySGlnaGxpZ2h0OiBib29sZWFuO1xuICBwdWJsaWMgcm93QWN0aW9uc1JhdzogYW55W107XG4gIHB1YmxpYyBncm91cEFjdGlvbnNSYXc6IGFueVtdO1xuICBwdWJsaWMgcm93Q2xhc3M7XG4gIHB1YmxpYyByb3dFdmVudHM6IGFueTtcbiAgcHVibGljIHJlc3RvcmU6IEZzTGlzdFJlc3RvcmVDb25maWc7XG4gIHB1YmxpYyBwZXJzaXN0OiBGc0xpc3RQZXJzaXRhbmNlO1xuICBwdWJsaWMgZmlsdGVycyA9IFtdO1xuICBwdWJsaWMgZmlsdGVySW5pdENiOiBDaGFuZ2VGbjtcbiAgcHVibGljIGZpbHRlckNoYW5nZUNiOiBDaGFuZ2VGbjtcbiAgcHVibGljIHNhdmVkRmlsdGVyczogSUZpbHRlclNhdmVkRmlsdGVyc0NvbmZpZztcbiAgcHVibGljIHNjcm9sbGFibGU6IEZzTGlzdFNjcm9sbGFibGVDb25maWc7XG4gIHB1YmxpYyBub1Jlc3VsdHM6IEZzTGlzdE5vUmVzdWx0c0NvbmZpZztcbiAgcHVibGljIGVtcHR5U3RhdGU6IEZzTGlzdEVtcHR5U3RhdGVDb25maWc7XG4gIHB1YmxpYyBmZXRjaEZuOiBGc0xpc3RGZXRjaEZuO1xuICBwdWJsaWMgYmVmb3JlRmV0Y2hGbjogRnNMaXN0QmVmb3JlRmV0Y2hGbjtcbiAgcHVibGljIGFmdGVyRmV0Y2hGbjogRnNMaXN0QWZ0ZXJGZXRjaEZuO1xuICBwdWJsaWMgYWZ0ZXJDb250ZW50SW5pdDogRnNMaXN0QWZ0ZXJDb250ZW50SW5pdEZuO1xuICBwdWJsaWMgYWZ0ZXJJbml0OiBGc0xpc3RBZnRlckluaXRGbjtcbiAgcHVibGljIHN0eWxlO1xuICBwdWJsaWMgaGFzUm93QWN0aW9ucztcbiAgcHVibGljIHBhZ2luZyA9IG5ldyBQYWdpbmF0aW9uQ29udHJvbGxlcigpO1xuICBwdWJsaWMgY29sdW1ucyA9IG5ldyBDb2x1bW5zQ29udHJvbGxlcigpO1xuICBwdWJsaWMgYWN0aW9ucyA9IG5ldyBBY3Rpb25zQ29udHJvbGxlcigpO1xuICBwdWJsaWMgZGF0YUNvbnRyb2xsZXIgPSBuZXcgRGF0YUNvbnRyb2xsZXIoKTtcbiAgcHVibGljIHNvcnRpbmcgPSBuZXcgU29ydGluZ0NvbnRyb2xsZXIoKTtcbiAgcHVibGljIGV4dGVybmFsUGFyYW1zOiBFeHRlcm5hbFBhcmFtc0NvbnRyb2xsZXI7XG4gIHB1YmxpYyBzZWxlY3Rpb246IFNlbGVjdGlvbkNvbnRyb2xsZXI7XG4gIHB1YmxpYyBmaWx0ZXJDb25maWc6IEZpbHRlckNvbmZpZyA9IG51bGw7XG4gIHB1YmxpYyBsb2FkaW5nJCA9IG5ldyBCZWhhdmlvclN1YmplY3QoZmFsc2UpO1xuICBwdWJsaWMgZmV0Y2hDb21wbGV0ZSQgPSBuZXcgU3ViamVjdDx7IHNjcm9sbEludG9WaWV3PzogYm9vbGVhbiB9PigpO1xuICBwdWJsaWMgZmlsdGVyc1JlYWR5JCA9IG5ldyBTdWJqZWN0PHZvaWQ+KCk7XG4gIHB1YmxpYyBzdGF0dXMgPSB0cnVlO1xuICBwdWJsaWMgY2hpcHMgPSBmYWxzZTtcbiAgcHVibGljIGZpbHRlcklucHV0ID0gdHJ1ZTtcbiAgcHVibGljIHF1ZXJ5UGFyYW0gPSBmYWxzZTtcbiAgcHVibGljIHJlc3RvcmVNb2RlID0gZmFsc2U7XG4gIHB1YmxpYyBhdXRvUmVsb2FkOiBGc0ZpbHRlckF1dG9SZWxvYWQ7XG5cbiAgcHVibGljIGluaXRpYWxGZXRjaCA9IHRydWU7XG5cbiAgLy8gRW1wdHkgc3RhdGVcbiAgcHVibGljIGVtcHR5U3RhdGVFbmFibGVkID0gZmFsc2U7XG4gIHB1YmxpYyBlbXB0eVN0YXRlVGVtcGxhdGU6IFRlbXBsYXRlUmVmPGFueT47XG5cbiAgcHVibGljIGZzU2Nyb2xsSW5zdGFuY2U6IEZzU2Nyb2xsSW5zdGFuY2U7XG5cbiAgcHJpdmF0ZSBfZGVzdHJveSQgPSBuZXcgU3ViamVjdCgpO1xuICBwcml2YXRlIF9pbml0aWFsaXplZCQgPSBuZXcgQmVoYXZpb3JTdWJqZWN0KGZhbHNlKTtcbiAgcHJpdmF0ZSBfZmV0Y2gkID0gbmV3IFN1YmplY3Q8RnNMaXN0RmV0Y2hTdWJzY3JpcHRpb24gfCB2b2lkPigpO1xuICBwcml2YXRlIHJlYWRvbmx5IF9maWx0ZXJzUXVlcnkgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PFJlY29yZDxzdHJpbmcsIGFueT4+KG51bGwpO1xuICBwcml2YXRlIHJlYWRvbmx5IF9hY3RpdmVGaWx0ZXJzQ291bnQkID0gdGhpcy5fZmlsdGVyc1F1ZXJ5XG4gICAgLnBpcGUobWFwKCh2KSA9PiBPYmplY3Qua2V5cyh2KS5sZW5ndGgpLCBzaGFyZVJlcGxheSgpKTtcblxuICBwcml2YXRlIHJlYWRvbmx5IF9oZWFkZXJDb25maWc6IFN0eWxlQ29uZmlnO1xuICBwcml2YXRlIHJlYWRvbmx5IF9ncm91cENlbGxDb25maWc6IFN0eWxlQ29uZmlnO1xuICBwcml2YXRlIHJlYWRvbmx5IF9jZWxsQ29uZmlnOiBTdHlsZUNvbmZpZztcbiAgcHJpdmF0ZSByZWFkb25seSBfZm9vdGVyQ29uZmlnOiBTdHlsZUNvbmZpZztcblxuICBwcml2YXRlIF9mc1Njcm9sbFN1YnNjcmlwdGlvbjogU3Vic2NyaXB0aW9uO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgX2VsOiBFbGVtZW50UmVmLFxuICAgIHByaXZhdGUgX2NvbmZpZzogRnNMaXN0Q29uZmlnID0ge30sXG4gICAgcHJpdmF0ZSBfZnNTY3JvbGw6IEZzU2Nyb2xsU2VydmljZSxcbiAgICBwcml2YXRlIF9zZWxlY3Rpb25EaWFsb2c6IFNlbGVjdGlvbkRpYWxvZyxcbiAgICBwcml2YXRlIF9yb3V0ZXI6IFJvdXRlcixcbiAgICBwcml2YXRlIF9yb3V0ZTogQWN0aXZhdGVkUm91dGUsXG4gICAgcHJpdmF0ZSBfcGVyc2lzdGFuY2U6IFBlcnNpc3RhbmNlQ29udHJvbGxlcixcbiAgICBwcml2YXRlIF9pbkRpYWxvZzogYm9vbGVhbixcbiAgKSB7XG4gICAgdGhpcy5faW5pdGlhbGl6ZShfY29uZmlnKTtcbiAgICB0aGlzLl9oZWFkZXJDb25maWcgPSBuZXcgU3R5bGVDb25maWcoX2NvbmZpZy5oZWFkZXIpO1xuICAgIHRoaXMuX2dyb3VwQ2VsbENvbmZpZyA9IG5ldyBTdHlsZUNvbmZpZyhfY29uZmlnLmNlbGwpO1xuICAgIHRoaXMuX2NlbGxDb25maWcgPSBuZXcgU3R5bGVDb25maWcoX2NvbmZpZy5jZWxsKTtcbiAgICB0aGlzLl9mb290ZXJDb25maWcgPSBuZXcgU3R5bGVDb25maWcoX2NvbmZpZy5mb290ZXIpO1xuICAgIHRoaXMuX2luaXRpYWxpemVkJC5uZXh0KHRydWUpO1xuICAgIHRoaXMuc3Vic2NyaWJlKCk7XG5cbiAgICBpZiAodGhpcy5pbml0aWFsRmV0Y2gpIHtcbiAgICAgIHRoaXMuZGF0YUNvbnRyb2xsZXIuc2V0T3BlcmF0aW9uKEZzTGlzdFN0YXRlLkxvYWQpO1xuICAgICAgdGhpcy5fZmV0Y2gkLm5leHQoKTtcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgZ2V0IGZldGNoJCgpOiBPYnNlcnZhYmxlPEZzTGlzdEZldGNoU3Vic2NyaXB0aW9uIHwgdm9pZD4ge1xuICAgIHJldHVybiB0aGlzLl9mZXRjaCQuYXNPYnNlcnZhYmxlKCk7XG4gIH1cblxuICBwdWJsaWMgZ2V0IGhhc1NhdmVkRmlsdGVycygpOiBib29sZWFuIHtcbiAgICByZXR1cm4gISF0aGlzLmZpbHRlckNvbmZpZy5zYXZlZEZpbHRlcnM7XG4gIH1cblxuICBwdWJsaWMgZ2V0IGZpbHRlcnNRdWVyeSgpOiBSZWNvcmQ8c3RyaW5nLCBhbnk+IHtcbiAgICByZXR1cm4gdGhpcy5fZmlsdGVyc1F1ZXJ5LmdldFZhbHVlKCk7XG4gIH1cblxuICBwdWJsaWMgZ2V0IGFjdGl2ZUZpbHRlcnNDb3VudCQoKTogT2JzZXJ2YWJsZTxudW1iZXI+IHtcbiAgICByZXR1cm4gdGhpcy5fYWN0aXZlRmlsdGVyc0NvdW50JDtcbiAgfVxuXG4gIHB1YmxpYyBnZXQgZGVzdHJveSQoKTogT2JzZXJ2YWJsZTxhbnk+IHtcbiAgICByZXR1cm4gdGhpcy5fZGVzdHJveSQ7XG4gIH1cblxuICBwdWJsaWMgZ2V0IGluaXRpYWxpemVkJCgpOiBPYnNlcnZhYmxlPGJvb2xlYW4+IHtcbiAgICByZXR1cm4gdGhpcy5faW5pdGlhbGl6ZWQkO1xuICB9XG5cbiAgcHVibGljIGZldGNoUmVtb3RlKHF1ZXJ5KSB7XG4gICAgY29uc3Qgb3B0aW9uczogRnNMaXN0RmV0Y2hPcHRpb25zID0ge1xuICAgICAgc3RhdGU6IHRoaXMuZGF0YUNvbnRyb2xsZXIub3BlcmF0aW9uLFxuICAgIH07XG5cbiAgICBjb25zdCByZXN1bHQ6IGFueSA9IHRoaXMuZmV0Y2hGbihxdWVyeSwgb3B0aW9ucyk7XG5cbiAgICByZXR1cm4gcmVzdWx0IGluc3RhbmNlb2YgUHJvbWlzZSA/IGZyb20ocmVzdWx0KSA6IHJlc3VsdDtcbiAgfVxuXG4gIC8vIHB1YmxpYyBsb2FkTG9jYWwoKSB7XG4gIC8vICAgdGhpcy5wYWdpbmcudXBkYXRlUGFnaW5nTWFudWFsKHRoaXMuX3Jvd3MpO1xuICAvLyAgIGNvbnN0IGZyb20gPSAodGhpcy5wYWdpbmcucGFnZSAtIDEpICogdGhpcy5wYWdpbmcubGltaXQ7XG4gIC8vICAgY29uc3QgdG8gPSAodGhpcy5wYWdpbmcucGFnZSA9PT0gMSkgPyB0aGlzLnBhZ2luZy5saW1pdCA6IHRoaXMucGFnaW5nLmxpbWl0ICogdGhpcy5wYWdpbmcucGFnZTtcbiAgLy8gICBjb25zdCBzbGljZU9mUm93cyA9IHRoaXMuX3Jvd3Muc2xpY2UoZnJvbSwgdG8pO1xuICAvLyAgIHRoaXMuZGF0YSQubmV4dChzbGljZU9mUm93cyk7XG4gIC8vIH1cblxuICAvKipcbiAgICogVHJhbnNmb3JtIHRlbXBsYXRlcyBmb3IgdXNpbmdcbiAgICpcbiAgICogQHBhcmFtIHRlbXBsYXRlc1xuICAgKi9cbiAgcHVibGljIHRyYW5mb3JtVGVtcGxhdGVzVG9Db2x1bW5zKHRlbXBsYXRlcykge1xuICAgIGNvbnN0IGRlZmF1bHRDb25maWdzID0ge1xuICAgICAgaGVhZGVyOiB0aGlzLl9oZWFkZXJDb25maWcsXG4gICAgICBncm91cENlbGw6IHRoaXMuX2dyb3VwQ2VsbENvbmZpZyxcbiAgICAgIGNlbGw6IHRoaXMuX2NlbGxDb25maWcsXG4gICAgICBmb290ZXI6IHRoaXMuX2Zvb3RlckNvbmZpZyxcbiAgICB9O1xuXG4gICAgdGhpcy5jb2x1bW5zLnNldERlZmF1bHRzKGRlZmF1bHRDb25maWdzKTtcbiAgICB0aGlzLmNvbHVtbnMuaW5pdGlhbGl6ZUNvbHVtbnModGVtcGxhdGVzKTtcblxuICAgIC8vIFNldCBzb3J0QnkgZGVmYXVsdCBjb2x1bW5cbiAgICB0aGlzLl91cGRhdGVTb3J0aW5nQ29sdW1ucygpO1xuXG4gICAgLy8gRGVmYXVsdCBzb3J0IGJ5XG4gICAgY29uc3QgZXh0ZXJuYWxTb3J0aW5nID0gdGhpcy5leHRlcm5hbFBhcmFtcy5leHRlcm5hbFNvcnRpbmc7XG4gICAgY29uc3QgaW5pdGlhbFNvcnRDb25maWcgPSBleHRlcm5hbFNvcnRpbmcgfHwgdGhpcy5fY29uZmlnLnNvcnQ7XG4gICAgdGhpcy5zb3J0aW5nLmluaXRpYWxTb3J0QnkoaW5pdGlhbFNvcnRDb25maWcpO1xuXG4gICAgaWYgKGV4dGVybmFsU29ydGluZyAmJiAhdGhpcy5zb3J0aW5nLmlzRGVmaW5lZCkge1xuICAgICAgdGhpcy5leHRlcm5hbFBhcmFtcy5jbGVhclNvcnRpbmdQYXJhbXMoKTtcblxuICAgICAgY29uc29sZS53YXJuKCdOb3QgYWJsZSB0byByZXN0b3JlIHBlcnNpc3RlZCBzb3J0aW5nIHBhcmFtcy4nLCBleHRlcm5hbFNvcnRpbmcpO1xuICAgIH1cblxuICAgIHRoaXMuX2luaXRGaWx0ZXJzKCk7XG4gICAgdGhpcy5faW5pdEluZmluaXR5U2Nyb2xsKCk7XG4gIH1cblxuICBwdWJsaWMgcmVsb2FkKCkge1xuICAgIHRoaXMubG9hZGluZyQubmV4dCh0cnVlKTtcblxuICAgIHRoaXMuZGF0YUNvbnRyb2xsZXIuc2V0T3BlcmF0aW9uKEZzTGlzdFN0YXRlLlJlbG9hZCk7XG5cbiAgICBpZiAodGhpcy5mc1Njcm9sbEluc3RhbmNlKSB7XG4gICAgICB0aGlzLnBhZ2luZy5yZXNldFBhZ2luZygpO1xuICAgICAgdGhpcy5kYXRhQ29udHJvbGxlci5jbGVhclJvd3MoKTtcbiAgICAgIHRoaXMuZnNTY3JvbGxJbnN0YW5jZS5yZWxvYWQoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5fZmV0Y2gkLm5leHQoKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogV2F0Y2ggcGFnZSBjaGFuZ2VzXG4gICAqL1xuICBwdWJsaWMgc3Vic2NyaWJlKCkge1xuICAgIHRoaXMucGFnaW5nLnBhZ2VDaGFuZ2VkJFxuICAgICAgLnBpcGUoXG4gICAgICAgIHRha2VVbnRpbCh0aGlzLl9kZXN0cm95JCksXG4gICAgICApXG4gICAgICAuc3Vic2NyaWJlKChldmVudDogUGFnZUNoYW5nZSkgPT4ge1xuICAgICAgICB0aGlzLmRhdGFDb250cm9sbGVyLnNldE9wZXJhdGlvbihGc0xpc3RTdGF0ZS5QYWdlQ2hhbmdlKTtcblxuICAgICAgICAvLyBSZW1vdmUgYWxsIHJvd3MgaWYgbGltaXRzIHdhcyBjaGFuZ2VkXG4gICAgICAgIGlmIChldmVudC50eXBlID09PSBQYWdlQ2hhbmdlVHlwZS5MaW1pdENoYW5nZWQgJiYgdGhpcy5wYWdpbmcuaGFzUGFnZVN0cmF0ZWd5KSB7XG4gICAgICAgICAgdGhpcy5kYXRhQ29udHJvbGxlci5jbGVhclJvd3MoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLnBhZ2luZy5oYXNPZmZzZXRTdHJhdGVneSkge1xuICAgICAgICAgIHRoaXMucGFnaW5nLnVwZGF0ZVBhZ2luYXRpb24oKTtcblxuICAgICAgICAgIGlmICh0aGlzLnNlbGVjdGlvbikge1xuICAgICAgICAgICAgdGhpcy5zZWxlY3Rpb24udXBkYXRlVmlzaWJsZVJlY29yZHNDb3VudCh0aGlzLnBhZ2luZy5nZXRWaXNpYmxlUmVjb3JkcygpKTtcbiAgICAgICAgICAgIHRoaXMuc2VsZWN0aW9uLnVwZGF0ZVRvdGFsUmVjb3Jkc0NvdW50KHRoaXMucGFnaW5nLnJlY29yZHMpO1xuICAgICAgICAgICAgdGhpcy5zZWxlY3Rpb24ucGFnZUNoYW5nZWQodGhpcy5zY3JvbGxhYmxlKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIXRoaXMuc2Nyb2xsYWJsZSAmJiAhdGhpcy5wYWdpbmcubG9hZE1vcmVFbmFibGVkKSB7XG4gICAgICAgICAgY29uc3QgY29udGFpbnMgPSBbXS5zbGljZS5jYWxsKGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoJy5jZGstb3ZlcmxheS1jb250YWluZXInKSkuc29tZSgob3ZlcmxheSkgPT4ge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2VsLm5hdGl2ZUVsZW1lbnQuY29udGFpbnMob3ZlcmxheSk7XG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICBsZXQgZWwgPSB0aGlzLl9lbC5uYXRpdmVFbGVtZW50O1xuXG4gICAgICAgICAgaWYgKCFjb250YWlucykge1xuICAgICAgICAgICAgY29uc3QgcmVjdCA9IHRoaXMuX2VsLm5hdGl2ZUVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgICAgICBpZiAoKE51bWJlcihyZWN0LnRvcCB8fCAwKSArIHdpbmRvdy5wYWdlWU9mZnNldCkgPCB3aW5kb3cuaW5uZXJIZWlnaHQpIHtcbiAgICAgICAgICAgICAgZWwgPSBkb2N1bWVudC5ib2R5O1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cblxuICAgICAgICAgIHRoaXMuZmV0Y2hDb21wbGV0ZSQuYXNPYnNlcnZhYmxlKClcbiAgICAgICAgICAgIC5waXBlKFxuICAgICAgICAgICAgICB0YWtlKDEpLFxuICAgICAgICAgICAgICB0YWtlVW50aWwodGhpcy5fZGVzdHJveSQpLFxuICAgICAgICAgICAgKVxuICAgICAgICAgICAgLnN1YnNjcmliZSgoZXZlbnQpID0+IHtcbiAgICAgICAgICAgICAgaWYoZXZlbnQ/LnNjcm9sbEludG9WaWV3ID8/IHRydWUpIHtcbiAgICAgICAgICAgICAgICBlbC5zY3JvbGxJbnRvVmlldyh7IGJlaGF2aW9yOiAnc21vb3RoJyB9KTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLl9mZXRjaCQubmV4dCgpO1xuICAgICAgfSk7XG5cbiAgICB0aGlzLnNvcnRpbmcuc29ydGluZ0NoYW5nZWQkXG4gICAgICAucGlwZShcbiAgICAgICAgdGFrZVVudGlsKHRoaXMuX2Rlc3Ryb3kkKSxcbiAgICAgIClcbiAgICAgIC5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgICB0aGlzLmRhdGFDb250cm9sbGVyLnNldE9wZXJhdGlvbihGc0xpc3RTdGF0ZS5Tb3J0KTtcbiAgICAgICAgdGhpcy5wYWdpbmcucGFnZSA9IDE7XG5cbiAgICAgICAgaWYgKHRoaXMuZnNTY3JvbGxJbnN0YW5jZSkge1xuICAgICAgICAgIHRoaXMuZGF0YUNvbnRyb2xsZXIuY2xlYXJSb3dzKCk7XG4gICAgICAgICAgdGhpcy5mc1Njcm9sbEluc3RhbmNlLnJlbG9hZCgpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRoaXMuX2ZldGNoJC5uZXh0KCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgdGhpcy5fbGlzdGVuVmlzaWJsZUNvbHVtbkNoYW5nZXMoKTtcbiAgICB0aGlzLl9saXN0ZW5Sb3dzUmVtb3ZlKCk7XG4gICAgdGhpcy5fbGlzdGVuRmV0Y2goKTtcbiAgfVxuXG4gIHB1YmxpYyBnZXREYXRhKHRyYWNrQnk/OiBGc0xpc3RUcmFja0J5Rm4pIHtcbiAgICBsZXQgcm93c0RhdGEgPSB0aGlzLmRhdGFDb250cm9sbGVyXG4gICAgICAudmlzaWJsZVJvd3NEYXRhO1xuXG4gICAgaWYgKHRyYWNrQnkpIHtcbiAgICAgIHJvd3NEYXRhID0gcm93c0RhdGFcbiAgICAgICAgLmZpbHRlcih0cmFja0J5KTtcbiAgICB9XG5cbiAgICByZXR1cm4gcm93c0RhdGFcbiAgICAgIC5tYXAoKGRhdGEpID0+IHtcbiAgICAgICAgcmV0dXJuIGNsb25lRGVlcChkYXRhKTtcbiAgICAgIH0pO1xuICB9XG5cbiAgcHVibGljIGhhc0RhdGEodHJhY2tCeTogRnNMaXN0VHJhY2tCeUZuKSB7XG4gICAgcmV0dXJuIHRoaXMuZGF0YUNvbnRyb2xsZXIudmlzaWJsZVJvd3NEYXRhLnNvbWUodHJhY2tCeSk7XG4gIH1cblxuICAvKipcbiAgICogVG9nZ2xlIGdyb3VwIG1vZGUgc3RhdHVzXG4gICAqXG4gICAqIEBwYXJhbSB2YWx1ZVxuICAgKi9cbiAgcHVibGljIGdyb3VwRW5hYmxlZCh2YWx1ZTogYm9vbGVhbikge1xuICAgIGlmICh0aGlzLmRhdGFDb250cm9sbGVyLmdyb3VwRW5hYmxlZCAhPT0gdmFsdWUpIHtcbiAgICAgIHRoaXMuZGF0YUNvbnRyb2xsZXIuZ3JvdXBFbmFibGVkID0gdmFsdWU7XG5cbiAgICAgIC8vIENvbW1lbnRlZCBvdXQgYmVjYXVzZSBSYXkgd2FudHMgdG8gY2hhbmdlIGdyb3VwIHN0YXR1cyBpbiBmZXRjaCBtYXAgcGlwZVxuICAgICAgLy8gYW5kIGl0IHRyaWdnZXJzIGV4dHJhIHJlcXVlc3RzXG4gICAgICAvLyB0aGlzLnJlbG9hZCgpO1xuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBkZXN0cm95KCkge1xuICAgIGlmICh0aGlzLl9mc1Njcm9sbFN1YnNjcmlwdGlvbikge1xuICAgICAgdGhpcy5fZnNTY3JvbGxTdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5wYWdpbmcpIHtcbiAgICAgIHRoaXMucGFnaW5nLmRlc3Ryb3koKTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5zb3J0aW5nKSB7XG4gICAgICB0aGlzLnNvcnRpbmcuZGVzdHJveSgpO1xuICAgIH1cblxuICAgIGlmICh0aGlzLnNlbGVjdGlvbikge1xuICAgICAgdGhpcy5zZWxlY3Rpb24uZGVzdHJveSgpO1xuICAgIH1cblxuICAgIGlmICh0aGlzLmZpbHRlckNvbmZpZykge1xuICAgICAgdGhpcy5maWx0ZXJDb25maWcgPSBudWxsO1xuICAgIH1cblxuICAgIGlmICh0aGlzLmV4dGVybmFsUGFyYW1zKSB7XG4gICAgICB0aGlzLmV4dGVybmFsUGFyYW1zLmRlc3Ryb3koKTtcbiAgICB9XG5cbiAgICB0aGlzLmNvbHVtbnMuZGVzdHJveSgpO1xuXG4gICAgdGhpcy5fZGVzdHJveSQubmV4dCgpO1xuICAgIHRoaXMuX2Rlc3Ryb3kkLmNvbXBsZXRlKCk7XG5cbiAgICB0aGlzLmRhdGFDb250cm9sbGVyLmRlc3Ryb3koKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBEbyBpbml0aWFsaXphdGlvbiBvZiB0YWJsZVxuICAgKlxuICAgKiBAcGFyYW0gY29uZmlnXG4gICAqL1xuICBwcml2YXRlIF9pbml0aWFsaXplKGNvbmZpZzogRnNMaXN0Q29uZmlnKSB7XG4gICAgdGhpcy5faW5pdFZhcmlhYmxlcyhjb25maWcpO1xuICAgIHRoaXMuX2luaXREZWZhdWx0T3B0aW9ucyhjb25maWcpO1xuICAgIHRoaXMuX2luaXRSZXN0b3JlKCk7XG4gICAgdGhpcy5faW5pdEFjdGlvbnMoY29uZmlnLmFjdGlvbnMpO1xuICAgIHRoaXMuX2luaXRQYWdpbmcoY29uZmlnLnBhZ2luZywgY29uZmlnLmxvYWRNb3JlKTtcbiAgICB0aGlzLl9pbml0U2VsZWN0aW9uKGNvbmZpZy5zZWxlY3Rpb24sIHRoaXMuX3NlbGVjdGlvbkRpYWxvZyk7XG4gICAgdGhpcy5faW5pdEdyb3Vwcyhjb25maWcuZ3JvdXApO1xuICAgIHRoaXMuX2luaXRFeHRlcm5hbFBhcmFtc0NvbnRyb2xsZXIoKTtcbiAgICB0aGlzLl9pbml0aWFsaXplRGF0YSgpO1xuICB9XG5cbiAgcHJpdmF0ZSBfaW5pdFZhcmlhYmxlcyhjb25maWc6IEZzTGlzdENvbmZpZykge1xuICAgIHRoaXMuYXV0b0ZvY3VzID0gY29uZmlnLmF1dG9Gb2N1cztcbiAgICB0aGlzLnJvd0hvdmVySGlnaGxpZ2h0ID0gY29uZmlnLnJvd0hvdmVySGlnaGxpZ2h0ID8/IHRydWU7XG4gICAgdGhpcy5oZWFkaW5nID0gY29uZmlnLmhlYWRpbmc7XG4gICAgdGhpcy50cmFja0J5ID0gY29uZmlnLnRyYWNrQnk7XG4gICAgdGhpcy5zdWJoZWFkaW5nID0gY29uZmlnLnN1YmhlYWRpbmc7XG4gICAgdGhpcy5yb3dBY3Rpb25zUmF3ID0gY29uZmlnLnJvd0FjdGlvbnM7XG4gICAgdGhpcy5yb3dDbGFzcyA9IGNvbmZpZy5yb3dDbGFzcztcbiAgICB0aGlzLnJvd0V2ZW50cyA9IGNvbmZpZy5yb3dFdmVudHM7XG4gICAgdGhpcy5yZXN0b3JlID0gY29uZmlnLnJlc3RvcmU7XG4gICAgdGhpcy5wZXJzaXN0ID0gY29uZmlnLnBlcnNpc3Q7XG4gICAgdGhpcy5maWx0ZXJzID0gY29uZmlnLmZpbHRlcnMgPz8gW107XG4gICAgdGhpcy5maWx0ZXJJbml0Q2IgPSBjb25maWcuZmlsdGVySW5pdDtcbiAgICB0aGlzLmZpbHRlckNoYW5nZUNiID0gY29uZmlnLmZpbHRlckNoYW5nZTtcbiAgICB0aGlzLnNhdmVkRmlsdGVycyA9IGNvbmZpZy5zYXZlZEZpbHRlcnM7XG4gICAgdGhpcy5zY3JvbGxhYmxlID0gY29uZmlnLnNjcm9sbGFibGU7XG4gICAgdGhpcy5ub1Jlc3VsdHMgPSBjb25maWcubm9SZXN1bHRzO1xuICAgIHRoaXMuZW1wdHlTdGF0ZSA9IGNvbmZpZy5lbXB0eVN0YXRlO1xuICAgIHRoaXMuZmV0Y2hGbiA9IGNvbmZpZy5mZXRjaDtcbiAgICB0aGlzLmFmdGVyRmV0Y2hGbiA9IGNvbmZpZy5hZnRlckZldGNoO1xuICAgIHRoaXMuYmVmb3JlRmV0Y2hGbiA9IGNvbmZpZy5iZWZvcmVGZXRjaDtcbiAgICB0aGlzLmFmdGVySW5pdCA9IGNvbmZpZy5hZnRlckluaXQ7XG4gICAgdGhpcy5zdHlsZSA9IGNvbmZpZy5zdHlsZTtcbiAgICB0aGlzLmF1dG9SZWxvYWQgPSBjb25maWcuYXV0b1JlbG9hZDtcbiAgICB0aGlzLmNvbHVtbnMuaW5pdENvbmZpZyhjb25maWcuY29sdW1uKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBKdXN0IGluaXQgb3B0aW9ucyBieSBkZWZhdWx0IGl0IGl0IHdhc24ndCBzcGVjaWZpZWRcbiAgICpcbiAgICogQHBhcmFtIGNvbmZpZ1xuICAgKi9cbiAgcHJpdmF0ZSBfaW5pdERlZmF1bHRPcHRpb25zKGNvbmZpZykge1xuICAgIC8vIFdlIHNob3VsZCBwcmV2ZW50IGluaXRpYWwgZmV0Y2ggaW4gY2FzZXMgd2hlbiBpdCB3aWxsIGJlIGZldGNoZWQgaW4gYW55IGNhc2VcbiAgICAvLyBBcyBleC4gc2Nyb2xsYWJsZSBvciBmaWx0ZXIgd2lsbCBkbyBmZXRjaCBpbiBhbnkgY2FzZXNcbiAgICBpZiAoY29uZmlnLmluaXRpYWxGZXRjaCA9PT0gZmFsc2UgfHwgY29uZmlnLnNjcm9sbGFibGUpIHsgLy8gVE9ETyBmaXhtZSBhZnRlciB0c21vZGVsIHZlcnNpb24gdXBkYXRlXG4gICAgICB0aGlzLmluaXRpYWxGZXRjaCA9IGZhbHNlO1xuICAgIH1cbiAgICBpZiAoY29uZmlnLnN0YXR1cyA9PT0gZmFsc2UpIHtcbiAgICAgIHRoaXMuc3RhdHVzID0gZmFsc2U7XG4gICAgfVxuICAgIGlmIChjb25maWcuY2hpcHMpIHtcbiAgICAgIHRoaXMuY2hpcHMgPSBjb25maWcuY2hpcHM7XG4gICAgfVxuICAgIGlmIChjb25maWcuZmlsdGVySW5wdXQgPT09IGZhbHNlKSB7XG4gICAgICB0aGlzLmZpbHRlcklucHV0ID0gZmFsc2U7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuX2luRGlhbG9nKSB7XG4gICAgICB0aGlzLnF1ZXJ5UGFyYW0gPSBmYWxzZTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5xdWVyeVBhcmFtID0gKGNvbmZpZy5xdWVyeVBhcmFtID09PSB1bmRlZmluZWQpXG4gICAgICAgID8gdHJ1ZVxuICAgICAgICA6IGNvbmZpZy5xdWVyeVBhcmFtO1xuICAgIH1cblxuICAgIGlmIChjb25maWcuc29ydHMpIHtcbiAgICAgIHRoaXMuc29ydGluZy5pbml0RmFrZUNvbHVtbnMoY29uZmlnLnNvcnRzKTtcbiAgICB9XG4gICAgaWYgKCFjb25maWcudHJhY2tCeSkge1xuICAgICAgdGhpcy50cmFja0J5ID0gJ2lkJztcbiAgICB9XG5cbiAgICBpZiAoY29uZmlnLmFmdGVyQ29udGVudEluaXQpIHtcbiAgICAgIHRoaXMuYWZ0ZXJDb250ZW50SW5pdCA9ICgpID0+IHtcbiAgICAgICAgY29uZmlnLmFmdGVyQ29udGVudEluaXQodGhpcy5wYWdpbmcucXVlcnksIHRoaXMuZGF0YUNvbnRyb2xsZXIudmlzaWJsZVJvd3MpO1xuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogSW5pdCByZXN0b3JlIHJvdyBhY3Rpb24gYW5kIGFwcGVuZCBTaG93IERlbGV0ZWQgb3B0aW9uIGludG8gZmlsdGVyc1xuICAgKi9cbiAgcHJpdmF0ZSBfaW5pdFJlc3RvcmUoKSB7XG4gICAgaWYgKHRoaXMucmVzdG9yZSkge1xuICAgICAgY29uc3QgcmVzdG9yZUFjdGlvbiA9IG5ldyBSb3dBY3Rpb24oe1xuICAgICAgICBsYWJlbDogdGhpcy5yZXN0b3JlLm1lbnVMYWJlbCB8fCAnUmVzdG9yZScsXG4gICAgICAgIG1lbnU6IHRydWUsXG4gICAgICAgIGNsaWNrOiAocm93KSA9PiB7XG4gICAgICAgICAgdGhpcy5fcmVzdG9yZUNsaWNrKHRoaXMucmVzdG9yZS5jbGljaywgcm93KTtcbiAgICAgICAgfSwgLy8gVE9ETyBmaXggbWUsIG1vdmUgdG8gc3BlY2lhbCBmaWxlXG4gICAgICAgIHJlc3RvcmU6IHRydWUsXG4gICAgICB9KTtcblxuICAgICAgaWYgKCF0aGlzLnJvd0FjdGlvbnNSYXcpIHtcbiAgICAgICAgdGhpcy5yb3dBY3Rpb25zUmF3ID0gW107XG4gICAgICB9XG5cbiAgICAgIHRoaXMucm93QWN0aW9uc1Jhdy5wdXNoKHJlc3RvcmVBY3Rpb24pO1xuXG4gICAgICBpZiAoIXRoaXMuZmlsdGVycykge1xuICAgICAgICB0aGlzLmZpbHRlcnMgPSBbXTtcbiAgICAgIH1cblxuICAgICAgaWYgKHRoaXMucmVzdG9yZS5maWx0ZXIgIT09IGZhbHNlKSB7XG4gICAgICAgIHRoaXMuZmlsdGVycy5wdXNoKHtcbiAgICAgICAgICBuYW1lOiBzaG93RGVsZXRlZEZpbHRlcktleSxcbiAgICAgICAgICB0eXBlOiBJdGVtVHlwZS5DaGVja2JveCxcbiAgICAgICAgICBsYWJlbDogdGhpcy5yZXN0b3JlLmZpbHRlckxhYmVsIHx8ICdTaG93IERlbGV0ZWQnLFxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgfVxuXG4gIC8qKlxuICAgKiBJbml0IHBhZ2luZ1xuICAgKlxuICAgKiBAcGFyYW0gcGFnaW5nQ29uZmlnXG4gICAqIEBwYXJhbSBsb2FkTW9yZVxuICAgKi9cbiAgcHJpdmF0ZSBfaW5pdFBhZ2luZyhwYWdpbmdDb25maWc6IEZzUGFnaW5nIHwgZmFsc2UsIGxvYWRNb3JlOiBGc0xpc3RMb2FkTW9yZUNvbmZpZyB8IGJvb2xlYW4pIHtcbiAgICB0aGlzLnBhZ2luZy5pbml0V2l0aENvbmZpZyhwYWdpbmdDb25maWcsIGxvYWRNb3JlLCAhIXRoaXMuc2Nyb2xsYWJsZSk7XG4gIH1cblxuICAvKipcbiAgICogU3BsaXQgYWN0aW9ucyBieSBjYXRlZ29yaWVzXG4gICAqL1xuICBwcml2YXRlIF9pbml0QWN0aW9ucyhhY3Rpb25zKSB7XG4gICAgaWYgKGFjdGlvbnMpIHtcbiAgICAgIHRoaXMuYWN0aW9ucy5zZXRBY3Rpb25zKGFjdGlvbnMpO1xuICAgIH1cblxuICAgIHRoaXMuaGFzUm93QWN0aW9ucyA9XG4gICAgICAodGhpcy5yb3dBY3Rpb25zUmF3ICYmIHRoaXMucm93QWN0aW9uc1Jhdy5sZW5ndGggPiAwKVxuICAgICAgfHwgKHRoaXMuZ3JvdXBBY3Rpb25zUmF3ICYmIHRoaXMuZ3JvdXBBY3Rpb25zUmF3Lmxlbmd0aCA+IDApO1xuICB9XG5cbiAgcHJpdmF0ZSBfaW5pdFNlbGVjdGlvbihcbiAgICBzZWxlY3Rpb25Db25maWc6IEZzTGlzdFNlbGVjdGlvbkNvbmZpZyxcbiAgICBzZWxlY3Rpb25EaWFsb2c6IFNlbGVjdGlvbkRpYWxvZyxcbiAgKSB7XG4gICAgaWYgKHNlbGVjdGlvbkNvbmZpZykge1xuICAgICAgdGhpcy5zZWxlY3Rpb24gPSBuZXcgU2VsZWN0aW9uQ29udHJvbGxlcihzZWxlY3Rpb25Db25maWcsIHRoaXMudHJhY2tCeSwgc2VsZWN0aW9uRGlhbG9nKTtcbiAgICAgIHRoaXMuc2VsZWN0aW9uLnNldFJvd3NDYWxsYmFjaygoKSA9PiB0aGlzLmRhdGFDb250cm9sbGVyLnZpc2libGVSb3dzKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIF9pbml0aWFsaXplRGF0YSgpIHtcbiAgICB0aGlzLmRhdGFDb250cm9sbGVyLnNldEFkZGl0aW9uYWxDb25maWdzKHtcbiAgICAgIHNjcm9sbGFibGU6ICEhdGhpcy5zY3JvbGxhYmxlLFxuICAgICAgbG9hZE1vcmVFbmFibGVkOiB0aGlzLnBhZ2luZy5sb2FkTW9yZUVuYWJsZWQsXG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIF9pbml0R3JvdXBzKGdyb3VwQ29uZmlnOiBGc0xpc3RHcm91cENvbmZpZykge1xuICAgIGlmIChncm91cENvbmZpZykge1xuICAgICAgdGhpcy5kYXRhQ29udHJvbGxlci5zZXRHcm91cENvbmZpZyhncm91cENvbmZpZyk7XG4gICAgICB0aGlzLmdyb3VwQWN0aW9uc1JhdyA9IGdyb3VwQ29uZmlnLmFjdGlvbnM7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBfaW5pdEV4dGVybmFsUGFyYW1zQ29udHJvbGxlcigpIHtcbiAgICB0aGlzLmV4dGVybmFsUGFyYW1zID0gbmV3IEV4dGVybmFsUGFyYW1zQ29udHJvbGxlcihcbiAgICAgIHRoaXMuX3JvdXRlcixcbiAgICAgIHRoaXMuX3JvdXRlLFxuICAgICAgdGhpcy5fcGVyc2lzdGFuY2UsXG4gICAgICB0aGlzLnBhZ2luZyxcbiAgICAgIHRoaXMuc29ydGluZyxcbiAgICAgIHRoaXMucXVlcnlQYXJhbSxcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIFN1YnNjcmliZSB0byBmZXRjaCQgZXZlbnQgd2l0aCBkZWJvdW5jZVxuICAgKi9cbiAgcHJpdmF0ZSBfbGlzdGVuRmV0Y2goKSB7XG4gICAgbGV0IGZldGNoJCA9IHRoaXMuZmV0Y2gkO1xuXG4gICAgLy8gU2hvdWxkIHdhaXQgdW50aWwgc2F2ZWQgZmlsdGVycyBub3QgbG9hZGVkXG4gICAgaWYgKHRoaXMuZmlsdGVycykge1xuICAgICAgZmV0Y2gkID0gY29tYmluZUxhdGVzdChbZmV0Y2gkLCB0aGlzLmZpbHRlcnNSZWFkeSRdKVxuICAgICAgICAucGlwZShcbiAgICAgICAgICBtYXAoKFtwYXJhbXNdKSA9PiBwYXJhbXMpLFxuICAgICAgICApO1xuICAgIH1cblxuICAgIGZldGNoJFxuICAgICAgLnBpcGUoXG4gICAgICAgIGRlYm91bmNlVGltZSg1MCksXG4gICAgICAgIHRhcCgoKSA9PiB7XG4gICAgICAgICAgdGhpcy5sb2FkaW5nJC5uZXh0KHRydWUpO1xuICAgICAgICB9KSxcbiAgICAgICAgdGFwKCgpID0+IHtcbiAgICAgICAgICB0aGlzLnNlbGVjdGlvbj8uY2xvc2VTZWxlY3Rpb25EaWFsb2coKTtcbiAgICAgICAgfSksXG4gICAgICAgIG1hcCgocGFyYW1zOiBGc0xpc3RGZXRjaFN1YnNjcmlwdGlvbikgPT4ge1xuICAgICAgICAgIGxldCBxdWVyeSA9IHsgLi4udGhpcy5maWx0ZXJzUXVlcnkgfTtcblxuICAgICAgICAgIGlmICh0aGlzLnBhZ2luZy5oYXNPZmZzZXRTdHJhdGVneSAmJiBwYXJhbXM/LmxvYWRPZmZzZXQpIHtcbiAgICAgICAgICAgIHF1ZXJ5ID0gT2JqZWN0LmFzc2lnbihxdWVyeSwgdGhpcy5wYWdpbmcubG9hZERlbGV0ZWRPZmZzZXRRdWVyeSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnN0IGFsbFJlY29yZHNSYW5nZU5lZWRlZCA9ICh0aGlzLmluaXRpYWxGZXRjaFxuICAgICAgICAgICAgICB8fCB0aGlzLmRhdGFDb250cm9sbGVyLm9wZXJhdGlvbiA9PT0gRnNMaXN0U3RhdGUuUmVsb2FkXG4gICAgICAgICAgICApICYmIHRoaXMucGFnaW5nLmxvYWRNb3JlRW5hYmxlZDtcblxuICAgICAgICAgICAgcXVlcnkgPSBhbGxSZWNvcmRzUmFuZ2VOZWVkZWQgPyBPYmplY3QuYXNzaWduKHF1ZXJ5LCB0aGlzLnBhZ2luZy5sb2FkTW9yZVF1ZXJ5KSA6IE9iamVjdC5hc3NpZ24ocXVlcnksIHRoaXMucGFnaW5nLnF1ZXJ5KTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAodGhpcy5zb3J0aW5nLnNvcnRpbmdDb2x1bW4pIHtcbiAgICAgICAgICAgIE9iamVjdC5hc3NpZ24oXG4gICAgICAgICAgICAgIHF1ZXJ5LFxuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgb3JkZXI6IGAke3RoaXMuc29ydGluZy5zb3J0aW5nQ29sdW1uLm5hbWV9LCR7dGhpcy5zb3J0aW5nLnNvcnRpbmdDb2x1bW4uZGlyZWN0aW9ufWAsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmICh0aGlzLmNvbHVtbnMuY29uZmlndXJlZCkge1xuICAgICAgICAgICAgcXVlcnkgPSB7XG4gICAgICAgICAgICAgIC4uLnF1ZXJ5LFxuICAgICAgICAgICAgICBjb2x1bW5zOiB0aGlzLmNvbHVtbnMudmlzaWJsZUNvbHVtbnNOYW1lcyxcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgcmV0dXJuIHsgcGFyYW1zLCBxdWVyeSB9O1xuICAgICAgICB9KSxcbiAgICAgICAgc3dpdGNoTWFwKCh7IHBhcmFtcywgcXVlcnkgfSkgPT4ge1xuICAgICAgICAgIGlmICh0aGlzLmNvbHVtbnMubG9hZEZuQ29uZmlndXJlZCAmJiAhdGhpcy5jb2x1bW5zLmNvbHVtbnNGZXRjaGVkKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jb2x1bW5zLmxvYWRSZW1vdGVDb2x1bW5Db25maWdzKClcbiAgICAgICAgICAgICAgLnBpcGUoXG4gICAgICAgICAgICAgICAgbWFwVG8oeyBwYXJhbXMsIHF1ZXJ5IH0pLFxuICAgICAgICAgICAgICApO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHJldHVybiBvZih7IHBhcmFtcywgcXVlcnkgfSk7XG4gICAgICAgIH0pLFxuICAgICAgICBzd2l0Y2hNYXAoKHsgcGFyYW1zLCBxdWVyeSB9KSA9PiB7XG4gICAgICAgICAgaWYgKHRoaXMuYmVmb3JlRmV0Y2hGbikge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuYmVmb3JlRmV0Y2hGbihxdWVyeSlcbiAgICAgICAgICAgICAgLnBpcGUoXG4gICAgICAgICAgICAgICAgbWFwKChiZWZvcmVGZXRjaFF1ZXJ5KSA9PiAoeyBwYXJhbXMsIHF1ZXJ5OiBiZWZvcmVGZXRjaFF1ZXJ5IH0pKSxcbiAgICAgICAgICAgICAgICBjYXRjaEVycm9yKChlcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG5cbiAgICAgICAgICAgICAgICAgIHJldHVybiBFTVBUWTtcbiAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICByZXR1cm4gb2YoeyBwYXJhbXMsIHF1ZXJ5IH0pO1xuICAgICAgICB9KSxcbiAgICAgICAgc3dpdGNoTWFwKCh7IHBhcmFtcywgcXVlcnkgfSkgPT4ge1xuICAgICAgICAgIGNvbnN0IHJlbW90ZUZldGNoID0gdGhpcy5mZXRjaFJlbW90ZShxdWVyeSlcbiAgICAgICAgICAgIC5waXBlKFxuICAgICAgICAgICAgICBjYXRjaEVycm9yKChlcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIEVNUFRZO1xuICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICk7XG5cbiAgICAgICAgICByZXR1cm4gY29tYmluZUxhdGVzdChbb2YoeyBwYXJhbXMsIHF1ZXJ5IH0pLCByZW1vdGVGZXRjaF0pO1xuICAgICAgICB9KSxcbiAgICAgICAgY2F0Y2hFcnJvcigoZXJyb3IpID0+IHtcbiAgICAgICAgICBjb25zb2xlLmVycm9yKGVycm9yKTtcblxuICAgICAgICAgIHJldHVybiBFTVBUWTtcbiAgICAgICAgfSksXG4gICAgICAgIHRha2VVbnRpbCh0aGlzLl9kZXN0cm95JCksXG4gICAgICApXG4gICAgICAuc3Vic2NyaWJlKChbcGFyYW1zUXVlcnksIHJlc3BvbnNlXSkgPT4ge1xuICAgICAgICB0aGlzLmluaXRpYWxGZXRjaCA9IGZhbHNlO1xuICAgICAgICB0aGlzLl9jb21wbGV0ZUZldGNoKHBhcmFtc1F1ZXJ5LnBhcmFtcywgcGFyYW1zUXVlcnkucXVlcnksIHJlc3BvbnNlKTtcbiAgICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBfbGlzdGVuUm93c1JlbW92ZSgpIHtcbiAgICB0aGlzLmRhdGFDb250cm9sbGVyLnJvd3NSZW1vdmVkJFxuICAgICAgLnBpcGUoXG4gICAgICAgIHRha2VVbnRpbCh0aGlzLl9kZXN0cm95JCksXG4gICAgICApXG4gICAgICAuc3Vic2NyaWJlKChyb3dzOiBhbnlbXSkgPT4ge1xuICAgICAgICBpZiAodGhpcy5wYWdpbmcuZW5hYmxlZCkge1xuXG4gICAgICAgICAgY29uc3QgcmVtb3ZlZENvdW50ID0gcm93cy5sZW5ndGg7XG5cbiAgICAgICAgICBpZiAodGhpcy5wYWdpbmcuaGFzUGFnZVN0cmF0ZWd5KSB7XG4gICAgICAgICAgICB0aGlzLl9ub0RhdGFQYWdpbmF0aW9uVXBkYXRlKHJlbW92ZWRDb3VudCk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIEZldGNoIG1vcmUgaWYgaGFzIHNvbWV0aGluZyBmb3IgZmV0Y2hcbiAgICAgICAgICAgIGlmICh0aGlzLmRhdGFDb250cm9sbGVyLmhhc0RhdGEgfHwgdGhpcy5wYWdpbmcuaGFzTmV4dFBhZ2UpIHtcbiAgICAgICAgICAgICAgdGhpcy5kYXRhQ29udHJvbGxlci5zZXRPcGVyYXRpb24oRnNMaXN0U3RhdGUuTG9hZE1vcmUpO1xuXG4gICAgICAgICAgICAgIHRoaXMucGFnaW5nLnJlbW92ZVJvd3MocmVtb3ZlZENvdW50KTtcbiAgICAgICAgICAgICAgdGhpcy5fZmV0Y2gkLm5leHQoeyBsb2FkT2Zmc2V0OiB0cnVlIH0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgdGhpcy5fbm9EYXRhUGFnaW5hdGlvblVwZGF0ZShyZW1vdmVkQ291bnQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFJlbW92ZSBmcm9tIHNlbGVjdGlvblxuICAgICAgICBpZiAodGhpcy5zZWxlY3Rpb24pIHtcbiAgICAgICAgICByb3dzLmZvckVhY2goKHJvdykgPT4ge1xuICAgICAgICAgICAgdGhpcy5zZWxlY3Rpb24ucmVtb3ZlUm93KHJvdy5kYXRhKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogTGlzdGVyIG1heSBoYXZlIG9yaWdpbmFsbHkgaGlkZGVuIGNvbHVtbnMsIGJ1dCB2aXNpYmlsaXR5IG9mIHRob3NlIGNvbHVtbnNcbiAgICogY2FuIGJlIGNoYW5nZWQgcHJvZ3JhbW1hdGljYWx5IGluIGFueSB0aW1lXG4gICAqL1xuICBwcml2YXRlIF9saXN0ZW5WaXNpYmxlQ29sdW1uQ2hhbmdlcygpOiB2b2lkIHtcbiAgICB0aGlzLmNvbHVtbnMudmlzaWJsZUNvbHVtbnMkXG4gICAgICAucGlwZShcbiAgICAgICAgdGFrZVVudGlsKHRoaXMuX2Rlc3Ryb3kkKSxcbiAgICAgIClcbiAgICAgIC5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgICB0aGlzLl91cGRhdGVTb3J0aW5nQ29sdW1ucygpO1xuICAgICAgfSk7XG4gIH1cblxuICBwcml2YXRlIF9pbml0SW5maW5pdHlTY3JvbGwoKSB7XG4gICAgaWYgKHRoaXMuZnNTY3JvbGxJbnN0YW5jZSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmICh0aGlzLnNjcm9sbGFibGUpIHtcbiAgICAgIC8vIFNjcm9sbGFibGUgc3RhdHVzIGJ5IGRlZmF1bHRcbiAgICAgIGlmICh0aGlzLnNjcm9sbGFibGUuc3RhdHVzID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgdGhpcy5zY3JvbGxhYmxlLnN0YXR1cyA9IHRydWU7XG4gICAgICB9XG5cblxuICAgICAgdGhpcy5fZnNTY3JvbGxcbiAgICAgICAgLmNvbXBvbmVudCh0aGlzLnNjcm9sbGFibGUubmFtZSlcbiAgICAgICAgLnBpcGUoXG4gICAgICAgICAgdGFrZVVudGlsKHRoaXMuX2Rlc3Ryb3kkKSxcbiAgICAgICAgKVxuICAgICAgICAuc3Vic2NyaWJlKChmc1Njcm9sbEluc3RhbmNlOiBGc1Njcm9sbEluc3RhbmNlKSA9PiB7XG4gICAgICAgICAgdGhpcy5mc1Njcm9sbEluc3RhbmNlID0gZnNTY3JvbGxJbnN0YW5jZTtcbiAgICAgICAgICB0aGlzLl9mc1Njcm9sbFN1YnNjcmlwdGlvbiA9IGZzU2Nyb2xsSW5zdGFuY2VcbiAgICAgICAgICAgIC5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgICAgICAgICBsZXQgc3RhcnRMb2FkaW5nID0gZmFsc2U7XG4gICAgICAgICAgICAgIGNvbnN0IG9wZXJhdGlvbiA9IHRoaXMuZGF0YUNvbnRyb2xsZXIub3BlcmF0aW9uO1xuXG4gICAgICAgICAgICAgIC8vIEluaXRpYWwgbG9hZGluZyBpZiBpbml0aWFsRmV0Y2ggZXF1YWxzIGZhbHNlXG4gICAgICAgICAgICAgIGlmICghdGhpcy5pbml0aWFsRmV0Y2hcbiAgICAgICAgICAgICAgICAmJiAhdGhpcy5wYWdpbmcuaW5pdGlhbGl6ZWRcbiAgICAgICAgICAgICAgICAmJiBvcGVyYXRpb24gIT09IEZzTGlzdFN0YXRlLlJlbG9hZFxuICAgICAgICAgICAgICApIHtcblxuICAgICAgICAgICAgICAgIHRoaXMuZGF0YUNvbnRyb2xsZXIuc2V0T3BlcmF0aW9uKEZzTGlzdFN0YXRlLkxvYWQpO1xuICAgICAgICAgICAgICAgIHN0YXJ0TG9hZGluZyA9IHRydWU7XG5cbiAgICAgICAgICAgICAgfSBlbHNlIGlmIChcbiAgICAgICAgICAgICAgICBvcGVyYXRpb24gPT09IEZzTGlzdFN0YXRlLlJlbG9hZCB8fFxuICAgICAgICAgICAgICAgIG9wZXJhdGlvbiA9PT0gRnNMaXN0U3RhdGUuRmlsdGVyIHx8XG4gICAgICAgICAgICAgICAgb3BlcmF0aW9uID09PSBGc0xpc3RTdGF0ZS5Tb3J0XG4gICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgIHN0YXJ0TG9hZGluZyA9IHRydWU7XG4gICAgICAgICAgICAgIH0gZWxzZSBpZiAodGhpcy5wYWdpbmcuaW5pdGlhbGl6ZWQgJiYgdGhpcy5wYWdpbmcuaGFzTmV4dFBhZ2UpIHtcbiAgICAgICAgICAgICAgICAvLyBMb2FkaW5nIGlmIGNvbnRlbnQgaGFzIGJlZW4gc2Nyb2xsZWRcbiAgICAgICAgICAgICAgICBzdGFydExvYWRpbmcgPSB0cnVlO1xuICAgICAgICAgICAgICAgIHRoaXMuZGF0YUNvbnRyb2xsZXIuc2V0T3BlcmF0aW9uKEZzTGlzdFN0YXRlLkxvYWQpO1xuICAgICAgICAgICAgICAgIHRoaXMucGFnaW5nLmdvTmV4dCgpO1xuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgaWYgKHN0YXJ0TG9hZGluZykge1xuICAgICAgICAgICAgICAgIHRoaXMuX2ZldGNoJC5uZXh0KCk7XG4gICAgICAgICAgICAgICAgZnNTY3JvbGxJbnN0YW5jZS5sb2FkaW5nKCk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgdGhpcy5kYXRhQ29udHJvbGxlci5yZW1vdGVSb3dzQ2hhbmdlJFxuICAgICAgICAgICAgLnBpcGUoXG4gICAgICAgICAgICAgIHRha2VVbnRpbCh0aGlzLl9kZXN0cm95JCksXG4gICAgICAgICAgICApXG4gICAgICAgICAgICAuc3Vic2NyaWJlKCgpID0+IHtcbiAgICAgICAgICAgICAgZnNTY3JvbGxJbnN0YW5jZS5sb2FkZWQoKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVXBkYXRlIGFuZCB3YXRjaCBmaWx0ZXIgY2hhbmdlc1xuICAgKi9cbiAgcHJpdmF0ZSBfaW5pdEZpbHRlcnMoKSB7XG4gICAgaWYgKHRoaXMuZmlsdGVyQ29uZmlnKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3Qgc29ydFZhbHVlcyA9IHRoaXMuc29ydGluZy5tYWtlU29ydGluZ0xpc3QoKTtcblxuICAgIGNvbnN0IHNvcnRDb25maWcgPSB0aGlzLnNvcnRpbmcuc29ydGluZ0NvbHVtblxuICAgICAgPyB7IHZhbHVlOiB0aGlzLnNvcnRpbmcuc29ydGluZ0NvbHVtbi5uYW1lLCBkaXJlY3Rpb246IHRoaXMuc29ydGluZy5zb3J0aW5nQ29sdW1uLmRpcmVjdGlvbiB9XG4gICAgICA6IG51bGw7XG5cbiAgICAvLyBDb25maWdcbiAgICB0aGlzLmZpbHRlckNvbmZpZyA9IHtcbiAgICAgIHBlcnNpc3Q6IHRoaXMucGVyc2lzdCxcbiAgICAgIGl0ZW1zOiB0aGlzLmZpbHRlcnMgfHwgW10sXG4gICAgICBzYXZlZEZpbHRlcnM6IHRoaXMuc2F2ZWRGaWx0ZXJzLFxuICAgICAgLy8gaW5saW5lOiB0aGlzLmlubGluZUZpbHRlcnMsXG4gICAgICBhY3Rpb25zOiB0aGlzLmFjdGlvbnMuYWN0aW9ucyxcbiAgICAgIHF1ZXJ5UGFyYW06IHRoaXMucXVlcnlQYXJhbSxcbiAgICAgIGF1dG9mb2N1czogdGhpcy5hdXRvRm9jdXMsXG4gICAgICBzb3J0czogc29ydFZhbHVlcyxcbiAgICAgIHNvcnQ6IHNvcnRDb25maWcsXG4gICAgICBjaGlwczogdGhpcy5jaGlwcyxcbiAgICAgIGF1dG9SZWxvYWQ6IHRoaXMuYXV0b1JlbG9hZCxcbiAgICAgIGluaXQ6IHRoaXMuX2ZpbHRlckluaXQuYmluZCh0aGlzKSxcbiAgICAgIGNoYW5nZTogdGhpcy5fZmlsdGVyQ2hhbmdlLmJpbmQodGhpcyksXG4gICAgICByZWxvYWQ6ICh0aGlzLl9jb25maWcucmVsb2FkID8/IHRydWUpID8gdGhpcy5yZWxvYWQuYmluZCh0aGlzKSA6IG51bGwsXG4gICAgICBzb3J0Q2hhbmdlOiB0aGlzLl9maWx0ZXJTb3J0LmJpbmQodGhpcyksXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDYWxsYmFjayB3aGVuIEZpbHRlciBoYXMgYmVlbiBpbml0aWFsaXplZFxuICAgKlxuICAgKiBAcGFyYW0gZmlsdGVyc1xuICAgKi9cbiAgcHJpdmF0ZSBfZmlsdGVySW5pdChmaWx0ZXJzKSB7XG4gICAgaWYgKHRoaXMuZmlsdGVySW5pdENiKSB7XG4gICAgICB0aGlzLmZpbHRlckluaXRDYihmaWx0ZXJzKTtcbiAgICB9XG5cbiAgICB0aGlzLl9maWx0ZXJzUXVlcnkubmV4dChmaWx0ZXJzKTtcblxuICAgIHRoaXMuX2NoZWNrUmVzdG9yZUZpbHRlcigpO1xuICB9XG5cbiAgLyoqXG4gICAqIENhbGxiYWNrIHdoZW4gRmlsdGVyIGhhcyBiZWVuIGNoYW5nZWRcbiAgICpcbiAgICogQHBhcmFtIGZpbHRlclF1ZXJ5XG4gICAqIEBwYXJhbSBmaWx0ZXJTb3J0XG4gICAqL1xuICBwcml2YXRlIF9maWx0ZXJDaGFuZ2UoZmlsdGVyUXVlcnksIGZpbHRlclNvcnQpIHtcbiAgICBpZiAodGhpcy5maWx0ZXJDaGFuZ2VDYikge1xuICAgICAgdGhpcy5maWx0ZXJDaGFuZ2VDYihmaWx0ZXJRdWVyeSwgZmlsdGVyU29ydCk7XG4gICAgfVxuXG4gICAgdGhpcy5fZmlsdGVyc1F1ZXJ5Lm5leHQoZmlsdGVyUXVlcnkpO1xuXG4gICAgdGhpcy5yZXN0b3JlTW9kZSA9IGZhbHNlO1xuXG4gICAgLy8gUmVzdG9yZSBvcHRpb25cbiAgICB0aGlzLl9jaGVja1Jlc3RvcmVGaWx0ZXIoKTtcblxuICAgIGlmICh0aGlzLnJlc3RvcmUgJiYgdGhpcy5yZXN0b3JlLnJlbG9hZCkge1xuICAgICAgdGhpcy5yZWxvYWQoKTtcbiAgICB9XG5cbiAgICB0aGlzLmRhdGFDb250cm9sbGVyLnNldE9wZXJhdGlvbihGc0xpc3RTdGF0ZS5GaWx0ZXIpO1xuXG4gICAgLy8gUmVzZXQgcGFnaW5nIGZvciByZXF1ZXN0IHdpdGggY29ycmVjdCBvZmZzZXRcbiAgICB0aGlzLnBhZ2luZy5yZXNldFBhZ2luZygpO1xuXG4gICAgaWYgKHRoaXMuZnNTY3JvbGxJbnN0YW5jZSkge1xuICAgICAgdGhpcy5kYXRhQ29udHJvbGxlci5jbGVhclJvd3MoKTtcbiAgICAgIHRoaXMuZnNTY3JvbGxJbnN0YW5jZS5yZWxvYWQoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5fZmV0Y2gkLm5leHQoKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIF9jaGVja1Jlc3RvcmVGaWx0ZXIoKSB7XG4gICAgLy8gUmVzdG9yZSBvcHRpb25cbiAgICBpZiAodGhpcy5yZXN0b3JlICYmIHRoaXMuZmlsdGVyc1F1ZXJ5W3Nob3dEZWxldGVkRmlsdGVyS2V5XSkge1xuICAgICAgZGVsZXRlIHRoaXMuZmlsdGVyc1F1ZXJ5W3Nob3dEZWxldGVkRmlsdGVyS2V5XTtcblxuICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLmZpbHRlcnNRdWVyeSwgdGhpcy5yZXN0b3JlLnF1ZXJ5KTtcblxuICAgICAgdGhpcy5yZXN0b3JlTW9kZSA9IHRydWU7XG4gICAgfVxuICB9XG5cbiAgLy8gQ2FsbGJhY2sgd2hlbiBGaWx0ZXIgc29ydCBoYXMgYmVlbiBjaGFuZ2VkXG4gIHByaXZhdGUgX2ZpbHRlclNvcnQoZmlsdGVyUXVlcnksIGZpbHRlclNvcnQpIHtcbiAgICBpZiAoZmlsdGVyU29ydCkge1xuICAgICAgdGhpcy5zb3J0aW5nLnNvcnRCeUNvbHVtbldpdGhOYW1lKGZpbHRlclNvcnQudmFsdWUpO1xuXG4gICAgICBjb25zdCBzb3J0RGlyZWN0aW9uID0gZmlsdGVyU29ydC5kaXJlY3Rpb24gPT09ICdhc2MnID8gU29ydGluZ0RpcmVjdGlvbi5hc2MgOiBTb3J0aW5nRGlyZWN0aW9uLmRlc2M7XG4gICAgICB0aGlzLnNvcnRpbmcuc29ydERpcmVjdGlvbihzb3J0RGlyZWN0aW9uKTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gRklYTUUgbmVlZCB0byBiZSByZWZhY3RvcmVkLi4uXG4gICAgICB0aGlzLnNvcnRpbmcuc29ydGluZ0NvbHVtbiA9IHVuZGVmaW5lZDtcbiAgICAgIHRoaXMucmVsb2FkKCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBfY29tcGxldGVGZXRjaChwYXJhbXMsIHF1ZXJ5LCByZXNwb25zZSkge1xuICAgIGlmICghdGhpcy5wYWdpbmcucGFnZSkge1xuICAgICAgdGhpcy5wYWdpbmcucGFnZSA9IDE7XG4gICAgfVxuXG4gICAgaWYgKHJlc3BvbnNlLnBhZ2luZykge1xuICAgICAgY29uc3QgZGlzcGxheWVkID0gKEFycmF5LmlzQXJyYXkocmVzcG9uc2UuZGF0YSkgJiYgcmVzcG9uc2UuZGF0YS5sZW5ndGgpIHx8IDA7XG4gICAgICB0aGlzLnBhZ2luZy51cGRhdGVQYWdpbmcoXG4gICAgICAgIHJlc3BvbnNlLnBhZ2luZyxcbiAgICAgICAgZGlzcGxheWVkLFxuICAgICAgICB0aGlzLmRhdGFDb250cm9sbGVyLm9wZXJhdGlvbiA9PT0gRnNMaXN0U3RhdGUuTG9hZE1vcmUsXG4gICAgICApO1xuICAgIH0gZWxzZSBpZiAodGhpcy5wYWdpbmcuZW5hYmxlZCkge1xuICAgICAgY29uc29sZS5sb2coXG4gICAgICAgICclYyBGc0xpc3QgV2FybmluZyAnLFxuICAgICAgICAnY29sb3I6IHdoaXRlOyBiYWNrZ3JvdW5kLWNvbG9yOiAjZmZjYzBiJyxcbiAgICAgICAgJ1BhZ2luYXRpb24gZG9lcyBub3QgY29uZmlndXJlZCBwcm9wZXJseS4gJyArXG4gICAgICAgICdQYWdpbmF0aW9uIGlzIGVuYWJsZWQsIGJ1dCBodHRwIHJlc3BvbnNlIGRvZXMgbm90IGNvbnRhaW4gXCJwYWdpbmdcIiBmaWVsZC4gJyArXG4gICAgICAgICdZb3UgaGF2ZSB0byBzZXQgXCJwYWdpbmc6IGZhbHNlXCIgaW4gY29uZmlnIG9yIGFkZCBcInBhZ2luZ1wiIGZpZWxkIHRvIHJlc3BvbnNlLicsXG4gICAgICApO1xuICAgIH1cblxuICAgIC8vLyBtdXN0IGJlIGJlZm9yZSBzZWxlY3Rpb24sIGJlY2F1c2Ugc2VsZXRpb24gdXNlIHJlY29yZHNcbiAgICB0aGlzLmRhdGFDb250cm9sbGVyLnNldFJvd3NGcm9tUmVzcG9uc2UocmVzcG9uc2UuZGF0YSk7XG4gICAgLy8vXG5cbiAgICB0aGlzLl9jb21wbGV0ZUZldGNoVXBkYXRlU2VsZWN0b24ocmVzcG9uc2UpO1xuXG4gICAgaWYgKHRoaXMuZW1wdHlTdGF0ZT8udmFsaWRhdGUgJiYgdGhpcy5lbXB0eVN0YXRlVGVtcGxhdGUpIHtcbiAgICAgIHRoaXMuZW1wdHlTdGF0ZUVuYWJsZWQgPSB0aGlzLmVtcHR5U3RhdGUudmFsaWRhdGUocXVlcnksIGNsb25lRGVlcCh0aGlzLmRhdGFDb250cm9sbGVyLnZpc2libGVSb3dzRGF0YSkpO1xuICAgIH1cblxuICAgIGlmICh0aGlzLmFmdGVyRmV0Y2hGbikge1xuICAgICAgdGhpcy5hZnRlckZldGNoRm4ocXVlcnksIHRoaXMuZGF0YUNvbnRyb2xsZXIudmlzaWJsZVJvd3NEYXRhKTtcbiAgICB9XG5cbiAgICAvLyBjYXNlIHdoZW4gaGF2ZSByZW1vdmVkIGFsbCByZXN1bHRzIGZyb20gbGFzdCBwYWdlXG4gICAgaWYgKHRoaXMuZGF0YUNvbnRyb2xsZXIudmlzaWJsZVJvd3MubGVuZ3RoID09PSAwXG4gICAgICAmJiB0aGlzLnBhZ2luZy5wYWdlID4gMVxuICAgICAgJiYgdGhpcy5wYWdpbmcucGFnZSA+IHRoaXMucGFnaW5nLnBhZ2VzXG4gICAgKSB7XG4gICAgICB0aGlzLnBhZ2luZy5nb0xhc3QoKTtcbiAgICB9XG5cbiAgICB0aGlzLmZldGNoQ29tcGxldGUkLm5leHQoeyBzY3JvbGxJbnRvVmlldzogcGFyYW1zPy5zY3JvbGxJbnRvVmlldyB9KTtcbiAgICB0aGlzLmxvYWRpbmckLm5leHQoZmFsc2UpO1xuICB9XG5cbiAgcHJpdmF0ZSBfY29tcGxldGVGZXRjaFVwZGF0ZVNlbGVjdG9uKHJlc3BvbnNlKSB7XG4gICAgLy8gVXBkYXRlIHNlbGVjdGlvbiBwYXJhbXNcbiAgICBpZiAodGhpcy5zZWxlY3Rpb24pIHtcbiAgICAgIGlmICh0aGlzLnBhZ2luZy5lbmFibGVkKSB7XG4gICAgICAgIHRoaXMuc2VsZWN0aW9uLnBhZ2VDaGFuZ2VkKHRoaXMuc2Nyb2xsYWJsZSk7XG4gICAgICAgIHRoaXMuc2VsZWN0aW9uLnVwZGF0ZVZpc2libGVSZWNvcmRzQ291bnQodGhpcy5wYWdpbmcuZ2V0VmlzaWJsZVJlY29yZHMoKSk7XG4gICAgICAgIHRoaXMuc2VsZWN0aW9uLnVwZGF0ZVRvdGFsUmVjb3Jkc0NvdW50KHRoaXMucGFnaW5nLnJlY29yZHMpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc3QgY291bnQgPSByZXNwb25zZS5wYWdpbmcgJiYgcmVzcG9uc2UucGFnaW5nLnJlY29yZHNcbiAgICAgICAgICB8fCBBcnJheS5pc0FycmF5KHJlc3BvbnNlLmRhdGEpICYmIHJlc3BvbnNlLmRhdGEubGVuZ3RoO1xuXG4gICAgICAgIHRoaXMuc2VsZWN0aW9uLnVwZGF0ZVZpc2libGVSZWNvcmRzQ291bnQoY291bnQpO1xuICAgICAgICB0aGlzLnNlbGVjdGlvbi51cGRhdGVUb3RhbFJlY29yZHNDb3VudChjb3VudCk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuc2VsZWN0aW9uLnNlbGVjdGVkUm93c0ludGVyc2VjdGlvbih0aGlzLmRhdGFDb250cm9sbGVyLnZpc2libGVSb3dzRGF0YSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFdpbGwgZG8gc29tZSBhY3Rpb25zIGlmIHlvdSByZW1vdmVkIGl0ZW0gYW5kIGl0ZW0gd2FzIGxhc3Qgb24gaGlzIG93biBwYWdlXG4gICAqXG4gICAqIEV4OiBpZiBsaXN0IGhhcyAzIHBhZ2VzIGFuZCBvbiB0aGlyZCBwYWdlIHlvdSBoYXZlIG9ubHkgb25lIGl0ZW0uIEFuZCB5b3UganVzdCBkZWxldGVkIHRoaXMgaXRlbS5cbiAgICogWW91IG11c3QgZ28gdG8gc2Vjb25kIHBhZ2UsIGJ1dCBpZiBpdCB3YXMgbGFzdCBwYWdlIGFuZCB5b3UgY2FuJ3QgZ28gYmFjayAtPiBqdXN0IHJlbG9hZFxuICAgKlxuICAgKiBAcGFyYW0gZGVsZXRlZENvdW50XG4gICAqL1xuICBwcml2YXRlIF9ub0RhdGFQYWdpbmF0aW9uVXBkYXRlKGRlbGV0ZWRDb3VudCkge1xuICAgIGlmICghdGhpcy5kYXRhQ29udHJvbGxlci5oYXNEYXRhKSB7XG4gICAgICBpZiAodGhpcy5wYWdpbmcucGFnZSA+IDEpIHtcbiAgICAgICAgdGhpcy5wYWdpbmcuZ29Ub1BhZ2UodGhpcy5wYWdpbmcucGFnZSAtIDEgfHwgMSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLnJlbG9hZCgpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRoaXMucGFnaW5nLnJlY29yZHMgLT0gZGVsZXRlZENvdW50O1xuICAgIHRoaXMucGFnaW5nLnVwZGF0ZVBhZ2luYXRpb24oKTtcblxuICAgIGlmICh0aGlzLmRhdGFDb250cm9sbGVyLmhhc0RhdGEgJiYgdGhpcy5zZWxlY3Rpb24pIHtcbiAgICAgIHRoaXMuc2VsZWN0aW9uLnVwZGF0ZVZpc2libGVSZWNvcmRzQ291bnQodGhpcy5kYXRhQ29udHJvbGxlci52aXNpYmxlUm93c0NvdW50KTtcbiAgICAgIHRoaXMuc2VsZWN0aW9uLnVwZGF0ZVRvdGFsUmVjb3Jkc0NvdW50KHRoaXMucGFnaW5nLnJlY29yZHMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBUZW1wb3Jhcnkgc29sdXRpb24sIHdpbGwgZG8gYXV0byBzdWJzY3JpYmUgaWYgd2FzIHJldHVybmVkIE9ic2VydmFibGUuXG4gICAqXG4gICAqIFRPRE86IE1PVkUgVEhJUyBQRUFDRSBPRiBDT0RFIFRPIFNQRUNJQUwgUExBQ0VcbiAgICpcbiAgICogQHBhcmFtIHJlc3RvcmVDbGlja0NhbGxiYWNrXG4gICAqIEBwYXJhbSByb3dcbiAgICovXG4gIHByaXZhdGUgX3Jlc3RvcmVDbGljayhyZXN0b3JlQ2xpY2tDYWxsYmFjaywgcm93KSB7XG4gICAgY29uc3QgcmVzdG9yZUNsaWNrUmVzdWx0ID0gcmVzdG9yZUNsaWNrQ2FsbGJhY2socm93KTtcblxuICAgIGlmIChyZXN0b3JlQ2xpY2tSZXN1bHQgaW5zdGFuY2VvZiBPYnNlcnZhYmxlKSB7XG4gICAgICByZXN0b3JlQ2xpY2tSZXN1bHRcbiAgICAgICAgLnBpcGUoXG4gICAgICAgICAgdGFrZSgxKSxcbiAgICAgICAgICB0YWtlVW50aWwodGhpcy5fZGVzdHJveSQpLFxuICAgICAgICApXG4gICAgICAgIC5zdWJzY3JpYmUoe1xuICAgICAgICAgIG5leHQ6ICgpID0+IHRoaXMucmVsb2FkKCksXG4gICAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgX3VwZGF0ZVNvcnRpbmdDb2x1bW5zKCk6IHZvaWQge1xuICAgIHRoaXMuc29ydGluZy5jbGVhclNvcnRhYmxlQ29sdW1ucygpO1xuICAgIHRoaXMuY29sdW1ucy5jb2x1bW5zXG4gICAgICAuZmlsdGVyKChjb2x1bW4pID0+IGNvbHVtbi5zb3J0YWJsZSAmJiBjb2x1bW4udmlzaWJsZSlcbiAgICAgIC5mb3JFYWNoKChjb2x1bW4pID0+IHtcbiAgICAgICAgdGhpcy5zb3J0aW5nLmFkZFNvcnRhYmxlQ29sdW1uKGNvbHVtbik7XG4gICAgICB9KTtcbiAgfVxufVxuIl19