ng-kinintel 0.0.397 → 20.0.2

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 (184) hide show
  1. package/fesm2022/ng-kinintel.mjs +11874 -0
  2. package/fesm2022/ng-kinintel.mjs.map +1 -0
  3. package/index.d.ts +2818 -5
  4. package/package.json +6 -14
  5. package/esm2020/lib/components/alert-groups/alert-groups.component.mjs +0 -76
  6. package/esm2020/lib/components/alert-groups/edit-alert-group/edit-alert-group.component.mjs +0 -83
  7. package/esm2020/lib/components/dashboard-editor/configure-item/configure-item.component.mjs +0 -853
  8. package/esm2020/lib/components/dashboard-editor/configure-item/edit-dashboard-alert/edit-dashboard-alert.component.mjs +0 -56
  9. package/esm2020/lib/components/dashboard-editor/configure-item/html-documentation/html-documentation.component.mjs +0 -114
  10. package/esm2020/lib/components/dashboard-editor/configure-item/table-cell-formatter/table-cell-formatter.component.mjs +0 -163
  11. package/esm2020/lib/components/dashboard-editor/configure-item/vis-network-options.json +0 -135
  12. package/esm2020/lib/components/dashboard-editor/dashboard-editor.component.mjs +0 -580
  13. package/esm2020/lib/components/dashboard-editor/dashboard-parameter/dashboard-parameter.component.mjs +0 -15
  14. package/esm2020/lib/components/dashboard-editor/dashboard-settings/dashboard-settings.component.mjs +0 -50
  15. package/esm2020/lib/components/dashboard-editor/item-component/item-component.component.mjs +0 -1226
  16. package/esm2020/lib/components/dashboard-editor/source-selector-dialog/source-selector-dialog.component.mjs +0 -111
  17. package/esm2020/lib/components/dashboards/dashboards.component.mjs +0 -163
  18. package/esm2020/lib/components/dashboards/view-dashboard/view-dashboard.component.mjs +0 -429
  19. package/esm2020/lib/components/data-explorer/change-source-warning/change-source-warning.component.mjs +0 -20
  20. package/esm2020/lib/components/data-explorer/data-explorer.component.mjs +0 -243
  21. package/esm2020/lib/components/data-explorer/export-data/export-data.component.mjs +0 -62
  22. package/esm2020/lib/components/data-explorer/snapshot-api-access/snapshot-api-access.component.mjs +0 -70
  23. package/esm2020/lib/components/data-explorer/snapshot-profile-dialog/snapshot-profile-dialog.component.mjs +0 -190
  24. package/esm2020/lib/components/data-picker/data-picker.component.mjs +0 -79
  25. package/esm2020/lib/components/data-search/data-search.component.mjs +0 -11
  26. package/esm2020/lib/components/data-sharing-invite/data-sharing-invite.component.mjs +0 -52
  27. package/esm2020/lib/components/dataset/create-dataset/create-dataset.component.mjs +0 -47
  28. package/esm2020/lib/components/dataset/dataset-editor/available-columns/available-columns.component.mjs +0 -28
  29. package/esm2020/lib/components/dataset/dataset-editor/dataset-add-join/dataset-add-join.component.mjs +0 -344
  30. package/esm2020/lib/components/dataset/dataset-editor/dataset-column-settings/dataset-column-editor/dataset-column-editor.component.mjs +0 -80
  31. package/esm2020/lib/components/dataset/dataset-editor/dataset-column-settings/dataset-column-settings.component.mjs +0 -54
  32. package/esm2020/lib/components/dataset/dataset-editor/dataset-create-formula/dataset-create-formula.component.mjs +0 -67
  33. package/esm2020/lib/components/dataset/dataset-editor/dataset-editor.component.mjs +0 -1134
  34. package/esm2020/lib/components/dataset/dataset-editor/dataset-filters/dataset-filter/dataset-filter.component.mjs +0 -201
  35. package/esm2020/lib/components/dataset/dataset-editor/dataset-filters/dataset-filter-inclusion/dataset-filter-inclusion.component.mjs +0 -25
  36. package/esm2020/lib/components/dataset/dataset-editor/dataset-filters/dataset-filter-junction/dataset-filter-junction.component.mjs +0 -72
  37. package/esm2020/lib/components/dataset/dataset-editor/dataset-filters/dataset-filters.component.mjs +0 -62
  38. package/esm2020/lib/components/dataset/dataset-editor/dataset-name-dialog/dataset-name-dialog.component.mjs +0 -41
  39. package/esm2020/lib/components/dataset/dataset-editor/dataset-parameter-values/dataset-add-parameter/dataset-add-parameter.component.mjs +0 -78
  40. package/esm2020/lib/components/dataset/dataset-editor/dataset-parameter-values/dataset-parameter-type/dataset-parameter-type.component.mjs +0 -39
  41. package/esm2020/lib/components/dataset/dataset-editor/dataset-parameter-values/dataset-parameter-values.component.mjs +0 -75
  42. package/esm2020/lib/components/dataset/dataset-editor/dataset-summarise/dataset-summarise.component.mjs +0 -107
  43. package/esm2020/lib/components/dataset/dataset-editor/move-transformation-confirmation/move-transformation-confirmation.component.mjs +0 -20
  44. package/esm2020/lib/components/dataset/dataset-editor/remove-transformation-warning/remove-transformation-warning.component.mjs +0 -20
  45. package/esm2020/lib/components/dataset/dataset-editor/save-as-query/save-as-query.component.mjs +0 -58
  46. package/esm2020/lib/components/dataset/dataset-editor/share-query/share-query.component.mjs +0 -110
  47. package/esm2020/lib/components/dataset/dataset-editor/upstream-changes-confirmation/upstream-changes-confirmation.component.mjs +0 -20
  48. package/esm2020/lib/components/dataset/dataset.component.mjs +0 -294
  49. package/esm2020/lib/components/datasource/create-datasource/advanced-settings/advanced-settings.component.mjs +0 -130
  50. package/esm2020/lib/components/datasource/create-datasource/api-access/api-access.component.mjs +0 -132
  51. package/esm2020/lib/components/datasource/create-datasource/create-datasource.component.mjs +0 -729
  52. package/esm2020/lib/components/datasource/create-datasource/import-data/import-data.component.mjs +0 -146
  53. package/esm2020/lib/components/datasource/create-datasource/import-data/import-wizard/import-wizard.component.mjs +0 -165
  54. package/esm2020/lib/components/datasource/create-datasource/tabular-datasource/tabular-datasource.component.mjs +0 -145
  55. package/esm2020/lib/components/datasource/datasource.component.mjs +0 -162
  56. package/esm2020/lib/components/datasource/document-datasource/document-datasource.component.mjs +0 -297
  57. package/esm2020/lib/components/export-project/export-project.component.mjs +0 -29
  58. package/esm2020/lib/components/feeds/feed/feed.component.mjs +0 -92
  59. package/esm2020/lib/components/feeds/feeds.component.mjs +0 -145
  60. package/esm2020/lib/components/job-tasks/job-tasks.component.mjs +0 -25
  61. package/esm2020/lib/components/marketplace/marketplace.component.mjs +0 -65
  62. package/esm2020/lib/components/metadata/metadata.component.mjs +0 -65
  63. package/esm2020/lib/components/notification-groups/edit-notification-group/edit-notification-group.component.mjs +0 -113
  64. package/esm2020/lib/components/notification-groups/notification-groups.component.mjs +0 -86
  65. package/esm2020/lib/components/project-picker/project-picker.component.mjs +0 -118
  66. package/esm2020/lib/components/project-settings/project-link-selection/project-link-selection.component.mjs +0 -104
  67. package/esm2020/lib/components/project-settings/project-settings.component.mjs +0 -155
  68. package/esm2020/lib/components/query-caching/edit-query-cache/edit-query-cache.component.mjs +0 -51
  69. package/esm2020/lib/components/query-caching/query-cache-view/query-cache-view.component.mjs +0 -121
  70. package/esm2020/lib/components/query-caching/query-caching.component.mjs +0 -162
  71. package/esm2020/lib/components/shared-with-me/feed-api-modal/feed-api-modal.component.mjs +0 -45
  72. package/esm2020/lib/components/shared-with-me/shared-with-me.component.mjs +0 -174
  73. package/esm2020/lib/components/snapshots/snapshots.component.mjs +0 -244
  74. package/esm2020/lib/components/tag-picker/tag-picker.component.mjs +0 -74
  75. package/esm2020/lib/components/task-time-periods/task-time-periods.component.mjs +0 -55
  76. package/esm2020/lib/components/whitelisted-sql-functions/whitelisted-sql-functions.component.mjs +0 -40
  77. package/esm2020/lib/guards/dashboard-changes.guard.mjs +0 -22
  78. package/esm2020/lib/kinintel-config.mjs +0 -3
  79. package/esm2020/lib/ng-kinintel.module.mjs +0 -437
  80. package/esm2020/lib/objects/action-event.mjs +0 -16
  81. package/esm2020/lib/services/alert.service.mjs +0 -52
  82. package/esm2020/lib/services/dashboard.service.mjs +0 -75
  83. package/esm2020/lib/services/data-processor.service.mjs +0 -56
  84. package/esm2020/lib/services/data-search.service.mjs +0 -36
  85. package/esm2020/lib/services/dataset.service.mjs +0 -187
  86. package/esm2020/lib/services/datasource.service.mjs +0 -93
  87. package/esm2020/lib/services/external.service.mjs +0 -33
  88. package/esm2020/lib/services/feed.service.mjs +0 -50
  89. package/esm2020/lib/services/notification.service.mjs +0 -41
  90. package/esm2020/lib/services/project.service.mjs +0 -130
  91. package/esm2020/lib/services/tag.service.mjs +0 -63
  92. package/esm2020/ng-kinintel.mjs +0 -5
  93. package/esm2020/public-api.mjs +0 -43
  94. package/fesm2015/ng-kinintel.mjs +0 -12182
  95. package/fesm2015/ng-kinintel.mjs.map +0 -1
  96. package/fesm2020/ng-kinintel.mjs +0 -11872
  97. package/fesm2020/ng-kinintel.mjs.map +0 -1
  98. package/lib/components/alert-groups/alert-groups.component.d.ts +0 -30
  99. package/lib/components/alert-groups/edit-alert-group/edit-alert-group.component.d.ts +0 -28
  100. package/lib/components/dashboard-editor/configure-item/configure-item.component.d.ts +0 -256
  101. package/lib/components/dashboard-editor/configure-item/edit-dashboard-alert/edit-dashboard-alert.component.d.ts +0 -16
  102. package/lib/components/dashboard-editor/configure-item/html-documentation/html-documentation.component.d.ts +0 -59
  103. package/lib/components/dashboard-editor/configure-item/table-cell-formatter/table-cell-formatter.component.d.ts +0 -26
  104. package/lib/components/dashboard-editor/dashboard-editor.component.d.ts +0 -85
  105. package/lib/components/dashboard-editor/dashboard-parameter/dashboard-parameter.component.d.ts +0 -8
  106. package/lib/components/dashboard-editor/dashboard-settings/dashboard-settings.component.d.ts +0 -22
  107. package/lib/components/dashboard-editor/item-component/item-component.component.d.ts +0 -264
  108. package/lib/components/dashboard-editor/source-selector-dialog/source-selector-dialog.component.d.ts +0 -30
  109. package/lib/components/dashboards/dashboards.component.d.ts +0 -56
  110. package/lib/components/dashboards/view-dashboard/view-dashboard.component.d.ts +0 -81
  111. package/lib/components/data-explorer/change-source-warning/change-source-warning.component.d.ts +0 -11
  112. package/lib/components/data-explorer/data-explorer.component.d.ts +0 -61
  113. package/lib/components/data-explorer/export-data/export-data.component.d.ts +0 -17
  114. package/lib/components/data-explorer/snapshot-api-access/snapshot-api-access.component.d.ts +0 -25
  115. package/lib/components/data-explorer/snapshot-profile-dialog/snapshot-profile-dialog.component.d.ts +0 -44
  116. package/lib/components/data-picker/data-picker.component.d.ts +0 -32
  117. package/lib/components/data-search/data-search.component.d.ts +0 -5
  118. package/lib/components/data-sharing-invite/data-sharing-invite.component.d.ts +0 -21
  119. package/lib/components/dataset/create-dataset/create-dataset.component.d.ts +0 -17
  120. package/lib/components/dataset/dataset-editor/available-columns/available-columns.component.d.ts +0 -12
  121. package/lib/components/dataset/dataset-editor/dataset-add-join/dataset-add-join.component.d.ts +0 -61
  122. package/lib/components/dataset/dataset-editor/dataset-column-settings/dataset-column-editor/dataset-column-editor.component.d.ts +0 -21
  123. package/lib/components/dataset/dataset-editor/dataset-column-settings/dataset-column-settings.component.d.ts +0 -20
  124. package/lib/components/dataset/dataset-editor/dataset-create-formula/dataset-create-formula.component.d.ts +0 -19
  125. package/lib/components/dataset/dataset-editor/dataset-editor.component.d.ts +0 -131
  126. package/lib/components/dataset/dataset-editor/dataset-filters/dataset-filter/dataset-filter.component.d.ts +0 -63
  127. package/lib/components/dataset/dataset-editor/dataset-filters/dataset-filter-inclusion/dataset-filter-inclusion.component.d.ts +0 -11
  128. package/lib/components/dataset/dataset-editor/dataset-filters/dataset-filter-junction/dataset-filter-junction.component.d.ts +0 -20
  129. package/lib/components/dataset/dataset-editor/dataset-filters/dataset-filters.component.d.ts +0 -16
  130. package/lib/components/dataset/dataset-editor/dataset-name-dialog/dataset-name-dialog.component.d.ts +0 -18
  131. package/lib/components/dataset/dataset-editor/dataset-parameter-values/dataset-add-parameter/dataset-add-parameter.component.d.ts +0 -23
  132. package/lib/components/dataset/dataset-editor/dataset-parameter-values/dataset-parameter-type/dataset-parameter-type.component.d.ts +0 -13
  133. package/lib/components/dataset/dataset-editor/dataset-parameter-values/dataset-parameter-values.component.d.ts +0 -22
  134. package/lib/components/dataset/dataset-editor/dataset-summarise/dataset-summarise.component.d.ts +0 -27
  135. package/lib/components/dataset/dataset-editor/move-transformation-confirmation/move-transformation-confirmation.component.d.ts +0 -11
  136. package/lib/components/dataset/dataset-editor/remove-transformation-warning/remove-transformation-warning.component.d.ts +0 -11
  137. package/lib/components/dataset/dataset-editor/save-as-query/save-as-query.component.d.ts +0 -25
  138. package/lib/components/dataset/dataset-editor/share-query/share-query.component.d.ts +0 -41
  139. package/lib/components/dataset/dataset-editor/upstream-changes-confirmation/upstream-changes-confirmation.component.d.ts +0 -11
  140. package/lib/components/dataset/dataset.component.d.ts +0 -74
  141. package/lib/components/datasource/create-datasource/advanced-settings/advanced-settings.component.d.ts +0 -26
  142. package/lib/components/datasource/create-datasource/api-access/api-access.component.d.ts +0 -31
  143. package/lib/components/datasource/create-datasource/create-datasource.component.d.ts +0 -112
  144. package/lib/components/datasource/create-datasource/import-data/import-data.component.d.ts +0 -28
  145. package/lib/components/datasource/create-datasource/import-data/import-wizard/import-wizard.component.d.ts +0 -40
  146. package/lib/components/datasource/create-datasource/tabular-datasource/tabular-datasource.component.d.ts +0 -34
  147. package/lib/components/datasource/datasource.component.d.ts +0 -46
  148. package/lib/components/datasource/document-datasource/document-datasource.component.d.ts +0 -64
  149. package/lib/components/export-project/export-project.component.d.ts +0 -9
  150. package/lib/components/feeds/feed/feed.component.d.ts +0 -30
  151. package/lib/components/feeds/feeds.component.d.ts +0 -47
  152. package/lib/components/job-tasks/job-tasks.component.d.ts +0 -11
  153. package/lib/components/marketplace/marketplace.component.d.ts +0 -42
  154. package/lib/components/metadata/metadata.component.d.ts +0 -24
  155. package/lib/components/notification-groups/edit-notification-group/edit-notification-group.component.d.ts +0 -37
  156. package/lib/components/notification-groups/notification-groups.component.d.ts +0 -28
  157. package/lib/components/project-picker/project-picker.component.d.ts +0 -37
  158. package/lib/components/project-settings/project-link-selection/project-link-selection.component.d.ts +0 -32
  159. package/lib/components/project-settings/project-settings.component.d.ts +0 -40
  160. package/lib/components/query-caching/edit-query-cache/edit-query-cache.component.d.ts +0 -17
  161. package/lib/components/query-caching/query-cache-view/query-cache-view.component.d.ts +0 -35
  162. package/lib/components/query-caching/query-caching.component.d.ts +0 -38
  163. package/lib/components/shared-with-me/feed-api-modal/feed-api-modal.component.d.ts +0 -21
  164. package/lib/components/shared-with-me/shared-with-me.component.d.ts +0 -43
  165. package/lib/components/snapshots/snapshots.component.d.ts +0 -52
  166. package/lib/components/tag-picker/tag-picker.component.d.ts +0 -27
  167. package/lib/components/task-time-periods/task-time-periods.component.d.ts +0 -20
  168. package/lib/components/whitelisted-sql-functions/whitelisted-sql-functions.component.d.ts +0 -17
  169. package/lib/guards/dashboard-changes.guard.d.ts +0 -11
  170. package/lib/kinintel-config.d.ts +0 -10
  171. package/lib/ng-kinintel.module.d.ts +0 -116
  172. package/lib/objects/action-event.d.ts +0 -12
  173. package/lib/services/alert.service.d.ts +0 -17
  174. package/lib/services/dashboard.service.d.ts +0 -25
  175. package/lib/services/data-processor.service.d.ts +0 -18
  176. package/lib/services/data-search.service.d.ts +0 -14
  177. package/lib/services/dataset.service.d.ts +0 -56
  178. package/lib/services/datasource.service.d.ts +0 -34
  179. package/lib/services/external.service.d.ts +0 -12
  180. package/lib/services/feed.service.d.ts +0 -19
  181. package/lib/services/notification.service.d.ts +0 -16
  182. package/lib/services/project.service.d.ts +0 -27
  183. package/lib/services/tag.service.d.ts +0 -19
  184. package/public-api.d.ts +0 -38
@@ -1,1226 +0,0 @@
1
- import { Component, EventEmitter, HostBinding, Input, Output, ViewChild } from '@angular/core';
2
- import { ConfigureItemComponent } from '../configure-item/configure-item.component';
3
- import * as lodash from 'lodash';
4
- import { Subject } from 'rxjs';
5
- import moment from 'moment';
6
- import regression from 'regression';
7
- import { EditDashboardAlertComponent } from '../configure-item/edit-dashboard-alert/edit-dashboard-alert.component';
8
- import { ExportDataComponent } from '../../data-explorer/export-data/export-data.component';
9
- import chroma from 'chroma-js';
10
- import { DataSet, Network } from 'vis-network/standalone';
11
- import visNetworkOptions from '../configure-item/vis-network-options.json';
12
- import * as i0 from "@angular/core";
13
- import * as i1 from "@angular/material/legacy-dialog";
14
- import * as i2 from "../../../services/datasource.service";
15
- import * as i3 from "../../../services/dataset.service";
16
- import * as i4 from "../../../services/alert.service";
17
- import * as i5 from "../../../services/dashboard.service";
18
- import * as i6 from "@angular/platform-browser";
19
- import * as i7 from "@angular/router";
20
- import * as i8 from "@angular/common";
21
- import * as i9 from "../../../services/external.service";
22
- import * as i10 from "../../../services/project.service";
23
- import * as i11 from "@angular/material/legacy-button";
24
- import * as i12 from "@angular/material/icon";
25
- import * as i13 from "ng2-charts";
26
- import * as i14 from "@angular/material/legacy-menu";
27
- import * as i15 from "@angular/forms";
28
- import * as i16 from "@angular/material/legacy-slide-toggle";
29
- import * as i17 from "@angular/material/divider";
30
- import * as i18 from "@angular/material/legacy-tooltip";
31
- import * as i19 from "angular-d3-cloud";
32
- const _ = lodash.default;
33
- export class ItemComponentComponent {
34
- constructor(dialog, kiDatasourceService, kiDatasetService, kiAlertService, dashboardService, sanitizer, router, location, externalService, projectService) {
35
- this.dialog = dialog;
36
- this.kiDatasourceService = kiDatasourceService;
37
- this.kiDatasetService = kiDatasetService;
38
- this.kiAlertService = kiAlertService;
39
- this.dashboardService = dashboardService;
40
- this.sanitizer = sanitizer;
41
- this.router = router;
42
- this.location = location;
43
- this.externalService = externalService;
44
- this.projectService = projectService;
45
- this.actionEvents = [];
46
- this.external = false;
47
- this.editAlerts = false;
48
- this.duplicateItem = new EventEmitter();
49
- this.configureClass = false;
50
- this._ = _;
51
- this.imageError = false;
52
- this.Object = Object;
53
- this.String = String;
54
- this.dashboardDatasetInstance = {};
55
- this.loadingItem = false;
56
- this.filterFields = [];
57
- this.dependencies = {};
58
- this.metric = {};
59
- this.textData = {};
60
- this.networkData = {};
61
- this.wordCloud = {};
62
- this.imageData = {};
63
- this.tabular = {};
64
- this.tableCells = {};
65
- this.hiddenColumns = {};
66
- this.general = {};
67
- this.callToAction = {};
68
- this.actionItem = {};
69
- this.alert = false;
70
- this.alertData = [];
71
- this.showAlertData = false;
72
- this.currencies = [
73
- {
74
- name: 'British Pound (£)',
75
- value: 'GBP',
76
- symbol: '£'
77
- },
78
- {
79
- name: 'US Dollar ($)',
80
- value: 'USD',
81
- symbol: '$'
82
- },
83
- {
84
- name: 'Euro (€)',
85
- value: 'EUR',
86
- symbol: '€'
87
- }
88
- ];
89
- this.limit = 25;
90
- this.page = 1;
91
- this.offset = 0;
92
- this.endOfResults = false;
93
- this.itemLocked = false;
94
- this.optimise = true;
95
- this.optimiseSubject = new Subject();
96
- this.canExportData = false;
97
- this.externalError = false;
98
- this.quotaExceeded = null;
99
- this.existingGridItem = false;
100
- this.itemNoMove = false;
101
- this.visNetworkOptions = visNetworkOptions;
102
- }
103
- ngAfterViewInit() {
104
- setTimeout(() => {
105
- this.canExportData = this.projectService.doesActiveProjectHavePrivilege('exportdata');
106
- const instanceElement = document.getElementById(this.itemInstanceKey);
107
- if (instanceElement) {
108
- const widget = instanceElement.closest('.grid-stack-item');
109
- this.itemNoMove = widget.getAttribute('gs-no-move') === 'true';
110
- }
111
- }, 50);
112
- }
113
- async init(evaluate = false) {
114
- this.mapLayoutSettingsToComponentData();
115
- if (this.tabular && this.tabular.limit) {
116
- this.limit = this.tabular.limit;
117
- }
118
- if (this.general && this.general.limit) {
119
- this.limit = this.general.limit;
120
- this.offset = this.general.offset;
121
- }
122
- if (!this.datasourceService) {
123
- this.datasourceService = this.kiDatasourceService;
124
- }
125
- if (!this.datasetService) {
126
- this.datasetService = this.kiDatasetService;
127
- }
128
- if (!this.alertService) {
129
- this.alertService = this.kiAlertService;
130
- }
131
- if (this.dashboard &&
132
- this.dashboard.displaySettings.heading &&
133
- this.dashboard.displaySettings.heading[this.itemInstanceKey]) {
134
- this.dashboardItemType.headingValue = this.dashboard.displaySettings.heading[this.itemInstanceKey];
135
- }
136
- if (this.general.parameterBar && Object.keys(this.general.parameterBar).length) {
137
- if (!this.general.widgetParameters || Array.isArray(this.general.widgetParameters)) {
138
- this.general.widgetParameters = {};
139
- }
140
- Object.keys(this.general.parameterBar).forEach(paramKey => {
141
- if (this.general.parameterBar[paramKey] && !this.general.widgetParameters[paramKey]) {
142
- this.general.widgetParameters[paramKey] = _.cloneDeep(this.dashboard.layoutSettings.parameters[paramKey]);
143
- }
144
- if (!this.general.parameterBar[paramKey]) {
145
- delete this.general.widgetParameters[paramKey];
146
- }
147
- });
148
- }
149
- this.configureClass = true;
150
- if (this.dependencies.instanceKeys && this.dependencies.instanceKeys.length) {
151
- this.loadingItem = true;
152
- this.itemLoadedSub = this.dashboardService.dashboardItems.subscribe(async (loaded) => {
153
- const loadedInstances = Object.keys(loaded);
154
- const dependent = _.filter(loadedInstances, key => {
155
- return this.dependencies.instanceKeys.indexOf(key) > -1;
156
- });
157
- if (dependent.length === this.dependencies.instanceKeys.length) {
158
- if (this.itemLoadedSub) {
159
- this.itemLoadedSub.unsubscribe();
160
- }
161
- const allLoaded = _.every(this.dependencies.instanceKeys, key => {
162
- return this.dependencies[key].type === 'LOADED';
163
- });
164
- if (allLoaded) {
165
- this.evaluate();
166
- }
167
- else {
168
- const matches = _.filter(this.dependencies, { type: 'MATCH' });
169
- const allMatched = [];
170
- for (const dep of matches) {
171
- const selectedDatasetInstance = _.find(this.dashboard.datasetInstances, { instanceKey: dep.key });
172
- if (selectedDatasetInstance) {
173
- const mappedParams = this.getMappedParams(selectedDatasetInstance);
174
- const transformations = _.clone(selectedDatasetInstance.transformationInstances);
175
- transformations.push({ type: 'filter', config: dep.filterJunction });
176
- const datasetInstanceSummary = {
177
- datasetInstanceId: selectedDatasetInstance.datasetInstanceId,
178
- datasourceInstanceKey: selectedDatasetInstance.datasourceInstanceKey,
179
- transformationInstances: transformations,
180
- parameterValues: mappedParams,
181
- parameters: selectedDatasetInstance.parameters
182
- };
183
- let data = null;
184
- if (this.external) {
185
- data = await this.externalService.evaluateDataset(this.dashboard.id, this.itemInstanceKey, selectedDatasetInstance.parameterValues, '0', '1', this.queryParams);
186
- }
187
- else {
188
- data = await this.datasetService.evaluateDataset(datasetInstanceSummary, '0', '1');
189
- }
190
- allMatched.push(data.allData.length === 1);
191
- }
192
- }
193
- if (_.every(allMatched)) {
194
- this.evaluate();
195
- }
196
- else {
197
- this.loadingItem = false;
198
- const itemElement = document.getElementById(this.itemInstanceKey).closest('.grid-stack-item');
199
- itemElement.classList.add('item-disabled');
200
- }
201
- }
202
- }
203
- });
204
- }
205
- else if (evaluate) {
206
- this.evaluate();
207
- }
208
- this.optimiseSub = this.optimiseSubject.subscribe(res => this.optimise = res);
209
- this.existingGridItem = !!_.find(this.dashboard.layoutSettings.grid, item => {
210
- return item.content.includes(this.itemInstanceKey);
211
- });
212
- }
213
- ngOnDestroy() {
214
- if (this.optimiseSub) {
215
- this.optimiseSub.unsubscribe();
216
- }
217
- if (this.itemLoadedSub) {
218
- this.itemLoadedSub.unsubscribe();
219
- }
220
- }
221
- lockItem() {
222
- const itemElement = document.getElementById(this.itemInstanceKey);
223
- const widget = itemElement.closest('.grid-stack-item');
224
- this.itemNoMove = widget.getAttribute('gs-no-move') !== 'true';
225
- this.grid.update(widget, { noMove: this.itemNoMove });
226
- }
227
- duplicate() {
228
- this.duplicateItem.emit(this.itemInstanceKey);
229
- }
230
- configure() {
231
- if (this.dashboardItemType.type === 'heading') {
232
- this.dashboardItemType._editing = true;
233
- }
234
- else {
235
- const queryParams = {};
236
- if (this.admin) {
237
- queryParams.a = true;
238
- }
239
- this.router.navigate([window.location.pathname], {
240
- queryParams,
241
- fragment: _.kebabCase(this.dashboard.title)
242
- });
243
- const dialogRef = this.dialog.open(ConfigureItemComponent, {
244
- width: '100vw',
245
- height: '100vh',
246
- maxWidth: '100vw',
247
- maxHeight: '100vh',
248
- hasBackdrop: false,
249
- data: {
250
- grid: this.grid,
251
- dashboard: this.dashboard,
252
- dashboardDatasetInstance: this.dashboardDatasetInstance,
253
- itemInstanceKey: this.itemInstanceKey,
254
- dashboardItemType: this.dashboardItemType,
255
- admin: this.admin,
256
- actionEvents: this.actionEvents
257
- }
258
- });
259
- dialogRef.afterClosed().subscribe(dashboardDatasetInstance => {
260
- if (dashboardDatasetInstance) {
261
- this.dashboardDatasetInstance = dashboardDatasetInstance;
262
- this.location.back();
263
- this.init(true);
264
- }
265
- });
266
- }
267
- }
268
- load() {
269
- // Check to see if any of the grid items are locked
270
- const grid = this.dashboard.layoutSettings.grid;
271
- const lockedItems = _.filter(grid, 'locked');
272
- this.itemLocked = !!_.find(lockedItems, lockedItem => {
273
- return lockedItem.content.includes(this.itemInstanceKey);
274
- });
275
- if (this.external) {
276
- this.itemLocked = true;
277
- }
278
- if (this.dashboardDatasetInstance) {
279
- return this.evaluate();
280
- }
281
- return Promise.resolve(true);
282
- }
283
- removeWidget(event) {
284
- const message = 'Are your sure you would like to remove this item from your dashboard?';
285
- if (window.confirm(message)) {
286
- const itemElement = document.getElementById(this.itemInstanceKey);
287
- _.remove(this.dashboard.datasetInstances, { instanceKey: this.itemInstanceKey });
288
- const widget = itemElement.closest('.grid-stack-item');
289
- this.grid.removeWidget(widget);
290
- }
291
- }
292
- triggerActionEvent(actionEvent, column, value) {
293
- const action = _.find(this.actionEvents, { name: actionEvent });
294
- if (action) {
295
- action.event.next({ key: column.name, value });
296
- }
297
- }
298
- getActionEventTitle(actionEvent, column, value) {
299
- const action = _.find(this.actionEvents, { name: actionEvent });
300
- let title = '';
301
- if (action) {
302
- title = this.isActionComplete(actionEvent, value) ? action.completeLabel : action.actionLabel;
303
- }
304
- return title;
305
- }
306
- isActionComplete(actionEvent, value) {
307
- let complete = false;
308
- const action = _.find(this.actionEvents, { name: actionEvent });
309
- if (action) {
310
- const findData = {};
311
- findData[action.comparisonField] = value;
312
- complete = _.find(action.data || [], findData);
313
- }
314
- return complete;
315
- }
316
- editItemAlerts(alert, index) {
317
- const dialogRef = this.dialog.open(EditDashboardAlertComponent, {
318
- width: '900px',
319
- height: '750px',
320
- data: {
321
- alert,
322
- filterFields: this.filterFields
323
- }
324
- });
325
- dialogRef.afterClosed().subscribe(alertItem => {
326
- if (alertItem) {
327
- if (!this.dashboardDatasetInstance.alerts) {
328
- this.dashboardDatasetInstance.alerts = [];
329
- }
330
- if (index >= 0) {
331
- this.dashboardDatasetInstance.alerts[index] = alertItem;
332
- }
333
- else {
334
- this.dashboardDatasetInstance.alerts.push(alertItem);
335
- }
336
- this.reloadAlert();
337
- }
338
- });
339
- }
340
- removeAlert(event, alert, i) {
341
- const message = `Are you sure you would like to delete the "${alert.title}" Alert?`;
342
- if (window.confirm(message)) {
343
- this.dashboardDatasetInstance.alerts.splice(i, 1);
344
- this.reloadAlert();
345
- }
346
- }
347
- exportData() {
348
- const datasetInstanceSummary = this.prepareDatasetInstanceSummaryForEvaluation();
349
- const dialogRef = this.dialog.open(ExportDataComponent, {
350
- width: '600px',
351
- height: '530px',
352
- data: {
353
- datasetInstanceSummary
354
- }
355
- });
356
- }
357
- updateHeading(event) {
358
- if (!this.dashboard.displaySettings.heading) {
359
- this.dashboard.displaySettings.heading = {};
360
- }
361
- this.dashboard.displaySettings.heading[this.itemInstanceKey] = this.dashboardItemType.headingValue;
362
- this.dashboardItemType._editing = false;
363
- }
364
- async setupNetworkChart() {
365
- const nodeData = this.dataset.allData;
366
- const datasetNodes = [];
367
- const datasetEdges = [];
368
- nodeData.forEach(item => {
369
- const nodeLevelItem = {};
370
- const nodeItem = {
371
- id: item[this.networkData.nodeIds],
372
- label: item[this.networkData.nodeLabels],
373
- group: item[this.networkData.nodeGroups]
374
- };
375
- if (this.networkData.nodes) {
376
- if (this.networkData.nodes[nodeItem.id]) {
377
- nodeItem.x = this.networkData.nodes[nodeItem.id].x;
378
- nodeItem.y = this.networkData.nodes[nodeItem.id].y;
379
- }
380
- }
381
- if (this.networkData.nodeLevelOptions && Object.keys(this.networkData.nodeLevelOptions).length &&
382
- this.networkData.nodeLevelOptions[nodeItem.id]) {
383
- this.networkData.nodeLevelOptions[nodeItem.id].forEach(option => {
384
- nodeLevelItem[option.key] = option.value;
385
- });
386
- }
387
- datasetNodes.push(Object.assign(nodeLevelItem, nodeItem));
388
- if (!this.networkData.edgeDatasetTitle) {
389
- datasetEdges.push({
390
- from: item[this.networkData.fromIds],
391
- to: item[this.networkData.toIds]
392
- });
393
- }
394
- });
395
- if (this.networkData.edgeDatasetTitle) {
396
- const datasetInstanceSummary = {
397
- datasetInstanceId: this.networkData.edgeDatasetId,
398
- datasourceInstanceKey: this.networkData.edgeDatasourceKey,
399
- transformationInstances: [],
400
- parameterValues: {},
401
- parameters: {}
402
- };
403
- const edgeDataset = await this.datasetService.evaluateDataset(datasetInstanceSummary, '0', '10000000');
404
- edgeDataset.allData.forEach(item => {
405
- datasetEdges.push({
406
- from: item[this.networkData.fromIds],
407
- to: item[this.networkData.toIds]
408
- });
409
- });
410
- }
411
- datasetEdges.forEach(edge => {
412
- const edgeOptions = _.find(this.networkData.edgeLevelOptions, { from: edge.from, to: edge.to });
413
- if (edgeOptions && edgeOptions.options.length) {
414
- edgeOptions.options.forEach(option => {
415
- edge[option.key] = option.value;
416
- });
417
- }
418
- });
419
- // create an array with nodes
420
- const nodes = new DataSet(datasetNodes);
421
- // create an array with edges
422
- const edges = new DataSet(datasetEdges);
423
- // create a network
424
- const container = document.getElementById(this.itemInstanceKey + 'VIS');
425
- const data = {
426
- nodes,
427
- edges
428
- };
429
- const options = {
430
- nodes: {
431
- font: {
432
- multi: 'html'
433
- }
434
- },
435
- edges: {},
436
- groups: {},
437
- layout: {}
438
- };
439
- const mapOptionValue = (option, networkType) => {
440
- if (option && Object.keys(option).length) {
441
- const type = visNetworkOptions[networkType][option.key].type;
442
- let value = option.value;
443
- if (type === 'number') {
444
- value = Number(value);
445
- }
446
- else if (type === 'boolean') {
447
- value = value === 'true';
448
- }
449
- options[networkType][option.key] = value;
450
- }
451
- };
452
- if (this.networkData.nodeOptions) {
453
- this.networkData.nodeOptions.forEach(option => {
454
- mapOptionValue(option, 'nodes');
455
- });
456
- }
457
- if (this.networkData.edgeOptions) {
458
- this.networkData.edgeOptions.forEach(option => {
459
- mapOptionValue(option, 'edges');
460
- });
461
- }
462
- if (this.networkData.nodeGroupOptions && Object.keys(this.networkData.nodeGroupOptions).length) {
463
- Object.keys(this.networkData.nodeGroupOptions).forEach(groupKey => {
464
- this.networkData.nodeGroupOptions[groupKey].options.forEach(option => {
465
- if (!options.groups[groupKey]) {
466
- options.groups[groupKey] = {};
467
- }
468
- if (option && Object.keys(option).length) {
469
- options.groups[groupKey][option.key] = option.value;
470
- }
471
- });
472
- });
473
- }
474
- const network = new Network(container, data, options);
475
- this.networkData.network = network;
476
- }
477
- evaluateTextData(textData) {
478
- let evaluatedTextData = '';
479
- const element = document.createElement('div');
480
- element.innerHTML = this.bindParametersInString(textData);
481
- const data = {
482
- dataSet: this.dataset.allData
483
- };
484
- _.forEach(this.dataset.allData[0] || [], (value, key) => {
485
- data[key] = value;
486
- });
487
- const Kinibind = window.Kinibind;
488
- Kinibind.config = {
489
- prefix: 'd',
490
- templateDelimiters: ['[[', ']]']
491
- };
492
- const bind = new Kinibind(element, data);
493
- const boundHTML = bind.boundContext.els[0].innerHTML;
494
- evaluatedTextData = this.sanitizer.sanitize(1, boundHTML);
495
- element.remove();
496
- return evaluatedTextData;
497
- }
498
- async setChartData() {
499
- if (this.dashboardItemType.xAxis && this.dashboardItemType.yAxis) {
500
- let datasetData = this.dataset.allData;
501
- if (this.dashboardItemType.limit) {
502
- datasetData = datasetData.slice(0, this.dashboardItemType.limit);
503
- if (this.dashboardItemType.combineRemaining && !this.dashboardItemType.seriesColumn) {
504
- const remainingData = await this.evaluateDataset(10000000, 0);
505
- const combined = [];
506
- for (let i = 0; i < remainingData.allData.length; i++) {
507
- if (i > this.dashboardItemType.limit) {
508
- combined.push(remainingData.allData[i]);
509
- }
510
- }
511
- const pushObject = {};
512
- pushObject[this.dashboardItemType.xAxis] = this.dashboardItemType.combineRemaingingLabel || 'Remaining';
513
- pushObject[this.dashboardItemType.yAxis] = _.sumBy(combined, remainingItem => {
514
- return Number(remainingItem[this.dashboardItemType.yAxis]);
515
- });
516
- datasetData.push(pushObject);
517
- }
518
- }
519
- let data;
520
- if (!this.dashboardItemType.seriesColumn) {
521
- if (this.dashboardItemType.type !== 'pie' && this.dashboardItemType.type !== 'doughnut') {
522
- data = _.map(datasetData, item => {
523
- return { x: item[this.dashboardItemType.xAxis], y: item[this.dashboardItemType.yAxis] };
524
- });
525
- }
526
- else {
527
- data = _.map(datasetData, item => {
528
- return item[this.dashboardItemType.yAxis];
529
- });
530
- }
531
- this.chartData = [
532
- {
533
- data,
534
- label: _.find(this.filterFields, { name: this.dashboardItemType.xAxis }).title,
535
- fill: !!this.dashboardItemType.fill,
536
- borderColor: (this.dashboardItemType.type === 'pie' || this.dashboardItemType.type === 'doughnut') ? chroma('white').alpha(0.2).hex() : this.dashboardItemType.borderColor,
537
- backgroundColor: this.dashboardItemType.type === 'line' ?
538
- (Array.isArray(this.dashboardItemType.borderColor) ? _.map(this.dashboardItemType.borderColor, colour => {
539
- return chroma(colour || 'black').alpha(0.5).hex();
540
- }) : chroma(this.dashboardItemType.borderColor || 'black').alpha(0.5).hex()) : this.dashboardItemType.backgroundColor,
541
- tension: 0.2,
542
- pointBackgroundColor: this.dashboardItemType.borderColor ? this.dashboardItemType.borderColor[0] : null,
543
- pointBorderColor: this.dashboardItemType.borderColor ? this.dashboardItemType.borderColor[0] : null
544
- }
545
- ];
546
- this.dashboardItemType.labels = _.map(datasetData, item => {
547
- return item[this.dashboardItemType.xAxis];
548
- });
549
- }
550
- else {
551
- const chartData = [];
552
- const series = _.uniq(_.map(datasetData, this.dashboardItemType.seriesColumn));
553
- series.forEach((value, index) => {
554
- const seriesResults = _.filter(datasetData, allData => {
555
- return allData[this.dashboardItemType.seriesColumn] === value;
556
- });
557
- chartData.push({
558
- data: _.map(seriesResults, item => {
559
- return { x: item[this.dashboardItemType.xAxis], y: item[this.dashboardItemType.yAxis] };
560
- }),
561
- label: value,
562
- fill: !!this.dashboardItemType.fill,
563
- borderColor: this.dashboardItemType.borderColor,
564
- backgroundColor: this.dashboardItemType.type === 'line' ?
565
- (Array.isArray(this.dashboardItemType.borderColor) ? _.map(this.dashboardItemType.borderColor, colour => {
566
- return chroma(colour || 'black').alpha(0.5).hex();
567
- }) : chroma(this.dashboardItemType.borderColor || 'black').alpha(0.5).hex()) : this.dashboardItemType.backgroundColor[index],
568
- tension: 0.2,
569
- pointBackgroundColor: this.dashboardItemType.borderColor[index],
570
- pointBorderColor: this.dashboardItemType.borderColor[index]
571
- });
572
- });
573
- this.chartData = chartData;
574
- this.dashboardItemType.labels = _.uniq(_.map(datasetData, item => {
575
- return item[this.dashboardItemType.xAxis];
576
- }));
577
- }
578
- if (this.dashboardItemType.trendLine) {
579
- let trendLine = [];
580
- let trendLabel = 'Trend';
581
- if (this.dashboardItemType.trendLine === 'average') {
582
- trendLabel = 'Average';
583
- const trendData = [];
584
- this.chartData.forEach(dataItem => {
585
- trendData.push(_.map(dataItem.data, 'y'));
586
- });
587
- const average = _.flatMap(trendData).reduce((p, c) => p + c, 0) / _.flatMap(trendData).length;
588
- trendLine = _.fill(_.range(0, _.flatMap(trendData).length), average, 0, _.flatMap(trendData).length);
589
- }
590
- else if (this.dashboardItemType.trendLine === 'logarithmic' ||
591
- this.dashboardItemType.trendLine === 'linear' ||
592
- this.dashboardItemType.trendLine === 'power' ||
593
- this.dashboardItemType.trendLine === 'exponential') {
594
- const trendLineData = _.map(this.dataset.allData, (item, index) => {
595
- return { x: index + 1, y: item[this.dashboardItemType.yAxis] };
596
- }).filter(({ x, y }) => {
597
- return (typeof x === typeof y && // filter out one string & one number
598
- !isNaN(x) && // filter out `NaN`
599
- !isNaN(y) &&
600
- Math.abs(x) !== Infinity &&
601
- Math.abs(y) !== Infinity);
602
- }).map(({ x, y }) => {
603
- return [x, y];
604
- });
605
- const trendLineResults = regression[this.dashboardItemType.trendLine](trendLineData);
606
- trendLine = trendLineResults.points.map(([x, y]) => {
607
- return y;
608
- });
609
- }
610
- else {
611
- trendLine = _.map(this.dataset.allData, item => {
612
- return item[this.dashboardItemType.trendLine];
613
- });
614
- trendLabel = _.find(this.filterFields, { name: this.dashboardItemType.trendLine }).title;
615
- }
616
- this.chartData.push({
617
- type: 'line',
618
- data: trendLine,
619
- label: trendLabel,
620
- borderColor: this.dashboardItemType.trendLineColour,
621
- fill: false,
622
- order: -1,
623
- tension: 0.15,
624
- pointBackgroundColor: this.dashboardItemType.trendLineColour,
625
- pointBorderColor: this.dashboardItemType.trendLineColour
626
- });
627
- }
628
- }
629
- }
630
- updateImageData() {
631
- this.imageData.source = this.imageData.column ? this.dataset.allData[0][this.imageData.column] : null;
632
- }
633
- updateMetricDataValues() {
634
- if (this.metric.main) {
635
- this.metric.mainValue = _.isNaN(Number(this.dataset.allData[0][this.metric.main])) ? this.dataset.allData[0][this.metric.main] : Number(this.dataset.allData[0][this.metric.main]);
636
- this.metric.title = _.startCase(this.metric.main);
637
- }
638
- if (this.metric.subMetric) {
639
- this.metric.subValue = Number(this.dataset.allData[0][this.metric.subMetric]);
640
- this.metric.subTitle = _.startCase(this.metric.subMetric);
641
- }
642
- if (this.metric.showSubChange) {
643
- this.metric.difference = Math.abs(this.metric.mainValue - this.metric.subValue);
644
- }
645
- }
646
- callToActionLink(cta, dataItem) {
647
- let url = null;
648
- if (cta.type === 'dashboard') {
649
- const params = _.pickBy(cta.parameters, (value, key) => {
650
- return !_.startsWith(key, 'custom-');
651
- });
652
- const data = dataItem || this.dashboard.layoutSettings.parameters;
653
- Object.keys(params).forEach(paramKey => {
654
- let value = this.bindParametersInString(params[paramKey], data);
655
- // Check if we have any column eg. [[ ]] values needing mapping
656
- value = this.mapColumnToValue(value, data);
657
- params[paramKey] = value;
658
- });
659
- const urlParams = new URLSearchParams(params).toString();
660
- url = `/dashboards/view/${cta.value}${this.admin ? '?a=true&' : '?'}${urlParams}`;
661
- }
662
- else if (cta.type === 'custom') {
663
- url = cta.link;
664
- const data = dataItem || this.dashboard.layoutSettings.parameters;
665
- url = this.bindParametersInString(url, data);
666
- // Check if we have any column eg. [[ ]] values needing mapping
667
- url = this.mapColumnToValue(url, data);
668
- }
669
- else if (cta.type === 'feed') {
670
- url = `/dap-data-feeds/${cta.value}`;
671
- }
672
- if (url) {
673
- if (!cta.windowLocation || cta.windowLocation === 'EXISTING') {
674
- window.location.href = url;
675
- }
676
- else {
677
- const a = document.createElement('a');
678
- a.href = url;
679
- a.setAttribute('target', '_blank');
680
- a.setAttribute('rel', 'noopener noreferrer');
681
- a.click();
682
- }
683
- }
684
- }
685
- bindParametersInString(searchString, data) {
686
- if (!data) {
687
- data = this.dashboard.layoutSettings.parameters;
688
- }
689
- if (searchString) {
690
- const matches = searchString.match(/\{\{(.*?)\}\}/g) || [];
691
- matches.forEach(exp => {
692
- const expValue = exp.replace('{{', '').replace('}}', '');
693
- const parameter = data ? data[expValue] : null;
694
- if (parameter) {
695
- const value = _.isPlainObject(parameter) ? parameter.value : parameter;
696
- searchString = searchString.replace(exp, value);
697
- }
698
- });
699
- }
700
- return searchString;
701
- }
702
- increaseOffset() {
703
- this.page = this.page + 1;
704
- this.offset = (this.limit * this.page) - this.limit;
705
- this.evaluate();
706
- }
707
- decreaseOffset() {
708
- this.page = this.page <= 1 ? 1 : this.page - 1;
709
- this.offset = (this.limit * this.page) - this.limit;
710
- this.evaluate();
711
- }
712
- pageSizeChange(value) {
713
- this.limit = value;
714
- // If we change the table limit - we also want to save the dashboard automatically to keep the changes
715
- this.tabular.limit = this.limit;
716
- this.dashboardService.saveDashboard(this.dashboard);
717
- this.evaluate(true);
718
- }
719
- sortHeader(columnObject) {
720
- const column = columnObject.name;
721
- let direction = '';
722
- const existingMultiSort = _.find(this.dashboardDatasetInstance.transformationInstances, { type: 'multisort' });
723
- let existingColumnIndex = -1;
724
- if (existingMultiSort) {
725
- existingColumnIndex = _.findIndex(existingMultiSort.config.sorts, { fieldName: column });
726
- }
727
- if (!existingMultiSort || existingColumnIndex === -1) {
728
- direction = 'asc';
729
- }
730
- else if (existingColumnIndex >= 0 && existingMultiSort.config.sorts[existingColumnIndex].direction === 'asc') {
731
- direction = 'desc';
732
- }
733
- else if (existingColumnIndex >= 0 && existingMultiSort.config.sorts[existingColumnIndex].direction === 'desc') {
734
- direction = '';
735
- }
736
- else if (existingColumnIndex >= 0 && !existingMultiSort.config.sorts[existingColumnIndex].direction) {
737
- direction = 'asc';
738
- }
739
- columnObject.direction = direction;
740
- if (existingMultiSort) {
741
- const existingIndex = _.findIndex(existingMultiSort.config.sorts, { fieldName: column });
742
- if (direction) {
743
- if (existingIndex > -1) {
744
- existingMultiSort.config.sorts[existingIndex] = { fieldName: column, direction };
745
- }
746
- else {
747
- existingMultiSort.config.sorts.push({ fieldName: column, direction });
748
- }
749
- }
750
- else {
751
- existingMultiSort.config.sorts.splice(existingIndex, 1);
752
- if (!existingMultiSort.config.sorts.length) {
753
- _.remove(this.dashboardDatasetInstance.transformationInstances, { type: 'multisort' });
754
- }
755
- }
756
- }
757
- else {
758
- if (direction) {
759
- this.dashboardDatasetInstance.transformationInstances.push({
760
- type: 'multisort',
761
- config: {
762
- sorts: [{ fieldName: column, direction }]
763
- }
764
- });
765
- }
766
- }
767
- this.evaluate(true);
768
- }
769
- changeDateType(event, parameter, value) {
770
- event.stopPropagation();
771
- event.preventDefault();
772
- parameter._dateType = value;
773
- this.reloadWidget();
774
- }
775
- updatePeriodValue(value, period, parameter) {
776
- parameter.value = `${value}_${period}_AGO`;
777
- this.reloadWidget();
778
- }
779
- booleanUpdate(event, parameter) {
780
- parameter.value = event.checked;
781
- this.reloadWidget();
782
- }
783
- reloadWidget() {
784
- const parameterValues = {};
785
- _.forEach(this.general.widgetParameters, param => {
786
- parameterValues[param.name] = param.value;
787
- });
788
- this.evaluate();
789
- }
790
- mapColumnToValue(searchString, data) {
791
- if (searchString) {
792
- const matches = searchString.match(/\[\[(.*?)\]\]/g) || [];
793
- matches.forEach(exp => {
794
- const expValue = exp.replace('[[', '').replace(']]', '');
795
- let value = data ? data[expValue] : null;
796
- if (value) {
797
- value = _.isPlainObject(value) ? value.initialValue : value;
798
- searchString = searchString.replace(exp, value);
799
- }
800
- });
801
- }
802
- return searchString;
803
- }
804
- evaluate(resetPager) {
805
- if (resetPager) {
806
- this.resetPager();
807
- }
808
- const itemElement = document.getElementById(this.itemInstanceKey);
809
- if (itemElement) {
810
- const parentElement = itemElement.closest('.grid-stack-item');
811
- parentElement.classList.remove('item-disabled');
812
- }
813
- if (this.grid && _.isFunction(this.grid.makeElement)) {
814
- setTimeout(() => {
815
- this.grid.makeElement(itemElement);
816
- }, 0);
817
- }
818
- this.loadingItem = true;
819
- this.hiddenColumns = {};
820
- return this.evaluateDataset().then(data => {
821
- if (Object.keys(this.tableCells).length) {
822
- Object.keys(this.tableCells).forEach(tableCell => {
823
- if (tableCell !== 'column') {
824
- data.allData.map((item, index) => {
825
- if (!_.isUndefined(item[tableCell])) {
826
- const cellData = this.tableCells[tableCell].data;
827
- switch (this.tableCells[tableCell].type) {
828
- case 'number':
829
- const cellNumber = parseFloat(String(item[tableCell]));
830
- item[tableCell] = {
831
- cellValue: cellNumber.toFixed(cellData.decimal),
832
- initialValue: item[tableCell]
833
- };
834
- break;
835
- case 'currency':
836
- let cellCurrency = parseFloat(String(item[tableCell]));
837
- if (cellData.thousandsSeparator && (cellData.currency && cellData.currency.value)) {
838
- cellCurrency = cellCurrency.toLocaleString('en-GB', {
839
- style: 'currency',
840
- currency: cellData.currency.value,
841
- minimumFractionDigits: cellData.decimal || 0
842
- });
843
- }
844
- else {
845
- cellCurrency = cellCurrency.toFixed(cellData.decimal);
846
- if (cellData.thousandsSeparator) {
847
- cellCurrency = Number(cellCurrency).toLocaleString('en-GB', {
848
- minimumFractionDigits: cellData.decimal || 0
849
- });
850
- }
851
- if (cellData.currency && cellData.currency.value) {
852
- cellCurrency = `${cellData.currency.symbol}${cellCurrency}`;
853
- }
854
- }
855
- item[tableCell] = { cellValue: cellCurrency, initialValue: item[tableCell] };
856
- break;
857
- case 'percentage':
858
- let cellPercent = Number(item[tableCell]);
859
- const formatter = new Intl.NumberFormat('en-GB', {
860
- style: 'percent',
861
- minimumFractionDigits: cellData.decimal || 0
862
- });
863
- cellPercent = formatter.format(cellPercent);
864
- if (!cellData.thousandsSeparator) {
865
- cellPercent = cellPercent.replace(',', '');
866
- }
867
- item[tableCell] = { cellValue: cellPercent, initialValue: item[tableCell] };
868
- break;
869
- case 'datetime':
870
- const dateMoment = moment(item[tableCell]);
871
- const dateFormat = cellData.dateFormat === 'null' ? '' : cellData.dateFormat;
872
- const timeFormat = cellData.timeFormat === 'null' ? '' : cellData.timeFormat;
873
- item[tableCell] = {
874
- cellValue: dateMoment.format(dateFormat + ' ' + timeFormat),
875
- initialValue: item[tableCell]
876
- };
877
- break;
878
- case 'comparison':
879
- const comparisonColumn = this.tableCells[tableCell].data.comparisonColumn;
880
- const initialValue = _.isPlainObject(item[tableCell]) ? item[tableCell].initialValue : item[tableCell];
881
- const comparisonValue = _.isPlainObject(data.allData[index][comparisonColumn]) ? data.allData[index][comparisonColumn].initialValue : data.allData[index][comparisonColumn];
882
- let difference = Number(initialValue) - Number(comparisonValue);
883
- let cellValue = `<div class="flex items-center space-between"><span class="font-medium">${initialValue}</span>`;
884
- if (difference === 0) {
885
- cellValue += `<span class="ml-1 text-blue-500 font-medium text-lg">&#61;</span>`;
886
- }
887
- if (difference > 0) {
888
- if (cellData.comparisonPercentage) {
889
- const compareFormatter = new Intl.NumberFormat('en-GB', {
890
- style: 'percent',
891
- minimumFractionDigits: cellData.comparisonDecimals || 0
892
- });
893
- difference = compareFormatter.format(difference / comparisonValue);
894
- }
895
- cellValue += `<span class="ml-1 text-green-500 font-medium text-lg">&#8593;</span><span class="text-sm text-green-500">${difference}</span>`;
896
- }
897
- if (difference < 0) {
898
- if (cellData.comparisonPercentage) {
899
- const compareFormatter = new Intl.NumberFormat('en-GB', {
900
- style: 'percent',
901
- minimumFractionDigits: cellData.comparisonDecimals || 0
902
- });
903
- difference = compareFormatter.format(difference / comparisonValue);
904
- }
905
- cellValue += `<span class="ml-1 text-red-500 font-medium text-lg">&#8595;</span><span class="text-sm text-red-500">${difference}</span>`;
906
- }
907
- cellValue += `<span class="ml-2 text-xs text-gray-400">from ${comparisonValue}</span></div>`;
908
- item[tableCell] = { cellValue, initialValue };
909
- break;
910
- case 'link':
911
- let linkValue = cellData.customLink;
912
- let anchor = '';
913
- if (cellData.linkType === 'custom') {
914
- const dataItem = data.allData[index] || this.dashboard.layoutSettings.parameters;
915
- linkValue = this.bindParametersInString(linkValue, dataItem);
916
- // Check if we have any column eg. [[ ]] values needing mapping
917
- linkValue = this.mapColumnToValue(linkValue, dataItem);
918
- anchor = `<a href="${linkValue}" target="_blank" class="text-cta hover:underline flex items-center">${item[tableCell]}</a>`;
919
- }
920
- else if (cellData.linkType === 'dashboard') {
921
- const params = {};
922
- const dashboardLink = cellData.dashboardLink;
923
- const dataItem = data.allData[index] || this.dashboard.layoutSettings.parameters;
924
- Object.keys(cellData.dashboardLinkParams).forEach(paramKey => {
925
- let value = this.bindParametersInString(cellData.dashboardLinkParams[paramKey], dataItem);
926
- // Check if we have any column eg. [[ ]] values needing mapping
927
- value = this.mapColumnToValue(value, dataItem);
928
- params[paramKey] = value;
929
- });
930
- const urlParams = new URLSearchParams(params).toString();
931
- linkValue = `${this.router.url.split('/')[0]}/dashboards/view/${dashboardLink.value}${this.admin ? '?a=true&' : '?'}${urlParams}`;
932
- anchor = `<a href="${linkValue}" class="text-cta hover:underline flex items-center">${item[tableCell]}</a>`;
933
- }
934
- else {
935
- linkValue = linkValue.includes('http') ? linkValue : `http://${linkValue}`;
936
- anchor = `<a href="${linkValue}" target="_blank" class="text-cta hover:underline flex items-center">${item[tableCell]}</a>`;
937
- }
938
- item[tableCell] = {
939
- cellValue: anchor,
940
- initialValue: linkValue
941
- };
942
- break;
943
- case 'custom':
944
- const element = document.createElement('div');
945
- const originalValue = item[tableCell];
946
- element.innerHTML = this.bindParametersInString(cellData.customText);
947
- const kData = {
948
- dataSet: data.allData
949
- };
950
- _.forEach(data.allData[index] || [], (value, key) => {
951
- kData[key] = value;
952
- });
953
- const Kinibind = window.Kinibind;
954
- Kinibind.config = {
955
- prefix: 'd',
956
- templateDelimiters: ['[[', ']]']
957
- };
958
- const bind = new Kinibind(element, kData);
959
- const boundHTML = bind.boundContext.els[0].innerHTML;
960
- item[tableCell] = {
961
- cellValue: this.sanitizer.sanitize(1, boundHTML),
962
- initialValue: originalValue
963
- };
964
- element.remove();
965
- break;
966
- case 'hide':
967
- this.hiddenColumns[tableCell] = true;
968
- break;
969
- }
970
- }
971
- return item;
972
- });
973
- }
974
- });
975
- }
976
- this.dataset = data;
977
- const returnedDataLength = this.dataset.allData.length;
978
- const existingMultiSort = _.find(this.dashboardDatasetInstance.transformationInstances, { type: 'multisort' });
979
- if (existingMultiSort && existingMultiSort.config.sorts.length) {
980
- existingMultiSort.config.sorts.forEach(sort => {
981
- const column = _.find(this.dataset.columns, { name: sort.fieldName });
982
- if (column) {
983
- column.direction = sort.direction;
984
- }
985
- });
986
- }
987
- this.filterFields = _.map(this.dataset.columns, column => {
988
- return {
989
- title: column.title,
990
- name: column.name
991
- };
992
- });
993
- if (this.dashboard.layoutSettings.metric) {
994
- this.updateMetricDataValues();
995
- }
996
- if (this.dashboard.layoutSettings.imageData) {
997
- this.updateImageData();
998
- }
999
- if (Object.keys(this.textData).length) {
1000
- this.textData.safeTextData = this.evaluateTextData(this.textData.value);
1001
- }
1002
- if (Object.keys(this.general).length) {
1003
- this.general.evaluatedName = this.general.name ? this.evaluateTextData(this.general.name) : '';
1004
- this.general.evaluatedDescription = this.general.description ? this.evaluateTextData(this.general.description) : '';
1005
- this.general.evaluatedFooter = this.general.footer ? this.evaluateTextData(this.general.footer) : '';
1006
- }
1007
- setTimeout(() => {
1008
- if (this.dashboardItemType.type === 'network') {
1009
- this.setupNetworkChart();
1010
- }
1011
- const element = document.getElementById(this.itemInstanceKey);
1012
- for (const child of Array.from(element ? element.children : [])) {
1013
- if (child.classList.contains('item-container')) {
1014
- this.wordCloud.width = child.clientWidth - 40;
1015
- this.wordCloud.height = child.clientHeight - 40;
1016
- }
1017
- }
1018
- if (Object.keys(this.wordCloud).length) {
1019
- if (this.wordCloud.populationMethod === 'SINGLE') {
1020
- const rowData = this.dataset.allData[this.wordCloud.row];
1021
- if (rowData) {
1022
- const words = _.words(rowData[this.wordCloud.column]);
1023
- const count = _.countBy(words, _.identity);
1024
- const max = _.max(_.values(count));
1025
- const fontSize = ((this.wordCloud.height) * (this.wordCloud.width)) / 1000;
1026
- this.wordCloud.data = _.orderBy(_.uniq(words).map(word => {
1027
- return { text: word, value: ((count[word] / max) * _.min([fontSize, 120])) };
1028
- }), ['value'], ['desc']).slice(0, 100);
1029
- }
1030
- }
1031
- else if (this.wordCloud.populationMethod === 'WHOLE') {
1032
- const maxFreq = _.maxBy(this.dataset.allData, item => {
1033
- return Number(item[this.wordCloud.frequency]);
1034
- })[this.wordCloud.frequency];
1035
- const maxWordWidth = _.max(_.map(this.dataset.allData, item => item[this.wordCloud.column].length * item[this.wordCloud.frequency] / maxFreq));
1036
- const fontSize = ((this.wordCloud.height) * (this.wordCloud.width)) / 3000;
1037
- this.wordCloud.data = _.orderBy(this.dataset.allData.map(item => {
1038
- const text = item[this.wordCloud.column];
1039
- const itemFrequency = item[this.wordCloud.frequency];
1040
- return {
1041
- text,
1042
- value: ((8 / maxWordWidth) * (Number(itemFrequency) / Number(maxFreq)) * _.min([fontSize, 400]))
1043
- };
1044
- }), ['value'], ['desc']).slice(0, 100);
1045
- }
1046
- }
1047
- }, 50);
1048
- this.loadingItem = false;
1049
- this.configureClass = false;
1050
- this.setChartData();
1051
- if (this.dashboard.alertsEnabled && !this.external) {
1052
- if (this.dashboardDatasetInstance.alerts && this.dashboardDatasetInstance.alerts.length) {
1053
- if (this.dashboard.layoutSettings.parameters && Object.keys(this.dashboard.layoutSettings.parameters).length) {
1054
- if (Array.isArray(this.dashboardDatasetInstance.parameterValues)) {
1055
- this.dashboardDatasetInstance.parameterValues = {};
1056
- }
1057
- _.forEach(this.dashboard.layoutSettings.parameters, parameter => {
1058
- this.dashboardDatasetInstance.parameterValues[parameter.name] = parameter.value;
1059
- });
1060
- }
1061
- const dashboardInstance = _.cloneDeep(this.dashboardDatasetInstance);
1062
- dashboardInstance.parameterValues = this.getMappedParams(this.dashboardDatasetInstance);
1063
- this.alertService.processAlertsForDashboardDatasetInstance(dashboardInstance)
1064
- .then((res) => {
1065
- if (res && res.length) {
1066
- this.alert = true;
1067
- this.alertData = res;
1068
- if (itemElement) {
1069
- itemElement.classList.add('alert');
1070
- itemElement.parentElement.classList.add('alert');
1071
- }
1072
- }
1073
- else {
1074
- this.resetAlertData(itemElement);
1075
- }
1076
- });
1077
- }
1078
- else {
1079
- this.resetAlertData(itemElement);
1080
- }
1081
- }
1082
- else {
1083
- this.resetAlertData(itemElement);
1084
- }
1085
- const existing = this.dashboardService.dashboardItems.getValue();
1086
- existing[this.itemInstanceKey] = true;
1087
- this.dashboardService.dashboardItems.next(existing);
1088
- this.endOfResults = returnedDataLength < this.limit;
1089
- return Promise.resolve(true);
1090
- }).catch(err => {
1091
- });
1092
- }
1093
- getMappedParams(dashboardDatasetInstance) {
1094
- const mappedParams = {};
1095
- _.forEach(dashboardDatasetInstance.parameterValues, (value, key) => {
1096
- if (_.isString(value) && value.includes('{{')) {
1097
- const globalKey = value.replace('{{', '').replace('}}', '');
1098
- if (this.dashboard.layoutSettings.parameters && this.dashboard.layoutSettings.parameters[globalKey]) {
1099
- mappedParams[key] = this.dashboard.layoutSettings.parameters[globalKey].value;
1100
- }
1101
- }
1102
- else {
1103
- mappedParams[key] = value;
1104
- }
1105
- });
1106
- return mappedParams;
1107
- }
1108
- resetAlertData(itemElement) {
1109
- this.alert = false;
1110
- this.alertData = [];
1111
- if (itemElement) {
1112
- itemElement.classList.remove('alert');
1113
- itemElement.parentElement.classList.remove('alert');
1114
- }
1115
- }
1116
- resetPager() {
1117
- this.offset = 0;
1118
- this.page = 1;
1119
- }
1120
- mapLayoutSettingsToComponentData() {
1121
- _.forEach(this.dashboard.layoutSettings, (data, key) => {
1122
- if (key !== 'grid') {
1123
- const defaultValue = _.isPlainObject(this[key]) ? {} : [];
1124
- this[key] = Object.keys(data).length ? data[this.itemInstanceKey] || defaultValue : defaultValue;
1125
- }
1126
- });
1127
- }
1128
- reloadAlert(save = true) {
1129
- const thisEl = document.getElementById(this.itemInstanceKey).closest('.grid-stack-item');
1130
- const existingGrid = _.find(this.dashboard.layoutSettings.grid, grid => {
1131
- return grid.content.includes(`id="${this.itemInstanceKey}"`);
1132
- });
1133
- if (thisEl && existingGrid) {
1134
- this.grid.removeWidget(thisEl);
1135
- this.grid.addWidget(existingGrid);
1136
- }
1137
- if (save) {
1138
- this.dashboardService.saveDashboard(this.dashboard);
1139
- }
1140
- }
1141
- evaluateDataset(limit, offset) {
1142
- const datasetInstanceSummary = this.prepareDatasetInstanceSummaryForEvaluation();
1143
- this.hiddenColumns = {};
1144
- this.externalError = false;
1145
- this.quotaExceeded = null;
1146
- if (this.external) {
1147
- return this.externalService.evaluateDataset(this.dashboard.id, this.itemInstanceKey, datasetInstanceSummary.parameterValues, String(offset || this.offset), String(limit || this.limit), this.queryParams).catch(e => {
1148
- this.externalError = true;
1149
- });
1150
- }
1151
- else {
1152
- return this.datasetService.evaluateDataset(datasetInstanceSummary, String(offset || this.offset), String(limit || this.limit)).catch(e => {
1153
- if (e && e.error && e.error.message && e.error.message.includes('quota')) {
1154
- this.quotaExceeded = e.error.message;
1155
- }
1156
- else {
1157
- this.externalError = true;
1158
- }
1159
- });
1160
- }
1161
- }
1162
- prepareDatasetInstanceSummaryForEvaluation() {
1163
- const mappedParams = this.getMappedParams(this.dashboardDatasetInstance);
1164
- const datasetInstanceSummary = {
1165
- datasetInstanceId: this.dashboardDatasetInstance.datasetInstanceId,
1166
- datasourceInstanceKey: this.dashboardDatasetInstance.datasourceInstanceKey,
1167
- transformationInstances: this.dashboardDatasetInstance.transformationInstances,
1168
- parameterValues: mappedParams,
1169
- parameters: this.dashboardDatasetInstance.parameters
1170
- };
1171
- if (this.dashboard.layoutSettings.parameters && Object.keys(this.dashboard.layoutSettings.parameters).length) {
1172
- _.forEach(this.dashboard.layoutSettings.parameters, (param, name) => {
1173
- let value = param.value;
1174
- if (param.type === 'date' || param.type === 'datetime') {
1175
- if (value && !value.includes('AGO')) {
1176
- value = moment(value).format('YYYY-MM-DD HH:mm:ss');
1177
- }
1178
- }
1179
- // Add in the widget specific parameter values if there are any
1180
- if (this.general.widgetParameters && Object.keys(this.general.widgetParameters).length) {
1181
- const widgetParam = _.find(this.general.widgetParameters, { name });
1182
- if (widgetParam && widgetParam.value) {
1183
- value = widgetParam.value;
1184
- }
1185
- }
1186
- datasetInstanceSummary.parameterValues[name] = value;
1187
- });
1188
- }
1189
- return datasetInstanceSummary;
1190
- }
1191
- }
1192
- ItemComponentComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: ItemComponentComponent, deps: [{ token: i1.MatLegacyDialog }, { token: i2.DatasourceService }, { token: i3.DatasetService }, { token: i4.AlertService }, { token: i5.DashboardService }, { token: i6.DomSanitizer }, { token: i7.Router }, { token: i8.Location }, { token: i9.ExternalService }, { token: i10.ProjectService }], target: i0.ɵɵFactoryTarget.Component });
1193
- ItemComponentComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: ItemComponentComponent, selector: "ki-item-component", inputs: { dashboardItemType: "dashboardItemType", itemInstanceKey: "itemInstanceKey", dashboard: "dashboard", dashboardItem: "dashboardItem", dragItem: "dragItem", grid: "grid", actionEvents: "actionEvents", external: "external", queryParams: "queryParams", editAlerts: "editAlerts" }, outputs: { duplicateItem: "duplicateItem" }, host: { properties: { "class.justify-center": "this.configureClass" } }, viewQueries: [{ propertyName: "textTemplate", first: true, predicate: ["textTemplate"], descendants: true }], ngImport: i0, template: "<div class=\"alert-panel\" *ngIf=\"showAlertData\" (click)=\"showAlertData = false\">\n <div class=\"align-center flex-col w-3/4 m-auto\">\n <mat-icon>notification_important</mat-icon>\n <h2 class=\"mb-0\">Alert Notification</h2>\n <p class=\"text-center\">The following alerts have been triggered based on the criteria set for this dashboard\n item...</p>\n <div class=\"alert-item mb-2\" *ngFor=\"let alertItem of alertData\"\n [innerHTML]=\"alertItem.notificationMessage\">\n </div>\n </div>\n</div>\n\n<div class=\"item-disabled\">\n <p>{{general.name || dashboardItemType.label}}</p>\n <mat-icon>block</mat-icon>\n <p class=\"disabled-notice\">{{dependencies.notice || 'No Data Available'}}</p>\n</div>\n\n<ng-template [ngIf]=\"dragItem\">\n <span class=\"material-symbols-outlined\">{{dashboardItemType.icon}}</span>\n <span [innerHTML]=\"dashboardItemType.label\"></span>\n</ng-template>\n<div class=\"alert-widget\" *ngIf=\"alert\" (click)=\"showAlertData = true;\">\n <button mat-icon-button>\n <mat-icon>notification_important</mat-icon>\n </button>\n <div class=\"alert-summaries\">\n <span class=\"mr-2\" *ngFor=\"let alertItem of alertData\">\n {{alertItem.summaryMessage}}\n </span>\n </div>\n</div>\n\n<ng-template\n [ngIf]=\"!dragItem && !dashboardDatasetInstance && !dashboardItemType.headingValue && !dashboardItemType._editing\">\n <button mat-stroked-button color=\"primary\" class=\"config-button\" (click)=\"configure()\">\n Configure {{dashboardItemType.label}}\n </button>\n</ng-template>\n\n<div class=\"absolute top-1 right-1 z-20\" *ngIf=\"!dragItem && loadingItem && (chartData || dataset)\">\n <svg class=\"animate-spin h-5 w-5 text-secondary\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\">\n <circle class=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" stroke-width=\"4\"></circle>\n <path class=\"opacity-75\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"></path>\n </svg>\n</div>\n\n<ng-template [ngIf]=\"!viewOnly\">\n <div class=\"absolute top-1 left-1 z-20 cursor-pointer\" *ngIf=\"!dragItem && this.itemNoMove\"\n (click)=\"lockItem()\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"currentColor\"\n class=\"h-5 w-5 text-gray-400\">\n <path fill-rule=\"evenodd\" d=\"M12 1.5a5.25 5.25 0 0 0-5.25 5.25v3a3 3 0 0 0-3 3v6.75a3 3 0 0 0 3 3h10.5a3 3 0 0 0 3-3v-6.75a3 3 0 0 0-3-3v-3c0-2.9-2.35-5.25-5.25-5.25Zm3.75 8.25v-3a3.75 3.75 0 1 0-7.5 0v3h7.5Z\" clip-rule=\"evenodd\" />\n </svg>\n </div>\n\n <div class=\"item-unlocked absolute top-1 left-1 z-20 cursor-pointer\" *ngIf=\"!dragItem && !this.itemNoMove\"\n (click)=\"lockItem()\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"currentColor\"\n class=\"h-5 w-5 text-gray-400\">\n <path d=\"M18 1.5c2.9 0 5.25 2.35 5.25 5.25v3.75a.75.75 0 0 1-1.5 0V6.75a3.75 3.75 0 1 0-7.5 0v3a3 3 0 0 1 3 3v6.75a3 3 0 0 1-3 3H3.75a3 3 0 0 1-3-3v-6.75a3 3 0 0 1 3-3h9v-3c0-2.9 2.35-5.25 5.25-5.25Z\" />\n </svg>\n </div>\n</ng-template>\n\n\n<ng-template [ngIf]=\"!externalError && !quotaExceeded\">\n <div class=\"loading-item\" *ngIf=\"!dragItem && loadingItem && !(chartData || dataset)\">\n\n <div class=\"mx-auto flex h-14 w-14 flex-shrink-0 items-center justify-center rounded-full bg-gray-100 \">\n <svg class=\"animate-spin h-14 w-14 text-gray-400\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\">\n <circle class=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" stroke-width=\"4\"></circle>\n <path class=\"opacity-75\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"></path>\n </svg>\n </div>\n <div class=\"px-4 text-center mt-4\">Loading {{dashboardItemType.label}} ...</div>\n </div>\n</ng-template>\n\n<ng-template [ngIf]=\"externalError\">\n <div class=\"loading-item\">\n <div class=\"mx-auto flex h-14 w-14 flex-shrink-0 items-center justify-center rounded-full bg-red-100 \">\n <svg class=\"h-10 w-10 text-red-600\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" aria-hidden=\"true\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126zM12 15.75h.007v.008H12v-.008z\" />\n </svg>\n </div>\n <div class=\"px-4 w-3/4 text-center mt-4\">There was a problem loading this item. Please try again later.</div>\n </div>\n</ng-template>\n\n<ng-template [ngIf]=\"quotaExceeded\">\n <div class=\"loading-item\">\n <div class=\"mx-auto flex h-14 w-14 flex-shrink-0 items-center justify-center rounded-full bg-blue-100 \">\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\"\n class=\"h-10 w-10 text-blue-600\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M11.25 11.25l.041-.02a.75.75 0 011.063.852l-.708 2.836a.75.75 0 001.063.853l.041-.021M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-9-3.75h.008v.008H12V8.25z\" />\n </svg>\n </div>\n <div class=\"px-4 w-3/4 text-center mt-4\">{{quotaExceeded}}</div>\n </div>\n</ng-template>\n\n<ng-template [ngIf]=\"!itemLocked\">\n <button *ngIf=\"!dragItem\" mat-mini-fab class=\"edit-widget bg-white text-gray-500 bg-opacity-90\"\n [matMenuTriggerFor]=\"editMenu\">\n <mat-icon>more_horiz</mat-icon>\n </button>\n <mat-menu #editMenu=\"matMenu\">\n <ng-template [ngIf]=\"!viewOnly\">\n <button mat-menu-item (click)=\"configure()\">\n <mat-icon>edit</mat-icon>\n Edit Item\n </button>\n <button *ngIf=\"existingGridItem\" mat-menu-item (click)=\"duplicate()\">\n <mat-icon>copy_all</mat-icon>\n Duplicate Item\n </button>\n <button *ngIf=\"canExportData\" mat-menu-item (click)=\"exportData()\">\n <mat-icon>file_download</mat-icon>\n Export Data\n </button>\n <mat-divider></mat-divider>\n <button mat-menu-item (click)=\"removeWidget($event)\">\n <mat-icon class=\"text-red-600\">delete</mat-icon>\n Delete Item\n </button>\n </ng-template>\n <ng-template [ngIf]=\"viewOnly\">\n <button *ngIf=\"canExportData\" mat-menu-item (click)=\"exportData()\">\n <mat-icon>file_download</mat-icon>\n Export Data\n </button>\n <mat-divider></mat-divider>\n <button mat-menu-item (click)=\"editItemAlerts(null)\">\n <mat-icon color=\"primary\">add</mat-icon>\n <span>New Alert</span>\n </button>\n <ng-template [ngIf]=\"dashboardDatasetInstance\">\n <div mat-menu-item class=\"flex items-center justify-between p-0 \"\n [ngClass]=\"{'border border-t border-b-0 border-r-0 border-l-0 border-solid border-gray-200': i === 0}\"\n *ngFor=\"let alert of dashboardDatasetInstance.alerts; let i = index\">\n <div class=\"px-4 flex items-center\" (click)=\"editItemAlerts(alert, i)\">\n <mat-icon>edit</mat-icon>\n <span>{{alert.title}}</span>\n </div>\n <div class=\"flex items-center\">\n <div class=\"mx-2 divider\"></div>\n <button mat-icon-button (click)=\"removeAlert($event, alert, i)\">\n <mat-icon class=\"mx-2 text-red-600 m-0\">highlight_off</mat-icon>\n </button>\n </div>\n\n </div>\n </ng-template>\n </ng-template>\n </mat-menu>\n</ng-template>\n\n<ng-template [ngIf]=\"!dragItem && dashboardItemType.type === 'heading'\">\n\n <div class=\"item-heading\" *ngIf=\"!dashboardItemType._editing\">\n {{bindParametersInString(dashboardItemType.headingValue)}}\n </div>\n\n <input type=\"text\" *ngIf=\"dashboardItemType._editing\" [(ngModel)]=\"dashboardItemType.headingValue\"\n (blur)=\"updateHeading($event)\" class=\"w-11/12\">\n\n</ng-template>\n\n<ng-template [ngIf]=\"!dragItem && (chartData || dataset)\">\n\n <div class=\"item-title \" *ngIf=\"general.name\" [innerHTML]=\"general.evaluatedName\"\n [ngClass]=\"{'pb-4': !general.description, 'pb-2': general.description}\"></div>\n\n <div class=\"item-description text-sm\" *ngIf=\"general.description\"\n [innerHTML]=\"general.evaluatedDescription\"></div>\n\n <ng-template [ngIf]=\"general.widgetParameters && _.values(general.widgetParameters).length\">\n <div class=\"p-2 bg-gray-100 w-full flex flex-wrap\">\n <ng-template ngFor let-parameter [ngForOf]=\"_.values(general.widgetParameters)\" let-i=index>\n <label class=\"widget-parameter\">\n {{parameter.title}}\n <div class=\"parameter-input\">\n <ng-template [ngIf]=\"parameter.type === 'text'\">\n <input type=\"text\" placeholder=\"Enter {{parameter.title}}\" [(ngModel)]=\"parameter.value\"\n (keyup.enter)=\"reloadWidget()\" required autofocus>\n </ng-template>\n <ng-template [ngIf]=\"parameter.type === 'numeric'\">\n <input type=\"number\" placeholder=\"Enter {{parameter.title}}\" [(ngModel)]=\"parameter.value\"\n (keyup.enter)=\"reloadWidget()\" required autofocus>\n </ng-template>\n <ng-template [ngIf]=\"parameter.type === 'date' || parameter.type === 'datetime'\">\n <ng-template [ngIf]=\"!parameter._dateType\">\n <div class=\"flex items-center\">\n <button (click)=\"changeDateType($event, parameter, 'picker')\"\n class=\"hover:bg-gray-50 text-gray-800 border border-gray-300 py-0.5 pr-2 rounded mr-2 bg-white flex items-center\">\n <mat-icon class=\"text-base\">calendar_month</mat-icon>\n Date Picker\n </button>\n <button (click)=\"changeDateType($event, parameter, 'period')\"\n class=\"hover:bg-gray-50 text-gray-800 border border-gray-300 py-0.5 pr-2 rounded bg-white flex items-center\">\n <mat-icon class=\"text-base\">restore</mat-icon>\n Time Period\n </button>\n </div>\n </ng-template>\n <ng-template [ngIf]=\"parameter._dateType === 'picker'\">\n <input [type]=\"parameter.type === 'date' ? 'date' : 'datetime-local'\" placeholder=\"Enter {{parameter.title}}\" [(ngModel)]=\"parameter.value\"\n (keyup.enter)=\"reloadWidget()\" required autofocus>\n\n <a (click)=\"changeDateType($event, parameter, 'period')\"\n matTooltip=\"Time Period\"\n class=\"text-center ml-2 hover:bg-gray-50 text-gray-800 border border-gray-300 py-0.5 pr-0.5 rounded mr-2 bg-white flex items-center\">\n <mat-icon class=\"text-base\">restore</mat-icon>\n </a>\n </ng-template>\n <ng-template [ngIf]=\"parameter._dateType === 'period'\">\n <div class=\"flex items-center\">\n <input #periodValue type=\"number\" placeholder=\"No.\" required autofocus\n class=\"w-16 mr-2\" min=\"0\" [value]=\"parameter._periodValue || 1\"\n (change)=\"updatePeriodValue(periodValue.value, period.value, parameter)\">\n\n <select class=\"param-period-picker mr-2\" [value]=\"parameter._period || 'DAYS'\"\n #period (change)=\"updatePeriodValue(periodValue.value, period.value, parameter)\">\n <option value=\"DAYS\">Days</option>\n <option value=\"HOURS\">Hours</option>\n </select>\n\n <div>Ago</div>\n </div>\n\n <a (click)=\"changeDateType($event, parameter, 'picker')\"\n matTooltip=\"Date Picker\"\n class=\"text-center ml-2 hover:bg-gray-50 text-gray-800 border border-gray-300 py-0.5 pr-0.5 rounded mr-2 bg-white flex items-center\">\n <mat-icon class=\"text-base\">calendar_month</mat-icon>\n </a>\n </ng-template>\n\n </ng-template>\n <ng-template [ngIf]=\"parameter.type === 'boolean'\">\n <mat-slide-toggle class=\"pr-4\" color=\"primary\"\n [checked]=\"parameter.value\" (change)=\"booleanUpdate($event, parameter)\"\n required></mat-slide-toggle>\n </ng-template>\n </div>\n </label>\n </ng-template>\n </div>\n </ng-template>\n\n <div class=\"item-container\" [ngClass]=\"{'flex justify-center': dashboardItemType.type === 'image',\n 'p-px': (dashboardItemType.type === 'table' || general.transparent), 'overflow-hidden': !!chartData,\n 'flex items-center': dashboardItemType.type === 'metric', 'cursor-pointer': (actionItem && Object.keys(actionItem).length)}\"\n (click)=\"(actionItem && Object.keys(actionItem).length) ? callToActionLink(actionItem): null\">\n\n <ng-template [ngIf]=\"dashboardItemType.type === 'text' && textData.value\">\n <div class=\"h-full\" *ngIf=\"textData.safeTextData\" [innerHTML]=\"textData.safeTextData\"></div>\n </ng-template>\n\n <ng-template [ngIf]=\"dashboardItemType.type === 'metric'\">\n <div class=\"w-full\">\n <dt class=\"text-base font-normal text-gray-900\">{{metric.title}}</dt>\n <dd class=\"mt-1 flex items-baseline justify-between md:block lg:flex\">\n <div class=\"flex items-baseline text-2xl font-semibold text-indigo-600\">\n {{metric.mainValue}}\n <span *ngIf=\"metric.subMetric\"\n class=\"ml-2 text-sm font-medium text-gray-500\">from {{metric.subValue}}\n <span class=\"text-xs\">({{metric.subTitle}})</span></span>\n </div>\n\n <div *ngIf=\"metric.showSubChange\"\n class=\"inline-flex items-baseline px-2.5 py-0.5 rounded-full text-sm font-medium md:mt-2 lg:mt-0\"\n [ngClass]=\"{'bg-green-100 text-green-800': metric.mainValue >= metric.subValue, 'bg-red-100 text-red-800': metric.mainValue < metric.subValue}\">\n <!-- Heroicon name: mini/arrow-up -->\n <svg *ngIf=\"metric.mainValue >= metric.subValue\"\n class=\"-ml-1 mr-0.5 h-5 w-5 flex-shrink-0 self-center text-green-500\"\n xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 20 20\" fill=\"currentColor\"\n aria-hidden=\"true\">\n <path fill-rule=\"evenodd\"\n d=\"M10 17a.75.75 0 01-.75-.75V5.612L5.29 9.77a.75.75 0 01-1.08-1.04l5.25-5.5a.75.75 0 011.08 0l5.25 5.5a.75.75 0 11-1.08 1.04l-3.96-4.158V16.25A.75.75 0 0110 17z\"\n clip-rule=\"evenodd\"/>\n </svg>\n <svg *ngIf=\"metric.mainValue < metric.subValue \" xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\" fill=\"currentColor\"\n class=\"-ml-1 mr-0.5 h-5 w-5 flex-shrink-0 self-center text-red-500\">\n <path fill-rule=\"evenodd\"\n d=\"M10 3a.75.75 0 01.75.75v10.638l3.96-4.158a.75.75 0 111.08 1.04l-5.25 5.5a.75.75 0 01-1.08 0l-5.25-5.5a.75.75 0 111.08-1.04l3.96 4.158V3.75A.75.75 0 0110 3z\"\n clip-rule=\"evenodd\"/>\n </svg>\n {{metric.difference}}\n </div>\n </dd>\n </div>\n </ng-template>\n\n <ng-template [ngIf]=\"dashboardItemType.type === 'network'\">\n <div class=\"w-full h-full\" [id]=\"itemInstanceKey + 'VIS'\"></div>\n </ng-template>\n\n <ng-template [ngIf]=\"dashboardItemType.type === 'image'\">\n <div *ngIf=\"imageData.source\" class=\"w-auto h-full\">\n <img [src]=\"imageData.source\" alt=\"\"\n (error)=\"imageError = true\">\n </div>\n\n <div *ngIf=\"!imageData.source || imageError\" class=\"h-full relative flex items-center justify-center\">\n <p class=\"z-10 text-lg\">No image</p>\n <svg xmlns=\"http://www.w3.org/2000/svg\" class=\"filter blur-sm absolute w-auto h-full text-gray-300\"\n fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"\n d=\"M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z\"/>\n </svg>\n </div>\n </ng-template>\n\n <ng-template [ngIf]=\"dashboardItemType.type === 'pie' || dashboardItemType.type === 'doughnut'\">\n <canvas baseChart *ngIf=\"chartData\" style=\"height: 200px\"\n [datasets]=\"chartData\"\n [labels]=\"dashboardItemType.labels\"\n [options]=\"{tooltips: { titleFontSize: 0 }, responsive:true, maintainAspectRatio: false}\"\n [legend]=\"!!dashboardItemType.legend\"\n [type]=\"dashboardItemType.type\"\n [plugins]=\"[]\">\n </canvas>\n </ng-template>\n\n <ng-template [ngIf]=\"dashboardItemType.type === 'line' || dashboardItemType.type === 'bar' || dashboardItemType.type === 'scatter'\">\n <canvas baseChart *ngIf=\"chartData\" style=\"height: 200px\"\n [datasets]=\"chartData\"\n [labels]=\"dashboardItemType.labels\"\n [options]=\"{tooltips: { titleFontSize: 0 }, scales: {y: {beginAtZero: dashboardItemType.beginAtZero, max: dashboardItemType.maxValue || null}}, responsive:true, maintainAspectRatio: false}\"\n [legend]=\"!!dashboardItemType.legend\"\n [type]=\"dashboardItemType.type\"\n [plugins]=\"[]\">\n </canvas>\n </ng-template>\n\n <ng-template [ngIf]=\"dashboardItemType.type === 'table'\">\n\n <table class=\"min-w-full border-separate\" style=\"border-spacing: 0\">\n <thead class=\"bg-gray-50 \">\n <tr>\n <ng-template ngFor let-column [ngForOf]=\"dataset.columns\">\n <th scope=\"col\" *ngIf=\"!hiddenColumns[column.name]\" (click)=\"sortHeader(column)\"\n class=\"cursor-pointer sticky -top-px z-10 border-b border-gray-300 bg-gray-50 bg-opacity-75 p-3 text-left text-xs font-semibold text-gray-900 backdrop-blur backdrop-filter\">\n <div *ngIf=\"!tableCells[column.name] || tableCells[column.name].type !== 'action'\"\n class=\"flex items-center \">\n {{column.title}}\n <svg *ngIf=\"column.direction === 'asc'\"\n xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\"\n stroke-width=\"1.5\"\n stroke=\"currentColor\" class=\"stroke-3 text-secondary ml-1 w-4 h-4\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\"\n d=\"M4.5 10.5L12 3m0 0l7.5 7.5M12 3v18\"/>\n </svg>\n <svg *ngIf=\"column.direction === 'desc'\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\"\n viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\"\n class=\"stroke-3 text-secondary ml-1 w-4 h-4\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\"\n d=\"M19.5 13.5L12 21m0 0l-7.5-7.5M12 21V3\"/>\n </svg>\n </div>\n </th>\n </ng-template>\n </tr>\n </thead>\n <tbody class=\"bg-white \">\n <tr *ngFor=\"let dataItem of optimise ? dataset.allData.slice(0,10) : dataset.allData\"\n [ngClass]=\"{'hover:bg-gray-50 cursor-pointer ': (tabular.actionRows && tabular.cta)}\"\n (click)=\"(tabular.actionRows && tabular.cta) ? callToActionLink(tabular.cta, dataItem) : null\">\n <ng-template ngFor let-column [ngForOf]=\"dataset.columns\" let-i=index>\n <td *ngIf=\"!hiddenColumns[column.name]\"\n [title]=\"(tableCells[column.name] && tableCells[column.name].maxWidth) ? dataItem[column.name] : ''\"\n class=\"border-b border-gray-200 px-3 py-2 text-sm text-gray-500 relative\"\n [ngClass]=\"{'whitespace-nowrap': !tabular.expandRows, 'font-medium text-gray-900': i === 0}\"\n [ngStyle]=\"{'width': '', 'max-width': (tableCells[column.name] && tableCells[column.name].maxWidth) ? tableCells[column.name].maxWidth + 'px' : null, 'overflow': (tableCells[column.name] && tableCells[column.name].maxWidth) ? 'hidden' : null, 'text-overflow': (tableCells[column.name] && tableCells[column.name].maxWidth) ? 'ellipsis' : null}\">\n <ng-template [ngIf]=\"tableCells[column.name] && tableCells[column.name].type === 'action'\">\n <button type=\"button\" *ngIf=\"tableCells[column.name].data.actionEvent\"\n [ngClass]=\"{'bg-orange-50 border-orange-200 hover:bg-orange-100': isActionComplete(tableCells[column.name].data.actionEvent, dataItem[column.name])}\"\n (click)=\"triggerActionEvent(tableCells[column.name].data.actionEvent, column, dataItem[column.name])\"\n class=\"text-gray-600 inline-flex items-center rounded border border-primary bg-gray-50 px-2.5 py-1.5 text-xs font-medium hover:bg-gray-100\">\n {{getActionEventTitle(tableCells[column.name].data.actionEvent, column, dataItem[column.name])}}\n </button>\n </ng-template>\n\n <ng-template [ngIf]=\"!tableCells[column.name] || tableCells[column.name].type !== 'action'\">\n\n\n <ng-template [ngIf]=\"tabular.expandRows\">\n <div *ngIf=\"!_.isPlainObject(dataItem[column.name])\"\n [innerHTML]=\"dataItem[column.name]\"></div>\n <div *ngIf=\"_.isPlainObject(dataItem[column.name])\"\n [innerHTML]=\"dataItem[column.name].cellValue\"></div>\n </ng-template>\n <ng-template [ngIf]=\"!tabular.expandRows && _.isPlainObject(dataItem[column.name])\">\n <div [innerHTML]=\"dataItem[column.name].cellValue\"\n [ngStyle]=\"{'max-width': (tableCells[column.name] && tableCells[column.name].maxWidth) ? tableCells[column.name].maxWidth + 'px' : null, 'overflow': (tableCells[column.name] && tableCells[column.name].maxWidth) ? 'hidden' : null, 'text-overflow': (tableCells[column.name] && tableCells[column.name].maxWidth) ? 'ellipsis' : null}\"></div>\n </ng-template>\n <ng-template [ngIf]=\"!tabular.expandRows && !_.isPlainObject(dataItem[column.name])\">\n <ng-template\n [ngIf]=\"dataItem[column.name] && String(dataItem[column.name]).length <= 100\">\n {{dataItem[column.name]}}\n </ng-template>\n <ng-template\n [ngIf]=\"dataItem[column.name] && String(dataItem[column.name]).length > 100\">\n <div\n [ngStyle]=\"{'max-width': (tableCells[column.name] && tableCells[column.name].maxWidth) ? tableCells[column.name].maxWidth + 'px' : null, 'overflow': (tableCells[column.name] && tableCells[column.name].maxWidth) ? 'hidden' : null, 'text-overflow': (tableCells[column.name] && tableCells[column.name].maxWidth) ? 'ellipsis' : null}\"\n [title]=\"dataItem[column.name]\">{{dataItem[column.name].substring(0, 100) + '...'}}</div>\n </ng-template>\n <ng-template [ngIf]=\"!dataItem[column.name]\">\n {{dataItem[column.name]}}\n </ng-template>\n </ng-template>\n </ng-template>\n </td>\n </ng-template>\n\n </tr>\n <tr *ngIf=\"optimise && dataset.allData.length > 10\">\n <td class=\"pl-3 text-gray-900 font-medium bg-gray-200\" [colSpan]=\"dataset.columns.length\">\n Results limited during editing for enhanced performance.\n </td>\n </tr>\n </tbody>\n </table>\n\n <div *ngIf=\"!dataset.allData.length\"\n class=\"no-table-records text-sm text-gray-500 flex m-0 justify-center items-center\">\n No records to show\n </div>\n </ng-template>\n\n <ng-template [ngIf]=\"dashboardItemType.type === 'words'\">\n <angular-d3-cloud *ngIf=\"wordCloud.data\"\n [data]=\"wordCloud.data\"\n [width]=\"wordCloud.width\"\n [height]=\"wordCloud.height\"\n [padding]=\"5\"\n font=\"serif\"\n [rotate]=\"0\"\n [autoFill]=\"true\"\n ></angular-d3-cloud>\n </ng-template>\n\n </div>\n\n <div *ngIf=\"!optimise && dashboardItemType.type === 'table' && !tabular.hidePager\"\n class=\"table-pager flex items-center justify-between px-2 border-t border-gray-200 h-12 bg-gray-50 w-full\">\n <div class=\"text-xs text-gray-400\">\n Showing {{offset + 1}} - {{(page * limit) - (limit - dataset.allData.length)}}</div>\n <div class=\"flex items-center justify-center\">\n <button mat-icon-button (click)=\"decreaseOffset()\" [disabled]=\"page <= 1\">\n <mat-icon>chevron_left</mat-icon>\n </button>\n <select [value]=\"limit\" (change)=\"pageSizeChange($event.target.value)\"\n class=\"p-1 mx-2\">\n <option [value]=\"1\">1</option>\n <option [value]=\"5\">5</option>\n <option [value]=\"10\">10</option>\n <option [value]=\"25\">25</option>\n <option [value]=\"50\">50</option>\n <option [value]=\"100\">100</option>\n <option [value]=\"250\">250</option>\n <option [value]=\"1000\">1000</option>\n </select>\n <button mat-icon-button (click)=\"increaseOffset()\" [disabled]=\"endOfResults\">\n <mat-icon>chevron_right</mat-icon>\n </button>\n </div>\n </div>\n\n <div class=\"footer w-full bg-gray-50 px-2 py-1 text-gray-600 border-b border-gray-200 text-xs\"\n [ngClass]=\"{'border-b': callToAction && Object.keys(callToAction).length}\"\n *ngIf=\"general.footer\" [innerHTML]=\"general.evaluatedFooter\"></div>\n\n <div class=\"call-to-action w-full bg-gray-50 px-5 py-3\" *ngIf=\"callToAction && Object.keys(callToAction).length\">\n <div class=\"text-sm\">\n <a class=\"font-medium text-cta flex items-center\"\n (click)=\"callToActionLink(callToAction)\">\n {{callToAction.label}}\n <mat-icon>chevron_right</mat-icon>\n </a>\n </div>\n </div>\n\n</ng-template>\n", styles: [":host:hover .edit-widget,:host:hover .item-unlocked{display:block}.alert-panel{position:absolute;background-color:#fffffff2;inset:0;z-index:99999;display:flex;align-items:center;flex-direction:column}.alert-panel .alert-item{font-weight:500}.alert-panel mat-icon{color:#c41717;font-size:3rem;width:3rem;height:3rem}.no-table-records{height:calc(100% - 41px)}.divider{width:1px;height:17px;background-color:#cecece}.loading-item{display:flex;align-items:center;justify-content:center;flex-direction:column}.loading-item p{margin:1rem 0}.item-title{width:100%;color:gray;padding:1rem 1rem 0;font-size:1rem;font-weight:300}.item-description{width:100%;padding:0 1rem 1rem;font-size:1.1rem;font-weight:500}.item-heading{font-size:1.2rem;display:flex;align-items:center;justify-content:center;width:100%;height:100%}.item-container{padding:1rem;box-sizing:border-box;position:relative;width:100%;height:100%;overflow:auto}.item-container::-webkit-scrollbar{width:.75em;height:.75em;background:transparent}.item-container::-webkit-scrollbar-thumb{background:#d2d2d2}.edit-widget,.item-unlocked{display:none}table{width:100%;border-collapse:collapse}table thead tr th{text-transform:uppercase;text-align:left;border-bottom:1px solid #dbdbdb;padding:0 1rem 1rem 0;color:#5f6368;letter-spacing:1px;white-space:nowrap;font-weight:400;font-size:12px}table tbody tr td{padding:.5rem 1rem .5rem 0;border-bottom:1px solid #ececec;font-size:13px}label.widget-parameter{flex-direction:row;align-items:center;margin-left:1rem}label.widget-parameter .parameter-input{border-radius:4px;padding-left:.5rem;height:36px;display:flex;align-items:center}label.widget-parameter .parameter-input .param-period-picker{padding:5px}label.widget-parameter .parameter-input button{color:#8e8e8e}label.widget-parameter .parameter-input button.edit-parameter{visibility:hidden}label.widget-parameter .parameter-input button.mat-icon-button{width:30px;height:30px;line-height:30px;align-self:center}label.widget-parameter .parameter-input button.mat-icon-button mat-icon{font-size:20px;width:20px;height:20px;line-height:20px}label.widget-parameter .parameter-input input{font-size:.9rem;padding:.25rem .45rem;width:175px}label.widget-parameter .parameter-input:hover .edit-parameter{visibility:visible}\n"], dependencies: [{ kind: "directive", type: i8.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i8.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i8.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i8.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: i11.MatLegacyButton, selector: "button[mat-button], button[mat-raised-button], button[mat-icon-button], button[mat-fab], button[mat-mini-fab], button[mat-stroked-button], button[mat-flat-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { kind: "component", type: i12.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: i13.BaseChartDirective, selector: "canvas[baseChart]", inputs: ["type", "legend", "data", "options", "plugins", "labels", "datasets"], outputs: ["chartClick", "chartHover"], exportAs: ["base-chart"] }, { kind: "component", type: i14.MatLegacyMenu, selector: "mat-menu", exportAs: ["matMenu"] }, { kind: "component", type: i14.MatLegacyMenuItem, selector: "[mat-menu-item]", inputs: ["disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i14.MatLegacyMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", exportAs: ["matMenuTrigger"] }, { kind: "directive", type: i15.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i15.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i15.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: i15.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i15.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i15.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i15.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i16.MatLegacySlideToggle, selector: "mat-slide-toggle", inputs: ["disabled", "disableRipple", "color", "tabIndex"], exportAs: ["matSlideToggle"] }, { kind: "component", type: i17.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "directive", type: i18.MatLegacyTooltip, selector: "[matTooltip]", exportAs: ["matTooltip"] }, { kind: "component", type: i19.AngularD3CloudComponent, selector: "angular-d3-cloud", inputs: ["data", "width", "height", "padding", "font", "fontSizeMapper", "rotate", "autoFill", "animations", "fillMapper"], outputs: ["wordClick", "wordMouseOver", "wordMouseOut"] }] });
1194
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: ItemComponentComponent, decorators: [{
1195
- type: Component,
1196
- args: [{ selector: 'ki-item-component', template: "<div class=\"alert-panel\" *ngIf=\"showAlertData\" (click)=\"showAlertData = false\">\n <div class=\"align-center flex-col w-3/4 m-auto\">\n <mat-icon>notification_important</mat-icon>\n <h2 class=\"mb-0\">Alert Notification</h2>\n <p class=\"text-center\">The following alerts have been triggered based on the criteria set for this dashboard\n item...</p>\n <div class=\"alert-item mb-2\" *ngFor=\"let alertItem of alertData\"\n [innerHTML]=\"alertItem.notificationMessage\">\n </div>\n </div>\n</div>\n\n<div class=\"item-disabled\">\n <p>{{general.name || dashboardItemType.label}}</p>\n <mat-icon>block</mat-icon>\n <p class=\"disabled-notice\">{{dependencies.notice || 'No Data Available'}}</p>\n</div>\n\n<ng-template [ngIf]=\"dragItem\">\n <span class=\"material-symbols-outlined\">{{dashboardItemType.icon}}</span>\n <span [innerHTML]=\"dashboardItemType.label\"></span>\n</ng-template>\n<div class=\"alert-widget\" *ngIf=\"alert\" (click)=\"showAlertData = true;\">\n <button mat-icon-button>\n <mat-icon>notification_important</mat-icon>\n </button>\n <div class=\"alert-summaries\">\n <span class=\"mr-2\" *ngFor=\"let alertItem of alertData\">\n {{alertItem.summaryMessage}}\n </span>\n </div>\n</div>\n\n<ng-template\n [ngIf]=\"!dragItem && !dashboardDatasetInstance && !dashboardItemType.headingValue && !dashboardItemType._editing\">\n <button mat-stroked-button color=\"primary\" class=\"config-button\" (click)=\"configure()\">\n Configure {{dashboardItemType.label}}\n </button>\n</ng-template>\n\n<div class=\"absolute top-1 right-1 z-20\" *ngIf=\"!dragItem && loadingItem && (chartData || dataset)\">\n <svg class=\"animate-spin h-5 w-5 text-secondary\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\">\n <circle class=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" stroke-width=\"4\"></circle>\n <path class=\"opacity-75\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"></path>\n </svg>\n</div>\n\n<ng-template [ngIf]=\"!viewOnly\">\n <div class=\"absolute top-1 left-1 z-20 cursor-pointer\" *ngIf=\"!dragItem && this.itemNoMove\"\n (click)=\"lockItem()\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"currentColor\"\n class=\"h-5 w-5 text-gray-400\">\n <path fill-rule=\"evenodd\" d=\"M12 1.5a5.25 5.25 0 0 0-5.25 5.25v3a3 3 0 0 0-3 3v6.75a3 3 0 0 0 3 3h10.5a3 3 0 0 0 3-3v-6.75a3 3 0 0 0-3-3v-3c0-2.9-2.35-5.25-5.25-5.25Zm3.75 8.25v-3a3.75 3.75 0 1 0-7.5 0v3h7.5Z\" clip-rule=\"evenodd\" />\n </svg>\n </div>\n\n <div class=\"item-unlocked absolute top-1 left-1 z-20 cursor-pointer\" *ngIf=\"!dragItem && !this.itemNoMove\"\n (click)=\"lockItem()\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"currentColor\"\n class=\"h-5 w-5 text-gray-400\">\n <path d=\"M18 1.5c2.9 0 5.25 2.35 5.25 5.25v3.75a.75.75 0 0 1-1.5 0V6.75a3.75 3.75 0 1 0-7.5 0v3a3 3 0 0 1 3 3v6.75a3 3 0 0 1-3 3H3.75a3 3 0 0 1-3-3v-6.75a3 3 0 0 1 3-3h9v-3c0-2.9 2.35-5.25 5.25-5.25Z\" />\n </svg>\n </div>\n</ng-template>\n\n\n<ng-template [ngIf]=\"!externalError && !quotaExceeded\">\n <div class=\"loading-item\" *ngIf=\"!dragItem && loadingItem && !(chartData || dataset)\">\n\n <div class=\"mx-auto flex h-14 w-14 flex-shrink-0 items-center justify-center rounded-full bg-gray-100 \">\n <svg class=\"animate-spin h-14 w-14 text-gray-400\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\">\n <circle class=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" stroke-width=\"4\"></circle>\n <path class=\"opacity-75\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"></path>\n </svg>\n </div>\n <div class=\"px-4 text-center mt-4\">Loading {{dashboardItemType.label}} ...</div>\n </div>\n</ng-template>\n\n<ng-template [ngIf]=\"externalError\">\n <div class=\"loading-item\">\n <div class=\"mx-auto flex h-14 w-14 flex-shrink-0 items-center justify-center rounded-full bg-red-100 \">\n <svg class=\"h-10 w-10 text-red-600\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" aria-hidden=\"true\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126zM12 15.75h.007v.008H12v-.008z\" />\n </svg>\n </div>\n <div class=\"px-4 w-3/4 text-center mt-4\">There was a problem loading this item. Please try again later.</div>\n </div>\n</ng-template>\n\n<ng-template [ngIf]=\"quotaExceeded\">\n <div class=\"loading-item\">\n <div class=\"mx-auto flex h-14 w-14 flex-shrink-0 items-center justify-center rounded-full bg-blue-100 \">\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\"\n class=\"h-10 w-10 text-blue-600\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M11.25 11.25l.041-.02a.75.75 0 011.063.852l-.708 2.836a.75.75 0 001.063.853l.041-.021M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-9-3.75h.008v.008H12V8.25z\" />\n </svg>\n </div>\n <div class=\"px-4 w-3/4 text-center mt-4\">{{quotaExceeded}}</div>\n </div>\n</ng-template>\n\n<ng-template [ngIf]=\"!itemLocked\">\n <button *ngIf=\"!dragItem\" mat-mini-fab class=\"edit-widget bg-white text-gray-500 bg-opacity-90\"\n [matMenuTriggerFor]=\"editMenu\">\n <mat-icon>more_horiz</mat-icon>\n </button>\n <mat-menu #editMenu=\"matMenu\">\n <ng-template [ngIf]=\"!viewOnly\">\n <button mat-menu-item (click)=\"configure()\">\n <mat-icon>edit</mat-icon>\n Edit Item\n </button>\n <button *ngIf=\"existingGridItem\" mat-menu-item (click)=\"duplicate()\">\n <mat-icon>copy_all</mat-icon>\n Duplicate Item\n </button>\n <button *ngIf=\"canExportData\" mat-menu-item (click)=\"exportData()\">\n <mat-icon>file_download</mat-icon>\n Export Data\n </button>\n <mat-divider></mat-divider>\n <button mat-menu-item (click)=\"removeWidget($event)\">\n <mat-icon class=\"text-red-600\">delete</mat-icon>\n Delete Item\n </button>\n </ng-template>\n <ng-template [ngIf]=\"viewOnly\">\n <button *ngIf=\"canExportData\" mat-menu-item (click)=\"exportData()\">\n <mat-icon>file_download</mat-icon>\n Export Data\n </button>\n <mat-divider></mat-divider>\n <button mat-menu-item (click)=\"editItemAlerts(null)\">\n <mat-icon color=\"primary\">add</mat-icon>\n <span>New Alert</span>\n </button>\n <ng-template [ngIf]=\"dashboardDatasetInstance\">\n <div mat-menu-item class=\"flex items-center justify-between p-0 \"\n [ngClass]=\"{'border border-t border-b-0 border-r-0 border-l-0 border-solid border-gray-200': i === 0}\"\n *ngFor=\"let alert of dashboardDatasetInstance.alerts; let i = index\">\n <div class=\"px-4 flex items-center\" (click)=\"editItemAlerts(alert, i)\">\n <mat-icon>edit</mat-icon>\n <span>{{alert.title}}</span>\n </div>\n <div class=\"flex items-center\">\n <div class=\"mx-2 divider\"></div>\n <button mat-icon-button (click)=\"removeAlert($event, alert, i)\">\n <mat-icon class=\"mx-2 text-red-600 m-0\">highlight_off</mat-icon>\n </button>\n </div>\n\n </div>\n </ng-template>\n </ng-template>\n </mat-menu>\n</ng-template>\n\n<ng-template [ngIf]=\"!dragItem && dashboardItemType.type === 'heading'\">\n\n <div class=\"item-heading\" *ngIf=\"!dashboardItemType._editing\">\n {{bindParametersInString(dashboardItemType.headingValue)}}\n </div>\n\n <input type=\"text\" *ngIf=\"dashboardItemType._editing\" [(ngModel)]=\"dashboardItemType.headingValue\"\n (blur)=\"updateHeading($event)\" class=\"w-11/12\">\n\n</ng-template>\n\n<ng-template [ngIf]=\"!dragItem && (chartData || dataset)\">\n\n <div class=\"item-title \" *ngIf=\"general.name\" [innerHTML]=\"general.evaluatedName\"\n [ngClass]=\"{'pb-4': !general.description, 'pb-2': general.description}\"></div>\n\n <div class=\"item-description text-sm\" *ngIf=\"general.description\"\n [innerHTML]=\"general.evaluatedDescription\"></div>\n\n <ng-template [ngIf]=\"general.widgetParameters && _.values(general.widgetParameters).length\">\n <div class=\"p-2 bg-gray-100 w-full flex flex-wrap\">\n <ng-template ngFor let-parameter [ngForOf]=\"_.values(general.widgetParameters)\" let-i=index>\n <label class=\"widget-parameter\">\n {{parameter.title}}\n <div class=\"parameter-input\">\n <ng-template [ngIf]=\"parameter.type === 'text'\">\n <input type=\"text\" placeholder=\"Enter {{parameter.title}}\" [(ngModel)]=\"parameter.value\"\n (keyup.enter)=\"reloadWidget()\" required autofocus>\n </ng-template>\n <ng-template [ngIf]=\"parameter.type === 'numeric'\">\n <input type=\"number\" placeholder=\"Enter {{parameter.title}}\" [(ngModel)]=\"parameter.value\"\n (keyup.enter)=\"reloadWidget()\" required autofocus>\n </ng-template>\n <ng-template [ngIf]=\"parameter.type === 'date' || parameter.type === 'datetime'\">\n <ng-template [ngIf]=\"!parameter._dateType\">\n <div class=\"flex items-center\">\n <button (click)=\"changeDateType($event, parameter, 'picker')\"\n class=\"hover:bg-gray-50 text-gray-800 border border-gray-300 py-0.5 pr-2 rounded mr-2 bg-white flex items-center\">\n <mat-icon class=\"text-base\">calendar_month</mat-icon>\n Date Picker\n </button>\n <button (click)=\"changeDateType($event, parameter, 'period')\"\n class=\"hover:bg-gray-50 text-gray-800 border border-gray-300 py-0.5 pr-2 rounded bg-white flex items-center\">\n <mat-icon class=\"text-base\">restore</mat-icon>\n Time Period\n </button>\n </div>\n </ng-template>\n <ng-template [ngIf]=\"parameter._dateType === 'picker'\">\n <input [type]=\"parameter.type === 'date' ? 'date' : 'datetime-local'\" placeholder=\"Enter {{parameter.title}}\" [(ngModel)]=\"parameter.value\"\n (keyup.enter)=\"reloadWidget()\" required autofocus>\n\n <a (click)=\"changeDateType($event, parameter, 'period')\"\n matTooltip=\"Time Period\"\n class=\"text-center ml-2 hover:bg-gray-50 text-gray-800 border border-gray-300 py-0.5 pr-0.5 rounded mr-2 bg-white flex items-center\">\n <mat-icon class=\"text-base\">restore</mat-icon>\n </a>\n </ng-template>\n <ng-template [ngIf]=\"parameter._dateType === 'period'\">\n <div class=\"flex items-center\">\n <input #periodValue type=\"number\" placeholder=\"No.\" required autofocus\n class=\"w-16 mr-2\" min=\"0\" [value]=\"parameter._periodValue || 1\"\n (change)=\"updatePeriodValue(periodValue.value, period.value, parameter)\">\n\n <select class=\"param-period-picker mr-2\" [value]=\"parameter._period || 'DAYS'\"\n #period (change)=\"updatePeriodValue(periodValue.value, period.value, parameter)\">\n <option value=\"DAYS\">Days</option>\n <option value=\"HOURS\">Hours</option>\n </select>\n\n <div>Ago</div>\n </div>\n\n <a (click)=\"changeDateType($event, parameter, 'picker')\"\n matTooltip=\"Date Picker\"\n class=\"text-center ml-2 hover:bg-gray-50 text-gray-800 border border-gray-300 py-0.5 pr-0.5 rounded mr-2 bg-white flex items-center\">\n <mat-icon class=\"text-base\">calendar_month</mat-icon>\n </a>\n </ng-template>\n\n </ng-template>\n <ng-template [ngIf]=\"parameter.type === 'boolean'\">\n <mat-slide-toggle class=\"pr-4\" color=\"primary\"\n [checked]=\"parameter.value\" (change)=\"booleanUpdate($event, parameter)\"\n required></mat-slide-toggle>\n </ng-template>\n </div>\n </label>\n </ng-template>\n </div>\n </ng-template>\n\n <div class=\"item-container\" [ngClass]=\"{'flex justify-center': dashboardItemType.type === 'image',\n 'p-px': (dashboardItemType.type === 'table' || general.transparent), 'overflow-hidden': !!chartData,\n 'flex items-center': dashboardItemType.type === 'metric', 'cursor-pointer': (actionItem && Object.keys(actionItem).length)}\"\n (click)=\"(actionItem && Object.keys(actionItem).length) ? callToActionLink(actionItem): null\">\n\n <ng-template [ngIf]=\"dashboardItemType.type === 'text' && textData.value\">\n <div class=\"h-full\" *ngIf=\"textData.safeTextData\" [innerHTML]=\"textData.safeTextData\"></div>\n </ng-template>\n\n <ng-template [ngIf]=\"dashboardItemType.type === 'metric'\">\n <div class=\"w-full\">\n <dt class=\"text-base font-normal text-gray-900\">{{metric.title}}</dt>\n <dd class=\"mt-1 flex items-baseline justify-between md:block lg:flex\">\n <div class=\"flex items-baseline text-2xl font-semibold text-indigo-600\">\n {{metric.mainValue}}\n <span *ngIf=\"metric.subMetric\"\n class=\"ml-2 text-sm font-medium text-gray-500\">from {{metric.subValue}}\n <span class=\"text-xs\">({{metric.subTitle}})</span></span>\n </div>\n\n <div *ngIf=\"metric.showSubChange\"\n class=\"inline-flex items-baseline px-2.5 py-0.5 rounded-full text-sm font-medium md:mt-2 lg:mt-0\"\n [ngClass]=\"{'bg-green-100 text-green-800': metric.mainValue >= metric.subValue, 'bg-red-100 text-red-800': metric.mainValue < metric.subValue}\">\n <!-- Heroicon name: mini/arrow-up -->\n <svg *ngIf=\"metric.mainValue >= metric.subValue\"\n class=\"-ml-1 mr-0.5 h-5 w-5 flex-shrink-0 self-center text-green-500\"\n xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 20 20\" fill=\"currentColor\"\n aria-hidden=\"true\">\n <path fill-rule=\"evenodd\"\n d=\"M10 17a.75.75 0 01-.75-.75V5.612L5.29 9.77a.75.75 0 01-1.08-1.04l5.25-5.5a.75.75 0 011.08 0l5.25 5.5a.75.75 0 11-1.08 1.04l-3.96-4.158V16.25A.75.75 0 0110 17z\"\n clip-rule=\"evenodd\"/>\n </svg>\n <svg *ngIf=\"metric.mainValue < metric.subValue \" xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\" fill=\"currentColor\"\n class=\"-ml-1 mr-0.5 h-5 w-5 flex-shrink-0 self-center text-red-500\">\n <path fill-rule=\"evenodd\"\n d=\"M10 3a.75.75 0 01.75.75v10.638l3.96-4.158a.75.75 0 111.08 1.04l-5.25 5.5a.75.75 0 01-1.08 0l-5.25-5.5a.75.75 0 111.08-1.04l3.96 4.158V3.75A.75.75 0 0110 3z\"\n clip-rule=\"evenodd\"/>\n </svg>\n {{metric.difference}}\n </div>\n </dd>\n </div>\n </ng-template>\n\n <ng-template [ngIf]=\"dashboardItemType.type === 'network'\">\n <div class=\"w-full h-full\" [id]=\"itemInstanceKey + 'VIS'\"></div>\n </ng-template>\n\n <ng-template [ngIf]=\"dashboardItemType.type === 'image'\">\n <div *ngIf=\"imageData.source\" class=\"w-auto h-full\">\n <img [src]=\"imageData.source\" alt=\"\"\n (error)=\"imageError = true\">\n </div>\n\n <div *ngIf=\"!imageData.source || imageError\" class=\"h-full relative flex items-center justify-center\">\n <p class=\"z-10 text-lg\">No image</p>\n <svg xmlns=\"http://www.w3.org/2000/svg\" class=\"filter blur-sm absolute w-auto h-full text-gray-300\"\n fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"\n d=\"M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z\"/>\n </svg>\n </div>\n </ng-template>\n\n <ng-template [ngIf]=\"dashboardItemType.type === 'pie' || dashboardItemType.type === 'doughnut'\">\n <canvas baseChart *ngIf=\"chartData\" style=\"height: 200px\"\n [datasets]=\"chartData\"\n [labels]=\"dashboardItemType.labels\"\n [options]=\"{tooltips: { titleFontSize: 0 }, responsive:true, maintainAspectRatio: false}\"\n [legend]=\"!!dashboardItemType.legend\"\n [type]=\"dashboardItemType.type\"\n [plugins]=\"[]\">\n </canvas>\n </ng-template>\n\n <ng-template [ngIf]=\"dashboardItemType.type === 'line' || dashboardItemType.type === 'bar' || dashboardItemType.type === 'scatter'\">\n <canvas baseChart *ngIf=\"chartData\" style=\"height: 200px\"\n [datasets]=\"chartData\"\n [labels]=\"dashboardItemType.labels\"\n [options]=\"{tooltips: { titleFontSize: 0 }, scales: {y: {beginAtZero: dashboardItemType.beginAtZero, max: dashboardItemType.maxValue || null}}, responsive:true, maintainAspectRatio: false}\"\n [legend]=\"!!dashboardItemType.legend\"\n [type]=\"dashboardItemType.type\"\n [plugins]=\"[]\">\n </canvas>\n </ng-template>\n\n <ng-template [ngIf]=\"dashboardItemType.type === 'table'\">\n\n <table class=\"min-w-full border-separate\" style=\"border-spacing: 0\">\n <thead class=\"bg-gray-50 \">\n <tr>\n <ng-template ngFor let-column [ngForOf]=\"dataset.columns\">\n <th scope=\"col\" *ngIf=\"!hiddenColumns[column.name]\" (click)=\"sortHeader(column)\"\n class=\"cursor-pointer sticky -top-px z-10 border-b border-gray-300 bg-gray-50 bg-opacity-75 p-3 text-left text-xs font-semibold text-gray-900 backdrop-blur backdrop-filter\">\n <div *ngIf=\"!tableCells[column.name] || tableCells[column.name].type !== 'action'\"\n class=\"flex items-center \">\n {{column.title}}\n <svg *ngIf=\"column.direction === 'asc'\"\n xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\"\n stroke-width=\"1.5\"\n stroke=\"currentColor\" class=\"stroke-3 text-secondary ml-1 w-4 h-4\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\"\n d=\"M4.5 10.5L12 3m0 0l7.5 7.5M12 3v18\"/>\n </svg>\n <svg *ngIf=\"column.direction === 'desc'\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\"\n viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\"\n class=\"stroke-3 text-secondary ml-1 w-4 h-4\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\"\n d=\"M19.5 13.5L12 21m0 0l-7.5-7.5M12 21V3\"/>\n </svg>\n </div>\n </th>\n </ng-template>\n </tr>\n </thead>\n <tbody class=\"bg-white \">\n <tr *ngFor=\"let dataItem of optimise ? dataset.allData.slice(0,10) : dataset.allData\"\n [ngClass]=\"{'hover:bg-gray-50 cursor-pointer ': (tabular.actionRows && tabular.cta)}\"\n (click)=\"(tabular.actionRows && tabular.cta) ? callToActionLink(tabular.cta, dataItem) : null\">\n <ng-template ngFor let-column [ngForOf]=\"dataset.columns\" let-i=index>\n <td *ngIf=\"!hiddenColumns[column.name]\"\n [title]=\"(tableCells[column.name] && tableCells[column.name].maxWidth) ? dataItem[column.name] : ''\"\n class=\"border-b border-gray-200 px-3 py-2 text-sm text-gray-500 relative\"\n [ngClass]=\"{'whitespace-nowrap': !tabular.expandRows, 'font-medium text-gray-900': i === 0}\"\n [ngStyle]=\"{'width': '', 'max-width': (tableCells[column.name] && tableCells[column.name].maxWidth) ? tableCells[column.name].maxWidth + 'px' : null, 'overflow': (tableCells[column.name] && tableCells[column.name].maxWidth) ? 'hidden' : null, 'text-overflow': (tableCells[column.name] && tableCells[column.name].maxWidth) ? 'ellipsis' : null}\">\n <ng-template [ngIf]=\"tableCells[column.name] && tableCells[column.name].type === 'action'\">\n <button type=\"button\" *ngIf=\"tableCells[column.name].data.actionEvent\"\n [ngClass]=\"{'bg-orange-50 border-orange-200 hover:bg-orange-100': isActionComplete(tableCells[column.name].data.actionEvent, dataItem[column.name])}\"\n (click)=\"triggerActionEvent(tableCells[column.name].data.actionEvent, column, dataItem[column.name])\"\n class=\"text-gray-600 inline-flex items-center rounded border border-primary bg-gray-50 px-2.5 py-1.5 text-xs font-medium hover:bg-gray-100\">\n {{getActionEventTitle(tableCells[column.name].data.actionEvent, column, dataItem[column.name])}}\n </button>\n </ng-template>\n\n <ng-template [ngIf]=\"!tableCells[column.name] || tableCells[column.name].type !== 'action'\">\n\n\n <ng-template [ngIf]=\"tabular.expandRows\">\n <div *ngIf=\"!_.isPlainObject(dataItem[column.name])\"\n [innerHTML]=\"dataItem[column.name]\"></div>\n <div *ngIf=\"_.isPlainObject(dataItem[column.name])\"\n [innerHTML]=\"dataItem[column.name].cellValue\"></div>\n </ng-template>\n <ng-template [ngIf]=\"!tabular.expandRows && _.isPlainObject(dataItem[column.name])\">\n <div [innerHTML]=\"dataItem[column.name].cellValue\"\n [ngStyle]=\"{'max-width': (tableCells[column.name] && tableCells[column.name].maxWidth) ? tableCells[column.name].maxWidth + 'px' : null, 'overflow': (tableCells[column.name] && tableCells[column.name].maxWidth) ? 'hidden' : null, 'text-overflow': (tableCells[column.name] && tableCells[column.name].maxWidth) ? 'ellipsis' : null}\"></div>\n </ng-template>\n <ng-template [ngIf]=\"!tabular.expandRows && !_.isPlainObject(dataItem[column.name])\">\n <ng-template\n [ngIf]=\"dataItem[column.name] && String(dataItem[column.name]).length <= 100\">\n {{dataItem[column.name]}}\n </ng-template>\n <ng-template\n [ngIf]=\"dataItem[column.name] && String(dataItem[column.name]).length > 100\">\n <div\n [ngStyle]=\"{'max-width': (tableCells[column.name] && tableCells[column.name].maxWidth) ? tableCells[column.name].maxWidth + 'px' : null, 'overflow': (tableCells[column.name] && tableCells[column.name].maxWidth) ? 'hidden' : null, 'text-overflow': (tableCells[column.name] && tableCells[column.name].maxWidth) ? 'ellipsis' : null}\"\n [title]=\"dataItem[column.name]\">{{dataItem[column.name].substring(0, 100) + '...'}}</div>\n </ng-template>\n <ng-template [ngIf]=\"!dataItem[column.name]\">\n {{dataItem[column.name]}}\n </ng-template>\n </ng-template>\n </ng-template>\n </td>\n </ng-template>\n\n </tr>\n <tr *ngIf=\"optimise && dataset.allData.length > 10\">\n <td class=\"pl-3 text-gray-900 font-medium bg-gray-200\" [colSpan]=\"dataset.columns.length\">\n Results limited during editing for enhanced performance.\n </td>\n </tr>\n </tbody>\n </table>\n\n <div *ngIf=\"!dataset.allData.length\"\n class=\"no-table-records text-sm text-gray-500 flex m-0 justify-center items-center\">\n No records to show\n </div>\n </ng-template>\n\n <ng-template [ngIf]=\"dashboardItemType.type === 'words'\">\n <angular-d3-cloud *ngIf=\"wordCloud.data\"\n [data]=\"wordCloud.data\"\n [width]=\"wordCloud.width\"\n [height]=\"wordCloud.height\"\n [padding]=\"5\"\n font=\"serif\"\n [rotate]=\"0\"\n [autoFill]=\"true\"\n ></angular-d3-cloud>\n </ng-template>\n\n </div>\n\n <div *ngIf=\"!optimise && dashboardItemType.type === 'table' && !tabular.hidePager\"\n class=\"table-pager flex items-center justify-between px-2 border-t border-gray-200 h-12 bg-gray-50 w-full\">\n <div class=\"text-xs text-gray-400\">\n Showing {{offset + 1}} - {{(page * limit) - (limit - dataset.allData.length)}}</div>\n <div class=\"flex items-center justify-center\">\n <button mat-icon-button (click)=\"decreaseOffset()\" [disabled]=\"page <= 1\">\n <mat-icon>chevron_left</mat-icon>\n </button>\n <select [value]=\"limit\" (change)=\"pageSizeChange($event.target.value)\"\n class=\"p-1 mx-2\">\n <option [value]=\"1\">1</option>\n <option [value]=\"5\">5</option>\n <option [value]=\"10\">10</option>\n <option [value]=\"25\">25</option>\n <option [value]=\"50\">50</option>\n <option [value]=\"100\">100</option>\n <option [value]=\"250\">250</option>\n <option [value]=\"1000\">1000</option>\n </select>\n <button mat-icon-button (click)=\"increaseOffset()\" [disabled]=\"endOfResults\">\n <mat-icon>chevron_right</mat-icon>\n </button>\n </div>\n </div>\n\n <div class=\"footer w-full bg-gray-50 px-2 py-1 text-gray-600 border-b border-gray-200 text-xs\"\n [ngClass]=\"{'border-b': callToAction && Object.keys(callToAction).length}\"\n *ngIf=\"general.footer\" [innerHTML]=\"general.evaluatedFooter\"></div>\n\n <div class=\"call-to-action w-full bg-gray-50 px-5 py-3\" *ngIf=\"callToAction && Object.keys(callToAction).length\">\n <div class=\"text-sm\">\n <a class=\"font-medium text-cta flex items-center\"\n (click)=\"callToActionLink(callToAction)\">\n {{callToAction.label}}\n <mat-icon>chevron_right</mat-icon>\n </a>\n </div>\n </div>\n\n</ng-template>\n", styles: [":host:hover .edit-widget,:host:hover .item-unlocked{display:block}.alert-panel{position:absolute;background-color:#fffffff2;inset:0;z-index:99999;display:flex;align-items:center;flex-direction:column}.alert-panel .alert-item{font-weight:500}.alert-panel mat-icon{color:#c41717;font-size:3rem;width:3rem;height:3rem}.no-table-records{height:calc(100% - 41px)}.divider{width:1px;height:17px;background-color:#cecece}.loading-item{display:flex;align-items:center;justify-content:center;flex-direction:column}.loading-item p{margin:1rem 0}.item-title{width:100%;color:gray;padding:1rem 1rem 0;font-size:1rem;font-weight:300}.item-description{width:100%;padding:0 1rem 1rem;font-size:1.1rem;font-weight:500}.item-heading{font-size:1.2rem;display:flex;align-items:center;justify-content:center;width:100%;height:100%}.item-container{padding:1rem;box-sizing:border-box;position:relative;width:100%;height:100%;overflow:auto}.item-container::-webkit-scrollbar{width:.75em;height:.75em;background:transparent}.item-container::-webkit-scrollbar-thumb{background:#d2d2d2}.edit-widget,.item-unlocked{display:none}table{width:100%;border-collapse:collapse}table thead tr th{text-transform:uppercase;text-align:left;border-bottom:1px solid #dbdbdb;padding:0 1rem 1rem 0;color:#5f6368;letter-spacing:1px;white-space:nowrap;font-weight:400;font-size:12px}table tbody tr td{padding:.5rem 1rem .5rem 0;border-bottom:1px solid #ececec;font-size:13px}label.widget-parameter{flex-direction:row;align-items:center;margin-left:1rem}label.widget-parameter .parameter-input{border-radius:4px;padding-left:.5rem;height:36px;display:flex;align-items:center}label.widget-parameter .parameter-input .param-period-picker{padding:5px}label.widget-parameter .parameter-input button{color:#8e8e8e}label.widget-parameter .parameter-input button.edit-parameter{visibility:hidden}label.widget-parameter .parameter-input button.mat-icon-button{width:30px;height:30px;line-height:30px;align-self:center}label.widget-parameter .parameter-input button.mat-icon-button mat-icon{font-size:20px;width:20px;height:20px;line-height:20px}label.widget-parameter .parameter-input input{font-size:.9rem;padding:.25rem .45rem;width:175px}label.widget-parameter .parameter-input:hover .edit-parameter{visibility:visible}\n"] }]
1197
- }], ctorParameters: function () { return [{ type: i1.MatLegacyDialog }, { type: i2.DatasourceService }, { type: i3.DatasetService }, { type: i4.AlertService }, { type: i5.DashboardService }, { type: i6.DomSanitizer }, { type: i7.Router }, { type: i8.Location }, { type: i9.ExternalService }, { type: i10.ProjectService }]; }, propDecorators: { dashboardItemType: [{
1198
- type: Input
1199
- }], itemInstanceKey: [{
1200
- type: Input
1201
- }], dashboard: [{
1202
- type: Input
1203
- }], dashboardItem: [{
1204
- type: Input
1205
- }], dragItem: [{
1206
- type: Input
1207
- }], grid: [{
1208
- type: Input
1209
- }], actionEvents: [{
1210
- type: Input
1211
- }], external: [{
1212
- type: Input
1213
- }], queryParams: [{
1214
- type: Input
1215
- }], editAlerts: [{
1216
- type: Input
1217
- }], duplicateItem: [{
1218
- type: Output
1219
- }], configureClass: [{
1220
- type: HostBinding,
1221
- args: ['class.justify-center']
1222
- }], textTemplate: [{
1223
- type: ViewChild,
1224
- args: ['textTemplate']
1225
- }] } });
1226
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaXRlbS1jb21wb25lbnQuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmcta2luaW50ZWwvc3JjL2xpYi9jb21wb25lbnRzL2Rhc2hib2FyZC1lZGl0b3IvaXRlbS1jb21wb25lbnQvaXRlbS1jb21wb25lbnQuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmcta2luaW50ZWwvc3JjL2xpYi9jb21wb25lbnRzL2Rhc2hib2FyZC1lZGl0b3IvaXRlbS1jb21wb25lbnQvaXRlbS1jb21wb25lbnQuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUVILFNBQVMsRUFFVCxZQUFZLEVBQ1osV0FBVyxFQUNYLEtBQUssRUFFTCxNQUFNLEVBQ04sU0FBUyxFQUNaLE1BQU0sZUFBZSxDQUFDO0FBRXZCLE9BQU8sRUFBQyxzQkFBc0IsRUFBQyxNQUFNLDRDQUE0QyxDQUFDO0FBRWxGLE9BQU8sS0FBSyxNQUFNLE1BQU0sUUFBUSxDQUFDO0FBS2pDLE9BQU8sRUFBQyxPQUFPLEVBQWUsTUFBTSxNQUFNLENBQUM7QUFHM0MsT0FBTyxNQUFNLE1BQU0sUUFBUSxDQUFDO0FBQzVCLE9BQU8sVUFBVSxNQUFNLFlBQVksQ0FBQztBQUVwQyxPQUFPLEVBQ0gsMkJBQTJCLEVBQzlCLE1BQU0sdUVBQXVFLENBQUM7QUFDL0UsT0FBTyxFQUFDLG1CQUFtQixFQUFDLE1BQU0sdURBQXVELENBQUM7QUFLMUYsT0FBTyxNQUFNLE1BQU0sV0FBVyxDQUFDO0FBQy9CLE9BQU8sRUFBRSxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDMUQsT0FBTyxpQkFBaUIsTUFBTSw0Q0FBNEMsQ0FBQzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBbkIzRSxNQUFNLENBQUMsR0FBRyxNQUFNLENBQUMsT0FBTyxDQUFDO0FBNEJ6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QkFBQyxjQUFjIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgICBBZnRlclZpZXdJbml0LFxuICAgIENvbXBvbmVudCxcbiAgICBFbGVtZW50UmVmLFxuICAgIEV2ZW50RW1pdHRlcixcbiAgICBIb3N0QmluZGluZyxcbiAgICBJbnB1dCxcbiAgICBPbkRlc3Ryb3ksXG4gICAgT3V0cHV0LFxuICAgIFZpZXdDaGlsZFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7TWF0TGVnYWN5RGlhbG9nIGFzIE1hdERpYWxvZ30gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvbGVnYWN5LWRpYWxvZyc7XG5pbXBvcnQge0NvbmZpZ3VyZUl0ZW1Db21wb25lbnR9IGZyb20gJy4uL2NvbmZpZ3VyZS1pdGVtL2NvbmZpZ3VyZS1pdGVtLmNvbXBvbmVudCc7XG5pbXBvcnQge0RhdGFzb3VyY2VTZXJ2aWNlfSBmcm9tICcuLi8uLi8uLi9zZXJ2aWNlcy9kYXRhc291cmNlLnNlcnZpY2UnO1xuaW1wb3J0ICogYXMgbG9kYXNoIGZyb20gJ2xvZGFzaCc7XG5cbmNvbnN0IF8gPSBsb2Rhc2guZGVmYXVsdDtcbmltcG9ydCB7RGF0YXNldFNlcnZpY2V9IGZyb20gJy4uLy4uLy4uL3NlcnZpY2VzL2RhdGFzZXQuc2VydmljZSc7XG5pbXBvcnQge0FsZXJ0U2VydmljZX0gZnJvbSAnLi4vLi4vLi4vc2VydmljZXMvYWxlcnQuc2VydmljZSc7XG5pbXBvcnQge1N1YmplY3QsIFN1YnNjcmlwdGlvbn0gZnJvbSAncnhqcyc7XG5pbXBvcnQge0Rhc2hib2FyZFNlcnZpY2V9IGZyb20gJy4uLy4uLy4uL3NlcnZpY2VzL2Rhc2hib2FyZC5zZXJ2aWNlJztcbmltcG9ydCB7RG9tU2FuaXRpemVyfSBmcm9tICdAYW5ndWxhci9wbGF0Zm9ybS1icm93c2VyJztcbmltcG9ydCBtb21lbnQgZnJvbSAnbW9tZW50JztcbmltcG9ydCByZWdyZXNzaW9uIGZyb20gJ3JlZ3Jlc3Npb24nO1xuaW1wb3J0IHtSb3V0ZXJ9IGZyb20gJ0Bhbmd1bGFyL3JvdXRlcic7XG5pbXBvcnQge1xuICAgIEVkaXREYXNoYm9hcmRBbGVydENvbXBvbmVudFxufSBmcm9tICcuLi9jb25maWd1cmUtaXRlbS9lZGl0LWRhc2hib2FyZC1hbGVydC9lZGl0LWRhc2hib2FyZC1hbGVydC5jb21wb25lbnQnO1xuaW1wb3J0IHtFeHBvcnREYXRhQ29tcG9uZW50fSBmcm9tICcuLi8uLi9kYXRhLWV4cGxvcmVyL2V4cG9ydC1kYXRhL2V4cG9ydC1kYXRhLmNvbXBvbmVudCc7XG5pbXBvcnQge0xvY2F0aW9ufSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHtBY3Rpb25FdmVudH0gZnJvbSAnLi4vLi4vLi4vb2JqZWN0cy9hY3Rpb24tZXZlbnQnO1xuaW1wb3J0IHtFeHRlcm5hbFNlcnZpY2V9IGZyb20gJy4uLy4uLy4uL3NlcnZpY2VzL2V4dGVybmFsLnNlcnZpY2UnO1xuaW1wb3J0IHtQcm9qZWN0U2VydmljZX0gZnJvbSAnLi4vLi4vLi4vc2VydmljZXMvcHJvamVjdC5zZXJ2aWNlJztcbmltcG9ydCBjaHJvbWEgZnJvbSAnY2hyb21hLWpzJztcbmltcG9ydCB7IERhdGFTZXQsIE5ldHdvcmsgfSBmcm9tICd2aXMtbmV0d29yay9zdGFuZGFsb25lJztcbmltcG9ydCB2aXNOZXR3b3JrT3B0aW9ucyBmcm9tICcuLi9jb25maWd1cmUtaXRlbS92aXMtbmV0d29yay1vcHRpb25zLmpzb24nO1xuXG5kZWNsYXJlIHZhciB3aW5kb3c6IGFueTtcblxuQENvbXBvbmVudCh7XG4gICAgc2VsZWN0b3I6ICdraS1pdGVtLWNvbXBvbmVudCcsXG4gICAgdGVtcGxhdGVVcmw6ICcuL2l0ZW0tY29tcG9uZW50LmNvbXBvbmVudC5odG1sJyxcbiAgICBzdHlsZVVybHM6IFsnLi9pdGVtLWNvbXBvbmVudC5jb21wb25lbnQuc2FzcyddXG59KVxuZXhwb3J0IGNsYXNzIEl0ZW1Db21wb25lbnRDb21wb25lbnQgaW1wbGVtZW50cyBBZnRlclZpZXdJbml0LCBPbkRlc3Ryb3kge1xuXG4gICAgQElucHV0KCkgZGFzaGJvYXJkSXRlbVR5cGU6IGFueTtcbiAgICBASW5wdXQoKSBpdGVtSW5zdGFuY2VLZXk6IGFueTtcbiAgICBASW5wdXQoKSBkYXNoYm9hcmQ6IGFueTtcbiAgICBASW5wdXQoKSBkYXNoYm9hcmRJdGVtOiBhbnk7XG4gICAgQElucHV0KCkgZHJhZ0l0ZW06IGJvb2xlYW47XG4gICAgQElucHV0KCkgZ3JpZDogYW55O1xuICAgIEBJbnB1dCgpIGFjdGlvbkV2ZW50czogQWN0aW9uRXZlbnRbXSA9IFtdO1xuICAgIEBJbnB1dCgpIGV4dGVybmFsID0gZmFsc2U7XG4gICAgQElucHV0KCkgcXVlcnlQYXJhbXM6IGFueTtcbiAgICBASW5wdXQoKSBlZGl0QWxlcnRzID0gZmFsc2U7XG5cbiAgICBAT3V0cHV0KCkgZHVwbGljYXRlSXRlbTogRXZlbnRFbWl0dGVyPGFueT4gPSBuZXcgRXZlbnRFbWl0dGVyPGFueT4oKTtcblxuICAgIEBIb3N0QmluZGluZygnY2xhc3MuanVzdGlmeS1jZW50ZXInKSBjb25maWd1cmVDbGFzcyA9IGZhbHNlO1xuXG4gICAgQFZpZXdDaGlsZCgndGV4dFRlbXBsYXRlJykgdGV4dFRlbXBsYXRlOiBFbGVtZW50UmVmO1xuXG4gICAgcHVibGljIGRhdGFzb3VyY2VTZXJ2aWNlOiBhbnk7XG4gICAgcHVibGljIGRhdGFzZXRTZXJ2aWNlOiBhbnk7XG4gICAgcHVibGljIGFsZXJ0U2VydmljZTogYW55O1xuICAgIHB1YmxpYyBfID0gXztcbiAgICBwdWJsaWMgaW1hZ2VFcnJvciA9IGZhbHNlO1xuICAgIHB1YmxpYyBPYmplY3QgPSBPYmplY3Q7XG4gICAgcHVibGljIFN0cmluZyA9IFN0cmluZztcbiAgICBwdWJsaWMgZGF0YXNldDogYW55O1xuICAgIHB1YmxpYyBjaGFydERhdGE6IGFueTtcbiAgICBwdWJsaWMgZGFzaGJvYXJkRGF0YXNldEluc3RhbmNlOiBhbnkgPSB7fTtcbiAgICBwdWJsaWMgbG9hZGluZ0l0ZW0gPSBmYWxzZTtcbiAgICBwdWJsaWMgZmlsdGVyRmllbGRzOiBhbnkgPSBbXTtcbiAgICBwdWJsaWMgZGVwZW5kZW5jaWVzOiBhbnkgPSB7fTtcbiAgICBwdWJsaWMgbWV0cmljOiBhbnkgPSB7fTtcbiAgICBwdWJsaWMgdGV4dERhdGE6IGFueSA9IHt9O1xuICAgIHB1YmxpYyBuZXR3b3JrRGF0YTogYW55ID0ge307XG4gICAgcHVibGljIHdvcmRDbG91ZDogYW55ID0ge307XG4gICAgcHVibGljIGltYWdlRGF0YTogYW55ID0ge307XG4gICAgcHVibGljIHRhYnVsYXI6IGFueSA9IHt9O1xuICAgIHB1YmxpYyB0YWJsZUNlbGxzOiBhbnkgPSB7fTtcbiAgICBwdWJsaWMgaGlkZGVuQ29sdW1uczogYW55ID0ge307XG4gICAgcHVibGljIGdlbmVyYWw6IGFueSA9IHt9O1xuICAgIHB1YmxpYyBjYWxsVG9BY3Rpb246IGFueSA9IHt9O1xuICAgIHB1YmxpYyBhY3Rpb25JdGVtOiBhbnkgPSB7fTtcbiAgICBwdWJsaWMgYWxlcnQgPSBmYWxzZTtcbiAgICBwdWJsaWMgYWxlcnREYXRhOiBhbnkgPSBbXTtcbiAgICBwdWJsaWMgc2hvd0FsZXJ0RGF0YSA9IGZhbHNlO1xuICAgIHB1YmxpYyBhZG1pbjogYm9vbGVhbjtcbiAgICBwdWJsaWMgdmlld09ubHk6IGJvb2xlYW47XG4gICAgcHVibGljIGN1cnJlbmNpZXMgPSBbXG4gICAgICAgIHtcbiAgICAgICAgICAgIG5hbWU6ICdCcml0aXNoIFBvdW5kICjCoyknLFxuICAgICAgICAgICAgdmFsdWU6ICdHQlAnLFxuICAgICAgICAgICAgc3ltYm9sOiAnwqMnXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICAgIG5hbWU6ICdVUyBEb2xsYXIgKCQpJyxcbiAgICAgICAgICAgIHZhbHVlOiAnVVNEJyxcbiAgICAgICAgICAgIHN5bWJvbDogJyQnXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICAgIG5hbWU6ICdFdXJvICjigqwpJyxcbiAgICAgICAgICAgIHZhbHVlOiAnRVVSJyxcbiAgICAgICAgICAgIHN5bWJvbDogJ+KCrCdcbiAgICAgICAgfVxuICAgIF07XG4gICAgcHVibGljIGxpbWl0ID0gMjU7XG4gICAgcHVibGljIHBhZ2UgPSAxO1xuICAgIHB1YmxpYyBvZmZzZXQgPSAwO1xuICAgIHB1YmxpYyBlbmRPZlJlc3VsdHMgPSBmYWxzZTtcbiAgICBwdWJsaWMgaXRlbUxvY2tlZCA9IGZhbHNlO1xuICAgIHB1YmxpYyBvcHRpbWlzZSA9IHRydWU7XG4gICAgcHVibGljIG9wdGltaXNlU3ViamVjdCA9IG5ldyBTdWJqZWN0PGJvb2xlYW4+KCk7XG4gICAgcHVibGljIGNhbkV4cG9ydERhdGEgPSBmYWxzZTtcbiAgICBwdWJsaWMgZXh0ZXJuYWxFcnJvciA9IGZhbHNlO1xuICAgIHB1YmxpYyBxdW90YUV4Y2VlZGVkOiBzdHJpbmcgPSBudWxsO1xuICAgIHB1YmxpYyBleGlzdGluZ0dyaWRJdGVtID0gZmFsc2U7XG4gICAgcHVibGljIGl0ZW1Ob01vdmUgPSBmYWxzZTtcbiAgICBwdWJsaWMgdmlzTmV0d29ya09wdGlvbnMgPSB2aXNOZXR3b3JrT3B0aW9ucztcblxuICAgIHByaXZhdGUgaXRlbUxvYWRlZFN1YjogU3Vic2NyaXB0aW9uO1xuICAgIHByaXZhdGUgb3B0aW1pc2VTdWI6IFN1YnNjcmlwdGlvbjtcblxuICAgIGNvbnN0cnVjdG9yKHByaXZhdGUgZGlhbG9nOiBNYXREaWFsb2csXG4gICAgICAgICAgICAgICAgcHJpdmF0ZSBraURhdGFzb3VyY2VTZXJ2aWNlOiBEYXRhc291cmNlU2VydmljZSxcbiAgICAgICAgICAgICAgICBwcml2YXRlIGtpRGF0YXNldFNlcnZpY2U6IERhdGFzZXRTZXJ2aWNlLFxuICAgICAgICAgICAgICAgIHByaXZhdGUga2lBbGVydFNlcnZpY2U6IEFsZXJ0U2VydmljZSxcbiAgICAgICAgICAgICAgICBwcml2YXRlIGRhc2hib2FyZFNlcnZpY2U6IERhc2hib2FyZFNlcnZpY2UsXG4gICAgICAgICAgICAgICAgcHJpdmF0ZSBzYW5pdGl6ZXI6IERvbVNhbml0aXplcixcbiAgICAgICAgICAgICAgICBwcml2YXRlIHJvdXRlcjogUm91dGVyLFxuICAgICAgICAgICAgICAgIHByaXZhdGUgbG9jYXRpb246IExvY2F0aW9uLFxuICAgICAgICAgICAgICAgIHByaXZhdGUgZXh0ZXJuYWxTZXJ2aWNlOiBFeHRlcm5hbFNlcnZpY2UsXG4gICAgICAgICAgICAgICAgcHJpdmF0ZSBwcm9qZWN0U2VydmljZTogUHJvamVjdFNlcnZpY2UpIHtcbiAgICB9XG5cbiAgICBuZ0FmdGVyVmlld0luaXQoKSB7XG4gICAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5jYW5FeHBvcnREYXRhID0gdGhpcy5wcm9qZWN0U2VydmljZS5kb2VzQWN0aXZlUHJvamVjdEhhdmVQcml2aWxlZ2UoJ2V4cG9ydGRhdGEnKTtcblxuICAgICAgICAgICAgY29uc3QgaW5zdGFuY2VFbGVtZW50ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQodGhpcy5pdGVtSW5zdGFuY2VLZXkpO1xuICAgICAgICAgICAgaWYgKGluc3RhbmNlRWxlbWVudCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IHdpZGdldCA9IGluc3RhbmNlRWxlbWVudC5jbG9zZXN0KCcuZ3JpZC1zdGFjay1pdGVtJyk7XG4gICAgICAgICAgICAgICAgdGhpcy5pdGVtTm9Nb3ZlID0gd2lkZ2V0LmdldEF0dHJpYnV0ZSgnZ3Mtbm8tbW92ZScpID09PSAndHJ1ZSc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIDUwKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgYXN5bmMgaW5pdChldmFsdWF0ZSA9IGZhbHNlKSB7XG4gICAgICAgIHRoaXMubWFwTGF5b3V0U2V0dGluZ3NUb0NvbXBvbmVudERhdGEoKTtcblxuICAgICAgICBpZiAodGhpcy50YWJ1bGFyICYmIHRoaXMudGFidWxhci5saW1pdCkge1xuICAgICAgICAgICAgdGhpcy5saW1pdCA9IHRoaXMudGFidWxhci5saW1pdDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLmdlbmVyYWwgJiYgdGhpcy5nZW5lcmFsLmxpbWl0KSB7XG4gICAgICAgICAgICB0aGlzLmxpbWl0ID0gdGhpcy5nZW5lcmFsLmxpbWl0O1xuICAgICAgICAgICAgdGhpcy5vZmZzZXQgPSB0aGlzLmdlbmVyYWwub2Zmc2V0O1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCF0aGlzLmRhdGFzb3VyY2VTZXJ2aWNlKSB7XG4gICAgICAgICAgICB0aGlzLmRhdGFzb3VyY2VTZXJ2aWNlID0gdGhpcy5raURhdGFzb3VyY2VTZXJ2aWNlO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCF0aGlzLmRhdGFzZXRTZXJ2aWNlKSB7XG4gICAgICAgICAgICB0aGlzLmRhdGFzZXRTZXJ2aWNlID0gdGhpcy5raURhdGFzZXRTZXJ2aWNlO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCF0aGlzLmFsZXJ0U2VydmljZSkge1xuICAgICAgICAgICAgdGhpcy5hbGVydFNlcnZpY2UgPSB0aGlzLmtpQWxlcnRTZXJ2aWNlO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMuZGFzaGJvYXJkICYmXG4gICAgICAgICAgICB0aGlzLmRhc2hib2FyZC5kaXNwbGF5U2V0dGluZ3MuaGVhZGluZyAmJlxuICAgICAgICAgICAgdGhpcy5kYXNoYm9hcmQuZGlzcGxheVNldHRpbmdzLmhlYWRpbmdbdGhpcy5pdGVtSW5zdGFuY2VLZXldKSB7XG4gICAgICAgICAgICB0aGlzLmRhc2hib2FyZEl0ZW1UeXBlLmhlYWRpbmdWYWx1ZSA9IHRoaXMuZGFzaGJvYXJkLmRpc3BsYXlTZXR0aW5ncy5oZWFkaW5nW3RoaXMuaXRlbUluc3RhbmNlS2V5XTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLmdlbmVyYWwucGFyYW1ldGVyQmFyICYmIE9iamVjdC5rZXlzKHRoaXMuZ2VuZXJhbC5wYXJhbWV0ZXJCYXIpLmxlbmd0aCkge1xuICAgICAgICAgICAgaWYgKCF0aGlzLmdlbmVyYWwud2lkZ2V0UGFyYW1ldGVycyB8fCBBcnJheS5pc0FycmF5KHRoaXMuZ2VuZXJhbC53aWRnZXRQYXJhbWV0ZXJzKSkge1xuICAgICAgICAgICAgICAgIHRoaXMuZ2VuZXJhbC53aWRnZXRQYXJhbWV0ZXJzID0ge307XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIE9iamVjdC5rZXlzKHRoaXMuZ2VuZXJhbC5wYXJhbWV0ZXJCYXIpLmZvckVhY2gocGFyYW1LZXkgPT4ge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLmdlbmVyYWwucGFyYW1ldGVyQmFyW3BhcmFtS2V5XSAmJiAhdGhpcy5nZW5lcmFsLndpZGdldFBhcmFtZXRlcnNbcGFyYW1LZXldKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZ2VuZXJhbC53aWRnZXRQYXJhbWV0ZXJzW3BhcmFtS2V5XSA9IF8uY2xvbmVEZWVwKHRoaXMuZGFzaGJvYXJkLmxheW91dFNldHRpbmdzLnBhcmFtZXRlcnNbcGFyYW1LZXldKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLmdlbmVyYWwucGFyYW1ldGVyQmFyW3BhcmFtS2V5XSkge1xuICAgICAgICAgICAgICAgICAgICBkZWxldGUgdGhpcy5nZW5lcmFsLndpZGdldFBhcmFtZXRlcnNbcGFyYW1LZXldO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5jb25maWd1cmVDbGFzcyA9IHRydWU7XG4gICAgICAgIGlmICh0aGlzLmRlcGVuZGVuY2llcy5pbnN0YW5jZUtleXMgJiYgdGhpcy5kZXBlbmRlbmNpZXMuaW5zdGFuY2VLZXlzLmxlbmd0aCkge1xuICAgICAgICAgICAgdGhpcy5sb2FkaW5nSXRlbSA9IHRydWU7XG5cbiAgICAgICAgICAgIHRoaXMuaXRlbUxvYWRlZFN1YiA9IHRoaXMuZGFzaGJvYXJkU2VydmljZS5kYXNoYm9hcmRJdGVtcy5zdWJzY3JpYmUoYXN5bmMgbG9hZGVkID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBsb2FkZWRJbnN0YW5jZXMgPSBPYmplY3Qua2V5cyhsb2FkZWQpO1xuICAgICAgICAgICAgICAgIGNvbnN0IGRlcGVuZGVudCA9IF8uZmlsdGVyKGxvYWRlZEluc3RhbmNlcywga2V5ID0+IHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuZGVwZW5kZW5jaWVzLmluc3RhbmNlS2V5cy5pbmRleE9mKGtleSkgPiAtMTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBpZiAoZGVwZW5kZW50Lmxlbmd0aCA9PT0gdGhpcy5kZXBlbmRlbmNpZXMuaW5zdGFuY2VLZXlzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5pdGVtTG9hZGVkU3ViKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLml0ZW1Mb2FkZWRTdWIudW5zdWJzY3JpYmUoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGFsbExvYWRlZCA9IF8uZXZlcnkodGhpcy5kZXBlbmRlbmNpZXMuaW5zdGFuY2VLZXlzLCBrZXkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuZGVwZW5kZW5jaWVzW2tleV0udHlwZSA9PT0gJ0xPQURFRCc7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICBpZiAoYWxsTG9hZGVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmV2YWx1YXRlKCk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBtYXRjaGVzID0gXy5maWx0ZXIodGhpcy5kZXBlbmRlbmNpZXMsIHt0eXBlOiAnTUFUQ0gnfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBhbGxNYXRjaGVkID0gW107XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGRlcCBvZiBtYXRjaGVzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgc2VsZWN0ZWREYXRhc2V0SW5zdGFuY2UgPSBfLmZpbmQodGhpcy5kYXNoYm9hcmQuZGF0YXNldEluc3RhbmNlcywge2luc3RhbmNlS2V5OiBkZXAua2V5fSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNlbGVjdGVkRGF0YXNldEluc3RhbmNlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG1hcHBlZFBhcmFtcyA9IHRoaXMuZ2V0TWFwcGVkUGFyYW1zKHNlbGVjdGVkRGF0YXNldEluc3RhbmNlKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB0cmFuc2Zvcm1hdGlvbnMgPSBfLmNsb25lKHNlbGVjdGVkRGF0YXNldEluc3RhbmNlLnRyYW5zZm9ybWF0aW9uSW5zdGFuY2VzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJhbnNmb3JtYXRpb25zLnB1c2goe3R5cGU6ICdmaWx0ZXInLCBjb25maWc6IGRlcC5maWx0ZXJKdW5jdGlvbn0pO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGRhdGFzZXRJbnN0YW5jZVN1bW1hcnkgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhc2V0SW5zdGFuY2VJZDogc2VsZWN0ZWREYXRhc2V0SW5zdGFuY2UuZGF0YXNldEluc3RhbmNlSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhc291cmNlSW5zdGFuY2VLZXk6IHNlbGVjdGVkRGF0YXNldEluc3RhbmNlLmRhdGFzb3VyY2VJbnN0YW5jZUtleSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyYW5zZm9ybWF0aW9uSW5zdGFuY2VzOiB0cmFuc2Zvcm1hdGlvbnMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXJhbWV0ZXJWYWx1ZXM6IG1hcHBlZFBhcmFtcyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhcmFtZXRlcnM6IHNlbGVjdGVkRGF0YXNldEluc3RhbmNlLnBhcmFtZXRlcnNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXQgZGF0YSA9IG51bGw7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmV4dGVybmFsKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gYXdhaXQgdGhpcy5leHRlcm5hbFNlcnZpY2UuZXZhbHVhdGVEYXRhc2V0KFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZGFzaGJvYXJkLmlkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuaXRlbUluc3RhbmNlS2V5LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGVjdGVkRGF0YXNldEluc3RhbmNlLnBhcmFtZXRlclZhbHVlcyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnMCcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJzEnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucXVlcnlQYXJhbXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGF3YWl0IHRoaXMuZGF0YXNldFNlcnZpY2UuZXZhbHVhdGVEYXRhc2V0KFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGFzZXRJbnN0YW5jZVN1bW1hcnksICcwJywgJzEnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWxsTWF0Y2hlZC5wdXNoKGRhdGEuYWxsRGF0YS5sZW5ndGggPT09IDEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChfLmV2ZXJ5KGFsbE1hdGNoZWQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5ldmFsdWF0ZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmxvYWRpbmdJdGVtID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgaXRlbUVsZW1lbnQ6IGFueSA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHRoaXMuaXRlbUluc3RhbmNlS2V5KS5jbG9zZXN0KCcuZ3JpZC1zdGFjay1pdGVtJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUVsZW1lbnQuY2xhc3NMaXN0LmFkZCgnaXRlbS1kaXNhYmxlZCcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSBpZiAoZXZhbHVhdGUpIHtcbiAgICAgICAgICAgIHRoaXMuZXZhbHVhdGUoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMub3B0aW1pc2VTdWIgPSB0aGlzLm9wdGltaXNlU3ViamVjdC5zdWJzY3JpYmUocmVzID0+IHRoaXMub3B0aW1pc2UgPSByZXMpO1xuXG4gICAgICAgIHRoaXMuZXhpc3RpbmdHcmlkSXRlbSA9ICEhXy5maW5kKHRoaXMuZGFzaGJvYXJkLmxheW91dFNldHRpbmdzLmdyaWQsIGl0ZW0gPT4ge1xuICAgICAgICAgICAgcmV0dXJuIGl0ZW0uY29udGVudC5pbmNsdWRlcyh0aGlzLml0ZW1JbnN0YW5jZUtleSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIG5nT25EZXN0cm95KCkge1xuICAgICAgICBpZiAodGhpcy5vcHRpbWlzZVN1Yikge1xuICAgICAgICAgICAgdGhpcy5vcHRpbWlzZVN1Yi51bnN1YnNjcmliZSgpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLml0ZW1Mb2FkZWRTdWIpIHtcbiAgICAgICAgICAgIHRoaXMuaXRlbUxvYWRlZFN1Yi51bnN1YnNjcmliZSgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHVibGljIGxvY2tJdGVtKCkge1xuICAgICAgICBjb25zdCBpdGVtRWxlbWVudCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHRoaXMuaXRlbUluc3RhbmNlS2V5KTtcbiAgICAgICAgY29uc3Qgd2lkZ2V0ID0gaXRlbUVsZW1lbnQuY2xvc2VzdCgnLmdyaWQtc3RhY2staXRlbScpO1xuICAgICAgICB0aGlzLml0ZW1Ob01vdmUgPSB3aWRnZXQuZ2V0QXR0cmlidXRlKCdncy1uby1tb3ZlJykgIT09ICd0cnVlJztcbiAgICAgICAgdGhpcy5ncmlkLnVwZGF0ZSh3aWRnZXQsIHtub01vdmU6IHRoaXMuaXRlbU5vTW92ZX0pO1xuICAgIH1cblxuICAgIHB1YmxpYyBkdXBsaWNhdGUoKSB7XG4gICAgICAgIHRoaXMuZHVwbGljYXRlSXRlbS5lbWl0KHRoaXMuaXRlbUluc3RhbmNlS2V5KTtcbiAgICB9XG5cbiAgICBwdWJsaWMgY29uZmlndXJlKCkge1xuICAgICAgICBpZiAodGhpcy5kYXNoYm9hcmRJdGVtVHlwZS50eXBlID09PSAnaGVhZGluZycpIHtcbiAgICAgICAgICAgIHRoaXMuZGFzaGJvYXJkSXRlbVR5cGUuX2VkaXRpbmcgPSB0cnVlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29uc3QgcXVlcnlQYXJhbXM6IGFueSA9IHt9O1xuICAgICAgICAgICAgaWYgKHRoaXMuYWRtaW4pIHtcbiAgICAgICAgICAgICAgICBxdWVyeVBhcmFtcy5hID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMucm91dGVyLm5hdmlnYXRlKFt3aW5kb3cubG9jYXRpb24ucGF0aG5hbWVdLCB7XG4gICAgICAgICAgICAgICAgcXVlcnlQYXJhbXMsXG4gICAgICAgICAgICAgICAgZnJhZ21lbnQ6IF8ua2ViYWJDYXNlKHRoaXMuZGFzaGJvYXJkLnRpdGxlKVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBjb25zdCBkaWFsb2dSZWYgPSB0aGlzLmRpYWxvZy5vcGVuKENvbmZpZ3VyZUl0ZW1Db21wb25lbnQsIHtcbiAgICAgICAgICAgICAgICB3aWR0aDogJzEwMHZ3JyxcbiAgICAgICAgICAgICAgICBoZWlnaHQ6ICcxMDB2aCcsXG4gICAgICAgICAgICAgICAgbWF4V2lkdGg6ICcxMDB2dycsXG4gICAgICAgICAgICAgICAgbWF4SGVpZ2h0OiAnMTAwdmgnLFxuICAgICAgICAgICAgICAgIGhhc0JhY2tkcm9wOiBmYWxzZSxcbiAgICAgICAgICAgICAgICBkYXRhOiB7XG4gICAgICAgICAgICAgICAgICAgIGdyaWQ6IHRoaXMuZ3JpZCxcbiAgICAgICAgICAgICAgICAgICAgZGFzaGJvYXJkOiB0aGlzLmRhc2hib2FyZCxcbiAgICAgICAgICAgICAgICAgICAgZGFzaGJvYXJkRGF0YXNldEluc3RhbmNlOiB0aGlzLmRhc2hib2FyZERhdGFzZXRJbnN0YW5jZSxcbiAgICAgICAgICAgICAgICAgICAgaXRlbUluc3RhbmNlS2V5OiB0aGlzLml0ZW1JbnN0YW5jZUtleSxcbiAgICAgICAgICAgICAgICAgICAgZGFzaGJvYXJkSXRlbVR5cGU6IHRoaXMuZGFzaGJvYXJkSXRlbVR5cGUsXG4gICAgICAgICAgICAgICAgICAgIGFkbWluOiB0aGlzLmFkbWluLFxuICAgICAgICAgICAgICAgICAgICBhY3Rpb25FdmVudHM6IHRoaXMuYWN0aW9uRXZlbnRzXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBkaWFsb2dSZWYuYWZ0ZXJDbG9zZWQoKS5zdWJzY3JpYmUoZGFzaGJvYXJkRGF0YXNldEluc3RhbmNlID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoZGFzaGJvYXJkRGF0YXNldEluc3RhbmNlKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGFzaGJvYXJkRGF0YXNldEluc3RhbmNlID0gZGFzaGJvYXJkRGF0YXNldEluc3RhbmNlO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmxvY2F0aW9uLmJhY2soKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5pbml0KHRydWUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHVibGljIGxvYWQoKSB7XG4gICAgICAgIC8vIENoZWNrIHRvIHNlZSBpZiBhbnkgb2YgdGhlIGdyaWQgaXRlbXMgYXJlIGxvY2tlZFxuICAgICAgICBjb25zdCBncmlkID0gdGhpcy5kYXNoYm9hcmQubGF5b3V0U2V0dGluZ3MuZ3JpZDtcbiAgICAgICAgY29uc3QgbG9ja2VkSXRlbXMgPSBfLmZpbHRlcihncmlkLCAnbG9ja2VkJyk7XG4gICAgICAgIHRoaXMuaXRlbUxvY2tlZCA9ICEhXy5maW5kKGxvY2tlZEl0ZW1zLCBsb2NrZWRJdGVtID0+IHtcbiAgICAgICAgICAgIHJldHVybiBsb2NrZWRJdGVtLmNvbnRlbnQuaW5jbHVkZXModGhpcy5pdGVtSW5zdGFuY2VLZXkpO1xuICAgICAgICB9KTtcblxuICAgICAgICBpZiAodGhpcy5leHRlcm5hbCkge1xuICAgICAgICAgICAgdGhpcy5pdGVtTG9ja2VkID0gdHJ1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLmRhc2hib2FyZERhdGFzZXRJbnN0YW5jZSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZXZhbHVhdGUoKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHRydWUpO1xuICAgIH1cblxuICAgIHB1YmxpYyByZW1vdmVXaWRnZXQoZXZlbnQpIHtcbiAgICAgICAgY29uc3QgbWVzc2FnZSA9ICdBcmUgeW91ciBzdXJlIHlvdSB3b3VsZCBsaWtlIHRvIHJlbW92ZSB0aGlzIGl0ZW0gZnJvbSB5b3VyIGRhc2hib2FyZD8nO1xuICAgICAgICBpZiAod2luZG93LmNvbmZpcm0obWVzc2FnZSkpIHtcbiAgICAgICAgICAgIGNvbnN0IGl0ZW1FbGVtZW50ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQodGhpcy5pdGVtSW5zdGFuY2VLZXkpO1xuICAgICAgICAgICAgXy5yZW1vdmUodGhpcy5kYXNoYm9hcmQuZGF0YXNldEluc3RhbmNlcywge2luc3RhbmNlS2V5OiB0aGlzLml0ZW1JbnN0YW5jZUtleX0pO1xuICAgICAgICAgICAgY29uc3Qgd2lkZ2V0ID0gaXRlbUVsZW1lbnQuY2xvc2VzdCgnLmdyaWQtc3RhY2staXRlbScpO1xuICAgICAgICAgICAgdGhpcy5ncmlkLnJlbW92ZVdpZGdldCh3aWRnZXQpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHVibGljIHRyaWdnZXJBY3Rpb25FdmVudChhY3Rpb25FdmVudCwgY29sdW1uLCB2YWx1ZSkge1xuICAgICAgICBjb25zdCBhY3Rpb246IEFjdGlvbkV2ZW50ID0gXy5maW5kKHRoaXMuYWN0aW9uRXZlbnRzLCB7bmFtZTogYWN0aW9uRXZlbnR9KTtcbiAgICAgICAgaWYgKGFjdGlvbikge1xuICAgICAgICAgICAgYWN0aW9uLmV2ZW50Lm5leHQoe2tleTogY29sdW1uLm5hbWUsIHZhbHVlfSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0QWN0aW9uRXZlbnRUaXRsZShhY3Rpb25FdmVudCwgY29sdW1uLCB2YWx1ZSkge1xuICAgICAgICBjb25zdCBhY3Rpb246IEFjdGlvbkV2ZW50ID0gXy5maW5kKHRoaXMuYWN0aW9uRXZlbnRzLCB7bmFtZTogYWN0aW9uRXZlbnR9KTtcblxuICAgICAgICBsZXQgdGl0bGUgPSAnJztcbiAgICAgICAgaWYgKGFjdGlvbikge1xuICAgICAgICAgICAgdGl0bGUgPSB0aGlzLmlzQWN0aW9uQ29tcGxldGUoYWN0aW9uRXZlbnQsIHZhbHVlKSA/IGFjdGlvbi5jb21wbGV0ZUxhYmVsIDogYWN0aW9uLmFjdGlvbkxhYmVsO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aXRsZTtcbiAgICB9XG5cbiAgICBwdWJsaWMgaXNBY3Rpb25Db21wbGV0ZShhY3Rpb25FdmVudCwgdmFsdWUpIHtcbiAgICAgICAgbGV0IGNvbXBsZXRlID0gZmFsc2U7XG4gICAgICAgIGNvbnN0IGFjdGlvbjogQWN0aW9uRXZlbnQgPSBfLmZpbmQodGhpcy5hY3Rpb25FdmVudHMsIHtuYW1lOiBhY3Rpb25FdmVudH0pO1xuXG4gICAgICAgIGlmIChhY3Rpb24pIHtcbiAgICAgICAgICAgIGNvbnN0IGZpbmREYXRhID0ge307XG4gICAgICAgICAgICBmaW5kRGF0YVthY3Rpb24uY29tcGFyaXNvbkZpZWxkXSA9IHZhbHVlO1xuICAgICAgICAgICAgY29tcGxldGUgPSBfLmZpbmQoYWN0aW9uLmRhdGEgfHwgW10sIGZpbmREYXRhKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBjb21wbGV0ZTtcbiAgICB9XG5cbiAgICBwdWJsaWMgZWRpdEl0ZW1BbGVydHMoYWxlcnQsIGluZGV4Pykge1xuICAgICAgICBjb25zdCBkaWFsb2dSZWYgPSB0aGlzLmRpYWxvZy5vcGVuKEVkaXREYXNoYm9hcmRBbGVydENvbXBvbmVudCwge1xuICAgICAgICAgICAgd2lkdGg6ICc5MDBweCcsXG4gICAgICAgICAgICBoZWlnaHQ6ICc3NTBweCcsXG4gICAgICAgICAgICBkYXRhOiB7XG4gICAgICAgICAgICAgICAgYWxlcnQsXG4gICAgICAgICAgICAgICAgZmlsdGVyRmllbGRzOiB0aGlzLmZpbHRlckZpZWxkc1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICBkaWFsb2dSZWYuYWZ0ZXJDbG9zZWQoKS5zdWJzY3JpYmUoYWxlcnRJdGVtID0+IHtcbiAgICAgICAgICAgIGlmIChhbGVydEl0ZW0pIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuZGFzaGJvYXJkRGF0YXNldEluc3RhbmNlLmFsZXJ0cykge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmRhc2hib2FyZERhdGFzZXRJbnN0YW5jZS5hbGVydHMgPSBbXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGluZGV4ID49IDApIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kYXNoYm9hcmREYXRhc2V0SW5zdGFuY2UuYWxlcnRzW2luZGV4XSA9IGFsZXJ0SXRlbTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmRhc2hib2FyZERhdGFzZXRJbnN0YW5jZS5hbGVydHMucHVzaChhbGVydEl0ZW0pO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMucmVsb2FkQWxlcnQoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHVibGljIHJlbW92ZUFsZXJ0KGV2ZW50LCBhbGVydCwgaSkge1xuICAgICAgICBjb25zdCBtZXNzYWdlID0gYEFyZSB5b3Ugc3VyZSB5b3Ugd291bGQgbGlrZSB0byBkZWxldGUgdGhlIFwiJHthbGVydC50aXRsZX1cIiBBbGVydD9gO1xuICAgICAgICBpZiAod2luZG93LmNvbmZpcm0obWVzc2FnZSkpIHtcbiAgICAgICAgICAgIHRoaXMuZGFzaGJvYXJkRGF0YXNldEluc3RhbmNlLmFsZXJ0cy5zcGxpY2UoaSwgMSk7XG4gICAgICAgICAgICB0aGlzLnJlbG9hZEFsZXJ0KCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwdWJsaWMgZXhwb3J0RGF0YSgpIHtcbiAgICAgICAgY29uc3QgZGF0YXNldEluc3RhbmNlU3VtbWFyeSA9IHRoaXMucHJlcGFyZURhdGFzZXRJbnN0YW5jZVN1bW1hcnlGb3JFdmFsdWF0aW9uKCk7XG5cbiAgICAgICAgY29uc3QgZGlhbG9nUmVmID0gdGhpcy5kaWFsb2cub3BlbihFeHBvcnREYXRhQ29tcG9uZW50LCB7XG4gICAgICAgICAgICB3aWR0aDogJzYwMHB4JyxcbiAgICAgICAgICAgIGhlaWdodDogJzUzMHB4JyxcbiAgICAgICAgICAgIGRhdGE6IHtcbiAgICAgICAgICAgICAgICBkYXRhc2V0SW5zdGFuY2VTdW1tYXJ5XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHB1YmxpYyB1cGRhdGVIZWFkaW5nKGV2ZW50KSB7XG4gICAgICAgIGlmICghdGhpcy5kYXNoYm9hcmQuZGlzcGxheVNldHRpbmdzLmhlYWRpbmcpIHtcbiAgICAgICAgICAgIHRoaXMuZGFzaGJvYXJkLmRpc3BsYXlTZXR0aW5ncy5oZWFkaW5nID0ge307XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmRhc2hib2FyZC5kaXNwbGF5U2V0dGluZ3MuaGVhZGluZ1t0aGlzLml0ZW1JbnN0YW5jZUtleV0gPSB0aGlzLmRhc2hib2FyZEl0ZW1UeXBlLmhlYWRpbmdWYWx1ZTtcbiAgICAgICAgdGhpcy5kYXNoYm9hcmRJdGVtVHlwZS5fZWRpdGluZyA9IGZhbHNlO1xuICAgIH1cblxuICAgIHB1YmxpYyBhc3luYyBzZXR1cE5ldHdvcmtDaGFydCgpIHtcbiAgICAgICAgY29uc3Qgbm9kZURhdGEgPSB0aGlzLmRhdGFzZXQuYWxsRGF0YTtcblxuICAgICAgICBjb25zdCBkYXRhc2V0Tm9kZXM6IGFueSA9IFtdO1xuICAgICAgICBjb25zdCBkYXRhc2V0RWRnZXM6IGFueSA9IFtdO1xuXG4gICAgICAgIG5vZGVEYXRhLmZvckVhY2goaXRlbSA9PiB7XG4gICAgICAgICAgICBjb25zdCBub2RlTGV2ZWxJdGVtOiBhbnkgPSB7fTtcbiAgICAgICAgICAgIGNvbnN0IG5vZGVJdGVtOiBhbnkgPSB7XG4gICAgICAgICAgICAgICAgaWQ6IGl0ZW1bdGhpcy5uZXR3b3JrRGF0YS5ub2RlSWRzXSxcbiAgICAgICAgICAgICAgICBsYWJlbDogaXRlbVt0aGlzLm5ldHdvcmtEYXRhLm5vZGVMYWJlbHNdLFxuICAgICAgICAgICAgICAgIGdyb3VwOiBpdGVtW3RoaXMubmV0d29ya0RhdGEubm9kZUdyb3Vwc11cbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGlmICh0aGlzLm5ldHdvcmtEYXRhLm5vZGVzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMubmV0d29ya0RhdGEubm9kZXNbbm9kZUl0ZW0uaWRdKSB7XG4gICAgICAgICAgICAgICAgICAgIG5vZGVJdGVtLnggPSB0aGlzLm5ldHdvcmtEYXRhLm5vZGVzW25vZGVJdGVtLmlkXS54O1xuICAgICAgICAgICAgICAgICAgICBub2RlSXRlbS55ID0gdGhpcy5uZXR3b3JrRGF0YS5ub2Rlc1tub2RlSXRlbS5pZF0ueTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0aGlzLm5ldHdvcmtEYXRhLm5vZGVMZXZlbE9wdGlvbnMgJiYgT2JqZWN0LmtleXModGhpcy5uZXR3b3JrRGF0YS5ub2RlTGV2ZWxPcHRpb25zKS5sZW5ndGggJiZcbiAgICAgICAgICAgICAgICB0aGlzLm5ldHdvcmtEYXRhLm5vZGVMZXZlbE9wdGlvbnNbbm9kZUl0ZW0uaWRdKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5uZXR3b3JrRGF0YS5ub2RlTGV2ZWxPcHRpb25zW25vZGVJdGVtLmlkXS5mb3JFYWNoKG9wdGlvbiA9PiB7XG4gICAgICAgICAgICAgICAgICAgIG5vZGVMZXZlbEl0ZW1bb3B0aW9uLmtleV0gPSBvcHRpb24udmFsdWU7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBkYXRhc2V0Tm9kZXMucHVzaChPYmplY3QuYXNzaWduKG5vZGVMZXZlbEl0ZW0sIG5vZGVJdGVtKSk7XG4gICAgICAgICAgICBpZiAoIXRoaXMubmV0d29ya0RhdGEuZWRnZURhdGFzZXRUaXRsZSkge1xuICAgICAgICAgICAgICAgIGRhdGFzZXRFZGdlcy5wdXNoKHtcbiAgICAgICAgICAgICAgICAgICAgZnJvbTogaXRlbVt0aGlzLm5ldHdvcmtEYXRhLmZyb21JZHNdLFxuICAgICAgICAgICAgICAgICAgICB0bzogaXRlbVt0aGlzLm5ldHdvcmtEYXRhLnRvSWRzXVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICBpZiAodGhpcy5uZXR3b3JrRGF0YS5lZGdlRGF0YXNldFRpdGxlKSB7XG4gICAgICAgICAgICBjb25zdCBkYXRhc2V0SW5zdGFuY2VTdW1tYXJ5ID0ge1xuICAgICAgICAgICAgICAgIGRhdGFzZXRJbnN0YW5jZUlkOiB0aGlzLm5ldHdvcmtEYXRhLmVkZ2VEYXRhc2V0SWQsXG4gICAgICAgICAgICAgICAgZGF0YXNvdXJjZUluc3RhbmNlS2V5OiB0aGlzLm5ldHdvcmtEYXRhLmVkZ2VEYXRhc291cmNlS2V5LFxuICAgICAgICAgICAgICAgIHRyYW5zZm9ybWF0aW9uSW5zdGFuY2VzOiBbXSxcbiAgICAgICAgICAgICAgICBwYXJhbWV0ZXJWYWx1ZXM6IHt9LFxuICAgICAgICAgICAgICAgIHBhcmFtZXRlcnM6IHt9XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBjb25zdCBlZGdlRGF0YXNldDogYW55ID0gYXdhaXQgdGhpcy5kYXRhc2V0U2VydmljZS5ldmFsdWF0ZURhdGFzZXQoXG4gICAgICAgICAgICAgICAgZGF0YXNldEluc3RhbmNlU3VtbWFyeSxcbiAgICAgICAgICAgICAgICAnMCcsXG4gICAgICAgICAgICAgICAgJzEwMDAwMDAwJ1xuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGVkZ2VEYXRhc2V0LmFsbERhdGEuZm9yRWFjaChpdGVtID0+IHtcbiAgICAgICAgICAgICAgICBkYXRhc2V0RWRnZXMucHVzaCh7XG4gICAgICAgICAgICAgICAgICAgIGZyb206IGl0ZW1bdGhpcy5uZXR3b3JrRGF0YS5mcm9tSWRzXSxcbiAgICAgICAgICAgICAgICAgICAgdG86IGl0ZW1bdGhpcy5uZXR3b3JrRGF0YS50b0lkc11cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgZGF0YXNldEVkZ2VzLmZvckVhY2goZWRnZSA9PiB7XG4gICAgICAgICAgICBjb25zdCBlZGdlT3B0aW9ucyA9IF8uZmluZCh0aGlzLm5ldHdvcmtEYXRhLmVkZ2VMZXZlbE9wdGlvbnMsIHtmcm9tOiBlZGdlLmZyb20sIHRvOiBlZGdlLnRvfSk7XG4gICAgICAgICAgICBpZiAoZWRnZU9wdGlvbnMgJiYgZWRnZU9wdGlvbnMub3B0aW9ucy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICBlZGdlT3B0aW9ucy5vcHRpb25zLmZvckVhY2gob3B0aW9uID0+IHtcbiAgICAgICAgICAgICAgICAgICAgZWRnZVtvcHRpb24ua2V5XSA9IG9wdGlvbi52YWx1ZTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gY3JlYXRlIGFuIGFycmF5IHdpdGggbm9kZXNcbiAgICAgICAgY29uc3Qgbm9kZXMgPSBuZXcgRGF0YVNldChkYXRhc2V0Tm9kZXMpO1xuXG4gICAgICAgIC8vIGNyZWF0ZSBhbiBhcnJheSB3aXRoIGVkZ2VzXG4gICAgICAgIGNvbnN0IGVkZ2VzID0gbmV3IERhdGFTZXQoZGF0YXNldEVkZ2VzKTtcblxuICAgICAgICAvLyBjcmVhdGUgYSBuZXR3b3JrXG4gICAgICAgIGNvbnN0IGNvbnRhaW5lciA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHRoaXMuaXRlbUluc3RhbmNlS2V5ICsgJ1ZJUycpO1xuICAgICAgICBjb25zdCBkYXRhID0ge1xuICAgICAgICAgICAgbm9kZXMsXG4gICAgICAgICAgICBlZGdlc1xuICAgICAgICB9O1xuICAgICAgICBjb25zdCBvcHRpb25zOiBhbnkgPSB7XG4gICAgICAgICAgICBub2Rlczoge1xuICAgICAgICAgICAgICAgIGZvbnQ6IHtcbiAgICAgICAgICAgICAgICAgICAgbXVsdGk6ICdodG1sJ1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBlZGdlczoge30sXG4gICAgICAgICAgICBncm91cHM6IHt9LFxuICAgICAgICAgICAgbGF5b3V0OiB7fVxuICAgICAgICB9O1xuXG4gICAgICAgIGNvbnN0IG1hcE9wdGlvblZhbHVlID0gKG9wdGlvbjogYW55LCBuZXR3b3JrVHlwZTogc3RyaW5nKSA9PiB7XG4gICAgICAgICAgICBpZiAob3B0aW9uICYmIE9iamVjdC5rZXlzKG9wdGlvbikubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgdHlwZSA9IHZpc05ldHdvcmtPcHRpb25zW25ldHdvcmtUeXBlXVtvcHRpb24ua2V5XS50eXBlO1xuICAgICAgICAgICAgICAgIGxldCB2YWx1ZSA9IG9wdGlvbi52YWx1ZTtcbiAgICAgICAgICAgICAgICBpZiAodHlwZSA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFsdWUgPSBOdW1iZXIodmFsdWUpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhbHVlID0gdmFsdWUgPT09ICd0cnVlJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgb3B0aW9uc1tuZXR3b3JrVHlwZV1bb3B0aW9uLmtleV0gPSB2YWx1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICBpZiAodGhpcy5uZXR3b3JrRGF0YS5ub2RlT3B0aW9ucykge1xuICAgICAgICAgICAgdGhpcy5uZXR3b3JrRGF0YS5ub2RlT3B0aW9ucy5mb3JFYWNoKG9wdGlvbiA9PiB7XG4gICAgICAgICAgICAgICAgbWFwT3B0aW9uVmFsdWUob3B0aW9uLCAnbm9kZXMnKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMubmV0d29ya0RhdGEuZWRnZU9wdGlvbnMpIHtcbiAgICAgICAgICAgIHRoaXMubmV0d29ya0RhdGEuZWRnZU9wdGlvbnMuZm9yRWFjaChvcHRpb24gPT4ge1xuICAgICAgICAgICAgICAgIG1hcE9wdGlvblZhbHVlKG9wdGlvbiwgJ2VkZ2VzJyk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLm5ldHdvcmtEYXRhLm5vZGVHcm91cE9wdGlvbnMgJiYgT2JqZWN0LmtleXModGhpcy5uZXR3b3JrRGF0YS5ub2RlR3JvdXBPcHRpb25zKS5sZW5ndGgpIHtcbiAgICAgICAgICAgIE9iamVjdC5rZXlzKHRoaXMubmV0d29ya0RhdGEubm9kZUdyb3VwT3B0aW9ucykuZm9yRWFjaChncm91cEtleSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5uZXR3b3JrRGF0YS5ub2RlR3JvdXBPcHRpb25zW2dyb3VwS2V5XS5vcHRpb25zLmZvckVhY2gob3B0aW9uID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFvcHRpb25zLmdyb3Vwc1tncm91cEtleV0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG9wdGlvbnMuZ3JvdXBzW2dyb3VwS2V5XSA9IHt9O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChvcHRpb24gJiYgT2JqZWN0LmtleXMob3B0aW9uKS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG9wdGlvbnMuZ3JvdXBzW2dyb3VwS2V5XVtvcHRpb24ua2V5XSA9IG9wdGlvbi52YWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBuZXR3b3JrID0gbmV3IE5ldHdvcmsoY29udGFpbmVyLCBkYXRhLCBvcHRpb25zKTtcbiAgICAgICAgdGhpcy5uZXR3b3JrRGF0YS5uZXR3b3JrID0gbmV0d29yaztcbiAgICB9XG5cbiAgICBwdWJsaWMgZXZhbHVhdGVUZXh0RGF0YSh0ZXh0RGF0YSkge1xuICAgICAgICBsZXQgZXZhbHVhdGVkVGV4dERhdGEgPSAnJztcbiAgICAgICAgY29uc3QgZWxlbWVudDogYW55ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgICAgIGVsZW1lbnQuaW5uZXJIVE1MID0gdGhpcy5iaW5kUGFyYW1ldGVyc0luU3RyaW5nKHRleHREYXRhKTtcblxuICAgICAgICBjb25zdCBkYXRhOiBhbnkgPSB7XG4gICAgICAgICAgICBkYXRhU2V0OiB0aGlzLmRhdGFzZXQuYWxsRGF0YVxuICAgICAgICB9O1xuICAgICAgICBfLmZvckVhY2godGhpcy5kYXRhc2V0LmFsbERhdGFbMF0gfHwgW10sICh2YWx1ZSwga2V5KSA9PiB7XG4gICAgICAgICAgICBkYXRhW2tleV0gPSB2YWx1ZTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgY29uc3QgS2luaWJpbmQgPSB3aW5kb3cuS2luaWJpbmQ7XG4gICAgICAgIEtpbmliaW5kLmNvbmZpZyA9IHtcbiAgICAgICAgICAgIHByZWZpeDogJ2QnLFxuICAgICAgICAgICAgdGVtcGxhdGVEZWxpbWl0ZXJzOiBbJ1tbJywgJ11dJ11cbiAgICAgICAgfTtcbiAgICAgICAgY29uc3QgYmluZCA9IG5ldyBLaW5pYmluZChlbGVtZW50LCBkYXRhKTtcbiAgICAgICAgY29uc3QgYm91bmRIVE1MID0gYmluZC5ib3VuZENvbnRleHQuZWxzWzBdLmlubmVySFRNTDtcbiAgICAgICAgZXZhbHVhdGVkVGV4dERhdGEgPSB0aGlzLnNhbml0aXplci5zYW5pdGl6ZSgxLCBib3VuZEhUTUwpO1xuICAgICAgICBlbGVtZW50LnJlbW92ZSgpO1xuICAgICAgICByZXR1cm4gZXZhbHVhdGVkVGV4dERhdGE7XG4gICAgfVxuXG4gICAgcHVibGljIGFzeW5jIHNldENoYXJ0RGF0YSgpIHtcbiAgICAgICAgaWYgKHRoaXMuZGFzaGJvYXJkSXRlbVR5cGUueEF4aXMgJiYgdGhpcy5kYXNoYm9hcmRJdGVtVHlwZS55QXhpcykge1xuICAgICAgICAgICAgbGV0IGRhdGFzZXREYXRhID0gdGhpcy5kYXRhc2V0LmFsbERhdGE7XG4gICAgICAgICAgICBpZiAodGhpcy5kYXNoYm9hcmRJdGVtVHlwZS5saW1pdCkge1xuICAgICAgICAgICAgICAgIGRhdGFzZXREYXRhID0gZGF0YXNldERhdGEuc2xpY2UoMCwgdGhpcy5kYXNoYm9hcmRJdGVtVHlwZS5saW1pdCk7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuZGFzaGJvYXJkSXRlbVR5cGUuY29tYmluZVJlbWFpbmluZyAmJiAhdGhpcy5kYXNoYm9hcmRJdGVtVHlwZS5zZXJpZXNDb2x1bW4pIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcmVtYWluaW5nRGF0YSA9IGF3YWl0IHRoaXMuZXZhbHVhdGVEYXRhc2V0KDEwMDAwMDAwLCAwKTtcblxuICAgICAgICAgICAgICAgICAgICBjb25zdCBjb21iaW5lZCA9IFtdO1xuICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHJlbWFpbmluZ0RhdGEuYWxsRGF0YS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGkgPiB0aGlzLmRhc2hib2FyZEl0ZW1UeXBlLmxpbWl0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29tYmluZWQucHVzaChyZW1haW5pbmdEYXRhLmFsbERhdGFbaV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcHVzaE9iamVjdCA9IHt9O1xuICAgICAgICAgICAgICAgICAgICBwdXNoT2JqZWN0W3RoaXMuZGFzaGJvYXJkSXRlbVR5cGUueEF4aXNdID0gdGhpcy5kYXNoYm9hcmRJdGVtVHlwZS5jb21iaW5lUmVtYWluZ2luZ0xhYmVsIHx8ICdSZW1haW5pbmcnO1xuICAgICAgICAgICAgICAgICAgICBwdXNoT2JqZWN0W3RoaXMuZGFzaGJvYXJkSXRlbVR5cGUueUF4aXNdID0gXy5zdW1CeShjb21iaW5lZCwgcmVtYWluaW5nSXRlbSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gTnVtYmVyKHJlbWFpbmluZ0l0ZW1bdGhpcy5kYXNoYm9hcmRJdGVtVHlwZS55QXhpc10pO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgZGF0YXNldERhdGEucHVzaChwdXNoT2JqZWN0KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGxldCBkYXRhOiBhbnk7XG5cbiAgICAgICAgICAgIGlmICghdGhpcy5kYXNoYm9hcmRJdGVtVHlwZS5zZXJpZXNDb2x1bW4pIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5kYXNoYm9hcmRJdGVtVHlwZS50eXBlICE9PSAncGllJyAmJiB0aGlzLmRhc2hib2FyZEl0ZW1UeXBlLnR5cGUgIT09ICdkb3VnaG51dCcpIHtcbiAgICAgICAgICAgICAgICAgICAgZGF0YSA9IF8ubWFwKGRhdGFzZXREYXRhLCBpdGVtID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB7eDogaXRlbVt0aGlzLmRhc2hib2FyZEl0ZW1UeXBlLnhBeGlzXSwgeTogaXRlbVt0aGlzLmRhc2hib2FyZEl0ZW1UeXBlLnlBeGlzXX07XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGRhdGEgPSBfLm1hcChkYXRhc2V0RGF0YSwgaXRlbSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gaXRlbVt0aGlzLmRhc2hib2FyZEl0ZW1UeXBlLnlBeGlzXTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy5jaGFydERhdGEgPSBbXG4gICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEsXG4gICAgICAgICAgICAgICAgICAgICAgICBsYWJlbDogXy5maW5kKHRoaXMuZmlsdGVyRmllbGRzLCB7bmFtZTogdGhpcy5kYXNoYm9hcmRJdGVtVHlwZS54QXhpc30pLnRpdGxlLFxuICAgICAgICAgICAgICAgICAgICAgICAgZmlsbDogISF0aGlzLmRhc2hib2FyZEl0ZW1UeXBlLmZpbGwsXG4gICAgICAgICAgICAgICAgICAgICAgICBib3JkZXJDb2xvcjogKHRoaXMuZGFzaGJvYXJkSXRlbVR5cGUudHlwZSA9PT0gJ3BpZScgfHwgdGhpcy5kYXNoYm9hcmRJdGVtVHlwZS50eXBlID09PSAnZG91Z2hudXQnKSA/IGNocm9tYSgnd2hpdGUnKS5hbHBoYSgwLjIpLmhleCgpIDogdGhpcy5kYXNoYm9hcmRJdGVtVHlwZS5ib3JkZXJDb2xvcixcbiAgICAgICAgICAgICAgICAgICAgICAgIGJhY2tncm91bmRDb2xvcjogdGhpcy5kYXNoYm9hcmRJdGVtVHlwZS50eXBlID09PSAnbGluZScgP1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIChBcnJheS5pc0FycmF5KHRoaXMuZGFzaGJvYXJkSXRlbVR5cGUuYm9yZGVyQ29sb3IpID8gXy5tYXAodGhpcy5kYXNoYm9hcmRJdGVtVHlwZS5ib3JkZXJDb2xvciwgY29sb3VyID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGNocm9tYShjb2xvdXIgfHwgJ2JsYWNrJykuYWxwaGEoMC41KS5oZXgoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KSA6IGNocm9tYSh0aGlzLmRhc2hib2FyZEl0ZW1UeXBlLmJvcmRlckNvbG9yIHx8ICdibGFjaycpLmFscGhhKDAuNSkuaGV4KCkpIDogdGhpcy5kYXNoYm9hcmRJdGVtVHlwZS5iYWNrZ3JvdW5kQ29sb3IsXG4gICAgICAgICAgICAgICAgICAgICAgICB0ZW5zaW9uOiAwLjIsXG4gICAgICAgICAgICAgICAgICAgICAgICBwb2ludEJhY2tncm91bmRDb2xvcjogdGhpcy5kYXNoYm9hcmRJdGVtVHlwZS5ib3JkZXJDb2xvciA/IHRoaXMuZGFzaGJvYXJkSXRlbVR5cGUuYm9yZGVyQ29sb3JbMF0gOiBudWxsLFxuICAgICAgICAgICAgICAgICAgICAgICAgcG9pbnRCb3JkZXJDb2xvcjogdGhpcy5kYXNoYm9hcmRJdGVtVHlwZS5ib3JkZXJDb2xvciA/IHRoaXMuZGFzaGJvYXJkSXRlbVR5cGUuYm9yZGVyQ29sb3JbMF0gOiBudWxsXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBdO1xuICAgICAgICAgICAgICAgIHRoaXMuZGFzaGJvYXJkSXRlbVR5cGUubGFiZWxzID0gXy5tYXAoZGF0YXNldERhdGEsIGl0ZW0gPT4ge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gaXRlbVt0aGlzLmRhc2hib2FyZEl0ZW1UeXBlLnhBeGlzXTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc3QgY2hhcnREYXRhID0gW107XG4gICAgICAgICAgICAgICAgY29uc3Qgc2VyaWVzID0gXy51bmlxKF8ubWFwKGRhdGFzZXREYXRhLCB0aGlzLmRhc2hib2FyZEl0ZW1UeXBlLnNlcmllc0NvbHVtbikpO1xuICAgICAgICAgICAgICAgIHNlcmllcy5mb3JFYWNoKCh2YWx1ZSwgaW5kZXgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgc2VyaWVzUmVzdWx0cyA9IF8uZmlsdGVyKGRhdGFzZXREYXRhLCBhbGxEYXRhID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBhbGxEYXRhW3RoaXMuZGFzaGJvYXJkSXRlbVR5cGUuc2VyaWVzQ29sdW1uXSA9PT0gdmFsdWU7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgICAgIGNoYXJ0RGF0YS5wdXNoKHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRhdGE6IF8ubWFwKHNlcmllc1Jlc3VsdHMsIGl0ZW0gPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB7eDogaXRlbVt0aGlzLmRhc2hib2FyZEl0ZW1UeXBlLnhBeGlzXSwgeTogaXRlbVt0aGlzLmRhc2hib2FyZEl0ZW1UeXBlLnlBeGlzXX07XG4gICAgICAgICAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVsOiB2YWx1ZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGZpbGw6ICEhdGhpcy5kYXNoYm9hcmRJdGVtVHlwZS5maWxsLFxuICAgICAgICAgICAgICAgICAgICAgICAgYm9yZGVyQ29sb3I6IHRoaXMuZGFzaGJvYXJkSXRlbVR5cGUuYm9yZGVyQ29sb3IsXG4gICAgICAgICAgICAgICAgICAgICAgICBiYWNrZ3JvdW5kQ29sb3I6IHRoaXMuZGFzaGJvYXJkSXRlbVR5cGUudHlwZSA9PT0gJ2xpbmUnID9cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoQXJyYXkuaXNBcnJheSh0aGlzLmRhc2hib2FyZEl0ZW1UeXBlLmJvcmRlckNvbG9yKSA/IF8ubWFwKHRoaXMuZGFzaGJvYXJkSXRlbVR5cGUuYm9yZGVyQ29sb3IsIGNvbG91ciA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBjaHJvbWEoY29sb3VyIHx8ICdibGFjaycpLmFscGhhKDAuNSkuaGV4KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSkgOiBjaHJvbWEodGhpcy5kYXNoYm9hcmRJdGVtVHlwZS5ib3JkZXJDb2xvciB8fCAnYmxhY2snKS5hbHBoYSgwLjUpLmhleCgpKSA6IHRoaXMuZGFzaGJvYXJkSXRlbVR5cGUuYmFja2dyb3VuZENvbG9yW2luZGV4XSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHRlbnNpb246IDAuMixcbiAgICAgICAgICAgICAgICAgICAgICAgIHBvaW50QmFja2dyb3VuZENvbG9yOiB0aGlzLmRhc2hib2FyZEl0ZW1UeXBlLmJvcmRlckNvbG9yW2luZGV4XSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHBvaW50Qm9yZGVyQ29sb3I6IHRoaXMuZGFzaGJvYXJkSXRlbVR5cGUuYm9yZGVyQ29sb3JbaW5kZXhdXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHRoaXMuY2hhcnREYXRhID0gY2hhcnREYXRhO1xuICAgICAgICAgICAgICAgIHRoaXMuZGFzaGJvYXJkSXRlbVR5cGUubGFiZWxzID0gXy51bmlxKF8ubWFwKGRhdGFzZXREYXRhLCBpdGVtID0+IHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGl0ZW1bdGhpcy5kYXNoYm9hcmRJdGVtVHlwZS54QXhpc107XG4gICAgICAgICAgICAgICAgfSkpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodGhpcy5kYXNoYm9hcmRJdGVtVHlwZS50cmVuZExpbmUpIHtcbiAgICAgICAgICAgICAgICBsZXQgdHJlbmRMaW5lID0gW107XG4gICAgICAgICAgICAgICAgbGV0IHRyZW5kTGFiZWwgPSAnVHJlbmQnO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLmRhc2hib2FyZEl0ZW1UeXBlLnRyZW5kTGluZSA9PT0gJ2F2ZXJhZ2UnKSB7XG4gICAgICAgICAgICAgICAgICAgIHRyZW5kTGFiZWwgPSAnQXZlcmFnZSc7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHRyZW5kRGF0YSA9IFtdO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmNoYXJ0RGF0YS5mb3JFYWNoKGRhdGFJdGVtID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRyZW5kRGF0YS5wdXNoKF8ubWFwKGRhdGFJdGVtLmRhdGEsICd5JykpO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgYXZlcmFnZSA9IF8uZmxhdE1hcCh0cmVuZERhdGEpLnJlZHVjZSgocCwgYykgPT4gcCArIGMsIDApIC8gXy5mbGF0TWFwKHRyZW5kRGF0YSkubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICB0cmVuZExpbmUgPSBfLmZpbGwoXy5yYW5nZSgwLCBfLmZsYXRNYXAodHJlbmREYXRhKS5sZW5ndGgpLCBhdmVyYWdlLCAwLCBfLmZsYXRNYXAodHJlbmREYXRhKS5sZW5ndGgpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodGhpcy5kYXNoYm9hcmRJdGVtVHlwZS50cmVuZExpbmUgPT09ICdsb2dhcml0aG1pYycgfHxcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kYXNoYm9hcmRJdGVtVHlwZS50cmVuZExpbmUgPT09ICdsaW5lYXInIHx8XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGFzaGJvYXJkSXRlbVR5cGUudHJlbmRMaW5lID09PSAncG93ZXInIHx8XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGFzaGJvYXJkSXRlbVR5cGUudHJlbmRMaW5lID09PSAnZXhwb25lbnRpYWwnKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgY29uc3QgdHJlbmRMaW5lRGF0YSA9IF8ubWFwKHRoaXMuZGF0YXNldC5hbGxEYXRhLCAoaXRlbSwgaW5kZXgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB7eDogaW5kZXggKyAxLCB5OiBpdGVtW3RoaXMuZGFzaGJvYXJkSXRlbVR5cGUueUF4aXNdfTtcbiAgICAgICAgICAgICAgICAgICAgfSkuZmlsdGVyKCh7eCwgeX0pID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZW9mIHggPT09IHR5cGVvZiB5ICYmICAvLyBmaWx0ZXIgb3V0IG9uZSBzdHJpbmcgJiBvbmUgbnVtYmVyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgIWlzTmFOKHgpICYmICAgICAgICAgICAgICAvLyBmaWx0ZXIgb3V0IGBOYU5gXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgIWlzTmFOKHkpICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgTWF0aC5hYnMoeCkgIT09IEluZmluaXR5ICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgTWF0aC5hYnMoeSkgIT09IEluZmluaXR5XG4gICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICB9KS5tYXAoKHt4LCB5fSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFt4LCB5XTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgICAgY29uc3QgdHJlbmRMaW5lUmVzdWx0cyA9IHJlZ3Jlc3Npb25bdGhpcy5kYXNoYm9hcmRJdGVtVHlwZS50cmVuZExpbmVdKHRyZW5kTGluZURhdGEpO1xuICAgICAgICAgICAgICAgICAgICB0cmVuZExpbmUgPSB0cmVuZExpbmVSZXN1bHRzLnBvaW50cy5tYXAoKFt4LCB5XSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHk7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRyZW5kTGluZSA9IF8ubWFwKHRoaXMuZGF0YXNldC5hbGxEYXRhLCBpdGVtID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBpdGVtW3RoaXMuZGFzaGJvYXJkSXRlbVR5cGUudHJlbmRMaW5lXTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIHRyZW5kTGFiZWwgPSBfLmZpbmQodGhpcy5maWx0ZXJGaWVsZHMsIHtuYW1lOiB0aGlzLmRhc2hib2FyZEl0ZW1UeXBlLnRyZW5kTGluZX0pLnRpdGxlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMuY2hhcnREYXRhLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICB0eXBlOiAnbGluZScsXG4gICAgICAgICAgICAgICAgICAgIGRhdGE6IHRyZW5kTGluZSxcbiAgICAgICAgICAgICAgICAgICAgbGFiZWw6IHRyZW5kTGFiZWwsXG4gICAgICAgICAgICAgICAgICAgIGJvcmRlckNvbG9yOiB0aGlzLmRhc2hib2FyZEl0ZW1UeXBlLnRyZW5kTGluZUNvbG91cixcbiAgICAgICAgICAgICAgICAgICAgZmlsbDogZmFsc2UsXG4gICAgICAgICAgICAgICAgICAgIG9yZGVyOiAtMSxcbiAgICAgICAgICAgICAgICAgICAgdGVuc2lvbjogMC4xNSxcbiAgICAgICAgICAgICAgICAgICAgcG9pbnRCYWNrZ3JvdW5kQ29sb3I6IHRoaXMuZGFzaGJvYXJkSXRlbVR5cGUudHJlbmRMaW5lQ29sb3VyLFxuICAgICAgICAgICAgICAgICAgICBwb2ludEJvcmRlckNvbG9yOiB0aGlzLmRhc2hib2FyZEl0ZW1UeXBlLnRyZW5kTGluZUNvbG91clxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHVibGljIHVwZGF0ZUltYWdlRGF0YSgpIHtcbiAgICAgICAgdGhpcy5pbWFnZURhdGEuc291cmNlID0gdGhpcy5pbWFnZURhdGEuY29sdW1uID8gdGhpcy5kYXRhc2V0LmFsbERhdGFbMF1bdGhpcy5pbWFnZURhdGEuY29sdW1uXSA6IG51bGw7XG4gICAgfVxuXG4gICAgcHVibGljIHVwZGF0ZU1ldHJpY0RhdGFWYWx1ZXMoKSB7XG4gICAgICAgIGlmICh0aGlzLm1ldHJpYy5tYWluKSB7XG4gICAgICAgICAgICB0aGlzLm1ldHJpYy5tYWluVmFsdWUgPSBfLmlzTmFOKE51bWJlcih0aGlzLmRhdGFzZXQuYWxsRGF0YVswXVt0aGlzLm1ldHJpYy5tYWluXSkpID8gdGhpcy5kYXRhc2V0LmFsbERhdGFbMF1bdGhpcy5tZXRyaWMubWFpbl0gOiBOdW1iZXIodGhpcy5kYXRhc2V0LmFsbERhdGFbMF1bdGhpcy5tZXRyaWMubWFpbl0pO1xuICAgICAgICAgICAgdGhpcy5tZXRyaWMudGl0bGUgPSBfLnN0YXJ0Q2FzZSh0aGlzLm1ldHJpYy5tYWluKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLm1ldHJpYy5zdWJNZXRyaWMpIHtcbiAgICAgICAgICAgIHRoaXMubWV0cmljLnN1YlZhbHVlID0gTnVtYmVyKHRoaXMuZGF0YXNldC5hbGxEYXRhWzBdW3RoaXMubWV0cmljLnN1Yk1ldHJpY10pO1xuICAgICAgICAgICAgdGhpcy5tZXRyaWMuc3ViVGl0bGUgPSBfLnN0YXJ0Q2FzZSh0aGlzLm1ldHJpYy5zdWJNZXRyaWMpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMubWV0cmljLnNob3dTdWJDaGFuZ2UpIHtcbiAgICAgICAgICAgIHRoaXMubWV0cmljLmRpZmZlcmVuY2UgPSBNYXRoLmFicyh0aGlzLm1ldHJpYy5tYWluVmFsdWUgLSB0aGlzLm1ldHJpYy5zdWJWYWx1ZSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwdWJsaWMgY2FsbFRvQWN0aW9uTGluayhjdGEsIGRhdGFJdGVtPykge1xuICAgICAgICBsZXQgdXJsOiBzdHJpbmcgPSBudWxsO1xuXG4gICAgICAgIGlmIChjdGEudHlwZSA9PT0gJ2Rhc2hib2FyZCcpIHtcbiAgICAgICAgICAgIGNvbnN0IHBhcmFtcyA9IF8ucGlja0J5KGN0YS5wYXJhbWV0ZXJzLCAodmFsdWUsIGtleSkgPT4ge1xuICAgICAgICAgICAgICAgIHJldHVybiAhXy5zdGFydHNXaXRoKGtleSwgJ2N1c3RvbS0nKTtcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICBjb25zdCBkYXRhID0gZGF0YUl0ZW0gfHwgdGhpcy5kYXNoYm9hcmQubGF5b3V0U2V0dGluZ3MucGFyYW1ldGVycztcblxuICAgICAgICAgICAgT2JqZWN0LmtleXMocGFyYW1zKS5mb3JFYWNoKHBhcmFtS2V5ID0+IHtcbiAgICAgICAgICAgICAgICBsZXQgdmFsdWUgPSB0aGlzLmJpbmRQYXJhbWV0ZXJzSW5TdHJpbmcocGFyYW1zW3BhcmFtS2V5XSwgZGF0YSk7XG4gICAgICAgICAgICAgICAgLy8gQ2hlY2sgaWYgd2UgaGF2ZSBhbnkgY29sdW1uIGVnLiBbWyBdXSB2YWx1ZXMgbmVlZGluZyBtYXBwaW5nXG4gICAgICAgICAgICAgICAgdmFsdWUgPSB0aGlzLm1hcENvbHVtblRvVmFsdWUodmFsdWUsIGRhdGEpO1xuXG4gICAgICAgICAgICAgICAgcGFyYW1zW3BhcmFtS2V5XSA9IHZhbHVlO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBjb25zdCB1cmxQYXJhbXMgPSBuZXcgVVJMU2VhcmNoUGFyYW1zKHBhcmFtcykudG9TdHJpbmcoKTtcbiAgICAgICAgICAgIHVybCA9IGAvZGFzaGJvYXJkcy92aWV3LyR7Y3RhLnZhbHVlfSR7dGhpcy5hZG1pbiA/ICc/YT10cnVlJicgOiAnPyd9JHt1cmxQYXJhbXN9YDtcbiAgICAgICAgfSBlbHNlIGlmIChjdGEudHlwZSA9PT0gJ2N1c3RvbScpIHtcbiAgICAgICAgICAgIHVybCA9IGN0YS5saW5rO1xuXG4gICAgICAgICAgICBjb25zdCBkYXRhID0gZGF0YUl0ZW0gfHwgdGhpcy5kYXNoYm9hcmQubGF5b3V0U2V0dGluZ3MucGFyYW1ldGVycztcblxuICAgICAgICAgICAgdXJsID0gdGhpcy5iaW5kUGFyYW1ldGVyc0luU3RyaW5nKHVybCwgZGF0YSk7XG4gICAgICAgICAgICAvLyBDaGVjayBpZiB3ZSBoYXZlIGFueSBjb2x1bW4gZWcuIFtbIF1dIHZhbHVlcyBuZWVkaW5nIG1hcHBpbmdcbiAgICAgICAgICAgIHVybCA9IHRoaXMubWFwQ29sdW1uVG9WYWx1ZSh1cmwsIGRhdGEpO1xuICAgICAgICB9IGVsc2UgaWYgKGN0YS50eXBlID09PSAnZmVlZCcpIHtcbiAgICAgICAgICAgIHVybCA9IGAvZGFwLWRhdGEtZmVlZHMvJHtjdGEudmFsdWV9YDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh1cmwpIHtcbiAgICAgICAgICAgIGlmICghY3RhLndpbmRvd0xvY2F0aW9uIHx8IGN0YS53aW5kb3dMb2NhdGlvbiA9PT0gJ0VYSVNUSU5HJykge1xuICAgICAgICAgICAgICAgIHdpbmRvdy5sb2NhdGlvbi5ocmVmID0gdXJsO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zdCBhID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnYScpO1xuICAgICAgICAgICAgICAgIGEuaHJlZiA9IHVybDtcbiAgICAgICAgICAgICAgICBhLnNldEF0dHJpYnV0ZSgndGFyZ2V0JywgJ19ibGFuaycpO1xuICAgICAgICAgICAgICAgIGEuc2V0QXR0cmlidXRlKCdyZWwnLCAnbm9vcGVuZXIgbm9yZWZlcnJlcicpO1xuICAgICAgICAgICAgICAgIGEuY2xpY2soKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIHB1YmxpYyBiaW5kUGFyYW1ldGVyc0luU3RyaW5nKHNlYXJjaFN0cmluZywgZGF0YT8pIHtcbiAgICAgICAgaWYgKCFkYXRhKSB7XG4gICAgICAgICAgICBkYXRhID0gdGhpcy5kYXNoYm9hcmQubGF5b3V0U2V0dGluZ3MucGFyYW1ldGVycztcbiAgICAgICAgfVxuICAgICAgICBpZiAoc2VhcmNoU3RyaW5nKSB7XG4gICAgICAgICAgICBjb25zdCBtYXRjaGVzID0gc2VhcmNoU3RyaW5nLm1hdGNoKC9cXHtcXHsoLio/KVxcfVxcfS9nKSB8fCBbXTtcbiAgICAgICAgICAgIG1hdGNoZXMuZm9yRWFjaChleHAgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IGV4cFZhbHVlID0gZXhwLnJlcGxhY2UoJ3t7JywgJycpLnJlcGxhY2UoJ319JywgJycpO1xuICAgICAgICAgICAgICAgIGNvbnN0IHBhcmFtZXRlciA9IGRhdGEgPyBkYXRhW2V4cFZhbHVlXSA6IG51bGw7XG4gICAgICAgICAgICAgICAgaWYgKHBhcmFtZXRlcikge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCB2YWx1ZSA9IF8uaXNQbGFpbk9iamVjdChwYXJhbWV0ZXIpID8gcGFyYW1ldGVyLnZhbHVlIDogcGFyYW1ldGVyO1xuICAgICAgICAgICAgICAgICAgICBzZWFyY2hTdHJpbmcgPSBzZWFyY2hTdHJpbmcucmVwbGFjZShleHAsIHZhbHVlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBzZWFyY2hTdHJpbmc7XG4gICAgfVxuXG4gICAgcHVibGljIGluY3JlYXNlT2Zmc2V0KCkge1xuICAgICAgICB0aGlzLnBhZ2UgPSB0aGlzLnBhZ2UgKyAxO1xuICAgICAgICB0aGlzLm9mZnNldCA9ICh0aGlzLmxpbWl0ICogdGhpcy5wYWdlKSAtIHRoaXMubGltaXQ7XG4gICAgICAgIHRoaXMuZXZhbHVhdGUoKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgZGVjcmVhc2VPZmZzZXQoKSB7XG4gICAgICAgIHRoaXMucGFnZSA9IHRoaXMucGFnZSA8PSAxID8gMSA6IHRoaXMucGFnZSAtIDE7XG4gICAgICAgIHRoaXMub2Zmc2V0ID0gKHRoaXMubGltaXQgKiB0aGlzLnBhZ2UpIC0gdGhpcy5saW1pdDtcbiAgICAgICAgdGhpcy5ldmFsdWF0ZSgpO1xuICAgIH1cblxuICAgIHB1YmxpYyBwYWdlU2l6ZUNoYW5nZSh2YWx1ZSkge1xuICAgICAgICB0aGlzLmxpbWl0ID0gdmFsdWU7XG5cbiAgICAgICAgLy8gSWYgd2UgY2hhbmdlIHRoZSB0YWJsZSBsaW1pdCAtIHdlIGFsc28gd2FudCB0byBzYXZlIHRoZSBkYXNoYm9hcmQgYXV0b21hdGljYWxseSB0byBrZWVwIHRoZSBjaGFuZ2VzXG4gICAgICAgIHRoaXMudGFidWxhci5saW1pdCA9IHRoaXMubGltaXQ7XG4gICAgICAgIHRoaXMuZGFzaGJvYXJkU2VydmljZS5zYXZlRGFzaGJvYXJkKHRoaXMuZGFzaGJvYXJkKTtcblxuICAgICAgICB0aGlzLmV2YWx1YXRlKHRydWUpO1xuICAgIH1cblxuICAgIHB1YmxpYyBzb3J0SGVhZGVyKGNvbHVtbk9iamVjdCkge1xuICAgICAgICBjb25zdCBjb2x1bW4gPSBjb2x1bW5PYmplY3QubmFtZTtcbiAgICAgICAgbGV0IGRpcmVjdGlvbiA9ICcnO1xuXG4gICAgICAgIGNvbnN0IGV4aXN0aW5nTXVsdGlTb3J0ID0gXy5maW5kKHRoaXMuZGFzaGJvYXJkRGF0YXNldEluc3RhbmNlLnRyYW5zZm9ybWF0aW9uSW5zdGFuY2VzLCB7dHlwZTogJ211bHRpc29ydCd9KTtcblxuICAgICAgICBsZXQgZXhpc3RpbmdDb2x1bW5JbmRleCA9IC0xO1xuICAgICAgICBpZiAoZXhpc3RpbmdNdWx0aVNvcnQpIHtcbiAgICAgICAgICAgIGV4aXN0aW5nQ29sdW1uSW5kZXggPSBfLmZpbmRJbmRleChleGlzdGluZ011bHRpU29ydC5jb25maWcuc29ydHMsIHtmaWVsZE5hbWU6IGNvbHVtbn0pO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFleGlzdGluZ011bHRpU29ydCB8fCBleGlzdGluZ0NvbHVtbkluZGV4ID09PSAtMSkge1xuICAgICAgICAgICAgZGlyZWN0aW9uID0gJ2FzYyc7XG4gICAgICAgIH0gZWxzZSBpZiAoZXhpc3RpbmdDb2x1bW5JbmRleCA+PSAwICYmIGV4aXN0aW5nTXVsdGlTb3J0LmNvbmZpZy5zb3J0c1tleGlzdGluZ0NvbHVtbkluZGV4XS5kaXJlY3Rpb24gPT09ICdhc2MnKSB7XG4gICAgICAgICAgICBkaXJlY3Rpb24gPSAnZGVzYyc7XG4gICAgICAgIH0gZWxzZSBpZiAoZXhpc3RpbmdDb2x1bW5JbmRleCA+PSAwICYmIGV4aXN0aW5nTXVsdGlTb3J0LmNvbmZpZy5zb3J0c1tleGlzdGluZ0NvbHVtbkluZGV4XS5kaXJlY3Rpb24gPT09ICdkZXNjJykge1xuICAgICAgICAgICAgZGlyZWN0aW9uID0gJyc7XG4gICAgICAgIH0gZWxzZSBpZiAoZXhpc3RpbmdDb2x1bW5JbmRleCA+PSAwICYmICFleGlzdGluZ011bHRpU29ydC5jb25maWcuc29ydHNbZXhpc3RpbmdDb2x1bW5JbmRleF0uZGlyZWN0aW9uKSB7XG4gICAgICAgICAgICBkaXJlY3Rpb24gPSAnYXNjJztcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbHVtbk9iamVjdC5kaXJlY3Rpb24gPSBkaXJlY3Rpb247XG5cbiAgICAgICAgaWYgKGV4aXN0aW5nTXVsdGlTb3J0KSB7XG4gICAgICAgICAgICBjb25zdCBleGlzdGluZ0luZGV4ID0gXy5maW5kSW5kZXgoZXhpc3RpbmdNdWx0aVNvcnQuY29uZmlnLnNvcnRzLCB7ZmllbGROYW1lOiBjb2x1bW59KTtcbiAgICAgICAgICAgIGlmIChkaXJlY3Rpb24pIHtcbiAgICAgICAgICAgICAgICBpZiAoZXhpc3RpbmdJbmRleCA+IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgIGV4aXN0aW5nTXVsdGlTb3J0LmNvbmZpZy5zb3J0c1tleGlzdGluZ0luZGV4XSA9IHtmaWVsZE5hbWU6IGNvbHVtbiwgZGlyZWN0aW9ufTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBleGlzdGluZ011bHRpU29ydC5jb25maWcuc29ydHMucHVzaCh7ZmllbGROYW1lOiBjb2x1bW4sIGRpcmVjdGlvbn0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgZXhpc3RpbmdNdWx0aVNvcnQuY29uZmlnLnNvcnRzLnNwbGljZShleGlzdGluZ0luZGV4LCAxKTtcbiAgICAgICAgICAgICAgICBpZiAoIWV4aXN0aW5nTXVsdGlTb3J0LmNvbmZpZy5zb3J0cy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgXy5yZW1vdmUodGhpcy5kYXNoYm9hcmREYXRhc2V0SW5zdGFuY2UudHJhbnNmb3JtYXRpb25JbnN0YW5jZXMsIHt0eXBlOiAnbXVsdGlzb3J0J30pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmIChkaXJlY3Rpb24pIHtcbiAgICAgICAgICAgICAgICB0aGlzLmRhc2hib2FyZERhdGFzZXRJbnN0YW5jZS50cmFuc2Zvcm1hdGlvbkluc3RhbmNlcy5wdXNoKFxuICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiAnbXVsdGlzb3J0JyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbmZpZzoge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNvcnRzOiBbe2ZpZWxkTmFtZTogY29sdW1uLCBkaXJlY3Rpb259XVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuZXZhbHVhdGUodHJ1ZSk7XG4gICAgfVxuXG4gICAgcHVibGljIGNoYW5nZURhdGVUeXBlKGV2ZW50LCBwYXJhbWV0ZXIsIHZhbHVlKSB7XG4gICAgICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICBwYXJhbWV0ZXIuX2RhdGVUeXBlID0gdmFsdWU7XG4gICAgICAgIHRoaXMucmVsb2FkV2lkZ2V0KCk7XG4gICAgfVxuXG4gICAgcHVibGljIHVwZGF0ZVBlcmlvZFZhbHVlKHZhbHVlLCBwZXJpb2QsIHBhcmFtZXRlcikge1xuICAgICAgICBwYXJhbWV0ZXIudmFsdWUgPSBgJHt2YWx1ZX1fJHtwZXJpb2R9X0FHT2A7XG4gICAgICAgIHRoaXMucmVsb2FkV2lkZ2V0KCk7XG4gICAgfVxuXG4gICAgcHVibGljIGJvb2xlYW5VcGRhdGUoZXZlbnQsIHBhcmFtZXRlcikge1xuICAgICAgICBwYXJhbWV0ZXIudmFsdWUgPSBldmVudC5jaGVja2VkO1xuICAgICAgICB0aGlzLnJlbG9hZFdpZGdldCgpO1xuICAgIH1cblxuICAgIHB1YmxpYyByZWxvYWRXaWRnZXQoKSB7XG4gICAgICAgIGNvbnN0IHBhcmFtZXRlclZhbHVlczogYW55ID0ge307XG4gICAgICAgIF8uZm9yRWFjaCh0aGlzLmdlbmVyYWwud2lkZ2V0UGFyYW1ldGVycywgcGFyYW0gPT4ge1xuICAgICAgICAgICAgcGFyYW1ldGVyVmFsdWVzW3BhcmFtLm5hbWVdID0gcGFyYW0udmFsdWU7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHRoaXMuZXZhbHVhdGUoKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIG1hcENvbHVtblRvVmFsdWUoc2VhcmNoU3RyaW5nLCBkYXRhKSB7XG4gICAgICAgIGlmIChzZWFyY2hTdHJpbmcpIHtcbiAgICAgICAgICAgIGNvbnN0IG1hdGNoZXMgPSBzZWFyY2hTdHJpbmcubWF0Y2goL1xcW1xcWyguKj8pXFxdXFxdL2cpIHx8IFtdO1xuICAgICAgICAgICAgbWF0Y2hlcy5mb3JFYWNoKGV4cCA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgZXhwVmFsdWUgPSBleHAucmVwbGFjZSgnW1snLCAnJykucmVwbGFjZSgnXV0nLCAnJyk7XG4gICAgICAgICAgICAgICAgbGV0IHZhbHVlID0gZGF0YSA/IGRhdGFbZXhwVmFsdWVdIDogbnVsbDtcbiAgICAgICAgICAgICAgICBpZiAodmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFsdWUgPSBfLmlzUGxhaW5PYmplY3QodmFsdWUpID8gdmFsdWUuaW5pdGlhbFZhbHVlIDogdmFsdWU7XG4gICAgICAgICAgICAgICAgICAgIHNlYXJjaFN0cmluZyA9IHNlYXJjaFN0cmluZy5yZXBsYWNlKGV4cCwgdmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHNlYXJjaFN0cmluZztcbiAgICB9XG5cbiAgICBwcml2YXRlIGV2YWx1YXRlKHJlc2V0UGFnZXI/KSB7XG4gICAgICAgIGlmIChyZXNldFBhZ2VyKSB7XG4gICAgICAgICAgICB0aGlzLnJlc2V0UGFnZXIoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGl0ZW1FbGVtZW50ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQodGhpcy5pdGVtSW5zdGFuY2VLZXkpO1xuICAgICAgICBpZiAoaXRlbUVsZW1lbnQpIHtcbiAgICAgICAgICAgIGNvbnN0IHBhcmVudEVsZW1lbnQgPSBpdGVtRWxlbWVudC5jbG9zZXN0KCcuZ3JpZC1zdGFjay1pdGVtJyk7XG4gICAgICAgICAgICBwYXJlbnRFbGVtZW50LmNsYXNzTGlzdC5yZW1vdmUoJ2l0ZW0tZGlzYWJsZWQnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLmdyaWQgJiYgXy5pc0Z1bmN0aW9uKHRoaXMuZ3JpZC5tYWtlRWxlbWVudCkpIHtcbiAgICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuZ3JpZC5tYWtlRWxlbWVudChpdGVtRWxlbWVudCk7XG4gICAgICAgICAgICB9LCAwKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMubG9hZGluZ0l0ZW0gPSB0cnVlO1xuICAgICAgICB0aGlzLmhpZGRlbkNvbHVtbnMgPSB7fTtcblxuICAgICAgICByZXR1cm4gdGhpcy5ldmFsdWF0ZURhdGFzZXQoKS50aGVuKGRhdGEgPT4ge1xuICAgICAgICAgICAgaWYgKE9iamVjdC5rZXlzKHRoaXMudGFibGVDZWxscykubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgT2JqZWN0LmtleXModGhpcy50YWJsZUNlbGxzKS5mb3JFYWNoKHRhYmxlQ2VsbCA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0YWJsZUNlbGwgIT09ICdjb2x1bW4nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkYXRhLmFsbERhdGEubWFwKChpdGVtLCBpbmRleCkgPT4ge1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFfLmlzVW5kZWZpbmVkKGl0ZW1bdGFibGVDZWxsXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY2VsbERhdGEgPSB0aGlzLnRhYmxlQ2VsbHNbdGFibGVDZWxsXS5kYXRhO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKHRoaXMudGFibGVDZWxsc1t0YWJsZUNlbGxdLnR5cGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ251bWJlcic6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY2VsbE51bWJlciA9IHBhcnNlRmxvYXQoU3RyaW5nKGl0ZW1bdGFibGVDZWxsXSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW1bdGFibGVDZWxsXSA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2VsbFZhbHVlOiBjZWxsTnVtYmVyLnRvRml4ZWQoY2VsbERhdGEuZGVjaW1hbCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluaXRpYWxWYWx1ZTogaXRlbVt0YWJsZUNlbGxdXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ2N1cnJlbmN5JzpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXQgY2VsbEN1cnJlbmN5OiBhbnkgPSBwYXJzZUZsb2F0KFN0cmluZyhpdGVtW3RhYmxlQ2VsbF0pKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjZWxsRGF0YS50aG91c2FuZHNTZXBhcmF0b3IgJiYgKGNlbGxEYXRhLmN1cnJlbmN5ICYmIGNlbGxEYXRhLmN1cnJlbmN5LnZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjZWxsQ3VycmVuY3kgPSBjZWxsQ3VycmVuY3kudG9Mb2NhbGVTdHJpbmcoJ2VuLUdCJywge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3R5bGU6ICdjdXJyZW5jeScsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW5jeTogY2VsbERhdGEuY3VycmVuY3kudmFsdWUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW5pbXVtRnJhY3Rpb25EaWdpdHM6IGNlbGxEYXRhLmRlY2ltYWwgfHwgMFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjZWxsQ3VycmVuY3kgPSBjZWxsQ3VycmVuY3kudG9GaXhlZChjZWxsRGF0YS5kZWNpbWFsKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNlbGxEYXRhLnRob3VzYW5kc1NlcGFyYXRvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2VsbEN1cnJlbmN5ID0gTnVtYmVyKGNlbGxDdXJyZW5jeSkudG9Mb2NhbGVTdHJpbmcoJ2VuLUdCJywge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbmltdW1GcmFjdGlvbkRpZ2l0czogY2VsbERhdGEuZGVjaW1hbCB8fCAwXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoY2VsbERhdGEuY3VycmVuY3kgJiYgY2VsbERhdGEuY3VycmVuY3kudmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNlbGxDdXJyZW5jeSA9IGAke2NlbGxEYXRhLmN1cnJlbmN5LnN5bWJvbH0ke2NlbGxDdXJyZW5jeX1gO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbVt0YWJsZUNlbGxdID0ge2NlbGxWYWx1ZTogY2VsbEN1cnJlbmN5LCBpbml0aWFsVmFsdWU6IGl0ZW1bdGFibGVDZWxsXX07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdwZXJjZW50YWdlJzpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXQgY2VsbFBlcmNlbnQ6IGFueSA9IE51bWJlcihpdGVtW3RhYmxlQ2VsbF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGZvcm1hdHRlciA9IG5ldyBJbnRsLk51bWJlckZvcm1hdCgnZW4tR0InLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0eWxlOiAncGVyY2VudCcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbmltdW1GcmFjdGlvbkRpZ2l0czogY2VsbERhdGEuZGVjaW1hbCB8fCAwXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2VsbFBlcmNlbnQgPSBmb3JtYXR0ZXIuZm9ybWF0KGNlbGxQZXJjZW50KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghY2VsbERhdGEudGhvdXNhbmRzU2VwYXJhdG9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNlbGxQZXJjZW50ID0gY2VsbFBlcmNlbnQucmVwbGFjZSgnLCcsICcnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtW3RhYmxlQ2VsbF0gPSB7Y2VsbFZhbHVlOiBjZWxsUGVyY2VudCwgaW5pdGlhbFZhbHVlOiBpdGVtW3RhYmxlQ2VsbF19O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnZGF0ZXRpbWUnOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGRhdGVNb21lbnQgPSBtb21lbnQoaXRlbVt0YWJsZUNlbGxdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBkYXRlRm9ybWF0ID0gY2VsbERhdGEuZGF0ZUZvcm1hdCA9PT0gJ251bGwnID8gJycgOiBjZWxsRGF0YS5kYXRlRm9ybWF0O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHRpbWVGb3JtYXQgPSBjZWxsRGF0YS50aW1lRm9ybWF0ID09PSAnbnVsbCcgPyAnJyA6IGNlbGxEYXRhLnRpbWVGb3JtYXQ7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtW3RhYmxlQ2VsbF0gPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNlbGxWYWx1ZTogZGF0ZU1vbWVudC5mb3JtYXQoZGF0ZUZvcm1hdCArICcgJyArIHRpbWVGb3JtYXQpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbml0aWFsVmFsdWU6IGl0ZW1bdGFibGVDZWxsXVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdjb21wYXJpc29uJzpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjb21wYXJpc29uQ29sdW1uID0gdGhpcy50YWJsZUNlbGxzW3RhYmxlQ2VsbF0uZGF0YS5jb21wYXJpc29uQ29sdW1uO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGluaXRpYWxWYWx1ZSA9IF8uaXNQbGFpbk9iamVjdChpdGVtW3RhYmxlQ2VsbF0pID8gaXRlbVt0YWJsZUNlbGxdLmluaXRpYWxWYWx1ZSA6IGl0ZW1bdGFibGVDZWxsXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjb21wYXJpc29uVmFsdWUgPSBfLmlzUGxhaW5PYmplY3QoZGF0YS5hbGxEYXRhW2luZGV4XVtjb21wYXJpc29uQ29sdW1uXSkgPyBkYXRhLmFsbERhdGFbaW5kZXhdW2NvbXBhcmlzb25Db2x1bW5dLmluaXRpYWxWYWx1ZSA6IGRhdGEuYWxsRGF0YVtpbmRleF1bY29tcGFyaXNvbkNvbHVtbl07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGRpZmZlcmVuY2U6IGFueSA9IE51bWJlcihpbml0aWFsVmFsdWUpIC0gTnVtYmVyKGNvbXBhcmlzb25WYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGNlbGxWYWx1ZSA9IGA8ZGl2IGNsYXNzPVwiZmxleCBpdGVtcy1jZW50ZXIgc3BhY2UtYmV0d2VlblwiPjxzcGFuIGNsYXNzPVwiZm9udC1tZWRpdW1cIj4ke2luaXRpYWxWYWx1ZX08L3NwYW4+YDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZGlmZmVyZW5jZSA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjZWxsVmFsdWUgKz0gYDxzcGFuIGNsYXNzPVwibWwtMSB0ZXh0LWJsdWUtNTAwIGZvbnQtbWVkaXVtIHRleHQtbGdcIj4mIzYxOzwvc3Bhbj5gO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZGlmZmVyZW5jZSA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNlbGxEYXRhLmNvbXBhcmlzb25QZXJjZW50YWdlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjb21wYXJlRm9ybWF0dGVyID0gbmV3IEludGwuTnVtYmVyRm9ybWF0KCdlbi1HQicsIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHlsZTogJ3BlcmNlbnQnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbmltdW1GcmFjdGlvbkRpZ2l0czogY2VsbERhdGEuY29tcGFyaXNvbkRlY2ltYWxzIHx8IDBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZmVyZW5jZSA9IGNvbXBhcmVGb3JtYXR0ZXIuZm9ybWF0KGRpZmZlcmVuY2UgLyBjb21wYXJpc29uVmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNlbGxWYWx1ZSArPSBgPHNwYW4gY2xhc3M9XCJtbC0xIHRleHQtZ3JlZW4tNTAwIGZvbnQtbWVkaXVtIHRleHQtbGdcIj4mIzg1OTM7PC9zcGFuPjxzcGFuIGNsYXNzPVwidGV4dC1zbSB0ZXh0LWdyZWVuLTUwMFwiPiR7ZGlmZmVyZW5jZX08L3NwYW4+YDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRpZmZlcmVuY2UgPCAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjZWxsRGF0YS5jb21wYXJpc29uUGVyY2VudGFnZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY29tcGFyZUZvcm1hdHRlciA9IG5ldyBJbnRsLk51bWJlckZvcm1hdCgnZW4tR0InLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3R5bGU6ICdwZXJjZW50JyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW5pbXVtRnJhY3Rpb25EaWdpdHM6IGNlbGxEYXRhLmNvbXBhcmlzb25EZWNpbWFscyB8fCAwXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZlcmVuY2UgPSBjb21wYXJlRm9ybWF0dGVyLmZvcm1hdChkaWZmZXJlbmNlIC8gY29tcGFyaXNvblZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjZWxsVmFsdWUgKz0gYDxzcGFuIGNsYXNzPVwibWwtMSB0ZXh0LXJlZC01MDAgZm9udC1tZWRpdW0gdGV4dC1sZ1wiPiYjODU5NTs8L3NwYW4+PHNwYW4gY2xhc3M9XCJ0ZXh0LXNtIHRleHQtcmVkLTUwMFwiPiR7ZGlmZmVyZW5jZX08L3NwYW4+YDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2VsbFZhbHVlICs9IGA8c3BhbiBjbGFzcz1cIm1sLTIgdGV4dC14cyB0ZXh0LWdyYXktNDAwXCI+ZnJvbSAke2NvbXBhcmlzb25WYWx1ZX08L3NwYW4+PC9kaXY+YDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtW3RhYmxlQ2VsbF0gPSB7Y2VsbFZhbHVlLCBpbml0aWFsVmFsdWV9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnbGluayc6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGxpbmtWYWx1ZSA9IGNlbGxEYXRhLmN1c3RvbUxpbms7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGFuY2hvciA9ICcnO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjZWxsRGF0YS5saW5rVHlwZSA9PT0gJ2N1c3RvbScpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZGF0YUl0ZW0gPSBkYXRhLmFsbERhdGFbaW5kZXhdIHx8IHRoaXMuZGFzaGJvYXJkLmxheW91dFNldHRpbmdzLnBhcmFtZXRlcnM7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlua1ZhbHVlID0gdGhpcy5iaW5kUGFyYW1ldGVyc0luU3RyaW5nKGxpbmtWYWx1ZSwgZGF0YUl0ZW0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBDaGVjayBpZiB3ZSBoYXZlIGFueSBjb2x1bW4gZWcuIFtbIF1dIHZhbHVlcyBuZWVkaW5nIG1hcHBpbmdcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlua1ZhbHVlID0gdGhpcy5tYXBDb2x1bW5Ub1ZhbHVlKGxpbmtWYWx1ZSwgZGF0YUl0ZW0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbmNob3IgPSBgPGEgaHJlZj1cIiR7bGlua1ZhbHVlfVwiIHRhcmdldD1cIl9ibGFua1wiIGNsYXNzPVwidGV4dC1jdGEgaG92ZXI6dW5kZXJsaW5lIGZsZXggaXRlbXMtY2VudGVyXCI+JHtpdGVtW3RhYmxlQ2VsbF19PC9hPmA7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjZWxsRGF0YS5saW5rVHlwZSA9PT0gJ2Rhc2hib2FyZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcGFyYW1zID0ge307XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGRhc2hib2FyZExpbmsgPSBjZWxsRGF0YS5kYXNoYm9hcmRMaW5rO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBkYXRhSXRlbSA9IGRhdGEuYWxsRGF0YVtpbmRleF0gfHwgdGhpcy5kYXNoYm9hcmQubGF5b3V0U2V0dGluZ3MucGFyYW1ldGVycztcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBPYmplY3Qua2V5cyhjZWxsRGF0YS5kYXNoYm9hcmRMaW5rUGFyYW1zKS5mb3JFYWNoKHBhcmFtS2V5ID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCB2YWx1ZSA9IHRoaXMuYmluZFBhcmFtZXRlcnNJblN0cmluZyhjZWxsRGF0YS5kYXNoYm9hcmRMaW5rUGFyYW1zW3BhcmFtS2V5XSwgZGF0YUl0ZW0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQ2hlY2sgaWYgd2UgaGF2ZSBhbnkgY29sdW1uIGVnLiBbWyBdXSB2YWx1ZXMgbmVlZGluZyBtYXBwaW5nXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSA9IHRoaXMubWFwQ29sdW1uVG9WYWx1ZSh2YWx1ZSwgZGF0YUl0ZW0pO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXJhbXNbcGFyYW1LZXldID0gdmFsdWU7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHVybFBhcmFtcyA9IG5ldyBVUkxTZWFyY2hQYXJhbXMocGFyYW1zKS50b1N0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaW5rVmFsdWUgPSBgJHt0aGlzLnJvdXRlci51cmwuc3BsaXQoJy8nKVswXX0vZGFzaGJvYXJkcy92aWV3LyR7ZGFzaGJvYXJkTGluay52YWx1ZX0ke3RoaXMuYWRtaW4gPyAnP2E9dHJ1ZSYnIDogJz8nfSR7dXJsUGFyYW1zfWA7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFuY2hvciA9IGA8YSBocmVmPVwiJHtsaW5rVmFsdWV9XCIgY2xhc3M9XCJ0ZXh0LWN0YSBob3Zlcjp1bmRlcmxpbmUgZmxleCBpdGVtcy1jZW50ZXJcIj4ke2l0ZW1bdGFibGVDZWxsXX08L2E+YDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaW5rVmFsdWUgPSBsaW5rVmFsdWUuaW5jbHVkZXMoJ2h0dHAnKSA/IGxpbmtWYWx1ZSA6IGBodHRwOi8vJHtsaW5rVmFsdWV9YDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYW5jaG9yID0gYDxhIGhyZWY9XCIke2xpbmtWYWx1ZX1cIiB0YXJnZXQ9XCJfYmxhbmtcIiBjbGFzcz1cInRleHQtY3RhIGhvdmVyOnVuZGVybGluZSBmbGV4IGl0ZW1zLWNlbnRlclwiPiR7aXRlbVt0YWJsZUNlbGxdfTwvYT5gO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW1bdGFibGVDZWxsXSA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2VsbFZhbHVlOiBhbmNob3IsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluaXRpYWxWYWx1ZTogbGlua1ZhbHVlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ2N1c3RvbSc6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZWxlbWVudDogYW55ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgb3JpZ2luYWxWYWx1ZSA9IGl0ZW1bdGFibGVDZWxsXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50LmlubmVySFRNTCA9IHRoaXMuYmluZFBhcmFtZXRlcnNJblN0cmluZyhjZWxsRGF0YS5jdXN0b21UZXh0KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGtEYXRhOiBhbnkgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGFTZXQ6IGRhdGEuYWxsRGF0YVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXy5mb3JFYWNoKGRhdGEuYWxsRGF0YVtpbmRleF0gfHwgW10sICh2YWx1ZSwga2V5KSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGtEYXRhW2tleV0gPSB2YWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBLaW5pYmluZCA9IHdpbmRvdy5LaW5pYmluZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBLaW5pYmluZC5jb25maWcgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByZWZpeDogJ2QnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0ZW1wbGF0ZURlbGltaXRlcnM6IFsnW1snLCAnXV0nXVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgYmluZCA9IG5ldyBLaW5pYmluZChlbGVtZW50LCBrRGF0YSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgYm91bmRIVE1MID0gYmluZC5ib3VuZENvbnRleHQuZWxzWzBdLmlubmVySFRNTDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtW3RhYmxlQ2VsbF0gPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNlbGxWYWx1ZTogdGhpcy5zYW5pdGl6ZXIuc2FuaXRpemUoMSwgYm91bmRIVE1MKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5pdGlhbFZhbHVlOiBvcmlnaW5hbFZhbHVlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50LnJlbW92ZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnaGlkZSc6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5oaWRkZW5Db2x1bW5zW3RhYmxlQ2VsbF0gPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBpdGVtO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuZGF0YXNldCA9IGRhdGE7XG4gICAgICAgICAgICBjb25zdCByZXR1cm5lZERhdGFMZW5ndGggPSB0aGlzLmRhdGFzZXQuYWxsRGF0YS5sZW5ndGg7XG5cbiAgICAgICAgICAgIGNvbnN0IGV4aXN0aW5nTXVsdGlTb3J0ID0gXy5maW5kKHRoaXMuZGFzaGJvYXJkRGF0YXNldEluc3RhbmNlLnRyYW5zZm9ybWF0aW9uSW5zdGFuY2VzLCB7dHlwZTogJ211bHRpc29ydCd9KTtcblxuICAgICAgICAgICAgaWYgKGV4aXN0aW5nTXVsdGlTb3J0ICYmIGV4aXN0aW5nTXVsdGlTb3J0LmNvbmZpZy5zb3J0cy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICBleGlzdGluZ011bHRpU29ydC5jb25maWcuc29ydHMuZm9yRWFjaChzb3J0ID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgY29sdW1uID0gXy5maW5kKHRoaXMuZGF0YXNldC5jb2x1bW5zLCB7bmFtZTogc29ydC5maWVsZE5hbWV9KTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGNvbHVtbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29sdW1uLmRpcmVjdGlvbiA9IHNvcnQuZGlyZWN0aW9uO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuZmlsdGVyRmllbGRzID0gXy5tYXAodGhpcy5kYXRhc2V0LmNvbHVtbnMsIGNvbHVtbiA9PiB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgdGl0bGU6IGNvbHVtbi50aXRsZSxcbiAgICAgICAgICAgICAgICAgICAgbmFtZTogY29sdW1uLm5hbWVcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBpZiAodGhpcy5kYXNoYm9hcmQubGF5b3V0U2V0dGluZ3MubWV0cmljKSB7XG4gICAgICAgICAgICAgICAgdGhpcy51cGRhdGVNZXRyaWNEYXRhVmFsdWVzKCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0aGlzLmRhc2hib2FyZC5sYXlvdXRTZXR0aW5ncy5pbWFnZURhdGEpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZUltYWdlRGF0YSgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoT2JqZWN0LmtleXModGhpcy50ZXh0RGF0YSkubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgdGhpcy50ZXh0RGF0YS5zYWZlVGV4dERhdGEgPSB0aGlzLmV2YWx1YXRlVGV4dERhdGEodGhpcy50ZXh0RGF0YS52YWx1ZSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChPYmplY3Qua2V5cyh0aGlzLmdlbmVyYWwpLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZ2VuZXJhbC5ldmFsdWF0ZWROYW1lID0gdGhpcy5nZW5lcmFsLm5hbWUgPyB0aGlzLmV2YWx1YXRlVGV4dERhdGEodGhpcy5nZW5lcmFsLm5hbWUpIDogJyc7XG4gICAgICAgICAgICAgICAgdGhpcy5nZW5lcmFsLmV2YWx1YXRlZERlc2NyaXB0aW9uID0gdGhpcy5nZW5lcmFsLmRlc2NyaXB0aW9uID8gdGhpcy5ldmFsdWF0ZVRleHREYXRhKHRoaXMuZ2VuZXJhbC5kZXNjcmlwdGlvbikgOiAnJztcbiAgICAgICAgICAgICAgICB0aGlzLmdlbmVyYWwuZXZhbHVhdGVkRm9vdGVyID0gdGhpcy5nZW5lcmFsLmZvb3RlciA/IHRoaXMuZXZhbHVhdGVUZXh0RGF0YSh0aGlzLmdlbmVyYWwuZm9vdGVyKSA6ICcnO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5kYXNoYm9hcmRJdGVtVHlwZS50eXBlID09PSAnbmV0d29yaycpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXR1cE5ldHdvcmtDaGFydCgpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGNvbnN0IGVsZW1lbnQgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCh0aGlzLml0ZW1JbnN0YW5jZUtleSk7XG4gICAgICAgICAgICAgICAgZm9yIChjb25zdCBjaGlsZCBvZiBBcnJheS5mcm9tKGVsZW1lbnQgPyBlbGVtZW50LmNoaWxkcmVuIDogW10pIGFzIGFueVtdKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjaGlsZC5jbGFzc0xpc3QuY29udGFpbnMoJ2l0ZW0tY29udGFpbmVyJykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMud29yZENsb3VkLndpZHRoID0gY2hpbGQuY2xpZW50V2lkdGggLSA0MDtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMud29yZENsb3VkLmhlaWdodCA9IGNoaWxkLmNsaWVudEhlaWdodCAtIDQwO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChPYmplY3Qua2V5cyh0aGlzLndvcmRDbG91ZCkubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLndvcmRDbG91ZC5wb3B1bGF0aW9uTWV0aG9kID09PSAnU0lOR0xFJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgcm93RGF0YSA9IHRoaXMuZGF0YXNldC5hbGxEYXRhW3RoaXMud29yZENsb3VkLnJvd107XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocm93RGF0YSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHdvcmRzID0gXy53b3Jkcyhyb3dEYXRhW3RoaXMud29yZENsb3VkLmNvbHVtbl0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNvdW50ID0gXy5jb3VudEJ5KHdvcmRzLCBfLmlkZW50aXR5KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG1heCA9IF8ubWF4KF8udmFsdWVzKGNvdW50KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZm9udFNpemUgPSAoKHRoaXMud29yZENsb3VkLmhlaWdodCkgKiAodGhpcy53b3JkQ2xvdWQud2lkdGgpKSAvIDEwMDA7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLndvcmRDbG91ZC5kYXRhID0gXy5vcmRlckJ5KF8udW5pcSh3b3JkcykubWFwKHdvcmQgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4ge3RleHQ6IHdvcmQsIHZhbHVlOiAoKGNvdW50W3dvcmRdIC8gbWF4KSAqIF8ubWluKFtmb250U2l6ZSwgMTIwXSkpfTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KSwgWyd2YWx1ZSddLCBbJ2Rlc2MnXSkuc2xpY2UoMCwgMTAwKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0aGlzLndvcmRDbG91ZC5wb3B1bGF0aW9uTWV0aG9kID09PSAnV0hPTEUnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBtYXhGcmVxID0gXy5tYXhCeSh0aGlzLmRhdGFzZXQuYWxsRGF0YSwgaXRlbSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE51bWJlcihpdGVtW3RoaXMud29yZENsb3VkLmZyZXF1ZW5jeV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSlbdGhpcy53b3JkQ2xvdWQuZnJlcXVlbmN5XTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG1heFdvcmRXaWR0aDogbnVtYmVyID0gXy5tYXgoXy5tYXAodGhpcy5kYXRhc2V0LmFsbERhdGEsIGl0ZW0gPT5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtW3RoaXMud29yZENsb3VkLmNvbHVtbl0ubGVuZ3RoICogaXRlbVt0aGlzLndvcmRDbG91ZC5mcmVxdWVuY3ldIC8gbWF4RnJlcVxuICAgICAgICAgICAgICAgICAgICAgICAgKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBmb250U2l6ZSA9ICgodGhpcy53b3JkQ2xvdWQuaGVpZ2h0KSAqICh0aGlzLndvcmRDbG91ZC53aWR0aCkpIC8gMzAwMDtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMud29yZENsb3VkLmRhdGEgPSBfLm9yZGVyQnkodGhpcy5kYXRhc2V0LmFsbERhdGEubWFwKGl0ZW0gPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHRleHQgPSBpdGVtW3RoaXMud29yZENsb3VkLmNvbHVtbl07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgaXRlbUZyZXF1ZW5jeSA9IGl0ZW1bdGhpcy53b3JkQ2xvdWQuZnJlcXVlbmN5XTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRleHQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlOiAoKDggLyBtYXhXb3JkV2lkdGgpICogKE51bWJlcihpdGVtRnJlcXVlbmN5KSAvIE51bWJlcihtYXhGcmVxKSkgKiBfLm1pbihbZm9udFNpemUsIDQwMF0pKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICB9KSwgWyd2YWx1ZSddLCBbJ2Rlc2MnXSkuc2xpY2UoMCwgMTAwKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSwgNTApO1xuXG5cbiAgICAgICAgICAgIHRoaXMubG9hZGluZ0l0ZW0gPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMuY29uZmlndXJlQ2xhc3MgPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMuc2V0Q2hhcnREYXRhKCk7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLmRhc2hib2FyZC5hbGVydHNFbmFibGVkICYmICF0aGlzLmV4dGVybmFsKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuZGFzaGJvYXJkRGF0YXNldEluc3RhbmNlLmFsZXJ0cyAmJiB0aGlzLmRhc2hib2FyZERhdGFzZXRJbnN0YW5jZS5hbGVydHMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmRhc2hib2FyZC5sYXlvdXRTZXR0aW5ncy5wYXJhbWV0ZXJzICYmIE9iamVjdC5rZXlzKHRoaXMuZGFzaGJvYXJkLmxheW91dFNldHRpbmdzLnBhcmFtZXRlcnMpLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkodGhpcy5kYXNoYm9hcmREYXRhc2V0SW5zdGFuY2UucGFyYW1ldGVyVmFsdWVzKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZGFzaGJvYXJkRGF0YXNldEluc3RhbmNlLnBhcmFtZXRlclZhbHVlcyA9IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgXy5mb3JFYWNoKHRoaXMuZGFzaGJvYXJkLmxheW91dFNldHRpbmdzLnBhcmFtZXRlcnMsIHBhcmFtZXRlciA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5kYXNoYm9hcmREYXRhc2V0SW5zdGFuY2UucGFyYW1ldGVyVmFsdWVzW3BhcmFtZXRlci5uYW1lXSA9IHBhcmFtZXRlci52YWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGRhc2hib2FyZEluc3RhbmNlID0gXy5jbG9uZURlZXAodGhpcy5kYXNoYm9hcmREYXRhc2V0SW5zdGFuY2UpO1xuICAgICAgICAgICAgICAgICAgICBkYXNoYm9hcmRJbnN0YW5jZS5wYXJhbWV0ZXJWYWx1ZXMgPSB0aGlzLmdldE1hcHBlZFBhcmFtcyh0aGlzLmRhc2hib2FyZERhdGFzZXRJbnN0YW5jZSk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuYWxlcnRTZXJ2aWNlLnByb2Nlc3NBbGVydHNGb3JEYXNoYm9hcmREYXRhc2V0SW5zdGFuY2UoZGFzaGJvYXJkSW5zdGFuY2UpXG4gICAgICAgICAgICAgICAgICAgICAgICAudGhlbigocmVzOiBhbnkpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocmVzICYmIHJlcy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5hbGVydCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuYWxlcnREYXRhID0gcmVzO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXRlbUVsZW1lbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW1FbGVtZW50LmNsYXNzTGlzdC5hZGQoJ2FsZXJ0Jyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtRWxlbWVudC5wYXJlbnRFbGVtZW50LmNsYXNzTGlzdC5hZGQoJ2FsZXJ0Jyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJlc2V0QWxlcnREYXRhKGl0ZW1FbGVtZW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnJlc2V0QWxlcnREYXRhKGl0ZW1FbGVtZW50KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMucmVzZXRBbGVydERhdGEoaXRlbUVsZW1lbnQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgZXhpc3RpbmcgPSB0aGlzLmRhc2hib2FyZFNlcnZpY2UuZGFzaGJvYXJkSXRlbXMuZ2V0VmFsdWUoKTtcbiAgICAgICAgICAgIGV4aXN0aW5nW3RoaXMuaXRlbUluc3RhbmNlS2V5XSA9IHRydWU7XG4gICAgICAgICAgICB0aGlzLmRhc2hib2FyZFNlcnZpY2UuZGFzaGJvYXJkSXRlbXMubmV4dChleGlzdGluZyk7XG5cbiAgICAgICAgICAgIHRoaXMuZW5kT2ZSZXN1bHRzID0gcmV0dXJuZWREYXRhTGVuZ3RoIDwgdGhpcy5saW1pdDtcblxuICAgICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh0cnVlKTtcbiAgICAgICAgfSkuY2F0Y2goZXJyID0+IHtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRNYXBwZWRQYXJhbXMoZGFzaGJvYXJkRGF0YXNldEluc3RhbmNlKSB7XG4gICAgICAgIGNvbnN0IG1hcHBlZFBhcmFtcyA9IHt9O1xuICAgICAgICBfLmZvckVhY2goZGFzaGJvYXJkRGF0YXNldEluc3RhbmNlLnBhcmFtZXRlclZhbHVlcywgKHZhbHVlLCBrZXkpID0+IHtcbiAgICAgICAgICAgIGlmIChfLmlzU3RyaW5nKHZhbHVlKSAmJiB2YWx1ZS5pbmNsdWRlcygne3snKSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGdsb2JhbEtleSA9IHZhbHVlLnJlcGxhY2UoJ3t7JywgJycpLnJlcGxhY2UoJ319JywgJycpO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLmRhc2hib2FyZC5sYXlvdXRTZXR0aW5ncy5wYXJhbWV0ZXJzICYmIHRoaXMuZGFzaGJvYXJkLmxheW91dFNldHRpbmdzLnBhcmFtZXRlcnNbZ2xvYmFsS2V5XSkge1xuICAgICAgICAgICAgICAgICAgICBtYXBwZWRQYXJhbXNba2V5XSA9IHRoaXMuZGFzaGJvYXJkLmxheW91dFNldHRpbmdzLnBhcmFtZXRlcnNbZ2xvYmFsS2V5XS52YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIG1hcHBlZFBhcmFtc1trZXldID0gdmFsdWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBtYXBwZWRQYXJhbXM7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSByZXNldEFsZXJ0RGF0YShpdGVtRWxlbWVudCkge1xuICAgICAgICB0aGlzLmFsZXJ0ID0gZmFsc2U7XG4gICAgICAgIHRoaXMuYWxlcnREYXRhID0gW107XG4gICAgICAgIGlmIChpdGVtRWxlbWVudCkge1xuICAgICAgICAgICAgaXRlbUVsZW1lbnQuY2xhc3NMaXN0LnJlbW92ZSgnYWxlcnQnKTtcbiAgICAgICAgICAgIGl0ZW1FbGVtZW50LnBhcmVudEVsZW1lbnQuY2xhc3NMaXN0LnJlbW92ZSgnYWxlcnQnKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgcmVzZXRQYWdlcigpIHtcbiAgICAgICAgdGhpcy5vZmZzZXQgPSAwO1xuICAgICAgICB0aGlzLnBhZ2UgPSAxO1xuICAgIH1cblxuICAgIHByaXZhdGUgbWFwTGF5b3V0U2V0dGluZ3NUb0NvbXBvbmVudERhdGEoKSB7XG4gICAgICAgIF8uZm9yRWFjaCh0aGlzLmRhc2hib2FyZC5sYXlvdXRTZXR0aW5ncywgKGRhdGEsIGtleSkgPT4ge1xuICAgICAgICAgICAgaWYgKGtleSAhPT0gJ2dyaWQnKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgZGVmYXVsdFZhbHVlID0gXy5pc1BsYWluT2JqZWN0KHRoaXNba2V5XSkgPyB7fSA6IFtdO1xuICAgICAgICAgICAgICAgIHRoaXNba2V5XSA9IE9iamVjdC5rZXlzKGRhdGEpLmxlbmd0aCA/IGRhdGFbdGhpcy5pdGVtSW5zdGFuY2VLZXldIHx8IGRlZmF1bHRWYWx1ZSA6IGRlZmF1bHRWYWx1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSByZWxvYWRBbGVydChzYXZlID0gdHJ1ZSkge1xuICAgICAgICBjb25zdCB0aGlzRWwgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCh0aGlzLml0ZW1JbnN0YW5jZUtleSkuY2xvc2VzdCgnLmdyaWQtc3RhY2staXRlbScpO1xuICAgICAgICBjb25zdCBleGlzdGluZ0dyaWQgPSBfLmZpbmQodGhpcy5kYXNoYm9hcmQubGF5b3V0U2V0dGluZ3MuZ3JpZCwgZ3JpZCA9PiB7XG4gICAgICAgICAgICByZXR1cm4gZ3JpZC5jb250ZW50LmluY2x1ZGVzKGBpZD1cIiR7dGhpcy5pdGVtSW5zdGFuY2VLZXl9XCJgKTtcbiAgICAgICAgfSk7XG4gICAgICAgIGlmICh0aGlzRWwgJiYgZXhpc3RpbmdHcmlkKSB7XG4gICAgICAgICAgICB0aGlzLmdyaWQucmVtb3ZlV2lkZ2V0KHRoaXNFbCk7XG4gICAgICAgICAgICB0aGlzLmdyaWQuYWRkV2lkZ2V0KGV4aXN0aW5nR3JpZCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoc2F2ZSkge1xuICAgICAgICAgICAgdGhpcy5kYXNoYm9hcmRTZXJ2aWNlLnNhdmVEYXNoYm9hcmQodGhpcy5kYXNoYm9hcmQpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBldmFsdWF0ZURhdGFzZXQobGltaXQ/LCBvZmZzZXQ/KSB7XG4gICAgICAgIGNvbnN0IGRhdGFzZXRJbnN0YW5jZVN1bW1hcnkgPSB0aGlzLnByZXBhcmVEYXRhc2V0SW5zdGFuY2VTdW1tYXJ5Rm9yRXZhbHVhdGlvbigpO1xuXG4gICAgICAgIHRoaXMuaGlkZGVuQ29sdW1ucyA9IHt9O1xuXG4gICAgICAgIHRoaXMuZXh0ZXJuYWxFcnJvciA9IGZhbHNlO1xuICAgICAgICB0aGlzLnF1b3RhRXhjZWVkZWQgPSBudWxsO1xuXG4gICAgICAgIGlmICh0aGlzLmV4dGVybmFsKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5leHRlcm5hbFNlcnZpY2UuZXZhbHVhdGVEYXRhc2V0KFxuICAgICAgICAgICAgICAgIHRoaXMuZGFzaGJvYXJkLmlkLFxuICAgICAgICAgICAgICAgIHRoaXMuaXRlbUluc3RhbmNlS2V5LFxuICAgICAgICAgICAgICAgIGRhdGFzZXRJbnN0YW5jZVN1bW1hcnkucGFyYW1ldGVyVmFsdWVzLFxuICAgICAgICAgICAgICAgIFN0cmluZyhvZmZzZXQgfHwgdGhpcy5vZmZzZXQpLFxuICAgICAgICAgICAgICAgIFN0cmluZyhsaW1pdCB8fCB0aGlzLmxpbWl0KSxcbiAgICAgICAgICAgICAgICB0aGlzLnF1ZXJ5UGFyYW1zXG4gICAgICAgICAgICApLmNhdGNoKGUgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuZXh0ZXJuYWxFcnJvciA9IHRydWU7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmRhdGFzZXRTZXJ2aWNlLmV2YWx1YXRlRGF0YXNldChcbiAgICAgICAgICAgICAgICBkYXRhc2V0SW5zdGFuY2VTdW1tYXJ5LFxuICAgICAgICAgICAgICAgIFN0cmluZyhvZmZzZXQgfHwgdGhpcy5vZmZzZXQpLFxuICAgICAgICAgICAgICAgIFN0cmluZyhsaW1pdCB8fCB0aGlzLmxpbWl0KVxuICAgICAgICAgICAgKS5jYXRjaChlID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoZSAmJiBlLmVycm9yICYmIGUuZXJyb3IubWVzc2FnZSAmJiBlLmVycm9yLm1lc3NhZ2UuaW5jbHVkZXMoJ3F1b3RhJykpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5xdW90YUV4Y2VlZGVkID0gZS5lcnJvci5tZXNzYWdlO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZXh0ZXJuYWxFcnJvciA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIHByZXBhcmVEYXRhc2V0SW5zdGFuY2VTdW1tYXJ5Rm9yRXZhbHVhdGlvbigpIHtcbiAgICAgICAgY29uc3QgbWFwcGVkUGFyYW1zID0gdGhpcy5nZXRNYXBwZWRQYXJhbXModGhpcy5kYXNoYm9hcmREYXRhc2V0SW5zdGFuY2UpO1xuXG4gICAgICAgIGNvbnN0IGRhdGFzZXRJbnN0YW5jZVN1bW1hcnkgPSB7XG4gICAgICAgICAgICBkYXRhc2V0SW5zdGFuY2VJZDogdGhpcy5kYXNoYm9hcmREYXRhc2V0SW5zdGFuY2UuZGF0YXNldEluc3RhbmNlSWQsXG4gICAgICAgICAgICBkYXRhc291cmNlSW5zdGFuY2VLZXk6IHRoaXMuZGFzaGJvYXJkRGF0YXNldEluc3RhbmNlLmRhdGFzb3VyY2VJbnN0YW5jZUtleSxcbiAgICAgICAgICAgIHRyYW5zZm9ybWF0aW9uSW5zdGFuY2VzOiB0aGlzLmRhc2hib2FyZERhdGFzZXRJbnN0YW5jZS50cmFuc2Zvcm1hdGlvbkluc3RhbmNlcyxcbiAgICAgICAgICAgIHBhcmFtZXRlclZhbHVlczogbWFwcGVkUGFyYW1zLFxuICAgICAgICAgICAgcGFyYW1ldGVyczogdGhpcy5kYXNoYm9hcmREYXRhc2V0SW5zdGFuY2UucGFyYW1ldGVyc1xuICAgICAgICB9O1xuXG4gICAgICAgIGlmICh0aGlzLmRhc2hib2FyZC5sYXlvdXRTZXR0aW5ncy5wYXJhbWV0ZXJzICYmIE9iamVjdC5rZXlzKHRoaXMuZGFzaGJvYXJkLmxheW91dFNldHRpbmdzLnBhcmFtZXRlcnMpLmxlbmd0aCkge1xuICAgICAgICAgICAgXy5mb3JFYWNoKHRoaXMuZGFzaGJvYXJkLmxheW91dFNldHRpbmdzLnBhcmFtZXRlcnMsIChwYXJhbSwgbmFtZSkgPT4ge1xuICAgICAgICAgICAgICAgIGxldCB2YWx1ZSA9IHBhcmFtLnZhbHVlO1xuICAgICAgICAgICAgICAgIGlmIChwYXJhbS50eXBlID09PSAnZGF0ZScgfHwgcGFyYW0udHlwZSA9PT0gJ2RhdGV0aW1lJykge1xuICAgICAgICAgICAgICAgICAgICBpZiAodmFsdWUgJiYgIXZhbHVlLmluY2x1ZGVzKCdBR08nKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUgPSBtb21lbnQodmFsdWUpLmZvcm1hdCgnWVlZWS1NTS1ERCBISDptbTpzcycpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gQWRkIGluIHRoZSB3aWRnZXQgc3BlY2lmaWMgcGFyYW1ldGVyIHZhbHVlcyBpZiB0aGVyZSBhcmUgYW55XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuZ2VuZXJhbC53aWRnZXRQYXJhbWV0ZXJzICYmIE9iamVjdC5rZXlzKHRoaXMuZ2VuZXJhbC53aWRnZXRQYXJhbWV0ZXJzKS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgd2lkZ2V0UGFyYW0gPSBfLmZpbmQodGhpcy5nZW5lcmFsLndpZGdldFBhcmFtZXRlcnMsIHtuYW1lfSk7XG4gICAgICAgICAgICAgICAgICAgIGlmICh3aWRnZXRQYXJhbSAmJiB3aWRnZXRQYXJhbS52YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUgPSB3aWRnZXRQYXJhbS52YWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGRhdGFzZXRJbnN0YW5jZVN1bW1hcnkucGFyYW1ldGVyVmFsdWVzW25hbWVdID0gdmFsdWU7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBkYXRhc2V0SW5zdGFuY2VTdW1tYXJ5O1xuICAgIH1cbn1cbiIsIjxkaXYgY2xhc3M9XCJhbGVydC1wYW5lbFwiICpuZ0lmPVwic2hvd0FsZXJ0RGF0YVwiIChjbGljayk9XCJzaG93QWxlcnREYXRhID0gZmFsc2VcIj5cbiAgICA8ZGl2IGNsYXNzPVwiYWxpZ24tY2VudGVyIGZsZXgtY29sIHctMy80IG0tYXV0b1wiPlxuICAgICAgICA8bWF0LWljb24+bm90aWZpY2F0aW9uX2ltcG9ydGFudDwvbWF0LWljb24+XG4gICAgICAgIDxoMiBjbGFzcz1cIm1iLTBcIj5BbGVydCBOb3RpZmljYXRpb248L2gyPlxuICAgICAgICA8cCBjbGFzcz1cInRleHQtY2VudGVyXCI+VGhlIGZvbGxvd2luZyBhbGVydHMgaGF2ZSBiZWVuIHRyaWdnZXJlZCBiYXNlZCBvbiB0aGUgY3JpdGVyaWEgc2V0IGZvciB0aGlzIGRhc2hib2FyZFxuICAgICAgICAgICAgaXRlbS4uLjwvcD5cbiAgICAgICAgPGRpdiBjbGFzcz1cImFsZXJ0LWl0ZW0gbWItMlwiICpuZ0Zvcj1cImxldCBhbGVydEl0ZW0gb2YgYWxlcnREYXRhXCJcbiAgICAgICAgICAgICBbaW5uZXJIVE1MXT1cImFsZXJ0SXRlbS5ub3RpZmljYXRpb25NZXNzYWdlXCI+XG4gICAgICAgIDwvZGl2PlxuICAgIDwvZGl2PlxuPC9kaXY+XG5cbjxkaXYgY2xhc3M9XCJpdGVtLWRpc2FibGVkXCI+XG4gICAgPHA+e3tnZW5lcmFsLm5hbWUgfHwgZGFzaGJvYXJkSXRlbVR5cGUubGFiZWx9fTwvcD5cbiAgICA8bWF0LWljb24+YmxvY2s8L21hdC1pY29uPlxuICAgIDxwIGNsYXNzPVwiZGlzYWJsZWQtbm90aWNlXCI+e3tkZXBlbmRlbmNpZXMubm90aWNlIHx8ICdObyBEYXRhIEF2YWlsYWJsZSd9fTwvcD5cbjwvZGl2PlxuXG48bmctdGVtcGxhdGUgW25nSWZdPVwiZHJhZ0l0ZW1cIj5cbiAgICA8c3BhbiBjbGFzcz1cIm1hdGVyaWFsLXN5bWJvbHMtb3V0bGluZWRcIj57e2Rhc2hib2FyZEl0ZW1UeXBlLmljb259fTwvc3Bhbj5cbiAgICA8c3BhbiBbaW5uZXJIVE1MXT1cImRhc2hib2FyZEl0ZW1UeXBlLmxhYmVsXCI+PC9zcGFuPlxuPC9uZy10ZW1wbGF0ZT5cbjxkaXYgY2xhc3M9XCJhbGVydC13aWRnZXRcIiAqbmdJZj1cImFsZXJ0XCIgKGNsaWNrKT1cInNob3dBbGVydERhdGEgPSB0cnVlO1wiPlxuICAgIDxidXR0b24gbWF0LWljb24tYnV0dG9uPlxuICAgICAgICA8bWF0LWljb24+bm90aWZpY2F0aW9uX2ltcG9ydGFudDwvbWF0LWljb24+XG4gICAgPC9idXR0b24+XG4gICAgPGRpdiBjbGFzcz1cImFsZXJ0LXN1bW1hcmllc1wiPlxuICAgICAgICA8c3BhbiBjbGFzcz1cIm1yLTJcIiAqbmdGb3I9XCJsZXQgYWxlcnRJdGVtIG9mIGFsZXJ0RGF0YVwiPlxuICAgICAgICAgICAge3thbGVydEl0ZW0uc3VtbWFyeU1lc3NhZ2V9fVxuICAgICAgICA8L3NwYW4+XG4gICAgPC9kaXY+XG48L2Rpdj5cblxuPG5nLXRlbXBsYXRlXG4gICAgW25nSWZdPVwiIWRyYWdJdGVtICYmICFkYXNoYm9hcmREYXRhc2V0SW5zdGFuY2UgJiYgIWRhc2hib2FyZEl0ZW1UeXBlLmhlYWRpbmdWYWx1ZSAmJiAhZGFzaGJvYXJkSXRlbVR5cGUuX2VkaXRpbmdcIj5cbiAgICA8YnV0dG9uIG1hdC1zdHJva2VkLWJ1dHRvbiBjb2xvcj1cInByaW1hcnlcIiBjbGFzcz1cImNvbmZpZy1idXR0b25cIiAoY2xpY2spPVwiY29uZmlndXJlKClcIj5cbiAgICAgICAgQ29uZmlndXJlIHt7ZGFzaGJvYXJkSXRlbVR5cGUubGFiZWx9fVxuICAgIDwvYnV0dG9uPlxuPC9uZy10ZW1wbGF0ZT5cblxuPGRpdiBjbGFzcz1cImFic29sdXRlIHRvcC0xIHJpZ2h0LTEgIHotMjBcIiAqbmdJZj1cIiFkcmFnSXRlbSAmJiBsb2FkaW5nSXRlbSAmJiAoY2hhcnREYXRhIHx8IGRhdGFzZXQpXCI+XG4gICAgPHN2ZyBjbGFzcz1cImFuaW1hdGUtc3BpbiBoLTUgdy01IHRleHQtc2Vjb25kYXJ5XCIgeG1sbnM9XCJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2Z1wiIGZpbGw9XCJub25lXCIgdmlld0JveD1cIjAgMCAyNCAyNFwiPlxuICAgICAgICA8Y2lyY2xlIGNsYXNzPVwib3BhY2l0eS0yNVwiIGN4PVwiMTJcIiBjeT1cIjEyXCIgcj1cIjEwXCIgc3Ryb2tlPVwiY3VycmVudENvbG9yXCIgc3Ryb2tlLXdpZHRoPVwiNFwiPjwvY2lyY2xlPlxuICAgICAgICA8cGF0aCBjbGFzcz1cIm9wYWNpdHktNzVcIiBmaWxsPVwiY3VycmVudENvbG9yXCIgZD1cIk00IDEyYTggOCAwIDAxOC04VjBDNS4zNzMgMCAwIDUuMzczIDAgMTJoNHptMiA1LjI5MUE3Ljk2MiA3Ljk2MiAwIDAxNCAxMkgwYzAgMy4wNDIgMS4xMzUgNS44MjQgMyA3LjkzOGwzLTIuNjQ3elwiPjwvcGF0aD5cbiAgICA8L3N2Zz5cbjwvZGl2PlxuXG48bmctdGVtcGxhdGUgW25nSWZdPVwiIXZpZXdPbmx5XCI+XG4gICAgPGRpdiBjbGFzcz1cImFic29sdXRlIHRvcC0xIGxlZnQtMSB6LTIwIGN1cnNvci1wb2ludGVyXCIgKm5nSWY9XCIhZHJhZ0l0ZW0gJiYgdGhpcy5pdGVtTm9Nb3ZlXCJcbiAgICAgICAgIChjbGljayk9XCJsb2NrSXRlbSgpXCI+XG4gICAgICAgIDxzdmcgeG1sbnM9XCJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2Z1wiIHZpZXdCb3g9XCIwIDAgMjQgMjRcIiBmaWxsPVwiY3VycmVudENvbG9yXCJcbiAgICAgICAgICAgICBjbGFzcz1cImgtNSB3LTUgdGV4dC1ncmF5LTQwMFwiPlxuICAgICAgICAgICAgPHBhdGggZmlsbC1ydWxlPVwiZXZlbm9kZFwiIGQ9XCJNMTIgMS41YTUuMjUgNS4yNSAwIDAgMC01LjI1IDUuMjV2M2EzIDMgMCAwIDAtMyAzdjYuNzVhMyAzIDAgMCAwIDMgM2gxMC41YTMgMyAwIDAgMCAzLTN2LTYuNzVhMyAzIDAgMCAwLTMtM3YtM2MwLTIuOS0yLjM1LTUuMjUtNS4yNS01LjI1Wm0zLjc1IDguMjV2LTNhMy43NSAzLjc1IDAgMSAwLTcuNSAwdjNoNy41WlwiIGNsaXAtcnVsZT1cImV2ZW5vZGRcIiAvPlxuICAgICAgICA8L3N2Zz5cbiAgICA8L2Rpdj5cblxuICAgIDxkaXYgY2xhc3M9XCJpdGVtLXVubG9ja2VkIGFic29sdXRlIHRvcC0xIGxlZnQtMSB6LTIwIGN1cnNvci1wb2ludGVyXCIgKm5nSWY9XCIhZHJhZ0l0ZW0gJiYgIXRoaXMuaXRlbU5vTW92ZVwiXG4gICAgICAgICAoY2xpY2spPVwibG9ja0l0ZW0oKVwiPlxuICAgICAgICA8c3ZnIHhtbG5zPVwiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmdcIiB2aWV3Qm94PVwiMCAwIDI0IDI0XCIgZmlsbD1cImN1cnJlbnRDb2xvclwiXG4gICAgICAgICAgICAgY2xhc3M9XCJoLTUgdy01IHRleHQtZ3JheS00MDBcIj5cbiAgICAgICAgICAgIDxwYXRoIGQ9XCJNMTggMS41YzIuOSAwIDUuMjUgMi4zNSA1LjI1IDUuMjV2My43NWEuNzUuNzUgMCAwIDEtMS41IDBWNi43NWEzLjc1IDMuNzUgMCAxIDAtNy41IDB2M2EzIDMgMCAwIDEgMyAzdjYuNzVhMyAzIDAgMCAxLTMgM0gzLjc1YTMgMyAwIDAgMS0zLTN2LTYuNzVhMyAzIDAgMCAxIDMtM2g5di0zYzAtMi45IDIuMzUtNS4yNSA1LjI1LTUuMjVaXCIgLz5cbiAgICAgICAgPC9zdmc+XG4gICAgPC9kaXY+XG48L25nLXRlbXBsYXRlPlxuXG5cbjxuZy10ZW1wbGF0ZSBbbmdJZl09XCIhZXh0ZXJuYWxFcnJvciAmJiAhcXVvdGFFeGNlZWRlZFwiPlxuICAgIDxkaXYgY2xhc3M9XCJsb2FkaW5nLWl0ZW1cIiAqbmdJZj1cIiFkcmFnSXRlbSAmJiBsb2FkaW5nSXRlbSAmJiAhKGNoYXJ0RGF0YSB8fCBkYXRhc2V0KVwiPlxuXG4gICAgICAgIDxkaXYgY2xhc3M9XCJteC1hdXRvIGZsZXggaC0xNCB3LTE0IGZsZXgtc2hyaW5rLTAgaXRlbXMtY2VudGVyIGp1c3RpZnktY2VudGVyIHJvdW5kZWQtZnVsbCBiZy1ncmF5LTEwMCBcIj5cbiAgICAgICAgICAgIDxzdmcgY2xhc3M9XCJhbmltYXRlLXNwaW4gaC0xNCB3LTE0IHRleHQtZ3JheS00MDBcIiB4bWxucz1cImh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnXCIgZmlsbD1cIm5vbmVcIiB2aWV3Qm94PVwiMCAwIDI0IDI0XCI+XG4gICAgICAgICAgICAgICAgPGNpcmNsZSBjbGFzcz1cIm9wYWNpdHktMjVcIiBjeD1cIjEyXCIgY3k9XCIxMlwiIHI9XCIxMFwiIHN0cm9rZT1cImN1cnJlbnRDb2xvclwiIHN0cm9rZS13aWR0aD1cIjRcIj48L2NpcmNsZT5cbiAgICAgICAgICAgICAgICA8cGF0aCBjbGFzcz1cIm9wYWNpdHktNzVcIiBmaWxsPVwiY3VycmVudENvbG9yXCIgZD1cIk00IDEyYTggOCAwIDAxOC04VjBDNS4zNzMgMCAwIDUuMzczIDAgMTJoNHptMiA1LjI5MUE3Ljk2MiA3Ljk2MiAwIDAxNCAxMkgwYzAgMy4wNDIgMS4xMzUgNS44MjQgMyA3LjkzOGwzLTIuNjQ3elwiPjwvcGF0aD5cbiAgICAgICAgICAgIDwvc3ZnPlxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPGRpdiBjbGFzcz1cInB4LTQgdGV4dC1jZW50ZXIgbXQtNFwiPkxvYWRpbmcge3tkYXNoYm9hcmRJdGVtVHlwZS5sYWJlbH19IC4uLjwvZGl2PlxuICAgIDwvZGl2PlxuPC9uZy10ZW1wbGF0ZT5cblxuPG5nLXRlbXBsYXRlIFtuZ0lmXT1cImV4dGVybmFsRXJyb3JcIj5cbiAgICA8ZGl2IGNsYXNzPVwibG9hZGluZy1pdGVtXCI+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJteC1hdXRvIGZsZXggaC0xNCB3LTE0IGZsZXgtc2hyaW5rLTAgaXRlbXMtY2VudGVyIGp1c3RpZnktY2VudGVyIHJvdW5kZWQtZnVsbCBiZy1yZWQtMTAwIFwiPlxuICAgICAgICAgICAgPHN2ZyBjbGFzcz1cImgtMTAgdy0xMCB0ZXh0LXJlZC02MDBcIiBmaWxsPVwibm9uZVwiIHZpZXdCb3g9XCIwIDAgMjQgMjRcIiBzdHJva2Utd2lkdGg9XCIxLjVcIiBzdHJva2U9XCJjdXJyZW50Q29sb3JcIiBhcmlhLWhpZGRlbj1cInRydWVcIj5cbiAgICAgICAgICAgICAgICA8cGF0aCBzdHJva2UtbGluZWNhcD1cInJvdW5kXCIgc3Ryb2tlLWxpbmVqb2luPVwicm91bmRcIiBkPVwiTTEyIDl2My43NW0tOS4zMDMgMy4zNzZjLS44NjYgMS41LjIxNyAzLjM3NCAxLjk0OCAzLjM3NGgxNC43MWMxLjczIDAgMi44MTMtMS44NzQgMS45NDgtMy4zNzRMMTMuOTQ5IDMuMzc4Yy0uODY2LTEuNS0zLjAzMi0xLjUtMy44OTggMEwyLjY5NyAxNi4xMjZ6TTEyIDE1Ljc1aC4wMDd2LjAwOEgxMnYtLjAwOHpcIiAvPlxuICAgICAgICAgICAgPC9zdmc+XG4gICAgICAgIDwvZGl2PlxuICAgICAgICA8ZGl2IGNsYXNzPVwicHgtNCB3LTMvNCB0ZXh0LWNlbnRlciBtdC00XCI+VGhlcmUgd2FzIGEgcHJvYmxlbSBsb2FkaW5nIHRoaXMgaXRlbS4gUGxlYXNlIHRyeSBhZ2FpbiBsYXRlci48L2Rpdj5cbiAgICA8L2Rpdj5cbjwvbmctdGVtcGxhdGU+XG5cbjxuZy10ZW1wbGF0ZSBbbmdJZl09XCJxdW90YUV4Y2VlZGVkXCI+XG4gICAgPGRpdiBjbGFzcz1cImxvYWRpbmctaXRlbVwiPlxuICAgICAgICA8ZGl2IGNsYXNzPVwibXgtYXV0byBmbGV4IGgtMTQgdy0xNCBmbGV4LXNocmluay0wIGl0ZW1zLWNlbnRlciBqdXN0aWZ5LWNlbnRlciByb3VuZGVkLWZ1bGwgYmctYmx1ZS0xMDAgXCI+XG4gICAgICAgICAgICA8c3ZnIHhtbG5zPVwiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmdcIiBmaWxsPVwibm9uZVwiIHZpZXdCb3g9XCIwIDAgMjQgMjRcIiBzdHJva2Utd2lkdGg9XCIxLjVcIiBzdHJva2U9XCJjdXJyZW50Q29sb3JcIlxuICAgICAgICAgICAgICAgICBjbGFzcz1cImgtMTAgdy0xMCB0ZXh0LWJsdWUtNjAwXCI+XG4gICAgICAgICAgICAgICAgPHBhdGggc3Ryb2tlLWxpbmVjYXA9XCJyb3VuZFwiIHN0cm9rZS1saW5lam9pbj1cInJvdW5kXCIgZD1cIk0xMS4yNSAxMS4yNWwuMDQxLS4wMmEuNzUuNzUgMCAwMTEuMDYzLjg1MmwtLjcwOCAyLjgzNmEuNzUuNzUgMCAwMDEuMDYzLjg1M2wuMDQxLS4wMjFNMjEgMTJhOSA5IDAgMTEtMTggMCA5IDkgMCAwMTE4IDB6bS05LTMuNzVoLjAwOHYuMDA4SDEyVjguMjV6XCIgLz5cbiAgICAgICAgICAgIDwvc3ZnPlxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPGRpdiBjbGFzcz1cInB4LTQgdy0zLzQgdGV4dC1jZW50ZXIgbXQtNFwiPnt7cXVvdGFFeGNlZWRlZH19PC9kaXY+XG4gICAgPC9kaXY+XG48L25nLXRlbXBsYXRlPlxuXG48bmctdGVtcGxhdGUgW25nSWZdPVwiIWl0ZW1Mb2NrZWRcIj5cbiAgICA8YnV0dG9uICpuZ0lmPVwiIWRyYWdJdGVtXCIgbWF0LW1pbmktZmFiIGNsYXNzPVwiZWRpdC13aWRnZXQgYmctd2hpdGUgdGV4dC1ncmF5LTUwMCBiZy1vcGFjaXR5LTkwXCJcbiAgICAgICAgICAgIFttYXRNZW51VHJpZ2dlckZvcl09XCJlZGl0TWVudVwiPlxuICAgICAgICA8bWF0LWljb24+bW9yZV9ob3JpejwvbWF0LWljb24+XG4gICAgPC9idXR0b24+XG4gICAgPG1hdC1tZW51ICNlZGl0TWVudT1cIm1hdE1lbnVcIj5cbiAgICAgICAgPG5nLXRlbXBsYXRlIFtuZ0lmXT1cIiF2aWV3T25seVwiPlxuICAgICAgICAgICAgPGJ1dHRvbiBtYXQtbWVudS1pdGVtIChjbGljayk9XCJjb25maWd1cmUoKVwiPlxuICAgICAgICAgICAgICAgIDxtYXQtaWNvbj5lZGl0PC9tYXQtaWNvbj5cbiAgICAgICAgICAgICAgICBFZGl0IEl0ZW1cbiAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgPGJ1dHRvbiAqbmdJZj1cImV4aXN0aW5nR3JpZEl0ZW1cIiBtYXQtbWVudS1pdGVtIChjbGljayk9XCJkdXBsaWNhdGUoKVwiPlxuICAgICAgICAgICAgICAgIDxtYXQtaWNvbj5jb3B5X2FsbDwvbWF0LWljb24+XG4gICAgICAgICAgICAgICAgRHVwbGljYXRlIEl0ZW1cbiAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgPGJ1dHRvbiAqbmdJZj1cImNhbkV4cG9ydERhdGFcIiBtYXQtbWVudS1pdGVtIChjbGljayk9XCJleHBvcnREYXRhKClcIj5cbiAgICAgICAgICAgICAgICA8bWF0LWljb24+ZmlsZV9kb3dubG9hZDwvbWF0LWljb24+XG4gICAgICAgICAgICAgICAgRXhwb3J0IERhdGFcbiAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgPG1hdC1kaXZpZGVyPjwvbWF0LWRpdmlkZXI+XG4gICAgICAgICAgICA8YnV0dG9uIG1hdC1tZW51LWl0ZW0gKGNsaWNrKT1cInJlbW92ZVdpZGdldCgkZXZlbnQpXCI+XG4gICAgICAgICAgICAgICAgPG1hdC1pY29uIGNsYXNzPVwidGV4dC1yZWQtNjAwXCI+ZGVsZXRlPC9tYXQtaWNvbj5cbiAgICAgICAgICAgICAgICBEZWxldGUgSXRlbVxuICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgICAgIDxuZy10ZW1wbGF0ZSBbbmdJZl09XCJ2aWV3T25seVwiPlxuICAgICAgICAgICAgPGJ1dHRvbiAqbmdJZj1cImNhbkV4cG9ydERhdGFcIiBtYXQtbWVudS1pdGVtIChjbGljayk9XCJleHBvcnREYXRhKClcIj5cbiAgICAgICAgICAgICAgICA8bWF0LWljb24+ZmlsZV9kb3dubG9hZDwvbWF0LWljb24+XG4gICAgICAgICAgICAgICAgRXhwb3J0IERhdGFcbiAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgPG1hdC1kaXZpZGVyPjwvbWF0LWRpdmlkZXI+XG4gICAgICAgICAgICA8YnV0dG9uIG1hdC1tZW51LWl0ZW0gKGNsaWNrKT1cImVkaXRJdGVtQWxlcnRzKG51bGwpXCI+XG4gICAgICAgICAgICAgICAgPG1hdC1pY29uIGNvbG9yPVwicHJpbWFyeVwiPmFkZDwvbWF0LWljb24+XG4gICAgICAgICAgICAgICAgPHNwYW4+TmV3IEFsZXJ0PC9zcGFuPlxuICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICA8bmctdGVtcGxhdGUgW25nSWZdPVwiZGFzaGJvYXJkRGF0YXNldEluc3RhbmNlXCI+XG4gICAgICAgICAgICAgICAgPGRpdiBtYXQtbWVudS1pdGVtIGNsYXNzPVwiZmxleCBpdGVtcy1jZW50ZXIganVzdGlmeS1iZXR3ZWVuIHAtMCBcIlxuICAgICAgICAgICAgICAgICAgICAgW25nQ2xhc3NdPVwieydib3JkZXIgYm9yZGVyLXQgYm9yZGVyLWItMCBib3JkZXItci0wIGJvcmRlci1sLTAgYm9yZGVyLXNvbGlkIGJvcmRlci1ncmF5LTIwMCc6IGkgPT09IDB9XCJcbiAgICAgICAgICAgICAgICAgICAgICpuZ0Zvcj1cImxldCBhbGVydCBvZiBkYXNoYm9hcmREYXRhc2V0SW5zdGFuY2UuYWxlcnRzOyBsZXQgaSA9IGluZGV4XCI+XG4gICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJweC00IGZsZXggaXRlbXMtY2VudGVyXCIgKGNsaWNrKT1cImVkaXRJdGVtQWxlcnRzKGFsZXJ0LCBpKVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgPG1hdC1pY29uPmVkaXQ8L21hdC1pY29uPlxuICAgICAgICAgICAgICAgICAgICAgICAgPHNwYW4+e3thbGVydC50aXRsZX19PC9zcGFuPlxuICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImZsZXggaXRlbXMtY2VudGVyXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwibXgtMiBkaXZpZGVyXCI+PC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICA8YnV0dG9uIG1hdC1pY29uLWJ1dHRvbiAoY2xpY2spPVwicmVtb3ZlQWxlcnQoJGV2ZW50LCBhbGVydCwgaSlcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bWF0LWljb24gY2xhc3M9XCJteC0yIHRleHQtcmVkLTYwMCBtLTBcIj5oaWdobGlnaHRfb2ZmPC9tYXQtaWNvbj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cblxuICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICA8L21hdC1tZW51PlxuPC9uZy10ZW1wbGF0ZT5cblxuPG5nLXRlbXBsYXRlIFtuZ0lmXT1cIiFkcmFnSXRlbSAmJiBkYXNoYm9hcmRJdGVtVHlwZS50eXBlID09PSAnaGVhZGluZydcIj5cblxuICAgIDxkaXYgY2xhc3M9XCJpdGVtLWhlYWRpbmdcIiAqbmdJZj1cIiFkYXNoYm9hcmRJdGVtVHlwZS5fZWRpdGluZ1wiPlxuICAgICAgICB7e2JpbmRQYXJhbWV0ZXJzSW5TdHJpbmcoZGFzaGJvYXJkSXRlbVR5cGUuaGVhZGluZ1ZhbHVlKX19XG4gICAgPC9kaXY+XG5cbiAgICA8aW5wdXQgdHlwZT1cInRleHRcIiAqbmdJZj1cImRhc2hib2FyZEl0ZW1UeXBlLl9lZGl0aW5nXCIgWyhuZ01vZGVsKV09XCJkYXNoYm9hcmRJdGVtVHlwZS5oZWFkaW5nVmFsdWVcIlxuICAgICAgICAgICAoYmx1cik9XCJ1cGRhdGVIZWFkaW5nKCRldmVudClcIiBjbGFzcz1cInctMTEvMTJcIj5cblxuPC9uZy10ZW1wbGF0ZT5cblxuPG5nLXRlbXBsYXRlIFtuZ0lmXT1cIiFkcmFnSXRlbSAmJiAoY2hhcnREYXRhIHx8IGRhdGFzZXQpXCI+XG5cbiAgICA8ZGl2IGNsYXNzPVwiaXRlbS10aXRsZSBcIiAqbmdJZj1cImdlbmVyYWwubmFtZVwiIFtpbm5lckhUTUxdPVwiZ2VuZXJhbC5ldmFsdWF0ZWROYW1lXCJcbiAgICAgICAgIFtuZ0NsYXNzXT1cInsncGItNCc6ICFnZW5lcmFsLmRlc2NyaXB0aW9uLCAncGItMic6IGdlbmVyYWwuZGVzY3JpcHRpb259XCI+PC9kaXY+XG5cbiAgICA8ZGl2IGNsYXNzPVwiaXRlbS1kZXNjcmlwdGlvbiB0ZXh0LXNtXCIgKm5nSWY9XCJnZW5lcmFsLmRlc2NyaXB0aW9uXCJcbiAgICAgICAgIFtpbm5lckhUTUxdPVwiZ2VuZXJhbC5ldmFsdWF0ZWREZXNjcmlwdGlvblwiPjwvZGl2PlxuXG4gICAgPG5nLXRlbXBsYXRlIFtuZ0lmXT1cImdlbmVyYWwud2lkZ2V0UGFyYW1ldGVycyAmJiBfLnZhbHVlcyhnZW5lcmFsLndpZGdldFBhcmFtZXRlcnMpLmxlbmd0aFwiPlxuICAgICAgICA8ZGl2IGNsYXNzPVwicC0yIGJnLWdyYXktMTAwIHctZnVsbCBmbGV4IGZsZXgtd3JhcFwiPlxuICAgICAgICAgICAgPG5nLXRlbXBsYXRlIG5nRm9yIGxldC1wYXJhbWV0ZXIgW25nRm9yT2ZdPVwiXy52YWx1ZXMoZ2VuZXJhbC53aWRnZXRQYXJhbWV0ZXJzKVwiIGxldC1pPWluZGV4PlxuICAgICAgICAgICAgICAgIDxsYWJlbCBjbGFzcz1cIndpZGdldC1wYXJhbWV0ZXJcIj5cbiAgICAgICAgICAgICAgICAgICAge3twYXJhbWV0ZXIudGl0bGV9fVxuICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwicGFyYW1ldGVyLWlucHV0XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICA8bmctdGVtcGxhdGUgW25nSWZdPVwicGFyYW1ldGVyLnR5cGUgPT09ICd0ZXh0J1wiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxpbnB1dCB0eXBlPVwidGV4dFwiIHBsYWNlaG9sZGVyPVwiRW50ZXIge3twYXJhbWV0ZXIudGl0bGV9fVwiIFsobmdNb2RlbCldPVwicGFyYW1ldGVyLnZhbHVlXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKGtleXVwLmVudGVyKT1cInJlbG9hZFdpZGdldCgpXCIgcmVxdWlyZWQgYXV0b2ZvY3VzPlxuICAgICAgICAgICAgICAgICAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxuZy10ZW1wbGF0ZSBbbmdJZl09XCJwYXJhbWV0ZXIudHlwZSA9PT0gJ251bWVyaWMnXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGlucHV0IHR5cGU9XCJudW1iZXJcIiBwbGFjZWhvbGRlcj1cIkVudGVyIHt7cGFyYW1ldGVyLnRpdGxlfX1cIiBbKG5nTW9kZWwpXT1cInBhcmFtZXRlci52YWx1ZVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChrZXl1cC5lbnRlcik9XCJyZWxvYWRXaWRnZXQoKVwiIHJlcXVpcmVkIGF1dG9mb2N1cz5cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgICAgICAgICAgICAgICAgICAgICA8bmctdGVtcGxhdGUgW25nSWZdPVwicGFyYW1ldGVyLnR5cGUgPT09ICdkYXRlJyB8fCBwYXJhbWV0ZXIudHlwZSA9PT0gJ2RhdGV0aW1lJ1wiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxuZy10ZW1wbGF0ZSBbbmdJZl09XCIhcGFyYW1ldGVyLl9kYXRlVHlwZVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZmxleCBpdGVtcy1jZW50ZXJcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxidXR0b24gKGNsaWNrKT1cImNoYW5nZURhdGVUeXBlKCRldmVudCwgcGFyYW1ldGVyLCAncGlja2VyJylcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbGFzcz1cImhvdmVyOmJnLWdyYXktNTAgdGV4dC1ncmF5LTgwMCBib3JkZXIgYm9yZGVyLWdyYXktMzAwIHB5LTAuNSBwci0yIHJvdW5kZWQgbXItMiBiZy13aGl0ZSBmbGV4IGl0ZW1zLWNlbnRlclwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxtYXQtaWNvbiBjbGFzcz1cInRleHQtYmFzZVwiPmNhbGVuZGFyX21vbnRoPC9tYXQtaWNvbj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBEYXRlIFBpY2tlclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8YnV0dG9uIChjbGljayk9XCJjaGFuZ2VEYXRlVHlwZSgkZXZlbnQsIHBhcmFtZXRlciwgJ3BlcmlvZCcpXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJob3ZlcjpiZy1ncmF5LTUwIHRleHQtZ3JheS04MDAgYm9yZGVyIGJvcmRlci1ncmF5LTMwMCBweS0wLjUgcHItMiByb3VuZGVkIGJnLXdoaXRlIGZsZXggaXRlbXMtY2VudGVyXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPG1hdC1pY29uIGNsYXNzPVwidGV4dC1iYXNlXCI+cmVzdG9yZTwvbWF0LWljb24+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVGltZSBQZXJpb2RcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxuZy10ZW1wbGF0ZSBbbmdJZl09XCJwYXJhbWV0ZXIuX2RhdGVUeXBlID09PSAncGlja2VyJ1wiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8aW5wdXQgW3R5cGVdPVwicGFyYW1ldGVyLnR5cGUgPT09ICdkYXRlJyA/ICdkYXRlJyA6ICdkYXRldGltZS1sb2NhbCdcIiBwbGFjZWhvbGRlcj1cIkVudGVyIHt7cGFyYW1ldGVyLnRpdGxlfX1cIiBbKG5nTW9kZWwpXT1cInBhcmFtZXRlci52YWx1ZVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoa2V5dXAuZW50ZXIpPVwicmVsb2FkV2lkZ2V0KClcIiByZXF1aXJlZCBhdXRvZm9jdXM+XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGEgKGNsaWNrKT1cImNoYW5nZURhdGVUeXBlKCRldmVudCwgcGFyYW1ldGVyLCAncGVyaW9kJylcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRUb29sdGlwPVwiVGltZSBQZXJpb2RcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbGFzcz1cInRleHQtY2VudGVyIG1sLTIgaG92ZXI6YmctZ3JheS01MCB0ZXh0LWdyYXktODAwIGJvcmRlciBib3JkZXItZ3JheS0zMDAgcHktMC41IHByLTAuNSByb3VuZGVkIG1yLTIgYmctd2hpdGUgZmxleCBpdGVtcy1jZW50ZXJcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxtYXQtaWNvbiBjbGFzcz1cInRleHQtYmFzZVwiPnJlc3RvcmU8L21hdC1pY29uPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2E+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bmctdGVtcGxhdGUgW25nSWZdPVwicGFyYW1ldGVyLl9kYXRlVHlwZSA9PT0gJ3BlcmlvZCdcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImZsZXggaXRlbXMtY2VudGVyXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8aW5wdXQgI3BlcmlvZFZhbHVlIHR5cGU9XCJudW1iZXJcIiBwbGFjZWhvbGRlcj1cIk5vLlwiIHJlcXVpcmVkIGF1dG9mb2N1c1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwidy0xNiBtci0yXCIgbWluPVwiMFwiIFt2YWx1ZV09XCJwYXJhbWV0ZXIuX3BlcmlvZFZhbHVlIHx8IDFcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChjaGFuZ2UpPVwidXBkYXRlUGVyaW9kVmFsdWUocGVyaW9kVmFsdWUudmFsdWUsIHBlcmlvZC52YWx1ZSwgcGFyYW1ldGVyKVwiPlxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8c2VsZWN0IGNsYXNzPVwicGFyYW0tcGVyaW9kLXBpY2tlciBtci0yXCIgW3ZhbHVlXT1cInBhcmFtZXRlci5fcGVyaW9kIHx8ICdEQVlTJ1wiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICNwZXJpb2QgKGNoYW5nZSk9XCJ1cGRhdGVQZXJpb2RWYWx1ZShwZXJpb2RWYWx1ZS52YWx1ZSwgcGVyaW9kLnZhbHVlLCBwYXJhbWV0ZXIpXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPG9wdGlvbiB2YWx1ZT1cIkRBWVNcIj5EYXlzPC9vcHRpb24+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPG9wdGlvbiB2YWx1ZT1cIkhPVVJTXCI+SG91cnM8L29wdGlvbj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvc2VsZWN0PlxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2PkFnbzwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8YSAoY2xpY2spPVwiY2hhbmdlRGF0ZVR5cGUoJGV2ZW50LCBwYXJhbWV0ZXIsICdwaWNrZXInKVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hdFRvb2x0aXA9XCJEYXRlIFBpY2tlclwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwidGV4dC1jZW50ZXIgbWwtMiBob3ZlcjpiZy1ncmF5LTUwIHRleHQtZ3JheS04MDAgYm9yZGVyIGJvcmRlci1ncmF5LTMwMCBweS0wLjUgcHItMC41IHJvdW5kZWQgbXItMiBiZy13aGl0ZSBmbGV4IGl0ZW1zLWNlbnRlclwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPG1hdC1pY29uIGNsYXNzPVwidGV4dC1iYXNlXCI+Y2FsZW5kYXJfbW9udGg8L21hdC1pY29uPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2E+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9uZy10ZW1wbGF0ZT5cblxuICAgICAgICAgICAgICAgICAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxuZy10ZW1wbGF0ZSBbbmdJZl09XCJwYXJhbWV0ZXIudHlwZSA9PT0gJ2Jvb2xlYW4nXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPG1hdC1zbGlkZS10b2dnbGUgY2xhc3M9XCJwci00XCIgY29sb3I9XCJwcmltYXJ5XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbY2hlY2tlZF09XCJwYXJhbWV0ZXIudmFsdWVcIiAoY2hhbmdlKT1cImJvb2xlYW5VcGRhdGUoJGV2ZW50LCBwYXJhbWV0ZXIpXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXF1aXJlZD48L21hdC1zbGlkZS10b2dnbGU+XG4gICAgICAgICAgICAgICAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICA8L2xhYmVsPlxuICAgICAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgICAgPC9kaXY+XG4gICAgPC9uZy10ZW1wbGF0ZT5cblxuICAgIDxkaXYgY2xhc3M9XCJpdGVtLWNvbnRhaW5lclwiIFtuZ0NsYXNzXT1cInsnZmxleCBqdXN0aWZ5LWNlbnRlcic6IGRhc2hib2FyZEl0ZW1UeXBlLnR5cGUgPT09ICdpbWFnZScsXG4gICAgICAgICdwLXB4JzogKGRhc2hib2FyZEl0ZW1UeXBlLnR5cGUgPT09ICd0YWJsZScgfHwgZ2VuZXJhbC50cmFuc3BhcmVudCksICdvdmVyZmxvdy1oaWRkZW4nOiAhIWNoYXJ0RGF0YSxcbiAgICAgICAgJ2ZsZXggaXRlbXMtY2VudGVyJzogZGFzaGJvYXJkSXRlbVR5cGUudHlwZSA9PT0gJ21ldHJpYycsICdjdXJzb3ItcG9pbnRlcic6IChhY3Rpb25JdGVtICYmIE9iamVjdC5rZXlzKGFjdGlvbkl0ZW0pLmxlbmd0aCl9XCJcbiAgICAgICAgIChjbGljayk9XCIoYWN0aW9uSXRlbSAmJiBPYmplY3Qua2V5cyhhY3Rpb25JdGVtKS5sZW5ndGgpID8gY2FsbFRvQWN0aW9uTGluayhhY3Rpb25JdGVtKTogbnVsbFwiPlxuXG4gICAgICAgIDxuZy10ZW1wbGF0ZSBbbmdJZl09XCJkYXNoYm9hcmRJdGVtVHlwZS50eXBlID09PSAndGV4dCcgJiYgdGV4dERhdGEudmFsdWVcIj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJoLWZ1bGxcIiAqbmdJZj1cInRleHREYXRhLnNhZmVUZXh0RGF0YVwiIFtpbm5lckhUTUxdPVwidGV4dERhdGEuc2FmZVRleHREYXRhXCI+PC9kaXY+XG4gICAgICAgIDwvbmctdGVtcGxhdGU+XG5cbiAgICAgICAgPG5nLXRlbXBsYXRlIFtuZ0lmXT1cImRhc2hib2FyZEl0ZW1UeXBlLnR5cGUgPT09ICdtZXRyaWMnXCI+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwidy1mdWxsXCI+XG4gICAgICAgICAgICAgICAgPGR0IGNsYXNzPVwidGV4dC1iYXNlIGZvbnQtbm9ybWFsIHRleHQtZ3JheS05MDBcIj57e21ldHJpYy50aXRsZX19PC9kdD5cbiAgICAgICAgICAgICAgICA8ZGQgY2xhc3M9XCJtdC0xIGZsZXggaXRlbXMtYmFzZWxpbmUganVzdGlmeS1iZXR3ZWVuIG1kOmJsb2NrIGxnOmZsZXhcIj5cbiAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImZsZXggaXRlbXMtYmFzZWxpbmUgdGV4dC0yeGwgZm9udC1zZW1pYm9sZCB0ZXh0LWluZGlnby02MDBcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgIHt7bWV0cmljLm1haW5WYWx1ZX19XG4gICAgICAgICAgICAgICAgICAgICAgICA8c3BhbiAqbmdJZj1cIm1ldHJpYy5zdWJNZXRyaWNcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJtbC0yIHRleHQtc20gZm9udC1tZWRpdW0gdGV4dC1ncmF5LTUwMFwiPmZyb20ge3ttZXRyaWMuc3ViVmFsdWV9fVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwidGV4dC14c1wiPih7e21ldHJpYy5zdWJUaXRsZX19KTwvc3Bhbj48L3NwYW4+XG4gICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuXG4gICAgICAgICAgICAgICAgICAgIDxkaXYgKm5nSWY9XCJtZXRyaWMuc2hvd1N1YkNoYW5nZVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJpbmxpbmUtZmxleCBpdGVtcy1iYXNlbGluZSBweC0yLjUgcHktMC41IHJvdW5kZWQtZnVsbCB0ZXh0LXNtIGZvbnQtbWVkaXVtIG1kOm10LTIgbGc6bXQtMFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgW25nQ2xhc3NdPVwieydiZy1ncmVlbi0xMDAgdGV4dC1ncmVlbi04MDAnOiBtZXRyaWMubWFpblZhbHVlID49IG1ldHJpYy5zdWJWYWx1ZSwgJ2JnLXJlZC0xMDAgdGV4dC1yZWQtODAwJzogbWV0cmljLm1haW5WYWx1ZSA8IG1ldHJpYy5zdWJWYWx1ZX1cIj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDwhLS0gSGVyb2ljb24gbmFtZTogbWluaS9hcnJvdy11cCAtLT5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxzdmcgKm5nSWY9XCJtZXRyaWMubWFpblZhbHVlID49IG1ldHJpYy5zdWJWYWx1ZVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwiLW1sLTEgbXItMC41IGgtNSB3LTUgZmxleC1zaHJpbmstMCBzZWxmLWNlbnRlciB0ZXh0LWdyZWVuLTUwMFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgIHhtbG5zPVwiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmdcIiB2aWV3Qm94PVwiMCAwIDIwIDIwXCIgZmlsbD1cImN1cnJlbnRDb2xvclwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFyaWEtaGlkZGVuPVwidHJ1ZVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxwYXRoIGZpbGwtcnVsZT1cImV2ZW5vZGRcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGQ9XCJNMTAgMTdhLjc1Ljc1IDAgMDEtLjc1LS43NVY1LjYxMkw1LjI5IDkuNzdhLjc1Ljc1IDAgMDEtMS4wOC0xLjA0bDUuMjUtNS41YS43NS43NSAwIDAxMS4wOCAwbDUuMjUgNS41YS43NS43NSAwIDExLTEuMDggMS4wNGwtMy45Ni00LjE1OFYxNi4yNUEuNzUuNzUgMCAwMTEwIDE3elwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xpcC1ydWxlPVwiZXZlbm9kZFwiLz5cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvc3ZnPlxuICAgICAgICAgICAgICAgICAgICAgICAgPHN2ZyAqbmdJZj1cIm1ldHJpYy5tYWluVmFsdWUgPCBtZXRyaWMuc3ViVmFsdWUgXCIgeG1sbnM9XCJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2Z1wiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZpZXdCb3g9XCIwIDAgMjAgMjBcIiBmaWxsPVwiY3VycmVudENvbG9yXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCItbWwtMSBtci0wLjUgaC01IHctNSBmbGV4LXNocmluay0wIHNlbGYtY2VudGVyIHRleHQtcmVkLTUwMFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxwYXRoIGZpbGwtcnVsZT1cImV2ZW5vZGRcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGQ9XCJNMTAgM2EuNzUuNzUgMCAwMS43NS43NXYxMC42MzhsMy45Ni00LjE1OGEuNzUuNzUgMCAxMTEuMDggMS4wNGwtNS4yNSA1LjVhLjc1Ljc1IDAgMDEtMS4wOCAwbC01LjI1LTUuNWEuNzUuNzUgMCAxMTEuMDgtMS4wNGwzLjk2IDQuMTU4VjMuNzVBLjc1Ljc1IDAgMDExMCAzelwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xpcC1ydWxlPVwiZXZlbm9kZFwiLz5cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvc3ZnPlxuICAgICAgICAgICAgICAgICAgICAgICAge3ttZXRyaWMuZGlmZmVyZW5jZX19XG4gICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgIDwvZGQ+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9uZy10ZW1wbGF0ZT5cblxuICAgICAgICA8bmctdGVtcGxhdGUgW25nSWZdPVwiZGFzaGJvYXJkSXRlbVR5cGUudHlwZSA9PT0gJ25ldHdvcmsnXCI+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwidy1mdWxsIGgtZnVsbFwiIFtpZF09XCJpdGVtSW5zdGFuY2VLZXkgKyAnVklTJ1wiPjwvZGl2PlxuICAgICAgICA8L25nLXRlbXBsYXRlPlxuXG4gICAgICAgIDxuZy10ZW1wbGF0ZSBbbmdJZl09XCJkYXNoYm9hcmRJdGVtVHlwZS50eXBlID09PSAnaW1hZ2UnXCI+XG4gICAgICAgICAgICA8ZGl2ICpuZ0lmPVwiaW1hZ2VEYXRhLnNvdXJjZVwiIGNsYXNzPVwidy1hdXRvIGgtZnVsbFwiPlxuICAgICAgICAgICAgICAgIDxpbWcgW3NyY109XCJpbWFnZURhdGEuc291cmNlXCIgYWx0PVwiXCJcbiAgICAgICAgICAgICAgICAgICAgIChlcnJvcik9XCJpbWFnZUVycm9yID0gdHJ1ZVwiPlxuICAgICAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgICAgIDxkaXYgKm5nSWY9XCIhaW1hZ2VEYXRhLnNvdXJjZSB8fCBpbWFnZUVycm9yXCIgY2xhc3M9XCJoLWZ1bGwgcmVsYXRpdmUgZmxleCBpdGVtcy1jZW50ZXIganVzdGlmeS1jZW50ZXJcIj5cbiAgICAgICAgICAgICAgICA8cCBjbGFzcz1cInotMTAgdGV4dC1sZ1wiPk5vIGltYWdlPC9wPlxuICAgICAgICAgICAgICAgIDxzdmcgeG1sbnM9XCJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2Z1wiIGNsYXNzPVwiZmlsdGVyIGJsdXItc20gYWJzb2x1dGUgdy1hdXRvIGgtZnVsbCB0ZXh0LWdyYXktMzAwXCJcbiAgICAgICAgICAgICAgICAgICAgIGZpbGw9XCJub25lXCIgdmlld0JveD1cIjAgMCAyNCAyNFwiIHN0cm9rZT1cImN1cnJlbnRDb2xvclwiPlxuICAgICAgICAgICAgICAgICAgICA8cGF0aCBzdHJva2UtbGluZWNhcD1cInJvdW5kXCIgc3Ryb2tlLWxpbmVqb2luPVwicm91bmRcIiBzdHJva2Utd2lkdGg9XCIyXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgZD1cIk00IDE2bDQuNTg2LTQuNTg2YTIgMiAwIDAxMi44MjggMEwxNiAxNm0tMi0ybDEuNTg2LTEuNTg2YTIgMiAwIDAxMi44MjggMEwyMCAxNG0tNi02aC4wMU02IDIwaDEyYTIgMiAwIDAwMi0yVjZhMiAyIDAgMDAtMi0ySDZhMiAyIDAgMDAtMiAydjEyYTIgMiAwIDAwMiAyelwiLz5cbiAgICAgICAgICAgICAgICA8L3N2Zz5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L25nLXRlbXBsYXRlPlxuXG4gICAgICAgIDxuZy10ZW1wbGF0ZSBbbmdJZl09XCJkYXNoYm9hcmRJdGVtVHlwZS50eXBlID09PSAncGllJyB8fCBkYXNoYm9hcmRJdGVtVHlwZS50eXBlID09PSAnZG91Z2hudXQnXCI+XG4gICAgICAgICAgICA8Y2FudmFzIGJhc2VDaGFydCAqbmdJZj1cImNoYXJ0RGF0YVwiIHN0eWxlPVwiaGVpZ2h0OiAyMDBweFwiXG4gICAgICAgICAgICAgICAgICAgIFtkYXRhc2V0c109XCJjaGFydERhdGFcIlxuICAgICAgICAgICAgICAgICAgICBbbGFiZWxzXT1cImRhc2hib2FyZEl0ZW1UeXBlLmxhYmVsc1wiXG4gICAgICAgICAgICAgICAgICAgIFtvcHRpb25zXT1cInt0b29sdGlwczogeyB0aXRsZUZvbnRTaXplOiAwIH0sIHJlc3BvbnNpdmU6dHJ1ZSwgbWFpbnRhaW5Bc3BlY3RSYXRpbzogZmFsc2V9XCJcbiAgICAgICAgICAgICAgICAgICAgW2xlZ2VuZF09XCIhIWRhc2hib2FyZEl0ZW1UeXBlLmxlZ2VuZFwiXG4gICAgICAgICAgICAgICAgICAgIFt0eXBlXT1cImRhc2hib2FyZEl0ZW1UeXBlLnR5cGVcIlxuICAgICAgICAgICAgICAgICAgICBbcGx1Z2luc109XCJbXVwiPlxuICAgICAgICAgICAgPC9jYW52YXM+XG4gICAgICAgIDwvbmctdGVtcGxhdGU+XG5cbiAgICAgICAgPG5nLXRlbXBsYXRlIFtuZ0lmXT1cImRhc2hib2FyZEl0ZW1UeXBlLnR5cGUgPT09ICdsaW5lJyB8fCBkYXNoYm9hcmRJdGVtVHlwZS50eXBlID09PSAnYmFyJyB8fCBkYXNoYm9hcmRJdGVtVHlwZS50eXBlID09PSAnc2NhdHRlcidcIj5cbiAgICAgICAgICAgIDxjYW52YXMgYmFzZUNoYXJ0ICpuZ0lmPVwiY2hhcnREYXRhXCIgc3R5bGU9XCJoZWlnaHQ6IDIwMHB4XCJcbiAgICAgICAgICAgICAgICAgICAgW2RhdGFzZXRzXT1cImNoYXJ0RGF0YVwiXG4gICAgICAgICAgICAgICAgICAgIFtsYWJlbHNdPVwiZGFzaGJvYXJkSXRlbVR5cGUubGFiZWxzXCJcbiAgICAgICAgICAgICAgICAgICAgW29wdGlvbnNdPVwie3Rvb2x0aXBzOiB7IHRpdGxlRm9udFNpemU6IDAgfSwgc2NhbGVzOiB7eToge2JlZ2luQXRaZXJvOiBkYXNoYm9hcmRJdGVtVHlwZS5iZWdpbkF0WmVybywgbWF4OiBkYXNoYm9hcmRJdGVtVHlwZS5tYXhWYWx1ZSB8fCBudWxsfX0sIHJlc3BvbnNpdmU6dHJ1ZSwgbWFpbnRhaW5Bc3BlY3RSYXRpbzogZmFsc2V9XCJcbiAgICAgICAgICAgICAgICAgICAgW2xlZ2VuZF09XCIhIWRhc2hib2FyZEl0ZW1UeXBlLmxlZ2VuZFwiXG4gICAgICAgICAgICAgICAgICAgIFt0eXBlXT1cImRhc2hib2FyZEl0ZW1UeXBlLnR5cGVcIlxuICAgICAgICAgICAgICAgICAgICBbcGx1Z2luc109XCJbXVwiPlxuICAgICAgICAgICAgPC9jYW52YXM+XG4gICAgICAgIDwvbmctdGVtcGxhdGU+XG5cbiAgICAgICAgPG5nLXRlbXBsYXRlIFtuZ0lmXT1cImRhc2hib2FyZEl0ZW1UeXBlLnR5cGUgPT09ICd0YWJsZSdcIj5cblxuICAgICAgICAgICAgPHRhYmxlIGNsYXNzPVwibWluLXctZnVsbCBib3JkZXItc2VwYXJhdGVcIiBzdHlsZT1cImJvcmRlci1zcGFjaW5nOiAwXCI+XG4gICAgICAgICAgICAgICAgPHRoZWFkIGNsYXNzPVwiYmctZ3JheS01MCBcIj5cbiAgICAgICAgICAgICAgICA8dHI+XG4gICAgICAgICAgICAgICAgICAgIDxuZy10ZW1wbGF0ZSBuZ0ZvciBsZXQtY29sdW1uIFtuZ0Zvck9mXT1cImRhdGFzZXQuY29sdW1uc1wiPlxuICAgICAgICAgICAgICAgICAgICAgICAgPHRoIHNjb3BlPVwiY29sXCIgKm5nSWY9XCIhaGlkZGVuQ29sdW1uc1tjb2x1bW4ubmFtZV1cIiAoY2xpY2spPVwic29ydEhlYWRlcihjb2x1bW4pXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbGFzcz1cImN1cnNvci1wb2ludGVyIHN0aWNreSAtdG9wLXB4IHotMTAgYm9yZGVyLWIgYm9yZGVyLWdyYXktMzAwIGJnLWdyYXktNTAgYmctb3BhY2l0eS03NSBwLTMgdGV4dC1sZWZ0IHRleHQteHMgZm9udC1zZW1pYm9sZCB0ZXh0LWdyYXktOTAwIGJhY2tkcm9wLWJsdXIgYmFja2Ryb3AtZmlsdGVyXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiAqbmdJZj1cIiF0YWJsZUNlbGxzW2NvbHVtbi5uYW1lXSB8fCB0YWJsZUNlbGxzW2NvbHVtbi5uYW1lXS50eXBlICE9PSAnYWN0aW9uJ1wiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbGFzcz1cImZsZXggaXRlbXMtY2VudGVyIFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7e2NvbHVtbi50aXRsZX19XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxzdmcgKm5nSWY9XCJjb2x1bW4uZGlyZWN0aW9uID09PSAnYXNjJ1wiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeG1sbnM9XCJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2Z1wiIGZpbGw9XCJub25lXCIgdmlld0JveD1cIjAgMCAyNCAyNFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3Ryb2tlLXdpZHRoPVwiMS41XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJva2U9XCJjdXJyZW50Q29sb3JcIiBjbGFzcz1cInN0cm9rZS0zIHRleHQtc2Vjb25kYXJ5IG1sLTEgdy00IGgtNFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHBhdGggc3Ryb2tlLWxpbmVjYXA9XCJyb3VuZFwiIHN0cm9rZS1saW5lam9pbj1cInJvdW5kXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGQ9XCJNNC41IDEwLjVMMTIgM20wIDBsNy41IDcuNU0xMiAzdjE4XCIvPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L3N2Zz5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHN2ZyAqbmdJZj1cImNvbHVtbi5kaXJlY3Rpb24gPT09ICdkZXNjJ1wiIHhtbG5zPVwiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmdcIiBmaWxsPVwibm9uZVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmlld0JveD1cIjAgMCAyNCAyNFwiIHN0cm9rZS13aWR0aD1cIjEuNVwiIHN0cm9rZT1cImN1cnJlbnRDb2xvclwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJzdHJva2UtMyB0ZXh0LXNlY29uZGFyeSBtbC0xIHctNCBoLTRcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxwYXRoIHN0cm9rZS1saW5lY2FwPVwicm91bmRcIiBzdHJva2UtbGluZWpvaW49XCJyb3VuZFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkPVwiTTE5LjUgMTMuNUwxMiAyMW0wIDBsLTcuNS03LjVNMTIgMjFWM1wiLz5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9zdmc+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICA8L3RoPlxuICAgICAgICAgICAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICAgICAgICAgIDwvdHI+XG4gICAgICAgICAgICAgICAgPC90aGVhZD5cbiAgICAgICAgICAgICAgICA8dGJvZHkgY2xhc3M9XCJiZy13aGl0ZSBcIj5cbiAgICAgICAgICAgICAgICA8dHIgKm5nRm9yPVwibGV0IGRhdGFJdGVtIG9mIG9wdGltaXNlID8gZGF0YXNldC5hbGxEYXRhLnNsaWNlKDAsMTApIDogZGF0YXNldC5hbGxEYXRhXCJcbiAgICAgICAgICAgICAgICAgICAgW25nQ2xhc3NdPVwieydob3ZlcjpiZy1ncmF5LTUwIGN1cnNvci1wb2ludGVyICc6ICh0YWJ1bGFyLmFjdGlvblJvd3MgJiYgdGFidWxhci5jdGEpfVwiXG4gICAgICAgICAgICAgICAgICAgIChjbGljayk9XCIodGFidWxhci5hY3Rpb25Sb3dzICYmIHRhYnVsYXIuY3RhKSA/IGNhbGxUb0FjdGlvbkxpbmsodGFidWxhci5jdGEsIGRhdGFJdGVtKSA6IG51bGxcIj5cbiAgICAgICAgICAgICAgICAgICAgPG5nLXRlbXBsYXRlIG5nRm9yIGxldC1jb2x1bW4gW25nRm9yT2ZdPVwiZGF0YXNldC5jb2x1bW5zXCIgbGV0LWk9aW5kZXg+XG4gICAgICAgICAgICAgICAgICAgICAgICA8dGQgKm5nSWY9XCIhaGlkZGVuQ29sdW1uc1tjb2x1bW4ubmFtZV1cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFt0aXRsZV09XCIodGFibGVDZWxsc1tjb2x1bW4ubmFtZV0gJiYgdGFibGVDZWxsc1tjb2x1bW4ubmFtZV0ubWF4V2lkdGgpID8gZGF0YUl0ZW1bY29sdW1uLm5hbWVdIDogJydcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwiYm9yZGVyLWIgYm9yZGVyLWdyYXktMjAwICBweC0zIHB5LTIgdGV4dC1zbSB0ZXh0LWdyYXktNTAwIHJlbGF0aXZlXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBbbmdDbGFzc109XCJ7J3doaXRlc3BhY2Utbm93cmFwJzogIXRhYnVsYXIuZXhwYW5kUm93cywgJ2ZvbnQtbWVkaXVtIHRleHQtZ3JheS05MDAnOiBpID09PSAwfVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgW25nU3R5bGVdPVwieyd3aWR0aCc6ICcnLCAnbWF4LXdpZHRoJzogKHRhYmxlQ2VsbHNbY29sdW1uLm5hbWVdICYmIHRhYmxlQ2VsbHNbY29sdW1uLm5hbWVdLm1heFdpZHRoKSA/IHRhYmxlQ2VsbHNbY29sdW1uLm5hbWVdLm1heFdpZHRoICsgJ3B4JyA6IG51bGwsICdvdmVyZmxvdyc6ICh0YWJsZUNlbGxzW2NvbHVtbi5uYW1lXSAmJiB0YWJsZUNlbGxzW2NvbHVtbi5uYW1lXS5tYXhXaWR0aCkgPyAnaGlkZGVuJyA6IG51bGwsICd0ZXh0LW92ZXJmbG93JzogKHRhYmxlQ2VsbHNbY29sdW1uLm5hbWVdICYmIHRhYmxlQ2VsbHNbY29sdW1uLm5hbWVdLm1heFdpZHRoKSA/ICdlbGxpcHNpcycgOiBudWxsfVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxuZy10ZW1wbGF0ZSBbbmdJZl09XCJ0YWJsZUNlbGxzW2NvbHVtbi5uYW1lXSAmJiB0YWJsZUNlbGxzW2NvbHVtbi5uYW1lXS50eXBlID09PSAnYWN0aW9uJ1wiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIiAqbmdJZj1cInRhYmxlQ2VsbHNbY29sdW1uLm5hbWVdLmRhdGEuYWN0aW9uRXZlbnRcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtuZ0NsYXNzXT1cInsnYmctb3JhbmdlLTUwIGJvcmRlci1vcmFuZ2UtMjAwIGhvdmVyOmJnLW9yYW5nZS0xMDAnOiBpc0FjdGlvbkNvbXBsZXRlKHRhYmxlQ2VsbHNbY29sdW1uLm5hbWVdLmRhdGEuYWN0aW9uRXZlbnQsIGRhdGFJdGVtW2NvbHVtbi5uYW1lXSl9XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoY2xpY2spPVwidHJpZ2dlckFjdGlvbkV2ZW50KHRhYmxlQ2VsbHNbY29sdW1uLm5hbWVdLmRhdGEuYWN0aW9uRXZlbnQsIGNvbHVtbiwgZGF0YUl0ZW1bY29sdW1uLm5hbWVdKVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJ0ZXh0LWdyYXktNjAwIGlubGluZS1mbGV4IGl0ZW1zLWNlbnRlciByb3VuZGVkIGJvcmRlciBib3JkZXItcHJpbWFyeSBiZy1ncmF5LTUwIHB4LTIuNSBweS0xLjUgdGV4dC14cyBmb250LW1lZGl1bSBob3ZlcjpiZy1ncmF5LTEwMFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAge3tnZXRBY3Rpb25FdmVudFRpdGxlKHRhYmxlQ2VsbHNbY29sdW1uLm5hbWVdLmRhdGEuYWN0aW9uRXZlbnQsIGNvbHVtbiwgZGF0YUl0ZW1bY29sdW1uLm5hbWVdKX19XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvbmctdGVtcGxhdGU+XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bmctdGVtcGxhdGUgW25nSWZdPVwiIXRhYmxlQ2VsbHNbY29sdW1uLm5hbWVdIHx8IHRhYmxlQ2VsbHNbY29sdW1uLm5hbWVdLnR5cGUgIT09ICdhY3Rpb24nXCI+XG5cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bmctdGVtcGxhdGUgW25nSWZdPVwidGFidWxhci5leHBhbmRSb3dzXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2ICpuZ0lmPVwiIV8uaXNQbGFpbk9iamVjdChkYXRhSXRlbVtjb2x1bW4ubmFtZV0pXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW2lubmVySFRNTF09XCJkYXRhSXRlbVtjb2x1bW4ubmFtZV1cIj48L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgKm5nSWY9XCJfLmlzUGxhaW5PYmplY3QoZGF0YUl0ZW1bY29sdW1uLm5hbWVdKVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtpbm5lckhUTUxdPVwiZGF0YUl0ZW1bY29sdW1uLm5hbWVdLmNlbGxWYWx1ZVwiPjwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bmctdGVtcGxhdGUgW25nSWZdPVwiIXRhYnVsYXIuZXhwYW5kUm93cyAmJiBfLmlzUGxhaW5PYmplY3QoZGF0YUl0ZW1bY29sdW1uLm5hbWVdKVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBbaW5uZXJIVE1MXT1cImRhdGFJdGVtW2NvbHVtbi5uYW1lXS5jZWxsVmFsdWVcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbbmdTdHlsZV09XCJ7J21heC13aWR0aCc6ICh0YWJsZUNlbGxzW2NvbHVtbi5uYW1lXSAmJiB0YWJsZUNlbGxzW2NvbHVtbi5uYW1lXS5tYXhXaWR0aCkgPyB0YWJsZUNlbGxzW2NvbHVtbi5uYW1lXS5tYXhXaWR0aCArICdweCcgOiBudWxsLCAnb3ZlcmZsb3cnOiAodGFibGVDZWxsc1tjb2x1bW4ubmFtZV0gJiYgdGFibGVDZWxsc1tjb2x1bW4ubmFtZV0ubWF4V2lkdGgpID8gJ2hpZGRlbicgOiBudWxsLCAndGV4dC1vdmVyZmxvdyc6ICh0YWJsZUNlbGxzW2NvbHVtbi5uYW1lXSAmJiB0YWJsZUNlbGxzW2NvbHVtbi5uYW1lXS5tYXhXaWR0aCkgPyAnZWxsaXBzaXMnIDogbnVsbH1cIj48L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPG5nLXRlbXBsYXRlIFtuZ0lmXT1cIiF0YWJ1bGFyLmV4cGFuZFJvd3MgJiYgIV8uaXNQbGFpbk9iamVjdChkYXRhSXRlbVtjb2x1bW4ubmFtZV0pXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bmctdGVtcGxhdGVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbbmdJZl09XCJkYXRhSXRlbVtjb2x1bW4ubmFtZV0gJiYgU3RyaW5nKGRhdGFJdGVtW2NvbHVtbi5uYW1lXSkubGVuZ3RoIDw9IDEwMFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHt7ZGF0YUl0ZW1bY29sdW1uLm5hbWVdfX1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bmctdGVtcGxhdGVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbbmdJZl09XCJkYXRhSXRlbVtjb2x1bW4ubmFtZV0gJiYgU3RyaW5nKGRhdGFJdGVtW2NvbHVtbi5uYW1lXSkubGVuZ3RoID4gMTAwXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbbmdTdHlsZV09XCJ7J21heC13aWR0aCc6ICh0YWJsZUNlbGxzW2NvbHVtbi5uYW1lXSAmJiB0YWJsZUNlbGxzW2NvbHVtbi5uYW1lXS5tYXhXaWR0aCkgPyB0YWJsZUNlbGxzW2NvbHVtbi5uYW1lXS5tYXhXaWR0aCArICdweCcgOiBudWxsLCAnb3ZlcmZsb3cnOiAodGFibGVDZWxsc1tjb2x1bW4ubmFtZV0gJiYgdGFibGVDZWxsc1tjb2x1bW4ubmFtZV0ubWF4V2lkdGgpID8gJ2hpZGRlbicgOiBudWxsLCAndGV4dC1vdmVyZmxvdyc6ICh0YWJsZUNlbGxzW2NvbHVtbi5uYW1lXSAmJiB0YWJsZUNlbGxzW2NvbHVtbi5uYW1lXS5tYXhXaWR0aCkgPyAnZWxsaXBzaXMnIDogbnVsbH1cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbdGl0bGVdPVwiZGF0YUl0ZW1bY29sdW1uLm5hbWVdXCI+e3tkYXRhSXRlbVtjb2x1bW4ubmFtZV0uc3Vic3RyaW5nKDAsIDEwMCkgKyAnLi4uJ319PC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPG5nLXRlbXBsYXRlIFtuZ0lmXT1cIiFkYXRhSXRlbVtjb2x1bW4ubmFtZV1cIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7e2RhdGFJdGVtW2NvbHVtbi5uYW1lXX19XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgICAgICAgICAgICAgICAgICAgICA8L3RkPlxuICAgICAgICAgICAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuXG4gICAgICAgICAgICAgICAgPC90cj5cbiAgICAgICAgICAgICAgICA8dHIgKm5nSWY9XCJvcHRpbWlzZSAmJiBkYXRhc2V0LmFsbERhdGEubGVuZ3RoID4gMTBcIj5cbiAgICAgICAgICAgICAgICAgICAgPHRkIGNsYXNzPVwicGwtMyB0ZXh0LWdyYXktOTAwIGZvbnQtbWVkaXVtIGJnLWdyYXktMjAwXCIgW2NvbFNwYW5dPVwiZGF0YXNldC5jb2x1bW5zLmxlbmd0aFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgUmVzdWx0cyBsaW1pdGVkIGR1cmluZyBlZGl0aW5nIGZvciBlbmhhbmNlZCBwZXJmb3JtYW5jZS5cbiAgICAgICAgICAgICAgICAgICAgPC90ZD5cbiAgICAgICAgICAgICAgICA8L3RyPlxuICAgICAgICAgICAgICAgIDwvdGJvZHk+XG4gICAgICAgICAgICA8L3RhYmxlPlxuXG4gICAgICAgICAgICA8ZGl2ICpuZ0lmPVwiIWRhdGFzZXQuYWxsRGF0YS5sZW5ndGhcIlxuICAgICAgICAgICAgICAgICBjbGFzcz1cIm5vLXRhYmxlLXJlY29yZHMgdGV4dC1zbSB0ZXh0LWdyYXktNTAwIGZsZXggbS0wIGp1c3RpZnktY2VudGVyIGl0ZW1zLWNlbnRlclwiPlxuICAgICAgICAgICAgICAgIE5vIHJlY29yZHMgdG8gc2hvd1xuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvbmctdGVtcGxhdGU+XG5cbiAgICAgICAgPG5nLXRlbXBsYXRlIFtuZ0lmXT1cImRhc2hib2FyZEl0ZW1UeXBlLnR5cGUgPT09ICd3b3JkcydcIj5cbiAgICAgICAgICAgIDxhbmd1bGFyLWQzLWNsb3VkICpuZ0lmPVwid29yZENsb3VkLmRhdGFcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW2RhdGFdPVwid29yZENsb3VkLmRhdGFcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW3dpZHRoXT1cIndvcmRDbG91ZC53aWR0aFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbaGVpZ2h0XT1cIndvcmRDbG91ZC5oZWlnaHRcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW3BhZGRpbmddPVwiNVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb250PVwic2VyaWZcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW3JvdGF0ZV09XCIwXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFthdXRvRmlsbF09XCJ0cnVlXCJcbiAgICAgICAgICAgID48L2FuZ3VsYXItZDMtY2xvdWQ+XG4gICAgICAgIDwvbmctdGVtcGxhdGU+XG5cbiAgICA8L2Rpdj5cblxuICAgIDxkaXYgKm5nSWY9XCIhb3B0aW1pc2UgJiYgZGFzaGJvYXJkSXRlbVR5cGUudHlwZSA9PT0gJ3RhYmxlJyAmJiAhdGFidWxhci5oaWRlUGFnZXJcIlxuICAgICAgICAgY2xhc3M9XCJ0YWJsZS1wYWdlciBmbGV4IGl0ZW1zLWNlbnRlciBqdXN0aWZ5LWJldHdlZW4gcHgtMiBib3JkZXItdCBib3JkZXItZ3JheS0yMDAgaC0xMiBiZy1ncmF5LTUwIHctZnVsbFwiPlxuICAgICAgICA8ZGl2IGNsYXNzPVwidGV4dC14cyB0ZXh0LWdyYXktNDAwXCI+XG4gICAgICAgICAgICBTaG93aW5nIHt7b2Zmc2V0ICsgMX19IC0ge3socGFnZSAqIGxpbWl0KSAtIChsaW1pdCAtIGRhdGFzZXQuYWxsRGF0YS5sZW5ndGgpfX08L2Rpdj5cbiAgICAgICAgPGRpdiBjbGFzcz1cImZsZXggaXRlbXMtY2VudGVyIGp1c3RpZnktY2VudGVyXCI+XG4gICAgICAgICAgICA8YnV0dG9uIG1hdC1pY29uLWJ1dHRvbiAoY2xpY2spPVwiZGVjcmVhc2VPZmZzZXQoKVwiIFtkaXNhYmxlZF09XCJwYWdlIDw9IDFcIj5cbiAgICAgICAgICAgICAgICA8bWF0LWljb24+Y2hldnJvbl9sZWZ0PC9tYXQtaWNvbj5cbiAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgPHNlbGVjdCBbdmFsdWVdPVwibGltaXRcIiAoY2hhbmdlKT1cInBhZ2VTaXplQ2hhbmdlKCRldmVudC50YXJnZXQudmFsdWUpXCJcbiAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJwLTEgbXgtMlwiPlxuICAgICAgICAgICAgICAgIDxvcHRpb24gW3ZhbHVlXT1cIjFcIj4xPC9vcHRpb24+XG4gICAgICAgICAgICAgICAgPG9wdGlvbiBbdmFsdWVdPVwiNVwiPjU8L29wdGlvbj5cbiAgICAgICAgICAgICAgICA8b3B0aW9uIFt2YWx1ZV09XCIxMFwiPjEwPC9vcHRpb24+XG4gICAgICAgICAgICAgICAgPG9wdGlvbiBbdmFsdWVdPVwiMjVcIj4yNTwvb3B0aW9uPlxuICAgICAgICAgICAgICAgIDxvcHRpb24gW3ZhbHVlXT1cIjUwXCI+NTA8L29wdGlvbj5cbiAgICAgICAgICAgICAgICA8b3B0aW9uIFt2YWx1ZV09XCIxMDBcIj4xMDA8L29wdGlvbj5cbiAgICAgICAgICAgICAgICA8b3B0aW9uIFt2YWx1ZV09XCIyNTBcIj4yNTA8L29wdGlvbj5cbiAgICAgICAgICAgICAgICA8b3B0aW9uIFt2YWx1ZV09XCIxMDAwXCI+MTAwMDwvb3B0aW9uPlxuICAgICAgICAgICAgPC9zZWxlY3Q+XG4gICAgICAgICAgICA8YnV0dG9uIG1hdC1pY29uLWJ1dHRvbiAoY2xpY2spPVwiaW5jcmVhc2VPZmZzZXQoKVwiIFtkaXNhYmxlZF09XCJlbmRPZlJlc3VsdHNcIj5cbiAgICAgICAgICAgICAgICA8bWF0LWljb24+Y2hldnJvbl9yaWdodDwvbWF0LWljb24+XG4gICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgPC9kaXY+XG4gICAgPC9kaXY+XG5cbiAgICA8ZGl2IGNsYXNzPVwiZm9vdGVyIHctZnVsbCBiZy1ncmF5LTUwIHB4LTIgcHktMSB0ZXh0LWdyYXktNjAwIGJvcmRlci1iIGJvcmRlci1ncmF5LTIwMCB0ZXh0LXhzXCJcbiAgICAgICAgIFtuZ0NsYXNzXT1cInsnYm9yZGVyLWInOiBjYWxsVG9BY3Rpb24gJiYgT2JqZWN0LmtleXMoY2FsbFRvQWN0aW9uKS5sZW5ndGh9XCJcbiAgICAgICAgICpuZ0lmPVwiZ2VuZXJhbC5mb290ZXJcIiBbaW5uZXJIVE1MXT1cImdlbmVyYWwuZXZhbHVhdGVkRm9vdGVyXCI+PC9kaXY+XG5cbiAgICA8ZGl2IGNsYXNzPVwiY2FsbC10by1hY3Rpb24gdy1mdWxsIGJnLWdyYXktNTAgcHgtNSBweS0zXCIgKm5nSWY9XCJjYWxsVG9BY3Rpb24gJiYgT2JqZWN0LmtleXMoY2FsbFRvQWN0aW9uKS5sZW5ndGhcIj5cbiAgICAgICAgPGRpdiBjbGFzcz1cInRleHQtc21cIj5cbiAgICAgICAgICAgIDxhIGNsYXNzPVwiZm9udC1tZWRpdW0gdGV4dC1jdGEgZmxleCBpdGVtcy1jZW50ZXJcIlxuICAgICAgICAgICAgICAgKGNsaWNrKT1cImNhbGxUb0FjdGlvbkxpbmsoY2FsbFRvQWN0aW9uKVwiPlxuICAgICAgICAgICAgICAgIHt7Y2FsbFRvQWN0aW9uLmxhYmVsfX1cbiAgICAgICAgICAgICAgICA8bWF0LWljb24+Y2hldnJvbl9yaWdodDwvbWF0LWljb24+XG4gICAgICAgICAgICA8L2E+XG4gICAgICAgIDwvZGl2PlxuICAgIDwvZGl2PlxuXG48L25nLXRlbXBsYXRlPlxuIl19