@firestitch/report 18.9.0 → 18.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (190) hide show
  1. package/app/reports/anchor-at-point.d.ts +14 -0
  2. package/app/reports/canvas-landing-page.d.ts +2 -0
  3. package/app/reports/components/component-chart/component-chart.component.d.ts +18 -2
  4. package/app/reports/components/component-kpi/component-kpi.component.d.ts +4 -1
  5. package/app/reports/components/report-canvas/report-canvas.component.d.ts +3 -0
  6. package/app/reports/components/report-component/report-component.component.d.ts +35 -1
  7. package/app/reports/components/report-view-picker/report-view-picker.component.d.ts +21 -0
  8. package/app/reports/data/report.data.d.ts +17 -2
  9. package/app/reports/dialogs/component-settings/component-settings.component.d.ts +18 -3
  10. package/app/reports/dialogs/report-settings/report-settings.component.d.ts +15 -6
  11. package/app/reports/dialogs/report-view/report-view-dialog.component.d.ts +13 -0
  12. package/app/reports/drill-crumbs.d.ts +12 -0
  13. package/app/reports/export/report-export-collector.service.d.ts +13 -4
  14. package/app/reports/export/report-filter-lines.d.ts +18 -0
  15. package/app/reports/filter-settings-rules.d.ts +33 -0
  16. package/app/reports/format.d.ts +0 -1
  17. package/app/reports/interfaces/canvas-landing-input.interface.d.ts +8 -0
  18. package/app/reports/interfaces/component-data-applied.interface.d.ts +13 -0
  19. package/app/reports/interfaces/component-data-drill.interface.d.ts +22 -0
  20. package/app/reports/interfaces/filter-bar-placement.type.d.ts +1 -0
  21. package/app/reports/interfaces/filter-component-toggle-state.interface.d.ts +4 -0
  22. package/app/reports/interfaces/filter-settings-option.interface.d.ts +4 -0
  23. package/app/reports/interfaces/filter-type-select-state.interface.d.ts +5 -0
  24. package/app/reports/interfaces/report-chart-hit.interface.d.ts +5 -0
  25. package/app/reports/interfaces/report-chat-viewer-cross-filter-field.interface.d.ts +4 -0
  26. package/app/reports/interfaces/report-chat-viewer-cross-filter.interface.d.ts +7 -0
  27. package/app/reports/interfaces/report-chat-viewer-detail.interface.d.ts +4 -0
  28. package/app/reports/interfaces/report-chat-viewer-drill-step.interface.d.ts +5 -0
  29. package/app/reports/interfaces/report-chat-viewer-drill.interface.d.ts +5 -0
  30. package/app/reports/interfaces/report-chat-viewer-filter.interface.d.ts +3 -0
  31. package/app/reports/interfaces/report-chat-viewer-selection.interface.d.ts +5 -0
  32. package/app/reports/interfaces/report-chat-viewer-state.interface.d.ts +12 -0
  33. package/app/reports/interfaces/report-drill-crumb.interface.d.ts +6 -0
  34. package/app/reports/interfaces/report-drill-refusal.type.d.ts +1 -0
  35. package/app/reports/interfaces/report-drill-step.interface.d.ts +5 -0
  36. package/app/reports/interfaces/report-export-line-kind.type.d.ts +1 -0
  37. package/app/reports/interfaces/report-export-line.interface.d.ts +8 -0
  38. package/app/reports/interfaces/report-export-lines-input.interface.d.ts +9 -0
  39. package/app/reports/interfaces/report-export-snapshot.interface.d.ts +15 -0
  40. package/app/reports/interfaces/report-filter-line-context.interface.d.ts +8 -0
  41. package/app/reports/interfaces/report-filter-line-form.type.d.ts +1 -0
  42. package/app/reports/interfaces/report-filter-match.type.d.ts +1 -0
  43. package/app/reports/interfaces/report-filter-option-pair.interface.d.ts +4 -0
  44. package/app/reports/interfaces/report-filter-options-ask.interface.d.ts +6 -0
  45. package/app/reports/interfaces/report-filter-options-list.interface.d.ts +7 -0
  46. package/app/reports/interfaces/report-filter-options-request.interface.d.ts +6 -0
  47. package/app/reports/interfaces/report-filter-options-stream.interface.d.ts +11 -0
  48. package/app/reports/interfaces/report-filter-options.interface.d.ts +7 -0
  49. package/app/reports/interfaces/report-filter-skip.type.d.ts +1 -0
  50. package/app/reports/interfaces/report-mark-action.type.d.ts +1 -0
  51. package/app/reports/interfaces/report-mark-click.interface.d.ts +13 -0
  52. package/app/reports/interfaces/report-mark-context.interface.d.ts +6 -0
  53. package/app/reports/interfaces/report-mark-decision.interface.d.ts +6 -0
  54. package/app/reports/interfaces/report-mark-event.interface.d.ts +11 -0
  55. package/app/reports/interfaces/report-mark-point.interface.d.ts +8 -0
  56. package/app/reports/interfaces/report-temporary-state.interface.d.ts +4 -0
  57. package/app/reports/interfaces/report-tile-state.interface.d.ts +8 -0
  58. package/app/reports/interfaces/report-url-link.interface.d.ts +4 -0
  59. package/app/reports/interfaces/report-url-value-name.type.d.ts +1 -0
  60. package/app/reports/interfaces/report-url-write.interface.d.ts +4 -0
  61. package/app/reports/interfaces/report-view-config.interface.d.ts +11 -0
  62. package/app/reports/interfaces/report-view-create.interface.d.ts +7 -0
  63. package/app/reports/interfaces/report-view-deleted.interface.d.ts +4 -0
  64. package/app/reports/interfaces/report-view-dialog-data.interface.d.ts +7 -0
  65. package/app/reports/interfaces/report-view-dropped.interface.d.ts +5 -0
  66. package/app/reports/interfaces/report-view-menu-item.interface.d.ts +10 -0
  67. package/app/reports/interfaces/report-view-summary.interface.d.ts +11 -0
  68. package/app/reports/interfaces/report-view.interface.d.ts +7 -0
  69. package/app/reports/interfaces/report-viewer-feature.type.d.ts +1 -0
  70. package/app/reports/interfaces/report-views.interface.d.ts +7 -0
  71. package/app/reports/interfaces/report.interface.d.ts +27 -3
  72. package/app/reports/interfaces/tile-load-result.interface.d.ts +4 -0
  73. package/app/reports/mark-click.d.ts +20 -0
  74. package/app/reports/option-builder.d.ts +12 -1
  75. package/app/reports/report-chat-viewer-state.d.ts +8 -0
  76. package/app/reports/report-date-presets.d.ts +2 -0
  77. package/app/reports/report-filter-items.d.ts +27 -22
  78. package/app/reports/report-tile.d.ts +2 -0
  79. package/app/reports/report-url-state.d.ts +27 -10
  80. package/app/reports/report-view-config.d.ts +36 -0
  81. package/app/reports/report-view-menu.d.ts +15 -0
  82. package/app/reports/report-viewer-features.d.ts +5 -0
  83. package/app/reports/services/report-filter-options.service.d.ts +26 -0
  84. package/app/reports/services/report-filter-state.service.d.ts +64 -1
  85. package/app/reports/services/report-view.service.d.ts +51 -0
  86. package/app/reports/tile-data-state.d.ts +7 -0
  87. package/app/reports/tile-loads.d.ts +4 -0
  88. package/app/reports/views/report/fs-ai-report.component.d.ts +9 -1
  89. package/app/reports/views/report/report.component.d.ts +6 -0
  90. package/esm2022/app/reports/anchor-at-point.mjs +49 -0
  91. package/esm2022/app/reports/canvas-landing-page.mjs +25 -0
  92. package/esm2022/app/reports/components/component-chart/component-chart.component.mjs +97 -5
  93. package/esm2022/app/reports/components/component-kpi/component-kpi.component.mjs +11 -4
  94. package/esm2022/app/reports/components/component-list/component-list.component.mjs +7 -1
  95. package/esm2022/app/reports/components/report-canvas/report-canvas.component.mjs +47 -32
  96. package/esm2022/app/reports/components/report-component/report-component.component.mjs +257 -61
  97. package/esm2022/app/reports/components/report-view-picker/report-view-picker.component.mjs +115 -0
  98. package/esm2022/app/reports/data/report.data.mjs +87 -10
  99. package/esm2022/app/reports/dialogs/component-settings/component-settings.component.mjs +106 -51
  100. package/esm2022/app/reports/dialogs/report-settings/report-settings.component.mjs +86 -90
  101. package/esm2022/app/reports/dialogs/report-view/report-view-dialog.component.mjs +52 -0
  102. package/esm2022/app/reports/drill-crumbs.mjs +73 -0
  103. package/esm2022/app/reports/export/report-export-collector.service.mjs +187 -117
  104. package/esm2022/app/reports/export/report-filter-lines.mjs +235 -0
  105. package/esm2022/app/reports/export/report-pdf.service.mjs +12 -7
  106. package/esm2022/app/reports/export/report-pptx.service.mjs +18 -14
  107. package/esm2022/app/reports/filter-settings-rules.mjs +283 -0
  108. package/esm2022/app/reports/format.mjs +2 -22
  109. package/esm2022/app/reports/interfaces/canvas-landing-input.interface.mjs +2 -0
  110. package/esm2022/app/reports/interfaces/component-data-applied.interface.mjs +2 -0
  111. package/esm2022/app/reports/interfaces/component-data-drill.interface.mjs +2 -0
  112. package/esm2022/app/reports/interfaces/filter-bar-placement.type.mjs +2 -0
  113. package/esm2022/app/reports/interfaces/filter-component-toggle-state.interface.mjs +2 -0
  114. package/esm2022/app/reports/interfaces/filter-settings-option.interface.mjs +2 -0
  115. package/esm2022/app/reports/interfaces/filter-type-select-state.interface.mjs +2 -0
  116. package/esm2022/app/reports/interfaces/report-chart-hit.interface.mjs +2 -0
  117. package/esm2022/app/reports/interfaces/report-chat-viewer-cross-filter-field.interface.mjs +2 -0
  118. package/esm2022/app/reports/interfaces/report-chat-viewer-cross-filter.interface.mjs +2 -0
  119. package/esm2022/app/reports/interfaces/report-chat-viewer-detail.interface.mjs +2 -0
  120. package/esm2022/app/reports/interfaces/report-chat-viewer-drill-step.interface.mjs +2 -0
  121. package/esm2022/app/reports/interfaces/report-chat-viewer-drill.interface.mjs +2 -0
  122. package/esm2022/app/reports/interfaces/report-chat-viewer-filter.interface.mjs +1 -1
  123. package/esm2022/app/reports/interfaces/report-chat-viewer-selection.interface.mjs +2 -0
  124. package/esm2022/app/reports/interfaces/report-chat-viewer-state.interface.mjs +1 -1
  125. package/esm2022/app/reports/interfaces/report-drill-crumb.interface.mjs +2 -0
  126. package/esm2022/app/reports/interfaces/report-drill-refusal.type.mjs +2 -0
  127. package/esm2022/app/reports/interfaces/report-drill-step.interface.mjs +2 -0
  128. package/esm2022/app/reports/interfaces/report-export-line-kind.type.mjs +2 -0
  129. package/esm2022/app/reports/interfaces/report-export-line.interface.mjs +2 -0
  130. package/esm2022/app/reports/interfaces/report-export-lines-input.interface.mjs +2 -0
  131. package/esm2022/app/reports/interfaces/report-export-snapshot.interface.mjs +2 -0
  132. package/esm2022/app/reports/interfaces/report-filter-line-context.interface.mjs +2 -0
  133. package/esm2022/app/reports/interfaces/report-filter-line-form.type.mjs +2 -0
  134. package/esm2022/app/reports/interfaces/report-filter-match.type.mjs +2 -0
  135. package/esm2022/app/reports/interfaces/report-filter-option-pair.interface.mjs +2 -0
  136. package/esm2022/app/reports/interfaces/report-filter-options-ask.interface.mjs +2 -0
  137. package/esm2022/app/reports/interfaces/report-filter-options-list.interface.mjs +2 -0
  138. package/esm2022/app/reports/interfaces/report-filter-options-request.interface.mjs +2 -0
  139. package/esm2022/app/reports/interfaces/report-filter-options-stream.interface.mjs +2 -0
  140. package/esm2022/app/reports/interfaces/report-filter-options.interface.mjs +2 -0
  141. package/esm2022/app/reports/interfaces/report-filter-skip.type.mjs +2 -0
  142. package/esm2022/app/reports/interfaces/report-mark-action.type.mjs +2 -0
  143. package/esm2022/app/reports/interfaces/report-mark-click.interface.mjs +2 -0
  144. package/esm2022/app/reports/interfaces/report-mark-context.interface.mjs +2 -0
  145. package/esm2022/app/reports/interfaces/report-mark-decision.interface.mjs +2 -0
  146. package/esm2022/app/reports/interfaces/report-mark-event.interface.mjs +2 -0
  147. package/esm2022/app/reports/interfaces/report-mark-point.interface.mjs +2 -0
  148. package/esm2022/app/reports/interfaces/report-temporary-state.interface.mjs +2 -0
  149. package/esm2022/app/reports/interfaces/report-tile-state.interface.mjs +2 -0
  150. package/esm2022/app/reports/interfaces/report-url-link.interface.mjs +2 -0
  151. package/esm2022/app/reports/interfaces/report-url-value-name.type.mjs +2 -0
  152. package/esm2022/app/reports/interfaces/report-url-write.interface.mjs +2 -0
  153. package/esm2022/app/reports/interfaces/report-view-config.interface.mjs +2 -0
  154. package/esm2022/app/reports/interfaces/report-view-create.interface.mjs +2 -0
  155. package/esm2022/app/reports/interfaces/report-view-deleted.interface.mjs +2 -0
  156. package/esm2022/app/reports/interfaces/report-view-dialog-data.interface.mjs +2 -0
  157. package/esm2022/app/reports/interfaces/report-view-dropped.interface.mjs +2 -0
  158. package/esm2022/app/reports/interfaces/report-view-menu-item.interface.mjs +2 -0
  159. package/esm2022/app/reports/interfaces/report-view-summary.interface.mjs +2 -0
  160. package/esm2022/app/reports/interfaces/report-view.interface.mjs +2 -0
  161. package/esm2022/app/reports/interfaces/report-viewer-feature.type.mjs +2 -0
  162. package/esm2022/app/reports/interfaces/report-views.interface.mjs +2 -0
  163. package/esm2022/app/reports/interfaces/report.interface.mjs +1 -1
  164. package/esm2022/app/reports/interfaces/tile-load-result.interface.mjs +2 -0
  165. package/esm2022/app/reports/mark-click.mjs +193 -0
  166. package/esm2022/app/reports/option-builder.mjs +159 -15
  167. package/esm2022/app/reports/report-chat-viewer-state.mjs +34 -0
  168. package/esm2022/app/reports/report-date-presets.mjs +18 -0
  169. package/esm2022/app/reports/report-filter-items.mjs +343 -72
  170. package/esm2022/app/reports/report-tile.mjs +12 -0
  171. package/esm2022/app/reports/report-url-state.mjs +596 -108
  172. package/esm2022/app/reports/report-view-config.mjs +697 -0
  173. package/esm2022/app/reports/report-view-menu.mjs +119 -0
  174. package/esm2022/app/reports/report-viewer-features.mjs +42 -0
  175. package/esm2022/app/reports/services/report-filter-options.service.mjs +238 -0
  176. package/esm2022/app/reports/services/report-filter-state.service.mjs +697 -62
  177. package/esm2022/app/reports/services/report-view.service.mjs +358 -0
  178. package/esm2022/app/reports/tile-data-state.mjs +127 -0
  179. package/esm2022/app/reports/tile-loads.mjs +38 -0
  180. package/esm2022/app/reports/views/report/fs-ai-report.component.mjs +177 -46
  181. package/esm2022/app/reports/views/report/report.component.mjs +103 -23
  182. package/esm2022/public_api.mjs +23 -1
  183. package/fesm2022/{firestitch-report-echarts-DBMOHmBF.mjs → firestitch-report-echarts-UBg8Wlhd.mjs} +2 -2
  184. package/fesm2022/{firestitch-report-echarts-DBMOHmBF.mjs.map → firestitch-report-echarts-UBg8Wlhd.mjs.map} +1 -1
  185. package/fesm2022/{firestitch-report-firestitch-report-CqbXT1gh.mjs → firestitch-report-firestitch-report-B1keNrcK.mjs} +9063 -4272
  186. package/fesm2022/firestitch-report-firestitch-report-B1keNrcK.mjs.map +1 -0
  187. package/fesm2022/firestitch-report.mjs +1 -1
  188. package/package.json +1 -1
  189. package/public_api.d.ts +22 -0
  190. package/fesm2022/firestitch-report-firestitch-report-CqbXT1gh.mjs.map +0 -1
@@ -25,6 +25,7 @@ import { resolveFormatContext } from '../../format';
25
25
  import { KPI_SPARKLINE_DEFAULT_GRANULARITY, KPI_SPARKLINE_DEFAULT_PERIODS, kpiCardSettings, sameKpiCardSettings, } from '../../kpi-card';
26
26
  import { GRANULARITY_OPTIONS, } from '../../interfaces/report.interface';
27
27
  import { DEFAULT_COMPONENT_PADDING } from '../../layout';
28
+ import { FILTER_TYPE_OPTIONS, barPlacement, barPlacementOptions, componentToggleState, filterLevel, filterLevelChoices, shownOnComponent, typeSelectState, valueFilterLevel, valuePlacementOptions, } from '../../filter-settings-rules';
28
29
  import { escapeHtml } from '../../text';
29
30
  import { operandKeys, reportComponents, valueKey } from '../../values';
30
31
  import * as i0 from "@angular/core";
@@ -127,19 +128,25 @@ export class ComponentSettingsComponent {
127
128
  sqlTimezone = signal('UTC');
128
129
  sqlError = signal(null);
129
130
  // ---- filter management state ----
130
- // One row per filterable column. The two booleans drive the toggles; we flip
131
- // them optimistically on click (so the UI never blinks while the request is
132
- // in flight) and reconcile from the server on reload.
131
+ // One row per filterable column. The placement and the toggle change
132
+ // optimistically on click (so the UI never blinks while the request is in
133
+ // flight) and reconcile from the server on reload.
133
134
  rows = signal([]);
134
135
  columnsError = signal(null);
136
+ // The Type select's choices. A row's Type select, Report bar select and
137
+ // This component toggle follow the rules in filter-settings-rules.ts.
138
+ typeOptions = FILTER_TYPE_OPTIONS;
135
139
  // The raw inputs the rows are built from.
136
140
  _filterableColumns = [];
137
141
  _filters = [];
138
142
  _groupsById = new Map();
143
+ // The type picked for a column with no filter yet, so a reload keeps it.
144
+ _pickedTypes = new Map();
139
145
  _typeLabels = {
140
146
  select: 'Pick values',
141
147
  dateRange: 'Date range',
142
148
  keyword: 'Search text',
149
+ numberRange: 'Number range',
143
150
  };
144
151
  _data = inject(MAT_DIALOG_DATA);
145
152
  _dialogRef = inject(MatDialogRef);
@@ -244,67 +251,96 @@ export class ComponentSettingsComponent {
244
251
  this._dialogRef.close({ settings: saved ? { ...settings, kpi: saved } : settings });
245
252
  }));
246
253
  };
247
- // Flip one exposure (report bar or this component) for a row. We update the
248
- // row's boolean first — so the toggle stays put with no blink — then persist
249
- // and reconcile on reload. Neither on → no filter (removed); either on → the
250
- // filter exists at the combined level. The interface type is inferred
251
- // server-side. A value has the report bar toggle only, with its own rules
252
- // (_setValueExposure).
253
- setExposure(row, target, on) {
254
+ // The type a column's filter will be made with. Only a column with no
255
+ // filter offers the pick (the Type select is locked otherwise), and nothing
256
+ // is saved until the filter is made.
257
+ setType(row, type) {
258
+ this._pickedTypes.set(row.column, type);
259
+ this._patchRow(row, { type });
260
+ }
261
+ // Where the row's filter shows in the report bar. This page only shows it
262
+ // in its page's bar alone, so the This component toggle goes off and locks.
263
+ // A value has this select only, with its own rules (_applyValueLevel).
264
+ setPlacement(row, placement) {
265
+ const patched = this._patchRow(row, {
266
+ placement,
267
+ component: placement === 'page' ? false : row.component,
268
+ componentToggle: componentToggleState(placement),
269
+ });
270
+ if (this.isValue()) {
271
+ this._applyValueLevel(patched);
272
+ }
273
+ else {
274
+ this._applyLevel(patched);
275
+ }
276
+ }
277
+ // A value has no This component toggle.
278
+ setComponent(row, component) {
254
279
  if (this.isValue()) {
255
- if (target === 'report') {
256
- this._setValueExposure(row, on);
257
- }
258
280
  return;
259
281
  }
260
- row[target] = on;
282
+ this._applyLevel(this._patchRow(row, { component }));
283
+ }
284
+ // Persist the level the row's controls ask for, then reconcile on reload.
285
+ // No level → no filter (removed); otherwise the filter exists at that
286
+ // level. A server refusal (a page filter whose members sit on two pages)
287
+ // shows its own text and the row snaps back.
288
+ _applyLevel(row) {
289
+ const level = filterLevel(row.placement, row.component);
261
290
  const existing = this._filters.find((filter) => filter.filterColumn === row.column);
262
- if (!row.report && !row.component) {
291
+ if (!level) {
263
292
  if (existing) {
264
293
  this._run(this._reportData.deleteFilter(this.report.id, existing.id));
265
294
  }
266
295
  return;
267
296
  }
268
- const level = row.report && row.component
269
- ? 'both'
270
- : (row.report ? 'report' : 'component');
271
297
  if (existing) {
272
298
  this._run(this._reportData.updateFilterGroup(this.report.id, existing.filterGroupId, { level }));
273
299
  }
274
300
  else {
275
- this._run(this._reportData.addFilter(this.report.id, this.component.id, {
276
- filterColumn: row.column,
277
- label: row.label,
278
- level,
279
- }));
301
+ this._addFilter(row, level);
280
302
  }
281
303
  }
282
- // A value's report bar toggle, the only one it has. Its filter's group is
283
- // report-wide and may be shared (the report's Period, say), and a value has
284
- // no strip of its own, so this never lowers a group's level: off unlinks
285
- // this value alone and the group keeps its other members, and on raises a
286
- // strip-only group to both, keeping its strips, or adds the value to a new
287
- // report-level group.
288
- _setValueExposure(row, on) {
289
- row.report = on;
304
+ // A value's Report bar select, the only control it has. Its filter's group
305
+ // may be shared (the report's Period, say), and a value has no strip of its
306
+ // own, so a pick never lowers the group (valueFilterLevel). A pick that
307
+ // moves nothing puts the row back as the group stands.
308
+ _applyValueLevel(row) {
290
309
  const existing = this._filters.find((filter) => filter.filterColumn === row.column);
291
- if (!on) {
310
+ const current = existing ? this._groupsById.get(existing.filterGroupId)?.level : undefined;
311
+ const level = valueFilterLevel(row.placement, current);
312
+ if (!level) {
292
313
  if (existing) {
293
314
  this._run(this._reportData.deleteFilter(this.report.id, existing.id));
294
315
  }
295
- return;
296
316
  }
297
- if (!existing) {
298
- this._run(this._reportData.addFilter(this.report.id, this.component.id, {
299
- filterColumn: row.column,
300
- label: row.label,
301
- level: 'report',
302
- }));
317
+ else if (!existing) {
318
+ this._addFilter(row, level);
319
+ }
320
+ else if (level !== current) {
321
+ this._run(this._reportData.updateFilterGroup(this.report.id, existing.filterGroupId, { level }));
303
322
  }
304
- else if (this._groupsById.get(existing.filterGroupId)?.level === 'component') {
305
- this._run(this._reportData.updateFilterGroup(this.report.id, existing.filterGroupId, { level: 'both' }));
323
+ else {
324
+ this._rebuildRows();
306
325
  }
307
326
  }
327
+ // The type goes only when the author could pick it; otherwise the server
328
+ // infers it, as it always has.
329
+ _addFilter(row, level) {
330
+ this._run(this._reportData.addFilter(this.report.id, this.component.id, {
331
+ filterColumn: row.column,
332
+ label: row.label,
333
+ level,
334
+ ...(row.typeSelect.show ? { type: row.type } : {}),
335
+ }));
336
+ }
337
+ // A new row object rather than a mutation, so the signal sees the change;
338
+ // the @for tracks the column, so the row's controls survive the swap.
339
+ _patchRow(row, patch) {
340
+ const patched = { ...row, ...patch };
341
+ this.rows.update((rows) => rows.map((item) => (item.column === row.column ? patched : item)));
342
+ return patched;
343
+ }
308
344
  // What a formula works out, naming each operand as its chips do. An op this
309
345
  // viewer does not know reads nothing.
310
346
  _formulaLine() {
@@ -405,24 +441,43 @@ export class ComponentSettingsComponent {
405
441
  });
406
442
  }
407
443
  // Build the row view-model from the loaded columns + filters/groups. Each
408
- // row's toggles reflect where its filter group is currently exposed. A
409
- // value's rows never read as on a component: it has no strip, whatever
410
- // level a group it shares is at.
444
+ // row's controls reflect where its filter group currently shows; a column
445
+ // with a filter shows the filter's own type. A value's rows never read as
446
+ // on a component: it has no strip, whatever level a group it shares is at,
447
+ // and its Report bar select offers no pick that lowers that group.
411
448
  _rebuildRows() {
449
+ const levelChoices = filterLevelChoices(this.report.viewerFeatures, this._onPage());
412
450
  this.rows.set(this._filterableColumns.map((column) => {
413
451
  const filter = this._filters.find((candidate) => candidate.filterColumn === column.column);
414
- const level = filter ? this._groupsById.get(filter.filterGroupId)?.level : undefined;
452
+ const group = filter ? this._groupsById.get(filter.filterGroupId) : undefined;
453
+ const placement = barPlacement(group?.level);
415
454
  return {
416
455
  column: column.column,
417
- type: column.type,
456
+ type: group?.type
457
+ ?? this._pickedTypes.get(column.column)
458
+ ?? column.types?.[0]
459
+ ?? column.type,
418
460
  label: filter?.label
419
461
  || this._groupsById.get(filter?.filterGroupId ?? -1)?.label
420
462
  || this._humanize(column.column),
421
- report: level === 'report' || level === 'both',
422
- component: !this.isValue() && (level === 'component' || level === 'both'),
463
+ placement,
464
+ component: !this.isValue() && shownOnComponent(group?.level),
465
+ typeSelect: typeSelectState(column.types, !!filter, this.report.viewerFeatures),
466
+ placementOptions: this.isValue()
467
+ ? valuePlacementOptions(levelChoices, group?.level)
468
+ : barPlacementOptions(levelChoices, placement),
469
+ componentToggle: componentToggleState(placement),
423
470
  };
424
471
  }));
425
472
  }
473
+ // Whether the component sits on a page: among its components, or, for a
474
+ // value, its values. A header or footer component or value sits on none,
475
+ // so its filters cannot be page filters.
476
+ _onPage() {
477
+ return (this.report.pages ?? [])
478
+ .some((page) => [...(page.components ?? []), ...(page.values ?? [])]
479
+ .some((candidate) => candidate.id === this.component.id));
480
+ }
426
481
  // After any filter mutation: re-fetch the report so the dialog's filter list
427
482
  // (and the parent canvas, on close) reflect the new groups/levels.
428
483
  _afterMutation() {
@@ -492,7 +547,7 @@ export class ComponentSettingsComponent {
492
547
  .replace(/\b\w/g, (character) => character.toUpperCase());
493
548
  }
494
549
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ComponentSettingsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
495
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: ComponentSettingsComponent, isStandalone: true, selector: "ng-component", ngImport: i0, template: "<form\n fsForm\n [submit]=\"save\">\n <fs-dialog>\n <h1 mat-dialog-title>\n {{ component.title || (isValue() ? 'Value' : 'Component') }}\n </h1>\n <mat-dialog-content>\n <mat-tab-group [(selected)]=\"selectedTab\">\n <mat-tab\n label=\"Settings\"\n name=\"settings\">\n <div class=\"fs-column tab-body\">\n <mat-form-field>\n <mat-label>\n {{ isValue() ? 'Name' : 'Title' }}\n </mat-label>\n <input\n matInput\n [(ngModel)]=\"title\"\n name=\"title\"\n [fsFormRequired]=\"isValue()\">\n </mat-form-field>\n <!-- A formula value is read-only beyond its name: what it works\n out is the AI's to change. A formula this viewer cannot\n read has no line, and no row. -->\n @if (formulaLine()) {\n <fs-label-field>\n <fs-label>\n Formula\n </fs-label>\n {{ formulaLine() }}\n <fs-label-message>\n Worked out on the server; it follows the filters of the values it reads.\n </fs-label-message>\n </fs-label-field>\n }\n <!-- A value sits inside a text block's words: no box, no padding. -->\n @if (!isValue()) {\n <div class=\"subheading-2\">\n Padding\n </div>\n <div class=\"geometry-row\">\n <mat-form-field>\n <mat-label>\n Top\n </mat-label>\n <input\n matInput\n fsMaskNumber\n [scale]=\"3\"\n [(ngModel)]=\"paddingTop\"\n name=\"paddingTop\"\n [fsFormMin]=\"0\">\n <div matTextSuffix>\n in\n </div>\n </mat-form-field>\n <mat-form-field>\n <mat-label>\n Right\n </mat-label>\n <input\n matInput\n fsMaskNumber\n [scale]=\"3\"\n [(ngModel)]=\"paddingRight\"\n name=\"paddingRight\"\n [fsFormMin]=\"0\">\n <div matTextSuffix>\n in\n </div>\n </mat-form-field>\n <mat-form-field>\n <mat-label>\n Bottom\n </mat-label>\n <input\n matInput\n fsMaskNumber\n [scale]=\"3\"\n [(ngModel)]=\"paddingBottom\"\n name=\"paddingBottom\"\n [fsFormMin]=\"0\">\n <div matTextSuffix>\n in\n </div>\n </mat-form-field>\n <mat-form-field>\n <mat-label>\n Left\n </mat-label>\n <input\n matInput\n fsMaskNumber\n [scale]=\"3\"\n [(ngModel)]=\"paddingLeft\"\n name=\"paddingLeft\"\n [fsFormMin]=\"0\">\n <div matTextSuffix>\n in\n </div>\n </mat-form-field>\n </div>\n }\n <!-- A derived KPI's card: what a rise means, a target and a\n sparkline. The server computes the progress and the points. -->\n @if (kpiCard()) {\n <div class=\"subheading-2\">\n Card\n </div>\n <mat-form-field class=\"full-width\">\n <mat-label>\n Increase is\n </mat-label>\n <mat-select\n [ngModel]=\"increaseIs()\"\n (ngModelChange)=\"increaseIs.set($event)\"\n name=\"increaseIs\">\n @for (option of kpiPolarityOptions; track option.value) {\n <mat-option [value]=\"option.value\">\n {{ option.name }}\n </mat-option>\n }\n </mat-select>\n <mat-hint>\n Colors the change and decides when the target is met.\n </mat-hint>\n </mat-form-field>\n <mat-form-field class=\"full-width\">\n <mat-label>\n Target\n </mat-label>\n <input\n matInput\n fsMaskNumber\n [scale]=\"6\"\n [signed]=\"true\"\n [ngModel]=\"targetValue()\"\n (ngModelChange)=\"targetValue.set($event)\"\n name=\"targetValue\"\n [validate]=\"validateTarget\">\n @if (targetPercent()) {\n <div matTextSuffix>\n %\n </div>\n }\n <mat-hint>\n The value to reach. Leave empty for no target.\n </mat-hint>\n </mat-form-field>\n @if (hasTarget()) {\n <mat-form-field class=\"full-width\">\n <mat-label>\n Target label\n </mat-label>\n <input\n matInput\n [ngModel]=\"targetLabel()\"\n (ngModelChange)=\"targetLabel.set($event)\"\n name=\"targetLabel\">\n <mat-hint>\n Shown before the target, such as Goal. Empty reads Target.\n </mat-hint>\n </mat-form-field>\n }\n <fs-label-field>\n <mat-slide-toggle\n [ngModel]=\"sparkline()\"\n (ngModelChange)=\"sparkline.set($event)\"\n name=\"sparkline\">\n Sparkline\n </mat-slide-toggle>\n <mat-hint>\n A small trend line of the value over its last periods.\n </mat-hint>\n </fs-label-field>\n @if (sparkline()) {\n <mat-form-field class=\"full-width\">\n <mat-label>\n Sparkline period\n </mat-label>\n <mat-select\n [ngModel]=\"sparklineGranularity()\"\n (ngModelChange)=\"sparklineGranularity.set($event)\"\n name=\"sparklineGranularity\">\n @for (option of granularityOptions; track option.value) {\n <mat-option [value]=\"option.value\">\n {{ option.name }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n <mat-form-field class=\"full-width\">\n <mat-label>\n Sparkline periods\n </mat-label>\n <input\n matInput\n fsMaskNumber\n [scale]=\"0\"\n [ngModel]=\"sparklinePeriods()\"\n (ngModelChange)=\"sparklinePeriods.set($event)\"\n name=\"sparklinePeriods\"\n [fsFormRequired]=\"true\"\n [fsFormInteger]=\"true\"\n [fsFormMin]=\"sparklineMinPeriods\"\n [fsFormMax]=\"sparklineMaxPeriods\">\n <mat-hint>\n How many periods the line covers, {{ sparklineMinPeriods }} to {{ sparklineMaxPeriods }}.\n </mat-hint>\n </mat-form-field>\n }\n }\n </div>\n </mat-tab>\n <!-- A formula runs no statement and follows the filters of the values\n it reads, so it has neither a Filters nor an SQL tab. -->\n @if (!isFormula()) {\n <mat-tab\n label=\"Filters\"\n name=\"filters\">\n <div class=\"tab-body\">\n @if (columnsError()) {\n <div class=\"filters-empty error\">\n {{ columnsError() }}\n </div>\n } @else if (rows().length) {\n <!-- Every filterable column. Toggle where its control shows: in\n the report bar, on this component, both, or neither. The\n interface (date range vs value picker) follows the data.\n A value sits inside text and has no component to show a\n control on, so it gets the report bar column only. -->\n <table class=\"filter-table\">\n <thead>\n <tr>\n <th class=\"filter-col-name\">\n Filter\n </th>\n <th class=\"filter-col-type\">\n Type\n </th>\n <th class=\"filter-col-toggle\">\n Report bar\n </th>\n @if (!isValue()) {\n <th class=\"filter-col-toggle\">\n This component\n </th>\n }\n </tr>\n </thead>\n <tbody>\n @for (row of rows(); track row.column) {\n <tr>\n <td class=\"filter-col-name\">\n {{ row.label }}\n </td>\n <td class=\"filter-col-type\">\n {{ typeLabel(row.type) }}\n </td>\n <td class=\"filter-col-toggle\">\n <mat-slide-toggle\n [ngModel]=\"row.report\"\n (ngModelChange)=\"setExposure(row, 'report', $event)\"\n [ngModelOptions]=\"{ standalone: true }\"\n matTooltip=\"Show in the report bar\">\n </mat-slide-toggle>\n </td>\n @if (!isValue()) {\n <td class=\"filter-col-toggle\">\n <mat-slide-toggle\n [ngModel]=\"row.component\"\n (ngModelChange)=\"setExposure(row, 'component', $event)\"\n [ngModelOptions]=\"{ standalone: true }\"\n matTooltip=\"Show on this component\">\n </mat-slide-toggle>\n </td>\n }\n </tr>\n }\n </tbody>\n </table>\n } @else {\n <div class=\"filters-empty\">\n This component has no filterable columns yet \u2014 give it some SQL first.\n </div>\n }\n </div>\n </mat-tab>\n <mat-tab\n label=\"SQL\"\n name=\"sql\">\n <div class=\"tab-body\">\n @if (sqlError()) {\n <div class=\"filters-empty error\">\n {{ sqlError() }}\n </div>\n } @else if (sql()) {\n @if (sqlBaseline()) {\n <!-- A derived component's statement is compiled from its\n document with no viewer state, so it is not byte-for-byte\n what produced the numbers on screen. Said here rather than\n left for the reader to discover. -->\n <div class=\"filters-empty\">\n Compiled from this component's query \u2014 no filters applied, times in {{ sqlTimezone() }}.\n </div>\n }\n <pre class=\"code-block\">{{ sql() }}</pre>\n } @else {\n <div class=\"filters-empty\">\n This component has no SQL yet.\n </div>\n }\n </div>\n </mat-tab>\n }\n <mat-tab\n label=\"Config\"\n name=\"config\">\n <div class=\"tab-body\">\n <pre class=\"code-block\">\n {{ configJson }}\n </pre>\n </div>\n </mat-tab>\n </mat-tab-group>\n </mat-dialog-content>\n <mat-dialog-actions>\n <!-- Save | Delete | Cancel, the standard order. fs-form-dialog-actions\n renders its own Save/Done BEFORE the projected content, which would\n put Delete after Cancel, so `[save]=\"false\"` foots the row here and\n all three buttons are projected in order. Save submits the Settings\n tab; the other tabs persist as you touch them, so they get Done. -->\n <fs-form-dialog-actions [save]=\"false\">\n @if (selectedTab === 'settings') {\n <button\n mat-button\n type=\"submit\"\n color=\"primary\">\n Save\n </button>\n } @else {\n <button\n mat-button\n type=\"button\"\n color=\"primary\"\n [mat-dialog-close]=\"null\">\n Done\n </button>\n }\n <button\n mat-button\n type=\"button\"\n color=\"warn\"\n (click)=\"delete()\">\n Delete\n </button>\n <button\n mat-button\n type=\"button\"\n class=\"cancel-button\"\n [mat-dialog-close]=\"null\">\n Cancel\n </button>\n </fs-form-dialog-actions>\n </mat-dialog-actions>\n </fs-dialog>\n</form>", styles: ["mat-form-field{width:100%}.tab-body{padding-top:16px}.geometry-row{display:flex;gap:8px}.geometry-row mat-form-field{flex:1}.filter-table{border-spacing:0;width:100%;border-collapse:collapse}.filter-table thead th{color:#8f8f8f;font-weight:400;font-size:85%;text-align:left;padding:8px 16px}.filter-table tbody tr{clip-path:xywh(0 3px 100% calc(100% - 6px) round 10px)}.filter-table tbody td{border:none;background-color:#fafafa;padding:8px 16px;vertical-align:middle;text-align:left}.filter-table .filter-col-name{font-weight:600;color:#1f2933}.filter-table .filter-col-type{color:#7b8794;width:120px}.filter-table .filter-col-toggle,.filter-table th.filter-col-toggle{width:130px;text-align:center}.filters-empty{font-size:13px;color:#7b8794;padding:8px 0 4px}.filters-empty.error{color:#e15759}.code-block{margin:0;padding:10px 12px;background:#1f2933;color:#e4e7eb;border-radius:6px;font-family:JetBrains Mono,Consolas,monospace;font-size:12px;line-height:1.5;white-space:pre-wrap;word-break:break-word;max-height:240px;overflow:auto}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i1.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: FsFormModule }, { kind: "directive", type: i2.FsFormDirective, selector: "[fsForm]", inputs: ["wrapperSelector", "messageSelector", "hintSelector", "labelSelector", "autocomplete", "shortcuts", "confirm", "confirmDialog", "confirmDrawer", "confirmBrowser", "dirtySubmitButton", "submit", "successDelay", "errorDelay", "deactivationGuard"], outputs: ["fsForm", "invalid", "valid", "submitted", "reseted", "cleared"], exportAs: ["fsForm"] }, { kind: "directive", type: i2.FsFormRequiredDirective, selector: "[fsFormRequired],[ngModel][required]", inputs: ["fsFormRequired", "required", "fsFormRequiredMessage"] }, { kind: "directive", type: i2.FsFormMinDirective, selector: "[fsFormMin]", inputs: ["fsFormMin", "fsFormMinMessage"] }, { kind: "directive", type: i2.FsFormMaxDirective, selector: "[fsFormMax]", inputs: ["fsFormMax", "fsFormMaxMessage"] }, { kind: "directive", type: i2.FsFormIntegerDirective, selector: "[fsFormInteger]", inputs: ["fsFormInteger", "fsFormIntegerMessage"] }, { kind: "directive", type: i2.FsFormValidateDirective, selector: "[validate]", inputs: ["validate", "validateData", "validateOnSubmit"] }, { kind: "component", type: i2.FsFormDialogActionsComponent, selector: "fs-form-dialog-actions", inputs: ["save", "create", "close", "done", "closeData", "name"] }, { kind: "directive", type: i2.FsFormNoFsValidatorsDirective, selector: "[ngModel]:not([required]):not([fsFormRequired]):not([fsFormCompare]):not([fsFormDateRange]):not([fsFormEmail]):not([fsFormEmails]):not([fsFormFunction]):not([fsFormGreater]):not([fsFormGreaterEqual]):not([fsFormInteger]):not([fsFormLesser]):not([fsFormMax]):not([fsFormMaxLength]):not([fsFormMin]):not([fsFormMinLength]):not([fsFormNumeric]):not([fsFormPattern]):not([fsFormPhone]):not([fsFormUrl]):not([validate])" }, { kind: "directive", type: i2.FsButtonDirective, selector: "[mat-raised-button],[mat-button],[mat-flat-button],[mat-stroked-button]", inputs: ["name", "dirtySubmit"] }, { kind: "ngmodule", type: FsMaskModule }, { kind: "directive", type: i3.FsMaskNumberDirective, selector: "[fsMaskNumber]" }, { kind: "ngmodule", type: FsDialogModule }, { kind: "component", type: i4.FsDialogComponent, selector: "fs-dialog", inputs: ["mobileMode", "mobileButtonPlacement", "mobileWidth", "mode", "buttonLayout"] }, { kind: "ngmodule", type: FsLabelModule }, { kind: "component", type: i5.FsLabelComponent, selector: "fs-label" }, { kind: "component", type: i5.FsLabelFieldComponent, selector: "fs-label-field", inputs: ["appearance", "showOutline", "disabled", "focused", "hoverable", "padless"] }, { kind: "component", type: i5.FsLabelMessageComponent, selector: "fs-label-message" }, { kind: "ngmodule", type: FsTabsModule }, { kind: "directive", type: i6.FsTabsHeaderTabGroupDirective, selector: "mat-tab-group, matTabGroup, [matTabGroup]", inputs: ["orientation", "selected", "selectedData"], outputs: ["selectedChange", "selectedDataChange"], exportAs: ["fsTabsHeaderTabGroup"] }, { kind: "directive", type: i6.FsTabsTabDirective, selector: "mat-tab,matTab", inputs: ["name", "data"], exportAs: ["fsTabsTab"] }, { kind: "ngmodule", type: MatTabsModule }, { kind: "component", type: i7.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass"], exportAs: ["matTab"] }, { kind: "component", type: i7.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }, { kind: "directive", type: MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "directive", type: MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "component", type: MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: MatLabel, selector: "mat-label" }, { kind: "directive", type: MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "component", type: MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "directive", type: MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "component", type: MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "component", type: MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { kind: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
550
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: ComponentSettingsComponent, isStandalone: true, selector: "ng-component", ngImport: i0, template: "<form\n fsForm\n [submit]=\"save\">\n <fs-dialog>\n <h1 mat-dialog-title>\n {{ component.title || (isValue() ? 'Value' : 'Component') }}\n </h1>\n <mat-dialog-content>\n <mat-tab-group [(selected)]=\"selectedTab\">\n <mat-tab\n label=\"Settings\"\n name=\"settings\">\n <div class=\"fs-column tab-body\">\n <mat-form-field>\n <mat-label>\n {{ isValue() ? 'Name' : 'Title' }}\n </mat-label>\n <input\n matInput\n [(ngModel)]=\"title\"\n name=\"title\"\n [fsFormRequired]=\"isValue()\">\n </mat-form-field>\n <!-- A formula value is read-only beyond its name: what it works\n out is the AI's to change. A formula this viewer cannot\n read has no line, and no row. -->\n @if (formulaLine()) {\n <fs-label-field>\n <fs-label>\n Formula\n </fs-label>\n {{ formulaLine() }}\n <fs-label-message>\n Worked out on the server; it follows the filters of the values it reads.\n </fs-label-message>\n </fs-label-field>\n }\n <!-- A value sits inside a text block's words: no box, no padding. -->\n @if (!isValue()) {\n <div class=\"subheading-2\">\n Padding\n </div>\n <div class=\"geometry-row\">\n <mat-form-field>\n <mat-label>\n Top\n </mat-label>\n <input\n matInput\n fsMaskNumber\n [scale]=\"3\"\n [(ngModel)]=\"paddingTop\"\n name=\"paddingTop\"\n [fsFormMin]=\"0\">\n <div matTextSuffix>\n in\n </div>\n </mat-form-field>\n <mat-form-field>\n <mat-label>\n Right\n </mat-label>\n <input\n matInput\n fsMaskNumber\n [scale]=\"3\"\n [(ngModel)]=\"paddingRight\"\n name=\"paddingRight\"\n [fsFormMin]=\"0\">\n <div matTextSuffix>\n in\n </div>\n </mat-form-field>\n <mat-form-field>\n <mat-label>\n Bottom\n </mat-label>\n <input\n matInput\n fsMaskNumber\n [scale]=\"3\"\n [(ngModel)]=\"paddingBottom\"\n name=\"paddingBottom\"\n [fsFormMin]=\"0\">\n <div matTextSuffix>\n in\n </div>\n </mat-form-field>\n <mat-form-field>\n <mat-label>\n Left\n </mat-label>\n <input\n matInput\n fsMaskNumber\n [scale]=\"3\"\n [(ngModel)]=\"paddingLeft\"\n name=\"paddingLeft\"\n [fsFormMin]=\"0\">\n <div matTextSuffix>\n in\n </div>\n </mat-form-field>\n </div>\n }\n <!-- A derived KPI's card: what a rise means, a target and a\n sparkline. The server computes the progress and the points. -->\n @if (kpiCard()) {\n <div class=\"subheading-2\">\n Card\n </div>\n <mat-form-field class=\"full-width\">\n <mat-label>\n Increase is\n </mat-label>\n <mat-select\n [ngModel]=\"increaseIs()\"\n (ngModelChange)=\"increaseIs.set($event)\"\n name=\"increaseIs\">\n @for (option of kpiPolarityOptions; track option.value) {\n <mat-option [value]=\"option.value\">\n {{ option.name }}\n </mat-option>\n }\n </mat-select>\n <mat-hint>\n Colors the change and decides when the target is met.\n </mat-hint>\n </mat-form-field>\n <mat-form-field class=\"full-width\">\n <mat-label>\n Target\n </mat-label>\n <input\n matInput\n fsMaskNumber\n [scale]=\"6\"\n [signed]=\"true\"\n [ngModel]=\"targetValue()\"\n (ngModelChange)=\"targetValue.set($event)\"\n name=\"targetValue\"\n [validate]=\"validateTarget\">\n @if (targetPercent()) {\n <div matTextSuffix>\n %\n </div>\n }\n <mat-hint>\n The value to reach. Leave empty for no target.\n </mat-hint>\n </mat-form-field>\n @if (hasTarget()) {\n <mat-form-field class=\"full-width\">\n <mat-label>\n Target label\n </mat-label>\n <input\n matInput\n [ngModel]=\"targetLabel()\"\n (ngModelChange)=\"targetLabel.set($event)\"\n name=\"targetLabel\">\n <mat-hint>\n Shown before the target, such as Goal. Empty reads Target.\n </mat-hint>\n </mat-form-field>\n }\n <fs-label-field>\n <mat-slide-toggle\n [ngModel]=\"sparkline()\"\n (ngModelChange)=\"sparkline.set($event)\"\n name=\"sparkline\">\n Sparkline\n </mat-slide-toggle>\n <mat-hint>\n A small trend line of the value over its last periods.\n </mat-hint>\n </fs-label-field>\n @if (sparkline()) {\n <mat-form-field class=\"full-width\">\n <mat-label>\n Sparkline period\n </mat-label>\n <mat-select\n [ngModel]=\"sparklineGranularity()\"\n (ngModelChange)=\"sparklineGranularity.set($event)\"\n name=\"sparklineGranularity\">\n @for (option of granularityOptions; track option.value) {\n <mat-option [value]=\"option.value\">\n {{ option.name }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n <mat-form-field class=\"full-width\">\n <mat-label>\n Sparkline periods\n </mat-label>\n <input\n matInput\n fsMaskNumber\n [scale]=\"0\"\n [ngModel]=\"sparklinePeriods()\"\n (ngModelChange)=\"sparklinePeriods.set($event)\"\n name=\"sparklinePeriods\"\n [fsFormRequired]=\"true\"\n [fsFormInteger]=\"true\"\n [fsFormMin]=\"sparklineMinPeriods\"\n [fsFormMax]=\"sparklineMaxPeriods\">\n <mat-hint>\n How many periods the line covers, {{ sparklineMinPeriods }} to {{ sparklineMaxPeriods }}.\n </mat-hint>\n </mat-form-field>\n }\n }\n </div>\n </mat-tab>\n <!-- A formula runs no statement and follows the filters of the values\n it reads, so it has neither a Filters nor an SQL tab. -->\n @if (!isFormula()) {\n <mat-tab\n label=\"Filters\"\n name=\"filters\">\n <div class=\"tab-body\">\n @if (columnsError()) {\n <div class=\"filters-empty error\">\n {{ columnsError() }}\n </div>\n } @else if (rows().length) {\n <!-- Every filterable column. Pick where its control shows: in\n the report bar (every page, or this page only), on this\n component, both, or neither. The interface follows the\n data; a numeric column can be values or a number range.\n A value sits inside text and has no component to show a\n control on, so it gets the report bar column only. -->\n <table class=\"filter-table\">\n <thead>\n <tr>\n <th class=\"filter-col-name\">\n Filter\n </th>\n <th class=\"filter-col-type\">\n Type\n </th>\n <th class=\"filter-col-select\">\n Report bar\n </th>\n @if (!isValue()) {\n <th class=\"filter-col-toggle\">\n This component\n </th>\n }\n </tr>\n </thead>\n <tbody>\n @for (row of rows(); track row.column) {\n <tr>\n <td class=\"filter-col-name\">\n {{ row.label }}\n </td>\n <td class=\"filter-col-type\">\n @if (row.typeSelect.show) {\n <mat-form-field\n [subscriptSizing]=\"'dynamic'\"\n [matTooltip]=\"row.typeSelect.tooltip\">\n <mat-select\n [panelWidth]=\"null\"\n [ngModel]=\"row.type\"\n (ngModelChange)=\"setType(row, $event)\"\n [ngModelOptions]=\"{ standalone: true }\"\n [disabled]=\"row.typeSelect.disabled\"\n aria-label=\"Type\">\n @for (option of typeOptions; track option.value) {\n <mat-option [value]=\"option.value\">\n {{ option.name }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n } @else {\n {{ typeLabel(row.type) }}\n }\n </td>\n <td class=\"filter-col-select\">\n <mat-form-field [subscriptSizing]=\"'dynamic'\">\n <mat-select\n [panelWidth]=\"null\"\n [ngModel]=\"row.placement\"\n (ngModelChange)=\"setPlacement(row, $event)\"\n [ngModelOptions]=\"{ standalone: true }\"\n aria-label=\"Report bar\">\n @for (option of row.placementOptions; track option.value) {\n <mat-option [value]=\"option.value\">\n {{ option.name }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n </td>\n @if (!isValue()) {\n <td class=\"filter-col-toggle\">\n <mat-slide-toggle\n [ngModel]=\"row.component\"\n (ngModelChange)=\"setComponent(row, $event)\"\n [ngModelOptions]=\"{ standalone: true }\"\n [disabled]=\"row.componentToggle.disabled\"\n [matTooltip]=\"row.componentToggle.tooltip\">\n </mat-slide-toggle>\n </td>\n }\n </tr>\n }\n </tbody>\n </table>\n } @else {\n <div class=\"filters-empty\">\n This component has no filterable columns yet \u2014 give it some SQL first.\n </div>\n }\n </div>\n </mat-tab>\n <mat-tab\n label=\"SQL\"\n name=\"sql\">\n <div class=\"tab-body\">\n @if (sqlError()) {\n <div class=\"filters-empty error\">\n {{ sqlError() }}\n </div>\n } @else if (sql()) {\n @if (sqlBaseline()) {\n <!-- A derived component's statement is compiled from its\n document with no viewer state, so it is not byte-for-byte\n what produced the numbers on screen. Said here rather than\n left for the reader to discover. -->\n <div class=\"filters-empty\">\n Compiled from this component's query \u2014 no filters applied, times in {{ sqlTimezone() }}.\n </div>\n }\n <pre class=\"code-block\">{{ sql() }}</pre>\n } @else {\n <div class=\"filters-empty\">\n This component has no SQL yet.\n </div>\n }\n </div>\n </mat-tab>\n }\n <mat-tab\n label=\"Config\"\n name=\"config\">\n <div class=\"tab-body\">\n <pre class=\"code-block\">\n {{ configJson }}\n </pre>\n </div>\n </mat-tab>\n </mat-tab-group>\n </mat-dialog-content>\n <mat-dialog-actions>\n <!-- Save | Delete | Cancel, the standard order. fs-form-dialog-actions\n renders its own Save/Done BEFORE the projected content, which would\n put Delete after Cancel, so `[save]=\"false\"` foots the row here and\n all three buttons are projected in order. Save submits the Settings\n tab; the other tabs persist as you touch them, so they get Done. -->\n <fs-form-dialog-actions [save]=\"false\">\n @if (selectedTab === 'settings') {\n <button\n mat-button\n type=\"submit\"\n color=\"primary\">\n Save\n </button>\n } @else {\n <button\n mat-button\n type=\"button\"\n color=\"primary\"\n [mat-dialog-close]=\"null\">\n Done\n </button>\n }\n <button\n mat-button\n type=\"button\"\n color=\"warn\"\n (click)=\"delete()\">\n Delete\n </button>\n <button\n mat-button\n type=\"button\"\n class=\"cancel-button\"\n [mat-dialog-close]=\"null\">\n Cancel\n </button>\n </fs-form-dialog-actions>\n </mat-dialog-actions>\n </fs-dialog>\n</form>", styles: ["mat-form-field{width:100%}.tab-body{padding-top:16px}.geometry-row{display:flex;gap:8px}.geometry-row mat-form-field{flex:1}.filter-table{border-spacing:0;width:100%;border-collapse:collapse}.filter-table thead th{color:#8f8f8f;font-weight:400;font-size:85%;text-align:left;padding:8px 16px}.filter-table tbody tr{clip-path:xywh(0 3px 100% calc(100% - 6px) round 10px)}.filter-table tbody td{border:none;background-color:#fafafa;padding:8px 16px;vertical-align:middle;text-align:left}.filter-table .filter-col-name{font-weight:600;color:#1f2933}.filter-table .filter-col-type{color:#7b8794;width:150px}.filter-table .filter-col-select{width:160px}.filter-table td.filter-col-type,.filter-table td.filter-col-select{padding-left:8px;padding-right:8px}.filter-table td.filter-col-type mat-form-field,.filter-table td.filter-col-select mat-form-field{width:100%;--mat-form-field-container-height: 36px;--mat-form-field-container-vertical-padding: 6px}.filter-table td.filter-col-type ::ng-deep .mat-mdc-form-field-infix,.filter-table td.filter-col-select ::ng-deep .mat-mdc-form-field-infix{width:auto}.filter-table td.filter-col-type ::ng-deep .mat-mdc-form-field-subscript-wrapper,.filter-table td.filter-col-select ::ng-deep .mat-mdc-form-field-subscript-wrapper{display:none}.filter-table .filter-col-toggle,.filter-table th.filter-col-toggle{width:110px;text-align:center}.filters-empty{font-size:13px;color:#7b8794;padding:8px 0 4px}.filters-empty.error{color:#e15759}.code-block{margin:0;padding:10px 12px;background:#1f2933;color:#e4e7eb;border-radius:6px;font-family:JetBrains Mono,Consolas,monospace;font-size:12px;line-height:1.5;white-space:pre-wrap;word-break:break-word;max-height:240px;overflow:auto}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i1.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: FsFormModule }, { kind: "directive", type: i2.FsFormDirective, selector: "[fsForm]", inputs: ["wrapperSelector", "messageSelector", "hintSelector", "labelSelector", "autocomplete", "shortcuts", "confirm", "confirmDialog", "confirmDrawer", "confirmBrowser", "dirtySubmitButton", "submit", "successDelay", "errorDelay", "deactivationGuard"], outputs: ["fsForm", "invalid", "valid", "submitted", "reseted", "cleared"], exportAs: ["fsForm"] }, { kind: "directive", type: i2.FsFormRequiredDirective, selector: "[fsFormRequired],[ngModel][required]", inputs: ["fsFormRequired", "required", "fsFormRequiredMessage"] }, { kind: "directive", type: i2.FsFormMinDirective, selector: "[fsFormMin]", inputs: ["fsFormMin", "fsFormMinMessage"] }, { kind: "directive", type: i2.FsFormMaxDirective, selector: "[fsFormMax]", inputs: ["fsFormMax", "fsFormMaxMessage"] }, { kind: "directive", type: i2.FsFormIntegerDirective, selector: "[fsFormInteger]", inputs: ["fsFormInteger", "fsFormIntegerMessage"] }, { kind: "directive", type: i2.FsFormValidateDirective, selector: "[validate]", inputs: ["validate", "validateData", "validateOnSubmit"] }, { kind: "component", type: i2.FsFormDialogActionsComponent, selector: "fs-form-dialog-actions", inputs: ["save", "create", "close", "done", "closeData", "name"] }, { kind: "directive", type: i2.FsFormNoFsValidatorsDirective, selector: "[ngModel]:not([required]):not([fsFormRequired]):not([fsFormCompare]):not([fsFormDateRange]):not([fsFormEmail]):not([fsFormEmails]):not([fsFormFunction]):not([fsFormGreater]):not([fsFormGreaterEqual]):not([fsFormInteger]):not([fsFormLesser]):not([fsFormMax]):not([fsFormMaxLength]):not([fsFormMin]):not([fsFormMinLength]):not([fsFormNumeric]):not([fsFormPattern]):not([fsFormPhone]):not([fsFormUrl]):not([validate])" }, { kind: "directive", type: i2.FsButtonDirective, selector: "[mat-raised-button],[mat-button],[mat-flat-button],[mat-stroked-button]", inputs: ["name", "dirtySubmit"] }, { kind: "ngmodule", type: FsMaskModule }, { kind: "directive", type: i3.FsMaskNumberDirective, selector: "[fsMaskNumber]" }, { kind: "ngmodule", type: FsDialogModule }, { kind: "component", type: i4.FsDialogComponent, selector: "fs-dialog", inputs: ["mobileMode", "mobileButtonPlacement", "mobileWidth", "mode", "buttonLayout"] }, { kind: "ngmodule", type: FsLabelModule }, { kind: "component", type: i5.FsLabelComponent, selector: "fs-label" }, { kind: "component", type: i5.FsLabelFieldComponent, selector: "fs-label-field", inputs: ["appearance", "showOutline", "disabled", "focused", "hoverable", "padless"] }, { kind: "component", type: i5.FsLabelMessageComponent, selector: "fs-label-message" }, { kind: "ngmodule", type: FsTabsModule }, { kind: "directive", type: i6.FsTabsHeaderTabGroupDirective, selector: "mat-tab-group, matTabGroup, [matTabGroup]", inputs: ["orientation", "selected", "selectedData"], outputs: ["selectedChange", "selectedDataChange"], exportAs: ["fsTabsHeaderTabGroup"] }, { kind: "directive", type: i6.FsTabsTabDirective, selector: "mat-tab,matTab", inputs: ["name", "data"], exportAs: ["fsTabsTab"] }, { kind: "ngmodule", type: MatTabsModule }, { kind: "component", type: i7.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass"], exportAs: ["matTab"] }, { kind: "component", type: i7.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }, { kind: "directive", type: MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "directive", type: MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "component", type: MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: MatLabel, selector: "mat-label" }, { kind: "directive", type: MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "component", type: MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "directive", type: MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "component", type: MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "component", type: MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { kind: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
496
551
  }
497
552
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ComponentSettingsComponent, decorators: [{
498
553
  type: Component,
@@ -518,6 +573,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
518
573
  MatSelect,
519
574
  MatSlideToggle,
520
575
  MatTooltip,
521
- ], template: "<form\n fsForm\n [submit]=\"save\">\n <fs-dialog>\n <h1 mat-dialog-title>\n {{ component.title || (isValue() ? 'Value' : 'Component') }}\n </h1>\n <mat-dialog-content>\n <mat-tab-group [(selected)]=\"selectedTab\">\n <mat-tab\n label=\"Settings\"\n name=\"settings\">\n <div class=\"fs-column tab-body\">\n <mat-form-field>\n <mat-label>\n {{ isValue() ? 'Name' : 'Title' }}\n </mat-label>\n <input\n matInput\n [(ngModel)]=\"title\"\n name=\"title\"\n [fsFormRequired]=\"isValue()\">\n </mat-form-field>\n <!-- A formula value is read-only beyond its name: what it works\n out is the AI's to change. A formula this viewer cannot\n read has no line, and no row. -->\n @if (formulaLine()) {\n <fs-label-field>\n <fs-label>\n Formula\n </fs-label>\n {{ formulaLine() }}\n <fs-label-message>\n Worked out on the server; it follows the filters of the values it reads.\n </fs-label-message>\n </fs-label-field>\n }\n <!-- A value sits inside a text block's words: no box, no padding. -->\n @if (!isValue()) {\n <div class=\"subheading-2\">\n Padding\n </div>\n <div class=\"geometry-row\">\n <mat-form-field>\n <mat-label>\n Top\n </mat-label>\n <input\n matInput\n fsMaskNumber\n [scale]=\"3\"\n [(ngModel)]=\"paddingTop\"\n name=\"paddingTop\"\n [fsFormMin]=\"0\">\n <div matTextSuffix>\n in\n </div>\n </mat-form-field>\n <mat-form-field>\n <mat-label>\n Right\n </mat-label>\n <input\n matInput\n fsMaskNumber\n [scale]=\"3\"\n [(ngModel)]=\"paddingRight\"\n name=\"paddingRight\"\n [fsFormMin]=\"0\">\n <div matTextSuffix>\n in\n </div>\n </mat-form-field>\n <mat-form-field>\n <mat-label>\n Bottom\n </mat-label>\n <input\n matInput\n fsMaskNumber\n [scale]=\"3\"\n [(ngModel)]=\"paddingBottom\"\n name=\"paddingBottom\"\n [fsFormMin]=\"0\">\n <div matTextSuffix>\n in\n </div>\n </mat-form-field>\n <mat-form-field>\n <mat-label>\n Left\n </mat-label>\n <input\n matInput\n fsMaskNumber\n [scale]=\"3\"\n [(ngModel)]=\"paddingLeft\"\n name=\"paddingLeft\"\n [fsFormMin]=\"0\">\n <div matTextSuffix>\n in\n </div>\n </mat-form-field>\n </div>\n }\n <!-- A derived KPI's card: what a rise means, a target and a\n sparkline. The server computes the progress and the points. -->\n @if (kpiCard()) {\n <div class=\"subheading-2\">\n Card\n </div>\n <mat-form-field class=\"full-width\">\n <mat-label>\n Increase is\n </mat-label>\n <mat-select\n [ngModel]=\"increaseIs()\"\n (ngModelChange)=\"increaseIs.set($event)\"\n name=\"increaseIs\">\n @for (option of kpiPolarityOptions; track option.value) {\n <mat-option [value]=\"option.value\">\n {{ option.name }}\n </mat-option>\n }\n </mat-select>\n <mat-hint>\n Colors the change and decides when the target is met.\n </mat-hint>\n </mat-form-field>\n <mat-form-field class=\"full-width\">\n <mat-label>\n Target\n </mat-label>\n <input\n matInput\n fsMaskNumber\n [scale]=\"6\"\n [signed]=\"true\"\n [ngModel]=\"targetValue()\"\n (ngModelChange)=\"targetValue.set($event)\"\n name=\"targetValue\"\n [validate]=\"validateTarget\">\n @if (targetPercent()) {\n <div matTextSuffix>\n %\n </div>\n }\n <mat-hint>\n The value to reach. Leave empty for no target.\n </mat-hint>\n </mat-form-field>\n @if (hasTarget()) {\n <mat-form-field class=\"full-width\">\n <mat-label>\n Target label\n </mat-label>\n <input\n matInput\n [ngModel]=\"targetLabel()\"\n (ngModelChange)=\"targetLabel.set($event)\"\n name=\"targetLabel\">\n <mat-hint>\n Shown before the target, such as Goal. Empty reads Target.\n </mat-hint>\n </mat-form-field>\n }\n <fs-label-field>\n <mat-slide-toggle\n [ngModel]=\"sparkline()\"\n (ngModelChange)=\"sparkline.set($event)\"\n name=\"sparkline\">\n Sparkline\n </mat-slide-toggle>\n <mat-hint>\n A small trend line of the value over its last periods.\n </mat-hint>\n </fs-label-field>\n @if (sparkline()) {\n <mat-form-field class=\"full-width\">\n <mat-label>\n Sparkline period\n </mat-label>\n <mat-select\n [ngModel]=\"sparklineGranularity()\"\n (ngModelChange)=\"sparklineGranularity.set($event)\"\n name=\"sparklineGranularity\">\n @for (option of granularityOptions; track option.value) {\n <mat-option [value]=\"option.value\">\n {{ option.name }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n <mat-form-field class=\"full-width\">\n <mat-label>\n Sparkline periods\n </mat-label>\n <input\n matInput\n fsMaskNumber\n [scale]=\"0\"\n [ngModel]=\"sparklinePeriods()\"\n (ngModelChange)=\"sparklinePeriods.set($event)\"\n name=\"sparklinePeriods\"\n [fsFormRequired]=\"true\"\n [fsFormInteger]=\"true\"\n [fsFormMin]=\"sparklineMinPeriods\"\n [fsFormMax]=\"sparklineMaxPeriods\">\n <mat-hint>\n How many periods the line covers, {{ sparklineMinPeriods }} to {{ sparklineMaxPeriods }}.\n </mat-hint>\n </mat-form-field>\n }\n }\n </div>\n </mat-tab>\n <!-- A formula runs no statement and follows the filters of the values\n it reads, so it has neither a Filters nor an SQL tab. -->\n @if (!isFormula()) {\n <mat-tab\n label=\"Filters\"\n name=\"filters\">\n <div class=\"tab-body\">\n @if (columnsError()) {\n <div class=\"filters-empty error\">\n {{ columnsError() }}\n </div>\n } @else if (rows().length) {\n <!-- Every filterable column. Toggle where its control shows: in\n the report bar, on this component, both, or neither. The\n interface (date range vs value picker) follows the data.\n A value sits inside text and has no component to show a\n control on, so it gets the report bar column only. -->\n <table class=\"filter-table\">\n <thead>\n <tr>\n <th class=\"filter-col-name\">\n Filter\n </th>\n <th class=\"filter-col-type\">\n Type\n </th>\n <th class=\"filter-col-toggle\">\n Report bar\n </th>\n @if (!isValue()) {\n <th class=\"filter-col-toggle\">\n This component\n </th>\n }\n </tr>\n </thead>\n <tbody>\n @for (row of rows(); track row.column) {\n <tr>\n <td class=\"filter-col-name\">\n {{ row.label }}\n </td>\n <td class=\"filter-col-type\">\n {{ typeLabel(row.type) }}\n </td>\n <td class=\"filter-col-toggle\">\n <mat-slide-toggle\n [ngModel]=\"row.report\"\n (ngModelChange)=\"setExposure(row, 'report', $event)\"\n [ngModelOptions]=\"{ standalone: true }\"\n matTooltip=\"Show in the report bar\">\n </mat-slide-toggle>\n </td>\n @if (!isValue()) {\n <td class=\"filter-col-toggle\">\n <mat-slide-toggle\n [ngModel]=\"row.component\"\n (ngModelChange)=\"setExposure(row, 'component', $event)\"\n [ngModelOptions]=\"{ standalone: true }\"\n matTooltip=\"Show on this component\">\n </mat-slide-toggle>\n </td>\n }\n </tr>\n }\n </tbody>\n </table>\n } @else {\n <div class=\"filters-empty\">\n This component has no filterable columns yet \u2014 give it some SQL first.\n </div>\n }\n </div>\n </mat-tab>\n <mat-tab\n label=\"SQL\"\n name=\"sql\">\n <div class=\"tab-body\">\n @if (sqlError()) {\n <div class=\"filters-empty error\">\n {{ sqlError() }}\n </div>\n } @else if (sql()) {\n @if (sqlBaseline()) {\n <!-- A derived component's statement is compiled from its\n document with no viewer state, so it is not byte-for-byte\n what produced the numbers on screen. Said here rather than\n left for the reader to discover. -->\n <div class=\"filters-empty\">\n Compiled from this component's query \u2014 no filters applied, times in {{ sqlTimezone() }}.\n </div>\n }\n <pre class=\"code-block\">{{ sql() }}</pre>\n } @else {\n <div class=\"filters-empty\">\n This component has no SQL yet.\n </div>\n }\n </div>\n </mat-tab>\n }\n <mat-tab\n label=\"Config\"\n name=\"config\">\n <div class=\"tab-body\">\n <pre class=\"code-block\">\n {{ configJson }}\n </pre>\n </div>\n </mat-tab>\n </mat-tab-group>\n </mat-dialog-content>\n <mat-dialog-actions>\n <!-- Save | Delete | Cancel, the standard order. fs-form-dialog-actions\n renders its own Save/Done BEFORE the projected content, which would\n put Delete after Cancel, so `[save]=\"false\"` foots the row here and\n all three buttons are projected in order. Save submits the Settings\n tab; the other tabs persist as you touch them, so they get Done. -->\n <fs-form-dialog-actions [save]=\"false\">\n @if (selectedTab === 'settings') {\n <button\n mat-button\n type=\"submit\"\n color=\"primary\">\n Save\n </button>\n } @else {\n <button\n mat-button\n type=\"button\"\n color=\"primary\"\n [mat-dialog-close]=\"null\">\n Done\n </button>\n }\n <button\n mat-button\n type=\"button\"\n color=\"warn\"\n (click)=\"delete()\">\n Delete\n </button>\n <button\n mat-button\n type=\"button\"\n class=\"cancel-button\"\n [mat-dialog-close]=\"null\">\n Cancel\n </button>\n </fs-form-dialog-actions>\n </mat-dialog-actions>\n </fs-dialog>\n</form>", styles: ["mat-form-field{width:100%}.tab-body{padding-top:16px}.geometry-row{display:flex;gap:8px}.geometry-row mat-form-field{flex:1}.filter-table{border-spacing:0;width:100%;border-collapse:collapse}.filter-table thead th{color:#8f8f8f;font-weight:400;font-size:85%;text-align:left;padding:8px 16px}.filter-table tbody tr{clip-path:xywh(0 3px 100% calc(100% - 6px) round 10px)}.filter-table tbody td{border:none;background-color:#fafafa;padding:8px 16px;vertical-align:middle;text-align:left}.filter-table .filter-col-name{font-weight:600;color:#1f2933}.filter-table .filter-col-type{color:#7b8794;width:120px}.filter-table .filter-col-toggle,.filter-table th.filter-col-toggle{width:130px;text-align:center}.filters-empty{font-size:13px;color:#7b8794;padding:8px 0 4px}.filters-empty.error{color:#e15759}.code-block{margin:0;padding:10px 12px;background:#1f2933;color:#e4e7eb;border-radius:6px;font-family:JetBrains Mono,Consolas,monospace;font-size:12px;line-height:1.5;white-space:pre-wrap;word-break:break-word;max-height:240px;overflow:auto}\n"] }]
576
+ ], template: "<form\n fsForm\n [submit]=\"save\">\n <fs-dialog>\n <h1 mat-dialog-title>\n {{ component.title || (isValue() ? 'Value' : 'Component') }}\n </h1>\n <mat-dialog-content>\n <mat-tab-group [(selected)]=\"selectedTab\">\n <mat-tab\n label=\"Settings\"\n name=\"settings\">\n <div class=\"fs-column tab-body\">\n <mat-form-field>\n <mat-label>\n {{ isValue() ? 'Name' : 'Title' }}\n </mat-label>\n <input\n matInput\n [(ngModel)]=\"title\"\n name=\"title\"\n [fsFormRequired]=\"isValue()\">\n </mat-form-field>\n <!-- A formula value is read-only beyond its name: what it works\n out is the AI's to change. A formula this viewer cannot\n read has no line, and no row. -->\n @if (formulaLine()) {\n <fs-label-field>\n <fs-label>\n Formula\n </fs-label>\n {{ formulaLine() }}\n <fs-label-message>\n Worked out on the server; it follows the filters of the values it reads.\n </fs-label-message>\n </fs-label-field>\n }\n <!-- A value sits inside a text block's words: no box, no padding. -->\n @if (!isValue()) {\n <div class=\"subheading-2\">\n Padding\n </div>\n <div class=\"geometry-row\">\n <mat-form-field>\n <mat-label>\n Top\n </mat-label>\n <input\n matInput\n fsMaskNumber\n [scale]=\"3\"\n [(ngModel)]=\"paddingTop\"\n name=\"paddingTop\"\n [fsFormMin]=\"0\">\n <div matTextSuffix>\n in\n </div>\n </mat-form-field>\n <mat-form-field>\n <mat-label>\n Right\n </mat-label>\n <input\n matInput\n fsMaskNumber\n [scale]=\"3\"\n [(ngModel)]=\"paddingRight\"\n name=\"paddingRight\"\n [fsFormMin]=\"0\">\n <div matTextSuffix>\n in\n </div>\n </mat-form-field>\n <mat-form-field>\n <mat-label>\n Bottom\n </mat-label>\n <input\n matInput\n fsMaskNumber\n [scale]=\"3\"\n [(ngModel)]=\"paddingBottom\"\n name=\"paddingBottom\"\n [fsFormMin]=\"0\">\n <div matTextSuffix>\n in\n </div>\n </mat-form-field>\n <mat-form-field>\n <mat-label>\n Left\n </mat-label>\n <input\n matInput\n fsMaskNumber\n [scale]=\"3\"\n [(ngModel)]=\"paddingLeft\"\n name=\"paddingLeft\"\n [fsFormMin]=\"0\">\n <div matTextSuffix>\n in\n </div>\n </mat-form-field>\n </div>\n }\n <!-- A derived KPI's card: what a rise means, a target and a\n sparkline. The server computes the progress and the points. -->\n @if (kpiCard()) {\n <div class=\"subheading-2\">\n Card\n </div>\n <mat-form-field class=\"full-width\">\n <mat-label>\n Increase is\n </mat-label>\n <mat-select\n [ngModel]=\"increaseIs()\"\n (ngModelChange)=\"increaseIs.set($event)\"\n name=\"increaseIs\">\n @for (option of kpiPolarityOptions; track option.value) {\n <mat-option [value]=\"option.value\">\n {{ option.name }}\n </mat-option>\n }\n </mat-select>\n <mat-hint>\n Colors the change and decides when the target is met.\n </mat-hint>\n </mat-form-field>\n <mat-form-field class=\"full-width\">\n <mat-label>\n Target\n </mat-label>\n <input\n matInput\n fsMaskNumber\n [scale]=\"6\"\n [signed]=\"true\"\n [ngModel]=\"targetValue()\"\n (ngModelChange)=\"targetValue.set($event)\"\n name=\"targetValue\"\n [validate]=\"validateTarget\">\n @if (targetPercent()) {\n <div matTextSuffix>\n %\n </div>\n }\n <mat-hint>\n The value to reach. Leave empty for no target.\n </mat-hint>\n </mat-form-field>\n @if (hasTarget()) {\n <mat-form-field class=\"full-width\">\n <mat-label>\n Target label\n </mat-label>\n <input\n matInput\n [ngModel]=\"targetLabel()\"\n (ngModelChange)=\"targetLabel.set($event)\"\n name=\"targetLabel\">\n <mat-hint>\n Shown before the target, such as Goal. Empty reads Target.\n </mat-hint>\n </mat-form-field>\n }\n <fs-label-field>\n <mat-slide-toggle\n [ngModel]=\"sparkline()\"\n (ngModelChange)=\"sparkline.set($event)\"\n name=\"sparkline\">\n Sparkline\n </mat-slide-toggle>\n <mat-hint>\n A small trend line of the value over its last periods.\n </mat-hint>\n </fs-label-field>\n @if (sparkline()) {\n <mat-form-field class=\"full-width\">\n <mat-label>\n Sparkline period\n </mat-label>\n <mat-select\n [ngModel]=\"sparklineGranularity()\"\n (ngModelChange)=\"sparklineGranularity.set($event)\"\n name=\"sparklineGranularity\">\n @for (option of granularityOptions; track option.value) {\n <mat-option [value]=\"option.value\">\n {{ option.name }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n <mat-form-field class=\"full-width\">\n <mat-label>\n Sparkline periods\n </mat-label>\n <input\n matInput\n fsMaskNumber\n [scale]=\"0\"\n [ngModel]=\"sparklinePeriods()\"\n (ngModelChange)=\"sparklinePeriods.set($event)\"\n name=\"sparklinePeriods\"\n [fsFormRequired]=\"true\"\n [fsFormInteger]=\"true\"\n [fsFormMin]=\"sparklineMinPeriods\"\n [fsFormMax]=\"sparklineMaxPeriods\">\n <mat-hint>\n How many periods the line covers, {{ sparklineMinPeriods }} to {{ sparklineMaxPeriods }}.\n </mat-hint>\n </mat-form-field>\n }\n }\n </div>\n </mat-tab>\n <!-- A formula runs no statement and follows the filters of the values\n it reads, so it has neither a Filters nor an SQL tab. -->\n @if (!isFormula()) {\n <mat-tab\n label=\"Filters\"\n name=\"filters\">\n <div class=\"tab-body\">\n @if (columnsError()) {\n <div class=\"filters-empty error\">\n {{ columnsError() }}\n </div>\n } @else if (rows().length) {\n <!-- Every filterable column. Pick where its control shows: in\n the report bar (every page, or this page only), on this\n component, both, or neither. The interface follows the\n data; a numeric column can be values or a number range.\n A value sits inside text and has no component to show a\n control on, so it gets the report bar column only. -->\n <table class=\"filter-table\">\n <thead>\n <tr>\n <th class=\"filter-col-name\">\n Filter\n </th>\n <th class=\"filter-col-type\">\n Type\n </th>\n <th class=\"filter-col-select\">\n Report bar\n </th>\n @if (!isValue()) {\n <th class=\"filter-col-toggle\">\n This component\n </th>\n }\n </tr>\n </thead>\n <tbody>\n @for (row of rows(); track row.column) {\n <tr>\n <td class=\"filter-col-name\">\n {{ row.label }}\n </td>\n <td class=\"filter-col-type\">\n @if (row.typeSelect.show) {\n <mat-form-field\n [subscriptSizing]=\"'dynamic'\"\n [matTooltip]=\"row.typeSelect.tooltip\">\n <mat-select\n [panelWidth]=\"null\"\n [ngModel]=\"row.type\"\n (ngModelChange)=\"setType(row, $event)\"\n [ngModelOptions]=\"{ standalone: true }\"\n [disabled]=\"row.typeSelect.disabled\"\n aria-label=\"Type\">\n @for (option of typeOptions; track option.value) {\n <mat-option [value]=\"option.value\">\n {{ option.name }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n } @else {\n {{ typeLabel(row.type) }}\n }\n </td>\n <td class=\"filter-col-select\">\n <mat-form-field [subscriptSizing]=\"'dynamic'\">\n <mat-select\n [panelWidth]=\"null\"\n [ngModel]=\"row.placement\"\n (ngModelChange)=\"setPlacement(row, $event)\"\n [ngModelOptions]=\"{ standalone: true }\"\n aria-label=\"Report bar\">\n @for (option of row.placementOptions; track option.value) {\n <mat-option [value]=\"option.value\">\n {{ option.name }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n </td>\n @if (!isValue()) {\n <td class=\"filter-col-toggle\">\n <mat-slide-toggle\n [ngModel]=\"row.component\"\n (ngModelChange)=\"setComponent(row, $event)\"\n [ngModelOptions]=\"{ standalone: true }\"\n [disabled]=\"row.componentToggle.disabled\"\n [matTooltip]=\"row.componentToggle.tooltip\">\n </mat-slide-toggle>\n </td>\n }\n </tr>\n }\n </tbody>\n </table>\n } @else {\n <div class=\"filters-empty\">\n This component has no filterable columns yet \u2014 give it some SQL first.\n </div>\n }\n </div>\n </mat-tab>\n <mat-tab\n label=\"SQL\"\n name=\"sql\">\n <div class=\"tab-body\">\n @if (sqlError()) {\n <div class=\"filters-empty error\">\n {{ sqlError() }}\n </div>\n } @else if (sql()) {\n @if (sqlBaseline()) {\n <!-- A derived component's statement is compiled from its\n document with no viewer state, so it is not byte-for-byte\n what produced the numbers on screen. Said here rather than\n left for the reader to discover. -->\n <div class=\"filters-empty\">\n Compiled from this component's query \u2014 no filters applied, times in {{ sqlTimezone() }}.\n </div>\n }\n <pre class=\"code-block\">{{ sql() }}</pre>\n } @else {\n <div class=\"filters-empty\">\n This component has no SQL yet.\n </div>\n }\n </div>\n </mat-tab>\n }\n <mat-tab\n label=\"Config\"\n name=\"config\">\n <div class=\"tab-body\">\n <pre class=\"code-block\">\n {{ configJson }}\n </pre>\n </div>\n </mat-tab>\n </mat-tab-group>\n </mat-dialog-content>\n <mat-dialog-actions>\n <!-- Save | Delete | Cancel, the standard order. fs-form-dialog-actions\n renders its own Save/Done BEFORE the projected content, which would\n put Delete after Cancel, so `[save]=\"false\"` foots the row here and\n all three buttons are projected in order. Save submits the Settings\n tab; the other tabs persist as you touch them, so they get Done. -->\n <fs-form-dialog-actions [save]=\"false\">\n @if (selectedTab === 'settings') {\n <button\n mat-button\n type=\"submit\"\n color=\"primary\">\n Save\n </button>\n } @else {\n <button\n mat-button\n type=\"button\"\n color=\"primary\"\n [mat-dialog-close]=\"null\">\n Done\n </button>\n }\n <button\n mat-button\n type=\"button\"\n color=\"warn\"\n (click)=\"delete()\">\n Delete\n </button>\n <button\n mat-button\n type=\"button\"\n class=\"cancel-button\"\n [mat-dialog-close]=\"null\">\n Cancel\n </button>\n </fs-form-dialog-actions>\n </mat-dialog-actions>\n </fs-dialog>\n</form>", styles: ["mat-form-field{width:100%}.tab-body{padding-top:16px}.geometry-row{display:flex;gap:8px}.geometry-row mat-form-field{flex:1}.filter-table{border-spacing:0;width:100%;border-collapse:collapse}.filter-table thead th{color:#8f8f8f;font-weight:400;font-size:85%;text-align:left;padding:8px 16px}.filter-table tbody tr{clip-path:xywh(0 3px 100% calc(100% - 6px) round 10px)}.filter-table tbody td{border:none;background-color:#fafafa;padding:8px 16px;vertical-align:middle;text-align:left}.filter-table .filter-col-name{font-weight:600;color:#1f2933}.filter-table .filter-col-type{color:#7b8794;width:150px}.filter-table .filter-col-select{width:160px}.filter-table td.filter-col-type,.filter-table td.filter-col-select{padding-left:8px;padding-right:8px}.filter-table td.filter-col-type mat-form-field,.filter-table td.filter-col-select mat-form-field{width:100%;--mat-form-field-container-height: 36px;--mat-form-field-container-vertical-padding: 6px}.filter-table td.filter-col-type ::ng-deep .mat-mdc-form-field-infix,.filter-table td.filter-col-select ::ng-deep .mat-mdc-form-field-infix{width:auto}.filter-table td.filter-col-type ::ng-deep .mat-mdc-form-field-subscript-wrapper,.filter-table td.filter-col-select ::ng-deep .mat-mdc-form-field-subscript-wrapper{display:none}.filter-table .filter-col-toggle,.filter-table th.filter-col-toggle{width:110px;text-align:center}.filters-empty{font-size:13px;color:#7b8794;padding:8px 0 4px}.filters-empty.error{color:#e15759}.code-block{margin:0;padding:10px 12px;background:#1f2933;color:#e4e7eb;border-radius:6px;font-family:JetBrains Mono,Consolas,monospace;font-size:12px;line-height:1.5;white-space:pre-wrap;word-break:break-word;max-height:240px;overflow:auto}\n"] }]
522
577
  }] });
523
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29tcG9uZW50LXNldHRpbmdzLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3NyYy9hcHAvcmVwb3J0cy9kaWFsb2dzL2NvbXBvbmVudC1zZXR0aW5ncy9jb21wb25lbnQtc2V0dGluZ3MuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2FwcC9yZXBvcnRzL2RpYWxvZ3MvY29tcG9uZW50LXNldHRpbmdzL2NvbXBvbmVudC1zZXR0aW5ncy5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsdUJBQXVCLEVBQUUsU0FBUyxFQUFFLFVBQVUsRUFBRSxZQUFZLEVBQVUsUUFBUSxFQUFFLE1BQU0sRUFBRSxNQUFNLEdBQy9GLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQ2hFLE9BQU8sRUFBbUIsV0FBVyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFOUQsT0FBTyxFQUFFLGVBQWUsRUFBRSxnQkFBZ0IsRUFBRSxjQUFjLEVBQUUsZ0JBQWdCLEVBQUUsWUFBWSxFQUFFLGNBQWMsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQzdJLE9BQU8sRUFBRSxZQUFZLEVBQUUsT0FBTyxFQUFFLFFBQVEsRUFBRSxTQUFTLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUMxRixPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDckQsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQ25ELE9BQU8sRUFBRSxTQUFTLEVBQUUsU0FBUyxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDaEUsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBQ2hFLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUN2RCxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFFdkQsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQ3BELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUNoRCxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDbEQsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBQ2hELE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUNoRCxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDOUMsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBR2hELE9BQU8sRUFBRSxTQUFTLEVBQUUsR0FBRyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFaEQsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQ3BELE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLHlDQUF5QyxDQUFDO0FBQy9FLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLHNDQUFzQyxDQUFDO0FBQ3pFLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLHVDQUF1QyxDQUFDO0FBQzNFLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUNwRCxPQUFPLEVBQ0wsaUNBQWlDLEVBQ2pDLDZCQUE2QixFQUM3QixlQUFlLEVBQ2YsbUJBQW1CLEdBQ3BCLE1BQU0sZ0JBQWdCLENBQUM7QUFDeEIsT0FBTyxFQUdMLG1CQUFtQixHQVdwQixNQUFNLG1DQUFtQyxDQUFDO0FBQzNDLE9BQU8sRUFBRSx5QkFBeUIsRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUN6RCxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sWUFBWSxDQUFDO0FBQ3hDLE9BQU8sRUFBRSxXQUFXLEVBQUUsZ0JBQWdCLEVBQUUsUUFBUSxFQUFFLE1BQU0sY0FBYyxDQUFDOzs7Ozs7Ozs7QUFxQnZFLGtFQUFrRTtBQUNsRSxNQUFNLDJCQUEyQixHQUFvRDtJQUNuRixFQUFFLEtBQUssRUFBRSxvQkFBb0IsQ0FBQyxJQUFJLEVBQUUsSUFBSSxFQUFFLGdDQUFnQyxFQUFFO0lBQzVFLEVBQUUsS0FBSyxFQUFFLG9CQUFvQixDQUFDLEdBQUcsRUFBRSxJQUFJLEVBQUUsNkJBQTZCLEVBQUU7SUFDeEUsRUFBRSxLQUFLLEVBQUUsb0JBQW9CLENBQUMsT0FBTyxFQUFFLElBQUksRUFBRSxvQkFBb0IsRUFBRTtDQUNwRSxDQUFDO0FBRUYsaURBQWlEO0FBQ2pELE1BQU0seUJBQXlCLEdBQUcsQ0FBQyxDQUFDO0FBQ3BDLE1BQU0seUJBQXlCLEdBQUcsRUFBRSxDQUFDO0FBRXJDLDBFQUEwRTtBQUMxRSw0RUFBNEU7QUFDNUUsMkNBQTJDO0FBQzNDLE1BQU0sc0JBQXNCLEdBQUcsS0FBSyxDQUFDO0FBRXJDLDBFQUEwRTtBQUMxRSxtQkFBbUI7QUFDbkIsTUFBTSxhQUFhLEdBQTREO0lBQzdFLENBQUMsa0JBQWtCLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDO0lBQ3pELENBQUMsa0JBQWtCLENBQUMsYUFBYSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsZUFBZSxDQUFDLFNBQVMsQ0FBQyxFQUFFO0lBQzVFLENBQUMsa0JBQWtCLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDO0lBQ3hELENBQUMsa0JBQWtCLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDO0NBQ3ZELENBQUM7QUFjRiwrQkFBK0I7QUFDL0IsMkVBQTJFO0FBQzNFLHFGQUFxRjtBQUNyRiwwRUFBMEU7QUFDMUUsdUVBQXVFO0FBQ3ZFLCtDQUErQztBQUMvQyw4RUFBOEU7QUFDOUUsd0VBQXdFO0FBQ3hFLDZFQUE2RTtBQUM3RSwwRUFBMEU7QUFDMUUsMkVBQTJFO0FBQzNFLGdFQUFnRTtBQUNoRSwwQ0FBMEM7QUFDMUMsOEVBQThFO0FBQzlFLDZFQUE2RTtBQUM3RSw0RUFBNEU7QUE4QjVFLE1BQU0sT0FBTywwQkFBMEI7SUFFckMsNEVBQTRFO0lBQzVFLDhFQUE4RTtJQUM5RSw4RUFBOEU7SUFDOUUsaUVBQWlFO0lBQ2pELGNBQWMsR0FBRyxJQUFJLFlBQVksRUFBUSxDQUFDO0lBRW5ELFNBQVMsQ0FBa0I7SUFDM0IsTUFBTSxDQUFTO0lBRWYsV0FBVyxHQUFHLFVBQVUsQ0FBQztJQUV6QixLQUFLLEdBQUcsRUFBRSxDQUFDO0lBRWxCLDRFQUE0RTtJQUM1RSw2RUFBNkU7SUFDN0UseUVBQXlFO0lBQ2xFLFVBQVUsR0FBb0IseUJBQXlCLENBQUM7SUFDeEQsWUFBWSxHQUFvQix5QkFBeUIsQ0FBQztJQUMxRCxhQUFhLEdBQW9CLHlCQUF5QixDQUFDO0lBQzNELFdBQVcsR0FBb0IseUJBQXlCLENBQUM7SUFFekQsVUFBVSxHQUFHLEVBQUUsQ0FBQztJQUV2QixnREFBZ0Q7SUFDaEMsa0JBQWtCLEdBQUcsMkJBQTJCLENBQUM7SUFDakQsa0JBQWtCLEdBQUcsbUJBQW1CLENBQUM7SUFDekMsbUJBQW1CLEdBQUcseUJBQXlCLENBQUM7SUFDaEQsbUJBQW1CLEdBQUcseUJBQXlCLENBQUM7SUFDaEQsT0FBTyxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUN4QyxzREFBc0Q7SUFDdEMsT0FBTyxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUN4QyxnRUFBZ0U7SUFDaEQsU0FBUyxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUMxQyx3RUFBd0U7SUFDeEUsYUFBYTtJQUNHLFdBQVcsR0FBRyxRQUFRLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUM1RSxVQUFVLEdBQUcsTUFBTSxDQUF1QixvQkFBb0IsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUNyRiwwRUFBMEU7SUFDMUUsa0VBQWtFO0lBQ2xELFdBQVcsR0FBRyxNQUFNLENBQXlCLElBQUksQ0FBQyxDQUFDO0lBQ25ELFdBQVcsR0FBRyxNQUFNLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDekIsYUFBYSxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUM5QixTQUFTLEdBQUcsUUFBUSxDQUFDLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDLEtBQUssSUFBSSxDQUFDLENBQUM7SUFDdEUsU0FBUyxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUMxQixvQkFBb0IsR0FBRyxNQUFNLENBQW1CLGlDQUFpQyxDQUFDLENBQUM7SUFDbkYsZ0JBQWdCLEdBQUcsTUFBTSxDQUFrQiw2QkFBNkIsQ0FBQyxDQUFDO0lBRTFGLDBCQUEwQjtJQUMxQiw2RUFBNkU7SUFDN0UsdUVBQXVFO0lBQ3ZELEdBQUcsR0FBRyxNQUFNLENBQWdCLElBQUksQ0FBQyxDQUFDO0lBQ2xELDBFQUEwRTtJQUMxRSw0RUFBNEU7SUFDNUUsMkVBQTJFO0lBQzNFLDBCQUEwQjtJQUNWLFdBQVcsR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDNUMsNEVBQTRFO0lBQzVFLDZEQUE2RDtJQUM3QyxXQUFXLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQzVCLFFBQVEsR0FBRyxNQUFNLENBQWdCLElBQUksQ0FBQyxDQUFDO0lBRXZELG9DQUFvQztJQUNwQyw2RUFBNkU7SUFDN0UsNEVBQTRFO0lBQzVFLHNEQUFzRDtJQUN0QyxJQUFJLEdBQUcsTUFBTSxDQUFjLEVBQUUsQ0FBQyxDQUFDO0lBQy9CLFlBQVksR0FBRyxNQUFNLENBQWdCLElBQUksQ0FBQyxDQUFDO0lBRTNELDBDQUEwQztJQUNsQyxrQkFBa0IsR0FBNkIsRUFBRSxDQUFDO0lBQ2xELFFBQVEsR0FBbUIsRUFBRSxDQUFDO0lBQzlCLFdBQVcsR0FBRyxJQUFJLEdBQUcsRUFBNkIsQ0FBQztJQUUxQyxXQUFXLEdBQXFDO1FBQy9ELE1BQU0sRUFBRSxhQUFhO1FBQ3JCLFNBQVMsRUFBRSxZQUFZO1FBQ3ZCLE9BQU8sRUFBRSxhQUFhO0tBQ3ZCLENBQUM7SUFFZSxLQUFLLEdBQW1ELE1BQU0sQ0FBQyxlQUFlLENBQUMsQ0FBQztJQUNoRixVQUFVLEdBQUcsTUFBTSxDQUFvRSxZQUFZLENBQUMsQ0FBQztJQUNyRyxXQUFXLEdBQUcsTUFBTSxDQUFDLFVBQVUsQ0FBQyxDQUFDO0lBQ2pDLFFBQVEsR0FBRyxNQUFNLENBQUMsU0FBUyxDQUFDLENBQUM7SUFDN0IsT0FBTyxHQUFHLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUMzQixXQUFXLEdBQUcsTUFBTSxDQUFDLFVBQVUsQ0FBQyxDQUFDO0lBRTNDLFFBQVE7UUFDYixJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDO1FBQ2hDLElBQUksQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUM7UUFFdEMsSUFBSSxDQUFDLEtBQUssR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssSUFBSSxFQUFFLENBQUM7UUFDeEMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLEtBQUssT0FBTyxDQUFDLENBQUM7UUFDbEQsSUFBSSxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBRXJELE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxFQUFFLE9BQU8sQ0FBQztRQUMvQyxJQUFJLENBQUMsVUFBVSxHQUFHLE9BQU8sRUFBRSxHQUFHLElBQUkseUJBQXlCLENBQUM7UUFDNUQsSUFBSSxDQUFDLFlBQVksR0FBRyxPQUFPLEVBQUUsS0FBSyxJQUFJLHlCQUF5QixDQUFDO1FBQ2hFLElBQUksQ0FBQyxhQUFhLEdBQUcsT0FBTyxFQUFFLE1BQU0sSUFBSSx5QkFBeUIsQ0FBQztRQUNsRSxJQUFJLENBQUMsV0FBVyxHQUFHLE9BQU8sRUFBRSxJQUFJLElBQUkseUJBQXlCLENBQUM7UUFFOUQsSUFBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxJQUFJLEVBQUUsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFFdkUsSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO1FBRXBCLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBRWxELHlFQUF5RTtRQUN6RSx5Q0FBeUM7UUFDekMsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsRUFBRSxDQUFDO1lBQ3RCLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztZQUNwQixJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7UUFDbEIsQ0FBQztJQUNILENBQUM7SUFFRCwyRUFBMkU7SUFDcEUsU0FBUyxDQUFDLElBQXNCO1FBQ3JDLE9BQU8sSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsSUFBSSxJQUFJLENBQUM7SUFDeEMsQ0FBQztJQUVELDZFQUE2RTtJQUM3RSxzRUFBc0U7SUFDdEUsOENBQThDO0lBQzlDLEVBQUU7SUFDRiw0RUFBNEU7SUFDNUUseUVBQXlFO0lBQ3pFLHNFQUFzRTtJQUN0RSw2RUFBNkU7SUFDN0UsMkRBQTJEO0lBQzNELEVBQUU7SUFDRiwyRUFBMkU7SUFDcEUsTUFBTTtRQUNYLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUU7WUFDakMsQ0FBQyxDQUFDO2dCQUNBLEtBQUssRUFBRSxjQUFjO2dCQUNyQixRQUFRLEVBQUUscUJBQXFCLFVBQVUsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssSUFBSSxRQUFRLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLDZFQUE2RSxJQUFJLENBQUMsZUFBZSxFQUFFLEVBQUU7YUFDak07WUFDRCxDQUFDLENBQUM7Z0JBQ0EsS0FBSyxFQUFFLGtCQUFrQjtnQkFDekIsUUFBUSxFQUFFLDBDQUEwQyxVQUFVLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLElBQUksZ0JBQWdCLENBQUMsMkJBQTJCO2FBQ3BJLENBQUM7YUFDRCxJQUFJLENBQ0gsU0FBUyxDQUFDLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRSxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDLENBQUMsRUFDcEYsR0FBRyxDQUFDLEdBQUcsRUFBRTtZQUNQLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDLENBQUMsZUFBZSxDQUFDLENBQUMsQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDO1lBQzlFLElBQUksQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7UUFDM0MsQ0FBQyxDQUFDLEVBQ0Ysa0JBQWtCLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUNyQzthQUNBLFNBQVMsRUFBRSxDQUFDO0lBQ2pCLENBQUM7SUFFRCx3RUFBd0U7SUFDeEUsMkVBQTJFO0lBQ3BFLGNBQWMsR0FBRyxDQUFDLE9BQXdCLEVBQVEsRUFBRTtRQUN6RCxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUUxQyxJQUFJLElBQUksQ0FBQyxhQUFhLEVBQUUsSUFBSSxLQUFLLEtBQUssSUFBSSxJQUFJLEtBQUssR0FBRyxzQkFBc0IsRUFBRSxDQUFDO1lBQzdFLE1BQU0sSUFBSSxLQUFLLENBQUMseUNBQXlDLENBQUMsQ0FBQztRQUM3RCxDQUFDO0lBQ0gsQ0FBQyxDQUFDO0lBRUssSUFBSSxHQUFHLEdBQUcsRUFBRTtRQUNqQixNQUFNLFFBQVEsR0FBc0I7WUFDbEMseUVBQXlFO1lBQ3pFLCtCQUErQjtZQUMvQixLQUFLLEVBQUUsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsS0FBSztZQUN0RCxPQUFPLEVBQUU7Z0JBQ1AsR0FBRyxFQUFFLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQztnQkFDbkMsS0FBSyxFQUFFLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQztnQkFDdkMsTUFBTSxFQUFFLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQztnQkFDekMsSUFBSSxFQUFFLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQzthQUN0QztTQUNGLENBQUM7UUFFRix5RUFBeUU7UUFDekUsdUVBQXVFO1FBQ3ZFLGlDQUFpQztRQUNqQyxNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUM7UUFDNUQsTUFBTSxVQUFVLEdBQUcsQ0FBQyxDQUFDLEdBQUc7ZUFDbkIsQ0FBQyxtQkFBbUIsQ0FBQyxHQUFHLEVBQUUsZUFBZSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBbUIsQ0FBQyxDQUFDLENBQUM7UUFFcEYsT0FBTyxJQUFJLENBQUMsV0FBVyxDQUFDLGVBQWUsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLEVBQUUsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLEVBQUUsRUFBRTtZQUN6RSxLQUFLLEVBQUUsUUFBUSxDQUFDLEtBQUs7WUFDckIsR0FBRyxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLE9BQU8sRUFBRSxRQUFRLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDeEQsR0FBRyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7U0FDM0IsQ0FBQzthQUNDLElBQUksQ0FDSCxHQUFHLENBQUMsQ0FBQyxRQUFtQyxFQUFFLEVBQUU7WUFDMUMsbUVBQW1FO1lBQ25FLGlFQUFpRTtZQUNqRSxtRUFBbUU7WUFDbkUsTUFBTSxLQUFLLEdBQUcsVUFBVSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUM7WUFFL0QsSUFBSSxVQUFVLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztnQkFDekIsSUFBSSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsZ0VBQWdFLENBQUMsQ0FBQztZQUMxRixDQUFDO2lCQUFNLENBQUM7Z0JBQ04sSUFBSSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUMsQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDLGlCQUFpQixDQUFDLENBQUM7WUFDNUUsQ0FBQztZQUVELElBQUksQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLEVBQUUsUUFBUSxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRSxHQUFHLFFBQVEsRUFBRSxHQUFHLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUM7UUFDdEYsQ0FBQyxDQUFDLENBQ0gsQ0FBQztJQUNOLENBQUMsQ0FBQztJQUVGLDRFQUE0RTtJQUM1RSw2RUFBNkU7SUFDN0UsNkVBQTZFO0lBQzdFLHNFQUFzRTtJQUN0RSwwRUFBMEU7SUFDMUUsdUJBQXVCO0lBQ2hCLFdBQVcsQ0FBQyxHQUFjLEVBQUUsTUFBOEIsRUFBRSxFQUFXO1FBQzVFLElBQUksSUFBSSxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUM7WUFDbkIsSUFBSSxNQUFNLEtBQUssUUFBUSxFQUFFLENBQUM7Z0JBQ3hCLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxHQUFHLEVBQUUsRUFBRSxDQUFDLENBQUM7WUFDbEMsQ0FBQztZQUVELE9BQU87UUFDVCxDQUFDO1FBRUQsR0FBRyxDQUFDLE1BQU0sQ0FBQyxHQUFHLEVBQUUsQ0FBQztRQUVqQixNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUMsTUFBTSxDQUFDLFlBQVksS0FBSyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUM7UUFFcEYsSUFBSSxDQUFDLEdBQUcsQ0FBQyxNQUFNLElBQUksQ0FBQyxHQUFHLENBQUMsU0FBUyxFQUFFLENBQUM7WUFDbEMsSUFBSSxRQUFRLEVBQUUsQ0FBQztnQkFDYixJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRSxFQUFFLFFBQVEsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO1lBQ3hFLENBQUM7WUFFRCxPQUFPO1FBQ1QsQ0FBQztRQUVELE1BQU0sS0FBSyxHQUFzQixHQUFHLENBQUMsTUFBTSxJQUFJLEdBQUcsQ0FBQyxTQUFTO1lBQzFELENBQUMsQ0FBQyxNQUFNO1lBQ1IsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUUxQyxJQUFJLFFBQVEsRUFBRSxDQUFDO1lBQ2IsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLGlCQUFpQixDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRSxFQUFFLFFBQVEsQ0FBQyxhQUFhLEVBQUUsRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDbkcsQ0FBQzthQUFNLENBQUM7WUFDTixJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRSxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsRUFBRSxFQUFFO2dCQUN0RSxZQUFZLEVBQUUsR0FBRyxDQUFDLE1BQU07Z0JBQ3hCLEtBQUssRUFBRSxHQUFHLENBQUMsS0FBSztnQkFDaEIsS0FBSzthQUNOLENBQUMsQ0FBQyxDQUFDO1FBQ04sQ0FBQztJQUNILENBQUM7SUFFRCwwRUFBMEU7SUFDMUUsNEVBQTRFO0lBQzVFLHlFQUF5RTtJQUN6RSwwRUFBMEU7SUFDMUUsMkVBQTJFO0lBQzNFLHNCQUFzQjtJQUNkLGlCQUFpQixDQUFDLEdBQWMsRUFBRSxFQUFXO1FBQ25ELEdBQUcsQ0FBQyxNQUFNLEdBQUcsRUFBRSxDQUFDO1FBRWhCLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsWUFBWSxLQUFLLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUVwRixJQUFJLENBQUMsRUFBRSxFQUFFLENBQUM7WUFDUixJQUFJLFFBQVEsRUFBRSxDQUFDO2dCQUNiLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLEVBQUUsUUFBUSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFDeEUsQ0FBQztZQUVELE9BQU87UUFDVCxDQUFDO1FBRUQsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO1lBQ2QsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLEVBQUUsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLEVBQUUsRUFBRTtnQkFDdEUsWUFBWSxFQUFFLEdBQUcsQ0FBQyxNQUFNO2dCQUN4QixLQUFLLEVBQUUsR0FBRyxDQUFDLEtBQUs7Z0JBQ2hCLEtBQUssRUFBRSxRQUFRO2FBQ2hCLENBQUMsQ0FBQyxDQUFDO1FBQ04sQ0FBQzthQUFNLElBQUksSUFBSSxDQUFDLFdBQVcsQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLGFBQWEsQ0FBQyxFQUFFLEtBQUssS0FBSyxXQUFXLEVBQUUsQ0FBQztZQUMvRSxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsaUJBQWlCLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLEVBQUUsUUFBUSxDQUFDLGFBQWEsRUFBRSxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDM0csQ0FBQztJQUNILENBQUM7SUFFRCw0RUFBNEU7SUFDNUUsc0NBQXNDO0lBQzlCLFlBQVk7UUFDbEIsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLEVBQUUsT0FBTyxDQUFDO1FBQy9DLE1BQU0sSUFBSSxHQUFHLE9BQU8sQ0FBQyxDQUFDLENBQUMsYUFBYSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDO1FBQzdELE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztRQUVuQyxPQUFPLElBQUksQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLE1BQU0sRUFBRSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztJQUNsRyxDQUFDO0lBRUQsNkVBQTZFO0lBQzdFLDZFQUE2RTtJQUM3RSxzQ0FBc0M7SUFDOUIsZUFBZTtRQUNyQixJQUFJLElBQUksQ0FBQyxTQUFTLEVBQUUsRUFBRSxDQUFDO1lBQ3JCLE9BQU8sRUFBRSxDQUFDO1FBQ1osQ0FBQztRQUVELE1BQU0sR0FBRyxHQUFHLFFBQVEsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDckMsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLFlBQVksRUFBRTthQUM5QixNQUFNLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLFdBQVcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLENBQUM7YUFDbkQsR0FBRyxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLEtBQUssSUFBSSxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBRTlELE9BQU8sS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsbURBQW1ELEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0lBQ3BHLENBQUM7SUFFRCw0RUFBNEU7SUFDNUUsb0RBQW9EO0lBQzVDLFlBQVk7UUFDbEIsTUFBTSxJQUFJLEdBQUcsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssSUFBSSxFQUFFLENBQUM7YUFDbkMsSUFBSSxDQUFDLENBQUMsU0FBUyxFQUFFLEVBQUUsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxNQUFNLElBQUksRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxLQUFLLENBQUMsRUFBRSxLQUFLLElBQUksQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztRQUVqRyxPQUFPLENBQUMsSUFBSSxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLEVBQUUsTUFBTSxJQUFJLEVBQUUsQ0FBQztJQUNwRCxDQUFDO0lBRUQsMEVBQTBFO0lBQzFFLGlFQUFpRTtJQUN6RCxVQUFVLENBQUMsTUFBeUIsRUFBRSxHQUFXO1FBQ3ZELE1BQU0sS0FBSyxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxTQUFTLEVBQUUsRUFBRSxDQUFDLFFBQVEsQ0FBQyxTQUFTLENBQUMsS0FBSyxHQUFHLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQztRQUU5RSxPQUFPLEtBQUssRUFBRSxLQUFLLElBQUksR0FBRyxDQUFDO0lBQzdCLENBQUM7SUFFRCwwRUFBMEU7SUFDMUUsbUNBQW1DO0lBQzNCLFlBQVk7UUFDbEIsTUFBTSxNQUFNLEdBQUcsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sSUFBSSxFQUFFLENBQWMsQ0FBQztRQUUxRCxJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksS0FBSyxLQUFLLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ3ZFLElBQUksQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxVQUFVLElBQUksb0JBQW9CLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDcEUsSUFBSSxDQUFDLGFBQWEsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLE9BQU8sRUFBRSxNQUFNLEtBQUssaUJBQWlCLENBQUMsT0FBTztlQUN0RSxvQkFBb0IsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDckQsSUFBSSxDQUFDLFdBQVcsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUMsTUFBTSxFQUFFLEtBQUssSUFBSSxJQUFJLENBQUMsQ0FBQyxDQUFDO1FBQ3RFLElBQUksQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxNQUFNLEVBQUUsS0FBSyxJQUFJLEVBQUUsQ0FBQyxDQUFDO1FBQ2pELElBQUksQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDdkMsSUFBSSxDQUFDLG9CQUFvQixDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsU0FBUyxFQUFFLFdBQVcsSUFBSSxpQ0FBaUMsQ0FBQyxDQUFDO1FBQ2xHLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLFNBQVMsRUFBRSxPQUFPLElBQUksNkJBQTZCLENBQUMsQ0FBQztJQUN4RixDQUFDO0lBRUQsd0VBQXdFO0lBQ3hFLGdFQUFnRTtJQUN4RCxhQUFhLENBQUMsUUFBc0Q7UUFDMUUsTUFBTSxNQUFNLEdBQUcsUUFBUSxFQUFFLE1BQU0sQ0FBQztRQUVoQyxPQUFPLE1BQU0sSUFBSSxPQUFPLE1BQU0sS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLGVBQWUsQ0FBQyxNQUFtQixDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQztJQUM1RixDQUFDO0lBRUQscUVBQXFFO0lBQzdELGdCQUFnQjtRQUN0QixNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDO1FBQ2hELE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUV4QyxPQUFPO1lBQ0wsVUFBVSxFQUFFLElBQUksQ0FBQyxVQUFVLEVBQUUsS0FBSyxvQkFBb0IsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRTtZQUN0RixNQUFNLEVBQUUsTUFBTSxLQUFLLElBQUksQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLEtBQUssRUFBRSxJQUFJLENBQUMsYUFBYSxDQUFDLE1BQU0sQ0FBQyxFQUFFLEtBQUssRUFBRSxLQUFLLElBQUksSUFBSSxFQUFFO1lBQzVGLFNBQVMsRUFBRSxJQUFJLENBQUMsU0FBUyxFQUFFO2dCQUN6QixDQUFDLENBQUMsRUFBRSxXQUFXLEVBQUUsSUFBSSxDQUFDLG9CQUFvQixFQUFFLEVBQUUsT0FBTyxFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUMsRUFBRTtnQkFDOUYsQ0FBQyxDQUFDLElBQUk7U0FDVCxDQUFDO0lBQ0osQ0FBQztJQUVELHdFQUF3RTtJQUN4RSxzQkFBc0I7SUFDZCxZQUFZLENBQUMsS0FBb0I7UUFDdkMsSUFBSSxLQUFLLEtBQUssSUFBSSxJQUFJLENBQUMsSUFBSSxDQUFDLGFBQWEsRUFBRSxFQUFFLENBQUM7WUFDNUMsT0FBTyxLQUFLLENBQUM7UUFDZixDQUFDO1FBRUQsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDLEtBQUssR0FBRyxHQUFHLEdBQUcsR0FBRyxDQUFDLEdBQUcsR0FBRyxDQUFDO0lBQzdDLENBQUM7SUFFTyxhQUFhLENBQUMsS0FBYTtRQUNqQyxPQUFPLElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQyxDQUFDLENBQUMsS0FBSyxHQUFHLEdBQUcsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDO0lBQ3BELENBQUM7SUFFRCxtREFBbUQ7SUFDM0MsT0FBTyxDQUFDLEtBQTZCO1FBQzNDLElBQUksS0FBSyxLQUFLLElBQUksSUFBSSxLQUFLLEtBQUssRUFBRSxFQUFFLENBQUM7WUFDbkMsT0FBTyxJQUFJLENBQUM7UUFDZCxDQUFDO1FBRUQsTUFBTSxNQUFNLEdBQUcsT0FBTyxLQUFLLEtBQUssUUFBUSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUVyRSxPQUFPLE1BQU0sQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDO0lBQ2pELENBQUM7SUFFRCx5RUFBeUU7SUFDekUseUVBQXlFO0lBQ3pFLDRFQUE0RTtJQUM1RSxtRUFBbUU7SUFDM0QsUUFBUSxDQUFDLEtBQXNCO1FBQ3JDLE9BQU8sT0FBTyxLQUFLLEtBQUssUUFBUSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUMvRCxDQUFDO0lBRUQsd0VBQXdFO0lBQ2hFLElBQUksQ0FBQyxPQUE0QjtRQUN2QyxPQUFPLENBQUMsU0FBUyxDQUFDO1lBQ2hCLElBQUksRUFBRSxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsY0FBYyxFQUFFO1lBQ2pDLEtBQUssRUFBRSxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxLQUFLLENBQUM7U0FDN0MsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVELDBFQUEwRTtJQUMxRSx1RUFBdUU7SUFDdkUsdUVBQXVFO0lBQ3ZFLGlDQUFpQztJQUN6QixZQUFZO1FBQ2xCLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxHQUFHLENBQUMsQ0FBQyxNQUFNLEVBQUUsRUFBRTtZQUNuRCxNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDLFNBQVMsRUFBRSxFQUFFLENBQUMsU0FBUyxDQUFDLFlBQVksS0FBSyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDM0YsTUFBTSxLQUFLLEdBQUcsTUFBTSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUM7WUFFckYsT0FBTztnQkFDTCxNQUFNLEVBQUUsTUFBTSxDQUFDLE1BQU07Z0JBQ3JCLElBQUksRUFBRSxNQUFNLENBQUMsSUFBSTtnQkFDakIsS0FBSyxFQUFFLE1BQU0sRUFBRSxLQUFLO3VCQUNmLElBQUksQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLE1BQU0sRUFBRSxhQUFhLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxLQUFLO3VCQUN4RCxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUM7Z0JBQ2xDLE1BQU0sRUFBRSxLQUFLLEtBQUssUUFBUSxJQUFJLEtBQUssS0FBSyxNQUFNO2dCQUM5QyxTQUFTLEVBQUUsQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxLQUFLLEtBQUssV0FBVyxJQUFJLEtBQUssS0FBSyxNQUFNLENBQUM7YUFDMUUsQ0FBQztRQUNKLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDTixDQUFDO0lBRUQsNkVBQTZFO0lBQzdFLG1FQUFtRTtJQUMzRCxjQUFjO1FBQ3BCLElBQUksQ0FBQyxjQUFjLENBQUMsSUFBSSxFQUFFLENBQUM7UUFFM0IsSUFBSSxDQUFDLFdBQVcsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUM7YUFDakMsU0FBUyxDQUFDLENBQUMsTUFBYyxFQUFFLEVBQUU7WUFDNUIsSUFBSSxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUM7WUFDckIsSUFBSSxDQUFDLFlBQVksQ0FBQyxNQUFNLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUMvQyxDQUFDLENBQUMsQ0FBQztJQUNQLENBQUM7SUFFTyxjQUFjLENBQUMsS0FBVTtRQUMvQixJQUFJLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxLQUFLLEVBQUUsS0FBSyxFQUFFLE9BQU8sSUFBSSxLQUFLLEVBQUUsT0FBTyxJQUFJLHlCQUF5QixDQUFDLENBQUM7UUFDMUYsd0VBQXdFO1FBQ3hFLElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQztJQUN4QixDQUFDO0lBRUQseUVBQXlFO0lBQ3pFLDJFQUEyRTtJQUNuRSxZQUFZLENBQUMsTUFBYyxFQUFFLFdBQW1CO1FBQ3RELElBQUksQ0FBQyxXQUFXLEdBQUcsSUFBSSxHQUFHLENBQUMsQ0FBQyxNQUFNLENBQUMsWUFBWSxJQUFJLEVBQUUsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQyxLQUFLLENBQUMsRUFBRSxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUUxRixNQUFNLFNBQVMsR0FBRyxnQkFBZ0IsQ0FBQyxNQUFNLENBQUM7YUFDdkMsSUFBSSxDQUFDLENBQUMsU0FBUyxFQUFFLEVBQUUsQ0FBQyxTQUFTLENBQUMsRUFBRSxLQUFLLFdBQVcsQ0FBQyxDQUFDO1FBRXJELElBQUksQ0FBQyxRQUFRLEdBQUcsU0FBUyxFQUFFLE9BQU8sSUFBSSxFQUFFLENBQUM7UUFDekMsSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO0lBQ3RCLENBQUM7SUFFRCxvRUFBb0U7SUFDcEUsb0VBQW9FO0lBQ3BFLHNEQUFzRDtJQUN0RCxFQUFFO0lBQ0YsNkVBQTZFO0lBQzdFLDRFQUE0RTtJQUM1RSw0RUFBNEU7SUFDNUUsOEVBQThFO0lBQzlFLDRFQUE0RTtJQUM1RSw0REFBNEQ7SUFDcEQsUUFBUTtRQUNkLElBQUksQ0FBQyxXQUFXLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRSxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDO2FBQzdELFNBQVMsQ0FBQztZQUNULElBQUksRUFBRSxDQUFDLE9BQTJCLEVBQUUsRUFBRTtnQkFDcEMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsT0FBTyxFQUFFLEdBQUcsSUFBSSxJQUFJLENBQUMsQ0FBQztnQkFDbkMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLE9BQU8sRUFBRSxRQUFRLENBQUMsQ0FBQztnQkFDMUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxHQUFHLENBQUMsT0FBTyxFQUFFLFFBQVEsSUFBSSxLQUFLLENBQUMsQ0FBQztnQkFDakQsSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsT0FBTyxFQUFFLEtBQUssSUFBSSxJQUFJLENBQUMsQ0FBQztZQUM1QyxDQUFDO1lBQ0QsS0FBSyxFQUFFLENBQUMsS0FBSyxFQUFFLEVBQUU7Z0JBQ2YsSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUM7Z0JBQ25CLElBQUksQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLEtBQUssRUFBRSxLQUFLLEVBQUUsT0FBTyxJQUFJLGtDQUFrQyxDQUFDLENBQUM7WUFDakYsQ0FBQztTQUNGLENBQUMsQ0FBQztJQUNQLENBQUM7SUFFTyxZQUFZO1FBQ2xCLElBQUksQ0FBQyxXQUFXLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUM7YUFDakUsU0FBUyxDQUFDO1lBQ1QsSUFBSSxFQUFFLENBQUMsT0FBaUMsRUFBRSxFQUFFO2dCQUMxQyxJQUFJLENBQUMsa0JBQWtCLEdBQUcsT0FBTyxJQUFJLEVBQUUsQ0FBQztnQkFDeEMsSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO1lBQ3RCLENBQUM7WUFDRCxLQUFLLEVBQUUsQ0FBQyxLQUFLLEVBQUUsRUFBRTtnQkFDZixJQUFJLENBQUMsWUFBWSxDQUFDLEdBQUcsQ0FBQyxLQUFLLEVBQUUsS0FBSyxFQUFFLE9BQU8sSUFBSSxzQ0FBc0MsQ0FBQyxDQUFDO1lBQ3pGLENBQUM7U0FDRixDQUFDLENBQUM7SUFDUCxDQUFDO0lBRU8sU0FBUyxDQUFDLE1BQWM7UUFDOUIsT0FBTyxNQUFNO2FBQ1YsT0FBTyxDQUFDLFNBQVMsRUFBRSxHQUFHLENBQUM7YUFDdkIsT0FBTyxDQUFDLE1BQU0sRUFBRSxHQUFHLENBQUM7YUFDcEIsSUFBSSxFQUFFO2FBQ04sT0FBTyxDQUFDLE9BQU8sRUFBRSxDQUFDLFNBQVMsRUFBRSxFQUFFLENBQUMsU0FBUyxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUM7SUFDOUQsQ0FBQzt3R0FoZlUsMEJBQTBCOzRGQUExQiwwQkFBMEIsd0VDN0p2Qyw2NmJBZ1hPLHlrQ0QxT0gsV0FBVyx1aUNBQ1gsWUFBWSw2NkRBQ1osWUFBWSxpSEFDWixjQUFjLGdNQUNkLGFBQWEsc1dBQ2IsWUFBWSxtYUFDWixhQUFhLDZvQkFDYixjQUFjLCtIQUNkLGdCQUFnQix5R0FDaEIsZ0JBQWdCLDRIQUNoQixjQUFjLHFMQUNkLFlBQVksNExBQ1osT0FBTyw4RUFDUCxRQUFRLHNEQUNSLFNBQVMscUhBQ1QsU0FBUyxpTEFDVCxRQUFRLGlVQUNSLFNBQVMscUpBQ1QsU0FBUyx3ZUFDVCxjQUFjLDBVQUNkLFVBQVU7OzRGQUdELDBCQUEwQjtrQkE3QnRDLFNBQVM7c0NBR1MsdUJBQXVCLENBQUMsTUFBTSxjQUNuQyxJQUFJLFdBQ1A7d0JBQ1AsV0FBVzt3QkFDWCxZQUFZO3dCQUNaLFlBQVk7d0JBQ1osY0FBYzt3QkFDZCxhQUFhO3dCQUNiLFlBQVk7d0JBQ1osYUFBYTt3QkFDYixjQUFjO3dCQUNkLGdCQUFnQjt3QkFDaEIsZ0JBQWdCO3dCQUNoQixjQUFjO3dCQUNkLFlBQVk7d0JBQ1osT0FBTzt3QkFDUCxRQUFRO3dCQUNSLFNBQVM7d0JBQ1QsU0FBUzt3QkFDVCxRQUFRO3dCQUNSLFNBQVM7d0JBQ1QsU0FBUzt3QkFDVCxjQUFjO3dCQUNkLFVBQVU7cUJBQ1giLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSwgQ29tcG9uZW50LCBEZXN0cm95UmVmLCBFdmVudEVtaXR0ZXIsIE9uSW5pdCwgY29tcHV0ZWQsIGluamVjdCwgc2lnbmFsLFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IHRha2VVbnRpbERlc3Ryb3llZCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUvcnhqcy1pbnRlcm9wJztcbmltcG9ydCB7IEFic3RyYWN0Q29udHJvbCwgRm9ybXNNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5cbmltcG9ydCB7IE1BVF9ESUFMT0dfREFUQSwgTWF0RGlhbG9nQWN0aW9ucywgTWF0RGlhbG9nQ2xvc2UsIE1hdERpYWxvZ0NvbnRlbnQsIE1hdERpYWxvZ1JlZiwgTWF0RGlhbG9nVGl0bGUgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9kaWFsb2cnO1xuaW1wb3J0IHsgTWF0Rm9ybUZpZWxkLCBNYXRIaW50LCBNYXRMYWJlbCwgTWF0U3VmZml4IH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvZm9ybS1maWVsZCc7XG5pbXBvcnQgeyBNYXRCdXR0b24gfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9idXR0b24nO1xuaW1wb3J0IHsgTWF0SW5wdXQgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9pbnB1dCc7XG5pbXBvcnQgeyBNYXRPcHRpb24sIE1hdFNlbGVjdCB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL3NlbGVjdCc7XG5pbXBvcnQgeyBNYXRTbGlkZVRvZ2dsZSB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL3NsaWRlLXRvZ2dsZSc7XG5pbXBvcnQgeyBNYXRUYWJzTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvdGFicyc7XG5pbXBvcnQgeyBNYXRUb29sdGlwIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvdG9vbHRpcCc7XG5cbmltcG9ydCB7IEZzRGlhbG9nTW9kdWxlIH0gZnJvbSAnQGZpcmVzdGl0Y2gvZGlhbG9nJztcbmltcG9ydCB7IEZzRm9ybU1vZHVsZSB9IGZyb20gJ0BmaXJlc3RpdGNoL2Zvcm0nO1xuaW1wb3J0IHsgRnNMYWJlbE1vZHVsZSB9IGZyb20gJ0BmaXJlc3RpdGNoL2xhYmVsJztcbmltcG9ydCB7IEZzTWFza01vZHVsZSB9IGZyb20gJ0BmaXJlc3RpdGNoL21hc2snO1xuaW1wb3J0IHsgRnNNZXNzYWdlIH0gZnJvbSAnQGZpcmVzdGl0Y2gvbWVzc2FnZSc7XG5pbXBvcnQgeyBGc1Byb21wdCB9IGZyb20gJ0BmaXJlc3RpdGNoL3Byb21wdCc7XG5pbXBvcnQgeyBGc1RhYnNNb2R1bGUgfSBmcm9tICdAZmlyZXN0aXRjaC90YWJzJztcblxuaW1wb3J0IHsgT2JzZXJ2YWJsZSB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgc3dpdGNoTWFwLCB0YXAgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5cbmltcG9ydCB7IFJlcG9ydERhdGEgfSBmcm9tICcuLi8uLi9kYXRhL3JlcG9ydC5kYXRhJztcbmltcG9ydCB7IFJlcG9ydENoYW5nZVBvbGFyaXR5IH0gZnJvbSAnLi4vLi4vZW51bXMvcmVwb3J0LWNoYW5nZS1wb2xhcml0eS5lbnVtJztcbmltcG9ydCB7IFJlcG9ydFZhbHVlRm9ybWF0IH0gZnJvbSAnLi4vLi4vZW51bXMvcmVwb3J0LXZhbHVlLWZvcm1hdC5lbnVtJztcbmltcG9ydCB7IFJlcG9ydFZhbHVlRm9ybXVsYSB9IGZyb20gJy4uLy4uL2VudW1zL3JlcG9ydC12YWx1ZS1mb3JtdWxhLmVudW0nO1xuaW1wb3J0IHsgcmVzb2x2ZUZvcm1hdENvbnRleHQgfSBmcm9tICcuLi8uLi9mb3JtYXQnO1xuaW1wb3J0IHtcbiAgS1BJX1NQQVJLTElORV9ERUZBVUxUX0dSQU5VTEFSSVRZLFxuICBLUElfU1BBUktMSU5FX0RFRkFVTFRfUEVSSU9EUyxcbiAga3BpQ2FyZFNldHRpbmdzLFxuICBzYW1lS3BpQ2FyZFNldHRpbmdzLFxufSBmcm9tICcuLi8uLi9rcGktY2FyZCc7XG5pbXBvcnQge1xuICBDaGFydEdyYW51bGFyaXR5LFxuICBDb21wb25lbnRTZXR0aW5ncyxcbiAgR1JBTlVMQVJJVFlfT1BUSU9OUyxcbiAgS3BpQ2FyZFNldHRpbmdzLFxuICBLcGlDb25maWcsXG4gIFJlcG9ydCxcbiAgUmVwb3J0Q29tcG9uZW50LFxuICBSZXBvcnRDb21wb25lbnRTcWwsXG4gIFJlcG9ydEZpbHRlcixcbiAgUmVwb3J0RmlsdGVyR3JvdXAsXG4gIFJlcG9ydEZpbHRlckxldmVsLFxuICBSZXBvcnRGaWx0ZXJUeXBlLFxuICBSZXBvcnRGaWx0ZXJhYmxlQ29sdW1uLFxufSBmcm9tICcuLi8uLi9pbnRlcmZhY2VzL3JlcG9ydC5pbnRlcmZhY2UnO1xuaW1wb3J0IHsgREVGQVVMVF9DT01QT05FTlRfUEFERElORyB9IGZyb20gJy4uLy4uL2xheW91dCc7XG5pbXBvcnQgeyBlc2NhcGVIdG1sIH0gZnJvbSAnLi4vLi4vdGV4dCc7XG5pbXBvcnQgeyBvcGVyYW5kS2V5cywgcmVwb3J0Q29tcG9uZW50cywgdmFsdWVLZXkgfSBmcm9tICcuLi8uLi92YWx1ZXMnO1xuXG5cbi8vIFdoYXQgdGhlIGRpYWxvZyBoYW5kcyBiYWNrLiBUaGUgU2V0dGluZ3MgdGFiJ3MgU2F2ZSBjYXJyaWVzIHRoZSBuZXdcbi8vIGBzZXR0aW5nc2A7IERlbGV0ZSBjYXJyaWVzIGBkZWxldGVkYCBhbmQgbm8gc2V0dGluZ3MsIGJlY2F1c2UgdGhlIGNvbXBvbmVudFxuLy8gaXQgd2FzIG9wZW5lZCBmb3Igbm8gbG9uZ2VyIGV4aXN0cy4gRXZlcnkgb3RoZXIgZXhpdCAoQ2FuY2VsLCBEb25lLCBFc2NhcGUsXG4vLyBiYWNrZHJvcCkgY2xvc2VzIHdpdGggbm8gcmVzdWx0IOKAlCBmaWx0ZXIgd29yayBpcyBhbm5vdW5jZWQgYXMgaXQgaGFwcGVuc1xuLy8gaW5zdGVhZCwgdGhyb3VnaCBgZmlsdGVyc0NoYW5nZWRgLlxuZXhwb3J0IGludGVyZmFjZSBDb21wb25lbnRTZXR0aW5nc1Jlc3VsdCB7XG4gIHNldHRpbmdzPzogQ29tcG9uZW50U2V0dGluZ3M7XG4gIGRlbGV0ZWQ/OiBib29sZWFuO1xufVxuXG4vLyBXaGF0IHRoZSBzZXR0aW5ncyBlbmRwb2ludCByZXR1cm5zIGZvciB0aGUgY29tcG9uZW50OiBpdHMgaWQgYW5kLCBmcm9tIGFcbi8vIHNlcnZlciB0aGF0IHNhdmVzIGEgS1BJJ3MgY2FyZCBrZXlzLCB0aGUgd2hvbGUgY29uZmlnIGFzIHNhdmVkLlxuaW50ZXJmYWNlIENvbXBvbmVudFNldHRpbmdzUmVzcG9uc2Uge1xuICBpZDogbnVtYmVyO1xuICBjb25maWc/OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiB8IG51bGw7XG59XG5cblxuLy8gV2hhdCBhIHJpc2UgaW4gYSBLUEkncyB2YWx1ZSBtZWFucywgZm9yIHRoZSBJbmNyZWFzZSBpcyBzZWxlY3QuXG5jb25zdCBLUElfQ0hBTkdFX1BPTEFSSVRZX09QVElPTlM6IHsgdmFsdWU6IFJlcG9ydENoYW5nZVBvbGFyaXR5OyBuYW1lOiBzdHJpbmcgfVtdID0gW1xuICB7IHZhbHVlOiBSZXBvcnRDaGFuZ2VQb2xhcml0eS5Hb29kLCBuYW1lOiAnR29vZCBuZXdzIOKAlCBhIHJpc2Ugc2hvd3MgZ3JlZW4nIH0sXG4gIHsgdmFsdWU6IFJlcG9ydENoYW5nZVBvbGFyaXR5LkJhZCwgbmFtZTogJ0JhZCBuZXdzIOKAlCBhIHJpc2Ugc2hvd3MgcmVkJyB9LFxuICB7IHZhbHVlOiBSZXBvcnRDaGFuZ2VQb2xhcml0eS5OZXV0cmFsLCBuYW1lOiAnTmVpdGhlciDigJQgbm8gY29sb3InIH0sXG5dO1xuXG4vLyBBIEtQSSBzcGFya2xpbmUncyBwZXJpb2RzIHN0YXkgd2l0aGluIDIgdG8gNjAuXG5jb25zdCBLUElfU1BBUktMSU5FX01JTl9QRVJJT0RTID0gMjtcbmNvbnN0IEtQSV9TUEFSS0xJTkVfTUFYX1BFUklPRFMgPSA2MDtcblxuLy8gQSBwZXJjZW50IEtQSSdzIHRhcmdldCBpcyBlbnRlcmVkIGFzIHRoZSBwZXJjZW50IHNob3duICgxNSBmb3IgMTUlKSBhbmRcbi8vIHN0b3JlZCBhcyB0aGUgMC0xIHJhdGlvIGl0cyB2YWx1ZSBhcnJpdmVzIGluOyB0aGUgc2VydmVyIHJlZnVzZXMgYSBzdG9yZWRcbi8vIHRhcmdldCBhYm92ZSAxMDAsIHdoaWNoIGlzIDEwLDAwMCUgaGVyZS5cbmNvbnN0IEtQSV9QRVJDRU5UX1RBUkdFVF9NQVggPSAxMDAwMDtcblxuLy8gSG93IGEgZm9ybXVsYSB2YWx1ZSdzIFNldHRpbmdzIHRhYiB3cml0ZXMgb3V0IHdoYXQgaXQgd29ya3Mgb3V0LCBpbiBpdHNcbi8vIG9wZXJhbmRzJyBuYW1lcy5cbmNvbnN0IEZPUk1VTEFfTElORVM6IFJlY29yZDxSZXBvcnRWYWx1ZUZvcm11bGEsIChuYW1lczogc3RyaW5nW10pID0+IHN0cmluZz4gPSB7XG4gIFtSZXBvcnRWYWx1ZUZvcm11bGEuQ2hhbmdlXTogKG5hbWVzKSA9PiBuYW1lcy5qb2luKCcg4oiSICcpLFxuICBbUmVwb3J0VmFsdWVGb3JtdWxhLlBlcmNlbnRDaGFuZ2VdOiAoW2EsIGJdKSA9PiBgJSBjaGFuZ2Ugb2YgJHthfSBvdmVyICR7Yn1gLFxuICBbUmVwb3J0VmFsdWVGb3JtdWxhLlJhdGlvXTogKG5hbWVzKSA9PiBuYW1lcy5qb2luKCcgw7cgJyksXG4gIFtSZXBvcnRWYWx1ZUZvcm11bGEuU3VtXTogKG5hbWVzKSA9PiBuYW1lcy5qb2luKCcgKyAnKSxcbn07XG5cblxuLy8gT25lIHJvdyBvZiB0aGUgRmlsdGVycyB0YWIgbGlzdGluZzogYSBmaWx0ZXJhYmxlIGNvbHVtbiwgdGhlIGludGVyZmFjZVxuLy8gaW5mZXJyZWQgZnJvbSBpdHMgZGF0YSwgYW5kIHdoZXJlIGl0cyBmaWx0ZXIgaXMgZXhwb3NlZCAodGhlIHR3byB0b2dnbGVzKS5cbmludGVyZmFjZSBGaWx0ZXJSb3cge1xuICBjb2x1bW46IHN0cmluZztcbiAgdHlwZTogUmVwb3J0RmlsdGVyVHlwZTtcbiAgbGFiZWw6IHN0cmluZztcbiAgcmVwb3J0OiBib29sZWFuO1xuICBjb21wb25lbnQ6IGJvb2xlYW47XG59XG5cblxuLy8gQ29tcG9uZW50IHNldHRpbmdzLCBpbiB0YWJzOlxuLy8gICBTZXR0aW5ncyDigJQgdGl0bGUgYW5kIGNvbnRlbnQgcGFkZGluZyAoYSB2YWx1ZToganVzdCBpdHMgbmFtZSwgc2luY2UgaXRcbi8vICAgc2l0cyBpbnNpZGUgYSB0ZXh0IGJsb2NrJ3Mgd29yZHMgYW5kIGhhcyBubyBib3gpLCBhbmQgb24gYSBkZXJpdmVkIEtQSSBpdHMgY2FyZDpcbi8vICAgd2hhdCBhIHJpc2UgbWVhbnMsIGEgdGFyZ2V0IGFuZCBhIHNwYXJrbGluZSAobnVtYmVyIGZvcm1hdHMgc3RheSB3aXRoXG4vLyAgIHRoZSBBSSkuIFBvc2l0aW9uL3NpemUgYXJlIHR1bmVkIGJ5IGRyYWdnaW5nIG9uIHRoZSBjYW52YXM7IGhlaWdodFxuLy8gICBiZWhhdmlvdXIgZm9sbG93cyBmcm9tIHRoZSBjb21wb25lbnQgdHlwZS5cbi8vICAgRmlsdGVycyAg4oCUIE9ORSBsaXN0aW5nIG9mIGV2ZXJ5IGZpbHRlcmFibGUgY29sdW1uIG9uIHRoaXMgY29tcG9uZW50LiBFYWNoXG4vLyAgIHJvdyBjYXJyaWVzIHR3byB0b2dnbGVzOiBzaG93IGluIHRoZSByZXBvcnQgYmFyIGFuZC9vciBzaG93IG9uIHRoaXNcbi8vICAgY29tcG9uZW50IChib3RoLCBlaXRoZXIsIG9yIG5laXRoZXIpLiBUaGUgaW50ZXJmYWNlIChkYXRlIHJhbmdlIHZzIHZhbHVlXG4vLyAgIHBpY2tlcikgaXMgaW5mZXJyZWQgZnJvbSB0aGUgZGF0YSwgbmV2ZXIgY2hvc2VuLiBFYWNoIHRvZ2dsZSBwZXJzaXN0c1xuLy8gICBpbW1lZGlhdGVseSBhbmQgcmVmcmVzaGVzIHRoZSBpbi1kaWFsb2cgbGlzdC4gQSB2YWx1ZSBoYXMgbm8gY29tcG9uZW50XG4vLyAgIHRvIHNob3cgYSBmaWx0ZXIgb24sIHNvIGl0IGdldHMgdGhlIHJlcG9ydCBiYXIgdG9nZ2xlIG9ubHkuXG4vLyAgIFNRTCAvIENvbmZpZyDigJQgcmVhZC1vbmx5IGRpYWdub3N0aWNzLlxuLy8gQSBmb3JtdWxhIHZhbHVlIGhhcyBubyBGaWx0ZXJzIG9yIFNRTCB0YWI6IHRoZSBzZXJ2ZXIgd29ya3MgaXQgb3V0IG9mIG90aGVyXG4vLyB2YWx1ZXMgb24gaXRzIHBhZ2UsIHNvIGl0IHJ1bnMgbm8gc3RhdGVtZW50IGFuZCBmb2xsb3dzIHRoZSBmaWx0ZXJzIG9mIHRoZVxuLy8gdmFsdWVzIGl0IHJlYWRzLiBJdHMgU2V0dGluZ3MgdGFiIHNheXMgd2hhdCBpdCB3b3JrcyBvdXQsIHVuZGVyIGl0cyBuYW1lLlxuQENvbXBvbmVudCh7XG4gIHRlbXBsYXRlVXJsOiAnLi9jb21wb25lbnQtc2V0dGluZ3MuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybHM6IFsnLi9jb21wb25lbnQtc2V0dGluZ3MuY29tcG9uZW50LnNjc3MnXSxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGltcG9ydHM6IFtcbiAgICBGb3Jtc01vZHVsZSxcbiAgICBGc0Zvcm1Nb2R1bGUsXG4gICAgRnNNYXNrTW9kdWxlLFxuICAgIEZzRGlhbG9nTW9kdWxlLFxuICAgIEZzTGFiZWxNb2R1bGUsXG4gICAgRnNUYWJzTW9kdWxlLFxuICAgIE1hdFRhYnNNb2R1bGUsXG4gICAgTWF0RGlhbG9nVGl0bGUsXG4gICAgTWF0RGlhbG9nQ29udGVudCxcbiAgICBNYXREaWFsb2dBY3Rpb25zLFxuICAgIE1hdERpYWxvZ0Nsb3NlLFxuICAgIE1hdEZvcm1GaWVsZCxcbiAgICBNYXRIaW50LFxuICAgIE1hdExhYmVsLFxuICAgIE1hdFN1ZmZpeCxcbiAgICBNYXRCdXR0b24sXG4gICAgTWF0SW5wdXQsXG4gICAgTWF0T3B0aW9uLFxuICAgIE1hdFNlbGVjdCxcbiAgICBNYXRTbGlkZVRvZ2dsZSxcbiAgICBNYXRUb29sdGlwLFxuICBdLFxufSlcbmV4cG9ydCBjbGFzcyBDb21wb25lbnRTZXR0aW5nc0NvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCB7XG5cbiAgLy8gQSBmaWx0ZXIgd2FzIGFkZGVkLCByZW1vdmVkIG9yIHJlLWxldmVsbGVkLCBzbyB0aGUgcmVwb3J0J3MgZmlsdGVyIGdyb3Vwc1xuICAvLyBjaGFuZ2VkLiBUaG9zZSBtdXRhdGlvbnMgcGVyc2lzdCB0aGUgbW9tZW50IHRoZXkgYXJlIGNsaWNrZWQgYW5kIHRoZSBkaWFsb2dcbiAgLy8gY2FuIHRoZW4gYmUgZGlzbWlzc2VkIGJ5IGEgcm91dGUgdGhhdCBjYXJyaWVzIG5vIHJlc3VsdCAoRXNjYXBlLCBiYWNrZHJvcCksXG4gIC8vIHNvIHRoZSBwYWdlIGlzIHRvbGQgaGVyZSByYXRoZXIgdGhhbiB0aHJvdWdoIHRoZSBjbG9zZSByZXN1bHQuXG4gIHB1YmxpYyByZWFkb25seSBmaWx0ZXJzQ2hhbmdlZCA9IG5ldyBFdmVudEVtaXR0ZXI8dm9pZD4oKTtcblxuICBwdWJsaWMgY29tcG9uZW50OiBSZXBvcnRDb21wb25lbnQ7XG4gIHB1YmxpYyByZXBvcnQ6IFJlcG9ydDtcblxuICBwdWJsaWMgc2VsZWN0ZWRUYWIgPSAnc2V0dGluZ3MnO1xuXG4gIHB1YmxpYyB0aXRsZSA9ICcnO1xuXG4gIC8vIENvbXBvbmVudCBwYWRkaW5nIGluIGluY2hlcy4gYG51bWJlciB8IHN0cmluZ2AgZm9yIHRoZSBzYW1lIHJlYXNvbiBhcyB0aGVcbiAgLy8gcGFnZSBkaW1lbnNpb25zIGluIHJlcG9ydC1zZXR0aW5nczogZnNNYXNrTnVtYmVyIHNlZWRzIGZyb20gdGhlIG51bWJlciBidXRcbiAgLy8gaGFuZHMgYmFjayB0aGUgdW5tYXNrZWQgc3RyaW5nLCBhbmQgc2F2ZSBjYXN0cyBpdCBvbmNlIG9uIHRoZSB3YXkgb3V0LlxuICBwdWJsaWMgcGFkZGluZ1RvcDogbnVtYmVyIHwgc3RyaW5nID0gREVGQVVMVF9DT01QT05FTlRfUEFERElORztcbiAgcHVibGljIHBhZGRpbmdSaWdodDogbnVtYmVyIHwgc3RyaW5nID0gREVGQVVMVF9DT01QT05FTlRfUEFERElORztcbiAgcHVibGljIHBhZGRpbmdCb3R0b206IG51bWJlciB8IHN0cmluZyA9IERFRkFVTFRfQ09NUE9ORU5UX1BBRERJTkc7XG4gIHB1YmxpYyBwYWRkaW5nTGVmdDogbnVtYmVyIHwgc3RyaW5nID0gREVGQVVMVF9DT01QT05FTlRfUEFERElORztcblxuICBwdWJsaWMgY29uZmlnSnNvbiA9ICcnO1xuXG4gIC8vIC0tLS0gS1BJIGNhcmQgc3RhdGUgKGEgZGVyaXZlZCBLUEkgb25seSkgLS0tLVxuICBwdWJsaWMgcmVhZG9ubHkga3BpUG9sYXJpdHlPcHRpb25zID0gS1BJX0NIQU5HRV9QT0xBUklUWV9PUFRJT05TO1xuICBwdWJsaWMgcmVhZG9ubHkgZ3JhbnVsYXJpdHlPcHRpb25zID0gR1JBTlVMQVJJVFlfT1BUSU9OUztcbiAgcHVibGljIHJlYWRvbmx5IHNwYXJrbGluZU1pblBlcmlvZHMgPSBLUElfU1BBUktMSU5FX01JTl9QRVJJT0RTO1xuICBwdWJsaWMgcmVhZG9ubHkgc3BhcmtsaW5lTWF4UGVyaW9kcyA9IEtQSV9TUEFSS0xJTkVfTUFYX1BFUklPRFM7XG4gIHB1YmxpYyByZWFkb25seSBrcGlDYXJkID0gc2lnbmFsKGZhbHNlKTtcbiAgLy8gQSB2YWx1ZSBpbnNpZGUgYSB0ZXh0IGJsb2NrOiBubyBib3gsIHNvIG5vIHBhZGRpbmcuXG4gIHB1YmxpYyByZWFkb25seSBpc1ZhbHVlID0gc2lnbmFsKGZhbHNlKTtcbiAgLy8gQSBmb3JtdWxhIHZhbHVlOiBubyBzdGF0ZW1lbnQsIGNvbHVtbnMgb3IgZmlsdGVycyBvZiBpdHMgb3duLlxuICBwdWJsaWMgcmVhZG9ubHkgaXNGb3JtdWxhID0gc2lnbmFsKGZhbHNlKTtcbiAgLy8gV2hhdCBhIGZvcm11bGEgd29ya3Mgb3V0LCBpbiBpdHMgb3BlcmFuZHMnIG5hbWVzOyBlbXB0eSBmb3IgYW55IG90aGVyXG4gIC8vIGNvbXBvbmVudC5cbiAgcHVibGljIHJlYWRvbmx5IGZvcm11bGFMaW5lID0gY29tcHV0ZWQoKCkgPT4gKHRoaXMuaXNGb3JtdWxhKCkgPyB0aGlzLl9mb3JtdWxhTGluZSgpIDogJycpKTtcbiAgcHVibGljIHJlYWRvbmx5IGluY3JlYXNlSXMgPSBzaWduYWw8UmVwb3J0Q2hhbmdlUG9sYXJpdHk+KFJlcG9ydENoYW5nZVBvbGFyaXR5Lkdvb2QpO1xuICAvLyBUaGUgdGFyZ2V0IGFzIHR5cGVkOiBmc01hc2tOdW1iZXIgaGFuZHMgYmFjayB0aGUgdW5tYXNrZWQgc3RyaW5nLiBFbXB0eVxuICAvLyBtZWFucyBubyB0YXJnZXQuIEEgcGVyY2VudCBLUEkncyBpcyBpbiBwZXJjZW50ICh0YXJnZXRQZXJjZW50KS5cbiAgcHVibGljIHJlYWRvbmx5IHRhcmdldFZhbHVlID0gc2lnbmFsPG51bWJlciB8IHN0cmluZyB8IG51bGw+KG51bGwpO1xuICBwdWJsaWMgcmVhZG9ubHkgdGFyZ2V0TGFiZWwgPSBzaWduYWwoJycpO1xuICBwdWJsaWMgcmVhZG9ubHkgdGFyZ2V0UGVyY2VudCA9IHNpZ25hbChmYWxzZSk7XG4gIHB1YmxpYyByZWFkb25seSBoYXNUYXJnZXQgPSBjb21wdXRlZCgoKSA9PiB0aGlzLl9udW1iZXIodGhpcy50YXJnZXRWYWx1ZSgpKSAhPT0gbnVsbCk7XG4gIHB1YmxpYyByZWFkb25seSBzcGFya2xpbmUgPSBzaWduYWwoZmFsc2UpO1xuICBwdWJsaWMgcmVhZG9ubHkgc3BhcmtsaW5lR3JhbnVsYXJpdHkgPSBzaWduYWw8Q2hhcnRHcmFudWxhcml0eT4oS1BJX1NQQVJLTElORV9ERUZBVUxUX0dSQU5VTEFSSVRZKTtcbiAgcHVibGljIHJlYWRvbmx5IHNwYXJrbGluZVBlcmlvZHMgPSBzaWduYWw8bnVtYmVyIHwgc3RyaW5nPihLUElfU1BBUktMSU5FX0RFRkFVTFRfUEVSSU9EUyk7XG5cbiAgLy8gLS0tLSBTUUwgdGFiIHN0YXRlIC0tLS1cbiAgLy8gVGhlIHN0YXRlbWVudCwgb25jZSBmZXRjaGVkLiBOdWxsIHdoaWxlIGl0IGlzIGluIGZsaWdodCwgYW5kIG51bGwgd2hlbiB0aGVcbiAgLy8gY29tcG9uZW50J3MgZG9jdW1lbnQgY291bGQgbm90IGJlIGNvbXBpbGVkIChzcWxFcnJvciB0aGVuIHNheXMgd2h5KS5cbiAgcHVibGljIHJlYWRvbmx5IHNxbCA9IHNpZ25hbDxzdHJpbmcgfCBudWxsPihudWxsKTtcbiAgLy8gVHJ1ZSB3aGVuIHRoZSBzdGF0ZW1lbnQgaXMgYSBERVJJVkVEIGJhc2VsaW5lOiBubyBmaWx0ZXJzLCB0aGUgYXV0aG9yZWRcbiAgLy8gZ3JhaW4sIHRpbWVzIGluIHRoZSByZXBvcnQncyBlZmZlY3RpdmUgem9uZS4gVGhlIHRhYiBzYXlzIHNvLCBiZWNhdXNlIHRoZVxuICAvLyBudW1iZXJzIG9uIHNjcmVlbiBjb21lIGZyb20gdGhpcyBzdGF0ZW1lbnQgcGx1cyB0aGUgdmlld2VyJ3Mgb3duIGNob2ljZXNcbiAgLy8gYW5kIHRoZSB0d28gY2FuIGRpZmZlci5cbiAgcHVibGljIHJlYWRvbmx5IHNxbEJhc2VsaW5lID0gc2lnbmFsKGZhbHNlKTtcbiAgLy8gVGhlIHpvbmUgdGhlIHN0YXRlbWVudCB3YXMgY29tcGlsZWQgaW46IHRoZSByZXBvcnQncyBlZmZlY3RpdmUgem9uZSwgc2VudFxuICAvLyB3aXRoIHRoZSBTUUwuIEEgc2VydmVyIHRvbyBvbGQgdG8gc2VuZCBpdCBjb21waWxlZCBpbiBVVEMuXG4gIHB1YmxpYyByZWFkb25seSBzcWxUaW1lem9uZSA9IHNpZ25hbCgnVVRDJyk7XG4gIHB1YmxpYyByZWFkb25seSBzcWxFcnJvciA9IHNpZ25hbDxzdHJpbmcgfCBudWxsPihudWxsKTtcblxuICAvLyAtLS0tIGZpbHRlciBtYW5hZ2VtZW50IHN0YXRlIC0tLS1cbiAgLy8gT25lIHJvdyBwZXIgZmlsdGVyYWJsZSBjb2x1bW4uIFRoZSB0d28gYm9vbGVhbnMgZHJpdmUgdGhlIHRvZ2dsZXM7IHdlIGZsaXBcbiAgLy8gdGhlbSBvcHRpbWlzdGljYWxseSBvbiBjbGljayAoc28gdGhlIFVJIG5ldmVyIGJsaW5rcyB3aGlsZSB0aGUgcmVxdWVzdCBpc1xuICAvLyBpbiBmbGlnaHQpIGFuZCByZWNvbmNpbGUgZnJvbSB0aGUgc2VydmVyIG9uIHJlbG9hZC5cbiAgcHVibGljIHJlYWRvbmx5IHJvd3MgPSBzaWduYWw8RmlsdGVyUm93W10+KFtdKTtcbiAgcHVibGljIHJlYWRvbmx5IGNvbHVtbnNFcnJvciA9IHNpZ25hbDxzdHJpbmcgfCBudWxsPihudWxsKTtcblxuICAvLyBUaGUgcmF3IGlucHV0cyB0aGUgcm93cyBhcmUgYnVpbHQgZnJvbS5cbiAgcHJpdmF0ZSBfZmlsdGVyYWJsZUNvbHVtbnM6IFJlcG9ydEZpbHRlcmFibGVDb2x1bW5bXSA9IFtdO1xuICBwcml2YXRlIF9maWx0ZXJzOiBSZXBvcnRGaWx0ZXJbXSA9IFtdO1xuICBwcml2YXRlIF9ncm91cHNCeUlkID0gbmV3IE1hcDxudW1iZXIsIFJlcG9ydEZpbHRlckdyb3VwPigpO1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgX3R5cGVMYWJlbHM6IFJlY29yZDxSZXBvcnRGaWx0ZXJUeXBlLCBzdHJpbmc+ID0ge1xuICAgIHNlbGVjdDogJ1BpY2sgdmFsdWVzJyxcbiAgICBkYXRlUmFuZ2U6ICdEYXRlIHJhbmdlJyxcbiAgICBrZXl3b3JkOiAnU2VhcmNoIHRleHQnLFxuICB9O1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgX2RhdGE6IHsgcmVwb3J0OiBSZXBvcnQ7IGNvbXBvbmVudDogUmVwb3J0Q29tcG9uZW50IH0gPSBpbmplY3QoTUFUX0RJQUxPR19EQVRBKTtcbiAgcHJpdmF0ZSByZWFkb25seSBfZGlhbG9nUmVmID0gaW5qZWN0PE1hdERpYWxvZ1JlZjxDb21wb25lbnRTZXR0aW5nc0NvbXBvbmVudCwgQ29tcG9uZW50U2V0dGluZ3NSZXN1bHQ+PihNYXREaWFsb2dSZWYpO1xuICBwcml2YXRlIHJlYWRvbmx5IF9yZXBvcnREYXRhID0gaW5qZWN0KFJlcG9ydERhdGEpO1xuICBwcml2YXRlIHJlYWRvbmx5IF9tZXNzYWdlID0gaW5qZWN0KEZzTWVzc2FnZSk7XG4gIHByaXZhdGUgcmVhZG9ubHkgX3Byb21wdCA9IGluamVjdChGc1Byb21wdCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgX2Rlc3Ryb3lSZWYgPSBpbmplY3QoRGVzdHJveVJlZik7XG5cbiAgcHVibGljIG5nT25Jbml0KCk6IHZvaWQge1xuICAgIHRoaXMucmVwb3J0ID0gdGhpcy5fZGF0YS5yZXBvcnQ7XG4gICAgdGhpcy5jb21wb25lbnQgPSB0aGlzLl9kYXRhLmNvbXBvbmVudDtcblxuICAgIHRoaXMudGl0bGUgPSB0aGlzLmNvbXBvbmVudC50aXRsZSA/PyAnJztcbiAgICB0aGlzLmlzVmFsdWUuc2V0KHRoaXMuY29tcG9uZW50LnR5cGUgPT09ICd2YWx1ZScpO1xuICAgIHRoaXMuaXNGb3JtdWxhLnNldCghIXRoaXMuY29tcG9uZW50LmNvbmZpZz8uZm9ybXVsYSk7XG5cbiAgICBjb25zdCBwYWRkaW5nID0gdGhpcy5jb21wb25lbnQuY29uZmlnPy5wYWRkaW5nO1xuICAgIHRoaXMucGFkZGluZ1RvcCA9IHBhZGRpbmc/LnRvcCA/PyBERUZBVUxUX0NPTVBPTkVOVF9QQURESU5HO1xuICAgIHRoaXMucGFkZGluZ1JpZ2h0ID0gcGFkZGluZz8ucmlnaHQgPz8gREVGQVVMVF9DT01QT05FTlRfUEFERElORztcbiAgICB0aGlzLnBhZGRpbmdCb3R0b20gPSBwYWRkaW5nPy5ib3R0b20gPz8gREVGQVVMVF9DT01QT05FTlRfUEFERElORztcbiAgICB0aGlzLnBhZGRpbmdMZWZ0ID0gcGFkZGluZz8ubGVmdCA/PyBERUZBVUxUX0NPTVBPTkVOVF9QQURESU5HO1xuXG4gICAgdGhpcy5jb25maWdKc29uID0gSlNPTi5zdHJpbmdpZnkodGhpcy5jb21wb25lbnQuY29uZmlnID8/IHt9LCBudWxsLCAyKTtcblxuICAgIHRoaXMuX3NlZWRLcGlDYXJkKCk7XG5cbiAgICB0aGlzLl9zZWVkRmlsdGVycyh0aGlzLnJlcG9ydCwgdGhpcy5jb21wb25lbnQuaWQpO1xuXG4gICAgLy8gQSBmb3JtdWxhIGhhcyBubyBzdGF0ZW1lbnQgdG8gY29tcGlsZSBhbmQgbm8gY29sdW1ucyB0byBmaWx0ZXIgb24sIGFuZFxuICAgIC8vIHRoZSBzZXJ2ZXIgd291bGQgcmVmdXNlIGJvdGggcmVxdWVzdHMuXG4gICAgaWYgKCF0aGlzLmlzRm9ybXVsYSgpKSB7XG4gICAgICB0aGlzLl9sb2FkQ29sdW1ucygpO1xuICAgICAgdGhpcy5fbG9hZFNxbCgpO1xuICAgIH1cbiAgfVxuXG4gIC8vIEh1bWFuLWZyaWVuZGx5IG5hbWUgZm9yIHRoZSBpbmZlcnJlZCBpbnRlcmZhY2Ugc2hvd24gYmVzaWRlIGVhY2ggY29sdW1uLlxuICBwdWJsaWMgdHlwZUxhYmVsKHR5cGU6IFJlcG9ydEZpbHRlclR5cGUpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLl90eXBlTGFiZWxzW3R5cGVdID8/IHR5cGU7XG4gIH1cblxuICAvLyBDb25maXJtIGFuZCBkZWxldGUgaGVyZSwgd2hpbGUgdGhlIGRpYWxvZyBpcyBzdGlsbCBvcGVuLCB0aGVuIGNsb3NlIHdpdGggYVxuICAvLyBgZGVsZXRlZGAgcmVzdWx0IGZvciB0aGUgcGFnZSB0byBhY3Qgb24g4oCUIHRoZSBzYW1lIHNoYXBlIHRoZSByZXBvcnRcbiAgLy8gc2V0dGluZ3MgZGlhbG9nIHVzZXMgZm9yIGRlbGV0aW5nIGEgcmVwb3J0LlxuICAvL1xuICAvLyBUaGUgY29uZmlybSBzYXlzIGl0IGNhbm5vdCBiZSB1bmRvbmUgYmVjYXVzZSwgZnJvbSB0aGUgVUksIGl0IGNhbm5vdDogdGhlXG4gIC8vIHJvdyBpcyBzb2Z0LWRlbGV0ZWQgc2VydmVyLXNpZGUgYnV0IG5vdGhpbmcgaGVyZSByZXN0b3JlcyBhIGNvbXBvbmVudC5cbiAgLy8gQSB2YWx1ZSdzIGNvbmZpcm0gYWxzbyBzYXlzIHdoYXQgZ29lcyB3aXRoIGl0OiB0aGUgc2VydmVyIHRha2VzIGl0c1xuICAvLyB0b2tlbnMgb3V0IG9mIGV2ZXJ5IHRleHQgb24gaXRzIHBhZ2UsIG5vdCBqdXN0IHRoZSBvbmUgaXQgd2FzIG9wZW5lZCBmcm9tLFxuICAvLyBhbmQgZGVsZXRlcyB0aGUgZm9ybXVsYXMgdGhhdCByZWFkIGl0IChfZGVwZW5kZW50c05vdGUpLlxuICAvL1xuICAvLyBUaGUgcHJvbXB0IHJlbmRlcnMgaXRzIHRlbXBsYXRlIGFzIGh0bWwsIHNvIGV2ZXJ5IG5hbWUgaW4gaXQgaXMgZXNjYXBlZC5cbiAgcHVibGljIGRlbGV0ZSgpOiB2b2lkIHtcbiAgICB0aGlzLl9wcm9tcHQuY29uZmlybSh0aGlzLmlzVmFsdWUoKVxuICAgICAgPyB7XG4gICAgICAgIHRpdGxlOiAnRGVsZXRlIFZhbHVlJyxcbiAgICAgICAgdGVtcGxhdGU6IGBEZWxldGUgdGhlIHZhbHVlIFwiJHtlc2NhcGVIdG1sKHRoaXMuY29tcG9uZW50LnRpdGxlIHx8IHZhbHVlS2V5KHRoaXMuY29tcG9uZW50KSl9XCI/IEl0IGlzIGFsc28gdGFrZW4gb3V0IG9mIGV2ZXJ5IHRleHQgb24gdGhpcyBwYWdlLiBUaGlzIGNhbm5vdCBiZSB1bmRvbmUuJHt0aGlzLl9kZXBlbmRlbnRzTm90ZSgpfWAsXG4gICAgICB9XG4gICAgICA6IHtcbiAgICAgICAgdGl0bGU6ICdEZWxldGUgQ29tcG9uZW50JyxcbiAgICAgICAgdGVtcGxhdGU6IGBBcmUgeW91IHN1cmUgeW91IHdvdWxkIGxpa2UgdG8gZGVsZXRlIFwiJHtlc2NhcGVIdG1sKHRoaXMuY29tcG9uZW50LnRpdGxlIHx8ICd0aGlzIGNvbXBvbmVudCcpfVwiPyBUaGlzIGNhbm5vdCBiZSB1bmRvbmUuYCxcbiAgICAgIH0pXG4gICAgICAucGlwZShcbiAgICAgICAgc3dpdGNoTWFwKCgpID0+IHRoaXMuX3JlcG9ydERhdGEuZGVsZXRlQ29tcG9uZW50KHRoaXMucmVwb3J0LmlkLCB0aGlzLmNvbXBvbmVudC5pZCkpLFxuICAgICAgICB0YXAoKCkgPT4ge1xuICAgICAgICAgIHRoaXMuX21lc3NhZ2Uuc3VjY2Vzcyh0aGlzLmlzVmFsdWUoKSA/ICdWYWx1ZSBkZWxldGVkJyA6ICdDb21wb25lbnQgZGVsZXRlZCcpO1xuICAgICAgICAgIHRoaXMuX2RpYWxvZ1JlZi5jbG9zZSh7IGRlbGV0ZWQ6IHRydWUgfSk7XG4gICAgICAgIH0pLFxuICAgICAgICB0YWtlVW50aWxEZXN0cm95ZWQodGhpcy5fZGVzdHJveVJlZiksXG4gICAgICApXG4gICAgICAuc3Vic2NyaWJlKCk7XG4gIH1cblxuICAvLyBBIHBlcmNlbnQgdGFyZ2V0J3MgYm91bmQsIGluIHRoZSBwZXJjZW50IGl0IGlzIHR5cGVkIGluLiBJdCByZWFkcyB0aGVcbiAgLy8gY29udHJvbCwgd2hpY2ggZnNGb3JtIHZhbGlkYXRlcyBiZWZvcmUgbmdNb2RlbENoYW5nZSB1cGRhdGVzIHRoZSBzaWduYWwuXG4gIHB1YmxpYyB2YWxpZGF0ZVRhcmdldCA9IChjb250cm9sOiBBYnN0cmFjdENvbnRyb2wpOiB2b2lkID0+IHtcbiAgICBjb25zdCB2YWx1ZSA9IHRoaXMuX251bWJlcihjb250cm9sLnZhbHVlKTtcblxuICAgIGlmICh0aGlzLnRhcmdldFBlcmNlbnQoKSAmJiB2YWx1ZSAhPT0gbnVsbCAmJiB2YWx1ZSA+IEtQSV9QRVJDRU5UX1RBUkdFVF9NQVgpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQSBwZXJjZW50IHRhcmdldCBjYW4gYmUgYXQgbW9zdCAxMCwwMDAlJyk7XG4gICAgfVxuICB9O1xuXG4gIHB1YmxpYyBzYXZlID0gKCkgPT4ge1xuICAgIGNvbnN0IHNldHRpbmdzOiBDb21wb25lbnRTZXR0aW5ncyA9IHtcbiAgICAgIC8vIFRoZSBzZXJ2ZXIgdHJpbXMgYSB0aXRsZTsgYSB2YWx1ZSdzIE5hbWUgaXMgd2hhdCBpdHMgY2hpcHMgc2hvdywgc28gaXRcbiAgICAgIC8vIGdvZXMgYXMgdGhlIHNlcnZlciBrZWVwcyBpdC5cbiAgICAgIHRpdGxlOiB0aGlzLmlzVmFsdWUoKSA/IHRoaXMudGl0bGUudHJpbSgpIDogdGhpcy50aXRsZSxcbiAgICAgIHBhZGRpbmc6IHtcbiAgICAgICAgdG9wOiB0aGlzLl9wYWRkaW5nKHRoaXMucGFkZGluZ1RvcCksXG4gICAgICAgIHJpZ2h0OiB0aGlzLl9wYWRkaW5nKHRoaXMucGFkZGluZ1JpZ2h0KSxcbiAgICAgICAgYm90dG9tOiB0aGlzLl9wYWRkaW5nKHRoaXMucGFkZGluZ0JvdHRvbSksXG4gICAgICAgIGxlZnQ6IHRoaXMuX3BhZGRpbmcodGhpcy5wYWRkaW5nTGVmdCksXG4gICAgICB9LFxuICAgIH07XG5cbiAgICAvLyBUaGUgY2FyZCBrZXlzIGdvIGFzIGNvbmZpZyBrZXlzIGJlc2lkZSB0aGUgcGFkZGluZyAoaW5jcmVhc2VJcywgdGFyZ2V0XG4gICAgLy8gYW5kIHNwYXJrbGluZSwgbnVsbCB0byByZW1vdmUgb25lKSwgYW5kIG9ubHkgd2hlbiB0aGV5IGNoYW5nZWQsIHNvIGFcbiAgICAvLyB0aXRsZSBlZGl0IG5ldmVyIHRvdWNoZXMgdGhlbS5cbiAgICBjb25zdCBrcGkgPSB0aGlzLmtwaUNhcmQoKSA/IHRoaXMuX2twaUNhcmRTZXR0aW5ncygpIDogbnVsbDtcbiAgICBjb25zdCBrcGlDaGFuZ2VkID0gISFrcGlcbiAgICAgICYmICFzYW1lS3BpQ2FyZFNldHRpbmdzKGtwaSwga3BpQ2FyZFNldHRpbmdzKHRoaXMuY29tcG9uZW50LmNvbmZpZyBhcyBLcGlDb25maWcpKTtcblxuICAgIHJldHVybiB0aGlzLl9yZXBvcnREYXRhLnVwZGF0ZUNvbXBvbmVudCh0aGlzLnJlcG9ydC5pZCwgdGhpcy5jb21wb25lbnQuaWQsIHtcbiAgICAgIHRpdGxlOiBzZXR0aW5ncy50aXRsZSxcbiAgICAgIC4uLih0aGlzLmlzVmFsdWUoKSA/IHt9IDogeyBwYWRkaW5nOiBzZXR0aW5ncy5wYWRkaW5nIH0pLFxuICAgICAgLi4uKGtwaUNoYW5nZWQgPyBrcGkgOiB7fSksXG4gICAgfSlcbiAgICAgIC5waXBlKFxuICAgICAgICB0YXAoKHJlc3BvbnNlOiBDb21wb25lbnRTZXR0aW5nc1Jlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgLy8gVGhlIGNhcmQgaXMgZHJhd24gZnJvbSB0aGUga2V5cyB0aGUgc2VydmVyIHNhdmVkLCByZWFkIGJhY2sgZnJvbVxuICAgICAgICAgIC8vIHRoZSBjb25maWcgaXQgcmV0dXJucy4gQSBzZXJ2ZXIgdGhhdCByZXR1cm5zIG5vIGNvbmZpZyBkaWQgbm90XG4gICAgICAgICAgLy8gc2F2ZSB0aGVtLCBzbyB0aGUgY2FyZCBrZWVwcyB3aGF0IGl0IGhhZCBhbmQgdGhlIGRpYWxvZyBzYXlzIHNvLlxuICAgICAgICAgIGNvbnN0IHNhdmVkID0ga3BpQ2hhbmdlZCA/IHRoaXMuX3NhdmVkS3BpQ2FyZChyZXNwb25zZSkgOiBudWxsO1xuXG4gICAgICAgICAgaWYgKGtwaUNoYW5nZWQgJiYgIXNhdmVkKSB7XG4gICAgICAgICAgICB0aGlzLl9tZXNzYWdlLndhcm5pbmcoJ0NvbXBvbmVudCBzYXZlZCwgYnV0IHRoZSBzZXJ2ZXIgZGlkIG5vdCBzYXZlIHRoZSBjYXJkIHNldHRpbmdzJyk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuX21lc3NhZ2Uuc3VjY2Vzcyh0aGlzLmlzVmFsdWUoKSA/ICdWYWx1ZSBzYXZlZCcgOiAnQ29tcG9uZW50IHNhdmVkJyk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgdGhpcy5fZGlhbG9nUmVmLmNsb3NlKHsgc2V0dGluZ3M6IHNhdmVkID8geyAuLi5zZXR0aW5ncywga3BpOiBzYXZlZCB9IDogc2V0dGluZ3MgfSk7XG4gICAgICAgIH0pLFxuICAgICAgKTtcbiAgfTtcblxuICAvLyBGbGlwIG9uZSBleHBvc3VyZSAocmVwb3J0IGJhciBvciB0aGlzIGNvbXBvbmVudCkgZm9yIGEgcm93LiBXZSB1cGRhdGUgdGhlXG4gIC8vIHJvdydzIGJvb2xlYW4gZmlyc3Qg4oCUIHNvIHRoZSB0b2dnbGUgc3RheXMgcHV0IHdpdGggbm8gYmxpbmsg4oCUIHRoZW4gcGVyc2lzdFxuICAvLyBhbmQgcmVjb25jaWxlIG9uIHJlbG9hZC4gTmVpdGhlciBvbiDihpIgbm8gZmlsdGVyIChyZW1vdmVkKTsgZWl0aGVyIG9uIOKGkiB0aGVcbiAgLy8gZmlsdGVyIGV4aXN0cyBhdCB0aGUgY29tYmluZWQgbGV2ZWwuIFRoZSBpbnRlcmZhY2UgdHlwZSBpcyBpbmZlcnJlZFxuICAvLyBzZXJ2ZXItc2lkZS4gQSB2YWx1ZSBoYXMgdGhlIHJlcG9ydCBiYXIgdG9nZ2xlIG9ubHksIHdpdGggaXRzIG93biBydWxlc1xuICAvLyAoX3NldFZhbHVlRXhwb3N1cmUpLlxuICBwdWJsaWMgc2V0RXhwb3N1cmUocm93OiBGaWx0ZXJSb3csIHRhcmdldDogJ3JlcG9ydCcgfCAnY29tcG9uZW50Jywgb246IGJvb2xlYW4pOiB2b2lkIHtcbiAgICBpZiAodGhpcy5pc1ZhbHVlKCkpIHtcbiAgICAgIGlmICh0YXJnZXQgPT09ICdyZXBvcnQnKSB7XG4gICAgICAgIHRoaXMuX3NldFZhbHVlRXhwb3N1cmUocm93LCBvbik7XG4gICAgICB9XG5cbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICByb3dbdGFyZ2V0XSA9IG9uO1xuXG4gICAgY29uc3QgZXhpc3RpbmcgPSB0aGlzLl9maWx0ZXJzLmZpbmQoKGZpbHRlcikgPT4gZmlsdGVyLmZpbHRlckNvbHVtbiA9PT0gcm93LmNvbHVtbik7XG5cbiAgICBpZiAoIXJvdy5yZXBvcnQgJiYgIXJvdy5jb21wb25lbnQpIHtcbiAgICAgIGlmIChleGlzdGluZykge1xuICAgICAgICB0aGlzLl9ydW4odGhpcy5fcmVwb3J0RGF0YS5kZWxldGVGaWx0ZXIodGhpcy5yZXBvcnQuaWQsIGV4aXN0aW5nLmlkKSk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBsZXZlbDogUmVwb3J0RmlsdGVyTGV2ZWwgPSByb3cucmVwb3J0ICYmIHJvdy5jb21wb25lbnRcbiAgICAgID8gJ2JvdGgnXG4gICAgICA6IChyb3cucmVwb3J0ID8gJ3JlcG9ydCcgOiAnY29tcG9uZW50Jyk7XG5cbiAgICBpZiAoZXhpc3RpbmcpIHtcbiAgICAgIHRoaXMuX3J1bih0aGlzLl9yZXBvcnREYXRhLnVwZGF0ZUZpbHRlckdyb3VwKHRoaXMucmVwb3J0LmlkLCBleGlzdGluZy5maWx0ZXJHcm91cElkLCB7IGxldmVsIH0pKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5fcnVuKHRoaXMuX3JlcG9ydERhdGEuYWRkRmlsdGVyKHRoaXMucmVwb3J0LmlkLCB0aGlzLmNvbXBvbmVudC5pZCwge1xuICAgICAgICBmaWx0ZXJDb2x1bW46IHJvdy5jb2x1bW4sXG4gICAgICAgIGxhYmVsOiByb3cubGFiZWwsXG4gICAgICAgIGxldmVsLFxuICAgICAgfSkpO1xuICAgIH1cbiAgfVxuXG4gIC8vIEEgdmFsdWUncyByZXBvcnQgYmFyIHRvZ2dsZSwgdGhlIG9ubHkgb25lIGl0IGhhcy4gSXRzIGZpbHRlcidzIGdyb3VwIGlzXG4gIC8vIHJlcG9ydC13aWRlIGFuZCBtYXkgYmUgc2hhcmVkICh0aGUgcmVwb3J0J3MgUGVyaW9kLCBzYXkpLCBhbmQgYSB2YWx1ZSBoYXNcbiAgLy8gbm8gc3RyaXAgb2YgaXRzIG93biwgc28gdGhpcyBuZXZlciBsb3dlcnMgYSBncm91cCdzIGxldmVsOiBvZmYgdW5saW5rc1xuICAvLyB0aGlzIHZhbHVlIGFsb25lIGFuZCB0aGUgZ3JvdXAga2VlcHMgaXRzIG90aGVyIG1lbWJlcnMsIGFuZCBvbiByYWlzZXMgYVxuICAvLyBzdHJpcC1vbmx5IGdyb3VwIHRvIGJvdGgsIGtlZXBpbmcgaXRzIHN0cmlwcywgb3IgYWRkcyB0aGUgdmFsdWUgdG8gYSBuZXdcbiAgLy8gcmVwb3J0LWxldmVsIGdyb3VwLlxuICBwcml2YXRlIF9zZXRWYWx1ZUV4cG9zdXJlKHJvdzogRmlsdGVyUm93LCBvbjogYm9vbGVhbik6IHZvaWQge1xuICAgIHJvdy5yZXBvcnQgPSBvbjtcblxuICAgIGNvbnN0IGV4aXN0aW5nID0gdGhpcy5fZmlsdGVycy5maW5kKChmaWx0ZXIpID0+IGZpbHRlci5maWx0ZXJDb2x1bW4gPT09IHJvdy5jb2x1bW4pO1xuXG4gICAgaWYgKCFvbikge1xuICAgICAgaWYgKGV4aXN0aW5nKSB7XG4gICAgICAgIHRoaXMuX3J1bih0aGlzLl9yZXBvcnREYXRhLmRlbGV0ZUZpbHRlcih0aGlzLnJlcG9ydC5pZCwgZXhpc3RpbmcuaWQpKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmICghZXhpc3RpbmcpIHtcbiAgICAgIHRoaXMuX3J1bih0aGlzLl9yZXBvcnREYXRhLmFkZEZpbHRlcih0aGlzLnJlcG9ydC5pZCwgdGhpcy5jb21wb25lbnQuaWQsIHtcbiAgICAgICAgZmlsdGVyQ29sdW1uOiByb3cuY29sdW1uLFxuICAgICAgICBsYWJlbDogcm93LmxhYmVsLFxuICAgICAgICBsZXZlbDogJ3JlcG9ydCcsXG4gICAgICB9KSk7XG4gICAgfSBlbHNlIGlmICh0aGlzLl9ncm91cHNCeUlkLmdldChleGlzdGluZy5maWx0ZXJHcm91cElkKT8ubGV2ZWwgPT09ICdjb21wb25lbnQnKSB7XG4gICAgICB0aGlzLl9ydW4odGhpcy5fcmVwb3J0RGF0YS51cGRhdGVGaWx0ZXJHcm91cCh0aGlzLnJlcG9ydC5pZCwgZXhpc3RpbmcuZmlsdGVyR3JvdXBJZCwgeyBsZXZlbDogJ2JvdGgnIH0pKTtcbiAgICB9XG4gIH1cblxuICAvLyBXaGF0IGEgZm9ybXVsYSB3b3JrcyBvdXQsIG5hbWluZyBlYWNoIG9wZXJhbmQgYXMgaXRzIGNoaXBzIGRvLiBBbiBvcCB0aGlzXG4gIC8vIHZpZXdlciBkb2VzIG5vdCBrbm93IHJlYWRzIG5vdGhpbmcuXG4gIHByaXZhdGUgX2Zvcm11bGFMaW5lKCk6IHN0cmluZyB7XG4gICAgY29uc3QgZm9ybXVsYSA9IHRoaXMuY29tcG9uZW50LmNvbmZpZz8uZm9ybXVsYTtcbiAgICBjb25zdCBsaW5lID0gZm9ybXVsYSA/IEZPUk1VTEFfTElORVNbZm9ybXVsYS5vcF0gOiB1bmRlZmluZWQ7XG4gICAgY29uc3QgdmFsdWVzID0gdGhpcy5fbGF5ZXJWYWx1ZXMoKTtcblxuICAgIHJldHVybiBsaW5lID8gbGluZShvcGVyYW5kS2V5cyh0aGlzLmNvbXBvbmVudCkubWFwKChrZXkpID0+IHRoaXMuX3ZhbHVlTmFtZSh2YWx1ZXMsIGtleSkpKSA6ICcnO1xuICB9XG5cbiAgLy8gVGhlIHNlbnRlbmNlIGEgcXVlcnkgdmFsdWUncyBkZWxldGUgY29uZmlybSBlbmRzIHdpdGggd2hlbiBmb3JtdWxhcyBvbiBpdHNcbiAgLy8gbGF5ZXIgcmVhZCBpdDogdGhlIHNlcnZlciBkZWxldGVzIHRob3NlIHdpdGggaXQuIEVtcHR5IHdoZW4gbm9uZSBkb2VzLCBhbmRcbiAgLy8gZm9yIGEgZm9ybXVsYSwgd2hvc2Ugb3BlcmFuZHMgc3RheS5cbiAgcHJpdmF0ZSBfZGVwZW5kZW50c05vdGUoKTogc3RyaW5nIHtcbiAgICBpZiAodGhpcy5pc0Zvcm11bGEoKSkge1xuICAgICAgcmV0dXJuICcnO1xuICAgIH1cblxuICAgIGNvbnN0IGtleSA9IHZhbHVlS2V5KHRoaXMuY29tcG9uZW50KTtcbiAgICBjb25zdCBuYW1lcyA9IHRoaXMuX2xheWVyVmFsdWVzKClcbiAgICAgIC5maWx0ZXIoKHZhbHVlKSA9PiBvcGVyYW5kS2V5cyh2YWx1ZSkuaW5jbHVkZXMoa2V5KSlcbiAgICAgIC5tYXAoKHZhbHVlKSA9PiBlc2NhcGVIdG1sKHZhbHVlLnRpdGxlIHx8IHZhbHVlS2V5KHZhbHVlKSkpO1xuXG4gICAgcmV0dXJuIG5hbWVzLmxlbmd0aCA/IGAgVGhlIHZhbHVlcyB3b3JrZWQgb3V0IGZyb20gaXQgYXJlIGRlbGV0ZWQgdG9vOiAke25hbWVzLmpvaW4oJywgJyl9LmAgOiAnJztcbiAgfVxuXG4gIC8vIFRoZSB2YWx1ZXMgb2YgdGhlIGxheWVyIHRoaXMgdmFsdWUgYmVsb25ncyB0bzogdGhlIHBhZ2Ugd2hvc2UgdmFsdWVzIGhvbGRcbiAgLy8gaXQsIGVsc2UgdGhlIG1hc3RlcidzIChhIGhlYWRlciBvciBmb290ZXIgdmFsdWUpLlxuICBwcml2YXRlIF9sYXllclZhbHVlcygpOiBSZXBvcnRDb21wb25lbnRbXSB7XG4gICAgY29uc3QgcGFnZSA9ICh0aGlzLnJlcG9ydC5wYWdlcyA/PyBbXSlcbiAgICAgIC5maW5kKChjYW5kaWRhdGUpID0+IChjYW5kaWRhdGUudmFsdWVzID8/IFtdKS5zb21lKCh2YWx1ZSkgPT4gdmFsdWUuaWQgPT09IHRoaXMuY29tcG9uZW50LmlkKSk7XG5cbiAgICByZXR1cm4gKHBhZ2UgPz8gdGhpcy5yZXBvcnQubWFzdGVyKT8udmFsdWVzID8/IFtdO1xuICB9XG5cbiAgLy8gV2hhdCBhIHZhbHVlIGlzIGNhbGxlZCB3aGVyZSBpdHMgY2hpcHMgc2hvdyBpdDogaXRzIG5hbWUsIGVsc2UgaXRzIGtleS5cbiAgLy8gVGhlIG5ld2VzdCB2YWx1ZSBob2xkcyBhIGtleSwgYXMgaXQgZG9lcyBpbiB0aGUgdGV4dCdzIHRva2Vucy5cbiAgcHJpdmF0ZSBfdmFsdWVOYW1lKHZhbHVlczogUmVwb3J0Q29tcG9uZW50W10sIGtleTogc3RyaW5nKTogc3RyaW5nIHtcbiAgICBjb25zdCB2YWx1ZSA9IHZhbHVlcy5maWx0ZXIoKGNhbmRpZGF0ZSkgPT4gdmFsdWVLZXkoY2FuZGlkYXRlKSA9PT0ga2V5KS5wb3AoKTtcblxuICAgIHJldHVybiB2YWx1ZT8udGl0bGUgfHwga2V5O1xuICB9XG5cbiAgLy8gQSBkZXJpdmVkIEtQSSdzIGNhcmQga2V5cywgZnJvbSBpdHMgY29uZmlnLiBBIHNxbC1tb2RlIEtQSSBjYW5ub3QgY2FycnlcbiAgLy8gdGhlbSwgc28gaXQgZ2V0cyBubyBjYXJkIGZpZWxkcy5cbiAgcHJpdmF0ZSBfc2VlZEtwaUNhcmQoKTogdm9pZCB7XG4gICAgY29uc3QgY29uZmlnID0gKHRoaXMuY29tcG9uZW50LmNvbmZpZyA/PyB7fSkgYXMgS3BpQ29uZmlnO1xuXG4gICAgdGhpcy5rcGlDYXJkLnNldCh0aGlzLmNvbXBvbmVudC50eXBlID09PSAna3BpJyAmJiAhdGhpcy5jb21wb25lbnQuc3FsKTtcbiAgICB0aGlzLmluY3JlYXNlSXMuc2V0KGNvbmZpZy5pbmNyZWFzZUlzID8/IFJlcG9ydENoYW5nZVBvbGFyaXR5Lkdvb2QpO1xuICAgIHRoaXMudGFyZ2V0UGVyY2VudC5zZXQoY29uZmlnLm1lYXN1cmU/LmZvcm1hdCA9PT0gUmVwb3J0VmFsdWVGb3JtYXQuUGVyY2VudFxuICAgICAgJiYgcmVzb2x2ZUZvcm1hdENvbnRleHQodGhpcy5yZXBvcnQpLnJhdGlvUGVyY2VudCk7XG4gICAgdGhpcy50YXJnZXRWYWx1ZS5zZXQodGhpcy5fdGFyZ2V0U2hvd24oY29uZmlnLnRhcmdldD8udmFsdWUgPz8gbnVsbCkpO1xuICAgIHRoaXMudGFyZ2V0TGFiZWwuc2V0KGNvbmZpZy50YXJnZXQ/LmxhYmVsID8/ICcnKTtcbiAgICB0aGlzLnNwYXJrbGluZS5zZXQoISFjb25maWcuc3BhcmtsaW5lKTtcbiAgICB0aGlzLnNwYXJrbGluZUdyYW51bGFyaXR5LnNldChjb25maWcuc3BhcmtsaW5lPy5ncmFudWxhcml0eSA/PyBLUElfU1BBUktMSU5FX0RFRkFVTFRfR1JBTlVMQVJJVFkpO1xuICAgIHRoaXMuc3BhcmtsaW5lUGVyaW9kcy5zZXQoY29uZmlnLnNwYXJrbGluZT8ucGVyaW9kcyA/PyBLUElfU1BBUktMSU5FX0RFRkFVTFRfUEVSSU9EUyk7XG4gIH1cblxuICAvLyBUaGUgY2FyZCBrZXlzIHRoZSBzZXJ2ZXIgc2F2ZWQsIGZyb20gdGhlIGNvbmZpZyBpdHMgcmVzcG9uc2UgY2FycmllcztcbiAgLy8gbnVsbCB3aGVuIGl0IGNhcnJpZXMgbm9uZSAoYSBzZXJ2ZXIgdGhhdCBkb2VzIG5vdCBzYXZlIHRoZW0pLlxuICBwcml2YXRlIF9zYXZlZEtwaUNhcmQocmVzcG9uc2U6IENvbXBvbmVudFNldHRpbmdzUmVzcG9uc2UgfCBudWxsIHwgdW5kZWZpbmVkKTogS3BpQ2FyZFNldHRpbmdzIHwgbnVsbCB7XG4gICAgY29uc3QgY29uZmlnID0gcmVzcG9uc2U/LmNvbmZpZztcblxuICAgIHJldHVybiBjb25maWcgJiYgdHlwZW9mIGNvbmZpZyA9PT0gJ29iamVjdCcgPyBrcGlDYXJkU2V0dGluZ3MoY29uZmlnIGFzIEtwaUNvbmZpZykgOiBudWxsO1xuICB9XG5cbiAgLy8gR29vZCBpcyB3aGF0IGFuIGFic2VudCBpbmNyZWFzZUlzIHJlYWRzLCBzbyBpdCBpcyBzYXZlZCBhcyBhYnNlbnQuXG4gIHByaXZhdGUgX2twaUNhcmRTZXR0aW5ncygpOiBLcGlDYXJkU2V0dGluZ3Mge1xuICAgIGNvbnN0IHRhcmdldCA9IHRoaXMuX251bWJlcih0aGlzLnRhcmdldFZhbHVlKCkpO1xuICAgIGNvbnN0IGxhYmVsID0gdGhpcy50YXJnZXRMYWJlbCgpLnRyaW0oKTtcblxuICAgIHJldHVybiB7XG4gICAgICBpbmNyZWFzZUlzOiB0aGlzLmluY3JlYXNlSXMoKSA9PT0gUmVwb3J0Q2hhbmdlUG9sYXJpdHkuR29vZCA/IG51bGwgOiB0aGlzLmluY3JlYXNlSXMoKSxcbiAgICAgIHRhcmdldDogdGFyZ2V0ID09PSBudWxsID8gbnVsbCA6IHsgdmFsdWU6IHRoaXMuX3RhcmdldFN0b3JlZCh0YXJnZXQpLCBsYWJlbDogbGFiZWwgfHwgbnVsbCB9LFxuICAgICAgc3BhcmtsaW5lOiB0aGlzLnNwYXJrbGluZSgpXG4gICAgICAgID8geyBncmFudWxhcml0eTogdGhpcy5zcGFya2xpbmVHcmFudWxhcml0eSgpLCBwZXJpb2RzOiB0aGlzLl9udW1iZXIodGhpcy5zcGFya2xpbmVQZXJpb2RzKCkpIH1cbiAgICAgICAgOiBudWxsLFxuICAgIH07XG4gIH1cblxuICAvLyBBIHN0b3JlZCByYXRpbyBhcyB0aGUgcGVyY2VudCB0eXBlZCwgcm91bmRlZCBzbyAwLjE1IHJlYWRzIDE1IGFuZCBub3RcbiAgLy8gMTUuMDAwMDAwMDAwMDAwMDAyLlxuICBwcml2YXRlIF90YXJnZXRTaG93bih2YWx1ZTogbnVtYmVyIHwgbnVsbCk6IG51bWJlciB8IG51bGwge1xuICAgIGlmICh2YWx1ZSA9PT0gbnVsbCB8fCAhdGhpcy50YXJnZXRQZXJjZW50KCkpIHtcbiAgICAgIHJldHVybiB2YWx1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gTWF0aC5yb3VuZCh2YWx1ZSAqIDEwMCAqIDFlNikgLyAxZTY7XG4gIH1cblxuICBwcml2YXRlIF90YXJnZXRTdG9yZWQodmFsdWU6IG51bWJlcik6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMudGFyZ2V0UGVyY2VudCgpID8gdmFsdWUgLyAxMDAgOiB2YWx1ZTtcbiAgfVxuXG4gIC8vIEEgdHlwZWQgbnVtYmVyLCBvciBudWxsIHdoZW4gdGhlIGZpZWxkIGlzIGVtcHR5LlxuICBwcml2YXRlIF9udW1iZXIodmFsdWU6IG51bWJlciB8IHN0cmluZyB8IG51bGwpOiBudW1iZXIgfCBudWxsIHtcbiAgICBpZiAodmFsdWUgPT09IG51bGwgfHwgdmFsdWUgPT09ICcnKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICBjb25zdCBudW1iZXIgPSB0eXBlb2YgdmFsdWUgPT09ICdudW1iZXInID8gdmFsdWUgOiBwYXJzZUZsb2F0KHZhbHVlKTtcblxuICAgIHJldHVybiBOdW1iZXIuaXNGaW5pdGUobnVtYmVyKSA/IG51bWJlciA6IG51bGw7XG4gIH1cblxuICAvLyBUaGUgcGFkZGluZyBhcyBhIHJlYWwgbnVtYmVyIGZvciB0aGUgd2lyZS4gZnNNYXNrTnVtYmVyIGhhbmRzIGJhY2sgdGhlXG4gIC8vIHVubWFza2VkIHN0cmluZyBpdCBidWlsdCB3aXRoIGEgZml4ZWQgJy4nIHJhZGl4LCBzbyB0aGlzIGlzIGEgc3RyYWlnaHRcbiAgLy8gcGFyc2UgLSB0aGUgd2hvbGUgcmVhc29uIGZvciB0aGUgbWFzayBpcyB0aGF0IGEgbmF0aXZlIG51bWJlciBpbnB1dCB3b3VsZFxuICAvLyBwYWludCAoYW5kIHJlYWQgYmFjaykgdGhlIHZpZXdlcidzIG93biBsb2NhbGUgc2VwYXJhdG9yIGluc3RlYWQuXG4gIHByaXZhdGUgX3BhZGRpbmcodmFsdWU6IG51bWJlciB8IHN0cmluZyk6IG51bWJlciB7XG4gICAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ251bWJlcicgPyB2YWx1ZSA6IHBhcnNlRmxvYXQodmFsdWUpO1xuICB9XG5cbiAgLy8gUnVuIGEgZmlsdGVyIG11dGF0aW9uLCB0aGVuIHJlbG9hZCB0byByZWNvbmNpbGUgdGhlIG9wdGltaXN0aWMgc3RhdGUuXG4gIHByaXZhdGUgX3J1bihyZXF1ZXN0OiBPYnNlcnZhYmxlPHVua25vd24+KTogdm9pZCB7XG4gICAgcmVxdWVzdC5zdWJzY3JpYmUoe1xuICAgICAgbmV4dDogKCkgPT4gdGhpcy5fYWZ0ZXJNdXRhdGlvbigpLFxuICAgICAgZXJyb3I6IChlcnJvcikgPT4gdGhpcy5fbXV0YXRpb25FcnJvcihlcnJvciksXG4gICAgfSk7XG4gIH1cblxuICAvLyBCdWlsZCB0aGUgcm93IHZpZXctbW9kZWwgZnJvbSB0aGUgbG9hZGVkIGNvbHVtbnMgKyBmaWx0ZXJzL2dyb3Vwcy4gRWFjaFxuICAvLyByb3cncyB0b2dnbGVzIHJlZmxlY3Qgd2hlcmUgaXRzIGZpbHRlciBncm91cCBpcyBjdXJyZW50bHkgZXhwb3NlZC4gQVxuICAvLyB2YWx1ZSdzIHJvd3MgbmV2ZXIgcmVhZCBhcyBvbiBhIGNvbXBvbmVudDogaXQgaGFzIG5vIHN0cmlwLCB3aGF0ZXZlclxuICAvLyBsZXZlbCBhIGdyb3VwIGl0IHNoYXJlcyBpcyBhdC5cbiAgcHJpdmF0ZSBfcmVidWlsZFJvd3MoKTogdm9pZCB7XG4gICAgdGhpcy5yb3dzLnNldCh0aGlzLl9maWx0ZXJhYmxlQ29sdW1ucy5tYXAoKGNvbHVtbikgPT4ge1xuICAgICAgY29uc3QgZmlsdGVyID0gdGhpcy5fZmlsdGVycy5maW5kKChjYW5kaWRhdGUpID0+IGNhbmRpZGF0ZS5maWx0ZXJDb2x1bW4gPT09IGNvbHVtbi5jb2x1bW4pO1xuICAgICAgY29uc3QgbGV2ZWwgPSBmaWx0ZXIgPyB0aGlzLl9ncm91cHNCeUlkLmdldChmaWx0ZXIuZmlsdGVyR3JvdXBJZCk/LmxldmVsIDogdW5kZWZpbmVkO1xuXG4gICAgICByZXR1cm4ge1xuICAgICAgICBjb2x1bW46IGNvbHVtbi5jb2x1bW4sXG4gICAgICAgIHR5cGU6IGNvbHVtbi50eXBlLFxuICAgICAgICBsYWJlbDogZmlsdGVyPy5sYWJlbFxuICAgICAgICAgIHx8IHRoaXMuX2dyb3Vwc0J5SWQuZ2V0KGZpbHRlcj8uZmlsdGVyR3JvdXBJZCA/PyAtMSk/LmxhYmVsXG4gICAgICAgICAgfHwgdGhpcy5faHVtYW5pemUoY29sdW1uLmNvbHVtbiksXG4gICAgICAgIHJlcG9ydDogbGV2ZWwgPT09ICdyZXBvcnQnIHx8IGxldmVsID09PSAnYm90aCcsXG4gICAgICAgIGNvbXBvbmVudDogIXRoaXMuaXNWYWx1ZSgpICYmIChsZXZlbCA9PT0gJ2NvbXBvbmVudCcgfHwgbGV2ZWwgPT09ICdib3RoJyksXG4gICAgICB9O1xuICAgIH0pKTtcbiAgfVxuXG4gIC8vIEFmdGVyIGFueSBmaWx0ZXIgbXV0YXRpb246IHJlLWZldGNoIHRoZSByZXBvcnQgc28gdGhlIGRpYWxvZydzIGZpbHRlciBsaXN0XG4gIC8vIChhbmQgdGhlIHBhcmVudCBjYW52YXMsIG9uIGNsb3NlKSByZWZsZWN0IHRoZSBuZXcgZ3JvdXBzL2xldmVscy5cbiAgcHJpdmF0ZSBfYWZ0ZXJNdXRhdGlvbigpOiB2b2lkIHtcbiAgICB0aGlzLmZpbHRlcnNDaGFuZ2VkLmVtaXQoKTtcblxuICAgIHRoaXMuX3JlcG9ydERhdGEuZ2V0KHRoaXMucmVwb3J0LmlkKVxuICAgICAgLnN1YnNjcmliZSgocmVwb3J0OiBSZXBvcnQpID0+IHtcbiAgICAgICAgdGhpcy5yZXBvcnQgPSByZXBvcnQ7XG4gICAgICAgIHRoaXMuX3NlZWRGaWx0ZXJzKHJlcG9ydCwgdGhpcy5jb21wb25lbnQuaWQpO1xuICAgICAgfSk7XG4gIH1cblxuICBwcml2YXRlIF9tdXRhdGlvbkVycm9yKGVycm9yOiBhbnkpOiB2b2lkIHtcbiAgICB0aGlzLl9tZXNzYWdlLmVycm9yKGVycm9yPy5lcnJvcj8ubWVzc2FnZSA/PyBlcnJvcj8ubWVzc2FnZSA/PyAnRmlsdGVyIG9wZXJhdGlvbiBmYWlsZWQnKTtcbiAgICAvLyBSZS1zZWVkIGZyb20gdGhlIHNlcnZlciBzbyB0aGUgb3B0aW1pc3RpYyB0b2dnbGUgc25hcHMgYmFjayB0byB0cnV0aC5cbiAgICB0aGlzLl9hZnRlck11dGF0aW9uKCk7XG4gIH1cblxuICAvLyBUaGUgY29tcG9uZW50J3MgZmlsdGVycyBhbmQgdGhlIGdyb3VwcyB0aGV5IHNpdCBpbiwgZnJvbSB0aGUgcmVwb3J0IGFzXG4gIC8vIGxhc3QgbG9hZGVkLiBBIHZhbHVlIGlzIGxpc3RlZCBpbiBpdHMgcGFnZSdzIHZhbHVlcywgbm90IGl0cyBjb21wb25lbnRzLlxuICBwcml2YXRlIF9zZWVkRmlsdGVycyhyZXBvcnQ6IFJlcG9ydCwgY29tcG9uZW50SWQ6IG51bWJlcik6IHZvaWQge1xuICAgIHRoaXMuX2dyb3Vwc0J5SWQgPSBuZXcgTWFwKChyZXBvcnQuZmlsdGVyR3JvdXBzID8/IFtdKS5tYXAoKGdyb3VwKSA9PiBbZ3JvdXAuaWQsIGdyb3VwXSkpO1xuXG4gICAgY29uc3QgY29tcG9uZW50ID0gcmVwb3J0Q29tcG9uZW50cyhyZXBvcnQpXG4gICAgICAuZmluZCgoY2FuZGlkYXRlKSA9PiBjYW5kaWRhdGUuaWQgPT09IGNvbXBvbmVudElkKTtcblxuICAgIHRoaXMuX2ZpbHRlcnMgPSBjb21wb25lbnQ/LmZpbHRlcnMgPz8gW107XG4gICAgdGhpcy5fcmVidWlsZFJvd3MoKTtcbiAgfVxuXG4gIC8vIFRoZSBzdGF0ZW1lbnQgdGhlIFNRTCB0YWIgc2hvd3MuIEZldGNoZWQgcmF0aGVyIHRoYW4gcmVhZCBvZmYgdGhlXG4gIC8vIGNvbXBvbmVudDogYSBkZXJpdmVkIGNvbXBvbmVudCBzdG9yZXMgYSBkb2N1bWVudCwgbm90IFNRTCwgc28gaXRzXG4gIC8vIHN0YXRlbWVudCBvbmx5IGV4aXN0cyBvbmNlIHRoZSBiYWNrZW5kIGNvbXBpbGVzIGl0LlxuICAvL1xuICAvLyBMb2FkZWQgaW4gbmdPbkluaXQgYmVzaWRlIHRoZSBjb2x1bW5zLCBOT1Qgb24gdGFiIGFjdGl2YXRpb24uIFRoZSB0YWJzIGFyZVxuICAvLyBub3QgbGF6eSAobm8gbWF0VGFiQ29udGVudCksIGFuZCBzd2l0Y2hpbmcgdGhlIHRhYi1ncm91cCdzIGBbKHNlbGVjdGVkKV1gXG4gIC8vIGJhbmFuYS1ib3ggdG8gYSBvbmUtd2F5IGJpbmRpbmcgcGx1cyAoc2VsZWN0ZWRDaGFuZ2UpIHRvIGdldCBhIGhvb2sgd291bGRcbiAgLy8gYnJlYWsgaXQ6IEZzVGFic0hlYWRlclRhYkdyb3VwRGlyZWN0aXZlIHNlbGYtYXNzaWducyBgdGhpcy5zZWxlY3RlZGAgYmVmb3JlXG4gIC8vIGl0IGVtaXRzLCBzbyB0aGUgZXZlbnQgaXMgZmlsdGVyZWQgb3V0IGFuZCB0aGUgbG9hZCB3b3VsZCBuZXZlciBmaXJlLiBPbmVcbiAgLy8gc21hbGwgcmVxdWVzdCB3aGVuIGEgZGlhbG9nIG9wZW5zIGlzIG5vdCB3b3J0aCB0aGF0IHJpc2suXG4gIHByaXZhdGUgX2xvYWRTcWwoKTogdm9pZCB7XG4gICAgdGhpcy5fcmVwb3J0RGF0YS5jb21wb25lbnRTcWwodGhpcy5yZXBvcnQuaWQsIHRoaXMuY29tcG9uZW50LmlkKVxuICAgICAgLnN1YnNjcmliZSh7XG4gICAgICAgIG5leHQ6IChwcmV2aWV3OiBSZXBvcnRDb21wb25lbnRTcWwpID0+IHtcbiAgICAgICAgICB0aGlzLnNxbC5zZXQocHJldmlldz8uc3FsID8/IG51bGwpO1xuICAgICAgICAgIHRoaXMuc3FsQmFzZWxpbmUuc2V0KCEhcHJldmlldz8uYmFzZWxpbmUpO1xuICAgICAgICAgIHRoaXMuc3FsVGltZXpvbmUuc2V0KHByZXZpZXc/LnRpbWV6b25lIHx8ICdVVEMnKTtcbiAgICAgICAgICB0aGlzLnNxbEVycm9yLnNldChwcmV2aWV3Py5lcnJvciA/PyBudWxsKTtcbiAgICAgICAgfSxcbiAgICAgICAgZXJyb3I6IChlcnJvcikgPT4ge1xuICAgICAgICAgIHRoaXMuc3FsLnNldChudWxsKTtcbiAgICAgICAgICB0aGlzLnNxbEVycm9yLnNldChlcnJvcj8uZXJyb3I/Lm1lc3NhZ2UgPz8gJ0NvdWxkIG5vdCByZWFkIHRoZSBjb21wb25lbnQgU1FMJyk7XG4gICAgICAgIH0sXG4gICAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgX2xvYWRDb2x1bW5zKCk6IHZvaWQge1xuICAgIHRoaXMuX3JlcG9ydERhdGEuY29tcG9uZW50Q29sdW1ucyh0aGlzLnJlcG9ydC5pZCwgdGhpcy5jb21wb25lbnQuaWQpXG4gICAgICAuc3Vic2NyaWJlKHtcbiAgICAgICAgbmV4dDogKGNvbHVtbnM6IFJlcG9ydEZpbHRlcmFibGVDb2x1bW5bXSkgPT4ge1xuICAgICAgICAgIHRoaXMuX2ZpbHRlcmFibGVDb2x1bW5zID0gY29sdW1ucyA/PyBbXTtcbiAgICAgICAgICB0aGlzLl9yZWJ1aWxkUm93cygpO1xuICAgICAgICB9LFxuICAgICAgICBlcnJvcjogKGVycm9yKSA9PiB7XG4gICAgICAgICAgdGhpcy5jb2x1bW5zRXJyb3Iuc2V0KGVycm9yPy5lcnJvcj8ubWVzc2FnZSA/PyAnQ291bGQgbm90IHJlYWQgdGhlIGNvbXBvbmVudCBjb2x1bW5zJyk7XG4gICAgICAgIH0sXG4gICAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgX2h1bWFuaXplKGNvbHVtbjogc3RyaW5nKTogc3RyaW5nIHtcbiAgICByZXR1cm4gY29sdW1uXG4gICAgICAucmVwbGFjZSgvW19cXC1dKy9nLCAnICcpXG4gICAgICAucmVwbGFjZSgvXFxzKy9nLCAnICcpXG4gICAgICAudHJpbSgpXG4gICAgICAucmVwbGFjZSgvXFxiXFx3L2csIChjaGFyYWN0ZXIpID0+IGNoYXJhY3Rlci50b1VwcGVyQ2FzZSgpKTtcbiAgfVxufVxuIiwiPGZvcm1cbiAgICBmc0Zvcm1cbiAgICBbc3VibWl0XT1cInNhdmVcIj5cbiAgPGZzLWRpYWxvZz5cbiAgICA8aDEgbWF0LWRpYWxvZy10aXRsZT5cbiAgICAgIHt7IGNvbXBvbmVudC50aXRsZSB8fCAoaXNWYWx1ZSgpID8gJ1ZhbHVlJyA6ICdDb21wb25lbnQnKSB9fVxuICAgIDwvaDE+XG4gICAgPG1hdC1kaWFsb2ctY29udGVudD5cbiAgICAgIDxtYXQtdGFiLWdyb3VwIFsoc2VsZWN0ZWQpXT1cInNlbGVjdGVkVGFiXCI+XG4gICAgICAgIDxtYXQtdGFiXG4gICAgICAgICAgICBsYWJlbD1cIlNldHRpbmdzXCJcbiAgICAgICAgICAgIG5hbWU9XCJzZXR0aW5nc1wiPlxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJmcy1jb2x1bW4gdGFiLWJvZHlcIj5cbiAgICAgICAgICAgIDxtYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgICAgPG1hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICB7eyBpc1ZhbHVlKCkgPyAnTmFtZScgOiAnVGl0bGUnIH19XG4gICAgICAgICAgICAgIDwvbWF0LWxhYmVsPlxuICAgICAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgICAgICBtYXRJbnB1dFxuICAgICAgICAgICAgICAgIFsobmdNb2RlbCldPVwidGl0bGVcIlxuICAgICAgICAgICAgICAgIG5hbWU9XCJ0aXRsZVwiXG4gICAgICAgICAgICAgICAgW2ZzRm9ybVJlcXVpcmVkXT1cImlzVmFsdWUoKVwiPlxuICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgIDwhLS0gQSBmb3JtdWxhIHZhbHVlIGlzIHJlYWQtb25seSBiZXlvbmQgaXRzIG5hbWU6IHdoYXQgaXQgd29ya3NcbiAgICAgICAgICAgICAgICAgb3V0IGlzIHRoZSBBSSdzIHRvIGNoYW5nZS4gQSBmb3JtdWxhIHRoaXMgdmlld2VyIGNhbm5vdFxuICAgICAgICAgICAgICAgICByZWFkIGhhcyBubyBsaW5lLCBhbmQgbm8gcm93LiAtLT5cbiAgICAgICAgICAgIEBpZiAoZm9ybXVsYUxpbmUoKSkge1xuICAgICAgICAgICAgICA8ZnMtbGFiZWwtZmllbGQ+XG4gICAgICAgICAgICAgICAgPGZzLWxhYmVsPlxuICAgICAgICAgICAgICAgICAgRm9ybXVsYVxuICAgICAgICAgICAgICAgIDwvZnMtbGFiZWw+XG4gICAgICAgICAgICAgICAge3sgZm9ybXVsYUxpbmUoKSB9fVxuICAgICAgICAgICAgICAgIDxmcy1sYWJlbC1tZXNzYWdlPlxuICAgICAgICAgICAgICAgICAgV29ya2VkIG91dCBvbiB0aGUgc2VydmVyOyBpdCBmb2xsb3dzIHRoZSBmaWx0ZXJzIG9mIHRoZSB2YWx1ZXMgaXQgcmVhZHMuXG4gICAgICAgICAgICAgICAgPC9mcy1sYWJlbC1tZXNzYWdlPlxuICAgICAgICAgICAgICA8L2ZzLWxhYmVsLWZpZWxkPlxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgPCEtLSBBIHZhbHVlIHNpdHMgaW5zaWRlIGEgdGV4dCBibG9jaydzIHdvcmRzOiBubyBib3gsIG5vIHBhZGRpbmcuIC0tPlxuICAgICAgICAgICAgQGlmICghaXNWYWx1ZSgpKSB7XG4gICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJzdWJoZWFkaW5nLTJcIj5cbiAgICAgICAgICAgICAgICBQYWRkaW5nXG4gICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZ2VvbWV0cnktcm93XCI+XG4gICAgICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgICAgICAgICAgPG1hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICAgICAgVG9wXG4gICAgICAgICAgICAgICAgICA8L21hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICAgIDxpbnB1dFxuICAgICAgICAgICAgICAgICAgICBtYXRJbnB1dFxuICAgICAgICAgICAgICAgICAgICBmc01hc2tOdW1iZXJcbiAgICAgICAgICAgICAgICAgICAgW3NjYWxlXT1cIjNcIlxuICAgICAgICAgICAgICAgICAgICBbKG5nTW9kZWwpXT1cInBhZGRpbmdUb3BcIlxuICAgICAgICAgICAgICAgICAgICBuYW1lPVwicGFkZGluZ1RvcFwiXG4gICAgICAgICAgICAgICAgICAgIFtmc0Zvcm1NaW5dPVwiMFwiPlxuICAgICAgICAgICAgICAgICAgPGRpdiBtYXRUZXh0U3VmZml4PlxuICAgICAgICAgICAgICAgICAgICBpblxuICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgICAgICAgICA8bWF0LWxhYmVsPlxuICAgICAgICAgICAgICAgICAgICBSaWdodFxuICAgICAgICAgICAgICAgICAgPC9tYXQtbGFiZWw+XG4gICAgICAgICAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgICAgICAgICAgbWF0SW5wdXRcbiAgICAgICAgICAgICAgICAgICAgZnNNYXNrTnVtYmVyXG4gICAgICAgICAgICAgICAgICAgIFtzY2FsZV09XCIzXCJcbiAgICAgICAgICAgICAgICAgICAgWyhuZ01vZGVsKV09XCJwYWRkaW5nUmlnaHRcIlxuICAgICAgICAgICAgICAgICAgICBuYW1lPVwicGFkZGluZ1JpZ2h0XCJcbiAgICAgICAgICAgICAgICAgICAgW2ZzRm9ybU1pbl09XCIwXCI+XG4gICAgICAgICAgICAgICAgICA8ZGl2IG1hdFRleHRTdWZmaXg+XG4gICAgICAgICAgICAgICAgICAgIGluXG4gICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgICAgICAgIDxtYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgICAgICAgIDxtYXQtbGFiZWw+XG4gICAgICAgICAgICAgICAgICAgIEJvdHRvbVxuICAgICAgICAgICAgICAgICAgPC9tYXQtbGFiZWw+XG4gICAgICAgICAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgICAgICAgICAgbWF0SW5wdXRcbiAgICAgICAgICAgICAgICAgICAgZnNNYXNrTnVtYmVyXG4gICAgICAgICAgICAgICAgICAgIFtzY2FsZV09XCIzXCJcbiAgICAgICAgICAgICAgICAgICAgWyhuZ01vZGVsKV09XCJwYWRkaW5nQm90dG9tXCJcbiAgICAgICAgICAgICAgICAgICAgbmFtZT1cInBhZGRpbmdCb3R0b21cIlxuICAgICAgICAgICAgICAgICAgICBbZnNGb3JtTWluXT1cIjBcIj5cbiAgICAgICAgICAgICAgICAgIDxkaXYgbWF0VGV4dFN1ZmZpeD5cbiAgICAgICAgICAgICAgICAgICAgaW5cbiAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgICAgICAgICAgPG1hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICAgICAgTGVmdFxuICAgICAgICAgICAgICAgICAgPC9tYXQtbGFiZWw+XG4gICAgICAgICAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgICAgICAgICAgbWF0SW5wdXRcbiAgICAgICAgICAgICAgICAgICAgZnNNYXNrTnVtYmVyXG4gICAgICAgICAgICAgICAgICAgIFtzY2FsZV09XCIzXCJcbiAgICAgICAgICAgICAgICAgICAgWyhuZ01vZGVsKV09XCJwYWRkaW5nTGVmdFwiXG4gICAgICAgICAgICAgICAgICAgIG5hbWU9XCJwYWRkaW5nTGVmdFwiXG4gICAgICAgICAgICAgICAgICAgIFtmc0Zvcm1NaW5dPVwiMFwiPlxuICAgICAgICAgICAgICAgICAgPGRpdiBtYXRUZXh0U3VmZml4PlxuICAgICAgICAgICAgICAgICAgICBpblxuICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICA8IS0tIEEgZGVyaXZlZCBLUEkncyBjYXJkOiB3aGF0IGEgcmlzZSBtZWFucywgYSB0YXJnZXQgYW5kIGFcbiAgICAgICAgICAgICAgICAgc3BhcmtsaW5lLiBUaGUgc2VydmVyIGNvbXB1dGVzIHRoZSBwcm9ncmVzcyBhbmQgdGhlIHBvaW50cy4gLS0+XG4gICAgICAgICAgICBAaWYgKGtwaUNhcmQoKSkge1xuICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwic3ViaGVhZGluZy0yXCI+XG4gICAgICAgICAgICAgICAgQ2FyZFxuICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkIGNsYXNzPVwiZnVsbC13aWR0aFwiPlxuICAgICAgICAgICAgICAgIDxtYXQtbGFiZWw+XG4gICAgICAgICAgICAgICAgICBJbmNyZWFzZSBpc1xuICAgICAgICAgICAgICAgIDwvbWF0LWxhYmVsPlxuICAgICAgICAgICAgICAgIDxtYXQtc2VsZWN0XG4gICAgICAgICAgICAgICAgICAgIFtuZ01vZGVsXT1cImluY3JlYXNlSXMoKVwiXG4gICAgICAgICAgICAgICAgICAgIChuZ01vZGVsQ2hhbmdlKT1cImluY3JlYXNlSXMuc2V0KCRldmVudClcIlxuICAgICAgICAgICAgICAgICAgICBuYW1lPVwiaW5jcmVhc2VJc1wiPlxuICAgICAgICAgICAgICAgICAgQGZvciAob3B0aW9uIG9mIGtwaVBvbGFyaXR5T3B0aW9uczsgdHJhY2sgb3B0aW9uLnZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIDxtYXQtb3B0aW9uIFt2YWx1ZV09XCJvcHRpb24udmFsdWVcIj5cbiAgICAgICAgICAgICAgICAgICAgICB7eyBvcHRpb24ubmFtZSB9fVxuICAgICAgICAgICAgICAgICAgICA8L21hdC1vcHRpb24+XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgPC9tYXQtc2VsZWN0PlxuICAgICAgICAgICAgICAgIDxtYXQtaGludD5cbiAgICAgICAgICAgICAgICAgIENvbG9ycyB0aGUgY2hhbmdlIGFuZCBkZWNpZGVzIHdoZW4gdGhlIHRhcmdldCBpcyBtZXQuXG4gICAgICAgICAgICAgICAgPC9tYXQtaGludD5cbiAgICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkIGNsYXNzPVwiZnVsbC13aWR0aFwiPlxuICAgICAgICAgICAgICAgIDxtYXQtbGFiZWw+XG4gICAgICAgICAgICAgICAgICBUYXJnZXRcbiAgICAgICAgICAgICAgICA8L21hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgICAgICAgIG1hdElucHV0XG4gICAgICAgICAgICAgICAgICBmc01hc2tOdW1iZXJcbiAgICAgICAgICAgICAgICAgIFtzY2FsZV09XCI2XCJcbiAgICAgICAgICAgICAgICAgIFtzaWduZWRdPVwidHJ1ZVwiXG4gICAgICAgICAgICAgICAgICBbbmdNb2RlbF09XCJ0YXJnZXRWYWx1ZSgpXCJcbiAgICAgICAgICAgICAgICAgIChuZ01vZGVsQ2hhbmdlKT1cInRhcmdldFZhbHVlLnNldCgkZXZlbnQpXCJcbiAgICAgICAgICAgICAgICAgIG5hbWU9XCJ0YXJnZXRWYWx1ZVwiXG4gICAgICAgICAgICAgICAgICBbdmFsaWRhdGVdPVwidmFsaWRhdGVUYXJnZXRcIj5cbiAgICAgICAgICAgICAgICBAaWYgKHRhcmdldFBlcmNlbnQoKSkge1xuICAgICAgICAgICAgICAgICAgPGRpdiBtYXRUZXh0U3VmZml4PlxuICAgICAgICAgICAgICAgICAgICAlXG4gICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgPG1hdC1oaW50PlxuICAgICAgICAgICAgICAgICAgVGhlIHZhbHVlIHRvIHJlYWNoLiBMZWF2ZSBlbXB0eSBmb3Igbm8gdGFyZ2V0LlxuICAgICAgICAgICAgICAgIDwvbWF0LWhpbnQ+XG4gICAgICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgICAgIEBpZiAoaGFzVGFyZ2V0KCkpIHtcbiAgICAgICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgY2xhc3M9XCJmdWxsLXdpZHRoXCI+XG4gICAgICAgICAgICAgICAgICA8bWF0LWxhYmVsPlxuICAgICAgICAgICAgICAgICAgICBUYXJnZXQgbGFiZWxcbiAgICAgICAgICAgICAgICAgIDwvbWF0LWxhYmVsPlxuICAgICAgICAgICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICAgICAgICAgIG1hdElucHV0XG4gICAgICAgICAgICAgICAgICAgIFtuZ01vZGVsXT1cInRhcmdldExhYmVsKClcIlxuICAgICAgICAgICAgICAgICAgICAobmdNb2RlbENoYW5nZSk9XCJ0YXJnZXRMYWJlbC5zZXQoJGV2ZW50KVwiXG4gICAgICAgICAgICAgICAgICAgIG5hbWU9XCJ0YXJnZXRMYWJlbFwiPlxuICAgICAgICAgICAgICAgICAgPG1hdC1oaW50PlxuICAgICAgICAgICAgICAgICAgICBTaG93biBiZWZvcmUgdGhlIHRhcmdldCwgc3VjaCBhcyBHb2FsLiBFbXB0eSByZWFkcyBUYXJnZXQuXG4gICAgICAgICAgICAgICAgICA8L21hdC1oaW50PlxuICAgICAgICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgPGZzLWxhYmVsLWZpZWxkPlxuICAgICAgICAgICAgICAgIDxtYXQtc2xpZGUtdG9nZ2xlXG4gICAgICAgICAgICAgICAgICAgIFtuZ01vZGVsXT1cInNwYXJrbGluZSgpXCJcbiAgICAgICAgICAgICAgICAgICAgKG5nTW9kZWxDaGFuZ2UpPVwic3BhcmtsaW5lLnNldCgkZXZlbnQpXCJcbiAgICAgICAgICAgICAgICAgICAgbmFtZT1cInNwYXJrbGluZVwiPlxuICAgICAgICAgICAgICAgICAgU3BhcmtsaW5lXG4gICAgICAgICAgICAgICAgPC9tYXQtc2xpZGUtdG9nZ2xlPlxuICAgICAgICAgICAgICAgIDxtYXQtaGludD5cbiAgICAgICAgICAgICAgICAgIEEgc21hbGwgdHJlbmQgbGluZSBvZiB0aGUgdmFsdWUgb3ZlciBpdHMgbGFzdCBwZXJpb2RzLlxuICAgICAgICAgICAgICAgIDwvbWF0LWhpbnQ+XG4gICAgICAgICAgICAgIDwvZnMtbGFiZWwtZmllbGQ+XG4gICAgICAgICAgICAgIEBpZiAoc3BhcmtsaW5lKCkpIHtcbiAgICAgICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgY2xhc3M9XCJmdWxsLXdpZHRoXCI+XG4gICAgICAgICAgICAgICAgICA8bWF0LWxhYmVsPlxuICAgICAgICAgICAgICAgICAgICBTcGFya2xpbmUgcGVyaW9kXG4gICAgICAgICAgICAgICAgICA8L21hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICAgIDxtYXQtc2VsZWN0XG4gICAgICAgICAgICAgICAgICAgICAgW25nTW9kZWxdPVwic3BhcmtsaW5lR3JhbnVsYXJpdHkoKVwiXG4gICAgICAgICAgICAgICAgICAgICAgKG5nTW9kZWxDaGFuZ2UpPVwic3BhcmtsaW5lR3JhbnVsYXJpdHkuc2V0KCRldmVudClcIlxuICAgICAgICAgICAgICAgICAgICAgIG5hbWU9XCJzcGFya2xpbmVHcmFudWxhcml0eVwiPlxuICAgICAgICAgICAgICAgICAgICBAZm9yIChvcHRpb24gb2YgZ3JhbnVsYXJpdHlPcHRpb25zOyB0cmFjayBvcHRpb24udmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICA8bWF0LW9wdGlvbiBbdmFsdWVdPVwib3B0aW9uLnZhbHVlXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICB7eyBvcHRpb24ubmFtZSB9fVxuICAgICAgICAgICAgICAgICAgICAgIDwvbWF0LW9wdGlvbj5cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgPC9tYXQtc2VsZWN0PlxuICAgICAgICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkIGNsYXNzPVwiZnVsbC13aWR0aFwiPlxuICAgICAgICAgICAgICAgICAgPG1hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICAgICAgU3BhcmtsaW5lIHBlcmlvZHNcbiAgICAgICAgICAgICAgICAgIDwvbWF0LWxhYmVsPlxuICAgICAgICAgICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICAgICAgICAgIG1hdElucHV0XG4gICAgICAgICAgICAgICAgICAgIGZzTWFza051bWJlclxuICAgICAgICAgICAgICAgICAgICBbc2NhbGVdPVwiMFwiXG4gICAgICAgICAgICAgICAgICAgIFtuZ01vZGVsXT1cInNwYXJrbGluZVBlcmlvZHMoKVwiXG4gICAgICAgICAgICAgICAgICAgIChuZ01vZGVsQ2hhbmdlKT1cInNwYXJrbGluZVBlcmlvZHMuc2V0KCRldmVudClcIlxuICAgICAgICAgICAgICAgICAgICBuYW1lPVwic3BhcmtsaW5lUGVyaW9kc1wiXG4gICAgICAgICAgICAgICAgICAgIFtmc0Zvcm1SZXF1aXJlZF09XCJ0cnVlXCJcbiAgICAgICAgICAgICAgICAgICAgW2ZzRm9ybUludGVnZXJdPVwidHJ1ZVwiXG4gICAgICAgICAgICAgICAgICAgIFtmc0Zvcm1NaW5dPVwic3BhcmtsaW5lTWluUGVyaW9kc1wiXG4gICAgICAgICAgICAgICAgICAgIFtmc0Zvcm1NYXhdPVwic3BhcmtsaW5lTWF4UGVyaW9kc1wiPlxuICAgICAgICAgICAgICAgICAgPG1hdC1oaW50PlxuICAgICAgICAgICAgICAgICAgICBIb3cgbWFueSBwZXJpb2RzIHRoZSBsaW5lIGNvdmVycywge3sgc3BhcmtsaW5lTWluUGVyaW9kcyB9fSB0byB7eyBzcGFya2xpbmVNYXhQZXJpb2RzIH19LlxuICAgICAgICAgICAgICAgICAgPC9tYXQtaGludD5cbiAgICAgICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvbWF0LXRhYj5cbiAgICAgICAgPCEtLSBBIGZvcm11bGEgcnVucyBubyBzdGF0ZW1lbnQgYW5kIGZvbGxvd3MgdGhlIGZpbHRlcnMgb2YgdGhlIHZhbHVlc1xuICAgICAgICAgICAgIGl0IHJlYWRzLCBzbyBpdCBoYXMgbmVpdGhlciBhIEZpbHRlcnMgbm9yIGFuIFNRTCB0YWIuIC0tPlxuICAgICAgICBAaWYgKCFpc0Zvcm11bGEoKSkge1xuICAgICAgICAgIDxtYXQtdGFiXG4gICAgICAgICAgICAgIGxhYmVsPVwiRmlsdGVyc1wiXG4gICAgICAgICAgICAgIG5hbWU9XCJmaWx0ZXJzXCI+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwidGFiLWJvZHlcIj5cbiAgICAgICAgICAgICAgQGlmIChjb2x1bW5zRXJyb3IoKSkge1xuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJmaWx0ZXJzLWVtcHR5IGVycm9yXCI+XG4gICAgICAgICAgICAgICAgICB7eyBjb2x1bW5zRXJyb3IoKSB9fVxuICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICB9IEBlbHNlIGlmIChyb3dzKCkubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgPCEtLSBFdmVyeSBmaWx0ZXJhYmxlIGNvbHVtbi4gVG9nZ2xlIHdoZXJlIGl0cyBjb250cm9sIHNob3dzOiBpblxuICAgICAgICAgICAgICAgICAgICAgdGhlIHJlcG9ydCBiYXIsIG9uIHRoaXMgY29tcG9uZW50LCBib3RoLCBvciBuZWl0aGVyLiBUaGVcbiAgICAgICAgICAgICAgICAgICAgIGludGVyZmFjZSAoZGF0ZSByYW5nZSB2cyB2YWx1ZSBwaWNrZXIpIGZvbGxvd3MgdGhlIGRhdGEuXG4gICAgICAgICAgICAgICAgICAgICBBIHZhbHVlIHNpdHMgaW5zaWRlIHRleHQgYW5kIGhhcyBubyBjb21wb25lbnQgdG8gc2hvdyBhXG4gICAgICAgICAgICAgICAgICAgICBjb250cm9sIG9uLCBzbyBpdCBnZXRzIHRoZSByZXBvcnQgYmFyIGNvbHVtbiBvbmx5LiAtLT5cbiAgICAgICAgICAgICAgICA8dGFibGUgY2xhc3M9XCJmaWx0ZXItdGFibGVcIj5cbiAgICAgICAgICAgICAgICAgIDx0aGVhZD5cbiAgICAgICAgICAgICAgICAgICAgPHRyPlxuICAgICAgICAgICAgICAgICAgICAgIDx0aCBjbGFzcz1cImZpbHRlci1jb2wtbmFtZVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgRmlsdGVyXG4gICAgICAgICAgICAgICAgICAgICAgPC90aD5cbiAgICAgICAgICAgICAgICAgICAgICA8dGggY2xhc3M9XCJmaWx0ZXItY29sLXR5cGVcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgIFR5cGVcbiAgICAgICAgICAgICAgICAgICAgICA8L3RoPlxuICAgICAgICAgICAgICAgICAgICAgIDx0aCBjbGFzcz1cImZpbHRlci1jb2wtdG9nZ2xlXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICBSZXBvcnQgYmFyXG4gICAgICAgICAgICAgICAgICAgICAgPC90aD5cbiAgICAgICAgICAgICAgICAgICAgICBAaWYgKCFpc1ZhbHVlKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIDx0aCBjbGFzcz1cImZpbHRlci1jb2wtdG9nZ2xlXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgIFRoaXMgY29tcG9uZW50XG4gICAgICAgICAgICAgICAgICAgICAgICA8L3RoPlxuICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgPC90cj5cbiAgICAgICAgICAgICAgICAgIDwvdGhlYWQ+XG4gICAgICAgICAgICAgICAgICA8dGJvZHk+XG4gICAgICAgICAgICAgICAgICAgIEBmb3IgKHJvdyBvZiByb3dzKCk7IHRyYWNrIHJvdy5jb2x1bW4pIHtcbiAgICAgICAgICAgICAgICAgICAgICA8dHI+XG4gICAgICAgICAgICAgICAgICAgICAgICA8dGQgY2xhc3M9XCJmaWx0ZXItY29sLW5hbWVcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAge3sgcm93LmxhYmVsIH19XG4gICAgICAgICAgICAgICAgICAgICAgICA8L3RkPlxuICAgICAgICAgICAgICAgICAgICAgICAgPHRkIGNsYXNzPVwiZmlsdGVyLWNvbC10eXBlXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHt7IHR5cGVMYWJlbChyb3cudHlwZSkgfX1cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvdGQ+XG4gICAgICAgICAgICAgICAgICAgICAgICA8dGQgY2xhc3M9XCJmaWx0ZXItY29sLXRvZ2dsZVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICA8bWF0LXNsaWRlLXRvZ2dsZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtuZ01vZGVsXT1cInJvdy5yZXBvcnRcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIChuZ01vZGVsQ2hhbmdlKT1cInNldEV4cG9zdXJlKHJvdywgJ3JlcG9ydCcsICRldmVudClcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtuZ01vZGVsT3B0aW9uc109XCJ7IHN0YW5kYWxvbmU6IHRydWUgfVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0VG9vbHRpcD1cIlNob3cgaW4gdGhlIHJlcG9ydCBiYXJcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgPC9tYXQtc2xpZGUtdG9nZ2xlPlxuICAgICAgICAgICAgICAgICAgICAgICAgPC90ZD5cbiAgICAgICAgICAgICAgICAgICAgICAgIEBpZiAoIWlzVmFsdWUoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICA8dGQgY2xhc3M9XCJmaWx0ZXItY29sLXRvZ2dsZVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxtYXQtc2xpZGUtdG9nZ2xlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbbmdNb2RlbF09XCJyb3cuY29tcG9uZW50XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChuZ01vZGVsQ2hhbmdlKT1cInNldEV4cG9zdXJlKHJvdywgJ2NvbXBvbmVudCcsICRldmVudClcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW25nTW9kZWxPcHRpb25zXT1cInsgc3RhbmRhbG9uZTogdHJ1ZSB9XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hdFRvb2x0aXA9XCJTaG93IG9uIHRoaXMgY29tcG9uZW50XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9tYXQtc2xpZGUtdG9nZ2xlPlxuICAgICAgICAgICAgICAgICAgICAgICAgICA8L3RkPlxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgIDwvdHI+XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIDwvdGJvZHk+XG4gICAgICAgICAgICAgICAgPC90YWJsZT5cbiAgICAgICAgICAgICAgfSBAZWxzZSB7XG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImZpbHRlcnMtZW1wdHlcIj5cbiAgICAgICAgICAgICAgICAgIFRoaXMgY29tcG9uZW50IGhhcyBubyBmaWx0ZXJhYmxlIGNvbHVtbnMgeWV0IOKAlCBnaXZlIGl0IHNvbWUgU1FMIGZpcnN0LlxuICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICA8L21hdC10YWI+XG4gICAgICAgICAgPG1hdC10YWJcbiAgICAgICAgICAgICAgbGFiZWw9XCJTUUxcIlxuICAgICAgICAgICAgICBuYW1lPVwic3FsXCI+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwidGFiLWJvZHlcIj5cbiAgICAgICAgICAgICAgQGlmIChzcWxFcnJvcigpKSB7XG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImZpbHRlcnMtZW1wdHkgZXJyb3JcIj5cbiAgICAgICAgICAgICAgICAgIHt7IHNxbEVycm9yKCkgfX1cbiAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgfSBAZWxzZSBpZiAoc3FsKCkpIHtcbiAgICAgICAgICAgICAgICBAaWYgKHNxbEJhc2VsaW5lKCkpIHtcbiAgICAgICAgICAgICAgICAgIDwhLS0gQSBkZXJpdmVkIGNvbXBvbmVudCdzIHN0YXRlbWVudCBpcyBjb21waWxlZCBmcm9tIGl0c1xuICAgICAgICAgICAgICAgICAgICAgICBkb2N1bWVudCB3aXRoIG5vIHZpZXdlciBzdGF0ZSwgc28gaXQgaXMgbm90IGJ5dGUtZm9yLWJ5dGVcbiAgICAgICAgICAgICAgICAgICAgICAgd2hhdCBwcm9kdWNlZCB0aGUgbnVtYmVycyBvbiBzY3JlZW4uIFNhaWQgaGVyZSByYXRoZXIgdGhhblxuICAgICAgICAgICAgICAgICAgICAgICBsZWZ0IGZvciB0aGUgcmVhZGVyIHRvIGRpc2NvdmVyLiAtLT5cbiAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJmaWx0ZXJzLWVtcHR5XCI+XG4gICAgICAgICAgICAgICAgICAgIENvbXBpbGVkIGZyb20gdGhpcyBjb21wb25lbnQncyBxdWVyeSDigJQgbm8gZmlsdGVycyBhcHBsaWVkLCB0aW1lcyBpbiB7eyBzcWxUaW1lem9uZSgpIH19LlxuICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIDxwcmUgY2xhc3M9XCJjb2RlLWJsb2NrXCI+e3sgc3FsKCkgfX08L3ByZT5cbiAgICAgICAgICAgICAgfSBAZWxzZSB7XG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImZpbHRlcnMtZW1wdHlcIj5cbiAgICAgICAgICAgICAgICAgIFRoaXMgY29tcG9uZW50IGhhcyBubyBTUUwgeWV0LlxuICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICA8L21hdC10YWI+XG4gICAgICAgIH1cbiAgICAgICAgPG1hdC10YWJcbiAgICAgICAgICAgIGxhYmVsPVwiQ29uZmlnXCJcbiAgICAgICAgICAgIG5hbWU9XCJjb25maWdcIj5cbiAgICAgICAgICA8ZGl2IGNsYXNzPVwidGFiLWJvZHlcIj5cbiAgICAgICAgICAgIDxwcmUgY2xhc3M9XCJjb2RlLWJsb2NrXCI+XG4gICAgICAgICAgICAgIHt7IGNvbmZpZ0pzb24gfX1cbiAgICAgICAgICAgIDwvcHJlPlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L21hdC10YWI+XG4gICAgICA8L21hdC10YWItZ3JvdXA+XG4gICAgPC9tYXQtZGlhbG9nLWNvbnRlbnQ+XG4gICAgPG1hdC1kaWFsb2ctYWN0aW9ucz5cbiAgICAgIDwhLS0gU2F2ZSB8IERlbGV0ZSB8IENhbmNlbCwgdGhlIHN0YW5kYXJkIG9yZGVyLiBmcy1mb3JtLWRpYWxvZy1hY3Rpb25zXG4gICAgICAgICAgIHJlbmRlcnMgaXRzIG93biBTYXZlL0RvbmUgQkVGT1JFIHRoZSBwcm9qZWN0ZWQgY29udGVudCwgd2hpY2ggd291bGRcbiAgICAgICAgICAgcHV0IERlbGV0ZSBhZnRlciBDYW5jZWwsIHNvIGBbc2F2ZV09XCJmYWxzZVwiYCBmb290cyB0aGUgcm93IGhlcmUgYW5kXG4gICAgICAgICAgIGFsbCB0aHJlZSBidXR0b25zIGFyZSBwcm9qZWN0ZWQgaW4gb3JkZXIuIFNhdmUgc3VibWl0cyB0aGUgU2V0dGluZ3NcbiAgICAgICAgICAgdGFiOyB0aGUgb3RoZXIgdGFicyBwZXJzaXN0IGFzIHlvdSB0b3VjaCB0aGVtLCBzbyB0aGV5IGdldCBEb25lLiAtLT5cbiAgICAgIDxmcy1mb3JtLWRpYWxvZy1hY3Rpb25zIFtzYXZlXT1cImZhbHNlXCI+XG4gICAgICAgIEBpZiAoc2VsZWN0ZWRUYWIgPT09ICdzZXR0aW5ncycpIHtcbiAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICAgIG1hdC1idXR0b25cbiAgICAgICAgICAgICAgdHlwZT1cInN1Ym1pdFwiXG4gICAgICAgICAgICAgIGNvbG9yPVwicHJpbWFyeVwiPlxuICAgICAgICAgICAgU2F2ZVxuICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICB9IEBlbHNlIHtcbiAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICAgIG1hdC1idXR0b25cbiAgICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgICAgICAgIGNvbG9yPVwicHJpbWFyeVwiXG4gICAgICAgICAgICAgIFttYXQtZGlhbG9nLWNsb3NlXT1cIm51bGxcIj5cbiAgICAgICAgICAgIERvbmVcbiAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgfVxuICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICBtYXQtYnV0dG9uXG4gICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgICAgIGNvbG9yPVwid2FyblwiXG4gICAgICAgICAgICAoY2xpY2spPVwiZGVsZXRlKClcIj5cbiAgICAgICAgICBEZWxldGVcbiAgICAgICAgPC9idXR0b24+XG4gICAgICAgIDxidXR0b25cbiAgICAgICAgICAgIG1hdC1idXR0b25cbiAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICAgICAgY2xhc3M9XCJjYW5jZWwtYnV0dG9uXCJcbiAgICAgICAgICAgIFttYXQtZGlhbG9nLWNsb3NlXT1cIm51bGxcIj5cbiAgICAgICAgICBDYW5jZWxcbiAgICAgICAgPC9idXR0b24+XG4gICAgICA8L2ZzLWZvcm0tZGlhbG9nLWFjdGlvbnM+XG4gICAgPC9tYXQtZGlhbG9nLWFjdGlvbnM+XG4gIDwvZnMtZGlhbG9nPlxuPC9mb3JtPiJdfQ==
578
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29tcG9uZW50LXNldHRpbmdzLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3NyYy9hcHAvcmVwb3J0cy9kaWFsb2dzL2NvbXBvbmVudC1zZXR0aW5ncy9jb21wb25lbnQtc2V0dGluZ3MuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2FwcC9yZXBvcnRzL2RpYWxvZ3MvY29tcG9uZW50LXNldHRpbmdzL2NvbXBvbmVudC1zZXR0aW5ncy5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsdUJBQXVCLEVBQUUsU0FBUyxFQUFFLFVBQVUsRUFBRSxZQUFZLEVBQVUsUUFBUSxFQUFFLE1BQU0sRUFBRSxNQUFNLEdBQy9GLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQ2hFLE9BQU8sRUFBbUIsV0FBVyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFOUQsT0FBTyxFQUFFLGVBQWUsRUFBRSxnQkFBZ0IsRUFBRSxjQUFjLEVBQUUsZ0JBQWdCLEVBQUUsWUFBWSxFQUFFLGNBQWMsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQzdJLE9BQU8sRUFBRSxZQUFZLEVBQUUsT0FBTyxFQUFFLFFBQVEsRUFBRSxTQUFTLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUMxRixPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDckQsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQ25ELE9BQU8sRUFBRSxTQUFTLEVBQUUsU0FBUyxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDaEUsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBQ2hFLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUN2RCxPQUFPLEVBQUUs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QUFFO2FBQ04sT0FBTyxDQUFDLE9BQU8sRUFBRSxDQUFDLFNBQVMsRUFBRSxFQUFFLENBQUMsU0FBUyxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUM7SUFDOUQsQ0FBQzt3R0F0aUJVLDBCQUEwQjs0RkFBMUIsMEJBQTBCLHdFQ2pMdkMseW5mQThZTywydUREcFBILFdBQVcsdWlDQUNYLFlBQVksNjZEQUNaLFlBQVksaUhBQ1osY0FBYyxnTUFDZCxhQUFhLHNXQUNiLFlBQVksbWFBQ1osYUFBYSw2b0JBQ2IsY0FBYywrSEFDZCxnQkFBZ0IseUdBQ2hCLGdCQUFnQiw0SEFDaEIsY0FBYyxxTEFDZCxZQUFZLDRMQUNaLE9BQU8sOEVBQ1AsUUFBUSxzREFDUixTQUFTLHFIQUNULFNBQVMsaUxBQ1QsUUFBUSxpVUFDUixTQUFTLHFKQUNULFNBQVMsd2VBQ1QsY0FBYywwVUFDZCxVQUFVOzs0RkFHRCwwQkFBMEI7a0JBN0J0QyxTQUFTO3NDQUdTLHVCQUF1QixDQUFDLE1BQU0sY0FDbkMsSUFBSSxXQUNQO3dCQUNQLFdBQVc7d0JBQ1gsWUFBWTt3QkFDWixZQUFZO3dCQUNaLGNBQWM7d0JBQ2QsYUFBYTt3QkFDYixZQUFZO3dCQUNaLGFBQWE7d0JBQ2IsY0FBYzt3QkFDZCxnQkFBZ0I7d0JBQ2hCLGdCQUFnQjt3QkFDaEIsY0FBYzt3QkFDZCxZQUFZO3dCQUNaLE9BQU87d0JBQ1AsUUFBUTt3QkFDUixTQUFTO3dCQUNULFNBQVM7d0JBQ1QsUUFBUTt3QkFDUixTQUFTO3dCQUNULFNBQVM7d0JBQ1QsY0FBYzt3QkFDZCxVQUFVO3FCQUNYIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksIENvbXBvbmVudCwgRGVzdHJveVJlZiwgRXZlbnRFbWl0dGVyLCBPbkluaXQsIGNvbXB1dGVkLCBpbmplY3QsIHNpZ25hbCxcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyB0YWtlVW50aWxEZXN0cm95ZWQgfSBmcm9tICdAYW5ndWxhci9jb3JlL3J4anMtaW50ZXJvcCc7XG5pbXBvcnQgeyBBYnN0cmFjdENvbnRyb2wsIEZvcm1zTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuXG5pbXBvcnQgeyBNQVRfRElBTE9HX0RBVEEsIE1hdERpYWxvZ0FjdGlvbnMsIE1hdERpYWxvZ0Nsb3NlLCBNYXREaWFsb2dDb250ZW50LCBNYXREaWFsb2dSZWYsIE1hdERpYWxvZ1RpdGxlIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvZGlhbG9nJztcbmltcG9ydCB7IE1hdEZvcm1GaWVsZCwgTWF0SGludCwgTWF0TGFiZWwsIE1hdFN1ZmZpeCB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2Zvcm0tZmllbGQnO1xuaW1wb3J0IHsgTWF0QnV0dG9uIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvYnV0dG9uJztcbmltcG9ydCB7IE1hdElucHV0IH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvaW5wdXQnO1xuaW1wb3J0IHsgTWF0T3B0aW9uLCBNYXRTZWxlY3QgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9zZWxlY3QnO1xuaW1wb3J0IHsgTWF0U2xpZGVUb2dnbGUgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9zbGlkZS10b2dnbGUnO1xuaW1wb3J0IHsgTWF0VGFic01vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL3RhYnMnO1xuaW1wb3J0IHsgTWF0VG9vbHRpcCB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL3Rvb2x0aXAnO1xuXG5pbXBvcnQgeyBGc0RpYWxvZ01vZHVsZSB9IGZyb20gJ0BmaXJlc3RpdGNoL2RpYWxvZyc7XG5pbXBvcnQgeyBGc0Zvcm1Nb2R1bGUgfSBmcm9tICdAZmlyZXN0aXRjaC9mb3JtJztcbmltcG9ydCB7IEZzTGFiZWxNb2R1bGUgfSBmcm9tICdAZmlyZXN0aXRjaC9sYWJlbCc7XG5pbXBvcnQgeyBGc01hc2tNb2R1bGUgfSBmcm9tICdAZmlyZXN0aXRjaC9tYXNrJztcbmltcG9ydCB7IEZzTWVzc2FnZSB9IGZyb20gJ0BmaXJlc3RpdGNoL21lc3NhZ2UnO1xuaW1wb3J0IHsgRnNQcm9tcHQgfSBmcm9tICdAZmlyZXN0aXRjaC9wcm9tcHQnO1xuaW1wb3J0IHsgRnNUYWJzTW9kdWxlIH0gZnJvbSAnQGZpcmVzdGl0Y2gvdGFicyc7XG5cbmltcG9ydCB7IE9ic2VydmFibGUgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IHN3aXRjaE1hcCwgdGFwIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuXG5pbXBvcnQgeyBSZXBvcnREYXRhIH0gZnJvbSAnLi4vLi4vZGF0YS9yZXBvcnQuZGF0YSc7XG5pbXBvcnQgeyBSZXBvcnRDaGFuZ2VQb2xhcml0eSB9IGZyb20gJy4uLy4uL2VudW1zL3JlcG9ydC1jaGFuZ2UtcG9sYXJpdHkuZW51bSc7XG5pbXBvcnQgeyBSZXBvcnRWYWx1ZUZvcm1hdCB9IGZyb20gJy4uLy4uL2VudW1zL3JlcG9ydC12YWx1ZS1mb3JtYXQuZW51bSc7XG5pbXBvcnQgeyBSZXBvcnRWYWx1ZUZvcm11bGEgfSBmcm9tICcuLi8uLi9lbnVtcy9yZXBvcnQtdmFsdWUtZm9ybXVsYS5lbnVtJztcbmltcG9ydCB7IHJlc29sdmVGb3JtYXRDb250ZXh0IH0gZnJvbSAnLi4vLi4vZm9ybWF0JztcbmltcG9ydCB7XG4gIEtQSV9TUEFSS0xJTkVfREVGQVVMVF9HUkFOVUxBUklUWSxcbiAgS1BJX1NQQVJLTElORV9ERUZBVUxUX1BFUklPRFMsXG4gIGtwaUNhcmRTZXR0aW5ncyxcbiAgc2FtZUtwaUNhcmRTZXR0aW5ncyxcbn0gZnJvbSAnLi4vLi4va3BpLWNhcmQnO1xuaW1wb3J0IHtcbiAgQ2hhcnRHcmFudWxhcml0eSxcbiAgQ29tcG9uZW50U2V0dGluZ3MsXG4gIEdSQU5VTEFSSVRZX09QVElPTlMsXG4gIEtwaUNhcmRTZXR0aW5ncyxcbiAgS3BpQ29uZmlnLFxuICBSZXBvcnQsXG4gIFJlcG9ydENvbXBvbmVudCxcbiAgUmVwb3J0Q29tcG9uZW50U3FsLFxuICBSZXBvcnRGaWx0ZXIsXG4gIFJlcG9ydEZpbHRlckdyb3VwLFxuICBSZXBvcnRGaWx0ZXJMZXZlbCxcbiAgUmVwb3J0RmlsdGVyVHlwZSxcbiAgUmVwb3J0RmlsdGVyYWJsZUNvbHVtbixcbn0gZnJvbSAnLi4vLi4vaW50ZXJmYWNlcy9yZXBvcnQuaW50ZXJmYWNlJztcbmltcG9ydCB7IERFRkFVTFRfQ09NUE9ORU5UX1BBRERJTkcgfSBmcm9tICcuLi8uLi9sYXlvdXQnO1xuaW1wb3J0IHtcbiAgRklMVEVSX1RZUEVfT1BUSU9OUyxcbiAgYmFyUGxhY2VtZW50LFxuICBiYXJQbGFjZW1lbnRPcHRpb25zLFxuICBjb21wb25lbnRUb2dnbGVTdGF0ZSxcbiAgZmlsdGVyTGV2ZWwsXG4gIGZpbHRlckxldmVsQ2hvaWNlcyxcbiAgc2hvd25PbkNvbXBvbmVudCxcbiAgdHlwZVNlbGVjdFN0YXRlLFxuICB2YWx1ZUZpbHRlckxldmVsLFxuICB2YWx1ZVBsYWNlbWVudE9wdGlvbnMsXG59IGZyb20gJy4uLy4uL2ZpbHRlci1zZXR0aW5ncy1ydWxlcyc7XG5pbXBvcnQgeyBGaWx0ZXJCYXJQbGFjZW1lbnQgfSBmcm9tICcuLi8uLi9pbnRlcmZhY2VzL2ZpbHRlci1iYXItcGxhY2VtZW50LnR5cGUnO1xuaW1wb3J0IHsgRmlsdGVyQ29tcG9uZW50VG9nZ2xlU3RhdGUgfSBmcm9tICcuLi8uLi9pbnRlcmZhY2VzL2ZpbHRlci1jb21wb25lbnQtdG9nZ2xlLXN0YXRlLmludGVyZmFjZSc7XG5pbXBvcnQgeyBGaWx0ZXJTZXR0aW5nc09wdGlvbiB9IGZyb20gJy4uLy4uL2ludGVyZmFjZXMvZmlsdGVyLXNldHRpbmdzLW9wdGlvbi5pbnRlcmZhY2UnO1xuaW1wb3J0IHsgRmlsdGVyVHlwZVNlbGVjdFN0YXRlIH0gZnJvbSAnLi4vLi4vaW50ZXJmYWNlcy9maWx0ZXItdHlwZS1zZWxlY3Qtc3RhdGUuaW50ZXJmYWNlJztcbmltcG9ydCB7IGVzY2FwZUh0bWwgfSBmcm9tICcuLi8uLi90ZXh0JztcbmltcG9ydCB7IG9wZXJhbmRLZXlzLCByZXBvcnRDb21wb25lbnRzLCB2YWx1ZUtleSB9IGZyb20gJy4uLy4uL3ZhbHVlcyc7XG5cblxuLy8gV2hhdCB0aGUgZGlhbG9nIGhhbmRzIGJhY2suIFRoZSBTZXR0aW5ncyB0YWIncyBTYXZlIGNhcnJpZXMgdGhlIG5ld1xuLy8gYHNldHRpbmdzYDsgRGVsZXRlIGNhcnJpZXMgYGRlbGV0ZWRgIGFuZCBubyBzZXR0aW5ncywgYmVjYXVzZSB0aGUgY29tcG9uZW50XG4vLyBpdCB3YXMgb3BlbmVkIGZvciBubyBsb25nZXIgZXhpc3RzLiBFdmVyeSBvdGhlciBleGl0IChDYW5jZWwsIERvbmUsIEVzY2FwZSxcbi8vIGJhY2tkcm9wKSBjbG9zZXMgd2l0aCBubyByZXN1bHQg4oCUIGZpbHRlciB3b3JrIGlzIGFubm91bmNlZCBhcyBpdCBoYXBwZW5zXG4vLyBpbnN0ZWFkLCB0aHJvdWdoIGBmaWx0ZXJzQ2hhbmdlZGAuXG5leHBvcnQgaW50ZXJmYWNlIENvbXBvbmVudFNldHRpbmdzUmVzdWx0IHtcbiAgc2V0dGluZ3M/OiBDb21wb25lbnRTZXR0aW5ncztcbiAgZGVsZXRlZD86IGJvb2xlYW47XG59XG5cbi8vIFdoYXQgdGhlIHNldHRpbmdzIGVuZHBvaW50IHJldHVybnMgZm9yIHRoZSBjb21wb25lbnQ6IGl0cyBpZCBhbmQsIGZyb20gYVxuLy8gc2VydmVyIHRoYXQgc2F2ZXMgYSBLUEkncyBjYXJkIGtleXMsIHRoZSB3aG9sZSBjb25maWcgYXMgc2F2ZWQuXG5pbnRlcmZhY2UgQ29tcG9uZW50U2V0dGluZ3NSZXNwb25zZSB7XG4gIGlkOiBudW1iZXI7XG4gIGNvbmZpZz86IFJlY29yZDxzdHJpbmcsIHVua25vd24+IHwgbnVsbDtcbn1cblxuXG4vLyBXaGF0IGEgcmlzZSBpbiBhIEtQSSdzIHZhbHVlIG1lYW5zLCBmb3IgdGhlIEluY3JlYXNlIGlzIHNlbGVjdC5cbmNvbnN0IEtQSV9DSEFOR0VfUE9MQVJJVFlfT1BUSU9OUzogeyB2YWx1ZTogUmVwb3J0Q2hhbmdlUG9sYXJpdHk7IG5hbWU6IHN0cmluZyB9W10gPSBbXG4gIHsgdmFsdWU6IFJlcG9ydENoYW5nZVBvbGFyaXR5Lkdvb2QsIG5hbWU6ICdHb29kIG5ld3Mg4oCUIGEgcmlzZSBzaG93cyBncmVlbicgfSxcbiAgeyB2YWx1ZTogUmVwb3J0Q2hhbmdlUG9sYXJpdHkuQmFkLCBuYW1lOiAnQmFkIG5ld3Mg4oCUIGEgcmlzZSBzaG93cyByZWQnIH0sXG4gIHsgdmFsdWU6IFJlcG9ydENoYW5nZVBvbGFyaXR5Lk5ldXRyYWwsIG5hbWU6ICdOZWl0aGVyIOKAlCBubyBjb2xvcicgfSxcbl07XG5cbi8vIEEgS1BJIHNwYXJrbGluZSdzIHBlcmlvZHMgc3RheSB3aXRoaW4gMiB0byA2MC5cbmNvbnN0IEtQSV9TUEFSS0xJTkVfTUlOX1BFUklPRFMgPSAyO1xuY29uc3QgS1BJX1NQQVJLTElORV9NQVhfUEVSSU9EUyA9IDYwO1xuXG4vLyBBIHBlcmNlbnQgS1BJJ3MgdGFyZ2V0IGlzIGVudGVyZWQgYXMgdGhlIHBlcmNlbnQgc2hvd24gKDE1IGZvciAxNSUpIGFuZFxuLy8gc3RvcmVkIGFzIHRoZSAwLTEgcmF0aW8gaXRzIHZhbHVlIGFycml2ZXMgaW47IHRoZSBzZXJ2ZXIgcmVmdXNlcyBhIHN0b3JlZFxuLy8gdGFyZ2V0IGFib3ZlIDEwMCwgd2hpY2ggaXMgMTAsMDAwJSBoZXJlLlxuY29uc3QgS1BJX1BFUkNFTlRfVEFSR0VUX01BWCA9IDEwMDAwO1xuXG4vLyBIb3cgYSBmb3JtdWxhIHZhbHVlJ3MgU2V0dGluZ3MgdGFiIHdyaXRlcyBvdXQgd2hhdCBpdCB3b3JrcyBvdXQsIGluIGl0c1xuLy8gb3BlcmFuZHMnIG5hbWVzLlxuY29uc3QgRk9STVVMQV9MSU5FUzogUmVjb3JkPFJlcG9ydFZhbHVlRm9ybXVsYSwgKG5hbWVzOiBzdHJpbmdbXSkgPT4gc3RyaW5nPiA9IHtcbiAgW1JlcG9ydFZhbHVlRm9ybXVsYS5DaGFuZ2VdOiAobmFtZXMpID0+IG5hbWVzLmpvaW4oJyDiiJIgJyksXG4gIFtSZXBvcnRWYWx1ZUZvcm11bGEuUGVyY2VudENoYW5nZV06IChbYSwgYl0pID0+IGAlIGNoYW5nZSBvZiAke2F9IG92ZXIgJHtifWAsXG4gIFtSZXBvcnRWYWx1ZUZvcm11bGEuUmF0aW9dOiAobmFtZXMpID0+IG5hbWVzLmpvaW4oJyDDtyAnKSxcbiAgW1JlcG9ydFZhbHVlRm9ybXVsYS5TdW1dOiAobmFtZXMpID0+IG5hbWVzLmpvaW4oJyArICcpLFxufTtcblxuXG4vLyBPbmUgcm93IG9mIHRoZSBGaWx0ZXJzIHRhYiBsaXN0aW5nOiBhIGZpbHRlcmFibGUgY29sdW1uLCBpdHMgZmlsdGVyJ3MgdHlwZVxuLy8gKHRoZSBpbmZlcnJlZCBvbmUsIHRoZSBvbmUgcGlja2VkLCBvciB0aGUgZmlsdGVyJ3Mgb3duKSwgYW5kIHdoZXJlIGl0c1xuLy8gZmlsdGVyIHNob3dzICh0aGUgUmVwb3J0IGJhciBzZWxlY3QgYW5kIHRoZSBUaGlzIGNvbXBvbmVudCB0b2dnbGUpLlxuaW50ZXJmYWNlIEZpbHRlclJvdyB7XG4gIGNvbHVtbjogc3RyaW5nO1xuICB0eXBlOiBSZXBvcnRGaWx0ZXJUeXBlO1xuICBsYWJlbDogc3RyaW5nO1xuICBwbGFjZW1lbnQ6IEZpbHRlckJhclBsYWNlbWVudDtcbiAgY29tcG9uZW50OiBib29sZWFuO1xuICB0eXBlU2VsZWN0OiBGaWx0ZXJUeXBlU2VsZWN0U3RhdGU7XG4gIHBsYWNlbWVudE9wdGlvbnM6IEZpbHRlclNldHRpbmdzT3B0aW9uPEZpbHRlckJhclBsYWNlbWVudD5bXTtcbiAgY29tcG9uZW50VG9nZ2xlOiBGaWx0ZXJDb21wb25lbnRUb2dnbGVTdGF0ZTtcbn1cblxuXG4vLyBDb21wb25lbnQgc2V0dGluZ3MsIGluIHRhYnM6XG4vLyAgIFNldHRpbmdzIOKAlCB0aXRsZSBhbmQgY29udGVudCBwYWRkaW5nIChhIHZhbHVlOiBqdXN0IGl0cyBuYW1lLCBzaW5jZSBpdFxuLy8gICBzaXRzIGluc2lkZSBhIHRleHQgYmxvY2sncyB3b3JkcyBhbmQgaGFzIG5vIGJveCksIGFuZCBvbiBhIGRlcml2ZWQgS1BJIGl0cyBjYXJkOlxuLy8gICB3aGF0IGEgcmlzZSBtZWFucywgYSB0YXJnZXQgYW5kIGEgc3BhcmtsaW5lIChudW1iZXIgZm9ybWF0cyBzdGF5IHdpdGhcbi8vICAgdGhlIEFJKS4gUG9zaXRpb24vc2l6ZSBhcmUgdHVuZWQgYnkgZHJhZ2dpbmcgb24gdGhlIGNhbnZhczsgaGVpZ2h0XG4vLyAgIGJlaGF2aW91ciBmb2xsb3dzIGZyb20gdGhlIGNvbXBvbmVudCB0eXBlLlxuLy8gICBGaWx0ZXJzICDigJQgT05FIGxpc3Rpbmcgb2YgZXZlcnkgZmlsdGVyYWJsZSBjb2x1bW4gb24gdGhpcyBjb21wb25lbnQuIEVhY2hcbi8vICAgcm93IGNhcnJpZXMgdHdvIHRvZ2dsZXM6IHNob3cgaW4gdGhlIHJlcG9ydCBiYXIgYW5kL29yIHNob3cgb24gdGhpc1xuLy8gICBjb21wb25lbnQgKGJvdGgsIGVpdGhlciwgb3IgbmVpdGhlcikuIFRoZSBpbnRlcmZhY2UgKGRhdGUgcmFuZ2UgdnMgdmFsdWVcbi8vICAgcGlja2VyKSBpcyBpbmZlcnJlZCBmcm9tIHRoZSBkYXRhLCBuZXZlciBjaG9zZW4uIEVhY2ggdG9nZ2xlIHBlcnNpc3RzXG4vLyAgIGltbWVkaWF0ZWx5IGFuZCByZWZyZXNoZXMgdGhlIGluLWRpYWxvZyBsaXN0LiBBIHZhbHVlIGhhcyBubyBjb21wb25lbnRcbi8vICAgdG8gc2hvdyBhIGZpbHRlciBvbiwgc28gaXQgZ2V0cyB0aGUgcmVwb3J0IGJhciB0b2dnbGUgb25seS5cbi8vICAgU1FMIC8gQ29uZmlnIOKAlCByZWFkLW9ubHkgZGlhZ25vc3RpY3MuXG4vLyBBIGZvcm11bGEgdmFsdWUgaGFzIG5vIEZpbHRlcnMgb3IgU1FMIHRhYjogdGhlIHNlcnZlciB3b3JrcyBpdCBvdXQgb2Ygb3RoZXJcbi8vIHZhbHVlcyBvbiBpdHMgcGFnZSwgc28gaXQgcnVucyBubyBzdGF0ZW1lbnQgYW5kIGZvbGxvd3MgdGhlIGZpbHRlcnMgb2YgdGhlXG4vLyB2YWx1ZXMgaXQgcmVhZHMuIEl0cyBTZXR0aW5ncyB0YWIgc2F5cyB3aGF0IGl0IHdvcmtzIG91dCwgdW5kZXIgaXRzIG5hbWUuXG5AQ29tcG9uZW50KHtcbiAgdGVtcGxhdGVVcmw6ICcuL2NvbXBvbmVudC1zZXR0aW5ncy5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsczogWycuL2NvbXBvbmVudC1zZXR0aW5ncy5jb21wb25lbnQuc2NzcyddLFxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgaW1wb3J0czogW1xuICAgIEZvcm1zTW9kdWxlLFxuICAgIEZzRm9ybU1vZHVsZSxcbiAgICBGc01hc2tNb2R1bGUsXG4gICAgRnNEaWFsb2dNb2R1bGUsXG4gICAgRnNMYWJlbE1vZHVsZSxcbiAgICBGc1RhYnNNb2R1bGUsXG4gICAgTWF0VGFic01vZHVsZSxcbiAgICBNYXREaWFsb2dUaXRsZSxcbiAgICBNYXREaWFsb2dDb250ZW50LFxuICAgIE1hdERpYWxvZ0FjdGlvbnMsXG4gICAgTWF0RGlhbG9nQ2xvc2UsXG4gICAgTWF0Rm9ybUZpZWxkLFxuICAgIE1hdEhpbnQsXG4gICAgTWF0TGFiZWwsXG4gICAgTWF0U3VmZml4LFxuICAgIE1hdEJ1dHRvbixcbiAgICBNYXRJbnB1dCxcbiAgICBNYXRPcHRpb24sXG4gICAgTWF0U2VsZWN0LFxuICAgIE1hdFNsaWRlVG9nZ2xlLFxuICAgIE1hdFRvb2x0aXAsXG4gIF0sXG59KVxuZXhwb3J0IGNsYXNzIENvbXBvbmVudFNldHRpbmdzQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0IHtcblxuICAvLyBBIGZpbHRlciB3YXMgYWRkZWQsIHJlbW92ZWQgb3IgcmUtbGV2ZWxsZWQsIHNvIHRoZSByZXBvcnQncyBmaWx0ZXIgZ3JvdXBzXG4gIC8vIGNoYW5nZWQuIFRob3NlIG11dGF0aW9ucyBwZXJzaXN0IHRoZSBtb21lbnQgdGhleSBhcmUgY2xpY2tlZCBhbmQgdGhlIGRpYWxvZ1xuICAvLyBjYW4gdGhlbiBiZSBkaXNtaXNzZWQgYnkgYSByb3V0ZSB0aGF0IGNhcnJpZXMgbm8gcmVzdWx0IChFc2NhcGUsIGJhY2tkcm9wKSxcbiAgLy8gc28gdGhlIHBhZ2UgaXMgdG9sZCBoZXJlIHJhdGhlciB0aGFuIHRocm91Z2ggdGhlIGNsb3NlIHJlc3VsdC5cbiAgcHVibGljIHJlYWRvbmx5IGZpbHRlcnNDaGFuZ2VkID0gbmV3IEV2ZW50RW1pdHRlcjx2b2lkPigpO1xuXG4gIHB1YmxpYyBjb21wb25lbnQ6IFJlcG9ydENvbXBvbmVudDtcbiAgcHVibGljIHJlcG9ydDogUmVwb3J0O1xuXG4gIHB1YmxpYyBzZWxlY3RlZFRhYiA9ICdzZXR0aW5ncyc7XG5cbiAgcHVibGljIHRpdGxlID0gJyc7XG5cbiAgLy8gQ29tcG9uZW50IHBhZGRpbmcgaW4gaW5jaGVzLiBgbnVtYmVyIHwgc3RyaW5nYCBmb3IgdGhlIHNhbWUgcmVhc29uIGFzIHRoZVxuICAvLyBwYWdlIGRpbWVuc2lvbnMgaW4gcmVwb3J0LXNldHRpbmdzOiBmc01hc2tOdW1iZXIgc2VlZHMgZnJvbSB0aGUgbnVtYmVyIGJ1dFxuICAvLyBoYW5kcyBiYWNrIHRoZSB1bm1hc2tlZCBzdHJpbmcsIGFuZCBzYXZlIGNhc3RzIGl0IG9uY2Ugb24gdGhlIHdheSBvdXQuXG4gIHB1YmxpYyBwYWRkaW5nVG9wOiBudW1iZXIgfCBzdHJpbmcgPSBERUZBVUxUX0NPTVBPTkVOVF9QQURESU5HO1xuICBwdWJsaWMgcGFkZGluZ1JpZ2h0OiBudW1iZXIgfCBzdHJpbmcgPSBERUZBVUxUX0NPTVBPTkVOVF9QQURESU5HO1xuICBwdWJsaWMgcGFkZGluZ0JvdHRvbTogbnVtYmVyIHwgc3RyaW5nID0gREVGQVVMVF9DT01QT05FTlRfUEFERElORztcbiAgcHVibGljIHBhZGRpbmdMZWZ0OiBudW1iZXIgfCBzdHJpbmcgPSBERUZBVUxUX0NPTVBPTkVOVF9QQURESU5HO1xuXG4gIHB1YmxpYyBjb25maWdKc29uID0gJyc7XG5cbiAgLy8gLS0tLSBLUEkgY2FyZCBzdGF0ZSAoYSBkZXJpdmVkIEtQSSBvbmx5KSAtLS0tXG4gIHB1YmxpYyByZWFkb25seSBrcGlQb2xhcml0eU9wdGlvbnMgPSBLUElfQ0hBTkdFX1BPTEFSSVRZX09QVElPTlM7XG4gIHB1YmxpYyByZWFkb25seSBncmFudWxhcml0eU9wdGlvbnMgPSBHUkFOVUxBUklUWV9PUFRJT05TO1xuICBwdWJsaWMgcmVhZG9ubHkgc3BhcmtsaW5lTWluUGVyaW9kcyA9IEtQSV9TUEFSS0xJTkVfTUlOX1BFUklPRFM7XG4gIHB1YmxpYyByZWFkb25seSBzcGFya2xpbmVNYXhQZXJpb2RzID0gS1BJX1NQQVJLTElORV9NQVhfUEVSSU9EUztcbiAgcHVibGljIHJlYWRvbmx5IGtwaUNhcmQgPSBzaWduYWwoZmFsc2UpO1xuICAvLyBBIHZhbHVlIGluc2lkZSBhIHRleHQgYmxvY2s6IG5vIGJveCwgc28gbm8gcGFkZGluZy5cbiAgcHVibGljIHJlYWRvbmx5IGlzVmFsdWUgPSBzaWduYWwoZmFsc2UpO1xuICAvLyBBIGZvcm11bGEgdmFsdWU6IG5vIHN0YXRlbWVudCwgY29sdW1ucyBvciBmaWx0ZXJzIG9mIGl0cyBvd24uXG4gIHB1YmxpYyByZWFkb25seSBpc0Zvcm11bGEgPSBzaWduYWwoZmFsc2UpO1xuICAvLyBXaGF0IGEgZm9ybXVsYSB3b3JrcyBvdXQsIGluIGl0cyBvcGVyYW5kcycgbmFtZXM7IGVtcHR5IGZvciBhbnkgb3RoZXJcbiAgLy8gY29tcG9uZW50LlxuICBwdWJsaWMgcmVhZG9ubHkgZm9ybXVsYUxpbmUgPSBjb21wdXRlZCgoKSA9PiAodGhpcy5pc0Zvcm11bGEoKSA/IHRoaXMuX2Zvcm11bGFMaW5lKCkgOiAnJykpO1xuICBwdWJsaWMgcmVhZG9ubHkgaW5jcmVhc2VJcyA9IHNpZ25hbDxSZXBvcnRDaGFuZ2VQb2xhcml0eT4oUmVwb3J0Q2hhbmdlUG9sYXJpdHkuR29vZCk7XG4gIC8vIFRoZSB0YXJnZXQgYXMgdHlwZWQ6IGZzTWFza051bWJlciBoYW5kcyBiYWNrIHRoZSB1bm1hc2tlZCBzdHJpbmcuIEVtcHR5XG4gIC8vIG1lYW5zIG5vIHRhcmdldC4gQSBwZXJjZW50IEtQSSdzIGlzIGluIHBlcmNlbnQgKHRhcmdldFBlcmNlbnQpLlxuICBwdWJsaWMgcmVhZG9ubHkgdGFyZ2V0VmFsdWUgPSBzaWduYWw8bnVtYmVyIHwgc3RyaW5nIHwgbnVsbD4obnVsbCk7XG4gIHB1YmxpYyByZWFkb25seSB0YXJnZXRMYWJlbCA9IHNpZ25hbCgnJyk7XG4gIHB1YmxpYyByZWFkb25seSB0YXJnZXRQZXJjZW50ID0gc2lnbmFsKGZhbHNlKTtcbiAgcHVibGljIHJlYWRvbmx5IGhhc1RhcmdldCA9IGNvbXB1dGVkKCgpID0+IHRoaXMuX251bWJlcih0aGlzLnRhcmdldFZhbHVlKCkpICE9PSBudWxsKTtcbiAgcHVibGljIHJlYWRvbmx5IHNwYXJrbGluZSA9IHNpZ25hbChmYWxzZSk7XG4gIHB1YmxpYyByZWFkb25seSBzcGFya2xpbmVHcmFudWxhcml0eSA9IHNpZ25hbDxDaGFydEdyYW51bGFyaXR5PihLUElfU1BBUktMSU5FX0RFRkFVTFRfR1JBTlVMQVJJVFkpO1xuICBwdWJsaWMgcmVhZG9ubHkgc3BhcmtsaW5lUGVyaW9kcyA9IHNpZ25hbDxudW1iZXIgfCBzdHJpbmc+KEtQSV9TUEFSS0xJTkVfREVGQVVMVF9QRVJJT0RTKTtcblxuICAvLyAtLS0tIFNRTCB0YWIgc3RhdGUgLS0tLVxuICAvLyBUaGUgc3RhdGVtZW50LCBvbmNlIGZldGNoZWQuIE51bGwgd2hpbGUgaXQgaXMgaW4gZmxpZ2h0LCBhbmQgbnVsbCB3aGVuIHRoZVxuICAvLyBjb21wb25lbnQncyBkb2N1bWVudCBjb3VsZCBub3QgYmUgY29tcGlsZWQgKHNxbEVycm9yIHRoZW4gc2F5cyB3aHkpLlxuICBwdWJsaWMgcmVhZG9ubHkgc3FsID0gc2lnbmFsPHN0cmluZyB8IG51bGw+KG51bGwpO1xuICAvLyBUcnVlIHdoZW4gdGhlIHN0YXRlbWVudCBpcyBhIERFUklWRUQgYmFzZWxpbmU6IG5vIGZpbHRlcnMsIHRoZSBhdXRob3JlZFxuICAvLyBncmFpbiwgdGltZXMgaW4gdGhlIHJlcG9ydCdzIGVmZmVjdGl2ZSB6b25lLiBUaGUgdGFiIHNheXMgc28sIGJlY2F1c2UgdGhlXG4gIC8vIG51bWJlcnMgb24gc2NyZWVuIGNvbWUgZnJvbSB0aGlzIHN0YXRlbWVudCBwbHVzIHRoZSB2aWV3ZXIncyBvd24gY2hvaWNlc1xuICAvLyBhbmQgdGhlIHR3byBjYW4gZGlmZmVyLlxuICBwdWJsaWMgcmVhZG9ubHkgc3FsQmFzZWxpbmUgPSBzaWduYWwoZmFsc2UpO1xuICAvLyBUaGUgem9uZSB0aGUgc3RhdGVtZW50IHdhcyBjb21waWxlZCBpbjogdGhlIHJlcG9ydCdzIGVmZmVjdGl2ZSB6b25lLCBzZW50XG4gIC8vIHdpdGggdGhlIFNRTC4gQSBzZXJ2ZXIgdG9vIG9sZCB0byBzZW5kIGl0IGNvbXBpbGVkIGluIFVUQy5cbiAgcHVibGljIHJlYWRvbmx5IHNxbFRpbWV6b25lID0gc2lnbmFsKCdVVEMnKTtcbiAgcHVibGljIHJlYWRvbmx5IHNxbEVycm9yID0gc2lnbmFsPHN0cmluZyB8IG51bGw+KG51bGwpO1xuXG4gIC8vIC0tLS0gZmlsdGVyIG1hbmFnZW1lbnQgc3RhdGUgLS0tLVxuICAvLyBPbmUgcm93IHBlciBmaWx0ZXJhYmxlIGNvbHVtbi4gVGhlIHBsYWNlbWVudCBhbmQgdGhlIHRvZ2dsZSBjaGFuZ2VcbiAgLy8gb3B0aW1pc3RpY2FsbHkgb24gY2xpY2sgKHNvIHRoZSBVSSBuZXZlciBibGlua3Mgd2hpbGUgdGhlIHJlcXVlc3QgaXMgaW5cbiAgLy8gZmxpZ2h0KSBhbmQgcmVjb25jaWxlIGZyb20gdGhlIHNlcnZlciBvbiByZWxvYWQuXG4gIHB1YmxpYyByZWFkb25seSByb3dzID0gc2lnbmFsPEZpbHRlclJvd1tdPihbXSk7XG4gIHB1YmxpYyByZWFkb25seSBjb2x1bW5zRXJyb3IgPSBzaWduYWw8c3RyaW5nIHwgbnVsbD4obnVsbCk7XG4gIC8vIFRoZSBUeXBlIHNlbGVjdCdzIGNob2ljZXMuIEEgcm93J3MgVHlwZSBzZWxlY3QsIFJlcG9ydCBiYXIgc2VsZWN0IGFuZFxuICAvLyBUaGlzIGNvbXBvbmVudCB0b2dnbGUgZm9sbG93IHRoZSBydWxlcyBpbiBmaWx0ZXItc2V0dGluZ3MtcnVsZXMudHMuXG4gIHB1YmxpYyByZWFkb25seSB0eXBlT3B0aW9ucyA9IEZJTFRFUl9UWVBFX09QVElPTlM7XG5cbiAgLy8gVGhlIHJhdyBpbnB1dHMgdGhlIHJvd3MgYXJlIGJ1aWx0IGZyb20uXG4gIHByaXZhdGUgX2ZpbHRlcmFibGVDb2x1bW5zOiBSZXBvcnRGaWx0ZXJhYmxlQ29sdW1uW10gPSBbXTtcbiAgcHJpdmF0ZSBfZmlsdGVyczogUmVwb3J0RmlsdGVyW10gPSBbXTtcbiAgcHJpdmF0ZSBfZ3JvdXBzQnlJZCA9IG5ldyBNYXA8bnVtYmVyLCBSZXBvcnRGaWx0ZXJHcm91cD4oKTtcbiAgLy8gVGhlIHR5cGUgcGlja2VkIGZvciBhIGNvbHVtbiB3aXRoIG5vIGZpbHRlciB5ZXQsIHNvIGEgcmVsb2FkIGtlZXBzIGl0LlxuICBwcml2YXRlIF9waWNrZWRUeXBlcyA9IG5ldyBNYXA8c3RyaW5nLCBSZXBvcnRGaWx0ZXJUeXBlPigpO1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgX3R5cGVMYWJlbHM6IFJlY29yZDxSZXBvcnRGaWx0ZXJUeXBlLCBzdHJpbmc+ID0ge1xuICAgIHNlbGVjdDogJ1BpY2sgdmFsdWVzJyxcbiAgICBkYXRlUmFuZ2U6ICdEYXRlIHJhbmdlJyxcbiAgICBrZXl3b3JkOiAnU2VhcmNoIHRleHQnLFxuICAgIG51bWJlclJhbmdlOiAnTnVtYmVyIHJhbmdlJyxcbiAgfTtcblxuICBwcml2YXRlIHJlYWRvbmx5IF9kYXRhOiB7IHJlcG9ydDogUmVwb3J0OyBjb21wb25lbnQ6IFJlcG9ydENvbXBvbmVudCB9ID0gaW5qZWN0KE1BVF9ESUFMT0dfREFUQSk7XG4gIHByaXZhdGUgcmVhZG9ubHkgX2RpYWxvZ1JlZiA9IGluamVjdDxNYXREaWFsb2dSZWY8Q29tcG9uZW50U2V0dGluZ3NDb21wb25lbnQsIENvbXBvbmVudFNldHRpbmdzUmVzdWx0Pj4oTWF0RGlhbG9nUmVmKTtcbiAgcHJpdmF0ZSByZWFkb25seSBfcmVwb3J0RGF0YSA9IGluamVjdChSZXBvcnREYXRhKTtcbiAgcHJpdmF0ZSByZWFkb25seSBfbWVzc2FnZSA9IGluamVjdChGc01lc3NhZ2UpO1xuICBwcml2YXRlIHJlYWRvbmx5IF9wcm9tcHQgPSBpbmplY3QoRnNQcm9tcHQpO1xuICBwcml2YXRlIHJlYWRvbmx5IF9kZXN0cm95UmVmID0gaW5qZWN0KERlc3Ryb3lSZWYpO1xuXG4gIHB1YmxpYyBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgICB0aGlzLnJlcG9ydCA9IHRoaXMuX2RhdGEucmVwb3J0O1xuICAgIHRoaXMuY29tcG9uZW50ID0gdGhpcy5fZGF0YS5jb21wb25lbnQ7XG5cbiAgICB0aGlzLnRpdGxlID0gdGhpcy5jb21wb25lbnQudGl0bGUgPz8gJyc7XG4gICAgdGhpcy5pc1ZhbHVlLnNldCh0aGlzLmNvbXBvbmVudC50eXBlID09PSAndmFsdWUnKTtcbiAgICB0aGlzLmlzRm9ybXVsYS5zZXQoISF0aGlzLmNvbXBvbmVudC5jb25maWc/LmZvcm11bGEpO1xuXG4gICAgY29uc3QgcGFkZGluZyA9IHRoaXMuY29tcG9uZW50LmNvbmZpZz8ucGFkZGluZztcbiAgICB0aGlzLnBhZGRpbmdUb3AgPSBwYWRkaW5nPy50b3AgPz8gREVGQVVMVF9DT01QT05FTlRfUEFERElORztcbiAgICB0aGlzLnBhZGRpbmdSaWdodCA9IHBhZGRpbmc/LnJpZ2h0ID8/IERFRkFVTFRfQ09NUE9ORU5UX1BBRERJTkc7XG4gICAgdGhpcy5wYWRkaW5nQm90dG9tID0gcGFkZGluZz8uYm90dG9tID8/IERFRkFVTFRfQ09NUE9ORU5UX1BBRERJTkc7XG4gICAgdGhpcy5wYWRkaW5nTGVmdCA9IHBhZGRpbmc/LmxlZnQgPz8gREVGQVVMVF9DT01QT05FTlRfUEFERElORztcblxuICAgIHRoaXMuY29uZmlnSnNvbiA9IEpTT04uc3RyaW5naWZ5KHRoaXMuY29tcG9uZW50LmNvbmZpZyA/PyB7fSwgbnVsbCwgMik7XG5cbiAgICB0aGlzLl9zZWVkS3BpQ2FyZCgpO1xuXG4gICAgdGhpcy5fc2VlZEZpbHRlcnModGhpcy5yZXBvcnQsIHRoaXMuY29tcG9uZW50LmlkKTtcblxuICAgIC8vIEEgZm9ybXVsYSBoYXMgbm8gc3RhdGVtZW50IHRvIGNvbXBpbGUgYW5kIG5vIGNvbHVtbnMgdG8gZmlsdGVyIG9uLCBhbmRcbiAgICAvLyB0aGUgc2VydmVyIHdvdWxkIHJlZnVzZSBib3RoIHJlcXVlc3RzLlxuICAgIGlmICghdGhpcy5pc0Zvcm11bGEoKSkge1xuICAgICAgdGhpcy5fbG9hZENvbHVtbnMoKTtcbiAgICAgIHRoaXMuX2xvYWRTcWwoKTtcbiAgICB9XG4gIH1cblxuICAvLyBIdW1hbi1mcmllbmRseSBuYW1lIGZvciB0aGUgaW5mZXJyZWQgaW50ZXJmYWNlIHNob3duIGJlc2lkZSBlYWNoIGNvbHVtbi5cbiAgcHVibGljIHR5cGVMYWJlbCh0eXBlOiBSZXBvcnRGaWx0ZXJUeXBlKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5fdHlwZUxhYmVsc1t0eXBlXSA/PyB0eXBlO1xuICB9XG5cbiAgLy8gQ29uZmlybSBhbmQgZGVsZXRlIGhlcmUsIHdoaWxlIHRoZSBkaWFsb2cgaXMgc3RpbGwgb3BlbiwgdGhlbiBjbG9zZSB3aXRoIGFcbiAgLy8gYGRlbGV0ZWRgIHJlc3VsdCBmb3IgdGhlIHBhZ2UgdG8gYWN0IG9uIOKAlCB0aGUgc2FtZSBzaGFwZSB0aGUgcmVwb3J0XG4gIC8vIHNldHRpbmdzIGRpYWxvZyB1c2VzIGZvciBkZWxldGluZyBhIHJlcG9ydC5cbiAgLy9cbiAgLy8gVGhlIGNvbmZpcm0gc2F5cyBpdCBjYW5ub3QgYmUgdW5kb25lIGJlY2F1c2UsIGZyb20gdGhlIFVJLCBpdCBjYW5ub3Q6IHRoZVxuICAvLyByb3cgaXMgc29mdC1kZWxldGVkIHNlcnZlci1zaWRlIGJ1dCBub3RoaW5nIGhlcmUgcmVzdG9yZXMgYSBjb21wb25lbnQuXG4gIC8vIEEgdmFsdWUncyBjb25maXJtIGFsc28gc2F5cyB3aGF0IGdvZXMgd2l0aCBpdDogdGhlIHNlcnZlciB0YWtlcyBpdHNcbiAgLy8gdG9rZW5zIG91dCBvZiBldmVyeSB0ZXh0IG9uIGl0cyBwYWdlLCBub3QganVzdCB0aGUgb25lIGl0IHdhcyBvcGVuZWQgZnJvbSxcbiAgLy8gYW5kIGRlbGV0ZXMgdGhlIGZvcm11bGFzIHRoYXQgcmVhZCBpdCAoX2RlcGVuZGVudHNOb3RlKS5cbiAgLy9cbiAgLy8gVGhlIHByb21wdCByZW5kZXJzIGl0cyB0ZW1wbGF0ZSBhcyBodG1sLCBzbyBldmVyeSBuYW1lIGluIGl0IGlzIGVzY2FwZWQuXG4gIHB1YmxpYyBkZWxldGUoKTogdm9pZCB7XG4gICAgdGhpcy5fcHJvbXB0LmNvbmZpcm0odGhpcy5pc1ZhbHVlKClcbiAgICAgID8ge1xuICAgICAgICB0aXRsZTogJ0RlbGV0ZSBWYWx1ZScsXG4gICAgICAgIHRlbXBsYXRlOiBgRGVsZXRlIHRoZSB2YWx1ZSBcIiR7ZXNjYXBlSHRtbCh0aGlzLmNvbXBvbmVudC50aXRsZSB8fCB2YWx1ZUtleSh0aGlzLmNvbXBvbmVudCkpfVwiPyBJdCBpcyBhbHNvIHRha2VuIG91dCBvZiBldmVyeSB0ZXh0IG9uIHRoaXMgcGFnZS4gVGhpcyBjYW5ub3QgYmUgdW5kb25lLiR7dGhpcy5fZGVwZW5kZW50c05vdGUoKX1gLFxuICAgICAgfVxuICAgICAgOiB7XG4gICAgICAgIHRpdGxlOiAnRGVsZXRlIENvbXBvbmVudCcsXG4gICAgICAgIHRlbXBsYXRlOiBgQXJlIHlvdSBzdXJlIHlvdSB3b3VsZCBsaWtlIHRvIGRlbGV0ZSBcIiR7ZXNjYXBlSHRtbCh0aGlzLmNvbXBvbmVudC50aXRsZSB8fCAndGhpcyBjb21wb25lbnQnKX1cIj8gVGhpcyBjYW5ub3QgYmUgdW5kb25lLmAsXG4gICAgICB9KVxuICAgICAgLnBpcGUoXG4gICAgICAgIHN3aXRjaE1hcCgoKSA9PiB0aGlzLl9yZXBvcnREYXRhLmRlbGV0ZUNvbXBvbmVudCh0aGlzLnJlcG9ydC5pZCwgdGhpcy5jb21wb25lbnQuaWQpKSxcbiAgICAgICAgdGFwKCgpID0+IHtcbiAgICAgICAgICB0aGlzLl9tZXNzYWdlLnN1Y2Nlc3ModGhpcy5pc1ZhbHVlKCkgPyAnVmFsdWUgZGVsZXRlZCcgOiAnQ29tcG9uZW50IGRlbGV0ZWQnKTtcbiAgICAgICAgICB0aGlzLl9kaWFsb2dSZWYuY2xvc2UoeyBkZWxldGVkOiB0cnVlIH0pO1xuICAgICAgICB9KSxcbiAgICAgICAgdGFrZVVudGlsRGVzdHJveWVkKHRoaXMuX2Rlc3Ryb3lSZWYpLFxuICAgICAgKVxuICAgICAgLnN1YnNjcmliZSgpO1xuICB9XG5cbiAgLy8gQSBwZXJjZW50IHRhcmdldCdzIGJvdW5kLCBpbiB0aGUgcGVyY2VudCBpdCBpcyB0eXBlZCBpbi4gSXQgcmVhZHMgdGhlXG4gIC8vIGNvbnRyb2wsIHdoaWNoIGZzRm9ybSB2YWxpZGF0ZXMgYmVmb3JlIG5nTW9kZWxDaGFuZ2UgdXBkYXRlcyB0aGUgc2lnbmFsLlxuICBwdWJsaWMgdmFsaWRhdGVUYXJnZXQgPSAoY29udHJvbDogQWJzdHJhY3RDb250cm9sKTogdm9pZCA9PiB7XG4gICAgY29uc3QgdmFsdWUgPSB0aGlzLl9udW1iZXIoY29udHJvbC52YWx1ZSk7XG5cbiAgICBpZiAodGhpcy50YXJnZXRQZXJjZW50KCkgJiYgdmFsdWUgIT09IG51bGwgJiYgdmFsdWUgPiBLUElfUEVSQ0VOVF9UQVJHRVRfTUFYKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0EgcGVyY2VudCB0YXJnZXQgY2FuIGJlIGF0IG1vc3QgMTAsMDAwJScpO1xuICAgIH1cbiAgfTtcblxuICBwdWJsaWMgc2F2ZSA9ICgpID0+IHtcbiAgICBjb25zdCBzZXR0aW5nczogQ29tcG9uZW50U2V0dGluZ3MgPSB7XG4gICAgICAvLyBUaGUgc2VydmVyIHRyaW1zIGEgdGl0bGU7IGEgdmFsdWUncyBOYW1lIGlzIHdoYXQgaXRzIGNoaXBzIHNob3csIHNvIGl0XG4gICAgICAvLyBnb2VzIGFzIHRoZSBzZXJ2ZXIga2VlcHMgaXQuXG4gICAgICB0aXRsZTogdGhpcy5pc1ZhbHVlKCkgPyB0aGlzLnRpdGxlLnRyaW0oKSA6IHRoaXMudGl0bGUsXG4gICAgICBwYWRkaW5nOiB7XG4gICAgICAgIHRvcDogdGhpcy5fcGFkZGluZyh0aGlzLnBhZGRpbmdUb3ApLFxuICAgICAgICByaWdodDogdGhpcy5fcGFkZGluZyh0aGlzLnBhZGRpbmdSaWdodCksXG4gICAgICAgIGJvdHRvbTogdGhpcy5fcGFkZGluZyh0aGlzLnBhZGRpbmdCb3R0b20pLFxuICAgICAgICBsZWZ0OiB0aGlzLl9wYWRkaW5nKHRoaXMucGFkZGluZ0xlZnQpLFxuICAgICAgfSxcbiAgICB9O1xuXG4gICAgLy8gVGhlIGNhcmQga2V5cyBnbyBhcyBjb25maWcga2V5cyBiZXNpZGUgdGhlIHBhZGRpbmcgKGluY3JlYXNlSXMsIHRhcmdldFxuICAgIC8vIGFuZCBzcGFya2xpbmUsIG51bGwgdG8gcmVtb3ZlIG9uZSksIGFuZCBvbmx5IHdoZW4gdGhleSBjaGFuZ2VkLCBzbyBhXG4gICAgLy8gdGl0bGUgZWRpdCBuZXZlciB0b3VjaGVzIHRoZW0uXG4gICAgY29uc3Qga3BpID0gdGhpcy5rcGlDYXJkKCkgPyB0aGlzLl9rcGlDYXJkU2V0dGluZ3MoKSA6IG51bGw7XG4gICAgY29uc3Qga3BpQ2hhbmdlZCA9ICEha3BpXG4gICAgICAmJiAhc2FtZUtwaUNhcmRTZXR0aW5ncyhrcGksIGtwaUNhcmRTZXR0aW5ncyh0aGlzLmNvbXBvbmVudC5jb25maWcgYXMgS3BpQ29uZmlnKSk7XG5cbiAgICByZXR1cm4gdGhpcy5fcmVwb3J0RGF0YS51cGRhdGVDb21wb25lbnQodGhpcy5yZXBvcnQuaWQsIHRoaXMuY29tcG9uZW50LmlkLCB7XG4gICAgICB0aXRsZTogc2V0dGluZ3MudGl0bGUsXG4gICAgICAuLi4odGhpcy5pc1ZhbHVlKCkgPyB7fSA6IHsgcGFkZGluZzogc2V0dGluZ3MucGFkZGluZyB9KSxcbiAgICAgIC4uLihrcGlDaGFuZ2VkID8ga3BpIDoge30pLFxuICAgIH0pXG4gICAgICAucGlwZShcbiAgICAgICAgdGFwKChyZXNwb25zZTogQ29tcG9uZW50U2V0dGluZ3NSZXNwb25zZSkgPT4ge1xuICAgICAgICAgIC8vIFRoZSBjYXJkIGlzIGRyYXduIGZyb20gdGhlIGtleXMgdGhlIHNlcnZlciBzYXZlZCwgcmVhZCBiYWNrIGZyb21cbiAgICAgICAgICAvLyB0aGUgY29uZmlnIGl0IHJldHVybnMuIEEgc2VydmVyIHRoYXQgcmV0dXJucyBubyBjb25maWcgZGlkIG5vdFxuICAgICAgICAgIC8vIHNhdmUgdGhlbSwgc28gdGhlIGNhcmQga2VlcHMgd2hhdCBpdCBoYWQgYW5kIHRoZSBkaWFsb2cgc2F5cyBzby5cbiAgICAgICAgICBjb25zdCBzYXZlZCA9IGtwaUNoYW5nZWQgPyB0aGlzLl9zYXZlZEtwaUNhcmQocmVzcG9uc2UpIDogbnVsbDtcblxuICAgICAgICAgIGlmIChrcGlDaGFuZ2VkICYmICFzYXZlZCkge1xuICAgICAgICAgICAgdGhpcy5fbWVzc2FnZS53YXJuaW5nKCdDb21wb25lbnQgc2F2ZWQsIGJ1dCB0aGUgc2VydmVyIGRpZCBub3Qgc2F2ZSB0aGUgY2FyZCBzZXR0aW5ncycpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLl9tZXNzYWdlLnN1Y2Nlc3ModGhpcy5pc1ZhbHVlKCkgPyAnVmFsdWUgc2F2ZWQnIDogJ0NvbXBvbmVudCBzYXZlZCcpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHRoaXMuX2RpYWxvZ1JlZi5jbG9zZSh7IHNldHRpbmdzOiBzYXZlZCA/IHsgLi4uc2V0dGluZ3MsIGtwaTogc2F2ZWQgfSA6IHNldHRpbmdzIH0pO1xuICAgICAgICB9KSxcbiAgICAgICk7XG4gIH07XG5cbiAgLy8gVGhlIHR5cGUgYSBjb2x1bW4ncyBmaWx0ZXIgd2lsbCBiZSBtYWRlIHdpdGguIE9ubHkgYSBjb2x1bW4gd2l0aCBub1xuICAvLyBmaWx0ZXIgb2ZmZXJzIHRoZSBwaWNrICh0aGUgVHlwZSBzZWxlY3QgaXMgbG9ja2VkIG90aGVyd2lzZSksIGFuZCBub3RoaW5nXG4gIC8vIGlzIHNhdmVkIHVudGlsIHRoZSBmaWx0ZXIgaXMgbWFkZS5cbiAgcHVibGljIHNldFR5cGUocm93OiBGaWx0ZXJSb3csIHR5cGU6IFJlcG9ydEZpbHRlclR5cGUpOiB2b2lkIHtcbiAgICB0aGlzLl9waWNrZWRUeXBlcy5zZXQocm93LmNvbHVtbiwgdHlwZSk7XG4gICAgdGhpcy5fcGF0Y2hSb3cocm93LCB7IHR5cGUgfSk7XG4gIH1cblxuICAvLyBXaGVyZSB0aGUgcm93J3MgZmlsdGVyIHNob3dzIGluIHRoZSByZXBvcnQgYmFyLiBUaGlzIHBhZ2Ugb25seSBzaG93cyBpdFxuICAvLyBpbiBpdHMgcGFnZSdzIGJhciBhbG9uZSwgc28gdGhlIFRoaXMgY29tcG9uZW50IHRvZ2dsZSBnb2VzIG9mZiBhbmQgbG9ja3MuXG4gIC8vIEEgdmFsdWUgaGFzIHRoaXMgc2VsZWN0IG9ubHksIHdpdGggaXRzIG93biBydWxlcyAoX2FwcGx5VmFsdWVMZXZlbCkuXG4gIHB1YmxpYyBzZXRQbGFjZW1lbnQocm93OiBGaWx0ZXJSb3csIHBsYWNlbWVudDogRmlsdGVyQmFyUGxhY2VtZW50KTogdm9pZCB7XG4gICAgY29uc3QgcGF0Y2hlZCA9IHRoaXMuX3BhdGNoUm93KHJvdywge1xuICAgICAgcGxhY2VtZW50LFxuICAgICAgY29tcG9uZW50OiBwbGFjZW1lbnQgPT09ICdwYWdlJyA/IGZhbHNlIDogcm93LmNvbXBvbmVudCxcbiAgICAgIGNvbXBvbmVudFRvZ2dsZTogY29tcG9uZW50VG9nZ2xlU3RhdGUocGxhY2VtZW50KSxcbiAgICB9KTtcblxuICAgIGlmICh0aGlzLmlzVmFsdWUoKSkge1xuICAgICAgdGhpcy5fYXBwbHlWYWx1ZUxldmVsKHBhdGNoZWQpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLl9hcHBseUxldmVsKHBhdGNoZWQpO1xuICAgIH1cbiAgfVxuXG4gIC8vIEEgdmFsdWUgaGFzIG5vIFRoaXMgY29tcG9uZW50IHRvZ2dsZS5cbiAgcHVibGljIHNldENvbXBvbmVudChyb3c6IEZpbHRlclJvdywgY29tcG9uZW50OiBib29sZWFuKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuaXNWYWx1ZSgpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5fYXBwbHlMZXZlbCh0aGlzLl9wYXRjaFJvdyhyb3csIHsgY29tcG9uZW50IH0pKTtcbiAgfVxuXG4gIC8vIFBlcnNpc3QgdGhlIGxldmVsIHRoZSByb3cncyBjb250cm9scyBhc2sgZm9yLCB0aGVuIHJlY29uY2lsZSBvbiByZWxvYWQuXG4gIC8vIE5vIGxldmVsIOKGkiBubyBmaWx0ZXIgKHJlbW92ZWQpOyBvdGhlcndpc2UgdGhlIGZpbHRlciBleGlzdHMgYXQgdGhhdFxuICAvLyBsZXZlbC4gQSBzZXJ2ZXIgcmVmdXNhbCAoYSBwYWdlIGZpbHRlciB3aG9zZSBtZW1iZXJzIHNpdCBvbiB0d28gcGFnZXMpXG4gIC8vIHNob3dzIGl0cyBvd24gdGV4dCBhbmQgdGhlIHJvdyBzbmFwcyBiYWNrLlxuICBwcml2YXRlIF9hcHBseUxldmVsKHJvdzogRmlsdGVyUm93KTogdm9pZCB7XG4gICAgY29uc3QgbGV2ZWwgPSBmaWx0ZXJMZXZlbChyb3cucGxhY2VtZW50LCByb3cuY29tcG9uZW50KTtcbiAgICBjb25zdCBleGlzdGluZyA9IHRoaXMuX2ZpbHRlcnMuZmluZCgoZmlsdGVyKSA9PiBmaWx0ZXIuZmlsdGVyQ29sdW1uID09PSByb3cuY29sdW1uKTtcblxuICAgIGlmICghbGV2ZWwpIHtcbiAgICAgIGlmIChleGlzdGluZykge1xuICAgICAgICB0aGlzLl9ydW4odGhpcy5fcmVwb3J0RGF0YS5kZWxldGVGaWx0ZXIodGhpcy5yZXBvcnQuaWQsIGV4aXN0aW5nLmlkKSk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoZXhpc3RpbmcpIHtcbiAgICAgIHRoaXMuX3J1bih0aGlzLl9yZXBvcnREYXRhLnVwZGF0ZUZpbHRlckdyb3VwKHRoaXMucmVwb3J0LmlkLCBleGlzdGluZy5maWx0ZXJHcm91cElkLCB7IGxldmVsIH0pKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5fYWRkRmlsdGVyKHJvdywgbGV2ZWwpO1xuICAgIH1cbiAgfVxuXG4gIC8vIEEgdmFsdWUncyBSZXBvcnQgYmFyIHNlbGVjdCwgdGhlIG9ubHkgY29udHJvbCBpdCBoYXMuIEl0cyBmaWx0ZXIncyBncm91cFxuICAvLyBtYXkgYmUgc2hhcmVkICh0aGUgcmVwb3J0J3MgUGVyaW9kLCBzYXkpLCBhbmQgYSB2YWx1ZSBoYXMgbm8gc3RyaXAgb2YgaXRzXG4gIC8vIG93biwgc28gYSBwaWNrIG5ldmVyIGxvd2VycyB0aGUgZ3JvdXAgKHZhbHVlRmlsdGVyTGV2ZWwpLiBBIHBpY2sgdGhhdFxuICAvLyBtb3ZlcyBub3RoaW5nIHB1dHMgdGhlIHJvdyBiYWNrIGFzIHRoZSBncm91cCBzdGFuZHMuXG4gIHByaXZhdGUgX2FwcGx5VmFsdWVMZXZlbChyb3c6IEZpbHRlclJvdyk6IHZvaWQge1xuICAgIGNvbnN0IGV4aXN0aW5nID0gdGhpcy5fZmlsdGVycy5maW5kKChmaWx0ZXIpID0+IGZpbHRlci5maWx0ZXJDb2x1bW4gPT09IHJvdy5jb2x1bW4pO1xuICAgIGNvbnN0IGN1cnJlbnQgPSBleGlzdGluZyA/IHRoaXMuX2dyb3Vwc0J5SWQuZ2V0KGV4aXN0aW5nLmZpbHRlckdyb3VwSWQpPy5sZXZlbCA6IHVuZGVmaW5lZDtcbiAgICBjb25zdCBsZXZlbCA9IHZhbHVlRmlsdGVyTGV2ZWwocm93LnBsYWNlbWVudCwgY3VycmVudCk7XG5cbiAgICBpZiAoIWxldmVsKSB7XG4gICAgICBpZiAoZXhpc3RpbmcpIHtcbiAgICAgICAgdGhpcy5fcnVuKHRoaXMuX3JlcG9ydERhdGEuZGVsZXRlRmlsdGVyKHRoaXMucmVwb3J0LmlkLCBleGlzdGluZy5pZCkpO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAoIWV4aXN0aW5nKSB7XG4gICAgICB0aGlzLl9hZGRGaWx0ZXIocm93LCBsZXZlbCk7XG4gICAgfSBlbHNlIGlmIChsZXZlbCAhPT0gY3VycmVudCkge1xuICAgICAgdGhpcy5fcnVuKHRoaXMuX3JlcG9ydERhdGEudXBkYXRlRmlsdGVyR3JvdXAodGhpcy5yZXBvcnQuaWQsIGV4aXN0aW5nLmZpbHRlckdyb3VwSWQsIHsgbGV2ZWwgfSkpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLl9yZWJ1aWxkUm93cygpO1xuICAgIH1cbiAgfVxuXG4gIC8vIFRoZSB0eXBlIGdvZXMgb25seSB3aGVuIHRoZSBhdXRob3IgY291bGQgcGljayBpdDsgb3RoZXJ3aXNlIHRoZSBzZXJ2ZXJcbiAgLy8gaW5mZXJzIGl0LCBhcyBpdCBhbHdheXMgaGFzLlxuICBwcml2YXRlIF9hZGRGaWx0ZXIocm93OiBGaWx0ZXJSb3csIGxldmVsOiBSZXBvcnRGaWx0ZXJMZXZlbCk6IHZvaWQge1xuICAgIHRoaXMuX3J1bih0aGlzLl9yZXBvcnREYXRhLmFkZEZpbHRlcih0aGlzLnJlcG9ydC5pZCwgdGhpcy5jb21wb25lbnQuaWQsIHtcbiAgICAgIGZpbHRlckNvbHVtbjogcm93LmNvbHVtbixcbiAgICAgIGxhYmVsOiByb3cubGFiZWwsXG4gICAgICBsZXZlbCxcbiAgICAgIC4uLihyb3cudHlwZVNlbGVjdC5zaG93ID8geyB0eXBlOiByb3cudHlwZSB9IDoge30pLFxuICAgIH0pKTtcbiAgfVxuXG4gIC8vIEEgbmV3IHJvdyBvYmplY3QgcmF0aGVyIHRoYW4gYSBtdXRhdGlvbiwgc28gdGhlIHNpZ25hbCBzZWVzIHRoZSBjaGFuZ2U7XG4gIC8vIHRoZSBAZm9yIHRyYWNrcyB0aGUgY29sdW1uLCBzbyB0aGUgcm93J3MgY29udHJvbHMgc3Vydml2ZSB0aGUgc3dhcC5cbiAgcHJpdmF0ZSBfcGF0Y2hSb3cocm93OiBGaWx0ZXJSb3csIHBhdGNoOiBQYXJ0aWFsPEZpbHRlclJvdz4pOiBGaWx0ZXJSb3cge1xuICAgIGNvbnN0IHBhdGNoZWQgPSB7IC4uLnJvdywgLi4ucGF0Y2ggfTtcbiAgICB0aGlzLnJvd3MudXBkYXRlKChyb3dzKSA9PiByb3dzLm1hcCgoaXRlbSkgPT4gKGl0ZW0uY29sdW1uID09PSByb3cuY29sdW1uID8gcGF0Y2hlZCA6IGl0ZW0pKSk7XG5cbiAgICByZXR1cm4gcGF0Y2hlZDtcbiAgfVxuXG4gIC8vIFdoYXQgYSBmb3JtdWxhIHdvcmtzIG91dCwgbmFtaW5nIGVhY2ggb3BlcmFuZCBhcyBpdHMgY2hpcHMgZG8uIEFuIG9wIHRoaXNcbiAgLy8gdmlld2VyIGRvZXMgbm90IGtub3cgcmVhZHMgbm90aGluZy5cbiAgcHJpdmF0ZSBfZm9ybXVsYUxpbmUoKTogc3RyaW5nIHtcbiAgICBjb25zdCBmb3JtdWxhID0gdGhpcy5jb21wb25lbnQuY29uZmlnPy5mb3JtdWxhO1xuICAgIGNvbnN0IGxpbmUgPSBmb3JtdWxhID8gRk9STVVMQV9MSU5FU1tmb3JtdWxhLm9wXSA6IHVuZGVmaW5lZDtcbiAgICBjb25zdCB2YWx1ZXMgPSB0aGlzLl9sYXllclZhbHVlcygpO1xuXG4gICAgcmV0dXJuIGxpbmUgPyBsaW5lKG9wZXJhbmRLZXlzKHRoaXMuY29tcG9uZW50KS5tYXAoKGtleSkgPT4gdGhpcy5fdmFsdWVOYW1lKHZhbHVlcywga2V5KSkpIDogJyc7XG4gIH1cblxuICAvLyBUaGUgc2VudGVuY2UgYSBxdWVyeSB2YWx1ZSdzIGRlbGV0ZSBjb25maXJtIGVuZHMgd2l0aCB3aGVuIGZvcm11bGFzIG9uIGl0c1xuICAvLyBsYXllciByZWFkIGl0OiB0aGUgc2VydmVyIGRlbGV0ZXMgdGhvc2Ugd2l0aCBpdC4gRW1wdHkgd2hlbiBub25lIGRvZXMsIGFuZFxuICAvLyBmb3IgYSBmb3JtdWxhLCB3aG9zZSBvcGVyYW5kcyBzdGF5LlxuICBwcml2YXRlIF9kZXBlbmRlbnRzTm90ZSgpOiBzdHJpbmcge1xuICAgIGlmICh0aGlzLmlzRm9ybXVsYSgpKSB7XG4gICAgICByZXR1cm4gJyc7XG4gICAgfVxuXG4gICAgY29uc3Qga2V5ID0gdmFsdWVLZXkodGhpcy5jb21wb25lbnQpO1xuICAgIGNvbnN0IG5hbWVzID0gdGhpcy5fbGF5ZXJWYWx1ZXMoKVxuICAgICAgLmZpbHRlcigodmFsdWUpID0+IG9wZXJhbmRLZXlzKHZhbHVlKS5pbmNsdWRlcyhrZXkpKVxuICAgICAgLm1hcCgodmFsdWUpID0+IGVzY2FwZUh0bWwodmFsdWUudGl0bGUgfHwgdmFsdWVLZXkodmFsdWUpKSk7XG5cbiAgICByZXR1cm4gbmFtZXMubGVuZ3RoID8gYCBUaGUgdmFsdWVzIHdvcmtlZCBvdXQgZnJvbSBpdCBhcmUgZGVsZXRlZCB0b286ICR7bmFtZXMuam9pbignLCAnKX0uYCA6ICcnO1xuICB9XG5cbiAgLy8gVGhlIHZhbHVlcyBvZiB0aGUgbGF5ZXIgdGhpcyB2YWx1ZSBiZWxvbmdzIHRvOiB0aGUgcGFnZSB3aG9zZSB2YWx1ZXMgaG9sZFxuICAvLyBpdCwgZWxzZSB0aGUgbWFzdGVyJ3MgKGEgaGVhZGVyIG9yIGZvb3RlciB2YWx1ZSkuXG4gIHByaXZhdGUgX2xheWVyVmFsdWVzKCk6IFJlcG9ydENvbXBvbmVudFtdIHtcbiAgICBjb25zdCBwYWdlID0gKHRoaXMucmVwb3J0LnBhZ2VzID8/IFtdKVxuICAgICAgLmZpbmQoKGNhbmRpZGF0ZSkgPT4gKGNhbmRpZGF0ZS52YWx1ZXMgPz8gW10pLnNvbWUoKHZhbHVlKSA9PiB2YWx1ZS5pZCA9PT0gdGhpcy5jb21wb25lbnQuaWQpKTtcblxuICAgIHJldHVybiAocGFnZSA/PyB0aGlzLnJlcG9ydC5tYXN0ZXIpPy52YWx1ZXMgPz8gW107XG4gIH1cblxuICAvLyBXaGF0IGEgdmFsdWUgaXMgY2FsbGVkIHdoZXJlIGl0cyBjaGlwcyBzaG93IGl0OiBpdHMgbmFtZSwgZWxzZSBpdHMga2V5LlxuICAvLyBUaGUgbmV3ZXN0IHZhbHVlIGhvbGRzIGEga2V5LCBhcyBpdCBkb2VzIGluIHRoZSB0ZXh0J3MgdG9rZW5zLlxuICBwcml2YXRlIF92YWx1ZU5hbWUodmFsdWVzOiBSZXBvcnRDb21wb25lbnRbXSwga2V5OiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIGNvbnN0IHZhbHVlID0gdmFsdWVzLmZpbHRlcigoY2FuZGlkYXRlKSA9PiB2YWx1ZUtleShjYW5kaWRhdGUpID09PSBrZXkpLnBvcCgpO1xuXG4gICAgcmV0dXJuIHZhbHVlPy50aXRsZSB8fCBrZXk7XG4gIH1cblxuICAvLyBBIGRlcml2ZWQgS1BJJ3MgY2FyZCBrZXlzLCBmcm9tIGl0cyBjb25maWcuIEEgc3FsLW1vZGUgS1BJIGNhbm5vdCBjYXJyeVxuICAvLyB0aGVtLCBzbyBpdCBnZXRzIG5vIGNhcmQgZmllbGRzLlxuICBwcml2YXRlIF9zZWVkS3BpQ2FyZCgpOiB2b2lkIHtcbiAgICBjb25zdCBjb25maWcgPSAodGhpcy5jb21wb25lbnQuY29uZmlnID8/IHt9KSBhcyBLcGlDb25maWc7XG5cbiAgICB0aGlzLmtwaUNhcmQuc2V0KHRoaXMuY29tcG9uZW50LnR5cGUgPT09ICdrcGknICYmICF0aGlzLmNvbXBvbmVudC5zcWwpO1xuICAgIHRoaXMuaW5jcmVhc2VJcy5zZXQoY29uZmlnLmluY3JlYXNlSXMgPz8gUmVwb3J0Q2hhbmdlUG9sYXJpdHkuR29vZCk7XG4gICAgdGhpcy50YXJnZXRQZXJjZW50LnNldChjb25maWcubWVhc3VyZT8uZm9ybWF0ID09PSBSZXBvcnRWYWx1ZUZvcm1hdC5QZXJjZW50XG4gICAgICAmJiByZXNvbHZlRm9ybWF0Q29udGV4dCh0aGlzLnJlcG9ydCkucmF0aW9QZXJjZW50KTtcbiAgICB0aGlzLnRhcmdldFZhbHVlLnNldCh0aGlzLl90YXJnZXRTaG93bihjb25maWcudGFyZ2V0Py52YWx1ZSA/PyBudWxsKSk7XG4gICAgdGhpcy50YXJnZXRMYWJlbC5zZXQoY29uZmlnLnRhcmdldD8ubGFiZWwgPz8gJycpO1xuICAgIHRoaXMuc3BhcmtsaW5lLnNldCghIWNvbmZpZy5zcGFya2xpbmUpO1xuICAgIHRoaXMuc3BhcmtsaW5lR3JhbnVsYXJpdHkuc2V0KGNvbmZpZy5zcGFya2xpbmU/LmdyYW51bGFyaXR5ID8/IEtQSV9TUEFSS0xJTkVfREVGQVVMVF9HUkFOVUxBUklUWSk7XG4gICAgdGhpcy5zcGFya2xpbmVQZXJpb2RzLnNldChjb25maWcuc3BhcmtsaW5lPy5wZXJpb2RzID8/IEtQSV9TUEFSS0xJTkVfREVGQVVMVF9QRVJJT0RTKTtcbiAgfVxuXG4gIC8vIFRoZSBjYXJkIGtleXMgdGhlIHNlcnZlciBzYXZlZCwgZnJvbSB0aGUgY29uZmlnIGl0cyByZXNwb25zZSBjYXJyaWVzO1xuICAvLyBudWxsIHdoZW4gaXQgY2FycmllcyBub25lIChhIHNlcnZlciB0aGF0IGRvZXMgbm90IHNhdmUgdGhlbSkuXG4gIHByaXZhdGUgX3NhdmVkS3BpQ2FyZChyZXNwb25zZTogQ29tcG9uZW50U2V0dGluZ3NSZXNwb25zZSB8IG51bGwgfCB1bmRlZmluZWQpOiBLcGlDYXJkU2V0dGluZ3MgfCBudWxsIHtcbiAgICBjb25zdCBjb25maWcgPSByZXNwb25zZT8uY29uZmlnO1xuXG4gICAgcmV0dXJuIGNvbmZpZyAmJiB0eXBlb2YgY29uZmlnID09PSAnb2JqZWN0JyA/IGtwaUNhcmRTZXR0aW5ncyhjb25maWcgYXMgS3BpQ29uZmlnKSA6IG51bGw7XG4gIH1cblxuICAvLyBHb29kIGlzIHdoYXQgYW4gYWJzZW50IGluY3JlYXNlSXMgcmVhZHMsIHNvIGl0IGlzIHNhdmVkIGFzIGFic2VudC5cbiAgcHJpdmF0ZSBfa3BpQ2FyZFNldHRpbmdzKCk6IEtwaUNhcmRTZXR0aW5ncyB7XG4gICAgY29uc3QgdGFyZ2V0ID0gdGhpcy5fbnVtYmVyKHRoaXMudGFyZ2V0VmFsdWUoKSk7XG4gICAgY29uc3QgbGFiZWwgPSB0aGlzLnRhcmdldExhYmVsKCkudHJpbSgpO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIGluY3JlYXNlSXM6IHRoaXMuaW5jcmVhc2VJcygpID09PSBSZXBvcnRDaGFuZ2VQb2xhcml0eS5Hb29kID8gbnVsbCA6IHRoaXMuaW5jcmVhc2VJcygpLFxuICAgICAgdGFyZ2V0OiB0YXJnZXQgPT09IG51bGwgPyBudWxsIDogeyB2YWx1ZTogdGhpcy5fdGFyZ2V0U3RvcmVkKHRhcmdldCksIGxhYmVsOiBsYWJlbCB8fCBudWxsIH0sXG4gICAgICBzcGFya2xpbmU6IHRoaXMuc3BhcmtsaW5lKClcbiAgICAgICAgPyB7IGdyYW51bGFyaXR5OiB0aGlzLnNwYXJrbGluZUdyYW51bGFyaXR5KCksIHBlcmlvZHM6IHRoaXMuX251bWJlcih0aGlzLnNwYXJrbGluZVBlcmlvZHMoKSkgfVxuICAgICAgICA6IG51bGwsXG4gICAgfTtcbiAgfVxuXG4gIC8vIEEgc3RvcmVkIHJhdGlvIGFzIHRoZSBwZXJjZW50IHR5cGVkLCByb3VuZGVkIHNvIDAuMTUgcmVhZHMgMTUgYW5kIG5vdFxuICAvLyAxNS4wMDAwMDAwMDAwMDAwMDIuXG4gIHByaXZhdGUgX3RhcmdldFNob3duKHZhbHVlOiBudW1iZXIgfCBudWxsKTogbnVtYmVyIHwgbnVsbCB7XG4gICAgaWYgKHZhbHVlID09PSBudWxsIHx8ICF0aGlzLnRhcmdldFBlcmNlbnQoKSkge1xuICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH1cblxuICAgIHJldHVybiBNYXRoLnJvdW5kKHZhbHVlICogMTAwICogMWU2KSAvIDFlNjtcbiAgfVxuXG4gIHByaXZhdGUgX3RhcmdldFN0b3JlZCh2YWx1ZTogbnVtYmVyKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy50YXJnZXRQZXJjZW50KCkgPyB2YWx1ZSAvIDEwMCA6IHZhbHVlO1xuICB9XG5cbiAgLy8gQSB0eXBlZCBudW1iZXIsIG9yIG51bGwgd2hlbiB0aGUgZmllbGQgaXMgZW1wdHkuXG4gIHByaXZhdGUgX251bWJlcih2YWx1ZTogbnVtYmVyIHwgc3RyaW5nIHwgbnVsbCk6IG51bWJlciB8IG51bGwge1xuICAgIGlmICh2YWx1ZSA9PT0gbnVsbCB8fCB2YWx1ZSA9PT0gJycpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIGNvbnN0IG51bWJlciA9IHR5cGVvZiB2YWx1ZSA9PT0gJ251bWJlcicgPyB2YWx1ZSA6IHBhcnNlRmxvYXQodmFsdWUpO1xuXG4gICAgcmV0dXJuIE51bWJlci5pc0Zpbml0ZShudW1iZXIpID8gbnVtYmVyIDogbnVsbDtcbiAgfVxuXG4gIC8vIFRoZSBwYWRkaW5nIGFzIGEgcmVhbCBudW1iZXIgZm9yIHRoZSB3aXJlLiBmc01hc2tOdW1iZXIgaGFuZHMgYmFjayB0aGVcbiAgLy8gdW5tYXNrZWQgc3RyaW5nIGl0IGJ1aWx0IHdpdGggYSBmaXhlZCAnLicgcmFkaXgsIHNvIHRoaXMgaXMgYSBzdHJhaWdodFxuICAvLyBwYXJzZSAtIHRoZSB3aG9sZSByZWFzb24gZm9yIHRoZSBtYXNrIGlzIHRoYXQgYSBuYXRpdmUgbnVtYmVyIGlucHV0IHdvdWxkXG4gIC8vIHBhaW50IChhbmQgcmVhZCBiYWNrKSB0aGUgdmlld2VyJ3Mgb3duIGxvY2FsZSBzZXBhcmF0b3IgaW5zdGVhZC5cbiAgcHJpdmF0ZSBfcGFkZGluZyh2YWx1ZTogbnVtYmVyIHwgc3RyaW5nKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJyA/IHZhbHVlIDogcGFyc2VGbG9hdCh2YWx1ZSk7XG4gIH1cblxuICAvLyBSdW4gYSBmaWx0ZXIgbXV0YXRpb24sIHRoZW4gcmVsb2FkIHRvIHJlY29uY2lsZSB0aGUgb3B0aW1pc3RpYyBzdGF0ZS5cbiAgcHJpdmF0ZSBfcnVuKHJlcXVlc3Q6IE9ic2VydmFibGU8dW5rbm93bj4pOiB2b2lkIHtcbiAgICByZXF1ZXN0LnN1YnNjcmliZSh7XG4gICAgICBuZXh0OiAoKSA9PiB0aGlzLl9hZnRlck11dGF0aW9uKCksXG4gICAgICBlcnJvcjogKGVycm9yKSA9PiB0aGlzLl9tdXRhdGlvbkVycm9yKGVycm9yKSxcbiAgICB9KTtcbiAgfVxuXG4gIC8vIEJ1aWxkIHRoZSByb3cgdmlldy1tb2RlbCBmcm9tIHRoZSBsb2FkZWQgY29sdW1ucyArIGZpbHRlcnMvZ3JvdXBzLiBFYWNoXG4gIC8vIHJvdydzIGNvbnRyb2xzIHJlZmxlY3Qgd2hlcmUgaXRzIGZpbHRlciBncm91cCBjdXJyZW50bHkgc2hvd3M7IGEgY29sdW1uXG4gIC8vIHdpdGggYSBmaWx0ZXIgc2hvd3MgdGhlIGZpbHRlcidzIG93biB0eXBlLiBBIHZhbHVlJ3Mgcm93cyBuZXZlciByZWFkIGFzXG4gIC8vIG9uIGEgY29tcG9uZW50OiBpdCBoYXMgbm8gc3RyaXAsIHdoYXRldmVyIGxldmVsIGEgZ3JvdXAgaXQgc2hhcmVzIGlzIGF0LFxuICAvLyBhbmQgaXRzIFJlcG9ydCBiYXIgc2VsZWN0IG9mZmVycyBubyBwaWNrIHRoYXQgbG93ZXJzIHRoYXQgZ3JvdXAuXG4gIHByaXZhdGUgX3JlYnVpbGRSb3dzKCk6IHZvaWQge1xuICAgIGNvbnN0IGxldmVsQ2hvaWNlcyA9IGZpbHRlckxldmVsQ2hvaWNlcyh0aGlzLnJlcG9ydC52aWV3ZXJGZWF0dXJlcywgdGhpcy5fb25QYWdlKCkpO1xuXG4gICAgdGhpcy5yb3dzLnNldCh0aGlzLl9maWx0ZXJhYmxlQ29sdW1ucy5tYXAoKGNvbHVtbikgPT4ge1xuICAgICAgY29uc3QgZmlsdGVyID0gdGhpcy5fZmlsdGVycy5maW5kKChjYW5kaWRhdGUpID0+IGNhbmRpZGF0ZS5maWx0ZXJDb2x1bW4gPT09IGNvbHVtbi5jb2x1bW4pO1xuICAgICAgY29uc3QgZ3JvdXAgPSBmaWx0ZXIgPyB0aGlzLl9ncm91cHNCeUlkLmdldChmaWx0ZXIuZmlsdGVyR3JvdXBJZCkgOiB1bmRlZmluZWQ7XG4gICAgICBjb25zdCBwbGFjZW1lbnQgPSBiYXJQbGFjZW1lbnQoZ3JvdXA/LmxldmVsKTtcblxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgY29sdW1uOiBjb2x1bW4uY29sdW1uLFxuICAgICAgICB0eXBlOiBncm91cD8udHlwZVxuICAgICAgICAgID8/IHRoaXMuX3BpY2tlZFR5cGVzLmdldChjb2x1bW4uY29sdW1uKVxuICAgICAgICAgID8/IGNvbHVtbi50eXBlcz8uWzBdXG4gICAgICAgICAgPz8gY29sdW1uLnR5cGUsXG4gICAgICAgIGxhYmVsOiBmaWx0ZXI/LmxhYmVsXG4gICAgICAgICAgfHwgdGhpcy5fZ3JvdXBzQnlJZC5nZXQoZmlsdGVyPy5maWx0ZXJHcm91cElkID8/IC0xKT8ubGFiZWxcbiAgICAgICAgICB8fCB0aGlzLl9odW1hbml6ZShjb2x1bW4uY29sdW1uKSxcbiAgICAgICAgcGxhY2VtZW50LFxuICAgICAgICBjb21wb25lbnQ6ICF0aGlzLmlzVmFsdWUoKSAmJiBzaG93bk9uQ29tcG9uZW50KGdyb3VwPy5sZXZlbCksXG4gICAgICAgIHR5cGVTZWxlY3Q6IHR5cGVTZWxlY3RTdGF0ZShjb2x1bW4udHlwZXMsICEhZmlsdGVyLCB0aGlzLnJlcG9ydC52aWV3ZXJGZWF0dXJlcyksXG4gICAgICAgIHBsYWNlbWVudE9wdGlvbnM6IHRoaXMuaXNWYWx1ZSgpXG4gICAgICAgICAgPyB2YWx1ZVBsYWNlbWVudE9wdGlvbnMobGV2ZWxDaG9pY2VzLCBncm91cD8ubGV2ZWwpXG4gICAgICAgICAgOiBiYXJQbGFjZW1lbnRPcHRpb25zKGxldmVsQ2hvaWNlcywgcGxhY2VtZW50KSxcbiAgICAgICAgY29tcG9uZW50VG9nZ2xlOiBjb21wb25lbnRUb2dnbGVTdGF0ZShwbGFjZW1lbnQpLFxuICAgICAgfTtcbiAgICB9KSk7XG4gIH1cblxuICAvLyBXaGV0aGVyIHRoZSBjb21wb25lbnQgc2l0cyBvbiBhIHBhZ2U6IGFtb25nIGl0cyBjb21wb25lbnRzLCBvciwgZm9yIGFcbiAgLy8gdmFsdWUsIGl0cyB2YWx1ZXMuIEEgaGVhZGVyIG9yIGZvb3RlciBjb21wb25lbnQgb3IgdmFsdWUgc2l0cyBvbiBub25lLFxuICAvLyBzbyBpdHMgZmlsdGVycyBjYW5ub3QgYmUgcGFnZSBmaWx0ZXJzLlxuICBwcml2YXRlIF9vblBhZ2UoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuICh0aGlzLnJlcG9ydC5wYWdlcyA/PyBbXSlcbiAgICAgIC5zb21lKChwYWdlKSA9PiBbLi4uKHBhZ2UuY29tcG9uZW50cyA/PyBbXSksIC4uLihwYWdlLnZhbHVlcyA/PyBbXSldXG4gICAgICAgIC5zb21lKChjYW5kaWRhdGUpID0+IGNhbmRpZGF0ZS5pZCA9PT0gdGhpcy5jb21wb25lbnQuaWQpKTtcbiAgfVxuXG4gIC8vIEFmdGVyIGFueSBmaWx0ZXIgbXV0YXRpb246IHJlLWZldGNoIHRoZSByZXBvcnQgc28gdGhlIGRpYWxvZydzIGZpbHRlciBsaXN0XG4gIC8vIChhbmQgdGhlIHBhcmVudCBjYW52YXMsIG9uIGNsb3NlKSByZWZsZWN0IHRoZSBuZXcgZ3JvdXBzL2xldmVscy5cbiAgcHJpdmF0ZSBfYWZ0ZXJNdXRhdGlvbigpOiB2b2lkIHtcbiAgICB0aGlzLmZpbHRlcnNDaGFuZ2VkLmVtaXQoKTtcblxuICAgIHRoaXMuX3JlcG9ydERhdGEuZ2V0KHRoaXMucmVwb3J0LmlkKVxuICAgICAgLnN1YnNjcmliZSgocmVwb3J0OiBSZXBvcnQpID0+IHtcbiAgICAgICAgdGhpcy5yZXBvcnQgPSByZXBvcnQ7XG4gICAgICAgIHRoaXMuX3NlZWRGaWx0ZXJzKHJlcG9ydCwgdGhpcy5jb21wb25lbnQuaWQpO1xuICAgICAgfSk7XG4gIH1cblxuICBwcml2YXRlIF9tdXRhdGlvbkVycm9yKGVycm9yOiBhbnkpOiB2b2lkIHtcbiAgICB0aGlzLl9tZXNzYWdlLmVycm9yKGVycm9yPy5lcnJvcj8ubWVzc2FnZSA/PyBlcnJvcj8ubWVzc2FnZSA/PyAnRmlsdGVyIG9wZXJhdGlvbiBmYWlsZWQnKTtcbiAgICAvLyBSZS1zZWVkIGZyb20gdGhlIHNlcnZlciBzbyB0aGUgb3B0aW1pc3RpYyB0b2dnbGUgc25hcHMgYmFjayB0byB0cnV0aC5cbiAgICB0aGlzLl9hZnRlck11dGF0aW9uKCk7XG4gIH1cblxuICAvLyBUaGUgY29tcG9uZW50J3MgZmlsdGVycyBhbmQgdGhlIGdyb3VwcyB0aGV5IHNpdCBpbiwgZnJvbSB0aGUgcmVwb3J0IGFzXG4gIC8vIGxhc3QgbG9hZGVkLiBBIHZhbHVlIGlzIGxpc3RlZCBpbiBpdHMgcGFnZSdzIHZhbHVlcywgbm90IGl0cyBjb21wb25lbnRzLlxuICBwcml2YXRlIF9zZWVkRmlsdGVycyhyZXBvcnQ6IFJlcG9ydCwgY29tcG9uZW50SWQ6IG51bWJlcik6IHZvaWQge1xuICAgIHRoaXMuX2dyb3Vwc0J5SWQgPSBuZXcgTWFwKChyZXBvcnQuZmlsdGVyR3JvdXBzID8/IFtdKS5tYXAoKGdyb3VwKSA9PiBbZ3JvdXAuaWQsIGdyb3VwXSkpO1xuXG4gICAgY29uc3QgY29tcG9uZW50ID0gcmVwb3J0Q29tcG9uZW50cyhyZXBvcnQpXG4gICAgICAuZmluZCgoY2FuZGlkYXRlKSA9PiBjYW5kaWRhdGUuaWQgPT09IGNvbXBvbmVudElkKTtcblxuICAgIHRoaXMuX2ZpbHRlcnMgPSBjb21wb25lbnQ/LmZpbHRlcnMgPz8gW107XG4gICAgdGhpcy5fcmVidWlsZFJvd3MoKTtcbiAgfVxuXG4gIC8vIFRoZSBzdGF0ZW1lbnQgdGhlIFNRTCB0YWIgc2hvd3MuIEZldGNoZWQgcmF0aGVyIHRoYW4gcmVhZCBvZmYgdGhlXG4gIC8vIGNvbXBvbmVudDogYSBkZXJpdmVkIGNvbXBvbmVudCBzdG9yZXMgYSBkb2N1bWVudCwgbm90IFNRTCwgc28gaXRzXG4gIC8vIHN0YXRlbWVudCBvbmx5IGV4aXN0cyBvbmNlIHRoZSBiYWNrZW5kIGNvbXBpbGVzIGl0LlxuICAvL1xuICAvLyBMb2FkZWQgaW4gbmdPbkluaXQgYmVzaWRlIHRoZSBjb2x1bW5zLCBOT1Qgb24gdGFiIGFjdGl2YXRpb24uIFRoZSB0YWJzIGFyZVxuICAvLyBub3QgbGF6eSAobm8gbWF0VGFiQ29udGVudCksIGFuZCBzd2l0Y2hpbmcgdGhlIHRhYi1ncm91cCdzIGBbKHNlbGVjdGVkKV1gXG4gIC8vIGJhbmFuYS1ib3ggdG8gYSBvbmUtd2F5IGJpbmRpbmcgcGx1cyAoc2VsZWN0ZWRDaGFuZ2UpIHRvIGdldCBhIGhvb2sgd291bGRcbiAgLy8gYnJlYWsgaXQ6IEZzVGFic0hlYWRlclRhYkdyb3VwRGlyZWN0aXZlIHNlbGYtYXNzaWducyBgdGhpcy5zZWxlY3RlZGAgYmVmb3JlXG4gIC8vIGl0IGVtaXRzLCBzbyB0aGUgZXZlbnQgaXMgZmlsdGVyZWQgb3V0IGFuZCB0aGUgbG9hZCB3b3VsZCBuZXZlciBmaXJlLiBPbmVcbiAgLy8gc21hbGwgcmVxdWVzdCB3aGVuIGEgZGlhbG9nIG9wZW5zIGlzIG5vdCB3b3J0aCB0aGF0IHJpc2suXG4gIHByaXZhdGUgX2xvYWRTcWwoKTogdm9pZCB7XG4gICAgdGhpcy5fcmVwb3J0RGF0YS5jb21wb25lbnRTcWwodGhpcy5yZXBvcnQuaWQsIHRoaXMuY29tcG9uZW50LmlkKVxuICAgICAgLnN1YnNjcmliZSh7XG4gICAgICAgIG5leHQ6IChwcmV2aWV3OiBSZXBvcnRDb21wb25lbnRTcWwpID0+IHtcbiAgICAgICAgICB0aGlzLnNxbC5zZXQocHJldmlldz8uc3FsID8/IG51bGwpO1xuICAgICAgICAgIHRoaXMuc3FsQmFzZWxpbmUuc2V0KCEhcHJldmlldz8uYmFzZWxpbmUpO1xuICAgICAgICAgIHRoaXMuc3FsVGltZXpvbmUuc2V0KHByZXZpZXc/LnRpbWV6b25lIHx8ICdVVEMnKTtcbiAgICAgICAgICB0aGlzLnNxbEVycm9yLnNldChwcmV2aWV3Py5lcnJvciA/PyBudWxsKTtcbiAgICAgICAgfSxcbiAgICAgICAgZXJyb3I6IChlcnJvcikgPT4ge1xuICAgICAgICAgIHRoaXMuc3FsLnNldChudWxsKTtcbiAgICAgICAgICB0aGlzLnNxbEVycm9yLnNldChlcnJvcj8uZXJyb3I/Lm1lc3NhZ2UgPz8gJ0NvdWxkIG5vdCByZWFkIHRoZSBjb21wb25lbnQgU1FMJyk7XG4gICAgICAgIH0sXG4gICAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgX2xvYWRDb2x1bW5zKCk6IHZvaWQge1xuICAgIHRoaXMuX3JlcG9ydERhdGEuY29tcG9uZW50Q29sdW1ucyh0aGlzLnJlcG9ydC5pZCwgdGhpcy5jb21wb25lbnQuaWQpXG4gICAgICAuc3Vic2NyaWJlKHtcbiAgICAgICAgbmV4dDogKGNvbHVtbnM6IFJlcG9ydEZpbHRlcmFibGVDb2x1bW5bXSkgPT4ge1xuICAgICAgICAgIHRoaXMuX2ZpbHRlcmFibGVDb2x1bW5zID0gY29sdW1ucyA/PyBbXTtcbiAgICAgICAgICB0aGlzLl9yZWJ1aWxkUm93cygpO1xuICAgICAgICB9LFxuICAgICAgICBlcnJvcjogKGVycm9yKSA9PiB7XG4gICAgICAgICAgdGhpcy5jb2x1bW5zRXJyb3Iuc2V0KGVycm9yPy5lcnJvcj8ubWVzc2FnZSA/PyAnQ291bGQgbm90IHJlYWQgdGhlIGNvbXBvbmVudCBjb2x1bW5zJyk7XG4gICAgICAgIH0sXG4gICAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgX2h1bWFuaXplKGNvbHVtbjogc3RyaW5nKTogc3RyaW5nIHtcbiAgICByZXR1cm4gY29sdW1uXG4gICAgICAucmVwbGFjZSgvW19cXC1dKy9nLCAnICcpXG4gICAgICAucmVwbGFjZSgvXFxzKy9nLCAnICcpXG4gICAgICAudHJpbSgpXG4gICAgICAucmVwbGFjZSgvXFxiXFx3L2csIChjaGFyYWN0ZXIpID0+IGNoYXJhY3Rlci50b1VwcGVyQ2FzZSgpKTtcbiAgfVxufVxuIiwiPGZvcm1cbiAgICBmc0Zvcm1cbiAgICBbc3VibWl0XT1cInNhdmVcIj5cbiAgPGZzLWRpYWxvZz5cbiAgICA8aDEgbWF0LWRpYWxvZy10aXRsZT5cbiAgICAgIHt7IGNvbXBvbmVudC50aXRsZSB8fCAoaXNWYWx1ZSgpID8gJ1ZhbHVlJyA6ICdDb21wb25lbnQnKSB9fVxuICAgIDwvaDE+XG4gICAgPG1hdC1kaWFsb2ctY29udGVudD5cbiAgICAgIDxtYXQtdGFiLWdyb3VwIFsoc2VsZWN0ZWQpXT1cInNlbGVjdGVkVGFiXCI+XG4gICAgICAgIDxtYXQtdGFiXG4gICAgICAgICAgICBsYWJlbD1cIlNldHRpbmdzXCJcbiAgICAgICAgICAgIG5hbWU9XCJzZXR0aW5nc1wiPlxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJmcy1jb2x1bW4gdGFiLWJvZHlcIj5cbiAgICAgICAgICAgIDxtYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgICAgPG1hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICB7eyBpc1ZhbHVlKCkgPyAnTmFtZScgOiAnVGl0bGUnIH19XG4gICAgICAgICAgICAgIDwvbWF0LWxhYmVsPlxuICAgICAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgICAgICBtYXRJbnB1dFxuICAgICAgICAgICAgICAgIFsobmdNb2RlbCldPVwidGl0bGVcIlxuICAgICAgICAgICAgICAgIG5hbWU9XCJ0aXRsZVwiXG4gICAgICAgICAgICAgICAgW2ZzRm9ybVJlcXVpcmVkXT1cImlzVmFsdWUoKVwiPlxuICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgIDwhLS0gQSBmb3JtdWxhIHZhbHVlIGlzIHJlYWQtb25seSBiZXlvbmQgaXRzIG5hbWU6IHdoYXQgaXQgd29ya3NcbiAgICAgICAgICAgICAgICAgb3V0IGlzIHRoZSBBSSdzIHRvIGNoYW5nZS4gQSBmb3JtdWxhIHRoaXMgdmlld2VyIGNhbm5vdFxuICAgICAgICAgICAgICAgICByZWFkIGhhcyBubyBsaW5lLCBhbmQgbm8gcm93LiAtLT5cbiAgICAgICAgICAgIEBpZiAoZm9ybXVsYUxpbmUoKSkge1xuICAgICAgICAgICAgICA8ZnMtbGFiZWwtZmllbGQ+XG4gICAgICAgICAgICAgICAgPGZzLWxhYmVsPlxuICAgICAgICAgICAgICAgICAgRm9ybXVsYVxuICAgICAgICAgICAgICAgIDwvZnMtbGFiZWw+XG4gICAgICAgICAgICAgICAge3sgZm9ybXVsYUxpbmUoKSB9fVxuICAgICAgICAgICAgICAgIDxmcy1sYWJlbC1tZXNzYWdlPlxuICAgICAgICAgICAgICAgICAgV29ya2VkIG91dCBvbiB0aGUgc2VydmVyOyBpdCBmb2xsb3dzIHRoZSBmaWx0ZXJzIG9mIHRoZSB2YWx1ZXMgaXQgcmVhZHMuXG4gICAgICAgICAgICAgICAgPC9mcy1sYWJlbC1tZXNzYWdlPlxuICAgICAgICAgICAgICA8L2ZzLWxhYmVsLWZpZWxkPlxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgPCEtLSBBIHZhbHVlIHNpdHMgaW5zaWRlIGEgdGV4dCBibG9jaydzIHdvcmRzOiBubyBib3gsIG5vIHBhZGRpbmcuIC0tPlxuICAgICAgICAgICAgQGlmICghaXNWYWx1ZSgpKSB7XG4gICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJzdWJoZWFkaW5nLTJcIj5cbiAgICAgICAgICAgICAgICBQYWRkaW5nXG4gICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZ2VvbWV0cnktcm93XCI+XG4gICAgICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgICAgICAgICAgPG1hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICAgICAgVG9wXG4gICAgICAgICAgICAgICAgICA8L21hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICAgIDxpbnB1dFxuICAgICAgICAgICAgICAgICAgICBtYXRJbnB1dFxuICAgICAgICAgICAgICAgICAgICBmc01hc2tOdW1iZXJcbiAgICAgICAgICAgICAgICAgICAgW3NjYWxlXT1cIjNcIlxuICAgICAgICAgICAgICAgICAgICBbKG5nTW9kZWwpXT1cInBhZGRpbmdUb3BcIlxuICAgICAgICAgICAgICAgICAgICBuYW1lPVwicGFkZGluZ1RvcFwiXG4gICAgICAgICAgICAgICAgICAgIFtmc0Zvcm1NaW5dPVwiMFwiPlxuICAgICAgICAgICAgICAgICAgPGRpdiBtYXRUZXh0U3VmZml4PlxuICAgICAgICAgICAgICAgICAgICBpblxuICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgICAgICAgICA8bWF0LWxhYmVsPlxuICAgICAgICAgICAgICAgICAgICBSaWdodFxuICAgICAgICAgICAgICAgICAgPC9tYXQtbGFiZWw+XG4gICAgICAgICAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgICAgICAgICAgbWF0SW5wdXRcbiAgICAgICAgICAgICAgICAgICAgZnNNYXNrTnVtYmVyXG4gICAgICAgICAgICAgICAgICAgIFtzY2FsZV09XCIzXCJcbiAgICAgICAgICAgICAgICAgICAgWyhuZ01vZGVsKV09XCJwYWRkaW5nUmlnaHRcIlxuICAgICAgICAgICAgICAgICAgICBuYW1lPVwicGFkZGluZ1JpZ2h0XCJcbiAgICAgICAgICAgICAgICAgICAgW2ZzRm9ybU1pbl09XCIwXCI+XG4gICAgICAgICAgICAgICAgICA8ZGl2IG1hdFRleHRTdWZmaXg+XG4gICAgICAgICAgICAgICAgICAgIGluXG4gICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgICAgICAgIDxtYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgICAgICAgIDxtYXQtbGFiZWw+XG4gICAgICAgICAgICAgICAgICAgIEJvdHRvbVxuICAgICAgICAgICAgICAgICAgPC9tYXQtbGFiZWw+XG4gICAgICAgICAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgICAgICAgICAgbWF0SW5wdXRcbiAgICAgICAgICAgICAgICAgICAgZnNNYXNrTnVtYmVyXG4gICAgICAgICAgICAgICAgICAgIFtzY2FsZV09XCIzXCJcbiAgICAgICAgICAgICAgICAgICAgWyhuZ01vZGVsKV09XCJwYWRkaW5nQm90dG9tXCJcbiAgICAgICAgICAgICAgICAgICAgbmFtZT1cInBhZGRpbmdCb3R0b21cIlxuICAgICAgICAgICAgICAgICAgICBbZnNGb3JtTWluXT1cIjBcIj5cbiAgICAgICAgICAgICAgICAgIDxkaXYgbWF0VGV4dFN1ZmZpeD5cbiAgICAgICAgICAgICAgICAgICAgaW5cbiAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgICAgICAgICAgPG1hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICAgICAgTGVmdFxuICAgICAgICAgICAgICAgICAgPC9tYXQtbGFiZWw+XG4gICAgICAgICAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgICAgICAgICAgbWF0SW5wdXRcbiAgICAgICAgICAgICAgICAgICAgZnNNYXNrTnVtYmVyXG4gICAgICAgICAgICAgICAgICAgIFtzY2FsZV09XCIzXCJcbiAgICAgICAgICAgICAgICAgICAgWyhuZ01vZGVsKV09XCJwYWRkaW5nTGVmdFwiXG4gICAgICAgICAgICAgICAgICAgIG5hbWU9XCJwYWRkaW5nTGVmdFwiXG4gICAgICAgICAgICAgICAgICAgIFtmc0Zvcm1NaW5dPVwiMFwiPlxuICAgICAgICAgICAgICAgICAgPGRpdiBtYXRUZXh0U3VmZml4PlxuICAgICAgICAgICAgICAgICAgICBpblxuICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICA8IS0tIEEgZGVyaXZlZCBLUEkncyBjYXJkOiB3aGF0IGEgcmlzZSBtZWFucywgYSB0YXJnZXQgYW5kIGFcbiAgICAgICAgICAgICAgICAgc3BhcmtsaW5lLiBUaGUgc2VydmVyIGNvbXB1dGVzIHRoZSBwcm9ncmVzcyBhbmQgdGhlIHBvaW50cy4gLS0+XG4gICAgICAgICAgICBAaWYgKGtwaUNhcmQoKSkge1xuICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwic3ViaGVhZGluZy0yXCI+XG4gICAgICAgICAgICAgICAgQ2FyZFxuICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkIGNsYXNzPVwiZnVsbC13aWR0aFwiPlxuICAgICAgICAgICAgICAgIDxtYXQtbGFiZWw+XG4gICAgICAgICAgICAgICAgICBJbmNyZWFzZSBpc1xuICAgICAgICAgICAgICAgIDwvbWF0LWxhYmVsPlxuICAgICAgICAgICAgICAgIDxtYXQtc2VsZWN0XG4gICAgICAgICAgICAgICAgICAgIFtuZ01vZGVsXT1cImluY3JlYXNlSXMoKVwiXG4gICAgICAgICAgICAgICAgICAgIChuZ01vZGVsQ2hhbmdlKT1cImluY3JlYXNlSXMuc2V0KCRldmVudClcIlxuICAgICAgICAgICAgICAgICAgICBuYW1lPVwiaW5jcmVhc2VJc1wiPlxuICAgICAgICAgICAgICAgICAgQGZvciAob3B0aW9uIG9mIGtwaVBvbGFyaXR5T3B0aW9uczsgdHJhY2sgb3B0aW9uLnZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIDxtYXQtb3B0aW9uIFt2YWx1ZV09XCJvcHRpb24udmFsdWVcIj5cbiAgICAgICAgICAgICAgICAgICAgICB7eyBvcHRpb24ubmFtZSB9fVxuICAgICAgICAgICAgICAgICAgICA8L21hdC1vcHRpb24+XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgPC9tYXQtc2VsZWN0PlxuICAgICAgICAgICAgICAgIDxtYXQtaGludD5cbiAgICAgICAgICAgICAgICAgIENvbG9ycyB0aGUgY2hhbmdlIGFuZCBkZWNpZGVzIHdoZW4gdGhlIHRhcmdldCBpcyBtZXQuXG4gICAgICAgICAgICAgICAgPC9tYXQtaGludD5cbiAgICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkIGNsYXNzPVwiZnVsbC13aWR0aFwiPlxuICAgICAgICAgICAgICAgIDxtYXQtbGFiZWw+XG4gICAgICAgICAgICAgICAgICBUYXJnZXRcbiAgICAgICAgICAgICAgICA8L21hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgICAgICAgIG1hdElucHV0XG4gICAgICAgICAgICAgICAgICBmc01hc2tOdW1iZXJcbiAgICAgICAgICAgICAgICAgIFtzY2FsZV09XCI2XCJcbiAgICAgICAgICAgICAgICAgIFtzaWduZWRdPVwidHJ1ZVwiXG4gICAgICAgICAgICAgICAgICBbbmdNb2RlbF09XCJ0YXJnZXRWYWx1ZSgpXCJcbiAgICAgICAgICAgICAgICAgIChuZ01vZGVsQ2hhbmdlKT1cInRhcmdldFZhbHVlLnNldCgkZXZlbnQpXCJcbiAgICAgICAgICAgICAgICAgIG5hbWU9XCJ0YXJnZXRWYWx1ZVwiXG4gICAgICAgICAgICAgICAgICBbdmFsaWRhdGVdPVwidmFsaWRhdGVUYXJnZXRcIj5cbiAgICAgICAgICAgICAgICBAaWYgKHRhcmdldFBlcmNlbnQoKSkge1xuICAgICAgICAgICAgICAgICAgPGRpdiBtYXRUZXh0U3VmZml4PlxuICAgICAgICAgICAgICAgICAgICAlXG4gICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgPG1hdC1oaW50PlxuICAgICAgICAgICAgICAgICAgVGhlIHZhbHVlIHRvIHJlYWNoLiBMZWF2ZSBlbXB0eSBmb3Igbm8gdGFyZ2V0LlxuICAgICAgICAgICAgICAgIDwvbWF0LWhpbnQ+XG4gICAgICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgICAgIEBpZiAoaGFzVGFyZ2V0KCkpIHtcbiAgICAgICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgY2xhc3M9XCJmdWxsLXdpZHRoXCI+XG4gICAgICAgICAgICAgICAgICA8bWF0LWxhYmVsPlxuICAgICAgICAgICAgICAgICAgICBUYXJnZXQgbGFiZWxcbiAgICAgICAgICAgICAgICAgIDwvbWF0LWxhYmVsPlxuICAgICAgICAgICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICAgICAgICAgIG1hdElucHV0XG4gICAgICAgICAgICAgICAgICAgIFtuZ01vZGVsXT1cInRhcmdldExhYmVsKClcIlxuICAgICAgICAgICAgICAgICAgICAobmdNb2RlbENoYW5nZSk9XCJ0YXJnZXRMYWJlbC5zZXQoJGV2ZW50KVwiXG4gICAgICAgICAgICAgICAgICAgIG5hbWU9XCJ0YXJnZXRMYWJlbFwiPlxuICAgICAgICAgICAgICAgICAgPG1hdC1oaW50PlxuICAgICAgICAgICAgICAgICAgICBTaG93biBiZWZvcmUgdGhlIHRhcmdldCwgc3VjaCBhcyBHb2FsLiBFbXB0eSByZWFkcyBUYXJnZXQuXG4gICAgICAgICAgICAgICAgICA8L21hdC1oaW50PlxuICAgICAgICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgPGZzLWxhYmVsLWZpZWxkPlxuICAgICAgICAgICAgICAgIDxtYXQtc2xpZGUtdG9nZ2xlXG4gICAgICAgICAgICAgICAgICAgIFtuZ01vZGVsXT1cInNwYXJrbGluZSgpXCJcbiAgICAgICAgICAgICAgICAgICAgKG5nTW9kZWxDaGFuZ2UpPVwic3BhcmtsaW5lLnNldCgkZXZlbnQpXCJcbiAgICAgICAgICAgICAgICAgICAgbmFtZT1cInNwYXJrbGluZVwiPlxuICAgICAgICAgICAgICAgICAgU3BhcmtsaW5lXG4gICAgICAgICAgICAgICAgPC9tYXQtc2xpZGUtdG9nZ2xlPlxuICAgICAgICAgICAgICAgIDxtYXQtaGludD5cbiAgICAgICAgICAgICAgICAgIEEgc21hbGwgdHJlbmQgbGluZSBvZiB0aGUgdmFsdWUgb3ZlciBpdHMgbGFzdCBwZXJpb2RzLlxuICAgICAgICAgICAgICAgIDwvbWF0LWhpbnQ+XG4gICAgICAgICAgICAgIDwvZnMtbGFiZWwtZmllbGQ+XG4gICAgICAgICAgICAgIEBpZiAoc3BhcmtsaW5lKCkpIHtcbiAgICAgICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgY2xhc3M9XCJmdWxsLXdpZHRoXCI+XG4gICAgICAgICAgICAgICAgICA8bWF0LWxhYmVsPlxuICAgICAgICAgICAgICAgICAgICBTcGFya2xpbmUgcGVyaW9kXG4gICAgICAgICAgICAgICAgICA8L21hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICAgIDxtYXQtc2VsZWN0XG4gICAgICAgICAgICAgICAgICAgICAgW25nTW9kZWxdPVwic3BhcmtsaW5lR3JhbnVsYXJpdHkoKVwiXG4gICAgICAgICAgICAgICAgICAgICAgKG5nTW9kZWxDaGFuZ2UpPVwic3BhcmtsaW5lR3JhbnVsYXJpdHkuc2V0KCRldmVudClcIlxuICAgICAgICAgICAgICAgICAgICAgIG5hbWU9XCJzcGFya2xpbmVHcmFudWxhcml0eVwiPlxuICAgICAgICAgICAgICAgICAgICBAZm9yIChvcHRpb24gb2YgZ3JhbnVsYXJpdHlPcHRpb25zOyB0cmFjayBvcHRpb24udmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICA8bWF0LW9wdGlvbiBbdmFsdWVdPVwib3B0aW9uLnZhbHVlXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICB7eyBvcHRpb24ubmFtZSB9fVxuICAgICAgICAgICAgICAgICAgICAgIDwvbWF0LW9wdGlvbj5cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgPC9tYXQtc2VsZWN0PlxuICAgICAgICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkIGNsYXNzPVwiZnVsbC13aWR0aFwiPlxuICAgICAgICAgICAgICAgICAgPG1hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICAgICAgU3BhcmtsaW5lIHBlcmlvZHNcbiAgICAgICAgICAgICAgICAgIDwvbWF0LWxhYmVsPlxuICAgICAgICAgICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICAgICAgICAgIG1hdElucHV0XG4gICAgICAgICAgICAgICAgICAgIGZzTWFza051bWJlclxuICAgICAgICAgICAgICAgICAgICBbc2NhbGVdPVwiMFwiXG4gICAgICAgICAgICAgICAgICAgIFtuZ01vZGVsXT1cInNwYXJrbGluZVBlcmlvZHMoKVwiXG4gICAgICAgICAgICAgICAgICAgIChuZ01vZGVsQ2hhbmdlKT1cInNwYXJrbGluZVBlcmlvZHMuc2V0KCRldmVudClcIlxuICAgICAgICAgICAgICAgICAgICBuYW1lPVwic3BhcmtsaW5lUGVyaW9kc1wiXG4gICAgICAgICAgICAgICAgICAgIFtmc0Zvcm1SZXF1aXJlZF09XCJ0cnVlXCJcbiAgICAgICAgICAgICAgICAgICAgW2ZzRm9ybUludGVnZXJdPVwidHJ1ZVwiXG4gICAgICAgICAgICAgICAgICAgIFtmc0Zvcm1NaW5dPVwic3BhcmtsaW5lTWluUGVyaW9kc1wiXG4gICAgICAgICAgICAgICAgICAgIFtmc0Zvcm1NYXhdPVwic3BhcmtsaW5lTWF4UGVyaW9kc1wiPlxuICAgICAgICAgICAgICAgICAgPG1hdC1oaW50PlxuICAgICAgICAgICAgICAgICAgICBIb3cgbWFueSBwZXJpb2RzIHRoZSBsaW5lIGNvdmVycywge3sgc3BhcmtsaW5lTWluUGVyaW9kcyB9fSB0byB7eyBzcGFya2xpbmVNYXhQZXJpb2RzIH19LlxuICAgICAgICAgICAgICAgICAgPC9tYXQtaGludD5cbiAgICAgICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvbWF0LXRhYj5cbiAgICAgICAgPCEtLSBBIGZvcm11bGEgcnVucyBubyBzdGF0ZW1lbnQgYW5kIGZvbGxvd3MgdGhlIGZpbHRlcnMgb2YgdGhlIHZhbHVlc1xuICAgICAgICAgICAgIGl0IHJlYWRzLCBzbyBpdCBoYXMgbmVpdGhlciBhIEZpbHRlcnMgbm9yIGFuIFNRTCB0YWIuIC0tPlxuICAgICAgICBAaWYgKCFpc0Zvcm11bGEoKSkge1xuICAgICAgICAgIDxtYXQtdGFiXG4gICAgICAgICAgICAgIGxhYmVsPVwiRmlsdGVyc1wiXG4gICAgICAgICAgICAgIG5hbWU9XCJmaWx0ZXJzXCI+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwidGFiLWJvZHlcIj5cbiAgICAgICAgICAgICAgQGlmIChjb2x1bW5zRXJyb3IoKSkge1xuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJmaWx0ZXJzLWVtcHR5IGVycm9yXCI+XG4gICAgICAgICAgICAgICAgICB7eyBjb2x1bW5zRXJyb3IoKSB9fVxuICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICB9IEBlbHNlIGlmIChyb3dzKCkubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgPCEtLSBFdmVyeSBmaWx0ZXJhYmxlIGNvbHVtbi4gUGljayB3aGVyZSBpdHMgY29udHJvbCBzaG93czogaW5cbiAgICAgICAgICAgICAgICAgICAgIHRoZSByZXBvcnQgYmFyIChldmVyeSBwYWdlLCBvciB0aGlzIHBhZ2Ugb25seSksIG9uIHRoaXNcbiAgICAgICAgICAgICAgICAgICAgIGNvbXBvbmVudCwgYm90aCwgb3IgbmVpdGhlci4gVGhlIGludGVyZmFjZSBmb2xsb3dzIHRoZVxuICAgICAgICAgICAgICAgICAgICAgZGF0YTsgYSBudW1lcmljIGNvbHVtbiBjYW4gYmUgdmFsdWVzIG9yIGEgbnVtYmVyIHJhbmdlLlxuICAgICAgICAgICAgICAgICAgICAgQSB2YWx1ZSBzaXRzIGluc2lkZSB0ZXh0IGFuZCBoYXMgbm8gY29tcG9uZW50IHRvIHNob3cgYVxuICAgICAgICAgICAgICAgICAgICAgY29udHJvbCBvbiwgc28gaXQgZ2V0cyB0aGUgcmVwb3J0IGJhciBjb2x1bW4gb25seS4gLS0+XG4gICAgICAgICAgICAgICAgPHRhYmxlIGNsYXNzPVwiZmlsdGVyLXRhYmxlXCI+XG4gICAgICAgICAgICAgICAgICA8dGhlYWQ+XG4gICAgICAgICAgICAgICAgICAgIDx0cj5cbiAgICAgICAgICAgICAgICAgICAgICA8dGggY2xhc3M9XCJmaWx0ZXItY29sLW5hbWVcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgIEZpbHRlclxuICAgICAgICAgICAgICAgICAgICAgIDwvdGg+XG4gICAgICAgICAgICAgICAgICAgICAgPHRoIGNsYXNzPVwiZmlsdGVyLWNvbC10eXBlXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICBUeXBlXG4gICAgICAgICAgICAgICAgICAgICAgPC90aD5cbiAgICAgICAgICAgICAgICAgICAgICA8dGggY2xhc3M9XCJmaWx0ZXItY29sLXNlbGVjdFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgUmVwb3J0IGJhclxuICAgICAgICAgICAgICAgICAgICAgIDwvdGg+XG4gICAgICAgICAgICAgICAgICAgICAgQGlmICghaXNWYWx1ZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICA8dGggY2xhc3M9XCJmaWx0ZXItY29sLXRvZ2dsZVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICBUaGlzIGNvbXBvbmVudFxuICAgICAgICAgICAgICAgICAgICAgICAgPC90aD5cbiAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIDwvdHI+XG4gICAgICAgICAgICAgICAgICA8L3RoZWFkPlxuICAgICAgICAgICAgICAgICAgPHRib2R5PlxuICAgICAgICAgICAgICAgICAgICBAZm9yIChyb3cgb2Ygcm93cygpOyB0cmFjayByb3cuY29sdW1uKSB7XG4gICAgICAgICAgICAgICAgICAgICAgPHRyPlxuICAgICAgICAgICAgICAgICAgICAgICAgPHRkIGNsYXNzPVwiZmlsdGVyLWNvbC1uYW1lXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHt7IHJvdy5sYWJlbCB9fVxuICAgICAgICAgICAgICAgICAgICAgICAgPC90ZD5cbiAgICAgICAgICAgICAgICAgICAgICAgIDx0ZCBjbGFzcz1cImZpbHRlci1jb2wtdHlwZVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICBAaWYgKHJvdy50eXBlU2VsZWN0LnNob3cpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bWF0LWZvcm0tZmllbGRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW3N1YnNjcmlwdFNpemluZ109XCInZHluYW1pYydcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbbWF0VG9vbHRpcF09XCJyb3cudHlwZVNlbGVjdC50b29sdGlwXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bWF0LXNlbGVjdFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtwYW5lbFdpZHRoXT1cIm51bGxcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtuZ01vZGVsXT1cInJvdy50eXBlXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAobmdNb2RlbENoYW5nZSk9XCJzZXRUeXBlKHJvdywgJGV2ZW50KVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW25nTW9kZWxPcHRpb25zXT1cInsgc3RhbmRhbG9uZTogdHJ1ZSB9XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbZGlzYWJsZWRdPVwicm93LnR5cGVTZWxlY3QuZGlzYWJsZWRcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFyaWEtbGFiZWw9XCJUeXBlXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEBmb3IgKG9wdGlvbiBvZiB0eXBlT3B0aW9uczsgdHJhY2sgb3B0aW9uLnZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPG1hdC1vcHRpb24gW3ZhbHVlXT1cIm9wdGlvbi52YWx1ZVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAge3sgb3B0aW9uLm5hbWUgfX1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L21hdC1vcHRpb24+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvbWF0LXNlbGVjdD5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgICAgICAgICAgICAgICAgICB9IEBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB7eyB0eXBlTGFiZWwocm93LnR5cGUpIH19XG4gICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvdGQ+XG4gICAgICAgICAgICAgICAgICAgICAgICA8dGQgY2xhc3M9XCJmaWx0ZXItY29sLXNlbGVjdFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgW3N1YnNjcmlwdFNpemluZ109XCInZHluYW1pYydcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bWF0LXNlbGVjdFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbcGFuZWxXaWR0aF09XCJudWxsXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW25nTW9kZWxdPVwicm93LnBsYWNlbWVudFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChuZ01vZGVsQ2hhbmdlKT1cInNldFBsYWNlbWVudChyb3csICRldmVudClcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbbmdNb2RlbE9wdGlvbnNdPVwieyBzdGFuZGFsb25lOiB0cnVlIH1cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcmlhLWxhYmVsPVwiUmVwb3J0IGJhclwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQGZvciAob3B0aW9uIG9mIHJvdy5wbGFjZW1lbnRPcHRpb25zOyB0cmFjayBvcHRpb24udmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPG1hdC1vcHRpb24gW3ZhbHVlXT1cIm9wdGlvbi52YWx1ZVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHt7IG9wdGlvbi5uYW1lIH19XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvbWF0LW9wdGlvbj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L21hdC1zZWxlY3Q+XG4gICAgICAgICAgICAgICAgICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgICAgICAgICAgICAgICA8L3RkPlxuICAgICAgICAgICAgICAgICAgICAgICAgQGlmICghaXNWYWx1ZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIDx0ZCBjbGFzcz1cImZpbHRlci1jb2wtdG9nZ2xlXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPG1hdC1zbGlkZS10b2dnbGVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtuZ01vZGVsXT1cInJvdy5jb21wb25lbnRcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKG5nTW9kZWxDaGFuZ2UpPVwic2V0Q29tcG9uZW50KHJvdywgJGV2ZW50KVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbbmdNb2RlbE9wdGlvbnNdPVwieyBzdGFuZGFsb25lOiB0cnVlIH1cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW2Rpc2FibGVkXT1cInJvdy5jb21wb25lbnRUb2dnbGUuZGlzYWJsZWRcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW21hdFRvb2x0aXBdPVwicm93LmNvbXBvbmVudFRvZ2dsZS50b29sdGlwXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9tYXQtc2xpZGUtdG9nZ2xlPlxuICAgICAgICAgICAgICAgICAgICAgICAgICA8L3RkPlxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgIDwvdHI+XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIDwvdGJvZHk+XG4gICAgICAgICAgICAgICAgPC90YWJsZT5cbiAgICAgICAgICAgICAgfSBAZWxzZSB7XG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImZpbHRlcnMtZW1wdHlcIj5cbiAgICAgICAgICAgICAgICAgIFRoaXMgY29tcG9uZW50IGhhcyBubyBmaWx0ZXJhYmxlIGNvbHVtbnMgeWV0IOKAlCBnaXZlIGl0IHNvbWUgU1FMIGZpcnN0LlxuICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICA8L21hdC10YWI+XG4gICAgICAgICAgPG1hdC10YWJcbiAgICAgICAgICAgICAgbGFiZWw9XCJTUUxcIlxuICAgICAgICAgICAgICBuYW1lPVwic3FsXCI+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwidGFiLWJvZHlcIj5cbiAgICAgICAgICAgICAgQGlmIChzcWxFcnJvcigpKSB7XG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImZpbHRlcnMtZW1wdHkgZXJyb3JcIj5cbiAgICAgICAgICAgICAgICAgIHt7IHNxbEVycm9yKCkgfX1cbiAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgfSBAZWxzZSBpZiAoc3FsKCkpIHtcbiAgICAgICAgICAgICAgICBAaWYgKHNxbEJhc2VsaW5lKCkpIHtcbiAgICAgICAgICAgICAgICAgIDwhLS0gQSBkZXJpdmVkIGNvbXBvbmVudCdzIHN0YXRlbWVudCBpcyBjb21waWxlZCBmcm9tIGl0c1xuICAgICAgICAgICAgICAgICAgICAgICBkb2N1bWVudCB3aXRoIG5vIHZpZXdlciBzdGF0ZSwgc28gaXQgaXMgbm90IGJ5dGUtZm9yLWJ5dGVcbiAgICAgICAgICAgICAgICAgICAgICAgd2hhdCBwcm9kdWNlZCB0aGUgbnVtYmVycyBvbiBzY3JlZW4uIFNhaWQgaGVyZSByYXRoZXIgdGhhblxuICAgICAgICAgICAgICAgICAgICAgICBsZWZ0IGZvciB0aGUgcmVhZGVyIHRvIGRpc2NvdmVyLiAtLT5cbiAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJmaWx0ZXJzLWVtcHR5XCI+XG4gICAgICAgICAgICAgICAgICAgIENvbXBpbGVkIGZyb20gdGhpcyBjb21wb25lbnQncyBxdWVyeSDigJQgbm8gZmlsdGVycyBhcHBsaWVkLCB0aW1lcyBpbiB7eyBzcWxUaW1lem9uZSgpIH19LlxuICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIDxwcmUgY2xhc3M9XCJjb2RlLWJsb2NrXCI+e3sgc3FsKCkgfX08L3ByZT5cbiAgICAgICAgICAgICAgfSBAZWxzZSB7XG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImZpbHRlcnMtZW1wdHlcIj5cbiAgICAgICAgICAgICAgICAgIFRoaXMgY29tcG9uZW50IGhhcyBubyBTUUwgeWV0LlxuICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICA8L21hdC10YWI+XG4gICAgICAgIH1cbiAgICAgICAgPG1hdC10YWJcbiAgICAgICAgICAgIGxhYmVsPVwiQ29uZmlnXCJcbiAgICAgICAgICAgIG5hbWU9XCJjb25maWdcIj5cbiAgICAgICAgICA8ZGl2IGNsYXNzPVwidGFiLWJvZHlcIj5cbiAgICAgICAgICAgIDxwcmUgY2xhc3M9XCJjb2RlLWJsb2NrXCI+XG4gICAgICAgICAgICAgIHt7IGNvbmZpZ0pzb24gfX1cbiAgICAgICAgICAgIDwvcHJlPlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L21hdC10YWI+XG4gICAgICA8L21hdC10YWItZ3JvdXA+XG4gICAgPC9tYXQtZGlhbG9nLWNvbnRlbnQ+XG4gICAgPG1hdC1kaWFsb2ctYWN0aW9ucz5cbiAgICAgIDwhLS0gU2F2ZSB8IERlbGV0ZSB8IENhbmNlbCwgdGhlIHN0YW5kYXJkIG9yZGVyLiBmcy1mb3JtLWRpYWxvZy1hY3Rpb25zXG4gICAgICAgICAgIHJlbmRlcnMgaXRzIG93biBTYXZlL0RvbmUgQkVGT1JFIHRoZSBwcm9qZWN0ZWQgY29udGVudCwgd2hpY2ggd291bGRcbiAgICAgICAgICAgcHV0IERlbGV0ZSBhZnRlciBDYW5jZWwsIHNvIGBbc2F2ZV09XCJmYWxzZVwiYCBmb290cyB0aGUgcm93IGhlcmUgYW5kXG4gICAgICAgICAgIGFsbCB0aHJlZSBidXR0b25zIGFyZSBwcm9qZWN0ZWQgaW4gb3JkZXIuIFNhdmUgc3VibWl0cyB0aGUgU2V0dGluZ3NcbiAgICAgICAgICAgdGFiOyB0aGUgb3RoZXIgdGFicyBwZXJzaXN0IGFzIHlvdSB0b3VjaCB0aGVtLCBzbyB0aGV5IGdldCBEb25lLiAtLT5cbiAgICAgIDxmcy1mb3JtLWRpYWxvZy1hY3Rpb25zIFtzYXZlXT1cImZhbHNlXCI+XG4gICAgICAgIEBpZiAoc2VsZWN0ZWRUYWIgPT09ICdzZXR0aW5ncycpIHtcbiAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICAgIG1hdC1idXR0b25cbiAgICAgICAgICAgICAgdHlwZT1cInN1Ym1pdFwiXG4gICAgICAgICAgICAgIGNvbG9yPVwicHJpbWFyeVwiPlxuICAgICAgICAgICAgU2F2ZVxuICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICB9IEBlbHNlIHtcbiAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICAgIG1hdC1idXR0b25cbiAgICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgICAgICAgIGNvbG9yPVwicHJpbWFyeVwiXG4gICAgICAgICAgICAgIFttYXQtZGlhbG9nLWNsb3NlXT1cIm51bGxcIj5cbiAgICAgICAgICAgIERvbmVcbiAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgfVxuICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICBtYXQtYnV0dG9uXG4gICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgICAgIGNvbG9yPVwid2FyblwiXG4gICAgICAgICAgICAoY2xpY2spPVwiZGVsZXRlKClcIj5cbiAgICAgICAgICBEZWxldGVcbiAgICAgICAgPC9idXR0b24+XG4gICAgICAgIDxidXR0b25cbiAgICAgICAgICAgIG1hdC1idXR0b25cbiAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICAgICAgY2xhc3M9XCJjYW5jZWwtYnV0dG9uXCJcbiAgICAgICAgICAgIFttYXQtZGlhbG9nLWNsb3NlXT1cIm51bGxcIj5cbiAgICAgICAgICBDYW5jZWxcbiAgICAgICAgPC9idXR0b24+XG4gICAgICA8L2ZzLWZvcm0tZGlhbG9nLWFjdGlvbnM+XG4gICAgPC9tYXQtZGlhbG9nLWFjdGlvbnM+XG4gIDwvZnMtZGlhbG9nPlxuPC9mb3JtPiJdfQ==