@esfaenza/es-table 13.1.12 → 13.1.15

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 (129) hide show
  1. package/esm2020/lib/components/es-table/es_table.component.mjs +102 -21
  2. package/esm2020/lib/core/handlers/ColumnMetadataHandler.mjs +777 -0
  3. package/esm2020/lib/core/handlers/DynamicModeHandler.mjs +63 -0
  4. package/esm2020/lib/core/handlers/ExportHandler.mjs +103 -0
  5. package/esm2020/lib/core/handlers/HierarchyModeHandler.mjs +136 -0
  6. package/esm2020/lib/core/handlers/ItemsHandler.mjs +111 -0
  7. package/esm2020/lib/core/handlers/ReportModeHandler.mjs +70 -0
  8. package/esm2020/lib/core/handlers/RowGroupingHandler.mjs +480 -0
  9. package/esm2020/lib/core/handlers/SelectionHandler.mjs +524 -0
  10. package/esm2020/lib/core/handlers/UtilitiesHandler.mjs +152 -0
  11. package/esm2020/lib/directives/es_td.directive.mjs +3 -1
  12. package/esm2020/lib/directives/es_th.directive.mjs +17 -5
  13. package/esm2020/lib/domain/configuration/EsTableDefaultable.mjs +1 -1
  14. package/esm2020/lib/domain/configuration/EsTableModuleConfig.mjs +1 -1
  15. package/esm2020/lib/domain/externals/CornerMenuOption.mjs +4 -0
  16. package/esm2020/lib/domain/externals/EsTableColumnsDefinition.mjs +31 -0
  17. package/esm2020/lib/domain/externals/EsTableOperationDefinition.mjs +22 -0
  18. package/esm2020/lib/domain/externals/appsearch/AppOrdering.mjs +16 -0
  19. package/esm2020/lib/domain/externals/appsearch/AppSearch.mjs +35 -0
  20. package/esm2020/lib/domain/externals/appsearch/EsTableMultiValue.mjs +25 -0
  21. package/esm2020/lib/domain/externals/appsearch/GenericItem.mjs +11 -0
  22. package/esm2020/lib/domain/externals/appsearch/Group.mjs +17 -0
  23. package/esm2020/lib/domain/externals/appsearch/GroupAggregation.mjs +16 -0
  24. package/esm2020/lib/domain/externals/appsearch/GroupFilter.mjs +14 -0
  25. package/esm2020/lib/domain/externals/appsearch/GroupOrAggregation.mjs +16 -0
  26. package/esm2020/lib/domain/externals/appsearch/ItemsSelection.mjs +23 -0
  27. package/esm2020/lib/domain/externals/report/ReportColumn.mjs +4 -0
  28. package/esm2020/lib/domain/externals/report/ReportDefinition.mjs +4 -0
  29. package/esm2020/lib/domain/externals/report/ReportOrder.mjs +4 -0
  30. package/esm2020/lib/domain/externals/report/ReportParam.mjs +4 -0
  31. package/esm2020/lib/domain/externals/report/ReportResult.mjs +4 -0
  32. package/esm2020/lib/domain/externals/report/ReportRow.mjs +4 -0
  33. package/esm2020/lib/domain/internals/CacheTriptic.mjs +16 -0
  34. package/esm2020/lib/domain/internals/EsTableColumn.mjs +31 -0
  35. package/esm2020/lib/domain/internals/GroupPager.mjs +22 -0
  36. package/esm2020/lib/domain/internals/GroupRouteFragment.mjs +17 -0
  37. package/esm2020/lib/domain/internals/TdElement.mjs +2 -0
  38. package/esm2020/lib/domain/internals/ThAggregation.mjs +16 -0
  39. package/esm2020/lib/domain/internals/ThElement.mjs +2 -0
  40. package/esm2020/lib/es-table.module.mjs +11 -6
  41. package/esm2020/public-api.mjs +19 -5
  42. package/fesm2015/esfaenza-es-table.mjs +687 -484
  43. package/fesm2015/esfaenza-es-table.mjs.map +1 -1
  44. package/fesm2020/esfaenza-es-table.mjs +670 -467
  45. package/fesm2020/esfaenza-es-table.mjs.map +1 -1
  46. package/lib/components/es-table/es_table.component.d.ts +38 -6
  47. package/lib/core/handlers/{classes/ColumnMetadataHandler.d.ts → ColumnMetadataHandler.d.ts} +18 -11
  48. package/lib/core/handlers/{classes/DynamicModeHandler.d.ts → DynamicModeHandler.d.ts} +2 -2
  49. package/lib/core/handlers/{classes/ExportHandler.d.ts → ExportHandler.d.ts} +1 -1
  50. package/lib/core/handlers/{classes/HierarchyModeHandler.d.ts → HierarchyModeHandler.d.ts} +1 -1
  51. package/lib/core/handlers/{classes/ItemsHandler.d.ts → ItemsHandler.d.ts} +1 -1
  52. package/lib/core/handlers/{classes/ReportModeHandler.d.ts → ReportModeHandler.d.ts} +2 -2
  53. package/lib/core/handlers/{classes/RowGroupingHandler.d.ts → RowGroupingHandler.d.ts} +8 -3
  54. package/lib/core/handlers/{classes/SelectionHandler.d.ts → SelectionHandler.d.ts} +3 -3
  55. package/lib/core/handlers/{classes/UtilitiesHandler.d.ts → UtilitiesHandler.d.ts} +0 -0
  56. package/lib/directives/es_td.directive.d.ts +2 -0
  57. package/lib/directives/es_th.directive.d.ts +20 -6
  58. package/lib/domain/configuration/EsTableDefaultable.d.ts +1 -0
  59. package/lib/domain/configuration/EsTableModuleConfig.d.ts +1 -1
  60. package/lib/domain/externals/{classes/CornerMenuOption.d.ts → CornerMenuOption.d.ts} +0 -0
  61. package/lib/domain/externals/{classes/EsTableColumnsDefinition.d.ts → EsTableColumnsDefinition.d.ts} +0 -0
  62. package/lib/domain/externals/{classes/EsTableOperationDefinition.d.ts → EsTableOperationDefinition.d.ts} +0 -0
  63. package/lib/domain/externals/{classes/appsearch → appsearch}/AppOrdering.d.ts +0 -0
  64. package/lib/domain/externals/{classes/appsearch → appsearch}/AppSearch.d.ts +0 -0
  65. package/lib/domain/externals/appsearch/EsTableMultiValue.d.ts +22 -0
  66. package/lib/domain/externals/{classes/appsearch → appsearch}/GenericItem.d.ts +0 -0
  67. package/lib/domain/externals/{classes/appsearch → appsearch}/Group.d.ts +0 -0
  68. package/lib/domain/externals/{classes/appsearch → appsearch}/GroupAggregation.d.ts +0 -0
  69. package/lib/domain/externals/{classes/appsearch → appsearch}/GroupFilter.d.ts +0 -0
  70. package/lib/domain/externals/{classes/appsearch → appsearch}/GroupOrAggregation.d.ts +0 -0
  71. package/lib/domain/externals/{classes/appsearch → appsearch}/ItemsSelection.d.ts +1 -1
  72. package/lib/domain/externals/{classes/report → report}/ReportColumn.d.ts +0 -0
  73. package/lib/domain/externals/{classes/report → report}/ReportDefinition.d.ts +3 -1
  74. package/lib/domain/externals/{classes/report → report}/ReportOrder.d.ts +0 -0
  75. package/lib/domain/externals/{classes/report → report}/ReportParam.d.ts +0 -0
  76. package/lib/domain/externals/{classes/report → report}/ReportResult.d.ts +2 -1
  77. package/lib/domain/externals/{classes/report → report}/ReportRow.d.ts +0 -0
  78. package/lib/domain/internals/{classes/CacheTriptic.d.ts → CacheTriptic.d.ts} +0 -0
  79. package/lib/domain/internals/{classes/EsTableColumn.d.ts → EsTableColumn.d.ts} +14 -3
  80. package/lib/domain/internals/{classes/GroupPager.d.ts → GroupPager.d.ts} +2 -1
  81. package/lib/domain/internals/{classes/GroupRouteFragment.d.ts → GroupRouteFragment.d.ts} +0 -0
  82. package/lib/domain/internals/TdElement.d.ts +42 -0
  83. package/lib/domain/internals/{classes/ThAggregation.d.ts → ThAggregation.d.ts} +0 -0
  84. package/lib/domain/internals/{classes/ThElement.d.ts → ThElement.d.ts} +0 -0
  85. package/lib/es-table.module.d.ts +2 -1
  86. package/package.json +2 -1
  87. package/public-api.d.ts +18 -1
  88. package/esm2020/lib/core/handlers/classes/ColumnMetadataHandler.mjs +0 -667
  89. package/esm2020/lib/core/handlers/classes/DynamicModeHandler.mjs +0 -64
  90. package/esm2020/lib/core/handlers/classes/ExportHandler.mjs +0 -103
  91. package/esm2020/lib/core/handlers/classes/HierarchyModeHandler.mjs +0 -136
  92. package/esm2020/lib/core/handlers/classes/ItemsHandler.mjs +0 -111
  93. package/esm2020/lib/core/handlers/classes/ReportModeHandler.mjs +0 -70
  94. package/esm2020/lib/core/handlers/classes/RowGroupingHandler.mjs +0 -477
  95. package/esm2020/lib/core/handlers/classes/SelectionHandler.mjs +0 -525
  96. package/esm2020/lib/core/handlers/classes/UtilitiesHandler.mjs +0 -152
  97. package/esm2020/lib/core/handlers/index.mjs +0 -10
  98. package/esm2020/lib/domain/externals/classes/CornerMenuOption.mjs +0 -4
  99. package/esm2020/lib/domain/externals/classes/EsTableColumnsDefinition.mjs +0 -31
  100. package/esm2020/lib/domain/externals/classes/EsTableOperationDefinition.mjs +0 -22
  101. package/esm2020/lib/domain/externals/classes/appsearch/AppOrdering.mjs +0 -16
  102. package/esm2020/lib/domain/externals/classes/appsearch/AppSearch.mjs +0 -35
  103. package/esm2020/lib/domain/externals/classes/appsearch/GenericItem.mjs +0 -11
  104. package/esm2020/lib/domain/externals/classes/appsearch/Group.mjs +0 -17
  105. package/esm2020/lib/domain/externals/classes/appsearch/GroupAggregation.mjs +0 -16
  106. package/esm2020/lib/domain/externals/classes/appsearch/GroupFilter.mjs +0 -14
  107. package/esm2020/lib/domain/externals/classes/appsearch/GroupOrAggregation.mjs +0 -16
  108. package/esm2020/lib/domain/externals/classes/appsearch/ItemsSelection.mjs +0 -23
  109. package/esm2020/lib/domain/externals/classes/report/ReportColumn.mjs +0 -4
  110. package/esm2020/lib/domain/externals/classes/report/ReportDefinition.mjs +0 -4
  111. package/esm2020/lib/domain/externals/classes/report/ReportOrder.mjs +0 -4
  112. package/esm2020/lib/domain/externals/classes/report/ReportParam.mjs +0 -4
  113. package/esm2020/lib/domain/externals/classes/report/ReportResult.mjs +0 -4
  114. package/esm2020/lib/domain/externals/classes/report/ReportRow.mjs +0 -4
  115. package/esm2020/lib/domain/externals/index.mjs +0 -18
  116. package/esm2020/lib/domain/index.mjs +0 -3
  117. package/esm2020/lib/domain/internals/classes/CacheTriptic.mjs +0 -16
  118. package/esm2020/lib/domain/internals/classes/EsTableColumn.mjs +0 -26
  119. package/esm2020/lib/domain/internals/classes/GroupPager.mjs +0 -22
  120. package/esm2020/lib/domain/internals/classes/GroupRouteFragment.mjs +0 -17
  121. package/esm2020/lib/domain/internals/classes/TdElement.mjs +0 -2
  122. package/esm2020/lib/domain/internals/classes/ThAggregation.mjs +0 -16
  123. package/esm2020/lib/domain/internals/classes/ThElement.mjs +0 -2
  124. package/esm2020/lib/domain/internals/index.mjs +0 -8
  125. package/lib/core/handlers/index.d.ts +0 -9
  126. package/lib/domain/externals/index.d.ts +0 -17
  127. package/lib/domain/index.d.ts +0 -2
  128. package/lib/domain/internals/classes/TdElement.d.ts +0 -19
  129. package/lib/domain/internals/index.d.ts +0 -7
