@sbb-esta/lyne-elements-experimental-dev 0.0.0 → 4.0.0-dev.1775550888
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/README.md +55 -0
- package/autocomplete-grid/autocomplete-grid/autocomplete-grid.component.js +67 -0
- package/autocomplete-grid/autocomplete-grid-button/autocomplete-grid-button.component.js +73 -0
- package/autocomplete-grid/autocomplete-grid-button.js +4 -0
- package/autocomplete-grid/autocomplete-grid-cell/autocomplete-grid-cell.component.js +2 -0
- package/autocomplete-grid/autocomplete-grid-cell.js +4 -0
- package/autocomplete-grid/autocomplete-grid-optgroup/autocomplete-grid-optgroup.component.js +21 -0
- package/autocomplete-grid/autocomplete-grid-optgroup.js +4 -0
- package/autocomplete-grid/autocomplete-grid-option/autocomplete-grid-option.component.js +2 -0
- package/autocomplete-grid/autocomplete-grid-option.js +4 -0
- package/autocomplete-grid/autocomplete-grid-row/autocomplete-grid-row.component.js +2 -0
- package/autocomplete-grid/autocomplete-grid-row.js +4 -0
- package/autocomplete-grid/autocomplete-grid.js +4 -0
- package/autocomplete-grid-cell.component-DkD9aFKc.js +24 -0
- package/autocomplete-grid-option.component-CtATJy7n.js +37 -0
- package/autocomplete-grid-row.component-6nJv5PMj.js +27 -0
- package/autocomplete-grid.js +10 -0
- package/autocomplete-grid.pure.js +7 -0
- package/core/datetime/date-helper.js +2 -0
- package/core/datetime.js +2 -0
- package/core/styles/core.scss +13 -0
- package/core/styles/lean-theme.scss +3 -0
- package/core/styles/off-brand-theme.scss +3 -0
- package/core/styles/safety-theme.scss +3 -0
- package/core/styles/standard-theme.scss +3 -0
- package/core/styles/theme.scss +5 -0
- package/core/timetable/access-leg-helper.js +96 -0
- package/core/timetable/timetable-helper.js +10 -0
- package/core/timetable/timetable-properties.js +0 -0
- package/core/timetable.js +4 -0
- package/core.css +13 -0
- package/custom-elements.json +8629 -0
- package/date-helper-CGproP5d.js +185 -0
- package/development/autocomplete-grid/autocomplete-grid/autocomplete-grid.component.d.ts +40 -0
- package/development/autocomplete-grid/autocomplete-grid/autocomplete-grid.component.d.ts.map +1 -0
- package/development/autocomplete-grid/autocomplete-grid/autocomplete-grid.component.js +120 -0
- package/development/autocomplete-grid/autocomplete-grid-button/autocomplete-grid-button.component.d.ts +32 -0
- package/development/autocomplete-grid/autocomplete-grid-button/autocomplete-grid-button.component.d.ts.map +1 -0
- package/development/autocomplete-grid/autocomplete-grid-button/autocomplete-grid-button.component.js +103 -0
- package/development/autocomplete-grid/autocomplete-grid-button.d.ts +2 -0
- package/development/autocomplete-grid/autocomplete-grid-button.d.ts.map +1 -0
- package/development/autocomplete-grid/autocomplete-grid-button.js +10 -0
- package/development/autocomplete-grid/autocomplete-grid-cell/autocomplete-grid-cell.component.d.ts +19 -0
- package/development/autocomplete-grid/autocomplete-grid-cell/autocomplete-grid-cell.component.d.ts.map +1 -0
- package/development/autocomplete-grid/autocomplete-grid-cell/autocomplete-grid-cell.component.js +2 -0
- package/development/autocomplete-grid/autocomplete-grid-cell.d.ts +2 -0
- package/development/autocomplete-grid/autocomplete-grid-cell.d.ts.map +1 -0
- package/development/autocomplete-grid/autocomplete-grid-cell.js +10 -0
- package/development/autocomplete-grid/autocomplete-grid-optgroup/autocomplete-grid-optgroup.component.d.ts +20 -0
- package/development/autocomplete-grid/autocomplete-grid-optgroup/autocomplete-grid-optgroup.component.d.ts.map +1 -0
- package/development/autocomplete-grid/autocomplete-grid-optgroup/autocomplete-grid-optgroup.component.js +30 -0
- package/development/autocomplete-grid/autocomplete-grid-optgroup.d.ts +2 -0
- package/development/autocomplete-grid/autocomplete-grid-optgroup.d.ts.map +1 -0
- package/development/autocomplete-grid/autocomplete-grid-optgroup.js +10 -0
- package/development/autocomplete-grid/autocomplete-grid-option/autocomplete-grid-option.component.d.ts +27 -0
- package/development/autocomplete-grid/autocomplete-grid-option/autocomplete-grid-option.component.d.ts.map +1 -0
- package/development/autocomplete-grid/autocomplete-grid-option/autocomplete-grid-option.component.js +2 -0
- package/development/autocomplete-grid/autocomplete-grid-option.d.ts +2 -0
- package/development/autocomplete-grid/autocomplete-grid-option.d.ts.map +1 -0
- package/development/autocomplete-grid/autocomplete-grid-option.js +10 -0
- package/development/autocomplete-grid/autocomplete-grid-row/autocomplete-grid-row.component.d.ts +20 -0
- package/development/autocomplete-grid/autocomplete-grid-row/autocomplete-grid-row.component.d.ts.map +1 -0
- package/development/autocomplete-grid/autocomplete-grid-row/autocomplete-grid-row.component.js +2 -0
- package/development/autocomplete-grid/autocomplete-grid-row.d.ts +2 -0
- package/development/autocomplete-grid/autocomplete-grid-row.d.ts.map +1 -0
- package/development/autocomplete-grid/autocomplete-grid-row.js +10 -0
- package/development/autocomplete-grid/autocomplete-grid.d.ts +2 -0
- package/development/autocomplete-grid/autocomplete-grid.d.ts.map +1 -0
- package/development/autocomplete-grid/autocomplete-grid.js +10 -0
- package/development/autocomplete-grid-cell.component-BxkWGaX0.js +34 -0
- package/development/autocomplete-grid-option.component-5mPGswUO.js +61 -0
- package/development/autocomplete-grid-row.component-DEm6zyHZ.js +39 -0
- package/development/autocomplete-grid.d.ts +2 -0
- package/development/autocomplete-grid.d.ts.map +1 -0
- package/development/autocomplete-grid.js +19 -0
- package/development/autocomplete-grid.pure.d.ts +8 -0
- package/development/autocomplete-grid.pure.d.ts.map +1 -0
- package/development/autocomplete-grid.pure.js +7 -0
- package/development/core/datetime/date-helper.d.ts +27 -0
- package/development/core/datetime/date-helper.d.ts.map +1 -0
- package/development/core/datetime/date-helper.js +2 -0
- package/development/core/datetime.d.ts +3 -0
- package/development/core/datetime.d.ts.map +1 -0
- package/development/core/datetime.js +2 -0
- package/development/core/timetable/access-leg-helper.d.ts +26 -0
- package/development/core/timetable/access-leg-helper.d.ts.map +1 -0
- package/development/core/timetable/access-leg-helper.js +147 -0
- package/development/core/timetable/timetable-helper.d.ts +12 -0
- package/development/core/timetable/timetable-helper.d.ts.map +1 -0
- package/development/core/timetable/timetable-helper.js +19 -0
- package/development/core/timetable/timetable-properties.d.ts +308 -0
- package/development/core/timetable/timetable-properties.d.ts.map +1 -0
- package/development/core/timetable/timetable-properties.js +0 -0
- package/development/core/timetable.d.ts +5 -0
- package/development/core/timetable.d.ts.map +1 -0
- package/development/core/timetable.js +4 -0
- package/development/date-helper-qNdwgC9O.js +520 -0
- package/development/differenceInMinutes-B7_GTDq7.js +110 -0
- package/development/format-DFx4997p.js +1848 -0
- package/development/isValid-JpZ7FphI.js +178 -0
- package/development/journey-summary/journey-summary.component.d.ts +67 -0
- package/development/journey-summary/journey-summary.component.d.ts.map +1 -0
- package/development/journey-summary/journey-summary.component.js +2 -0
- package/development/journey-summary.component-BZwgD4im.js +340 -0
- package/development/journey-summary.d.ts +2 -0
- package/development/journey-summary.d.ts.map +1 -0
- package/development/journey-summary.js +9 -0
- package/development/journey-summary.pure.d.ts +3 -0
- package/development/journey-summary.pure.d.ts.map +1 -0
- package/development/journey-summary.pure.js +2 -0
- package/development/mapper-hWWm7Uke.js +11454 -0
- package/development/pearl-chain/pearl-chain.component.d.ts +44 -0
- package/development/pearl-chain/pearl-chain.component.d.ts.map +1 -0
- package/development/pearl-chain/pearl-chain.component.js +2 -0
- package/development/pearl-chain-time/pearl-chain-time.component.d.ts +49 -0
- package/development/pearl-chain-time/pearl-chain-time.component.d.ts.map +1 -0
- package/development/pearl-chain-time/pearl-chain-time.component.js +2 -0
- package/development/pearl-chain-time.component-B2_BI6E_.js +319 -0
- package/development/pearl-chain-time.d.ts +2 -0
- package/development/pearl-chain-time.d.ts.map +1 -0
- package/development/pearl-chain-time.js +9 -0
- package/development/pearl-chain-time.pure.d.ts +3 -0
- package/development/pearl-chain-time.pure.d.ts.map +1 -0
- package/development/pearl-chain-time.pure.js +2 -0
- package/development/pearl-chain-vertical/pearl-chain-vertical.component.d.ts +18 -0
- package/development/pearl-chain-vertical/pearl-chain-vertical.component.d.ts.map +1 -0
- package/development/pearl-chain-vertical/pearl-chain-vertical.component.js +2 -0
- package/development/pearl-chain-vertical-item/pearl-chain-vertical-item.component.d.ts +36 -0
- package/development/pearl-chain-vertical-item/pearl-chain-vertical-item.component.d.ts.map +1 -0
- package/development/pearl-chain-vertical-item/pearl-chain-vertical-item.component.js +2 -0
- package/development/pearl-chain-vertical-item.component-DcmH13Vb.js +133 -0
- package/development/pearl-chain-vertical-item.d.ts +2 -0
- package/development/pearl-chain-vertical-item.d.ts.map +1 -0
- package/development/pearl-chain-vertical-item.js +9 -0
- package/development/pearl-chain-vertical-item.pure.d.ts +3 -0
- package/development/pearl-chain-vertical-item.pure.d.ts.map +1 -0
- package/development/pearl-chain-vertical-item.pure.js +2 -0
- package/development/pearl-chain-vertical.component-CpcNFl-x.js +31 -0
- package/development/pearl-chain-vertical.d.ts +2 -0
- package/development/pearl-chain-vertical.d.ts.map +1 -0
- package/development/pearl-chain-vertical.js +9 -0
- package/development/pearl-chain-vertical.pure.d.ts +3 -0
- package/development/pearl-chain-vertical.pure.d.ts.map +1 -0
- package/development/pearl-chain-vertical.pure.js +2 -0
- package/development/pearl-chain.component-oQZUzsyW.js +316 -0
- package/development/pearl-chain.d.ts +2 -0
- package/development/pearl-chain.d.ts.map +1 -0
- package/development/pearl-chain.js +9 -0
- package/development/pearl-chain.pure.d.ts +3 -0
- package/development/pearl-chain.pure.d.ts.map +1 -0
- package/development/pearl-chain.pure.js +2 -0
- package/development/seat-reservation/common/mapper/icon-mapper.d.ts +106 -0
- package/development/seat-reservation/common/mapper/icon-mapper.d.ts.map +1 -0
- package/development/seat-reservation/common/mapper/icon-mapper.js +170 -0
- package/development/seat-reservation/common/mapper/mapper.d.ts +34 -0
- package/development/seat-reservation/common/mapper/mapper.d.ts.map +1 -0
- package/development/seat-reservation/common/mapper/mapper.js +2 -0
- package/development/seat-reservation/common/mapper.d.ts +3 -0
- package/development/seat-reservation/common/mapper.d.ts.map +1 -0
- package/development/seat-reservation/common/mapper.js +3 -0
- package/development/seat-reservation/common/svgs.d.ts +24 -0
- package/development/seat-reservation/common/svgs.d.ts.map +1 -0
- package/development/seat-reservation/common/svgs.js +2 -0
- package/development/seat-reservation/common/translations/i18n.d.ts +28 -0
- package/development/seat-reservation/common/translations/i18n.d.ts.map +1 -0
- package/development/seat-reservation/common/translations/i18n.js +1120 -0
- package/development/seat-reservation/common/translations.d.ts +2 -0
- package/development/seat-reservation/common/translations.d.ts.map +1 -0
- package/development/seat-reservation/common/translations.js +2 -0
- package/development/seat-reservation/common/types.d.ts +102 -0
- package/development/seat-reservation/common/types.d.ts.map +1 -0
- package/development/seat-reservation/common/types.js +0 -0
- package/development/seat-reservation/common.d.ts +6 -0
- package/development/seat-reservation/common.d.ts.map +1 -0
- package/development/seat-reservation/common.js +12 -0
- package/development/seat-reservation/seat-reservation/seat-reservation-base-element.d.ts +294 -0
- package/development/seat-reservation/seat-reservation/seat-reservation-base-element.d.ts.map +1 -0
- package/development/seat-reservation/seat-reservation/seat-reservation-base-element.js +1350 -0
- package/development/seat-reservation/seat-reservation/seat-reservation.component.d.ts +77 -0
- package/development/seat-reservation/seat-reservation/seat-reservation.component.d.ts.map +1 -0
- package/development/seat-reservation/seat-reservation/seat-reservation.component.js +2 -0
- package/development/seat-reservation/seat-reservation-area/seat-reservation-area.component.d.ts +20 -0
- package/development/seat-reservation/seat-reservation-area/seat-reservation-area.component.d.ts.map +1 -0
- package/development/seat-reservation/seat-reservation-area/seat-reservation-area.component.js +2 -0
- package/development/seat-reservation/seat-reservation-area.d.ts +2 -0
- package/development/seat-reservation/seat-reservation-area.d.ts.map +1 -0
- package/development/seat-reservation/seat-reservation-area.js +10 -0
- package/development/seat-reservation/seat-reservation-graphic/seat-reservation-assets.d.ts +9 -0
- package/development/seat-reservation/seat-reservation-graphic/seat-reservation-assets.d.ts.map +1 -0
- package/development/seat-reservation/seat-reservation-graphic/seat-reservation-assets.js +306 -0
- package/development/seat-reservation/seat-reservation-graphic/seat-reservation-graphic.component.d.ts +22 -0
- package/development/seat-reservation/seat-reservation-graphic/seat-reservation-graphic.component.d.ts.map +1 -0
- package/development/seat-reservation/seat-reservation-graphic/seat-reservation-graphic.component.js +2 -0
- package/development/seat-reservation/seat-reservation-graphic.d.ts +2 -0
- package/development/seat-reservation/seat-reservation-graphic.d.ts.map +1 -0
- package/development/seat-reservation/seat-reservation-graphic.js +10 -0
- package/development/seat-reservation/seat-reservation-navigation-coach/seat-reservation-navigation-coach.component.d.ts +56 -0
- package/development/seat-reservation/seat-reservation-navigation-coach/seat-reservation-navigation-coach.component.d.ts.map +1 -0
- package/development/seat-reservation/seat-reservation-navigation-coach/seat-reservation-navigation-coach.component.js +2 -0
- package/development/seat-reservation/seat-reservation-navigation-coach.d.ts +2 -0
- package/development/seat-reservation/seat-reservation-navigation-coach.d.ts.map +1 -0
- package/development/seat-reservation/seat-reservation-navigation-coach.js +10 -0
- package/development/seat-reservation/seat-reservation-navigation-services/seat-reservation-navigation-services.component.d.ts +25 -0
- package/development/seat-reservation/seat-reservation-navigation-services/seat-reservation-navigation-services.component.d.ts.map +1 -0
- package/development/seat-reservation/seat-reservation-navigation-services/seat-reservation-navigation-services.component.js +2 -0
- package/development/seat-reservation/seat-reservation-navigation-services.d.ts +2 -0
- package/development/seat-reservation/seat-reservation-navigation-services.d.ts.map +1 -0
- package/development/seat-reservation/seat-reservation-navigation-services.js +10 -0
- package/development/seat-reservation/seat-reservation-place-control/seat-reservation-place-control.component.d.ts +49 -0
- package/development/seat-reservation/seat-reservation-place-control/seat-reservation-place-control.component.d.ts.map +1 -0
- package/development/seat-reservation/seat-reservation-place-control/seat-reservation-place-control.component.js +2 -0
- package/development/seat-reservation/seat-reservation-place-control.d.ts +2 -0
- package/development/seat-reservation/seat-reservation-place-control.d.ts.map +1 -0
- package/development/seat-reservation/seat-reservation-place-control.js +10 -0
- package/development/seat-reservation/seat-reservation-scoped/seat-reservation-scoped.component.d.ts +16 -0
- package/development/seat-reservation/seat-reservation-scoped/seat-reservation-scoped.component.d.ts.map +1 -0
- package/development/seat-reservation/seat-reservation-scoped/seat-reservation-scoped.component.js +2 -0
- package/development/seat-reservation/seat-reservation-scoped.d.ts +2 -0
- package/development/seat-reservation/seat-reservation-scoped.d.ts.map +1 -0
- package/development/seat-reservation/seat-reservation-scoped.js +10 -0
- package/development/seat-reservation/seat-reservation.d.ts +3 -0
- package/development/seat-reservation/seat-reservation.d.ts.map +1 -0
- package/development/seat-reservation/seat-reservation.js +11 -0
- package/development/seat-reservation-area.component-DbeuTnXT.js +96 -0
- package/development/seat-reservation-graphic.component-DlrHtlia.js +129 -0
- package/development/seat-reservation-navigation-coach.component-CjoDkcVU.js +428 -0
- package/development/seat-reservation-navigation-services.component-CGel7__P.js +159 -0
- package/development/seat-reservation-place-control.component-CM9efId7.js +429 -0
- package/development/seat-reservation-scoped.component-CFA_bJ3o.js +25 -0
- package/development/seat-reservation.component-DFJVFmrI.js +510 -0
- package/development/seat-reservation.d.ts +2 -0
- package/development/seat-reservation.d.ts.map +1 -0
- package/development/seat-reservation.js +27 -0
- package/development/seat-reservation.pure.d.ts +15 -0
- package/development/seat-reservation.pure.d.ts.map +1 -0
- package/development/seat-reservation.pure.js +15 -0
- package/development/svgs-kDpBCto5.js +28 -0
- package/development/timetable-duration/timetable-duration.component.d.ts +24 -0
- package/development/timetable-duration/timetable-duration.component.d.ts.map +1 -0
- package/development/timetable-duration/timetable-duration.component.js +2 -0
- package/development/timetable-duration.component-BhFlqYbV.js +100 -0
- package/development/timetable-duration.d.ts +2 -0
- package/development/timetable-duration.d.ts.map +1 -0
- package/development/timetable-duration.js +9 -0
- package/development/timetable-duration.pure.d.ts +3 -0
- package/development/timetable-duration.pure.d.ts.map +1 -0
- package/development/timetable-duration.pure.js +2 -0
- package/development/timetable-row/timetable-row.component.d.ts +89 -0
- package/development/timetable-row/timetable-row.component.d.ts.map +1 -0
- package/development/timetable-row/timetable-row.component.js +2 -0
- package/development/timetable-row.component-Dko8laRT.js +729 -0
- package/development/timetable-row.d.ts +2 -0
- package/development/timetable-row.d.ts.map +1 -0
- package/development/timetable-row.js +9 -0
- package/development/timetable-row.pure.d.ts +3 -0
- package/development/timetable-row.pure.d.ts.map +1 -0
- package/development/timetable-row.pure.js +2 -0
- package/development/toDate-DOFAOjP-.js +150 -0
- package/differenceInMinutes-Dr9gRqtu.js +27 -0
- package/format-CM5exOsN.js +1103 -0
- package/index.d.ts +33 -0
- package/index.js +32 -0
- package/isValid-B9oVW3lA.js +36 -0
- package/journey-summary/journey-summary.component.js +2 -0
- package/journey-summary.component-DC7-qPHY.js +264 -0
- package/journey-summary.js +6 -0
- package/journey-summary.pure.js +2 -0
- package/mapper-DkiDDseD.js +11382 -0
- package/off-brand-theme.css +13 -0
- package/package.json +222 -1
- package/pearl-chain/pearl-chain.component.js +2 -0
- package/pearl-chain-time/pearl-chain-time.component.js +2 -0
- package/pearl-chain-time.component-CkKsrbgQ.js +239 -0
- package/pearl-chain-time.js +6 -0
- package/pearl-chain-time.pure.js +2 -0
- package/pearl-chain-vertical/pearl-chain-vertical.component.js +2 -0
- package/pearl-chain-vertical-item/pearl-chain-vertical-item.component.js +2 -0
- package/pearl-chain-vertical-item.component-BUqZ-3Ay.js +108 -0
- package/pearl-chain-vertical-item.js +6 -0
- package/pearl-chain-vertical-item.pure.js +2 -0
- package/pearl-chain-vertical.component-Df9CvRxo.js +21 -0
- package/pearl-chain-vertical.js +6 -0
- package/pearl-chain-vertical.pure.js +2 -0
- package/pearl-chain.component-CpISVoAu.js +194 -0
- package/pearl-chain.js +6 -0
- package/pearl-chain.pure.js +2 -0
- package/safety-theme.css +13 -0
- package/seat-reservation/common/mapper/icon-mapper.js +72 -0
- package/seat-reservation/common/mapper/mapper.js +2 -0
- package/seat-reservation/common/mapper.js +3 -0
- package/seat-reservation/common/svgs.js +2 -0
- package/seat-reservation/common/translations/i18n.js +1085 -0
- package/seat-reservation/common/translations.js +2 -0
- package/seat-reservation/common/types.js +0 -0
- package/seat-reservation/common.js +9 -0
- package/seat-reservation/seat-reservation/seat-reservation-base-element.js +861 -0
- package/seat-reservation/seat-reservation/seat-reservation.component.js +2 -0
- package/seat-reservation/seat-reservation-area/seat-reservation-area.component.js +2 -0
- package/seat-reservation/seat-reservation-area.js +4 -0
- package/seat-reservation/seat-reservation-graphic/seat-reservation-assets.js +291 -0
- package/seat-reservation/seat-reservation-graphic/seat-reservation-graphic.component.js +2 -0
- package/seat-reservation/seat-reservation-graphic.js +4 -0
- package/seat-reservation/seat-reservation-navigation-coach/seat-reservation-navigation-coach.component.js +2 -0
- package/seat-reservation/seat-reservation-navigation-coach.js +4 -0
- package/seat-reservation/seat-reservation-navigation-services/seat-reservation-navigation-services.component.js +2 -0
- package/seat-reservation/seat-reservation-navigation-services.js +4 -0
- package/seat-reservation/seat-reservation-place-control/seat-reservation-place-control.component.js +2 -0
- package/seat-reservation/seat-reservation-place-control.js +4 -0
- package/seat-reservation/seat-reservation-scoped/seat-reservation-scoped.component.js +2 -0
- package/seat-reservation/seat-reservation-scoped.js +4 -0
- package/seat-reservation/seat-reservation.js +5 -0
- package/seat-reservation-area.component-CtYawDjE.js +75 -0
- package/seat-reservation-graphic.component-Cm_pVxaB.js +102 -0
- package/seat-reservation-navigation-coach.component-sug9IBTH.js +333 -0
- package/seat-reservation-navigation-services.component-C9dDYD_M.js +127 -0
- package/seat-reservation-place-control.component-CE7d9M2b.js +322 -0
- package/seat-reservation-scoped.component-DVyP2JGE.js +17 -0
- package/seat-reservation.component-DajC6fqU.js +367 -0
- package/seat-reservation.js +17 -0
- package/seat-reservation.pure.js +15 -0
- package/standard-theme.css +13 -0
- package/svgs-D5DhLHxC.js +26 -0
- package/timetable-duration/timetable-duration.component.js +2 -0
- package/timetable-duration.component-BnJA8wSb.js +65 -0
- package/timetable-duration.js +6 -0
- package/timetable-duration.pure.js +2 -0
- package/timetable-row/timetable-row.component.js +2 -0
- package/timetable-row.component-DbzBCpKR.js +559 -0
- package/timetable-row.js +6 -0
- package/timetable-row.pure.js +2 -0
- package/toDate-p-Tpkb7t.js +16 -0
|
@@ -0,0 +1,1350 @@
|
|
|
1
|
+
import { __esDecorate, __runInitializers } from "tslib";
|
|
2
|
+
import { SbbElement } from "@sbb-esta/lyne-elements/core/base-elements.js";
|
|
3
|
+
import { forceType } from "@sbb-esta/lyne-elements/core/decorators.js";
|
|
4
|
+
import { isServer } from "lit";
|
|
5
|
+
import { isArrowKeyOrPageKeysPressed } from "@sbb-esta/lyne-elements/core/a11y.js";
|
|
6
|
+
import { eventOptions, property, state } from "lit/decorators.js";
|
|
7
|
+
import { mapCoachInfosToCoachSelection, mapIconToSvg, mapPlaceAndCoachToSeatReservationPlaceSelection, mapPlaceInfosToPlaceSelection } from "../common/mapper.js";
|
|
8
|
+
//#region src/elements-experimental/seat-reservation/seat-reservation/seat-reservation-base-element.ts
|
|
9
|
+
var ScrollDirection;
|
|
10
|
+
(function(ScrollDirection) {
|
|
11
|
+
ScrollDirection["right"] = "right";
|
|
12
|
+
ScrollDirection["left"] = "left";
|
|
13
|
+
})(ScrollDirection || (ScrollDirection = {}));
|
|
14
|
+
var MAX_SERVICE_PROPERTIES = 3;
|
|
15
|
+
var ALLOWED_SERVICE_ICONS = [
|
|
16
|
+
"sa-vo",
|
|
17
|
+
"sa-rs",
|
|
18
|
+
"sa-abteilkinderwagen",
|
|
19
|
+
"sa-wr",
|
|
20
|
+
"sa-fa",
|
|
21
|
+
"sa-bz",
|
|
22
|
+
"sa-rz"
|
|
23
|
+
];
|
|
24
|
+
var SeatReservationBaseElement = (() => {
|
|
25
|
+
let _classSuper = SbbElement;
|
|
26
|
+
let _instanceExtraInitializers = [];
|
|
27
|
+
let _seatReservations_decorators;
|
|
28
|
+
let _seatReservations_initializers = [];
|
|
29
|
+
let _seatReservations_extraInitializers = [];
|
|
30
|
+
let _travelDirection_decorators;
|
|
31
|
+
let _travelDirection_initializers = [];
|
|
32
|
+
let _travelDirection_extraInitializers = [];
|
|
33
|
+
let _hasNavigation_decorators;
|
|
34
|
+
let _hasNavigation_initializers = [];
|
|
35
|
+
let _hasNavigation_extraInitializers = [];
|
|
36
|
+
let _alignVertical_decorators;
|
|
37
|
+
let _alignVertical_initializers = [];
|
|
38
|
+
let _alignVertical_extraInitializers = [];
|
|
39
|
+
let _baseGridSize_decorators;
|
|
40
|
+
let _baseGridSize_initializers = [];
|
|
41
|
+
let _baseGridSize_extraInitializers = [];
|
|
42
|
+
let _height_decorators;
|
|
43
|
+
let _height_initializers = [];
|
|
44
|
+
let _height_extraInitializers = [];
|
|
45
|
+
let _maxSeatReservations_decorators;
|
|
46
|
+
let _maxSeatReservations_initializers = [];
|
|
47
|
+
let _maxSeatReservations_extraInitializers = [];
|
|
48
|
+
let _maxBicycleReservations_decorators;
|
|
49
|
+
let _maxBicycleReservations_initializers = [];
|
|
50
|
+
let _maxBicycleReservations_extraInitializers = [];
|
|
51
|
+
let _preventPlaceClick_decorators;
|
|
52
|
+
let _preventPlaceClick_initializers = [];
|
|
53
|
+
let _preventPlaceClick_extraInitializers = [];
|
|
54
|
+
let _preselectCoachIndex_decorators;
|
|
55
|
+
let _preselectCoachIndex_initializers = [];
|
|
56
|
+
let _preselectCoachIndex_extraInitializers = [];
|
|
57
|
+
let _showTitleInfo_decorators;
|
|
58
|
+
let _showTitleInfo_initializers = [];
|
|
59
|
+
let _showTitleInfo_extraInitializers = [];
|
|
60
|
+
let _selectedCoachIndex_decorators;
|
|
61
|
+
let _selectedCoachIndex_initializers = [];
|
|
62
|
+
let _selectedCoachIndex_extraInitializers = [];
|
|
63
|
+
let _focusedCoachIndex_decorators;
|
|
64
|
+
let _focusedCoachIndex_initializers = [];
|
|
65
|
+
let _focusedCoachIndex_extraInitializers = [];
|
|
66
|
+
let _hoveredCoachIndex_decorators;
|
|
67
|
+
let _hoveredCoachIndex_initializers = [];
|
|
68
|
+
let _hoveredCoachIndex_extraInitializers = [];
|
|
69
|
+
let _coachAreaScrollend_decorators;
|
|
70
|
+
return class SeatReservationBaseElement extends _classSuper {
|
|
71
|
+
static {
|
|
72
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
|
|
73
|
+
_seatReservations_decorators = [property({
|
|
74
|
+
attribute: "seat-reservations",
|
|
75
|
+
type: Array
|
|
76
|
+
})];
|
|
77
|
+
_travelDirection_decorators = [property({
|
|
78
|
+
attribute: "travel-direction",
|
|
79
|
+
type: String
|
|
80
|
+
})];
|
|
81
|
+
_hasNavigation_decorators = [forceType(), property({
|
|
82
|
+
attribute: "has-navigation",
|
|
83
|
+
type: Boolean
|
|
84
|
+
})];
|
|
85
|
+
_alignVertical_decorators = [forceType(), property({
|
|
86
|
+
attribute: "align-vertical",
|
|
87
|
+
type: Boolean,
|
|
88
|
+
reflect: true,
|
|
89
|
+
useDefault: true
|
|
90
|
+
})];
|
|
91
|
+
_baseGridSize_decorators = [forceType(), property({
|
|
92
|
+
attribute: "base-grid-size",
|
|
93
|
+
type: Number
|
|
94
|
+
})];
|
|
95
|
+
_height_decorators = [forceType(), property({
|
|
96
|
+
attribute: "height",
|
|
97
|
+
type: Number
|
|
98
|
+
})];
|
|
99
|
+
_maxSeatReservations_decorators = [forceType(), property({
|
|
100
|
+
attribute: "max-seat-reservations",
|
|
101
|
+
type: Number
|
|
102
|
+
})];
|
|
103
|
+
_maxBicycleReservations_decorators = [forceType(), property({
|
|
104
|
+
attribute: "max-bicycle-reservations",
|
|
105
|
+
type: Number
|
|
106
|
+
})];
|
|
107
|
+
_preventPlaceClick_decorators = [forceType(), property({
|
|
108
|
+
attribute: "prevent-place-click",
|
|
109
|
+
type: Boolean
|
|
110
|
+
})];
|
|
111
|
+
_preselectCoachIndex_decorators = [forceType(), property({
|
|
112
|
+
attribute: "preselect-coach-index",
|
|
113
|
+
type: Number
|
|
114
|
+
})];
|
|
115
|
+
_showTitleInfo_decorators = [forceType(), property({
|
|
116
|
+
attribute: "show-title-info",
|
|
117
|
+
type: Boolean
|
|
118
|
+
})];
|
|
119
|
+
_selectedCoachIndex_decorators = [state()];
|
|
120
|
+
_focusedCoachIndex_decorators = [state()];
|
|
121
|
+
_hoveredCoachIndex_decorators = [state()];
|
|
122
|
+
_coachAreaScrollend_decorators = [eventOptions({ passive: true })];
|
|
123
|
+
__esDecorate(this, null, _seatReservations_decorators, {
|
|
124
|
+
kind: "accessor",
|
|
125
|
+
name: "seatReservations",
|
|
126
|
+
static: false,
|
|
127
|
+
private: false,
|
|
128
|
+
access: {
|
|
129
|
+
has: (obj) => "seatReservations" in obj,
|
|
130
|
+
get: (obj) => obj.seatReservations,
|
|
131
|
+
set: (obj, value) => {
|
|
132
|
+
obj.seatReservations = value;
|
|
133
|
+
}
|
|
134
|
+
},
|
|
135
|
+
metadata: _metadata
|
|
136
|
+
}, _seatReservations_initializers, _seatReservations_extraInitializers);
|
|
137
|
+
__esDecorate(this, null, _travelDirection_decorators, {
|
|
138
|
+
kind: "accessor",
|
|
139
|
+
name: "travelDirection",
|
|
140
|
+
static: false,
|
|
141
|
+
private: false,
|
|
142
|
+
access: {
|
|
143
|
+
has: (obj) => "travelDirection" in obj,
|
|
144
|
+
get: (obj) => obj.travelDirection,
|
|
145
|
+
set: (obj, value) => {
|
|
146
|
+
obj.travelDirection = value;
|
|
147
|
+
}
|
|
148
|
+
},
|
|
149
|
+
metadata: _metadata
|
|
150
|
+
}, _travelDirection_initializers, _travelDirection_extraInitializers);
|
|
151
|
+
__esDecorate(this, null, _hasNavigation_decorators, {
|
|
152
|
+
kind: "accessor",
|
|
153
|
+
name: "hasNavigation",
|
|
154
|
+
static: false,
|
|
155
|
+
private: false,
|
|
156
|
+
access: {
|
|
157
|
+
has: (obj) => "hasNavigation" in obj,
|
|
158
|
+
get: (obj) => obj.hasNavigation,
|
|
159
|
+
set: (obj, value) => {
|
|
160
|
+
obj.hasNavigation = value;
|
|
161
|
+
}
|
|
162
|
+
},
|
|
163
|
+
metadata: _metadata
|
|
164
|
+
}, _hasNavigation_initializers, _hasNavigation_extraInitializers);
|
|
165
|
+
__esDecorate(this, null, _alignVertical_decorators, {
|
|
166
|
+
kind: "accessor",
|
|
167
|
+
name: "alignVertical",
|
|
168
|
+
static: false,
|
|
169
|
+
private: false,
|
|
170
|
+
access: {
|
|
171
|
+
has: (obj) => "alignVertical" in obj,
|
|
172
|
+
get: (obj) => obj.alignVertical,
|
|
173
|
+
set: (obj, value) => {
|
|
174
|
+
obj.alignVertical = value;
|
|
175
|
+
}
|
|
176
|
+
},
|
|
177
|
+
metadata: _metadata
|
|
178
|
+
}, _alignVertical_initializers, _alignVertical_extraInitializers);
|
|
179
|
+
__esDecorate(this, null, _baseGridSize_decorators, {
|
|
180
|
+
kind: "accessor",
|
|
181
|
+
name: "baseGridSize",
|
|
182
|
+
static: false,
|
|
183
|
+
private: false,
|
|
184
|
+
access: {
|
|
185
|
+
has: (obj) => "baseGridSize" in obj,
|
|
186
|
+
get: (obj) => obj.baseGridSize,
|
|
187
|
+
set: (obj, value) => {
|
|
188
|
+
obj.baseGridSize = value;
|
|
189
|
+
}
|
|
190
|
+
},
|
|
191
|
+
metadata: _metadata
|
|
192
|
+
}, _baseGridSize_initializers, _baseGridSize_extraInitializers);
|
|
193
|
+
__esDecorate(this, null, _height_decorators, {
|
|
194
|
+
kind: "accessor",
|
|
195
|
+
name: "height",
|
|
196
|
+
static: false,
|
|
197
|
+
private: false,
|
|
198
|
+
access: {
|
|
199
|
+
has: (obj) => "height" in obj,
|
|
200
|
+
get: (obj) => obj.height,
|
|
201
|
+
set: (obj, value) => {
|
|
202
|
+
obj.height = value;
|
|
203
|
+
}
|
|
204
|
+
},
|
|
205
|
+
metadata: _metadata
|
|
206
|
+
}, _height_initializers, _height_extraInitializers);
|
|
207
|
+
__esDecorate(this, null, _maxSeatReservations_decorators, {
|
|
208
|
+
kind: "accessor",
|
|
209
|
+
name: "maxSeatReservations",
|
|
210
|
+
static: false,
|
|
211
|
+
private: false,
|
|
212
|
+
access: {
|
|
213
|
+
has: (obj) => "maxSeatReservations" in obj,
|
|
214
|
+
get: (obj) => obj.maxSeatReservations,
|
|
215
|
+
set: (obj, value) => {
|
|
216
|
+
obj.maxSeatReservations = value;
|
|
217
|
+
}
|
|
218
|
+
},
|
|
219
|
+
metadata: _metadata
|
|
220
|
+
}, _maxSeatReservations_initializers, _maxSeatReservations_extraInitializers);
|
|
221
|
+
__esDecorate(this, null, _maxBicycleReservations_decorators, {
|
|
222
|
+
kind: "accessor",
|
|
223
|
+
name: "maxBicycleReservations",
|
|
224
|
+
static: false,
|
|
225
|
+
private: false,
|
|
226
|
+
access: {
|
|
227
|
+
has: (obj) => "maxBicycleReservations" in obj,
|
|
228
|
+
get: (obj) => obj.maxBicycleReservations,
|
|
229
|
+
set: (obj, value) => {
|
|
230
|
+
obj.maxBicycleReservations = value;
|
|
231
|
+
}
|
|
232
|
+
},
|
|
233
|
+
metadata: _metadata
|
|
234
|
+
}, _maxBicycleReservations_initializers, _maxBicycleReservations_extraInitializers);
|
|
235
|
+
__esDecorate(this, null, _preventPlaceClick_decorators, {
|
|
236
|
+
kind: "accessor",
|
|
237
|
+
name: "preventPlaceClick",
|
|
238
|
+
static: false,
|
|
239
|
+
private: false,
|
|
240
|
+
access: {
|
|
241
|
+
has: (obj) => "preventPlaceClick" in obj,
|
|
242
|
+
get: (obj) => obj.preventPlaceClick,
|
|
243
|
+
set: (obj, value) => {
|
|
244
|
+
obj.preventPlaceClick = value;
|
|
245
|
+
}
|
|
246
|
+
},
|
|
247
|
+
metadata: _metadata
|
|
248
|
+
}, _preventPlaceClick_initializers, _preventPlaceClick_extraInitializers);
|
|
249
|
+
__esDecorate(this, null, _preselectCoachIndex_decorators, {
|
|
250
|
+
kind: "accessor",
|
|
251
|
+
name: "preselectCoachIndex",
|
|
252
|
+
static: false,
|
|
253
|
+
private: false,
|
|
254
|
+
access: {
|
|
255
|
+
has: (obj) => "preselectCoachIndex" in obj,
|
|
256
|
+
get: (obj) => obj.preselectCoachIndex,
|
|
257
|
+
set: (obj, value) => {
|
|
258
|
+
obj.preselectCoachIndex = value;
|
|
259
|
+
}
|
|
260
|
+
},
|
|
261
|
+
metadata: _metadata
|
|
262
|
+
}, _preselectCoachIndex_initializers, _preselectCoachIndex_extraInitializers);
|
|
263
|
+
__esDecorate(this, null, _showTitleInfo_decorators, {
|
|
264
|
+
kind: "accessor",
|
|
265
|
+
name: "showTitleInfo",
|
|
266
|
+
static: false,
|
|
267
|
+
private: false,
|
|
268
|
+
access: {
|
|
269
|
+
has: (obj) => "showTitleInfo" in obj,
|
|
270
|
+
get: (obj) => obj.showTitleInfo,
|
|
271
|
+
set: (obj, value) => {
|
|
272
|
+
obj.showTitleInfo = value;
|
|
273
|
+
}
|
|
274
|
+
},
|
|
275
|
+
metadata: _metadata
|
|
276
|
+
}, _showTitleInfo_initializers, _showTitleInfo_extraInitializers);
|
|
277
|
+
__esDecorate(this, null, _selectedCoachIndex_decorators, {
|
|
278
|
+
kind: "accessor",
|
|
279
|
+
name: "selectedCoachIndex",
|
|
280
|
+
static: false,
|
|
281
|
+
private: false,
|
|
282
|
+
access: {
|
|
283
|
+
has: (obj) => "selectedCoachIndex" in obj,
|
|
284
|
+
get: (obj) => obj.selectedCoachIndex,
|
|
285
|
+
set: (obj, value) => {
|
|
286
|
+
obj.selectedCoachIndex = value;
|
|
287
|
+
}
|
|
288
|
+
},
|
|
289
|
+
metadata: _metadata
|
|
290
|
+
}, _selectedCoachIndex_initializers, _selectedCoachIndex_extraInitializers);
|
|
291
|
+
__esDecorate(this, null, _focusedCoachIndex_decorators, {
|
|
292
|
+
kind: "accessor",
|
|
293
|
+
name: "focusedCoachIndex",
|
|
294
|
+
static: false,
|
|
295
|
+
private: false,
|
|
296
|
+
access: {
|
|
297
|
+
has: (obj) => "focusedCoachIndex" in obj,
|
|
298
|
+
get: (obj) => obj.focusedCoachIndex,
|
|
299
|
+
set: (obj, value) => {
|
|
300
|
+
obj.focusedCoachIndex = value;
|
|
301
|
+
}
|
|
302
|
+
},
|
|
303
|
+
metadata: _metadata
|
|
304
|
+
}, _focusedCoachIndex_initializers, _focusedCoachIndex_extraInitializers);
|
|
305
|
+
__esDecorate(this, null, _hoveredCoachIndex_decorators, {
|
|
306
|
+
kind: "accessor",
|
|
307
|
+
name: "hoveredCoachIndex",
|
|
308
|
+
static: false,
|
|
309
|
+
private: false,
|
|
310
|
+
access: {
|
|
311
|
+
has: (obj) => "hoveredCoachIndex" in obj,
|
|
312
|
+
get: (obj) => obj.hoveredCoachIndex,
|
|
313
|
+
set: (obj, value) => {
|
|
314
|
+
obj.hoveredCoachIndex = value;
|
|
315
|
+
}
|
|
316
|
+
},
|
|
317
|
+
metadata: _metadata
|
|
318
|
+
}, _hoveredCoachIndex_initializers, _hoveredCoachIndex_extraInitializers);
|
|
319
|
+
__esDecorate(this, null, _coachAreaScrollend_decorators, {
|
|
320
|
+
kind: "method",
|
|
321
|
+
name: "coachAreaScrollend",
|
|
322
|
+
static: false,
|
|
323
|
+
private: false,
|
|
324
|
+
access: {
|
|
325
|
+
has: (obj) => "coachAreaScrollend" in obj,
|
|
326
|
+
get: (obj) => obj.coachAreaScrollend
|
|
327
|
+
},
|
|
328
|
+
metadata: _metadata
|
|
329
|
+
}, null, _instanceExtraInitializers);
|
|
330
|
+
if (_metadata) Object.defineProperty(this, Symbol.metadata, {
|
|
331
|
+
enumerable: true,
|
|
332
|
+
configurable: true,
|
|
333
|
+
writable: true,
|
|
334
|
+
value: _metadata
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
static {
|
|
338
|
+
this.events = {
|
|
339
|
+
selectedplaces: "selectedplaces",
|
|
340
|
+
selectedcoach: "selectedcoach"
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
#seatReservations_accessor_storage;
|
|
344
|
+
/** The seat reservations array contains all coaches and places */
|
|
345
|
+
get seatReservations() {
|
|
346
|
+
return this.#seatReservations_accessor_storage;
|
|
347
|
+
}
|
|
348
|
+
set seatReservations(value) {
|
|
349
|
+
this.#seatReservations_accessor_storage = value;
|
|
350
|
+
}
|
|
351
|
+
#travelDirection_accessor_storage;
|
|
352
|
+
/** Displays an arrow showing what direction does train drive*/
|
|
353
|
+
get travelDirection() {
|
|
354
|
+
return this.#travelDirection_accessor_storage;
|
|
355
|
+
}
|
|
356
|
+
set travelDirection(value) {
|
|
357
|
+
this.#travelDirection_accessor_storage = value;
|
|
358
|
+
}
|
|
359
|
+
#hasNavigation_accessor_storage;
|
|
360
|
+
/** The seat reservation navigation can be toggled by this property */
|
|
361
|
+
get hasNavigation() {
|
|
362
|
+
return this.#hasNavigation_accessor_storage;
|
|
363
|
+
}
|
|
364
|
+
set hasNavigation(value) {
|
|
365
|
+
this.#hasNavigation_accessor_storage = value;
|
|
366
|
+
}
|
|
367
|
+
#alignVertical_accessor_storage;
|
|
368
|
+
/** The seat reservation area is aligned vertically */
|
|
369
|
+
get alignVertical() {
|
|
370
|
+
return this.#alignVertical_accessor_storage;
|
|
371
|
+
}
|
|
372
|
+
set alignVertical(value) {
|
|
373
|
+
this.#alignVertical_accessor_storage = value;
|
|
374
|
+
}
|
|
375
|
+
#baseGridSize_accessor_storage;
|
|
376
|
+
/** The seat reservation area's base grid size */
|
|
377
|
+
get baseGridSize() {
|
|
378
|
+
return this.#baseGridSize_accessor_storage;
|
|
379
|
+
}
|
|
380
|
+
set baseGridSize(value) {
|
|
381
|
+
this.#baseGridSize_accessor_storage = value;
|
|
382
|
+
}
|
|
383
|
+
#height_accessor_storage;
|
|
384
|
+
/** The seat reservation area's width */
|
|
385
|
+
get height() {
|
|
386
|
+
return this.#height_accessor_storage;
|
|
387
|
+
}
|
|
388
|
+
set height(value) {
|
|
389
|
+
this.#height_accessor_storage = value;
|
|
390
|
+
}
|
|
391
|
+
#maxSeatReservations_accessor_storage;
|
|
392
|
+
/** Maximal number of possible clickable seats */
|
|
393
|
+
get maxSeatReservations() {
|
|
394
|
+
return this.#maxSeatReservations_accessor_storage;
|
|
395
|
+
}
|
|
396
|
+
set maxSeatReservations(value) {
|
|
397
|
+
this.#maxSeatReservations_accessor_storage = value;
|
|
398
|
+
}
|
|
399
|
+
#maxBicycleReservations_accessor_storage;
|
|
400
|
+
/** Maximal number of possible clickable bicycle places */
|
|
401
|
+
get maxBicycleReservations() {
|
|
402
|
+
return this.#maxBicycleReservations_accessor_storage;
|
|
403
|
+
}
|
|
404
|
+
set maxBicycleReservations(value) {
|
|
405
|
+
this.#maxBicycleReservations_accessor_storage = value;
|
|
406
|
+
}
|
|
407
|
+
#preventPlaceClick_accessor_storage;
|
|
408
|
+
/** Any click functionality is prevented */
|
|
409
|
+
get preventPlaceClick() {
|
|
410
|
+
return this.#preventPlaceClick_accessor_storage;
|
|
411
|
+
}
|
|
412
|
+
set preventPlaceClick(value) {
|
|
413
|
+
this.#preventPlaceClick_accessor_storage = value;
|
|
414
|
+
}
|
|
415
|
+
#preselectCoachIndex_accessor_storage;
|
|
416
|
+
get preselectCoachIndex() {
|
|
417
|
+
return this.#preselectCoachIndex_accessor_storage;
|
|
418
|
+
}
|
|
419
|
+
set preselectCoachIndex(value) {
|
|
420
|
+
this.#preselectCoachIndex_accessor_storage = value;
|
|
421
|
+
}
|
|
422
|
+
#showTitleInfo_accessor_storage;
|
|
423
|
+
/** The seat reservation title information at place-controls, navigation-coaches and navigation-services can be toggled by this property */
|
|
424
|
+
get showTitleInfo() {
|
|
425
|
+
return this.#showTitleInfo_accessor_storage;
|
|
426
|
+
}
|
|
427
|
+
set showTitleInfo(value) {
|
|
428
|
+
this.#showTitleInfo_accessor_storage = value;
|
|
429
|
+
}
|
|
430
|
+
#selectedCoachIndex_accessor_storage;
|
|
431
|
+
get selectedCoachIndex() {
|
|
432
|
+
return this.#selectedCoachIndex_accessor_storage;
|
|
433
|
+
}
|
|
434
|
+
set selectedCoachIndex(value) {
|
|
435
|
+
this.#selectedCoachIndex_accessor_storage = value;
|
|
436
|
+
}
|
|
437
|
+
#focusedCoachIndex_accessor_storage;
|
|
438
|
+
get focusedCoachIndex() {
|
|
439
|
+
return this.#focusedCoachIndex_accessor_storage;
|
|
440
|
+
}
|
|
441
|
+
set focusedCoachIndex(value) {
|
|
442
|
+
this.#focusedCoachIndex_accessor_storage = value;
|
|
443
|
+
}
|
|
444
|
+
#hoveredCoachIndex_accessor_storage;
|
|
445
|
+
get hoveredCoachIndex() {
|
|
446
|
+
return this.#hoveredCoachIndex_accessor_storage;
|
|
447
|
+
}
|
|
448
|
+
set hoveredCoachIndex(value) {
|
|
449
|
+
this.#hoveredCoachIndex_accessor_storage = value;
|
|
450
|
+
}
|
|
451
|
+
constructor() {
|
|
452
|
+
super();
|
|
453
|
+
this.#seatReservations_accessor_storage = (__runInitializers(this, _instanceExtraInitializers), __runInitializers(this, _seatReservations_initializers, null));
|
|
454
|
+
this.#travelDirection_accessor_storage = (__runInitializers(this, _seatReservations_extraInitializers), __runInitializers(this, _travelDirection_initializers, "NONE"));
|
|
455
|
+
this.#hasNavigation_accessor_storage = (__runInitializers(this, _travelDirection_extraInitializers), __runInitializers(this, _hasNavigation_initializers, true));
|
|
456
|
+
this.#alignVertical_accessor_storage = (__runInitializers(this, _hasNavigation_extraInitializers), __runInitializers(this, _alignVertical_initializers, false));
|
|
457
|
+
this.#baseGridSize_accessor_storage = (__runInitializers(this, _alignVertical_extraInitializers), __runInitializers(this, _baseGridSize_initializers, 16));
|
|
458
|
+
this.#height_accessor_storage = (__runInitializers(this, _baseGridSize_extraInitializers), __runInitializers(this, _height_initializers, null));
|
|
459
|
+
this.#maxSeatReservations_accessor_storage = (__runInitializers(this, _height_extraInitializers), __runInitializers(this, _maxSeatReservations_initializers, -1));
|
|
460
|
+
this.#maxBicycleReservations_accessor_storage = (__runInitializers(this, _maxSeatReservations_extraInitializers), __runInitializers(this, _maxBicycleReservations_initializers, -1));
|
|
461
|
+
this.#preventPlaceClick_accessor_storage = (__runInitializers(this, _maxBicycleReservations_extraInitializers), __runInitializers(this, _preventPlaceClick_initializers, false));
|
|
462
|
+
this.#preselectCoachIndex_accessor_storage = (__runInitializers(this, _preventPlaceClick_extraInitializers), __runInitializers(this, _preselectCoachIndex_initializers, -1));
|
|
463
|
+
this.#showTitleInfo_accessor_storage = (__runInitializers(this, _preselectCoachIndex_extraInitializers), __runInitializers(this, _showTitleInfo_initializers, false));
|
|
464
|
+
this.#selectedCoachIndex_accessor_storage = (__runInitializers(this, _showTitleInfo_extraInitializers), __runInitializers(this, _selectedCoachIndex_initializers, -1));
|
|
465
|
+
this.#focusedCoachIndex_accessor_storage = (__runInitializers(this, _selectedCoachIndex_extraInitializers), __runInitializers(this, _focusedCoachIndex_initializers, -1));
|
|
466
|
+
this.#hoveredCoachIndex_accessor_storage = (__runInitializers(this, _focusedCoachIndex_extraInitializers), __runInitializers(this, _hoveredCoachIndex_initializers, -1));
|
|
467
|
+
this.coachBorderPadding = (__runInitializers(this, _hoveredCoachIndex_extraInitializers), 6);
|
|
468
|
+
this.gapBetweenCoaches = 4;
|
|
469
|
+
this.coachBorderOffset = this.coachBorderPadding / this.baseGridSize;
|
|
470
|
+
this.gapBetweenCoachDecks = 48;
|
|
471
|
+
this.coachNavButtonDim = 0;
|
|
472
|
+
this.globalAreaIconDim = {
|
|
473
|
+
w: 2,
|
|
474
|
+
h: 2
|
|
475
|
+
};
|
|
476
|
+
this.globalAreaIconPadding = .8;
|
|
477
|
+
this.coachItemDetailsElements = [];
|
|
478
|
+
this.currScrollDirection = ScrollDirection.right;
|
|
479
|
+
this.maxCalcCoachesWidth = 0;
|
|
480
|
+
this.scrollCoachesAreaWidth = 0;
|
|
481
|
+
this.scrollNavigationAreaDim = 0;
|
|
482
|
+
this.triggerCoachPositionsCollection = [];
|
|
483
|
+
this.navigationScrollArea = null;
|
|
484
|
+
this.coachScrollArea = null;
|
|
485
|
+
this.currSelectedPlace = null;
|
|
486
|
+
this.currSelectedPlaceElementId = null;
|
|
487
|
+
this.currSelectedCoachIndex = -1;
|
|
488
|
+
this.currSelectedDeckIndex = 0;
|
|
489
|
+
this.preventCoachScrollByPlaceClick = false;
|
|
490
|
+
this.selectedSeatReservationPlaces = {
|
|
491
|
+
seats: [],
|
|
492
|
+
bicycles: []
|
|
493
|
+
};
|
|
494
|
+
this.seatReservationWithoutNavigationHasFocus = false;
|
|
495
|
+
this.isCoachGridFocusable = false;
|
|
496
|
+
this.isAutoScrolling = false;
|
|
497
|
+
this.isKeyboardNavigation = false;
|
|
498
|
+
this.hasMultipleDecks = false;
|
|
499
|
+
this.hasSeatReservationNativeFocus = false;
|
|
500
|
+
this.keyboardNavigationEvents = {
|
|
501
|
+
ArrowLeft: "ArrowLeft",
|
|
502
|
+
ArrowRight: "ArrowRight",
|
|
503
|
+
ArrowUp: "ArrowUp",
|
|
504
|
+
ArrowDown: "ArrowDown",
|
|
505
|
+
Tab: "Tab",
|
|
506
|
+
Enter: "Enter"
|
|
507
|
+
};
|
|
508
|
+
this.notAreaElements = [
|
|
509
|
+
"DRIVER_AREA",
|
|
510
|
+
"DRIVER_AREA_NO_VERTICAL_WALL",
|
|
511
|
+
"COACH_PASSAGE",
|
|
512
|
+
"COACH_WALL_NO_PASSAGE",
|
|
513
|
+
"COMPARTMENT_PASSAGE",
|
|
514
|
+
"COMPARTMENT_PASSAGE_HIGH",
|
|
515
|
+
"COMPARTMENT_PASSAGE_MIDDLE",
|
|
516
|
+
"COMPARTMENT_PASSAGE_LOW",
|
|
517
|
+
"COMPARTMENT_WALL"
|
|
518
|
+
];
|
|
519
|
+
this.overHangingElementInformation = [];
|
|
520
|
+
this._isRunningInitPreselectCoachIndex = false;
|
|
521
|
+
this._lastStartScrollPos = -1;
|
|
522
|
+
this._prepareServiceIconsNavigation = (propertyIds) => {
|
|
523
|
+
if (!propertyIds) return [];
|
|
524
|
+
const shrunkPropertyIds = propertyIds?.map(function(propertyId) {
|
|
525
|
+
return {
|
|
526
|
+
pId: propertyId,
|
|
527
|
+
svgName: mapIconToSvg[propertyId]?.svgName ? mapIconToSvg[propertyId]?.svgName : ""
|
|
528
|
+
};
|
|
529
|
+
}).filter((propertyToSvg) => ALLOWED_SERVICE_ICONS.indexOf(propertyToSvg.svgName) !== -1).filter((value, index, self) => self.map((propSvg) => propSvg.svgName).indexOf(value.svgName) === index).map((propertyToSvg) => propertyToSvg.pId).slice(0, MAX_SERVICE_PROPERTIES);
|
|
530
|
+
return shrunkPropertyIds ? shrunkPropertyIds : [];
|
|
531
|
+
};
|
|
532
|
+
this.addEventListener("blur", () => this._onLeaveSeatReservationComponent());
|
|
533
|
+
}
|
|
534
|
+
willUpdate(changedProperties) {
|
|
535
|
+
super.willUpdate(changedProperties);
|
|
536
|
+
if (changedProperties.has("seatReservations")) {
|
|
537
|
+
this.hasMultipleDecks = this.seatReservations?.length > 1;
|
|
538
|
+
this._initPrepareSeatReservationData();
|
|
539
|
+
this._prepareCoachWidthAndGapCalculations();
|
|
540
|
+
this._initSeatReservationPlaceSelection();
|
|
541
|
+
this.initNavigationSelectionByScrollEvent();
|
|
542
|
+
}
|
|
543
|
+
if (changedProperties.has("baseGridSize")) {
|
|
544
|
+
this.coachBorderOffset = this.coachBorderPadding / this.baseGridSize;
|
|
545
|
+
this.style?.setProperty("--sbb-seat-reservation-grid-size", `${this.baseGridSize}px`);
|
|
546
|
+
this.initNavigationSelectionByScrollEvent();
|
|
547
|
+
}
|
|
548
|
+
if (changedProperties.has("height") && !!this.height) {
|
|
549
|
+
const seatReservationLayer = this.seatReservations[this.currSelectedDeckIndex] || null;
|
|
550
|
+
if (seatReservationLayer?.coachItems.length) {
|
|
551
|
+
this.baseGridSize = this.height / seatReservationLayer.coachItems[0].dimension.h;
|
|
552
|
+
this.coachBorderOffset = this.coachBorderPadding / this.baseGridSize;
|
|
553
|
+
this.style?.setProperty("--sbb-seat-reservation-grid-size", `${this.baseGridSize}px`);
|
|
554
|
+
this._initPrepareSeatReservationData();
|
|
555
|
+
this.initNavigationSelectionByScrollEvent();
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
if (changedProperties.has("alignVertical") && this.alignVertical) this.initNavigationSelectionByScrollEvent();
|
|
559
|
+
if (changedProperties.has("preselectCoachIndex")) {
|
|
560
|
+
this._isRunningInitPreselectCoachIndex = true;
|
|
561
|
+
setTimeout(() => this.scrollToSelectedNavCoach(this.preselectCoachIndex), 1);
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
navigateByDirectionBtn(btnDirection) {
|
|
565
|
+
this.unfocusPlaceElement();
|
|
566
|
+
let navigateToCoachIndex = this.currSelectedCoachIndex;
|
|
567
|
+
if (btnDirection == "DIRECTION_LEFT" && navigateToCoachIndex > 0) navigateToCoachIndex = this.currSelectedCoachIndex != -1 ? this.currSelectedCoachIndex - 1 : 0;
|
|
568
|
+
else if (btnDirection == "DIRECTION_RIGHT" && navigateToCoachIndex < this.seatReservations[this.currSelectedDeckIndex]?.coachItems.length - 1) navigateToCoachIndex = this.currSelectedCoachIndex != -1 ? this.currSelectedCoachIndex + 1 : 0;
|
|
569
|
+
this.scrollToSelectedNavCoach(navigateToCoachIndex);
|
|
570
|
+
}
|
|
571
|
+
/**
|
|
572
|
+
* Data can be prepared once for the entire component
|
|
573
|
+
* in order to avoid recurring iteration processes in rendering.
|
|
574
|
+
*/
|
|
575
|
+
_initPrepareSeatReservationData() {
|
|
576
|
+
this._determineBaseFontSize();
|
|
577
|
+
if (this.hasMultipleDecks) this._initEmptyCoachDeckOffsets();
|
|
578
|
+
this._prepareCoachItemDetailsData();
|
|
579
|
+
this._prepareOptimizeAreaIconDimensionByMedian();
|
|
580
|
+
}
|
|
581
|
+
/** Init scroll event handling for coach navigation */
|
|
582
|
+
initNavigationSelectionByScrollEvent() {
|
|
583
|
+
this.coachScrollArea = this.shadowRoot?.querySelector("#sbb-sr__wrapper-scrollarea");
|
|
584
|
+
this.navigationScrollArea = this.shadowRoot?.querySelector("#sbb-sr__navigation-list-coaches");
|
|
585
|
+
const seatReservationDeck = this.seatReservations ? this.seatReservations[this.currSelectedDeckIndex] : null;
|
|
586
|
+
if (seatReservationDeck && seatReservationDeck.coachItems.length > 0) {
|
|
587
|
+
const coachHeightWithBorderPadding = seatReservationDeck.coachItems[0].dimension.h * this.baseGridSize + this.coachBorderPadding;
|
|
588
|
+
const gapBetweenCoachDecks = (this.seatReservations.length - 1) * this.gapBetweenCoachDecks;
|
|
589
|
+
this.style?.setProperty("--sbb-seat-reservation-height", `${coachHeightWithBorderPadding * this.seatReservations.length + gapBetweenCoachDecks}`);
|
|
590
|
+
this.style?.setProperty("--sbb-seat-reservation-decks", `${this.seatReservations.length}`);
|
|
591
|
+
}
|
|
592
|
+
if (this.navigationScrollArea) {
|
|
593
|
+
this.scrollNavigationAreaDim = this.alignVertical ? this.navigationScrollArea.getBoundingClientRect().height : this.navigationScrollArea.getBoundingClientRect().width;
|
|
594
|
+
const navCoachesList = this.navigationScrollArea.querySelector("ul > li");
|
|
595
|
+
if (navCoachesList) {
|
|
596
|
+
const firstLiEleDimension = navCoachesList?.getBoundingClientRect();
|
|
597
|
+
this.coachNavButtonDim = this.alignVertical ? firstLiEleDimension.height : firstLiEleDimension.width;
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
if (this.coachScrollArea && seatReservationDeck) {
|
|
601
|
+
let currCalcTriggerPos = 0;
|
|
602
|
+
this.scrollCoachesAreaWidth = this.alignVertical ? this.coachScrollArea.getBoundingClientRect().height : this.coachScrollArea.getBoundingClientRect().width;
|
|
603
|
+
this.triggerCoachPositionsCollection = seatReservationDeck.coachItems.map((coach) => {
|
|
604
|
+
const startPosX = currCalcTriggerPos;
|
|
605
|
+
const coachWidth = this.getCalculatedDimension(coach.dimension).w;
|
|
606
|
+
const currentCoachOverhangingInfo = this.overHangingElementInformation.find((e) => e.coachId === coach.id);
|
|
607
|
+
const overhangingElementsPresent = currentCoachOverhangingInfo?.overhangingPlaces || currentCoachOverhangingInfo?.overhangingGraphicAreas;
|
|
608
|
+
currCalcTriggerPos += coachWidth + (!overhangingElementsPresent ? this.gapBetweenCoaches : 2 * this.gapBetweenCoaches);
|
|
609
|
+
return {
|
|
610
|
+
start: startPosX,
|
|
611
|
+
end: currCalcTriggerPos,
|
|
612
|
+
width: coachWidth
|
|
613
|
+
};
|
|
614
|
+
});
|
|
615
|
+
this.maxCalcCoachesWidth = currCalcTriggerPos - this.gapBetweenCoaches;
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
/**
|
|
619
|
+
* Scroll event handler managed the end of scrolling inside the coach scroll area.
|
|
620
|
+
* Timeout event handling to check if the scrolling has been completed.
|
|
621
|
+
* It is required because the Safari browser does not handle scrollend event,
|
|
622
|
+
* and we therefore imitate this event -> scrollend.
|
|
623
|
+
*/
|
|
624
|
+
coachAreaScrollend() {
|
|
625
|
+
if (this._scrollTimeout) clearTimeout(this._scrollTimeout);
|
|
626
|
+
this._scrollTimeout = setTimeout(() => this._handleCoachAreaScrollendEvent(), 150);
|
|
627
|
+
}
|
|
628
|
+
/**
|
|
629
|
+
* If no navigation exists (property setting -> hasNavigation) and a table coach gets the focus,
|
|
630
|
+
* the first place in the coach must be automatically preselected to control the place navigation via keyboard
|
|
631
|
+
*
|
|
632
|
+
* @param focusCoachIndex
|
|
633
|
+
*/
|
|
634
|
+
onFocusTableCoachAndPreselectPlace(focusCoachIndex) {
|
|
635
|
+
if (!this.seatReservationWithoutNavigationHasFocus && !this.hasNavigation) {
|
|
636
|
+
this.seatReservationWithoutNavigationHasFocus = true;
|
|
637
|
+
this.currSelectedCoachIndex = focusCoachIndex === 0 ? this.getNextAvailableCoachIndex(-1) : this.getPrevAvailableCoachIndex(focusCoachIndex);
|
|
638
|
+
this.preselectPlaceInCoach();
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
/** Will be triggered by focus navigation direction */
|
|
642
|
+
onFocusNavDirectionButton() {
|
|
643
|
+
this.focusedCoachIndex = -1;
|
|
644
|
+
}
|
|
645
|
+
/** TAB Key Event handling for Coach Navigation */
|
|
646
|
+
onKeyNavigationNavCoachButton(event, currNavCoachButtonIndex) {
|
|
647
|
+
if (event.key === this.keyboardNavigationEvents.Tab) {
|
|
648
|
+
this._handleTabKeyNavigation(event, "navigation", currNavCoachButtonIndex);
|
|
649
|
+
return;
|
|
650
|
+
}
|
|
651
|
+
if (isArrowKeyOrPageKeysPressed(event)) this.keyboardSeatmapEventHandling(event);
|
|
652
|
+
}
|
|
653
|
+
/** General TAB Key Event handling for tab navigation inside the coach navigation area and the seatmap area */
|
|
654
|
+
_handleTabKeyNavigation(event, eventArea, currTabIndex) {
|
|
655
|
+
const pressedKey = event.key;
|
|
656
|
+
const pressedShiftTab = event.shiftKey;
|
|
657
|
+
if (pressedKey === this.keyboardNavigationEvents.Tab) {
|
|
658
|
+
if (eventArea == "navigation") {
|
|
659
|
+
if (currTabIndex == this.currSelectedCoachIndex) {
|
|
660
|
+
if (!this.currSelectedPlace || !pressedShiftTab || this.coachItemDetailsElements[currTabIndex].isDriverArea || this.focusedCoachIndex == -1) this.focusedCoachIndex = currTabIndex;
|
|
661
|
+
else if (pressedShiftTab && this.currSelectedPlace) {
|
|
662
|
+
this.focusedCoachIndex = -1;
|
|
663
|
+
this.focusPlaceElement(this.currSelectedPlace);
|
|
664
|
+
}
|
|
665
|
+
} else this.focusedCoachIndex = currTabIndex;
|
|
666
|
+
this._scrollToSelectedNavigationButton(currTabIndex);
|
|
667
|
+
} else if (eventArea == "seatmap") {
|
|
668
|
+
event.preventDefault();
|
|
669
|
+
if (pressedShiftTab) this._navigateCoachNavigationByKeyboard("PREV_TAB");
|
|
670
|
+
else this._navigateCoachNavigationByKeyboard("NEXT_TAB");
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
/**
|
|
675
|
+
* Initialisation of Keyboard Seatmap event handling to navigation between each places inside a selected coach by using [arrow] keys.
|
|
676
|
+
* With the [TAB] key the user navigation goes to the next coach navigation element and the currently selected place is automatically reset.
|
|
677
|
+
*/
|
|
678
|
+
keyboardSeatmapEventHandling(event) {
|
|
679
|
+
const isTabNext = event.key === this.keyboardNavigationEvents.Tab;
|
|
680
|
+
const isTabPrev = event.shiftKey && isTabNext;
|
|
681
|
+
if (!this.hasNavigation && this.currSelectedCoachIndex === 0 && isTabPrev || this.currSelectedCoachIndex === this.coachItemDetailsElements.length - 1 && isTabNext) return;
|
|
682
|
+
const pressedKey = event.key;
|
|
683
|
+
this.preventCoachScrollByPlaceClick = false;
|
|
684
|
+
if (!this.hasSeatReservationNativeFocus && (isTabNext || isTabPrev)) this.hasSeatReservationNativeFocus = true;
|
|
685
|
+
if (isTabNext) {
|
|
686
|
+
this._handleTabKeyNavigation(event, "seatmap");
|
|
687
|
+
return;
|
|
688
|
+
}
|
|
689
|
+
if (this.currSelectedCoachIndex !== -1 && isArrowKeyOrPageKeysPressed(event)) {
|
|
690
|
+
event.preventDefault();
|
|
691
|
+
switch (pressedKey) {
|
|
692
|
+
case this.keyboardNavigationEvents.ArrowLeft:
|
|
693
|
+
{
|
|
694
|
+
const pressedLeftKeyMapping = this.alignVertical ? this.keyboardNavigationEvents.ArrowDown : pressedKey;
|
|
695
|
+
this._navigateToPlaceByKeyboard(pressedLeftKeyMapping);
|
|
696
|
+
}
|
|
697
|
+
break;
|
|
698
|
+
case this.keyboardNavigationEvents.ArrowRight:
|
|
699
|
+
{
|
|
700
|
+
const pressedRightKeyMapping = this.alignVertical ? this.keyboardNavigationEvents.ArrowUp : pressedKey;
|
|
701
|
+
this._navigateToPlaceByKeyboard(pressedRightKeyMapping);
|
|
702
|
+
}
|
|
703
|
+
break;
|
|
704
|
+
case this.keyboardNavigationEvents.ArrowUp:
|
|
705
|
+
{
|
|
706
|
+
const pressedUpKeyMapping = this.alignVertical ? this.keyboardNavigationEvents.ArrowLeft : pressedKey;
|
|
707
|
+
this._navigateToPlaceByKeyboard(pressedUpKeyMapping);
|
|
708
|
+
}
|
|
709
|
+
break;
|
|
710
|
+
case this.keyboardNavigationEvents.ArrowDown:
|
|
711
|
+
{
|
|
712
|
+
const pressedDownKeyMapping = this.alignVertical ? this.keyboardNavigationEvents.ArrowRight : pressedKey;
|
|
713
|
+
this._navigateToPlaceByKeyboard(pressedDownKeyMapping);
|
|
714
|
+
}
|
|
715
|
+
break;
|
|
716
|
+
default: break;
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
/**
|
|
721
|
+
* Selects a place inside the coach if navigated via keyboard,
|
|
722
|
+
* otherwise the coach grid is selected (necessary for ScreenReader)
|
|
723
|
+
*/
|
|
724
|
+
preselectPlaceInCoach() {
|
|
725
|
+
if (!this.isAutoScrolling) return;
|
|
726
|
+
if (this._isRunningInitPreselectCoachIndex) {
|
|
727
|
+
this._isRunningInitPreselectCoachIndex = false;
|
|
728
|
+
return;
|
|
729
|
+
}
|
|
730
|
+
if (this.coachItemDetailsElements[this.currSelectedCoachIndex] && this.coachItemDetailsElements[this.currSelectedCoachIndex].isDriverArea) {
|
|
731
|
+
this._setFocusToSelectedCoachGrid();
|
|
732
|
+
return;
|
|
733
|
+
}
|
|
734
|
+
if (this.isKeyboardNavigation && this.isAutoScrolling) {
|
|
735
|
+
const closestPlace = this._getClosestPlaceByKeyDirection();
|
|
736
|
+
if (closestPlace) {
|
|
737
|
+
this.unfocusPlaceElement();
|
|
738
|
+
this.focusPlaceElement(closestPlace);
|
|
739
|
+
this.focusedCoachIndex = -1;
|
|
740
|
+
} else this._setFocusToSelectedCoachGrid();
|
|
741
|
+
} else {
|
|
742
|
+
this.unfocusPlaceElement();
|
|
743
|
+
this.isCoachGridFocusable = true;
|
|
744
|
+
this._setFocusToSelectedCoachGrid();
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
scrollToSelectedNavCoach(selectedNavCoachIndex) {
|
|
748
|
+
if (this._isValidCoachIndex(selectedNavCoachIndex) && selectedNavCoachIndex !== this.currSelectedCoachIndex) {
|
|
749
|
+
this.hoveredCoachIndex = selectedNavCoachIndex;
|
|
750
|
+
this.isAutoScrolling = true;
|
|
751
|
+
this.isCoachGridFocusable = true;
|
|
752
|
+
this.currSelectedCoachIndex = selectedNavCoachIndex;
|
|
753
|
+
this.currSelectedDeckIndex = this._getExistingCoachDeckIndex();
|
|
754
|
+
this._setScrollDirectionByCoachIndex();
|
|
755
|
+
const scrollToCoachPosX = this._getCoachScrollPositionX();
|
|
756
|
+
if ((this.selectedCoachIndex !== -1 || this.currSelectedCoachIndex > 0) && this._isScrollableToSelectedCoach()) {
|
|
757
|
+
this._lastStartScrollPos = this.coachScrollArea.scrollLeft;
|
|
758
|
+
this.coachScrollArea.scrollTo({
|
|
759
|
+
top: this.alignVertical ? scrollToCoachPosX : 0,
|
|
760
|
+
left: this.alignVertical ? 0 : scrollToCoachPosX,
|
|
761
|
+
behavior: "smooth"
|
|
762
|
+
});
|
|
763
|
+
} else this.updateCurrentSelectedCoach();
|
|
764
|
+
this._scrollToSelectedNavigationButton(selectedNavCoachIndex);
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
focusPlaceElement(place) {
|
|
768
|
+
this.unfocusPlaceElement();
|
|
769
|
+
if (place) {
|
|
770
|
+
this.currSelectedPlace = place;
|
|
771
|
+
this._setCurrSelectedPlaceElementId(place);
|
|
772
|
+
const selectedPlaceElement = this._getPlaceHtmlElement();
|
|
773
|
+
if (selectedPlaceElement) {
|
|
774
|
+
selectedPlaceElement.setAttribute("keyfocus", "focus");
|
|
775
|
+
const delayScrollInViewport = setTimeout(() => {
|
|
776
|
+
const placeId = this.getPlaceElementId(this.currSelectedDeckIndex, this.currSelectedCoachIndex, place.number);
|
|
777
|
+
this._scrollPlaceIntoNearestViewport(placeId);
|
|
778
|
+
clearTimeout(delayScrollInViewport);
|
|
779
|
+
}, 0);
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
}
|
|
783
|
+
unfocusPlaceElement() {
|
|
784
|
+
const selectedPlaceElement = this._getPlaceHtmlElement();
|
|
785
|
+
if (selectedPlaceElement) {
|
|
786
|
+
selectedPlaceElement.setAttribute("keyfocus", "unfocus");
|
|
787
|
+
this._setCurrSelectedPlaceElementId(null);
|
|
788
|
+
this.currSelectedPlace = null;
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
getCalculatedDimension(elementDimension, coachDimension, isOriginHeight, isStretchHeight) {
|
|
792
|
+
if (coachDimension && !isOriginHeight) elementDimension.h += this.coachBorderOffset * 2;
|
|
793
|
+
if (isStretchHeight) elementDimension.h += this.coachBorderOffset;
|
|
794
|
+
return {
|
|
795
|
+
w: this.baseGridSize * elementDimension.w,
|
|
796
|
+
h: this.baseGridSize * elementDimension.h
|
|
797
|
+
};
|
|
798
|
+
}
|
|
799
|
+
getCalculatedPosition(elementPosition, elementDimension, coachDimension, isOriginHeight) {
|
|
800
|
+
if (coachDimension && elementDimension) {
|
|
801
|
+
const endPosHeight = isOriginHeight ? coachDimension.h : coachDimension.h + this.coachBorderOffset;
|
|
802
|
+
if (elementPosition.y === 0) elementPosition.y -= this.coachBorderOffset;
|
|
803
|
+
else if (elementPosition.y + elementDimension.h === endPosHeight) elementPosition.y += this.coachBorderOffset;
|
|
804
|
+
}
|
|
805
|
+
return {
|
|
806
|
+
x: this.baseGridSize * elementPosition.x,
|
|
807
|
+
y: this.baseGridSize * elementPosition.y,
|
|
808
|
+
z: elementPosition.z
|
|
809
|
+
};
|
|
810
|
+
}
|
|
811
|
+
/**
|
|
812
|
+
* detects if a (graphical) element is on the border with its position (upper or lower border).
|
|
813
|
+
* @param baseElement
|
|
814
|
+
* @param coachDimension
|
|
815
|
+
* @protected
|
|
816
|
+
*/
|
|
817
|
+
isElementDirectlyOnBorder(baseElement, coachDimension) {
|
|
818
|
+
return baseElement.position.y === 0 || baseElement.position.y + baseElement.dimension.h === coachDimension.h;
|
|
819
|
+
}
|
|
820
|
+
/**
|
|
821
|
+
* Counts all available seats together depending on the seat type
|
|
822
|
+
*
|
|
823
|
+
* @param places
|
|
824
|
+
* @returns An Object with count of free seats and free bicycle places
|
|
825
|
+
*/
|
|
826
|
+
getAvailableFreePlacesNumFromCoach(places) {
|
|
827
|
+
const accumulator = {
|
|
828
|
+
seats: 0,
|
|
829
|
+
bicycles: 0
|
|
830
|
+
};
|
|
831
|
+
const freePlaces = places?.reduce((accumulator, currPlace) => {
|
|
832
|
+
if (currPlace.state !== "FREE") return accumulator;
|
|
833
|
+
if (currPlace.type === "SEAT") accumulator.seats++;
|
|
834
|
+
else accumulator.bicycles++;
|
|
835
|
+
return accumulator;
|
|
836
|
+
}, accumulator);
|
|
837
|
+
return freePlaces ? freePlaces : accumulator;
|
|
838
|
+
}
|
|
839
|
+
/**
|
|
840
|
+
* At the end of a scroll Event from the coach scrollable area,
|
|
841
|
+
* the reached coach is marked as selected
|
|
842
|
+
*/
|
|
843
|
+
_handleCoachAreaScrollendEvent() {
|
|
844
|
+
const findScrollCoachIndex = this.isAutoScrolling ? this.currSelectedCoachIndex : this._getCoachIndexByScrollTriggerPosition();
|
|
845
|
+
if (this.preventCoachScrollByPlaceClick) {
|
|
846
|
+
if (Math.abs(this._lastStartScrollPos - this.coachScrollArea.scrollLeft) > this.baseGridSize * 2) this.selectedCoachIndex = findScrollCoachIndex;
|
|
847
|
+
this.preventCoachScrollByPlaceClick = false;
|
|
848
|
+
return;
|
|
849
|
+
}
|
|
850
|
+
this._lastStartScrollPos = this.coachScrollArea.scrollLeft;
|
|
851
|
+
this.hoveredCoachIndex = -1;
|
|
852
|
+
if (this.currSelectedCoachIndex === -1) this.currSelectedCoachIndex = findScrollCoachIndex;
|
|
853
|
+
if (this._isScrollableToSelectedCoach()) this.currSelectedCoachIndex = findScrollCoachIndex;
|
|
854
|
+
else this.currSelectedCoachIndex = findScrollCoachIndex < this.currSelectedCoachIndex ? this.currSelectedCoachIndex : findScrollCoachIndex;
|
|
855
|
+
if (!this.isAutoScrolling) this._scrollToSelectedNavigationButton(findScrollCoachIndex);
|
|
856
|
+
this.preventCoachScrollByPlaceClick = false;
|
|
857
|
+
this.updateCurrentSelectedCoach();
|
|
858
|
+
if (!this.hasNavigation) {
|
|
859
|
+
this.preselectPlaceInCoach();
|
|
860
|
+
this.isAutoScrolling = false;
|
|
861
|
+
}
|
|
862
|
+
}
|
|
863
|
+
/**
|
|
864
|
+
* Performs an automatic main navigation scroll to the specified selectedNavCoachIndex.
|
|
865
|
+
* Calculates the central scroll offset of the nav coach to be selected.
|
|
866
|
+
* @param selectedNavCoachIndex
|
|
867
|
+
*/
|
|
868
|
+
_scrollToSelectedNavigationButton(selectedNavCoachIndex) {
|
|
869
|
+
setTimeout(() => {
|
|
870
|
+
if (this.hasNavigation && this.navigationScrollArea) {
|
|
871
|
+
const navigationAreaCenteredPosX = this.scrollNavigationAreaDim / 2;
|
|
872
|
+
const scrollOffsetX = selectedNavCoachIndex * this.coachNavButtonDim - navigationAreaCenteredPosX + this.coachNavButtonDim;
|
|
873
|
+
this.navigationScrollArea.scrollTo({
|
|
874
|
+
top: this.alignVertical ? scrollOffsetX : 0,
|
|
875
|
+
left: this.alignVertical ? 0 : scrollOffsetX,
|
|
876
|
+
behavior: "smooth"
|
|
877
|
+
});
|
|
878
|
+
}
|
|
879
|
+
}, 10);
|
|
880
|
+
}
|
|
881
|
+
/**
|
|
882
|
+
* Sets the new ScrollDirection by the new given target coach index.
|
|
883
|
+
*/
|
|
884
|
+
_setScrollDirectionByCoachIndex() {
|
|
885
|
+
this.currScrollDirection = this.currSelectedCoachIndex > this.selectedCoachIndex ? ScrollDirection.right : ScrollDirection.left;
|
|
886
|
+
}
|
|
887
|
+
/**
|
|
888
|
+
* Returns the scroll start or end position X from the selected coach.
|
|
889
|
+
* In case the user is currently navigating through places by keyboard and goes to previous coach,
|
|
890
|
+
* then we return the end position of the coach to get the closest scroll position of the next focus place.
|
|
891
|
+
* @returns number
|
|
892
|
+
*/
|
|
893
|
+
_getCoachScrollPositionX() {
|
|
894
|
+
const coachTriggerPoint = this.triggerCoachPositionsCollection[this.currSelectedCoachIndex];
|
|
895
|
+
return this.isKeyboardNavigation && this.currScrollDirection === ScrollDirection.left && coachTriggerPoint.width > this.scrollCoachesAreaWidth ? coachTriggerPoint.end - this.scrollCoachesAreaWidth : coachTriggerPoint.start;
|
|
896
|
+
}
|
|
897
|
+
/**
|
|
898
|
+
* Sets the focus on the HTML table (grid) caption element so that the heading is read out when using a ScreenReader.
|
|
899
|
+
*/
|
|
900
|
+
_setFocusToSelectedCoachGrid() {
|
|
901
|
+
if (this.isCoachGridFocusable && this.hasSeatReservationNativeFocus) {
|
|
902
|
+
this.isCoachGridFocusable = false;
|
|
903
|
+
const coachTableCaptionElement = this.shadowRoot?.querySelector("#sbb-sr-coach-caption-" + this.currSelectedCoachIndex);
|
|
904
|
+
if (coachTableCaptionElement) coachTableCaptionElement.focus();
|
|
905
|
+
}
|
|
906
|
+
}
|
|
907
|
+
/**
|
|
908
|
+
* Returns whether the current scrolled position can be used to scroll to the selected wagon
|
|
909
|
+
* @returns boolean
|
|
910
|
+
*/
|
|
911
|
+
_isScrollableToSelectedCoach() {
|
|
912
|
+
const currScrollPosX = this.alignVertical ? this.coachScrollArea.scrollTop : this.coachScrollArea.scrollLeft;
|
|
913
|
+
const coachScrollWindowWidth = this.alignVertical ? this.coachScrollArea.getBoundingClientRect().height : this.coachScrollArea.getBoundingClientRect().width;
|
|
914
|
+
const maxScrollWidthArea = this.maxCalcCoachesWidth - coachScrollWindowWidth;
|
|
915
|
+
const currCoachTrigger = this.triggerCoachPositionsCollection[this.currSelectedCoachIndex];
|
|
916
|
+
const isScrollPosSameToCurrCoachPos = currScrollPosX === this.triggerCoachPositionsCollection[this.currSelectedCoachIndex].start;
|
|
917
|
+
return (currScrollPosX < maxScrollWidthArea || currScrollPosX > currCoachTrigger.start) && !isScrollPosSameToCurrCoachPos;
|
|
918
|
+
}
|
|
919
|
+
/**
|
|
920
|
+
* Returns the coach index which is currently visible in the scroll area
|
|
921
|
+
* @returns number
|
|
922
|
+
*/
|
|
923
|
+
_getCoachIndexByScrollTriggerPosition() {
|
|
924
|
+
const scrollOffsetX = (this.alignVertical ? this.coachScrollArea.scrollTop : this.coachScrollArea.scrollLeft) + this.scrollCoachesAreaWidth / 2;
|
|
925
|
+
return this.triggerCoachPositionsCollection.findIndex((coachTrigger) => scrollOffsetX >= coachTrigger.start && scrollOffsetX <= coachTrigger.end);
|
|
926
|
+
}
|
|
927
|
+
/**
|
|
928
|
+
* Get the first place of current selected coach by table cell coordinate 0-0 id.
|
|
929
|
+
* @returns Place or null
|
|
930
|
+
*/
|
|
931
|
+
_getFirstPlaceInSelectedCoach() {
|
|
932
|
+
let firstPlace = null;
|
|
933
|
+
const coach = this.seatReservations[this.currSelectedDeckIndex].coachItems[this.currSelectedCoachIndex];
|
|
934
|
+
const firstCellId = "cell-" + this.currSelectedDeckIndex + "-" + this.currSelectedCoachIndex + "-0-0";
|
|
935
|
+
const placeNumber = this.shadowRoot?.querySelector("#" + firstCellId)?.querySelector("sbb-seat-reservation-place-control")?.getAttribute("text") || null;
|
|
936
|
+
if (coach && placeNumber) firstPlace = coach.places?.find((place) => place.number === placeNumber) || null;
|
|
937
|
+
return firstPlace;
|
|
938
|
+
}
|
|
939
|
+
_getSwitchedCoachDeckIndexByKeyNavigation(pressedKey, coach) {
|
|
940
|
+
if (!this.currSelectedPlace || pressedKey === this.keyboardNavigationEvents.ArrowRight || pressedKey === this.keyboardNavigationEvents.ArrowLeft) return null;
|
|
941
|
+
if (pressedKey === this.keyboardNavigationEvents.ArrowDown && this.currSelectedPlace.position.y + 2 === coach.dimension.h && !!this.seatReservations[this.currSelectedDeckIndex + 1]) return this.currSelectedDeckIndex + 1;
|
|
942
|
+
else if (pressedKey === this.keyboardNavigationEvents.ArrowUp && this.currSelectedPlace.position.y === 0 && !!this.seatReservations[this.currSelectedDeckIndex - 1]) return this.currSelectedDeckIndex - 1;
|
|
943
|
+
return null;
|
|
944
|
+
}
|
|
945
|
+
/**
|
|
946
|
+
* To get the correct closest place of current pressed key and the current selected place,
|
|
947
|
+
* we have to investigate the coordinates of each place to find the closest place of the currSelectedPlaceElementId.
|
|
948
|
+
* @param pressedKey
|
|
949
|
+
* @returns Place or null
|
|
950
|
+
*/
|
|
951
|
+
_getClosestPlaceByKeyDirection(pressedKey) {
|
|
952
|
+
const coach = this.seatReservations[this.currSelectedDeckIndex].coachItems[this.currSelectedCoachIndex];
|
|
953
|
+
let closestPlace = null;
|
|
954
|
+
let coachPlaces = coach.places;
|
|
955
|
+
let switchedCoachDeckIndex = null;
|
|
956
|
+
if (coachPlaces) {
|
|
957
|
+
if (!this.currSelectedPlaceElementId) return this._getFirstPlaceInSelectedCoach();
|
|
958
|
+
else if (this.currSelectedPlace) {
|
|
959
|
+
const currSelectedPlacePosition = { ...this.currSelectedPlace.position };
|
|
960
|
+
if (pressedKey) {
|
|
961
|
+
switchedCoachDeckIndex = this._getSwitchedCoachDeckIndexByKeyNavigation(pressedKey, coach);
|
|
962
|
+
if (switchedCoachDeckIndex !== null) {
|
|
963
|
+
coachPlaces = this.seatReservations[switchedCoachDeckIndex].coachItems[this.currSelectedCoachIndex].places || [];
|
|
964
|
+
currSelectedPlacePosition.y = switchedCoachDeckIndex < this.currSelectedDeckIndex ? coach.dimension.h : -1;
|
|
965
|
+
}
|
|
966
|
+
}
|
|
967
|
+
for (const place of coachPlaces) if (!pressedKey) {
|
|
968
|
+
if (this.currScrollDirection === ScrollDirection.right && place.position.y === currSelectedPlacePosition.y && (!closestPlace || place.position.x < closestPlace.position.x)) closestPlace = place;
|
|
969
|
+
else if (this.currScrollDirection === ScrollDirection.left && place.position.y === currSelectedPlacePosition.y && (!closestPlace || place.position.x > closestPlace.position.x)) closestPlace = place;
|
|
970
|
+
} else if (place.number !== this.currSelectedPlace?.number) {
|
|
971
|
+
if (pressedKey === this.keyboardNavigationEvents.ArrowRight && (place.position.y === currSelectedPlacePosition.y || place.position.y === currSelectedPlacePosition.y - 1) && place.position.x > currSelectedPlacePosition.x && (!closestPlace || place.position.x < closestPlace.position.x)) closestPlace = place;
|
|
972
|
+
else if (pressedKey === this.keyboardNavigationEvents.ArrowDown && (place.position.x === currSelectedPlacePosition.x || place.position.x === currSelectedPlacePosition.x + 1) && place.position.y > currSelectedPlacePosition.y && (!closestPlace || place.position.y < closestPlace.position.y)) closestPlace = place;
|
|
973
|
+
else if (pressedKey === this.keyboardNavigationEvents.ArrowLeft && (place.position.y === currSelectedPlacePosition.y || place.position.y === currSelectedPlacePosition.y + 1) && place.position.x < currSelectedPlacePosition.x && (!closestPlace || place.position.x > closestPlace.position.x)) closestPlace = place;
|
|
974
|
+
else if (pressedKey === this.keyboardNavigationEvents.ArrowUp && (place.position.x === currSelectedPlacePosition.x || place.position.x === currSelectedPlacePosition.x - 1) && place.position.y < currSelectedPlacePosition.y && (!closestPlace || place.position.y > closestPlace.position.y)) closestPlace = place;
|
|
975
|
+
}
|
|
976
|
+
if (switchedCoachDeckIndex !== null && closestPlace) this.currSelectedDeckIndex = switchedCoachDeckIndex;
|
|
977
|
+
}
|
|
978
|
+
}
|
|
979
|
+
return closestPlace;
|
|
980
|
+
}
|
|
981
|
+
_navigateCoachNavigationByKeyboard(tabDirection) {
|
|
982
|
+
const currFocusIndex = this.focusedCoachIndex === -1 ? this.currSelectedCoachIndex === -1 ? 0 : this.currSelectedCoachIndex : this.focusedCoachIndex;
|
|
983
|
+
const newFocusableIndex = tabDirection === "NEXT_TAB" ? this.getNextAvailableCoachIndex(currFocusIndex) : this.getPrevAvailableCoachIndex(currFocusIndex);
|
|
984
|
+
if (this.hasNavigation) {
|
|
985
|
+
const selectedPlaceElement = this._getPlaceHtmlElement();
|
|
986
|
+
const placeInCoachHasFocus = selectedPlaceElement ? selectedPlaceElement.getAttribute("keyfocus") === "focus" : false;
|
|
987
|
+
if (tabDirection === "PREV_TAB" && this.selectedCoachIndex === currFocusIndex) if (placeInCoachHasFocus || this.currSelectedPlace !== null) {
|
|
988
|
+
this.focusedCoachIndex = currFocusIndex;
|
|
989
|
+
this.unfocusPlaceElement();
|
|
990
|
+
return;
|
|
991
|
+
} else if (currFocusIndex === 0) this._refocusCurrentFocusedNavCoach(currFocusIndex);
|
|
992
|
+
else this.focusedCoachIndex = newFocusableIndex;
|
|
993
|
+
else if (newFocusableIndex !== this.currSelectedCoachIndex) this.focusedCoachIndex = newFocusableIndex;
|
|
994
|
+
else if (tabDirection === "NEXT_TAB" && newFocusableIndex === this.coachItemDetailsElements.length - 1) this._refocusCurrentFocusedNavCoach(currFocusIndex);
|
|
995
|
+
else {
|
|
996
|
+
this.focusedCoachIndex = -1;
|
|
997
|
+
this.selectedCoachIndex = newFocusableIndex;
|
|
998
|
+
if (placeInCoachHasFocus) this.focusPlaceElement(this.currSelectedPlace);
|
|
999
|
+
else {
|
|
1000
|
+
this.isCoachGridFocusable = true;
|
|
1001
|
+
this._setFocusToSelectedCoachGrid();
|
|
1002
|
+
}
|
|
1003
|
+
}
|
|
1004
|
+
this._scrollToSelectedNavigationButton(newFocusableIndex);
|
|
1005
|
+
} else this.scrollToSelectedNavCoach(newFocusableIndex);
|
|
1006
|
+
}
|
|
1007
|
+
_refocusCurrentFocusedNavCoach(focusIndex) {
|
|
1008
|
+
this.focusedCoachIndex = -1;
|
|
1009
|
+
setTimeout(() => this.focusedCoachIndex = focusIndex, 0);
|
|
1010
|
+
}
|
|
1011
|
+
_navigateToPlaceByKeyboard(pressedKey) {
|
|
1012
|
+
this.isKeyboardNavigation = true;
|
|
1013
|
+
if (this.focusedCoachIndex !== -1) this.focusedCoachIndex = -1;
|
|
1014
|
+
if (!this.preventPlaceClick) {
|
|
1015
|
+
const findClosestPlace = this._getClosestPlaceByKeyDirection(pressedKey);
|
|
1016
|
+
if (findClosestPlace) this.focusPlaceElement(findClosestPlace);
|
|
1017
|
+
else if (pressedKey === this.keyboardNavigationEvents.ArrowRight || pressedKey === this.keyboardNavigationEvents.ArrowLeft || this.alignVertical && (pressedKey === this.keyboardNavigationEvents.ArrowUp || pressedKey === this.keyboardNavigationEvents.ArrowDown)) {
|
|
1018
|
+
const newSelectedCoachIndex = pressedKey === this.keyboardNavigationEvents.ArrowRight ? this.getNextAvailableCoachIndex() : this.getPrevAvailableCoachIndex();
|
|
1019
|
+
this.scrollToSelectedNavCoach(newSelectedCoachIndex);
|
|
1020
|
+
}
|
|
1021
|
+
}
|
|
1022
|
+
}
|
|
1023
|
+
getNextAvailableCoachIndex(currentIndex) {
|
|
1024
|
+
const startIndex = currentIndex ?? this.currSelectedCoachIndex;
|
|
1025
|
+
return startIndex < this.seatReservations[this.currSelectedDeckIndex].coachItems.length - 1 ? startIndex + 1 : startIndex;
|
|
1026
|
+
}
|
|
1027
|
+
getPrevAvailableCoachIndex(currentIndex) {
|
|
1028
|
+
const startIndex = currentIndex ?? this.currSelectedCoachIndex;
|
|
1029
|
+
return startIndex > 0 ? startIndex - 1 : startIndex;
|
|
1030
|
+
}
|
|
1031
|
+
updateSelectedSeatReservationPlaces(placeSelection) {
|
|
1032
|
+
const placeTypeProp = placeSelection.placeType === "SEAT" ? "seats" : "bicycles";
|
|
1033
|
+
const maxReservations = placeSelection.placeType === "SEAT" ? this.maxSeatReservations : this.maxBicycleReservations;
|
|
1034
|
+
const currSelectedPlaces = this.selectedSeatReservationPlaces[placeTypeProp];
|
|
1035
|
+
this.selectedSeatReservationPlaces[placeTypeProp] = this._updateSelectedSeatReservationPlaces(currSelectedPlaces, maxReservations, placeSelection);
|
|
1036
|
+
/**
|
|
1037
|
+
* @type {CustomEvent<SeatReservationSelectedPlaces>}
|
|
1038
|
+
* Emits when a place was selected and returns a Place array with all selected places.
|
|
1039
|
+
*/
|
|
1040
|
+
this.dispatchEvent(new CustomEvent("selectedplaces", {
|
|
1041
|
+
bubbles: true,
|
|
1042
|
+
composed: true,
|
|
1043
|
+
detail: this.selectedSeatReservationPlaces
|
|
1044
|
+
}));
|
|
1045
|
+
}
|
|
1046
|
+
_updateSelectedSeatReservationPlaces(selectedSeatReservationPlaces, maxReservations, placeSelection) {
|
|
1047
|
+
if (placeSelection.state === "SELECTED") {
|
|
1048
|
+
const selectedPlaceDeckIndex = this._getDeckIndexByPlaceId(placeSelection.id);
|
|
1049
|
+
const seatReservationSelection = this._getSeatReservationPlaceSelection(placeSelection, selectedPlaceDeckIndex);
|
|
1050
|
+
if (seatReservationSelection) selectedSeatReservationPlaces.push(seatReservationSelection);
|
|
1051
|
+
} else selectedSeatReservationPlaces = selectedSeatReservationPlaces.filter((_selectedPlace) => _selectedPlace.id !== placeSelection.id);
|
|
1052
|
+
if (maxReservations > -1 && selectedSeatReservationPlaces.length > maxReservations) {
|
|
1053
|
+
const resetWithPlaceSelection = maxReservations > 0 ? placeSelection : void 0;
|
|
1054
|
+
selectedSeatReservationPlaces = this._resetAllPlaceSelections(selectedSeatReservationPlaces, resetWithPlaceSelection);
|
|
1055
|
+
}
|
|
1056
|
+
return selectedSeatReservationPlaces;
|
|
1057
|
+
}
|
|
1058
|
+
updateCurrentSelectedPlaceInCoach(placeSelection) {
|
|
1059
|
+
const placeDeckIndex = this._getDeckIndexByPlaceId(placeSelection.id);
|
|
1060
|
+
const coachIndex = placeSelection.coachIndex;
|
|
1061
|
+
if (placeDeckIndex === null) return;
|
|
1062
|
+
const place = this.seatReservations[placeDeckIndex].coachItems[coachIndex].places?.find((place) => place.number == placeSelection.number);
|
|
1063
|
+
if (!place) return;
|
|
1064
|
+
this.currSelectedDeckIndex = placeDeckIndex;
|
|
1065
|
+
this.currSelectedCoachIndex = coachIndex;
|
|
1066
|
+
this.currSelectedPlace = place;
|
|
1067
|
+
if (this.currSelectedCoachIndex !== this.selectedCoachIndex) this.updateCurrentSelectedCoach();
|
|
1068
|
+
this._setCurrSelectedPlaceElementId(place);
|
|
1069
|
+
const delayScrollInViewport = setTimeout(() => {
|
|
1070
|
+
this._scrollPlaceIntoNearestViewport(placeSelection.id);
|
|
1071
|
+
clearTimeout(delayScrollInViewport);
|
|
1072
|
+
}, 0);
|
|
1073
|
+
}
|
|
1074
|
+
updateCurrentSelectedCoach() {
|
|
1075
|
+
if (this.currSelectedCoachIndex == this.selectedCoachIndex) return;
|
|
1076
|
+
if (this.focusedCoachIndex != -1) this.focusedCoachIndex = this.currSelectedCoachIndex;
|
|
1077
|
+
this.selectedCoachIndex = this.currSelectedCoachIndex;
|
|
1078
|
+
const coachSelection = this._getSeatReservationSelectedCoach(this.selectedCoachIndex);
|
|
1079
|
+
if (coachSelection)
|
|
1080
|
+
/**
|
|
1081
|
+
* @type {CustomEvent<SeatReservationSelectedCoach>}
|
|
1082
|
+
* Emits when a coach was selected and returns a CoachSelection
|
|
1083
|
+
*/
|
|
1084
|
+
this.dispatchEvent(new CustomEvent("selectedcoach", {
|
|
1085
|
+
bubbles: true,
|
|
1086
|
+
composed: true,
|
|
1087
|
+
detail: coachSelection
|
|
1088
|
+
}));
|
|
1089
|
+
}
|
|
1090
|
+
getPlaceElementId(coachDeckIndex, coachIndex, placeNumber) {
|
|
1091
|
+
return "seat-reservation__place-button-" + coachDeckIndex + "-" + coachIndex + "-" + placeNumber;
|
|
1092
|
+
}
|
|
1093
|
+
/**
|
|
1094
|
+
* In the case of coach layouts with different decks,
|
|
1095
|
+
* it is necessary to extend the offset with empty coaches
|
|
1096
|
+
* in order to create a stable vehicle layout.
|
|
1097
|
+
*
|
|
1098
|
+
* [ooo]-[ooo]-[ooo]
|
|
1099
|
+
* [ooo]-[ooo]-[ooo]-[ooo]-[ooo]
|
|
1100
|
+
*/
|
|
1101
|
+
_initEmptyCoachDeckOffsets() {
|
|
1102
|
+
const coachOffsetIndexCounter = Array(this.seatReservations.length - 1).fill(0);
|
|
1103
|
+
this.seatReservations[this.seatReservations.length - 1].coachItems.forEach((lowerCoachItem) => {
|
|
1104
|
+
for (let i = 0; i < this.seatReservations.length - 1; i++) {
|
|
1105
|
+
const deckCoachItem = this.seatReservations[i].coachItems[coachOffsetIndexCounter[i]];
|
|
1106
|
+
if (lowerCoachItem.id != deckCoachItem?.id) {
|
|
1107
|
+
const emptyOffsetCoach = {
|
|
1108
|
+
...lowerCoachItem,
|
|
1109
|
+
places: void 0,
|
|
1110
|
+
propertyIds: void 0,
|
|
1111
|
+
graphicElements: void 0,
|
|
1112
|
+
serviceElements: void 0,
|
|
1113
|
+
travelClass: []
|
|
1114
|
+
};
|
|
1115
|
+
this.seatReservations[i].coachItems.splice(coachOffsetIndexCounter[i], 0, emptyOffsetCoach);
|
|
1116
|
+
}
|
|
1117
|
+
coachOffsetIndexCounter[i]++;
|
|
1118
|
+
}
|
|
1119
|
+
});
|
|
1120
|
+
}
|
|
1121
|
+
/**
|
|
1122
|
+
* Initialization of SeatReservationPlaceSelection Array based on the transferred places
|
|
1123
|
+
* that have the state SELECTED within the seatReservation object
|
|
1124
|
+
*/
|
|
1125
|
+
_initSeatReservationPlaceSelection() {
|
|
1126
|
+
this.selectedSeatReservationPlaces.seats = [];
|
|
1127
|
+
this.selectedSeatReservationPlaces.bicycles = [];
|
|
1128
|
+
this.seatReservations?.forEach((seatReservation, coachDeckIndex) => seatReservation.coachItems.map((coach, coachIndex) => {
|
|
1129
|
+
coach.places?.filter((place) => place.state === "SELECTED")?.forEach((place) => {
|
|
1130
|
+
const preselectedPlaceSelection = mapPlaceInfosToPlaceSelection(place, this.getPlaceElementId(coachDeckIndex, coachIndex, place.number), seatReservation.deckCoachIndex, coachIndex);
|
|
1131
|
+
const seatReservationPlaceSelection = this._getSeatReservationPlaceSelection(preselectedPlaceSelection, coachDeckIndex);
|
|
1132
|
+
if (seatReservationPlaceSelection) if (seatReservationPlaceSelection.placeType === "SEAT") this.selectedSeatReservationPlaces.seats.push(seatReservationPlaceSelection);
|
|
1133
|
+
else this.selectedSeatReservationPlaces.bicycles.push(seatReservationPlaceSelection);
|
|
1134
|
+
});
|
|
1135
|
+
}));
|
|
1136
|
+
}
|
|
1137
|
+
/**
|
|
1138
|
+
* All selected places will be reset or the currentSelectedPlace was given, then we reset all except currentSelectedPlace
|
|
1139
|
+
* @param reservationPlaceSelections
|
|
1140
|
+
* @param currSelectedPlace
|
|
1141
|
+
*/
|
|
1142
|
+
_resetAllPlaceSelections(reservationPlaceSelections, currSelectedPlace) {
|
|
1143
|
+
for (const placeSelection of reservationPlaceSelections) if (!currSelectedPlace || currSelectedPlace.id !== placeSelection.id) {
|
|
1144
|
+
const placeElement = this.shadowRoot?.getElementById(placeSelection.id);
|
|
1145
|
+
if (placeElement) placeElement.setAttribute("state", "FREE");
|
|
1146
|
+
}
|
|
1147
|
+
if (currSelectedPlace) reservationPlaceSelections = reservationPlaceSelections.filter((_selectedPlace) => _selectedPlace.id === currSelectedPlace.id);
|
|
1148
|
+
else reservationPlaceSelections = [];
|
|
1149
|
+
return reservationPlaceSelections;
|
|
1150
|
+
}
|
|
1151
|
+
_getSeatReservationPlaceSelection(currSelectedPlace, coachDeckIndex) {
|
|
1152
|
+
if (coachDeckIndex === null) return null;
|
|
1153
|
+
const coach = this.seatReservations[coachDeckIndex].coachItems[currSelectedPlace.coachIndex];
|
|
1154
|
+
const place = coach.places?.find((place) => place.number === currSelectedPlace.number);
|
|
1155
|
+
return place ? mapPlaceAndCoachToSeatReservationPlaceSelection(place, coach, currSelectedPlace.id, currSelectedPlace.deckIndex, currSelectedPlace.coachIndex) : null;
|
|
1156
|
+
}
|
|
1157
|
+
_getSeatReservationSelectedCoach(coachIndex) {
|
|
1158
|
+
if (!this.seatReservations[this.currSelectedDeckIndex].coachItems[coachIndex]) return null;
|
|
1159
|
+
const coach = this.seatReservations[this.currSelectedDeckIndex].coachItems[coachIndex];
|
|
1160
|
+
return mapCoachInfosToCoachSelection(coachIndex, coach, this.getAvailableFreePlacesNumFromCoach(coach.places));
|
|
1161
|
+
}
|
|
1162
|
+
_setCurrSelectedPlaceElementId(place) {
|
|
1163
|
+
this.currSelectedPlaceElementId = place ? this.getPlaceElementId(this.currSelectedDeckIndex, this.currSelectedCoachIndex, place.number) : null;
|
|
1164
|
+
}
|
|
1165
|
+
/**
|
|
1166
|
+
* Preparation of the used documents font-size which needs
|
|
1167
|
+
* to be determined in order to correctly calculate CSS values with rem
|
|
1168
|
+
* */
|
|
1169
|
+
_determineBaseFontSize() {
|
|
1170
|
+
if (!isServer) {
|
|
1171
|
+
const onePixelInRem = 1 / parseInt(window.getComputedStyle(document.body).fontSize, 10);
|
|
1172
|
+
this.style?.setProperty("--sbb-seat-reservation-one-px-rem", `${onePixelInRem + "rem"}`);
|
|
1173
|
+
}
|
|
1174
|
+
}
|
|
1175
|
+
/**
|
|
1176
|
+
* Prepares data for displaying navigation area.
|
|
1177
|
+
* Calculates the values which are not going to change during use of a component:
|
|
1178
|
+
* - coach id
|
|
1179
|
+
* - list of service icons
|
|
1180
|
+
* - class (first, second, any)
|
|
1181
|
+
* - whether there is a driver area left or right
|
|
1182
|
+
* */
|
|
1183
|
+
_prepareCoachItemDetailsData() {
|
|
1184
|
+
if (this.seatReservations) {
|
|
1185
|
+
const lowerDeck = this.seatReservations[this.seatReservations.length - 1].coachItems;
|
|
1186
|
+
this.coachItemDetailsElements = [];
|
|
1187
|
+
lowerDeck.forEach((coach, index) => {
|
|
1188
|
+
const travelClasses = [];
|
|
1189
|
+
const propertyIds = [];
|
|
1190
|
+
const places = [];
|
|
1191
|
+
this.seatReservations.map((sr) => {
|
|
1192
|
+
return sr.coachItems[index];
|
|
1193
|
+
}).forEach((coach) => {
|
|
1194
|
+
travelClasses.push(...coach.travelClass);
|
|
1195
|
+
propertyIds.push(...coach.propertyIds ? coach.propertyIds : []);
|
|
1196
|
+
places.push(...coach.places ? coach.places : []);
|
|
1197
|
+
});
|
|
1198
|
+
this.coachItemDetailsElements.push({
|
|
1199
|
+
id: coach.id,
|
|
1200
|
+
travelClass: this._prepareTravelClassNavigation(travelClasses),
|
|
1201
|
+
propertyIds: this._prepareServiceIconsNavigation(propertyIds),
|
|
1202
|
+
isDriverArea: coach.places ? coach.places.length === 0 : true,
|
|
1203
|
+
driverAreaSide: this._prepareDriverAreaSideNavigation(coach),
|
|
1204
|
+
freePlaces: this.getAvailableFreePlacesNumFromCoach(places),
|
|
1205
|
+
driverAreaElements: this._setDriverAreasElements(coach)
|
|
1206
|
+
});
|
|
1207
|
+
});
|
|
1208
|
+
}
|
|
1209
|
+
}
|
|
1210
|
+
_prepareOptimizeAreaIconDimensionByMedian() {
|
|
1211
|
+
if (this.seatReservations) {
|
|
1212
|
+
const allServiceDimensions = [];
|
|
1213
|
+
this.seatReservations.forEach((deck) => deck.coachItems.forEach((coach) => coach.serviceElements?.forEach((icon) => allServiceDimensions.push(icon.dimension))));
|
|
1214
|
+
if (allServiceDimensions.length) {
|
|
1215
|
+
allServiceDimensions.sort((dim1, dim2) => {
|
|
1216
|
+
if (dim1 && dim2) {
|
|
1217
|
+
const maxDim1 = dim1.w + dim1.h;
|
|
1218
|
+
const maxDim2 = dim2.w + dim2.h;
|
|
1219
|
+
if (maxDim1 > maxDim2) return 1;
|
|
1220
|
+
else if (maxDim1 < maxDim2) return -1;
|
|
1221
|
+
else return 0;
|
|
1222
|
+
}
|
|
1223
|
+
return 0;
|
|
1224
|
+
});
|
|
1225
|
+
const medianIconSize = allServiceDimensions[Math.floor(allServiceDimensions.length / 2)];
|
|
1226
|
+
this.globalAreaIconDim = this.getCalculatedDimension(medianIconSize);
|
|
1227
|
+
} else {
|
|
1228
|
+
const maxCoachHeight = this.seatReservations.flatMap((deck) => deck.coachItems.map((coach) => coach.dimension.h)).reduce((max, height) => Math.max(max, height), 0);
|
|
1229
|
+
const iconDimension = Math.floor(maxCoachHeight * .2);
|
|
1230
|
+
this.globalAreaIconDim = this.getCalculatedDimension({
|
|
1231
|
+
w: iconDimension,
|
|
1232
|
+
h: iconDimension
|
|
1233
|
+
});
|
|
1234
|
+
}
|
|
1235
|
+
}
|
|
1236
|
+
}
|
|
1237
|
+
_prepareTravelClassNavigation(travelClasses) {
|
|
1238
|
+
if (travelClasses.indexOf("FIRST") !== -1) return "FIRST";
|
|
1239
|
+
if (travelClasses.indexOf("SECOND") !== -1) return "SECOND";
|
|
1240
|
+
return "ANY_CLASS";
|
|
1241
|
+
}
|
|
1242
|
+
_prepareDriverAreaSideNavigation(coachItem) {
|
|
1243
|
+
const coachDriverAreas = coachItem.graphicElements?.filter((graphicalElements) => graphicalElements.icon === "DRIVER_AREA");
|
|
1244
|
+
if (coachDriverAreas && coachDriverAreas.length > 0) {
|
|
1245
|
+
const hasLeftDriverArea = coachDriverAreas.find((driverAreaElement) => driverAreaElement.position.x === 0) || false;
|
|
1246
|
+
const hasRightDriverArea = coachDriverAreas.find((driverAreaElement) => driverAreaElement.position.x > 0) || false;
|
|
1247
|
+
return {
|
|
1248
|
+
left: !!hasLeftDriverArea,
|
|
1249
|
+
right: !!hasRightDriverArea
|
|
1250
|
+
};
|
|
1251
|
+
}
|
|
1252
|
+
}
|
|
1253
|
+
_prepareCoachWidthAndGapCalculations() {
|
|
1254
|
+
if (this.seatReservations) this.seatReservations.forEach((seatReservation) => {
|
|
1255
|
+
seatReservation?.coachItems?.forEach((coachItem) => {
|
|
1256
|
+
const hasOverhangingPlaces = this._isOverhangingElementsPresent(coachItem.dimension.w, coachItem.places);
|
|
1257
|
+
const filteredElements = coachItem.graphicElements?.filter((e) => e.icon && !this.notAreaElements.includes(e.icon));
|
|
1258
|
+
const hasOverhangingGraphicAreas = this._isOverhangingElementsPresent(coachItem.dimension.w, filteredElements);
|
|
1259
|
+
this.overHangingElementInformation.push({
|
|
1260
|
+
coachId: coachItem.id,
|
|
1261
|
+
overhangingPlaces: hasOverhangingPlaces,
|
|
1262
|
+
overhangingGraphicAreas: hasOverhangingGraphicAreas
|
|
1263
|
+
});
|
|
1264
|
+
});
|
|
1265
|
+
});
|
|
1266
|
+
}
|
|
1267
|
+
/**
|
|
1268
|
+
* Returns the current selected place HTML element by currSelectedPlaceElementId.
|
|
1269
|
+
* @returns HTMLElement or null
|
|
1270
|
+
*/
|
|
1271
|
+
_getPlaceHtmlElement() {
|
|
1272
|
+
return this.currSelectedPlaceElementId ? this.shadowRoot?.getElementById(this.currSelectedPlaceElementId) || null : null;
|
|
1273
|
+
}
|
|
1274
|
+
/**
|
|
1275
|
+
* Returns the extracted coach deck index from place id
|
|
1276
|
+
* @returns number
|
|
1277
|
+
*/
|
|
1278
|
+
_getDeckIndexByPlaceId(placeId) {
|
|
1279
|
+
const deckIndex = this.shadowRoot?.querySelector("#" + placeId)?.getAttribute("data-deck-index");
|
|
1280
|
+
if (deckIndex && !isNaN(+deckIndex)) return +deckIndex;
|
|
1281
|
+
return null;
|
|
1282
|
+
}
|
|
1283
|
+
_isValidCoachIndex(coachIndex) {
|
|
1284
|
+
return coachIndex >= 0 && coachIndex <= this.seatReservations[this.seatReservations.length - 1].coachItems.length;
|
|
1285
|
+
}
|
|
1286
|
+
/**
|
|
1287
|
+
* Returns existing coach deck index depending on the selected coach.
|
|
1288
|
+
* This method is necessary to get an available coach deck index during keyboard navigation, which can vary between coaches with different decks.
|
|
1289
|
+
* For example, when navigating from a coach with two decks to a coach with one deck.
|
|
1290
|
+
*
|
|
1291
|
+
* [ooo]-[ooo]-[ooo]
|
|
1292
|
+
* [ooo]-[ooo]-[ooo]-[ooo]-[ooo]
|
|
1293
|
+
*
|
|
1294
|
+
* @returns number
|
|
1295
|
+
*/
|
|
1296
|
+
_getExistingCoachDeckIndex() {
|
|
1297
|
+
if (this.seatReservations[this.currSelectedDeckIndex].coachItems[this.currSelectedCoachIndex].places !== void 0) return this.currSelectedDeckIndex;
|
|
1298
|
+
const nextAvailableDeckCoachIndex = this.seatReservations.findIndex((seatReservation) => seatReservation.coachItems[this.currSelectedCoachIndex].places !== void 0);
|
|
1299
|
+
return this.currSelectedDeckIndex >= nextAvailableDeckCoachIndex ? this.currSelectedDeckIndex : nextAvailableDeckCoachIndex;
|
|
1300
|
+
}
|
|
1301
|
+
/**
|
|
1302
|
+
* If a selected place is slightly hidden by the overflow scroll content and is still clicked,
|
|
1303
|
+
* the method tries to scroll the selected place into the nearest viewport, so that it is completely visible.
|
|
1304
|
+
*
|
|
1305
|
+
* @param placeId
|
|
1306
|
+
*/
|
|
1307
|
+
_scrollPlaceIntoNearestViewport(placeId) {
|
|
1308
|
+
this.shadowRoot?.getElementById(placeId)?.scrollIntoView({
|
|
1309
|
+
behavior: "smooth",
|
|
1310
|
+
block: "nearest",
|
|
1311
|
+
inline: "nearest"
|
|
1312
|
+
});
|
|
1313
|
+
}
|
|
1314
|
+
/**
|
|
1315
|
+
* checks if any places or graphical elements (e.g. toilet area, etc.) are overhanging the coach borders
|
|
1316
|
+
* @param coachItemWidth
|
|
1317
|
+
* @param elements
|
|
1318
|
+
*/
|
|
1319
|
+
_isOverhangingElementsPresent(coachItemWidth, elements) {
|
|
1320
|
+
return elements?.some((element) => element.position.x === 0 || element.position.x + element.dimension.w >= coachItemWidth) ?? false;
|
|
1321
|
+
}
|
|
1322
|
+
/**
|
|
1323
|
+
* collect information about the driverAreas for one coach
|
|
1324
|
+
* @param coachItem
|
|
1325
|
+
* @private
|
|
1326
|
+
*/
|
|
1327
|
+
_setDriverAreasElements(coachItem) {
|
|
1328
|
+
if (coachItem) return {
|
|
1329
|
+
driverArea: coachItem.graphicElements?.find((element) => element.icon === "DRIVER_AREA"),
|
|
1330
|
+
driverAreaNoVerticalWall: coachItem.type === "LOCOMOTIVE_COACH" ? coachItem.graphicElements?.find((element) => element.icon === "DRIVER_AREA_NO_VERTICAL_WALL") : void 0
|
|
1331
|
+
};
|
|
1332
|
+
return {
|
|
1333
|
+
driverArea: void 0,
|
|
1334
|
+
driverAreaNoVerticalWall: void 0
|
|
1335
|
+
};
|
|
1336
|
+
}
|
|
1337
|
+
/**
|
|
1338
|
+
* Is called when the SeatReservation loses focus, what happens when the user tabs out or clicks somewhere else.
|
|
1339
|
+
* Then we reset the focused elements.
|
|
1340
|
+
*/
|
|
1341
|
+
_onLeaveSeatReservationComponent() {
|
|
1342
|
+
if (this.hasNavigation) this.focusedCoachIndex = -1;
|
|
1343
|
+
this.unfocusPlaceElement();
|
|
1344
|
+
}
|
|
1345
|
+
};
|
|
1346
|
+
})();
|
|
1347
|
+
//#endregion
|
|
1348
|
+
export { SeatReservationBaseElement };
|
|
1349
|
+
|
|
1350
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VhdC1yZXNlcnZhdGlvbi1iYXNlLWVsZW1lbnQuanMiLCJuYW1lcyI6W10sInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL2VsZW1lbnRzLWV4cGVyaW1lbnRhbC9zZWF0LXJlc2VydmF0aW9uL3NlYXQtcmVzZXJ2YXRpb24vc2VhdC1yZXNlcnZhdGlvbi1iYXNlLWVsZW1lbnQudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgaXNBcnJvd0tleU9yUGFnZUtleXNQcmVzc2VkIH0gZnJvbSAnQHNiYi1lc3RhL2x5bmUtZWxlbWVudHMvY29yZS9hMTF5LmpzJztcbmltcG9ydCB7IFNiYkVsZW1lbnQgfSBmcm9tICdAc2JiLWVzdGEvbHluZS1lbGVtZW50cy9jb3JlL2Jhc2UtZWxlbWVudHMuanMnO1xuaW1wb3J0IHsgZm9yY2VUeXBlIH0gZnJvbSAnQHNiYi1lc3RhL2x5bmUtZWxlbWVudHMvY29yZS9kZWNvcmF0b3JzLmpzJztcbmltcG9ydCB7IGlzU2VydmVyLCB0eXBlIFByb3BlcnR5VmFsdWVzIH0gZnJvbSAnbGl0JztcbmltcG9ydCB7IGV2ZW50T3B0aW9ucywgcHJvcGVydHksIHN0YXRlIH0gZnJvbSAnbGl0L2RlY29yYXRvcnMuanMnO1xuXG5pbXBvcnQge1xuICBtYXBDb2FjaEluZm9zVG9Db2FjaFNlbGVjdGlvbixcbiAgbWFwSWNvblRvU3ZnLFxuICBtYXBQbGFjZUFuZENvYWNoVG9TZWF0UmVzZXJ2YXRpb25QbGFjZVNlbGVjdGlvbixcbiAgbWFwUGxhY2VJbmZvc1RvUGxhY2VTZWxlY3Rpb24sXG59IGZyb20gJy4uL2NvbW1vbi9tYXBwZXIudHMnO1xuaW1wb3J0IHR5cGUge1xuICBCYXNlRWxlbWVudCxcbiAgQ29hY2hJdGVtLFxuICBDb2FjaE51bWJlck9mRnJlZVBsYWNlcyxcbiAgRWxlbWVudERpbWVuc2lvbixcbiAgRWxlbWVudFBvc2l0aW9uLFxuICBDb2FjaEl0ZW1EZXRhaWxzLFxuICBQbGFjZSxcbiAgUGxhY2VTZWxlY3Rpb24sXG4gIFBsYWNlVHJhdmVsQ2xhc3MsXG4gIFNlYXRSZXNlcnZhdGlvbixcbiAgU2VhdFJlc2VydmF0aW9uUGxhY2VTZWxlY3Rpb24sXG4gIFNlYXRSZXNlcnZhdGlvblNlbGVjdGVkQ29hY2gsXG4gIFNlYXRSZXNlcnZhdGlvblNlbGVjdGVkUGxhY2VzLFxuICBUcmF2ZWxEaXJlY3Rpb24sXG59IGZyb20gJy4uL2NvbW1vbi90eXBlcy50cyc7XG5pbXBvcnQgdHlwZSB7IFNiYlNlYXRSZXNlcnZhdGlvblBsYWNlQ29udHJvbEVsZW1lbnQgfSBmcm9tICcuLi9zZWF0LXJlc2VydmF0aW9uLXBsYWNlLWNvbnRyb2wvc2VhdC1yZXNlcnZhdGlvbi1wbGFjZS1jb250cm9sLmNvbXBvbmVudC50cyc7XG5cbmVudW0gU2Nyb2xsRGlyZWN0aW9uIHtcbiAgcmlnaHQgPSAncmlnaHQnLFxuICBsZWZ0ID0gJ2xlZnQnLFxufVxuXG5pbnRlcmZhY2UgQ29hY2hTY3JvbGxUcmlnZ2VyUG9pbnQge1xuICBzdGFydDogbnVtYmVyO1xuICBlbmQ6IG51bWJlcjtcbiAgd2lkdGg6IG51bWJlcjtcbn1cblxuY29uc3QgTUFYX1NFUlZJQ0VfUFJPUEVSVElFUyA9IDM7XG5jb25zdCBBTExPV0VEX1NFUlZJQ0VfSUNPTlM6IHN0cmluZ1tdID0gW1xuICAnc2Etdm8nLFxuICAnc2EtcnMnLFxuICAnc2EtYWJ0ZWlsa2luZGVyd2FnZW4nLFxuICAnc2Etd3InLFxuICAnc2EtZmEnLFxuICAnc2EtYnonLFxuICAnc2EtcnonLFxuXTtcblxuZXhwb3J0IGNsYXNzIFNlYXRSZXNlcnZhdGlvbkJhc2VFbGVtZW50IGV4dGVuZHMgU2JiRWxlbWVudCB7XG4gIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgZXZlbnRzID0ge1xuICAgIHNlbGVjdGVkcGxhY2VzOiAnc2VsZWN0ZWRwbGFjZXMnLFxuICAgIHNlbGVjdGVkY29hY2g6ICdzZWxlY3RlZGNvYWNoJyxcbiAgfSBhcyBjb25zdDtcblxuICAvKiogVGhlIHNlYXQgcmVzZXJ2YXRpb25zIGFycmF5IGNvbnRhaW5zIGFsbCBjb2FjaGVzIGFuZCBwbGFjZXMgKi9cbiAgQHByb3BlcnR5KHsgYXR0cmlidXRlOiAnc2VhdC1yZXNlcnZhdGlvbnMnLCB0eXBlOiBBcnJheSB9KVxuICBwdWJsaWMgYWNjZXNzb3Igc2VhdFJlc2VydmF0aW9uczogU2VhdFJlc2VydmF0aW9uW10gPSBudWxsITtcblxuICAvKiogRGlzcGxheXMgYW4gYXJyb3cgc2hvd2luZyB3aGF0IGRpcmVjdGlvbiBkb2VzIHRyYWluIGRyaXZlKi9cbiAgQHByb3BlcnR5KHsgYXR0cmlidXRlOiAndHJhdmVsLWRpcmVjdGlvbicsIHR5cGU6IFN0cmluZyB9KVxuICBwdWJsaWMgYWNjZXNzb3IgdHJhdmVsRGlyZWN0aW9uOiBUcmF2ZWxEaXJlY3Rpb24gPSAnTk9ORSc7XG5cbiAgLyoqIFRoZSBzZWF0IHJlc2VydmF0aW9uIG5hdmlnYXRpb24gY2FuIGJlIHRvZ2dsZWQgYnkgdGhpcyBwcm9wZXJ0eSAqL1xuICBAZm9yY2VUeXBlKClcbiAgQHByb3BlcnR5KHsgYXR0cmlidXRlOiAnaGFzLW5hdmlnYXRpb24nLCB0eXBlOiBCb29sZWFuIH0pXG4gIHB1YmxpYyBhY2Nlc3NvciBoYXNOYXZpZ2F0aW9uOiBib29sZWFuID0gdHJ1ZTtcblxuICAvKiogVGhlIHNlYXQgcmVzZXJ2YXRpb24gYXJlYSBpcyBhbGlnbmVkIHZlcnRpY2FsbHkgKi9cbiAgQGZvcmNlVHlwZSgpXG4gIEBwcm9wZXJ0eSh7IGF0dHJpYnV0ZTogJ2FsaWduLXZlcnRpY2FsJywgdHlwZTogQm9vbGVhbiwgcmVmbGVjdDogdHJ1ZSwgdXNlRGVmYXVsdDogdHJ1ZSB9KVxuICBwdWJsaWMgYWNjZXNzb3IgYWxpZ25WZXJ0aWNhbDogYm9vbGVhbiA9IGZhbHNlO1xuXG4gIC8qKiBUaGUgc2VhdCByZXNlcnZhdGlvbiBhcmVhJ3MgYmFzZSBncmlkIHNpemUgKi9cbiAgQGZvcmNlVHlwZSgpXG4gIEBwcm9wZXJ0eSh7IGF0dHJpYnV0ZTogJ2Jhc2UtZ3JpZC1zaXplJywgdHlwZTogTnVtYmVyIH0pXG4gIHB1YmxpYyBhY2Nlc3NvciBiYXNlR3JpZFNpemU6IG51bWJlciA9IDE2O1xuXG4gIC8qKiBUaGUgc2VhdCByZXNlcnZhdGlvbiBhcmVhJ3Mgd2lkdGggKi9cbiAgQGZvcmNlVHlwZSgpXG4gIEBwcm9wZXJ0eSh7IGF0dHJpYnV0ZTogJ2hlaWdodCcsIHR5cGU6IE51bWJlciB9KVxuICBwdWJsaWMgYWNjZXNzb3IgaGVpZ2h0OiBudW1iZXIgPSBudWxsITtcblxuICAvKiogTWF4aW1hbCBudW1iZXIgb2YgcG9zc2libGUgY2xpY2thYmxlIHNlYXRzICovXG4gIEBmb3JjZVR5cGUoKVxuICBAcHJvcGVydHkoeyBhdHRyaWJ1dGU6ICdtYXgtc2VhdC1yZXNlcnZhdGlvbnMnLCB0eXBlOiBOdW1iZXIgfSlcbiAgcHVibGljIGFjY2Vzc29yIG1heFNlYXRSZXNlcnZhdGlvbnM6IG51bWJlciA9IC0xO1xuXG4gIC8qKiBNYXhpbWFsIG51bWJlciBvZiBwb3NzaWJsZSBjbGlja2FibGUgYmljeWNsZSBwbGFjZXMgKi9cbiAgQGZvcmNlVHlwZSgpXG4gIEBwcm9wZXJ0eSh7IGF0dHJpYnV0ZTogJ21heC1iaWN5Y2xlLXJlc2VydmF0aW9ucycsIHR5cGU6IE51bWJlciB9KVxuICBwdWJsaWMgYWNjZXNzb3IgbWF4QmljeWNsZVJlc2VydmF0aW9uczogbnVtYmVyID0gLTE7XG5cbiAgLyoqIEFueSBjbGljayBmdW5jdGlvbmFsaXR5IGlzIHByZXZlbnRlZCAqL1xuICBAZm9yY2VUeXBlKClcbiAgQHByb3BlcnR5KHsgYXR0cmlidXRlOiAncHJldmVudC1wbGFjZS1jbGljaycsIHR5cGU6IEJvb2xlYW4gfSlcbiAgcHVibGljIGFjY2Vzc29yIHByZXZlbnRQbGFjZUNsaWNrOiBib29sZWFuID0gZmFsc2U7XG5cbiAgQGZvcmNlVHlwZSgpXG4gIEBwcm9wZXJ0eSh7IGF0dHJpYnV0ZTogJ3ByZXNlbGVjdC1jb2FjaC1pbmRleCcsIHR5cGU6IE51bWJlciB9KVxuICBwdWJsaWMgYWNjZXNzb3IgcHJlc2VsZWN0Q29hY2hJbmRleDogbnVtYmVyID0gLTE7XG5cbiAgLyoqIFRoZSBzZWF0IHJlc2VydmF0aW9uIHRpdGxlIGluZm9ybWF0aW9uIGF0IHBsYWNlLWNvbnRyb2xzLCBuYXZpZ2F0aW9uLWNvYWNoZXMgYW5kIG5hdmlnYXRpb24tc2VydmljZXMgY2FuIGJlIHRvZ2dsZWQgYnkgdGhpcyBwcm9wZXJ0eSAqL1xuICBAZm9yY2VUeXBlKClcbiAgQHByb3BlcnR5KHsgYXR0cmlidXRlOiAnc2hvdy10aXRsZS1pbmZvJywgdHlwZTogQm9vbGVhbiB9KVxuICBwdWJsaWMgYWNjZXNzb3Igc2hvd1RpdGxlSW5mbzogYm9vbGVhbiA9IGZhbHNlO1xuXG4gIEBzdGF0ZSgpIHByb3RlY3RlZCBhY2Nlc3NvciBzZWxlY3RlZENvYWNoSW5kZXg6IG51bWJlciA9IC0xO1xuICBAc3RhdGUoKSBwcm90ZWN0ZWQgYWNjZXNzb3IgZm9jdXNlZENvYWNoSW5kZXg6IG51bWJlciA9IC0xO1xuICBAc3RhdGUoKSBwcm90ZWN0ZWQgYWNjZXNzb3IgaG92ZXJlZENvYWNoSW5kZXg6IG51bWJlciA9IC0xO1xuXG4gIC8vIERlc2NyaWJlcyB0aGUgZGlzdGFuY2UgYmV0d2VlbiB0aGUgYm9yZGVyIG9mIHRoZSBjb2FjaCBhbmQgdGhlIHBsYWNlcyBpbiBwaXhlbHNcbiAgcHJvdGVjdGVkIGNvYWNoQm9yZGVyUGFkZGluZyA9IDY7XG4gIC8vIERlc2NyaWJlcyB0aGUgZ2FwIGJldHdlZW4gdGhlIGNvYWNoZXMgaW4gcGl4ZWxzXG4gIHByb3RlY3RlZCBnYXBCZXR3ZWVuQ29hY2hlcyA9IDQ7XG4gIC8vIFRoZSBjYWxjdWxhdGVkIGNvYWNoQm9yZGVyT2Zmc2V0IGlzIHVzZWQgdG8gY2FsY3VsYXRlIHRoZSB3aWR0aCBhbmQgaGVpZ2h0IG9mIGNvYWNoIGJvcmRlciBncmFwaGljLFxuICAvLyBidXQgYWxzbyB0byBwb3NpdGlvbiBvdGhlciBncmFwaGljcyB0aGF0IGFyZSBhbGlnbmVkIGRpcmVjdGx5IHRvIHRoZSBjb2FjaCBib3JkZXIuXG4gIHByb3RlY3RlZCBjb2FjaEJvcmRlck9mZnNldCA9IHRoaXMuY29hY2hCb3JkZXJQYWRkaW5nIC8gdGhpcy5iYXNlR3JpZFNpemU7XG4gIC8vIERlc2NyaWJlcyB0aGUgZ2FwIGJldHdlZW4gdGhlIGNvYWNoZXMgZGVja3MgYnkgbXVsdGlwbGUgZGVjayB2aXN1YWxpemF0aW9uXG4gIHByb3RlY3RlZCBnYXBCZXR3ZWVuQ29hY2hEZWNrcyA9IDQ4O1xuICAvLyBEZXNjcmliZXMgdGhlIGZpeCB3aWR0aCBvZiBjb2FjaCBuYXZpZ2F0aW9uIGJ1dHRvblxuICBwcm90ZWN0ZWQgY29hY2hOYXZCdXR0b25EaW06IG51bWJlciA9IDA7XG4gIC8vIERlc2NyaWJlcyB0aGUgY2FsY3VsYXRlZCBkaW1lbnNpb24gZm9yIHRoZSBhcmVhIGljb25zLCB3aGljaCBpcyB1c2VkIHRvIHNldCB0aGUgbWF4IHdpZHRoIGFuZCBoZWlnaHQgb2YgdGhlIGFyZWEgaWNvbnNcbiAgcHJvdGVjdGVkIGdsb2JhbEFyZWFJY29uRGltOiBFbGVtZW50RGltZW5zaW9uID0geyB3OiAyLCBoOiAyIH07XG4gIC8vICNUSU1PLTQ1ODU4XG4gIC8vIERlc2NyaWJlcyB0aGUgcGFkZGluZyBmb3IgdGhlIGljb24gd2l0aGluIHRoZSBhcmVhIGFzIGEgcGVyY2VudGFnZSBzaXplIG9mIHRoZSBhcmVhIHNlbGYuIDgwJSAoMC44IHBlcmNlbnQpIGNvcnJlc3BvbmRzXG4gIC8vIHRvIGEgZ29vZCBvcHRpY2FsIHNpemUgYW5kIGNyZWF0ZXMgYSBnb29kIHBhZGRpbmcgZnJvbSB0aGUgYXJlYSB0aSBpY29uXG4gIHByb3RlY3RlZCBnbG9iYWxBcmVhSWNvblBhZGRpbmc6IG51bWJlciA9IDAuODtcbiAgcHJvdGVjdGVkIGNvYWNoSXRlbURldGFpbHNFbGVtZW50czogQ29hY2hJdGVtRGV0YWlsc1tdID0gW107XG4gIHByb3RlY3RlZCBjdXJyU2Nyb2xsRGlyZWN0aW9uOiBTY3JvbGxEaXJlY3Rpb24gPSBTY3JvbGxEaXJlY3Rpb24ucmlnaHQ7XG4gIHByb3RlY3RlZCBtYXhDYWxjQ29hY2hlc1dpZHRoOiBudW1iZXIgPSAwO1xuICBwcm90ZWN0ZWQgc2Nyb2xsQ29hY2hlc0FyZWFXaWR0aDogbnVtYmVyID0gMDtcbiAgcHJvdGVjdGVkIHNjcm9sbE5hdmlnYXRpb25BcmVhRGltOiBudW1iZXIgPSAwO1xuICBwcm90ZWN0ZWQgdHJpZ2dlckNvYWNoUG9zaXRpb25zQ29sbGVjdGlvbjogQ29hY2hTY3JvbGxUcmlnZ2VyUG9pbnRbXSA9IFtdO1xuICBwcm90ZWN0ZWQgbmF2aWdhdGlvblNjcm9sbEFyZWE6IEhUTUxFbGVtZW50ID0gbnVsbCE7XG4gIHByb3RlY3RlZCBjb2FjaFNjcm9sbEFyZWE6IEhUTUxFbGVtZW50ID0gbnVsbCE7XG4gIHByb3RlY3RlZCBjdXJyU2VsZWN0ZWRQbGFjZTogUGxhY2UgfCBudWxsID0gbnVsbDtcbiAgcHJvdGVjdGVkIGN1cnJTZWxlY3RlZFBsYWNlRWxlbWVudElkOiBzdHJpbmcgfCBudWxsID0gbnVsbDtcbiAgcHJvdGVjdGVkIGN1cnJTZWxlY3RlZENvYWNoSW5kZXg6IG51bWJlciA9IC0xO1xuICBwcm90ZWN0ZWQgY3VyclNlbGVjdGVkRGVja0luZGV4OiBudW1iZXIgPSAwO1xuICBwcm90ZWN0ZWQgcHJldmVudENvYWNoU2Nyb2xsQnlQbGFjZUNsaWNrOiBib29sZWFuID0gZmFsc2U7XG4gIHByb3RlY3RlZCBzZWxlY3RlZFNlYXRSZXNlcnZhdGlvblBsYWNlczogU2VhdFJlc2VydmF0aW9uU2VsZWN0ZWRQbGFjZXMgPSB7XG4gICAgc2VhdHM6IFtdLFxuICAgIGJpY3ljbGVzOiBbXSxcbiAgfTtcbiAgcHJvdGVjdGVkIHNlYXRSZXNlcnZhdGlvbldpdGhvdXROYXZpZ2F0aW9uSGFzRm9jdXMgPSBmYWxzZTtcbiAgcHJvdGVjdGVkIGlzQ29hY2hHcmlkRm9jdXNhYmxlID0gZmFsc2U7XG4gIHByb3RlY3RlZCBpc0F1dG9TY3JvbGxpbmcgPSBmYWxzZTtcbiAgcHJvdGVjdGVkIGlzS2V5Ym9hcmROYXZpZ2F0aW9uID0gZmFsc2U7XG4gIHByb3RlY3RlZCBoYXNNdWx0aXBsZURlY2tzID0gZmFsc2U7XG4gIHByb3RlY3RlZCBoYXNTZWF0UmVzZXJ2YXRpb25OYXRpdmVGb2N1cyA9IGZhbHNlO1xuICBwcm90ZWN0ZWQga2V5Ym9hcmROYXZpZ2F0aW9uRXZlbnRzID0ge1xuICAgIEFycm93TGVmdDogJ0Fycm93TGVmdCcsXG4gICAgQXJyb3dSaWdodDogJ0Fycm93UmlnaHQnLFxuICAgIEFycm93VXA6ICdBcnJvd1VwJyxcbiAgICBBcnJvd0Rvd246ICdBcnJvd0Rvd24nLFxuICAgIFRhYjogJ1RhYicsXG4gICAgRW50ZXI6ICdFbnRlcicsXG4gIH0gYXMgY29uc3Q7XG5cbiAgLy8gR3JhcGhpY3MgdGhhdCBzaG91bGQgbm90IGJlIHJlbmRlcmVkIHdpdGggYW4gYXJlYVxuICBwcm90ZWN0ZWQgbm90QXJlYUVsZW1lbnRzID0gW1xuICAgICdEUklWRVJfQVJFQScsXG4gICAgJ0RSSVZFUl9BUkVBX05PX1ZFUlRJQ0FMX1dBTEwnLFxuICAgICdDT0FDSF9QQVNTQUdFJyxcbiAgICAnQ09BQ0hfV0FMTF9OT19QQVNTQUdFJyxcbiAgICAnQ09NUEFSVE1FTlRfUEFTU0FHRScsXG4gICAgJ0NPTVBBUlRNRU5UX1BBU1NBR0VfSElHSCcsXG4gICAgJ0NPTVBBUlRNRU5UX1BBU1NBR0VfTUlERExFJyxcbiAgICAnQ09NUEFSVE1FTlRfUEFTU0FHRV9MT1cnLFxuICAgICdDT01QQVJUTUVOVF9XQUxMJyxcbiAgXTtcblxuICBwcm90ZWN0ZWQgb3ZlckhhbmdpbmdFbGVtZW50SW5mb3JtYXRpb246IHtcbiAgICBjb2FjaElkOiBzdHJpbmc7XG4gICAgb3ZlcmhhbmdpbmdQbGFjZXM6IGJvb2xlYW47XG4gICAgb3ZlcmhhbmdpbmdHcmFwaGljQXJlYXM6IGJvb2xlYW47XG4gIH1bXSA9IFtdO1xuXG4gIHByaXZhdGUgX2lzUnVubmluZ0luaXRQcmVzZWxlY3RDb2FjaEluZGV4ID0gZmFsc2U7XG4gIHByaXZhdGUgX3Njcm9sbFRpbWVvdXQ6IFJldHVyblR5cGU8dHlwZW9mIHNldFRpbWVvdXQ+IHwgdW5kZWZpbmVkO1xuICBwcml2YXRlIF9sYXN0U3RhcnRTY3JvbGxQb3MgPSAtMTtcblxuICBwdWJsaWMgY29uc3RydWN0b3IoKSB7XG4gICAgc3VwZXIoKTtcbiAgICAvLyBBZGQgYmx1ciBldmVudCBsaXN0ZW5lciBvbiB0aGUgZW50aXJlIGNvbXBvbmVudCB0byBkZXRlY3Qgd2hlbiB0aGUgdXNlciBsZWF2ZXMgdGhlIGNvbXBvbmVudFxuICAgIC8vIGJ5IHVzaW5nIHRhYiBuYXZpZ2F0aW9uIG9yIGNsaWNraW5nIG91dHNpZGUgb2YgdGhlIGNvbXBvbmVudC4gSW4gdGhpcyBjYXNlLCB3ZSBjYW4gcmVzZXQgdGhlIHNlbGVjdGVkIGNvYWNoIGFuZCBwbGFjZS5cbiAgICB0aGlzLmFkZEV2ZW50TGlzdGVuZXIoJ2JsdXInLCAoKSA9PiB0aGlzLl9vbkxlYXZlU2VhdFJlc2VydmF0aW9uQ29tcG9uZW50KCkpO1xuICB9XG5cbiAgcHJvdGVjdGVkIG92ZXJyaWRlIHdpbGxVcGRhdGUoY2hhbmdlZFByb3BlcnRpZXM6IFByb3BlcnR5VmFsdWVzPHRoaXM+KTogdm9pZCB7XG4gICAgc3VwZXIud2lsbFVwZGF0ZShjaGFuZ2VkUHJvcGVydGllcyk7XG5cbiAgICBpZiAoY2hhbmdlZFByb3BlcnRpZXMuaGFzKCdzZWF0UmVzZXJ2YXRpb25zJykpIHtcbiAgICAgIHRoaXMuaGFzTXVsdGlwbGVEZWNrcyA9IHRoaXMuc2VhdFJlc2VydmF0aW9ucz8ubGVuZ3RoID4gMTtcblxuICAgICAgdGhpcy5faW5pdFByZXBhcmVTZWF0UmVzZXJ2YXRpb25EYXRhKCk7XG4gICAgICB0aGlzLl9wcmVwYXJlQ29hY2hXaWR0aEFuZEdhcENhbGN1bGF0aW9ucygpO1xuICAgICAgdGhpcy5faW5pdFNlYXRSZXNlcnZhdGlvblBsYWNlU2VsZWN0aW9uKCk7XG4gICAgICB0aGlzLmluaXROYXZpZ2F0aW9uU2VsZWN0aW9uQnlTY3JvbGxFdmVudCgpO1xuICAgIH1cblxuICAgIGlmIChjaGFuZ2VkUHJvcGVydGllcy5oYXMoJ2Jhc2VHcmlkU2l6ZScpKSB7XG4gICAgICB0aGlzLmNvYWNoQm9yZGVyT2Zmc2V0ID0gdGhpcy5jb2FjaEJvcmRlclBhZGRpbmcgLyB0aGlzLmJhc2VHcmlkU2l6ZTtcbiAgICAgIHRoaXMuc3R5bGU/LnNldFByb3BlcnR5KCctLXNiYi1zZWF0LXJlc2VydmF0aW9uLWdyaWQtc2l6ZScsIGAke3RoaXMuYmFzZUdyaWRTaXplfXB4YCk7XG5cbiAgICAgIHRoaXMuaW5pdE5hdmlnYXRpb25TZWxlY3Rpb25CeVNjcm9sbEV2ZW50KCk7XG4gICAgfVxuXG4gICAgLy8gSWYgdGhlIGhlaWdodCBpcyB1c2VkLCB0aGUgYmFzZUdyaWRTaXplIG11c3QgYmUgcmVjYWxjdWxhdGVkXG4gICAgaWYgKGNoYW5nZWRQcm9wZXJ0aWVzLmhhcygnaGVpZ2h0JykgJiYgISF0aGlzLmhlaWdodCkge1xuICAgICAgY29uc3Qgc2VhdFJlc2VydmF0aW9uTGF5ZXIgPSB0aGlzLnNlYXRSZXNlcnZhdGlvbnNbdGhpcy5jdXJyU2VsZWN0ZWREZWNrSW5kZXhdIHx8IG51bGw7XG4gICAgICBpZiAoc2VhdFJlc2VydmF0aW9uTGF5ZXI/LmNvYWNoSXRlbXMubGVuZ3RoKSB7XG4gICAgICAgIHRoaXMuYmFzZUdyaWRTaXplID0gdGhpcy5oZWlnaHQgLyBzZWF0UmVzZXJ2YXRpb25MYXllci5jb2FjaEl0ZW1zWzBdLmRpbWVuc2lvbi5oO1xuICAgICAgICB0aGlzLmNvYWNoQm9yZGVyT2Zmc2V0ID0gdGhpcy5jb2FjaEJvcmRlclBhZGRpbmcgLyB0aGlzLmJhc2VHcmlkU2l6ZTtcbiAgICAgICAgdGhpcy5zdHlsZT8uc2V0UHJvcGVydHkoJy0tc2JiLXNlYXQtcmVzZXJ2YXRpb24tZ3JpZC1zaXplJywgYCR7dGhpcy5iYXNlR3JpZFNpemV9cHhgKTtcblxuICAgICAgICB0aGlzLl9pbml0UHJlcGFyZVNlYXRSZXNlcnZhdGlvbkRhdGEoKTtcbiAgICAgICAgdGhpcy5pbml0TmF2aWdhdGlvblNlbGVjdGlvbkJ5U2Nyb2xsRXZlbnQoKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoY2hhbmdlZFByb3BlcnRpZXMuaGFzKCdhbGlnblZlcnRpY2FsJykgJiYgdGhpcy5hbGlnblZlcnRpY2FsKSB7XG4gICAgICB0aGlzLmluaXROYXZpZ2F0aW9uU2VsZWN0aW9uQnlTY3JvbGxFdmVudCgpO1xuICAgIH1cblxuICAgIGlmIChjaGFuZ2VkUHJvcGVydGllcy5oYXMoJ3ByZXNlbGVjdENvYWNoSW5kZXgnKSkge1xuICAgICAgLy8gc2V0VGltZW91dCBpcyBuZWNlc3NhcnkgYmVjYXVzZSB3aXRob3V0LCBfZ2V0Q29hY2hTY3JvbGxQb3NpdGlvblgoKSB3b3VsZCBmYWlsIHdpdGggTlBFIGJlY2F1c2VcbiAgICAgIC8vIHRoZSBjb2FjaFNjcm9sbEFyZWEgaXMgbm90IHlldCBpbml0aWFsaXplZFxuICAgICAgdGhpcy5faXNSdW5uaW5nSW5pdFByZXNlbGVjdENvYWNoSW5kZXggPSB0cnVlO1xuICAgICAgc2V0VGltZW91dCgoKSA9PiB0aGlzLnNjcm9sbFRvU2VsZWN0ZWROYXZDb2FjaCh0aGlzLnByZXNlbGVjdENvYWNoSW5kZXgpLCAxKTtcbiAgICB9XG4gIH1cblxuICBwcm90ZWN0ZWQgbmF2aWdhdGVCeURpcmVjdGlvbkJ0bihidG5EaXJlY3Rpb246IHN0cmluZyk6IHZvaWQge1xuICAgIHRoaXMudW5mb2N1c1BsYWNlRWxlbWVudCgpO1xuICAgIGxldCBuYXZpZ2F0ZVRvQ29hY2hJbmRleCA9IHRoaXMuY3VyclNlbGVjdGVkQ29hY2hJbmRleDtcbiAgICBpZiAoYnRuRGlyZWN0aW9uID09ICdESVJFQ1RJT05fTEVGVCcgJiYgbmF2aWdhdGVUb0NvYWNoSW5kZXggPiAwKSB7XG4gICAgICBuYXZpZ2F0ZVRvQ29hY2hJbmRleCA9XG4gICAgICAgIHRoaXMuY3VyclNlbGVjdGVkQ29hY2hJbmRleCAhPSAtMSA/IHRoaXMuY3VyclNlbGVjdGVkQ29hY2hJbmRleCAtIDEgOiAwO1xuICAgIH0gZWxzZSBpZiAoXG4gICAgICBidG5EaXJlY3Rpb24gPT0gJ0RJUkVDVElPTl9SSUdIVCcgJiZcbiAgICAgIG5hdmlnYXRlVG9Db2FjaEluZGV4IDxcbiAgICAgICAgdGhpcy5zZWF0UmVzZXJ2YXRpb25zW3RoaXMuY3VyclNlbGVjdGVkRGVja0luZGV4XT8uY29hY2hJdGVtcy5sZW5ndGggLSAxXG4gICAgKSB7XG4gICAgICBuYXZpZ2F0ZVRvQ29hY2hJbmRleCA9XG4gICAgICAgIHRoaXMuY3VyclNlbGVjdGVkQ29hY2hJbmRleCAhPSAtMSA/IHRoaXMuY3VyclNlbGVjdGVkQ29hY2hJbmRleCArIDEgOiAwO1xuICAgIH1cblxuICAgIHRoaXMuc2Nyb2xsVG9TZWxlY3RlZE5hdkNvYWNoKG5hdmlnYXRlVG9Db2FjaEluZGV4KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBEYXRhIGNhbiBiZSBwcmVwYXJlZCBvbmNlIGZvciB0aGUgZW50aXJlIGNvbXBvbmVudFxuICAgKiBpbiBvcmRlciB0byBhdm9pZCByZWN1cnJpbmcgaXRlcmF0aW9uIHByb2Nlc3NlcyBpbiByZW5kZXJpbmcuXG4gICAqL1xuICBwcml2YXRlIF9pbml0UHJlcGFyZVNlYXRSZXNlcnZhdGlvbkRhdGEoKTogdm9pZCB7XG4gICAgdGhpcy5fZGV0ZXJtaW5lQmFzZUZvbnRTaXplKCk7XG5cbiAgICBpZiAodGhpcy5oYXNNdWx0aXBsZURlY2tzKSB7XG4gICAgICAvLyBJZiB0aGVyZSBhcmUgbXVsdGlwbGUgZGVja3MsIHdlIG5lZWQgdG8gY2hlY2tcbiAgICAgIC8vIHdoZXRoZXIgZW1wdHkgY29hY2hlcyBuZWVkIHRvIGJlIGFkZGVkIG9uIGRpZmZlcmVudCBkZWNrIGxldmVsc1xuICAgICAgdGhpcy5faW5pdEVtcHR5Q29hY2hEZWNrT2Zmc2V0cygpO1xuICAgIH1cblxuICAgIHRoaXMuX3ByZXBhcmVDb2FjaEl0ZW1EZXRhaWxzRGF0YSgpO1xuICAgIHRoaXMuX3ByZXBhcmVPcHRpbWl6ZUFyZWFJY29uRGltZW5zaW9uQnlNZWRpYW4oKTtcbiAgfVxuXG4gIC8qKiBJbml0IHNjcm9sbCBldmVudCBoYW5kbGluZyBmb3IgY29hY2ggbmF2aWdhdGlvbiAqL1xuICBwcm90ZWN0ZWQgaW5pdE5hdmlnYXRpb25TZWxlY3Rpb25CeVNjcm9sbEV2ZW50KCk6IHZvaWQge1xuICAgIHRoaXMuY29hY2hTY3JvbGxBcmVhID0gdGhpcy5zaGFkb3dSb290Py5xdWVyeVNlbGVjdG9yKFxuICAgICAgJyNzYmItc3JfX3dyYXBwZXItc2Nyb2xsYXJlYScsXG4gICAgKSBhcyBIVE1MRWxlbWVudDtcbiAgICB0aGlzLm5hdmlnYXRpb25TY3JvbGxBcmVhID0gdGhpcy5zaGFkb3dSb290Py5xdWVyeVNlbGVjdG9yKFxuICAgICAgJyNzYmItc3JfX25hdmlnYXRpb24tbGlzdC1jb2FjaGVzJyxcbiAgICApIGFzIEhUTUxFbGVtZW50O1xuXG4gICAgY29uc3Qgc2VhdFJlc2VydmF0aW9uRGVjayA9IHRoaXMuc2VhdFJlc2VydmF0aW9uc1xuICAgICAgPyB0aGlzLnNlYXRSZXNlcnZhdGlvbnNbdGhpcy5jdXJyU2VsZWN0ZWREZWNrSW5kZXhdXG4gICAgICA6IG51bGw7XG4gICAgaWYgKHNlYXRSZXNlcnZhdGlvbkRlY2sgJiYgc2VhdFJlc2VydmF0aW9uRGVjay5jb2FjaEl0ZW1zLmxlbmd0aCA+IDApIHtcbiAgICAgIC8vIENhbGN1bGF0ZXMgdGhlIGFic29sdXRlIGhlaWdodCBvZiBvbmUgY29hY2ggaW5jbHVkaW5nIGJvcmRlciBwYWRkaW5nXG4gICAgICBjb25zdCBjb2FjaEhlaWdodFdpdGhCb3JkZXJQYWRkaW5nID1cbiAgICAgICAgc2VhdFJlc2VydmF0aW9uRGVjay5jb2FjaEl0ZW1zWzBdLmRpbWVuc2lvbi5oICogdGhpcy5iYXNlR3JpZFNpemUgKyB0aGlzLmNvYWNoQm9yZGVyUGFkZGluZztcblxuICAgICAgLy8gQ2FsY3VsYXRlIGVhY2ggZ2FwIGJldHdlZW4gbXVsdGlwbGUgY29hY2ggdGhlIGRlY2tzLlxuICAgICAgLy8gTm8gZ2FwIGV4aXN0IGlmIGp1c3Qgb25lIGNvYWNoIGRlY2sgZXhpc3QuXG4gICAgICBjb25zdCBnYXBCZXR3ZWVuQ29hY2hEZWNrcyA9ICh0aGlzLnNlYXRSZXNlcnZhdGlvbnMubGVuZ3RoIC0gMSkgKiB0aGlzLmdhcEJldHdlZW5Db2FjaERlY2tzO1xuXG4gICAgICB0aGlzLnN0eWxlPy5zZXRQcm9wZXJ0eShcbiAgICAgICAgJy0tc2JiLXNlYXQtcmVzZXJ2YXRpb24taGVpZ2h0JyxcbiAgICAgICAgYCR7Y29hY2hIZWlnaHRXaXRoQm9yZGVyUGFkZGluZyAqIHRoaXMuc2VhdFJlc2VydmF0aW9ucy5sZW5ndGggKyBnYXBCZXR3ZWVuQ29hY2hEZWNrc31gLFxuICAgICAgKTtcbiAgICAgIHRoaXMuc3R5bGU/LnNldFByb3BlcnR5KCctLXNiYi1zZWF0LXJlc2VydmF0aW9uLWRlY2tzJywgYCR7dGhpcy5zZWF0UmVzZXJ2YXRpb25zLmxlbmd0aH1gKTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5uYXZpZ2F0aW9uU2Nyb2xsQXJlYSkge1xuICAgICAgdGhpcy5zY3JvbGxOYXZpZ2F0aW9uQXJlYURpbSA9IHRoaXMuYWxpZ25WZXJ0aWNhbFxuICAgICAgICA/IHRoaXMubmF2aWdhdGlvblNjcm9sbEFyZWEuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkuaGVpZ2h0XG4gICAgICAgIDogdGhpcy5uYXZpZ2F0aW9uU2Nyb2xsQXJlYS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS53aWR0aDtcblxuICAgICAgLy8gSW5pdCB0aGUgY29hY2hOYXZCdXR0b25EaW0gZGltZW5zaW9uLCB3aGljaCBpcyBuZWVkZWQgdG8gY2FsY3VsYXRlIHRoZSBjb3JyZWN0IHNjcm9sbCBuYXZpZ2F0aW9uIGxhdGVyXG4gICAgICBjb25zdCBuYXZDb2FjaGVzTGlzdCA9IHRoaXMubmF2aWdhdGlvblNjcm9sbEFyZWEucXVlcnlTZWxlY3RvcigndWwgPiBsaScpIGFzIEhUTUxVTGlzdEVsZW1lbnQ7XG4gICAgICBpZiAobmF2Q29hY2hlc0xpc3QpIHtcbiAgICAgICAgY29uc3QgZmlyc3RMaUVsZURpbWVuc2lvbiA9IG5hdkNvYWNoZXNMaXN0Py5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgICAgdGhpcy5jb2FjaE5hdkJ1dHRvbkRpbSA9IHRoaXMuYWxpZ25WZXJ0aWNhbFxuICAgICAgICAgID8gZmlyc3RMaUVsZURpbWVuc2lvbi5oZWlnaHRcbiAgICAgICAgICA6IGZpcnN0TGlFbGVEaW1lbnNpb24ud2lkdGg7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuY29hY2hTY3JvbGxBcmVhICYmIHNlYXRSZXNlcnZhdGlvbkRlY2spIHtcbiAgICAgIC8vIEluaXQgdGhlIHN0YXJ0IG9mZnNldCBmb3IgdGhlIGNhbGN1bGF0aW9uIG9mIHRoZSBjb2FjaCBzY3JvbGwgdHJpZ2dlciBwb3NpdGlvbnNcbiAgICAgIGxldCBjdXJyQ2FsY1RyaWdnZXJQb3MgPSAwO1xuICAgICAgdGhpcy5zY3JvbGxDb2FjaGVzQXJlYVdpZHRoID0gdGhpcy5hbGlnblZlcnRpY2FsXG4gICAgICAgID8gdGhpcy5jb2FjaFNjcm9sbEFyZWEuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkuaGVpZ2h0XG4gICAgICAgIDogdGhpcy5jb2FjaFNjcm9sbEFyZWEuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkud2lkdGg7XG5cbiAgICAgIC8vIFByZWNhbGN1bGF0ZSB0cmlnZ2VyIHNjcm9sbCBwb3NpdGlvbiBhcnJheSBkZXBlbmRzIG9uIGNvYWNoIHdpZHRoXG4gICAgICB0aGlzLnRyaWdnZXJDb2FjaFBvc2l0aW9uc0NvbGxlY3Rpb24gPSBzZWF0UmVzZXJ2YXRpb25EZWNrLmNvYWNoSXRlbXMubWFwKChjb2FjaCkgPT4ge1xuICAgICAgICBjb25zdCBzdGFydFBvc1ggPSBjdXJyQ2FsY1RyaWdnZXJQb3M7XG4gICAgICAgIGNvbnN0IGNvYWNoV2lkdGggPSB0aGlzLmdldENhbGN1bGF0ZWREaW1lbnNpb24oY29hY2guZGltZW5zaW9uKS53O1xuXG4gICAgICAgIC8vIENhbGN1bGF0aW9uIG9mIHRoZSBlbmQgc2Nyb2xsIHRyaWdnZXIgcG9zaXRpb24gb2YgYSBjb2FjaCwgaW5jbHVkaW5nIHRoZSBnYXAgYmV0d2VlbiB0aGUgY29hY2hlc1xuICAgICAgICAvLyBUaGUgZ2FwIGlzIG1heWJlIGFkanVzdGVkIGlmIG92ZXJoYW5naW5nIHBsYWNlcyBvciBncmFwaGljcyBleGlzdFxuICAgICAgICBjb25zdCBjdXJyZW50Q29hY2hPdmVyaGFuZ2luZ0luZm8gPSB0aGlzLm92ZXJIYW5naW5nRWxlbWVudEluZm9ybWF0aW9uLmZpbmQoXG4gICAgICAgICAgKGUpID0+IGUuY29hY2hJZCA9PT0gY29hY2guaWQsXG4gICAgICAgICk7XG4gICAgICAgIGNvbnN0IG92ZXJoYW5naW5nRWxlbWVudHNQcmVzZW50ID1cbiAgICAgICAgICBjdXJyZW50Q29hY2hPdmVyaGFuZ2luZ0luZm8/Lm92ZXJoYW5naW5nUGxhY2VzIHx8XG4gICAgICAgICAgY3VycmVudENvYWNoT3ZlcmhhbmdpbmdJbmZvPy5vdmVyaGFuZ2luZ0dyYXBoaWNBcmVhcztcbiAgICAgICAgY3VyckNhbGNUcmlnZ2VyUG9zICs9XG4gICAgICAgICAgY29hY2hXaWR0aCArXG4gICAgICAgICAgKCFvdmVyaGFuZ2luZ0VsZW1lbnRzUHJlc2VudCA/IHRoaXMuZ2FwQmV0d2VlbkNvYWNoZXMgOiAyICogdGhpcy5nYXBCZXR3ZWVuQ29hY2hlcyk7XG5cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBzdGFydDogc3RhcnRQb3NYLFxuICAgICAgICAgIGVuZDogY3VyckNhbGNUcmlnZ2VyUG9zLFxuICAgICAgICAgIHdpZHRoOiBjb2FjaFdpZHRoLFxuICAgICAgICB9IGFzIENvYWNoU2Nyb2xsVHJpZ2dlclBvaW50O1xuICAgICAgfSk7XG5cbiAgICAgIC8vIFNldCBtYXhpbXVtIGNhbGN1bGF0ZWQgY29hY2ggd2lkdGhcbiAgICAgIHRoaXMubWF4Q2FsY0NvYWNoZXNXaWR0aCA9IGN1cnJDYWxjVHJpZ2dlclBvcyAtIHRoaXMuZ2FwQmV0d2VlbkNvYWNoZXM7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFNjcm9sbCBldmVudCBoYW5kbGVyIG1hbmFnZWQgdGhlIGVuZCBvZiBzY3JvbGxpbmcgaW5zaWRlIHRoZSBjb2FjaCBzY3JvbGwgYXJlYS5cbiAgICogVGltZW91dCBldmVudCBoYW5kbGluZyB0byBjaGVjayBpZiB0aGUgc2Nyb2xsaW5nIGhhcyBiZWVuIGNvbXBsZXRlZC5cbiAgICogSXQgaXMgcmVxdWlyZWQgYmVjYXVzZSB0aGUgU2FmYXJpIGJyb3dzZXIgZG9lcyBub3QgaGFuZGxlIHNjcm9sbGVuZCBldmVudCxcbiAgICogYW5kIHdlIHRoZXJlZm9yZSBpbWl0YXRlIHRoaXMgZXZlbnQgLT4gc2Nyb2xsZW5kLlxuICAgKi9cbiAgQGV2ZW50T3B0aW9ucyh7IHBhc3NpdmU6IHRydWUgfSlcbiAgcHJvdGVjdGVkIGNvYWNoQXJlYVNjcm9sbGVuZCgpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5fc2Nyb2xsVGltZW91dCkge1xuICAgICAgLy8gRmlyc3QsIHdlIGNsZWFyZWQgdGhlIHJlZ2lzdGVyZWQgdGltZW91dCwgYXMgdGhlIHNjcm9sbGluZyBpcyBzdGlsbCBydW5uaW5nXG4gICAgICAvLyBhbmQgdGh1cyB3ZSBwcmV2ZW50IHRoZSBleGVjdXRpb24gb2YgdGhlIF9oYW5kbGVDb2FjaEFyZWFTY3JvbGxlbmRFdmVudCBmdW5jdGlvblxuICAgICAgY2xlYXJUaW1lb3V0KHRoaXMuX3Njcm9sbFRpbWVvdXQpO1xuICAgIH1cbiAgICAvLyBJZiBubyBmdXJ0aGVyIHNjcm9sbCBldmVudCBpcyBmaXJlZCwgdGhlIG5leHQgdGltZW91dCBjYW4gZXhlY3V0ZSB0aGUgaW5uZXIgZnVuY3Rpb24gX2hhbmRsZUNvYWNoQXJlYVNjcm9sbGVuZEV2ZW50IHdpdGhvdXQgY2xlYXJpbmdcbiAgICB0aGlzLl9zY3JvbGxUaW1lb3V0ID0gc2V0VGltZW91dCgoKSA9PiB0aGlzLl9oYW5kbGVDb2FjaEFyZWFTY3JvbGxlbmRFdmVudCgpLCAxNTApO1xuICB9XG5cbiAgLyoqXG4gICAqIElmIG5vIG5hdmlnYXRpb24gZXhpc3RzIChwcm9wZXJ0eSBzZXR0aW5nIC0+IGhhc05hdmlnYXRpb24pIGFuZCBhIHRhYmxlIGNvYWNoIGdldHMgdGhlIGZvY3VzLFxuICAgKiB0aGUgZmlyc3QgcGxhY2UgaW4gdGhlIGNvYWNoIG11c3QgYmUgYXV0b21hdGljYWxseSBwcmVzZWxlY3RlZCB0byBjb250cm9sIHRoZSBwbGFjZSBuYXZpZ2F0aW9uIHZpYSBrZXlib2FyZFxuICAgKlxuICAgKiBAcGFyYW0gZm9jdXNDb2FjaEluZGV4XG4gICAqL1xuICBwcm90ZWN0ZWQgb25Gb2N1c1RhYmxlQ29hY2hBbmRQcmVzZWxlY3RQbGFjZShmb2N1c0NvYWNoSW5kZXg6IG51bWJlcik6IHZvaWQge1xuICAgIGlmICghdGhpcy5zZWF0UmVzZXJ2YXRpb25XaXRob3V0TmF2aWdhdGlvbkhhc0ZvY3VzICYmICF0aGlzLmhhc05hdmlnYXRpb24pIHtcbiAgICAgIHRoaXMuc2VhdFJlc2VydmF0aW9uV2l0aG91dE5hdmlnYXRpb25IYXNGb2N1cyA9IHRydWU7XG4gICAgICB0aGlzLmN1cnJTZWxlY3RlZENvYWNoSW5kZXggPVxuICAgICAgICBmb2N1c0NvYWNoSW5kZXggPT09IDBcbiAgICAgICAgICA/IHRoaXMuZ2V0TmV4dEF2YWlsYWJsZUNvYWNoSW5kZXgoLTEpXG4gICAgICAgICAgOiB0aGlzLmdldFByZXZBdmFpbGFibGVDb2FjaEluZGV4KGZvY3VzQ29hY2hJbmRleCk7XG4gICAgICB0aGlzLnByZXNlbGVjdFBsYWNlSW5Db2FjaCgpO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBXaWxsIGJlIHRyaWdnZXJlZCBieSBmb2N1cyBuYXZpZ2F0aW9uIGRpcmVjdGlvbiAqL1xuICBwcm90ZWN0ZWQgb25Gb2N1c05hdkRpcmVjdGlvbkJ1dHRvbigpOiB2b2lkIHtcbiAgICAvLyBJZiBhbnkgbmF2aWdhdGlvbiBkaXJlY3Rpb24gYnV0dG9uIChyaWdodHxsZWZ0KSBnZXQgdGhlIGZvY3VzLCBzbyB3ZSBoYXZlIG1hbnVhbCByZXNldCB0aGUgcHJldmlvdXMgZm9jdXNDb2FjaEluZGV4LlxuICAgIHRoaXMuZm9jdXNlZENvYWNoSW5kZXggPSAtMTtcbiAgfVxuXG4gIC8qKiBUQUIgS2V5IEV2ZW50IGhhbmRsaW5nIGZvciBDb2FjaCBOYXZpZ2F0aW9uICovXG4gIHByb3RlY3RlZCBvbktleU5hdmlnYXRpb25OYXZDb2FjaEJ1dHRvbihcbiAgICBldmVudDogS2V5Ym9hcmRFdmVudCxcbiAgICBjdXJyTmF2Q29hY2hCdXR0b25JbmRleDogbnVtYmVyLFxuICApOiB2b2lkIHtcbiAgICBpZiAoZXZlbnQua2V5ID09PSB0aGlzLmtleWJvYXJkTmF2aWdhdGlvbkV2ZW50cy5UYWIpIHtcbiAgICAgIHRoaXMuX2hhbmRsZVRhYktleU5hdmlnYXRpb24oZXZlbnQsICduYXZpZ2F0aW9uJywgY3Vyck5hdkNvYWNoQnV0dG9uSW5kZXgpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIEJ5IHVzaW5nIGFueSBvdGhlciBrZXkgKG5vIFRBQikgaW5zaWRlIHRoZSBOYXZpZ2F0aW9uIGFyZWEsIHNvIHdlIGNhbiBoYW5kbGUgdGhpcyBieSB1c2luZyB0aGUgbG9naWMgZnJvbSBrZXlib2FyZFNlYXRtYXBFdmVudEhhbmRsaW5nXG4gICAgaWYgKGlzQXJyb3dLZXlPclBhZ2VLZXlzUHJlc3NlZChldmVudCkpIHtcbiAgICAgIHRoaXMua2V5Ym9hcmRTZWF0bWFwRXZlbnRIYW5kbGluZyhldmVudCk7XG4gICAgfVxuICB9XG5cbiAgLyoqIEdlbmVyYWwgVEFCIEtleSBFdmVudCBoYW5kbGluZyBmb3IgdGFiIG5hdmlnYXRpb24gaW5zaWRlIHRoZSBjb2FjaCBuYXZpZ2F0aW9uIGFyZWEgYW5kIHRoZSBzZWF0bWFwIGFyZWEgKi9cbiAgcHJpdmF0ZSBfaGFuZGxlVGFiS2V5TmF2aWdhdGlvbihcbiAgICBldmVudDogS2V5Ym9hcmRFdmVudCxcbiAgICBldmVudEFyZWE6IHN0cmluZyxcbiAgICBjdXJyVGFiSW5kZXg/OiBudW1iZXIsXG4gICk6IHZvaWQge1xuICAgIGNvbnN0IHByZXNzZWRLZXkgPSBldmVudC5rZXk7XG4gICAgY29uc3QgcHJlc3NlZFNoaWZ0VGFiID0gZXZlbnQuc2hpZnRLZXk7XG5cbiAgICBpZiAocHJlc3NlZEtleSA9PT0gdGhpcy5rZXlib2FyZE5hdmlnYXRpb25FdmVudHMuVGFiKSB7XG4gICAgICAvLyBIYW5kbGUgVEFCIGtleSBldmVudCBuYXZpZ2F0aW9uIGZvciBjb2FjaCBuYXZpZ2F0aW9uIGFyZWEuXG4gICAgICAvLyBGcHIgY29hY2ggbmF2aWdhdGlvbiB3ZSBqdXN0IGNvbnRyb2wgdGhlIGZvY3VzIGluZGV4IHRvIHZpc3VhbGl6ZSBmb2N1cyBzdHlsZSBmb3IgbmF2IGNvYWNoIGJ1dHRvblxuICAgICAgaWYgKGV2ZW50QXJlYSA9PSAnbmF2aWdhdGlvbicpIHtcbiAgICAgICAgaWYgKGN1cnJUYWJJbmRleCA9PSB0aGlzLmN1cnJTZWxlY3RlZENvYWNoSW5kZXgpIHtcbiAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAhdGhpcy5jdXJyU2VsZWN0ZWRQbGFjZSB8fFxuICAgICAgICAgICAgIXByZXNzZWRTaGlmdFRhYiB8fFxuICAgICAgICAgICAgdGhpcy5jb2FjaEl0ZW1EZXRhaWxzRWxlbWVudHNbY3VyclRhYkluZGV4XS5pc0RyaXZlckFyZWEgfHxcbiAgICAgICAgICAgIHRoaXMuZm9jdXNlZENvYWNoSW5kZXggPT0gLTFcbiAgICAgICAgICApIHtcbiAgICAgICAgICAgIHRoaXMuZm9jdXNlZENvYWNoSW5kZXggPSBjdXJyVGFiSW5kZXg7XG4gICAgICAgICAgfSBlbHNlIGlmIChwcmVzc2VkU2hpZnRUYWIgJiYgdGhpcy5jdXJyU2VsZWN0ZWRQbGFjZSkge1xuICAgICAgICAgICAgLy9JZiB0aGUgRm9yIGJhY2sgdGFiYmluZywgd2UganVtcFxuICAgICAgICAgICAgdGhpcy5mb2N1c2VkQ29hY2hJbmRleCA9IC0xO1xuICAgICAgICAgICAgdGhpcy5mb2N1c1BsYWNlRWxlbWVudCh0aGlzLmN1cnJTZWxlY3RlZFBsYWNlKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhpcy5mb2N1c2VkQ29hY2hJbmRleCA9IGN1cnJUYWJJbmRleCE7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLl9zY3JvbGxUb1NlbGVjdGVkTmF2aWdhdGlvbkJ1dHRvbihjdXJyVGFiSW5kZXghKTtcbiAgICAgIH1cbiAgICAgIC8vIEhhbmRsZSBUQUIga2V5IGV2ZW50IG5hdmlnYXRpb24gZm9yIHNlYXRtYXAgYXJlYVxuICAgICAgZWxzZSBpZiAoZXZlbnRBcmVhID09ICdzZWF0bWFwJykge1xuICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICBpZiAocHJlc3NlZFNoaWZ0VGFiKSB7XG4gICAgICAgICAgdGhpcy5fbmF2aWdhdGVDb2FjaE5hdmlnYXRpb25CeUtleWJvYXJkKCdQUkVWX1RBQicpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRoaXMuX25hdmlnYXRlQ29hY2hOYXZpZ2F0aW9uQnlLZXlib2FyZCgnTkVYVF9UQUInKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBJbml0aWFsaXNhdGlvbiBvZiBLZXlib2FyZCBTZWF0bWFwIGV2ZW50IGhhbmRsaW5nIHRvIG5hdmlnYXRpb24gYmV0d2VlbiBlYWNoIHBsYWNlcyBpbnNpZGUgYSBzZWxlY3RlZCBjb2FjaCBieSB1c2luZyBbYXJyb3ddIGtleXMuXG4gICAqIFdpdGggdGhlIFtUQUJdIGtleSB0aGUgdXNlciBuYXZpZ2F0aW9uIGdvZXMgdG8gdGhlIG5leHQgY29hY2ggbmF2aWdhdGlvbiBlbGVtZW50IGFuZCB0aGUgY3VycmVudGx5IHNlbGVjdGVkIHBsYWNlIGlzIGF1dG9tYXRpY2FsbHkgcmVzZXQuXG4gICAqL1xuICBwcm90ZWN0ZWQga2V5Ym9hcmRTZWF0bWFwRXZlbnRIYW5kbGluZyhldmVudDogS2V5Ym9hcmRFdmVudCk6IHZvaWQge1xuICAgIGNvbnN0IGlzVGFiTmV4dCA9IGV2ZW50LmtleSA9PT0gdGhpcy5rZXlib2FyZE5hdmlnYXRpb25FdmVudHMuVGFiO1xuICAgIGNvbnN0IGlzVGFiUHJldiA9IGV2ZW50LnNoaWZ0S2V5ICYmIGlzVGFiTmV4dDtcblxuICAgIC8vIElmIG5vIG5hdmlnYXRpb24gZXhpc3QgYW5kIHRoZSBmaXJzdCBvciBsYXN0IGNvYWNoIGlzIHNlbGVjdGVkLCB0aGUgdGhlIHVzZSB0cmllcyB0byBsZWF2ZSB0aGUgc2VhdCByZXNlcnZhdGlvbiBjb21wb25lbnQgYnkgdXNpbmcgdGFiLFxuICAgIC8vIHNvIHdlIGNhbiByZXR1cm4gaGVyZSBhbmQgYWxsb3cgdGhlIG5hdGl2ZSBmb2N1cyB0byBsZWF2ZSB0aGUgY29tcG9uZW50LlxuICAgIGlmIChcbiAgICAgICghdGhpcy5oYXNOYXZpZ2F0aW9uICYmIHRoaXMuY3VyclNlbGVjdGVkQ29hY2hJbmRleCA9PT0gMCAmJiBpc1RhYlByZXYpIHx8XG4gICAgICAodGhpcy5jdXJyU2VsZWN0ZWRDb2FjaEluZGV4ID09PSB0aGlzLmNvYWNoSXRlbURldGFpbHNFbGVtZW50cy5sZW5ndGggLSAxICYmIGlzVGFiTmV4dClcbiAgICApIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBwcmVzc2VkS2V5ID0gZXZlbnQua2V5O1xuICAgIHRoaXMucHJldmVudENvYWNoU2Nyb2xsQnlQbGFjZUNsaWNrID0gZmFsc2U7XG4gICAgLy8gQ2hlY2sgYW55IGtleWJvYXJkIGV2ZW50IHdhcyB0cmlnZ2VyZWQgaW5zaWRlIHRoZSBzZWF0IHJlc2VydmF0aW9uIGNvbXBvbmVudCxcbiAgICAvLyBzbyB3ZSBjYW4gc2F5IHRoZSBuYXRpdmUgYnJvd3NlciBmb2N1cyBsaWVzIG9uIHRoZSBjb21wb25lbnRcbiAgICBpZiAoIXRoaXMuaGFzU2VhdFJlc2VydmF0aW9uTmF0aXZlRm9jdXMgJiYgKGlzVGFiTmV4dCB8fCBpc1RhYlByZXYpKSB7XG4gICAgICB0aGlzLmhhc1NlYXRSZXNlcnZhdGlvbk5hdGl2ZUZvY3VzID0gdHJ1ZTtcbiAgICB9XG5cbiAgICAvLyBJZiBhbnkgcGxhY2UgaXMgc2VsZWN0ZWQgYW5kIFRBQiBLZXkgY29tYmluYXRpb24gaXN0IHByZXNzZWQsXG4gICAgLy8gdGhlbiB3ZSBoYW5kbGUgdGhlIG5leHQgb3IgcHJldmlvdXMgY29hY2ggc2VsZWN0aW9uXG4gICAgaWYgKGlzVGFiTmV4dCkge1xuICAgICAgdGhpcy5faGFuZGxlVGFiS2V5TmF2aWdhdGlvbihldmVudCwgJ3NlYXRtYXAnKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBBcnJvdyBLZXlib2FyZCBuYXZpZ2F0aW9uIHRvIGNvbnRyb2wgcGxhY2VzIGluc2lkZSB0aGUgc2VhdG1hcFxuICAgIGlmICh0aGlzLmN1cnJTZWxlY3RlZENvYWNoSW5kZXggIT09IC0xICYmIGlzQXJyb3dLZXlPclBhZ2VLZXlzUHJlc3NlZChldmVudCkpIHtcbiAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cbiAgICAgIHN3aXRjaCAocHJlc3NlZEtleSkge1xuICAgICAgICBjYXNlIHRoaXMua2V5Ym9hcmROYXZpZ2F0aW9uRXZlbnRzLkFycm93TGVmdDpcbiAgICAgICAgICB7XG4gICAgICAgICAgICBjb25zdCBwcmVzc2VkTGVmdEtleU1hcHBpbmc6IHN0cmluZyA9IHRoaXMuYWxpZ25WZXJ0aWNhbFxuICAgICAgICAgICAgICA/IHRoaXMua2V5Ym9hcmROYXZpZ2F0aW9uRXZlbnRzLkFycm93RG93blxuICAgICAgICAgICAgICA6IHByZXNzZWRLZXk7XG4gICAgICAgICAgICB0aGlzLl9uYXZpZ2F0ZVRvUGxhY2VCeUtleWJvYXJkKHByZXNzZWRMZWZ0S2V5TWFwcGluZyk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIHRoaXMua2V5Ym9hcmROYXZpZ2F0aW9uRXZlbnRzLkFycm93UmlnaHQ6XG4gICAgICAgICAge1xuICAgICAgICAgICAgY29uc3QgcHJlc3NlZFJpZ2h0S2V5TWFwcGluZzogc3RyaW5nID0gdGhpcy5hbGlnblZlcnRpY2FsXG4gICAgICAgICAgICAgID8gdGhpcy5rZXlib2FyZE5hdmlnYXRpb25FdmVudHMuQXJyb3dVcFxuICAgICAgICAgICAgICA6IHByZXNzZWRLZXk7XG4gICAgICAgICAgICB0aGlzLl9uYXZpZ2F0ZVRvUGxhY2VCeUtleWJvYXJkKHByZXNzZWRSaWdodEtleU1hcHBpbmcpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSB0aGlzLmtleWJvYXJkTmF2aWdhdGlvbkV2ZW50cy5BcnJvd1VwOlxuICAgICAgICAgIHtcbiAgICAgICAgICAgIGNvbnN0IHByZXNzZWRVcEtleU1hcHBpbmc6IHN0cmluZyA9IHRoaXMuYWxpZ25WZXJ0aWNhbFxuICAgICAgICAgICAgICA/IHRoaXMua2V5Ym9hcmROYXZpZ2F0aW9uRXZlbnRzLkFycm93TGVmdFxuICAgICAgICAgICAgICA6IHByZXNzZWRLZXk7XG4gICAgICAgICAgICB0aGlzLl9uYXZpZ2F0ZVRvUGxhY2VCeUtleWJvYXJkKHByZXNzZWRVcEtleU1hcHBpbmcpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSB0aGlzLmtleWJvYXJkTmF2aWdhdGlvbkV2ZW50cy5BcnJvd0Rvd246XG4gICAgICAgICAge1xuICAgICAgICAgICAgY29uc3QgcHJlc3NlZERvd25LZXlNYXBwaW5nOiBzdHJpbmcgPSB0aGlzLmFsaWduVmVydGljYWxcbiAgICAgICAgICAgICAgPyB0aGlzLmtleWJvYXJkTmF2aWdhdGlvbkV2ZW50cy5BcnJvd1JpZ2h0XG4gICAgICAgICAgICAgIDogcHJlc3NlZEtleTtcbiAgICAgICAgICAgIHRoaXMuX25hdmlnYXRlVG9QbGFjZUJ5S2V5Ym9hcmQocHJlc3NlZERvd25LZXlNYXBwaW5nKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFNlbGVjdHMgYSBwbGFjZSBpbnNpZGUgdGhlIGNvYWNoIGlmIG5hdmlnYXRlZCB2aWEga2V5Ym9hcmQsXG4gICAqIG90aGVyd2lzZSB0aGUgY29hY2ggZ3JpZCBpcyBzZWxlY3RlZCAobmVjZXNzYXJ5IGZvciBTY3JlZW5SZWFkZXIpXG4gICAqL1xuICBwcm90ZWN0ZWQgcHJlc2VsZWN0UGxhY2VJbkNvYWNoKCk6IHZvaWQge1xuICAgIC8vIE5vIHByZXNlbGVjdCBwbGFjZSBieSBtYW51YWwgc2VhdG1hcCBzY3JvbGxpbmdcbiAgICBpZiAoIXRoaXMuaXNBdXRvU2Nyb2xsaW5nKSByZXR1cm47XG5cbiAgICAvLyBObyBhdXRvIHBsYWNlIHByZXNlbGVjdGlvbiBieSBydW5uaW5nIHRoZSBwcmVzZWxlY3QgY29hY2ggaW5kZXhcbiAgICBpZiAodGhpcy5faXNSdW5uaW5nSW5pdFByZXNlbGVjdENvYWNoSW5kZXgpIHtcbiAgICAgIHRoaXMuX2lzUnVubmluZ0luaXRQcmVzZWxlY3RDb2FjaEluZGV4ID0gZmFsc2U7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gRm9yIERyaXZlckFyZWEgb3IgRW1wdHkgY29hY2ggKG5vIHBsYWNlcyksIG5vIHBsYWNlIGlzIHNlbGVjdGFibGUsIHNvIHdlIHJldHVybiBkaXJlY3RseVxuICAgIGlmIChcbiAgICAgIHRoaXMuY29hY2hJdGVtRGV0YWlsc0VsZW1lbnRzW3RoaXMuY3VyclNlbGVjdGVkQ29hY2hJbmRleF0gJiZcbiAgICAgIHRoaXMuY29hY2hJdGVtRGV0YWlsc0VsZW1lbnRzW3RoaXMuY3VyclNlbGVjdGVkQ29hY2hJbmRleF0uaXNEcml2ZXJBcmVhXG4gICAgKSB7XG4gICAgICB0aGlzLl9zZXRGb2N1c1RvU2VsZWN0ZWRDb2FjaEdyaWQoKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBPbmx5IHdoZW4ga2V5Ym9hcmQgbmF2aWdhdGlvbiBpcyB1c2VkIGFuZCBjb2FjaGVzIGFyZSBzY3JvbGxlZCBieSBhdXRvIHNjcm9sbGluZyxcbiAgICAvLyB0aGVuIHdlIGNhbiBzZXQgdGhlIGZvY3VzIG9uIHRoZSBmaXJzdCBwbGFjZSBpbiB0aGUgY29hY2guXG4gICAgaWYgKHRoaXMuaXNLZXlib2FyZE5hdmlnYXRpb24gJiYgdGhpcy5pc0F1dG9TY3JvbGxpbmcpIHtcbiAgICAgIGNvbnN0IGNsb3Nlc3RQbGFjZSA9IHRoaXMuX2dldENsb3Nlc3RQbGFjZUJ5S2V5RGlyZWN0aW9uKCk7XG4gICAgICAvL0lmIGNsb3Nlc3RQbGFjZSBleGlzdCwgd2UgaGF2ZSB0byB1bmZvY3VzIHByZXZpb3VzIGZvY3VzZWQgcGxhY2VcbiAgICAgIGlmIChjbG9zZXN0UGxhY2UpIHtcbiAgICAgICAgdGhpcy51bmZvY3VzUGxhY2VFbGVtZW50KCk7XG4gICAgICAgIHRoaXMuZm9jdXNQbGFjZUVsZW1lbnQoY2xvc2VzdFBsYWNlKTtcbiAgICAgICAgdGhpcy5mb2N1c2VkQ29hY2hJbmRleCA9IC0xO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gSWYgYSBjb2FjaCB3YXMgc2VsZWN0ZWQgd2l0aCBubyBwbGFjZXMsIHRoZW4gd2UgaGF2ZSB0byBmb2N1cyB0aGUgY29hY2hHcmlkXG4gICAgICAgIHRoaXMuX3NldEZvY3VzVG9TZWxlY3RlZENvYWNoR3JpZCgpO1xuICAgICAgfVxuICAgIH1cbiAgICAvLyBJbiBjYXNlcyB3aGVyZSB0aGUgcHJlc2VsZWN0aW9uIGZ1bmN0aW9uIGlzIHRyaWdnZXJlZCBieSBub3JtYWwgY2xpY2tpbmcgb3IgdmlhIHNjcmVlbiByZWFkZXIgdmlhIHRhYixcbiAgICAvLyB3ZSBvbmx5IGZvY3VzIHRoZSB0YWJsZSB3aXRob3V0IGRpcmVjdGx5IGZvY3VzaW5nIHRoZSBwbGFjZS5cbiAgICBlbHNlIHtcbiAgICAgIHRoaXMudW5mb2N1c1BsYWNlRWxlbWVudCgpO1xuXG4gICAgICB0aGlzLmlzQ29hY2hHcmlkRm9jdXNhYmxlID0gdHJ1ZTtcbiAgICAgIHRoaXMuX3NldEZvY3VzVG9TZWxlY3RlZENvYWNoR3JpZCgpO1xuICAgIH1cbiAgfVxuXG4gIHByb3RlY3RlZCBzY3JvbGxUb1NlbGVjdGVkTmF2Q29hY2goc2VsZWN0ZWROYXZDb2FjaEluZGV4OiBudW1iZXIpOiB2b2lkIHtcbiAgICBpZiAoXG4gICAgICB0aGlzLl9pc1ZhbGlkQ29hY2hJbmRleChzZWxlY3RlZE5hdkNvYWNoSW5kZXgpICYmXG4gICAgICBzZWxlY3RlZE5hdkNvYWNoSW5kZXggIT09IHRoaXMuY3VyclNlbGVjdGVkQ29hY2hJbmRleFxuICAgICkge1xuICAgICAgdGhpcy5ob3ZlcmVkQ29hY2hJbmRleCA9IHNlbGVjdGVkTmF2Q29hY2hJbmRleDtcbiAgICAgIHRoaXMuaXNBdXRvU2Nyb2xsaW5nID0gdHJ1ZTtcbiAgICAgIHRoaXMuaXNDb2FjaEdyaWRGb2N1c2FibGUgPSB0cnVlO1xuICAgICAgdGhpcy5jdXJyU2VsZWN0ZWRDb2FjaEluZGV4ID0gc2VsZWN0ZWROYXZDb2FjaEluZGV4O1xuICAgICAgdGhpcy5jdXJyU2VsZWN0ZWREZWNrSW5kZXggPSB0aGlzLl9nZXRFeGlzdGluZ0NvYWNoRGVja0luZGV4KCk7XG4gICAgICB0aGlzLl9zZXRTY3JvbGxEaXJlY3Rpb25CeUNvYWNoSW5kZXgoKTtcblxuICAgICAgY29uc3Qgc2Nyb2xsVG9Db2FjaFBvc1ggPSB0aGlzLl9nZXRDb2FjaFNjcm9sbFBvc2l0aW9uWCgpO1xuICAgICAgY29uc3QgaXNTZWxlY3RlZENvYWNoSW5kZXhTY3JvbGxhYmxlID1cbiAgICAgICAgdGhpcy5zZWxlY3RlZENvYWNoSW5kZXggIT09IC0xIHx8IHRoaXMuY3VyclNlbGVjdGVkQ29hY2hJbmRleCA+IDA7XG5cbiAgICAgIC8vIENoZWNrcyB3aGV0aGVyIHRoZSBjdXJyZW50IHNjcm9sbCBwb3NpdGlvbiBhbGxvd3Mgc2Nyb2xsaW5nIHRvIHRoZSBuZXh0IHdhZ29uIG9yIG5vdFxuICAgICAgaWYgKGlzU2VsZWN0ZWRDb2FjaEluZGV4U2Nyb2xsYWJsZSAmJiB0aGlzLl9pc1Njcm9sbGFibGVUb1NlbGVjdGVkQ29hY2goKSkge1xuICAgICAgICB0aGlzLl9sYXN0U3RhcnRTY3JvbGxQb3MgPSB0aGlzLmNvYWNoU2Nyb2xsQXJlYS5zY3JvbGxMZWZ0O1xuICAgICAgICB0aGlzLmNvYWNoU2Nyb2xsQXJlYS5zY3JvbGxUbyh7XG4gICAgICAgICAgdG9wOiB0aGlzLmFsaWduVmVydGljYWwgPyBzY3JvbGxUb0NvYWNoUG9zWCA6IDAsXG4gICAgICAgICAgbGVmdDogdGhpcy5hbGlnblZlcnRpY2FsID8gMCA6IHNjcm9sbFRvQ29hY2hQb3NYLFxuICAgICAgICAgIGJlaGF2aW9yOiAnc21vb3RoJyxcbiAgICAgICAgfSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLnVwZGF0ZUN1cnJlbnRTZWxlY3RlZENvYWNoKCk7XG4gICAgICB9XG5cbiAgICAgIC8vIEF1dG9tYXRpYyBzY3JvbGxpbmcgdG8gdGhlIHNlbGVjdGVkIGNvYWNoIGluIHRoZSBtYWluIG5hdmlnYXRpb25cbiAgICAgIHRoaXMuX3Njcm9sbFRvU2VsZWN0ZWROYXZpZ2F0aW9uQnV0dG9uKHNlbGVjdGVkTmF2Q29hY2hJbmRleCk7XG4gICAgfVxuICB9XG5cbiAgcHJvdGVjdGVkIGZvY3VzUGxhY2VFbGVtZW50KHBsYWNlOiBQbGFjZSB8IG51bGwpOiB2b2lkIHtcbiAgICB0aGlzLnVuZm9jdXNQbGFjZUVsZW1lbnQoKTtcbiAgICBpZiAocGxhY2UpIHtcbiAgICAgIHRoaXMuY3VyclNlbGVjdGVkUGxhY2UgPSBwbGFjZTtcbiAgICAgIHRoaXMuX3NldEN1cnJTZWxlY3RlZFBsYWNlRWxlbWVudElkKHBsYWNlKTtcblxuICAgICAgY29uc3Qgc2VsZWN0ZWRQbGFjZUVsZW1lbnQgPSB0aGlzLl9nZXRQbGFjZUh0bWxFbGVtZW50KCk7XG4gICAgICBpZiAoc2VsZWN0ZWRQbGFjZUVsZW1lbnQpIHtcbiAgICAgICAgc2VsZWN0ZWRQbGFjZUVsZW1lbnQuc2V0QXR0cmlidXRlKCdrZXlmb2N1cycsICdmb2N1cycpO1xuXG4gICAgICAgIC8vVHJ5IHRvIHNjcm9sbCBmb2N1c2VkIHBsYWNlIGludG8gdGhlIHZpZXdwb3J0XG4gICAgICAgIGNvbnN0IGRlbGF5U2Nyb2xsSW5WaWV3cG9ydCA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgIGNvbnN0IHBsYWNlSWQgPSB0aGlzLmdldFBsYWNlRWxlbWVudElkKFxuICAgICAgICAgICAgdGhpcy5jdXJyU2VsZWN0ZWREZWNrSW5kZXgsXG4gICAgICAgICAgICB0aGlzLmN1cnJTZWxlY3RlZENvYWNoSW5kZXgsXG4gICAgICAgICAgICBwbGFjZS5udW1iZXIsXG4gICAgICAgICAgKTtcbiAgICAgICAgICB0aGlzLl9zY3JvbGxQbGFjZUludG9OZWFyZXN0Vmlld3BvcnQocGxhY2VJZCk7XG4gICAgICAgICAgY2xlYXJUaW1lb3V0KGRlbGF5U2Nyb2xsSW5WaWV3cG9ydCk7XG4gICAgICAgIH0sIDApO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHByb3RlY3RlZCB1bmZvY3VzUGxhY2VFbGVtZW50KCk6IHZvaWQge1xuICAgIGNvbnN0IHNlbGVjdGVkUGxhY2VFbGVtZW50ID0gdGhpcy5fZ2V0UGxhY2VIdG1sRWxlbWVudCgpO1xuICAgIGlmIChzZWxlY3RlZFBsYWNlRWxlbWVudCkge1xuICAgICAgc2VsZWN0ZWRQbGFjZUVsZW1lbnQuc2V0QXR0cmlidXRlKCdrZXlmb2N1cycsICd1bmZvY3VzJyk7XG4gICAgICB0aGlzLl9zZXRDdXJyU2VsZWN0ZWRQbGFjZUVsZW1lbnRJZChudWxsKTtcbiAgICAgIHRoaXMuY3VyclNlbGVjdGVkUGxhY2UgPSBudWxsO1xuICAgIH1cbiAgfVxuXG4gIHByb3RlY3RlZCBnZXRDYWxjdWxhdGVkRGltZW5zaW9uKFxuICAgIGVsZW1lbnREaW1lbnNpb246IEVsZW1lbnREaW1lbnNpb24sXG4gICAgY29hY2hEaW1lbnNpb24/OiBFbGVtZW50RGltZW5zaW9uLFxuICAgIGlzT3JpZ2luSGVpZ2h0PzogYm9vbGVhbixcbiAgICBpc1N0cmV0Y2hIZWlnaHQ/OiBib29sZWFuLFxuICApOiBFbGVtZW50RGltZW5zaW9uIHtcbiAgICBpZiAoY29hY2hEaW1lbnNpb24gJiYgIWlzT3JpZ2luSGVpZ2h0KSB7XG4gICAgICAvLyBTaW5jZSB0aGUgaGVpZ2h0IG9mIHRoZSBjb2FjaCBoYXMgYmVlbiB2aXN1YWxseSBleHBhbmRlZCB0byBtYWludGFpbiBhIGRpc3RhbmNlIGJldHdlZW4gdGhlIGJvcmRlciBvZiB0aGUgY29hY2ggYW5kIHRoZSBwbGFjZXMsXG4gICAgICAvLyBzb21lIGdyYXBoaWNzIG11c3QgYWxzbyBiZSBhZGFwdGVkIHRvIHRoZSBoZWlnaHQsIHdoaWNoIGVuZCB3aXRoIHRoZSBib3JkZXJzIG9mIHRoZSBjb2FjaFxuICAgICAgZWxlbWVudERpbWVuc2lvbi5oICs9IHRoaXMuY29hY2hCb3JkZXJPZmZzZXQgKiAyO1xuICAgIH1cblxuICAgIGlmIChpc1N0cmV0Y2hIZWlnaHQpIHtcbiAgICAgIC8vIEluIHRoZSBjYXNlIG9mIGdyYXBoaWNzIGFyZSBhc3NpZ25lZCBkaXJlY3RseSBhdCB0aGUgYm9yZGVyIG9mIHRoZSBjb2FjaCxcbiAgICAgIC8vIHRoZXNlIGdyYXBoaWNzIG11c3QgYmUgZXhwYW5kZWQgaW4gaGVpZ2h0IGJ5IGEgY29hY2hCb3JkZXJPZmZzZXQgaW4gb3JkZXIgdG8gcmVhY2ggdGhlaXIgb3JpZ2luYWwgdmlzdWFsIHBvc2l0aW9uXG4gICAgICBlbGVtZW50RGltZW5zaW9uLmggKz0gdGhpcy5jb2FjaEJvcmRlck9mZnNldDtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgdzogdGhpcy5iYXNlR3JpZFNpemUgKiBlbGVtZW50RGltZW5zaW9uLncsXG4gICAgICBoOiB0aGlzLmJhc2VHcmlkU2l6ZSAqIGVsZW1lbnREaW1lbnNpb24uaCxcbiAgICB9O1xuICB9XG5cbiAgcHJvdGVjdGVkIGdldENhbGN1bGF0ZWRQb3NpdGlvbihcbiAgICBlbGVtZW50UG9zaXRpb246IEVsZW1lbnRQb3NpdGlvbixcbiAgICBlbGVtZW50RGltZW5zaW9uPzogRWxlbWVudERpbWVuc2lvbixcbiAgICBjb2FjaERpbWVuc2lvbj86IEVsZW1lbnREaW1lbnNpb24sXG4gICAgaXNPcmlnaW5IZWlnaHQ/OiBib29sZWFuLFxuICApOiBFbGVtZW50UG9zaXRpb24ge1xuICAgIGlmIChjb2FjaERpbWVuc2lvbiAmJiBlbGVtZW50RGltZW5zaW9uKSB7XG4gICAgICBjb25zdCBlbmRQb3NIZWlnaHQgPSBpc09yaWdpbkhlaWdodFxuICAgICAgICA/IGNvYWNoRGltZW5zaW9uLmhcbiAgICAgICAgOiBjb2FjaERpbWVuc2lvbi5oICsgdGhpcy5jb2FjaEJvcmRlck9mZnNldDtcbiAgICAgIC8vIElmIHRoZSBvcmlnaW5hbCBlbGVtZW50IGlzIHBvc2l0aW9uZWQgYXQgdGhlIHRvcCBvciBib3R0b20gb2YgdGhlIGNvYWNoLCB3ZSBuZWVkIHRvIHJlY2FsY3VsYXRlIHRoZSBZIGNvb3JkaW5hdGUgd2l0aCB0aGUgYWRkaXRpb25hbCBib3JkZXIgcGFkZGluZ1xuICAgICAgaWYgKGVsZW1lbnRQb3NpdGlvbi55ID09PSAwKSB7XG4gICAgICAgIGVsZW1lbnRQb3NpdGlvbi55IC09IHRoaXMuY29hY2hCb3JkZXJPZmZzZXQ7XG4gICAgICB9IGVsc2UgaWYgKGVsZW1lbnRQb3NpdGlvbi55ICsgZWxlbWVudERpbWVuc2lvbi5oID09PSBlbmRQb3NIZWlnaHQpIHtcbiAgICAgICAgZWxlbWVudFBvc2l0aW9uLnkgKz0gdGhpcy5jb2FjaEJvcmRlck9mZnNldDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgeDogdGhpcy5iYXNlR3JpZFNpemUgKiBlbGVtZW50UG9zaXRpb24ueCxcbiAgICAgIHk6IHRoaXMuYmFzZUdyaWRTaXplICogZWxlbWVudFBvc2l0aW9uLnksXG4gICAgICB6OiBlbGVtZW50UG9zaXRpb24ueixcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIGRldGVjdHMgaWYgYSAoZ3JhcGhpY2FsKSBlbGVtZW50IGlzIG9uIHRoZSBib3JkZXIgd2l0aCBpdHMgcG9zaXRpb24gKHVwcGVyIG9yIGxvd2VyIGJvcmRlcikuXG4gICAqIEBwYXJhbSBiYXNlRWxlbWVudFxuICAgKiBAcGFyYW0gY29hY2hEaW1lbnNpb25cbiAgICogQHByb3RlY3RlZFxuICAgKi9cbiAgcHJvdGVjdGVkIGlzRWxlbWVudERpcmVjdGx5T25Cb3JkZXIoXG4gICAgYmFzZUVsZW1lbnQ6IEJhc2VFbGVtZW50LFxuICAgIGNvYWNoRGltZW5zaW9uOiBFbGVtZW50RGltZW5zaW9uLFxuICApOiBib29sZWFuIHtcbiAgICByZXR1cm4gKFxuICAgICAgYmFzZUVsZW1lbnQucG9zaXRpb24ueSA9PT0gMCB8fFxuICAgICAgYmFzZUVsZW1lbnQucG9zaXRpb24ueSArIGJhc2VFbGVtZW50LmRpbWVuc2lvbi5oID09PSBjb2FjaERpbWVuc2lvbi5oXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb3VudHMgYWxsIGF2YWlsYWJsZSBzZWF0cyB0b2dldGhlciBkZXBlbmRpbmcgb24gdGhlIHNlYXQgdHlwZVxuICAgKlxuICAgKiBAcGFyYW0gcGxhY2VzXG4gICAqIEByZXR1cm5zIEFuIE9iamVjdCB3aXRoIGNvdW50IG9mIGZyZWUgc2VhdHMgYW5kIGZyZWUgYmljeWNsZSBwbGFjZXNcbiAgICovXG4gIHByb3RlY3RlZCBnZXRBdmFpbGFibGVGcmVlUGxhY2VzTnVtRnJvbUNvYWNoKFxuICAgIHBsYWNlczogUGxhY2VbXSB8IHVuZGVmaW5lZCxcbiAgKTogQ29hY2hOdW1iZXJPZkZyZWVQbGFjZXMge1xuICAgIGNvbnN0IGFjY3VtdWxhdG9yOiBDb2FjaE51bWJlck9mRnJlZVBsYWNlcyA9IHsgc2VhdHM6IDAsIGJpY3ljbGVzOiAwIH07XG4gICAgY29uc3QgZnJlZVBsYWNlcyA9IHBsYWNlcz8ucmVkdWNlKChhY2N1bXVsYXRvciwgY3VyclBsYWNlOiBQbGFjZSkgPT4ge1xuICAgICAgaWYgKGN1cnJQbGFjZS5zdGF0ZSAhPT0gJ0ZSRUUnKSB7XG4gICAgICAgIHJldHVybiBhY2N1bXVsYXRvcjtcbiAgICAgIH1cbiAgICAgIC8vIENvdW50IHVwIGRlcGVuZGluZyBvbiBzZWF0IHR5cGVcbiAgICAgIGlmIChjdXJyUGxhY2UudHlwZSA9PT0gJ1NFQVQnKSB7XG4gICAgICAgIGFjY3VtdWxhdG9yLnNlYXRzKys7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBhY2N1bXVsYXRvci5iaWN5Y2xlcysrO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGFjY3VtdWxhdG9yO1xuICAgIH0sIGFjY3VtdWxhdG9yKTtcbiAgICByZXR1cm4gZnJlZVBsYWNlcyA/IGZyZWVQbGFjZXMgOiBhY2N1bXVsYXRvcjtcbiAgfVxuXG4gIC8qKlxuICAgKiBBdCB0aGUgZW5kIG9mIGEgc2Nyb2xsIEV2ZW50IGZyb20gdGhlIGNvYWNoIHNjcm9sbGFibGUgYXJlYSxcbiAgICogdGhlIHJlYWNoZWQgY29hY2ggaXMgbWFya2VkIGFzIHNlbGVjdGVkXG4gICAqL1xuICBwcml2YXRlIF9oYW5kbGVDb2FjaEFyZWFTY3JvbGxlbmRFdmVudCgpOiB2b2lkIHtcbiAgICBjb25zdCBmaW5kU2Nyb2xsQ29hY2hJbmRleCA9IHRoaXMuaXNBdXRvU2Nyb2xsaW5nXG4gICAgICA/IHRoaXMuY3VyclNlbGVjdGVkQ29hY2hJbmRleFxuICAgICAgOiB0aGlzLl9nZXRDb2FjaEluZGV4QnlTY3JvbGxUcmlnZ2VyUG9zaXRpb24oKTtcblxuICAgIC8vIFRJTU8tNDM3MDVcbiAgICAvLyBJZiBhIHBsYWNlIHdhcyBzZWxlY3RlZCBieSBtb3VzZSBjbGljayAocHJldmVudENvYWNoU2Nyb2xsQnlQbGFjZUNsaWNrKSBiZWZvcmUgdHJpZ2dlcmluZyB0aGlzIHNjcm9sbGVuZCBtZXRob2QsXG4gICAgLy8gdGhlbiB0aGlzIHNjcm9sbGluZyB3YXMgdHJpZ2dlcmVkIGJ5IHRoZSBtZXRob2QgX3Njcm9sbFBsYWNlSW50b05lYXJlc3RWaWV3cG9ydCwgYW5kIGl0IGlzIG9ubHkgYSBwbGFjZSBhZGp1c3RtZW50IHNjcm9sbCAoc2Nyb2xsSW50b1ZpZXcpLFxuICAgIC8vIHdoZXJlIGEgbGVzcyB2aXNpYmxlIHBsYWNlIGhhcyBiZWVuIHNjcm9sbGVkIGludG8gdGhlIHZpZXdwb3J0LiBJbiBjYXNlIG9mIGEgcGxhY2UgYWRqdXN0bWVudCBieSBjbGljaywgd2UgY2FuIHJldHVybiBoZXJlLlxuICAgIGlmICh0aGlzLnByZXZlbnRDb2FjaFNjcm9sbEJ5UGxhY2VDbGljaykge1xuICAgICAgLy8gQ2hlY2sgd2hldGhlciB0aGUgZW5kc2Nyb2xsaW5nIGlzIGp1c3QgYSBwbGFjZSBhZGp1c3RtZW50IHNjcm9sbGluZyAocGxhY2UgaGFzIDIgZ3JpZCBzaXplIHVuaXRzKVxuICAgICAgY29uc3QgaXNDb2FjaFNjcm9sbGluZyA9XG4gICAgICAgIE1hdGguYWJzKHRoaXMuX2xhc3RTdGFydFNjcm9sbFBvcyAtIHRoaXMuY29hY2hTY3JvbGxBcmVhLnNjcm9sbExlZnQpID5cbiAgICAgICAgdGhpcy5iYXNlR3JpZFNpemUgKiAyO1xuICAgICAgaWYgKGlzQ29hY2hTY3JvbGxpbmcpIHtcbiAgICAgICAgdGhpcy5zZWxlY3RlZENvYWNoSW5kZXggPSBmaW5kU2Nyb2xsQ29hY2hJbmRleDtcbiAgICAgIH1cblxuICAgICAgdGhpcy5wcmV2ZW50Q29hY2hTY3JvbGxCeVBsYWNlQ2xpY2sgPSBmYWxzZTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLl9sYXN0U3RhcnRTY3JvbGxQb3MgPSB0aGlzLmNvYWNoU2Nyb2xsQXJlYS5zY3JvbGxMZWZ0O1xuXG4gICAgLy8gQWZ0ZXIgY29hY2ggc2Nyb2xsZW5kIGV2ZW50IHdlIGNhbiByZXNldCB0aGUgaG92ZXJlZCBjb2FjaCBpbmRleFxuICAgIHRoaXMuaG92ZXJlZENvYWNoSW5kZXggPSAtMTtcblxuICAgIC8vIEluIGNhc2UgdGhlIHVzZXIgdXNlcyB0aGUgc2Nyb2xsYmFyIHdpdGhvdXQgaW50ZXJhY3Rpbmcgd2l0aCB0aGUgc2VhdCByZXNlcnZhdGlvbixcbiAgICAvLyB0aGUgY3VycmVudGx5IHNlbGVjdGVkIGluZGV4IGlzIC0xLCBhbmQgd2UgaGF2ZSB0byBzZXQgdGhpcyB2YWx1ZSB3aXRoIGZpbmRTY3JvbGxDb2FjaEluZGV4LlxuICAgIGlmICh0aGlzLmN1cnJTZWxlY3RlZENvYWNoSW5kZXggPT09IC0xKSB7XG4gICAgICB0aGlzLmN1cnJTZWxlY3RlZENvYWNoSW5kZXggPSBmaW5kU2Nyb2xsQ29hY2hJbmRleDtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5faXNTY3JvbGxhYmxlVG9TZWxlY3RlZENvYWNoKCkpIHtcbiAgICAgIHRoaXMuY3VyclNlbGVjdGVkQ29hY2hJbmRleCA9IGZpbmRTY3JvbGxDb2FjaEluZGV4O1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmN1cnJTZWxlY3RlZENvYWNoSW5kZXggPVxuICAgICAgICBmaW5kU2Nyb2xsQ29hY2hJbmRleCA8IHRoaXMuY3VyclNlbGVjdGVkQ29hY2hJbmRleFxuICAgICAgICAgID8gdGhpcy5jdXJyU2VsZWN0ZWRDb2FjaEluZGV4XG4gICAgICAgICAgOiBmaW5kU2Nyb2xsQ29hY2hJbmRleDtcbiAgICB9XG5cbiAgICBpZiAoIXRoaXMuaXNBdXRvU2Nyb2xsaW5nKSB7XG4gICAgICAvL1doZW4gdXNlciBpcyBzY3JvbGxpbmcgdmlhIHNjcm9sbGJhciwgaXQgYXV0b21hdGljYWxseSBzY3JvbGxzIHRvIHRoZSBmb2N1c2VkIGNvYWNoIGluIHRoZSBtYWluIG5hdmlnYXRpb25cbiAgICAgIHRoaXMuX3Njcm9sbFRvU2VsZWN0ZWROYXZpZ2F0aW9uQnV0dG9uKGZpbmRTY3JvbGxDb2FjaEluZGV4KTtcbiAgICB9XG4gICAgdGhpcy5wcmV2ZW50Q29hY2hTY3JvbGxCeVBsYWNlQ2xpY2sgPSBmYWxzZTtcbiAgICB0aGlzLnVwZGF0ZUN1cnJlbnRTZWxlY3RlZENvYWNoKCk7XG5cbiAgICBpZiAoIXRoaXMuaGFzTmF2aWdhdGlvbikge1xuICAgICAgdGhpcy5wcmVzZWxlY3RQbGFjZUluQ29hY2goKTtcbiAgICAgIHRoaXMuaXNBdXRvU2Nyb2xsaW5nID0gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFBlcmZvcm1zIGFuIGF1dG9tYXRpYyBtYWluIG5hdmlnYXRpb24gc2Nyb2xsIHRvIHRoZSBzcGVjaWZpZWQgc2VsZWN0ZWROYXZDb2FjaEluZGV4LlxuICAgKiBDYWxjdWxhdGVzIHRoZSBjZW50cmFsIHNjcm9sbCBvZmZzZXQgb2YgdGhlIG5hdiBjb2FjaCB0byBiZSBzZWxlY3RlZC5cbiAgICogQHBhcmFtIHNlbGVjdGVkTmF2Q29hY2hJbmRleFxuICAgKi9cbiAgcHJpdmF0ZSBfc2Nyb2xsVG9TZWxlY3RlZE5hdmlnYXRpb25CdXR0b24oc2VsZWN0ZWROYXZDb2FjaEluZGV4OiBudW1iZXIpOiB2b2lkIHtcbiAgICAvL1RpbWUgZGVsYXkgdG8gbm90IGludGVyZmVyZSB3aXRoIG90aGVyIGV4ZWN1dGluZyBjYWxsaW5nIHNjcm9sbFRvIGZ1bmN0aW9ucyAoY29hY2hlcyBzY3JvbGxpbmcpXG4gICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICBpZiAodGhpcy5oYXNOYXZpZ2F0aW9uICYmIHRoaXMubmF2aWdhdGlvblNjcm9sbEFyZWEpIHtcbiAgICAgICAgY29uc3QgbmF2aWdhdGlvbkFyZWFDZW50ZXJlZFBvc1ggPSB0aGlzLnNjcm9sbE5hdmlnYXRpb25BcmVhRGltIC8gMjtcbiAgICAgICAgY29uc3Qgc2Nyb2xsQnV0dG9uT2Zmc2V0WCA9IHNlbGVjdGVkTmF2Q29hY2hJbmRleCAqIHRoaXMuY29hY2hOYXZCdXR0b25EaW07XG4gICAgICAgIGNvbnN0IHNjcm9sbE9mZnNldFggPVxuICAgICAgICAgIHNjcm9sbEJ1dHRvbk9mZnNldFggLSBuYXZpZ2F0aW9uQXJlYUNlbnRlcmVkUG9zWCArIHRoaXMuY29hY2hOYXZCdXR0b25EaW07XG4gICAgICAgIHRoaXMubmF2aWdhdGlvblNjcm9sbEFyZWEuc2Nyb2xsVG8oe1xuICAgICAgICAgIHRvcDogdGhpcy5hbGlnblZlcnRpY2FsID8gc2Nyb2xsT2Zmc2V0WCA6IDAsXG4gICAgICAgICAgbGVmdDogdGhpcy5hbGlnblZlcnRpY2FsID8gMCA6IHNjcm9sbE9mZnNldFgsXG4gICAgICAgICAgYmVoYXZpb3I6ICdzbW9vdGgnLFxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9LCAxMCk7XG4gIH1cblxuICAvKipcbiAgICogU2V0cyB0aGUgbmV3IFNjcm9sbERpcmVjdGlvbiBieSB0aGUgbmV3IGdpdmVuIHRhcmdldCBjb2FjaCBpbmRleC5cbiAgICovXG4gIHByaXZhdGUgX3NldFNjcm9sbERpcmVjdGlvbkJ5Q29hY2hJbmRleCgpOiB2b2lkIHtcbiAgICB0aGlzLmN1cnJTY3JvbGxEaXJlY3Rpb24gPVxuICAgICAgdGhpcy5jdXJyU2VsZWN0ZWRDb2FjaEluZGV4ID4gdGhpcy5zZWxlY3RlZENvYWNoSW5kZXhcbiAgICAgICAgPyBTY3JvbGxEaXJlY3Rpb24ucmlnaHRcbiAgICAgICAgOiBTY3JvbGxEaXJlY3Rpb24ubGVmdDtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBzY3JvbGwgc3RhcnQgb3IgZW5kIHBvc2l0aW9uIFggZnJvbSB0aGUgc2VsZWN0ZWQgY29hY2guXG4gICAqIEluIGNhc2UgdGhlIHVzZXIgaXMgY3VycmVudGx5IG5hdmlnYXRpbmcgdGhyb3VnaCBwbGFjZXMgYnkga2V5Ym9hcmQgYW5kIGdvZXMgdG8gcHJldmlvdXMgY29hY2gsXG4gICAqIHRoZW4gd2UgcmV0dXJuIHRoZSBlbmQgcG9zaXRpb24gb2YgdGhlIGNvYWNoIHRvIGdldCB0aGUgY2xvc2VzdCBzY3JvbGwgcG9zaXRpb24gb2YgdGhlIG5leHQgZm9jdXMgcGxhY2UuXG4gICAqIEByZXR1cm5zIG51bWJlclxuICAgKi9cbiAgcHJpdmF0ZSBfZ2V0Q29hY2hTY3JvbGxQb3NpdGlvblgoKTogbnVtYmVyIHtcbiAgICBjb25zdCBjb2FjaFRyaWdnZXJQb2ludCA9IHRoaXMudHJpZ2dlckNvYWNoUG9zaXRpb25zQ29sbGVjdGlvblt0aGlzLmN1cnJTZWxlY3RlZENvYWNoSW5kZXhdO1xuICAgIGNvbnN0IGlzRm9jdXNQbGFjZUZyb21QcmV2aW91c0NvYWNoUG9zaXRpb24gPVxuICAgICAgdGhpcy5pc0tleWJvYXJkTmF2aWdhdGlvbiAmJlxuICAgICAgdGhpcy5jdXJyU2Nyb2xsRGlyZWN0aW9uID09PSBTY3JvbGxEaXJlY3Rpb24ubGVmdCAmJlxuICAgICAgY29hY2hUcmlnZ2VyUG9pbnQud2lkdGggPiB0aGlzLnNjcm9sbENvYWNoZXNBcmVhV2lkdGg7XG5cbiAgICByZXR1cm4gaXNGb2N1c1BsYWNlRnJvbVByZXZpb3VzQ29hY2hQb3NpdGlvblxuICAgICAgPyBjb2FjaFRyaWdnZXJQb2ludC5lbmQgLSB0aGlzLnNjcm9sbENvYWNoZXNBcmVhV2lkdGhcbiAgICAgIDogY29hY2hUcmlnZ2VyUG9pbnQuc3RhcnQ7XG4gIH1cblxuICAvKipcbiAgICogU2V0cyB0aGUgZm9jdXMgb24gdGhlIEhUTUwgdGFibGUgKGdyaWQpIGNhcHRpb24gZWxlbWVudCBzbyB0aGF0IHRoZSBoZWFkaW5nIGlzIHJlYWQgb3V0IHdoZW4gdXNpbmcgYSBTY3JlZW5SZWFkZXIuXG4gICAqL1xuICBwcml2YXRlIF9zZXRGb2N1c1RvU2VsZWN0ZWRDb2FjaEdyaWQoKTogdm9pZCB7XG4gICAgLy8gV2hlbiB0aGUgdXNlciBwZXJmb3JtcyBhbiBhY3Rpb24gdGhhdCBhZmZlY3RzIHRoZSBjb2FjaCBuYXZpZ2F0aW9uLCB0aGVuIHRoZSBuYXZpZ2F0ZWQgdGFibGUgaXMgZm9jdXNhYmxlLlxuICAgIGlmICh0aGlzLmlzQ29hY2hHcmlkRm9jdXNhYmxlICYmIHRoaXMuaGFzU2VhdFJlc2VydmF0aW9uTmF0aXZlRm9jdXMpIHtcbiAgICAgIHRoaXMuaXNDb2FjaEdyaWRGb2N1c2FibGUgPSBmYWxzZTtcbiAgICAgIGNvbnN0IGNvYWNoVGFibGVDYXB0aW9uRWxlbWVudCA9IHRoaXMuc2hhZG93Um9vdD8ucXVlcnlTZWxlY3RvcihcbiAgICAgICAgJyNzYmItc3ItY29hY2gtY2FwdGlvbi0nICsgdGhpcy5jdXJyU2VsZWN0ZWRDb2FjaEluZGV4LFxuICAgICAgKSBhcyBIVE1MVGFibGVDYXB0aW9uRWxlbWVudDtcbiAgICAgIGlmIChjb2FjaFRhYmxlQ2FwdGlvbkVsZW1lbnQpIHtcbiAgICAgICAgY29hY2hUYWJsZUNhcHRpb25FbGVtZW50LmZvY3VzKCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgd2hldGhlciB0aGUgY3VycmVudCBzY3JvbGxlZCBwb3NpdGlvbiBjYW4gYmUgdXNlZCB0byBzY3JvbGwgdG8gdGhlIHNlbGVjdGVkIHdhZ29uXG4gICAqIEByZXR1cm5zIGJvb2xlYW5cbiAgICovXG4gIHByaXZhdGUgX2lzU2Nyb2xsYWJsZVRvU2VsZWN0ZWRDb2FjaCgpOiBib29sZWFuIHtcbiAgICBjb25zdCBjdXJyU2Nyb2xsUG9zWCA9IHRoaXMuYWxpZ25WZXJ0aWNhbFxuICAgICAgPyB0aGlzLmNvYWNoU2Nyb2xsQXJlYS5zY3JvbGxUb3BcbiAgICAgIDogdGhpcy5jb2FjaFNjcm9sbEFyZWEuc2Nyb2xsTGVmdDtcbiAgICBjb25zdCBjb2FjaFNjcm9sbFdpbmRvd1dpZHRoID0gdGhpcy5hbGlnblZlcnRpY2FsXG4gICAgICA/IHRoaXMuY29hY2hTY3JvbGxBcmVhLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLmhlaWdodFxuICAgICAgOiB0aGlzLmNvYWNoU2Nyb2xsQXJlYS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS53aWR0aDtcbiAgICBjb25zdCBtYXhTY3JvbGxXaWR0aEFyZWEgPSB0aGlzLm1heENhbGNDb2FjaGVzV2lkdGggLSBjb2FjaFNjcm9sbFdpbmRvd1dpZHRoO1xuICAgIGNvbnN0IGN1cnJDb2FjaFRyaWdnZXIgPSB0aGlzLnRyaWdnZXJDb2FjaFBvc2l0aW9uc0NvbGxlY3Rpb25bdGhpcy5jdXJyU2VsZWN0ZWRDb2FjaEluZGV4XTtcbiAgICBjb25zdCBpc1Njcm9sbFBvc1NhbWVUb0N1cnJDb2FjaFBvcyA9XG4gICAgICBjdXJyU2Nyb2xsUG9zWCA9PT0gdGhpcy50cmlnZ2VyQ29hY2hQb3NpdGlvbnNDb2xsZWN0aW9uW3RoaXMuY3VyclNlbGVjdGVkQ29hY2hJbmRleF0uc3RhcnQ7XG5cbiAgICByZXR1cm4gKFxuICAgICAgKGN1cnJTY3JvbGxQb3NYIDwgbWF4U2Nyb2xsV2lkdGhBcmVhIHx8IGN1cnJTY3JvbGxQb3NYID4gY3VyckNvYWNoVHJpZ2dlci5zdGFydCkgJiZcbiAgICAgICFpc1Njcm9sbFBvc1NhbWVUb0N1cnJDb2FjaFBvc1xuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgY29hY2ggaW5kZXggd2hpY2ggaXMgY3VycmVudGx5IHZpc2libGUgaW4gdGhlIHNjcm9sbCBhcmVhXG4gICAqIEByZXR1cm5zIG51bWJlclxuICAgKi9cbiAgcHJpdmF0ZSBfZ2V0Q29hY2hJbmRleEJ5U2Nyb2xsVHJpZ2dlclBvc2l0aW9uKCk6IG51bWJlciB7XG4gICAgY29uc3Qgc2Nyb2xsUG9zID0gdGhpcy5hbGlnblZlcnRpY2FsXG4gICAgICA/IHRoaXMuY29hY2hTY3JvbGxBcmVhLnNjcm9sbFRvcFxuICAgICAgOiB0aGlzLmNvYWNoU2Nyb2xsQXJlYS5zY3JvbGxMZWZ0O1xuICAgIGNvbnN0IHNjcm9sbE9mZnNldFggPSBzY3JvbGxQb3MgKyB0aGlzLnNjcm9sbENvYWNoZXNBcmVhV2lkdGggLyAyO1xuICAgIHJldHVybiB0aGlzLnRyaWdnZXJDb2FjaFBvc2l0aW9uc0NvbGxlY3Rpb24uZmluZEluZGV4KFxuICAgICAgKGNvYWNoVHJpZ2dlcikgPT4gc2Nyb2xsT2Zmc2V0WCA+PSBjb2FjaFRyaWdnZXIuc3RhcnQgJiYgc2Nyb2xsT2Zmc2V0WCA8PSBjb2FjaFRyaWdnZXIuZW5kLFxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogR2V0IHRoZSBmaXJzdCBwbGFjZSBvZiBjdXJyZW50IHNlbGVjdGVkIGNvYWNoIGJ5IHRhYmxlIGNlbGwgY29vcmRpbmF0ZSAwLTAgaWQuXG4gICAqIEByZXR1cm5zIFBsYWNlIG9yIG51bGxcbiAgICovXG4gIHByaXZhdGUgX2dldEZpcnN0UGxhY2VJblNlbGVjdGVkQ29hY2goKTogUGxhY2UgfCBudWxsIHtcbiAgICBsZXQgZmlyc3RQbGFjZTogUGxhY2UgfCBudWxsID0gbnVsbDtcbiAgICBjb25zdCBjb2FjaCA9XG4gICAgICB0aGlzLnNlYXRSZXNlcnZhdGlvbnNbdGhpcy5jdXJyU2VsZWN0ZWREZWNrSW5kZXhdLmNvYWNoSXRlbXNbdGhpcy5jdXJyU2VsZWN0ZWRDb2FjaEluZGV4XTtcbiAgICBjb25zdCBmaXJzdENlbGxJZCA9XG4gICAgICAnY2VsbC0nICsgdGhpcy5jdXJyU2VsZWN0ZWREZWNrSW5kZXggKyAnLScgKyB0aGlzLmN1cnJTZWxlY3RlZENvYWNoSW5kZXggKyAnLTAtMCc7XG4gICAgY29uc3QgcGxhY2VOdW1iZXIgPVxuICAgICAgdGhpcy5zaGFkb3dSb290XG4gICAgICAgID8ucXVlcnlTZWxlY3RvcjxIVE1MVGFibGVDZWxsRWxlbWVudD4oJyMnICsgZmlyc3RDZWxsSWQpXG4gICAgICAgID8ucXVlcnlTZWxlY3RvcjxTYmJTZWF0UmVzZXJ2YXRpb25QbGFjZUNvbnRyb2xFbGVtZW50Pignc2JiLXNlYXQtcmVzZXJ2YXRpb24tcGxhY2UtY29udHJvbCcpXG4gICAgICAgID8uZ2V0QXR0cmlidXRlKCd0ZXh0JykgfHwgbnVsbDtcblxuICAgIGlmIChjb2FjaCAmJiBwbGFjZU51bWJlcikge1xuICAgICAgZmlyc3RQbGFjZSA9IGNvYWNoLnBsYWNlcz8uZmluZCgocGxhY2UpID0+IHBsYWNlLm51bWJlciA9PT0gcGxhY2VOdW1iZXIpIHx8IG51bGw7XG4gICAgfVxuICAgIHJldHVybiBmaXJzdFBsYWNlO1xuICB9XG5cbiAgcHJpdmF0ZSBfZ2V0U3dpdGNoZWRDb2FjaERlY2tJbmRleEJ5S2V5TmF2aWdhdGlvbihcbiAgICBwcmVzc2VkS2V5OiBzdHJpbmcsXG4gICAgY29hY2g6IENvYWNoSXRlbSxcbiAgKTogbnVtYmVyIHwgbnVsbCB7XG4gICAgaWYgKFxuICAgICAgIXRoaXMuY3VyclNlbGVjdGVkUGxhY2UgfHxcbiAgICAgIHByZXNzZWRLZXkgPT09IHRoaXMua2V5Ym9hcmROYXZpZ2F0aW9uRXZlbnRzLkFycm93UmlnaHQgfHxcbiAgICAgIHByZXNzZWRLZXkgPT09IHRoaXMua2V5Ym9hcmROYXZpZ2F0aW9uRXZlbnRzLkFycm93TGVmdFxuICAgIClcbiAgICAgIHJldHVybiBudWxsO1xuXG4gICAgLy9DSEVDSyBERUNLIFNXSVRDSCBET1dOXG4gICAgaWYgKFxuICAgICAgcHJlc3NlZEtleSA9PT0gdGhpcy5rZXlib2FyZE5hdmlnYXRpb25FdmVudHMuQXJyb3dEb3duICYmXG4gICAgICB0aGlzLmN1cnJTZWxlY3RlZFBsYWNlLnBvc2l0aW9uLnkgKyAyID09PSBjb2FjaC5kaW1lbnNpb24uaCAmJlxuICAgICAgISF0aGlzLnNlYXRSZXNlcnZhdGlvbnNbdGhpcy5jdXJyU2VsZWN0ZWREZWNrSW5kZXggKyAxXVxuICAgICkge1xuICAgICAgcmV0dXJuIHRoaXMuY3VyclNlbGVjdGVkRGVja0luZGV4ICsgMTtcbiAgICB9XG4gICAgLy9DSEVDSyBERUNLIFNXSVRDSCBVUFxuICAgIGVsc2UgaWYgKFxuICAgICAgcHJlc3NlZEtleSA9PT0gdGhpcy5rZXlib2FyZE5hdmlnYXRpb25FdmVudHMuQXJyb3dVcCAmJlxuICAgICAgdGhpcy5jdXJyU2VsZWN0ZWRQbGFjZS5wb3NpdGlvbi55ID09PSAwICYmXG4gICAgICAhIXRoaXMuc2VhdFJlc2VydmF0aW9uc1t0aGlzLmN1cnJTZWxlY3RlZERlY2tJbmRleCAtIDFdXG4gICAgKSB7XG4gICAgICByZXR1cm4gdGhpcy5jdXJyU2VsZWN0ZWREZWNrSW5kZXggLSAxO1xuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBUbyBnZXQgdGhlIGNvcnJlY3QgY2xvc2VzdCBwbGFjZSBvZiBjdXJyZW50IHByZXNzZWQga2V5IGFuZCB0aGUgY3VycmVudCBzZWxlY3RlZCBwbGFjZSxcbiAgICogd2UgaGF2ZSB0byBpbnZlc3RpZ2F0ZSB0aGUgY29vcmRpbmF0ZXMgb2YgZWFjaCBwbGFjZSB0byBmaW5kIHRoZSBjbG9zZXN0IHBsYWNlIG9mIHRoZSBjdXJyU2VsZWN0ZWRQbGFjZUVsZW1lbnRJZC5cbiAgICogQHBhcmFtIHByZXNzZWRLZXlcbiAgICogQHJldHVybnMgUGxhY2Ugb3IgbnVsbFxuICAgKi9cbiAgcHJpdmF0ZSBfZ2V0Q2xvc2VzdFBsYWNlQnlLZXlEaXJlY3Rpb24ocHJlc3NlZEtleT86IHN0cmluZyk6IFBsYWNlIHwgbnVsbCB7XG4gICAgY29uc3QgY29hY2ggPVxuICAgICAgdGhpcy5zZWF0UmVzZXJ2YXRpb25zW3RoaXMuY3VyclNlbGVjdGVkRGVja0luZGV4XS5jb2FjaEl0ZW1zW3RoaXMuY3VyclNlbGVjdGVkQ29hY2hJbmRleF07XG4gICAgbGV0IGNsb3Nlc3RQbGFjZSA9IG51bGw7XG4gICAgbGV0IGNvYWNoUGxhY2VzID0gY29hY2gucGxhY2VzO1xuICAgIGxldCBzd2l0Y2hlZENvYWNoRGVja0luZGV4ID0gbnVsbDtcblxuICAgIGlmIChjb2FjaFBsYWNlcykge1xuICAgICAgLy8gSWYgbm8gcGxhY2Ugc2V0LCB0aGVuIHdlIHVzZSBpbml0aWFsIHRoZSBsZWZ0LXRvcCBwbGFjZSBvbiB0aGUgY29hY2hcbiAgICAgIGlmICghdGhpcy5jdXJyU2VsZWN0ZWRQbGFjZUVsZW1lbnRJZCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fZ2V0Rmlyc3RQbGFjZUluU2VsZWN0ZWRDb2FjaCgpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaWYgKHRoaXMuY3VyclNlbGVjdGVkUGxhY2UpIHtcbiAgICAgICAgICBjb25zdCBjdXJyU2VsZWN0ZWRQbGFjZVBvc2l0aW9uID0geyAuLi50aGlzLmN1cnJTZWxlY3RlZFBsYWNlLnBvc2l0aW9uIH07XG5cbiAgICAgICAgICBpZiAocHJlc3NlZEtleSkge1xuICAgICAgICAgICAgLy8gQ2hlY2sgd2hldGhlciB0aGUga2V5Ym9hcmQgbmF2aWdhdGlvbiBpcyB1c2VkIHRvIHN3aXRjaCB0byBhbm90aGVyIGNvYWNoIGRlY2sgKFVwIC0+IERvd24gfCBEb3duIC0+IFVwKS5cbiAgICAgICAgICAgIC8vIEluIHRoaXMgY2FzZSwgd2UgdGFrZSB0aGUgY29hY2ggcGxhY2VzIHdlIGhhdmUgdG8gY2hlY2tlZCBmcm9tIHRoZSB0YXJnZXQgZGVjayBub3cuXG4gICAgICAgICAgICBzd2l0Y2hlZENvYWNoRGVja0luZGV4ID0gdGhpcy5fZ2V0U3dpdGNoZWRDb2FjaERlY2tJbmRleEJ5S2V5TmF2aWdhdGlvbihcbiAgICAgICAgICAgICAgcHJlc3NlZEtleSxcbiAgICAgICAgICAgICAgY29hY2gsXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgaWYgKHN3aXRjaGVkQ29hY2hEZWNrSW5kZXggIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgLy8gQXNzaWduIGNoZWNrIHBsYWNlcyBmcm9tIHRoZSB0YXJnZXQgc3dpdGNoIGRlY2tcbiAgICAgICAgICAgICAgY29hY2hQbGFjZXMgPVxuICAgICAgICAgICAgICAgIHRoaXMuc2VhdFJlc2VydmF0aW9uc1tzd2l0Y2hlZENvYWNoRGVja0luZGV4XS5jb2FjaEl0ZW1zW1xuICAgICAgICAgICAgICAgICAgdGhpcy5jdXJyU2VsZWN0ZWRDb2FjaEluZGV4XG4gICAgICAgICAgICAgICAgXS5wbGFjZXMgfHwgW107XG4gICAgICAgICAgICAgIC8vIFdlIGhhdmUgdG8gdXBkYXRlIHkgY29vcmRpbmF0ZVxuICAgICAgICAgICAgICBjdXJyU2VsZWN0ZWRQbGFjZVBvc2l0aW9uLnkgPVxuICAgICAgICAgICAgICAgIHN3aXRjaGVkQ29hY2hEZWNrSW5kZXggPCB0aGlzLmN1cnJTZWxlY3RlZERlY2tJbmRleCA/IGNvYWNoLmRpbWVuc2lvbi5oIDogLTE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgZm9yIChjb25zdCBwbGFjZSBvZiBjb2FjaFBsYWNlcykge1xuICAgICAgICAgICAgLy8gSWYgbm8ga2V5IHByZXNzZWQsIHRoZW4gd2UgdHJ5IHRvIGZpbmQgdGhlIHBsYWNlIG9mIHRoZSBjdXJyZW50IGN1cnJTY3JvbGxEaXJlY3Rpb25cbiAgICAgICAgICAgIGlmICghcHJlc3NlZEtleSkge1xuICAgICAgICAgICAgICAvLyBGaW5kIHBsYWNlIGZyb20gdGhlIGxlZnQgc2lkZSBvZiBjb2FjaCBieSB5IGNvb3JkaW5hdGUuIEN1cnJlbnQgY3VyclNjcm9sbERpcmVjdGlvbiBpcyBSSUdIVFxuICAgICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgdGhpcy5jdXJyU2Nyb2xsRGlyZWN0aW9uID09PSBTY3JvbGxEaXJlY3Rpb24ucmlnaHQgJiZcbiAgICAgICAgICAgICAgICBwbGFjZS5wb3NpdGlvbi55ID09PSBjdXJyU2VsZWN0ZWRQbGFjZVBvc2l0aW9uLnkgJiZcbiAgICAgICAgICAgICAgICAoIWNsb3Nlc3RQbGFjZSB8fCBwbGFjZS5wb3NpdGlvbi54IDwgY2xvc2VzdFBsYWNlLnBvc2l0aW9uLngpXG4gICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgIGNsb3Nlc3RQbGFjZSA9IHBsYWNlO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIC8vRmluZCBwbGFjZSBmcm9tIHRoZSByaWdodCBzaWRlIG9mIGNvYWNoIGJ5IHkgY29vcmRpbmF0ZS4gQ3VycmVudCBjdXJyU2Nyb2xsRGlyZWN0aW9uIGlzIExFRlRcbiAgICAgICAgICAgICAgZWxzZSBpZiAoXG4gICAgICAgICAgICAgICAgdGhpcy5jdXJyU2Nyb2xsRGlyZWN0aW9uID09PSBTY3JvbGxEaXJlY3Rpb24ubGVmdCAmJlxuICAgICAgICAgICAgICAgIHBsYWNlLnBvc2l0aW9uLnkgPT09IGN1cnJTZWxlY3RlZFBsYWNlUG9zaXRpb24ueSAmJlxuICAgICAgICAgICAgICAgICghY2xvc2VzdFBsYWNlIHx8IHBsYWNlLnBvc2l0aW9uLnggPiBjbG9zZXN0UGxhY2UucG9zaXRpb24ueClcbiAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgY2xvc2VzdFBsYWNlID0gcGxhY2U7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIGlmIChwbGFjZS5udW1iZXIgIT09IHRoaXMuY3VyclNlbGVjdGVkUGxhY2U/Lm51bWJlcikge1xuICAgICAgICAgICAgICAgIC8vS2V5IFtSaWdodF0gbmF2aWdhdGlvbiwgd2UgY2hlY2sgdGhlIHBsYWNlIGNvb3JkaW5hdGVzIG9mIHRoZSB4LWF4aXMgdG8gZ2V0IHRoZSBzbWFsbGVzdCBsYXJnZXIgeCBwbGFjZSBjb29yZGluYXRlIG9mIHRoZSBjdXJyZW50bHkgc2VsZWN0ZWQgcGxhY2VcbiAgICAgICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgICBwcmVzc2VkS2V5ID09PSB0aGlzLmtleWJvYXJkTmF2aWdhdGlvbkV2ZW50cy5BcnJvd1JpZ2h0ICYmXG4gICAgICAgICAgICAgICAgICAocGxhY2UucG9zaXRpb24ueSA9PT0gY3VyclNlbGVjdGVkUGxhY2VQb3NpdGlvbi55IHx8XG4gICAgICAgICAgICAgICAgICAgIHBsYWNlLnBvc2l0aW9uLnkgPT09IGN1cnJTZWxlY3RlZFBsYWNlUG9zaXRpb24ueSAtIDEpICYmXG4gICAgICAgICAgICAgICAgICBwbGFjZS5wb3NpdGlvbi54ID4gY3VyclNlbGVjdGVkUGxhY2VQb3NpdGlvbi54ICYmXG4gICAgICAgICAgICAgICAgICAoIWNsb3Nlc3RQbGFjZSB8fCBwbGFjZS5wb3NpdGlvbi54IDwgY2xvc2VzdFBsYWNlLnBvc2l0aW9uLngpXG4gICAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgICBjbG9zZXN0UGxhY2UgPSBwbGFjZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgLy9LZXkgW0Rvd25dIG5hdmlnYXRpb24sIHdlIGNoZWNrIHRoZSBwbGFjZSBjb29yZGluYXRlcyBvZiB0aGUgeS1heGlzIHRvIGdldCB0aGUgc21hbGxlc3QgbGFyZ2VyIHkgcGxhY2UgY29vcmRpbmF0ZSBvZiB0aGUgY3VycmVudGx5IHNlbGVjdGVkIHBsYWNlXG4gICAgICAgICAgICAgICAgZWxzZSBpZiAoXG4gICAgICAgICAgICAgICAgICBwcmVzc2VkS2V5ID09PSB0aGlzLmtleWJvYXJkTmF2aWdhdGlvbkV2ZW50cy5BcnJvd0Rvd24gJiZcbiAgICAgICAgICAgICAgICAgIChwbGFjZS5wb3NpdGlvbi54ID09PSBjdXJyU2VsZWN0ZWRQbGFjZVBvc2l0aW9uLnggfHxcbiAgICAgICAgICAgICAgICAgICAgcGxhY2UucG9zaXRpb24ueCA9PT0gY3VyclNlbGVjdGVkUGxhY2VQb3NpdGlvbi54ICsgMSkgJiZcbiAgICAgICAgICAgICAgICAgIHBsYWNlLnBvc2l0aW9uLnkgPiBjdXJyU2VsZWN0ZWRQbGFjZVBvc2l0aW9uLnkgJiZcbiAgICAgICAgICAgICAgICAgICghY2xvc2VzdFBsYWNlIHx8IHBsYWNlLnBvc2l0aW9uLnkgPCBjbG9zZXN0UGxhY2UucG9zaXRpb24ueSlcbiAgICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICAgIGNsb3Nlc3RQbGFjZSA9IHBsYWNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAvL0tleSBbTGVmdF0gbmF2aWdhdGlvbiwgd2UgY2hlY2sgdGhlIHBsYWNlIGNvb3JkaW5hdGVzIG9mIHRoZSB4LWF4aXMgdG8gZ2V0IHRoZSBncmVhdGVzdCBzbWFsbGVyIHggcGxhY2UgY29vcmRpbmF0ZSBvZiB0aGUgY3VycmVudGx5IHNlbGVjdGVkIHBsYWNlXG4gICAgICAgICAgICAgICAgZWxzZSBpZiAoXG4gICAgICAgICAgICAgICAgICBwcmVzc2VkS2V5ID09PSB0aGlzLmtleWJvYXJkTmF2aWdhdGlvbkV2ZW50cy5BcnJvd0xlZnQgJiZcbiAgICAgICAgICAgICAgICAgIChwbGFjZS5wb3NpdGlvbi55ID09PSBjdXJyU2VsZWN0ZWRQbGFjZVBvc2l0aW9uLnkgfHxcbiAgICAgICAgICAgICAgICAgICAgcGxhY2UucG9zaXRpb24ueSA9PT0gY3VyclNlbGVjdGVkUGxhY2VQb3NpdGlvbi55ICsgMSkgJiZcbiAgICAgICAgICAgICAgICAgIHBsYWNlLnBvc2l0aW9uLnggPCBjdXJyU2VsZWN0ZWRQbGFjZVBvc2l0aW9uLnggJiZcbiAgICAgICAgICAgICAgICAgICghY2xvc2VzdFBsYWNlIHx8IHBsYWNlLnBvc2l0aW9uLnggPiBjbG9zZXN0UGxhY2UucG9zaXRpb24ueClcbiAgICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICAgIGNsb3Nlc3RQbGFjZSA9IHBsYWNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAvL0tleSBbVXBdIG5hdmlnYXRpb24sIHdlIGNoZWNrIHRoZSBwbGFjZSBjb29yZGluYXRlcyBvZiB0aGUgeS1heGlzIHRvIGdldCB0aGUgZ3JlYXRlc3Qgc21hbGxlciB5IHBsYWNlIGNvb3JkaW5hdGUgb2YgdGhlIGN1cnJlbnRseSBzZWxlY3RlZCBwbGFjZVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKFxuICAgICAgICAgICAgICAgICAgcHJlc3NlZEtleSA9PT0gdGhpcy5rZXlib2FyZE5hdmlnYXRpb25FdmVudHMuQXJyb3dVcCAmJlxuICAgICAgICAgICAgICAgICAgKHBsYWNlLnBvc2l0aW9uLnggPT09IGN1cnJTZWxlY3RlZFBsYWNlUG9zaXRpb24ueCB8fFxuICAgICAgICAgICAgICAgICAgICBwbGFjZS5wb3NpdGlvbi54ID09PSBjdXJyU2VsZWN0ZWRQbGFjZVBvc2l0aW9uLnggLSAxKSAmJlxuICAgICAgICAgICAgICAgICAgcGxhY2UucG9zaXRpb24ueSA8IGN1cnJTZWxlY3RlZFBsYWNlUG9zaXRpb24ueSAmJlxuICAgICAgICAgICAgICAgICAgKCFjbG9zZXN0UGxhY2UgfHwgcGxhY2UucG9zaXRpb24ueSA+IGNsb3Nlc3RQbGFjZS5wb3NpdGlvbi55KVxuICAgICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgICAgY2xvc2VzdFBsYWNlID0gcGxhY2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgLy8gSWYgYSBwbGFjZSBoYXMgYmVlbiBmb3VuZCBpbiB0aGUgY2hhbmdpbmcgc3dpdGNoIGNvYWNoLFxuICAgICAgICAgIC8vIHdlIGNhbiB1cGRhdGUgdGhlIGN1cnJTZWxlY3RlZERlY2tJbmRleFxuICAgICAgICAgIGlmIChzd2l0Y2hlZENvYWNoRGVja0luZGV4ICE9PSBudWxsICYmIGNsb3Nlc3RQbGFjZSkge1xuICAgICAgICAgICAgdGhpcy5jdXJyU2VsZWN0ZWREZWNrSW5kZXggPSBzd2l0Y2hlZENvYWNoRGVja0luZGV4O1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gY2xvc2VzdFBsYWNlO1xuICB9XG5cbiAgLy8gSGFuZGxpbmcgZm9yIFRhYiBuYXZpZ2F0aW9uIGlmIGEgcGxhY2UgaXMgc2VsZWN0ZWQgaW5zaWRlIHRoZSBjb2FjaC5cbiAgLy8gVGhpcyBjb250cm9scyB0aGUgZm9jdXNlZCBjb2FjaCBmcm9tIHRoZSBjdXJyZW50IHNlbGVjdGVkIGNvYWNoLlxuICBwcml2YXRlIF9uYXZpZ2F0ZUNvYWNoTmF2aWdhdGlvbkJ5S2V5Ym9hcmQodGFiRGlyZWN0aW9uOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBjb25zdCBjdXJyRm9jdXNJbmRleCA9XG4gICAgICB0aGlzLmZvY3VzZWRDb2FjaEluZGV4ID09PSAtMVxuICAgICAgICA/IHRoaXMuY3VyclNlbGVjdGVkQ29hY2hJbmRleCA9PT0gLTFcbiAgICAgICAgICA/IDBcbiAgICAgICAgICA6IHRoaXMuY3VyclNlbGVjdGVkQ29hY2hJbmRleFxuICAgICAgICA6IHRoaXMuZm9jdXNlZENvYWNoSW5kZXg7XG5cbiAgICAvLyBDaGVjayBuZXh0IG9yIHByZXYgdGFiIGlzIHByZXNzZWQsIHRoZW4gd2UgbmVlZCB0byBmaW5kIHRoZSBuZXh0IGF2YWlsYWJsZSBjb2FjaCBpbmRleCB0aGF0IHNob3VsZCByZWNlaXZlIHRoZSBmb2N1c1xuICAgIGNvbnN0IG5ld0ZvY3VzYWJsZUluZGV4OiBudW1iZXIgPVxuICAgICAgdGFiRGlyZWN0aW9uID09PSAnTkVYVF9UQUInXG4gICAgICAgID8gdGhpcy5nZXROZXh0QXZhaWxhYmxlQ29hY2hJbmRleChjdXJyRm9jdXNJbmRleClcbiAgICAgICAgOiB0aGlzLmdldFByZXZBdmFpbGFibGVDb2FjaEluZGV4KGN1cnJGb2N1c0luZGV4KTtcblxuICAgIGlmICh0aGlzLmhhc05hdmlnYXRpb24pIHtcbiAgICAgIGNvbnN0IHNlbGVjdGVkUGxhY2VFbGVtZW50ID0gdGhpcy5fZ2V0UGxhY2VIdG1sRWxlbWVudCgpO1xuICAgICAgY29uc3QgcGxhY2VJbkNvYWNoSGFzRm9jdXMgPSBzZWxlY3RlZFBsYWNlRWxlbWVudFxuICAgICAgICA/IHNlbGVjdGVkUGxhY2VFbGVtZW50LmdldEF0dHJpYnV0ZSgna2V5Zm9jdXMnKSA9PT0gJ2ZvY3VzJ1xuICAgICAgICA6IGZhbHNlO1xuXG4gICAgICAvLyBJZiB3ZSB0YWIgYmFjayAoUFJFVl9UQUIpIGFuZCB0aGUgZm9jdXMgaXMgY3VycmVudGx5IG9uIHBsYWNlLFxuICAgICAgLy8gd2UgcmVtb3ZlIHRoZSBzZWxlY3RlZCBzdGF0ZSBmcm9tIHRoZSBjdXJyZW50bHkgc2VsZWN0ZWQgbmF2aWdhdGlvbiBjb2FjaCBhbmQgb25seSBzZXQgdGhlIGZvY3VzIHN0YXR1cyB0byBpdFxuICAgICAgaWYgKHRhYkRpcmVjdGlvbiA9PT0gJ1BSRVZfVEFCJyAmJiB0aGlzLnNlbGVjdGVkQ29hY2hJbmRleCA9PT0gY3VyckZvY3VzSW5kZXgpIHtcbiAgICAgICAgLy8gSWYgd2UgVEFCIGJhY2sgYW5kIGhhdmUgYSBzZWxlY3RlZCBwbGFjZXMgaW5zaWRlIHRoZSBjdXJyZW50IGNvYWNoLCB0aGVuIHdlIG1vdmUgb3V0IGZyb20gdGhlIHNlYXRtYXAgYW5kIHNldCB0aGUgZm9jdXMgdG8gdGhlIGN1cnJlbnQgc2VsZWN0ZWQgY29hY2hcbiAgICAgICAgaWYgKHBsYWNlSW5Db2FjaEhhc0ZvY3VzIHx8IHRoaXMuY3VyclNlbGVjdGVkUGxhY2UgIT09IG51bGwpIHtcbiAgICAgICAgICB0aGlzLmZvY3VzZWRDb2FjaEluZGV4ID0gY3VyckZvY3VzSW5kZXg7XG4gICAgICAgICAgdGhpcy51bmZvY3VzUGxhY2VFbGVtZW50KCk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIC8vIFdoZW4gdGhlIGZpcnN0IGNvYWNoIGlzIHNlbGVjdGVkIGFuZCB3ZSBUQUIgYmFjaywgd2UgaGF2ZSB0byBzZXQgdGhlIG5hdGl2ZSBmb2N1cyBvbiB0aGUgZmlyc3QgY29hY2ggaW4gdGhlIG5hdmlnYXRpb24gdG8gZ2V0IGJhY2sgdG8gdGhlIG5vcm1hbCB0YWIgbmF2aWdhdGlvbi5cbiAgICAgICAgLy8gVG8gZG8gdGhpcywgd2UgaGF2ZSB0byByZW1vdmUgdGhlIGZvY3VzZWRJbmRleCBmcm9tIHRoZSBmaXJzdCBjb2FjaCBhbmQgc2V0IGl0IGFnYWluIGFmdGVyIGEgc2hvcnQgZGVsYXlcbiAgICAgICAgZWxzZSBpZiAoY3VyckZvY3VzSW5kZXggPT09IDApIHtcbiAgICAgICAgICAvLyBSZWZvY3VzIHRoZSBmaXJzdCBjb2FjaFxuICAgICAgICAgIHRoaXMuX3JlZm9jdXNDdXJyZW50Rm9jdXNlZE5hdkNvYWNoKGN1cnJGb2N1c0luZGV4KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aGlzLmZvY3VzZWRDb2FjaEluZGV4ID0gbmV3Rm9jdXNhYmxlSW5kZXg7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIC8vIE9ubHkgc2V0cyB0aGUgZm9jdXMgb24gdGhlIG5ldyBuYXZpZ2F0aW9uIGNvYWNoXG4gICAgICBlbHNlIGlmIChuZXdGb2N1c2FibGVJbmRleCAhPT0gdGhpcy5jdXJyU2VsZWN0ZWRDb2FjaEluZGV4KSB7XG4gICAgICAgIHRoaXMuZm9jdXNlZENvYWNoSW5kZXggPSBuZXdGb2N1c2FibGVJbmRleDtcbiAgICAgIH1cbiAgICAgIC8vIFdoZW4gdGhlIGxhc3QgY29hY2ggaXMgc2VsZWN0ZWQgYW5kIHdlIFRBQiwgd2UgaGF2ZSB0byBzZXQgdGhlIG5hdGl2ZSBmb2N1cyBvbiB0aGUgbGFzdCBjb2FjaCBpbiB0aGUgbmF2aWdhdGlvbiB0byBnZXQgYmFjayB0byB0aGUgbm9ybWFsIHRhYiBuYXZpZ2F0aW9uLlxuICAgICAgLy8gVG8gZG8gdGhpcywgd2UgaGF2ZSAgdG8gcmVtb3ZlIHRoZSBmb2N1c2VkSW5kZXggZnJvbSB0aGUgZmlyc3QgY29hY2ggYW5kIHNldCBpdCBhZ2FpbiBhZnRlciBhIHNob3J0IGRlbGF5XG4gICAgICBlbHNlIGlmIChcbiAgICAgICAgdGFiRGlyZWN0aW9uID09PSAnTkVYVF9UQUInICYmXG4gICAgICAgIG5ld0ZvY3VzYWJsZUluZGV4ID09PSB0aGlzLmNvYWNoSXRlbURldGFpbHNFbGVtZW50cy5sZW5ndGggLSAxXG4gICAgICApIHtcbiAgICAgICAgLy8gUmVmb2N1cyB0aGUgbGFzdCBjb2FjaFxuICAgICAgICB0aGlzLl9yZWZvY3VzQ3VycmVudEZvY3VzZWROYXZDb2FjaChjdXJyRm9jdXNJbmRleCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLmZvY3VzZWRDb2FjaEluZGV4ID0gLTE7XG4gICAgICAgIHRoaXMuc2VsZWN0ZWRDb2FjaEluZGV4ID0gbmV3Rm9jdXNhYmxlSW5kZXg7XG4gICAgICAgIC8vIElmIGFueSBwbGFjZSB3YXMgZm9jdXNlZCBpbiBjb2FjaCwgc28gd2Ugc2V0IGZvY3VzZWQgYWdhaW5cbiAgICAgICAgaWYgKHBsYWNlSW5Db2FjaEhhc0ZvY3VzKSB7XG4gICAgICAgICAgdGhpcy5mb2N1c1BsYWNlRWxlbWVudCh0aGlzLmN1cnJTZWxlY3RlZFBsYWNlKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBJZiBubyBwbGFjZSB3YXMgc2VsZWN0ZWQsIHRoZW4gd2Ugc2VsZWN0IHRoZSBjb2FjaCBncmlkXG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgIHRoaXMuaXNDb2FjaEdyaWRGb2N1c2FibGUgPSB0cnVlO1xuICAgICAgICAgIHRoaXMuX3NldEZvY3VzVG9TZWxlY3RlZENvYWNoR3JpZCgpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIC8vIEJ5IFRhYiBOYXZpZ2F0aW9uLCBwZXJmb3JtIGF1dG9tYXRpYyBzY3JvbGxpbmcgdG8gdGhlIGZvY3VzZWQgd2Fnb25cbiAgICAgIHRoaXMuX3Njcm9sbFRvU2VsZWN0ZWROYXZpZ2F0aW9uQnV0dG9uKG5ld0ZvY3VzYWJsZUluZGV4KTtcbiAgICB9XG4gICAgLy8gSWYgbm8gbmF2aWdhdGlvbiBleGlzdCwgd2Ugc2Nyb2xsIGRpcmVjdGx5IHRvIHRoZSBuZXh0IHRhYmFibGUgY29hY2hcbiAgICBlbHNlIHtcbiAgICAgIHRoaXMuc2Nyb2xsVG9TZWxlY3RlZE5hdkNvYWNoKG5ld0ZvY3VzYWJsZUluZGV4KTtcbiAgICB9XG4gIH1cblxuICAvLyBSZWZvY3VzZWQgdGhlIGN1cnJlbnQgZm9jdXNlZCAodmlzdWFsKSBuYXYgY29hY2ggdG8gZ2V0IHRoZSBuYXRpdmUgZm9jdXMgYmFjayB0byB0aGUgbmF2aWdhdGlvblxuICBwcml2YXRlIF9yZWZvY3VzQ3VycmVudEZvY3VzZWROYXZDb2FjaChmb2N1c0luZGV4OiBudW1iZXIpOiB2b2lkIHtcbiAgICB0aGlzLmZvY3VzZWRDb2FjaEluZGV4ID0gLTE7XG4gICAgc2V0VGltZW91dCgoKSA9PiAodGhpcy5mb2N1c2VkQ29hY2hJbmRleCA9IGZvY3VzSW5kZXgpLCAwKTtcbiAgfVxuXG4gIHByaXZhdGUgX25hdmlnYXRlVG9QbGFjZUJ5S2V5Ym9hcmQocHJlc3NlZEtleTogc3RyaW5nKTogdm9pZCB7XG4gICAgdGhpcy5pc0tleWJvYXJkTmF2aWdhdGlvbiA9IHRydWU7XG5cbiAgICBpZiAodGhpcy5mb2N1c2VkQ29hY2hJbmRleCAhPT0gLTEpIHtcbiAgICAgIHRoaXMuZm9jdXNlZENvYWNoSW5kZXggPSAtMTtcbiAgICB9XG5cbiAgICBpZiAoIXRoaXMucHJldmVudFBsYWNlQ2xpY2spIHtcbiAgICAgIGNvbnN0IGZpbmRDbG9zZXN0UGxhY2UgPSB0aGlzLl9nZXRDbG9zZXN0UGxhY2VCeUtleURpcmVjdGlvbihwcmVzc2VkS2V5KTtcblxuICAgICAgaWYgKGZpbmRDbG9zZXN0UGxhY2UpIHtcbiAgICAgICAgdGhpcy5mb2N1c1BsYWNlRWxlbWVudChmaW5kQ2xvc2VzdFBsYWNlKTtcbiAgICAgIH1cbiAgICAgIC8vIE5vIGNsb3Nlc3QgcGxhY2UgZm91bmQgYnkga2V5IG5hdmlnYXRpb25cbiAgICAgIGVsc2Uge1xuICAgICAgICBpZiAoXG4gICAgICAgICAgcHJlc3NlZEtleSA9PT0gdGhpcy5rZXlib2FyZE5hdmlnYXRpb25FdmVudHMuQXJyb3dSaWdodCB8fFxuICAgICAgICAgIHByZXNzZWRLZXkgPT09IHRoaXMua2V5Ym9hcmROYXZpZ2F0aW9uRXZlbnRzLkFycm93TGVmdCB8fFxuICAgICAgICAgICh0aGlzLmFsaWduVmVydGljYWwgJiZcbiAgICAgICAgICAgIChwcmVzc2VkS2V5ID09PSB0aGlzLmtleWJvYXJkTmF2aWdhdGlvbkV2ZW50cy5BcnJvd1VwIHx8XG4gICAgICAgICAgICAgIHByZXNzZWRLZXkgPT09IHRoaXMua2V5Ym9hcmROYXZpZ2F0aW9uRXZlbnRzLkFycm93RG93bikpXG4gICAgICAgICkge1xuICAgICAgICAgIC8vIENoZWNrIHRoZSBjdXJyZW50IHByZXNzZWQga2V5IHRvIGdldCB0aGUgbmV4dCBhdmFpbGFibGUgY29hY2ggaW5kZXhcbiAgICAgICAgICBjb25zdCBuZXdTZWxlY3RlZENvYWNoSW5kZXggPVxuICAgICAgICAgICAgcHJlc3NlZEtleSA9PT0gdGhpcy5rZXlib2FyZE5hdmlnYXRpb25FdmVudHMuQXJyb3dSaWdodFxuICAgICAgICAgICAgICA/IHRoaXMuZ2V0TmV4dEF2YWlsYWJsZUNvYWNoSW5kZXgoKVxuICAgICAgICAgICAgICA6IHRoaXMuZ2V0UHJldkF2YWlsYWJsZUNvYWNoSW5kZXgoKTtcblxuICAgICAgICAgIHRoaXMuc2Nyb2xsVG9TZWxlY3RlZE5hdkNvYWNoKG5ld1NlbGVjdGVkQ29hY2hJbmRleCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBwcm90ZWN0ZWQgZ2V0TmV4dEF2YWlsYWJsZUNvYWNoSW5kZXgoY3VycmVudEluZGV4PzogbnVtYmVyKTogbnVtYmVyIHtcbiAgICBjb25zdCBzdGFydEluZGV4ID0gY3VycmVudEluZGV4ID8/IHRoaXMuY3VyclNlbGVjdGVkQ29hY2hJbmRleDtcbiAgICByZXR1cm4gc3RhcnRJbmRleCA8IHRoaXMuc2VhdFJlc2VydmF0aW9uc1t0aGlzLmN1cnJTZWxlY3RlZERlY2tJbmRleF0uY29hY2hJdGVtcy5sZW5ndGggLSAxXG4gICAgICA/IHN0YXJ0SW5kZXggKyAxXG4gICAgICA6IHN0YXJ0SW5kZXg7XG4gIH1cblxuICBwcm90ZWN0ZWQgZ2V0UHJldkF2YWlsYWJsZUNvYWNoSW5kZXgoY3VycmVudEluZGV4PzogbnVtYmVyKTogbnVtYmVyIHtcbiAgICBjb25zdCBzdGFydEluZGV4ID0gY3VycmVudEluZGV4ID8/IHRoaXMuY3VyclNlbGVjdGVkQ29hY2hJbmRleDtcbiAgICByZXR1cm4gc3RhcnRJbmRleCA+IDAgPyBzdGFydEluZGV4IC0gMSA6IHN0YXJ0SW5kZXg7XG4gIH1cblxuICBwcm90ZWN0ZWQgdXBkYXRlU2VsZWN0ZWRTZWF0UmVzZXJ2YXRpb25QbGFjZXMocGxhY2VTZWxlY3Rpb246IFBsYWNlU2VsZWN0aW9uKTogdm9pZCB7XG4gICAgY29uc3QgcGxhY2VUeXBlUHJvcCA9IHBsYWNlU2VsZWN0aW9uLnBsYWNlVHlwZSA9PT0gJ1NFQVQnID8gJ3NlYXRzJyA6ICdiaWN5Y2xlcyc7XG4gICAgY29uc3QgbWF4UmVzZXJ2YXRpb25zID1cbiAgICAgIHBsYWNlU2VsZWN0aW9uLnBsYWNlVHlwZSA9PT0gJ1NFQVQnID8gdGhpcy5tYXhTZWF0UmVzZXJ2YXRpb25zIDogdGhpcy5tYXhCaWN5Y2xlUmVzZXJ2YXRpb25zO1xuICAgIGNvbnN0IGN1cnJTZWxlY3RlZFBsYWNlcyA9IHRoaXMuc2VsZWN0ZWRTZWF0UmVzZXJ2YXRpb25QbGFjZXNbcGxhY2VUeXBlUHJvcF07XG5cbiAgICB0aGlzLnNlbGVjdGVkU2VhdFJlc2VydmF0aW9uUGxhY2VzW3BsYWNlVHlwZVByb3BdID0gdGhpcy5fdXBkYXRlU2VsZWN0ZWRTZWF0UmVzZXJ2YXRpb25QbGFjZXMoXG4gICAgICBjdXJyU2VsZWN0ZWRQbGFjZXMsXG4gICAgICBtYXhSZXNlcnZhdGlvbnMsXG4gICAgICBwbGFjZVNlbGVjdGlvbixcbiAgICApO1xuICAgIC8qKlxuICAgICAqIEB0eXBlIHtDdXN0b21FdmVudDxTZWF0UmVzZXJ2YXRpb25TZWxlY3RlZFBsYWNlcz59XG4gICAgICogRW1pdHMgd2hlbiBhIHBsYWNlIHdhcyBzZWxlY3RlZCBhbmQgcmV0dXJucyBhIFBsYWNlIGFycmF5IHdpdGggYWxsIHNlbGVjdGVkIHBsYWNlcy5cbiAgICAgKi9cbiAgICB0aGlzLmRpc3BhdGNoRXZlbnQoXG4gICAgICBuZXcgQ3VzdG9tRXZlbnQ8U2VhdFJlc2VydmF0aW9uU2VsZWN0ZWRQbGFjZXM+KCdzZWxlY3RlZHBsYWNlcycsIHtcbiAgICAgICAgYnViYmxlczogdHJ1ZSxcbiAgICAgICAgY29tcG9zZWQ6IHRydWUsXG4gICAgICAgIGRldGFpbDogdGhpcy5zZWxlY3RlZFNlYXRSZXNlcnZhdGlvblBsYWNlcyxcbiAgICAgIH0pLFxuICAgICk7XG4gIH1cblxuICBwcml2YXRlIF91cGRhdGVTZWxlY3RlZFNlYXRSZXNlcnZhdGlvblBsYWNlcyhcbiAgICBzZWxlY3RlZFNlYXRSZXNlcnZhdGlvblBsYWNlczogU2VhdFJlc2VydmF0aW9uUGxhY2VTZWxlY3Rpb25bXSxcbiAgICBtYXhSZXNlcnZhdGlvbnM6IG51bWJlcixcbiAgICBwbGFjZVNlbGVjdGlvbjogUGxhY2VTZWxlY3Rpb24sXG4gICk6IFNlYXRSZXNlcnZhdGlvblBsYWNlU2VsZWN0aW9uW10ge1xuICAgIC8vIEFkZCBzZWxlY3RlZCBwbGFjZSB0byBzZWxlY3RlZFNlYXRSZXNlcnZhdGlvblBsYWNlc1xuICAgIGlmIChwbGFjZVNlbGVjdGlvbi5zdGF0ZSA9PT0gJ1NFTEVDVEVEJykge1xuICAgICAgY29uc3Qgc2VsZWN0ZWRQbGFjZURlY2tJbmRleCA9IHRoaXMuX2dldERlY2tJbmRleEJ5UGxhY2VJZChwbGFjZVNlbGVjdGlvbi5pZCk7XG4gICAgICBjb25zdCBzZWF0UmVzZXJ2YXRpb25TZWxlY3Rpb24gPSB0aGlzLl9nZXRTZWF0UmVzZXJ2YXRpb25QbGFjZVNlbGVjdGlvbihcbiAgICAgICAgcGxhY2VTZWxlY3Rpb24sXG4gICAgICAgIHNlbGVjdGVkUGxhY2VEZWNrSW5kZXgsXG4gICAgICApO1xuICAgICAgaWYgKHNlYXRSZXNlcnZhdGlvblNlbGVjdGlvbikge1xuICAgICAgICBzZWxlY3RlZFNlYXRSZXNlcnZhdGlvblBsYWNlcy5wdXNoKHNlYXRSZXNlcnZhdGlvblNlbGVjdGlvbik7XG4gICAgICB9XG4gICAgfVxuICAgIC8vIFJlbW92ZSBzZWxlY3RlZCBwbGFjZSBmcm9tIHNlbGVjdGVkU2VhdFJlc2VydmF0aW9uUGxhY2VzXG4gICAgZWxzZSB7XG4gICAgICBzZWxlY3RlZFNlYXRSZXNlcnZhdGlvblBsYWNlcyA9IHNlbGVjdGVkU2VhdFJlc2VydmF0aW9uUGxhY2VzLmZpbHRlcihcbiAgICAgICAgKF9zZWxlY3RlZFBsYWNlKSA9PiBfc2VsZWN0ZWRQbGFjZS5pZCAhPT0gcGxhY2VTZWxlY3Rpb24uaWQsXG4gICAgICApO1xuICAgIH1cbiAgICAvLyBDaGVja3Mgd2hldGhlciBtYXhSZXNlcnZhdGlvbiBpcyBhY3RpdmF0ZWQgYW5kIHRoZSBtYXhpbXVtIG51bWJlciBvZiBzZWxlY3RlZCBwbGFjZXMgaXMgcmVhY2hlZFxuICAgIGlmIChtYXhSZXNlcnZhdGlvbnMgPiAtMSAmJiBzZWxlY3RlZFNlYXRSZXNlcnZhdGlvblBsYWNlcy5sZW5ndGggPiBtYXhSZXNlcnZhdGlvbnMpIHtcbiAgICAgIGNvbnN0IHJlc2V0V2l0aFBsYWNlU2VsZWN0aW9uID0gbWF4UmVzZXJ2YXRpb25zID4gMCA/IHBsYWNlU2VsZWN0aW9uIDogdW5kZWZpbmVkO1xuXG4gICAgICBzZWxlY3RlZFNlYXRSZXNlcnZhdGlvblBsYWNlcyA9IHRoaXMuX3Jlc2V0QWxsUGxhY2VTZWxlY3Rpb25zKFxuICAgICAgICBzZWxlY3RlZFNlYXRSZXNlcnZhdGlvblBsYWNlcyxcbiAgICAgICAgcmVzZXRXaXRoUGxhY2VTZWxlY3Rpb24sXG4gICAgICApO1xuICAgIH1cbiAgICByZXR1cm4gc2VsZWN0ZWRTZWF0UmVzZXJ2YXRpb25QbGFjZXM7XG4gIH1cblxuICBwcm90ZWN0ZWQgdXBkYXRlQ3VycmVudFNlbGVjdGVkUGxhY2VJbkNvYWNoKHBsYWNlU2VsZWN0aW9uOiBQbGFjZVNlbGVjdGlvbik6IHZvaWQge1xuICAgIGNvbnN0IHBsYWNlRGVja0luZGV4ID0gdGhpcy5fZ2V0RGVja0luZGV4QnlQbGFjZUlkKHBsYWNlU2VsZWN0aW9uLmlkKTtcbiAgICBjb25zdCBjb2FjaEluZGV4ID0gcGxhY2VTZWxlY3Rpb24uY29hY2hJbmRleDtcblxuICAgIGlmIChwbGFjZURlY2tJbmRleCA9PT0gbnVsbCkgcmV0dXJuO1xuXG4gICAgY29uc3QgcGxhY2UgPSB0aGlzLnNlYXRSZXNlcnZhdGlvbnNbcGxhY2VEZWNrSW5kZXhdLmNvYWNoSXRlbXNbY29hY2hJbmRleF0ucGxhY2VzPy5maW5kKFxuICAgICAgKHBsYWNlKSA9PiBwbGFjZS5udW1iZXIgPT0gcGxhY2VTZWxlY3Rpb24ubnVtYmVyLFxuICAgICk7XG5cbiAgICBpZiAoIXBsYWNlKSByZXR1cm47XG5cbiAgICB0aGlzLmN1cnJTZWxlY3RlZERlY2tJbmRleCA9IHBsYWNlRGVja0luZGV4O1xuICAgIHRoaXMuY3VyclNlbGVjdGVkQ29hY2hJbmRleCA9IGNvYWNoSW5kZXg7XG4gICAgdGhpcy5jdXJyU2VsZWN0ZWRQbGFjZSA9IHBsYWNlO1xuXG4gICAgaWYgKHRoaXMuY3VyclNlbGVjdGVkQ29hY2hJbmRleCAhPT0gdGhpcy5zZWxlY3RlZENvYWNoSW5kZXgpIHtcbiAgICAgIHRoaXMudXBkYXRlQ3VycmVudFNlbGVjdGVkQ29hY2goKTtcbiAgICB9XG5cbiAgICB0aGlzLl9zZXRDdXJyU2VsZWN0ZWRQbGFjZUVsZW1lbnRJZChwbGFjZSk7XG5cbiAgICAvLyBUaW1lIGRlbGF5IHRvIHdhaXQgZm9yIHN0YXR1cyB1cGRhdGUgcHJvY2VzcyBhdCBjbGlja2VkIHBsYWNlXG4gICAgY29uc3QgZGVsYXlTY3JvbGxJblZpZXdwb3J0ID0gc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICB0aGlzLl9zY3JvbGxQbGFjZUludG9OZWFyZXN0Vmlld3BvcnQocGxhY2VTZWxlY3Rpb24uaWQpO1xuICAgICAgY2xlYXJUaW1lb3V0KGRlbGF5U2Nyb2xsSW5WaWV3cG9ydCk7XG4gICAgfSwgMCk7XG4gIH1cblxuICBwcm90ZWN0ZWQgdXBkYXRlQ3VycmVudFNlbGVjdGVkQ29hY2goKTogdm9pZCB7XG4gICAgLy9Pbmx5IGlmIHRoZSBzZWxlY3RlZENvYWNoSW5kZXggaGFzIGNoYW5nZWQsIGFuIHVwZGF0ZSBuZWVkcyB0byBiZSBjYXJyaWVkIG91dFxuICAgIGlmICh0aGlzLmN1cnJTZWxlY3RlZENvYWNoSW5kZXggPT0gdGhpcy5zZWxlY3RlZENvYWNoSW5kZXgpIHJldHVybjtcblxuICAgIC8vIElmIGEgZm9jdXNpbmRleCBoYXMgYmVlbiBzZXQgKCE9IC0xKSwgaXQgY2FuIGJlIHVwZGF0ZWQgd2l0aCB0aGUgY3VycmVudCBzZWxlY3RlZENvYWNoSW5kZXhcbiAgICBpZiAodGhpcy5mb2N1c2VkQ29hY2hJbmRleCAhPSAtMSkge1xuICAgICAgdGhpcy5mb2N1c2VkQ29hY2hJbmRleCA9IHRoaXMuY3VyclNlbGVjdGVkQ29hY2hJbmRleDtcbiAgICB9XG4gICAgdGhpcy5zZWxlY3RlZENvYWNoSW5kZXggPSB0aGlzLmN1cnJTZWxlY3RlZENvYWNoSW5kZXg7XG5cbiAgICBjb25zdCBjb2FjaFNlbGVjdGlvbiA9IHRoaXMuX2dldFNlYXRSZXNlcnZhdGlvblNlbGVjdGVkQ29hY2godGhpcy5zZWxlY3RlZENvYWNoSW5kZXgpO1xuICAgIGlmIChjb2FjaFNlbGVjdGlvbikge1xuICAgICAgLyoqXG4gICAgICAgKiBAdHlwZSB7Q3VzdG9tRXZlbnQ8U2VhdFJlc2VydmF0aW9uU2VsZWN0ZWRDb2FjaD59XG4gICAgICAgKiBFbWl0cyB3aGVuIGEgY29hY2ggd2FzIHNlbGVjdGVkIGFuZCByZXR1cm5zIGEgQ29hY2hTZWxlY3Rpb25cbiAgICAgICAqL1xuICAgICAgdGhpcy5kaXNwYXRjaEV2ZW50KFxuICAgICAgICBuZXcgQ3VzdG9tRXZlbnQ8U2VhdFJlc2VydmF0aW9uU2VsZWN0ZWRDb2FjaD4oJ3NlbGVjdGVkY29hY2gnLCB7XG4gICAgICAgICAgYnViYmxlczogdHJ1ZSxcbiAgICAgICAgICBjb21wb3NlZDogdHJ1ZSxcbiAgICAgICAgICBkZXRhaWw6IGNvYWNoU2VsZWN0aW9uLFxuICAgICAgICB9KSxcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgcHJvdGVjdGVkIGdldFBsYWNlRWxlbWVudElkKFxuICAgIGNvYWNoRGVja0luZGV4OiBudW1iZXIsXG4gICAgY29hY2hJbmRleDogbnVtYmVyLFxuICAgIHBsYWNlTnVtYmVyOiBzdHJpbmcsXG4gICk6IHN0cmluZyB7XG4gICAgcmV0dXJuIChcbiAgICAgICdzZWF0LXJlc2VydmF0aW9uX19wbGFjZS1idXR0b24tJyArIGNvYWNoRGVja0luZGV4ICsgJy0nICsgY29hY2hJbmRleCArICctJyArIHBsYWNlTnVtYmVyXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBJbiB0aGUgY2FzZSBvZiBjb2FjaCBsYXlvdXRzIHdpdGggZGlmZmVyZW50IGRlY2tzLFxuICAgKiBpdCBpcyBuZWNlc3NhcnkgdG8gZXh0ZW5kIHRoZSBvZmZzZXQgd2l0aCBlbXB0eSBjb2FjaGVzXG4gICAqIGluIG9yZGVyIHRvIGNyZWF0ZSBhIHN0YWJsZSB2ZWhpY2xlIGxheW91dC5cbiAgICpcbiAgICogICAgICAgICAgICAgW29vb10tW29vb10tW29vb11cbiAgICogW29vb10tW29vb10tW29vb10tW29vb10tW29vb11cbiAgICovXG4gIHByaXZhdGUgX2luaXRFbXB0eUNvYWNoRGVja09mZnNldHMoKTogdm9pZCB7XG4gICAgLy8gUHJlZmlsbCBvZmZzZXQgY291bnRlcnMgd2l0aCAwIHN0YXJ0IGluZGV4XG4gICAgY29uc3QgY29hY2hPZmZzZXRJbmRleENvdW50ZXIgPSBBcnJheSh0aGlzLnNlYXRSZXNlcnZhdGlvbnMubGVuZ3RoIC0gMSkuZmlsbCgwKTtcbiAgICAvLyBUYWtlcyB0aGUgbG93ZXIgZGVjayB3aGljaCBjb250YWlucyB0aGUgbWF4IG51bWJlcnMgb2YgY29hY2hlc1xuICAgIGNvbnN0IGxvd2VyRGVjayA9IHRoaXMuc2VhdFJlc2VydmF0aW9uc1t0aGlzLnNlYXRSZXNlcnZhdGlvbnMubGVuZ3RoIC0gMV07XG5cbiAgICBsb3dlckRlY2suY29hY2hJdGVtcy5mb3JFYWNoKChsb3dlckNvYWNoSXRlbTogQ29hY2hJdGVtKSA9PiB7XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuc2VhdFJlc2VydmF0aW9ucy5sZW5ndGggLSAxOyBpKyspIHtcbiAgICAgICAgY29uc3QgZGVja0NvYWNoSXRlbSA9IHRoaXMuc2VhdFJlc2VydmF0aW9uc1tpXS5jb2FjaEl0ZW1zW2NvYWNoT2Zmc2V0SW5kZXhDb3VudGVyW2ldXTtcbiAgICAgICAgaWYgKGxvd2VyQ29hY2hJdGVtLmlkICE9IGRlY2tDb2FjaEl0ZW0/LmlkKSB7XG4gICAgICAgICAgLy8gQWRkIEVtcHR5IG9mZnNldCBjb2FjaCB0byBzcGVjaWZpZWQgaW5kZXggcG9zaXRpb25cbiAgICAgICAgICBjb25zdCBlbXB0eU9mZnNldENvYWNoID0ge1xuICAgICAgICAgICAgLi4ubG93ZXJDb2FjaEl0ZW0sXG4gICAgICAgICAgICBwbGFjZXM6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgIHByb3BlcnR5SWRzOiB1bmRlZmluZWQsXG4gICAgICAgICAgICBncmFwaGljRWxlbWVudHM6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgIHNlcnZpY2VFbGVtZW50czogdW5kZWZpbmVkLFxuICAgICAgICAgICAgdHJhdmVsQ2xhc3M6IFtdLFxuICAgICAgICAgIH07XG4gICAgICAgICAgdGhpcy5zZWF0UmVzZXJ2YXRpb25zW2ldLmNvYWNoSXRlbXMuc3BsaWNlKFxuICAgICAgICAgICAgY29hY2hPZmZzZXRJbmRleENvdW50ZXJbaV0sXG4gICAgICAgICAgICAwLFxuICAgICAgICAgICAgZW1wdHlPZmZzZXRDb2FjaCxcbiAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgY29hY2hPZmZzZXRJbmRleENvdW50ZXJbaV0rKztcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBJbml0aWFsaXphdGlvbiBvZiBTZWF0UmVzZXJ2YXRpb25QbGFjZVNlbGVjdGlvbiBBcnJheSBiYXNlZCBvbiB0aGUgdHJhbnNmZXJyZWQgcGxhY2VzXG4gICAqIHRoYXQgaGF2ZSB0aGUgc3RhdGUgU0VMRUNURUQgd2l0aGluIHRoZSBzZWF0UmVzZXJ2YXRpb24gb2JqZWN0XG4gICAqL1xuICBwcml2YXRlIF9pbml0U2VhdFJlc2VydmF0aW9uUGxhY2VTZWxlY3Rpb24oKTogdm9pZCB7XG4gICAgLy8gUmVzZXQgcGxhY2Ugc2VsZWN0aW9uc1xuICAgIHRoaXMuc2VsZWN0ZWRTZWF0UmVzZXJ2YXRpb25QbGFjZXMuc2VhdHMgPSBbXTtcbiAgICB0aGlzLnNlbGVjdGVkU2VhdFJlc2VydmF0aW9uUGxhY2VzLmJpY3ljbGVzID0gW107XG5cbiAgICB0aGlzLnNlYXRSZXNlcnZhdGlvbnM/LmZvckVhY2goKHNlYXRSZXNlcnZhdGlvbjogU2VhdFJlc2VydmF0aW9uLCBjb2FjaERlY2tJbmRleDogbnVtYmVyKSA9PlxuICAgICAgc2VhdFJlc2VydmF0aW9uLmNvYWNoSXRlbXMubWFwKChjb2FjaDogQ29hY2hJdGVtLCBjb2FjaEluZGV4OiBudW1iZXIpID0+IHtcbiAgICAgICAgY29hY2gucGxhY2VzXG4gICAgICAgICAgPy5maWx0ZXIoKHBsYWNlKSA9PiBwbGFjZS5zdGF0ZSA9PT0gJ1NFTEVDVEVEJylcbiAgICAgICAgICA/LmZvckVhY2goKHBsYWNlKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBwbGFjZUlkID0gdGhpcy5nZXRQbGFjZUVsZW1lbnRJZChjb2FjaERlY2tJbmRleCwgY29hY2hJbmRleCwgcGxhY2UubnVtYmVyKTtcbiAgICAgICAgICAgIGNvbnN0IHByZXNlbGVjdGVkUGxhY2VTZWxlY3Rpb246IFBsYWNlU2VsZWN0aW9uID0gbWFwUGxhY2VJbmZvc1RvUGxhY2VTZWxlY3Rpb24oXG4gICAgICAgICAgICAgIHBsYWNlLFxuICAgICAgICAgICAgICBwbGFjZUlkLFxuICAgICAgICAgICAgICBzZWF0UmVzZXJ2YXRpb24uZGVja0NvYWNoSW5kZXgsXG4gICAgICAgICAgICAgIGNvYWNoSW5kZXgsXG4gICAgICAgICAgICApO1xuXG4gICAgICAgICAgICBjb25zdCBzZWF0UmVzZXJ2YXRpb25QbGFjZVNlbGVjdGlvbjogU2VhdFJlc2VydmF0aW9uUGxhY2VTZWxlY3Rpb24gfCBudWxsID1cbiAgICAgICAgICAgICAgdGhpcy5fZ2V0U2VhdFJlc2VydmF0aW9uUGxhY2VTZWxlY3Rpb24ocHJlc2VsZWN0ZWRQbGFjZVNlbGVjdGlvbiwgY29hY2hEZWNrSW5kZXgpO1xuXG4gICAgICAgICAgICBpZiAoc2VhdFJlc2VydmF0aW9uUGxhY2VTZWxlY3Rpb24pIHtcbiAgICAgICAgICAgICAgaWYgKHNlYXRSZXNlcnZhdGlvblBsYWNlU2VsZWN0aW9uLnBsYWNlVHlwZSA9PT0gJ1NFQVQnKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zZWxlY3RlZFNlYXRSZXNlcnZhdGlvblBsYWNlcy5zZWF0cy5wdXNoKHNlYXRSZXNlcnZhdGlvblBsYWNlU2VsZWN0aW9uKTtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNlbGVjdGVkU2VhdFJlc2VydmF0aW9uUGxhY2VzLmJpY3ljbGVzLnB1c2goc2VhdFJlc2VydmF0aW9uUGxhY2VTZWxlY3Rpb24pO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG4gICAgICB9KSxcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIEFsbCBzZWxlY3RlZCBwbGFjZXMgd2lsbCBiZSByZXNldCBvciB0aGUgY3VycmVudFNlbGVjdGVkUGxhY2Ugd2FzIGdpdmVuLCB0aGVuIHdlIHJlc2V0IGFsbCBleGNlcHQgY3VycmVudFNlbGVjdGVkUGxhY2VcbiAgICogQHBhcmFtIHJlc2VydmF0aW9uUGxhY2VTZWxlY3Rpb25zXG4gICAqIEBwYXJhbSBjdXJyU2VsZWN0ZWRQbGFjZVxuICAgKi9cbiAgcHJpdmF0ZSBfcmVzZXRBbGxQbGFjZVNlbGVjdGlvbnMoXG4gICAgcmVzZXJ2YXRpb25QbGFjZVNlbGVjdGlvbnM6IFNlYXRSZXNlcnZhdGlvblBsYWNlU2VsZWN0aW9uW10sXG4gICAgY3VyclNlbGVjdGVkUGxhY2U/OiBQbGFjZVNlbGVjdGlvbixcbiAgKTogU2VhdFJlc2VydmF0aW9uUGxhY2VTZWxlY3Rpb25bXSB7XG4gICAgLy9GaW5kIGFsbCBwbGFjZXMgdG8gYmUgbmVlZGVkIHVuc2VsZWN0XG4gICAgZm9yIChjb25zdCBwbGFjZVNlbGVjdGlvbiBvZiByZXNlcnZhdGlvblBsYWNlU2VsZWN0aW9ucykge1xuICAgICAgaWYgKCFjdXJyU2VsZWN0ZWRQbGFjZSB8fCBjdXJyU2VsZWN0ZWRQbGFjZS5pZCAhPT0gcGxhY2VTZWxlY3Rpb24uaWQpIHtcbiAgICAgICAgY29uc3QgcGxhY2VFbGVtZW50ID0gdGhpcy5zaGFkb3dSb290Py5nZXRFbGVtZW50QnlJZChwbGFjZVNlbGVjdGlvbi5pZCkgYXMgSFRNTEVsZW1lbnQ7XG4gICAgICAgIGlmIChwbGFjZUVsZW1lbnQpIHtcbiAgICAgICAgICBwbGFjZUVsZW1lbnQuc2V0QXR0cmlidXRlKCdzdGF0ZScsICdGUkVFJyk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgLy9SZW1vdmVzIGFsbCBzZWxlY3RlZCBwbGFjZXMgZXhjZXB0IHRoZSBjdXJyZW50bHkgc2VsZWN0ZWQgcGxhY2VcbiAgICBpZiAoY3VyclNlbGVjdGVkUGxhY2UpIHtcbiAgICAgIHJlc2VydmF0aW9uUGxhY2VTZWxlY3Rpb25zID0gcmVzZXJ2YXRpb25QbGFjZVNlbGVjdGlvbnMuZmlsdGVyKFxuICAgICAgICAoX3NlbGVjdGVkUGxhY2UpID0+IF9zZWxlY3RlZFBsYWNlLmlkID09PSBjdXJyU2VsZWN0ZWRQbGFjZS5pZCxcbiAgICAgICk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJlc2VydmF0aW9uUGxhY2VTZWxlY3Rpb25zID0gW107XG4gICAgfVxuICAgIHJldHVybiByZXNlcnZhdGlvblBsYWNlU2VsZWN0aW9ucztcbiAgfVxuXG4gIHByaXZhdGUgX2dldFNlYXRSZXNlcnZhdGlvblBsYWNlU2VsZWN0aW9uKFxuICAgIGN1cnJTZWxlY3RlZFBsYWNlOiBQbGFjZVNlbGVjdGlvbixcbiAgICBjb2FjaERlY2tJbmRleDogbnVtYmVyIHwgbnVsbCxcbiAgKTogU2VhdFJlc2VydmF0aW9uUGxhY2VTZWxlY3Rpb24gfCBudWxsIHtcbiAgICBpZiAoY29hY2hEZWNrSW5kZXggPT09IG51bGwpIHJldHVybiBudWxsO1xuXG4gICAgY29uc3QgY29hY2ggPSB0aGlzLnNlYXRSZXNlcnZhdGlvbnNbY29hY2hEZWNrSW5kZXhdLmNvYWNoSXRlbXNbY3VyclNlbGVjdGVkUGxhY2UuY29hY2hJbmRleF07XG4gICAgY29uc3QgcGxhY2UgPSBjb2FjaC5wbGFjZXM/LmZpbmQoKHBsYWNlKSA9PiBwbGFjZS5udW1iZXIgPT09IGN1cnJTZWxlY3RlZFBsYWNlLm51bWJlcik7XG5cbiAgICByZXR1cm4gcGxhY2VcbiAgICAgID8gbWFwUGxhY2VBbmRDb2FjaFRvU2VhdFJlc2VydmF0aW9uUGxhY2VTZWxlY3Rpb24oXG4gICAgICAgICAgcGxhY2UsXG4gICAgICAgICAgY29hY2gsXG4gICAgICAgICAgY3VyclNlbGVjdGVkUGxhY2UuaWQsXG4gICAgICAgICAgY3VyclNlbGVjdGVkUGxhY2UuZGVja0luZGV4LFxuICAgICAgICAgIGN1cnJTZWxlY3RlZFBsYWNlLmNvYWNoSW5kZXgsXG4gICAgICAgIClcbiAgICAgIDogbnVsbDtcbiAgfVxuXG4gIHByaXZhdGUgX2dldFNlYXRSZXNlcnZhdGlvblNlbGVjdGVkQ29hY2goXG4gICAgY29hY2hJbmRleDogbnVtYmVyLFxuICApOiBTZWF0UmVzZXJ2YXRpb25TZWxlY3RlZENvYWNoIHwgbnVsbCB7XG4gICAgaWYgKCF0aGlzLnNlYXRSZXNlcnZhdGlvbnNbdGhpcy5jdXJyU2VsZWN0ZWREZWNrSW5kZXhdLmNvYWNoSXRlbXNbY29hY2hJbmRleF0pIHJldHVybiBudWxsO1xuXG4gICAgY29uc3QgY29hY2ggPSB0aGlzLnNlYXRSZXNlcnZhdGlvbnNbdGhpcy5jdXJyU2VsZWN0ZWREZWNrSW5kZXhdLmNvYWNoSXRlbXNbY29hY2hJbmRleF07XG4gICAgY29uc3QgY29hY2hOdW1iZXJPZkZyZWVQbGFjZXMgPSB0aGlzLmdldEF2YWlsYWJsZUZyZWVQbGFjZXNOdW1Gcm9tQ29hY2goY29hY2gucGxhY2VzKTtcbiAgICByZXR1cm4gbWFwQ29hY2hJbmZvc1RvQ29hY2hTZWxlY3Rpb24oY29hY2hJbmRleCwgY29hY2gsIGNvYWNoTnVtYmVyT2ZGcmVlUGxhY2VzKTtcbiAgfVxuXG4gIHByaXZhdGUgX3NldEN1cnJTZWxlY3RlZFBsYWNlRWxlbWVudElkKHBsYWNlOiBQbGFjZSB8IG51bGwpOiB2b2lkIHtcbiAgICB0aGlzLmN1cnJTZWxlY3RlZFBsYWNlRWxlbWVudElkID0gcGxhY2VcbiAgICAgID8gdGhpcy5nZXRQbGFjZUVsZW1lbnRJZChcbiAgICAgICAgICB0aGlzLmN1cnJTZWxlY3RlZERlY2tJbmRleCxcbiAgICAgICAgICB0aGlzLmN1cnJTZWxlY3RlZENvYWNoSW5kZXgsXG4gICAgICAgICAgcGxhY2UubnVtYmVyLFxuICAgICAgICApXG4gICAgICA6IG51bGw7XG4gIH1cblxuICAvKipcbiAgICogUHJlcGFyYXRpb24gb2YgdGhlIHVzZWQgZG9jdW1lbnRzIGZvbnQtc2l6ZSB3aGljaCBuZWVkc1xuICAgKiB0byBiZSBkZXRlcm1pbmVkIGluIG9yZGVyIHRvIGNvcnJlY3RseSBjYWxjdWxhdGUgQ1NTIHZhbHVlcyB3aXRoIHJlbVxuICAgKiAqL1xuICBwcml2YXRlIF9kZXRlcm1pbmVCYXNlRm9udFNpemUoKTogdm9pZCB7XG4gICAgaWYgKCFpc1NlcnZlcikge1xuICAgICAgY29uc3QgYmFzZUZvbnRTaXplID0gcGFyc2VJbnQod2luZG93LmdldENvbXB1dGVkU3R5bGUoZG9jdW1lbnQuYm9keSkuZm9udFNpemUsIDEwKTtcbiAgICAgIC8vY2FsY3VsYXRlIHJlbSBvZiAxcHhcbiAgICAgIGNvbnN0IG9uZVBpeGVsSW5SZW0gPSAxIC8gYmFzZUZvbnRTaXplO1xuICAgICAgdGhpcy5zdHlsZT8uc2V0UHJvcGVydHkoJy0tc2JiLXNlYXQtcmVzZXJ2YXRpb24tb25lLXB4LXJlbScsIGAke29uZVBpeGVsSW5SZW0gKyAncmVtJ31gKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUHJlcGFyZXMgZGF0YSBmb3IgZGlzcGxheWluZyBuYXZpZ2F0aW9uIGFyZWEuXG4gICAqIENhbGN1bGF0ZXMgdGhlIHZhbHVlcyB3aGljaCBhcmUgbm90IGdvaW5nIHRvIGNoYW5nZSBkdXJpbmcgdXNlIG9mIGEgY29tcG9uZW50OlxuICAgKiAgICAtIGNvYWNoIGlkXG4gICAqICAgIC0gbGlzdCBvZiBzZXJ2aWNlIGljb25zXG4gICAqICAgIC0gY2xhc3MgKGZpcnN0LCBzZWNvbmQsIGFueSlcbiAgICogICAgLSB3aGV0aGVyIHRoZXJlIGlzIGEgZHJpdmVyIGFyZWEgbGVmdCBvciByaWdodFxuICAgKiAqL1xuICBwcml2YXRlIF9wcmVwYXJlQ29hY2hJdGVtRGV0YWlsc0RhdGEoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuc2VhdFJlc2VydmF0aW9ucykge1xuICAgICAgY29uc3QgbG93ZXJEZWNrOiBDb2FjaEl0ZW1bXSA9XG4gICAgICAgIHRoaXMuc2VhdFJlc2VydmF0aW9uc1t0aGlzLnNlYXRSZXNlcnZhdGlvbnMubGVuZ3RoIC0gMV0uY29hY2hJdGVtcztcblxuICAgICAgdGhpcy5jb2FjaEl0ZW1EZXRhaWxzRWxlbWVudHMgPSBbXTtcblxuICAgICAgbG93ZXJEZWNrLmZvckVhY2goKGNvYWNoLCBpbmRleCkgPT4ge1xuICAgICAgICBjb25zdCB0cmF2ZWxDbGFzc2VzOiBQbGFjZVRyYXZlbENsYXNzW10gPSBbXTtcbiAgICAgICAgY29uc3QgcHJvcGVydHlJZHM6IHN0cmluZ1tdID0gW107XG4gICAgICAgIGNvbnN0IHBsYWNlczogUGxhY2VbXSA9IFtdO1xuXG4gICAgICAgIC8vIENvbGxlY3QgYWxsIGltcG9ydGFudCBuYXZpZ2F0aW9uIGRhdGEgdG8gYmUgcmVuZGVyZWRcbiAgICAgICAgdGhpcy5zZWF0UmVzZXJ2YXRpb25zXG4gICAgICAgICAgLm1hcCgoc3IpID0+IHtcbiAgICAgICAgICAgIHJldHVybiBzci5jb2FjaEl0ZW1zW2luZGV4XTtcbiAgICAgICAgICB9KVxuICAgICAgICAgIC5mb3JFYWNoKChjb2FjaDogQ29hY2hJdGVtKSA9PiB7XG4gICAgICAgICAgICB0cmF2ZWxDbGFzc2VzLnB1c2goLi4uY29hY2gudHJhdmVsQ2xhc3MpO1xuICAgICAgICAgICAgcHJvcGVydHlJZHMucHVzaCguLi4oY29hY2gucHJvcGVydHlJZHMgPyBjb2FjaC5wcm9wZXJ0eUlkcyA6IFtdKSk7XG4gICAgICAgICAgICBwbGFjZXMucHVzaCguLi4oY29hY2gucGxhY2VzID8gY29hY2gucGxhY2VzIDogW10pKTtcbiAgICAgICAgICB9KTtcblxuICAgICAgICB0aGlzLmNvYWNoSXRlbURldGFpbHNFbGVtZW50cy5wdXNoKHtcbiAgICAgICAgICBpZDogY29hY2guaWQsXG4gICAgICAgICAgdHJhdmVsQ2xhc3M6IHRoaXMuX3ByZXBhcmVUcmF2ZWxDbGFzc05hdmlnYXRpb24odHJhdmVsQ2xhc3NlcyksXG4gICAgICAgICAgcHJvcGVydHlJZHM6IHRoaXMuX3ByZXBhcmVTZXJ2aWNlSWNvbnNOYXZpZ2F0aW9uKHByb3BlcnR5SWRzKSxcbiAgICAgICAgICBpc0RyaXZlckFyZWE6IGNvYWNoLnBsYWNlcyA/IGNvYWNoLnBsYWNlcy5sZW5ndGggPT09IDAgOiB0cnVlLFxuICAgICAgICAgIGRyaXZlckFyZWFTaWRlOiB0aGlzLl9wcmVwYXJlRHJpdmVyQXJlYVNpZGVOYXZpZ2F0aW9uKGNvYWNoKSxcbiAgICAgICAgICBmcmVlUGxhY2VzOiB0aGlzLmdldEF2YWlsYWJsZUZyZWVQbGFjZXNOdW1Gcm9tQ29hY2gocGxhY2VzKSxcbiAgICAgICAgICBkcml2ZXJBcmVhRWxlbWVudHM6IHRoaXMuX3NldERyaXZlckFyZWFzRWxlbWVudHMoY29hY2gpLFxuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIC8vICNUSU1PLTQ1ODU4XG4gIC8vIEZpbmRzIHRoZSBvcHRpbWFsIGljb24gc2l6ZSBiYXNlZCBvbiBhbGwgc2VydmljZUVsZW1lbnRzIGFuZCB0aGVpciBkaW1lbnNpb24uXG4gIC8vIFRoaXMgc2V0cyB0aGUgZ2xvYmFsQXJlYUljb25EaW0gYW5kIGlzIHVzZWQgd2hlbiBjcmVhdGluZyB0aGUgc2VhdCByZXNlcnZhdGlvbiBhcmVhIGVsZW1lbnRzLlxuICAvLyBUaGlzIGdpdmVzIHVzIGEgbWF4aW11bSB1bmlmb3JtIGljb24gc2l6ZSB3aXRoaW4gdGhlIGFyZWEgZWxlbWVudHNcbiAgcHJpdmF0ZSBfcHJlcGFyZU9wdGltaXplQXJlYUljb25EaW1lbnNpb25CeU1lZGlhbigpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5zZWF0UmVzZXJ2YXRpb25zKSB7XG4gICAgICBjb25zdCBhbGxTZXJ2aWNlRGltZW5zaW9uczogRWxlbWVudERpbWVuc2lvbltdID0gW107XG4gICAgICB0aGlzLnNlYXRSZXNlcnZhdGlvbnMuZm9yRWFjaCgoZGVjaykgPT5cbiAgICAgICAgZGVjay5jb2FjaEl0ZW1zLmZvckVhY2goKGNvYWNoKSA9PlxuICAgICAgICAgIGNvYWNoLnNlcnZpY2VFbGVtZW50cz8uZm9yRWFjaCgoaWNvbikgPT4gYWxsU2VydmljZURpbWVuc2lvbnMucHVzaChpY29uLmRpbWVuc2lvbikpLFxuICAgICAgICApLFxuICAgICAgKTtcblxuICAgICAgaWYgKGFsbFNlcnZpY2VEaW1lbnNpb25zLmxlbmd0aCkge1xuICAgICAgICBhbGxTZXJ2aWNlRGltZW5zaW9ucy5zb3J0KFxuICAgICAgICAgIChkaW0xOiBFbGVtZW50RGltZW5zaW9uIHwgdW5kZWZpbmVkLCBkaW0yOiBFbGVtZW50RGltZW5zaW9uIHwgdW5kZWZpbmVkKSA9PiB7XG4gICAgICAgICAgICBpZiAoZGltMSAmJiBkaW0yKSB7XG4gICAgICAgICAgICAgIGNvbnN0IG1heERpbTEgPSBkaW0xLncgKyBkaW0xLmg7XG4gICAgICAgICAgICAgIGNvbnN0IG1heERpbTIgPSBkaW0yLncgKyBkaW0yLmg7XG4gICAgICAgICAgICAgIGlmIChtYXhEaW0xID4gbWF4RGltMikgcmV0dXJuIDE7XG4gICAgICAgICAgICAgIGVsc2UgaWYgKG1heERpbTEgPCBtYXhEaW0yKSByZXR1cm4gLTE7XG4gICAgICAgICAgICAgIGVsc2UgcmV0dXJuIDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgICB9LFxuICAgICAgICApO1xuICAgICAgICAvLyBjYWxjdWxhdGUgdGhlIGJlc3QgaWNvbiBzaXplIGJ5IG1lZGlhblxuICAgICAgICBjb25zdCBtZWRpYW5JY29uU2l6ZSA9IGFsbFNlcnZpY2VEaW1lbnNpb25zW01hdGguZmxvb3IoYWxsU2VydmljZURpbWVuc2lvbnMubGVuZ3RoIC8gMildITtcblxuICAgICAgICAvLyBTZXQgdGhlIGRldGVybWluZWQgbWVkaWFuIGljb24gc2l6ZSBhcyBnbG9iYWwgY2FsY3VsYXRlZCBhcmVhIGljb24gZGltZW5zaW9uXG4gICAgICAgIHRoaXMuZ2xvYmFsQXJlYUljb25EaW0gPSB0aGlzLmdldENhbGN1bGF0ZWREaW1lbnNpb24obWVkaWFuSWNvblNpemUpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gZmluZCB0aGUgbWF4aW11bSBjb2FjaCBoZWlnaHQgZnJvbSBhbGwgZGVja3NcbiAgICAgICAgY29uc3QgbWF4Q29hY2hIZWlnaHQgPSB0aGlzLnNlYXRSZXNlcnZhdGlvbnNcbiAgICAgICAgICAuZmxhdE1hcCgoZGVjaykgPT4gZGVjay5jb2FjaEl0ZW1zLm1hcCgoY29hY2gpID0+IGNvYWNoLmRpbWVuc2lvbi5oKSlcbiAgICAgICAgICAucmVkdWNlKChtYXgsIGhlaWdodCkgPT4gTWF0aC5tYXgobWF4LCBoZWlnaHQpLCAwKTtcblxuICAgICAgICAvL2NhbGN1bGF0ZSAyMCUgb2YgbWF4aW11bSBoZWlnaHQgYXMgaWNvbiBkaW1lbnNpb25cbiAgICAgICAgY29uc3QgaWNvbkRpbWVuc2lvbiA9IE1hdGguZmxvb3IobWF4Q29hY2hIZWlnaHQgKiAwLjIpO1xuICAgICAgICB0aGlzLmdsb2JhbEFyZWFJY29uRGltID0gdGhpcy5nZXRDYWxjdWxhdGVkRGltZW5zaW9uKHtcbiAgICAgICAgICB3OiBpY29uRGltZW5zaW9uLFxuICAgICAgICAgIGg6IGljb25EaW1lbnNpb24sXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgX3ByZXBhcmVUcmF2ZWxDbGFzc05hdmlnYXRpb24odHJhdmVsQ2xhc3NlczogUGxhY2VUcmF2ZWxDbGFzc1tdKTogUGxhY2VUcmF2ZWxDbGFzcyB7XG4gICAgaWYgKHRyYXZlbENsYXNzZXMuaW5kZXhPZignRklSU1QnKSAhPT0gLTEpIHJldHVybiAnRklSU1QnO1xuICAgIGlmICh0cmF2ZWxDbGFzc2VzLmluZGV4T2YoJ1NFQ09ORCcpICE9PSAtMSkgcmV0dXJuICdTRUNPTkQnO1xuICAgIHJldHVybiAnQU5ZX0NMQVNTJztcbiAgfVxuXG4gIHByaXZhdGUgX3ByZXBhcmVEcml2ZXJBcmVhU2lkZU5hdmlnYXRpb24oXG4gICAgY29hY2hJdGVtOiBDb2FjaEl0ZW0sXG4gICk6IFJlY29yZDxzdHJpbmcsIGJvb2xlYW4+IHwgdW5kZWZpbmVkIHtcbiAgICBjb25zdCBjb2FjaERyaXZlckFyZWFzID0gY29hY2hJdGVtLmdyYXBoaWNFbGVtZW50cz8uZmlsdGVyKFxuICAgICAgKGdyYXBoaWNhbEVsZW1lbnRzKSA9PiBncmFwaGljYWxFbGVtZW50cy5pY29uID09PSAnRFJJVkVSX0FSRUEnLFxuICAgICk7XG5cbiAgICBpZiAoY29hY2hEcml2ZXJBcmVhcyAmJiBjb2FjaERyaXZlckFyZWFzLmxlbmd0aCA+IDApIHtcbiAgICAgIC8vIENoZWNraW5nIHRoZSBkcml2ZXIgYXJlYSBwb3NpdGlvbiB3aGV0aGVyIGl0IGlzIHByZXNlbnQgb24gdGhlIGxlZnQgb3IgcmlnaHQgc2lkZSBpbiBhIGNvYWNoXG4gICAgICBjb25zdCBoYXNMZWZ0RHJpdmVyQXJlYSA9XG4gICAgICAgIGNvYWNoRHJpdmVyQXJlYXMuZmluZCgoZHJpdmVyQXJlYUVsZW1lbnQpID0+IGRyaXZlckFyZWFFbGVtZW50LnBvc2l0aW9uLnggPT09IDApIHx8IGZhbHNlO1xuICAgICAgY29uc3QgaGFzUmlnaHREcml2ZXJBcmVhID1cbiAgICAgICAgY29hY2hEcml2ZXJBcmVhcy5maW5kKChkcml2ZXJBcmVhRWxlbWVudCkgPT4gZHJpdmVyQXJlYUVsZW1lbnQucG9zaXRpb24ueCA+IDApIHx8IGZhbHNlO1xuXG4gICAgICByZXR1cm4ge1xuICAgICAgICBsZWZ0OiAhIWhhc0xlZnREcml2ZXJBcmVhLFxuICAgICAgICByaWdodDogISFoYXNSaWdodERyaXZlckFyZWEsXG4gICAgICB9O1xuICAgIH1cbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG5cbiAgcHJpdmF0ZSBfcHJlcGFyZVNlcnZpY2VJY29uc05hdmlnYXRpb24gPSAocHJvcGVydHlJZHM6IHN0cmluZ1tdKTogc3RyaW5nW10gPT4ge1xuICAgIGlmICghcHJvcGVydHlJZHMpIHtcbiAgICAgIHJldHVybiBbXTtcbiAgICB9XG5cbiAgICBjb25zdCBzaHJ1bmtQcm9wZXJ0eUlkcyA9IHByb3BlcnR5SWRzXG4gICAgICA/Lm1hcChmdW5jdGlvbiAocHJvcGVydHlJZDogc3RyaW5nKToge1xuICAgICAgICBwSWQ6IHN0cmluZztcbiAgICAgICAgc3ZnTmFtZTogc3RyaW5nO1xuICAgICAgfSB7XG4gICAgICAgIC8vIHByZXBhcmUgdGVtcG9yYXJ5IG9iamVjdCBtYXBwaW5nIHByb3BlcnR5IGlkIHRvIGl0J3Mgc3ZnTmFtZSBzbyB0aGF0IHdlIGNhbiBjb21wYXJlIGl0IHRvIHRoZSBsaXN0IG9mIGFsbG93ZWQgaWNvbnNcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBwSWQ6IHByb3BlcnR5SWQsXG4gICAgICAgICAgc3ZnTmFtZTogbWFwSWNvblRvU3ZnW3Byb3BlcnR5SWRdPy5zdmdOYW1lID8gbWFwSWNvblRvU3ZnW3Byb3BlcnR5SWRdPy5zdmdOYW1lIDogJycsXG4gICAgICAgIH07XG4gICAgICB9KVxuICAgICAgLy9maWx0ZXIgb3V0IG9iamVjdHMgc2VydmljZSBpY29ucyB3aGljaCBhcmUgbm90IGluIEFMTE9XRURfU0VSVklDRV9JQ09OU1xuICAgICAgLmZpbHRlcigocHJvcGVydHlUb1N2ZykgPT4gQUxMT1dFRF9TRVJWSUNFX0lDT05TLmluZGV4T2YocHJvcGVydHlUb1N2Zy5zdmdOYW1lKSAhPT0gLTEpXG4gICAgICAvL21ha2UgaXQgZGlzdGluY3QgYnkgc3ZnTmFtZVxuICAgICAgLmZpbHRlcihcbiAgICAgICAgKHZhbHVlLCBpbmRleCwgc2VsZikgPT5cbiAgICAgICAgICBzZWxmLm1hcCgocHJvcFN2ZykgPT4gcHJvcFN2Zy5zdmdOYW1lKS5pbmRleE9mKHZhbHVlLnN2Z05hbWUpID09PSBpbmRleCxcbiAgICAgIClcbiAgICAgIC8vIGdvIGJhY2sgdG8gcHJvcGVydHlJZCBzdHJpbmcgZnJvbSB0ZW1wb3Jhcnkgb2JqZWN0XG4gICAgICAubWFwKChwcm9wZXJ0eVRvU3ZnKSA9PiBwcm9wZXJ0eVRvU3ZnLnBJZClcbiAgICAgIC8vIHRha2UgZmlyc3QgTUFYX1NFUlZJQ0VfUFJPUEVSVElFUyByZWdhcmRsZXNzIG9mIHRoZSBpbnB1dCBmcm9tIEJhY2tlbmQsIG90aGVyd2lzZSB0aGUgbGF5b3V0IGNvdWxkIGJlIGRlc3Ryb3llZFxuICAgICAgLnNsaWNlKDAsIE1BWF9TRVJWSUNFX1BST1BFUlRJRVMpO1xuICAgIHJldHVybiBzaHJ1bmtQcm9wZXJ0eUlkcyA/IHNocnVua1Byb3BlcnR5SWRzIDogW107XG4gIH07XG5cbiAgcHJpdmF0ZSBfcHJlcGFyZUNvYWNoV2lkdGhBbmRHYXBDYWxjdWxhdGlvbnMoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuc2VhdFJlc2VydmF0aW9ucykge1xuICAgICAgdGhpcy5zZWF0UmVzZXJ2YXRpb25zLmZvckVhY2goKHNlYXRSZXNlcnZhdGlvbjogU2VhdFJlc2VydmF0aW9uKSA9PiB7XG4gICAgICAgIHNlYXRSZXNlcnZhdGlvbj8uY29hY2hJdGVtcz8uZm9yRWFjaCgoY29hY2hJdGVtOiBDb2FjaEl0ZW0pID0+IHtcbiAgICAgICAgICBjb25zdCBoYXNPdmVyaGFuZ2luZ1BsYWNlcyA9IHRoaXMuX2lzT3ZlcmhhbmdpbmdFbGVtZW50c1ByZXNlbnQoXG4gICAgICAgICAgICBjb2FjaEl0ZW0uZGltZW5zaW9uLncsXG4gICAgICAgICAgICBjb2FjaEl0ZW0ucGxhY2VzLFxuICAgICAgICAgICk7XG5cbiAgICAgICAgICAvL011c3QgIGJlIGRvbmUgYWxzbyBmb3IgZ3JhcGhpY2FsIGVsZW1lbnRzLCBhcyB0aGV5IGNhbiBhbHNvIHByb3RydWRlIHRoZSBjb2FjaCBib3JkZXJcbiAgICAgICAgICAvLyBDaGVjayBvbmx5IGdyYXBoaWNhbCBlbGVtZW50cyB0aGF0IGFyZSBub3QgYXJlYSBlbGVtZW50c1xuICAgICAgICAgIGNvbnN0IGZpbHRlcmVkRWxlbWVudHMgPSBjb2FjaEl0ZW0uZ3JhcGhpY0VsZW1lbnRzPy5maWx0ZXIoXG4gICAgICAgICAgICAoZSkgPT4gZS5pY29uICYmICF0aGlzLm5vdEFyZWFFbGVtZW50cy5pbmNsdWRlcyhlLmljb24pLFxuICAgICAgICAgICk7XG5cbiAgICAgICAgICBjb25zdCBoYXNPdmVyaGFuZ2luZ0dyYXBoaWNBcmVhcyA9IHRoaXMuX2lzT3ZlcmhhbmdpbmdFbGVtZW50c1ByZXNlbnQoXG4gICAgICAgICAgICBjb2FjaEl0ZW0uZGltZW5zaW9uLncsXG4gICAgICAgICAgICBmaWx0ZXJlZEVsZW1lbnRzLFxuICAgICAgICAgICk7XG5cbiAgICAgICAgICB0aGlzLm92ZXJIYW5naW5nRWxlbWVudEluZm9ybWF0aW9uLnB1c2goe1xuICAgICAgICAgICAgY29hY2hJZDogY29hY2hJdGVtLmlkLFxuICAgICAgICAgICAgb3ZlcmhhbmdpbmdQbGFjZXM6IGhhc092ZXJoYW5naW5nUGxhY2VzLFxuICAgICAgICAgICAgb3ZlcmhhbmdpbmdHcmFwaGljQXJlYXM6IGhhc092ZXJoYW5naW5nR3JhcGhpY0FyZWFzLFxuICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBjdXJyZW50IHNlbGVjdGVkIHBsYWNlIEhUTUwgZWxlbWVudCBieSBjdXJyU2VsZWN0ZWRQbGFjZUVsZW1lbnRJZC5cbiAgICogQHJldHVybnMgSFRNTEVsZW1lbnQgb3IgbnVsbFxuICAgKi9cbiAgcHJpdmF0ZSBfZ2V0UGxhY2VIdG1sRWxlbWVudCgpOiBIVE1MRWxlbWVudCB8IG51bGwge1xuICAgIHJldHVybiB0aGlzLmN1cnJTZWxlY3RlZFBsYWNlRWxlbWVudElkXG4gICAgICA/IHRoaXMuc2hhZG93Um9vdD8uZ2V0RWxlbWVudEJ5SWQodGhpcy5jdXJyU2VsZWN0ZWRQbGFjZUVsZW1lbnRJZCkgfHwgbnVsbFxuICAgICAgOiBudWxsO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIGV4dHJhY3RlZCBjb2FjaCBkZWNrIGluZGV4IGZyb20gcGxhY2UgaWRcbiAgICogQHJldHVybnMgbnVtYmVyXG4gICAqL1xuICBwcml2YXRlIF9nZXREZWNrSW5kZXhCeVBsYWNlSWQocGxhY2VJZDogc3RyaW5nKTogbnVtYmVyIHwgbnVsbCB7XG4gICAgY29uc3QgZGVja0luZGV4ID0gdGhpcy5zaGFkb3dSb290XG4gICAgICA/LnF1ZXJ5U2VsZWN0b3IoJyMnICsgcGxhY2VJZClcbiAgICAgID8uZ2V0QXR0cmlidXRlKCdkYXRhLWRlY2staW5kZXgnKTtcbiAgICBpZiAoZGVja0luZGV4ICYmICFpc05hTigrZGVja0luZGV4KSkge1xuICAgICAgcmV0dXJuICtkZWNrSW5kZXg7XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgcHJpdmF0ZSBfaXNWYWxpZENvYWNoSW5kZXgoY29hY2hJbmRleDogbnVtYmVyKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIChcbiAgICAgIGNvYWNoSW5kZXggPj0gMCAmJlxuICAgICAgY29hY2hJbmRleCA8PSB0aGlzLnNlYXRSZXNlcnZhdGlvbnNbdGhpcy5zZWF0UmVzZXJ2YXRpb25zLmxlbmd0aCAtIDFdLmNvYWNoSXRlbXMubGVuZ3RoXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGV4aXN0aW5nIGNvYWNoIGRlY2sgaW5kZXggZGVwZW5kaW5nIG9uIHRoZSBzZWxlY3RlZCBjb2FjaC5cbiAgICogVGhpcyBtZXRob2QgaXMgbmVjZXNzYXJ5IHRvIGdldCBhbiBhdmFpbGFibGUgY29hY2ggZGVjayBpbmRleCBkdXJpbmcga2V5Ym9hcmQgbmF2aWdhdGlvbiwgd2hpY2ggY2FuIHZhcnkgYmV0d2VlbiBjb2FjaGVzIHdpdGggZGlmZmVyZW50IGRlY2tzLlxuICAgKiBGb3IgZXhhbXBsZSwgd2hlbiBuYXZpZ2F0aW5nIGZyb20gYSBjb2FjaCB3aXRoIHR3byBkZWNrcyB0byBhIGNvYWNoIHdpdGggb25lIGRlY2suXG4gICAqXG4gICAqICAgICAgIFtvb29dLVtvb29dLVtvb29dXG4gICAqIFtvb29dLVtvb29dLVtvb29dLVtvb29dLVtvb29dXG4gICAqXG4gICAqIEByZXR1cm5zIG51bWJlclxuICAgKi9cbiAgcHJpdmF0ZSBfZ2V0RXhpc3RpbmdDb2FjaERlY2tJbmRleCgpOiBudW1iZXIge1xuICAgIGlmIChcbiAgICAgIHRoaXMuc2VhdFJlc2VydmF0aW9uc1t0aGlzLmN1cnJTZWxlY3RlZERlY2tJbmRleF0uY29hY2hJdGVtc1t0aGlzLmN1cnJTZWxlY3RlZENvYWNoSW5kZXhdXG4gICAgICAgIC5wbGFjZXMgIT09IHVuZGVmaW5lZFxuICAgICkge1xuICAgICAgcmV0dXJuIHRoaXMuY3VyclNlbGVjdGVkRGVja0luZGV4O1xuICAgIH1cblxuICAgIC8vIEZpbmQgbmV4dCBwb3NzaWJsZSBjb2FjaCBkZWNrIGluZGV4IHdoZXJlIHBsYWNlcyBleGlzdFxuICAgIGNvbnN0IG5leHRBdmFpbGFibGVEZWNrQ29hY2hJbmRleCA9IHRoaXMuc2VhdFJlc2VydmF0aW9ucy5maW5kSW5kZXgoXG4gICAgICAoc2VhdFJlc2VydmF0aW9uKSA9PlxuICAgICAgICBzZWF0UmVzZXJ2YXRpb24uY29hY2hJdGVtc1t0aGlzLmN1cnJTZWxlY3RlZENvYWNoSW5kZXhdLnBsYWNlcyAhPT0gdW5kZWZpbmVkLFxuICAgICk7XG4gICAgcmV0dXJuIHRoaXMuY3VyclNlbGVjdGVkRGVja0luZGV4ID49IG5leHRBdmFpbGFibGVEZWNrQ29hY2hJbmRleFxuICAgICAgPyB0aGlzLmN1cnJTZWxlY3RlZERlY2tJbmRleFxuICAgICAgOiBuZXh0QXZhaWxhYmxlRGVja0NvYWNoSW5kZXg7XG4gIH1cblxuICAvKipcbiAgICogSWYgYSBzZWxlY3RlZCBwbGFjZSBpcyBzbGlnaHRseSBoaWRkZW4gYnkgdGhlIG92ZXJmbG93IHNjcm9sbCBjb250ZW50IGFuZCBpcyBzdGlsbCBjbGlja2VkLFxuICAgKiB0aGUgbWV0aG9kIHRyaWVzIHRvIHNjcm9sbCB0aGUgc2VsZWN0ZWQgcGxhY2UgaW50byB0aGUgbmVhcmVzdCB2aWV3cG9ydCwgc28gdGhhdCBpdCBpcyBjb21wbGV0ZWx5IHZpc2libGUuXG4gICAqXG4gICAqIEBwYXJhbSBwbGFjZUlkXG4gICAqL1xuICBwcml2YXRlIF9zY3JvbGxQbGFjZUludG9OZWFyZXN0Vmlld3BvcnQocGxhY2VJZDogc3RyaW5nKTogdm9pZCB7XG4gICAgdGhpcy5zaGFkb3dSb290XG4gICAgICA/LmdldEVsZW1lbnRCeUlkKHBsYWNlSWQpXG4gICAgICA/LnNjcm9sbEludG9WaWV3KHsgYmVoYXZpb3I6ICdzbW9vdGgnLCBibG9jazogJ25lYXJlc3QnLCBpbmxpbmU6ICduZWFyZXN0JyB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBjaGVja3MgaWYgYW55IHBsYWNlcyBvciBncmFwaGljYWwgZWxlbWVudHMgKGUuZy4gdG9pbGV0IGFyZWEsIGV0Yy4pIGFyZSBvdmVyaGFuZ2luZyB0aGUgY29hY2ggYm9yZGVyc1xuICAgKiBAcGFyYW0gY29hY2hJdGVtV2lkdGhcbiAgICogQHBhcmFtIGVsZW1lbnRzXG4gICAqL1xuICBwcml2YXRlIF9pc092ZXJoYW5naW5nRWxlbWVudHNQcmVzZW50KFxuICAgIGNvYWNoSXRlbVdpZHRoOiBudW1iZXIsXG4gICAgZWxlbWVudHM6IChQbGFjZSB8IEJhc2VFbGVtZW50KVtdIHwgdW5kZWZpbmVkLFxuICApOiBib29sZWFuIHtcbiAgICByZXR1cm4gKFxuICAgICAgZWxlbWVudHM/LnNvbWUoXG4gICAgICAgIChlbGVtZW50KSA9PlxuICAgICAgICAgIGVsZW1lbnQucG9zaXRpb24ueCA9PT0gMCB8fCBlbGVtZW50LnBvc2l0aW9uLnggKyBlbGVtZW50LmRpbWVuc2lvbi53ID49IGNvYWNoSXRlbVdpZHRoLFxuICAgICAgKSA/PyBmYWxzZVxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogY29sbGVjdCBpbmZvcm1hdGlvbiBhYm91dCB0aGUgZHJpdmVyQXJlYXMgZm9yIG9uZSBjb2FjaFxuICAgKiBAcGFyYW0gY29hY2hJdGVtXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBwcml2YXRlIF9zZXREcml2ZXJBcmVhc0VsZW1lbnRzKGNvYWNoSXRlbTogQ29hY2hJdGVtKToge1xuICAgIGRyaXZlckFyZWE6IEJhc2VFbGVtZW50IHwgdW5kZWZpbmVkO1xuICAgIGRyaXZlckFyZWFOb1ZlcnRpY2FsV2FsbDogQmFzZUVsZW1lbnQgfCB1bmRlZmluZWQ7XG4gIH0ge1xuICAgIGlmIChjb2FjaEl0ZW0pIHtcbiAgICAgIGNvbnN0IGRyaXZlckFyZWEgPSBjb2FjaEl0ZW0uZ3JhcGhpY0VsZW1lbnRzPy5maW5kKFxuICAgICAgICAoZWxlbWVudDogQmFzZUVsZW1lbnQpID0+IGVsZW1lbnQuaWNvbiA9PT0gJ0RSSVZFUl9BUkVBJyxcbiAgICAgICk7XG5cbiAgICAgIGNvbnN0IGRyaXZlckFyZWFOb1ZlcnRpY2FsV2FsbCA9XG4gICAgICAgIGNvYWNoSXRlbS50eXBlID09PSAnTE9DT01PVElWRV9DT0FDSCdcbiAgICAgICAgICA/IGNvYWNoSXRlbS5ncmFwaGljRWxlbWVudHM/LmZpbmQoXG4gICAgICAgICAgICAgIChlbGVtZW50OiBCYXNlRWxlbWVudCkgPT4gZWxlbWVudC5pY29uID09PSAnRFJJVkVSX0FSRUFfTk9fVkVSVElDQUxfV0FMTCcsXG4gICAgICAgICAgICApXG4gICAgICAgICAgOiB1bmRlZmluZWQ7XG5cbiAgICAgIHJldHVybiB7XG4gICAgICAgIGRyaXZlckFyZWE6IGRyaXZlckFyZWEsXG4gICAgICAgIGRyaXZlckFyZWFOb1ZlcnRpY2FsV2FsbDogZHJpdmVyQXJlYU5vVmVydGljYWxXYWxsLFxuICAgICAgfTtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgZHJpdmVyQXJlYTogdW5kZWZpbmVkLFxuICAgICAgZHJpdmVyQXJlYU5vVmVydGljYWxXYWxsOiB1bmRlZmluZWQsXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBJcyBjYWxsZWQgd2hlbiB0aGUgU2VhdFJlc2VydmF0aW9uIGxvc2VzIGZvY3VzLCB3aGF0IGhhcHBlbnMgd2hlbiB0aGUgdXNlciB0YWJzIG91dCBvciBjbGlja3Mgc29tZXdoZXJlIGVsc2UuXG4gICAqIFRoZW4gd2UgcmVzZXQgdGhlIGZvY3VzZWQgZWxlbWVudHMuXG4gICAqL1xuICBwcml2YXRlIF9vbkxlYXZlU2VhdFJlc2VydmF0aW9uQ29tcG9uZW50KCk6IHZvaWQge1xuICAgIGlmICh0aGlzLmhhc05hdmlnYXRpb24pIHtcbiAgICAgIHRoaXMuZm9jdXNlZENvYWNoSW5kZXggPSAtMTtcbiAgICB9XG4gICAgdGhpcy51bmZvY3VzUGxhY2VFbGVtZW50KCk7XG4gIH1cbn1cbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7QUE4QkEsSUFBSztDQUFMLFNBQUssaUJBQWU7QUFDbEIsaUJBQUEsV0FBQTtBQUNBLGlCQUFBLFVBQUE7R0FGRyxvQkFBQSxrQkFBZSxFQUFBLEVBQUE7QUFXcEIsSUFBTSx5QkFBeUI7QUFDL0IsSUFBTSx3QkFBa0M7Q0FDdEM7Q0FDQTtDQUNBO0NBQ0E7Q0FDQTtDQUNBO0NBQ0E7Q0FDRDtJQUVZLG9DQUEwQjttQkFBUzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O2NBQW5DLG1DQUFtQyxZQUFVOzs7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
|