@c8y/ngx-components 1021.51.1 → 1021.54.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 (252) hide show
  1. package/alarm-event-selector/alarm-event-attributes-form/alarm-event-attributes-form.component.d.ts +10 -2
  2. package/alarm-event-selector/alarm-event-attributes-form/alarm-event-attributes-form.component.d.ts.map +1 -1
  3. package/alarm-event-selector/alarm-event-attributes-form/alarm-event-attributes-form.model.d.ts +11 -0
  4. package/alarm-event-selector/alarm-event-attributes-form/alarm-event-attributes-form.model.d.ts.map +1 -0
  5. package/alarm-event-selector/alarm-event-selection-list/alarm-event-selection-list.component.d.ts +10 -4
  6. package/alarm-event-selector/alarm-event-selection-list/alarm-event-selection-list.component.d.ts.map +1 -1
  7. package/alarm-event-selector/alarm-event-selector-list-item/alarm-event-selector-list-item.component.d.ts +3 -1
  8. package/alarm-event-selector/alarm-event-selector-list-item/alarm-event-selector-list-item.component.d.ts.map +1 -1
  9. package/alarm-event-selector/alarm-event-selector.model.d.ts +7 -0
  10. package/alarm-event-selector/alarm-event-selector.model.d.ts.map +1 -1
  11. package/core/dashboard/dashboard-child-action.component.d.ts +1 -1
  12. package/core/dashboard/dashboard-child-action.component.d.ts.map +1 -1
  13. package/core/dashboard/dashboard.module.d.ts +29 -29
  14. package/core/dashboard/index.d.ts +3 -0
  15. package/core/dashboard/index.d.ts.map +1 -1
  16. package/core/dashboard/widgets-dashboard.component.d.ts +1 -1
  17. package/core/dashboard/widgets-dashboard.component.d.ts.map +1 -1
  18. package/core/dashboard/wiget-time-context/aggregation-picker/aggregation-picker.component.d.ts +1 -1
  19. package/core/dashboard/wiget-time-context/aggregation-picker/aggregation-picker.component.d.ts.map +1 -1
  20. package/core/dashboard/wiget-time-context/realtime-control/realtime-control.component.d.ts +1 -1
  21. package/core/dashboard/wiget-time-context/realtime-control/realtime-control.component.d.ts.map +1 -1
  22. package/core/dashboard/wiget-time-context/widget-time-context-date-range.service.d.ts +10 -0
  23. package/core/dashboard/wiget-time-context/widget-time-context-date-range.service.d.ts.map +1 -0
  24. package/core/dashboard/wiget-time-context/widget-time-context.component.d.ts +7 -4
  25. package/core/dashboard/wiget-time-context/widget-time-context.component.d.ts.map +1 -1
  26. package/core/dashboard/wiget-time-context/widget-time-context.model.d.ts +0 -1
  27. package/core/dashboard/wiget-time-context/widget-time-context.model.d.ts.map +1 -1
  28. package/core/date-picker/date-picker.component.d.ts +1 -1
  29. package/core/date-picker/date-picker.component.d.ts.map +1 -1
  30. package/core/date-picker/date-picker.module.d.ts +9 -9
  31. package/core/date-time-picker/close-date-picker.directive.d.ts +1 -1
  32. package/core/date-time-picker/close-date-picker.directive.d.ts.map +1 -1
  33. package/core/date-time-picker/date-time-picker.component.d.ts +6 -3
  34. package/core/date-time-picker/date-time-picker.component.d.ts.map +1 -1
  35. package/core/date-time-picker/date-time-picker.module.d.ts +11 -11
  36. package/core/date-time-picker/date-time-picker.module.d.ts.map +1 -1
  37. package/core/forms/forms.module.d.ts +18 -18
  38. package/core/forms/required-input-placeholder.directive.d.ts +1 -1
  39. package/core/forms/required-input-placeholder.directive.d.ts.map +1 -1
  40. package/core/router/router.service.d.ts.map +1 -1
  41. package/core/user/user-menu.service.d.ts +36 -11
  42. package/core/user/user-menu.service.d.ts.map +1 -1
  43. package/datapoint-explorer/c8y-ngx-components-datapoint-explorer.d.ts.map +1 -0
  44. package/datapoint-explorer/datapoint-explorer.module.d.ts +7 -0
  45. package/datapoint-explorer/datapoint-explorer.module.d.ts.map +1 -0
  46. package/datapoint-explorer/index.d.ts +2 -0
  47. package/datapoint-explorer/index.d.ts.map +1 -0
  48. package/datapoint-explorer/view/c8y-ngx-components-datapoint-explorer-view.d.ts.map +1 -0
  49. package/datapoint-explorer/view/configuration/naming-dictionary.d.ts +3 -0
  50. package/datapoint-explorer/view/configuration/naming-dictionary.d.ts.map +1 -0
  51. package/datapoint-explorer/view/configuration/workspace-configuration.component.d.ts +38 -0
  52. package/datapoint-explorer/view/configuration/workspace-configuration.component.d.ts.map +1 -0
  53. package/datapoint-explorer/view/configuration/workspace-configuration.model.d.ts +7 -0
  54. package/datapoint-explorer/view/configuration/workspace-configuration.model.d.ts.map +1 -0
  55. package/datapoint-explorer/view/configuration/workspace-configuration.service.d.ts +15 -0
  56. package/datapoint-explorer/view/configuration/workspace-configuration.service.d.ts.map +1 -0
  57. package/datapoint-explorer/view/create-new-report-modal/create-new-report-modal.component.d.ts +25 -0
  58. package/datapoint-explorer/view/create-new-report-modal/create-new-report-modal.component.d.ts.map +1 -0
  59. package/datapoint-explorer/view/datapoint-explorer.component.d.ts +67 -0
  60. package/datapoint-explorer/view/datapoint-explorer.component.d.ts.map +1 -0
  61. package/datapoint-explorer/view/datapoint-explorer.service.d.ts +9 -0
  62. package/datapoint-explorer/view/datapoint-explorer.service.d.ts.map +1 -0
  63. package/datapoint-explorer/view/index.d.ts +2 -0
  64. package/datapoint-explorer/view/index.d.ts.map +1 -0
  65. package/datapoint-explorer/view/send-as-widget-to-report-modal/send-as-widget-to-report-modal.component.d.ts +23 -0
  66. package/datapoint-explorer/view/send-as-widget-to-report-modal/send-as-widget-to-report-modal.component.d.ts.map +1 -0
  67. package/echart/c8y-ngx-components-echart.d.ts.map +1 -0
  68. package/echart/chart-alerts/chart-alerts.component.d.ts +8 -0
  69. package/echart/chart-alerts/chart-alerts.component.d.ts.map +1 -0
  70. package/echart/charts.component.d.ts +63 -0
  71. package/echart/charts.component.d.ts.map +1 -0
  72. package/echart/index.d.ts +5 -0
  73. package/echart/index.d.ts.map +1 -0
  74. package/echart/models/c8y-ngx-components-echart-models.d.ts.map +1 -0
  75. package/echart/models/chart.model.d.ts +37 -0
  76. package/echart/models/chart.model.d.ts.map +1 -0
  77. package/echart/models/datapoints-graph-widget.model.d.ts +126 -0
  78. package/echart/models/datapoints-graph-widget.model.d.ts.map +1 -0
  79. package/echart/models/index.d.ts +4 -0
  80. package/echart/models/index.d.ts.map +1 -0
  81. package/echart/models/svg-icons.model.d.ts +22 -0
  82. package/echart/models/svg-icons.model.d.ts.map +1 -0
  83. package/echart/services/chart-alarms.service.d.ts +17 -0
  84. package/echart/services/chart-alarms.service.d.ts.map +1 -0
  85. package/echart/services/chart-events.service.d.ts +17 -0
  86. package/echart/services/chart-events.service.d.ts.map +1 -0
  87. package/echart/services/chart-realtime.service.d.ts +35 -0
  88. package/echart/services/chart-realtime.service.d.ts.map +1 -0
  89. package/echart/services/chart-types.service.d.ts +15 -0
  90. package/echart/services/chart-types.service.d.ts.map +1 -0
  91. package/echart/services/custom-measurements.service.d.ts +12 -0
  92. package/echart/services/custom-measurements.service.d.ts.map +1 -0
  93. package/echart/services/echarts-options.service.d.ts +143 -0
  94. package/echart/services/echarts-options.service.d.ts.map +1 -0
  95. package/echart/services/y-axis.service.d.ts +17 -0
  96. package/echart/services/y-axis.service.d.ts.map +1 -0
  97. package/esm2022/alarm-event-selector/alarm-event-attributes-form/alarm-event-attributes-form.component.mjs +37 -12
  98. package/esm2022/alarm-event-selector/alarm-event-attributes-form/alarm-event-attributes-form.model.mjs +2 -0
  99. package/esm2022/alarm-event-selector/alarm-event-selection-list/alarm-event-selection-list.component.mjs +39 -12
  100. package/esm2022/alarm-event-selector/alarm-event-selector-list-item/alarm-event-selector-list-item.component.mjs +6 -4
  101. package/esm2022/alarm-event-selector/alarm-event-selector.component.mjs +1 -1
  102. package/esm2022/alarm-event-selector/alarm-event-selector.model.mjs +1 -1
  103. package/esm2022/alarm-event-selector/custom-alarm-event-form/custom-alarm-event-form.component.mjs +1 -1
  104. package/esm2022/alarms/alarms-filter.component.mjs +3 -3
  105. package/esm2022/core/dashboard/dashboard-child-action.component.mjs +3 -3
  106. package/esm2022/core/dashboard/dashboard.module.mjs +17 -14
  107. package/esm2022/core/dashboard/index.mjs +4 -1
  108. package/esm2022/core/dashboard/widgets-dashboard.component.mjs +9 -9
  109. package/esm2022/core/dashboard/wiget-time-context/aggregation-picker/aggregation-picker.component.mjs +11 -9
  110. package/esm2022/core/dashboard/wiget-time-context/realtime-control/realtime-control.component.mjs +8 -7
  111. package/esm2022/core/dashboard/wiget-time-context/widget-time-context-date-range.service.mjs +23 -0
  112. package/esm2022/core/dashboard/wiget-time-context/widget-time-context.component.mjs +70 -26
  113. package/esm2022/core/dashboard/wiget-time-context/widget-time-context.model.mjs +1 -1
  114. package/esm2022/core/date-picker/date-picker.component.mjs +29 -14
  115. package/esm2022/core/date-picker/date-picker.module.mjs +9 -7
  116. package/esm2022/core/date-time-picker/close-date-picker.directive.mjs +4 -3
  117. package/esm2022/core/date-time-picker/date-time-picker.component.mjs +57 -29
  118. package/esm2022/core/date-time-picker/date-time-picker.module.mjs +11 -7
  119. package/esm2022/core/forms/forms.module.mjs +3 -3
  120. package/esm2022/core/forms/ip-range-input-list.component.mjs +5 -5
  121. package/esm2022/core/forms/required-input-placeholder.directive.mjs +4 -3
  122. package/esm2022/core/router/router.service.mjs +1 -1
  123. package/esm2022/core/user/user-menu.service.mjs +57 -17
  124. package/esm2022/datapoint-explorer/c8y-ngx-components-datapoint-explorer.mjs +5 -0
  125. package/esm2022/datapoint-explorer/datapoint-explorer.module.mjs +65 -0
  126. package/esm2022/datapoint-explorer/index.mjs +2 -0
  127. package/esm2022/datapoint-explorer/view/c8y-ngx-components-datapoint-explorer-view.mjs +5 -0
  128. package/esm2022/datapoint-explorer/view/configuration/naming-dictionary.mjs +65 -0
  129. package/esm2022/datapoint-explorer/view/configuration/workspace-configuration.component.mjs +169 -0
  130. package/esm2022/datapoint-explorer/view/configuration/workspace-configuration.model.mjs +2 -0
  131. package/esm2022/datapoint-explorer/view/configuration/workspace-configuration.service.mjs +40 -0
  132. package/esm2022/datapoint-explorer/view/create-new-report-modal/create-new-report-modal.component.mjs +64 -0
  133. package/esm2022/datapoint-explorer/view/datapoint-explorer.component.mjs +279 -0
  134. package/esm2022/datapoint-explorer/view/datapoint-explorer.service.mjs +23 -0
  135. package/esm2022/datapoint-explorer/view/index.mjs +2 -0
  136. package/esm2022/datapoint-explorer/view/send-as-widget-to-report-modal/send-as-widget-to-report-modal.component.mjs +48 -0
  137. package/esm2022/datapoint-selector/datapoint-attributes-form/datapoint-attributes-form.component.mjs +3 -3
  138. package/esm2022/datapoint-selector/datapoint-selector-list-item/datapoint-selector-list-item.component.mjs +3 -3
  139. package/esm2022/datapoints-export-selector/datapoints-export-selector-modal/datapoints-export-selector-file-exporter/datapoints-exports-selector-file-types/datapoints-exports-selector-file-types.component.mjs +3 -3
  140. package/esm2022/datapoints-export-selector/datapoints-export-selector.component.mjs +3 -3
  141. package/esm2022/device-list/add-smart-group.component.mjs +3 -3
  142. package/esm2022/echart/c8y-ngx-components-echart.mjs +5 -0
  143. package/esm2022/echart/chart-alerts/chart-alerts.component.mjs +16 -0
  144. package/esm2022/echart/charts.component.mjs +560 -0
  145. package/esm2022/echart/index.mjs +5 -0
  146. package/esm2022/echart/models/c8y-ngx-components-echart-models.mjs +5 -0
  147. package/esm2022/echart/models/chart.model.mjs +2 -0
  148. package/esm2022/echart/models/datapoints-graph-widget.model.mjs +17 -0
  149. package/esm2022/echart/models/index.mjs +4 -0
  150. package/esm2022/echart/models/svg-icons.model.mjs +22 -0
  151. package/esm2022/echart/services/chart-alarms.service.mjs +58 -0
  152. package/esm2022/echart/services/chart-events.service.mjs +44 -0
  153. package/esm2022/echart/services/chart-realtime.service.mjs +193 -0
  154. package/esm2022/echart/services/chart-types.service.mjs +102 -0
  155. package/esm2022/echart/services/custom-measurements.service.mjs +52 -0
  156. package/esm2022/echart/services/echarts-options.service.mjs +857 -0
  157. package/esm2022/echart/services/y-axis.service.mjs +150 -0
  158. package/esm2022/icon-selector/icons/platform/index.mjs +10 -8
  159. package/esm2022/interval-picker/interval-picker.component.mjs +3 -3
  160. package/esm2022/interval-picker/interval-picker.model.mjs +1 -1
  161. package/esm2022/report-dashboard/index.mjs +2 -1
  162. package/esm2022/time-context/c8y-ngx-components-time-context.mjs +5 -0
  163. package/esm2022/time-context/index.mjs +2 -0
  164. package/esm2022/time-context/time-context.component.mjs +217 -0
  165. package/esm2022/time-context/time-context.service.mjs +83 -0
  166. package/esm2022/translation-editor/lazy/translation-editor/translation-editor.component.mjs +6 -5
  167. package/esm2022/widgets/cockpit-exports/index.mjs +8 -1
  168. package/esm2022/widgets/definitions/datapoints-graph/c8y-ngx-components-widgets-definitions-datapoints-graph.mjs +5 -0
  169. package/esm2022/widgets/definitions/datapoints-graph/index.mjs +31 -0
  170. package/esm2022/widgets/definitions/index.mjs +3 -2
  171. package/esm2022/widgets/implementations/datapoints-graph/c8y-ngx-components-widgets-implementations-datapoints-graph.mjs +5 -0
  172. package/esm2022/widgets/implementations/datapoints-graph/datapoints-graph-config/datapoints-graph-widget-config.component.mjs +239 -0
  173. package/esm2022/widgets/implementations/datapoints-graph/datapoints-graph-view/datapoints-graph-widget-view.component.mjs +241 -0
  174. package/esm2022/widgets/implementations/datapoints-graph/index.mjs +3 -0
  175. package/fesm2022/c8y-ngx-components-alarm-event-selector.mjs +80 -28
  176. package/fesm2022/c8y-ngx-components-alarm-event-selector.mjs.map +1 -1
  177. package/fesm2022/c8y-ngx-components-alarms.mjs +2 -2
  178. package/fesm2022/c8y-ngx-components-alarms.mjs.map +1 -1
  179. package/fesm2022/c8y-ngx-components-datapoint-explorer-view.mjs +658 -0
  180. package/fesm2022/c8y-ngx-components-datapoint-explorer-view.mjs.map +1 -0
  181. package/fesm2022/c8y-ngx-components-datapoint-explorer.mjs +72 -0
  182. package/fesm2022/c8y-ngx-components-datapoint-explorer.mjs.map +1 -0
  183. package/fesm2022/c8y-ngx-components-datapoint-selector.mjs +4 -4
  184. package/fesm2022/c8y-ngx-components-datapoint-selector.mjs.map +1 -1
  185. package/fesm2022/c8y-ngx-components-datapoints-export-selector.mjs +4 -4
  186. package/fesm2022/c8y-ngx-components-datapoints-export-selector.mjs.map +1 -1
  187. package/fesm2022/c8y-ngx-components-device-list.mjs +2 -2
  188. package/fesm2022/c8y-ngx-components-device-list.mjs.map +1 -1
  189. package/fesm2022/c8y-ngx-components-echart-models.mjs +46 -0
  190. package/fesm2022/c8y-ngx-components-echart-models.mjs.map +1 -0
  191. package/fesm2022/c8y-ngx-components-echart.mjs +2023 -0
  192. package/fesm2022/c8y-ngx-components-echart.mjs.map +1 -0
  193. package/fesm2022/c8y-ngx-components-icon-selector-icons-platform.mjs +9 -7
  194. package/fesm2022/c8y-ngx-components-icon-selector-icons-platform.mjs.map +1 -1
  195. package/fesm2022/c8y-ngx-components-interval-picker.mjs +2 -2
  196. package/fesm2022/c8y-ngx-components-interval-picker.mjs.map +1 -1
  197. package/fesm2022/c8y-ngx-components-report-dashboard.mjs +1 -1
  198. package/fesm2022/c8y-ngx-components-time-context.mjs +300 -0
  199. package/fesm2022/c8y-ngx-components-time-context.mjs.map +1 -0
  200. package/fesm2022/c8y-ngx-components-translation-editor-lazy.mjs +5 -4
  201. package/fesm2022/c8y-ngx-components-translation-editor-lazy.mjs.map +1 -1
  202. package/fesm2022/c8y-ngx-components-widgets-cockpit-exports.mjs +7 -0
  203. package/fesm2022/c8y-ngx-components-widgets-cockpit-exports.mjs.map +1 -1
  204. package/fesm2022/c8y-ngx-components-widgets-definitions-datapoints-graph.mjs +38 -0
  205. package/fesm2022/c8y-ngx-components-widgets-definitions-datapoints-graph.mjs.map +1 -0
  206. package/fesm2022/c8y-ngx-components-widgets-definitions.mjs +2 -1
  207. package/fesm2022/c8y-ngx-components-widgets-definitions.mjs.map +1 -1
  208. package/fesm2022/c8y-ngx-components-widgets-implementations-datapoints-graph.mjs +467 -0
  209. package/fesm2022/c8y-ngx-components-widgets-implementations-datapoints-graph.mjs.map +1 -0
  210. package/fesm2022/c8y-ngx-components.mjs +429 -277
  211. package/fesm2022/c8y-ngx-components.mjs.map +1 -1
  212. package/icon-selector/icons/index.d.ts +1 -1
  213. package/icon-selector/icons/platform/index.d.ts +2 -2
  214. package/icon-selector/icons/platform/index.d.ts.map +1 -1
  215. package/interval-picker/interval-picker.component.d.ts.map +1 -1
  216. package/interval-picker/interval-picker.model.d.ts.map +1 -1
  217. package/locales/de.po +206 -279
  218. package/locales/es.po +206 -279
  219. package/locales/fr.po +206 -279
  220. package/locales/ja_JP.po +196 -279
  221. package/locales/ko.po +455 -444
  222. package/locales/locales.pot +190 -272
  223. package/locales/nl.po +206 -279
  224. package/locales/pl.po +206 -279
  225. package/locales/pt_BR.po +206 -279
  226. package/locales/zh_CN.po +450 -443
  227. package/locales/zh_TW.po +452 -445
  228. package/package.json +1 -1
  229. package/report-dashboard/index.d.ts +1 -0
  230. package/report-dashboard/index.d.ts.map +1 -1
  231. package/time-context/c8y-ngx-components-time-context.d.ts.map +1 -0
  232. package/time-context/index.d.ts +2 -0
  233. package/time-context/index.d.ts.map +1 -0
  234. package/time-context/time-context.component.d.ts +61 -0
  235. package/time-context/time-context.component.d.ts.map +1 -0
  236. package/time-context/time-context.service.d.ts +25 -0
  237. package/time-context/time-context.service.d.ts.map +1 -0
  238. package/translation-editor/lazy/translation-editor/translation-editor.component.d.ts.map +1 -1
  239. package/widgets/cockpit-exports/index.d.ts +6 -0
  240. package/widgets/cockpit-exports/index.d.ts.map +1 -1
  241. package/widgets/definitions/datapoints-graph/c8y-ngx-components-widgets-definitions-datapoints-graph.d.ts.map +1 -0
  242. package/widgets/definitions/datapoints-graph/index.d.ts +16 -0
  243. package/widgets/definitions/datapoints-graph/index.d.ts.map +1 -0
  244. package/widgets/definitions/index.d.ts +1 -0
  245. package/widgets/definitions/index.d.ts.map +1 -1
  246. package/widgets/implementations/datapoints-graph/c8y-ngx-components-widgets-implementations-datapoints-graph.d.ts.map +1 -0
  247. package/widgets/implementations/datapoints-graph/datapoints-graph-config/datapoints-graph-widget-config.component.d.ts +43 -0
  248. package/widgets/implementations/datapoints-graph/datapoints-graph-config/datapoints-graph-widget-config.component.d.ts.map +1 -0
  249. package/widgets/implementations/datapoints-graph/datapoints-graph-view/datapoints-graph-widget-view.component.d.ts +54 -0
  250. package/widgets/implementations/datapoints-graph/datapoints-graph-view/datapoints-graph-widget-view.component.d.ts.map +1 -0
  251. package/widgets/implementations/datapoints-graph/index.d.ts +3 -0
  252. package/widgets/implementations/datapoints-graph/index.d.ts.map +1 -0
