@rivet-health/design-system 40.44.4 → 41.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (302) hide show
  1. package/fesm2022/rivet-health-design-system.mjs +23103 -18810
  2. package/fesm2022/rivet-health-design-system.mjs.map +1 -1
  3. package/package.json +8 -9
  4. package/types/rivet-health-design-system.d.ts +6566 -0
  5. package/esm2022/lib/accessibility/sr-only/sr-only.component.mjs +0 -18
  6. package/esm2022/lib/download/download.service.mjs +0 -47
  7. package/esm2022/lib/format/pipes/common.mjs +0 -24
  8. package/esm2022/lib/format/pipes/date.pipe.mjs +0 -20
  9. package/esm2022/lib/format/pipes/days.pipe.mjs +0 -20
  10. package/esm2022/lib/format/pipes/dollars.pipe.mjs +0 -19
  11. package/esm2022/lib/format/pipes/number.pipe.mjs +0 -19
  12. package/esm2022/lib/format/pipes/percentage.pipe.mjs +0 -19
  13. package/esm2022/lib/format/pipes/sentence-case.pipe.mjs +0 -61
  14. package/esm2022/lib/format/pipes/small-currency.pipe.mjs +0 -24
  15. package/esm2022/lib/format/pipes/small-number.pipe.mjs +0 -29
  16. package/esm2022/lib/format/svg-text-truncate/svg-text-truncate.directive.mjs +0 -62
  17. package/esm2022/lib/format/truncate/truncate.component.mjs +0 -51
  18. package/esm2022/lib/icon/dom-cache.mjs +0 -32
  19. package/esm2022/lib/icon/icon.component.mjs +0 -86
  20. package/esm2022/lib/icon/icons.mjs +0 -271
  21. package/esm2022/lib/input/alphabetic-field/alphabetic-field.component.mjs +0 -42
  22. package/esm2022/lib/input/auto-focus/auto-focus.directive.mjs +0 -48
  23. package/esm2022/lib/input/button/button.component.mjs +0 -139
  24. package/esm2022/lib/input/button-group/button-group.component.mjs +0 -39
  25. package/esm2022/lib/input/calendar/calendar.component.mjs +0 -318
  26. package/esm2022/lib/input/card-checkbox/card-checkbox.component.mjs +0 -13
  27. package/esm2022/lib/input/checkbox/checkbox.component.mjs +0 -84
  28. package/esm2022/lib/input/currency-field/currency-field.component.mjs +0 -26
  29. package/esm2022/lib/input/date/date.component.mjs +0 -279
  30. package/esm2022/lib/input/date-range/date-range.component.mjs +0 -478
  31. package/esm2022/lib/input/filter-chip/filter-chip.component.mjs +0 -47
  32. package/esm2022/lib/input/filter-dropdown/filter-dropdown.component.mjs +0 -89
  33. package/esm2022/lib/input/input-label/input-label.component.mjs +0 -38
  34. package/esm2022/lib/input/mentions-input/mentions-input.component.mjs +0 -745
  35. package/esm2022/lib/input/number-field/number-field.component.mjs +0 -125
  36. package/esm2022/lib/input/percentage-field/percentage-field.component.mjs +0 -20
  37. package/esm2022/lib/input/phone-field/phone-field.component.mjs +0 -74
  38. package/esm2022/lib/input/radio/radio.component.mjs +0 -58
  39. package/esm2022/lib/input/search/search.component.mjs +0 -26
  40. package/esm2022/lib/input/search-select/search-select.component.mjs +0 -189
  41. package/esm2022/lib/input/select/select/select.component.mjs +0 -179
  42. package/esm2022/lib/input/select/select-node/select-node.component.mjs +0 -60
  43. package/esm2022/lib/input/select/state.mjs +0 -882
  44. package/esm2022/lib/input/simple-select/option-group.pipe.mjs +0 -19
  45. package/esm2022/lib/input/simple-select/simple-select.component.mjs +0 -178
  46. package/esm2022/lib/input/switch-checkbox/switch-checkbox.component.mjs +0 -33
  47. package/esm2022/lib/input/text-field/text-field.component.mjs +0 -115
  48. package/esm2022/lib/input/textarea-field/textarea-field.component.mjs +0 -21
  49. package/esm2022/lib/input/validation-message/validation-message.component.mjs +0 -17
  50. package/esm2022/lib/layout/card/card-actions.component.mjs +0 -72
  51. package/esm2022/lib/layout/card/card-content.component.mjs +0 -64
  52. package/esm2022/lib/layout/card/card-header.component.mjs +0 -201
  53. package/esm2022/lib/layout/card/card-link.component.mjs +0 -115
  54. package/esm2022/lib/layout/card/card-media.component.mjs +0 -70
  55. package/esm2022/lib/layout/card/card.component.mjs +0 -306
  56. package/esm2022/lib/layout/setting-row/setting-row.component.mjs +0 -111
  57. package/esm2022/lib/load/loading/loading.component.mjs +0 -43
  58. package/esm2022/lib/load/loading-cover/loading-cover.component.mjs +0 -25
  59. package/esm2022/lib/navigation/editable-heading/editable-heading.component.mjs +0 -243
  60. package/esm2022/lib/navigation/link/link.component.mjs +0 -48
  61. package/esm2022/lib/navigation/page-header/page-header.component.mjs +0 -68
  62. package/esm2022/lib/navigation/simple-tabs/simple-tab/simple-tab.component.mjs +0 -43
  63. package/esm2022/lib/navigation/simple-tabs/simple-tabs/simple-tabs.component.mjs +0 -11
  64. package/esm2022/lib/navigation/tabs/tab/tab.component.mjs +0 -16
  65. package/esm2022/lib/navigation/tabs/tabs/tabs.component.mjs +0 -11
  66. package/esm2022/lib/navigation/views/all-views-modal/all-views-modal.component.mjs +0 -43
  67. package/esm2022/lib/navigation/views/edit-view/edit-view.component.mjs +0 -118
  68. package/esm2022/lib/navigation/views/permission-picker/permission-picker.component.mjs +0 -151
  69. package/esm2022/lib/navigation/views/state.mjs +0 -456
  70. package/esm2022/lib/navigation/views/view-menu/view-menu.component.mjs +0 -30
  71. package/esm2022/lib/navigation/views/views/views.component.mjs +0 -90
  72. package/esm2022/lib/notification/badge/badge.component.mjs +0 -45
  73. package/esm2022/lib/notification/banner/banner-action.component.mjs +0 -48
  74. package/esm2022/lib/notification/banner/banner.component.mjs +0 -61
  75. package/esm2022/lib/notification/map-indicator/map-indicator.component.mjs +0 -50
  76. package/esm2022/lib/notification/map-indicator/map-indicators.mjs +0 -15
  77. package/esm2022/lib/notification/notification-badge/notification-badge.component.mjs +0 -26
  78. package/esm2022/lib/overlay/callout/callout.component.mjs +0 -130
  79. package/esm2022/lib/overlay/callout/callout.helpers.mjs +0 -113
  80. package/esm2022/lib/overlay/callout/help/help.component.mjs +0 -23
  81. package/esm2022/lib/overlay/callout/lock-scroll.directive.mjs +0 -69
  82. package/esm2022/lib/overlay/callout/menu/menu-item/menu-item.component.mjs +0 -71
  83. package/esm2022/lib/overlay/callout/menu/menu.component.mjs +0 -39
  84. package/esm2022/lib/overlay/callout/select-callout-defaults.mjs +0 -13
  85. package/esm2022/lib/overlay/callout/tooltip/locked-tooltip.directive.mjs +0 -30
  86. package/esm2022/lib/overlay/callout/tooltip/tooltip.component.mjs +0 -57
  87. package/esm2022/lib/overlay/callout/tooltip/tooltip.directive.mjs +0 -138
  88. package/esm2022/lib/overlay/modal/dialog/dialog.component.mjs +0 -47
  89. package/esm2022/lib/overlay/modal/dialog-stack.service.mjs +0 -41
  90. package/esm2022/lib/overlay/modal/form-dialog/form-dialog.component.mjs +0 -146
  91. package/esm2022/lib/overlay/modal/modal.component.mjs +0 -31
  92. package/esm2022/lib/overlay/modal/side-sheet/side-sheet.component.mjs +0 -30
  93. package/esm2022/lib/overlay/overlay-outlet.component.mjs +0 -98
  94. package/esm2022/lib/overlay/overlay.directive.mjs +0 -25
  95. package/esm2022/lib/overlay/overlay.service.mjs +0 -35
  96. package/esm2022/lib/overlay/toast/toast-action.component.mjs +0 -11
  97. package/esm2022/lib/overlay/toast/toast.component.mjs +0 -41
  98. package/esm2022/lib/riv.module.mjs +0 -580
  99. package/esm2022/lib/size/size.directive.mjs +0 -33
  100. package/esm2022/lib/table/simple-table/coordinate-helper.mjs +0 -61
  101. package/esm2022/lib/table/simple-table/simple-table-cell.component.mjs +0 -36
  102. package/esm2022/lib/table/simple-table/simple-table-header-cell.component.mjs +0 -37
  103. package/esm2022/lib/table/simple-table/simple-table-row.component.mjs +0 -19
  104. package/esm2022/lib/table/simple-table/simple-table.component.mjs +0 -104
  105. package/esm2022/lib/table/table/clipboard.mjs +0 -182
  106. package/esm2022/lib/table/table/state-helpers/collapse-helpers.mjs +0 -116
  107. package/esm2022/lib/table/table/state-helpers/column-helpers.mjs +0 -383
  108. package/esm2022/lib/table/table/state-helpers/display-helpers.mjs +0 -50
  109. package/esm2022/lib/table/table/state-helpers/nesting-helpers.mjs +0 -123
  110. package/esm2022/lib/table/table/state-helpers/order-helpers.mjs +0 -164
  111. package/esm2022/lib/table/table/state-helpers/pagination-helpers.mjs +0 -139
  112. package/esm2022/lib/table/table/state-helpers/result-helpers.mjs +0 -70
  113. package/esm2022/lib/table/table/state-helpers/search-helpers.mjs +0 -72
  114. package/esm2022/lib/table/table/state-helpers/selection-helpers.mjs +0 -180
  115. package/esm2022/lib/table/table/state.mjs +0 -1035
  116. package/esm2022/lib/table/table/table/table.component.mjs +0 -367
  117. package/esm2022/lib/table/table/table-collapse-all/table-collapse-all.component.mjs +0 -25
  118. package/esm2022/lib/table/table/table-column-settings/table-column-settings-side-sheet.component.mjs +0 -227
  119. package/esm2022/lib/table/table/table-column-settings/table-column-settings.component.mjs +0 -134
  120. package/esm2022/lib/table/table/table-csv-export/table-csv-export.component.mjs +0 -35
  121. package/esm2022/lib/table/table/table-header-resize-handle/table-header-resize-handle.component.mjs +0 -28
  122. package/esm2022/lib/table/table/table-search/table-search.component.mjs +0 -71
  123. package/esm2022/lib/table/table/table-search-columns/table-search-columns.component.mjs +0 -57
  124. package/esm2022/lib/util/local-storage.mjs +0 -17
  125. package/esm2022/lib/visibility/visibility.directive.mjs +0 -34
  126. package/esm2022/lib/visualization/chart/chart-scaling.mjs +0 -380
  127. package/esm2022/lib/visualization/chart/chart.component.mjs +0 -626
  128. package/esm2022/lib/visualization/chart/chart.mjs +0 -3768
  129. package/esm2022/lib/visualization/data-table/data-table-cell.component.mjs +0 -22
  130. package/esm2022/lib/visualization/data-table/data-table-header-cell.component.mjs +0 -11
  131. package/esm2022/lib/visualization/data-table/data-table-row.component.mjs +0 -19
  132. package/esm2022/lib/visualization/data-table/data-table.component.mjs +0 -17
  133. package/esm2022/lib/visualization/donut/donut.component.mjs +0 -54
  134. package/esm2022/lib/visualization/funnel-chart/funnel-chart.component.mjs +0 -73
  135. package/esm2022/lib/visualization/funnel-chart/funnel-chart.helpers.mjs +0 -33
  136. package/esm2022/lib/visualization/highlight/highlight.component.mjs +0 -24
  137. package/esm2022/lib/visualization/highlight/highlight.helpers.mjs +0 -20
  138. package/esm2022/lib/visualization/intervals.mjs +0 -63
  139. package/esm2022/lib/visualization/issue/issue.component.mjs +0 -30
  140. package/esm2022/lib/visualization/legend-item/legend-item.component.mjs +0 -49
  141. package/esm2022/lib/visualization/metric/metric.component.mjs +0 -52
  142. package/esm2022/lib/visualization/mini-pie/mini-pie.component.mjs +0 -51
  143. package/esm2022/lib/visualization/progress/progress.component.mjs +0 -24
  144. package/esm2022/lib/visualization/stacked-column/stacked-column.component.mjs +0 -377
  145. package/esm2022/lib/visualization/stacked-column/stacked-column.helpers.mjs +0 -18
  146. package/esm2022/lib/visualization/stacked-row/stacked-row.component.mjs +0 -270
  147. package/esm2022/lib/visualization/stacked-row/stacked-row.helpers.mjs +0 -74
  148. package/esm2022/lib/visualization/time-series/time-series.component.mjs +0 -374
  149. package/esm2022/lib/visualization/time-series/time-series.helpers.mjs +0 -15
  150. package/esm2022/lib/visualization/trend/trend.component.mjs +0 -51
  151. package/esm2022/lib/visualization/zero-state/zero-state.component.mjs +0 -22
  152. package/esm2022/public-api.mjs +0 -118
  153. package/esm2022/rivet-health-design-system.mjs +0 -5
  154. package/index.d.ts +0 -5
  155. package/lib/accessibility/sr-only/sr-only.component.d.ts +0 -12
  156. package/lib/download/download.service.d.ts +0 -9
  157. package/lib/format/pipes/common.d.ts +0 -6
  158. package/lib/format/pipes/date.pipe.d.ts +0 -8
  159. package/lib/format/pipes/days.pipe.d.ts +0 -8
  160. package/lib/format/pipes/dollars.pipe.d.ts +0 -9
  161. package/lib/format/pipes/number.pipe.d.ts +0 -8
  162. package/lib/format/pipes/percentage.pipe.d.ts +0 -8
  163. package/lib/format/pipes/sentence-case.pipe.d.ts +0 -8
  164. package/lib/format/pipes/small-currency.pipe.d.ts +0 -8
  165. package/lib/format/pipes/small-number.pipe.d.ts +0 -8
  166. package/lib/format/svg-text-truncate/svg-text-truncate.directive.d.ts +0 -14
  167. package/lib/format/truncate/truncate.component.d.ts +0 -17
  168. package/lib/icon/dom-cache.d.ts +0 -13
  169. package/lib/icon/icon.component.d.ts +0 -27
  170. package/lib/icon/icons.d.ts +0 -137
  171. package/lib/input/alphabetic-field/alphabetic-field.component.d.ts +0 -14
  172. package/lib/input/auto-focus/auto-focus.directive.d.ts +0 -21
  173. package/lib/input/button/button.component.d.ts +0 -37
  174. package/lib/input/button-group/button-group.component.d.ts +0 -11
  175. package/lib/input/calendar/calendar.component.d.ts +0 -67
  176. package/lib/input/card-checkbox/card-checkbox.component.d.ts +0 -6
  177. package/lib/input/checkbox/checkbox.component.d.ts +0 -32
  178. package/lib/input/currency-field/currency-field.component.d.ts +0 -9
  179. package/lib/input/date/date.component.d.ts +0 -62
  180. package/lib/input/date-range/date-range.component.d.ts +0 -97
  181. package/lib/input/filter-chip/filter-chip.component.d.ts +0 -13
  182. package/lib/input/filter-dropdown/filter-dropdown.component.d.ts +0 -30
  183. package/lib/input/input-label/input-label.component.d.ts +0 -17
  184. package/lib/input/mentions-input/mentions-input.component.d.ts +0 -93
  185. package/lib/input/number-field/number-field.component.d.ts +0 -36
  186. package/lib/input/percentage-field/percentage-field.component.d.ts +0 -7
  187. package/lib/input/phone-field/phone-field.component.d.ts +0 -17
  188. package/lib/input/radio/radio.component.d.ts +0 -28
  189. package/lib/input/search/search.component.d.ts +0 -10
  190. package/lib/input/search-select/search-select.component.d.ts +0 -62
  191. package/lib/input/select/select/select.component.d.ts +0 -63
  192. package/lib/input/select/select-node/select-node.component.d.ts +0 -30
  193. package/lib/input/select/state.d.ts +0 -250
  194. package/lib/input/simple-select/option-group.pipe.d.ts +0 -8
  195. package/lib/input/simple-select/simple-select.component.d.ts +0 -63
  196. package/lib/input/switch-checkbox/switch-checkbox.component.d.ts +0 -18
  197. package/lib/input/text-field/text-field.component.d.ts +0 -38
  198. package/lib/input/textarea-field/textarea-field.component.d.ts +0 -8
  199. package/lib/input/validation-message/validation-message.component.d.ts +0 -6
  200. package/lib/layout/card/card-actions.component.d.ts +0 -38
  201. package/lib/layout/card/card-content.component.d.ts +0 -33
  202. package/lib/layout/card/card-header.component.d.ts +0 -132
  203. package/lib/layout/card/card-link.component.d.ts +0 -64
  204. package/lib/layout/card/card-media.component.d.ts +0 -43
  205. package/lib/layout/card/card.component.d.ts +0 -225
  206. package/lib/layout/setting-row/setting-row.component.d.ts +0 -72
  207. package/lib/load/loading/loading.component.d.ts +0 -17
  208. package/lib/load/loading-cover/loading-cover.component.d.ts +0 -10
  209. package/lib/navigation/editable-heading/editable-heading.component.d.ts +0 -118
  210. package/lib/navigation/link/link.component.d.ts +0 -19
  211. package/lib/navigation/page-header/page-header.component.d.ts +0 -50
  212. package/lib/navigation/simple-tabs/simple-tab/simple-tab.component.d.ts +0 -11
  213. package/lib/navigation/simple-tabs/simple-tabs/simple-tabs.component.d.ts +0 -5
  214. package/lib/navigation/tabs/tab/tab.component.d.ts +0 -6
  215. package/lib/navigation/tabs/tabs/tabs.component.d.ts +0 -5
  216. package/lib/navigation/views/all-views-modal/all-views-modal.component.d.ts +0 -14
  217. package/lib/navigation/views/edit-view/edit-view.component.d.ts +0 -31
  218. package/lib/navigation/views/permission-picker/permission-picker.component.d.ts +0 -37
  219. package/lib/navigation/views/state.d.ts +0 -175
  220. package/lib/navigation/views/view-menu/view-menu.component.d.ts +0 -13
  221. package/lib/navigation/views/views/views.component.d.ts +0 -25
  222. package/lib/notification/badge/badge.component.d.ts +0 -14
  223. package/lib/notification/banner/banner-action.component.d.ts +0 -15
  224. package/lib/notification/banner/banner.component.d.ts +0 -25
  225. package/lib/notification/map-indicator/map-indicator.component.d.ts +0 -24
  226. package/lib/notification/map-indicator/map-indicators.d.ts +0 -9
  227. package/lib/notification/notification-badge/notification-badge.component.d.ts +0 -11
  228. package/lib/overlay/callout/callout.component.d.ts +0 -36
  229. package/lib/overlay/callout/callout.helpers.d.ts +0 -16
  230. package/lib/overlay/callout/help/help.component.d.ts +0 -11
  231. package/lib/overlay/callout/lock-scroll.directive.d.ts +0 -22
  232. package/lib/overlay/callout/menu/menu-item/menu-item.component.d.ts +0 -27
  233. package/lib/overlay/callout/menu/menu.component.d.ts +0 -17
  234. package/lib/overlay/callout/select-callout-defaults.d.ts +0 -5
  235. package/lib/overlay/callout/tooltip/locked-tooltip.directive.d.ts +0 -14
  236. package/lib/overlay/callout/tooltip/tooltip.component.d.ts +0 -26
  237. package/lib/overlay/callout/tooltip/tooltip.directive.d.ts +0 -48
  238. package/lib/overlay/modal/dialog/dialog.component.d.ts +0 -19
  239. package/lib/overlay/modal/dialog-stack.service.d.ts +0 -23
  240. package/lib/overlay/modal/form-dialog/form-dialog.component.d.ts +0 -63
  241. package/lib/overlay/modal/modal.component.d.ts +0 -11
  242. package/lib/overlay/modal/side-sheet/side-sheet.component.d.ts +0 -13
  243. package/lib/overlay/overlay-outlet.component.d.ts +0 -19
  244. package/lib/overlay/overlay.directive.d.ts +0 -13
  245. package/lib/overlay/overlay.service.d.ts +0 -14
  246. package/lib/overlay/toast/toast-action.component.d.ts +0 -5
  247. package/lib/overlay/toast/toast.component.d.ts +0 -17
  248. package/lib/riv.module.d.ts +0 -122
  249. package/lib/size/size.directive.d.ts +0 -12
  250. package/lib/table/simple-table/coordinate-helper.d.ts +0 -13
  251. package/lib/table/simple-table/simple-table-cell.component.d.ts +0 -19
  252. package/lib/table/simple-table/simple-table-header-cell.component.d.ts +0 -20
  253. package/lib/table/simple-table/simple-table-row.component.d.ts +0 -6
  254. package/lib/table/simple-table/simple-table.component.d.ts +0 -11
  255. package/lib/table/table/clipboard.d.ts +0 -38
  256. package/lib/table/table/state-helpers/collapse-helpers.d.ts +0 -9
  257. package/lib/table/table/state-helpers/column-helpers.d.ts +0 -29
  258. package/lib/table/table/state-helpers/display-helpers.d.ts +0 -5
  259. package/lib/table/table/state-helpers/nesting-helpers.d.ts +0 -13
  260. package/lib/table/table/state-helpers/order-helpers.d.ts +0 -13
  261. package/lib/table/table/state-helpers/pagination-helpers.d.ts +0 -12
  262. package/lib/table/table/state-helpers/result-helpers.d.ts +0 -10
  263. package/lib/table/table/state-helpers/search-helpers.d.ts +0 -17
  264. package/lib/table/table/state-helpers/selection-helpers.d.ts +0 -13
  265. package/lib/table/table/state.d.ts +0 -512
  266. package/lib/table/table/table/table.component.d.ts +0 -88
  267. package/lib/table/table/table-collapse-all/table-collapse-all.component.d.ts +0 -10
  268. package/lib/table/table/table-column-settings/table-column-settings-side-sheet.component.d.ts +0 -52
  269. package/lib/table/table/table-column-settings/table-column-settings.component.d.ts +0 -37
  270. package/lib/table/table/table-csv-export/table-csv-export.component.d.ts +0 -14
  271. package/lib/table/table/table-header-resize-handle/table-header-resize-handle.component.d.ts +0 -11
  272. package/lib/table/table/table-search/table-search.component.d.ts +0 -21
  273. package/lib/table/table/table-search-columns/table-search-columns.component.d.ts +0 -23
  274. package/lib/util/local-storage.d.ts +0 -14
  275. package/lib/visibility/visibility.directive.d.ts +0 -12
  276. package/lib/visualization/chart/chart-scaling.d.ts +0 -100
  277. package/lib/visualization/chart/chart.component.d.ts +0 -116
  278. package/lib/visualization/chart/chart.d.ts +0 -354
  279. package/lib/visualization/data-table/data-table-cell.component.d.ts +0 -11
  280. package/lib/visualization/data-table/data-table-header-cell.component.d.ts +0 -5
  281. package/lib/visualization/data-table/data-table-row.component.d.ts +0 -6
  282. package/lib/visualization/data-table/data-table.component.d.ts +0 -6
  283. package/lib/visualization/donut/donut.component.d.ts +0 -22
  284. package/lib/visualization/funnel-chart/funnel-chart.component.d.ts +0 -30
  285. package/lib/visualization/funnel-chart/funnel-chart.helpers.d.ts +0 -4
  286. package/lib/visualization/highlight/highlight.component.d.ts +0 -15
  287. package/lib/visualization/highlight/highlight.helpers.d.ts +0 -2
  288. package/lib/visualization/intervals.d.ts +0 -8
  289. package/lib/visualization/issue/issue.component.d.ts +0 -10
  290. package/lib/visualization/legend-item/legend-item.component.d.ts +0 -22
  291. package/lib/visualization/metric/metric.component.d.ts +0 -20
  292. package/lib/visualization/mini-pie/mini-pie.component.d.ts +0 -17
  293. package/lib/visualization/progress/progress.component.d.ts +0 -8
  294. package/lib/visualization/stacked-column/stacked-column.component.d.ts +0 -129
  295. package/lib/visualization/stacked-column/stacked-column.helpers.d.ts +0 -3
  296. package/lib/visualization/stacked-row/stacked-row.component.d.ts +0 -109
  297. package/lib/visualization/stacked-row/stacked-row.helpers.d.ts +0 -53
  298. package/lib/visualization/time-series/time-series.component.d.ts +0 -126
  299. package/lib/visualization/time-series/time-series.helpers.d.ts +0 -34
  300. package/lib/visualization/trend/trend.component.d.ts +0 -13
  301. package/lib/visualization/zero-state/zero-state.component.d.ts +0 -9
  302. package/public-api.d.ts +0 -118
