@rivet-health/design-system 40.44.0 → 40.44.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 (321) hide show
  1. package/{esm2020 → esm2022}/lib/accessibility/sr-only/sr-only.component.mjs +4 -4
  2. package/esm2022/lib/download/download.service.mjs +47 -0
  3. package/{esm2020 → esm2022}/lib/format/pipes/common.mjs +5 -5
  4. package/{esm2020 → esm2022}/lib/format/pipes/date.pipe.mjs +4 -4
  5. package/{esm2020 → esm2022}/lib/format/pipes/days.pipe.mjs +4 -4
  6. package/{esm2020 → esm2022}/lib/format/pipes/dollars.pipe.mjs +4 -4
  7. package/{esm2020 → esm2022}/lib/format/pipes/number.pipe.mjs +4 -4
  8. package/{esm2020 → esm2022}/lib/format/pipes/percentage.pipe.mjs +4 -4
  9. package/esm2022/lib/format/pipes/sentence-case.pipe.mjs +61 -0
  10. package/esm2022/lib/format/pipes/small-currency.pipe.mjs +24 -0
  11. package/esm2022/lib/format/pipes/small-number.pipe.mjs +29 -0
  12. package/esm2022/lib/format/svg-text-truncate/svg-text-truncate.directive.mjs +62 -0
  13. package/esm2022/lib/format/truncate/truncate.component.mjs +51 -0
  14. package/esm2022/lib/icon/dom-cache.mjs +32 -0
  15. package/esm2022/lib/icon/icon.component.mjs +86 -0
  16. package/{esm2020 → esm2022}/lib/icon/icons.mjs +1 -1
  17. package/{esm2020 → esm2022}/lib/input/alphabetic-field/alphabetic-field.component.mjs +4 -4
  18. package/esm2022/lib/input/auto-focus/auto-focus.directive.mjs +48 -0
  19. package/esm2022/lib/input/button/button.component.mjs +139 -0
  20. package/esm2022/lib/input/button-group/button-group.component.mjs +39 -0
  21. package/{esm2020 → esm2022}/lib/input/calendar/calendar.component.mjs +4 -4
  22. package/{esm2020 → esm2022}/lib/input/card-checkbox/card-checkbox.component.mjs +4 -4
  23. package/{esm2020 → esm2022}/lib/input/checkbox/checkbox.component.mjs +4 -4
  24. package/{esm2020 → esm2022}/lib/input/currency-field/currency-field.component.mjs +4 -4
  25. package/esm2022/lib/input/date/date.component.mjs +279 -0
  26. package/esm2022/lib/input/date-range/date-range.component.mjs +477 -0
  27. package/esm2022/lib/input/filter-chip/filter-chip.component.mjs +47 -0
  28. package/{esm2020 → esm2022}/lib/input/filter-dropdown/filter-dropdown.component.mjs +5 -5
  29. package/{esm2020 → esm2022}/lib/input/input-label/input-label.component.mjs +4 -4
  30. package/esm2022/lib/input/mentions-input/mentions-input.component.mjs +745 -0
  31. package/esm2022/lib/input/number-field/number-field.component.mjs +125 -0
  32. package/{esm2020 → esm2022}/lib/input/percentage-field/percentage-field.component.mjs +4 -4
  33. package/esm2022/lib/input/phone-field/phone-field.component.mjs +74 -0
  34. package/{esm2020 → esm2022}/lib/input/radio/radio.component.mjs +4 -4
  35. package/{esm2020 → esm2022}/lib/input/search/search.component.mjs +4 -4
  36. package/esm2022/lib/input/search-select/search-select.component.mjs +189 -0
  37. package/esm2022/lib/input/select/select/select.component.mjs +178 -0
  38. package/{esm2020 → esm2022}/lib/input/select/select-node/select-node.component.mjs +4 -4
  39. package/esm2022/lib/input/select/state.mjs +882 -0
  40. package/{esm2020 → esm2022}/lib/input/simple-select/option-group.pipe.mjs +4 -4
  41. package/esm2022/lib/input/simple-select/simple-select.component.mjs +178 -0
  42. package/esm2022/lib/input/switch-checkbox/switch-checkbox.component.mjs +33 -0
  43. package/esm2022/lib/input/text-field/text-field.component.mjs +115 -0
  44. package/{esm2020 → esm2022}/lib/input/textarea-field/textarea-field.component.mjs +4 -4
  45. package/{esm2020 → esm2022}/lib/input/validation-message/validation-message.component.mjs +4 -4
  46. package/{esm2020 → esm2022}/lib/layout/card/card-actions.component.mjs +4 -4
  47. package/esm2022/lib/layout/card/card-content.component.mjs +64 -0
  48. package/esm2022/lib/layout/card/card-header.component.mjs +201 -0
  49. package/{esm2020 → esm2022}/lib/layout/card/card-link.component.mjs +5 -5
  50. package/{esm2020 → esm2022}/lib/layout/card/card-media.component.mjs +4 -4
  51. package/esm2022/lib/layout/card/card.component.mjs +291 -0
  52. package/{esm2020 → esm2022}/lib/layout/setting-row/setting-row.component.mjs +4 -4
  53. package/esm2022/lib/load/loading/loading.component.mjs +43 -0
  54. package/{esm2020 → esm2022}/lib/load/loading-cover/loading-cover.component.mjs +4 -4
  55. package/esm2022/lib/navigation/editable-heading/editable-heading.component.mjs +243 -0
  56. package/{esm2020 → esm2022}/lib/navigation/link/link.component.mjs +6 -6
  57. package/{esm2020 → esm2022}/lib/navigation/page-header/page-header.component.mjs +4 -4
  58. package/{esm2020 → esm2022}/lib/navigation/simple-tabs/simple-tab/simple-tab.component.mjs +4 -4
  59. package/{esm2020 → esm2022}/lib/navigation/simple-tabs/simple-tabs/simple-tabs.component.mjs +4 -4
  60. package/{esm2020 → esm2022}/lib/navigation/tabs/tab/tab.component.mjs +4 -4
  61. package/{esm2020 → esm2022}/lib/navigation/tabs/tabs/tabs.component.mjs +4 -4
  62. package/{esm2020 → esm2022}/lib/navigation/views/all-views-modal/all-views-modal.component.mjs +4 -4
  63. package/{esm2020 → esm2022}/lib/navigation/views/edit-view/edit-view.component.mjs +9 -9
  64. package/esm2022/lib/navigation/views/permission-picker/permission-picker.component.mjs +151 -0
  65. package/esm2022/lib/navigation/views/state.mjs +456 -0
  66. package/{esm2020 → esm2022}/lib/navigation/views/view-menu/view-menu.component.mjs +5 -5
  67. package/esm2022/lib/navigation/views/views/views.component.mjs +90 -0
  68. package/{esm2020 → esm2022}/lib/notification/badge/badge.component.mjs +4 -4
  69. package/esm2022/lib/notification/banner/banner-action.component.mjs +48 -0
  70. package/esm2022/lib/notification/banner/banner.component.mjs +61 -0
  71. package/esm2022/lib/notification/map-indicator/map-indicator.component.mjs +50 -0
  72. package/esm2022/lib/notification/map-indicator/map-indicators.mjs +15 -0
  73. package/{esm2020 → esm2022}/lib/notification/notification-badge/notification-badge.component.mjs +4 -4
  74. package/esm2022/lib/overlay/callout/callout.component.mjs +130 -0
  75. package/esm2022/lib/overlay/callout/callout.helpers.mjs +113 -0
  76. package/{esm2020 → esm2022}/lib/overlay/callout/help/help.component.mjs +4 -4
  77. package/esm2022/lib/overlay/callout/lock-scroll.directive.mjs +69 -0
  78. package/{esm2020 → esm2022}/lib/overlay/callout/menu/menu-item/menu-item.component.mjs +5 -5
  79. package/{esm2020 → esm2022}/lib/overlay/callout/menu/menu.component.mjs +4 -4
  80. package/esm2022/lib/overlay/callout/tooltip/locked-tooltip.directive.mjs +30 -0
  81. package/{esm2020 → esm2022}/lib/overlay/callout/tooltip/tooltip.component.mjs +4 -4
  82. package/esm2022/lib/overlay/callout/tooltip/tooltip.directive.mjs +138 -0
  83. package/esm2022/lib/overlay/modal/dialog/dialog.component.mjs +47 -0
  84. package/{esm2020 → esm2022}/lib/overlay/modal/dialog-stack.service.mjs +4 -4
  85. package/esm2022/lib/overlay/modal/form-dialog/form-dialog.component.mjs +146 -0
  86. package/esm2022/lib/overlay/modal/modal.component.mjs +31 -0
  87. package/{esm2020 → esm2022}/lib/overlay/modal/side-sheet/side-sheet.component.mjs +4 -4
  88. package/esm2022/lib/overlay/overlay-outlet.component.mjs +98 -0
  89. package/{esm2020 → esm2022}/lib/overlay/overlay.directive.mjs +5 -5
  90. package/{esm2020 → esm2022}/lib/overlay/overlay.service.mjs +5 -5
  91. package/{esm2020 → esm2022}/lib/overlay/toast/toast-action.component.mjs +4 -4
  92. package/esm2022/lib/overlay/toast/toast.component.mjs +41 -0
  93. package/{esm2020 → esm2022}/lib/riv.module.mjs +227 -227
  94. package/esm2022/lib/size/size.directive.mjs +33 -0
  95. package/esm2022/lib/table/simple-table/coordinate-helper.mjs +61 -0
  96. package/esm2022/lib/table/simple-table/simple-table-cell.component.mjs +36 -0
  97. package/esm2022/lib/table/simple-table/simple-table-header-cell.component.mjs +37 -0
  98. package/{esm2020 → esm2022}/lib/table/simple-table/simple-table-row.component.mjs +4 -4
  99. package/esm2022/lib/table/simple-table/simple-table.component.mjs +104 -0
  100. package/esm2022/lib/table/table/clipboard.mjs +182 -0
  101. package/esm2022/lib/table/table/state-helpers/collapse-helpers.mjs +116 -0
  102. package/esm2022/lib/table/table/state-helpers/column-helpers.mjs +383 -0
  103. package/{esm2020 → esm2022}/lib/table/table/state-helpers/display-helpers.mjs +1 -1
  104. package/esm2022/lib/table/table/state-helpers/nesting-helpers.mjs +123 -0
  105. package/esm2022/lib/table/table/state-helpers/order-helpers.mjs +164 -0
  106. package/esm2022/lib/table/table/state-helpers/pagination-helpers.mjs +139 -0
  107. package/esm2022/lib/table/table/state-helpers/result-helpers.mjs +70 -0
  108. package/esm2022/lib/table/table/state-helpers/search-helpers.mjs +72 -0
  109. package/esm2022/lib/table/table/state-helpers/selection-helpers.mjs +180 -0
  110. package/esm2022/lib/table/table/state.mjs +1035 -0
  111. package/esm2022/lib/table/table/table/table.component.mjs +367 -0
  112. package/{esm2020 → esm2022}/lib/table/table/table-collapse-all/table-collapse-all.component.mjs +5 -5
  113. package/esm2022/lib/table/table/table-column-settings/table-column-settings-side-sheet.component.mjs +227 -0
  114. package/esm2022/lib/table/table/table-column-settings/table-column-settings.component.mjs +134 -0
  115. package/esm2022/lib/table/table/table-csv-export/table-csv-export.component.mjs +35 -0
  116. package/{esm2020 → esm2022}/lib/table/table/table-header-resize-handle/table-header-resize-handle.component.mjs +6 -6
  117. package/esm2022/lib/table/table/table-search/table-search.component.mjs +71 -0
  118. package/{esm2020 → esm2022}/lib/table/table/table-search-columns/table-search-columns.component.mjs +4 -4
  119. package/esm2022/lib/visibility/visibility.directive.mjs +34 -0
  120. package/esm2022/lib/visualization/chart/chart-scaling.mjs +380 -0
  121. package/esm2022/lib/visualization/chart/chart.component.mjs +626 -0
  122. package/esm2022/lib/visualization/chart/chart.mjs +3768 -0
  123. package/{esm2020 → esm2022}/lib/visualization/data-table/data-table-cell.component.mjs +5 -5
  124. package/{esm2020 → esm2022}/lib/visualization/data-table/data-table-header-cell.component.mjs +4 -4
  125. package/{esm2020 → esm2022}/lib/visualization/data-table/data-table-row.component.mjs +4 -4
  126. package/{esm2020 → esm2022}/lib/visualization/data-table/data-table.component.mjs +4 -4
  127. package/{esm2020 → esm2022}/lib/visualization/donut/donut.component.mjs +4 -4
  128. package/{esm2020 → esm2022}/lib/visualization/funnel-chart/funnel-chart.component.mjs +5 -5
  129. package/esm2022/lib/visualization/funnel-chart/funnel-chart.helpers.mjs +33 -0
  130. package/{esm2020 → esm2022}/lib/visualization/highlight/highlight.component.mjs +4 -4
  131. package/esm2022/lib/visualization/highlight/highlight.helpers.mjs +20 -0
  132. package/esm2022/lib/visualization/intervals.mjs +63 -0
  133. package/{esm2020 → esm2022}/lib/visualization/issue/issue.component.mjs +4 -4
  134. package/{esm2020 → esm2022}/lib/visualization/legend-item/legend-item.component.mjs +4 -4
  135. package/{esm2020 → esm2022}/lib/visualization/metric/metric.component.mjs +4 -4
  136. package/{esm2020 → esm2022}/lib/visualization/mini-pie/mini-pie.component.mjs +4 -4
  137. package/{esm2020 → esm2022}/lib/visualization/progress/progress.component.mjs +5 -5
  138. package/esm2022/lib/visualization/stacked-column/stacked-column.component.mjs +377 -0
  139. package/esm2022/lib/visualization/stacked-column/stacked-column.helpers.mjs +18 -0
  140. package/esm2022/lib/visualization/stacked-row/stacked-row.component.mjs +270 -0
  141. package/esm2022/lib/visualization/stacked-row/stacked-row.helpers.mjs +74 -0
  142. package/esm2022/lib/visualization/time-series/time-series.component.mjs +374 -0
  143. package/esm2022/lib/visualization/time-series/time-series.helpers.mjs +15 -0
  144. package/esm2022/lib/visualization/trend/trend.component.mjs +51 -0
  145. package/{esm2020 → esm2022}/lib/visualization/zero-state/zero-state.component.mjs +4 -4
  146. package/{fesm2020 → fesm2022}/rivet-health-design-system.mjs +670 -670
  147. package/{fesm2020 → fesm2022}/rivet-health-design-system.mjs.map +1 -1
  148. package/lib/format/svg-text-truncate/svg-text-truncate.directive.d.ts +1 -1
  149. package/lib/format/truncate/truncate.component.d.ts +1 -1
  150. package/lib/icon/icon.component.d.ts +1 -1
  151. package/lib/input/auto-focus/auto-focus.directive.d.ts +1 -1
  152. package/lib/input/button/button.component.d.ts +1 -1
  153. package/lib/input/calendar/calendar.component.d.ts +1 -1
  154. package/lib/input/checkbox/checkbox.component.d.ts +1 -1
  155. package/lib/input/currency-field/currency-field.component.d.ts +1 -1
  156. package/lib/input/date/date.component.d.ts +1 -1
  157. package/lib/input/date-range/date-range.component.d.ts +1 -1
  158. package/lib/input/filter-chip/filter-chip.component.d.ts +1 -1
  159. package/lib/input/filter-dropdown/filter-dropdown.component.d.ts +1 -1
  160. package/lib/input/input-label/input-label.component.d.ts +1 -1
  161. package/lib/input/mentions-input/mentions-input.component.d.ts +1 -1
  162. package/lib/input/number-field/number-field.component.d.ts +1 -1
  163. package/lib/input/percentage-field/percentage-field.component.d.ts +1 -1
  164. package/lib/input/phone-field/phone-field.component.d.ts +1 -1
  165. package/lib/input/radio/radio.component.d.ts +1 -1
  166. package/lib/input/search/search.component.d.ts +1 -1
  167. package/lib/input/search-select/search-select.component.d.ts +1 -1
  168. package/lib/input/select/select/select.component.d.ts +1 -1
  169. package/lib/input/select/select-node/select-node.component.d.ts +1 -1
  170. package/lib/input/simple-select/simple-select.component.d.ts +1 -1
  171. package/lib/input/switch-checkbox/switch-checkbox.component.d.ts +1 -1
  172. package/lib/input/text-field/text-field.component.d.ts +1 -1
  173. package/lib/input/textarea-field/textarea-field.component.d.ts +1 -1
  174. package/lib/input/validation-message/validation-message.component.d.ts +1 -1
  175. package/lib/layout/card/card-actions.component.d.ts +1 -1
  176. package/lib/layout/card/card-content.component.d.ts +1 -1
  177. package/lib/layout/card/card-header.component.d.ts +1 -1
  178. package/lib/layout/card/card-link.component.d.ts +1 -1
  179. package/lib/layout/card/card-media.component.d.ts +1 -1
  180. package/lib/layout/card/card.component.d.ts +1 -1
  181. package/lib/layout/setting-row/setting-row.component.d.ts +1 -1
  182. package/lib/load/loading/loading.component.d.ts +1 -1
  183. package/lib/load/loading-cover/loading-cover.component.d.ts +1 -1
  184. package/lib/navigation/editable-heading/editable-heading.component.d.ts +1 -1
  185. package/lib/navigation/link/link.component.d.ts +1 -1
  186. package/lib/navigation/page-header/page-header.component.d.ts +1 -1
  187. package/lib/navigation/simple-tabs/simple-tab/simple-tab.component.d.ts +1 -1
  188. package/lib/navigation/tabs/tab/tab.component.d.ts +1 -1
  189. package/lib/navigation/views/all-views-modal/all-views-modal.component.d.ts +1 -1
  190. package/lib/navigation/views/edit-view/edit-view.component.d.ts +1 -1
  191. package/lib/navigation/views/permission-picker/permission-picker.component.d.ts +3 -3
  192. package/lib/navigation/views/view-menu/view-menu.component.d.ts +1 -1
  193. package/lib/navigation/views/views/views.component.d.ts +1 -1
  194. package/lib/notification/badge/badge.component.d.ts +1 -1
  195. package/lib/notification/banner/banner-action.component.d.ts +1 -1
  196. package/lib/notification/banner/banner.component.d.ts +1 -1
  197. package/lib/notification/map-indicator/map-indicator.component.d.ts +1 -1
  198. package/lib/notification/notification-badge/notification-badge.component.d.ts +1 -1
  199. package/lib/overlay/callout/callout.component.d.ts +1 -1
  200. package/lib/overlay/callout/help/help.component.d.ts +1 -1
  201. package/lib/overlay/callout/lock-scroll.directive.d.ts +1 -1
  202. package/lib/overlay/callout/menu/menu-item/menu-item.component.d.ts +1 -1
  203. package/lib/overlay/callout/menu/menu.component.d.ts +1 -1
  204. package/lib/overlay/callout/tooltip/locked-tooltip.directive.d.ts +1 -1
  205. package/lib/overlay/callout/tooltip/tooltip.component.d.ts +1 -1
  206. package/lib/overlay/callout/tooltip/tooltip.directive.d.ts +1 -1
  207. package/lib/overlay/modal/dialog/dialog.component.d.ts +1 -1
  208. package/lib/overlay/modal/form-dialog/form-dialog.component.d.ts +1 -1
  209. package/lib/overlay/modal/modal.component.d.ts +1 -1
  210. package/lib/overlay/modal/side-sheet/side-sheet.component.d.ts +1 -1
  211. package/lib/overlay/toast/toast.component.d.ts +1 -1
  212. package/lib/table/simple-table/simple-table-header-cell.component.d.ts +1 -1
  213. package/lib/table/simple-table/simple-table-row.component.d.ts +1 -1
  214. package/lib/table/table/table/table.component.d.ts +1 -1
  215. package/lib/table/table/table-collapse-all/table-collapse-all.component.d.ts +1 -1
  216. package/lib/table/table/table-column-settings/table-column-settings-side-sheet.component.d.ts +1 -1
  217. package/lib/table/table/table-column-settings/table-column-settings.component.d.ts +1 -1
  218. package/lib/table/table/table-csv-export/table-csv-export.component.d.ts +1 -1
  219. package/lib/table/table/table-search/table-search.component.d.ts +1 -1
  220. package/lib/table/table/table-search-columns/table-search-columns.component.d.ts +1 -1
  221. package/lib/visualization/chart/chart.component.d.ts +1 -1
  222. package/lib/visualization/data-table/data-table-row.component.d.ts +1 -1
  223. package/lib/visualization/donut/donut.component.d.ts +1 -1
  224. package/lib/visualization/funnel-chart/funnel-chart.component.d.ts +1 -1
  225. package/lib/visualization/highlight/highlight.component.d.ts +1 -1
  226. package/lib/visualization/issue/issue.component.d.ts +1 -1
  227. package/lib/visualization/legend-item/legend-item.component.d.ts +1 -1
  228. package/lib/visualization/metric/metric.component.d.ts +1 -1
  229. package/lib/visualization/mini-pie/mini-pie.component.d.ts +1 -1
  230. package/lib/visualization/progress/progress.component.d.ts +1 -1
  231. package/lib/visualization/stacked-column/stacked-column.component.d.ts +3 -3
  232. package/lib/visualization/stacked-row/stacked-row.component.d.ts +1 -1
  233. package/lib/visualization/time-series/time-series.component.d.ts +3 -3
  234. package/lib/visualization/trend/trend.component.d.ts +1 -1
  235. package/lib/visualization/zero-state/zero-state.component.d.ts +1 -1
  236. package/package.json +5 -11
  237. package/esm2020/lib/download/download.service.mjs +0 -47
  238. package/esm2020/lib/format/pipes/sentence-case.pipe.mjs +0 -61
  239. package/esm2020/lib/format/pipes/small-currency.pipe.mjs +0 -24
  240. package/esm2020/lib/format/pipes/small-number.pipe.mjs +0 -29
  241. package/esm2020/lib/format/svg-text-truncate/svg-text-truncate.directive.mjs +0 -62
  242. package/esm2020/lib/format/truncate/truncate.component.mjs +0 -51
  243. package/esm2020/lib/icon/dom-cache.mjs +0 -32
  244. package/esm2020/lib/icon/icon.component.mjs +0 -86
  245. package/esm2020/lib/input/auto-focus/auto-focus.directive.mjs +0 -48
  246. package/esm2020/lib/input/button/button.component.mjs +0 -139
  247. package/esm2020/lib/input/button-group/button-group.component.mjs +0 -39
  248. package/esm2020/lib/input/date/date.component.mjs +0 -279
  249. package/esm2020/lib/input/date-range/date-range.component.mjs +0 -477
  250. package/esm2020/lib/input/filter-chip/filter-chip.component.mjs +0 -47
  251. package/esm2020/lib/input/mentions-input/mentions-input.component.mjs +0 -745
  252. package/esm2020/lib/input/number-field/number-field.component.mjs +0 -125
  253. package/esm2020/lib/input/phone-field/phone-field.component.mjs +0 -74
  254. package/esm2020/lib/input/search-select/search-select.component.mjs +0 -189
  255. package/esm2020/lib/input/select/select/select.component.mjs +0 -178
  256. package/esm2020/lib/input/select/state.mjs +0 -882
  257. package/esm2020/lib/input/simple-select/simple-select.component.mjs +0 -178
  258. package/esm2020/lib/input/switch-checkbox/switch-checkbox.component.mjs +0 -33
  259. package/esm2020/lib/input/text-field/text-field.component.mjs +0 -115
  260. package/esm2020/lib/layout/card/card-content.component.mjs +0 -64
  261. package/esm2020/lib/layout/card/card-header.component.mjs +0 -201
  262. package/esm2020/lib/layout/card/card.component.mjs +0 -291
  263. package/esm2020/lib/load/loading/loading.component.mjs +0 -43
  264. package/esm2020/lib/navigation/editable-heading/editable-heading.component.mjs +0 -243
  265. package/esm2020/lib/navigation/views/permission-picker/permission-picker.component.mjs +0 -151
  266. package/esm2020/lib/navigation/views/state.mjs +0 -456
  267. package/esm2020/lib/navigation/views/views/views.component.mjs +0 -90
  268. package/esm2020/lib/notification/banner/banner-action.component.mjs +0 -48
  269. package/esm2020/lib/notification/banner/banner.component.mjs +0 -61
  270. package/esm2020/lib/notification/map-indicator/map-indicator.component.mjs +0 -50
  271. package/esm2020/lib/notification/map-indicator/map-indicators.mjs +0 -15
  272. package/esm2020/lib/overlay/callout/callout.component.mjs +0 -130
  273. package/esm2020/lib/overlay/callout/callout.helpers.mjs +0 -113
  274. package/esm2020/lib/overlay/callout/lock-scroll.directive.mjs +0 -69
  275. package/esm2020/lib/overlay/callout/tooltip/locked-tooltip.directive.mjs +0 -30
  276. package/esm2020/lib/overlay/callout/tooltip/tooltip.directive.mjs +0 -138
  277. package/esm2020/lib/overlay/modal/dialog/dialog.component.mjs +0 -47
  278. package/esm2020/lib/overlay/modal/form-dialog/form-dialog.component.mjs +0 -146
  279. package/esm2020/lib/overlay/modal/modal.component.mjs +0 -31
  280. package/esm2020/lib/overlay/overlay-outlet.component.mjs +0 -98
  281. package/esm2020/lib/overlay/toast/toast.component.mjs +0 -41
  282. package/esm2020/lib/size/size.directive.mjs +0 -33
  283. package/esm2020/lib/table/simple-table/coordinate-helper.mjs +0 -61
  284. package/esm2020/lib/table/simple-table/simple-table-cell.component.mjs +0 -36
  285. package/esm2020/lib/table/simple-table/simple-table-header-cell.component.mjs +0 -37
  286. package/esm2020/lib/table/simple-table/simple-table.component.mjs +0 -104
  287. package/esm2020/lib/table/table/clipboard.mjs +0 -182
  288. package/esm2020/lib/table/table/state-helpers/collapse-helpers.mjs +0 -116
  289. package/esm2020/lib/table/table/state-helpers/column-helpers.mjs +0 -383
  290. package/esm2020/lib/table/table/state-helpers/nesting-helpers.mjs +0 -123
  291. package/esm2020/lib/table/table/state-helpers/order-helpers.mjs +0 -164
  292. package/esm2020/lib/table/table/state-helpers/pagination-helpers.mjs +0 -139
  293. package/esm2020/lib/table/table/state-helpers/result-helpers.mjs +0 -70
  294. package/esm2020/lib/table/table/state-helpers/search-helpers.mjs +0 -72
  295. package/esm2020/lib/table/table/state-helpers/selection-helpers.mjs +0 -180
  296. package/esm2020/lib/table/table/state.mjs +0 -1035
  297. package/esm2020/lib/table/table/table/table.component.mjs +0 -367
  298. package/esm2020/lib/table/table/table-column-settings/table-column-settings-side-sheet.component.mjs +0 -227
  299. package/esm2020/lib/table/table/table-column-settings/table-column-settings.component.mjs +0 -134
  300. package/esm2020/lib/table/table/table-csv-export/table-csv-export.component.mjs +0 -35
  301. package/esm2020/lib/table/table/table-search/table-search.component.mjs +0 -71
  302. package/esm2020/lib/visibility/visibility.directive.mjs +0 -34
  303. package/esm2020/lib/visualization/chart/chart-scaling.mjs +0 -380
  304. package/esm2020/lib/visualization/chart/chart.component.mjs +0 -626
  305. package/esm2020/lib/visualization/chart/chart.mjs +0 -3768
  306. package/esm2020/lib/visualization/funnel-chart/funnel-chart.helpers.mjs +0 -33
  307. package/esm2020/lib/visualization/highlight/highlight.helpers.mjs +0 -20
  308. package/esm2020/lib/visualization/intervals.mjs +0 -63
  309. package/esm2020/lib/visualization/stacked-column/stacked-column.component.mjs +0 -377
  310. package/esm2020/lib/visualization/stacked-column/stacked-column.helpers.mjs +0 -18
  311. package/esm2020/lib/visualization/stacked-row/stacked-row.component.mjs +0 -270
  312. package/esm2020/lib/visualization/stacked-row/stacked-row.helpers.mjs +0 -74
  313. package/esm2020/lib/visualization/time-series/time-series.component.mjs +0 -374
  314. package/esm2020/lib/visualization/time-series/time-series.helpers.mjs +0 -15
  315. package/esm2020/lib/visualization/trend/trend.component.mjs +0 -51
  316. package/fesm2015/rivet-health-design-system.mjs +0 -18370
  317. package/fesm2015/rivet-health-design-system.mjs.map +0 -1
  318. /package/{esm2020 → esm2022}/lib/overlay/callout/select-callout-defaults.mjs +0 -0
  319. /package/{esm2020 → esm2022}/lib/util/local-storage.mjs +0 -0
  320. /package/{esm2020 → esm2022}/public-api.mjs +0 -0
  321. /package/{esm2020 → esm2022}/rivet-health-design-system.mjs +0 -0
@@ -1,3768 +0,0 @@
1
- import { CurrencyPipe } from '@angular/common';
2
- import { scaleLinear } from 'd3-scale';
3
- import { arc, area, line, pie } from 'd3-shape';
4
- import { utcFormat } from 'd3-time-format';
5
- import { sum, uniq } from 'lodash';
6
- import { DaysPipe } from '../../format/pipes/days.pipe';
7
- import { NumberPipe } from '../../format/pipes/number.pipe';
8
- import { PercentagePipe } from '../../format/pipes/percentage.pipe';
9
- import { SmallCurrencyPipe } from '../../format/pipes/small-currency.pipe';
10
- import { SmallNumberPipe } from '../../format/pipes/small-number.pipe';
11
- import { DefaultDonutSizingConfig, emptyChartScaleValues, getDefaultScalingConfigByChartType, } from './chart-scaling';
12
- export var Chart;
13
- (function (Chart) {
14
- Chart.defaultColorPalette = [
15
- //Base colors
16
- '--baja-blast-50',
17
- '--teal-diamond-50',
18
- '--fyre-50',
19
- '--tang-50',
20
- '--purp-60',
21
- '--rosi-70',
22
- //Shift lighter from base by -20
23
- '--baja-blast-30',
24
- '--teal-diamond-30',
25
- '--fyre-30',
26
- '--tang-30',
27
- '--purp-40',
28
- '--rosi-50',
29
- //Shift darker from base by +20
30
- '--baja-blast-70',
31
- '--teal-diamond-70',
32
- '--fyre-70',
33
- '--tang-70',
34
- '--purp-80',
35
- '--rosi-90',
36
- ];
37
- function chart(config, data, dimensions) {
38
- return config.type === 'line'
39
- ? lines(config, data, dimensions)
40
- : config.type === 'area'
41
- ? areas(config, data, dimensions)
42
- : config.type === 'donut'
43
- ? arcs(config, data, dimensions)
44
- : config.type === 'horizontal-bar'
45
- ? horizontalBars(config, data, dimensions)
46
- : config.type === 'bar'
47
- ? bars(config, data, dimensions)
48
- : config.type === 'waterfall'
49
- ? waterfall(config, data, dimensions)
50
- : config.type === 'funnel'
51
- ? funnel(config, data, dimensions)
52
- : config.type === 'flow'
53
- ? flows(config, data, dimensions)
54
- : emptyChart;
55
- }
56
- Chart.chart = chart;
57
- function lines(config, allData, dimensions) {
58
- if (!warnFlowData(allData, 'line')) {
59
- return { ...emptyChart, chartError: 'config' };
60
- }
61
- const { data: hiddenData, visibleIndices } = hide(allData);
62
- if (hiddenData.type === 'labeled') {
63
- // eslint-disable-next-line no-console
64
- console.warn("Heads up! Labeled series aren't currently supported for line charts");
65
- return emptyChart;
66
- }
67
- if (hasSupplementaryData(hiddenData)) {
68
- // eslint-disable-next-line no-console
69
- console.warn("Heads up! Supplementary y values aren't supported for non-bar charts");
70
- return emptyChart;
71
- }
72
- warnUnsupportedPatterns(hiddenData, ['striped', 'dots'], 'line');
73
- //This assignment makes typescript recognize the actual type (TimeseriesData)
74
- const data = hiddenData;
75
- const { dateFormat, pipeTransform, colors } = getFormattingAndColors(allData, data, config);
76
- const chartSizingValues = getFullChartScaleValues(config, data, dimensions, pipeTransform, dateFormat);
77
- if (chartSizingValues === null) {
78
- return { ...emptyChart, chartError: 'sizing' };
79
- }
80
- const tickCount = getBucketTickCount(chartSizingValues);
81
- const xTicks = generateTimeseriesTicks(data, config, tickCount, chartSizingValues, dateFormat).map(tick => toXTick(tick));
82
- const xScale = (index) => {
83
- return (chartSizingValues.totalLeftOffset + chartSizingValues.bucketGap * index);
84
- };
85
- const { scale, ticks: dataTicks } = calcDataAxisScalesAndTicks(data, pipeTransform, config, chartSizingValues);
86
- const yTicks = dataTicks.map(tick => toYTick(tick));
87
- const indices = data.x.map((_, i) => i);
88
- const lines = data.x.length > 1
89
- ? data.ys.map(y => ({
90
- line: line(i => xScale(i), i => scale(y.values[i], y.isSecondary))(indices),
91
- pattern: y.pattern,
92
- }))
93
- : [];
94
- const circles = data.x.length === 1
95
- ? data.ys.map((ySeries, i) => ({
96
- cx: xScale(0),
97
- cy: scale(ySeries.values[0], checkIfSecondary(data, i, 0)),
98
- }))
99
- : [];
100
- const yOffset = chartSizingValues.dataLabelPadding;
101
- const dataLabels = data.ys.flatMap((y, yIndex) => {
102
- const subLabels = y.values.map((val, xIndex) => ({
103
- elementType: 'dataLabel',
104
- label: pipeTransform(val, checkIfSecondary(data, yIndex, xIndex)),
105
- yPos: scale(val, checkIfSecondary(data, yIndex, xIndex)) - yOffset,
106
- xPos: xScale(xIndex),
107
- anchor: 'middle',
108
- }));
109
- return subLabels;
110
- });
111
- function hover(pos) {
112
- const realPosX = pos.x + pos.containerScrollX;
113
- const realPosY = pos.y + pos.containerScrollY;
114
- if (chartSizingValues === null ||
115
- getIfHoverOutOfBounds(pos.x, pos.y, realPosX, realPosY, chartSizingValues, dimensions)) {
116
- return null;
117
- }
118
- const xHoverIndices = getBucketAndClusterNumForHover(realPosX, chartSizingValues, data, config, data.x.length);
119
- if (!xHoverIndices) {
120
- return null;
121
- }
122
- const { bucketNum: xIndex } = xHoverIndices;
123
- const x = xScale(xIndex);
124
- const visibleYIndex = findNearestIndexWithSecondary(data.ys.map((y, i) => ({
125
- value: y.values[xIndex],
126
- isSecondary: checkIfSecondary(data, i, xIndex),
127
- })), pos.y, scale);
128
- const yIndex = visibleIndices[visibleYIndex];
129
- const ys = data.ys.map((y, i) => scale(y.values[xIndex], checkIfSecondary(data, i, xIndex)));
130
- const format = (date) => formatedDate(config.dateFormat || 'day', date);
131
- // Clamp in chart-local coordinates first so the tooltip stays within the
132
- // visible chart area, then translate to viewport coordinates by adding
133
- // pos.rect.x/y (which are viewport-relative from getBoundingClientRect).
134
- const localAnchorX = x - pos.containerScrollX;
135
- const localAnchorY = ys[visibleYIndex] - pos.containerScrollY;
136
- const { anchorX, anchorY } = checkAnchorsAgainstBound(localAnchorX, localAnchorY, dimensions);
137
- const anchor = new DOMRect(anchorX + pos.rect.x, anchorY + pos.rect.y, SMALL_PADDING, 0);
138
- return {
139
- hoverType: 'standard',
140
- x,
141
- xIndex,
142
- ys,
143
- yIndex,
144
- visibleYIndex,
145
- tooltip: {
146
- anchor,
147
- date: format(new Date(data.x[xIndex])),
148
- metrics: data.ys
149
- .map((y, index) => ({
150
- color: colors[index % colors.length],
151
- label: y.label,
152
- pattern: y.pattern,
153
- value: pipeTransform(y.values[xIndex], checkIfSecondary(data, index, xIndex), true) ?? '-',
154
- }))
155
- .filter((_, i) => config.groupedTooltip || i === visibleYIndex),
156
- },
157
- };
158
- }
159
- return {
160
- chartWidth: chartSizingValues.totalWidth,
161
- chartHeight: chartSizingValues.totalHeight,
162
- chartSizingValues,
163
- xTicks,
164
- yTicks,
165
- colors,
166
- lines,
167
- circles,
168
- hover,
169
- bars: [],
170
- areas: [],
171
- arcs: [],
172
- horizontalBars: [],
173
- dataLabels,
174
- waterfallLines: [],
175
- gradients: [],
176
- flowConnections: [],
177
- horizontalContainerScale: chartSizingValues.horizontalContainerScale,
178
- verticalContainerScale: chartSizingValues.verticalContainerScale,
179
- chartError: null,
180
- };
181
- }
182
- function areas(config, allData, dimensions) {
183
- if (!warnFlowData(allData, 'area')) {
184
- return { ...emptyChart, chartError: 'config' };
185
- }
186
- const { data: uncheckedData, visibleIndices } = hide(allData);
187
- if (uncheckedData.type === 'labeled') {
188
- // eslint-disable-next-line no-console
189
- console.warn("Heads up! Labeled series aren't currently supported for area charts");
190
- return emptyChart;
191
- }
192
- if (config.showDataLabels === true) {
193
- // eslint-disable-next-line no-console
194
- console.warn("Heads up! Data labels aren't supported for any stacked chart type");
195
- return emptyChart;
196
- }
197
- if (hasSupplementaryData(uncheckedData)) {
198
- // eslint-disable-next-line no-console
199
- console.warn("Heads up! Supplementary y values aren't supported for non-bar charts");
200
- return emptyChart;
201
- }
202
- warnUnsupportedPatterns(uncheckedData, ['striped'], 'area');
203
- //This assignment makes typescript recognize the actual type (TimeseriesData)
204
- const data = uncheckedData;
205
- const { dateFormat, pipeTransform, colors } = getFormattingAndColors(allData, data, config);
206
- const chartSizingValues = getFullChartScaleValues(config, data, dimensions, pipeTransform, dateFormat);
207
- if (chartSizingValues === null) {
208
- return { ...emptyChart, chartError: 'sizing' };
209
- }
210
- const tickCount = getBucketTickCount(chartSizingValues);
211
- const xTicks = generateTimeseriesTicks(data, config, tickCount, chartSizingValues, dateFormat).map(tick => toXTick(tick));
212
- const xScale = (index) => {
213
- return (chartSizingValues.totalLeftOffset + chartSizingValues.bucketGap * index);
214
- };
215
- const { scale, ticks: dataTicks } = calcDataAxisScalesAndTicks(data, pipeTransform, config, chartSizingValues);
216
- const yTicks = dataTicks.map(tick => toYTick(tick));
217
- const zeroAxisPosVal = scale(0, true);
218
- const indices = data.x.map((_, i) => i);
219
- const areas = data.ys.map((y, yIndex) => ({
220
- pattern: y.pattern,
221
- area: area(i => xScale(i), i => getBarYInfo(data, config, yIndex, i, scale).yValue, i => getBarYInfo(data, config, yIndex, i, scale).yValue +
222
- getBarYInfo(data, config, yIndex, i, scale).height)(indices),
223
- }));
224
- function hover(pos) {
225
- const realPosX = pos.x + pos.containerScrollX;
226
- const realPosY = pos.y + pos.containerScrollY;
227
- if (chartSizingValues === null ||
228
- getIfHoverOutOfBounds(pos.x, pos.y, realPosX, realPosY, chartSizingValues, dimensions)) {
229
- return null;
230
- }
231
- const xHoverIndices = getBucketAndClusterNumForHover(realPosX, chartSizingValues, data, config, data.x.length);
232
- if (!xHoverIndices) {
233
- return null;
234
- }
235
- const { bucketNum: xIndex } = xHoverIndices;
236
- const x = xScale(xIndex);
237
- const fullYs = data.ys.map((_, mapYIndex) => getBarYInfo(data, config, mapYIndex, xIndex, scale));
238
- const ys = fullYs.map(y => y.yValue);
239
- //This is the ys array, but shifted so that the y position for negative values is away from the axis (for the hover circles)
240
- const shiftedYs = fullYs.map(y => {
241
- if (y.yValue >= zeroAxisPosVal) {
242
- return y.yValue + y.height;
243
- }
244
- return y.yValue;
245
- });
246
- const yPosSign = zeroAxisPosVal - pos.y;
247
- let visibleYIndex = -1;
248
- if (yPosSign < 0 && data.ys.find(y => y.values.find(val => val < 0))) {
249
- for (let i = ys.length - 1; i >= 0; i--) {
250
- if (ys[i] >= zeroAxisPosVal && ys[i] < pos.y) {
251
- visibleYIndex = i;
252
- break;
253
- }
254
- }
255
- }
256
- else {
257
- for (let i = 0; i < ys.length; i++) {
258
- if (ys[i] <= zeroAxisPosVal && ys[i] < pos.y) {
259
- visibleYIndex = i;
260
- break;
261
- }
262
- }
263
- }
264
- if (visibleYIndex === -1) {
265
- if (pos.y <= zeroAxisPosVal) {
266
- visibleYIndex = ys.indexOf(Math.min(...ys));
267
- }
268
- else {
269
- visibleYIndex = ys.indexOf(Math.max(...ys));
270
- }
271
- }
272
- const yIndex = visibleIndices[visibleYIndex];
273
- const localAnchorX = x - pos.containerScrollX;
274
- const localAnchorY = ys[visibleYIndex] - pos.containerScrollY;
275
- const { anchorX, anchorY } = checkAnchorsAgainstBound(localAnchorX, localAnchorY, dimensions);
276
- const anchor = new DOMRect(anchorX + pos.rect.x, anchorY + pos.rect.y, SMALL_PADDING, 0);
277
- return {
278
- hoverType: 'standard',
279
- x,
280
- xIndex,
281
- ys: shiftedYs,
282
- yIndex,
283
- visibleYIndex,
284
- tooltip: {
285
- anchor,
286
- date: utcFormat('%B %d, %Y')(new Date(data.x[xIndex])),
287
- metrics: data.ys
288
- .map((y, index) => ({
289
- color: colors[index % colors.length],
290
- label: y.label,
291
- pattern: y.pattern,
292
- value: pipeTransform(y.values[xIndex], checkIfSecondary(data, index, xIndex), true),
293
- }))
294
- .filter((_, i) => config.groupedTooltip || i === visibleYIndex),
295
- },
296
- };
297
- }
298
- return {
299
- chartWidth: chartSizingValues.totalWidth,
300
- chartHeight: chartSizingValues.totalHeight,
301
- chartSizingValues,
302
- xTicks,
303
- yTicks,
304
- colors,
305
- areas,
306
- lines: [],
307
- circles: [],
308
- hover,
309
- bars: [],
310
- arcs: [],
311
- horizontalBars: [],
312
- dataLabels: [],
313
- waterfallLines: [],
314
- gradients: [],
315
- flowConnections: [],
316
- horizontalContainerScale: chartSizingValues.horizontalContainerScale,
317
- verticalContainerScale: chartSizingValues.verticalContainerScale,
318
- chartError: null,
319
- };
320
- }
321
- function bars(config, allData, dimensions) {
322
- if (!warnFlowData(allData, 'bar')) {
323
- return { ...emptyChart, chartError: 'config' };
324
- }
325
- const { data, visibleIndices, visibleSuppIndices } = hide(allData);
326
- if (config.showDataLabels === true &&
327
- isStackedData(config) &&
328
- !isGroupingTypeException(data, config)) {
329
- // eslint-disable-next-line no-console
330
- console.warn("Heads up! Data labels aren't supported for any stacked chart type");
331
- return emptyChart;
332
- }
333
- if (hasSupplementaryData(data) &&
334
- isClusteredData(data, config, false) &&
335
- !isGroupingTypeException(data, config)) {
336
- // eslint-disable-next-line no-console
337
- console.warn("Heads up! Supplementary y values aren't supported for clustered data (just use another normal y series)");
338
- return emptyChart;
339
- }
340
- return barsHelper(config, allData, data, visibleIndices, visibleSuppIndices, dimensions, false, false);
341
- }
342
- function funnel(config, allData, dimensions) {
343
- if (!warnFlowData(allData, 'funnel')) {
344
- return { ...emptyChart, chartError: 'config' };
345
- }
346
- const { data, visibleIndices, visibleSuppIndices } = hide(allData);
347
- return barsHelper(config, allData, data, visibleIndices, visibleSuppIndices, dimensions, true, false);
348
- }
349
- function waterfall(config, allData, dimensions) {
350
- if (!warnFlowData(allData, 'waterfall')) {
351
- return { ...emptyChart, chartError: 'config' };
352
- }
353
- const { data: uncheckedData, visibleIndices } = hide(allData);
354
- if (hasSupplementaryData(uncheckedData)) {
355
- // eslint-disable-next-line no-console
356
- console.warn("Heads up! Supplementary y values aren't supported for non-bar charts");
357
- return emptyChart;
358
- }
359
- if (config.secondaryValueType) {
360
- // eslint-disable-next-line no-console
361
- console.warn('Heads up! Waterfall charts do not currently have two-axis support');
362
- return emptyChart;
363
- }
364
- warnUnsupportedPatterns(uncheckedData, [], 'waterfall');
365
- return barsHelper(config, allData, uncheckedData, visibleIndices, [], dimensions, false, true);
366
- }
367
- function barsHelper(config, allData, uncheckedData, visibleIndices, visibleSuppIndices, dimensions, isFunnel, isWaterfall) {
368
- const { dateFormat, pipeTransform, colorIndices, colors } = getFormattingAndColors(allData, uncheckedData, config);
369
- const waterfallData = waterfallTransform(uncheckedData, isWaterfall);
370
- const data = isWaterfall ? waterfallData.data : uncheckedData;
371
- const chartSizingValues = getFullChartScaleValues(config, data, dimensions, pipeTransform, dateFormat);
372
- if (chartSizingValues === null) {
373
- return { ...emptyChart, chartError: 'sizing' };
374
- }
375
- const tickCount = getBucketTickCount(chartSizingValues);
376
- const xTicks = (data.type === 'labeled'
377
- ? generateLabelledTicks(data, config, tickCount, chartSizingValues)
378
- : generateTimeseriesTicks(data, config, tickCount, chartSizingValues, dateFormat)).map(tick => toXTick(tick));
379
- const { scale, ticks: dataTicks } = calcDataAxisScalesAndTicks(data, pipeTransform, config, chartSizingValues);
380
- const yTicks = dataTicks.map(tick => toYTick(tick));
381
- const zeroAxisPosVal = scale(0, true);
382
- const gradients = [];
383
- const bars = data.ys.map((y, yIndex) => {
384
- const indSeriesGradients = [];
385
- const indSeriesBars = y.values.map((_, index) => {
386
- const { yValue, height } = getBarYInfo(data, config, yIndex, index, scale);
387
- const xValue = calculateBarPosition(data, config, chartSizingValues, index, isClusteredData(data, config, false) ? yIndex : 0);
388
- if (isFunnel) {
389
- //The empty gradient still needs to be inserted to keep data aligned
390
- if (index === 0) {
391
- indSeriesGradients.push({
392
- elementType: 'rect',
393
- x: 0,
394
- y: 0,
395
- width: 0,
396
- height: 0,
397
- });
398
- }
399
- else {
400
- const { yValue: prevBarYVal } = getBarYInfo(data, config, yIndex, index - 1, scale);
401
- indSeriesGradients.push({
402
- elementType: 'rect',
403
- x: xValue,
404
- y: prevBarYVal,
405
- width: chartSizingValues.barSize,
406
- height: Math.max(yValue - prevBarYVal, 0),
407
- });
408
- }
409
- }
410
- const bar = {
411
- elementType: 'rect',
412
- x: xValue,
413
- y: yValue,
414
- width: chartSizingValues.barSize,
415
- height,
416
- offset: 0,
417
- pattern: y.pattern,
418
- };
419
- return bar;
420
- });
421
- gradients.push(indSeriesGradients);
422
- return indSeriesBars;
423
- });
424
- let suppBars = [];
425
- if (hasSupplementaryData(data)) {
426
- suppBars = data.supplementaryYs.map((y, yIndex) => y.values.map((_, index) => {
427
- const { yValue, height } = getBarYInfo(data, config, yIndex, index, scale, true);
428
- const xValue = calculateBarPosition(data, config, chartSizingValues, index, y.supplementalIndex + 1);
429
- return {
430
- elementType: 'rect',
431
- x: xValue,
432
- y: yValue,
433
- width: chartSizingValues.barSize,
434
- height,
435
- offset: 0,
436
- pattern: y.pattern,
437
- };
438
- }));
439
- bars.push(...suppBars);
440
- colors.push(...data.supplementaryYs.map(y => getColor(y, colorIndices, config.colors)));
441
- }
442
- const waterfallLines = [];
443
- if (isWaterfall) {
444
- //Move bars based on height of previous bars (except the total bar)
445
- let barOffsetRunningTotal = 0;
446
- for (let i = 0; i < data.x.length - 1; i++) {
447
- let barOffsetChange = 0;
448
- for (let j = 0; j < bars.length; j++) {
449
- const barIsNegative = bars[j][i].y >= zeroAxisPosVal && bars[j][i].height > 0;
450
- if (barIsNegative) {
451
- barOffsetChange -= bars[j][i].height;
452
- }
453
- else {
454
- barOffsetChange += bars[j][i].height;
455
- }
456
- bars[j][i].offset = barOffsetRunningTotal;
457
- bars[j][i].y -= barOffsetRunningTotal;
458
- if (j === bars.length - 1) {
459
- const x1 = bars[j][i].x + bars[bars.length - 1][i].width;
460
- const y1 = bars[j][i].y + (barIsNegative ? bars[j][i].height : 0);
461
- const x2 = bars[j][i + 1].x;
462
- const y2 = y1;
463
- waterfallLines.push({
464
- x1,
465
- y1,
466
- x2,
467
- y2,
468
- });
469
- }
470
- }
471
- barOffsetRunningTotal += barOffsetChange;
472
- }
473
- }
474
- const dataLabels = data.ys.flatMap((y, yIndex) => {
475
- const subLabels = y.values.map((val, xIndex) => {
476
- const isNegativeBar = bars[yIndex][xIndex].y >= zeroAxisPosVal &&
477
- bars[yIndex][xIndex].height > 0;
478
- const yOffset = isNegativeBar
479
- ? chartSizingValues.dataLabelPadding +
480
- chartSizingValues.dataLabelTextSize +
481
- bars[yIndex][xIndex].height
482
- : -chartSizingValues.dataLabelPadding;
483
- return {
484
- elementType: 'dataLabel',
485
- label: pipeTransform(val, checkIfSecondary(data, yIndex, xIndex)) ?? '',
486
- yPos: (isFunnel && gradients[yIndex][xIndex].height !== 0
487
- ? gradients[yIndex][xIndex].y
488
- : bars[yIndex][xIndex].y) + yOffset,
489
- xPos: bars[yIndex][xIndex].x + bars[yIndex][xIndex].width / 2,
490
- anchor: 'middle',
491
- };
492
- });
493
- return subLabels;
494
- });
495
- if (hasSupplementaryData(data)) {
496
- const suppDataLabels = data.supplementaryYs.flatMap((y, yIndex) => {
497
- const subLabels = y.values.map((val, xIndex) => {
498
- const isNegativeBar = suppBars[yIndex][xIndex].y >= zeroAxisPosVal &&
499
- suppBars[yIndex][xIndex].height > 0;
500
- const yOffset = isNegativeBar
501
- ? chartSizingValues.dataLabelPadding +
502
- suppBars[yIndex][xIndex].height
503
- : -chartSizingValues.dataLabelPadding;
504
- return {
505
- elementType: 'dataLabel',
506
- label: pipeTransform(val, checkIfSecondary(data, yIndex, xIndex, true)) ?? '',
507
- yPos: suppBars[yIndex][xIndex].y + yOffset,
508
- xPos: suppBars[yIndex][xIndex].x + suppBars[yIndex][xIndex].width / 2,
509
- anchor: 'middle',
510
- };
511
- });
512
- return subLabels;
513
- });
514
- dataLabels.push(...suppDataLabels);
515
- }
516
- function hover(pos) {
517
- const realPosX = pos.x + pos.containerScrollX;
518
- const realPosY = pos.y + pos.containerScrollY;
519
- if (chartSizingValues === null ||
520
- getIfHoverOutOfBounds(pos.x, pos.y, realPosX, realPosY, chartSizingValues, dimensions)) {
521
- return null;
522
- }
523
- const suppYs = hasSupplementaryData(data) ? data.supplementaryYs : null;
524
- const xHoverIndices = getBucketAndClusterNumForHover(realPosX, chartSizingValues, data, config, data.x.length);
525
- if (!xHoverIndices) {
526
- return null;
527
- }
528
- const { bucketNum: xIndex, clusterNum, clusterNormCount, clusterNumType, } = xHoverIndices;
529
- let isSuppValue = false;
530
- let suppIndexVal = 0;
531
- if (suppYs) {
532
- suppIndexVal = clusterNum - clusterNormCount;
533
- if (clusterNumType === 'supp') {
534
- isSuppValue = true;
535
- }
536
- }
537
- const calcX = calculateBarPosition(data, config, chartSizingValues, xIndex, clusterNum);
538
- const ys = data.ys.map((_, mapYIndex) => isSuppValue
539
- ? getSuppBarYInfoViaYIndex(data, config, mapYIndex, suppIndexVal, xIndex, scale).yValue
540
- : getBarYInfo(data, config, mapYIndex, xIndex, scale).yValue -
541
- (!isSuppValue && isWaterfall
542
- ? bars[mapYIndex][xIndex].offset ?? 0
543
- : 0));
544
- const yPosSign = zeroAxisPosVal - realPosY;
545
- let visibleYIndex = -1;
546
- let dropOffHoverDetected = false;
547
- if (yPosSign < 0 && data.ys.find(y => y.values.find(val => val < 0))) {
548
- for (let i = ys.length - 1; i >= 0; i--) {
549
- if (ys[i] >= zeroAxisPosVal && ys[i] < realPosY) {
550
- visibleYIndex = i;
551
- break;
552
- }
553
- }
554
- }
555
- else {
556
- for (let i = 0; i < ys.length; i++) {
557
- if (ys[i] <= zeroAxisPosVal && ys[i] < realPosY) {
558
- visibleYIndex = i;
559
- break;
560
- }
561
- }
562
- }
563
- if (isClusteredData(data, config, false) && !suppYs) {
564
- visibleYIndex = clusterNum;
565
- if (isFunnel && xIndex !== 0 && ys[visibleYIndex] > realPosY) {
566
- dropOffHoverDetected = true;
567
- }
568
- }
569
- if (visibleYIndex === -1) {
570
- if (realPosY <= zeroAxisPosVal) {
571
- visibleYIndex = ys.indexOf(Math.min(...ys));
572
- }
573
- else {
574
- visibleYIndex = ys.indexOf(Math.max(...ys));
575
- }
576
- }
577
- const yIndex = visibleIndices[visibleYIndex];
578
- let { yValue, height } = isSuppValue
579
- ? getSuppBarYInfoViaYIndex(data, config, yIndex, suppIndexVal, xIndex, scale)
580
- : getBarYInfo(data, config, yIndex, xIndex, scale);
581
- if (dropOffHoverDetected) {
582
- yValue = gradients[yIndex][xIndex].y;
583
- height = gradients[yIndex][xIndex].height;
584
- }
585
- const localAnchorX = calcX - pos.containerScrollX - SMALL_PADDING;
586
- const width = chartSizingValues.barSize + SMALL_PADDING * 2;
587
- const waterfallOffset = !isSuppValue && isWaterfall ? bars[yIndex][xIndex].offset ?? 0 : 0;
588
- const localAnchorY = yValue - pos.containerScrollY - waterfallOffset;
589
- const { anchorX, anchorY, anchorWidth, anchorHeight } = checkAnchorsAgainstBound(localAnchorX, localAnchorY, dimensions, width, height);
590
- const anchor = new DOMRect(anchorX + pos.rect.x, anchorY + pos.rect.y, anchorWidth, anchorHeight);
591
- //We need to preserve the original index for the later checkIfSecondary call
592
- const ysForMetrics = isSuppValue && suppYs
593
- ? suppYs
594
- .map((suppY, index) => ({ data: suppY, originalIndex: index }))
595
- .filter(suppY => suppY.data.supplementalIndex === suppIndexVal)
596
- : data.ys.map((y, index) => ({ data: y, originalIndex: index }));
597
- // Find the specific supplementary item that was hovered
598
- const groupSupps = suppYs
599
- ? suppYs.filter(s => s.supplementalIndex === suppIndexVal) ?? []
600
- : [];
601
- const suppArrayIndex = visibleYIndex; // Use the visual Y position within the layer
602
- const filteredSuppYIndex = suppArrayIndex >= 0 && suppArrayIndex < groupSupps.length && suppYs
603
- ? suppYs.indexOf(groupSupps[suppArrayIndex]) ?? -1
604
- : -1;
605
- const suppYIndex = filteredSuppYIndex >= 0 ? visibleSuppIndices[filteredSuppYIndex] : -1;
606
- return {
607
- hoverType: 'standard',
608
- x: calcX + chartSizingValues.barSize / 2,
609
- xIndex,
610
- ys,
611
- yIndex,
612
- visibleYIndex,
613
- ...(isSuppValue && suppYIndex >= 0
614
- ? {
615
- isSuppValue,
616
- suppYIndex: suppYIndex,
617
- }
618
- : {}),
619
- ...(dropOffHoverDetected ? { isDropOff: true } : {}),
620
- tooltip: {
621
- anchor,
622
- date: data.type === 'labeled'
623
- ? dropOffHoverDetected
624
- ? 'Drop off from '.concat(data.x[xIndex - 1].label)
625
- : data.x[xIndex].label
626
- : utcFormat('%B %d, %Y')(new Date(data.x[xIndex])),
627
- metrics: ysForMetrics
628
- .map(y => ({
629
- color: getColor(isWaterfall ? waterfallData.map.get(y.data) : y.data, colorIndices, config.colors),
630
- label: y.data.label,
631
- pattern: y.data.pattern,
632
- value: pipeTransform(dropOffHoverDetected
633
- ? Math.max(y.data.values[xIndex - 1] - y.data.values[xIndex], 0)
634
- : y.data.values[xIndex], checkIfSecondary(data, y.originalIndex, dropOffHoverDetected ? xIndex - 1 : xIndex, isSuppValue), true),
635
- }))
636
- .filter((_, i) => config.groupedTooltip || i === visibleYIndex),
637
- },
638
- };
639
- }
640
- return {
641
- chartWidth: chartSizingValues.totalWidth,
642
- chartHeight: chartSizingValues.totalHeight,
643
- chartSizingValues,
644
- xTicks,
645
- yTicks,
646
- colors,
647
- bars,
648
- lines: [],
649
- circles: [],
650
- areas: [],
651
- hover,
652
- arcs: [],
653
- horizontalBars: [],
654
- dataLabels,
655
- waterfallLines,
656
- gradients,
657
- flowConnections: [],
658
- horizontalContainerScale: chartSizingValues.horizontalContainerScale,
659
- verticalContainerScale: chartSizingValues.verticalContainerScale,
660
- chartError: null,
661
- };
662
- }
663
- function horizontalBars(config, allData, dimensions) {
664
- if (!warnFlowData(allData, 'horizontal bar')) {
665
- return { ...emptyChart, chartError: 'config' };
666
- }
667
- //Some of this stuff gets confusing, because x and y are essentially inverted here
668
- // So, if you see a situation where a variable is named 'y', but referencing
669
- // 'x' (or vice versa), that's why
670
- const { data, visibleIndices, visibleSuppIndices } = hide(allData);
671
- if (config.showDataLabels === true &&
672
- isStackedData(config) &&
673
- !isGroupingTypeException(data, config)) {
674
- // eslint-disable-next-line no-console
675
- console.warn("Heads up! Data labels aren't supported for any stacked chart type");
676
- return emptyChart;
677
- }
678
- if (hasSupplementaryData(data) &&
679
- isClusteredData(data, config, false) &&
680
- !isGroupingTypeException(data, config)) {
681
- // eslint-disable-next-line no-console
682
- console.warn("Heads up! Supplementary y values aren't supported for clustered data (just use another normal y series)");
683
- return emptyChart;
684
- }
685
- const { dateFormat, pipeTransform, colorIndices, colors } = getFormattingAndColors(allData, data, config);
686
- const chartSizingValues = getFullChartScaleValues(config, data, dimensions, pipeTransform, dateFormat);
687
- if (chartSizingValues === null) {
688
- return { ...emptyChart, chartError: 'sizing' };
689
- }
690
- const tickCount = getBucketTickCount(chartSizingValues);
691
- const yTicks = (data.type === 'labeled'
692
- ? generateLabelledTicks(data, config, tickCount, chartSizingValues)
693
- : generateTimeseriesTicks(data, config, tickCount, chartSizingValues, dateFormat)).map(tick => toYTick(tick));
694
- const { scale, ticks: dataTicks } = calcDataAxisScalesAndTicks(data, pipeTransform, config, chartSizingValues);
695
- const xTicks = dataTicks.map(tick => toXTick(tick));
696
- const zeroAxisPosVal = scale(0, true);
697
- const simplifiedHorizontalBars = [];
698
- const horizontalBars = data.ys.map((y, yIndex) => {
699
- const subSimpHorBars = [];
700
- const retVal = y.values.map((_, index) => {
701
- const { xValue, width } = getBarXInfo(data, config, yIndex, index, scale);
702
- const clusterInfo = getClusterInfoForBucket(data, config);
703
- const clusterNum = clusterInfo.normClusterIndices.indexOf(yIndex);
704
- const yValue = calculateBarPosition(data, config, chartSizingValues, index, isClusteredData(data, config, false) ? clusterNum : 0);
705
- const horR = Math.min(DEFAULT_HORIZONTAL_BAR_CORNER_RADIUS, Math.floor(width / 2));
706
- const verR = Math.min(DEFAULT_HORIZONTAL_BAR_CORNER_RADIUS, Math.floor(chartSizingValues.barSize / 2));
707
- subSimpHorBars.push({
708
- xPos: xValue,
709
- yPos: yValue,
710
- width,
711
- });
712
- //If clusterNum is -1, then the value of data[yIndex][xIndex] must be zero
713
- if (clusterNum === -1) {
714
- return {
715
- horizontalBar: '',
716
- pattern: y.pattern,
717
- x: xValue,
718
- y: yValue,
719
- };
720
- }
721
- //Don't draw anything for zero-value bars
722
- if (width === 0) {
723
- return {
724
- horizontalBar: '',
725
- pattern: y.pattern,
726
- x: xValue,
727
- y: yValue,
728
- };
729
- }
730
- const isPositive = data.ys[yIndex].values[index] > 0;
731
- const hasAnyNegativeBars = data.ys
732
- .map(y => y.values[index])
733
- .find(val => val < 0);
734
- const hasAnyPositiveBars = data.ys
735
- .map(y => y.values[index])
736
- .find(val => val > 0);
737
- //These checks are to make sure we still round if all previous/later values are 0
738
- const allLeftZero = isPositive
739
- ? data.ys
740
- .slice(0, yIndex)
741
- .map(y => y.values[index])
742
- .filter(val => val > 0).length === 0 && !hasAnyNegativeBars
743
- : data.ys
744
- .slice(yIndex + 1, data.ys.length)
745
- .map(y => y.values[index])
746
- .filter(val => val < 0).length === 0;
747
- const leftSideRound = !isStackedData(config) || allLeftZero;
748
- const allRightZero = isPositive
749
- ? data.ys
750
- .slice(yIndex + 1, data.ys.length)
751
- .map(y => y.values[index])
752
- .filter(val => val > 0).length === 0
753
- : data.ys
754
- .slice(0, yIndex)
755
- .map(y => y.values[index])
756
- .filter(val => val < 0).length === 0 && !hasAnyPositiveBars;
757
- const rightSideRound = !isStackedData(config) || allRightZero;
758
- const pathD = calculateHorizontalBarPath(leftSideRound, rightSideRound, xValue, yValue, horR, verR, chartSizingValues.barSize, width);
759
- return {
760
- horizontalBar: pathD,
761
- pattern: y.pattern,
762
- x: xValue,
763
- y: yValue,
764
- };
765
- });
766
- simplifiedHorizontalBars.push(subSimpHorBars);
767
- return retVal;
768
- });
769
- const suppYs = data.supplementaryYs;
770
- const simplifiedSuppHorizontalBars = [];
771
- if (suppYs) {
772
- const suppHorizontalBars = suppYs.map((y, yIndex) => {
773
- const subSimpHorBars = [];
774
- const retVal = y.values.map((_, index) => {
775
- const { xValue, width } = getBarXInfo(data, config, yIndex, index, scale, true);
776
- const clusterInfo = getClusterInfoForBucket(data, config);
777
- const clusterNum = clusterInfo.suppClusterIndices.indexOf(y.supplementalIndex) +
778
- clusterInfo.normCount;
779
- const yValue = calculateBarPosition(data, config, chartSizingValues, index, clusterNum);
780
- const horR = Math.min(DEFAULT_HORIZONTAL_BAR_CORNER_RADIUS, Math.floor(width / 2));
781
- const verR = Math.min(DEFAULT_HORIZONTAL_BAR_CORNER_RADIUS, Math.floor(chartSizingValues.barSize / 2));
782
- subSimpHorBars.push({
783
- xPos: xValue,
784
- yPos: yValue,
785
- width,
786
- });
787
- //Don't draw anything for zero-value bars
788
- if (width === 0) {
789
- return {
790
- horizontalBar: '',
791
- pattern: y.pattern,
792
- x: xValue,
793
- y: yValue,
794
- };
795
- }
796
- const isPositive = suppYs[yIndex].values[index] > 0;
797
- const hasAnyNegativeBars = suppYs
798
- .filter(suppY => suppY.supplementalIndex === y.supplementalIndex)
799
- .map(y => y.values[index])
800
- .find(val => val < 0);
801
- const hasAnyPositiveBars = suppYs
802
- .filter(suppY => suppY.supplementalIndex === y.supplementalIndex)
803
- .map(y => y.values[index])
804
- .find(val => val > 0);
805
- //These checks are to make sure we still round if all previous/later values are 0
806
- const allLeftZero = isPositive
807
- ? suppYs
808
- .slice(0, yIndex)
809
- .filter(suppY => suppY.supplementalIndex === y.supplementalIndex)
810
- .map(y => y.values[index])
811
- .filter(val => val > 0).length === 0 && !hasAnyNegativeBars
812
- : suppYs
813
- .slice(yIndex + 1, suppYs.length)
814
- .filter(suppY => suppY.supplementalIndex === y.supplementalIndex)
815
- .map(y => y.values[index])
816
- .filter(val => val < 0).length === 0;
817
- const leftSideRound = !isStackedData(config) || allLeftZero;
818
- const allRightZero = isPositive
819
- ? suppYs
820
- .slice(yIndex + 1, suppYs.length)
821
- .filter(suppY => suppY.supplementalIndex === y.supplementalIndex)
822
- .map(y => y.values[index])
823
- .filter(val => val > 0).length === 0
824
- : suppYs
825
- .slice(0, yIndex)
826
- .filter(suppY => suppY.supplementalIndex === y.supplementalIndex)
827
- .map(y => y.values[index])
828
- .filter(val => val < 0).length === 0 && !hasAnyPositiveBars;
829
- const rightSideRound = !isStackedData(config) || allRightZero;
830
- const pathD = calculateHorizontalBarPath(leftSideRound, rightSideRound, xValue, yValue, horR, verR, chartSizingValues.barSize, width);
831
- return {
832
- horizontalBar: pathD,
833
- pattern: y.pattern,
834
- x: xValue,
835
- y: yValue,
836
- };
837
- });
838
- simplifiedSuppHorizontalBars.push(subSimpHorBars);
839
- return retVal;
840
- });
841
- horizontalBars.push(...suppHorizontalBars);
842
- colors.push(...suppYs.map(y => getColor(y, colorIndices, config.colors)));
843
- }
844
- const yOffset = chartSizingValues.barSize;
845
- const dataLabels = data.ys.flatMap((y, yIndex) => {
846
- const subLabels = y.values.map((val, xIndex) => {
847
- const barIsNegative = simplifiedHorizontalBars[yIndex][xIndex].xPos < zeroAxisPosVal &&
848
- simplifiedHorizontalBars[yIndex][xIndex].width > 0;
849
- const xOffset = barIsNegative
850
- ? -chartSizingValues.dataLabelPadding
851
- : simplifiedHorizontalBars[yIndex][xIndex].width +
852
- chartSizingValues.dataLabelPadding;
853
- return {
854
- elementType: 'dataLabel',
855
- label: pipeTransform(val, checkIfSecondary(data, yIndex, xIndex)) ?? '',
856
- yPos: simplifiedHorizontalBars[yIndex][xIndex].yPos + yOffset,
857
- xPos: simplifiedHorizontalBars[yIndex][xIndex].xPos + xOffset,
858
- anchor: barIsNegative ? 'end' : 'start',
859
- };
860
- });
861
- return subLabels;
862
- });
863
- if (suppYs) {
864
- const suppDataLabels = suppYs.flatMap((y, yIndex) => {
865
- const subLabels = y.values.map((val, xIndex) => {
866
- const barIsNegative = simplifiedSuppHorizontalBars[yIndex][xIndex].xPos <
867
- zeroAxisPosVal &&
868
- simplifiedSuppHorizontalBars[yIndex][xIndex].width > 0;
869
- const xOffset = barIsNegative
870
- ? -chartSizingValues.dataLabelPadding
871
- : simplifiedSuppHorizontalBars[yIndex][xIndex].width +
872
- chartSizingValues.dataLabelPadding;
873
- return {
874
- elementType: 'dataLabel',
875
- label: pipeTransform(val, checkIfSecondary(data, yIndex, xIndex, true)) ?? '',
876
- yPos: simplifiedSuppHorizontalBars[yIndex][xIndex].yPos + yOffset,
877
- xPos: simplifiedSuppHorizontalBars[yIndex][xIndex].xPos + xOffset,
878
- anchor: barIsNegative ? 'end' : 'start',
879
- };
880
- });
881
- return subLabels;
882
- });
883
- dataLabels.push(...suppDataLabels);
884
- }
885
- function hover(pos) {
886
- const realPosX = pos.x + pos.containerScrollX;
887
- const realPosY = pos.y + pos.containerScrollY;
888
- if (chartSizingValues === null ||
889
- getIfHoverOutOfBounds(pos.x, pos.y, realPosX, realPosY, chartSizingValues, dimensions)) {
890
- return null;
891
- }
892
- const suppYs = hasSupplementaryData(data) ? data.supplementaryYs : null;
893
- const xHoverIndices = getBucketAndClusterNumForHover(realPosY, chartSizingValues, data, config, data.x.length);
894
- if (!xHoverIndices) {
895
- return null;
896
- }
897
- const { bucketNum: xIndex, clusterNum, clusterNormCount, clusterNumType, } = xHoverIndices;
898
- let x = calculateBarPosition(data, config, chartSizingValues, xIndex, clusterNum);
899
- let isSuppValue = false;
900
- let suppIndexVal = 0;
901
- if (suppYs) {
902
- suppIndexVal = clusterNum - clusterNormCount;
903
- if (clusterNumType === 'supp') {
904
- isSuppValue = true;
905
- }
906
- }
907
- // When hovering supplementary values, get bars for that supplemental layer
908
- // When hovering original Ys, get bars for original Ys
909
- const fullYs = hasSupplementaryData(data) && isSuppValue
910
- ? (data.supplementaryYs.filter(s => s.supplementalIndex === suppIndexVal) ?? []).map(suppY => getBarXInfo(data, config, data.supplementaryYs.indexOf(suppY), xIndex, scale, true))
911
- : data.ys.map((_, mapYIndex) => getBarXInfo(data, config, mapYIndex, xIndex, scale));
912
- const ys = fullYs.map(y => y.xValue);
913
- let visibleYIndex = -1;
914
- for (let i = 0; i < fullYs.length; i++) {
915
- const leftBorder = fullYs[i].xValue;
916
- const rightBorderCandidates = fullYs
917
- .filter(y => y.xValue > leftBorder)
918
- .map(y => y.xValue);
919
- const rightBorder = rightBorderCandidates.length > 0
920
- ? Math.min(...rightBorderCandidates)
921
- : leftBorder + fullYs[i].width;
922
- if (realPosX > leftBorder && realPosX < rightBorder) {
923
- visibleYIndex = i;
924
- }
925
- }
926
- if (isClusteredData(data, config, false)) {
927
- visibleYIndex = clusterNum;
928
- }
929
- if (visibleYIndex === -1) {
930
- if (realPosX >= zeroAxisPosVal) {
931
- visibleYIndex = ys.indexOf(Math.max(...ys));
932
- }
933
- else {
934
- visibleYIndex = ys.indexOf(Math.min(...ys));
935
- }
936
- }
937
- // For supplementary bars: visibleYIndex is index within filtered supplementary array
938
- // For original Ys: visibleYIndex is index within original Ys array
939
- const actualSuppYIndex = hasSupplementaryData(data) && isSuppValue
940
- ? data.supplementaryYs.findIndex(s => s.supplementalIndex === suppIndexVal &&
941
- data.supplementaryYs
942
- .filter(s2 => s2.supplementalIndex === suppIndexVal)
943
- .indexOf(s) === visibleYIndex) ?? -1
944
- : -1;
945
- const yIndex = isSuppValue ? 0 : visibleIndices[visibleYIndex];
946
- //Check if we've landed on a zero-width bar (only really relevant on ends)
947
- const barsToCheck = isSuppValue
948
- ? simplifiedSuppHorizontalBars
949
- : simplifiedHorizontalBars;
950
- const barIndexToCheck = isSuppValue ? actualSuppYIndex : visibleYIndex;
951
- if (barIndexToCheck >= 0 &&
952
- barsToCheck[barIndexToCheck][xIndex].width === 0 &&
953
- isStackedData(config)) {
954
- let altBarFound = false;
955
- //Check upwards
956
- for (let i = barIndexToCheck + 1; i < barsToCheck.length; i++) {
957
- if (altBarFound) {
958
- break;
959
- }
960
- if (barsToCheck[i][xIndex].width !== 0) {
961
- if (hasSupplementaryData(data) && isSuppValue) {
962
- visibleYIndex = data.supplementaryYs
963
- .filter(s => s.supplementalIndex === suppIndexVal)
964
- .indexOf(data.supplementaryYs[i]);
965
- }
966
- else {
967
- visibleYIndex = i;
968
- }
969
- altBarFound = true;
970
- }
971
- }
972
- //Check downwards
973
- for (let i = barIndexToCheck - 1; i >= 0; i--) {
974
- if (altBarFound) {
975
- break;
976
- }
977
- if (barsToCheck[i][xIndex].width !== 0) {
978
- if (hasSupplementaryData(data) && isSuppValue) {
979
- visibleYIndex = data.supplementaryYs
980
- .filter(s => s.supplementalIndex === suppIndexVal)
981
- .indexOf(data.supplementaryYs[i]);
982
- }
983
- else {
984
- visibleYIndex = i;
985
- }
986
- altBarFound = true;
987
- }
988
- }
989
- }
990
- const originalSuppYIndex = isSuppValue && actualSuppYIndex >= 0
991
- ? visibleSuppIndices[actualSuppYIndex]
992
- : -1;
993
- const barXPos = isSuppValue
994
- ? simplifiedSuppHorizontalBars[actualSuppYIndex][xIndex].xPos
995
- : simplifiedHorizontalBars[visibleYIndex][xIndex].xPos;
996
- const barYPos = isSuppValue
997
- ? simplifiedSuppHorizontalBars[actualSuppYIndex][xIndex].yPos
998
- : simplifiedHorizontalBars[visibleYIndex][xIndex].yPos;
999
- const barWidth = isSuppValue
1000
- ? simplifiedSuppHorizontalBars[actualSuppYIndex][xIndex].width
1001
- : simplifiedHorizontalBars[visibleYIndex][xIndex].width;
1002
- const localAnchorX = barXPos - pos.containerScrollX - SMALL_PADDING;
1003
- const width = barWidth + SMALL_PADDING * 2;
1004
- const localAnchorY = barYPos - pos.containerScrollY;
1005
- const height = chartSizingValues.barSize;
1006
- const { anchorX, anchorY, anchorWidth, anchorHeight } = checkAnchorsAgainstBound(localAnchorX, localAnchorY, dimensions, width, height);
1007
- const anchor = new DOMRect(anchorX + pos.rect.x, anchorY + pos.rect.y, anchorWidth, anchorHeight);
1008
- //We need to preserve the original index for the later checkIfSecondary call
1009
- const ysForMetrics = isSuppValue && suppYs
1010
- ? suppYs
1011
- .map((suppY, index) => ({ data: suppY, originalIndex: index }))
1012
- .filter(suppY => suppY.data.supplementalIndex === suppIndexVal)
1013
- : data.ys.map((y, index) => ({ data: y, originalIndex: index }));
1014
- return {
1015
- hoverType: 'standard',
1016
- x,
1017
- xIndex,
1018
- ys,
1019
- yIndex,
1020
- visibleYIndex,
1021
- ...(isSuppValue && originalSuppYIndex >= 0
1022
- ? { isSuppValue, suppYIndex: originalSuppYIndex }
1023
- : {}),
1024
- tooltip: {
1025
- anchor,
1026
- date: data.type === 'labeled'
1027
- ? data.x[xIndex].label
1028
- : utcFormat('%B %d, %Y')(new Date(data.x[xIndex])),
1029
- metrics: ysForMetrics
1030
- .map(y => ({
1031
- color: getColor(y.data, colorIndices, config.colors),
1032
- label: y.data.label,
1033
- pattern: y.data.pattern,
1034
- value: pipeTransform(y.data.values[xIndex], checkIfSecondary(data, y.originalIndex, xIndex, isSuppValue), true),
1035
- }))
1036
- .filter((_, i) => config.groupedTooltip || i === visibleYIndex),
1037
- },
1038
- };
1039
- }
1040
- return {
1041
- chartWidth: chartSizingValues.totalWidth,
1042
- chartHeight: chartSizingValues.totalHeight,
1043
- chartSizingValues,
1044
- xTicks: xTicks,
1045
- yTicks: yTicks,
1046
- hover,
1047
- colors,
1048
- bars: [],
1049
- lines: [],
1050
- circles: [],
1051
- areas: [],
1052
- arcs: [],
1053
- horizontalBars,
1054
- dataLabels,
1055
- waterfallLines: [],
1056
- gradients: [],
1057
- flowConnections: [],
1058
- horizontalContainerScale: chartSizingValues.horizontalContainerScale,
1059
- verticalContainerScale: chartSizingValues.verticalContainerScale,
1060
- chartError: null,
1061
- };
1062
- }
1063
- function arcs(config, allData, dimensions) {
1064
- if (!warnFlowData(allData, 'donut')) {
1065
- return { ...emptyChart, chartError: 'config' };
1066
- }
1067
- if (config.secondaryValueType &&
1068
- (config.valueType === 'percentage' ||
1069
- config.secondaryValueType === 'percentage')) {
1070
- // eslint-disable-next-line no-console
1071
- console.warn("Heads up! Two axes with percentage aren't supported for donut charts");
1072
- return emptyChart;
1073
- }
1074
- if (hasSupplementaryData(allData)) {
1075
- // eslint-disable-next-line no-console
1076
- console.warn("Heads up! Supplementary y values aren't supported for non-bar charts");
1077
- return emptyChart;
1078
- }
1079
- warnUnsupportedPatterns(allData, [], 'donut');
1080
- const { data: unstackedData, visibleIndices } = hide(allData);
1081
- const donutData = Chart.convertChartDataToDonutData(unstackedData);
1082
- const hasNonZeroValue = donutData.some(d => d.value > 0);
1083
- const arcData = hasNonZeroValue
1084
- ? donutData
1085
- : [
1086
- {
1087
- label: '',
1088
- value: 1,
1089
- },
1090
- ];
1091
- const colors = hasNonZeroValue
1092
- ? visibleIndices.map(i => config.colors[i % config.colors.length])
1093
- : ['--gray-30'];
1094
- const { pipeTransform } = getFormattingAndColors(allData, unstackedData, config);
1095
- const donutDefaultConfig = DefaultDonutSizingConfig;
1096
- const dataLabelPaddingConfig = getElementScalingInfo(config.donutDisplayInfo.scalingConfig?.elementScales, donutDefaultConfig.elementScales, 'dataLabelPadding');
1097
- const fontSizeConfig = getElementScalingInfo(config.donutDisplayInfo.scalingConfig?.elementScales, donutDefaultConfig.elementScales, 'fontSize');
1098
- const dataLabelTextSizing = getDataLabelSize(unstackedData, pipeTransform, fontSizeConfig.target);
1099
- const horizontalContainerScale = config.donutDisplayInfo.scalingConfig?.horizontalContainerScale !==
1100
- undefined
1101
- ? config.donutDisplayInfo.scalingConfig.horizontalContainerScale
1102
- : donutDefaultConfig.horizontalContainerScale;
1103
- const verticalContainerScale = config.donutDisplayInfo.scalingConfig?.verticalContainerScale !==
1104
- undefined
1105
- ? config.donutDisplayInfo.scalingConfig.verticalContainerScale
1106
- : donutDefaultConfig.verticalContainerScale;
1107
- const outerRadiusConfig = config.donutDisplayInfo.scalingConfig?.outerRadius !== undefined
1108
- ? config.donutDisplayInfo.scalingConfig.outerRadius
1109
- : donutDefaultConfig.outerRadius;
1110
- const drawRadiusConfig = config.donutDisplayInfo.scalingConfig?.drawRadius !== undefined
1111
- ? config.donutDisplayInfo.scalingConfig.drawRadius
1112
- : donutDefaultConfig.drawRadius;
1113
- const outer = outerRadiusConfig.type === 'proportion'
1114
- ? (dimensions.height / 2) * outerRadiusConfig.value
1115
- : outerRadiusConfig.value;
1116
- const drawRadius = drawRadiusConfig.type === 'proportion'
1117
- ? outer * drawRadiusConfig.value
1118
- : drawRadiusConfig.value;
1119
- const inner = outer - drawRadius;
1120
- const pieArcs = pie()
1121
- .sortValues(null)
1122
- .value(d => Math.max(d.value, 0))(arcData);
1123
- const arcs = pieArcs.map(pieArc => arc()
1124
- .innerRadius(inner)
1125
- .outerRadius(outer)
1126
- .padAngle(0.013)
1127
- .startAngle(pieArc.startAngle)
1128
- .endAngle(pieArc.endAngle)(pieArc.data));
1129
- const dataLabels = hasNonZeroValue
1130
- ? pieArcs.map(arc => {
1131
- //Don't show data labels for zero-width donut slices (includes negative values)
1132
- if (arc.startAngle === arc.endAngle) {
1133
- return {
1134
- elementType: 'dataLabel',
1135
- label: '',
1136
- yPos: 0,
1137
- xPos: 0,
1138
- anchor: 'middle',
1139
- };
1140
- }
1141
- const arcCenterAngle = (arc.startAngle + arc.endAngle) / 2;
1142
- const edgePoint = arcToPoint(arcCenterAngle, outer);
1143
- const lineEndPoint = arcToPoint(arcCenterAngle, outer + dataLabelPaddingConfig.target);
1144
- const middleArea = outer / 4;
1145
- let yOffset = 0;
1146
- let xOffset = 0;
1147
- if (lineEndPoint.y > 0) {
1148
- if (Math.abs(lineEndPoint.y) < middleArea) {
1149
- yOffset = SMALL_PADDING / 2;
1150
- }
1151
- else {
1152
- yOffset = SMALL_PADDING;
1153
- }
1154
- if (Math.abs(lineEndPoint.x) < middleArea) {
1155
- yOffset += SMALL_PADDING / 2;
1156
- }
1157
- }
1158
- else {
1159
- if (Math.abs(lineEndPoint.y) < middleArea) {
1160
- yOffset = SMALL_PADDING / 2;
1161
- }
1162
- if (Math.abs(lineEndPoint.x) < middleArea) {
1163
- yOffset -= SMALL_PADDING / 2;
1164
- }
1165
- }
1166
- return {
1167
- elementType: 'dataLabel',
1168
- label: pipeTransform(arc.data.value, arc.data.isSecondary),
1169
- yPos: lineEndPoint.y + yOffset,
1170
- xPos: lineEndPoint.x + xOffset,
1171
- anchor: Math.abs(lineEndPoint.x) < middleArea
1172
- ? 'middle'
1173
- : lineEndPoint.x < 0
1174
- ? 'end'
1175
- : 'start',
1176
- line: {
1177
- x1: edgePoint.x,
1178
- y1: edgePoint.y,
1179
- x2: lineEndPoint.x,
1180
- y2: lineEndPoint.y,
1181
- },
1182
- };
1183
- })
1184
- : [];
1185
- const drawWidth = (outer +
1186
- (config.showDataLabels
1187
- ? dataLabelPaddingConfig.target + dataLabelTextSizing.horizontal
1188
- : 0)) *
1189
- 2;
1190
- const drawHeight = (outer +
1191
- (config.showDataLabels
1192
- ? dataLabelPaddingConfig.target + dataLabelTextSizing.vertical
1193
- : 0)) *
1194
- 2;
1195
- function hover(pos) {
1196
- const realPosX = pos.x + pos.containerScrollX;
1197
- const realPosY = pos.y + pos.containerScrollY;
1198
- if (getIfHoverOutOfBounds(pos.x, pos.y, realPosX, realPosY, null, dimensions)) {
1199
- return null;
1200
- }
1201
- const centerPointX = dimensions.width / 2;
1202
- const centerPointY = dimensions.height / 2;
1203
- const donutPositionX = realPosX - centerPointX;
1204
- const donutPositionY = realPosY - centerPointY;
1205
- const hoverPosArcInfo = pointToArc(donutPositionX, donutPositionY);
1206
- const arcCenterLine = (outer + inner) / 2;
1207
- //Detect donut slice
1208
- let foundYIndex = -1;
1209
- let preferredPosition = undefined;
1210
- let donutXPosition = 0;
1211
- let donutYPosition = 0;
1212
- for (let i = 0; i < pieArcs.length; i++) {
1213
- const arc = pieArcs[i];
1214
- if (hoverPosArcInfo.angle > arc.startAngle &&
1215
- hoverPosArcInfo.angle < arc.endAngle &&
1216
- hoverPosArcInfo.radius > arcCenterLine - drawRadius &&
1217
- hoverPosArcInfo.radius < arcCenterLine + drawRadius) {
1218
- foundYIndex = i;
1219
- const arcCenterPoint = arcToPoint((arc.startAngle + arc.endAngle) / 2, arcCenterLine);
1220
- //Need to un-offset the positions
1221
- donutXPosition = arcCenterPoint.x + centerPointX;
1222
- donutYPosition = arcCenterPoint.y + centerPointY;
1223
- const verticalArea = arcCenterPoint.y < (dimensions.height * -1) / 4
1224
- ? 'top'
1225
- : arcCenterPoint.y > dimensions.height / 4
1226
- ? 'bottom'
1227
- : 'center';
1228
- //Determine the best position for the tooltip
1229
- if (arcCenterPoint.x > 0) {
1230
- //Right path
1231
- if (!config.groupedTooltip || verticalArea === 'center') {
1232
- preferredPosition = 'center-right';
1233
- }
1234
- else if (verticalArea === 'top') {
1235
- preferredPosition = 'right-top';
1236
- }
1237
- else if (verticalArea === 'bottom') {
1238
- preferredPosition = 'right-bottom';
1239
- }
1240
- }
1241
- else {
1242
- //Left path
1243
- if (!config.groupedTooltip || verticalArea === 'center') {
1244
- preferredPosition = 'center-left';
1245
- }
1246
- else if (verticalArea === 'top') {
1247
- preferredPosition = 'left-top';
1248
- }
1249
- else if (verticalArea === 'bottom') {
1250
- preferredPosition = 'left-bottom';
1251
- }
1252
- }
1253
- break;
1254
- }
1255
- }
1256
- if (foundYIndex === -1) {
1257
- return null;
1258
- }
1259
- if (!hasNonZeroValue) {
1260
- donutXPosition = centerPointX + arcCenterLine;
1261
- donutYPosition = centerPointY;
1262
- }
1263
- const localAnchorX = donutXPosition - pos.containerScrollX;
1264
- const localAnchorY = donutYPosition - pos.containerScrollY;
1265
- const { anchorX, anchorY } = checkAnchorsAgainstBound(localAnchorX, localAnchorY, dimensions);
1266
- const anchor = new DOMRect(anchorX + pos.rect.x, anchorY + pos.rect.y, SMALL_PADDING, 0);
1267
- return {
1268
- hoverType: 'standard',
1269
- tooltip: {
1270
- anchor,
1271
- preferredPosition,
1272
- date: null,
1273
- metrics: donutData
1274
- .map((y, index) => ({
1275
- color: colors[index % colors.length],
1276
- label: y.label,
1277
- value: pipeTransform(y.value, y.isSecondary, true),
1278
- }))
1279
- .filter((_, i) => config.groupedTooltip || i === foundYIndex),
1280
- },
1281
- //Not used by donut charts
1282
- x: 0,
1283
- xIndex: 0,
1284
- ys: [],
1285
- yIndex: 0,
1286
- visibleYIndex: 0,
1287
- };
1288
- }
1289
- return {
1290
- chartWidth: drawWidth,
1291
- chartHeight: drawHeight,
1292
- chartSizingValues: {
1293
- ...emptyChartScaleValues,
1294
- dataLabelPadding: dataLabelPaddingConfig.target,
1295
- dataLabelTextSize: dataLabelTextSizing.horizontal,
1296
- fontSize: fontSizeConfig.target,
1297
- },
1298
- xTicks: [],
1299
- yTicks: [],
1300
- areas: [],
1301
- lines: [],
1302
- circles: [],
1303
- bars: [],
1304
- colors,
1305
- arcs,
1306
- horizontalBars: [],
1307
- dataLabels,
1308
- waterfallLines: [],
1309
- gradients: [],
1310
- flowConnections: [],
1311
- horizontalContainerScale,
1312
- verticalContainerScale,
1313
- chartError: null,
1314
- hover,
1315
- };
1316
- }
1317
- function flows(config, allData, dimensions) {
1318
- if (allData.type !== 'flow') {
1319
- // eslint-disable-next-line no-console
1320
- console.warn(`Heads up! The '${allData.type}' data type isn't supported for flow charts.`);
1321
- return { ...emptyChart, chartError: 'config' };
1322
- }
1323
- const data = flowsTransform(config, allData);
1324
- if (data.x.length === 0) {
1325
- return emptyChart;
1326
- }
1327
- const overallTotal = data.x[0].totalCount;
1328
- const chartSizingValues = getFullChartScaleValues(config, data, dimensions, null, null);
1329
- if (chartSizingValues === null) {
1330
- return { ...emptyChart, chartError: 'sizing' };
1331
- }
1332
- const { scale } = calcDataAxisScalesAndTicks(data, null, config, chartSizingValues);
1333
- const valuePipes = getPipes(config.valueType);
1334
- const percentPipes = getPipes('percentage');
1335
- const bars = [];
1336
- const flowConnections = [];
1337
- const dataLabels = [];
1338
- const minimumSize = getMinimumDataElementSize(config);
1339
- for (let i = 0; i < data.x.length; i++) {
1340
- const bucketBars = [];
1341
- let runningHeight = 0;
1342
- for (const bar of data.x[i].subBuckets) {
1343
- const continuingCount = bar.connections
1344
- .filter(connection => connection.direction === 'forward')
1345
- .map(connection => connection.count)
1346
- .reduce((a, b) => a + b, 0);
1347
- const { totalSize: totalHeight, continuingSize: darkenedHeight, connectionSizes, } = getFlowSubBucketSizes(bar, value => scale(value, false) - chartSizingValues.totalTopOffset, minimumSize);
1348
- const connectionHeight = (connection) => connectionSizes[bar.connections.indexOf(connection)];
1349
- const nonDarkenedHeight = totalHeight - darkenedHeight;
1350
- const darkenedY = runningHeight + chartSizingValues.totalTopOffset;
1351
- const nonDarkenedY = darkenedY + darkenedHeight;
1352
- const width = chartSizingValues.barSize;
1353
- const x = chartSizingValues.totalLeftOffset +
1354
- i * (chartSizingValues.barSize + chartSizingValues.bucketGap);
1355
- const colorOverride = config.flowConfig.subBucketsConfig.find(bc => bc.bucketId === bar.id)?.color;
1356
- if (darkenedHeight > 0) {
1357
- bucketBars.push({
1358
- elementType: 'rect',
1359
- rectType: 'flow',
1360
- height: darkenedHeight,
1361
- width,
1362
- y: darkenedY,
1363
- x,
1364
- colorOverride,
1365
- darken: true,
1366
- deEmphasize: isDeEmphasized(config, bar.id, true),
1367
- id: bar.id,
1368
- bucketIndex: i,
1369
- count: continuingCount,
1370
- totalCount: bar.count,
1371
- });
1372
- }
1373
- if (nonDarkenedHeight > 0) {
1374
- bucketBars.push({
1375
- elementType: 'rect',
1376
- rectType: 'flow',
1377
- height: nonDarkenedHeight,
1378
- width,
1379
- y: nonDarkenedY,
1380
- x,
1381
- colorOverride,
1382
- darken: false,
1383
- deEmphasize: isDeEmphasized(config, bar.id, false),
1384
- id: bar.id,
1385
- bucketIndex: i,
1386
- count: bar.count - continuingCount,
1387
- totalCount: bar.count,
1388
- });
1389
- }
1390
- //Invisible bar for hover highlight purposes
1391
- bucketBars.push({
1392
- elementType: 'rect',
1393
- rectType: 'flow',
1394
- height: darkenedHeight + nonDarkenedHeight,
1395
- width,
1396
- y: darkenedY,
1397
- x,
1398
- nonDisplay: true,
1399
- id: bar.id,
1400
- bucketIndex: i,
1401
- count: bar.count,
1402
- totalCount: bar.count,
1403
- darken: false,
1404
- deEmphasize: false,
1405
- });
1406
- runningHeight +=
1407
- totalHeight +
1408
- chartSizingValues.dataLabelPadding +
1409
- chartSizingValues.dataLabelTextSize;
1410
- //Connections
1411
- //Add new renders for forward connections
1412
- let verticalConnectionOffset = 0;
1413
- for (const connection of bar.connections.filter(connection => connection.direction === 'forward')) {
1414
- const topLineY1 = darkenedY + verticalConnectionOffset;
1415
- const bottomLineY1 = topLineY1 + connectionHeight(connection);
1416
- const x1 = x + width;
1417
- const connectionRender = {
1418
- elementType: 'connection',
1419
- start: connection.start,
1420
- end: connection.end,
1421
- count: connection.count,
1422
- step: i,
1423
- topLine: {
1424
- y1: topLineY1,
1425
- x1,
1426
- //To be filled in later
1427
- y2: 0,
1428
- x2: 0,
1429
- },
1430
- bottomLine: {
1431
- y1: bottomLineY1,
1432
- x1,
1433
- //To be filled in later
1434
- y2: 0,
1435
- x2: 0,
1436
- },
1437
- //To be filled in later
1438
- path: '',
1439
- };
1440
- verticalConnectionOffset += connectionHeight(connection);
1441
- flowConnections.push(connectionRender);
1442
- }
1443
- //Backfill position info for backwards connections
1444
- verticalConnectionOffset = 0;
1445
- for (const connection of bar.connections.filter(connection => connection.direction === 'backward')) {
1446
- const matchingConnection = flowConnections.find(con => con.start === connection.start &&
1447
- con.end === connection.end &&
1448
- con.step === i - 1);
1449
- if (matchingConnection) {
1450
- const topLineY2 = darkenedY + verticalConnectionOffset;
1451
- const bottomLineY2 = topLineY2 + connectionHeight(connection);
1452
- matchingConnection.topLine.y2 = topLineY2;
1453
- matchingConnection.topLine.x2 = x;
1454
- matchingConnection.bottomLine.y2 = bottomLineY2;
1455
- matchingConnection.bottomLine.x2 = x;
1456
- matchingConnection.path =
1457
- calculateFlowConnectionPath(matchingConnection);
1458
- verticalConnectionOffset += connectionHeight(connection);
1459
- }
1460
- }
1461
- //Data Labels
1462
- const barName = config.flowConfig.subBucketsConfig.find(sbc => sbc.bucketId === bar.id)?.bucketName;
1463
- if (barName !== undefined) {
1464
- dataLabels.push({
1465
- elementType: 'dataLabel',
1466
- dataLabelType: 'flow',
1467
- label: `${barName} (${percentPipes.pipe.transform(bar.count / data.x[i].totalCount)})`,
1468
- xPos: x,
1469
- yPos: darkenedY -
1470
- (chartSizingValues.dataLabelTextSize +
1471
- chartSizingValues.dataLabelPadding) /
1472
- 2,
1473
- anchor: 'start',
1474
- bold: true,
1475
- bucketIndex: i,
1476
- barId: bar.id,
1477
- });
1478
- }
1479
- const barSubtitle = config.flowConfig.subtitleFormatString.replace('{value}', valuePipes.pipe.transform(bar.count));
1480
- dataLabels.push({
1481
- elementType: 'dataLabel',
1482
- dataLabelType: 'flow',
1483
- label: barSubtitle,
1484
- xPos: x,
1485
- yPos: darkenedY - chartSizingValues.dataLabelPadding / 4,
1486
- anchor: 'start',
1487
- bucketIndex: i,
1488
- barId: bar.id,
1489
- });
1490
- }
1491
- bars.push(bucketBars);
1492
- }
1493
- function hover(pos) {
1494
- const realPosX = pos.x + pos.containerScrollX;
1495
- const realPosY = pos.y + pos.containerScrollY;
1496
- if (chartSizingValues === null ||
1497
- getIfHoverOutOfBounds(pos.x, pos.y, realPosX, realPosY, chartSizingValues, dimensions)) {
1498
- return null;
1499
- }
1500
- const bucketIndexInfo = getFlowBucketIndexForHover(chartSizingValues, realPosX);
1501
- if (bucketIndexInfo === null || bucketIndexInfo.index >= bars.length) {
1502
- return null;
1503
- }
1504
- if (bucketIndexInfo.area === 'bar') {
1505
- for (const bar of bars[bucketIndexInfo.index]) {
1506
- if (realPosY < bar.y) {
1507
- //Bar title
1508
- const localAnchorX = bar.x - pos.containerScrollX;
1509
- const width = bar.width;
1510
- const height = chartSizingValues.dataLabelPadding / 2 +
1511
- chartSizingValues.dataLabelTextSize;
1512
- const localAnchorY = bar.y - (pos.containerScrollY + height);
1513
- const { anchorX, anchorY, anchorWidth, anchorHeight } = checkAnchorsAgainstBound(localAnchorX, localAnchorY, dimensions, width, height);
1514
- const anchor = new DOMRect(anchorX + pos.rect.x, anchorY + pos.rect.y, anchorWidth, anchorHeight);
1515
- return {
1516
- hoverType: 'flow',
1517
- hoverTarget: 'barTitle',
1518
- barId: bar.id ?? '',
1519
- bucketIndex: bucketIndexInfo.index,
1520
- tooltip: {
1521
- anchor,
1522
- subtitle: config.flowConfig.subtitleFormatString.replace('{value}', valuePipes.pipe.transform(bar.totalCount)),
1523
- },
1524
- };
1525
- }
1526
- else if (
1527
- // The invisible highlight bar spans both portions, so skip it to
1528
- // avoid misreporting a portion boundary as the ending portion
1529
- !bar.nonDisplay &&
1530
- realPosY >= bar.y &&
1531
- realPosY < bar.y + bar.height) {
1532
- //Bar
1533
- const localAnchorX = bar.x - pos.containerScrollX;
1534
- const width = bar.width;
1535
- const localAnchorY = bar.y - pos.containerScrollY;
1536
- const height = bar.height;
1537
- const { anchorX, anchorY, anchorWidth, anchorHeight } = checkAnchorsAgainstBound(localAnchorX, localAnchorY, dimensions, width, height);
1538
- const anchor = new DOMRect(anchorX + pos.rect.x, anchorY + pos.rect.y, anchorWidth, anchorHeight);
1539
- return {
1540
- hoverType: 'flow',
1541
- hoverTarget: 'bar',
1542
- barId: bar.id ?? '',
1543
- bucketIndex: bucketIndexInfo.index,
1544
- forDarken: bar.darken === true,
1545
- tooltip: {
1546
- anchor,
1547
- subtitle: config.flowConfig.subtitleFormatString.replace('{value}', valuePipes.pipe.transform(bar.count)),
1548
- },
1549
- };
1550
- }
1551
- }
1552
- }
1553
- else {
1554
- for (const connection of flowConnections.filter(flowCon => flowCon.step === bucketIndexInfo.index)) {
1555
- if (checkIfPointWithinConnection(connection, realPosX, realPosY)) {
1556
- const localAnchorX = connection.topLine.x1 - pos.containerScrollX;
1557
- const width = connection.topLine.x2 - connection.topLine.x1;
1558
- const curveTop = bezierYAtX((connection.topLine.x1 + connection.topLine.x2) / 2, connection.topLine);
1559
- const curveBottom = bezierYAtX((connection.topLine.x1 + connection.topLine.x2) / 2, connection.bottomLine);
1560
- const localAnchorY = curveTop - pos.containerScrollY;
1561
- const height = curveBottom - curveTop;
1562
- const { anchorX, anchorY, anchorWidth, anchorHeight } = checkAnchorsAgainstBound(localAnchorX, localAnchorY, dimensions, width, height);
1563
- const anchor = new DOMRect(anchorX + pos.rect.x, anchorY + pos.rect.y, anchorWidth, anchorHeight);
1564
- return {
1565
- hoverType: 'flow',
1566
- hoverTarget: 'connection',
1567
- startId: connection.start,
1568
- endId: connection.end,
1569
- startBucketIndex: connection.step,
1570
- tooltip: {
1571
- anchor,
1572
- subtitle: config.flowConfig.subtitleFormatString.replace('{value}', valuePipes.pipe.transform(connection.count)),
1573
- },
1574
- };
1575
- }
1576
- }
1577
- }
1578
- return null;
1579
- }
1580
- return {
1581
- chartWidth: chartSizingValues.totalWidth,
1582
- chartHeight: chartSizingValues.totalHeight,
1583
- chartSizingValues,
1584
- xTicks: [],
1585
- yTicks: [],
1586
- colors: [],
1587
- bars,
1588
- lines: [],
1589
- circles: [],
1590
- areas: [],
1591
- hover,
1592
- arcs: [],
1593
- horizontalBars: [],
1594
- dataLabels,
1595
- waterfallLines: [],
1596
- gradients: [],
1597
- flowConnections,
1598
- horizontalContainerScale: chartSizingValues.horizontalContainerScale,
1599
- verticalContainerScale: chartSizingValues.verticalContainerScale,
1600
- chartError: null,
1601
- };
1602
- }
1603
- /*
1604
- Mirrors the bucketing in flowsTransform: a path contributes values[i] to
1605
- the bar at step i, and values[i + 1] to its forward connection (which is
1606
- also the bar's continuing portion).
1607
- */
1608
- function flowValueAtStep(y, step) {
1609
- return y.steps.length > step && y.values.length > step
1610
- ? y.values[step]
1611
- : null;
1612
- }
1613
- function sumFlowValues(data, yIndices, step) {
1614
- return yIndices
1615
- .map(index => flowValueAtStep(data.ys[index], step) ?? 0)
1616
- .reduce((a, b) => a + b, 0);
1617
- }
1618
- function toFlowClickEvent(hover, data) {
1619
- const allYIndices = data.ys.map((_, index) => index);
1620
- if (hover.hoverTarget === 'connection') {
1621
- const step = hover.startBucketIndex;
1622
- const yIndices = allYIndices.filter(index => data.ys[index].steps[step] === hover.startId &&
1623
- flowValueAtStep(data.ys[index], step) !== null &&
1624
- data.ys[index].steps[step + 1] === hover.endId &&
1625
- flowValueAtStep(data.ys[index], step + 1) !== null);
1626
- return {
1627
- target: 'connection',
1628
- startBucketIndex: step,
1629
- startId: hover.startId,
1630
- endId: hover.endId,
1631
- count: sumFlowValues(data, yIndices, step + 1),
1632
- yIndices,
1633
- };
1634
- }
1635
- const step = hover.bucketIndex;
1636
- const barYIndices = allYIndices.filter(index => data.ys[index].steps[step] === hover.barId &&
1637
- flowValueAtStep(data.ys[index], step) !== null);
1638
- const totalCount = sumFlowValues(data, barYIndices, step);
1639
- const base = { bucketIndex: step, barId: hover.barId };
1640
- if (hover.hoverTarget === 'barTitle') {
1641
- return {
1642
- ...base,
1643
- target: 'title',
1644
- count: totalCount,
1645
- yIndices: barYIndices,
1646
- };
1647
- }
1648
- const continuingCount = sumFlowValues(data, barYIndices, step + 1);
1649
- if (hover.forDarken) {
1650
- return {
1651
- ...base,
1652
- target: 'continuing',
1653
- count: continuingCount,
1654
- totalCount,
1655
- yIndices: barYIndices.filter(index => (flowValueAtStep(data.ys[index], step + 1) ?? 0) > 0),
1656
- };
1657
- }
1658
- return {
1659
- ...base,
1660
- target: 'ending',
1661
- count: totalCount - continuingCount,
1662
- totalCount,
1663
- yIndices: barYIndices.filter(index => (flowValueAtStep(data.ys[index], step) ?? 0) >
1664
- (flowValueAtStep(data.ys[index], step + 1) ?? 0)),
1665
- };
1666
- }
1667
- Chart.toFlowClickEvent = toFlowClickEvent;
1668
- const SMALL_PADDING = 8;
1669
- Chart.DEFAULT_FONT_SIZE = 12; //the width constants are based on font size 12, so this variable can help w/ scaling
1670
- Chart.WIDTH_PER_LETTER = 6.5;
1671
- const WIDTH_PER_NUMBER = 7;
1672
- const WIDTH_PER_PERIOD = 2;
1673
- const WIDTH_PER_SLASH = 4;
1674
- //When the data axis grows, the data is always given at least this portion of the provided size
1675
- const GROWN_DATA_MINIMUM_RATIO = 0.5;
1676
- const DEFAULT_HORIZONTAL_BAR_CORNER_RADIUS = 4;
1677
- const FLOW_CONNECTION_CURVE_CONSTANT = 0.5;
1678
- function getFormattingAndColors(originalData, data, config) {
1679
- const dateFormat = (date) => formatedDate(config.dateFormat || 'day', date);
1680
- const { pipe, fullPipe } = getPipes(config.valueType);
1681
- const { pipe: secondaryPipe, fullPipe: secondaryFullPipe } = config.secondaryValueType
1682
- ? getPipes(config.secondaryValueType)
1683
- : {
1684
- pipe,
1685
- fullPipe,
1686
- };
1687
- const pipeTransform = (value, isSecondary, isFull) => {
1688
- if (isFull !== true) {
1689
- if (isSecondary === true) {
1690
- return secondaryPipe.transform(value);
1691
- }
1692
- return pipe.transform(value);
1693
- }
1694
- let retVal = null;
1695
- if (isSecondary) {
1696
- retVal = secondaryFullPipe.transform(value);
1697
- }
1698
- else {
1699
- retVal = fullPipe.transform(value);
1700
- }
1701
- return retVal !== null ? retVal : '-';
1702
- };
1703
- // Pre-calculate color indices for all items (use original data for stable colors)
1704
- const colorIndices = calculateColorIndices(originalData);
1705
- const colors = data.ys.map(y => getColor(y, colorIndices, config.colors));
1706
- return {
1707
- dateFormat,
1708
- pipeTransform,
1709
- colorIndices,
1710
- colors,
1711
- };
1712
- }
1713
- function calculateColorIndices(data) {
1714
- const colorMap = new Map();
1715
- // Original Ys: use their array index directly
1716
- data.ys.forEach((y, index) => {
1717
- colorMap.set(y, index);
1718
- });
1719
- // Supplementary Ys: group by supplementalIndex, use position within that group
1720
- if (hasSupplementaryData(data)) {
1721
- const suppGroups = new Map();
1722
- data.supplementaryYs.forEach(suppY => {
1723
- if (!suppGroups.has(suppY.supplementalIndex)) {
1724
- suppGroups.set(suppY.supplementalIndex, []);
1725
- }
1726
- suppGroups.get(suppY.supplementalIndex).push(suppY);
1727
- });
1728
- suppGroups.forEach(items => {
1729
- items.forEach((item, positionInGroup) => {
1730
- colorMap.set(item, positionInGroup);
1731
- });
1732
- });
1733
- }
1734
- return colorMap;
1735
- }
1736
- Chart.calculateColorIndices = calculateColorIndices;
1737
- function getColor(item, colorIndices, colors) {
1738
- if (item === undefined) {
1739
- return colors[0];
1740
- }
1741
- if (item.colorToken)
1742
- return item.colorToken;
1743
- const colorIndex = colorIndices.get(item) ?? 0;
1744
- return colors[colorIndex % colors.length];
1745
- }
1746
- Chart.getColor = getColor;
1747
- function getBucketTickCount(chartSizingValues) {
1748
- let availableSize = 0;
1749
- let minSpacing = 1;
1750
- if (chartSizingValues.chartDataDirection === 'vertical') {
1751
- availableSize =
1752
- chartSizingValues.totalWidth -
1753
- chartSizingValues.leftPadding -
1754
- chartSizingValues.rightPadding;
1755
- minSpacing =
1756
- chartSizingValues.horizontalAxisLabelTextSize + SMALL_PADDING;
1757
- }
1758
- if (chartSizingValues.chartDataDirection === 'horizontal') {
1759
- availableSize =
1760
- chartSizingValues.totalHeight -
1761
- chartSizingValues.topPadding -
1762
- chartSizingValues.bottomPadding;
1763
- minSpacing = chartSizingValues.verticalAxisLabelTextSize + SMALL_PADDING;
1764
- }
1765
- minSpacing = minSpacing * (chartSizingValues.fontSize / Chart.DEFAULT_FONT_SIZE);
1766
- return Math.max(2, Math.floor(availableSize / minSpacing));
1767
- }
1768
- function getClusterInfoForBucket(data, config) {
1769
- // Slot layout is the same for every bucket — zero values still occupy
1770
- // their slot, they just render with no height/width. This keeps bucket
1771
- // sizes, bar positions, and hover detection consistent across buckets
1772
- // regardless of which series happen to be zero.
1773
- const normClusterIndices = data.ys.map((_, yIndex) => yIndex);
1774
- const normClusterCount = normClusterIndices.length;
1775
- const suppClusterIndices = uniq(hasSupplementaryData(data)
1776
- ? data.supplementaryYs.map(y => y.supplementalIndex)
1777
- : []);
1778
- suppClusterIndices.sort((a, b) => a - b);
1779
- const suppClusterCount = suppClusterIndices.length;
1780
- const actualNormClusterCount = isClusteredData(data, config, false)
1781
- ? normClusterCount
1782
- : Math.min(normClusterCount, 1);
1783
- return {
1784
- normCount: actualNormClusterCount,
1785
- suppCount: suppClusterCount,
1786
- total: actualNormClusterCount + suppClusterCount,
1787
- normClusterIndices,
1788
- suppClusterIndices,
1789
- };
1790
- }
1791
- //This function gives the total distance from the start of the given bucket, to the end of the current bucket
1792
- function getBucketSize(data, config, chartSizingValues) {
1793
- const totalBarNumber = getClusterInfoForBucket(data, config);
1794
- const bucketSize = totalBarNumber.total * chartSizingValues.barSize +
1795
- (totalBarNumber.total - 1) * chartSizingValues.barClusterGap;
1796
- return bucketSize;
1797
- }
1798
- //This function gives the total distance from the start of the given bucket, to the start of the next bucket
1799
- function getTotalBucketGap(data, config, chartSizingValues) {
1800
- const bucketSize = getBucketSize(data, config, chartSizingValues);
1801
- return bucketSize + chartSizingValues.bucketGap;
1802
- }
1803
- //This function gives the total distance from the start of the first bucket, to the start of the given bucket
1804
- function getTotalPreBucketGap(data, config, chartSizingValues, bucketIndex) {
1805
- let cumulativeBucketGap = 0;
1806
- for (let i = 0; i < bucketIndex; i++) {
1807
- cumulativeBucketGap += getTotalBucketGap(data, config, chartSizingValues);
1808
- }
1809
- return cumulativeBucketGap;
1810
- }
1811
- function generateTimeseriesTicks(data, config, tickCount, chartSizingValues, format) {
1812
- const getLabel = (index) => {
1813
- return format(new Date(data.x[index]));
1814
- };
1815
- return getTicks(data, getLabel, config, tickCount, chartSizingValues);
1816
- }
1817
- function generateLabelledTicks(data, config, tickCount, chartSizingValues) {
1818
- const getLabel = (index) => {
1819
- return data.x[index].label;
1820
- };
1821
- return getTicks(data, getLabel, config, tickCount, chartSizingValues);
1822
- }
1823
- function getTicks(data, getLabel, config, tickCount, chartSizingValues) {
1824
- if (data.x.length === 0) {
1825
- return [];
1826
- }
1827
- if (data.x.length === 1) {
1828
- const labelOffset = getTickLabelOffset(data, config, chartSizingValues, 0);
1829
- return [{ value: labelOffset, label: getLabel(0) }];
1830
- }
1831
- const lastIndex = data.x.length - 1;
1832
- const tickBucketSpacing = Math.ceil(lastIndex / tickCount);
1833
- const numTicks = Math.floor(lastIndex / tickBucketSpacing) + 1;
1834
- const step = lastIndex / (numTicks - 1);
1835
- // Always include first and last data points.
1836
- // Inner ticks are approximately evenly spaced using rounding.
1837
- const indices = [];
1838
- for (let i = 0; i < numTicks; i++) {
1839
- indices.push(Math.round(i * step));
1840
- }
1841
- return indices.map(i => {
1842
- const labelOffset = getTickLabelOffset(data, config, chartSizingValues, i);
1843
- return {
1844
- value: getTotalPreBucketGap(data, config, chartSizingValues, i) +
1845
- labelOffset,
1846
- label: getLabel(i),
1847
- };
1848
- });
1849
- }
1850
- function getTickLabelOffset(data, config, chartSizingValues, bucketIndex) {
1851
- const inherentOffset = chartSizingValues.chartDataDirection === 'horizontal'
1852
- ? chartSizingValues.totalTopOffset
1853
- : chartSizingValues.totalLeftOffset;
1854
- //To have the label be centered on the bucket's center position
1855
- const bucketOffset = getBucketSize(data, config, chartSizingValues) / 2;
1856
- let horizontalBarOffset = 0;
1857
- if (chartSizingValues.chartDataDirection === 'horizontal') {
1858
- //This account for the fact that the inherentOffset and bucketOffset result in matching y values for the bar and the label
1859
- // However, for the bar, that y position is the top of the bar, while for the label, it's the bottom of the label
1860
- // When exactly lined up like that, the label actually looks a little low, so that -2 makes it look correct
1861
- horizontalBarOffset = chartSizingValues.fontSize / 2 - 2;
1862
- }
1863
- return inherentOffset + bucketOffset + horizontalBarOffset;
1864
- }
1865
- Chart.defaultConfig = {
1866
- type: 'line',
1867
- groupedTooltip: true,
1868
- colors: Chart.defaultColorPalette,
1869
- allowLegendToggle: false,
1870
- zeroStateMessage: 'No data to display.',
1871
- sizingErrorStateMessage: 'The chart cannot display at the current size.',
1872
- valueType: 'currency',
1873
- truncateLegend: true,
1874
- dateFormat: 'day',
1875
- };
1876
- Chart.defaultDonutConfig = {
1877
- type: 'donut',
1878
- groupedTooltip: true,
1879
- colors: Chart.defaultColorPalette,
1880
- allowLegendToggle: false,
1881
- zeroStateMessage: 'No data to display.',
1882
- sizingErrorStateMessage: 'The chart cannot display at the current size.',
1883
- valueType: 'currency',
1884
- truncateLegend: true,
1885
- dateFormat: 'day',
1886
- donutDisplayInfo: {
1887
- size: 'medium',
1888
- displayValue: '',
1889
- },
1890
- };
1891
- function toXTick(tick) {
1892
- return {
1893
- x: tick.value,
1894
- label: tick.label,
1895
- secondaryLabel: tick.secondaryLabel,
1896
- };
1897
- }
1898
- function toYTick(tick) {
1899
- return {
1900
- y: tick.value,
1901
- label: tick.label,
1902
- secondaryLabel: tick.secondaryLabel,
1903
- };
1904
- }
1905
- const emptyChart = {
1906
- chartWidth: 0,
1907
- chartHeight: 0,
1908
- chartSizingValues: emptyChartScaleValues,
1909
- xTicks: [],
1910
- yTicks: [],
1911
- colors: [],
1912
- lines: [],
1913
- circles: [],
1914
- areas: [],
1915
- bars: [],
1916
- arcs: [],
1917
- horizontalBars: [],
1918
- dataLabels: [],
1919
- waterfallLines: [],
1920
- gradients: [],
1921
- flowConnections: [],
1922
- horizontalContainerScale: 'no-scale',
1923
- verticalContainerScale: 'no-scale',
1924
- chartError: null,
1925
- };
1926
- //'y' in this function refers to the data y, since this function
1927
- // is also used by horizontal-bars, where the data y is the chart x
1928
- function calcDataAxisScalesAndTicks(data, pipeTransformInput, config, chartSizingValues) {
1929
- const pipeTransform = pipeTransformInput !== null ? pipeTransformInput : () => '';
1930
- const { primaryDataMin, primaryDataMax, secondaryDataMin, secondaryDataMax, scaleDomainMultipleForMax, scaleDomainMultipleForNeg, } = calcDataScalingValues(data, config);
1931
- const startOffset = chartSizingValues.chartDataDirection === 'horizontal'
1932
- ? chartSizingValues.totalLeftOffset
1933
- : chartSizingValues.totalTopOffset;
1934
- let minSpacing = (chartSizingValues.chartDataDirection === 'horizontal'
1935
- ? chartSizingValues.horizontalAxisLabelTextSize
1936
- : chartSizingValues.verticalAxisLabelTextSize) + SMALL_PADDING;
1937
- minSpacing = minSpacing * (chartSizingValues.fontSize / Chart.DEFAULT_FONT_SIZE);
1938
- const spacingTickCount = Math.max(2, Math.floor(chartSizingValues.sizeForData / minSpacing));
1939
- const actualTargetTickCount = Math.min(spacingTickCount, chartSizingValues.targetTickCount);
1940
- const hasPrimary = primaryDataMin !== 0 || primaryDataMax !== 0;
1941
- const hasSecondary = secondaryDataMin !== 0 || secondaryDataMax !== 0;
1942
- const scaleRange = chartSizingValues.chartDataDirection === 'horizontal' ||
1943
- config.type === 'flow'
1944
- ? [0, chartSizingValues.sizeForData]
1945
- : [chartSizingValues.sizeForData, 0];
1946
- //These 'effective' values ensure we have room for potential stacking of secondary and non-secondary values
1947
- let effectivePrimaryMin = primaryDataMin * scaleDomainMultipleForNeg;
1948
- let effectivePrimaryMax = primaryDataMax * scaleDomainMultipleForMax;
1949
- //Simpler path for data w/o secondaries
1950
- if (!hasSecondary) {
1951
- const primaryYDomain = [effectivePrimaryMin, effectivePrimaryMax];
1952
- const yScale = scaleLinear(primaryYDomain, scaleRange);
1953
- const ticks = yScale
1954
- .ticks(actualTargetTickCount)
1955
- .map(tick => ({
1956
- value: yScale(tick) + startOffset,
1957
- label: pipeTransform(tick, false),
1958
- }));
1959
- const scale = (input) => {
1960
- return yScale(input) + startOffset;
1961
- };
1962
- return {
1963
- scale,
1964
- ticks,
1965
- };
1966
- }
1967
- //Simpler path for data w/o primaries
1968
- if (!hasPrimary) {
1969
- const secondaryYDomain = [secondaryDataMin, secondaryDataMax];
1970
- const yScale = scaleLinear(secondaryYDomain, scaleRange);
1971
- const ticks = yScale
1972
- .ticks(actualTargetTickCount)
1973
- .map(tick => ({
1974
- value: yScale(tick) + startOffset,
1975
- label: pipeTransform(tick, true),
1976
- }));
1977
- const scale = (input) => {
1978
- return yScale(input) + startOffset;
1979
- };
1980
- return {
1981
- scale,
1982
- ticks,
1983
- };
1984
- }
1985
- let effectiveSecondaryMax = 0;
1986
- let effectiveSecondaryMin = 0;
1987
- //This block sets the effective max for primary and secondary
1988
- //This to ensure that the effective maxes for both data sets are properly set so that
1989
- // 0 will fall at the same place on both and each will have 'room' for potential stacking
1990
- if ((primaryDataMax <= 0 && secondaryDataMin >= 0) ||
1991
- (primaryDataMin >= 0 && secondaryDataMax <= 0)) {
1992
- //In this scenario, one set of data is competely positive, while the other is completely negative
1993
- //The two data sets can scale completely independently
1994
- //We 'mirror' the values of the two data sets, which'll put the 0 axis in the center of the data
1995
- if (primaryDataMax <= 0) {
1996
- effectivePrimaryMax = Math.abs(effectivePrimaryMin);
1997
- }
1998
- if (primaryDataMin >= 0) {
1999
- effectivePrimaryMin = -Math.abs(effectivePrimaryMax);
2000
- }
2001
- if (secondaryDataMax <= 0) {
2002
- effectiveSecondaryMin = secondaryDataMin;
2003
- effectiveSecondaryMax = Math.abs(secondaryDataMin);
2004
- }
2005
- if (secondaryDataMin >= 0) {
2006
- effectiveSecondaryMax = secondaryDataMax;
2007
- effectiveSecondaryMin = -secondaryDataMax;
2008
- }
2009
- }
2010
- else if (primaryDataMax > 0) {
2011
- if (primaryDataMin < 0) {
2012
- //Primary data has positive and negative
2013
- if (secondaryDataMax > 0) {
2014
- //Secondary data has positive
2015
- effectiveSecondaryMax = secondaryDataMax * scaleDomainMultipleForMax;
2016
- if (secondaryDataMin < 0) {
2017
- //Secondary data has negative
2018
- effectiveSecondaryMin =
2019
- secondaryDataMin * scaleDomainMultipleForNeg;
2020
- }
2021
- else {
2022
- //Secondary data is only positive
2023
- effectiveSecondaryMin =
2024
- (secondaryDataMax / primaryDataMax) *
2025
- primaryDataMin *
2026
- scaleDomainMultipleForNeg;
2027
- }
2028
- }
2029
- else {
2030
- //Secondary data has only negative
2031
- effectiveSecondaryMin = secondaryDataMin * scaleDomainMultipleForNeg;
2032
- effectiveSecondaryMax =
2033
- (secondaryDataMin / primaryDataMin) *
2034
- primaryDataMax *
2035
- scaleDomainMultipleForMax;
2036
- }
2037
- }
2038
- else {
2039
- //Primary data is only positive
2040
- //Due to earlier check, we know that secondary data is either also all-positive, or positive and negative
2041
- effectiveSecondaryMax = secondaryDataMax * scaleDomainMultipleForMax;
2042
- effectiveSecondaryMin = secondaryDataMin * scaleDomainMultipleForNeg;
2043
- effectivePrimaryMin =
2044
- (primaryDataMax / secondaryDataMax) *
2045
- secondaryDataMin *
2046
- scaleDomainMultipleForNeg;
2047
- }
2048
- }
2049
- else {
2050
- //Primary data is only negative
2051
- //Due to earlier check, we know that secondary data is either also all-negative, or positive and negative
2052
- effectiveSecondaryMax = secondaryDataMax * scaleDomainMultipleForMax;
2053
- effectiveSecondaryMin = secondaryDataMin * scaleDomainMultipleForNeg;
2054
- effectivePrimaryMax =
2055
- (primaryDataMin / secondaryDataMin) *
2056
- secondaryDataMax *
2057
- scaleDomainMultipleForMax;
2058
- }
2059
- const primaryYDomain = [effectivePrimaryMin, effectivePrimaryMax];
2060
- const yScale = scaleLinear(primaryYDomain, scaleRange);
2061
- //Figuring out the best tick count to fit the two data srouces
2062
- const yScalePrimaryProto = scaleLinear(primaryYDomain, scaleRange);
2063
- const yScaleSecondaryProto = scaleLinear([effectiveSecondaryMin, effectiveSecondaryMax], scaleRange);
2064
- const tickCount = Math.max(actualTargetTickCount, yScalePrimaryProto.ticks(actualTargetTickCount).length, yScaleSecondaryProto.ticks(actualTargetTickCount).length);
2065
- const primaryTicks = yScale.ticks(tickCount).map(tick => ({
2066
- value: yScale(tick) + startOffset,
2067
- label: pipeTransform(tick, false),
2068
- rawY: tick,
2069
- }));
2070
- //Finding a domain for the secondary data such that it will result in round tick values when matched with the primary ticks
2071
- const secondaryTicksProto = yScaleSecondaryProto
2072
- .ticks(tickCount)
2073
- .map(tick => ({
2074
- y: yScaleSecondaryProto(tick),
2075
- rawY: tick,
2076
- label: pipeTransform(tick, true),
2077
- }));
2078
- const primaryMinTick = Math.min(...primaryTicks.map(tick => tick.rawY));
2079
- const primaryMaxTick = Math.max(...primaryTicks.map(tick => tick.rawY));
2080
- const primaryDomainMaxTickRatio = primaryMaxTick !== 0 ? effectivePrimaryMax / primaryMaxTick : 0;
2081
- const primaryDomainMinTickRatio = primaryMinTick !== 0 ? effectivePrimaryMin / primaryMinTick : 0;
2082
- const primaryGap = primaryTicks[1].rawY - primaryTicks[0].rawY;
2083
- const ticksBelowZero = primaryMinTick / primaryGap;
2084
- const ticksAboveZero = primaryMaxTick / primaryGap;
2085
- const secondaryGap = secondaryTicksProto[1].rawY - secondaryTicksProto[0].rawY;
2086
- let calcRangeMult = 1;
2087
- const secondaryDomainMinMult = ticksBelowZero * secondaryGap * primaryDomainMinTickRatio;
2088
- const secondaryDomainMaxMult = ticksAboveZero * secondaryGap * primaryDomainMaxTickRatio;
2089
- //First, we ensure the calcRangeMult is big enough
2090
- let sizeUpComplete = false;
2091
- while (!sizeUpComplete) {
2092
- const calcRangeTooSmallForMin = secondaryDomainMinMult * calcRangeMult > effectiveSecondaryMin &&
2093
- secondaryDomainMinMult !== 0;
2094
- const calcRangeTooSmallForMax = secondaryDomainMaxMult * calcRangeMult < effectiveSecondaryMax &&
2095
- secondaryDomainMaxMult !== 0;
2096
- if (calcRangeTooSmallForMin || calcRangeTooSmallForMax) {
2097
- calcRangeMult = calcRangeMult * 2;
2098
- }
2099
- else {
2100
- sizeUpComplete = true;
2101
- }
2102
- }
2103
- //Then, we check if we can scale down (for this one, both conditions have to be true, so it won't undo a previous scale up)
2104
- let sizeDownComplete = false;
2105
- while (!sizeDownComplete) {
2106
- const calcRangeTooBigForMin = secondaryDomainMinMult * calcRangeMult < effectiveSecondaryMin * 2 &&
2107
- secondaryDomainMinMult !== 0;
2108
- const calcRangeTooBigForMax = secondaryDomainMaxMult * calcRangeMult > effectiveSecondaryMax * 2 &&
2109
- secondaryDomainMaxMult !== 0;
2110
- if (calcRangeTooBigForMin && calcRangeTooBigForMax) {
2111
- calcRangeMult = calcRangeMult / 2;
2112
- }
2113
- else {
2114
- sizeDownComplete = true;
2115
- }
2116
- }
2117
- let secondaryDomainMin = secondaryDomainMinMult * calcRangeMult;
2118
- let secondaryDomainMax = secondaryDomainMaxMult * calcRangeMult;
2119
- //If the data is lopsided enough, it's possible that one of positive/negative have values, but no ticks
2120
- if (secondaryDomainMin === 0 && effectivePrimaryMin < 0) {
2121
- const posSecRatio = secondaryDomainMax / effectivePrimaryMax;
2122
- secondaryDomainMin = posSecRatio * effectivePrimaryMin;
2123
- }
2124
- if (secondaryDomainMax === 0 && effectivePrimaryMax > 0) {
2125
- const posSecRatio = secondaryDomainMin / effectivePrimaryMin;
2126
- secondaryDomainMax = posSecRatio * effectivePrimaryMax;
2127
- }
2128
- const yScaleSecondary = scaleLinear([secondaryDomainMin, secondaryDomainMax], scaleRange);
2129
- const ticks = primaryTicks.map(tick => ({
2130
- ...tick,
2131
- secondaryLabel: pipeTransform(yScaleSecondary.invert(yScale(tick.rawY)), true),
2132
- }));
2133
- const scale = (input, isSecondary) => {
2134
- if (isSecondary) {
2135
- return yScaleSecondary(input) + startOffset;
2136
- }
2137
- return yScale(input) + startOffset;
2138
- };
2139
- return {
2140
- scale,
2141
- ticks,
2142
- };
2143
- }
2144
- function calcDataScalingValues(data, config) {
2145
- const isStacked = isStackedData(config);
2146
- const primaryDomainValues = calcYScaleDomainValues(data, isStacked, false);
2147
- const secondaryDomainValues = calcYScaleDomainValues(data, isStacked, true);
2148
- const primaryDataMax = Math.max(...primaryDomainValues.map(val => val.max));
2149
- const secondaryDataMax = Math.max(...secondaryDomainValues.map(val => val.max));
2150
- const primaryDataMin = Math.min(...primaryDomainValues.map(val => val.min));
2151
- const secondaryDataMin = Math.min(...secondaryDomainValues.map(val => val.min));
2152
- let scaleDomainMultipleForMax = 1;
2153
- let scaleDomainMultipleForNeg = 1;
2154
- //Calculating how much we need to multiple the domain by to 'fit' both axes' data
2155
- if (isStacked) {
2156
- for (let i = 0; i < primaryDomainValues.length; i++) {
2157
- //Check positive max
2158
- const primaryVal = primaryDomainValues[i].max;
2159
- const secondaryVal = secondaryDomainValues[i].max;
2160
- const primaryRatio = primaryDataMax !== 0 ? primaryVal / primaryDataMax : 0;
2161
- const secondaryRatio = secondaryDataMax !== 0 ? secondaryVal / secondaryDataMax : 0;
2162
- const multVal = primaryRatio + secondaryRatio;
2163
- if (multVal > scaleDomainMultipleForMax) {
2164
- scaleDomainMultipleForMax = multVal;
2165
- }
2166
- //Check negative min
2167
- const primaryNegVal = primaryDomainValues[i].min < 0 ? primaryDomainValues[i].min : 0;
2168
- const secondaryNegVal = secondaryDomainValues[i].min < 0 ? secondaryDomainValues[i].min : 0;
2169
- const primaryNegRatio = primaryDataMin !== 0 ? primaryNegVal / primaryDataMin : 0;
2170
- const secondaryNegRatio = secondaryDataMin !== 0 ? secondaryNegVal / secondaryDataMin : 0;
2171
- const negMultVal = primaryNegRatio + secondaryNegRatio;
2172
- if (negMultVal > scaleDomainMultipleForNeg) {
2173
- scaleDomainMultipleForNeg = negMultVal;
2174
- }
2175
- }
2176
- }
2177
- return {
2178
- primaryDataMin,
2179
- primaryDataMax,
2180
- secondaryDataMin,
2181
- secondaryDataMax,
2182
- scaleDomainMultipleForMax,
2183
- scaleDomainMultipleForNeg,
2184
- };
2185
- }
2186
- function calcYScaleDomainValues(data, isStacked, forSecondary) {
2187
- if (data.type === 'flow-processed') {
2188
- if (forSecondary) {
2189
- //Flow charts don't support secondary data
2190
- return [{ min: 0, max: 0 }];
2191
- }
2192
- return [
2193
- {
2194
- min: 0,
2195
- max: Math.max(...data.x.map(x => x.totalCount)),
2196
- },
2197
- ];
2198
- }
2199
- const possiblyStackedYs = data.ys.map((y, yIndex) => {
2200
- //Handle stacking
2201
- return isStacked
2202
- ? y.values.map((val, xIndex) => {
2203
- let prevRunningTotal = 0;
2204
- for (let yI = 0; yI < yIndex; yI++) {
2205
- if (checkIfSecondary(data, yI, xIndex, false) !== forSecondary) {
2206
- continue;
2207
- }
2208
- const addVal = data.ys[yI].values[xIndex];
2209
- //Only stack values of the same sign
2210
- if (addVal < 0 === val < 0) {
2211
- prevRunningTotal += addVal;
2212
- }
2213
- }
2214
- return val + prevRunningTotal;
2215
- })
2216
- : y.values;
2217
- });
2218
- const suppYs = hasSupplementaryData(data) ? data.supplementaryYs : null;
2219
- let possiblyStackedSupYs = [];
2220
- if (suppYs) {
2221
- possiblyStackedSupYs = suppYs.map((y, yIndex) => {
2222
- //Handle stacking
2223
- return isStacked
2224
- ? y.values.map((val, xIndex) => {
2225
- let prevRunningTotal = 0;
2226
- for (let yI = 0; yI < yIndex; yI++) {
2227
- if (checkIfSecondary(data, yI, xIndex, true) !== forSecondary ||
2228
- suppYs[yI].supplementalIndex !== y.supplementalIndex) {
2229
- continue;
2230
- }
2231
- const addVal = suppYs[yI].values[xIndex];
2232
- //Only stack values of the same sign
2233
- if (addVal < 0 === val < 0) {
2234
- prevRunningTotal += addVal;
2235
- }
2236
- }
2237
- return val + prevRunningTotal;
2238
- })
2239
- : y.values;
2240
- });
2241
- }
2242
- const scaleRange = [];
2243
- for (let i = 0; i < data.x.length; i++) {
2244
- const maxNormY = Math.max(...possiblyStackedYs.map((y, yIndex) => {
2245
- if (checkIfSecondary(data, yIndex, i, false) !== forSecondary) {
2246
- return 0;
2247
- }
2248
- return y[i];
2249
- }));
2250
- const minNormY = Math.min(...possiblyStackedYs.map((y, yIndex) => {
2251
- if (checkIfSecondary(data, yIndex, i, false) !== forSecondary) {
2252
- return 0;
2253
- }
2254
- return y[i];
2255
- }));
2256
- const maxSupY = suppYs
2257
- ? Math.max(...possiblyStackedSupYs.map((y, yIndex) => {
2258
- if (checkIfSecondary(data, yIndex, i, true) !== forSecondary) {
2259
- return 0;
2260
- }
2261
- return y[i];
2262
- }))
2263
- : 0;
2264
- const minSupY = suppYs
2265
- ? Math.min(...possiblyStackedSupYs.map((y, yIndex) => {
2266
- if (checkIfSecondary(data, yIndex, i, true) !== forSecondary) {
2267
- return 0;
2268
- }
2269
- return y[i];
2270
- }))
2271
- : 0;
2272
- const max = maxNormY > 0 && maxNormY > maxSupY
2273
- ? maxNormY
2274
- : maxSupY > 0
2275
- ? maxSupY
2276
- : 0;
2277
- const min = minNormY < 0 && minNormY < minSupY
2278
- ? minNormY
2279
- : minSupY < 0
2280
- ? minSupY
2281
- : 0;
2282
- scaleRange.push({ max, min });
2283
- }
2284
- return scaleRange;
2285
- }
2286
- function calculateBarPosition(data, config, chartSizingValues, bucketNum, clusterNum) {
2287
- const offset = chartSizingValues.chartDataDirection === 'vertical'
2288
- ? chartSizingValues.totalLeftOffset
2289
- : chartSizingValues.totalTopOffset;
2290
- const clusterOffset = clusterNum *
2291
- (chartSizingValues.barSize + chartSizingValues.barClusterGap);
2292
- const cumulativeBucketGap = getTotalPreBucketGap(data, config, chartSizingValues, bucketNum);
2293
- return offset + cumulativeBucketGap + clusterOffset;
2294
- }
2295
- function calculateHorizontalBarPath(leftSideRound, rightSideRound, xValue, yValue, horR, verR, height, width) {
2296
- if (leftSideRound && rightSideRound) {
2297
- //Both-sides rounding variation
2298
- const pathD = `
2299
- M ${xValue + horR},${yValue}
2300
- h ${width - horR * 2}
2301
- q${horR},0 ${horR},${verR}
2302
- v ${height - verR * 2}
2303
- q0,${verR} -${horR},${verR}
2304
- h ${-(width - horR * 2)}
2305
- q-${horR},0 -${horR},-${verR}
2306
- v -${height - verR * 2}
2307
- q0,-${verR} ${horR},-${verR}
2308
- Z
2309
- `;
2310
- return pathD;
2311
- }
2312
- if (leftSideRound) {
2313
- //Left-side rounding variation
2314
- const pathD = `
2315
- M ${xValue + horR},${yValue}
2316
- h ${width - horR}
2317
- v ${height}
2318
- h ${-(width - horR)}
2319
- q-${horR},0 -${horR},-${verR}
2320
- v -${height - verR * 2}
2321
- q0,-${verR} ${horR},-${verR}
2322
- Z
2323
- `;
2324
- return pathD;
2325
- }
2326
- if (rightSideRound) {
2327
- //Right-side rounding variation
2328
- const pathD = `
2329
- M ${xValue},${yValue}
2330
- h ${width - horR}
2331
- q${horR},0 ${horR},${verR}
2332
- v ${height - verR * 2}
2333
- q0,${verR} -${horR},${verR}
2334
- h ${-(width - horR)}
2335
- Z
2336
- `;
2337
- return pathD;
2338
- }
2339
- //No-rounding variation
2340
- const pathD = `
2341
- M ${xValue},${yValue}
2342
- h ${width}
2343
- v ${height}
2344
- h ${-width}
2345
- v -${height}
2346
- Z
2347
- `;
2348
- return pathD;
2349
- }
2350
- function getBucketAndClusterNumForHover(pos, chartSizingValues, data, config, bucketCount) {
2351
- let bucketLeeway = chartSizingValues.bucketGap / 4;
2352
- //if there's only 1 data point, use the outerGap as leeway instead
2353
- if (data.x.length === 1) {
2354
- bucketLeeway = chartSizingValues.outerGap / 4;
2355
- }
2356
- const barLeeway = chartSizingValues.barClusterGap / 2;
2357
- const offset = chartSizingValues.chartDataDirection === 'vertical'
2358
- ? chartSizingValues.totalLeftOffset
2359
- : chartSizingValues.totalTopOffset;
2360
- const relativePos = pos - offset;
2361
- let bucketNum = -1;
2362
- for (let i = 0; i < bucketCount; i++) {
2363
- const bucketStartPos = getTotalPreBucketGap(data, config, chartSizingValues, i);
2364
- if (bucketStartPos - bucketLeeway < relativePos &&
2365
- bucketStartPos +
2366
- getBucketSize(data, config, chartSizingValues) +
2367
- bucketLeeway >
2368
- relativePos) {
2369
- bucketNum = i;
2370
- break;
2371
- }
2372
- }
2373
- if (bucketNum === -1) {
2374
- return null;
2375
- }
2376
- if (!isClusteredData(data, config, true)) {
2377
- return {
2378
- bucketNum,
2379
- clusterNum: 0,
2380
- clusterNormCount: 1,
2381
- clusterNumType: 'norm',
2382
- };
2383
- }
2384
- const relativeBucketPos = relativePos -
2385
- getTotalPreBucketGap(data, config, chartSizingValues, bucketNum);
2386
- const clusterCount = getClusterInfoForBucket(data, config);
2387
- let clusterNum = -1;
2388
- for (let i = 0; i < clusterCount.total; i++) {
2389
- const barStartPos = (chartSizingValues.barSize + chartSizingValues.barClusterGap) * i;
2390
- if (barStartPos - barLeeway < relativeBucketPos &&
2391
- barStartPos + chartSizingValues.barSize + barLeeway > relativeBucketPos) {
2392
- clusterNum = i;
2393
- break;
2394
- }
2395
- }
2396
- if (clusterNum === -1) {
2397
- return null;
2398
- }
2399
- let clusterNumType = 'norm';
2400
- if (clusterNum >= clusterCount.normCount) {
2401
- clusterNumType = 'supp';
2402
- }
2403
- return {
2404
- bucketNum,
2405
- clusterNum,
2406
- clusterNormCount: clusterCount.normCount,
2407
- clusterNumType,
2408
- };
2409
- }
2410
- function findNearestIndexWithSecondary(yInfo, yPos, scale) {
2411
- let foundIndex = 0;
2412
- let currMinDistance = Math.abs(scale(yInfo[0].value, yInfo[0].isSecondary) - yPos);
2413
- for (let i = 1; i < yInfo.length; i++) {
2414
- const newDistance = Math.abs(scale(yInfo[i].value, yInfo[i].isSecondary) - yPos);
2415
- if (newDistance < currMinDistance) {
2416
- foundIndex = i;
2417
- currMinDistance = newDistance;
2418
- }
2419
- }
2420
- return foundIndex;
2421
- }
2422
- function getBarYInfo(data, config, yIndex, xIndex, scale, isSupplementary = false) {
2423
- const isStacked = isStackedData(config);
2424
- const minimumSize = getMinimumDataElementSize(config);
2425
- const zeroVal = scale(0, true);
2426
- const yData = getMainOrSuppY(data, yIndex, isSupplementary);
2427
- const scaleValue = scale(yData.values[xIndex], checkIfSecondary(data, yIndex, xIndex, isSupplementary));
2428
- if (scaleValue > zeroVal) {
2429
- let prevBarHeights = 0;
2430
- if (isStacked) {
2431
- for (let i = 0; i < yIndex; i++) {
2432
- const checkData = getMainOrSuppY(data, i, isSupplementary);
2433
- //Both yData and checkData are definitely SupplementaryDataYs if isSupplementary is true, but they don't realize it
2434
- if (isSupplementary &&
2435
- 'supplementalIndex' in yData &&
2436
- 'supplementalIndex' in checkData) {
2437
- if (yData.supplementalIndex !== checkData.supplementalIndex) {
2438
- continue;
2439
- }
2440
- }
2441
- const checkValue = scale(checkData.values[xIndex], checkIfSecondary(data, i, xIndex, isSupplementary));
2442
- //Skip positive values
2443
- if (checkValue < zeroVal) {
2444
- continue;
2445
- }
2446
- prevBarHeights += applyMinimumDataElementSize(checkValue - zeroVal, checkData.values[xIndex], minimumSize);
2447
- }
2448
- }
2449
- const yValue = zeroVal + prevBarHeights;
2450
- const height = applyMinimumDataElementSize(scaleValue - zeroVal, yData.values[xIndex], minimumSize);
2451
- return { yValue, height };
2452
- }
2453
- let prevBarHeights = 0;
2454
- if (isStacked) {
2455
- for (let i = 0; i < yIndex; i++) {
2456
- const checkData = getMainOrSuppY(data, i, isSupplementary);
2457
- //Both yData and checkData are definitely SupplementaryDataYs if isSupplementary is true, but they don't realize it
2458
- if (isSupplementary &&
2459
- 'supplementalIndex' in yData &&
2460
- 'supplementalIndex' in checkData) {
2461
- if (yData.supplementalIndex !== checkData.supplementalIndex) {
2462
- continue;
2463
- }
2464
- }
2465
- const checkValue = scale(checkData.values[xIndex], checkIfSecondary(data, i, xIndex, isSupplementary));
2466
- //Skip negative values
2467
- if (checkValue > zeroVal) {
2468
- continue;
2469
- }
2470
- prevBarHeights += applyMinimumDataElementSize(zeroVal - checkValue, checkData.values[xIndex], minimumSize);
2471
- }
2472
- }
2473
- const height = applyMinimumDataElementSize(zeroVal - scaleValue, yData.values[xIndex], minimumSize);
2474
- const yValue = zeroVal - height - prevBarHeights;
2475
- return { yValue, height };
2476
- }
2477
- function getSuppBarYInfoViaYIndex(data, config, yIndex, suppIndex, xIndex, scale) {
2478
- if (!hasSupplementaryData(data)) {
2479
- return { yValue: 0, height: 0 };
2480
- }
2481
- const suppYs = data.supplementaryYs;
2482
- // Find supplementary bars with the given supplementalIndex
2483
- const groupSupps = suppYs.filter(s => s.supplementalIndex === suppIndex);
2484
- // yIndex refers to which Y series (within the supplemental group) we're looking at
2485
- if (yIndex >= 0 && yIndex < groupSupps.length) {
2486
- // Find this supp in the original array
2487
- const suppInOriginalArray = suppYs.indexOf(groupSupps[yIndex]);
2488
- return getBarYInfo(data, config, suppInOriginalArray, xIndex, scale, true);
2489
- }
2490
- return { yValue: 0, height: 0 };
2491
- }
2492
- function getMainOrSuppY(data, yIndex, isSupplementary) {
2493
- if (hasSupplementaryData(data) && isSupplementary) {
2494
- return data.supplementaryYs[yIndex];
2495
- }
2496
- return data.ys[yIndex];
2497
- }
2498
- function getBarXInfo(data, config, yIndex, xIndex, scale, isSupplementary = false) {
2499
- const isStacked = isStackedData(config);
2500
- const minimumSize = getMinimumDataElementSize(config);
2501
- const zeroVal = scale(0, true);
2502
- const yData = getMainOrSuppY(data, yIndex, isSupplementary);
2503
- const scaleValue = scale(yData.values[xIndex], checkIfSecondary(data, yIndex, xIndex, isSupplementary));
2504
- if (scaleValue < zeroVal) {
2505
- let prevBarWidths = 0;
2506
- if (isStacked) {
2507
- for (let i = 0; i < yIndex; i++) {
2508
- const checkData = getMainOrSuppY(data, i, isSupplementary);
2509
- //Both yData and checkData are definitely SupplementaryDataYs if isSupplementary is true, but they don't realize it
2510
- if (isSupplementary &&
2511
- 'supplementalIndex' in yData &&
2512
- 'supplementalIndex' in checkData) {
2513
- if (yData.supplementalIndex !== checkData.supplementalIndex) {
2514
- continue;
2515
- }
2516
- }
2517
- const checkVal = scale(checkData.values[xIndex], checkIfSecondary(data, i, xIndex, isSupplementary));
2518
- //Skip positive values
2519
- if (checkVal > zeroVal) {
2520
- continue;
2521
- }
2522
- prevBarWidths += applyMinimumDataElementSize(zeroVal - checkVal, checkData.values[xIndex], minimumSize);
2523
- }
2524
- }
2525
- const width = applyMinimumDataElementSize(zeroVal - scaleValue, yData.values[xIndex], minimumSize);
2526
- const xValue = zeroVal - width - prevBarWidths;
2527
- return { xValue, width };
2528
- }
2529
- let prevBarWidths = 0;
2530
- if (isStacked) {
2531
- for (let i = 0; i < yIndex; i++) {
2532
- const checkData = getMainOrSuppY(data, i, isSupplementary);
2533
- //Both yData and checkData are definitely SupplementaryDataYs if isSupplementary is true, but they don't realize it
2534
- if (isSupplementary &&
2535
- 'supplementalIndex' in yData &&
2536
- 'supplementalIndex' in checkData) {
2537
- if (yData.supplementalIndex !== checkData.supplementalIndex) {
2538
- continue;
2539
- }
2540
- }
2541
- const checkVal = scale(checkData.values[xIndex], checkIfSecondary(data, i, xIndex, isSupplementary));
2542
- //Skip negative values
2543
- if (checkVal < zeroVal) {
2544
- continue;
2545
- }
2546
- prevBarWidths += applyMinimumDataElementSize(checkVal - zeroVal, checkData.values[xIndex], minimumSize);
2547
- }
2548
- }
2549
- const xValue = prevBarWidths + zeroVal;
2550
- const width = applyMinimumDataElementSize(scaleValue - zeroVal, yData.values[xIndex], minimumSize);
2551
- return { xValue, width };
2552
- }
2553
- function checkIfSecondary(data, yIndex, xIndex, isSupplementary = false) {
2554
- if (data.type === 'labeled') {
2555
- if (data.x[xIndex].isSecondary === true) {
2556
- return true;
2557
- }
2558
- }
2559
- return getMainOrSuppY(data, yIndex, isSupplementary).isSecondary === true;
2560
- }
2561
- function warnUnsupportedPatterns(data, supportedPatterns, chartType) {
2562
- const allYs = [
2563
- ...data.ys,
2564
- ...(hasSupplementaryData(data) ? data.supplementaryYs : []),
2565
- ];
2566
- for (const y of allYs) {
2567
- if (y.pattern &&
2568
- y.pattern !== 'solid' &&
2569
- !supportedPatterns.includes(y.pattern)) {
2570
- // eslint-disable-next-line no-console
2571
- console.warn(`Heads up! The '${y.pattern}' pattern isn't supported for ${chartType} charts. Falling back to solid.`);
2572
- }
2573
- }
2574
- }
2575
- function warnFlowData(data, chartType) {
2576
- if (data.type === 'flow') {
2577
- // eslint-disable-next-line no-console
2578
- console.warn(`Heads up! The 'flow' data type isn't supported for ${chartType} charts.`);
2579
- return false;
2580
- }
2581
- return true;
2582
- }
2583
- // hide strips out hidden y values while retaining the original indices
2584
- // for the remaining visible values
2585
- function hide(data) {
2586
- const visibleIndices = data.ys
2587
- .map((y, i) => ({ y, i }))
2588
- .filter(({ y }) => !y.hidden)
2589
- .map(({ i }) => i);
2590
- const visibleSuppIndices = hasSupplementaryData(data)
2591
- ? data.supplementaryYs
2592
- .map((y, i) => ({ y, i }))
2593
- .filter(({ y }) => !y.hidden)
2594
- .map(({ i }) => i)
2595
- : [];
2596
- return {
2597
- data: {
2598
- ...data,
2599
- ys: visibleIndices.map(i => data.ys[i]),
2600
- supplementaryYs: visibleSuppIndices.map(i => data.supplementaryYs[i]),
2601
- },
2602
- visibleIndices,
2603
- visibleSuppIndices,
2604
- };
2605
- }
2606
- function waterfallTransform(data, isWaterfall) {
2607
- const waterfallMap = new Map();
2608
- if (data.type === 'timeseries' || !isWaterfall) {
2609
- return {
2610
- data: {
2611
- type: 'labeled',
2612
- x: [],
2613
- ys: [],
2614
- },
2615
- map: waterfallMap,
2616
- };
2617
- }
2618
- const newData = {
2619
- ...data,
2620
- x: [...data.x, { label: 'Total' }],
2621
- ys: [
2622
- ...data.ys.map(y => {
2623
- const newY = {
2624
- ...y,
2625
- values: [...y.values, y.values.reduce((a, b) => a + b, 0)],
2626
- };
2627
- waterfallMap.set(newY, y);
2628
- return newY;
2629
- }),
2630
- ],
2631
- };
2632
- return {
2633
- data: newData,
2634
- map: waterfallMap,
2635
- };
2636
- }
2637
- function flowsTransform(config, data) {
2638
- const returnBuckets = [];
2639
- const maxPathLength = Math.max(...data.ys.map(y => y.steps.length));
2640
- if (maxPathLength > 0 && maxPathLength < Infinity) {
2641
- for (let i = 0; i < maxPathLength; i++) {
2642
- const flowBucket = {
2643
- totalCount: 0,
2644
- subBuckets: [],
2645
- };
2646
- for (const y of data.ys) {
2647
- if (y.values.length > i && y.steps.length > i) {
2648
- const subBucketId = y.steps[i];
2649
- const foundSubBucket = flowBucket.subBuckets.find(subBucket => subBucket.id === subBucketId);
2650
- let subBucket;
2651
- if (foundSubBucket !== undefined) {
2652
- subBucket = foundSubBucket;
2653
- subBucket.count += y.values[i];
2654
- }
2655
- else {
2656
- subBucket = {
2657
- id: subBucketId,
2658
- count: y.values[i],
2659
- connections: [],
2660
- };
2661
- flowBucket.subBuckets.push(subBucket);
2662
- }
2663
- flowBucket.totalCount += y.values[i];
2664
- //Fill in backwards connections
2665
- if (i > 0) {
2666
- const foundConnection = subBucket.connections.find(connection => connection.start === y.steps[i - 1] &&
2667
- connection.end === subBucketId &&
2668
- connection.direction === 'backward');
2669
- if (foundConnection !== undefined) {
2670
- foundConnection.count += y.values[i];
2671
- }
2672
- else {
2673
- const newConnection = {
2674
- direction: 'backward',
2675
- start: y.steps[i - 1],
2676
- end: subBucketId,
2677
- count: y.values[i],
2678
- };
2679
- subBucket.connections.push(newConnection);
2680
- }
2681
- }
2682
- //Fill in forwards connections
2683
- if (i < y.steps.length - 1 && i < y.values.length - 1) {
2684
- const foundConnection = subBucket.connections.find(connection => connection.start === subBucketId &&
2685
- connection.end === y.steps[i + 1] &&
2686
- connection.direction === 'forward');
2687
- if (foundConnection !== undefined) {
2688
- foundConnection.count += y.values[i + 1];
2689
- }
2690
- else {
2691
- const newConnection = {
2692
- direction: 'forward',
2693
- start: subBucketId,
2694
- end: y.steps[i + 1],
2695
- count: y.values[i + 1],
2696
- };
2697
- subBucket.connections.push(newConnection);
2698
- }
2699
- }
2700
- }
2701
- }
2702
- returnBuckets.push(flowBucket);
2703
- }
2704
- }
2705
- const subBucketOrderingMap = new Map();
2706
- for (let i = 0; i < config.flowConfig.subBucketsConfig.length; i++) {
2707
- subBucketOrderingMap.set(config.flowConfig.subBucketsConfig[i].bucketId, i);
2708
- }
2709
- const mapGet = (id) => {
2710
- const foundResult = subBucketOrderingMap.get(id);
2711
- if (foundResult !== undefined) {
2712
- return foundResult;
2713
- }
2714
- //If something isn't defined in the config, put it at the end
2715
- return Infinity;
2716
- };
2717
- //Ensure the data is sorted the same the way the config is, and drop empty
2718
- //bars/connections so they're neither displayed nor factored into sizing
2719
- return {
2720
- type: 'flow-processed',
2721
- x: returnBuckets.map(bucket => ({
2722
- ...bucket,
2723
- subBuckets: bucket.subBuckets
2724
- .filter(subBucket => subBucket.count !== 0)
2725
- .sort((a, b) => mapGet(a.id) - mapGet(b.id))
2726
- .map(subBucket => ({
2727
- ...subBucket,
2728
- connections: subBucket.connections
2729
- .filter(connection => connection.count !== 0)
2730
- .sort((a, b) => {
2731
- const firstSort = mapGet(a.start) - mapGet(b.start);
2732
- if (firstSort !== 0) {
2733
- return firstSort;
2734
- }
2735
- return mapGet(a.end) - mapGet(b.end);
2736
- }),
2737
- })),
2738
- })),
2739
- };
2740
- }
2741
- function getPipes(valueType) {
2742
- switch (valueType) {
2743
- case 'count': {
2744
- return { pipe: new SmallNumberPipe(), fullPipe: new NumberPipe() };
2745
- }
2746
- case 'currency':
2747
- return {
2748
- pipe: new SmallCurrencyPipe(),
2749
- fullPipe: new CurrencyPipe('en-us'),
2750
- };
2751
- case 'percentage': {
2752
- const pipe = new PercentagePipe();
2753
- return { pipe, fullPipe: pipe };
2754
- }
2755
- case 'days': {
2756
- const pipe = new DaysPipe();
2757
- return { pipe, fullPipe: pipe };
2758
- }
2759
- }
2760
- }
2761
- Chart.getPipes = getPipes;
2762
- const intervals = ['year', 'quarter', 'month', 'week', 'day'];
2763
- function formatedDate(dateFormat, date) {
2764
- if (dateFormat === 'quarter') {
2765
- const quarter = Math.ceil((date.getUTCMonth() + 1) / 3);
2766
- const year = utcFormat(getTimeIntervalFormat('year'))(date);
2767
- return `Q${quarter} ${year}`;
2768
- }
2769
- const format = getTimeIntervalFormat(dateFormat);
2770
- return utcFormat(format)(date);
2771
- }
2772
- Chart.formatedDate = formatedDate;
2773
- function getTimeIntervalFormat(interval) {
2774
- switch (interval) {
2775
- case 'day':
2776
- case 'week':
2777
- return '%m/%d/%Y';
2778
- case 'month':
2779
- case 'quarter':
2780
- return '%b %Y';
2781
- case 'year':
2782
- return '%Y';
2783
- }
2784
- }
2785
- function convertChartDataToDonutData(chartData) {
2786
- if (chartData.ys.find(y => y.values.length > 1)) {
2787
- // eslint-disable-next-line no-console
2788
- console.warn("Heads up! Pie charts don't support multiple values per series");
2789
- }
2790
- const donutData = chartData.ys.map(y => ({
2791
- label: y.label,
2792
- hidden: y.hidden,
2793
- value: y.values.length >= 1 ? y.values[0] : 0,
2794
- isSecondary: y.isSecondary,
2795
- }));
2796
- return donutData;
2797
- }
2798
- Chart.convertChartDataToDonutData = convertChartDataToDonutData;
2799
- function arcToPoint(angle, radius) {
2800
- return {
2801
- x: radius * Math.cos(angle - Math.PI / 2),
2802
- y: radius * Math.sin(angle - Math.PI / 2),
2803
- };
2804
- }
2805
- function pointToArc(x, y) {
2806
- const radius = Math.hypot(x, y);
2807
- let angle = Math.atan2(y, x) + Math.PI / 2;
2808
- //Normalize to be within range [0, 2π]
2809
- angle = (angle + 2 * Math.PI) % (2 * Math.PI);
2810
- return {
2811
- angle,
2812
- radius,
2813
- };
2814
- }
2815
- function getFullChartScaleValues(config, data, dimensions, pipeTransform, dateFormat) {
2816
- const chartDataDirection = getChartDataDirection(config);
2817
- const defaultScalingConfig = getDefaultScalingConfigByChartType(config.type, config.secondaryValueType !== undefined);
2818
- const scalingConfig = combineScalingInfo(config, defaultScalingConfig);
2819
- const nonDataAxisValues = calculateNonDataAxisValues(config, scalingConfig, config.scalingConfig?.elementScales, defaultScalingConfig.elementScales, dimensions, data);
2820
- const dataAxisValues = calculateDataAxisValues(config, scalingConfig, config.scalingConfig?.elementScales, defaultScalingConfig.elementScales, dimensions, data, pipeTransform, dateFormat);
2821
- if (nonDataAxisValues.sizingError === true ||
2822
- dataAxisValues.sizingError === true) {
2823
- return null;
2824
- }
2825
- const dataLabelStartPadding = getDataLabelSizingCount(data, config).start *
2826
- (dataAxisValues.dataLabelPadding + dataAxisValues.dataLabelTextSize);
2827
- const dataLabelEndPadding = getDataLabelSizingCount(data, config).end *
2828
- (dataAxisValues.dataLabelPadding + dataAxisValues.dataLabelTextSize);
2829
- return {
2830
- ...nonDataAxisValues,
2831
- ...dataAxisValues,
2832
- leftPadding: chartDataDirection === 'horizontal'
2833
- ? dataAxisValues.startPadding
2834
- : nonDataAxisValues.startPadding,
2835
- rightPadding: chartDataDirection === 'horizontal'
2836
- ? dataAxisValues.endPadding
2837
- : nonDataAxisValues.endPadding,
2838
- topPadding: chartDataDirection === 'horizontal'
2839
- ? nonDataAxisValues.startPadding
2840
- : dataAxisValues.startPadding,
2841
- bottomPadding: chartDataDirection === 'horizontal'
2842
- ? nonDataAxisValues.endPadding
2843
- : dataAxisValues.endPadding,
2844
- totalLeftOffset: chartDataDirection === 'horizontal'
2845
- ? dataAxisValues.startPadding +
2846
- dataAxisValues.leftBucketLabel +
2847
- dataLabelStartPadding
2848
- : nonDataAxisValues.startPadding + nonDataAxisValues.outerGap,
2849
- totalRightOffset: chartDataDirection === 'horizontal'
2850
- ? dataAxisValues.startPadding + dataLabelEndPadding
2851
- : nonDataAxisValues.endPadding + nonDataAxisValues.outerGap,
2852
- totalTopOffset: chartDataDirection === 'horizontal'
2853
- ? nonDataAxisValues.startPadding + nonDataAxisValues.outerGap
2854
- : dataAxisValues.startPadding + dataLabelStartPadding,
2855
- totalBottomOffset: chartDataDirection === 'horizontal'
2856
- ? nonDataAxisValues.endPadding + nonDataAxisValues.outerGap
2857
- : dataAxisValues.endPadding + dataLabelEndPadding,
2858
- targetTickCount: scalingConfig.targetTickCount,
2859
- sizeForData: dataAxisValues.sizeForData,
2860
- totalWidth: chartDataDirection === 'horizontal'
2861
- ? dataAxisValues.totalSize
2862
- : nonDataAxisValues.totalSize,
2863
- totalHeight: chartDataDirection === 'horizontal'
2864
- ? nonDataAxisValues.totalSize
2865
- : dataAxisValues.totalSize,
2866
- dataLabelTextSize: config.showDataLabels
2867
- ? dataAxisValues.dataLabelTextSize
2868
- : 0,
2869
- horizontalAxisLabelTextSize: chartDataDirection === 'vertical'
2870
- ? dataAxisValues.bucketLabelTextSize
2871
- : dataAxisValues.dataLabelTextSize,
2872
- verticalAxisLabelTextSize: dataAxisValues.fontSize,
2873
- chartDataDirection,
2874
- horizontalContainerScale: scalingConfig.horizontalContainerScale,
2875
- verticalContainerScale: scalingConfig.verticalContainerScale,
2876
- };
2877
- }
2878
- function calculateNonDataAxisValues(config, scalingConfig, elementScales, defaultSizing, dimensions, data) {
2879
- const chartDataDirection = getChartDataDirection(config);
2880
- const boundingDimension = chartDataDirection === 'horizontal'
2881
- ? dimensions.height
2882
- : dimensions.width;
2883
- const axisScale = chartDataDirection === 'horizontal'
2884
- ? scalingConfig?.verticalAxisScale
2885
- : scalingConfig?.horizontalAxisScale;
2886
- const barSizeConfig = getElementScalingInfo(elementScales, defaultSizing, 'barSize');
2887
- const barClusterGapConfig = getElementScalingInfo(elementScales, defaultSizing, 'barClusterGap');
2888
- const bucketGapConfig = getElementScalingInfo(elementScales, defaultSizing, 'bucketGap');
2889
- const outerGapConfig = getElementScalingInfo(elementScales, defaultSizing, 'outerGap');
2890
- const startPaddingConfig = getElementScalingInfo(elementScales, defaultSizing, chartDataDirection === 'horizontal' ? 'topPadding' : 'leftPadding');
2891
- const endPaddingConfig = getElementScalingInfo(elementScales, defaultSizing, chartDataDirection === 'horizontal' ? 'bottomPadding' : 'rightPadding');
2892
- const bucketCount = data.x.length;
2893
- let barCount = 0;
2894
- let barClusterGapCount = 0;
2895
- for (let i = 0; i < bucketCount; i++) {
2896
- if (data.type === 'flow-processed') {
2897
- barCount += 1;
2898
- }
2899
- else {
2900
- const bucketClusterCount = getClusterInfoForBucket(data, config);
2901
- barCount += bucketClusterCount.total;
2902
- barClusterGapCount += bucketClusterCount.total - 1;
2903
- }
2904
- }
2905
- const bucketGapCount = bucketCount - 1;
2906
- const barTotalSize = determinePossibleSizesOfElement(barSizeConfig, barCount);
2907
- const clusterGapTotalSize = determinePossibleSizesOfElement(barClusterGapConfig, barClusterGapCount);
2908
- const bucketGapTotalSize = determinePossibleSizesOfElement(bucketGapConfig, bucketGapCount);
2909
- const outerGapTotalSize = determinePossibleSizesOfElement(outerGapConfig, 2);
2910
- const startPaddingTotalSize = determinePossibleSizesOfElement(startPaddingConfig, 1);
2911
- const endPaddingTotalSize = determinePossibleSizesOfElement(endPaddingConfig, 1);
2912
- const calcTargetSize = barTotalSize.target +
2913
- clusterGapTotalSize.target +
2914
- bucketGapTotalSize.target +
2915
- outerGapTotalSize.target +
2916
- startPaddingTotalSize.target +
2917
- endPaddingTotalSize.target;
2918
- if (axisScale === 'no-scale' ||
2919
- calcTargetSize === boundingDimension ||
2920
- (axisScale === 'grow' && calcTargetSize > boundingDimension) ||
2921
- (axisScale === 'shrink' && calcTargetSize < boundingDimension)) {
2922
- //No element scaling necessary, return everything as it's target value
2923
- return {
2924
- barSize: barSizeConfig.target,
2925
- barClusterGap: barClusterGapConfig.target,
2926
- bucketGap: bucketGapConfig.target,
2927
- outerGap: outerGapConfig.target,
2928
- startPadding: startPaddingConfig.target,
2929
- endPadding: endPaddingConfig.target,
2930
- totalSize: calcTargetSize,
2931
- };
2932
- }
2933
- const calcMinSize = barTotalSize.min +
2934
- clusterGapTotalSize.min +
2935
- bucketGapTotalSize.min +
2936
- outerGapTotalSize.min +
2937
- startPaddingTotalSize.min +
2938
- endPaddingTotalSize.min;
2939
- //Note: This is only actually a max size if all elements have a defined max
2940
- const calcMaxSize = barTotalSize.max +
2941
- clusterGapTotalSize.max +
2942
- bucketGapTotalSize.max +
2943
- outerGapTotalSize.max +
2944
- startPaddingTotalSize.max +
2945
- endPaddingTotalSize.max;
2946
- if (calcMinSize > boundingDimension) {
2947
- // eslint-disable-next-line no-console
2948
- console.warn('The provided minimum element sizes mean the chart cannot display at this small of a size');
2949
- return {
2950
- barSize: 0,
2951
- barClusterGap: 0,
2952
- bucketGap: 0,
2953
- outerGap: 0,
2954
- startPadding: 0,
2955
- endPadding: 0,
2956
- totalSize: 0,
2957
- sizingError: true,
2958
- };
2959
- }
2960
- const configChecks = [
2961
- getCheckingInfoForElementConfig(barSizeConfig, barCount),
2962
- getCheckingInfoForElementConfig(barClusterGapConfig, barClusterGapCount),
2963
- getCheckingInfoForElementConfig(bucketGapConfig, bucketGapCount),
2964
- getCheckingInfoForElementConfig(outerGapConfig, 2),
2965
- getCheckingInfoForElementConfig(startPaddingConfig, 1),
2966
- getCheckingInfoForElementConfig(endPaddingConfig, 1),
2967
- ];
2968
- let currScalingFactor = 1;
2969
- if (calcTargetSize > boundingDimension) {
2970
- //Scaling down
2971
- let finalScalingFactorFound = false;
2972
- while (!finalScalingFactorFound) {
2973
- const nextScaleFactorBreakpoint = Math.max(...configChecks
2974
- .map(check => check.minScaleFactor)
2975
- .filter((val) => val !== undefined && !(val >= currScalingFactor)), 0);
2976
- const newScaleFactorSize = getSumForScaleValue(configChecks, nextScaleFactorBreakpoint);
2977
- if (newScaleFactorSize <= boundingDimension) {
2978
- //There's a scale value that'll work between the curr and new values
2979
- //These are the values that'll just be at their min
2980
- const nonScaleableValues = configChecks.filter(check => check.minScaleFactor && check.minScaleFactor >= currScalingFactor);
2981
- //These are the values that can still be scaled down
2982
- const scaleableValues = configChecks.filter(check => !check.minScaleFactor || check.minScaleFactor < currScalingFactor);
2983
- const workingSpace = boundingDimension -
2984
- getSumForScaleValue(nonScaleableValues, currScalingFactor);
2985
- currScalingFactor =
2986
- workingSpace / getSumForScaleValue(scaleableValues, 1);
2987
- finalScalingFactorFound = true;
2988
- }
2989
- else {
2990
- //One of the elements is hitting their minScaleFactor, so for simplicity we'll just go again
2991
- currScalingFactor = nextScaleFactorBreakpoint;
2992
- //Just in case, though previous checks should make this impossible
2993
- if (currScalingFactor === 0) {
2994
- // eslint-disable-next-line no-console
2995
- console.warn('The given size cannot contain the fixed sizes given for the elements');
2996
- return {
2997
- barSize: 0,
2998
- barClusterGap: 0,
2999
- bucketGap: 0,
3000
- outerGap: 0,
3001
- startPadding: 0,
3002
- endPadding: 0,
3003
- totalSize: 0,
3004
- sizingError: true,
3005
- };
3006
- }
3007
- }
3008
- }
3009
- }
3010
- else {
3011
- //Checking to see if all elements have a defined max
3012
- const maximumSizePossible = configChecks.filter(check => check.maxScaleFactor === undefined)
3013
- .length === 0;
3014
- //If all elements have a defined max, and that max is less than the size we're trying to grow to, it's impossible
3015
- if (maximumSizePossible && calcMaxSize < boundingDimension) {
3016
- // eslint-disable-next-line no-console
3017
- console.warn('The provided maximum element widths mean the chart cannot display at this large of a size');
3018
- return {
3019
- barSize: 0,
3020
- barClusterGap: 0,
3021
- bucketGap: 0,
3022
- outerGap: 0,
3023
- startPadding: 0,
3024
- endPadding: 0,
3025
- totalSize: 0,
3026
- sizingError: true,
3027
- };
3028
- }
3029
- //Scaling up
3030
- let finalScalingFactorFound = false;
3031
- while (!finalScalingFactorFound) {
3032
- const nextScaleFactorBreakpoint = Math.min(...configChecks
3033
- .map(check => check.maxScaleFactor)
3034
- .filter((val) => val !== undefined && !(val <= currScalingFactor)));
3035
- const newScaleFactorSize = getSumForScaleValue(configChecks, nextScaleFactorBreakpoint);
3036
- if (newScaleFactorSize >= boundingDimension ||
3037
- nextScaleFactorBreakpoint === Infinity) {
3038
- //There's a scale value that'll work between the curr and new values
3039
- //These are the values that'll just be at their max
3040
- const nonScaleableValues = configChecks.filter(check => check.maxScaleFactor && check.maxScaleFactor <= currScalingFactor);
3041
- //These are the values that can still be scaled up
3042
- const scaleableValues = configChecks.filter(check => !check.maxScaleFactor || check.maxScaleFactor > currScalingFactor);
3043
- const workingSpace = boundingDimension -
3044
- getSumForScaleValue(nonScaleableValues, currScalingFactor);
3045
- currScalingFactor =
3046
- workingSpace / getSumForScaleValue(scaleableValues, 1);
3047
- finalScalingFactorFound = true;
3048
- }
3049
- else {
3050
- //One of the elements is hitting their maxScaleFactor, so for simplicity we'll just go again
3051
- currScalingFactor = nextScaleFactorBreakpoint;
3052
- }
3053
- }
3054
- }
3055
- const barSize = getScaledElementSize(barSizeConfig, currScalingFactor);
3056
- const barClusterGap = getScaledElementSize(barClusterGapConfig, currScalingFactor);
3057
- const bucketGap = getScaledElementSize(bucketGapConfig, currScalingFactor);
3058
- return {
3059
- barSize,
3060
- barClusterGap,
3061
- bucketGap,
3062
- outerGap: getScaledElementSize(outerGapConfig, currScalingFactor),
3063
- startPadding: getScaledElementSize(startPaddingConfig, currScalingFactor),
3064
- endPadding: getScaledElementSize(endPaddingConfig, currScalingFactor),
3065
- totalSize: boundingDimension,
3066
- };
3067
- }
3068
- function calculateDataAxisValues(config, scalingConfig, elementScales, defaultSizing, dimensions, data, pipeTransform, dateFormat) {
3069
- const chartDataDirection = getChartDataDirection(config);
3070
- const boundingDimension = chartDataDirection === 'horizontal'
3071
- ? dimensions.width
3072
- : dimensions.height;
3073
- const axisScale = chartDataDirection === 'horizontal'
3074
- ? scalingConfig.horizontalAxisScale
3075
- : scalingConfig.verticalAxisScale;
3076
- const startPaddingConfig = getElementScalingInfo(elementScales, defaultSizing, chartDataDirection === 'horizontal' ? 'leftPadding' : 'topPadding');
3077
- const endPaddingConfig = getElementScalingInfo(elementScales, defaultSizing, chartDataDirection === 'horizontal' ? 'rightPadding' : 'bottomPadding');
3078
- const leftLabelConfig = getElementScalingInfo(elementScales, defaultSizing, 'leftBucketLabel');
3079
- const dataLabelPaddingConfig = getElementScalingInfo(elementScales, defaultSizing, 'dataLabelPadding');
3080
- const fontSizeConfig = getElementScalingInfo(elementScales, defaultSizing, 'fontSize');
3081
- const fontSize = fontSizeConfig.target;
3082
- const dataLabelTextSizing = getDataLabelSize(data, pipeTransform, fontSize);
3083
- //We always calculate and return dataLabelTextSize, since it's also used for determing axis label size
3084
- const dataLabelTextSize = chartDataDirection === 'horizontal'
3085
- ? dataLabelTextSizing.horizontal
3086
- : dataLabelTextSizing.vertical;
3087
- const dataLabelFixedSize = dataLabelTextSize * getDataLabelSizingCount(data, config).total;
3088
- const bucketLabelTextSize = getBucketLabelSize(data, fontSize, dateFormat);
3089
- //Flow charts have a data label above each sub-bucket
3090
- const flowLabelSize = dataLabelTextSize + dataLabelPaddingConfig.target;
3091
- const startPaddingTotalSize = determinePossibleSizesOfElement(startPaddingConfig, 1);
3092
- const endPaddingTotalSize = determinePossibleSizesOfElement(endPaddingConfig, 1);
3093
- const dataLabelPaddingTotalSize = determinePossibleSizesOfElement(dataLabelPaddingConfig, getDataLabelSizingCount(data, config).total);
3094
- let leftBucketLabelActualSize = leftLabelConfig.target;
3095
- if (chartDataDirection === 'horizontal' && data.type === 'labeled') {
3096
- //For horizontal bars, the start padding will scale based on the bucket labels
3097
- const longestLabelLength = Math.max(...data.x.map(x => x.label.length)) *
3098
- (Chart.WIDTH_PER_LETTER * (fontSize / Chart.DEFAULT_FONT_SIZE));
3099
- const minLength = leftLabelConfig.min
3100
- ? Math.max(longestLabelLength, leftLabelConfig.min)
3101
- : longestLabelLength;
3102
- leftBucketLabelActualSize = leftLabelConfig.max
3103
- ? Math.min(minLength, leftLabelConfig.max)
3104
- : longestLabelLength;
3105
- }
3106
- let fixedSizeValue = leftBucketLabelActualSize +
3107
- dataLabelFixedSize +
3108
- startPaddingTotalSize.target +
3109
- endPaddingTotalSize.target +
3110
- dataLabelPaddingTotalSize.target;
3111
- if (fixedSizeValue > boundingDimension) {
3112
- //See if further truncating the label can help
3113
- if (leftLabelConfig.min &&
3114
- fixedSizeValue - boundingDimension <
3115
- leftBucketLabelActualSize - leftLabelConfig.min) {
3116
- leftBucketLabelActualSize =
3117
- leftBucketLabelActualSize - (fixedSizeValue - boundingDimension);
3118
- fixedSizeValue =
3119
- leftBucketLabelActualSize +
3120
- startPaddingTotalSize.target +
3121
- endPaddingTotalSize.target +
3122
- dataLabelPaddingTotalSize.target;
3123
- }
3124
- else if (axisScale !== 'grow' &&
3125
- (axisScale !== 'no-scale' || scalingConfig.dataScale.type === 'fit')) {
3126
- //Growing and non-fitting data axes can scroll instead
3127
- // eslint-disable-next-line no-console
3128
- console.warn('The provided element sizes mean the chart cannot display at this small of a size');
3129
- return {
3130
- startPadding: 0,
3131
- endPadding: 0,
3132
- leftBucketLabel: 0,
3133
- dataLabelTextSize: 0,
3134
- dataLabelPadding: 0,
3135
- fontSize: 0,
3136
- sizeForData: 0,
3137
- totalSize: 0,
3138
- bucketLabelTextSize: 0,
3139
- sizingError: true,
3140
- };
3141
- }
3142
- }
3143
- if (axisScale === 'scale-to-fit' ||
3144
- axisScale === 'grow' ||
3145
- axisScale === 'shrink' ||
3146
- scalingConfig.dataScale.type === 'fit') {
3147
- //A growing data axis scrolls rather than squeezing the data below its minimum size
3148
- const availableSize = axisScale === 'grow'
3149
- ? Math.max(boundingDimension - fixedSizeValue, getMinimumGrownDataSize(data, config, boundingDimension, flowLabelSize))
3150
- : boundingDimension - fixedSizeValue;
3151
- const sizeForData = getFittedDataSize(data, config, availableSize, flowLabelSize);
3152
- if (sizeForData === null) {
3153
- // eslint-disable-next-line no-console
3154
- console.warn('The provided minimum data element size means the chart cannot display at this small of a size');
3155
- return {
3156
- startPadding: 0,
3157
- endPadding: 0,
3158
- leftBucketLabel: 0,
3159
- dataLabelTextSize: 0,
3160
- dataLabelPadding: 0,
3161
- fontSize: 0,
3162
- sizeForData: 0,
3163
- totalSize: 0,
3164
- bucketLabelTextSize: 0,
3165
- sizingError: true,
3166
- };
3167
- }
3168
- return {
3169
- startPadding: startPaddingConfig.target,
3170
- endPadding: endPaddingConfig.target,
3171
- leftBucketLabel: leftBucketLabelActualSize,
3172
- dataLabelTextSize,
3173
- dataLabelPadding: dataLabelPaddingConfig.target,
3174
- fontSize: fontSizeConfig.target,
3175
- sizeForData,
3176
- totalSize: fixedSizeValue + availableSize,
3177
- bucketLabelTextSize,
3178
- };
3179
- }
3180
- const { primaryDataMin, primaryDataMax, scaleDomainMultipleForMax, scaleDomainMultipleForNeg, } = calcDataScalingValues(data, config);
3181
- const effectivePrimaryMaxForScaling = primaryDataMax * scaleDomainMultipleForMax;
3182
- const effectivePrimaryMinForScaling = primaryDataMin < 0 ? primaryDataMin * scaleDomainMultipleForNeg : 0;
3183
- if (scalingConfig.dataScale.type === 'max') {
3184
- const dataSize = scalingConfig.dataScale.value *
3185
- ((effectivePrimaryMaxForScaling - effectivePrimaryMinForScaling) /
3186
- effectivePrimaryMaxForScaling);
3187
- return {
3188
- startPadding: startPaddingConfig.target,
3189
- endPadding: endPaddingConfig.target,
3190
- leftBucketLabel: leftBucketLabelActualSize,
3191
- dataLabelTextSize,
3192
- dataLabelPadding: dataLabelPaddingConfig.target,
3193
- fontSize: fontSizeConfig.target,
3194
- sizeForData: dataSize,
3195
- totalSize: getScaledDataTotalSize(data, config, dataSize, flowLabelSize) +
3196
- fixedSizeValue,
3197
- bucketLabelTextSize,
3198
- };
3199
- }
3200
- const dataSize = ((effectivePrimaryMaxForScaling - effectivePrimaryMinForScaling) /
3201
- scalingConfig.dataScale.ratio.value) *
3202
- scalingConfig.dataScale.ratio.px;
3203
- return {
3204
- startPadding: startPaddingConfig.target,
3205
- endPadding: endPaddingConfig.target,
3206
- leftBucketLabel: leftBucketLabelActualSize,
3207
- dataLabelTextSize,
3208
- dataLabelPadding: dataLabelPaddingConfig.target,
3209
- fontSize: fontSizeConfig.target,
3210
- sizeForData: dataSize,
3211
- totalSize: getScaledDataTotalSize(data, config, dataSize, flowLabelSize) +
3212
- fixedSizeValue,
3213
- bucketLabelTextSize,
3214
- };
3215
- }
3216
- //The least space a growing data axis gives the data: a portion of the provided size, on top of the space that
3217
- // elements enlarged to the minimum size need (so the data stays proportional rather than all being the minimum)
3218
- function getMinimumGrownDataSize(data, config, boundingDimension, labelSize) {
3219
- const minimumElementsSize = data.type === 'flow-processed'
3220
- ? getMaxFlowBucketSize(data, 0, getMinimumDataElementSize(config), labelSize) - getFlowMidLabelSize(data, labelSize)
3221
- : 0;
3222
- return boundingDimension * GROWN_DATA_MINIMUM_RATIO + minimumElementsSize;
3223
- }
3224
- //For flow charts, finds the size the data scale should map to so that every bucket (including its own data labels,
3225
- // and any elements enlarged to the minimum size) fits in the available size
3226
- //Returns null if the minimum sizes alone can't fit
3227
- function getFittedDataSize(data, config, availableSize, labelSize) {
3228
- if (data.type !== 'flow-processed') {
3229
- return availableSize;
3230
- }
3231
- const dataMax = Math.max(...data.x.map(x => x.totalCount));
3232
- if (dataMax <= 0) {
3233
- return availableSize;
3234
- }
3235
- const minimumSize = getMinimumDataElementSize(config);
3236
- const bucketAvailableSize = availableSize + getFlowMidLabelSize(data, labelSize);
3237
- //Calculate what the sizing would need to be for each individual column,
3238
- // taking the value that is most restrictive. Not applying minimum size yet
3239
- const unenlargedRatio = Math.min(...data.x
3240
- .filter(bucket => bucket.totalCount > 0)
3241
- .map(bucket => (bucketAvailableSize - (bucket.subBuckets.length - 1) * labelSize) /
3242
- bucket.totalCount));
3243
- if (minimumSize === 0 ||
3244
- getMaxFlowBucketSize(data, unenlargedRatio, minimumSize, labelSize) <=
3245
- bucketAvailableSize) {
3246
- return unenlargedRatio * dataMax;
3247
- }
3248
- if (getMaxFlowBucketSize(data, 0, minimumSize, labelSize) >
3249
- bucketAvailableSize) {
3250
- return null;
3251
- }
3252
- //Now, we apply minimum size to the bars to calculate our true ratio (found through binary search)
3253
- let low = 0;
3254
- let high = unenlargedRatio;
3255
- for (let i = 0; i < 50; i++) {
3256
- const mid = (low + high) / 2;
3257
- if (getMaxFlowBucketSize(data, mid, minimumSize, labelSize) >
3258
- bucketAvailableSize) {
3259
- high = mid;
3260
- }
3261
- else {
3262
- low = mid;
3263
- }
3264
- }
3265
- return low * dataMax;
3266
- }
3267
- //The size needed along the data axis beyond the fixed size
3268
- //For flow charts, this is based on the tallest bucket (including its own data labels and any enlarged elements),
3269
- // rather than assuming the bucket with the most data also has the most sub-buckets
3270
- function getScaledDataTotalSize(data, config, dataSize, labelSize) {
3271
- if (data.type !== 'flow-processed') {
3272
- return dataSize;
3273
- }
3274
- const dataMax = Math.max(...data.x.map(x => x.totalCount));
3275
- if (dataMax <= 0) {
3276
- return dataSize;
3277
- }
3278
- return (getMaxFlowBucketSize(data, dataSize / dataMax, getMinimumDataElementSize(config), labelSize) - getFlowMidLabelSize(data, labelSize));
3279
- }
3280
- function getDataLabelSize(data, pipeTransform, fontSize) {
3281
- let normHorizontalMaxLength = 0;
3282
- let normSuppMaxLength = 0;
3283
- if (data.type !== 'flow-processed' && pipeTransform !== null) {
3284
- normHorizontalMaxLength = Math.max(...data.ys.map((y, yIndex) => Math.max(...y.values.map((val, xIndex) => checkLabelLength(pipeTransform(val, checkIfSecondary(data, yIndex, xIndex, false)), fontSize)))));
3285
- normSuppMaxLength = Math.max(...(data.supplementaryYs ?? []).map((y, yIndex) => Math.max(...y.values.map((val, xIndex) => checkLabelLength(pipeTransform(val, checkIfSecondary(data, yIndex, xIndex, true)), fontSize)))));
3286
- }
3287
- if (data.type === 'flow-processed') {
3288
- return {
3289
- horizontal: Math.max(normHorizontalMaxLength, normSuppMaxLength),
3290
- vertical: fontSize * 2,
3291
- };
3292
- }
3293
- return {
3294
- horizontal: Math.max(normHorizontalMaxLength, normSuppMaxLength),
3295
- vertical: fontSize,
3296
- };
3297
- }
3298
- function getBucketLabelSize(data, fontSize, dateFormat) {
3299
- if (dateFormat !== null) {
3300
- if (data.type === 'labeled') {
3301
- return Math.max(...data.x.map(x => checkLabelLength(x.label, fontSize)));
3302
- }
3303
- else if (data.type === 'timeseries') {
3304
- return Math.max(...data.x.map(x => checkLabelLength(dateFormat(new Date(x)), fontSize)));
3305
- }
3306
- }
3307
- return 0;
3308
- }
3309
- function checkLabelLength(value, fontSize) {
3310
- const periodCount = (value.match(/\./g) || []).length;
3311
- const slashCount = (value.match(/\//g) || []).length;
3312
- const fontScaleFactor = fontSize / Chart.DEFAULT_FONT_SIZE;
3313
- return ((value.length - (periodCount + slashCount)) *
3314
- (WIDTH_PER_NUMBER * fontScaleFactor) +
3315
- periodCount * (WIDTH_PER_PERIOD * fontScaleFactor) +
3316
- slashCount * (WIDTH_PER_SLASH * fontScaleFactor));
3317
- }
3318
- function isBarType(type) {
3319
- if (type === 'bar' ||
3320
- type === 'horizontal-bar' ||
3321
- type === 'waterfall' ||
3322
- type === 'funnel') {
3323
- return true;
3324
- }
3325
- return false;
3326
- }
3327
- Chart.isBarType = isBarType;
3328
- //Only bar-type and flow charts have discrete data elements that the minimum size applies to
3329
- function getMinimumDataElementSize(config) {
3330
- if (config.type === 'donut' ||
3331
- config.type === 'line' ||
3332
- config.type === 'area') {
3333
- return 0;
3334
- }
3335
- return config.scalingConfig?.dataScale?.minimumDataElementSize ?? 0;
3336
- }
3337
- //Any data element with a non-zero value is kept at or above the minimum size
3338
- function applyMinimumDataElementSize(size, value, minimumSize) {
3339
- return value !== 0 ? Math.max(size, minimumSize) : size;
3340
- }
3341
- function getFlowSubBucketSizes(subBucket, valueToSize, minimumSize) {
3342
- const connectionSizes = subBucket.connections.map(connection => applyMinimumDataElementSize(valueToSize(connection.count), connection.count, minimumSize));
3343
- const sumSizes = (direction) => sum(connectionSizes.filter((_, i) => subBucket.connections[i].direction === direction));
3344
- const continuingSize = sumSizes('forward');
3345
- const backwardSize = sumSizes('backward');
3346
- const nonContinuingCount = subBucket.count -
3347
- sum(subBucket.connections
3348
- .filter(connection => connection.direction === 'forward')
3349
- .map(connection => connection.count));
3350
- //The sub-bucket must be big enough to hold all of its (possibly enlarged) connections on either side
3351
- const totalSize = Math.max(applyMinimumDataElementSize(valueToSize(subBucket.count), subBucket.count, minimumSize), continuingSize +
3352
- applyMinimumDataElementSize(valueToSize(nonContinuingCount), nonContinuingCount, minimumSize), backwardSize);
3353
- //Every unit in a sub-bucket arrives through its backward connections, so they're stretched to fill the
3354
- // sub-bucket when it has been enlarged beyond them
3355
- return {
3356
- totalSize,
3357
- continuingSize,
3358
- connectionSizes: connectionSizes.map((size, i) => subBucket.connections[i].direction === 'backward' && backwardSize > 0
3359
- ? (size * totalSize) / backwardSize
3360
- : size),
3361
- };
3362
- }
3363
- //The size of the tallest flow bucket for the given scaling ratio, including the data labels between its sub-buckets
3364
- // The label above the first sub-bucket is excluded, since it's part of the top offset
3365
- function getMaxFlowBucketSize(data, pxPerValue, minimumSize, labelSize) {
3366
- return Math.max(...data.x.map(bucket => sum(bucket.subBuckets.map(subBucket => getFlowSubBucketSizes(subBucket, value => value * pxPerValue, minimumSize).totalSize)) +
3367
- (bucket.subBuckets.length - 1) * labelSize));
3368
- }
3369
- //The fixed size reserves room for the labels between sub-buckets as if every bucket had as many sub-buckets as the
3370
- // bucket with the most, so this is the portion of the fixed size that each bucket can instead use based on its own labels
3371
- function getFlowMidLabelSize(data, labelSize) {
3372
- return ((Math.max(...data.x.map(bucket => bucket.subBuckets.length)) - 1) *
3373
- labelSize);
3374
- }
3375
- function isStackedData(config) {
3376
- if (config.type === 'bar' || config.type === 'horizontal-bar') {
3377
- if (config.groupingType === 'stacked') {
3378
- return true;
3379
- }
3380
- }
3381
- if (config.type === 'area' || config.type === 'waterfall') {
3382
- return true;
3383
- }
3384
- return false;
3385
- }
3386
- function isClusteredData(data, config, includeSupplementary) {
3387
- //It varies whether we want to include supplementary data in this check
3388
- if (hasSupplementaryData(data) && includeSupplementary) {
3389
- return true;
3390
- }
3391
- if ((config.type === 'bar' || config.type === 'horizontal-bar') &&
3392
- config.groupingType === 'clustered') {
3393
- return true;
3394
- }
3395
- if (config.type === 'funnel') {
3396
- return true;
3397
- }
3398
- return false;
3399
- }
3400
- //In some cases, the distinction between clustered and stacked doesn't matter
3401
- function isGroupingTypeException(data, config) {
3402
- if (data.ys.length === 1) {
3403
- return true;
3404
- }
3405
- //Checking for a 'metric' charts, which is a special case for horizontal bar charts,
3406
- // where each series is also a bucket (and vice versa)
3407
- if (config.type === 'horizontal-bar') {
3408
- if (data.x.length === data.ys.length &&
3409
- data.ys.length ===
3410
- data.ys.filter(y => y.values.filter(val => val !== 0).length === 1)
3411
- .length) {
3412
- return true;
3413
- }
3414
- }
3415
- return false;
3416
- }
3417
- function hasSupplementaryData(data) {
3418
- if (data.type === 'flow') {
3419
- return false;
3420
- }
3421
- if (data.supplementaryYs && data.supplementaryYs.length > 0) {
3422
- return true;
3423
- }
3424
- return false;
3425
- }
3426
- function getElementScalingInfo(elementScales, defaultScalingConfig, element) {
3427
- const defaultElementConfig = defaultScalingConfig[element];
3428
- let inputConfig;
3429
- if (elementScales) {
3430
- const possibleConfig = elementScales[element];
3431
- if (possibleConfig) {
3432
- inputConfig = possibleConfig;
3433
- }
3434
- else {
3435
- inputConfig = null;
3436
- }
3437
- }
3438
- else {
3439
- inputConfig = null;
3440
- }
3441
- if (inputConfig !== null) {
3442
- const returnConfig = inputConfig;
3443
- return returnConfig;
3444
- }
3445
- if (defaultElementConfig.target !== undefined) {
3446
- const returnConfig = defaultElementConfig;
3447
- return returnConfig;
3448
- }
3449
- return {
3450
- target: 0,
3451
- };
3452
- }
3453
- function determinePossibleSizesOfElement(elementConfig, elementCount) {
3454
- const indMin = elementConfig.min !== undefined ? elementConfig.min : 0;
3455
- const indMax = elementConfig.max !== undefined ? elementConfig.max : 0;
3456
- const indTarget = elementConfig.target;
3457
- return {
3458
- min: indMin * elementCount,
3459
- max: indMax * elementCount,
3460
- target: indTarget * elementCount,
3461
- };
3462
- }
3463
- function determineTotalScaledSizeOfElement(elementConfig, elementCount, scaleValue) {
3464
- const scaledVal = getScaledElementSize(elementConfig, scaleValue);
3465
- return scaledVal * elementCount;
3466
- }
3467
- function getScaledElementSize(elementConfig, scaleValue) {
3468
- const scaledTarget = elementConfig.target * scaleValue;
3469
- if (scaleValue < 1) {
3470
- if (elementConfig.min && elementConfig.min > scaledTarget) {
3471
- return elementConfig.min;
3472
- }
3473
- return scaledTarget;
3474
- }
3475
- if (scaleValue > 1) {
3476
- if (elementConfig.max && elementConfig.max < scaledTarget) {
3477
- return elementConfig.max;
3478
- }
3479
- return scaledTarget;
3480
- }
3481
- return scaledTarget;
3482
- }
3483
- function getCheckingInfoForElementConfig(config, elementCount) {
3484
- let minScaleFactor = undefined;
3485
- if (config.min) {
3486
- minScaleFactor =
3487
- config.target !== 0 ? config.min / config.target : undefined;
3488
- }
3489
- let maxScaleFactor = undefined;
3490
- if (config.max) {
3491
- maxScaleFactor =
3492
- config.target !== 0 ? config.max / config.target : undefined;
3493
- }
3494
- return {
3495
- config,
3496
- minScaleFactor,
3497
- maxScaleFactor,
3498
- elementCount,
3499
- };
3500
- }
3501
- function getSumForScaleValue(checkInfos, scaleValue) {
3502
- let sum = 0;
3503
- for (const check of checkInfos) {
3504
- sum += determineTotalScaledSizeOfElement(check.config, check.elementCount, scaleValue);
3505
- }
3506
- return sum;
3507
- }
3508
- function getDataLabelSizingCount(data, config) {
3509
- if (config.showDataLabels !== true) {
3510
- return {
3511
- start: 0,
3512
- end: 0,
3513
- total: 0,
3514
- };
3515
- }
3516
- //Data labels are always shown above the data for all but these 3 types
3517
- if (config.type !== 'bar' &&
3518
- config.type !== 'horizontal-bar' &&
3519
- config.type !== 'waterfall' &&
3520
- config.type !== 'flow') {
3521
- return {
3522
- start: 1,
3523
- end: 0,
3524
- total: 1,
3525
- };
3526
- }
3527
- let startCount = 0;
3528
- let midCount = 0;
3529
- let endCount = 0;
3530
- if (data.type !== 'flow-processed') {
3531
- if (data.ys.find(y => y.values.find(val => val >= 0))) {
3532
- if (config.type === 'horizontal-bar') {
3533
- endCount += 1;
3534
- }
3535
- else {
3536
- startCount += 1;
3537
- }
3538
- }
3539
- if (data.ys.find(y => y.values.find(val => val < 0))) {
3540
- if (config.type === 'horizontal-bar') {
3541
- startCount += 1;
3542
- }
3543
- else {
3544
- endCount += 1;
3545
- }
3546
- }
3547
- }
3548
- else {
3549
- startCount = 1;
3550
- midCount = Math.max(...data.x.map(x => x.subBuckets.length)) - 1;
3551
- }
3552
- return {
3553
- start: startCount,
3554
- end: endCount,
3555
- total: startCount + midCount + endCount,
3556
- };
3557
- }
3558
- function getIfHoverOutOfBounds(
3559
- //Position not accounting for scrolling
3560
- relPosX, relPosY,
3561
- //Position accounting for scrolling
3562
- realPosX, realPosY, chartSizingValues, dimensions) {
3563
- //Check if we're on top of one of the scrollbars
3564
- if (relPosX > dimensions.width || relPosY > dimensions.height) {
3565
- return true;
3566
- }
3567
- if (chartSizingValues === null) {
3568
- //If chartSizingValues aren't provided, no more checks
3569
- return false;
3570
- }
3571
- //Check if we're in one of the padding areas
3572
- if (realPosX < chartSizingValues.leftPadding ||
3573
- realPosX >
3574
- chartSizingValues.totalWidth - chartSizingValues.rightPadding ||
3575
- realPosY < chartSizingValues.topPadding ||
3576
- realPosY > chartSizingValues.totalHeight - chartSizingValues.bottomPadding) {
3577
- return true;
3578
- }
3579
- return false;
3580
- }
3581
- function getChartDataDirection(config) {
3582
- if (config.type === 'horizontal-bar') {
3583
- return 'horizontal';
3584
- }
3585
- return 'vertical';
3586
- }
3587
- function combineScalingInfo(config, defaultConfig) {
3588
- const providedScalingConfig = config.scalingConfig;
3589
- const chartDataDirection = getChartDataDirection(config);
3590
- //If the user provides a data scale, we don't want to override that unless they also provided a specific scale for the corresponding axis
3591
- const dataScale = providedScalingConfig && providedScalingConfig.dataScale
3592
- ? providedScalingConfig.dataScale
3593
- : defaultConfig.nonElementScales.dataScale;
3594
- let verticalAxisScale = providedScalingConfig?.verticalAxisScale;
3595
- if (verticalAxisScale === undefined) {
3596
- if (chartDataDirection === 'horizontal' || dataScale.type === 'fit') {
3597
- verticalAxisScale = defaultConfig.nonElementScales.verticalAxisScale;
3598
- }
3599
- else {
3600
- //The vertical axis is the data axis, the dataScale has a user-inputted value, and there isn't a user-inputted verticalAxisScale
3601
- // So, we'll prevent the axis scaling from interfering with the dataScale
3602
- verticalAxisScale = 'no-scale';
3603
- }
3604
- }
3605
- let horizontalAxisScale = providedScalingConfig?.horizontalAxisScale;
3606
- if (horizontalAxisScale === undefined) {
3607
- if (chartDataDirection === 'vertical' || dataScale.type === 'fit') {
3608
- horizontalAxisScale =
3609
- defaultConfig.nonElementScales.horizontalAxisScale;
3610
- }
3611
- else {
3612
- //The horizontal axis is the data axis, the dataScale has a user-inputted value, and there isn't a user-inputted horizontalAxisScale
3613
- // So, we'll prevent the axis scaling from interfering with the dataScale
3614
- horizontalAxisScale = 'no-scale';
3615
- }
3616
- }
3617
- return {
3618
- dataScale: providedScalingConfig && providedScalingConfig.dataScale
3619
- ? providedScalingConfig.dataScale
3620
- : defaultConfig.nonElementScales.dataScale,
3621
- horizontalAxisScale,
3622
- verticalAxisScale,
3623
- horizontalContainerScale: providedScalingConfig && providedScalingConfig.horizontalContainerScale
3624
- ? providedScalingConfig.horizontalContainerScale
3625
- : defaultConfig.nonElementScales.horizontalContainerScale,
3626
- verticalContainerScale: providedScalingConfig && providedScalingConfig.verticalContainerScale
3627
- ? providedScalingConfig.verticalContainerScale
3628
- : defaultConfig.nonElementScales.verticalContainerScale,
3629
- targetTickCount: providedScalingConfig &&
3630
- providedScalingConfig.targetTickCount !== undefined
3631
- ? providedScalingConfig.targetTickCount
3632
- : defaultConfig.nonElementScales.targetTickCount,
3633
- };
3634
- }
3635
- function isDeEmphasized(config, id, isDarkened) {
3636
- const highlightedBuckets = config.flowConfig.subBucketsConfig
3637
- .filter(sbc => sbc.isHighlighted === true)
3638
- .map(sbc => sbc.bucketId);
3639
- if (highlightedBuckets.length === 0) {
3640
- return false;
3641
- }
3642
- if (isDarkened) {
3643
- return true;
3644
- }
3645
- if (highlightedBuckets.some(hb => hb === id)) {
3646
- return false;
3647
- }
3648
- return true;
3649
- }
3650
- function calculateFlowConnectionPath(connection) {
3651
- const dx = connection.topLine.x2 - connection.topLine.x1;
3652
- const curve = Math.abs(dx) * FLOW_CONNECTION_CURVE_CONSTANT;
3653
- const path = `
3654
- M ${connection.topLine.x1},${connection.topLine.y1}
3655
-
3656
- C ${connection.topLine.x1 + curve},${connection.topLine.y1}
3657
- ${connection.topLine.x2 - curve},${connection.topLine.y2}
3658
- ${connection.topLine.x2},${connection.topLine.y2}
3659
-
3660
- L ${connection.bottomLine.x2},${connection.bottomLine.y2}
3661
-
3662
- C ${connection.bottomLine.x2 - curve},${connection.bottomLine.y2}
3663
- ${connection.bottomLine.x1 + curve},${connection.bottomLine.y1}
3664
- ${connection.bottomLine.x1},${connection.bottomLine.y1}
3665
-
3666
- Z
3667
- `;
3668
- return path;
3669
- }
3670
- function cubic(a, b, c, d, t) {
3671
- const mt = 1 - t;
3672
- return mt ** 3 * a + 3 * mt ** 2 * t * b + 3 * mt * t ** 2 * c + t ** 3 * d;
3673
- }
3674
- function bezierYAtX(x, line) {
3675
- const curve = Math.abs(line.x2 - line.x1) * FLOW_CONNECTION_CURVE_CONSTANT;
3676
- const p0 = { x: line.x1, y: line.y1 };
3677
- const p1 = { x: line.x1 + curve, y: line.y1 };
3678
- const p2 = { x: line.x2 - curve, y: line.y2 };
3679
- const p3 = { x: line.x2, y: line.y2 };
3680
- let lo = 0;
3681
- let hi = 1;
3682
- // Binary search for t where bezierX(t) ~= x
3683
- for (let i = 0; i < 20; i++) {
3684
- const t = (lo + hi) / 2;
3685
- const bx = cubic(p0.x, p1.x, p2.x, p3.x, t);
3686
- if (bx < x)
3687
- lo = t;
3688
- else
3689
- hi = t;
3690
- }
3691
- const t = (lo + hi) / 2;
3692
- return cubic(p0.y, p1.y, p2.y, p3.y, t);
3693
- }
3694
- function checkIfPointWithinConnection(connection, pointX, pointY) {
3695
- const topY = bezierYAtX(pointX, connection.topLine);
3696
- const bottomY = bezierYAtX(pointX, connection.bottomLine);
3697
- return (pointX >= connection.topLine.x1 &&
3698
- pointX <= connection.topLine.x2 &&
3699
- pointY >= Math.min(topY, bottomY) &&
3700
- pointY <= Math.max(topY, bottomY));
3701
- }
3702
- function getFlowBucketIndexForHover(chartSizingValues, xPos) {
3703
- let bucketIndex = 0;
3704
- const bucketLeftEdge = chartSizingValues.totalLeftOffset;
3705
- const totalBucketGap = chartSizingValues.barSize + chartSizingValues.bucketGap;
3706
- if (bucketLeftEdge > xPos) {
3707
- return null;
3708
- }
3709
- while (bucketLeftEdge + bucketIndex * totalBucketGap < xPos) {
3710
- if (bucketLeftEdge + (bucketIndex + 1) * totalBucketGap > xPos) {
3711
- if (bucketLeftEdge +
3712
- bucketIndex * totalBucketGap +
3713
- chartSizingValues.barSize >
3714
- xPos) {
3715
- return {
3716
- index: bucketIndex,
3717
- area: 'bar',
3718
- };
3719
- }
3720
- else {
3721
- return {
3722
- index: bucketIndex,
3723
- area: 'connection',
3724
- };
3725
- }
3726
- }
3727
- bucketIndex += 1;
3728
- }
3729
- return null;
3730
- }
3731
- function checkAnchorsAgainstBound(anchorX, anchorY, dimensions, width, height) {
3732
- let retAnchorX = anchorX;
3733
- let retAnchorY = anchorY;
3734
- let retWidth = width;
3735
- let retHeight = height;
3736
- if (retAnchorX > dimensions.width) {
3737
- retAnchorX = dimensions.width;
3738
- if (retWidth !== undefined) {
3739
- retWidth = 0;
3740
- }
3741
- }
3742
- if (retAnchorX < 0) {
3743
- retAnchorX = 0;
3744
- if (retWidth !== undefined) {
3745
- retWidth = 0;
3746
- }
3747
- }
3748
- if (retAnchorY > dimensions.height) {
3749
- retAnchorY = dimensions.height;
3750
- if (retHeight !== undefined) {
3751
- retHeight = 0;
3752
- }
3753
- }
3754
- if (retAnchorY < 0) {
3755
- retAnchorY = 0;
3756
- if (retHeight !== undefined) {
3757
- retHeight = 0;
3758
- }
3759
- }
3760
- return {
3761
- anchorX: retAnchorX,
3762
- anchorY: retAnchorY,
3763
- anchorWidth: retWidth,
3764
- anchorHeight: retHeight,
3765
- };
3766
- }
3767
- })(Chart || (Chart = {}));
3768
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2hhcnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9yaXYvc3JjL2xpYi92aXN1YWxpemF0aW9uL2NoYXJ0L2NoYXJ0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUMvQyxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sVUFBVSxDQUFDO0FBQ3ZDLE9BQU8sRUFBRSxHQUFHLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxHQUFHLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFDaEQsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQzNDLE9BQU8sRUFBRSxHQUFHLEVBQUUsSUFBSSxFQUFFLE1BQU0sUUFBUSxDQUFDO0FBQ25DLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUN4RCxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFDNUQsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLG9DQUFvQyxDQUFDO0FBQ3BFLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLHdDQUF3QyxDQUFDO0FBQzNFLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxzQ0FBc0MsQ0FBQztBQUV2RSxPQUFPLEVBSUwsd0JBQXdCLEVBSXhCLHFCQUFxQixFQUlyQixrQ0FBa0MsR0FHbkMsTUFBTSxpQkFBaUIsQ0FBQztBQUV6QixNQUFNLEtBQVcsS0FBSyxDQTAxTHJCO0FBMTFMRCxXQUFpQixLQUFLO0lBQ1AseUJBQW1CLEdBQUc7UUFDakMsYUFBYTtRQUNiLGlCQUFpQjtRQUNqQixtQkFBbUI7UUFDbkIsV0FBVztRQUNYLFdBQVc7UUFDWCxXQUFXO1FBQ1gsV0FBVztRQUNYLGdDQUFnQztRQUNoQyxpQkFBaUI7UUFDakIsbUJBQW1CO1FBQ25CLFdBQVc7UUFDWCxXQUFXO1FBQ1gsV0FBVztR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LFVBQVUsQ0FBQyxPQUFPLENBQUMsRUFBRSxHQUFHLFVBQVUsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDO1FBQ3pELE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsOEJBQThCLENBQUM7UUFFNUQsTUFBTSxJQUFJLEdBQUc7VUFDUCxVQUFVLENBQUMsT0FBTyxDQUFDLEVBQUUsSUFBSSxVQUFVLENBQUMsT0FBTyxDQUFDLEVBQUU7O1VBRTlDLFVBQVUsQ0FBQyxPQUFPLENBQUMsRUFBRSxHQUFHLEtBQUssSUFBSSxVQUFVLENBQUMsT0FBTyxDQUFDLEVBQUU7VUFDdEQsVUFBVSxDQUFDLE9BQU8sQ0FBQyxFQUFFLEdBQUcsS0FBSyxJQUFJLFVBQVUsQ0FBQyxPQUFPLENBQUMsRUFBRTtVQUN0RCxVQUFVLENBQUMsT0FBTyxDQUFDLEVBQUUsSUFBSSxVQUFVLENBQUMsT0FBTyxDQUFDLEVBQUU7O1VBRTlDLFVBQVUsQ0FBQyxVQUFVLENBQUMsRUFBRSxJQUFJLFVBQVUsQ0FBQyxVQUFVLENBQUMsRUFBRTs7VUFFcEQsVUFBVSxDQUFDLFVBQVUsQ0FBQyxFQUFFLEdBQUcsS0FBSyxJQUFJLFVBQVUsQ0FBQyxVQUFVLENBQUMsRUFBRTtVQUM1RCxVQUFVLENBQUMsVUFBVSxDQUFDLEVBQUUsR0FBRyxLQUFLLElBQUksVUFBVSxDQUFDLFVBQVUsQ0FBQyxFQUFFO1VBQzVELFVBQVUsQ0FBQyxVQUFVLENBQUMsRUFBRSxJQUFJLFVBQVUsQ0FBQyxVQUFVLENBQUMsRUFBRTs7O0tBR3pELENBQUM7UUFFRixPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFFRCxTQUFTLEtBQUssQ0FDWixDQUFTLEVBQ1QsQ0FBUyxFQUNULENBQVMsRUFDVCxDQUFTLEVBQ1QsQ0FBUztRQUVULE1BQU0sRUFBRSxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDakIsT0FBTyxFQUFFLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDOUUsQ0FBQztJQUVELFNBQVMsVUFBVSxDQUNqQixDQUFTLEVBQ1QsSUFLQztRQUVELE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUUsR0FBRyxJQUFJLENBQUMsRUFBRSxDQUFDLEdBQUcsOEJBQThCLENBQUM7UUFDM0UsTUFBTSxFQUFFLEdBQUcsRUFBRSxDQUFDLEVBQUUsSUFBSSxDQUFDLEVBQUUsRUFBRSxDQUFDLEVBQUUsSUFBSSxDQUFDLEVBQUUsRUFBRSxDQUFDO1FBQ3RDLE1BQU0sRUFBRSxHQUFHLEVBQUUsQ0FBQyxFQUFFLElBQUksQ0FBQyxFQUFFLEdBQUcsS0FBSyxFQUFFLENBQUMsRUFBRSxJQUFJLENBQUMsRUFBRSxFQUFFLENBQUM7UUFDOUMsTUFBTSxFQUFFLEdBQUcsRUFBRSxDQUFDLEVBQUUsSUFBSSxDQUFDLEVBQUUsR0FBRyxLQUFLLEVBQUUsQ0FBQyxFQUFFLElBQUksQ0FBQyxFQUFFLEVBQUUsQ0FBQztRQUM5QyxNQUFNLEVBQUUsR0FBRyxFQUFFLENBQUMsRUFBRSxJQUFJLENBQUMsRUFBRSxFQUFFLENBQUMsRUFBRSxJQUFJLENBQUMsRUFBRSxFQUFFLENBQUM7UUFFdEMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxDQUFDO1FBQ1gsSUFBSSxFQUFFLEdBQUcsQ0FBQyxDQUFDO1FBRVgsNENBQTRDO1FBQzVDLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFLEVBQUUsQ0FBQyxFQUFFLEVBQUU7WUFDM0IsTUFBTSxDQUFDLEdBQUcsQ0FBQyxFQUFFLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQ3hCLE1BQU0sRUFBRSxHQUFHLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLEVB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QUFLLFNBQVMsRUFBRTtnQkFDMUIsUUFBUSxHQUFHLENBQUMsQ0FBQzthQUNkO1NBQ0Y7UUFDRCxJQUFJLFVBQVUsR0FBRyxVQUFVLENBQUMsTUFBTSxFQUFFO1lBQ2xDLFVBQVUsR0FBRyxVQUFVLENBQUMsTUFBTSxDQUFDO1lBQy9CLElBQUksU0FBUyxLQUFLLFNBQVMsRUFBRTtnQkFDM0IsU0FBUyxHQUFHLENBQUMsQ0FBQzthQUNmO1NBQ0Y7UUFDRCxJQUFJLFVBQVUsR0FBRyxDQUFDLEVBQUU7WUFDbEIsVUFBVSxHQUFHLENBQUMsQ0FBQztZQUNmLElBQUksU0FBUyxLQUFLLFNBQVMsRUFBRTtnQkFDM0IsU0FBUyxHQUFHLENBQUMsQ0FBQzthQUNmO1NBQ0Y7UUFFRCxPQUFPO1lBQ0wsT0FBTyxFQUFFLFVBQVU7WUFDbkIsT0FBTyxFQUFFLFVBQVU7WUFDbkIsV0FBVyxFQUFFLFFBQVE7WUFDckIsWUFBWSxFQUFFLFNBQVM7U0FDeEIsQ0FBQztJQUNKLENBQUM7QUFDSCxDQUFDLEVBMTFMZ0IsS0FBSyxLQUFMLEtBQUssUUEwMUxyQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEN1cnJlbmN5UGlwZSB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQgeyBzY2FsZUxpbmVhciB9IGZyb20gJ2QzLXNjYWxlJztcbmltcG9ydCB7IGFyYywgYXJlYSwgbGluZSwgcGllIH0gZnJvbSAnZDMtc2hhcGUnO1xuaW1wb3J0IHsgdXRjRm9ybWF0IH0gZnJvbSAnZDMtdGltZS1mb3JtYXQnO1xuaW1wb3J0IHsgc3VtLCB1bmlxIH0gZnJvbSAnbG9kYXNoJztcbmltcG9ydCB7IERheXNQaXBlIH0gZnJvbSAnLi4vLi4vZm9ybWF0L3BpcGVzL2RheXMucGlwZSc7XG5pbXBvcnQgeyBOdW1iZXJQaXBlIH0gZnJvbSAnLi4vLi4vZm9ybWF0L3BpcGVzL251bWJlci5waXBlJztcbmltcG9ydCB7IFBlcmNlbnRhZ2VQaXBlIH0gZnJvbSAnLi4vLi4vZm9ybWF0L3BpcGVzL3BlcmNlbnRhZ2UucGlwZSc7XG5pbXBvcnQgeyBTbWFsbEN1cnJlbmN5UGlwZSB9IGZyb20gJy4uLy4uL2Zvcm1hdC9waXBlcy9zbWFsbC1jdXJyZW5jeS5waXBlJztcbmltcG9ydCB7IFNtYWxsTnVtYmVyUGlwZSB9IGZyb20gJy4uLy4uL2Zvcm1hdC9waXBlcy9zbWFsbC1udW1iZXIucGlwZSc7XG5pbXBvcnQgeyBDYWxsb3V0Q29tcG9uZW50IH0gZnJvbSAnLi4vLi4vb3ZlcmxheS9jYWxsb3V0L2NhbGxvdXQuY29tcG9uZW50JztcbmltcG9ydCB7XG4gIENoYXJ0RGF0YURpcmVjdGlvbixcbiAgQ2hhcnRTY2FsZUVsZW1lbnQsXG4gIENvbnRhaW5lclNjYWxpbmdUeXBlLFxuICBEZWZhdWx0RG9udXRTaXppbmdDb25maWcsXG4gIERlZmF1bHRTY2FsaW5nQ29uZmlnLFxuICBEb251dFNpemluZ0NvbmZpZyxcbiAgRWxlbWVudFNjYWxpbmdDb25maWd1cmF0aW9uLFxuICBlbXB0eUNoYXJ0U2NhbGVWYWx1ZXMsXG4gIEZ1bGxDaGFydFNjYWxlVmFsdWVzLFxuICBGdWxsRWxlbWVudFNjYWxpbmdDb25maWcsXG4gIEZ1bGxTY2FsaW5nQ29uZmlnLFxuICBnZXREZWZhdWx0U2NhbGluZ0NvbmZpZ0J5Q2hhcnRUeXBlLFxuICBOb25FbGVtZW50U2NhbGluZ0NvbmZpZyxcbiAgUGFydGlhbEVsZW1lbnRTY2FsaW5nQ29uZmlnLFxufSBmcm9tICcuL2NoYXJ0LXNjYWxpbmcnO1xuXG5leHBvcnQgbmFtZXNwYWNlIENoYXJ0IHtcbiAgZXhwb3J0IGNvbnN0IGRlZmF1bHRDb2xvclBhbGV0dGUgPSBbXG4gICAgLy9CYXNlIGNvbG9yc1xuICAgICctLWJhamEtYmxhc3QtNTAnLFxuICAgICctLXRlYWwtZGlhbW9uZC01MCcsXG4gICAgJy0tZnlyZS01MCcsXG4gICAgJy0tdGFuZy01MCcsXG4gICAgJy0tcHVycC02MCcsXG4gICAgJy0tcm9zaS03MCcsXG4gICAgLy9TaGlmdCBsaWdodGVyIGZyb20gYmFzZSBieSAtMjBcbiAgICAnLS1iYWphLWJsYXN0LTMwJyxcbiAgICAnLS10ZWFsLWRpYW1vbmQtMzAnLFxuICAgICctLWZ5cmUtMzAnLFxuICAgICctLXRhbmctMzAnLFxuICAgICctLXB1cnAtNDAnLFxuICAgICctLXJvc2ktNTAnLFxuICAgIC8vU2hpZnQgZGFya2VyIGZyb20gYmFzZSBieSArMjBcbiAgICAnLS1iYWphLWJsYXN0LTcwJyxcbiAgICAnLS10ZWFsLWRpYW1vbmQtNzAnLFxuICAgICctLWZ5cmUtNzAnLFxuICAgICctLXRhbmctNzAnLFxuICAgICctLXB1cnAtODAnLFxuICAgICctLXJvc2ktOTAnLFxuICBdO1xuXG4gIGV4cG9ydCBmdW5jdGlvbiBjaGFydChcbiAgICBjb25maWc6IENvbmZpZyxcbiAgICBkYXRhOiBJbnB1dERhdGEsXG4gICAgZGltZW5zaW9uczogRGltZW5zaW9ucyxcbiAgKTogUmVuZGVyZWRDaGFydCB7XG4gICAgcmV0dXJuIGNvbmZpZy50eXBlID09PSAnbGluZSdcbiAgICAgID8gbGluZXMoY29uZmlnLCBkYXRhLCBkaW1lbnNpb25zKVxuICAgICAgOiBjb25maWcudHlwZSA9PT0gJ2FyZWEnXG4gICAgICA/IGFyZWFzKGNvbmZpZywgZGF0YSwgZGltZW5zaW9ucylcbiAgICAgIDogY29uZmlnLnR5cGUgPT09ICdkb251dCdcbiAgICAgID8gYXJjcyhjb25maWcsIGRhdGEsIGRpbWVuc2lvbnMpXG4gICAgICA6IGNvbmZpZy50eXBlID09PSAnaG9yaXpvbnRhbC1iYXInXG4gICAgICA/IGhvcml6b250YWxCYXJzKGNvbmZpZywgZGF0YSwgZGltZW5zaW9ucylcbiAgICAgIDogY29uZmlnLnR5cGUgPT09ICdiYXInXG4gICAgICA/IGJhcnMoY29uZmlnLCBkYXRhLCBkaW1lbnNpb25zKVxuICAgICAgOiBjb25maWcudHlwZSA9PT0gJ3dhdGVyZmFsbCdcbiAgICAgID8gd2F0ZXJmYWxsKGNvbmZpZywgZGF0YSwgZGltZW5zaW9ucylcbiAgICAgIDogY29uZmlnLnR5cGUgPT09ICdmdW5uZWwnXG4gICAgICA/IGZ1bm5lbChjb25maWcsIGRhdGEsIGRpbWVuc2lvbnMpXG4gICAgICA6IGNvbmZpZy50eXBlID09PSAnZmxvdydcbiAgICAgID8gZmxvd3MoY29uZmlnLCBkYXRhLCBkaW1lbnNpb25zKVxuICAgICAgOiBlbXB0eUNoYXJ0O1xuICB9XG5cbiAgZnVuY3Rpb24gbGluZXMoXG4gICAgY29uZmlnOiBDb25maWdXaXRoRnVsbFNjYWxpbmcsXG4gICAgYWxsRGF0YTogSW5wdXREYXRhLFxuICAgIGRpbWVuc2lvbnM6IERpbWVuc2lvbnMsXG4gICk6IFJlbmRlcmVkQ2hhcnQge1xuICAgIGlmICghd2FybkZsb3dEYXRhKGFsbERhdGEsICdsaW5lJykpIHtcbiAgICAgIHJldHVybiB7IC4uLmVtcHR5Q2hhcnQsIGNoYXJ0RXJyb3I6ICdjb25maWcnIH07XG4gICAgfVxuICAgIGNvbnN0IHsgZGF0YTogaGlkZGVuRGF0YSwgdmlzaWJsZUluZGljZXMgfSA9IGhpZGUoYWxsRGF0YSk7XG4gICAgaWYgKGhpZGRlbkRhdGEudHlwZSA9PT0gJ2xhYmVsZWQnKSB7XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29uc29sZVxuICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICBcIkhlYWRzIHVwISBMYWJlbGVkIHNlcmllcyBhcmVuJ3QgY3VycmVudGx5IHN1cHBvcnRlZCBmb3IgbGluZSBjaGFydHNcIixcbiAgICAgICk7XG4gICAgICByZXR1cm4gZW1wdHlDaGFydDtcbiAgICB9XG4gICAgaWYgKGhhc1N1cHBsZW1lbnRhcnlEYXRhKGhpZGRlbkRhdGEpKSB7XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29uc29sZVxuICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICBcIkhlYWRzIHVwISBTdXBwbGVtZW50YXJ5IHkgdmFsdWVzIGFyZW4ndCBzdXBwb3J0ZWQgZm9yIG5vbi1iYXIgY2hhcnRzXCIsXG4gICAgICApO1xuICAgICAgcmV0dXJuIGVtcHR5Q2hhcnQ7XG4gICAgfVxuICAgIHdhcm5VbnN1cHBvcnRlZFBhdHRlcm5zKGhpZGRlbkRhdGEsIFsnc3RyaXBlZCcsICdkb3RzJ10sICdsaW5lJyk7XG4gICAgLy9UaGlzIGFzc2lnbm1lbnQgbWFrZXMgdHlwZXNjcmlwdCByZWNvZ25pemUgdGhlIGFjdHVhbCB0eXBlIChUaW1lc2VyaWVzRGF0YSlcbiAgICBjb25zdCBkYXRhID0gaGlkZGVuRGF0YTtcblxuICAgIGNvbnN0IHsgZGF0ZUZvcm1hdCwgcGlwZVRyYW5zZm9ybSwgY29sb3JzIH0gPSBnZXRGb3JtYXR0aW5nQW5kQ29sb3JzKFxuICAgICAgYWxsRGF0YSxcbiAgICAgIGRhdGEsXG4gICAgICBjb25maWcsXG4gICAgKTtcblxuICAgIGNvbnN0IGNoYXJ0U2l6aW5nVmFsdWVzID0gZ2V0RnVsbENoYXJ0U2NhbGVWYWx1ZXMoXG4gICAgICBjb25maWcsXG4gICAgICBkYXRhLFxuICAgICAgZGltZW5zaW9ucyxcbiAgICAgIHBpcGVUcmFuc2Zvcm0sXG4gICAgICBkYXRlRm9ybWF0LFxuICAgICk7XG4gICAgaWYgKGNoYXJ0U2l6aW5nVmFsdWVzID09PSBudWxsKSB7XG4gICAgICByZXR1cm4geyAuLi5lbXB0eUNoYXJ0LCBjaGFydEVycm9yOiAnc2l6aW5nJyB9O1xuICAgIH1cblxuICAgIGNvbnN0IHRpY2tDb3VudCA9IGdldEJ1Y2tldFRpY2tDb3VudChjaGFydFNpemluZ1ZhbHVlcyk7XG4gICAgY29uc3QgeFRpY2tzID0gZ2VuZXJhdGVUaW1lc2VyaWVzVGlja3MoXG4gICAgICBkYXRhLFxuICAgICAgY29uZmlnLFxuICAgICAgdGlja0NvdW50LFxuICAgICAgY2hhcnRTaXppbmdWYWx1ZXMsXG4gICAgICBkYXRlRm9ybWF0LFxuICAgICkubWFwKHRpY2sgPT4gdG9YVGljayh0aWNrKSk7XG4gICAgY29uc3QgeFNjYWxlID0gKGluZGV4OiBudW1iZXIpOiBudW1iZXIgPT4ge1xuICAgICAgcmV0dXJuIChcbiAgICAgICAgY2hhcnRTaXppbmdWYWx1ZXMudG90YWxMZWZ0T2Zmc2V0ICsgY2hhcnRTaXppbmdWYWx1ZXMuYnVja2V0R2FwICogaW5kZXhcbiAgICAgICk7XG4gICAgfTtcbiAgICBjb25zdCB7IHNjYWxlLCB0aWNrczogZGF0YVRpY2tzIH0gPSBjYWxjRGF0YUF4aXNTY2FsZXNBbmRUaWNrcyhcbiAgICAgIGRhdGEsXG4gICAgICBwaXBlVHJhbnNmb3JtLFxuICAgICAgY29uZmlnLFxuICAgICAgY2hhcnRTaXppbmdWYWx1ZXMsXG4gICAgKTtcbiAgICBjb25zdCB5VGlja3MgPSBkYXRhVGlja3MubWFwKHRpY2sgPT4gdG9ZVGljayh0aWNrKSk7XG5cbiAgICBjb25zdCBpbmRpY2VzID0gZGF0YS54Lm1hcCgoXywgaSkgPT4gaSk7XG4gICAgY29uc3QgbGluZXMgPVxuICAgICAgZGF0YS54Lmxlbmd0aCA+IDFcbiAgICAgICAgPyBkYXRhLnlzLm1hcCh5ID0+ICh7XG4gICAgICAgICAgICBsaW5lOiBsaW5lPG51bWJlcj4oXG4gICAgICAgICAgICAgIGkgPT4geFNjYWxlKGkpLFxuICAgICAgICAgICAgICBpID0+IHNjYWxlKHkudmFsdWVzW2ldLCB5LmlzU2Vjb25kYXJ5KSxcbiAgICAgICAgICAgICkoaW5kaWNlcyksXG4gICAgICAgICAgICBwYXR0ZXJuOiB5LnBhdHRlcm4sXG4gICAgICAgICAgfSkpXG4gICAgICAgIDogW107XG4gICAgY29uc3QgY2lyY2xlcyA9XG4gICAgICBkYXRhLngubGVuZ3RoID09PSAxXG4gICAgICAgID8gZGF0YS55cy5tYXAoKHlTZXJpZXMsIGkpID0+ICh7XG4gICAgICAgICAgICBjeDogeFNjYWxlKDApLFxuICAgICAgICAgICAgY3k6IHNjYWxlKHlTZXJpZXMudmFsdWVzWzBdLCBjaGVja0lmU2Vjb25kYXJ5KGRhdGEsIGksIDApKSxcbiAgICAgICAgICB9KSlcbiAgICAgICAgOiBbXTtcblxuICAgIGNvbnN0IHlPZmZzZXQgPSBjaGFydFNpemluZ1ZhbHVlcy5kYXRhTGFiZWxQYWRkaW5nO1xuICAgIGNvbnN0IGRhdGFMYWJlbHM6IERhdGFMYWJlbFtdID0gZGF0YS55cy5mbGF0TWFwKCh5LCB5SW5kZXgpID0+IHtcbiAgICAgIGNvbnN0IHN1YkxhYmVsczogRGF0YUxhYmVsW10gPSB5LnZhbHVlcy5tYXAoKHZhbCwgeEluZGV4KSA9PiAoe1xuICAgICAgICBlbGVtZW50VHlwZTogJ2RhdGFMYWJlbCcsXG4gICAgICAgIGxhYmVsOiBwaXBlVHJhbnNmb3JtKHZhbCwgY2hlY2tJZlNlY29uZGFyeShkYXRhLCB5SW5kZXgsIHhJbmRleCkpLFxuICAgICAgICB5UG9zOiBzY2FsZSh2YWwsIGNoZWNrSWZTZWNvbmRhcnkoZGF0YSwgeUluZGV4LCB4SW5kZXgpKSAtIHlPZmZzZXQsXG4gICAgICAgIHhQb3M6IHhTY2FsZSh4SW5kZXgpLFxuICAgICAgICBhbmNob3I6ICdtaWRkbGUnLFxuICAgICAgfSkpO1xuICAgICAgcmV0dXJuIHN1YkxhYmVscztcbiAgICB9KTtcblxuICAgIGZ1bmN0aW9uIGhvdmVyKHBvczoge1xuICAgICAgcmVjdDogRE9NUmVjdDtcbiAgICAgIHg6IG51bWJlcjtcbiAgICAgIHk6IG51bWJlcjtcbiAgICAgIGNvbnRhaW5lclNjcm9sbFg6IG51bWJlcjtcbiAgICAgIGNvbnRhaW5lclNjcm9sbFk6IG51bWJlcjtcbiAgICB9KTogSG92ZXJSZXR1cm4ge1xuICAgICAgY29uc3QgcmVhbFBvc1ggPSBwb3MueCArIHBvcy5jb250YWluZXJTY3JvbGxYO1xuICAgICAgY29uc3QgcmVhbFBvc1kgPSBwb3MueSArIHBvcy5jb250YWluZXJTY3JvbGxZO1xuICAgICAgaWYgKFxuICAgICAgICBjaGFydFNpemluZ1ZhbHVlcyA9PT0gbnVsbCB8fFxuICAgICAgICBnZXRJZkhvdmVyT3V0T2ZCb3VuZHMoXG4gICAgICAgICAgcG9zLngsXG4gICAgICAgICAgcG9zLnksXG4gICAgICAgICAgcmVhbFBvc1gsXG4gICAgICAgICAgcmVhbFBvc1ksXG4gICAgICAgICAgY2hhcnRTaXppbmdWYWx1ZXMsXG4gICAgICAgICAgZGltZW5zaW9ucyxcbiAgICAgICAgKVxuICAgICAgKSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfVxuXG4gICAgICBjb25zdCB4SG92ZXJJbmRpY2VzID0gZ2V0QnVja2V0QW5kQ2x1c3Rlck51bUZvckhvdmVyKFxuICAgICAgICByZWFsUG9zWCxcbiAgICAgICAgY2hhcnRTaXppbmdWYWx1ZXMsXG4gICAgICAgIGRhdGEsXG4gICAgICAgIGNvbmZpZyxcbiAgICAgICAgZGF0YS54Lmxlbmd0aCxcbiAgICAgICk7XG4gICAgICBpZiAoIXhIb3ZlckluZGljZXMpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9XG4gICAgICBjb25zdCB7IGJ1Y2tldE51bTogeEluZGV4IH0gPSB4SG92ZXJJbmRpY2VzO1xuICAgICAgY29uc3QgeCA9IHhTY2FsZSh4SW5kZXgpO1xuICAgICAgY29uc3QgdmlzaWJsZVlJbmRleCA9IGZpbmROZWFyZXN0SW5kZXhXaXRoU2Vjb25kYXJ5KFxuICAgICAgICBkYXRhLnlzLm1hcCgoeSwgaSkgPT4gKHtcbiAgICAgICAgICB2YWx1ZTogeS52YWx1ZXNbeEluZGV4XSxcbiAgICAgICAgICBpc1NlY29uZGFyeTogY2hlY2tJZlNlY29uZGFyeShkYXRhLCBpLCB4SW5kZXgpLFxuICAgICAgICB9KSksXG4gICAgICAgIHBvcy55LFxuICAgICAgICBzY2FsZSxcbiAgICAgICk7XG4gICAgICBjb25zdCB5SW5kZXggPSB2aXNpYmxlSW5kaWNlc1t2aXNpYmxlWUluZGV4XTtcbiAgICAgIGNvbnN0IHlzID0gZGF0YS55cy5tYXAoKHksIGkpID0+XG4gICAgICAgIHNjYWxlKHkudmFsdWVzW3hJbmRleF0sIGNoZWNrSWZTZWNvbmRhcnkoZGF0YSwgaSwgeEluZGV4KSksXG4gICAgICApO1xuXG4gICAgICBjb25zdCBmb3JtYXQgPSAoZGF0ZTogRGF0ZSkgPT5cbiAgICAgICAgZm9ybWF0ZWREYXRlKGNvbmZpZy5kYXRlRm9ybWF0IHx8ICdkYXknLCBkYXRlKTtcblxuICAgICAgLy8gQ2xhbXAgaW4gY2hhcnQtbG9jYWwgY29vcmRpbmF0ZXMgZmlyc3Qgc28gdGhlIHRvb2x0aXAgc3RheXMgd2l0aGluIHRoZVxuICAgICAgLy8gdmlzaWJsZSBjaGFydCBhcmVhLCB0aGVuIHRyYW5zbGF0ZSB0byB2aWV3cG9ydCBjb29yZGluYXRlcyBieSBhZGRpbmdcbiAgICAgIC8vIHBvcy5yZWN0LngveSAod2hpY2ggYXJlIHZpZXdwb3J0LXJlbGF0aXZlIGZyb20gZ2V0Qm91bmRpbmdDbGllbnRSZWN0KS5cbiAgICAgIGNvbnN0IGxvY2FsQW5jaG9yWCA9IHggLSBwb3MuY29udGFpbmVyU2Nyb2xsWDtcbiAgICAgIGNvbnN0IGxvY2FsQW5jaG9yWSA9IHlzW3Zpc2libGVZSW5kZXhdIC0gcG9zLmNvbnRhaW5lclNjcm9sbFk7XG4gICAgICBjb25zdCB7IGFuY2hvclgsIGFuY2hvclkgfSA9IGNoZWNrQW5jaG9yc0FnYWluc3RCb3VuZChcbiAgICAgICAgbG9jYWxBbmNob3JYLFxuICAgICAgICBsb2NhbEFuY2hvclksXG4gICAgICAgIGRpbWVuc2lvbnMsXG4gICAgICApO1xuICAgICAgY29uc3QgYW5jaG9yID0gbmV3IERPTVJlY3QoXG4gICAgICAgIGFuY2hvclggKyBwb3MucmVjdC54LFxuICAgICAgICBhbmNob3JZICsgcG9zLnJlY3QueSxcbiAgICAgICAgU01BTExfUEFERElORyxcbiAgICAgICAgMCxcbiAgICAgICk7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBob3ZlclR5cGU6ICdzdGFuZGFyZCcsXG4gICAgICAgIHgsXG4gICAgICAgIHhJbmRleCxcbiAgICAgICAgeXMsXG4gICAgICAgIHlJbmRleCxcbiAgICAgICAgdmlzaWJsZVlJbmRleCxcbiAgICAgICAgdG9vbHRpcDoge1xuICAgICAgICAgIGFuY2hvcixcbiAgICAgICAgICBkYXRlOiBmb3JtYXQobmV3IERhdGUoZGF0YS54W3hJbmRleF0pKSxcbiAgICAgICAgICBtZXRyaWNzOiBkYXRhLnlzXG4gICAgICAgICAgICAubWFwKCh5LCBpbmRleCkgPT4gKHtcbiAgICAgICAgICAgICAgY29sb3I6IGNvbG9yc1tpbmRleCAlIGNvbG9ycy5sZW5ndGhdLFxuICAgICAgICAgICAgICBsYWJlbDogeS5sYWJlbCxcbiAgICAgICAgICAgICAgcGF0dGVybjogeS5wYXR0ZXJuLFxuICAgICAgICAgICAgICB2YWx1ZTpcbiAgICAgICAgICAgICAgICBwaXBlVHJhbnNmb3JtKFxuICAgICAgICAgICAgICAgICAgeS52YWx1ZXNbeEluZGV4XSxcbiAgICAgICAgICAgICAgICAgIGNoZWNrSWZTZWNvbmRhcnkoZGF0YSwgaW5kZXgsIHhJbmRleCksXG4gICAgICAgICAgICAgICAgICB0cnVlLFxuICAgICAgICAgICAgICAgICkgPz8gJy0nLFxuICAgICAgICAgICAgfSkpXG4gICAgICAgICAgICAuZmlsdGVyKChfLCBpKSA9PiBjb25maWcuZ3JvdXBlZFRvb2x0aXAgfHwgaSA9PT0gdmlzaWJsZVlJbmRleCksXG4gICAgICAgIH0sXG4gICAgICB9O1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBjaGFydFdpZHRoOiBjaGFydFNpemluZ1ZhbHVlcy50b3RhbFdpZHRoLFxuICAgICAgY2hhcnRIZWlnaHQ6IGNoYXJ0U2l6aW5nVmFsdWVzLnRvdGFsSGVpZ2h0LFxuICAgICAgY2hhcnRTaXppbmdWYWx1ZXMsXG4gICAgICB4VGlja3MsXG4gICAgICB5VGlja3MsXG4gICAgICBjb2xvcnMsXG4gICAgICBsaW5lcyxcbiAgICAgIGNpcmNsZXMsXG4gICAgICBob3ZlcixcbiAgICAgIGJhcnM6IFtdLFxuICAgICAgYXJlYXM6IFtdLFxuICAgICAgYXJjczogW10sXG4gICAgICBob3Jpem9udGFsQmFyczogW10sXG4gICAgICBkYXRhTGFiZWxzLFxuICAgICAgd2F0ZXJmYWxsTGluZXM6IFtdLFxuICAgICAgZ3JhZGllbnRzOiBbXSxcbiAgICAgIGZsb3dDb25uZWN0aW9uczogW10sXG4gICAgICBob3Jpem9udGFsQ29udGFpbmVyU2NhbGU6IGNoYXJ0U2l6aW5nVmFsdWVzLmhvcml6b250YWxDb250YWluZXJTY2FsZSxcbiAgICAgIHZlcnRpY2FsQ29udGFpbmVyU2NhbGU6IGNoYXJ0U2l6aW5nVmFsdWVzLnZlcnRpY2FsQ29udGFpbmVyU2NhbGUsXG4gICAgICBjaGFydEVycm9yOiBudWxsLFxuICAgIH07XG4gIH1cblxuICBmdW5jdGlvbiBhcmVhcyhcbiAgICBjb25maWc6IENvbmZpZ1dpdGhGdWxsU2NhbGluZyxcbiAgICBhbGxEYXRhOiBJbnB1dERhdGEsXG4gICAgZGltZW5zaW9uczogRGltZW5zaW9ucyxcbiAgKTogUmVuZGVyZWRDaGFydCB7XG4gICAgaWYgKCF3YXJuRmxvd0RhdGEoYWxsRGF0YSwgJ2FyZWEnKSkge1xuICAgICAgcmV0dXJuIHsgLi4uZW1wdHlDaGFydCwgY2hhcnRFcnJvcjogJ2NvbmZpZycgfTtcbiAgICB9XG4gICAgY29uc3QgeyBkYXRhOiB1bmNoZWNrZWREYXRhLCB2aXNpYmxlSW5kaWNlcyB9ID0gaGlkZShhbGxEYXRhKTtcbiAgICBpZiAodW5jaGVja2VkRGF0YS50eXBlID09PSAnbGFiZWxlZCcpIHtcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgIFwiSGVhZHMgdXAhIExhYmVsZWQgc2VyaWVzIGFyZW4ndCBjdXJyZW50bHkgc3VwcG9ydGVkIGZvciBhcmVhIGNoYXJ0c1wiLFxuICAgICAgKTtcbiAgICAgIHJldHVybiBlbXB0eUNoYXJ0O1xuICAgIH1cbiAgICBpZiAoY29uZmlnLnNob3dEYXRhTGFiZWxzID09PSB0cnVlKSB7XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29uc29sZVxuICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICBcIkhlYWRzIHVwISBEYXRhIGxhYmVscyBhcmVuJ3Qgc3VwcG9ydGVkIGZvciBhbnkgc3RhY2tlZCBjaGFydCB0eXBlXCIsXG4gICAgICApO1xuICAgICAgcmV0dXJuIGVtcHR5Q2hhcnQ7XG4gICAgfVxuICAgIGlmIChoYXNTdXBwbGVtZW50YXJ5RGF0YSh1bmNoZWNrZWREYXRhKSkge1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgXCJIZWFkcyB1cCEgU3VwcGxlbWVudGFyeSB5IHZhbHVlcyBhcmVuJ3Qgc3VwcG9ydGVkIGZvciBub24tYmFyIGNoYXJ0c1wiLFxuICAgICAgKTtcbiAgICAgIHJldHVybiBlbXB0eUNoYXJ0O1xuICAgIH1cbiAgICB3YXJuVW5zdXBwb3J0ZWRQYXR0ZXJucyh1bmNoZWNrZWREYXRhLCBbJ3N0cmlwZWQnXSwgJ2FyZWEnKTtcbiAgICAvL1RoaXMgYXNzaWdubWVudCBtYWtlcyB0eXBlc2NyaXB0IHJlY29nbml6ZSB0aGUgYWN0dWFsIHR5cGUgKFRpbWVzZXJpZXNEYXRhKVxuICAgIGNvbnN0IGRhdGEgPSB1bmNoZWNrZWREYXRhO1xuXG4gICAgY29uc3QgeyBkYXRlRm9ybWF0LCBwaXBlVHJhbnNmb3JtLCBjb2xvcnMgfSA9IGdldEZvcm1hdHRpbmdBbmRDb2xvcnMoXG4gICAgICBhbGxEYXRhLFxuICAgICAgZGF0YSxcbiAgICAgIGNvbmZpZyxcbiAgICApO1xuICAgIGNvbnN0IGNoYXJ0U2l6aW5nVmFsdWVzID0gZ2V0RnVsbENoYXJ0U2NhbGVWYWx1ZXMoXG4gICAgICBjb25maWcsXG4gICAgICBkYXRhLFxuICAgICAgZGltZW5zaW9ucyxcbiAgICAgIHBpcGVUcmFuc2Zvcm0sXG4gICAgICBkYXRlRm9ybWF0LFxuICAgICk7XG4gICAgaWYgKGNoYXJ0U2l6aW5nVmFsdWVzID09PSBudWxsKSB7XG4gICAgICByZXR1cm4geyAuLi5lbXB0eUNoYXJ0LCBjaGFydEVycm9yOiAnc2l6aW5nJyB9O1xuICAgIH1cblxuICAgIGNvbnN0IHRpY2tDb3VudCA9IGdldEJ1Y2tldFRpY2tDb3VudChjaGFydFNpemluZ1ZhbHVlcyk7XG4gICAgY29uc3QgeFRpY2tzID0gZ2VuZXJhdGVUaW1lc2VyaWVzVGlja3MoXG4gICAgICBkYXRhLFxuICAgICAgY29uZmlnLFxuICAgICAgdGlja0NvdW50LFxuICAgICAgY2hhcnRTaXppbmdWYWx1ZXMsXG4gICAgICBkYXRlRm9ybWF0LFxuICAgICkubWFwKHRpY2sgPT4gdG9YVGljayh0aWNrKSk7XG4gICAgY29uc3QgeFNjYWxlID0gKGluZGV4OiBudW1iZXIpOiBudW1iZXIgPT4ge1xuICAgICAgcmV0dXJuIChcbiAgICAgICAgY2hhcnRTaXppbmdWYWx1ZXMudG90YWxMZWZ0T2Zmc2V0ICsgY2hhcnRTaXppbmdWYWx1ZXMuYnVja2V0R2FwICogaW5kZXhcbiAgICAgICk7XG4gICAgfTtcbiAgICBjb25zdCB7IHNjYWxlLCB0aWNrczogZGF0YVRpY2tzIH0gPSBjYWxjRGF0YUF4aXNTY2FsZXNBbmRUaWNrcyhcbiAgICAgIGRhdGEsXG4gICAgICBwaXBlVHJhbnNmb3JtLFxuICAgICAgY29uZmlnLFxuICAgICAgY2hhcnRTaXppbmdWYWx1ZXMsXG4gICAgKTtcbiAgICBjb25zdCB5VGlja3MgPSBkYXRhVGlja3MubWFwKHRpY2sgPT4gdG9ZVGljayh0aWNrKSk7XG4gICAgY29uc3QgemVyb0F4aXNQb3NWYWwgPSBzY2FsZSgwLCB0cnVlKTtcblxuICAgIGNvbnN0IGluZGljZXMgPSBkYXRhLngubWFwKChfLCBpKSA9PiBpKTtcbiAgICBjb25zdCBhcmVhcyA9IGRhdGEueXMubWFwKCh5LCB5SW5kZXgpID0+ICh7XG4gICAgICBwYXR0ZXJuOiB5LnBhdHRlcm4sXG4gICAgICBhcmVhOiBhcmVhPG51bWJlcj4oXG4gICAgICAgIGkgPT4geFNjYWxlKGkpLFxuICAgICAgICBpID0+IGdldEJhcllJbmZvKGRhdGEsIGNvbmZpZywgeUluZGV4LCBpLCBzY2FsZSkueVZhbHVlLFxuICAgICAgICBpID0+XG4gICAgICAgICAgZ2V0QmFyWUluZm8oZGF0YSwgY29uZmlnLCB5SW5kZXgsIGksIHNjYWxlKS55VmFsdWUgK1xuICAgICAgICAgIGdldEJhcllJbmZvKGRhdGEsIGNvbmZpZywgeUluZGV4LCBpLCBzY2FsZSkuaGVpZ2h0LFxuICAgICAgKShpbmRpY2VzKSxcbiAgICB9KSk7XG5cbiAgICBmdW5jdGlvbiBob3Zlcihwb3M6IHtcbiAgICAgIHJlY3Q6IERPTVJlY3Q7XG4gICAgICB4OiBudW1iZXI7XG4gICAgICB5OiBudW1iZXI7XG4gICAgICBjb250YWluZXJTY3JvbGxYOiBudW1iZXI7XG4gICAgICBjb250YWluZXJTY3JvbGxZOiBudW1iZXI7XG4gICAgfSk6IEhvdmVyUmV0dXJuIHtcbiAgICAgIGNvbnN0IHJlYWxQb3NYID0gcG9zLnggKyBwb3MuY29udGFpbmVyU2Nyb2xsWDtcbiAgICAgIGNvbnN0IHJlYWxQb3NZID0gcG9zLnkgKyBwb3MuY29udGFpbmVyU2Nyb2xsWTtcbiAgICAgIGlmIChcbiAgICAgICAgY2hhcnRTaXppbmdWYWx1ZXMgPT09IG51bGwgfHxcbiAgICAgICAgZ2V0SWZIb3Zlck91dE9mQm91bmRzKFxuICAgICAgICAgIHBvcy54LFxuICAgICAgICAgIHBvcy55LFxuICAgICAgICAgIHJlYWxQb3NYLFxuICAgICAgICAgIHJlYWxQb3NZLFxuICAgICAgICAgIGNoYXJ0U2l6aW5nVmFsdWVzLFxuICAgICAgICAgIGRpbWVuc2lvbnMsXG4gICAgICAgIClcbiAgICAgICkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cblxuICAgICAgY29uc3QgeEhvdmVySW5kaWNlcyA9IGdldEJ1Y2tldEFuZENsdXN0ZXJOdW1Gb3JIb3ZlcihcbiAgICAgICAgcmVhbFBvc1gsXG4gICAgICAgIGNoYXJ0U2l6aW5nVmFsdWVzLFxuICAgICAgICBkYXRhLFxuICAgICAgICBjb25maWcsXG4gICAgICAgIGRhdGEueC5sZW5ndGgsXG4gICAgICApO1xuICAgICAgaWYgKCF4SG92ZXJJbmRpY2VzKSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfVxuICAgICAgY29uc3QgeyBidWNrZXROdW06IHhJbmRleCB9ID0geEhvdmVySW5kaWNlcztcbiAgICAgIGNvbnN0IHggPSB4U2NhbGUoeEluZGV4KTtcbiAgICAgIGNvbnN0IGZ1bGxZcyA9IGRhdGEueXMubWFwKChfLCBtYXBZSW5kZXgpID0+XG4gICAgICAgIGdldEJhcllJbmZvKGRhdGEsIGNvbmZpZywgbWFwWUluZGV4LCB4SW5kZXgsIHNjYWxlKSxcbiAgICAgICk7XG4gICAgICBjb25zdCB5cyA9IGZ1bGxZcy5tYXAoeSA9PiB5LnlWYWx1ZSk7XG4gICAgICAvL1RoaXMgaXMgdGhlIHlzIGFycmF5LCBidXQgc2hpZnRlZCBzbyB0aGF0IHRoZSB5IHBvc2l0aW9uIGZvciBuZWdhdGl2ZSB2YWx1ZXMgaXMgYXdheSBmcm9tIHRoZSBheGlzIChmb3IgdGhlIGhvdmVyIGNpcmNsZXMpXG4gICAgICBjb25zdCBzaGlmdGVkWXMgPSBmdWxsWXMubWFwKHkgPT4ge1xuICAgICAgICBpZiAoeS55VmFsdWUgPj0gemVyb0F4aXNQb3NWYWwpIHtcbiAgICAgICAgICByZXR1cm4geS55VmFsdWUgKyB5LmhlaWdodDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4geS55VmFsdWU7XG4gICAgICB9KTtcbiAgICAgIGNvbnN0IHlQb3NTaWduID0gemVyb0F4aXNQb3NWYWwgLSBwb3MueTtcbiAgICAgIGxldCB2aXNpYmxlWUluZGV4ID0gLTE7XG4gICAgICBpZiAoeVBvc1NpZ24gPCAwICYmIGRhdGEueXMuZmluZCh5ID0+IHkudmFsdWVzLmZpbmQodmFsID0+IHZhbCA8IDApKSkge1xuICAgICAgICBmb3IgKGxldCBpID0geXMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgICBpZiAoeXNbaV0gPj0gemVyb0F4aXNQb3NWYWwgJiYgeXNbaV0gPCBwb3MueSkge1xuICAgICAgICAgICAgdmlzaWJsZVlJbmRleCA9IGk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgeXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICBpZiAoeXNbaV0gPD0gemVyb0F4aXNQb3NWYWwgJiYgeXNbaV0gPCBwb3MueSkge1xuICAgICAgICAgICAgdmlzaWJsZVlJbmRleCA9IGk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGlmICh2aXNpYmxlWUluZGV4ID09PSAtMSkge1xuICAgICAgICBpZiAocG9zLnkgPD0gemVyb0F4aXNQb3NWYWwpIHtcbiAgICAgICAgICB2aXNpYmxlWUluZGV4ID0geXMuaW5kZXhPZihNYXRoLm1pbiguLi55cykpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHZpc2libGVZSW5kZXggPSB5cy5pbmRleE9mKE1hdGgubWF4KC4uLnlzKSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGNvbnN0IHlJbmRleCA9IHZpc2libGVJbmRpY2VzW3Zpc2libGVZSW5kZXhdO1xuICAgICAgY29uc3QgbG9jYWxBbmNob3JYID0geCAtIHBvcy5jb250YWluZXJTY3JvbGxYO1xuICAgICAgY29uc3QgbG9jYWxBbmNob3JZID0geXNbdmlzaWJsZVlJbmRleF0gLSBwb3MuY29udGFpbmVyU2Nyb2xsWTtcbiAgICAgIGNvbnN0IHsgYW5jaG9yWCwgYW5jaG9yWSB9ID0gY2hlY2tBbmNob3JzQWdhaW5zdEJvdW5kKFxuICAgICAgICBsb2NhbEFuY2hvclgsXG4gICAgICAgIGxvY2FsQW5jaG9yWSxcbiAgICAgICAgZGltZW5zaW9ucyxcbiAgICAgICk7XG4gICAgICBjb25zdCBhbmNob3IgPSBuZXcgRE9NUmVjdChcbiAgICAgICAgYW5jaG9yWCArIHBvcy5yZWN0LngsXG4gICAgICAgIGFuY2hvclkgKyBwb3MucmVjdC55LFxuICAgICAgICBTTUFMTF9QQURESU5HLFxuICAgICAgICAwLFxuICAgICAgKTtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGhvdmVyVHlwZTogJ3N0YW5kYXJkJyxcbiAgICAgICAgeCxcbiAgICAgICAgeEluZGV4LFxuICAgICAgICB5czogc2hpZnRlZFlzLFxuICAgICAgICB5SW5kZXgsXG4gICAgICAgIHZpc2libGVZSW5kZXgsXG4gICAgICAgIHRvb2x0aXA6IHtcbiAgICAgICAgICBhbmNob3IsXG4gICAgICAgICAgZGF0ZTogdXRjRm9ybWF0KCclQiAlZCwgJVknKShuZXcgRGF0ZShkYXRhLnhbeEluZGV4XSkpLFxuICAgICAgICAgIG1ldHJpY3M6IGRhdGEueXNcbiAgICAgICAgICAgIC5tYXAoKHksIGluZGV4KSA9PiAoe1xuICAgICAgICAgICAgICBjb2xvcjogY29sb3JzW2luZGV4ICUgY29sb3JzLmxlbmd0aF0sXG4gICAgICAgICAgICAgIGxhYmVsOiB5LmxhYmVsLFxuICAgICAgICAgICAgICBwYXR0ZXJuOiB5LnBhdHRlcm4sXG4gICAgICAgICAgICAgIHZhbHVlOiBwaXBlVHJhbnNmb3JtKFxuICAgICAgICAgICAgICAgIHkudmFsdWVzW3hJbmRleF0sXG4gICAgICAgICAgICAgICAgY2hlY2tJZlNlY29uZGFyeShkYXRhLCBpbmRleCwgeEluZGV4KSxcbiAgICAgICAgICAgICAgICB0cnVlLFxuICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgfSkpXG4gICAgICAgICAgICAuZmlsdGVyKChfLCBpKSA9PiBjb25maWcuZ3JvdXBlZFRvb2x0aXAgfHwgaSA9PT0gdmlzaWJsZVlJbmRleCksXG4gICAgICAgIH0sXG4gICAgICB9O1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBjaGFydFdpZHRoOiBjaGFydFNpemluZ1ZhbHVlcy50b3RhbFdpZHRoLFxuICAgICAgY2hhcnRIZWlnaHQ6IGNoYXJ0U2l6aW5nVmFsdWVzLnRvdGFsSGVpZ2h0LFxuICAgICAgY2hhcnRTaXppbmdWYWx1ZXMsXG4gICAgICB4VGlja3MsXG4gICAgICB5VGlja3MsXG4gICAgICBjb2xvcnMsXG4gICAgICBhcmVhcyxcbiAgICAgIGxpbmVzOiBbXSxcbiAgICAgIGNpcmNsZXM6IFtdLFxuICAgICAgaG92ZXIsXG4gICAgICBiYXJzOiBbXSxcbiAgICAgIGFyY3M6IFtdLFxuICAgICAgaG9yaXpvbnRhbEJhcnM6IFtdLFxuICAgICAgZGF0YUxhYmVsczogW10sXG4gICAgICB3YXRlcmZhbGxMaW5lczogW10sXG4gICAgICBncmFkaWVudHM6IFtdLFxuICAgICAgZmxvd0Nvbm5lY3Rpb25zOiBbXSxcbiAgICAgIGhvcml6b250YWxDb250YWluZXJTY2FsZTogY2hhcnRTaXppbmdWYWx1ZXMuaG9yaXpvbnRhbENvbnRhaW5lclNjYWxlLFxuICAgICAgdmVydGljYWxDb250YWluZXJTY2FsZTogY2hhcnRTaXppbmdWYWx1ZXMudmVydGljYWxDb250YWluZXJTY2FsZSxcbiAgICAgIGNoYXJ0RXJyb3I6IG51bGwsXG4gICAgfTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGJhcnMoXG4gICAgY29uZmlnOiBDb25maWdXaXRoRnVsbFNjYWxpbmcsXG4gICAgYWxsRGF0YTogSW5wdXREYXRhLFxuICAgIGRpbWVuc2lvbnM6IERpbWVuc2lvbnMsXG4gICk6IFJlbmRlcmVkQ2hhcnQge1xuICAgIGlmICghd2FybkZsb3dEYXRhKGFsbERhdGEsICdiYXInKSkge1xuICAgICAgcmV0dXJuIHsgLi4uZW1wdHlDaGFydCwgY2hhcnRFcnJvcjogJ2NvbmZpZycgfTtcbiAgICB9XG4gICAgY29uc3QgeyBkYXRhLCB2aXNpYmxlSW5kaWNlcywgdmlzaWJsZVN1cHBJbmRpY2VzIH0gPSBoaWRlKGFsbERhdGEpO1xuICAgIGlmIChcbiAgICAgIGNvbmZpZy5zaG93RGF0YUxhYmVscyA9PT0gdHJ1ZSAmJlxuICAgICAgaXNTdGFja2VkRGF0YShjb25maWcpICYmXG4gICAgICAhaXNHcm91cGluZ1R5cGVFeGNlcHRpb24oZGF0YSwgY29uZmlnKVxuICAgICkge1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgXCJIZWFkcyB1cCEgRGF0YSBsYWJlbHMgYXJlbid0IHN1cHBvcnRlZCBmb3IgYW55IHN0YWNrZWQgY2hhcnQgdHlwZVwiLFxuICAgICAgKTtcbiAgICAgIHJldHVybiBlbXB0eUNoYXJ0O1xuICAgIH1cbiAgICBpZiAoXG4gICAgICBoYXNTdXBwbGVtZW50YXJ5RGF0YShkYXRhKSAmJlxuICAgICAgaXNDbHVzdGVyZWREYXRhKGRhdGEsIGNvbmZpZywgZmFsc2UpICYmXG4gICAgICAhaXNHcm91cGluZ1R5cGVFeGNlcHRpb24oZGF0YSwgY29uZmlnKVxuICAgICkge1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgXCJIZWFkcyB1cCEgU3VwcGxlbWVudGFyeSB5IHZhbHVlcyBhcmVuJ3Qgc3VwcG9ydGVkIGZvciBjbHVzdGVyZWQgZGF0YSAoanVzdCB1c2UgYW5vdGhlciBub3JtYWwgeSBzZXJpZXMpXCIsXG4gICAgICApO1xuICAgICAgcmV0dXJuIGVtcHR5Q2hhcnQ7XG4gICAgfVxuICAgIHJldHVybiBiYXJzSGVscGVyKFxuICAgICAgY29uZmlnLFxuICAgICAgYWxsRGF0YSxcbiAgICAgIGRhdGEsXG4gICAgICB2aXNpYmxlSW5kaWNlcyxcbiAgICAgIHZpc2libGVTdXBwSW5kaWNlcyxcbiAgICAgIGRpbWVuc2lvbnMsXG4gICAgICBmYWxzZSxcbiAgICAgIGZhbHNlLFxuICAgICk7XG4gIH1cblxuICBmdW5jdGlvbiBmdW5uZWwoXG4gICAgY29uZmlnOiBDb25maWdXaXRoRnVsbFNjYWxpbmcsXG4gICAgYWxsRGF0YTogSW5wdXREYXRhLFxuICAgIGRpbWVuc2lvbnM6IERpbWVuc2lvbnMsXG4gICk6IFJlbmRlcmVkQ2hhcnQge1xuICAgIGlmICghd2FybkZsb3dEYXRhKGFsbERhdGEsICdmdW5uZWwnKSkge1xuICAgICAgcmV0dXJuIHsgLi4uZW1wdHlDaGFydCwgY2hhcnRFcnJvcjogJ2NvbmZpZycgfTtcbiAgICB9XG4gICAgY29uc3QgeyBkYXRhLCB2aXNpYmxlSW5kaWNlcywgdmlzaWJsZVN1cHBJbmRpY2VzIH0gPSBoaWRlKGFsbERhdGEpO1xuICAgIHJldHVybiBiYXJzSGVscGVyKFxuICAgICAgY29uZmlnLFxuICAgICAgYWxsRGF0YSxcbiAgICAgIGRhdGEsXG4gICAgICB2aXNpYmxlSW5kaWNlcyxcbiAgICAgIHZpc2libGVTdXBwSW5kaWNlcyxcbiAgICAgIGRpbWVuc2lvbnMsXG4gICAgICB0cnVlLFxuICAgICAgZmFsc2UsXG4gICAgKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHdhdGVyZmFsbChcbiAgICBjb25maWc6IENvbmZpZ1dpdGhGdWxsU2NhbGluZyxcbiAgICBhbGxEYXRhOiBJbnB1dERhdGEsXG4gICAgZGltZW5zaW9uczogRGltZW5zaW9ucyxcbiAgKTogUmVuZGVyZWRDaGFydCB7XG4gICAgaWYgKCF3YXJuRmxvd0RhdGEoYWxsRGF0YSwgJ3dhdGVyZmFsbCcpKSB7XG4gICAgICByZXR1cm4geyAuLi5lbXB0eUNoYXJ0LCBjaGFydEVycm9yOiAnY29uZmlnJyB9O1xuICAgIH1cbiAgICBjb25zdCB7IGRhdGE6IHVuY2hlY2tlZERhdGEsIHZpc2libGVJbmRpY2VzIH0gPSBoaWRlKGFsbERhdGEpO1xuICAgIGlmIChoYXNTdXBwbGVtZW50YXJ5RGF0YSh1bmNoZWNrZWREYXRhKSkge1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgXCJIZWFkcyB1cCEgU3VwcGxlbWVudGFyeSB5IHZhbHVlcyBhcmVuJ3Qgc3VwcG9ydGVkIGZvciBub24tYmFyIGNoYXJ0c1wiLFxuICAgICAgKTtcbiAgICAgIHJldHVybiBlbXB0eUNoYXJ0O1xuICAgIH1cbiAgICBpZiAoY29uZmlnLnNlY29uZGFyeVZhbHVlVHlwZSkge1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgJ0hlYWRzIHVwISBXYXRlcmZhbGwgY2hhcnRzIGRvIG5vdCBjdXJyZW50bHkgaGF2ZSB0d28tYXhpcyBzdXBwb3J0JyxcbiAgICAgICk7XG4gICAgICByZXR1cm4gZW1wdHlDaGFydDtcbiAgICB9XG4gICAgd2FyblVuc3VwcG9ydGVkUGF0dGVybnModW5jaGVja2VkRGF0YSwgW10sICd3YXRlcmZhbGwnKTtcblxuICAgIHJldHVybiBiYXJzSGVscGVyKFxuICAgICAgY29uZmlnLFxuICAgICAgYWxsRGF0YSxcbiAgICAgIHVuY2hlY2tlZERhdGEsXG4gICAgICB2aXNpYmxlSW5kaWNlcyxcbiAgICAgIFtdLFxuICAgICAgZGltZW5zaW9ucyxcbiAgICAgIGZhbHNlLFxuICAgICAgdHJ1ZSxcbiAgICApO1xuICB9XG5cbiAgZnVuY3Rpb24gYmFyc0hlbHBlcihcbiAgICBjb25maWc6IENvbmZpZ1dpdGhGdWxsU2NhbGluZyxcbiAgICBhbGxEYXRhOiBOb25GbG93RGF0YSxcbiAgICB1bmNoZWNrZWREYXRhOiBOb25GbG93RGF0YSxcbiAgICB2aXNpYmxlSW5kaWNlczogbnVtYmVyW10sXG4gICAgdmlzaWJsZVN1cHBJbmRpY2VzOiBudW1iZXJbXSxcbiAgICBkaW1lbnNpb25zOiBEaW1lbnNpb25zLFxuICAgIGlzRnVubmVsOiBib29sZWFuLFxuICAgIGlzV2F0ZXJmYWxsOiBib29sZWFuLFxuICApOiBSZW5kZXJlZENoYXJ0IHtcbiAgICBjb25zdCB7IGRhdGVGb3JtYXQsIHBpcGVUcmFuc2Zvcm0sIGNvbG9ySW5kaWNlcywgY29sb3JzIH0gPVxuICAgICAgZ2V0Rm9ybWF0dGluZ0FuZENvbG9ycyhhbGxEYXRhLCB1bmNoZWNrZWREYXRhLCBjb25maWcpO1xuICAgIGNvbnN0IHdhdGVyZmFsbERhdGEgPSB3YXRlcmZhbGxUcmFuc2Zvcm0odW5jaGVja2VkRGF0YSwgaXNXYXRlcmZhbGwpO1xuICAgIGNvbnN0IGRhdGEgPSBpc1dhdGVyZmFsbCA/IHdhdGVyZmFsbERhdGEuZGF0YSA6IHVuY2hlY2tlZERhdGE7XG5cbiAgICBjb25zdCBjaGFydFNpemluZ1ZhbHVlcyA9IGdldEZ1bGxDaGFydFNjYWxlVmFsdWVzKFxuICAgICAgY29uZmlnLFxuICAgICAgZGF0YSxcbiAgICAgIGRpbWVuc2lvbnMsXG4gICAgICBwaXBlVHJhbnNmb3JtLFxuICAgICAgZGF0ZUZvcm1hdCxcbiAgICApO1xuICAgIGlmIChjaGFydFNpemluZ1ZhbHVlcyA9PT0gbnVsbCkge1xuICAgICAgcmV0dXJuIHsgLi4uZW1wdHlDaGFydCwgY2hhcnRFcnJvcjogJ3NpemluZycgfTtcbiAgICB9XG5cbiAgICBjb25zdCB0aWNrQ291bnQgPSBnZXRCdWNrZXRUaWNrQ291bnQoY2hhcnRTaXppbmdWYWx1ZXMpO1xuICAgIGNvbnN0IHhUaWNrcyA9IChcbiAgICAgIGRhdGEudHlwZSA9PT0gJ2xhYmVsZWQnXG4gICAgICAgID8gZ2VuZXJhdGVMYWJlbGxlZFRpY2tzKGRhdGEsIGNvbmZpZywgdGlja0NvdW50LCBjaGFydFNpemluZ1ZhbHVlcylcbiAgICAgICAgOiBnZW5lcmF0ZVRpbWVzZXJpZXNUaWNrcyhcbiAgICAgICAgICAgIGRhdGEsXG4gICAgICAgICAgICBjb25maWcsXG4gICAgICAgICAgICB0aWNrQ291bnQsXG4gICAgICAgICAgICBjaGFydFNpemluZ1ZhbHVlcyxcbiAgICAgICAgICAgIGRhdGVGb3JtYXQsXG4gICAgICAgICAgKVxuICAgICkubWFwKHRpY2sgPT4gdG9YVGljayh0aWNrKSk7XG4gICAgY29uc3QgeyBzY2FsZSwgdGlja3M6IGRhdGFUaWNrcyB9ID0gY2FsY0RhdGFBeGlzU2NhbGVzQW5kVGlja3MoXG4gICAgICBkYXRhLFxuICAgICAgcGlwZVRyYW5zZm9ybSxcbiAgICAgIGNvbmZpZyxcbiAgICAgIGNoYXJ0U2l6aW5nVmFsdWVzLFxuICAgICk7XG4gICAgY29uc3QgeVRpY2tzID0gZGF0YVRpY2tzLm1hcCh0aWNrID0+IHRvWVRpY2sodGljaykpO1xuICAgIGNvbnN0IHplcm9BeGlzUG9zVmFsID0gc2NhbGUoMCwgdHJ1ZSk7XG5cbiAgICBjb25zdCBncmFkaWVudHM6IFJlY3RbXVtdID0gW107XG4gICAgY29uc3QgYmFyczogUmVjdFtdW10gPSBkYXRhLnlzLm1hcCgoeSwgeUluZGV4KSA9PiB7XG4gICAgICBjb25zdCBpbmRTZXJpZXNHcmFkaWVudHM6IFJlY3RbXSA9IFtdO1xuICAgICAgY29uc3QgaW5kU2VyaWVzQmFycyA9IHkudmFsdWVzLm1hcCgoXywgaW5kZXgpID0+IHtcbiAgICAgICAgY29uc3QgeyB5VmFsdWUsIGhlaWdodCB9ID0gZ2V0QmFyWUluZm8oXG4gICAgICAgICAgZGF0YSxcbiAgICAgICAgICBjb25maWcsXG4gICAgICAgICAgeUluZGV4LFxuICAgICAgICAgIGluZGV4LFxuICAgICAgICAgIHNjYWxlLFxuICAgICAgICApO1xuICAgICAgICBjb25zdCB4VmFsdWUgPSBjYWxjdWxhdGVCYXJQb3NpdGlvbihcbiAgICAgICAgICBkYXRhLFxuICAgICAgICAgIGNvbmZpZyxcbiAgICAgICAgICBjaGFydFNpemluZ1ZhbHVlcyxcbiAgICAgICAgICBpbmRleCxcbiAgICAgICAgICBpc0NsdXN0ZXJlZERhdGEoZGF0YSwgY29uZmlnLCBmYWxzZSkgPyB5SW5kZXggOiAwLFxuICAgICAgICApO1xuICAgICAgICBpZiAoaXNGdW5uZWwpIHtcbiAgICAgICAgICAvL1RoZSBlbXB0eSBncmFkaWVudCBzdGlsbCBuZWVkcyB0byBiZSBpbnNlcnRlZCB0byBrZWVwIGRhdGEgYWxpZ25lZFxuICAgICAgICAgIGlmIChpbmRleCA9PT0gMCkge1xuICAgICAgICAgICAgaW5kU2VyaWVzR3JhZGllbnRzLnB1c2goe1xuICAgICAgICAgICAgICBlbGVtZW50VHlwZTogJ3JlY3QnLFxuICAgICAgICAgICAgICB4OiAwLFxuICAgICAgICAgICAgICB5OiAwLFxuICAgICAgICAgICAgICB3aWR0aDogMCxcbiAgICAgICAgICAgICAgaGVpZ2h0OiAwLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnN0IHsgeVZhbHVlOiBwcmV2QmFyWVZhbCB9ID0gZ2V0QmFyWUluZm8oXG4gICAgICAgICAgICAgIGRhdGEsXG4gICAgICAgICAgICAgIGNvbmZpZyxcbiAgICAgICAgICAgICAgeUluZGV4LFxuICAgICAgICAgICAgICBpbmRleCAtIDEsXG4gICAgICAgICAgICAgIHNjYWxlLFxuICAgICAgICAgICAgKTtcblxuICAgICAgICAgICAgaW5kU2VyaWVzR3JhZGllbnRzLnB1c2goe1xuICAgICAgICAgICAgICBlbGVtZW50VHlwZTogJ3JlY3QnLFxuICAgICAgICAgICAgICB4OiB4VmFsdWUsXG4gICAgICAgICAgICAgIHk6IHByZXZCYXJZVmFsLFxuICAgICAgICAgICAgICB3aWR0aDogY2hhcnRTaXppbmdWYWx1ZXMuYmFyU2l6ZSxcbiAgICAgICAgICAgICAgaGVpZ2h0OiBNYXRoLm1heCh5VmFsdWUgLSBwcmV2QmFyWVZhbCwgMCksXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBiYXI6IFJlY3QgPSB7XG4gICAgICAgICAgZWxlbWVudFR5cGU6ICdyZWN0JyxcbiAgICAgICAgICB4OiB4VmFsdWUsXG4gICAgICAgICAgeTogeVZhbHVlLFxuICAgICAgICAgIHdpZHRoOiBjaGFydFNpemluZ1ZhbHVlcy5iYXJTaXplLFxuICAgICAgICAgIGhlaWdodCxcbiAgICAgICAgICBvZmZzZXQ6IDAsXG4gICAgICAgICAgcGF0dGVybjogeS5wYXR0ZXJuLFxuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gYmFyO1xuICAgICAgfSk7XG4gICAgICBncmFkaWVudHMucHVzaChpbmRTZXJpZXNHcmFkaWVudHMpO1xuICAgICAgcmV0dXJuIGluZFNlcmllc0JhcnM7XG4gICAgfSk7XG4gICAgbGV0IHN1cHBCYXJzOiBSZWN0W11bXSA9IFtdO1xuICAgIGlmIChoYXNTdXBwbGVtZW50YXJ5RGF0YShkYXRhKSkge1xuICAgICAgc3VwcEJhcnMgPSBkYXRhLnN1cHBsZW1lbnRhcnlZcy5tYXAoKHksIHlJbmRleCkgPT5cbiAgICAgICAgeS52YWx1ZXMubWFwKChfLCBpbmRleCkgPT4ge1xuICAgICAgICAgIGNvbnN0IHsgeVZhbHVlLCBoZWlnaHQgfSA9IGdldEJhcllJbmZvKFxuICAgICAgICAgICAgZGF0YSxcbiAgICAgICAgICAgIGNvbmZpZyxcbiAgICAgICAgICAgIHlJbmRleCxcbiAgICAgICAgICAgIGluZGV4LFxuICAgICAgICAgICAgc2NhbGUsXG4gICAgICAgICAgICB0cnVlLFxuICAgICAgICAgICk7XG4gICAgICAgICAgY29uc3QgeFZhbHVlID0gY2FsY3VsYXRlQmFyUG9zaXRpb24oXG4gICAgICAgICAgICBkYXRhLFxuICAgICAgICAgICAgY29uZmlnLFxuICAgICAgICAgICAgY2hhcnRTaXppbmdWYWx1ZXMsXG4gICAgICAgICAgICBpbmRleCxcbiAgICAgICAgICAgIHkuc3VwcGxlbWVudGFsSW5kZXggKyAxLFxuICAgICAgICAgICk7XG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGVsZW1lbnRUeXBlOiAncmVjdCcsXG4gICAgICAgICAgICB4OiB4VmFsdWUsXG4gICAgICAgICAgICB5OiB5VmFsdWUsXG4gICAgICAgICAgICB3aWR0aDogY2hhcnRTaXppbmdWYWx1ZXMuYmFyU2l6ZSxcbiAgICAgICAgICAgIGhlaWdodCxcbiAgICAgICAgICAgIG9mZnNldDogMCxcbiAgICAgICAgICAgIHBhdHRlcm46IHkucGF0dGVybixcbiAgICAgICAgICB9O1xuICAgICAgICB9KSxcbiAgICAgICk7XG4gICAgICBiYXJzLnB1c2goLi4uc3VwcEJhcnMpO1xuICAgICAgY29sb3JzLnB1c2goXG4gICAgICAgIC4uLmRhdGEuc3VwcGxlbWVudGFyeVlzLm1hcCh5ID0+XG4gICAgICAgICAgZ2V0Q29sb3IoeSwgY29sb3JJbmRpY2VzLCBjb25maWcuY29sb3JzKSxcbiAgICAgICAgKSxcbiAgICAgICk7XG4gICAgfVxuXG4gICAgY29uc3Qgd2F0ZXJmYWxsTGluZXM6IHtcbiAgICAgIHgxOiBudW1iZXI7XG4gICAgICB4MjogbnVtYmVyO1xuICAgICAgeTE6IG51bWJlcjtcbiAgICAgIHkyOiBudW1iZXI7XG4gICAgfVtdID0gW107XG4gICAgaWYgKGlzV2F0ZXJmYWxsKSB7XG4gICAgICAvL01vdmUgYmFycyBiYXNlZCBvbiBoZWlnaHQgb2YgcHJldmlvdXMgYmFycyAoZXhjZXB0IHRoZSB0b3RhbCBiYXIpXG4gICAgICBsZXQgYmFyT2Zmc2V0UnVubmluZ1RvdGFsID0gMDtcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZGF0YS54Lmxlbmd0aCAtIDE7IGkrKykge1xuICAgICAgICBsZXQgYmFyT2Zmc2V0Q2hhbmdlID0gMDtcbiAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCBiYXJzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgY29uc3QgYmFySXNOZWdhdGl2ZSA9XG4gICAgICAgICAgICBiYXJzW2pdW2ldLnkgPj0gemVyb0F4aXNQb3NWYWwgJiYgYmFyc1tqXVtpXS5oZWlnaHQgPiAwO1xuICAgICAgICAgIGlmIChiYXJJc05lZ2F0aXZlKSB7XG4gICAgICAgICAgICBiYXJPZmZzZXRDaGFuZ2UgLT0gYmFyc1tqXVtpXS5oZWlnaHQ7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGJhck9mZnNldENoYW5nZSArPSBiYXJzW2pdW2ldLmhlaWdodDtcbiAgICAgICAgICB9XG4gICAgICAgICAgYmFyc1tqXVtpXS5vZmZzZXQgPSBiYXJPZmZzZXRSdW5uaW5nVG90YWw7XG4gICAgICAgICAgYmFyc1tqXVtpXS55IC09IGJhck9mZnNldFJ1bm5pbmdUb3RhbDtcbiAgICAgICAgICBpZiAoaiA9PT0gYmFycy5sZW5ndGggLSAxKSB7XG4gICAgICAgICAgICBjb25zdCB4MSA9IGJhcnNbal1baV0ueCArIGJhcnNbYmFycy5sZW5ndGggLSAxXVtpXS53aWR0aDtcbiAgICAgICAgICAgIGNvbnN0IHkxID0gYmFyc1tqXVtpXS55ICsgKGJhcklzTmVnYXRpdmUgPyBiYXJzW2pdW2ldLmhlaWdodCA6IDApO1xuICAgICAgICAgICAgY29uc3QgeDIgPSBiYXJzW2pdW2kgKyAxXS54O1xuICAgICAgICAgICAgY29uc3QgeTIgPSB5MTtcbiAgICAgICAgICAgIHdhdGVyZmFsbExpbmVzLnB1c2goe1xuICAgICAgICAgICAgICB4MSxcbiAgICAgICAgICAgICAgeTEsXG4gICAgICAgICAgICAgIHgyLFxuICAgICAgICAgICAgICB5MixcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBiYXJPZmZzZXRSdW5uaW5nVG90YWwgKz0gYmFyT2Zmc2V0Q2hhbmdlO1xuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IGRhdGFMYWJlbHM6IERhdGFMYWJlbFtdID0gZGF0YS55cy5mbGF0TWFwKCh5LCB5SW5kZXgpID0+IHtcbiAgICAgIGNvbnN0IHN1YkxhYmVsczogRGF0YUxhYmVsW10gPSB5LnZhbHVlcy5tYXAoKHZhbCwgeEluZGV4KSA9PiB7XG4gICAgICAgIGNvbnN0IGlzTmVnYXRpdmVCYXIgPVxuICAgICAgICAgIGJhcnNbeUluZGV4XVt4SW5kZXhdLnkgPj0gemVyb0F4aXNQb3NWYWwgJiZcbiAgICAgICAgICBiYXJzW3lJbmRleF1beEluZGV4XS5oZWlnaHQgPiAwO1xuICAgICAgICBjb25zdCB5T2Zmc2V0ID0gaXNOZWdhdGl2ZUJhclxuICAgICAgICAgID8gY2hhcnRTaXppbmdWYWx1ZXMuZGF0YUxhYmVsUGFkZGluZyArXG4gICAgICAgICAgICBjaGFydFNpemluZ1ZhbHVlcy5kYXRhTGFiZWxUZXh0U2l6ZSArXG4gICAgICAgICAgICBiYXJzW3lJbmRleF1beEluZGV4XS5oZWlnaHRcbiAgICAgICAgICA6IC1jaGFydFNpemluZ1ZhbHVlcy5kYXRhTGFiZWxQYWRkaW5nO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIGVsZW1lbnRUeXBlOiAnZGF0YUxhYmVsJyxcbiAgICAgICAgICBsYWJlbDpcbiAgICAgICAgICAgIHBpcGVUcmFuc2Zvcm0odmFsLCBjaGVja0lmU2Vjb25kYXJ5KGRhdGEsIHlJbmRleCwgeEluZGV4KSkgPz8gJycsXG4gICAgICAgICAgeVBvczpcbiAgICAgICAgICAgIChpc0Z1bm5lbCAmJiBncmFkaWVudHNbeUluZGV4XVt4SW5kZXhdLmhlaWdodCAhPT0gMFxuICAgICAgICAgICAgICA/IGdyYWRpZW50c1t5SW5kZXhdW3hJbmRleF0ueVxuICAgICAgICAgICAgICA6IGJhcnNbeUluZGV4XVt4SW5kZXhdLnkpICsgeU9mZnNldCxcbiAgICAgICAgICB4UG9zOiBiYXJzW3lJbmRleF1beEluZGV4XS54ICsgYmFyc1t5SW5kZXhdW3hJbmRleF0ud2lkdGggLyAyLFxuICAgICAgICAgIGFuY2hvcjogJ21pZGRsZScsXG4gICAgICAgIH07XG4gICAgICB9KTtcbiAgICAgIHJldHVybiBzdWJMYWJlbHM7XG4gICAgfSk7XG4gICAgaWYgKGhhc1N1cHBsZW1lbnRhcnlEYXRhKGRhdGEpKSB7XG4gICAgICBjb25zdCBzdXBwRGF0YUxhYmVsczogRGF0YUxhYmVsW10gPSBkYXRhLnN1cHBsZW1lbnRhcnlZcy5mbGF0TWFwKFxuICAgICAgICAoeSwgeUluZGV4KSA9PiB7XG4gICAgICAgICAgY29uc3Qgc3ViTGFiZWxzOiBEYXRhTGFiZWxbXSA9IHkudmFsdWVzLm1hcCgodmFsLCB4SW5kZXgpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGlzTmVnYXRpdmVCYXIgPVxuICAgICAgICAgICAgICBzdXBwQmFyc1t5SW5kZXhdW3hJbmRleF0ueSA+PSB6ZXJvQXhpc1Bvc1ZhbCAmJlxuICAgICAgICAgICAgICBzdXBwQmFyc1t5SW5kZXhdW3hJbmRleF0uaGVpZ2h0ID4gMDtcbiAgICAgICAgICAgIGNvbnN0IHlPZmZzZXQgPSBpc05lZ2F0aXZlQmFyXG4gICAgICAgICAgICAgID8gY2hhcnRTaXppbmdWYWx1ZXMuZGF0YUxhYmVsUGFkZGluZyArXG4gICAgICAgICAgICAgICAgc3VwcEJhcnNbeUluZGV4XVt4SW5kZXhdLmhlaWdodFxuICAgICAgICAgICAgICA6IC1jaGFydFNpemluZ1ZhbHVlcy5kYXRhTGFiZWxQYWRkaW5nO1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgZWxlbWVudFR5cGU6ICdkYXRhTGFiZWwnLFxuICAgICAgICAgICAgICBsYWJlbDpcbiAgICAgICAgICAgICAgICBwaXBlVHJhbnNmb3JtKFxuICAgICAgICAgICAgICAgICAgdmFsLFxuICAgICAgICAgICAgICAgICAgY2hlY2tJZlNlY29uZGFyeShkYXRhLCB5SW5kZXgsIHhJbmRleCwgdHJ1ZSksXG4gICAgICAgICAgICAgICAgKSA/PyAnJyxcbiAgICAgICAgICAgICAgeVBvczogc3VwcEJhcnNbeUluZGV4XVt4SW5kZXhdLnkgKyB5T2Zmc2V0LFxuICAgICAgICAgICAgICB4UG9zOlxuICAgICAgICAgICAgICAgIHN1cHBCYXJzW3lJbmRleF1beEluZGV4XS54ICsgc3VwcEJhcnNbeUluZGV4XVt4SW5kZXhdLndpZHRoIC8gMixcbiAgICAgICAgICAgICAgYW5jaG9yOiAnbWlkZGxlJyxcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgfSk7XG4gICAgICAgICAgcmV0dXJuIHN1YkxhYmVscztcbiAgICAgICAgfSxcbiAgICAgICk7XG4gICAgICBkYXRhTGFiZWxzLnB1c2goLi4uc3VwcERhdGFMYWJlbHMpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGhvdmVyKHBvczoge1xuICAgICAgcmVjdDogRE9NUmVjdDtcbiAgICAgIHg6IG51bWJlcjtcbiAgICAgIHk6IG51bWJlcjtcbiAgICAgIGNvbnRhaW5lclNjcm9sbFg6IG51bWJlcjtcbiAgICAgIGNvbnRhaW5lclNjcm9sbFk6IG51bWJlcjtcbiAgICB9KTogSG92ZXJSZXR1cm4ge1xuICAgICAgY29uc3QgcmVhbFBvc1ggPSBwb3MueCArIHBvcy5jb250YWluZXJTY3JvbGxYO1xuICAgICAgY29uc3QgcmVhbFBvc1kgPSBwb3MueSArIHBvcy5jb250YWluZXJTY3JvbGxZO1xuICAgICAgaWYgKFxuICAgICAgICBjaGFydFNpemluZ1ZhbHVlcyA9PT0gbnVsbCB8fFxuICAgICAgICBnZXRJZkhvdmVyT3V0T2ZCb3VuZHMoXG4gICAgICAgICAgcG9zLngsXG4gICAgICAgICAgcG9zLnksXG4gICAgICAgICAgcmVhbFBvc1gsXG4gICAgICAgICAgcmVhbFBvc1ksXG4gICAgICAgICAgY2hhcnRTaXppbmdWYWx1ZXMsXG4gICAgICAgICAgZGltZW5zaW9ucyxcbiAgICAgICAgKVxuICAgICAgKSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBzdXBwWXMgPSBoYXNTdXBwbGVtZW50YXJ5RGF0YShkYXRhKSA/IGRhdGEuc3VwcGxlbWVudGFyeVlzIDogbnVsbDtcblxuICAgICAgY29uc3QgeEhvdmVySW5kaWNlcyA9IGdldEJ1Y2tldEFuZENsdXN0ZXJOdW1Gb3JIb3ZlcihcbiAgICAgICAgcmVhbFBvc1gsXG4gICAgICAgIGNoYXJ0U2l6aW5nVmFsdWVzLFxuICAgICAgICBkYXRhLFxuICAgICAgICBjb25maWcsXG4gICAgICAgIGRhdGEueC5sZW5ndGgsXG4gICAgICApO1xuICAgICAgaWYgKCF4SG92ZXJJbmRpY2VzKSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfVxuICAgICAgY29uc3Qge1xuICAgICAgICBidWNrZXROdW06IHhJbmRleCxcbiAgICAgICAgY2x1c3Rlck51bSxcbiAgICAgICAgY2x1c3Rlck5vcm1Db3VudCxcbiAgICAgICAgY2x1c3Rlck51bVR5cGUsXG4gICAgICB9ID0geEhvdmVySW5kaWNlcztcblxuICAgICAgbGV0IGlzU3VwcFZhbHVlOiBib29sZWFuID0gZmFsc2U7XG4gICAgICBsZXQgc3VwcEluZGV4VmFsID0gMDtcbiAgICAgIGlmIChzdXBwWXMpIHtcbiAgICAgICAgc3VwcEluZGV4VmFsID0gY2x1c3Rlck51bSAtIGNsdXN0ZXJOb3JtQ291bnQ7XG4gICAgICAgIGlmIChjbHVzdGVyTnVtVHlwZSA9PT0gJ3N1cHAnKSB7XG4gICAgICAgICAgaXNTdXBwVmFsdWUgPSB0cnVlO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGNhbGNYID0gY2FsY3VsYXRlQmFyUG9zaXRpb24oXG4gICAgICAgIGRhdGEsXG4gICAgICAgIGNvbmZpZyxcbiAgICAgICAgY2hhcnRTaXppbmdWYWx1ZXMsXG4gICAgICAgIHhJbmRleCxcbiAgICAgICAgY2x1c3Rlck51bSxcbiAgICAgICk7XG4gICAgICBjb25zdCB5cyA9IGRhdGEueXMubWFwKChfLCBtYXBZSW5kZXgpID0+XG4gICAgICAgIGlzU3VwcFZhbHVlXG4gICAgICAgICAgPyBnZXRTdXBwQmFyWUluZm9WaWFZSW5kZXgoXG4gICAgICAgICAgICAgIGRhdGEsXG4gICAgICAgICAgICAgIGNvbmZpZyxcbiAgICAgICAgICAgICAgbWFwWUluZGV4LFxuICAgICAgICAgICAgICBzdXBwSW5kZXhWYWwsXG4gICAgICAgICAgICAgIHhJbmRleCxcbiAgICAgICAgICAgICAgc2NhbGUsXG4gICAgICAgICAgICApLnlWYWx1ZVxuICAgICAgICAgIDogZ2V0QmFyWUluZm8oZGF0YSwgY29uZmlnLCBtYXBZSW5kZXgsIHhJbmRleCwgc2NhbGUpLnlWYWx1ZSAtXG4gICAgICAgICAgICAoIWlzU3VwcFZhbHVlICYmIGlzV2F0ZXJmYWxsXG4gICAgICAgICAgICAgID8gYmFyc1ttYXBZSW5kZXhdW3hJbmRleF0ub2Zmc2V0ID8/IDBcbiAgICAgICAgICAgICAgOiAwKSxcbiAgICAgICk7XG4gICAgICBjb25zdCB5UG9zU2lnbiA9IHplcm9BeGlzUG9zVmFsIC0gcmVhbFBvc1k7XG4gICAgICBsZXQgdmlzaWJsZVlJbmRleCA9IC0xO1xuICAgICAgbGV0IGRyb3BPZmZIb3ZlckRldGVjdGVkID0gZmFsc2U7XG4gICAgICBpZiAoeVBvc1NpZ24gPCAwICYmIGRhdGEueXMuZmluZCh5ID0+IHkudmFsdWVzLmZpbmQodmFsID0+IHZhbCA8IDApKSkge1xuICAgICAgICBmb3IgKGxldCBpID0geXMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgICBpZiAoeXNbaV0gPj0gemVyb0F4aXNQb3NWYWwgJiYgeXNbaV0gPCByZWFsUG9zWSkge1xuICAgICAgICAgICAgdmlzaWJsZVlJbmRleCA9IGk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgeXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICBpZiAoeXNbaV0gPD0gemVyb0F4aXNQb3NWYWwgJiYgeXNbaV0gPCByZWFsUG9zWSkge1xuICAgICAgICAgICAgdmlzaWJsZVlJbmRleCA9IGk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGlmIChpc0NsdXN0ZXJlZERhdGEoZGF0YSwgY29uZmlnLCBmYWxzZSkgJiYgIXN1cHBZcykge1xuICAgICAgICB2aXNpYmxlWUluZGV4ID0gY2x1c3Rlck51bTtcbiAgICAgICAgaWYgKGlzRnVubmVsICYmIHhJbmRleCAhPT0gMCAmJiB5c1t2aXNpYmxlWUluZGV4XSA+IHJlYWxQb3NZKSB7XG4gICAgICAgICAgZHJvcE9mZkhvdmVyRGV0ZWN0ZWQgPSB0cnVlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAodmlzaWJsZVlJbmRleCA9PT0gLTEpIHtcbiAgICAgICAgaWYgKHJlYWxQb3NZIDw9IHplcm9BeGlzUG9zVmFsKSB7XG4gICAgICAgICAgdmlzaWJsZVlJbmRleCA9IHlzLmluZGV4T2YoTWF0aC5taW4oLi4ueXMpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB2aXNpYmxlWUluZGV4ID0geXMuaW5kZXhPZihNYXRoLm1heCguLi55cykpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBjb25zdCB5SW5kZXggPSB2aXNpYmxlSW5kaWNlc1t2aXNpYmxlWUluZGV4XTtcbiAgICAgIGxldCB7IHlWYWx1ZSwgaGVpZ2h0IH0gPSBpc1N1cHBWYWx1ZVxuICAgICAgICA/IGdldFN1cHBCYXJZSW5mb1ZpYVlJbmRleChcbiAgICAgICAgICAgIGRhdGEsXG4gICAgICAgICAgICBjb25maWcsXG4gICAgICAgICAgICB5SW5kZXgsXG4gICAgICAgICAgICBzdXBwSW5kZXhWYWwsXG4gICAgICAgICAgICB4SW5kZXgsXG4gICAgICAgICAgICBzY2FsZSxcbiAgICAgICAgICApXG4gICAgICAgIDogZ2V0QmFyWUluZm8oZGF0YSwgY29uZmlnLCB5SW5kZXgsIHhJbmRleCwgc2NhbGUpO1xuICAgICAgaWYgKGRyb3BPZmZIb3ZlckRldGVjdGVkKSB7XG4gICAgICAgIHlWYWx1ZSA9IGdyYWRpZW50c1t5SW5kZXhdW3hJbmRleF0ueTtcbiAgICAgICAgaGVpZ2h0ID0gZ3JhZGllbnRzW3lJbmRleF1beEluZGV4XS5oZWlnaHQ7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGxvY2FsQW5jaG9yWCA9IGNhbGNYIC0gcG9zLmNvbnRhaW5lclNjcm9sbFggLSBTTUFMTF9QQURESU5HO1xuICAgICAgY29uc3Qgd2lkdGggPSBjaGFydFNpemluZ1ZhbHVlcy5iYXJTaXplICsgU01BTExfUEFERElORyAqIDI7XG4gICAgICBjb25zdCB3YXRlcmZhbGxPZmZzZXQgPVxuICAgICAgICAhaXNTdXBwVmFsdWUgJiYgaXNXYXRlcmZhbGwgPyBiYXJzW3lJbmRleF1beEluZGV4XS5vZmZzZXQgPz8gMCA6IDA7XG4gICAgICBjb25zdCBsb2NhbEFuY2hvclkgPSB5VmFsdWUgLSBwb3MuY29udGFpbmVyU2Nyb2xsWSAtIHdhdGVyZmFsbE9mZnNldDtcbiAgICAgIGNvbnN0IHsgYW5jaG9yWCwgYW5jaG9yWSwgYW5jaG9yV2lkdGgsIGFuY2hvckhlaWdodCB9ID1cbiAgICAgICAgY2hlY2tBbmNob3JzQWdhaW5zdEJvdW5kKFxuICAgICAgICAgIGxvY2FsQW5jaG9yWCxcbiAgICAgICAgICBsb2NhbEFuY2hvclksXG4gICAgICAgICAgZGltZW5zaW9ucyxcbiAgICAgICAgICB3aWR0aCxcbiAgICAgICAgICBoZWlnaHQsXG4gICAgICAgICk7XG4gICAgICBjb25zdCBhbmNob3IgPSBuZXcgRE9NUmVjdChcbiAgICAgICAgYW5jaG9yWCArIHBvcy5yZWN0LngsXG4gICAgICAgIGFuY2hvclkgKyBwb3MucmVjdC55LFxuICAgICAgICBhbmNob3JXaWR0aCxcbiAgICAgICAgYW5jaG9ySGVpZ2h0LFxuICAgICAgKTtcbiAgICAgIC8vV2UgbmVlZCB0byBwcmVzZXJ2ZSB0aGUgb3JpZ2luYWwgaW5kZXggZm9yIHRoZSBsYXRlciBjaGVja0lmU2Vjb25kYXJ5IGNhbGxcbiAgICAgIGNvbnN0IHlzRm9yTWV0cmljczoge1xuICAgICAgICBkYXRhOiBTdXBwbGVtZW50YXJ5RGF0YVkgfCBEYXRhWTtcbiAgICAgICAgb3JpZ2luYWxJbmRleDogbnVtYmVyO1xuICAgICAgfVtdID1cbiAgICAgICAgaXNTdXBwVmFsdWUgJiYgc3VwcFlzXG4gICAgICAgICAgPyBzdXBwWXNcbiAgICAgICAgICAgICAgLm1hcCgoc3VwcFksIGluZGV4KSA9PiAoeyBkYXRhOiBzdXBwWSwgb3JpZ2luYWxJbmRleDogaW5kZXggfSkpXG4gICAgICAgICAgICAgIC5maWx0ZXIoc3VwcFkgPT4gc3VwcFkuZGF0YS5zdXBwbGVtZW50YWxJbmRleCA9PT0gc3VwcEluZGV4VmFsKVxuICAgICAgICAgIDogZGF0YS55cy5tYXAoKHksIGluZGV4KSA9PiAoeyBkYXRhOiB5LCBvcmlnaW5hbEluZGV4OiBpbmRleCB9KSk7XG4gICAgICAvLyBGaW5kIHRoZSBzcGVjaWZpYyBzdXBwbGVtZW50YXJ5IGl0ZW0gdGhhdCB3YXMgaG92ZXJlZFxuICAgICAgY29uc3QgZ3JvdXBTdXBwcyA9IHN1cHBZc1xuICAgICAgICA/IHN1cHBZcy5maWx0ZXIocyA9PiBzLnN1cHBsZW1lbnRhbEluZGV4ID09PSBzdXBwSW5kZXhWYWwpID8/IFtdXG4gICAgICAgIDogW107XG4gICAgICBjb25zdCBzdXBwQXJyYXlJbmRleCA9IHZpc2libGVZSW5kZXg7IC8vIFVzZSB0aGUgdmlzdWFsIFkgcG9zaXRpb24gd2l0aGluIHRoZSBsYXllclxuICAgICAgY29uc3QgZmlsdGVyZWRTdXBwWUluZGV4ID1cbiAgICAgICAgc3VwcEFycmF5SW5kZXggPj0gMCAmJiBzdXBwQXJyYXlJbmRleCA8IGdyb3VwU3VwcHMubGVuZ3RoICYmIHN1cHBZc1xuICAgICAgICAgID8gc3VwcFlzLmluZGV4T2YoZ3JvdXBTdXBwc1tzdXBwQXJyYXlJbmRleF0pID8/IC0xXG4gICAgICAgICAgOiAtMTtcbiAgICAgIGNvbnN0IHN1cHBZSW5kZXggPVxuICAgICAgICBmaWx0ZXJlZFN1cHBZSW5kZXggPj0gMCA/IHZpc2libGVTdXBwSW5kaWNlc1tmaWx0ZXJlZFN1cHBZSW5kZXhdIDogLTE7XG5cbiAgICAgIHJldHVybiB7XG4gICAgICAgIGhvdmVyVHlwZTogJ3N0YW5kYXJkJyxcbiAgICAgICAgeDogY2FsY1ggKyBjaGFydFNpemluZ1ZhbHVlcy5iYXJTaXplIC8gMixcbiAgICAgICAgeEluZGV4LFxuICAgICAgICB5cyxcbiAgICAgICAgeUluZGV4LFxuICAgICAgICB2aXNpYmxlWUluZGV4LFxuICAgICAgICAuLi4oaXNTdXBwVmFsdWUgJiYgc3VwcFlJbmRleCA+PSAwXG4gICAgICAgICAgPyB7XG4gICAgICAgICAgICAgIGlzU3VwcFZhbHVlLFxuICAgICAgICAgICAgICBzdXBwWUluZGV4OiBzdXBwWUluZGV4LFxuICAgICAgICAgICAgfVxuICAgICAgICAgIDoge30pLFxuICAgICAgICAuLi4oZHJvcE9mZkhvdmVyRGV0ZWN0ZWQgPyB7IGlzRHJvcE9mZjogdHJ1ZSB9IDoge30pLFxuICAgICAgICB0b29sdGlwOiB7XG4gICAgICAgICAgYW5jaG9yLFxuICAgICAgICAgIGRhdGU6XG4gICAgICAgICAgICBkYXRhLnR5cGUgPT09ICdsYWJlbGVkJ1xuICAgICAgICAgICAgICA/IGRyb3BPZmZIb3ZlckRldGVjdGVkXG4gICAgICAgICAgICAgICAgPyAnRHJvcCBvZmYgZnJvbSAnLmNvbmNhdChkYXRhLnhbeEluZGV4IC0gMV0ubGFiZWwpXG4gICAgICAgICAgICAgICAgOiBkYXRhLnhbeEluZGV4XS5sYWJlbFxuICAgICAgICAgICAgICA6IHV0Y0Zvcm1hdCgnJUIgJWQsICVZJykobmV3IERhdGUoZGF0YS54W3hJbmRleF0pKSxcbiAgICAgICAgICBtZXRyaWNzOiB5c0Zvck1ldHJpY3NcbiAgICAgICAgICAgIC5tYXAoeSA9PiAoe1xuICAgICAgICAgICAgICBjb2xvcjogZ2V0Q29sb3IoXG4gICAgICAgICAgICAgICAgaXNXYXRlcmZhbGwgPyB3YXRlcmZhbGxEYXRhLm1hcC5nZXQoeS5kYXRhKSA6IHkuZGF0YSxcbiAgICAgICAgICAgICAgICBjb2xvckluZGljZXMsXG4gICAgICAgICAgICAgICAgY29uZmlnLmNvbG9ycyxcbiAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgbGFiZWw6IHkuZGF0YS5sYWJlbCxcbiAgICAgICAgICAgICAgcGF0dGVybjogeS5kYXRhLnBhdHRlcm4sXG4gICAgICAgICAgICAgIHZhbHVlOiBwaXBlVHJhbnNmb3JtKFxuICAgICAgICAgICAgICAgIGRyb3BPZmZIb3ZlckRldGVjdGVkXG4gICAgICAgICAgICAgICAgICA/IE1hdGgubWF4KFxuICAgICAgICAgICAgICAgICAgICAgIHkuZGF0YS52YWx1ZXNbeEluZGV4IC0gMV0gLSB5LmRhdGEudmFsdWVzW3hJbmRleF0sXG4gICAgICAgICAgICAgICAgICAgICAgMCxcbiAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgOiB5LmRhdGEudmFsdWVzW3hJbmRleF0sXG4gICAgICAgICAgICAgICAgY2hlY2tJZlNlY29uZGFyeShcbiAgICAgICAgICAgICAgICAgIGRhdGEsXG4gICAgICAgICAgICAgICAgICB5Lm9yaWdpbmFsSW5kZXgsXG4gICAgICAgICAgICAgICAgICBkcm9wT2ZmSG92ZXJEZXRlY3RlZCA/IHhJbmRleCAtIDEgOiB4SW5kZXgsXG4gICAgICAgICAgICAgICAgICBpc1N1cHBWYWx1ZSxcbiAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgIHRydWUsXG4gICAgICAgICAgICAgICksXG4gICAgICAgICAgICB9KSlcbiAgICAgICAgICAgIC5maWx0ZXIoKF8sIGkpID0+IGNvbmZpZy5ncm91cGVkVG9vbHRpcCB8fCBpID09PSB2aXNpYmxlWUluZGV4KSxcbiAgICAgICAgfSxcbiAgICAgIH07XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIGNoYXJ0V2lkdGg6IGNoYXJ0U2l6aW5nVmFsdWVzLnRvdGFsV2lkdGgsXG4gICAgICBjaGFydEhlaWdodDogY2hhcnRTaXppbmdWYWx1ZXMudG90YWxIZWlnaHQsXG4gICAgICBjaGFydFNpemluZ1ZhbHVlcyxcbiAgICAgIHhUaWNrcyxcbiAgICAgIHlUaWNrcyxcbiAgICAgIGNvbG9ycyxcbiAgICAgIGJhcnMsXG4gICAgICBsaW5lczogW10sXG4gICAgICBjaXJjbGVzOiBbXSxcbiAgICAgIGFyZWFzOiBbXSxcbiAgICAgIGhvdmVyLFxuICAgICAgYXJjczogW10sXG4gICAgICBob3Jpem9udGFsQmFyczogW10sXG4gICAgICBkYXRhTGFiZWxzLFxuICAgICAgd2F0ZXJmYWxsTGluZXMsXG4gICAgICBncmFkaWVudHMsXG4gICAgICBmbG93Q29ubmVjdGlvbnM6IFtdLFxuICAgICAgaG9yaXpvbnRhbENvbnRhaW5lclNjYWxlOiBjaGFydFNpemluZ1ZhbHVlcy5ob3Jpem9udGFsQ29udGFpbmVyU2NhbGUsXG4gICAgICB2ZXJ0aWNhbENvbnRhaW5lclNjYWxlOiBjaGFydFNpemluZ1ZhbHVlcy52ZXJ0aWNhbENvbnRhaW5lclNjYWxlLFxuICAgICAgY2hhcnRFcnJvcjogbnVsbCxcbiAgICB9O1xuICB9XG5cbiAgZnVuY3Rpb24gaG9yaXpvbnRhbEJhcnMoXG4gICAgY29uZmlnOiBDb25maWdXaXRoRnVsbFNjYWxpbmcsXG4gICAgYWxsRGF0YTogSW5wdXREYXRhLFxuICAgIGRpbWVuc2lvbnM6IERpbWVuc2lvbnMsXG4gICk6IFJlbmRlcmVkQ2hhcnQge1xuICAgIGlmICghd2FybkZsb3dEYXRhKGFsbERhdGEsICdob3Jpem9udGFsIGJhcicpKSB7XG4gICAgICByZXR1cm4geyAuLi5lbXB0eUNoYXJ0LCBjaGFydEVycm9yOiAnY29uZmlnJyB9O1xuICAgIH1cbiAgICAvL1NvbWUgb2YgdGhpcyBzdHVmZiBnZXRzIGNvbmZ1c2luZywgYmVjYXVzZSB4IGFuZCB5IGFyZSBlc3NlbnRpYWxseSBpbnZlcnRlZCBoZXJlXG4gICAgLy8gIFNvLCBpZiB5b3Ugc2VlIGEgc2l0dWF0aW9uIHdoZXJlIGEgdmFyaWFibGUgaXMgbmFtZWQgJ3knLCBidXQgcmVmZXJlbmNpbmdcbiAgICAvLyAgJ3gnIChvciB2aWNlIHZlcnNhKSwgdGhhdCdzIHdoeVxuICAgIGNvbnN0IHsgZGF0YSwgdmlzaWJsZUluZGljZXMsIHZpc2libGVTdXBwSW5kaWNlcyB9ID0gaGlkZShhbGxEYXRhKTtcbiAgICBpZiAoXG4gICAgICBjb25maWcuc2hvd0RhdGFMYWJlbHMgPT09IHRydWUgJiZcbiAgICAgIGlzU3RhY2tlZERhdGEoY29uZmlnKSAmJlxuICAgICAgIWlzR3JvdXBpbmdUeXBlRXhjZXB0aW9uKGRhdGEsIGNvbmZpZylcbiAgICApIHtcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgIFwiSGVhZHMgdXAhIERhdGEgbGFiZWxzIGFyZW4ndCBzdXBwb3J0ZWQgZm9yIGFueSBzdGFja2VkIGNoYXJ0IHR5cGVcIixcbiAgICAgICk7XG4gICAgICByZXR1cm4gZW1wdHlDaGFydDtcbiAgICB9XG4gICAgaWYgKFxuICAgICAgaGFzU3VwcGxlbWVudGFyeURhdGEoZGF0YSkgJiZcbiAgICAgIGlzQ2x1c3RlcmVkRGF0YShkYXRhLCBjb25maWcsIGZhbHNlKSAmJlxuICAgICAgIWlzR3JvdXBpbmdUeXBlRXhjZXB0aW9uKGRhdGEsIGNvbmZpZylcbiAgICApIHtcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgIFwiSGVhZHMgdXAhIFN1cHBsZW1lbnRhcnkgeSB2YWx1ZXMgYXJlbid0IHN1cHBvcnRlZCBmb3IgY2x1c3RlcmVkIGRhdGEgKGp1c3QgdXNlIGFub3RoZXIgbm9ybWFsIHkgc2VyaWVzKVwiLFxuICAgICAgKTtcbiAgICAgIHJldHVybiBlbXB0eUNoYXJ0O1xuICAgIH1cblxuICAgIGNvbnN0IHsgZGF0ZUZvcm1hdCwgcGlwZVRyYW5zZm9ybSwgY29sb3JJbmRpY2VzLCBjb2xvcnMgfSA9XG4gICAgICBnZXRGb3JtYXR0aW5nQW5kQ29sb3JzKGFsbERhdGEsIGRhdGEsIGNvbmZpZyk7XG5cbiAgICBjb25zdCBjaGFydFNpemluZ1ZhbHVlcyA9IGdldEZ1bGxDaGFydFNjYWxlVmFsdWVzKFxuICAgICAgY29uZmlnLFxuICAgICAgZGF0YSxcbiAgICAgIGRpbWVuc2lvbnMsXG4gICAgICBwaXBlVHJhbnNmb3JtLFxuICAgICAgZGF0ZUZvcm1hdCxcbiAgICApO1xuICAgIGlmIChjaGFydFNpemluZ1ZhbHVlcyA9PT0gbnVsbCkge1xuICAgICAgcmV0dXJuIHsgLi4uZW1wdHlDaGFydCwgY2hhcnRFcnJvcjogJ3NpemluZycgfTtcbiAgICB9XG5cbiAgICBjb25zdCB0aWNrQ291bnQgPSBnZXRCdWNrZXRUaWNrQ291bnQoY2hhcnRTaXppbmdWYWx1ZXMpO1xuICAgIGNvbnN0IHlUaWNrcyA9IChcbiAgICAgIGRhdGEudHlwZSA9PT0gJ2xhYmVsZWQnXG4gICAgICAgID8gZ2VuZXJhdGVMYWJlbGxlZFRpY2tzKGRhdGEsIGNvbmZpZywgdGlja0NvdW50LCBjaGFydFNpemluZ1ZhbHVlcylcbiAgICAgICAgOiBnZW5lcmF0ZVRpbWVzZXJpZXNUaWNrcyhcbiAgICAgICAgICAgIGRhdGEsXG4gICAgICAgICAgICBjb25maWcsXG4gICAgICAgICAgICB0aWNrQ291bnQsXG4gICAgICAgICAgICBjaGFydFNpemluZ1ZhbHVlcyxcbiAgICAgICAgICAgIGRhdGVGb3JtYXQsXG4gICAgICAgICAgKVxuICAgICkubWFwKHRpY2sgPT4gdG9ZVGljayh0aWNrKSk7XG4gICAgY29uc3QgeyBzY2FsZSwgdGlja3M6IGRhdGFUaWNrcyB9ID0gY2FsY0RhdGFBeGlzU2NhbGVzQW5kVGlja3MoXG4gICAgICBkYXRhLFxuICAgICAgcGlwZVRyYW5zZm9ybSxcbiAgICAgIGNvbmZpZyxcbiAgICAgIGNoYXJ0U2l6aW5nVmFsdWVzLFxuICAgICk7XG4gICAgY29uc3QgeFRpY2tzID0gZGF0YVRpY2tzLm1hcCh0aWNrID0+IHRvWFRpY2sodGljaykpO1xuICAgIGNvbnN0IHplcm9BeGlzUG9zVmFsID0gc2NhbGUoMCwgdHJ1ZSk7XG5cbiAgICBjb25zdCBzaW1wbGlmaWVkSG9yaXpvbnRhbEJhcnM6IHtcbiAgICAgIHhQb3M6IG51bWJlcjtcbiAgICAgIHlQb3M6IG51bWJlcjtcbiAgICAgIHdpZHRoOiBudW1iZXI7XG4gICAgfVtdW10gPSBbXTtcbiAgICBjb25zdCBob3Jpem9udGFsQmFycyA9IGRhdGEueXMubWFwKCh5LCB5SW5kZXgpID0+IHtcbiAgICAgIGNvbnN0IHN1YlNpbXBIb3JCYXJzOiB7XG4gICAgICAgIHhQb3M6IG51bWJlcjtcbiAgICAgICAgeVBvczogbnVtYmVyO1xuICAgICAgICB3aWR0aDogbnVtYmVyO1xuICAgICAgfVtdID0gW107XG4gICAgICBjb25zdCByZXRWYWwgPSB5LnZhbHVlcy5tYXAoKF8sIGluZGV4KSA9PiB7XG4gICAgICAgIGNvbnN0IHsgeFZhbHVlLCB3aWR0aCB9ID0gZ2V0QmFyWEluZm8oXG4gICAgICAgICAgZGF0YSxcbiAgICAgICAgICBjb25maWcsXG4gICAgICAgICAgeUluZGV4LFxuICAgICAgICAgIGluZGV4LFxuICAgICAgICAgIHNjYWxlLFxuICAgICAgICApO1xuICAgICAgICBjb25zdCBjbHVzdGVySW5mbyA9IGdldENsdXN0ZXJJbmZvRm9yQnVja2V0KGRhdGEsIGNvbmZpZyk7XG4gICAgICAgIGNvbnN0IGNsdXN0ZXJOdW0gPSBjbHVzdGVySW5mby5ub3JtQ2x1c3RlckluZGljZXMuaW5kZXhPZih5SW5kZXgpO1xuICAgICAgICBjb25zdCB5VmFsdWUgPSBjYWxjdWxhdGVCYXJQb3NpdGlvbihcbiAgICAgICAgICBkYXRhLFxuICAgICAgICAgIGNvbmZpZyxcbiAgICAgICAgICBjaGFydFNpemluZ1ZhbHVlcyxcbiAgICAgICAgICBpbmRleCxcbiAgICAgICAgICBpc0NsdXN0ZXJlZERhdGEoZGF0YSwgY29uZmlnLCBmYWxzZSkgPyBjbHVzdGVyTnVtIDogMCxcbiAgICAgICAgKTtcblxuICAgICAgICBjb25zdCBob3JSID0gTWF0aC5taW4oXG4gICAgICAgICAgREVGQVVMVF9IT1JJWk9OVEFMX0JBUl9DT1JORVJfUkFESVVTLFxuICAgICAgICAgIE1hdGguZmxvb3Iod2lkdGggLyAyKSxcbiAgICAgICAgKTtcbiAgICAgICAgY29uc3QgdmVyUiA9IE1hdGgubWluKFxuICAgICAgICAgIERFRkFVTFRfSE9SSVpPTlRBTF9CQVJfQ09STkVSX1JBRElVUyxcbiAgICAgICAgICBNYXRoLmZsb29yKGNoYXJ0U2l6aW5nVmFsdWVzLmJhclNpemUgLyAyKSxcbiAgICAgICAgKTtcbiAgICAgICAgc3ViU2ltcEhvckJhcnMucHVzaCh7XG4gICAgICAgICAgeFBvczogeFZhbHVlLFxuICAgICAgICAgIHlQb3M6IHlWYWx1ZSxcbiAgICAgICAgICB3aWR0aCxcbiAgICAgICAgfSk7XG4gICAgICAgIC8vSWYgY2x1c3Rlck51bSBpcyAtMSwgdGhlbiB0aGUgdmFsdWUgb2YgZGF0YVt5SW5kZXhdW3hJbmRleF0gbXVzdCBiZSB6ZXJvXG4gICAgICAgIGlmIChjbHVzdGVyTnVtID09PSAtMSkge1xuICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBob3Jpem9udGFsQmFyOiAnJyxcbiAgICAgICAgICAgIHBhdHRlcm46IHkucGF0dGVybixcbiAgICAgICAgICAgIHg6IHhWYWx1ZSxcbiAgICAgICAgICAgIHk6IHlWYWx1ZSxcbiAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIC8vRG9uJ3QgZHJhdyBhbnl0aGluZyBmb3IgemVyby12YWx1ZSBiYXJzXG4gICAgICAgIGlmICh3aWR0aCA9PT0gMCkge1xuICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBob3Jpem9udGFsQmFyOiAnJyxcbiAgICAgICAgICAgIHBhdHRlcm46IHkucGF0dGVybixcbiAgICAgICAgICAgIHg6IHhWYWx1ZSxcbiAgICAgICAgICAgIHk6IHlWYWx1ZSxcbiAgICAgICAgICB9O1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgaXNQb3NpdGl2ZSA9IGRhdGEueXNbeUluZGV4XS52YWx1ZXNbaW5kZXhdID4gMDtcbiAgICAgICAgY29uc3QgaGFzQW55TmVnYXRpdmVCYXJzID0gZGF0YS55c1xuICAgICAgICAgIC5tYXAoeSA9PiB5LnZhbHVlc1tpbmRleF0pXG4gICAgICAgICAgLmZpbmQodmFsID0+IHZhbCA8IDApO1xuICAgICAgICBjb25zdCBoYXNBbnlQb3NpdGl2ZUJhcnMgPSBkYXRhLnlzXG4gICAgICAgICAgLm1hcCh5ID0+IHkudmFsdWVzW2luZGV4XSlcbiAgICAgICAgICAuZmluZCh2YWwgPT4gdmFsID4gMCk7XG5cbiAgICAgICAgLy9UaGVzZSBjaGVja3MgYXJlIHRvIG1ha2Ugc3VyZSB3ZSBzdGlsbCByb3VuZCBpZiBhbGwgcHJldmlvdXMvbGF0ZXIgdmFsdWVzIGFyZSAwXG4gICAgICAgIGNvbnN0IGFsbExlZnRaZXJvID0gaXNQb3NpdGl2ZVxuICAgICAgICAgID8gZGF0YS55c1xuICAgICAgICAgICAgICAuc2xpY2UoMCwgeUluZGV4KVxuICAgICAgICAgICAgICAubWFwKHkgPT4geS52YWx1ZXNbaW5kZXhdKVxuICAgICAgICAgICAgICAuZmlsdGVyKHZhbCA9PiB2YWwgPiAwKS5sZW5ndGggPT09IDAgJiYgIWhhc0FueU5lZ2F0aXZlQmFyc1xuICAgICAgICAgIDogZGF0YS55c1xuICAgICAgICAgICAgICAuc2xpY2UoeUluZGV4ICsgMSwgZGF0YS55cy5sZW5ndGgpXG4gICAgICAgICAgICAgIC5tYXAoeSA9PiB5LnZhbHVlc1tpbmRleF0pXG4gICAgICAgICAgICAgIC5maWx0ZXIodmFsID0+IHZhbCA8IDApLmxlbmd0aCA9PT0gMDtcbiAgICAgICAgY29uc3QgbGVmdFNpZGVSb3VuZCA9ICFpc1N0YWNrZWREYXRhKGNvbmZpZykgfHwgYWxsTGVmdFplcm87XG4gICAgICAgIGNvbnN0IGFsbFJpZ2h0WmVybyA9IGlzUG9zaXRpdmVcbiAgICAgICAgICA/IGRhdGEueXNcbiAgICAgICAgICAgICAgLnNsaWNlKHlJbmRleCArIDEsIGRhdGEueXMubGVuZ3RoKVxuICAgICAgICAgICAgICAubWFwKHkgPT4geS52YWx1ZXNbaW5kZXhdKVxuICAgICAgICAgICAgICAuZmlsdGVyKHZhbCA9PiB2YWwgPiAwKS5sZW5ndGggPT09IDBcbiAgICAgICAgICA6IGRhdGEueXNcbiAgICAgICAgICAgICAgLnNsaWNlKDAsIHlJbmRleClcbiAgICAgICAgICAgICAgLm1hcCh5ID0+IHkudmFsdWVzW2luZGV4XSlcbiAgICAgICAgICAgICAgLmZpbHRlcih2YWwgPT4gdmFsIDwgMCkubGVuZ3RoID09PSAwICYmICFoYXNBbnlQb3NpdGl2ZUJhcnM7XG4gICAgICAgIGNvbnN0IHJpZ2h0U2lkZVJvdW5kID0gIWlzU3RhY2tlZERhdGEoY29uZmlnKSB8fCBhbGxSaWdodFplcm87XG4gICAgICAgIGNvbnN0IHBhdGhEID0gY2FsY3VsYXRlSG9yaXpvbnRhbEJhclBhdGgoXG4gICAgICAgICAgbGVmdFNpZGVSb3VuZCxcbiAgICAgICAgICByaWdodFNpZGVSb3VuZCxcbiAgICAgICAgICB4VmFsdWUsXG4gICAgICAgICAgeVZhbHVlLFxuICAgICAgICAgIGhvclIsXG4gICAgICAgICAgdmVyUixcbiAgICAgICAgICBjaGFydFNpemluZ1ZhbHVlcy5iYXJTaXplLFxuICAgICAgICAgIHdpZHRoLFxuICAgICAgICApO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIGhvcml6b250YWxCYXI6IHBhdGhELFxuICAgICAgICAgIHBhdHRlcm46IHkucGF0dGVybixcbiAgICAgICAgICB4OiB4VmFsdWUsXG4gICAgICAgICAgeTogeVZhbHVlLFxuICAgICAgICB9O1xuICAgICAgfSk7XG4gICAgICBzaW1wbGlmaWVkSG9yaXpvbnRhbEJhcnMucHVzaChzdWJTaW1wSG9yQmFycyk7XG4gICAgICByZXR1cm4gcmV0VmFsO1xuICAgIH0pO1xuICAgIGNvbnN0IHN1cHBZcyA9IGRhdGEuc3VwcGxlbWVudGFyeVlzO1xuICAgIGNvbnN0IHNpbXBsaWZpZWRTdXBwSG9yaXpvbnRhbEJhcnM6IHtcbiAgICAgIHhQb3M6IG51bWJlcjtcbiAgICAgIHlQb3M6IG51bWJlcjtcbiAgICAgIHdpZHRoOiBudW1iZXI7XG4gICAgfVtdW10gPSBbXTtcbiAgICBpZiAoc3VwcFlzKSB7XG4gICAgICBjb25zdCBzdXBwSG9yaXpvbnRhbEJhcnMgPSBzdXBwWXMubWFwKCh5LCB5SW5kZXgpID0+IHtcbiAgICAgICAgY29uc3Qgc3ViU2ltcEhvckJhcnM6IHtcbiAgICAgICAgICB4UG9zOiBudW1iZXI7XG4gICAgICAgICAgeVBvczogbnVtYmVyO1xuICAgICAgICAgIHdpZHRoOiBudW1iZXI7XG4gICAgICAgIH1bXSA9IFtdO1xuICAgICAgICBjb25zdCByZXRWYWwgPSB5LnZhbHVlcy5tYXAoKF8sIGluZGV4KSA9PiB7XG4gICAgICAgICAgY29uc3QgeyB4VmFsdWUsIHdpZHRoIH0gPSBnZXRCYXJYSW5mbyhcbiAgICAgICAgICAgIGRhdGEsXG4gICAgICAgICAgICBjb25maWcsXG4gICAgICAgICAgICB5SW5kZXgsXG4gICAgICAgICAgICBpbmRleCxcbiAgICAgICAgICAgIHNjYWxlLFxuICAgICAgICAgICAgdHJ1ZSxcbiAgICAgICAgICApO1xuICAgICAgICAgIGNvbnN0IGNsdXN0ZXJJbmZvID0gZ2V0Q2x1c3RlckluZm9Gb3JCdWNrZXQoZGF0YSwgY29uZmlnKTtcbiAgICAgICAgICBjb25zdCBjbHVzdGVyTnVtID1cbiAgICAgICAgICAgIGNsdXN0ZXJJbmZvLnN1cHBDbHVzdGVySW5kaWNlcy5pbmRleE9mKHkuc3VwcGxlbWVudGFsSW5kZXgpICtcbiAgICAgICAgICAgIGNsdXN0ZXJJbmZvLm5vcm1Db3VudDtcbiAgICAgICAgICBjb25zdCB5VmFsdWUgPSBjYWxjdWxhdGVCYXJQb3NpdGlvbihcbiAgICAgICAgICAgIGRhdGEsXG4gICAgICAgICAgICBjb25maWcsXG4gICAgICAgICAgICBjaGFydFNpemluZ1ZhbHVlcyxcbiAgICAgICAgICAgIGluZGV4LFxuICAgICAgICAgICAgY2x1c3Rlck51bSxcbiAgICAgICAgICApO1xuXG4gICAgICAgICAgY29uc3QgaG9yUiA9IE1hdGgubWluKFxuICAgICAgICAgICAgREVGQVVMVF9IT1JJWk9OVEFMX0JBUl9DT1JORVJfUkFESVVTLFxuICAgICAgICAgICAgTWF0aC5mbG9vcih3aWR0aCAvIDIpLFxuICAgICAgICAgICk7XG4gICAgICAgICAgY29uc3QgdmVyUiA9IE1hdGgubWluKFxuICAgICAgICAgICAgREVGQVVMVF9IT1JJWk9OVEFMX0JBUl9DT1JORVJfUkFESVVTLFxuICAgICAgICAgICAgTWF0aC5mbG9vcihjaGFydFNpemluZ1ZhbHVlcy5iYXJTaXplIC8gMiksXG4gICAgICAgICAgKTtcbiAgICAgICAgICBzdWJTaW1wSG9yQmFycy5wdXNoKHtcbiAgICAgICAgICAgIHhQb3M6IHhWYWx1ZSxcbiAgICAgICAgICAgIHlQb3M6IHlWYWx1ZSxcbiAgICAgICAgICAgIHdpZHRoLFxuICAgICAgICAgIH0pO1xuICAgICAgICAgIC8vRG9uJ3QgZHJhdyBhbnl0aGluZyBmb3IgemVyby12YWx1ZSBiYXJzXG4gICAgICAgICAgaWYgKHdpZHRoID09PSAwKSB7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICBob3Jpem9udGFsQmFyOiAnJyxcbiAgICAgICAgICAgICAgcGF0dGVybjogeS5wYXR0ZXJuLFxuICAgICAgICAgICAgICB4OiB4VmFsdWUsXG4gICAgICAgICAgICAgIHk6IHlWYWx1ZSxcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgY29uc3QgaXNQb3NpdGl2ZSA9IHN1cHBZc1t5SW5kZXhdLnZhbHVlc1tpbmRleF0gPiAwO1xuICAgICAgICAgIGNvbnN0IGhhc0FueU5lZ2F0aXZlQmFycyA9IHN1cHBZc1xuICAgICAgICAgICAgLmZpbHRlcihzdXBwWSA9PiBzdXBwWS5zdXBwbGVtZW50YWxJbmRleCA9PT0geS5zdXBwbGVtZW50YWxJbmRleClcbiAgICAgICAgICAgIC5tYXAoeSA9PiB5LnZhbHVlc1tpbmRleF0pXG4gICAgICAgICAgICAuZmluZCh2YWwgPT4gdmFsIDwgMCk7XG4gICAgICAgICAgY29uc3QgaGFzQW55UG9zaXRpdmVCYXJzID0gc3VwcFlzXG4gICAgICAgICAgICAuZmlsdGVyKHN1cHBZID0+IHN1cHBZLnN1cHBsZW1lbnRhbEluZGV4ID09PSB5LnN1cHBsZW1lbnRhbEluZGV4KVxuICAgICAgICAgICAgLm1hcCh5ID0+IHkudmFsdWVzW2luZGV4XSlcbiAgICAgICAgICAgIC5maW5kKHZhbCA9PiB2YWwgPiAwKTtcblxuICAgICAgICAgIC8vVGhlc2UgY2hlY2tzIGFyZSB0byBtYWtlIHN1cmUgd2Ugc3RpbGwgcm91bmQgaWYgYWxsIHByZXZpb3VzL2xhdGVyIHZhbHVlcyBhcmUgMFxuICAgICAgICAgIGNvbnN0IGFsbExlZnRaZXJvID0gaXNQb3NpdGl2ZVxuICAgICAgICAgICAgPyBzdXBwWXNcbiAgICAgICAgICAgICAgICAuc2xpY2UoMCwgeUluZGV4KVxuICAgICAgICAgICAgICAgIC5maWx0ZXIoXG4gICAgICAgICAgICAgICAgICBzdXBwWSA9PiBzdXBwWS5zdXBwbGVtZW50YWxJbmRleCA9PT0geS5zdXBwbGVtZW50YWxJbmRleCxcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgLm1hcCh5ID0+IHkudmFsdWVzW2luZGV4XSlcbiAgICAgICAgICAgICAgICAuZmlsdGVyKHZhbCA9PiB2YWwgPiAwKS5sZW5ndGggPT09IDAgJiYgIWhhc0FueU5lZ2F0aXZlQmFyc1xuICAgICAgICAgICAgOiBzdXBwWXNcbiAgICAgICAgICAgICAgICAuc2xpY2UoeUluZGV4ICsgMSwgc3VwcFlzLmxlbmd0aClcbiAgICAgICAgICAgICAgICAuZmlsdGVyKFxuICAgICAgICAgICAgICAgICAgc3VwcFkgPT4gc3VwcFkuc3VwcGxlbWVudGFsSW5kZXggPT09IHkuc3VwcGxlbWVudGFsSW5kZXgsXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgIC5tYXAoeSA9PiB5LnZhbHVlc1tpbmRleF0pXG4gICAgICAgICAgICAgICAgLmZpbHRlcih2YWwgPT4gdmFsIDwgMCkubGVuZ3RoID09PSAwO1xuICAgICAgICAgIGNvbnN0IGxlZnRTaWRlUm91bmQgPSAhaXNTdGFja2VkRGF0YShjb25maWcpIHx8IGFsbExlZnRaZXJvO1xuICAgICAgICAgIGNvbnN0IGFsbFJpZ2h0WmVybyA9IGlzUG9zaXRpdmVcbiAgICAgICAgICAgID8gc3VwcFlzXG4gICAgICAgICAgICAgICAgLnNsaWNlKHlJbmRleCArIDEsIHN1cHBZcy5sZW5ndGgpXG4gICAgICAgICAgICAgICAgLmZpbHRlcihcbiAgICAgICAgICAgICAgICAgIHN1cHBZID0+IHN1cHBZLnN1cHBsZW1lbnRhbEluZGV4ID09PSB5LnN1cHBsZW1lbnRhbEluZGV4LFxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAubWFwKHkgPT4geS52YWx1ZXNbaW5kZXhdKVxuICAgICAgICAgICAgICAgIC5maWx0ZXIodmFsID0+IHZhbCA+IDApLmxlbmd0aCA9PT0gMFxuICAgICAgICAgICAgOiBzdXBwWXNcbiAgICAgICAgICAgICAgICAuc2xpY2UoMCwgeUluZGV4KVxuICAgICAgICAgICAgICAgIC5maWx0ZXIoXG4gICAgICAgICAgICAgICAgICBzdXBwWSA9PiBzdXBwWS5zdXBwbGVtZW50YWxJbmRleCA9PT0geS5zdXBwbGVtZW50YWxJbmRleCxcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgLm1hcCh5ID0+IHkudmFsdWVzW2luZGV4XSlcbiAgICAgICAgICAgICAgICAuZmlsdGVyKHZhbCA9PiB2YWwgPCAwKS5sZW5ndGggPT09IDAgJiYgIWhhc0FueVBvc2l0aXZlQmFycztcbiAgICAgICAgICBjb25zdCByaWdodFNpZGVSb3VuZCA9ICFpc1N0YWNrZWREYXRhKGNvbmZpZykgfHwgYWxsUmlnaHRaZXJvO1xuICAgICAgICAgIGNvbnN0IHBhdGhEID0gY2FsY3VsYXRlSG9yaXpvbnRhbEJhclBhdGgoXG4gICAgICAgICAgICBsZWZ0U2lkZVJvdW5kLFxuICAgICAgICAgICAgcmlnaHRTaWRlUm91bmQsXG4gICAgICAgICAgICB4VmFsdWUsXG4gICAgICAgICAgICB5VmFsdWUsXG4gICAgICAgICAgICBob3JSLFxuICAgICAgICAgICAgdmVyUixcbiAgICAgICAgICAgIGNoYXJ0U2l6aW5nVmFsdWVzLmJhclNpemUsXG4gICAgICAgICAgICB3aWR0aCxcbiAgICAgICAgICApO1xuICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBob3Jpem9udGFsQmFyOiBwYXRoRCxcbiAgICAgICAgICAgIHBhdHRlcm46IHkucGF0dGVybixcbiAgICAgICAgICAgIHg6IHhWYWx1ZSxcbiAgICAgICAgICAgIHk6IHlWYWx1ZSxcbiAgICAgICAgICB9O1xuICAgICAgICB9KTtcbiAgICAgICAgc2ltcGxpZmllZFN1cHBIb3Jpem9udGFsQmFycy5wdXNoKHN1YlNpbXBIb3JCYXJzKTtcbiAgICAgICAgcmV0dXJuIHJldFZhbDtcbiAgICAgIH0pO1xuICAgICAgaG9yaXpvbnRhbEJhcnMucHVzaCguLi5zdXBwSG9yaXpvbnRhbEJhcnMpO1xuICAgICAgY29sb3JzLnB1c2goLi4uc3VwcFlzLm1hcCh5ID0+IGdldENvbG9yKHksIGNvbG9ySW5kaWNlcywgY29uZmlnLmNvbG9ycykpKTtcbiAgICB9XG5cbiAgICBjb25zdCB5T2Zmc2V0ID0gY2hhcnRTaXppbmdWYWx1ZXMuYmFyU2l6ZTtcbiAgICBjb25zdCBkYXRhTGFiZWxzOiBEYXRhTGFiZWxbXSA9IGRhdGEueXMuZmxhdE1hcCgoeSwgeUluZGV4KSA9PiB7XG4gICAgICBjb25zdCBzdWJMYWJlbHM6IERhdGFMYWJlbFtdID0geS52YWx1ZXMubWFwKCh2YWwsIHhJbmRleCkgPT4ge1xuICAgICAgICBjb25zdCBiYXJJc05lZ2F0aXZlID1cbiAgICAgICAgICBzaW1wbGlmaWVkSG9yaXpvbnRhbEJhcnNbeUluZGV4XVt4SW5kZXhdLnhQb3MgPCB6ZXJvQXhpc1Bvc1ZhbCAmJlxuICAgICAgICAgIHNpbXBsaWZpZWRIb3Jpem9udGFsQmFyc1t5SW5kZXhdW3hJbmRleF0ud2lkdGggPiAwO1xuICAgICAgICBjb25zdCB4T2Zmc2V0ID0gYmFySXNOZWdhdGl2ZVxuICAgICAgICAgID8gLWNoYXJ0U2l6aW5nVmFsdWVzLmRhdGFMYWJlbFBhZGRpbmdcbiAgICAgICAgICA6IHNpbXBsaWZpZWRIb3Jpem9udGFsQmFyc1t5SW5kZXhdW3hJbmRleF0ud2lkdGggK1xuICAgICAgICAgICAgY2hhcnRTaXppbmdWYWx1ZXMuZGF0YUxhYmVsUGFkZGluZztcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBlbGVtZW50VHlwZTogJ2RhdGFMYWJlbCcsXG4gICAgICAgICAgbGFiZWw6XG4gICAgICAgICAgICBwaXBlVHJhbnNmb3JtKHZhbCwgY2hlY2tJZlNlY29uZGFyeShkYXRhLCB5SW5kZXgsIHhJbmRleCkpID8/ICcnLFxuICAgICAgICAgIHlQb3M6IHNpbXBsaWZpZWRIb3Jpem9udGFsQmFyc1t5SW5kZXhdW3hJbmRleF0ueVBvcyArIHlPZmZzZXQsXG4gICAgICAgICAgeFBvczogc2ltcGxpZmllZEhvcml6b250YWxCYXJzW3lJbmRleF1beEluZGV4XS54UG9zICsgeE9mZnNldCxcbiAgICAgICAgICBhbmNob3I6IGJhcklzTmVnYXRpdmUgPyAnZW5kJyA6ICdzdGFydCcsXG4gICAgICAgIH07XG4gICAgICB9KTtcbiAgICAgIHJldHVybiBzdWJMYWJlbHM7XG4gICAgfSk7XG4gICAgaWYgKHN1cHBZcykge1xuICAgICAgY29uc3Qgc3VwcERhdGFMYWJlbHM6IERhdGFMYWJlbFtdID0gc3VwcFlzLmZsYXRNYXAoKHksIHlJbmRleCkgPT4ge1xuICAgICAgICBjb25zdCBzdWJMYWJlbHM6IERhdGFMYWJlbFtdID0geS52YWx1ZXMubWFwKCh2YWwsIHhJbmRleCkgPT4ge1xuICAgICAgICAgIGNvbnN0IGJhcklzTmVnYXRpdmUgPVxuICAgICAgICAgICAgc2ltcGxpZmllZFN1cHBIb3Jpem9udGFsQmFyc1t5SW5kZXhdW3hJbmRleF0ueFBvcyA8XG4gICAgICAgICAgICAgIHplcm9BeGlzUG9zVmFsICYmXG4gICAgICAgICAgICBzaW1wbGlmaWVkU3VwcEhvcml6b250YWxCYXJzW3lJbmRleF1beEluZGV4XS53aWR0aCA+IDA7XG4gICAgICAgICAgY29uc3QgeE9mZnNldCA9IGJhcklzTmVnYXRpdmVcbiAgICAgICAgICAgID8gLWNoYXJ0U2l6aW5nVmFsdWVzLmRhdGFMYWJlbFBhZGRpbmdcbiAgICAgICAgICAgIDogc2ltcGxpZmllZFN1cHBIb3Jpem9udGFsQmFyc1t5SW5kZXhdW3hJbmRleF0ud2lkdGggK1xuICAgICAgICAgICAgICBjaGFydFNpemluZ1ZhbHVlcy5kYXRhTGFiZWxQYWRkaW5nO1xuICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBlbGVtZW50VHlwZTogJ2RhdGFMYWJlbCcsXG4gICAgICAgICAgICBsYWJlbDpcbiAgICAgICAgICAgICAgcGlwZVRyYW5zZm9ybShcbiAgICAgICAgICAgICAgICB2YWwsXG4gICAgICAgICAgICAgICAgY2hlY2tJZlNlY29uZGFyeShkYXRhLCB5SW5kZXgsIHhJbmRleCwgdHJ1ZSksXG4gICAgICAgICAgICAgICkgPz8gJycsXG4gICAgICAgICAgICB5UG9zOiBzaW1wbGlmaWVkU3VwcEhvcml6b250YWxCYXJzW3lJbmRleF1beEluZGV4XS55UG9zICsgeU9mZnNldCxcbiAgICAgICAgICAgIHhQb3M6IHNpbXBsaWZpZWRTdXBwSG9yaXpvbnRhbEJhcnNbeUluZGV4XVt4SW5kZXhdLnhQb3MgKyB4T2Zmc2V0LFxuICAgICAgICAgICAgYW5jaG9yOiBiYXJJc05lZ2F0aXZlID8gJ2VuZCcgOiAnc3RhcnQnLFxuICAgICAgICAgIH07XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gc3ViTGFiZWxzO1xuICAgICAgfSk7XG4gICAgICBkYXRhTGFiZWxzLnB1c2goLi4uc3VwcERhdGFMYWJlbHMpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGhvdmVyKHBvczoge1xuICAgICAgcmVjdDogRE9NUmVjdDtcbiAgICAgIHg6IG51bWJlcjtcbiAgICAgIHk6IG51bWJlcjtcbiAgICAgIGNvbnRhaW5lclNjcm9sbFg6IG51bWJlcjtcbiAgICAgIGNvbnRhaW5lclNjcm9sbFk6IG51bWJlcjtcbiAgICB9KTogSG92ZXJSZXR1cm4ge1xuICAgICAgY29uc3QgcmVhbFBvc1ggPSBwb3MueCArIHBvcy5jb250YWluZXJTY3JvbGxYO1xuICAgICAgY29uc3QgcmVhbFBvc1kgPSBwb3MueSArIHBvcy5jb250YWluZXJTY3JvbGxZO1xuICAgICAgaWYgKFxuICAgICAgICBjaGFydFNpemluZ1ZhbHVlcyA9PT0gbnVsbCB8fFxuICAgICAgICBnZXRJZkhvdmVyT3V0T2ZCb3VuZHMoXG4gICAgICAgICAgcG9zLngsXG4gICAgICAgICAgcG9zLnksXG4gICAgICAgICAgcmVhbFBvc1gsXG4gICAgICAgICAgcmVhbFBvc1ksXG4gICAgICAgICAgY2hhcnRTaXppbmdWYWx1ZXMsXG4gICAgICAgICAgZGltZW5zaW9ucyxcbiAgICAgICAgKVxuICAgICAgKSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBzdXBwWXMgPSBoYXNTdXBwbGVtZW50YXJ5RGF0YShkYXRhKSA/IGRhdGEuc3VwcGxlbWVudGFyeVlzIDogbnVsbDtcbiAgICAgIGNvbnN0IHhIb3ZlckluZGljZXMgPSBnZXRCdWNrZXRBbmRDbHVzdGVyTnVtRm9ySG92ZXIoXG4gICAgICAgIHJlYWxQb3NZLFxuICAgICAgICBjaGFydFNpemluZ1ZhbHVlcyxcbiAgICAgICAgZGF0YSxcbiAgICAgICAgY29uZmlnLFxuICAgICAgICBkYXRhLngubGVuZ3RoLFxuICAgICAgKTtcbiAgICAgIGlmICgheEhvdmVySW5kaWNlcykge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHtcbiAgICAgICAgYnVja2V0TnVtOiB4SW5kZXgsXG4gICAgICAgIGNsdXN0ZXJOdW0sXG4gICAgICAgIGNsdXN0ZXJOb3JtQ291bnQsXG4gICAgICAgIGNsdXN0ZXJOdW1UeXBlLFxuICAgICAgfSA9IHhIb3ZlckluZGljZXM7XG5cbiAgICAgIGxldCB4ID0gY2FsY3VsYXRlQmFyUG9zaXRpb24oXG4gICAgICAgIGRhdGEsXG4gICAgICAgIGNvbmZpZyxcbiAgICAgICAgY2hhcnRTaXppbmdWYWx1ZXMsXG4gICAgICAgIHhJbmRleCxcbiAgICAgICAgY2x1c3Rlck51bSxcbiAgICAgICk7XG4gICAgICBsZXQgaXNTdXBwVmFsdWU6IGJvb2xlYW4gPSBmYWxzZTtcbiAgICAgIGxldCBzdXBwSW5kZXhWYWwgPSAwO1xuICAgICAgaWYgKHN1cHBZcykge1xuICAgICAgICBzdXBwSW5kZXhWYWwgPSBjbHVzdGVyTnVtIC0gY2x1c3Rlck5vcm1Db3VudDtcbiAgICAgICAgaWYgKGNsdXN0ZXJOdW1UeXBlID09PSAnc3VwcCcpIHtcbiAgICAgICAgICBpc1N1cHBWYWx1ZSA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLy8gV2hlbiBob3ZlcmluZyBzdXBwbGVtZW50YXJ5IHZhbHVlcywgZ2V0IGJhcnMgZm9yIHRoYXQgc3VwcGxlbWVudGFsIGxheWVyXG4gICAgICAvLyBXaGVuIGhvdmVyaW5nIG9yaWdpbmFsIFlzLCBnZXQgYmFycyBmb3Igb3JpZ2luYWwgWXNcbiAgICAgIGNvbnN0IGZ1bGxZcyA9XG4gICAgICAgIGhhc1N1cHBsZW1lbnRhcnlEYXRhKGRhdGEpICYmIGlzU3VwcFZhbHVlXG4gICAgICAgICAgPyAoXG4gICAgICAgICAgICAgIGRhdGEuc3VwcGxlbWVudGFyeVlzLmZpbHRlcihcbiAgICAgICAgICAgICAgICBzID0+IHMuc3VwcGxlbWVudGFsSW5kZXggPT09IHN1cHBJbmRleFZhbCxcbiAgICAgICAgICAgICAgKSA/PyBbXVxuICAgICAgICAgICAgKS5tYXAoc3VwcFkgPT5cbiAgICAgICAgICAgICAgZ2V0QmFyWEluZm8oXG4gICAgICAgICAgICAgICAgZGF0YSxcbiAgICAgICAgICAgICAgICBjb25maWcsXG4gICAgICAgICAgICAgICAgZGF0YS5zdXBwbGVtZW50YXJ5WXMuaW5kZXhPZihzdXBwWSksXG4gICAgICAgICAgICAgICAgeEluZGV4LFxuICAgICAgICAgICAgICAgIHNjYWxlLFxuICAgICAgICAgICAgICAgIHRydWUsXG4gICAgICAgICAgICAgICksXG4gICAgICAgICAgICApXG4gICAgICAgICAgOiBkYXRhLnlzLm1hcCgoXywgbWFwWUluZGV4KSA9PlxuICAgICAgICAgICAgICBnZXRCYXJYSW5mbyhkYXRhLCBjb25maWcsIG1hcFlJbmRleCwgeEluZGV4LCBzY2FsZSksXG4gICAgICAgICAgICApO1xuICAgICAgY29uc3QgeXMgPSBmdWxsWXMubWFwKHkgPT4geS54VmFsdWUpO1xuICAgICAgbGV0IHZpc2libGVZSW5kZXggPSAtMTtcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZnVsbFlzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGNvbnN0IGxlZnRCb3JkZXIgPSBmdWxsWXNbaV0ueFZhbHVlO1xuICAgICAgICBjb25zdCByaWdodEJvcmRlckNhbmRpZGF0ZXMgPSBmdWxsWXNcbiAgICAgICAgICAuZmlsdGVyKHkgPT4geS54VmFsdWUgPiBsZWZ0Qm9yZGVyKVxuICAgICAgICAgIC5tYXAoeSA9PiB5LnhWYWx1ZSk7XG4gICAgICAgIGNvbnN0IHJpZ2h0Qm9yZGVyID1cbiAgICAgICAgICByaWdodEJvcmRlckNhbmRpZGF0ZXMubGVuZ3RoID4gMFxuICAgICAgICAgICAgPyBNYXRoLm1pbiguLi5yaWdodEJvcmRlckNhbmRpZGF0ZXMpXG4gICAgICAgICAgICA6IGxlZnRCb3JkZXIgKyBmdWxsWXNbaV0ud2lkdGg7XG4gICAgICAgIGlmIChyZWFsUG9zWCA+IGxlZnRCb3JkZXIgJiYgcmVhbFBvc1ggPCByaWdodEJvcmRlcikge1xuICAgICAgICAgIHZpc2libGVZSW5kZXggPSBpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAoaXNDbHVzdGVyZWREYXRhKGRhdGEsIGNvbmZpZywgZmFsc2UpKSB7XG4gICAgICAgIHZpc2libGVZSW5kZXggPSBjbHVzdGVyTnVtO1xuICAgICAgfVxuXG4gICAgICBpZiAodmlzaWJsZVlJbmRleCA9PT0gLTEpIHtcbiAgICAgICAgaWYgKHJlYWxQb3NYID49IHplcm9BeGlzUG9zVmFsKSB7XG4gICAgICAgICAgdmlzaWJsZVlJbmRleCA9IHlzLmluZGV4T2YoTWF0aC5tYXgoLi4ueXMpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB2aXNpYmxlWUluZGV4ID0geXMuaW5kZXhPZihNYXRoLm1pbiguLi55cykpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICAvLyBGb3Igc3VwcGxlbWVudGFyeSBiYXJzOiB2aXNpYmxlWUluZGV4IGlzIGluZGV4IHdpdGhpbiBmaWx0ZXJlZCBzdXBwbGVtZW50YXJ5IGFycmF5XG4gICAgICAvLyBGb3Igb3JpZ2luYWwgWXM6IHZpc2libGVZSW5kZXggaXMgaW5kZXggd2l0aGluIG9yaWdpbmFsIFlzIGFycmF5XG4gICAgICBjb25zdCBhY3R1YWxTdXBwWUluZGV4ID1cbiAgICAgICAgaGFzU3VwcGxlbWVudGFyeURhdGEoZGF0YSkgJiYgaXNTdXBwVmFsdWVcbiAgICAgICAgICA/IGRhdGEuc3VwcGxlbWVudGFyeVlzLmZpbmRJbmRleChcbiAgICAgICAgICAgICAgcyA9PlxuICAgICAgICAgICAgICAgIHMuc3VwcGxlbWVudGFsSW5kZXggPT09IHN1cHBJbmRleFZhbCAmJlxuICAgICAgICAgICAgICAgIGRhdGEuc3VwcGxlbWVudGFyeVlzXG4gICAgICAgICAgICAgICAgICAuZmlsdGVyKHMyID0+IHMyLnN1cHBsZW1lbnRhbEluZGV4ID09PSBzdXBwSW5kZXhWYWwpXG4gICAgICAgICAgICAgICAgICAuaW5kZXhPZihzKSA9PT0gdmlzaWJsZVlJbmRleCxcbiAgICAgICAgICAgICkgPz8gLTFcbiAgICAgICAgICA6IC0xO1xuXG4gICAgICBjb25zdCB5SW5kZXggPSBpc1N1cHBWYWx1ZSA/IDAgOiB2aXNpYmxlSW5kaWNlc1t2aXNpYmxlWUluZGV4XTtcblxuICAgICAgLy9DaGVjayBpZiB3ZSd2ZSBsYW5kZWQgb24gYSB6ZXJvLXdpZHRoIGJhciAob25seSByZWFsbHkgcmVsZXZhbnQgb24gZW5kcylcbiAgICAgIGNvbnN0IGJhcnNUb0NoZWNrID0gaXNTdXBwVmFsdWVcbiAgICAgICAgPyBzaW1wbGlmaWVkU3VwcEhvcml6b250YWxCYXJzXG4gICAgICAgIDogc2ltcGxpZmllZEhvcml6b250YWxCYXJzO1xuICAgICAgY29uc3QgYmFySW5kZXhUb0NoZWNrID0gaXNTdXBwVmFsdWUgPyBhY3R1YWxTdXBwWUluZGV4IDogdmlzaWJsZVlJbmRleDtcblxuICAgICAgaWYgKFxuICAgICAgICBiYXJJbmRleFRvQ2hlY2sgPj0gMCAmJlxuICAgICAgICBiYXJzVG9DaGVja1tiYXJJbmRleFRvQ2hlY2tdW3hJbmRleF0ud2lkdGggPT09IDAgJiZcbiAgICAgICAgaXNTdGFja2VkRGF0YShjb25maWcpXG4gICAgICApIHtcbiAgICAgICAgbGV0IGFsdEJhckZvdW5kID0gZmFsc2U7XG4gICAgICAgIC8vQ2hlY2sgdXB3YXJkc1xuICAgICAgICBmb3IgKGxldCBpID0gYmFySW5kZXhUb0NoZWNrICsgMTsgaSA8IGJhcnNUb0NoZWNrLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgaWYgKGFsdEJhckZvdW5kKSB7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKGJhcnNUb0NoZWNrW2ldW3hJbmRleF0ud2lkdGggIT09IDApIHtcbiAgICAgICAgICAgIGlmIChoYXNTdXBwbGVtZW50YXJ5RGF0YShkYXRhKSAmJiBpc1N1cHBWYWx1ZSkge1xuICAgICAgICAgICAgICB2aXNpYmxlWUluZGV4ID0gZGF0YS5zdXBwbGVtZW50YXJ5WXNcbiAgICAgICAgICAgICAgICAuZmlsdGVyKHMgPT4gcy5zdXBwbGVtZW50YWxJbmRleCA9PT0gc3VwcEluZGV4VmFsKVxuICAgICAgICAgICAgICAgIC5pbmRleE9mKGRhdGEuc3VwcGxlbWVudGFyeVlzW2ldKSE7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICB2aXNpYmxlWUluZGV4ID0gaTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGFsdEJhckZvdW5kID0gdHJ1ZTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvL0NoZWNrIGRvd253YXJkc1xuICAgICAgICBmb3IgKGxldCBpID0gYmFySW5kZXhUb0NoZWNrIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgICBpZiAoYWx0QmFyRm91bmQpIHtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoYmFyc1RvQ2hlY2tbaV1beEluZGV4XS53aWR0aCAhPT0gMCkge1xuICAgICAgICAgICAgaWYgKGhhc1N1cHBsZW1lbnRhcnlEYXRhKGRhdGEpICYmIGlzU3VwcFZhbHVlKSB7XG4gICAgICAgICAgICAgIHZpc2libGVZSW5kZXggPSBkYXRhLnN1cHBsZW1lbnRhcnlZc1xuICAgICAgICAgICAgICAgIC5maWx0ZXIocyA9PiBzLnN1cHBsZW1lbnRhbEluZGV4ID09PSBzdXBwSW5kZXhWYWwpXG4gICAgICAgICAgICAgICAgLmluZGV4T2YoZGF0YS5zdXBwbGVtZW50YXJ5WXNbaV0pITtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHZpc2libGVZSW5kZXggPSBpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYWx0QmFyRm91bmQgPSB0cnVlO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBjb25zdCBvcmlnaW5hbFN1cHBZSW5kZXggPVxuICAgICAgICBpc1N1cHBWYWx1ZSAmJiBhY3R1YWxTdXBwWUluZGV4ID49IDBcbiAgICAgICAgICA/IHZpc2libGVTdXBwSW5kaWNlc1thY3R1YWxTdXBwWUluZGV4XVxuICAgICAgICAgIDogLTE7XG5cbiAgICAgIGNvbnN0IGJhclhQb3MgPSBpc1N1cHBWYWx1ZVxuICAgICAgICA/IHNpbXBsaWZpZWRTdXBwSG9yaXpvbnRhbEJhcnNbYWN0dWFsU3VwcFlJbmRleF1beEluZGV4XS54UG9zXG4gICAgICAgIDogc2ltcGxpZmllZEhvcml6b250YWxCYXJzW3Zpc2libGVZSW5kZXhdW3hJbmRleF0ueFBvcztcbiAgICAgIGNvbnN0IGJhcllQb3MgPSBpc1N1cHBWYWx1ZVxuICAgICAgICA/IHNpbXBsaWZpZWRTdXBwSG9yaXpvbnRhbEJhcnNbYWN0dWFsU3VwcFlJbmRleF1beEluZGV4XS55UG9zXG4gICAgICAgIDogc2ltcGxpZmllZEhvcml6b250YWxCYXJzW3Zpc2libGVZSW5kZXhdW3hJbmRleF0ueVBvcztcbiAgICAgIGNvbnN0IGJhcldpZHRoID0gaXNTdXBwVmFsdWVcbiAgICAgICAgPyBzaW1wbGlmaWVkU3VwcEhvcml6b250YWxCYXJzW2FjdHVhbFN1cHBZSW5kZXhdW3hJbmRleF0ud2lkdGhcbiAgICAgICAgOiBzaW1wbGlmaWVkSG9yaXpvbnRhbEJhcnNbdmlzaWJsZVlJbmRleF1beEluZGV4XS53aWR0aDtcblxuICAgICAgY29uc3QgbG9jYWxBbmNob3JYID0gYmFyWFBvcyAtIHBvcy5jb250YWluZXJTY3JvbGxYIC0gU01BTExfUEFERElORztcbiAgICAgIGNvbnN0IHdpZHRoID0gYmFyV2lkdGggKyBTTUFMTF9QQURESU5HICogMjtcbiAgICAgIGNvbnN0IGxvY2FsQW5jaG9yWSA9IGJhcllQb3MgLSBwb3MuY29udGFpbmVyU2Nyb2xsWTtcbiAgICAgIGNvbnN0IGhlaWdodCA9IGNoYXJ0U2l6aW5nVmFsdWVzLmJhclNpemU7XG4gICAgICBjb25zdCB7IGFuY2hvclgsIGFuY2hvclksIGFuY2hvcldpZHRoLCBhbmNob3JIZWlnaHQgfSA9XG4gICAgICAgIGNoZWNrQW5jaG9yc0FnYWluc3RCb3VuZChcbiAgICAgICAgICBsb2NhbEFuY2hvclgsXG4gICAgICAgICAgbG9jYWxBbmNob3JZLFxuICAgICAgICAgIGRpbWVuc2lvbnMsXG4gICAgICAgICAgd2lkdGgsXG4gICAgICAgICAgaGVpZ2h0LFxuICAgICAgICApO1xuICAgICAgY29uc3QgYW5jaG9yID0gbmV3IERPTVJlY3QoXG4gICAgICAgIGFuY2hvclggKyBwb3MucmVjdC54LFxuICAgICAgICBhbmNob3JZICsgcG9zLnJlY3QueSxcbiAgICAgICAgYW5jaG9yV2lkdGgsXG4gICAgICAgIGFuY2hvckhlaWdodCxcbiAgICAgICk7XG4gICAgICAvL1dlIG5lZWQgdG8gcHJlc2VydmUgdGhlIG9yaWdpbmFsIGluZGV4IGZvciB0aGUgbGF0ZXIgY2hlY2tJZlNlY29uZGFyeSBjYWxsXG4gICAgICBjb25zdCB5c0Zvck1ldHJpY3M6IHtcbiAgICAgICAgZGF0YTogU3VwcGxlbWVudGFyeURhdGFZIHwgRGF0YVk7XG4gICAgICAgIG9yaWdpbmFsSW5kZXg6IG51bWJlcjtcbiAgICAgIH1bXSA9XG4gICAgICAgIGlzU3VwcFZhbHVlICYmIHN1cHBZc1xuICAgICAgICAgID8gc3VwcFlzXG4gICAgICAgICAgICAgIC5tYXAoKHN1cHBZLCBpbmRleCkgPT4gKHsgZGF0YTogc3VwcFksIG9yaWdpbmFsSW5kZXg6IGluZGV4IH0pKVxuICAgICAgICAgICAgICAuZmlsdGVyKHN1cHBZID0+IHN1cHBZLmRhdGEuc3VwcGxlbWVudGFsSW5kZXggPT09IHN1cHBJbmRleFZhbClcbiAgICAgICAgICA6IGRhdGEueXMubWFwKCh5LCBpbmRleCkgPT4gKHsgZGF0YTogeSwgb3JpZ2luYWxJbmRleDogaW5kZXggfSkpO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgaG92ZXJUeXBlOiAnc3RhbmRhcmQnLFxuICAgICAgICB4LFxuICAgICAgICB4SW5kZXgsXG4gICAgICAgIHlzLFxuICAgICAgICB5SW5kZXgsXG4gICAgICAgIHZpc2libGVZSW5kZXgsXG4gICAgICAgIC4uLihpc1N1cHBWYWx1ZSAmJiBvcmlnaW5hbFN1cHBZSW5kZXggPj0gMFxuICAgICAgICAgID8geyBpc1N1cHBWYWx1ZSwgc3VwcFlJbmRleDogb3JpZ2luYWxTdXBwWUluZGV4IH1cbiAgICAgICAgICA6IHt9KSxcbiAgICAgICAgdG9vbHRpcDoge1xuICAgICAgICAgIGFuY2hvcixcbiAgICAgICAgICBkYXRlOlxuICAgICAgICAgICAgZGF0YS50eXBlID09PSAnbGFiZWxlZCdcbiAgICAgICAgICAgICAgPyBkYXRhLnhbeEluZGV4XS5sYWJlbFxuICAgICAgICAgICAgICA6IHV0Y0Zvcm1hdCgnJUIgJWQsICVZJykobmV3IERhdGUoZGF0YS54W3hJbmRleF0pKSxcbiAgICAgICAgICBtZXRyaWNzOiB5c0Zvck1ldHJpY3NcbiAgICAgICAgICAgIC5tYXAoeSA9PiAoe1xuICAgICAgICAgICAgICBjb2xvcjogZ2V0Q29sb3IoeS5kYXRhLCBjb2xvckluZGljZXMsIGNvbmZpZy5jb2xvcnMpLFxuICAgICAgICAgICAgICBsYWJlbDogeS5kYXRhLmxhYmVsLFxuICAgICAgICAgICAgICBwYXR0ZXJuOiB5LmRhdGEucGF0dGVybixcbiAgICAgICAgICAgICAgdmFsdWU6IHBpcGVUcmFuc2Zvcm0oXG4gICAgICAgICAgICAgICAgeS5kYXRhLnZhbHVlc1t4SW5kZXhdLFxuICAgICAgICAgICAgICAgIGNoZWNrSWZTZWNvbmRhcnkoZGF0YSwgeS5vcmlnaW5hbEluZGV4LCB4SW5kZXgsIGlzU3VwcFZhbHVlKSxcbiAgICAgICAgICAgICAgICB0cnVlLFxuICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgfSkpXG4gICAgICAgICAgICAuZmlsdGVyKChfLCBpKSA9PiBjb25maWcuZ3JvdXBlZFRvb2x0aXAgfHwgaSA9PT0gdmlzaWJsZVlJbmRleCksXG4gICAgICAgIH0sXG4gICAgICB9O1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBjaGFydFdpZHRoOiBjaGFydFNpemluZ1ZhbHVlcy50b3RhbFdpZHRoLFxuICAgICAgY2hhcnRIZWlnaHQ6IGNoYXJ0U2l6aW5nVmFsdWVzLnRvdGFsSGVpZ2h0LFxuICAgICAgY2hhcnRTaXppbmdWYWx1ZXMsXG4gICAgICB4VGlja3M6IHhUaWNrcyxcbiAgICAgIHlUaWNrczogeVRpY2tzLFxuICAgICAgaG92ZXIsXG4gICAgICBjb2xvcnMsXG4gICAgICBiYXJzOiBbXSxcbiAgICAgIGxpbmVzOiBbXSxcbiAgICAgIGNpcmNsZXM6IFtdLFxuICAgICAgYXJlYXM6IFtdLFxuICAgICAgYXJjczogW10sXG4gICAgICBob3Jpem9udGFsQmFycyxcbiAgICAgIGRhdGFMYWJlbHMsXG4gICAgICB3YXRlcmZhbGxMaW5lczogW10sXG4gICAgICBncmFkaWVudHM6IFtdLFxuICAgICAgZmxvd0Nvbm5lY3Rpb25zOiBbXSxcbiAgICAgIGhvcml6b250YWxDb250YWluZXJTY2FsZTogY2hhcnRTaXppbmdWYWx1ZXMuaG9yaXpvbnRhbENvbnRhaW5lclNjYWxlLFxuICAgICAgdmVydGljYWxDb250YWluZXJTY2FsZTogY2hhcnRTaXppbmdWYWx1ZXMudmVydGljYWxDb250YWluZXJTY2FsZSxcbiAgICAgIGNoYXJ0RXJyb3I6IG51bGwsXG4gICAgfTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGFyY3MoXG4gICAgY29uZmlnOiBEb251dENvbmZpZyxcbiAgICBhbGxEYXRhOiBJbnB1dERhdGEsXG4gICAgZGltZW5zaW9uczogRGltZW5zaW9ucyxcbiAgKTogUmVuZGVyZWRDaGFydCB7XG4gICAgaWYgKCF3YXJuRmxvd0RhdGEoYWxsRGF0YSwgJ2RvbnV0JykpIHtcbiAgICAgIHJldHVybiB7IC4uLmVtcHR5Q2hhcnQsIGNoYXJ0RXJyb3I6ICdjb25maWcnIH07XG4gICAgfVxuICAgIGlmIChcbiAgICAgIGNvbmZpZy5zZWNvbmRhcnlWYWx1ZVR5cGUgJiZcbiAgICAgIChjb25maWcudmFsdWVUeXBlID09PSAncGVyY2VudGFnZScgfHxcbiAgICAgICAgY29uZmlnLnNlY29uZGFyeVZhbHVlVHlwZSA9PT0gJ3BlcmNlbnRhZ2UnKVxuICAgICkge1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgXCJIZWFkcyB1cCEgVHdvIGF4ZXMgd2l0aCBwZXJjZW50YWdlIGFyZW4ndCBzdXBwb3J0ZWQgZm9yIGRvbnV0IGNoYXJ0c1wiLFxuICAgICAgKTtcbiAgICAgIHJldHVybiBlbXB0eUNoYXJ0O1xuICAgIH1cbiAgICBpZiAoaGFzU3VwcGxlbWVudGFyeURhdGEoYWxsRGF0YSkpIHtcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgIFwiSGVhZHMgdXAhIFN1cHBsZW1lbnRhcnkgeSB2YWx1ZXMgYXJlbid0IHN1cHBvcnRlZCBmb3Igbm9uLWJhciBjaGFydHNcIixcbiAgICAgICk7XG4gICAgICByZXR1cm4gZW1wdHlDaGFydDtcbiAgICB9XG4gICAgd2FyblVuc3VwcG9ydGVkUGF0dGVybnMoYWxsRGF0YSwgW10sICdkb251dCcpO1xuICAgIGNvbnN0IHsgZGF0YTogdW5zdGFja2VkRGF0YSwgdmlzaWJsZUluZGljZXMgfSA9IGhpZGUoYWxsRGF0YSk7XG4gICAgY29uc3QgZG9udXREYXRhID0gQ2hhcnQuY29udmVydENoYXJ0RGF0YVRvRG9udXREYXRhKHVuc3RhY2tlZERhdGEpO1xuICAgIGNvbnN0IGhhc05vblplcm9WYWx1ZSA9IGRvbnV0RGF0YS5zb21lKGQgPT4gZC52YWx1ZSA+IDApO1xuICAgIGNvbnN0IGFyY0RhdGEgPSBoYXNOb25aZXJvVmFsdWVcbiAgICAgID8gZG9udXREYXRhXG4gICAgICA6IFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICBsYWJlbDogJycsXG4gICAgICAgICAgICB2YWx1ZTogMSxcbiAgICAgICAgICB9LFxuICAgICAgICBdO1xuICAgIGNvbnN0IGNvbG9ycyA9IGhhc05vblplcm9WYWx1ZVxuICAgICAgPyB2aXNpYmxlSW5kaWNlcy5tYXAoaSA9PiBjb25maWcuY29sb3JzW2kgJSBjb25maWcuY29sb3JzLmxlbmd0aF0pXG4gICAgICA6IFsnLS1ncmF5LTMwJ107XG4gICAgY29uc3QgeyBwaXBlVHJhbnNmb3JtIH0gPSBnZXRGb3JtYXR0aW5nQW5kQ29sb3JzKFxuICAgICAgYWxsRGF0YSxcbiAgICAgIHVuc3RhY2tlZERhdGEsXG4gICAgICBjb25maWcsXG4gICAgKTtcblxuICAgIGNvbnN0IGRvbnV0RGVmYXVsdENvbmZpZyA9IERlZmF1bHREb251dFNpemluZ0NvbmZpZztcbiAgICBjb25zdCBkYXRhTGFiZWxQYWRkaW5nQ29uZmlnID0gZ2V0RWxlbWVudFNjYWxpbmdJbmZvKFxuICAgICAgY29uZmlnLmRvbnV0RGlzcGxheUluZm8uc2NhbGluZ0NvbmZpZz8uZWxlbWVudFNjYWxlcyxcbiAgICAgIGRvbnV0RGVmYXVsdENvbmZpZy5lbGVtZW50U2NhbGVzLFxuICAgICAgJ2RhdGFMYWJlbFBhZGRpbmcnLFxuICAgICk7XG4gICAgY29uc3QgZm9udFNpemVDb25maWcgPSBnZXRFbGVtZW50U2NhbGluZ0luZm8oXG4gICAgICBjb25maWcuZG9udXREaXNwbGF5SW5mby5zY2FsaW5nQ29uZmlnPy5lbGVtZW50U2NhbGVzLFxuICAgICAgZG9udXREZWZhdWx0Q29uZmlnLmVsZW1lbnRTY2FsZXMsXG4gICAgICAnZm9udFNpemUnLFxuICAgICk7XG4gICAgY29uc3QgZGF0YUxhYmVsVGV4dFNpemluZyA9IGdldERhdGFMYWJlbFNpemUoXG4gICAgICB1bnN0YWNrZWREYXRhLFxuICAgICAgcGlwZVRyYW5zZm9ybSxcbiAgICAgIGZvbnRTaXplQ29uZmlnLnRhcmdldCxcbiAgICApO1xuXG4gICAgY29uc3QgaG9yaXpvbnRhbENvbnRhaW5lclNjYWxlID1cbiAgICAgIGNvbmZpZy5kb251dERpc3BsYXlJbmZvLnNjYWxpbmdDb25maWc/Lmhvcml6b250YWxDb250YWluZXJTY2FsZSAhPT1cbiAgICAgIHVuZGVmaW5lZFxuICAgICAgICA/IGNvbmZpZy5kb251dERpc3BsYXlJbmZvLnNjYWxpbmdDb25maWcuaG9yaXpvbnRhbENvbnRhaW5lclNjYWxlXG4gICAgICAgIDogZG9udXREZWZhdWx0Q29uZmlnLmhvcml6b250YWxDb250YWluZXJTY2FsZTtcbiAgICBjb25zdCB2ZXJ0aWNhbENvbnRhaW5lclNjYWxlID1cbiAgICAgIGNvbmZpZy5kb251dERpc3BsYXlJbmZvLnNjYWxpbmdDb25maWc/LnZlcnRpY2FsQ29udGFpbmVyU2NhbGUgIT09XG4gICAgICB1bmRlZmluZWRcbiAgICAgICAgPyBjb25maWcuZG9udXREaXNwbGF5SW5mby5zY2FsaW5nQ29uZmlnLnZlcnRpY2FsQ29udGFpbmVyU2NhbGVcbiAgICAgICAgOiBkb251dERlZmF1bHRDb25maWcudmVydGljYWxDb250YWluZXJTY2FsZTtcbiAgICBjb25zdCBvdXRlclJhZGl1c0NvbmZpZyA9XG4gICAgICBjb25maWcuZG9udXREaXNwbGF5SW5mby5zY2FsaW5nQ29uZmlnPy5vdXRlclJhZGl1cyAhPT0gdW5kZWZpbmVkXG4gICAgICAgID8gY29uZmlnLmRvbnV0RGlzcGxheUluZm8uc2NhbGluZ0NvbmZpZy5vdXRlclJhZGl1c1xuICAgICAgICA6IGRvbnV0RGVmYXVsdENvbmZpZy5vdXRlclJhZGl1cztcbiAgICBjb25zdCBkcmF3UmFkaXVzQ29uZmlnID1cbiAgICAgIGNvbmZpZy5kb251dERpc3BsYXlJbmZvLnNjYWxpbmdDb25maWc/LmRyYXdSYWRpdXMgIT09IHVuZGVmaW5lZFxuICAgICAgICA/IGNvbmZpZy5kb251dERpc3BsYXlJbmZvLnNjYWxpbmdDb25maWcuZHJhd1JhZGl1c1xuICAgICAgICA6IGRvbnV0RGVmYXVsdENvbmZpZy5kcmF3UmFkaXVzO1xuXG4gICAgY29uc3Qgb3V0ZXIgPVxuICAgICAgb3V0ZXJSYWRpdXNDb25maWcudHlwZSA9PT0gJ3Byb3BvcnRpb24nXG4gICAgICAgID8gKGRpbWVuc2lvbnMuaGVpZ2h0IC8gMikgKiBvdXRlclJhZGl1c0NvbmZpZy52YWx1ZVxuICAgICAgICA6IG91dGVyUmFkaXVzQ29uZmlnLnZhbHVlO1xuICAgIGNvbnN0IGRyYXdSYWRpdXMgPVxuICAgICAgZHJhd1JhZGl1c0NvbmZpZy50eXBlID09PSAncHJvcG9ydGlvbidcbiAgICAgICAgPyBvdXRlciAqIGRyYXdSYWRpdXNDb25maWcudmFsdWVcbiAgICAgICAgOiBkcmF3UmFkaXVzQ29uZmlnLnZhbHVlO1xuICAgIGNvbnN0IGlubmVyID0gb3V0ZXIgLSBkcmF3UmFkaXVzO1xuXG4gICAgY29uc3QgcGllQXJjcyA9IHBpZTxEb251dERhdGE+KClcbiAgICAgIC5zb3J0VmFsdWVzKG51bGwpXG4gICAgICAudmFsdWUoZCA9PiBNYXRoLm1heChkLnZhbHVlLCAwKSkoYXJjRGF0YSk7XG5cbiAgICBjb25zdCBhcmNzID0gcGllQXJjcy5tYXAocGllQXJjID0+XG4gICAgICBhcmM8RG9udXREYXRhPigpXG4gICAgICAgIC5pbm5lclJhZGl1cyhpbm5lcilcbiAgICAgICAgLm91dGVyUmFkaXVzKG91dGVyKVxuICAgICAgICAucGFkQW5nbGUoMC4wMTMpXG4gICAgICAgIC5zdGFydEFuZ2xlKHBpZUFyYy5zdGFydEFuZ2xlKVxuICAgICAgICAuZW5kQW5nbGUocGllQXJjLmVuZEFuZ2xlKShwaWVBcmMuZGF0YSksXG4gICAgKTtcblxuICAgIGNvbnN0IGRhdGFMYWJlbHM6IERhdGFMYWJlbFtdID0gaGFzTm9uWmVyb1ZhbHVlXG4gICAgICA/IHBpZUFyY3MubWFwKGFyYyA9PiB7XG4gICAgICAgICAgLy9Eb24ndCBzaG93IGRhdGEgbGFiZWxzIGZvciB6ZXJvLXdpZHRoIGRvbnV0IHNsaWNlcyAoaW5jbHVkZXMgbmVnYXRpdmUgdmFsdWVzKVxuICAgICAgICAgIGlmIChhcmMuc3RhcnRBbmdsZSA9PT0gYXJjLmVuZEFuZ2xlKSB7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICBlbGVtZW50VHlwZTogJ2RhdGFMYWJlbCcsXG4gICAgICAgICAgICAgIGxhYmVsOiAnJyxcbiAgICAgICAgICAgICAgeVBvczogMCxcbiAgICAgICAgICAgICAgeFBvczogMCxcbiAgICAgICAgICAgICAgYW5jaG9yOiAnbWlkZGxlJyxcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgfVxuICAgICAgICAgIGNvbnN0IGFyY0NlbnRlckFuZ2xlID0gKGFyYy5zdGFydEFuZ2xlICsgYXJjLmVuZEFuZ2xlKSAvIDI7XG4gICAgICAgICAgY29uc3QgZWRnZVBvaW50ID0gYXJjVG9Qb2ludChhcmNDZW50ZXJBbmdsZSwgb3V0ZXIpO1xuICAgICAgICAgIGNvbnN0IGxpbmVFbmRQb2ludCA9IGFyY1RvUG9pbnQoXG4gICAgICAgICAgICBhcmNDZW50ZXJBbmdsZSxcbiAgICAgICAgICAgIG91dGVyICsgZGF0YUxhYmVsUGFkZGluZ0NvbmZpZy50YXJnZXQsXG4gICAgICAgICAgKTtcbiAgICAgICAgICBjb25zdCBtaWRkbGVBcmVhID0gb3V0ZXIgLyA0O1xuICAgICAgICAgIGxldCB5T2Zmc2V0ID0gMDtcbiAgICAgICAgICBsZXQgeE9mZnNldCA9IDA7XG4gICAgICAgICAgaWYgKGxpbmVFbmRQb2ludC55ID4gMCkge1xuICAgICAgICAgICAgaWYgKE1hdGguYWJzKGxpbmVFbmRQb2ludC55KSA8IG1pZGRsZUFyZWEpIHtcbiAgICAgICAgICAgICAgeU9mZnNldCA9IFNNQUxMX1BBRERJTkcgLyAyO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgeU9mZnNldCA9IFNNQUxMX1BBRERJTkc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoTWF0aC5hYnMobGluZUVuZFBvaW50LngpIDwgbWlkZGxlQXJlYSkge1xuICAgICAgICAgICAgICB5T2Zmc2V0ICs9IFNNQUxMX1BBRERJTkcgLyAyO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpZiAoTWF0aC5hYnMobGluZUVuZFBvaW50LnkpIDwgbWlkZGxlQXJlYSkge1xuICAgICAgICAgICAgICB5T2Zmc2V0ID0gU01BTExfUEFERElORyAvIDI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoTWF0aC5hYnMobGluZUVuZFBvaW50LngpIDwgbWlkZGxlQXJlYSkge1xuICAgICAgICAgICAgICB5T2Zmc2V0IC09IFNNQUxMX1BBRERJTkcgLyAyO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgZWxlbWVudFR5cGU6ICdkYXRhTGFiZWwnLFxuICAgICAgICAgICAgbGFiZWw6IHBpcGVUcmFuc2Zvcm0oYXJjLmRhdGEudmFsdWUsIGFyYy5kYXRhLmlzU2Vjb25kYXJ5KSxcbiAgICAgICAgICAgIHlQb3M6IGxpbmVFbmRQb2ludC55ICsgeU9mZnNldCxcbiAgICAgICAgICAgIHhQb3M6IGxpbmVFbmRQb2ludC54ICsgeE9mZnNldCxcbiAgICAgICAgICAgIGFuY2hvcjpcbiAgICAgICAgICAgICAgTWF0aC5hYnMobGluZUVuZFBvaW50LngpIDwgbWlkZGxlQXJlYVxuICAgICAgICAgICAgICAgID8gJ21pZGRsZSdcbiAgICAgICAgICAgICAgICA6IGxpbmVFbmRQb2ludC54IDwgMFxuICAgICAgICAgICAgICAgID8gJ2VuZCdcbiAgICAgICAgICAgICAgICA6ICdzdGFydCcsXG4gICAgICAgICAgICBsaW5lOiB7XG4gICAgICAgICAgICAgIHgxOiBlZGdlUG9pbnQueCxcbiAgICAgICAgICAgICAgeTE6IGVkZ2VQb2ludC55LFxuICAgICAgICAgICAgICB4MjogbGluZUVuZFBvaW50LngsXG4gICAgICAgICAgICAgIHkyOiBsaW5lRW5kUG9pbnQueSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfTtcbiAgICAgICAgfSlcbiAgICAgIDogW107XG5cbiAgICBjb25zdCBkcmF3V2lkdGggPVxuICAgICAgKG91dGVyICtcbiAgICAgICAgKGNvbmZpZy5zaG93RGF0YUxhYmVsc1xuICAgICAgICAgID8gZGF0YUxhYmVsUGFkZGluZ0NvbmZpZy50YXJnZXQgKyBkYXRhTGFiZWxUZXh0U2l6aW5nLmhvcml6b250YWxcbiAgICAgICAgICA6IDApKSAqXG4gICAgICAyO1xuICAgIGNvbnN0IGRyYXdIZWlnaHQgPVxuICAgICAgKG91dGVyICtcbiAgICAgICAgKGNvbmZpZy5zaG93RGF0YUxhYmVsc1xuICAgICAgICAgID8gZGF0YUxhYmVsUGFkZGluZ0NvbmZpZy50YXJnZXQgKyBkYXRhTGFiZWxUZXh0U2l6aW5nLnZlcnRpY2FsXG4gICAgICAgICAgOiAwKSkgKlxuICAgICAgMjtcblxuICAgIGZ1bmN0aW9uIGhvdmVyKHBvczoge1xuICAgICAgcmVjdDogRE9NUmVjdDtcbiAgICAgIHg6IG51bWJlcjtcbiAgICAgIHk6IG51bWJlcjtcbiAgICAgIGNvbnRhaW5lclNjcm9sbFg6IG51bWJlcjtcbiAgICAgIGNvbnRhaW5lclNjcm9sbFk6IG51bWJlcjtcbiAgICB9KTogSG92ZXJSZXR1cm4ge1xuICAgICAgY29uc3QgcmVhbFBvc1ggPSBwb3MueCArIHBvcy5jb250YWluZXJTY3JvbGxYO1xuICAgICAgY29uc3QgcmVhbFBvc1kgPSBwb3MueSArIHBvcy5jb250YWluZXJTY3JvbGxZO1xuICAgICAgaWYgKFxuICAgICAgICBnZXRJZkhvdmVyT3V0T2ZCb3VuZHMoXG4gICAgICAgICAgcG9zLngsXG4gICAgICAgICAgcG9zLnksXG4gICAgICAgICAgcmVhbFBvc1gsXG4gICAgICAgICAgcmVhbFBvc1ksXG4gICAgICAgICAgbnVsbCxcbiAgICAgICAgICBkaW1lbnNpb25zLFxuICAgICAgICApXG4gICAgICApIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9XG4gICAgICBjb25zdCBjZW50ZXJQb2ludFggPSBkaW1lbnNpb25zLndpZHRoIC8gMjtcbiAgICAgIGNvbnN0IGNlbnRlclBvaW50WSA9IGRpbWVuc2lvbnMuaGVpZ2h0IC8gMjtcbiAgICAgIGNvbnN0IGRvbnV0UG9zaXRpb25YID0gcmVhbFBvc1ggLSBjZW50ZXJQb2ludFg7XG4gICAgICBjb25zdCBkb251dFBvc2l0aW9uWSA9IHJlYWxQb3NZIC0gY2VudGVyUG9pbnRZO1xuICAgICAgY29uc3QgaG92ZXJQb3NBcmNJbmZvID0gcG9pbnRUb0FyYyhkb251dFBvc2l0aW9uWCwgZG9udXRQb3NpdGlvblkpO1xuICAgICAgY29uc3QgYXJjQ2VudGVyTGluZSA9IChvdXRlciArIGlubmVyKSAvIDI7XG5cbiAgICAgIC8vRGV0ZWN0IGRvbnV0IHNsaWNlXG4gICAgICBsZXQgZm91bmRZSW5kZXggPSAtMTtcbiAgICAgIGxldCBwcmVmZXJyZWRQb3NpdGlvbjogQ2FsbG91dENvbXBvbmVudC5BbmNob3JlZFBvc2l0aW9uIHwgdW5kZWZpbmVkID1cbiAgICAgICAgdW5kZWZpbmVkO1xuICAgICAgbGV0IGRvbnV0WFBvc2l0aW9uID0gMDtcbiAgICAgIGxldCBkb251dFlQb3NpdGlvbiA9IDA7XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHBpZUFyY3MubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgY29uc3QgYXJjID0gcGllQXJjc1tpXTtcblxuICAgICAgICBpZiAoXG4gICAgICAgICAgaG92ZXJQb3NBcmNJbmZvLmFuZ2xlID4gYXJjLnN0YXJ0QW5nbGUgJiZcbiAgICAgICAgICBob3ZlclBvc0FyY0luZm8uYW5nbGUgPCBhcmMuZW5kQW5nbGUgJiZcbiAgICAgICAgICBob3ZlclBvc0FyY0luZm8ucmFkaXVzID4gYXJjQ2VudGVyTGluZSAtIGRyYXdSYWRpdXMgJiZcbiAgICAgICAgICBob3ZlclBvc0FyY0luZm8ucmFkaXVzIDwgYXJjQ2VudGVyTGluZSArIGRyYXdSYWRpdXNcbiAgICAgICAgKSB7XG4gICAgICAgICAgZm91bmRZSW5kZXggPSBpO1xuICAgICAgICAgIGNvbnN0IGFyY0NlbnRlclBvaW50ID0gYXJjVG9Qb2ludChcbiAgICAgICAgICAgIChhcmMuc3RhcnRBbmdsZSArIGFyYy5lbmRBbmdsZSkgLyAyLFxuICAgICAgICAgICAgYXJjQ2VudGVyTGluZSxcbiAgICAgICAgICApO1xuXG4gICAgICAgICAgLy9OZWVkIHRvIHVuLW9mZnNldCB0aGUgcG9zaXRpb25zXG4gICAgICAgICAgZG9udXRYUG9zaXRpb24gPSBhcmNDZW50ZXJQb2ludC54ICsgY2VudGVyUG9pbnRYO1xuICAgICAgICAgIGRvbnV0WVBvc2l0aW9uID0gYXJjQ2VudGVyUG9pbnQueSArIGNlbnRlclBvaW50WTtcbiAgICAgICAgICBjb25zdCB2ZXJ0aWNhbEFyZWEgPVxuICAgICAgICAgICAgYXJjQ2VudGVyUG9pbnQueSA8IChkaW1lbnNpb25zLmhlaWdodCAqIC0xKSAvIDRcbiAgICAgICAgICAgICAgPyAndG9wJ1xuICAgICAgICAgICAgICA6IGFyY0NlbnRlclBvaW50LnkgPiBkaW1lbnNpb25zLmhlaWdodCAvIDRcbiAgICAgICAgICAgICAgPyAnYm90dG9tJ1xuICAgICAgICAgICAgICA6ICdjZW50ZXInO1xuXG4gICAgICAgICAgLy9EZXRlcm1pbmUgdGhlIGJlc3QgcG9zaXRpb24gZm9yIHRoZSB0b29sdGlwXG4gICAgICAgICAgaWYgKGFyY0NlbnRlclBvaW50LnggPiAwKSB7XG4gICAgICAgICAgICAvL1JpZ2h0IHBhdGhcbiAgICAgICAgICAgIGlmICghY29uZmlnLmdyb3VwZWRUb29sdGlwIHx8IHZlcnRpY2FsQXJlYSA9PT0gJ2NlbnRlcicpIHtcbiAgICAgICAgICAgICAgcHJlZmVycmVkUG9zaXRpb24gPSAnY2VudGVyLXJpZ2h0JztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAodmVydGljYWxBcmVhID09PSAndG9wJykge1xuICAgICAgICAgICAgICBwcmVmZXJyZWRQb3NpdGlvbiA9ICdyaWdodC10b3AnO1xuICAgICAgICAgICAgfSBlbHNlIGlmICh2ZXJ0aWNhbEFyZWEgPT09ICdib3R0b20nKSB7XG4gICAgICAgICAgICAgIHByZWZlcnJlZFBvc2l0aW9uID0gJ3JpZ2h0LWJvdHRvbSc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vTGVmdCBwYXRoXG4gICAgICAgICAgICBpZiAoIWNvbmZpZy5ncm91cGVkVG9vbHRpcCB8fCB2ZXJ0aWNhbEFyZWEgPT09ICdjZW50ZXInKSB7XG4gICAgICAgICAgICAgIHByZWZlcnJlZFBvc2l0aW9uID0gJ2NlbnRlci1sZWZ0JztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAodmVydGljYWxBcmVhID09PSAndG9wJykge1xuICAgICAgICAgICAgICBwcmVmZXJyZWRQb3NpdGlvbiA9ICdsZWZ0LXRvcCc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHZlcnRpY2FsQXJlYSA9PT0gJ2JvdHRvbScpIHtcbiAgICAgICAgICAgICAgcHJlZmVycmVkUG9zaXRpb24gPSAnbGVmdC1ib3R0b20nO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKGZvdW5kWUluZGV4ID09PSAtMSkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cbiAgICAgIGlmICghaGFzTm9uWmVyb1ZhbHVlKSB7XG4gICAgICAgIGRvbnV0WFBvc2l0aW9uID0gY2VudGVyUG9pbnRYICsgYXJjQ2VudGVyTGluZTtcbiAgICAgICAgZG9udXRZUG9zaXRpb24gPSBjZW50ZXJQb2ludFk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGxvY2FsQW5jaG9yWCA9IGRvbnV0WFBvc2l0aW9uIC0gcG9zLmNvbnRhaW5lclNjcm9sbFg7XG4gICAgICBjb25zdCBsb2NhbEFuY2hvclkgPSBkb251dFlQb3NpdGlvbiAtIHBvcy5jb250YWluZXJTY3JvbGxZO1xuICAgICAgY29uc3QgeyBhbmNob3JYLCBhbmNob3JZIH0gPSBjaGVja0FuY2hvcnNBZ2FpbnN0Qm91bmQoXG4gICAgICAgIGxvY2FsQW5jaG9yWCxcbiAgICAgICAgbG9jYWxBbmNob3JZLFxuICAgICAgICBkaW1lbnNpb25zLFxuICAgICAgKTtcbiAgICAgIGNvbnN0IGFuY2hvciA9IG5ldyBET01SZWN0KFxuICAgICAgICBhbmNob3JYICsgcG9zLnJlY3QueCxcbiAgICAgICAgYW5jaG9yWSArIHBvcy5yZWN0LnksXG4gICAgICAgIFNNQUxMX1BBRERJTkcsXG4gICAgICAgIDAsXG4gICAgICApO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgaG92ZXJUeXBlOiAnc3RhbmRhcmQnLFxuICAgICAgICB0b29sdGlwOiB7XG4gICAgICAgICAgYW5jaG9yLFxuICAgICAgICAgIHByZWZlcnJlZFBvc2l0aW9uLFxuICAgICAgICAgIGRhdGU6IG51bGwsXG4gICAgICAgICAgbWV0cmljczogZG9udXREYXRhXG4gICAgICAgICAgICAubWFwKCh5LCBpbmRleCkgPT4gKHtcbiAgICAgICAgICAgICAgY29sb3I6IGNvbG9yc1tpbmRleCAlIGNvbG9ycy5sZW5ndGhdLFxuICAgICAgICAgICAgICBsYWJlbDogeS5sYWJlbCxcbiAgICAgICAgICAgICAgdmFsdWU6IHBpcGVUcmFuc2Zvcm0oeS52YWx1ZSwgeS5pc1NlY29uZGFyeSwgdHJ1ZSksXG4gICAgICAgICAgICB9KSlcbiAgICAgICAgICAgIC5maWx0ZXIoKF8sIGkpID0+IGNvbmZpZy5ncm91cGVkVG9vbHRpcCB8fCBpID09PSBmb3VuZFlJbmRleCksXG4gICAgICAgIH0sXG4gICAgICAgIC8vTm90IHVzZWQgYnkgZG9udXQgY2hhcnRzXG4gICAgICAgIHg6IDAsXG4gICAgICAgIHhJbmRleDogMCxcbiAgICAgICAgeXM6IFtdLFxuICAgICAgICB5SW5kZXg6IDAsXG4gICAgICAgIHZpc2libGVZSW5kZXg6IDAsXG4gICAgICB9O1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBjaGFydFdpZHRoOiBkcmF3V2lkdGgsXG4gICAgICBjaGFydEhlaWdodDogZHJhd0hlaWdodCxcbiAgICAgIGNoYXJ0U2l6aW5nVmFsdWVzOiB7XG4gICAgICAgIC4uLmVtcHR5Q2hhcnRTY2FsZVZhbHVlcyxcbiAgICAgICAgZGF0YUxhYmVsUGFkZGluZzogZGF0YUxhYmVsUGFkZGluZ0NvbmZpZy50YXJnZXQsXG4gICAgICAgIGRhdGFMYWJlbFRleHRTaXplOiBkYXRhTGFiZWxUZXh0U2l6aW5nLmhvcml6b250YWwsXG4gICAgICAgIGZvbnRTaXplOiBmb250U2l6ZUNvbmZpZy50YXJnZXQsXG4gICAgICB9LFxuICAgICAgeFRpY2tzOiBbXSxcbiAgICAgIHlUaWNrczogW10sXG4gICAgICBhcmVhczogW10sXG4gICAgICBsaW5lczogW10sXG4gICAgICBjaXJjbGVzOiBbXSxcbiAgICAgIGJhcnM6IFtdLFxuICAgICAgY29sb3JzLFxuICAgICAgYXJjcyxcbiAgICAgIGhvcml6b250YWxCYXJzOiBbXSxcbiAgICAgIGRhdGFMYWJlbHMsXG4gICAgICB3YXRlcmZhbGxMaW5lczogW10sXG4gICAgICBncmFkaWVudHM6IFtdLFxuICAgICAgZmxvd0Nvbm5lY3Rpb25zOiBbXSxcbiAgICAgIGhvcml6b250YWxDb250YWluZXJTY2FsZSxcbiAgICAgIHZlcnRpY2FsQ29udGFpbmVyU2NhbGUsXG4gICAgICBjaGFydEVycm9yOiBudWxsLFxuICAgICAgaG92ZXIsXG4gICAgfTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGZsb3dzKFxuICAgIGNvbmZpZzogRmxvd0NvbmZpZyxcbiAgICBhbGxEYXRhOiBJbnB1dERhdGEsXG4gICAgZGltZW5zaW9uczogRGltZW5zaW9ucyxcbiAgKTogUmVuZGVyZWRDaGFydCB7XG4gICAgaWYgKGFsbERhdGEudHlwZSAhPT0gJ2Zsb3cnKSB7XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29uc29sZVxuICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICBgSGVhZHMgdXAhIFRoZSAnJHthbGxEYXRhLnR5cGV9JyBkYXRhIHR5cGUgaXNuJ3Qgc3VwcG9ydGVkIGZvciBmbG93IGNoYXJ0cy5gLFxuICAgICAgKTtcbiAgICAgIHJldHVybiB7IC4uLmVtcHR5Q2hhcnQsIGNoYXJ0RXJyb3I6ICdjb25maWcnIH07XG4gICAgfVxuXG4gICAgY29uc3QgZGF0YSA9IGZsb3dzVHJhbnNmb3JtKGNvbmZpZywgYWxsRGF0YSk7XG4gICAgaWYgKGRhdGEueC5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVybiBlbXB0eUNoYXJ0O1xuICAgIH1cbiAgICBjb25zdCBvdmVyYWxsVG90YWwgPSBkYXRhLnhbMF0udG90YWxDb3VudDtcblxuICAgIGNvbnN0IGNoYXJ0U2l6aW5nVmFsdWVzID0gZ2V0RnVsbENoYXJ0U2NhbGVWYWx1ZXMoXG4gICAgICBjb25maWcsXG4gICAgICBkYXRhLFxuICAgICAgZGltZW5zaW9ucyxcbiAgICAgIG51bGwsXG4gICAgICBudWxsLFxuICAgICk7XG4gICAgaWYgKGNoYXJ0U2l6aW5nVmFsdWVzID09PSBudWxsKSB7XG4gICAgICByZXR1cm4geyAuLi5lbXB0eUNoYXJ0LCBjaGFydEVycm9yOiAnc2l6aW5nJyB9O1xuICAgIH1cblxuICAgIGNvbnN0IHsgc2NhbGUgfSA9IGNhbGNEYXRhQXhpc1NjYWxlc0FuZFRpY2tzKFxuICAgICAgZGF0YSxcbiAgICAgIG51bGwsXG4gICAgICBjb25maWcsXG4gICAgICBjaGFydFNpemluZ1ZhbHVlcyxcbiAgICApO1xuICAgIGNvbnN0IHZhbHVlUGlwZXMgPSBnZXRQaXBlcyhjb25maWcudmFsdWVUeXBlKTtcbiAgICBjb25zdCBwZXJjZW50UGlwZXMgPSBnZXRQaXBlcygncGVyY2VudGFnZScpO1xuXG4gICAgY29uc3QgYmFyczogRmxvd1JlY3RbXVtdID0gW107XG4gICAgY29uc3QgZmxvd0Nvbm5lY3Rpb25zOiBGbG93Q29ubmVjdGlvblJlbmRlcltdID0gW107XG4gICAgY29uc3QgZGF0YUxhYmVsczogRmxvd0RhdGFMYWJlbFtdID0gW107XG4gICAgY29uc3QgbWluaW11bVNpemUgPSBnZXRNaW5pbXVtRGF0YUVsZW1lbnRTaXplKGNvbmZpZyk7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBkYXRhLngubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNvbnN0IGJ1Y2tldEJhcnM6IEZsb3dSZWN0W10gPSBbXTtcbiAgICAgIGxldCBydW5uaW5nSGVpZ2h0ID0gMDtcbiAgICAgIGZvciAoY29uc3QgYmFyIG9mIGRhdGEueFtpXS5zdWJCdWNrZXRzKSB7XG4gICAgICAgIGNvbnN0IGNvbnRpbnVpbmdDb3VudCA9IGJhci5jb25uZWN0aW9uc1xuICAgICAgICAgIC5maWx0ZXIoY29ubmVjdGlvbiA9PiBjb25uZWN0aW9uLmRpcmVjdGlvbiA9PT0gJ2ZvcndhcmQnKVxuICAgICAgICAgIC5tYXAoY29ubmVjdGlvbiA9PiBjb25uZWN0aW9uLmNvdW50KVxuICAgICAgICAgIC5yZWR1Y2UoKGEsIGIpID0+IGEgKyBiLCAwKTtcbiAgICAgICAgY29uc3Qge1xuICAgICAgICAgIHRvdGFsU2l6ZTogdG90YWxIZWlnaHQsXG4gICAgICAgICAgY29udGludWluZ1NpemU6IGRhcmtlbmVkSGVpZ2h0LFxuICAgICAgICAgIGNvbm5lY3Rpb25TaXplcyxcbiAgICAgICAgfSA9IGdldEZsb3dTdWJCdWNrZXRTaXplcyhcbiAgICAgICAgICBiYXIsXG4gICAgICAgICAgdmFsdWUgPT4gc2NhbGUodmFsdWUsIGZhbHNlKSAtIGNoYXJ0U2l6aW5nVmFsdWVzLnRvdGFsVG9wT2Zmc2V0LFxuICAgICAgICAgIG1pbmltdW1TaXplLFxuICAgICAgICApO1xuICAgICAgICBjb25zdCBjb25uZWN0aW9uSGVpZ2h0ID0gKGNvbm5lY3Rpb246IEZsb3dDb25uZWN0aW9uKTogbnVtYmVyID0+XG4gICAgICAgICAgY29ubmVjdGlvblNpemVzW2Jhci5jb25uZWN0aW9ucy5pbmRleE9mKGNvbm5lY3Rpb24pXTtcbiAgICAgICAgY29uc3Qgbm9uRGFya2VuZWRIZWlnaHQgPSB0b3RhbEhlaWdodCAtIGRhcmtlbmVkSGVpZ2h0O1xuICAgICAgICBjb25zdCBkYXJrZW5lZFkgPSBydW5uaW5nSGVpZ2h0ICsgY2hhcnRTaXppbmdWYWx1ZXMudG90YWxUb3BPZmZzZXQ7XG4gICAgICAgIGNvbnN0IG5vbkRhcmtlbmVkWSA9IGRhcmtlbmVkWSArIGRhcmtlbmVkSGVpZ2h0O1xuXG4gICAgICAgIGNvbnN0IHdpZHRoID0gY2hhcnRTaXppbmdWYWx1ZXMuYmFyU2l6ZTtcbiAgICAgICAgY29uc3QgeCA9XG4gICAgICAgICAgY2hhcnRTaXppbmdWYWx1ZXMudG90YWxMZWZ0T2Zmc2V0ICtcbiAgICAgICAgICBpICogKGNoYXJ0U2l6aW5nVmFsdWVzLmJhclNpemUgKyBjaGFydFNpemluZ1ZhbHVlcy5idWNrZXRHYXApO1xuICAgICAgICBjb25zdCBjb2xvck92ZXJyaWRlID0gY29uZmlnLmZsb3dDb25maWcuc3ViQnVja2V0c0NvbmZpZy5maW5kKFxuICAgICAgICAgIGJjID0+IGJjLmJ1Y2tldElkID09PSBiYXIuaWQsXG4gICAgICAgICk/LmNvbG9yO1xuICAgICAgICBpZiAoZGFya2VuZWRIZWlnaHQgPiAwKSB7XG4gICAgICAgICAgYnVja2V0QmFycy5wdXNoKHtcbiAgICAgICAgICAgIGVsZW1lbnRUeXBlOiAncmVjdCcsXG4gICAgICAgICAgICByZWN0VHlwZTogJ2Zsb3cnLFxuICAgICAgICAgICAgaGVpZ2h0OiBkYXJrZW5lZEhlaWdodCxcbiAgICAgICAgICAgIHdpZHRoLFxuICAgICAgICAgICAgeTogZGFya2VuZWRZLFxuICAgICAgICAgICAgeCxcbiAgICAgICAgICAgIGNvbG9yT3ZlcnJpZGUsXG4gICAgICAgICAgICBkYXJrZW46IHRydWUsXG4gICAgICAgICAgICBkZUVtcGhhc2l6ZTogaXNEZUVtcGhhc2l6ZWQoY29uZmlnLCBiYXIuaWQsIHRydWUpLFxuICAgICAgICAgICAgaWQ6IGJhci5pZCxcbiAgICAgICAgICAgIGJ1Y2tldEluZGV4OiBpLFxuICAgICAgICAgICAgY291bnQ6IGNvbnRpbnVpbmdDb3VudCxcbiAgICAgICAgICAgIHRvdGFsQ291bnQ6IGJhci5jb3VudCxcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBpZiAobm9uRGFya2VuZWRIZWlnaHQgPiAwKSB7XG4gICAgICAgICAgYnVja2V0QmFycy5wdXNoKHtcbiAgICAgICAgICAgIGVsZW1lbnRUeXBlOiAncmVjdCcsXG4gICAgICAgICAgICByZWN0VHlwZTogJ2Zsb3cnLFxuICAgICAgICAgICAgaGVpZ2h0OiBub25EYXJrZW5lZEhlaWdodCxcbiAgICAgICAgICAgIHdpZHRoLFxuICAgICAgICAgICAgeTogbm9uRGFya2VuZWRZLFxuICAgICAgICAgICAgeCxcbiAgICAgICAgICAgIGNvbG9yT3ZlcnJpZGUsXG4gICAgICAgICAgICBkYXJrZW46IGZhbHNlLFxuICAgICAgICAgICAgZGVFbXBoYXNpemU6IGlzRGVFbXBoYXNpemVkKGNvbmZpZywgYmFyLmlkLCBmYWxzZSksXG4gICAgICAgICAgICBpZDogYmFyLmlkLFxuICAgICAgICAgICAgYnVja2V0SW5kZXg6IGksXG4gICAgICAgICAgICBjb3VudDogYmFyLmNvdW50IC0gY29udGludWluZ0NvdW50LFxuICAgICAgICAgICAgdG90YWxDb3VudDogYmFyLmNvdW50LFxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIC8vSW52aXNpYmxlIGJhciBmb3IgaG92ZXIgaGlnaGxpZ2h0IHB1cnBvc2VzXG4gICAgICAgIGJ1Y2tldEJhcnMucHVzaCh7XG4gICAgICAgICAgZWxlbWVudFR5cGU6ICdyZWN0JyxcbiAgICAgICAgICByZWN0VHlwZTogJ2Zsb3cnLFxuICAgICAgICAgIGhlaWdodDogZGFya2VuZWRIZWlnaHQgKyBub25EYXJrZW5lZEhlaWdodCxcbiAgICAgICAgICB3aWR0aCxcbiAgICAgICAgICB5OiBkYXJrZW5lZFksXG4gICAgICAgICAgeCxcbiAgICAgICAgICBub25EaXNwbGF5OiB0cnVlLFxuICAgICAgICAgIGlkOiBiYXIuaWQsXG4gICAgICAgICAgYnVja2V0SW5kZXg6IGksXG4gICAgICAgICAgY291bnQ6IGJhci5jb3VudCxcbiAgICAgICAgICB0b3RhbENvdW50OiBiYXIuY291bnQsXG4gICAgICAgICAgZGFya2VuOiBmYWxzZSxcbiAgICAgICAgICBkZUVtcGhhc2l6ZTogZmFsc2UsXG4gICAgICAgIH0pO1xuICAgICAgICBydW5uaW5nSGVpZ2h0ICs9XG4gICAgICAgICAgdG90YWxIZWlnaHQgK1xuICAgICAgICAgIGNoYXJ0U2l6aW5nVmFsdWVzLmRhdGFMYWJlbFBhZGRpbmcgK1xuICAgICAgICAgIGNoYXJ0U2l6aW5nVmFsdWVzLmRhdGFMYWJlbFRleHRTaXplO1xuXG4gICAgICAgIC8vQ29ubmVjdGlvbnNcbiAgICAgICAgLy9BZGQgbmV3IHJlbmRlcnMgZm9yIGZvcndhcmQgY29ubmVjdGlvbnNcbiAgICAgICAgbGV0IHZlcnRpY2FsQ29ubmVjdGlvbk9mZnNldCA9IDA7XG4gICAgICAgIGZvciAoY29uc3QgY29ubmVjdGlvbiBvZiBiYXIuY29ubmVjdGlvbnMuZmlsdGVyKFxuICAgICAgICAgIGNvbm5lY3Rpb24gPT4gY29ubmVjdGlvbi5kaXJlY3Rpb24gPT09ICdmb3J3YXJkJyxcbiAgICAgICAgKSkge1xuICAgICAgICAgIGNvbnN0IHRvcExpbmVZMSA9IGRhcmtlbmVkWSArIHZlcnRpY2FsQ29ubmVjdGlvbk9mZnNldDtcbiAgICAgICAgICBjb25zdCBib3R0b21MaW5lWTEgPSB0b3BMaW5lWTEgKyBjb25uZWN0aW9uSGVpZ2h0KGNvbm5lY3Rpb24pO1xuICAgICAgICAgIGNvbnN0IHgxID0geCArIHdpZHRoO1xuICAgICAgICAgIGNvbnN0IGNvbm5lY3Rpb25SZW5kZXI6IEZsb3dDb25uZWN0aW9uUmVuZGVyID0ge1xuICAgICAgICAgICAgZWxlbWVudFR5cGU6ICdjb25uZWN0aW9uJyxcbiAgICAgICAgICAgIHN0YXJ0OiBjb25uZWN0aW9uLnN0YXJ0LFxuICAgICAgICAgICAgZW5kOiBjb25uZWN0aW9uLmVuZCxcbiAgICAgICAgICAgIGNvdW50OiBjb25uZWN0aW9uLmNvdW50LFxuICAgICAgICAgICAgc3RlcDogaSxcbiAgICAgICAgICAgIHRvcExpbmU6IHtcbiAgICAgICAgICAgICAgeTE6IHRvcExpbmVZMSxcbiAgICAgICAgICAgICAgeDEsXG4gICAgICAgICAgICAgIC8vVG8gYmUgZmlsbGVkIGluIGxhdGVyXG4gICAgICAgICAgICAgIHkyOiAwLFxuICAgICAgICAgICAgICB4MjogMCxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBib3R0b21MaW5lOiB7XG4gICAgICAgICAgICAgIHkxOiBib3R0b21MaW5lWTEsXG4gICAgICAgICAgICAgIHgxLFxuICAgICAgICAgICAgICAvL1RvIGJlIGZpbGxlZCBpbiBsYXRlclxuICAgICAgICAgICAgICB5MjogMCxcbiAgICAgICAgICAgICAgeDI6IDAsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgLy9UbyBiZSBmaWxsZWQgaW4gbGF0ZXJcbiAgICAgICAgICAgIHBhdGg6ICcnLFxuICAgICAgICAgIH07XG4gICAgICAgICAgdmVydGljYWxDb25uZWN0aW9uT2Zmc2V0ICs9IGNvbm5lY3Rpb25IZWlnaHQoY29ubmVjdGlvbik7XG4gICAgICAgICAgZmxvd0Nvbm5lY3Rpb25zLnB1c2goY29ubmVjdGlvblJlbmRlcik7XG4gICAgICAgIH1cbiAgICAgICAgLy9CYWNrZmlsbCBwb3NpdGlvbiBpbmZvIGZvciBiYWNrd2FyZHMgY29ubmVjdGlvbnNcbiAgICAgICAgdmVydGljYWxDb25uZWN0aW9uT2Zmc2V0ID0gMDtcbiAgICAgICAgZm9yIChjb25zdCBjb25uZWN0aW9uIG9mIGJhci5jb25uZWN0aW9ucy5maWx0ZXIoXG4gICAgICAgICAgY29ubmVjdGlvbiA9PiBjb25uZWN0aW9uLmRpcmVjdGlvbiA9PT0gJ2JhY2t3YXJkJyxcbiAgICAgICAgKSkge1xuICAgICAgICAgIGNvbnN0IG1hdGNoaW5nQ29ubmVjdGlvbiA9IGZsb3dDb25uZWN0aW9ucy5maW5kKFxuICAgICAgICAgICAgY29uID0+XG4gICAgICAgICAgICAgIGNvbi5zdGFydCA9PT0gY29ubmVjdGlvbi5zdGFydCAmJlxuICAgICAgICAgICAgICBjb24uZW5kID09PSBjb25uZWN0aW9uLmVuZCAmJlxuICAgICAgICAgICAgICBjb24uc3RlcCA9PT0gaSAtIDEsXG4gICAgICAgICAgKTtcbiAgICAgICAgICBpZiAobWF0Y2hpbmdDb25uZWN0aW9uKSB7XG4gICAgICAgICAgICBjb25zdCB0b3BMaW5lWTIgPSBkYXJrZW5lZFkgKyB2ZXJ0aWNhbENvbm5lY3Rpb25PZmZzZXQ7XG4gICAgICAgICAgICBjb25zdCBib3R0b21MaW5lWTIgPSB0b3BMaW5lWTIgKyBjb25uZWN0aW9uSGVpZ2h0KGNvbm5lY3Rpb24pO1xuICAgICAgICAgICAgbWF0Y2hpbmdDb25uZWN0aW9uLnRvcExpbmUueTIgPSB0b3BMaW5lWTI7XG4gICAgICAgICAgICBtYXRjaGluZ0Nvbm5lY3Rpb24udG9wTGluZS54MiA9IHg7XG4gICAgICAgICAgICBtYXRjaGluZ0Nvbm5lY3Rpb24uYm90dG9tTGluZS55MiA9IGJvdHRvbUxpbmVZMjtcbiAgICAgICAgICAgIG1hdGNoaW5nQ29ubmVjdGlvbi5ib3R0b21MaW5lLngyID0geDtcbiAgICAgICAgICAgIG1hdGNoaW5nQ29ubmVjdGlvbi5wYXRoID1cbiAgICAgICAgICAgICAgY2FsY3VsYXRlRmxvd0Nvbm5lY3Rpb25QYXRoKG1hdGNoaW5nQ29ubmVjdGlvbik7XG5cbiAgICAgICAgICAgIHZlcnRpY2FsQ29ubmVjdGlvbk9mZnNldCArPSBjb25uZWN0aW9uSGVpZ2h0KGNvbm5lY3Rpb24pO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vRGF0YSBMYWJlbHNcbiAgICAgICAgY29uc3QgYmFyTmFtZSA9IGNvbmZpZy5mbG93Q29uZmlnLnN1YkJ1Y2tldHNDb25maWcuZmluZChcbiAgICAgICAgICBzYmMgPT4gc2JjLmJ1Y2tldElkID09PSBiYXIuaWQsXG4gICAgICAgICk/LmJ1Y2tldE5hbWU7XG4gICAgICAgIGlmIChiYXJOYW1lICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICBkYXRhTGFiZWxzLnB1c2goe1xuICAgICAgICAgICAgZWxlbWVudFR5cGU6ICdkYXRhTGFiZWwnLFxuICAgICAgICAgICAgZGF0YUxhYmVsVHlwZTogJ2Zsb3cnLFxuICAgICAgICAgICAgbGFiZWw6IGAke2Jhck5hbWV9ICgke3BlcmNlbnRQaXBlcy5waXBlLnRyYW5zZm9ybShcbiAgICAgICAgICAgICAgYmFyLmNvdW50IC8gZGF0YS54W2ldLnRvdGFsQ291bnQsXG4gICAgICAgICAgICApfSlgLFxuICAgICAgICAgICAgeFBvczogeCxcbiAgICAgICAgICAgIHlQb3M6XG4gICAgICAgICAgICAgIGRhcmtlbmVkWSAtXG4gICAgICAgICAgICAgIChjaGFydFNpemluZ1ZhbHVlcy5kYXRhTGFiZWxUZXh0U2l6ZSArXG4gICAgICAgICAgICAgICAgY2hhcnRTaXppbmdWYWx1ZXMuZGF0YUxhYmVsUGFkZGluZykgL1xuICAgICAgICAgICAgICAgIDIsXG4gICAgICAgICAgICBhbmNob3I6ICdzdGFydCcsXG4gICAgICAgICAgICBib2xkOiB0cnVlLFxuICAgICAgICAgICAgYnVja2V0SW5kZXg6IGksXG4gICAgICAgICAgICBiYXJJZDogYmFyLmlkLFxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGJhclN1YnRpdGxlID0gY29uZmlnLmZsb3dDb25maWcuc3VidGl0bGVGb3JtYXRTdHJpbmcucmVwbGFjZShcbiAgICAgICAgICAne3ZhbHVlfScsXG4gICAgICAgICAgdmFsdWVQaXBlcy5waXBlLnRyYW5zZm9ybShiYXIuY291bnQpLFxuICAgICAgICApO1xuICAgICAgICBkYXRhTGFiZWxzLnB1c2goe1xuICAgICAgICAgIGVsZW1lbnRUeXBlOiAnZGF0YUxhYmVsJyxcbiAgICAgICAgICBkYXRhTGFiZWxUeXBlOiAnZmxvdycsXG4gICAgICAgICAgbGFiZWw6IGJhclN1YnRpdGxlLFxuICAgICAgICAgIHhQb3M6IHgsXG4gICAgICAgICAgeVBvczogZGFya2VuZWRZIC0gY2hhcnRTaXppbmdWYWx1ZXMuZGF0YUxhYmVsUGFkZGluZyAvIDQsXG4gICAgICAgICAgYW5jaG9yOiAnc3RhcnQnLFxuICAgICAgICAgIGJ1Y2tldEluZGV4OiBpLFxuICAgICAgICAgIGJhcklkOiBiYXIuaWQsXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgICAgYmFycy5wdXNoKGJ1Y2tldEJhcnMpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGhvdmVyKHBvczoge1xuICAgICAgcmVjdDogRE9NUmVjdDtcbiAgICAgIHg6IG51bWJlcjtcbiAgICAgIHk6IG51bWJlcjtcbiAgICAgIGNvbnRhaW5lclNjcm9sbFg6IG51bWJlcjtcbiAgICAgIGNvbnRhaW5lclNjcm9sbFk6IG51bWJlcjtcbiAgICB9KTogSG92ZXJSZXR1cm4ge1xuICAgICAgY29uc3QgcmVhbFBvc1ggPSBwb3MueCArIHBvcy5jb250YWluZXJTY3JvbGxYO1xuICAgICAgY29uc3QgcmVhbFBvc1kgPSBwb3MueSArIHBvcy5jb250YWluZXJTY3JvbGxZO1xuICAgICAgaWYgKFxuICAgICAgICBjaGFydFNpemluZ1ZhbHVlcyA9PT0gbnVsbCB8fFxuICAgICAgICBnZXRJZkhvdmVyT3V0T2ZCb3VuZHMoXG4gICAgICAgICAgcG9zLngsXG4gICAgICAgICAgcG9zLnksXG4gICAgICAgICAgcmVhbFBvc1gsXG4gICAgICAgICAgcmVhbFBvc1ksXG4gICAgICAgICAgY2hhcnRTaXppbmdWYWx1ZXMsXG4gICAgICAgICAgZGltZW5zaW9ucyxcbiAgICAgICAgKVxuICAgICAgKSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBidWNrZXRJbmRleEluZm8gPSBnZXRGbG93QnVja2V0SW5kZXhGb3JIb3ZlcihcbiAgICAgICAgY2hhcnRTaXppbmdWYWx1ZXMsXG4gICAgICAgIHJlYWxQb3NYLFxuICAgICAgKTtcbiAgICAgIGlmIChidWNrZXRJbmRleEluZm8gPT09IG51bGwgfHwgYnVja2V0SW5kZXhJbmZvLmluZGV4ID49IGJhcnMubGVuZ3RoKSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfVxuICAgICAgaWYgKGJ1Y2tldEluZGV4SW5mby5hcmVhID09PSAnYmFyJykge1xuICAgICAgICBmb3IgKGNvbnN0IGJhciBvZiBiYXJzW2J1Y2tldEluZGV4SW5mby5pbmRleF0pIHtcbiAgICAgICAgICBpZiAocmVhbFBvc1kgPCBiYXIueSkge1xuICAgICAgICAgICAgLy9CYXIgdGl0bGVcbiAgICAgICAgICAgIGNvbnN0IGxvY2FsQW5jaG9yWCA9IGJhci54IC0gcG9zLmNvbnRhaW5lclNjcm9sbFg7XG4gICAgICAgICAgICBjb25zdCB3aWR0aCA9IGJhci53aWR0aDtcbiAgICAgICAgICAgIGNvbnN0IGhlaWdodCA9XG4gICAgICAgICAgICAgIGNoYXJ0U2l6aW5nVmFsdWVzLmRhdGFMYWJlbFBhZGRpbmcgLyAyICtcbiAgICAgICAgICAgICAgY2hhcnRTaXppbmdWYWx1ZXMuZGF0YUxhYmVsVGV4dFNpemU7XG4gICAgICAgICAgICBjb25zdCBsb2NhbEFuY2hvclkgPSBiYXIueSAtIChwb3MuY29udGFpbmVyU2Nyb2xsWSArIGhlaWdodCk7XG4gICAgICAgICAgICBjb25zdCB7IGFuY2hvclgsIGFuY2hvclksIGFuY2hvcldpZHRoLCBhbmNob3JIZWlnaHQgfSA9XG4gICAgICAgICAgICAgIGNoZWNrQW5jaG9yc0FnYWluc3RCb3VuZChcbiAgICAgICAgICAgICAgICBsb2NhbEFuY2hvclgsXG4gICAgICAgICAgICAgICAgbG9jYWxBbmNob3JZLFxuICAgICAgICAgICAgICAgIGRpbWVuc2lvbnMsXG4gICAgICAgICAgICAgICAgd2lkdGgsXG4gICAgICAgICAgICAgICAgaGVpZ2h0LFxuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgY29uc3QgYW5jaG9yID0gbmV3IERPTVJlY3QoXG4gICAgICAgICAgICAgIGFuY2hvclggKyBwb3MucmVjdC54LFxuICAgICAgICAgICAgICBhbmNob3JZICsgcG9zLnJlY3QueSxcbiAgICAgICAgICAgICAgYW5jaG9yV2lkdGgsXG4gICAgICAgICAgICAgIGFuY2hvckhlaWdodCxcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICBob3ZlclR5cGU6ICdmbG93JyxcbiAgICAgICAgICAgICAgaG92ZXJUYXJnZXQ6ICdiYXJUaXRsZScsXG4gICAgICAgICAgICAgIGJhcklkOiBiYXIuaWQgPz8gJycsXG4gICAgICAgICAgICAgIGJ1Y2tldEluZGV4OiBidWNrZXRJbmRleEluZm8uaW5kZXgsXG4gICAgICAgICAgICAgIHRvb2x0aXA6IHtcbiAgICAgICAgICAgICAgICBhbmNob3IsXG4gICAgICAgICAgICAgICAgc3VidGl0bGU6IGNvbmZpZy5mbG93Q29uZmlnLnN1YnRpdGxlRm9ybWF0U3RyaW5nLnJlcGxhY2UoXG4gICAgICAgICAgICAgICAgICAne3ZhbHVlfScsXG4gICAgICAgICAgICAgICAgICB2YWx1ZVBpcGVzLnBpcGUudHJhbnNmb3JtKGJhci50b3RhbENvdW50KSxcbiAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICB9IGVsc2UgaWYgKFxuICAgICAgICAgICAgLy8gVGhlIGludmlzaWJsZSBoaWdobGlnaHQgYmFyIHNwYW5zIGJvdGggcG9ydGlvbnMsIHNvIHNraXAgaXQgdG9cbiAgICAgICAgICAgIC8vIGF2b2lkIG1pc3JlcG9ydGluZyBhIHBvcnRpb24gYm91bmRhcnkgYXMgdGhlIGVuZGluZyBwb3J0aW9uXG4gICAgICAgICAgICAhYmFyLm5vbkRpc3BsYXkgJiZcbiAgICAgICAgICAgIHJlYWxQb3NZID49IGJhci55ICYmXG4gICAgICAgICAgICByZWFsUG9zWSA8IGJhci55ICsgYmFyLmhlaWdodFxuICAgICAgICAgICkge1xuICAgICAgICAgICAgLy9CYXJcbiAgICAgICAgICAgIGNvbnN0IGxvY2FsQW5jaG9yWCA9IGJhci54IC0gcG9zLmNvbnRhaW5lclNjcm9sbFg7XG4gICAgICAgICAgICBjb25zdCB3aWR0aCA9IGJhci53aWR0aDtcbiAgICAgICAgICAgIGNvbnN0IGxvY2FsQW5jaG9yWSA9IGJhci55IC0gcG9zLmNvbnRhaW5lclNjcm9sbFk7XG4gICAgICAgICAgICBjb25zdCBoZWlnaHQgPSBiYXIuaGVpZ2h0O1xuICAgICAgICAgICAgY29uc3QgeyBhbmNob3JYLCBhbmNob3JZLCBhbmNob3JXaWR0aCwgYW5jaG9ySGVpZ2h0IH0gPVxuICAgICAgICAgICAgICBjaGVja0FuY2hvcnNBZ2FpbnN0Qm91bmQoXG4gICAgICAgICAgICAgICAgbG9jYWxBbmNob3JYLFxuICAgICAgICAgICAgICAgIGxvY2FsQW5jaG9yWSxcbiAgICAgICAgICAgICAgICBkaW1lbnNpb25zLFxuICAgICAgICAgICAgICAgIHdpZHRoLFxuICAgICAgICAgICAgICAgIGhlaWdodCxcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGNvbnN0IGFuY2hvciA9IG5ldyBET01SZWN0KFxuICAgICAgICAgICAgICBhbmNob3JYICsgcG9zLnJlY3QueCxcbiAgICAgICAgICAgICAgYW5jaG9yWSArIHBvcy5yZWN0LnksXG4gICAgICAgICAgICAgIGFuY2hvcldpZHRoLFxuICAgICAgICAgICAgICBhbmNob3JIZWlnaHQsXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgaG92ZXJUeXBlOiAnZmxvdycsXG4gICAgICAgICAgICAgIGhvdmVyVGFyZ2V0OiAnYmFyJyxcbiAgICAgICAgICAgICAgYmFySWQ6IGJhci5pZCA/PyAnJyxcbiAgICAgICAgICAgICAgYnVja2V0SW5kZXg6IGJ1Y2tldEluZGV4SW5mby5pbmRleCxcbiAgICAgICAgICAgICAgZm9yRGFya2VuOiBiYXIuZGFya2VuID09PSB0cnVlLFxuICAgICAgICAgICAgICB0b29sdGlwOiB7XG4gICAgICAgICAgICAgICAgYW5jaG9yLFxuICAgICAgICAgICAgICAgIHN1YnRpdGxlOiBjb25maWcuZmxvd0NvbmZpZy5zdWJ0aXRsZUZvcm1hdFN0cmluZy5yZXBsYWNlKFxuICAgICAgICAgICAgICAgICAgJ3t2YWx1ZX0nLFxuICAgICAgICAgICAgICAgICAgdmFsdWVQaXBlcy5waXBlLnRyYW5zZm9ybShiYXIuY291bnQpLFxuICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9O1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZm9yIChjb25zdCBjb25uZWN0aW9uIG9mIGZsb3dDb25uZWN0aW9ucy5maWx0ZXIoXG4gICAgICAgICAgZmxvd0NvbiA9PiBmbG93Q29uLnN0ZXAgPT09IGJ1Y2tldEluZGV4SW5mby5pbmRleCxcbiAgICAgICAgKSkge1xuICAgICAgICAgIGlmIChjaGVja0lmUG9pbnRXaXRoaW5Db25uZWN0aW9uKGNvbm5lY3Rpb24sIHJlYWxQb3NYLCByZWFsUG9zWSkpIHtcbiAgICAgICAgICAgIGNvbnN0IGxvY2FsQW5jaG9yWCA9IGNvbm5lY3Rpb24udG9wTGluZS54MSAtIHBvcy5jb250YWluZXJTY3JvbGxYO1xuICAgICAgICAgICAgY29uc3Qgd2lkdGggPSBjb25uZWN0aW9uLnRvcExpbmUueDIgLSBjb25uZWN0aW9uLnRvcExpbmUueDE7XG4gICAgICAgICAgICBjb25zdCBjdXJ2ZVRvcCA9IGJlemllcllBdFgoXG4gICAgICAgICAgICAgIChjb25uZWN0aW9uLnRvcExpbmUueDEgKyBjb25uZWN0aW9uLnRvcExpbmUueDIpIC8gMixcbiAgICAgICAgICAgICAgY29ubmVjdGlvbi50b3BMaW5lLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGNvbnN0IGN1cnZlQm90dG9tID0gYmV6aWVyWUF0WChcbiAgICAgICAgICAgICAgKGNvbm5lY3Rpb24udG9wTGluZS54MSArIGNvbm5lY3Rpb24udG9wTGluZS54MikgLyAyLFxuICAgICAgICAgICAgICBjb25uZWN0aW9uLmJvdHRvbUxpbmUsXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgY29uc3QgbG9jYWxBbmNob3JZID0gY3VydmVUb3AgLSBwb3MuY29udGFpbmVyU2Nyb2xsWTtcbiAgICAgICAgICAgIGNvbnN0IGhlaWdodCA9IGN1cnZlQm90dG9tIC0gY3VydmVUb3A7XG4gICAgICAgICAgICBjb25zdCB7IGFuY2hvclgsIGFuY2hvclksIGFuY2hvcldpZHRoLCBhbmNob3JIZWlnaHQgfSA9XG4gICAgICAgICAgICAgIGNoZWNrQW5jaG9yc0FnYWluc3RCb3VuZChcbiAgICAgICAgICAgICAgICBsb2NhbEFuY2hvclgsXG4gICAgICAgICAgICAgICAgbG9jYWxBbmNob3JZLFxuICAgICAgICAgICAgICAgIGRpbWVuc2lvbnMsXG4gICAgICAgICAgICAgICAgd2lkdGgsXG4gICAgICAgICAgICAgICAgaGVpZ2h0LFxuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgY29uc3QgYW5jaG9yID0gbmV3IERPTVJlY3QoXG4gICAgICAgICAgICAgIGFuY2hvclggKyBwb3MucmVjdC54LFxuICAgICAgICAgICAgICBhbmNob3JZICsgcG9zLnJlY3QueSxcbiAgICAgICAgICAgICAgYW5jaG9yV2lkdGgsXG4gICAgICAgICAgICAgIGFuY2hvckhlaWdodCxcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICBob3ZlclR5cGU6ICdmbG93JyxcbiAgICAgICAgICAgICAgaG92ZXJUYXJnZXQ6ICdjb25uZWN0aW9uJyxcbiAgICAgICAgICAgICAgc3RhcnRJZDogY29ubmVjdGlvbi5zdGFydCxcbiAgICAgICAgICAgICAgZW5kSWQ6IGNvbm5lY3Rpb24uZW5kLFxuICAgICAgICAgICAgICBzdGFydEJ1Y2tldEluZGV4OiBjb25uZWN0aW9uLnN0ZXAsXG4gICAgICAgICAgICAgIHRvb2x0aXA6IHtcbiAgICAgICAgICAgICAgICBhbmNob3IsXG4gICAgICAgICAgICAgICAgc3VidGl0bGU6IGNvbmZpZy5mbG93Q29uZmlnLnN1YnRpdGxlRm9ybWF0U3RyaW5nLnJlcGxhY2UoXG4gICAgICAgICAgICAgICAgICAne3ZhbHVlfScsXG4gICAgICAgICAgICAgICAgICB2YWx1ZVBpcGVzLnBpcGUudHJhbnNmb3JtKGNvbm5lY3Rpb24uY291bnQpLFxuICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9O1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgY2hhcnRXaWR0aDogY2hhcnRTaXppbmdWYWx1ZXMudG90YWxXaWR0aCxcbiAgICAgIGNoYXJ0SGVpZ2h0OiBjaGFydFNpemluZ1ZhbHVlcy50b3RhbEhlaWdodCxcbiAgICAgIGNoYXJ0U2l6aW5nVmFsdWVzLFxuICAgICAgeFRpY2tzOiBbXSxcbiAgICAgIHlUaWNrczogW10sXG4gICAgICBjb2xvcnM6IFtdLFxuICAgICAgYmFycyxcbiAgICAgIGxpbmVzOiBbXSxcbiAgICAgIGNpcmNsZXM6IFtdLFxuICAgICAgYXJlYXM6IFtdLFxuICAgICAgaG92ZXIsXG4gICAgICBhcmNzOiBbXSxcbiAgICAgIGhvcml6b250YWxCYXJzOiBbXSxcbiAgICAgIGRhdGFMYWJlbHMsXG4gICAgICB3YXRlcmZhbGxMaW5lczogW10sXG4gICAgICBncmFkaWVudHM6IFtdLFxuICAgICAgZmxvd0Nvbm5lY3Rpb25zLFxuICAgICAgaG9yaXpvbnRhbENvbnRhaW5lclNjYWxlOiBjaGFydFNpemluZ1ZhbHVlcy5ob3Jpem9udGFsQ29udGFpbmVyU2NhbGUsXG4gICAgICB2ZXJ0aWNhbENvbnRhaW5lclNjYWxlOiBjaGFydFNpemluZ1ZhbHVlcy52ZXJ0aWNhbENvbnRhaW5lclNjYWxlLFxuICAgICAgY2hhcnRFcnJvcjogbnVsbCxcbiAgICB9O1xuICB9XG5cbiAgLypcbiAgICBNaXJyb3JzIHRoZSBidWNrZXRpbmcgaW4gZmxvd3NUcmFuc2Zvcm06IGEgcGF0aCBjb250cmlidXRlcyB2YWx1ZXNbaV0gdG9cbiAgICB0aGUgYmFyIGF0IHN0ZXAgaSwgYW5kIHZhbHVlc1tpICsgMV0gdG8gaXRzIGZvcndhcmQgY29ubmVjdGlvbiAod2hpY2ggaXNcbiAgICBhbHNvIHRoZSBiYXIncyBjb250aW51aW5nIHBvcnRpb24pLlxuICAqL1xuICBmdW5jdGlvbiBmbG93VmFsdWVBdFN0ZXAoeTogRmxvd1ksIHN0ZXA6IG51bWJlcik6IG51bWJlciB8IG51bGwge1xuICAgIHJldHVybiB5LnN0ZXBzLmxlbmd0aCA+IHN0ZXAgJiYgeS52YWx1ZXMubGVuZ3RoID4gc3RlcFxuICAgICAgPyB5LnZhbHVlc1tzdGVwXVxuICAgICAgOiBudWxsO1xuICB9XG5cbiAgZnVuY3Rpb24gc3VtRmxvd1ZhbHVlcyhcbiAgICBkYXRhOiBGbG93RGF0YSxcbiAgICB5SW5kaWNlczogbnVtYmVyW10sXG4gICAgc3RlcDogbnVtYmVyLFxuICApOiBudW1iZXIge1xuICAgIHJldHVybiB5SW5kaWNlc1xuICAgICAgLm1hcChpbmRleCA9PiBmbG93VmFsdWVBdFN0ZXAoZGF0YS55c1tpbmRleF0sIHN0ZXApID8/IDApXG4gICAgICAucmVkdWNlKChhLCBiKSA9PiBhICsgYiwgMCk7XG4gIH1cblxuICBleHBvcnQgZnVuY3Rpb24gdG9GbG93Q2xpY2tFdmVudChcbiAgICBob3ZlcjogRmxvd0hvdmVyVGFyZ2V0LFxuICAgIGRhdGE6IEZsb3dEYXRhLFxuICApOiBGbG93Q2xpY2tFdmVudCB7XG4gICAgY29uc3QgYWxsWUluZGljZXMgPSBkYXRhLnlzLm1hcCgoXywgaW5kZXgpID0+IGluZGV4KTtcbiAgICBpZiAoaG92ZXIuaG92ZXJUYXJnZXQgPT09ICdjb25uZWN0aW9uJykge1xuICAgICAgY29uc3Qgc3RlcCA9IGhvdmVyLnN0YXJ0QnVja2V0SW5kZXg7XG4gICAgICBjb25zdCB5SW5kaWNlcyA9IGFsbFlJbmRpY2VzLmZpbHRlcihcbiAgICAgICAgaW5kZXggPT5cbiAgICAgICAgICBkYXRhLnlzW2luZGV4XS5zdGVwc1tzdGVwXSA9PT0gaG92ZXIuc3RhcnRJZCAmJlxuICAgICAgICAgIGZsb3dWYWx1ZUF0U3RlcChkYXRhLnlzW2luZGV4XSwgc3RlcCkgIT09IG51bGwgJiZcbiAgICAgICAgICBkYXRhLnlzW2luZGV4XS5zdGVwc1tzdGVwICsgMV0gPT09IGhvdmVyLmVuZElkICYmXG4gICAgICAgICAgZmxvd1ZhbHVlQXRTdGVwKGRhdGEueXNbaW5kZXhdLCBzdGVwICsgMSkgIT09IG51bGwsXG4gICAgICApO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgdGFyZ2V0OiAnY29ubmVjdGlvbicsXG4gICAgICAgIHN0YXJ0QnVja2V0SW5kZXg6IHN0ZXAsXG4gICAgICAgIHN0YXJ0SWQ6IGhvdmVyLnN0YXJ0SWQsXG4gICAgICAgIGVuZElkOiBob3Zlci5lbmRJZCxcbiAgICAgICAgY291bnQ6IHN1bUZsb3dWYWx1ZXMoZGF0YSwgeUluZGljZXMsIHN0ZXAgKyAxKSxcbiAgICAgICAgeUluZGljZXMsXG4gICAgICB9O1xuICAgIH1cblxuICAgIGNvbnN0IHN0ZXAgPSBob3Zlci5idWNrZXRJbmRleDtcbiAgICBjb25zdCBiYXJZSW5kaWNlcyA9IGFsbFlJbmRpY2VzLmZpbHRlcihcbiAgICAgIGluZGV4ID0+XG4gICAgICAgIGRhdGEueXNbaW5kZXhdLnN0ZXBzW3N0ZXBdID09PSBob3Zlci5iYXJJZCAmJlxuICAgICAgICBmbG93VmFsdWVBdFN0ZXAoZGF0YS55c1tpbmRleF0sIHN0ZXApICE9PSBudWxsLFxuICAgICk7XG4gICAgY29uc3QgdG90YWxDb3VudCA9IHN1bUZsb3dWYWx1ZXMoZGF0YSwgYmFyWUluZGljZXMsIHN0ZXApO1xuICAgIGNvbnN0IGJhc2UgPSB7IGJ1Y2tldEluZGV4OiBzdGVwLCBiYXJJZDogaG92ZXIuYmFySWQgfTtcbiAgICBpZiAoaG92ZXIuaG92ZXJUYXJnZXQgPT09ICdiYXJUaXRsZScpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIC4uLmJhc2UsXG4gICAgICAgIHRhcmdldDogJ3RpdGxlJyxcbiAgICAgICAgY291bnQ6IHRvdGFsQ291bnQsXG4gICAgICAgIHlJbmRpY2VzOiBiYXJZSW5kaWNlcyxcbiAgICAgIH07XG4gICAgfVxuXG4gICAgY29uc3QgY29udGludWluZ0NvdW50ID0gc3VtRmxvd1ZhbHVlcyhkYXRhLCBiYXJZSW5kaWNlcywgc3RlcCArIDEpO1xuICAgIGlmIChob3Zlci5mb3JEYXJrZW4pIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIC4uLmJhc2UsXG4gICAgICAgIHRhcmdldDogJ2NvbnRpbnVpbmcnLFxuICAgICAgICBjb3VudDogY29udGludWluZ0NvdW50LFxuICAgICAgICB0b3RhbENvdW50LFxuICAgICAgICB5SW5kaWNlczogYmFyWUluZGljZXMuZmlsdGVyKFxuICAgICAgICAgIGluZGV4ID0+IChmbG93VmFsdWVBdFN0ZXAoZGF0YS55c1tpbmRleF0sIHN0ZXAgKyAxKSA/PyAwKSA+IDAsXG4gICAgICAgICksXG4gICAgICB9O1xuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgLi4uYmFzZSxcbiAgICAgIHRhcmdldDogJ2VuZGluZycsXG4gICAgICBjb3VudDogdG90YWxDb3VudCAtIGNvbnRpbnVpbmdDb3VudCxcbiAgICAgIHRvdGFsQ291bnQsXG4gICAgICB5SW5kaWNlczogYmFyWUluZGljZXMuZmlsdGVyKFxuICAgICAgICBpbmRleCA9PlxuICAgICAgICAgIChmbG93VmFsdWVBdFN0ZXAoZGF0YS55c1tpbmRleF0sIHN0ZXApID8/IDApID5cbiAgICAgICAgICAoZmxvd1ZhbHVlQXRTdGVwKGRhdGEueXNbaW5kZXhdLCBzdGVwICsgMSkgPz8gMCksXG4gICAgICApLFxuICAgIH07XG4gIH1cblxuICBjb25zdCBTTUFMTF9QQURESU5HID0gODtcbiAgZXhwb3J0IGNvbnN0IERFRkFVTFRfRk9OVF9TSVpFID0gMTI7IC8vdGhlIHdpZHRoIGNvbnN0YW50cyBhcmUgYmFzZWQgb24gZm9udCBzaXplIDEyLCBzbyB0aGlzIHZhcmlhYmxlIGNhbiBoZWxwIHcvIHNjYWxpbmdcbiAgZXhwb3J0IGNvbnN0IFdJRFRIX1BFUl9MRVRURVIgPSA2LjU7XG4gIGNvbnN0IFdJRFRIX1BFUl9OVU1CRVIgPSA3O1xuICBjb25zdCBXSURUSF9QRVJfUEVSSU9EID0gMjtcbiAgY29uc3QgV0lEVEhfUEVSX1NMQVNIID0gNDtcbiAgLy9XaGVuIHRoZSBkYXRhIGF4aXMgZ3Jvd3MsIHRoZSBkYXRhIGlzIGFsd2F5cyBnaXZlbiBhdCBsZWFzdCB0aGlzIHBvcnRpb24gb2YgdGhlIHByb3ZpZGVkIHNpemVcbiAgY29uc3QgR1JPV05fREFUQV9NSU5JTVVNX1JBVElPID0gMC41O1xuICBjb25zdCBERUZBVUxUX0hPUklaT05UQUxfQkFSX0NPUk5FUl9SQURJVVMgPSA0O1xuICBjb25zdCBGTE9XX0NPTk5FQ1RJT05fQ1VSVkVfQ09OU1RBTlQgPSAwLjU7XG5cbiAgZnVuY3Rpb24gZ2V0Rm9ybWF0dGluZ0FuZENvbG9ycyhcbiAgICBvcmlnaW5hbERhdGE6IE5vbkZsb3dEYXRhLFxuICAgIGRhdGE6IE5vbkZsb3dEYXRhLFxuICAgIGNvbmZpZzogQ29uZmlnLFxuICApIHtcbiAgICBjb25zdCBkYXRlRm9ybWF0ID0gKGRhdGU6IERhdGUpID0+XG4gICAgICBmb3JtYXRlZERhdGUoY29uZmlnLmRhdGVGb3JtYXQgfHwgJ2RheScsIGRhdGUpO1xuICAgIGNvbnN0IHsgcGlwZSwgZnVsbFBpcGUgfSA9IGdldFBpcGVzKGNvbmZpZy52YWx1ZVR5cGUpO1xuICAgIGNvbnN0IHsgcGlwZTogc2Vjb25kYXJ5UGlwZSwgZnVsbFBpcGU6IHNlY29uZGFyeUZ1bGxQaXBlIH0gPVxuICAgICAgY29uZmlnLnNlY29uZGFyeVZhbHVlVHlwZVxuICAgICAgICA/IGdldFBpcGVzKGNvbmZpZy5zZWNvbmRhcnlWYWx1ZVR5cGUpXG4gICAgICAgIDoge1xuICAgICAgICAgICAgcGlwZSxcbiAgICAgICAgICAgIGZ1bGxQaXBlLFxuICAgICAgICAgIH07XG4gICAgY29uc3QgcGlwZVRyYW5zZm9ybSA9IChcbiAgICAgIHZhbHVlOiBudW1iZXIsXG4gICAgICBpc1NlY29uZGFyeTogYm9vbGVhbiB8IHVuZGVmaW5lZCxcbiAgICAgIGlzRnVsbD86IGJvb2xlYW4sXG4gICAgKTogc3RyaW5nID0+IHtcbiAgICAgIGlmIChpc0Z1bGwgIT09IHRydWUpIHtcbiAgICAgICAgaWYgKGlzU2Vjb25kYXJ5ID09PSB0cnVlKSB7XG4gICAgICAgICAgcmV0dXJuIHNlY29uZGFyeVBpcGUudHJhbnNmb3JtKHZhbHVlKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcGlwZS50cmFuc2Zvcm0odmFsdWUpO1xuICAgICAgfVxuICAgICAgbGV0IHJldFZhbDogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG4gICAgICBpZiAoaXNTZWNvbmRhcnkpIHtcbiAgICAgICAgcmV0VmFsID0gc2Vjb25kYXJ5RnVsbFBpcGUudHJhbnNmb3JtKHZhbHVlKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldFZhbCA9IGZ1bGxQaXBlLnRyYW5zZm9ybSh2YWx1ZSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmV0VmFsICE9PSBudWxsID8gcmV0VmFsIDogJy0nO1xuICAgIH07XG5cbiAgICAvLyBQcmUtY2FsY3VsYXRlIGNvbG9yIGluZGljZXMgZm9yIGFsbCBpdGVtcyAodXNlIG9yaWdpbmFsIGRhdGEgZm9yIHN0YWJsZSBjb2xvcnMpXG4gICAgY29uc3QgY29sb3JJbmRpY2VzID0gY2FsY3VsYXRlQ29sb3JJbmRpY2VzKG9yaWdpbmFsRGF0YSk7XG4gICAgY29uc3QgY29sb3JzID0gZGF0YS55cy5tYXAoeSA9PiBnZXRDb2xvcih5LCBjb2xvckluZGljZXMsIGNvbmZpZy5jb2xvcnMpKTtcblxuICAgIHJldHVybiB7XG4gICAgICBkYXRlRm9ybWF0LFxuICAgICAgcGlwZVRyYW5zZm9ybSxcbiAgICAgIGNvbG9ySW5kaWNlcyxcbiAgICAgIGNvbG9ycyxcbiAgICB9O1xuICB9XG5cbiAgZXhwb3J0IGZ1bmN0aW9uIGNhbGN1bGF0ZUNvbG9ySW5kaWNlcyhcbiAgICBkYXRhOiBOb25GbG93RGF0YSxcbiAgKTogTWFwPERhdGFZIHwgU3VwcGxlbWVudGFyeURhdGFZLCBudW1iZXI+IHtcbiAgICBjb25zdCBjb2xvck1hcCA9IG5ldyBNYXA8RGF0YVkgfCBTdXBwbGVtZW50YXJ5RGF0YVksIG51bWJlcj4oKTtcblxuICAgIC8vIE9yaWdpbmFsIFlzOiB1c2UgdGhlaXIgYXJyYXkgaW5kZXggZGlyZWN0bHlcbiAgICBkYXRhLnlzLmZvckVhY2goKHksIGluZGV4KSA9PiB7XG4gICAgICBjb2xvck1hcC5zZXQoeSwgaW5kZXgpO1xuICAgIH0pO1xuXG4gICAgLy8gU3VwcGxlbWVudGFyeSBZczogZ3JvdXAgYnkgc3VwcGxlbWVudGFsSW5kZXgsIHVzZSBwb3NpdGlvbiB3aXRoaW4gdGhhdCBncm91cFxuICAgIGlmIChoYXNTdXBwbGVtZW50YXJ5RGF0YShkYXRhKSkge1xuICAgICAgY29uc3Qgc3VwcEdyb3VwcyA9IG5ldyBNYXA8bnVtYmVyLCBTdXBwbGVtZW50YXJ5RGF0YVlbXT4oKTtcblxuICAgICAgZGF0YS5zdXBwbGVtZW50YXJ5WXMuZm9yRWFjaChzdXBwWSA9PiB7XG4gICAgICAgIGlmICghc3VwcEdyb3Vwcy5oYXMoc3VwcFkuc3VwcGxlbWVudGFsSW5kZXgpKSB7XG4gICAgICAgICAgc3VwcEdyb3Vwcy5zZXQoc3VwcFkuc3VwcGxlbWVudGFsSW5kZXgsIFtdKTtcbiAgICAgICAgfVxuICAgICAgICBzdXBwR3JvdXBzLmdldChzdXBwWS5zdXBwbGVtZW50YWxJbmRleCkhLnB1c2goc3VwcFkpO1xuICAgICAgfSk7XG5cbiAgICAgIHN1cHBHcm91cHMuZm9yRWFjaChpdGVtcyA9PiB7XG4gICAgICAgIGl0ZW1zLmZvckVhY2goKGl0ZW0sIHBvc2l0aW9uSW5Hcm91cCkgPT4ge1xuICAgICAgICAgIGNvbG9yTWFwLnNldChpdGVtLCBwb3NpdGlvbkluR3JvdXApO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHJldHVybiBjb2xvck1hcDtcbiAgfVxuXG4gIGV4cG9ydCBmdW5jdGlvbiBnZXRDb2xvcihcbiAgICBpdGVtOiBEYXRhWSB8IFN1cHBsZW1lbnRhcnlEYXRhWSB8IHVuZGVmaW5lZCxcbiAgICBjb2xvckluZGljZXM6IE1hcDxEYXRhWSB8IFN1cHBsZW1lbnRhcnlEYXRhWSwgbnVtYmVyPixcbiAgICBjb2xvcnM6IHJlYWRvbmx5IHN0cmluZ1tdLFxuICApOiBzdHJpbmcge1xuICAgIGlmIChpdGVtID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHJldHVybiBjb2xvcnNbMF07XG4gICAgfVxuICAgIGlmIChpdGVtLmNvbG9yVG9rZW4pIHJldHVybiBpdGVtLmNvbG9yVG9rZW47XG4gICAgY29uc3QgY29sb3JJbmRleCA9IGNvbG9ySW5kaWNlcy5nZXQoaXRlbSkgPz8gMDtcbiAgICByZXR1cm4gY29sb3JzW2NvbG9ySW5kZXggJSBjb2xvcnMubGVuZ3RoXTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGdldEJ1Y2tldFRpY2tDb3VudChjaGFydFNpemluZ1ZhbHVlczogRnVsbENoYXJ0U2NhbGVWYWx1ZXMpOiBudW1iZXIge1xuICAgIGxldCBhdmFpbGFibGVTaXplID0gMDtcbiAgICBsZXQgbWluU3BhY2luZyA9IDE7XG4gICAgaWYgKGNoYXJ0U2l6aW5nVmFsdWVzLmNoYXJ0RGF0YURpcmVjdGlvbiA9PT0gJ3ZlcnRpY2FsJykge1xuICAgICAgYXZhaWxhYmxlU2l6ZSA9XG4gICAgICAgIGNoYXJ0U2l6aW5nVmFsdWVzLnRvdGFsV2lkdGggLVxuICAgICAgICBjaGFydFNpemluZ1ZhbHVlcy5sZWZ0UGFkZGluZyAtXG4gICAgICAgIGNoYXJ0U2l6aW5nVmFsdWVzLnJpZ2h0UGFkZGluZztcbiAgICAgIG1pblNwYWNpbmcgPVxuICAgICAgICBjaGFydFNpemluZ1ZhbHVlcy5ob3Jpem9udGFsQXhpc0xhYmVsVGV4dFNpemUgKyBTTUFMTF9QQURESU5HO1xuICAgIH1cbiAgICBpZiAoY2hhcnRTaXppbmdWYWx1ZXMuY2hhcnREYXRhRGlyZWN0aW9uID09PSAnaG9yaXpvbnRhbCcpIHtcbiAgICAgIGF2YWlsYWJsZVNpemUgPVxuICAgICAgICBjaGFydFNpemluZ1ZhbHVlcy50b3RhbEhlaWdodCAtXG4gICAgICAgIGNoYXJ0U2l6aW5nVmFsdWVzLnRvcFBhZGRpbmcgLVxuICAgICAgICBjaGFydFNpemluZ1ZhbHVlcy5ib3R0b21QYWRkaW5nO1xuICAgICAgbWluU3BhY2luZyA9IGNoYXJ0U2l6aW5nVmFsdWVzLnZlcnRpY2FsQXhpc0xhYmVsVGV4dFNpemUgKyBTTUFMTF9QQURESU5HO1xuICAgIH1cbiAgICBtaW5TcGFjaW5nID0gbWluU3BhY2luZyAqIChjaGFydFNpemluZ1ZhbHVlcy5mb250U2l6ZSAvIERFRkFVTFRfRk9OVF9TSVpFKTtcbiAgICByZXR1cm4gTWF0aC5tYXgoMiwgTWF0aC5mbG9vcihhdmFpbGFibGVTaXplIC8gbWluU3BhY2luZykpO1xuICB9XG5cbiAgZnVuY3Rpb24gZ2V0Q2x1c3RlckluZm9Gb3JCdWNrZXQoXG4gICAgZGF0YTogTm9uRmxvd0RhdGEsXG4gICAgY29uZmlnOiBDb25maWcsXG4gICk6IHtcbiAgICBub3JtQ291bnQ6IG51bWJlcjtcbiAgICBzdXBwQ291bnQ6IG51bWJlcjtcbiAgICB0b3RhbDogbnVtYmVyO1xuICAgIG5vcm1DbHVzdGVySW5kaWNlczogbnVtYmVyW107XG4gICAgc3VwcENsdXN0ZXJJbmRpY2VzOiBudW1iZXJbXTtcbiAgfSB7XG4gICAgLy8gU2xvdCBsYXlvdXQgaXMgdGhlIHNhbWUgZm9yIGV2ZXJ5IGJ1Y2tldCDigJQgemVybyB2YWx1ZXMgc3RpbGwgb2NjdXB5XG4gICAgLy8gdGhlaXIgc2xvdCwgdGhleSBqdXN0IHJlbmRlciB3aXRoIG5vIGhlaWdodC93aWR0aC4gVGhpcyBrZWVwcyBidWNrZXRcbiAgICAvLyBzaXplcywgYmFyIHBvc2l0aW9ucywgYW5kIGhvdmVyIGRldGVjdGlvbiBjb25zaXN0ZW50IGFjcm9zcyBidWNrZXRzXG4gICAgLy8gcmVnYXJkbGVzcyBvZiB3aGljaCBzZXJpZXMgaGFwcGVuIHRvIGJlIHplcm8uXG4gICAgY29uc3Qgbm9ybUNsdXN0ZXJJbmRpY2VzID0gZGF0YS55cy5tYXAoKF8sIHlJbmRleCkgPT4geUluZGV4KTtcbiAgICBjb25zdCBub3JtQ2x1c3RlckNvdW50ID0gbm9ybUNsdXN0ZXJJbmRpY2VzLmxlbmd0aDtcbiAgICBjb25zdCBzdXBwQ2x1c3RlckluZGljZXMgPSB1bmlxKFxuICAgICAgaGFzU3VwcGxlbWVudGFyeURhdGEoZGF0YSlcbiAgICAgICAgPyBkYXRhLnN1cHBsZW1lbnRhcnlZcy5tYXAoeSA9PiB5LnN1cHBsZW1lbnRhbEluZGV4KVxuICAgICAgICA6IFtdLFxuICAgICk7XG4gICAgc3VwcENsdXN0ZXJJbmRpY2VzLnNvcnQoKGEsIGIpID0+IGEgLSBiKTtcblxuICAgIGNvbnN0IHN1cHBDbHVzdGVyQ291bnQgPSBzdXBwQ2x1c3RlckluZGljZXMubGVuZ3RoO1xuICAgIGNvbnN0IGFjdHVhbE5vcm1DbHVzdGVyQ291bnQgPSBpc0NsdXN0ZXJlZERhdGEoZGF0YSwgY29uZmlnLCBmYWxzZSlcbiAgICAgID8gbm9ybUNsdXN0ZXJDb3VudFxuICAgICAgOiBNYXRoLm1pbihub3JtQ2x1c3RlckNvdW50LCAxKTtcblxuICAgIHJldHVybiB7XG4gICAgICBub3JtQ291bnQ6IGFjdHVhbE5vcm1DbHVzdGVyQ291bnQsXG4gICAgICBzdXBwQ291bnQ6IHN1cHBDbHVzdGVyQ291bnQsXG4gICAgICB0b3RhbDogYWN0dWFsTm9ybUNsdXN0ZXJDb3VudCArIHN1cHBDbHVzdGVyQ291bnQsXG4gICAgICBub3JtQ2x1c3RlckluZGljZXMsXG4gICAgICBzdXBwQ2x1c3RlckluZGljZXMsXG4gICAgfTtcbiAgfVxuXG4gIC8vVGhpcyBmdW5jdGlvbiBnaXZlcyB0aGUgdG90YWwgZGlzdGFuY2UgZnJvbSB0aGUgc3RhcnQgb2YgdGhlIGdpdmVuIGJ1Y2tldCwgdG8gdGhlIGVuZCBvZiB0aGUgY3VycmVudCBidWNrZXRcbiAgZnVuY3Rpb24gZ2V0QnVja2V0U2l6ZShcbiAgICBkYXRhOiBOb25GbG93RGF0YSxcbiAgICBjb25maWc6IENvbmZpZyxcbiAgICBjaGFydFNpemluZ1ZhbHVlczogRnVsbENoYXJ0U2NhbGVWYWx1ZXMsXG4gICk6IG51bWJlciB7XG4gICAgY29uc3QgdG90YWxCYXJOdW1iZXIgPSBnZXRDbHVzdGVySW5mb0ZvckJ1Y2tldChkYXRhLCBjb25maWcpO1xuICAgIGNvbnN0IGJ1Y2tldFNpemUgPVxuICAgICAgdG90YWxCYXJOdW1iZXIudG90YWwgKiBjaGFydFNpemluZ1ZhbHVlcy5iYXJTaXplICtcbiAgICAgICh0b3RhbEJhck51bWJlci50b3RhbCAtIDEpICogY2hhcnRTaXppbmdWYWx1ZXMuYmFyQ2x1c3RlckdhcDtcblxuICAgIHJldHVybiBidWNrZXRTaXplO1xuICB9XG5cbiAgLy9UaGlzIGZ1bmN0aW9uIGdpdmVzIHRoZSB0b3RhbCBkaXN0YW5jZSBmcm9tIHRoZSBzdGFydCBvZiB0aGUgZ2l2ZW4gYnVja2V0LCB0byB0aGUgc3RhcnQgb2YgdGhlIG5leHQgYnVja2V0XG4gIGZ1bmN0aW9uIGdldFRvdGFsQnVja2V0R2FwKFxuICAgIGRhdGE6IE5vbkZsb3dEYXRhLFxuICAgIGNvbmZpZzogQ29uZmlnLFxuICAgIGNoYXJ0U2l6aW5nVmFsdWVzOiBGdWxsQ2hhcnRTY2FsZVZhbHVlcyxcbiAgKTogbnVtYmVyIHtcbiAgICBjb25zdCBidWNrZXRTaXplID0gZ2V0QnVja2V0U2l6ZShkYXRhLCBjb25maWcsIGNoYXJ0U2l6aW5nVmFsdWVzKTtcbiAgICByZXR1cm4gYnVja2V0U2l6ZSArIGNoYXJ0U2l6aW5nVmFsdWVzLmJ1Y2tldEdhcDtcbiAgfVxuXG4gIC8vVGhpcyBmdW5jdGlvbiBnaXZlcyB0aGUgdG90YWwgZGlzdGFuY2UgZnJvbSB0aGUgc3RhcnQgb2YgdGhlIGZpcnN0IGJ1Y2tldCwgdG8gdGhlIHN0YXJ0IG9mIHRoZSBnaXZlbiBidWNrZXRcbiAgZnVuY3Rpb24gZ2V0VG90YWxQcmVCdWNrZXRHYXAoXG4gICAgZGF0YTogTm9uRmxvd0RhdGEsXG4gICAgY29uZmlnOiBDb25maWcsXG4gICAgY2hhcnRTaXppbmdWYWx1ZXM6IEZ1bGxDaGFydFNjYWxlVmFsdWVzLFxuICAgIGJ1Y2tldEluZGV4OiBudW1iZXIsXG4gICk6IG51bWJlciB7XG4gICAgbGV0IGN1bXVsYXRpdmVCdWNrZXRHYXAgPSAwO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYnVja2V0SW5kZXg7IGkrKykge1xuICAgICAgY3VtdWxhdGl2ZUJ1Y2tldEdhcCArPSBnZXRUb3RhbEJ1Y2tldEdhcChkYXRhLCBjb25maWcsIGNoYXJ0U2l6aW5nVmFsdWVzKTtcbiAgICB9XG4gICAgcmV0dXJuIGN1bXVsYXRpdmVCdWNrZXRHYXA7XG4gIH1cblxuICBmdW5jdGlvbiBnZW5lcmF0ZVRpbWVzZXJpZXNUaWNrcyhcbiAgICBkYXRhOiBUaW1lc2VyaWVzRGF0YSxcbiAgICBjb25maWc6IENvbmZpZyxcbiAgICB0aWNrQ291bnQ6IG51bWJlcixcbiAgICBjaGFydFNpemluZ1ZhbHVlczogRnVsbENoYXJ0U2NhbGVWYWx1ZXMsXG4gICAgZm9ybWF0OiAoZGF0ZTogRGF0ZSkgPT4gc3RyaW5nLFxuICApOiBHZW5lcmljVGlja1tdIHtcbiAgICBjb25zdCBnZXRMYWJlbCA9IChpbmRleDogbnVtYmVyKSA9PiB7XG4gICAgICByZXR1cm4gZm9ybWF0KG5ldyBEYXRlKGRhdGEueFtpbmRleF0pKTtcbiAgICB9O1xuICAgIHJldHVybiBnZXRUaWNrcyhkYXRhLCBnZXRMYWJlbCwgY29uZmlnLCB0aWNrQ291bnQsIGNoYXJ0U2l6aW5nVmFsdWVzKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGdlbmVyYXRlTGFiZWxsZWRUaWNrcyhcbiAgICBkYXRhOiBMYWJlbGVkRGF0YSxcbiAgICBjb25maWc6IENvbmZpZyxcbiAgICB0aWNrQ291bnQ6IG51bWJlcixcbiAgICBjaGFydFNpemluZ1ZhbHVlczogRnVsbENoYXJ0U2NhbGVWYWx1ZXMsXG4gICk6IEdlbmVyaWNUaWNrW10ge1xuICAgIGNvbnN0IGdldExhYmVsID0gKGluZGV4OiBudW1iZXIpID0+IHtcbiAgICAgIHJldHVybiBkYXRhLnhbaW5kZXhdLmxhYmVsO1xuICAgIH07XG4gICAgcmV0dXJuIGdldFRpY2tzKGRhdGEsIGdldExhYmVsLCBjb25maWcsIHRpY2tDb3VudCwgY2hhcnRTaXppbmdWYWx1ZXMpO1xuICB9XG5cbiAgZnVuY3Rpb24gZ2V0VGlja3MoXG4gICAgZGF0YTogTm9uRmxvd0RhdGEsXG4gICAgZ2V0TGFiZWw6IChpbmRleDogbnVtYmVyKSA9PiBzdHJpbmcsXG4gICAgY29uZmlnOiBDb25maWcsXG4gICAgdGlja0NvdW50OiBudW1iZXIsXG4gICAgY2hhcnRTaXppbmdWYWx1ZXM6IEZ1bGxDaGFydFNjYWxlVmFsdWVzLFxuICApOiBHZW5lcmljVGlja1tdIHtcbiAgICBpZiAoZGF0YS54Lmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuIFtdO1xuICAgIH1cbiAgICBpZiAoZGF0YS54Lmxlbmd0aCA9PT0gMSkge1xuICAgICAgY29uc3QgbGFiZWxPZmZzZXQgPSBnZXRUaWNrTGFiZWxPZmZzZXQoXG4gICAgICAgIGRhdGEsXG4gICAgICAgIGNvbmZpZyxcbiAgICAgICAgY2hhcnRTaXppbmdWYWx1ZXMsXG4gICAgICAgIDAsXG4gICAgICApO1xuICAgICAgcmV0dXJuIFt7IHZhbHVlOiBsYWJlbE9mZnNldCwgbGFiZWw6IGdldExhYmVsKDApIH1dO1xuICAgIH1cblxuICAgIGNvbnN0IGxhc3RJbmRleCA9IGRhdGEueC5sZW5ndGggLSAxO1xuICAgIGNvbnN0IHRpY2tCdWNrZXRTcGFjaW5nID0gTWF0aC5jZWlsKGxhc3RJbmRleCAvIHRpY2tDb3VudCk7XG4gICAgY29uc3QgbnVtVGlja3MgPSBNYXRoLmZsb29yKGxhc3RJbmRleCAvIHRpY2tCdWNrZXRTcGFjaW5nKSArIDE7XG4gICAgY29uc3Qgc3RlcCA9IGxhc3RJbmRleCAvIChudW1UaWNrcyAtIDEpO1xuXG4gICAgLy8gQWx3YXlzIGluY2x1ZGUgZmlyc3QgYW5kIGxhc3QgZGF0YSBwb2ludHMuXG4gICAgLy8gSW5uZXIgdGlja3MgYXJlIGFwcHJveGltYXRlbHkgZXZlbmx5IHNwYWNlZCB1c2luZyByb3VuZGluZy5cbiAgICBjb25zdCBpbmRpY2VzOiBudW1iZXJbXSA9IFtdO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbnVtVGlja3M7IGkrKykge1xuICAgICAgaW5kaWNlcy5wdXNoKE1hdGgucm91bmQoaSAqIHN0ZXApKTtcbiAgICB9XG5cbiAgICByZXR1cm4gaW5kaWNlcy5tYXAoaSA9PiB7XG4gICAgICBjb25zdCBsYWJlbE9mZnNldCA9IGdldFRpY2tMYWJlbE9mZnNldChcbiAgICAgICAgZGF0YSxcbiAgICAgICAgY29uZmlnLFxuICAgICAgICBjaGFydFNpemluZ1ZhbHVlcyxcbiAgICAgICAgaSxcbiAgICAgICk7XG4gICAgICByZXR1cm4ge1xuICAgICAgICB2YWx1ZTpcbiAgICAgICAgICBnZXRUb3RhbFByZUJ1Y2tldEdhcChkYXRhLCBjb25maWcsIGNoYXJ0U2l6aW5nVmFsdWVzLCBpKSArXG4gICAgICAgICAgbGFiZWxPZmZzZXQsXG4gICAgICAgIGxhYmVsOiBnZXRMYWJlbChpKSxcbiAgICAgIH07XG4gICAgfSk7XG4gIH1cblxuICBmdW5jdGlvbiBnZXRUaWNrTGFiZWxPZmZzZXQoXG4gICAgZGF0YTogTm9uRmxvd0RhdGEsXG4gICAgY29uZmlnOiBDb25maWcsXG4gICAgY2hhcnRTaXppbmdWYWx1ZXM6IEZ1bGxDaGFydFNjYWxlVmFsdWVzLFxuICAgIGJ1Y2tldEluZGV4OiBudW1iZXIsXG4gICkge1xuICAgIGNvbnN0IGluaGVyZW50T2Zmc2V0ID1cbiAgICAgIGNoYXJ0U2l6aW5nVmFsdWVzLmNoYXJ0RGF0YURpcmVjdGlvbiA9PT0gJ2hvcml6b250YWwnXG4gICAgICAgID8gY2hhcnRTaXppbmdWYWx1ZXMudG90YWxUb3BPZmZzZXRcbiAgICAgICAgOiBjaGFydFNpemluZ1ZhbHVlcy50b3RhbExlZnRPZmZzZXQ7XG4gICAgLy9UbyBoYXZlIHRoZSBsYWJlbCBiZSBjZW50ZXJlZCBvbiB0aGUgYnVja2V0J3MgY2VudGVyIHBvc2l0aW9uXG4gICAgY29uc3QgYnVja2V0T2Zmc2V0ID0gZ2V0QnVja2V0U2l6ZShkYXRhLCBjb25maWcsIGNoYXJ0U2l6aW5nVmFsdWVzKSAvIDI7XG4gICAgbGV0IGhvcml6b250YWxCYXJPZmZzZXQgPSAwO1xuICAgIGlmIChjaGFydFNpemluZ1ZhbHVlcy5jaGFydERhdGFEaXJlY3Rpb24gPT09ICdob3Jpem9udGFsJykge1xuICAgICAgLy9UaGlzIGFjY291bnQgZm9yIHRoZSBmYWN0IHRoYXQgdGhlIGluaGVyZW50T2Zmc2V0IGFuZCBidWNrZXRPZmZzZXQgcmVzdWx0IGluIG1hdGNoaW5nIHkgdmFsdWVzIGZvciB0aGUgYmFyIGFuZCB0aGUgbGFiZWxcbiAgICAgIC8vICBIb3dldmVyLCBmb3IgdGhlIGJhciwgdGhhdCB5IHBvc2l0aW9uIGlzIHRoZSB0b3Agb2YgdGhlIGJhciwgd2hpbGUgZm9yIHRoZSBsYWJlbCwgaXQncyB0aGUgYm90dG9tIG9mIHRoZSBsYWJlbFxuICAgICAgLy8gIFdoZW4gZXhhY3RseSBsaW5lZCB1cCBsaWtlIHRoYXQsIHRoZSBsYWJlbCBhY3R1YWxseSBsb29rcyBhIGxpdHRsZSBsb3csIHNvIHRoYXQgLTIgbWFrZXMgaXQgbG9vayBjb3JyZWN0XG4gICAgICBob3Jpem9udGFsQmFyT2Zmc2V0ID0gY2hhcnRTaXppbmdWYWx1ZXMuZm9udFNpemUgLyAyIC0gMjtcbiAgICB9XG5cbiAgICByZXR1cm4gaW5oZXJlbnRPZmZzZXQgKyBidWNrZXRPZmZzZXQgKyBob3Jpem9udGFsQmFyT2Zmc2V0O1xuICB9XG5cbiAgZXhwb3J0IHR5cGUgSW5wdXREYXRhID0gTGFiZWxlZERhdGEgfCBUaW1lc2VyaWVzRGF0YSB8IEZsb3dEYXRhO1xuICBleHBvcnQgdHlwZSBQcm9jZXNzRGF0YSA9IExhYmVsZWREYXRhIHwgVGltZXNlcmllc0RhdGEgfCBQcm9jZXNzZWRGbG93RGF0YTtcbiAgZXhwb3J0IHR5cGUgTm9uRmxvd0RhdGEgPSBMYWJlbGVkRGF0YSB8IFRpbWVzZXJpZXNEYXRhO1xuXG4gIHR5cGUgQmFzZURhdGEgPSB7XG4gICAgeXM6IERhdGFZW107XG4gICAgc3VwcGxlbWVudGFyeVlzPzogU3VwcGxlbWVudGFyeURhdGFZW107XG4gIH07XG5cbiAgZXhwb3J0IHR5cGUgUGF0dGVybiA9ICdzb2xpZCcgfCAnc3RyaXBlZCcgfCAnZG90cyc7XG5cbiAgZXhwb3J0IHR5cGUgRGF0YVkgPSB7XG4gICAgbGFiZWw6IHN0cmluZztcbiAgICBjb2xvclRva2VuPzogc3RyaW5nO1xuICAgIGhpZGRlbj86IGJvb2xlYW47XG4gICAgaXNTZWNvbmRhcnk/OiBib29sZWFuO1xuICAgIHBhdHRlcm4/OiBQYXR0ZXJuO1xuICAgIHNob3dMZWdlbmRJdGVtPzogYm9vbGVhbjtcbiAgICBjbGlja2FibGU/OiBib29sZWFuO1xuICAgIHZhbHVlczogbnVtYmVyW107XG4gIH07XG5cbiAgZXhwb3J0IHR5cGUgU3VwcGxlbWVudGFyeURhdGFZID0gRGF0YVkgJiB7XG4gICAgc3VwcGxlbWVudGFsSW5kZXg6IG51bWJlcjtcbiAgfTtcblxuICBleHBvcnQgdHlwZSBGbG93WSA9IHtcbiAgICBzdGVwczogc3RyaW5nW107IC8vU2hvdWxkIGFsd2F5cyBtYXRjaCBpbiBsZW5ndGggdy8gdmFsdWVzXG4gICAgdmFsdWVzOiBudW1iZXJbXTsgLy9GbG93WSB2YWx1ZXMgc2hvdWxkIGFsd2F5cyBiZSB3ZWFrbHkgZGVjcmVhc2luZ1xuICAgIGNsaWNrYWJsZT86IGJvb2xlYW47XG4gIH07XG5cbiAgLy9DdXJyZW50bHkgb25seSBzdXBwb3J0ZWQgZm9yIGhvcml6b250YWwgYmFyIGNoYXJ0c1xuICBleHBvcnQgdHlwZSBMYWJlbGVkRGF0YSA9IEJhc2VEYXRhICYge1xuICAgIHR5cGU6ICdsYWJlbGVkJztcbiAgICB4OiB7IGxhYmVsOiBzdHJpbmc7IGlzU2Vjb25kYXJ5PzogYm9vbGVhbiB9W107XG4gIH07XG5cbiAgZXhwb3J0IHR5cGUgVGltZXNlcmllc0RhdGEgPSBCYXNlRGF0YSAmIHtcbiAgICB0eXBlOiAndGltZXNlcmllcyc7XG4gICAgeDogbnVtYmVyW107XG4gIH07XG5cbiAgZXhwb3J0IHR5cGUgRmxvd0RhdGEgPSB7XG4gICAgdHlwZTogJ2Zsb3cnO1xuICAgIHlzOiBGbG93WVtdO1xuICB9O1xuXG4gIGV4cG9ydCB0eXBlIFByb2Nlc3NlZEZsb3dEYXRhID0ge1xuICAgIHR5cGU6ICdmbG93LXByb2Nlc3NlZCc7XG4gICAgeDogRmxvd0J1Y2tldFtdO1xuICB9O1xuXG4gIHR5cGUgRmxvd0J1Y2tldCA9IHtcbiAgICB0b3RhbENvdW50OiBudW1iZXI7XG4gICAgc3ViQnVja2V0czogRmxvd1N1YkJ1Y2tldFtdO1xuICB9O1xuXG4gIHR5cGUgRmxvd1N1YkJ1Y2tldCA9IHtcbiAgICBpZDogc3RyaW5nO1xuICAgIGNvdW50OiBudW1iZXI7XG4gICAgY29ubmVjdGlvbnM6IEZsb3dDb25uZWN0aW9uW107XG4gIH07XG5cbiAgdHlwZSBGbG93Q29ubmVjdGlvbiA9IHtcbiAgICBkaXJlY3Rpb246ICdmb3J3YXJkJyB8ICdiYWNrd2FyZCc7XG4gICAgc3RhcnQ6IHN0cmluZztcbiAgICBlbmQ6IHN0cmluZztcbiAgICBjb3VudDogbnVtYmVyO1xuICB9O1xuXG4gIGV4cG9ydCB0eXBlIEZsb3dDb25uZWN0aW9uUmVuZGVyID0gT21pdDxGbG93Q29ubmVjdGlvbiwgJ2RpcmVjdGlvbic+ICYge1xuICAgIGVsZW1lbnRUeXBlOiAnY29ubmVjdGlvbic7XG4gICAgc3RlcDogbnVtYmVyO1xuICAgIHBhdGg6IHN0cmluZztcbiAgICBlbXBoYXNpemU/OiBib29sZWFuO1xuICAgIHRvcExpbmU6IHtcbiAgICAgIHgxOiBudW1iZXI7XG4gICAgICB5MTogbnVtYmVyO1xuICAgICAgeDI6IG51bWJlcjtcbiAgICAgIHkyOiBudW1iZXI7XG4gICAgfTtcbiAgICBib3R0b21MaW5lOiB7XG4gICAgICB4MTogbnVtYmVyO1xuICAgICAgeTE6IG51bWJlcjtcbiAgICAgIHgyOiBudW1iZXI7XG4gICAgICB5MjogbnVtYmVyO1xuICAgIH07XG4gIH07XG5cbiAgdHlwZSBEb251dERhdGEgPSB7XG4gICAgbGFiZWw6IHN0cmluZztcbiAgICBoaWRkZW4/OiBib29sZWFuO1xuICAgIHZhbHVlOiBudW1iZXI7XG4gICAgaXNTZWNvbmRhcnk/OiBib29sZWFuO1xuICB9O1xuXG4gIHR5cGUgRGltZW5zaW9ucyA9IHtcbiAgICB3aWR0aDogbnVtYmVyO1xuICAgIGhlaWdodDogbnVtYmVyO1xuICB9O1xuXG4gIGV4cG9ydCB0eXBlIENoYXJ0VHlwZSA9XG4gICAgfCAnbGluZSdcbiAgICB8ICdhcmVhJ1xuICAgIHwgJ2JhcidcbiAgICB8ICdob3Jpem9udGFsLWJhcidcbiAgICB8ICdkb251dCdcbiAgICB8ICd3YXRlcmZhbGwnXG4gICAgfCAnZnVubmVsJ1xuICAgIHwgJ2Zsb3cnO1xuXG4gIHR5cGUgQmFzZUNvbmZpZyA9IHtcbiAgICB0eXBlOiBDaGFydFR5cGU7XG4gICAgZ3JvdXBlZFRvb2x0aXA6IGJvb2xlYW47XG4gICAgY29sb3JzOiBzdHJpbmdbXTtcbiAgICBhbGxvd0xlZ2VuZFRvZ2dsZTogYm9vbGVhbjtcbiAgICB6ZXJvU3RhdGVNZXNzYWdlOiBzdHJpbmc7XG4gICAgc2l6aW5nRXJyb3JTdGF0ZU1lc3NhZ2U6IHN0cmluZztcbiAgICB2YWx1ZVR5cGU6IFZhbHVlVHlwZTtcbiAgICBzZWNvbmRhcnlWYWx1ZVR5cGU/OiBWYWx1ZVR5cGU7XG4gICAgdHJ1bmNhdGVMZWdlbmQ6IGJvb2xlYW47XG4gICAgZGF0ZUZvcm1hdD86IEludGVydmFsO1xuICAgIHNob3dEYXRhTGFiZWxzPzogYm9vbGVhbjtcbiAgfTtcblxuICB0eXBlIERvbnV0U3ViQ29uZmlnID0ge1xuICAgIHNpemU6ICd4c21hbGwnIHwgJ3NtYWxsJyB8ICdtZWRpdW0nIHwgJ2xhcmdlJztcbiAgICBkaXNwbGF5VmFsdWU6IHN0cmluZztcbiAgICBkaXNwbGF5TGFiZWw/OiBzdHJpbmc7XG4gICAgc2NhbGluZ0NvbmZpZz86IERvbnV0U2l6aW5nQ29uZmlnO1xuICB9O1xuXG4gIHR5cGUgRmxvd1N1YkNvbmZpZyA9IHtcbiAgICBzdWJ0aXRsZUZvcm1hdFN0cmluZzogc3RyaW5nO1xuICAgIHN1YkJ1Y2tldHNDb25maWc6IHtcbiAgICAgIGJ1Y2tldElkOiBzdHJpbmc7XG4gICAgICBidWNrZXROYW1lOiBzdHJpbmc7XG4gICAgICBjb2xvcjogc3RyaW5nO1xuICAgICAgaXNIaWdobGlnaHRlZD86IGJvb2xlYW47XG4gICAgfVtdO1xuICAgIGNvbm5lY3Rpb25Db2xvcj86IHN0cmluZztcbiAgfTtcblxuICBleHBvcnQgdHlwZSBDb25maWcgPSBCYXNlQ29uZmlnICZcbiAgICAoXG4gICAgICB8IHtcbiAgICAgICAgICB0eXBlOiAnbGluZScgfCAnYXJlYScgfCAnd2F0ZXJmYWxsJyB8ICdmdW5uZWwnO1xuICAgICAgICAgIHNjYWxpbmdDb25maWc/OiBGdWxsU2NhbGluZ0NvbmZpZztcbiAgICAgICAgfVxuICAgICAgfCB7XG4gICAgICAgICAgdHlwZTogJ2JhcicgfCAnaG9yaXpvbnRhbC1iYXInO1xuICAgICAgICAgIGdyb3VwaW5nVHlwZTogJ3N0YWNrZWQnIHwgJ2NsdXN0ZXJlZCc7XG4gICAgICAgICAgc2NhbGluZ0NvbmZpZz86IEZ1bGxTY2FsaW5nQ29uZmlnO1xuICAgICAgICB9XG4gICAgICB8IHtcbiAgICAgICAgICB0eXBlOiAnZG9udXQnO1xuICAgICAgICAgIGRvbnV0RGlzcGxheUluZm86IERvbnV0U3ViQ29uZmlnO1xuICAgICAgICB9XG4gICAgICB8IHtcbiAgICAgICAgICB0eXBlOiAnZmxvdyc7XG4gICAgICAgICAgc2hvd0RhdGFMYWJlbHM6IHRydWU7XG4gICAgICAgICAgZmxvd0NvbmZpZzogRmxvd1N1YkNvbmZpZztcbiAgICAgICAgICBzY2FsaW5nQ29uZmlnPzogRnVsbFNjYWxpbmdDb25maWc7XG4gICAgICAgIH1cbiAgICApO1xuXG4gIHR5cGUgRG9udXRDb25maWcgPSBFeHRyYWN0PENvbmZpZywgeyB0eXBlOiAnZG9udXQnIH0+O1xuXG4gIHR5cGUgRmxvd0NvbmZpZyA9IEV4dHJhY3Q8Q29uZmlnLCB7IHR5cGU6ICdmbG93JyB9PjtcblxuICB0eXBlIENvbmZpZ1dpdGhGdWxsU2NhbGluZyA9IEV4dHJhY3Q8XG4gICAgQ29uZmlnLFxuICAgIHtcbiAgICAgIHR5cGU6XG4gICAgICAgIHwgJ2JhcidcbiAgICAgICAgfCAnaG9yaXpvbnRhbC1iYXInXG4gICAgICAgIHwgJ2xpbmUnXG4gICAgICAgIHwgJ2FyZWEnXG4gICAgICAgIHwgJ3dhdGVyZmFsbCdcbiAgICAgICAgfCAnZnVubmVsJ1xuICAgICAgICB8ICdmbG93JztcbiAgICB9XG4gID47XG5cbiAgZXhwb3J0IGNvbnN0IGRlZmF1bHRDb25maWc6IENvbmZpZyA9IHtcbiAgICB0eXBlOiAnbGluZScsXG4gICAgZ3JvdXBlZFRvb2x0aXA6IHRydWUsXG4gICAgY29sb3JzOiBkZWZhdWx0Q29sb3JQYWxldHRlLFxuICAgIGFsbG93TGVnZW5kVG9nZ2xlOiBmYWxzZSxcbiAgICB6ZXJvU3RhdGVNZXNzYWdlOiAnTm8gZGF0YSB0byBkaXNwbGF5LicsXG4gICAgc2l6aW5nRXJyb3JTdGF0ZU1lc3NhZ2U6ICdUaGUgY2hhcnQgY2Fubm90IGRpc3BsYXkgYXQgdGhlIGN1cnJlbnQgc2l6ZS4nLFxuICAgIHZhbHVlVHlwZTogJ2N1cnJlbmN5JyxcbiAgICB0cnVuY2F0ZUxlZ2VuZDogdHJ1ZSxcbiAgICBkYXRlRm9ybWF0OiAnZGF5JyxcbiAgfTtcblxuICBleHBvcnQgY29uc3QgZGVmYXVsdERvbnV0Q29uZmlnOiBDb25maWcgPSB7XG4gICAgdHlwZTogJ2RvbnV0JyxcbiAgICBncm91cGVkVG9vbHRpcDogdHJ1ZSxcbiAgICBjb2xvcnM6IGRlZmF1bHRDb2xvclBhbGV0dGUsXG4gICAgYWxsb3dMZWdlbmRUb2dnbGU6IGZhbHNlLFxuICAgIHplcm9TdGF0ZU1lc3NhZ2U6ICdObyBkYXRhIHRvIGRpc3BsYXkuJyxcbiAgICBzaXppbmdFcnJvclN0YXRlTWVzc2FnZTogJ1RoZSBjaGFydCBjYW5ub3QgZGlzcGxheSBhdCB0aGUgY3VycmVudCBzaXplLicsXG4gICAgdmFsdWVUeXBlOiAnY3VycmVuY3knLFxuICAgIHRydW5jYXRlTGVnZW5kOiB0cnVlLFxuICAgIGRhdGVGb3JtYXQ6ICdkYXknLFxuICAgIGRvbnV0RGlzcGxheUluZm86IHtcbiAgICAgIHNpemU6ICdtZWRpdW0nLFxuICAgICAgZGlzcGxheVZhbHVlOiAnJyxcbiAgICB9LFxuICB9O1xuXG4gIHR5cGUgR2VuZXJpY1RpY2sgPSB7XG4gICAgdmFsdWU6IG51bWJlcjtcbiAgICBsYWJlbDogc3RyaW5nO1xuICAgIHNlY29uZGFyeUxhYmVsPzogc3RyaW5nO1xuICB9O1xuXG4gIHR5cGUgWFRpY2sgPSBPbWl0PEdlbmVyaWNUaWNrLCAndmFsdWUnPiAmIHtcbiAgICB4OiBudW1iZXI7XG4gIH07XG5cbiAgZnVuY3Rpb24gdG9YVGljayh0aWNrOiBHZW5lcmljVGljayk6IFhUaWNrIHtcbiAgICByZXR1cm4ge1xuICAgICAgeDogdGljay52YWx1ZSxcbiAgICAgIGxhYmVsOiB0aWNrLmxhYmVsLFxuICAgICAgc2Vjb25kYXJ5TGFiZWw6IHRpY2suc2Vjb25kYXJ5TGFiZWwsXG4gICAgfTtcbiAgfVxuXG4gIHR5cGUgWVRpY2sgPSBPbWl0PEdlbmVyaWNUaWNrLCAndmFsdWUnPiAmIHtcbiAgICB5OiBudW1iZXI7XG4gIH07XG5cbiAgZnVuY3Rpb24gdG9ZVGljayh0aWNrOiBHZW5lcmljVGljayk6IFlUaWNrIHtcbiAgICByZXR1cm4ge1xuICAgICAgeTogdGljay52YWx1ZSxcbiAgICAgIGxhYmVsOiB0aWNrLmxhYmVsLFxuICAgICAgc2Vjb25kYXJ5TGFiZWw6IHRpY2suc2Vjb25kYXJ5TGFiZWwsXG4gICAgfTtcbiAgfVxuXG4gIHR5cGUgQmFzaWNSZWN0ID0ge1xuICAgIGVsZW1lbnRUeXBlOiAncmVjdCc7XG4gICAgcmVjdFR5cGU/OiBzdHJpbmc7XG4gICAgeDogbnVtYmVyO1xuICAgIHk6IG51bWJlcjtcbiAgICB3aWR0aDogbnVtYmVyO1xuICAgIGhlaWdodDogbnVtYmVyO1xuICAgIG9mZnNldD86IG51bWJlcjtcbiAgICBwYXR0ZXJuPzogUGF0dGVybjtcbiAgICByb3VuZGluZz86ICd0b3AnIHwgJ2JvdHRvbScgfCAnYWxsJyB8ICdub25lJztcbiAgICBub25EaXNwbGF5PzogYm9vbGVhbjtcbiAgfTtcblxuICB0eXBlIEZsb3dSZWN0ID0gQmFzaWNSZWN0ICYge1xuICAgIHJlY3RUeXBlOiAnZmxvdyc7XG4gICAgaWQ6IHN0cmluZztcbiAgICBidWNrZXRJbmRleDogbnVtYmVyO1xuICAgIGNvdW50OiBudW1iZXI7XG4gICAgdG90YWxDb3VudDogbnVtYmVyO1xuICAgIGNvbG9yT3ZlcnJpZGU/OiBzdHJpbmc7XG4gICAgZGFya2VuOiBib29sZWFuO1xuICAgIGRlRW1waGFzaXplOiBib29sZWFuO1xuICB9O1xuXG4gIGV4cG9ydCB0eXBlIFJlY3QgPSAoQmFzaWNSZWN0ICYgeyByZWN0VHlwZT86IHVuZGVmaW5lZCB9KSB8IEZsb3dSZWN0O1xuXG4gIHR5cGUgQ2lyY2xlID0ge1xuICAgIGN4OiBudW1iZXI7XG4gICAgY3k6IG51bWJlcjtcbiAgfTtcblxuICBleHBvcnQgdHlwZSBGbG93SG92ZXJUYXJnZXQgPVxuICAgIHwge1xuICAgICAgICBob3ZlclRhcmdldDogJ2JhclRpdGxlJztcbiAgICAgICAgYnVja2V0SW5kZXg6IG51bWJlcjtcbiAgICAgICAgYmFySWQ6IHN0cmluZztcbiAgICAgIH1cbiAgICB8IHtcbiAgICAgICAgaG92ZXJUYXJnZXQ6ICdiYXInO1xuICAgICAgICBidWNrZXRJbmRleDogbnVtYmVyO1xuICAgICAgICBiYXJJZDogc3RyaW5nO1xuICAgICAgICBmb3JEYXJrZW46IGJvb2xlYW47XG4gICAgICB9XG4gICAgfCB7XG4gICAgICAgIGhvdmVyVGFyZ2V0OiAnY29ubmVjdGlvbic7XG4gICAgICAgIHN0YXJ0SWQ6IHN0cmluZztcbiAgICAgICAgZW5kSWQ6IHN0cmluZztcbiAgICAgICAgc3RhcnRCdWNrZXRJbmRleDogbnVtYmVyO1xuICAgICAgfTtcblxuICBleHBvcnQgdHlwZSBGbG93SG92ZXJSZXR1cm4gPSB7XG4gICAgaG92ZXJUeXBlOiAnZmxvdyc7XG5cbiAgICB0b29sdGlwOiB7XG4gICAgICBhbmNob3I6IERPTVJlY3Q7XG4gICAgICBzdWJ0aXRsZTogc3RyaW5nO1xuICAgICAgc2Vjb25kYXJ5U3VidGl0bGU/OiBzdHJpbmc7XG4gICAgfTtcbiAgfSAmIEZsb3dIb3ZlclRhcmdldDtcblxuICAvKipcbiAgICogRW1pdHRlZCB3aGVuIGEgY2xpY2thYmxlIGZsb3cgZWxlbWVudCBpcyBjbGlja2VkLiBgeUluZGljZXNgIGFyZSB0aGVcbiAgICogaW5kaWNlcyBpbnRvIGBGbG93RGF0YS55c2Agb2YgdGhlIHBhdGhzIHRoYXQgbWFrZSB1cCB0aGUgY2xpY2tlZCBlbGVtZW50LlxuICAgKi9cbiAgZXhwb3J0IHR5cGUgRmxvd0NsaWNrRXZlbnQgPSB7XG4gICAgY291bnQ6IG51bWJlcjtcbiAgICB5SW5kaWNlczogbnVtYmVyW107XG4gIH0gJiAoXG4gICAgfCAoe1xuICAgICAgICBidWNrZXRJbmRleDogbnVtYmVyO1xuICAgICAgICBiYXJJZDogc3RyaW5nO1xuICAgICAgfSAmIChcbiAgICAgICAgfCB7XG4gICAgICAgICAgICB0YXJnZXQ6ICd0aXRsZSc7XG4gICAgICAgICAgfVxuICAgICAgICB8IHtcbiAgICAgICAgICAgIHRhcmdldDogJ2NvbnRpbnVpbmcnIHwgJ2VuZGluZyc7XG4gICAgICAgICAgICB0b3RhbENvdW50OiBudW1iZXI7XG4gICAgICAgICAgfVxuICAgICAgKSlcbiAgICB8IHtcbiAgICAgICAgdGFyZ2V0OiAnY29ubmVjdGlvbic7XG4gICAgICAgIHN0YXJ0QnVja2V0SW5kZXg6IG51bWJlcjtcbiAgICAgICAgc3RhcnRJZDogc3RyaW5nO1xuICAgICAgICBlbmRJZDogc3RyaW5nO1xuICAgICAgfVxuICApO1xuXG4gIGV4cG9ydCB0eXBlIEhvdmVyUmV0dXJuID1cbiAgICB8IHtcbiAgICAgICAgaG92ZXJUeXBlOiAnc3RhbmRhcmQnO1xuICAgICAgICAvLyB0aGUgaW5kaWNlcyBpbnRvIHRoZSBkYXRhIG9mIHRoZSBjbG9zZXN0IHBvaW50XG4gICAgICAgIHhJbmRleDogbnVtYmVyO1xuICAgICAgICAvLyB3ZSB3YW50IHRvIGtub3cgd2hpY2ggdmlzaWJsZSB5IGluZGV4IGlzIGhvdmVyZWRcbiAgICAgICAgLy8gYW5kIHdoaWNoIGFjdHVhbCB5IGluZGV4IGlzIGhvdmVyZWRcbiAgICAgICAgeUluZGV4OiBudW1iZXI7XG4gICAgICAgIHZpc2libGVZSW5kZXg6IG51bWJlcjtcbiAgICAgICAgaXNTdXBwVmFsdWU/OiBib29sZWFuO1xuICAgICAgICBzdXBwWUluZGV4PzogbnVtYmVyO1xuICAgICAgICAvL0Z1bm5lbCBvbmx5LCBmb3Igd2hlbiBkcm9wT2ZmIHNlY3Rpb24gaXMgaG92ZXJlZFxuICAgICAgICBpc0Ryb3BPZmY/OiBib29sZWFuO1xuXG4gICAgICAgIC8vIHRoZSB2aWV3cG9ydCB4IGFuZCB5cyBvZiB0aGUgaG92ZXJlZCBpdGVtc1xuICAgICAgICB4OiBudW1iZXI7XG4gICAgICAgIHlzOiBudW1iZXJbXTtcblxuICAgICAgICB0b29sdGlwOiB7XG4gICAgICAgICAgYW5jaG9yOiBET01SZWN0O1xuICAgICAgICAgIHByZWZlcnJlZFBvc2l0aW9uPzogQ2FsbG91dENvbXBvbmVudC5BbmNob3JlZFBvc2l0aW9uO1xuICAgICAgICAgIGRhdGU6IHN0cmluZyB8IG51bGw7XG4gICAgICAgICAgbWV0cmljczoge1xuICAgICAgICAgICAgY29sb3I6IHN0cmluZztcbiAgICAgICAgICAgIGxhYmVsOiBzdHJpbmc7XG4gICAgICAgICAgICB2YWx1ZTogc3RyaW5nO1xuICAgICAgICAgICAgcGF0dGVybj86IFBhdHRlcm47XG4gICAgICAgICAgfVtdO1xuICAgICAgICB9O1xuICAgICAgfVxuICAgIHwgRmxvd0hvdmVyUmV0dXJuXG4gICAgfCBudWxsO1xuXG4gIC8vIEhvdmVyIGlzIGEgZnVuY3Rpb24gdGhhdCB0YWtlcyBhIHZpZXdwb3J0IHggYW5kIHkgYW5kIHJldHVybnMgYSByaWNoXG4gIC8vIHNldCBvZiBpbmZvcm1hdGlvbiBhYm91dCB3aGF0IHZhbHVlcyBhcmUgYmVpbmcgaG92ZXJlZCBhbmQgd2hhdCB0aGUgdG9vbHRpcFxuICAvLyBzaG91bGQgbG9vayBsaWtlXG4gIGV4cG9ydCB0eXBlIEhvdmVyID0gKHBvczoge1xuICAgIHJlY3Q6IERPTVJlY3Q7XG4gICAgeDogbnVtYmVyO1xuICAgIHk6IG51bWJlcjtcbiAgICBjb250YWluZXJTY3JvbGxYOiBudW1iZXI7XG4gICAgY29udGFpbmVyU2Nyb2xsWTogbnVtYmVyO1xuICB9KSA9PiBIb3ZlclJldHVybjtcblxuICBleHBvcnQgdHlwZSBUb29sdGlwQ29udGV4dCA9IHtcbiAgICB4SW5kZXg6IG51bWJlcjtcbiAgICB5SW5kZXg6IG51bWJlcjtcbiAgICBpc1N1cHBWYWx1ZT86IGJvb2xlYW47XG4gICAgc3VwcFlJbmRleD86IG51bWJlcjtcbiAgfTtcblxuICAvLyBSZW5kZXJlZENoYXJ0IHJlcHJlc2VudHMgYWxsIG9mIHRoZSBwYXJ0cyBvZiBhIGNoYXJ0XG4gIC8vIHRoYXQgZW5kIHVwIG9uIHNjcmVlbi4gRXZlcnkgY2hhcnQgaGFzIHggYW5kIHkgdGlja3NcbiAgLy8gYW5kIGhvdmVyIGZ1bmN0aW9uYWxpdHksIGV2ZW4gdGhvdWdoIHRoZXkgbWlnaHQgYmVcbiAgLy8gZGlmZmVyZW50IGZyb20gY2hhcnQgdG8gY2hhcnQuXG4gIGV4cG9ydCB0eXBlIFJlbmRlcmVkQ2hhcnQgPSB7XG4gICAgY2hhcnRXaWR0aDogbnVtYmVyO1xuICAgIGNoYXJ0SGVpZ2h0OiBudW1iZXI7XG4gICAgY2hhcnRTaXppbmdWYWx1ZXM6IEZ1bGxDaGFydFNjYWxlVmFsdWVzO1xuICAgIHhUaWNrczogWFRpY2tbXTtcbiAgICB5VGlja3M6IFlUaWNrW107XG4gICAgaG92ZXI/OiBIb3ZlcjtcbiAgICBjb2xvcnM6IHN0cmluZ1tdO1xuICAgIGxpbmVzOiB7IHBhdHRlcm4/OiBQYXR0ZXJuOyBsaW5lOiBzdHJpbmcgfCBudWxsIH1bXTtcbiAgICBjaXJjbGVzOiBDaXJjbGVbXTsgLy9MaW5lIGZhbGxiYWNrIGZvciBhIHNpbmdsZSBwb2ludFxuICAgIGFyZWFzOiB7IHBhdHRlcm4/OiBQYXR0ZXJuOyBhcmVhOiBzdHJpbmcgfCBudWxsIH1bXTtcbiAgICBiYXJzOiBSZWN0W11bXTtcbiAgICBhcmNzOiAoc3RyaW5nIHwgbnVsbClbXTtcbiAgICBob3Jpem9udGFsQmFyczoge1xuICAgICAgcGF0dGVybj86IFBhdHRlcm47XG4gICAgICBob3Jpem9udGFsQmFyOiBzdHJpbmcgfCBudWxsO1xuICAgICAgeDogbnVtYmVyO1xuICAgICAgeTogbnVtYmVyO1xuICAgIH1bXVtdO1xuICAgIGRhdGFMYWJlbHM6IERhdGFMYWJlbFtdO1xuICAgIHdhdGVyZmFsbExpbmVzOiB7XG4gICAgICB4MTogbnVtYmVyO1xuICAgICAgeDI6IG51bWJlcjtcbiAgICAgIHkxOiBudW1iZXI7XG4gICAgICB5MjogbnVtYmVyO1xuICAgIH1bXTtcbiAgICBncmFkaWVudHM6IFJlY3RbXVtdO1xuICAgIGZsb3dDb25uZWN0aW9uczogRmxvd0Nvbm5lY3Rpb25SZW5kZXJbXTtcbiAgICBob3Jpem9udGFsQ29udGFpbmVyU2NhbGU6IENvbnRhaW5lclNjYWxpbmdUeXBlO1xuICAgIHZlcnRpY2FsQ29udGFpbmVyU2NhbGU6IENvbnRhaW5lclNjYWxpbmdUeXBlO1xuICAgIGNoYXJ0RXJyb3I6ICdzaXppbmcnIHwgJ2NvbmZpZycgfCBudWxsO1xuICB9O1xuXG4gIHR5cGUgQmFzaWNEYXRhTGFiZWwgPSB7XG4gICAgZWxlbWVudFR5cGU6ICdkYXRhTGFiZWwnO1xuICAgIGRhdGFMYWJlbFR5cGU/OiBzdHJpbmc7XG4gICAgbGFiZWw6IHN0cmluZztcbiAgICB4UG9zOiBudW1iZXI7XG4gICAgeVBvczogbnVtYmVyO1xuICAgIGFuY2hvcjogJ3N0YXJ0JyB8ICdtaWRkbGUnIHwgJ2VuZCc7XG4gICAgbGluZT86IHtcbiAgICAgIHgxOiBudW1iZXI7XG4gICAgICB5MTogbnVtYmVyO1xuICAgICAgeDI6IG51bWJlcjtcbiAgICAgIHkyOiBudW1iZXI7XG4gICAgfTtcbiAgICBib2xkPzogYm9vbGVhbjtcbiAgfTtcblxuICB0eXBlIEZsb3dEYXRhTGFiZWwgPSBCYXNpY0RhdGFMYWJlbCAmIHtcbiAgICBlbGVtZW50VHlwZTogJ2RhdGFMYWJlbCc7XG4gICAgZGF0YUxhYmVsVHlwZTogJ2Zsb3cnO1xuICAgIC8vSGVscGVyIGRhdGEgZm9yIGZsb3dzXG4gICAgYnVja2V0SW5kZXg6IG51bWJlcjtcbiAgICBiYXJJZDogc3RyaW5nO1xuICB9O1xuXG4gIGV4cG9ydCB0eXBlIERhdGFMYWJlbCA9XG4gICAgfCAoQmFzaWNEYXRhTGFiZWwgJiB7IGRhdGFMYWJlbFR5cGU/OiB1bmRlZmluZWQgfSlcbiAgICB8IEZsb3dEYXRhTGFiZWw7XG5cbiAgY29uc3QgZW1wdHlDaGFydDogUmVuZGVyZWRDaGFydCA9IHtcbiAgICBjaGFydFdpZHRoOiAwLFxuICAgIGNoYXJ0SGVpZ2h0OiAwLFxuICAgIGNoYXJ0U2l6aW5nVmFsdWVzOiBlbXB0eUNoYXJ0U2NhbGVWYWx1ZXMsXG4gICAgeFRpY2tzOiBbXSxcbiAgICB5VGlja3M6IFtdLFxuICAgIGNvbG9yczogW10sXG4gICAgbGluZXM6IFtdLFxuICAgIGNpcmNsZXM6IFtdLFxuICAgIGFyZWFzOiBbXSxcbiAgICBiYXJzOiBbXSxcbiAgICBhcmNzOiBbXSxcbiAgICBob3Jpem9udGFsQmFyczogW10sXG4gICAgZGF0YUxhYmVsczogW10sXG4gICAgd2F0ZXJmYWxsTGluZXM6IFtdLFxuICAgIGdyYWRpZW50czogW10sXG4gICAgZmxvd0Nvbm5lY3Rpb25zOiBbXSxcbiAgICBob3Jpem9udGFsQ29udGFpbmVyU2NhbGU6ICduby1zY2FsZScsXG4gICAgdmVydGljYWxDb250YWluZXJTY2FsZTogJ25vLXNjYWxlJyxcbiAgICBjaGFydEVycm9yOiBudWxsLFxuICB9O1xuXG4gIC8vJ3knIGluIHRoaXMgZnVuY3Rpb24gcmVmZXJzIHRvIHRoZSBkYXRhIHksIHNpbmNlIHRoaXMgZnVuY3Rpb25cbiAgLy8gaXMgYWxzbyB1c2VkIGJ5IGhvcml6b250YWwtYmFycywgd2hlcmUgdGhlIGRhdGEgeSBpcyB0aGUgY2hhcnQgeFxuICBmdW5jdGlvbiBjYWxjRGF0YUF4aXNTY2FsZXNBbmRUaWNrcyhcbiAgICBkYXRhOiBQcm9jZXNzRGF0YSxcbiAgICBwaXBlVHJhbnNmb3JtSW5wdXQ6XG4gICAgICB8ICgodmFsdWU6IG51bWJlciwgaXNTZWNvbmRhcnk6IGJvb2xlYW4pID0+IHN0cmluZylcbiAgICAgIHwgbnVsbCxcbiAgICBjb25maWc6IENvbmZpZyxcbiAgICBjaGFydFNpemluZ1ZhbHVlczogRnVsbENoYXJ0U2NhbGVWYWx1ZXMsXG4gICk6IHtcbiAgICBzY2FsZTogKGlucHV0OiBudW1iZXIsIGlzU2Vjb25kYXJ5OiBib29sZWFuIHwgdW5kZWZpbmVkKSA9PiBudW1iZXI7XG4gICAgdGlja3M6IEdlbmVyaWNUaWNrW107XG4gIH0ge1xuICAgIGNvbnN0IHBpcGVUcmFuc2Zvcm0gPVxuICAgICAgcGlwZVRyYW5zZm9ybUlucHV0ICE9PSBudWxsID8gcGlwZVRyYW5zZm9ybUlucHV0IDogKCkgPT4gJyc7XG4gICAgY29uc3Qge1xuICAgICAgcHJpbWFyeURhdGFNaW4sXG4gICAgICBwcmltYXJ5RGF0YU1heCxcbiAgICAgIHNlY29uZGFyeURhdGFNaW4sXG4gICAgICBzZWNvbmRhcnlEYXRhTWF4LFxuICAgICAgc2NhbGVEb21haW5NdWx0aXBsZUZvck1heCxcbiAgICAgIHNjYWxlRG9tYWluTXVsdGlwbGVGb3JOZWcsXG4gICAgfSA9IGNhbGNEYXRhU2NhbGluZ1ZhbHVlcyhkYXRhLCBjb25maWcpO1xuICAgIGNvbnN0IHN0YXJ0T2Zmc2V0ID1cbiAgICAgIGNoYXJ0U2l6aW5nVmFsdWVzLmNoYXJ0RGF0YURpcmVjdGlvbiA9PT0gJ2hvcml6b250YWwnXG4gICAgICAgID8gY2hhcnRTaXppbmdWYWx1ZXMudG90YWxMZWZ0T2Zmc2V0XG4gICAgICAgIDogY2hhcnRTaXppbmdWYWx1ZXMudG90YWxUb3BPZmZzZXQ7XG4gICAgbGV0IG1pblNwYWNpbmcgPVxuICAgICAgKGNoYXJ0U2l6aW5nVmFsdWVzLmNoYXJ0RGF0YURpcmVjdGlvbiA9PT0gJ2hvcml6b250YWwnXG4gICAgICAgID8gY2hhcnRTaXppbmdWYWx1ZXMuaG9yaXpvbnRhbEF4aXNMYWJlbFRleHRTaXplXG4gICAgICAgIDogY2hhcnRTaXppbmdWYWx1ZXMudmVydGljYWxBeGlzTGFiZWxUZXh0U2l6ZSkgKyBTTUFMTF9QQURESU5HO1xuICAgIG1pblNwYWNpbmcgPSBtaW5TcGFjaW5nICogKGNoYXJ0U2l6aW5nVmFsdWVzLmZvbnRTaXplIC8gREVGQVVMVF9GT05UX1NJWkUpO1xuICAgIGNvbnN0IHNwYWNpbmdUaWNrQ291bnQgPSBNYXRoLm1heChcbiAgICAgIDIsXG4gICAgICBNYXRoLmZsb29yKGNoYXJ0U2l6aW5nVmFsdWVzLnNpemVGb3JEYXRhIC8gbWluU3BhY2luZyksXG4gICAgKTtcbiAgICBjb25zdCBhY3R1YWxUYXJnZXRUaWNrQ291bnQgPSBNYXRoLm1pbihcbiAgICAgIHNwYWNpbmdUaWNrQ291bnQsXG4gICAgICBjaGFydFNpemluZ1ZhbHVlcy50YXJnZXRUaWNrQ291bnQsXG4gICAgKTtcblxuICAgIGNvbnN0IGhhc1ByaW1hcnkgPSBwcmltYXJ5RGF0YU1pbiAhPT0gMCB8fCBwcmltYXJ5RGF0YU1heCAhPT0gMDtcbiAgICBjb25zdCBoYXNTZWNvbmRhcnkgPSBzZWNvbmRhcnlEYXRhTWluICE9PSAwIHx8IHNlY29uZGFyeURhdGFNYXggIT09IDA7XG4gICAgY29uc3Qgc2NhbGVSYW5nZSA9XG4gICAgICBjaGFydFNpemluZ1ZhbHVlcy5jaGFydERhdGFEaXJlY3Rpb24gPT09ICdob3Jpem9udGFsJyB8fFxuICAgICAgY29uZmlnLnR5cGUgPT09ICdmbG93J1xuICAgICAgICA/IFswLCBjaGFydFNpemluZ1ZhbHVlcy5zaXplRm9yRGF0YV1cbiAgICAgICAgOiBbY2hhcnRTaXppbmdWYWx1ZXMuc2l6ZUZvckRhdGEsIDBdO1xuICAgIC8vVGhlc2UgJ2VmZmVjdGl2ZScgdmFsdWVzIGVuc3VyZSB3ZSBoYXZlIHJvb20gZm9yIHBvdGVudGlhbCBzdGFja2luZyBvZiBzZWNvbmRhcnkgYW5kIG5vbi1zZWNvbmRhcnkgdmFsdWVzXG4gICAgbGV0IGVmZmVjdGl2ZVByaW1hcnlNaW4gPSBwcmltYXJ5RGF0YU1pbiAqIHNjYWxlRG9tYWluTXVsdGlwbGVGb3JOZWc7XG4gICAgbGV0IGVmZmVjdGl2ZVByaW1hcnlNYXggPSBwcmltYXJ5RGF0YU1heCAqIHNjYWxlRG9tYWluTXVsdGlwbGVGb3JNYXg7XG5cbiAgICAvL1NpbXBsZXIgcGF0aCBmb3IgZGF0YSB3L28gc2Vjb25kYXJpZXNcbiAgICBpZiAoIWhhc1NlY29uZGFyeSkge1xuICAgICAgY29uc3QgcHJpbWFyeVlEb21haW4gPSBbZWZmZWN0aXZlUHJpbWFyeU1pbiwgZWZmZWN0aXZlUHJpbWFyeU1heF07XG5cbiAgICAgIGNvbnN0IHlTY2FsZSA9IHNjYWxlTGluZWFyKHByaW1hcnlZRG9tYWluLCBzY2FsZVJhbmdlKTtcbiAgICAgIGNvbnN0IHRpY2tzOiBHZW5lcmljVGlja1tdID0geVNjYWxlXG4gICAgICAgIC50aWNrcyhhY3R1YWxUYXJnZXRUaWNrQ291bnQpXG4gICAgICAgIC5tYXAodGljayA9PiAoe1xuICAgICAgICAgIHZhbHVlOiB5U2NhbGUodGljaykgKyBzdGFydE9mZnNldCxcbiAgICAgICAgICBsYWJlbDogcGlwZVRyYW5zZm9ybSh0aWNrLCBmYWxzZSksXG4gICAgICAgIH0pKTtcbiAgICAgIGNvbnN0IHNjYWxlID0gKGlucHV0OiBudW1iZXIpOiBudW1iZXIgPT4ge1xuICAgICAgICByZXR1cm4geVNjYWxlKGlucHV0KSArIHN0YXJ0T2Zmc2V0O1xuICAgICAgfTtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHNjYWxlLFxuICAgICAgICB0aWNrcyxcbiAgICAgIH07XG4gICAgfVxuICAgIC8vU2ltcGxlciBwYXRoIGZvciBkYXRhIHcvbyBwcmltYXJpZXNcbiAgICBpZiAoIWhhc1ByaW1hcnkpIHtcbiAgICAgIGNvbnN0IHNlY29uZGFyeVlEb21haW4gPSBbc2Vjb25kYXJ5RGF0YU1pbiwgc2Vjb25kYXJ5RGF0YU1heF07XG5cbiAgICAgIGNvbnN0IHlTY2FsZSA9IHNjYWxlTGluZWFyKHNlY29uZGFyeVlEb21haW4sIHNjYWxlUmFuZ2UpO1xuICAgICAgY29uc3QgdGlja3M6IEdlbmVyaWNUaWNrW10gPSB5U2NhbGVcbiAgICAgICAgLnRpY2tzKGFjdHVhbFRhcmdldFRpY2tDb3VudClcbiAgICAgICAgLm1hcCh0aWNrID0+ICh7XG4gICAgICAgICAgdmFsdWU6IHlTY2FsZSh0aWNrKSArIHN0YXJ0T2Zmc2V0LFxuICAgICAgICAgIGxhYmVsOiBwaXBlVHJhbnNmb3JtKHRpY2ssIHRydWUpLFxuICAgICAgICB9KSk7XG4gICAgICBjb25zdCBzY2FsZSA9IChpbnB1dDogbnVtYmVyKTogbnVtYmVyID0+IHtcbiAgICAgICAgcmV0dXJuIHlTY2FsZShpbnB1dCkgKyBzdGFydE9mZnNldDtcbiAgICAgIH07XG4gICAgICByZXR1cm4ge1xuICAgICAgICBzY2FsZSxcbiAgICAgICAgdGlja3MsXG4gICAgICB9O1xuICAgIH1cbiAgICBsZXQgZWZmZWN0aXZlU2Vjb25kYXJ5TWF4ID0gMDtcbiAgICBsZXQgZWZmZWN0aXZlU2Vjb25kYXJ5TWluID0gMDtcblxuICAgIC8vVGhpcyBibG9jayBzZXRzIHRoZSBlZmZlY3RpdmUgbWF4IGZvciBwcmltYXJ5IGFuZCBzZWNvbmRhcnlcbiAgICAvL1RoaXMgdG8gZW5zdXJlIHRoYXQgdGhlIGVmZmVjdGl2ZSBtYXhlcyBmb3IgYm90aCBkYXRhIHNldHMgYXJlIHByb3Blcmx5IHNldCBzbyB0aGF0XG4gICAgLy8gMCB3aWxsIGZhbGwgYXQgdGhlIHNhbWUgcGxhY2Ugb24gYm90aCBhbmQgZWFjaCB3aWxsIGhhdmUgJ3Jvb20nIGZvciBwb3RlbnRpYWwgc3RhY2tpbmdcbiAgICBpZiAoXG4gICAgICAocHJpbWFyeURhdGFNYXggPD0gMCAmJiBzZWNvbmRhcnlEYXRhTWluID49IDApIHx8XG4gICAgICAocHJpbWFyeURhdGFNaW4gPj0gMCAmJiBzZWNvbmRhcnlEYXRhTWF4IDw9IDApXG4gICAgKSB7XG4gICAgICAvL0luIHRoaXMgc2NlbmFyaW8sIG9uZSBzZXQgb2YgZGF0YSBpcyBjb21wZXRlbHkgcG9zaXRpdmUsIHdoaWxlIHRoZSBvdGhlciBpcyBjb21wbGV0ZWx5IG5lZ2F0aXZlXG4gICAgICAvL1RoZSB0d28gZGF0YSBzZXRzIGNhbiBzY2FsZSBjb21wbGV0ZWx5IGluZGVwZW5kZW50bHlcbiAgICAgIC8vV2UgJ21pcnJvcicgdGhlIHZhbHVlcyBvZiB0aGUgdHdvIGRhdGEgc2V0cywgd2hpY2gnbGwgcHV0IHRoZSAwIGF4aXMgaW4gdGhlIGNlbnRlciBvZiB0aGUgZGF0YVxuICAgICAgaWYgKHByaW1hcnlEYXRhTWF4IDw9IDApIHtcbiAgICAgICAgZWZmZWN0aXZlUHJpbWFyeU1heCA9IE1hdGguYWJzKGVmZmVjdGl2ZVByaW1hcnlNaW4pO1xuICAgICAgfVxuICAgICAgaWYgKHByaW1hcnlEYXRhTWluID49IDApIHtcbiAgICAgICAgZWZmZWN0aXZlUHJpbWFyeU1pbiA9IC1NYXRoLmFicyhlZmZlY3RpdmVQcmltYXJ5TWF4KTtcbiAgICAgIH1cbiAgICAgIGlmIChzZWNvbmRhcnlEYXRhTWF4IDw9IDApIHtcbiAgICAgICAgZWZmZWN0aXZlU2Vjb25kYXJ5TWluID0gc2Vjb25kYXJ5RGF0YU1pbjtcbiAgICAgICAgZWZmZWN0aXZlU2Vjb25kYXJ5TWF4ID0gTWF0aC5hYnMoc2Vjb25kYXJ5RGF0YU1pbik7XG4gICAgICB9XG4gICAgICBpZiAoc2Vjb25kYXJ5RGF0YU1pbiA+PSAwKSB7XG4gICAgICAgIGVmZmVjdGl2ZVNlY29uZGFyeU1heCA9IHNlY29uZGFyeURhdGFNYXg7XG4gICAgICAgIGVmZmVjdGl2ZVNlY29uZGFyeU1pbiA9IC1zZWNvbmRhcnlEYXRhTWF4O1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAocHJpbWFyeURhdGFNYXggPiAwKSB7XG4gICAgICBpZiAocHJpbWFyeURhdGFNaW4gPCAwKSB7XG4gICAgICAgIC8vUHJpbWFyeSBkYXRhIGhhcyBwb3NpdGl2ZSBhbmQgbmVnYXRpdmVcbiAgICAgICAgaWYgKHNlY29uZGFyeURhdGFNYXggPiAwKSB7XG4gICAgICAgICAgLy9TZWNvbmRhcnkgZGF0YSBoYXMgcG9zaXRpdmVcbiAgICAgICAgICBlZmZlY3RpdmVTZWNvbmRhcnlNYXggPSBzZWNvbmRhcnlEYXRhTWF4ICogc2NhbGVEb21haW5NdWx0aXBsZUZvck1heDtcbiAgICAgICAgICBpZiAoc2Vjb25kYXJ5RGF0YU1pbiA8IDApIHtcbiAgICAgICAgICAgIC8vU2Vjb25kYXJ5IGRhdGEgaGFzIG5lZ2F0aXZlXG4gICAgICAgICAgICBlZmZlY3RpdmVTZWNvbmRhcnlNaW4gPVxuICAgICAgICAgICAgICBzZWNvbmRhcnlEYXRhTWluICogc2NhbGVEb21haW5NdWx0aXBsZUZvck5lZztcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy9TZWNvbmRhcnkgZGF0YSBpcyBvbmx5IHBvc2l0aXZlXG4gICAgICAgICAgICBlZmZlY3RpdmVTZWNvbmRhcnlNaW4gPVxuICAgICAgICAgICAgICAoc2Vjb25kYXJ5RGF0YU1heCAvIHByaW1hcnlEYXRhTWF4KSAqXG4gICAgICAgICAgICAgIHByaW1hcnlEYXRhTWluICpcbiAgICAgICAgICAgICAgc2NhbGVEb21haW5NdWx0aXBsZUZvck5lZztcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy9TZWNvbmRhcnkgZGF0YSBoYXMgb25seSBuZWdhdGl2ZVxuICAgICAgICAgIGVmZmVjdGl2ZVNlY29uZGFyeU1pbiA9IHNlY29uZGFyeURhdGFNaW4gKiBzY2FsZURvbWFpbk11bHRpcGxlRm9yTmVnO1xuICAgICAgICAgIGVmZmVjdGl2ZVNlY29uZGFyeU1heCA9XG4gICAgICAgICAgICAoc2Vjb25kYXJ5RGF0YU1pbiAvIHByaW1hcnlEYXRhTWluKSAqXG4gICAgICAgICAgICBwcmltYXJ5RGF0YU1heCAqXG4gICAgICAgICAgICBzY2FsZURvbWFpbk11bHRpcGxlRm9yTWF4O1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvL1ByaW1hcnkgZGF0YSBpcyBvbmx5IHBvc2l0aXZlXG4gICAgICAgIC8vRHVlIHRvIGVhcmxpZXIgY2hlY2ssIHdlIGtub3cgdGhhdCBzZWNvbmRhcnkgZGF0YSBpcyBlaXRoZXIgYWxzbyBhbGwtcG9zaXRpdmUsIG9yIHBvc2l0aXZlIGFuZCBuZWdhdGl2ZVxuICAgICAgICBlZmZlY3RpdmVTZWNvbmRhcnlNYXggPSBzZWNvbmRhcnlEYXRhTWF4ICogc2NhbGVEb21haW5NdWx0aXBsZUZvck1heDtcbiAgICAgICAgZWZmZWN0aXZlU2Vjb25kYXJ5TWluID0gc2Vjb25kYXJ5RGF0YU1pbiAqIHNjYWxlRG9tYWluTXVsdGlwbGVGb3JOZWc7XG4gICAgICAgIGVmZmVjdGl2ZVByaW1hcnlNaW4gPVxuICAgICAgICAgIChwcmltYXJ5RGF0YU1heCAvIHNlY29uZGFyeURhdGFNYXgpICpcbiAgICAgICAgICBzZWNvbmRhcnlEYXRhTWluICpcbiAgICAgICAgICBzY2FsZURvbWFpbk11bHRpcGxlRm9yTmVnO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAvL1ByaW1hcnkgZGF0YSBpcyBvbmx5IG5lZ2F0aXZlXG4gICAgICAvL0R1ZSB0byBlYXJsaWVyIGNoZWNrLCB3ZSBrbm93IHRoYXQgc2Vjb25kYXJ5IGRhdGEgaXMgZWl0aGVyIGFsc28gYWxsLW5lZ2F0aXZlLCBvciBwb3NpdGl2ZSBhbmQgbmVnYXRpdmVcbiAgICAgIGVmZmVjdGl2ZVNlY29uZGFyeU1heCA9IHNlY29uZGFyeURhdGFNYXggKiBzY2FsZURvbWFpbk11bHRpcGxlRm9yTWF4O1xuICAgICAgZWZmZWN0aXZlU2Vjb25kYXJ5TWluID0gc2Vjb25kYXJ5RGF0YU1pbiAqIHNjYWxlRG9tYWluTXVsdGlwbGVGb3JOZWc7XG4gICAgICBlZmZlY3RpdmVQcmltYXJ5TWF4ID1cbiAgICAgICAgKHByaW1hcnlEYXRhTWluIC8gc2Vjb25kYXJ5RGF0YU1pbikgKlxuICAgICAgICBzZWNvbmRhcnlEYXRhTWF4ICpcbiAgICAgICAgc2NhbGVEb21haW5NdWx0aXBsZUZvck1heDtcbiAgICB9XG4gICAgY29uc3QgcHJpbWFyeVlEb21haW4gPSBbZWZmZWN0aXZlUHJpbWFyeU1pbiwgZWZmZWN0aXZlUHJpbWFyeU1heF07XG5cbiAgICBjb25zdCB5U2NhbGUgPSBzY2FsZUxpbmVhcihwcmltYXJ5WURvbWFpbiwgc2NhbGVSYW5nZSk7XG5cbiAgICAvL0ZpZ3VyaW5nIG91dCB0aGUgYmVzdCB0aWNrIGNvdW50IHRvIGZpdCB0aGUgdHdvIGRhdGEgc3JvdWNlc1xuICAgIGNvbnN0IHlTY2FsZVByaW1hcnlQcm90byA9IHNjYWxlTGluZWFyKHByaW1hcnlZRG9tYWluLCBzY2FsZVJhbmdlKTtcbiAgICBjb25zdCB5U2NhbGVTZWNvbmRhcnlQcm90byA9IHNjYWxlTGluZWFyKFxuICAgICAgW2VmZmVjdGl2ZVNlY29uZGFyeU1pbiwgZWZmZWN0aXZlU2Vjb25kYXJ5TWF4XSxcbiAgICAgIHNjYWxlUmFuZ2UsXG4gICAgKTtcbiAgICBjb25zdCB0aWNrQ291bnQgPSBNYXRoLm1heChcbiAgICAgIGFjdHVhbFRhcmdldFRpY2tDb3VudCxcbiAgICAgIHlTY2FsZVByaW1hcnlQcm90by50aWNrcyhhY3R1YWxUYXJnZXRUaWNrQ291bnQpLmxlbmd0aCxcbiAgICAgIHlTY2FsZVNlY29uZGFyeVByb3RvLnRpY2tzKGFjdHVhbFRhcmdldFRpY2tDb3VudCkubGVuZ3RoLFxuICAgICk7XG4gICAgY29uc3QgcHJpbWFyeVRpY2tzID0geVNjYWxlLnRpY2tzKHRpY2tDb3VudCkubWFwKHRpY2sgPT4gKHtcbiAgICAgIHZhbHVlOiB5U2NhbGUodGljaykgKyBzdGFydE9mZnNldCxcbiAgICAgIGxhYmVsOiBwaXBlVHJhbnNmb3JtKHRpY2ssIGZhbHNlKSxcbiAgICAgIHJhd1k6IHRpY2ssXG4gICAgfSkpO1xuXG4gICAgLy9GaW5kaW5nIGEgZG9tYWluIGZvciB0aGUgc2Vjb25kYXJ5IGRhdGEgc3VjaCB0aGF0IGl0IHdpbGwgcmVzdWx0IGluIHJvdW5kIHRpY2sgdmFsdWVzIHdoZW4gbWF0Y2hlZCB3aXRoIHRoZSBwcmltYXJ5IHRpY2tzXG4gICAgY29uc3Qgc2Vjb25kYXJ5VGlja3NQcm90byA9IHlTY2FsZVNlY29uZGFyeVByb3RvXG4gICAgICAudGlja3ModGlja0NvdW50KVxuICAgICAgLm1hcCh0aWNrID0+ICh7XG4gICAgICAgIHk6IHlTY2FsZVNlY29uZGFyeVByb3RvKHRpY2spLFxuICAgICAgICByYXdZOiB0aWNrLFxuICAgICAgICBsYWJlbDogcGlwZVRyYW5zZm9ybSh0aWNrLCB0cnVlKSxcbiAgICAgIH0pKTtcbiAgICBjb25zdCBwcmltYXJ5TWluVGljayA9IE1hdGgubWluKC4uLnByaW1hcnlUaWNrcy5tYXAodGljayA9PiB0aWNrLnJhd1kpKTtcbiAgICBjb25zdCBwcmltYXJ5TWF4VGljayA9IE1hdGgubWF4KC4uLnByaW1hcnlUaWNrcy5tYXAodGljayA9PiB0aWNrLnJhd1kpKTtcbiAgICBjb25zdCBwcmltYXJ5RG9tYWluTWF4VGlja1JhdGlvID1cbiAgICAgIHByaW1hcnlNYXhUaWNrICE9PSAwID8gZWZmZWN0aXZlUHJpbWFyeU1heCAvIHByaW1hcnlNYXhUaWNrIDogMDtcbiAgICBjb25zdCBwcmltYXJ5RG9tYWluTWluVGlja1JhdGlvID1cbiAgICAgIHByaW1hcnlNaW5UaWNrICE9PSAwID8gZWZmZWN0aXZlUHJpbWFyeU1pbiAvIHByaW1hcnlNaW5UaWNrIDogMDtcblxuICAgIGNvbnN0IHByaW1hcnlHYXAgPSBwcmltYXJ5VGlja3NbMV0ucmF3WSAtIHByaW1hcnlUaWNrc1swXS5yYXdZO1xuICAgIGNvbnN0IHRpY2tzQmVsb3daZXJvID0gcHJpbWFyeU1pblRpY2sgLyBwcmltYXJ5R2FwO1xuICAgIGNvbnN0IHRpY2tzQWJvdmVaZXJvID0gcHJpbWFyeU1heFRpY2sgLyBwcmltYXJ5R2FwO1xuXG4gICAgY29uc3Qgc2Vjb25kYXJ5R2FwID1cbiAgICAgIHNlY29uZGFyeVRpY2tzUHJvdG9bMV0ucmF3WSAtIHNlY29uZGFyeVRpY2tzUHJvdG9bMF0ucmF3WTtcbiAgICBsZXQgY2FsY1JhbmdlTXVsdCA9IDE7XG4gICAgY29uc3Qgc2Vjb25kYXJ5RG9tYWluTWluTXVsdCA9XG4gICAgICB0aWNrc0JlbG93WmVybyAqIHNlY29uZGFyeUdhcCAqIHByaW1hcnlEb21haW5NaW5UaWNrUmF0aW87XG4gICAgY29uc3Qgc2Vjb25kYXJ5RG9tYWluTWF4TXVsdCA9XG4gICAgICB0aWNrc0Fib3ZlWmVybyAqIHNlY29uZGFyeUdhcCAqIHByaW1hcnlEb21haW5NYXhUaWNrUmF0aW87XG4gICAgLy9GaXJzdCwgd2UgZW5zdXJlIHRoZSBjYWxjUmFuZ2VNdWx0IGlzIGJpZyBlbm91Z2hcbiAgICBsZXQgc2l6ZVVwQ29tcGxldGUgPSBmYWxzZTtcbiAgICB3aGlsZSAoIXNpemVVcENvbXBsZXRlKSB7XG4gICAgICBjb25zdCBjYWxjUmFuZ2VUb29TbWFsbEZvck1pbiA9XG4gICAgICAgIHNlY29uZGFyeURvbWFpbk1pbk11bHQgKiBjYWxjUmFuZ2VNdWx0ID4gZWZmZWN0aXZlU2Vjb25kYXJ5TWluICYmXG4gICAgICAgIHNlY29uZGFyeURvbWFpbk1pbk11bHQgIT09IDA7XG4gICAgICBjb25zdCBjYWxjUmFuZ2VUb29TbWFsbEZvck1heCA9XG4gICAgICAgIHNlY29uZGFyeURvbWFpbk1heE11bHQgKiBjYWxjUmFuZ2VNdWx0IDwgZWZmZWN0aXZlU2Vjb25kYXJ5TWF4ICYmXG4gICAgICAgIHNlY29uZGFyeURvbWFpbk1heE11bHQgIT09IDA7XG4gICAgICBpZiAoY2FsY1JhbmdlVG9vU21hbGxGb3JNaW4gfHwgY2FsY1JhbmdlVG9vU21hbGxGb3JNYXgpIHtcbiAgICAgICAgY2FsY1JhbmdlTXVsdCA9IGNhbGNSYW5nZU11bHQgKiAyO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgc2l6ZVVwQ29tcGxldGUgPSB0cnVlO1xuICAgICAgfVxuICAgIH1cbiAgICAvL1RoZW4sIHdlIGNoZWNrIGlmIHdlIGNhbiBzY2FsZSBkb3duIChmb3IgdGhpcyBvbmUsIGJvdGggY29uZGl0aW9ucyBoYXZlIHRvIGJlIHRydWUsIHNvIGl0IHdvbid0IHVuZG8gYSBwcmV2aW91cyBzY2FsZSB1cClcbiAgICBsZXQgc2l6ZURvd25Db21wbGV0ZSA9IGZhbHNlO1xuICAgIHdoaWxlICghc2l6ZURvd25Db21wbGV0ZSkge1xuICAgICAgY29uc3QgY2FsY1JhbmdlVG9vQmlnRm9yTWluID1cbiAgICAgICAgc2Vjb25kYXJ5RG9tYWluTWluTXVsdCAqIGNhbGNSYW5nZU11bHQgPCBlZmZlY3RpdmVTZWNvbmRhcnlNaW4gKiAyICYmXG4gICAgICAgIHNlY29uZGFyeURvbWFpbk1pbk11bHQgIT09IDA7XG4gICAgICBjb25zdCBjYWxjUmFuZ2VUb29CaWdGb3JNYXggPVxuICAgICAgICBzZWNvbmRhcnlEb21haW5NYXhNdWx0ICogY2FsY1JhbmdlTXVsdCA+IGVmZmVjdGl2ZVNlY29uZGFyeU1heCAqIDIgJiZcbiAgICAgICAgc2Vjb25kYXJ5RG9tYWluTWF4TXVsdCAhPT0gMDtcbiAgICAgIGlmIChjYWxjUmFuZ2VUb29CaWdGb3JNaW4gJiYgY2FsY1JhbmdlVG9vQmlnRm9yTWF4KSB7XG4gICAgICAgIGNhbGNSYW5nZU11bHQgPSBjYWxjUmFuZ2VNdWx0IC8gMjtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHNpemVEb3duQ29tcGxldGUgPSB0cnVlO1xuICAgICAgfVxuICAgIH1cbiAgICBsZXQgc2Vjb25kYXJ5RG9tYWluTWluID0gc2Vjb25kYXJ5RG9tYWluTWluTXVsdCAqIGNhbGNSYW5nZU11bHQ7XG4gICAgbGV0IHNlY29uZGFyeURvbWFpbk1heCA9IHNlY29uZGFyeURvbWFpbk1heE11bHQgKiBjYWxjUmFuZ2VNdWx0O1xuICAgIC8vSWYgdGhlIGRhdGEgaXMgbG9wc2lkZWQgZW5vdWdoLCBpdCdzIHBvc3NpYmxlIHRoYXQgb25lIG9mIHBvc2l0aXZlL25lZ2F0aXZlIGhhdmUgdmFsdWVzLCBidXQgbm8gdGlja3NcbiAgICBpZiAoc2Vjb25kYXJ5RG9tYWluTWluID09PSAwICYmIGVmZmVjdGl2ZVByaW1hcnlNaW4gPCAwKSB7XG4gICAgICBjb25zdCBwb3NTZWNSYXRpbyA9IHNlY29uZGFyeURvbWFpbk1heCAvIGVmZmVjdGl2ZVByaW1hcnlNYXg7XG4gICAgICBzZWNvbmRhcnlEb21haW5NaW4gPSBwb3NTZWNSYXRpbyAqIGVmZmVjdGl2ZVByaW1hcnlNaW47XG4gICAgfVxuICAgIGlmIChzZWNvbmRhcnlEb21haW5NYXggPT09IDAgJiYgZWZmZWN0aXZlUHJpbWFyeU1heCA+IDApIHtcbiAgICAgIGNvbnN0IHBvc1NlY1JhdGlvID0gc2Vjb25kYXJ5RG9tYWluTWluIC8gZWZmZWN0aXZlUHJpbWFyeU1pbjtcbiAgICAgIHNlY29uZGFyeURvbWFpbk1heCA9IHBvc1NlY1JhdGlvICogZWZmZWN0aXZlUHJpbWFyeU1heDtcbiAgICB9XG4gICAgY29uc3QgeVNjYWxlU2Vjb25kYXJ5ID0gc2NhbGVMaW5lYXIoXG4gICAgICBbc2Vjb25kYXJ5RG9tYWluTWluLCBzZWNvbmRhcnlEb21haW5NYXhdLFxuICAgICAgc2NhbGVSYW5nZSxcbiAgICApO1xuXG4gICAgY29uc3QgdGlja3M6IEdlbmVyaWNUaWNrW10gPSBwcmltYXJ5VGlja3MubWFwKHRpY2sgPT4gKHtcbiAgICAgIC4uLnRpY2ssXG4gICAgICBzZWNvbmRhcnlMYWJlbDogcGlwZVRyYW5zZm9ybShcbiAgICAgICAgeVNjYWxlU2Vjb25kYXJ5LmludmVydCh5U2NhbGUodGljay5yYXdZKSksXG4gICAgICAgIHRydWUsXG4gICAgICApLFxuICAgIH0pKTtcblxuICAgIGNvbnN0IHNjYWxlID0gKGlucHV0OiBudW1iZXIsIGlzU2Vjb25kYXJ5OiBib29sZWFuIHwgdW5kZWZpbmVkKTogbnVtYmVyID0+IHtcbiAgICAgIGlmIChpc1NlY29uZGFyeSkge1xuICAgICAgICByZXR1cm4geVNjYWxlU2Vjb25kYXJ5KGlucHV0KSArIHN0YXJ0T2Zmc2V0O1xuICAgICAgfVxuICAgICAgcmV0dXJuIHlTY2FsZShpbnB1dCkgKyBzdGFydE9mZnNldDtcbiAgICB9O1xuICAgIHJldHVybiB7XG4gICAgICBzY2FsZSxcbiAgICAgIHRpY2tzLFxuICAgIH07XG4gIH1cblxuICBmdW5jdGlvbiBjYWxjRGF0YVNjYWxpbmdWYWx1ZXMoZGF0YTogUHJvY2Vzc0RhdGEsIGNvbmZpZzogQ29uZmlnKSB7XG4gICAgY29uc3QgaXNTdGFja2VkID0gaXNTdGFja2VkRGF0YShjb25maWcpO1xuICAgIGNvbnN0IHByaW1hcnlEb21haW5WYWx1ZXMgPSBjYWxjWVNjYWxlRG9tYWluVmFsdWVzKGRhdGEsIGlzU3RhY2tlZCwgZmFsc2UpO1xuICAgIGNvbnN0IHNlY29uZGFyeURvbWFpblZhbHVlcyA9IGNhbGNZU2NhbGVEb21haW5WYWx1ZXMoZGF0YSwgaXNTdGFja2VkLCB0cnVlKTtcbiAgICBjb25zdCBwcmltYXJ5RGF0YU1heCA9IE1hdGgubWF4KC4uLnByaW1hcnlEb21haW5WYWx1ZXMubWFwKHZhbCA9PiB2YWwubWF4KSk7XG4gICAgY29uc3Qgc2Vjb25kYXJ5RGF0YU1heCA9IE1hdGgubWF4KFxuICAgICAgLi4uc2Vjb25kYXJ5RG9tYWluVmFsdWVzLm1hcCh2YWwgPT4gdmFsLm1heCksXG4gICAgKTtcbiAgICBjb25zdCBwcmltYXJ5RGF0YU1pbiA9IE1hdGgubWluKC4uLnByaW1hcnlEb21haW5WYWx1ZXMubWFwKHZhbCA9PiB2YWwubWluKSk7XG4gICAgY29uc3Qgc2Vjb25kYXJ5RGF0YU1pbiA9IE1hdGgubWluKFxuICAgICAgLi4uc2Vjb25kYXJ5RG9tYWluVmFsdWVzLm1hcCh2YWwgPT4gdmFsLm1pbiksXG4gICAgKTtcbiAgICBsZXQgc2NhbGVEb21haW5NdWx0aXBsZUZvck1heCA9IDE7XG4gICAgbGV0IHNjYWxlRG9tYWluTXVsdGlwbGVGb3JOZWcgPSAxO1xuXG4gICAgLy9DYWxjdWxhdGluZyBob3cgbXVjaCB3ZSBuZWVkIHRvIG11bHRpcGxlIHRoZSBkb21haW4gYnkgdG8gJ2ZpdCcgYm90aCBheGVzJyBkYXRhXG4gICAgaWYgKGlzU3RhY2tlZCkge1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBwcmltYXJ5RG9tYWluVmFsdWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIC8vQ2hlY2sgcG9zaXRpdmUgbWF4XG4gICAgICAgIGNvbnN0IHByaW1hcnlWYWwgPSBwcmltYXJ5RG9tYWluVmFsdWVzW2ldLm1heDtcbiAgICAgICAgY29uc3Qgc2Vjb25kYXJ5VmFsID0gc2Vjb25kYXJ5RG9tYWluVmFsdWVzW2ldLm1heDtcbiAgICAgICAgY29uc3QgcHJpbWFyeVJhdGlvID1cbiAgICAgICAgICBwcmltYXJ5RGF0YU1heCAhPT0gMCA/IHByaW1hcnlWYWwgLyBwcmltYXJ5RGF0YU1heCA6IDA7XG4gICAgICAgIGNvbnN0IHNlY29uZGFyeVJhdGlvID1cbiAgICAgICAgICBzZWNvbmRhcnlEYXRhTWF4ICE9PSAwID8gc2Vjb25kYXJ5VmFsIC8gc2Vjb25kYXJ5RGF0YU1heCA6IDA7XG4gICAgICAgIGNvbnN0IG11bHRWYWwgPSBwcmltYXJ5UmF0aW8gKyBzZWNvbmRhcnlSYXRpbztcbiAgICAgICAgaWYgKG11bHRWYWwgPiBzY2FsZURvbWFpbk11bHRpcGxlRm9yTWF4KSB7XG4gICAgICAgICAgc2NhbGVEb21haW5NdWx0aXBsZUZvck1heCA9IG11bHRWYWw7XG4gICAgICAgIH1cblxuICAgICAgICAvL0NoZWNrIG5lZ2F0aXZlIG1pblxuICAgICAgICBjb25zdCBwcmltYXJ5TmVnVmFsID1cbiAgICAgICAgICBwcmltYXJ5RG9tYWluVmFsdWVzW2ldLm1pbiA8IDAgPyBwcmltYXJ5RG9tYWluVmFsdWVzW2ldLm1pbiA6IDA7XG4gICAgICAgIGNvbnN0IHNlY29uZGFyeU5lZ1ZhbCA9XG4gICAgICAgICAgc2Vjb25kYXJ5RG9tYWluVmFsdWVzW2ldLm1pbiA8IDAgPyBzZWNvbmRhcnlEb21haW5WYWx1ZXNbaV0ubWluIDogMDtcbiAgICAgICAgY29uc3QgcHJpbWFyeU5lZ1JhdGlvID1cbiAgICAgICAgICBwcmltYXJ5RGF0YU1pbiAhPT0gMCA/IHByaW1hcnlOZWdWYWwgLyBwcmltYXJ5RGF0YU1pbiA6IDA7XG4gICAgICAgIGNvbnN0IHNlY29uZGFyeU5lZ1JhdGlvID1cbiAgICAgICAgICBzZWNvbmRhcnlEYXRhTWluICE9PSAwID8gc2Vjb25kYXJ5TmVnVmFsIC8gc2Vjb25kYXJ5RGF0YU1pbiA6IDA7XG4gICAgICAgIGNvbnN0IG5lZ011bHRWYWwgPSBwcmltYXJ5TmVnUmF0aW8gKyBzZWNvbmRhcnlOZWdSYXRpbztcbiAgICAgICAgaWYgKG5lZ011bHRWYWwgPiBzY2FsZURvbWFpbk11bHRpcGxlRm9yTmVnKSB7XG4gICAgICAgICAgc2NhbGVEb21haW5NdWx0aXBsZUZvck5lZyA9IG5lZ011bHRWYWw7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgcHJpbWFyeURhdGFNaW4sXG4gICAgICBwcmltYXJ5RGF0YU1heCxcbiAgICAgIHNlY29uZGFyeURhdGFNaW4sXG4gICAgICBzZWNvbmRhcnlEYXRhTWF4LFxuICAgICAgc2NhbGVEb21haW5NdWx0aXBsZUZvck1heCxcbiAgICAgIHNjYWxlRG9tYWluTXVsdGlwbGVGb3JOZWcsXG4gICAgfTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGNhbGNZU2NhbGVEb21haW5WYWx1ZXMoXG4gICAgZGF0YTogUHJvY2Vzc0RhdGEsXG4gICAgaXNTdGFja2VkOiBib29sZWFuLFxuICAgIGZvclNlY29uZGFyeTogYm9vbGVhbixcbiAgKTogeyBtYXg6IG51bWJlcjsgbWluOiBudW1iZXIgfVtdIHtcbiAgICBpZiAoZGF0YS50eXBlID09PSAnZmxvdy1wcm9jZXNzZWQnKSB7XG4gICAgICBpZiAoZm9yU2Vjb25kYXJ5KSB7XG4gICAgICAgIC8vRmxvdyBjaGFydHMgZG9uJ3Qgc3VwcG9ydCBzZWNvbmRhcnkgZGF0YVxuICAgICAgICByZXR1cm4gW3sgbWluOiAwLCBtYXg6IDAgfV07XG4gICAgICB9XG4gICAgICByZXR1cm4gW1xuICAgICAgICB7XG4gICAgICAgICAgbWluOiAwLFxuICAgICAgICAgIG1heDogTWF0aC5tYXgoLi4uZGF0YS54Lm1hcCh4ID0+IHgudG90YWxDb3VudCkpLFxuICAgICAgICB9LFxuICAgICAgXTtcbiAgICB9XG4gICAgY29uc3QgcG9zc2libHlTdGFja2VkWXMgPSBkYXRhLnlzLm1hcCgoeSwgeUluZGV4KSA9PiB7XG4gICAgICAvL0hhbmRsZSBzdGFja2luZ1xuICAgICAgcmV0dXJuIGlzU3RhY2tlZFxuICAgICAgICA/IHkudmFsdWVzLm1hcCgodmFsLCB4SW5kZXgpID0+IHtcbiAgICAgICAgICAgIGxldCBwcmV2UnVubmluZ1RvdGFsID0gMDtcbiAgICAgICAgICAgIGZvciAobGV0IHlJID0gMDsgeUkgPCB5SW5kZXg7IHlJKyspIHtcbiAgICAgICAgICAgICAgaWYgKGNoZWNrSWZTZWNvbmRhcnkoZGF0YSwgeUksIHhJbmRleCwgZmFsc2UpICE9PSBmb3JTZWNvbmRhcnkpIHtcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBjb25zdCBhZGRWYWwgPSBkYXRhLnlzW3lJXS52YWx1ZXNbeEluZGV4XTtcbiAgICAgICAgICAgICAgLy9Pbmx5IHN0YWNrIHZhbHVlcyBvZiB0aGUgc2FtZSBzaWduXG4gICAgICAgICAgICAgIGlmIChhZGRWYWwgPCAwID09PSB2YWwgPCAwKSB7XG4gICAgICAgICAgICAgICAgcHJldlJ1bm5pbmdUb3RhbCArPSBhZGRWYWw7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB2YWwgKyBwcmV2UnVubmluZ1RvdGFsO1xuICAgICAgICAgIH0pXG4gICAgICAgIDogeS52YWx1ZXM7XG4gICAgfSk7XG4gICAgY29uc3Qgc3VwcFlzID0gaGFzU3VwcGxlbWVudGFyeURhdGEoZGF0YSkgPyBkYXRhLnN1cHBsZW1lbnRhcnlZcyA6IG51bGw7XG4gICAgbGV0IHBvc3NpYmx5U3RhY2tlZFN1cFlzOiBudW1iZXJbXVtdID0gW107XG4gICAgaWYgKHN1cHBZcykge1xuICAgICAgcG9zc2libHlTdGFja2VkU3VwWXMgPSBzdXBwWXMubWFwKCh5LCB5SW5kZXgpID0+IHtcbiAgICAgICAgLy9IYW5kbGUgc3RhY2tpbmdcbiAgICAgICAgcmV0dXJuIGlzU3RhY2tlZFxuICAgICAgICAgID8geS52YWx1ZXMubWFwKCh2YWwsIHhJbmRleCkgPT4ge1xuICAgICAgICAgICAgICBsZXQgcHJldlJ1bm5pbmdUb3RhbCA9IDA7XG4gICAgICAgICAgICAgIGZvciAobGV0IHlJID0gMDsgeUkgPCB5SW5kZXg7IHlJKyspIHtcbiAgICAgICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgICBjaGVja0lmU2Vjb25kYXJ5KGRhdGEsIHlJLCB4SW5kZXgsIHRydWUpICE9PSBmb3JTZWNvbmRhcnkgfHxcbiAgICAgICAgICAgICAgICAgIHN1cHBZc1t5SV0uc3VwcGxlbWVudGFsSW5kZXggIT09IHkuc3VwcGxlbWVudGFsSW5kZXhcbiAgICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjb25zdCBhZGRWYWwgPSBzdXBwWXNbeUldLnZhbHVlc1t4SW5kZXhdO1xuICAgICAgICAgICAgICAgIC8vT25seSBzdGFjayB2YWx1ZXMgb2YgdGhlIHNhbWUgc2lnblxuICAgICAgICAgICAgICAgIGlmIChhZGRWYWwgPCAwID09PSB2YWwgPCAwKSB7XG4gICAgICAgICAgICAgICAgICBwcmV2UnVubmluZ1RvdGFsICs9IGFkZFZhbDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgcmV0dXJuIHZhbCArIHByZXZSdW5uaW5nVG90YWw7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgIDogeS52YWx1ZXM7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBjb25zdCBzY2FsZVJhbmdlOiB7IG1heDogbnVtYmVyOyBtaW46IG51bWJlciB9W10gPSBbXTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGRhdGEueC5sZW5ndGg7IGkrKykge1xuICAgICAgY29uc3QgbWF4Tm9ybVkgPSBNYXRoLm1heChcbiAgICAgICAgLi4ucG9zc2libHlTdGFja2VkWXMubWFwKCh5LCB5SW5kZXgpID0+IHtcbiAgICAgICAgICBpZiAoY2hlY2tJZlNlY29uZGFyeShkYXRhLCB5SW5kZXgsIGksIGZhbHNlKSAhPT0gZm9yU2Vjb25kYXJ5KSB7XG4gICAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIHlbaV07XG4gICAgICAgIH0pLFxuICAgICAgKTtcbiAgICAgIGNvbnN0IG1pbk5vcm1ZID0gTWF0aC5taW4oXG4gICAgICAgIC4uLnBvc3NpYmx5U3RhY2tlZFlzLm1hcCgoeSwgeUluZGV4KSA9PiB7XG4gICAgICAgICAgaWYgKGNoZWNrSWZTZWNvbmRhcnkoZGF0YSwgeUluZGV4LCBpLCBmYWxzZSkgIT09IGZvclNlY29uZGFyeSkge1xuICAgICAgICAgICAgcmV0dXJuIDA7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiB5W2ldO1xuICAgICAgICB9KSxcbiAgICAgICk7XG4gICAgICBjb25zdCBtYXhTdXBZID0gc3VwcFlzXG4gICAgICAgID8gTWF0aC5tYXgoXG4gICAgICAgICAgICAuLi5wb3NzaWJseVN0YWNrZWRTdXBZcy5tYXAoKHksIHlJbmRleCkgPT4ge1xuICAgICAgICAgICAgICBpZiAoY2hlY2tJZlNlY29uZGFyeShkYXRhLCB5SW5kZXgsIGksIHRydWUpICE9PSBmb3JTZWNvbmRhcnkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICByZXR1cm4geVtpXTtcbiAgICAgICAgICAgIH0pLFxuICAgICAgICAgIClcbiAgICAgICAgOiAwO1xuICAgICAgY29uc3QgbWluU3VwWSA9IHN1cHBZc1xuICAgICAgICA/IE1hdGgubWluKFxuICAgICAgICAgICAgLi4ucG9zc2libHlTdGFja2VkU3VwWXMubWFwKCh5LCB5SW5kZXgpID0+IHtcbiAgICAgICAgICAgICAgaWYgKGNoZWNrSWZTZWNvbmRhcnkoZGF0YSwgeUluZGV4LCBpLCB0cnVlKSAhPT0gZm9yU2Vjb25kYXJ5KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIDA7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgcmV0dXJuIHlbaV07XG4gICAgICAgICAgICB9KSxcbiAgICAgICAgICApXG4gICAgICAgIDogMDtcbiAgICAgIGNvbnN0IG1heCA9XG4gICAgICAgIG1heE5vcm1ZID4gMCAmJiBtYXhOb3JtWSA+IG1heFN1cFlcbiAgICAgICAgICA/IG1heE5vcm1ZXG4gICAgICAgICAgOiBtYXhTdXBZID4gMFxuICAgICAgICAgID8gbWF4U3VwWVxuICAgICAgICAgIDogMDtcbiAgICAgIGNvbnN0IG1pbiA9XG4gICAgICAgIG1pbk5vcm1ZIDwgMCAmJiBtaW5Ob3JtWSA8IG1pblN1cFlcbiAgICAgICAgICA/IG1pbk5vcm1ZXG4gICAgICAgICAgOiBtaW5TdXBZIDwgMFxuICAgICAgICAgID8gbWluU3VwWVxuICAgICAgICAgIDogMDtcbiAgICAgIHNjYWxlUmFuZ2UucHVzaCh7IG1heCwgbWluIH0pO1xuICAgIH1cbiAgICByZXR1cm4gc2NhbGVSYW5nZTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGNhbGN1bGF0ZUJhclBvc2l0aW9uKFxuICAgIGRhdGE6IE5vbkZsb3dEYXRhLFxuICAgIGNvbmZpZzogQ29uZmlnLFxuICAgIGNoYXJ0U2l6aW5nVmFsdWVzOiBGdWxsQ2hhcnRTY2FsZVZhbHVlcyxcbiAgICBidWNrZXROdW06IG51bWJlcixcbiAgICBjbHVzdGVyTnVtOiBudW1iZXIsXG4gICk6IG51bWJlciB7XG4gICAgY29uc3Qgb2Zmc2V0ID1cbiAgICAgIGNoYXJ0U2l6aW5nVmFsdWVzLmNoYXJ0RGF0YURpcmVjdGlvbiA9PT0gJ3ZlcnRpY2FsJ1xuICAgICAgICA/IGNoYXJ0U2l6aW5nVmFsdWVzLnRvdGFsTGVmdE9mZnNldFxuICAgICAgICA6IGNoYXJ0U2l6aW5nVmFsdWVzLnRvdGFsVG9wT2Zmc2V0O1xuICAgIGNvbnN0IGNsdXN0ZXJPZmZzZXQgPVxuICAgICAgY2x1c3Rlck51bSAqXG4gICAgICAoY2hhcnRTaXppbmdWYWx1ZXMuYmFyU2l6ZSArIGNoYXJ0U2l6aW5nVmFsdWVzLmJhckNsdXN0ZXJHYXApO1xuICAgIGNvbnN0IGN1bXVsYXRpdmVCdWNrZXRHYXAgPSBnZXRUb3RhbFByZUJ1Y2tldEdhcChcbiAgICAgIGRhdGEsXG4gICAgICBjb25maWcsXG4gICAgICBjaGFydFNpemluZ1ZhbHVlcyxcbiAgICAgIGJ1Y2tldE51bSxcbiAgICApO1xuICAgIHJldHVybiBvZmZzZXQgKyBjdW11bGF0aXZlQnVja2V0R2FwICsgY2x1c3Rlck9mZnNldDtcbiAgfVxuXG4gIGZ1bmN0aW9uIGNhbGN1bGF0ZUhvcml6b250YWxCYXJQYXRoKFxuICAgIGxlZnRTaWRlUm91bmQ6IGJvb2xlYW4sXG4gICAgcmlnaHRTaWRlUm91bmQ6IGJvb2xlYW4sXG4gICAgeFZhbHVlOiBudW1iZXIsXG4gICAgeVZhbHVlOiBudW1iZXIsXG4gICAgaG9yUjogbnVtYmVyLFxuICAgIHZlclI6IG51bWJlcixcbiAgICBoZWlnaHQ6IG51bWJlcixcbiAgICB3aWR0aDogbnVtYmVyLFxuICApOiBzdHJpbmcge1xuICAgIGlmIChsZWZ0U2lkZVJvdW5kICYmIHJpZ2h0U2lkZVJvdW5kKSB7XG4gICAgICAvL0JvdGgtc2lkZXMgcm91bmRpbmcgdmFyaWF0aW9uXG4gICAgICBjb25zdCBwYXRoRCA9IGBcbiAgICAgICAgTSAke3hWYWx1ZSArIGhvclJ9LCR7eVZhbHVlfVxuICAgICAgICBoICR7d2lkdGggLSBob3JSICogMn1cbiAgICAgICAgcSR7aG9yUn0sMCAke2hvclJ9LCR7dmVyUn1cbiAgICAgICAgdiAke2hlaWdodCAtIHZlclIgKiAyfVxuICAgICAgICBxMCwke3ZlclJ9IC0ke2hvclJ9LCR7dmVyUn1cbiAgICAgICAgaCAkey0od2lkdGggLSBob3JSICogMil9XG4gICAgICAgIHEtJHtob3JSfSwwIC0ke2hvclJ9LC0ke3ZlclJ9XG4gICAgICAgIHYgLSR7aGVpZ2h0IC0gdmVyUiAqIDJ9XG4gICAgICAgIHEwLC0ke3ZlclJ9ICR7aG9yUn0sLSR7dmVyUn1cbiAgICAgICAgWlxuICAgICAgYDtcbiAgICAgIHJldHVybiBwYXRoRDtcbiAgICB9XG4gICAgaWYgKGxlZnRTaWRlUm91bmQpIHtcbiAgICAgIC8vTGVmdC1zaWRlIHJvdW5kaW5nIHZhcmlhdGlvblxuICAgICAgY29uc3QgcGF0aEQgPSBgXG4gICAgICAgIE0gJHt4VmFsdWUgKyBob3JSfSwke3lWYWx1ZX1cbiAgICAgICAgaCAke3dpZHRoIC0gaG9yUn1cbiAgICAgICAgdiAke2hlaWdodH1cbiAgICAgICAgaCAkey0od2lkdGggLSBob3JSKX1cbiAgICAgICAgcS0ke2hvclJ9LDAgLSR7aG9yUn0sLSR7dmVyUn1cbiAgICAgICAgdiAtJHtoZWlnaHQgLSB2ZXJSICogMn1cbiAgICAgICAgcTAsLSR7dmVyUn0gJHtob3JSfSwtJHt2ZXJSfVxuICAgICAgICBaXG4gICAgICBgO1xuICAgICAgcmV0dXJuIHBhdGhEO1xuICAgIH1cbiAgICBpZiAocmlnaHRTaWRlUm91bmQpIHtcbiAgICAgIC8vUmlnaHQtc2lkZSByb3VuZGluZyB2YXJpYXRpb25cbiAgICAgIGNvbnN0IHBhdGhEID0gYFxuICAgICAgICBNICR7eFZhbHVlfSwke3lWYWx1ZX1cbiAgICAgICAgaCAke3dpZHRoIC0gaG9yUn1cbiAgICAgICAgcSR7aG9yUn0sMCAke2hvclJ9LCR7dmVyUn1cbiAgICAgICAgdiAke2hlaWdodCAtIHZlclIgKiAyfVxuICAgICAgICBxMCwke3ZlclJ9IC0ke2hvclJ9LCR7dmVyUn1cbiAgICAgICAgaCAkey0od2lkdGggLSBob3JSKX1cbiAgICAgICAgWlxuICAgICAgYDtcbiAgICAgIHJldHVybiBwYXRoRDtcbiAgICB9XG4gICAgLy9Oby1yb3VuZGluZyB2YXJpYXRpb25cbiAgICBjb25zdCBwYXRoRCA9IGBcbiAgICAgIE0gJHt4VmFsdWV9LCR7eVZhbHVlfVxuICAgICAgaCAke3dpZHRofVxuICAgICAgdiAke2hlaWdodH1cbiAgICAgIGggJHstd2lkdGh9XG4gICAgICB2IC0ke2hlaWdodH1cbiAgICAgIFpcbiAgICBgO1xuICAgIHJldHVybiBwYXRoRDtcbiAgfVxuXG4gIGZ1bmN0aW9uIGdldEJ1Y2tldEFuZENsdXN0ZXJOdW1Gb3JIb3ZlcihcbiAgICBwb3M6IG51bWJlcixcbiAgICBjaGFydFNpemluZ1ZhbHVlczogRnVsbENoYXJ0U2NhbGVWYWx1ZXMsXG4gICAgZGF0YTogTm9uRmxvd0RhdGEsXG4gICAgY29uZmlnOiBDb25maWcsXG4gICAgYnVja2V0Q291bnQ6IG51bWJlcixcbiAgKToge1xuICAgIGJ1Y2tldE51bTogbnVtYmVyO1xuICAgIGNsdXN0ZXJOdW06IG51bWJlcjtcbiAgICBjbHVzdGVyTm9ybUNvdW50OiBudW1iZXI7XG4gICAgY2x1c3Rlck51bVR5cGU6ICdub3JtJyB8ICdzdXBwJztcbiAgfSB8IG51bGwge1xuICAgIGxldCBidWNrZXRMZWV3YXkgPSBjaGFydFNpemluZ1ZhbHVlcy5idWNrZXRHYXAgLyA0O1xuICAgIC8vaWYgdGhlcmUncyBvbmx5IDEgZGF0YSBwb2ludCwgdXNlIHRoZSBvdXRlckdhcCBhcyBsZWV3YXkgaW5zdGVhZFxuICAgIGlmIChkYXRhLngubGVuZ3RoID09PSAxKSB7XG4gICAgICBidWNrZXRMZWV3YXkgPSBjaGFydFNpemluZ1ZhbHVlcy5vdXRlckdhcCAvIDQ7XG4gICAgfVxuICAgIGNvbnN0IGJhckxlZXdheSA9IGNoYXJ0U2l6aW5nVmFsdWVzLmJhckNsdXN0ZXJHYXAgLyAyO1xuXG4gICAgY29uc3Qgb2Zmc2V0ID1cbiAgICAgIGNoYXJ0U2l6aW5nVmFsdWVzLmNoYXJ0RGF0YURpcmVjdGlvbiA9PT0gJ3ZlcnRpY2FsJ1xuICAgICAgICA/IGNoYXJ0U2l6aW5nVmFsdWVzLnRvdGFsTGVmdE9mZnNldFxuICAgICAgICA6IGNoYXJ0U2l6aW5nVmFsdWVzLnRvdGFsVG9wT2Zmc2V0O1xuICAgIGNvbnN0IHJlbGF0aXZlUG9zID0gcG9zIC0gb2Zmc2V0O1xuICAgIGxldCBidWNrZXROdW0gPSAtMTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGJ1Y2tldENvdW50OyBpKyspIHtcbiAgICAgIGNvbnN0IGJ1Y2tldFN0YXJ0UG9zID0gZ2V0VG90YWxQcmVCdWNrZXRHYXAoXG4gICAgICAgIGRhdGEsXG4gICAgICAgIGNvbmZpZyxcbiAgICAgICAgY2hhcnRTaXppbmdWYWx1ZXMsXG4gICAgICAgIGksXG4gICAgICApO1xuICAgICAgaWYgKFxuICAgICAgICBidWNrZXRTdGFydFBvcyAtIGJ1Y2tldExlZXdheSA8IHJlbGF0aXZlUG9zICYmXG4gICAgICAgIGJ1Y2tldFN0YXJ0UG9zICtcbiAgICAgICAgICBnZXRCdWNrZXRTaXplKGRhdGEsIGNvbmZpZywgY2hhcnRTaXppbmdWYWx1ZXMpICtcbiAgICAgICAgICBidWNrZXRMZWV3YXkgPlxuICAgICAgICAgIHJlbGF0aXZlUG9zXG4gICAgICApIHtcbiAgICAgICAgYnVja2V0TnVtID0gaTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuICAgIGlmIChidWNrZXROdW0gPT09IC0xKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgaWYgKCFpc0NsdXN0ZXJlZERhdGEoZGF0YSwgY29uZmlnLCB0cnVlKSkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgYnVja2V0TnVtLFxuICAgICAgICBjbHVzdGVyTnVtOiAwLFxuICAgICAgICBjbHVzdGVyTm9ybUNvdW50OiAxLFxuICAgICAgICBjbHVzdGVyTnVtVHlwZTogJ25vcm0nLFxuICAgICAgfTtcbiAgICB9XG5cbiAgICBjb25zdCByZWxhdGl2ZUJ1Y2tldFBvcyA9XG4gICAgICByZWxhdGl2ZVBvcyAtXG4gICAgICBnZXRUb3RhbFByZUJ1Y2tldEdhcChkYXRhLCBjb25maWcsIGNoYXJ0U2l6aW5nVmFsdWVzLCBidWNrZXROdW0pO1xuICAgIGNvbnN0IGNsdXN0ZXJDb3VudCA9IGdldENsdXN0ZXJJbmZvRm9yQnVja2V0KGRhdGEsIGNvbmZpZyk7XG4gICAgbGV0IGNsdXN0ZXJOdW0gPSAtMTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGNsdXN0ZXJDb3VudC50b3RhbDsgaSsrKSB7XG4gICAgICBjb25zdCBiYXJTdGFydFBvcyA9XG4gICAgICAgIChjaGFydFNpemluZ1ZhbHVlcy5iYXJTaXplICsgY2hhcnRTaXppbmdWYWx1ZXMuYmFyQ2x1c3RlckdhcCkgKiBpO1xuICAgICAgaWYgKFxuICAgICAgICBiYXJTdGFydFBvcyAtIGJhckxlZXdheSA8IHJlbGF0aXZlQnVja2V0UG9zICYmXG4gICAgICAgIGJhclN0YXJ0UG9zICsgY2hhcnRTaXppbmdWYWx1ZXMuYmFyU2l6ZSArIGJhckxlZXdheSA+IHJlbGF0aXZlQnVja2V0UG9zXG4gICAgICApIHtcbiAgICAgICAgY2x1c3Rlck51bSA9IGk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cbiAgICBpZiAoY2x1c3Rlck51bSA9PT0gLTEpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICBsZXQgY2x1c3Rlck51bVR5cGU6ICdub3JtJyB8ICdzdXBwJyA9ICdub3JtJztcbiAgICBpZiAoY2x1c3Rlck51bSA+PSBjbHVzdGVyQ291bnQubm9ybUNvdW50KSB7XG4gICAgICBjbHVzdGVyTnVtVHlwZSA9ICdzdXBwJztcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgYnVja2V0TnVtLFxuICAgICAgY2x1c3Rlck51bSxcbiAgICAgIGNsdXN0ZXJOb3JtQ291bnQ6IGNsdXN0ZXJDb3VudC5ub3JtQ291bnQsXG4gICAgICBjbHVzdGVyTnVtVHlwZSxcbiAgICB9O1xuICB9XG5cbiAgZnVuY3Rpb24gZmluZE5lYXJlc3RJbmRleFdpdGhTZWNvbmRhcnkoXG4gICAgeUluZm86IHsgdmFsdWU6IG51bWJlcjsgaXNTZWNvbmRhcnk6IGJvb2xlYW4gfVtdLFxuICAgIHlQb3M6IG51bWJlcixcbiAgICBzY2FsZTogKGlucHV0OiBudW1iZXIsIGlzU2Vjb25kYXJ5OiBib29sZWFuIHwgdW5kZWZpbmVkKSA9PiBudW1iZXIsXG4gICkge1xuICAgIGxldCBmb3VuZEluZGV4ID0gMDtcbiAgICBsZXQgY3Vyck1pbkRpc3RhbmNlID0gTWF0aC5hYnMoXG4gICAgICBzY2FsZSh5SW5mb1swXS52YWx1ZSwgeUluZm9bMF0uaXNTZWNvbmRhcnkpIC0geVBvcyxcbiAgICApO1xuICAgIGZvciAobGV0IGkgPSAxOyBpIDwgeUluZm8ubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNvbnN0IG5ld0Rpc3RhbmNlID0gTWF0aC5hYnMoXG4gICAgICAgIHNjYWxlKHlJbmZvW2ldLnZhbHVlLCB5SW5mb1tpXS5pc1NlY29uZGFyeSkgLSB5UG9zLFxuICAgICAgKTtcbiAgICAgIGlmIChuZXdEaXN0YW5jZSA8IGN1cnJNaW5EaXN0YW5jZSkge1xuICAgICAgICBmb3VuZEluZGV4ID0gaTtcbiAgICAgICAgY3Vyck1pbkRpc3RhbmNlID0gbmV3RGlzdGFuY2U7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBmb3VuZEluZGV4O1xuICB9XG5cbiAgZnVuY3Rpb24gZ2V0QmFyWUluZm8oXG4gICAgZGF0YTogTm9uRmxvd0RhdGEsXG4gICAgY29uZmlnOiBDb25maWcsXG4gICAgeUluZGV4OiBudW1iZXIsXG4gICAgeEluZGV4OiBudW1iZXIsXG4gICAgc2NhbGU6IChpbnB1dDogbnVtYmVyLCBpc1NlY29uZGFyeTogYm9vbGVhbiB8IHVuZGVmaW5lZCkgPT4gbnVtYmVyLFxuICAgIGlzU3VwcGxlbWVudGFyeTogYm9vbGVhbiA9IGZhbHNlLFxuICApOiB7IHlWYWx1ZTogbnVtYmVyOyBoZWlnaHQ6IG51bWJlciB9IHtcbiAgICBjb25zdCBpc1N0YWNrZWQgPSBpc1N0YWNrZWREYXRhKGNvbmZpZyk7XG4gICAgY29uc3QgbWluaW11bVNpemUgPSBnZXRNaW5pbXVtRGF0YUVsZW1lbnRTaXplKGNvbmZpZyk7XG4gICAgY29uc3QgemVyb1ZhbCA9IHNjYWxlKDAsIHRydWUpO1xuICAgIGNvbnN0IHlEYXRhID0gZ2V0TWFpbk9yU3VwcFkoZGF0YSwgeUluZGV4LCBpc1N1cHBsZW1lbnRhcnkpO1xuICAgIGNvbnN0IHNjYWxlVmFsdWUgPSBzY2FsZShcbiAgICAgIHlEYXRhLnZhbHVlc1t4SW5kZXhdLFxuICAgICAgY2hlY2tJZlNlY29uZGFyeShkYXRhLCB5SW5kZXgsIHhJbmRleCwgaXNTdXBwbGVtZW50YXJ5KSxcbiAgICApO1xuICAgIGlmIChzY2FsZVZhbHVlID4gemVyb1ZhbCkge1xuICAgICAgbGV0IHByZXZCYXJIZWlnaHRzID0gMDtcbiAgICAgIGlmIChpc1N0YWNrZWQpIHtcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB5SW5kZXg7IGkrKykge1xuICAgICAgICAgIGNvbnN0IGNoZWNrRGF0YSA9IGdldE1haW5PclN1cHBZKGRhdGEsIGksIGlzU3VwcGxlbWVudGFyeSk7XG4gICAgICAgICAgLy9Cb3RoIHlEYXRhIGFuZCBjaGVja0RhdGEgYXJlIGRlZmluaXRlbHkgU3VwcGxlbWVudGFyeURhdGFZcyBpZiBpc1N1cHBsZW1lbnRhcnkgaXMgdHJ1ZSwgYnV0IHRoZXkgZG9uJ3QgcmVhbGl6ZSBpdFxuICAgICAgICAgIGlmIChcbiAgICAgICAgICAgIGlzU3VwcGxlbWVudGFyeSAmJlxuICAgICAgICAgICAgJ3N1cHBsZW1lbnRhbEluZGV4JyBpbiB5RGF0YSAmJlxuICAgICAgICAgICAgJ3N1cHBsZW1lbnRhbEluZGV4JyBpbiBjaGVja0RhdGFcbiAgICAgICAgICApIHtcbiAgICAgICAgICAgIGlmICh5RGF0YS5zdXBwbGVtZW50YWxJbmRleCAhPT0gY2hlY2tEYXRhLnN1cHBsZW1lbnRhbEluZGV4KSB7XG4gICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBjb25zdCBjaGVja1ZhbHVlID0gc2NhbGUoXG4gICAgICAgICAgICBjaGVja0RhdGEudmFsdWVzW3hJbmRleF0sXG4gICAgICAgICAgICBjaGVja0lmU2Vjb25kYXJ5KGRhdGEsIGksIHhJbmRleCwgaXNTdXBwbGVtZW50YXJ5KSxcbiAgICAgICAgICApO1xuICAgICAgICAgIC8vU2tpcCBwb3NpdGl2ZSB2YWx1ZXNcbiAgICAgICAgICBpZiAoY2hlY2tWYWx1ZSA8IHplcm9WYWwpIHtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgIH1cbiAgICAgICAgICBwcmV2QmFySGVpZ2h0cyArPSBhcHBseU1pbmltdW1EYXRhRWxlbWVudFNpemUoXG4gICAgICAgICAgICBjaGVja1ZhbHVlIC0gemVyb1ZhbCxcbiAgICAgICAgICAgIGNoZWNrRGF0YS52YWx1ZXNbeEluZGV4XSxcbiAgICAgICAgICAgIG1pbmltdW1TaXplLFxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGNvbnN0IHlWYWx1ZSA9IHplcm9WYWwgKyBwcmV2QmFySGVpZ2h0cztcbiAgICAgIGNvbnN0IGhlaWdodCA9IGFwcGx5TWluaW11bURhdGFFbGVtZW50U2l6ZShcbiAgICAgICAgc2NhbGVWYWx1ZSAtIHplcm9WYWwsXG4gICAgICAgIHlEYXRhLnZhbHVlc1t4SW5kZXhdLFxuICAgICAgICBtaW5pbXVtU2l6ZSxcbiAgICAgICk7XG4gICAgICByZXR1cm4geyB5VmFsdWUsIGhlaWdodCB9O1xuICAgIH1cbiAgICBsZXQgcHJldkJhckhlaWdodHMgPSAwO1xuICAgIGlmIChpc1N0YWNrZWQpIHtcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgeUluZGV4OyBpKyspIHtcbiAgICAgICAgY29uc3QgY2hlY2tEYXRhID0gZ2V0TWFpbk9yU3VwcFkoZGF0YSwgaSwgaXNTdXBwbGVtZW50YXJ5KTtcbiAgICAgICAgLy9Cb3RoIHlEYXRhIGFuZCBjaGVja0RhdGEgYXJlIGRlZmluaXRlbHkgU3VwcGxlbWVudGFyeURhdGFZcyBpZiBpc1N1cHBsZW1lbnRhcnkgaXMgdHJ1ZSwgYnV0IHRoZXkgZG9uJ3QgcmVhbGl6ZSBpdFxuICAgICAgICBpZiAoXG4gICAgICAgICAgaXNTdXBwbGVtZW50YXJ5ICYmXG4gICAgICAgICAgJ3N1cHBsZW1lbnRhbEluZGV4JyBpbiB5RGF0YSAmJlxuICAgICAgICAgICdzdXBwbGVtZW50YWxJbmRleCcgaW4gY2hlY2tEYXRhXG4gICAgICAgICkge1xuICAgICAgICAgIGlmICh5RGF0YS5zdXBwbGVtZW50YWxJbmRleCAhPT0gY2hlY2tEYXRhLnN1cHBsZW1lbnRhbEluZGV4KSB7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgY2hlY2tWYWx1ZSA9IHNjYWxlKFxuICAgICAgICAgIGNoZWNrRGF0YS52YWx1ZXNbeEluZGV4XSxcbiAgICAgICAgICBjaGVja0lmU2Vjb25kYXJ5KGRhdGEsIGksIHhJbmRleCwgaXNTdXBwbGVtZW50YXJ5KSxcbiAgICAgICAgKTtcbiAgICAgICAgLy9Ta2lwIG5lZ2F0aXZlIHZhbHVlc1xuICAgICAgICBpZiAoY2hlY2tWYWx1ZSA+IHplcm9WYWwpIHtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBwcmV2QmFySGVpZ2h0cyArPSBhcHBseU1pbmltdW1EYXRhRWxlbWVudFNpemUoXG4gICAgICAgICAgemVyb1ZhbCAtIGNoZWNrVmFsdWUsXG4gICAgICAgICAgY2hlY2tEYXRhLnZhbHVlc1t4SW5kZXhdLFxuICAgICAgICAgIG1pbmltdW1TaXplLFxuICAgICAgICApO1xuICAgICAgfVxuICAgIH1cbiAgICBjb25zdCBoZWlnaHQgPSBhcHBseU1pbmltdW1EYXRhRWxlbWVudFNpemUoXG4gICAgICB6ZXJvVmFsIC0gc2NhbGVWYWx1ZSxcbiAgICAgIHlEYXRhLnZhbHVlc1t4SW5kZXhdLFxuICAgICAgbWluaW11bVNpemUsXG4gICAgKTtcbiAgICBjb25zdCB5VmFsdWUgPSB6ZXJvVmFsIC0gaGVpZ2h0IC0gcHJldkJhckhlaWdodHM7XG4gICAgcmV0dXJuIHsgeVZhbHVlLCBoZWlnaHQgfTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGdldFN1cHBCYXJZSW5mb1ZpYVlJbmRleChcbiAgICBkYXRhOiBOb25GbG93RGF0YSxcbiAgICBjb25maWc6IENvbmZpZyxcbiAgICB5SW5kZXg6IG51bWJlcixcbiAgICBzdXBwSW5kZXg6IG51bWJlcixcbiAgICB4SW5kZXg6IG51bWJlcixcbiAgICBzY2FsZTogKGlucHV0OiBudW1iZXIsIGlzU2Vjb25kYXJ5OiBib29sZWFuIHwgdW5kZWZpbmVkKSA9PiBudW1iZXIsXG4gICk6IHsgeVZhbHVlOiBudW1iZXI7IGhlaWdodDogbnVtYmVyIH0ge1xuICAgIGlmICghaGFzU3VwcGxlbWVudGFyeURhdGEoZGF0YSkpIHtcbiAgICAgIHJldHVybiB7IHlWYWx1ZTogMCwgaGVpZ2h0OiAwIH07XG4gICAgfVxuICAgIGNvbnN0IHN1cHBZcyA9IGRhdGEuc3VwcGxlbWVudGFyeVlzO1xuICAgIC8vIEZpbmQgc3VwcGxlbWVudGFyeSBiYXJzIHdpdGggdGhlIGdpdmVuIHN1cHBsZW1lbnRhbEluZGV4XG4gICAgY29uc3QgZ3JvdXBTdXBwcyA9IHN1cHBZcy5maWx0ZXIocyA9PiBzLnN1cHBsZW1lbnRhbEluZGV4ID09PSBzdXBwSW5kZXgpO1xuICAgIC8vIHlJbmRleCByZWZlcnMgdG8gd2hpY2ggWSBzZXJpZXMgKHdpdGhpbiB0aGUgc3VwcGxlbWVudGFsIGdyb3VwKSB3ZSdyZSBsb29raW5nIGF0XG4gICAgaWYgKHlJbmRleCA+PSAwICYmIHlJbmRleCA8IGdyb3VwU3VwcHMubGVuZ3RoKSB7XG4gICAgICAvLyBGaW5kIHRoaXMgc3VwcCBpbiB0aGUgb3JpZ2luYWwgYXJyYXlcbiAgICAgIGNvbnN0IHN1cHBJbk9yaWdpbmFsQXJyYXkgPSBzdXBwWXMuaW5kZXhPZihncm91cFN1cHBzW3lJbmRleF0pO1xuICAgICAgcmV0dXJuIGdldEJhcllJbmZvKFxuICAgICAgICBkYXRhLFxuICAgICAgICBjb25maWcsXG4gICAgICAgIHN1cHBJbk9yaWdpbmFsQXJyYXksXG4gICAgICAgIHhJbmRleCxcbiAgICAgICAgc2NhbGUsXG4gICAgICAgIHRydWUsXG4gICAgICApO1xuICAgIH1cbiAgICByZXR1cm4geyB5VmFsdWU6IDAsIGhlaWdodDogMCB9O1xuICB9XG5cbiAgZnVuY3Rpb24gZ2V0TWFpbk9yU3VwcFkoXG4gICAgZGF0YTogTm9uRmxvd0RhdGEsXG4gICAgeUluZGV4OiBudW1iZXIsXG4gICAgaXNTdXBwbGVtZW50YXJ5OiBib29sZWFuLFxuICApOiBEYXRhWSB8IFN1cHBsZW1lbnRhcnlEYXRhWSB7XG4gICAgaWYgKGhhc1N1cHBsZW1lbnRhcnlEYXRhKGRhdGEpICYmIGlzU3VwcGxlbWVudGFyeSkge1xuICAgICAgcmV0dXJuIGRhdGEuc3VwcGxlbWVudGFyeVlzW3lJbmRleF07XG4gICAgfVxuICAgIHJldHVybiBkYXRhLnlzW3lJbmRleF07XG4gIH1cblxuICBmdW5jdGlvbiBnZXRCYXJYSW5mbyhcbiAgICBkYXRhOiBOb25GbG93RGF0YSxcbiAgICBjb25maWc6IENvbmZpZyxcbiAgICB5SW5kZXg6IG51bWJlcixcbiAgICB4SW5kZXg6IG51bWJlcixcbiAgICBzY2FsZTogKGlucHV0OiBudW1iZXIsIGlzU2Vjb25kYXJ5OiBib29sZWFuIHwgdW5kZWZpbmVkKSA9PiBudW1iZXIsXG4gICAgaXNTdXBwbGVtZW50YXJ5OiBib29sZWFuID0gZmFsc2UsXG4gICk6IHsgeFZhbHVlOiBudW1iZXI7IHdpZHRoOiBudW1iZXIgfSB7XG4gICAgY29uc3QgaXNTdGFja2VkID0gaXNTdGFja2VkRGF0YShjb25maWcpO1xuICAgIGNvbnN0IG1pbmltdW1TaXplID0gZ2V0TWluaW11bURhdGFFbGVtZW50U2l6ZShjb25maWcpO1xuICAgIGNvbnN0IHplcm9WYWwgPSBzY2FsZSgwLCB0cnVlKTtcbiAgICBjb25zdCB5RGF0YSA9IGdldE1haW5PclN1cHBZKGRhdGEsIHlJbmRleCwgaXNTdXBwbGVtZW50YXJ5KTtcbiAgICBjb25zdCBzY2FsZVZhbHVlID0gc2NhbGUoXG4gICAgICB5RGF0YS52YWx1ZXNbeEluZGV4XSxcbiAgICAgIGNoZWNrSWZTZWNvbmRhcnkoZGF0YSwgeUluZGV4LCB4SW5kZXgsIGlzU3VwcGxlbWVudGFyeSksXG4gICAgKTtcbiAgICBpZiAoc2NhbGVWYWx1ZSA8IHplcm9WYWwpIHtcbiAgICAgIGxldCBwcmV2QmFyV2lkdGhzID0gMDtcbiAgICAgIGlmIChpc1N0YWNrZWQpIHtcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB5SW5kZXg7IGkrKykge1xuICAgICAgICAgIGNvbnN0IGNoZWNrRGF0YSA9IGdldE1haW5PclN1cHBZKGRhdGEsIGksIGlzU3VwcGxlbWVudGFyeSk7XG4gICAgICAgICAgLy9Cb3RoIHlEYXRhIGFuZCBjaGVja0RhdGEgYXJlIGRlZmluaXRlbHkgU3VwcGxlbWVudGFyeURhdGFZcyBpZiBpc1N1cHBsZW1lbnRhcnkgaXMgdHJ1ZSwgYnV0IHRoZXkgZG9uJ3QgcmVhbGl6ZSBpdFxuICAgICAgICAgIGlmIChcbiAgICAgICAgICAgIGlzU3VwcGxlbWVudGFyeSAmJlxuICAgICAgICAgICAgJ3N1cHBsZW1lbnRhbEluZGV4JyBpbiB5RGF0YSAmJlxuICAgICAgICAgICAgJ3N1cHBsZW1lbnRhbEluZGV4JyBpbiBjaGVja0RhdGFcbiAgICAgICAgICApIHtcbiAgICAgICAgICAgIGlmICh5RGF0YS5zdXBwbGVtZW50YWxJbmRleCAhPT0gY2hlY2tEYXRhLnN1cHBsZW1lbnRhbEluZGV4KSB7XG4gICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBjb25zdCBjaGVja1ZhbCA9IHNjYWxlKFxuICAgICAgICAgICAgY2hlY2tEYXRhLnZhbHVlc1t4SW5kZXhdLFxuICAgICAgICAgICAgY2hlY2tJZlNlY29uZGFyeShkYXRhLCBpLCB4SW5kZXgsIGlzU3VwcGxlbWVudGFyeSksXG4gICAgICAgICAgKTtcbiAgICAgICAgICAvL1NraXAgcG9zaXRpdmUgdmFsdWVzXG4gICAgICAgICAgaWYgKGNoZWNrVmFsID4gemVyb1ZhbCkge1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgfVxuICAgICAgICAgIHByZXZCYXJXaWR0aHMgKz0gYXBwbHlNaW5pbXVtRGF0YUVsZW1lbnRTaXplKFxuICAgICAgICAgICAgemVyb1ZhbCAtIGNoZWNrVmFsLFxuICAgICAgICAgICAgY2hlY2tEYXRhLnZhbHVlc1t4SW5kZXhdLFxuICAgICAgICAgICAgbWluaW11bVNpemUsXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgY29uc3Qgd2lkdGggPSBhcHBseU1pbmltdW1EYXRhRWxlbWVudFNpemUoXG4gICAgICAgIHplcm9WYWwgLSBzY2FsZVZhbHVlLFxuICAgICAgICB5RGF0YS52YWx1ZXNbeEluZGV4XSxcbiAgICAgICAgbWluaW11bVNpemUsXG4gICAgICApO1xuICAgICAgY29uc3QgeFZhbHVlID0gemVyb1ZhbCAtIHdpZHRoIC0gcHJldkJhcldpZHRocztcbiAgICAgIHJldHVybiB7IHhWYWx1ZSwgd2lkdGggfTtcbiAgICB9XG4gICAgbGV0IHByZXZCYXJXaWR0aHMgPSAwO1xuICAgIGlmIChpc1N0YWNrZWQpIHtcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgeUluZGV4OyBpKyspIHtcbiAgICAgICAgY29uc3QgY2hlY2tEYXRhID0gZ2V0TWFpbk9yU3VwcFkoZGF0YSwgaSwgaXNTdXBwbGVtZW50YXJ5KTtcbiAgICAgICAgLy9Cb3RoIHlEYXRhIGFuZCBjaGVja0RhdGEgYXJlIGRlZmluaXRlbHkgU3VwcGxlbWVudGFyeURhdGFZcyBpZiBpc1N1cHBsZW1lbnRhcnkgaXMgdHJ1ZSwgYnV0IHRoZXkgZG9uJ3QgcmVhbGl6ZSBpdFxuICAgICAgICBpZiAoXG4gICAgICAgICAgaXNTdXBwbGVtZW50YXJ5ICYmXG4gICAgICAgICAgJ3N1cHBsZW1lbnRhbEluZGV4JyBpbiB5RGF0YSAmJlxuICAgICAgICAgICdzdXBwbGVtZW50YWxJbmRleCcgaW4gY2hlY2tEYXRhXG4gICAgICAgICkge1xuICAgICAgICAgIGlmICh5RGF0YS5zdXBwbGVtZW50YWxJbmRleCAhPT0gY2hlY2tEYXRhLnN1cHBsZW1lbnRhbEluZGV4KSB7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgY2hlY2tWYWwgPSBzY2FsZShcbiAgICAgICAgICBjaGVja0RhdGEudmFsdWVzW3hJbmRleF0sXG4gICAgICAgICAgY2hlY2tJZlNlY29uZGFyeShkYXRhLCBpLCB4SW5kZXgsIGlzU3VwcGxlbWVudGFyeSksXG4gICAgICAgICk7XG4gICAgICAgIC8vU2tpcCBuZWdhdGl2ZSB2YWx1ZXNcbiAgICAgICAgaWYgKGNoZWNrVmFsIDwgemVyb1ZhbCkge1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIHByZXZCYXJXaWR0aHMgKz0gYXBwbHlNaW5pbXVtRGF0YUVsZW1lbnRTaXplKFxuICAgICAgICAgIGNoZWNrVmFsIC0gemVyb1ZhbCxcbiAgICAgICAgICBjaGVja0RhdGEudmFsdWVzW3hJbmRleF0sXG4gICAgICAgICAgbWluaW11bVNpemUsXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfVxuICAgIGNvbnN0IHhWYWx1ZSA9IHByZXZCYXJXaWR0aHMgKyB6ZXJvVmFsO1xuICAgIGNvbnN0IHdpZHRoID0gYXBwbHlNaW5pbXVtRGF0YUVsZW1lbnRTaXplKFxuICAgICAgc2NhbGVWYWx1ZSAtIHplcm9WYWwsXG4gICAgICB5RGF0YS52YWx1ZXNbeEluZGV4XSxcbiAgICAgIG1pbmltdW1TaXplLFxuICAgICk7XG4gICAgcmV0dXJuIHsgeFZhbHVlLCB3aWR0aCB9O1xuICB9XG5cbiAgZnVuY3Rpb24gY2hlY2tJZlNlY29uZGFyeShcbiAgICBkYXRhOiBOb25GbG93RGF0YSxcbiAgICB5SW5kZXg6IG51bWJlcixcbiAgICB4SW5kZXg6IG51bWJlcixcbiAgICBpc1N1cHBsZW1lbnRhcnk6IGJvb2xlYW4gPSBmYWxzZSxcbiAgKTogYm9vbGVhbiB7XG4gICAgaWYgKGRhdGEudHlwZSA9PT0gJ2xhYmVsZWQnKSB7XG4gICAgICBpZiAoZGF0YS54W3hJbmRleF0uaXNTZWNvbmRhcnkgPT09IHRydWUpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBnZXRNYWluT3JTdXBwWShkYXRhLCB5SW5kZXgsIGlzU3VwcGxlbWVudGFyeSkuaXNTZWNvbmRhcnkgPT09IHRydWU7XG4gIH1cblxuICBmdW5jdGlvbiB3YXJuVW5zdXBwb3J0ZWRQYXR0ZXJucyhcbiAgICBkYXRhOiBOb25GbG93RGF0YSxcbiAgICBzdXBwb3J0ZWRQYXR0ZXJuczogUGF0dGVybltdLFxuICAgIGNoYXJ0VHlwZTogc3RyaW5nLFxuICApOiB2b2lkIHtcbiAgICBjb25zdCBhbGxZczogRGF0YVlbXSA9IFtcbiAgICAgIC4uLmRhdGEueXMsXG4gICAgICAuLi4oaGFzU3VwcGxlbWVudGFyeURhdGEoZGF0YSkgPyBkYXRhLnN1cHBsZW1lbnRhcnlZcyA6IFtdKSxcbiAgICBdO1xuICAgIGZvciAoY29uc3QgeSBvZiBhbGxZcykge1xuICAgICAgaWYgKFxuICAgICAgICB5LnBhdHRlcm4gJiZcbiAgICAgICAgeS5wYXR0ZXJuICE9PSAnc29saWQnICYmXG4gICAgICAgICFzdXBwb3J0ZWRQYXR0ZXJucy5pbmNsdWRlcyh5LnBhdHRlcm4pXG4gICAgICApIHtcbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICAgIGBIZWFkcyB1cCEgVGhlICcke3kucGF0dGVybn0nIHBhdHRlcm4gaXNuJ3Qgc3VwcG9ydGVkIGZvciAke2NoYXJ0VHlwZX0gY2hhcnRzLiBGYWxsaW5nIGJhY2sgdG8gc29saWQuYCxcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiB3YXJuRmxvd0RhdGEoXG4gICAgZGF0YTogSW5wdXREYXRhLFxuICAgIGNoYXJ0VHlwZTogc3RyaW5nLFxuICApOiBkYXRhIGlzIE5vbkZsb3dEYXRhIHtcbiAgICBpZiAoZGF0YS50eXBlID09PSAnZmxvdycpIHtcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgIGBIZWFkcyB1cCEgVGhlICdmbG93JyBkYXRhIHR5cGUgaXNuJ3Qgc3VwcG9ydGVkIGZvciAke2NoYXJ0VHlwZX0gY2hhcnRzLmAsXG4gICAgICApO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIC8vIGhpZGUgc3RyaXBzIG91dCBoaWRkZW4geSB2YWx1ZXMgd2hpbGUgcmV0YWluaW5nIHRoZSBvcmlnaW5hbCBpbmRpY2VzXG4gIC8vIGZvciB0aGUgcmVtYWluaW5nIHZpc2libGUgdmFsdWVzXG4gIGZ1bmN0aW9uIGhpZGUoZGF0YTogTm9uRmxvd0RhdGEpOiB7XG4gICAgZGF0YTogTm9uRmxvd0RhdGE7XG4gICAgdmlzaWJsZUluZGljZXM6IG51bWJlcltdO1xuICAgIHZpc2libGVTdXBwSW5kaWNlczogbnVtYmVyW107XG4gIH0ge1xuICAgIGNvbnN0IHZpc2libGVJbmRpY2VzID0gZGF0YS55c1xuICAgICAgLm1hcCgoeSwgaSkgPT4gKHsgeSwgaSB9KSlcbiAgICAgIC5maWx0ZXIoKHsgeSB9KSA9PiAheS5oaWRkZW4pXG4gICAgICAubWFwKCh7IGkgfSkgPT4gaSk7XG4gICAgY29uc3QgdmlzaWJsZVN1cHBJbmRpY2VzID0gaGFzU3VwcGxlbWVudGFyeURhdGEoZGF0YSlcbiAgICAgID8gZGF0YS5zdXBwbGVtZW50YXJ5WXNcbiAgICAgICAgICAubWFwKCh5LCBpKSA9PiAoeyB5LCBpIH0pKVxuICAgICAgICAgIC5maWx0ZXIoKHsgeSB9KSA9PiAheS5oaWRkZW4pXG4gICAgICAgICAgLm1hcCgoeyBpIH0pID0+IGkpXG4gICAgICA6IFtdO1xuICAgIHJldHVybiB7XG4gICAgICBkYXRhOiB7XG4gICAgICAgIC4uLmRhdGEsXG4gICAgICAgIHlzOiB2aXNpYmxlSW5kaWNlcy5tYXAoaSA9PiBkYXRhLnlzW2ldKSxcbiAgICAgICAgc3VwcGxlbWVudGFyeVlzOiB2aXNpYmxlU3VwcEluZGljZXMubWFwKGkgPT4gZGF0YS5zdXBwbGVtZW50YXJ5WXMhW2ldKSxcbiAgICAgIH0sXG4gICAgICB2aXNpYmxlSW5kaWNlcyxcbiAgICAgIHZpc2libGVTdXBwSW5kaWNlcyxcbiAgICB9O1xuICB9XG5cbiAgZnVuY3Rpb24gd2F0ZXJmYWxsVHJhbnNmb3JtKFxuICAgIGRhdGE6IE5vbkZsb3dEYXRhLFxuICAgIGlzV2F0ZXJmYWxsOiBib29sZWFuLFxuICApOiB7IGRhdGE6IExhYmVsZWREYXRhOyBtYXA6IE1hcDxEYXRhWSwgRGF0YVk+IH0ge1xuICAgIGNvbnN0IHdhdGVyZmFsbE1hcCA9IG5ldyBNYXA8RGF0YVksIERhdGFZPigpO1xuICAgIGlmIChkYXRhLnR5cGUgPT09ICd0aW1lc2VyaWVzJyB8fCAhaXNXYXRlcmZhbGwpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGRhdGE6IHtcbiAgICAgICAgICB0eXBlOiAnbGFiZWxlZCcsXG4gICAgICAgICAgeDogW10sXG4gICAgICAgICAgeXM6IFtdLFxuICAgICAgICB9LFxuICAgICAgICBtYXA6IHdhdGVyZmFsbE1hcCxcbiAgICAgIH07XG4gICAgfVxuICAgIGNvbnN0IG5ld0RhdGE6IExhYmVsZWREYXRhID0ge1xuICAgICAgLi4uZGF0YSxcbiAgICAgIHg6IFsuLi5kYXRhLngsIHsgbGFiZWw6ICdUb3RhbCcgfV0sXG4gICAgICB5czogW1xuICAgICAgICAuLi5kYXRhLnlzLm1hcCh5ID0+IHtcbiAgICAgICAgICBjb25zdCBuZXdZOiBEYXRhWSA9IHtcbiAgICAgICAgICAgIC4uLnksXG4gICAgICAgICAgICB2YWx1ZXM6IFsuLi55LnZhbHVlcywgeS52YWx1ZXMucmVkdWNlKChhLCBiKSA9PiBhICsgYiwgMCldLFxuICAgICAgICAgIH07XG4gICAgICAgICAgd2F0ZXJmYWxsTWFwLnNldChuZXdZLCB5KTtcbiAgICAgICAgICByZXR1cm4gbmV3WTtcbiAgICAgICAgfSksXG4gICAgICBdLFxuICAgIH07XG4gICAgcmV0dXJuIHtcbiAgICAgIGRhdGE6IG5ld0RhdGEsXG4gICAgICBtYXA6IHdhdGVyZmFsbE1hcCxcbiAgICB9O1xuICB9XG5cbiAgZnVuY3Rpb24gZmxvd3NUcmFuc2Zvcm0oXG4gICAgY29uZmlnOiBGbG93Q29uZmlnLFxuICAgIGRhdGE6IEZsb3dEYXRhLFxuICApOiBQcm9jZXNzZWRGbG93RGF0YSB7XG4gICAgY29uc3QgcmV0dXJuQnVja2V0czogRmxvd0J1Y2tldFtdID0gW107XG4gICAgY29uc3QgbWF4UGF0aExlbmd0aCA9IE1hdGgubWF4KC4uLmRhdGEueXMubWFwKHkgPT4geS5zdGVwcy5sZW5ndGgpKTtcbiAgICBpZiAobWF4UGF0aExlbmd0aCA+IDAgJiYgbWF4UGF0aExlbmd0aCA8IEluZmluaXR5KSB7XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG1heFBhdGhMZW5ndGg7IGkrKykge1xuICAgICAgICBjb25zdCBmbG93QnVja2V0OiBGbG93QnVja2V0ID0ge1xuICAgICAgICAgIHRvdGFsQ291bnQ6IDAsXG4gICAgICAgICAgc3ViQnVja2V0czogW10sXG4gICAgICAgIH07XG4gICAgICAgIGZvciAoY29uc3QgeSBvZiBkYXRhLnlzKSB7XG4gICAgICAgICAgaWYgKHkudmFsdWVzLmxlbmd0aCA+IGkgJiYgeS5zdGVwcy5sZW5ndGggPiBpKSB7XG4gICAgICAgICAgICBjb25zdCBzdWJCdWNrZXRJZCA9IHkuc3RlcHNbaV07XG4gICAgICAgICAgICBjb25zdCBmb3VuZFN1YkJ1Y2tldCA9IGZsb3dCdWNrZXQuc3ViQnVja2V0cy5maW5kKFxuICAgICAgICAgICAgICBzdWJCdWNrZXQgPT4gc3ViQnVja2V0LmlkID09PSBzdWJCdWNrZXRJZCxcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBsZXQgc3ViQnVja2V0OiBGbG93U3ViQnVja2V0O1xuICAgICAgICAgICAgaWYgKGZvdW5kU3ViQnVja2V0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgc3ViQnVja2V0ID0gZm91bmRTdWJCdWNrZXQ7XG4gICAgICAgICAgICAgIHN1YkJ1Y2tldC5jb3VudCArPSB5LnZhbHVlc1tpXTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHN1YkJ1Y2tldCA9IHtcbiAgICAgICAgICAgICAgICBpZDogc3ViQnVja2V0SWQsXG4gICAgICAgICAgICAgICAgY291bnQ6IHkudmFsdWVzW2ldLFxuICAgICAgICAgICAgICAgIGNvbm5lY3Rpb25zOiBbXSxcbiAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgZmxvd0J1Y2tldC5zdWJCdWNrZXRzLnB1c2goc3ViQnVja2V0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZsb3dCdWNrZXQudG90YWxDb3VudCArPSB5LnZhbHVlc1tpXTtcblxuICAgICAgICAgICAgLy9GaWxsIGluIGJhY2t3YXJkcyBjb25uZWN0aW9uc1xuICAgICAgICAgICAgaWYgKGkgPiAwKSB7XG4gICAgICAgICAgICAgIGNvbnN0IGZvdW5kQ29ubmVjdGlvbiA9IHN1YkJ1Y2tldC5jb25uZWN0aW9ucy5maW5kKFxuICAgICAgICAgICAgICAgIGNvbm5lY3Rpb24gPT5cbiAgICAgICAgICAgICAgICAgIGNvbm5lY3Rpb24uc3RhcnQgPT09IHkuc3RlcHNbaSAtIDFdICYmXG4gICAgICAgICAgICAgICAgICBjb25uZWN0aW9uLmVuZCA9PT0gc3ViQnVja2V0SWQgJiZcbiAgICAgICAgICAgICAgICAgIGNvbm5lY3Rpb24uZGlyZWN0aW9uID09PSAnYmFja3dhcmQnLFxuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICBpZiAoZm91bmRDb25uZWN0aW9uICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICBmb3VuZENvbm5lY3Rpb24uY291bnQgKz0geS52YWx1ZXNbaV07XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc3QgbmV3Q29ubmVjdGlvbjogRmxvd0Nvbm5lY3Rpb24gPSB7XG4gICAgICAgICAgICAgICAgICBkaXJlY3Rpb246ICdiYWNrd2FyZCcsXG4gICAgICAgICAgICAgICAgICBzdGFydDogeS5zdGVwc1tpIC0gMV0sXG4gICAgICAgICAgICAgICAgICBlbmQ6IHN1YkJ1Y2tldElkLFxuICAgICAgICAgICAgICAgICAgY291bnQ6IHkudmFsdWVzW2ldLFxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgc3ViQnVja2V0LmNvbm5lY3Rpb25zLnB1c2gobmV3Q29ubmVjdGlvbik7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy9GaWxsIGluIGZvcndhcmRzIGNvbm5lY3Rpb25zXG4gICAgICAgICAgICBpZiAoaSA8IHkuc3RlcHMubGVuZ3RoIC0gMSAmJiBpIDwgeS52YWx1ZXMubGVuZ3RoIC0gMSkge1xuICAgICAgICAgICAgICBjb25zdCBmb3VuZENvbm5lY3Rpb24gPSBzdWJCdWNrZXQuY29ubmVjdGlvbnMuZmluZChcbiAgICAgICAgICAgICAgICBjb25uZWN0aW9uID0+XG4gICAgICAgICAgICAgICAgICBjb25uZWN0aW9uLnN0YXJ0ID09PSBzdWJCdWNrZXRJZCAmJlxuICAgICAgICAgICAgICAgICAgY29ubmVjdGlvbi5lbmQgPT09IHkuc3RlcHNbaSArIDFdICYmXG4gICAgICAgICAgICAgICAgICBjb25uZWN0aW9uLmRpcmVjdGlvbiA9PT0gJ2ZvcndhcmQnLFxuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICBpZiAoZm91bmRDb25uZWN0aW9uICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICBmb3VuZENvbm5lY3Rpb24uY291bnQgKz0geS52YWx1ZXNbaSArIDFdO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnN0IG5ld0Nvbm5lY3Rpb246IEZsb3dDb25uZWN0aW9uID0ge1xuICAgICAgICAgICAgICAgICAgZGlyZWN0aW9uOiAnZm9yd2FyZCcsXG4gICAgICAgICAgICAgICAgICBzdGFydDogc3ViQnVja2V0SWQsXG4gICAgICAgICAgICAgICAgICBlbmQ6IHkuc3RlcHNbaSArIDFdLFxuICAgICAgICAgICAgICAgICAgY291bnQ6IHkudmFsdWVzW2kgKyAxXSxcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIHN1YkJ1Y2tldC5jb25uZWN0aW9ucy5wdXNoKG5ld0Nvbm5lY3Rpb24pO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybkJ1Y2tldHMucHVzaChmbG93QnVja2V0KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBzdWJCdWNrZXRPcmRlcmluZ01hcCA9IG5ldyBNYXA8c3RyaW5nLCBudW1iZXI+KCk7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjb25maWcuZmxvd0NvbmZpZy5zdWJCdWNrZXRzQ29uZmlnLmxlbmd0aDsgaSsrKSB7XG4gICAgICBzdWJCdWNrZXRPcmRlcmluZ01hcC5zZXQoXG4gICAgICAgIGNvbmZpZy5mbG93Q29uZmlnLnN1YkJ1Y2tldHNDb25maWdbaV0uYnVja2V0SWQsXG4gICAgICAgIGksXG4gICAgICApO1xuICAgIH1cbiAgICBjb25zdCBtYXBHZXQgPSAoaWQ6IHN0cmluZyk6IG51bWJlciA9PiB7XG4gICAgICBjb25zdCBmb3VuZFJlc3VsdCA9IHN1YkJ1Y2tldE9yZGVyaW5nTWFwLmdldChpZCk7XG4gICAgICBpZiAoZm91bmRSZXN1bHQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICByZXR1cm4gZm91bmRSZXN1bHQ7XG4gICAgICB9XG4gICAgICAvL0lmIHNvbWV0aGluZyBpc24ndCBkZWZpbmVkIGluIHRoZSBjb25maWcsIHB1dCBpdCBhdCB0aGUgZW5kXG4gICAgICByZXR1cm4gSW5maW5pdHk7XG4gICAgfTtcblxuICAgIC8vRW5zdXJlIHRoZSBkYXRhIGlzIHNvcnRlZCB0aGUgc2FtZSB0aGUgd2F5IHRoZSBjb25maWcgaXMsIGFuZCBkcm9wIGVtcHR5XG4gICAgLy9iYXJzL2Nvbm5lY3Rpb25zIHNvIHRoZXkncmUgbmVpdGhlciBkaXNwbGF5ZWQgbm9yIGZhY3RvcmVkIGludG8gc2l6aW5nXG4gICAgcmV0dXJuIHtcbiAgICAgIHR5cGU6ICdmbG93LXByb2Nlc3NlZCcsXG4gICAgICB4OiByZXR1cm5CdWNrZXRzLm1hcChidWNrZXQgPT4gKHtcbiAgICAgICAgLi4uYnVja2V0LFxuICAgICAgICBzdWJCdWNrZXRzOiBidWNrZXQuc3ViQnVja2V0c1xuICAgICAgICAgIC5maWx0ZXIoc3ViQnVja2V0ID0+IHN1YkJ1Y2tldC5jb3VudCAhPT0gMClcbiAgICAgICAgICAuc29ydCgoYSwgYikgPT4gbWFwR2V0KGEuaWQpIC0gbWFwR2V0KGIuaWQpKVxuICAgICAgICAgIC5tYXAoc3ViQnVja2V0ID0+ICh7XG4gICAgICAgICAgICAuLi5zdWJCdWNrZXQsXG4gICAgICAgICAgICBjb25uZWN0aW9uczogc3ViQnVja2V0LmNvbm5lY3Rpb25zXG4gICAgICAgICAgICAgIC5maWx0ZXIoY29ubmVjdGlvbiA9PiBjb25uZWN0aW9uLmNvdW50ICE9PSAwKVxuICAgICAgICAgICAgICAuc29ydCgoYSwgYikgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IGZpcnN0U29ydCA9IG1hcEdldChhLnN0YXJ0KSAtIG1hcEdldChiLnN0YXJ0KTtcbiAgICAgICAgICAgICAgICBpZiAoZmlyc3RTb3J0ICE9PSAwKSB7XG4gICAgICAgICAgICAgICAgICByZXR1cm4gZmlyc3RTb3J0O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gbWFwR2V0KGEuZW5kKSAtIG1hcEdldChiLmVuZCk7XG4gICAgICAgICAgICAgIH0pLFxuICAgICAgICAgIH0pKSxcbiAgICAgIH0pKSxcbiAgICB9O1xuICB9XG5cbiAgdHlwZSBWYWx1ZVR5cGUgPSAnY291bnQnIHwgJ2N1cnJlbmN5JyB8ICdwZXJjZW50YWdlJyB8ICdkYXlzJztcblxuICBleHBvcnQgZnVuY3Rpb24gZ2V0UGlwZXModmFsdWVUeXBlOiBWYWx1ZVR5cGUpIHtcbiAgICBzd2l0Y2ggKHZhbHVlVHlwZSkge1xuICAgICAgY2FzZSAnY291bnQnOiB7XG4gICAgICAgIHJldHVybiB7IHBpcGU6IG5ldyBTbWFsbE51bWJlclBpcGUoKSwgZnVsbFBpcGU6IG5ldyBOdW1iZXJQaXBlKCkgfTtcbiAgICAgIH1cbiAgICAgIGNhc2UgJ2N1cnJlbmN5JzpcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBwaXBlOiBuZXcgU21hbGxDdXJyZW5jeVBpcGUoKSxcbiAgICAgICAgICBmdWxsUGlwZTogbmV3IEN1cnJlbmN5UGlwZSgnZW4tdXMnKSxcbiAgICAgICAgfTtcbiAgICAgIGNhc2UgJ3BlcmNlbnRhZ2UnOiB7XG4gICAgICAgIGNvbnN0IHBpcGUgPSBuZXcgUGVyY2VudGFnZVBpcGUoKTtcbiAgICAgICAgcmV0dXJuIHsgcGlwZSwgZnVsbFBpcGU6IHBpcGUgfTtcbiAgICAgIH1cbiAgICAgIGNhc2UgJ2RheXMnOiB7XG4gICAgICAgIGNvbnN0IHBpcGUgPSBuZXcgRGF5c1BpcGUoKTtcbiAgICAgICAgcmV0dXJuIHsgcGlwZSwgZnVsbFBpcGU6IHBpcGUgfTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBjb25zdCBpbnRlcnZhbHMgPSBbJ3llYXInLCAncXVhcnRlcicsICdtb250aCcsICd3ZWVrJywgJ2RheSddIGFzIGNvbnN0O1xuICBleHBvcnQgdHlwZSBJbnRlcnZhbCA9ICh0eXBlb2YgaW50ZXJ2YWxzKVtudW1iZXJdO1xuXG4gIGV4cG9ydCBmdW5jdGlvbiBmb3JtYXRlZERhdGUoZGF0ZUZvcm1hdDogSW50ZXJ2YWwsIGRhdGU6IERhdGUpIHtcbiAgICBpZiAoZGF0ZUZvcm1hdCA9PT0gJ3F1YXJ0ZXInKSB7XG4gICAgICBjb25zdCBxdWFydGVyID0gTWF0aC5jZWlsKChkYXRlLmdldFVUQ01vbnRoKCkgKyAxKSAvIDMpO1xuICAgICAgY29uc3QgeWVhciA9IHV0Y0Zvcm1hdChnZXRUaW1lSW50ZXJ2YWxGb3JtYXQoJ3llYXInKSkoZGF0ZSk7XG4gICAgICByZXR1cm4gYFEke3F1YXJ0ZXJ9ICR7eWVhcn1gO1xuICAgIH1cbiAgICBjb25zdCBmb3JtYXQgPSBnZXRUaW1lSW50ZXJ2YWxGb3JtYXQoZGF0ZUZvcm1hdCk7XG4gICAgcmV0dXJuIHV0Y0Zvcm1hdChmb3JtYXQpKGRhdGUpO1xuICB9XG5cbiAgZnVuY3Rpb24gZ2V0VGltZUludGVydmFsRm9ybWF0KGludGVydmFsOiBJbnRlcnZhbCk6IHN0cmluZyB7XG4gICAgc3dpdGNoIChpbnRlcnZhbCkge1xuICAgICAgY2FzZSAnZGF5JzpcbiAgICAgIGNhc2UgJ3dlZWsnOlxuICAgICAgICByZXR1cm4gJyVtLyVkLyVZJztcbiAgICAgIGNhc2UgJ21vbnRoJzpcbiAgICAgIGNhc2UgJ3F1YXJ0ZXInOlxuICAgICAgICByZXR1cm4gJyViICVZJztcbiAgICAgIGNhc2UgJ3llYXInOlxuICAgICAgICByZXR1cm4gJyVZJztcbiAgICB9XG4gIH1cblxuICBleHBvcnQgZnVuY3Rpb24gY29udmVydENoYXJ0RGF0YVRvRG9udXREYXRhKFxuICAgIGNoYXJ0RGF0YTogTm9uRmxvd0RhdGEsXG4gICk6IERvbnV0RGF0YVtdIHtcbiAgICBpZiAoY2hhcnREYXRhLnlzLmZpbmQoeSA9PiB5LnZhbHVlcy5sZW5ndGggPiAxKSkge1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgXCJIZWFkcyB1cCEgUGllIGNoYXJ0cyBkb24ndCBzdXBwb3J0IG11bHRpcGxlIHZhbHVlcyBwZXIgc2VyaWVzXCIsXG4gICAgICApO1xuICAgIH1cblxuICAgIGNvbnN0IGRvbnV0RGF0YSA9IGNoYXJ0RGF0YS55cy5tYXAoeSA9PiAoe1xuICAgICAgbGFiZWw6IHkubGFiZWwsXG4gICAgICBoaWRkZW46IHkuaGlkZGVuLFxuICAgICAgdmFsdWU6IHkudmFsdWVzLmxlbmd0aCA+PSAxID8geS52YWx1ZXNbMF0gOiAwLFxuICAgICAgaXNTZWNvbmRhcnk6IHkuaXNTZWNvbmRhcnksXG4gICAgfSkpO1xuICAgIHJldHVybiBkb251dERhdGE7XG4gIH1cblxuICBmdW5jdGlvbiBhcmNUb1BvaW50KGFuZ2xlOiBudW1iZXIsIHJhZGl1czogbnVtYmVyKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHg6IHJhZGl1cyAqIE1hdGguY29zKGFuZ2xlIC0gTWF0aC5QSSAvIDIpLFxuICAgICAgeTogcmFkaXVzICogTWF0aC5zaW4oYW5nbGUgLSBNYXRoLlBJIC8gMiksXG4gICAgfTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHBvaW50VG9BcmMoeDogbnVtYmVyLCB5OiBudW1iZXIpIHtcbiAgICBjb25zdCByYWRpdXMgPSBNYXRoLmh5cG90KHgsIHkpO1xuICAgIGxldCBhbmdsZSA9IE1hdGguYXRhbjIoeSwgeCkgKyBNYXRoLlBJIC8gMjtcbiAgICAvL05vcm1hbGl6ZSB0byBiZSB3aXRoaW4gcmFuZ2UgWzAsIDLPgF1cbiAgICBhbmdsZSA9IChhbmdsZSArIDIgKiBNYXRoLlBJKSAlICgyICogTWF0aC5QSSk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgYW5nbGUsXG4gICAgICByYWRpdXMsXG4gICAgfTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGdldEZ1bGxDaGFydFNjYWxlVmFsdWVzKFxuICAgIGNvbmZpZzogQ29uZmlnV2l0aEZ1bGxTY2FsaW5nLFxuICAgIGRhdGE6IFByb2Nlc3NEYXRhLFxuICAgIGRpbWVuc2lvbnM6IERpbWVuc2lvbnMsXG4gICAgcGlwZVRyYW5zZm9ybTogKCh2YWx1ZTogbnVtYmVyLCBpc1NlY29uZGFyeTogYm9vbGVhbikgPT4gc3RyaW5nKSB8IG51bGwsXG4gICAgZGF0ZUZvcm1hdDogKChkYXRlOiBEYXRlKSA9PiBzdHJpbmcpIHwgbnVsbCxcbiAgKTogRnVsbENoYXJ0U2NhbGVWYWx1ZXMgfCBudWxsIHtcbiAgICBjb25zdCBjaGFydERhdGFEaXJlY3Rpb24gPSBnZXRDaGFydERhdGFEaXJlY3Rpb24oY29uZmlnKTtcbiAgICBjb25zdCBkZWZhdWx0U2NhbGluZ0NvbmZpZyA9IGdldERlZmF1bHRTY2FsaW5nQ29uZmlnQnlDaGFydFR5cGUoXG4gICAgICBjb25maWcudHlwZSxcbiAgICAgIGNvbmZpZy5zZWNvbmRhcnlWYWx1ZVR5cGUgIT09IHVuZGVmaW5lZCxcbiAgICApO1xuICAgIGNvbnN0IHNjYWxpbmdDb25maWcgPSBjb21iaW5lU2NhbGluZ0luZm8oY29uZmlnLCBkZWZhdWx0U2NhbGluZ0NvbmZpZyk7XG4gICAgY29uc3Qgbm9uRGF0YUF4aXNWYWx1ZXMgPSBjYWxjdWxhdGVOb25EYXRhQXhpc1ZhbHVlcyhcbiAgICAgIGNvbmZpZyxcbiAgICAgIHNjYWxpbmdDb25maWcsXG4gICAgICBjb25maWcuc2NhbGluZ0NvbmZpZz8uZWxlbWVudFNjYWxlcyxcbiAgICAgIGRlZmF1bHRTY2FsaW5nQ29uZmlnLmVsZW1lbnRTY2FsZXMsXG4gICAgICBkaW1lbnNpb25zLFxuICAgICAgZGF0YSxcbiAgICApO1xuICAgIGNvbnN0IGRhdGFBeGlzVmFsdWVzID0gY2FsY3VsYXRlRGF0YUF4aXNWYWx1ZXMoXG4gICAgICBjb25maWcsXG4gICAgICBzY2FsaW5nQ29uZmlnLFxuICAgICAgY29uZmlnLnNjYWxpbmdDb25maWc/LmVsZW1lbnRTY2FsZXMsXG4gICAgICBkZWZhdWx0U2NhbGluZ0NvbmZpZy5lbGVtZW50U2NhbGVzLFxuICAgICAgZGltZW5zaW9ucyxcbiAgICAgIGRhdGEsXG4gICAgICBwaXBlVHJhbnNmb3JtLFxuICAgICAgZGF0ZUZvcm1hdCxcbiAgICApO1xuICAgIGlmIChcbiAgICAgIG5vbkRhdGFBeGlzVmFsdWVzLnNpemluZ0Vycm9yID09PSB0cnVlIHx8XG4gICAgICBkYXRhQXhpc1ZhbHVlcy5zaXppbmdFcnJvciA9PT0gdHJ1ZVxuICAgICkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIGNvbnN0IGRhdGFMYWJlbFN0YXJ0UGFkZGluZyA9XG4gICAgICBnZXREYXRhTGFiZWxTaXppbmdDb3VudChkYXRhLCBjb25maWcpLnN0YXJ0ICpcbiAgICAgIChkYXRhQXhpc1ZhbHVlcy5kYXRhTGFiZWxQYWRkaW5nICsgZGF0YUF4aXNWYWx1ZXMuZGF0YUxhYmVsVGV4dFNpemUpO1xuICAgIGNvbnN0IGRhdGFMYWJlbEVuZFBhZGRpbmcgPVxuICAgICAgZ2V0RGF0YUxhYmVsU2l6aW5nQ291bnQoZGF0YSwgY29uZmlnKS5lbmQgKlxuICAgICAgKGRhdGFBeGlzVmFsdWVzLmRhdGFMYWJlbFBhZGRpbmcgKyBkYXRhQXhpc1ZhbHVlcy5kYXRhTGFiZWxUZXh0U2l6ZSk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgLi4ubm9uRGF0YUF4aXNWYWx1ZXMsXG4gICAgICAuLi5kYXRhQXhpc1ZhbHVlcyxcbiAgICAgIGxlZnRQYWRkaW5nOlxuICAgICAgICBjaGFydERhdGFEaXJlY3Rpb24gPT09ICdob3Jpem9udGFsJ1xuICAgICAgICAgID8gZGF0YUF4aXNWYWx1ZXMuc3RhcnRQYWRkaW5nXG4gICAgICAgICAgOiBub25EYXRhQXhpc1ZhbHVlcy5zdGFydFBhZGRpbmcsXG4gICAgICByaWdodFBhZGRpbmc6XG4gICAgICAgIGNoYXJ0RGF0YURpcmVjdGlvbiA9PT0gJ2hvcml6b250YWwnXG4gICAgICAgICAgPyBkYXRhQXhpc1ZhbHVlcy5lbmRQYWRkaW5nXG4gICAgICAgICAgOiBub25EYXRhQXhpc1ZhbHVlcy5lbmRQYWRkaW5nLFxuICAgICAgdG9wUGFkZGluZzpcbiAgICAgICAgY2hhcnREYXRhRGlyZWN0aW9uID09PSAnaG9yaXpvbnRhbCdcbiAgICAgICAgICA/IG5vbkRhdGFBeGlzVmFsdWVzLnN0YXJ0UGFkZGluZ1xuICAgICAgICAgIDogZGF0YUF4aXNWYWx1ZXMuc3RhcnRQYWRkaW5nLFxuICAgICAgYm90dG9tUGFkZGluZzpcbiAgICAgICAgY2hhcnREYXRhRGlyZWN0aW9uID09PSAnaG9yaXpvbnRhbCdcbiAgICAgICAgICA/IG5vbkRhdGFBeGlzVmFsdWVzLmVuZFBhZGRpbmdcbiAgICAgICAgICA6IGRhdGFBeGlzVmFsdWVzLmVuZFBhZGRpbmcsXG4gICAgICB0b3RhbExlZnRPZmZzZXQ6XG4gICAgICAgIGNoYXJ0RGF0YURpcmVjdGlvbiA9PT0gJ2hvcml6b250YWwnXG4gICAgICAgICAgPyBkYXRhQXhpc1ZhbHVlcy5zdGFydFBhZGRpbmcgK1xuICAgICAgICAgICAgZGF0YUF4aXNWYWx1ZXMubGVmdEJ1Y2tldExhYmVsICtcbiAgICAgICAgICAgIGRhdGFMYWJlbFN0YXJ0UGFkZGluZ1xuICAgICAgICAgIDogbm9uRGF0YUF4aXNWYWx1ZXMuc3RhcnRQYWRkaW5nICsgbm9uRGF0YUF4aXNWYWx1ZXMub3V0ZXJHYXAsXG4gICAgICB0b3RhbFJpZ2h0T2Zmc2V0OlxuICAgICAgICBjaGFydERhdGFEaXJlY3Rpb24gPT09ICdob3Jpem9udGFsJ1xuICAgICAgICAgID8gZGF0YUF4aXNWYWx1ZXMuc3RhcnRQYWRkaW5nICsgZGF0YUxhYmVsRW5kUGFkZGluZ1xuICAgICAgICAgIDogbm9uRGF0YUF4aXNWYWx1ZXMuZW5kUGFkZGluZyArIG5vbkRhdGFBeGlzVmFsdWVzLm91dGVyR2FwLFxuICAgICAgdG90YWxUb3BPZmZzZXQ6XG4gICAgICAgIGNoYXJ0RGF0YURpcmVjdGlvbiA9PT0gJ2hvcml6b250YWwnXG4gICAgICAgICAgPyBub25EYXRhQXhpc1ZhbHVlcy5zdGFydFBhZGRpbmcgKyBub25EYXRhQXhpc1ZhbHVlcy5vdXRlckdhcFxuICAgICAgICAgIDogZGF0YUF4aXNWYWx1ZXMuc3RhcnRQYWRkaW5nICsgZGF0YUxhYmVsU3RhcnRQYWRkaW5nLFxuICAgICAgdG90YWxCb3R0b21PZmZzZXQ6XG4gICAgICAgIGNoYXJ0RGF0YURpcmVjdGlvbiA9PT0gJ2hvcml6b250YWwnXG4gICAgICAgICAgPyBub25EYXRhQXhpc1ZhbHVlcy5lbmRQYWRkaW5nICsgbm9uRGF0YUF4aXNWYWx1ZXMub3V0ZXJHYXBcbiAgICAgICAgICA6IGRhdGFBeGlzVmFsdWVzLmVuZFBhZGRpbmcgKyBkYXRhTGFiZWxFbmRQYWRkaW5nLFxuICAgICAgdGFyZ2V0VGlja0NvdW50OiBzY2FsaW5nQ29uZmlnLnRhcmdldFRpY2tDb3VudCxcbiAgICAgIHNpemVGb3JEYXRhOiBkYXRhQXhpc1ZhbHVlcy5zaXplRm9yRGF0YSxcbiAgICAgIHRvdGFsV2lkdGg6XG4gICAgICAgIGNoYXJ0RGF0YURpcmVjdGlvbiA9PT0gJ2hvcml6b250YWwnXG4gICAgICAgICAgPyBkYXRhQXhpc1ZhbHVlcy50b3RhbFNpemVcbiAgICAgICAgICA6IG5vbkRhdGFBeGlzVmFsdWVzLnRvdGFsU2l6ZSxcbiAgICAgIHRvdGFsSGVpZ2h0OlxuICAgICAgICBjaGFydERhdGFEaXJlY3Rpb24gPT09ICdob3Jpem9udGFsJ1xuICAgICAgICAgID8gbm9uRGF0YUF4aXNWYWx1ZXMudG90YWxTaXplXG4gICAgICAgICAgOiBkYXRhQXhpc1ZhbHVlcy50b3RhbFNpemUsXG4gICAgICBkYXRhTGFiZWxUZXh0U2l6ZTogY29uZmlnLnNob3dEYXRhTGFiZWxzXG4gICAgICAgID8gZGF0YUF4aXNWYWx1ZXMuZGF0YUxhYmVsVGV4dFNpemVcbiAgICAgICAgOiAwLFxuICAgICAgaG9yaXpvbnRhbEF4aXNMYWJlbFRleHRTaXplOlxuICAgICAgICBjaGFydERhdGFEaXJlY3Rpb24gPT09ICd2ZXJ0aWNhbCdcbiAgICAgICAgICA/IGRhdGFBeGlzVmFsdWVzLmJ1Y2tldExhYmVsVGV4dFNpemVcbiAgICAgICAgICA6IGRhdGFBeGlzVmFsdWVzLmRhdGFMYWJlbFRleHRTaXplLCAvL1RpY2tzIGFuZCBkYXRhIGxhYmVscyB1c2UgdGhlIHNhbWUgZm9ybWF0dGluZyBvbiB0aGUgc2FtZSBraW5kIG9mIGRhdGFcbiAgICAgIHZlcnRpY2FsQXhpc0xhYmVsVGV4dFNpemU6IGRhdGFBeGlzVmFsdWVzLmZvbnRTaXplLFxuICAgICAgY2hhcnREYXRhRGlyZWN0aW9uLFxuICAgICAgaG9yaXpvbnRhbENvbnRhaW5lclNjYWxlOiBzY2FsaW5nQ29uZmlnLmhvcml6b250YWxDb250YWluZXJTY2FsZSxcbiAgICAgIHZlcnRpY2FsQ29udGFpbmVyU2NhbGU6IHNjYWxpbmdDb25maWcudmVydGljYWxDb250YWluZXJTY2FsZSxcbiAgICB9O1xuICB9XG5cbiAgZnVuY3Rpb24gY2FsY3VsYXRlTm9uRGF0YUF4aXNWYWx1ZXMoXG4gICAgY29uZmlnOiBDb25maWcsXG4gICAgc2NhbGluZ0NvbmZpZzogTm9uRWxlbWVudFNjYWxpbmdDb25maWcsXG4gICAgZWxlbWVudFNjYWxlczogUGFydGlhbEVsZW1lbnRTY2FsaW5nQ29uZmlnIHwgdW5kZWZpbmVkLFxuICAgIGRlZmF1bHRTaXppbmc6IEZ1bGxFbGVtZW50U2NhbGluZ0NvbmZpZyxcbiAgICBkaW1lbnNpb25zOiBEaW1lbnNpb25zLFxuICAgIGRhdGE6IFByb2Nlc3NEYXRhLFxuICApOiB7XG4gICAgYmFyU2l6ZTogbnVtYmVyO1xuICAgIGJhckNsdXN0ZXJHYXA6IG51bWJlcjtcbiAgICBidWNrZXRHYXA6IG51bWJlcjtcbiAgICBvdXRlckdhcDogbnVtYmVyO1xuICAgIHN0YXJ0UGFkZGluZzogbnVtYmVyO1xuICAgIGVuZFBhZGRpbmc6IG51bWJlcjtcbiAgICB0b3RhbFNpemU6IG51bWJlcjtcbiAgICBzaXppbmdFcnJvcj86IGJvb2xlYW47XG4gIH0ge1xuICAgIGNvbnN0IGNoYXJ0RGF0YURpcmVjdGlvbiA9IGdldENoYXJ0RGF0YURpcmVjdGlvbihjb25maWcpO1xuICAgIGNvbnN0IGJvdW5kaW5nRGltZW5zaW9uID1cbiAgICAgIGNoYXJ0RGF0YURpcmVjdGlvbiA9PT0gJ2hvcml6b250YWwnXG4gICAgICAgID8gZGltZW5zaW9ucy5oZWlnaHRcbiAgICAgICAgOiBkaW1lbnNpb25zLndpZHRoO1xuICAgIGNvbnN0IGF4aXNTY2FsZSA9XG4gICAgICBjaGFydERhdGFEaXJlY3Rpb24gPT09ICdob3Jpem9udGFsJ1xuICAgICAgICA/IHNjYWxpbmdDb25maWc/LnZlcnRpY2FsQXhpc1NjYWxlXG4gICAgICAgIDogc2NhbGluZ0NvbmZpZz8uaG9yaXpvbnRhbEF4aXNTY2FsZTtcblxuICAgIGNvbnN0IGJhclNpemVDb25maWcgPSBnZXRFbGVtZW50U2NhbGluZ0luZm8oXG4gICAgICBlbGVtZW50U2NhbGVzLFxuICAgICAgZGVmYXVsdFNpemluZyxcbiAgICAgICdiYXJTaXplJyxcbiAgICApO1xuICAgIGNvbnN0IGJhckNsdXN0ZXJHYXBDb25maWcgPSBnZXRFbGVtZW50U2NhbGluZ0luZm8oXG4gICAgICBlbGVtZW50U2NhbGVzLFxuICAgICAgZGVmYXVsdFNpemluZyxcbiAgICAgICdiYXJDbHVzdGVyR2FwJyxcbiAgICApO1xuICAgIGNvbnN0IGJ1Y2tldEdhcENvbmZpZyA9IGdldEVsZW1lbnRTY2FsaW5nSW5mbyhcbiAgICAgIGVsZW1lbnRTY2FsZXMsXG4gICAgICBkZWZhdWx0U2l6aW5nLFxuICAgICAgJ2J1Y2tldEdhcCcsXG4gICAgKTtcbiAgICBjb25zdCBvdXRlckdhcENvbmZpZyA9IGdldEVsZW1lbnRTY2FsaW5nSW5mbyhcbiAgICAgIGVsZW1lbnRTY2FsZXMsXG4gICAgICBkZWZhdWx0U2l6aW5nLFxuICAgICAgJ291dGVyR2FwJyxcbiAgICApO1xuICAgIGNvbnN0IHN0YXJ0UGFkZGluZ0NvbmZpZyA9IGdldEVsZW1lbnRTY2FsaW5nSW5mbyhcbiAgICAgIGVsZW1lbnRTY2FsZXMsXG4gICAgICBkZWZhdWx0U2l6aW5nLFxuICAgICAgY2hhcnREYXRhRGlyZWN0aW9uID09PSAnaG9yaXpvbnRhbCcgPyAndG9wUGFkZGluZycgOiAnbGVmdFBhZGRpbmcnLFxuICAgICk7XG4gICAgY29uc3QgZW5kUGFkZGluZ0NvbmZpZyA9IGdldEVsZW1lbnRTY2FsaW5nSW5mbyhcbiAgICAgIGVsZW1lbnRTY2FsZXMsXG4gICAgICBkZWZhdWx0U2l6aW5nLFxuICAgICAgY2hhcnREYXRhRGlyZWN0aW9uID09PSAnaG9yaXpvbnRhbCcgPyAnYm90dG9tUGFkZGluZycgOiAncmlnaHRQYWRkaW5nJyxcbiAgICApO1xuXG4gICAgY29uc3QgYnVja2V0Q291bnQgPSBkYXRhLngubGVuZ3RoO1xuICAgIGxldCBiYXJDb3VudCA9IDA7XG4gICAgbGV0IGJhckNsdXN0ZXJHYXBDb3VudCA9IDA7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBidWNrZXRDb3VudDsgaSsrKSB7XG4gICAgICBpZiAoZGF0YS50eXBlID09PSAnZmxvdy1wcm9jZXNzZWQnKSB7XG4gICAgICAgIGJhckNvdW50ICs9IDE7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb25zdCBidWNrZXRDbHVzdGVyQ291bnQgPSBnZXRDbHVzdGVySW5mb0ZvckJ1Y2tldChkYXRhLCBjb25maWcpO1xuICAgICAgICBiYXJDb3VudCArPSBidWNrZXRDbHVzdGVyQ291bnQudG90YWw7XG4gICAgICAgIGJhckNsdXN0ZXJHYXBDb3VudCArPSBidWNrZXRDbHVzdGVyQ291bnQudG90YWwgLSAxO1xuICAgICAgfVxuICAgIH1cbiAgICBjb25zdCBidWNrZXRHYXBDb3VudCA9IGJ1Y2tldENvdW50IC0gMTtcblxuICAgIGNvbnN0IGJhclRvdGFsU2l6ZSA9IGRldGVybWluZVBvc3NpYmxlU2l6ZXNPZkVsZW1lbnQoXG4gICAgICBiYXJTaXplQ29uZmlnLFxuICAgICAgYmFyQ291bnQsXG4gICAgKTtcbiAgICBjb25zdCBjbHVzdGVyR2FwVG90YWxTaXplID0gZGV0ZXJtaW5lUG9zc2libGVTaXplc09mRWxlbWVudChcbiAgICAgIGJhckNsdXN0ZXJHYXBDb25maWcsXG4gICAgICBiYXJDbHVzdGVyR2FwQ291bnQsXG4gICAgKTtcbiAgICBjb25zdCBidWNrZXRHYXBUb3RhbFNpemUgPSBkZXRlcm1pbmVQb3NzaWJsZVNpemVzT2ZFbGVtZW50KFxuICAgICAgYnVja2V0R2FwQ29uZmlnLFxuICAgICAgYnVja2V0R2FwQ291bnQsXG4gICAgKTtcbiAgICBjb25zdCBvdXRlckdhcFRvdGFsU2l6ZSA9IGRldGVybWluZVBvc3NpYmxlU2l6ZXNPZkVsZW1lbnQoXG4gICAgICBvdXRlckdhcENvbmZpZyxcbiAgICAgIDIsXG4gICAgKTtcbiAgICBjb25zdCBzdGFydFBhZGRpbmdUb3RhbFNpemUgPSBkZXRlcm1pbmVQb3NzaWJsZVNpemVzT2ZFbGVtZW50KFxuICAgICAgc3RhcnRQYWRkaW5nQ29uZmlnLFxuICAgICAgMSxcbiAgICApO1xuICAgIGNvbnN0IGVuZFBhZGRpbmdUb3RhbFNpemUgPSBkZXRlcm1pbmVQb3NzaWJsZVNpemVzT2ZFbGVtZW50KFxuICAgICAgZW5kUGFkZGluZ0NvbmZpZyxcbiAgICAgIDEsXG4gICAgKTtcblxuICAgIGNvbnN0IGNhbGNUYXJnZXRTaXplID1cbiAgICAgIGJhclRvdGFsU2l6ZS50YXJnZXQgK1xuICAgICAgY2x1c3RlckdhcFRvdGFsU2l6ZS50YXJnZXQgK1xuICAgICAgYnVja2V0R2FwVG90YWxTaXplLnRhcmdldCArXG4gICAgICBvdXRlckdhcFRvdGFsU2l6ZS50YXJnZXQgK1xuICAgICAgc3RhcnRQYWRkaW5nVG90YWxTaXplLnRhcmdldCArXG4gICAgICBlbmRQYWRkaW5nVG90YWxTaXplLnRhcmdldDtcblxuICAgIGlmIChcbiAgICAgIGF4aXNTY2FsZSA9PT0gJ25vLXNjYWxlJyB8fFxuICAgICAgY2FsY1RhcmdldFNpemUgPT09IGJvdW5kaW5nRGltZW5zaW9uIHx8XG4gICAgICAoYXhpc1NjYWxlID09PSAnZ3JvdycgJiYgY2FsY1RhcmdldFNpemUgPiBib3VuZGluZ0RpbWVuc2lvbikgfHxcbiAgICAgIChheGlzU2NhbGUgPT09ICdzaHJpbmsnICYmIGNhbGNUYXJnZXRTaXplIDwgYm91bmRpbmdEaW1lbnNpb24pXG4gICAgKSB7XG4gICAgICAvL05vIGVsZW1lbnQgc2NhbGluZyBuZWNlc3NhcnksIHJldHVybiBldmVyeXRoaW5nIGFzIGl0J3MgdGFyZ2V0IHZhbHVlXG4gICAgICByZXR1cm4ge1xuICAgICAgICBiYXJTaXplOiBiYXJTaXplQ29uZmlnLnRhcmdldCxcbiAgICAgICAgYmFyQ2x1c3RlckdhcDogYmFyQ2x1c3RlckdhcENvbmZpZy50YXJnZXQsXG4gICAgICAgIGJ1Y2tldEdhcDogYnVja2V0R2FwQ29uZmlnLnRhcmdldCxcbiAgICAgICAgb3V0ZXJHYXA6IG91dGVyR2FwQ29uZmlnLnRhcmdldCxcbiAgICAgICAgc3RhcnRQYWRkaW5nOiBzdGFydFBhZGRpbmdDb25maWcudGFyZ2V0LFxuICAgICAgICBlbmRQYWRkaW5nOiBlbmRQYWRkaW5nQ29uZmlnLnRhcmdldCxcbiAgICAgICAgdG90YWxTaXplOiBjYWxjVGFyZ2V0U2l6ZSxcbiAgICAgIH07XG4gICAgfVxuXG4gICAgY29uc3QgY2FsY01pblNpemUgPVxuICAgICAgYmFyVG90YWxTaXplLm1pbiArXG4gICAgICBjbHVzdGVyR2FwVG90YWxTaXplLm1pbiArXG4gICAgICBidWNrZXRHYXBUb3RhbFNpemUubWluICtcbiAgICAgIG91dGVyR2FwVG90YWxTaXplLm1pbiArXG4gICAgICBzdGFydFBhZGRpbmdUb3RhbFNpemUubWluICtcbiAgICAgIGVuZFBhZGRpbmdUb3RhbFNpemUubWluO1xuXG4gICAgLy9Ob3RlOiBUaGlzIGlzIG9ubHkgYWN0dWFsbHkgYSBtYXggc2l6ZSBpZiBhbGwgZWxlbWVudHMgaGF2ZSBhIGRlZmluZWQgbWF4XG4gICAgY29uc3QgY2FsY01heFNpemUgPVxuICAgICAgYmFyVG90YWxTaXplLm1heCArXG4gICAgICBjbHVzdGVyR2FwVG90YWxTaXplLm1heCArXG4gICAgICBidWNrZXRHYXBUb3RhbFNpemUubWF4ICtcbiAgICAgIG91dGVyR2FwVG90YWxTaXplLm1heCArXG4gICAgICBzdGFydFBhZGRpbmdUb3RhbFNpemUubWF4ICtcbiAgICAgIGVuZFBhZGRpbmdUb3RhbFNpemUubWF4O1xuXG4gICAgaWYgKGNhbGNNaW5TaXplID4gYm91bmRpbmdEaW1lbnNpb24pIHtcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgICdUaGUgcHJvdmlkZWQgbWluaW11bSBlbGVtZW50IHNpemVzIG1lYW4gdGhlIGNoYXJ0IGNhbm5vdCBkaXNwbGF5IGF0IHRoaXMgc21hbGwgb2YgYSBzaXplJyxcbiAgICAgICk7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBiYXJTaXplOiAwLFxuICAgICAgICBiYXJDbHVzdGVyR2FwOiAwLFxuICAgICAgICBidWNrZXRHYXA6IDAsXG4gICAgICAgIG91dGVyR2FwOiAwLFxuICAgICAgICBzdGFydFBhZGRpbmc6IDAsXG4gICAgICAgIGVuZFBhZGRpbmc6IDAsXG4gICAgICAgIHRvdGFsU2l6ZTogMCxcbiAgICAgICAgc2l6aW5nRXJyb3I6IHRydWUsXG4gICAgICB9O1xuICAgIH1cbiAgICBjb25zdCBjb25maWdDaGVja3MgPSBbXG4gICAgICBnZXRDaGVja2luZ0luZm9Gb3JFbGVtZW50Q29uZmlnKGJhclNpemVDb25maWcsIGJhckNvdW50KSxcbiAgICAgIGdldENoZWNraW5nSW5mb0ZvckVsZW1lbnRDb25maWcoYmFyQ2x1c3RlckdhcENvbmZpZywgYmFyQ2x1c3RlckdhcENvdW50KSxcbiAgICAgIGdldENoZWNraW5nSW5mb0ZvckVsZW1lbnRDb25maWcoYnVja2V0R2FwQ29uZmlnLCBidWNrZXRHYXBDb3VudCksXG4gICAgICBnZXRDaGVja2luZ0luZm9Gb3JFbGVtZW50Q29uZmlnKG91dGVyR2FwQ29uZmlnLCAyKSxcbiAgICAgIGdldENoZWNraW5nSW5mb0ZvckVsZW1lbnRDb25maWcoc3RhcnRQYWRkaW5nQ29uZmlnLCAxKSxcbiAgICAgIGdldENoZWNraW5nSW5mb0ZvckVsZW1lbnRDb25maWcoZW5kUGFkZGluZ0NvbmZpZywgMSksXG4gICAgXTtcbiAgICBsZXQgY3VyclNjYWxpbmdGYWN0b3IgPSAxO1xuICAgIGlmIChjYWxjVGFyZ2V0U2l6ZSA+IGJvdW5kaW5nRGltZW5zaW9uKSB7XG4gICAgICAvL1NjYWxpbmcgZG93blxuICAgICAgbGV0IGZpbmFsU2NhbGluZ0ZhY3RvckZvdW5kID0gZmFsc2U7XG4gICAgICB3aGlsZSAoIWZpbmFsU2NhbGluZ0ZhY3RvckZvdW5kKSB7XG4gICAgICAgIGNvbnN0IG5leHRTY2FsZUZhY3RvckJyZWFrcG9pbnQgPSBNYXRoLm1heChcbiAgICAgICAgICAuLi5jb25maWdDaGVja3NcbiAgICAgICAgICAgIC5tYXAoY2hlY2sgPT4gY2hlY2subWluU2NhbGVGYWN0b3IpXG4gICAgICAgICAgICAuZmlsdGVyKFxuICAgICAgICAgICAgICAodmFsKTogdmFsIGlzIG51bWJlciA9PlxuICAgICAgICAgICAgICAgIHZhbCAhPT0gdW5kZWZpbmVkICYmICEodmFsID49IGN1cnJTY2FsaW5nRmFjdG9yKSxcbiAgICAgICAgICAgICksXG4gICAgICAgICAgMCxcbiAgICAgICAgKTtcbiAgICAgICAgY29uc3QgbmV3U2NhbGVGYWN0b3JTaXplID0gZ2V0U3VtRm9yU2NhbGVWYWx1ZShcbiAgICAgICAgICBjb25maWdDaGVja3MsXG4gICAgICAgICAgbmV4dFNjYWxlRmFjdG9yQnJlYWtwb2ludCxcbiAgICAgICAgKTtcblxuICAgICAgICBpZiAobmV3U2NhbGVGYWN0b3JTaXplIDw9IGJvdW5kaW5nRGltZW5zaW9uKSB7XG4gICAgICAgICAgLy9UaGVyZSdzIGEgc2NhbGUgdmFsdWUgdGhhdCdsbCB3b3JrIGJldHdlZW4gdGhlIGN1cnIgYW5kIG5ldyB2YWx1ZXNcbiAgICAgICAgICAvL1RoZXNlIGFyZSB0aGUgdmFsdWVzIHRoYXQnbGwganVzdCBiZSBhdCB0aGVpciBtaW5cbiAgICAgICAgICBjb25zdCBub25TY2FsZWFibGVWYWx1ZXMgPSBjb25maWdDaGVja3MuZmlsdGVyKFxuICAgICAgICAgICAgY2hlY2sgPT5cbiAgICAgICAgICAgICAgY2hlY2subWluU2NhbGVGYWN0b3IgJiYgY2hlY2subWluU2NhbGVGYWN0b3IgPj0gY3VyclNjYWxpbmdGYWN0b3IsXG4gICAgICAgICAgKTtcbiAgICAgICAgICAvL1RoZXNlIGFyZSB0aGUgdmFsdWVzIHRoYXQgY2FuIHN0aWxsIGJlIHNjYWxlZCBkb3duXG4gICAgICAgICAgY29uc3Qgc2NhbGVhYmxlVmFsdWVzID0gY29uZmlnQ2hlY2tzLmZpbHRlcihcbiAgICAgICAgICAgIGNoZWNrID0+XG4gICAgICAgICAgICAgICFjaGVjay5taW5TY2FsZUZhY3RvciB8fCBjaGVjay5taW5TY2FsZUZhY3RvciA8IGN1cnJTY2FsaW5nRmFjdG9yLFxuICAgICAgICAgICk7XG4gICAgICAgICAgY29uc3Qgd29ya2luZ1NwYWNlID1cbiAgICAgICAgICAgIGJvdW5kaW5nRGltZW5zaW9uIC1cbiAgICAgICAgICAgIGdldFN1bUZvclNjYWxlVmFsdWUobm9uU2NhbGVhYmxlVmFsdWVzLCBjdXJyU2NhbGluZ0ZhY3Rvcik7XG4gICAgICAgICAgY3VyclNjYWxpbmdGYWN0b3IgPVxuICAgICAgICAgICAgd29ya2luZ1NwYWNlIC8gZ2V0U3VtRm9yU2NhbGVWYWx1ZShzY2FsZWFibGVWYWx1ZXMsIDEpO1xuICAgICAgICAgIGZpbmFsU2NhbGluZ0ZhY3RvckZvdW5kID0gdHJ1ZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAvL09uZSBvZiB0aGUgZWxlbWVudHMgaXMgaGl0dGluZyB0aGVpciBtaW5TY2FsZUZhY3Rvciwgc28gZm9yIHNpbXBsaWNpdHkgd2UnbGwganVzdCBnbyBhZ2FpblxuICAgICAgICAgIGN1cnJTY2FsaW5nRmFjdG9yID0gbmV4dFNjYWxlRmFjdG9yQnJlYWtwb2ludDtcblxuICAgICAgICAgIC8vSnVzdCBpbiBjYXNlLCB0aG91Z2ggcHJldmlvdXMgY2hlY2tzIHNob3VsZCBtYWtlIHRoaXMgaW1wb3NzaWJsZVxuICAgICAgICAgIGlmIChjdXJyU2NhbGluZ0ZhY3RvciA9PT0gMCkge1xuICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgICAgICAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgICAgICAgJ1RoZSBnaXZlbiBzaXplIGNhbm5vdCBjb250YWluIHRoZSBmaXhlZCBzaXplcyBnaXZlbiBmb3IgdGhlIGVsZW1lbnRzJyxcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICBiYXJTaXplOiAwLFxuICAgICAgICAgICAgICBiYXJDbHVzdGVyR2FwOiAwLFxuICAgICAgICAgICAgICBidWNrZXRHYXA6IDAsXG4gICAgICAgICAgICAgIG91dGVyR2FwOiAwLFxuICAgICAgICAgICAgICBzdGFydFBhZGRpbmc6IDAsXG4gICAgICAgICAgICAgIGVuZFBhZGRpbmc6IDAsXG4gICAgICAgICAgICAgIHRvdGFsU2l6ZTogMCxcbiAgICAgICAgICAgICAgc2l6aW5nRXJyb3I6IHRydWUsXG4gICAgICAgICAgICB9O1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAvL0NoZWNraW5nIHRvIHNlZSBpZiBhbGwgZWxlbWVudHMgaGF2ZSBhIGRlZmluZWQgbWF4XG4gICAgICBjb25zdCBtYXhpbXVtU2l6ZVBvc3NpYmxlID1cbiAgICAgICAgY29uZmlnQ2hlY2tzLmZpbHRlcihjaGVjayA9PiBjaGVjay5tYXhTY2FsZUZhY3RvciA9PT0gdW5kZWZpbmVkKVxuICAgICAgICAgIC5sZW5ndGggPT09IDA7XG4gICAgICAvL0lmIGFsbCBlbGVtZW50cyBoYXZlIGEgZGVmaW5lZCBtYXgsIGFuZCB0aGF0IG1heCBpcyBsZXNzIHRoYW4gdGhlIHNpemUgd2UncmUgdHJ5aW5nIHRvIGdyb3cgdG8sIGl0J3MgaW1wb3NzaWJsZVxuICAgICAgaWYgKG1heGltdW1TaXplUG9zc2libGUgJiYgY2FsY01heFNpemUgPCBib3VuZGluZ0RpbWVuc2lvbikge1xuICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29uc29sZVxuICAgICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgICAgJ1RoZSBwcm92aWRlZCBtYXhpbXVtIGVsZW1lbnQgd2lkdGhzIG1lYW4gdGhlIGNoYXJ0IGNhbm5vdCBkaXNwbGF5IGF0IHRoaXMgbGFyZ2Ugb2YgYSBzaXplJyxcbiAgICAgICAgKTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBiYXJTaXplOiAwLFxuICAgICAgICAgIGJhckNsdXN0ZXJHYXA6IDAsXG4gICAgICAgICAgYnVja2V0R2FwOiAwLFxuICAgICAgICAgIG91dGVyR2FwOiAwLFxuICAgICAgICAgIHN0YXJ0UGFkZGluZzogMCxcbiAgICAgICAgICBlbmRQYWRkaW5nOiAwLFxuICAgICAgICAgIHRvdGFsU2l6ZTogMCxcbiAgICAgICAgICBzaXppbmdFcnJvcjogdHJ1ZSxcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICAgIC8vU2NhbGluZyB1cFxuICAgICAgbGV0IGZpbmFsU2NhbGluZ0ZhY3RvckZvdW5kID0gZmFsc2U7XG4gICAgICB3aGlsZSAoIWZpbmFsU2NhbGluZ0ZhY3RvckZvdW5kKSB7XG4gICAgICAgIGNvbnN0IG5leHRTY2FsZUZhY3RvckJyZWFrcG9pbnQgPSBNYXRoLm1pbihcbiAgICAgICAgICAuLi5jb25maWdDaGVja3NcbiAgICAgICAgICAgIC5tYXAoY2hlY2sgPT4gY2hlY2subWF4U2NhbGVGYWN0b3IpXG4gICAgICAgICAgICAuZmlsdGVyKFxuICAgICAgICAgICAgICAodmFsKTogdmFsIGlzIG51bWJlciA9PlxuICAgICAgICAgICAgICAgIHZhbCAhPT0gdW5kZWZpbmVkICYmICEodmFsIDw9IGN1cnJTY2FsaW5nRmFjdG9yKSxcbiAgICAgICAgICAgICksXG4gICAgICAgICk7XG4gICAgICAgIGNvbnN0IG5ld1NjYWxlRmFjdG9yU2l6ZSA9IGdldFN1bUZvclNjYWxlVmFsdWUoXG4gICAgICAgICAgY29uZmlnQ2hlY2tzLFxuICAgICAgICAgIG5leHRTY2FsZUZhY3RvckJyZWFrcG9pbnQsXG4gICAgICAgICk7XG5cbiAgICAgICAgaWYgKFxuICAgICAgICAgIG5ld1NjYWxlRmFjdG9yU2l6ZSA+PSBib3VuZGluZ0RpbWVuc2lvbiB8fFxuICAgICAgICAgIG5leHRTY2FsZUZhY3RvckJyZWFrcG9pbnQgPT09IEluZmluaXR5XG4gICAgICAgICkge1xuICAgICAgICAgIC8vVGhlcmUncyBhIHNjYWxlIHZhbHVlIHRoYXQnbGwgd29yayBiZXR3ZWVuIHRoZSBjdXJyIGFuZCBuZXcgdmFsdWVzXG4gICAgICAgICAgLy9UaGVzZSBhcmUgdGhlIHZhbHVlcyB0aGF0J2xsIGp1c3QgYmUgYXQgdGhlaXIgbWF4XG4gICAgICAgICAgY29uc3Qgbm9uU2NhbGVhYmxlVmFsdWVzID0gY29uZmlnQ2hlY2tzLmZpbHRlcihcbiAgICAgICAgICAgIGNoZWNrID0+XG4gICAgICAgICAgICAgIGNoZWNrLm1heFNjYWxlRmFjdG9yICYmIGNoZWNrLm1heFNjYWxlRmFjdG9yIDw9IGN1cnJTY2FsaW5nRmFjdG9yLFxuICAgICAgICAgICk7XG4gICAgICAgICAgLy9UaGVzZSBhcmUgdGhlIHZhbHVlcyB0aGF0IGNhbiBzdGlsbCBiZSBzY2FsZWQgdXBcbiAgICAgICAgICBjb25zdCBzY2FsZWFibGVWYWx1ZXMgPSBjb25maWdDaGVja3MuZmlsdGVyKFxuICAgICAgICAgICAgY2hlY2sgPT5cbiAgICAgICAgICAgICAgIWNoZWNrLm1heFNjYWxlRmFjdG9yIHx8IGNoZWNrLm1heFNjYWxlRmFjdG9yID4gY3VyclNjYWxpbmdGYWN0b3IsXG4gICAgICAgICAgKTtcbiAgICAgICAgICBjb25zdCB3b3JraW5nU3BhY2UgPVxuICAgICAgICAgICAgYm91bmRpbmdEaW1lbnNpb24gLVxuICAgICAgICAgICAgZ2V0U3VtRm9yU2NhbGVWYWx1ZShub25TY2FsZWFibGVWYWx1ZXMsIGN1cnJTY2FsaW5nRmFjdG9yKTtcbiAgICAgICAgICBjdXJyU2NhbGluZ0ZhY3RvciA9XG4gICAgICAgICAgICB3b3JraW5nU3BhY2UgLyBnZXRTdW1Gb3JTY2FsZVZhbHVlKHNjYWxlYWJsZVZhbHVlcywgMSk7XG4gICAgICAgICAgZmluYWxTY2FsaW5nRmFjdG9yRm91bmQgPSB0cnVlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vT25lIG9mIHRoZSBlbGVtZW50cyBpcyBoaXR0aW5nIHRoZWlyIG1heFNjYWxlRmFjdG9yLCBzbyBmb3Igc2ltcGxpY2l0eSB3ZSdsbCBqdXN0IGdvIGFnYWluXG4gICAgICAgICAgY3VyclNjYWxpbmdGYWN0b3IgPSBuZXh0U2NhbGVGYWN0b3JCcmVha3BvaW50O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIGNvbnN0IGJhclNpemUgPSBnZXRTY2FsZWRFbGVtZW50U2l6ZShiYXJTaXplQ29uZmlnLCBjdXJyU2NhbGluZ0ZhY3Rvcik7XG4gICAgY29uc3QgYmFyQ2x1c3RlckdhcCA9IGdldFNjYWxlZEVsZW1lbnRTaXplKFxuICAgICAgYmFyQ2x1c3RlckdhcENvbmZpZyxcbiAgICAgIGN1cnJTY2FsaW5nRmFjdG9yLFxuICAgICk7XG4gICAgY29uc3QgYnVja2V0R2FwID0gZ2V0U2NhbGVkRWxlbWVudFNpemUoYnVja2V0R2FwQ29uZmlnLCBjdXJyU2NhbGluZ0ZhY3Rvcik7XG4gICAgcmV0dXJuIHtcbiAgICAgIGJhclNpemUsXG4gICAgICBiYXJDbHVzdGVyR2FwLFxuICAgICAgYnVja2V0R2FwLFxuICAgICAgb3V0ZXJHYXA6IGdldFNjYWxlZEVsZW1lbnRTaXplKG91dGVyR2FwQ29uZmlnLCBjdXJyU2NhbGluZ0ZhY3RvciksXG4gICAgICBzdGFydFBhZGRpbmc6IGdldFNjYWxlZEVsZW1lbnRTaXplKHN0YXJ0UGFkZGluZ0NvbmZpZywgY3VyclNjYWxpbmdGYWN0b3IpLFxuICAgICAgZW5kUGFkZGluZzogZ2V0U2NhbGVkRWxlbWVudFNpemUoZW5kUGFkZGluZ0NvbmZpZywgY3VyclNjYWxpbmdGYWN0b3IpLFxuICAgICAgdG90YWxTaXplOiBib3VuZGluZ0RpbWVuc2lvbixcbiAgICB9O1xuICB9XG5cbiAgZnVuY3Rpb24gY2FsY3VsYXRlRGF0YUF4aXNWYWx1ZXMoXG4gICAgY29uZmlnOiBDb25maWcsXG4gICAgc2NhbGluZ0NvbmZpZzogTm9uRWxlbWVudFNjYWxpbmdDb25maWcsXG4gICAgZWxlbWVudFNjYWxlczogUGFydGlhbEVsZW1lbnRTY2FsaW5nQ29uZmlnIHwgdW5kZWZpbmVkLFxuICAgIGRlZmF1bHRTaXppbmc6IEZ1bGxFbGVtZW50U2NhbGluZ0NvbmZpZyxcbiAgICBkaW1lbnNpb25zOiBEaW1lbnNpb25zLFxuICAgIGRhdGE6IFByb2Nlc3NEYXRhLFxuICAgIHBpcGVUcmFuc2Zvcm06ICgodmFsdWU6IG51bWJlciwgaXNTZWNvbmRhcnk6IGJvb2xlYW4pID0+IHN0cmluZykgfCBudWxsLFxuICAgIGRhdGVGb3JtYXQ6ICgoZGF0ZTogRGF0ZSkgPT4gc3RyaW5nKSB8IG51bGwsXG4gICk6IHtcbiAgICBzdGFydFBhZGRpbmc6IG51bWJlcjtcbiAgICBlbmRQYWRkaW5nOiBudW1iZXI7XG4gICAgbGVmdEJ1Y2tldExhYmVsOiBudW1iZXI7XG4gICAgZGF0YUxhYmVsVGV4dFNpemU6IG51bWJlcjtcbiAgICBkYXRhTGFiZWxQYWRkaW5nOiBudW1iZXI7XG4gICAgZm9udFNpemU6IG51bWJlcjtcbiAgICBzaXplRm9yRGF0YTogbnVtYmVyO1xuICAgIHRvdGFsU2l6ZTogbnVtYmVyO1xuICAgIGJ1Y2tldExhYmVsVGV4dFNpemU6IG51bWJlcjtcbiAgICBzaXppbmdFcnJvcj86IGJvb2xlYW47XG4gIH0ge1xuICAgIGNvbnN0IGNoYXJ0RGF0YURpcmVjdGlvbiA9IGdldENoYXJ0RGF0YURpcmVjdGlvbihjb25maWcpO1xuICAgIGNvbnN0IGJvdW5kaW5nRGltZW5zaW9uID1cbiAgICAgIGNoYXJ0RGF0YURpcmVjdGlvbiA9PT0gJ2hvcml6b250YWwnXG4gICAgICAgID8gZGltZW5zaW9ucy53aWR0aFxuICAgICAgICA6IGRpbWVuc2lvbnMuaGVpZ2h0O1xuICAgIGNvbnN0IGF4aXNTY2FsZSA9XG4gICAgICBjaGFydERhdGFEaXJlY3Rpb24gPT09ICdob3Jpem9udGFsJ1xuICAgICAgICA/IHNjYWxpbmdDb25maWcuaG9yaXpvbnRhbEF4aXNTY2FsZVxuICAgICAgICA6IHNjYWxpbmdDb25maWcudmVydGljYWxBeGlzU2NhbGU7XG5cbiAgICBjb25zdCBzdGFydFBhZGRpbmdDb25maWcgPSBnZXRFbGVtZW50U2NhbGluZ0luZm8oXG4gICAgICBlbGVtZW50U2NhbGVzLFxuICAgICAgZGVmYXVsdFNpemluZyxcbiAgICAgIGNoYXJ0RGF0YURpcmVjdGlvbiA9PT0gJ2hvcml6b250YWwnID8gJ2xlZnRQYWRkaW5nJyA6ICd0b3BQYWRkaW5nJyxcbiAgICApO1xuICAgIGNvbnN0IGVuZFBhZGRpbmdDb25maWcgPSBnZXRFbGVtZW50U2NhbGluZ0luZm8oXG4gICAgICBlbGVtZW50U2NhbGVzLFxuICAgICAgZGVmYXVsdFNpemluZyxcbiAgICAgIGNoYXJ0RGF0YURpcmVjdGlvbiA9PT0gJ2hvcml6b250YWwnID8gJ3JpZ2h0UGFkZGluZycgOiAnYm90dG9tUGFkZGluZycsXG4gICAgKTtcbiAgICBjb25zdCBsZWZ0TGFiZWxDb25maWcgPSBnZXRFbGVtZW50U2NhbGluZ0luZm8oXG4gICAgICBlbGVtZW50U2NhbGVzLFxuICAgICAgZGVmYXVsdFNpemluZyxcbiAgICAgICdsZWZ0QnVja2V0TGFiZWwnLFxuICAgICk7XG4gICAgY29uc3QgZGF0YUxhYmVsUGFkZGluZ0NvbmZpZyA9IGdldEVsZW1lbnRTY2FsaW5nSW5mbyhcbiAgICAgIGVsZW1lbnRTY2FsZXMsXG4gICAgICBkZWZhdWx0U2l6aW5nLFxuICAgICAgJ2RhdGFMYWJlbFBhZGRpbmcnLFxuICAgICk7XG4gICAgY29uc3QgZm9udFNpemVDb25maWcgPSBnZXRFbGVtZW50U2NhbGluZ0luZm8oXG4gICAgICBlbGVtZW50U2NhbGVzLFxuICAgICAgZGVmYXVsdFNpemluZyxcbiAgICAgICdmb250U2l6ZScsXG4gICAgKTtcbiAgICBjb25zdCBmb250U2l6ZSA9IGZvbnRTaXplQ29uZmlnLnRhcmdldDtcbiAgICBjb25zdCBkYXRhTGFiZWxUZXh0U2l6aW5nID0gZ2V0RGF0YUxhYmVsU2l6ZShkYXRhLCBwaXBlVHJhbnNmb3JtLCBmb250U2l6ZSk7XG4gICAgLy9XZSBhbHdheXMgY2FsY3VsYXRlIGFuZCByZXR1cm4gZGF0YUxhYmVsVGV4dFNpemUsIHNpbmNlIGl0J3MgYWxzbyB1c2VkIGZvciBkZXRlcm1pbmcgYXhpcyBsYWJlbCBzaXplXG4gICAgY29uc3QgZGF0YUxhYmVsVGV4dFNpemUgPVxuICAgICAgY2hhcnREYXRhRGlyZWN0aW9uID09PSAnaG9yaXpvbnRhbCdcbiAgICAgICAgPyBkYXRhTGFiZWxUZXh0U2l6aW5nLmhvcml6b250YWxcbiAgICAgICAgOiBkYXRhTGFiZWxUZXh0U2l6aW5nLnZlcnRpY2FsO1xuICAgIGNvbnN0IGRhdGFMYWJlbEZpeGVkU2l6ZSA9XG4gICAgICBkYXRhTGFiZWxUZXh0U2l6ZSAqIGdldERhdGFMYWJlbFNpemluZ0NvdW50KGRhdGEsIGNvbmZpZykudG90YWw7XG4gICAgY29uc3QgYnVja2V0TGFiZWxUZXh0U2l6ZSA9IGdldEJ1Y2tldExhYmVsU2l6ZShkYXRhLCBmb250U2l6ZSwgZGF0ZUZvcm1hdCk7XG4gICAgLy9GbG93IGNoYXJ0cyBoYXZlIGEgZGF0YSBsYWJlbCBhYm92ZSBlYWNoIHN1Yi1idWNrZXRcbiAgICBjb25zdCBmbG93TGFiZWxTaXplID0gZGF0YUxhYmVsVGV4dFNpemUgKyBkYXRhTGFiZWxQYWRkaW5nQ29uZmlnLnRhcmdldDtcblxuICAgIGNvbnN0IHN0YXJ0UGFkZGluZ1RvdGFsU2l6ZSA9IGRldGVybWluZVBvc3NpYmxlU2l6ZXNPZkVsZW1lbnQoXG4gICAgICBzdGFydFBhZGRpbmdDb25maWcsXG4gICAgICAxLFxuICAgICk7XG4gICAgY29uc3QgZW5kUGFkZGluZ1RvdGFsU2l6ZSA9IGRldGVybWluZVBvc3NpYmxlU2l6ZXNPZkVsZW1lbnQoXG4gICAgICBlbmRQYWRkaW5nQ29uZmlnLFxuICAgICAgMSxcbiAgICApO1xuICAgIGNvbnN0IGRhdGFMYWJlbFBhZGRpbmdUb3RhbFNpemUgPSBkZXRlcm1pbmVQb3NzaWJsZVNpemVzT2ZFbGVtZW50KFxuICAgICAgZGF0YUxhYmVsUGFkZGluZ0NvbmZpZyxcbiAgICAgIGdldERhdGFMYWJlbFNpemluZ0NvdW50KGRhdGEsIGNvbmZpZykudG90YWwsXG4gICAgKTtcblxuICAgIGxldCBsZWZ0QnVja2V0TGFiZWxBY3R1YWxTaXplID0gbGVmdExhYmVsQ29uZmlnLnRhcmdldDtcbiAgICBpZiAoY2hhcnREYXRhRGlyZWN0aW9uID09PSAnaG9yaXpvbnRhbCcgJiYgZGF0YS50eXBlID09PSAnbGFiZWxlZCcpIHtcbiAgICAgIC8vRm9yIGhvcml6b250YWwgYmFycywgdGhlIHN0YXJ0IHBhZGRpbmcgd2lsbCBzY2FsZSBiYXNlZCBvbiB0aGUgYnVja2V0IGxhYmVsc1xuICAgICAgY29uc3QgbG9uZ2VzdExhYmVsTGVuZ3RoID1cbiAgICAgICAgTWF0aC5tYXgoLi4uZGF0YS54Lm1hcCh4ID0+IHgubGFiZWwubGVuZ3RoKSkgKlxuICAgICAgICAoV0lEVEhfUEVSX0xFVFRFUiAqIChmb250U2l6ZSAvIERFRkFVTFRfRk9OVF9TSVpFKSk7XG4gICAgICBjb25zdCBtaW5MZW5ndGggPSBsZWZ0TGFiZWxDb25maWcubWluXG4gICAgICAgID8gTWF0aC5tYXgobG9uZ2VzdExhYmVsTGVuZ3RoLCBsZWZ0TGFiZWxDb25maWcubWluKVxuICAgICAgICA6IGxvbmdlc3RMYWJlbExlbmd0aDtcbiAgICAgIGxlZnRCdWNrZXRMYWJlbEFjdHVhbFNpemUgPSBsZWZ0TGFiZWxDb25maWcubWF4XG4gICAgICAgID8gTWF0aC5taW4obWluTGVuZ3RoLCBsZWZ0TGFiZWxDb25maWcubWF4KVxuICAgICAgICA6IGxvbmdlc3RMYWJlbExlbmd0aDtcbiAgICB9XG5cbiAgICBsZXQgZml4ZWRTaXplVmFsdWUgPVxuICAgICAgbGVmdEJ1Y2tldExhYmVsQWN0dWFsU2l6ZSArXG4gICAgICBkYXRhTGFiZWxGaXhlZFNpemUgK1xuICAgICAgc3RhcnRQYWRkaW5nVG90YWxTaXplLnRhcmdldCArXG4gICAgICBlbmRQYWRkaW5nVG90YWxTaXplLnRhcmdldCArXG4gICAgICBkYXRhTGFiZWxQYWRkaW5nVG90YWxTaXplLnRhcmdldDtcbiAgICBpZiAoZml4ZWRTaXplVmFsdWUgPiBib3VuZGluZ0RpbWVuc2lvbikge1xuICAgICAgLy9TZWUgaWYgZnVydGhlciB0cnVuY2F0aW5nIHRoZSBsYWJlbCBjYW4gaGVscFxuICAgICAgaWYgKFxuICAgICAgICBsZWZ0TGFiZWxDb25maWcubWluICYmXG4gICAgICAgIGZpeGVkU2l6ZVZhbHVlIC0gYm91bmRpbmdEaW1lbnNpb24gPFxuICAgICAgICAgIGxlZnRCdWNrZXRMYWJlbEFjdHVhbFNpemUgLSBsZWZ0TGFiZWxDb25maWcubWluXG4gICAgICApIHtcbiAgICAgICAgbGVmdEJ1Y2tldExhYmVsQWN0dWFsU2l6ZSA9XG4gICAgICAgICAgbGVmdEJ1Y2tldExhYmVsQWN0dWFsU2l6ZSAtIChmaXhlZFNpemVWYWx1ZSAtIGJvdW5kaW5nRGltZW5zaW9uKTtcbiAgICAgICAgZml4ZWRTaXplVmFsdWUgPVxuICAgICAgICAgIGxlZnRCdWNrZXRMYWJlbEFjdHVhbFNpemUgK1xuICAgICAgICAgIHN0YXJ0UGFkZGluZ1RvdGFsU2l6ZS50YXJnZXQgK1xuICAgICAgICAgIGVuZFBhZGRpbmdUb3RhbFNpemUudGFyZ2V0ICtcbiAgICAgICAgICBkYXRhTGFiZWxQYWRkaW5nVG90YWxTaXplLnRhcmdldDtcbiAgICAgIH0gZWxzZSBpZiAoXG4gICAgICAgIGF4aXNTY2FsZSAhPT0gJ2dyb3cnICYmXG4gICAgICAgIChheGlzU2NhbGUgIT09ICduby1zY2FsZScgfHwgc2NhbGluZ0NvbmZpZy5kYXRhU2NhbGUudHlwZSA9PT0gJ2ZpdCcpXG4gICAgICApIHtcbiAgICAgICAgLy9Hcm93aW5nIGFuZCBub24tZml0dGluZyBkYXRhIGF4ZXMgY2FuIHNjcm9sbCBpbnN0ZWFkXG4gICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gICAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgICAnVGhlIHByb3ZpZGVkIGVsZW1lbnQgc2l6ZXMgbWVhbiB0aGUgY2hhcnQgY2Fubm90IGRpc3BsYXkgYXQgdGhpcyBzbWFsbCBvZiBhIHNpemUnLFxuICAgICAgICApO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIHN0YXJ0UGFkZGluZzogMCxcbiAgICAgICAgICBlbmRQYWRkaW5nOiAwLFxuICAgICAgICAgIGxlZnRCdWNrZXRMYWJlbDogMCxcbiAgICAgICAgICBkYXRhTGFiZWxUZXh0U2l6ZTogMCxcbiAgICAgICAgICBkYXRhTGFiZWxQYWRkaW5nOiAwLFxuICAgICAgICAgIGZvbnRTaXplOiAwLFxuICAgICAgICAgIHNpemVGb3JEYXRhOiAwLFxuICAgICAgICAgIHRvdGFsU2l6ZTogMCxcbiAgICAgICAgICBidWNrZXRMYWJlbFRleHRTaXplOiAwLFxuICAgICAgICAgIHNpemluZ0Vycm9yOiB0cnVlLFxuICAgICAgICB9O1xuICAgICAgfVxuICAgIH1cbiAgICBpZiAoXG4gICAgICBheGlzU2NhbGUgPT09ICdzY2FsZS10by1maXQnIHx8XG4gICAgICBheGlzU2NhbGUgPT09ICdncm93JyB8fFxuICAgICAgYXhpc1NjYWxlID09PSAnc2hyaW5rJyB8fFxuICAgICAgc2NhbGluZ0NvbmZpZy5kYXRhU2NhbGUudHlwZSA9PT0gJ2ZpdCdcbiAgICApIHtcbiAgICAgIC8vQSBncm93aW5nIGRhdGEgYXhpcyBzY3JvbGxzIHJhdGhlciB0aGFuIHNxdWVlemluZyB0aGUgZGF0YSBiZWxvdyBpdHMgbWluaW11bSBzaXplXG4gICAgICBjb25zdCBhdmFpbGFibGVTaXplID1cbiAgICAgICAgYXhpc1NjYWxlID09PSAnZ3JvdydcbiAgICAgICAgICA/IE1hdGgubWF4KFxuICAgICAgICAgICAgICBib3VuZGluZ0RpbWVuc2lvbiAtIGZpeGVkU2l6ZVZhbHVlLFxuICAgICAgICAgICAgICBnZXRNaW5pbXVtR3Jvd25EYXRhU2l6ZShcbiAgICAgICAgICAgICAgICBkYXRhLFxuICAgICAgICAgICAgICAgIGNvbmZpZyxcbiAgICAgICAgICAgICAgICBib3VuZGluZ0RpbWVuc2lvbixcbiAgICAgICAgICAgICAgICBmbG93TGFiZWxTaXplLFxuICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgKVxuICAgICAgICAgIDogYm91bmRpbmdEaW1lbnNpb24gLSBmaXhlZFNpemVWYWx1ZTtcbiAgICAgIGNvbnN0IHNpemVGb3JEYXRhID0gZ2V0Rml0dGVkRGF0YVNpemUoXG4gICAgICAgIGRhdGEsXG4gICAgICAgIGNvbmZpZyxcbiAgICAgICAgYXZhaWxhYmxlU2l6ZSxcbiAgICAgICAgZmxvd0xhYmVsU2l6ZSxcbiAgICAgICk7XG4gICAgICBpZiAoc2l6ZUZvckRhdGEgPT09IG51bGwpIHtcbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICAgICdUaGUgcHJvdmlkZWQgbWluaW11bSBkYXRhIGVsZW1lbnQgc2l6ZSBtZWFucyB0aGUgY2hhcnQgY2Fubm90IGRpc3BsYXkgYXQgdGhpcyBzbWFsbCBvZiBhIHNpemUnLFxuICAgICAgICApO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIHN0YXJ0UGFkZGluZzogMCxcbiAgICAgICAgICBlbmRQYWRkaW5nOiAwLFxuICAgICAgICAgIGxlZnRCdWNrZXRMYWJlbDogMCxcbiAgICAgICAgICBkYXRhTGFiZWxUZXh0U2l6ZTogMCxcbiAgICAgICAgICBkYXRhTGFiZWxQYWRkaW5nOiAwLFxuICAgICAgICAgIGZvbnRTaXplOiAwLFxuICAgICAgICAgIHNpemVGb3JEYXRhOiAwLFxuICAgICAgICAgIHRvdGFsU2l6ZTogMCxcbiAgICAgICAgICBidWNrZXRMYWJlbFRleHRTaXplOiAwLFxuICAgICAgICAgIHNpemluZ0Vycm9yOiB0cnVlLFxuICAgICAgICB9O1xuICAgICAgfVxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgc3RhcnRQYWRkaW5nOiBzdGFydFBhZGRpbmdDb25maWcudGFyZ2V0LFxuICAgICAgICBlbmRQYWRkaW5nOiBlbmRQYWRkaW5nQ29uZmlnLnRhcmdldCxcbiAgICAgICAgbGVmdEJ1Y2tldExhYmVsOiBsZWZ0QnVja2V0TGFiZWxBY3R1YWxTaXplLFxuICAgICAgICBkYXRhTGFiZWxUZXh0U2l6ZSxcbiAgICAgICAgZGF0YUxhYmVsUGFkZGluZzogZGF0YUxhYmVsUGFkZGluZ0NvbmZpZy50YXJnZXQsXG4gICAgICAgIGZvbnRTaXplOiBmb250U2l6ZUNvbmZpZy50YXJnZXQsXG4gICAgICAgIHNpemVGb3JEYXRhLFxuICAgICAgICB0b3RhbFNpemU6IGZpeGVkU2l6ZVZhbHVlICsgYXZhaWxhYmxlU2l6ZSxcbiAgICAgICAgYnVja2V0TGFiZWxUZXh0U2l6ZSxcbiAgICAgIH07XG4gICAgfVxuXG4gICAgY29uc3Qge1xuICAgICAgcHJpbWFyeURhdGFNaW4sXG4gICAgICBwcmltYXJ5RGF0YU1heCxcbiAgICAgIHNjYWxlRG9tYWluTXVsdGlwbGVGb3JNYXgsXG4gICAgICBzY2FsZURvbWFpbk11bHRpcGxlRm9yTmVnLFxuICAgIH0gPSBjYWxjRGF0YVNjYWxpbmdWYWx1ZXMoZGF0YSwgY29uZmlnKTtcblxuICAgIGNvbnN0IGVmZmVjdGl2ZVByaW1hcnlNYXhGb3JTY2FsaW5nID1cbiAgICAgIHByaW1hcnlEYXRhTWF4ICogc2NhbGVEb21haW5NdWx0aXBsZUZvck1heDtcbiAgICBjb25zdCBlZmZlY3RpdmVQcmltYXJ5TWluRm9yU2NhbGluZyA9XG4gICAgICBwcmltYXJ5RGF0YU1pbiA8IDAgPyBwcmltYXJ5RGF0YU1pbiAqIHNjYWxlRG9tYWluTXVsdGlwbGVGb3JOZWcgOiAwO1xuXG4gICAgaWYgKHNjYWxpbmdDb25maWcuZGF0YVNjYWxlLnR5cGUgPT09ICdtYXgnKSB7XG4gICAgICBjb25zdCBkYXRhU2l6ZSA9XG4gICAgICAgIHNjYWxpbmdDb25maWcuZGF0YVNjYWxlLnZhbHVlICpcbiAgICAgICAgKChlZmZlY3RpdmVQcmltYXJ5TWF4Rm9yU2NhbGluZyAtIGVmZmVjdGl2ZVByaW1hcnlNaW5Gb3JTY2FsaW5nKSAvXG4gICAgICAgICAgZWZmZWN0aXZlUHJpbWFyeU1heEZvclNjYWxpbmcpO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgc3RhcnRQYWRkaW5nOiBzdGFydFBhZGRpbmdDb25maWcudGFyZ2V0LFxuICAgICAgICBlbmRQYWRkaW5nOiBlbmRQYWRkaW5nQ29uZmlnLnRhcmdldCxcbiAgICAgICAgbGVmdEJ1Y2tldExhYmVsOiBsZWZ0QnVja2V0TGFiZWxBY3R1YWxTaXplLFxuICAgICAgICBkYXRhTGFiZWxUZXh0U2l6ZSxcbiAgICAgICAgZGF0YUxhYmVsUGFkZGluZzogZGF0YUxhYmVsUGFkZGluZ0NvbmZpZy50YXJnZXQsXG4gICAgICAgIGZvbnRTaXplOiBmb250U2l6ZUNvbmZpZy50YXJnZXQsXG4gICAgICAgIHNpemVGb3JEYXRhOiBkYXRhU2l6ZSxcbiAgICAgICAgdG90YWxTaXplOlxuICAgICAgICAgIGdldFNjYWxlZERhdGFUb3RhbFNpemUoZGF0YSwgY29uZmlnLCBkYXRhU2l6ZSwgZmxvd0xhYmVsU2l6ZSkgK1xuICAgICAgICAgIGZpeGVkU2l6ZVZhbHVlLFxuICAgICAgICBidWNrZXRMYWJlbFRleHRTaXplLFxuICAgICAgfTtcbiAgICB9XG5cbiAgICBjb25zdCBkYXRhU2l6ZSA9XG4gICAgICAoKGVmZmVjdGl2ZVByaW1hcnlNYXhGb3JTY2FsaW5nIC0gZWZmZWN0aXZlUHJpbWFyeU1pbkZvclNjYWxpbmcpIC9cbiAgICAgICAgc2NhbGluZ0NvbmZpZy5kYXRhU2NhbGUucmF0aW8udmFsdWUpICpcbiAgICAgIHNjYWxpbmdDb25maWcuZGF0YVNjYWxlLnJhdGlvLnB4O1xuICAgIHJldHVybiB7XG4gICAgICBzdGFydFBhZGRpbmc6IHN0YXJ0UGFkZGluZ0NvbmZpZy50YXJnZXQsXG4gICAgICBlbmRQYWRkaW5nOiBlbmRQYWRkaW5nQ29uZmlnLnRhcmdldCxcbiAgICAgIGxlZnRCdWNrZXRMYWJlbDogbGVmdEJ1Y2tldExhYmVsQWN0dWFsU2l6ZSxcbiAgICAgIGRhdGFMYWJlbFRleHRTaXplLFxuICAgICAgZGF0YUxhYmVsUGFkZGluZzogZGF0YUxhYmVsUGFkZGluZ0NvbmZpZy50YXJnZXQsXG4gICAgICBmb250U2l6ZTogZm9udFNpemVDb25maWcudGFyZ2V0LFxuICAgICAgc2l6ZUZvckRhdGE6IGRhdGFTaXplLFxuICAgICAgdG90YWxTaXplOlxuICAgICAgICBnZXRTY2FsZWREYXRhVG90YWxTaXplKGRhdGEsIGNvbmZpZywgZGF0YVNpemUsIGZsb3dMYWJlbFNpemUpICtcbiAgICAgICAgZml4ZWRTaXplVmFsdWUsXG4gICAgICBidWNrZXRMYWJlbFRleHRTaXplLFxuICAgIH07XG4gIH1cblxuICAvL1RoZSBsZWFzdCBzcGFjZSBhIGdyb3dpbmcgZGF0YSBheGlzIGdpdmVzIHRoZSBkYXRhOiBhIHBvcnRpb24gb2YgdGhlIHByb3ZpZGVkIHNpemUsIG9uIHRvcCBvZiB0aGUgc3BhY2UgdGhhdFxuICAvLyBlbGVtZW50cyBlbmxhcmdlZCB0byB0aGUgbWluaW11bSBzaXplIG5lZWQgKHNvIHRoZSBkYXRhIHN0YXlzIHByb3BvcnRpb25hbCByYXRoZXIgdGhhbiBhbGwgYmVpbmcgdGhlIG1pbmltdW0pXG4gIGZ1bmN0aW9uIGdldE1pbmltdW1Hcm93bkRhdGFTaXplKFxuICAgIGRhdGE6IFByb2Nlc3NEYXRhLFxuICAgIGNvbmZpZzogQ29uZmlnLFxuICAgIGJvdW5kaW5nRGltZW5zaW9uOiBudW1iZXIsXG4gICAgbGFiZWxTaXplOiBudW1iZXIsXG4gICk6IG51bWJlciB7XG4gICAgY29uc3QgbWluaW11bUVsZW1lbnRzU2l6ZSA9XG4gICAgICBkYXRhLnR5cGUgPT09ICdmbG93LXByb2Nlc3NlZCdcbiAgICAgICAgPyBnZXRNYXhGbG93QnVja2V0U2l6ZShcbiAgICAgICAgICAgIGRhdGEsXG4gICAgICAgICAgICAwLFxuICAgICAgICAgICAgZ2V0TWluaW11bURhdGFFbGVtZW50U2l6ZShjb25maWcpLFxuICAgICAgICAgICAgbGFiZWxTaXplLFxuICAgICAgICAgICkgLSBnZXRGbG93TWlkTGFiZWxTaXplKGRhdGEsIGxhYmVsU2l6ZSlcbiAgICAgICAgOiAwO1xuICAgIHJldHVybiBib3VuZGluZ0RpbWVuc2lvbiAqIEdST1dOX0RBVEFfTUlOSU1VTV9SQVRJTyArIG1pbmltdW1FbGVtZW50c1NpemU7XG4gIH1cblxuICAvL0ZvciBmbG93IGNoYXJ0cywgZmluZHMgdGhlIHNpemUgdGhlIGRhdGEgc2NhbGUgc2hvdWxkIG1hcCB0byBzbyB0aGF0IGV2ZXJ5IGJ1Y2tldCAoaW5jbHVkaW5nIGl0cyBvd24gZGF0YSBsYWJlbHMsXG4gIC8vIGFuZCBhbnkgZWxlbWVudHMgZW5sYXJnZWQgdG8gdGhlIG1pbmltdW0gc2l6ZSkgZml0cyBpbiB0aGUgYXZhaWxhYmxlIHNpemVcbiAgLy9SZXR1cm5zIG51bGwgaWYgdGhlIG1pbmltdW0gc2l6ZXMgYWxvbmUgY2FuJ3QgZml0XG4gIGZ1bmN0aW9uIGdldEZpdHRlZERhdGFTaXplKFxuICAgIGRhdGE6IFByb2Nlc3NEYXRhLFxuICAgIGNvbmZpZzogQ29uZmlnLFxuICAgIGF2YWlsYWJsZVNpemU6IG51bWJlcixcbiAgICBsYWJlbFNpemU6IG51bWJlcixcbiAgKTogbnVtYmVyIHwgbnVsbCB7XG4gICAgaWYgKGRhdGEudHlwZSAhPT0gJ2Zsb3ctcHJvY2Vzc2VkJykge1xuICAgICAgcmV0dXJuIGF2YWlsYWJsZVNpemU7XG4gICAgfVxuICAgIGNvbnN0IGRhdGFNYXggPSBNYXRoLm1heCguLi5kYXRhLngubWFwKHggPT4geC50b3RhbENvdW50KSk7XG4gICAgaWYgKGRhdGFNYXggPD0gMCkge1xuICAgICAgcmV0dXJuIGF2YWlsYWJsZVNpemU7XG4gICAgfVxuICAgIGNvbnN0IG1pbmltdW1TaXplID0gZ2V0TWluaW11bURhdGFFbGVtZW50U2l6ZShjb25maWcpO1xuICAgIGNvbnN0IGJ1Y2tldEF2YWlsYWJsZVNpemUgPVxuICAgICAgYXZhaWxhYmxlU2l6ZSArIGdldEZsb3dNaWRMYWJlbFNpemUoZGF0YSwgbGFiZWxTaXplKTtcbiAgICAvL0NhbGN1bGF0ZSB3aGF0IHRoZSBzaXppbmcgd291bGQgbmVlZCB0byBiZSBmb3IgZWFjaCBpbmRpdmlkdWFsIGNvbHVtbixcbiAgICAvLyAgdGFraW5nIHRoZSB2YWx1ZSB0aGF0IGlzIG1vc3QgcmVzdHJpY3RpdmUuIE5vdCBhcHBseWluZyBtaW5pbXVtIHNpemUgeWV0XG4gICAgY29uc3QgdW5lbmxhcmdlZFJhdGlvID0gTWF0aC5taW4oXG4gICAgICAuLi5kYXRhLnhcbiAgICAgICAgLmZpbHRlcihidWNrZXQgPT4gYnVja2V0LnRvdGFsQ291bnQgPiAwKVxuICAgICAgICAubWFwKFxuICAgICAgICAgIGJ1Y2tldCA9PlxuICAgICAgICAgICAgKGJ1Y2tldEF2YWlsYWJsZVNpemUgLSAoYnVja2V0LnN1YkJ1Y2tldHMubGVuZ3RoIC0gMSkgKiBsYWJlbFNpemUpIC9cbiAgICAgICAgICAgIGJ1Y2tldC50b3RhbENvdW50LFxuICAgICAgICApLFxuICAgICk7XG4gICAgaWYgKFxuICAgICAgbWluaW11bVNpemUgPT09IDAgfHxcbiAgICAgIGdldE1heEZsb3dCdWNrZXRTaXplKGRhdGEsIHVuZW5sYXJnZWRSYXRpbywgbWluaW11bVNpemUsIGxhYmVsU2l6ZSkgPD1cbiAgICAgICAgYnVja2V0QXZhaWxhYmxlU2l6ZVxuICAgICkge1xuICAgICAgcmV0dXJuIHVuZW5sYXJnZWRSYXRpbyAqIGRhdGFNYXg7XG4gICAgfVxuICAgIGlmIChcbiAgICAgIGdldE1heEZsb3dCdWNrZXRTaXplKGRhdGEsIDAsIG1pbmltdW1TaXplLCBsYWJlbFNpemUpID5cbiAgICAgIGJ1Y2tldEF2YWlsYWJsZVNpemVcbiAgICApIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICAvL05vdywgd2UgYXBwbHkgbWluaW11bSBzaXplIHRvIHRoZSBiYXJzIHRvIGNhbGN1bGF0ZSBvdXIgdHJ1ZSByYXRpbyAoZm91bmQgdGhyb3VnaCBiaW5hcnkgc2VhcmNoKVxuICAgIGxldCBsb3cgPSAwO1xuICAgIGxldCBoaWdoID0gdW5lbmxhcmdlZFJhdGlvO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgNTA7IGkrKykge1xuICAgICAgY29uc3QgbWlkID0gKGxvdyArIGhpZ2gpIC8gMjtcbiAgICAgIGlmIChcbiAgICAgICAgZ2V0TWF4Rmxvd0J1Y2tldFNpemUoZGF0YSwgbWlkLCBtaW5pbXVtU2l6ZSwgbGFiZWxTaXplKSA+XG4gICAgICAgIGJ1Y2tldEF2YWlsYWJsZVNpemVcbiAgICAgICkge1xuICAgICAgICBoaWdoID0gbWlkO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbG93ID0gbWlkO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gbG93ICogZGF0YU1heDtcbiAgfVxuXG4gIC8vVGhlIHNpemUgbmVlZGVkIGFsb25nIHRoZSBkYXRhIGF4aXMgYmV5b25kIHRoZSBmaXhlZCBzaXplXG4gIC8vRm9yIGZsb3cgY2hhcnRzLCB0aGlzIGlzIGJhc2VkIG9uIHRoZSB0YWxsZXN0IGJ1Y2tldCAoaW5jbHVkaW5nIGl0cyBvd24gZGF0YSBsYWJlbHMgYW5kIGFueSBlbmxhcmdlZCBlbGVtZW50cyksXG4gIC8vIHJhdGhlciB0aGFuIGFzc3VtaW5nIHRoZSBidWNrZXQgd2l0aCB0aGUgbW9zdCBkYXRhIGFsc28gaGFzIHRoZSBtb3N0IHN1Yi1idWNrZXRzXG4gIGZ1bmN0aW9uIGdldFNjYWxlZERhdGFUb3RhbFNpemUoXG4gICAgZGF0YTogUHJvY2Vzc0RhdGEsXG4gICAgY29uZmlnOiBDb25maWcsXG4gICAgZGF0YVNpemU6IG51bWJlcixcbiAgICBsYWJlbFNpemU6IG51bWJlcixcbiAgKTogbnVtYmVyIHtcbiAgICBpZiAoZGF0YS50eXBlICE9PSAnZmxvdy1wcm9jZXNzZWQnKSB7XG4gICAgICByZXR1cm4gZGF0YVNpemU7XG4gICAgfVxuICAgIGNvbnN0IGRhdGFNYXggPSBNYXRoLm1heCguLi5kYXRhLngubWFwKHggPT4geC50b3RhbENvdW50KSk7XG4gICAgaWYgKGRhdGFNYXggPD0gMCkge1xuICAgICAgcmV0dXJuIGRhdGFTaXplO1xuICAgIH1cbiAgICByZXR1cm4gKFxuICAgICAgZ2V0TWF4Rmxvd0J1Y2tldFNpemUoXG4gICAgICAgIGRhdGEsXG4gICAgICAgIGRhdGFTaXplIC8gZGF0YU1heCxcbiAgICAgICAgZ2V0TWluaW11bURhdGFFbGVtZW50U2l6ZShjb25maWcpLFxuICAgICAgICBsYWJlbFNpemUsXG4gICAgICApIC0gZ2V0Rmxvd01pZExhYmVsU2l6ZShkYXRhLCBsYWJlbFNpemUpXG4gICAgKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGdldERhdGFMYWJlbFNpemUoXG4gICAgZGF0YTogUHJvY2Vzc0RhdGEsXG4gICAgcGlwZVRyYW5zZm9ybTogKCh2YWx1ZTogbnVtYmVyLCBpc1NlY29uZGFyeTogYm9vbGVhbikgPT4gc3RyaW5nKSB8IG51bGwsXG4gICAgZm9udFNpemU6IG51bWJlcixcbiAgKTogeyBob3Jpem9udGFsOiBudW1iZXI7IHZlcnRpY2FsOiBudW1iZXIgfSB7XG4gICAgbGV0IG5vcm1Ib3Jpem9udGFsTWF4TGVuZ3RoID0gMDtcbiAgICBsZXQgbm9ybVN1cHBNYXhMZW5ndGggPSAwO1xuICAgIGlmIChkYXRhLnR5cGUgIT09ICdmbG93LXByb2Nlc3NlZCcgJiYgcGlwZVRyYW5zZm9ybSAhPT0gbnVsbCkge1xuICAgICAgbm9ybUhvcml6b250YWxNYXhMZW5ndGggPSBNYXRoLm1heChcbiAgICAgICAgLi4uZGF0YS55cy5tYXAoKHksIHlJbmRleCkgPT5cbiAgICAgICAgICBNYXRoLm1heChcbiAgICAgICAgICAgIC4uLnkudmFsdWVzLm1hcCgodmFsLCB4SW5kZXgpID0+XG4gICAgICAgICAgICAgIGNoZWNrTGFiZWxMZW5ndGgoXG4gICAgICAgICAgICAgICAgcGlwZVRyYW5zZm9ybShcbiAgICAgICAgICAgICAgICAgIHZhbCxcbiAgICAgICAgICAgICAgICAgIGNoZWNrSWZTZWNvbmRhcnkoZGF0YSwgeUluZGV4LCB4SW5kZXgsIGZhbHNlKSxcbiAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgIGZvbnRTaXplLFxuICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgKSxcbiAgICAgICAgICApLFxuICAgICAgICApLFxuICAgICAgKTtcbiAgICAgIG5vcm1TdXBwTWF4TGVuZ3RoID0gTWF0aC5tYXgoXG4gICAgICAgIC4uLihkYXRhLnN1cHBsZW1lbnRhcnlZcyA/PyBbXSkubWFwKCh5LCB5SW5kZXgpID0+XG4gICAgICAgICAgTWF0aC5tYXgoXG4gICAgICAgICAgICAuLi55LnZhbHVlcy5tYXAoKHZhbCwgeEluZGV4KSA9PlxuICAgICAgICAgICAgICBjaGVja0xhYmVsTGVuZ3RoKFxuICAgICAgICAgICAgICAgIHBpcGVUcmFuc2Zvcm0oXG4gICAgICAgICAgICAgICAgICB2YWwsXG4gICAgICAgICAgICAgICAgICBjaGVja0lmU2Vjb25kYXJ5KGRhdGEsIHlJbmRleCwgeEluZGV4LCB0cnVlKSxcbiAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgIGZvbnRTaXplLFxuICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgKSxcbiAgICAgICAgICApLFxuICAgICAgICApLFxuICAgICAgKTtcbiAgICB9XG4gICAgaWYgKGRhdGEudHlwZSA9PT0gJ2Zsb3ctcHJvY2Vzc2VkJykge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgaG9yaXpvbnRhbDogTWF0aC5tYXgobm9ybUhvcml6b250YWxNYXhMZW5ndGgsIG5vcm1TdXBwTWF4TGVuZ3RoKSxcbiAgICAgICAgdmVydGljYWw6IGZvbnRTaXplICogMixcbiAgICAgIH07XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICBob3Jpem9udGFsOiBNYXRoLm1heChub3JtSG9yaXpvbnRhbE1heExlbmd0aCwgbm9ybVN1cHBNYXhMZW5ndGgpLFxuICAgICAgdmVydGljYWw6IGZvbnRTaXplLFxuICAgIH07XG4gIH1cblxuICBmdW5jdGlvbiBnZXRCdWNrZXRMYWJlbFNpemUoXG4gICAgZGF0YTogUHJvY2Vzc0RhdGEsXG4gICAgZm9udFNpemU6IG51bWJlcixcbiAgICBkYXRlRm9ybWF0OiAoKGRhdGU6IERhdGUpID0+IHN0cmluZykgfCBudWxsLFxuICApIHtcbiAgICBpZiAoZGF0ZUZvcm1hdCAhPT0gbnVsbCkge1xuICAgICAgaWYgKGRhdGEudHlwZSA9PT0gJ2xhYmVsZWQnKSB7XG4gICAgICAgIHJldHVybiBNYXRoLm1heChcbiAgICAgICAgICAuLi5kYXRhLngubWFwKHggPT4gY2hlY2tMYWJlbExlbmd0aCh4LmxhYmVsLCBmb250U2l6ZSkpLFxuICAgICAgICApO1xuICAgICAgfSBlbHNlIGlmIChkYXRhLnR5cGUgPT09ICd0aW1lc2VyaWVzJykge1xuICAgICAgICByZXR1cm4gTWF0aC5tYXgoXG4gICAgICAgICAgLi4uZGF0YS54Lm1hcCh4ID0+XG4gICAgICAgICAgICBjaGVja0xhYmVsTGVuZ3RoKGRhdGVGb3JtYXQobmV3IERhdGUoeCkpLCBmb250U2l6ZSksXG4gICAgICAgICAgKSxcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIDA7XG4gIH1cblxuICBmdW5jdGlvbiBjaGVja0xhYmVsTGVuZ3RoKHZhbHVlOiBzdHJpbmcsIGZvbnRTaXplOiBudW1iZXIpOiBudW1iZXIge1xuICAgIGNvbnN0IHBlcmlvZENvdW50ID0gKHZhbHVlLm1hdGNoKC9cXC4vZykgfHwgW10pLmxlbmd0aDtcbiAgICBjb25zdCBzbGFzaENvdW50ID0gKHZhbHVlLm1hdGNoKC9cXC8vZykgfHwgW10pLmxlbmd0aDtcbiAgICBjb25zdCBmb250U2NhbGVGYWN0b3IgPSBmb250U2l6ZSAvIERFRkFVTFRfRk9OVF9TSVpFO1xuICAgIHJldHVybiAoXG4gICAgICAodmFsdWUubGVuZ3RoIC0gKHBlcmlvZENvdW50ICsgc2xhc2hDb3VudCkpICpcbiAgICAgICAgKFdJRFRIX1BFUl9OVU1CRVIgKiBmb250U2NhbGVGYWN0b3IpICtcbiAgICAgIHBlcmlvZENvdW50ICogKFdJRFRIX1BFUl9QRVJJT0QgKiBmb250U2NhbGVGYWN0b3IpICtcbiAgICAgIHNsYXNoQ291bnQgKiAoV0lEVEhfUEVSX1NMQVNIICogZm9udFNjYWxlRmFjdG9yKVxuICAgICk7XG4gIH1cblxuICBleHBvcnQgZnVuY3Rpb24gaXNCYXJUeXBlKHR5cGU6IENoYXJ0LkNoYXJ0VHlwZSk6IGJvb2xlYW4ge1xuICAgIGlmIChcbiAgICAgIHR5cGUgPT09ICdiYXInIHx8XG4gICAgICB0eXBlID09PSAnaG9yaXpvbnRhbC1iYXInIHx8XG4gICAgICB0eXBlID09PSAnd2F0ZXJmYWxsJyB8fFxuICAgICAgdHlwZSA9PT0gJ2Z1bm5lbCdcbiAgICApIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICAvL09ubHkgYmFyLXR5cGUgYW5kIGZsb3cgY2hhcnRzIGhhdmUgZGlzY3JldGUgZGF0YSBlbGVtZW50cyB0aGF0IHRoZSBtaW5pbXVtIHNpemUgYXBwbGllcyB0b1xuICBmdW5jdGlvbiBnZXRNaW5pbXVtRGF0YUVsZW1lbnRTaXplKGNvbmZpZzogQ29uZmlnKTogbnVtYmVyIHtcbiAgICBpZiAoXG4gICAgICBjb25maWcudHlwZSA9PT0gJ2RvbnV0JyB8fFxuICAgICAgY29uZmlnLnR5cGUgPT09ICdsaW5lJyB8fFxuICAgICAgY29uZmlnLnR5cGUgPT09ICdhcmVhJ1xuICAgICkge1xuICAgICAgcmV0dXJuIDA7XG4gICAgfVxuICAgIHJldHVybiBjb25maWcuc2NhbGluZ0NvbmZpZz8uZGF0YVNjYWxlPy5taW5pbXVtRGF0YUVsZW1lbnRTaXplID8/IDA7XG4gIH1cblxuICAvL0FueSBkYXRhIGVsZW1lbnQgd2l0aCBhIG5vbi16ZXJvIHZhbHVlIGlzIGtlcHQgYXQgb3IgYWJvdmUgdGhlIG1pbmltdW0gc2l6ZVxuICBmdW5jdGlvbiBhcHBseU1pbmltdW1EYXRhRWxlbWVudFNpemUoXG4gICAgc2l6ZTogbnVtYmVyLFxuICAgIHZhbHVlOiBudW1iZXIsXG4gICAgbWluaW11bVNpemU6IG51bWJlcixcbiAgKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdmFsdWUgIT09IDAgPyBNYXRoLm1heChzaXplLCBtaW5pbXVtU2l6ZSkgOiBzaXplO1xuICB9XG5cbiAgZnVuY3Rpb24gZ2V0Rmxvd1N1YkJ1Y2tldFNpemVzKFxuICAgIHN1YkJ1Y2tldDogRmxvd1N1YkJ1Y2tldCxcbiAgICB2YWx1ZVRvU2l6ZTogKHZhbHVlOiBudW1iZXIpID0+IG51bWJlcixcbiAgICBtaW5pbXVtU2l6ZTogbnVtYmVyLFxuICApOiB7XG4gICAgdG90YWxTaXplOiBudW1iZXI7XG4gICAgY29udGludWluZ1NpemU6IG51bWJlcjtcbiAgICBjb25uZWN0aW9uU2l6ZXM6IG51bWJlcltdO1xuICB9IHtcbiAgICBjb25zdCBjb25uZWN0aW9uU2l6ZXMgPSBzdWJCdWNrZXQuY29ubmVjdGlvbnMubWFwKGNvbm5lY3Rpb24gPT5cbiAgICAgIGFwcGx5TWluaW11bURhdGFFbGVtZW50U2l6ZShcbiAgICAgICAgdmFsdWVUb1NpemUoY29ubmVjdGlvbi5jb3VudCksXG4gICAgICAgIGNvbm5lY3Rpb24uY291bnQsXG4gICAgICAgIG1pbmltdW1TaXplLFxuICAgICAgKSxcbiAgICApO1xuICAgIGNvbnN0IHN1bVNpemVzID0gKGRpcmVjdGlvbjogRmxvd0Nvbm5lY3Rpb25bJ2RpcmVjdGlvbiddKTogbnVtYmVyID0+XG4gICAgICBzdW0oXG4gICAgICAgIGNvbm5lY3Rpb25TaXplcy5maWx0ZXIoXG4gICAgICAgICAgKF8sIGkpID0+IHN1YkJ1Y2tldC5jb25uZWN0aW9uc1tpXS5kaXJlY3Rpb24gPT09IGRpcmVjdGlvbixcbiAgICAgICAgKSxcbiAgICAgICk7XG4gICAgY29uc3QgY29udGludWluZ1NpemUgPSBzdW1TaXplcygnZm9yd2FyZCcpO1xuICAgIGNvbnN0IGJhY2t3YXJkU2l6ZSA9IHN1bVNpemVzKCdiYWNrd2FyZCcpO1xuICAgIGNvbnN0IG5vbkNvbnRpbnVpbmdDb3VudCA9XG4gICAgICBzdWJCdWNrZXQuY291bnQgLVxuICAgICAgc3VtKFxuICAgICAgICBzdWJCdWNrZXQuY29ubmVjdGlvbnNcbiAgICAgICAgICAuZmlsdGVyKGNvbm5lY3Rpb24gPT4gY29ubmVjdGlvbi5kaXJlY3Rpb24gPT09ICdmb3J3YXJkJylcbiAgICAgICAgICAubWFwKGNvbm5lY3Rpb24gPT4gY29ubmVjdGlvbi5jb3VudCksXG4gICAgICApO1xuICAgIC8vVGhlIHN1Yi1idWNrZXQgbXVzdCBiZSBiaWcgZW5vdWdoIHRvIGhvbGQgYWxsIG9mIGl0cyAocG9zc2libHkgZW5sYXJnZWQpIGNvbm5lY3Rpb25zIG9uIGVpdGhlciBzaWRlXG4gICAgY29uc3QgdG90YWxTaXplID0gTWF0aC5tYXgoXG4gICAgICBhcHBseU1pbmltdW1EYXRhRWxlbWVudFNpemUoXG4gICAgICAgIHZhbHVlVG9TaXplKHN1YkJ1Y2tldC5jb3VudCksXG4gICAgICAgIHN1YkJ1Y2tldC5jb3VudCxcbiAgICAgICAgbWluaW11bVNpemUsXG4gICAgICApLFxuICAgICAgY29udGludWluZ1NpemUgK1xuICAgICAgICBhcHBseU1pbmltdW1EYXRhRWxlbWVudFNpemUoXG4gICAgICAgICAgdmFsdWVUb1NpemUobm9uQ29udGludWluZ0NvdW50KSxcbiAgICAgICAgICBub25Db250aW51aW5nQ291bnQsXG4gICAgICAgICAgbWluaW11bVNpemUsXG4gICAgICAgICksXG4gICAgICBiYWNrd2FyZFNpemUsXG4gICAgKTtcbiAgICAvL0V2ZXJ5IHVuaXQgaW4gYSBzdWItYnVja2V0IGFycml2ZXMgdGhyb3VnaCBpdHMgYmFja3dhcmQgY29ubmVjdGlvbnMsIHNvIHRoZXkncmUgc3RyZXRjaGVkIHRvIGZpbGwgdGhlXG4gICAgLy8gc3ViLWJ1Y2tldCB3aGVuIGl0IGhhcyBiZWVuIGVubGFyZ2VkIGJleW9uZCB0aGVtXG4gICAgcmV0dXJuIHtcbiAgICAgIHRvdGFsU2l6ZSxcbiAgICAgIGNvbnRpbnVpbmdTaXplLFxuICAgICAgY29ubmVjdGlvblNpemVzOiBjb25uZWN0aW9uU2l6ZXMubWFwKChzaXplLCBpKSA9PlxuICAgICAgICBzdWJCdWNrZXQuY29ubmVjdGlvbnNbaV0uZGlyZWN0aW9uID09PSAnYmFja3dhcmQnICYmIGJhY2t3YXJkU2l6ZSA+IDBcbiAgICAgICAgICA/IChzaXplICogdG90YWxTaXplKSAvIGJhY2t3YXJkU2l6ZVxuICAgICAgICAgIDogc2l6ZSxcbiAgICAgICksXG4gICAgfTtcbiAgfVxuXG4gIC8vVGhlIHNpemUgb2YgdGhlIHRhbGxlc3QgZmxvdyBidWNrZXQgZm9yIHRoZSBnaXZlbiBzY2FsaW5nIHJhdGlvLCBpbmNsdWRpbmcgdGhlIGRhdGEgbGFiZWxzIGJldHdlZW4gaXRzIHN1Yi1idWNrZXRzXG4gIC8vICBUaGUgbGFiZWwgYWJvdmUgdGhlIGZpcnN0IHN1Yi1idWNrZXQgaXMgZXhjbHVkZWQsIHNpbmNlIGl0J3MgcGFydCBvZiB0aGUgdG9wIG9mZnNldFxuICBmdW5jdGlvbiBnZXRNYXhGbG93QnVja2V0U2l6ZShcbiAgICBkYXRhOiBQcm9jZXNzZWRGbG93RGF0YSxcbiAgICBweFBlclZhbHVlOiBudW1iZXIsXG4gICAgbWluaW11bVNpemU6IG51bWJlcixcbiAgICBsYWJlbFNpemU6IG51bWJlcixcbiAgKTogbnVtYmVyIHtcbiAgICByZXR1cm4gTWF0aC5tYXgoXG4gICAgICAuLi5kYXRhLngubWFwKFxuICAgICAgICBidWNrZXQgPT5cbiAgICAgICAgICBzdW0oXG4gICAgICAgICAgICBidWNrZXQuc3ViQnVja2V0cy5tYXAoXG4gICAgICAgICAgICAgIHN1YkJ1Y2tldCA9PlxuICAgICAgICAgICAgICAgIGdldEZsb3dTdWJCdWNrZXRTaXplcyhcbiAgICAgICAgICAgICAgICAgIHN1YkJ1Y2tldCxcbiAgICAgICAgICAgICAgICAgIHZhbHVlID0+IHZhbHVlICogcHhQZXJWYWx1ZSxcbiAgICAgICAgICAgICAgICAgIG1pbmltdW1TaXplLFxuICAgICAgICAgICAgICAgICkudG90YWxTaXplLFxuICAgICAgICAgICAgKSxcbiAgICAgICAgICApICtcbiAgICAgICAgICAoYnVja2V0LnN1YkJ1Y2tldHMubGVuZ3RoIC0gMSkgKiBsYWJlbFNpemUsXG4gICAgICApLFxuICAgICk7XG4gIH1cblxuICAvL1RoZSBmaXhlZCBzaXplIHJlc2VydmVzIHJvb20gZm9yIHRoZSBsYWJlbHMgYmV0d2VlbiBzdWItYnVja2V0cyBhcyBpZiBldmVyeSBidWNrZXQgaGFkIGFzIG1hbnkgc3ViLWJ1Y2tldHMgYXMgdGhlXG4gIC8vIGJ1Y2tldCB3aXRoIHRoZSBtb3N0LCBzbyB0aGlzIGlzIHRoZSBwb3J0aW9uIG9mIHRoZSBmaXhlZCBzaXplIHRoYXQgZWFjaCBidWNrZXQgY2FuIGluc3RlYWQgdXNlIGJhc2VkIG9uIGl0cyBvd24gbGFiZWxzXG4gIGZ1bmN0aW9uIGdldEZsb3dNaWRMYWJlbFNpemUoXG4gICAgZGF0YTogUHJvY2Vzc2VkRmxvd0RhdGEsXG4gICAgbGFiZWxTaXplOiBudW1iZXIsXG4gICk6IG51bWJlciB7XG4gICAgcmV0dXJuIChcbiAgICAgIChNYXRoLm1heCguLi5kYXRhLngubWFwKGJ1Y2tldCA9PiBidWNrZXQuc3ViQnVja2V0cy5sZW5ndGgpKSAtIDEpICpcbiAgICAgIGxhYmVsU2l6ZVxuICAgICk7XG4gIH1cblxuICBmdW5jdGlvbiBpc1N0YWNrZWREYXRhKGNvbmZpZzogQ29uZmlnKTogYm9vbGVhbiB7XG4gICAgaWYgKGNvbmZpZy50eXBlID09PSAnYmFyJyB8fCBjb25maWcudHlwZSA9PT0gJ2hvcml6b250YWwtYmFyJykge1xuICAgICAgaWYgKGNvbmZpZy5ncm91cGluZ1R5cGUgPT09ICdzdGFja2VkJykge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKGNvbmZpZy50eXBlID09PSAnYXJlYScgfHwgY29uZmlnLnR5cGUgPT09ICd3YXRlcmZhbGwnKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgZnVuY3Rpb24gaXNDbHVzdGVyZWREYXRhKFxuICAgIGRhdGE6IE5vbkZsb3dEYXRhLFxuICAgIGNvbmZpZzogQ29uZmlnLFxuICAgIGluY2x1ZGVTdXBwbGVtZW50YXJ5OiBib29sZWFuLFxuICApOiBib29sZWFuIHtcbiAgICAvL0l0IHZhcmllcyB3aGV0aGVyIHdlIHdhbnQgdG8gaW5jbHVkZSBzdXBwbGVtZW50YXJ5IGRhdGEgaW4gdGhpcyBjaGVja1xuICAgIGlmIChoYXNTdXBwbGVtZW50YXJ5RGF0YShkYXRhKSAmJiBpbmNsdWRlU3VwcGxlbWVudGFyeSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIGlmIChcbiAgICAgIChjb25maWcudHlwZSA9PT0gJ2JhcicgfHwgY29uZmlnLnR5cGUgPT09ICdob3Jpem9udGFsLWJhcicpICYmXG4gICAgICBjb25maWcuZ3JvdXBpbmdUeXBlID09PSAnY2x1c3RlcmVkJ1xuICAgICkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIGlmIChjb25maWcudHlwZSA9PT0gJ2Z1bm5lbCcpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICAvL0luIHNvbWUgY2FzZXMsIHRoZSBkaXN0aW5jdGlvbiBiZXR3ZWVuIGNsdXN0ZXJlZCBhbmQgc3RhY2tlZCBkb2Vzbid0IG1hdHRlclxuICBmdW5jdGlvbiBpc0dyb3VwaW5nVHlwZUV4Y2VwdGlvbihkYXRhOiBOb25GbG93RGF0YSwgY29uZmlnOiBDb25maWcpOiBib29sZWFuIHtcbiAgICBpZiAoZGF0YS55cy5sZW5ndGggPT09IDEpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICAvL0NoZWNraW5nIGZvciBhICdtZXRyaWMnIGNoYXJ0cywgd2hpY2ggaXMgYSBzcGVjaWFsIGNhc2UgZm9yIGhvcml6b250YWwgYmFyIGNoYXJ0cyxcbiAgICAvLyB3aGVyZSBlYWNoIHNlcmllcyBpcyBhbHNvIGEgYnVja2V0IChhbmQgdmljZSB2ZXJzYSlcbiAgICBpZiAoY29uZmlnLnR5cGUgPT09ICdob3Jpem9udGFsLWJhcicpIHtcbiAgICAgIGlmIChcbiAgICAgICAgZGF0YS54Lmxlbmd0aCA9PT0gZGF0YS55cy5sZW5ndGggJiZcbiAgICAgICAgZGF0YS55cy5sZW5ndGggPT09XG4gICAgICAgICAgZGF0YS55cy5maWx0ZXIoeSA9PiB5LnZhbHVlcy5maWx0ZXIodmFsID0+IHZhbCAhPT0gMCkubGVuZ3RoID09PSAxKVxuICAgICAgICAgICAgLmxlbmd0aFxuICAgICAgKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBmdW5jdGlvbiBoYXNTdXBwbGVtZW50YXJ5RGF0YShkYXRhOiBJbnB1dERhdGEpOiBkYXRhIGlzIE5vbkZsb3dEYXRhICYge1xuICAgIHN1cHBsZW1lbnRhcnlZczogTm9uTnVsbGFibGU8Tm9uRmxvd0RhdGFbJ3N1cHBsZW1lbnRhcnlZcyddPjtcbiAgfSB7XG4gICAgaWYgKGRhdGEudHlwZSA9PT0gJ2Zsb3cnKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIGlmIChkYXRhLnN1cHBsZW1lbnRhcnlZcyAmJiBkYXRhLnN1cHBsZW1lbnRhcnlZcy5sZW5ndGggPiAwKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgZnVuY3Rpb24gZ2V0RWxlbWVudFNjYWxpbmdJbmZvKFxuICAgIGVsZW1lbnRTY2FsZXM6IFBhcnRpYWxFbGVtZW50U2NhbGluZ0NvbmZpZyB8IHVuZGVmaW5lZCxcbiAgICBkZWZhdWx0U2NhbGluZ0NvbmZpZzogRnVsbEVsZW1lbnRTY2FsaW5nQ29uZmlnLFxuICAgIGVsZW1lbnQ6IENoYXJ0U2NhbGVFbGVtZW50LFxuICApOiBFbGVtZW50U2NhbGluZ0NvbmZpZ3VyYXRpb24ge1xuICAgIGNvbnN0IGRlZmF1bHRFbGVtZW50Q29uZmlnID0gZGVmYXVsdFNjYWxpbmdDb25maWdbZWxlbWVudF07XG4gICAgbGV0IGlucHV0Q29uZmlnOiBFbGVtZW50U2NhbGluZ0NvbmZpZ3VyYXRpb24gfCBudWxsO1xuICAgIGlmIChlbGVtZW50U2NhbGVzKSB7XG4gICAgICBjb25zdCBwb3NzaWJsZUNvbmZpZyA9IGVsZW1lbnRTY2FsZXNbZWxlbWVudF07XG4gICAgICBpZiAocG9zc2libGVDb25maWcpIHtcbiAgICAgICAgaW5wdXRDb25maWcgPSBwb3NzaWJsZUNvbmZpZztcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlucHV0Q29uZmlnID0gbnVsbDtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgaW5wdXRDb25maWcgPSBudWxsO1xuICAgIH1cblxuICAgIGlmIChpbnB1dENvbmZpZyAhPT0gbnVsbCkge1xuICAgICAgY29uc3QgcmV0dXJuQ29uZmlnID0gaW5wdXRDb25maWcgYXMgRWxlbWVudFNjYWxpbmdDb25maWd1cmF0aW9uO1xuICAgICAgcmV0dXJuIHJldHVybkNvbmZpZztcbiAgICB9XG4gICAgaWYgKGRlZmF1bHRFbGVtZW50Q29uZmlnLnRhcmdldCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBjb25zdCByZXR1cm5Db25maWcgPSBkZWZhdWx0RWxlbWVudENvbmZpZyBhcyBFbGVtZW50U2NhbGluZ0NvbmZpZ3VyYXRpb247XG4gICAgICByZXR1cm4gcmV0dXJuQ29uZmlnO1xuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgdGFyZ2V0OiAwLFxuICAgIH07XG4gIH1cblxuICBmdW5jdGlvbiBkZXRlcm1pbmVQb3NzaWJsZVNpemVzT2ZFbGVtZW50KFxuICAgIGVsZW1lbnRDb25maWc6IEVsZW1lbnRTY2FsaW5nQ29uZmlndXJhdGlvbixcbiAgICBlbGVtZW50Q291bnQ6IG51bWJlcixcbiAgKTogeyBtaW46IG51bWJlcjsgbWF4OiBudW1iZXI7IHRhcmdldDogbnVtYmVyIH0ge1xuICAgIGNvbnN0IGluZE1pbiA9IGVsZW1lbnRDb25maWcubWluICE9PSB1bmRlZmluZWQgPyBlbGVtZW50Q29uZmlnLm1pbiA6IDA7XG4gICAgY29uc3QgaW5kTWF4ID0gZWxlbWVudENvbmZpZy5tYXggIT09IHVuZGVmaW5lZCA/IGVsZW1lbnRDb25maWcubWF4IDogMDtcbiAgICBjb25zdCBpbmRUYXJnZXQgPSBlbGVtZW50Q29uZmlnLnRhcmdldDtcbiAgICByZXR1cm4ge1xuICAgICAgbWluOiBpbmRNaW4gKiBlbGVtZW50Q291bnQsXG4gICAgICBtYXg6IGluZE1heCAqIGVsZW1lbnRDb3VudCxcbiAgICAgIHRhcmdldDogaW5kVGFyZ2V0ICogZWxlbWVudENvdW50LFxuICAgIH07XG4gIH1cblxuICBmdW5jdGlvbiBkZXRlcm1pbmVUb3RhbFNjYWxlZFNpemVPZkVsZW1lbnQoXG4gICAgZWxlbWVudENvbmZpZzogRWxlbWVudFNjYWxpbmdDb25maWd1cmF0aW9uLFxuICAgIGVsZW1lbnRDb3VudDogbnVtYmVyLFxuICAgIHNjYWxlVmFsdWU6IG51bWJlcixcbiAgKTogbnVtYmVyIHtcbiAgICBjb25zdCBzY2FsZWRWYWwgPSBnZXRTY2FsZWRFbGVtZW50U2l6ZShlbGVtZW50Q29uZmlnLCBzY2FsZVZhbHVlKTtcbiAgICByZXR1cm4gc2NhbGVkVmFsICogZWxlbWVudENvdW50O1xuICB9XG5cbiAgZnVuY3Rpb24gZ2V0U2NhbGVkRWxlbWVudFNpemUoXG4gICAgZWxlbWVudENvbmZpZzogRWxlbWVudFNjYWxpbmdDb25maWd1cmF0aW9uLFxuICAgIHNjYWxlVmFsdWU6IG51bWJlcixcbiAgKTogbnVtYmVyIHtcbiAgICBjb25zdCBzY2FsZWRUYXJnZXQgPSBlbGVtZW50Q29uZmlnLnRhcmdldCAqIHNjYWxlVmFsdWU7XG4gICAgaWYgKHNjYWxlVmFsdWUgPCAxKSB7XG4gICAgICBpZiAoZWxlbWVudENvbmZpZy5taW4gJiYgZWxlbWVudENvbmZpZy5taW4gPiBzY2FsZWRUYXJnZXQpIHtcbiAgICAgICAgcmV0dXJuIGVsZW1lbnRDb25maWcubWluO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHNjYWxlZFRhcmdldDtcbiAgICB9XG4gICAgaWYgKHNjYWxlVmFsdWUgPiAxKSB7XG4gICAgICBpZiAoZWxlbWVudENvbmZpZy5tYXggJiYgZWxlbWVudENvbmZpZy5tYXggPCBzY2FsZWRUYXJnZXQpIHtcbiAgICAgICAgcmV0dXJuIGVsZW1lbnRDb25maWcubWF4O1xuICAgICAgfVxuICAgICAgcmV0dXJuIHNjYWxlZFRhcmdldDtcbiAgICB9XG4gICAgcmV0dXJuIHNjYWxlZFRhcmdldDtcbiAgfVxuXG4gIHR5cGUgRWxlbWVudFNjYWxlQ2hlY2tJbmZvID0ge1xuICAgIGNvbmZpZzogRWxlbWVudFNjYWxpbmdDb25maWd1cmF0aW9uO1xuICAgIG1pblNjYWxlRmFjdG9yPzogbnVtYmVyO1xuICAgIG1heFNjYWxlRmFjdG9yPzogbnVtYmVyO1xuICAgIGVsZW1lbnRDb3VudDogbnVtYmVyO1xuICB9O1xuXG4gIGZ1bmN0aW9uIGdldENoZWNraW5nSW5mb0ZvckVsZW1lbnRDb25maWcoXG4gICAgY29uZmlnOiBFbGVtZW50U2NhbGluZ0NvbmZpZ3VyYXRpb24sXG4gICAgZWxlbWVudENvdW50OiBudW1iZXIsXG4gICk6IEVsZW1lbnRTY2FsZUNoZWNrSW5mbyB7XG4gICAgbGV0IG1pblNjYWxlRmFjdG9yOiBudW1iZXIgfCB1bmRlZmluZWQgPSB1bmRlZmluZWQ7XG4gICAgaWYgKGNvbmZpZy5taW4pIHtcbiAgICAgIG1pblNjYWxlRmFjdG9yID1cbiAgICAgICAgY29uZmlnLnRhcmdldCAhPT0gMCA/IGNvbmZpZy5taW4gLyBjb25maWcudGFyZ2V0IDogdW5kZWZpbmVkO1xuICAgIH1cbiAgICBsZXQgbWF4U2NhbGVGYWN0b3I6IG51bWJlciB8IHVuZGVmaW5lZCA9IHVuZGVmaW5lZDtcbiAgICBpZiAoY29uZmlnLm1heCkge1xuICAgICAgbWF4U2NhbGVGYWN0b3IgPVxuICAgICAgICBjb25maWcudGFyZ2V0ICE9PSAwID8gY29uZmlnLm1heCAvIGNvbmZpZy50YXJnZXQgOiB1bmRlZmluZWQ7XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICBjb25maWcsXG4gICAgICBtaW5TY2FsZUZhY3RvcixcbiAgICAgIG1heFNjYWxlRmFjdG9yLFxuICAgICAgZWxlbWVudENvdW50LFxuICAgIH07XG4gIH1cblxuICBmdW5jdGlvbiBnZXRTdW1Gb3JTY2FsZVZhbHVlKFxuICAgIGNoZWNrSW5mb3M6IEVsZW1lbnRTY2FsZUNoZWNrSW5mb1tdLFxuICAgIHNjYWxlVmFsdWU6IG51bWJlcixcbiAgKTogbnVtYmVyIHtcbiAgICBsZXQgc3VtID0gMDtcbiAgICBmb3IgKGNvbnN0IGNoZWNrIG9mIGNoZWNrSW5mb3MpIHtcbiAgICAgIHN1bSArPSBkZXRlcm1pbmVUb3RhbFNjYWxlZFNpemVPZkVsZW1lbnQoXG4gICAgICAgIGNoZWNrLmNvbmZpZyxcbiAgICAgICAgY2hlY2suZWxlbWVudENvdW50LFxuICAgICAgICBzY2FsZVZhbHVlLFxuICAgICAgKTtcbiAgICB9XG4gICAgcmV0dXJuIHN1bTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGdldERhdGFMYWJlbFNpemluZ0NvdW50KFxuICAgIGRhdGE6IFByb2Nlc3NEYXRhLFxuICAgIGNvbmZpZzogQ29uZmlnLFxuICApOiB7IHN0YXJ0OiBudW1iZXI7IGVuZDogbnVtYmVyOyB0b3RhbDogbnVtYmVyIH0ge1xuICAgIGlmIChjb25maWcuc2hvd0RhdGFMYWJlbHMgIT09IHRydWUpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHN0YXJ0OiAwLFxuICAgICAgICBlbmQ6IDAsXG4gICAgICAgIHRvdGFsOiAwLFxuICAgICAgfTtcbiAgICB9XG4gICAgLy9EYXRhIGxhYmVscyBhcmUgYWx3YXlzIHNob3duIGFib3ZlIHRoZSBkYXRhIGZvciBhbGwgYnV0IHRoZXNlIDMgdHlwZXNcbiAgICBpZiAoXG4gICAgICBjb25maWcudHlwZSAhPT0gJ2JhcicgJiZcbiAgICAgIGNvbmZpZy50eXBlICE9PSAnaG9yaXpvbnRhbC1iYXInICYmXG4gICAgICBjb25maWcudHlwZSAhPT0gJ3dhdGVyZmFsbCcgJiZcbiAgICAgIGNvbmZpZy50eXBlICE9PSAnZmxvdydcbiAgICApIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHN0YXJ0OiAxLFxuICAgICAgICBlbmQ6IDAsXG4gICAgICAgIHRvdGFsOiAxLFxuICAgICAgfTtcbiAgICB9XG4gICAgbGV0IHN0YXJ0Q291bnQgPSAwO1xuICAgIGxldCBtaWRDb3VudCA9IDA7XG4gICAgbGV0IGVuZENvdW50ID0gMDtcbiAgICBpZiAoZGF0YS50eXBlICE9PSAnZmxvdy1wcm9jZXNzZWQnKSB7XG4gICAgICBpZiAoZGF0YS55cy5maW5kKHkgPT4geS52YWx1ZXMuZmluZCh2YWwgPT4gdmFsID49IDApKSkge1xuICAgICAgICBpZiAoY29uZmlnLnR5cGUgPT09ICdob3Jpem9udGFsLWJhcicpIHtcbiAgICAgICAgICBlbmRDb3VudCArPSAxO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHN0YXJ0Q291bnQgKz0gMTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKGRhdGEueXMuZmluZCh5ID0+IHkudmFsdWVzLmZpbmQodmFsID0+IHZhbCA8IDApKSkge1xuICAgICAgICBpZiAoY29uZmlnLnR5cGUgPT09ICdob3Jpem9udGFsLWJhcicpIHtcbiAgICAgICAgICBzdGFydENvdW50ICs9IDE7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgZW5kQ291bnQgKz0gMTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBzdGFydENvdW50ID0gMTtcbiAgICAgIG1pZENvdW50ID0gTWF0aC5tYXgoLi4uZGF0YS54Lm1hcCh4ID0+IHguc3ViQnVja2V0cy5sZW5ndGgpKSAtIDE7XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICBzdGFydDogc3RhcnRDb3VudCxcbiAgICAgIGVuZDogZW5kQ291bnQsXG4gICAgICB0b3RhbDogc3RhcnRDb3VudCArIG1pZENvdW50ICsgZW5kQ291bnQsXG4gICAgfTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGdldElmSG92ZXJPdXRPZkJvdW5kcyhcbiAgICAvL1Bvc2l0aW9uIG5vdCBhY2NvdW50aW5nIGZvciBzY3JvbGxpbmdcbiAgICByZWxQb3NYOiBudW1iZXIsXG4gICAgcmVsUG9zWTogbnVtYmVyLFxuICAgIC8vUG9zaXRpb24gYWNjb3VudGluZyBmb3Igc2Nyb2xsaW5nXG4gICAgcmVhbFBvc1g6IG51bWJlcixcbiAgICByZWFsUG9zWTogbnVtYmVyLFxuICAgIGNoYXJ0U2l6aW5nVmFsdWVzOiBGdWxsQ2hhcnRTY2FsZVZhbHVlcyB8IG51bGwsXG4gICAgZGltZW5zaW9uczogRGltZW5zaW9ucyxcbiAgKTogYm9vbGVhbiB7XG4gICAgLy9DaGVjayBpZiB3ZSdyZSBvbiB0b3Agb2Ygb25lIG9mIHRoZSBzY3JvbGxiYXJzXG4gICAgaWYgKHJlbFBvc1ggPiBkaW1lbnNpb25zLndpZHRoIHx8IHJlbFBvc1kgPiBkaW1lbnNpb25zLmhlaWdodCkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIGlmIChjaGFydFNpemluZ1ZhbHVlcyA9PT0gbnVsbCkge1xuICAgICAgLy9JZiBjaGFydFNpemluZ1ZhbHVlcyBhcmVuJ3QgcHJvdmlkZWQsIG5vIG1vcmUgY2hlY2tzXG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIC8vQ2hlY2sgaWYgd2UncmUgaW4gb25lIG9mIHRoZSBwYWRkaW5nIGFyZWFzXG4gICAgaWYgKFxuICAgICAgcmVhbFBvc1ggPCBjaGFydFNpemluZ1ZhbHVlcy5sZWZ0UGFkZGluZyB8fFxuICAgICAgcmVhbFBvc1ggPlxuICAgICAgICBjaGFydFNpemluZ1ZhbHVlcy50b3RhbFdpZHRoIC0gY2hhcnRTaXppbmdWYWx1ZXMucmlnaHRQYWRkaW5nIHx8XG4gICAgICByZWFsUG9zWSA8IGNoYXJ0U2l6aW5nVmFsdWVzLnRvcFBhZGRpbmcgfHxcbiAgICAgIHJlYWxQb3NZID4gY2hhcnRTaXppbmdWYWx1ZXMudG90YWxIZWlnaHQgLSBjaGFydFNpemluZ1ZhbHVlcy5ib3R0b21QYWRkaW5nXG4gICAgKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgZnVuY3Rpb24gZ2V0Q2hhcnREYXRhRGlyZWN0aW9uKGNvbmZpZzogQ29uZmlnKTogQ2hhcnREYXRhRGlyZWN0aW9uIHtcbiAgICBpZiAoY29uZmlnLnR5cGUgPT09ICdob3Jpem9udGFsLWJhcicpIHtcbiAgICAgIHJldHVybiAnaG9yaXpvbnRhbCc7XG4gICAgfVxuICAgIHJldHVybiAndmVydGljYWwnO1xuICB9XG5cbiAgZnVuY3Rpb24gY29tYmluZVNjYWxpbmdJbmZvKFxuICAgIGNvbmZpZzogQ29uZmlnV2l0aEZ1bGxTY2FsaW5nLFxuICAgIGRlZmF1bHRDb25maWc6IERlZmF1bHRTY2FsaW5nQ29uZmlnLFxuICApOiBOb25FbGVtZW50U2NhbGluZ0NvbmZpZyB7XG4gICAgY29uc3QgcHJvdmlkZWRTY2FsaW5nQ29uZmlnID0gY29uZmlnLnNjYWxpbmdDb25maWc7XG4gICAgY29uc3QgY2hhcnREYXRhRGlyZWN0aW9uID0gZ2V0Q2hhcnREYXRhRGlyZWN0aW9uKGNvbmZpZyk7XG5cbiAgICAvL0lmIHRoZSB1c2VyIHByb3ZpZGVzIGEgZGF0YSBzY2FsZSwgd2UgZG9uJ3Qgd2FudCB0byBvdmVycmlkZSB0aGF0IHVubGVzcyB0aGV5IGFsc28gcHJvdmlkZWQgYSBzcGVjaWZpYyBzY2FsZSBmb3IgdGhlIGNvcnJlc3BvbmRpbmcgYXhpc1xuICAgIGNvbnN0IGRhdGFTY2FsZSA9XG4gICAgICBwcm92aWRlZFNjYWxpbmdDb25maWcgJiYgcHJvdmlkZWRTY2FsaW5nQ29uZmlnLmRhdGFTY2FsZVxuICAgICAgICA/IHByb3ZpZGVkU2NhbGluZ0NvbmZpZy5kYXRhU2NhbGVcbiAgICAgICAgOiBkZWZhdWx0Q29uZmlnLm5vbkVsZW1lbnRTY2FsZXMuZGF0YVNjYWxlO1xuICAgIGxldCB2ZXJ0aWNhbEF4aXNTY2FsZSA9IHByb3ZpZGVkU2NhbGluZ0NvbmZpZz8udmVydGljYWxBeGlzU2NhbGU7XG4gICAgaWYgKHZlcnRpY2FsQXhpc1NjYWxlID09PSB1bmRlZmluZWQpIHtcbiAgICAgIGlmIChjaGFydERhdGFEaXJlY3Rpb24gPT09ICdob3Jpem9udGFsJyB8fCBkYXRhU2NhbGUudHlwZSA9PT0gJ2ZpdCcpIHtcbiAgICAgICAgdmVydGljYWxBeGlzU2NhbGUgPSBkZWZhdWx0Q29uZmlnLm5vbkVsZW1lbnRTY2FsZXMudmVydGljYWxBeGlzU2NhbGU7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvL1RoZSB2ZXJ0aWNhbCBheGlzIGlzIHRoZSBkYXRhIGF4aXMsIHRoZSBkYXRhU2NhbGUgaGFzIGEgdXNlci1pbnB1dHRlZCB2YWx1ZSwgYW5kIHRoZXJlIGlzbid0IGEgdXNlci1pbnB1dHRlZCB2ZXJ0aWNhbEF4aXNTY2FsZVxuICAgICAgICAvLyBTbywgd2UnbGwgcHJldmVudCB0aGUgYXhpcyBzY2FsaW5nIGZyb20gaW50ZXJmZXJpbmcgd2l0aCB0aGUgZGF0YVNjYWxlXG4gICAgICAgIHZlcnRpY2FsQXhpc1NjYWxlID0gJ25vLXNjYWxlJztcbiAgICAgIH1cbiAgICB9XG4gICAgbGV0IGhvcml6b250YWxBeGlzU2NhbGUgPSBwcm92aWRlZFNjYWxpbmdDb25maWc/Lmhvcml6b250YWxBeGlzU2NhbGU7XG4gICAgaWYgKGhvcml6b250YWxBeGlzU2NhbGUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgaWYgKGNoYXJ0RGF0YURpcmVjdGlvbiA9PT0gJ3ZlcnRpY2FsJyB8fCBkYXRhU2NhbGUudHlwZSA9PT0gJ2ZpdCcpIHtcbiAgICAgICAgaG9yaXpvbnRhbEF4aXNTY2FsZSA9XG4gICAgICAgICAgZGVmYXVsdENvbmZpZy5ub25FbGVtZW50U2NhbGVzLmhvcml6b250YWxBeGlzU2NhbGU7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvL1RoZSBob3Jpem9udGFsIGF4aXMgaXMgdGhlIGRhdGEgYXhpcywgdGhlIGRhdGFTY2FsZSBoYXMgYSB1c2VyLWlucHV0dGVkIHZhbHVlLCBhbmQgdGhlcmUgaXNuJ3QgYSB1c2VyLWlucHV0dGVkIGhvcml6b250YWxBeGlzU2NhbGVcbiAgICAgICAgLy8gU28sIHdlJ2xsIHByZXZlbnQgdGhlIGF4aXMgc2NhbGluZyBmcm9tIGludGVyZmVyaW5nIHdpdGggdGhlIGRhdGFTY2FsZVxuICAgICAgICBob3Jpem9udGFsQXhpc1NjYWxlID0gJ25vLXNjYWxlJztcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgIGRhdGFTY2FsZTpcbiAgICAgICAgcHJvdmlkZWRTY2FsaW5nQ29uZmlnICYmIHByb3ZpZGVkU2NhbGluZ0NvbmZpZy5kYXRhU2NhbGVcbiAgICAgICAgICA/IHByb3ZpZGVkU2NhbGluZ0NvbmZpZy5kYXRhU2NhbGVcbiAgICAgICAgICA6IGRlZmF1bHRDb25maWcubm9uRWxlbWVudFNjYWxlcy5kYXRhU2NhbGUsXG4gICAgICBob3Jpem9udGFsQXhpc1NjYWxlLFxuICAgICAgdmVydGljYWxBeGlzU2NhbGUsXG4gICAgICBob3Jpem9udGFsQ29udGFpbmVyU2NhbGU6XG4gICAgICAgIHByb3ZpZGVkU2NhbGluZ0NvbmZpZyAmJiBwcm92aWRlZFNjYWxpbmdDb25maWcuaG9yaXpvbnRhbENvbnRhaW5lclNjYWxlXG4gICAgICAgICAgPyBwcm92aWRlZFNjYWxpbmdDb25maWcuaG9yaXpvbnRhbENvbnRhaW5lclNjYWxlXG4gICAgICAgICAgOiBkZWZhdWx0Q29uZmlnLm5vbkVsZW1lbnRTY2FsZXMuaG9yaXpvbnRhbENvbnRhaW5lclNjYWxlLFxuICAgICAgdmVydGljYWxDb250YWluZXJTY2FsZTpcbiAgICAgICAgcHJvdmlkZWRTY2FsaW5nQ29uZmlnICYmIHByb3ZpZGVkU2NhbGluZ0NvbmZpZy52ZXJ0aWNhbENvbnRhaW5lclNjYWxlXG4gICAgICAgICAgPyBwcm92aWRlZFNjYWxpbmdDb25maWcudmVydGljYWxDb250YWluZXJTY2FsZVxuICAgICAgICAgIDogZGVmYXVsdENvbmZpZy5ub25FbGVtZW50U2NhbGVzLnZlcnRpY2FsQ29udGFpbmVyU2NhbGUsXG4gICAgICB0YXJnZXRUaWNrQ291bnQ6XG4gICAgICAgIHByb3ZpZGVkU2NhbGluZ0NvbmZpZyAmJlxuICAgICAgICBwcm92aWRlZFNjYWxpbmdDb25maWcudGFyZ2V0VGlja0NvdW50ICE9PSB1bmRlZmluZWRcbiAgICAgICAgICA/IHByb3ZpZGVkU2NhbGluZ0NvbmZpZy50YXJnZXRUaWNrQ291bnRcbiAgICAgICAgICA6IGRlZmF1bHRDb25maWcubm9uRWxlbWVudFNjYWxlcy50YXJnZXRUaWNrQ291bnQsXG4gICAgfTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGlzRGVFbXBoYXNpemVkKFxuICAgIGNvbmZpZzogRmxvd0NvbmZpZyxcbiAgICBpZDogc3RyaW5nLFxuICAgIGlzRGFya2VuZWQ6IGJvb2xlYW4sXG4gICk6IGJvb2xlYW4ge1xuICAgIGNvbnN0IGhpZ2hsaWdodGVkQnVja2V0cyA9IGNvbmZpZy5mbG93Q29uZmlnLnN1YkJ1Y2tldHNDb25maWdcbiAgICAgIC5maWx0ZXIoc2JjID0+IHNiYy5pc0hpZ2hsaWdodGVkID09PSB0cnVlKVxuICAgICAgLm1hcChzYmMgPT4gc2JjLmJ1Y2tldElkKTtcbiAgICBpZiAoaGlnaGxpZ2h0ZWRCdWNrZXRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBpZiAoaXNEYXJrZW5lZCkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIGlmIChoaWdobGlnaHRlZEJ1Y2tldHMuc29tZShoYiA9PiBoYiA9PT0gaWQpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgZnVuY3Rpb24gY2FsY3VsYXRlRmxvd0Nvbm5lY3Rpb25QYXRoKFxuICAgIGNvbm5lY3Rpb246IEZsb3dDb25uZWN0aW9uUmVuZGVyLFxuICApOiBzdHJpbmcge1xuICAgIGNvbnN0IGR4ID0gY29ubmVjdGlvbi50b3BMaW5lLngyIC0gY29ubmVjdGlvbi50b3BMaW5lLngxO1xuICAgIGNvbnN0IGN1cnZlID0gTWF0aC5hYnMoZHgpICogRkxPV19DT05ORUNUSU9OX0NVUlZFX0NPTlNUQU5UO1xuXG4gICAgY29uc3QgcGF0aCA9IGBcbiAgICAgIE0gJHtjb25uZWN0aW9uLnRvcExpbmUueDF9LCR7Y29ubmVjdGlvbi50b3BMaW5lLnkxfVxuXG4gICAgICBDICR7Y29ubmVjdGlvbi50b3BMaW5lLngxICsgY3VydmV9LCR7Y29ubmVjdGlvbi50b3BMaW5lLnkxfVxuICAgICAgICAke2Nvbm5lY3Rpb24udG9wTGluZS54MiAtIGN1cnZlfSwke2Nvbm5lY3Rpb24udG9wTGluZS55Mn1cbiAgICAgICAgJHtjb25uZWN0aW9uLnRvcExpbmUueDJ9LCR7Y29ubmVjdGlvbi50b3BMaW5lLnkyfVxuXG4gICAgICBMICR7Y29ubmVjdGlvbi5ib3R0b21MaW5lLngyfSwke2Nvbm5lY3Rpb24uYm90dG9tTGluZS55Mn1cblxuICAgICAgQyAke2Nvbm5lY3Rpb24uYm90dG9tTGluZS54MiAtIGN1cnZlfSwke2Nvbm5lY3Rpb24uYm90dG9tTGluZS55Mn1cbiAgICAgICAgJHtjb25uZWN0aW9uLmJvdHRvbUxpbmUueDEgKyBjdXJ2ZX0sJHtjb25uZWN0aW9uLmJvdHRvbUxpbmUueTF9XG4gICAgICAgICR7Y29ubmVjdGlvbi5ib3R0b21MaW5lLngxfSwke2Nvbm5lY3Rpb24uYm90dG9tTGluZS55MX1cblxuICAgICAgWlxuICAgIGA7XG5cbiAgICByZXR1cm4gcGF0aDtcbiAgfVxuXG4gIGZ1bmN0aW9uIGN1YmljKFxuICAgIGE6IG51bWJlcixcbiAgICBiOiBudW1iZXIsXG4gICAgYzogbnVtYmVyLFxuICAgIGQ6IG51bWJlcixcbiAgICB0OiBudW1iZXIsXG4gICk6IG51bWJlciB7XG4gICAgY29uc3QgbXQgPSAxIC0gdDtcbiAgICByZXR1cm4gbXQgKiogMyAqIGEgKyAzICogbXQgKiogMiAqIHQgKiBiICsgMyAqIG10ICogdCAqKiAyICogYyArIHQgKiogMyAqIGQ7XG4gIH1cblxuICBmdW5jdGlvbiBiZXppZXJZQXRYKFxuICAgIHg6IG51bWJlcixcbiAgICBsaW5lOiB7XG4gICAgICB4MTogbnVtYmVyO1xuICAgICAgeTE6IG51bWJlcjtcbiAgICAgIHgyOiBudW1iZXI7XG4gICAgICB5MjogbnVtYmVyO1xuICAgIH0sXG4gICk6IG51bWJlciB7XG4gICAgY29uc3QgY3VydmUgPSBNYXRoLmFicyhsaW5lLngyIC0gbGluZS54MSkgKiBGTE9XX0NPTk5FQ1RJT05fQ1VSVkVfQ09OU1RBTlQ7XG4gICAgY29uc3QgcDAgPSB7IHg6IGxpbmUueDEsIHk6IGxpbmUueTEgfTtcbiAgICBjb25zdCBwMSA9IHsgeDogbGluZS54MSArIGN1cnZlLCB5OiBsaW5lLnkxIH07XG4gICAgY29uc3QgcDIgPSB7IHg6IGxpbmUueDIgLSBjdXJ2ZSwgeTogbGluZS55MiB9O1xuICAgIGNvbnN0IHAzID0geyB4OiBsaW5lLngyLCB5OiBsaW5lLnkyIH07XG5cbiAgICBsZXQgbG8gPSAwO1xuICAgIGxldCBoaSA9IDE7XG5cbiAgICAvLyBCaW5hcnkgc2VhcmNoIGZvciB0IHdoZXJlIGJlemllclgodCkgfj0geFxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgMjA7IGkrKykge1xuICAgICAgY29uc3QgdCA9IChsbyArIGhpKSAvIDI7XG4gICAgICBjb25zdCBieCA9IGN1YmljKHAwLngsIHAxLngsIHAyLngsIHAzLngsIHQpO1xuXG4gICAgICBpZiAoYnggPCB4KSBsbyA9IHQ7XG4gICAgICBlbHNlIGhpID0gdDtcbiAgICB9XG5cbiAgICBjb25zdCB0ID0gKGxvICsgaGkpIC8gMjtcbiAgICByZXR1cm4gY3ViaWMocDAueSwgcDEueSwgcDIueSwgcDMueSwgdCk7XG4gIH1cblxuICBmdW5jdGlvbiBjaGVja0lmUG9pbnRXaXRoaW5Db25uZWN0aW9uKFxuICAgIGNvbm5lY3Rpb246IEZsb3dDb25uZWN0aW9uUmVuZGVyLFxuICAgIHBvaW50WDogbnVtYmVyLFxuICAgIHBvaW50WTogbnVtYmVyLFxuICApOiBib29sZWFuIHtcbiAgICBjb25zdCB0b3BZID0gYmV6aWVyWUF0WChwb2ludFgsIGNvbm5lY3Rpb24udG9wTGluZSk7XG5cbiAgICBjb25zdCBib3R0b21ZID0gYmV6aWVyWUF0WChwb2ludFgsIGNvbm5lY3Rpb24uYm90dG9tTGluZSk7XG5cbiAgICByZXR1cm4gKFxuICAgICAgcG9pbnRYID49IGNvbm5lY3Rpb24udG9wTGluZS54MSAmJlxuICAgICAgcG9pbnRYIDw9IGNvbm5lY3Rpb24udG9wTGluZS54MiAmJlxuICAgICAgcG9pbnRZID49IE1hdGgubWluKHRvcFksIGJvdHRvbVkpICYmXG4gICAgICBwb2ludFkgPD0gTWF0aC5tYXgodG9wWSwgYm90dG9tWSlcbiAgICApO1xuICB9XG5cbiAgZnVuY3Rpb24gZ2V0Rmxvd0J1Y2tldEluZGV4Rm9ySG92ZXIoXG4gICAgY2hhcnRTaXppbmdWYWx1ZXM6IEZ1bGxDaGFydFNjYWxlVmFsdWVzLFxuICAgIHhQb3M6IG51bWJlcixcbiAgKTogeyBpbmRleDogbnVtYmVyOyBhcmVhOiAnYmFyJyB8ICdjb25uZWN0aW9uJyB9IHwgbnVsbCB7XG4gICAgbGV0IGJ1Y2tldEluZGV4ID0gMDtcbiAgICBjb25zdCBidWNrZXRMZWZ0RWRnZSA9IGNoYXJ0U2l6aW5nVmFsdWVzLnRvdGFsTGVmdE9mZnNldDtcbiAgICBjb25zdCB0b3RhbEJ1Y2tldEdhcCA9XG4gICAgICBjaGFydFNpemluZ1ZhbHVlcy5iYXJTaXplICsgY2hhcnRTaXppbmdWYWx1ZXMuYnVja2V0R2FwO1xuICAgIGlmIChidWNrZXRMZWZ0RWRnZSA+IHhQb3MpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICB3aGlsZSAoYnVja2V0TGVmdEVkZ2UgKyBidWNrZXRJbmRleCAqIHRvdGFsQnVja2V0R2FwIDwgeFBvcykge1xuICAgICAgaWYgKGJ1Y2tldExlZnRFZGdlICsgKGJ1Y2tldEluZGV4ICsgMSkgKiB0b3RhbEJ1Y2tldEdhcCA+IHhQb3MpIHtcbiAgICAgICAgaWYgKFxuICAgICAgICAgIGJ1Y2tldExlZnRFZGdlICtcbiAgICAgICAgICAgIGJ1Y2tldEluZGV4ICogdG90YWxCdWNrZXRHYXAgK1xuICAgICAgICAgICAgY2hhcnRTaXppbmdWYWx1ZXMuYmFyU2l6ZSA+XG4gICAgICAgICAgeFBvc1xuICAgICAgICApIHtcbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgaW5kZXg6IGJ1Y2tldEluZGV4LFxuICAgICAgICAgICAgYXJlYTogJ2JhcicsXG4gICAgICAgICAgfTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgaW5kZXg6IGJ1Y2tldEluZGV4LFxuICAgICAgICAgICAgYXJlYTogJ2Nvbm5lY3Rpb24nLFxuICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGJ1Y2tldEluZGV4ICs9IDE7XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgLy9UaGVzZSBvdmVybG9hZHMgZW5zdXJlIHRoZSBmdW5jdGlvbiBrbm93cyB0aGF0LCBpZiB3aWR0aCBhbmQgaGVpZ2h0IGFyZSBkZWZpbmVkIG9uIGlucHV0LCB0aGV5J2xsIGJlIGRlZmluZWQgb24gb3V0cHV0XG4gIGZ1bmN0aW9uIGNoZWNrQW5jaG9yc0FnYWluc3RCb3VuZChcbiAgICBhbmNob3JYOiBudW1iZXIsXG4gICAgYW5jaG9yWTogbnVtYmVyLFxuICAgIGRpbWVuc2lvbnM6IERpbWVuc2lvbnMsXG4gICk6IHsgYW5jaG9yWDogbnVtYmVyOyBhbmNob3JZOiBudW1iZXIgfTtcblxuICBmdW5jdGlvbiBjaGVja0FuY2hvcnNBZ2FpbnN0Qm91bmQoXG4gICAgYW5jaG9yWDogbnVtYmVyLFxuICAgIGFuY2hvclk6IG51bWJlcixcbiAgICBkaW1lbnNpb25zOiBEaW1lbnNpb25zLFxuICAgIHdpZHRoOiBudW1iZXIsXG4gICAgaGVpZ2h0OiBudW1iZXIsXG4gICk6IHtcbiAgICBhbmNob3JYOiBudW1iZXI7XG4gICAgYW5jaG9yWTogbnVtYmVyO1xuICAgIGFuY2hvcldpZHRoOiBudW1iZXI7XG4gICAgYW5jaG9ySGVpZ2h0OiBudW1iZXI7XG4gIH07XG5cbiAgZnVuY3Rpb24gY2hlY2tBbmNob3JzQWdhaW5zdEJvdW5kKFxuICAgIGFuY2hvclg6IG51bWJlcixcbiAgICBhbmNob3JZOiBudW1iZXIsXG4gICAgZGltZW5zaW9uczogRGltZW5zaW9ucyxcbiAgICB3aWR0aD86IG51bWJlcixcbiAgICBoZWlnaHQ/OiBudW1iZXIsXG4gICk6IHtcbiAgICBhbmNob3JYOiBudW1iZXI7XG4gICAgYW5jaG9yWTogbnVtYmVyO1xuICAgIGFuY2hvcldpZHRoPzogbnVtYmVyO1xuICAgIGFuY2hvckhlaWdodD86IG51bWJlcjtcbiAgfSB7XG4gICAgbGV0IHJldEFuY2hvclggPSBhbmNob3JYO1xuICAgIGxldCByZXRBbmNob3JZID0gYW5jaG9yWTtcbiAgICBsZXQgcmV0V2lkdGg6IG51bWJlciB8IHVuZGVmaW5lZCA9IHdpZHRoO1xuICAgIGxldCByZXRIZWlnaHQ6IG51bWJlciB8IHVuZGVmaW5lZCA9IGhlaWdodDtcbiAgICBpZiAocmV0QW5jaG9yWCA+IGRpbWVuc2lvbnMud2lkdGgpIHtcbiAgICAgIHJldEFuY2hvclggPSBkaW1lbnNpb25zLndpZHRoO1xuICAgICAgaWYgKHJldFdpZHRoICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgcmV0V2lkdGggPSAwO1xuICAgICAgfVxuICAgIH1cbiAgICBpZiAocmV0QW5jaG9yWCA8IDApIHtcbiAgICAgIHJldEFuY2hvclggPSAwO1xuICAgICAgaWYgKHJldFdpZHRoICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgcmV0V2lkdGggPSAwO1xuICAgICAgfVxuICAgIH1cbiAgICBpZiAocmV0QW5jaG9yWSA+IGRpbWVuc2lvbnMuaGVpZ2h0KSB7XG4gICAgICByZXRBbmNob3JZID0gZGltZW5zaW9ucy5oZWlnaHQ7XG4gICAgICBpZiAocmV0SGVpZ2h0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgcmV0SGVpZ2h0ID0gMDtcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKHJldEFuY2hvclkgPCAwKSB7XG4gICAgICByZXRBbmNob3JZID0gMDtcbiAgICAgIGlmIChyZXRIZWlnaHQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICByZXRIZWlnaHQgPSAwO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBhbmNob3JYOiByZXRBbmNob3JYLFxuICAgICAgYW5jaG9yWTogcmV0QW5jaG9yWSxcbiAgICAgIGFuY2hvcldpZHRoOiByZXRXaWR0aCxcbiAgICAgIGFuY2hvckhlaWdodDogcmV0SGVpZ2h0LFxuICAgIH07XG4gIH1cbn1cbiJdfQ==