@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
@@ -0,0 +1,3768 @@
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, //Ticks and data labels use the same formatting on the same kind of data
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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TUFBTSxJQUFJLEdBQUc7VUFDUCxVQUFVLENBQUMsT0FBTyxDQUFDLEVBQUUsSUFBSSxVQUFVLENBQUMsT0FBTyxDQUFDLEVBQUU7O1VBRTlDLFVBQVUsQ0FBQyxPQUFPLENBQUMsRUFBRSxHQUFHLEtBQUssSUFBSSxVQUFVLENBQUMsT0FBTyxDQUFDLEVBQUU7VUFDdEQsVUFBVSxDQUFDLE9BQU8sQ0FBQyxFQUFFLEdBQUcsS0FBSyxJQUFJLFVBQVUsQ0FBQyxPQUFPLENBQUMsRUFBRTtVQUN0RCxVQUFVLENBQUMsT0FBTyxDQUFDLEVBQUUsSUFBSSxVQUFVLENBQUMsT0FBTyxDQUFDLEVBQUU7O1VBRTlDLFVBQVUsQ0FBQyxVQUFVLENBQUMsRUFBRSxJQUFJLFVBQVUsQ0FBQyxVQUFVLENBQUMsRUFBRTs7VUFFcEQsVUFBVSxDQUFDLFVBQVUsQ0FBQyxFQUFFLEdBQUcsS0FBSyxJQUFJLFVBQVUsQ0FBQyxVQUFVLENBQUMsRUFBRTtVQUM1RCxVQUFVLENBQUMsVUFBVSxDQUFDLEVBQUUsR0FBRyxLQUFLLElBQUksVUFBVSxDQUFDLFVBQVUsQ0FBQyxFQUFFO1VBQzVELFVBQVUsQ0FBQyxVQUFVLENBQUMsRUFBRSxJQUFJLFVBQVUsQ0FBQyxVQUFVLENBQUMsRUFBRTs7O0tBR3pELENBQUM7UUFFRixPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFFRCxTQUFTLEtBQUssQ0FDWixDQUFTLEVBQ1QsQ0FBUyxFQUNULENBQVMsRUFDVCxDQUFTLEVBQ1QsQ0FBUztRQUVULE1BQU0sRUFBRSxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDakIsT0FBTyxFQUFFLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDOUUsQ0FBQztJQUVELFNBQVMsVUFBVSxDQUNqQixDQUFTLEVBQ1QsSUFLQztRQUVELE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUUsR0FBRyxJQUFJLENBQUMsRUFBRSxDQUFDLEdBQUcsOEJBQThCLENBQUM7UUFDM0UsTUFBTSxFQUFFLEdBQUcsRUFBRSxDQUFDLEVBQUUsSUFBSSxDQUFDLEVBQUUsRUFBRSxDQUFDLEVBQUUsSUFBSSxDQUFDLEVBQUUsRUFBRSxDQUFDO1FBQ3RDLE1BQU0sRUFBRSxHQUFHLEVBQUUsQ0FBQyxFQUFFLElBQUksQ0FBQyxFQUFFLEdBQUcsS0FBSyxFQUFFLENBQUMsRUFBRSxJQUFJLENBQUMsRUFBRSxFQUFFLENBQUM7UUFDOUMsTUFBTSxFQUFFLEdBQUcsRUFBRSxDQUFDLEVBQUUsSUFBSSxDQUFDLEVBQUUsR0FBRyxLQUFLLEVBQUUsQ0FBQyxFQUFFLElBQUksQ0FBQyxFQUFFLEVBQUUsQ0FBQztRQUM5QyxNQUFNLEVBQUUsR0FBRyxFQUFFLENBQUMsRUFBRSxJQUFJLENBQUMsRUFBRSxFQUFFLENBQUMsRUFBRSxJQUFJLENBQUMsRUFBRSxFQUFFLENBQUM7UUFFdEMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxDQUFDO1FBQ1gsSUFBSSxFQUFFLEdBQUcsQ0FBQyxDQUFDO1FBRVgsNENBQTRDO1FBQzVDLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQztZQUM1QixNQUFNLENBQUMsR0FBRyxDQUFDLEVBQUUsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDeEIsTUFBTSxFQUFFLEdBQUcsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFFNUMsSUFBSSxFQUFFLEdBQUcsQ0FBQztnQkFBRSxFQUFFLEdBQUcsQ0FBQyxDQUFDOztnQkFDZCxFQUFFLEdBQUcsQ0FBQyxDQUFDO1FBQ2QsQ0FBQztRQUVELE1BQU0sQ0FBQyxHQUFHLENBQUMsRUFBRSxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUN4QixPQUFPLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQzFDLENBQUM7SUFFRCxTQUFTLDRCQUE0QixDQUNuQyxVQUFnQyxFQUNoQyxNQUFjLEVBQ2QsTUFBYztRQUVkLE1BQU0sSUFBSSxHQUFHLFVBQVUsQ0FBQyxNQUFNLEVBQUUsVUFBVSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBRXBELE1BQU0sT0FBTyxHQUFHLFVBQVUsQ0FBQyxNQUFNLEVBQUUsVUFBVSxDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBRTFELE9BQU8sQ0FDTCxNQUFNLElBQUksVUFBVSxDQUFDLE9BQU8sQ0FBQyxFQUFFO1lBQy9CLE1BQU0sSUFBSSxVQUFVLENBQUMsT0FBTyxDQUFDLEVBQUU7WUFDL0IsTUFBTSxJQUFJLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxFQUFFLE9BQU8sQ0FBQztZQUNqQyxNQUFNLElBQUksSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLEVBQUUsT0FBTyxDQUFDLENBQ2xDLENBQUM7SUFDSixDQUFDO0lBRUQsU0FBUywwQkFBMEIsQ0FDakMsaUJBQXVDLEVBQ3ZDLElBQVk7UUFFWixJQUFJLFdBQVcsR0FBRyxDQUFDLENBQUM7UUFDcEIsTUFBTSxjQUFjLEdBQUcsaUJBQWlCLENBQUMsZUFBZSxDQUFDO1FBQ3pELE1BQU0sY0FBYyxHQUNsQixpQkFBaUIsQ0FBQyxPQUFPLEdBQUcsaUJBQWlCLENBQUMsU0FBUyxDQUFDO1FBQzFELElBQUksY0FBYyxHQUFHLElBQUksRUFBRSxDQUFDO1lBQzFCLE9BQU8sSUFBSSxDQUFDO1FBQ2QsQ0FBQztRQUNELE9BQU8sY0FBYyxHQUFHLFdBQVcsR0FBRyxjQUFjLEdBQUcsSUFBSSxFQUFFLENBQUM7WUFDNUQsSUFBSSxjQUFjLEdBQUcsQ0FBQyxXQUFXLEdBQUcsQ0FBQyxDQUFDLEdBQUcsY0FBYyxHQUFHLElBQUksRUFBRSxDQUFDO2dCQUMvRCxJQUNFLGNBQWM7b0JBQ1osV0FBVyxHQUFHLGNBQWM7b0JBQzVCLGlCQUFpQixDQUFDLE9BQU87b0JBQzNCLElBQUksRUFDSixDQUFDO29CQUNELE9BQU87d0JBQ0wsS0FBSyxFQUFFLFdBQVc7d0JBQ2xCLElBQUksRUFBRSxLQUFLO3FCQUNaLENBQUM7Z0JBQ0osQ0FBQztxQkFBTSxDQUFDO29CQUNOLE9BQU87d0JBQ0wsS0FBSyxFQUFFLFdBQVc7d0JBQ2xCLElBQUksRUFBRSxZQUFZO3FCQUNuQixDQUFDO2dCQUNKLENBQUM7WUFDSCxDQUFDO1lBQ0QsV0FBVyxJQUFJLENBQUMsQ0FBQztRQUNuQixDQUFDO1FBQ0QsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBc0JELFNBQVMsd0JBQXdCLENBQy9CLE9BQWUsRUFDZixPQUFlLEVBQ2YsVUFBc0IsRUFDdEIsS0FBYyxFQUNkLE1BQWU7UUFPZixJQUFJLFVBQVUsR0FBRyxPQUFPLENBQUM7UUFDekIsSUFBSSxVQUFVLEdBQUcsT0FBTyxDQUFDO1FBQ3pCLElBQUksUUFBUSxHQUF1QixLQUFLLENBQUM7UUFDekMsSUFBSSxTQUFTLEdBQXVCLE1BQU0sQ0FBQztRQUMzQyxJQUFJLFVBQVUsR0FBRyxVQUFVLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDbEMsVUFBVSxHQUFHLFVBQVUsQ0FBQyxLQUFLLENBQUM7WUFDOUIsSUFBSSxRQUFRLEtBQUssU0FBUyxFQUFFLENBQUM7Z0JBQzNCLFFBQVEsR0FBRyxDQUFDLENBQUM7WUFDZixDQUFDO1FBQ0gsQ0FBQztRQUNELElBQUksVUFBVSxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQ25CLFVBQVUsR0FBRyxDQUFDLENBQUM7WUFDZixJQUFJLFFBQVEsS0FBSyxTQUFTLEVBQUUsQ0FBQztnQkFDM0IsUUFBUSxHQUFHLENBQUMsQ0FBQztZQUNmLENBQUM7UUFDSCxDQUFDO1FBQ0QsSUFBSSxVQUFVLEdBQUcsVUFBVSxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQ25DLFVBQVUsR0FBRyxVQUFVLENBQUMsTUFBTSxDQUFDO1lBQy9CLElBQUksU0FBUyxLQUFLLFNBQVMsRUFBRSxDQUFDO2dCQUM1QixTQUFTLEdBQUcsQ0FBQyxDQUFDO1lBQ2hCLENBQUM7UUFDSCxDQUFDO1FBQ0QsSUFBSSxVQUFVLEdBQUcsQ0FBQyxFQUFFLENBQUM7WUFDbkIsVUFBVSxHQUFHLENBQUMsQ0FBQztZQUNmLElBQUksU0FBUyxLQUFLLFNBQVMsRUFBRSxDQUFDO2dCQUM1QixTQUFTLEdBQUcsQ0FBQyxDQUFDO1lBQ2hCLENBQUM7UUFDSCxDQUFDO1FBRUQsT0FBTztZQUNMLE9BQU8sRUFBRSxVQUFVO1lBQ25CLE9BQU8sRUFBRSxVQUFVO1lBQ25CLFdBQVcsRUFBRSxRQUFRO1lBQ3JCLFlBQVksRUFBRSxTQUFTO1NBQ3hCLENBQUM7SUFDSixDQUFDO0FBQ0gsQ0FBQyxFQTExTGdCLEtBQUssS0FBTCxLQUFLLFFBMDFMckIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDdXJyZW5jeVBpcGUgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHsgc2NhbGVMaW5lYXIgfSBmcm9tICdkMy1zY2FsZSc7XG5pbXBvcnQgeyBhcmMsIGFyZWEsIGxpbmUsIHBpZSB9IGZyb20gJ2QzLXNoYXBlJztcbmltcG9ydCB7IHV0Y0Zvcm1hdCB9IGZyb20gJ2QzLXRpbWUtZm9ybWF0JztcbmltcG9ydCB7IHN1bSwgdW5pcSB9IGZyb20gJ2xvZGFzaCc7XG5pbXBvcnQgeyBEYXlzUGlwZSB9IGZyb20gJy4uLy4uL2Zvcm1hdC9waXBlcy9kYXlzLnBpcGUnO1xuaW1wb3J0IHsgTnVtYmVyUGlwZSB9IGZyb20gJy4uLy4uL2Zvcm1hdC9waXBlcy9udW1iZXIucGlwZSc7XG5pbXBvcnQgeyBQZXJjZW50YWdlUGlwZSB9IGZyb20gJy4uLy4uL2Zvcm1hdC9waXBlcy9wZXJjZW50YWdlLnBpcGUnO1xuaW1wb3J0IHsgU21hbGxDdXJyZW5jeVBpcGUgfSBmcm9tICcuLi8uLi9mb3JtYXQvcGlwZXMvc21hbGwtY3VycmVuY3kucGlwZSc7XG5pbXBvcnQgeyBTbWFsbE51bWJlclBpcGUgfSBmcm9tICcuLi8uLi9mb3JtYXQvcGlwZXMvc21hbGwtbnVtYmVyLnBpcGUnO1xuaW1wb3J0IHsgQ2FsbG91dENvbXBvbmVudCB9IGZyb20gJy4uLy4uL292ZXJsYXkvY2FsbG91dC9jYWxsb3V0LmNvbXBvbmVudCc7XG5pbXBvcnQge1xuICBDaGFydERhdGFEaXJlY3Rpb24sXG4gIENoYXJ0U2NhbGVFbGVtZW50LFxuICBDb250YWluZXJTY2FsaW5nVHlwZSxcbiAgRGVmYXVsdERvbnV0U2l6aW5nQ29uZmlnLFxuICBEZWZhdWx0U2NhbGluZ0NvbmZpZyxcbiAgRG9udXRTaXppbmdDb25maWcsXG4gIEVsZW1lbnRTY2FsaW5nQ29uZmlndXJhdGlvbixcbiAgZW1wdHlDaGFydFNjYWxlVmFsdWVzLFxuICBGdWxsQ2hhcnRTY2FsZVZhbHVlcyxcbiAgRnVsbEVsZW1lbnRTY2FsaW5nQ29uZmlnLFxuICBGdWxsU2NhbGluZ0NvbmZpZyxcbiAgZ2V0RGVmYXVsdFNjYWxpbmdDb25maWdCeUNoYXJ0VHlwZSxcbiAgTm9uRWxlbWVudFNjYWxpbmdDb25maWcsXG4gIFBhcnRpYWxFbGVtZW50U2NhbGluZ0NvbmZpZyxcbn0gZnJvbSAnLi9jaGFydC1zY2FsaW5nJztcblxuZXhwb3J0IG5hbWVzcGFjZSBDaGFydCB7XG4gIGV4cG9ydCBjb25zdCBkZWZhdWx0Q29sb3JQYWxldHRlID0gW1xuICAgIC8vQmFzZSBjb2xvcnNcbiAgICAnLS1iYWphLWJsYXN0LTUwJyxcbiAgICAnLS10ZWFsLWRpYW1vbmQtNTAnLFxuICAgICctLWZ5cmUtNTAnLFxuICAgICctLXRhbmctNTAnLFxuICAgICctLXB1cnAtNjAnLFxuICAgICctLXJvc2ktNzAnLFxuICAgIC8vU2hpZnQgbGlnaHRlciBmcm9tIGJhc2UgYnkgLTIwXG4gICAgJy0tYmFqYS1ibGFzdC0zMCcsXG4gICAgJy0tdGVhbC1kaWFtb25kLTMwJyxcbiAgICAnLS1meXJlLTMwJyxcbiAgICAnLS10YW5nLTMwJyxcbiAgICAnLS1wdXJwLTQwJyxcbiAgICAnLS1yb3NpLTUwJyxcbiAgICAvL1NoaWZ0IGRhcmtlciBmcm9tIGJhc2UgYnkgKzIwXG4gICAgJy0tYmFqYS1ibGFzdC03MCcsXG4gICAgJy0tdGVhbC1kaWFtb25kLTcwJyxcbiAgICAnLS1meXJlLTcwJyxcbiAgICAnLS10YW5nLTcwJyxcbiAgICAnLS1wdXJwLTgwJyxcbiAgICAnLS1yb3NpLTkwJyxcbiAgXTtcblxuICBleHBvcnQgZnVuY3Rpb24gY2hhcnQoXG4gICAgY29uZmlnOiBDb25maWcsXG4gICAgZGF0YTogSW5wdXREYXRhLFxuICAgIGRpbWVuc2lvbnM6IERpbWVuc2lvbnMsXG4gICk6IFJlbmRlcmVkQ2hhcnQge1xuICAgIHJldHVybiBjb25maWcudHlwZSA9PT0gJ2xpbmUnXG4gICAgICA/IGxpbmVzKGNvbmZpZywgZGF0YSwgZGltZW5zaW9ucylcbiAgICAgIDogY29uZmlnLnR5cGUgPT09ICdhcmVhJ1xuICAgICAgPyBhcmVhcyhjb25maWcsIGRhdGEsIGRpbWVuc2lvbnMpXG4gICAgICA6IGNvbmZpZy50eXBlID09PSAnZG9udXQnXG4gICAgICA/IGFyY3MoY29uZmlnLCBkYXRhLCBkaW1lbnNpb25zKVxuICAgICAgOiBjb25maWcudHlwZSA9PT0gJ2hvcml6b250YWwtYmFyJ1xuICAgICAgPyBob3Jpem9udGFsQmFycyhjb25maWcsIGRhdGEsIGRpbWVuc2lvbnMpXG4gICAgICA6IGNvbmZpZy50eXBlID09PSAnYmFyJ1xuICAgICAgPyBiYXJzKGNvbmZpZywgZGF0YSwgZGltZW5zaW9ucylcbiAgICAgIDogY29uZmlnLnR5cGUgPT09ICd3YXRlcmZhbGwnXG4gICAgICA/IHdhdGVyZmFsbChjb25maWcsIGRhdGEsIGRpbWVuc2lvbnMpXG4gICAgICA6IGNvbmZpZy50eXBlID09PSAnZnVubmVsJ1xuICAgICAgPyBmdW5uZWwoY29uZmlnLCBkYXRhLCBkaW1lbnNpb25zKVxuICAgICAgOiBjb25maWcudHlwZSA9PT0gJ2Zsb3cnXG4gICAgICA/IGZsb3dzKGNvbmZpZywgZGF0YSwgZGltZW5zaW9ucylcbiAgICAgIDogZW1wdHlDaGFydDtcbiAgfVxuXG4gIGZ1bmN0aW9uIGxpbmVzKFxuICAgIGNvbmZpZzogQ29uZmlnV2l0aEZ1bGxTY2FsaW5nLFxuICAgIGFsbERhdGE6IElucHV0RGF0YSxcbiAgICBkaW1lbnNpb25zOiBEaW1lbnNpb25zLFxuICApOiBSZW5kZXJlZENoYXJ0IHtcbiAgICBpZiAoIXdhcm5GbG93RGF0YShhbGxEYXRhLCAnbGluZScpKSB7XG4gICAgICByZXR1cm4geyAuLi5lbXB0eUNoYXJ0LCBjaGFydEVycm9yOiAnY29uZmlnJyB9O1xuICAgIH1cbiAgICBjb25zdCB7IGRhdGE6IGhpZGRlbkRhdGEsIHZpc2libGVJbmRpY2VzIH0gPSBoaWRlKGFsbERhdGEpO1xuICAgIGlmIChoaWRkZW5EYXRhLnR5cGUgPT09ICdsYWJlbGVkJykge1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgXCJIZWFkcyB1cCEgTGFiZWxlZCBzZXJpZXMgYXJlbid0IGN1cnJlbnRseSBzdXBwb3J0ZWQgZm9yIGxpbmUgY2hhcnRzXCIsXG4gICAgICApO1xuICAgICAgcmV0dXJuIGVtcHR5Q2hhcnQ7XG4gICAgfVxuICAgIGlmIChoYXNTdXBwbGVtZW50YXJ5RGF0YShoaWRkZW5EYXRhKSkge1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgXCJIZWFkcyB1cCEgU3VwcGxlbWVudGFyeSB5IHZhbHVlcyBhcmVuJ3Qgc3VwcG9ydGVkIGZvciBub24tYmFyIGNoYXJ0c1wiLFxuICAgICAgKTtcbiAgICAgIHJldHVybiBlbXB0eUNoYXJ0O1xuICAgIH1cbiAgICB3YXJuVW5zdXBwb3J0ZWRQYXR0ZXJucyhoaWRkZW5EYXRhLCBbJ3N0cmlwZWQnLCAnZG90cyddLCAnbGluZScpO1xuICAgIC8vVGhpcyBhc3NpZ25tZW50IG1ha2VzIHR5cGVzY3JpcHQgcmVjb2duaXplIHRoZSBhY3R1YWwgdHlwZSAoVGltZXNlcmllc0RhdGEpXG4gICAgY29uc3QgZGF0YSA9IGhpZGRlbkRhdGE7XG5cbiAgICBjb25zdCB7IGRhdGVGb3JtYXQsIHBpcGVUcmFuc2Zvcm0sIGNvbG9ycyB9ID0gZ2V0Rm9ybWF0dGluZ0FuZENvbG9ycyhcbiAgICAgIGFsbERhdGEsXG4gICAgICBkYXRhLFxuICAgICAgY29uZmlnLFxuICAgICk7XG5cbiAgICBjb25zdCBjaGFydFNpemluZ1ZhbHVlcyA9IGdldEZ1bGxDaGFydFNjYWxlVmFsdWVzKFxuICAgICAgY29uZmlnLFxuICAgICAgZGF0YSxcbiAgICAgIGRpbWVuc2lvbnMsXG4gICAgICBwaXBlVHJhbnNmb3JtLFxuICAgICAgZGF0ZUZvcm1hdCxcbiAgICApO1xuICAgIGlmIChjaGFydFNpemluZ1ZhbHVlcyA9PT0gbnVsbCkge1xuICAgICAgcmV0dXJuIHsgLi4uZW1wdHlDaGFydCwgY2hhcnRFcnJvcjogJ3NpemluZycgfTtcbiAgICB9XG5cbiAgICBjb25zdCB0aWNrQ291bnQgPSBnZXRCdWNrZXRUaWNrQ291bnQoY2hhcnRTaXppbmdWYWx1ZXMpO1xuICAgIGNvbnN0IHhUaWNrcyA9IGdlbmVyYXRlVGltZXNlcmllc1RpY2tzKFxuICAgICAgZGF0YSxcbiAgICAgIGNvbmZpZyxcbiAgICAgIHRpY2tDb3VudCxcbiAgICAgIGNoYXJ0U2l6aW5nVmFsdWVzLFxuICAgICAgZGF0ZUZvcm1hdCxcbiAgICApLm1hcCh0aWNrID0+IHRvWFRpY2sodGljaykpO1xuICAgIGNvbnN0IHhTY2FsZSA9IChpbmRleDogbnVtYmVyKTogbnVtYmVyID0+IHtcbiAgICAgIHJldHVybiAoXG4gICAgICAgIGNoYXJ0U2l6aW5nVmFsdWVzLnRvdGFsTGVmdE9mZnNldCArIGNoYXJ0U2l6aW5nVmFsdWVzLmJ1Y2tldEdhcCAqIGluZGV4XG4gICAgICApO1xuICAgIH07XG4gICAgY29uc3QgeyBzY2FsZSwgdGlja3M6IGRhdGFUaWNrcyB9ID0gY2FsY0RhdGFBeGlzU2NhbGVzQW5kVGlja3MoXG4gICAgICBkYXRhLFxuICAgICAgcGlwZVRyYW5zZm9ybSxcbiAgICAgIGNvbmZpZyxcbiAgICAgIGNoYXJ0U2l6aW5nVmFsdWVzLFxuICAgICk7XG4gICAgY29uc3QgeVRpY2tzID0gZGF0YVRpY2tzLm1hcCh0aWNrID0+IHRvWVRpY2sodGljaykpO1xuXG4gICAgY29uc3QgaW5kaWNlcyA9IGRhdGEueC5tYXAoKF8sIGkpID0+IGkpO1xuICAgIGNvbnN0IGxpbmVzID1cbiAgICAgIGRhdGEueC5sZW5ndGggPiAxXG4gICAgICAgID8gZGF0YS55cy5tYXAoeSA9PiAoe1xuICAgICAgICAgICAgbGluZTogbGluZTxudW1iZXI+KFxuICAgICAgICAgICAgICBpID0+IHhTY2FsZShpKSxcbiAgICAgICAgICAgICAgaSA9PiBzY2FsZSh5LnZhbHVlc1tpXSwgeS5pc1NlY29uZGFyeSksXG4gICAgICAgICAgICApKGluZGljZXMpLFxuICAgICAgICAgICAgcGF0dGVybjogeS5wYXR0ZXJuLFxuICAgICAgICAgIH0pKVxuICAgICAgICA6IFtdO1xuICAgIGNvbnN0IGNpcmNsZXMgPVxuICAgICAgZGF0YS54Lmxlbmd0aCA9PT0gMVxuICAgICAgICA/IGRhdGEueXMubWFwKCh5U2VyaWVzLCBpKSA9PiAoe1xuICAgICAgICAgICAgY3g6IHhTY2FsZSgwKSxcbiAgICAgICAgICAgIGN5OiBzY2FsZSh5U2VyaWVzLnZhbHVlc1swXSwgY2hlY2tJZlNlY29uZGFyeShkYXRhLCBpLCAwKSksXG4gICAgICAgICAgfSkpXG4gICAgICAgIDogW107XG5cbiAgICBjb25zdCB5T2Zmc2V0ID0gY2hhcnRTaXppbmdWYWx1ZXMuZGF0YUxhYmVsUGFkZGluZztcbiAgICBjb25zdCBkYXRhTGFiZWxzOiBEYXRhTGFiZWxbXSA9IGRhdGEueXMuZmxhdE1hcCgoeSwgeUluZGV4KSA9PiB7XG4gICAgICBjb25zdCBzdWJMYWJlbHM6IERhdGFMYWJlbFtdID0geS52YWx1ZXMubWFwKCh2YWwsIHhJbmRleCkgPT4gKHtcbiAgICAgICAgZWxlbWVudFR5cGU6ICdkYXRhTGFiZWwnLFxuICAgICAgICBsYWJlbDogcGlwZVRyYW5zZm9ybSh2YWwsIGNoZWNrSWZTZWNvbmRhcnkoZGF0YSwgeUluZGV4LCB4SW5kZXgpKSxcbiAgICAgICAgeVBvczogc2NhbGUodmFsLCBjaGVja0lmU2Vjb25kYXJ5KGRhdGEsIHlJbmRleCwgeEluZGV4KSkgLSB5T2Zmc2V0LFxuICAgICAgICB4UG9zOiB4U2NhbGUoeEluZGV4KSxcbiAgICAgICAgYW5jaG9yOiAnbWlkZGxlJyxcbiAgICAgIH0pKTtcbiAgICAgIHJldHVybiBzdWJMYWJlbHM7XG4gICAgfSk7XG5cbiAgICBmdW5jdGlvbiBob3Zlcihwb3M6IHtcbiAgICAgIHJlY3Q6IERPTVJlY3Q7XG4gICAgICB4OiBudW1iZXI7XG4gICAgICB5OiBudW1iZXI7XG4gICAgICBjb250YWluZXJTY3JvbGxYOiBudW1iZXI7XG4gICAgICBjb250YWluZXJTY3JvbGxZOiBudW1iZXI7XG4gICAgfSk6IEhvdmVyUmV0dXJuIHtcbiAgICAgIGNvbnN0IHJlYWxQb3NYID0gcG9zLnggKyBwb3MuY29udGFpbmVyU2Nyb2xsWDtcbiAgICAgIGNvbnN0IHJlYWxQb3NZID0gcG9zLnkgKyBwb3MuY29udGFpbmVyU2Nyb2xsWTtcbiAgICAgIGlmIChcbiAgICAgICAgY2hhcnRTaXppbmdWYWx1ZXMgPT09IG51bGwgfHxcbiAgICAgICAgZ2V0SWZIb3Zlck91dE9mQm91bmRzKFxuICAgICAgICAgIHBvcy54LFxuICAgICAgICAgIHBvcy55LFxuICAgICAgICAgIHJlYWxQb3NYLFxuICAgICAgICAgIHJlYWxQb3NZLFxuICAgICAgICAgIGNoYXJ0U2l6aW5nVmFsdWVzLFxuICAgICAgICAgIGRpbWVuc2lvbnMsXG4gICAgICAgIClcbiAgICAgICkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cblxuICAgICAgY29uc3QgeEhvdmVySW5kaWNlcyA9IGdldEJ1Y2tldEFuZENsdXN0ZXJOdW1Gb3JIb3ZlcihcbiAgICAgICAgcmVhbFBvc1gsXG4gICAgICAgIGNoYXJ0U2l6aW5nVmFsdWVzLFxuICAgICAgICBkYXRhLFxuICAgICAgICBjb25maWcsXG4gICAgICAgIGRhdGEueC5sZW5ndGgsXG4gICAgICApO1xuICAgICAgaWYgKCF4SG92ZXJJbmRpY2VzKSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfVxuICAgICAgY29uc3QgeyBidWNrZXROdW06IHhJbmRleCB9ID0geEhvdmVySW5kaWNlcztcbiAgICAgIGNvbnN0IHggPSB4U2NhbGUoeEluZGV4KTtcbiAgICAgIGNvbnN0IHZpc2libGVZSW5kZXggPSBmaW5kTmVhcmVzdEluZGV4V2l0aFNlY29uZGFyeShcbiAgICAgICAgZGF0YS55cy5tYXAoKHksIGkpID0+ICh7XG4gICAgICAgICAgdmFsdWU6IHkudmFsdWVzW3hJbmRleF0sXG4gICAgICAgICAgaXNTZWNvbmRhcnk6IGNoZWNrSWZTZWNvbmRhcnkoZGF0YSwgaSwgeEluZGV4KSxcbiAgICAgICAgfSkpLFxuICAgICAgICBwb3MueSxcbiAgICAgICAgc2NhbGUsXG4gICAgICApO1xuICAgICAgY29uc3QgeUluZGV4ID0gdmlzaWJsZUluZGljZXNbdmlzaWJsZVlJbmRleF07XG4gICAgICBjb25zdCB5cyA9IGRhdGEueXMubWFwKCh5LCBpKSA9PlxuICAgICAgICBzY2FsZSh5LnZhbHVlc1t4SW5kZXhdLCBjaGVja0lmU2Vjb25kYXJ5KGRhdGEsIGksIHhJbmRleCkpLFxuICAgICAgKTtcblxuICAgICAgY29uc3QgZm9ybWF0ID0gKGRhdGU6IERhdGUpID0+XG4gICAgICAgIGZvcm1hdGVkRGF0ZShjb25maWcuZGF0ZUZvcm1hdCB8fCAnZGF5JywgZGF0ZSk7XG5cbiAgICAgIC8vIENsYW1wIGluIGNoYXJ0LWxvY2FsIGNvb3JkaW5hdGVzIGZpcnN0IHNvIHRoZSB0b29sdGlwIHN0YXlzIHdpdGhpbiB0aGVcbiAgICAgIC8vIHZpc2libGUgY2hhcnQgYXJlYSwgdGhlbiB0cmFuc2xhdGUgdG8gdmlld3BvcnQgY29vcmRpbmF0ZXMgYnkgYWRkaW5nXG4gICAgICAvLyBwb3MucmVjdC54L3kgKHdoaWNoIGFyZSB2aWV3cG9ydC1yZWxhdGl2ZSBmcm9tIGdldEJvdW5kaW5nQ2xpZW50UmVjdCkuXG4gICAgICBjb25zdCBsb2NhbEFuY2hvclggPSB4IC0gcG9zLmNvbnRhaW5lclNjcm9sbFg7XG4gICAgICBjb25zdCBsb2NhbEFuY2hvclkgPSB5c1t2aXNpYmxlWUluZGV4XSAtIHBvcy5jb250YWluZXJTY3JvbGxZO1xuICAgICAgY29uc3QgeyBhbmNob3JYLCBhbmNob3JZIH0gPSBjaGVja0FuY2hvcnNBZ2FpbnN0Qm91bmQoXG4gICAgICAgIGxvY2FsQW5jaG9yWCxcbiAgICAgICAgbG9jYWxBbmNob3JZLFxuICAgICAgICBkaW1lbnNpb25zLFxuICAgICAgKTtcbiAgICAgIGNvbnN0IGFuY2hvciA9IG5ldyBET01SZWN0KFxuICAgICAgICBhbmNob3JYICsgcG9zLnJlY3QueCxcbiAgICAgICAgYW5jaG9yWSArIHBvcy5yZWN0LnksXG4gICAgICAgIFNNQUxMX1BBRERJTkcsXG4gICAgICAgIDAsXG4gICAgICApO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgaG92ZXJUeXBlOiAnc3RhbmRhcmQnLFxuICAgICAgICB4LFxuICAgICAgICB4SW5kZXgsXG4gICAgICAgIHlzLFxuICAgICAgICB5SW5kZXgsXG4gICAgICAgIHZpc2libGVZSW5kZXgsXG4gICAgICAgIHRvb2x0aXA6IHtcbiAgICAgICAgICBhbmNob3IsXG4gICAgICAgICAgZGF0ZTogZm9ybWF0KG5ldyBEYXRlKGRhdGEueFt4SW5kZXhdKSksXG4gICAgICAgICAgbWV0cmljczogZGF0YS55c1xuICAgICAgICAgICAgLm1hcCgoeSwgaW5kZXgpID0+ICh7XG4gICAgICAgICAgICAgIGNvbG9yOiBjb2xvcnNbaW5kZXggJSBjb2xvcnMubGVuZ3RoXSxcbiAgICAgICAgICAgICAgbGFiZWw6IHkubGFiZWwsXG4gICAgICAgICAgICAgIHBhdHRlcm46IHkucGF0dGVybixcbiAgICAgICAgICAgICAgdmFsdWU6XG4gICAgICAgICAgICAgICAgcGlwZVRyYW5zZm9ybShcbiAgICAgICAgICAgICAgICAgIHkudmFsdWVzW3hJbmRleF0sXG4gICAgICAgICAgICAgICAgICBjaGVja0lmU2Vjb25kYXJ5KGRhdGEsIGluZGV4LCB4SW5kZXgpLFxuICAgICAgICAgICAgICAgICAgdHJ1ZSxcbiAgICAgICAgICAgICAgICApID8/ICctJyxcbiAgICAgICAgICAgIH0pKVxuICAgICAgICAgICAgLmZpbHRlcigoXywgaSkgPT4gY29uZmlnLmdyb3VwZWRUb29sdGlwIHx8IGkgPT09IHZpc2libGVZSW5kZXgpLFxuICAgICAgICB9LFxuICAgICAgfTtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgY2hhcnRXaWR0aDogY2hhcnRTaXppbmdWYWx1ZXMudG90YWxXaWR0aCxcbiAgICAgIGNoYXJ0SGVpZ2h0OiBjaGFydFNpemluZ1ZhbHVlcy50b3RhbEhlaWdodCxcbiAgICAgIGNoYXJ0U2l6aW5nVmFsdWVzLFxuICAgICAgeFRpY2tzLFxuICAgICAgeVRpY2tzLFxuICAgICAgY29sb3JzLFxuICAgICAgbGluZXMsXG4gICAgICBjaXJjbGVzLFxuICAgICAgaG92ZXIsXG4gICAgICBiYXJzOiBbXSxcbiAgICAgIGFyZWFzOiBbXSxcbiAgICAgIGFyY3M6IFtdLFxuICAgICAgaG9yaXpvbnRhbEJhcnM6IFtdLFxuICAgICAgZGF0YUxhYmVscyxcbiAgICAgIHdhdGVyZmFsbExpbmVzOiBbXSxcbiAgICAgIGdyYWRpZW50czogW10sXG4gICAgICBmbG93Q29ubmVjdGlvbnM6IFtdLFxuICAgICAgaG9yaXpvbnRhbENvbnRhaW5lclNjYWxlOiBjaGFydFNpemluZ1ZhbHVlcy5ob3Jpem9udGFsQ29udGFpbmVyU2NhbGUsXG4gICAgICB2ZXJ0aWNhbENvbnRhaW5lclNjYWxlOiBjaGFydFNpemluZ1ZhbHVlcy52ZXJ0aWNhbENvbnRhaW5lclNjYWxlLFxuICAgICAgY2hhcnRFcnJvcjogbnVsbCxcbiAgICB9O1xuICB9XG5cbiAgZnVuY3Rpb24gYXJlYXMoXG4gICAgY29uZmlnOiBDb25maWdXaXRoRnVsbFNjYWxpbmcsXG4gICAgYWxsRGF0YTogSW5wdXREYXRhLFxuICAgIGRpbWVuc2lvbnM6IERpbWVuc2lvbnMsXG4gICk6IFJlbmRlcmVkQ2hhcnQge1xuICAgIGlmICghd2FybkZsb3dEYXRhKGFsbERhdGEsICdhcmVhJykpIHtcbiAgICAgIHJldHVybiB7IC4uLmVtcHR5Q2hhcnQsIGNoYXJ0RXJyb3I6ICdjb25maWcnIH07XG4gICAgfVxuICAgIGNvbnN0IHsgZGF0YTogdW5jaGVja2VkRGF0YSwgdmlzaWJsZUluZGljZXMgfSA9IGhpZGUoYWxsRGF0YSk7XG4gICAgaWYgKHVuY2hlY2tlZERhdGEudHlwZSA9PT0gJ2xhYmVsZWQnKSB7XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29uc29sZVxuICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICBcIkhlYWRzIHVwISBMYWJlbGVkIHNlcmllcyBhcmVuJ3QgY3VycmVudGx5IHN1cHBvcnRlZCBmb3IgYXJlYSBjaGFydHNcIixcbiAgICAgICk7XG4gICAgICByZXR1cm4gZW1wdHlDaGFydDtcbiAgICB9XG4gICAgaWYgKGNvbmZpZy5zaG93RGF0YUxhYmVscyA9PT0gdHJ1ZSkge1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgXCJIZWFkcyB1cCEgRGF0YSBsYWJlbHMgYXJlbid0IHN1cHBvcnRlZCBmb3IgYW55IHN0YWNrZWQgY2hhcnQgdHlwZVwiLFxuICAgICAgKTtcbiAgICAgIHJldHVybiBlbXB0eUNoYXJ0O1xuICAgIH1cbiAgICBpZiAoaGFzU3VwcGxlbWVudGFyeURhdGEodW5jaGVja2VkRGF0YSkpIHtcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgIFwiSGVhZHMgdXAhIFN1cHBsZW1lbnRhcnkgeSB2YWx1ZXMgYXJlbid0IHN1cHBvcnRlZCBmb3Igbm9uLWJhciBjaGFydHNcIixcbiAgICAgICk7XG4gICAgICByZXR1cm4gZW1wdHlDaGFydDtcbiAgICB9XG4gICAgd2FyblVuc3VwcG9ydGVkUGF0dGVybnModW5jaGVja2VkRGF0YSwgWydzdHJpcGVkJ10sICdhcmVhJyk7XG4gICAgLy9UaGlzIGFzc2lnbm1lbnQgbWFrZXMgdHlwZXNjcmlwdCByZWNvZ25pemUgdGhlIGFjdHVhbCB0eXBlIChUaW1lc2VyaWVzRGF0YSlcbiAgICBjb25zdCBkYXRhID0gdW5jaGVja2VkRGF0YTtcblxuICAgIGNvbnN0IHsgZGF0ZUZvcm1hdCwgcGlwZVRyYW5zZm9ybSwgY29sb3JzIH0gPSBnZXRGb3JtYXR0aW5nQW5kQ29sb3JzKFxuICAgICAgYWxsRGF0YSxcbiAgICAgIGRhdGEsXG4gICAgICBjb25maWcsXG4gICAgKTtcbiAgICBjb25zdCBjaGFydFNpemluZ1ZhbHVlcyA9IGdldEZ1bGxDaGFydFNjYWxlVmFsdWVzKFxuICAgICAgY29uZmlnLFxuICAgICAgZGF0YSxcbiAgICAgIGRpbWVuc2lvbnMsXG4gICAgICBwaXBlVHJhbnNmb3JtLFxuICAgICAgZGF0ZUZvcm1hdCxcbiAgICApO1xuICAgIGlmIChjaGFydFNpemluZ1ZhbHVlcyA9PT0gbnVsbCkge1xuICAgICAgcmV0dXJuIHsgLi4uZW1wdHlDaGFydCwgY2hhcnRFcnJvcjogJ3NpemluZycgfTtcbiAgICB9XG5cbiAgICBjb25zdCB0aWNrQ291bnQgPSBnZXRCdWNrZXRUaWNrQ291bnQoY2hhcnRTaXppbmdWYWx1ZXMpO1xuICAgIGNvbnN0IHhUaWNrcyA9IGdlbmVyYXRlVGltZXNlcmllc1RpY2tzKFxuICAgICAgZGF0YSxcbiAgICAgIGNvbmZpZyxcbiAgICAgIHRpY2tDb3VudCxcbiAgICAgIGNoYXJ0U2l6aW5nVmFsdWVzLFxuICAgICAgZGF0ZUZvcm1hdCxcbiAgICApLm1hcCh0aWNrID0+IHRvWFRpY2sodGljaykpO1xuICAgIGNvbnN0IHhTY2FsZSA9IChpbmRleDogbnVtYmVyKTogbnVtYmVyID0+IHtcbiAgICAgIHJldHVybiAoXG4gICAgICAgIGNoYXJ0U2l6aW5nVmFsdWVzLnRvdGFsTGVmdE9mZnNldCArIGNoYXJ0U2l6aW5nVmFsdWVzLmJ1Y2tldEdhcCAqIGluZGV4XG4gICAgICApO1xuICAgIH07XG4gICAgY29uc3QgeyBzY2FsZSwgdGlja3M6IGRhdGFUaWNrcyB9ID0gY2FsY0RhdGFBeGlzU2NhbGVzQW5kVGlja3MoXG4gICAgICBkYXRhLFxuICAgICAgcGlwZVRyYW5zZm9ybSxcbiAgICAgIGNvbmZpZyxcbiAgICAgIGNoYXJ0U2l6aW5nVmFsdWVzLFxuICAgICk7XG4gICAgY29uc3QgeVRpY2tzID0gZGF0YVRpY2tzLm1hcCh0aWNrID0+IHRvWVRpY2sodGljaykpO1xuICAgIGNvbnN0IHplcm9BeGlzUG9zVmFsID0gc2NhbGUoMCwgdHJ1ZSk7XG5cbiAgICBjb25zdCBpbmRpY2VzID0gZGF0YS54Lm1hcCgoXywgaSkgPT4gaSk7XG4gICAgY29uc3QgYXJlYXMgPSBkYXRhLnlzLm1hcCgoeSwgeUluZGV4KSA9PiAoe1xuICAgICAgcGF0dGVybjogeS5wYXR0ZXJuLFxuICAgICAgYXJlYTogYXJlYTxudW1iZXI+KFxuICAgICAgICBpID0+IHhTY2FsZShpKSxcbiAgICAgICAgaSA9PiBnZXRCYXJZSW5mbyhkYXRhLCBjb25maWcsIHlJbmRleCwgaSwgc2NhbGUpLnlWYWx1ZSxcbiAgICAgICAgaSA9PlxuICAgICAgICAgIGdldEJhcllJbmZvKGRhdGEsIGNvbmZpZywgeUluZGV4LCBpLCBzY2FsZSkueVZhbHVlICtcbiAgICAgICAgICBnZXRCYXJZSW5mbyhkYXRhLCBjb25maWcsIHlJbmRleCwgaSwgc2NhbGUpLmhlaWdodCxcbiAgICAgICkoaW5kaWNlcyksXG4gICAgfSkpO1xuXG4gICAgZnVuY3Rpb24gaG92ZXIocG9zOiB7XG4gICAgICByZWN0OiBET01SZWN0O1xuICAgICAgeDogbnVtYmVyO1xuICAgICAgeTogbnVtYmVyO1xuICAgICAgY29udGFpbmVyU2Nyb2xsWDogbnVtYmVyO1xuICAgICAgY29udGFpbmVyU2Nyb2xsWTogbnVtYmVyO1xuICAgIH0pOiBIb3ZlclJldHVybiB7XG4gICAgICBjb25zdCByZWFsUG9zWCA9IHBvcy54ICsgcG9zLmNvbnRhaW5lclNjcm9sbFg7XG4gICAgICBjb25zdCByZWFsUG9zWSA9IHBvcy55ICsgcG9zLmNvbnRhaW5lclNjcm9sbFk7XG4gICAgICBpZiAoXG4gICAgICAgIGNoYXJ0U2l6aW5nVmFsdWVzID09PSBudWxsIHx8XG4gICAgICAgIGdldElmSG92ZXJPdXRPZkJvdW5kcyhcbiAgICAgICAgICBwb3MueCxcbiAgICAgICAgICBwb3MueSxcbiAgICAgICAgICByZWFsUG9zWCxcbiAgICAgICAgICByZWFsUG9zWSxcbiAgICAgICAgICBjaGFydFNpemluZ1ZhbHVlcyxcbiAgICAgICAgICBkaW1lbnNpb25zLFxuICAgICAgICApXG4gICAgICApIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHhIb3ZlckluZGljZXMgPSBnZXRCdWNrZXRBbmRDbHVzdGVyTnVtRm9ySG92ZXIoXG4gICAgICAgIHJlYWxQb3NYLFxuICAgICAgICBjaGFydFNpemluZ1ZhbHVlcyxcbiAgICAgICAgZGF0YSxcbiAgICAgICAgY29uZmlnLFxuICAgICAgICBkYXRhLngubGVuZ3RoLFxuICAgICAgKTtcbiAgICAgIGlmICgheEhvdmVySW5kaWNlcykge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHsgYnVja2V0TnVtOiB4SW5kZXggfSA9IHhIb3ZlckluZGljZXM7XG4gICAgICBjb25zdCB4ID0geFNjYWxlKHhJbmRleCk7XG4gICAgICBjb25zdCBmdWxsWXMgPSBkYXRhLnlzLm1hcCgoXywgbWFwWUluZGV4KSA9PlxuICAgICAgICBnZXRCYXJZSW5mbyhkYXRhLCBjb25maWcsIG1hcFlJbmRleCwgeEluZGV4LCBzY2FsZSksXG4gICAgICApO1xuICAgICAgY29uc3QgeXMgPSBmdWxsWXMubWFwKHkgPT4geS55VmFsdWUpO1xuICAgICAgLy9UaGlzIGlzIHRoZSB5cyBhcnJheSwgYnV0IHNoaWZ0ZWQgc28gdGhhdCB0aGUgeSBwb3NpdGlvbiBmb3IgbmVnYXRpdmUgdmFsdWVzIGlzIGF3YXkgZnJvbSB0aGUgYXhpcyAoZm9yIHRoZSBob3ZlciBjaXJjbGVzKVxuICAgICAgY29uc3Qgc2hpZnRlZFlzID0gZnVsbFlzLm1hcCh5ID0+IHtcbiAgICAgICAgaWYgKHkueVZhbHVlID49IHplcm9BeGlzUG9zVmFsKSB7XG4gICAgICAgICAgcmV0dXJuIHkueVZhbHVlICsgeS5oZWlnaHQ7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHkueVZhbHVlO1xuICAgICAgfSk7XG4gICAgICBjb25zdCB5UG9zU2lnbiA9IHplcm9BeGlzUG9zVmFsIC0gcG9zLnk7XG4gICAgICBsZXQgdmlzaWJsZVlJbmRleCA9IC0xO1xuICAgICAgaWYgKHlQb3NTaWduIDwgMCAmJiBkYXRhLnlzLmZpbmQoeSA9PiB5LnZhbHVlcy5maW5kKHZhbCA9PiB2YWwgPCAwKSkpIHtcbiAgICAgICAgZm9yIChsZXQgaSA9IHlzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgICAgaWYgKHlzW2ldID49IHplcm9BeGlzUG9zVmFsICYmIHlzW2ldIDwgcG9zLnkpIHtcbiAgICAgICAgICAgIHZpc2libGVZSW5kZXggPSBpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHlzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgaWYgKHlzW2ldIDw9IHplcm9BeGlzUG9zVmFsICYmIHlzW2ldIDwgcG9zLnkpIHtcbiAgICAgICAgICAgIHZpc2libGVZSW5kZXggPSBpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAodmlzaWJsZVlJbmRleCA9PT0gLTEpIHtcbiAgICAgICAgaWYgKHBvcy55IDw9IHplcm9BeGlzUG9zVmFsKSB7XG4gICAgICAgICAgdmlzaWJsZVlJbmRleCA9IHlzLmluZGV4T2YoTWF0aC5taW4oLi4ueXMpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB2aXNpYmxlWUluZGV4ID0geXMuaW5kZXhPZihNYXRoLm1heCguLi55cykpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBjb25zdCB5SW5kZXggPSB2aXNpYmxlSW5kaWNlc1t2aXNpYmxlWUluZGV4XTtcbiAgICAgIGNvbnN0IGxvY2FsQW5jaG9yWCA9IHggLSBwb3MuY29udGFpbmVyU2Nyb2xsWDtcbiAgICAgIGNvbnN0IGxvY2FsQW5jaG9yWSA9IHlzW3Zpc2libGVZSW5kZXhdIC0gcG9zLmNvbnRhaW5lclNjcm9sbFk7XG4gICAgICBjb25zdCB7IGFuY2hvclgsIGFuY2hvclkgfSA9IGNoZWNrQW5jaG9yc0FnYWluc3RCb3VuZChcbiAgICAgICAgbG9jYWxBbmNob3JYLFxuICAgICAgICBsb2NhbEFuY2hvclksXG4gICAgICAgIGRpbWVuc2lvbnMsXG4gICAgICApO1xuICAgICAgY29uc3QgYW5jaG9yID0gbmV3IERPTVJlY3QoXG4gICAgICAgIGFuY2hvclggKyBwb3MucmVjdC54LFxuICAgICAgICBhbmNob3JZICsgcG9zLnJlY3QueSxcbiAgICAgICAgU01BTExfUEFERElORyxcbiAgICAgICAgMCxcbiAgICAgICk7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBob3ZlclR5cGU6ICdzdGFuZGFyZCcsXG4gICAgICAgIHgsXG4gICAgICAgIHhJbmRleCxcbiAgICAgICAgeXM6IHNoaWZ0ZWRZcyxcbiAgICAgICAgeUluZGV4LFxuICAgICAgICB2aXNpYmxlWUluZGV4LFxuICAgICAgICB0b29sdGlwOiB7XG4gICAgICAgICAgYW5jaG9yLFxuICAgICAgICAgIGRhdGU6IHV0Y0Zvcm1hdCgnJUIgJWQsICVZJykobmV3IERhdGUoZGF0YS54W3hJbmRleF0pKSxcbiAgICAgICAgICBtZXRyaWNzOiBkYXRhLnlzXG4gICAgICAgICAgICAubWFwKCh5LCBpbmRleCkgPT4gKHtcbiAgICAgICAgICAgICAgY29sb3I6IGNvbG9yc1tpbmRleCAlIGNvbG9ycy5sZW5ndGhdLFxuICAgICAgICAgICAgICBsYWJlbDogeS5sYWJlbCxcbiAgICAgICAgICAgICAgcGF0dGVybjogeS5wYXR0ZXJuLFxuICAgICAgICAgICAgICB2YWx1ZTogcGlwZVRyYW5zZm9ybShcbiAgICAgICAgICAgICAgICB5LnZhbHVlc1t4SW5kZXhdLFxuICAgICAgICAgICAgICAgIGNoZWNrSWZTZWNvbmRhcnkoZGF0YSwgaW5kZXgsIHhJbmRleCksXG4gICAgICAgICAgICAgICAgdHJ1ZSxcbiAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgIH0pKVxuICAgICAgICAgICAgLmZpbHRlcigoXywgaSkgPT4gY29uZmlnLmdyb3VwZWRUb29sdGlwIHx8IGkgPT09IHZpc2libGVZSW5kZXgpLFxuICAgICAgICB9LFxuICAgICAgfTtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgY2hhcnRXaWR0aDogY2hhcnRTaXppbmdWYWx1ZXMudG90YWxXaWR0aCxcbiAgICAgIGNoYXJ0SGVpZ2h0OiBjaGFydFNpemluZ1ZhbHVlcy50b3RhbEhlaWdodCxcbiAgICAgIGNoYXJ0U2l6aW5nVmFsdWVzLFxuICAgICAgeFRpY2tzLFxuICAgICAgeVRpY2tzLFxuICAgICAgY29sb3JzLFxuICAgICAgYXJlYXMsXG4gICAgICBsaW5lczogW10sXG4gICAgICBjaXJjbGVzOiBbXSxcbiAgICAgIGhvdmVyLFxuICAgICAgYmFyczogW10sXG4gICAgICBhcmNzOiBbXSxcbiAgICAgIGhvcml6b250YWxCYXJzOiBbXSxcbiAgICAgIGRhdGFMYWJlbHM6IFtdLFxuICAgICAgd2F0ZXJmYWxsTGluZXM6IFtdLFxuICAgICAgZ3JhZGllbnRzOiBbXSxcbiAgICAgIGZsb3dDb25uZWN0aW9uczogW10sXG4gICAgICBob3Jpem9udGFsQ29udGFpbmVyU2NhbGU6IGNoYXJ0U2l6aW5nVmFsdWVzLmhvcml6b250YWxDb250YWluZXJTY2FsZSxcbiAgICAgIHZlcnRpY2FsQ29udGFpbmVyU2NhbGU6IGNoYXJ0U2l6aW5nVmFsdWVzLnZlcnRpY2FsQ29udGFpbmVyU2NhbGUsXG4gICAgICBjaGFydEVycm9yOiBudWxsLFxuICAgIH07XG4gIH1cblxuICBmdW5jdGlvbiBiYXJzKFxuICAgIGNvbmZpZzogQ29uZmlnV2l0aEZ1bGxTY2FsaW5nLFxuICAgIGFsbERhdGE6IElucHV0RGF0YSxcbiAgICBkaW1lbnNpb25zOiBEaW1lbnNpb25zLFxuICApOiBSZW5kZXJlZENoYXJ0IHtcbiAgICBpZiAoIXdhcm5GbG93RGF0YShhbGxEYXRhLCAnYmFyJykpIHtcbiAgICAgIHJldHVybiB7IC4uLmVtcHR5Q2hhcnQsIGNoYXJ0RXJyb3I6ICdjb25maWcnIH07XG4gICAgfVxuICAgIGNvbnN0IHsgZGF0YSwgdmlzaWJsZUluZGljZXMsIHZpc2libGVTdXBwSW5kaWNlcyB9ID0gaGlkZShhbGxEYXRhKTtcbiAgICBpZiAoXG4gICAgICBjb25maWcuc2hvd0RhdGFMYWJlbHMgPT09IHRydWUgJiZcbiAgICAgIGlzU3RhY2tlZERhdGEoY29uZmlnKSAmJlxuICAgICAgIWlzR3JvdXBpbmdUeXBlRXhjZXB0aW9uKGRhdGEsIGNvbmZpZylcbiAgICApIHtcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgIFwiSGVhZHMgdXAhIERhdGEgbGFiZWxzIGFyZW4ndCBzdXBwb3J0ZWQgZm9yIGFueSBzdGFja2VkIGNoYXJ0IHR5cGVcIixcbiAgICAgICk7XG4gICAgICByZXR1cm4gZW1wdHlDaGFydDtcbiAgICB9XG4gICAgaWYgKFxuICAgICAgaGFzU3VwcGxlbWVudGFyeURhdGEoZGF0YSkgJiZcbiAgICAgIGlzQ2x1c3RlcmVkRGF0YShkYXRhLCBjb25maWcsIGZhbHNlKSAmJlxuICAgICAgIWlzR3JvdXBpbmdUeXBlRXhjZXB0aW9uKGRhdGEsIGNvbmZpZylcbiAgICApIHtcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgIFwiSGVhZHMgdXAhIFN1cHBsZW1lbnRhcnkgeSB2YWx1ZXMgYXJlbid0IHN1cHBvcnRlZCBmb3IgY2x1c3RlcmVkIGRhdGEgKGp1c3QgdXNlIGFub3RoZXIgbm9ybWFsIHkgc2VyaWVzKVwiLFxuICAgICAgKTtcbiAgICAgIHJldHVybiBlbXB0eUNoYXJ0O1xuICAgIH1cbiAgICByZXR1cm4gYmFyc0hlbHBlcihcbiAgICAgIGNvbmZpZyxcbiAgICAgIGFsbERhdGEsXG4gICAgICBkYXRhLFxuICAgICAgdmlzaWJsZUluZGljZXMsXG4gICAgICB2aXNpYmxlU3VwcEluZGljZXMsXG4gICAgICBkaW1lbnNpb25zLFxuICAgICAgZmFsc2UsXG4gICAgICBmYWxzZSxcbiAgICApO1xuICB9XG5cbiAgZnVuY3Rpb24gZnVubmVsKFxuICAgIGNvbmZpZzogQ29uZmlnV2l0aEZ1bGxTY2FsaW5nLFxuICAgIGFsbERhdGE6IElucHV0RGF0YSxcbiAgICBkaW1lbnNpb25zOiBEaW1lbnNpb25zLFxuICApOiBSZW5kZXJlZENoYXJ0IHtcbiAgICBpZiAoIXdhcm5GbG93RGF0YShhbGxEYXRhLCAnZnVubmVsJykpIHtcbiAgICAgIHJldHVybiB7IC4uLmVtcHR5Q2hhcnQsIGNoYXJ0RXJyb3I6ICdjb25maWcnIH07XG4gICAgfVxuICAgIGNvbnN0IHsgZGF0YSwgdmlzaWJsZUluZGljZXMsIHZpc2libGVTdXBwSW5kaWNlcyB9ID0gaGlkZShhbGxEYXRhKTtcbiAgICByZXR1cm4gYmFyc0hlbHBlcihcbiAgICAgIGNvbmZpZyxcbiAgICAgIGFsbERhdGEsXG4gICAgICBkYXRhLFxuICAgICAgdmlzaWJsZUluZGljZXMsXG4gICAgICB2aXNpYmxlU3VwcEluZGljZXMsXG4gICAgICBkaW1lbnNpb25zLFxuICAgICAgdHJ1ZSxcbiAgICAgIGZhbHNlLFxuICAgICk7XG4gIH1cblxuICBmdW5jdGlvbiB3YXRlcmZhbGwoXG4gICAgY29uZmlnOiBDb25maWdXaXRoRnVsbFNjYWxpbmcsXG4gICAgYWxsRGF0YTogSW5wdXREYXRhLFxuICAgIGRpbWVuc2lvbnM6IERpbWVuc2lvbnMsXG4gICk6IFJlbmRlcmVkQ2hhcnQge1xuICAgIGlmICghd2FybkZsb3dEYXRhKGFsbERhdGEsICd3YXRlcmZhbGwnKSkge1xuICAgICAgcmV0dXJuIHsgLi4uZW1wdHlDaGFydCwgY2hhcnRFcnJvcjogJ2NvbmZpZycgfTtcbiAgICB9XG4gICAgY29uc3QgeyBkYXRhOiB1bmNoZWNrZWREYXRhLCB2aXNpYmxlSW5kaWNlcyB9ID0gaGlkZShhbGxEYXRhKTtcbiAgICBpZiAoaGFzU3VwcGxlbWVudGFyeURhdGEodW5jaGVja2VkRGF0YSkpIHtcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgIFwiSGVhZHMgdXAhIFN1cHBsZW1lbnRhcnkgeSB2YWx1ZXMgYXJlbid0IHN1cHBvcnRlZCBmb3Igbm9uLWJhciBjaGFydHNcIixcbiAgICAgICk7XG4gICAgICByZXR1cm4gZW1wdHlDaGFydDtcbiAgICB9XG4gICAgaWYgKGNvbmZpZy5zZWNvbmRhcnlWYWx1ZVR5cGUpIHtcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgICdIZWFkcyB1cCEgV2F0ZXJmYWxsIGNoYXJ0cyBkbyBub3QgY3VycmVudGx5IGhhdmUgdHdvLWF4aXMgc3VwcG9ydCcsXG4gICAgICApO1xuICAgICAgcmV0dXJuIGVtcHR5Q2hhcnQ7XG4gICAgfVxuICAgIHdhcm5VbnN1cHBvcnRlZFBhdHRlcm5zKHVuY2hlY2tlZERhdGEsIFtdLCAnd2F0ZXJmYWxsJyk7XG5cbiAgICByZXR1cm4gYmFyc0hlbHBlcihcbiAgICAgIGNvbmZpZyxcbiAgICAgIGFsbERhdGEsXG4gICAgICB1bmNoZWNrZWREYXRhLFxuICAgICAgdmlzaWJsZUluZGljZXMsXG4gICAgICBbXSxcbiAgICAgIGRpbWVuc2lvbnMsXG4gICAgICBmYWxzZSxcbiAgICAgIHRydWUsXG4gICAgKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGJhcnNIZWxwZXIoXG4gICAgY29uZmlnOiBDb25maWdXaXRoRnVsbFNjYWxpbmcsXG4gICAgYWxsRGF0YTogTm9uRmxvd0RhdGEsXG4gICAgdW5jaGVja2VkRGF0YTogTm9uRmxvd0RhdGEsXG4gICAgdmlzaWJsZUluZGljZXM6IG51bWJlcltdLFxuICAgIHZpc2libGVTdXBwSW5kaWNlczogbnVtYmVyW10sXG4gICAgZGltZW5zaW9uczogRGltZW5zaW9ucyxcbiAgICBpc0Z1bm5lbDogYm9vbGVhbixcbiAgICBpc1dhdGVyZmFsbDogYm9vbGVhbixcbiAgKTogUmVuZGVyZWRDaGFydCB7XG4gICAgY29uc3QgeyBkYXRlRm9ybWF0LCBwaXBlVHJhbnNmb3JtLCBjb2xvckluZGljZXMsIGNvbG9ycyB9ID1cbiAgICAgIGdldEZvcm1hdHRpbmdBbmRDb2xvcnMoYWxsRGF0YSwgdW5jaGVja2VkRGF0YSwgY29uZmlnKTtcbiAgICBjb25zdCB3YXRlcmZhbGxEYXRhID0gd2F0ZXJmYWxsVHJhbnNmb3JtKHVuY2hlY2tlZERhdGEsIGlzV2F0ZXJmYWxsKTtcbiAgICBjb25zdCBkYXRhID0gaXNXYXRlcmZhbGwgPyB3YXRlcmZhbGxEYXRhLmRhdGEgOiB1bmNoZWNrZWREYXRhO1xuXG4gICAgY29uc3QgY2hhcnRTaXppbmdWYWx1ZXMgPSBnZXRGdWxsQ2hhcnRTY2FsZVZhbHVlcyhcbiAgICAgIGNvbmZpZyxcbiAgICAgIGRhdGEsXG4gICAgICBkaW1lbnNpb25zLFxuICAgICAgcGlwZVRyYW5zZm9ybSxcbiAgICAgIGRhdGVGb3JtYXQsXG4gICAgKTtcbiAgICBpZiAoY2hhcnRTaXppbmdWYWx1ZXMgPT09IG51bGwpIHtcbiAgICAgIHJldHVybiB7IC4uLmVtcHR5Q2hhcnQsIGNoYXJ0RXJyb3I6ICdzaXppbmcnIH07XG4gICAgfVxuXG4gICAgY29uc3QgdGlja0NvdW50ID0gZ2V0QnVja2V0VGlja0NvdW50KGNoYXJ0U2l6aW5nVmFsdWVzKTtcbiAgICBjb25zdCB4VGlja3MgPSAoXG4gICAgICBkYXRhLnR5cGUgPT09ICdsYWJlbGVkJ1xuICAgICAgICA/IGdlbmVyYXRlTGFiZWxsZWRUaWNrcyhkYXRhLCBjb25maWcsIHRpY2tDb3VudCwgY2hhcnRTaXppbmdWYWx1ZXMpXG4gICAgICAgIDogZ2VuZXJhdGVUaW1lc2VyaWVzVGlja3MoXG4gICAgICAgICAgICBkYXRhLFxuICAgICAgICAgICAgY29uZmlnLFxuICAgICAgICAgICAgdGlja0NvdW50LFxuICAgICAgICAgICAgY2hhcnRTaXppbmdWYWx1ZXMsXG4gICAgICAgICAgICBkYXRlRm9ybWF0LFxuICAgICAgICAgIClcbiAgICApLm1hcCh0aWNrID0+IHRvWFRpY2sodGljaykpO1xuICAgIGNvbnN0IHsgc2NhbGUsIHRpY2tzOiBkYXRhVGlja3MgfSA9IGNhbGNEYXRhQXhpc1NjYWxlc0FuZFRpY2tzKFxuICAgICAgZGF0YSxcbiAgICAgIHBpcGVUcmFuc2Zvcm0sXG4gICAgICBjb25maWcsXG4gICAgICBjaGFydFNpemluZ1ZhbHVlcyxcbiAgICApO1xuICAgIGNvbnN0IHlUaWNrcyA9IGRhdGFUaWNrcy5tYXAodGljayA9PiB0b1lUaWNrKHRpY2spKTtcbiAgICBjb25zdCB6ZXJvQXhpc1Bvc1ZhbCA9IHNjYWxlKDAsIHRydWUpO1xuXG4gICAgY29uc3QgZ3JhZGllbnRzOiBSZWN0W11bXSA9IFtdO1xuICAgIGNvbnN0IGJhcnM6IFJlY3RbXVtdID0gZGF0YS55cy5tYXAoKHksIHlJbmRleCkgPT4ge1xuICAgICAgY29uc3QgaW5kU2VyaWVzR3JhZGllbnRzOiBSZWN0W10gPSBbXTtcbiAgICAgIGNvbnN0IGluZFNlcmllc0JhcnMgPSB5LnZhbHVlcy5tYXAoKF8sIGluZGV4KSA9PiB7XG4gICAgICAgIGNvbnN0IHsgeVZhbHVlLCBoZWlnaHQgfSA9IGdldEJhcllJbmZvKFxuICAgICAgICAgIGRhdGEsXG4gICAgICAgICAgY29uZmlnLFxuICAgICAgICAgIHlJbmRleCxcbiAgICAgICAgICBpbmRleCxcbiAgICAgICAgICBzY2FsZSxcbiAgICAgICAgKTtcbiAgICAgICAgY29uc3QgeFZhbHVlID0gY2FsY3VsYXRlQmFyUG9zaXRpb24oXG4gICAgICAgICAgZGF0YSxcbiAgICAgICAgICBjb25maWcsXG4gICAgICAgICAgY2hhcnRTaXppbmdWYWx1ZXMsXG4gICAgICAgICAgaW5kZXgsXG4gICAgICAgICAgaXNDbHVzdGVyZWREYXRhKGRhdGEsIGNvbmZpZywgZmFsc2UpID8geUluZGV4IDogMCxcbiAgICAgICAgKTtcbiAgICAgICAgaWYgKGlzRnVubmVsKSB7XG4gICAgICAgICAgLy9UaGUgZW1wdHkgZ3JhZGllbnQgc3RpbGwgbmVlZHMgdG8gYmUgaW5zZXJ0ZWQgdG8ga2VlcCBkYXRhIGFsaWduZWRcbiAgICAgICAgICBpZiAoaW5kZXggPT09IDApIHtcbiAgICAgICAgICAgIGluZFNlcmllc0dyYWRpZW50cy5wdXNoKHtcbiAgICAgICAgICAgICAgZWxlbWVudFR5cGU6ICdyZWN0JyxcbiAgICAgICAgICAgICAgeDogMCxcbiAgICAgICAgICAgICAgeTogMCxcbiAgICAgICAgICAgICAgd2lkdGg6IDAsXG4gICAgICAgICAgICAgIGhlaWdodDogMCxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zdCB7IHlWYWx1ZTogcHJldkJhcllWYWwgfSA9IGdldEJhcllJbmZvKFxuICAgICAgICAgICAgICBkYXRhLFxuICAgICAgICAgICAgICBjb25maWcsXG4gICAgICAgICAgICAgIHlJbmRleCxcbiAgICAgICAgICAgICAgaW5kZXggLSAxLFxuICAgICAgICAgICAgICBzY2FsZSxcbiAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgIGluZFNlcmllc0dyYWRpZW50cy5wdXNoKHtcbiAgICAgICAgICAgICAgZWxlbWVudFR5cGU6ICdyZWN0JyxcbiAgICAgICAgICAgICAgeDogeFZhbHVlLFxuICAgICAgICAgICAgICB5OiBwcmV2QmFyWVZhbCxcbiAgICAgICAgICAgICAgd2lkdGg6IGNoYXJ0U2l6aW5nVmFsdWVzLmJhclNpemUsXG4gICAgICAgICAgICAgIGhlaWdodDogTWF0aC5tYXgoeVZhbHVlIC0gcHJldkJhcllWYWwsIDApLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgYmFyOiBSZWN0ID0ge1xuICAgICAgICAgIGVsZW1lbnRUeXBlOiAncmVjdCcsXG4gICAgICAgICAgeDogeFZhbHVlLFxuICAgICAgICAgIHk6IHlWYWx1ZSxcbiAgICAgICAgICB3aWR0aDogY2hhcnRTaXppbmdWYWx1ZXMuYmFyU2l6ZSxcbiAgICAgICAgICBoZWlnaHQsXG4gICAgICAgICAgb2Zmc2V0OiAwLFxuICAgICAgICAgIHBhdHRlcm46IHkucGF0dGVybixcbiAgICAgICAgfTtcbiAgICAgICAgcmV0dXJuIGJhcjtcbiAgICAgIH0pO1xuICAgICAgZ3JhZGllbnRzLnB1c2goaW5kU2VyaWVzR3JhZGllbnRzKTtcbiAgICAgIHJldHVybiBpbmRTZXJpZXNCYXJzO1xuICAgIH0pO1xuICAgIGxldCBzdXBwQmFyczogUmVjdFtdW10gPSBbXTtcbiAgICBpZiAoaGFzU3VwcGxlbWVudGFyeURhdGEoZGF0YSkpIHtcbiAgICAgIHN1cHBCYXJzID0gZGF0YS5zdXBwbGVtZW50YXJ5WXMubWFwKCh5LCB5SW5kZXgpID0+XG4gICAgICAgIHkudmFsdWVzLm1hcCgoXywgaW5kZXgpID0+IHtcbiAgICAgICAgICBjb25zdCB7IHlWYWx1ZSwgaGVpZ2h0IH0gPSBnZXRCYXJZSW5mbyhcbiAgICAgICAgICAgIGRhdGEsXG4gICAgICAgICAgICBjb25maWcsXG4gICAgICAgICAgICB5SW5kZXgsXG4gICAgICAgICAgICBpbmRleCxcbiAgICAgICAgICAgIHNjYWxlLFxuICAgICAgICAgICAgdHJ1ZSxcbiAgICAgICAgICApO1xuICAgICAgICAgIGNvbnN0IHhWYWx1ZSA9IGNhbGN1bGF0ZUJhclBvc2l0aW9uKFxuICAgICAgICAgICAgZGF0YSxcbiAgICAgICAgICAgIGNvbmZpZyxcbiAgICAgICAgICAgIGNoYXJ0U2l6aW5nVmFsdWVzLFxuICAgICAgICAgICAgaW5kZXgsXG4gICAgICAgICAgICB5LnN1cHBsZW1lbnRhbEluZGV4ICsgMSxcbiAgICAgICAgICApO1xuICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBlbGVtZW50VHlwZTogJ3JlY3QnLFxuICAgICAgICAgICAgeDogeFZhbHVlLFxuICAgICAgICAgICAgeTogeVZhbHVlLFxuICAgICAgICAgICAgd2lkdGg6IGNoYXJ0U2l6aW5nVmFsdWVzLmJhclNpemUsXG4gICAgICAgICAgICBoZWlnaHQsXG4gICAgICAgICAgICBvZmZzZXQ6IDAsXG4gICAgICAgICAgICBwYXR0ZXJuOiB5LnBhdHRlcm4sXG4gICAgICAgICAgfTtcbiAgICAgICAgfSksXG4gICAgICApO1xuICAgICAgYmFycy5wdXNoKC4uLnN1cHBCYXJzKTtcbiAgICAgIGNvbG9ycy5wdXNoKFxuICAgICAgICAuLi5kYXRhLnN1cHBsZW1lbnRhcnlZcy5tYXAoeSA9PlxuICAgICAgICAgIGdldENvbG9yKHksIGNvbG9ySW5kaWNlcywgY29uZmlnLmNvbG9ycyksXG4gICAgICAgICksXG4gICAgICApO1xuICAgIH1cblxuICAgIGNvbnN0IHdhdGVyZmFsbExpbmVzOiB7XG4gICAgICB4MTogbnVtYmVyO1xuICAgICAgeDI6IG51bWJlcjtcbiAgICAgIHkxOiBudW1iZXI7XG4gICAgICB5MjogbnVtYmVyO1xuICAgIH1bXSA9IFtdO1xuICAgIGlmIChpc1dhdGVyZmFsbCkge1xuICAgICAgLy9Nb3ZlIGJhcnMgYmFzZWQgb24gaGVpZ2h0IG9mIHByZXZpb3VzIGJhcnMgKGV4Y2VwdCB0aGUgdG90YWwgYmFyKVxuICAgICAgbGV0IGJhck9mZnNldFJ1bm5pbmdUb3RhbCA9IDA7XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGRhdGEueC5sZW5ndGggLSAxOyBpKyspIHtcbiAgICAgICAgbGV0IGJhck9mZnNldENoYW5nZSA9IDA7XG4gICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgYmFycy5sZW5ndGg7IGorKykge1xuICAgICAgICAgIGNvbnN0IGJhcklzTmVnYXRpdmUgPVxuICAgICAgICAgICAgYmFyc1tqXVtpXS55ID49IHplcm9BeGlzUG9zVmFsICYmIGJhcnNbal1baV0uaGVpZ2h0ID4gMDtcbiAgICAgICAgICBpZiAoYmFySXNOZWdhdGl2ZSkge1xuICAgICAgICAgICAgYmFyT2Zmc2V0Q2hhbmdlIC09IGJhcnNbal1baV0uaGVpZ2h0O1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBiYXJPZmZzZXRDaGFuZ2UgKz0gYmFyc1tqXVtpXS5oZWlnaHQ7XG4gICAgICAgICAgfVxuICAgICAgICAgIGJhcnNbal1baV0ub2Zmc2V0ID0gYmFyT2Zmc2V0UnVubmluZ1RvdGFsO1xuICAgICAgICAgIGJhcnNbal1baV0ueSAtPSBiYXJPZmZzZXRSdW5uaW5nVG90YWw7XG4gICAgICAgICAgaWYgKGogPT09IGJhcnMubGVuZ3RoIC0gMSkge1xuICAgICAgICAgICAgY29uc3QgeDEgPSBiYXJzW2pdW2ldLnggKyBiYXJzW2JhcnMubGVuZ3RoIC0gMV1baV0ud2lkdGg7XG4gICAgICAgICAgICBjb25zdCB5MSA9IGJhcnNbal1baV0ueSArIChiYXJJc05lZ2F0aXZlID8gYmFyc1tqXVtpXS5oZWlnaHQgOiAwKTtcbiAgICAgICAgICAgIGNvbnN0IHgyID0gYmFyc1tqXVtpICsgMV0ueDtcbiAgICAgICAgICAgIGNvbnN0IHkyID0geTE7XG4gICAgICAgICAgICB3YXRlcmZhbGxMaW5lcy5wdXNoKHtcbiAgICAgICAgICAgICAgeDEsXG4gICAgICAgICAgICAgIHkxLFxuICAgICAgICAgICAgICB4MixcbiAgICAgICAgICAgICAgeTIsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgYmFyT2Zmc2V0UnVubmluZ1RvdGFsICs9IGJhck9mZnNldENoYW5nZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBkYXRhTGFiZWxzOiBEYXRhTGFiZWxbXSA9IGRhdGEueXMuZmxhdE1hcCgoeSwgeUluZGV4KSA9PiB7XG4gICAgICBjb25zdCBzdWJMYWJlbHM6IERhdGFMYWJlbFtdID0geS52YWx1ZXMubWFwKCh2YWwsIHhJbmRleCkgPT4ge1xuICAgICAgICBjb25zdCBpc05lZ2F0aXZlQmFyID1cbiAgICAgICAgICBiYXJzW3lJbmRleF1beEluZGV4XS55ID49IHplcm9BeGlzUG9zVmFsICYmXG4gICAgICAgICAgYmFyc1t5SW5kZXhdW3hJbmRleF0uaGVpZ2h0ID4gMDtcbiAgICAgICAgY29uc3QgeU9mZnNldCA9IGlzTmVnYXRpdmVCYXJcbiAgICAgICAgICA/IGNoYXJ0U2l6aW5nVmFsdWVzLmRhdGFMYWJlbFBhZGRpbmcgK1xuICAgICAgICAgICAgY2hhcnRTaXppbmdWYWx1ZXMuZGF0YUxhYmVsVGV4dFNpemUgK1xuICAgICAgICAgICAgYmFyc1t5SW5kZXhdW3hJbmRleF0uaGVpZ2h0XG4gICAgICAgICAgOiAtY2hhcnRTaXppbmdWYWx1ZXMuZGF0YUxhYmVsUGFkZGluZztcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBlbGVtZW50VHlwZTogJ2RhdGFMYWJlbCcsXG4gICAgICAgICAgbGFiZWw6XG4gICAgICAgICAgICBwaXBlVHJhbnNmb3JtKHZhbCwgY2hlY2tJZlNlY29uZGFyeShkYXRhLCB5SW5kZXgsIHhJbmRleCkpID8/ICcnLFxuICAgICAgICAgIHlQb3M6XG4gICAgICAgICAgICAoaXNGdW5uZWwgJiYgZ3JhZGllbnRzW3lJbmRleF1beEluZGV4XS5oZWlnaHQgIT09IDBcbiAgICAgICAgICAgICAgPyBncmFkaWVudHNbeUluZGV4XVt4SW5kZXhdLnlcbiAgICAgICAgICAgICAgOiBiYXJzW3lJbmRleF1beEluZGV4XS55KSArIHlPZmZzZXQsXG4gICAgICAgICAgeFBvczogYmFyc1t5SW5kZXhdW3hJbmRleF0ueCArIGJhcnNbeUluZGV4XVt4SW5kZXhdLndpZHRoIC8gMixcbiAgICAgICAgICBhbmNob3I6ICdtaWRkbGUnLFxuICAgICAgICB9O1xuICAgICAgfSk7XG4gICAgICByZXR1cm4gc3ViTGFiZWxzO1xuICAgIH0pO1xuICAgIGlmIChoYXNTdXBwbGVtZW50YXJ5RGF0YShkYXRhKSkge1xuICAgICAgY29uc3Qgc3VwcERhdGFMYWJlbHM6IERhdGFMYWJlbFtdID0gZGF0YS5zdXBwbGVtZW50YXJ5WXMuZmxhdE1hcChcbiAgICAgICAgKHksIHlJbmRleCkgPT4ge1xuICAgICAgICAgIGNvbnN0IHN1YkxhYmVsczogRGF0YUxhYmVsW10gPSB5LnZhbHVlcy5tYXAoKHZhbCwgeEluZGV4KSA9PiB7XG4gICAgICAgICAgICBjb25zdCBpc05lZ2F0aXZlQmFyID1cbiAgICAgICAgICAgICAgc3VwcEJhcnNbeUluZGV4XVt4SW5kZXhdLnkgPj0gemVyb0F4aXNQb3NWYWwgJiZcbiAgICAgICAgICAgICAgc3VwcEJhcnNbeUluZGV4XVt4SW5kZXhdLmhlaWdodCA+IDA7XG4gICAgICAgICAgICBjb25zdCB5T2Zmc2V0ID0gaXNOZWdhdGl2ZUJhclxuICAgICAgICAgICAgICA/IGNoYXJ0U2l6aW5nVmFsdWVzLmRhdGFMYWJlbFBhZGRpbmcgK1xuICAgICAgICAgICAgICAgIHN1cHBCYXJzW3lJbmRleF1beEluZGV4XS5oZWlnaHRcbiAgICAgICAgICAgICAgOiAtY2hhcnRTaXppbmdWYWx1ZXMuZGF0YUxhYmVsUGFkZGluZztcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgIGVsZW1lbnRUeXBlOiAnZGF0YUxhYmVsJyxcbiAgICAgICAgICAgICAgbGFiZWw6XG4gICAgICAgICAgICAgICAgcGlwZVRyYW5zZm9ybShcbiAgICAgICAgICAgICAgICAgIHZhbCxcbiAgICAgICAgICAgICAgICAgIGNoZWNrSWZTZWNvbmRhcnkoZGF0YSwgeUluZGV4LCB4SW5kZXgsIHRydWUpLFxuICAgICAgICAgICAgICAgICkgPz8gJycsXG4gICAgICAgICAgICAgIHlQb3M6IHN1cHBCYXJzW3lJbmRleF1beEluZGV4XS55ICsgeU9mZnNldCxcbiAgICAgICAgICAgICAgeFBvczpcbiAgICAgICAgICAgICAgICBzdXBwQmFyc1t5SW5kZXhdW3hJbmRleF0ueCArIHN1cHBCYXJzW3lJbmRleF1beEluZGV4XS53aWR0aCAvIDIsXG4gICAgICAgICAgICAgIGFuY2hvcjogJ21pZGRsZScsXG4gICAgICAgICAgICB9O1xuICAgICAgICAgIH0pO1xuICAgICAgICAgIHJldHVybiBzdWJMYWJlbHM7XG4gICAgICAgIH0sXG4gICAgICApO1xuICAgICAgZGF0YUxhYmVscy5wdXNoKC4uLnN1cHBEYXRhTGFiZWxzKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBob3Zlcihwb3M6IHtcbiAgICAgIHJlY3Q6IERPTVJlY3Q7XG4gICAgICB4OiBudW1iZXI7XG4gICAgICB5OiBudW1iZXI7XG4gICAgICBjb250YWluZXJTY3JvbGxYOiBudW1iZXI7XG4gICAgICBjb250YWluZXJTY3JvbGxZOiBudW1iZXI7XG4gICAgfSk6IEhvdmVyUmV0dXJuIHtcbiAgICAgIGNvbnN0IHJlYWxQb3NYID0gcG9zLnggKyBwb3MuY29udGFpbmVyU2Nyb2xsWDtcbiAgICAgIGNvbnN0IHJlYWxQb3NZID0gcG9zLnkgKyBwb3MuY29udGFpbmVyU2Nyb2xsWTtcbiAgICAgIGlmIChcbiAgICAgICAgY2hhcnRTaXppbmdWYWx1ZXMgPT09IG51bGwgfHxcbiAgICAgICAgZ2V0SWZIb3Zlck91dE9mQm91bmRzKFxuICAgICAgICAgIHBvcy54LFxuICAgICAgICAgIHBvcy55LFxuICAgICAgICAgIHJlYWxQb3NYLFxuICAgICAgICAgIHJlYWxQb3NZLFxuICAgICAgICAgIGNoYXJ0U2l6aW5nVmFsdWVzLFxuICAgICAgICAgIGRpbWVuc2lvbnMsXG4gICAgICAgIClcbiAgICAgICkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cblxuICAgICAgY29uc3Qgc3VwcFlzID0gaGFzU3VwcGxlbWVudGFyeURhdGEoZGF0YSkgPyBkYXRhLnN1cHBsZW1lbnRhcnlZcyA6IG51bGw7XG5cbiAgICAgIGNvbnN0IHhIb3ZlckluZGljZXMgPSBnZXRCdWNrZXRBbmRDbHVzdGVyTnVtRm9ySG92ZXIoXG4gICAgICAgIHJlYWxQb3NYLFxuICAgICAgICBjaGFydFNpemluZ1ZhbHVlcyxcbiAgICAgICAgZGF0YSxcbiAgICAgICAgY29uZmlnLFxuICAgICAgICBkYXRhLngubGVuZ3RoLFxuICAgICAgKTtcbiAgICAgIGlmICgheEhvdmVySW5kaWNlcykge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHtcbiAgICAgICAgYnVja2V0TnVtOiB4SW5kZXgsXG4gICAgICAgIGNsdXN0ZXJOdW0sXG4gICAgICAgIGNsdXN0ZXJOb3JtQ291bnQsXG4gICAgICAgIGNsdXN0ZXJOdW1UeXBlLFxuICAgICAgfSA9IHhIb3ZlckluZGljZXM7XG5cbiAgICAgIGxldCBpc1N1cHBWYWx1ZTogYm9vbGVhbiA9IGZhbHNlO1xuICAgICAgbGV0IHN1cHBJbmRleFZhbCA9IDA7XG4gICAgICBpZiAoc3VwcFlzKSB7XG4gICAgICAgIHN1cHBJbmRleFZhbCA9IGNsdXN0ZXJOdW0gLSBjbHVzdGVyTm9ybUNvdW50O1xuICAgICAgICBpZiAoY2x1c3Rlck51bVR5cGUgPT09ICdzdXBwJykge1xuICAgICAgICAgIGlzU3VwcFZhbHVlID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBjb25zdCBjYWxjWCA9IGNhbGN1bGF0ZUJhclBvc2l0aW9uKFxuICAgICAgICBkYXRhLFxuICAgICAgICBjb25maWcsXG4gICAgICAgIGNoYXJ0U2l6aW5nVmFsdWVzLFxuICAgICAgICB4SW5kZXgsXG4gICAgICAgIGNsdXN0ZXJOdW0sXG4gICAgICApO1xuICAgICAgY29uc3QgeXMgPSBkYXRhLnlzLm1hcCgoXywgbWFwWUluZGV4KSA9PlxuICAgICAgICBpc1N1cHBWYWx1ZVxuICAgICAgICAgID8gZ2V0U3VwcEJhcllJbmZvVmlhWUluZGV4KFxuICAgICAgICAgICAgICBkYXRhLFxuICAgICAgICAgICAgICBjb25maWcsXG4gICAgICAgICAgICAgIG1hcFlJbmRleCxcbiAgICAgICAgICAgICAgc3VwcEluZGV4VmFsLFxuICAgICAgICAgICAgICB4SW5kZXgsXG4gICAgICAgICAgICAgIHNjYWxlLFxuICAgICAgICAgICAgKS55VmFsdWVcbiAgICAgICAgICA6IGdldEJhcllJbmZvKGRhdGEsIGNvbmZpZywgbWFwWUluZGV4LCB4SW5kZXgsIHNjYWxlKS55VmFsdWUgLVxuICAgICAgICAgICAgKCFpc1N1cHBWYWx1ZSAmJiBpc1dhdGVyZmFsbFxuICAgICAgICAgICAgICA/IGJhcnNbbWFwWUluZGV4XVt4SW5kZXhdLm9mZnNldCA/PyAwXG4gICAgICAgICAgICAgIDogMCksXG4gICAgICApO1xuICAgICAgY29uc3QgeVBvc1NpZ24gPSB6ZXJvQXhpc1Bvc1ZhbCAtIHJlYWxQb3NZO1xuICAgICAgbGV0IHZpc2libGVZSW5kZXggPSAtMTtcbiAgICAgIGxldCBkcm9wT2ZmSG92ZXJEZXRlY3RlZCA9IGZhbHNlO1xuICAgICAgaWYgKHlQb3NTaWduIDwgMCAmJiBkYXRhLnlzLmZpbmQoeSA9PiB5LnZhbHVlcy5maW5kKHZhbCA9PiB2YWwgPCAwKSkpIHtcbiAgICAgICAgZm9yIChsZXQgaSA9IHlzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgICAgaWYgKHlzW2ldID49IHplcm9BeGlzUG9zVmFsICYmIHlzW2ldIDwgcmVhbFBvc1kpIHtcbiAgICAgICAgICAgIHZpc2libGVZSW5kZXggPSBpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHlzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgaWYgKHlzW2ldIDw9IHplcm9BeGlzUG9zVmFsICYmIHlzW2ldIDwgcmVhbFBvc1kpIHtcbiAgICAgICAgICAgIHZpc2libGVZSW5kZXggPSBpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAoaXNDbHVzdGVyZWREYXRhKGRhdGEsIGNvbmZpZywgZmFsc2UpICYmICFzdXBwWXMpIHtcbiAgICAgICAgdmlzaWJsZVlJbmRleCA9IGNsdXN0ZXJOdW07XG4gICAgICAgIGlmIChpc0Z1bm5lbCAmJiB4SW5kZXggIT09IDAgJiYgeXNbdmlzaWJsZVlJbmRleF0gPiByZWFsUG9zWSkge1xuICAgICAgICAgIGRyb3BPZmZIb3ZlckRldGVjdGVkID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKHZpc2libGVZSW5kZXggPT09IC0xKSB7XG4gICAgICAgIGlmIChyZWFsUG9zWSA8PSB6ZXJvQXhpc1Bvc1ZhbCkge1xuICAgICAgICAgIHZpc2libGVZSW5kZXggPSB5cy5pbmRleE9mKE1hdGgubWluKC4uLnlzKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdmlzaWJsZVlJbmRleCA9IHlzLmluZGV4T2YoTWF0aC5tYXgoLi4ueXMpKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgY29uc3QgeUluZGV4ID0gdmlzaWJsZUluZGljZXNbdmlzaWJsZVlJbmRleF07XG4gICAgICBsZXQgeyB5VmFsdWUsIGhlaWdodCB9ID0gaXNTdXBwVmFsdWVcbiAgICAgICAgPyBnZXRTdXBwQmFyWUluZm9WaWFZSW5kZXgoXG4gICAgICAgICAgICBkYXRhLFxuICAgICAgICAgICAgY29uZmlnLFxuICAgICAgICAgICAgeUluZGV4LFxuICAgICAgICAgICAgc3VwcEluZGV4VmFsLFxuICAgICAgICAgICAgeEluZGV4LFxuICAgICAgICAgICAgc2NhbGUsXG4gICAgICAgICAgKVxuICAgICAgICA6IGdldEJhcllJbmZvKGRhdGEsIGNvbmZpZywgeUluZGV4LCB4SW5kZXgsIHNjYWxlKTtcbiAgICAgIGlmIChkcm9wT2ZmSG92ZXJEZXRlY3RlZCkge1xuICAgICAgICB5VmFsdWUgPSBncmFkaWVudHNbeUluZGV4XVt4SW5kZXhdLnk7XG4gICAgICAgIGhlaWdodCA9IGdyYWRpZW50c1t5SW5kZXhdW3hJbmRleF0uaGVpZ2h0O1xuICAgICAgfVxuXG4gICAgICBjb25zdCBsb2NhbEFuY2hvclggPSBjYWxjWCAtIHBvcy5jb250YWluZXJTY3JvbGxYIC0gU01BTExfUEFERElORztcbiAgICAgIGNvbnN0IHdpZHRoID0gY2hhcnRTaXppbmdWYWx1ZXMuYmFyU2l6ZSArIFNNQUxMX1BBRERJTkcgKiAyO1xuICAgICAgY29uc3Qgd2F0ZXJmYWxsT2Zmc2V0ID1cbiAgICAgICAgIWlzU3VwcFZhbHVlICYmIGlzV2F0ZXJmYWxsID8gYmFyc1t5SW5kZXhdW3hJbmRleF0ub2Zmc2V0ID8/IDAgOiAwO1xuICAgICAgY29uc3QgbG9jYWxBbmNob3JZID0geVZhbHVlIC0gcG9zLmNvbnRhaW5lclNjcm9sbFkgLSB3YXRlcmZhbGxPZmZzZXQ7XG4gICAgICBjb25zdCB7IGFuY2hvclgsIGFuY2hvclksIGFuY2hvcldpZHRoLCBhbmNob3JIZWlnaHQgfSA9XG4gICAgICAgIGNoZWNrQW5jaG9yc0FnYWluc3RCb3VuZChcbiAgICAgICAgICBsb2NhbEFuY2hvclgsXG4gICAgICAgICAgbG9jYWxBbmNob3JZLFxuICAgICAgICAgIGRpbWVuc2lvbnMsXG4gICAgICAgICAgd2lkdGgsXG4gICAgICAgICAgaGVpZ2h0LFxuICAgICAgICApO1xuICAgICAgY29uc3QgYW5jaG9yID0gbmV3IERPTVJlY3QoXG4gICAgICAgIGFuY2hvclggKyBwb3MucmVjdC54LFxuICAgICAgICBhbmNob3JZICsgcG9zLnJlY3QueSxcbiAgICAgICAgYW5jaG9yV2lkdGgsXG4gICAgICAgIGFuY2hvckhlaWdodCxcbiAgICAgICk7XG4gICAgICAvL1dlIG5lZWQgdG8gcHJlc2VydmUgdGhlIG9yaWdpbmFsIGluZGV4IGZvciB0aGUgbGF0ZXIgY2hlY2tJZlNlY29uZGFyeSBjYWxsXG4gICAgICBjb25zdCB5c0Zvck1ldHJpY3M6IHtcbiAgICAgICAgZGF0YTogU3VwcGxlbWVudGFyeURhdGFZIHwgRGF0YVk7XG4gICAgICAgIG9yaWdpbmFsSW5kZXg6IG51bWJlcjtcbiAgICAgIH1bXSA9XG4gICAgICAgIGlzU3VwcFZhbHVlICYmIHN1cHBZc1xuICAgICAgICAgID8gc3VwcFlzXG4gICAgICAgICAgICAgIC5tYXAoKHN1cHBZLCBpbmRleCkgPT4gKHsgZGF0YTogc3VwcFksIG9yaWdpbmFsSW5kZXg6IGluZGV4IH0pKVxuICAgICAgICAgICAgICAuZmlsdGVyKHN1cHBZID0+IHN1cHBZLmRhdGEuc3VwcGxlbWVudGFsSW5kZXggPT09IHN1cHBJbmRleFZhbClcbiAgICAgICAgICA6IGRhdGEueXMubWFwKCh5LCBpbmRleCkgPT4gKHsgZGF0YTogeSwgb3JpZ2luYWxJbmRleDogaW5kZXggfSkpO1xuICAgICAgLy8gRmluZCB0aGUgc3BlY2lmaWMgc3VwcGxlbWVudGFyeSBpdGVtIHRoYXQgd2FzIGhvdmVyZWRcbiAgICAgIGNvbnN0IGdyb3VwU3VwcHMgPSBzdXBwWXNcbiAgICAgICAgPyBzdXBwWXMuZmlsdGVyKHMgPT4gcy5zdXBwbGVtZW50YWxJbmRleCA9PT0gc3VwcEluZGV4VmFsKSA/PyBbXVxuICAgICAgICA6IFtdO1xuICAgICAgY29uc3Qgc3VwcEFycmF5SW5kZXggPSB2aXNpYmxlWUluZGV4OyAvLyBVc2UgdGhlIHZpc3VhbCBZIHBvc2l0aW9uIHdpdGhpbiB0aGUgbGF5ZXJcbiAgICAgIGNvbnN0IGZpbHRlcmVkU3VwcFlJbmRleCA9XG4gICAgICAgIHN1cHBBcnJheUluZGV4ID49IDAgJiYgc3VwcEFycmF5SW5kZXggPCBncm91cFN1cHBzLmxlbmd0aCAmJiBzdXBwWXNcbiAgICAgICAgICA/IHN1cHBZcy5pbmRleE9mKGdyb3VwU3VwcHNbc3VwcEFycmF5SW5kZXhdKSA/PyAtMVxuICAgICAgICAgIDogLTE7XG4gICAgICBjb25zdCBzdXBwWUluZGV4ID1cbiAgICAgICAgZmlsdGVyZWRTdXBwWUluZGV4ID49IDAgPyB2aXNpYmxlU3VwcEluZGljZXNbZmlsdGVyZWRTdXBwWUluZGV4XSA6IC0xO1xuXG4gICAgICByZXR1cm4ge1xuICAgICAgICBob3ZlclR5cGU6ICdzdGFuZGFyZCcsXG4gICAgICAgIHg6IGNhbGNYICsgY2hhcnRTaXppbmdWYWx1ZXMuYmFyU2l6ZSAvIDIsXG4gICAgICAgIHhJbmRleCxcbiAgICAgICAgeXMsXG4gICAgICAgIHlJbmRleCxcbiAgICAgICAgdmlzaWJsZVlJbmRleCxcbiAgICAgICAgLi4uKGlzU3VwcFZhbHVlICYmIHN1cHBZSW5kZXggPj0gMFxuICAgICAgICAgID8ge1xuICAgICAgICAgICAgICBpc1N1cHBWYWx1ZSxcbiAgICAgICAgICAgICAgc3VwcFlJbmRleDogc3VwcFlJbmRleCxcbiAgICAgICAgICAgIH1cbiAgICAgICAgICA6IHt9KSxcbiAgICAgICAgLi4uKGRyb3BPZmZIb3ZlckRldGVjdGVkID8geyBpc0Ryb3BPZmY6IHRydWUgfSA6IHt9KSxcbiAgICAgICAgdG9vbHRpcDoge1xuICAgICAgICAgIGFuY2hvcixcbiAgICAgICAgICBkYXRlOlxuICAgICAgICAgICAgZGF0YS50eXBlID09PSAnbGFiZWxlZCdcbiAgICAgICAgICAgICAgPyBkcm9wT2ZmSG92ZXJEZXRlY3RlZFxuICAgICAgICAgICAgICAgID8gJ0Ryb3Agb2ZmIGZyb20gJy5jb25jYXQoZGF0YS54W3hJbmRleCAtIDFdLmxhYmVsKVxuICAgICAgICAgICAgICAgIDogZGF0YS54W3hJbmRleF0ubGFiZWxcbiAgICAgICAgICAgICAgOiB1dGNGb3JtYXQoJyVCICVkLCAlWScpKG5ldyBEYXRlKGRhdGEueFt4SW5kZXhdKSksXG4gICAgICAgICAgbWV0cmljczogeXNGb3JNZXRyaWNzXG4gICAgICAgICAgICAubWFwKHkgPT4gKHtcbiAgICAgICAgICAgICAgY29sb3I6IGdldENvbG9yKFxuICAgICAgICAgICAgICAgIGlzV2F0ZXJmYWxsID8gd2F0ZXJmYWxsRGF0YS5tYXAuZ2V0KHkuZGF0YSkgOiB5LmRhdGEsXG4gICAgICAgICAgICAgICAgY29sb3JJbmRpY2VzLFxuICAgICAgICAgICAgICAgIGNvbmZpZy5jb2xvcnMsXG4gICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgIGxhYmVsOiB5LmRhdGEubGFiZWwsXG4gICAgICAgICAgICAgIHBhdHRlcm46IHkuZGF0YS5wYXR0ZXJuLFxuICAgICAgICAgICAgICB2YWx1ZTogcGlwZVRyYW5zZm9ybShcbiAgICAgICAgICAgICAgICBkcm9wT2ZmSG92ZXJEZXRlY3RlZFxuICAgICAgICAgICAgICAgICAgPyBNYXRoLm1heChcbiAgICAgICAgICAgICAgICAgICAgICB5LmRhdGEudmFsdWVzW3hJbmRleCAtIDFdIC0geS5kYXRhLnZhbHVlc1t4SW5kZXhdLFxuICAgICAgICAgICAgICAgICAgICAgIDAsXG4gICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgIDogeS5kYXRhLnZhbHVlc1t4SW5kZXhdLFxuICAgICAgICAgICAgICAgIGNoZWNrSWZTZWNvbmRhcnkoXG4gICAgICAgICAgICAgICAgICBkYXRhLFxuICAgICAgICAgICAgICAgICAgeS5vcmlnaW5hbEluZGV4LFxuICAgICAgICAgICAgICAgICAgZHJvcE9mZkhvdmVyRGV0ZWN0ZWQgPyB4SW5kZXggLSAxIDogeEluZGV4LFxuICAgICAgICAgICAgICAgICAgaXNTdXBwVmFsdWUsXG4gICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICB0cnVlLFxuICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgfSkpXG4gICAgICAgICAgICAuZmlsdGVyKChfLCBpKSA9PiBjb25maWcuZ3JvdXBlZFRvb2x0aXAgfHwgaSA9PT0gdmlzaWJsZVlJbmRleCksXG4gICAgICAgIH0sXG4gICAgICB9O1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBjaGFydFdpZHRoOiBjaGFydFNpemluZ1ZhbHVlcy50b3RhbFdpZHRoLFxuICAgICAgY2hhcnRIZWlnaHQ6IGNoYXJ0U2l6aW5nVmFsdWVzLnRvdGFsSGVpZ2h0LFxuICAgICAgY2hhcnRTaXppbmdWYWx1ZXMsXG4gICAgICB4VGlja3MsXG4gICAgICB5VGlja3MsXG4gICAgICBjb2xvcnMsXG4gICAgICBiYXJzLFxuICAgICAgbGluZXM6IFtdLFxuICAgICAgY2lyY2xlczogW10sXG4gICAgICBhcmVhczogW10sXG4gICAgICBob3ZlcixcbiAgICAgIGFyY3M6IFtdLFxuICAgICAgaG9yaXpvbnRhbEJhcnM6IFtdLFxuICAgICAgZGF0YUxhYmVscyxcbiAgICAgIHdhdGVyZmFsbExpbmVzLFxuICAgICAgZ3JhZGllbnRzLFxuICAgICAgZmxvd0Nvbm5lY3Rpb25zOiBbXSxcbiAgICAgIGhvcml6b250YWxDb250YWluZXJTY2FsZTogY2hhcnRTaXppbmdWYWx1ZXMuaG9yaXpvbnRhbENvbnRhaW5lclNjYWxlLFxuICAgICAgdmVydGljYWxDb250YWluZXJTY2FsZTogY2hhcnRTaXppbmdWYWx1ZXMudmVydGljYWxDb250YWluZXJTY2FsZSxcbiAgICAgIGNoYXJ0RXJyb3I6IG51bGwsXG4gICAgfTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGhvcml6b250YWxCYXJzKFxuICAgIGNvbmZpZzogQ29uZmlnV2l0aEZ1bGxTY2FsaW5nLFxuICAgIGFsbERhdGE6IElucHV0RGF0YSxcbiAgICBkaW1lbnNpb25zOiBEaW1lbnNpb25zLFxuICApOiBSZW5kZXJlZENoYXJ0IHtcbiAgICBpZiAoIXdhcm5GbG93RGF0YShhbGxEYXRhLCAnaG9yaXpvbnRhbCBiYXInKSkge1xuICAgICAgcmV0dXJuIHsgLi4uZW1wdHlDaGFydCwgY2hhcnRFcnJvcjogJ2NvbmZpZycgfTtcbiAgICB9XG4gICAgLy9Tb21lIG9mIHRoaXMgc3R1ZmYgZ2V0cyBjb25mdXNpbmcsIGJlY2F1c2UgeCBhbmQgeSBhcmUgZXNzZW50aWFsbHkgaW52ZXJ0ZWQgaGVyZVxuICAgIC8vICBTbywgaWYgeW91IHNlZSBhIHNpdHVhdGlvbiB3aGVyZSBhIHZhcmlhYmxlIGlzIG5hbWVkICd5JywgYnV0IHJlZmVyZW5jaW5nXG4gICAgLy8gICd4JyAob3IgdmljZSB2ZXJzYSksIHRoYXQncyB3aHlcbiAgICBjb25zdCB7IGRhdGEsIHZpc2libGVJbmRpY2VzLCB2aXNpYmxlU3VwcEluZGljZXMgfSA9IGhpZGUoYWxsRGF0YSk7XG4gICAgaWYgKFxuICAgICAgY29uZmlnLnNob3dEYXRhTGFiZWxzID09PSB0cnVlICYmXG4gICAgICBpc1N0YWNrZWREYXRhKGNvbmZpZykgJiZcbiAgICAgICFpc0dyb3VwaW5nVHlwZUV4Y2VwdGlvbihkYXRhLCBjb25maWcpXG4gICAgKSB7XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29uc29sZVxuICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICBcIkhlYWRzIHVwISBEYXRhIGxhYmVscyBhcmVuJ3Qgc3VwcG9ydGVkIGZvciBhbnkgc3RhY2tlZCBjaGFydCB0eXBlXCIsXG4gICAgICApO1xuICAgICAgcmV0dXJuIGVtcHR5Q2hhcnQ7XG4gICAgfVxuICAgIGlmIChcbiAgICAgIGhhc1N1cHBsZW1lbnRhcnlEYXRhKGRhdGEpICYmXG4gICAgICBpc0NsdXN0ZXJlZERhdGEoZGF0YSwgY29uZmlnLCBmYWxzZSkgJiZcbiAgICAgICFpc0dyb3VwaW5nVHlwZUV4Y2VwdGlvbihkYXRhLCBjb25maWcpXG4gICAgKSB7XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29uc29sZVxuICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICBcIkhlYWRzIHVwISBTdXBwbGVtZW50YXJ5IHkgdmFsdWVzIGFyZW4ndCBzdXBwb3J0ZWQgZm9yIGNsdXN0ZXJlZCBkYXRhIChqdXN0IHVzZSBhbm90aGVyIG5vcm1hbCB5IHNlcmllcylcIixcbiAgICAgICk7XG4gICAgICByZXR1cm4gZW1wdHlDaGFydDtcbiAgICB9XG5cbiAgICBjb25zdCB7IGRhdGVGb3JtYXQsIHBpcGVUcmFuc2Zvcm0sIGNvbG9ySW5kaWNlcywgY29sb3JzIH0gPVxuICAgICAgZ2V0Rm9ybWF0dGluZ0FuZENvbG9ycyhhbGxEYXRhLCBkYXRhLCBjb25maWcpO1xuXG4gICAgY29uc3QgY2hhcnRTaXppbmdWYWx1ZXMgPSBnZXRGdWxsQ2hhcnRTY2FsZVZhbHVlcyhcbiAgICAgIGNvbmZpZyxcbiAgICAgIGRhdGEsXG4gICAgICBkaW1lbnNpb25zLFxuICAgICAgcGlwZVRyYW5zZm9ybSxcbiAgICAgIGRhdGVGb3JtYXQsXG4gICAgKTtcbiAgICBpZiAoY2hhcnRTaXppbmdWYWx1ZXMgPT09IG51bGwpIHtcbiAgICAgIHJldHVybiB7IC4uLmVtcHR5Q2hhcnQsIGNoYXJ0RXJyb3I6ICdzaXppbmcnIH07XG4gICAgfVxuXG4gICAgY29uc3QgdGlja0NvdW50ID0gZ2V0QnVja2V0VGlja0NvdW50KGNoYXJ0U2l6aW5nVmFsdWVzKTtcbiAgICBjb25zdCB5VGlja3MgPSAoXG4gICAgICBkYXRhLnR5cGUgPT09ICdsYWJlbGVkJ1xuICAgICAgICA/IGdlbmVyYXRlTGFiZWxsZWRUaWNrcyhkYXRhLCBjb25maWcsIHRpY2tDb3VudCwgY2hhcnRTaXppbmdWYWx1ZXMpXG4gICAgICAgIDogZ2VuZXJhdGVUaW1lc2VyaWVzVGlja3MoXG4gICAgICAgICAgICBkYXRhLFxuICAgICAgICAgICAgY29uZmlnLFxuICAgICAgICAgICAgdGlja0NvdW50LFxuICAgICAgICAgICAgY2hhcnRTaXppbmdWYWx1ZXMsXG4gICAgICAgICAgICBkYXRlRm9ybWF0LFxuICAgICAgICAgIClcbiAgICApLm1hcCh0aWNrID0+IHRvWVRpY2sodGljaykpO1xuICAgIGNvbnN0IHsgc2NhbGUsIHRpY2tzOiBkYXRhVGlja3MgfSA9IGNhbGNEYXRhQXhpc1NjYWxlc0FuZFRpY2tzKFxuICAgICAgZGF0YSxcbiAgICAgIHBpcGVUcmFuc2Zvcm0sXG4gICAgICBjb25maWcsXG4gICAgICBjaGFydFNpemluZ1ZhbHVlcyxcbiAgICApO1xuICAgIGNvbnN0IHhUaWNrcyA9IGRhdGFUaWNrcy5tYXAodGljayA9PiB0b1hUaWNrKHRpY2spKTtcbiAgICBjb25zdCB6ZXJvQXhpc1Bvc1ZhbCA9IHNjYWxlKDAsIHRydWUpO1xuXG4gICAgY29uc3Qgc2ltcGxpZmllZEhvcml6b250YWxCYXJzOiB7XG4gICAgICB4UG9zOiBudW1iZXI7XG4gICAgICB5UG9zOiBudW1iZXI7XG4gICAgICB3aWR0aDogbnVtYmVyO1xuICAgIH1bXVtdID0gW107XG4gICAgY29uc3QgaG9yaXpvbnRhbEJhcnMgPSBkYXRhLnlzLm1hcCgoeSwgeUluZGV4KSA9PiB7XG4gICAgICBjb25zdCBzdWJTaW1wSG9yQmFyczoge1xuICAgICAgICB4UG9zOiBudW1iZXI7XG4gICAgICAgIHlQb3M6IG51bWJlcjtcbiAgICAgICAgd2lkdGg6IG51bWJlcjtcbiAgICAgIH1bXSA9IFtdO1xuICAgICAgY29uc3QgcmV0VmFsID0geS52YWx1ZXMubWFwKChfLCBpbmRleCkgPT4ge1xuICAgICAgICBjb25zdCB7IHhWYWx1ZSwgd2lkdGggfSA9IGdldEJhclhJbmZvKFxuICAgICAgICAgIGRhdGEsXG4gICAgICAgICAgY29uZmlnLFxuICAgICAgICAgIHlJbmRleCxcbiAgICAgICAgICBpbmRleCxcbiAgICAgICAgICBzY2FsZSxcbiAgICAgICAgKTtcbiAgICAgICAgY29uc3QgY2x1c3RlckluZm8gPSBnZXRDbHVzdGVySW5mb0ZvckJ1Y2tldChkYXRhLCBjb25maWcpO1xuICAgICAgICBjb25zdCBjbHVzdGVyTnVtID0gY2x1c3RlckluZm8ubm9ybUNsdXN0ZXJJbmRpY2VzLmluZGV4T2YoeUluZGV4KTtcbiAgICAgICAgY29uc3QgeVZhbHVlID0gY2FsY3VsYXRlQmFyUG9zaXRpb24oXG4gICAgICAgICAgZGF0YSxcbiAgICAgICAgICBjb25maWcsXG4gICAgICAgICAgY2hhcnRTaXppbmdWYWx1ZXMsXG4gICAgICAgICAgaW5kZXgsXG4gICAgICAgICAgaXNDbHVzdGVyZWREYXRhKGRhdGEsIGNvbmZpZywgZmFsc2UpID8gY2x1c3Rlck51bSA6IDAsXG4gICAgICAgICk7XG5cbiAgICAgICAgY29uc3QgaG9yUiA9IE1hdGgubWluKFxuICAgICAgICAgIERFRkFVTFRfSE9SSVpPTlRBTF9CQVJfQ09STkVSX1JBRElVUyxcbiAgICAgICAgICBNYXRoLmZsb29yKHdpZHRoIC8gMiksXG4gICAgICAgICk7XG4gICAgICAgIGNvbnN0IHZlclIgPSBNYXRoLm1pbihcbiAgICAgICAgICBERUZBVUxUX0hPUklaT05UQUxfQkFSX0NPUk5FUl9SQURJVVMsXG4gICAgICAgICAgTWF0aC5mbG9vcihjaGFydFNpemluZ1ZhbHVlcy5iYXJTaXplIC8gMiksXG4gICAgICAgICk7XG4gICAgICAgIHN1YlNpbXBIb3JCYXJzLnB1c2goe1xuICAgICAgICAgIHhQb3M6IHhWYWx1ZSxcbiAgICAgICAgICB5UG9zOiB5VmFsdWUsXG4gICAgICAgICAgd2lkdGgsXG4gICAgICAgIH0pO1xuICAgICAgICAvL0lmIGNsdXN0ZXJOdW0gaXMgLTEsIHRoZW4gdGhlIHZhbHVlIG9mIGRhdGFbeUluZGV4XVt4SW5kZXhdIG11c3QgYmUgemVyb1xuICAgICAgICBpZiAoY2x1c3Rlck51bSA9PT0gLTEpIHtcbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgaG9yaXpvbnRhbEJhcjogJycsXG4gICAgICAgICAgICBwYXR0ZXJuOiB5LnBhdHRlcm4sXG4gICAgICAgICAgICB4OiB4VmFsdWUsXG4gICAgICAgICAgICB5OiB5VmFsdWUsXG4gICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgICAgICAvL0Rvbid0IGRyYXcgYW55dGhpbmcgZm9yIHplcm8tdmFsdWUgYmFyc1xuICAgICAgICBpZiAod2lkdGggPT09IDApIHtcbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgaG9yaXpvbnRhbEJhcjogJycsXG4gICAgICAgICAgICBwYXR0ZXJuOiB5LnBhdHRlcm4sXG4gICAgICAgICAgICB4OiB4VmFsdWUsXG4gICAgICAgICAgICB5OiB5VmFsdWUsXG4gICAgICAgICAgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGlzUG9zaXRpdmUgPSBkYXRhLnlzW3lJbmRleF0udmFsdWVzW2luZGV4XSA+IDA7XG4gICAgICAgIGNvbnN0IGhhc0FueU5lZ2F0aXZlQmFycyA9IGRhdGEueXNcbiAgICAgICAgICAubWFwKHkgPT4geS52YWx1ZXNbaW5kZXhdKVxuICAgICAgICAgIC5maW5kKHZhbCA9PiB2YWwgPCAwKTtcbiAgICAgICAgY29uc3QgaGFzQW55UG9zaXRpdmVCYXJzID0gZGF0YS55c1xuICAgICAgICAgIC5tYXAoeSA9PiB5LnZhbHVlc1tpbmRleF0pXG4gICAgICAgICAgLmZpbmQodmFsID0+IHZhbCA+IDApO1xuXG4gICAgICAgIC8vVGhlc2UgY2hlY2tzIGFyZSB0byBtYWtlIHN1cmUgd2Ugc3RpbGwgcm91bmQgaWYgYWxsIHByZXZpb3VzL2xhdGVyIHZhbHVlcyBhcmUgMFxuICAgICAgICBjb25zdCBhbGxMZWZ0WmVybyA9IGlzUG9zaXRpdmVcbiAgICAgICAgICA/IGRhdGEueXNcbiAgICAgICAgICAgICAgLnNsaWNlKDAsIHlJbmRleClcbiAgICAgICAgICAgICAgLm1hcCh5ID0+IHkudmFsdWVzW2luZGV4XSlcbiAgICAgICAgICAgICAgLmZpbHRlcih2YWwgPT4gdmFsID4gMCkubGVuZ3RoID09PSAwICYmICFoYXNBbnlOZWdhdGl2ZUJhcnNcbiAgICAgICAgICA6IGRhdGEueXNcbiAgICAgICAgICAgICAgLnNsaWNlKHlJbmRleCArIDEsIGRhdGEueXMubGVuZ3RoKVxuICAgICAgICAgICAgICAubWFwKHkgPT4geS52YWx1ZXNbaW5kZXhdKVxuICAgICAgICAgICAgICAuZmlsdGVyKHZhbCA9PiB2YWwgPCAwKS5sZW5ndGggPT09IDA7XG4gICAgICAgIGNvbnN0IGxlZnRTaWRlUm91bmQgPSAhaXNTdGFja2VkRGF0YShjb25maWcpIHx8IGFsbExlZnRaZXJvO1xuICAgICAgICBjb25zdCBhbGxSaWdodFplcm8gPSBpc1Bvc2l0aXZlXG4gICAgICAgICAgPyBkYXRhLnlzXG4gICAgICAgICAgICAgIC5zbGljZSh5SW5kZXggKyAxLCBkYXRhLnlzLmxlbmd0aClcbiAgICAgICAgICAgICAgLm1hcCh5ID0+IHkudmFsdWVzW2luZGV4XSlcbiAgICAgICAgICAgICAgLmZpbHRlcih2YWwgPT4gdmFsID4gMCkubGVuZ3RoID09PSAwXG4gICAgICAgICAgOiBkYXRhLnlzXG4gICAgICAgICAgICAgIC5zbGljZSgwLCB5SW5kZXgpXG4gICAgICAgICAgICAgIC5tYXAoeSA9PiB5LnZhbHVlc1tpbmRleF0pXG4gICAgICAgICAgICAgIC5maWx0ZXIodmFsID0+IHZhbCA8IDApLmxlbmd0aCA9PT0gMCAmJiAhaGFzQW55UG9zaXRpdmVCYXJzO1xuICAgICAgICBjb25zdCByaWdodFNpZGVSb3VuZCA9ICFpc1N0YWNrZWREYXRhKGNvbmZpZykgfHwgYWxsUmlnaHRaZXJvO1xuICAgICAgICBjb25zdCBwYXRoRCA9IGNhbGN1bGF0ZUhvcml6b250YWxCYXJQYXRoKFxuICAgICAgICAgIGxlZnRTaWRlUm91bmQsXG4gICAgICAgICAgcmlnaHRTaWRlUm91bmQsXG4gICAgICAgICAgeFZhbHVlLFxuICAgICAgICAgIHlWYWx1ZSxcbiAgICAgICAgICBob3JSLFxuICAgICAgICAgIHZlclIsXG4gICAgICAgICAgY2hhcnRTaXppbmdWYWx1ZXMuYmFyU2l6ZSxcbiAgICAgICAgICB3aWR0aCxcbiAgICAgICAgKTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBob3Jpem9udGFsQmFyOiBwYXRoRCxcbiAgICAgICAgICBwYXR0ZXJuOiB5LnBhdHRlcm4sXG4gICAgICAgICAgeDogeFZhbHVlLFxuICAgICAgICAgIHk6IHlWYWx1ZSxcbiAgICAgICAgfTtcbiAgICAgIH0pO1xuICAgICAgc2ltcGxpZmllZEhvcml6b250YWxCYXJzLnB1c2goc3ViU2ltcEhvckJhcnMpO1xuICAgICAgcmV0dXJuIHJldFZhbDtcbiAgICB9KTtcbiAgICBjb25zdCBzdXBwWXMgPSBkYXRhLnN1cHBsZW1lbnRhcnlZcztcbiAgICBjb25zdCBzaW1wbGlmaWVkU3VwcEhvcml6b250YWxCYXJzOiB7XG4gICAgICB4UG9zOiBudW1iZXI7XG4gICAgICB5UG9zOiBudW1iZXI7XG4gICAgICB3aWR0aDogbnVtYmVyO1xuICAgIH1bXVtdID0gW107XG4gICAgaWYgKHN1cHBZcykge1xuICAgICAgY29uc3Qgc3VwcEhvcml6b250YWxCYXJzID0gc3VwcFlzLm1hcCgoeSwgeUluZGV4KSA9PiB7XG4gICAgICAgIGNvbnN0IHN1YlNpbXBIb3JCYXJzOiB7XG4gICAgICAgICAgeFBvczogbnVtYmVyO1xuICAgICAgICAgIHlQb3M6IG51bWJlcjtcbiAgICAgICAgICB3aWR0aDogbnVtYmVyO1xuICAgICAgICB9W10gPSBbXTtcbiAgICAgICAgY29uc3QgcmV0VmFsID0geS52YWx1ZXMubWFwKChfLCBpbmRleCkgPT4ge1xuICAgICAgICAgIGNvbnN0IHsgeFZhbHVlLCB3aWR0aCB9ID0gZ2V0QmFyWEluZm8oXG4gICAgICAgICAgICBkYXRhLFxuICAgICAgICAgICAgY29uZmlnLFxuICAgICAgICAgICAgeUluZGV4LFxuICAgICAgICAgICAgaW5kZXgsXG4gICAgICAgICAgICBzY2FsZSxcbiAgICAgICAgICAgIHRydWUsXG4gICAgICAgICAgKTtcbiAgICAgICAgICBjb25zdCBjbHVzdGVySW5mbyA9IGdldENsdXN0ZXJJbmZvRm9yQnVja2V0KGRhdGEsIGNvbmZpZyk7XG4gICAgICAgICAgY29uc3QgY2x1c3Rlck51bSA9XG4gICAgICAgICAgICBjbHVzdGVySW5mby5zdXBwQ2x1c3RlckluZGljZXMuaW5kZXhPZih5LnN1cHBsZW1lbnRhbEluZGV4KSArXG4gICAgICAgICAgICBjbHVzdGVySW5mby5ub3JtQ291bnQ7XG4gICAgICAgICAgY29uc3QgeVZhbHVlID0gY2FsY3VsYXRlQmFyUG9zaXRpb24oXG4gICAgICAgICAgICBkYXRhLFxuICAgICAgICAgICAgY29uZmlnLFxuICAgICAgICAgICAgY2hhcnRTaXppbmdWYWx1ZXMsXG4gICAgICAgICAgICBpbmRleCxcbiAgICAgICAgICAgIGNsdXN0ZXJOdW0sXG4gICAgICAgICAgKTtcblxuICAgICAgICAgIGNvbnN0IGhvclIgPSBNYXRoLm1pbihcbiAgICAgICAgICAgIERFRkFVTFRfSE9SSVpPTlRBTF9CQVJfQ09STkVSX1JBRElVUyxcbiAgICAgICAgICAgIE1hdGguZmxvb3Iod2lkdGggLyAyKSxcbiAgICAgICAgICApO1xuICAgICAgICAgIGNvbnN0IHZlclIgPSBNYXRoLm1pbihcbiAgICAgICAgICAgIERFRkFVTFRfSE9SSVpPTlRBTF9CQVJfQ09STkVSX1JBRElVUyxcbiAgICAgICAgICAgIE1hdGguZmxvb3IoY2hhcnRTaXppbmdWYWx1ZXMuYmFyU2l6ZSAvIDIpLFxuICAgICAgICAgICk7XG4gICAgICAgICAgc3ViU2ltcEhvckJhcnMucHVzaCh7XG4gICAgICAgICAgICB4UG9zOiB4VmFsdWUsXG4gICAgICAgICAgICB5UG9zOiB5VmFsdWUsXG4gICAgICAgICAgICB3aWR0aCxcbiAgICAgICAgICB9KTtcbiAgICAgICAgICAvL0Rvbid0IGRyYXcgYW55dGhpbmcgZm9yIHplcm8tdmFsdWUgYmFyc1xuICAgICAgICAgIGlmICh3aWR0aCA9PT0gMCkge1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgaG9yaXpvbnRhbEJhcjogJycsXG4gICAgICAgICAgICAgIHBhdHRlcm46IHkucGF0dGVybixcbiAgICAgICAgICAgICAgeDogeFZhbHVlLFxuICAgICAgICAgICAgICB5OiB5VmFsdWUsXG4gICAgICAgICAgICB9O1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGNvbnN0IGlzUG9zaXRpdmUgPSBzdXBwWXNbeUluZGV4XS52YWx1ZXNbaW5kZXhdID4gMDtcbiAgICAgICAgICBjb25zdCBoYXNBbnlOZWdhdGl2ZUJhcnMgPSBzdXBwWXNcbiAgICAgICAgICAgIC5maWx0ZXIoc3VwcFkgPT4gc3VwcFkuc3VwcGxlbWVudGFsSW5kZXggPT09IHkuc3VwcGxlbWVudGFsSW5kZXgpXG4gICAgICAgICAgICAubWFwKHkgPT4geS52YWx1ZXNbaW5kZXhdKVxuICAgICAgICAgICAgLmZpbmQodmFsID0+IHZhbCA8IDApO1xuICAgICAgICAgIGNvbnN0IGhhc0FueVBvc2l0aXZlQmFycyA9IHN1cHBZc1xuICAgICAgICAgICAgLmZpbHRlcihzdXBwWSA9PiBzdXBwWS5zdXBwbGVtZW50YWxJbmRleCA9PT0geS5zdXBwbGVtZW50YWxJbmRleClcbiAgICAgICAgICAgIC5tYXAoeSA9PiB5LnZhbHVlc1tpbmRleF0pXG4gICAgICAgICAgICAuZmluZCh2YWwgPT4gdmFsID4gMCk7XG5cbiAgICAgICAgICAvL1RoZXNlIGNoZWNrcyBhcmUgdG8gbWFrZSBzdXJlIHdlIHN0aWxsIHJvdW5kIGlmIGFsbCBwcmV2aW91cy9sYXRlciB2YWx1ZXMgYXJlIDBcbiAgICAgICAgICBjb25zdCBhbGxMZWZ0WmVybyA9IGlzUG9zaXRpdmVcbiAgICAgICAgICAgID8gc3VwcFlzXG4gICAgICAgICAgICAgICAgLnNsaWNlKDAsIHlJbmRleClcbiAgICAgICAgICAgICAgICAuZmlsdGVyKFxuICAgICAgICAgICAgICAgICAgc3VwcFkgPT4gc3VwcFkuc3VwcGxlbWVudGFsSW5kZXggPT09IHkuc3VwcGxlbWVudGFsSW5kZXgsXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgIC5tYXAoeSA9PiB5LnZhbHVlc1tpbmRleF0pXG4gICAgICAgICAgICAgICAgLmZpbHRlcih2YWwgPT4gdmFsID4gMCkubGVuZ3RoID09PSAwICYmICFoYXNBbnlOZWdhdGl2ZUJhcnNcbiAgICAgICAgICAgIDogc3VwcFlzXG4gICAgICAgICAgICAgICAgLnNsaWNlKHlJbmRleCArIDEsIHN1cHBZcy5sZW5ndGgpXG4gICAgICAgICAgICAgICAgLmZpbHRlcihcbiAgICAgICAgICAgICAgICAgIHN1cHBZID0+IHN1cHBZLnN1cHBsZW1lbnRhbEluZGV4ID09PSB5LnN1cHBsZW1lbnRhbEluZGV4LFxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAubWFwKHkgPT4geS52YWx1ZXNbaW5kZXhdKVxuICAgICAgICAgICAgICAgIC5maWx0ZXIodmFsID0+IHZhbCA8IDApLmxlbmd0aCA9PT0gMDtcbiAgICAgICAgICBjb25zdCBsZWZ0U2lkZVJvdW5kID0gIWlzU3RhY2tlZERhdGEoY29uZmlnKSB8fCBhbGxMZWZ0WmVybztcbiAgICAgICAgICBjb25zdCBhbGxSaWdodFplcm8gPSBpc1Bvc2l0aXZlXG4gICAgICAgICAgICA/IHN1cHBZc1xuICAgICAgICAgICAgICAgIC5zbGljZSh5SW5kZXggKyAxLCBzdXBwWXMubGVuZ3RoKVxuICAgICAgICAgICAgICAgIC5maWx0ZXIoXG4gICAgICAgICAgICAgICAgICBzdXBwWSA9PiBzdXBwWS5zdXBwbGVtZW50YWxJbmRleCA9PT0geS5zdXBwbGVtZW50YWxJbmRleCxcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgLm1hcCh5ID0+IHkudmFsdWVzW2luZGV4XSlcbiAgICAgICAgICAgICAgICAuZmlsdGVyKHZhbCA9PiB2YWwgPiAwKS5sZW5ndGggPT09IDBcbiAgICAgICAgICAgIDogc3VwcFlzXG4gICAgICAgICAgICAgICAgLnNsaWNlKDAsIHlJbmRleClcbiAgICAgICAgICAgICAgICAuZmlsdGVyKFxuICAgICAgICAgICAgICAgICAgc3VwcFkgPT4gc3VwcFkuc3VwcGxlbWVudGFsSW5kZXggPT09IHkuc3VwcGxlbWVudGFsSW5kZXgsXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgIC5tYXAoeSA9PiB5LnZhbHVlc1tpbmRleF0pXG4gICAgICAgICAgICAgICAgLmZpbHRlcih2YWwgPT4gdmFsIDwgMCkubGVuZ3RoID09PSAwICYmICFoYXNBbnlQb3NpdGl2ZUJhcnM7XG4gICAgICAgICAgY29uc3QgcmlnaHRTaWRlUm91bmQgPSAhaXNTdGFja2VkRGF0YShjb25maWcpIHx8IGFsbFJpZ2h0WmVybztcbiAgICAgICAgICBjb25zdCBwYXRoRCA9IGNhbGN1bGF0ZUhvcml6b250YWxCYXJQYXRoKFxuICAgICAgICAgICAgbGVmdFNpZGVSb3VuZCxcbiAgICAgICAgICAgIHJpZ2h0U2lkZVJvdW5kLFxuICAgICAgICAgICAgeFZhbHVlLFxuICAgICAgICAgICAgeVZhbHVlLFxuICAgICAgICAgICAgaG9yUixcbiAgICAgICAgICAgIHZlclIsXG4gICAgICAgICAgICBjaGFydFNpemluZ1ZhbHVlcy5iYXJTaXplLFxuICAgICAgICAgICAgd2lkdGgsXG4gICAgICAgICAgKTtcbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgaG9yaXpvbnRhbEJhcjogcGF0aEQsXG4gICAgICAgICAgICBwYXR0ZXJuOiB5LnBhdHRlcm4sXG4gICAgICAgICAgICB4OiB4VmFsdWUsXG4gICAgICAgICAgICB5OiB5VmFsdWUsXG4gICAgICAgICAgfTtcbiAgICAgICAgfSk7XG4gICAgICAgIHNpbXBsaWZpZWRTdXBwSG9yaXpvbnRhbEJhcnMucHVzaChzdWJTaW1wSG9yQmFycyk7XG4gICAgICAgIHJldHVybiByZXRWYWw7XG4gICAgICB9KTtcbiAgICAgIGhvcml6b250YWxCYXJzLnB1c2goLi4uc3VwcEhvcml6b250YWxCYXJzKTtcbiAgICAgIGNvbG9ycy5wdXNoKC4uLnN1cHBZcy5tYXAoeSA9PiBnZXRDb2xvcih5LCBjb2xvckluZGljZXMsIGNvbmZpZy5jb2xvcnMpKSk7XG4gICAgfVxuXG4gICAgY29uc3QgeU9mZnNldCA9IGNoYXJ0U2l6aW5nVmFsdWVzLmJhclNpemU7XG4gICAgY29uc3QgZGF0YUxhYmVsczogRGF0YUxhYmVsW10gPSBkYXRhLnlzLmZsYXRNYXAoKHksIHlJbmRleCkgPT4ge1xuICAgICAgY29uc3Qgc3ViTGFiZWxzOiBEYXRhTGFiZWxbXSA9IHkudmFsdWVzLm1hcCgodmFsLCB4SW5kZXgpID0+IHtcbiAgICAgICAgY29uc3QgYmFySXNOZWdhdGl2ZSA9XG4gICAgICAgICAgc2ltcGxpZmllZEhvcml6b250YWxCYXJzW3lJbmRleF1beEluZGV4XS54UG9zIDwgemVyb0F4aXNQb3NWYWwgJiZcbiAgICAgICAgICBzaW1wbGlmaWVkSG9yaXpvbnRhbEJhcnNbeUluZGV4XVt4SW5kZXhdLndpZHRoID4gMDtcbiAgICAgICAgY29uc3QgeE9mZnNldCA9IGJhcklzTmVnYXRpdmVcbiAgICAgICAgICA/IC1jaGFydFNpemluZ1ZhbHVlcy5kYXRhTGFiZWxQYWRkaW5nXG4gICAgICAgICAgOiBzaW1wbGlmaWVkSG9yaXpvbnRhbEJhcnNbeUluZGV4XVt4SW5kZXhdLndpZHRoICtcbiAgICAgICAgICAgIGNoYXJ0U2l6aW5nVmFsdWVzLmRhdGFMYWJlbFBhZGRpbmc7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgZWxlbWVudFR5cGU6ICdkYXRhTGFiZWwnLFxuICAgICAgICAgIGxhYmVsOlxuICAgICAgICAgICAgcGlwZVRyYW5zZm9ybSh2YWwsIGNoZWNrSWZTZWNvbmRhcnkoZGF0YSwgeUluZGV4LCB4SW5kZXgpKSA/PyAnJyxcbiAgICAgICAgICB5UG9zOiBzaW1wbGlmaWVkSG9yaXpvbnRhbEJhcnNbeUluZGV4XVt4SW5kZXhdLnlQb3MgKyB5T2Zmc2V0LFxuICAgICAgICAgIHhQb3M6IHNpbXBsaWZpZWRIb3Jpem9udGFsQmFyc1t5SW5kZXhdW3hJbmRleF0ueFBvcyArIHhPZmZzZXQsXG4gICAgICAgICAgYW5jaG9yOiBiYXJJc05lZ2F0aXZlID8gJ2VuZCcgOiAnc3RhcnQnLFxuICAgICAgICB9O1xuICAgICAgfSk7XG4gICAgICByZXR1cm4gc3ViTGFiZWxzO1xuICAgIH0pO1xuICAgIGlmIChzdXBwWXMpIHtcbiAgICAgIGNvbnN0IHN1cHBEYXRhTGFiZWxzOiBEYXRhTGFiZWxbXSA9IHN1cHBZcy5mbGF0TWFwKCh5LCB5SW5kZXgpID0+IHtcbiAgICAgICAgY29uc3Qgc3ViTGFiZWxzOiBEYXRhTGFiZWxbXSA9IHkudmFsdWVzLm1hcCgodmFsLCB4SW5kZXgpID0+IHtcbiAgICAgICAgICBjb25zdCBiYXJJc05lZ2F0aXZlID1cbiAgICAgICAgICAgIHNpbXBsaWZpZWRTdXBwSG9yaXpvbnRhbEJhcnNbeUluZGV4XVt4SW5kZXhdLnhQb3MgPFxuICAgICAgICAgICAgICB6ZXJvQXhpc1Bvc1ZhbCAmJlxuICAgICAgICAgICAgc2ltcGxpZmllZFN1cHBIb3Jpem9udGFsQmFyc1t5SW5kZXhdW3hJbmRleF0ud2lkdGggPiAwO1xuICAgICAgICAgIGNvbnN0IHhPZmZzZXQgPSBiYXJJc05lZ2F0aXZlXG4gICAgICAgICAgICA/IC1jaGFydFNpemluZ1ZhbHVlcy5kYXRhTGFiZWxQYWRkaW5nXG4gICAgICAgICAgICA6IHNpbXBsaWZpZWRTdXBwSG9yaXpvbnRhbEJhcnNbeUluZGV4XVt4SW5kZXhdLndpZHRoICtcbiAgICAgICAgICAgICAgY2hhcnRTaXppbmdWYWx1ZXMuZGF0YUxhYmVsUGFkZGluZztcbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgZWxlbWVudFR5cGU6ICdkYXRhTGFiZWwnLFxuICAgICAgICAgICAgbGFiZWw6XG4gICAgICAgICAgICAgIHBpcGVUcmFuc2Zvcm0oXG4gICAgICAgICAgICAgICAgdmFsLFxuICAgICAgICAgICAgICAgIGNoZWNrSWZTZWNvbmRhcnkoZGF0YSwgeUluZGV4LCB4SW5kZXgsIHRydWUpLFxuICAgICAgICAgICAgICApID8/ICcnLFxuICAgICAgICAgICAgeVBvczogc2ltcGxpZmllZFN1cHBIb3Jpem9udGFsQmFyc1t5SW5kZXhdW3hJbmRleF0ueVBvcyArIHlPZmZzZXQsXG4gICAgICAgICAgICB4UG9zOiBzaW1wbGlmaWVkU3VwcEhvcml6b250YWxCYXJzW3lJbmRleF1beEluZGV4XS54UG9zICsgeE9mZnNldCxcbiAgICAgICAgICAgIGFuY2hvcjogYmFySXNOZWdhdGl2ZSA/ICdlbmQnIDogJ3N0YXJ0JyxcbiAgICAgICAgICB9O1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHN1YkxhYmVscztcbiAgICAgIH0pO1xuICAgICAgZGF0YUxhYmVscy5wdXNoKC4uLnN1cHBEYXRhTGFiZWxzKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBob3Zlcihwb3M6IHtcbiAgICAgIHJlY3Q6IERPTVJlY3Q7XG4gICAgICB4OiBudW1iZXI7XG4gICAgICB5OiBudW1iZXI7XG4gICAgICBjb250YWluZXJTY3JvbGxYOiBudW1iZXI7XG4gICAgICBjb250YWluZXJTY3JvbGxZOiBudW1iZXI7XG4gICAgfSk6IEhvdmVyUmV0dXJuIHtcbiAgICAgIGNvbnN0IHJlYWxQb3NYID0gcG9zLnggKyBwb3MuY29udGFpbmVyU2Nyb2xsWDtcbiAgICAgIGNvbnN0IHJlYWxQb3NZID0gcG9zLnkgKyBwb3MuY29udGFpbmVyU2Nyb2xsWTtcbiAgICAgIGlmIChcbiAgICAgICAgY2hhcnRTaXppbmdWYWx1ZXMgPT09IG51bGwgfHxcbiAgICAgICAgZ2V0SWZIb3Zlck91dE9mQm91bmRzKFxuICAgICAgICAgIHBvcy54LFxuICAgICAgICAgIHBvcy55LFxuICAgICAgICAgIHJlYWxQb3NYLFxuICAgICAgICAgIHJlYWxQb3NZLFxuICAgICAgICAgIGNoYXJ0U2l6aW5nVmFsdWVzLFxuICAgICAgICAgIGRpbWVuc2lvbnMsXG4gICAgICAgIClcbiAgICAgICkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cblxuICAgICAgY29uc3Qgc3VwcFlzID0gaGFzU3VwcGxlbWVudGFyeURhdGEoZGF0YSkgPyBkYXRhLnN1cHBsZW1lbnRhcnlZcyA6IG51bGw7XG4gICAgICBjb25zdCB4SG92ZXJJbmRpY2VzID0gZ2V0QnVja2V0QW5kQ2x1c3Rlck51bUZvckhvdmVyKFxuICAgICAgICByZWFsUG9zWSxcbiAgICAgICAgY2hhcnRTaXppbmdWYWx1ZXMsXG4gICAgICAgIGRhdGEsXG4gICAgICAgIGNvbmZpZyxcbiAgICAgICAgZGF0YS54Lmxlbmd0aCxcbiAgICAgICk7XG4gICAgICBpZiAoIXhIb3ZlckluZGljZXMpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9XG4gICAgICBjb25zdCB7XG4gICAgICAgIGJ1Y2tldE51bTogeEluZGV4LFxuICAgICAgICBjbHVzdGVyTnVtLFxuICAgICAgICBjbHVzdGVyTm9ybUNvdW50LFxuICAgICAgICBjbHVzdGVyTnVtVHlwZSxcbiAgICAgIH0gPSB4SG92ZXJJbmRpY2VzO1xuXG4gICAgICBsZXQgeCA9IGNhbGN1bGF0ZUJhclBvc2l0aW9uKFxuICAgICAgICBkYXRhLFxuICAgICAgICBjb25maWcsXG4gICAgICAgIGNoYXJ0U2l6aW5nVmFsdWVzLFxuICAgICAgICB4SW5kZXgsXG4gICAgICAgIGNsdXN0ZXJOdW0sXG4gICAgICApO1xuICAgICAgbGV0IGlzU3VwcFZhbHVlOiBib29sZWFuID0gZmFsc2U7XG4gICAgICBsZXQgc3VwcEluZGV4VmFsID0gMDtcbiAgICAgIGlmIChzdXBwWXMpIHtcbiAgICAgICAgc3VwcEluZGV4VmFsID0gY2x1c3Rlck51bSAtIGNsdXN0ZXJOb3JtQ291bnQ7XG4gICAgICAgIGlmIChjbHVzdGVyTnVtVHlwZSA9PT0gJ3N1cHAnKSB7XG4gICAgICAgICAgaXNTdXBwVmFsdWUgPSB0cnVlO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIC8vIFdoZW4gaG92ZXJpbmcgc3VwcGxlbWVudGFyeSB2YWx1ZXMsIGdldCBiYXJzIGZvciB0aGF0IHN1cHBsZW1lbnRhbCBsYXllclxuICAgICAgLy8gV2hlbiBob3ZlcmluZyBvcmlnaW5hbCBZcywgZ2V0IGJhcnMgZm9yIG9yaWdpbmFsIFlzXG4gICAgICBjb25zdCBmdWxsWXMgPVxuICAgICAgICBoYXNTdXBwbGVtZW50YXJ5RGF0YShkYXRhKSAmJiBpc1N1cHBWYWx1ZVxuICAgICAgICAgID8gKFxuICAgICAgICAgICAgICBkYXRhLnN1cHBsZW1lbnRhcnlZcy5maWx0ZXIoXG4gICAgICAgICAgICAgICAgcyA9PiBzLnN1cHBsZW1lbnRhbEluZGV4ID09PSBzdXBwSW5kZXhWYWwsXG4gICAgICAgICAgICAgICkgPz8gW11cbiAgICAgICAgICAgICkubWFwKHN1cHBZID0+XG4gICAgICAgICAgICAgIGdldEJhclhJbmZvKFxuICAgICAgICAgICAgICAgIGRhdGEsXG4gICAgICAgICAgICAgICAgY29uZmlnLFxuICAgICAgICAgICAgICAgIGRhdGEuc3VwcGxlbWVudGFyeVlzLmluZGV4T2Yoc3VwcFkpLFxuICAgICAgICAgICAgICAgIHhJbmRleCxcbiAgICAgICAgICAgICAgICBzY2FsZSxcbiAgICAgICAgICAgICAgICB0cnVlLFxuICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgKVxuICAgICAgICAgIDogZGF0YS55cy5tYXAoKF8sIG1hcFlJbmRleCkgPT5cbiAgICAgICAgICAgICAgZ2V0QmFyWEluZm8oZGF0YSwgY29uZmlnLCBtYXBZSW5kZXgsIHhJbmRleCwgc2NhbGUpLFxuICAgICAgICAgICAgKTtcbiAgICAgIGNvbnN0IHlzID0gZnVsbFlzLm1hcCh5ID0+IHkueFZhbHVlKTtcbiAgICAgIGxldCB2aXNpYmxlWUluZGV4ID0gLTE7XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGZ1bGxZcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBjb25zdCBsZWZ0Qm9yZGVyID0gZnVsbFlzW2ldLnhWYWx1ZTtcbiAgICAgICAgY29uc3QgcmlnaHRCb3JkZXJDYW5kaWRhdGVzID0gZnVsbFlzXG4gICAgICAgICAgLmZpbHRlcih5ID0+IHkueFZhbHVlID4gbGVmdEJvcmRlcilcbiAgICAgICAgICAubWFwKHkgPT4geS54VmFsdWUpO1xuICAgICAgICBjb25zdCByaWdodEJvcmRlciA9XG4gICAgICAgICAgcmlnaHRCb3JkZXJDYW5kaWRhdGVzLmxlbmd0aCA+IDBcbiAgICAgICAgICAgID8gTWF0aC5taW4oLi4ucmlnaHRCb3JkZXJDYW5kaWRhdGVzKVxuICAgICAgICAgICAgOiBsZWZ0Qm9yZGVyICsgZnVsbFlzW2ldLndpZHRoO1xuICAgICAgICBpZiAocmVhbFBvc1ggPiBsZWZ0Qm9yZGVyICYmIHJlYWxQb3NYIDwgcmlnaHRCb3JkZXIpIHtcbiAgICAgICAgICB2aXNpYmxlWUluZGV4ID0gaTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKGlzQ2x1c3RlcmVkRGF0YShkYXRhLCBjb25maWcsIGZhbHNlKSkge1xuICAgICAgICB2aXNpYmxlWUluZGV4ID0gY2x1c3Rlck51bTtcbiAgICAgIH1cblxuICAgICAgaWYgKHZpc2libGVZSW5kZXggPT09IC0xKSB7XG4gICAgICAgIGlmIChyZWFsUG9zWCA+PSB6ZXJvQXhpc1Bvc1ZhbCkge1xuICAgICAgICAgIHZpc2libGVZSW5kZXggPSB5cy5pbmRleE9mKE1hdGgubWF4KC4uLnlzKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdmlzaWJsZVlJbmRleCA9IHlzLmluZGV4T2YoTWF0aC5taW4oLi4ueXMpKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgLy8gRm9yIHN1cHBsZW1lbnRhcnkgYmFyczogdmlzaWJsZVlJbmRleCBpcyBpbmRleCB3aXRoaW4gZmlsdGVyZWQgc3VwcGxlbWVudGFyeSBhcnJheVxuICAgICAgLy8gRm9yIG9yaWdpbmFsIFlzOiB2aXNpYmxlWUluZGV4IGlzIGluZGV4IHdpdGhpbiBvcmlnaW5hbCBZcyBhcnJheVxuICAgICAgY29uc3QgYWN0dWFsU3VwcFlJbmRleCA9XG4gICAgICAgIGhhc1N1cHBsZW1lbnRhcnlEYXRhKGRhdGEpICYmIGlzU3VwcFZhbHVlXG4gICAgICAgICAgPyBkYXRhLnN1cHBsZW1lbnRhcnlZcy5maW5kSW5kZXgoXG4gICAgICAgICAgICAgIHMgPT5cbiAgICAgICAgICAgICAgICBzLnN1cHBsZW1lbnRhbEluZGV4ID09PSBzdXBwSW5kZXhWYWwgJiZcbiAgICAgICAgICAgICAgICBkYXRhLnN1cHBsZW1lbnRhcnlZc1xuICAgICAgICAgICAgICAgICAgLmZpbHRlcihzMiA9PiBzMi5zdXBwbGVtZW50YWxJbmRleCA9PT0gc3VwcEluZGV4VmFsKVxuICAgICAgICAgICAgICAgICAgLmluZGV4T2YocykgPT09IHZpc2libGVZSW5kZXgsXG4gICAgICAgICAgICApID8/IC0xXG4gICAgICAgICAgOiAtMTtcblxuICAgICAgY29uc3QgeUluZGV4ID0gaXNTdXBwVmFsdWUgPyAwIDogdmlzaWJsZUluZGljZXNbdmlzaWJsZVlJbmRleF07XG5cbiAgICAgIC8vQ2hlY2sgaWYgd2UndmUgbGFuZGVkIG9uIGEgemVyby13aWR0aCBiYXIgKG9ubHkgcmVhbGx5IHJlbGV2YW50IG9uIGVuZHMpXG4gICAgICBjb25zdCBiYXJzVG9DaGVjayA9IGlzU3VwcFZhbHVlXG4gICAgICAgID8gc2ltcGxpZmllZFN1cHBIb3Jpem9udGFsQmFyc1xuICAgICAgICA6IHNpbXBsaWZpZWRIb3Jpem9udGFsQmFycztcbiAgICAgIGNvbnN0IGJhckluZGV4VG9DaGVjayA9IGlzU3VwcFZhbHVlID8gYWN0dWFsU3VwcFlJbmRleCA6IHZpc2libGVZSW5kZXg7XG5cbiAgICAgIGlmIChcbiAgICAgICAgYmFySW5kZXhUb0NoZWNrID49IDAgJiZcbiAgICAgICAgYmFyc1RvQ2hlY2tbYmFySW5kZXhUb0NoZWNrXVt4SW5kZXhdLndpZHRoID09PSAwICYmXG4gICAgICAgIGlzU3RhY2tlZERhdGEoY29uZmlnKVxuICAgICAgKSB7XG4gICAgICAgIGxldCBhbHRCYXJGb3VuZCA9IGZhbHNlO1xuICAgICAgICAvL0NoZWNrIHVwd2FyZHNcbiAgICAgICAgZm9yIChsZXQgaSA9IGJhckluZGV4VG9DaGVjayArIDE7IGkgPCBiYXJzVG9DaGVjay5sZW5ndGg7IGkrKykge1xuICAgICAgICAgIGlmIChhbHRCYXJGb3VuZCkge1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChiYXJzVG9DaGVja1tpXVt4SW5kZXhdLndpZHRoICE9PSAwKSB7XG4gICAgICAgICAgICBpZiAoaGFzU3VwcGxlbWVudGFyeURhdGEoZGF0YSkgJiYgaXNTdXBwVmFsdWUpIHtcbiAgICAgICAgICAgICAgdmlzaWJsZVlJbmRleCA9IGRhdGEuc3VwcGxlbWVudGFyeVlzXG4gICAgICAgICAgICAgICAgLmZpbHRlcihzID0+IHMuc3VwcGxlbWVudGFsSW5kZXggPT09IHN1cHBJbmRleFZhbClcbiAgICAgICAgICAgICAgICAuaW5kZXhPZihkYXRhLnN1cHBsZW1lbnRhcnlZc1tpXSkhO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgdmlzaWJsZVlJbmRleCA9IGk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBhbHRCYXJGb3VuZCA9IHRydWU7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy9DaGVjayBkb3dud2FyZHNcbiAgICAgICAgZm9yIChsZXQgaSA9IGJhckluZGV4VG9DaGVjayAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgICAgaWYgKGFsdEJhckZvdW5kKSB7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKGJhcnNUb0NoZWNrW2ldW3hJbmRleF0ud2lkdGggIT09IDApIHtcbiAgICAgICAgICAgIGlmIChoYXNTdXBwbGVtZW50YXJ5RGF0YShkYXRhKSAmJiBpc1N1cHBWYWx1ZSkge1xuICAgICAgICAgICAgICB2aXNpYmxlWUluZGV4ID0gZGF0YS5zdXBwbGVtZW50YXJ5WXNcbiAgICAgICAgICAgICAgICAuZmlsdGVyKHMgPT4gcy5zdXBwbGVtZW50YWxJbmRleCA9PT0gc3VwcEluZGV4VmFsKVxuICAgICAgICAgICAgICAgIC5pbmRleE9mKGRhdGEuc3VwcGxlbWVudGFyeVlzW2ldKSE7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICB2aXNpYmxlWUluZGV4ID0gaTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGFsdEJhckZvdW5kID0gdHJ1ZTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgY29uc3Qgb3JpZ2luYWxTdXBwWUluZGV4ID1cbiAgICAgICAgaXNTdXBwVmFsdWUgJiYgYWN0dWFsU3VwcFlJbmRleCA+PSAwXG4gICAgICAgICAgPyB2aXNpYmxlU3VwcEluZGljZXNbYWN0dWFsU3VwcFlJbmRleF1cbiAgICAgICAgICA6IC0xO1xuXG4gICAgICBjb25zdCBiYXJYUG9zID0gaXNTdXBwVmFsdWVcbiAgICAgICAgPyBzaW1wbGlmaWVkU3VwcEhvcml6b250YWxCYXJzW2FjdHVhbFN1cHBZSW5kZXhdW3hJbmRleF0ueFBvc1xuICAgICAgICA6IHNpbXBsaWZpZWRIb3Jpem9udGFsQmFyc1t2aXNpYmxlWUluZGV4XVt4SW5kZXhdLnhQb3M7XG4gICAgICBjb25zdCBiYXJZUG9zID0gaXNTdXBwVmFsdWVcbiAgICAgICAgPyBzaW1wbGlmaWVkU3VwcEhvcml6b250YWxCYXJzW2FjdHVhbFN1cHBZSW5kZXhdW3hJbmRleF0ueVBvc1xuICAgICAgICA6IHNpbXBsaWZpZWRIb3Jpem9udGFsQmFyc1t2aXNpYmxlWUluZGV4XVt4SW5kZXhdLnlQb3M7XG4gICAgICBjb25zdCBiYXJXaWR0aCA9IGlzU3VwcFZhbHVlXG4gICAgICAgID8gc2ltcGxpZmllZFN1cHBIb3Jpem9udGFsQmFyc1thY3R1YWxTdXBwWUluZGV4XVt4SW5kZXhdLndpZHRoXG4gICAgICAgIDogc2ltcGxpZmllZEhvcml6b250YWxCYXJzW3Zpc2libGVZSW5kZXhdW3hJbmRleF0ud2lkdGg7XG5cbiAgICAgIGNvbnN0IGxvY2FsQW5jaG9yWCA9IGJhclhQb3MgLSBwb3MuY29udGFpbmVyU2Nyb2xsWCAtIFNNQUxMX1BBRERJTkc7XG4gICAgICBjb25zdCB3aWR0aCA9IGJhcldpZHRoICsgU01BTExfUEFERElORyAqIDI7XG4gICAgICBjb25zdCBsb2NhbEFuY2hvclkgPSBiYXJZUG9zIC0gcG9zLmNvbnRhaW5lclNjcm9sbFk7XG4gICAgICBjb25zdCBoZWlnaHQgPSBjaGFydFNpemluZ1ZhbHVlcy5iYXJTaXplO1xuICAgICAgY29uc3QgeyBhbmNob3JYLCBhbmNob3JZLCBhbmNob3JXaWR0aCwgYW5jaG9ySGVpZ2h0IH0gPVxuICAgICAgICBjaGVja0FuY2hvcnNBZ2FpbnN0Qm91bmQoXG4gICAgICAgICAgbG9jYWxBbmNob3JYLFxuICAgICAgICAgIGxvY2FsQW5jaG9yWSxcbiAgICAgICAgICBkaW1lbnNpb25zLFxuICAgICAgICAgIHdpZHRoLFxuICAgICAgICAgIGhlaWdodCxcbiAgICAgICAgKTtcbiAgICAgIGNvbnN0IGFuY2hvciA9IG5ldyBET01SZWN0KFxuICAgICAgICBhbmNob3JYICsgcG9zLnJlY3QueCxcbiAgICAgICAgYW5jaG9yWSArIHBvcy5yZWN0LnksXG4gICAgICAgIGFuY2hvcldpZHRoLFxuICAgICAgICBhbmNob3JIZWlnaHQsXG4gICAgICApO1xuICAgICAgLy9XZSBuZWVkIHRvIHByZXNlcnZlIHRoZSBvcmlnaW5hbCBpbmRleCBmb3IgdGhlIGxhdGVyIGNoZWNrSWZTZWNvbmRhcnkgY2FsbFxuICAgICAgY29uc3QgeXNGb3JNZXRyaWNzOiB7XG4gICAgICAgIGRhdGE6IFN1cHBsZW1lbnRhcnlEYXRhWSB8IERhdGFZO1xuICAgICAgICBvcmlnaW5hbEluZGV4OiBudW1iZXI7XG4gICAgICB9W10gPVxuICAgICAgICBpc1N1cHBWYWx1ZSAmJiBzdXBwWXNcbiAgICAgICAgICA/IHN1cHBZc1xuICAgICAgICAgICAgICAubWFwKChzdXBwWSwgaW5kZXgpID0+ICh7IGRhdGE6IHN1cHBZLCBvcmlnaW5hbEluZGV4OiBpbmRleCB9KSlcbiAgICAgICAgICAgICAgLmZpbHRlcihzdXBwWSA9PiBzdXBwWS5kYXRhLnN1cHBsZW1lbnRhbEluZGV4ID09PSBzdXBwSW5kZXhWYWwpXG4gICAgICAgICAgOiBkYXRhLnlzLm1hcCgoeSwgaW5kZXgpID0+ICh7IGRhdGE6IHksIG9yaWdpbmFsSW5kZXg6IGluZGV4IH0pKTtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGhvdmVyVHlwZTogJ3N0YW5kYXJkJyxcbiAgICAgICAgeCxcbiAgICAgICAgeEluZGV4LFxuICAgICAgICB5cyxcbiAgICAgICAgeUluZGV4LFxuICAgICAgICB2aXNpYmxlWUluZGV4LFxuICAgICAgICAuLi4oaXNTdXBwVmFsdWUgJiYgb3JpZ2luYWxTdXBwWUluZGV4ID49IDBcbiAgICAgICAgICA/IHsgaXNTdXBwVmFsdWUsIHN1cHBZSW5kZXg6IG9yaWdpbmFsU3VwcFlJbmRleCB9XG4gICAgICAgICAgOiB7fSksXG4gICAgICAgIHRvb2x0aXA6IHtcbiAgICAgICAgICBhbmNob3IsXG4gICAgICAgICAgZGF0ZTpcbiAgICAgICAgICAgIGRhdGEudHlwZSA9PT0gJ2xhYmVsZWQnXG4gICAgICAgICAgICAgID8gZGF0YS54W3hJbmRleF0ubGFiZWxcbiAgICAgICAgICAgICAgOiB1dGNGb3JtYXQoJyVCICVkLCAlWScpKG5ldyBEYXRlKGRhdGEueFt4SW5kZXhdKSksXG4gICAgICAgICAgbWV0cmljczogeXNGb3JNZXRyaWNzXG4gICAgICAgICAgICAubWFwKHkgPT4gKHtcbiAgICAgICAgICAgICAgY29sb3I6IGdldENvbG9yKHkuZGF0YSwgY29sb3JJbmRpY2VzLCBjb25maWcuY29sb3JzKSxcbiAgICAgICAgICAgICAgbGFiZWw6IHkuZGF0YS5sYWJlbCxcbiAgICAgICAgICAgICAgcGF0dGVybjogeS5kYXRhLnBhdHRlcm4sXG4gICAgICAgICAgICAgIHZhbHVlOiBwaXBlVHJhbnNmb3JtKFxuICAgICAgICAgICAgICAgIHkuZGF0YS52YWx1ZXNbeEluZGV4XSxcbiAgICAgICAgICAgICAgICBjaGVja0lmU2Vjb25kYXJ5KGRhdGEsIHkub3JpZ2luYWxJbmRleCwgeEluZGV4LCBpc1N1cHBWYWx1ZSksXG4gICAgICAgICAgICAgICAgdHJ1ZSxcbiAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgIH0pKVxuICAgICAgICAgICAgLmZpbHRlcigoXywgaSkgPT4gY29uZmlnLmdyb3VwZWRUb29sdGlwIHx8IGkgPT09IHZpc2libGVZSW5kZXgpLFxuICAgICAgICB9LFxuICAgICAgfTtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgY2hhcnRXaWR0aDogY2hhcnRTaXppbmdWYWx1ZXMudG90YWxXaWR0aCxcbiAgICAgIGNoYXJ0SGVpZ2h0OiBjaGFydFNpemluZ1ZhbHVlcy50b3RhbEhlaWdodCxcbiAgICAgIGNoYXJ0U2l6aW5nVmFsdWVzLFxuICAgICAgeFRpY2tzOiB4VGlja3MsXG4gICAgICB5VGlja3M6IHlUaWNrcyxcbiAgICAgIGhvdmVyLFxuICAgICAgY29sb3JzLFxuICAgICAgYmFyczogW10sXG4gICAgICBsaW5lczogW10sXG4gICAgICBjaXJjbGVzOiBbXSxcbiAgICAgIGFyZWFzOiBbXSxcbiAgICAgIGFyY3M6IFtdLFxuICAgICAgaG9yaXpvbnRhbEJhcnMsXG4gICAgICBkYXRhTGFiZWxzLFxuICAgICAgd2F0ZXJmYWxsTGluZXM6IFtdLFxuICAgICAgZ3JhZGllbnRzOiBbXSxcbiAgICAgIGZsb3dDb25uZWN0aW9uczogW10sXG4gICAgICBob3Jpem9udGFsQ29udGFpbmVyU2NhbGU6IGNoYXJ0U2l6aW5nVmFsdWVzLmhvcml6b250YWxDb250YWluZXJTY2FsZSxcbiAgICAgIHZlcnRpY2FsQ29udGFpbmVyU2NhbGU6IGNoYXJ0U2l6aW5nVmFsdWVzLnZlcnRpY2FsQ29udGFpbmVyU2NhbGUsXG4gICAgICBjaGFydEVycm9yOiBudWxsLFxuICAgIH07XG4gIH1cblxuICBmdW5jdGlvbiBhcmNzKFxuICAgIGNvbmZpZzogRG9udXRDb25maWcsXG4gICAgYWxsRGF0YTogSW5wdXREYXRhLFxuICAgIGRpbWVuc2lvbnM6IERpbWVuc2lvbnMsXG4gICk6IFJlbmRlcmVkQ2hhcnQge1xuICAgIGlmICghd2FybkZsb3dEYXRhKGFsbERhdGEsICdkb251dCcpKSB7XG4gICAgICByZXR1cm4geyAuLi5lbXB0eUNoYXJ0LCBjaGFydEVycm9yOiAnY29uZmlnJyB9O1xuICAgIH1cbiAgICBpZiAoXG4gICAgICBjb25maWcuc2Vjb25kYXJ5VmFsdWVUeXBlICYmXG4gICAgICAoY29uZmlnLnZhbHVlVHlwZSA9PT0gJ3BlcmNlbnRhZ2UnIHx8XG4gICAgICAgIGNvbmZpZy5zZWNvbmRhcnlWYWx1ZVR5cGUgPT09ICdwZXJjZW50YWdlJylcbiAgICApIHtcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgIFwiSGVhZHMgdXAhIFR3byBheGVzIHdpdGggcGVyY2VudGFnZSBhcmVuJ3Qgc3VwcG9ydGVkIGZvciBkb251dCBjaGFydHNcIixcbiAgICAgICk7XG4gICAgICByZXR1cm4gZW1wdHlDaGFydDtcbiAgICB9XG4gICAgaWYgKGhhc1N1cHBsZW1lbnRhcnlEYXRhKGFsbERhdGEpKSB7XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29uc29sZVxuICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICBcIkhlYWRzIHVwISBTdXBwbGVtZW50YXJ5IHkgdmFsdWVzIGFyZW4ndCBzdXBwb3J0ZWQgZm9yIG5vbi1iYXIgY2hhcnRzXCIsXG4gICAgICApO1xuICAgICAgcmV0dXJuIGVtcHR5Q2hhcnQ7XG4gICAgfVxuICAgIHdhcm5VbnN1cHBvcnRlZFBhdHRlcm5zKGFsbERhdGEsIFtdLCAnZG9udXQnKTtcbiAgICBjb25zdCB7IGRhdGE6IHVuc3RhY2tlZERhdGEsIHZpc2libGVJbmRpY2VzIH0gPSBoaWRlKGFsbERhdGEpO1xuICAgIGNvbnN0IGRvbnV0RGF0YSA9IENoYXJ0LmNvbnZlcnRDaGFydERhdGFUb0RvbnV0RGF0YSh1bnN0YWNrZWREYXRhKTtcbiAgICBjb25zdCBoYXNOb25aZXJvVmFsdWUgPSBkb251dERhdGEuc29tZShkID0+IGQudmFsdWUgPiAwKTtcbiAgICBjb25zdCBhcmNEYXRhID0gaGFzTm9uWmVyb1ZhbHVlXG4gICAgICA/IGRvbnV0RGF0YVxuICAgICAgOiBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgbGFiZWw6ICcnLFxuICAgICAgICAgICAgdmFsdWU6IDEsXG4gICAgICAgICAgfSxcbiAgICAgICAgXTtcbiAgICBjb25zdCBjb2xvcnMgPSBoYXNOb25aZXJvVmFsdWVcbiAgICAgID8gdmlzaWJsZUluZGljZXMubWFwKGkgPT4gY29uZmlnLmNvbG9yc1tpICUgY29uZmlnLmNvbG9ycy5sZW5ndGhdKVxuICAgICAgOiBbJy0tZ3JheS0zMCddO1xuICAgIGNvbnN0IHsgcGlwZVRyYW5zZm9ybSB9ID0gZ2V0Rm9ybWF0dGluZ0FuZENvbG9ycyhcbiAgICAgIGFsbERhdGEsXG4gICAgICB1bnN0YWNrZWREYXRhLFxuICAgICAgY29uZmlnLFxuICAgICk7XG5cbiAgICBjb25zdCBkb251dERlZmF1bHRDb25maWcgPSBEZWZhdWx0RG9udXRTaXppbmdDb25maWc7XG4gICAgY29uc3QgZGF0YUxhYmVsUGFkZGluZ0NvbmZpZyA9IGdldEVsZW1lbnRTY2FsaW5nSW5mbyhcbiAgICAgIGNvbmZpZy5kb251dERpc3BsYXlJbmZvLnNjYWxpbmdDb25maWc/LmVsZW1lbnRTY2FsZXMsXG4gICAgICBkb251dERlZmF1bHRDb25maWcuZWxlbWVudFNjYWxlcyxcbiAgICAgICdkYXRhTGFiZWxQYWRkaW5nJyxcbiAgICApO1xuICAgIGNvbnN0IGZvbnRTaXplQ29uZmlnID0gZ2V0RWxlbWVudFNjYWxpbmdJbmZvKFxuICAgICAgY29uZmlnLmRvbnV0RGlzcGxheUluZm8uc2NhbGluZ0NvbmZpZz8uZWxlbWVudFNjYWxlcyxcbiAgICAgIGRvbnV0RGVmYXVsdENvbmZpZy5lbGVtZW50U2NhbGVzLFxuICAgICAgJ2ZvbnRTaXplJyxcbiAgICApO1xuICAgIGNvbnN0IGRhdGFMYWJlbFRleHRTaXppbmcgPSBnZXREYXRhTGFiZWxTaXplKFxuICAgICAgdW5zdGFja2VkRGF0YSxcbiAgICAgIHBpcGVUcmFuc2Zvcm0sXG4gICAgICBmb250U2l6ZUNvbmZpZy50YXJnZXQsXG4gICAgKTtcblxuICAgIGNvbnN0IGhvcml6b250YWxDb250YWluZXJTY2FsZSA9XG4gICAgICBjb25maWcuZG9udXREaXNwbGF5SW5mby5zY2FsaW5nQ29uZmlnPy5ob3Jpem9udGFsQ29udGFpbmVyU2NhbGUgIT09XG4gICAgICB1bmRlZmluZWRcbiAgICAgICAgPyBjb25maWcuZG9udXREaXNwbGF5SW5mby5zY2FsaW5nQ29uZmlnLmhvcml6b250YWxDb250YWluZXJTY2FsZVxuICAgICAgICA6IGRvbnV0RGVmYXVsdENvbmZpZy5ob3Jpem9udGFsQ29udGFpbmVyU2NhbGU7XG4gICAgY29uc3QgdmVydGljYWxDb250YWluZXJTY2FsZSA9XG4gICAgICBjb25maWcuZG9udXREaXNwbGF5SW5mby5zY2FsaW5nQ29uZmlnPy52ZXJ0aWNhbENvbnRhaW5lclNjYWxlICE9PVxuICAgICAgdW5kZWZpbmVkXG4gICAgICAgID8gY29uZmlnLmRvbnV0RGlzcGxheUluZm8uc2NhbGluZ0NvbmZpZy52ZXJ0aWNhbENvbnRhaW5lclNjYWxlXG4gICAgICAgIDogZG9udXREZWZhdWx0Q29uZmlnLnZlcnRpY2FsQ29udGFpbmVyU2NhbGU7XG4gICAgY29uc3Qgb3V0ZXJSYWRpdXNDb25maWcgPVxuICAgICAgY29uZmlnLmRvbnV0RGlzcGxheUluZm8uc2NhbGluZ0NvbmZpZz8ub3V0ZXJSYWRpdXMgIT09IHVuZGVmaW5lZFxuICAgICAgICA/IGNvbmZpZy5kb251dERpc3BsYXlJbmZvLnNjYWxpbmdDb25maWcub3V0ZXJSYWRpdXNcbiAgICAgICAgOiBkb251dERlZmF1bHRDb25maWcub3V0ZXJSYWRpdXM7XG4gICAgY29uc3QgZHJhd1JhZGl1c0NvbmZpZyA9XG4gICAgICBjb25maWcuZG9udXREaXNwbGF5SW5mby5zY2FsaW5nQ29uZmlnPy5kcmF3UmFkaXVzICE9PSB1bmRlZmluZWRcbiAgICAgICAgPyBjb25maWcuZG9udXREaXNwbGF5SW5mby5zY2FsaW5nQ29uZmlnLmRyYXdSYWRpdXNcbiAgICAgICAgOiBkb251dERlZmF1bHRDb25maWcuZHJhd1JhZGl1cztcblxuICAgIGNvbnN0IG91dGVyID1cbiAgICAgIG91dGVyUmFkaXVzQ29uZmlnLnR5cGUgPT09ICdwcm9wb3J0aW9uJ1xuICAgICAgICA/IChkaW1lbnNpb25zLmhlaWdodCAvIDIpICogb3V0ZXJSYWRpdXNDb25maWcudmFsdWVcbiAgICAgICAgOiBvdXRlclJhZGl1c0NvbmZpZy52YWx1ZTtcbiAgICBjb25zdCBkcmF3UmFkaXVzID1cbiAgICAgIGRyYXdSYWRpdXNDb25maWcudHlwZSA9PT0gJ3Byb3BvcnRpb24nXG4gICAgICAgID8gb3V0ZXIgKiBkcmF3UmFkaXVzQ29uZmlnLnZhbHVlXG4gICAgICAgIDogZHJhd1JhZGl1c0NvbmZpZy52YWx1ZTtcbiAgICBjb25zdCBpbm5lciA9IG91dGVyIC0gZHJhd1JhZGl1cztcblxuICAgIGNvbnN0IHBpZUFyY3MgPSBwaWU8RG9udXREYXRhPigpXG4gICAgICAuc29ydFZhbHVlcyhudWxsKVxuICAgICAgLnZhbHVlKGQgPT4gTWF0aC5tYXgoZC52YWx1ZSwgMCkpKGFyY0RhdGEpO1xuXG4gICAgY29uc3QgYXJjcyA9IHBpZUFyY3MubWFwKHBpZUFyYyA9PlxuICAgICAgYXJjPERvbnV0RGF0YT4oKVxuICAgICAgICAuaW5uZXJSYWRpdXMoaW5uZXIpXG4gICAgICAgIC5vdXRlclJhZGl1cyhvdXRlcilcbiAgICAgICAgLnBhZEFuZ2xlKDAuMDEzKVxuICAgICAgICAuc3RhcnRBbmdsZShwaWVBcmMuc3RhcnRBbmdsZSlcbiAgICAgICAgLmVuZEFuZ2xlKHBpZUFyYy5lbmRBbmdsZSkocGllQXJjLmRhdGEpLFxuICAgICk7XG5cbiAgICBjb25zdCBkYXRhTGFiZWxzOiBEYXRhTGFiZWxbXSA9IGhhc05vblplcm9WYWx1ZVxuICAgICAgPyBwaWVBcmNzLm1hcChhcmMgPT4ge1xuICAgICAgICAgIC8vRG9uJ3Qgc2hvdyBkYXRhIGxhYmVscyBmb3IgemVyby13aWR0aCBkb251dCBzbGljZXMgKGluY2x1ZGVzIG5lZ2F0aXZlIHZhbHVlcylcbiAgICAgICAgICBpZiAoYXJjLnN0YXJ0QW5nbGUgPT09IGFyYy5lbmRBbmdsZSkge1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgZWxlbWVudFR5cGU6ICdkYXRhTGFiZWwnLFxuICAgICAgICAgICAgICBsYWJlbDogJycsXG4gICAgICAgICAgICAgIHlQb3M6IDAsXG4gICAgICAgICAgICAgIHhQb3M6IDAsXG4gICAgICAgICAgICAgIGFuY2hvcjogJ21pZGRsZScsXG4gICAgICAgICAgICB9O1xuICAgICAgICAgIH1cbiAgICAgICAgICBjb25zdCBhcmNDZW50ZXJBbmdsZSA9IChhcmMuc3RhcnRBbmdsZSArIGFyYy5lbmRBbmdsZSkgLyAyO1xuICAgICAgICAgIGNvbnN0IGVkZ2VQb2ludCA9IGFyY1RvUG9pbnQoYXJjQ2VudGVyQW5nbGUsIG91dGVyKTtcbiAgICAgICAgICBjb25zdCBsaW5lRW5kUG9pbnQgPSBhcmNUb1BvaW50KFxuICAgICAgICAgICAgYXJjQ2VudGVyQW5nbGUsXG4gICAgICAgICAgICBvdXRlciArIGRhdGFMYWJlbFBhZGRpbmdDb25maWcudGFyZ2V0LFxuICAgICAgICAgICk7XG4gICAgICAgICAgY29uc3QgbWlkZGxlQXJlYSA9IG91dGVyIC8gNDtcbiAgICAgICAgICBsZXQgeU9mZnNldCA9IDA7XG4gICAgICAgICAgbGV0IHhPZmZzZXQgPSAwO1xuICAgICAgICAgIGlmIChsaW5lRW5kUG9pbnQueSA+IDApIHtcbiAgICAgICAgICAgIGlmIChNYXRoLmFicyhsaW5lRW5kUG9pbnQueSkgPCBtaWRkbGVBcmVhKSB7XG4gICAgICAgICAgICAgIHlPZmZzZXQgPSBTTUFMTF9QQURESU5HIC8gMjtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHlPZmZzZXQgPSBTTUFMTF9QQURESU5HO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKE1hdGguYWJzKGxpbmVFbmRQb2ludC54KSA8IG1pZGRsZUFyZWEpIHtcbiAgICAgICAgICAgICAgeU9mZnNldCArPSBTTUFMTF9QQURESU5HIC8gMjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYgKE1hdGguYWJzKGxpbmVFbmRQb2ludC55KSA8IG1pZGRsZUFyZWEpIHtcbiAgICAgICAgICAgICAgeU9mZnNldCA9IFNNQUxMX1BBRERJTkcgLyAyO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKE1hdGguYWJzKGxpbmVFbmRQb2ludC54KSA8IG1pZGRsZUFyZWEpIHtcbiAgICAgICAgICAgICAgeU9mZnNldCAtPSBTTUFMTF9QQURESU5HIC8gMjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGVsZW1lbnRUeXBlOiAnZGF0YUxhYmVsJyxcbiAgICAgICAgICAgIGxhYmVsOiBwaXBlVHJhbnNmb3JtKGFyYy5kYXRhLnZhbHVlLCBhcmMuZGF0YS5pc1NlY29uZGFyeSksXG4gICAgICAgICAgICB5UG9zOiBsaW5lRW5kUG9pbnQueSArIHlPZmZzZXQsXG4gICAgICAgICAgICB4UG9zOiBsaW5lRW5kUG9pbnQueCArIHhPZmZzZXQsXG4gICAgICAgICAgICBhbmNob3I6XG4gICAgICAgICAgICAgIE1hdGguYWJzKGxpbmVFbmRQb2ludC54KSA8IG1pZGRsZUFyZWFcbiAgICAgICAgICAgICAgICA/ICdtaWRkbGUnXG4gICAgICAgICAgICAgICAgOiBsaW5lRW5kUG9pbnQueCA8IDBcbiAgICAgICAgICAgICAgICA/ICdlbmQnXG4gICAgICAgICAgICAgICAgOiAnc3RhcnQnLFxuICAgICAgICAgICAgbGluZToge1xuICAgICAgICAgICAgICB4MTogZWRnZVBvaW50LngsXG4gICAgICAgICAgICAgIHkxOiBlZGdlUG9pbnQueSxcbiAgICAgICAgICAgICAgeDI6IGxpbmVFbmRQb2ludC54LFxuICAgICAgICAgICAgICB5MjogbGluZUVuZFBvaW50LnksXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH07XG4gICAgICAgIH0pXG4gICAgICA6IFtdO1xuXG4gICAgY29uc3QgZHJhd1dpZHRoID1cbiAgICAgIChvdXRlciArXG4gICAgICAgIChjb25maWcuc2hvd0RhdGFMYWJlbHNcbiAgICAgICAgICA/IGRhdGFMYWJlbFBhZGRpbmdDb25maWcudGFyZ2V0ICsgZGF0YUxhYmVsVGV4dFNpemluZy5ob3Jpem9udGFsXG4gICAgICAgICAgOiAwKSkgKlxuICAgICAgMjtcbiAgICBjb25zdCBkcmF3SGVpZ2h0ID1cbiAgICAgIChvdXRlciArXG4gICAgICAgIChjb25maWcuc2hvd0RhdGFMYWJlbHNcbiAgICAgICAgICA/IGRhdGFMYWJlbFBhZGRpbmdDb25maWcudGFyZ2V0ICsgZGF0YUxhYmVsVGV4dFNpemluZy52ZXJ0aWNhbFxuICAgICAgICAgIDogMCkpICpcbiAgICAgIDI7XG5cbiAgICBmdW5jdGlvbiBob3Zlcihwb3M6IHtcbiAgICAgIHJlY3Q6IERPTVJlY3Q7XG4gICAgICB4OiBudW1iZXI7XG4gICAgICB5OiBudW1iZXI7XG4gICAgICBjb250YWluZXJTY3JvbGxYOiBudW1iZXI7XG4gICAgICBjb250YWluZXJTY3JvbGxZOiBudW1iZXI7XG4gICAgfSk6IEhvdmVyUmV0dXJuIHtcbiAgICAgIGNvbnN0IHJlYWxQb3NYID0gcG9zLnggKyBwb3MuY29udGFpbmVyU2Nyb2xsWDtcbiAgICAgIGNvbnN0IHJlYWxQb3NZID0gcG9zLnkgKyBwb3MuY29udGFpbmVyU2Nyb2xsWTtcbiAgICAgIGlmIChcbiAgICAgICAgZ2V0SWZIb3Zlck91dE9mQm91bmRzKFxuICAgICAgICAgIHBvcy54LFxuICAgICAgICAgIHBvcy55LFxuICAgICAgICAgIHJlYWxQb3NYLFxuICAgICAgICAgIHJlYWxQb3NZLFxuICAgICAgICAgIG51bGwsXG4gICAgICAgICAgZGltZW5zaW9ucyxcbiAgICAgICAgKVxuICAgICAgKSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfVxuICAgICAgY29uc3QgY2VudGVyUG9pbnRYID0gZGltZW5zaW9ucy53aWR0aCAvIDI7XG4gICAgICBjb25zdCBjZW50ZXJQb2ludFkgPSBkaW1lbnNpb25zLmhlaWdodCAvIDI7XG4gICAgICBjb25zdCBkb251dFBvc2l0aW9uWCA9IHJlYWxQb3NYIC0gY2VudGVyUG9pbnRYO1xuICAgICAgY29uc3QgZG9udXRQb3NpdGlvblkgPSByZWFsUG9zWSAtIGNlbnRlclBvaW50WTtcbiAgICAgIGNvbnN0IGhvdmVyUG9zQXJjSW5mbyA9IHBvaW50VG9BcmMoZG9udXRQb3NpdGlvblgsIGRvbnV0UG9zaXRpb25ZKTtcbiAgICAgIGNvbnN0IGFyY0NlbnRlckxpbmUgPSAob3V0ZXIgKyBpbm5lcikgLyAyO1xuXG4gICAgICAvL0RldGVjdCBkb251dCBzbGljZVxuICAgICAgbGV0IGZvdW5kWUluZGV4ID0gLTE7XG4gICAgICBsZXQgcHJlZmVycmVkUG9zaXRpb246IENhbGxvdXRDb21wb25lbnQuQW5jaG9yZWRQb3NpdGlvbiB8IHVuZGVmaW5lZCA9XG4gICAgICAgIHVuZGVmaW5lZDtcbiAgICAgIGxldCBkb251dFhQb3NpdGlvbiA9IDA7XG4gICAgICBsZXQgZG9udXRZUG9zaXRpb24gPSAwO1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBwaWVBcmNzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGNvbnN0IGFyYyA9IHBpZUFyY3NbaV07XG5cbiAgICAgICAgaWYgKFxuICAgICAgICAgIGhvdmVyUG9zQXJjSW5mby5hbmdsZSA+IGFyYy5zdGFydEFuZ2xlICYmXG4gICAgICAgICAgaG92ZXJQb3NBcmNJbmZvLmFuZ2xlIDwgYXJjLmVuZEFuZ2xlICYmXG4gICAgICAgICAgaG92ZXJQb3NBcmNJbmZvLnJhZGl1cyA+IGFyY0NlbnRlckxpbmUgLSBkcmF3UmFkaXVzICYmXG4gICAgICAgICAgaG92ZXJQb3NBcmNJbmZvLnJhZGl1cyA8IGFyY0NlbnRlckxpbmUgKyBkcmF3UmFkaXVzXG4gICAgICAgICkge1xuICAgICAgICAgIGZvdW5kWUluZGV4ID0gaTtcbiAgICAgICAgICBjb25zdCBhcmNDZW50ZXJQb2ludCA9IGFyY1RvUG9pbnQoXG4gICAgICAgICAgICAoYXJjLnN0YXJ0QW5nbGUgKyBhcmMuZW5kQW5nbGUpIC8gMixcbiAgICAgICAgICAgIGFyY0NlbnRlckxpbmUsXG4gICAgICAgICAgKTtcblxuICAgICAgICAgIC8vTmVlZCB0byB1bi1vZmZzZXQgdGhlIHBvc2l0aW9uc1xuICAgICAgICAgIGRvbnV0WFBvc2l0aW9uID0gYXJjQ2VudGVyUG9pbnQueCArIGNlbnRlclBvaW50WDtcbiAgICAgICAgICBkb251dFlQb3NpdGlvbiA9IGFyY0NlbnRlclBvaW50LnkgKyBjZW50ZXJQb2ludFk7XG4gICAgICAgICAgY29uc3QgdmVydGljYWxBcmVhID1cbiAgICAgICAgICAgIGFyY0NlbnRlclBvaW50LnkgPCAoZGltZW5zaW9ucy5oZWlnaHQgKiAtMSkgLyA0XG4gICAgICAgICAgICAgID8gJ3RvcCdcbiAgICAgICAgICAgICAgOiBhcmNDZW50ZXJQb2ludC55ID4gZGltZW5zaW9ucy5oZWlnaHQgLyA0XG4gICAgICAgICAgICAgID8gJ2JvdHRvbSdcbiAgICAgICAgICAgICAgOiAnY2VudGVyJztcblxuICAgICAgICAgIC8vRGV0ZXJtaW5lIHRoZSBiZXN0IHBvc2l0aW9uIGZvciB0aGUgdG9vbHRpcFxuICAgICAgICAgIGlmIChhcmNDZW50ZXJQb2ludC54ID4gMCkge1xuICAgICAgICAgICAgLy9SaWdodCBwYXRoXG4gICAgICAgICAgICBpZiAoIWNvbmZpZy5ncm91cGVkVG9vbHRpcCB8fCB2ZXJ0aWNhbEFyZWEgPT09ICdjZW50ZXInKSB7XG4gICAgICAgICAgICAgIHByZWZlcnJlZFBvc2l0aW9uID0gJ2NlbnRlci1yaWdodCc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHZlcnRpY2FsQXJlYSA9PT0gJ3RvcCcpIHtcbiAgICAgICAgICAgICAgcHJlZmVycmVkUG9zaXRpb24gPSAncmlnaHQtdG9wJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAodmVydGljYWxBcmVhID09PSAnYm90dG9tJykge1xuICAgICAgICAgICAgICBwcmVmZXJyZWRQb3NpdGlvbiA9ICdyaWdodC1ib3R0b20nO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvL0xlZnQgcGF0aFxuICAgICAgICAgICAgaWYgKCFjb25maWcuZ3JvdXBlZFRvb2x0aXAgfHwgdmVydGljYWxBcmVhID09PSAnY2VudGVyJykge1xuICAgICAgICAgICAgICBwcmVmZXJyZWRQb3NpdGlvbiA9ICdjZW50ZXItbGVmdCc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHZlcnRpY2FsQXJlYSA9PT0gJ3RvcCcpIHtcbiAgICAgICAgICAgICAgcHJlZmVycmVkUG9zaXRpb24gPSAnbGVmdC10b3AnO1xuICAgICAgICAgICAgfSBlbHNlIGlmICh2ZXJ0aWNhbEFyZWEgPT09ICdib3R0b20nKSB7XG4gICAgICAgICAgICAgIHByZWZlcnJlZFBvc2l0aW9uID0gJ2xlZnQtYm90dG9tJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGlmIChmb3VuZFlJbmRleCA9PT0gLTEpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9XG4gICAgICBpZiAoIWhhc05vblplcm9WYWx1ZSkge1xuICAgICAgICBkb251dFhQb3NpdGlvbiA9IGNlbnRlclBvaW50WCArIGFyY0NlbnRlckxpbmU7XG4gICAgICAgIGRvbnV0WVBvc2l0aW9uID0gY2VudGVyUG9pbnRZO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBsb2NhbEFuY2hvclggPSBkb251dFhQb3NpdGlvbiAtIHBvcy5jb250YWluZXJTY3JvbGxYO1xuICAgICAgY29uc3QgbG9jYWxBbmNob3JZID0gZG9udXRZUG9zaXRpb24gLSBwb3MuY29udGFpbmVyU2Nyb2xsWTtcbiAgICAgIGNvbnN0IHsgYW5jaG9yWCwgYW5jaG9yWSB9ID0gY2hlY2tBbmNob3JzQWdhaW5zdEJvdW5kKFxuICAgICAgICBsb2NhbEFuY2hvclgsXG4gICAgICAgIGxvY2FsQW5jaG9yWSxcbiAgICAgICAgZGltZW5zaW9ucyxcbiAgICAgICk7XG4gICAgICBjb25zdCBhbmNob3IgPSBuZXcgRE9NUmVjdChcbiAgICAgICAgYW5jaG9yWCArIHBvcy5yZWN0LngsXG4gICAgICAgIGFuY2hvclkgKyBwb3MucmVjdC55LFxuICAgICAgICBTTUFMTF9QQURESU5HLFxuICAgICAgICAwLFxuICAgICAgKTtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGhvdmVyVHlwZTogJ3N0YW5kYXJkJyxcbiAgICAgICAgdG9vbHRpcDoge1xuICAgICAgICAgIGFuY2hvcixcbiAgICAgICAgICBwcmVmZXJyZWRQb3NpdGlvbixcbiAgICAgICAgICBkYXRlOiBudWxsLFxuICAgICAgICAgIG1ldHJpY3M6IGRvbnV0RGF0YVxuICAgICAgICAgICAgLm1hcCgoeSwgaW5kZXgpID0+ICh7XG4gICAgICAgICAgICAgIGNvbG9yOiBjb2xvcnNbaW5kZXggJSBjb2xvcnMubGVuZ3RoXSxcbiAgICAgICAgICAgICAgbGFiZWw6IHkubGFiZWwsXG4gICAgICAgICAgICAgIHZhbHVlOiBwaXBlVHJhbnNmb3JtKHkudmFsdWUsIHkuaXNTZWNvbmRhcnksIHRydWUpLFxuICAgICAgICAgICAgfSkpXG4gICAgICAgICAgICAuZmlsdGVyKChfLCBpKSA9PiBjb25maWcuZ3JvdXBlZFRvb2x0aXAgfHwgaSA9PT0gZm91bmRZSW5kZXgpLFxuICAgICAgICB9LFxuICAgICAgICAvL05vdCB1c2VkIGJ5IGRvbnV0IGNoYXJ0c1xuICAgICAgICB4OiAwLFxuICAgICAgICB4SW5kZXg6IDAsXG4gICAgICAgIHlzOiBbXSxcbiAgICAgICAgeUluZGV4OiAwLFxuICAgICAgICB2aXNpYmxlWUluZGV4OiAwLFxuICAgICAgfTtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgY2hhcnRXaWR0aDogZHJhd1dpZHRoLFxuICAgICAgY2hhcnRIZWlnaHQ6IGRyYXdIZWlnaHQsXG4gICAgICBjaGFydFNpemluZ1ZhbHVlczoge1xuICAgICAgICAuLi5lbXB0eUNoYXJ0U2NhbGVWYWx1ZXMsXG4gICAgICAgIGRhdGFMYWJlbFBhZGRpbmc6IGRhdGFMYWJlbFBhZGRpbmdDb25maWcudGFyZ2V0LFxuICAgICAgICBkYXRhTGFiZWxUZXh0U2l6ZTogZGF0YUxhYmVsVGV4dFNpemluZy5ob3Jpem9udGFsLFxuICAgICAgICBmb250U2l6ZTogZm9udFNpemVDb25maWcudGFyZ2V0LFxuICAgICAgfSxcbiAgICAgIHhUaWNrczogW10sXG4gICAgICB5VGlja3M6IFtdLFxuICAgICAgYXJlYXM6IFtdLFxuICAgICAgbGluZXM6IFtdLFxuICAgICAgY2lyY2xlczogW10sXG4gICAgICBiYXJzOiBbXSxcbiAgICAgIGNvbG9ycyxcbiAgICAgIGFyY3MsXG4gICAgICBob3Jpem9udGFsQmFyczogW10sXG4gICAgICBkYXRhTGFiZWxzLFxuICAgICAgd2F0ZXJmYWxsTGluZXM6IFtdLFxuICAgICAgZ3JhZGllbnRzOiBbXSxcbiAgICAgIGZsb3dDb25uZWN0aW9uczogW10sXG4gICAgICBob3Jpem9udGFsQ29udGFpbmVyU2NhbGUsXG4gICAgICB2ZXJ0aWNhbENvbnRhaW5lclNjYWxlLFxuICAgICAgY2hhcnRFcnJvcjogbnVsbCxcbiAgICAgIGhvdmVyLFxuICAgIH07XG4gIH1cblxuICBmdW5jdGlvbiBmbG93cyhcbiAgICBjb25maWc6IEZsb3dDb25maWcsXG4gICAgYWxsRGF0YTogSW5wdXREYXRhLFxuICAgIGRpbWVuc2lvbnM6IERpbWVuc2lvbnMsXG4gICk6IFJlbmRlcmVkQ2hhcnQge1xuICAgIGlmIChhbGxEYXRhLnR5cGUgIT09ICdmbG93Jykge1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgYEhlYWRzIHVwISBUaGUgJyR7YWxsRGF0YS50eXBlfScgZGF0YSB0eXBlIGlzbid0IHN1cHBvcnRlZCBmb3IgZmxvdyBjaGFydHMuYCxcbiAgICAgICk7XG4gICAgICByZXR1cm4geyAuLi5lbXB0eUNoYXJ0LCBjaGFydEVycm9yOiAnY29uZmlnJyB9O1xuICAgIH1cblxuICAgIGNvbnN0IGRhdGEgPSBmbG93c1RyYW5zZm9ybShjb25maWcsIGFsbERhdGEpO1xuICAgIGlmIChkYXRhLngubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm4gZW1wdHlDaGFydDtcbiAgICB9XG4gICAgY29uc3Qgb3ZlcmFsbFRvdGFsID0gZGF0YS54WzBdLnRvdGFsQ291bnQ7XG5cbiAgICBjb25zdCBjaGFydFNpemluZ1ZhbHVlcyA9IGdldEZ1bGxDaGFydFNjYWxlVmFsdWVzKFxuICAgICAgY29uZmlnLFxuICAgICAgZGF0YSxcbiAgICAgIGRpbWVuc2lvbnMsXG4gICAgICBudWxsLFxuICAgICAgbnVsbCxcbiAgICApO1xuICAgIGlmIChjaGFydFNpemluZ1ZhbHVlcyA9PT0gbnVsbCkge1xuICAgICAgcmV0dXJuIHsgLi4uZW1wdHlDaGFydCwgY2hhcnRFcnJvcjogJ3NpemluZycgfTtcbiAgICB9XG5cbiAgICBjb25zdCB7IHNjYWxlIH0gPSBjYWxjRGF0YUF4aXNTY2FsZXNBbmRUaWNrcyhcbiAgICAgIGRhdGEsXG4gICAgICBudWxsLFxuICAgICAgY29uZmlnLFxuICAgICAgY2hhcnRTaXppbmdWYWx1ZXMsXG4gICAgKTtcbiAgICBjb25zdCB2YWx1ZVBpcGVzID0gZ2V0UGlwZXMoY29uZmlnLnZhbHVlVHlwZSk7XG4gICAgY29uc3QgcGVyY2VudFBpcGVzID0gZ2V0UGlwZXMoJ3BlcmNlbnRhZ2UnKTtcblxuICAgIGNvbnN0IGJhcnM6IEZsb3dSZWN0W11bXSA9IFtdO1xuICAgIGNvbnN0IGZsb3dDb25uZWN0aW9uczogRmxvd0Nvbm5lY3Rpb25SZW5kZXJbXSA9IFtdO1xuICAgIGNvbnN0IGRhdGFMYWJlbHM6IEZsb3dEYXRhTGFiZWxbXSA9IFtdO1xuICAgIGNvbnN0IG1pbmltdW1TaXplID0gZ2V0TWluaW11bURhdGFFbGVtZW50U2l6ZShjb25maWcpO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZGF0YS54Lmxlbmd0aDsgaSsrKSB7XG4gICAgICBjb25zdCBidWNrZXRCYXJzOiBGbG93UmVjdFtdID0gW107XG4gICAgICBsZXQgcnVubmluZ0hlaWdodCA9IDA7XG4gICAgICBmb3IgKGNvbnN0IGJhciBvZiBkYXRhLnhbaV0uc3ViQnVja2V0cykge1xuICAgICAgICBjb25zdCBjb250aW51aW5nQ291bnQgPSBiYXIuY29ubmVjdGlvbnNcbiAgICAgICAgICAuZmlsdGVyKGNvbm5lY3Rpb24gPT4gY29ubmVjdGlvbi5kaXJlY3Rpb24gPT09ICdmb3J3YXJkJylcbiAgICAgICAgICAubWFwKGNvbm5lY3Rpb24gPT4gY29ubmVjdGlvbi5jb3VudClcbiAgICAgICAgICAucmVkdWNlKChhLCBiKSA9PiBhICsgYiwgMCk7XG4gICAgICAgIGNvbnN0IHtcbiAgICAgICAgICB0b3RhbFNpemU6IHRvdGFsSGVpZ2h0LFxuICAgICAgICAgIGNvbnRpbnVpbmdTaXplOiBkYXJrZW5lZEhlaWdodCxcbiAgICAgICAgICBjb25uZWN0aW9uU2l6ZXMsXG4gICAgICAgIH0gPSBnZXRGbG93U3ViQnVja2V0U2l6ZXMoXG4gICAgICAgICAgYmFyLFxuICAgICAgICAgIHZhbHVlID0+IHNjYWxlKHZhbHVlLCBmYWxzZSkgLSBjaGFydFNpemluZ1ZhbHVlcy50b3RhbFRvcE9mZnNldCxcbiAgICAgICAgICBtaW5pbXVtU2l6ZSxcbiAgICAgICAgKTtcbiAgICAgICAgY29uc3QgY29ubmVjdGlvbkhlaWdodCA9IChjb25uZWN0aW9uOiBGbG93Q29ubmVjdGlvbik6IG51bWJlciA9PlxuICAgICAgICAgIGNvbm5lY3Rpb25TaXplc1tiYXIuY29ubmVjdGlvbnMuaW5kZXhPZihjb25uZWN0aW9uKV07XG4gICAgICAgIGNvbnN0IG5vbkRhcmtlbmVkSGVpZ2h0ID0gdG90YWxIZWlnaHQgLSBkYXJrZW5lZEhlaWdodDtcbiAgICAgICAgY29uc3QgZGFya2VuZWRZID0gcnVubmluZ0hlaWdodCArIGNoYXJ0U2l6aW5nVmFsdWVzLnRvdGFsVG9wT2Zmc2V0O1xuICAgICAgICBjb25zdCBub25EYXJrZW5lZFkgPSBkYXJrZW5lZFkgKyBkYXJrZW5lZEhlaWdodDtcblxuICAgICAgICBjb25zdCB3aWR0aCA9IGNoYXJ0U2l6aW5nVmFsdWVzLmJhclNpemU7XG4gICAgICAgIGNvbnN0IHggPVxuICAgICAgICAgIGNoYXJ0U2l6aW5nVmFsdWVzLnRvdGFsTGVmdE9mZnNldCArXG4gICAgICAgICAgaSAqIChjaGFydFNpemluZ1ZhbHVlcy5iYXJTaXplICsgY2hhcnRTaXppbmdWYWx1ZXMuYnVja2V0R2FwKTtcbiAgICAgICAgY29uc3QgY29sb3JPdmVycmlkZSA9IGNvbmZpZy5mbG93Q29uZmlnLnN1YkJ1Y2tldHNDb25maWcuZmluZChcbiAgICAgICAgICBiYyA9PiBiYy5idWNrZXRJZCA9PT0gYmFyLmlkLFxuICAgICAgICApPy5jb2xvcjtcbiAgICAgICAgaWYgKGRhcmtlbmVkSGVpZ2h0ID4gMCkge1xuICAgICAgICAgIGJ1Y2tldEJhcnMucHVzaCh7XG4gICAgICAgICAgICBlbGVtZW50VHlwZTogJ3JlY3QnLFxuICAgICAgICAgICAgcmVjdFR5cGU6ICdmbG93JyxcbiAgICAgICAgICAgIGhlaWdodDogZGFya2VuZWRIZWlnaHQsXG4gICAgICAgICAgICB3aWR0aCxcbiAgICAgICAgICAgIHk6IGRhcmtlbmVkWSxcbiAgICAgICAgICAgIHgsXG4gICAgICAgICAgICBjb2xvck92ZXJyaWRlLFxuICAgICAgICAgICAgZGFya2VuOiB0cnVlLFxuICAgICAgICAgICAgZGVFbXBoYXNpemU6IGlzRGVFbXBoYXNpemVkKGNvbmZpZywgYmFyLmlkLCB0cnVlKSxcbiAgICAgICAgICAgIGlkOiBiYXIuaWQsXG4gICAgICAgICAgICBidWNrZXRJbmRleDogaSxcbiAgICAgICAgICAgIGNvdW50OiBjb250aW51aW5nQ291bnQsXG4gICAgICAgICAgICB0b3RhbENvdW50OiBiYXIuY291bnQsXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG5vbkRhcmtlbmVkSGVpZ2h0ID4gMCkge1xuICAgICAgICAgIGJ1Y2tldEJhcnMucHVzaCh7XG4gICAgICAgICAgICBlbGVtZW50VHlwZTogJ3JlY3QnLFxuICAgICAgICAgICAgcmVjdFR5cGU6ICdmbG93JyxcbiAgICAgICAgICAgIGhlaWdodDogbm9uRGFya2VuZWRIZWlnaHQsXG4gICAgICAgICAgICB3aWR0aCxcbiAgICAgICAgICAgIHk6IG5vbkRhcmtlbmVkWSxcbiAgICAgICAgICAgIHgsXG4gICAgICAgICAgICBjb2xvck92ZXJyaWRlLFxuICAgICAgICAgICAgZGFya2VuOiBmYWxzZSxcbiAgICAgICAgICAgIGRlRW1waGFzaXplOiBpc0RlRW1waGFzaXplZChjb25maWcsIGJhci5pZCwgZmFsc2UpLFxuICAgICAgICAgICAgaWQ6IGJhci5pZCxcbiAgICAgICAgICAgIGJ1Y2tldEluZGV4OiBpLFxuICAgICAgICAgICAgY291bnQ6IGJhci5jb3VudCAtIGNvbnRpbnVpbmdDb3VudCxcbiAgICAgICAgICAgIHRvdGFsQ291bnQ6IGJhci5jb3VudCxcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICAvL0ludmlzaWJsZSBiYXIgZm9yIGhvdmVyIGhpZ2hsaWdodCBwdXJwb3Nlc1xuICAgICAgICBidWNrZXRCYXJzLnB1c2goe1xuICAgICAgICAgIGVsZW1lbnRUeXBlOiAncmVjdCcsXG4gICAgICAgICAgcmVjdFR5cGU6ICdmbG93JyxcbiAgICAgICAgICBoZWlnaHQ6IGRhcmtlbmVkSGVpZ2h0ICsgbm9uRGFya2VuZWRIZWlnaHQsXG4gICAgICAgICAgd2lkdGgsXG4gICAgICAgICAgeTogZGFya2VuZWRZLFxuICAgICAgICAgIHgsXG4gICAgICAgICAgbm9uRGlzcGxheTogdHJ1ZSxcbiAgICAgICAgICBpZDogYmFyLmlkLFxuICAgICAgICAgIGJ1Y2tldEluZGV4OiBpLFxuICAgICAgICAgIGNvdW50OiBiYXIuY291bnQsXG4gICAgICAgICAgdG90YWxDb3VudDogYmFyLmNvdW50LFxuICAgICAgICAgIGRhcmtlbjogZmFsc2UsXG4gICAgICAgICAgZGVFbXBoYXNpemU6IGZhbHNlLFxuICAgICAgICB9KTtcbiAgICAgICAgcnVubmluZ0hlaWdodCArPVxuICAgICAgICAgIHRvdGFsSGVpZ2h0ICtcbiAgICAgICAgICBjaGFydFNpemluZ1ZhbHVlcy5kYXRhTGFiZWxQYWRkaW5nICtcbiAgICAgICAgICBjaGFydFNpemluZ1ZhbHVlcy5kYXRhTGFiZWxUZXh0U2l6ZTtcblxuICAgICAgICAvL0Nvbm5lY3Rpb25zXG4gICAgICAgIC8vQWRkIG5ldyByZW5kZXJzIGZvciBmb3J3YXJkIGNvbm5lY3Rpb25zXG4gICAgICAgIGxldCB2ZXJ0aWNhbENvbm5lY3Rpb25PZmZzZXQgPSAwO1xuICAgICAgICBmb3IgKGNvbnN0IGNvbm5lY3Rpb24gb2YgYmFyLmNvbm5lY3Rpb25zLmZpbHRlcihcbiAgICAgICAgICBjb25uZWN0aW9uID0+IGNvbm5lY3Rpb24uZGlyZWN0aW9uID09PSAnZm9yd2FyZCcsXG4gICAgICAgICkpIHtcbiAgICAgICAgICBjb25zdCB0b3BMaW5lWTEgPSBkYXJrZW5lZFkgKyB2ZXJ0aWNhbENvbm5lY3Rpb25PZmZzZXQ7XG4gICAgICAgICAgY29uc3QgYm90dG9tTGluZVkxID0gdG9wTGluZVkxICsgY29ubmVjdGlvbkhlaWdodChjb25uZWN0aW9uKTtcbiAgICAgICAgICBjb25zdCB4MSA9IHggKyB3aWR0aDtcbiAgICAgICAgICBjb25zdCBjb25uZWN0aW9uUmVuZGVyOiBGbG93Q29ubmVjdGlvblJlbmRlciA9IHtcbiAgICAgICAgICAgIGVsZW1lbnRUeXBlOiAnY29ubmVjdGlvbicsXG4gICAgICAgICAgICBzdGFydDogY29ubmVjdGlvbi5zdGFydCxcbiAgICAgICAgICAgIGVuZDogY29ubmVjdGlvbi5lbmQsXG4gICAgICAgICAgICBjb3VudDogY29ubmVjdGlvbi5jb3VudCxcbiAgICAgICAgICAgIHN0ZXA6IGksXG4gICAgICAgICAgICB0b3BMaW5lOiB7XG4gICAgICAgICAgICAgIHkxOiB0b3BMaW5lWTEsXG4gICAgICAgICAgICAgIHgxLFxuICAgICAgICAgICAgICAvL1RvIGJlIGZpbGxlZCBpbiBsYXRlclxuICAgICAgICAgICAgICB5MjogMCxcbiAgICAgICAgICAgICAgeDI6IDAsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgYm90dG9tTGluZToge1xuICAgICAgICAgICAgICB5MTogYm90dG9tTGluZVkxLFxuICAgICAgICAgICAgICB4MSxcbiAgICAgICAgICAgICAgLy9UbyBiZSBmaWxsZWQgaW4gbGF0ZXJcbiAgICAgICAgICAgICAgeTI6IDAsXG4gICAgICAgICAgICAgIHgyOiAwLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIC8vVG8gYmUgZmlsbGVkIGluIGxhdGVyXG4gICAgICAgICAgICBwYXRoOiAnJyxcbiAgICAgICAgICB9O1xuICAgICAgICAgIHZlcnRpY2FsQ29ubmVjdGlvbk9mZnNldCArPSBjb25uZWN0aW9uSGVpZ2h0KGNvbm5lY3Rpb24pO1xuICAgICAgICAgIGZsb3dDb25uZWN0aW9ucy5wdXNoKGNvbm5lY3Rpb25SZW5kZXIpO1xuICAgICAgICB9XG4gICAgICAgIC8vQmFja2ZpbGwgcG9zaXRpb24gaW5mbyBmb3IgYmFja3dhcmRzIGNvbm5lY3Rpb25zXG4gICAgICAgIHZlcnRpY2FsQ29ubmVjdGlvbk9mZnNldCA9IDA7XG4gICAgICAgIGZvciAoY29uc3QgY29ubmVjdGlvbiBvZiBiYXIuY29ubmVjdGlvbnMuZmlsdGVyKFxuICAgICAgICAgIGNvbm5lY3Rpb24gPT4gY29ubmVjdGlvbi5kaXJlY3Rpb24gPT09ICdiYWNrd2FyZCcsXG4gICAgICAgICkpIHtcbiAgICAgICAgICBjb25zdCBtYXRjaGluZ0Nvbm5lY3Rpb24gPSBmbG93Q29ubmVjdGlvbnMuZmluZChcbiAgICAgICAgICAgIGNvbiA9PlxuICAgICAgICAgICAgICBjb24uc3RhcnQgPT09IGNvbm5lY3Rpb24uc3RhcnQgJiZcbiAgICAgICAgICAgICAgY29uLmVuZCA9PT0gY29ubmVjdGlvbi5lbmQgJiZcbiAgICAgICAgICAgICAgY29uLnN0ZXAgPT09IGkgLSAxLFxuICAgICAgICAgICk7XG4gICAgICAgICAgaWYgKG1hdGNoaW5nQ29ubmVjdGlvbikge1xuICAgICAgICAgICAgY29uc3QgdG9wTGluZVkyID0gZGFya2VuZWRZICsgdmVydGljYWxDb25uZWN0aW9uT2Zmc2V0O1xuICAgICAgICAgICAgY29uc3QgYm90dG9tTGluZVkyID0gdG9wTGluZVkyICsgY29ubmVjdGlvbkhlaWdodChjb25uZWN0aW9uKTtcbiAgICAgICAgICAgIG1hdGNoaW5nQ29ubmVjdGlvbi50b3BMaW5lLnkyID0gdG9wTGluZVkyO1xuICAgICAgICAgICAgbWF0Y2hpbmdDb25uZWN0aW9uLnRvcExpbmUueDIgPSB4O1xuICAgICAgICAgICAgbWF0Y2hpbmdDb25uZWN0aW9uLmJvdHRvbUxpbmUueTIgPSBib3R0b21MaW5lWTI7XG4gICAgICAgICAgICBtYXRjaGluZ0Nvbm5lY3Rpb24uYm90dG9tTGluZS54MiA9IHg7XG4gICAgICAgICAgICBtYXRjaGluZ0Nvbm5lY3Rpb24ucGF0aCA9XG4gICAgICAgICAgICAgIGNhbGN1bGF0ZUZsb3dDb25uZWN0aW9uUGF0aChtYXRjaGluZ0Nvbm5lY3Rpb24pO1xuXG4gICAgICAgICAgICB2ZXJ0aWNhbENvbm5lY3Rpb25PZmZzZXQgKz0gY29ubmVjdGlvbkhlaWdodChjb25uZWN0aW9uKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvL0RhdGEgTGFiZWxzXG4gICAgICAgIGNvbnN0IGJhck5hbWUgPSBjb25maWcuZmxvd0NvbmZpZy5zdWJCdWNrZXRzQ29uZmlnLmZpbmQoXG4gICAgICAgICAgc2JjID0+IHNiYy5idWNrZXRJZCA9PT0gYmFyLmlkLFxuICAgICAgICApPy5idWNrZXROYW1lO1xuICAgICAgICBpZiAoYmFyTmFtZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgZGF0YUxhYmVscy5wdXNoKHtcbiAgICAgICAgICAgIGVsZW1lbnRUeXBlOiAnZGF0YUxhYmVsJyxcbiAgICAgICAgICAgIGRhdGFMYWJlbFR5cGU6ICdmbG93JyxcbiAgICAgICAgICAgIGxhYmVsOiBgJHtiYXJOYW1lfSAoJHtwZXJjZW50UGlwZXMucGlwZS50cmFuc2Zvcm0oXG4gICAgICAgICAgICAgIGJhci5jb3VudCAvIGRhdGEueFtpXS50b3RhbENvdW50LFxuICAgICAgICAgICAgKX0pYCxcbiAgICAgICAgICAgIHhQb3M6IHgsXG4gICAgICAgICAgICB5UG9zOlxuICAgICAgICAgICAgICBkYXJrZW5lZFkgLVxuICAgICAgICAgICAgICAoY2hhcnRTaXppbmdWYWx1ZXMuZGF0YUxhYmVsVGV4dFNpemUgK1xuICAgICAgICAgICAgICAgIGNoYXJ0U2l6aW5nVmFsdWVzLmRhdGFMYWJlbFBhZGRpbmcpIC9cbiAgICAgICAgICAgICAgICAyLFxuICAgICAgICAgICAgYW5jaG9yOiAnc3RhcnQnLFxuICAgICAgICAgICAgYm9sZDogdHJ1ZSxcbiAgICAgICAgICAgIGJ1Y2tldEluZGV4OiBpLFxuICAgICAgICAgICAgYmFySWQ6IGJhci5pZCxcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBiYXJTdWJ0aXRsZSA9IGNvbmZpZy5mbG93Q29uZmlnLnN1YnRpdGxlRm9ybWF0U3RyaW5nLnJlcGxhY2UoXG4gICAgICAgICAgJ3t2YWx1ZX0nLFxuICAgICAgICAgIHZhbHVlUGlwZXMucGlwZS50cmFuc2Zvcm0oYmFyLmNvdW50KSxcbiAgICAgICAgKTtcbiAgICAgICAgZGF0YUxhYmVscy5wdXNoKHtcbiAgICAgICAgICBlbGVtZW50VHlwZTogJ2RhdGFMYWJlbCcsXG4gICAgICAgICAgZGF0YUxhYmVsVHlwZTogJ2Zsb3cnLFxuICAgICAgICAgIGxhYmVsOiBiYXJTdWJ0aXRsZSxcbiAgICAgICAgICB4UG9zOiB4LFxuICAgICAgICAgIHlQb3M6IGRhcmtlbmVkWSAtIGNoYXJ0U2l6aW5nVmFsdWVzLmRhdGFMYWJlbFBhZGRpbmcgLyA0LFxuICAgICAgICAgIGFuY2hvcjogJ3N0YXJ0JyxcbiAgICAgICAgICBidWNrZXRJbmRleDogaSxcbiAgICAgICAgICBiYXJJZDogYmFyLmlkLFxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICAgIGJhcnMucHVzaChidWNrZXRCYXJzKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBob3Zlcihwb3M6IHtcbiAgICAgIHJlY3Q6IERPTVJlY3Q7XG4gICAgICB4OiBudW1iZXI7XG4gICAgICB5OiBudW1iZXI7XG4gICAgICBjb250YWluZXJTY3JvbGxYOiBudW1iZXI7XG4gICAgICBjb250YWluZXJTY3JvbGxZOiBudW1iZXI7XG4gICAgfSk6IEhvdmVyUmV0dXJuIHtcbiAgICAgIGNvbnN0IHJlYWxQb3NYID0gcG9zLnggKyBwb3MuY29udGFpbmVyU2Nyb2xsWDtcbiAgICAgIGNvbnN0IHJlYWxQb3NZID0gcG9zLnkgKyBwb3MuY29udGFpbmVyU2Nyb2xsWTtcbiAgICAgIGlmIChcbiAgICAgICAgY2hhcnRTaXppbmdWYWx1ZXMgPT09IG51bGwgfHxcbiAgICAgICAgZ2V0SWZIb3Zlck91dE9mQm91bmRzKFxuICAgICAgICAgIHBvcy54LFxuICAgICAgICAgIHBvcy55LFxuICAgICAgICAgIHJlYWxQb3NYLFxuICAgICAgICAgIHJlYWxQb3NZLFxuICAgICAgICAgIGNoYXJ0U2l6aW5nVmFsdWVzLFxuICAgICAgICAgIGRpbWVuc2lvbnMsXG4gICAgICAgIClcbiAgICAgICkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cblxuICAgICAgY29uc3QgYnVja2V0SW5kZXhJbmZvID0gZ2V0Rmxvd0J1Y2tldEluZGV4Rm9ySG92ZXIoXG4gICAgICAgIGNoYXJ0U2l6aW5nVmFsdWVzLFxuICAgICAgICByZWFsUG9zWCxcbiAgICAgICk7XG4gICAgICBpZiAoYnVja2V0SW5kZXhJbmZvID09PSBudWxsIHx8IGJ1Y2tldEluZGV4SW5mby5pbmRleCA+PSBiYXJzLmxlbmd0aCkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cbiAgICAgIGlmIChidWNrZXRJbmRleEluZm8uYXJlYSA9PT0gJ2JhcicpIHtcbiAgICAgICAgZm9yIChjb25zdCBiYXIgb2YgYmFyc1tidWNrZXRJbmRleEluZm8uaW5kZXhdKSB7XG4gICAgICAgICAgaWYgKHJlYWxQb3NZIDwgYmFyLnkpIHtcbiAgICAgICAgICAgIC8vQmFyIHRpdGxlXG4gICAgICAgICAgICBjb25zdCBsb2NhbEFuY2hvclggPSBiYXIueCAtIHBvcy5jb250YWluZXJTY3JvbGxYO1xuICAgICAgICAgICAgY29uc3Qgd2lkdGggPSBiYXIud2lkdGg7XG4gICAgICAgICAgICBjb25zdCBoZWlnaHQgPVxuICAgICAgICAgICAgICBjaGFydFNpemluZ1ZhbHVlcy5kYXRhTGFiZWxQYWRkaW5nIC8gMiArXG4gICAgICAgICAgICAgIGNoYXJ0U2l6aW5nVmFsdWVzLmRhdGFMYWJlbFRleHRTaXplO1xuICAgICAgICAgICAgY29uc3QgbG9jYWxBbmNob3JZID0gYmFyLnkgLSAocG9zLmNvbnRhaW5lclNjcm9sbFkgKyBoZWlnaHQpO1xuICAgICAgICAgICAgY29uc3QgeyBhbmNob3JYLCBhbmNob3JZLCBhbmNob3JXaWR0aCwgYW5jaG9ySGVpZ2h0IH0gPVxuICAgICAgICAgICAgICBjaGVja0FuY2hvcnNBZ2FpbnN0Qm91bmQoXG4gICAgICAgICAgICAgICAgbG9jYWxBbmNob3JYLFxuICAgICAgICAgICAgICAgIGxvY2FsQW5jaG9yWSxcbiAgICAgICAgICAgICAgICBkaW1lbnNpb25zLFxuICAgICAgICAgICAgICAgIHdpZHRoLFxuICAgICAgICAgICAgICAgIGhlaWdodCxcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGNvbnN0IGFuY2hvciA9IG5ldyBET01SZWN0KFxuICAgICAgICAgICAgICBhbmNob3JYICsgcG9zLnJlY3QueCxcbiAgICAgICAgICAgICAgYW5jaG9yWSArIHBvcy5yZWN0LnksXG4gICAgICAgICAgICAgIGFuY2hvcldpZHRoLFxuICAgICAgICAgICAgICBhbmNob3JIZWlnaHQsXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgaG92ZXJUeXBlOiAnZmxvdycsXG4gICAgICAgICAgICAgIGhvdmVyVGFyZ2V0OiAnYmFyVGl0bGUnLFxuICAgICAgICAgICAgICBiYXJJZDogYmFyLmlkID8/ICcnLFxuICAgICAgICAgICAgICBidWNrZXRJbmRleDogYnVja2V0SW5kZXhJbmZvLmluZGV4LFxuICAgICAgICAgICAgICB0b29sdGlwOiB7XG4gICAgICAgICAgICAgICAgYW5jaG9yLFxuICAgICAgICAgICAgICAgIHN1YnRpdGxlOiBjb25maWcuZmxvd0NvbmZpZy5zdWJ0aXRsZUZvcm1hdFN0cmluZy5yZXBsYWNlKFxuICAgICAgICAgICAgICAgICAgJ3t2YWx1ZX0nLFxuICAgICAgICAgICAgICAgICAgdmFsdWVQaXBlcy5waXBlLnRyYW5zZm9ybShiYXIudG90YWxDb3VudCksXG4gICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgfSBlbHNlIGlmIChcbiAgICAgICAgICAgIC8vIFRoZSBpbnZpc2libGUgaGlnaGxpZ2h0IGJhciBzcGFucyBib3RoIHBvcnRpb25zLCBzbyBza2lwIGl0IHRvXG4gICAgICAgICAgICAvLyBhdm9pZCBtaXNyZXBvcnRpbmcgYSBwb3J0aW9uIGJvdW5kYXJ5IGFzIHRoZSBlbmRpbmcgcG9ydGlvblxuICAgICAgICAgICAgIWJhci5ub25EaXNwbGF5ICYmXG4gICAgICAgICAgICByZWFsUG9zWSA+PSBiYXIueSAmJlxuICAgICAgICAgICAgcmVhbFBvc1kgPCBiYXIueSArIGJhci5oZWlnaHRcbiAgICAgICAgICApIHtcbiAgICAgICAgICAgIC8vQmFyXG4gICAgICAgICAgICBjb25zdCBsb2NhbEFuY2hvclggPSBiYXIueCAtIHBvcy5jb250YWluZXJTY3JvbGxYO1xuICAgICAgICAgICAgY29uc3Qgd2lkdGggPSBiYXIud2lkdGg7XG4gICAgICAgICAgICBjb25zdCBsb2NhbEFuY2hvclkgPSBiYXIueSAtIHBvcy5jb250YWluZXJTY3JvbGxZO1xuICAgICAgICAgICAgY29uc3QgaGVpZ2h0ID0gYmFyLmhlaWdodDtcbiAgICAgICAgICAgIGNvbnN0IHsgYW5jaG9yWCwgYW5jaG9yWSwgYW5jaG9yV2lkdGgsIGFuY2hvckhlaWdodCB9ID1cbiAgICAgICAgICAgICAgY2hlY2tBbmNob3JzQWdhaW5zdEJvdW5kKFxuICAgICAgICAgICAgICAgIGxvY2FsQW5jaG9yWCxcbiAgICAgICAgICAgICAgICBsb2NhbEFuY2hvclksXG4gICAgICAgICAgICAgICAgZGltZW5zaW9ucyxcbiAgICAgICAgICAgICAgICB3aWR0aCxcbiAgICAgICAgICAgICAgICBoZWlnaHQsXG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICBjb25zdCBhbmNob3IgPSBuZXcgRE9NUmVjdChcbiAgICAgICAgICAgICAgYW5jaG9yWCArIHBvcy5yZWN0LngsXG4gICAgICAgICAgICAgIGFuY2hvclkgKyBwb3MucmVjdC55LFxuICAgICAgICAgICAgICBhbmNob3JXaWR0aCxcbiAgICAgICAgICAgICAgYW5jaG9ySGVpZ2h0LFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgIGhvdmVyVHlwZTogJ2Zsb3cnLFxuICAgICAgICAgICAgICBob3ZlclRhcmdldDogJ2JhcicsXG4gICAgICAgICAgICAgIGJhcklkOiBiYXIuaWQgPz8gJycsXG4gICAgICAgICAgICAgIGJ1Y2tldEluZGV4OiBidWNrZXRJbmRleEluZm8uaW5kZXgsXG4gICAgICAgICAgICAgIGZvckRhcmtlbjogYmFyLmRhcmtlbiA9PT0gdHJ1ZSxcbiAgICAgICAgICAgICAgdG9vbHRpcDoge1xuICAgICAgICAgICAgICAgIGFuY2hvcixcbiAgICAgICAgICAgICAgICBzdWJ0aXRsZTogY29uZmlnLmZsb3dDb25maWcuc3VidGl0bGVGb3JtYXRTdHJpbmcucmVwbGFjZShcbiAgICAgICAgICAgICAgICAgICd7dmFsdWV9JyxcbiAgICAgICAgICAgICAgICAgIHZhbHVlUGlwZXMucGlwZS50cmFuc2Zvcm0oYmFyLmNvdW50KSxcbiAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGZvciAoY29uc3QgY29ubmVjdGlvbiBvZiBmbG93Q29ubmVjdGlvbnMuZmlsdGVyKFxuICAgICAgICAgIGZsb3dDb24gPT4gZmxvd0Nvbi5zdGVwID09PSBidWNrZXRJbmRleEluZm8uaW5kZXgsXG4gICAgICAgICkpIHtcbiAgICAgICAgICBpZiAoY2hlY2tJZlBvaW50V2l0aGluQ29ubmVjdGlvbihjb25uZWN0aW9uLCByZWFsUG9zWCwgcmVhbFBvc1kpKSB7XG4gICAgICAgICAgICBjb25zdCBsb2NhbEFuY2hvclggPSBjb25uZWN0aW9uLnRvcExpbmUueDEgLSBwb3MuY29udGFpbmVyU2Nyb2xsWDtcbiAgICAgICAgICAgIGNvbnN0IHdpZHRoID0gY29ubmVjdGlvbi50b3BMaW5lLngyIC0gY29ubmVjdGlvbi50b3BMaW5lLngxO1xuICAgICAgICAgICAgY29uc3QgY3VydmVUb3AgPSBiZXppZXJZQXRYKFxuICAgICAgICAgICAgICAoY29ubmVjdGlvbi50b3BMaW5lLngxICsgY29ubmVjdGlvbi50b3BMaW5lLngyKSAvIDIsXG4gICAgICAgICAgICAgIGNvbm5lY3Rpb24udG9wTGluZSxcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBjb25zdCBjdXJ2ZUJvdHRvbSA9IGJlemllcllBdFgoXG4gICAgICAgICAgICAgIChjb25uZWN0aW9uLnRvcExpbmUueDEgKyBjb25uZWN0aW9uLnRvcExpbmUueDIpIC8gMixcbiAgICAgICAgICAgICAgY29ubmVjdGlvbi5ib3R0b21MaW5lLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGNvbnN0IGxvY2FsQW5jaG9yWSA9IGN1cnZlVG9wIC0gcG9zLmNvbnRhaW5lclNjcm9sbFk7XG4gICAgICAgICAgICBjb25zdCBoZWlnaHQgPSBjdXJ2ZUJvdHRvbSAtIGN1cnZlVG9wO1xuICAgICAgICAgICAgY29uc3QgeyBhbmNob3JYLCBhbmNob3JZLCBhbmNob3JXaWR0aCwgYW5jaG9ySGVpZ2h0IH0gPVxuICAgICAgICAgICAgICBjaGVja0FuY2hvcnNBZ2FpbnN0Qm91bmQoXG4gICAgICAgICAgICAgICAgbG9jYWxBbmNob3JYLFxuICAgICAgICAgICAgICAgIGxvY2FsQW5jaG9yWSxcbiAgICAgICAgICAgICAgICBkaW1lbnNpb25zLFxuICAgICAgICAgICAgICAgIHdpZHRoLFxuICAgICAgICAgICAgICAgIGhlaWdodCxcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGNvbnN0IGFuY2hvciA9IG5ldyBET01SZWN0KFxuICAgICAgICAgICAgICBhbmNob3JYICsgcG9zLnJlY3QueCxcbiAgICAgICAgICAgICAgYW5jaG9yWSArIHBvcy5yZWN0LnksXG4gICAgICAgICAgICAgIGFuY2hvcldpZHRoLFxuICAgICAgICAgICAgICBhbmNob3JIZWlnaHQsXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgaG92ZXJUeXBlOiAnZmxvdycsXG4gICAgICAgICAgICAgIGhvdmVyVGFyZ2V0OiAnY29ubmVjdGlvbicsXG4gICAgICAgICAgICAgIHN0YXJ0SWQ6IGNvbm5lY3Rpb24uc3RhcnQsXG4gICAgICAgICAgICAgIGVuZElkOiBjb25uZWN0aW9uLmVuZCxcbiAgICAgICAgICAgICAgc3RhcnRCdWNrZXRJbmRleDogY29ubmVjdGlvbi5zdGVwLFxuICAgICAgICAgICAgICB0b29sdGlwOiB7XG4gICAgICAgICAgICAgICAgYW5jaG9yLFxuICAgICAgICAgICAgICAgIHN1YnRpdGxlOiBjb25maWcuZmxvd0NvbmZpZy5zdWJ0aXRsZUZvcm1hdFN0cmluZy5yZXBsYWNlKFxuICAgICAgICAgICAgICAgICAgJ3t2YWx1ZX0nLFxuICAgICAgICAgICAgICAgICAgdmFsdWVQaXBlcy5waXBlLnRyYW5zZm9ybShjb25uZWN0aW9uLmNvdW50KSxcbiAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIGNoYXJ0V2lkdGg6IGNoYXJ0U2l6aW5nVmFsdWVzLnRvdGFsV2lkdGgsXG4gICAgICBjaGFydEhlaWdodDogY2hhcnRTaXppbmdWYWx1ZXMudG90YWxIZWlnaHQsXG4gICAgICBjaGFydFNpemluZ1ZhbHVlcyxcbiAgICAgIHhUaWNrczogW10sXG4gICAgICB5VGlja3M6IFtdLFxuICAgICAgY29sb3JzOiBbXSxcbiAgICAgIGJhcnMsXG4gICAgICBsaW5lczogW10sXG4gICAgICBjaXJjbGVzOiBbXSxcbiAgICAgIGFyZWFzOiBbXSxcbiAgICAgIGhvdmVyLFxuICAgICAgYXJjczogW10sXG4gICAgICBob3Jpem9udGFsQmFyczogW10sXG4gICAgICBkYXRhTGFiZWxzLFxuICAgICAgd2F0ZXJmYWxsTGluZXM6IFtdLFxuICAgICAgZ3JhZGllbnRzOiBbXSxcbiAgICAgIGZsb3dDb25uZWN0aW9ucyxcbiAgICAgIGhvcml6b250YWxDb250YWluZXJTY2FsZTogY2hhcnRTaXppbmdWYWx1ZXMuaG9yaXpvbnRhbENvbnRhaW5lclNjYWxlLFxuICAgICAgdmVydGljYWxDb250YWluZXJTY2FsZTogY2hhcnRTaXppbmdWYWx1ZXMudmVydGljYWxDb250YWluZXJTY2FsZSxcbiAgICAgIGNoYXJ0RXJyb3I6IG51bGwsXG4gICAgfTtcbiAgfVxuXG4gIC8qXG4gICAgTWlycm9ycyB0aGUgYnVja2V0aW5nIGluIGZsb3dzVHJhbnNmb3JtOiBhIHBhdGggY29udHJpYnV0ZXMgdmFsdWVzW2ldIHRvXG4gICAgdGhlIGJhciBhdCBzdGVwIGksIGFuZCB2YWx1ZXNbaSArIDFdIHRvIGl0cyBmb3J3YXJkIGNvbm5lY3Rpb24gKHdoaWNoIGlzXG4gICAgYWxzbyB0aGUgYmFyJ3MgY29udGludWluZyBwb3J0aW9uKS5cbiAgKi9cbiAgZnVuY3Rpb24gZmxvd1ZhbHVlQXRTdGVwKHk6IEZsb3dZLCBzdGVwOiBudW1iZXIpOiBudW1iZXIgfCBudWxsIHtcbiAgICByZXR1cm4geS5zdGVwcy5sZW5ndGggPiBzdGVwICYmIHkudmFsdWVzLmxlbmd0aCA+IHN0ZXBcbiAgICAgID8geS52YWx1ZXNbc3RlcF1cbiAgICAgIDogbnVsbDtcbiAgfVxuXG4gIGZ1bmN0aW9uIHN1bUZsb3dWYWx1ZXMoXG4gICAgZGF0YTogRmxvd0RhdGEsXG4gICAgeUluZGljZXM6IG51bWJlcltdLFxuICAgIHN0ZXA6IG51bWJlcixcbiAgKTogbnVtYmVyIHtcbiAgICByZXR1cm4geUluZGljZXNcbiAgICAgIC5tYXAoaW5kZXggPT4gZmxvd1ZhbHVlQXRTdGVwKGRhdGEueXNbaW5kZXhdLCBzdGVwKSA/PyAwKVxuICAgICAgLnJlZHVjZSgoYSwgYikgPT4gYSArIGIsIDApO1xuICB9XG5cbiAgZXhwb3J0IGZ1bmN0aW9uIHRvRmxvd0NsaWNrRXZlbnQoXG4gICAgaG92ZXI6IEZsb3dIb3ZlclRhcmdldCxcbiAgICBkYXRhOiBGbG93RGF0YSxcbiAgKTogRmxvd0NsaWNrRXZlbnQge1xuICAgIGNvbnN0IGFsbFlJbmRpY2VzID0gZGF0YS55cy5tYXAoKF8sIGluZGV4KSA9PiBpbmRleCk7XG4gICAgaWYgKGhvdmVyLmhvdmVyVGFyZ2V0ID09PSAnY29ubmVjdGlvbicpIHtcbiAgICAgIGNvbnN0IHN0ZXAgPSBob3Zlci5zdGFydEJ1Y2tldEluZGV4O1xuICAgICAgY29uc3QgeUluZGljZXMgPSBhbGxZSW5kaWNlcy5maWx0ZXIoXG4gICAgICAgIGluZGV4ID0+XG4gICAgICAgICAgZGF0YS55c1tpbmRleF0uc3RlcHNbc3RlcF0gPT09IGhvdmVyLnN0YXJ0SWQgJiZcbiAgICAgICAgICBmbG93VmFsdWVBdFN0ZXAoZGF0YS55c1tpbmRleF0sIHN0ZXApICE9PSBudWxsICYmXG4gICAgICAgICAgZGF0YS55c1tpbmRleF0uc3RlcHNbc3RlcCArIDFdID09PSBob3Zlci5lbmRJZCAmJlxuICAgICAgICAgIGZsb3dWYWx1ZUF0U3RlcChkYXRhLnlzW2luZGV4XSwgc3RlcCArIDEpICE9PSBudWxsLFxuICAgICAgKTtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHRhcmdldDogJ2Nvbm5lY3Rpb24nLFxuICAgICAgICBzdGFydEJ1Y2tldEluZGV4OiBzdGVwLFxuICAgICAgICBzdGFydElkOiBob3Zlci5zdGFydElkLFxuICAgICAgICBlbmRJZDogaG92ZXIuZW5kSWQsXG4gICAgICAgIGNvdW50OiBzdW1GbG93VmFsdWVzKGRhdGEsIHlJbmRpY2VzLCBzdGVwICsgMSksXG4gICAgICAgIHlJbmRpY2VzLFxuICAgICAgfTtcbiAgICB9XG5cbiAgICBjb25zdCBzdGVwID0gaG92ZXIuYnVja2V0SW5kZXg7XG4gICAgY29uc3QgYmFyWUluZGljZXMgPSBhbGxZSW5kaWNlcy5maWx0ZXIoXG4gICAgICBpbmRleCA9PlxuICAgICAgICBkYXRhLnlzW2luZGV4XS5zdGVwc1tzdGVwXSA9PT0gaG92ZXIuYmFySWQgJiZcbiAgICAgICAgZmxvd1ZhbHVlQXRTdGVwKGRhdGEueXNbaW5kZXhdLCBzdGVwKSAhPT0gbnVsbCxcbiAgICApO1xuICAgIGNvbnN0IHRvdGFsQ291bnQgPSBzdW1GbG93VmFsdWVzKGRhdGEsIGJhcllJbmRpY2VzLCBzdGVwKTtcbiAgICBjb25zdCBiYXNlID0geyBidWNrZXRJbmRleDogc3RlcCwgYmFySWQ6IGhvdmVyLmJhcklkIH07XG4gICAgaWYgKGhvdmVyLmhvdmVyVGFyZ2V0ID09PSAnYmFyVGl0bGUnKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICAuLi5iYXNlLFxuICAgICAgICB0YXJnZXQ6ICd0aXRsZScsXG4gICAgICAgIGNvdW50OiB0b3RhbENvdW50LFxuICAgICAgICB5SW5kaWNlczogYmFyWUluZGljZXMsXG4gICAgICB9O1xuICAgIH1cblxuICAgIGNvbnN0IGNvbnRpbnVpbmdDb3VudCA9IHN1bUZsb3dWYWx1ZXMoZGF0YSwgYmFyWUluZGljZXMsIHN0ZXAgKyAxKTtcbiAgICBpZiAoaG92ZXIuZm9yRGFya2VuKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICAuLi5iYXNlLFxuICAgICAgICB0YXJnZXQ6ICdjb250aW51aW5nJyxcbiAgICAgICAgY291bnQ6IGNvbnRpbnVpbmdDb3VudCxcbiAgICAgICAgdG90YWxDb3VudCxcbiAgICAgICAgeUluZGljZXM6IGJhcllJbmRpY2VzLmZpbHRlcihcbiAgICAgICAgICBpbmRleCA9PiAoZmxvd1ZhbHVlQXRTdGVwKGRhdGEueXNbaW5kZXhdLCBzdGVwICsgMSkgPz8gMCkgPiAwLFxuICAgICAgICApLFxuICAgICAgfTtcbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgIC4uLmJhc2UsXG4gICAgICB0YXJnZXQ6ICdlbmRpbmcnLFxuICAgICAgY291bnQ6IHRvdGFsQ291bnQgLSBjb250aW51aW5nQ291bnQsXG4gICAgICB0b3RhbENvdW50LFxuICAgICAgeUluZGljZXM6IGJhcllJbmRpY2VzLmZpbHRlcihcbiAgICAgICAgaW5kZXggPT5cbiAgICAgICAgICAoZmxvd1ZhbHVlQXRTdGVwKGRhdGEueXNbaW5kZXhdLCBzdGVwKSA/PyAwKSA+XG4gICAgICAgICAgKGZsb3dWYWx1ZUF0U3RlcChkYXRhLnlzW2luZGV4XSwgc3RlcCArIDEpID8/IDApLFxuICAgICAgKSxcbiAgICB9O1xuICB9XG5cbiAgY29uc3QgU01BTExfUEFERElORyA9IDg7XG4gIGV4cG9ydCBjb25zdCBERUZBVUxUX0ZPTlRfU0laRSA9IDEyOyAvL3RoZSB3aWR0aCBjb25zdGFudHMgYXJlIGJhc2VkIG9uIGZvbnQgc2l6ZSAxMiwgc28gdGhpcyB2YXJpYWJsZSBjYW4gaGVscCB3LyBzY2FsaW5nXG4gIGV4cG9ydCBjb25zdCBXSURUSF9QRVJfTEVUVEVSID0gNi41O1xuICBjb25zdCBXSURUSF9QRVJfTlVNQkVSID0gNztcbiAgY29uc3QgV0lEVEhfUEVSX1BFUklPRCA9IDI7XG4gIGNvbnN0IFdJRFRIX1BFUl9TTEFTSCA9IDQ7XG4gIC8vV2hlbiB0aGUgZGF0YSBheGlzIGdyb3dzLCB0aGUgZGF0YSBpcyBhbHdheXMgZ2l2ZW4gYXQgbGVhc3QgdGhpcyBwb3J0aW9uIG9mIHRoZSBwcm92aWRlZCBzaXplXG4gIGNvbnN0IEdST1dOX0RBVEFfTUlOSU1VTV9SQVRJTyA9IDAuNTtcbiAgY29uc3QgREVGQVVMVF9IT1JJWk9OVEFMX0JBUl9DT1JORVJfUkFESVVTID0gNDtcbiAgY29uc3QgRkxPV19DT05ORUNUSU9OX0NVUlZFX0NPTlNUQU5UID0gMC41O1xuXG4gIGZ1bmN0aW9uIGdldEZvcm1hdHRpbmdBbmRDb2xvcnMoXG4gICAgb3JpZ2luYWxEYXRhOiBOb25GbG93RGF0YSxcbiAgICBkYXRhOiBOb25GbG93RGF0YSxcbiAgICBjb25maWc6IENvbmZpZyxcbiAgKSB7XG4gICAgY29uc3QgZGF0ZUZvcm1hdCA9IChkYXRlOiBEYXRlKSA9PlxuICAgICAgZm9ybWF0ZWREYXRlKGNvbmZpZy5kYXRlRm9ybWF0IHx8ICdkYXknLCBkYXRlKTtcbiAgICBjb25zdCB7IHBpcGUsIGZ1bGxQaXBlIH0gPSBnZXRQaXBlcyhjb25maWcudmFsdWVUeXBlKTtcbiAgICBjb25zdCB7IHBpcGU6IHNlY29uZGFyeVBpcGUsIGZ1bGxQaXBlOiBzZWNvbmRhcnlGdWxsUGlwZSB9ID1cbiAgICAgIGNvbmZpZy5zZWNvbmRhcnlWYWx1ZVR5cGVcbiAgICAgICAgPyBnZXRQaXBlcyhjb25maWcuc2Vjb25kYXJ5VmFsdWVUeXBlKVxuICAgICAgICA6IHtcbiAgICAgICAgICAgIHBpcGUsXG4gICAgICAgICAgICBmdWxsUGlwZSxcbiAgICAgICAgICB9O1xuICAgIGNvbnN0IHBpcGVUcmFuc2Zvcm0gPSAoXG4gICAgICB2YWx1ZTogbnVtYmVyLFxuICAgICAgaXNTZWNvbmRhcnk6IGJvb2xlYW4gfCB1bmRlZmluZWQsXG4gICAgICBpc0Z1bGw/OiBib29sZWFuLFxuICAgICk6IHN0cmluZyA9PiB7XG4gICAgICBpZiAoaXNGdWxsICE9PSB0cnVlKSB7XG4gICAgICAgIGlmIChpc1NlY29uZGFyeSA9PT0gdHJ1ZSkge1xuICAgICAgICAgIHJldHVybiBzZWNvbmRhcnlQaXBlLnRyYW5zZm9ybSh2YWx1ZSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHBpcGUudHJhbnNmb3JtKHZhbHVlKTtcbiAgICAgIH1cbiAgICAgIGxldCByZXRWYWw6IHN0cmluZyB8IG51bGwgPSBudWxsO1xuICAgICAgaWYgKGlzU2Vjb25kYXJ5KSB7XG4gICAgICAgIHJldFZhbCA9IHNlY29uZGFyeUZ1bGxQaXBlLnRyYW5zZm9ybSh2YWx1ZSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXRWYWwgPSBmdWxsUGlwZS50cmFuc2Zvcm0odmFsdWUpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJldFZhbCAhPT0gbnVsbCA/IHJldFZhbCA6ICctJztcbiAgICB9O1xuXG4gICAgLy8gUHJlLWNhbGN1bGF0ZSBjb2xvciBpbmRpY2VzIGZvciBhbGwgaXRlbXMgKHVzZSBvcmlnaW5hbCBkYXRhIGZvciBzdGFibGUgY29sb3JzKVxuICAgIGNvbnN0IGNvbG9ySW5kaWNlcyA9IGNhbGN1bGF0ZUNvbG9ySW5kaWNlcyhvcmlnaW5hbERhdGEpO1xuICAgIGNvbnN0IGNvbG9ycyA9IGRhdGEueXMubWFwKHkgPT4gZ2V0Q29sb3IoeSwgY29sb3JJbmRpY2VzLCBjb25maWcuY29sb3JzKSk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgZGF0ZUZvcm1hdCxcbiAgICAgIHBpcGVUcmFuc2Zvcm0sXG4gICAgICBjb2xvckluZGljZXMsXG4gICAgICBjb2xvcnMsXG4gICAgfTtcbiAgfVxuXG4gIGV4cG9ydCBmdW5jdGlvbiBjYWxjdWxhdGVDb2xvckluZGljZXMoXG4gICAgZGF0YTogTm9uRmxvd0RhdGEsXG4gICk6IE1hcDxEYXRhWSB8IFN1cHBsZW1lbnRhcnlEYXRhWSwgbnVtYmVyPiB7XG4gICAgY29uc3QgY29sb3JNYXAgPSBuZXcgTWFwPERhdGFZIHwgU3VwcGxlbWVudGFyeURhdGFZLCBudW1iZXI+KCk7XG5cbiAgICAvLyBPcmlnaW5hbCBZczogdXNlIHRoZWlyIGFycmF5IGluZGV4IGRpcmVjdGx5XG4gICAgZGF0YS55cy5mb3JFYWNoKCh5LCBpbmRleCkgPT4ge1xuICAgICAgY29sb3JNYXAuc2V0KHksIGluZGV4KTtcbiAgICB9KTtcblxuICAgIC8vIFN1cHBsZW1lbnRhcnkgWXM6IGdyb3VwIGJ5IHN1cHBsZW1lbnRhbEluZGV4LCB1c2UgcG9zaXRpb24gd2l0aGluIHRoYXQgZ3JvdXBcbiAgICBpZiAoaGFzU3VwcGxlbWVudGFyeURhdGEoZGF0YSkpIHtcbiAgICAgIGNvbnN0IHN1cHBHcm91cHMgPSBuZXcgTWFwPG51bWJlciwgU3VwcGxlbWVudGFyeURhdGFZW10+KCk7XG5cbiAgICAgIGRhdGEuc3VwcGxlbWVudGFyeVlzLmZvckVhY2goc3VwcFkgPT4ge1xuICAgICAgICBpZiAoIXN1cHBHcm91cHMuaGFzKHN1cHBZLnN1cHBsZW1lbnRhbEluZGV4KSkge1xuICAgICAgICAgIHN1cHBHcm91cHMuc2V0KHN1cHBZLnN1cHBsZW1lbnRhbEluZGV4LCBbXSk7XG4gICAgICAgIH1cbiAgICAgICAgc3VwcEdyb3Vwcy5nZXQoc3VwcFkuc3VwcGxlbWVudGFsSW5kZXgpIS5wdXNoKHN1cHBZKTtcbiAgICAgIH0pO1xuXG4gICAgICBzdXBwR3JvdXBzLmZvckVhY2goaXRlbXMgPT4ge1xuICAgICAgICBpdGVtcy5mb3JFYWNoKChpdGVtLCBwb3NpdGlvbkluR3JvdXApID0+IHtcbiAgICAgICAgICBjb2xvck1hcC5zZXQoaXRlbSwgcG9zaXRpb25Jbkdyb3VwKTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICByZXR1cm4gY29sb3JNYXA7XG4gIH1cblxuICBleHBvcnQgZnVuY3Rpb24gZ2V0Q29sb3IoXG4gICAgaXRlbTogRGF0YVkgfCBTdXBwbGVtZW50YXJ5RGF0YVkgfCB1bmRlZmluZWQsXG4gICAgY29sb3JJbmRpY2VzOiBNYXA8RGF0YVkgfCBTdXBwbGVtZW50YXJ5RGF0YVksIG51bWJlcj4sXG4gICAgY29sb3JzOiByZWFkb25seSBzdHJpbmdbXSxcbiAgKTogc3RyaW5nIHtcbiAgICBpZiAoaXRlbSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICByZXR1cm4gY29sb3JzWzBdO1xuICAgIH1cbiAgICBpZiAoaXRlbS5jb2xvclRva2VuKSByZXR1cm4gaXRlbS5jb2xvclRva2VuO1xuICAgIGNvbnN0IGNvbG9ySW5kZXggPSBjb2xvckluZGljZXMuZ2V0KGl0ZW0pID8/IDA7XG4gICAgcmV0dXJuIGNvbG9yc1tjb2xvckluZGV4ICUgY29sb3JzLmxlbmd0aF07XG4gIH1cblxuICBmdW5jdGlvbiBnZXRCdWNrZXRUaWNrQ291bnQoY2hhcnRTaXppbmdWYWx1ZXM6IEZ1bGxDaGFydFNjYWxlVmFsdWVzKTogbnVtYmVyIHtcbiAgICBsZXQgYXZhaWxhYmxlU2l6ZSA9IDA7XG4gICAgbGV0IG1pblNwYWNpbmcgPSAxO1xuICAgIGlmIChjaGFydFNpemluZ1ZhbHVlcy5jaGFydERhdGFEaXJlY3Rpb24gPT09ICd2ZXJ0aWNhbCcpIHtcbiAgICAgIGF2YWlsYWJsZVNpemUgPVxuICAgICAgICBjaGFydFNpemluZ1ZhbHVlcy50b3RhbFdpZHRoIC1cbiAgICAgICAgY2hhcnRTaXppbmdWYWx1ZXMubGVmdFBhZGRpbmcgLVxuICAgICAgICBjaGFydFNpemluZ1ZhbHVlcy5yaWdodFBhZGRpbmc7XG4gICAgICBtaW5TcGFjaW5nID1cbiAgICAgICAgY2hhcnRTaXppbmdWYWx1ZXMuaG9yaXpvbnRhbEF4aXNMYWJlbFRleHRTaXplICsgU01BTExfUEFERElORztcbiAgICB9XG4gICAgaWYgKGNoYXJ0U2l6aW5nVmFsdWVzLmNoYXJ0RGF0YURpcmVjdGlvbiA9PT0gJ2hvcml6b250YWwnKSB7XG4gICAgICBhdmFpbGFibGVTaXplID1cbiAgICAgICAgY2hhcnRTaXppbmdWYWx1ZXMudG90YWxIZWlnaHQgLVxuICAgICAgICBjaGFydFNpemluZ1ZhbHVlcy50b3BQYWRkaW5nIC1cbiAgICAgICAgY2hhcnRTaXppbmdWYWx1ZXMuYm90dG9tUGFkZGluZztcbiAgICAgIG1pblNwYWNpbmcgPSBjaGFydFNpemluZ1ZhbHVlcy52ZXJ0aWNhbEF4aXNMYWJlbFRleHRTaXplICsgU01BTExfUEFERElORztcbiAgICB9XG4gICAgbWluU3BhY2luZyA9IG1pblNwYWNpbmcgKiAoY2hhcnRTaXppbmdWYWx1ZXMuZm9udFNpemUgLyBERUZBVUxUX0ZPTlRfU0laRSk7XG4gICAgcmV0dXJuIE1hdGgubWF4KDIsIE1hdGguZmxvb3IoYXZhaWxhYmxlU2l6ZSAvIG1pblNwYWNpbmcpKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGdldENsdXN0ZXJJbmZvRm9yQnVja2V0KFxuICAgIGRhdGE6IE5vbkZsb3dEYXRhLFxuICAgIGNvbmZpZzogQ29uZmlnLFxuICApOiB7XG4gICAgbm9ybUNvdW50OiBudW1iZXI7XG4gICAgc3VwcENvdW50OiBudW1iZXI7XG4gICAgdG90YWw6IG51bWJlcjtcbiAgICBub3JtQ2x1c3RlckluZGljZXM6IG51bWJlcltdO1xuICAgIHN1cHBDbHVzdGVySW5kaWNlczogbnVtYmVyW107XG4gIH0ge1xuICAgIC8vIFNsb3QgbGF5b3V0IGlzIHRoZSBzYW1lIGZvciBldmVyeSBidWNrZXQg4oCUIHplcm8gdmFsdWVzIHN0aWxsIG9jY3VweVxuICAgIC8vIHRoZWlyIHNsb3QsIHRoZXkganVzdCByZW5kZXIgd2l0aCBubyBoZWlnaHQvd2lkdGguIFRoaXMga2VlcHMgYnVja2V0XG4gICAgLy8gc2l6ZXMsIGJhciBwb3NpdGlvbnMsIGFuZCBob3ZlciBkZXRlY3Rpb24gY29uc2lzdGVudCBhY3Jvc3MgYnVja2V0c1xuICAgIC8vIHJlZ2FyZGxlc3Mgb2Ygd2hpY2ggc2VyaWVzIGhhcHBlbiB0byBiZSB6ZXJvLlxuICAgIGNvbnN0IG5vcm1DbHVzdGVySW5kaWNlcyA9IGRhdGEueXMubWFwKChfLCB5SW5kZXgpID0+IHlJbmRleCk7XG4gICAgY29uc3Qgbm9ybUNsdXN0ZXJDb3VudCA9IG5vcm1DbHVzdGVySW5kaWNlcy5sZW5ndGg7XG4gICAgY29uc3Qgc3VwcENsdXN0ZXJJbmRpY2VzID0gdW5pcShcbiAgICAgIGhhc1N1cHBsZW1lbnRhcnlEYXRhKGRhdGEpXG4gICAgICAgID8gZGF0YS5zdXBwbGVtZW50YXJ5WXMubWFwKHkgPT4geS5zdXBwbGVtZW50YWxJbmRleClcbiAgICAgICAgOiBbXSxcbiAgICApO1xuICAgIHN1cHBDbHVzdGVySW5kaWNlcy5zb3J0KChhLCBiKSA9PiBhIC0gYik7XG5cbiAgICBjb25zdCBzdXBwQ2x1c3RlckNvdW50ID0gc3VwcENsdXN0ZXJJbmRpY2VzLmxlbmd0aDtcbiAgICBjb25zdCBhY3R1YWxOb3JtQ2x1c3RlckNvdW50ID0gaXNDbHVzdGVyZWREYXRhKGRhdGEsIGNvbmZpZywgZmFsc2UpXG4gICAgICA/IG5vcm1DbHVzdGVyQ291bnRcbiAgICAgIDogTWF0aC5taW4obm9ybUNsdXN0ZXJDb3VudCwgMSk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgbm9ybUNvdW50OiBhY3R1YWxOb3JtQ2x1c3RlckNvdW50LFxuICAgICAgc3VwcENvdW50OiBzdXBwQ2x1c3RlckNvdW50LFxuICAgICAgdG90YWw6IGFjdHVhbE5vcm1DbHVzdGVyQ291bnQgKyBzdXBwQ2x1c3RlckNvdW50LFxuICAgICAgbm9ybUNsdXN0ZXJJbmRpY2VzLFxuICAgICAgc3VwcENsdXN0ZXJJbmRpY2VzLFxuICAgIH07XG4gIH1cblxuICAvL1RoaXMgZnVuY3Rpb24gZ2l2ZXMgdGhlIHRvdGFsIGRpc3RhbmNlIGZyb20gdGhlIHN0YXJ0IG9mIHRoZSBnaXZlbiBidWNrZXQsIHRvIHRoZSBlbmQgb2YgdGhlIGN1cnJlbnQgYnVja2V0XG4gIGZ1bmN0aW9uIGdldEJ1Y2tldFNpemUoXG4gICAgZGF0YTogTm9uRmxvd0RhdGEsXG4gICAgY29uZmlnOiBDb25maWcsXG4gICAgY2hhcnRTaXppbmdWYWx1ZXM6IEZ1bGxDaGFydFNjYWxlVmFsdWVzLFxuICApOiBudW1iZXIge1xuICAgIGNvbnN0IHRvdGFsQmFyTnVtYmVyID0gZ2V0Q2x1c3RlckluZm9Gb3JCdWNrZXQoZGF0YSwgY29uZmlnKTtcbiAgICBjb25zdCBidWNrZXRTaXplID1cbiAgICAgIHRvdGFsQmFyTnVtYmVyLnRvdGFsICogY2hhcnRTaXppbmdWYWx1ZXMuYmFyU2l6ZSArXG4gICAgICAodG90YWxCYXJOdW1iZXIudG90YWwgLSAxKSAqIGNoYXJ0U2l6aW5nVmFsdWVzLmJhckNsdXN0ZXJHYXA7XG5cbiAgICByZXR1cm4gYnVja2V0U2l6ZTtcbiAgfVxuXG4gIC8vVGhpcyBmdW5jdGlvbiBnaXZlcyB0aGUgdG90YWwgZGlzdGFuY2UgZnJvbSB0aGUgc3RhcnQgb2YgdGhlIGdpdmVuIGJ1Y2tldCwgdG8gdGhlIHN0YXJ0IG9mIHRoZSBuZXh0IGJ1Y2tldFxuICBmdW5jdGlvbiBnZXRUb3RhbEJ1Y2tldEdhcChcbiAgICBkYXRhOiBOb25GbG93RGF0YSxcbiAgICBjb25maWc6IENvbmZpZyxcbiAgICBjaGFydFNpemluZ1ZhbHVlczogRnVsbENoYXJ0U2NhbGVWYWx1ZXMsXG4gICk6IG51bWJlciB7XG4gICAgY29uc3QgYnVja2V0U2l6ZSA9IGdldEJ1Y2tldFNpemUoZGF0YSwgY29uZmlnLCBjaGFydFNpemluZ1ZhbHVlcyk7XG4gICAgcmV0dXJuIGJ1Y2tldFNpemUgKyBjaGFydFNpemluZ1ZhbHVlcy5idWNrZXRHYXA7XG4gIH1cblxuICAvL1RoaXMgZnVuY3Rpb24gZ2l2ZXMgdGhlIHRvdGFsIGRpc3RhbmNlIGZyb20gdGhlIHN0YXJ0IG9mIHRoZSBmaXJzdCBidWNrZXQsIHRvIHRoZSBzdGFydCBvZiB0aGUgZ2l2ZW4gYnVja2V0XG4gIGZ1bmN0aW9uIGdldFRvdGFsUHJlQnVja2V0R2FwKFxuICAgIGRhdGE6IE5vbkZsb3dEYXRhLFxuICAgIGNvbmZpZzogQ29uZmlnLFxuICAgIGNoYXJ0U2l6aW5nVmFsdWVzOiBGdWxsQ2hhcnRTY2FsZVZhbHVlcyxcbiAgICBidWNrZXRJbmRleDogbnVtYmVyLFxuICApOiBudW1iZXIge1xuICAgIGxldCBjdW11bGF0aXZlQnVja2V0R2FwID0gMDtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGJ1Y2tldEluZGV4OyBpKyspIHtcbiAgICAgIGN1bXVsYXRpdmVCdWNrZXRHYXAgKz0gZ2V0VG90YWxCdWNrZXRHYXAoZGF0YSwgY29uZmlnLCBjaGFydFNpemluZ1ZhbHVlcyk7XG4gICAgfVxuICAgIHJldHVybiBjdW11bGF0aXZlQnVja2V0R2FwO1xuICB9XG5cbiAgZnVuY3Rpb24gZ2VuZXJhdGVUaW1lc2VyaWVzVGlja3MoXG4gICAgZGF0YTogVGltZXNlcmllc0RhdGEsXG4gICAgY29uZmlnOiBDb25maWcsXG4gICAgdGlja0NvdW50OiBudW1iZXIsXG4gICAgY2hhcnRTaXppbmdWYWx1ZXM6IEZ1bGxDaGFydFNjYWxlVmFsdWVzLFxuICAgIGZvcm1hdDogKGRhdGU6IERhdGUpID0+IHN0cmluZyxcbiAgKTogR2VuZXJpY1RpY2tbXSB7XG4gICAgY29uc3QgZ2V0TGFiZWwgPSAoaW5kZXg6IG51bWJlcikgPT4ge1xuICAgICAgcmV0dXJuIGZvcm1hdChuZXcgRGF0ZShkYXRhLnhbaW5kZXhdKSk7XG4gICAgfTtcbiAgICByZXR1cm4gZ2V0VGlja3MoZGF0YSwgZ2V0TGFiZWwsIGNvbmZpZywgdGlja0NvdW50LCBjaGFydFNpemluZ1ZhbHVlcyk7XG4gIH1cblxuICBmdW5jdGlvbiBnZW5lcmF0ZUxhYmVsbGVkVGlja3MoXG4gICAgZGF0YTogTGFiZWxlZERhdGEsXG4gICAgY29uZmlnOiBDb25maWcsXG4gICAgdGlja0NvdW50OiBudW1iZXIsXG4gICAgY2hhcnRTaXppbmdWYWx1ZXM6IEZ1bGxDaGFydFNjYWxlVmFsdWVzLFxuICApOiBHZW5lcmljVGlja1tdIHtcbiAgICBjb25zdCBnZXRMYWJlbCA9IChpbmRleDogbnVtYmVyKSA9PiB7XG4gICAgICByZXR1cm4gZGF0YS54W2luZGV4XS5sYWJlbDtcbiAgICB9O1xuICAgIHJldHVybiBnZXRUaWNrcyhkYXRhLCBnZXRMYWJlbCwgY29uZmlnLCB0aWNrQ291bnQsIGNoYXJ0U2l6aW5nVmFsdWVzKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGdldFRpY2tzKFxuICAgIGRhdGE6IE5vbkZsb3dEYXRhLFxuICAgIGdldExhYmVsOiAoaW5kZXg6IG51bWJlcikgPT4gc3RyaW5nLFxuICAgIGNvbmZpZzogQ29uZmlnLFxuICAgIHRpY2tDb3VudDogbnVtYmVyLFxuICAgIGNoYXJ0U2l6aW5nVmFsdWVzOiBGdWxsQ2hhcnRTY2FsZVZhbHVlcyxcbiAgKTogR2VuZXJpY1RpY2tbXSB7XG4gICAgaWYgKGRhdGEueC5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVybiBbXTtcbiAgICB9XG4gICAgaWYgKGRhdGEueC5sZW5ndGggPT09IDEpIHtcbiAgICAgIGNvbnN0IGxhYmVsT2Zmc2V0ID0gZ2V0VGlja0xhYmVsT2Zmc2V0KFxuICAgICAgICBkYXRhLFxuICAgICAgICBjb25maWcsXG4gICAgICAgIGNoYXJ0U2l6aW5nVmFsdWVzLFxuICAgICAgICAwLFxuICAgICAgKTtcbiAgICAgIHJldHVybiBbeyB2YWx1ZTogbGFiZWxPZmZzZXQsIGxhYmVsOiBnZXRMYWJlbCgwKSB9XTtcbiAgICB9XG5cbiAgICBjb25zdCBsYXN0SW5kZXggPSBkYXRhLngubGVuZ3RoIC0gMTtcbiAgICBjb25zdCB0aWNrQnVja2V0U3BhY2luZyA9IE1hdGguY2VpbChsYXN0SW5kZXggLyB0aWNrQ291bnQpO1xuICAgIGNvbnN0IG51bVRpY2tzID0gTWF0aC5mbG9vcihsYXN0SW5kZXggLyB0aWNrQnVja2V0U3BhY2luZykgKyAxO1xuICAgIGNvbnN0IHN0ZXAgPSBsYXN0SW5kZXggLyAobnVtVGlja3MgLSAxKTtcblxuICAgIC8vIEFsd2F5cyBpbmNsdWRlIGZpcnN0IGFuZCBsYXN0IGRhdGEgcG9pbnRzLlxuICAgIC8vIElubmVyIHRpY2tzIGFyZSBhcHByb3hpbWF0ZWx5IGV2ZW5seSBzcGFjZWQgdXNpbmcgcm91bmRpbmcuXG4gICAgY29uc3QgaW5kaWNlczogbnVtYmVyW10gPSBbXTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IG51bVRpY2tzOyBpKyspIHtcbiAgICAgIGluZGljZXMucHVzaChNYXRoLnJvdW5kKGkgKiBzdGVwKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGluZGljZXMubWFwKGkgPT4ge1xuICAgICAgY29uc3QgbGFiZWxPZmZzZXQgPSBnZXRUaWNrTGFiZWxPZmZzZXQoXG4gICAgICAgIGRhdGEsXG4gICAgICAgIGNvbmZpZyxcbiAgICAgICAgY2hhcnRTaXppbmdWYWx1ZXMsXG4gICAgICAgIGksXG4gICAgICApO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgdmFsdWU6XG4gICAgICAgICAgZ2V0VG90YWxQcmVCdWNrZXRHYXAoZGF0YSwgY29uZmlnLCBjaGFydFNpemluZ1ZhbHVlcywgaSkgK1xuICAgICAgICAgIGxhYmVsT2Zmc2V0LFxuICAgICAgICBsYWJlbDogZ2V0TGFiZWwoaSksXG4gICAgICB9O1xuICAgIH0pO1xuICB9XG5cbiAgZnVuY3Rpb24gZ2V0VGlja0xhYmVsT2Zmc2V0KFxuICAgIGRhdGE6IE5vbkZsb3dEYXRhLFxuICAgIGNvbmZpZzogQ29uZmlnLFxuICAgIGNoYXJ0U2l6aW5nVmFsdWVzOiBGdWxsQ2hhcnRTY2FsZVZhbHVlcyxcbiAgICBidWNrZXRJbmRleDogbnVtYmVyLFxuICApIHtcbiAgICBjb25zdCBpbmhlcmVudE9mZnNldCA9XG4gICAgICBjaGFydFNpemluZ1ZhbHVlcy5jaGFydERhdGFEaXJlY3Rpb24gPT09ICdob3Jpem9udGFsJ1xuICAgICAgICA/IGNoYXJ0U2l6aW5nVmFsdWVzLnRvdGFsVG9wT2Zmc2V0XG4gICAgICAgIDogY2hhcnRTaXppbmdWYWx1ZXMudG90YWxMZWZ0T2Zmc2V0O1xuICAgIC8vVG8gaGF2ZSB0aGUgbGFiZWwgYmUgY2VudGVyZWQgb24gdGhlIGJ1Y2tldCdzIGNlbnRlciBwb3NpdGlvblxuICAgIGNvbnN0IGJ1Y2tldE9mZnNldCA9IGdldEJ1Y2tldFNpemUoZGF0YSwgY29uZmlnLCBjaGFydFNpemluZ1ZhbHVlcykgLyAyO1xuICAgIGxldCBob3Jpem9udGFsQmFyT2Zmc2V0ID0gMDtcbiAgICBpZiAoY2hhcnRTaXppbmdWYWx1ZXMuY2hhcnREYXRhRGlyZWN0aW9uID09PSAnaG9yaXpvbnRhbCcpIHtcbiAgICAgIC8vVGhpcyBhY2NvdW50IGZvciB0aGUgZmFjdCB0aGF0IHRoZSBpbmhlcmVudE9mZnNldCBhbmQgYnVja2V0T2Zmc2V0IHJlc3VsdCBpbiBtYXRjaGluZyB5IHZhbHVlcyBmb3IgdGhlIGJhciBhbmQgdGhlIGxhYmVsXG4gICAgICAvLyAgSG93ZXZlciwgZm9yIHRoZSBiYXIsIHRoYXQgeSBwb3NpdGlvbiBpcyB0aGUgdG9wIG9mIHRoZSBiYXIsIHdoaWxlIGZvciB0aGUgbGFiZWwsIGl0J3MgdGhlIGJvdHRvbSBvZiB0aGUgbGFiZWxcbiAgICAgIC8vICBXaGVuIGV4YWN0bHkgbGluZWQgdXAgbGlrZSB0aGF0LCB0aGUgbGFiZWwgYWN0dWFsbHkgbG9va3MgYSBsaXR0bGUgbG93LCBzbyB0aGF0IC0yIG1ha2VzIGl0IGxvb2sgY29ycmVjdFxuICAgICAgaG9yaXpvbnRhbEJhck9mZnNldCA9IGNoYXJ0U2l6aW5nVmFsdWVzLmZvbnRTaXplIC8gMiAtIDI7XG4gICAgfVxuXG4gICAgcmV0dXJuIGluaGVyZW50T2Zmc2V0ICsgYnVja2V0T2Zmc2V0ICsgaG9yaXpvbnRhbEJhck9mZnNldDtcbiAgfVxuXG4gIGV4cG9ydCB0eXBlIElucHV0RGF0YSA9IExhYmVsZWREYXRhIHwgVGltZXNlcmllc0RhdGEgfCBGbG93RGF0YTtcbiAgZXhwb3J0IHR5cGUgUHJvY2Vzc0RhdGEgPSBMYWJlbGVkRGF0YSB8IFRpbWVzZXJpZXNEYXRhIHwgUHJvY2Vzc2VkRmxvd0RhdGE7XG4gIGV4cG9ydCB0eXBlIE5vbkZsb3dEYXRhID0gTGFiZWxlZERhdGEgfCBUaW1lc2VyaWVzRGF0YTtcblxuICB0eXBlIEJhc2VEYXRhID0ge1xuICAgIHlzOiBEYXRhWVtdO1xuICAgIHN1cHBsZW1lbnRhcnlZcz86IFN1cHBsZW1lbnRhcnlEYXRhWVtdO1xuICB9O1xuXG4gIGV4cG9ydCB0eXBlIFBhdHRlcm4gPSAnc29saWQnIHwgJ3N0cmlwZWQnIHwgJ2RvdHMnO1xuXG4gIGV4cG9ydCB0eXBlIERhdGFZID0ge1xuICAgIGxhYmVsOiBzdHJpbmc7XG4gICAgY29sb3JUb2tlbj86IHN0cmluZztcbiAgICBoaWRkZW4/OiBib29sZWFuO1xuICAgIGlzU2Vjb25kYXJ5PzogYm9vbGVhbjtcbiAgICBwYXR0ZXJuPzogUGF0dGVybjtcbiAgICBzaG93TGVnZW5kSXRlbT86IGJvb2xlYW47XG4gICAgY2xpY2thYmxlPzogYm9vbGVhbjtcbiAgICB2YWx1ZXM6IG51bWJlcltdO1xuICB9O1xuXG4gIGV4cG9ydCB0eXBlIFN1cHBsZW1lbnRhcnlEYXRhWSA9IERhdGFZICYge1xuICAgIHN1cHBsZW1lbnRhbEluZGV4OiBudW1iZXI7XG4gIH07XG5cbiAgZXhwb3J0IHR5cGUgRmxvd1kgPSB7XG4gICAgc3RlcHM6IHN0cmluZ1tdOyAvL1Nob3VsZCBhbHdheXMgbWF0Y2ggaW4gbGVuZ3RoIHcvIHZhbHVlc1xuICAgIHZhbHVlczogbnVtYmVyW107IC8vRmxvd1kgdmFsdWVzIHNob3VsZCBhbHdheXMgYmUgd2Vha2x5IGRlY3JlYXNpbmdcbiAgICBjbGlja2FibGU/OiBib29sZWFuO1xuICB9O1xuXG4gIC8vQ3VycmVudGx5IG9ubHkgc3VwcG9ydGVkIGZvciBob3Jpem9udGFsIGJhciBjaGFydHNcbiAgZXhwb3J0IHR5cGUgTGFiZWxlZERhdGEgPSBCYXNlRGF0YSAmIHtcbiAgICB0eXBlOiAnbGFiZWxlZCc7XG4gICAgeDogeyBsYWJlbDogc3RyaW5nOyBpc1NlY29uZGFyeT86IGJvb2xlYW4gfVtdO1xuICB9O1xuXG4gIGV4cG9ydCB0eXBlIFRpbWVzZXJpZXNEYXRhID0gQmFzZURhdGEgJiB7XG4gICAgdHlwZTogJ3RpbWVzZXJpZXMnO1xuICAgIHg6IG51bWJlcltdO1xuICB9O1xuXG4gIGV4cG9ydCB0eXBlIEZsb3dEYXRhID0ge1xuICAgIHR5cGU6ICdmbG93JztcbiAgICB5czogRmxvd1lbXTtcbiAgfTtcblxuICBleHBvcnQgdHlwZSBQcm9jZXNzZWRGbG93RGF0YSA9IHtcbiAgICB0eXBlOiAnZmxvdy1wcm9jZXNzZWQnO1xuICAgIHg6IEZsb3dCdWNrZXRbXTtcbiAgfTtcblxuICB0eXBlIEZsb3dCdWNrZXQgPSB7XG4gICAgdG90YWxDb3VudDogbnVtYmVyO1xuICAgIHN1YkJ1Y2tldHM6IEZsb3dTdWJCdWNrZXRbXTtcbiAgfTtcblxuICB0eXBlIEZsb3dTdWJCdWNrZXQgPSB7XG4gICAgaWQ6IHN0cmluZztcbiAgICBjb3VudDogbnVtYmVyO1xuICAgIGNvbm5lY3Rpb25zOiBGbG93Q29ubmVjdGlvbltdO1xuICB9O1xuXG4gIHR5cGUgRmxvd0Nvbm5lY3Rpb24gPSB7XG4gICAgZGlyZWN0aW9uOiAnZm9yd2FyZCcgfCAnYmFja3dhcmQnO1xuICAgIHN0YXJ0OiBzdHJpbmc7XG4gICAgZW5kOiBzdHJpbmc7XG4gICAgY291bnQ6IG51bWJlcjtcbiAgfTtcblxuICBleHBvcnQgdHlwZSBGbG93Q29ubmVjdGlvblJlbmRlciA9IE9taXQ8Rmxvd0Nvbm5lY3Rpb24sICdkaXJlY3Rpb24nPiAmIHtcbiAgICBlbGVtZW50VHlwZTogJ2Nvbm5lY3Rpb24nO1xuICAgIHN0ZXA6IG51bWJlcjtcbiAgICBwYXRoOiBzdHJpbmc7XG4gICAgZW1waGFzaXplPzogYm9vbGVhbjtcbiAgICB0b3BMaW5lOiB7XG4gICAgICB4MTogbnVtYmVyO1xuICAgICAgeTE6IG51bWJlcjtcbiAgICAgIHgyOiBudW1iZXI7XG4gICAgICB5MjogbnVtYmVyO1xuICAgIH07XG4gICAgYm90dG9tTGluZToge1xuICAgICAgeDE6IG51bWJlcjtcbiAgICAgIHkxOiBudW1iZXI7XG4gICAgICB4MjogbnVtYmVyO1xuICAgICAgeTI6IG51bWJlcjtcbiAgICB9O1xuICB9O1xuXG4gIHR5cGUgRG9udXREYXRhID0ge1xuICAgIGxhYmVsOiBzdHJpbmc7XG4gICAgaGlkZGVuPzogYm9vbGVhbjtcbiAgICB2YWx1ZTogbnVtYmVyO1xuICAgIGlzU2Vjb25kYXJ5PzogYm9vbGVhbjtcbiAgfTtcblxuICB0eXBlIERpbWVuc2lvbnMgPSB7XG4gICAgd2lkdGg6IG51bWJlcjtcbiAgICBoZWlnaHQ6IG51bWJlcjtcbiAgfTtcblxuICBleHBvcnQgdHlwZSBDaGFydFR5cGUgPVxuICAgIHwgJ2xpbmUnXG4gICAgfCAnYXJlYSdcbiAgICB8ICdiYXInXG4gICAgfCAnaG9yaXpvbnRhbC1iYXInXG4gICAgfCAnZG9udXQnXG4gICAgfCAnd2F0ZXJmYWxsJ1xuICAgIHwgJ2Z1bm5lbCdcbiAgICB8ICdmbG93JztcblxuICB0eXBlIEJhc2VDb25maWcgPSB7XG4gICAgdHlwZTogQ2hhcnRUeXBlO1xuICAgIGdyb3VwZWRUb29sdGlwOiBib29sZWFuO1xuICAgIGNvbG9yczogc3RyaW5nW107XG4gICAgYWxsb3dMZWdlbmRUb2dnbGU6IGJvb2xlYW47XG4gICAgemVyb1N0YXRlTWVzc2FnZTogc3RyaW5nO1xuICAgIHNpemluZ0Vycm9yU3RhdGVNZXNzYWdlOiBzdHJpbmc7XG4gICAgdmFsdWVUeXBlOiBWYWx1ZVR5cGU7XG4gICAgc2Vjb25kYXJ5VmFsdWVUeXBlPzogVmFsdWVUeXBlO1xuICAgIHRydW5jYXRlTGVnZW5kOiBib29sZWFuO1xuICAgIGRhdGVGb3JtYXQ/OiBJbnRlcnZhbDtcbiAgICBzaG93RGF0YUxhYmVscz86IGJvb2xlYW47XG4gIH07XG5cbiAgdHlwZSBEb251dFN1YkNvbmZpZyA9IHtcbiAgICBzaXplOiAneHNtYWxsJyB8ICdzbWFsbCcgfCAnbWVkaXVtJyB8ICdsYXJnZSc7XG4gICAgZGlzcGxheVZhbHVlOiBzdHJpbmc7XG4gICAgZGlzcGxheUxhYmVsPzogc3RyaW5nO1xuICAgIHNjYWxpbmdDb25maWc/OiBEb251dFNpemluZ0NvbmZpZztcbiAgfTtcblxuICB0eXBlIEZsb3dTdWJDb25maWcgPSB7XG4gICAgc3VidGl0bGVGb3JtYXRTdHJpbmc6IHN0cmluZztcbiAgICBzdWJCdWNrZXRzQ29uZmlnOiB7XG4gICAgICBidWNrZXRJZDogc3RyaW5nO1xuICAgICAgYnVja2V0TmFtZTogc3RyaW5nO1xuICAgICAgY29sb3I6IHN0cmluZztcbiAgICAgIGlzSGlnaGxpZ2h0ZWQ/OiBib29sZWFuO1xuICAgIH1bXTtcbiAgICBjb25uZWN0aW9uQ29sb3I/OiBzdHJpbmc7XG4gIH07XG5cbiAgZXhwb3J0IHR5cGUgQ29uZmlnID0gQmFzZUNvbmZpZyAmXG4gICAgKFxuICAgICAgfCB7XG4gICAgICAgICAgdHlwZTogJ2xpbmUnIHwgJ2FyZWEnIHwgJ3dhdGVyZmFsbCcgfCAnZnVubmVsJztcbiAgICAgICAgICBzY2FsaW5nQ29uZmlnPzogRnVsbFNjYWxpbmdDb25maWc7XG4gICAgICAgIH1cbiAgICAgIHwge1xuICAgICAgICAgIHR5cGU6ICdiYXInIHwgJ2hvcml6b250YWwtYmFyJztcbiAgICAgICAgICBncm91cGluZ1R5cGU6ICdzdGFja2VkJyB8ICdjbHVzdGVyZWQnO1xuICAgICAgICAgIHNjYWxpbmdDb25maWc/OiBGdWxsU2NhbGluZ0NvbmZpZztcbiAgICAgICAgfVxuICAgICAgfCB7XG4gICAgICAgICAgdHlwZTogJ2RvbnV0JztcbiAgICAgICAgICBkb251dERpc3BsYXlJbmZvOiBEb251dFN1YkNvbmZpZztcbiAgICAgICAgfVxuICAgICAgfCB7XG4gICAgICAgICAgdHlwZTogJ2Zsb3cnO1xuICAgICAgICAgIHNob3dEYXRhTGFiZWxzOiB0cnVlO1xuICAgICAgICAgIGZsb3dDb25maWc6IEZsb3dTdWJDb25maWc7XG4gICAgICAgICAgc2NhbGluZ0NvbmZpZz86IEZ1bGxTY2FsaW5nQ29uZmlnO1xuICAgICAgICB9XG4gICAgKTtcblxuICB0eXBlIERvbnV0Q29uZmlnID0gRXh0cmFjdDxDb25maWcsIHsgdHlwZTogJ2RvbnV0JyB9PjtcblxuICB0eXBlIEZsb3dDb25maWcgPSBFeHRyYWN0PENvbmZpZywgeyB0eXBlOiAnZmxvdycgfT47XG5cbiAgdHlwZSBDb25maWdXaXRoRnVsbFNjYWxpbmcgPSBFeHRyYWN0PFxuICAgIENvbmZpZyxcbiAgICB7XG4gICAgICB0eXBlOlxuICAgICAgICB8ICdiYXInXG4gICAgICAgIHwgJ2hvcml6b250YWwtYmFyJ1xuICAgICAgICB8ICdsaW5lJ1xuICAgICAgICB8ICdhcmVhJ1xuICAgICAgICB8ICd3YXRlcmZhbGwnXG4gICAgICAgIHwgJ2Z1bm5lbCdcbiAgICAgICAgfCAnZmxvdyc7XG4gICAgfVxuICA+O1xuXG4gIGV4cG9ydCBjb25zdCBkZWZhdWx0Q29uZmlnOiBDb25maWcgPSB7XG4gICAgdHlwZTogJ2xpbmUnLFxuICAgIGdyb3VwZWRUb29sdGlwOiB0cnVlLFxuICAgIGNvbG9yczogZGVmYXVsdENvbG9yUGFsZXR0ZSxcbiAgICBhbGxvd0xlZ2VuZFRvZ2dsZTogZmFsc2UsXG4gICAgemVyb1N0YXRlTWVzc2FnZTogJ05vIGRhdGEgdG8gZGlzcGxheS4nLFxuICAgIHNpemluZ0Vycm9yU3RhdGVNZXNzYWdlOiAnVGhlIGNoYXJ0IGNhbm5vdCBkaXNwbGF5IGF0IHRoZSBjdXJyZW50IHNpemUuJyxcbiAgICB2YWx1ZVR5cGU6ICdjdXJyZW5jeScsXG4gICAgdHJ1bmNhdGVMZWdlbmQ6IHRydWUsXG4gICAgZGF0ZUZvcm1hdDogJ2RheScsXG4gIH07XG5cbiAgZXhwb3J0IGNvbnN0IGRlZmF1bHREb251dENvbmZpZzogQ29uZmlnID0ge1xuICAgIHR5cGU6ICdkb251dCcsXG4gICAgZ3JvdXBlZFRvb2x0aXA6IHRydWUsXG4gICAgY29sb3JzOiBkZWZhdWx0Q29sb3JQYWxldHRlLFxuICAgIGFsbG93TGVnZW5kVG9nZ2xlOiBmYWxzZSxcbiAgICB6ZXJvU3RhdGVNZXNzYWdlOiAnTm8gZGF0YSB0byBkaXNwbGF5LicsXG4gICAgc2l6aW5nRXJyb3JTdGF0ZU1lc3NhZ2U6ICdUaGUgY2hhcnQgY2Fubm90IGRpc3BsYXkgYXQgdGhlIGN1cnJlbnQgc2l6ZS4nLFxuICAgIHZhbHVlVHlwZTogJ2N1cnJlbmN5JyxcbiAgICB0cnVuY2F0ZUxlZ2VuZDogdHJ1ZSxcbiAgICBkYXRlRm9ybWF0OiAnZGF5JyxcbiAgICBkb251dERpc3BsYXlJbmZvOiB7XG4gICAgICBzaXplOiAnbWVkaXVtJyxcbiAgICAgIGRpc3BsYXlWYWx1ZTogJycsXG4gICAgfSxcbiAgfTtcblxuICB0eXBlIEdlbmVyaWNUaWNrID0ge1xuICAgIHZhbHVlOiBudW1iZXI7XG4gICAgbGFiZWw6IHN0cmluZztcbiAgICBzZWNvbmRhcnlMYWJlbD86IHN0cmluZztcbiAgfTtcblxuICB0eXBlIFhUaWNrID0gT21pdDxHZW5lcmljVGljaywgJ3ZhbHVlJz4gJiB7XG4gICAgeDogbnVtYmVyO1xuICB9O1xuXG4gIGZ1bmN0aW9uIHRvWFRpY2sodGljazogR2VuZXJpY1RpY2spOiBYVGljayB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHg6IHRpY2sudmFsdWUsXG4gICAgICBsYWJlbDogdGljay5sYWJlbCxcbiAgICAgIHNlY29uZGFyeUxhYmVsOiB0aWNrLnNlY29uZGFyeUxhYmVsLFxuICAgIH07XG4gIH1cblxuICB0eXBlIFlUaWNrID0gT21pdDxHZW5lcmljVGljaywgJ3ZhbHVlJz4gJiB7XG4gICAgeTogbnVtYmVyO1xuICB9O1xuXG4gIGZ1bmN0aW9uIHRvWVRpY2sodGljazogR2VuZXJpY1RpY2spOiBZVGljayB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHk6IHRpY2sudmFsdWUsXG4gICAgICBsYWJlbDogdGljay5sYWJlbCxcbiAgICAgIHNlY29uZGFyeUxhYmVsOiB0aWNrLnNlY29uZGFyeUxhYmVsLFxuICAgIH07XG4gIH1cblxuICB0eXBlIEJhc2ljUmVjdCA9IHtcbiAgICBlbGVtZW50VHlwZTogJ3JlY3QnO1xuICAgIHJlY3RUeXBlPzogc3RyaW5nO1xuICAgIHg6IG51bWJlcjtcbiAgICB5OiBudW1iZXI7XG4gICAgd2lkdGg6IG51bWJlcjtcbiAgICBoZWlnaHQ6IG51bWJlcjtcbiAgICBvZmZzZXQ/OiBudW1iZXI7XG4gICAgcGF0dGVybj86IFBhdHRlcm47XG4gICAgcm91bmRpbmc/OiAndG9wJyB8ICdib3R0b20nIHwgJ2FsbCcgfCAnbm9uZSc7XG4gICAgbm9uRGlzcGxheT86IGJvb2xlYW47XG4gIH07XG5cbiAgdHlwZSBGbG93UmVjdCA9IEJhc2ljUmVjdCAmIHtcbiAgICByZWN0VHlwZTogJ2Zsb3cnO1xuICAgIGlkOiBzdHJpbmc7XG4gICAgYnVja2V0SW5kZXg6IG51bWJlcjtcbiAgICBjb3VudDogbnVtYmVyO1xuICAgIHRvdGFsQ291bnQ6IG51bWJlcjtcbiAgICBjb2xvck92ZXJyaWRlPzogc3RyaW5nO1xuICAgIGRhcmtlbjogYm9vbGVhbjtcbiAgICBkZUVtcGhhc2l6ZTogYm9vbGVhbjtcbiAgfTtcblxuICBleHBvcnQgdHlwZSBSZWN0ID0gKEJhc2ljUmVjdCAmIHsgcmVjdFR5cGU/OiB1bmRlZmluZWQgfSkgfCBGbG93UmVjdDtcblxuICB0eXBlIENpcmNsZSA9IHtcbiAgICBjeDogbnVtYmVyO1xuICAgIGN5OiBudW1iZXI7XG4gIH07XG5cbiAgZXhwb3J0IHR5cGUgRmxvd0hvdmVyVGFyZ2V0ID1cbiAgICB8IHtcbiAgICAgICAgaG92ZXJUYXJnZXQ6ICdiYXJUaXRsZSc7XG4gICAgICAgIGJ1Y2tldEluZGV4OiBudW1iZXI7XG4gICAgICAgIGJhcklkOiBzdHJpbmc7XG4gICAgICB9XG4gICAgfCB7XG4gICAgICAgIGhvdmVyVGFyZ2V0OiAnYmFyJztcbiAgICAgICAgYnVja2V0SW5kZXg6IG51bWJlcjtcbiAgICAgICAgYmFySWQ6IHN0cmluZztcbiAgICAgICAgZm9yRGFya2VuOiBib29sZWFuO1xuICAgICAgfVxuICAgIHwge1xuICAgICAgICBob3ZlclRhcmdldDogJ2Nvbm5lY3Rpb24nO1xuICAgICAgICBzdGFydElkOiBzdHJpbmc7XG4gICAgICAgIGVuZElkOiBzdHJpbmc7XG4gICAgICAgIHN0YXJ0QnVja2V0SW5kZXg6IG51bWJlcjtcbiAgICAgIH07XG5cbiAgZXhwb3J0IHR5cGUgRmxvd0hvdmVyUmV0dXJuID0ge1xuICAgIGhvdmVyVHlwZTogJ2Zsb3cnO1xuXG4gICAgdG9vbHRpcDoge1xuICAgICAgYW5jaG9yOiBET01SZWN0O1xuICAgICAgc3VidGl0bGU6IHN0cmluZztcbiAgICAgIHNlY29uZGFyeVN1YnRpdGxlPzogc3RyaW5nO1xuICAgIH07XG4gIH0gJiBGbG93SG92ZXJUYXJnZXQ7XG5cbiAgLyoqXG4gICAqIEVtaXR0ZWQgd2hlbiBhIGNsaWNrYWJsZSBmbG93IGVsZW1lbnQgaXMgY2xpY2tlZC4gYHlJbmRpY2VzYCBhcmUgdGhlXG4gICAqIGluZGljZXMgaW50byBgRmxvd0RhdGEueXNgIG9mIHRoZSBwYXRocyB0aGF0IG1ha2UgdXAgdGhlIGNsaWNrZWQgZWxlbWVudC5cbiAgICovXG4gIGV4cG9ydCB0eXBlIEZsb3dDbGlja0V2ZW50ID0ge1xuICAgIGNvdW50OiBudW1iZXI7XG4gICAgeUluZGljZXM6IG51bWJlcltdO1xuICB9ICYgKFxuICAgIHwgKHtcbiAgICAgICAgYnVja2V0SW5kZXg6IG51bWJlcjtcbiAgICAgICAgYmFySWQ6IHN0cmluZztcbiAgICAgIH0gJiAoXG4gICAgICAgIHwge1xuICAgICAgICAgICAgdGFyZ2V0OiAndGl0bGUnO1xuICAgICAgICAgIH1cbiAgICAgICAgfCB7XG4gICAgICAgICAgICB0YXJnZXQ6ICdjb250aW51aW5nJyB8ICdlbmRpbmcnO1xuICAgICAgICAgICAgdG90YWxDb3VudDogbnVtYmVyO1xuICAgICAgICAgIH1cbiAgICAgICkpXG4gICAgfCB7XG4gICAgICAgIHRhcmdldDogJ2Nvbm5lY3Rpb24nO1xuICAgICAgICBzdGFydEJ1Y2tldEluZGV4OiBudW1iZXI7XG4gICAgICAgIHN0YXJ0SWQ6IHN0cmluZztcbiAgICAgICAgZW5kSWQ6IHN0cmluZztcbiAgICAgIH1cbiAgKTtcblxuICBleHBvcnQgdHlwZSBIb3ZlclJldHVybiA9XG4gICAgfCB7XG4gICAgICAgIGhvdmVyVHlwZTogJ3N0YW5kYXJkJztcbiAgICAgICAgLy8gdGhlIGluZGljZXMgaW50byB0aGUgZGF0YSBvZiB0aGUgY2xvc2VzdCBwb2ludFxuICAgICAgICB4SW5kZXg6IG51bWJlcjtcbiAgICAgICAgLy8gd2Ugd2FudCB0byBrbm93IHdoaWNoIHZpc2libGUgeSBpbmRleCBpcyBob3ZlcmVkXG4gICAgICAgIC8vIGFuZCB3aGljaCBhY3R1YWwgeSBpbmRleCBpcyBob3ZlcmVkXG4gICAgICAgIHlJbmRleDogbnVtYmVyO1xuICAgICAgICB2aXNpYmxlWUluZGV4OiBudW1iZXI7XG4gICAgICAgIGlzU3VwcFZhbHVlPzogYm9vbGVhbjtcbiAgICAgICAgc3VwcFlJbmRleD86IG51bWJlcjtcbiAgICAgICAgLy9GdW5uZWwgb25seSwgZm9yIHdoZW4gZHJvcE9mZiBzZWN0aW9uIGlzIGhvdmVyZWRcbiAgICAgICAgaXNEcm9wT2ZmPzogYm9vbGVhbjtcblxuICAgICAgICAvLyB0aGUgdmlld3BvcnQgeCBhbmQgeXMgb2YgdGhlIGhvdmVyZWQgaXRlbXNcbiAgICAgICAgeDogbnVtYmVyO1xuICAgICAgICB5czogbnVtYmVyW107XG5cbiAgICAgICAgdG9vbHRpcDoge1xuICAgICAgICAgIGFuY2hvcjogRE9NUmVjdDtcbiAgICAgICAgICBwcmVmZXJyZWRQb3NpdGlvbj86IENhbGxvdXRDb21wb25lbnQuQW5jaG9yZWRQb3NpdGlvbjtcbiAgICAgICAgICBkYXRlOiBzdHJpbmcgfCBudWxsO1xuICAgICAgICAgIG1ldHJpY3M6IHtcbiAgICAgICAgICAgIGNvbG9yOiBzdHJpbmc7XG4gICAgICAgICAgICBsYWJlbDogc3RyaW5nO1xuICAgICAgICAgICAgdmFsdWU6IHN0cmluZztcbiAgICAgICAgICAgIHBhdHRlcm4/OiBQYXR0ZXJuO1xuICAgICAgICAgIH1bXTtcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICB8IEZsb3dIb3ZlclJldHVyblxuICAgIHwgbnVsbDtcblxuICAvLyBIb3ZlciBpcyBhIGZ1bmN0aW9uIHRoYXQgdGFrZXMgYSB2aWV3cG9ydCB4IGFuZCB5IGFuZCByZXR1cm5zIGEgcmljaFxuICAvLyBzZXQgb2YgaW5mb3JtYXRpb24gYWJvdXQgd2hhdCB2YWx1ZXMgYXJlIGJlaW5nIGhvdmVyZWQgYW5kIHdoYXQgdGhlIHRvb2x0aXBcbiAgLy8gc2hvdWxkIGxvb2sgbGlrZVxuICBleHBvcnQgdHlwZSBIb3ZlciA9IChwb3M6IHtcbiAgICByZWN0OiBET01SZWN0O1xuICAgIHg6IG51bWJlcjtcbiAgICB5OiBudW1iZXI7XG4gICAgY29udGFpbmVyU2Nyb2xsWDogbnVtYmVyO1xuICAgIGNvbnRhaW5lclNjcm9sbFk6IG51bWJlcjtcbiAgfSkgPT4gSG92ZXJSZXR1cm47XG5cbiAgZXhwb3J0IHR5cGUgVG9vbHRpcENvbnRleHQgPSB7XG4gICAgeEluZGV4OiBudW1iZXI7XG4gICAgeUluZGV4OiBudW1iZXI7XG4gICAgaXNTdXBwVmFsdWU/OiBib29sZWFuO1xuICAgIHN1cHBZSW5kZXg/OiBudW1iZXI7XG4gIH07XG5cbiAgLy8gUmVuZGVyZWRDaGFydCByZXByZXNlbnRzIGFsbCBvZiB0aGUgcGFydHMgb2YgYSBjaGFydFxuICAvLyB0aGF0IGVuZCB1cCBvbiBzY3JlZW4uIEV2ZXJ5IGNoYXJ0IGhhcyB4IGFuZCB5IHRpY2tzXG4gIC8vIGFuZCBob3ZlciBmdW5jdGlvbmFsaXR5LCBldmVuIHRob3VnaCB0aGV5IG1pZ2h0IGJlXG4gIC8vIGRpZmZlcmVudCBmcm9tIGNoYXJ0IHRvIGNoYXJ0LlxuICBleHBvcnQgdHlwZSBSZW5kZXJlZENoYXJ0ID0ge1xuICAgIGNoYXJ0V2lkdGg6IG51bWJlcjtcbiAgICBjaGFydEhlaWdodDogbnVtYmVyO1xuICAgIGNoYXJ0U2l6aW5nVmFsdWVzOiBGdWxsQ2hhcnRTY2FsZVZhbHVlcztcbiAgICB4VGlja3M6IFhUaWNrW107XG4gICAgeVRpY2tzOiBZVGlja1tdO1xuICAgIGhvdmVyPzogSG92ZXI7XG4gICAgY29sb3JzOiBzdHJpbmdbXTtcbiAgICBsaW5lczogeyBwYXR0ZXJuPzogUGF0dGVybjsgbGluZTogc3RyaW5nIHwgbnVsbCB9W107XG4gICAgY2lyY2xlczogQ2lyY2xlW107IC8vTGluZSBmYWxsYmFjayBmb3IgYSBzaW5nbGUgcG9pbnRcbiAgICBhcmVhczogeyBwYXR0ZXJuPzogUGF0dGVybjsgYXJlYTogc3RyaW5nIHwgbnVsbCB9W107XG4gICAgYmFyczogUmVjdFtdW107XG4gICAgYXJjczogKHN0cmluZyB8IG51bGwpW107XG4gICAgaG9yaXpvbnRhbEJhcnM6IHtcbiAgICAgIHBhdHRlcm4/OiBQYXR0ZXJuO1xuICAgICAgaG9yaXpvbnRhbEJhcjogc3RyaW5nIHwgbnVsbDtcbiAgICAgIHg6IG51bWJlcjtcbiAgICAgIHk6IG51bWJlcjtcbiAgICB9W11bXTtcbiAgICBkYXRhTGFiZWxzOiBEYXRhTGFiZWxbXTtcbiAgICB3YXRlcmZhbGxMaW5lczoge1xuICAgICAgeDE6IG51bWJlcjtcbiAgICAgIHgyOiBudW1iZXI7XG4gICAgICB5MTogbnVtYmVyO1xuICAgICAgeTI6IG51bWJlcjtcbiAgICB9W107XG4gICAgZ3JhZGllbnRzOiBSZWN0W11bXTtcbiAgICBmbG93Q29ubmVjdGlvbnM6IEZsb3dDb25uZWN0aW9uUmVuZGVyW107XG4gICAgaG9yaXpvbnRhbENvbnRhaW5lclNjYWxlOiBDb250YWluZXJTY2FsaW5nVHlwZTtcbiAgICB2ZXJ0aWNhbENvbnRhaW5lclNjYWxlOiBDb250YWluZXJTY2FsaW5nVHlwZTtcbiAgICBjaGFydEVycm9yOiAnc2l6aW5nJyB8ICdjb25maWcnIHwgbnVsbDtcbiAgfTtcblxuICB0eXBlIEJhc2ljRGF0YUxhYmVsID0ge1xuICAgIGVsZW1lbnRUeXBlOiAnZGF0YUxhYmVsJztcbiAgICBkYXRhTGFiZWxUeXBlPzogc3RyaW5nO1xuICAgIGxhYmVsOiBzdHJpbmc7XG4gICAgeFBvczogbnVtYmVyO1xuICAgIHlQb3M6IG51bWJlcjtcbiAgICBhbmNob3I6ICdzdGFydCcgfCAnbWlkZGxlJyB8ICdlbmQnO1xuICAgIGxpbmU/OiB7XG4gICAgICB4MTogbnVtYmVyO1xuICAgICAgeTE6IG51bWJlcjtcbiAgICAgIHgyOiBudW1iZXI7XG4gICAgICB5MjogbnVtYmVyO1xuICAgIH07XG4gICAgYm9sZD86IGJvb2xlYW47XG4gIH07XG5cbiAgdHlwZSBGbG93RGF0YUxhYmVsID0gQmFzaWNEYXRhTGFiZWwgJiB7XG4gICAgZWxlbWVudFR5cGU6ICdkYXRhTGFiZWwnO1xuICAgIGRhdGFMYWJlbFR5cGU6ICdmbG93JztcbiAgICAvL0hlbHBlciBkYXRhIGZvciBmbG93c1xuICAgIGJ1Y2tldEluZGV4OiBudW1iZXI7XG4gICAgYmFySWQ6IHN0cmluZztcbiAgfTtcblxuICBleHBvcnQgdHlwZSBEYXRhTGFiZWwgPVxuICAgIHwgKEJhc2ljRGF0YUxhYmVsICYgeyBkYXRhTGFiZWxUeXBlPzogdW5kZWZpbmVkIH0pXG4gICAgfCBGbG93RGF0YUxhYmVsO1xuXG4gIGNvbnN0IGVtcHR5Q2hhcnQ6IFJlbmRlcmVkQ2hhcnQgPSB7XG4gICAgY2hhcnRXaWR0aDogMCxcbiAgICBjaGFydEhlaWdodDogMCxcbiAgICBjaGFydFNpemluZ1ZhbHVlczogZW1wdHlDaGFydFNjYWxlVmFsdWVzLFxuICAgIHhUaWNrczogW10sXG4gICAgeVRpY2tzOiBbXSxcbiAgICBjb2xvcnM6IFtdLFxuICAgIGxpbmVzOiBbXSxcbiAgICBjaXJjbGVzOiBbXSxcbiAgICBhcmVhczogW10sXG4gICAgYmFyczogW10sXG4gICAgYXJjczogW10sXG4gICAgaG9yaXpvbnRhbEJhcnM6IFtdLFxuICAgIGRhdGFMYWJlbHM6IFtdLFxuICAgIHdhdGVyZmFsbExpbmVzOiBbXSxcbiAgICBncmFkaWVudHM6IFtdLFxuICAgIGZsb3dDb25uZWN0aW9uczogW10sXG4gICAgaG9yaXpvbnRhbENvbnRhaW5lclNjYWxlOiAnbm8tc2NhbGUnLFxuICAgIHZlcnRpY2FsQ29udGFpbmVyU2NhbGU6ICduby1zY2FsZScsXG4gICAgY2hhcnRFcnJvcjogbnVsbCxcbiAgfTtcblxuICAvLyd5JyBpbiB0aGlzIGZ1bmN0aW9uIHJlZmVycyB0byB0aGUgZGF0YSB5LCBzaW5jZSB0aGlzIGZ1bmN0aW9uXG4gIC8vIGlzIGFsc28gdXNlZCBieSBob3Jpem9udGFsLWJhcnMsIHdoZXJlIHRoZSBkYXRhIHkgaXMgdGhlIGNoYXJ0IHhcbiAgZnVuY3Rpb24gY2FsY0RhdGFBeGlzU2NhbGVzQW5kVGlja3MoXG4gICAgZGF0YTogUHJvY2Vzc0RhdGEsXG4gICAgcGlwZVRyYW5zZm9ybUlucHV0OlxuICAgICAgfCAoKHZhbHVlOiBudW1iZXIsIGlzU2Vjb25kYXJ5OiBib29sZWFuKSA9PiBzdHJpbmcpXG4gICAgICB8IG51bGwsXG4gICAgY29uZmlnOiBDb25maWcsXG4gICAgY2hhcnRTaXppbmdWYWx1ZXM6IEZ1bGxDaGFydFNjYWxlVmFsdWVzLFxuICApOiB7XG4gICAgc2NhbGU6IChpbnB1dDogbnVtYmVyLCBpc1NlY29uZGFyeTogYm9vbGVhbiB8IHVuZGVmaW5lZCkgPT4gbnVtYmVyO1xuICAgIHRpY2tzOiBHZW5lcmljVGlja1tdO1xuICB9IHtcbiAgICBjb25zdCBwaXBlVHJhbnNmb3JtID1cbiAgICAgIHBpcGVUcmFuc2Zvcm1JbnB1dCAhPT0gbnVsbCA/IHBpcGVUcmFuc2Zvcm1JbnB1dCA6ICgpID0+ICcnO1xuICAgIGNvbnN0IHtcbiAgICAgIHByaW1hcnlEYXRhTWluLFxuICAgICAgcHJpbWFyeURhdGFNYXgsXG4gICAgICBzZWNvbmRhcnlEYXRhTWluLFxuICAgICAgc2Vjb25kYXJ5RGF0YU1heCxcbiAgICAgIHNjYWxlRG9tYWluTXVsdGlwbGVGb3JNYXgsXG4gICAgICBzY2FsZURvbWFpbk11bHRpcGxlRm9yTmVnLFxuICAgIH0gPSBjYWxjRGF0YVNjYWxpbmdWYWx1ZXMoZGF0YSwgY29uZmlnKTtcbiAgICBjb25zdCBzdGFydE9mZnNldCA9XG4gICAgICBjaGFydFNpemluZ1ZhbHVlcy5jaGFydERhdGFEaXJlY3Rpb24gPT09ICdob3Jpem9udGFsJ1xuICAgICAgICA/IGNoYXJ0U2l6aW5nVmFsdWVzLnRvdGFsTGVmdE9mZnNldFxuICAgICAgICA6IGNoYXJ0U2l6aW5nVmFsdWVzLnRvdGFsVG9wT2Zmc2V0O1xuICAgIGxldCBtaW5TcGFjaW5nID1cbiAgICAgIChjaGFydFNpemluZ1ZhbHVlcy5jaGFydERhdGFEaXJlY3Rpb24gPT09ICdob3Jpem9udGFsJ1xuICAgICAgICA/IGNoYXJ0U2l6aW5nVmFsdWVzLmhvcml6b250YWxBeGlzTGFiZWxUZXh0U2l6ZVxuICAgICAgICA6IGNoYXJ0U2l6aW5nVmFsdWVzLnZlcnRpY2FsQXhpc0xhYmVsVGV4dFNpemUpICsgU01BTExfUEFERElORztcbiAgICBtaW5TcGFjaW5nID0gbWluU3BhY2luZyAqIChjaGFydFNpemluZ1ZhbHVlcy5mb250U2l6ZSAvIERFRkFVTFRfRk9OVF9TSVpFKTtcbiAgICBjb25zdCBzcGFjaW5nVGlja0NvdW50ID0gTWF0aC5tYXgoXG4gICAgICAyLFxuICAgICAgTWF0aC5mbG9vcihjaGFydFNpemluZ1ZhbHVlcy5zaXplRm9yRGF0YSAvIG1pblNwYWNpbmcpLFxuICAgICk7XG4gICAgY29uc3QgYWN0dWFsVGFyZ2V0VGlja0NvdW50ID0gTWF0aC5taW4oXG4gICAgICBzcGFjaW5nVGlja0NvdW50LFxuICAgICAgY2hhcnRTaXppbmdWYWx1ZXMudGFyZ2V0VGlja0NvdW50LFxuICAgICk7XG5cbiAgICBjb25zdCBoYXNQcmltYXJ5ID0gcHJpbWFyeURhdGFNaW4gIT09IDAgfHwgcHJpbWFyeURhdGFNYXggIT09IDA7XG4gICAgY29uc3QgaGFzU2Vjb25kYXJ5ID0gc2Vjb25kYXJ5RGF0YU1pbiAhPT0gMCB8fCBzZWNvbmRhcnlEYXRhTWF4ICE9PSAwO1xuICAgIGNvbnN0IHNjYWxlUmFuZ2UgPVxuICAgICAgY2hhcnRTaXppbmdWYWx1ZXMuY2hhcnREYXRhRGlyZWN0aW9uID09PSAnaG9yaXpvbnRhbCcgfHxcbiAgICAgIGNvbmZpZy50eXBlID09PSAnZmxvdydcbiAgICAgICAgPyBbMCwgY2hhcnRTaXppbmdWYWx1ZXMuc2l6ZUZvckRhdGFdXG4gICAgICAgIDogW2NoYXJ0U2l6aW5nVmFsdWVzLnNpemVGb3JEYXRhLCAwXTtcbiAgICAvL1RoZXNlICdlZmZlY3RpdmUnIHZhbHVlcyBlbnN1cmUgd2UgaGF2ZSByb29tIGZvciBwb3RlbnRpYWwgc3RhY2tpbmcgb2Ygc2Vjb25kYXJ5IGFuZCBub24tc2Vjb25kYXJ5IHZhbHVlc1xuICAgIGxldCBlZmZlY3RpdmVQcmltYXJ5TWluID0gcHJpbWFyeURhdGFNaW4gKiBzY2FsZURvbWFpbk11bHRpcGxlRm9yTmVnO1xuICAgIGxldCBlZmZlY3RpdmVQcmltYXJ5TWF4ID0gcHJpbWFyeURhdGFNYXggKiBzY2FsZURvbWFpbk11bHRpcGxlRm9yTWF4O1xuXG4gICAgLy9TaW1wbGVyIHBhdGggZm9yIGRhdGEgdy9vIHNlY29uZGFyaWVzXG4gICAgaWYgKCFoYXNTZWNvbmRhcnkpIHtcbiAgICAgIGNvbnN0IHByaW1hcnlZRG9tYWluID0gW2VmZmVjdGl2ZVByaW1hcnlNaW4sIGVmZmVjdGl2ZVByaW1hcnlNYXhdO1xuXG4gICAgICBjb25zdCB5U2NhbGUgPSBzY2FsZUxpbmVhcihwcmltYXJ5WURvbWFpbiwgc2NhbGVSYW5nZSk7XG4gICAgICBjb25zdCB0aWNrczogR2VuZXJpY1RpY2tbXSA9IHlTY2FsZVxuICAgICAgICAudGlja3MoYWN0dWFsVGFyZ2V0VGlja0NvdW50KVxuICAgICAgICAubWFwKHRpY2sgPT4gKHtcbiAgICAgICAgICB2YWx1ZTogeVNjYWxlKHRpY2spICsgc3RhcnRPZmZzZXQsXG4gICAgICAgICAgbGFiZWw6IHBpcGVUcmFuc2Zvcm0odGljaywgZmFsc2UpLFxuICAgICAgICB9KSk7XG4gICAgICBjb25zdCBzY2FsZSA9IChpbnB1dDogbnVtYmVyKTogbnVtYmVyID0+IHtcbiAgICAgICAgcmV0dXJuIHlTY2FsZShpbnB1dCkgKyBzdGFydE9mZnNldDtcbiAgICAgIH07XG4gICAgICByZXR1cm4ge1xuICAgICAgICBzY2FsZSxcbiAgICAgICAgdGlja3MsXG4gICAgICB9O1xuICAgIH1cbiAgICAvL1NpbXBsZXIgcGF0aCBmb3IgZGF0YSB3L28gcHJpbWFyaWVzXG4gICAgaWYgKCFoYXNQcmltYXJ5KSB7XG4gICAgICBjb25zdCBzZWNvbmRhcnlZRG9tYWluID0gW3NlY29uZGFyeURhdGFNaW4sIHNlY29uZGFyeURhdGFNYXhdO1xuXG4gICAgICBjb25zdCB5U2NhbGUgPSBzY2FsZUxpbmVhcihzZWNvbmRhcnlZRG9tYWluLCBzY2FsZVJhbmdlKTtcbiAgICAgIGNvbnN0IHRpY2tzOiBHZW5lcmljVGlja1tdID0geVNjYWxlXG4gICAgICAgIC50aWNrcyhhY3R1YWxUYXJnZXRUaWNrQ291bnQpXG4gICAgICAgIC5tYXAodGljayA9PiAoe1xuICAgICAgICAgIHZhbHVlOiB5U2NhbGUodGljaykgKyBzdGFydE9mZnNldCxcbiAgICAgICAgICBsYWJlbDogcGlwZVRyYW5zZm9ybSh0aWNrLCB0cnVlKSxcbiAgICAgICAgfSkpO1xuICAgICAgY29uc3Qgc2NhbGUgPSAoaW5wdXQ6IG51bWJlcik6IG51bWJlciA9PiB7XG4gICAgICAgIHJldHVybiB5U2NhbGUoaW5wdXQpICsgc3RhcnRPZmZzZXQ7XG4gICAgICB9O1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgc2NhbGUsXG4gICAgICAgIHRpY2tzLFxuICAgICAgfTtcbiAgICB9XG4gICAgbGV0IGVmZmVjdGl2ZVNlY29uZGFyeU1heCA9IDA7XG4gICAgbGV0IGVmZmVjdGl2ZVNlY29uZGFyeU1pbiA9IDA7XG5cbiAgICAvL1RoaXMgYmxvY2sgc2V0cyB0aGUgZWZmZWN0aXZlIG1heCBmb3IgcHJpbWFyeSBhbmQgc2Vjb25kYXJ5XG4gICAgLy9UaGlzIHRvIGVuc3VyZSB0aGF0IHRoZSBlZmZlY3RpdmUgbWF4ZXMgZm9yIGJvdGggZGF0YSBzZXRzIGFyZSBwcm9wZXJseSBzZXQgc28gdGhhdFxuICAgIC8vIDAgd2lsbCBmYWxsIGF0IHRoZSBzYW1lIHBsYWNlIG9uIGJvdGggYW5kIGVhY2ggd2lsbCBoYXZlICdyb29tJyBmb3IgcG90ZW50aWFsIHN0YWNraW5nXG4gICAgaWYgKFxuICAgICAgKHByaW1hcnlEYXRhTWF4IDw9IDAgJiYgc2Vjb25kYXJ5RGF0YU1pbiA+PSAwKSB8fFxuICAgICAgKHByaW1hcnlEYXRhTWluID49IDAgJiYgc2Vjb25kYXJ5RGF0YU1heCA8PSAwKVxuICAgICkge1xuICAgICAgLy9JbiB0aGlzIHNjZW5hcmlvLCBvbmUgc2V0IG9mIGRhdGEgaXMgY29tcGV0ZWx5IHBvc2l0aXZlLCB3aGlsZSB0aGUgb3RoZXIgaXMgY29tcGxldGVseSBuZWdhdGl2ZVxuICAgICAgLy9UaGUgdHdvIGRhdGEgc2V0cyBjYW4gc2NhbGUgY29tcGxldGVseSBpbmRlcGVuZGVudGx5XG4gICAgICAvL1dlICdtaXJyb3InIHRoZSB2YWx1ZXMgb2YgdGhlIHR3byBkYXRhIHNldHMsIHdoaWNoJ2xsIHB1dCB0aGUgMCBheGlzIGluIHRoZSBjZW50ZXIgb2YgdGhlIGRhdGFcbiAgICAgIGlmIChwcmltYXJ5RGF0YU1heCA8PSAwKSB7XG4gICAgICAgIGVmZmVjdGl2ZVByaW1hcnlNYXggPSBNYXRoLmFicyhlZmZlY3RpdmVQcmltYXJ5TWluKTtcbiAgICAgIH1cbiAgICAgIGlmIChwcmltYXJ5RGF0YU1pbiA+PSAwKSB7XG4gICAgICAgIGVmZmVjdGl2ZVByaW1hcnlNaW4gPSAtTWF0aC5hYnMoZWZmZWN0aXZlUHJpbWFyeU1heCk7XG4gICAgICB9XG4gICAgICBpZiAoc2Vjb25kYXJ5RGF0YU1heCA8PSAwKSB7XG4gICAgICAgIGVmZmVjdGl2ZVNlY29uZGFyeU1pbiA9IHNlY29uZGFyeURhdGFNaW47XG4gICAgICAgIGVmZmVjdGl2ZVNlY29uZGFyeU1heCA9IE1hdGguYWJzKHNlY29uZGFyeURhdGFNaW4pO1xuICAgICAgfVxuICAgICAgaWYgKHNlY29uZGFyeURhdGFNaW4gPj0gMCkge1xuICAgICAgICBlZmZlY3RpdmVTZWNvbmRhcnlNYXggPSBzZWNvbmRhcnlEYXRhTWF4O1xuICAgICAgICBlZmZlY3RpdmVTZWNvbmRhcnlNaW4gPSAtc2Vjb25kYXJ5RGF0YU1heDtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKHByaW1hcnlEYXRhTWF4ID4gMCkge1xuICAgICAgaWYgKHByaW1hcnlEYXRhTWluIDwgMCkge1xuICAgICAgICAvL1ByaW1hcnkgZGF0YSBoYXMgcG9zaXRpdmUgYW5kIG5lZ2F0aXZlXG4gICAgICAgIGlmIChzZWNvbmRhcnlEYXRhTWF4ID4gMCkge1xuICAgICAgICAgIC8vU2Vjb25kYXJ5IGRhdGEgaGFzIHBvc2l0aXZlXG4gICAgICAgICAgZWZmZWN0aXZlU2Vjb25kYXJ5TWF4ID0gc2Vjb25kYXJ5RGF0YU1heCAqIHNjYWxlRG9tYWluTXVsdGlwbGVGb3JNYXg7XG4gICAgICAgICAgaWYgKHNlY29uZGFyeURhdGFNaW4gPCAwKSB7XG4gICAgICAgICAgICAvL1NlY29uZGFyeSBkYXRhIGhhcyBuZWdhdGl2ZVxuICAgICAgICAgICAgZWZmZWN0aXZlU2Vjb25kYXJ5TWluID1cbiAgICAgICAgICAgICAgc2Vjb25kYXJ5RGF0YU1pbiAqIHNjYWxlRG9tYWluTXVsdGlwbGVGb3JOZWc7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vU2Vjb25kYXJ5IGRhdGEgaXMgb25seSBwb3NpdGl2ZVxuICAgICAgICAgICAgZWZmZWN0aXZlU2Vjb25kYXJ5TWluID1cbiAgICAgICAgICAgICAgKHNlY29uZGFyeURhdGFNYXggLyBwcmltYXJ5RGF0YU1heCkgKlxuICAgICAgICAgICAgICBwcmltYXJ5RGF0YU1pbiAqXG4gICAgICAgICAgICAgIHNjYWxlRG9tYWluTXVsdGlwbGVGb3JOZWc7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vU2Vjb25kYXJ5IGRhdGEgaGFzIG9ubHkgbmVnYXRpdmVcbiAgICAgICAgICBlZmZlY3RpdmVTZWNvbmRhcnlNaW4gPSBzZWNvbmRhcnlEYXRhTWluICogc2NhbGVEb21haW5NdWx0aXBsZUZvck5lZztcbiAgICAgICAgICBlZmZlY3RpdmVTZWNvbmRhcnlNYXggPVxuICAgICAgICAgICAgKHNlY29uZGFyeURhdGFNaW4gLyBwcmltYXJ5RGF0YU1pbikgKlxuICAgICAgICAgICAgcHJpbWFyeURhdGFNYXggKlxuICAgICAgICAgICAgc2NhbGVEb21haW5NdWx0aXBsZUZvck1heDtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy9QcmltYXJ5IGRhdGEgaXMgb25seSBwb3NpdGl2ZVxuICAgICAgICAvL0R1ZSB0byBlYXJsaWVyIGNoZWNrLCB3ZSBrbm93IHRoYXQgc2Vjb25kYXJ5IGRhdGEgaXMgZWl0aGVyIGFsc28gYWxsLXBvc2l0aXZlLCBvciBwb3NpdGl2ZSBhbmQgbmVnYXRpdmVcbiAgICAgICAgZWZmZWN0aXZlU2Vjb25kYXJ5TWF4ID0gc2Vjb25kYXJ5RGF0YU1heCAqIHNjYWxlRG9tYWluTXVsdGlwbGVGb3JNYXg7XG4gICAgICAgIGVmZmVjdGl2ZVNlY29uZGFyeU1pbiA9IHNlY29uZGFyeURhdGFNaW4gKiBzY2FsZURvbWFpbk11bHRpcGxlRm9yTmVnO1xuICAgICAgICBlZmZlY3RpdmVQcmltYXJ5TWluID1cbiAgICAgICAgICAocHJpbWFyeURhdGFNYXggLyBzZWNvbmRhcnlEYXRhTWF4KSAqXG4gICAgICAgICAgc2Vjb25kYXJ5RGF0YU1pbiAqXG4gICAgICAgICAgc2NhbGVEb21haW5NdWx0aXBsZUZvck5lZztcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgLy9QcmltYXJ5IGRhdGEgaXMgb25seSBuZWdhdGl2ZVxuICAgICAgLy9EdWUgdG8gZWFybGllciBjaGVjaywgd2Uga25vdyB0aGF0IHNlY29uZGFyeSBkYXRhIGlzIGVpdGhlciBhbHNvIGFsbC1uZWdhdGl2ZSwgb3IgcG9zaXRpdmUgYW5kIG5lZ2F0aXZlXG4gICAgICBlZmZlY3RpdmVTZWNvbmRhcnlNYXggPSBzZWNvbmRhcnlEYXRhTWF4ICogc2NhbGVEb21haW5NdWx0aXBsZUZvck1heDtcbiAgICAgIGVmZmVjdGl2ZVNlY29uZGFyeU1pbiA9IHNlY29uZGFyeURhdGFNaW4gKiBzY2FsZURvbWFpbk11bHRpcGxlRm9yTmVnO1xuICAgICAgZWZmZWN0aXZlUHJpbWFyeU1heCA9XG4gICAgICAgIChwcmltYXJ5RGF0YU1pbiAvIHNlY29uZGFyeURhdGFNaW4pICpcbiAgICAgICAgc2Vjb25kYXJ5RGF0YU1heCAqXG4gICAgICAgIHNjYWxlRG9tYWluTXVsdGlwbGVGb3JNYXg7XG4gICAgfVxuICAgIGNvbnN0IHByaW1hcnlZRG9tYWluID0gW2VmZmVjdGl2ZVByaW1hcnlNaW4sIGVmZmVjdGl2ZVByaW1hcnlNYXhdO1xuXG4gICAgY29uc3QgeVNjYWxlID0gc2NhbGVMaW5lYXIocHJpbWFyeVlEb21haW4sIHNjYWxlUmFuZ2UpO1xuXG4gICAgLy9GaWd1cmluZyBvdXQgdGhlIGJlc3QgdGljayBjb3VudCB0byBmaXQgdGhlIHR3byBkYXRhIHNyb3VjZXNcbiAgICBjb25zdCB5U2NhbGVQcmltYXJ5UHJvdG8gPSBzY2FsZUxpbmVhcihwcmltYXJ5WURvbWFpbiwgc2NhbGVSYW5nZSk7XG4gICAgY29uc3QgeVNjYWxlU2Vjb25kYXJ5UHJvdG8gPSBzY2FsZUxpbmVhcihcbiAgICAgIFtlZmZlY3RpdmVTZWNvbmRhcnlNaW4sIGVmZmVjdGl2ZVNlY29uZGFyeU1heF0sXG4gICAgICBzY2FsZVJhbmdlLFxuICAgICk7XG4gICAgY29uc3QgdGlja0NvdW50ID0gTWF0aC5tYXgoXG4gICAgICBhY3R1YWxUYXJnZXRUaWNrQ291bnQsXG4gICAgICB5U2NhbGVQcmltYXJ5UHJvdG8udGlja3MoYWN0dWFsVGFyZ2V0VGlja0NvdW50KS5sZW5ndGgsXG4gICAgICB5U2NhbGVTZWNvbmRhcnlQcm90by50aWNrcyhhY3R1YWxUYXJnZXRUaWNrQ291bnQpLmxlbmd0aCxcbiAgICApO1xuICAgIGNvbnN0IHByaW1hcnlUaWNrcyA9IHlTY2FsZS50aWNrcyh0aWNrQ291bnQpLm1hcCh0aWNrID0+ICh7XG4gICAgICB2YWx1ZTogeVNjYWxlKHRpY2spICsgc3RhcnRPZmZzZXQsXG4gICAgICBsYWJlbDogcGlwZVRyYW5zZm9ybSh0aWNrLCBmYWxzZSksXG4gICAgICByYXdZOiB0aWNrLFxuICAgIH0pKTtcblxuICAgIC8vRmluZGluZyBhIGRvbWFpbiBmb3IgdGhlIHNlY29uZGFyeSBkYXRhIHN1Y2ggdGhhdCBpdCB3aWxsIHJlc3VsdCBpbiByb3VuZCB0aWNrIHZhbHVlcyB3aGVuIG1hdGNoZWQgd2l0aCB0aGUgcHJpbWFyeSB0aWNrc1xuICAgIGNvbnN0IHNlY29uZGFyeVRpY2tzUHJvdG8gPSB5U2NhbGVTZWNvbmRhcnlQcm90b1xuICAgICAgLnRpY2tzKHRpY2tDb3VudClcbiAgICAgIC5tYXAodGljayA9PiAoe1xuICAgICAgICB5OiB5U2NhbGVTZWNvbmRhcnlQcm90byh0aWNrKSxcbiAgICAgICAgcmF3WTogdGljayxcbiAgICAgICAgbGFiZWw6IHBpcGVUcmFuc2Zvcm0odGljaywgdHJ1ZSksXG4gICAgICB9KSk7XG4gICAgY29uc3QgcHJpbWFyeU1pblRpY2sgPSBNYXRoLm1pbiguLi5wcmltYXJ5VGlja3MubWFwKHRpY2sgPT4gdGljay5yYXdZKSk7XG4gICAgY29uc3QgcHJpbWFyeU1heFRpY2sgPSBNYXRoLm1heCguLi5wcmltYXJ5VGlja3MubWFwKHRpY2sgPT4gdGljay5yYXdZKSk7XG4gICAgY29uc3QgcHJpbWFyeURvbWFpbk1heFRpY2tSYXRpbyA9XG4gICAgICBwcmltYXJ5TWF4VGljayAhPT0gMCA/IGVmZmVjdGl2ZVByaW1hcnlNYXggLyBwcmltYXJ5TWF4VGljayA6IDA7XG4gICAgY29uc3QgcHJpbWFyeURvbWFpbk1pblRpY2tSYXRpbyA9XG4gICAgICBwcmltYXJ5TWluVGljayAhPT0gMCA/IGVmZmVjdGl2ZVByaW1hcnlNaW4gLyBwcmltYXJ5TWluVGljayA6IDA7XG5cbiAgICBjb25zdCBwcmltYXJ5R2FwID0gcHJpbWFyeVRpY2tzWzFdLnJhd1kgLSBwcmltYXJ5VGlja3NbMF0ucmF3WTtcbiAgICBjb25zdCB0aWNrc0JlbG93WmVybyA9IHByaW1hcnlNaW5UaWNrIC8gcHJpbWFyeUdhcDtcbiAgICBjb25zdCB0aWNrc0Fib3ZlWmVybyA9IHByaW1hcnlNYXhUaWNrIC8gcHJpbWFyeUdhcDtcblxuICAgIGNvbnN0IHNlY29uZGFyeUdhcCA9XG4gICAgICBzZWNvbmRhcnlUaWNrc1Byb3RvWzFdLnJhd1kgLSBzZWNvbmRhcnlUaWNrc1Byb3RvWzBdLnJhd1k7XG4gICAgbGV0IGNhbGNSYW5nZU11bHQgPSAxO1xuICAgIGNvbnN0IHNlY29uZGFyeURvbWFpbk1pbk11bHQgPVxuICAgICAgdGlja3NCZWxvd1plcm8gKiBzZWNvbmRhcnlHYXAgKiBwcmltYXJ5RG9tYWluTWluVGlja1JhdGlvO1xuICAgIGNvbnN0IHNlY29uZGFyeURvbWFpbk1heE11bHQgPVxuICAgICAgdGlja3NBYm92ZVplcm8gKiBzZWNvbmRhcnlHYXAgKiBwcmltYXJ5RG9tYWluTWF4VGlja1JhdGlvO1xuICAgIC8vRmlyc3QsIHdlIGVuc3VyZSB0aGUgY2FsY1JhbmdlTXVsdCBpcyBiaWcgZW5vdWdoXG4gICAgbGV0IHNpemVVcENvbXBsZXRlID0gZmFsc2U7XG4gICAgd2hpbGUgKCFzaXplVXBDb21wbGV0ZSkge1xuICAgICAgY29uc3QgY2FsY1JhbmdlVG9vU21hbGxGb3JNaW4gPVxuICAgICAgICBzZWNvbmRhcnlEb21haW5NaW5NdWx0ICogY2FsY1JhbmdlTXVsdCA+IGVmZmVjdGl2ZVNlY29uZGFyeU1pbiAmJlxuICAgICAgICBzZWNvbmRhcnlEb21haW5NaW5NdWx0ICE9PSAwO1xuICAgICAgY29uc3QgY2FsY1JhbmdlVG9vU21hbGxGb3JNYXggPVxuICAgICAgICBzZWNvbmRhcnlEb21haW5NYXhNdWx0ICogY2FsY1JhbmdlTXVsdCA8IGVmZmVjdGl2ZVNlY29uZGFyeU1heCAmJlxuICAgICAgICBzZWNvbmRhcnlEb21haW5NYXhNdWx0ICE9PSAwO1xuICAgICAgaWYgKGNhbGNSYW5nZVRvb1NtYWxsRm9yTWluIHx8IGNhbGNSYW5nZVRvb1NtYWxsRm9yTWF4KSB7XG4gICAgICAgIGNhbGNSYW5nZU11bHQgPSBjYWxjUmFuZ2VNdWx0ICogMjtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHNpemVVcENvbXBsZXRlID0gdHJ1ZTtcbiAgICAgIH1cbiAgICB9XG4gICAgLy9UaGVuLCB3ZSBjaGVjayBpZiB3ZSBjYW4gc2NhbGUgZG93biAoZm9yIHRoaXMgb25lLCBib3RoIGNvbmRpdGlvbnMgaGF2ZSB0byBiZSB0cnVlLCBzbyBpdCB3b24ndCB1bmRvIGEgcHJldmlvdXMgc2NhbGUgdXApXG4gICAgbGV0IHNpemVEb3duQ29tcGxldGUgPSBmYWxzZTtcbiAgICB3aGlsZSAoIXNpemVEb3duQ29tcGxldGUpIHtcbiAgICAgIGNvbnN0IGNhbGNSYW5nZVRvb0JpZ0Zvck1pbiA9XG4gICAgICAgIHNlY29uZGFyeURvbWFpbk1pbk11bHQgKiBjYWxjUmFuZ2VNdWx0IDwgZWZmZWN0aXZlU2Vjb25kYXJ5TWluICogMiAmJlxuICAgICAgICBzZWNvbmRhcnlEb21haW5NaW5NdWx0ICE9PSAwO1xuICAgICAgY29uc3QgY2FsY1JhbmdlVG9vQmlnRm9yTWF4ID1cbiAgICAgICAgc2Vjb25kYXJ5RG9tYWluTWF4TXVsdCAqIGNhbGNSYW5nZU11bHQgPiBlZmZlY3RpdmVTZWNvbmRhcnlNYXggKiAyICYmXG4gICAgICAgIHNlY29uZGFyeURvbWFpbk1heE11bHQgIT09IDA7XG4gICAgICBpZiAoY2FsY1JhbmdlVG9vQmlnRm9yTWluICYmIGNhbGNSYW5nZVRvb0JpZ0Zvck1heCkge1xuICAgICAgICBjYWxjUmFuZ2VNdWx0ID0gY2FsY1JhbmdlTXVsdCAvIDI7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzaXplRG93bkNvbXBsZXRlID0gdHJ1ZTtcbiAgICAgIH1cbiAgICB9XG4gICAgbGV0IHNlY29uZGFyeURvbWFpbk1pbiA9IHNlY29uZGFyeURvbWFpbk1pbk11bHQgKiBjYWxjUmFuZ2VNdWx0O1xuICAgIGxldCBzZWNvbmRhcnlEb21haW5NYXggPSBzZWNvbmRhcnlEb21haW5NYXhNdWx0ICogY2FsY1JhbmdlTXVsdDtcbiAgICAvL0lmIHRoZSBkYXRhIGlzIGxvcHNpZGVkIGVub3VnaCwgaXQncyBwb3NzaWJsZSB0aGF0IG9uZSBvZiBwb3NpdGl2ZS9uZWdhdGl2ZSBoYXZlIHZhbHVlcywgYnV0IG5vIHRpY2tzXG4gICAgaWYgKHNlY29uZGFyeURvbWFpbk1pbiA9PT0gMCAmJiBlZmZlY3RpdmVQcmltYXJ5TWluIDwgMCkge1xuICAgICAgY29uc3QgcG9zU2VjUmF0aW8gPSBzZWNvbmRhcnlEb21haW5NYXggLyBlZmZlY3RpdmVQcmltYXJ5TWF4O1xuICAgICAgc2Vjb25kYXJ5RG9tYWluTWluID0gcG9zU2VjUmF0aW8gKiBlZmZlY3RpdmVQcmltYXJ5TWluO1xuICAgIH1cbiAgICBpZiAoc2Vjb25kYXJ5RG9tYWluTWF4ID09PSAwICYmIGVmZmVjdGl2ZVByaW1hcnlNYXggPiAwKSB7XG4gICAgICBjb25zdCBwb3NTZWNSYXRpbyA9IHNlY29uZGFyeURvbWFpbk1pbiAvIGVmZmVjdGl2ZVByaW1hcnlNaW47XG4gICAgICBzZWNvbmRhcnlEb21haW5NYXggPSBwb3NTZWNSYXRpbyAqIGVmZmVjdGl2ZVByaW1hcnlNYXg7XG4gICAgfVxuICAgIGNvbnN0IHlTY2FsZVNlY29uZGFyeSA9IHNjYWxlTGluZWFyKFxuICAgICAgW3NlY29uZGFyeURvbWFpbk1pbiwgc2Vjb25kYXJ5RG9tYWluTWF4XSxcbiAgICAgIHNjYWxlUmFuZ2UsXG4gICAgKTtcblxuICAgIGNvbnN0IHRpY2tzOiBHZW5lcmljVGlja1tdID0gcHJpbWFyeVRpY2tzLm1hcCh0aWNrID0+ICh7XG4gICAgICAuLi50aWNrLFxuICAgICAgc2Vjb25kYXJ5TGFiZWw6IHBpcGVUcmFuc2Zvcm0oXG4gICAgICAgIHlTY2FsZVNlY29uZGFyeS5pbnZlcnQoeVNjYWxlKHRpY2sucmF3WSkpLFxuICAgICAgICB0cnVlLFxuICAgICAgKSxcbiAgICB9KSk7XG5cbiAgICBjb25zdCBzY2FsZSA9IChpbnB1dDogbnVtYmVyLCBpc1NlY29uZGFyeTogYm9vbGVhbiB8IHVuZGVmaW5lZCk6IG51bWJlciA9PiB7XG4gICAgICBpZiAoaXNTZWNvbmRhcnkpIHtcbiAgICAgICAgcmV0dXJuIHlTY2FsZVNlY29uZGFyeShpbnB1dCkgKyBzdGFydE9mZnNldDtcbiAgICAgIH1cbiAgICAgIHJldHVybiB5U2NhbGUoaW5wdXQpICsgc3RhcnRPZmZzZXQ7XG4gICAgfTtcbiAgICByZXR1cm4ge1xuICAgICAgc2NhbGUsXG4gICAgICB0aWNrcyxcbiAgICB9O1xuICB9XG5cbiAgZnVuY3Rpb24gY2FsY0RhdGFTY2FsaW5nVmFsdWVzKGRhdGE6IFByb2Nlc3NEYXRhLCBjb25maWc6IENvbmZpZykge1xuICAgIGNvbnN0IGlzU3RhY2tlZCA9IGlzU3RhY2tlZERhdGEoY29uZmlnKTtcbiAgICBjb25zdCBwcmltYXJ5RG9tYWluVmFsdWVzID0gY2FsY1lTY2FsZURvbWFpblZhbHVlcyhkYXRhLCBpc1N0YWNrZWQsIGZhbHNlKTtcbiAgICBjb25zdCBzZWNvbmRhcnlEb21haW5WYWx1ZXMgPSBjYWxjWVNjYWxlRG9tYWluVmFsdWVzKGRhdGEsIGlzU3RhY2tlZCwgdHJ1ZSk7XG4gICAgY29uc3QgcHJpbWFyeURhdGFNYXggPSBNYXRoLm1heCguLi5wcmltYXJ5RG9tYWluVmFsdWVzLm1hcCh2YWwgPT4gdmFsLm1heCkpO1xuICAgIGNvbnN0IHNlY29uZGFyeURhdGFNYXggPSBNYXRoLm1heChcbiAgICAgIC4uLnNlY29uZGFyeURvbWFpblZhbHVlcy5tYXAodmFsID0+IHZhbC5tYXgpLFxuICAgICk7XG4gICAgY29uc3QgcHJpbWFyeURhdGFNaW4gPSBNYXRoLm1pbiguLi5wcmltYXJ5RG9tYWluVmFsdWVzLm1hcCh2YWwgPT4gdmFsLm1pbikpO1xuICAgIGNvbnN0IHNlY29uZGFyeURhdGFNaW4gPSBNYXRoLm1pbihcbiAgICAgIC4uLnNlY29uZGFyeURvbWFpblZhbHVlcy5tYXAodmFsID0+IHZhbC5taW4pLFxuICAgICk7XG4gICAgbGV0IHNjYWxlRG9tYWluTXVsdGlwbGVGb3JNYXggPSAxO1xuICAgIGxldCBzY2FsZURvbWFpbk11bHRpcGxlRm9yTmVnID0gMTtcblxuICAgIC8vQ2FsY3VsYXRpbmcgaG93IG11Y2ggd2UgbmVlZCB0byBtdWx0aXBsZSB0aGUgZG9tYWluIGJ5IHRvICdmaXQnIGJvdGggYXhlcycgZGF0YVxuICAgIGlmIChpc1N0YWNrZWQpIHtcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcHJpbWFyeURvbWFpblZhbHVlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAvL0NoZWNrIHBvc2l0aXZlIG1heFxuICAgICAgICBjb25zdCBwcmltYXJ5VmFsID0gcHJpbWFyeURvbWFpblZhbHVlc1tpXS5tYXg7XG4gICAgICAgIGNvbnN0IHNlY29uZGFyeVZhbCA9IHNlY29uZGFyeURvbWFpblZhbHVlc1tpXS5tYXg7XG4gICAgICAgIGNvbnN0IHByaW1hcnlSYXRpbyA9XG4gICAgICAgICAgcHJpbWFyeURhdGFNYXggIT09IDAgPyBwcmltYXJ5VmFsIC8gcHJpbWFyeURhdGFNYXggOiAwO1xuICAgICAgICBjb25zdCBzZWNvbmRhcnlSYXRpbyA9XG4gICAgICAgICAgc2Vjb25kYXJ5RGF0YU1heCAhPT0gMCA/IHNlY29uZGFyeVZhbCAvIHNlY29uZGFyeURhdGFNYXggOiAwO1xuICAgICAgICBjb25zdCBtdWx0VmFsID0gcHJpbWFyeVJhdGlvICsgc2Vjb25kYXJ5UmF0aW87XG4gICAgICAgIGlmIChtdWx0VmFsID4gc2NhbGVEb21haW5NdWx0aXBsZUZvck1heCkge1xuICAgICAgICAgIHNjYWxlRG9tYWluTXVsdGlwbGVGb3JNYXggPSBtdWx0VmFsO1xuICAgICAgICB9XG5cbiAgICAgICAgLy9DaGVjayBuZWdhdGl2ZSBtaW5cbiAgICAgICAgY29uc3QgcHJpbWFyeU5lZ1ZhbCA9XG4gICAgICAgICAgcHJpbWFyeURvbWFpblZhbHVlc1tpXS5taW4gPCAwID8gcHJpbWFyeURvbWFpblZhbHVlc1tpXS5taW4gOiAwO1xuICAgICAgICBjb25zdCBzZWNvbmRhcnlOZWdWYWwgPVxuICAgICAgICAgIHNlY29uZGFyeURvbWFpblZhbHVlc1tpXS5taW4gPCAwID8gc2Vjb25kYXJ5RG9tYWluVmFsdWVzW2ldLm1pbiA6IDA7XG4gICAgICAgIGNvbnN0IHByaW1hcnlOZWdSYXRpbyA9XG4gICAgICAgICAgcHJpbWFyeURhdGFNaW4gIT09IDAgPyBwcmltYXJ5TmVnVmFsIC8gcHJpbWFyeURhdGFNaW4gOiAwO1xuICAgICAgICBjb25zdCBzZWNvbmRhcnlOZWdSYXRpbyA9XG4gICAgICAgICAgc2Vjb25kYXJ5RGF0YU1pbiAhPT0gMCA/IHNlY29uZGFyeU5lZ1ZhbCAvIHNlY29uZGFyeURhdGFNaW4gOiAwO1xuICAgICAgICBjb25zdCBuZWdNdWx0VmFsID0gcHJpbWFyeU5lZ1JhdGlvICsgc2Vjb25kYXJ5TmVnUmF0aW87XG4gICAgICAgIGlmIChuZWdNdWx0VmFsID4gc2NhbGVEb21haW5NdWx0aXBsZUZvck5lZykge1xuICAgICAgICAgIHNjYWxlRG9tYWluTXVsdGlwbGVGb3JOZWcgPSBuZWdNdWx0VmFsO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIHByaW1hcnlEYXRhTWluLFxuICAgICAgcHJpbWFyeURhdGFNYXgsXG4gICAgICBzZWNvbmRhcnlEYXRhTWluLFxuICAgICAgc2Vjb25kYXJ5RGF0YU1heCxcbiAgICAgIHNjYWxlRG9tYWluTXVsdGlwbGVGb3JNYXgsXG4gICAgICBzY2FsZURvbWFpbk11bHRpcGxlRm9yTmVnLFxuICAgIH07XG4gIH1cblxuICBmdW5jdGlvbiBjYWxjWVNjYWxlRG9tYWluVmFsdWVzKFxuICAgIGRhdGE6IFByb2Nlc3NEYXRhLFxuICAgIGlzU3RhY2tlZDogYm9vbGVhbixcbiAgICBmb3JTZWNvbmRhcnk6IGJvb2xlYW4sXG4gICk6IHsgbWF4OiBudW1iZXI7IG1pbjogbnVtYmVyIH1bXSB7XG4gICAgaWYgKGRhdGEudHlwZSA9PT0gJ2Zsb3ctcHJvY2Vzc2VkJykge1xuICAgICAgaWYgKGZvclNlY29uZGFyeSkge1xuICAgICAgICAvL0Zsb3cgY2hhcnRzIGRvbid0IHN1cHBvcnQgc2Vjb25kYXJ5IGRhdGFcbiAgICAgICAgcmV0dXJuIFt7IG1pbjogMCwgbWF4OiAwIH1dO1xuICAgICAgfVxuICAgICAgcmV0dXJuIFtcbiAgICAgICAge1xuICAgICAgICAgIG1pbjogMCxcbiAgICAgICAgICBtYXg6IE1hdGgubWF4KC4uLmRhdGEueC5tYXAoeCA9PiB4LnRvdGFsQ291bnQpKSxcbiAgICAgICAgfSxcbiAgICAgIF07XG4gICAgfVxuICAgIGNvbnN0IHBvc3NpYmx5U3RhY2tlZFlzID0gZGF0YS55cy5tYXAoKHksIHlJbmRleCkgPT4ge1xuICAgICAgLy9IYW5kbGUgc3RhY2tpbmdcbiAgICAgIHJldHVybiBpc1N0YWNrZWRcbiAgICAgICAgPyB5LnZhbHVlcy5tYXAoKHZhbCwgeEluZGV4KSA9PiB7XG4gICAgICAgICAgICBsZXQgcHJldlJ1bm5pbmdUb3RhbCA9IDA7XG4gICAgICAgICAgICBmb3IgKGxldCB5SSA9IDA7IHlJIDwgeUluZGV4OyB5SSsrKSB7XG4gICAgICAgICAgICAgIGlmIChjaGVja0lmU2Vjb25kYXJ5KGRhdGEsIHlJLCB4SW5kZXgsIGZhbHNlKSAhPT0gZm9yU2Vjb25kYXJ5KSB7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgY29uc3QgYWRkVmFsID0gZGF0YS55c1t5SV0udmFsdWVzW3hJbmRleF07XG4gICAgICAgICAgICAgIC8vT25seSBzdGFjayB2YWx1ZXMgb2YgdGhlIHNhbWUgc2lnblxuICAgICAgICAgICAgICBpZiAoYWRkVmFsIDwgMCA9PT0gdmFsIDwgMCkge1xuICAgICAgICAgICAgICAgIHByZXZSdW5uaW5nVG90YWwgKz0gYWRkVmFsO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdmFsICsgcHJldlJ1bm5pbmdUb3RhbDtcbiAgICAgICAgICB9KVxuICAgICAgICA6IHkudmFsdWVzO1xuICAgIH0pO1xuICAgIGNvbnN0IHN1cHBZcyA9IGhhc1N1cHBsZW1lbnRhcnlEYXRhKGRhdGEpID8gZGF0YS5zdXBwbGVtZW50YXJ5WXMgOiBudWxsO1xuICAgIGxldCBwb3NzaWJseVN0YWNrZWRTdXBZczogbnVtYmVyW11bXSA9IFtdO1xuICAgIGlmIChzdXBwWXMpIHtcbiAgICAgIHBvc3NpYmx5U3RhY2tlZFN1cFlzID0gc3VwcFlzLm1hcCgoeSwgeUluZGV4KSA9PiB7XG4gICAgICAgIC8vSGFuZGxlIHN0YWNraW5nXG4gICAgICAgIHJldHVybiBpc1N0YWNrZWRcbiAgICAgICAgICA/IHkudmFsdWVzLm1hcCgodmFsLCB4SW5kZXgpID0+IHtcbiAgICAgICAgICAgICAgbGV0IHByZXZSdW5uaW5nVG90YWwgPSAwO1xuICAgICAgICAgICAgICBmb3IgKGxldCB5SSA9IDA7IHlJIDwgeUluZGV4OyB5SSsrKSB7XG4gICAgICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgICAgY2hlY2tJZlNlY29uZGFyeShkYXRhLCB5SSwgeEluZGV4LCB0cnVlKSAhPT0gZm9yU2Vjb25kYXJ5IHx8XG4gICAgICAgICAgICAgICAgICBzdXBwWXNbeUldLnN1cHBsZW1lbnRhbEluZGV4ICE9PSB5LnN1cHBsZW1lbnRhbEluZGV4XG4gICAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY29uc3QgYWRkVmFsID0gc3VwcFlzW3lJXS52YWx1ZXNbeEluZGV4XTtcbiAgICAgICAgICAgICAgICAvL09ubHkgc3RhY2sgdmFsdWVzIG9mIHRoZSBzYW1lIHNpZ25cbiAgICAgICAgICAgICAgICBpZiAoYWRkVmFsIDwgMCA9PT0gdmFsIDwgMCkge1xuICAgICAgICAgICAgICAgICAgcHJldlJ1bm5pbmdUb3RhbCArPSBhZGRWYWw7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIHJldHVybiB2YWwgKyBwcmV2UnVubmluZ1RvdGFsO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICA6IHkudmFsdWVzO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgY29uc3Qgc2NhbGVSYW5nZTogeyBtYXg6IG51bWJlcjsgbWluOiBudW1iZXIgfVtdID0gW107XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBkYXRhLngubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNvbnN0IG1heE5vcm1ZID0gTWF0aC5tYXgoXG4gICAgICAgIC4uLnBvc3NpYmx5U3RhY2tlZFlzLm1hcCgoeSwgeUluZGV4KSA9PiB7XG4gICAgICAgICAgaWYgKGNoZWNrSWZTZWNvbmRhcnkoZGF0YSwgeUluZGV4LCBpLCBmYWxzZSkgIT09IGZvclNlY29uZGFyeSkge1xuICAgICAgICAgICAgcmV0dXJuIDA7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiB5W2ldO1xuICAgICAgICB9KSxcbiAgICAgICk7XG4gICAgICBjb25zdCBtaW5Ob3JtWSA9IE1hdGgubWluKFxuICAgICAgICAuLi5wb3NzaWJseVN0YWNrZWRZcy5tYXAoKHksIHlJbmRleCkgPT4ge1xuICAgICAgICAgIGlmIChjaGVja0lmU2Vjb25kYXJ5KGRhdGEsIHlJbmRleCwgaSwgZmFsc2UpICE9PSBmb3JTZWNvbmRhcnkpIHtcbiAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4geVtpXTtcbiAgICAgICAgfSksXG4gICAgICApO1xuICAgICAgY29uc3QgbWF4U3VwWSA9IHN1cHBZc1xuICAgICAgICA/IE1hdGgubWF4KFxuICAgICAgICAgICAgLi4ucG9zc2libHlTdGFja2VkU3VwWXMubWFwKCh5LCB5SW5kZXgpID0+IHtcbiAgICAgICAgICAgICAgaWYgKGNoZWNrSWZTZWNvbmRhcnkoZGF0YSwgeUluZGV4LCBpLCB0cnVlKSAhPT0gZm9yU2Vjb25kYXJ5KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIDA7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgcmV0dXJuIHlbaV07XG4gICAgICAgICAgICB9KSxcbiAgICAgICAgICApXG4gICAgICAgIDogMDtcbiAgICAgIGNvbnN0IG1pblN1cFkgPSBzdXBwWXNcbiAgICAgICAgPyBNYXRoLm1pbihcbiAgICAgICAgICAgIC4uLnBvc3NpYmx5U3RhY2tlZFN1cFlzLm1hcCgoeSwgeUluZGV4KSA9PiB7XG4gICAgICAgICAgICAgIGlmIChjaGVja0lmU2Vjb25kYXJ5KGRhdGEsIHlJbmRleCwgaSwgdHJ1ZSkgIT09IGZvclNlY29uZGFyeSkge1xuICAgICAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIHJldHVybiB5W2ldO1xuICAgICAgICAgICAgfSksXG4gICAgICAgICAgKVxuICAgICAgICA6IDA7XG4gICAgICBjb25zdCBtYXggPVxuICAgICAgICBtYXhOb3JtWSA+IDAgJiYgbWF4Tm9ybVkgPiBtYXhTdXBZXG4gICAgICAgICAgPyBtYXhOb3JtWVxuICAgICAgICAgIDogbWF4U3VwWSA+IDBcbiAgICAgICAgICA/IG1heFN1cFlcbiAgICAgICAgICA6IDA7XG4gICAgICBjb25zdCBtaW4gPVxuICAgICAgICBtaW5Ob3JtWSA8IDAgJiYgbWluTm9ybVkgPCBtaW5TdXBZXG4gICAgICAgICAgPyBtaW5Ob3JtWVxuICAgICAgICAgIDogbWluU3VwWSA8IDBcbiAgICAgICAgICA/IG1pblN1cFlcbiAgICAgICAgICA6IDA7XG4gICAgICBzY2FsZVJhbmdlLnB1c2goeyBtYXgsIG1pbiB9KTtcbiAgICB9XG4gICAgcmV0dXJuIHNjYWxlUmFuZ2U7XG4gIH1cblxuICBmdW5jdGlvbiBjYWxjdWxhdGVCYXJQb3NpdGlvbihcbiAgICBkYXRhOiBOb25GbG93RGF0YSxcbiAgICBjb25maWc6IENvbmZpZyxcbiAgICBjaGFydFNpemluZ1ZhbHVlczogRnVsbENoYXJ0U2NhbGVWYWx1ZXMsXG4gICAgYnVja2V0TnVtOiBudW1iZXIsXG4gICAgY2x1c3Rlck51bTogbnVtYmVyLFxuICApOiBudW1iZXIge1xuICAgIGNvbnN0IG9mZnNldCA9XG4gICAgICBjaGFydFNpemluZ1ZhbHVlcy5jaGFydERhdGFEaXJlY3Rpb24gPT09ICd2ZXJ0aWNhbCdcbiAgICAgICAgPyBjaGFydFNpemluZ1ZhbHVlcy50b3RhbExlZnRPZmZzZXRcbiAgICAgICAgOiBjaGFydFNpemluZ1ZhbHVlcy50b3RhbFRvcE9mZnNldDtcbiAgICBjb25zdCBjbHVzdGVyT2Zmc2V0ID1cbiAgICAgIGNsdXN0ZXJOdW0gKlxuICAgICAgKGNoYXJ0U2l6aW5nVmFsdWVzLmJhclNpemUgKyBjaGFydFNpemluZ1ZhbHVlcy5iYXJDbHVzdGVyR2FwKTtcbiAgICBjb25zdCBjdW11bGF0aXZlQnVja2V0R2FwID0gZ2V0VG90YWxQcmVCdWNrZXRHYXAoXG4gICAgICBkYXRhLFxuICAgICAgY29uZmlnLFxuICAgICAgY2hhcnRTaXppbmdWYWx1ZXMsXG4gICAgICBidWNrZXROdW0sXG4gICAgKTtcbiAgICByZXR1cm4gb2Zmc2V0ICsgY3VtdWxhdGl2ZUJ1Y2tldEdhcCArIGNsdXN0ZXJPZmZzZXQ7XG4gIH1cblxuICBmdW5jdGlvbiBjYWxjdWxhdGVIb3Jpem9udGFsQmFyUGF0aChcbiAgICBsZWZ0U2lkZVJvdW5kOiBib29sZWFuLFxuICAgIHJpZ2h0U2lkZVJvdW5kOiBib29sZWFuLFxuICAgIHhWYWx1ZTogbnVtYmVyLFxuICAgIHlWYWx1ZTogbnVtYmVyLFxuICAgIGhvclI6IG51bWJlcixcbiAgICB2ZXJSOiBudW1iZXIsXG4gICAgaGVpZ2h0OiBudW1iZXIsXG4gICAgd2lkdGg6IG51bWJlcixcbiAgKTogc3RyaW5nIHtcbiAgICBpZiAobGVmdFNpZGVSb3VuZCAmJiByaWdodFNpZGVSb3VuZCkge1xuICAgICAgLy9Cb3RoLXNpZGVzIHJvdW5kaW5nIHZhcmlhdGlvblxuICAgICAgY29uc3QgcGF0aEQgPSBgXG4gICAgICAgIE0gJHt4VmFsdWUgKyBob3JSfSwke3lWYWx1ZX1cbiAgICAgICAgaCAke3dpZHRoIC0gaG9yUiAqIDJ9XG4gICAgICAgIHEke2hvclJ9LDAgJHtob3JSfSwke3ZlclJ9XG4gICAgICAgIHYgJHtoZWlnaHQgLSB2ZXJSICogMn1cbiAgICAgICAgcTAsJHt2ZXJSfSAtJHtob3JSfSwke3ZlclJ9XG4gICAgICAgIGggJHstKHdpZHRoIC0gaG9yUiAqIDIpfVxuICAgICAgICBxLSR7aG9yUn0sMCAtJHtob3JSfSwtJHt2ZXJSfVxuICAgICAgICB2IC0ke2hlaWdodCAtIHZlclIgKiAyfVxuICAgICAgICBxMCwtJHt2ZXJSfSAke2hvclJ9LC0ke3ZlclJ9XG4gICAgICAgIFpcbiAgICAgIGA7XG4gICAgICByZXR1cm4gcGF0aEQ7XG4gICAgfVxuICAgIGlmIChsZWZ0U2lkZVJvdW5kKSB7XG4gICAgICAvL0xlZnQtc2lkZSByb3VuZGluZyB2YXJpYXRpb25cbiAgICAgIGNvbnN0IHBhdGhEID0gYFxuICAgICAgICBNICR7eFZhbHVlICsgaG9yUn0sJHt5VmFsdWV9XG4gICAgICAgIGggJHt3aWR0aCAtIGhvclJ9XG4gICAgICAgIHYgJHtoZWlnaHR9XG4gICAgICAgIGggJHstKHdpZHRoIC0gaG9yUil9XG4gICAgICAgIHEtJHtob3JSfSwwIC0ke2hvclJ9LC0ke3ZlclJ9XG4gICAgICAgIHYgLSR7aGVpZ2h0IC0gdmVyUiAqIDJ9XG4gICAgICAgIHEwLC0ke3ZlclJ9ICR7aG9yUn0sLSR7dmVyUn1cbiAgICAgICAgWlxuICAgICAgYDtcbiAgICAgIHJldHVybiBwYXRoRDtcbiAgICB9XG4gICAgaWYgKHJpZ2h0U2lkZVJvdW5kKSB7XG4gICAgICAvL1JpZ2h0LXNpZGUgcm91bmRpbmcgdmFyaWF0aW9uXG4gICAgICBjb25zdCBwYXRoRCA9IGBcbiAgICAgICAgTSAke3hWYWx1ZX0sJHt5VmFsdWV9XG4gICAgICAgIGggJHt3aWR0aCAtIGhvclJ9XG4gICAgICAgIHEke2hvclJ9LDAgJHtob3JSfSwke3ZlclJ9XG4gICAgICAgIHYgJHtoZWlnaHQgLSB2ZXJSICogMn1cbiAgICAgICAgcTAsJHt2ZXJSfSAtJHtob3JSfSwke3ZlclJ9XG4gICAgICAgIGggJHstKHdpZHRoIC0gaG9yUil9XG4gICAgICAgIFpcbiAgICAgIGA7XG4gICAgICByZXR1cm4gcGF0aEQ7XG4gICAgfVxuICAgIC8vTm8tcm91bmRpbmcgdmFyaWF0aW9uXG4gICAgY29uc3QgcGF0aEQgPSBgXG4gICAgICBNICR7eFZhbHVlfSwke3lWYWx1ZX1cbiAgICAgIGggJHt3aWR0aH1cbiAgICAgIHYgJHtoZWlnaHR9XG4gICAgICBoICR7LXdpZHRofVxuICAgICAgdiAtJHtoZWlnaHR9XG4gICAgICBaXG4gICAgYDtcbiAgICByZXR1cm4gcGF0aEQ7XG4gIH1cblxuICBmdW5jdGlvbiBnZXRCdWNrZXRBbmRDbHVzdGVyTnVtRm9ySG92ZXIoXG4gICAgcG9zOiBudW1iZXIsXG4gICAgY2hhcnRTaXppbmdWYWx1ZXM6IEZ1bGxDaGFydFNjYWxlVmFsdWVzLFxuICAgIGRhdGE6IE5vbkZsb3dEYXRhLFxuICAgIGNvbmZpZzogQ29uZmlnLFxuICAgIGJ1Y2tldENvdW50OiBudW1iZXIsXG4gICk6IHtcbiAgICBidWNrZXROdW06IG51bWJlcjtcbiAgICBjbHVzdGVyTnVtOiBudW1iZXI7XG4gICAgY2x1c3Rlck5vcm1Db3VudDogbnVtYmVyO1xuICAgIGNsdXN0ZXJOdW1UeXBlOiAnbm9ybScgfCAnc3VwcCc7XG4gIH0gfCBudWxsIHtcbiAgICBsZXQgYnVja2V0TGVld2F5ID0gY2hhcnRTaXppbmdWYWx1ZXMuYnVja2V0R2FwIC8gNDtcbiAgICAvL2lmIHRoZXJlJ3Mgb25seSAxIGRhdGEgcG9pbnQsIHVzZSB0aGUgb3V0ZXJHYXAgYXMgbGVld2F5IGluc3RlYWRcbiAgICBpZiAoZGF0YS54Lmxlbmd0aCA9PT0gMSkge1xuICAgICAgYnVja2V0TGVld2F5ID0gY2hhcnRTaXppbmdWYWx1ZXMub3V0ZXJHYXAgLyA0O1xuICAgIH1cbiAgICBjb25zdCBiYXJMZWV3YXkgPSBjaGFydFNpemluZ1ZhbHVlcy5iYXJDbHVzdGVyR2FwIC8gMjtcblxuICAgIGNvbnN0IG9mZnNldCA9XG4gICAgICBjaGFydFNpemluZ1ZhbHVlcy5jaGFydERhdGFEaXJlY3Rpb24gPT09ICd2ZXJ0aWNhbCdcbiAgICAgICAgPyBjaGFydFNpemluZ1ZhbHVlcy50b3RhbExlZnRPZmZzZXRcbiAgICAgICAgOiBjaGFydFNpemluZ1ZhbHVlcy50b3RhbFRvcE9mZnNldDtcbiAgICBjb25zdCByZWxhdGl2ZVBvcyA9IHBvcyAtIG9mZnNldDtcbiAgICBsZXQgYnVja2V0TnVtID0gLTE7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBidWNrZXRDb3VudDsgaSsrKSB7XG4gICAgICBjb25zdCBidWNrZXRTdGFydFBvcyA9IGdldFRvdGFsUHJlQnVja2V0R2FwKFxuICAgICAgICBkYXRhLFxuICAgICAgICBjb25maWcsXG4gICAgICAgIGNoYXJ0U2l6aW5nVmFsdWVzLFxuICAgICAgICBpLFxuICAgICAgKTtcbiAgICAgIGlmIChcbiAgICAgICAgYnVja2V0U3RhcnRQb3MgLSBidWNrZXRMZWV3YXkgPCByZWxhdGl2ZVBvcyAmJlxuICAgICAgICBidWNrZXRTdGFydFBvcyArXG4gICAgICAgICAgZ2V0QnVja2V0U2l6ZShkYXRhLCBjb25maWcsIGNoYXJ0U2l6aW5nVmFsdWVzKSArXG4gICAgICAgICAgYnVja2V0TGVld2F5ID5cbiAgICAgICAgICByZWxhdGl2ZVBvc1xuICAgICAgKSB7XG4gICAgICAgIGJ1Y2tldE51bSA9IGk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cbiAgICBpZiAoYnVja2V0TnVtID09PSAtMSkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIGlmICghaXNDbHVzdGVyZWREYXRhKGRhdGEsIGNvbmZpZywgdHJ1ZSkpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGJ1Y2tldE51bSxcbiAgICAgICAgY2x1c3Rlck51bTogMCxcbiAgICAgICAgY2x1c3Rlck5vcm1Db3VudDogMSxcbiAgICAgICAgY2x1c3Rlck51bVR5cGU6ICdub3JtJyxcbiAgICAgIH07XG4gICAgfVxuXG4gICAgY29uc3QgcmVsYXRpdmVCdWNrZXRQb3MgPVxuICAgICAgcmVsYXRpdmVQb3MgLVxuICAgICAgZ2V0VG90YWxQcmVCdWNrZXRHYXAoZGF0YSwgY29uZmlnLCBjaGFydFNpemluZ1ZhbHVlcywgYnVja2V0TnVtKTtcbiAgICBjb25zdCBjbHVzdGVyQ291bnQgPSBnZXRDbHVzdGVySW5mb0ZvckJ1Y2tldChkYXRhLCBjb25maWcpO1xuICAgIGxldCBjbHVzdGVyTnVtID0gLTE7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjbHVzdGVyQ291bnQudG90YWw7IGkrKykge1xuICAgICAgY29uc3QgYmFyU3RhcnRQb3MgPVxuICAgICAgICAoY2hhcnRTaXppbmdWYWx1ZXMuYmFyU2l6ZSArIGNoYXJ0U2l6aW5nVmFsdWVzLmJhckNsdXN0ZXJHYXApICogaTtcbiAgICAgIGlmIChcbiAgICAgICAgYmFyU3RhcnRQb3MgLSBiYXJMZWV3YXkgPCByZWxhdGl2ZUJ1Y2tldFBvcyAmJlxuICAgICAgICBiYXJTdGFydFBvcyArIGNoYXJ0U2l6aW5nVmFsdWVzLmJhclNpemUgKyBiYXJMZWV3YXkgPiByZWxhdGl2ZUJ1Y2tldFBvc1xuICAgICAgKSB7XG4gICAgICAgIGNsdXN0ZXJOdW0gPSBpO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKGNsdXN0ZXJOdW0gPT09IC0xKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgbGV0IGNsdXN0ZXJOdW1UeXBlOiAnbm9ybScgfCAnc3VwcCcgPSAnbm9ybSc7XG4gICAgaWYgKGNsdXN0ZXJOdW0gPj0gY2x1c3RlckNvdW50Lm5vcm1Db3VudCkge1xuICAgICAgY2x1c3Rlck51bVR5cGUgPSAnc3VwcCc7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIGJ1Y2tldE51bSxcbiAgICAgIGNsdXN0ZXJOdW0sXG4gICAgICBjbHVzdGVyTm9ybUNvdW50OiBjbHVzdGVyQ291bnQubm9ybUNvdW50LFxuICAgICAgY2x1c3Rlck51bVR5cGUsXG4gICAgfTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGZpbmROZWFyZXN0SW5kZXhXaXRoU2Vjb25kYXJ5KFxuICAgIHlJbmZvOiB7IHZhbHVlOiBudW1iZXI7IGlzU2Vjb25kYXJ5OiBib29sZWFuIH1bXSxcbiAgICB5UG9zOiBudW1iZXIsXG4gICAgc2NhbGU6IChpbnB1dDogbnVtYmVyLCBpc1NlY29uZGFyeTogYm9vbGVhbiB8IHVuZGVmaW5lZCkgPT4gbnVtYmVyLFxuICApIHtcbiAgICBsZXQgZm91bmRJbmRleCA9IDA7XG4gICAgbGV0IGN1cnJNaW5EaXN0YW5jZSA9IE1hdGguYWJzKFxuICAgICAgc2NhbGUoeUluZm9bMF0udmFsdWUsIHlJbmZvWzBdLmlzU2Vjb25kYXJ5KSAtIHlQb3MsXG4gICAgKTtcbiAgICBmb3IgKGxldCBpID0gMTsgaSA8IHlJbmZvLmxlbmd0aDsgaSsrKSB7XG4gICAgICBjb25zdCBuZXdEaXN0YW5jZSA9IE1hdGguYWJzKFxuICAgICAgICBzY2FsZSh5SW5mb1tpXS52YWx1ZSwgeUluZm9baV0uaXNTZWNvbmRhcnkpIC0geVBvcyxcbiAgICAgICk7XG4gICAgICBpZiAobmV3RGlzdGFuY2UgPCBjdXJyTWluRGlzdGFuY2UpIHtcbiAgICAgICAgZm91bmRJbmRleCA9IGk7XG4gICAgICAgIGN1cnJNaW5EaXN0YW5jZSA9IG5ld0Rpc3RhbmNlO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZm91bmRJbmRleDtcbiAgfVxuXG4gIGZ1bmN0aW9uIGdldEJhcllJbmZvKFxuICAgIGRhdGE6IE5vbkZsb3dEYXRhLFxuICAgIGNvbmZpZzogQ29uZmlnLFxuICAgIHlJbmRleDogbnVtYmVyLFxuICAgIHhJbmRleDogbnVtYmVyLFxuICAgIHNjYWxlOiAoaW5wdXQ6IG51bWJlciwgaXNTZWNvbmRhcnk6IGJvb2xlYW4gfCB1bmRlZmluZWQpID0+IG51bWJlcixcbiAgICBpc1N1cHBsZW1lbnRhcnk6IGJvb2xlYW4gPSBmYWxzZSxcbiAgKTogeyB5VmFsdWU6IG51bWJlcjsgaGVpZ2h0OiBudW1iZXIgfSB7XG4gICAgY29uc3QgaXNTdGFja2VkID0gaXNTdGFja2VkRGF0YShjb25maWcpO1xuICAgIGNvbnN0IG1pbmltdW1TaXplID0gZ2V0TWluaW11bURhdGFFbGVtZW50U2l6ZShjb25maWcpO1xuICAgIGNvbnN0IHplcm9WYWwgPSBzY2FsZSgwLCB0cnVlKTtcbiAgICBjb25zdCB5RGF0YSA9IGdldE1haW5PclN1cHBZKGRhdGEsIHlJbmRleCwgaXNTdXBwbGVtZW50YXJ5KTtcbiAgICBjb25zdCBzY2FsZVZhbHVlID0gc2NhbGUoXG4gICAgICB5RGF0YS52YWx1ZXNbeEluZGV4XSxcbiAgICAgIGNoZWNrSWZTZWNvbmRhcnkoZGF0YSwgeUluZGV4LCB4SW5kZXgsIGlzU3VwcGxlbWVudGFyeSksXG4gICAgKTtcbiAgICBpZiAoc2NhbGVWYWx1ZSA+IHplcm9WYWwpIHtcbiAgICAgIGxldCBwcmV2QmFySGVpZ2h0cyA9IDA7XG4gICAgICBpZiAoaXNTdGFja2VkKSB7XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgeUluZGV4OyBpKyspIHtcbiAgICAgICAgICBjb25zdCBjaGVja0RhdGEgPSBnZXRNYWluT3JTdXBwWShkYXRhLCBpLCBpc1N1cHBsZW1lbnRhcnkpO1xuICAgICAgICAgIC8vQm90aCB5RGF0YSBhbmQgY2hlY2tEYXRhIGFyZSBkZWZpbml0ZWx5IFN1cHBsZW1lbnRhcnlEYXRhWXMgaWYgaXNTdXBwbGVtZW50YXJ5IGlzIHRydWUsIGJ1dCB0aGV5IGRvbid0IHJlYWxpemUgaXRcbiAgICAgICAgICBpZiAoXG4gICAgICAgICAgICBpc1N1cHBsZW1lbnRhcnkgJiZcbiAgICAgICAgICAgICdzdXBwbGVtZW50YWxJbmRleCcgaW4geURhdGEgJiZcbiAgICAgICAgICAgICdzdXBwbGVtZW50YWxJbmRleCcgaW4gY2hlY2tEYXRhXG4gICAgICAgICAgKSB7XG4gICAgICAgICAgICBpZiAoeURhdGEuc3VwcGxlbWVudGFsSW5kZXggIT09IGNoZWNrRGF0YS5zdXBwbGVtZW50YWxJbmRleCkge1xuICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgY29uc3QgY2hlY2tWYWx1ZSA9IHNjYWxlKFxuICAgICAgICAgICAgY2hlY2tEYXRhLnZhbHVlc1t4SW5kZXhdLFxuICAgICAgICAgICAgY2hlY2tJZlNlY29uZGFyeShkYXRhLCBpLCB4SW5kZXgsIGlzU3VwcGxlbWVudGFyeSksXG4gICAgICAgICAgKTtcbiAgICAgICAgICAvL1NraXAgcG9zaXRpdmUgdmFsdWVzXG4gICAgICAgICAgaWYgKGNoZWNrVmFsdWUgPCB6ZXJvVmFsKSB7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcHJldkJhckhlaWdodHMgKz0gYXBwbHlNaW5pbXVtRGF0YUVsZW1lbnRTaXplKFxuICAgICAgICAgICAgY2hlY2tWYWx1ZSAtIHplcm9WYWwsXG4gICAgICAgICAgICBjaGVja0RhdGEudmFsdWVzW3hJbmRleF0sXG4gICAgICAgICAgICBtaW5pbXVtU2l6ZSxcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBjb25zdCB5VmFsdWUgPSB6ZXJvVmFsICsgcHJldkJhckhlaWdodHM7XG4gICAgICBjb25zdCBoZWlnaHQgPSBhcHBseU1pbmltdW1EYXRhRWxlbWVudFNpemUoXG4gICAgICAgIHNjYWxlVmFsdWUgLSB6ZXJvVmFsLFxuICAgICAgICB5RGF0YS52YWx1ZXNbeEluZGV4XSxcbiAgICAgICAgbWluaW11bVNpemUsXG4gICAgICApO1xuICAgICAgcmV0dXJuIHsgeVZhbHVlLCBoZWlnaHQgfTtcbiAgICB9XG4gICAgbGV0IHByZXZCYXJIZWlnaHRzID0gMDtcbiAgICBpZiAoaXNTdGFja2VkKSB7XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHlJbmRleDsgaSsrKSB7XG4gICAgICAgIGNvbnN0IGNoZWNrRGF0YSA9IGdldE1haW5PclN1cHBZKGRhdGEsIGksIGlzU3VwcGxlbWVudGFyeSk7XG4gICAgICAgIC8vQm90aCB5RGF0YSBhbmQgY2hlY2tEYXRhIGFyZSBkZWZpbml0ZWx5IFN1cHBsZW1lbnRhcnlEYXRhWXMgaWYgaXNTdXBwbGVtZW50YXJ5IGlzIHRydWUsIGJ1dCB0aGV5IGRvbid0IHJlYWxpemUgaXRcbiAgICAgICAgaWYgKFxuICAgICAgICAgIGlzU3VwcGxlbWVudGFyeSAmJlxuICAgICAgICAgICdzdXBwbGVtZW50YWxJbmRleCcgaW4geURhdGEgJiZcbiAgICAgICAgICAnc3VwcGxlbWVudGFsSW5kZXgnIGluIGNoZWNrRGF0YVxuICAgICAgICApIHtcbiAgICAgICAgICBpZiAoeURhdGEuc3VwcGxlbWVudGFsSW5kZXggIT09IGNoZWNrRGF0YS5zdXBwbGVtZW50YWxJbmRleCkge1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGNoZWNrVmFsdWUgPSBzY2FsZShcbiAgICAgICAgICBjaGVja0RhdGEudmFsdWVzW3hJbmRleF0sXG4gICAgICAgICAgY2hlY2tJZlNlY29uZGFyeShkYXRhLCBpLCB4SW5kZXgsIGlzU3VwcGxlbWVudGFyeSksXG4gICAgICAgICk7XG4gICAgICAgIC8vU2tpcCBuZWdhdGl2ZSB2YWx1ZXNcbiAgICAgICAgaWYgKGNoZWNrVmFsdWUgPiB6ZXJvVmFsKSB7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgcHJldkJhckhlaWdodHMgKz0gYXBwbHlNaW5pbXVtRGF0YUVsZW1lbnRTaXplKFxuICAgICAgICAgIHplcm9WYWwgLSBjaGVja1ZhbHVlLFxuICAgICAgICAgIGNoZWNrRGF0YS52YWx1ZXNbeEluZGV4XSxcbiAgICAgICAgICBtaW5pbXVtU2l6ZSxcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9XG4gICAgY29uc3QgaGVpZ2h0ID0gYXBwbHlNaW5pbXVtRGF0YUVsZW1lbnRTaXplKFxuICAgICAgemVyb1ZhbCAtIHNjYWxlVmFsdWUsXG4gICAgICB5RGF0YS52YWx1ZXNbeEluZGV4XSxcbiAgICAgIG1pbmltdW1TaXplLFxuICAgICk7XG4gICAgY29uc3QgeVZhbHVlID0gemVyb1ZhbCAtIGhlaWdodCAtIHByZXZCYXJIZWlnaHRzO1xuICAgIHJldHVybiB7IHlWYWx1ZSwgaGVpZ2h0IH07XG4gIH1cblxuICBmdW5jdGlvbiBnZXRTdXBwQmFyWUluZm9WaWFZSW5kZXgoXG4gICAgZGF0YTogTm9uRmxvd0RhdGEsXG4gICAgY29uZmlnOiBDb25maWcsXG4gICAgeUluZGV4OiBudW1iZXIsXG4gICAgc3VwcEluZGV4OiBudW1iZXIsXG4gICAgeEluZGV4OiBudW1iZXIsXG4gICAgc2NhbGU6IChpbnB1dDogbnVtYmVyLCBpc1NlY29uZGFyeTogYm9vbGVhbiB8IHVuZGVmaW5lZCkgPT4gbnVtYmVyLFxuICApOiB7IHlWYWx1ZTogbnVtYmVyOyBoZWlnaHQ6IG51bWJlciB9IHtcbiAgICBpZiAoIWhhc1N1cHBsZW1lbnRhcnlEYXRhKGRhdGEpKSB7XG4gICAgICByZXR1cm4geyB5VmFsdWU6IDAsIGhlaWdodDogMCB9O1xuICAgIH1cbiAgICBjb25zdCBzdXBwWXMgPSBkYXRhLnN1cHBsZW1lbnRhcnlZcztcbiAgICAvLyBGaW5kIHN1cHBsZW1lbnRhcnkgYmFycyB3aXRoIHRoZSBnaXZlbiBzdXBwbGVtZW50YWxJbmRleFxuICAgIGNvbnN0IGdyb3VwU3VwcHMgPSBzdXBwWXMuZmlsdGVyKHMgPT4gcy5zdXBwbGVtZW50YWxJbmRleCA9PT0gc3VwcEluZGV4KTtcbiAgICAvLyB5SW5kZXggcmVmZXJzIHRvIHdoaWNoIFkgc2VyaWVzICh3aXRoaW4gdGhlIHN1cHBsZW1lbnRhbCBncm91cCkgd2UncmUgbG9va2luZyBhdFxuICAgIGlmICh5SW5kZXggPj0gMCAmJiB5SW5kZXggPCBncm91cFN1cHBzLmxlbmd0aCkge1xuICAgICAgLy8gRmluZCB0aGlzIHN1cHAgaW4gdGhlIG9yaWdpbmFsIGFycmF5XG4gICAgICBjb25zdCBzdXBwSW5PcmlnaW5hbEFycmF5ID0gc3VwcFlzLmluZGV4T2YoZ3JvdXBTdXBwc1t5SW5kZXhdKTtcbiAgICAgIHJldHVybiBnZXRCYXJZSW5mbyhcbiAgICAgICAgZGF0YSxcbiAgICAgICAgY29uZmlnLFxuICAgICAgICBzdXBwSW5PcmlnaW5hbEFycmF5LFxuICAgICAgICB4SW5kZXgsXG4gICAgICAgIHNjYWxlLFxuICAgICAgICB0cnVlLFxuICAgICAgKTtcbiAgICB9XG4gICAgcmV0dXJuIHsgeVZhbHVlOiAwLCBoZWlnaHQ6IDAgfTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGdldE1haW5PclN1cHBZKFxuICAgIGRhdGE6IE5vbkZsb3dEYXRhLFxuICAgIHlJbmRleDogbnVtYmVyLFxuICAgIGlzU3VwcGxlbWVudGFyeTogYm9vbGVhbixcbiAgKTogRGF0YVkgfCBTdXBwbGVtZW50YXJ5RGF0YVkge1xuICAgIGlmIChoYXNTdXBwbGVtZW50YXJ5RGF0YShkYXRhKSAmJiBpc1N1cHBsZW1lbnRhcnkpIHtcbiAgICAgIHJldHVybiBkYXRhLnN1cHBsZW1lbnRhcnlZc1t5SW5kZXhdO1xuICAgIH1cbiAgICByZXR1cm4gZGF0YS55c1t5SW5kZXhdO1xuICB9XG5cbiAgZnVuY3Rpb24gZ2V0QmFyWEluZm8oXG4gICAgZGF0YTogTm9uRmxvd0RhdGEsXG4gICAgY29uZmlnOiBDb25maWcsXG4gICAgeUluZGV4OiBudW1iZXIsXG4gICAgeEluZGV4OiBudW1iZXIsXG4gICAgc2NhbGU6IChpbnB1dDogbnVtYmVyLCBpc1NlY29uZGFyeTogYm9vbGVhbiB8IHVuZGVmaW5lZCkgPT4gbnVtYmVyLFxuICAgIGlzU3VwcGxlbWVudGFyeTogYm9vbGVhbiA9IGZhbHNlLFxuICApOiB7IHhWYWx1ZTogbnVtYmVyOyB3aWR0aDogbnVtYmVyIH0ge1xuICAgIGNvbnN0IGlzU3RhY2tlZCA9IGlzU3RhY2tlZERhdGEoY29uZmlnKTtcbiAgICBjb25zdCBtaW5pbXVtU2l6ZSA9IGdldE1pbmltdW1EYXRhRWxlbWVudFNpemUoY29uZmlnKTtcbiAgICBjb25zdCB6ZXJvVmFsID0gc2NhbGUoMCwgdHJ1ZSk7XG4gICAgY29uc3QgeURhdGEgPSBnZXRNYWluT3JTdXBwWShkYXRhLCB5SW5kZXgsIGlzU3VwcGxlbWVudGFyeSk7XG4gICAgY29uc3Qgc2NhbGVWYWx1ZSA9IHNjYWxlKFxuICAgICAgeURhdGEudmFsdWVzW3hJbmRleF0sXG4gICAgICBjaGVja0lmU2Vjb25kYXJ5KGRhdGEsIHlJbmRleCwgeEluZGV4LCBpc1N1cHBsZW1lbnRhcnkpLFxuICAgICk7XG4gICAgaWYgKHNjYWxlVmFsdWUgPCB6ZXJvVmFsKSB7XG4gICAgICBsZXQgcHJldkJhcldpZHRocyA9IDA7XG4gICAgICBpZiAoaXNTdGFja2VkKSB7XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgeUluZGV4OyBpKyspIHtcbiAgICAgICAgICBjb25zdCBjaGVja0RhdGEgPSBnZXRNYWluT3JTdXBwWShkYXRhLCBpLCBpc1N1cHBsZW1lbnRhcnkpO1xuICAgICAgICAgIC8vQm90aCB5RGF0YSBhbmQgY2hlY2tEYXRhIGFyZSBkZWZpbml0ZWx5IFN1cHBsZW1lbnRhcnlEYXRhWXMgaWYgaXNTdXBwbGVtZW50YXJ5IGlzIHRydWUsIGJ1dCB0aGV5IGRvbid0IHJlYWxpemUgaXRcbiAgICAgICAgICBpZiAoXG4gICAgICAgICAgICBpc1N1cHBsZW1lbnRhcnkgJiZcbiAgICAgICAgICAgICdzdXBwbGVtZW50YWxJbmRleCcgaW4geURhdGEgJiZcbiAgICAgICAgICAgICdzdXBwbGVtZW50YWxJbmRleCcgaW4gY2hlY2tEYXRhXG4gICAgICAgICAgKSB7XG4gICAgICAgICAgICBpZiAoeURhdGEuc3VwcGxlbWVudGFsSW5kZXggIT09IGNoZWNrRGF0YS5zdXBwbGVtZW50YWxJbmRleCkge1xuICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgY29uc3QgY2hlY2tWYWwgPSBzY2FsZShcbiAgICAgICAgICAgIGNoZWNrRGF0YS52YWx1ZXNbeEluZGV4XSxcbiAgICAgICAgICAgIGNoZWNrSWZTZWNvbmRhcnkoZGF0YSwgaSwgeEluZGV4LCBpc1N1cHBsZW1lbnRhcnkpLFxuICAgICAgICAgICk7XG4gICAgICAgICAgLy9Ta2lwIHBvc2l0aXZlIHZhbHVlc1xuICAgICAgICAgIGlmIChjaGVja1ZhbCA+IHplcm9WYWwpIHtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgIH1cbiAgICAgICAgICBwcmV2QmFyV2lkdGhzICs9IGFwcGx5TWluaW11bURhdGFFbGVtZW50U2l6ZShcbiAgICAgICAgICAgIHplcm9WYWwgLSBjaGVja1ZhbCxcbiAgICAgICAgICAgIGNoZWNrRGF0YS52YWx1ZXNbeEluZGV4XSxcbiAgICAgICAgICAgIG1pbmltdW1TaXplLFxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGNvbnN0IHdpZHRoID0gYXBwbHlNaW5pbXVtRGF0YUVsZW1lbnRTaXplKFxuICAgICAgICB6ZXJvVmFsIC0gc2NhbGVWYWx1ZSxcbiAgICAgICAgeURhdGEudmFsdWVzW3hJbmRleF0sXG4gICAgICAgIG1pbmltdW1TaXplLFxuICAgICAgKTtcbiAgICAgIGNvbnN0IHhWYWx1ZSA9IHplcm9WYWwgLSB3aWR0aCAtIHByZXZCYXJXaWR0aHM7XG4gICAgICByZXR1cm4geyB4VmFsdWUsIHdpZHRoIH07XG4gICAgfVxuICAgIGxldCBwcmV2QmFyV2lkdGhzID0gMDtcbiAgICBpZiAoaXNTdGFja2VkKSB7XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHlJbmRleDsgaSsrKSB7XG4gICAgICAgIGNvbnN0IGNoZWNrRGF0YSA9IGdldE1haW5PclN1cHBZKGRhdGEsIGksIGlzU3VwcGxlbWVudGFyeSk7XG4gICAgICAgIC8vQm90aCB5RGF0YSBhbmQgY2hlY2tEYXRhIGFyZSBkZWZpbml0ZWx5IFN1cHBsZW1lbnRhcnlEYXRhWXMgaWYgaXNTdXBwbGVtZW50YXJ5IGlzIHRydWUsIGJ1dCB0aGV5IGRvbid0IHJlYWxpemUgaXRcbiAgICAgICAgaWYgKFxuICAgICAgICAgIGlzU3VwcGxlbWVudGFyeSAmJlxuICAgICAgICAgICdzdXBwbGVtZW50YWxJbmRleCcgaW4geURhdGEgJiZcbiAgICAgICAgICAnc3VwcGxlbWVudGFsSW5kZXgnIGluIGNoZWNrRGF0YVxuICAgICAgICApIHtcbiAgICAgICAgICBpZiAoeURhdGEuc3VwcGxlbWVudGFsSW5kZXggIT09IGNoZWNrRGF0YS5zdXBwbGVtZW50YWxJbmRleCkge1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGNoZWNrVmFsID0gc2NhbGUoXG4gICAgICAgICAgY2hlY2tEYXRhLnZhbHVlc1t4SW5kZXhdLFxuICAgICAgICAgIGNoZWNrSWZTZWNvbmRhcnkoZGF0YSwgaSwgeEluZGV4LCBpc1N1cHBsZW1lbnRhcnkpLFxuICAgICAgICApO1xuICAgICAgICAvL1NraXAgbmVnYXRpdmUgdmFsdWVzXG4gICAgICAgIGlmIChjaGVja1ZhbCA8IHplcm9WYWwpIHtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBwcmV2QmFyV2lkdGhzICs9IGFwcGx5TWluaW11bURhdGFFbGVtZW50U2l6ZShcbiAgICAgICAgICBjaGVja1ZhbCAtIHplcm9WYWwsXG4gICAgICAgICAgY2hlY2tEYXRhLnZhbHVlc1t4SW5kZXhdLFxuICAgICAgICAgIG1pbmltdW1TaXplLFxuICAgICAgICApO1xuICAgICAgfVxuICAgIH1cbiAgICBjb25zdCB4VmFsdWUgPSBwcmV2QmFyV2lkdGhzICsgemVyb1ZhbDtcbiAgICBjb25zdCB3aWR0aCA9IGFwcGx5TWluaW11bURhdGFFbGVtZW50U2l6ZShcbiAgICAgIHNjYWxlVmFsdWUgLSB6ZXJvVmFsLFxuICAgICAgeURhdGEudmFsdWVzW3hJbmRleF0sXG4gICAgICBtaW5pbXVtU2l6ZSxcbiAgICApO1xuICAgIHJldHVybiB7IHhWYWx1ZSwgd2lkdGggfTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGNoZWNrSWZTZWNvbmRhcnkoXG4gICAgZGF0YTogTm9uRmxvd0RhdGEsXG4gICAgeUluZGV4OiBudW1iZXIsXG4gICAgeEluZGV4OiBudW1iZXIsXG4gICAgaXNTdXBwbGVtZW50YXJ5OiBib29sZWFuID0gZmFsc2UsXG4gICk6IGJvb2xlYW4ge1xuICAgIGlmIChkYXRhLnR5cGUgPT09ICdsYWJlbGVkJykge1xuICAgICAgaWYgKGRhdGEueFt4SW5kZXhdLmlzU2Vjb25kYXJ5ID09PSB0cnVlKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZ2V0TWFpbk9yU3VwcFkoZGF0YSwgeUluZGV4LCBpc1N1cHBsZW1lbnRhcnkpLmlzU2Vjb25kYXJ5ID09PSB0cnVlO1xuICB9XG5cbiAgZnVuY3Rpb24gd2FyblVuc3VwcG9ydGVkUGF0dGVybnMoXG4gICAgZGF0YTogTm9uRmxvd0RhdGEsXG4gICAgc3VwcG9ydGVkUGF0dGVybnM6IFBhdHRlcm5bXSxcbiAgICBjaGFydFR5cGU6IHN0cmluZyxcbiAgKTogdm9pZCB7XG4gICAgY29uc3QgYWxsWXM6IERhdGFZW10gPSBbXG4gICAgICAuLi5kYXRhLnlzLFxuICAgICAgLi4uKGhhc1N1cHBsZW1lbnRhcnlEYXRhKGRhdGEpID8gZGF0YS5zdXBwbGVtZW50YXJ5WXMgOiBbXSksXG4gICAgXTtcbiAgICBmb3IgKGNvbnN0IHkgb2YgYWxsWXMpIHtcbiAgICAgIGlmIChcbiAgICAgICAgeS5wYXR0ZXJuICYmXG4gICAgICAgIHkucGF0dGVybiAhPT0gJ3NvbGlkJyAmJlxuICAgICAgICAhc3VwcG9ydGVkUGF0dGVybnMuaW5jbHVkZXMoeS5wYXR0ZXJuKVxuICAgICAgKSB7XG4gICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gICAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgICBgSGVhZHMgdXAhIFRoZSAnJHt5LnBhdHRlcm59JyBwYXR0ZXJuIGlzbid0IHN1cHBvcnRlZCBmb3IgJHtjaGFydFR5cGV9IGNoYXJ0cy4gRmFsbGluZyBiYWNrIHRvIHNvbGlkLmAsXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gd2FybkZsb3dEYXRhKFxuICAgIGRhdGE6IElucHV0RGF0YSxcbiAgICBjaGFydFR5cGU6IHN0cmluZyxcbiAgKTogZGF0YSBpcyBOb25GbG93RGF0YSB7XG4gICAgaWYgKGRhdGEudHlwZSA9PT0gJ2Zsb3cnKSB7XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29uc29sZVxuICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICBgSGVhZHMgdXAhIFRoZSAnZmxvdycgZGF0YSB0eXBlIGlzbid0IHN1cHBvcnRlZCBmb3IgJHtjaGFydFR5cGV9IGNoYXJ0cy5gLFxuICAgICAgKTtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICAvLyBoaWRlIHN0cmlwcyBvdXQgaGlkZGVuIHkgdmFsdWVzIHdoaWxlIHJldGFpbmluZyB0aGUgb3JpZ2luYWwgaW5kaWNlc1xuICAvLyBmb3IgdGhlIHJlbWFpbmluZyB2aXNpYmxlIHZhbHVlc1xuICBmdW5jdGlvbiBoaWRlKGRhdGE6IE5vbkZsb3dEYXRhKToge1xuICAgIGRhdGE6IE5vbkZsb3dEYXRhO1xuICAgIHZpc2libGVJbmRpY2VzOiBudW1iZXJbXTtcbiAgICB2aXNpYmxlU3VwcEluZGljZXM6IG51bWJlcltdO1xuICB9IHtcbiAgICBjb25zdCB2aXNpYmxlSW5kaWNlcyA9IGRhdGEueXNcbiAgICAgIC5tYXAoKHksIGkpID0+ICh7IHksIGkgfSkpXG4gICAgICAuZmlsdGVyKCh7IHkgfSkgPT4gIXkuaGlkZGVuKVxuICAgICAgLm1hcCgoeyBpIH0pID0+IGkpO1xuICAgIGNvbnN0IHZpc2libGVTdXBwSW5kaWNlcyA9IGhhc1N1cHBsZW1lbnRhcnlEYXRhKGRhdGEpXG4gICAgICA/IGRhdGEuc3VwcGxlbWVudGFyeVlzXG4gICAgICAgICAgLm1hcCgoeSwgaSkgPT4gKHsgeSwgaSB9KSlcbiAgICAgICAgICAuZmlsdGVyKCh7IHkgfSkgPT4gIXkuaGlkZGVuKVxuICAgICAgICAgIC5tYXAoKHsgaSB9KSA9PiBpKVxuICAgICAgOiBbXTtcbiAgICByZXR1cm4ge1xuICAgICAgZGF0YToge1xuICAgICAgICAuLi5kYXRhLFxuICAgICAgICB5czogdmlzaWJsZUluZGljZXMubWFwKGkgPT4gZGF0YS55c1tpXSksXG4gICAgICAgIHN1cHBsZW1lbnRhcnlZczogdmlzaWJsZVN1cHBJbmRpY2VzLm1hcChpID0+IGRhdGEuc3VwcGxlbWVudGFyeVlzIVtpXSksXG4gICAgICB9LFxuICAgICAgdmlzaWJsZUluZGljZXMsXG4gICAgICB2aXNpYmxlU3VwcEluZGljZXMsXG4gICAgfTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHdhdGVyZmFsbFRyYW5zZm9ybShcbiAgICBkYXRhOiBOb25GbG93RGF0YSxcbiAgICBpc1dhdGVyZmFsbDogYm9vbGVhbixcbiAgKTogeyBkYXRhOiBMYWJlbGVkRGF0YTsgbWFwOiBNYXA8RGF0YVksIERhdGFZPiB9IHtcbiAgICBjb25zdCB3YXRlcmZhbGxNYXAgPSBuZXcgTWFwPERhdGFZLCBEYXRhWT4oKTtcbiAgICBpZiAoZGF0YS50eXBlID09PSAndGltZXNlcmllcycgfHwgIWlzV2F0ZXJmYWxsKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBkYXRhOiB7XG4gICAgICAgICAgdHlwZTogJ2xhYmVsZWQnLFxuICAgICAgICAgIHg6IFtdLFxuICAgICAgICAgIHlzOiBbXSxcbiAgICAgICAgfSxcbiAgICAgICAgbWFwOiB3YXRlcmZhbGxNYXAsXG4gICAgICB9O1xuICAgIH1cbiAgICBjb25zdCBuZXdEYXRhOiBMYWJlbGVkRGF0YSA9IHtcbiAgICAgIC4uLmRhdGEsXG4gICAgICB4OiBbLi4uZGF0YS54LCB7IGxhYmVsOiAnVG90YWwnIH1dLFxuICAgICAgeXM6IFtcbiAgICAgICAgLi4uZGF0YS55cy5tYXAoeSA9PiB7XG4gICAgICAgICAgY29uc3QgbmV3WTogRGF0YVkgPSB7XG4gICAgICAgICAgICAuLi55LFxuICAgICAgICAgICAgdmFsdWVzOiBbLi4ueS52YWx1ZXMsIHkudmFsdWVzLnJlZHVjZSgoYSwgYikgPT4gYSArIGIsIDApXSxcbiAgICAgICAgICB9O1xuICAgICAgICAgIHdhdGVyZmFsbE1hcC5zZXQobmV3WSwgeSk7XG4gICAgICAgICAgcmV0dXJuIG5ld1k7XG4gICAgICAgIH0pLFxuICAgICAgXSxcbiAgICB9O1xuICAgIHJldHVybiB7XG4gICAgICBkYXRhOiBuZXdEYXRhLFxuICAgICAgbWFwOiB3YXRlcmZhbGxNYXAsXG4gICAgfTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGZsb3dzVHJhbnNmb3JtKFxuICAgIGNvbmZpZzogRmxvd0NvbmZpZyxcbiAgICBkYXRhOiBGbG93RGF0YSxcbiAgKTogUHJvY2Vzc2VkRmxvd0RhdGEge1xuICAgIGNvbnN0IHJldHVybkJ1Y2tldHM6IEZsb3dCdWNrZXRbXSA9IFtdO1xuICAgIGNvbnN0IG1heFBhdGhMZW5ndGggPSBNYXRoLm1heCguLi5kYXRhLnlzLm1hcCh5ID0+IHkuc3RlcHMubGVuZ3RoKSk7XG4gICAgaWYgKG1heFBhdGhMZW5ndGggPiAwICYmIG1heFBhdGhMZW5ndGggPCBJbmZpbml0eSkge1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBtYXhQYXRoTGVuZ3RoOyBpKyspIHtcbiAgICAgICAgY29uc3QgZmxvd0J1Y2tldDogRmxvd0J1Y2tldCA9IHtcbiAgICAgICAgICB0b3RhbENvdW50OiAwLFxuICAgICAgICAgIHN1YkJ1Y2tldHM6IFtdLFxuICAgICAgICB9O1xuICAgICAgICBmb3IgKGNvbnN0IHkgb2YgZGF0YS55cykge1xuICAgICAgICAgIGlmICh5LnZhbHVlcy5sZW5ndGggPiBpICYmIHkuc3RlcHMubGVuZ3RoID4gaSkge1xuICAgICAgICAgICAgY29uc3Qgc3ViQnVja2V0SWQgPSB5LnN0ZXBzW2ldO1xuICAgICAgICAgICAgY29uc3QgZm91bmRTdWJCdWNrZXQgPSBmbG93QnVja2V0LnN1YkJ1Y2tldHMuZmluZChcbiAgICAgICAgICAgICAgc3ViQnVja2V0ID0+IHN1YkJ1Y2tldC5pZCA9PT0gc3ViQnVja2V0SWQsXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgbGV0IHN1YkJ1Y2tldDogRmxvd1N1YkJ1Y2tldDtcbiAgICAgICAgICAgIGlmIChmb3VuZFN1YkJ1Y2tldCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgIHN1YkJ1Y2tldCA9IGZvdW5kU3ViQnVja2V0O1xuICAgICAgICAgICAgICBzdWJCdWNrZXQuY291bnQgKz0geS52YWx1ZXNbaV07XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBzdWJCdWNrZXQgPSB7XG4gICAgICAgICAgICAgICAgaWQ6IHN1YkJ1Y2tldElkLFxuICAgICAgICAgICAgICAgIGNvdW50OiB5LnZhbHVlc1tpXSxcbiAgICAgICAgICAgICAgICBjb25uZWN0aW9uczogW10sXG4gICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgIGZsb3dCdWNrZXQuc3ViQnVja2V0cy5wdXNoKHN1YkJ1Y2tldCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmbG93QnVja2V0LnRvdGFsQ291bnQgKz0geS52YWx1ZXNbaV07XG5cbiAgICAgICAgICAgIC8vRmlsbCBpbiBiYWNrd2FyZHMgY29ubmVjdGlvbnNcbiAgICAgICAgICAgIGlmIChpID4gMCkge1xuICAgICAgICAgICAgICBjb25zdCBmb3VuZENvbm5lY3Rpb24gPSBzdWJCdWNrZXQuY29ubmVjdGlvbnMuZmluZChcbiAgICAgICAgICAgICAgICBjb25uZWN0aW9uID0+XG4gICAgICAgICAgICAgICAgICBjb25uZWN0aW9uLnN0YXJ0ID09PSB5LnN0ZXBzW2kgLSAxXSAmJlxuICAgICAgICAgICAgICAgICAgY29ubmVjdGlvbi5lbmQgPT09IHN1YkJ1Y2tldElkICYmXG4gICAgICAgICAgICAgICAgICBjb25uZWN0aW9uLmRpcmVjdGlvbiA9PT0gJ2JhY2t3YXJkJyxcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgaWYgKGZvdW5kQ29ubmVjdGlvbiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgZm91bmRDb25uZWN0aW9uLmNvdW50ICs9IHkudmFsdWVzW2ldO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnN0IG5ld0Nvbm5lY3Rpb246IEZsb3dDb25uZWN0aW9uID0ge1xuICAgICAgICAgICAgICAgICAgZGlyZWN0aW9uOiAnYmFja3dhcmQnLFxuICAgICAgICAgICAgICAgICAgc3RhcnQ6IHkuc3RlcHNbaSAtIDFdLFxuICAgICAgICAgICAgICAgICAgZW5kOiBzdWJCdWNrZXRJZCxcbiAgICAgICAgICAgICAgICAgIGNvdW50OiB5LnZhbHVlc1tpXSxcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIHN1YkJ1Y2tldC5jb25uZWN0aW9ucy5wdXNoKG5ld0Nvbm5lY3Rpb24pO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vRmlsbCBpbiBmb3J3YXJkcyBjb25uZWN0aW9uc1xuICAgICAgICAgICAgaWYgKGkgPCB5LnN0ZXBzLmxlbmd0aCAtIDEgJiYgaSA8IHkudmFsdWVzLmxlbmd0aCAtIDEpIHtcbiAgICAgICAgICAgICAgY29uc3QgZm91bmRDb25uZWN0aW9uID0gc3ViQnVja2V0LmNvbm5lY3Rpb25zLmZpbmQoXG4gICAgICAgICAgICAgICAgY29ubmVjdGlvbiA9PlxuICAgICAgICAgICAgICAgICAgY29ubmVjdGlvbi5zdGFydCA9PT0gc3ViQnVja2V0SWQgJiZcbiAgICAgICAgICAgICAgICAgIGNvbm5lY3Rpb24uZW5kID09PSB5LnN0ZXBzW2kgKyAxXSAmJlxuICAgICAgICAgICAgICAgICAgY29ubmVjdGlvbi5kaXJlY3Rpb24gPT09ICdmb3J3YXJkJyxcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgaWYgKGZvdW5kQ29ubmVjdGlvbiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgZm91bmRDb25uZWN0aW9uLmNvdW50ICs9IHkudmFsdWVzW2kgKyAxXTtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zdCBuZXdDb25uZWN0aW9uOiBGbG93Q29ubmVjdGlvbiA9IHtcbiAgICAgICAgICAgICAgICAgIGRpcmVjdGlvbjogJ2ZvcndhcmQnLFxuICAgICAgICAgICAgICAgICAgc3RhcnQ6IHN1YkJ1Y2tldElkLFxuICAgICAgICAgICAgICAgICAgZW5kOiB5LnN0ZXBzW2kgKyAxXSxcbiAgICAgICAgICAgICAgICAgIGNvdW50OiB5LnZhbHVlc1tpICsgMV0sXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICBzdWJCdWNrZXQuY29ubmVjdGlvbnMucHVzaChuZXdDb25uZWN0aW9uKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm5CdWNrZXRzLnB1c2goZmxvd0J1Y2tldCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3Qgc3ViQnVja2V0T3JkZXJpbmdNYXAgPSBuZXcgTWFwPHN0cmluZywgbnVtYmVyPigpO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY29uZmlnLmZsb3dDb25maWcuc3ViQnVja2V0c0NvbmZpZy5sZW5ndGg7IGkrKykge1xuICAgICAgc3ViQnVja2V0T3JkZXJpbmdNYXAuc2V0KFxuICAgICAgICBjb25maWcuZmxvd0NvbmZpZy5zdWJCdWNrZXRzQ29uZmlnW2ldLmJ1Y2tldElkLFxuICAgICAgICBpLFxuICAgICAgKTtcbiAgICB9XG4gICAgY29uc3QgbWFwR2V0ID0gKGlkOiBzdHJpbmcpOiBudW1iZXIgPT4ge1xuICAgICAgY29uc3QgZm91bmRSZXN1bHQgPSBzdWJCdWNrZXRPcmRlcmluZ01hcC5nZXQoaWQpO1xuICAgICAgaWYgKGZvdW5kUmVzdWx0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgcmV0dXJuIGZvdW5kUmVzdWx0O1xuICAgICAgfVxuICAgICAgLy9JZiBzb21ldGhpbmcgaXNuJ3QgZGVmaW5lZCBpbiB0aGUgY29uZmlnLCBwdXQgaXQgYXQgdGhlIGVuZFxuICAgICAgcmV0dXJuIEluZmluaXR5O1xuICAgIH07XG5cbiAgICAvL0Vuc3VyZSB0aGUgZGF0YSBpcyBzb3J0ZWQgdGhlIHNhbWUgdGhlIHdheSB0aGUgY29uZmlnIGlzLCBhbmQgZHJvcCBlbXB0eVxuICAgIC8vYmFycy9jb25uZWN0aW9ucyBzbyB0aGV5J3JlIG5laXRoZXIgZGlzcGxheWVkIG5vciBmYWN0b3JlZCBpbnRvIHNpemluZ1xuICAgIHJldHVybiB7XG4gICAgICB0eXBlOiAnZmxvdy1wcm9jZXNzZWQnLFxuICAgICAgeDogcmV0dXJuQnVja2V0cy5tYXAoYnVja2V0ID0+ICh7XG4gICAgICAgIC4uLmJ1Y2tldCxcbiAgICAgICAgc3ViQnVja2V0czogYnVja2V0LnN1YkJ1Y2tldHNcbiAgICAgICAgICAuZmlsdGVyKHN1YkJ1Y2tldCA9PiBzdWJCdWNrZXQuY291bnQgIT09IDApXG4gICAgICAgICAgLnNvcnQoKGEsIGIpID0+IG1hcEdldChhLmlkKSAtIG1hcEdldChiLmlkKSlcbiAgICAgICAgICAubWFwKHN1YkJ1Y2tldCA9PiAoe1xuICAgICAgICAgICAgLi4uc3ViQnVja2V0LFxuICAgICAgICAgICAgY29ubmVjdGlvbnM6IHN1YkJ1Y2tldC5jb25uZWN0aW9uc1xuICAgICAgICAgICAgICAuZmlsdGVyKGNvbm5lY3Rpb24gPT4gY29ubmVjdGlvbi5jb3VudCAhPT0gMClcbiAgICAgICAgICAgICAgLnNvcnQoKGEsIGIpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBmaXJzdFNvcnQgPSBtYXBHZXQoYS5zdGFydCkgLSBtYXBHZXQoYi5zdGFydCk7XG4gICAgICAgICAgICAgICAgaWYgKGZpcnN0U29ydCAhPT0gMCkge1xuICAgICAgICAgICAgICAgICAgcmV0dXJuIGZpcnN0U29ydDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIG1hcEdldChhLmVuZCkgLSBtYXBHZXQoYi5lbmQpO1xuICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICB9KSksXG4gICAgICB9KSksXG4gICAgfTtcbiAgfVxuXG4gIHR5cGUgVmFsdWVUeXBlID0gJ2NvdW50JyB8ICdjdXJyZW5jeScgfCAncGVyY2VudGFnZScgfCAnZGF5cyc7XG5cbiAgZXhwb3J0IGZ1bmN0aW9uIGdldFBpcGVzKHZhbHVlVHlwZTogVmFsdWVUeXBlKSB7XG4gICAgc3dpdGNoICh2YWx1ZVR5cGUpIHtcbiAgICAgIGNhc2UgJ2NvdW50Jzoge1xuICAgICAgICByZXR1cm4geyBwaXBlOiBuZXcgU21hbGxOdW1iZXJQaXBlKCksIGZ1bGxQaXBlOiBuZXcgTnVtYmVyUGlwZSgpIH07XG4gICAgICB9XG4gICAgICBjYXNlICdjdXJyZW5jeSc6XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgcGlwZTogbmV3IFNtYWxsQ3VycmVuY3lQaXBlKCksXG4gICAgICAgICAgZnVsbFBpcGU6IG5ldyBDdXJyZW5jeVBpcGUoJ2VuLXVzJyksXG4gICAgICAgIH07XG4gICAgICBjYXNlICdwZXJjZW50YWdlJzoge1xuICAgICAgICBjb25zdCBwaXBlID0gbmV3IFBlcmNlbnRhZ2VQaXBlKCk7XG4gICAgICAgIHJldHVybiB7IHBpcGUsIGZ1bGxQaXBlOiBwaXBlIH07XG4gICAgICB9XG4gICAgICBjYXNlICdkYXlzJzoge1xuICAgICAgICBjb25zdCBwaXBlID0gbmV3IERheXNQaXBlKCk7XG4gICAgICAgIHJldHVybiB7IHBpcGUsIGZ1bGxQaXBlOiBwaXBlIH07XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgY29uc3QgaW50ZXJ2YWxzID0gWyd5ZWFyJywgJ3F1YXJ0ZXInLCAnbW9udGgnLCAnd2VlaycsICdkYXknXSBhcyBjb25zdDtcbiAgZXhwb3J0IHR5cGUgSW50ZXJ2YWwgPSAodHlwZW9mIGludGVydmFscylbbnVtYmVyXTtcblxuICBleHBvcnQgZnVuY3Rpb24gZm9ybWF0ZWREYXRlKGRhdGVGb3JtYXQ6IEludGVydmFsLCBkYXRlOiBEYXRlKSB7XG4gICAgaWYgKGRhdGVGb3JtYXQgPT09ICdxdWFydGVyJykge1xuICAgICAgY29uc3QgcXVhcnRlciA9IE1hdGguY2VpbCgoZGF0ZS5nZXRVVENNb250aCgpICsgMSkgLyAzKTtcbiAgICAgIGNvbnN0IHllYXIgPSB1dGNGb3JtYXQoZ2V0VGltZUludGVydmFsRm9ybWF0KCd5ZWFyJykpKGRhdGUpO1xuICAgICAgcmV0dXJuIGBRJHtxdWFydGVyfSAke3llYXJ9YDtcbiAgICB9XG4gICAgY29uc3QgZm9ybWF0ID0gZ2V0VGltZUludGVydmFsRm9ybWF0KGRhdGVGb3JtYXQpO1xuICAgIHJldHVybiB1dGNGb3JtYXQoZm9ybWF0KShkYXRlKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGdldFRpbWVJbnRlcnZhbEZvcm1hdChpbnRlcnZhbDogSW50ZXJ2YWwpOiBzdHJpbmcge1xuICAgIHN3aXRjaCAoaW50ZXJ2YWwpIHtcbiAgICAgIGNhc2UgJ2RheSc6XG4gICAgICBjYXNlICd3ZWVrJzpcbiAgICAgICAgcmV0dXJuICclbS8lZC8lWSc7XG4gICAgICBjYXNlICdtb250aCc6XG4gICAgICBjYXNlICdxdWFydGVyJzpcbiAgICAgICAgcmV0dXJuICclYiAlWSc7XG4gICAgICBjYXNlICd5ZWFyJzpcbiAgICAgICAgcmV0dXJuICclWSc7XG4gICAgfVxuICB9XG5cbiAgZXhwb3J0IGZ1bmN0aW9uIGNvbnZlcnRDaGFydERhdGFUb0RvbnV0RGF0YShcbiAgICBjaGFydERhdGE6IE5vbkZsb3dEYXRhLFxuICApOiBEb251dERhdGFbXSB7XG4gICAgaWYgKGNoYXJ0RGF0YS55cy5maW5kKHkgPT4geS52YWx1ZXMubGVuZ3RoID4gMSkpIHtcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgIFwiSGVhZHMgdXAhIFBpZSBjaGFydHMgZG9uJ3Qgc3VwcG9ydCBtdWx0aXBsZSB2YWx1ZXMgcGVyIHNlcmllc1wiLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBjb25zdCBkb251dERhdGEgPSBjaGFydERhdGEueXMubWFwKHkgPT4gKHtcbiAgICAgIGxhYmVsOiB5LmxhYmVsLFxuICAgICAgaGlkZGVuOiB5LmhpZGRlbixcbiAgICAgIHZhbHVlOiB5LnZhbHVlcy5sZW5ndGggPj0gMSA/IHkudmFsdWVzWzBdIDogMCxcbiAgICAgIGlzU2Vjb25kYXJ5OiB5LmlzU2Vjb25kYXJ5LFxuICAgIH0pKTtcbiAgICByZXR1cm4gZG9udXREYXRhO1xuICB9XG5cbiAgZnVuY3Rpb24gYXJjVG9Qb2ludChhbmdsZTogbnVtYmVyLCByYWRpdXM6IG51bWJlcikge1xuICAgIHJldHVybiB7XG4gICAgICB4OiByYWRpdXMgKiBNYXRoLmNvcyhhbmdsZSAtIE1hdGguUEkgLyAyKSxcbiAgICAgIHk6IHJhZGl1cyAqIE1hdGguc2luKGFuZ2xlIC0gTWF0aC5QSSAvIDIpLFxuICAgIH07XG4gIH1cblxuICBmdW5jdGlvbiBwb2ludFRvQXJjKHg6IG51bWJlciwgeTogbnVtYmVyKSB7XG4gICAgY29uc3QgcmFkaXVzID0gTWF0aC5oeXBvdCh4LCB5KTtcbiAgICBsZXQgYW5nbGUgPSBNYXRoLmF0YW4yKHksIHgpICsgTWF0aC5QSSAvIDI7XG4gICAgLy9Ob3JtYWxpemUgdG8gYmUgd2l0aGluIHJhbmdlIFswLCAyz4BdXG4gICAgYW5nbGUgPSAoYW5nbGUgKyAyICogTWF0aC5QSSkgJSAoMiAqIE1hdGguUEkpO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIGFuZ2xlLFxuICAgICAgcmFkaXVzLFxuICAgIH07XG4gIH1cblxuICBmdW5jdGlvbiBnZXRGdWxsQ2hhcnRTY2FsZVZhbHVlcyhcbiAgICBjb25maWc6IENvbmZpZ1dpdGhGdWxsU2NhbGluZyxcbiAgICBkYXRhOiBQcm9jZXNzRGF0YSxcbiAgICBkaW1lbnNpb25zOiBEaW1lbnNpb25zLFxuICAgIHBpcGVUcmFuc2Zvcm06ICgodmFsdWU6IG51bWJlciwgaXNTZWNvbmRhcnk6IGJvb2xlYW4pID0+IHN0cmluZykgfCBudWxsLFxuICAgIGRhdGVGb3JtYXQ6ICgoZGF0ZTogRGF0ZSkgPT4gc3RyaW5nKSB8IG51bGwsXG4gICk6IEZ1bGxDaGFydFNjYWxlVmFsdWVzIHwgbnVsbCB7XG4gICAgY29uc3QgY2hhcnREYXRhRGlyZWN0aW9uID0gZ2V0Q2hhcnREYXRhRGlyZWN0aW9uKGNvbmZpZyk7XG4gICAgY29uc3QgZGVmYXVsdFNjYWxpbmdDb25maWcgPSBnZXREZWZhdWx0U2NhbGluZ0NvbmZpZ0J5Q2hhcnRUeXBlKFxuICAgICAgY29uZmlnLnR5cGUsXG4gICAgICBjb25maWcuc2Vjb25kYXJ5VmFsdWVUeXBlICE9PSB1bmRlZmluZWQsXG4gICAgKTtcbiAgICBjb25zdCBzY2FsaW5nQ29uZmlnID0gY29tYmluZVNjYWxpbmdJbmZvKGNvbmZpZywgZGVmYXVsdFNjYWxpbmdDb25maWcpO1xuICAgIGNvbnN0IG5vbkRhdGFBeGlzVmFsdWVzID0gY2FsY3VsYXRlTm9uRGF0YUF4aXNWYWx1ZXMoXG4gICAgICBjb25maWcsXG4gICAgICBzY2FsaW5nQ29uZmlnLFxuICAgICAgY29uZmlnLnNjYWxpbmdDb25maWc/LmVsZW1lbnRTY2FsZXMsXG4gICAgICBkZWZhdWx0U2NhbGluZ0NvbmZpZy5lbGVtZW50U2NhbGVzLFxuICAgICAgZGltZW5zaW9ucyxcbiAgICAgIGRhdGEsXG4gICAgKTtcbiAgICBjb25zdCBkYXRhQXhpc1ZhbHVlcyA9IGNhbGN1bGF0ZURhdGFBeGlzVmFsdWVzKFxuICAgICAgY29uZmlnLFxuICAgICAgc2NhbGluZ0NvbmZpZyxcbiAgICAgIGNvbmZpZy5zY2FsaW5nQ29uZmlnPy5lbGVtZW50U2NhbGVzLFxuICAgICAgZGVmYXVsdFNjYWxpbmdDb25maWcuZWxlbWVudFNjYWxlcyxcbiAgICAgIGRpbWVuc2lvbnMsXG4gICAgICBkYXRhLFxuICAgICAgcGlwZVRyYW5zZm9ybSxcbiAgICAgIGRhdGVGb3JtYXQsXG4gICAgKTtcbiAgICBpZiAoXG4gICAgICBub25EYXRhQXhpc1ZhbHVlcy5zaXppbmdFcnJvciA9PT0gdHJ1ZSB8fFxuICAgICAgZGF0YUF4aXNWYWx1ZXMuc2l6aW5nRXJyb3IgPT09IHRydWVcbiAgICApIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICBjb25zdCBkYXRhTGFiZWxTdGFydFBhZGRpbmcgPVxuICAgICAgZ2V0RGF0YUxhYmVsU2l6aW5nQ291bnQoZGF0YSwgY29uZmlnKS5zdGFydCAqXG4gICAgICAoZGF0YUF4aXNWYWx1ZXMuZGF0YUxhYmVsUGFkZGluZyArIGRhdGFBeGlzVmFsdWVzLmRhdGFMYWJlbFRleHRTaXplKTtcbiAgICBjb25zdCBkYXRhTGFiZWxFbmRQYWRkaW5nID1cbiAgICAgIGdldERhdGFMYWJlbFNpemluZ0NvdW50KGRhdGEsIGNvbmZpZykuZW5kICpcbiAgICAgIChkYXRhQXhpc1ZhbHVlcy5kYXRhTGFiZWxQYWRkaW5nICsgZGF0YUF4aXNWYWx1ZXMuZGF0YUxhYmVsVGV4dFNpemUpO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIC4uLm5vbkRhdGFBeGlzVmFsdWVzLFxuICAgICAgLi4uZGF0YUF4aXNWYWx1ZXMsXG4gICAgICBsZWZ0UGFkZGluZzpcbiAgICAgICAgY2hhcnREYXRhRGlyZWN0aW9uID09PSAnaG9yaXpvbnRhbCdcbiAgICAgICAgICA/IGRhdGFBeGlzVmFsdWVzLnN0YXJ0UGFkZGluZ1xuICAgICAgICAgIDogbm9uRGF0YUF4aXNWYWx1ZXMuc3RhcnRQYWRkaW5nLFxuICAgICAgcmlnaHRQYWRkaW5nOlxuICAgICAgICBjaGFydERhdGFEaXJlY3Rpb24gPT09ICdob3Jpem9udGFsJ1xuICAgICAgICAgID8gZGF0YUF4aXNWYWx1ZXMuZW5kUGFkZGluZ1xuICAgICAgICAgIDogbm9uRGF0YUF4aXNWYWx1ZXMuZW5kUGFkZGluZyxcbiAgICAgIHRvcFBhZGRpbmc6XG4gICAgICAgIGNoYXJ0RGF0YURpcmVjdGlvbiA9PT0gJ2hvcml6b250YWwnXG4gICAgICAgICAgPyBub25EYXRhQXhpc1ZhbHVlcy5zdGFydFBhZGRpbmdcbiAgICAgICAgICA6IGRhdGFBeGlzVmFsdWVzLnN0YXJ0UGFkZGluZyxcbiAgICAgIGJvdHRvbVBhZGRpbmc6XG4gICAgICAgIGNoYXJ0RGF0YURpcmVjdGlvbiA9PT0gJ2hvcml6b250YWwnXG4gICAgICAgICAgPyBub25EYXRhQXhpc1ZhbHVlcy5lbmRQYWRkaW5nXG4gICAgICAgICAgOiBkYXRhQXhpc1ZhbHVlcy5lbmRQYWRkaW5nLFxuICAgICAgdG90YWxMZWZ0T2Zmc2V0OlxuICAgICAgICBjaGFydERhdGFEaXJlY3Rpb24gPT09ICdob3Jpem9udGFsJ1xuICAgICAgICAgID8gZGF0YUF4aXNWYWx1ZXMuc3RhcnRQYWRkaW5nICtcbiAgICAgICAgICAgIGRhdGFBeGlzVmFsdWVzLmxlZnRCdWNrZXRMYWJlbCArXG4gICAgICAgICAgICBkYXRhTGFiZWxTdGFydFBhZGRpbmdcbiAgICAgICAgICA6IG5vbkRhdGFBeGlzVmFsdWVzLnN0YXJ0UGFkZGluZyArIG5vbkRhdGFBeGlzVmFsdWVzLm91dGVyR2FwLFxuICAgICAgdG90YWxSaWdodE9mZnNldDpcbiAgICAgICAgY2hhcnREYXRhRGlyZWN0aW9uID09PSAnaG9yaXpvbnRhbCdcbiAgICAgICAgICA/IGRhdGFBeGlzVmFsdWVzLnN0YXJ0UGFkZGluZyArIGRhdGFMYWJlbEVuZFBhZGRpbmdcbiAgICAgICAgICA6IG5vbkRhdGFBeGlzVmFsdWVzLmVuZFBhZGRpbmcgKyBub25EYXRhQXhpc1ZhbHVlcy5vdXRlckdhcCxcbiAgICAgIHRvdGFsVG9wT2Zmc2V0OlxuICAgICAgICBjaGFydERhdGFEaXJlY3Rpb24gPT09ICdob3Jpem9udGFsJ1xuICAgICAgICAgID8gbm9uRGF0YUF4aXNWYWx1ZXMuc3RhcnRQYWRkaW5nICsgbm9uRGF0YUF4aXNWYWx1ZXMub3V0ZXJHYXBcbiAgICAgICAgICA6IGRhdGFBeGlzVmFsdWVzLnN0YXJ0UGFkZGluZyArIGRhdGFMYWJlbFN0YXJ0UGFkZGluZyxcbiAgICAgIHRvdGFsQm90dG9tT2Zmc2V0OlxuICAgICAgICBjaGFydERhdGFEaXJlY3Rpb24gPT09ICdob3Jpem9udGFsJ1xuICAgICAgICAgID8gbm9uRGF0YUF4aXNWYWx1ZXMuZW5kUGFkZGluZyArIG5vbkRhdGFBeGlzVmFsdWVzLm91dGVyR2FwXG4gICAgICAgICAgOiBkYXRhQXhpc1ZhbHVlcy5lbmRQYWRkaW5nICsgZGF0YUxhYmVsRW5kUGFkZGluZyxcbiAgICAgIHRhcmdldFRpY2tDb3VudDogc2NhbGluZ0NvbmZpZy50YXJnZXRUaWNrQ291bnQsXG4gICAgICBzaXplRm9yRGF0YTogZGF0YUF4aXNWYWx1ZXMuc2l6ZUZvckRhdGEsXG4gICAgICB0b3RhbFdpZHRoOlxuICAgICAgICBjaGFydERhdGFEaXJlY3Rpb24gPT09ICdob3Jpem9udGFsJ1xuICAgICAgICAgID8gZGF0YUF4aXNWYWx1ZXMudG90YWxTaXplXG4gICAgICAgICAgOiBub25EYXRhQXhpc1ZhbHVlcy50b3RhbFNpemUsXG4gICAgICB0b3RhbEhlaWdodDpcbiAgICAgICAgY2hhcnREYXRhRGlyZWN0aW9uID09PSAnaG9yaXpvbnRhbCdcbiAgICAgICAgICA/IG5vbkRhdGFBeGlzVmFsdWVzLnRvdGFsU2l6ZVxuICAgICAgICAgIDogZGF0YUF4aXNWYWx1ZXMudG90YWxTaXplLFxuICAgICAgZGF0YUxhYmVsVGV4dFNpemU6IGNvbmZpZy5zaG93RGF0YUxhYmVsc1xuICAgICAgICA/IGRhdGFBeGlzVmFsdWVzLmRhdGFMYWJlbFRleHRTaXplXG4gICAgICAgIDogMCxcbiAgICAgIGhvcml6b250YWxBeGlzTGFiZWxUZXh0U2l6ZTpcbiAgICAgICAgY2hhcnREYXRhRGlyZWN0aW9uID09PSAndmVydGljYWwnXG4gICAgICAgICAgPyBkYXRhQXhpc1ZhbHVlcy5idWNrZXRMYWJlbFRleHRTaXplXG4gICAgICAgICAgOiBkYXRhQXhpc1ZhbHVlcy5kYXRhTGFiZWxUZXh0U2l6ZSwgLy9UaWNrcyBhbmQgZGF0YSBsYWJlbHMgdXNlIHRoZSBzYW1lIGZvcm1hdHRpbmcgb24gdGhlIHNhbWUga2luZCBvZiBkYXRhXG4gICAgICB2ZXJ0aWNhbEF4aXNMYWJlbFRleHRTaXplOiBkYXRhQXhpc1ZhbHVlcy5mb250U2l6ZSxcbiAgICAgIGNoYXJ0RGF0YURpcmVjdGlvbixcbiAgICAgIGhvcml6b250YWxDb250YWluZXJTY2FsZTogc2NhbGluZ0NvbmZpZy5ob3Jpem9udGFsQ29udGFpbmVyU2NhbGUsXG4gICAgICB2ZXJ0aWNhbENvbnRhaW5lclNjYWxlOiBzY2FsaW5nQ29uZmlnLnZlcnRpY2FsQ29udGFpbmVyU2NhbGUsXG4gICAgfTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGNhbGN1bGF0ZU5vbkRhdGFBeGlzVmFsdWVzKFxuICAgIGNvbmZpZzogQ29uZmlnLFxuICAgIHNjYWxpbmdDb25maWc6IE5vbkVsZW1lbnRTY2FsaW5nQ29uZmlnLFxuICAgIGVsZW1lbnRTY2FsZXM6IFBhcnRpYWxFbGVtZW50U2NhbGluZ0NvbmZpZyB8IHVuZGVmaW5lZCxcbiAgICBkZWZhdWx0U2l6aW5nOiBGdWxsRWxlbWVudFNjYWxpbmdDb25maWcsXG4gICAgZGltZW5zaW9uczogRGltZW5zaW9ucyxcbiAgICBkYXRhOiBQcm9jZXNzRGF0YSxcbiAgKToge1xuICAgIGJhclNpemU6IG51bWJlcjtcbiAgICBiYXJDbHVzdGVyR2FwOiBudW1iZXI7XG4gICAgYnVja2V0R2FwOiBudW1iZXI7XG4gICAgb3V0ZXJHYXA6IG51bWJlcjtcbiAgICBzdGFydFBhZGRpbmc6IG51bWJlcjtcbiAgICBlbmRQYWRkaW5nOiBudW1iZXI7XG4gICAgdG90YWxTaXplOiBudW1iZXI7XG4gICAgc2l6aW5nRXJyb3I/OiBib29sZWFuO1xuICB9IHtcbiAgICBjb25zdCBjaGFydERhdGFEaXJlY3Rpb24gPSBnZXRDaGFydERhdGFEaXJlY3Rpb24oY29uZmlnKTtcbiAgICBjb25zdCBib3VuZGluZ0RpbWVuc2lvbiA9XG4gICAgICBjaGFydERhdGFEaXJlY3Rpb24gPT09ICdob3Jpem9udGFsJ1xuICAgICAgICA/IGRpbWVuc2lvbnMuaGVpZ2h0XG4gICAgICAgIDogZGltZW5zaW9ucy53aWR0aDtcbiAgICBjb25zdCBheGlzU2NhbGUgPVxuICAgICAgY2hhcnREYXRhRGlyZWN0aW9uID09PSAnaG9yaXpvbnRhbCdcbiAgICAgICAgPyBzY2FsaW5nQ29uZmlnPy52ZXJ0aWNhbEF4aXNTY2FsZVxuICAgICAgICA6IHNjYWxpbmdDb25maWc/Lmhvcml6b250YWxBeGlzU2NhbGU7XG5cbiAgICBjb25zdCBiYXJTaXplQ29uZmlnID0gZ2V0RWxlbWVudFNjYWxpbmdJbmZvKFxuICAgICAgZWxlbWVudFNjYWxlcyxcbiAgICAgIGRlZmF1bHRTaXppbmcsXG4gICAgICAnYmFyU2l6ZScsXG4gICAgKTtcbiAgICBjb25zdCBiYXJDbHVzdGVyR2FwQ29uZmlnID0gZ2V0RWxlbWVudFNjYWxpbmdJbmZvKFxuICAgICAgZWxlbWVudFNjYWxlcyxcbiAgICAgIGRlZmF1bHRTaXppbmcsXG4gICAgICAnYmFyQ2x1c3RlckdhcCcsXG4gICAgKTtcbiAgICBjb25zdCBidWNrZXRHYXBDb25maWcgPSBnZXRFbGVtZW50U2NhbGluZ0luZm8oXG4gICAgICBlbGVtZW50U2NhbGVzLFxuICAgICAgZGVmYXVsdFNpemluZyxcbiAgICAgICdidWNrZXRHYXAnLFxuICAgICk7XG4gICAgY29uc3Qgb3V0ZXJHYXBDb25maWcgPSBnZXRFbGVtZW50U2NhbGluZ0luZm8oXG4gICAgICBlbGVtZW50U2NhbGVzLFxuICAgICAgZGVmYXVsdFNpemluZyxcbiAgICAgICdvdXRlckdhcCcsXG4gICAgKTtcbiAgICBjb25zdCBzdGFydFBhZGRpbmdDb25maWcgPSBnZXRFbGVtZW50U2NhbGluZ0luZm8oXG4gICAgICBlbGVtZW50U2NhbGVzLFxuICAgICAgZGVmYXVsdFNpemluZyxcbiAgICAgIGNoYXJ0RGF0YURpcmVjdGlvbiA9PT0gJ2hvcml6b250YWwnID8gJ3RvcFBhZGRpbmcnIDogJ2xlZnRQYWRkaW5nJyxcbiAgICApO1xuICAgIGNvbnN0IGVuZFBhZGRpbmdDb25maWcgPSBnZXRFbGVtZW50U2NhbGluZ0luZm8oXG4gICAgICBlbGVtZW50U2NhbGVzLFxuICAgICAgZGVmYXVsdFNpemluZyxcbiAgICAgIGNoYXJ0RGF0YURpcmVjdGlvbiA9PT0gJ2hvcml6b250YWwnID8gJ2JvdHRvbVBhZGRpbmcnIDogJ3JpZ2h0UGFkZGluZycsXG4gICAgKTtcblxuICAgIGNvbnN0IGJ1Y2tldENvdW50ID0gZGF0YS54Lmxlbmd0aDtcbiAgICBsZXQgYmFyQ291bnQgPSAwO1xuICAgIGxldCBiYXJDbHVzdGVyR2FwQ291bnQgPSAwO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYnVja2V0Q291bnQ7IGkrKykge1xuICAgICAgaWYgKGRhdGEudHlwZSA9PT0gJ2Zsb3ctcHJvY2Vzc2VkJykge1xuICAgICAgICBiYXJDb3VudCArPSAxO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc3QgYnVja2V0Q2x1c3RlckNvdW50ID0gZ2V0Q2x1c3RlckluZm9Gb3JCdWNrZXQoZGF0YSwgY29uZmlnKTtcbiAgICAgICAgYmFyQ291bnQgKz0gYnVja2V0Q2x1c3RlckNvdW50LnRvdGFsO1xuICAgICAgICBiYXJDbHVzdGVyR2FwQ291bnQgKz0gYnVja2V0Q2x1c3RlckNvdW50LnRvdGFsIC0gMTtcbiAgICAgIH1cbiAgICB9XG4gICAgY29uc3QgYnVja2V0R2FwQ291bnQgPSBidWNrZXRDb3VudCAtIDE7XG5cbiAgICBjb25zdCBiYXJUb3RhbFNpemUgPSBkZXRlcm1pbmVQb3NzaWJsZVNpemVzT2ZFbGVtZW50KFxuICAgICAgYmFyU2l6ZUNvbmZpZyxcbiAgICAgIGJhckNvdW50LFxuICAgICk7XG4gICAgY29uc3QgY2x1c3RlckdhcFRvdGFsU2l6ZSA9IGRldGVybWluZVBvc3NpYmxlU2l6ZXNPZkVsZW1lbnQoXG4gICAgICBiYXJDbHVzdGVyR2FwQ29uZmlnLFxuICAgICAgYmFyQ2x1c3RlckdhcENvdW50LFxuICAgICk7XG4gICAgY29uc3QgYnVja2V0R2FwVG90YWxTaXplID0gZGV0ZXJtaW5lUG9zc2libGVTaXplc09mRWxlbWVudChcbiAgICAgIGJ1Y2tldEdhcENvbmZpZyxcbiAgICAgIGJ1Y2tldEdhcENvdW50LFxuICAgICk7XG4gICAgY29uc3Qgb3V0ZXJHYXBUb3RhbFNpemUgPSBkZXRlcm1pbmVQb3NzaWJsZVNpemVzT2ZFbGVtZW50KFxuICAgICAgb3V0ZXJHYXBDb25maWcsXG4gICAgICAyLFxuICAgICk7XG4gICAgY29uc3Qgc3RhcnRQYWRkaW5nVG90YWxTaXplID0gZGV0ZXJtaW5lUG9zc2libGVTaXplc09mRWxlbWVudChcbiAgICAgIHN0YXJ0UGFkZGluZ0NvbmZpZyxcbiAgICAgIDEsXG4gICAgKTtcbiAgICBjb25zdCBlbmRQYWRkaW5nVG90YWxTaXplID0gZGV0ZXJtaW5lUG9zc2libGVTaXplc09mRWxlbWVudChcbiAgICAgIGVuZFBhZGRpbmdDb25maWcsXG4gICAgICAxLFxuICAgICk7XG5cbiAgICBjb25zdCBjYWxjVGFyZ2V0U2l6ZSA9XG4gICAgICBiYXJUb3RhbFNpemUudGFyZ2V0ICtcbiAgICAgIGNsdXN0ZXJHYXBUb3RhbFNpemUudGFyZ2V0ICtcbiAgICAgIGJ1Y2tldEdhcFRvdGFsU2l6ZS50YXJnZXQgK1xuICAgICAgb3V0ZXJHYXBUb3RhbFNpemUudGFyZ2V0ICtcbiAgICAgIHN0YXJ0UGFkZGluZ1RvdGFsU2l6ZS50YXJnZXQgK1xuICAgICAgZW5kUGFkZGluZ1RvdGFsU2l6ZS50YXJnZXQ7XG5cbiAgICBpZiAoXG4gICAgICBheGlzU2NhbGUgPT09ICduby1zY2FsZScgfHxcbiAgICAgIGNhbGNUYXJnZXRTaXplID09PSBib3VuZGluZ0RpbWVuc2lvbiB8fFxuICAgICAgKGF4aXNTY2FsZSA9PT0gJ2dyb3cnICYmIGNhbGNUYXJnZXRTaXplID4gYm91bmRpbmdEaW1lbnNpb24pIHx8XG4gICAgICAoYXhpc1NjYWxlID09PSAnc2hyaW5rJyAmJiBjYWxjVGFyZ2V0U2l6ZSA8IGJvdW5kaW5nRGltZW5zaW9uKVxuICAgICkge1xuICAgICAgLy9ObyBlbGVtZW50IHNjYWxpbmcgbmVjZXNzYXJ5LCByZXR1cm4gZXZlcnl0aGluZyBhcyBpdCdzIHRhcmdldCB2YWx1ZVxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgYmFyU2l6ZTogYmFyU2l6ZUNvbmZpZy50YXJnZXQsXG4gICAgICAgIGJhckNsdXN0ZXJHYXA6IGJhckNsdXN0ZXJHYXBDb25maWcudGFyZ2V0LFxuICAgICAgICBidWNrZXRHYXA6IGJ1Y2tldEdhcENvbmZpZy50YXJnZXQsXG4gICAgICAgIG91dGVyR2FwOiBvdXRlckdhcENvbmZpZy50YXJnZXQsXG4gICAgICAgIHN0YXJ0UGFkZGluZzogc3RhcnRQYWRkaW5nQ29uZmlnLnRhcmdldCxcbiAgICAgICAgZW5kUGFkZGluZzogZW5kUGFkZGluZ0NvbmZpZy50YXJnZXQsXG4gICAgICAgIHRvdGFsU2l6ZTogY2FsY1RhcmdldFNpemUsXG4gICAgICB9O1xuICAgIH1cblxuICAgIGNvbnN0IGNhbGNNaW5TaXplID1cbiAgICAgIGJhclRvdGFsU2l6ZS5taW4gK1xuICAgICAgY2x1c3RlckdhcFRvdGFsU2l6ZS5taW4gK1xuICAgICAgYnVja2V0R2FwVG90YWxTaXplLm1pbiArXG4gICAgICBvdXRlckdhcFRvdGFsU2l6ZS5taW4gK1xuICAgICAgc3RhcnRQYWRkaW5nVG90YWxTaXplLm1pbiArXG4gICAgICBlbmRQYWRkaW5nVG90YWxTaXplLm1pbjtcblxuICAgIC8vTm90ZTogVGhpcyBpcyBvbmx5IGFjdHVhbGx5IGEgbWF4IHNpemUgaWYgYWxsIGVsZW1lbnRzIGhhdmUgYSBkZWZpbmVkIG1heFxuICAgIGNvbnN0IGNhbGNNYXhTaXplID1cbiAgICAgIGJhclRvdGFsU2l6ZS5tYXggK1xuICAgICAgY2x1c3RlckdhcFRvdGFsU2l6ZS5tYXggK1xuICAgICAgYnVja2V0R2FwVG90YWxTaXplLm1heCArXG4gICAgICBvdXRlckdhcFRvdGFsU2l6ZS5tYXggK1xuICAgICAgc3RhcnRQYWRkaW5nVG90YWxTaXplLm1heCArXG4gICAgICBlbmRQYWRkaW5nVG90YWxTaXplLm1heDtcblxuICAgIGlmIChjYWxjTWluU2l6ZSA+IGJvdW5kaW5nRGltZW5zaW9uKSB7XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29uc29sZVxuICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICAnVGhlIHByb3ZpZGVkIG1pbmltdW0gZWxlbWVudCBzaXplcyBtZWFuIHRoZSBjaGFydCBjYW5ub3QgZGlzcGxheSBhdCB0aGlzIHNtYWxsIG9mIGEgc2l6ZScsXG4gICAgICApO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgYmFyU2l6ZTogMCxcbiAgICAgICAgYmFyQ2x1c3RlckdhcDogMCxcbiAgICAgICAgYnVja2V0R2FwOiAwLFxuICAgICAgICBvdXRlckdhcDogMCxcbiAgICAgICAgc3RhcnRQYWRkaW5nOiAwLFxuICAgICAgICBlbmRQYWRkaW5nOiAwLFxuICAgICAgICB0b3RhbFNpemU6IDAsXG4gICAgICAgIHNpemluZ0Vycm9yOiB0cnVlLFxuICAgICAgfTtcbiAgICB9XG4gICAgY29uc3QgY29uZmlnQ2hlY2tzID0gW1xuICAgICAgZ2V0Q2hlY2tpbmdJbmZvRm9yRWxlbWVudENvbmZpZyhiYXJTaXplQ29uZmlnLCBiYXJDb3VudCksXG4gICAgICBnZXRDaGVja2luZ0luZm9Gb3JFbGVtZW50Q29uZmlnKGJhckNsdXN0ZXJHYXBDb25maWcsIGJhckNsdXN0ZXJHYXBDb3VudCksXG4gICAgICBnZXRDaGVja2luZ0luZm9Gb3JFbGVtZW50Q29uZmlnKGJ1Y2tldEdhcENvbmZpZywgYnVja2V0R2FwQ291bnQpLFxuICAgICAgZ2V0Q2hlY2tpbmdJbmZvRm9yRWxlbWVudENvbmZpZyhvdXRlckdhcENvbmZpZywgMiksXG4gICAgICBnZXRDaGVja2luZ0luZm9Gb3JFbGVtZW50Q29uZmlnKHN0YXJ0UGFkZGluZ0NvbmZpZywgMSksXG4gICAgICBnZXRDaGVja2luZ0luZm9Gb3JFbGVtZW50Q29uZmlnKGVuZFBhZGRpbmdDb25maWcsIDEpLFxuICAgIF07XG4gICAgbGV0IGN1cnJTY2FsaW5nRmFjdG9yID0gMTtcbiAgICBpZiAoY2FsY1RhcmdldFNpemUgPiBib3VuZGluZ0RpbWVuc2lvbikge1xuICAgICAgLy9TY2FsaW5nIGRvd25cbiAgICAgIGxldCBmaW5hbFNjYWxpbmdGYWN0b3JGb3VuZCA9IGZhbHNlO1xuICAgICAgd2hpbGUgKCFmaW5hbFNjYWxpbmdGYWN0b3JGb3VuZCkge1xuICAgICAgICBjb25zdCBuZXh0U2NhbGVGYWN0b3JCcmVha3BvaW50ID0gTWF0aC5tYXgoXG4gICAgICAgICAgLi4uY29uZmlnQ2hlY2tzXG4gICAgICAgICAgICAubWFwKGNoZWNrID0+IGNoZWNrLm1pblNjYWxlRmFjdG9yKVxuICAgICAgICAgICAgLmZpbHRlcihcbiAgICAgICAgICAgICAgKHZhbCk6IHZhbCBpcyBudW1iZXIgPT5cbiAgICAgICAgICAgICAgICB2YWwgIT09IHVuZGVmaW5lZCAmJiAhKHZhbCA+PSBjdXJyU2NhbGluZ0ZhY3RvciksXG4gICAgICAgICAgICApLFxuICAgICAgICAgIDAsXG4gICAgICAgICk7XG4gICAgICAgIGNvbnN0IG5ld1NjYWxlRmFjdG9yU2l6ZSA9IGdldFN1bUZvclNjYWxlVmFsdWUoXG4gICAgICAgICAgY29uZmlnQ2hlY2tzLFxuICAgICAgICAgIG5leHRTY2FsZUZhY3RvckJyZWFrcG9pbnQsXG4gICAgICAgICk7XG5cbiAgICAgICAgaWYgKG5ld1NjYWxlRmFjdG9yU2l6ZSA8PSBib3VuZGluZ0RpbWVuc2lvbikge1xuICAgICAgICAgIC8vVGhlcmUncyBhIHNjYWxlIHZhbHVlIHRoYXQnbGwgd29yayBiZXR3ZWVuIHRoZSBjdXJyIGFuZCBuZXcgdmFsdWVzXG4gICAgICAgICAgLy9UaGVzZSBhcmUgdGhlIHZhbHVlcyB0aGF0J2xsIGp1c3QgYmUgYXQgdGhlaXIgbWluXG4gICAgICAgICAgY29uc3Qgbm9uU2NhbGVhYmxlVmFsdWVzID0gY29uZmlnQ2hlY2tzLmZpbHRlcihcbiAgICAgICAgICAgIGNoZWNrID0+XG4gICAgICAgICAgICAgIGNoZWNrLm1pblNjYWxlRmFjdG9yICYmIGNoZWNrLm1pblNjYWxlRmFjdG9yID49IGN1cnJTY2FsaW5nRmFjdG9yLFxuICAgICAgICAgICk7XG4gICAgICAgICAgLy9UaGVzZSBhcmUgdGhlIHZhbHVlcyB0aGF0IGNhbiBzdGlsbCBiZSBzY2FsZWQgZG93blxuICAgICAgICAgIGNvbnN0IHNjYWxlYWJsZVZhbHVlcyA9IGNvbmZpZ0NoZWNrcy5maWx0ZXIoXG4gICAgICAgICAgICBjaGVjayA9PlxuICAgICAgICAgICAgICAhY2hlY2subWluU2NhbGVGYWN0b3IgfHwgY2hlY2subWluU2NhbGVGYWN0b3IgPCBjdXJyU2NhbGluZ0ZhY3RvcixcbiAgICAgICAgICApO1xuICAgICAgICAgIGNvbnN0IHdvcmtpbmdTcGFjZSA9XG4gICAgICAgICAgICBib3VuZGluZ0RpbWVuc2lvbiAtXG4gICAgICAgICAgICBnZXRTdW1Gb3JTY2FsZVZhbHVlKG5vblNjYWxlYWJsZVZhbHVlcywgY3VyclNjYWxpbmdGYWN0b3IpO1xuICAgICAgICAgIGN1cnJTY2FsaW5nRmFjdG9yID1cbiAgICAgICAgICAgIHdvcmtpbmdTcGFjZSAvIGdldFN1bUZvclNjYWxlVmFsdWUoc2NhbGVhYmxlVmFsdWVzLCAxKTtcbiAgICAgICAgICBmaW5hbFNjYWxpbmdGYWN0b3JGb3VuZCA9IHRydWU7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy9PbmUgb2YgdGhlIGVsZW1lbnRzIGlzIGhpdHRpbmcgdGhlaXIgbWluU2NhbGVGYWN0b3IsIHNvIGZvciBzaW1wbGljaXR5IHdlJ2xsIGp1c3QgZ28gYWdhaW5cbiAgICAgICAgICBjdXJyU2NhbGluZ0ZhY3RvciA9IG5leHRTY2FsZUZhY3RvckJyZWFrcG9pbnQ7XG5cbiAgICAgICAgICAvL0p1c3QgaW4gY2FzZSwgdGhvdWdoIHByZXZpb3VzIGNoZWNrcyBzaG91bGQgbWFrZSB0aGlzIGltcG9zc2libGVcbiAgICAgICAgICBpZiAoY3VyclNjYWxpbmdGYWN0b3IgPT09IDApIHtcbiAgICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gICAgICAgICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgICAgICAgICdUaGUgZ2l2ZW4gc2l6ZSBjYW5ub3QgY29udGFpbiB0aGUgZml4ZWQgc2l6ZXMgZ2l2ZW4gZm9yIHRoZSBlbGVtZW50cycsXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgYmFyU2l6ZTogMCxcbiAgICAgICAgICAgICAgYmFyQ2x1c3RlckdhcDogMCxcbiAgICAgICAgICAgICAgYnVja2V0R2FwOiAwLFxuICAgICAgICAgICAgICBvdXRlckdhcDogMCxcbiAgICAgICAgICAgICAgc3RhcnRQYWRkaW5nOiAwLFxuICAgICAgICAgICAgICBlbmRQYWRkaW5nOiAwLFxuICAgICAgICAgICAgICB0b3RhbFNpemU6IDAsXG4gICAgICAgICAgICAgIHNpemluZ0Vycm9yOiB0cnVlLFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgLy9DaGVja2luZyB0byBzZWUgaWYgYWxsIGVsZW1lbnRzIGhhdmUgYSBkZWZpbmVkIG1heFxuICAgICAgY29uc3QgbWF4aW11bVNpemVQb3NzaWJsZSA9XG4gICAgICAgIGNvbmZpZ0NoZWNrcy5maWx0ZXIoY2hlY2sgPT4gY2hlY2subWF4U2NhbGVGYWN0b3IgPT09IHVuZGVmaW5lZClcbiAgICAgICAgICAubGVuZ3RoID09PSAwO1xuICAgICAgLy9JZiBhbGwgZWxlbWVudHMgaGF2ZSBhIGRlZmluZWQgbWF4LCBhbmQgdGhhdCBtYXggaXMgbGVzcyB0aGFuIHRoZSBzaXplIHdlJ3JlIHRyeWluZyB0byBncm93IHRvLCBpdCdzIGltcG9zc2libGVcbiAgICAgIGlmIChtYXhpbXVtU2l6ZVBvc3NpYmxlICYmIGNhbGNNYXhTaXplIDwgYm91bmRpbmdEaW1lbnNpb24pIHtcbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICAgICdUaGUgcHJvdmlkZWQgbWF4aW11bSBlbGVtZW50IHdpZHRocyBtZWFuIHRoZSBjaGFydCBjYW5ub3QgZGlzcGxheSBhdCB0aGlzIGxhcmdlIG9mIGEgc2l6ZScsXG4gICAgICAgICk7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgYmFyU2l6ZTogMCxcbiAgICAgICAgICBiYXJDbHVzdGVyR2FwOiAwLFxuICAgICAgICAgIGJ1Y2tldEdhcDogMCxcbiAgICAgICAgICBvdXRlckdhcDogMCxcbiAgICAgICAgICBzdGFydFBhZGRpbmc6IDAsXG4gICAgICAgICAgZW5kUGFkZGluZzogMCxcbiAgICAgICAgICB0b3RhbFNpemU6IDAsXG4gICAgICAgICAgc2l6aW5nRXJyb3I6IHRydWUsXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICAvL1NjYWxpbmcgdXBcbiAgICAgIGxldCBmaW5hbFNjYWxpbmdGYWN0b3JGb3VuZCA9IGZhbHNlO1xuICAgICAgd2hpbGUgKCFmaW5hbFNjYWxpbmdGYWN0b3JGb3VuZCkge1xuICAgICAgICBjb25zdCBuZXh0U2NhbGVGYWN0b3JCcmVha3BvaW50ID0gTWF0aC5taW4oXG4gICAgICAgICAgLi4uY29uZmlnQ2hlY2tzXG4gICAgICAgICAgICAubWFwKGNoZWNrID0+IGNoZWNrLm1heFNjYWxlRmFjdG9yKVxuICAgICAgICAgICAgLmZpbHRlcihcbiAgICAgICAgICAgICAgKHZhbCk6IHZhbCBpcyBudW1iZXIgPT5cbiAgICAgICAgICAgICAgICB2YWwgIT09IHVuZGVmaW5lZCAmJiAhKHZhbCA8PSBjdXJyU2NhbGluZ0ZhY3RvciksXG4gICAgICAgICAgICApLFxuICAgICAgICApO1xuICAgICAgICBjb25zdCBuZXdTY2FsZUZhY3RvclNpemUgPSBnZXRTdW1Gb3JTY2FsZVZhbHVlKFxuICAgICAgICAgIGNvbmZpZ0NoZWNrcyxcbiAgICAgICAgICBuZXh0U2NhbGVGYWN0b3JCcmVha3BvaW50LFxuICAgICAgICApO1xuXG4gICAgICAgIGlmIChcbiAgICAgICAgICBuZXdTY2FsZUZhY3RvclNpemUgPj0gYm91bmRpbmdEaW1lbnNpb24gfHxcbiAgICAgICAgICBuZXh0U2NhbGVGYWN0b3JCcmVha3BvaW50ID09PSBJbmZpbml0eVxuICAgICAgICApIHtcbiAgICAgICAgICAvL1RoZXJlJ3MgYSBzY2FsZSB2YWx1ZSB0aGF0J2xsIHdvcmsgYmV0d2VlbiB0aGUgY3VyciBhbmQgbmV3IHZhbHVlc1xuICAgICAgICAgIC8vVGhlc2UgYXJlIHRoZSB2YWx1ZXMgdGhhdCdsbCBqdXN0IGJlIGF0IHRoZWlyIG1heFxuICAgICAgICAgIGNvbnN0IG5vblNjYWxlYWJsZVZhbHVlcyA9IGNvbmZpZ0NoZWNrcy5maWx0ZXIoXG4gICAgICAgICAgICBjaGVjayA9PlxuICAgICAgICAgICAgICBjaGVjay5tYXhTY2FsZUZhY3RvciAmJiBjaGVjay5tYXhTY2FsZUZhY3RvciA8PSBjdXJyU2NhbGluZ0ZhY3RvcixcbiAgICAgICAgICApO1xuICAgICAgICAgIC8vVGhlc2UgYXJlIHRoZSB2YWx1ZXMgdGhhdCBjYW4gc3RpbGwgYmUgc2NhbGVkIHVwXG4gICAgICAgICAgY29uc3Qgc2NhbGVhYmxlVmFsdWVzID0gY29uZmlnQ2hlY2tzLmZpbHRlcihcbiAgICAgICAgICAgIGNoZWNrID0+XG4gICAgICAgICAgICAgICFjaGVjay5tYXhTY2FsZUZhY3RvciB8fCBjaGVjay5tYXhTY2FsZUZhY3RvciA+IGN1cnJTY2FsaW5nRmFjdG9yLFxuICAgICAgICAgICk7XG4gICAgICAgICAgY29uc3Qgd29ya2luZ1NwYWNlID1cbiAgICAgICAgICAgIGJvdW5kaW5nRGltZW5zaW9uIC1cbiAgICAgICAgICAgIGdldFN1bUZvclNjYWxlVmFsdWUobm9uU2NhbGVhYmxlVmFsdWVzLCBjdXJyU2NhbGluZ0ZhY3Rvcik7XG4gICAgICAgICAgY3VyclNjYWxpbmdGYWN0b3IgPVxuICAgICAgICAgICAgd29ya2luZ1NwYWNlIC8gZ2V0U3VtRm9yU2NhbGVWYWx1ZShzY2FsZWFibGVWYWx1ZXMsIDEpO1xuICAgICAgICAgIGZpbmFsU2NhbGluZ0ZhY3RvckZvdW5kID0gdHJ1ZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAvL09uZSBvZiB0aGUgZWxlbWVudHMgaXMgaGl0dGluZyB0aGVpciBtYXhTY2FsZUZhY3Rvciwgc28gZm9yIHNpbXBsaWNpdHkgd2UnbGwganVzdCBnbyBhZ2FpblxuICAgICAgICAgIGN1cnJTY2FsaW5nRmFjdG9yID0gbmV4dFNjYWxlRmFjdG9yQnJlYWtwb2ludDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICBjb25zdCBiYXJTaXplID0gZ2V0U2NhbGVkRWxlbWVudFNpemUoYmFyU2l6ZUNvbmZpZywgY3VyclNjYWxpbmdGYWN0b3IpO1xuICAgIGNvbnN0IGJhckNsdXN0ZXJHYXAgPSBnZXRTY2FsZWRFbGVtZW50U2l6ZShcbiAgICAgIGJhckNsdXN0ZXJHYXBDb25maWcsXG4gICAgICBjdXJyU2NhbGluZ0ZhY3RvcixcbiAgICApO1xuICAgIGNvbnN0IGJ1Y2tldEdhcCA9IGdldFNjYWxlZEVsZW1lbnRTaXplKGJ1Y2tldEdhcENvbmZpZywgY3VyclNjYWxpbmdGYWN0b3IpO1xuICAgIHJldHVybiB7XG4gICAgICBiYXJTaXplLFxuICAgICAgYmFyQ2x1c3RlckdhcCxcbiAgICAgIGJ1Y2tldEdhcCxcbiAgICAgIG91dGVyR2FwOiBnZXRTY2FsZWRFbGVtZW50U2l6ZShvdXRlckdhcENvbmZpZywgY3VyclNjYWxpbmdGYWN0b3IpLFxuICAgICAgc3RhcnRQYWRkaW5nOiBnZXRTY2FsZWRFbGVtZW50U2l6ZShzdGFydFBhZGRpbmdDb25maWcsIGN1cnJTY2FsaW5nRmFjdG9yKSxcbiAgICAgIGVuZFBhZGRpbmc6IGdldFNjYWxlZEVsZW1lbnRTaXplKGVuZFBhZGRpbmdDb25maWcsIGN1cnJTY2FsaW5nRmFjdG9yKSxcbiAgICAgIHRvdGFsU2l6ZTogYm91bmRpbmdEaW1lbnNpb24sXG4gICAgfTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGNhbGN1bGF0ZURhdGFBeGlzVmFsdWVzKFxuICAgIGNvbmZpZzogQ29uZmlnLFxuICAgIHNjYWxpbmdDb25maWc6IE5vbkVsZW1lbnRTY2FsaW5nQ29uZmlnLFxuICAgIGVsZW1lbnRTY2FsZXM6IFBhcnRpYWxFbGVtZW50U2NhbGluZ0NvbmZpZyB8IHVuZGVmaW5lZCxcbiAgICBkZWZhdWx0U2l6aW5nOiBGdWxsRWxlbWVudFNjYWxpbmdDb25maWcsXG4gICAgZGltZW5zaW9uczogRGltZW5zaW9ucyxcbiAgICBkYXRhOiBQcm9jZXNzRGF0YSxcbiAgICBwaXBlVHJhbnNmb3JtOiAoKHZhbHVlOiBudW1iZXIsIGlzU2Vjb25kYXJ5OiBib29sZWFuKSA9PiBzdHJpbmcpIHwgbnVsbCxcbiAgICBkYXRlRm9ybWF0OiAoKGRhdGU6IERhdGUpID0+IHN0cmluZykgfCBudWxsLFxuICApOiB7XG4gICAgc3RhcnRQYWRkaW5nOiBudW1iZXI7XG4gICAgZW5kUGFkZGluZzogbnVtYmVyO1xuICAgIGxlZnRCdWNrZXRMYWJlbDogbnVtYmVyO1xuICAgIGRhdGFMYWJlbFRleHRTaXplOiBudW1iZXI7XG4gICAgZGF0YUxhYmVsUGFkZGluZzogbnVtYmVyO1xuICAgIGZvbnRTaXplOiBudW1iZXI7XG4gICAgc2l6ZUZvckRhdGE6IG51bWJlcjtcbiAgICB0b3RhbFNpemU6IG51bWJlcjtcbiAgICBidWNrZXRMYWJlbFRleHRTaXplOiBudW1iZXI7XG4gICAgc2l6aW5nRXJyb3I/OiBib29sZWFuO1xuICB9IHtcbiAgICBjb25zdCBjaGFydERhdGFEaXJlY3Rpb24gPSBnZXRDaGFydERhdGFEaXJlY3Rpb24oY29uZmlnKTtcbiAgICBjb25zdCBib3VuZGluZ0RpbWVuc2lvbiA9XG4gICAgICBjaGFydERhdGFEaXJlY3Rpb24gPT09ICdob3Jpem9udGFsJ1xuICAgICAgICA/IGRpbWVuc2lvbnMud2lkdGhcbiAgICAgICAgOiBkaW1lbnNpb25zLmhlaWdodDtcbiAgICBjb25zdCBheGlzU2NhbGUgPVxuICAgICAgY2hhcnREYXRhRGlyZWN0aW9uID09PSAnaG9yaXpvbnRhbCdcbiAgICAgICAgPyBzY2FsaW5nQ29uZmlnLmhvcml6b250YWxBeGlzU2NhbGVcbiAgICAgICAgOiBzY2FsaW5nQ29uZmlnLnZlcnRpY2FsQXhpc1NjYWxlO1xuXG4gICAgY29uc3Qgc3RhcnRQYWRkaW5nQ29uZmlnID0gZ2V0RWxlbWVudFNjYWxpbmdJbmZvKFxuICAgICAgZWxlbWVudFNjYWxlcyxcbiAgICAgIGRlZmF1bHRTaXppbmcsXG4gICAgICBjaGFydERhdGFEaXJlY3Rpb24gPT09ICdob3Jpem9udGFsJyA/ICdsZWZ0UGFkZGluZycgOiAndG9wUGFkZGluZycsXG4gICAgKTtcbiAgICBjb25zdCBlbmRQYWRkaW5nQ29uZmlnID0gZ2V0RWxlbWVudFNjYWxpbmdJbmZvKFxuICAgICAgZWxlbWVudFNjYWxlcyxcbiAgICAgIGRlZmF1bHRTaXppbmcsXG4gICAgICBjaGFydERhdGFEaXJlY3Rpb24gPT09ICdob3Jpem9udGFsJyA/ICdyaWdodFBhZGRpbmcnIDogJ2JvdHRvbVBhZGRpbmcnLFxuICAgICk7XG4gICAgY29uc3QgbGVmdExhYmVsQ29uZmlnID0gZ2V0RWxlbWVudFNjYWxpbmdJbmZvKFxuICAgICAgZWxlbWVudFNjYWxlcyxcbiAgICAgIGRlZmF1bHRTaXppbmcsXG4gICAgICAnbGVmdEJ1Y2tldExhYmVsJyxcbiAgICApO1xuICAgIGNvbnN0IGRhdGFMYWJlbFBhZGRpbmdDb25maWcgPSBnZXRFbGVtZW50U2NhbGluZ0luZm8oXG4gICAgICBlbGVtZW50U2NhbGVzLFxuICAgICAgZGVmYXVsdFNpemluZyxcbiAgICAgICdkYXRhTGFiZWxQYWRkaW5nJyxcbiAgICApO1xuICAgIGNvbnN0IGZvbnRTaXplQ29uZmlnID0gZ2V0RWxlbWVudFNjYWxpbmdJbmZvKFxuICAgICAgZWxlbWVudFNjYWxlcyxcbiAgICAgIGRlZmF1bHRTaXppbmcsXG4gICAgICAnZm9udFNpemUnLFxuICAgICk7XG4gICAgY29uc3QgZm9udFNpemUgPSBmb250U2l6ZUNvbmZpZy50YXJnZXQ7XG4gICAgY29uc3QgZGF0YUxhYmVsVGV4dFNpemluZyA9IGdldERhdGFMYWJlbFNpemUoZGF0YSwgcGlwZVRyYW5zZm9ybSwgZm9udFNpemUpO1xuICAgIC8vV2UgYWx3YXlzIGNhbGN1bGF0ZSBhbmQgcmV0dXJuIGRhdGFMYWJlbFRleHRTaXplLCBzaW5jZSBpdCdzIGFsc28gdXNlZCBmb3IgZGV0ZXJtaW5nIGF4aXMgbGFiZWwgc2l6ZVxuICAgIGNvbnN0IGRhdGFMYWJlbFRleHRTaXplID1cbiAgICAgIGNoYXJ0RGF0YURpcmVjdGlvbiA9PT0gJ2hvcml6b250YWwnXG4gICAgICAgID8gZGF0YUxhYmVsVGV4dFNpemluZy5ob3Jpem9udGFsXG4gICAgICAgIDogZGF0YUxhYmVsVGV4dFNpemluZy52ZXJ0aWNhbDtcbiAgICBjb25zdCBkYXRhTGFiZWxGaXhlZFNpemUgPVxuICAgICAgZGF0YUxhYmVsVGV4dFNpemUgKiBnZXREYXRhTGFiZWxTaXppbmdDb3VudChkYXRhLCBjb25maWcpLnRvdGFsO1xuICAgIGNvbnN0IGJ1Y2tldExhYmVsVGV4dFNpemUgPSBnZXRCdWNrZXRMYWJlbFNpemUoZGF0YSwgZm9udFNpemUsIGRhdGVGb3JtYXQpO1xuICAgIC8vRmxvdyBjaGFydHMgaGF2ZSBhIGRhdGEgbGFiZWwgYWJvdmUgZWFjaCBzdWItYnVja2V0XG4gICAgY29uc3QgZmxvd0xhYmVsU2l6ZSA9IGRhdGFMYWJlbFRleHRTaXplICsgZGF0YUxhYmVsUGFkZGluZ0NvbmZpZy50YXJnZXQ7XG5cbiAgICBjb25zdCBzdGFydFBhZGRpbmdUb3RhbFNpemUgPSBkZXRlcm1pbmVQb3NzaWJsZVNpemVzT2ZFbGVtZW50KFxuICAgICAgc3RhcnRQYWRkaW5nQ29uZmlnLFxuICAgICAgMSxcbiAgICApO1xuICAgIGNvbnN0IGVuZFBhZGRpbmdUb3RhbFNpemUgPSBkZXRlcm1pbmVQb3NzaWJsZVNpemVzT2ZFbGVtZW50KFxuICAgICAgZW5kUGFkZGluZ0NvbmZpZyxcbiAgICAgIDEsXG4gICAgKTtcbiAgICBjb25zdCBkYXRhTGFiZWxQYWRkaW5nVG90YWxTaXplID0gZGV0ZXJtaW5lUG9zc2libGVTaXplc09mRWxlbWVudChcbiAgICAgIGRhdGFMYWJlbFBhZGRpbmdDb25maWcsXG4gICAgICBnZXREYXRhTGFiZWxTaXppbmdDb3VudChkYXRhLCBjb25maWcpLnRvdGFsLFxuICAgICk7XG5cbiAgICBsZXQgbGVmdEJ1Y2tldExhYmVsQWN0dWFsU2l6ZSA9IGxlZnRMYWJlbENvbmZpZy50YXJnZXQ7XG4gICAgaWYgKGNoYXJ0RGF0YURpcmVjdGlvbiA9PT0gJ2hvcml6b250YWwnICYmIGRhdGEudHlwZSA9PT0gJ2xhYmVsZWQnKSB7XG4gICAgICAvL0ZvciBob3Jpem9udGFsIGJhcnMsIHRoZSBzdGFydCBwYWRkaW5nIHdpbGwgc2NhbGUgYmFzZWQgb24gdGhlIGJ1Y2tldCBsYWJlbHNcbiAgICAgIGNvbnN0IGxvbmdlc3RMYWJlbExlbmd0aCA9XG4gICAgICAgIE1hdGgubWF4KC4uLmRhdGEueC5tYXAoeCA9PiB4LmxhYmVsLmxlbmd0aCkpICpcbiAgICAgICAgKFdJRFRIX1BFUl9MRVRURVIgKiAoZm9udFNpemUgLyBERUZBVUxUX0ZPTlRfU0laRSkpO1xuICAgICAgY29uc3QgbWluTGVuZ3RoID0gbGVmdExhYmVsQ29uZmlnLm1pblxuICAgICAgICA/IE1hdGgubWF4KGxvbmdlc3RMYWJlbExlbmd0aCwgbGVmdExhYmVsQ29uZmlnLm1pbilcbiAgICAgICAgOiBsb25nZXN0TGFiZWxMZW5ndGg7XG4gICAgICBsZWZ0QnVja2V0TGFiZWxBY3R1YWxTaXplID0gbGVmdExhYmVsQ29uZmlnLm1heFxuICAgICAgICA/IE1hdGgubWluKG1pbkxlbmd0aCwgbGVmdExhYmVsQ29uZmlnLm1heClcbiAgICAgICAgOiBsb25nZXN0TGFiZWxMZW5ndGg7XG4gICAgfVxuXG4gICAgbGV0IGZpeGVkU2l6ZVZhbHVlID1cbiAgICAgIGxlZnRCdWNrZXRMYWJlbEFjdHVhbFNpemUgK1xuICAgICAgZGF0YUxhYmVsRml4ZWRTaXplICtcbiAgICAgIHN0YXJ0UGFkZGluZ1RvdGFsU2l6ZS50YXJnZXQgK1xuICAgICAgZW5kUGFkZGluZ1RvdGFsU2l6ZS50YXJnZXQgK1xuICAgICAgZGF0YUxhYmVsUGFkZGluZ1RvdGFsU2l6ZS50YXJnZXQ7XG4gICAgaWYgKGZpeGVkU2l6ZVZhbHVlID4gYm91bmRpbmdEaW1lbnNpb24pIHtcbiAgICAgIC8vU2VlIGlmIGZ1cnRoZXIgdHJ1bmNhdGluZyB0aGUgbGFiZWwgY2FuIGhlbHBcbiAgICAgIGlmIChcbiAgICAgICAgbGVmdExhYmVsQ29uZmlnLm1pbiAmJlxuICAgICAgICBmaXhlZFNpemVWYWx1ZSAtIGJvdW5kaW5nRGltZW5zaW9uIDxcbiAgICAgICAgICBsZWZ0QnVja2V0TGFiZWxBY3R1YWxTaXplIC0gbGVmdExhYmVsQ29uZmlnLm1pblxuICAgICAgKSB7XG4gICAgICAgIGxlZnRCdWNrZXRMYWJlbEFjdHVhbFNpemUgPVxuICAgICAgICAgIGxlZnRCdWNrZXRMYWJlbEFjdHVhbFNpemUgLSAoZml4ZWRTaXplVmFsdWUgLSBib3VuZGluZ0RpbWVuc2lvbik7XG4gICAgICAgIGZpeGVkU2l6ZVZhbHVlID1cbiAgICAgICAgICBsZWZ0QnVja2V0TGFiZWxBY3R1YWxTaXplICtcbiAgICAgICAgICBzdGFydFBhZGRpbmdUb3RhbFNpemUudGFyZ2V0ICtcbiAgICAgICAgICBlbmRQYWRkaW5nVG90YWxTaXplLnRhcmdldCArXG4gICAgICAgICAgZGF0YUxhYmVsUGFkZGluZ1RvdGFsU2l6ZS50YXJnZXQ7XG4gICAgICB9IGVsc2UgaWYgKFxuICAgICAgICBheGlzU2NhbGUgIT09ICdncm93JyAmJlxuICAgICAgICAoYXhpc1NjYWxlICE9PSAnbm8tc2NhbGUnIHx8IHNjYWxpbmdDb25maWcuZGF0YVNjYWxlLnR5cGUgPT09ICdmaXQnKVxuICAgICAgKSB7XG4gICAgICAgIC8vR3Jvd2luZyBhbmQgbm9uLWZpdHRpbmcgZGF0YSBheGVzIGNhbiBzY3JvbGwgaW5zdGVhZFxuICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29uc29sZVxuICAgICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgICAgJ1RoZSBwcm92aWRlZCBlbGVtZW50IHNpemVzIG1lYW4gdGhlIGNoYXJ0IGNhbm5vdCBkaXNwbGF5IGF0IHRoaXMgc21hbGwgb2YgYSBzaXplJyxcbiAgICAgICAgKTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBzdGFydFBhZGRpbmc6IDAsXG4gICAgICAgICAgZW5kUGFkZGluZzogMCxcbiAgICAgICAgICBsZWZ0QnVja2V0TGFiZWw6IDAsXG4gICAgICAgICAgZGF0YUxhYmVsVGV4dFNpemU6IDAsXG4gICAgICAgICAgZGF0YUxhYmVsUGFkZGluZzogMCxcbiAgICAgICAgICBmb250U2l6ZTogMCxcbiAgICAgICAgICBzaXplRm9yRGF0YTogMCxcbiAgICAgICAgICB0b3RhbFNpemU6IDAsXG4gICAgICAgICAgYnVja2V0TGFiZWxUZXh0U2l6ZTogMCxcbiAgICAgICAgICBzaXppbmdFcnJvcjogdHJ1ZSxcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKFxuICAgICAgYXhpc1NjYWxlID09PSAnc2NhbGUtdG8tZml0JyB8fFxuICAgICAgYXhpc1NjYWxlID09PSAnZ3JvdycgfHxcbiAgICAgIGF4aXNTY2FsZSA9PT0gJ3NocmluaycgfHxcbiAgICAgIHNjYWxpbmdDb25maWcuZGF0YVNjYWxlLnR5cGUgPT09ICdmaXQnXG4gICAgKSB7XG4gICAgICAvL0EgZ3Jvd2luZyBkYXRhIGF4aXMgc2Nyb2xscyByYXRoZXIgdGhhbiBzcXVlZXppbmcgdGhlIGRhdGEgYmVsb3cgaXRzIG1pbmltdW0gc2l6ZVxuICAgICAgY29uc3QgYXZhaWxhYmxlU2l6ZSA9XG4gICAgICAgIGF4aXNTY2FsZSA9PT0gJ2dyb3cnXG4gICAgICAgICAgPyBNYXRoLm1heChcbiAgICAgICAgICAgICAgYm91bmRpbmdEaW1lbnNpb24gLSBmaXhlZFNpemVWYWx1ZSxcbiAgICAgICAgICAgICAgZ2V0TWluaW11bUdyb3duRGF0YVNpemUoXG4gICAgICAgICAgICAgICAgZGF0YSxcbiAgICAgICAgICAgICAgICBjb25maWcsXG4gICAgICAgICAgICAgICAgYm91bmRpbmdEaW1lbnNpb24sXG4gICAgICAgICAgICAgICAgZmxvd0xhYmVsU2l6ZSxcbiAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgIClcbiAgICAgICAgICA6IGJvdW5kaW5nRGltZW5zaW9uIC0gZml4ZWRTaXplVmFsdWU7XG4gICAgICBjb25zdCBzaXplRm9yRGF0YSA9IGdldEZpdHRlZERhdGFTaXplKFxuICAgICAgICBkYXRhLFxuICAgICAgICBjb25maWcsXG4gICAgICAgIGF2YWlsYWJsZVNpemUsXG4gICAgICAgIGZsb3dMYWJlbFNpemUsXG4gICAgICApO1xuICAgICAgaWYgKHNpemVGb3JEYXRhID09PSBudWxsKSB7XG4gICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gICAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgICAnVGhlIHByb3ZpZGVkIG1pbmltdW0gZGF0YSBlbGVtZW50IHNpemUgbWVhbnMgdGhlIGNoYXJ0IGNhbm5vdCBkaXNwbGF5IGF0IHRoaXMgc21hbGwgb2YgYSBzaXplJyxcbiAgICAgICAgKTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBzdGFydFBhZGRpbmc6IDAsXG4gICAgICAgICAgZW5kUGFkZGluZzogMCxcbiAgICAgICAgICBsZWZ0QnVja2V0TGFiZWw6IDAsXG4gICAgICAgICAgZGF0YUxhYmVsVGV4dFNpemU6IDAsXG4gICAgICAgICAgZGF0YUxhYmVsUGFkZGluZzogMCxcbiAgICAgICAgICBmb250U2l6ZTogMCxcbiAgICAgICAgICBzaXplRm9yRGF0YTogMCxcbiAgICAgICAgICB0b3RhbFNpemU6IDAsXG4gICAgICAgICAgYnVja2V0TGFiZWxUZXh0U2l6ZTogMCxcbiAgICAgICAgICBzaXppbmdFcnJvcjogdHJ1ZSxcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICAgIHJldHVybiB7XG4gICAgICAgIHN0YXJ0UGFkZGluZzogc3RhcnRQYWRkaW5nQ29uZmlnLnRhcmdldCxcbiAgICAgICAgZW5kUGFkZGluZzogZW5kUGFkZGluZ0NvbmZpZy50YXJnZXQsXG4gICAgICAgIGxlZnRCdWNrZXRMYWJlbDogbGVmdEJ1Y2tldExhYmVsQWN0dWFsU2l6ZSxcbiAgICAgICAgZGF0YUxhYmVsVGV4dFNpemUsXG4gICAgICAgIGRhdGFMYWJlbFBhZGRpbmc6IGRhdGFMYWJlbFBhZGRpbmdDb25maWcudGFyZ2V0LFxuICAgICAgICBmb250U2l6ZTogZm9udFNpemVDb25maWcudGFyZ2V0LFxuICAgICAgICBzaXplRm9yRGF0YSxcbiAgICAgICAgdG90YWxTaXplOiBmaXhlZFNpemVWYWx1ZSArIGF2YWlsYWJsZVNpemUsXG4gICAgICAgIGJ1Y2tldExhYmVsVGV4dFNpemUsXG4gICAgICB9O1xuICAgIH1cblxuICAgIGNvbnN0IHtcbiAgICAgIHByaW1hcnlEYXRhTWluLFxuICAgICAgcHJpbWFyeURhdGFNYXgsXG4gICAgICBzY2FsZURvbWFpbk11bHRpcGxlRm9yTWF4LFxuICAgICAgc2NhbGVEb21haW5NdWx0aXBsZUZvck5lZyxcbiAgICB9ID0gY2FsY0RhdGFTY2FsaW5nVmFsdWVzKGRhdGEsIGNvbmZpZyk7XG5cbiAgICBjb25zdCBlZmZlY3RpdmVQcmltYXJ5TWF4Rm9yU2NhbGluZyA9XG4gICAgICBwcmltYXJ5RGF0YU1heCAqIHNjYWxlRG9tYWluTXVsdGlwbGVGb3JNYXg7XG4gICAgY29uc3QgZWZmZWN0aXZlUHJpbWFyeU1pbkZvclNjYWxpbmcgPVxuICAgICAgcHJpbWFyeURhdGFNaW4gPCAwID8gcHJpbWFyeURhdGFNaW4gKiBzY2FsZURvbWFpbk11bHRpcGxlRm9yTmVnIDogMDtcblxuICAgIGlmIChzY2FsaW5nQ29uZmlnLmRhdGFTY2FsZS50eXBlID09PSAnbWF4Jykge1xuICAgICAgY29uc3QgZGF0YVNpemUgPVxuICAgICAgICBzY2FsaW5nQ29uZmlnLmRhdGFTY2FsZS52YWx1ZSAqXG4gICAgICAgICgoZWZmZWN0aXZlUHJpbWFyeU1heEZvclNjYWxpbmcgLSBlZmZlY3RpdmVQcmltYXJ5TWluRm9yU2NhbGluZykgL1xuICAgICAgICAgIGVmZmVjdGl2ZVByaW1hcnlNYXhGb3JTY2FsaW5nKTtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHN0YXJ0UGFkZGluZzogc3RhcnRQYWRkaW5nQ29uZmlnLnRhcmdldCxcbiAgICAgICAgZW5kUGFkZGluZzogZW5kUGFkZGluZ0NvbmZpZy50YXJnZXQsXG4gICAgICAgIGxlZnRCdWNrZXRMYWJlbDogbGVmdEJ1Y2tldExhYmVsQWN0dWFsU2l6ZSxcbiAgICAgICAgZGF0YUxhYmVsVGV4dFNpemUsXG4gICAgICAgIGRhdGFMYWJlbFBhZGRpbmc6IGRhdGFMYWJlbFBhZGRpbmdDb25maWcudGFyZ2V0LFxuICAgICAgICBmb250U2l6ZTogZm9udFNpemVDb25maWcudGFyZ2V0LFxuICAgICAgICBzaXplRm9yRGF0YTogZGF0YVNpemUsXG4gICAgICAgIHRvdGFsU2l6ZTpcbiAgICAgICAgICBnZXRTY2FsZWREYXRhVG90YWxTaXplKGRhdGEsIGNvbmZpZywgZGF0YVNpemUsIGZsb3dMYWJlbFNpemUpICtcbiAgICAgICAgICBmaXhlZFNpemVWYWx1ZSxcbiAgICAgICAgYnVja2V0TGFiZWxUZXh0U2l6ZSxcbiAgICAgIH07XG4gICAgfVxuXG4gICAgY29uc3QgZGF0YVNpemUgPVxuICAgICAgKChlZmZlY3RpdmVQcmltYXJ5TWF4Rm9yU2NhbGluZyAtIGVmZmVjdGl2ZVByaW1hcnlNaW5Gb3JTY2FsaW5nKSAvXG4gICAgICAgIHNjYWxpbmdDb25maWcuZGF0YVNjYWxlLnJhdGlvLnZhbHVlKSAqXG4gICAgICBzY2FsaW5nQ29uZmlnLmRhdGFTY2FsZS5yYXRpby5weDtcbiAgICByZXR1cm4ge1xuICAgICAgc3RhcnRQYWRkaW5nOiBzdGFydFBhZGRpbmdDb25maWcudGFyZ2V0LFxuICAgICAgZW5kUGFkZGluZzogZW5kUGFkZGluZ0NvbmZpZy50YXJnZXQsXG4gICAgICBsZWZ0QnVja2V0TGFiZWw6IGxlZnRCdWNrZXRMYWJlbEFjdHVhbFNpemUsXG4gICAgICBkYXRhTGFiZWxUZXh0U2l6ZSxcbiAgICAgIGRhdGFMYWJlbFBhZGRpbmc6IGRhdGFMYWJlbFBhZGRpbmdDb25maWcudGFyZ2V0LFxuICAgICAgZm9udFNpemU6IGZvbnRTaXplQ29uZmlnLnRhcmdldCxcbiAgICAgIHNpemVGb3JEYXRhOiBkYXRhU2l6ZSxcbiAgICAgIHRvdGFsU2l6ZTpcbiAgICAgICAgZ2V0U2NhbGVkRGF0YVRvdGFsU2l6ZShkYXRhLCBjb25maWcsIGRhdGFTaXplLCBmbG93TGFiZWxTaXplKSArXG4gICAgICAgIGZpeGVkU2l6ZVZhbHVlLFxuICAgICAgYnVja2V0TGFiZWxUZXh0U2l6ZSxcbiAgICB9O1xuICB9XG5cbiAgLy9UaGUgbGVhc3Qgc3BhY2UgYSBncm93aW5nIGRhdGEgYXhpcyBnaXZlcyB0aGUgZGF0YTogYSBwb3J0aW9uIG9mIHRoZSBwcm92aWRlZCBzaXplLCBvbiB0b3Agb2YgdGhlIHNwYWNlIHRoYXRcbiAgLy8gZWxlbWVudHMgZW5sYXJnZWQgdG8gdGhlIG1pbmltdW0gc2l6ZSBuZWVkIChzbyB0aGUgZGF0YSBzdGF5cyBwcm9wb3J0aW9uYWwgcmF0aGVyIHRoYW4gYWxsIGJlaW5nIHRoZSBtaW5pbXVtKVxuICBmdW5jdGlvbiBnZXRNaW5pbXVtR3Jvd25EYXRhU2l6ZShcbiAgICBkYXRhOiBQcm9jZXNzRGF0YSxcbiAgICBjb25maWc6IENvbmZpZyxcbiAgICBib3VuZGluZ0RpbWVuc2lvbjogbnVtYmVyLFxuICAgIGxhYmVsU2l6ZTogbnVtYmVyLFxuICApOiBudW1iZXIge1xuICAgIGNvbnN0IG1pbmltdW1FbGVtZW50c1NpemUgPVxuICAgICAgZGF0YS50eXBlID09PSAnZmxvdy1wcm9jZXNzZWQnXG4gICAgICAgID8gZ2V0TWF4Rmxvd0J1Y2tldFNpemUoXG4gICAgICAgICAgICBkYXRhLFxuICAgICAgICAgICAgMCxcbiAgICAgICAgICAgIGdldE1pbmltdW1EYXRhRWxlbWVudFNpemUoY29uZmlnKSxcbiAgICAgICAgICAgIGxhYmVsU2l6ZSxcbiAgICAgICAgICApIC0gZ2V0Rmxvd01pZExhYmVsU2l6ZShkYXRhLCBsYWJlbFNpemUpXG4gICAgICAgIDogMDtcbiAgICByZXR1cm4gYm91bmRpbmdEaW1lbnNpb24gKiBHUk9XTl9EQVRBX01JTklNVU1fUkFUSU8gKyBtaW5pbXVtRWxlbWVudHNTaXplO1xuICB9XG5cbiAgLy9Gb3IgZmxvdyBjaGFydHMsIGZpbmRzIHRoZSBzaXplIHRoZSBkYXRhIHNjYWxlIHNob3VsZCBtYXAgdG8gc28gdGhhdCBldmVyeSBidWNrZXQgKGluY2x1ZGluZyBpdHMgb3duIGRhdGEgbGFiZWxzLFxuICAvLyBhbmQgYW55IGVsZW1lbnRzIGVubGFyZ2VkIHRvIHRoZSBtaW5pbXVtIHNpemUpIGZpdHMgaW4gdGhlIGF2YWlsYWJsZSBzaXplXG4gIC8vUmV0dXJucyBudWxsIGlmIHRoZSBtaW5pbXVtIHNpemVzIGFsb25lIGNhbid0IGZpdFxuICBmdW5jdGlvbiBnZXRGaXR0ZWREYXRhU2l6ZShcbiAgICBkYXRhOiBQcm9jZXNzRGF0YSxcbiAgICBjb25maWc6IENvbmZpZyxcbiAgICBhdmFpbGFibGVTaXplOiBudW1iZXIsXG4gICAgbGFiZWxTaXplOiBudW1iZXIsXG4gICk6IG51bWJlciB8IG51bGwge1xuICAgIGlmIChkYXRhLnR5cGUgIT09ICdmbG93LXByb2Nlc3NlZCcpIHtcbiAgICAgIHJldHVybiBhdmFpbGFibGVTaXplO1xuICAgIH1cbiAgICBjb25zdCBkYXRhTWF4ID0gTWF0aC5tYXgoLi4uZGF0YS54Lm1hcCh4ID0+IHgudG90YWxDb3VudCkpO1xuICAgIGlmIChkYXRhTWF4IDw9IDApIHtcbiAgICAgIHJldHVybiBhdmFpbGFibGVTaXplO1xuICAgIH1cbiAgICBjb25zdCBtaW5pbXVtU2l6ZSA9IGdldE1pbmltdW1EYXRhRWxlbWVudFNpemUoY29uZmlnKTtcbiAgICBjb25zdCBidWNrZXRBdmFpbGFibGVTaXplID1cbiAgICAgIGF2YWlsYWJsZVNpemUgKyBnZXRGbG93TWlkTGFiZWxTaXplKGRhdGEsIGxhYmVsU2l6ZSk7XG4gICAgLy9DYWxjdWxhdGUgd2hhdCB0aGUgc2l6aW5nIHdvdWxkIG5lZWQgdG8gYmUgZm9yIGVhY2ggaW5kaXZpZHVhbCBjb2x1bW4sXG4gICAgLy8gIHRha2luZyB0aGUgdmFsdWUgdGhhdCBpcyBtb3N0IHJlc3RyaWN0aXZlLiBOb3QgYXBwbHlpbmcgbWluaW11bSBzaXplIHlldFxuICAgIGNvbnN0IHVuZW5sYXJnZWRSYXRpbyA9IE1hdGgubWluKFxuICAgICAgLi4uZGF0YS54XG4gICAgICAgIC5maWx0ZXIoYnVja2V0ID0+IGJ1Y2tldC50b3RhbENvdW50ID4gMClcbiAgICAgICAgLm1hcChcbiAgICAgICAgICBidWNrZXQgPT5cbiAgICAgICAgICAgIChidWNrZXRBdmFpbGFibGVTaXplIC0gKGJ1Y2tldC5zdWJCdWNrZXRzLmxlbmd0aCAtIDEpICogbGFiZWxTaXplKSAvXG4gICAgICAgICAgICBidWNrZXQudG90YWxDb3VudCxcbiAgICAgICAgKSxcbiAgICApO1xuICAgIGlmIChcbiAgICAgIG1pbmltdW1TaXplID09PSAwIHx8XG4gICAgICBnZXRNYXhGbG93QnVja2V0U2l6ZShkYXRhLCB1bmVubGFyZ2VkUmF0aW8sIG1pbmltdW1TaXplLCBsYWJlbFNpemUpIDw9XG4gICAgICAgIGJ1Y2tldEF2YWlsYWJsZVNpemVcbiAgICApIHtcbiAgICAgIHJldHVybiB1bmVubGFyZ2VkUmF0aW8gKiBkYXRhTWF4O1xuICAgIH1cbiAgICBpZiAoXG4gICAgICBnZXRNYXhGbG93QnVja2V0U2l6ZShkYXRhLCAwLCBtaW5pbXVtU2l6ZSwgbGFiZWxTaXplKSA+XG4gICAgICBidWNrZXRBdmFpbGFibGVTaXplXG4gICAgKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgLy9Ob3csIHdlIGFwcGx5IG1pbmltdW0gc2l6ZSB0byB0aGUgYmFycyB0byBjYWxjdWxhdGUgb3VyIHRydWUgcmF0aW8gKGZvdW5kIHRocm91Z2ggYmluYXJ5IHNlYXJjaClcbiAgICBsZXQgbG93ID0gMDtcbiAgICBsZXQgaGlnaCA9IHVuZW5sYXJnZWRSYXRpbztcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IDUwOyBpKyspIHtcbiAgICAgIGNvbnN0IG1pZCA9IChsb3cgKyBoaWdoKSAvIDI7XG4gICAgICBpZiAoXG4gICAgICAgIGdldE1heEZsb3dCdWNrZXRTaXplKGRhdGEsIG1pZCwgbWluaW11bVNpemUsIGxhYmVsU2l6ZSkgPlxuICAgICAgICBidWNrZXRBdmFpbGFibGVTaXplXG4gICAgICApIHtcbiAgICAgICAgaGlnaCA9IG1pZDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGxvdyA9IG1pZDtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGxvdyAqIGRhdGFNYXg7XG4gIH1cblxuICAvL1RoZSBzaXplIG5lZWRlZCBhbG9uZyB0aGUgZGF0YSBheGlzIGJleW9uZCB0aGUgZml4ZWQgc2l6ZVxuICAvL0ZvciBmbG93IGNoYXJ0cywgdGhpcyBpcyBiYXNlZCBvbiB0aGUgdGFsbGVzdCBidWNrZXQgKGluY2x1ZGluZyBpdHMgb3duIGRhdGEgbGFiZWxzIGFuZCBhbnkgZW5sYXJnZWQgZWxlbWVudHMpLFxuICAvLyByYXRoZXIgdGhhbiBhc3N1bWluZyB0aGUgYnVja2V0IHdpdGggdGhlIG1vc3QgZGF0YSBhbHNvIGhhcyB0aGUgbW9zdCBzdWItYnVja2V0c1xuICBmdW5jdGlvbiBnZXRTY2FsZWREYXRhVG90YWxTaXplKFxuICAgIGRhdGE6IFByb2Nlc3NEYXRhLFxuICAgIGNvbmZpZzogQ29uZmlnLFxuICAgIGRhdGFTaXplOiBudW1iZXIsXG4gICAgbGFiZWxTaXplOiBudW1iZXIsXG4gICk6IG51bWJlciB7XG4gICAgaWYgKGRhdGEudHlwZSAhPT0gJ2Zsb3ctcHJvY2Vzc2VkJykge1xuICAgICAgcmV0dXJuIGRhdGFTaXplO1xuICAgIH1cbiAgICBjb25zdCBkYXRhTWF4ID0gTWF0aC5tYXgoLi4uZGF0YS54Lm1hcCh4ID0+IHgudG90YWxDb3VudCkpO1xuICAgIGlmIChkYXRhTWF4IDw9IDApIHtcbiAgICAgIHJldHVybiBkYXRhU2l6ZTtcbiAgICB9XG4gICAgcmV0dXJuIChcbiAgICAgIGdldE1heEZsb3dCdWNrZXRTaXplKFxuICAgICAgICBkYXRhLFxuICAgICAgICBkYXRhU2l6ZSAvIGRhdGFNYXgsXG4gICAgICAgIGdldE1pbmltdW1EYXRhRWxlbWVudFNpemUoY29uZmlnKSxcbiAgICAgICAgbGFiZWxTaXplLFxuICAgICAgKSAtIGdldEZsb3dNaWRMYWJlbFNpemUoZGF0YSwgbGFiZWxTaXplKVxuICAgICk7XG4gIH1cblxuICBmdW5jdGlvbiBnZXREYXRhTGFiZWxTaXplKFxuICAgIGRhdGE6IFByb2Nlc3NEYXRhLFxuICAgIHBpcGVUcmFuc2Zvcm06ICgodmFsdWU6IG51bWJlciwgaXNTZWNvbmRhcnk6IGJvb2xlYW4pID0+IHN0cmluZykgfCBudWxsLFxuICAgIGZvbnRTaXplOiBudW1iZXIsXG4gICk6IHsgaG9yaXpvbnRhbDogbnVtYmVyOyB2ZXJ0aWNhbDogbnVtYmVyIH0ge1xuICAgIGxldCBub3JtSG9yaXpvbnRhbE1heExlbmd0aCA9IDA7XG4gICAgbGV0IG5vcm1TdXBwTWF4TGVuZ3RoID0gMDtcbiAgICBpZiAoZGF0YS50eXBlICE9PSAnZmxvdy1wcm9jZXNzZWQnICYmIHBpcGVUcmFuc2Zvcm0gIT09IG51bGwpIHtcbiAgICAgIG5vcm1Ib3Jpem9udGFsTWF4TGVuZ3RoID0gTWF0aC5tYXgoXG4gICAgICAgIC4uLmRhdGEueXMubWFwKCh5LCB5SW5kZXgpID0+XG4gICAgICAgICAgTWF0aC5tYXgoXG4gICAgICAgICAgICAuLi55LnZhbHVlcy5tYXAoKHZhbCwgeEluZGV4KSA9PlxuICAgICAgICAgICAgICBjaGVja0xhYmVsTGVuZ3RoKFxuICAgICAgICAgICAgICAgIHBpcGVUcmFuc2Zvcm0oXG4gICAgICAgICAgICAgICAgICB2YWwsXG4gICAgICAgICAgICAgICAgICBjaGVja0lmU2Vjb25kYXJ5KGRhdGEsIHlJbmRleCwgeEluZGV4LCBmYWxzZSksXG4gICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICBmb250U2l6ZSxcbiAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICksXG4gICAgICAgICAgKSxcbiAgICAgICAgKSxcbiAgICAgICk7XG4gICAgICBub3JtU3VwcE1heExlbmd0aCA9IE1hdGgubWF4KFxuICAgICAgICAuLi4oZGF0YS5zdXBwbGVtZW50YXJ5WXMgPz8gW10pLm1hcCgoeSwgeUluZGV4KSA9PlxuICAgICAgICAgIE1hdGgubWF4KFxuICAgICAgICAgICAgLi4ueS52YWx1ZXMubWFwKCh2YWwsIHhJbmRleCkgPT5cbiAgICAgICAgICAgICAgY2hlY2tMYWJlbExlbmd0aChcbiAgICAgICAgICAgICAgICBwaXBlVHJhbnNmb3JtKFxuICAgICAgICAgICAgICAgICAgdmFsLFxuICAgICAgICAgICAgICAgICAgY2hlY2tJZlNlY29uZGFyeShkYXRhLCB5SW5kZXgsIHhJbmRleCwgdHJ1ZSksXG4gICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICBmb250U2l6ZSxcbiAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICksXG4gICAgICAgICAgKSxcbiAgICAgICAgKSxcbiAgICAgICk7XG4gICAgfVxuICAgIGlmIChkYXRhLnR5cGUgPT09ICdmbG93LXByb2Nlc3NlZCcpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGhvcml6b250YWw6IE1hdGgubWF4KG5vcm1Ib3Jpem9udGFsTWF4TGVuZ3RoLCBub3JtU3VwcE1heExlbmd0aCksXG4gICAgICAgIHZlcnRpY2FsOiBmb250U2l6ZSAqIDIsXG4gICAgICB9O1xuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgaG9yaXpvbnRhbDogTWF0aC5tYXgobm9ybUhvcml6b250YWxNYXhMZW5ndGgsIG5vcm1TdXBwTWF4TGVuZ3RoKSxcbiAgICAgIHZlcnRpY2FsOiBmb250U2l6ZSxcbiAgICB9O1xuICB9XG5cbiAgZnVuY3Rpb24gZ2V0QnVja2V0TGFiZWxTaXplKFxuICAgIGRhdGE6IFByb2Nlc3NEYXRhLFxuICAgIGZvbnRTaXplOiBudW1iZXIsXG4gICAgZGF0ZUZvcm1hdDogKChkYXRlOiBEYXRlKSA9PiBzdHJpbmcpIHwgbnVsbCxcbiAgKSB7XG4gICAgaWYgKGRhdGVGb3JtYXQgIT09IG51bGwpIHtcbiAgICAgIGlmIChkYXRhLnR5cGUgPT09ICdsYWJlbGVkJykge1xuICAgICAgICByZXR1cm4gTWF0aC5tYXgoXG4gICAgICAgICAgLi4uZGF0YS54Lm1hcCh4ID0+IGNoZWNrTGFiZWxMZW5ndGgoeC5sYWJlbCwgZm9udFNpemUpKSxcbiAgICAgICAgKTtcbiAgICAgIH0gZWxzZSBpZiAoZGF0YS50eXBlID09PSAndGltZXNlcmllcycpIHtcbiAgICAgICAgcmV0dXJuIE1hdGgubWF4KFxuICAgICAgICAgIC4uLmRhdGEueC5tYXAoeCA9PlxuICAgICAgICAgICAgY2hlY2tMYWJlbExlbmd0aChkYXRlRm9ybWF0KG5ldyBEYXRlKHgpKSwgZm9udFNpemUpLFxuICAgICAgICAgICksXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiAwO1xuICB9XG5cbiAgZnVuY3Rpb24gY2hlY2tMYWJlbExlbmd0aCh2YWx1ZTogc3RyaW5nLCBmb250U2l6ZTogbnVtYmVyKTogbnVtYmVyIHtcbiAgICBjb25zdCBwZXJpb2RDb3VudCA9ICh2YWx1ZS5tYXRjaCgvXFwuL2cpIHx8IFtdKS5sZW5ndGg7XG4gICAgY29uc3Qgc2xhc2hDb3VudCA9ICh2YWx1ZS5tYXRjaCgvXFwvL2cpIHx8IFtdKS5sZW5ndGg7XG4gICAgY29uc3QgZm9udFNjYWxlRmFjdG9yID0gZm9udFNpemUgLyBERUZBVUxUX0ZPTlRfU0laRTtcbiAgICByZXR1cm4gKFxuICAgICAgKHZhbHVlLmxlbmd0aCAtIChwZXJpb2RDb3VudCArIHNsYXNoQ291bnQpKSAqXG4gICAgICAgIChXSURUSF9QRVJfTlVNQkVSICogZm9udFNjYWxlRmFjdG9yKSArXG4gICAgICBwZXJpb2RDb3VudCAqIChXSURUSF9QRVJfUEVSSU9EICogZm9udFNjYWxlRmFjdG9yKSArXG4gICAgICBzbGFzaENvdW50ICogKFdJRFRIX1BFUl9TTEFTSCAqIGZvbnRTY2FsZUZhY3RvcilcbiAgICApO1xuICB9XG5cbiAgZXhwb3J0IGZ1bmN0aW9uIGlzQmFyVHlwZSh0eXBlOiBDaGFydC5DaGFydFR5cGUpOiBib29sZWFuIHtcbiAgICBpZiAoXG4gICAgICB0eXBlID09PSAnYmFyJyB8fFxuICAgICAgdHlwZSA9PT0gJ2hvcml6b250YWwtYmFyJyB8fFxuICAgICAgdHlwZSA9PT0gJ3dhdGVyZmFsbCcgfHxcbiAgICAgIHR5cGUgPT09ICdmdW5uZWwnXG4gICAgKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgLy9Pbmx5IGJhci10eXBlIGFuZCBmbG93IGNoYXJ0cyBoYXZlIGRpc2NyZXRlIGRhdGEgZWxlbWVudHMgdGhhdCB0aGUgbWluaW11bSBzaXplIGFwcGxpZXMgdG9cbiAgZnVuY3Rpb24gZ2V0TWluaW11bURhdGFFbGVtZW50U2l6ZShjb25maWc6IENvbmZpZyk6IG51bWJlciB7XG4gICAgaWYgKFxuICAgICAgY29uZmlnLnR5cGUgPT09ICdkb251dCcgfHxcbiAgICAgIGNvbmZpZy50eXBlID09PSAnbGluZScgfHxcbiAgICAgIGNvbmZpZy50eXBlID09PSAnYXJlYSdcbiAgICApIHtcbiAgICAgIHJldHVybiAwO1xuICAgIH1cbiAgICByZXR1cm4gY29uZmlnLnNjYWxpbmdDb25maWc/LmRhdGFTY2FsZT8ubWluaW11bURhdGFFbGVtZW50U2l6ZSA/PyAwO1xuICB9XG5cbiAgLy9BbnkgZGF0YSBlbGVtZW50IHdpdGggYSBub24temVybyB2YWx1ZSBpcyBrZXB0IGF0IG9yIGFib3ZlIHRoZSBtaW5pbXVtIHNpemVcbiAgZnVuY3Rpb24gYXBwbHlNaW5pbXVtRGF0YUVsZW1lbnRTaXplKFxuICAgIHNpemU6IG51bWJlcixcbiAgICB2YWx1ZTogbnVtYmVyLFxuICAgIG1pbmltdW1TaXplOiBudW1iZXIsXG4gICk6IG51bWJlciB7XG4gICAgcmV0dXJuIHZhbHVlICE9PSAwID8gTWF0aC5tYXgoc2l6ZSwgbWluaW11bVNpemUpIDogc2l6ZTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGdldEZsb3dTdWJCdWNrZXRTaXplcyhcbiAgICBzdWJCdWNrZXQ6IEZsb3dTdWJCdWNrZXQsXG4gICAgdmFsdWVUb1NpemU6ICh2YWx1ZTogbnVtYmVyKSA9PiBudW1iZXIsXG4gICAgbWluaW11bVNpemU6IG51bWJlcixcbiAgKToge1xuICAgIHRvdGFsU2l6ZTogbnVtYmVyO1xuICAgIGNvbnRpbnVpbmdTaXplOiBudW1iZXI7XG4gICAgY29ubmVjdGlvblNpemVzOiBudW1iZXJbXTtcbiAgfSB7XG4gICAgY29uc3QgY29ubmVjdGlvblNpemVzID0gc3ViQnVja2V0LmNvbm5lY3Rpb25zLm1hcChjb25uZWN0aW9uID0+XG4gICAgICBhcHBseU1pbmltdW1EYXRhRWxlbWVudFNpemUoXG4gICAgICAgIHZhbHVlVG9TaXplKGNvbm5lY3Rpb24uY291bnQpLFxuICAgICAgICBjb25uZWN0aW9uLmNvdW50LFxuICAgICAgICBtaW5pbXVtU2l6ZSxcbiAgICAgICksXG4gICAgKTtcbiAgICBjb25zdCBzdW1TaXplcyA9IChkaXJlY3Rpb246IEZsb3dDb25uZWN0aW9uWydkaXJlY3Rpb24nXSk6IG51bWJlciA9PlxuICAgICAgc3VtKFxuICAgICAgICBjb25uZWN0aW9uU2l6ZXMuZmlsdGVyKFxuICAgICAgICAgIChfLCBpKSA9PiBzdWJCdWNrZXQuY29ubmVjdGlvbnNbaV0uZGlyZWN0aW9uID09PSBkaXJlY3Rpb24sXG4gICAgICAgICksXG4gICAgICApO1xuICAgIGNvbnN0IGNvbnRpbnVpbmdTaXplID0gc3VtU2l6ZXMoJ2ZvcndhcmQnKTtcbiAgICBjb25zdCBiYWNrd2FyZFNpemUgPSBzdW1TaXplcygnYmFja3dhcmQnKTtcbiAgICBjb25zdCBub25Db250aW51aW5nQ291bnQgPVxuICAgICAgc3ViQnVja2V0LmNvdW50IC1cbiAgICAgIHN1bShcbiAgICAgICAgc3ViQnVja2V0LmNvbm5lY3Rpb25zXG4gICAgICAgICAgLmZpbHRlcihjb25uZWN0aW9uID0+IGNvbm5lY3Rpb24uZGlyZWN0aW9uID09PSAnZm9yd2FyZCcpXG4gICAgICAgICAgLm1hcChjb25uZWN0aW9uID0+IGNvbm5lY3Rpb24uY291bnQpLFxuICAgICAgKTtcbiAgICAvL1RoZSBzdWItYnVja2V0IG11c3QgYmUgYmlnIGVub3VnaCB0byBob2xkIGFsbCBvZiBpdHMgKHBvc3NpYmx5IGVubGFyZ2VkKSBjb25uZWN0aW9ucyBvbiBlaXRoZXIgc2lkZVxuICAgIGNvbnN0IHRvdGFsU2l6ZSA9IE1hdGgubWF4KFxuICAgICAgYXBwbHlNaW5pbXVtRGF0YUVsZW1lbnRTaXplKFxuICAgICAgICB2YWx1ZVRvU2l6ZShzdWJCdWNrZXQuY291bnQpLFxuICAgICAgICBzdWJCdWNrZXQuY291bnQsXG4gICAgICAgIG1pbmltdW1TaXplLFxuICAgICAgKSxcbiAgICAgIGNvbnRpbnVpbmdTaXplICtcbiAgICAgICAgYXBwbHlNaW5pbXVtRGF0YUVsZW1lbnRTaXplKFxuICAgICAgICAgIHZhbHVlVG9TaXplKG5vbkNvbnRpbnVpbmdDb3VudCksXG4gICAgICAgICAgbm9uQ29udGludWluZ0NvdW50LFxuICAgICAgICAgIG1pbmltdW1TaXplLFxuICAgICAgICApLFxuICAgICAgYmFja3dhcmRTaXplLFxuICAgICk7XG4gICAgLy9FdmVyeSB1bml0IGluIGEgc3ViLWJ1Y2tldCBhcnJpdmVzIHRocm91Z2ggaXRzIGJhY2t3YXJkIGNvbm5lY3Rpb25zLCBzbyB0aGV5J3JlIHN0cmV0Y2hlZCB0byBmaWxsIHRoZVxuICAgIC8vIHN1Yi1idWNrZXQgd2hlbiBpdCBoYXMgYmVlbiBlbmxhcmdlZCBiZXlvbmQgdGhlbVxuICAgIHJldHVybiB7XG4gICAgICB0b3RhbFNpemUsXG4gICAgICBjb250aW51aW5nU2l6ZSxcbiAgICAgIGNvbm5lY3Rpb25TaXplczogY29ubmVjdGlvblNpemVzLm1hcCgoc2l6ZSwgaSkgPT5cbiAgICAgICAgc3ViQnVja2V0LmNvbm5lY3Rpb25zW2ldLmRpcmVjdGlvbiA9PT0gJ2JhY2t3YXJkJyAmJiBiYWNrd2FyZFNpemUgPiAwXG4gICAgICAgICAgPyAoc2l6ZSAqIHRvdGFsU2l6ZSkgLyBiYWNrd2FyZFNpemVcbiAgICAgICAgICA6IHNpemUsXG4gICAgICApLFxuICAgIH07XG4gIH1cblxuICAvL1RoZSBzaXplIG9mIHRoZSB0YWxsZXN0IGZsb3cgYnVja2V0IGZvciB0aGUgZ2l2ZW4gc2NhbGluZyByYXRpbywgaW5jbHVkaW5nIHRoZSBkYXRhIGxhYmVscyBiZXR3ZWVuIGl0cyBzdWItYnVja2V0c1xuICAvLyAgVGhlIGxhYmVsIGFib3ZlIHRoZSBmaXJzdCBzdWItYnVja2V0IGlzIGV4Y2x1ZGVkLCBzaW5jZSBpdCdzIHBhcnQgb2YgdGhlIHRvcCBvZmZzZXRcbiAgZnVuY3Rpb24gZ2V0TWF4Rmxvd0J1Y2tldFNpemUoXG4gICAgZGF0YTogUHJvY2Vzc2VkRmxvd0RhdGEsXG4gICAgcHhQZXJWYWx1ZTogbnVtYmVyLFxuICAgIG1pbmltdW1TaXplOiBudW1iZXIsXG4gICAgbGFiZWxTaXplOiBudW1iZXIsXG4gICk6IG51bWJlciB7XG4gICAgcmV0dXJuIE1hdGgubWF4KFxuICAgICAgLi4uZGF0YS54Lm1hcChcbiAgICAgICAgYnVja2V0ID0+XG4gICAgICAgICAgc3VtKFxuICAgICAgICAgICAgYnVja2V0LnN1YkJ1Y2tldHMubWFwKFxuICAgICAgICAgICAgICBzdWJCdWNrZXQgPT5cbiAgICAgICAgICAgICAgICBnZXRGbG93U3ViQnVja2V0U2l6ZXMoXG4gICAgICAgICAgICAgICAgICBzdWJCdWNrZXQsXG4gICAgICAgICAgICAgICAgICB2YWx1ZSA9PiB2YWx1ZSAqIHB4UGVyVmFsdWUsXG4gICAgICAgICAgICAgICAgICBtaW5pbXVtU2l6ZSxcbiAgICAgICAgICAgICAgICApLnRvdGFsU2l6ZSxcbiAgICAgICAgICAgICksXG4gICAgICAgICAgKSArXG4gICAgICAgICAgKGJ1Y2tldC5zdWJCdWNrZXRzLmxlbmd0aCAtIDEpICogbGFiZWxTaXplLFxuICAgICAgKSxcbiAgICApO1xuICB9XG5cbiAgLy9UaGUgZml4ZWQgc2l6ZSByZXNlcnZlcyByb29tIGZvciB0aGUgbGFiZWxzIGJldHdlZW4gc3ViLWJ1Y2tldHMgYXMgaWYgZXZlcnkgYnVja2V0IGhhZCBhcyBtYW55IHN1Yi1idWNrZXRzIGFzIHRoZVxuICAvLyBidWNrZXQgd2l0aCB0aGUgbW9zdCwgc28gdGhpcyBpcyB0aGUgcG9ydGlvbiBvZiB0aGUgZml4ZWQgc2l6ZSB0aGF0IGVhY2ggYnVja2V0IGNhbiBpbnN0ZWFkIHVzZSBiYXNlZCBvbiBpdHMgb3duIGxhYmVsc1xuICBmdW5jdGlvbiBnZXRGbG93TWlkTGFiZWxTaXplKFxuICAgIGRhdGE6IFByb2Nlc3NlZEZsb3dEYXRhLFxuICAgIGxhYmVsU2l6ZTogbnVtYmVyLFxuICApOiBudW1iZXIge1xuICAgIHJldHVybiAoXG4gICAgICAoTWF0aC5tYXgoLi4uZGF0YS54Lm1hcChidWNrZXQgPT4gYnVja2V0LnN1YkJ1Y2tldHMubGVuZ3RoKSkgLSAxKSAqXG4gICAgICBsYWJlbFNpemVcbiAgICApO1xuICB9XG5cbiAgZnVuY3Rpb24gaXNTdGFja2VkRGF0YShjb25maWc6IENvbmZpZyk6IGJvb2xlYW4ge1xuICAgIGlmIChjb25maWcudHlwZSA9PT0gJ2JhcicgfHwgY29uZmlnLnR5cGUgPT09ICdob3Jpem9udGFsLWJhcicpIHtcbiAgICAgIGlmIChjb25maWcuZ3JvdXBpbmdUeXBlID09PSAnc3RhY2tlZCcpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG4gICAgfVxuICAgIGlmIChjb25maWcudHlwZSA9PT0gJ2FyZWEnIHx8IGNvbmZpZy50eXBlID09PSAnd2F0ZXJmYWxsJykge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGlzQ2x1c3RlcmVkRGF0YShcbiAgICBkYXRhOiBOb25GbG93RGF0YSxcbiAgICBjb25maWc6IENvbmZpZyxcbiAgICBpbmNsdWRlU3VwcGxlbWVudGFyeTogYm9vbGVhbixcbiAgKTogYm9vbGVhbiB7XG4gICAgLy9JdCB2YXJpZXMgd2hldGhlciB3ZSB3YW50IHRvIGluY2x1ZGUgc3VwcGxlbWVudGFyeSBkYXRhIGluIHRoaXMgY2hlY2tcbiAgICBpZiAoaGFzU3VwcGxlbWVudGFyeURhdGEoZGF0YSkgJiYgaW5jbHVkZVN1cHBsZW1lbnRhcnkpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICBpZiAoXG4gICAgICAoY29uZmlnLnR5cGUgPT09ICdiYXInIHx8IGNvbmZpZy50eXBlID09PSAnaG9yaXpvbnRhbC1iYXInKSAmJlxuICAgICAgY29uZmlnLmdyb3VwaW5nVHlwZSA9PT0gJ2NsdXN0ZXJlZCdcbiAgICApIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICBpZiAoY29uZmlnLnR5cGUgPT09ICdmdW5uZWwnKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgLy9JbiBzb21lIGNhc2VzLCB0aGUgZGlzdGluY3Rpb24gYmV0d2VlbiBjbHVzdGVyZWQgYW5kIHN0YWNrZWQgZG9lc24ndCBtYXR0ZXJcbiAgZnVuY3Rpb24gaXNHcm91cGluZ1R5cGVFeGNlcHRpb24oZGF0YTogTm9uRmxvd0RhdGEsIGNvbmZpZzogQ29uZmlnKTogYm9vbGVhbiB7XG4gICAgaWYgKGRhdGEueXMubGVuZ3RoID09PSAxKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgLy9DaGVja2luZyBmb3IgYSAnbWV0cmljJyBjaGFydHMsIHdoaWNoIGlzIGEgc3BlY2lhbCBjYXNlIGZvciBob3Jpem9udGFsIGJhciBjaGFydHMsXG4gICAgLy8gd2hlcmUgZWFjaCBzZXJpZXMgaXMgYWxzbyBhIGJ1Y2tldCAoYW5kIHZpY2UgdmVyc2EpXG4gICAgaWYgKGNvbmZpZy50eXBlID09PSAnaG9yaXpvbnRhbC1iYXInKSB7XG4gICAgICBpZiAoXG4gICAgICAgIGRhdGEueC5sZW5ndGggPT09IGRhdGEueXMubGVuZ3RoICYmXG4gICAgICAgIGRhdGEueXMubGVuZ3RoID09PVxuICAgICAgICAgIGRhdGEueXMuZmlsdGVyKHkgPT4geS52YWx1ZXMuZmlsdGVyKHZhbCA9PiB2YWwgIT09IDApLmxlbmd0aCA9PT0gMSlcbiAgICAgICAgICAgIC5sZW5ndGhcbiAgICAgICkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgZnVuY3Rpb24gaGFzU3VwcGxlbWVudGFyeURhdGEoZGF0YTogSW5wdXREYXRhKTogZGF0YSBpcyBOb25GbG93RGF0YSAmIHtcbiAgICBzdXBwbGVtZW50YXJ5WXM6IE5vbk51bGxhYmxlPE5vbkZsb3dEYXRhWydzdXBwbGVtZW50YXJ5WXMnXT47XG4gIH0ge1xuICAgIGlmIChkYXRhLnR5cGUgPT09ICdmbG93Jykge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBpZiAoZGF0YS5zdXBwbGVtZW50YXJ5WXMgJiYgZGF0YS5zdXBwbGVtZW50YXJ5WXMubGVuZ3RoID4gMCkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGdldEVsZW1lbnRTY2FsaW5nSW5mbyhcbiAgICBlbGVtZW50U2NhbGVzOiBQYXJ0aWFsRWxlbWVudFNjYWxpbmdDb25maWcgfCB1bmRlZmluZWQsXG4gICAgZGVmYXVsdFNjYWxpbmdDb25maWc6IEZ1bGxFbGVtZW50U2NhbGluZ0NvbmZpZyxcbiAgICBlbGVtZW50OiBDaGFydFNjYWxlRWxlbWVudCxcbiAgKTogRWxlbWVudFNjYWxpbmdDb25maWd1cmF0aW9uIHtcbiAgICBjb25zdCBkZWZhdWx0RWxlbWVudENvbmZpZyA9IGRlZmF1bHRTY2FsaW5nQ29uZmlnW2VsZW1lbnRdO1xuICAgIGxldCBpbnB1dENvbmZpZzogRWxlbWVudFNjYWxpbmdDb25maWd1cmF0aW9uIHwgbnVsbDtcbiAgICBpZiAoZWxlbWVudFNjYWxlcykge1xuICAgICAgY29uc3QgcG9zc2libGVDb25maWcgPSBlbGVtZW50U2NhbGVzW2VsZW1lbnRdO1xuICAgICAgaWYgKHBvc3NpYmxlQ29uZmlnKSB7XG4gICAgICAgIGlucHV0Q29uZmlnID0gcG9zc2libGVDb25maWc7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpbnB1dENvbmZpZyA9IG51bGw7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGlucHV0Q29uZmlnID0gbnVsbDtcbiAgICB9XG5cbiAgICBpZiAoaW5wdXRDb25maWcgIT09IG51bGwpIHtcbiAgICAgIGNvbnN0IHJldHVybkNvbmZpZyA9IGlucHV0Q29uZmlnIGFzIEVsZW1lbnRTY2FsaW5nQ29uZmlndXJhdGlvbjtcbiAgICAgIHJldHVybiByZXR1cm5Db25maWc7XG4gICAgfVxuICAgIGlmIChkZWZhdWx0RWxlbWVudENvbmZpZy50YXJnZXQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgY29uc3QgcmV0dXJuQ29uZmlnID0gZGVmYXVsdEVsZW1lbnRDb25maWcgYXMgRWxlbWVudFNjYWxpbmdDb25maWd1cmF0aW9uO1xuICAgICAgcmV0dXJuIHJldHVybkNvbmZpZztcbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgIHRhcmdldDogMCxcbiAgICB9O1xuICB9XG5cbiAgZnVuY3Rpb24gZGV0ZXJtaW5lUG9zc2libGVTaXplc09mRWxlbWVudChcbiAgICBlbGVtZW50Q29uZmlnOiBFbGVtZW50U2NhbGluZ0NvbmZpZ3VyYXRpb24sXG4gICAgZWxlbWVudENvdW50OiBudW1iZXIsXG4gICk6IHsgbWluOiBudW1iZXI7IG1heDogbnVtYmVyOyB0YXJnZXQ6IG51bWJlciB9IHtcbiAgICBjb25zdCBpbmRNaW4gPSBlbGVtZW50Q29uZmlnLm1pbiAhPT0gdW5kZWZpbmVkID8gZWxlbWVudENvbmZpZy5taW4gOiAwO1xuICAgIGNvbnN0IGluZE1heCA9IGVsZW1lbnRDb25maWcubWF4ICE9PSB1bmRlZmluZWQgPyBlbGVtZW50Q29uZmlnLm1heCA6IDA7XG4gICAgY29uc3QgaW5kVGFyZ2V0ID0gZWxlbWVudENvbmZpZy50YXJnZXQ7XG4gICAgcmV0dXJuIHtcbiAgICAgIG1pbjogaW5kTWluICogZWxlbWVudENvdW50LFxuICAgICAgbWF4OiBpbmRNYXggKiBlbGVtZW50Q291bnQsXG4gICAgICB0YXJnZXQ6IGluZFRhcmdldCAqIGVsZW1lbnRDb3VudCxcbiAgICB9O1xuICB9XG5cbiAgZnVuY3Rpb24gZGV0ZXJtaW5lVG90YWxTY2FsZWRTaXplT2ZFbGVtZW50KFxuICAgIGVsZW1lbnRDb25maWc6IEVsZW1lbnRTY2FsaW5nQ29uZmlndXJhdGlvbixcbiAgICBlbGVtZW50Q291bnQ6IG51bWJlcixcbiAgICBzY2FsZVZhbHVlOiBudW1iZXIsXG4gICk6IG51bWJlciB7XG4gICAgY29uc3Qgc2NhbGVkVmFsID0gZ2V0U2NhbGVkRWxlbWVudFNpemUoZWxlbWVudENvbmZpZywgc2NhbGVWYWx1ZSk7XG4gICAgcmV0dXJuIHNjYWxlZFZhbCAqIGVsZW1lbnRDb3VudDtcbiAgfVxuXG4gIGZ1bmN0aW9uIGdldFNjYWxlZEVsZW1lbnRTaXplKFxuICAgIGVsZW1lbnRDb25maWc6IEVsZW1lbnRTY2FsaW5nQ29uZmlndXJhdGlvbixcbiAgICBzY2FsZVZhbHVlOiBudW1iZXIsXG4gICk6IG51bWJlciB7XG4gICAgY29uc3Qgc2NhbGVkVGFyZ2V0ID0gZWxlbWVudENvbmZpZy50YXJnZXQgKiBzY2FsZVZhbHVlO1xuICAgIGlmIChzY2FsZVZhbHVlIDwgMSkge1xuICAgICAgaWYgKGVsZW1lbnRDb25maWcubWluICYmIGVsZW1lbnRDb25maWcubWluID4gc2NhbGVkVGFyZ2V0KSB7XG4gICAgICAgIHJldHVybiBlbGVtZW50Q29uZmlnLm1pbjtcbiAgICAgIH1cbiAgICAgIHJldHVybiBzY2FsZWRUYXJnZXQ7XG4gICAgfVxuICAgIGlmIChzY2FsZVZhbHVlID4gMSkge1xuICAgICAgaWYgKGVsZW1lbnRDb25maWcubWF4ICYmIGVsZW1lbnRDb25maWcubWF4IDwgc2NhbGVkVGFyZ2V0KSB7XG4gICAgICAgIHJldHVybiBlbGVtZW50Q29uZmlnLm1heDtcbiAgICAgIH1cbiAgICAgIHJldHVybiBzY2FsZWRUYXJnZXQ7XG4gICAgfVxuICAgIHJldHVybiBzY2FsZWRUYXJnZXQ7XG4gIH1cblxuICB0eXBlIEVsZW1lbnRTY2FsZUNoZWNrSW5mbyA9IHtcbiAgICBjb25maWc6IEVsZW1lbnRTY2FsaW5nQ29uZmlndXJhdGlvbjtcbiAgICBtaW5TY2FsZUZhY3Rvcj86IG51bWJlcjtcbiAgICBtYXhTY2FsZUZhY3Rvcj86IG51bWJlcjtcbiAgICBlbGVtZW50Q291bnQ6IG51bWJlcjtcbiAgfTtcblxuICBmdW5jdGlvbiBnZXRDaGVja2luZ0luZm9Gb3JFbGVtZW50Q29uZmlnKFxuICAgIGNvbmZpZzogRWxlbWVudFNjYWxpbmdDb25maWd1cmF0aW9uLFxuICAgIGVsZW1lbnRDb3VudDogbnVtYmVyLFxuICApOiBFbGVtZW50U2NhbGVDaGVja0luZm8ge1xuICAgIGxldCBtaW5TY2FsZUZhY3RvcjogbnVtYmVyIHwgdW5kZWZpbmVkID0gdW5kZWZpbmVkO1xuICAgIGlmIChjb25maWcubWluKSB7XG4gICAgICBtaW5TY2FsZUZhY3RvciA9XG4gICAgICAgIGNvbmZpZy50YXJnZXQgIT09IDAgPyBjb25maWcubWluIC8gY29uZmlnLnRhcmdldCA6IHVuZGVmaW5lZDtcbiAgICB9XG4gICAgbGV0IG1heFNjYWxlRmFjdG9yOiBudW1iZXIgfCB1bmRlZmluZWQgPSB1bmRlZmluZWQ7XG4gICAgaWYgKGNvbmZpZy5tYXgpIHtcbiAgICAgIG1heFNjYWxlRmFjdG9yID1cbiAgICAgICAgY29uZmlnLnRhcmdldCAhPT0gMCA/IGNvbmZpZy5tYXggLyBjb25maWcudGFyZ2V0IDogdW5kZWZpbmVkO1xuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgY29uZmlnLFxuICAgICAgbWluU2NhbGVGYWN0b3IsXG4gICAgICBtYXhTY2FsZUZhY3RvcixcbiAgICAgIGVsZW1lbnRDb3VudCxcbiAgICB9O1xuICB9XG5cbiAgZnVuY3Rpb24gZ2V0U3VtRm9yU2NhbGVWYWx1ZShcbiAgICBjaGVja0luZm9zOiBFbGVtZW50U2NhbGVDaGVja0luZm9bXSxcbiAgICBzY2FsZVZhbHVlOiBudW1iZXIsXG4gICk6IG51bWJlciB7XG4gICAgbGV0IHN1bSA9IDA7XG4gICAgZm9yIChjb25zdCBjaGVjayBvZiBjaGVja0luZm9zKSB7XG4gICAgICBzdW0gKz0gZGV0ZXJtaW5lVG90YWxTY2FsZWRTaXplT2ZFbGVtZW50KFxuICAgICAgICBjaGVjay5jb25maWcsXG4gICAgICAgIGNoZWNrLmVsZW1lbnRDb3VudCxcbiAgICAgICAgc2NhbGVWYWx1ZSxcbiAgICAgICk7XG4gICAgfVxuICAgIHJldHVybiBzdW07XG4gIH1cblxuICBmdW5jdGlvbiBnZXREYXRhTGFiZWxTaXppbmdDb3VudChcbiAgICBkYXRhOiBQcm9jZXNzRGF0YSxcbiAgICBjb25maWc6IENvbmZpZyxcbiAgKTogeyBzdGFydDogbnVtYmVyOyBlbmQ6IG51bWJlcjsgdG90YWw6IG51bWJlciB9IHtcbiAgICBpZiAoY29uZmlnLnNob3dEYXRhTGFiZWxzICE9PSB0cnVlKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBzdGFydDogMCxcbiAgICAgICAgZW5kOiAwLFxuICAgICAgICB0b3RhbDogMCxcbiAgICAgIH07XG4gICAgfVxuICAgIC8vRGF0YSBsYWJlbHMgYXJlIGFsd2F5cyBzaG93biBhYm92ZSB0aGUgZGF0YSBmb3IgYWxsIGJ1dCB0aGVzZSAzIHR5cGVzXG4gICAgaWYgKFxuICAgICAgY29uZmlnLnR5cGUgIT09ICdiYXInICYmXG4gICAgICBjb25maWcudHlwZSAhPT0gJ2hvcml6b250YWwtYmFyJyAmJlxuICAgICAgY29uZmlnLnR5cGUgIT09ICd3YXRlcmZhbGwnICYmXG4gICAgICBjb25maWcudHlwZSAhPT0gJ2Zsb3cnXG4gICAgKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBzdGFydDogMSxcbiAgICAgICAgZW5kOiAwLFxuICAgICAgICB0b3RhbDogMSxcbiAgICAgIH07XG4gICAgfVxuICAgIGxldCBzdGFydENvdW50ID0gMDtcbiAgICBsZXQgbWlkQ291bnQgPSAwO1xuICAgIGxldCBlbmRDb3VudCA9IDA7XG4gICAgaWYgKGRhdGEudHlwZSAhPT0gJ2Zsb3ctcHJvY2Vzc2VkJykge1xuICAgICAgaWYgKGRhdGEueXMuZmluZCh5ID0+IHkudmFsdWVzLmZpbmQodmFsID0+IHZhbCA+PSAwKSkpIHtcbiAgICAgICAgaWYgKGNvbmZpZy50eXBlID09PSAnaG9yaXpvbnRhbC1iYXInKSB7XG4gICAgICAgICAgZW5kQ291bnQgKz0gMTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBzdGFydENvdW50ICs9IDE7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGlmIChkYXRhLnlzLmZpbmQoeSA9PiB5LnZhbHVlcy5maW5kKHZhbCA9PiB2YWwgPCAwKSkpIHtcbiAgICAgICAgaWYgKGNvbmZpZy50eXBlID09PSAnaG9yaXpvbnRhbC1iYXInKSB7XG4gICAgICAgICAgc3RhcnRDb3VudCArPSAxO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGVuZENvdW50ICs9IDE7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgc3RhcnRDb3VudCA9IDE7XG4gICAgICBtaWRDb3VudCA9IE1hdGgubWF4KC4uLmRhdGEueC5tYXAoeCA9PiB4LnN1YkJ1Y2tldHMubGVuZ3RoKSkgLSAxO1xuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgc3RhcnQ6IHN0YXJ0Q291bnQsXG4gICAgICBlbmQ6IGVuZENvdW50LFxuICAgICAgdG90YWw6IHN0YXJ0Q291bnQgKyBtaWRDb3VudCArIGVuZENvdW50LFxuICAgIH07XG4gIH1cblxuICBmdW5jdGlvbiBnZXRJZkhvdmVyT3V0T2ZCb3VuZHMoXG4gICAgLy9Qb3NpdGlvbiBub3QgYWNjb3VudGluZyBmb3Igc2Nyb2xsaW5nXG4gICAgcmVsUG9zWDogbnVtYmVyLFxuICAgIHJlbFBvc1k6IG51bWJlcixcbiAgICAvL1Bvc2l0aW9uIGFjY291bnRpbmcgZm9yIHNjcm9sbGluZ1xuICAgIHJlYWxQb3NYOiBudW1iZXIsXG4gICAgcmVhbFBvc1k6IG51bWJlcixcbiAgICBjaGFydFNpemluZ1ZhbHVlczogRnVsbENoYXJ0U2NhbGVWYWx1ZXMgfCBudWxsLFxuICAgIGRpbWVuc2lvbnM6IERpbWVuc2lvbnMsXG4gICk6IGJvb2xlYW4ge1xuICAgIC8vQ2hlY2sgaWYgd2UncmUgb24gdG9wIG9mIG9uZSBvZiB0aGUgc2Nyb2xsYmFyc1xuICAgIGlmIChyZWxQb3NYID4gZGltZW5zaW9ucy53aWR0aCB8fCByZWxQb3NZID4gZGltZW5zaW9ucy5oZWlnaHQpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICBpZiAoY2hhcnRTaXppbmdWYWx1ZXMgPT09IG51bGwpIHtcbiAgICAgIC8vSWYgY2hhcnRTaXppbmdWYWx1ZXMgYXJlbid0IHByb3ZpZGVkLCBubyBtb3JlIGNoZWNrc1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICAvL0NoZWNrIGlmIHdlJ3JlIGluIG9uZSBvZiB0aGUgcGFkZGluZyBhcmVhc1xuICAgIGlmIChcbiAgICAgIHJlYWxQb3NYIDwgY2hhcnRTaXppbmdWYWx1ZXMubGVmdFBhZGRpbmcgfHxcbiAgICAgIHJlYWxQb3NYID5cbiAgICAgICAgY2hhcnRTaXppbmdWYWx1ZXMudG90YWxXaWR0aCAtIGNoYXJ0U2l6aW5nVmFsdWVzLnJpZ2h0UGFkZGluZyB8fFxuICAgICAgcmVhbFBvc1kgPCBjaGFydFNpemluZ1ZhbHVlcy50b3BQYWRkaW5nIHx8XG4gICAgICByZWFsUG9zWSA+IGNoYXJ0U2l6aW5nVmFsdWVzLnRvdGFsSGVpZ2h0IC0gY2hhcnRTaXppbmdWYWx1ZXMuYm90dG9tUGFkZGluZ1xuICAgICkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGdldENoYXJ0RGF0YURpcmVjdGlvbihjb25maWc6IENvbmZpZyk6IENoYXJ0RGF0YURpcmVjdGlvbiB7XG4gICAgaWYgKGNvbmZpZy50eXBlID09PSAnaG9yaXpvbnRhbC1iYXInKSB7XG4gICAgICByZXR1cm4gJ2hvcml6b250YWwnO1xuICAgIH1cbiAgICByZXR1cm4gJ3ZlcnRpY2FsJztcbiAgfVxuXG4gIGZ1bmN0aW9uIGNvbWJpbmVTY2FsaW5nSW5mbyhcbiAgICBjb25maWc6IENvbmZpZ1dpdGhGdWxsU2NhbGluZyxcbiAgICBkZWZhdWx0Q29uZmlnOiBEZWZhdWx0U2NhbGluZ0NvbmZpZyxcbiAgKTogTm9uRWxlbWVudFNjYWxpbmdDb25maWcge1xuICAgIGNvbnN0IHByb3ZpZGVkU2NhbGluZ0NvbmZpZyA9IGNvbmZpZy5zY2FsaW5nQ29uZmlnO1xuICAgIGNvbnN0IGNoYXJ0RGF0YURpcmVjdGlvbiA9IGdldENoYXJ0RGF0YURpcmVjdGlvbihjb25maWcpO1xuXG4gICAgLy9JZiB0aGUgdXNlciBwcm92aWRlcyBhIGRhdGEgc2NhbGUsIHdlIGRvbid0IHdhbnQgdG8gb3ZlcnJpZGUgdGhhdCB1bmxlc3MgdGhleSBhbHNvIHByb3ZpZGVkIGEgc3BlY2lmaWMgc2NhbGUgZm9yIHRoZSBjb3JyZXNwb25kaW5nIGF4aXNcbiAgICBjb25zdCBkYXRhU2NhbGUgPVxuICAgICAgcHJvdmlkZWRTY2FsaW5nQ29uZmlnICYmIHByb3ZpZGVkU2NhbGluZ0NvbmZpZy5kYXRhU2NhbGVcbiAgICAgICAgPyBwcm92aWRlZFNjYWxpbmdDb25maWcuZGF0YVNjYWxlXG4gICAgICAgIDogZGVmYXVsdENvbmZpZy5ub25FbGVtZW50U2NhbGVzLmRhdGFTY2FsZTtcbiAgICBsZXQgdmVydGljYWxBeGlzU2NhbGUgPSBwcm92aWRlZFNjYWxpbmdDb25maWc/LnZlcnRpY2FsQXhpc1NjYWxlO1xuICAgIGlmICh2ZXJ0aWNhbEF4aXNTY2FsZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICBpZiAoY2hhcnREYXRhRGlyZWN0aW9uID09PSAnaG9yaXpvbnRhbCcgfHwgZGF0YVNjYWxlLnR5cGUgPT09ICdmaXQnKSB7XG4gICAgICAgIHZlcnRpY2FsQXhpc1NjYWxlID0gZGVmYXVsdENvbmZpZy5ub25FbGVtZW50U2NhbGVzLnZlcnRpY2FsQXhpc1NjYWxlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy9UaGUgdmVydGljYWwgYXhpcyBpcyB0aGUgZGF0YSBheGlzLCB0aGUgZGF0YVNjYWxlIGhhcyBhIHVzZXItaW5wdXR0ZWQgdmFsdWUsIGFuZCB0aGVyZSBpc24ndCBhIHVzZXItaW5wdXR0ZWQgdmVydGljYWxBeGlzU2NhbGVcbiAgICAgICAgLy8gU28sIHdlJ2xsIHByZXZlbnQgdGhlIGF4aXMgc2NhbGluZyBmcm9tIGludGVyZmVyaW5nIHdpdGggdGhlIGRhdGFTY2FsZVxuICAgICAgICB2ZXJ0aWNhbEF4aXNTY2FsZSA9ICduby1zY2FsZSc7XG4gICAgICB9XG4gICAgfVxuICAgIGxldCBob3Jpem9udGFsQXhpc1NjYWxlID0gcHJvdmlkZWRTY2FsaW5nQ29uZmlnPy5ob3Jpem9udGFsQXhpc1NjYWxlO1xuICAgIGlmIChob3Jpem9udGFsQXhpc1NjYWxlID09PSB1bmRlZmluZWQpIHtcbiAgICAgIGlmIChjaGFydERhdGFEaXJlY3Rpb24gPT09ICd2ZXJ0aWNhbCcgfHwgZGF0YVNjYWxlLnR5cGUgPT09ICdmaXQnKSB7XG4gICAgICAgIGhvcml6b250YWxBeGlzU2NhbGUgPVxuICAgICAgICAgIGRlZmF1bHRDb25maWcubm9uRWxlbWVudFNjYWxlcy5ob3Jpem9udGFsQXhpc1NjYWxlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy9UaGUgaG9yaXpvbnRhbCBheGlzIGlzIHRoZSBkYXRhIGF4aXMsIHRoZSBkYXRhU2NhbGUgaGFzIGEgdXNlci1pbnB1dHRlZCB2YWx1ZSwgYW5kIHRoZXJlIGlzbid0IGEgdXNlci1pbnB1dHRlZCBob3Jpem9udGFsQXhpc1NjYWxlXG4gICAgICAgIC8vIFNvLCB3ZSdsbCBwcmV2ZW50IHRoZSBheGlzIHNjYWxpbmcgZnJvbSBpbnRlcmZlcmluZyB3aXRoIHRoZSBkYXRhU2NhbGVcbiAgICAgICAgaG9yaXpvbnRhbEF4aXNTY2FsZSA9ICduby1zY2FsZSc7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICBkYXRhU2NhbGU6XG4gICAgICAgIHByb3ZpZGVkU2NhbGluZ0NvbmZpZyAmJiBwcm92aWRlZFNjYWxpbmdDb25maWcuZGF0YVNjYWxlXG4gICAgICAgICAgPyBwcm92aWRlZFNjYWxpbmdDb25maWcuZGF0YVNjYWxlXG4gICAgICAgICAgOiBkZWZhdWx0Q29uZmlnLm5vbkVsZW1lbnRTY2FsZXMuZGF0YVNjYWxlLFxuICAgICAgaG9yaXpvbnRhbEF4aXNTY2FsZSxcbiAgICAgIHZlcnRpY2FsQXhpc1NjYWxlLFxuICAgICAgaG9yaXpvbnRhbENvbnRhaW5lclNjYWxlOlxuICAgICAgICBwcm92aWRlZFNjYWxpbmdDb25maWcgJiYgcHJvdmlkZWRTY2FsaW5nQ29uZmlnLmhvcml6b250YWxDb250YWluZXJTY2FsZVxuICAgICAgICAgID8gcHJvdmlkZWRTY2FsaW5nQ29uZmlnLmhvcml6b250YWxDb250YWluZXJTY2FsZVxuICAgICAgICAgIDogZGVmYXVsdENvbmZpZy5ub25FbGVtZW50U2NhbGVzLmhvcml6b250YWxDb250YWluZXJTY2FsZSxcbiAgICAgIHZlcnRpY2FsQ29udGFpbmVyU2NhbGU6XG4gICAgICAgIHByb3ZpZGVkU2NhbGluZ0NvbmZpZyAmJiBwcm92aWRlZFNjYWxpbmdDb25maWcudmVydGljYWxDb250YWluZXJTY2FsZVxuICAgICAgICAgID8gcHJvdmlkZWRTY2FsaW5nQ29uZmlnLnZlcnRpY2FsQ29udGFpbmVyU2NhbGVcbiAgICAgICAgICA6IGRlZmF1bHRDb25maWcubm9uRWxlbWVudFNjYWxlcy52ZXJ0aWNhbENvbnRhaW5lclNjYWxlLFxuICAgICAgdGFyZ2V0VGlja0NvdW50OlxuICAgICAgICBwcm92aWRlZFNjYWxpbmdDb25maWcgJiZcbiAgICAgICAgcHJvdmlkZWRTY2FsaW5nQ29uZmlnLnRhcmdldFRpY2tDb3VudCAhPT0gdW5kZWZpbmVkXG4gICAgICAgICAgPyBwcm92aWRlZFNjYWxpbmdDb25maWcudGFyZ2V0VGlja0NvdW50XG4gICAgICAgICAgOiBkZWZhdWx0Q29uZmlnLm5vbkVsZW1lbnRTY2FsZXMudGFyZ2V0VGlja0NvdW50LFxuICAgIH07XG4gIH1cblxuICBmdW5jdGlvbiBpc0RlRW1waGFzaXplZChcbiAgICBjb25maWc6IEZsb3dDb25maWcsXG4gICAgaWQ6IHN0cmluZyxcbiAgICBpc0RhcmtlbmVkOiBib29sZWFuLFxuICApOiBib29sZWFuIHtcbiAgICBjb25zdCBoaWdobGlnaHRlZEJ1Y2tldHMgPSBjb25maWcuZmxvd0NvbmZpZy5zdWJCdWNrZXRzQ29uZmlnXG4gICAgICAuZmlsdGVyKHNiYyA9PiBzYmMuaXNIaWdobGlnaHRlZCA9PT0gdHJ1ZSlcbiAgICAgIC5tYXAoc2JjID0+IHNiYy5idWNrZXRJZCk7XG4gICAgaWYgKGhpZ2hsaWdodGVkQnVja2V0cy5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgaWYgKGlzRGFya2VuZWQpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICBpZiAoaGlnaGxpZ2h0ZWRCdWNrZXRzLnNvbWUoaGIgPT4gaGIgPT09IGlkKSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGNhbGN1bGF0ZUZsb3dDb25uZWN0aW9uUGF0aChcbiAgICBjb25uZWN0aW9uOiBGbG93Q29ubmVjdGlvblJlbmRlcixcbiAgKTogc3RyaW5nIHtcbiAgICBjb25zdCBkeCA9IGNvbm5lY3Rpb24udG9wTGluZS54MiAtIGNvbm5lY3Rpb24udG9wTGluZS54MTtcbiAgICBjb25zdCBjdXJ2ZSA9IE1hdGguYWJzKGR4KSAqIEZMT1dfQ09OTkVDVElPTl9DVVJWRV9DT05TVEFOVDtcblxuICAgIGNvbnN0IHBhdGggPSBgXG4gICAgICBNICR7Y29ubmVjdGlvbi50b3BMaW5lLngxfSwke2Nvbm5lY3Rpb24udG9wTGluZS55MX1cblxuICAgICAgQyAke2Nvbm5lY3Rpb24udG9wTGluZS54MSArIGN1cnZlfSwke2Nvbm5lY3Rpb24udG9wTGluZS55MX1cbiAgICAgICAgJHtjb25uZWN0aW9uLnRvcExpbmUueDIgLSBjdXJ2ZX0sJHtjb25uZWN0aW9uLnRvcExpbmUueTJ9XG4gICAgICAgICR7Y29ubmVjdGlvbi50b3BMaW5lLngyfSwke2Nvbm5lY3Rpb24udG9wTGluZS55Mn1cblxuICAgICAgTCAke2Nvbm5lY3Rpb24uYm90dG9tTGluZS54Mn0sJHtjb25uZWN0aW9uLmJvdHRvbUxpbmUueTJ9XG5cbiAgICAgIEMgJHtjb25uZWN0aW9uLmJvdHRvbUxpbmUueDIgLSBjdXJ2ZX0sJHtjb25uZWN0aW9uLmJvdHRvbUxpbmUueTJ9XG4gICAgICAgICR7Y29ubmVjdGlvbi5ib3R0b21MaW5lLngxICsgY3VydmV9LCR7Y29ubmVjdGlvbi5ib3R0b21MaW5lLnkxfVxuICAgICAgICAke2Nvbm5lY3Rpb24uYm90dG9tTGluZS54MX0sJHtjb25uZWN0aW9uLmJvdHRvbUxpbmUueTF9XG5cbiAgICAgIFpcbiAgICBgO1xuXG4gICAgcmV0dXJuIHBhdGg7XG4gIH1cblxuICBmdW5jdGlvbiBjdWJpYyhcbiAgICBhOiBudW1iZXIsXG4gICAgYjogbnVtYmVyLFxuICAgIGM6IG51bWJlcixcbiAgICBkOiBudW1iZXIsXG4gICAgdDogbnVtYmVyLFxuICApOiBudW1iZXIge1xuICAgIGNvbnN0IG10ID0gMSAtIHQ7XG4gICAgcmV0dXJuIG10ICoqIDMgKiBhICsgMyAqIG10ICoqIDIgKiB0ICogYiArIDMgKiBtdCAqIHQgKiogMiAqIGMgKyB0ICoqIDMgKiBkO1xuICB9XG5cbiAgZnVuY3Rpb24gYmV6aWVyWUF0WChcbiAgICB4OiBudW1iZXIsXG4gICAgbGluZToge1xuICAgICAgeDE6IG51bWJlcjtcbiAgICAgIHkxOiBudW1iZXI7XG4gICAgICB4MjogbnVtYmVyO1xuICAgICAgeTI6IG51bWJlcjtcbiAgICB9LFxuICApOiBudW1iZXIge1xuICAgIGNvbnN0IGN1cnZlID0gTWF0aC5hYnMobGluZS54MiAtIGxpbmUueDEpICogRkxPV19DT05ORUNUSU9OX0NVUlZFX0NPTlNUQU5UO1xuICAgIGNvbnN0IHAwID0geyB4OiBsaW5lLngxLCB5OiBsaW5lLnkxIH07XG4gICAgY29uc3QgcDEgPSB7IHg6IGxpbmUueDEgKyBjdXJ2ZSwgeTogbGluZS55MSB9O1xuICAgIGNvbnN0IHAyID0geyB4OiBsaW5lLngyIC0gY3VydmUsIHk6IGxpbmUueTIgfTtcbiAgICBjb25zdCBwMyA9IHsgeDogbGluZS54MiwgeTogbGluZS55MiB9O1xuXG4gICAgbGV0IGxvID0gMDtcbiAgICBsZXQgaGkgPSAxO1xuXG4gICAgLy8gQmluYXJ5IHNlYXJjaCBmb3IgdCB3aGVyZSBiZXppZXJYKHQpIH49IHhcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IDIwOyBpKyspIHtcbiAgICAgIGNvbnN0IHQgPSAobG8gKyBoaSkgLyAyO1xuICAgICAgY29uc3QgYnggPSBjdWJpYyhwMC54LCBwMS54LCBwMi54LCBwMy54LCB0KTtcblxuICAgICAgaWYgKGJ4IDwgeCkgbG8gPSB0O1xuICAgICAgZWxzZSBoaSA9IHQ7XG4gICAgfVxuXG4gICAgY29uc3QgdCA9IChsbyArIGhpKSAvIDI7XG4gICAgcmV0dXJuIGN1YmljKHAwLnksIHAxLnksIHAyLnksIHAzLnksIHQpO1xuICB9XG5cbiAgZnVuY3Rpb24gY2hlY2tJZlBvaW50V2l0aGluQ29ubmVjdGlvbihcbiAgICBjb25uZWN0aW9uOiBGbG93Q29ubmVjdGlvblJlbmRlcixcbiAgICBwb2ludFg6IG51bWJlcixcbiAgICBwb2ludFk6IG51bWJlcixcbiAgKTogYm9vbGVhbiB7XG4gICAgY29uc3QgdG9wWSA9IGJlemllcllBdFgocG9pbnRYLCBjb25uZWN0aW9uLnRvcExpbmUpO1xuXG4gICAgY29uc3QgYm90dG9tWSA9IGJlemllcllBdFgocG9pbnRYLCBjb25uZWN0aW9uLmJvdHRvbUxpbmUpO1xuXG4gICAgcmV0dXJuIChcbiAgICAgIHBvaW50WCA+PSBjb25uZWN0aW9uLnRvcExpbmUueDEgJiZcbiAgICAgIHBvaW50WCA8PSBjb25uZWN0aW9uLnRvcExpbmUueDIgJiZcbiAgICAgIHBvaW50WSA+PSBNYXRoLm1pbih0b3BZLCBib3R0b21ZKSAmJlxuICAgICAgcG9pbnRZIDw9IE1hdGgubWF4KHRvcFksIGJvdHRvbVkpXG4gICAgKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGdldEZsb3dCdWNrZXRJbmRleEZvckhvdmVyKFxuICAgIGNoYXJ0U2l6aW5nVmFsdWVzOiBGdWxsQ2hhcnRTY2FsZVZhbHVlcyxcbiAgICB4UG9zOiBudW1iZXIsXG4gICk6IHsgaW5kZXg6IG51bWJlcjsgYXJlYTogJ2JhcicgfCAnY29ubmVjdGlvbicgfSB8IG51bGwge1xuICAgIGxldCBidWNrZXRJbmRleCA9IDA7XG4gICAgY29uc3QgYnVja2V0TGVmdEVkZ2UgPSBjaGFydFNpemluZ1ZhbHVlcy50b3RhbExlZnRPZmZzZXQ7XG4gICAgY29uc3QgdG90YWxCdWNrZXRHYXAgPVxuICAgICAgY2hhcnRTaXppbmdWYWx1ZXMuYmFyU2l6ZSArIGNoYXJ0U2l6aW5nVmFsdWVzLmJ1Y2tldEdhcDtcbiAgICBpZiAoYnVja2V0TGVmdEVkZ2UgPiB4UG9zKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgd2hpbGUgKGJ1Y2tldExlZnRFZGdlICsgYnVja2V0SW5kZXggKiB0b3RhbEJ1Y2tldEdhcCA8IHhQb3MpIHtcbiAgICAgIGlmIChidWNrZXRMZWZ0RWRnZSArIChidWNrZXRJbmRleCArIDEpICogdG90YWxCdWNrZXRHYXAgPiB4UG9zKSB7XG4gICAgICAgIGlmIChcbiAgICAgICAgICBidWNrZXRMZWZ0RWRnZSArXG4gICAgICAgICAgICBidWNrZXRJbmRleCAqIHRvdGFsQnVja2V0R2FwICtcbiAgICAgICAgICAgIGNoYXJ0U2l6aW5nVmFsdWVzLmJhclNpemUgPlxuICAgICAgICAgIHhQb3NcbiAgICAgICAgKSB7XG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGluZGV4OiBidWNrZXRJbmRleCxcbiAgICAgICAgICAgIGFyZWE6ICdiYXInLFxuICAgICAgICAgIH07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGluZGV4OiBidWNrZXRJbmRleCxcbiAgICAgICAgICAgIGFyZWE6ICdjb25uZWN0aW9uJyxcbiAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBidWNrZXRJbmRleCArPSAxO1xuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIC8vVGhlc2Ugb3ZlcmxvYWRzIGVuc3VyZSB0aGUgZnVuY3Rpb24ga25vd3MgdGhhdCwgaWYgd2lkdGggYW5kIGhlaWdodCBhcmUgZGVmaW5lZCBvbiBpbnB1dCwgdGhleSdsbCBiZSBkZWZpbmVkIG9uIG91dHB1dFxuICBmdW5jdGlvbiBjaGVja0FuY2hvcnNBZ2FpbnN0Qm91bmQoXG4gICAgYW5jaG9yWDogbnVtYmVyLFxuICAgIGFuY2hvclk6IG51bWJlcixcbiAgICBkaW1lbnNpb25zOiBEaW1lbnNpb25zLFxuICApOiB7IGFuY2hvclg6IG51bWJlcjsgYW5jaG9yWTogbnVtYmVyIH07XG5cbiAgZnVuY3Rpb24gY2hlY2tBbmNob3JzQWdhaW5zdEJvdW5kKFxuICAgIGFuY2hvclg6IG51bWJlcixcbiAgICBhbmNob3JZOiBudW1iZXIsXG4gICAgZGltZW5zaW9uczogRGltZW5zaW9ucyxcbiAgICB3aWR0aDogbnVtYmVyLFxuICAgIGhlaWdodDogbnVtYmVyLFxuICApOiB7XG4gICAgYW5jaG9yWDogbnVtYmVyO1xuICAgIGFuY2hvclk6IG51bWJlcjtcbiAgICBhbmNob3JXaWR0aDogbnVtYmVyO1xuICAgIGFuY2hvckhlaWdodDogbnVtYmVyO1xuICB9O1xuXG4gIGZ1bmN0aW9uIGNoZWNrQW5jaG9yc0FnYWluc3RCb3VuZChcbiAgICBhbmNob3JYOiBudW1iZXIsXG4gICAgYW5jaG9yWTogbnVtYmVyLFxuICAgIGRpbWVuc2lvbnM6IERpbWVuc2lvbnMsXG4gICAgd2lkdGg/OiBudW1iZXIsXG4gICAgaGVpZ2h0PzogbnVtYmVyLFxuICApOiB7XG4gICAgYW5jaG9yWDogbnVtYmVyO1xuICAgIGFuY2hvclk6IG51bWJlcjtcbiAgICBhbmNob3JXaWR0aD86IG51bWJlcjtcbiAgICBhbmNob3JIZWlnaHQ/OiBudW1iZXI7XG4gIH0ge1xuICAgIGxldCByZXRBbmNob3JYID0gYW5jaG9yWDtcbiAgICBsZXQgcmV0QW5jaG9yWSA9IGFuY2hvclk7XG4gICAgbGV0IHJldFdpZHRoOiBudW1iZXIgfCB1bmRlZmluZWQgPSB3aWR0aDtcbiAgICBsZXQgcmV0SGVpZ2h0OiBudW1iZXIgfCB1bmRlZmluZWQgPSBoZWlnaHQ7XG4gICAgaWYgKHJldEFuY2hvclggPiBkaW1lbnNpb25zLndpZHRoKSB7XG4gICAgICByZXRBbmNob3JYID0gZGltZW5zaW9ucy53aWR0aDtcbiAgICAgIGlmIChyZXRXaWR0aCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHJldFdpZHRoID0gMDtcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKHJldEFuY2hvclggPCAwKSB7XG4gICAgICByZXRBbmNob3JYID0gMDtcbiAgICAgIGlmIChyZXRXaWR0aCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHJldFdpZHRoID0gMDtcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKHJldEFuY2hvclkgPiBkaW1lbnNpb25zLmhlaWdodCkge1xuICAgICAgcmV0QW5jaG9yWSA9IGRpbWVuc2lvbnMuaGVpZ2h0O1xuICAgICAgaWYgKHJldEhlaWdodCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHJldEhlaWdodCA9IDA7XG4gICAgICB9XG4gICAgfVxuICAgIGlmIChyZXRBbmNob3JZIDwgMCkge1xuICAgICAgcmV0QW5jaG9yWSA9IDA7XG4gICAgICBpZiAocmV0SGVpZ2h0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgcmV0SGVpZ2h0ID0gMDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgYW5jaG9yWDogcmV0QW5jaG9yWCxcbiAgICAgIGFuY2hvclk6IHJldEFuY2hvclksXG4gICAgICBhbmNob3JXaWR0aDogcmV0V2lkdGgsXG4gICAgICBhbmNob3JIZWlnaHQ6IHJldEhlaWdodCxcbiAgICB9O1xuICB9XG59XG4iXX0=