@@ -1,3768 +0,0 @@
1
- import { CurrencyPipe } from '@angular/common';
2
- import { scaleLinear } from 'd3-scale';
3
- import { arc, area, line, pie } from 'd3-shape';
4
- import { utcFormat } from 'd3-time-format';
5
- import { sum, uniq } from 'lodash';
6
- import { DaysPipe } from '../../format/pipes/days.pipe';
7
- import { NumberPipe } from '../../format/pipes/number.pipe';
8
- import { PercentagePipe } from '../../format/pipes/percentage.pipe';
9
- import { SmallCurrencyPipe } from '../../format/pipes/small-currency.pipe';
10
- import { SmallNumberPipe } from '../../format/pipes/small-number.pipe';
11
- import { DefaultDonutSizingConfig, emptyChartScaleValues, getDefaultScalingConfigByChartType, } from './chart-scaling';
12
- export var Chart;
13
- (function (Chart) {
14
- Chart.defaultColorPalette = [
15
- //Base colors
16
- '--baja-blast-50',
17
- '--teal-diamond-50',
18
- '--fyre-50',
19
- '--tang-50',
20
- '--purp-60',
21
- '--rosi-70',
22
- //Shift lighter from base by -20
23
- '--baja-blast-30',
24
- '--teal-diamond-30',
25
- '--fyre-30',
26
- '--tang-30',
27
- '--purp-40',
28
- '--rosi-50',
29
- //Shift darker from base by +20
30
- '--baja-blast-70',
31
- '--teal-diamond-70',
32
- '--fyre-70',
33
- '--tang-70',
34
- '--purp-80',
35
- '--rosi-90',
36
- ];
37
- function chart(config, data, dimensions) {
38
- return config.type === 'line'
39
- ? lines(config, data, dimensions)
40
- : config.type === 'area'
41
- ? areas(config, data, dimensions)
42
- : config.type === 'donut'
43
- ? arcs(config, data, dimensions)
44
- : config.type === 'horizontal-bar'
45
- ? horizontalBars(config, data, dimensions)
46
- : config.type === 'bar'
47
- ? bars(config, data, dimensions)
48
- : config.type === 'waterfall'
49
- ? waterfall(config, data, dimensions)
50
- : config.type === 'funnel'
51
- ? funnel(config, data, dimensions)
52
- : config.type === 'flow'
53
- ? flows(config, data, dimensions)
54
- : emptyChart;
55
- }
56
- Chart.chart = chart;
57
- function lines(config, allData, dimensions) {
58
- if (!warnFlowData(allData, 'line')) {
59
- return { ...emptyChart, chartError: 'config' };
60
- }
61
- const { data: hiddenData, visibleIndices } = hide(allData);
62
- if (hiddenData.type === 'labeled') {
63
- // eslint-disable-next-line no-console
64
- console.warn("Heads up! Labeled series aren't currently supported for line charts");
65
- return emptyChart;
66
- }
67
- if (hasSupplementaryData(hiddenData)) {
68
- // eslint-disable-next-line no-console
69
- console.warn("Heads up! Supplementary y values aren't supported for non-bar charts");
70
- return emptyChart;
71
- }
72
- warnUnsupportedPatterns(hiddenData, ['striped', 'dots'], 'line');
73
- //This assignment makes typescript recognize the actual type (TimeseriesData)
74
- const data = hiddenData;
75
- const { dateFormat, pipeTransform, colors } = getFormattingAndColors(allData, data, config);
76
- const chartSizingValues = getFullChartScaleValues(config, data, dimensions, pipeTransform, dateFormat);
77
- if (chartSizingValues === null) {
78
- return { ...emptyChart, chartError: 'sizing' };
79
- }
80
- const tickCount = getBucketTickCount(chartSizingValues);
81
- const xTicks = generateTimeseriesTicks(data, config, tickCount, chartSizingValues, dateFormat).map(tick => toXTick(tick));
82
- const xScale = (index) => {
83
- return (chartSizingValues.totalLeftOffset + chartSizingValues.bucketGap * index);
84
- };
85
- const { scale, ticks: dataTicks } = calcDataAxisScalesAndTicks(data, pipeTransform, config, chartSizingValues);
86
- const yTicks = dataTicks.map(tick => toYTick(tick));
87
- const indices = data.x.map((_, i) => i);
88
- const lines = data.x.length > 1
89
- ? data.ys.map(y => ({
90
- line: line(i => xScale(i), i => scale(y.values[i], y.isSecondary))(indices),
91
- pattern: y.pattern,
92
- }))
93
- : [];
94
- const circles = data.x.length === 1
95
- ? data.ys.map((ySeries, i) => ({
96
- cx: xScale(0),
97
- cy: scale(ySeries.values[0], checkIfSecondary(data, i, 0)),
98
- }))
99
- : [];
100
- const yOffset = chartSizingValues.dataLabelPadding;
101
- const dataLabels = data.ys.flatMap((y, yIndex) => {
102
- const subLabels = y.values.map((val, xIndex) => ({
103
- elementType: 'dataLabel',
104
- label: pipeTransform(val, checkIfSecondary(data, yIndex, xIndex)),
105
- yPos: scale(val, checkIfSecondary(data, yIndex, xIndex)) - yOffset,
106
- xPos: xScale(xIndex),
107
- anchor: 'middle',
108
- }));
109
- return subLabels;
110
- });
111
- function hover(pos) {
112
- const realPosX = pos.x + pos.containerScrollX;
113
- const realPosY = pos.y + pos.containerScrollY;
114
- if (chartSizingValues === null ||
115
- getIfHoverOutOfBounds(pos.x, pos.y, realPosX, realPosY, chartSizingValues, dimensions)) {
116
- return null;
117
- }
118
- const xHoverIndices = getBucketAndClusterNumForHover(realPosX, chartSizingValues, data, config, data.x.length);
119
- if (!xHoverIndices) {
120
- return null;
121
- }
122
- const { bucketNum: xIndex } = xHoverIndices;
123
- const x = xScale(xIndex);
124
- const visibleYIndex = findNearestIndexWithSecondary(data.ys.map((y, i) => ({
125
- value: y.values[xIndex],
126
- isSecondary: checkIfSecondary(data, i, xIndex),
127
- })), pos.y, scale);
128
- const yIndex = visibleIndices[visibleYIndex];
129
- const ys = data.ys.map((y, i) => scale(y.values[xIndex], checkIfSecondary(data, i, xIndex)));
130
- const format = (date) => formatedDate(config.dateFormat || 'day', date);
131
- // Clamp in chart-local coordinates first so the tooltip stays within the
132
- // visible chart area, then translate to viewport coordinates by adding
133
- // pos.rect.x/y (which are viewport-relative from getBoundingClientRect).
134
- const localAnchorX = x - pos.containerScrollX;
135
- const localAnchorY = ys[visibleYIndex] - pos.containerScrollY;
136
- const { anchorX, anchorY } = checkAnchorsAgainstBound(localAnchorX, localAnchorY, dimensions);
137
- const anchor = new DOMRect(anchorX + pos.rect.x, anchorY + pos.rect.y, SMALL_PADDING, 0);
138
- return {
139
- hoverType: 'standard',
140
- x,
141
- xIndex,
142
- ys,
143
- yIndex,
144
- visibleYIndex,
145
- tooltip: {
146
- anchor,
147
- date: format(new Date(data.x[xIndex])),
148
- metrics: data.ys
149
- .map((y, index) => ({
150
- color: colors[index % colors.length],
151
- label: y.label,
152
- pattern: y.pattern,
153
- value: pipeTransform(y.values[xIndex], checkIfSecondary(data, index, xIndex), true) ?? '-',
154
- }))
155
- .filter((_, i) => config.groupedTooltip || i === visibleYIndex),
156
- },
157
- };
158
- }
159
- return {
160
- chartWidth: chartSizingValues.totalWidth,
161
- chartHeight: chartSizingValues.totalHeight,
162
- chartSizingValues,
163
- xTicks,
164
- yTicks,
165
- colors,
166
- lines,
167
- circles,
168
- hover,
169
- bars: [],
170
- areas: [],
171
- arcs: [],
172
- horizontalBars: [],
173
- dataLabels,
174
- waterfallLines: [],
175
- gradients: [],
176
- flowConnections: [],
177
- horizontalContainerScale: chartSizingValues.horizontalContainerScale,
178
- verticalContainerScale: chartSizingValues.verticalContainerScale,
179
- chartError: null,
180
- };
181
- }
182
- function areas(config, allData, dimensions) {
183
- if (!warnFlowData(allData, 'area')) {
184
- return { ...emptyChart, chartError: 'config' };
185
- }
186
- const { data: uncheckedData, visibleIndices } = hide(allData);
187
- if (uncheckedData.type === 'labeled') {
188
- // eslint-disable-next-line no-console
189
- console.warn("Heads up! Labeled series aren't currently supported for area charts");
190
- return emptyChart;
191
- }
192
- if (config.showDataLabels === true) {
193
- // eslint-disable-next-line no-console
194
- console.warn("Heads up! Data labels aren't supported for any stacked chart type");
195
- return emptyChart;
196
- }
197
- if (hasSupplementaryData(uncheckedData)) {
198
- // eslint-disable-next-line no-console
199
- console.warn("Heads up! Supplementary y values aren't supported for non-bar charts");
200
- return emptyChart;
201
- }
202
- warnUnsupportedPatterns(uncheckedData, ['striped'], 'area');
203
- //This assignment makes typescript recognize the actual type (TimeseriesData)
204
- const data = uncheckedData;
205
- const { dateFormat, pipeTransform, colors } = getFormattingAndColors(allData, data, config);
206
- const chartSizingValues = getFullChartScaleValues(config, data, dimensions, pipeTransform, dateFormat);
207
- if (chartSizingValues === null) {
208
- return { ...emptyChart, chartError: 'sizing' };
209
- }
210
- const tickCount = getBucketTickCount(chartSizingValues);
211
- const xTicks = generateTimeseriesTicks(data, config, tickCount, chartSizingValues, dateFormat).map(tick => toXTick(tick));
212
- const xScale = (index) => {
213
- return (chartSizingValues.totalLeftOffset + chartSizingValues.bucketGap * index);
214
- };
215
- const { scale, ticks: dataTicks } = calcDataAxisScalesAndTicks(data, pipeTransform, config, chartSizingValues);
216
- const yTicks = dataTicks.map(tick => toYTick(tick));
217
- const zeroAxisPosVal = scale(0, true);
218
- const indices = data.x.map((_, i) => i);
219
- const areas = data.ys.map((y, yIndex) => ({
220
- pattern: y.pattern,
221
- area: area(i => xScale(i), i => getBarYInfo(data, config, yIndex, i, scale).yValue, i => getBarYInfo(data, config, yIndex, i, scale).yValue +
222
- getBarYInfo(data, config, yIndex, i, scale).height)(indices),
223
- }));
224
- function hover(pos) {
225
- const realPosX = pos.x + pos.containerScrollX;
226
- const realPosY = pos.y + pos.containerScrollY;
227
- if (chartSizingValues === null ||
228
- getIfHoverOutOfBounds(pos.x, pos.y, realPosX, realPosY, chartSizingValues, dimensions)) {
229
- return null;
230
- }
231
- const xHoverIndices = getBucketAndClusterNumForHover(realPosX, chartSizingValues, data, config, data.x.length);
232
- if (!xHoverIndices) {
233
- return null;
234
- }
235
- const { bucketNum: xIndex } = xHoverIndices;
236
- const x = xScale(xIndex);
237
- const fullYs = data.ys.map((_, mapYIndex) => getBarYInfo(data, config, mapYIndex, xIndex, scale));
238
- const ys = fullYs.map(y => y.yValue);
239
- //This is the ys array, but shifted so that the y position for negative values is away from the axis (for the hover circles)
240
- const shiftedYs = fullYs.map(y => {
241
- if (y.yValue >= zeroAxisPosVal) {
242
- return y.yValue + y.height;
243
- }
244
- return y.yValue;
245
- });
246
- const yPosSign = zeroAxisPosVal - pos.y;
247
- let visibleYIndex = -1;
248
- if (yPosSign < 0 && data.ys.find(y => y.values.find(val => val < 0))) {
249
- for (let i = ys.length - 1; i >= 0; i--) {
250
- if (ys[i] >= zeroAxisPosVal && ys[i] < pos.y) {
251
- visibleYIndex = i;
252
- break;
253
- }
254
- }
255
- }
256
- else {
257
- for (let i = 0; i < ys.length; i++) {
258
- if (ys[i] <= zeroAxisPosVal && ys[i] < pos.y) {
259
- visibleYIndex = i;
260
- break;
261
- }
262
- }
263
- }
264
- if (visibleYIndex === -1) {
265
- if (pos.y <= zeroAxisPosVal) {
266
- visibleYIndex = ys.indexOf(Math.min(...ys));
267
- }
268
- else {
269
- visibleYIndex = ys.indexOf(Math.max(...ys));
270
- }
271
- }
272
- const yIndex = visibleIndices[visibleYIndex];
273
- const localAnchorX = x - pos.containerScrollX;
274
- const localAnchorY = ys[visibleYIndex] - pos.containerScrollY;
275
- const { anchorX, anchorY } = checkAnchorsAgainstBound(localAnchorX, localAnchorY, dimensions);
276
- const anchor = new DOMRect(anchorX + pos.rect.x, anchorY + pos.rect.y, SMALL_PADDING, 0);
277
- return {
278
- hoverType: 'standard',
279
- x,
280
- xIndex,
281
- ys: shiftedYs,
282
- yIndex,
283
- visibleYIndex,
284
- tooltip: {
285
- anchor,
286
- date: utcFormat('%B %d, %Y')(new Date(data.x[xIndex])),
287
- metrics: data.ys
288
- .map((y, index) => ({
289
- color: colors[index % colors.length],
290
- label: y.label,
291
- pattern: y.pattern,
292
- value: pipeTransform(y.values[xIndex], checkIfSecondary(data, index, xIndex), true),
293
- }))
294
- .filter((_, i) => config.groupedTooltip || i === visibleYIndex),
295
- },
296
- };
297
- }
298
- return {
299
- chartWidth: chartSizingValues.totalWidth,
300
- chartHeight: chartSizingValues.totalHeight,
301
- chartSizingValues,
302
- xTicks,
303
- yTicks,
304
- colors,
305
- areas,
306
- lines: [],
307
- circles: [],
308
- hover,
309
- bars: [],
310
- arcs: [],
311
- horizontalBars: [],
312
- dataLabels: [],
313
- waterfallLines: [],
314
- gradients: [],
315
- flowConnections: [],
316
- horizontalContainerScale: chartSizingValues.horizontalContainerScale,
317
- verticalContainerScale: chartSizingValues.verticalContainerScale,
318
- chartError: null,
319
- };
320
- }
321
- function bars(config, allData, dimensions) {
322
- if (!warnFlowData(allData, 'bar')) {
323
- return { ...emptyChart, chartError: 'config' };
324
- }
325
- const { data, visibleIndices, visibleSuppIndices } = hide(allData);
326
- if (config.showDataLabels === true &&
327
- isStackedData(config) &&
328
- !isGroupingTypeException(data, config)) {
329
- // eslint-disable-next-line no-console
330
- console.warn("Heads up! Data labels aren't supported for any stacked chart type");
331
- return emptyChart;
332
- }
333
- if (hasSupplementaryData(data) &&
334
- isClusteredData(data, config, false) &&
335
- !isGroupingTypeException(data, config)) {
336
- // eslint-disable-next-line no-console
337
- console.warn("Heads up! Supplementary y values aren't supported for clustered data (just use another normal y series)");
338
- return emptyChart;
339
- }
340
- return barsHelper(config, allData, data, visibleIndices, visibleSuppIndices, dimensions, false, false);
341
- }
342
- function funnel(config, allData, dimensions) {
343
- if (!warnFlowData(allData, 'funnel')) {
344
- return { ...emptyChart, chartError: 'config' };
345
- }
346
- const { data, visibleIndices, visibleSuppIndices } = hide(allData);
347
- return barsHelper(config, allData, data, visibleIndices, visibleSuppIndices, dimensions, true, false);
348
- }
349
- function waterfall(config, allData, dimensions) {
350
- if (!warnFlowData(allData, 'waterfall')) {
351
- return { ...emptyChart, chartError: 'config' };
352
- }
353
- const { data: uncheckedData, visibleIndices } = hide(allData);
354
- if (hasSupplementaryData(uncheckedData)) {
355
- // eslint-disable-next-line no-console
356
- console.warn("Heads up! Supplementary y values aren't supported for non-bar charts");
357
- return emptyChart;
358
- }
359
- if (config.secondaryValueType) {
360
- // eslint-disable-next-line no-console
361
- console.warn('Heads up! Waterfall charts do not currently have two-axis support');
362
- return emptyChart;
363
- }
364
- warnUnsupportedPatterns(uncheckedData, [], 'waterfall');
365
- return barsHelper(config, allData, uncheckedData, visibleIndices, [], dimensions, false, true);
366
- }
367
- function barsHelper(config, allData, uncheckedData, visibleIndices, visibleSuppIndices, dimensions, isFunnel, isWaterfall) {
368
- const { dateFormat, pipeTransform, colorIndices, colors } = getFormattingAndColors(allData, uncheckedData, config);
369
- const waterfallData = waterfallTransform(uncheckedData, isWaterfall);
370
- const data = isWaterfall ? waterfallData.data : uncheckedData;
371
- const chartSizingValues = getFullChartScaleValues(config, data, dimensions, pipeTransform, dateFormat);
372
- if (chartSizingValues === null) {
373
- return { ...emptyChart, chartError: 'sizing' };
374
- }
375
- const tickCount = getBucketTickCount(chartSizingValues);
376
- const xTicks = (data.type === 'labeled'
377
- ? generateLabelledTicks(data, config, tickCount, chartSizingValues)
378
- : generateTimeseriesTicks(data, config, tickCount, chartSizingValues, dateFormat)).map(tick => toXTick(tick));
379
- const { scale, ticks: dataTicks } = calcDataAxisScalesAndTicks(data, pipeTransform, config, chartSizingValues);
380
- const yTicks = dataTicks.map(tick => toYTick(tick));
381
- const zeroAxisPosVal = scale(0, true);
382
- const gradients = [];
383
- const bars = data.ys.map((y, yIndex) => {
384
- const indSeriesGradients = [];
385
- const indSeriesBars = y.values.map((_, index) => {
386
- const { yValue, height } = getBarYInfo(data, config, yIndex, index, scale);
387
- const xValue = calculateBarPosition(data, config, chartSizingValues, index, isClusteredData(data, config, false) ? yIndex : 0);
388
- if (isFunnel) {
389
- //The empty gradient still needs to be inserted to keep data aligned
390
- if (index === 0) {
391
- indSeriesGradients.push({
392
- elementType: 'rect',
393
- x: 0,
394
- y: 0,
395
- width: 0,
396
- height: 0,
397
- });
398
- }
399
- else {
400
- const { yValue: prevBarYVal } = getBarYInfo(data, config, yIndex, index - 1, scale);
401
- indSeriesGradients.push({
402
- elementType: 'rect',
403
- x: xValue,
404
- y: prevBarYVal,
405
- width: chartSizingValues.barSize,
406
- height: Math.max(yValue - prevBarYVal, 0),
407
- });
408
- }
409
- }
410
- const bar = {
411
- elementType: 'rect',
412
- x: xValue,
413
- y: yValue,
414
- width: chartSizingValues.barSize,
415
- height,
416
- offset: 0,
417
- pattern: y.pattern,
418
- };
419
- return bar;
420
- });
421
- gradients.push(indSeriesGradients);
422
- return indSeriesBars;
423
- });
424
- let suppBars = [];
425
- if (hasSupplementaryData(data)) {
426
- suppBars = data.supplementaryYs.map((y, yIndex) => y.values.map((_, index) => {
427
- const { yValue, height } = getBarYInfo(data, config, yIndex, index, scale, true);
428
- const xValue = calculateBarPosition(data, config, chartSizingValues, index, y.supplementalIndex + 1);
429
- return {
430
- elementType: 'rect',
431
- x: xValue,
432
- y: yValue,
433
- width: chartSizingValues.barSize,
434
- height,
435
- offset: 0,
436
- pattern: y.pattern,
437
- };
438
- }));
439
- bars.push(...suppBars);
440
- colors.push(...data.supplementaryYs.map(y => getColor(y, colorIndices, config.colors)));
441
- }
442
- const waterfallLines = [];
443
- if (isWaterfall) {
444
- //Move bars based on height of previous bars (except the total bar)
445
- let barOffsetRunningTotal = 0;
446
- for (let i = 0; i < data.x.length - 1; i++) {
447
- let barOffsetChange = 0;
448
- for (let j = 0; j < bars.length; j++) {
449
- const barIsNegative = bars[j][i].y >= zeroAxisPosVal && bars[j][i].height > 0;
450
- if (barIsNegative) {
451
- barOffsetChange -= bars[j][i].height;
452
- }
453
- else {
454
- barOffsetChange += bars[j][i].height;
455
- }
456
- bars[j][i].offset = barOffsetRunningTotal;
457
- bars[j][i].y -= barOffsetRunningTotal;
458
- if (j === bars.length - 1) {
459
- const x1 = bars[j][i].x + bars[bars.length - 1][i].width;
460
- const y1 = bars[j][i].y + (barIsNegative ? bars[j][i].height : 0);
461
- const x2 = bars[j][i + 1].x;
462
- const y2 = y1;
463
- waterfallLines.push({
464
- x1,
465
- y1,
466
- x2,
467
- y2,
468
- });
469
- }
470
- }
471
- barOffsetRunningTotal += barOffsetChange;
472
- }
473
- }
474
- const dataLabels = data.ys.flatMap((y, yIndex) => {
475
- const subLabels = y.values.map((val, xIndex) => {
476
- const isNegativeBar = bars[yIndex][xIndex].y >= zeroAxisPosVal &&
477
- bars[yIndex][xIndex].height > 0;
478
- const yOffset = isNegativeBar
479
- ? chartSizingValues.dataLabelPadding +
480
- chartSizingValues.dataLabelTextSize +
481
- bars[yIndex][xIndex].height
482
- : -chartSizingValues.dataLabelPadding;
483
- return {
484
- elementType: 'dataLabel',
485
- label: pipeTransform(val, checkIfSecondary(data, yIndex, xIndex)) ?? '',
486
- yPos: (isFunnel && gradients[yIndex][xIndex].height !== 0
487
- ? gradients[yIndex][xIndex].y
488
- : bars[yIndex][xIndex].y) + yOffset,
489
- xPos: bars[yIndex][xIndex].x + bars[yIndex][xIndex].width / 2,
490
- anchor: 'middle',
491
- };
492
- });
493
- return subLabels;
494
- });
495
- if (hasSupplementaryData(data)) {
496
- const suppDataLabels = data.supplementaryYs.flatMap((y, yIndex) => {
497
- const subLabels = y.values.map((val, xIndex) => {
498
- const isNegativeBar = suppBars[yIndex][xIndex].y >= zeroAxisPosVal &&
499
- suppBars[yIndex][xIndex].height > 0;
500
- const yOffset = isNegativeBar
501
- ? chartSizingValues.dataLabelPadding +
502
- suppBars[yIndex][xIndex].height
503
- : -chartSizingValues.dataLabelPadding;
504
- return {
505
- elementType: 'dataLabel',
506
- label: pipeTransform(val, checkIfSecondary(data, yIndex, xIndex, true)) ?? '',
507
- yPos: suppBars[yIndex][xIndex].y + yOffset,
508
- xPos: suppBars[yIndex][xIndex].x + suppBars[yIndex][xIndex].width / 2,
509
- anchor: 'middle',
510
- };
511
- });
512
- return subLabels;
513
- });
514
- dataLabels.push(...suppDataLabels);
515
- }
516
- function hover(pos) {
517
- const realPosX = pos.x + pos.containerScrollX;
518
- const realPosY = pos.y + pos.containerScrollY;
519
- if (chartSizingValues === null ||
520
- getIfHoverOutOfBounds(pos.x, pos.y, realPosX, realPosY, chartSizingValues, dimensions)) {
521
- return null;
522
- }
523
- const suppYs = hasSupplementaryData(data) ? data.supplementaryYs : null;
524
- const xHoverIndices = getBucketAndClusterNumForHover(realPosX, chartSizingValues, data, config, data.x.length);
525
- if (!xHoverIndices) {
526
- return null;
527
- }
528
- const { bucketNum: xIndex, clusterNum, clusterNormCount, clusterNumType, } = xHoverIndices;
529
- let isSuppValue = false;
530
- let suppIndexVal = 0;
531
- if (suppYs) {
532
- suppIndexVal = clusterNum - clusterNormCount;
533
- if (clusterNumType === 'supp') {
534
- isSuppValue = true;
535
- }
536
- }
537
- const calcX = calculateBarPosition(data, config, chartSizingValues, xIndex, clusterNum);
538
- const ys = data.ys.map((_, mapYIndex) => isSuppValue
539
- ? getSuppBarYInfoViaYIndex(data, config, mapYIndex, suppIndexVal, xIndex, scale).yValue
540
- : getBarYInfo(data, config, mapYIndex, xIndex, scale).yValue -
541
- (!isSuppValue && isWaterfall
542
- ? bars[mapYIndex][xIndex].offset ?? 0
543
- : 0));
544
- const yPosSign = zeroAxisPosVal - realPosY;
545
- let visibleYIndex = -1;
546
- let dropOffHoverDetected = false;
547
- if (yPosSign < 0 && data.ys.find(y => y.values.find(val => val < 0))) {
548
- for (let i = ys.length - 1; i >= 0; i--) {
549
- if (ys[i] >= zeroAxisPosVal && ys[i] < realPosY) {
550
- visibleYIndex = i;
551
- break;
552
- }
553
- }
554
- }
555
- else {
556
- for (let i = 0; i < ys.length; i++) {
557
- if (ys[i] <= zeroAxisPosVal && ys[i] < realPosY) {
558
- visibleYIndex = i;
559
- break;
560
- }
561
- }
562
- }
563
- if (isClusteredData(data, config, false) && !suppYs) {
564
- visibleYIndex = clusterNum;
565
- if (isFunnel && xIndex !== 0 && ys[visibleYIndex] > realPosY) {
566
- dropOffHoverDetected = true;
567
- }
568
- }
569
- if (visibleYIndex === -1) {
570
- if (realPosY <= zeroAxisPosVal) {
571
- visibleYIndex = ys.indexOf(Math.min(...ys));
572
- }
573
- else {
574
- visibleYIndex = ys.indexOf(Math.max(...ys));
575
- }
576
- }
577
- const yIndex = visibleIndices[visibleYIndex];
578
- let { yValue, height } = isSuppValue
579
- ? getSuppBarYInfoViaYIndex(data, config, yIndex, suppIndexVal, xIndex, scale)
580
- : getBarYInfo(data, config, yIndex, xIndex, scale);
581
- if (dropOffHoverDetected) {
582
- yValue = gradients[yIndex][xIndex].y;
583
- height = gradients[yIndex][xIndex].height;
584
- }
585
- const localAnchorX = calcX - pos.containerScrollX - SMALL_PADDING;
586
- const width = chartSizingValues.barSize + SMALL_PADDING * 2;
587
- const waterfallOffset = !isSuppValue && isWaterfall ? bars[yIndex][xIndex].offset ?? 0 : 0;
588
- const localAnchorY = yValue - pos.containerScrollY - waterfallOffset;
589
- const { anchorX, anchorY, anchorWidth, anchorHeight } = checkAnchorsAgainstBound(localAnchorX, localAnchorY, dimensions, width, height);
590
- const anchor = new DOMRect(anchorX + pos.rect.x, anchorY + pos.rect.y, anchorWidth, anchorHeight);
591
- //We need to preserve the original index for the later checkIfSecondary call
592
- const ysForMetrics = isSuppValue && suppYs
593
- ? suppYs
594
- .map((suppY, index) => ({ data: suppY, originalIndex: index }))
595
- .filter(suppY => suppY.data.supplementalIndex === suppIndexVal)
596
- : data.ys.map((y, index) => ({ data: y, originalIndex: index }));
597
- // Find the specific supplementary item that was hovered
598
- const groupSupps = suppYs
599
- ? suppYs.filter(s => s.supplementalIndex === suppIndexVal) ?? []
600
- : [];
601
- const suppArrayIndex = visibleYIndex; // Use the visual Y position within the layer
602
- const filteredSuppYIndex = suppArrayIndex >= 0 && suppArrayIndex < groupSupps.length && suppYs
603
- ? suppYs.indexOf(groupSupps[suppArrayIndex]) ?? -1
604
- : -1;
605
- const suppYIndex = filteredSuppYIndex >= 0 ? visibleSuppIndices[filteredSuppYIndex] : -1;
606
- return {
607
- hoverType: 'standard',
608
- x: calcX + chartSizingValues.barSize / 2,
609
- xIndex,
610
- ys,
611
- yIndex,
612
- visibleYIndex,
613
- ...(isSuppValue && suppYIndex >= 0
614
- ? {
615
- isSuppValue,
616
- suppYIndex: suppYIndex,
617
- }
618
- : {}),
619
- ...(dropOffHoverDetected ? { isDropOff: true } : {}),
620
- tooltip: {
621
- anchor,
622
- date: data.type === 'labeled'
623
- ? dropOffHoverDetected
624
- ? 'Drop off from '.concat(data.x[xIndex - 1].label)
625
- : data.x[xIndex].label
626
- : utcFormat('%B %d, %Y')(new Date(data.x[xIndex])),
627
- metrics: ysForMetrics
628
- .map(y => ({
629
- color: getColor(isWaterfall ? waterfallData.map.get(y.data) : y.data, colorIndices, config.colors),
630
- label: y.data.label,
631
- pattern: y.data.pattern,
632
- value: pipeTransform(dropOffHoverDetected
633
- ? Math.max(y.data.values[xIndex - 1] - y.data.values[xIndex], 0)
634
- : y.data.values[xIndex], checkIfSecondary(data, y.originalIndex, dropOffHoverDetected ? xIndex - 1 : xIndex, isSuppValue), true),
635
- }))
636
- .filter((_, i) => config.groupedTooltip || i === visibleYIndex),
637
- },
638
- };
639
- }
640
- return {
641
- chartWidth: chartSizingValues.totalWidth,
642
- chartHeight: chartSizingValues.totalHeight,
643
- chartSizingValues,
644
- xTicks,
645
- yTicks,
646
- colors,
647
- bars,
648
- lines: [],
649
- circles: [],
650
- areas: [],
651
- hover,
652
- arcs: [],
653
- horizontalBars: [],
654
- dataLabels,
655
- waterfallLines,
656
- gradients,
657
- flowConnections: [],
658
- horizontalContainerScale: chartSizingValues.horizontalContainerScale,
659
- verticalContainerScale: chartSizingValues.verticalContainerScale,
660
- chartError: null,
661
- };
662
- }
663
- function horizontalBars(config, allData, dimensions) {
664
- if (!warnFlowData(allData, 'horizontal bar')) {
665
- return { ...emptyChart, chartError: 'config' };
666
- }
667
- //Some of this stuff gets confusing, because x and y are essentially inverted here
668
- // So, if you see a situation where a variable is named 'y', but referencing
669
- // 'x' (or vice versa), that's why
670
- const { data, visibleIndices, visibleSuppIndices } = hide(allData);
671
- if (config.showDataLabels === true &&
672
- isStackedData(config) &&
673
- !isGroupingTypeException(data, config)) {
674
- // eslint-disable-next-line no-console
675
- console.warn("Heads up! Data labels aren't supported for any stacked chart type");
676
- return emptyChart;
677
- }
678
- if (hasSupplementaryData(data) &&
679
- isClusteredData(data, config, false) &&
680
- !isGroupingTypeException(data, config)) {
681
- // eslint-disable-next-line no-console
682
- console.warn("Heads up! Supplementary y values aren't supported for clustered data (just use another normal y series)");
683
- return emptyChart;
684
- }
685
- const { dateFormat, pipeTransform, colorIndices, colors } = getFormattingAndColors(allData, data, config);
686
- const chartSizingValues = getFullChartScaleValues(config, data, dimensions, pipeTransform, dateFormat);
687
- if (chartSizingValues === null) {
688
- return { ...emptyChart, chartError: 'sizing' };
689
- }
690
- const tickCount = getBucketTickCount(chartSizingValues);
691
- const yTicks = (data.type === 'labeled'
692
- ? generateLabelledTicks(data, config, tickCount, chartSizingValues)
693
- : generateTimeseriesTicks(data, config, tickCount, chartSizingValues, dateFormat)).map(tick => toYTick(tick));
694
- const { scale, ticks: dataTicks } = calcDataAxisScalesAndTicks(data, pipeTransform, config, chartSizingValues);
695
- const xTicks = dataTicks.map(tick => toXTick(tick));
696
- const zeroAxisPosVal = scale(0, true);
697
- const simplifiedHorizontalBars = [];
698
- const horizontalBars = data.ys.map((y, yIndex) => {
699
- const subSimpHorBars = [];
700
- const retVal = y.values.map((_, index) => {
701
- const { xValue, width } = getBarXInfo(data, config, yIndex, index, scale);
702
- const clusterInfo = getClusterInfoForBucket(data, config);
703
- const clusterNum = clusterInfo.normClusterIndices.indexOf(yIndex);
704
- const yValue = calculateBarPosition(data, config, chartSizingValues, index, isClusteredData(data, config, false) ? clusterNum : 0);
705
- const horR = Math.min(DEFAULT_HORIZONTAL_BAR_CORNER_RADIUS, Math.floor(width / 2));
706
- const verR = Math.min(DEFAULT_HORIZONTAL_BAR_CORNER_RADIUS, Math.floor(chartSizingValues.barSize / 2));
707
- subSimpHorBars.push({
708
- xPos: xValue,
709
- yPos: yValue,
710
- width,
711
- });
712
- //If clusterNum is -1, then the value of data[yIndex][xIndex] must be zero
713
- if (clusterNum === -1) {
714
- return {
715
- horizontalBar: '',
716
- pattern: y.pattern,
717
- x: xValue,
718
- y: yValue,
719
- };
720
- }
721
- //Don't draw anything for zero-value bars
722
- if (width === 0) {
723
- return {
724
- horizontalBar: '',
725
- pattern: y.pattern,
726
- x: xValue,
727
- y: yValue,
728
- };
729
- }
730
- const isPositive = data.ys[yIndex].values[index] > 0;
731
- const hasAnyNegativeBars = data.ys
732
- .map(y => y.values[index])
733
- .find(val => val < 0);
734
- const hasAnyPositiveBars = data.ys
735
- .map(y => y.values[index])
736
- .find(val => val > 0);
737
- //These checks are to make sure we still round if all previous/later values are 0
738
- const allLeftZero = isPositive
739
- ? data.ys
740
- .slice(0, yIndex)
741
- .map(y => y.values[index])
742
- .filter(val => val > 0).length === 0 && !hasAnyNegativeBars
743
- : data.ys
744
- .slice(yIndex + 1, data.ys.length)
745
- .map(y => y.values[index])
746
- .filter(val => val < 0).length === 0;
747
- const leftSideRound = !isStackedData(config) || allLeftZero;
748
- const allRightZero = isPositive
749
- ? data.ys
750
- .slice(yIndex + 1, data.ys.length)
751
- .map(y => y.values[index])
752
- .filter(val => val > 0).length === 0
753
- : data.ys
754
- .slice(0, yIndex)
755
- .map(y => y.values[index])
756
- .filter(val => val < 0).length === 0 && !hasAnyPositiveBars;
757
- const rightSideRound = !isStackedData(config) || allRightZero;
758
- const pathD = calculateHorizontalBarPath(leftSideRound, rightSideRound, xValue, yValue, horR, verR, chartSizingValues.barSize, width);
759
- return {
760
- horizontalBar: pathD,
761
- pattern: y.pattern,
762
- x: xValue,
763
- y: yValue,
764
- };
765
- });
766
- simplifiedHorizontalBars.push(subSimpHorBars);
767
- return retVal;
768
- });
769
- const suppYs = data.supplementaryYs;
770
- const simplifiedSuppHorizontalBars = [];
771
- if (suppYs) {
772
- const suppHorizontalBars = suppYs.map((y, yIndex) => {
773
- const subSimpHorBars = [];
774
- const retVal = y.values.map((_, index) => {
775
- const { xValue, width } = getBarXInfo(data, config, yIndex, index, scale, true);
776
- const clusterInfo = getClusterInfoForBucket(data, config);
777
- const clusterNum = clusterInfo.suppClusterIndices.indexOf(y.supplementalIndex) +
778
- clusterInfo.normCount;
779
- const yValue = calculateBarPosition(data, config, chartSizingValues, index, clusterNum);
780
- const horR = Math.min(DEFAULT_HORIZONTAL_BAR_CORNER_RADIUS, Math.floor(width / 2));
781
- const verR = Math.min(DEFAULT_HORIZONTAL_BAR_CORNER_RADIUS, Math.floor(chartSizingValues.barSize / 2));
782
- subSimpHorBars.push({
783
- xPos: xValue,
784
- yPos: yValue,
785
- width,
786
- });
787
- //Don't draw anything for zero-value bars
788
- if (width === 0) {
789
- return {
790
- horizontalBar: '',
791
- pattern: y.pattern,
792
- x: xValue,
793
- y: yValue,
794
- };
795
- }
796
- const isPositive = suppYs[yIndex].values[index] > 0;
797
- const hasAnyNegativeBars = suppYs
798
- .filter(suppY => suppY.supplementalIndex === y.supplementalIndex)
799
- .map(y => y.values[index])
800
- .find(val => val < 0);
801
- const hasAnyPositiveBars = suppYs
802
- .filter(suppY => suppY.supplementalIndex === y.supplementalIndex)
803
- .map(y => y.values[index])
804
- .find(val => val > 0);
805
- //These checks are to make sure we still round if all previous/later values are 0
806
- const allLeftZero = isPositive
807
- ? suppYs
808
- .slice(0, yIndex)
809
- .filter(suppY => suppY.supplementalIndex === y.supplementalIndex)
810
- .map(y => y.values[index])
811
- .filter(val => val > 0).length === 0 && !hasAnyNegativeBars
812
- : suppYs
813
- .slice(yIndex + 1, suppYs.length)
814
- .filter(suppY => suppY.supplementalIndex === y.supplementalIndex)
815
- .map(y => y.values[index])
816
- .filter(val => val < 0).length === 0;
817
- const leftSideRound = !isStackedData(config) || allLeftZero;
818
- const allRightZero = isPositive
819
- ? suppYs
820
- .slice(yIndex + 1, suppYs.length)
821
- .filter(suppY => suppY.supplementalIndex === y.supplementalIndex)
822
- .map(y => y.values[index])
823
- .filter(val => val > 0).length === 0
824
- : suppYs
825
- .slice(0, yIndex)
826
- .filter(suppY => suppY.supplementalIndex === y.supplementalIndex)
827
- .map(y => y.values[index])
828
- .filter(val => val < 0).length === 0 && !hasAnyPositiveBars;
829
- const rightSideRound = !isStackedData(config) || allRightZero;
830
- const pathD = calculateHorizontalBarPath(leftSideRound, rightSideRound, xValue, yValue, horR, verR, chartSizingValues.barSize, width);
831
- return {
832
- horizontalBar: pathD,
833
- pattern: y.pattern,
834
- x: xValue,
835
- y: yValue,
836
- };
837
- });
838
- simplifiedSuppHorizontalBars.push(subSimpHorBars);
839
- return retVal;
840
- });
841
- horizontalBars.push(...suppHorizontalBars);
842
- colors.push(...suppYs.map(y => getColor(y, colorIndices, config.colors)));
843
- }
844
- const yOffset = chartSizingValues.barSize;
845
- const dataLabels = data.ys.flatMap((y, yIndex) => {
846
- const subLabels = y.values.map((val, xIndex) => {
847
- const barIsNegative = simplifiedHorizontalBars[yIndex][xIndex].xPos < zeroAxisPosVal &&
848
- simplifiedHorizontalBars[yIndex][xIndex].width > 0;
849
- const xOffset = barIsNegative
850
- ? -chartSizingValues.dataLabelPadding
851
- : simplifiedHorizontalBars[yIndex][xIndex].width +
852
- chartSizingValues.dataLabelPadding;
853
- return {
854
- elementType: 'dataLabel',
855
- label: pipeTransform(val, checkIfSecondary(data, yIndex, xIndex)) ?? '',
856
- yPos: simplifiedHorizontalBars[yIndex][xIndex].yPos + yOffset,
857
- xPos: simplifiedHorizontalBars[yIndex][xIndex].xPos + xOffset,
858
- anchor: barIsNegative ? 'end' : 'start',
859
- };
860
- });
861
- return subLabels;
862
- });
863
- if (suppYs) {
864
- const suppDataLabels = suppYs.flatMap((y, yIndex) => {
865
- const subLabels = y.values.map((val, xIndex) => {
866
- const barIsNegative = simplifiedSuppHorizontalBars[yIndex][xIndex].xPos <
867
- zeroAxisPosVal &&
868
- simplifiedSuppHorizontalBars[yIndex][xIndex].width > 0;
869
- const xOffset = barIsNegative
870
- ? -chartSizingValues.dataLabelPadding
871
- : simplifiedSuppHorizontalBars[yIndex][xIndex].width +
872
- chartSizingValues.dataLabelPadding;
873
- return {
874
- elementType: 'dataLabel',
875
- label: pipeTransform(val, checkIfSecondary(data, yIndex, xIndex, true)) ?? '',
876
- yPos: simplifiedSuppHorizontalBars[yIndex][xIndex].yPos + yOffset,
877
- xPos: simplifiedSuppHorizontalBars[yIndex][xIndex].xPos + xOffset,
878
- anchor: barIsNegative ? 'end' : 'start',
879
- };
880
- });
881
- return subLabels;
882
- });
883
- dataLabels.push(...suppDataLabels);
884
- }
885
- function hover(pos) {
886
- const realPosX = pos.x + pos.containerScrollX;
887
- const realPosY = pos.y + pos.containerScrollY;
888
- if (chartSizingValues === null ||
889
- getIfHoverOutOfBounds(pos.x, pos.y, realPosX, realPosY, chartSizingValues, dimensions)) {
890
- return null;
891
- }
892
- const suppYs = hasSupplementaryData(data) ? data.supplementaryYs : null;
893
- const xHoverIndices = getBucketAndClusterNumForHover(realPosY, chartSizingValues, data, config, data.x.length);
894
- if (!xHoverIndices) {
895
- return null;
896
- }
897
- const { bucketNum: xIndex, clusterNum, clusterNormCount, clusterNumType, } = xHoverIndices;
898
- let x = calculateBarPosition(data, config, chartSizingValues, xIndex, clusterNum);
899
- let isSuppValue = false;
900
- let suppIndexVal = 0;
901
- if (suppYs) {
902
- suppIndexVal = clusterNum - clusterNormCount;
903
- if (clusterNumType === 'supp') {
904
- isSuppValue = true;
905
- }
906
- }
907
- // When hovering supplementary values, get bars for that supplemental layer
908
- // When hovering original Ys, get bars for original Ys
909
- const fullYs = hasSupplementaryData(data) && isSuppValue
910
- ? (data.supplementaryYs.filter(s => s.supplementalIndex === suppIndexVal) ?? []).map(suppY => getBarXInfo(data, config, data.supplementaryYs.indexOf(suppY), xIndex, scale, true))
911
- : data.ys.map((_, mapYIndex) => getBarXInfo(data, config, mapYIndex, xIndex, scale));
912
- const ys = fullYs.map(y => y.xValue);
913
- let visibleYIndex = -1;
914
- for (let i = 0; i < fullYs.length; i++) {
915
- const leftBorder = fullYs[i].xValue;
916
- const rightBorderCandidates = fullYs
917
- .filter(y => y.xValue > leftBorder)
918
- .map(y => y.xValue);
919
- const rightBorder = rightBorderCandidates.length > 0
920
- ? Math.min(...rightBorderCandidates)
921
- : leftBorder + fullYs[i].width;
922
- if (realPosX > leftBorder && realPosX < rightBorder) {
923
- visibleYIndex = i;
924
- }
925
- }
926
- if (isClusteredData(data, config, false)) {
927
- visibleYIndex = clusterNum;
928
- }
929
- if (visibleYIndex === -1) {
930
- if (realPosX >= zeroAxisPosVal) {
931
- visibleYIndex = ys.indexOf(Math.max(...ys));
932
- }
933
- else {
934
- visibleYIndex = ys.indexOf(Math.min(...ys));
935
- }
936
- }
937
- // For supplementary bars: visibleYIndex is index within filtered supplementary array
938
- // For original Ys: visibleYIndex is index within original Ys array
939
- const actualSuppYIndex = hasSupplementaryData(data) && isSuppValue
940
- ? data.supplementaryYs.findIndex(s => s.supplementalIndex === suppIndexVal &&
941
- data.supplementaryYs
942
- .filter(s2 => s2.supplementalIndex === suppIndexVal)
943
- .indexOf(s) === visibleYIndex) ?? -1
944
- : -1;
945
- const yIndex = isSuppValue ? 0 : visibleIndices[visibleYIndex];
946
- //Check if we've landed on a zero-width bar (only really relevant on ends)
947
- const barsToCheck = isSuppValue
948
- ? simplifiedSuppHorizontalBars
949
- : simplifiedHorizontalBars;
950
- const barIndexToCheck = isSuppValue ? actualSuppYIndex : visibleYIndex;
951
- if (barIndexToCheck >= 0 &&
952
- barsToCheck[barIndexToCheck][xIndex].width === 0 &&
953
- isStackedData(config)) {
954
- let altBarFound = false;
955
- //Check upwards
956
- for (let i = barIndexToCheck + 1; i < barsToCheck.length; i++) {
957
- if (altBarFound) {
958
- break;
959
- }
960
- if (barsToCheck[i][xIndex].width !== 0) {
961
- if (hasSupplementaryData(data) && isSuppValue) {
962
- visibleYIndex = data.supplementaryYs
963
- .filter(s => s.supplementalIndex === suppIndexVal)
964
- .indexOf(data.supplementaryYs[i]);
965
- }
966
- else {
967
- visibleYIndex = i;
968
- }
969
- altBarFound = true;
970
- }
971
- }
972
- //Check downwards
973
- for (let i = barIndexToCheck - 1; i >= 0; i--) {
974
- if (altBarFound) {
975
- break;
976
- }
977
- if (barsToCheck[i][xIndex].width !== 0) {
978
- if (hasSupplementaryData(data) && isSuppValue) {
979
- visibleYIndex = data.supplementaryYs
980
- .filter(s => s.supplementalIndex === suppIndexVal)
981
- .indexOf(data.supplementaryYs[i]);
982
- }
983
- else {
984
- visibleYIndex = i;
985
- }
986
- altBarFound = true;
987
- }
988
- }
989
- }
990
- const originalSuppYIndex = isSuppValue && actualSuppYIndex >= 0
991
- ? visibleSuppIndices[actualSuppYIndex]
992
- : -1;
993
- const barXPos = isSuppValue
994
- ? simplifiedSuppHorizontalBars[actualSuppYIndex][xIndex].xPos
995
- : simplifiedHorizontalBars[visibleYIndex][xIndex].xPos;
996
- const barYPos = isSuppValue
997
- ? simplifiedSuppHorizontalBars[actualSuppYIndex][xIndex].yPos
998
- : simplifiedHorizontalBars[visibleYIndex][xIndex].yPos;
999
- const barWidth = isSuppValue
1000
- ? simplifiedSuppHorizontalBars[actualSuppYIndex][xIndex].width
1001
- : simplifiedHorizontalBars[visibleYIndex][xIndex].width;
1002
- const localAnchorX = barXPos - pos.containerScrollX - SMALL_PADDING;
1003
- const width = barWidth + SMALL_PADDING * 2;
1004
- const localAnchorY = barYPos - pos.containerScrollY;
1005
- const height = chartSizingValues.barSize;
1006
- const { anchorX, anchorY, anchorWidth, anchorHeight } = checkAnchorsAgainstBound(localAnchorX, localAnchorY, dimensions, width, height);
1007
- const anchor = new DOMRect(anchorX + pos.rect.x, anchorY + pos.rect.y, anchorWidth, anchorHeight);
1008
- //We need to preserve the original index for the later checkIfSecondary call
1009
- const ysForMetrics = isSuppValue && suppYs
1010
- ? suppYs
1011
- .map((suppY, index) => ({ data: suppY, originalIndex: index }))
1012
- .filter(suppY => suppY.data.supplementalIndex === suppIndexVal)
1013
- : data.ys.map((y, index) => ({ data: y, originalIndex: index }));
1014
- return {
1015
- hoverType: 'standard',
1016
- x,
1017
- xIndex,
1018
- ys,
1019
- yIndex,
1020
- visibleYIndex,
1021
- ...(isSuppValue && originalSuppYIndex >= 0
1022
- ? { isSuppValue, suppYIndex: originalSuppYIndex }
1023
- : {}),
1024
- tooltip: {
1025
- anchor,
1026
- date: data.type === 'labeled'
1027
- ? data.x[xIndex].label
1028
- : utcFormat('%B %d, %Y')(new Date(data.x[xIndex])),
1029
- metrics: ysForMetrics
1030
- .map(y => ({
1031
- color: getColor(y.data, colorIndices, config.colors),
1032
- label: y.data.label,
1033
- pattern: y.data.pattern,
1034
- value: pipeTransform(y.data.values[xIndex], checkIfSecondary(data, y.originalIndex, xIndex, isSuppValue), true),
1035
- }))
1036
- .filter((_, i) => config.groupedTooltip || i === visibleYIndex),
1037
- },
1038
- };
1039
- }
1040
- return {
1041
- chartWidth: chartSizingValues.totalWidth,
1042
- chartHeight: chartSizingValues.totalHeight,
1043
- chartSizingValues,
1044
- xTicks: xTicks,
1045
- yTicks: yTicks,
1046
- hover,
1047
- colors,
1048
- bars: [],
1049
- lines: [],
1050
- circles: [],
1051
- areas: [],
1052
- arcs: [],
1053
- horizontalBars,
1054
- dataLabels,
1055
- waterfallLines: [],
1056
- gradients: [],
1057
- flowConnections: [],
1058
- horizontalContainerScale: chartSizingValues.horizontalContainerScale,
1059
- verticalContainerScale: chartSizingValues.verticalContainerScale,
1060
- chartError: null,
1061
- };
1062
- }
1063
- function arcs(config, allData, dimensions) {
1064
- if (!warnFlowData(allData, 'donut')) {
1065
- return { ...emptyChart, chartError: 'config' };
1066
- }
1067
- if (config.secondaryValueType &&
1068
- (config.valueType === 'percentage' ||
1069
- config.secondaryValueType === 'percentage')) {
1070
- // eslint-disable-next-line no-console
1071
- console.warn("Heads up! Two axes with percentage aren't supported for donut charts");
1072
- return emptyChart;
1073
- }
1074
- if (hasSupplementaryData(allData)) {
1075
- // eslint-disable-next-line no-console
1076
- console.warn("Heads up! Supplementary y values aren't supported for non-bar charts");
1077
- return emptyChart;
1078
- }
1079
- warnUnsupportedPatterns(allData, [], 'donut');
1080
- const { data: unstackedData, visibleIndices } = hide(allData);
1081
- const donutData = Chart.convertChartDataToDonutData(unstackedData);
1082
- const hasNonZeroValue = donutData.some(d => d.value > 0);
1083
- const arcData = hasNonZeroValue
1084
- ? donutData
1085
- : [
1086
- {
1087
- label: '',
1088
- value: 1,
1089
- },
1090
- ];
1091
- const colors = hasNonZeroValue
1092
- ? visibleIndices.map(i => config.colors[i % config.colors.length])
1093
- : ['--gray-30'];
1094
- const { pipeTransform } = getFormattingAndColors(allData, unstackedData, config);
1095
- const donutDefaultConfig = DefaultDonutSizingConfig;
1096
- const dataLabelPaddingConfig = getElementScalingInfo(config.donutDisplayInfo.scalingConfig?.elementScales, donutDefaultConfig.elementScales, 'dataLabelPadding');
1097
- const fontSizeConfig = getElementScalingInfo(config.donutDisplayInfo.scalingConfig?.elementScales, donutDefaultConfig.elementScales, 'fontSize');
1098
- const dataLabelTextSizing = getDataLabelSize(unstackedData, pipeTransform, fontSizeConfig.target);
1099
- const horizontalContainerScale = config.donutDisplayInfo.scalingConfig?.horizontalContainerScale !==
1100
- undefined
1101
- ? config.donutDisplayInfo.scalingConfig.horizontalContainerScale
1102
- : donutDefaultConfig.horizontalContainerScale;
1103
- const verticalContainerScale = config.donutDisplayInfo.scalingConfig?.verticalContainerScale !==
1104
- undefined
1105
- ? config.donutDisplayInfo.scalingConfig.verticalContainerScale
1106
- : donutDefaultConfig.verticalContainerScale;
1107
- const outerRadiusConfig = config.donutDisplayInfo.scalingConfig?.outerRadius !== undefined
1108
- ? config.donutDisplayInfo.scalingConfig.outerRadius
1109
- : donutDefaultConfig.outerRadius;
1110
- const drawRadiusConfig = config.donutDisplayInfo.scalingConfig?.drawRadius !== undefined
1111
- ? config.donutDisplayInfo.scalingConfig.drawRadius
1112
- : donutDefaultConfig.drawRadius;
1113
- const outer = outerRadiusConfig.type === 'proportion'
1114
- ? (dimensions.height / 2) * outerRadiusConfig.value
1115
- : outerRadiusConfig.value;
1116
- const drawRadius = drawRadiusConfig.type === 'proportion'
1117
- ? outer * drawRadiusConfig.value
1118
- : drawRadiusConfig.value;
1119
- const inner = outer - drawRadius;
1120
- const pieArcs = pie()
1121
- .sortValues(null)
1122
- .value(d => Math.max(d.value, 0))(arcData);
1123
- const arcs = pieArcs.map(pieArc => arc()
1124
- .innerRadius(inner)
1125
- .outerRadius(outer)
1126
- .padAngle(0.013)
1127
- .startAngle(pieArc.startAngle)
1128
- .endAngle(pieArc.endAngle)(pieArc.data));
1129
- const dataLabels = hasNonZeroValue
1130
- ? pieArcs.map(arc => {
1131
- //Don't show data labels for zero-width donut slices (includes negative values)
1132
- if (arc.startAngle === arc.endAngle) {
1133
- return {
1134
- elementType: 'dataLabel',
1135
- label: '',
1136
- yPos: 0,
1137
- xPos: 0,
1138
- anchor: 'middle',
1139
- };
1140
- }
1141
- const arcCenterAngle = (arc.startAngle + arc.endAngle) / 2;
1142
- const edgePoint = arcToPoint(arcCenterAngle, outer);
1143
- const lineEndPoint = arcToPoint(arcCenterAngle, outer + dataLabelPaddingConfig.target);
1144
- const middleArea = outer / 4;
1145
- let yOffset = 0;
1146
- let xOffset = 0;
1147
- if (lineEndPoint.y > 0) {
1148
- if (Math.abs(lineEndPoint.y) < middleArea) {
1149
- yOffset = SMALL_PADDING / 2;
1150
- }
1151
- else {
1152
- yOffset = SMALL_PADDING;
1153
- }
1154
- if (Math.abs(lineEndPoint.x) < middleArea) {
1155
- yOffset += SMALL_PADDING / 2;
1156
- }
1157
- }
1158
- else {
1159
- if (Math.abs(lineEndPoint.y) < middleArea) {
1160
- yOffset = SMALL_PADDING / 2;
1161
- }
1162
- if (Math.abs(lineEndPoint.x) < middleArea) {
1163
- yOffset -= SMALL_PADDING / 2;
1164
- }
1165
- }
1166
- return {
1167
- elementType: 'dataLabel',
1168
- label: pipeTransform(arc.data.value, arc.data.isSecondary),
1169
- yPos: lineEndPoint.y + yOffset,
1170
- xPos: lineEndPoint.x + xOffset,
1171
- anchor: Math.abs(lineEndPoint.x) < middleArea
1172
- ? 'middle'
1173
- : lineEndPoint.x < 0
1174
- ? 'end'
1175
- : 'start',
1176
- line: {
1177
- x1: edgePoint.x,
1178
- y1: edgePoint.y,
1179
- x2: lineEndPoint.x,
1180
- y2: lineEndPoint.y,
1181
- },
1182
- };
1183
- })
1184
- : [];
1185
- const drawWidth = (outer +
1186
- (config.showDataLabels
1187
- ? dataLabelPaddingConfig.target + dataLabelTextSizing.horizontal
1188
- : 0)) *
1189
- 2;
1190
- const drawHeight = (outer +
1191
- (config.showDataLabels
1192
- ? dataLabelPaddingConfig.target + dataLabelTextSizing.vertical
1193
- : 0)) *
1194
- 2;
1195
- function hover(pos) {
1196
- const realPosX = pos.x + pos.containerScrollX;
1197
- const realPosY = pos.y + pos.containerScrollY;
1198
- if (getIfHoverOutOfBounds(pos.x, pos.y, realPosX, realPosY, null, dimensions)) {
1199
- return null;
1200
- }
1201
- const centerPointX = dimensions.width / 2;
1202
- const centerPointY = dimensions.height / 2;
1203
- const donutPositionX = realPosX - centerPointX;
1204
- const donutPositionY = realPosY - centerPointY;
1205
- const hoverPosArcInfo = pointToArc(donutPositionX, donutPositionY);
1206
- const arcCenterLine = (outer + inner) / 2;
1207
- //Detect donut slice
1208
- let foundYIndex = -1;
1209
- let preferredPosition = undefined;
1210
- let donutXPosition = 0;
1211
- let donutYPosition = 0;
1212
- for (let i = 0; i < pieArcs.length; i++) {
1213
- const arc = pieArcs[i];
1214
- if (hoverPosArcInfo.angle > arc.startAngle &&
1215
- hoverPosArcInfo.angle < arc.endAngle &&
1216
- hoverPosArcInfo.radius > arcCenterLine - drawRadius &&
1217
- hoverPosArcInfo.radius < arcCenterLine + drawRadius) {
1218
- foundYIndex = i;
1219
- const arcCenterPoint = arcToPoint((arc.startAngle + arc.endAngle) / 2, arcCenterLine);
1220
- //Need to un-offset the positions
1221
- donutXPosition = arcCenterPoint.x + centerPointX;
1222
- donutYPosition = arcCenterPoint.y + centerPointY;
1223
- const verticalArea = arcCenterPoint.y < (dimensions.height * -1) / 4
1224
- ? 'top'
1225
- : arcCenterPoint.y > dimensions.height / 4
1226
- ? 'bottom'
1227
- : 'center';
1228
- //Determine the best position for the tooltip
1229
- if (arcCenterPoint.x > 0) {
1230
- //Right path
1231
- if (!config.groupedTooltip || verticalArea === 'center') {
1232
- preferredPosition = 'center-right';
1233
- }
1234
- else if (verticalArea === 'top') {
1235
- preferredPosition = 'right-top';
1236
- }
1237
- else if (verticalArea === 'bottom') {
1238
- preferredPosition = 'right-bottom';
1239
- }
1240
- }
1241
- else {
1242
- //Left path
1243
- if (!config.groupedTooltip || verticalArea === 'center') {
1244
- preferredPosition = 'center-left';
1245
- }
1246
- else if (verticalArea === 'top') {
1247
- preferredPosition = 'left-top';
1248
- }
1249
- else if (verticalArea === 'bottom') {
1250
- preferredPosition = 'left-bottom';
1251
- }
1252
- }
1253
- break;
1254
- }
1255
- }
1256
- if (foundYIndex === -1) {
1257
- return null;
1258
- }
1259
- if (!hasNonZeroValue) {
1260
- donutXPosition = centerPointX + arcCenterLine;
1261
- donutYPosition = centerPointY;
1262
- }
1263
- const localAnchorX = donutXPosition - pos.containerScrollX;
1264
- const localAnchorY = donutYPosition - pos.containerScrollY;
1265
- const { anchorX, anchorY } = checkAnchorsAgainstBound(localAnchorX, localAnchorY, dimensions);
1266
- const anchor = new DOMRect(anchorX + pos.rect.x, anchorY + pos.rect.y, SMALL_PADDING, 0);
1267
- return {
1268
- hoverType: 'standard',
1269
- tooltip: {
1270
- anchor,
1271
- preferredPosition,
1272
- date: null,
1273
- metrics: donutData
1274
- .map((y, index) => ({
1275
- color: colors[index % colors.length],
1276
- label: y.label,
1277
- value: pipeTransform(y.value, y.isSecondary, true),
1278
- }))
1279
- .filter((_, i) => config.groupedTooltip || i === foundYIndex),
1280
- },
1281
- //Not used by donut charts
1282
- x: 0,
1283
- xIndex: 0,
1284
- ys: [],
1285
- yIndex: 0,
1286
- visibleYIndex: 0,
1287
- };
1288
- }
1289
- return {
1290
- chartWidth: drawWidth,
1291
- chartHeight: drawHeight,
1292
- chartSizingValues: {
1293
- ...emptyChartScaleValues,
1294
- dataLabelPadding: dataLabelPaddingConfig.target,
1295
- dataLabelTextSize: dataLabelTextSizing.horizontal,
1296
- fontSize: fontSizeConfig.target,
1297
- },
1298
- xTicks: [],
1299
- yTicks: [],
1300
- areas: [],
1301
- lines: [],
1302
- circles: [],
1303
- bars: [],
1304
- colors,
1305
- arcs,
1306
- horizontalBars: [],
1307
- dataLabels,
1308
- waterfallLines: [],
1309
- gradients: [],
1310
- flowConnections: [],
1311
- horizontalContainerScale,
1312
- verticalContainerScale,
1313
- chartError: null,
1314
- hover,
1315
- };
1316
- }
1317
- function flows(config, allData, dimensions) {
1318
- if (allData.type !== 'flow') {
1319
- // eslint-disable-next-line no-console
1320
- console.warn(`Heads up! The '${allData.type}' data type isn't supported for flow charts.`);
1321
- return { ...emptyChart, chartError: 'config' };
1322
- }
1323
- const data = flowsTransform(config, allData);
1324
- if (data.x.length === 0) {
1325
- return emptyChart;
1326
- }
1327
- const overallTotal = data.x[0].totalCount;
1328
- const chartSizingValues = getFullChartScaleValues(config, data, dimensions, null, null);
1329
- if (chartSizingValues === null) {
1330
- return { ...emptyChart, chartError: 'sizing' };
1331
- }
1332
- const { scale } = calcDataAxisScalesAndTicks(data, null, config, chartSizingValues);
1333
- const valuePipes = getPipes(config.valueType);
1334
- const percentPipes = getPipes('percentage');
1335
- const bars = [];
1336
- const flowConnections = [];
1337
- const dataLabels = [];
1338
- const minimumSize = getMinimumDataElementSize(config);
1339
- for (let i = 0; i < data.x.length; i++) {
1340
- const bucketBars = [];
1341
- let runningHeight = 0;
1342
- for (const bar of data.x[i].subBuckets) {
1343
- const continuingCount = bar.connections
1344
- .filter(connection => connection.direction === 'forward')
1345
- .map(connection => connection.count)
1346
- .reduce((a, b) => a + b, 0);
1347
- const { totalSize: totalHeight, continuingSize: darkenedHeight, connectionSizes, } = getFlowSubBucketSizes(bar, value => scale(value, false) - chartSizingValues.totalTopOffset, minimumSize);
1348
- const connectionHeight = (connection) => connectionSizes[bar.connections.indexOf(connection)];
1349
- const nonDarkenedHeight = totalHeight - darkenedHeight;
1350
- const darkenedY = runningHeight + chartSizingValues.totalTopOffset;
1351
- const nonDarkenedY = darkenedY + darkenedHeight;
1352
- const width = chartSizingValues.barSize;
1353
- const x = chartSizingValues.totalLeftOffset +
1354
- i * (chartSizingValues.barSize + chartSizingValues.bucketGap);
1355
- const colorOverride = config.flowConfig.subBucketsConfig.find(bc => bc.bucketId === bar.id)?.color;
1356
- if (darkenedHeight > 0) {
1357
- bucketBars.push({
1358
- elementType: 'rect',
1359
- rectType: 'flow',
1360
- height: darkenedHeight,
1361
- width,
1362
- y: darkenedY,
1363
- x,
1364
- colorOverride,
1365
- darken: true,
1366
- deEmphasize: isDeEmphasized(config, bar.id, true),
1367
- id: bar.id,
1368
- bucketIndex: i,
1369
- count: continuingCount,
1370
- totalCount: bar.count,
1371
- });
1372
- }
1373
- if (nonDarkenedHeight > 0) {
1374
- bucketBars.push({
1375
- elementType: 'rect',
1376
- rectType: 'flow',
1377
- height: nonDarkenedHeight,
1378
- width,
1379
- y: nonDarkenedY,
1380
- x,
1381
- colorOverride,
1382
- darken: false,
1383
- deEmphasize: isDeEmphasized(config, bar.id, false),
1384
- id: bar.id,
1385
- bucketIndex: i,
1386
- count: bar.count - continuingCount,
1387
- totalCount: bar.count,
1388
- });
1389
- }
1390
- //Invisible bar for hover highlight purposes
1391
- bucketBars.push({
1392
- elementType: 'rect',
1393
- rectType: 'flow',
1394
- height: darkenedHeight + nonDarkenedHeight,
1395
- width,
1396
- y: darkenedY,
1397
- x,
1398
- nonDisplay: true,
1399
- id: bar.id,
1400
- bucketIndex: i,
1401
- count: bar.count,
1402
- totalCount: bar.count,
1403
- darken: false,
1404
- deEmphasize: false,
1405
- });
1406
- runningHeight +=
1407
- totalHeight +
1408
- chartSizingValues.dataLabelPadding +
1409
- chartSizingValues.dataLabelTextSize;
1410
- //Connections
1411
- //Add new renders for forward connections
1412
- let verticalConnectionOffset = 0;
1413
- for (const connection of bar.connections.filter(connection => connection.direction === 'forward')) {
1414
- const topLineY1 = darkenedY + verticalConnectionOffset;
1415
- const bottomLineY1 = topLineY1 + connectionHeight(connection);
1416
- const x1 = x + width;
1417
- const connectionRender = {
1418
- elementType: 'connection',
1419
- start: connection.start,
1420
- end: connection.end,
1421
- count: connection.count,
1422
- step: i,
1423
- topLine: {
1424
- y1: topLineY1,
1425
- x1,
1426
- //To be filled in later
1427
- y2: 0,
1428
- x2: 0,
1429
- },
1430
- bottomLine: {
1431
- y1: bottomLineY1,
1432
- x1,
1433
- //To be filled in later
1434
- y2: 0,
1435
- x2: 0,
1436
- },
1437
- //To be filled in later
1438
- path: '',
1439
- };
1440
- verticalConnectionOffset += connectionHeight(connection);
1441
- flowConnections.push(connectionRender);
1442
- }
1443
- //Backfill position info for backwards connections
1444
- verticalConnectionOffset = 0;
1445
- for (const connection of bar.connections.filter(connection => connection.direction === 'backward')) {
1446
- const matchingConnection = flowConnections.find(con => con.start === connection.start &&
1447
- con.end === connection.end &&
1448
- con.step === i - 1);
1449
- if (matchingConnection) {
1450
- const topLineY2 = darkenedY + verticalConnectionOffset;
1451
- const bottomLineY2 = topLineY2 + connectionHeight(connection);
1452
- matchingConnection.topLine.y2 = topLineY2;
1453
- matchingConnection.topLine.x2 = x;
1454
- matchingConnection.bottomLine.y2 = bottomLineY2;
1455
- matchingConnection.bottomLine.x2 = x;
1456
- matchingConnection.path =
1457
- calculateFlowConnectionPath(matchingConnection);
1458
- verticalConnectionOffset += connectionHeight(connection);
1459
- }
1460
- }
1461
- //Data Labels
1462
- const barName = config.flowConfig.subBucketsConfig.find(sbc => sbc.bucketId === bar.id)?.bucketName;
1463
- if (barName !== undefined) {
1464
- dataLabels.push({
1465
- elementType: 'dataLabel',
1466
- dataLabelType: 'flow',
1467
- label: `${barName} (${percentPipes.pipe.transform(bar.count / data.x[i].totalCount)})`,
1468
- xPos: x,
1469
- yPos: darkenedY -
1470
- (chartSizingValues.dataLabelTextSize +
1471
- chartSizingValues.dataLabelPadding) /
1472
- 2,
1473
- anchor: 'start',
1474
- bold: true,
1475
- bucketIndex: i,
1476
- barId: bar.id,
1477
- });
1478
- }
1479
- const barSubtitle = config.flowConfig.subtitleFormatString.replace('{value}', valuePipes.pipe.transform(bar.count));
1480
- dataLabels.push({
1481
- elementType: 'dataLabel',
1482
- dataLabelType: 'flow',
1483
- label: barSubtitle,
1484
- xPos: x,
1485
- yPos: darkenedY - chartSizingValues.dataLabelPadding / 4,
1486
- anchor: 'start',
1487
- bucketIndex: i,
1488
- barId: bar.id,
1489
- });
1490
- }
1491
- bars.push(bucketBars);
1492
- }
1493
- function hover(pos) {
1494
- const realPosX = pos.x + pos.containerScrollX;
1495
- const realPosY = pos.y + pos.containerScrollY;
1496
- if (chartSizingValues === null ||
1497
- getIfHoverOutOfBounds(pos.x, pos.y, realPosX, realPosY, chartSizingValues, dimensions)) {
1498
- return null;
1499
- }
1500
- const bucketIndexInfo = getFlowBucketIndexForHover(chartSizingValues, realPosX);
1501
- if (bucketIndexInfo === null || bucketIndexInfo.index >= bars.length) {
1502
- return null;
1503
- }
1504
- if (bucketIndexInfo.area === 'bar') {
1505
- for (const bar of bars[bucketIndexInfo.index]) {
1506
- if (realPosY < bar.y) {
1507
- //Bar title
1508
- const localAnchorX = bar.x - pos.containerScrollX;
1509
- const width = bar.width;
1510
- const height = chartSizingValues.dataLabelPadding / 2 +
1511
- chartSizingValues.dataLabelTextSize;
1512
- const localAnchorY = bar.y - (pos.containerScrollY + height);
1513
- const { anchorX, anchorY, anchorWidth, anchorHeight } = checkAnchorsAgainstBound(localAnchorX, localAnchorY, dimensions, width, height);
1514
- const anchor = new DOMRect(anchorX + pos.rect.x, anchorY + pos.rect.y, anchorWidth, anchorHeight);
1515
- return {
1516
- hoverType: 'flow',
1517
- hoverTarget: 'barTitle',
1518
- barId: bar.id ?? '',
1519
- bucketIndex: bucketIndexInfo.index,
1520
- tooltip: {
1521
- anchor,
1522
- subtitle: config.flowConfig.subtitleFormatString.replace('{value}', valuePipes.pipe.transform(bar.totalCount)),
1523
- },
1524
- };
1525
- }
1526
- else if (
1527
- // The invisible highlight bar spans both portions, so skip it to
1528
- // avoid misreporting a portion boundary as the ending portion
1529
- !bar.nonDisplay &&
1530
- realPosY >= bar.y &&
1531
- realPosY < bar.y + bar.height) {
1532
- //Bar
1533
- const localAnchorX = bar.x - pos.containerScrollX;
1534
- const width = bar.width;
1535
- const localAnchorY = bar.y - pos.containerScrollY;
1536
- const height = bar.height;
1537
- const { anchorX, anchorY, anchorWidth, anchorHeight } = checkAnchorsAgainstBound(localAnchorX, localAnchorY, dimensions, width, height);
1538
- const anchor = new DOMRect(anchorX + pos.rect.x, anchorY + pos.rect.y, anchorWidth, anchorHeight);
1539
- return {
1540
- hoverType: 'flow',
1541
- hoverTarget: 'bar',
1542
- barId: bar.id ?? '',
1543
- bucketIndex: bucketIndexInfo.index,
1544
- forDarken: bar.darken === true,
1545
- tooltip: {
1546
- anchor,
1547
- subtitle: config.flowConfig.subtitleFormatString.replace('{value}', valuePipes.pipe.transform(bar.count)),
1548
- },
1549
- };
1550
- }
1551
- }
1552
- }
1553
- else {
1554
- for (const connection of flowConnections.filter(flowCon => flowCon.step === bucketIndexInfo.index)) {
1555
- if (checkIfPointWithinConnection(connection, realPosX, realPosY)) {
1556
- const localAnchorX = connection.topLine.x1 - pos.containerScrollX;
1557
- const width = connection.topLine.x2 - connection.topLine.x1;
1558
- const curveTop = bezierYAtX((connection.topLine.x1 + connection.topLine.x2) / 2, connection.topLine);
1559
- const curveBottom = bezierYAtX((connection.topLine.x1 + connection.topLine.x2) / 2, connection.bottomLine);
1560
- const localAnchorY = curveTop - pos.containerScrollY;
1561
- const height = curveBottom - curveTop;
1562
- const { anchorX, anchorY, anchorWidth, anchorHeight } = checkAnchorsAgainstBound(localAnchorX, localAnchorY, dimensions, width, height);
1563
- const anchor = new DOMRect(anchorX + pos.rect.x, anchorY + pos.rect.y, anchorWidth, anchorHeight);
1564
- return {
1565
- hoverType: 'flow',
1566
- hoverTarget: 'connection',
1567
- startId: connection.start,
1568
- endId: connection.end,
1569
- startBucketIndex: connection.step,
1570
- tooltip: {
1571
- anchor,
1572
- subtitle: config.flowConfig.subtitleFormatString.replace('{value}', valuePipes.pipe.transform(connection.count)),
1573
- },
1574
- };
1575
- }
1576
- }
1577
- }
1578
- return null;
1579
- }
1580
- return {
1581
- chartWidth: chartSizingValues.totalWidth,
1582
- chartHeight: chartSizingValues.totalHeight,
1583
- chartSizingValues,
1584
- xTicks: [],
1585
- yTicks: [],
1586
- colors: [],
1587
- bars,
1588
- lines: [],
1589
- circles: [],
1590
- areas: [],
1591
- hover,
1592
- arcs: [],
1593
- horizontalBars: [],
1594
- dataLabels,
1595
- waterfallLines: [],
1596
- gradients: [],
1597
- flowConnections,
1598
- horizontalContainerScale: chartSizingValues.horizontalContainerScale,
1599
- verticalContainerScale: chartSizingValues.verticalContainerScale,
1600
- chartError: null,
1601
- };
1602
- }
1603
- /*
1604
- Mirrors the bucketing in flowsTransform: a path contributes values[i] to
1605
- the bar at step i, and values[i + 1] to its forward connection (which is
1606
- also the bar's continuing portion).
1607
- */
1608
- function flowValueAtStep(y, step) {
1609
- return y.steps.length > step && y.values.length > step
1610
- ? y.values[step]
1611
- : null;
1612
- }
1613
- function sumFlowValues(data, yIndices, step) {
1614
- return yIndices
1615
- .map(index => flowValueAtStep(data.ys[index], step) ?? 0)
1616
- .reduce((a, b) => a + b, 0);
1617
- }
1618
- function toFlowClickEvent(hover, data) {
1619
- const allYIndices = data.ys.map((_, index) => index);
1620
- if (hover.hoverTarget === 'connection') {
1621
- const step = hover.startBucketIndex;
1622
- const yIndices = allYIndices.filter(index => data.ys[index].steps[step] === hover.startId &&
1623
- flowValueAtStep(data.ys[index], step) !== null &&
1624
- data.ys[index].steps[step + 1] === hover.endId &&
1625
- flowValueAtStep(data.ys[index], step + 1) !== null);
1626
- return {
1627
- target: 'connection',
1628
- startBucketIndex: step,
1629
- startId: hover.startId,
1630
- endId: hover.endId,
1631
- count: sumFlowValues(data, yIndices, step + 1),
1632
- yIndices,
1633
- };
1634
- }
1635
- const step = hover.bucketIndex;
1636
- const barYIndices = allYIndices.filter(index => data.ys[index].steps[step] === hover.barId &&
1637
- flowValueAtStep(data.ys[index], step) !== null);
1638
- const totalCount = sumFlowValues(data, barYIndices, step);
1639
- const base = { bucketIndex: step, barId: hover.barId };
1640
- if (hover.hoverTarget === 'barTitle') {
1641
- return {
1642
- ...base,
1643
- target: 'title',
1644
- count: totalCount,
1645
- yIndices: barYIndices,
1646
- };
1647
- }
1648
- const continuingCount = sumFlowValues(data, barYIndices, step + 1);
1649
- if (hover.forDarken) {
1650
- return {
1651
- ...base,
1652
- target: 'continuing',
1653
- count: continuingCount,
1654
- totalCount,
1655
- yIndices: barYIndices.filter(index => (flowValueAtStep(data.ys[index], step + 1) ?? 0) > 0),
1656
- };
1657
- }
1658
- return {
1659
- ...base,
1660
- target: 'ending',
1661
- count: totalCount - continuingCount,
1662
- totalCount,
1663
- yIndices: barYIndices.filter(index => (flowValueAtStep(data.ys[index], step) ?? 0) >
1664
- (flowValueAtStep(data.ys[index], step + 1) ?? 0)),
1665
- };
1666
- }
1667
- Chart.toFlowClickEvent = toFlowClickEvent;
1668
- const SMALL_PADDING = 8;
1669
- Chart.DEFAULT_FONT_SIZE = 12; //the width constants are based on font size 12, so this variable can help w/ scaling
1670
- Chart.WIDTH_PER_LETTER = 6.5;
1671
- const WIDTH_PER_NUMBER = 7;
1672
- const WIDTH_PER_PERIOD = 2;
1673
- const WIDTH_PER_SLASH = 4;
1674
- //When the data axis grows, the data is always given at least this portion of the provided size
1675
- const GROWN_DATA_MINIMUM_RATIO = 0.5;
1676
- const DEFAULT_HORIZONTAL_BAR_CORNER_RADIUS = 4;
1677
- const FLOW_CONNECTION_CURVE_CONSTANT = 0.5;
1678
- function getFormattingAndColors(originalData, data, config) {
1679
- const dateFormat = (date) => formatedDate(config.dateFormat || 'day', date);
1680
- const { pipe, fullPipe } = getPipes(config.valueType);
1681
- const { pipe: secondaryPipe, fullPipe: secondaryFullPipe } = config.secondaryValueType
1682
- ? getPipes(config.secondaryValueType)
1683
- : {
1684
- pipe,
1685
- fullPipe,
1686
- };
1687
- const pipeTransform = (value, isSecondary, isFull) => {
1688
- if (isFull !== true) {
1689
- if (isSecondary === true) {
1690
- return secondaryPipe.transform(value);
1691
- }
1692
- return pipe.transform(value);
1693
- }
1694
- let retVal = null;
1695
- if (isSecondary) {
1696
- retVal = secondaryFullPipe.transform(value);
1697
- }
1698
- else {
1699
- retVal = fullPipe.transform(value);
1700
- }
1701
- return retVal !== null ? retVal : '-';
1702
- };
1703
- // Pre-calculate color indices for all items (use original data for stable colors)
1704
- const colorIndices = calculateColorIndices(originalData);
1705
- const colors = data.ys.map(y => getColor(y, colorIndices, config.colors));
1706
- return {
1707
- dateFormat,
1708
- pipeTransform,
1709
- colorIndices,
1710
- colors,
1711
- };
1712
- }
1713
- function calculateColorIndices(data) {
1714
- const colorMap = new Map();
1715
- // Original Ys: use their array index directly
1716
- data.ys.forEach((y, index) => {
1717
- colorMap.set(y, index);
1718
- });
1719
- // Supplementary Ys: group by supplementalIndex, use position within that group
1720
- if (hasSupplementaryData(data)) {
1721
- const suppGroups = new Map();
1722
- data.supplementaryYs.forEach(suppY => {
1723
- if (!suppGroups.has(suppY.supplementalIndex)) {
1724
- suppGroups.set(suppY.supplementalIndex, []);
1725
- }
1726
- suppGroups.get(suppY.supplementalIndex).push(suppY);
1727
- });
1728
- suppGroups.forEach(items => {
1729
- items.forEach((item, positionInGroup) => {
1730
- colorMap.set(item, positionInGroup);
1731
- });
1732
- });
1733
- }
1734
- return colorMap;
1735
- }
1736
- Chart.calculateColorIndices = calculateColorIndices;
1737
- function getColor(item, colorIndices, colors) {
1738
- if (item === undefined) {
1739
- return colors[0];
1740
- }
1741
- if (item.colorToken)
1742
- return item.colorToken;
1743
- const colorIndex = colorIndices.get(item) ?? 0;
1744
- return colors[colorIndex % colors.length];
1745
- }
1746
- Chart.getColor = getColor;
1747
- function getBucketTickCount(chartSizingValues) {
1748
- let availableSize = 0;
1749
- let minSpacing = 1;
1750
- if (chartSizingValues.chartDataDirection === 'vertical') {
1751
- availableSize =
1752
- chartSizingValues.totalWidth -
1753
- chartSizingValues.leftPadding -
1754
- chartSizingValues.rightPadding;
1755
- minSpacing =
1756
- chartSizingValues.horizontalAxisLabelTextSize + SMALL_PADDING;
1757
- }
1758
- if (chartSizingValues.chartDataDirection === 'horizontal') {
1759
- availableSize =
1760
- chartSizingValues.totalHeight -
1761
- chartSizingValues.topPadding -
1762
- chartSizingValues.bottomPadding;
1763
- minSpacing = chartSizingValues.verticalAxisLabelTextSize + SMALL_PADDING;
1764
- }
1765
- minSpacing = minSpacing * (chartSizingValues.fontSize / Chart.DEFAULT_FONT_SIZE);
1766
- return Math.max(2, Math.floor(availableSize / minSpacing));
1767
- }
1768
- function getClusterInfoForBucket(data, config) {
1769
- // Slot layout is the same for every bucket — zero values still occupy
1770
- // their slot, they just render with no height/width. This keeps bucket
1771
- // sizes, bar positions, and hover detection consistent across buckets
1772
- // regardless of which series happen to be zero.
1773
- const normClusterIndices = data.ys.map((_, yIndex) => yIndex);
1774
- const normClusterCount = normClusterIndices.length;
1775
- const suppClusterIndices = uniq(hasSupplementaryData(data)
1776
- ? data.supplementaryYs.map(y => y.supplementalIndex)
1777
- : []);
1778
- suppClusterIndices.sort((a, b) => a - b);
1779
- const suppClusterCount = suppClusterIndices.length;
1780
- const actualNormClusterCount = isClusteredData(data, config, false)
1781
- ? normClusterCount
1782
- : Math.min(normClusterCount, 1);
1783
- return {
1784
- normCount: actualNormClusterCount,
1785
- suppCount: suppClusterCount,
1786
- total: actualNormClusterCount + suppClusterCount,
1787
- normClusterIndices,
1788
- suppClusterIndices,
1789
- };
1790
- }
1791
- //This function gives the total distance from the start of the given bucket, to the end of the current bucket
1792
- function getBucketSize(data, config, chartSizingValues) {
1793
- const totalBarNumber = getClusterInfoForBucket(data, config);
1794
- const bucketSize = totalBarNumber.total * chartSizingValues.barSize +
1795
- (totalBarNumber.total - 1) * chartSizingValues.barClusterGap;
1796
- return bucketSize;
1797
- }
1798
- //This function gives the total distance from the start of the given bucket, to the start of the next bucket
1799
- function getTotalBucketGap(data, config, chartSizingValues) {
1800
- const bucketSize = getBucketSize(data, config, chartSizingValues);
1801
- return bucketSize + chartSizingValues.bucketGap;
1802
- }
1803
- //This function gives the total distance from the start of the first bucket, to the start of the given bucket
1804
- function getTotalPreBucketGap(data, config, chartSizingValues, bucketIndex) {
1805
- let cumulativeBucketGap = 0;
1806
- for (let i = 0; i < bucketIndex; i++) {
1807
- cumulativeBucketGap += getTotalBucketGap(data, config, chartSizingValues);
1808
- }
1809
- return cumulativeBucketGap;
1810
- }
1811
- function generateTimeseriesTicks(data, config, tickCount, chartSizingValues, format) {
1812
- const getLabel = (index) => {
1813
- return format(new Date(data.x[index]));
1814
- };
1815
- return getTicks(data, getLabel, config, tickCount, chartSizingValues);
1816
- }
1817
- function generateLabelledTicks(data, config, tickCount, chartSizingValues) {
1818
- const getLabel = (index) => {
1819
- return data.x[index].label;
1820
- };
1821
- return getTicks(data, getLabel, config, tickCount, chartSizingValues);
1822
- }
1823
- function getTicks(data, getLabel, config, tickCount, chartSizingValues) {
1824
- if (data.x.length === 0) {
1825
- return [];
1826
- }
1827
- if (data.x.length === 1) {
1828
- const labelOffset = getTickLabelOffset(data, config, chartSizingValues, 0);
1829
- return [{ value: labelOffset, label: getLabel(0) }];
1830
- }
1831
- const lastIndex = data.x.length - 1;
1832
- const tickBucketSpacing = Math.ceil(lastIndex / tickCount);
1833
- const numTicks = Math.floor(lastIndex / tickBucketSpacing) + 1;
1834
- const step = lastIndex / (numTicks - 1);
1835
- // Always include first and last data points.
1836
- // Inner ticks are approximately evenly spaced using rounding.
1837
- const indices = [];
1838
- for (let i = 0; i < numTicks; i++) {
1839
- indices.push(Math.round(i * step));
1840
- }
1841
- return indices.map(i => {
1842
- const labelOffset = getTickLabelOffset(data, config, chartSizingValues, i);
1843
- return {
1844
- value: getTotalPreBucketGap(data, config, chartSizingValues, i) +
1845
- labelOffset,
1846
- label: getLabel(i),
1847
- };
1848
- });
1849
- }
1850
- function getTickLabelOffset(data, config, chartSizingValues, bucketIndex) {
1851
- const inherentOffset = chartSizingValues.chartDataDirection === 'horizontal'
1852
- ? chartSizingValues.totalTopOffset
1853
- : chartSizingValues.totalLeftOffset;
1854
- //To have the label be centered on the bucket's center position
1855
- const bucketOffset = getBucketSize(data, config, chartSizingValues) / 2;
1856
- let horizontalBarOffset = 0;
1857
- if (chartSizingValues.chartDataDirection === 'horizontal') {
1858
- //This account for the fact that the inherentOffset and bucketOffset result in matching y values for the bar and the label
1859
- // However, for the bar, that y position is the top of the bar, while for the label, it's the bottom of the label
1860
- // When exactly lined up like that, the label actually looks a little low, so that -2 makes it look correct
1861
- horizontalBarOffset = chartSizingValues.fontSize / 2 - 2;
1862
- }
1863
- return inherentOffset + bucketOffset + horizontalBarOffset;
1864
- }
1865
- Chart.defaultConfig = {
1866
- type: 'line',
1867
- groupedTooltip: true,
1868
- colors: Chart.defaultColorPalette,
1869
- allowLegendToggle: false,
1870
- zeroStateMessage: 'No data to display.',
1871
- sizingErrorStateMessage: 'The chart cannot display at the current size.',
1872
- valueType: 'currency',
1873
- truncateLegend: true,
1874
- dateFormat: 'day',
1875
- };
1876
- Chart.defaultDonutConfig = {
1877
- type: 'donut',
1878
- groupedTooltip: true,
1879
- colors: Chart.defaultColorPalette,
1880
- allowLegendToggle: false,
1881
- zeroStateMessage: 'No data to display.',
1882
- sizingErrorStateMessage: 'The chart cannot display at the current size.',
1883
- valueType: 'currency',
1884
- truncateLegend: true,
1885
- dateFormat: 'day',
1886
- donutDisplayInfo: {
1887
- size: 'medium',
1888
- displayValue: '',
1889
- },
1890
- };
1891
- function toXTick(tick) {
1892
- return {
1893
- x: tick.value,
1894
- label: tick.label,
1895
- secondaryLabel: tick.secondaryLabel,
1896
- };
1897
- }
1898
- function toYTick(tick) {
1899
- return {
1900
- y: tick.value,
1901
- label: tick.label,
1902
- secondaryLabel: tick.secondaryLabel,
1903
- };
1904
- }
1905
- const emptyChart = {
1906
- chartWidth: 0,
1907
- chartHeight: 0,
1908
- chartSizingValues: emptyChartScaleValues,
1909
- xTicks: [],
1910
- yTicks: [],
1911
- colors: [],
1912
- lines: [],
1913
- circles: [],
1914
- areas: [],
1915
- bars: [],
1916
- arcs: [],
1917
- horizontalBars: [],
1918
- dataLabels: [],
1919
- waterfallLines: [],
1920
- gradients: [],
1921
- flowConnections: [],
1922
- horizontalContainerScale: 'no-scale',
1923
- verticalContainerScale: 'no-scale',
1924
- chartError: null,
1925
- };
1926
- //'y' in this function refers to the data y, since this function
1927
- // is also used by horizontal-bars, where the data y is the chart x
1928
- function calcDataAxisScalesAndTicks(data, pipeTransformInput, config, chartSizingValues) {
1929
- const pipeTransform = pipeTransformInput !== null ? pipeTransformInput : () => '';
1930
- const { primaryDataMin, primaryDataMax, secondaryDataMin, secondaryDataMax, scaleDomainMultipleForMax, scaleDomainMultipleForNeg, } = calcDataScalingValues(data, config);
1931
- const startOffset = chartSizingValues.chartDataDirection === 'horizontal'
1932
- ? chartSizingValues.totalLeftOffset
1933
- : chartSizingValues.totalTopOffset;
1934
- let minSpacing = (chartSizingValues.chartDataDirection === 'horizontal'
1935
- ? chartSizingValues.horizontalAxisLabelTextSize
1936
- : chartSizingValues.verticalAxisLabelTextSize) + SMALL_PADDING;
1937
- minSpacing = minSpacing * (chartSizingValues.fontSize / Chart.DEFAULT_FONT_SIZE);
1938
- const spacingTickCount = Math.max(2, Math.floor(chartSizingValues.sizeForData / minSpacing));
1939
- const actualTargetTickCount = Math.min(spacingTickCount, chartSizingValues.targetTickCount);
1940
- const hasPrimary = primaryDataMin !== 0 || primaryDataMax !== 0;
1941
- const hasSecondary = secondaryDataMin !== 0 || secondaryDataMax !== 0;
1942
- const scaleRange = chartSizingValues.chartDataDirection === 'horizontal' ||
1943
- config.type === 'flow'
1944
- ? [0, chartSizingValues.sizeForData]
1945
- : [chartSizingValues.sizeForData, 0];
1946
- //These 'effective' values ensure we have room for potential stacking of secondary and non-secondary values
1947
- let effectivePrimaryMin = primaryDataMin * scaleDomainMultipleForNeg;
1948
- let effectivePrimaryMax = primaryDataMax * scaleDomainMultipleForMax;
1949
- //Simpler path for data w/o secondaries
1950
- if (!hasSecondary) {
1951
- const primaryYDomain = [effectivePrimaryMin, effectivePrimaryMax];
1952
- const yScale = scaleLinear(primaryYDomain, scaleRange);
1953
- const ticks = yScale
1954
- .ticks(actualTargetTickCount)
1955
- .map(tick => ({
1956
- value: yScale(tick) + startOffset,
1957
- label: pipeTransform(tick, false),
1958
- }));
1959
- const scale = (input) => {
1960
- return yScale(input) + startOffset;
1961
- };
1962
- return {
1963
- scale,
1964
- ticks,
1965
- };
1966
- }
1967
- //Simpler path for data w/o primaries
1968
- if (!hasPrimary) {
1969
- const secondaryYDomain = [secondaryDataMin, secondaryDataMax];
1970
- const yScale = scaleLinear(secondaryYDomain, scaleRange);
1971
- const ticks = yScale
1972
- .ticks(actualTargetTickCount)
1973
- .map(tick => ({
1974
- value: yScale(tick) + startOffset,
1975
- label: pipeTransform(tick, true),
1976
- }));
1977
- const scale = (input) => {
1978
- return yScale(input) + startOffset;
1979
- };
1980
- return {
1981
- scale,
1982
- ticks,
1983
- };
1984
- }
1985
- let effectiveSecondaryMax = 0;
1986
- let effectiveSecondaryMin = 0;
1987
- //This block sets the effective max for primary and secondary
1988
- //This to ensure that the effective maxes for both data sets are properly set so that
1989
- // 0 will fall at the same place on both and each will have 'room' for potential stacking
1990
- if ((primaryDataMax <= 0 && secondaryDataMin >= 0) ||
1991
- (primaryDataMin >= 0 && secondaryDataMax <= 0)) {
1992
- //In this scenario, one set of data is competely positive, while the other is completely negative
1993
- //The two data sets can scale completely independently
1994
- //We 'mirror' the values of the two data sets, which'll put the 0 axis in the center of the data
1995
- if (primaryDataMax <= 0) {
1996
- effectivePrimaryMax = Math.abs(effectivePrimaryMin);
1997
- }
1998
- if (primaryDataMin >= 0) {
1999
- effectivePrimaryMin = -Math.abs(effectivePrimaryMax);
2000
- }
2001
- if (secondaryDataMax <= 0) {
2002
- effectiveSecondaryMin = secondaryDataMin;
2003
- effectiveSecondaryMax = Math.abs(secondaryDataMin);
2004
- }
2005
- if (secondaryDataMin >= 0) {
2006
- effectiveSecondaryMax = secondaryDataMax;
2007
- effectiveSecondaryMin = -secondaryDataMax;
2008
- }
2009
- }
2010
- else if (primaryDataMax > 0) {
2011
- if (primaryDataMin < 0) {
2012
- //Primary data has positive and negative
2013
- if (secondaryDataMax > 0) {
2014
- //Secondary data has positive
2015
- effectiveSecondaryMax = secondaryDataMax * scaleDomainMultipleForMax;
2016
- if (secondaryDataMin < 0) {
2017
- //Secondary data has negative
2018
- effectiveSecondaryMin =
2019
- secondaryDataMin * scaleDomainMultipleForNeg;
2020
- }
2021
- else {
2022
- //Secondary data is only positive
2023
- effectiveSecondaryMin =
2024
- (secondaryDataMax / primaryDataMax) *
2025
- primaryDataMin *
2026
- scaleDomainMultipleForNeg;
2027
- }
2028
- }
2029
- else {
2030
- //Secondary data has only negative
2031
- effectiveSecondaryMin = secondaryDataMin * scaleDomainMultipleForNeg;
2032
- effectiveSecondaryMax =
2033
- (secondaryDataMin / primaryDataMin) *
2034
- primaryDataMax *
2035
- scaleDomainMultipleForMax;
2036
- }
2037
- }
2038
- else {
2039
- //Primary data is only positive
2040
- //Due to earlier check, we know that secondary data is either also all-positive, or positive and negative
2041
- effectiveSecondaryMax = secondaryDataMax * scaleDomainMultipleForMax;
2042
- effectiveSecondaryMin = secondaryDataMin * scaleDomainMultipleForNeg;
2043
- effectivePrimaryMin =
2044
- (primaryDataMax / secondaryDataMax) *
2045
- secondaryDataMin *
2046
- scaleDomainMultipleForNeg;
2047
- }
2048
- }
2049
- else {
2050
- //Primary data is only negative
2051
- //Due to earlier check, we know that secondary data is either also all-negative, or positive and negative
2052
- effectiveSecondaryMax = secondaryDataMax * scaleDomainMultipleForMax;
2053
- effectiveSecondaryMin = secondaryDataMin * scaleDomainMultipleForNeg;
2054
- effectivePrimaryMax =
2055
- (primaryDataMin / secondaryDataMin) *
2056
- secondaryDataMax *
2057
- scaleDomainMultipleForMax;
2058
- }
2059
- const primaryYDomain = [effectivePrimaryMin, effectivePrimaryMax];
2060
- const yScale = scaleLinear(primaryYDomain, scaleRange);
2061
- //Figuring out the best tick count to fit the two data srouces
2062
- const yScalePrimaryProto = scaleLinear(primaryYDomain, scaleRange);
2063
- const yScaleSecondaryProto = scaleLinear([effectiveSecondaryMin, effectiveSecondaryMax], scaleRange);
2064
- const tickCount = Math.max(actualTargetTickCount, yScalePrimaryProto.ticks(actualTargetTickCount).length, yScaleSecondaryProto.ticks(actualTargetTickCount).length);
2065
- const primaryTicks = yScale.ticks(tickCount).map(tick => ({
2066
- value: yScale(tick) + startOffset,
2067
- label: pipeTransform(tick, false),
2068
- rawY: tick,
2069
- }));
2070
- //Finding a domain for the secondary data such that it will result in round tick values when matched with the primary ticks
2071
- const secondaryTicksProto = yScaleSecondaryProto
2072
- .ticks(tickCount)
2073
- .map(tick => ({
2074
- y: yScaleSecondaryProto(tick),
2075
- rawY: tick,
2076
- label: pipeTransform(tick, true),
2077
- }));
2078
- const primaryMinTick = Math.min(...primaryTicks.map(tick => tick.rawY));
2079
- const primaryMaxTick = Math.max(...primaryTicks.map(tick => tick.rawY));
2080
- const primaryDomainMaxTickRatio = primaryMaxTick !== 0 ? effectivePrimaryMax / primaryMaxTick : 0;
2081
- const primaryDomainMinTickRatio = primaryMinTick !== 0 ? effectivePrimaryMin / primaryMinTick : 0;
2082
- const primaryGap = primaryTicks[1].rawY - primaryTicks[0].rawY;
2083
- const ticksBelowZero = primaryMinTick / primaryGap;
2084
- const ticksAboveZero = primaryMaxTick / primaryGap;
2085
- const secondaryGap = secondaryTicksProto[1].rawY - secondaryTicksProto[0].rawY;
2086
- let calcRangeMult = 1;
2087
- const secondaryDomainMinMult = ticksBelowZero * secondaryGap * primaryDomainMinTickRatio;
2088
- const secondaryDomainMaxMult = ticksAboveZero * secondaryGap * primaryDomainMaxTickRatio;
2089
- //First, we ensure the calcRangeMult is big enough
2090
- let sizeUpComplete = false;
2091
- while (!sizeUpComplete) {
2092
- const calcRangeTooSmallForMin = secondaryDomainMinMult * calcRangeMult > effectiveSecondaryMin &&
2093
- secondaryDomainMinMult !== 0;
2094
- const calcRangeTooSmallForMax = secondaryDomainMaxMult * calcRangeMult < effectiveSecondaryMax &&
2095
- secondaryDomainMaxMult !== 0;
2096
- if (calcRangeTooSmallForMin || calcRangeTooSmallForMax) {
2097
- calcRangeMult = calcRangeMult * 2;
2098
- }
2099
- else {
2100
- sizeUpComplete = true;
2101
- }
2102
- }
2103
- //Then, we check if we can scale down (for this one, both conditions have to be true, so it won't undo a previous scale up)
2104
- let sizeDownComplete = false;
2105
- while (!sizeDownComplete) {
2106
- const calcRangeTooBigForMin = secondaryDomainMinMult * calcRangeMult < effectiveSecondaryMin * 2 &&
2107
- secondaryDomainMinMult !== 0;
2108
- const calcRangeTooBigForMax = secondaryDomainMaxMult * calcRangeMult > effectiveSecondaryMax * 2 &&
2109
- secondaryDomainMaxMult !== 0;
2110
- if (calcRangeTooBigForMin && calcRangeTooBigForMax) {
2111
- calcRangeMult = calcRangeMult / 2;
2112
- }
2113
- else {
2114
- sizeDownComplete = true;
2115
- }
2116
- }
2117
- let secondaryDomainMin = secondaryDomainMinMult * calcRangeMult;
2118
- let secondaryDomainMax = secondaryDomainMaxMult * calcRangeMult;
2119
- //If the data is lopsided enough, it's possible that one of positive/negative have values, but no ticks
2120
- if (secondaryDomainMin === 0 && effectivePrimaryMin < 0) {
2121
- const posSecRatio = secondaryDomainMax / effectivePrimaryMax;
2122
- secondaryDomainMin = posSecRatio * effectivePrimaryMin;
2123
- }
2124
- if (secondaryDomainMax === 0 && effectivePrimaryMax > 0) {
2125
- const posSecRatio = secondaryDomainMin / effectivePrimaryMin;
2126
- secondaryDomainMax = posSecRatio * effectivePrimaryMax;
2127
- }
2128
- const yScaleSecondary = scaleLinear([secondaryDomainMin, secondaryDomainMax], scaleRange);
2129
- const ticks = primaryTicks.map(tick => ({
2130
- ...tick,
2131
- secondaryLabel: pipeTransform(yScaleSecondary.invert(yScale(tick.rawY)), true),
2132
- }));
2133
- const scale = (input, isSecondary) => {
2134
- if (isSecondary) {
2135
- return yScaleSecondary(input) + startOffset;
2136
- }
2137
- return yScale(input) + startOffset;
2138
- };
2139
- return {
2140
- scale,
2141
- ticks,
2142
- };
2143
- }
2144
- function calcDataScalingValues(data, config) {
2145
- const isStacked = isStackedData(config);
2146
- const primaryDomainValues = calcYScaleDomainValues(data, isStacked, false);
2147
- const secondaryDomainValues = calcYScaleDomainValues(data, isStacked, true);
2148
- const primaryDataMax = Math.max(...primaryDomainValues.map(val => val.max));
2149
- const secondaryDataMax = Math.max(...secondaryDomainValues.map(val => val.max));
2150
- const primaryDataMin = Math.min(...primaryDomainValues.map(val => val.min));
2151
- const secondaryDataMin = Math.min(...secondaryDomainValues.map(val => val.min));
2152
- let scaleDomainMultipleForMax = 1;
2153
- let scaleDomainMultipleForNeg = 1;
2154
- //Calculating how much we need to multiple the domain by to 'fit' both axes' data
2155
- if (isStacked) {
2156
- for (let i = 0; i < primaryDomainValues.length; i++) {
2157
- //Check positive max
2158
- const primaryVal = primaryDomainValues[i].max;
2159
- const secondaryVal = secondaryDomainValues[i].max;
2160
- const primaryRatio = primaryDataMax !== 0 ? primaryVal / primaryDataMax : 0;
2161
- const secondaryRatio = secondaryDataMax !== 0 ? secondaryVal / secondaryDataMax : 0;
2162
- const multVal = primaryRatio + secondaryRatio;
2163
- if (multVal > scaleDomainMultipleForMax) {
2164
- scaleDomainMultipleForMax = multVal;
2165
- }
2166
- //Check negative min
2167
- const primaryNegVal = primaryDomainValues[i].min < 0 ? primaryDomainValues[i].min : 0;
2168
- const secondaryNegVal = secondaryDomainValues[i].min < 0 ? secondaryDomainValues[i].min : 0;
2169
- const primaryNegRatio = primaryDataMin !== 0 ? primaryNegVal / primaryDataMin : 0;
2170
- const secondaryNegRatio = secondaryDataMin !== 0 ? secondaryNegVal / secondaryDataMin : 0;
2171
- const negMultVal = primaryNegRatio + secondaryNegRatio;
2172
- if (negMultVal > scaleDomainMultipleForNeg) {
2173
- scaleDomainMultipleForNeg = negMultVal;
2174
- }
2175
- }
2176
- }
2177
- return {
2178
- primaryDataMin,
2179
- primaryDataMax,
2180
- secondaryDataMin,
2181
- secondaryDataMax,
2182
- scaleDomainMultipleForMax,
2183
- scaleDomainMultipleForNeg,
2184
- };
2185
- }
2186
- function calcYScaleDomainValues(data, isStacked, forSecondary) {
2187
- if (data.type === 'flow-processed') {
2188
- if (forSecondary) {
2189
- //Flow charts don't support secondary data
2190
- return [{ min: 0, max: 0 }];
2191
- }
2192
- return [
2193
- {
2194
- min: 0,
2195
- max: Math.max(...data.x.map(x => x.totalCount)),
2196
- },
2197
- ];
2198
- }
2199
- const possiblyStackedYs = data.ys.map((y, yIndex) => {
2200
- //Handle stacking
2201
- return isStacked
2202
- ? y.values.map((val, xIndex) => {
2203
- let prevRunningTotal = 0;
2204
- for (let yI = 0; yI < yIndex; yI++) {
2205
- if (checkIfSecondary(data, yI, xIndex, false) !== forSecondary) {
2206
- continue;
2207
- }
2208
- const addVal = data.ys[yI].values[xIndex];
2209
- //Only stack values of the same sign
2210
- if (addVal < 0 === val < 0) {
2211
- prevRunningTotal += addVal;
2212
- }
2213
- }
2214
- return val + prevRunningTotal;
2215
- })
2216
- : y.values;
2217
- });
2218
- const suppYs = hasSupplementaryData(data) ? data.supplementaryYs : null;
2219
- let possiblyStackedSupYs = [];
2220
- if (suppYs) {
2221
- possiblyStackedSupYs = suppYs.map((y, yIndex) => {
2222
- //Handle stacking
2223
- return isStacked
2224
- ? y.values.map((val, xIndex) => {
2225
- let prevRunningTotal = 0;
2226
- for (let yI = 0; yI < yIndex; yI++) {
2227
- if (checkIfSecondary(data, yI, xIndex, true) !== forSecondary ||
2228
- suppYs[yI].supplementalIndex !== y.supplementalIndex) {
2229
- continue;
2230
- }
2231
- const addVal = suppYs[yI].values[xIndex];
2232
- //Only stack values of the same sign
2233
- if (addVal < 0 === val < 0) {
2234
- prevRunningTotal += addVal;
2235
- }
2236
- }
2237
- return val + prevRunningTotal;
2238
- })
2239
- : y.values;
2240
- });
2241
- }
2242
- const scaleRange = [];
2243
- for (let i = 0; i < data.x.length; i++) {
2244
- const maxNormY = Math.max(...possiblyStackedYs.map((y, yIndex) => {
2245
- if (checkIfSecondary(data, yIndex, i, false) !== forSecondary) {
2246
- return 0;
2247
- }
2248
- return y[i];
2249
- }));
2250
- const minNormY = Math.min(...possiblyStackedYs.map((y, yIndex) => {
2251
- if (checkIfSecondary(data, yIndex, i, false) !== forSecondary) {
2252
- return 0;
2253
- }
2254
- return y[i];
2255
- }));
2256
- const maxSupY = suppYs
2257
- ? Math.max(...possiblyStackedSupYs.map((y, yIndex) => {
2258
- if (checkIfSecondary(data, yIndex, i, true) !== forSecondary) {
2259
- return 0;
2260
- }
2261
- return y[i];
2262
- }))
2263
- : 0;
2264
- const minSupY = suppYs
2265
- ? Math.min(...possiblyStackedSupYs.map((y, yIndex) => {
2266
- if (checkIfSecondary(data, yIndex, i, true) !== forSecondary) {
2267
- return 0;
2268
- }
2269
- return y[i];
2270
- }))
2271
- : 0;
2272
- const max = maxNormY > 0 && maxNormY > maxSupY
2273
- ? maxNormY
2274
- : maxSupY > 0
2275
- ? maxSupY
2276
- : 0;
2277
- const min = minNormY < 0 && minNormY < minSupY
2278
- ? minNormY
2279
- : minSupY < 0
2280
- ? minSupY
2281
- : 0;
2282
- scaleRange.push({ max, min });
2283
- }
2284
- return scaleRange;
2285
- }
2286
- function calculateBarPosition(data, config, chartSizingValues, bucketNum, clusterNum) {
2287
- const offset = chartSizingValues.chartDataDirection === 'vertical'
2288
- ? chartSizingValues.totalLeftOffset
2289
- : chartSizingValues.totalTopOffset;
2290
- const clusterOffset = clusterNum *
2291
- (chartSizingValues.barSize + chartSizingValues.barClusterGap);
2292
- const cumulativeBucketGap = getTotalPreBucketGap(data, config, chartSizingValues, bucketNum);
2293
- return offset + cumulativeBucketGap + clusterOffset;
2294
- }
2295
- function calculateHorizontalBarPath(leftSideRound, rightSideRound, xValue, yValue, horR, verR, height, width) {
2296
- if (leftSideRound && rightSideRound) {
2297
- //Both-sides rounding variation
2298
- const pathD = `
2299
- M ${xValue + horR},${yValue}
2300
- h ${width - horR * 2}
2301
- q${horR},0 ${horR},${verR}
2302
- v ${height - verR * 2}
2303
- q0,${verR} -${horR},${verR}
2304
- h ${-(width - horR * 2)}
2305
- q-${horR},0 -${horR},-${verR}
2306
- v -${height - verR * 2}
2307
- q0,-${verR} ${horR},-${verR}
2308
- Z
2309
- `;
2310
- return pathD;
2311
- }
2312
- if (leftSideRound) {
2313
- //Left-side rounding variation
2314
- const pathD = `
2315
- M ${xValue + horR},${yValue}
2316
- h ${width - horR}
2317
- v ${height}
2318
- h ${-(width - horR)}
2319
- q-${horR},0 -${horR},-${verR}
2320
- v -${height - verR * 2}
2321
- q0,-${verR} ${horR},-${verR}
2322
- Z
2323
- `;
2324
- return pathD;
2325
- }
2326
- if (rightSideRound) {
2327
- //Right-side rounding variation
2328
- const pathD = `
2329
- M ${xValue},${yValue}
2330
- h ${width - horR}
2331
- q${horR},0 ${horR},${verR}
2332
- v ${height - verR * 2}
2333
- q0,${verR} -${horR},${verR}
2334
- h ${-(width - horR)}
2335
- Z
2336
- `;
2337
- return pathD;
2338
- }
2339
- //No-rounding variation
2340
- const pathD = `
2341
- M ${xValue},${yValue}
2342
- h ${width}
2343
- v ${height}
2344
- h ${-width}
2345
- v -${height}
2346
- Z
2347
- `;
2348
- return pathD;
2349
- }
2350
- function getBucketAndClusterNumForHover(pos, chartSizingValues, data, config, bucketCount) {
2351
- let bucketLeeway = chartSizingValues.bucketGap / 4;
2352
- //if there's only 1 data point, use the outerGap as leeway instead
2353
- if (data.x.length === 1) {
2354
- bucketLeeway = chartSizingValues.outerGap / 4;
2355
- }
2356
- const barLeeway = chartSizingValues.barClusterGap / 2;
2357
- const offset = chartSizingValues.chartDataDirection === 'vertical'
2358
- ? chartSizingValues.totalLeftOffset
2359
- : chartSizingValues.totalTopOffset;
2360
- const relativePos = pos - offset;
2361
- let bucketNum = -1;
2362
- for (let i = 0; i < bucketCount; i++) {
2363
- const bucketStartPos = getTotalPreBucketGap(data, config, chartSizingValues, i);
2364
- if (bucketStartPos - bucketLeeway < relativePos &&
2365
- bucketStartPos +
2366
- getBucketSize(data, config, chartSizingValues) +
2367
- bucketLeeway >
2368
- relativePos) {
2369
- bucketNum = i;
2370
- break;
2371
- }
2372
- }
2373
- if (bucketNum === -1) {
2374
- return null;
2375
- }
2376
- if (!isClusteredData(data, config, true)) {
2377
- return {
2378
- bucketNum,
2379
- clusterNum: 0,
2380
- clusterNormCount: 1,
2381
- clusterNumType: 'norm',
2382
- };
2383
- }
2384
- const relativeBucketPos = relativePos -
2385
- getTotalPreBucketGap(data, config, chartSizingValues, bucketNum);
2386
- const clusterCount = getClusterInfoForBucket(data, config);
2387
- let clusterNum = -1;
2388
- for (let i = 0; i < clusterCount.total; i++) {
2389
- const barStartPos = (chartSizingValues.barSize + chartSizingValues.barClusterGap) * i;
2390
- if (barStartPos - barLeeway < relativeBucketPos &&
2391
- barStartPos + chartSizingValues.barSize + barLeeway > relativeBucketPos) {
2392
- clusterNum = i;
2393
- break;
2394
- }
2395
- }
2396
- if (clusterNum === -1) {
2397
- return null;
2398
- }
2399
- let clusterNumType = 'norm';
2400
- if (clusterNum >= clusterCount.normCount) {
2401
- clusterNumType = 'supp';
2402
- }
2403
- return {
2404
- bucketNum,
2405
- clusterNum,
2406
- clusterNormCount: clusterCount.normCount,
2407
- clusterNumType,
2408
- };
2409
- }
2410
- function findNearestIndexWithSecondary(yInfo, yPos, scale) {
2411
- let foundIndex = 0;
2412
- let currMinDistance = Math.abs(scale(yInfo[0].value, yInfo[0].isSecondary) - yPos);
2413
- for (let i = 1; i < yInfo.length; i++) {
2414
- const newDistance = Math.abs(scale(yInfo[i].value, yInfo[i].isSecondary) - yPos);
2415
- if (newDistance < currMinDistance) {
2416
- foundIndex = i;
2417
- currMinDistance = newDistance;
2418
- }
2419
- }
2420
- return foundIndex;
2421
- }
2422
- function getBarYInfo(data, config, yIndex, xIndex, scale, isSupplementary = false) {
2423
- const isStacked = isStackedData(config);
2424
- const minimumSize = getMinimumDataElementSize(config);
2425
- const zeroVal = scale(0, true);
2426
- const yData = getMainOrSuppY(data, yIndex, isSupplementary);
2427
- const scaleValue = scale(yData.values[xIndex], checkIfSecondary(data, yIndex, xIndex, isSupplementary));
2428
- if (scaleValue > zeroVal) {
2429
- let prevBarHeights = 0;
2430
- if (isStacked) {
2431
- for (let i = 0; i < yIndex; i++) {
2432
- const checkData = getMainOrSuppY(data, i, isSupplementary);
2433
- //Both yData and checkData are definitely SupplementaryDataYs if isSupplementary is true, but they don't realize it
2434
- if (isSupplementary &&
2435
- 'supplementalIndex' in yData &&
2436
- 'supplementalIndex' in checkData) {
2437
- if (yData.supplementalIndex !== checkData.supplementalIndex) {
2438
- continue;
2439
- }
2440
- }
2441
- const checkValue = scale(checkData.values[xIndex], checkIfSecondary(data, i, xIndex, isSupplementary));
2442
- //Skip positive values
2443
- if (checkValue < zeroVal) {
2444
- continue;
2445
- }
2446
- prevBarHeights += applyMinimumDataElementSize(checkValue - zeroVal, checkData.values[xIndex], minimumSize);
2447
- }
2448
- }
2449
- const yValue = zeroVal + prevBarHeights;
2450
- const height = applyMinimumDataElementSize(scaleValue - zeroVal, yData.values[xIndex], minimumSize);
2451
- return { yValue, height };
2452
- }
2453
- let prevBarHeights = 0;
2454
- if (isStacked) {
2455
- for (let i = 0; i < yIndex; i++) {
2456
- const checkData = getMainOrSuppY(data, i, isSupplementary);
2457
- //Both yData and checkData are definitely SupplementaryDataYs if isSupplementary is true, but they don't realize it
2458
- if (isSupplementary &&
2459
- 'supplementalIndex' in yData &&
2460
- 'supplementalIndex' in checkData) {
2461
- if (yData.supplementalIndex !== checkData.supplementalIndex) {
2462
- continue;
2463
- }
2464
- }
2465
- const checkValue = scale(checkData.values[xIndex], checkIfSecondary(data, i, xIndex, isSupplementary));
2466
- //Skip negative values
2467
- if (checkValue > zeroVal) {
2468
- continue;
2469
- }
2470
- prevBarHeights += applyMinimumDataElementSize(zeroVal - checkValue, checkData.values[xIndex], minimumSize);
2471
- }
2472
- }
2473
- const height = applyMinimumDataElementSize(zeroVal - scaleValue, yData.values[xIndex], minimumSize);
2474
- const yValue = zeroVal - height - prevBarHeights;
2475
- return { yValue, height };
2476
- }
2477
- function getSuppBarYInfoViaYIndex(data, config, yIndex, suppIndex, xIndex, scale) {
2478
- if (!hasSupplementaryData(data)) {
2479
- return { yValue: 0, height: 0 };
2480
- }
2481
- const suppYs = data.supplementaryYs;
2482
- // Find supplementary bars with the given supplementalIndex
2483
- const groupSupps = suppYs.filter(s => s.supplementalIndex === suppIndex);
2484
- // yIndex refers to which Y series (within the supplemental group) we're looking at
2485
- if (yIndex >= 0 && yIndex < groupSupps.length) {
2486
- // Find this supp in the original array
2487
- const suppInOriginalArray = suppYs.indexOf(groupSupps[yIndex]);
2488
- return getBarYInfo(data, config, suppInOriginalArray, xIndex, scale, true);
2489
- }
2490
- return { yValue: 0, height: 0 };
2491
- }
2492
- function getMainOrSuppY(data, yIndex, isSupplementary) {
2493
- if (hasSupplementaryData(data) && isSupplementary) {
2494
- return data.supplementaryYs[yIndex];
2495
- }
2496
- return data.ys[yIndex];
2497
- }
2498
- function getBarXInfo(data, config, yIndex, xIndex, scale, isSupplementary = false) {
2499
- const isStacked = isStackedData(config);
2500
- const minimumSize = getMinimumDataElementSize(config);
2501
- const zeroVal = scale(0, true);
2502
- const yData = getMainOrSuppY(data, yIndex, isSupplementary);
2503
- const scaleValue = scale(yData.values[xIndex], checkIfSecondary(data, yIndex, xIndex, isSupplementary));
2504
- if (scaleValue < zeroVal) {
2505
- let prevBarWidths = 0;
2506
- if (isStacked) {
2507
- for (let i = 0; i < yIndex; i++) {
2508
- const checkData = getMainOrSuppY(data, i, isSupplementary);
2509
- //Both yData and checkData are definitely SupplementaryDataYs if isSupplementary is true, but they don't realize it
2510
- if (isSupplementary &&
2511
- 'supplementalIndex' in yData &&
2512
- 'supplementalIndex' in checkData) {
2513
- if (yData.supplementalIndex !== checkData.supplementalIndex) {
2514
- continue;
2515
- }
2516
- }
2517
- const checkVal = scale(checkData.values[xIndex], checkIfSecondary(data, i, xIndex, isSupplementary));
2518
- //Skip positive values
2519
- if (checkVal > zeroVal) {
2520
- continue;
2521
- }
2522
- prevBarWidths += applyMinimumDataElementSize(zeroVal - checkVal, checkData.values[xIndex], minimumSize);
2523
- }
2524
- }
2525
- const width = applyMinimumDataElementSize(zeroVal - scaleValue, yData.values[xIndex], minimumSize);
2526
- const xValue = zeroVal - width - prevBarWidths;
2527
- return { xValue, width };
2528
- }
2529
- let prevBarWidths = 0;
2530
- if (isStacked) {
2531
- for (let i = 0; i < yIndex; i++) {
2532
- const checkData = getMainOrSuppY(data, i, isSupplementary);
2533
- //Both yData and checkData are definitely SupplementaryDataYs if isSupplementary is true, but they don't realize it
2534
- if (isSupplementary &&
2535
- 'supplementalIndex' in yData &&
2536
- 'supplementalIndex' in checkData) {
2537
- if (yData.supplementalIndex !== checkData.supplementalIndex) {
2538
- continue;
2539
- }
2540
- }
2541
- const checkVal = scale(checkData.values[xIndex], checkIfSecondary(data, i, xIndex, isSupplementary));
2542
- //Skip negative values
2543
- if (checkVal < zeroVal) {
2544
- continue;
2545
- }
2546
- prevBarWidths += applyMinimumDataElementSize(checkVal - zeroVal, checkData.values[xIndex], minimumSize);
2547
- }
2548
- }
2549
- const xValue = prevBarWidths + zeroVal;
2550
- const width = applyMinimumDataElementSize(scaleValue - zeroVal, yData.values[xIndex], minimumSize);
2551
- return { xValue, width };
2552
- }
2553
- function checkIfSecondary(data, yIndex, xIndex, isSupplementary = false) {
2554
- if (data.type === 'labeled') {
2555
- if (data.x[xIndex].isSecondary === true) {
2556
- return true;
2557
- }
2558
- }
2559
- return getMainOrSuppY(data, yIndex, isSupplementary).isSecondary === true;
2560
- }
2561
- function warnUnsupportedPatterns(data, supportedPatterns, chartType) {
2562
- const allYs = [
2563
- ...data.ys,
2564
- ...(hasSupplementaryData(data) ? data.supplementaryYs : []),
2565
- ];
2566
- for (const y of allYs) {
2567
- if (y.pattern &&
2568
- y.pattern !== 'solid' &&
2569
- !supportedPatterns.includes(y.pattern)) {
2570
- // eslint-disable-next-line no-console
2571
- console.warn(`Heads up! The '${y.pattern}' pattern isn't supported for ${chartType} charts. Falling back to solid.`);
2572
- }
2573
- }
2574
- }
2575
- function warnFlowData(data, chartType) {
2576
- if (data.type === 'flow') {
2577
- // eslint-disable-next-line no-console
2578
- console.warn(`Heads up! The 'flow' data type isn't supported for ${chartType} charts.`);
2579
- return false;
2580
- }
2581
- return true;
2582
- }
2583
- // hide strips out hidden y values while retaining the original indices
2584
- // for the remaining visible values
2585
- function hide(data) {
2586
- const visibleIndices = data.ys
2587
- .map((y, i) => ({ y, i }))
2588
- .filter(({ y }) => !y.hidden)
2589
- .map(({ i }) => i);
2590
- const visibleSuppIndices = hasSupplementaryData(data)
2591
- ? data.supplementaryYs
2592
- .map((y, i) => ({ y, i }))
2593
- .filter(({ y }) => !y.hidden)
2594
- .map(({ i }) => i)
2595
- : [];
2596
- return {
2597
- data: {
2598
- ...data,
2599
- ys: visibleIndices.map(i => data.ys[i]),
2600
- supplementaryYs: visibleSuppIndices.map(i => data.supplementaryYs[i]),
2601
- },
2602
- visibleIndices,
2603
- visibleSuppIndices,
2604
- };
2605
- }
2606
- function waterfallTransform(data, isWaterfall) {
2607
- const waterfallMap = new Map();
2608
- if (data.type === 'timeseries' || !isWaterfall) {
2609
- return {
2610
- data: {
2611
- type: 'labeled',
2612
- x: [],
2613
- ys: [],
2614
- },
2615
- map: waterfallMap,
2616
- };
2617
- }
2618
- const newData = {
2619
- ...data,
2620
- x: [...data.x, { label: 'Total' }],
2621
- ys: [
2622
- ...data.ys.map(y => {
2623
- const newY = {
2624
- ...y,
2625
- values: [...y.values, y.values.reduce((a, b) => a + b, 0)],
2626
- };
2627
- waterfallMap.set(newY, y);
2628
- return newY;
2629
- }),
2630
- ],
2631
- };
2632
- return {
2633
- data: newData,
2634
- map: waterfallMap,
2635
- };
2636
- }
2637
- function flowsTransform(config, data) {
2638
- const returnBuckets = [];
2639
- const maxPathLength = Math.max(...data.ys.map(y => y.steps.length));
2640
- if (maxPathLength > 0 && maxPathLength < Infinity) {
2641
- for (let i = 0; i < maxPathLength; i++) {
2642
- const flowBucket = {
2643
- totalCount: 0,
2644
- subBuckets: [],
2645
- };
2646
- for (const y of data.ys) {
2647
- if (y.values.length > i && y.steps.length > i) {
2648
- const subBucketId = y.steps[i];
2649
- const foundSubBucket = flowBucket.subBuckets.find(subBucket => subBucket.id === subBucketId);
2650
- let subBucket;
2651
- if (foundSubBucket !== undefined) {
2652
- subBucket = foundSubBucket;
2653
- subBucket.count += y.values[i];
2654
- }
2655
- else {
2656
- subBucket = {
2657
- id: subBucketId,
2658
- count: y.values[i],
2659
- connections: [],
2660
- };
2661
- flowBucket.subBuckets.push(subBucket);
2662
- }
2663
- flowBucket.totalCount += y.values[i];
2664
- //Fill in backwards connections
2665
- if (i > 0) {
2666
- const foundConnection = subBucket.connections.find(connection => connection.start === y.steps[i - 1] &&
2667
- connection.end === subBucketId &&
2668
- connection.direction === 'backward');
2669
- if (foundConnection !== undefined) {
2670
- foundConnection.count += y.values[i];
2671
- }
2672
- else {
2673
- const newConnection = {
2674
- direction: 'backward',
2675
- start: y.steps[i - 1],
2676
- end: subBucketId,
2677
- count: y.values[i],
2678
- };
2679
- subBucket.connections.push(newConnection);
2680
- }
2681
- }
2682
- //Fill in forwards connections
2683
- if (i < y.steps.length - 1 && i < y.values.length - 1) {
2684
- const foundConnection = subBucket.connections.find(connection => connection.start === subBucketId &&
2685
- connection.end === y.steps[i + 1] &&
2686
- connection.direction === 'forward');
2687
- if (foundConnection !== undefined) {
2688
- foundConnection.count += y.values[i + 1];
2689
- }
2690
- else {
2691
- const newConnection = {
2692
- direction: 'forward',
2693
- start: subBucketId,
2694
- end: y.steps[i + 1],
2695
- count: y.values[i + 1],
2696
- };
2697
- subBucket.connections.push(newConnection);
2698
- }
2699
- }
2700
- }
2701
- }
2702
- returnBuckets.push(flowBucket);
2703
- }
2704
- }
2705
- const subBucketOrderingMap = new Map();
2706
- for (let i = 0; i < config.flowConfig.subBucketsConfig.length; i++) {
2707
- subBucketOrderingMap.set(config.flowConfig.subBucketsConfig[i].bucketId, i);
2708
- }
2709
- const mapGet = (id) => {
2710
- const foundResult = subBucketOrderingMap.get(id);
2711
- if (foundResult !== undefined) {
2712
- return foundResult;
2713
- }
2714
- //If something isn't defined in the config, put it at the end
2715
- return Infinity;
2716
- };
2717
- //Ensure the data is sorted the same the way the config is, and drop empty
2718
- //bars/connections so they're neither displayed nor factored into sizing
2719
- return {
2720
- type: 'flow-processed',
2721
- x: returnBuckets.map(bucket => ({
2722
- ...bucket,
2723
- subBuckets: bucket.subBuckets
2724
- .filter(subBucket => subBucket.count !== 0)
2725
- .sort((a, b) => mapGet(a.id) - mapGet(b.id))
2726
- .map(subBucket => ({
2727
- ...subBucket,
2728
- connections: subBucket.connections
2729
- .filter(connection => connection.count !== 0)
2730
- .sort((a, b) => {
2731
- const firstSort = mapGet(a.start) - mapGet(b.start);
2732
- if (firstSort !== 0) {
2733
- return firstSort;
2734
- }
2735
- return mapGet(a.end) - mapGet(b.end);
2736
- }),
2737
- })),
2738
- })),
2739
- };
2740
- }
2741
- function getPipes(valueType) {
2742
- switch (valueType) {
2743
- case 'count': {
2744
- return { pipe: new SmallNumberPipe(), fullPipe: new NumberPipe() };
2745
- }
2746
- case 'currency':
2747
- return {
2748
- pipe: new SmallCurrencyPipe(),
2749
- fullPipe: new CurrencyPipe('en-us'),
2750
- };
2751
- case 'percentage': {
2752
- const pipe = new PercentagePipe();
2753
- return { pipe, fullPipe: pipe };
2754
- }
2755
- case 'days': {
2756
- const pipe = new DaysPipe();
2757
- return { pipe, fullPipe: pipe };
2758
- }
2759
- }
2760
- }
2761
- Chart.getPipes = getPipes;
2762
- const intervals = ['year', 'quarter', 'month', 'week', 'day'];
2763
- function formatedDate(dateFormat, date) {
2764
- if (dateFormat === 'quarter') {
2765
- const quarter = Math.ceil((date.getUTCMonth() + 1) / 3);
2766
- const year = utcFormat(getTimeIntervalFormat('year'))(date);
2767
- return `Q${quarter} ${year}`;
2768
- }
2769
- const format = getTimeIntervalFormat(dateFormat);
2770
- return utcFormat(format)(date);
2771
- }
2772
- Chart.formatedDate = formatedDate;
2773
- function getTimeIntervalFormat(interval) {
2774
- switch (interval) {
2775
- case 'day':
2776
- case 'week':
2777
- return '%m/%d/%Y';
2778
- case 'month':
2779
- case 'quarter':
2780
- return '%b %Y';
2781
- case 'year':
2782
- return '%Y';
2783
- }
2784
- }
2785
- function convertChartDataToDonutData(chartData) {
2786
- if (chartData.ys.find(y => y.values.length > 1)) {
2787
- // eslint-disable-next-line no-console
2788
- console.warn("Heads up! Pie charts don't support multiple values per series");
2789
- }
2790
- const donutData = chartData.ys.map(y => ({
2791
- label: y.label,
2792
- hidden: y.hidden,
2793
- value: y.values.length >= 1 ? y.values[0] : 0,
2794
- isSecondary: y.isSecondary,
2795
- }));
2796
- return donutData;
2797
- }
2798
- Chart.convertChartDataToDonutData = convertChartDataToDonutData;
2799
- function arcToPoint(angle, radius) {
2800
- return {
2801
- x: radius * Math.cos(angle - Math.PI / 2),
2802
- y: radius * Math.sin(angle - Math.PI / 2),
2803
- };
2804
- }
2805
- function pointToArc(x, y) {
2806
- const radius = Math.hypot(x, y);
2807
- let angle = Math.atan2(y, x) + Math.PI / 2;
2808
- //Normalize to be within range [0, 2π]
2809
- angle = (angle + 2 * Math.PI) % (2 * Math.PI);
2810
- return {
2811
- angle,
2812
- radius,
2813
- };
2814
- }
2815
- function getFullChartScaleValues(config, data, dimensions, pipeTransform, dateFormat) {
2816
- const chartDataDirection = getChartDataDirection(config);
2817
- const defaultScalingConfig = getDefaultScalingConfigByChartType(config.type, config.secondaryValueType !== undefined);
2818
- const scalingConfig = combineScalingInfo(config, defaultScalingConfig);
2819
- const nonDataAxisValues = calculateNonDataAxisValues(config, scalingConfig, config.scalingConfig?.elementScales, defaultScalingConfig.elementScales, dimensions, data);
2820
- const dataAxisValues = calculateDataAxisValues(config, scalingConfig, config.scalingConfig?.elementScales, defaultScalingConfig.elementScales, dimensions, data, pipeTransform, dateFormat);
2821
- if (nonDataAxisValues.sizingError === true ||
2822
- dataAxisValues.sizingError === true) {
2823
- return null;
2824
- }
2825
- const dataLabelStartPadding = getDataLabelSizingCount(data, config).start *
2826
- (dataAxisValues.dataLabelPadding + dataAxisValues.dataLabelTextSize);
2827
- const dataLabelEndPadding = getDataLabelSizingCount(data, config).end *
2828
- (dataAxisValues.dataLabelPadding + dataAxisValues.dataLabelTextSize);
2829
- return {
2830
- ...nonDataAxisValues,
2831
- ...dataAxisValues,
2832
- leftPadding: chartDataDirection === 'horizontal'
2833
- ? dataAxisValues.startPadding
2834
- : nonDataAxisValues.startPadding,
2835
- rightPadding: chartDataDirection === 'horizontal'
2836
- ? dataAxisValues.endPadding
2837
- : nonDataAxisValues.endPadding,
2838
- topPadding: chartDataDirection === 'horizontal'
2839
- ? nonDataAxisValues.startPadding
2840
- : dataAxisValues.startPadding,
2841
- bottomPadding: chartDataDirection === 'horizontal'
2842
- ? nonDataAxisValues.endPadding
2843
- : dataAxisValues.endPadding,
2844
- totalLeftOffset: chartDataDirection === 'horizontal'
2845
- ? dataAxisValues.startPadding +
2846
- dataAxisValues.leftBucketLabel +
2847
- dataLabelStartPadding
2848
- : nonDataAxisValues.startPadding + nonDataAxisValues.outerGap,
2849
- totalRightOffset: chartDataDirection === 'horizontal'
2850
- ? dataAxisValues.startPadding + dataLabelEndPadding
2851
- : nonDataAxisValues.endPadding + nonDataAxisValues.outerGap,
2852
- totalTopOffset: chartDataDirection === 'horizontal'
2853
- ? nonDataAxisValues.startPadding + nonDataAxisValues.outerGap
2854
- : dataAxisValues.startPadding + dataLabelStartPadding,
2855
- totalBottomOffset: chartDataDirection === 'horizontal'
2856
- ? nonDataAxisValues.endPadding + nonDataAxisValues.outerGap
2857
- : dataAxisValues.endPadding + dataLabelEndPadding,
2858
- targetTickCount: scalingConfig.targetTickCount,
2859
- sizeForData: dataAxisValues.sizeForData,
2860
- totalWidth: chartDataDirection === 'horizontal'
2861
- ? dataAxisValues.totalSize
2862
- : nonDataAxisValues.totalSize,
2863
- totalHeight: chartDataDirection === 'horizontal'
2864
- ? nonDataAxisValues.totalSize
2865
- : dataAxisValues.totalSize,
2866
- dataLabelTextSize: config.showDataLabels
2867
- ? dataAxisValues.dataLabelTextSize
2868
- : 0,
2869
- horizontalAxisLabelTextSize: chartDataDirection === 'vertical'
2870
- ? dataAxisValues.bucketLabelTextSize
2871
- : dataAxisValues.dataLabelTextSize, //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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TUFBTSxJQUFJLEdBQUc7VUFDUCxVQUFVLENBQUMsT0FBTyxDQUFDLEVBQUUsSUFBSSxVQUFVLENBQUMsT0FBTyxDQUFDLEVBQUU7O1VBRTlDLFVBQVUsQ0FBQyxPQUFPLENBQUMsRUFBRSxHQUFHLEtBQUssSUFBSSxVQUFVLENBQUMsT0FBTyxDQUFDLEVBQUU7VUFDdEQsVUFBVSxDQUFDLE9BQU8sQ0FBQyxFQUFFLEdBQUcsS0FBSyxJQUFJLFVBQVUsQ0FBQyxPQUFPLENBQUMsRUFBRTtVQUN0RCxVQUFVLENBQUMsT0FBTyxDQUFDLEVBQUUsSUFBSSxVQUFVLENBQUMsT0FBTyxDQUFDLEVBQUU7O1VBRTlDLFVBQVUsQ0FBQyxVQUFVLENBQUMsRUFBRSxJQUFJLFVBQVUsQ0FBQyxVQUFVLENBQUMsRUFBRTs7VUFFcEQsVUFBVSxDQUFDLFVBQVUsQ0FBQyxFQUFFLEdBQUcsS0FBSyxJQUFJLFVBQVUsQ0FBQyxVQUFVLENBQUMsRUFBRTtVQUM1RCxVQUFVLENBQUMsVUFBVSxDQUFDLEVBQUUsR0FBRyxLQUFLLElBQUksVUFBVSxDQUFDLFVBQVUsQ0FBQyxFQUFFO1VBQzVELFVBQVUsQ0FBQyxVQUFVLENBQUMsRUFBRSxJQUFJLFVBQVUsQ0FBQyxVQUFVLENBQUMsRUFBRTs7O0tBR3pELENBQUM7UUFFRixPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFFRCxTQUFTLEtBQUssQ0FDWixDQUFTLEVBQ1QsQ0FBUyxFQUNULENBQVMsRUFDVCxDQUFTLEVBQ1QsQ0FBUztRQUVULE1BQU0sRUFBRSxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDakIsT0FBTyxFQUFFLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDOUUsQ0FBQztJQUVELFNBQVMsVUFBVSxDQUNqQixDQUFTLEVBQ1QsSUFLQztRQUVELE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUUsR0FBRyxJQUFJLENBQUMsRUFBRSxDQUFDLEdBQUcsOEJBQThCLENBQUM7UUFDM0UsTUFBTSxFQUFFLEdBQUcsRUFBRSxDQUFDLEVBQUUsSUFBSSxDQUFDLEVBQUUsRUFBRSxDQUFDLEVBQUUsSUFBSSxDQUFDLEVBQUUsRUFBRSxDQUFDO1FBQ3RDLE1BQU0sRUFBRSxHQUFHLEVBQUUsQ0FBQyxFQUFFLElBQUksQ0FBQyxFQUFFLEdBQUcsS0FBSyxFQUFFLENBQUMsRUFBRSxJQUFJLENBQUMsRUFBRSxFQUFFLENBQUM7UUFDOUMsTUFBTSxFQUFFLEdBQUcsRUFBRSxDQUFDLEVBQUUsSUFBSSxDQUFDLEVBQUUsR0FBRyxLQUFLLEVBQUUsQ0FBQyxFQUFFLElBQUksQ0FBQyxFQUFFLEVBQUUsQ0FBQztRQUM5QyxNQUFNLEVBQUUsR0FBRyxFQUFFLENBQUMsRUFBRSxJQUFJLENBQUMsRUFBRSxFQUFFLENBQUMsRUFBRSxJQUFJLENBQUMsRUFBRSxFQUFFLENBQUM7UUFFdEMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxDQUFDO1FBQ1gsSUFBSSxFQUFFLEdBQUcsQ0FBQyxDQUFDO1FBRVgsNENBQTRDO1FBQzVDLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQztZQUM1QixNQUFNLENBQUMsR0FBRyxDQUFDLEVBQUUsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDeEIsTUFBTSxFQUFFLEdBQUcsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFFNUMsSUFBSSxFQUFFLEdBQUcsQ0FBQztnQkFBRSxFQUFFLEdBQUcsQ0FBQyxDQUFDOztnQkFDZCxFQUFFLEdBQUcsQ0FB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LENBQUM7UUFDSCxDQUFDO1FBQ0QsSUFBSSxVQUFVLEdBQUcsVUFBVSxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQ25DLFVBQVUsR0FBRyxVQUFVLENBQUMsTUFBTSxDQUFDO1lBQy9CLElBQUksU0FBUyxLQUFLLFNBQVMsRUFBRSxDQUFDO2dCQUM1QixTQUFTLEdBQUcsQ0FBQyxDQUFDO1lBQ2hCLENBQUM7UUFDSCxDQUFDO1FBQ0QsSUFBSSxVQUFVLEdBQUcsQ0FBQyxFQUFFLENBQUM7WUFDbkIsVUFBVSxHQUFHLENBQUMsQ0FBQztZQUNmLElBQUksU0FBUyxLQUFLLFNBQVMsRUFBRSxDQUFDO2dCQUM1QixTQUFTLEdBQUcsQ0FBQyxDQUFDO1lBQ2hCLENBQUM7UUFDSCxDQUFDO1FBRUQsT0FBTztZQUNMLE9BQU8sRUFBRSxVQUFVO1lBQ25CLE9BQU8sRUFBRSxVQUFVO1lBQ25CLFdBQVcsRUFBRSxRQUFRO1lBQ3JCLFlBQVksRUFBRSxTQUFTO1NBQ3hCLENBQUM7SUFDSixDQUFDO0FBQ0gsQ0FBQyxFQTExTGdCLEtBQUssS0FBTCxLQUFLLFFBMDFMckIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDdXJyZW5jeVBpcGUgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHsgc2NhbGVMaW5lYXIgfSBmcm9tICdkMy1zY2FsZSc7XG5pbXBvcnQgeyBhcmMsIGFyZWEsIGxpbmUsIHBpZSB9IGZyb20gJ2QzLXNoYXBlJztcbmltcG9ydCB7IHV0Y0Zvcm1hdCB9IGZyb20gJ2QzLXRpbWUtZm9ybWF0JztcbmltcG9ydCB7IHN1bSwgdW5pcSB9IGZyb20gJ2xvZGFzaCc7XG5pbXBvcnQgeyBEYXlzUGlwZSB9IGZyb20gJy4uLy4uL2Zvcm1hdC9waXBlcy9kYXlzLnBpcGUnO1xuaW1wb3J0IHsgTnVtYmVyUGlwZSB9IGZyb20gJy4uLy4uL2Zvcm1hdC9waXBlcy9udW1iZXIucGlwZSc7XG5pbXBvcnQgeyBQZXJjZW50YWdlUGlwZSB9IGZyb20gJy4uLy4uL2Zvcm1hdC9waXBlcy9wZXJjZW50YWdlLnBpcGUnO1xuaW1wb3J0IHsgU21hbGxDdXJyZW5jeVBpcGUgfSBmcm9tICcuLi8uLi9mb3JtYXQvcGlwZXMvc21hbGwtY3VycmVuY3kucGlwZSc7XG5pbXBvcnQgeyBTbWFsbE51bWJlclBpcGUgfSBmcm9tICcuLi8uLi9mb3JtYXQvcGlwZXMvc21hbGwtbnVtYmVyLnBpcGUnO1xuaW1wb3J0IHsgQ2FsbG91dENvbXBvbmVudCB9IGZyb20gJy4uLy4uL292ZXJsYXkvY2FsbG91dC9jYWxsb3V0LmNvbXBvbmVudCc7XG5pbXBvcnQge1xuICBDaGFydERhdGFEaXJlY3Rpb24sXG4gIENoYXJ0U2NhbGVFbGVtZW50LFxuICBDb250YWluZXJTY2FsaW5nVHlwZSxcbiAgRGVmYXVsdERvbnV0U2l6aW5nQ29uZmlnLFxuICBEZWZhdWx0U2NhbGluZ0NvbmZpZyxcbiAgRG9udXRTaXppbmdDb25maWcsXG4gIEVsZW1lbnRTY2FsaW5nQ29uZmlndXJhdGlvbixcbiAgZW1wdHlDaGFydFNjYWxlVmFsdWVzLFxuICBGdWxsQ2hhcnRTY2FsZVZhbHVlcyxcbiAgRnVsbEVsZW1lbnRTY2FsaW5nQ29uZmlnLFxuICBGdWxsU2NhbGluZ0NvbmZpZyxcbiAgZ2V0RGVmYXVsdFNjYWxpbmdDb25maWdCeUNoYXJ0VHlwZSxcbiAgTm9uRWxlbWVudFNjYWxpbmdDb25maWcsXG4gIFBhcnRpYWxFbGVtZW50U2NhbGluZ0NvbmZpZyxcbn0gZnJvbSAnLi9jaGFydC1zY2FsaW5nJztcblxuZXhwb3J0IG5hbWVzcGFjZSBDaGFydCB7XG4gIGV4cG9ydCBjb25zdCBkZWZhdWx0Q29sb3JQYWxldHRlID0gW1xuICAgIC8vQmFzZSBjb2xvcnNcbiAgICAnLS1iYWphLWJsYXN0LTUwJyxcbiAgICAnLS10ZWFsLWRpYW1vbmQtNTAnLFxuICAgICctLWZ5cmUtNTAnLFxuICAgICctLXRhbmctNTAnLFxuICAgICctLXB1cnAtNjAnLFxuICAgICctLXJvc2ktNzAnLFxuICAgIC8vU2hpZnQgbGlnaHRlciBmcm9tIGJhc2UgYnkgLTIwXG4gICAgJy0tYmFqYS1ibGFzdC0zMCcsXG4gICAgJy0tdGVhbC1kaWFtb25kLTMwJyxcbiAgICAnLS1meXJlLTMwJyxcbiAgICAnLS10YW5nLTMwJyxcbiAgICAnLS1wdXJwLTQwJyxcbiAgICAnLS1yb3NpLTUwJyxcbiAgICAvL1NoaWZ0IGRhcmtlciBmcm9tIGJhc2UgYnkgKzIwXG4gICAgJy0tYmFqYS1ibGFzdC03MCcsXG4gICAgJy0tdGVhbC1kaWFtb25kLTcwJyxcbiAgICAnLS1meXJlLTcwJyxcbiAgICAnLS10YW5nLTcwJyxcbiAgICAnLS1wdXJwLTgwJyxcbiAgICAnLS1yb3NpLTkwJyxcbiAgXTtcblxuICBleHBvcnQgZnVuY3Rpb24gY2hhcnQoXG4gICAgY29uZmlnOiBDb25maWcsXG4gICAgZGF0YTogSW5wdXREYXRhLFxuICAgIGRpbWVuc2lvbnM6IERpbWVuc2lvbnMsXG4gICk6IFJlbmRlcmVkQ2hhcnQge1xuICAgIHJldHVybiBjb25maWcudHlwZSA9PT0gJ2xpbmUnXG4gICAgICA/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=