@@ -1,477 +0,0 @@
1
- // Modelli
2
- import { Group, GroupAggregation, GroupOrAggregation, GroupPager, GroupRouteFragment } from "../../../domain";
3
- /** Classe che gestisce la modalità Row Grouping dell'es-table */
4
- export class RowGroupingHandler {
5
- /** @ignore Costruttore */
6
- constructor(est, utilities, dateExts) {
7
- this.est = est;
8
- this.utilities = utilities;
9
- this.dateExts = dateExts;
10
- /** Cache per salvare per ogni chiave di ogni gruppo chi è il gruppo rappresentato */
11
- this.rgGroupCache = new Map();
12
- /** Cache per salvare per ogni chiave di ogni gruppo chi sono gli oggetti sottostanti, non dei sottogruppi */
13
- this.rgItemCache = new Map();
14
- /** Cache per salvare per ogni chiave di ogni gruppo chi sono gli oggetti sottostanti, non dei sottogruppi */
15
- this.rgChildGroupsCache = new Map();
16
- }
17
- /**
18
- * In modalità rowgrouping quando mi arriva un nuovo blocco di oggetti devo aggiungerlo alla vista attuale:
19
- *
20
- * 1) Se non viene richiesto il dettaglio di alcun gruppo significa che devo considerare mi siano arrivati tutti i gruppi principali
21
- * 2) Se viene richiesto il dettaglio di un gruppo diverso dall'ultimo devo aggiungere dopo al gruppo cliccato la lista dei sottogruppi
22
- * 2) Se viene richiesto il dettaglio dell'ultimo gruppo devo aggiungere dopo al gruppo cliccato la lista degli oggetti
23
- *
24
- * @param {any} view AppSearch<T> da cui sono arrivati gli oggetti
25
- * @param {number} groupingKeys Livelli di raggruppamento da aspettarsi sui dati
26
- */
27
- handleNewDataOnRowGrouping(view, groupingKeys) {
28
- // 1) Se non viene richiesto il dettaglio di alcun gruppo significa che la chiamata restituisce la lista paginata dei gruppi principali.
29
- // Li tratto come se fosse una qualsiasi altra query paginata su N elementi
30
- if ((view.requestedgroups?.length || 0) == 0) {
31
- this.est.boundSource = this.est.TMPBoundSource;
32
- this.rgGroupCache = new Map();
33
- this.rgItemCache = new Map();
34
- this.rgChildGroupsCache = new Map();
35
- this.est.TMPBoundSource.forEach(itm => {
36
- itm._thisRoute = itm._group ? [{ column: itm.column, value: itm.value }] : [];
37
- itm._thisKey = itm._group ? itm.value : null;
38
- itm._grouplevel = 0;
39
- this.rgGroupCache.set(itm._thisKey, itm);
40
- });
41
- // Resetto la ricerca alla cache di questa "sessione"
42
- let firstItem = this.est.TMPBoundSource[0];
43
- this.est.MainGroupView = Object.assign({}, view);
44
- this.est.groupSearchRequestsCache = [{ path: '', route: [{ column: firstItem.column, value: firstItem.value }], view: this.est.MainGroupView, group_column: this.est.TMPBoundSource[0].column }];
45
- this.est.BaseItemsCount = view.objectcount;
46
- }
47
- else {
48
- // 2) Se viene richiesto il dettaglio di un qualsiasi gruppo diverso dall'ultimo vuol dire che devo aggiungere
49
- // dopo al gruppo che ho cliccato la lista dei gruppi tirata fuori questa volta (intermediateGroup = true)
50
- /*
51
- * GruppoA GruppoA
52
- * GruppoB GruppoB
53
- * GruppoC <- Clicco qui GruppoC
54
- * GruppoD GruppoC1
55
- * GruppoE GruppoC2
56
- * GruppoD
57
- * GruppoE
58
- */
59
- // 3) se i gruppi richiesti dalla view sono uguali ai gruppi presenti vuol dire che sto prendendo gli oggetti veri e propri, sono in
60
- // view.items e quindi in TMPBoundSource, ho inoltre le informazioni di paginazione **per il singolo sottogruppo** (intermediateGroup = false)
61
- /*
62
- * GruppoA GruppoA
63
- * GruppoC1 GruppoC1
64
- * GruppoB GruppoB
65
- * GruppoC GruppoC
66
- * GruppoC1 <-- Clicco qui GruppoC1
67
- * Oggetto1
68
- * Oggetto2
69
- * Oggetto3
70
- * GruppoC2 GruppoC2
71
- * GruppoD GruppoD
72
- * GruppoE GruppoE
73
- */
74
- let intermediateGroup = view.requestedgroups.length != groupingKeys;
75
- let items = this.est.boundSource;
76
- let insertIndex = 0;
77
- let insertGroup = null;
78
- let groupKey = "";
79
- let groupRoute = [];
80
- // Navigo la stuttura dei gruppi ignorando ricorsivamente tutti gli indici fino ai gruppi che mi interessano in modo da non beccare il primo "GruppoC1" del caso sopra
81
- for (let i = 0; i < view.requestedgroups.length; i++) {
82
- let rg = view.requestedgroups[i];
83
- groupKey += rg.value;
84
- groupRoute.push({ column: rg.column, value: rg.value });
85
- for (let i = insertIndex; i < items.length; i++) {
86
- let t = items[i];
87
- if (i >= insertIndex && t._group && t.column == rg.column && t.value == rg.value) {
88
- insertIndex = i;
89
- insertGroup = t;
90
- // Lo marco expanded dato che questo click sul gruppo potrebbe non essere stato fatto
91
- insertGroup._expanded = true;
92
- break;
93
- }
94
- }
95
- }
96
- let itemsCacheReference;
97
- let childGroupsCacheReference;
98
- // Se non è un gruppo intermedio devo ripulire la cache del gruppo su cui ho attualmente cliccato. Gli oggetti saranno riaggiunti dopo
99
- if (!intermediateGroup) {
100
- this.rgItemCache.set(groupKey, []);
101
- itemsCacheReference = this.rgItemCache.get(groupKey);
102
- }
103
- else {
104
- // Se invece è un gruppo intermedio devo ripulire sia tutti i child group ricorsivamente, sia tutti gli item
105
- for (let key of this.rgChildGroupsCache.keys())
106
- if (key.startsWith(groupKey))
107
- this.rgChildGroupsCache.delete(key);
108
- for (let key of this.rgItemCache.keys())
109
- if (key.startsWith(groupKey))
110
- this.rgItemCache.delete(key);
111
- this.rgChildGroupsCache.set(groupKey, []);
112
- childGroupsCacheReference = this.rgChildGroupsCache.get(groupKey);
113
- }
114
- // Assegno un livello ai valori che arrivano da usare per formattare la parte grafica. Il primo gruppo cliccato sarà a livello 1,
115
- // il secondo sarà a livello 2 e così via...
116
- // Li marco inoltre con il parent in modo da poter eliminare i vecchi qualora servisse
117
- this.est.TMPBoundSource.forEach(itm => {
118
- itm._parent = groupKey;
119
- itm._parentRoute = groupRoute;
120
- itm._thisRoute = itm._group ? [...groupRoute, new GroupRouteFragment(itm.column, itm.value)] : [];
121
- itm._thisKey = itm._group ? groupKey + itm.value : groupKey;
122
- // Per le ricerca intermedie metto i gruppi nella cache dei gruppi
123
- if (intermediateGroup) {
124
- itm._grouplevel = view.requestedgroups.length;
125
- this.rgGroupCache.set(itm._thisKey, itm);
126
- childGroupsCacheReference.push(itm);
127
- }
128
- else {
129
- // Metto anche gli oggetti nella cache non ricorsiva
130
- itemsCacheReference.push(itm);
131
- }
132
- });
133
- // Elimino gli oggetti vecchi
134
- // 1) Ricerca intermedia, stato salvato - Elimino tutti gli item e tutti i gruppi la cui route è più lunga della corrente, tutti gli item relativi alla path corrente, e tutte
135
- // le cache di ricerca effettuate su una path più profonda dell'attuale
136
- // 2) Ricerca finale o ricerca intermedia senza stato salvato - Elimino tutti gli item relativi alla path corrente
137
- // Per "stato salvato" si intendono ricerche vecchie salvate per poter essere rieffettuate in caso di ordinamenti su colonne di interesse
138
- if (intermediateGroup && view.savedstate) {
139
- this.est.boundSource = this.est.boundSource.filter(t => !(t._item || t._thisRoute.length > groupRoute.length));
140
- this.est.groupSearchRequestsCache = this.est.groupSearchRequestsCache.filter(t => !(t.route.length > groupRoute.length));
141
- }
142
- else if (intermediateGroup) {
143
- // Se invece lo stato non è salvato vuol dire che c'è stato un cambio di pagina interno ad un gruppo già aperto:
144
- // - Elimino tutti gli elementi riconducibili a questo gruppo che erano già presenti
145
- this.est.boundSource = this.est.boundSource.filter(t => !(t._item || (t._thisKey.startsWith(groupKey) && t._thisKey != groupKey)));
146
- }
147
- this.est.boundSource = this.est.boundSource.filter(t => !(t._parent == groupKey));
148
- let thisGroup = this.est.boundSource[insertIndex];
149
- if (intermediateGroup)
150
- thisGroup._groupscount = this.est.View?.groupcount;
151
- // Li sostituisco coi nuovi di questa ricerca
152
- this.est.boundSource.splice(insertIndex + 1, 0, ...this.est.TMPBoundSource);
153
- // Aggiungo un separatore alla fine o all'inizio di questi gruppi che dovrà occuparsi di caricare ALTRI gruppi o oggetti (se sono all'ultimo gruppo)
154
- let addLast = false;
155
- this.est.boundSource.splice(insertIndex + 1 + (addLast ? this.est.TMPBoundSource.length : 0), 0, this.getGroupSeparator(view, groupKey, groupRoute, view.requestedgroups.length, intermediateGroup ? 'groups' : 'items'));
156
- // Aggiungo la ricerca alla cache di questa "sessione"
157
- let toAdd = { path: groupKey, route: groupRoute, view: Object.assign({}, view), group_column: intermediateGroup ? this.est.TMPBoundSource[0].column : '' };
158
- let prev = this.est.groupSearchRequestsCache.findIndex(t => t.path == toAdd.path && t.group_column == toAdd.group_column);
159
- if (prev == -1)
160
- this.est.groupSearchRequestsCache.push(toAdd);
161
- else
162
- this.est.groupSearchRequestsCache.splice(prev, 1, toAdd);
163
- }
164
- }
165
- /**
166
- * Se in modalità array applica i raggruppamenti definiti lato row-grouping
167
- *
168
- * @param {ths: EsThDirective[]} ths Header
169
- */
170
- arrayModeReviewGroupings(ths) {
171
- if (ths.length == 0)
172
- return;
173
- let headerGroups = [];
174
- let headerAggregations = [];
175
- for (let i = 0; i < ths.length; i++) {
176
- let th = ths[i];
177
- if (th.thGroup)
178
- headerGroups.push(new Group(th.th, 0, ""));
179
- else if (th.thAggregation)
180
- headerAggregations = [...headerAggregations, ...this.getGroupAggregations(th)];
181
- }
182
- if (headerGroups.length > 0) {
183
- // Pulizia delle cache
184
- this.rgGroupCache.clear();
185
- this.rgItemCache.clear();
186
- this.rgChildGroupsCache.clear();
187
- this.est.ArrayGrouping = true;
188
- this.est.boundSource = this.getGroupsRecursive(headerGroups, 0, this.est.boundSource, headerAggregations, null);
189
- }
190
- }
191
- /**
192
- * Data una direttiva EsTh restituisce la lista delle aggregazioni richiesta per questa colonna o il gruppo che rappresenta
193
- *
194
- * @param {EsThDirective} th Direttiva
195
- *
196
- * @returns {GroupOrAggregation[]} Lista dei gruppi o aggregazioni relativi alla Direttiva passata
197
- */
198
- getGroupAggregations(th) {
199
- let ret = [];
200
- // Es: '{min:dd/MM/yyyy} - {max:dd/MM/yyyy}'
201
- if (th.thAggregation) {
202
- this.getEsThDirectiveListOfAggregations(th).forEach((agg) => {
203
- let isdate = agg.format && ['small', 'long', 'verylong'].includes(agg.format);
204
- let isnumber = agg.format && agg.format.startsWith("F") && !Number.isNaN(agg.format.charAt(1)) && agg.format.length == 2;
205
- if (!isdate && !isnumber && agg.format)
206
- throw "Le aggergazioni supportate dall'es-table sono solo 'small', 'long', 'verylong' per le date e 'F0-9' per i numeri";
207
- ret.push(new GroupOrAggregation(th.th, agg.func, isdate ? 'date' : isnumber ? 'number' : 'string'));
208
- });
209
- }
210
- else if (th.thGroup)
211
- ret.push(new GroupOrAggregation(th.th, null));
212
- return ret;
213
- }
214
- /**
215
- * Data una direttiva con un formato restituisce tutte le coppie Funzione di Aggregazione - Formato
216
- *
217
- * @param {EsThDirective} th Direttiva EsTh di cui calcolare le funzioni di aggregazione usate
218
- *
219
- * @returns {{ func: string, format: string }[]} Lista delle funzioni di aggregazione rilevate
220
- */
221
- getEsThDirectiveListOfAggregations(th) {
222
- if (!th.thAggregation)
223
- return [];
224
- // Se ho già effettuato questo calcolo per questo th restituisco la versione in cache
225
- if (th._thAggregations)
226
- return th._thAggregations;
227
- let ret = [];
228
- let display = th.thAggregation;
229
- var matches = display.match(/{[a-zA-Z0-9\/:]*}/gi);
230
- if (!matches)
231
- return [];
232
- matches.forEach(m => {
233
- let split = m.split(":");
234
- let func = m, format = "";
235
- if (split.length > 0) {
236
- // Escludo primo e ultimo carattere (le graffe)
237
- func = split[0].substr(1);
238
- format = split[1].substr(0, split[1].length - 1);
239
- }
240
- ret.push({ func: func, format: format, match: m });
241
- });
242
- th._thAggregations = ret;
243
- return ret;
244
- }
245
- /**
246
- * Data la definizione dei gruppi da generare da una lista di oggetti, suddivide gli oggetti passati in gruppi e sottogruppi
247
- *
248
- * @param {Group[]} grps Definizione dei gruppi
249
- * @param {number} currentIndex Indice di elaborazione. Al livello 0 ho tutti gli oggetti e devo generare i primi gruppi, a livello 1 ho tutti i gruppi principali e devo
250
- * elaborare i sottogruppi, e così via ricorsivamente...
251
- * @param {any[]} items Oggetti da raggruppare
252
- * @param {GroupOrAggregation[]} aggregations Info di aggregazione
253
- * @param {any} parent Riferimento al gruppo padre
254
- */
255
- getGroupsRecursive(grps, currentIndex, items, aggregations, parent) {
256
- // Se l'indice è 0 devo sicuramente nascondere tutti gli oggetti. Solo i gruppi saranno visualizzati
257
- if (currentIndex == 0)
258
- items.forEach(i => i._visible = false);
259
- let grp = grps[currentIndex];
260
- let ret = [];
261
- let last = grps.length == currentIndex + 1;
262
- let groups = this.utilities.groupBy(items, grp.column);
263
- for (let prop in groups) {
264
- let itms = groups[prop];
265
- let gp = new Group(grp.column, itms.length, prop);
266
- gp.aggregations = this.generateAggregations(itms, aggregations);
267
- let anygp = gp;
268
- anygp._group = true;
269
- anygp._expanded = false;
270
- if (!parent) {
271
- anygp._thisRoute = [{ column: gp.column, value: gp.value }];
272
- anygp._thisKey = gp.value;
273
- anygp._grouplevel = 0;
274
- }
275
- else {
276
- anygp._parent = parent._thisKey;
277
- anygp._parentRoute = parent._thisRoute;
278
- anygp._thisRoute = [...parent._thisRoute, { column: gp.column, value: gp.value }];
279
- anygp._thisKey = parent._thisKey + gp.value;
280
- anygp._grouplevel = parent._grouplevel + 1;
281
- }
282
- // Pusho il gruppo, tutti i gruppi del livello sotto, o gli item se io sono l'ultimo gruppo.
283
- // La visibilità è solo per il gruppo a livello 0, tutti gli altri gruppi saranno mostrati o nascosti di conseguenza
284
- if (currentIndex == 0)
285
- anygp._visible = true;
286
- this.utilities.calculateHash([anygp]);
287
- this.utilities.cacheAggregations(anygp);
288
- // Aggiungo il gruppo padre
289
- ret.push(anygp);
290
- this.rgGroupCache.set(anygp._thisKey, anygp);
291
- if (!last) {
292
- //Dal gruppo padre, se non è l'ultimo gruppo della catena, calcolo ricorsivamente tutta la catena sotto
293
- let subGroupsAndItems = this.getGroupsRecursive(grps, currentIndex + 1, itms, aggregations, anygp);
294
- let childgroups = subGroupsAndItems.filter(t => t._group && t._parent == anygp._thisKey);
295
- anygp._groupscount = childgroups.length;
296
- // Aggiungo la catena del gruppo sotto, aggiungendo alla cache solo i gruppi padre
297
- ret.push(...subGroupsAndItems);
298
- this.rgChildGroupsCache.set(anygp._thisKey, childgroups);
299
- }
300
- else {
301
- // Al gruppo padre, se è l'ultimo assegno tutte le foglie assegnandogli anche la chiave del gruppo
302
- itms.forEach(i => i._thisKey = anygp._thisKey);
303
- ret.push(...itms);
304
- this.rgItemCache.set(anygp._thisKey, itms);
305
- }
306
- }
307
- return ret;
308
- }
309
- /**
310
- * Data una lista di oggetti genera le aggregazioni specificate. Si considera di avere tutti gli oggetti
311
- *
312
- * @param {any[]} items Oggetti di cui calcolare le aggregazione
313
- * @param {GroupOrAggregation[]} aggregations Aggergazioni da generare
314
- */
315
- generateAggregations(items, aggregations) {
316
- let rets = [];
317
- let aggregationValue = "", feField = null, stringAgg = null, dateAgg = null, numberAgg = null;
318
- for (let i = 0; i < aggregations.length; i++) {
319
- let agg = aggregations[i];
320
- feField = agg.column;
321
- if (!feField)
322
- continue;
323
- switch (agg.datatype) {
324
- case 'string':
325
- stringAgg = items.map(i => i[feField].toString());
326
- break;
327
- case 'date':
328
- dateAgg = items.map(i => new Date(i[feField]).getTime());
329
- break;
330
- case 'number':
331
- numberAgg = items.map(i => parseFloat(i[feField]));
332
- break;
333
- }
334
- switch (agg.aggregation) {
335
- case 'max':
336
- switch (agg.datatype) {
337
- case 'string':
338
- aggregationValue = stringAgg.sort().reverse()[0];
339
- break;
340
- case 'date':
341
- aggregationValue = new Date(Math.max(...dateAgg)).toString();
342
- break;
343
- case 'number':
344
- aggregationValue = Math.max(...numberAgg).toString();
345
- break;
346
- }
347
- break;
348
- case 'min':
349
- switch (agg.datatype) {
350
- case 'string':
351
- aggregationValue = stringAgg.sort()[0];
352
- break;
353
- case 'date':
354
- aggregationValue = new Date(Math.min(...dateAgg)).toString();
355
- break;
356
- case 'number':
357
- aggregationValue = Math.min(...numberAgg).toString();
358
- break;
359
- }
360
- break;
361
- case 'sum':
362
- switch (agg.datatype) {
363
- case 'string':
364
- aggregationValue = stringAgg.join(", ");
365
- break;
366
- case 'date':
367
- aggregationValue = "";
368
- break;
369
- case 'number':
370
- aggregationValue = numberAgg.reduce((pre, curr) => pre + curr, 0).toString();
371
- break;
372
- }
373
- break;
374
- }
375
- rets.push(new GroupAggregation(agg.column, agg.aggregation, aggregationValue));
376
- }
377
- return rets;
378
- }
379
- /**
380
- * Ottiene un elemento di separazione fra Gruppi che serve per paginare le ricerche all'interno di ogni singolo gruppo
381
- *
382
- * @param {AppSearch<any>} view View utilizzata per la ricerca. Me ne salvo i parametri nel separatore attuale dato che ne ho bisogno per caricare altri elementi
383
- * facenti riferimento allo stesso contesto
384
- * @param {string} parent Parent path che rappresenta a quale gruppo è affibbiato questo separatore
385
- * @param {GroupRouteFragment[]} route Route path che rappresenta a quale gruppo è affibbiato questo separatore
386
- * @param {number} level Livello del gruppo di cui questo elemento è separatore, viene usato per applicare la classe "est-lvl-{{level}}"
387
- *
388
- * @returns {any} Elemento di separazione contenente tutti i bind per presentare una paginazione sotto questo gruppo lato interfaccia
389
- */
390
- getGroupSeparator(view, parent, route, level, searches) {
391
- let item = new GroupPager(level, route, parent, Object.assign({}, view), searches);
392
- item.buttons = this.utilities.getPagesArray(6, view.page, view.pages);
393
- this.utilities.calculateHash([item]);
394
- return item;
395
- }
396
- /**
397
- * Data una colonna effettua la riemissione di tutte le ricerche relative.
398
- *
399
- * Es. Ho 2 campi di gruppo e ho espanso fino a vedere i valori fino ad un livello qualsiasi.
400
- * Clicco l'ordinamento sul secondo gruppo.
401
- * Tutte le ricerche relative ai primi gruppi devono essere rieseguite. Quando i risultati arriveranno ci penserà il metodo **bindDisplayToLoadedItemsOrGroups**
402
- * a tagliare via gli oggetti non più visualizzati
403
- *
404
- * @param {string} column Colonna su cui si è effettuata un'operazione di ordinamento
405
- * @param {AppOrdering[]} orderings Direttive di ordinamento da applicare alle varie sottoricerche
406
- */
407
- emitRowGroupingSearches(column, orderings) {
408
- // Per tutte le ricerche intermedie che devo rivalutare le re-emitto in modo da aggiornargli i dati
409
- var meaningfulAppSearches = this.est.groupSearchRequestsCache.filter(t => t.group_column == column).map(t => t.view);
410
- // Se non ne trovo significa che ho fatto l'ordinamento o sugli item, o su colonne relative a un sottogruppo non caricato
411
- if (!meaningfulAppSearches || meaningfulAppSearches.length == 0)
412
- meaningfulAppSearches = this.est.groupSearchRequestsCache.filter(t => !t.group_column).map(t => t.view);
413
- // Se non ne trovo qui significa che sto ordinando su colonne relative a un sottogruppo non caricato
414
- if (!meaningfulAppSearches || meaningfulAppSearches.length == 0)
415
- return;
416
- meaningfulAppSearches.forEach(as => {
417
- // Ovviamente gli oridnamenti devono essere quelli appena generati
418
- as.orders = orderings;
419
- as.savedstate = true;
420
- this.est.emitSearchRequest(false, as);
421
- });
422
- }
423
- /**
424
- * Helper che calcola il contenuto di una cella relativa a un gruppo riga, tenendo conto del formato delle eventuali aggregazioni
425
- *
426
- * @param {Group} grp Gruppo di cui mostrare le celle
427
- * @param {string} cell Cella attuale di cui calcolare il testo
428
- * @param {EsThDirective} header Header relativo alla cella attuale, utilizzata per identificare le informazioni di aggregazione
429
- *
430
- * @returns {string} Testo finale calcolato per la **cell** corrente, in base alle aggregazioni di **header**
431
- */
432
- getGroupCellDisplay(grp, cell, header) {
433
- if (grp._sep)
434
- return "";
435
- let display = header.thAggregation;
436
- if (grp.column == cell) {
437
- let groupsPart = grp._groupscount ? " - " + grp._groupscount + " " + this.est.lc.loc("Groups") : "";
438
- return grp.value + " (" + grp.count + groupsPart + ")";
439
- }
440
- else {
441
- let agg = grp._aggregationsCache.get(cell);
442
- if (!agg)
443
- return "";
444
- this.getEsThDirectiveListOfAggregations(header).forEach((itm) => {
445
- display = display.replace(itm.match, this.formatAggregationValue(agg.get(itm.func), itm.format));
446
- });
447
- return display;
448
- }
449
- }
450
- /**
451
- * Funzione che dato un valore lo formatta in base al tipo
452
- *
453
- * @param {string} value Valore che generalemnte può essere una data o un numero
454
- * @param {string} fromat Formato su cui formattare il valore. Può essere ad esempio "small", "long" "verylong" per le date o F{0-9} per i numeri decimali
455
- *
456
- * @returns {string} Valore dell'aggregazione formattato come si deve
457
- */
458
- formatAggregationValue(value, format) {
459
- if (!format)
460
- return value;
461
- let isNumber = !Number.isNaN(value) && (!format || format.startsWith("F"));
462
- if (isNumber && format.startsWith("F") && !Number.isNaN(format.substr(1)))
463
- return parseFloat(value).toFixed(parseInt(format.substr(1)));
464
- let date = null;
465
- // Alcune versione di extensions rischiano di crashare con cose non date... è stato risolto dopo quindi questo try - catch in realtà
466
- // torna utile solo con versioni vecchie/deprecate della libreria @esfaenza/extensions
467
- try {
468
- date = this.dateExts.getDateConvertion(value);
469
- }
470
- catch { }
471
- if (date)
472
- return this.dateExts.getFormatted(date, format == 'small', format == 'verylong');
473
- // Qui ci finisco sia per input che non sono né date né numeri, sia per formati non riconosciuti
474
- return value;
475
- }
476
- }
477
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUm93R3JvdXBpbmdIYW5kbGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvZXMtdGFibGUvc3JjL2xpYi9jb3JlL2hhbmRsZXJzL2NsYXNzZXMvUm93R3JvdXBpbmdIYW5kbGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQVFBLFVBQVU7QUFDVixPQUFPLEVBQTBCLEtBQUssRUFBRSxnQkFBZ0IsRUFBRSxrQkFBa0IsRUFBRSxVQUFVLEVBQUUsa0JBQWtCLEVBQWlCLE1BQU0saUJBQWlCLENBQUM7QUFLckosaUVBQWlFO0FBQ2pFLE1BQU0sT0FBTyxrQkFBa0I7SUFTM0IsMEJBQTBCO0lBQzFCLFlBQW9CLEdBQXFCLEVBQVUsU0FBMkIsRUFBVSxRQUFxQjtRQUF6RixRQUFHLEdBQUgsR0FBRyxDQUFrQjtRQUFVLGNBQVMsR0FBVCxTQUFTLENBQWtCO1FBQVUsYUFBUSxHQUFSLFFBQVEsQ0FBYTtRQVI3RyxxRkFBcUY7UUFDOUUsaUJBQVksR0FBdUIsSUFBSSxHQUFHLEVBQWlCLENBQUM7UUFDbkUsNkdBQTZHO1FBQ3RHLGdCQUFXLEdBQXVCLElBQUksR0FBRyxFQUFpQixDQUFDO1FBQ2xFLDZHQUE2RztRQUN0Ryx1QkFBa0IsR0FBeUIsSUFBSSxHQUFHLEVBQW1CLENBQUM7SUFHb0MsQ0FBQztJQUVsSDs7Ozs7Ozs7O09BU0c7SUFDSSwwQkFBMEIsQ0FBQyxJQUFvQixFQUFFLFlBQW9CO1FBQ3hFLHdJQUF3STtRQUN4SSw4RUFBOEU7UUFDOUUsSUFBSSxDQUFDLElBQUksQ0FBQyxlQUFlLEVBQUUsTUFBTSxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsRUFBRTtZQUMxQyxJQUFJLENBQUMsR0FBRyxDQUFDLFdBQVcsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLGNBQWMsQ0FBQztZQUMvQyxJQUFJLENBQUMsWUFBWSxHQUFHLElBQUksR0FBRyxFQUFpQixDQUFDO1lBQzdDLElBQUksQ0FBQyxXQUFXLEdBQUcsSUFBSSxHQUFHLEVBQWlCLENBQUM7WUFDNUMsSUFBSSxDQUFDLGtCQUFrQixHQUFHLElBQUksR0FBRyxFQUFtQixDQUFDO1lBRXJELElBQUksQ0FBQyxHQUFHLENBQUMsY0FBYyxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsRUFBRTtnQkFDbEMsR0FBRyxDQUFDLFVBQVUsR0FBRyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsTUFBTSxFQUFVLEdBQUksQ0FBQyxNQUFNLEVBQUUsS0FBSyxFQUFVLEdBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7Z0JBQ2hHLEdBQUcsQ0FBQyxRQUFRLEdBQUcsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQVMsR0FBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDO2dCQUN0RCxHQUFHLENBQUMsV0FBVyxHQUFHLENBQUMsQ0FBQztnQkFFcEIsSUFBSSxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLFFBQVEsRUFBRSxHQUFHLENBQUMsQ0FBQztZQUM3QyxDQUFDLENBQUMsQ0FBQztZQUVILHFEQUFxRDtZQUNyRCxJQUFJLFNBQVMsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLGNBQWMsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUMzQyxJQUFJLENBQUMsR0FBRyxDQUFDLGFBQWEsR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDLEVBQUUsRUFBRSxJQUFJLENBQUMsQ0FBQztZQUNqRCxJQUFJLENBQUMsR0FBRyxDQUFDLHdCQUF3QixHQUFHLENBQUMsRUFBRSxJQUFJLEVBQUUsRUFBRSxFQUFFLEtBQUssRUFBRSxDQUFDLEVBQUUsTUFBTSxFQUFVLFNBQVUsQ0FBQyxNQUFNLEVBQUUsS0FBSyxFQUFVLFNBQVUsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsR0FBRyxDQUFDLGFBQWEsRUFBRSxZQUFZLEVBQVUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxjQUFjLENBQUMsQ0FBQyxDQUFFLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQztZQUM1TixJQUFJLENBQUMsR0FBRyxDQUFDLGNBQWMsR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDO1NBQzlDO2FBQ0k7WUFDRCw4R0FBOEc7WUFDOUcsNkdBQTZHO1lBQzdHOzs7Ozs7OztjQVFFO1lBQ0Ysb0lBQW9JO1lBQ3BJLDhJQUE4STtZQUM5STs7Ozs7Ozs7Ozs7O2NBWUU7WUFDRixJQUFJLGlCQUFpQixHQUFHLElBQUksQ0FBQyxlQUFlLENBQUMsTUFBTSxJQUFJLFlBQVksQ0FBQztZQUVwRSxJQUFJLEtBQUssR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLFdBQVcsQ0FBQztZQUNqQyxJQUFJLFdBQVcsR0FBRyxDQUFDLENBQUM7WUFDcEIsSUFBSSxXQUFXLEdBQUcsSUFBSSxDQUFDO1lBQ3ZCLElBQUksUUFBUSxHQUFXLEVBQUUsQ0FBQztZQUMxQixJQUFJLFVBQVUsR0FBeUIsRUFBRSxDQUFDO1lBRTFDLHNLQUFzSztZQUN0SyxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLGVBQWUsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUU7Z0JBQ2xELElBQUksRUFBRSxHQUFHLElBQUksQ0FBQyxlQUFlLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQ2pDLFFBQVEsSUFBSSxFQUFFLENBQUMsS0FBSyxDQUFDO2dCQUNyQixVQUFVLENBQUMsSUFBSSxDQUFDLEVBQUUsTUFBTSxFQUFFLEVBQUUsQ0FBQyxNQUFNLEVBQUUsS0FBSyxFQUFFLEVBQUUsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDO2dCQUN4RCxLQUFLLElBQUksQ0FBQyxHQUFHLFdBQVcsRUFBRSxDQUFDLEdBQUcsS0FBSyxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRTtvQkFDN0MsSUFBSSxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO29CQUNqQixJQUFJLENBQUMsSUFBSSxXQUFXLElBQUksQ0FBQyxDQUFDLE1BQU0sSUFBSSxDQUFDLENBQUMsTUFBTSxJQUFJLEVBQUUsQ0FBQyxNQUFNLElBQUksQ0FBQyxDQUFDLEtBQUssSUFBSSxFQUFFLENBQUMsS0FBSyxFQUFFO3dCQUM5RSxXQUFXLEdBQUcsQ0FBQyxDQUFDO3dCQUFDLFdBQVcsR0FBRyxDQUFDLENBQUM7d0JBQ2pDLHFGQUFxRjt3QkFDckYsV0FBVyxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUM7d0JBQzdCLE1BQU07cUJBQ1Q7aUJBQ0o7YUFDSjtZQUVELElBQUksbUJBQW1CLENBQUM7WUFDeEIsSUFBSSx5QkFBeUIsQ0FBQztZQUU5QixzSUFBc0k7WUFDdEksSUFBSSxDQUFDLGlCQUFpQixFQUFFO2dCQUNwQixJQUFJLENBQUMsV0FBVyxDQUFDLEdBQUcsQ0FBQyxRQUFRLEVBQUUsRUFBRSxDQUFDLENBQUM7Z0JBQ25DLG1CQUFtQixHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxDQUFDO2FBQ3hEO2lCQUNJO2dCQUNELDRHQUE0RztnQkFDNUcsS0FBSyxJQUFJLEdBQUcsSUFBSSxJQUFJLENBQUMsa0JBQWtCLENBQUMsSUFBSSxFQUFFO29CQUMxQyxJQUFJLEdBQUcsQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDO3dCQUN4QixJQUFJLENBQUMsa0JBQWtCLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDO2dCQUU1QyxLQUFLLElBQUksR0FBRyxJQUFJLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxFQUFFO29CQUNuQyxJQUFJLEdBQUcsQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDO3dCQUN4QixJQUFJLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQztnQkFFckMsSUFBSSxDQUFDLGtCQUFrQixDQUFDLEdBQUcsQ0FBQyxRQUFRLEVBQUUsRUFBRSxDQUFDLENBQUM7Z0JBQzFDLHlCQUF5QixHQUFHLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLENBQUM7YUFDckU7WUFFRCxpSUFBaUk7WUFDakksNENBQTRDO1lBQzVDLHNGQUFzRjtZQUN0RixJQUFJLENBQUMsR0FBRyxDQUFDLGNBQWMsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLEVBQUU7Z0JBQ2xDLEdBQUcsQ0FBQyxPQUFPLEdBQUcsUUFBUSxDQUFDO2dCQUN2QixHQUFHLENBQUMsWUFBWSxHQUFHLFVBQVUsQ0FBQztnQkFDOUIsR0FBRyxDQUFDLFVBQVUsR0FBRyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsVUFBVSxFQUFFLElBQUksa0JBQWtCLENBQVMsR0FBSSxDQUFDLE1BQU0sRUFBVSxHQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO2dCQUNwSCxHQUFHLENBQUMsUUFBUSxHQUFHLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLFFBQVEsR0FBVyxHQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUM7Z0JBRXJFLGtFQUFrRTtnQkFDbEUsSUFBSSxpQkFBaUIsRUFBRTtvQkFDbkIsR0FBRyxDQUFDLFdBQVcsR0FBRyxJQUFJLENBQUMsZUFBZSxDQUFDLE1BQU0sQ0FBQztvQkFDOUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLFFBQVEsRUFBRSxHQUFHLENBQUMsQ0FBQztvQkFDekMseUJBQXlCLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO2lCQUN2QztxQkFDSTtvQkFDRCxvREFBb0Q7b0JBQ3BELG1CQUFtQixDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztpQkFDakM7WUFDTCxDQUFDLENBQUMsQ0FBQztZQUVILDZCQUE2QjtZQUM3Qiw4S0FBOEs7WUFDOUssMEVBQTBFO1lBQzFFLGtIQUFrSDtZQUNsSCx5SUFBeUk7WUFDekksSUFBSSxpQkFBaUIsSUFBSSxJQUFJLENBQUMsVUFBVSxFQUFFO2dCQUN0QyxJQUFJLENBQUMsR0FBRyxDQUFDLFdBQVcsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssSUFBSSxDQUFDLENBQUMsVUFBVSxDQUFDLE1BQU0sR0FBRyxVQUFVLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztnQkFDL0csSUFBSSxDQUFDLEdBQUcsQ0FBQyx3QkFBd0IsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLHdCQUF3QixDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLE1BQU0sR0FBRyxVQUFVLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQzthQUM1SDtpQkFDSSxJQUFJLGlCQUFpQixFQUMxQjtnQkFDSSxnSEFBZ0g7Z0JBQ2hILG9GQUFvRjtnQkFDcEYsSUFBSSxDQUFDLEdBQUcsQ0FBQyxXQUFXLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLElBQUksQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUMsUUFBUSxJQUFJLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQzthQUN0STtZQUVELElBQUksQ0FBQyxHQUFHLENBQUMsV0FBVyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxJQUFJLFFBQVEsQ0FBQyxDQUFDLENBQUM7WUFFbEYsSUFBSSxTQUFTLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxXQUFXLENBQUMsV0FBVyxDQUFDLENBQUM7WUFDbEQsSUFBSSxpQkFBaUI7Z0JBQ2pCLFNBQVMsQ0FBQyxZQUFZLEdBQW9CLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSyxFQUFFLFVBQVUsQ0FBQztZQUV6RSw2Q0FBNkM7WUFDN0MsSUFBSSxDQUFDLEdBQUcsQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLFdBQVcsR0FBRyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxjQUFjLENBQUMsQ0FBQztZQUU1RSxvSkFBb0o7WUFDcEosSUFBSSxPQUFPLEdBQUcsS0FBSyxDQUFDO1lBQ3BCLElBQUksQ0FBQyxHQUFHLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxXQUFXLEdBQUcsQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLGNBQWMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxJQUFJLENBQUMsaUJBQWlCLENBQUMsSUFBSSxFQUFFLFFBQVEsRUFBRSxVQUFVLEVBQUUsSUFBSSxDQUFDLGVBQWUsQ0FBQyxNQUFNLEVBQUUsaUJBQWlCLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQztZQUUxTixzREFBc0Q7WUFDdEQsSUFBSSxLQUFLLEdBQUcsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRSxVQUFVLEVBQUUsSUFBSSxFQUFFLE1BQU0sQ0FBQyxNQUFNLENBQUMsRUFBRSxFQUFFLElBQUksQ0FBQyxFQUFFLFlBQVksRUFBRSxpQkFBaUIsQ0FBQyxDQUFDLENBQVMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxjQUFjLENBQUMsQ0FBQyxDQUFFLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQztZQUNwSyxJQUFJLElBQUksR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLHdCQUF3QixDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLElBQUksS0FBSyxDQUFDLElBQUksSUFBSSxDQUFDLENBQUMsWUFBWSxJQUFJLEtBQUssQ0FBQyxZQUFZLENBQUMsQ0FBQztZQUMxSCxJQUFJLElBQUksSUFBSSxDQUFDLENBQUM7Z0JBQ1YsSUFBSSxDQUFDLEdBQUcsQ0FBQyx3QkFBd0IsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7O2dCQUc5QyxJQUFJLENBQUMsR0FBRyxDQUFDLHdCQUF3QixDQUFDLE1BQU0sQ0FBQyxJQUFJLEVBQUUsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDO1NBQ2hFO0lBQ0wsQ0FBQztJQUVEOzs7O09BSUc7SUFDSSx3QkFBd0IsQ0FBQyxHQUFvQjtRQUNoRCxJQUFJLEdBQUcsQ0FBQyxNQUFNLElBQUksQ0FBQztZQUNmLE9BQU87UUFFWCxJQUFJLFlBQVksR0FBWSxFQUFFLENBQUM7UUFDL0IsSUFBSSxrQkFBa0IsR0FBeUIsRUFBRSxDQUFDO1FBRWxELEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxHQUFHLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFO1lBQ2pDLElBQUksRUFBRSxHQUFHLEdBQUcsQ0FBQyxDQUFDLENBQWtCLENBQUM7WUFFakMsSUFBSSxFQUFFLENBQUMsT0FBTztnQkFDVixZQUFZLENBQUMsSUFBSSxDQUFDLElBQUksS0FBSyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUM7aUJBQzFDLElBQUksRUFBRSxDQUFDLGFBQWE7Z0JBQ3JCLGtCQUFrQixHQUFHLENBQUMsR0FBRyxrQkFBa0IsRUFBRSxHQUFHLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO1NBQ3RGO1FBRUQsSUFBSSxZQUFZLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRTtZQUN6QixzQkFBc0I7WUFDdEIsSUFBSSxDQUFDLFlBQVksQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUMxQixJQUFJLENBQUMsV0FBVyxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQ3pCLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUVoQyxJQUFJLENBQUMsR0FBRyxDQUFDLGFBQWEsR0FBRyxJQUFJLENBQUM7WUFDOUIsSUFBSSxDQUFDLEdBQUcsQ0FBQyxXQUFXLEdBQUcsSUFBSSxDQUFDLGtCQUFrQixDQUFDLFlBQVksRUFBRSxDQUFDLEVBQUUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxXQUFXLEVBQUUsa0JBQWtCLEVBQUUsSUFBSSxDQUFDLENBQUM7U0FDbkg7SUFDTCxDQUFDO0lBRUQ7Ozs7OztPQU1HO0lBQ0ksb0JBQW9CLENBQUMsRUFBaUI7UUFDekMsSUFBSSxHQUFHLEdBQUcsRUFBRSxDQUFDO1FBQ2IsNENBQTRDO1FBQzVDLElBQUksRUFBRSxDQUFDLGFBQWEsRUFBRTtZQUNsQixJQUFJLENBQUMsa0NBQWtDLENBQUMsRUFBRSxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsR0FBa0IsRUFBRSxFQUFFO2dCQUN2RSxJQUFJLE1BQU0sR0FBRyxHQUFHLENBQUMsTUFBTSxJQUFJLENBQUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxVQUFVLENBQUMsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDO2dCQUM5RSxJQUFJLFFBQVEsR0FBRyxHQUFHLENBQUMsTUFBTSxJQUFJLEdBQUcsQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLEdBQUcsQ0FBQyxNQUFNLENBQUMsTUFBTSxJQUFJLENBQUMsQ0FBQztnQkFFekgsSUFBSSxDQUFDLE1BQU0sSUFBSSxDQUFDLFFBQVEsSUFBSSxHQUFHLENBQUMsTUFBTTtvQkFDbEMsTUFBTSxrSEFBa0gsQ0FBQztnQkFFN0gsR0FBRyxDQUFDLElBQUksQ0FBQyxJQUFJLGtCQUFrQixDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsR0FBRyxDQUFDLElBQUksRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUM7WUFDeEcsQ0FBQyxDQUFDLENBQUM7U0FDTjthQUNJLElBQUksRUFBRSxDQUFDLE9BQU87WUFDZixHQUFHLENBQUMsSUFBSSxDQUFDLElBQUksa0JBQWtCLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDO1FBRWxELE9BQU8sR0FBRyxDQUFDO0lBQ2YsQ0FBQztJQUdEOzs7Ozs7TUFNRTtJQUNNLGtDQUFrQyxDQUFDLEVBQWlCO1FBQ3hELElBQUksQ0FBQyxFQUFFLENBQUMsYUFBYTtZQUNqQixPQUFPLEVBQUUsQ0FBQztRQUVkLHFGQUFxRjtRQUNyRixJQUFJLEVBQUUsQ0FBQyxlQUFlO1lBQ2xCLE9BQU8sRUFBRSxDQUFDLGVBQWUsQ0FBQztRQUU5QixJQUFJLEdBQUcsR0FBRyxFQUFFLENBQUM7UUFDYixJQUFJLE9BQU8sR0FBRyxFQUFFLENBQUMsYUFBYSxDQUFDO1FBQy9CLElBQUksT0FBTyxHQUFHLE9BQU8sQ0FBQyxLQUFLLENBQUMscUJBQXFCLENBQUMsQ0FBQztRQUNuRCxJQUFJLENBQUMsT0FBTztZQUNSLE9BQU8sRUFBRSxDQUFDO1FBQ2QsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsRUFBRTtZQUNoQixJQUFJLEtBQUssR0FBRyxDQUFDLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQ3pCLElBQUksSUFBSSxHQUFHLENBQUMsRUFBRSxNQUFNLEdBQUcsRUFBRSxDQUFDO1lBQzFCLElBQUksS0FBSyxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUU7Z0JBQ2xCLCtDQUErQztnQkFDL0MsSUFBSSxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQzFCLE1BQU0sR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDO2FBQ3BEO1lBRUQsR0FBRyxDQUFDLElBQUksQ0FBQyxFQUFFLElBQUksRUFBeUIsSUFBSSxFQUFFLE1BQU0sRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDOUUsQ0FBQyxDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMsZUFBZSxHQUFHLEdBQUcsQ0FBQztRQUN6QixPQUFPLEdBQUcsQ0FBQztJQUNmLENBQUM7SUFFRDs7Ozs7Ozs7O09BU0c7SUFDSyxrQkFBa0IsQ0FBQyxJQUFhLEVBQUUsWUFBb0IsRUFBRSxLQUFZLEVBQUUsWUFBa0MsRUFBRSxNQUFZO1FBQzFILG9HQUFvRztRQUNwRyxJQUFJLFlBQVksSUFBSSxDQUFDO1lBQ2pCLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsUUFBUSxHQUFHLEtBQUssQ0FBQyxDQUFDO1FBRTNDLElBQUksR0FBRyxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUM3QixJQUFJLEdBQUcsR0FBVSxFQUFFLENBQUM7UUFDcEIsSUFBSSxJQUFJLEdBQUcsSUFBSSxDQUFDLE1BQU0sSUFBSSxZQUFZLEdBQUcsQ0FBQyxDQUFDO1FBQzNDLElBQUksTUFBTSxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRSxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDdkQsS0FBSyxJQUFJLElBQUksSUFBSSxNQUFNLEVBQUU7WUFDckIsSUFBSSxJQUFJLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQ3hCLElBQUksRUFBRSxHQUFHLElBQUksS0FBSyxDQUFDLEdBQUcsQ0FBQyxNQUFNLEVBQUUsSUFBSSxDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsQ0FBQztZQUNsRCxFQUFFLENBQUMsWUFBWSxHQUFHLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxJQUFJLEVBQUUsWUFBWSxDQUFDLENBQUM7WUFFaEUsSUFBSSxLQUFLLEdBQVMsRUFBRyxDQUFDO1lBQ3RCLEtBQUssQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDO1lBQ3BCLEtBQUssQ0FBQyxTQUFTLEdBQUcsS0FBSyxDQUFDO1lBQ3hCLElBQUksQ0FBQyxNQUFNLEVBQUU7Z0JBQ1QsS0FBSyxDQUFDLFVBQVUsR0FBRyxDQUFDLEVBQUUsTUFBTSxFQUFFLEVBQUUsQ0FBQyxNQUFNLEVBQUUsS0FBSyxFQUFFLEVBQUUsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDO2dCQUM1RCxLQUFLLENBQUMsUUFBUSxHQUFHLEVBQUUsQ0FBQyxLQUFLLENBQUM7Z0JBQzFCLEtBQUssQ0FBQyxXQUFXLEdBQUcsQ0FBQyxDQUFDO2FBQ3pCO2lCQUNJO2dCQUNELEtBQUssQ0FBQyxPQUFPLEdBQUcsTUFBTSxDQUFDLFFBQVEsQ0FBQztnQkFDaEMsS0FBSyxDQUFDLFlBQVksR0FBRyxNQUFNLENBQUMsVUFBVSxDQUFDO2dCQUN2QyxLQUFLLENBQUMsVUFBVSxHQUFHLENBQUMsR0FBRyxNQUFNLENBQUMsVUFBVSxFQUFFLEVBQUUsTUFBTSxFQUFFLEVBQUUsQ0FBQyxNQUFNLEVBQUUsS0FBSyxFQUFFLEVBQUUsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDO2dCQUNsRixLQUFLLENBQUMsUUFBUSxHQUFHLE1BQU0sQ0FBQyxRQUFRLEdBQUcsRUFBRSxDQUFDLEtBQUssQ0FBQztnQkFDNUMsS0FBSyxDQUFDLFdBQVcsR0FBRyxNQUFNLENBQUMsV0FBVyxHQUFHLENBQUMsQ0FBQzthQUM5QztZQUVELDRGQUE0RjtZQUM1RixvSEFBb0g7WUFDcEgsSUFBSSxZQUFZLElBQUksQ0FBQztnQkFDakIsS0FBSyxDQUFDLFFBQVEsR0FBRyxJQUFJLENBQUM7WUFFMUIsSUFBSSxDQUFDLFNBQVMsQ0FBQyxhQUFhLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO1lBQ3RDLElBQUksQ0FBQyxTQUFTLENBQUMsaUJBQWlCLENBQUMsS0FBSyxDQUFDLENBQUM7WUFFeEMsMkJBQTJCO1lBQzNCLEdBQUcsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDaEIsSUFBSSxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLFFBQVEsRUFBRSxLQUFLLENBQUMsQ0FBQztZQUM3QyxJQUFJLENBQUMsSUFBSSxFQUFFO2dCQUVQLHVHQUF1RztnQkFDdkcsSUFBSSxpQkFBaUIsR0FBRyxJQUFJLENBQUMsa0JBQWtCLENBQUMsSUFBSSxFQUFFLFlBQVksR0FBRyxDQUFDLEVBQUUsSUFBSSxFQUFFLFlBQVksRUFBRSxLQUFLLENBQUMsQ0FBQztnQkFDbkcsSUFBSSxXQUFXLEdBQUcsaUJBQWlCLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLE1BQU0sSUFBSSxDQUFDLENBQUMsT0FBTyxJQUFJLEtBQUssQ0FBQyxRQUFRLENBQUMsQ0FBQztnQkFDekYsS0FBSyxDQUFDLFlBQVksR0FBRyxXQUFXLENBQUMsTUFBTSxDQUFDO2dCQUV4QyxrRkFBa0Y7Z0JBQ2xGLEdBQUcsQ0FBQyxJQUFJLENBQUMsR0FBRyxpQkFBaUIsQ0FBQyxDQUFDO2dCQUMvQixJQUFJLENBQUMsa0JBQWtCLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxRQUFRLEVBQUUsV0FBVyxDQUFDLENBQUM7YUFDNUQ7aUJBQ0k7Z0JBQ0Qsa0dBQWtHO2dCQUNsRyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLFFBQVEsR0FBRyxLQUFLLENBQUMsUUFBUSxDQUFDLENBQUM7Z0JBRS9DLEdBQUcsQ0FBQyxJQUFJLENBQUMsR0FBRyxJQUFJLENBQUMsQ0FBQztnQkFDbEIsSUFBSSxDQUFDLFdBQVcsQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLFFBQVEsRUFBRSxJQUFJLENBQUMsQ0FBQzthQUM5QztTQUNKO1FBQ0QsT0FBTyxHQUFHLENBQUM7SUFDZixDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSyxvQkFBb0IsQ0FBQyxLQUFZLEVBQUUsWUFBa0M7UUFDekUsSUFBSSxJQUFJLEdBQXVCLEVBQUUsQ0FBQztRQUNsQyxJQUFJLGdCQUFnQixHQUFHLEVBQUUsRUFBRSxPQUFPLEdBQUcsSUFBSSxFQUFFLFNBQVMsR0FBRyxJQUFJLEVBQUUsT0FBTyxHQUFHLElBQUksRUFBRSxTQUFTLEdBQUcsSUFBSSxDQUFDO1FBRTlGLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxZQUFZLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFO1lBQzFDLElBQUksR0FBRyxHQUFHLFlBQVksQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUMxQixPQUFPLEdBQUcsR0FBRyxDQUFDLE1BQU0sQ0FBQztZQUNyQixJQUFJLENBQUMsT0FBTztnQkFDUixTQUFTO1lBRWIsUUFBUSxHQUFHLENBQUMsUUFBUSxFQUFFO2dCQUNsQixLQUFLLFFBQVE7b0JBQUUsU0FBUyxHQUFHLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQztvQkFBQyxNQUFNO2dCQUN4RSxLQUFLLE1BQU07b0JBQUUsT0FBTyxHQUFHLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxJQUFJLElBQUksQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDO29CQUFDLE1BQU07Z0JBQzdFLEtBQUssUUFBUTtvQkFBRSxTQUFTLEdBQUcsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDO29CQUFDLE1BQU07YUFDNUU7WUFFRCxRQUFRLEdBQUcsQ0FBQyxXQUFXLEVBQUU7Z0JBQ3JCLEtBQUssS0FBSztvQkFDTixRQUFRLEdBQUcsQ0FBQyxRQUFRLEVBQUU7d0JBQ2xCLEtBQUssUUFBUTs0QkFBRSxnQkFBZ0IsR0FBRyxTQUFTLENBQUMsSUFBSSxFQUFFLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7NEJBQUMsTUFBTTt3QkFDdkUsS0FBSyxNQUFNOzRCQUFFLGdCQUFnQixHQUFHLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxPQUFPLENBQUMsQ0FBQyxDQUFDLFFBQVEsRUFBRSxDQUFDOzRCQUFDLE1BQU07d0JBQ2pGLEtBQUssUUFBUTs0QkFBRSxnQkFBZ0IsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsU0FBUyxDQUFDLENBQUMsUUFBUSxFQUFFLENBQUM7NEJBQUMsTUFBTTtxQkFDOUU7b0JBQ0QsTUFBTTtnQkFDVixLQUFLLEtBQUs7b0JBQ04sUUFBUSxHQUFHLENBQUMsUUFBUSxFQUFFO3dCQUNsQixLQUFLLFFBQVE7NEJBQUUsZ0JBQWdCLEdBQUcsU0FBUyxDQUFDLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDOzRCQUFDLE1BQU07d0JBQzdELEtBQUssTUFBTTs0QkFBRSxnQkFBZ0IsR0FBRyxJQUFJLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsT0FBTyxDQUFDLENBQUMsQ0FBQyxRQUFRLEVBQUUsQ0FBQzs0QkFBQyxNQUFNO3dCQUNqRixLQUFLLFFBQVE7NEJBQUUsZ0JBQWdCLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLFNBQVMsQ0FBQyxDQUFDLFFBQVEsRUFBRSxDQUFDOzRCQUFDLE1BQU07cUJBQzlFO29CQUNELE1BQU07Z0JBQ1YsS0FBSyxLQUFLO29CQUNOLFFBQVEsR0FBRyxDQUFDLFFBQVEsRUFBRTt3QkFDbEIsS0FBSyxRQUFROzRCQUFFLGdCQUFnQixHQUFHLFNBQVMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7NEJBQUMsTUFBTTt3QkFDOUQsS0FBSyxNQUFNOzRCQUFFLGdCQUFnQixHQUFHLEVBQUUsQ0FBQzs0QkFBQyxNQUFNO3dCQUMxQyxLQUFLLFFBQVE7NEJBQUUsZ0JBQWdCLEdBQUcsU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFDLEdBQUcsRUFBRSxJQUFJLEVBQUUsRUFBRSxDQUFDLEdBQUcsR0FBRyxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUMsUUFBUSxFQUFFLENBQUM7NEJBQUMsTUFBTTtxQkFDdEc7b0JBQ0QsTUFBTTthQUNiO1lBQ0QsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLGdCQUFnQixDQUFDLEdBQUcsQ0FBQyxNQUFNLEVBQUUsR0FBRyxDQUFDLFdBQVcsRUFBRSxnQkFBZ0IsQ0FBQyxDQUFDLENBQUM7U0FDbEY7UUFFRCxPQUFPLElBQUksQ0FBQztJQUNoQixDQUFDO0lBRUQ7Ozs7Ozs7Ozs7TUFVRTtJQUNLLGlCQUFpQixDQUFDLElBQW9CLEVBQUUsTUFBYyxFQUFFLEtBQTJCLEVBQUUsS0FBYSxFQUFFLFFBQTRCO1FBQ25JLElBQUksSUFBSSxHQUFHLElBQUksVUFBVSxDQUFDLEtBQUssRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLE1BQU0sQ0FBQyxNQUFNLENBQUMsRUFBRSxFQUFFLElBQUksQ0FBQyxFQUFFLFFBQVEsQ0FBQyxDQUFDO1FBQ25GLElBQUksQ0FBQyxPQUFPLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxhQUFhLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ3RFLElBQUksQ0FBQyxTQUFTLENBQUMsYUFBYSxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztRQUNyQyxPQUFPLElBQUksQ0FBQztJQUNoQixDQUFDO0lBR0Q7Ozs7Ozs7Ozs7T0FVRztJQUNJLHVCQUF1QixDQUFDLE1BQWMsRUFBRSxTQUF3QjtRQUNuRSxtR0FBbUc7UUFDbkcsSUFBSSxxQkFBcUIsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLHdCQUF3QixDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxZQUFZLElBQUksTUFBTSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBRXJILHlIQUF5SDtRQUN6SCxJQUFJLENBQUMscUJBQXFCLElBQUkscUJBQXFCLENBQUMsTUFBTSxJQUFJLENBQUM7WUFDM0QscUJBQXFCLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyx3QkFBd0IsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxZQUFZLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUM7UUFFNUcsb0dBQW9HO1FBQ3BHLElBQUksQ0FBQyxxQkFBcUIsSUFBSSxxQkFBcUIsQ0FBQyxNQUFNLElBQUksQ0FBQztZQUMzRCxPQUFPO1FBRVgscUJBQXFCLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxFQUFFO1lBQy9CLGtFQUFrRTtZQUNsRSxFQUFFLENBQUMsTUFBTSxHQUFHLFNBQVMsQ0FBQztZQUN0QixFQUFFLENBQUMsVUFBVSxHQUFHLElBQUksQ0FBQztZQUNyQixJQUFJLENBQUMsR0FBRyxDQUFDLGlCQUFpQixDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQztRQUMxQyxDQUFDLENBQUMsQ0FBQztJQUNQLENBQUM7SUFFRDs7Ozs7Ozs7T0FRRztJQUNJLG1CQUFtQixDQUFDLEdBQVUsRUFBRSxJQUFZLEVBQUUsTUFBcUI7UUFDdEUsSUFBVSxHQUFJLENBQUMsSUFBSTtZQUNmLE9BQU8sRUFBRSxDQUFDO1FBQ2QsSUFBSSxPQUFPLEdBQUcsTUFBTSxDQUFDLGFBQWEsQ0FBQztRQUNuQyxJQUFJLEdBQUcsQ0FBQyxNQUFNLElBQUksSUFBSSxFQUFFO1lBQ3BCLElBQUksVUFBVSxHQUFTLEdBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLEtBQUssR0FBUyxHQUFJLENBQUMsWUFBWSxHQUFHLEdBQUcsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztZQUNsSCxPQUFPLEdBQUcsQ0FBQyxLQUFLLEdBQUcsSUFBSSxHQUFHLEdBQUcsQ0FBQyxLQUFLLEdBQUcsVUFBVSxHQUFHLEdBQUcsQ0FBQztTQUMxRDthQUNJO1lBRUQsSUFBSSxHQUFHLEdBQTRDLEdBQUksQ0FBQyxrQkFBbUIsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDdEYsSUFBSSxDQUFDLEdBQUc7Z0JBQ0osT0FBTyxFQUFFLENBQUM7WUFFZCxJQUFJLENBQUMsa0NBQWtDLENBQUMsTUFBTSxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsR0FBa0IsRUFBRSxFQUFFO2dCQUMzRSxPQUFPLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRSxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztZQUNyRyxDQUFDLENBQUMsQ0FBQztZQUVILE9BQU8sT0FBTyxDQUFDO1NBQ2xCO0lBQ0wsQ0FBQztJQUVEOzs7Ozs7O09BT0c7SUFDSyxzQkFBc0IsQ0FBQyxLQUFhLEVBQUUsTUFBZTtRQUN6RCxJQUFJLENBQUMsTUFBTTtZQUNQLE9BQU8sS0FBSyxDQUFDO1FBRWpCLElBQUksUUFBUSxHQUFHLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsTUFBTSxJQUFJLE1BQU0sQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztRQUUzRSxJQUFJLFFBQVEsSUFBSSxNQUFNLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ3JFLE9BQU8sVUFBVSxDQUFDLEtBQUssQ0FBQyxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFFakUsSUFBSSxJQUFJLEdBQUcsSUFBSSxDQUFDO1FBQ2hCLG9JQUFvSTtRQUNwSSxzRkFBc0Y7UUFDdEYsSUFBSTtZQUFFLElBQUksR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLGlCQUFpQixDQUFDLEtBQUssQ0FBQyxDQUFDO1NBQUU7UUFBQyxNQUFNLEdBQUc7UUFFaEUsSUFBSSxJQUFJO1lBQ0osT0FBTyxJQUFJLENBQUMsUUFBUSxDQUFDLFlBQVksQ0FBQyxJQUFJLEVBQUUsTUFBTSxJQUFJLE9BQU8sRUFBRSxNQUFNLElBQUksVUFBVSxDQUFDLENBQUM7UUFFckYsZ0dBQWdHO1FBQ2hHLE9BQU8sS0FBSyxDQUFDO0lBQ2pCLENBQUM7Q0FDSiIsInNvdXJjZXNDb250ZW50IjpbIi8vIExpYnJlcmllXHJcbmltcG9ydCB7IERhdGVTZXJ2aWNlIH0gZnJvbSBcIkBlc2ZhZW56YS9leHRlbnNpb25zXCI7XHJcblxyXG4vLyBEaXJldHRpdmUgLyBDb21wb25lbnRpXHJcbmltcG9ydCB7IEVzVGggfSBmcm9tIFwiLi4vLi4vLi4vY29tcG9uZW50cy9lcy10aC9lc190aC5jb21wb25lbnRcIjtcclxuaW1wb3J0IHsgRXNUaERpcmVjdGl2ZSB9IGZyb20gXCIuLi8uLi8uLi9kaXJlY3RpdmVzL2VzX3RoLmRpcmVjdGl2ZVwiO1xyXG5pbXBvcnQgeyBFc1RhYmxlQ29tcG9uZW50IH0gZnJvbSBcIi4uLy4uLy4uL2NvbXBvbmVudHMvZXMtdGFibGUvZXNfdGFibGUuY29tcG9uZW50XCJcclxuXHJcbi8vIE1vZGVsbGlcclxuaW1wb3J0IHsgQXBwT3JkZXJpbmcsIEFwcFNlYXJjaCwgR3JvdXAsIEdyb3VwQWdncmVnYXRpb24sIEdyb3VwT3JBZ2dyZWdhdGlvbiwgR3JvdXBQYWdlciwgR3JvdXBSb3V0ZUZyYWdtZW50LCBUaEFnZ3JlZ2F0aW9uIH0gZnJvbSBcIi4uLy4uLy4uL2RvbWFpblwiO1xyXG5cclxuLy8gVXRpbGl0aWVzXHJcbmltcG9ydCB7IFV0aWxpdGllc0hhbmRsZXIgfSBmcm9tIFwiLi9VdGlsaXRpZXNIYW5kbGVyXCI7XHJcblxyXG4vKiogQ2xhc3NlIGNoZSBnZXN0aXNjZSBsYSBtb2RhbGl0w6AgUm93IEdyb3VwaW5nIGRlbGwnZXMtdGFibGUgKi9cclxuZXhwb3J0IGNsYXNzIFJvd0dyb3VwaW5nSGFuZGxlciB7XHJcblxyXG4gICAgLyoqIENhY2hlIHBlciBzYWx2YXJlIHBlciBvZ25pIGNoaWF2ZSBkaSBvZ25pIGdydXBwbyBjaGkgw6ggaWwgZ3J1cHBvIHJhcHByZXNlbnRhdG8gKi9cclxuICAgIHB1YmxpYyByZ0dyb3VwQ2FjaGU6IE1hcDxzdHJpbmcsIEdyb3VwPiA9IG5ldyBNYXA8c3RyaW5nLCBHcm91cD4oKTtcclxuICAgIC8qKiBDYWNoZSBwZXIgc2FsdmFyZSBwZXIgb2duaSBjaGlhdmUgZGkgb2duaSBncnVwcG8gY2hpIHNvbm8gZ2xpIG9nZ2V0dGkgc290dG9zdGFudGksIG5vbiBkZWkgc290dG9ncnVwcGkgKi9cclxuICAgIHB1YmxpYyByZ0l0ZW1DYWNoZTogTWFwPHN0cmluZywgYW55W10+ID0gbmV3IE1hcDxzdHJpbmcsIGFueVtdPigpO1xyXG4gICAgLyoqIENhY2hlIHBlciBzYWx2YXJlIHBlciBvZ25pIGNoaWF2ZSBkaSBvZ25pIGdydXBwbyBjaGkgc29ubyBnbGkgb2dnZXR0aSBzb3R0b3N0YW50aSwgbm9uIGRlaSBzb3R0b2dydXBwaSAqL1xyXG4gICAgcHVibGljIHJnQ2hpbGRHcm91cHNDYWNoZTogTWFwPHN0cmluZywgR3JvdXBbXT4gPSBuZXcgTWFwPHN0cmluZywgR3JvdXBbXT4oKTtcclxuXHJcbiAgICAvKiogQGlnbm9yZSBDb3N0cnV0dG9yZSAqL1xyXG4gICAgY29uc3RydWN0b3IocHJpdmF0ZSBlc3Q6IEVzVGFibGVDb21wb25lbnQsIHByaXZhdGUgdXRpbGl0aWVzOiBVdGlsaXRpZXNIYW5kbGVyLCBwcml2YXRlIGRhdGVFeHRzOiBEYXRlU2VydmljZSkgeyB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBJbiBtb2RhbGl0w6Agcm93Z3JvdXBpbmcgcXVhbmRvIG1pIGFycml2YSB1biBudW92byBibG9jY28gZGkgb2dnZXR0aSBkZXZvIGFnZ2l1bmdlcmxvIGFsbGEgdmlzdGEgYXR0dWFsZTpcclxuICAgICAqXHJcbiAgICAgKiAxKSBTZSBub24gdmllbmUgcmljaGllc3RvIGlsIGRldHRhZ2xpbyBkaSBhbGN1biBncnVwcG8gc2lnbmlmaWNhIGNoZSBkZXZvIGNvbnNpZGVyYXJlIG1pIHNpYW5vIGFycml2YXRpIHR1dHRpIGkgZ3J1cHBpIHByaW5jaXBhbGlcclxuICAgICAqIDIpIFNlIHZpZW5lIHJpY2hpZXN0byBpbCBkZXR0YWdsaW8gZGkgdW4gZ3J1cHBvIGRpdmVyc28gZGFsbCd1bHRpbW8gZGV2byBhZ2dpdW5nZXJlIGRvcG8gYWwgZ3J1cHBvIGNsaWNjYXRvIGxhIGxpc3RhIGRlaSBzb3R0b2dydXBwaVxyXG4gICAgICogMikgU2UgdmllbmUgcmljaGllc3RvIGlsIGRldHRhZ2xpbyBkZWxsJ3VsdGltbyBncnVwcG8gZGV2byBhZ2dpdW5nZXJlIGRvcG8gYWwgZ3J1cHBvIGNsaWNjYXRvIGxhIGxpc3RhIGRlZ2xpIG9nZ2V0dGlcclxuICAgICAqXHJcbiAgICAgKiBAcGFyYW0ge2FueX0gdmlldyBBcHBTZWFyY2g8VD4gZGEgY3VpIHNvbm8gYXJyaXZhdGkgZ2xpIG9nZ2V0dGlcclxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBncm91cGluZ0tleXMgTGl2ZWxsaSBkaSByYWdncnVwcGFtZW50byBkYSBhc3BldHRhcnNpIHN1aSBkYXRpXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBoYW5kbGVOZXdEYXRhT25Sb3dHcm91cGluZyh2aWV3OiBBcHBTZWFyY2g8YW55PiwgZ3JvdXBpbmdLZXlzOiBudW1iZXIpIHtcclxuICAgICAgICAvLyAxKSBTZSBub24gdmllbmUgcmljaGllc3RvIGlsIGRldHRhZ2xpbyBkaSBhbGN1biBncnVwcG8gc2lnbmlmaWNhIGNoZSBsYSBjaGlhbWF0YSByZXN0aXR1aXNjZSBsYSBsaXN0YSBwYWdpbmF0YSBkZWkgZ3J1cHBpIHByaW5jaXBhbGkuXHJcbiAgICAgICAgLy8gICAgTGkgdHJhdHRvIGNvbWUgc2UgZm9zc2UgdW5hIHF1YWxzaWFzaSBhbHRyYSBxdWVyeSBwYWdpbmF0YSBzdSBOIGVsZW1lbnRpXHJcbiAgICAgICAgaWYgKCh2aWV3LnJlcXVlc3RlZGdyb3Vwcz8ubGVuZ3RoIHx8IDApID09IDApIHtcclxuICAgICAgICAgICAgdGhpcy5lc3QuYm91bmRTb3VyY2UgPSB0aGlzLmVzdC5UTVBCb3VuZFNvdXJjZTtcclxuICAgICAgICAgICAgdGhpcy5yZ0dyb3VwQ2FjaGUgPSBuZXcgTWFwPHN0cmluZywgR3JvdXA+KCk7XHJcbiAgICAgICAgICAgIHRoaXMucmdJdGVtQ2FjaGUgPSBuZXcgTWFwPHN0cmluZywgYW55W10+KCk7XHJcbiAgICAgICAgICAgIHRoaXMucmdDaGlsZEdyb3Vwc0NhY2hlID0gbmV3IE1hcDxzdHJpbmcsIEdyb3VwW10+KCk7XHJcblxyXG4gICAgICAgICAgICB0aGlzLmVzdC5UTVBCb3VuZFNvdXJjZS5mb3JFYWNoKGl0bSA9PiB7XHJcbiAgICAgICAgICAgICAgICBpdG0uX3RoaXNSb3V0ZSA9IGl0bS5fZ3JvdXAgPyBbeyBjb2x1bW46ICg8R3JvdXA+aXRtKS5jb2x1bW4sIHZhbHVlOiAoPEdyb3VwPml0bSkudmFsdWUgfV0gOiBbXTtcclxuICAgICAgICAgICAgICAgIGl0bS5fdGhpc0tleSA9IGl0bS5fZ3JvdXAgPyAoPEdyb3VwPml0bSkudmFsdWUgOiBudWxsO1xyXG4gICAgICAgICAgICAgICAgaXRtLl9ncm91cGxldmVsID0gMDtcclxuXHJcbiAgICAgICAgICAgICAgICB0aGlzLnJnR3JvdXBDYWNoZS5zZXQoaXRtLl90aGlzS2V5LCBpdG0pO1xyXG4gICAgICAgICAgICB9KTtcclxuXHJcbiAgICAgICAgICAgIC8vIFJlc2V0dG8gbGEgcmljZXJjYSBhbGxhIGNhY2hlIGRpIHF1ZXN0YSBcInNlc3Npb25lXCJcclxuICAgICAgICAgICAgbGV0IGZpcnN0SXRlbSA9IHRoaXMuZXN0LlRNUEJvdW5kU291cmNlWzBdO1xyXG4gICAgICAgICAgICB0aGlzLmVzdC5NYWluR3JvdXBWaWV3ID0gT2JqZWN0LmFzc2lnbih7fSwgdmlldyk7XHJcbiAgICAgICAgICAgIHRoaXMuZXN0Lmdyb3VwU2VhcmNoUmVxdWVzdHNDYWNoZSA9IFt7IHBhdGg6ICcnLCByb3V0ZTogW3sgY29sdW1uOiAoPEdyb3VwPmZpcnN0SXRlbSkuY29sdW1uLCB2YWx1ZTogKDxHcm91cD5maXJzdEl0ZW0pLnZhbHVlIH1dLCB2aWV3OiB0aGlzLmVzdC5NYWluR3JvdXBWaWV3LCBncm91cF9jb2x1bW46ICg8R3JvdXA+dGhpcy5lc3QuVE1QQm91bmRTb3VyY2VbMF0pLmNvbHVtbiB9XTtcclxuICAgICAgICAgICAgdGhpcy5lc3QuQmFzZUl0ZW1zQ291bnQgPSB2aWV3Lm9iamVjdGNvdW50O1xyXG4gICAgICAgIH1cclxuICAgICAgICBlbHNlIHtcclxuICAgICAgICAgICAgLy8gMikgU2UgdmllbmUgcmljaGllc3RvIGlsIGRldHRhZ2xpbyBkaSB1biBxdWFsc2lhc2kgZ3J1cHBvIGRpdmVyc28gZGFsbCd1bHRpbW8gdnVvbCBkaXJlIGNoZSBkZXZvIGFnZ2l1bmdlcmVcclxuICAgICAgICAgICAgLy8gICAgZG9wbyBhbCBncnVwcG8gY2hlIGhvIGNsaWNjYXRvIGxhIGxpc3RhIGRlaSBncnVwcGkgdGlyYXRhIGZ1b3JpIHF1ZXN0YSB2b2x0YSAoaW50ZXJtZWRpYXRlR3JvdXAgPSB0cnVlKVxyXG4gICAgICAgICAgICAvKlxyXG4gICAgICAgICAgICAqICAgR3J1cHBvQSAgICAgICAgICAgICAgICAgICAgICBHcnVwcG9BXHJcbiAgICAgICAgICAgICogICBHcnVwcG9CICAgICAgICAgICAgICAgICAgICAgIEdydXBwb0JcclxuICAgICAgICAgICAgKiAgIEdydXBwb0MgPC0gQ2xpY2NvIHF1aSAgICAgICAgR3J1cHBvQ1xyXG4gICAgICAgICAgICAqICAgR3J1cHBvRCAgICAgICAgICAgICAgICAgICAgICAgICAgR3J1cHBvQzFcclxuICAgICAgICAgICAgKiAgIEdydXBwb0UgICAgICAgICAgICAgICAgICAgICAgICAgIEdydXBwb0MyXHJcbiAgICAgICAgICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEdydXBwb0RcclxuICAgICAgICAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgR3J1cHBvRVxyXG4gICAgICAgICAgICAqL1xyXG4gICAgICAgICAgICAvLyAzKSBzZSBpIGdydXBwaSByaWNoaWVzdGkgZGFsbGEgdmlldyBzb25vIHVndWFsaSBhaSBncnVwcGkgcHJlc2VudGkgdnVvbCBkaXJlIGNoZSBzdG8gcHJlbmRlbmRvIGdsaSBvZ2dldHRpIHZlcmkgZSBwcm9wcmksIHNvbm8gaW5cclxuICAgICAgICAgICAgLy8gdmlldy5pdGVtcyBlIHF1aW5kaSBpbiBUTVBCb3VuZFNvdXJjZSwgaG8gaW5vbHRyZSBsZSBpbmZvcm1hemlvbmkgZGkgcGFnaW5hemlvbmUgKipwZXIgaWwgc2luZ29sbyBzb3R0b2dydXBwbyoqIChpbnRlcm1lZGlhdGVHcm91cCA9IGZhbHNlKVxyXG4gICAgICAgICAgICAvKlxyXG4gICAgICAgICAgICAqICAgR3J1cHBvQSAgICAgICAgICAgICAgICAgICAgICAgICBHcnVwcG9BXHJcbiAgICAgICAgICAgICogICAgICAgR3J1cHBvQzEgICAgICAgICAgICAgICAgICAgICAgICBHcnVwcG9DMVxyXG4gICAgICAgICAgICAqICAgR3J1cHBvQiAgICAgICAgICAgICAgICAgICAgICAgICBHcnVwcG9CXHJcbiAgICAgICAgICAgICogICBHcnVwcG9DICAgICAgICAgICAgICAgICAgICAgICAgIEdydXBwb0NcclxuICAgICAgICAgICAgKiAgICAgICBHcnVwcG9DMSA8LS0gQ2xpY2NvIHF1aSAgICAgICAgIEdydXBwb0MxXHJcbiAgICAgICAgICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgT2dnZXR0bzFcclxuICAgICAgICAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBPZ2dldHRvMlxyXG4gICAgICAgICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE9nZ2V0dG8zXHJcbiAgICAgICAgICAgICogICAgICAgR3J1cHBvQzIgICAgICAgICAgICAgICAgICAgICAgICBHcnVwcG9DMlxyXG4gICAgICAgICAgICAqICAgR3J1cHBvRCAgICAgICAgICAgICAgICAgICAgICAgICBHcnVwcG9EXHJcbiAgICAgICAgICAgICogICBHcnVwcG9FICAgICAgICAgICAgICAgICAgICAgICAgIEdydXBwb0VcclxuICAgICAgICAgICAgKi9cclxuICAgICAgICAgICAgbGV0IGludGVybWVkaWF0ZUdyb3VwID0gdmlldy5yZXF1ZXN0ZWRncm91cHMubGVuZ3RoICE9IGdyb3VwaW5nS2V5cztcclxuXHJcbiAgICAgICAgICAgIGxldCBpdGVtcyA9IHRoaXMuZXN0LmJvdW5kU291cmNlO1xyXG4gICAgICAgICAgICBsZXQgaW5zZXJ0SW5kZXggPSAwO1xyXG4gICAgICAgICAgICBsZXQgaW5zZXJ0R3JvdXAgPSBudWxsO1xyXG4gICAgICAgICAgICBsZXQgZ3JvdXBLZXk6IHN0cmluZyA9IFwiXCI7XHJcbiAgICAgICAgICAgIGxldCBncm91cFJvdXRlOiBHcm91cFJvdXRlRnJhZ21lbnRbXSA9IFtdO1xyXG5cclxuICAgICAgICAgICAgLy8gTmF2aWdvIGxhIHN0dXR0dXJhIGRlaSBncnVwcGkgaWdub3JhbmRvIHJpY29yc2l2YW1lbnRlIHR1dHRpIGdsaSBpbmRpY2kgZmlubyBhaSBncnVwcGkgY2hlIG1pIGludGVyZXNzYW5vIGluIG1vZG8gZGEgbm9uIGJlY2NhcmUgaWwgcHJpbW8gXCJHcnVwcG9DMVwiIGRlbCBjYXNvIHNvcHJhXHJcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdmlldy5yZXF1ZXN0ZWRncm91cHMubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICAgICAgICAgIGxldCByZyA9IHZpZXcucmVxdWVzdGVkZ3JvdXBzW2ldO1xyXG4gICAgICAgICAgICAgICAgZ3JvdXBLZXkgKz0gcmcudmFsdWU7XHJcbiAgICAgICAgICAgICAgICBncm91cFJvdXRlLnB1c2goeyBjb2x1bW46IHJnLmNvbHVtbiwgdmFsdWU6IHJnLnZhbHVlIH0pO1xyXG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IGluc2VydEluZGV4OyBpIDwgaXRlbXMubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICAgICAgICAgICAgICBsZXQgdCA9IGl0ZW1zW2ldO1xyXG4gICAgICAgICAgICAgICAgICAgIGlmIChpID49IGluc2VydEluZGV4ICYmIHQuX2dyb3VwICYmIHQuY29sdW1uID09IHJnLmNvbHVtbiAmJiB0LnZhbHVlID09IHJnLnZhbHVlKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGluc2VydEluZGV4ID0gaTsgaW5zZXJ0R3JvdXAgPSB0O1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBMbyBtYXJjbyBleHBhbmRlZCBkYXRvIGNoZSBxdWVzdG8gY2xpY2sgc3VsIGdydXBwbyBwb3RyZWJiZSBub24gZXNzZXJlIHN0YXRvIGZhdHRvXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGluc2VydEdyb3VwLl9leHBhbmRlZCA9IHRydWU7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgbGV0IGl0ZW1zQ2FjaGVSZWZlcmVuY2U7XHJcbiAgICAgICAgICAgIGxldCBjaGlsZEdyb3Vwc0NhY2hlUmVmZXJlbmNlO1xyXG5cclxuICAgICAgICAgICAgLy8gU2Ugbm9uIMOoIHVuIGdydXBwbyBpbnRlcm1lZGlvIGRldm8gcmlwdWxpcmUgbGEgY2FjaGUgZGVsIGdydXBwbyBzdSBjdWkgaG8gYXR0dWFsbWVudGUgY2xpY2NhdG8uIEdsaSBvZ2dldHRpIHNhcmFubm8gcmlhZ2dpdW50aSBkb3BvXHJcbiAgICAgICAgICAgIGlmICghaW50ZXJtZWRpYXRlR3JvdXApIHtcclxuICAgICAgICAgICAgICAgIHRoaXMucmdJdGVtQ2FjaGUuc2V0KGdyb3VwS2V5LCBbXSk7XHJcbiAgICAgICAgICAgICAgICBpdGVtc0NhY2hlUmVmZXJlbmNlID0gdGhpcy5yZ0l0ZW1DYWNoZS5nZXQoZ3JvdXBLZXkpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgLy8gU2UgaW52ZWNlIMOoIHVuIGdydXBwbyBpbnRlcm1lZGlvIGRldm8gcmlwdWxpcmUgc2lhIHR1dHRpIGkgY2hpbGQgZ3JvdXAgcmljb3JzaXZhbWVudGUsIHNpYSB0dXR0aSBnbGkgaXRlbVxyXG4gICAgICAgICAgICAgICAgZm9yIChsZXQga2V5IG9mIHRoaXMucmdDaGlsZEdyb3Vwc0NhY2hlLmtleXMoKSlcclxuICAgICAgICAgICAgICAgICAgICBpZiAoa2V5LnN0YXJ0c1dpdGgoZ3JvdXBLZXkpKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJnQ2hpbGRHcm91cHNDYWNoZS5kZWxldGUoa2V5KTtcclxuXHJcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBrZXkgb2YgdGhpcy5yZ0l0ZW1DYWNoZS5rZXlzKCkpXHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKGtleS5zdGFydHNXaXRoKGdyb3VwS2V5KSlcclxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5yZ0l0ZW1DYWNoZS5kZWxldGUoa2V5KTtcclxuXHJcbiAgICAgICAgICAgICAgICB0aGlzLnJnQ2hpbGRHcm91cHNDYWNoZS5zZXQoZ3JvdXBLZXksIFtdKTtcclxuICAgICAgICAgICAgICAgIGNoaWxkR3JvdXBzQ2FjaGVSZWZlcmVuY2UgPSB0aGlzLnJnQ2hpbGRHcm91cHNDYWNoZS5nZXQoZ3JvdXBLZXkpO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAvLyBBc3NlZ25vIHVuIGxpdmVsbG8gYWkgdmFsb3JpIGNoZSBhcnJpdmFubyBkYSB1c2FyZSBwZXIgZm9ybWF0dGFyZSBsYSBwYXJ0ZSBncmFmaWNhLiBJbCBwcmltbyBncnVwcG8gY2xpY2NhdG8gc2Fyw6AgYSBsaXZlbGxvIDEsXHJcbiAgICAgICAgICAgIC8vIGlsIHNlY29uZG8gc2Fyw6AgYSBsaXZlbGxvIDIgZSBjb3PDrCB2aWEuLi5cclxuICAgICAgICAgICAgLy8gTGkgbWFyY28gaW5vbHRyZSBjb24gaWwgcGFyZW50IGluIG1vZG8gZGEgcG90ZXIgZWxpbWluYXJlIGkgdmVjY2hpIHF1YWxvcmEgc2Vydmlzc2VcclxuICAgICAgICAgICAgdGhpcy5lc3QuVE1QQm91bmRTb3VyY2UuZm9yRWFjaChpdG0gPT4ge1xyXG4gICAgICAgICAgICAgICAgaXRtLl9wYXJlbnQgPSBncm91cEtleTtcclxuICAgICAgICAgICAgICAgIGl0bS5fcGFyZW50Um91dGUgPSBncm91cFJvdXRlO1xyXG4gICAgICAgICAgICAgICAgaXRtLl90aGlzUm91dGUgPSBpdG0uX2dyb3VwID8gWy4uLmdyb3VwUm91dGUsIG5ldyBHcm91cFJvdXRlRnJhZ21lbnQoKDxHcm91cD5pdG0pLmNvbHVtbiwgKDxHcm91cD5pdG0pLnZhbHVlKV0gOiBbXTtcclxuICAgICAgICAgICAgICAgIGl0bS5fdGhpc0tleSA9IGl0bS5fZ3JvdXAgPyBncm91cEtleSArICg8R3JvdXA+aXRtKS52YWx1ZSA6IGdyb3VwS2V5O1xyXG5cclxuICAgICAgICAgICAgICAgIC8vIFBlciBsZSByaWNlcmNhIGludGVybWVkaWUgbWV0dG8gaSBncnVwcGkgbmVsbGEgY2FjaGUgZGVpIGdydXBwaVxyXG4gICAgICAgICAgICAgICAgaWYgKGludGVybWVkaWF0ZUdyb3VwKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgaXRtLl9ncm91cGxldmVsID0gdmlldy5yZXF1ZXN0ZWRncm91cHMubGVuZ3RoO1xyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMucmdHcm91cENhY2hlLnNldChpdG0uX3RoaXNLZXksIGl0bSk7XHJcbiAgICAgICAgICAgICAgICAgICAgY2hpbGRHcm91cHNDYWNoZVJlZmVyZW5jZS5wdXNoKGl0bSk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICAvLyBNZXR0byBhbmNoZSBnbGkgb2dnZXR0aSBuZWxsYSBjYWNoZSBub24gcmljb3JzaXZhXHJcbiAgICAgICAgICAgICAgICAgICAgaXRlbXNDYWNoZVJlZmVyZW5jZS5wdXNoKGl0bSk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH0pO1xyXG5cclxuICAgICAgICAgICAgLy8gRWxpbWlubyBnbGkgb2dnZXR0aSB2ZWNjaGlcclxuICAgICAgICAgICAgLy8gMSkgUmljZXJjYSBpbnRlcm1lZGlhLCBzdGF0byBzYWx2YXRvIC0gRWxpbWlubyB0dXR0aSBnbGkgaXRlbSBlIHR1dHRpIGkgZ3J1cHBpIGxhIGN1aSByb3V0ZSDDqCBwacO5IGx1bmdhIGRlbGxhIGNvcnJlbnRlLCB0dXR0aSBnbGkgaXRlbSByZWxhdGl2aSBhbGxhIHBhdGggY29ycmVudGUsIGUgdHV0dGVcclxuICAgICAgICAgICAgLy8gICAgbGUgY2FjaGUgZGkgcmljZXJjYSBlZmZldHR1YXRlIHN1IHVuYSBwYXRoIHBpw7kgcHJvZm9uZGEgZGVsbCdhdHR1YWxlXHJcbiAgICAgICAgICAgIC8vIDIpIFJpY2VyY2EgZmluYWxlIG8gcmljZXJjYSBpbnRlcm1lZGlhIHNlbnphIHN0YXRvIHNhbHZhdG8gLSBFbGltaW5vIHR1dHRpIGdsaSBpdGVtIHJlbGF0aXZpIGFsbGEgcGF0aCBjb3JyZW50ZVxyXG4gICAgICAgICAgICAvLyBQZXIgXCJzdGF0byBzYWx2YXRvXCIgc2kgaW50ZW5kb25vIHJpY2VyY2hlIHZlY2NoaWUgc2FsdmF0ZSBwZXIgcG90ZXIgZXNzZXJlIHJpZWZmZXR0dWF0ZSBpbiBjYXNvIGRpIG9yZGluYW1lbnRpIHN1IGNvbG9ubmUgZGkgaW50ZXJlc3NlXHJcbiAgICAgICAgICAgIGlmIChpbnRlcm1lZGlhdGVHcm91cCAmJiB2aWV3LnNhdmVkc3RhdGUpIHtcclxuICAgICAgICAgICAgICAgIHRoaXMuZXN0LmJvdW5kU291cmNlID0gdGhpcy5lc3QuYm91bmRTb3VyY2UuZmlsdGVyKHQgPT4gISh0Ll9pdGVtIHx8IHQuX3RoaXNSb3V0ZS5sZW5ndGggPiBncm91cFJvdXRlLmxlbmd0aCkpO1xyXG4gICAgICAgICAgICAgICAgdGhpcy5lc3QuZ3JvdXBTZWFyY2hSZXF1ZXN0c0NhY2hlID0gdGhpcy5lc3QuZ3JvdXBTZWFyY2hSZXF1ZXN0c0NhY2hlLmZpbHRlcih0ID0+ICEodC5yb3V0ZS5sZW5ndGggPiBncm91cFJvdXRlLmxlbmd0aCkpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGVsc2UgaWYgKGludGVybWVkaWF0ZUdyb3VwKVxyXG4gICAgICAgICAgICB7XHJcbiAgICAgICAgICAgICAgICAvLyBTZSBpbnZlY2UgbG8gc3RhdG8gbm9uIMOoIHNhbHZhdG8gdnVvbCBkaXJlIGNoZSBjJ8OoIHN0YXRvIHVuIGNhbWJpbyBkaSBwYWdpbmEgaW50ZXJubyBhZCB1biBncnVwcG8gZ2nDoCBhcGVydG86XHJcbiAgICAgICAgICAgICAgICAvLyAtIEVsaW1pbm8gdHV0dGkgZ2xpIGVsZW1lbnRpIHJpY29uZHVjaWJpbGkgYSBxdWVzdG8gZ3J1cHBvIGNoZSBlcmFubyBnacOgIHByZXNlbnRpXHJcbiAgICAgICAgICAgICAgICB0aGlzLmVzdC5ib3VuZFNvdXJjZSA9IHRoaXMuZXN0LmJvdW5kU291cmNlLmZpbHRlcih0ID0+ICEodC5faXRlbSB8fCAodC5fdGhpc0tleS5zdGFydHNXaXRoKGdyb3VwS2V5KSAmJiB0Ll90aGlzS2V5ICE9IGdyb3VwS2V5KSkpO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICB0aGlzLmVzdC5ib3VuZFNvdXJjZSA9IHRoaXMuZXN0LmJvdW5kU291cmNlLmZpbHRlcih0ID0+ICEodC5fcGFyZW50ID09IGdyb3VwS2V5KSk7XHJcblxyXG4gICAgICAgICAgICBsZXQgdGhpc0dyb3VwID0gdGhpcy5lc3QuYm91bmRTb3VyY2VbaW5zZXJ0SW5kZXhdO1xyXG4gICAgICAgICAgICBpZiAoaW50ZXJtZWRpYXRlR3JvdXApXHJcbiAgICAgICAgICAgICAgICB0aGlzR3JvdXAuX2dyb3Vwc2NvdW50ID0gKDxBcHBTZWFyY2g8YW55Pj50aGlzLmVzdC5WaWV3KT8uZ3JvdXBjb3VudDtcclxuXHJcbiAgICAgICAgICAgIC8vIExpIHNvc3RpdHVpc2NvIGNvaSBudW92aSBkaSBxdWVzdGEgcmljZXJjYVxyXG4gICAgICAgICAgICB0aGlzLmVzdC5ib3VuZFNvdXJjZS5zcGxpY2UoaW5zZXJ0SW5kZXggKyAxLCAwLCAuLi50aGlzLmVzdC5UTVBCb3VuZFNvdXJjZSk7XHJcblxyXG4gICAgICAgICAgICAvLyBBZ2dpdW5nbyB1biBzZXBhcmF0b3JlIGFsbGEgZmluZSBvIGFsbCdpbml6aW8gZGkgcXVlc3RpIGdydXBwaSBjaGUgZG92csOgIG9jY3VwYXJzaSBkaSBjYXJpY2FyZSBBTFRSSSBncnVwcGkgbyBvZ2dldHRpIChzZSBzb25vIGFsbCd1bHRpbW8gZ3J1cHBvKVxyXG4gICAgICAgICAgICBsZXQgYWRkTGFzdCA9IGZhbHNlO1xyXG4gICAgICAgICAgICB0aGlzLmVzdC5ib3VuZFNvdXJjZS5zcGxpY2UoaW5zZXJ0SW5kZXggKyAxICsgKGFkZExhc3QgPyB0aGlzLmVzdC5UTVBCb3VuZFNvdXJjZS5sZW5ndGggOiAwKSwgMCwgdGhpcy5nZXRHcm91cFNlcGFyYXRvcih2aWV3LCBncm91cEtleSwgZ3JvdXBSb3V0ZSwgdmlldy5yZXF1ZXN0ZWRncm91cHMubGVuZ3RoLCBpbnRlcm1lZGlhdGVHcm91cCA/ICdncm91cHMnIDogJ2l0ZW1zJykpO1xyXG5cclxuICAgICAgICAgICAgLy8gQWdnaXVuZ28gbGEgcmljZXJjYSBhbGxhIGNhY2hlIGRpIHF1ZXN0YSBcInNlc3Npb25lXCJcclxuICAgICAgICAgICAgbGV0IHRvQWRkID0geyBwYXRoOiBncm91cEtleSwgcm91dGU6IGdyb3VwUm91dGUsIHZpZXc6IE9iamVjdC5hc3NpZ24oe30sIHZpZXcpLCBncm91cF9jb2x1bW46IGludGVybWVkaWF0ZUdyb3VwID8gKDxHcm91cD50aGlzLmVzdC5UTVBCb3VuZFNvdXJjZVswXSkuY29sdW1uIDogJycgfTtcclxuICAgICAgICAgICAgbGV0IHByZXYgPSB0aGlzLmVzdC5ncm91cFNlYXJjaFJlcXVlc3RzQ2FjaGUuZmluZEluZGV4KHQgPT4gdC5wYXRoID09IHRvQWRkLnBhdGggJiYgdC5ncm91cF9jb2x1bW4gPT0gdG9BZGQuZ3JvdXBfY29sdW1uKTtcclxuICAgICAgICAgICAgaWYgKHByZXYgPT0gLTEpXHJcbiAgICAgICAgICAgICAgICB0aGlzLmVzdC5ncm91cFNlYXJjaFJlcXVlc3RzQ2FjaGUucHVzaCh0b0FkZCk7XHJcblxyXG4gICAgICAgICAgICBlbHNlXHJcbiAgICAgICAgICAgICAgICB0aGlzLmVzdC5ncm91cFNlYXJjaFJlcXVlc3RzQ2FjaGUuc3BsaWNlKHByZXYsIDEsIHRvQWRkKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBTZSBpbiBtb2RhbGl0w6AgYXJyYXkgYXBwbGljYSBpIHJhZ2dydXBwYW1lbnRpIGRlZmluaXRpIGxhdG8gcm93LWdyb3VwaW5nXHJcbiAgICAgKlxyXG4gICAgICogQHBhcmFtIHt0aHM6IEVzVGhEaXJlY3RpdmVbXX0gdGhzIEhlYWRlclxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgYXJyYXlNb2RlUmV2aWV3R3JvdXBpbmdzKHRoczogRXNUaERpcmVjdGl2ZVtdKSB7XHJcbiAgICAgICAgaWYgKHRocy5sZW5ndGggPT0gMClcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG5cclxuICAgICAgICBsZXQgaGVhZGVyR3JvdXBzOiBHcm91cFtdID0gW107XHJcbiAgICAgICAgbGV0IGhlYWRlckFnZ3JlZ2F0aW9uczogR3JvdXBPckFnZ3JlZ2F0aW9uW10gPSBbXTtcclxuXHJcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aHMubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICAgICAgbGV0IHRoID0gdGhzW2ldIGFzIEVzVGhEaXJlY3RpdmU7XHJcblxyXG4gICAgICAgICAgICBpZiAodGgudGhHcm91cClcclxuICAgICAgICAgICAgICAgIGhlYWRlckdyb3Vwcy5wdXNoKG5ldyBHcm91cCh0aC50aCwgMCwgXCJcIikpO1xyXG4gICAgICAgICAgICBlbHNlIGlmICh0aC50aEFnZ3JlZ2F0aW9uKVxyXG4gICAgICAgICAgICAgICAgaGVhZGVyQWdncmVnYXRpb25zID0gWy4uLmhlYWRlckFnZ3JlZ2F0aW9ucywgLi4udGhpcy5nZXRHcm91cEFnZ3JlZ2F0aW9ucyh0aCldO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKGhlYWRlckdyb3Vwcy5sZW5ndGggPiAwKSB7XHJcbiAgICAgICAgICAgIC8vIFB1bGl6aWEgZGVsbGUgY2FjaGVcclxuICAgICAgICAgICAgdGhpcy5yZ0dyb3VwQ2FjaGUuY2xlYXIoKTtcclxuICAgICAgICAgICAgdGhpcy5yZ0l0ZW1DYWNoZS5jbGVhcigpO1xyXG4gICAgICAgICAgICB0aGlzLnJnQ2hpbGRHcm91cHNDYWNoZS5jbGVhcigpO1xyXG5cclxuICAgICAgICAgICAgdGhpcy5lc3QuQXJyYXlHcm91cGluZyA9IHRydWU7XHJcbiAgICAgICAgICAgIHRoaXMuZXN0LmJvdW5kU291cmNlID0gdGhpcy5nZXRHcm91cHNSZWN1cnNpdmUoaGVhZGVyR3JvdXBzLCAwLCB0aGlzLmVzdC5ib3VuZFNvdXJjZSwgaGVhZGVyQWdncmVnYXRpb25zLCBudWxsKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBEYXRhIHVuYSBkaXJldHRpdmEgRXNUaCByZXN0aXR1aXNjZSBsYSBsaXN0YSBkZWxsZSBhZ2dyZWdhemlvbmkgcmljaGllc3RhIHBlciBxdWVzdGEgY29sb25uYSBvIGlsIGdydXBwbyBjaGUgcmFwcHJlc2VudGFcclxuICAgICAqXHJcbiAgICAgKiBAcGFyYW0ge0VzVGhEaXJlY3RpdmV9IHRoIERpcmV0dGl2YVxyXG4gICAgICpcclxuICAgICAqIEByZXR1cm5zIHtHcm91cE9yQWdncmVnYXRpb25bXX0gTGlzdGEgZGVpIGdydXBwaSBvIGFnZ3JlZ2F6aW9uaSByZWxhdGl2aSBhbGxhIERpcmV0dGl2YSBwYXNzYXRhXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBnZXRHcm91cEFnZ3JlZ2F0aW9ucyh0aDogRXNUaERpcmVjdGl2ZSk6IEdyb3VwT3JBZ2dyZWdhdGlvbltdIHtcclxuICAgICAgICBsZXQgcmV0ID0gW107XHJcbiAgICAgICAgLy8gRXM6ICd7bWluOmRkL01NL3l5eXl9IC0ge21heDpkZC9NTS95eXl5fSdcclxuICAgICAgICBpZiAodGgudGhBZ2dyZWdhdGlvbikge1xyXG4gICAgICAgICAgICB0aGlzLmdldEVzVGhEaXJlY3RpdmVMaXN0T2ZBZ2dyZWdhdGlvbnModGgpLmZvckVhY2goKGFnZzogVGhBZ2dyZWdhdGlvbikgPT4ge1xyXG4gICAgICAgICAgICAgICAgbGV0IGlzZGF0ZSA9IGFnZy5mb3JtYXQgJiYgWydzbWFsbCcsICdsb25nJywgJ3Zlcnlsb25nJ10uaW5jbHVkZXMoYWdnLmZvcm1hdCk7XHJcbiAgICAgICAgICAgICAgICBsZXQgaXNudW1iZXIgPSBhZ2cuZm9ybWF0ICYmIGFnZy5mb3JtYXQuc3RhcnRzV2l0aChcIkZcIikgJiYgIU51bWJlci5pc05hTihhZ2cuZm9ybWF0LmNoYXJBdCgxKSkgJiYgYWdnLmZvcm1hdC5sZW5ndGggPT0gMjtcclxuXHJcbiAgICAgICAgICAgICAgICBpZiAoIWlzZGF0ZSAmJiAhaXNudW1iZXIgJiYgYWdnLmZvcm1hdClcclxuICAgICAgICAgICAgICAgICAgICB0aHJvdyBcIkxlIGFnZ2VyZ2F6aW9uaSBzdXBwb3J0YXRlIGRhbGwnZXMtdGFibGUgc29ubyBzb2xvICdzbWFsbCcsICdsb25nJywgJ3Zlcnlsb25nJyBwZXIgbGUgZGF0ZSBlICdGMC05JyBwZXIgaSBudW1lcmlcIjtcclxuXHJcbiAgICAgICAgICAgICAgICByZXQucHVzaChuZXcgR3JvdXBPckFnZ3JlZ2F0aW9uKHRoLnRoLCBhZ2cuZnVuYywgaXNkYXRlID8gJ2RhdGUnIDogaXNudW1iZXIgPyAnbnVtYmVyJyA6ICdzdHJpbmcnKSk7XHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgIH1cclxuICAgICAgICBlbHNlIGlmICh0aC50aEdyb3VwKVxyXG4gICAgICAgICAgICByZXQucHVzaChuZXcgR3JvdXBPckFnZ3JlZ2F0aW9uKHRoLnRoLCBudWxsKSk7XHJcblxyXG4gICAgICAgIHJldHVybiByZXQ7XHJcbiAgICB9XHJcblxyXG5cclxuICAgIC8qKlxyXG4gICAgKiBEYXRhIHVuYSBkaXJldHRpdmEgY29uIHVuIGZvcm1hdG8gcmVzdGl0dWlzY2UgdHV0dGUgbGUgY29wcGllIEZ1bnppb25lIGRpIEFnZ3JlZ2F6aW9uZSAtIEZvcm1hdG9cclxuICAgICpcclxuICAgICogQHBhcmFtIHtFc1RoRGlyZWN0aXZlfSB0aCBEaXJldHRpdmEgRXNUaCBkaSBjdWkgY2FsY29sYXJlIGxlIGZ1bnppb25pIGRpIGFnZ3JlZ2F6aW9uZSB1c2F0ZVxyXG4gICAgKlxyXG4gICAgKiBAcmV0dXJucyB7eyBmdW5jOiBzdHJpbmcsIGZvcm1hdDogc3RyaW5nIH1bXX0gTGlzdGEgZGVsbGUgZnVuemlvbmkgZGkgYWdncmVnYXppb25lIHJpbGV2YXRlXHJcbiAgICAqL1xyXG4gICAgcHJpdmF0ZSBnZXRFc1RoRGlyZWN0aXZlTGlzdE9mQWdncmVnYXRpb25zKHRoOiBFc1RoRGlyZWN0aXZlKTogVGhBZ2dyZWdhdGlvbltdIHtcclxuICAgICAgICBpZiAoIXRoLnRoQWdncmVnYXRpb24pXHJcbiAgICAgICAgICAgIHJldHVybiBbXTtcclxuXHJcbiAgICAgICAgLy8gU2UgaG8gZ2nDoCBlZmZldHR1YXRvIHF1ZXN0byBjYWxjb2xvIHBlciBxdWVzdG8gdGggcmVzdGl0dWlzY28gbGEgdmVyc2lvbmUgaW4gY2FjaGVcclxuICAgICAgICBpZiAodGguX3RoQWdncmVnYXRpb25zKVxyXG4gICAgICAgICAgICByZXR1cm4gdGguX3RoQWdncmVnYXRpb25zO1xyXG5cclxuICAgICAgICBsZXQgcmV0ID0gW107XHJcbiAgICAgICAgbGV0IGRpc3BsYXkgPSB0aC50aEFnZ3JlZ2F0aW9uO1xyXG4gICAgICAgIHZhciBtYXRjaGVzID0gZGlzcGxheS5tYXRjaCgve1thLXpBLVowLTlcXC86XSp9L2dpKTtcclxuICAgICAgICBpZiAoIW1hdGNoZXMpXHJcbiAgICAgICAgICAgIHJldHVybiBbXTtcclxuICAgICAgICBtYXRjaGVzLmZvckVhY2gobSA9PiB7XHJcbiAgICAgICAgICAgIGxldCBzcGxpdCA9IG0uc3BsaXQoXCI6XCIpO1xyXG4gICAgICAgICAgICBsZXQgZnVuYyA9IG0sIGZvcm1hdCA9IFwiXCI7XHJcbiAgICAgICAgICAgIGlmIChzcGxpdC5sZW5ndGggPiAwKSB7XHJcbiAgICAgICAgICAgICAgICAvLyBFc2NsdWRvIHByaW1vIGUgdWx0aW1vIGNhcmF0dGVyZSAobGUgZ3JhZmZlKVxyXG4gICAgICAgICAgICAgICAgZnVuYyA9IHNwbGl0WzBdLnN1YnN0cigxKTtcclxuICAgICAgICAgICAgICAgIGZvcm1hdCA9IHNwbGl0WzFdLnN1YnN0cigwLCBzcGxpdFsxXS5sZW5ndGggLSAxKTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgcmV0LnB1c2goeyBmdW5jOiA8J21pbicgfCAnbWF4JyB8ICdzdW0nPmZ1bmMsIGZvcm1hdDogZm9ybWF0LCBtYXRjaDogbSB9KTtcclxuICAgICAgICB9KTtcclxuXHJcbiAgICAgICAgdGguX3RoQWdncmVnYXRpb25zID0gcmV0O1xyXG4gICAgICAgIHJldHVybiByZXQ7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBEYXRhIGxhIGRlZmluaXppb25lIGRlaSBncnVwcGkgZGEgZ2VuZXJhcmUgZGEgdW5hIGxpc3RhIGRpIG9nZ2V0dGksIHN1ZGRpdmlkZSBnbGkgb2dnZXR0aSBwYXNzYXRpIGluIGdydXBwaSBlIHNvdHRvZ3J1cHBpXHJcbiAgICAgKlxyXG4gICAgICogQHBhcmFtIHtHcm91cFtdfSBncnBzIERlZmluaXppb25lIGRlaSBncnVwcGlcclxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBjdXJyZW50SW5kZXggSW5kaWNlIGRpIGVsYWJvcmF6aW9uZS4gQWwgbGl2ZWxsbyAwIGhvIHR1dHRpIGdsaSBvZ2dldHRpIGUgZGV2byBnZW5lcmFyZSBpIHByaW1pIGdydXBwaSwgYSBsaXZlbGxvIDEgaG8gdHV0dGkgaSBncnVwcGkgcHJpbmNpcGFsaSBlIGRldm9cclxuICAgICAqIGVsYWJvcmFyZSBpIHNvdHRvZ3J1cHBpLCBlIGNvc8OsIHZpYSByaWNvcnNpdmFtZW50ZS4uLlxyXG4gICAgICogQHBhcmFtIHthbnlbXX0gaXRlbXMgT2dnZXR0aSBkYSByYWdncnVwcGFyZVxyXG4gICAgICogQHBhcmFtIHtHcm91cE9yQWdncmVnYXRpb25bXX0gYWdncmVnYXRpb25zIEluZm8gZGkgYWdncmVnYXppb25lXHJcbiAgICAgKiBAcGFyYW0ge2FueX0gcGFyZW50IFJpZmVyaW1lbnRvIGFsIGdydXBwbyBwYWRyZVxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIGdldEdyb3Vwc1JlY3Vyc2l2ZShncnBzOiBHcm91cFtdLCBjdXJyZW50SW5kZXg6IG51bWJlciwgaXRlbXM6IGFueVtdLCBhZ2dyZWdhdGlvbnM6IEdyb3VwT3JBZ2dyZWdhdGlvbltdLCBwYXJlbnQ/OiBhbnkpOiBhbnlbXSB7XHJcbiAgICAgICAgLy8gU2UgbCdpbmRpY2Ugw6ggMCBkZXZvIHNpY3VyYW1lbnRlIG5hc2NvbmRlcmUgdHV0dGkgZ2xpIG9nZ2V0dGkuIFNvbG8gaSBncnVwcGkgc2FyYW5ubyB2aXN1YWxpenphdGlcclxuICAgICAgICBpZiAoY3VycmVudEluZGV4ID09IDApXHJcbiAgICAgICAgICAgIGl0ZW1zLmZvckVhY2goaSA9PiBpLl92aXNpYmxlID0gZmFsc2UpO1xyXG5cclxuICAgICAgICBsZXQgZ3JwID0gZ3Jwc1tjdXJyZW50SW5kZXhdO1xyXG4gICAgICAgIGxldCByZXQ6IGFueVtdID0gW107XHJcbiAgICAgICAgbGV0IGxhc3QgPSBncnBzLmxlbmd0aCA9PSBjdXJyZW50SW5kZXggKyAxO1xyXG4gICAgICAgIGxldCBncm91cHMgPSB0aGlzLnV0aWxpdGllcy5ncm91cEJ5KGl0ZW1zLCBncnAuY29sdW1uKTtcclxuICAgICAgICBmb3IgKGxldCBwcm9wIGluIGdyb3Vwcykge1xyXG4gICAgICAgICAgICBsZXQgaXRtcyA9IGdyb3Vwc1twcm9wXTtcclxuICAgICAgICAgICAgbGV0IGdwID0gbmV3IEdyb3VwKGdycC5jb2x1bW4sIGl0bXMubGVuZ3RoLCBwcm9wKTtcclxuICAgICAgICAgICAgZ3AuYWdncmVnYXRpb25zID0gdGhpcy5nZW5lcmF0ZUFnZ3JlZ2F0aW9ucyhpdG1zLCBhZ2dyZWdhdGlvbnMpO1xyXG5cclxuICAgICAgICAgICAgbGV0IGFueWdwID0gKDxhbnk+Z3ApO1xyXG4gICAgICAgICAgICBhbnlncC5fZ3JvdXAgPSB0cnVlO1xyXG4gICAgICAgICAgICBhbnlncC5fZXhwYW5kZWQgPSBmYWxzZTtcclxuICAgICAgICAgICAgaWYgKCFwYXJlbnQpIHtcclxuICAgICAgICAgICAgICAgIGFueWdwLl90aGlzUm91dGUgPSBbeyBjb2x1bW46IGdwLmNvbHVtbiwgdmFsdWU6IGdwLnZhbHVlIH1dO1xyXG4gICAgICAgICAgICAgICAgYW55Z3AuX3RoaXNLZXkgPSBncC52YWx1ZTtcclxuICAgICAgICAgICAgICAgIGFueWdwLl9ncm91cGxldmVsID0gMDtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBlbHNlIHtcclxuICAgICAgICAgICAgICAgIGFueWdwLl9wYXJlbnQgPSBwYXJlbnQuX3RoaXNLZXk7XHJcbiAgICAgICAgICAgICAgICBhbnlncC5fcGFyZW50Um91dGUgPSBwYXJlbnQuX3RoaXNSb3V0ZTtcclxuICAgICAgICAgICAgICAgIGFueWdwLl90aGlzUm91dGUgPSBbLi4ucGFyZW50Ll90aGlzUm91dGUsIHsgY29sdW1uOiBncC5jb2x1bW4sIHZhbHVlOiBncC52YWx1ZSB9XTtcclxuICAgICAgICAgICAgICAgIGFueWdwLl90aGlzS2V5ID0gcGFyZW50Ll90aGlzS2V5ICsgZ3AudmFsdWU7XHJcbiAgICAgICAgICAgICAgICBhbnlncC5fZ3JvdXBsZXZlbCA9IHBhcmVudC5fZ3JvdXBsZXZlbCArIDE7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIC8vIFB1c2hvIGlsIGdydXBwbywgdHV0dGkgaSBncnVwcGkgZGVsIGxpdmVsbG8gc290dG8sIG8gZ2xpIGl0ZW0gc2UgaW8gc29ubyBsJ3VsdGltbyBncnVwcG8uXHJcbiAgICAgICAgICAgIC8vIExhIHZpc2liaWxpdMOgIMOoIHNvbG8gcGVyIGlsIGdydXBwbyBhIGxpdmVsbG8gMCwgdHV0dGkgZ2xpIGFsdHJpIGdydXBwaSBzYXJhbm5vIG1vc3RyYXRpIG8gbmFzY29zdGkgZGkgY29uc2VndWVuemFcclxuICAgICAgICAgICAgaWYgKGN1cnJlbnRJbmRleCA9PSAwKVxyXG4gICAgICAgICAgICAgICAgYW55Z3AuX3Zpc2libGUgPSB0cnVlO1xyXG5cclxuICAgICAgICAgICAgdGhpcy51dGlsaXRpZXMuY2FsY3VsYXRlSGFzaChbYW55Z3BdKTtcclxuICAgICAgICAgICAgdGhpcy51dGlsaXRpZXMuY2FjaGVBZ2dyZWdhdGlvbnMoYW55Z3ApO1xyXG5cclxuICAgICAgICAgICAgLy8gQWdnaXVuZ28gaWwgZ3J1cHBvIHBhZHJlXHJcbiAgICAgICAgICAgIHJldC5wdXNoKGFueWdwKTtcclxuICAgICAgICAgICAgdGhpcy5yZ0dyb3VwQ2FjaGUuc2V0KGFueWdwLl90aGlzS2V5LCBhbnlncCk7XHJcbiAgICAgICAgICAgIGlmICghbGFzdCkge1xyXG5cclxuICAgICAgICAgICAgICAgIC8vRGFsIGdydXBwbyBwYWRyZSwgc2Ugbm9uIMOoIGwndWx0aW1vIGdydXBwbyBkZWxsYSBjYXRlbmEsIGNhbGNvbG8gcmljb3JzaXZhbWVudGUgdHV0dGEgbGEgY2F0ZW5hIHNvdHRvXHJcbiAgICAgICAgICAgICAgICBsZXQgc3ViR3JvdXBzQW5kSXRlbXMgPSB0aGlzLmdldEdyb3Vwc1JlY3Vyc2l2ZShncnBzLCBjdXJyZW50SW5kZXggKyAxLCBpdG1zLCBhZ2dyZWdhdGlvbnMsIGFueWdwKTtcclxuICAgICAgICAgICAgICAgIGxldCBjaGlsZGdyb3VwcyA9IHN1Ykdyb3Vwc0FuZEl0ZW1zLmZpbHRlcih0ID0+IHQuX2dyb3VwICYmIHQuX3BhcmVudCA9PSBhbnlncC5fdGhpc0tleSk7XHJcbiAgICAgICAgICAgICAgICBhbnlncC5fZ3JvdXBzY291bnQgPSBjaGlsZGdyb3Vwcy5sZW5ndGg7XHJcblxyXG4gICAgICAgICAgICAgICAgLy8gQWdnaXVuZ28gbGEgY2F0ZW5hIGRlbCBncnVwcG8gc290dG8sIGFnZ2l1bmdlbmRvIGFsbGEgY2FjaGUgc29sbyBpIGdydXBwaSBwYWRyZVxyXG4gICAgICAgICAgICAgICAgcmV0LnB1c2goLi4uc3ViR3JvdXBzQW5kSXRlbXMpO1xyXG4gICAgICAgICAgICAgICAgdGhpcy5yZ0NoaWxkR3JvdXBzQ2FjaGUuc2V0KGFueWdwLl90aGlzS2V5LCBjaGlsZGdyb3Vwcyk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAvLyBBbCBncnVwcG8gcGFkcmUsIHNlIMOoIGwndWx0aW1vIGFzc2Vnbm8gdHV0dGUgbGUgZm9nbGllIGFzc2VnbmFuZG9nbGkgYW5jaGUgbGEgY2hpYXZlIGRlbCBncnVwcG9cclxuICAgICAgICAgICAgICAgIGl0bXMuZm9yRWFjaChpID0+IGkuX3RoaXNLZXkgPSBhbnlncC5fdGhpc0tleSk7XHJcblxyXG4gICAgICAgICAgICAgICAgcmV0LnB1c2goLi4uaXRtcyk7XHJcbiAgICAgICAgICAgICAgICB0aGlzLnJnSXRlbUNhY2hlLnNldChhbnlncC5fdGhpc0tleSwgaXRtcyk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIHJldDtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIERhdGEgdW5hIGxpc3RhIGRpIG9nZ2V0dGkgZ2VuZXJhIGxlIGFnZ3JlZ2F6aW9uaSBzcGVjaWZpY2F0ZS4gU2kgY29uc2lkZXJhIGRpIGF2ZXJlIHR1dHRpIGdsaSBvZ2dldHRpXHJcbiAgICAgKlxyXG4gICAgICogQHBhcmFtIHthbnlbXX0gaXRlbXMgT2dnZXR0aSBkaSBjdWkgY2FsY29sYXJlIGxlIGFnZ3JlZ2F6aW9uZVxyXG4gICAgICogQHBhcmFtIHtHcm91cE9yQWdncmVnYXRpb25bXX0gYWdncmVnYXRpb25zIEFnZ2VyZ2F6aW9uaSBkYSBnZW5lcmFyZVxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIGdlbmVyYXRlQWdncmVnYXRpb25zKGl0ZW1zOiBhbnlbXSwgYWdncmVnYXRpb25zOiBHcm91cE9yQWdncmVnYXRpb25bXSk6IEdyb3VwQWdncmVnYXRpb25bXSB7XHJcbiAgICAgICAgbGV0IHJldHM6IEdyb3VwQWdncmVnYXRpb25bXSA9IFtdO1xyXG4gICAgICAgIGxldCBhZ2dyZWdhdGlvblZhbHVlID0gXCJcIiwgZmVGaWVsZCA9IG51bGwsIHN0cmluZ0FnZyA9IG51bGwsIGRhdGVBZ2cgPSBudWxsLCBudW1iZXJBZ2cgPSBudWxsO1xyXG5cclxuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGFnZ3JlZ2F0aW9ucy5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgICAgICBsZXQgYWdnID0gYWdncmVnYXRpb25zW2ldO1xyXG4gICAgICAgICAgICBmZUZpZWxkID0gYWdnLmNvbHVtbjtcclxuICAgICAgICAgICAgaWYgKCFmZUZpZWxkKVxyXG4gICAgICAgICAgICAgICAgY29udGludWU7XHJcblxyXG4gICAgICAgICAgICBzd2l0Y2ggKGFnZy5kYXRhdHlwZSkge1xyXG4gICAgICAgICAgICAgICAgY2FzZSAnc3RyaW5nJzogc3RyaW5nQWdnID0gaXRlbXMubWFwKGkgPT4gaVtmZUZpZWxkXS50b1N0cmluZygpKTsgYnJlYWs7XHJcbiAgICAgICAgICAgICAgICBjYXNlICdkYXRlJzogZGF0ZUFnZyA9IGl0ZW1zLm1hcChpID0+IG5ldyBEYXRlKGlbZmVGaWVsZF0pLmdldFRpbWUoKSk7IGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgY2FzZSAnbnVtYmVyJzogbnVtYmVyQWdnID0gaXRlbXMubWFwKGkgPT4gcGFyc2VGbG9hdChpW2ZlRmllbGRdKSk7IGJyZWFrO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBzd2l0Y2ggKGFnZy5hZ2dyZWdhdGlvbikge1xyXG4gICAgICAgICAgICAgICAgY2FzZSAnbWF4JzpcclxuICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKGFnZy5kYXRhdHlwZSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdzdHJpbmcnOiBhZ2dyZWdhdGlvblZhbHVlID0gc3RyaW5nQWdnLnNvcnQoKS5yZXZlcnNlKClbMF07IGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdkYXRlJzogYWdncmVnYXRpb25WYWx1ZSA9IG5ldyBEYXRlKE1hdGgubWF4KC4uLmRhdGVBZ2cpKS50b1N0cmluZygpOyBicmVhaztcclxuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnbnVtYmVyJzogYWdncmVnYXRpb25WYWx1ZSA9IE1hdGgubWF4KC4uLm51bWJlckFnZykudG9TdHJpbmcoKTsgYnJlYWs7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgY2FzZSAnbWluJzpcclxuICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKGFnZy5kYXRhdHlwZSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdzdHJpbmcnOiBhZ2dyZWdhdGlvblZhbHVlID0gc3RyaW5nQWdnLnNvcnQoKVswXTsgYnJlYWs7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ2RhdGUnOiBhZ2dyZWdhdGlvblZhbHVlID0gbmV3IERhdGUoTWF0aC5taW4oLi4uZGF0ZUFnZykpLnRvU3RyaW5nKCk7IGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdudW1iZXInOiBhZ2dyZWdhdGlvblZhbHVlID0gTWF0aC5taW4oLi4ubnVtYmVyQWdnKS50b1N0cmluZygpOyBicmVhaztcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgICAgICBjYXNlICdzdW0nOlxyXG4gICAgICAgICAgICAgICAgICAgIHN3aXRjaCAoYWdnLmRhdGF0eXBlKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ3N0cmluZyc6IGFnZ3JlZ2F0aW9uVmFsdWUgPSBzdHJpbmdBZ2cuam9pbihcIiwgXCIpOyBicmVhaztcclxuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnZGF0ZSc6IGFnZ3JlZ2F0aW9uVmFsdWUgPSBcIlwiOyBicmVhaztcclxuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnbnVtYmVyJzogYWdncmVnYXRpb25WYWx1ZSA9IG51bWJlckFnZy5yZWR1Y2UoKHByZSwgY3VycikgPT4gcHJlICsgY3VyciwgMCkudG9TdHJpbmcoKTsgYnJlYWs7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIHJldHMucHVzaChuZXcgR3JvdXBBZ2dyZWdhdGlvbihhZ2cuY29sdW1uLCBhZ2cuYWdncmVnYXRpb24sIGFnZ3JlZ2F0aW9uVmFsdWUpKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiByZXRzO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgKiBPdHRpZW5lIHVuIGVsZW1lbnRvIGRpIHNlcGFyYXppb25lIGZyYSBHcnVwcGkgY2hlIHNlcnZlIHBlciBwYWdpbmFyZSBsZSByaWNlcmNoZSBhbGwnaW50ZXJubyBkaSBvZ25pIHNpbmdvbG8gZ3J1cHBvXHJcbiAgICAqXHJcbiAgICAqIEBwYXJhbSB7QXBwU2VhcmNoPGFueT59IHZpZXcgVmlldyB1dGlsaXp6YXRhIHBlciBsYSByaWNlcmNhLiBNZSBuZSBzYWx2byBpIHBhcmFtZXRyaSBuZWwgc2VwYXJhdG9yZSBhdHR1YWxlIGRhdG8gY2hlIG5lIGhvIGJpc29nbm8gcGVyIGNhcmljYXJlIGFsdHJpIGVsZW1lbnRpXHJcbiAgICAqIGZhY2VudGkgcmlmZXJpbWVudG8gYWxsbyBzdGVzc28gY29udGVzdG9cclxuICAgICogQHBhcmFtIHtzdHJpbmd9IHBhcmVudCBQYXJlbnQgcGF0aCBjaGUgcmFwcHJlc2VudGEgYSBxdWFsZSBncnVwcG8gw6ggYWZmaWJiaWF0byBxdWVzdG8gc2VwYXJhdG9yZVxyXG4gICAgKiBAcGFyYW0ge0dyb3VwUm91dGVGcmFnbWVudFtdfSByb3V0ZSBSb3V0ZSBwYXRoIGNoZSByYXBwcmVzZW50YSBhIHF1YWxlIGdydXBwbyDDqCBhZmZpYmJpYXRvIHF1ZXN0byBzZXBhcmF0b3JlXHJcbiAgICAqIEBwYXJhbSB7bnVtYmVyfSBsZXZlbCBMaXZlbGxvIGRlbCBncnVwcG8gZGkgY3VpIHF1ZXN0byBlbGVtZW50byDDqCBzZXBhcmF0b3JlLCB2aWVuZSB1c2F0byBwZXIgYXBwbGljYXJlIGxhIGNsYXNzZSBcImVzdC1sdmwte3tsZXZlbH19XCJcclxuICAgICpcclxuICAgICogQHJldHVybnMge2FueX0gRWxlbWVudG8gZGkgc2VwYXJhemlvbmUgY29udGVuZW50ZSB0dXR0aSBpIGJpbmQgcGVyIHByZXNlbnRhcmUgdW5hIHBhZ2luYXppb25lIHNvdHRvIHF1ZXN0byBncnVwcG8gbGF0byBpbnRlcmZhY2NpYVxyXG4gICAgKi9cclxuICAgIHB1YmxpYyBnZXRHcm91cFNlcGFyYXRvcih2aWV3OiBBcHBTZWFyY2g8YW55PiwgcGFyZW50OiBzdHJpbmcsIHJvdXRlOiBHcm91cFJvdXRlRnJhZ21lbnRbXSwgbGV2ZWw6IG51bWJlciwgc2VhcmNoZXM6ICdncm91cHMnIHwgJ2l0ZW1zJyk6IEdyb3VwUGFnZXIge1xyXG4gICAgICAgIGxldCBpdGVtID0gbmV3IEdyb3VwUGFnZXIobGV2ZWwsIHJvdXRlLCBwYXJlbnQsIE9iamVjdC5hc3NpZ24oe30sIHZpZXcpLCBzZWFyY2hlcyk7XHJcbiAgICAgICAgaXRlbS5idXR0b25zID0gdGhpcy51dGlsaXRpZXMuZ2V0UGFnZXNBcnJheSg2LCB2aWV3LnBhZ2UsIHZpZXcucGFnZXMpO1xyXG4gICAgICAgIHRoaXMudXRpbGl0aWVzLmNhbGN1bGF0ZUhhc2goW2l0ZW1dKTtcclxuICAgICAgICByZXR1cm4gaXRlbTtcclxuICAgIH1cclxuXHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBEYXRhIHVuYSBjb2xvbm5hIGVmZmV0dHVhIGxhIHJpZW1pc3Npb25lIGRpIHR1dHRlIGxlIHJpY2VyY2hlIHJlbGF0aXZlLlxyXG4gICAgICpcclxuICAgICAqIEVzLiBIbyAyIGNhbXBpIGRpIGdydXBwbyBlIGhvIGVzcGFuc28gZmlubyBhIHZlZGVyZSBpIHZhbG9yaSBmaW5vIGFkIHVuIGxpdmVsbG8gcXVhbHNpYXNpLlxyXG4gICAgICogQ2xpY2NvIGwnb3JkaW5hbWVudG8gc3VsIHNlY29uZG8gZ3J1cHBvLlxyXG4gICAgICogVHV0dGUgbGUgcmljZXJjaGUgcmVsYXRpdmUgYWkgcHJpbWkgZ3J1cHBpIGRldm9ubyBlc3NlcmUgcmllc2VndWl0ZS4gUXVhbmRvIGkgcmlzdWx0YXRpIGFycml2ZXJhbm5vIGNpIHBlbnNlcsOgIGlsIG1ldG9kbyAqKmJpbmREaXNwbGF5VG9Mb2FkZWRJdGVtc09yR3JvdXBzKipcclxuICAgICAqIGEgdGFnbGlhcmUgdmlhIGdsaSBvZ2dldHRpIG5vbiBwacO5IHZpc3VhbGl6emF0aVxyXG4gICAgICpcclxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBjb2x1bW4gQ29sb25uYSBzdSBjdWkgc2kgw6ggZWZmZXR0dWF0YSB1bidvcGVyYXppb25lIGRpIG9yZGluYW1lbnRvXHJcbiAgICAgKiBAcGFyYW0ge0FwcE9yZGVyaW5nW119IG9yZGVyaW5ncyBEaXJldHRpdmUgZGkgb3JkaW5hbWVudG8gZGEgYXBwbGljYXJlIGFsbGUgdmFyaWUgc290dG9yaWNlcmNoZVxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgZW1pdFJvd0dyb3VwaW5nU2VhcmNoZXMoY29sdW1uOiBzdHJpbmcsIG9yZGVyaW5nczogQXBwT3JkZXJpbmdbXSkge1xyXG4gICAgICAgIC8vIFBlciB0dXR0ZSBsZSByaWNlcmNoZSBpbnRlcm1lZGllIGNoZSBkZXZvIHJpdmFsdXRhcmUgbGUgcmUtZW1pdHRvIGluIG1vZG8gZGEgYWdnaW9ybmFyZ2xpIGkgZGF0aVxyXG4gICAgICAgIHZhciBtZWFuaW5nZnVsQXBwU2VhcmNoZXMgPSB0aGlzLmVzdC5ncm91cFNlYXJjaFJlcXVlc3RzQ2FjaGUuZmlsdGVyKHQgPT4gdC5ncm91cF9jb2x1bW4gPT0gY29sdW1uKS5tYXAodCA9PiB0LnZpZXcpO1xyXG5cclxuICAgICAgICAvLyBTZSBub24gbmUgdHJvdm8gc2lnbmlmaWNhIGNoZSBobyBmYXR0byBsJ29yZGluYW1lbnRvIG8gc3VnbGkgaXRlbSwgbyBzdSBjb2xvbm5lIHJlbGF0aXZlIGEgdW4gc290dG9ncnVwcG8gbm9uIGNhcmljYXRvXHJcbiAgICAgICAgaWYgKCFtZWFuaW5nZnVsQXBwU2VhcmNoZXMgfHwgbWVhbmluZ2Z1bEFwcFNlYXJjaGVzLmxlbmd0aCA9PSAwKVxyXG4gICAgICAgICAgICBtZWFuaW5nZnVsQXBwU2VhcmNoZXMgPSB0aGlzLmVzdC5ncm91cFNlYXJjaFJlcXVlc3RzQ2FjaGUuZmlsdGVyKHQgPT4gIXQuZ3JvdXBfY29sdW1uKS5tYXAodCA9PiB0LnZpZXcpO1xyXG5cclxuICAgICAgICAvLyBTZSBub24gbmUgdHJvdm8gcXVpIHNpZ25pZmljYSBjaGUgc3RvIG9yZGluYW5kbyBzdSBjb2xvbm5lIHJlbGF0aXZlIGEgdW4gc290dG9ncnVwcG8gbm9uIGNhcmljYXRvXHJcbiAgICAgICAgaWYgKCFtZWFuaW5nZnVsQXBwU2VhcmNoZXMgfHwgbWVhbmluZ2Z1bEFwcFNlYXJjaGVzLmxlbmd0aCA9PSAwKVxyXG4gICAgICAgICAgICByZXR1cm47XHJcblxyXG4gICAgICAgIG1lYW5pbmdmdWxBcHBTZWFyY2hlcy5mb3JFYWNoKGFzID0+IHtcclxuICAgICAgICAgICAgLy8gT3Z2aWFtZW50ZSBnbGkgb3JpZG5hbWVudGkgZGV2b25vIGVzc2VyZSBxdWVsbGkgYXBwZW5hIGdlbmVyYXRpXHJcbiAgICAgICAgICAgIGFzLm9yZGVycyA9IG9yZGVyaW5ncztcclxuICAgICAgICAgICAgYXMuc2F2ZWRzdGF0ZSA9IHRydWU7XHJcbiAgICAgICAgICAgIHRoaXMuZXN0LmVtaXRTZWFyY2hSZXF1ZXN0KGZhbHNlLCBhcyk7XHJcbiAgICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBIZWxwZXIgY2hlIGNhbGNvbGEgaWwgY29udGVudXRvIGRpIHVuYSBjZWxsYSByZWxhdGl2YSBhIHVuIGdydXBwbyByaWdhLCB0ZW5lbmRvIGNvbnRvIGRlbCBmb3JtYXRvIGRlbGxlIGV2ZW50dWFsaSBhZ2dyZWdhemlvbmlcclxuICAgICAqXHJcbiAgICAgKiBAcGFyYW0ge0dyb3VwfSBncnAgR3J1cHBvIGRpIGN1aSBtb3N0cmFyZSBsZSBjZWxsZVxyXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGNlbGwgQ2VsbGEgYXR0dWFsZSBkaSBjdWkgY2FsY29sYXJlIGlsIHRlc3RvXHJcbiAgICAgKiBAcGFyYW0ge0VzVGhEaXJlY3RpdmV9IGhlYWRlciBIZWFkZXIgcmVsYXRpdm8gYWxsYSBjZWxsYSBhdHR1YWxlLCB1dGlsaXp6YXRhIHBlciBpZGVudGlmaWNhcmUgbGUgaW5mb3JtYXppb25pIGRpIGFnZ3JlZ2F6aW9uZVxyXG4gICAgICpcclxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFRlc3RvIGZpbmFsZSBjYWxjb2xhdG8gcGVyIGxhICoqY2VsbCoqIGNvcnJlbnRlLCBpbiBiYXNlIGFsbGUgYWdncmVnYXppb25pIGRpICoqaGVhZGVyKipcclxuICAgICAqL1xyXG4gICAgcHVibGljIGdldEdyb3VwQ2VsbERpc3BsYXkoZ3JwOiBHcm91cCwgY2VsbDogc3RyaW5nLCBoZWFkZXI6IEVzVGhEaXJlY3RpdmUpOiBzdHJpbmcge1xyXG4gICAgICAgIGlmICgoPGFueT5ncnApLl9zZXApXHJcbiAgICAgICAgICAgIHJldHVybiBcIlwiO1xyXG4gICAgICAgIGxldCBkaXNwbGF5ID0gaGVhZGVyLnRoQWdncmVnYXRpb247XHJcbiAgICAgICAgaWYgKGdycC5jb2x1bW4gPT0gY2VsbCkge1xyXG4gICAgICAgICAgICBsZXQgZ3JvdXBzUGFydCA9ICg8YW55PmdycCkuX2dyb3Vwc2NvdW50ID8gXCIgLSBcIiArICg8YW55PmdycCkuX2dyb3Vwc2NvdW50ICsgXCIgXCIgKyB0aGlzLmVzdC5sYy5sb2MoXCJHcm91cHNcIikgOiBcIlwiO1xyXG4gICAgICAgICAgICByZXR1cm4gZ3JwLnZhbHVlICsgXCIgKFwiICsgZ3JwLmNvdW50ICsgZ3JvdXBzUGFydCArIFwiKVwiO1xyXG4gICAgICAgIH1cclxuICAgICAgICBlbHNlIHtcclxuXHJcbiAgICAgICAgICAgIGxldCBhZ2cgPSAoPE1hcDxzdHJpbmcsIE1hcDxzdHJpbmcsIHN0cmluZz4+Pig8YW55PmdycCkuX2FnZ3JlZ2F0aW9uc0NhY2hlKS5nZXQoY2VsbCk7XHJcbiAgICAgICAgICAgIGlmICghYWdnKVxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIFwiXCI7XHJcblxyXG4gICAgICAgICAgICB0aGlzLmdldEVzVGhEaXJlY3RpdmVMaXN0T2ZBZ2dyZWdhdGlvbnMoaGVhZGVyKS5mb3JFYWNoKChpdG06IFRoQWdncmVnYXRpb24pID0+IHtcclxuICAgICAgICAgICAgICAgIGRpc3BsYXkgPSBkaXNwbGF5LnJlcGxhY2UoaXRtLm1hdGNoLCB0aGlzLmZvcm1hdEFnZ3JlZ2F0aW9uVmFsdWUoYWdnLmdldChpdG0uZnVuYyksIGl0bS5mb3JtYXQpKTtcclxuICAgICAgICAgICAgfSk7XHJcblxyXG4gICAgICAgICAgICByZXR1cm4gZGlzcGxheTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBGdW56aW9uZSBjaGUgZGF0byB1biB2YWxvcmUgbG8gZm9ybWF0dGEgaW4gYmFzZSBhbCB0aXBvXHJcbiAgICAgKlxyXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHZhbHVlIFZhbG9yZSBjaGUgZ2VuZXJhbGVtbnRlIHB1w7IgZXNzZXJlIHVuYSBkYXRhIG8gdW4gbnVtZXJvXHJcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gZnJvbWF0IEZvcm1hdG8gc3UgY3VpIGZvcm1hdHRhcmUgaWwgdmFsb3JlLiBQdcOyIGVzc2VyZSBhZCBlc2VtcGlvIFwic21hbGxcIiwgXCJsb25nXCIgXCJ2ZXJ5bG9uZ1wiIHBlciBsZSBkYXRlIG8gRnswLTl9IHBlciBpIG51bWVyaSBkZWNpbWFsaVxyXG4gICAgICpcclxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFZhbG9yZSBkZWxsJ2FnZ3JlZ2F6aW9uZSBmb3JtYXR0YXRvIGNvbWUgc2kgZGV2ZVxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIGZvcm1hdEFnZ3JlZ2F0aW9uVmFsdWUodmFsdWU6IHN0cmluZywgZm9ybWF0Pzogc3RyaW5nKTogc3RyaW5nIHtcclxuICAgICAgICBpZiAoIWZvcm1hdClcclxuICAgICAgICAgICAgcmV0dXJuIHZhbHVlO1xyXG5cclxuICAgICAgICBsZXQgaXNOdW1iZXIgPSAhTnVtYmVyLmlzTmFOKHZhbHVlKSAmJiAoIWZvcm1hdCB8fCBmb3JtYXQuc3RhcnRzV2l0aChcIkZcIikpO1xyXG5cclxuICAgICAgICBpZiAoaXNOdW1iZXIgJiYgZm9ybWF0LnN0YXJ0c1dpdGgoXCJGXCIpICYmICFOdW1iZXIuaXNOYU4oZm9ybWF0LnN1YnN0cigxKSkpXHJcbiAgICAgICAgICAgIHJldHVybiBwYXJzZUZsb2F0KHZhbHVlKS50b0ZpeGVkKHBhcnNlSW50KGZvcm1hdC5zdWJzdHIoMSkpKTtcclxuXHJcbiAgICAgICAgbGV0IGRhdGUgPSBudWxsO1xyXG4gICAgICAgIC8vIEFsY3VuZSB2ZXJzaW9uZSBkaSBleHRlbnNpb25zIHJpc2NoaWFubyBkaSBjcmFzaGFyZSBjb24gY29zZSBub24gZGF0ZS4uLiDDqCBzdGF0byByaXNvbHRvIGRvcG8gcXVpbmRpIHF1ZXN0byB0cnkgLSBjYXRjaCBpbiByZWFsdMOgXHJcbiAgICAgICAgLy8gdG9ybmEgdXRpbGUgc29sbyBjb24gdmVyc2lvbmkgdmVjY2hpZS9kZXByZWNhdGUgZGVsbGEgbGlicmVyaWEgQGVzZmFlbnphL2V4dGVuc2lvbnNcclxuICAgICAgICB0cnkgeyBkYXRlID0gdGhpcy5kYXRlRXh0cy5nZXREYXRlQ29udmVydGlvbih2YWx1ZSk7IH0gY2F0Y2ggeyB9XHJcblxyXG4gICAgICAgIGlmIChkYXRlKVxyXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5kYXRlRXh0cy5nZXRGb3JtYXR0ZWQoZGF0ZSwgZm9ybWF0ID09ICdzbWFsbCcsIGZvcm1hdCA9PSAndmVyeWxvbmcnKTtcclxuXHJcbiAgICAgICAgLy8gUXVpIGNpIGZpbmlzY28gc2lhIHBlciBpbnB1dCBjaGUgbm9uIHNvbm8gbsOpIGRhdGUgbsOpIG51bWVyaSwgc2lhIHBlciBmb3JtYXRpIG5vbiByaWNvbm9zY2l1dGlcclxuICAgICAgICByZXR1cm4gdmFsdWU7XHJcbiAgICB9XHJcbn0iXX0=