@@ -0,0 +1,857 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ import { Injectable } from '@angular/core';
3
+ import { DatePipe } from '@c8y/ngx-components';
4
+ import { YAxisService } from './y-axis.service';
5
+ import { ChartTypesService } from './chart-types.service';
6
+ import { AlarmStatus } from '@c8y/client';
7
+ import { ICONS_MAP } from '../models/svg-icons.model';
8
+ import { Router } from '@angular/router';
9
+ import { AlarmSeverityToIconPipe, AlarmSeverityToLabelPipe } from '@c8y/ngx-components/alarms';
10
+ import { INTERVALS } from '@c8y/ngx-components/interval-picker';
11
+ import * as i0 from "@angular/core";
12
+ import * as i1 from "@c8y/ngx-components";
13
+ import * as i2 from "./y-axis.service";
14
+ import * as i3 from "./chart-types.service";
15
+ import * as i4 from "@c8y/ngx-components/alarms";
16
+ import * as i5 from "@angular/router";
17
+ const INDEX_HTML = '/index.html';
18
+ export class EchartsOptionsService {
19
+ constructor(datePipe, yAxisService, chartTypesService, severityIconPipe, severityLabelPipe, router) {
20
+ this.datePipe = datePipe;
21
+ this.yAxisService = yAxisService;
22
+ this.chartTypesService = chartTypesService;
23
+ this.severityIconPipe = severityIconPipe;
24
+ this.severityLabelPipe = severityLabelPipe;
25
+ this.router = router;
26
+ this.TOOLTIP_WIDTH = 300;
27
+ }
28
+ getChartOptions(datapointsWithValues, timeRange, showSplitLines, events, alarms, displayOptions, selectedTimeRange, aggregatedDatapoints, sliderZoomUsed = false) {
29
+ const yAxis = this.yAxisService.getYAxis(datapointsWithValues, {
30
+ showSplitLines: showSplitLines.YAxis,
31
+ mergeMatchingDatapoints: displayOptions.mergeMatchingDatapoints,
32
+ showLabelAndUnit: displayOptions.showLabelAndUnit
33
+ });
34
+ const leftAxis = yAxis.filter(yx => yx.position === 'left');
35
+ const gridLeft = leftAxis.length ? leftAxis.length * this.yAxisService.Y_AXIS_OFFSET : 16;
36
+ const rightAxis = yAxis.filter(yx => yx.position === 'right');
37
+ const gridRight = rightAxis.length ? rightAxis.length * this.yAxisService.Y_AXIS_OFFSET : 16;
38
+ let intervalInMs = this.calculateExtendedIntervalInMs(selectedTimeRange?.interval || timeRange.interval || 'hours', selectedTimeRange || timeRange);
39
+ if (sliderZoomUsed) {
40
+ intervalInMs = this.calculateExtendedIntervalInMs(timeRange.interval || 'hours', timeRange);
41
+ }
42
+ return {
43
+ grid: {
44
+ containLabel: false, // axis labels are not taken into account to calculate graph grid
45
+ left: gridLeft,
46
+ top: 16,
47
+ right: gridRight,
48
+ bottom: 68
49
+ },
50
+ dataZoom: [
51
+ {
52
+ type: 'inside',
53
+ // TODO: use 'none' only when this bug is fixed https://github.com/apache/echarts/issues/17858
54
+ filterMode: datapointsWithValues.some(dp => dp.lineType === 'bars') ? 'filter' : 'none',
55
+ zoomOnMouseWheel: true,
56
+ startValue: selectedTimeRange
57
+ ? selectedTimeRange.dateFrom.valueOf()
58
+ : timeRange.dateFrom.valueOf(),
59
+ endValue: selectedTimeRange
60
+ ? selectedTimeRange.dateTo.valueOf()
61
+ : timeRange.dateTo.valueOf()
62
+ },
63
+ {
64
+ type: 'slider',
65
+ show: displayOptions.showSlider,
66
+ bottom: 8,
67
+ realtime: false
68
+ }
69
+ ], // on realtime, 'none' will cause extending chart line to left edge of the chart
70
+ animation: false,
71
+ toolbox: {
72
+ show: true,
73
+ itemSize: 0, // toolbox is needed for zooming in action, but we provide our own buttons
74
+ feature: {
75
+ dataZoom: {
76
+ yAxisIndex: 'none'
77
+ }
78
+ }
79
+ },
80
+ tooltip: {
81
+ trigger: 'axis',
82
+ axisPointer: {
83
+ type: 'cross',
84
+ snap: true
85
+ },
86
+ backgroundColor: 'rgba(255, 255, 255, 0.9)',
87
+ formatter: this.getTooltipFormatter(),
88
+ appendToBody: true,
89
+ position: this.tooltipPosition(),
90
+ transitionDuration: 0
91
+ },
92
+ legend: {
93
+ show: false
94
+ },
95
+ xAxis: {
96
+ min: new Date(timeRange.dateFrom).valueOf() - intervalInMs,
97
+ max: timeRange.dateTo,
98
+ type: 'time',
99
+ animation: false,
100
+ axisPointer: {
101
+ label: {
102
+ show: false
103
+ }
104
+ },
105
+ axisLine: {
106
+ // align X axis to 0 of Y axis of datapoint with lineType 'bars'
107
+ onZeroAxisIndex: datapointsWithValues.findIndex(dp => dp.lineType === 'bars')
108
+ },
109
+ axisLabel: {
110
+ hideOverlap: true,
111
+ borderWidth: 2, // as there is no margin for labels spacing, transparent border is a workaround
112
+ borderColor: 'transparent'
113
+ },
114
+ splitLine: {
115
+ show: showSplitLines.XAxis,
116
+ lineStyle: { opacity: 0.8, type: 'dashed', width: 2 }
117
+ }
118
+ },
119
+ yAxis,
120
+ series: [
121
+ ...this.getAggregatedSeries(aggregatedDatapoints || []).filter(series => series !== undefined),
122
+ ...this.getChartSeries(datapointsWithValues, events, alarms, displayOptions)
123
+ ]
124
+ };
125
+ }
126
+ calculateExtendedIntervalInMs(interval, selectedTimeRange) {
127
+ let intervalInMs = INTERVALS.find(i => i.id === interval).timespanInMs;
128
+ switch (interval) {
129
+ case 'minutes':
130
+ intervalInMs = INTERVALS.find(i => i.id === interval).timespanInMs * 60;
131
+ break;
132
+ case 'hours':
133
+ intervalInMs = INTERVALS.find(i => i.id === interval).timespanInMs * 24;
134
+ break;
135
+ case 'days':
136
+ intervalInMs = INTERVALS.find(i => i.id === interval).timespanInMs * 28;
137
+ break;
138
+ case 'weeks':
139
+ intervalInMs = INTERVALS.find(i => i.id === interval).timespanInMs * 12;
140
+ break;
141
+ case 'months':
142
+ intervalInMs = INTERVALS.find(i => i.id === interval).timespanInMs * 12;
143
+ break;
144
+ case 'custom':
145
+ intervalInMs =
146
+ (new Date(selectedTimeRange.dateTo).valueOf() -
147
+ new Date(selectedTimeRange.dateFrom).valueOf()) *
148
+ 12;
149
+ break;
150
+ default:
151
+ intervalInMs = INTERVALS.find(i => i.id === interval).timespanInMs;
152
+ break;
153
+ }
154
+ return intervalInMs;
155
+ }
156
+ getAggregatedSeries(aggregatedDatapoints) {
157
+ const series = [];
158
+ aggregatedDatapoints.forEach((dp, idx) => {
159
+ const renderType = dp.renderType || 'min';
160
+ if (renderType === 'area') {
161
+ series.push(this.getSingleSeries(dp, 'min', idx, true, 'aggr'));
162
+ series.push(this.getSingleSeries(dp, 'max', idx, true, 'aggr'));
163
+ }
164
+ else {
165
+ series.push(this.getSingleSeries(dp, renderType, idx, false, 'aggr'));
166
+ }
167
+ });
168
+ series.forEach((s) => {
169
+ s.datapointId = 'aggregated';
170
+ s.typeOfSeries = 'fake';
171
+ s.itemStyle = {
172
+ ...s.itemStyle,
173
+ opacity: 0
174
+ };
175
+ s.lineStyle = {
176
+ ...s.lineStyle,
177
+ opacity: 0
178
+ };
179
+ });
180
+ return [series[0]];
181
+ }
182
+ /**
183
+ * This method is used to get the series for alarms and events.
184
+ * @param dp - The data point.
185
+ * @param renderType - The render type.
186
+ * @param isMinMaxChart - If the chart is min max chart.
187
+ * @param items - All alarms or events which should be displayed on the chart.
188
+ * @param itemType - The item type.
189
+ * @param id - The id of the device
190
+ */
191
+ getAlarmOrEventSeries(dp, renderType, isMinMaxChart = false, items = [], itemType = 'alarm', displayOptions = { displayMarkedLine: true, displayMarkedPoint: true }, id, idx, realtime) {
192
+ if (!items.length) {
193
+ return [];
194
+ }
195
+ if (!displayOptions.displayMarkedLine && !displayOptions.displayMarkedPoint) {
196
+ return [];
197
+ }
198
+ //filter items that are not __hidden
199
+ const filteredItems = items.filter(item => !item['__hidden']);
200
+ const itemsByType = this.groupByType(filteredItems, 'type');
201
+ const isAlarm = itemType === 'alarm';
202
+ return Object.entries(itemsByType).flatMap(([type, itemsOfType]) => {
203
+ // Main series data
204
+ const mainData = itemsOfType.map(item => [item.creationTime, null, 'markLineFlag']);
205
+ // Is a specific datapoint template selected for this alarm/event type?
206
+ let isDpTemplateSelected = false;
207
+ // MarkPoint data
208
+ const markPointData = itemsOfType.reduce((acc, item) => {
209
+ isDpTemplateSelected =
210
+ item['selectedDatapoint'] &&
211
+ dp['__target'] &&
212
+ item['selectedDatapoint']['fragment'] === dp['fragment'] &&
213
+ item['selectedDatapoint']['series'] === dp['series'] &&
214
+ item['selectedDatapoint']['target'] === dp['__target']['id'];
215
+ if (dp.__target?.id === item.source.id) {
216
+ const isCleared = isAlarm && item.status === AlarmStatus.CLEARED;
217
+ const isEvent = !isAlarm;
218
+ return acc.concat(this.createMarkPoint(item, dp, isCleared, isEvent, realtime));
219
+ }
220
+ else {
221
+ if (!item.creationTime) {
222
+ return [];
223
+ }
224
+ return acc.concat([
225
+ {
226
+ coord: [item.creationTime, null],
227
+ name: item.type,
228
+ itemType: item.type,
229
+ itemStyle: { color: item['color'] }
230
+ }
231
+ ]);
232
+ }
233
+ }, []);
234
+ // Construct series with markPoint
235
+ const seriesWithMarkPoint = {
236
+ id: `${type}/${dp.__target?.id}+${id ? id : ''}-markPoint`,
237
+ name: `${type}-markPoint`,
238
+ typeOfSeries: itemType,
239
+ data: mainData,
240
+ isDpTemplateSelected,
241
+ position: 'bottom',
242
+ silent: true,
243
+ markPoint: {
244
+ showSymbol: true,
245
+ symbolKeepAspect: true,
246
+ data: markPointData
247
+ },
248
+ yAxisIndex: idx,
249
+ ...this.chartTypesService.getSeriesOptions(dp, isMinMaxChart, renderType)
250
+ };
251
+ const markLineData = this.createMarkLine(itemsOfType);
252
+ // Construct series with markLine
253
+ const seriesWithMarkLine = {
254
+ id: `${type}/${dp.__target?.id}+${id ? id : ''}-markLine`,
255
+ name: `${type}-markLine`,
256
+ typeOfSeries: itemType,
257
+ isDpTemplateSelected,
258
+ data: mainData,
259
+ markLine: {
260
+ showSymbol: false,
261
+ symbol: ['none', 'none'], // no symbol at the start/end of the line
262
+ data: markLineData
263
+ },
264
+ ...this.chartTypesService.getSeriesOptions(dp, isMinMaxChart, renderType)
265
+ };
266
+ //depending on the options return only the required series
267
+ if (displayOptions.displayMarkedLine && displayOptions.displayMarkedPoint) {
268
+ return [seriesWithMarkLine, seriesWithMarkPoint];
269
+ }
270
+ else if (displayOptions.displayMarkedLine) {
271
+ return [seriesWithMarkLine];
272
+ }
273
+ else if (displayOptions.displayMarkedPoint) {
274
+ return [seriesWithMarkPoint];
275
+ }
276
+ else {
277
+ return null;
278
+ }
279
+ });
280
+ }
281
+ /**
282
+ * This method is used to get tooltip formatter for alarms and events.
283
+ * @param tooltipParams - The tooltip parameters.
284
+ * @param params - The parameters data.
285
+ * @param allEvents - All events.
286
+ * @param allAlarms - All alarms.
287
+ * @returns The formatted string for the tooltip.
288
+ */
289
+ getTooltipFormatterForAlarmAndEvents(tooltipParams, params, allEvents, allAlarms) {
290
+ if (!Array.isArray(tooltipParams)) {
291
+ return '';
292
+ }
293
+ const XAxisValue = tooltipParams[0].data[0];
294
+ const YAxisReadings = [];
295
+ const allSeries = this.echartsInstance?.getOption()['series'];
296
+ // filter out alarm and event series
297
+ const allDataPointSeries = allSeries.filter(series => series['typeOfSeries'] !== 'alarm' && series['typeOfSeries'] !== 'event');
298
+ this.processSeries(allDataPointSeries, XAxisValue, YAxisReadings);
299
+ // find event and alarm of the same type as the hovered markedLine or markedPoint
300
+ const event = allEvents.find(e => e.type === params.data.itemType);
301
+ const alarm = allAlarms.find(a => a.type === params.data.itemType);
302
+ let value = '';
303
+ if (event) {
304
+ value = this.processEvent(event);
305
+ }
306
+ if (alarm) {
307
+ this.processAlarm(alarm).then(alarmVal => {
308
+ value = alarmVal;
309
+ YAxisReadings.push(value);
310
+ const options = this.echartsInstance?.getOption();
311
+ if (!options.tooltip || !Array.isArray(options.tooltip)) {
312
+ return;
313
+ }
314
+ const updatedOptions = {
315
+ tooltip: options['tooltip'][0]
316
+ };
317
+ if (!updatedOptions.tooltip) {
318
+ return;
319
+ }
320
+ updatedOptions.tooltip.formatter = `<div style="width: ${this.TOOLTIP_WIDTH}px">${YAxisReadings.join('')}</div>`;
321
+ updatedOptions.tooltip.transitionDuration = 0;
322
+ updatedOptions.tooltip.position = this.tooltipPosition();
323
+ this.echartsInstance?.setOption(updatedOptions);
324
+ return;
325
+ });
326
+ }
327
+ YAxisReadings.push(value);
328
+ return `<div style="width: 300px">${YAxisReadings.join('')}</div>`;
329
+ }
330
+ tooltipPosition() {
331
+ let lastPositionOfTooltip = {};
332
+ if (this.tooltipPositionCallback) {
333
+ return this.tooltipPositionCallback;
334
+ }
335
+ this.tooltipPositionCallback = (point, // position of mouse in chart [X, Y]; 0,0 is top left corner
336
+ _, // tooltip data
337
+ dom, // tooltip element
338
+ __, size // size of chart
339
+ ) => {
340
+ const offset = 10;
341
+ const [mouseX, mouseY] = point;
342
+ const chartWidth = size?.viewSize[0] || 0;
343
+ const chartHeight = size?.viewSize[1] || 0;
344
+ const tooltipWidth = size?.contentSize[0] || 0;
345
+ const tooltipHeight = size?.contentSize[1] || 0;
346
+ const tooltipRect = dom?.getBoundingClientRect();
347
+ const tooltipOverflowsBottomEdge = tooltipRect.bottom > window.innerHeight;
348
+ const tooltipOverflowsRightEdge = tooltipRect.right > window.innerWidth;
349
+ const tooltipWouldOverflowBottomEdgeOnPositionChange = !lastPositionOfTooltip.top &&
350
+ tooltipRect.bottom + 2 * offset + tooltipHeight > window.innerHeight;
351
+ const tooltipWouldOverflowRightEdgeOnPositionChange = !lastPositionOfTooltip.left &&
352
+ tooltipRect.right + 2 * offset + tooltipWidth > window.innerWidth;
353
+ let verticalPosition = {
354
+ top: mouseY + offset
355
+ };
356
+ let horizontalPosition = {
357
+ left: mouseX + offset
358
+ };
359
+ if (tooltipOverflowsBottomEdge || tooltipWouldOverflowBottomEdgeOnPositionChange) {
360
+ verticalPosition = {
361
+ bottom: chartHeight - mouseY + offset
362
+ };
363
+ }
364
+ if (tooltipOverflowsRightEdge || tooltipWouldOverflowRightEdgeOnPositionChange) {
365
+ horizontalPosition = {
366
+ right: chartWidth - mouseX + offset
367
+ };
368
+ }
369
+ lastPositionOfTooltip = {
370
+ ...verticalPosition,
371
+ ...horizontalPosition
372
+ };
373
+ return lastPositionOfTooltip;
374
+ };
375
+ return this.tooltipPositionCallback;
376
+ }
377
+ /**
378
+ * This method is used to add the data point info to the tooltip.
379
+ * @param allDataPointSeries - All the data point series.
380
+ * @param XAxisValue - The X Axis value.
381
+ * @param YAxisReadings - The Y Axis readings.
382
+ */
383
+ processSeries(allDataPointSeries, XAxisValue, YAxisReadings) {
384
+ allDataPointSeries.forEach((series) => {
385
+ let value = '';
386
+ if (series.id.endsWith('/min')) {
387
+ value = this.processMinSeries(series, allDataPointSeries, XAxisValue);
388
+ }
389
+ else if (!series.id.endsWith('/max')) {
390
+ value = this.processRegularSeries(series, XAxisValue);
391
+ }
392
+ if (value) {
393
+ YAxisReadings.push(`<div class="d-flex a-i-center p-b-8"><span class='dlt-c8y-icon-circle m-r-4' style='color: ${series.itemStyle.color};'></span>` + // color circle
394
+ `<strong>${series.datapointLabel}</strong></div>` + // name
395
+ `${value}` // single value or min-max range
396
+ );
397
+ }
398
+ });
399
+ }
400
+ /**
401
+ * This method is used to process the min series.
402
+ * @param series - The series.
403
+ * @param allDataPointSeries - All the data point series.
404
+ * @param XAxisValue - The X Axis value.
405
+ * @returns The processed value.
406
+ */
407
+ processMinSeries(series, allDataPointSeries, XAxisValue) {
408
+ const minValue = this.findValueForExactOrEarlierTimestamp(series.data, XAxisValue);
409
+ if (!minValue) {
410
+ return '';
411
+ }
412
+ const maxSeries = allDataPointSeries.find(s => s['id'] === series.id.replace('/min', '/max'));
413
+ const maxValue = this.findValueForExactOrEarlierTimestamp(maxSeries?.['data'], XAxisValue);
414
+ return (`<div class="d-flex a-i-center separator-top p-t-8 p-b-8"><label class="text-12 m-r-8 m-b-0">${this.datePipe.transform(minValue[0])}</label>` +
415
+ `<span class="m-l-auto text-12">${minValue[1]} — ${maxValue?.[1]}` +
416
+ (series.datapointUnit ? ` ${series.datapointUnit}` : '') +
417
+ `</span></div>`);
418
+ }
419
+ /**
420
+ * This method is used to process the regular series.
421
+ * @param series - The series.
422
+ * @param XAxisValue - The X Axis value.
423
+ * @returns The processed value.
424
+ */
425
+ processRegularSeries(series, XAxisValue) {
426
+ const seriesValue = this.findValueForExactOrEarlierTimestamp(series.data, XAxisValue);
427
+ if (!seriesValue) {
428
+ return '';
429
+ }
430
+ return (`<div class="d-flex a-i-center p-t-8 p-b-8 separator-top">` +
431
+ `<label class="m-b-0 m-r-8 text-12">${this.datePipe.transform(seriesValue[0])}</label><span class="m-l-auto text-12">` +
432
+ seriesValue[1]?.toString() +
433
+ (series.datapointUnit ? ` ${series.datapointUnit}` : '') +
434
+ `</span></div>`);
435
+ }
436
+ /**
437
+ * This method is used to process the event tooltip.
438
+ * @param event - The event object.
439
+ * @returns The processed value.
440
+ */
441
+ processEvent(event) {
442
+ let value = `<ul class="list-unstyled small separator-top">`;
443
+ value += `<li class="p-t-4 p-b-4 d-flex separator-bottom text-no-wrap"><label class="small m-b-0 m-r-8">Event type</label><code class="m-l-auto">${event.type}</code></li>`;
444
+ value += `<li class="p-t-4 p-b-4 d-flex separator-bottom text-no-wrap"><label class="small m-b-0 m-r-8">Event text</label><span class="m-l-auto">${event.text}<span></li>`;
445
+ value += `<li class="p-t-4 p-b-4 d-flex separator-bottom text-no-wrap"><label class="small m-b-0 m-r-8">Last update</label><span class="m-l-auto">${this.datePipe.transform(event['lastUpdated'])}<span></li>`;
446
+ value += `</ul>`;
447
+ return value;
448
+ }
449
+ /**
450
+ * This method is used to process the alarm tooltip.
451
+ * @param alarm - The alarm object.
452
+ * @returns The processed value.
453
+ */
454
+ async processAlarm(alarm) {
455
+ let value = `<ul class="list-unstyled small separator-top m-0">`;
456
+ value += `<li class="p-t-4 p-b-4 d-flex a-i-center separator-bottom text-no-wrap"><label class="text-label-small m-b-0 m-r-8">Alarm Severity</label>`;
457
+ value += `<span class="small d-inline-flex a-i-center gap-4 m-l-auto"><i class="stroked-icon icon-14 status dlt-c8y-icon-${this.severityIconPipe.transform(alarm.severity)} ${alarm.severity.toLowerCase()}" > </i> ${this.severityLabelPipe.transform(alarm.severity)} </span></li>`;
458
+ value += `<li class="p-t-4 p-b-4 d-flex separator-bottom text-no-wrap"><label class="text-label-small m-b-0 m-r-8">Alarm Type</label><span class="small m-l-auto"><code>${alarm.type}</code></span></li>`;
459
+ value += `<li class="p-t-4 p-b-4 d-flex separator-bottom text-no-wrap"><label class="text-label-small m-b-0 m-r-8">Message</label><span class="small m-l-auto" style="overflow: hidden; text-overflow: ellipsis;" title="${alarm.text}">${alarm.text}</span></li>`;
460
+ value += `<li class="p-t-4 p-b-4 d-flex separator-bottom text-no-wrap"><label class="text-label-small m-b-0 m-r-8">Last Updated</label><span class="small m-l-auto">${this.datePipe.transform(alarm['lastUpdated'])}</span></li>`;
461
+ const exists = await this.alarmRouteExists();
462
+ if (exists) {
463
+ const currentUrl = window.location.href;
464
+ const baseUrlIndex = currentUrl.indexOf(INDEX_HTML);
465
+ const baseUrl = currentUrl.substring(0, baseUrlIndex + INDEX_HTML.length);
466
+ value += `<li class="p-t-4 p-b-4 d-flex separator-bottom text-no-wrap"><label class="text-label-small m-b-0 m-r-8">Link</label><span class="small m-l-auto"><a href="${baseUrl}#/alarms/${alarm.id}">Alarm Details</a></span></li>`;
467
+ }
468
+ value += `<li class="p-t-4 p-b-4 d-flex text-no-wrap"><label class="text-label-small m-b-0 m-r-8">Alarm count</label><span class="small m-l-auto"><span class="badge badge-info">${alarm.count}</span></span></li>`;
469
+ value += `</ul>`;
470
+ return value;
471
+ }
472
+ async alarmRouteExists() {
473
+ const exists = this.router.config.some(route => {
474
+ return `${route.path}` === 'alarms';
475
+ });
476
+ return exists;
477
+ }
478
+ getChartSeries(datapointsWithValues, events, alarms, displayOptions) {
479
+ const series = [];
480
+ let eventSeries = [];
481
+ let alarmSeries = [];
482
+ datapointsWithValues.forEach((dp, idx) => {
483
+ const renderType = dp.renderType || 'min';
484
+ if (renderType === 'area') {
485
+ series.push(this.getSingleSeries(dp, 'min', idx, true));
486
+ series.push(this.getSingleSeries(dp, 'max', idx, true));
487
+ }
488
+ else {
489
+ series.push(this.getSingleSeries(dp, renderType, idx, false));
490
+ }
491
+ const newEventSeries = this.getAlarmOrEventSeries(dp, renderType, false, events, 'event', displayOptions, null, idx);
492
+ const newAlarmSeries = this.getAlarmOrEventSeries(dp, renderType, false, alarms, 'alarm', displayOptions, null, idx);
493
+ eventSeries = [...eventSeries, ...newEventSeries];
494
+ alarmSeries = [...alarmSeries, ...newAlarmSeries];
495
+ });
496
+ const deduplicateFilterCallback = (obj1, i, arr) => {
497
+ const duplicates = arr.filter(obj2 => obj1['id'] === obj2['id'] && i !== arr.indexOf(obj2));
498
+ if (duplicates.length > 0) {
499
+ return obj1['isDpTemplateSelected'];
500
+ }
501
+ return true;
502
+ };
503
+ const deduplicateFilterCallbackFallback = (obj1, i, arr) => arr.findIndex(obj2 => obj2['id'] === obj1['id']) === i;
504
+ let deduplicatedEvents = eventSeries.filter(deduplicateFilterCallback);
505
+ let deduplicatedAlarms = alarmSeries.filter(deduplicateFilterCallback);
506
+ if (deduplicatedAlarms.length === 0) {
507
+ deduplicatedAlarms = alarmSeries.filter(deduplicateFilterCallbackFallback);
508
+ }
509
+ if (deduplicatedEvents.length === 0) {
510
+ deduplicatedEvents = eventSeries.filter(deduplicateFilterCallbackFallback);
511
+ }
512
+ return [...series, ...deduplicatedEvents, ...deduplicatedAlarms];
513
+ }
514
+ groupByType(items, typeField) {
515
+ return items.reduce((grouped, item) => {
516
+ (grouped[item[typeField]] = grouped[item[typeField]] || []).push(item);
517
+ return grouped;
518
+ }, {});
519
+ }
520
+ /**
521
+ * This method interpolates between two data points. The goal is to place the markPoint on the chart in the right place.
522
+ * @param dpValuesArray array of data points
523
+ * @param targetTime time of the alarm or event
524
+ * @returns interpolated data point
525
+ */
526
+ interpolateBetweenTwoDps(dpValuesArray, targetTime) {
527
+ let maxValue;
528
+ let minValue;
529
+ return dpValuesArray.reduce((acc, curr, idx, arr) => {
530
+ if (new Date(curr.time).getTime() <= targetTime) {
531
+ if (idx === arr.length - 1) {
532
+ return {
533
+ time: targetTime,
534
+ values: [{ min: minValue, max: maxValue }]
535
+ };
536
+ }
537
+ const nextDp = arr[idx + 1];
538
+ if (new Date(nextDp.time).getTime() >= targetTime) {
539
+ const timeDiff = new Date(nextDp.time).getTime() - new Date(curr.time).getTime();
540
+ const targetTimeDiff = targetTime - new Date(curr.time).getTime();
541
+ const minValueDiff = nextDp.values[0]?.min - curr.values[0]?.min;
542
+ const maxValueDiff = nextDp.values[0]?.max - curr.values[0]?.max;
543
+ minValue = curr.values[0]?.min + (minValueDiff * targetTimeDiff) / timeDiff;
544
+ maxValue = curr.values[0]?.max + (maxValueDiff * targetTimeDiff) / timeDiff;
545
+ return {
546
+ time: targetTime,
547
+ values: [{ min: minValue, max: maxValue }]
548
+ };
549
+ }
550
+ }
551
+ return acc;
552
+ });
553
+ }
554
+ getClosestDpValueToTargetTime(dpValuesArray, targetTime) {
555
+ return dpValuesArray.reduce((prev, curr) =>
556
+ //should take the value closest to the target time, for realtime the current time would always change
557
+ Math.abs(new Date(curr.time).getTime() - targetTime) <
558
+ Math.abs(new Date(prev.time).getTime() - targetTime)
559
+ ? curr
560
+ : prev);
561
+ }
562
+ /**
563
+ * This method creates a markPoint on the chart which represents the icon of the alarm or event.
564
+ * @param item Single alarm or event
565
+ * @param dp Data point
566
+ * @param isCleared If the alarm is cleared in case of alarm
567
+ * @param isEvent If the item is an event
568
+ * @param realtime If the chart is in realtime mode
569
+ * @returns MarkPointDataItemOption[]
570
+ */
571
+ createMarkPoint(item, dp, isCleared, isEvent, realtime) {
572
+ // check if dp.values object is empty
573
+ if (!item.creationTime || Object.keys(dp.values).length === 0) {
574
+ return [];
575
+ }
576
+ const dpValuesArray = Object.entries(dp.values).map(([time, values]) => ({
577
+ time: new Date(time).getTime(),
578
+ values
579
+ }));
580
+ const creationTime = new Date(item.creationTime).getTime();
581
+ const lastUpdatedTime = new Date(item['lastUpdated']).getTime();
582
+ let coordCreationTime;
583
+ let coordLastUpdatedTime;
584
+ if (realtime) {
585
+ const lastValue = dpValuesArray[dpValuesArray.length - 1];
586
+ coordCreationTime = [
587
+ item.creationTime,
588
+ lastValue?.values[0]?.min ?? lastValue?.values[1] ?? null
589
+ ];
590
+ coordLastUpdatedTime = [
591
+ item['lastUpdated'],
592
+ lastValue?.values[0]?.min ?? lastValue?.values[1] ?? null
593
+ ];
594
+ }
595
+ else {
596
+ const closestDpValue = this.interpolateBetweenTwoDps(dpValuesArray, creationTime);
597
+ const dpValuesForNewAlarms = this.getClosestDpValueToTargetTime(dpValuesArray, creationTime);
598
+ const closestDpValueLastUpdated = this.interpolateBetweenTwoDps(dpValuesArray, lastUpdatedTime);
599
+ const dpValuesForNewAlarmsLastUpdated = this.getClosestDpValueToTargetTime(dpValuesArray, lastUpdatedTime);
600
+ coordCreationTime = [
601
+ item.creationTime,
602
+ closestDpValue?.values[0]?.min ??
603
+ closestDpValue?.values[1] ??
604
+ dpValuesForNewAlarms?.values[0]?.min ??
605
+ dpValuesForNewAlarms?.values[1] ??
606
+ null
607
+ ];
608
+ coordLastUpdatedTime = [
609
+ item['lastUpdated'],
610
+ closestDpValueLastUpdated?.values[0]?.min ??
611
+ closestDpValueLastUpdated?.values[1] ??
612
+ dpValuesForNewAlarmsLastUpdated?.values[0]?.min ??
613
+ dpValuesForNewAlarmsLastUpdated?.values[1] ??
614
+ null
615
+ ];
616
+ }
617
+ if (isEvent) {
618
+ return [
619
+ {
620
+ coord: coordCreationTime,
621
+ name: item.type,
622
+ itemType: item.type,
623
+ itemStyle: {
624
+ color: item['color']
625
+ },
626
+ symbol: 'circle',
627
+ symbolSize: 24
628
+ },
629
+ {
630
+ coord: coordCreationTime,
631
+ name: item.type,
632
+ itemType: item.type,
633
+ itemStyle: { color: 'white' },
634
+ symbol: ICONS_MAP.EVENT,
635
+ symbolSize: 16
636
+ }
637
+ ];
638
+ }
639
+ return isCleared
640
+ ? [
641
+ {
642
+ coord: coordCreationTime,
643
+ name: item.type,
644
+ itemType: item.type,
645
+ itemStyle: {
646
+ color: item['color']
647
+ },
648
+ symbol: 'circle',
649
+ symbolSize: 24
650
+ },
651
+ {
652
+ coord: coordCreationTime,
653
+ name: item.type,
654
+ itemType: item.type,
655
+ itemStyle: { color: 'white' },
656
+ symbol: ICONS_MAP[item.severity],
657
+ symbolSize: 16
658
+ },
659
+ {
660
+ coord: coordLastUpdatedTime,
661
+ name: item.type,
662
+ itemType: item.type,
663
+ itemStyle: {
664
+ color: item['color']
665
+ },
666
+ symbol: 'circle',
667
+ symbolSize: 24
668
+ },
669
+ {
670
+ coord: coordLastUpdatedTime,
671
+ name: item.type,
672
+ itemType: item.type,
673
+ itemStyle: { color: 'white' },
674
+ symbol: ICONS_MAP.CLEARED,
675
+ symbolSize: 16
676
+ }
677
+ ]
678
+ : [
679
+ {
680
+ coord: coordCreationTime,
681
+ name: item.type,
682
+ itemType: item.type,
683
+ itemStyle: {
684
+ color: item['color']
685
+ },
686
+ symbol: 'circle',
687
+ symbolSize: 24
688
+ },
689
+ {
690
+ coord: coordCreationTime,
691
+ name: item.type,
692
+ itemType: item.type,
693
+ itemStyle: { color: 'white' },
694
+ symbol: ICONS_MAP[item.severity],
695
+ symbolSize: 16
696
+ },
697
+ {
698
+ coord: coordLastUpdatedTime,
699
+ name: item.type,
700
+ itemType: item.type,
701
+ itemStyle: {
702
+ color: item['color']
703
+ },
704
+ symbol: 'circle',
705
+ symbolSize: 24
706
+ },
707
+ {
708
+ coord: coordLastUpdatedTime,
709
+ name: item.type,
710
+ itemType: item.type,
711
+ itemStyle: { color: 'white' },
712
+ symbol: ICONS_MAP[item.severity],
713
+ symbolSize: 16
714
+ }
715
+ ];
716
+ }
717
+ /**
718
+ * This method creates a markLine on the chart which represents the line between every alarm or event on the chart.
719
+ * @param items Array of alarms or events
720
+ * @returns MarkLineDataItemOptionBase[]
721
+ */
722
+ createMarkLine(items) {
723
+ return items.reduce((acc, item) => {
724
+ if (!item.creationTime) {
725
+ return acc;
726
+ }
727
+ if (item.creationTime === item['lastUpdated']) {
728
+ return acc.concat([
729
+ {
730
+ xAxis: item.creationTime,
731
+ itemType: item.type,
732
+ label: { show: false, formatter: () => item.type },
733
+ itemStyle: { color: item['color'] }
734
+ }
735
+ ]);
736
+ }
737
+ else {
738
+ return acc.concat([
739
+ {
740
+ xAxis: item.creationTime,
741
+ itemType: item.type,
742
+ label: { show: false, formatter: () => item.type },
743
+ itemStyle: { color: item['color'] }
744
+ },
745
+ {
746
+ xAxis: item['lastUpdated'],
747
+ itemType: item.type,
748
+ label: { show: false, formatter: () => item.type },
749
+ itemStyle: { color: item['color'] }
750
+ }
751
+ ]);
752
+ }
753
+ }, []);
754
+ }
755
+ getSingleSeries(dp, renderType, idx, isMinMaxChart = false, seriesType = '') {
756
+ const datapointId = dp.__target?.id + dp.fragment + dp.series;
757
+ return {
758
+ datapointId,
759
+ datapointUnit: dp.unit || '',
760
+ // 'id' property is needed as 'seriesId' in tooltip formatter
761
+ id: isMinMaxChart
762
+ ? `${datapointId}/${renderType}${seriesType}`
763
+ : `${datapointId}${seriesType}`,
764
+ name: `${dp.label} (${dp.__target?.['name']})`,
765
+ // datapointLabel used to proper display of tooltip
766
+ datapointLabel: dp.label || '',
767
+ data: Object.entries(dp.values).map(([dateString, values]) => {
768
+ return [dateString, values[0][renderType]];
769
+ }),
770
+ yAxisIndex: idx,
771
+ ...this.chartTypesService.getSeriesOptions(dp, isMinMaxChart, renderType)
772
+ };
773
+ }
774
+ /**
775
+ * This method creates a general tooltip formatter for the chart.
776
+ * @returns TooltipFormatterCallback<TopLevelFormatterParams>
777
+ */
778
+ getTooltipFormatter() {
779
+ return params => {
780
+ if (!Array.isArray(params) || !params[0]?.data) {
781
+ return '';
782
+ }
783
+ const data = params[0].data;
784
+ const XAxisValue = data[0];
785
+ const YAxisReadings = [];
786
+ const allSeries = this.echartsInstance?.getOption()['series'];
787
+ const allDataPointSeries = allSeries.filter(series => series['typeOfSeries'] !== 'alarm' &&
788
+ series['typeOfSeries'] !== 'event' &&
789
+ series['typeOfSeries'] !== 'fake');
790
+ allDataPointSeries.forEach((series) => {
791
+ let value;
792
+ const id = series['id'];
793
+ if (id.endsWith('/min')) {
794
+ const minValue = this.findValueForExactOrEarlierTimestamp(series['data'], XAxisValue);
795
+ if (!minValue) {
796
+ return;
797
+ }
798
+ const maxSeries = allDataPointSeries.find(s => s['id'] === id.replace('/min', '/max'));
799
+ if (!maxSeries) {
800
+ return;
801
+ }
802
+ const maxValue = this.findValueForExactOrEarlierTimestamp(maxSeries['data'], XAxisValue);
803
+ if (maxValue === null) {
804
+ return;
805
+ }
806
+ value =
807
+ `<div class="d-flex a-i-center separator-top p-t-8 p-b-8">` +
808
+ `<label class="text-12 m-r-8 m-b-0">${this.datePipe.transform(minValue[0])}</label>` +
809
+ `<div class="m-l-auto text-12" >${minValue[1]} — ${maxValue[1]}` +
810
+ (series['datapointUnit'] ? ` ${series['datapointUnit']}` : '') +
811
+ `</div></div>`;
812
+ }
813
+ else if (id.endsWith('/max')) {
814
+ // do nothing, value is handled in 'min' case
815
+ return;
816
+ }
817
+ else {
818
+ const seriesValue = this.findValueForExactOrEarlierTimestamp(series['data'], XAxisValue);
819
+ if (!seriesValue) {
820
+ return;
821
+ }
822
+ value =
823
+ `<div class="d-flex a-i-center separator-top p-t-8 p-b-8">` +
824
+ `<label class="text-12 m-r-8 m-b-0">${this.datePipe.transform(seriesValue[0])}</label>` +
825
+ `<div class="m-l-auto text-12" >${seriesValue[1]?.toString()}` +
826
+ (series['datapointUnit'] ? ` ${series['datapointUnit']}` : '') +
827
+ `</div></div>`;
828
+ }
829
+ const itemStyle = series['itemStyle'];
830
+ YAxisReadings.push(`<div class="d-flex a-i-center p-b-8"><span class='dlt-c8y-icon-circle m-r-4' style='color: ${itemStyle.color}'></span>` + // color circle
831
+ `<strong>${series['datapointLabel']} </strong></div>` + // name
832
+ `${value}` // single value or min-max range
833
+ );
834
+ });
835
+ return `<div style="width: ${this.TOOLTIP_WIDTH}px">${YAxisReadings.join('')}</div>`;
836
+ };
837
+ }
838
+ findValueForExactOrEarlierTimestamp(values, timestampString) {
839
+ const timestamp = new Date(timestampString).valueOf();
840
+ return values.reduce((acc, curr) => {
841
+ if (new Date(curr[0]).valueOf() <= timestamp) {
842
+ if (acc === null ||
843
+ Math.abs(new Date(curr[0]).valueOf() - timestamp) <
844
+ Math.abs(new Date(acc[0]).valueOf() - timestamp)) {
845
+ return curr;
846
+ }
847
+ }
848
+ return acc;
849
+ }, null);
850
+ }
851
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: EchartsOptionsService, deps: [{ token: i1.DatePipe }, { token: i2.YAxisService }, { token: i3.ChartTypesService }, { token: i4.AlarmSeverityToIconPipe }, { token: i4.AlarmSeverityToLabelPipe }, { token: i5.Router }], target: i0.ɵɵFactoryTarget.Injectable }); }
852
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: EchartsOptionsService }); }
853
+ }
854
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: EchartsOptionsService, decorators: [{
855
+ type: Injectable
856
+ }], ctorParameters: () => [{ type: i1.DatePipe }, { type: i2.YAxisService }, { type: i3.ChartTypesService }, { type: i4.AlarmSeverityToIconPipe }, { type: i4.AlarmSeverityToLabelPipe }, { type: i5.Router }] });
857
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZWNoYXJ0cy1vcHRpb25zLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9lY2hhcnQvc2VydmljZXMvZWNoYXJ0cy1vcHRpb25zLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsdURBQXVEO0FBQ3ZELE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDM0MsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBYS9DLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUNoRCxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUcxRCxPQUFPLEVBQUUsV0FBVyxFQUFnQyxNQUFNLGFBQWEsQ0FBQztBQUN4RSxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFFdEQsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQ3pDLE9BQU8sRUFBRSx1QkFBdUIsRUFBRSx3QkFBd0IsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQy9GLE9BQU8sRUFBWSxTQUFTLEVBQUUsTUFBTSxxQ0FBcUMsQ0FBQzs7Ozs7OztBQWExRSxNQUFNLFVBQVUsR0FBRyxhQUFhLENBQUM7QUFHakMsTUFBTSxPQUFPLHFCQUFxQjtJQUtoQyxZQUNVLFFBQWtCLEVBQ2xCLFlBQTBCLEVBQzFCLGlCQUFvQyxFQUNwQyxnQkFBeUMsRUFDekMsaUJBQTJDLEVBQzNDLE1BQWM7UUFMZCxhQUFRLEdBQVIsUUFBUSxDQUFVO1FBQ2xCLGlCQUFZLEdBQVosWUFBWSxDQUFjO1FBQzFCLHNCQUFpQixHQUFqQixpQkFBaUIsQ0FBbUI7UUFDcEMscUJBQWdCLEdBQWhCLGdCQUFnQixDQUF5QjtRQUN6QyxzQkFBaUIsR0FBakIsaUJBQWlCLENBQTBCO1FBQzNDLFdBQU0sR0FBTixNQUFNLENBQVE7UUFUaEIsa0JBQWEsR0FBRyxH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akMsVUFBVSIsInNvdXJjZXNDb250ZW50IjpbIi8qIGVzbGludC1kaXNhYmxlIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnkgKi9cbmltcG9ydCB7IEluamVjdGFibGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IERhdGVQaXBlIH0gZnJvbSAnQGM4eS9uZ3gtY29tcG9uZW50cyc7XG5pbXBvcnQgdHlwZSB7IEVDaGFydHNPcHRpb24sIFNlcmllc09wdGlvbiB9IGZyb20gJ2VjaGFydHMnO1xuaW1wb3J0IHsgRUNoYXJ0cyB9IGZyb20gJ2VjaGFydHMnO1xuaW1wb3J0IHtcbiAgRGF0YXBvaW50Q2hhcnRSZW5kZXJUeXBlLFxuICBEcFdpdGhWYWx1ZXMsXG4gIERhdGVTdHJpbmcsXG4gIERwVmFsdWVzSXRlbSxcbiAgTWFya0xpbmVEYXRhLFxuICBNYXJrUG9pbnREYXRhLFxuICBTZXJpZXNEYXRhcG9pbnRJbmZvLFxuICBTZXJpZXNWYWx1ZVxufSBmcm9tICcuLi9tb2RlbHMnO1xuaW1wb3J0IHsgWUF4aXNTZXJ2aWNlIH0gZnJvbSAnLi95LWF4aXMuc2VydmljZSc7XG5pbXBvcnQgeyBDaGFydFR5cGVzU2VydmljZSB9IGZyb20gJy4vY2hhcnQtdHlwZXMuc2VydmljZSc7XG5pbXBvcnQgdHlwZSB7IENhbGxiYWNrRGF0YVBhcmFtcywgVG9vbHRpcEZvcm1hdHRlckNhbGxiYWNrIH0gZnJvbSAnZWNoYXJ0cy90eXBlcy9zcmMvdXRpbC90eXBlcyc7XG5pbXBvcnQgdHlwZSB7IFRvcExldmVsRm9ybWF0dGVyUGFyYW1zIH0gZnJvbSAnZWNoYXJ0cy90eXBlcy9zcmMvY29tcG9uZW50L3Rvb2x0aXAvVG9vbHRpcE1vZGVsJztcbmltcG9ydCB7IEFsYXJtU3RhdHVzLCBJQWxhcm0sIElFdmVudCwgU2V2ZXJpdHlUeXBlIH0gZnJvbSAnQGM4eS9jbGllbnQnO1xuaW1wb3J0IHsgSUNPTlNfTUFQIH0gZnJvbSAnLi4vbW9kZWxzL3N2Zy1pY29ucy5tb2RlbCc7XG5pbXBvcnQgeyBDdXN0b21TZXJpZXNPcHRpb25zIH0gZnJvbSAnLi4vbW9kZWxzL2NoYXJ0Lm1vZGVsJztcbmltcG9ydCB7IFJvdXRlciB9IGZyb20gJ0Bhbmd1bGFyL3JvdXRlcic7XG5pbXBvcnQgeyBBbGFybVNldmVyaXR5VG9JY29uUGlwZSwgQWxhcm1TZXZlcml0eVRvTGFiZWxQaXBlIH0gZnJvbSAnQGM4eS9uZ3gtY29tcG9uZW50cy9hbGFybXMnO1xuaW1wb3J0IHsgSW50ZXJ2YWwsIElOVEVSVkFMUyB9IGZyb20gJ0BjOHkvbmd4LWNvbXBvbmVudHMvaW50ZXJ2YWwtcGlja2VyJztcblxudHlwZSBUb29sdGlwUG9zaXRpb25DYWxsYmFjayA9IChcbiAgcG9pbnQ6IFtudW1iZXIsIG51bWJlcl0sIC8vIHBvc2l0aW9uIG9mIG1vdXNlIGluIGNoYXJ0IFtYLCBZXTsgMCwwIGlzIHRvcCBsZWZ0IGNvcm5lclxuICBfOiBhbnksIC8vIHRvb2x0aXAgZGF0YVxuICBkb206IEhUTUxFbGVtZW50IHwgdW5rbm93biwgLy8gdG9vbHRpcCBlbGVtZW50XG4gIF9fOiBhbnksIC8vIHZhbGlkIG9ubHkgd2hlbiBtb3VzZSBpcyBvbiBncmFwaGljIGVsZW1lbnRzOyBub3QgcmVsZXZhbnQgaW4gb3VyIGNhc2VcbiAgc2l6ZToge1xuICAgIGNvbnRlbnRTaXplOiBbbnVtYmVyLCBudW1iZXJdOyAvLyBzaXplIG9mIHRvb2x0aXBcbiAgICB2aWV3U2l6ZTogW251bWJlciwgbnVtYmVyXTsgLy8gc2l6ZSBvZiB0aGUgY2hhcnRcbiAgfSB8IG51bGwgLy8gc2l6ZSBvZiBjaGFydFxuKSA9PiBQYXJ0aWFsPFJlY29yZDwndG9wJyB8ICdib3R0b20nIHwgJ2xlZnQnIHwgJ3JpZ2h0JywgbnVtYmVyPj47XG5cbmNvbnN0IElOREVYX0hUTUwgPSAnL2luZGV4Lmh0bWwnO1xuXG5ASW5qZWN0YWJsZSgpXG5leHBvcnQgY2xhc3MgRWNoYXJ0c09wdGlvbnNTZXJ2aWNlIHtcbiAgZWNoYXJ0c0luc3RhbmNlOiBFQ2hhcnRzIHwgdW5kZWZpbmVkO1xuICBwcml2YXRlIFRPT0xUSVBfV0lEVEggPSAzMDA7XG4gIHByaXZhdGUgdG9vbHRpcFBvc2l0aW9uQ2FsbGJhY2s6IFRvb2x0aXBQb3NpdGlvbkNhbGxiYWNrIHwgdW5kZWZpbmVkO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgZGF0ZVBpcGU6IERhdGVQaXBlLFxuICAgIHByaXZhdGUgeUF4aXNTZXJ2aWNlOiBZQXhpc1NlcnZpY2UsXG4gICAgcHJpdmF0ZSBjaGFydFR5cGVzU2VydmljZTogQ2hhcnRUeXBlc1NlcnZpY2UsXG4gICAgcHJpdmF0ZSBzZXZlcml0eUljb25QaXBlOiBBbGFybVNldmVyaXR5VG9JY29uUGlwZSxcbiAgICBwcml2YXRlIHNldmVyaXR5TGFiZWxQaXBlOiBBbGFybVNldmVyaXR5VG9MYWJlbFBpcGUsXG4gICAgcHJpdmF0ZSByb3V0ZXI6IFJvdXRlclxuICApIHt9XG5cbiAgZ2V0Q2hhcnRPcHRpb25zKFxuICAgIGRhdGFwb2ludHNXaXRoVmFsdWVzOiBEcFdpdGhWYWx1ZXNbXSxcbiAgICB0aW1lUmFuZ2U6IHsgZGF0ZUZyb206IHN0cmluZzsgZGF0ZVRvOiBzdHJpbmc7IGludGVydmFsOiBJbnRlcnZhbFsnaWQnXSB9LFxuICAgIHNob3dTcGxpdExpbmVzOiB7IFlBeGlzOiBib29sZWFuOyBYQXhpczogYm9vbGVhbiB9LFxuICAgIGV2ZW50czogSUV2ZW50W10sXG4gICAgYWxhcm1zOiBJQWxhcm1bXSxcbiAgICBkaXNwbGF5T3B0aW9uczoge1xuICAgICAgZGlzcGxheU1hcmtlZExpbmU6IGJvb2xlYW47XG4gICAgICBkaXNwbGF5TWFya2VkUG9pbnQ6IGJvb2xlYW47XG4gICAgICBtZXJnZU1hdGNoaW5nRGF0YXBvaW50czogYm9vbGVhbjtcbiAgICAgIHNob3dMYWJlbEFuZFVuaXQ6IGJvb2xlYW47XG4gICAgICBzaG93U2xpZGVyOiBib29sZWFuO1xuICAgIH0sXG4gICAgc2VsZWN0ZWRUaW1lUmFuZ2U/OiB7IGRhdGVGcm9tOiBzdHJpbmc7IGRhdGVUbzogc3RyaW5nOyBpbnRlcnZhbDogSW50ZXJ2YWxbJ2lkJ10gfSB8IG51bGwsXG4gICAgYWdncmVnYXRlZERhdGFwb2ludHM/OiBEcFdpdGhWYWx1ZXNbXSxcbiAgICBzbGlkZXJab29tVXNlZCA9IGZhbHNlXG4gICk6IEVDaGFydHNPcHRpb24ge1xuICAgIGNvbnN0IHlBeGlzID0gdGhpcy55QXhpc1NlcnZpY2UuZ2V0WUF4aXMoZGF0YXBvaW50c1dpdGhWYWx1ZXMsIHtcbiAgICAgIHNob3dTcGxpdExpbmVzOiBzaG93U3BsaXRMaW5lcy5ZQXhpcyxcbiAgICAgIG1lcmdlTWF0Y2hpbmdEYXRhcG9pbnRzOiBkaXNwbGF5T3B0aW9ucy5tZXJnZU1hdGNoaW5nRGF0YXBvaW50cyxcbiAgICAgIHNob3dMYWJlbEFuZFVuaXQ6IGRpc3BsYXlPcHRpb25zLnNob3dMYWJlbEFuZFVuaXRcbiAgICB9KTtcbiAgICBjb25zdCBsZWZ0QXhpcyA9IHlBeGlzLmZpbHRlcih5eCA9PiB5eC5wb3NpdGlvbiA9PT0gJ2xlZnQnKTtcbiAgICBjb25zdCBncmlkTGVmdCA9IGxlZnRBeGlzLmxlbmd0aCA/IGxlZnRBeGlzLmxlbmd0aCAqIHRoaXMueUF4aXNTZXJ2aWNlLllfQVhJU19PRkZTRVQgOiAxNjtcbiAgICBjb25zdCByaWdodEF4aXMgPSB5QXhpcy5maWx0ZXIoeXggPT4geXgucG9zaXRpb24gPT09ICdyaWdodCcpO1xuICAgIGNvbnN0IGdyaWRSaWdodCA9IHJpZ2h0QXhpcy5sZW5ndGggPyByaWdodEF4aXMubGVuZ3RoICogdGhpcy55QXhpc1NlcnZpY2UuWV9BWElTX09GRlNFVCA6IDE2O1xuICAgIGxldCBpbnRlcnZhbEluTXMgPSB0aGlzLmNhbGN1bGF0ZUV4dGVuZGVkSW50ZXJ2YWxJbk1zKFxuICAgICAgc2VsZWN0ZWRUaW1lUmFuZ2U/LmludGVydmFsIHx8IHRpbWVSYW5nZS5pbnRlcnZhbCB8fCAnaG91cnMnLFxuICAgICAgc2VsZWN0ZWRUaW1lUmFuZ2UgfHwgdGltZVJhbmdlXG4gICAgKTtcbiAgICBpZiAoc2xpZGVyWm9vbVVzZWQpIHtcbiAgICAgIGludGVydmFsSW5NcyA9IHRoaXMuY2FsY3VsYXRlRXh0ZW5kZWRJbnRlcnZhbEluTXModGltZVJhbmdlLmludGVydmFsIHx8ICdob3VycycsIHRpbWVSYW5nZSk7XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICBncmlkOiB7XG4gICAgICAgIGNvbnRhaW5MYWJlbDogZmFsc2UsIC8vIGF4aXMgbGFiZWxzIGFyZSBub3QgdGFrZW4gaW50byBhY2NvdW50IHRvIGNhbGN1bGF0ZSBncmFwaCBncmlkXG4gICAgICAgIGxlZnQ6IGdyaWRMZWZ0LFxuICAgICAgICB0b3A6IDE2LFxuICAgICAgICByaWdodDogZ3JpZFJpZ2h0LFxuICAgICAgICBib3R0b206IDY4XG4gICAgICB9LFxuICAgICAgZGF0YVpvb206IFtcbiAgICAgICAge1xuICAgICAgICAgIHR5cGU6ICdpbnNpZGUnLFxuICAgICAgICAgIC8vIFRPRE86IHVzZSAnbm9uZScgb25seSB3aGVuIHRoaXMgYnVnIGlzIGZpeGVkIGh0dHBzOi8vZ2l0aHViLmNvbS9hcGFjaGUvZWNoYXJ0cy9pc3N1ZXMvMTc4NThcbiAgICAgICAgICBmaWx0ZXJNb2RlOiBkYXRhcG9pbnRzV2l0aFZhbHVlcy5zb21lKGRwID0+IGRwLmxpbmVUeXBlID09PSAnYmFycycpID8gJ2ZpbHRlcicgOiAnbm9uZScsXG4gICAgICAgICAgem9vbU9uTW91c2VXaGVlbDogdHJ1ZSxcbiAgICAgICAgICBzdGFydFZhbHVlOiBzZWxlY3RlZFRpbWVSYW5nZVxuICAgICAgICAgICAgPyBzZWxlY3RlZFRpbWVSYW5nZS5kYXRlRnJvbS52YWx1ZU9mKClcbiAgICAgICAgICAgIDogdGltZVJhbmdlLmRhdGVGcm9tLnZhbHVlT2YoKSxcbiAgICAgICAgICBlbmRWYWx1ZTogc2VsZWN0ZWRUaW1lUmFuZ2VcbiAgICAgICAgICAgID8gc2VsZWN0ZWRUaW1lUmFuZ2UuZGF0ZVRvLnZhbHVlT2YoKVxuICAgICAgICAgICAgOiB0aW1lUmFuZ2UuZGF0ZVRvLnZhbHVlT2YoKVxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgdHlwZTogJ3NsaWRlcicsXG4gICAgICAgICAgc2hvdzogZGlzcGxheU9wdGlvbnMuc2hvd1NsaWRlcixcbiAgICAgICAgICBib3R0b206IDgsXG4gICAgICAgICAgcmVhbHRpbWU6IGZhbHNlXG4gICAgICAgIH1cbiAgICAgIF0sIC8vIG9uIHJlYWx0aW1lLCAnbm9uZScgd2lsbCBjYXVzZSBleHRlbmRpbmcgY2hhcnQgbGluZSB0byBsZWZ0IGVkZ2Ugb2YgdGhlIGNoYXJ0XG4gICAgICBhbmltYXRpb246IGZhbHNlLFxuICAgICAgdG9vbGJveDoge1xuICAgICAgICBzaG93OiB0cnVlLFxuICAgICAgICBpdGVtU2l6ZTogMCwgLy8gdG9vbGJveCBpcyBuZWVkZWQgZm9yIHpvb21pbmcgaW4gYWN0aW9uLCBidXQgd2UgcHJvdmlkZSBvdXIgb3duIGJ1dHRvbnNcbiAgICAgICAgZmVhdHVyZToge1xuICAgICAgICAgIGRhdGFab29tOiB7XG4gICAgICAgICAgICB5QXhpc0luZGV4OiAnbm9uZSdcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgICB0b29sdGlwOiB7XG4gICAgICAgIHRyaWdnZXI6ICdheGlzJyxcbiAgICAgICAgYXhpc1BvaW50ZXI6IHtcbiAgICAgICAgICB0eXBlOiAnY3Jvc3MnLFxuICAgICAgICAgIHNuYXA6IHRydWVcbiAgICAgICAgfSxcbiAgICAgICAgYmFja2dyb3VuZENvbG9yOiAncmdiYSgyNTUsIDI1NSwgMjU1LCAwLjkpJyxcbiAgICAgICAgZm9ybWF0dGVyOiB0aGlzLmdldFRvb2x0aXBGb3JtYXR0ZXIoKSxcbiAgICAgICAgYXBwZW5kVG9Cb2R5OiB0cnVlLFxuICAgICAgICBwb3NpdGlvbjogdGhpcy50b29sdGlwUG9zaXRpb24oKSxcbiAgICAgICAgdHJhbnNpdGlvbkR1cmF0aW9uOiAwXG4gICAgICB9LFxuICAgICAgbGVnZW5kOiB7XG4gICAgICAgIHNob3c6IGZhbHNlXG4gICAgICB9LFxuICAgICAgeEF4aXM6IHtcbiAgICAgICAgbWluOiBuZXcgRGF0ZSh0aW1lUmFuZ2UuZGF0ZUZyb20pLnZhbHVlT2YoKSAtIGludGVydmFsSW5NcyxcbiAgICAgICAgbWF4OiB0aW1lUmFuZ2UuZGF0ZVRvLFxuICAgICAgICB0eXBlOiAndGltZScsXG4gICAgICAgIGFuaW1hdGlvbjogZmFsc2UsXG4gICAgICAgIGF4aXNQb2ludGVyOiB7XG4gICAgICAgICAgbGFiZWw6IHtcbiAgICAgICAgICAgIHNob3c6IGZhbHNlXG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBheGlzTGluZToge1xuICAgICAgICAgIC8vIGFsaWduIFggYXhpcyB0byAwIG9mIFkgYXhpcyBvZiBkYXRhcG9pbnQgd2l0aCBsaW5lVHlwZSAnYmFycydcbiAgICAgICAgICBvblplcm9BeGlzSW5kZXg6IGRhdGFwb2ludHNXaXRoVmFsdWVzLmZpbmRJbmRleChkcCA9PiBkcC5saW5lVHlwZSA9PT0gJ2JhcnMnKVxuICAgICAgICB9LFxuICAgICAgICBheGlzTGFiZWw6IHtcbiAgICAgICAgICBoaWRlT3ZlcmxhcDogdHJ1ZSxcbiAgICAgICAgICBib3JkZXJXaWR0aDogMiwgLy8gYXMgdGhlcmUgaXMgbm8gbWFyZ2luIGZvciBsYWJlbHMgc3BhY2luZywgdHJhbnNwYXJlbnQgYm9yZGVyIGlzIGEgd29ya2Fyb3VuZFxuICAgICAgICAgIGJvcmRlckNvbG9yOiAndHJhbnNwYXJlbnQnXG4gICAgICAgIH0sXG4gICAgICAgIHNwbGl0TGluZToge1xuICAgICAgICAgIHNob3c6IHNob3dTcGxpdExpbmVzLlhBeGlzLFxuICAgICAgICAgIGxpbmVTdHlsZTogeyBvcGFjaXR5OiAwLjgsIHR5cGU6ICdkYXNoZWQnLCB3aWR0aDogMiB9XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgICB5QXhpcyxcbiAgICAgIHNlcmllczogW1xuICAgICAgICAuLi50aGlzLmdldEFnZ3JlZ2F0ZWRTZXJpZXMoYWdncmVnYXRlZERhdGFwb2ludHMgfHwgW10pLmZpbHRlcihcbiAgICAgICAgICBzZXJpZXMgPT4gc2VyaWVzICE9PSB1bmRlZmluZWRcbiAgICAgICAgKSxcbiAgICAgICAgLi4udGhpcy5nZXRDaGFydFNlcmllcyhkYXRhcG9pbnRzV2l0aFZhbHVlcywgZXZlbnRzLCBhbGFybXMsIGRpc3BsYXlPcHRpb25zKVxuICAgICAgXVxuICAgIH07XG4gIH1cblxuICBjYWxjdWxhdGVFeHRlbmRlZEludGVydmFsSW5NcyhpbnRlcnZhbDogSW50ZXJ2YWxbJ2lkJ10sIHNlbGVjdGVkVGltZVJhbmdlKTogbnVtYmVyIHtcbiAgICBsZXQgaW50ZXJ2YWxJbk1zID0gSU5URVJWQUxTLmZpbmQoaSA9PiBpLmlkID09PSBpbnRlcnZhbCkudGltZXNwYW5Jbk1zO1xuICAgIHN3aXRjaCAoaW50ZXJ2YWwpIHtcbiAgICAgIGNhc2UgJ21pbnV0ZXMnOlxuICAgICAgICBpbnRlcnZhbEluTXMgPSBJTlRFUlZBTFMuZmluZChpID0+IGkuaWQgPT09IGludGVydmFsKS50aW1lc3BhbkluTXMgKiA2MDtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdob3Vycyc6XG4gICAgICAgIGludGVydmFsSW5NcyA9IElOVEVSVkFMUy5maW5kKGkgPT4gaS5pZCA9PT0gaW50ZXJ2YWwpLnRpbWVzcGFuSW5NcyAqIDI0O1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ2RheXMnOlxuICAgICAgICBpbnRlcnZhbEluTXMgPSBJTlRFUlZBTFMuZmluZChpID0+IGkuaWQgPT09IGludGVydmFsKS50aW1lc3BhbkluTXMgKiAyODtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICd3ZWVrcyc6XG4gICAgICAgIGludGVydmFsSW5NcyA9IElOVEVSVkFMUy5maW5kKGkgPT4gaS5pZCA9PT0gaW50ZXJ2YWwpLnRpbWVzcGFuSW5NcyAqIDEyO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ21vbnRocyc6XG4gICAgICAgIGludGVydmFsSW5NcyA9IElOVEVSVkFMUy5maW5kKGkgPT4gaS5pZCA9PT0gaW50ZXJ2YWwpLnRpbWVzcGFuSW5NcyAqIDEyO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ2N1c3RvbSc6XG4gICAgICAgIGludGVydmFsSW5NcyA9XG4gICAgICAgICAgKG5ldyBEYXRlKHNlbGVjdGVkVGltZVJhbmdlLmRhdGVUbykudmFsdWVPZigpIC1cbiAgICAgICAgICAgIG5ldyBEYXRlKHNlbGVjdGVkVGltZVJhbmdlLmRhdGVGcm9tKS52YWx1ZU9mKCkpICpcbiAgICAgICAgICAxMjtcbiAgICAgICAgYnJlYWs7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICBpbnRlcnZhbEluTXMgPSBJTlRFUlZBTFMuZmluZChpID0+IGkuaWQgPT09IGludGVydmFsKS50aW1lc3BhbkluTXM7XG4gICAgICAgIGJyZWFrO1xuICAgIH1cbiAgICByZXR1cm4gaW50ZXJ2YWxJbk1zO1xuICB9XG5cbiAgZ2V0QWdncmVnYXRlZFNlcmllcyhhZ2dyZWdhdGVkRGF0YXBvaW50czogRHBXaXRoVmFsdWVzW10pOiBTZXJpZXNPcHRpb25bXSB7XG4gICAgY29uc3Qgc2VyaWVzOiBTZXJpZXNPcHRpb25bXSA9IFtdO1xuICAgIGFnZ3JlZ2F0ZWREYXRhcG9pbnRzLmZvckVhY2goKGRwLCBpZHgpID0+IHtcbiAgICAgIGNvbnN0IHJlbmRlclR5cGU6IERhdGFwb2ludENoYXJ0UmVuZGVyVHlwZSA9IGRwLnJlbmRlclR5cGUgfHwgJ21pbic7XG4gICAgICBpZiAocmVuZGVyVHlwZSA9PT0gJ2FyZWEnKSB7XG4gICAgICAgIHNlcmllcy5wdXNoKHRoaXMuZ2V0U2luZ2xlU2VyaWVzKGRwLCAnbWluJywgaWR4LCB0cnVlLCAnYWdncicpKTtcbiAgICAgICAgc2VyaWVzLnB1c2godGhpcy5nZXRTaW5nbGVTZXJpZXMoZHAsICdtYXgnLCBpZHgsIHRydWUsICdhZ2dyJykpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgc2VyaWVzLnB1c2godGhpcy5nZXRTaW5nbGVTZXJpZXMoZHAsIHJlbmRlclR5cGUsIGlkeCwgZmFsc2UsICdhZ2dyJykpO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgc2VyaWVzLmZvckVhY2goKHM6IGFueSkgPT4ge1xuICAgICAgcy5kYXRhcG9pbnRJZCA9ICdhZ2dyZWdhdGVkJztcbiAgICAgIHMudHlwZU9mU2VyaWVzID0gJ2Zha2UnO1xuICAgICAgcy5pdGVtU3R5bGUgPSB7XG4gICAgICAgIC4uLnMuaXRlbVN0eWxlLFxuICAgICAgICBvcGFjaXR5OiAwXG4gICAgICB9O1xuICAgICAgcy5saW5lU3R5bGUgPSB7XG4gICAgICAgIC4uLnMubGluZVN0eWxlLFxuICAgICAgICBvcGFjaXR5OiAwXG4gICAgICB9O1xuICAgIH0pO1xuXG4gICAgcmV0dXJuIFtzZXJpZXNbMF1dO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoaXMgbWV0aG9kIGlzIHVzZWQgdG8gZ2V0IHRoZSBzZXJpZXMgZm9yIGFsYXJtcyBhbmQgZXZlbnRzLlxuICAgKiBAcGFyYW0gZHAgLSBUaGUgZGF0YSBwb2ludC5cbiAgICogQHBhcmFtIHJlbmRlclR5cGUgLSBUaGUgcmVuZGVyIHR5cGUuXG4gICAqIEBwYXJhbSBpc01pbk1heENoYXJ0IC0gSWYgdGhlIGNoYXJ0IGlzIG1pbiBtYXggY2hhcnQuXG4gICAqIEBwYXJhbSBpdGVtcyAtIEFsbCBhbGFybXMgb3IgZXZlbnRzIHdoaWNoIHNob3VsZCBiZSBkaXNwbGF5ZWQgb24gdGhlIGNoYXJ0LlxuICAgKiBAcGFyYW0gaXRlbVR5cGUgLSBUaGUgaXRlbSB0eXBlLlxuICAgKiBAcGFyYW0gaWQgLSBUaGUgaWQgb2YgdGhlIGRldmljZVxuICAgKi9cbiAgZ2V0QWxhcm1PckV2ZW50U2VyaWVzKFxuICAgIGRwOiBEcFdpdGhWYWx1ZXMsXG4gICAgcmVuZGVyVHlwZTogRGF0YXBvaW50Q2hhcnRSZW5kZXJUeXBlLFxuICAgIGlzTWluTWF4Q2hhcnQgPSBmYWxzZSxcbiAgICBpdGVtczogSUFsYXJtW10gfCBJRXZlbnRbXSA9IFtdLFxuICAgIGl0ZW1UeXBlOiAnYWxhcm0nIHwgJ2V2ZW50JyA9ICdhbGFybScsXG4gICAgZGlzcGxheU9wdGlvbnMgPSB7IGRpc3BsYXlNYXJrZWRMaW5lOiB0cnVlLCBkaXNwbGF5TWFya2VkUG9pbnQ6IHRydWUgfSxcbiAgICBpZD86IHN0cmluZyB8IG51bWJlcixcbiAgICBpZHg/OiBudW1iZXIsXG4gICAgcmVhbHRpbWU/OiBib29sZWFuXG4gICk6IEN1c3RvbVNlcmllc09wdGlvbnNbXSB7XG4gICAgaWYgKCFpdGVtcy5sZW5ndGgpIHtcbiAgICAgIHJldHVybiBbXTtcbiAgICB9XG5cbiAgICBpZiAoIWRpc3BsYXlPcHRpb25zLmRpc3BsYXlNYXJrZWRMaW5lICYmICFkaXNwbGF5T3B0aW9ucy5kaXNwbGF5TWFya2VkUG9pbnQpIHtcbiAgICAgIHJldHVybiBbXTtcbiAgICB9XG5cbiAgICAvL2ZpbHRlciBpdGVtcyB0aGF0IGFyZSBub3QgX19oaWRkZW5cbiAgICBjb25zdCBmaWx0ZXJlZEl0ZW1zOiBJQWxhcm1bXSB8IElFdmVudFtdID0gaXRlbXMuZmlsdGVyKGl0ZW0gPT4gIWl0ZW1bJ19faGlkZGVuJ10pO1xuICAgIGNvbnN0IGl0ZW1zQnlUeXBlID0gdGhpcy5ncm91cEJ5VHlwZShmaWx0ZXJlZEl0ZW1zLCAndHlwZScpO1xuICAgIGNvbnN0IGlzQWxhcm0gPSBpdGVtVHlwZSA9PT0gJ2FsYXJtJztcblxuICAgIHJldHVybiBPYmplY3QuZW50cmllcyhpdGVtc0J5VHlwZSkuZmxhdE1hcChcbiAgICAgIChbdHlwZSwgaXRlbXNPZlR5cGVdOiBbc3RyaW5nLCAoSUFsYXJtIHwgSUV2ZW50KVtdXSkgPT4ge1xuICAgICAgICAvLyBNYWluIHNlcmllcyBkYXRhXG4gICAgICAgIGNvbnN0IG1haW5EYXRhID0gaXRlbXNPZlR5cGUubWFwKGl0ZW0gPT4gW2l0ZW0uY3JlYXRpb25UaW1lLCBudWxsLCAnbWFya0xpbmVGbGFnJ10pO1xuICAgICAgICAvLyBJcyBhIHNwZWNpZmljIGRhdGFwb2ludCB0ZW1wbGF0ZSBzZWxlY3RlZCBmb3IgdGhpcyBhbGFybS9ldmVudCB0eXBlP1xuICAgICAgICBsZXQgaXNEcFRlbXBsYXRlU2VsZWN0ZWQgPSBmYWxzZTtcblxuICAgICAgICAvLyBNYXJrUG9pbnQgZGF0YVxuICAgICAgICBjb25zdCBtYXJrUG9pbnREYXRhID0gaXRlbXNPZlR5cGUucmVkdWNlPE1hcmtQb2ludERhdGFbXT4oKGFjYywgaXRlbSkgPT4ge1xuICAgICAgICAgIGlzRHBUZW1wbGF0ZVNlbGVjdGVkID1cbiAgICAgICAgICAgIGl0ZW1bJ3NlbGVjdGVkRGF0YXBvaW50J10gJiZcbiAgICAgICAgICAgIGRwWydfX3RhcmdldCddICYmXG4gICAgICAgICAgICBpdGVtWydzZWxlY3RlZERhdGFwb2ludCddWydmcmFnbWVudCddID09PSBkcFsnZnJhZ21lbnQnXSAmJlxuICAgICAgICAgICAgaXRlbVsnc2VsZWN0ZWREYXRhcG9pbnQnXVsnc2VyaWVzJ10gPT09IGRwWydzZXJpZXMnXSAmJlxuICAgICAgICAgICAgaXRlbVsnc2VsZWN0ZWREYXRhcG9pbnQnXVsndGFyZ2V0J10gPT09IGRwWydfX3RhcmdldCddWydpZCddO1xuICAgICAgICAgIGlmIChkcC5fX3RhcmdldD8uaWQgPT09IGl0ZW0uc291cmNlLmlkKSB7XG4gICAgICAgICAgICBjb25zdCBpc0NsZWFyZWQgPSBpc0FsYXJtICYmIGl0ZW0uc3RhdHVzID09PSBBbGFybVN0YXR1cy5DTEVBUkVEO1xuICAgICAgICAgICAgY29uc3QgaXNFdmVudCA9ICFpc0FsYXJtO1xuICAgICAgICAgICAgcmV0dXJuIGFjYy5jb25jYXQodGhpcy5jcmVhdGVNYXJrUG9pbnQoaXRlbSwgZHAsIGlzQ2xlYXJlZCwgaXNFdmVudCwgcmVhbHRpbWUpKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYgKCFpdGVtLmNyZWF0aW9uVGltZSkge1xuICAgICAgICAgICAgICByZXR1cm4gW107XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gYWNjLmNvbmNhdChbXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBjb29yZDogW2l0ZW0uY3JlYXRpb25UaW1lLCBudWxsXSxcbiAgICAgICAgICAgICAgICBuYW1lOiBpdGVtLnR5cGUsXG4gICAgICAgICAgICAgICAgaXRlbVR5cGU6IGl0ZW0udHlwZSxcbiAgICAgICAgICAgICAgICBpdGVtU3R5bGU6IHsgY29sb3I6IGl0ZW1bJ2NvbG9yJ10gfVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICBdKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0sIFtdKTtcblxuICAgICAgICAvLyBDb25zdHJ1Y3Qgc2VyaWVzIHdpdGggbWFya1BvaW50XG4gICAgICAgIGNvbnN0IHNlcmllc1dpdGhNYXJrUG9pbnQgPSB7XG4gICAgICAgICAgaWQ6IGAke3R5cGV9LyR7ZHAuX190YXJnZXQ/LmlkfSske2lkID8gaWQgOiAnJ30tbWFya1BvaW50YCxcbiAgICAgICAgICBuYW1lOiBgJHt0eXBlfS1tYXJrUG9pbnRgLFxuICAgICAgICAgIHR5cGVPZlNlcmllczogaXRlbVR5cGUsXG4gICAgICAgICAgZGF0YTogbWFpbkRhdGEsXG4gICAgICAgICAgaXNEcFRlbXBsYXRlU2VsZWN0ZWQsXG4gICAgICAgICAgcG9zaXRpb246ICdib3R0b20nLFxuICAgICAgICAgIHNpbGVudDogdHJ1ZSxcbiAgICAgICAgICBtYXJrUG9pbnQ6IHtcbiAgICAgICAgICAgIHNob3dTeW1ib2w6IHRydWUsXG4gICAgICAgICAgICBzeW1ib2xLZWVwQXNwZWN0OiB0cnVlLFxuICAgICAgICAgICAgZGF0YTogbWFya1BvaW50RGF0YVxuICAgICAgICAgIH0sXG4gICAgICAgICAgeUF4aXNJbmRleDogaWR4LFxuICAgICAgICAgIC4uLnRoaXMuY2hhcnRUeXBlc1NlcnZpY2UuZ2V0U2VyaWVzT3B0aW9ucyhkcCwgaXNNaW5NYXhDaGFydCwgcmVuZGVyVHlwZSlcbiAgICAgICAgfTtcblxuICAgICAgICBjb25zdCBtYXJrTGluZURhdGEgPSB0aGlzLmNyZWF0ZU1hcmtMaW5lKGl0ZW1zT2ZUeXBlKTtcblxuICAgICAgICAvLyBDb25zdHJ1Y3Qgc2VyaWVzIHdpdGggbWFya0xpbmVcbiAgICAgICAgY29uc3Qgc2VyaWVzV2l0aE1hcmtMaW5lID0ge1xuICAgICAgICAgIGlkOiBgJHt0eXBlfS8ke2RwLl9fdGFyZ2V0Py5pZH0rJHtpZCA/IGlkIDogJyd9LW1hcmtMaW5lYCxcbiAgICAgICAgICBuYW1lOiBgJHt0eXBlfS1tYXJrTGluZWAsXG4gICAgICAgICAgdHlwZU9mU2VyaWVzOiBpdGVtVHlwZSxcbiAgICAgICAgICBpc0RwVGVtcGxhdGVTZWxlY3RlZCxcbiAgICAgICAgICBkYXRhOiBtYWluRGF0YSxcbiAgICAgICAgICBtYXJrTGluZToge1xuICAgICAgICAgICAgc2hvd1N5bWJvbDogZmFsc2UsXG4gICAgICAgICAgICBzeW1ib2w6IFsnbm9uZScsICdub25lJ10sIC8vIG5vIHN5bWJvbCBhdCB0aGUgc3RhcnQvZW5kIG9mIHRoZSBsaW5lXG4gICAgICAgICAgICBkYXRhOiBtYXJrTGluZURhdGFcbiAgICAgICAgICB9LFxuICAgICAgICAgIC4uLnRoaXMuY2hhcnRUeXBlc1NlcnZpY2UuZ2V0U2VyaWVzT3B0aW9ucyhkcCwgaXNNaW5NYXhDaGFydCwgcmVuZGVyVHlwZSlcbiAgICAgICAgfTtcblxuICAgICAgICAvL2RlcGVuZGluZyBvbiB0aGUgb3B0aW9ucyByZXR1cm4gb25seSB0aGUgcmVxdWlyZWQgc2VyaWVzXG4gICAgICAgIGlmIChkaXNwbGF5T3B0aW9ucy5kaXNwbGF5TWFya2VkTGluZSAmJiBkaXNwbGF5T3B0aW9ucy5kaXNwbGF5TWFya2VkUG9pbnQpIHtcbiAgICAgICAgICByZXR1cm4gW3Nlcmllc1dpdGhNYXJrTGluZSwgc2VyaWVzV2l0aE1hcmtQb2ludF07XG4gICAgICAgIH0gZWxzZSBpZiAoZGlzcGxheU9wdGlvbnMuZGlzcGxheU1hcmtlZExpbmUpIHtcbiAgICAgICAgICByZXR1cm4gW3Nlcmllc1dpdGhNYXJrTGluZV07XG4gICAgICAgIH0gZWxzZSBpZiAoZGlzcGxheU9wdGlvbnMuZGlzcGxheU1hcmtlZFBvaW50KSB7XG4gICAgICAgICAgcmV0dXJuIFtzZXJpZXNXaXRoTWFya1BvaW50XTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICkgYXMgQ3VzdG9tU2VyaWVzT3B0aW9uc1tdO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoaXMgbWV0aG9kIGlzIHVzZWQgdG8gZ2V0IHRvb2x0aXAgZm9ybWF0dGVyIGZvciBhbGFybXMgYW5kIGV2ZW50cy5cbiAgICogQHBhcmFtIHRvb2x0aXBQYXJhbXMgLSBUaGUgdG9vbHRpcCBwYXJhbWV0ZXJzLlxuICAgKiBAcGFyYW0gcGFyYW1zIC0gVGhlIHBhcmFtZXRlcnMgZGF0YS5cbiAgICogQHBhcmFtIGFsbEV2ZW50cyAtIEFsbCBldmVudHMuXG4gICAqIEBwYXJhbSBhbGxBbGFybXMgLSBBbGwgYWxhcm1zLlxuICAgKiBAcmV0dXJucyBUaGUgZm9ybWF0dGVkIHN0cmluZyBmb3IgdGhlIHRvb2x0aXAuXG4gICAqL1xuICBnZXRUb29sdGlwRm9ybWF0dGVyRm9yQWxhcm1BbmRFdmVudHMoXG4gICAgdG9vbHRpcFBhcmFtczogQ2FsbGJhY2tEYXRhUGFyYW1zLFxuICAgIHBhcmFtczogeyBkYXRhOiB7IGl0ZW1UeXBlOiBzdHJpbmcgfSB9LFxuICAgIGFsbEV2ZW50czogSUV2ZW50W10sXG4gICAgYWxsQWxhcm1zOiBJQWxhcm1bXVxuICApOiBzdHJpbmcge1xuICAgIGlmICghQXJyYXkuaXNBcnJheSh0b29sdGlwUGFyYW1zKSkge1xuICAgICAgcmV0dXJuICcnO1xuICAgIH1cbiAgICBjb25zdCBYQXhpc1ZhbHVlOiBzdHJpbmcgPSB0b29sdGlwUGFyYW1zWzBdLmRhdGFbMF07XG4gICAgY29uc3QgWUF4aXNSZWFkaW5nczogc3RyaW5nW10gPSBbXTtcbiAgICBjb25zdCBhbGxTZXJpZXMgPSB0aGlzLmVjaGFydHNJbnN0YW5jZT8uZ2V0T3B0aW9uKClbJ3NlcmllcyddIGFzIEN1c3RvbVNlcmllc09wdGlvbnNbXTtcblxuICAgIC8vIGZpbHRlciBvdXQgYWxhcm0gYW5kIGV2ZW50IHNlcmllc1xuICAgIGNvbnN0IGFsbERhdGFQb2ludFNlcmllcyA9IGFsbFNlcmllcy5maWx0ZXIoXG4gICAgICBzZXJpZXMgPT4gc2VyaWVzWyd0eXBlT2ZTZXJpZXMnXSAhPT0gJ2FsYXJtJyAmJiBzZXJpZXNbJ3R5cGVPZlNlcmllcyddICE9PSAnZXZlbnQnXG4gICAgKTtcblxuICAgIHRoaXMucHJvY2Vzc1NlcmllcyhhbGxEYXRhUG9pbnRTZXJpZXMsIFhBeGlzVmFsdWUsIFlBeGlzUmVhZGluZ3MpO1xuXG4gICAgLy8gZmluZCBldmVudCBhbmQgYWxhcm0gb2YgdGhlIHNhbWUgdHlwZSBhcyB0aGUgaG92ZXJlZCBtYXJrZWRMaW5lIG9yIG1hcmtlZFBvaW50XG4gICAgY29uc3QgZXZlbnQgPSBhbGxFdmVudHMuZmluZChlID0+IGUudHlwZSA9PT0gcGFyYW1zLmRhdGEuaXRlbVR5cGUpO1xuICAgIGNvbnN0IGFsYXJtID0gYWxsQWxhcm1zLmZpbmQoYSA9PiBhLnR5cGUgPT09IHBhcmFtcy5kYXRhLml0ZW1UeXBlKTtcblxuICAgIGxldCB2YWx1ZSA9ICcnO1xuICAgIGlmIChldmVudCkge1xuICAgICAgdmFsdWUgPSB0aGlzLnByb2Nlc3NFdmVudChldmVudCk7XG4gICAgfVxuXG4gICAgaWYgKGFsYXJtKSB7XG4gICAgICB0aGlzLnByb2Nlc3NBbGFybShhbGFybSkudGhlbihhbGFybVZhbCA9PiB7XG4gICAgICAgIHZhbHVlID0gYWxhcm1WYWw7XG4gICAgICAgIFlBeGlzUmVhZGluZ3MucHVzaCh2YWx1ZSk7XG4gICAgICAgIGNvbnN0IG9wdGlvbnMgPSB0aGlzLmVjaGFydHNJbnN0YW5jZT8uZ2V0T3B0aW9uKCkgYXMgRUNoYXJ0c09wdGlvbjtcbiAgICAgICAgaWYgKCFvcHRpb25zLnRvb2x0aXAgfHwgIUFycmF5LmlzQXJyYXkob3B0aW9ucy50b29sdGlwKSkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCB1cGRhdGVkT3B0aW9uczogUGFydGlhbDxTZXJpZXNPcHRpb24+ID0ge1xuICAgICAgICAgIHRvb2x0aXA6IG9wdGlvbnNbJ3Rvb2x0aXAnXVswXVxuICAgICAgICB9O1xuXG4gICAgICAgIGlmICghdXBkYXRlZE9wdGlvbnMudG9vbHRpcCkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB1cGRhdGVkT3B0aW9ucy50b29sdGlwLmZvcm1hdHRlciA9IGA8ZGl2IHN0eWxlPVwid2lkdGg6ICR7dGhpcy5UT09MVElQX1dJRFRIfXB4XCI+JHtZQXhpc1JlYWRpbmdzLmpvaW4oJycpfTwvZGl2PmA7XG4gICAgICAgIHVwZGF0ZWRPcHRpb25zLnRvb2x0aXAudHJhbnNpdGlvbkR1cmF0aW9uID0gMDtcbiAgICAgICAgdXBkYXRlZE9wdGlvbnMudG9vbHRpcC5wb3NpdGlvbiA9IHRoaXMudG9vbHRpcFBvc2l0aW9uKCk7XG4gICAgICAgIHRoaXMuZWNoYXJ0c0luc3RhbmNlPy5zZXRPcHRpb24odXBkYXRlZE9wdGlvbnMpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9KTtcbiAgICB9XG4gICAgWUF4aXNSZWFkaW5ncy5wdXNoKHZhbHVlKTtcblxuICAgIHJldHVybiBgPGRpdiBzdHlsZT1cIndpZHRoOiAzMDBweFwiPiR7WUF4aXNSZWFkaW5ncy5qb2luKCcnKX08L2Rpdj5gO1xuICB9XG5cbiAgcHJpdmF0ZSB0b29sdGlwUG9zaXRpb24oKTogVG9vbHRpcFBvc2l0aW9uQ2FsbGJhY2sge1xuICAgIGxldCBsYXN0UG9zaXRpb25PZlRvb2x0aXA6IFBhcnRpYWw8UmVjb3JkPCd0b3AnIHwgJ2JvdHRvbScgfCAnbGVmdCcgfCAncmlnaHQnLCBudW1iZXI+PiA9IHt9O1xuICAgIGlmICh0aGlzLnRvb2x0aXBQb3NpdGlvbkNhbGxiYWNrKSB7XG4gICAgICByZXR1cm4gdGhpcy50b29sdGlwUG9zaXRpb25DYWxsYmFjaztcbiAgICB9XG5cbiAgICB0aGlzLnRvb2x0aXBQb3NpdGlvbkNhbGxiYWNrID0gKFxuICAgICAgcG9pbnQ6IFtudW1iZXIsIG51bWJlcl0sIC8vIHBvc2l0aW9uIG9mIG1vdXNlIGluIGNoYXJ0IFtYLCBZXTsgMCwwIGlzIHRvcCBsZWZ0IGNvcm5lclxuICAgICAgXzogYW55LCAvLyB0b29sdGlwIGRhdGFcbiAgICAgIGRvbTogSFRNTEVsZW1lbnQgfCB1bmtub3duLCAvLyB0b29sdGlwIGVsZW1lbnRcbiAgICAgIF9fOiBhbnksXG4gICAgICBzaXplOiB7XG4gICAgICAgIGNvbnRlbnRTaXplOiBbbnVtYmVyLCBudW1iZXJdOyAvLyBzaXplIG9mIHRvb2x0aXBcbiAgICAgICAgdmlld1NpemU6IFtudW1iZXIsIG51bWJlcl07XG4gICAgICB9IHwgbnVsbCAvLyBzaXplIG9mIGNoYXJ0XG4gICAgKSA9PiB7XG4gICAgICBjb25zdCBvZmZzZXQgPSAxMDtcbiAgICAgIGNvbnN0IFttb3VzZVgsIG1vdXNlWV0gPSBwb2ludDtcbiAgICAgIGNvbnN0IGNoYXJ0V2lkdGggPSBzaXplPy52aWV3U2l6ZVswXSB8fCAwO1xuICAgICAgY29uc3QgY2hhcnRIZWlnaHQgPSBzaXplPy52aWV3U2l6ZVsxXSB8fCAwO1xuICAgICAgY29uc3QgdG9vbHRpcFdpZHRoID0gc2l6ZT8uY29udGVudFNpemVbMF0gfHwgMDtcbiAgICAgIGNvbnN0IHRvb2x0aXBIZWlnaHQgPSBzaXplPy5jb250ZW50U2l6ZVsxXSB8fCAwO1xuICAgICAgY29uc3QgdG9vbHRpcFJlY3QgPSAoZG9tIGFzIEhUTUxFbGVtZW50KT8uZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICBjb25zdCB0b29sdGlwT3ZlcmZsb3dzQm90dG9tRWRnZSA9IHRvb2x0aXBSZWN0LmJvdHRvbSA+IHdpbmRvdy5pbm5lckhlaWdodDtcblxuICAgICAgY29uc3QgdG9vbHRpcE92ZXJmbG93c1JpZ2h0RWRnZSA9IHRvb2x0aXBSZWN0LnJpZ2h0ID4gd2luZG93LmlubmVyV2lkdGg7XG5cbiAgICAgIGNvbnN0IHRvb2x0aXBXb3VsZE92ZXJmbG93Qm90dG9tRWRnZU9uUG9zaXRpb25DaGFuZ2UgPVxuICAgICAgICAhbGFzdFBvc2l0aW9uT2ZUb29sdGlwLnRvcCAmJlxuICAgICAgICB0b29sdGlwUmVjdC5ib3R0b20gKyAyICogb2Zmc2V0ICsgdG9vbHRpcEhlaWdodCA+IHdpbmRvdy5pbm5lckhlaWdodDtcblxuICAgICAgY29uc3QgdG9vbHRpcFdvdWxkT3ZlcmZsb3dSaWdodEVkZ2VPblBvc2l0aW9uQ2hhbmdlID1cbiAgICAgICAgIWxhc3RQb3NpdGlvbk9mVG9vbHRpcC5sZWZ0ICYmXG4gICAgICAgIHRvb2x0aXBSZWN0LnJpZ2h0ICsgMiAqIG9mZnNldCArIHRvb2x0aXBXaWR0aCA+IHdpbmRvdy5pbm5lcldpZHRoO1xuXG4gICAgICBsZXQgdmVydGljYWxQb3NpdGlvbjogeyB0b3A6IG51bWJlciB9IHwgeyBib3R0b206IG51bWJlciB9ID0ge1xuICAgICAgICB0b3A6IG1vdXNlWSArIG9mZnNldFxuICAgICAgfTtcbiAgICAgIGxldCBob3Jpem9udGFsUG9zaXRpb246IHsgbGVmdDogbnVtYmVyIH0gfCB7IHJpZ2h0OiBudW1iZXIgfSA9IHtcbiAgICAgICAgbGVmdDogbW91c2VYICsgb2Zmc2V0XG4gICAgICB9O1xuXG4gICAgICBpZiAodG9vbHRpcE92ZXJmbG93c0JvdHRvbUVkZ2UgfHwgdG9vbHRpcFdvdWxkT3ZlcmZsb3dCb3R0b21FZGdlT25Qb3NpdGlvbkNoYW5nZSkge1xuICAgICAgICB2ZXJ0aWNhbFBvc2l0aW9uID0ge1xuICAgICAgICAgIGJvdHRvbTogY2hhcnRIZWlnaHQgLSBtb3VzZVkgKyBvZmZzZXRcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICAgIGlmICh0b29sdGlwT3ZlcmZsb3dzUmlnaHRFZGdlIHx8IHRvb2x0aXBXb3VsZE92ZXJmbG93UmlnaHRFZGdlT25Qb3NpdGlvbkNoYW5nZSkge1xuICAgICAgICBob3Jpem9udGFsUG9zaXRpb24gPSB7XG4gICAgICAgICAgcmlnaHQ6IGNoYXJ0V2lkdGggLSBtb3VzZVggKyBvZmZzZXRcbiAgICAgICAgfTtcbiAgICAgIH1cblxuICAgICAgbGFzdFBvc2l0aW9uT2ZUb29sdGlwID0ge1xuICAgICAgICAuLi52ZXJ0aWNhbFBvc2l0aW9uLFxuICAgICAgICAuLi5ob3Jpem9udGFsUG9zaXRpb25cbiAgICAgIH07XG4gICAgICByZXR1cm4gbGFzdFBvc2l0aW9uT2ZUb29sdGlwO1xuICAgIH07XG4gICAgcmV0dXJuIHRoaXMudG9vbHRpcFBvc2l0aW9uQ2FsbGJhY2s7XG4gIH1cblxuICAvKipcbiAgICogVGhpcyBtZXRob2QgaXMgdXNlZCB0byBhZGQgdGhlIGRhdGEgcG9pbnQgaW5mbyB0byB0aGUgdG9vbHRpcC5cbiAgICogQHBhcmFtIGFsbERhdGFQb2ludFNlcmllcyAtIEFsbCB0aGUgZGF0YSBwb2ludCBzZXJpZXMuXG4gICAqIEBwYXJhbSBYQXhpc1ZhbHVlIC0gVGhlIFggQXhpcyB2YWx1ZS5cbiAgICogQHBhcmFtIFlBeGlzUmVhZGluZ3MgLSBUaGUgWSBBeGlzIHJlYWRpbmdzLlxuICAgKi9cbiAgcHJpdmF0ZSBwcm9jZXNzU2VyaWVzKFxuICAgIGFsbERhdGFQb2ludFNlcmllczogQ3VzdG9tU2VyaWVzT3B0aW9uc1tdLFxuICAgIFhBeGlzVmFsdWU6IHN0cmluZyxcbiAgICBZQXhpc1JlYWRpbmdzOiBzdHJpbmdbXVxuICApOiB2b2lkIHtcbiAgICBhbGxEYXRhUG9pbnRTZXJpZXMuZm9yRWFjaCgoc2VyaWVzOiBhbnkpID0+IHtcbiAgICAgIGxldCB2YWx1ZSA9ICcnO1xuICAgICAgaWYgKHNlcmllcy5pZC5lbmRzV2l0aCgnL21pbicpKSB7XG4gICAgICAgIHZhbHVlID0gdGhpcy5wcm9jZXNzTWluU2VyaWVzKHNlcmllcywgYWxsRGF0YVBvaW50U2VyaWVzLCBYQXhpc1ZhbHVlKTtcbiAgICAgIH0gZWxzZSBpZiAoIXNlcmllcy5pZC5lbmRzV2l0aCgnL21heCcpKSB7XG4gICAgICAgIHZhbHVlID0gdGhpcy5wcm9jZXNzUmVndWxhclNlcmllcyhzZXJpZXMsIFhBeGlzVmFsdWUpO1xuICAgICAgfVxuXG4gICAgICBpZiAodmFsdWUpIHtcbiAgICAgICAgWUF4aXNSZWFkaW5ncy5wdXNoKFxuICAgICAgICAgIGA8ZGl2IGNsYXNzPVwiZC1mbGV4IGEtaS1jZW50ZXIgcC1iLThcIj48c3BhbiBjbGFzcz0nZGx0LWM4eS1pY29uLWNpcmNsZSBtLXItNCcgc3R5bGU9J2NvbG9yOiAke3Nlcmllcy5pdGVtU3R5bGUuY29sb3J9Oyc+PC9zcGFuPmAgKyAvLyBjb2xvciBjaXJjbGVcbiAgICAgICAgICAgIGA8c3Ryb25nPiR7c2VyaWVzLmRhdGFwb2ludExhYmVsfTwvc3Ryb25nPjwvZGl2PmAgKyAvLyBuYW1lXG4gICAgICAgICAgICBgJHt2YWx1ZX1gIC8vIHNpbmdsZSB2YWx1ZSBvciBtaW4tbWF4IHJhbmdlXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogVGhpcyBtZXRob2QgaXMgdXNlZCB0byBwcm9jZXNzIHRoZSBtaW4gc2VyaWVzLlxuICAgKiBAcGFyYW0gc2VyaWVzIC0gVGhlIHNlcmllcy5cbiAgICogQHBhcmFtIGFsbERhdGFQb2ludFNlcmllcyAtIEFsbCB0aGUgZGF0YSBwb2ludCBzZXJpZXMuXG4gICAqIEBwYXJhbSBYQXhpc1ZhbHVlIC0gVGhlIFggQXhpcyB2YWx1ZS5cbiAgICogQHJldHVybnMgVGhlIHByb2Nlc3NlZCB2YWx1ZS5cbiAgICovXG4gIHByaXZhdGUgcHJvY2Vzc01pblNlcmllcyhcbiAgICBzZXJpZXM6IGFueSxcbiAgICBhbGxEYXRhUG9pbnRTZXJpZXM6IEN1c3RvbVNlcmllc09wdGlvbnNbXSxcbiAgICBYQXhpc1ZhbHVlOiBzdHJpbmdcbiAgKTogc3RyaW5nIHtcbiAgICBjb25zdCBtaW5WYWx1ZSA9IHRoaXMuZmluZFZhbHVlRm9yRXhhY3RPckVhcmxpZXJUaW1lc3RhbXAoc2VyaWVzLmRhdGEsIFhBeGlzVmFsdWUpO1xuICAgIGlmICghbWluVmFsdWUpIHtcbiAgICAgIHJldHVybiAnJztcbiAgICB9XG4gICAgY29uc3QgbWF4U2VyaWVzID0gYWxsRGF0YVBvaW50U2VyaWVzLmZpbmQocyA9PiBzWydpZCddID09PSBzZXJpZXMuaWQucmVwbGFjZSgnL21pbicsICcvbWF4JykpO1xuICAgIGNvbnN0IG1heFZhbHVlID0gdGhpcy5maW5kVmFsdWVGb3JFeGFjdE9yRWFybGllclRpbWVzdGFtcChcbiAgICAgIG1heFNlcmllcz8uWydkYXRhJ10gYXMgU2VyaWVzVmFsdWVbXSxcbiAgICAgIFhBeGlzVmFsdWVcbiAgICApO1xuICAgIHJldHVybiAoXG4gICAgICBgPGRpdiBjbGFzcz1cImQtZmxleCBhLWktY2VudGVyIHNlcGFyYXRvci10b3AgcC10LTggcC1iLThcIj48bGFiZWwgY2xhc3M9XCJ0ZXh0LTEyIG0tci04IG0tYi0wXCI+JHt0aGlzLmRhdGVQaXBlLnRyYW5zZm9ybShtaW5WYWx1ZVswXSl9PC9sYWJlbD5gICtcbiAgICAgIGA8c3BhbiBjbGFzcz1cIm0tbC1hdXRvIHRleHQtMTJcIj4ke21pblZhbHVlWzFdfSDigJQgJHttYXhWYWx1ZT8uWzFdfWAgK1xuICAgICAgKHNlcmllcy5kYXRhcG9pbnRVbml0ID8gYCAke3Nlcmllcy5kYXRhcG9pbnRVbml0fWAgOiAnJykgK1xuICAgICAgYDwvc3Bhbj48L2Rpdj5gXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGlzIG1ldGhvZCBpcyB1c2VkIHRvIHByb2Nlc3MgdGhlIHJlZ3VsYXIgc2VyaWVzLlxuICAgKiBAcGFyYW0gc2VyaWVzIC0gVGhlIHNlcmllcy5cbiAgICogQHBhcmFtIFhBeGlzVmFsdWUgLSBUaGUgWCBBeGlzIHZhbHVlLlxuICAgKiBAcmV0dXJucyBUaGUgcHJvY2Vzc2VkIHZhbHVlLlxuICAgKi9cbiAgcHJpdmF0ZSBwcm9jZXNzUmVndWxhclNlcmllcyhzZXJpZXM6IGFueSwgWEF4aXNWYWx1ZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgICBjb25zdCBzZXJpZXNWYWx1ZSA9IHRoaXMuZmluZFZhbHVlRm9yRXhhY3RPckVhcmxpZXJUaW1lc3RhbXAoc2VyaWVzLmRhdGEsIFhBeGlzVmFsdWUpO1xuICAgIGlmICghc2VyaWVzVmFsdWUpIHtcbiAgICAgIHJldHVybiAnJztcbiAgICB9XG4gICAgcmV0dXJuIChcbiAgICAgIGA8ZGl2IGNsYXNzPVwiZC1mbGV4IGEtaS1jZW50ZXIgcC10LTggcC1iLTggc2VwYXJhdG9yLXRvcFwiPmAgK1xuICAgICAgYDxsYWJlbCBjbGFzcz1cIm0tYi0wIG0tci04IHRleHQtMTJcIj4ke3RoaXMuZGF0ZVBpcGUudHJhbnNmb3JtKFxuICAgICAgICBzZXJpZXNWYWx1ZVswXVxuICAgICAgKX08L2xhYmVsPjxzcGFuIGNsYXNzPVwibS1sLWF1dG8gdGV4dC0xMlwiPmAgK1xuICAgICAgc2VyaWVzVmFsdWVbMV0/LnRvU3RyaW5nKCkgK1xuICAgICAgKHNlcmllcy5kYXRhcG9pbnRVbml0ID8gYCAke3Nlcmllcy5kYXRhcG9pbnRVbml0fWAgOiAnJykgK1xuICAgICAgYDwvc3Bhbj48L2Rpdj5gXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGlzIG1ldGhvZCBpcyB1c2VkIHRvIHByb2Nlc3MgdGhlIGV2ZW50IHRvb2x0aXAuXG4gICAqIEBwYXJhbSBldmVudCAtIFRoZSBldmVudCBvYmplY3QuXG4gICAqIEByZXR1cm5zIFRoZSBwcm9jZXNzZWQgdmFsdWUuXG4gICAqL1xuICBwcml2YXRlIHByb2Nlc3NFdmVudChldmVudDogSUV2ZW50KTogc3RyaW5nIHtcbiAgICBsZXQgdmFsdWUgPSBgPHVsIGNsYXNzPVwibGlzdC11bnN0eWxlZCBzbWFsbCBzZXBhcmF0b3ItdG9wXCI+YDtcbiAgICB2YWx1ZSArPSBgPGxpIGNsYXNzPVwicC10LTQgcC1iLTQgZC1mbGV4IHNlcGFyYXRvci1ib3R0b20gdGV4dC1uby13cmFwXCI+PGxhYmVsIGNsYXNzPVwic21hbGwgbS1iLTAgbS1yLThcIj5FdmVudCB0eXBlPC9sYWJlbD48Y29kZSBjbGFzcz1cIm0tbC1hdXRvXCI+JHtldmVudC50eXBlfTwvY29kZT48L2xpPmA7XG4gICAgdmFsdWUgKz0gYDxsaSBjbGFzcz1cInAtdC00IHAtYi00IGQtZmxleCBzZXBhcmF0b3ItYm90dG9tIHRleHQtbm8td3JhcFwiPjxsYWJlbCBjbGFzcz1cInNtYWxsIG0tYi0wIG0tci04XCI+RXZlbnQgdGV4dDwvbGFiZWw+PHNwYW4gY2xhc3M9XCJtLWwtYXV0b1wiPiR7ZXZlbnQudGV4dH08c3Bhbj48L2xpPmA7XG4gICAgdmFsdWUgKz0gYDxsaSBjbGFzcz1cInAtdC00IHAtYi00IGQtZmxleCBzZXBhcmF0b3ItYm90dG9tIHRleHQtbm8td3JhcFwiPjxsYWJlbCBjbGFzcz1cInNtYWxsIG0tYi0wIG0tci04XCI+TGFzdCB1cGRhdGU8L2xhYmVsPjxzcGFuIGNsYXNzPVwibS1sLWF1dG9cIj4ke3RoaXMuZGF0ZVBpcGUudHJhbnNmb3JtKGV2ZW50WydsYXN0VXBkYXRlZCddKX08c3Bhbj48L2xpPmA7XG4gICAgdmFsdWUgKz0gYDwvdWw+YDtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICAvKipcbiAgICogVGhpcyBtZXRob2QgaXMgdXNlZCB0byBwcm9jZXNzIHRoZSBhbGFybSB0b29sdGlwLlxuICAgKiBAcGFyYW0gYWxhcm0gLSBUaGUgYWxhcm0gb2JqZWN0LlxuICAgKiBAcmV0dXJucyBUaGUgcHJvY2Vzc2VkIHZhbHVlLlxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBwcm9jZXNzQWxhcm0oYWxhcm06IElBbGFybSk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgbGV0IHZhbHVlID0gYDx1bCBjbGFzcz1cImxpc3QtdW5zdHlsZWQgc21hbGwgc2VwYXJhdG9yLXRvcCBtLTBcIj5gO1xuICAgIHZhbHVlICs9IGA8bGkgY2xhc3M9XCJwLXQtNCBwLWItNCBkLWZsZXggYS1pLWNlbnRlciBzZXBhcmF0b3ItYm90dG9tIHRleHQtbm8td3JhcFwiPjxsYWJlbCBjbGFzcz1cInRleHQtbGFiZWwtc21hbGwgbS1iLTAgbS1yLThcIj5BbGFybSBTZXZlcml0eTwvbGFiZWw+YDtcbiAgICB2YWx1ZSArPSBgPHNwYW4gY2xhc3M9XCJzbWFsbCBkLWlubGluZS1mbGV4IGEtaS1jZW50ZXIgZ2FwLTQgbS1sLWF1dG9cIj48aSBjbGFzcz1cInN0cm9rZWQtaWNvbiBpY29uLTE0IHN0YXR1cyBkbHQtYzh5LWljb24tJHt0aGlzLnNldmVyaXR5SWNvblBpcGUudHJhbnNmb3JtKGFsYXJtLnNldmVyaXR5KX0gJHthbGFybS5zZXZlcml0eS50b0xvd2VyQ2FzZSgpfVwiID4gPC9pPiAke3RoaXMuc2V2ZXJpdHlMYWJlbFBpcGUudHJhbnNmb3JtKGFsYXJtLnNldmVyaXR5KX0gPC9zcGFuPjwvbGk+YDtcbiAgICB2YWx1ZSArPSBgPGxpIGNsYXNzPVwicC10LTQgcC1iLTQgZC1mbGV4IHNlcGFyYXRvci1ib3R0b20gdGV4dC1uby13cmFwXCI+PGxhYmVsIGNsYXNzPVwidGV4dC1sYWJlbC1zbWFsbCBtLWItMCBtLXItOFwiPkFsYXJtIFR5cGU8L2xhYmVsPjxzcGFuIGNsYXNzPVwic21hbGwgbS1sLWF1dG9cIj48Y29kZT4ke2FsYXJtLnR5cGV9PC9jb2RlPjwvc3Bhbj48L2xpPmA7XG4gICAgdmFsdWUgKz0gYDxsaSBjbGFzcz1cInAtdC00IHAtYi00IGQtZmxleCBzZXBhcmF0b3ItYm90dG9tIHRleHQtbm8td3JhcFwiPjxsYWJlbCBjbGFzcz1cInRleHQtbGFiZWwtc21hbGwgbS1iLTAgbS1yLThcIj5NZXNzYWdlPC9sYWJlbD48c3BhbiBjbGFzcz1cInNtYWxsIG0tbC1hdXRvXCIgc3R5bGU9XCJvdmVyZmxvdzogaGlkZGVuOyB0ZXh0LW92ZXJmbG93OiBlbGxpcHNpcztcIiB0aXRsZT1cIiR7YWxhcm0udGV4dH1cIj4ke2FsYXJtLnRleHR9PC9zcGFuPjwvbGk+YDtcbiAgICB2YWx1ZSArPSBgPGxpIGNsYXNzPVwicC10LTQgcC1iLTQgZC1mbGV4IHNlcGFyYXRvci1ib3R0b20gdGV4dC1uby13cmFwXCI+PGxhYmVsIGNsYXNzPVwidGV4dC1sYWJlbC1zbWFsbCBtLWItMCBtLXItOFwiPkxhc3QgVXBkYXRlZDwvbGFiZWw+PHNwYW4gY2xhc3M9XCJzbWFsbCBtLWwtYXV0b1wiPiR7dGhpcy5kYXRlUGlwZS50cmFuc2Zvcm0oYWxhcm1bJ2xhc3RVcGRhdGVkJ10pfTwvc3Bhbj48L2xpPmA7XG4gICAgY29uc3QgZXhpc3RzID0gYXdhaXQgdGhpcy5hbGFybVJvdXRlRXhpc3RzKCk7XG4gICAgaWYgKGV4aXN0cykge1xuICAgICAgY29uc3QgY3VycmVudFVybCA9IHdpbmRvdy5sb2NhdGlvbi5ocmVmO1xuICAgICAgY29uc3QgYmFzZVVybEluZGV4ID0gY3VycmVudFVybC5pbmRleE9mKElOREVYX0hUTUwpO1xuICAgICAgY29uc3QgYmFzZVVybCA9IGN1cnJlbnRVcmwuc3Vic3RyaW5nKDAsIGJhc2VVcmxJbmRleCArIElOREVYX0hUTUwubGVuZ3RoKTtcbiAgICAgIHZhbHVlICs9IGA8bGkgY2xhc3M9XCJwLXQtNCBwLWItNCBkLWZsZXggc2VwYXJhdG9yLWJvdHRvbSB0ZXh0LW5vLXdyYXBcIj48bGFiZWwgY2xhc3M9XCJ0ZXh0LWxhYmVsLXNtYWxsIG0tYi0wIG0tci04XCI+TGluazwvbGFiZWw+PHNwYW4gY2xhc3M9XCJzbWFsbCBtLWwtYXV0b1wiPjxhIGhyZWY9XCIke2Jhc2VVcmx9Iy9hbGFybXMvJHthbGFybS5pZH1cIj5BbGFybSBEZXRhaWxzPC9hPjwvc3Bhbj48L2xpPmA7XG4gICAgfVxuICAgIHZhbHVlICs9IGA8bGkgY2xhc3M9XCJwLXQtNCBwLWItNCBkLWZsZXggdGV4dC1uby13cmFwXCI+PGxhYmVsIGNsYXNzPVwidGV4dC1sYWJlbC1zbWFsbCBtLWItMCBtLXItOFwiPkFsYXJtIGNvdW50PC9sYWJlbD48c3BhbiBjbGFzcz1cInNtYWxsIG0tbC1hdXRvXCI+PHNwYW4gY2xhc3M9XCJiYWRnZSBiYWRnZS1pbmZvXCI+JHthbGFybS5jb3VudH08L3NwYW4+PC9zcGFuPjwvbGk+YDtcbiAgICB2YWx1ZSArPSBgPC91bD5gO1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgYWxhcm1Sb3V0ZUV4aXN0cygpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICBjb25zdCBleGlzdHMgPSB0aGlzLnJvdXRlci5jb25maWcuc29tZShyb3V0ZSA9PiB7XG4gICAgICByZXR1cm4gYCR7cm91dGUucGF0aH1gID09PSAnYWxhcm1zJztcbiAgICB9KTtcbiAgICByZXR1cm4gZXhpc3RzO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRDaGFydFNlcmllcyhcbiAgICBkYXRhcG9pbnRzV2l0aFZhbHVlczogRHBXaXRoVmFsdWVzW10sXG4gICAgZXZlbnRzOiBJRXZlbnRbXSxcbiAgICBhbGFybXM6IElBbGFybVtdLFxuICAgIGRpc3BsYXlPcHRpb25zOiB7IGRpc3BsYXlNYXJrZWRMaW5lOiBib29sZWFuOyBkaXNwbGF5TWFya2VkUG9pbnQ6IGJvb2xlYW4gfVxuICApOiBDdXN0b21TZXJpZXNPcHRpb25zW10gfCBTZXJpZXNPcHRpb25bXSB7XG4gICAgY29uc3Qgc2VyaWVzOiBTZXJpZXNPcHRpb25bXSA9IFtdO1xuICAgIGxldCBldmVudFNlcmllczogQ3VzdG9tU2VyaWVzT3B0aW9uc1tdID0gW107XG4gICAgbGV0IGFsYXJtU2VyaWVzOiBDdXN0b21TZXJpZXNPcHRpb25zW10gPSBbXTtcbiAgICBkYXRhcG9pbnRzV2l0aFZhbHVlcy5mb3JFYWNoKChkcCwgaWR4KSA9PiB7XG4gICAgICBjb25zdCByZW5kZXJUeXBlOiBEYXRhcG9pbnRDaGFydFJlbmRlclR5cGUgPSBkcC5yZW5kZXJUeXBlIHx8ICdtaW4nO1xuICAgICAgaWYgKHJlbmRlclR5cGUgPT09ICdhcmVhJykge1xuICAgICAgICBzZXJpZXMucHVzaCh0aGlzLmdldFNpbmdsZVNlcmllcyhkcCwgJ21pbicsIGlkeCwgdHJ1ZSkpO1xuICAgICAgICBzZXJpZXMucHVzaCh0aGlzLmdldFNpbmdsZVNlcmllcyhkcCwgJ21heCcsIGlkeCwgdHJ1ZSkpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgc2VyaWVzLnB1c2godGhpcy5nZXRTaW5nbGVTZXJpZXMoZHAsIHJlbmRlclR5cGUsIGlkeCwgZmFsc2UpKTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgbmV3RXZlbnRTZXJpZXMgPSB0aGlzLmdldEFsYXJtT3JFdmVudFNlcmllcyhcbiAgICAgICAgZHAsXG4gICAgICAgIHJlbmRlclR5cGUsXG4gICAgICAgIGZhbHNlLFxuICAgICAgICBldmVudHMsXG4gICAgICAgICdldmVudCcsXG4gICAgICAgIGRpc3BsYXlPcHRpb25zLFxuICAgICAgICBudWxsLFxuICAgICAgICBpZHhcbiAgICAgICk7XG4gICAgICBjb25zdCBuZXdBbGFybVNlcmllcyA9IHRoaXMuZ2V0QWxhcm1PckV2ZW50U2VyaWVzKFxuICAgICAgICBkcCxcbiAgICAgICAgcmVuZGVyVHlwZSxcbiAgICAgICAgZmFsc2UsXG4gICAgICAgIGFsYXJtcyxcbiAgICAgICAgJ2FsYXJtJyxcbiAgICAgICAgZGlzcGxheU9wdGlvbnMsXG4gICAgICAgIG51bGwsXG4gICAgICAgIGlkeFxuICAgICAgKTtcbiAgICAgIGV2ZW50U2VyaWVzID0gWy4uLmV2ZW50U2VyaWVzLCAuLi5uZXdFdmVudFNlcmllc107XG4gICAgICBhbGFybVNlcmllcyA9IFsuLi5hbGFybVNlcmllcywgLi4ubmV3QWxhcm1TZXJpZXNdO1xuICAgIH0pO1xuICAgIGNvbnN0IGRlZHVwbGljYXRlRmlsdGVyQ2FsbGJhY2sgPSAoXG4gICAgICBvYmoxOiBDdXN0b21TZXJpZXNPcHRpb25zLFxuICAgICAgaTogbnVtYmVyLFxuICAgICAgYXJyOiBTZXJpZXNPcHRpb25bXVxuICAgICk6IG9iajEgaXMgQ3VzdG9tU2VyaWVzT3B0aW9ucyA9PiB7XG4gICAgICBjb25zdCBkdXBsaWNhdGVzID0gYXJyLmZpbHRlcihvYmoyID0+IG9iajFbJ2lkJ10gPT09IG9iajJbJ2lkJ10gJiYgaSAhPT0gYXJyLmluZGV4T2Yob2JqMikpO1xuXG4gICAgICBpZiAoZHVwbGljYXRlcy5sZW5ndGggPiAwKSB7XG4gICAgICAgIHJldHVybiBvYmoxWydpc0RwVGVtcGxhdGVTZWxlY3RlZCddIGFzIGJvb2xlYW47XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH07XG5cbiAgICBjb25zdCBkZWR1cGxpY2F0ZUZpbHRlckNhbGxiYWNrRmFsbGJhY2sgPSAoXG4gICAgICBvYmoxOiBTZXJpZXNPcHRpb24sXG4gICAgICBpOiBudW1iZXIsXG4gICAgICBhcnI6IFNlcmllc09wdGlvbltdXG4gICAgKTogb2JqMSBpcyBTZXJpZXNPcHRpb24gPT4gYXJyLmZpbmRJbmRleChvYmoyID0+IG9iajJbJ2lkJ10gPT09IG9iajFbJ2lkJ10pID09PSBpO1xuXG4gICAgbGV0IGRlZHVwbGljYXRlZEV2ZW50cyA9IGV2ZW50U2VyaWVzLmZpbHRlcihkZWR1cGxpY2F0ZUZpbHRlckNhbGxiYWNrKTtcbiAgICBsZXQgZGVkdXBsaWNhdGVkQWxhcm1zID0gYWxhcm1TZXJpZXMuZmlsdGVyKGRlZHVwbGljYXRlRmlsdGVyQ2FsbGJhY2spO1xuICAgIGlmIChkZWR1cGxpY2F0ZWRBbGFybXMubGVuZ3RoID09PSAwKSB7XG4gICAgICBkZWR1cGxpY2F0ZWRBbGFybXMgPSBhbGFybVNlcmllcy5maWx0ZXIoZGVkdXBsaWNhdGVGaWx0ZXJDYWxsYmFja0ZhbGxiYWNrKTtcbiAgICB9XG4gICAgaWYgKGRlZHVwbGljYXRlZEV2ZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgIGRlZHVwbGljYXRlZEV2ZW50cyA9IGV2ZW50U2VyaWVzLmZpbHRlcihkZWR1cGxpY2F0ZUZpbHRlckNhbGxiYWNrRmFsbGJhY2spO1xuICAgIH1cbiAgICByZXR1cm4gWy4uLnNlcmllcywgLi4uZGVkdXBsaWNhdGVkRXZlbnRzLCAuLi5kZWR1cGxpY2F0ZWRBbGFybXNdO1xuICB9XG5cbiAgcHJpdmF0ZSBncm91cEJ5VHlwZShcbiAgICBpdGVtczogSUFsYXJtW10gfCBJRXZlbnRbXSxcbiAgICB0eXBlRmllbGQ6IHN0cmluZ1xuICApOiBSZWNvcmQ8c3RyaW5nLCBJQWxhcm1bXSB8IElFdmVudFtdPiB7XG4gICAgcmV0dXJuIGl0ZW1zLnJlZHVjZSgoZ3JvdXBlZCwgaXRlbSkgPT4ge1xuICAgICAgKGdyb3VwZWRbaXRlbVt0eXBlRmllbGRdXSA9IGdyb3VwZWRbaXRlbVt0eXBlRmllbGRdXSB8fCBbXSkucHVzaChpdGVtKTtcbiAgICAgIHJldHVybiBncm91cGVkO1xuICAgIH0sIHt9IGFzIGFueSk7XG4gIH1cblxuICAvKipcbiAgICogVGhpcyBtZXRob2QgaW50ZXJwb2xhdGVzIGJldHdlZW4gdHdvIGRhdGEgcG9pbnRzLiBUaGUgZ29hbCBpcyB0byBwbGFjZSB0aGUgbWFya1BvaW50IG9uIHRoZSBjaGFydCBpbiB0aGUgcmlnaHQgcGxhY2UuXG4gICAqIEBwYXJhbSBkcFZhbHVlc0FycmF5IGFycmF5IG9mIGRhdGEgcG9pbnRzXG4gICAqIEBwYXJhbSB0YXJnZXRUaW1lIHRpbWUgb2YgdGhlIGFsYXJtIG9yIGV2ZW50XG4gICAqIEByZXR1cm5zIGludGVycG9sYXRlZCBkYXRhIHBvaW50XG4gICAqL1xuICBwcml2YXRlIGludGVycG9sYXRlQmV0d2VlblR3b0RwcyhcbiAgICBkcFZhbHVlc0FycmF5OiBEcFZhbHVlc0l0ZW1bXSxcbiAgICB0YXJnZXRUaW1lOiBudW1iZXJcbiAgKTogRHBWYWx1ZXNJdGVtIHtcbiAgICBsZXQgbWF4VmFsdWU6IG51bWJlcjtcbiAgICBsZXQgbWluVmFsdWU6IG51bWJlcjtcbiAgICByZXR1cm4gZHBWYWx1ZXNBcnJheS5yZWR1Y2UoKGFjYywgY3VyciwgaWR4LCBhcnIpID0+IHtcbiAgICAgIGlmIChuZXcgRGF0ZShjdXJyLnRpbWUpLmdldFRpbWUoKSA8PSB0YXJnZXRUaW1lKSB7XG4gICAgICAgIGlmIChpZHggPT09IGFyci5sZW5ndGggLSAxKSB7XG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHRpbWU6IHRhcmdldFRpbWUsXG4gICAgICAgICAgICB2YWx1ZXM6IFt7IG1pbjogbWluVmFsdWUsIG1heDogbWF4VmFsdWUgfV1cbiAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IG5leHREcCA9IGFycltpZHggKyAxXTtcbiAgICAgICAgaWYgKG5ldyBEYXRlKG5leHREcC50aW1lKS5nZXRUaW1lKCkgPj0gdGFyZ2V0VGltZSkge1xuICAgICAgICAgIGNvbnN0IHRpbWVEaWZmID0gbmV3IERhdGUobmV4dERwLnRpbWUpLmdldFRpbWUoKSAtIG5ldyBEYXRlKGN1cnIudGltZSkuZ2V0VGltZSgpO1xuICAgICAgICAgIGNvbnN0IHRhcmdldFRpbWVEaWZmID0gdGFyZ2V0VGltZSAtIG5ldyBEYXRlKGN1cnIudGltZSkuZ2V0VGltZSgpO1xuICAgICAgICAgIGNvbnN0IG1pblZhbHVlRGlmZiA9IG5leHREcC52YWx1ZXNbMF0/Lm1pbiAtIGN1cnIudmFsdWVzWzBdPy5taW47XG4gICAgICAgICAgY29uc3QgbWF4VmFsdWVEaWZmID0gbmV4dERwLnZhbHVlc1swXT8ubWF4IC0gY3Vyci52YWx1ZXNbMF0/Lm1heDtcbiAgICAgICAgICBtaW5WYWx1ZSA9IGN1cnIudmFsdWVzWzBdPy5taW4gKyAobWluVmFsdWVEaWZmICogdGFyZ2V0VGltZURpZmYpIC8gdGltZURpZmY7XG4gICAgICAgICAgbWF4VmFsdWUgPSBjdXJyLnZhbHVlc1swXT8ubWF4ICsgKG1heFZhbHVlRGlmZiAqIHRhcmdldFRpbWVEaWZmKSAvIHRpbWVEaWZmO1xuICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICB0aW1lOiB0YXJnZXRUaW1lLFxuICAgICAgICAgICAgdmFsdWVzOiBbeyBtaW46IG1pblZhbHVlLCBtYXg6IG1heFZhbHVlIH1dXG4gICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIGFjYztcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0Q2xvc2VzdERwVmFsdWVUb1RhcmdldFRpbWUoXG4gICAgZHBWYWx1ZXNBcnJheTogRHBWYWx1ZXNJdGVtW10sXG4gICAgdGFyZ2V0VGltZTogbnVtYmVyXG4gICk6IERwVmFsdWVzSXRlbSB7XG4gICAgcmV0dXJuIGRwVmFsdWVzQXJyYXkucmVkdWNlKChwcmV2LCBjdXJyKSA9PlxuICAgICAgLy9zaG91bGQgdGFrZSB0aGUgdmFsdWUgY2xvc2VzdCB0byB0aGUgdGFyZ2V0IHRpbWUsIGZvciByZWFsdGltZSB0aGUgY3VycmVudCB0aW1lIHdvdWxkIGFsd2F5cyBjaGFuZ2VcbiAgICAgIE1hdGguYWJzKG5ldyBEYXRlKGN1cnIudGltZSkuZ2V0VGltZSgpIC0gdGFyZ2V0VGltZSkgPFxuICAgICAgTWF0aC5hYnMobmV3IERhdGUocHJldi50aW1lKS5nZXRUaW1lKCkgLSB0YXJnZXRUaW1lKVxuICAgICAgICA/IGN1cnJcbiAgICAgICAgOiBwcmV2XG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGlzIG1ldGhvZCBjcmVhdGVzIGEgbWFya1BvaW50IG9uIHRoZSBjaGFydCB3aGljaCByZXByZXNlbnRzIHRoZSBpY29uIG9mIHRoZSBhbGFybSBvciBldmVudC5cbiAgICogQHBhcmFtIGl0ZW0gU2luZ2xlIGFsYXJtIG9yIGV2ZW50XG4gICAqIEBwYXJhbSBkcCBEYXRhIHBvaW50XG4gICAqIEBwYXJhbSBpc0NsZWFyZWQgSWYgdGhlIGFsYXJtIGlzIGNsZWFyZWQgaW4gY2FzZSBvZiBhbGFybVxuICAgKiBAcGFyYW0gaXNFdmVudCBJZiB0aGUgaXRlbSBpcyBhbiBldmVudFxuICAgKiBAcGFyYW0gcmVhbHRpbWUgSWYgdGhlIGNoYXJ0IGlzIGluIHJlYWx0aW1lIG1vZGVcbiAgICogQHJldHVybnMgTWFya1BvaW50RGF0YUl0ZW1PcHRpb25bXVxuICAgKi9cbiAgcHJpdmF0ZSBjcmVhdGVNYXJrUG9pbnQoXG4gICAgaXRlbTogSUFsYXJtIHwgSUV2ZW50LFxuICAgIGRwOiBEcFdpdGhWYWx1ZXMsXG4gICAgaXNDbGVhcmVkOiBib29sZWFuLFxuICAgIGlzRXZlbnQ6IGJvb2xlYW4sXG4gICAgcmVhbHRpbWU6IGJvb2xlYW5cbiAgKTogTWFya1BvaW50RGF0YVtdIHtcbiAgICAvLyBjaGVjayBpZiBkcC52YWx1ZXMgb2JqZWN0IGlzIGVtcHR5XG4gICAgaWYgKCFpdGVtLmNyZWF0aW9uVGltZSB8fCBPYmplY3Qua2V5cyhkcC52YWx1ZXMpLmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuIFtdO1xuICAgIH1cblxuICAgIGNvbnN0IGRwVmFsdWVzQXJyYXk6IERwVmFsdWVzSXRlbVtdID0gT2JqZWN0LmVudHJpZXMoZHAudmFsdWVzKS5tYXAoKFt0aW1lLCB2YWx1ZXNdKSA9PiAoe1xuICAgICAgdGltZTogbmV3IERhdGUodGltZSkuZ2V0VGltZSgpLFxuICAgICAgdmFsdWVzXG4gICAgfSkpO1xuICAgIGNvbnN0IGNyZWF0aW9uVGltZSA9IG5ldyBEYXRlKGl0ZW0uY3JlYXRpb25UaW1lKS5nZXRUaW1lKCk7XG4gICAgY29uc3QgbGFzdFVwZGF0ZWRUaW1lID0gbmV3IERhdGUoaXRlbVsnbGFzdFVwZGF0ZWQnXSkuZ2V0VGltZSgpO1xuXG4gICAgbGV0IGNvb3JkQ3JlYXRpb25UaW1lOiBhbnk7XG4gICAgbGV0IGNvb3JkTGFzdFVwZGF0ZWRUaW1lOiBhbnk7XG5cbiAgICBpZiAocmVhbHRpbWUpIHtcbiAgICAgIGNvbnN0IGxhc3RWYWx1ZSA9IGRwVmFsdWVzQXJyYXlbZHBWYWx1ZXNBcnJheS5sZW5ndGggLSAxXTtcbiAgICAgIGNvb3JkQ3JlYXRpb25UaW1lID0gW1xuICAgICAgICBpdGVtLmNyZWF0aW9uVGltZSxcbiAgICAgICAgbGFzdFZhbHVlPy52YWx1ZXNbMF0/Lm1pbiA/PyBsYXN0VmFsdWU/LnZhbHVlc1sxXSA/PyBudWxsXG4gICAgICBdO1xuICAgICAgY29vcmRMYXN0VXBkYXRlZFRpbWUgPSBbXG4gICAgICAgIGl0ZW1bJ2xhc3RVcGRhdGVkJ10sXG4gICAgICAgIGxhc3RWYWx1ZT8udmFsdWVzWzBdPy5taW4gPz8gbGFzdFZhbHVlPy52YWx1ZXNbMV0gPz8gbnVsbFxuICAgICAgXTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3QgY2xvc2VzdERwVmFsdWUgPSB0aGlzLmludGVycG9sYXRlQmV0d2VlblR3b0RwcyhkcFZhbHVlc0FycmF5LCBjcmVhdGlvblRpbWUpO1xuICAgICAgY29uc3QgZHBWYWx1ZXNGb3JOZXdBbGFybXMgPSB0aGlzLmdldENsb3Nlc3REcFZhbHVlVG9UYXJnZXRUaW1lKGRwVmFsdWVzQXJyYXksIGNyZWF0aW9uVGltZSk7XG4gICAgICBjb25zdCBjbG9zZXN0RHBWYWx1ZUxhc3RVcGRhdGVkID0gdGhpcy5pbnRlcnBvbGF0ZUJldHdlZW5Ud29EcHMoXG4gICAgICAgIGRwVmFsdWVzQXJyYXksXG4gICAgICAgIGxhc3RVcGRhdGVkVGltZVxuICAgICAgKTtcbiAgICAgIGNvbnN0IGRwVmFsdWVzRm9yTmV3QWxhcm1zTGFzdFVwZGF0ZWQgPSB0aGlzLmdldENsb3Nlc3REcFZhbHVlVG9UYXJnZXRUaW1lKFxuICAgICAgICBkcFZhbHVlc0FycmF5LFxuICAgICAgICBsYXN0VXBkYXRlZFRpbWVcbiAgICAgICk7XG5cbiAgICAgIGNvb3JkQ3JlYXRpb25UaW1lID0gW1xuICAgICAgICBpdGVtLmNyZWF0aW9uVGltZSxcbiAgICAgICAgY2xvc2VzdERwVmFsdWU/LnZhbHVlc1swXT8ubWluID8/XG4gICAgICAgICAgY2xvc2VzdERwVmFsdWU/LnZhbHVlc1sxXSA/P1xuICAgICAgICAgIGRwVmFsdWVzRm9yTmV3QWxhcm1zPy52YWx1ZXNbMF0/Lm1pbiA/P1xuICAgICAgICAgIGRwVmFsdWVzRm9yTmV3QWxhcm1zPy52YWx1ZXNbMV0gPz9cbiAgICAgICAgICBudWxsXG4gICAgICBdO1xuICAgICAgY29vcmRMYXN0VXBkYXRlZFRpbWUgPSBbXG4gICAgICAgIGl0ZW1bJ2xhc3RVcGRhdGVkJ10sXG4gICAgICAgIGNsb3Nlc3REcFZhbHVlTGFzdFVwZGF0ZWQ/LnZhbHVlc1swXT8ubWluID8/XG4gICAgICAgICAgY2xvc2VzdERwVmFsdWVMYXN0VXBkYXRlZD8udmFsdWVzWzFdID8/XG4gICAgICAgICAgZHBWYWx1ZXNGb3JOZXdBbGFybXNMYXN0VXBkYXRlZD8udmFsdWVzWzBdPy5taW4gPz9cbiAgICAgICAgICBkcFZhbHVlc0Zvck5ld0FsYXJtc0xhc3RVcGRhdGVkPy52YWx1ZXNbMV0gPz9cbiAgICAgICAgICBudWxsXG4gICAgICBdO1xuICAgIH1cblxuICAgIGlmIChpc0V2ZW50KSB7XG4gICAgICByZXR1cm4gW1xuICAgICAgICB7XG4gICAgICAgICAgY29vcmQ6IGNvb3JkQ3JlYXRpb25UaW1lLFxuICAgICAgICAgIG5hbWU6IGl0ZW0udHlwZSxcbiAgICAgICAgICBpdGVtVHlwZTogaXRlbS50eXBlLFxuICAgICAgICAgIGl0ZW1TdHlsZToge1xuICAgICAgICAgICAgY29sb3I6IGl0ZW1bJ2NvbG9yJ11cbiAgICAgICAgICB9LFxuICAgICAgICAgIHN5bWJvbDogJ2NpcmNsZScsXG4gICAgICAgICAgc3ltYm9sU2l6ZTogMjRcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIGNvb3JkOiBjb29yZENyZWF0aW9uVGltZSxcbiAgICAgICAgICBuYW1lOiBpdGVtLnR5cGUsXG4gICAgICAgICAgaXRlbVR5cGU6IGl0ZW0udHlwZSxcbiAgICAgICAgICBpdGVtU3R5bGU6IHsgY29sb3I6ICd3aGl0ZScgfSxcbiAgICAgICAgICBzeW1ib2w6IElDT05TX01BUC5FVkVOVCxcbiAgICAgICAgICBzeW1ib2xTaXplOiAxNlxuICAgICAgICB9XG4gICAgICBdO1xuICAgIH1cblxuICAgIHJldHVybiBpc0NsZWFyZWRcbiAgICAgID8gW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIGNvb3JkOiBjb29yZENyZWF0aW9uVGltZSxcbiAgICAgICAgICAgIG5hbWU6IGl0ZW0udHlwZSxcbiAgICAgICAgICAgIGl0ZW1UeXBlOiBpdGVtLnR5cGUsXG4gICAgICAgICAgICBpdGVtU3R5bGU6IHtcbiAgICAgICAgICAgICAgY29sb3I6IGl0ZW1bJ2NvbG9yJ11cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBzeW1ib2w6ICdjaXJjbGUnLFxuICAgICAgICAgICAgc3ltYm9sU2l6ZTogMjRcbiAgICAgICAgICB9LFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIGNvb3JkOiBjb29yZENyZWF0aW9uVGltZSxcbiAgICAgICAgICAgIG5hbWU6IGl0ZW0udHlwZSxcbiAgICAgICAgICAgIGl0ZW1UeXBlOiBpdGVtLnR5cGUsXG4gICAgICAgICAgICBpdGVtU3R5bGU6IHsgY29sb3I6ICd3aGl0ZScgfSxcbiAgICAgICAgICAgIHN5bWJvbDogSUNPTlNfTUFQW2l0ZW0uc2V2ZXJpdHkgYXMgU2V2ZXJpdHlUeXBlXSxcbiAgICAgICAgICAgIHN5bWJvbFNpemU6IDE2XG4gICAgICAgICAgfSxcbiAgICAgICAgICB7XG4gICAgICAgICAgICBjb29yZDogY29vcmRMYXN0VXBkYXRlZFRpbWUsXG4gICAgICAgICAgICBuYW1lOiBpdGVtLnR5cGUsXG4gICAgICAgICAgICBpdGVtVHlwZTogaXRlbS50eXBlLFxuICAgICAgICAgICAgaXRlbVN0eWxlOiB7XG4gICAgICAgICAgICAgIGNvbG9yOiBpdGVtWydjb2xvciddXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc3ltYm9sOiAnY2lyY2xlJyxcbiAgICAgICAgICAgIHN5bWJvbFNpemU6IDI0XG4gICAgICAgICAgfSxcbiAgICAgICAgICB7XG4gICAgICAgICAgICBjb29yZDogY29vcmRMYXN0VXBkYXRlZFRpbWUsXG4gICAgICAgICAgICBuYW1lOiBpdGVtLnR5cGUsXG4gICAgICAgICAgICBpdGVtVHlwZTogaXRlbS50eXBlLFxuICAgICAgICAgICAgaXRlbVN0eWxlOiB7IGNvbG9yOiAnd2hpdGUnIH0sXG4gICAgICAgICAgICBzeW1ib2w6IElDT05TX01BUC5DTEVBUkVELFxuICAgICAgICAgICAgc3ltYm9sU2l6ZTogMTZcbiAgICAgICAgICB9XG4gICAgICAgIF1cbiAgICAgIDogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIGNvb3JkOiBjb29yZENyZWF0aW9uVGltZSxcbiAgICAgICAgICAgIG5hbWU6IGl0ZW0udHlwZSxcbiAgICAgICAgICAgIGl0ZW1UeXBlOiBpdGVtLnR5cGUsXG4gICAgICAgICAgICBpdGVtU3R5bGU6IHtcbiAgICAgICAgICAgICAgY29sb3I6IGl0ZW1bJ2NvbG9yJ11cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBzeW1ib2w6ICdjaXJjbGUnLFxuICAgICAgICAgICAgc3ltYm9sU2l6ZTogMjRcbiAgICAgICAgICB9LFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIGNvb3JkOiBjb29yZENyZWF0aW9uVGltZSxcbiAgICAgICAgICAgIG5hbWU6IGl0ZW0udHlwZSxcbiAgICAgICAgICAgIGl0ZW1UeXBlOiBpdGVtLnR5cGUsXG4gICAgICAgICAgICBpdGVtU3R5bGU6IHsgY29sb3I6ICd3aGl0ZScgfSxcbiAgICAgICAgICAgIHN5bWJvbDogSUNPTlNfTUFQW2l0ZW0uc2V2ZXJpdHkgYXMgU2V2ZXJpdHlUeXBlXSxcbiAgICAgICAgICAgIHN5bWJvbFNpemU6IDE2XG4gICAgICAgICAgfSxcbiAgICAgICAgICB7XG4gICAgICAgICAgICBjb29yZDogY29vcmRMYXN0VXBkYXRlZFRpbWUsXG4gICAgICAgICAgICBuYW1lOiBpdGVtLnR5cGUsXG4gICAgICAgICAgICBpdGVtVHlwZTogaXRlbS50eXBlLFxuICAgICAgICAgICAgaXRlbVN0eWxlOiB7XG4gICAgICAgICAgICAgIGNvbG9yOiBpdGVtWydjb2xvciddXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc3ltYm9sOiAnY2lyY2xlJyxcbiAgICAgICAgICAgIHN5bWJvbFNpemU6IDI0XG4gICAgICAgICAgfSxcbiAgICAgICAgICB7XG4gICAgICAgICAgICBjb29yZDogY29vcmRMYXN0VXBkYXRlZFRpbWUsXG4gICAgICAgICAgICBuYW1lOiBpdGVtLnR5cGUsXG4gICAgICAgICAgICBpdGVtVHlwZTogaXRlbS50eXBlLFxuICAgICAgICAgICAgaXRlbVN0eWxlOiB7IGNvbG9yOiAnd2hpdGUnIH0sXG4gICAgICAgICAgICBzeW1ib2w6IElDT05TX01BUFtpdGVtLnNldmVyaXR5IGFzIFNldmVyaXR5VHlwZV0sXG4gICAgICAgICAgICBzeW1ib2xTaXplOiAxNlxuICAgICAgICAgIH1cbiAgICAgICAgXTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGlzIG1ldGhvZCBjcmVhdGVzIGEgbWFya0xpbmUgb24gdGhlIGNoYXJ0IHdoaWNoIHJlcHJlc2VudHMgdGhlIGxpbmUgYmV0d2VlbiBldmVyeSBhbGFybSBvciBldmVudCBvbiB0aGUgY2hhcnQuXG4gICAqIEBwYXJhbSBpdGVtcyBBcnJheSBvZiBhbGFybXMgb3IgZXZlbnRzXG4gICAqIEByZXR1cm5zIE1hcmtMaW5lRGF0YUl0ZW1PcHRpb25CYXNlW11cbiAgICovXG4gIHByaXZhdGUgY3JlYXRlTWFya0xpbmU8VCBleHRlbmRzIElBbGFybSB8IElFdmVudD4oaXRlbXM6IFRbXSk6IE1hcmtMaW5lRGF0YVtdIHtcbiAgICByZXR1cm4gaXRlbXMucmVkdWNlPE1hcmtMaW5lRGF0YVtdPigoYWNjLCBpdGVtKSA9PiB7XG4gICAgICBpZiAoIWl0ZW0uY3JlYXRpb25UaW1lKSB7XG4gICAgICAgIHJldHVybiBhY2M7XG4gICAgICB9XG4gICAgICBpZiAoaXRlbS5jcmVhdGlvblRpbWUgPT09IGl0ZW1bJ2xhc3RVcGRhdGVkJ10pIHtcbiAgICAgICAgcmV0dXJuIGFjYy5jb25jYXQoW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIHhBeGlzOiBpdGVtLmNyZWF0aW9uVGltZSxcbiAgICAgICAgICAgIGl0ZW1UeXBlOiBpdGVtLnR5cGUsXG4gICAgICAgICAgICBsYWJlbDogeyBzaG93OiBmYWxzZSwgZm9ybWF0dGVyOiAoKSA9PiBpdGVtLnR5cGUgfSxcbiAgICAgICAgICAgIGl0ZW1TdHlsZTogeyBjb2xvcjogaXRlbVsnY29sb3InXSB9XG4gICAgICAgICAgfVxuICAgICAgICBdKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBhY2MuY29uY2F0KFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICB4QXhpczogaXRlbS5jcmVhdGlvblRpbWUsXG4gICAgICAgICAgICBpdGVtVHlwZTogaXRlbS50eXBlLFxuICAgICAgICAgICAgbGFiZWw6IHsgc2hvdzogZmFsc2UsIGZvcm1hdHRlcjogKCkgPT4gaXRlbS50eXBlIH0sXG4gICAgICAgICAgICBpdGVtU3R5bGU6IHsgY29sb3I6IGl0ZW1bJ2NvbG9yJ10gfVxuICAgICAgICAgIH0sXG4gICAgICAgICAge1xuICAgICAgICAgICAgeEF4aXM6IGl0ZW1bJ2xhc3RVcGRhdGVkJ10sXG4gICAgICAgICAgICBpdGVtVHlwZTogaXRlbS50eXBlLFxuICAgICAgICAgICAgbGFiZWw6IHsgc2hvdzogZmFsc2UsIGZvcm1hdHRlcjogKCkgPT4gaXRlbS50eXBlIH0sXG4gICAgICAgICAgICBpdGVtU3R5bGU6IHsgY29sb3I6IGl0ZW1bJ2NvbG9yJ10gfVxuICAgICAgICAgIH1cbiAgICAgICAgXSk7XG4gICAgICB9XG4gICAgfSwgW10pO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRTaW5nbGVTZXJpZXMoXG4gICAgZHA6IERwV2l0aFZhbHVlcyxcbiAgICByZW5kZXJUeXBlOiBFeGNsdWRlPERhdGFwb2ludENoYXJ0UmVuZGVyVHlwZSwgJ2FyZWEnPixcbiAgICBpZHg6IG51bWJlcixcbiAgICBpc01pbk1heENoYXJ0ID0gZmFsc2UsXG4gICAgc2VyaWVzVHlwZSA9ICcnXG4gICk6IFNlcmllc09wdGlvbiAmIFNlcmllc0RhdGFwb2ludEluZm8ge1xuICAgIGNvbnN0IGRhdGFwb2ludElkID0gZHAuX190YXJnZXQ/LmlkICsgZHAuZnJhZ21lbnQgKyBkcC5zZXJpZXM7XG4gICAgcmV0dXJuIHtcbiAgICAgIGRhdGFwb2ludElkLFxuICAgICAgZGF0YXBvaW50VW5pdDogZHAudW5pdCB8fCAnJyxcbiAgICAgIC8vICdpZCcgcHJvcGVydHkgaXMgbmVlZGVkIGFzICdzZXJpZXNJZCcgaW4gdG9vbHRpcCBmb3JtYXR0ZXJcbiAgICAgIGlkOiBpc01pbk1heENoYXJ0XG4gICAgICAgID8gYCR7ZGF0YXBvaW50SWR9LyR7cmVuZGVyVHlwZX0ke3Nlcmllc1R5cGV9YFxuICAgICAgICA6IGAke2RhdGFwb2ludElkfSR7c2VyaWVzVHlwZX1gLFxuICAgICAgbmFtZTogYCR7ZHAubGFiZWx9ICgke2RwLl9fdGFyZ2V0Py5bJ25hbWUnXX0pYCxcbiAgICAgIC8vIGRhdGFwb2ludExhYmVsIHVzZWQgdG8gcHJvcGVyIGRpc3BsYXkgb2YgdG9vbHRpcFxuICAgICAgZGF0YXBvaW50TGFiZWw6IGRwLmxhYmVsIHx8ICcnLFxuICAgICAgZGF0YTogT2JqZWN0LmVudHJpZXMoZHAudmFsdWVzKS5tYXAoKFtkYXRlU3RyaW5nLCB2YWx1ZXNdKSA9PiB7XG4gICAgICAgIHJldHVybiBbZGF0ZVN0cmluZywgdmFsdWVzWzBdW3JlbmRlclR5cGVdXTtcbiAgICAgIH0pLFxuICAgICAgeUF4aXNJbmRleDogaWR4LFxuICAgICAgLi4udGhpcy5jaGFydFR5cGVzU2VydmljZS5nZXRTZXJpZXNPcHRpb25zKGRwLCBpc01pbk1heENoYXJ0LCByZW5kZXJUeXBlKVxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogVGhpcyBtZXRob2QgY3JlYXRlcyBhIGdlbmVyYWwgdG9vbHRpcCBmb3JtYXR0ZXIgZm9yIHRoZSBjaGFydC5cbiAgICogQHJldHVybnMgVG9vbHRpcEZvcm1hdHRlckNhbGxiYWNrPFRvcExldmVsRm9ybWF0dGVyUGFyYW1zPlxuICAgKi9cbiAgcHJpdmF0ZSBnZXRUb29sdGlwRm9ybWF0dGVyKCk6IFRvb2x0aXBGb3JtYXR0ZXJDYWxsYmFjazxUb3BMZXZlbEZvcm1hdHRlclBhcmFtcz4ge1xuICAgIHJldHVybiBwYXJhbXMgPT4ge1xuICAgICAgaWYgKCFBcnJheS5pc0FycmF5KHBhcmFtcykgfHwgIXBhcmFtc1swXT8uZGF0YSkge1xuICAgICAgICByZXR1cm4gJyc7XG4gICAgICB9XG4gICAgICBjb25zdCBkYXRhID0gcGFyYW1zWzBdLmRhdGEgYXMgW3N0cmluZywgLi4uYW55W11dO1xuICAgICAgY29uc3QgWEF4aXNWYWx1ZTogc3RyaW5nID0gZGF0YVswXTtcbiAgICAgIGNvbnN0IFlBeGlzUmVhZGluZ3M6IHN0cmluZ1tdID0gW107XG4gICAgICBjb25zdCBhbGxTZXJpZXMgPSB0aGlzLmVjaGFydHNJbnN0YW5jZT8uZ2V0T3B0aW9uKClbJ3NlcmllcyddIGFzIEN1c3RvbVNlcmllc09wdGlvbnNbXTtcblxuICAgICAgY29uc3QgYWxsRGF0YVBvaW50U2VyaWVzID0gYWxsU2VyaWVzLmZpbHRlcihcbiAgICAgICAgc2VyaWVzID0+XG4gICAgICAgICAgc2VyaWVzWyd0eXBlT2ZTZXJpZXMnXSAhPT0gJ2FsYXJtJyAmJlxuICAgICAgICAgIHNlcmllc1sndHlwZU9mU2VyaWVzJ10gIT09ICdldmVudCcgJiZcbiAgICAgICAgICBzZXJpZXNbJ3R5cGVPZlNlcmllcyddICE9PSAnZmFrZSdcbiAgICAgICk7XG5cbiAgICAgIGFsbERhdGFQb2ludFNlcmllcy5mb3JFYWNoKChzZXJpZXM6IEN1c3RvbVNlcmllc09wdGlvbnMpID0+IHtcbiAgICAgICAgbGV0IHZhbHVlOiBzdHJpbmc7XG4gICAgICAgIGNvbnN0IGlkID0gc2VyaWVzWydpZCddIGFzIHN0cmluZztcbiAgICAgICAgaWYgKGlkLmVuZHNXaXRoKCcvbWluJykpIHtcbiAgICAgICAgICBjb25zdCBtaW5WYWx1ZSA9IHRoaXMuZmluZFZhbHVlRm9yRXhhY3RPckVhcmxpZXJUaW1lc3RhbXAoXG4gICAgICAgICAgICBzZXJpZXNbJ2RhdGEnXSBhcyBTZXJpZXNWYWx1ZVtdLFxuICAgICAgICAgICAgWEF4aXNWYWx1ZVxuICAgICAgICAgICk7XG4gICAgICAgICAgaWYgKCFtaW5WYWx1ZSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH1cbiAgICAgICAgICBjb25zdCBtYXhTZXJpZXMgPSBhbGxEYXRhUG9pbnRTZXJpZXMuZmluZChzID0+IHNbJ2lkJ10gPT09IGlkLnJlcGxhY2UoJy9taW4nLCAnL21heCcpKTtcbiAgICAgICAgICBpZiAoIW1heFNlcmllcykge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH1cbiAgICAgICAgICBjb25zdCBtYXhWYWx1ZSA9IHRoaXMuZmluZFZhbHVlRm9yRXhhY3RPckVhcmxpZXJUaW1lc3RhbXAoXG4gICAgICAgICAgICBtYXhTZXJpZXNbJ2RhdGEnXSBhcyBTZXJpZXNWYWx1ZVtdLFxuICAgICAgICAgICAgWEF4aXNWYWx1ZVxuICAgICAgICAgICk7XG4gICAgICAgICAgaWYgKG1heFZhbHVlID09PSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgfVxuICAgICAgICAgIHZhbHVlID1cbiAgICAgICAgICAgIGA8ZGl2IGNsYXNzPVwiZC1mbGV4IGEtaS1jZW50ZXIgc2VwYXJhdG9yLXRvcCBwLXQtOCBwLWItOFwiPmAgK1xuICAgICAgICAgICAgYDxsYWJlbCBjbGFzcz1cInRleHQtMTIgbS1yLTggbS1iLTBcIj4ke3RoaXMuZGF0ZVBpcGUudHJhbnNmb3JtKG1pblZhbHVlWzBdKX08L2xhYmVsPmAgK1xuICAgICAgICAgICAgYDxkaXYgY2xhc3M9XCJtLWwtYXV0byB0ZXh0LTEyXCIgPiR7bWluVmFsdWVbMV19IOKAlCAke21heFZhbHVlWzFdfWAgK1xuICAgICAgICAgICAgKHNlcmllc1snZGF0YXBvaW50VW5pdCddID8gYCAke3Nlcmllc1snZGF0YXBvaW50VW5pdCddfWAgOiAnJykgK1xuICAgICAgICAgICAgYDwvZGl2PjwvZGl2PmA7XG4gICAgICAgIH0gZWxzZSBpZiAoaWQuZW5kc1dpdGgoJy9tYXgnKSkge1xuICAgICAgICAgIC8vIGRvIG5vdGhpbmcsIHZhbHVlIGlzIGhhbmRsZWQgIGluICdtaW4nIGNhc2VcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY29uc3Qgc2VyaWVzVmFsdWUgPSB0aGlzLmZpbmRWYWx1ZUZvckV4YWN0T3JFYXJsaWVyVGltZXN0YW1wKFxuICAgICAgICAgICAgc2VyaWVzWydkYXRhJ10gYXMgU2VyaWVzVmFsdWVbXSxcbiAgICAgICAgICAgIFhBeGlzVmFsdWVcbiAgICAgICAgICApO1xuICAgICAgICAgIGlmICghc2VyaWVzVmFsdWUpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG4gICAgICAgICAgdmFsdWUgPVxuICAgICAgICAgICAgYDxkaXYgY2xhc3M9XCJkLWZsZXggYS1pLWNlbnRlciBzZXBhcmF0b3ItdG9wIHAtdC04IHAtYi04XCI+YCArXG4gICAgICAgICAgICBgPGxhYmVsIGNsYXNzPVwidGV4dC0xMiBtLXItOCBtLWItMFwiPiR7dGhpcy5kYXRlUGlwZS50cmFuc2Zvcm0oc2VyaWVzVmFsdWVbMF0pfTwvbGFiZWw+YCArXG4gICAgICAgICAgICBgPGRpdiBjbGFzcz1cIm0tbC1hdXRvIHRleHQtMTJcIiA+JHtzZXJpZXNWYWx1ZVsxXT8udG9TdHJpbmcoKX1gICtcbiAgICAgICAgICAgIChzZXJpZXNbJ2RhdGFwb2ludFVuaXQnXSA/IGAgJHtzZXJpZXNbJ2RhdGFwb2ludFVuaXQnXX1gIDogJycpICtcbiAgICAgICAgICAgIGA8L2Rpdj48L2Rpdj5gO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgaXRlbVN0eWxlID0gc2VyaWVzWydpdGVtU3R5bGUnXSBhcyB7IGNvbG9yOiBzdHJpbmcgfTtcblxuICAgICAgICBZQXhpc1JlYWRpbmdzLnB1c2goXG4gICAgICAgICAgYDxkaXYgY2xhc3M9XCJkLWZsZXggYS1pLWNlbnRlciBwLWItOFwiPjxzcGFuIGNsYXNzPSdkbHQtYzh5LWljb24tY2lyY2xlIG0tci00JyBzdHlsZT0nY29sb3I6ICR7aXRlbVN0eWxlLmNvbG9yfSc+PC9zcGFuPmAgKyAvLyBjb2xvciBjaXJjbGVcbiAgICAgICAgICAgIGA8c3Ryb25nPiR7c2VyaWVzWydkYXRhcG9pbnRMYWJlbCddfSA8L3N0cm9uZz48L2Rpdj5gICsgLy8gbmFtZVxuICAgICAgICAgICAgYCR7dmFsdWV9YCAvLyBzaW5nbGUgdmFsdWUgb3IgbWluLW1heCByYW5nZVxuICAgICAgICApO1xuICAgICAgfSk7XG5cbiAgICAgIHJldHVybiBgPGRpdiBzdHlsZT1cIndpZHRoOiAke3RoaXMuVE9PTFRJUF9XSURUSH1weFwiPiR7WUF4aXNSZWFkaW5ncy5qb2luKCcnKX08L2Rpdj5gO1xuICAgIH07XG4gIH1cblxuICBwcml2YXRlIGZpbmRWYWx1ZUZvckV4YWN0T3JFYXJsaWVyVGltZXN0YW1wKFxuICAgIHZhbHVlczogU2VyaWVzVmFsdWVbXSxcbiAgICB0aW1lc3RhbXBTdHJpbmc6IERhdGVTdHJpbmdcbiAgKTogU2VyaWVzVmFsdWUgfCBudWxsIHtcbiAgICBjb25zdCB0aW1lc3RhbXAgPSBuZXcgRGF0ZSh0aW1lc3RhbXBTdHJpbmcpLnZhbHVlT2YoKTtcbiAgICByZXR1cm4gdmFsdWVzLnJlZHVjZSgoYWNjOiBTZXJpZXNWYWx1ZSB8IG51bGwsIGN1cnI6IFNlcmllc1ZhbHVlKSA9PiB7XG4gICAgICBpZiAobmV3IERhdGUoY3VyclswXSkudmFsdWVPZigpIDw9IHRpbWVzdGFtcCkge1xuICAgICAgICBpZiAoXG4gICAgICAgICAgYWNjID09PSBudWxsIHx8XG4gICAgICAgICAgTWF0aC5hYnMobmV3IERhdGUoY3VyclswXSkudmFsdWVPZigpIC0gdGltZXN0YW1wKSA8XG4gICAgICAgICAgICBNYXRoLmFicyhuZXcgRGF0ZShhY2NbMF0pLnZhbHVlT2YoKSAtIHRpbWVzdGFtcClcbiAgICAgICAgKSB7XG4gICAgICAgICAgcmV0dXJuIGN1cnI7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiBhY2M7XG4gICAgfSwgbnVsbCk7XG4gIH1cbn1cbiJdfQ==