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