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