@colijnit/homedecorator 255.1.1
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/_variables.scss +1 -0
- package/app/app.component.scss +30 -0
- package/app/app.version.d.ts +5 -0
- package/app/bundle/threedselector-bundle/threedselector-bundle.component.scss +24 -0
- package/app/bundle/threedselector-bundle/threedselector-selections-bundle.component.scss +4 -0
- package/app/core/components/debug/debug.component.d.ts +17 -0
- package/app/core/components/debug/debug.component.scss +27 -0
- package/app/core/components/error/error-message.component.d.ts +14 -0
- package/app/core/components/error/error-message.component.scss +18 -0
- package/app/core/components/tooltip/tooltip.component.d.ts +17 -0
- package/app/core/components/tooltip/tooltip.component.scss +34 -0
- package/app/core/const/dimensioning.d.ts +24 -0
- package/app/core/core.module.d.ts +27 -0
- package/app/core/directive/autofocus.directive.d.ts +11 -0
- package/app/core/directive/tooltip.directive.d.ts +21 -0
- package/app/core/directive/visibility-observer-master.directive.d.ts +12 -0
- package/app/core/directive/visibility-observer.directive.d.ts +16 -0
- package/app/core/enum/configuration-key.enum.d.ts +35 -0
- package/app/core/enum/export-type.enum.d.ts +5 -0
- package/app/core/enum/google-tag-manager-event.enum.d.ts +12 -0
- package/app/core/enum/icon-name.enum.d.ts +15 -0
- package/app/core/enum/icon.enum.d.ts +33 -0
- package/app/core/enum/light.enum.d.ts +7 -0
- package/app/core/enum/message-type.enum.d.ts +69 -0
- package/app/core/enum/model-type.enum.d.ts +6 -0
- package/app/core/enum/output-encoding.enum.d.ts +4 -0
- package/app/core/enum/shadow-map-type.enum.d.ts +6 -0
- package/app/core/enum/user-role-type.enum.d.ts +18 -0
- package/app/core/enum/view-mode.enum.d.ts +9 -0
- package/app/core/enum/xr-mode.enum.d.ts +4 -0
- package/app/core/interface/adjustable-element.interface.d.ts +5 -0
- package/app/core/interface/category.interface.d.ts +9 -0
- package/app/core/interface/changes.interface.d.ts +9 -0
- package/app/core/interface/child-params.interface.d.ts +3 -0
- package/app/core/interface/configuration-data.interface.d.ts +36 -0
- package/app/core/interface/external-settings.interface.d.ts +6 -0
- package/app/core/interface/info-dialog-data.interface.d.ts +4 -0
- package/app/core/interface/light-preset.interface.d.ts +18 -0
- package/app/core/interface/loading-overlay-data.interface.d.ts +4 -0
- package/app/core/interface/media-resource.interface.d.ts +6 -0
- package/app/core/interface/message-with-payload.interface.d.ts +81 -0
- package/app/core/interface/message-without-payload.interface.d.ts +35 -0
- package/app/core/interface/preset.interface.d.ts +8 -0
- package/app/core/interface/selected-floor-event.interface.d.ts +5 -0
- package/app/core/interface/selected-wall-event.interface.d.ts +6 -0
- package/app/core/interface/texture.interface.d.ts +37 -0
- package/app/core/interface/toolbar-icon.interface.d.ts +8 -0
- package/app/core/model/ar-position-indicator.d.ts +4 -0
- package/app/core/model/camera-settings.d.ts +12 -0
- package/app/core/model/category.d.ts +12 -0
- package/app/core/model/custom-button.d.ts +10 -0
- package/app/core/model/error-message.d.ts +8 -0
- package/app/core/model/export-object.d.ts +5 -0
- package/app/core/model/from-intersection-observer.d.ts +7 -0
- package/app/core/model/homedecorator-settings-options.d.ts +46 -0
- package/app/core/model/homedecorator-settings.d.ts +54 -0
- package/app/core/model/icon.d.ts +4 -0
- package/app/core/model/light-preset.d.ts +27 -0
- package/app/core/model/light-properties.d.ts +25 -0
- package/app/core/model/media-resource.d.ts +7 -0
- package/app/core/model/preset.d.ts +10 -0
- package/app/core/model/ral-color.d.ts +19 -0
- package/app/core/model/shadow-properties.d.ts +7 -0
- package/app/core/model/texture-type.d.ts +6 -0
- package/app/core/model/texture.d.ts +43 -0
- package/app/core/model/three-object.d.ts +1 -0
- package/app/core/model/toast-type.d.ts +5 -0
- package/app/core/model/toast.d.ts +5 -0
- package/app/core/model/xr-reticle.d.ts +17 -0
- package/app/core/pipe/append.pipe.d.ts +7 -0
- package/app/core/pipe/cm-to-measure.pipe.d.ts +10 -0
- package/app/core/pipe/filter.pipe.d.ts +7 -0
- package/app/core/pipe/keys.pipe.d.ts +7 -0
- package/app/core/pipe/localize.pipe.d.ts +10 -0
- package/app/core/pipe/m-to-measure.pipe.d.ts +10 -0
- package/app/core/pipe/prepend.pipe.d.ts +7 -0
- package/app/core/pipe/scm-to-measure.pipe.d.ts +10 -0
- package/app/core/pipe/sm-to-measure.pipe.d.ts +10 -0
- package/app/core/pipe/strip-html.pipe.d.ts +7 -0
- package/app/core/service/3dm-api.d.ts +65 -0
- package/app/core/service/app-state.service.d.ts +49 -0
- package/app/core/service/configuration.service.d.ts +15 -0
- package/app/core/service/debug.service.d.ts +16 -0
- package/app/core/service/dimensioning.service.d.ts +14 -0
- package/app/core/service/dynamic-camera.service.d.ts +23 -0
- package/app/core/service/environment.service.d.ts +8 -0
- package/app/core/service/error.service.d.ts +11 -0
- package/app/core/service/export.service.d.ts +18 -0
- package/app/core/service/file.service.d.ts +9 -0
- package/app/core/service/homedecorator-app-event.service.d.ts +23 -0
- package/app/core/service/homedecorator-app.service.d.ts +58 -0
- package/app/core/service/homedecorator-connector-adapter.service.d.ts +90 -0
- package/app/core/service/homedecorator-connector.service.d.ts +127 -0
- package/app/core/service/homedecorator-dictionary.service.d.ts +15 -0
- package/app/core/service/homedecorator-icon-cache.service.d.ts +21 -0
- package/app/core/service/homedecorator-settings.service.d.ts +23 -0
- package/app/core/service/homedecorator.service.d.ts +14 -0
- package/app/core/service/integration.service.d.ts +16 -0
- package/app/core/service/item-serialization.service.d.ts +78 -0
- package/app/core/service/json-utils.service.d.ts +7 -0
- package/app/core/service/message-bus.service.d.ts +21 -0
- package/app/core/service/permanent-store.service.d.ts +37 -0
- package/app/core/service/presets.service.d.ts +50 -0
- package/app/core/service/progress.service.d.ts +17 -0
- package/app/core/service/ral.service.d.ts +17 -0
- package/app/core/service/skip-button-info.service.d.ts +19 -0
- package/app/core/service/toast.service.d.ts +12 -0
- package/app/core/service/utils.service.d.ts +68 -0
- package/app/core/service/view-mode.service.d.ts +27 -0
- package/app/core/service/web-worker.service.d.ts +18 -0
- package/app/core/utils/clone-utils.d.ts +5 -0
- package/app/core/utils/color.utils.d.ts +7 -0
- package/app/core/utils/file.utils.d.ts +36 -0
- package/app/core/utils/function/is-empty.function.d.ts +1 -0
- package/app/core/utils/function/is-nill.function.d.ts +1 -0
- package/app/core/utils/material.utils.d.ts +33 -0
- package/app/core/utils/object.utils.d.ts +14 -0
- package/app/core/utils/relative-position.utils.d.ts +12 -0
- package/app/core/utils/variation-utils.d.ts +12 -0
- package/app/core/workers/enum/web-worker-message.enum.d.ts +4 -0
- package/app/core/workers/enum/web-worker-type.enum.d.ts +3 -0
- package/app/development/components/selected-child-material-texture.component.d.ts +58 -0
- package/app/development/components/selected-child-material-texture.component.scss +122 -0
- package/app/development/components/selected-child-material.component.d.ts +73 -0
- package/app/development/components/selected-child-material.component.scss +45 -0
- package/app/development/components/selected-child.component.d.ts +8 -0
- package/app/development/components/selected-child.component.scss +40 -0
- package/app/development/components/selected-object-base.d.ts +32 -0
- package/app/development/components/selected-object.component.d.ts +20 -0
- package/app/development/components/selected-object.component.scss +13 -0
- package/app/development/development.module.d.ts +19 -0
- package/app/development/directive/development.directive.d.ts +19 -0
- package/app/development/service/development.service.d.ts +49 -0
- package/app/homedecorator.component.d.ts +42 -0
- package/app/homedecorator.component.scss +34 -0
- package/app/homedecorator.module.d.ts +18 -0
- package/app/plugins/core3d/collision-manager/collision-manager.service.d.ts +23 -0
- package/app/plugins/core3d/collision-manager/floorplan-collision-detection.d.ts +9 -0
- package/app/plugins/core3d/collision-manager/snapping-collision.service.d.ts +47 -0
- package/app/plugins/core3d/components/ar-gui/ar-gui-root/ar-gui-elements/ar-gui-buttons/ar-gui-buttons.component.d.ts +17 -0
- package/app/plugins/core3d/components/ar-gui/ar-gui-root/ar-gui-elements/ar-gui-buttons/ar-gui-buttons.component.scss +30 -0
- package/app/plugins/core3d/components/ar-gui/ar-gui-root/ar-gui-elements/ar-gui-configurator/ar-gui-configurator.component.d.ts +25 -0
- package/app/plugins/core3d/components/ar-gui/ar-gui-root/ar-gui-elements/ar-gui-configurator/ar-gui-configurator.component.scss +13 -0
- package/app/plugins/core3d/components/ar-gui/ar-gui-root/ar-gui-elements/ar-gui-context-menu/ar-gui-context-menu.component.d.ts +21 -0
- package/app/plugins/core3d/components/ar-gui/ar-gui-root/ar-gui-elements/ar-gui-context-menu/ar-gui-context-menu.component.scss +6 -0
- package/app/plugins/core3d/components/ar-gui/ar-gui-root/ar-gui-elements/ar-gui-notifications/ar-gui-notifications.component.d.ts +11 -0
- package/app/plugins/core3d/components/ar-gui/ar-gui-root/ar-gui-elements/ar-gui-notifications/ar-gui-notifications.component.scss +19 -0
- package/app/plugins/core3d/components/ar-gui/ar-gui-root/ar-gui-root.component.d.ts +16 -0
- package/app/plugins/core3d/components/ar-gui/ar-gui-root/ar-gui-root.component.scss +23 -0
- package/app/plugins/core3d/components/lightplan/edit-light/edit-light.component.d.ts +46 -0
- package/app/plugins/core3d/components/lightplan/edit-light/edit-light.component.scss +93 -0
- package/app/plugins/core3d/components/lightplan/edit-lightplan/edit-lightplan.component.d.ts +24 -0
- package/app/plugins/core3d/components/lightplan/edit-lightplan/edit-lightplan.component.scss +93 -0
- package/app/plugins/core3d/components/lightplan/lightplan.component.d.ts +60 -0
- package/app/plugins/core3d/components/lightplan/lightplan.component.scss +102 -0
- package/app/plugins/core3d/components/scene-options/scene-options.component.d.ts +17 -0
- package/app/plugins/core3d/components/scene-options/scene-options.component.scss +54 -0
- package/app/plugins/core3d/core/angles.d.ts +8 -0
- package/app/plugins/core3d/core/corner-utils.d.ts +8 -0
- package/app/plugins/core3d/core/dimensioning.d.ts +19 -0
- package/app/plugins/core3d/core/utils.d.ts +147 -0
- package/app/plugins/core3d/core3d/components/scenecontrol/scene-control.component.d.ts +49 -0
- package/app/plugins/core3d/core3d/components/scenecontrol/scene-control.component.scss +3 -0
- package/app/plugins/core3d/core3d/core3d.component.d.ts +76 -0
- package/app/plugins/core3d/core3d/core3d.component.scss +27 -0
- package/app/plugins/core3d/core3d.module.d.ts +38 -0
- package/app/plugins/core3d/directive/scene.directive.d.ts +26 -0
- package/app/plugins/core3d/enum/ar-feature.enum.d.ts +12 -0
- package/app/plugins/core3d/enum/direction.enum.d.ts +8 -0
- package/app/plugins/core3d/enum/result-type.enum.d.ts +19 -0
- package/app/plugins/core3d/hud/bounding-measurement-box/bounding-box-measurement.d.ts +28 -0
- package/app/plugins/core3d/hud/bounding-measurement-box/box-measurement.d.ts +17 -0
- package/app/plugins/core3d/hud/bounding-measurement-box/door-or-window-box-measurement.d.ts +29 -0
- package/app/plugins/core3d/hud/bounding-measurement-box/measurable.d.ts +8 -0
- package/app/plugins/core3d/hud/bounding-measurement-box/measurement-utils.d.ts +9 -0
- package/app/plugins/core3d/hud/custom-shape-name-label.d.ts +15 -0
- package/app/plugins/core3d/hud/floor-indicator.d.ts +20 -0
- package/app/plugins/core3d/hud/furniture-measurements.d.ts +12 -0
- package/app/plugins/core3d/hud/indicator-factory.d.ts +7 -0
- package/app/plugins/core3d/hud/measurements.d.ts +46 -0
- package/app/plugins/core3d/hud/on-wall-measurements.d.ts +18 -0
- package/app/plugins/core3d/hud/opening-symbol.d.ts +11 -0
- package/app/plugins/core3d/hud/rotation-helper.d.ts +44 -0
- package/app/plugins/core3d/hud/utils.d.ts +3 -0
- package/app/plugins/core3d/interface/dragged-data.interface.d.ts +10 -0
- package/app/plugins/core3d/interface/edge-visibility-changes.d.ts +5 -0
- package/app/plugins/core3d/interface/model.interface.d.ts +42 -0
- package/app/plugins/core3d/interface/opening.interface.d.ts +6 -0
- package/app/plugins/core3d/interface/scene-option-button.interface.d.ts +17 -0
- package/app/plugins/core3d/interface/scene-update.interface.d.ts +5 -0
- package/app/plugins/core3d/items/base-item.d.ts +97 -0
- package/app/plugins/core3d/items/custom-cylinder-floor-item.d.ts +12 -0
- package/app/plugins/core3d/items/custom-cylinder-wall-item.d.ts +13 -0
- package/app/plugins/core3d/items/custom-floor-item.d.ts +9 -0
- package/app/plugins/core3d/items/custom-objects.d.ts +55 -0
- package/app/plugins/core3d/items/custom-shape-floor-item.d.ts +9 -0
- package/app/plugins/core3d/items/custom-shape-wall-item.d.ts +10 -0
- package/app/plugins/core3d/items/custom-wall-floor-item.d.ts +19 -0
- package/app/plugins/core3d/items/custom-wall-item.d.ts +9 -0
- package/app/plugins/core3d/items/factory.d.ts +24 -0
- package/app/plugins/core3d/items/floor-item.d.ts +13 -0
- package/app/plugins/core3d/items/floor-pin.d.ts +11 -0
- package/app/plugins/core3d/items/floor-plane-item.d.ts +30 -0
- package/app/plugins/core3d/items/furniture.d.ts +3 -0
- package/app/plugins/core3d/items/in-wall-floor-item.d.ts +9 -0
- package/app/plugins/core3d/items/item-group.d.ts +51 -0
- package/app/plugins/core3d/items/item-type.d.ts +21 -0
- package/app/plugins/core3d/items/item.d.ts +84 -0
- package/app/plugins/core3d/items/metadata.d.ts +74 -0
- package/app/plugins/core3d/items/on-floor-item.d.ts +8 -0
- package/app/plugins/core3d/items/pin.d.ts +5 -0
- package/app/plugins/core3d/items/three-mesh.d.ts +8 -0
- package/app/plugins/core3d/items/wall-floor-item.d.ts +8 -0
- package/app/plugins/core3d/items/wall-objects.d.ts +512 -0
- package/app/plugins/core3d/items/wall-pin.d.ts +8 -0
- package/app/plugins/core3d/model/ar-parameters.d.ts +9 -0
- package/app/plugins/core3d/model/box-skin-default.d.ts +5 -0
- package/app/plugins/core3d/model/collision-info.d.ts +6 -0
- package/app/plugins/core3d/model/custom-floor-group-result.d.ts +18 -0
- package/app/plugins/core3d/model/cylinder-skin-default.d.ts +4 -0
- package/app/plugins/core3d/model/dragged-status.d.ts +18 -0
- package/app/plugins/core3d/model/face.d.ts +11 -0
- package/app/plugins/core3d/model/geometry.d.ts +11 -0
- package/app/plugins/core3d/model/scene-event.enum.d.ts +10 -0
- package/app/plugins/core3d/model/skin.d.ts +15 -0
- package/app/plugins/core3d/model/threed-model.d.ts +47 -0
- package/app/plugins/core3d/service/ar.service.d.ts +121 -0
- package/app/plugins/core3d/service/camera.service.d.ts +70 -0
- package/app/plugins/core3d/service/ceiling.service.d.ts +25 -0
- package/app/plugins/core3d/service/controls.d.ts +11 -0
- package/app/plugins/core3d/service/drag-and-drop.service.d.ts +73 -0
- package/app/plugins/core3d/service/error-glow.service.d.ts +18 -0
- package/app/plugins/core3d/service/floor.service.d.ts +43 -0
- package/app/plugins/core3d/service/font.service.d.ts +10 -0
- package/app/plugins/core3d/service/hud.service.d.ts +79 -0
- package/app/plugins/core3d/service/intersection.service.d.ts +10 -0
- package/app/plugins/core3d/service/item-group.service.d.ts +33 -0
- package/app/plugins/core3d/service/item.service.d.ts +37 -0
- package/app/plugins/core3d/service/light-presets.service.d.ts +46 -0
- package/app/plugins/core3d/service/lights.service.d.ts +38 -0
- package/app/plugins/core3d/service/message-board.service.d.ts +18 -0
- package/app/plugins/core3d/service/models.service.d.ts +37 -0
- package/app/plugins/core3d/service/outline.service.d.ts +40 -0
- package/app/plugins/core3d/service/rotation.service.d.ts +57 -0
- package/app/plugins/core3d/service/scene-event.service.d.ts +131 -0
- package/app/plugins/core3d/service/scene-options.service.d.ts +11 -0
- package/app/plugins/core3d/service/scene.service.d.ts +74 -0
- package/app/plugins/core3d/service/vr.service.d.ts +44 -0
- package/app/plugins/core3d/service/wall-measurements.service.d.ts +23 -0
- package/app/plugins/core3d/service/xr.service.d.ts +56 -0
- package/app/plugins/core3d/textures/DepthDataTexture.d.ts +5 -0
- package/app/plugins/core3d/walkthrough-camera-controls/walkthrough-camera-controls.component.d.ts +19 -0
- package/app/plugins/core3d/walkthrough-camera-controls/walkthrough-camera-controls.component.scss +7 -0
- package/app/plugins/furniture-manager/furniture-library/furniture-library.component.d.ts +27 -0
- package/app/plugins/furniture-manager/furniture-library/furniture-library.component.scss +20 -0
- package/app/plugins/furniture-manager/furniture-manager/furniture-manager.component.d.ts +91 -0
- package/app/plugins/furniture-manager/furniture-manager/furniture-manager.component.scss +57 -0
- package/app/plugins/furniture-manager/furniture-manager.module.d.ts +23 -0
- package/app/plugins/help/help/help.component.d.ts +21 -0
- package/app/plugins/help/help/help.component.scss +0 -0
- package/app/plugins/help/help-dialog/help-dialog.component.d.ts +20 -0
- package/app/plugins/help/help-dialog/help-dialog.component.scss +28 -0
- package/app/plugins/help/help.module.d.ts +12 -0
- package/app/plugins/lite-selector/lite-selector/component/animation/animation.component.d.ts +19 -0
- package/app/plugins/lite-selector/lite-selector/component/animation/animation.component.scss +0 -0
- package/app/plugins/lite-selector/lite-selector/component/answer-card/answer-card.component.d.ts +41 -0
- package/app/plugins/lite-selector/lite-selector/component/answer-card/answer-card.component.scss +25 -0
- package/app/plugins/lite-selector/lite-selector/component/answers-slideout/answers-slideout.component.d.ts +72 -0
- package/app/plugins/lite-selector/lite-selector/component/answers-slideout/answers-slideout.component.scss +146 -0
- package/app/plugins/lite-selector/lite-selector/component/color-filter/color-filter.component.d.ts +19 -0
- package/app/plugins/lite-selector/lite-selector/component/color-filter/color-filter.component.scss +37 -0
- package/app/plugins/lite-selector/lite-selector/component/customizer/customizer.component.d.ts +28 -0
- package/app/plugins/lite-selector/lite-selector/component/customizer/customizer.component.scss +127 -0
- package/app/plugins/lite-selector/lite-selector/component/image-zoom/image-zoom.component.d.ts +9 -0
- package/app/plugins/lite-selector/lite-selector/component/image-zoom/image-zoom.component.scss +47 -0
- package/app/plugins/lite-selector/lite-selector/component/selections-summary/selections-summary-line.component.d.ts +31 -0
- package/app/plugins/lite-selector/lite-selector/component/selections-summary/selections-summary-line.component.scss +11 -0
- package/app/plugins/lite-selector/lite-selector/component/selections-summary/selections-summary.component.d.ts +38 -0
- package/app/plugins/lite-selector/lite-selector/component/selections-summary/selections-summary.component.scss +80 -0
- package/app/plugins/lite-selector/lite-selector/component/tag-filter/tag-filter.component.d.ts +8 -0
- package/app/plugins/lite-selector/lite-selector/component/tag-filter/tag-filter.component.scss +10 -0
- package/app/plugins/lite-selector/lite-selector/lite-selector.component.d.ts +40 -0
- package/app/plugins/lite-selector/lite-selector/lite-selector.component.scss +10 -0
- package/app/plugins/lite-selector/lite-selector/service/customizer.service.d.ts +44 -0
- package/app/plugins/lite-selector/lite-selector.module.d.ts +22 -0
- package/app/plugins/model-uploader/model-previewer/model-preview.component.d.ts +57 -0
- package/app/plugins/model-uploader/model-previewer/model-preview.component.scss +75 -0
- package/app/plugins/model-uploader/model-uploader/model-upload.component.scss +34 -0
- package/app/plugins/model-uploader/model-uploader/model-uploader.component.d.ts +23 -0
- package/app/plugins/model-uploader/model-uploader.module.d.ts +16 -0
- package/app/plugins/plugin-interface.d.ts +5 -0
- package/app/plugins/plugins.module.d.ts +15 -0
- package/app/plugins/presets/presets/presets.component.d.ts +22 -0
- package/app/plugins/presets/presets/presets.component.scss +0 -0
- package/app/plugins/presets/presets.module.d.ts +10 -0
- package/app/plugins/product-catalog/own-collection-catalog/product-own-collection.component.d.ts +19 -0
- package/app/plugins/product-catalog/own-collection-catalog/product-own-collection.component.scss +4 -0
- package/app/plugins/product-catalog/own-collection-catalog/product-own-collection.module.d.ts +10 -0
- package/app/plugins/product-catalog/product-catalog/product-catalog.component.d.ts +70 -0
- package/app/plugins/product-catalog/product-catalog/product-catalog.component.scss +128 -0
- package/app/plugins/product-catalog/product-catalog.module.d.ts +16 -0
- package/app/plugins/render/enum/connection-status.d.ts +6 -0
- package/app/plugins/render/enum/render-modes.d.ts +5 -0
- package/app/plugins/render/enum/render-status.d.ts +7 -0
- package/app/plugins/render/model/camera-position.d.ts +7 -0
- package/app/plugins/render/model/image-size.d.ts +6 -0
- package/app/plugins/render/model/lightning.d.ts +5 -0
- package/app/plugins/render/model/render-data.d.ts +15 -0
- package/app/plugins/render/model/render-environment.d.ts +6 -0
- package/app/plugins/render/model/render-parameters.d.ts +15 -0
- package/app/plugins/render/model/render-queue-item.d.ts +14 -0
- package/app/plugins/render/model/render-settings.d.ts +9 -0
- package/app/plugins/render/model/render.d.ts +14 -0
- package/app/plugins/render/render-controls/render-controls.component.d.ts +27 -0
- package/app/plugins/render/render-controls/render-controls.component.scss +51 -0
- package/app/plugins/render/render-dialog/render-dialog.component.d.ts +59 -0
- package/app/plugins/render/render-dialog/render-dialog.component.scss +320 -0
- package/app/plugins/render/render.module.d.ts +20 -0
- package/app/plugins/render/service/new-render.service.d.ts +65 -0
- package/app/plugins/render/service/render.service.d.ts +104 -0
- package/app/plugins/room-planner/components/appearance-section/appearance-section.component.d.ts +43 -0
- package/app/plugins/room-planner/components/appearance-section/appearance-section.component.scss +14 -0
- package/app/plugins/room-planner/components/color-picker/color-picker.component.d.ts +11 -0
- package/app/plugins/room-planner/components/color-picker/color-picker.component.scss +0 -0
- package/app/plugins/room-planner/components/custom-cylinder-creator/custom-cylinder-creator.component.d.ts +49 -0
- package/app/plugins/room-planner/components/custom-cylinder-creator/custom-cylinder-creator.component.scss +19 -0
- package/app/plugins/room-planner/components/custome-shape-creator/custom-shape-creator.component.d.ts +49 -0
- package/app/plugins/room-planner/components/custome-shape-creator/custom-shape-creator.component.scss +24 -0
- package/app/plugins/room-planner/components/dimension-input/dimension-input.component.d.ts +22 -0
- package/app/plugins/room-planner/components/dimension-input/dimension-input.component.scss +14 -0
- package/app/plugins/room-planner/components/edit-apply/edit-apply.component.d.ts +19 -0
- package/app/plugins/room-planner/components/edit-apply/edit-apply.component.scss +0 -0
- package/app/plugins/room-planner/components/edit-parameter/edit-parameter.component.d.ts +28 -0
- package/app/plugins/room-planner/components/edit-parameter/edit-parameter.component.scss +23 -0
- package/app/plugins/room-planner/components/file-drop/file-drop.component.d.ts +21 -0
- package/app/plugins/room-planner/components/file-drop/file-drop.component.scss +31 -0
- package/app/plugins/room-planner/components/floorplanner/const/defaults.d.ts +48 -0
- package/app/plugins/room-planner/components/floorplanner/floorplanner-mode.d.ts +9 -0
- package/app/plugins/room-planner/components/floorplanner/floorplanner.component.d.ts +172 -0
- package/app/plugins/room-planner/components/floorplanner/floorplanner.component.scss +48 -0
- package/app/plugins/room-planner/components/floorplanner/service/floorplan.service.d.ts +103 -0
- package/app/plugins/room-planner/components/floorplanner/service/room.service.d.ts +75 -0
- package/app/plugins/room-planner/components/floorplanner/snap-indicator-mode.d.ts +5 -0
- package/app/plugins/room-planner/components/floorplanner/utils/context.utils.d.ts +5 -0
- package/app/plugins/room-planner/components/object-library/object-library.component.d.ts +23 -0
- package/app/plugins/room-planner/components/object-library/object-library.component.scss +43 -0
- package/app/plugins/room-planner/components/ral-color-picker/ral-color-picker.component.d.ts +22 -0
- package/app/plugins/room-planner/components/ral-color-picker/ral-color-picker.component.scss +55 -0
- package/app/plugins/room-planner/components/rgb-color-picker/rgb-color-picker.component.d.ts +11 -0
- package/app/plugins/room-planner/components/rgb-color-picker/rgb-color-picker.component.scss +10 -0
- package/app/plugins/room-planner/components/selected-floor/selected-floor.component.d.ts +16 -0
- package/app/plugins/room-planner/components/selected-floor/selected-floor.component.scss +16 -0
- package/app/plugins/room-planner/components/selected-object/selected-object.component.d.ts +44 -0
- package/app/plugins/room-planner/components/selected-object/selected-object.component.scss +21 -0
- package/app/plugins/room-planner/components/selected-threed-object/selected-threed-object.component.d.ts +57 -0
- package/app/plugins/room-planner/components/selected-threed-object/selected-threed-object.component.scss +35 -0
- package/app/plugins/room-planner/components/selected-wall/selected-wall.component.d.ts +45 -0
- package/app/plugins/room-planner/components/selected-wall/selected-wall.component.scss +31 -0
- package/app/plugins/room-planner/components/settings/settings-options.component.d.ts +18 -0
- package/app/plugins/room-planner/components/settings/settings-options.component.scss +46 -0
- package/app/plugins/room-planner/components/settings/settings.component.d.ts +63 -0
- package/app/plugins/room-planner/components/settings/settings.component.scss +42 -0
- package/app/plugins/room-planner/components/texture-editor/texture-editor.component.d.ts +125 -0
- package/app/plugins/room-planner/components/texture-editor/texture-editor.component.scss +38 -0
- package/app/plugins/room-planner/components/texture-picker/texture-picker.component.d.ts +25 -0
- package/app/plugins/room-planner/components/texture-picker/texture-picker.component.scss +49 -0
- package/app/plugins/room-planner/components/wall-length-input/wall-length-input.component.d.ts +16 -0
- package/app/plugins/room-planner/components/wall-length-input/wall-length-input.component.scss +5 -0
- package/app/plugins/room-planner/const/key.d.ts +10 -0
- package/app/plugins/room-planner/room-planner/room-planner.component.d.ts +236 -0
- package/app/plugins/room-planner/room-planner/room-planner.component.scss +167 -0
- package/app/plugins/room-planner/room-planner.module.d.ts +59 -0
- package/app/plugins/threed-in-photo/components/threed-in-photo-scene/threed-in-photo-scene.component.d.ts +18 -0
- package/app/plugins/threed-in-photo/components/threed-in-photo-scene/threed-in-photo-scene.component.scss +7 -0
- package/app/plugins/threed-in-photo/components/upload-image/upload-image.component.d.ts +18 -0
- package/app/plugins/threed-in-photo/components/upload-image/upload-image.component.scss +7 -0
- package/app/plugins/threed-in-photo/components/view-control/view-control.component.d.ts +30 -0
- package/app/plugins/threed-in-photo/components/view-control/view-control.component.scss +40 -0
- package/app/plugins/threed-in-photo/models/model-output.d.ts +14 -0
- package/app/plugins/threed-in-photo/services/threed-in-photo-build.service.d.ts +37 -0
- package/app/plugins/threed-in-photo/services/threed-in-photo-connection.service.d.ts +8 -0
- package/app/plugins/threed-in-photo/services/threed-in-photo-control.service.d.ts +14 -0
- package/app/plugins/threed-in-photo/services/threed-in-photo-event-listeners.service.d.ts +15 -0
- package/app/plugins/threed-in-photo/services/threed-in-photo-event.service.d.ts +9 -0
- package/app/plugins/threed-in-photo/services/threed-in-photo-initializer.service.d.ts +27 -0
- package/app/plugins/threed-in-photo/services/threed-in-photo-render.service.d.ts +20 -0
- package/app/plugins/threed-in-photo/services/threed-in-photo-scene.service.d.ts +12 -0
- package/app/plugins/threed-in-photo/services/threed-in-photo-view.service.d.ts +8 -0
- package/app/plugins/threed-in-photo/threed-in-photo.module.d.ts +17 -0
- package/app/plugins/threed-in-photo/utils/utils.d.ts +6 -0
- package/app/plugins/threedselector/element-buttons/element-buttons.component.d.ts +31 -0
- package/app/plugins/threedselector/element-buttons/element-buttons.component.scss +61 -0
- package/app/plugins/threedselector/element-slider/element-slider.component.d.ts +14 -0
- package/app/plugins/threedselector/element-slider/element-slider.component.scss +47 -0
- package/app/plugins/threedselector/element-toolbar/element-toolbar.component.d.ts +26 -0
- package/app/plugins/threedselector/element-toolbar/element-toolbar.component.scss +142 -0
- package/app/plugins/threedselector/threedselector/model/furniture-connected-part-integration.d.ts +7 -0
- package/app/plugins/threedselector/threedselector/model/furniture-integration.d.ts +12 -0
- package/app/plugins/threedselector/threedselector/model/furniture-part-integration.d.ts +14 -0
- package/app/plugins/threedselector/threedselector/model/furniture-part-variation.d.ts +7 -0
- package/app/plugins/threedselector/threedselector/model/material.d.ts +41 -0
- package/app/plugins/threedselector/threedselector/model/variation-settings.d.ts +53 -0
- package/app/plugins/threedselector/threedselector/model/variation.d.ts +11 -0
- package/app/plugins/threedselector/threedselector/service/animation.service.d.ts +22 -0
- package/app/plugins/threedselector/threedselector/service/build-furniture.service.d.ts +186 -0
- package/app/plugins/threedselector/threedselector/service/dimensions.service.d.ts +33 -0
- package/app/plugins/threedselector/threedselector/service/element.service.d.ts +45 -0
- package/app/plugins/threedselector/threedselector/service/light-creation.service.d.ts +9 -0
- package/app/plugins/threedselector/threedselector/service/load-furniture.service.d.ts +74 -0
- package/app/plugins/threedselector/threedselector/service/resize.service.d.ts +13 -0
- package/app/plugins/threedselector/threedselector/service/third-party-model.service.d.ts +66 -0
- package/app/plugins/threedselector/threedselector/service/threedselector.service.d.ts +22 -0
- package/app/plugins/threedselector/threedselector/service/variation-cache.service.d.ts +23 -0
- package/app/plugins/threedselector/threedselector/service/variation.service.d.ts +23 -0
- package/app/plugins/threedselector/threedselector/threedselector.component.d.ts +188 -0
- package/app/plugins/threedselector/threedselector/threedselector.component.scss +82 -0
- package/app/plugins/threedselector/threedselector/utils/asset.utils.d.ts +19 -0
- package/app/plugins/threedselector/threedselector/utils/image.utils.d.ts +6 -0
- package/app/plugins/threedselector/threedselector/utils/json-parser.utils.d.ts +9 -0
- package/app/plugins/threedselector/threedselector/utils/scene-3d.utils.d.ts +10 -0
- package/app/plugins/threedselector/threedselector.module.d.ts +31 -0
- package/app/plugins/toolbar/download-dialog/download-dialog.component.d.ts +14 -0
- package/app/plugins/toolbar/download-dialog/download-dialog.component.scss +22 -0
- package/app/plugins/toolbar/draw-dialog/draw-dialog.component.d.ts +66 -0
- package/app/plugins/toolbar/draw-dialog/draw-dialog.component.scss +97 -0
- package/app/plugins/toolbar/edit-preset-dialog/edit-preset-dialog.component.d.ts +8 -0
- package/app/plugins/toolbar/edit-preset-dialog/edit-preset-dialog.component.scss +0 -0
- package/app/plugins/toolbar/landing-screen-modal/landing-screen-modal.component.d.ts +36 -0
- package/app/plugins/toolbar/landing-screen-modal/landing-screen-modal.component.scss +71 -0
- package/app/plugins/toolbar/load-from-cloud-dialog/load-from-cloud-dialog.component.d.ts +36 -0
- package/app/plugins/toolbar/load-from-cloud-dialog/load-from-cloud-dialog.component.scss +3 -0
- package/app/plugins/toolbar/open-dialog/open-dialog.component.d.ts +23 -0
- package/app/plugins/toolbar/open-dialog/open-dialog.component.scss +0 -0
- package/app/plugins/toolbar/pdf-crop-dialog/pdf-crop-dialog.component.d.ts +34 -0
- package/app/plugins/toolbar/pdf-crop-dialog/pdf-crop-dialog.component.scss +17 -0
- package/app/plugins/toolbar/save-dialog/save-dialog.component.d.ts +38 -0
- package/app/plugins/toolbar/save-dialog/save-dialog.component.scss +33 -0
- package/app/plugins/toolbar/saved-dialog/saved-dialog.component.d.ts +24 -0
- package/app/plugins/toolbar/saved-dialog/saved-dialog.component.scss +7 -0
- package/app/plugins/toolbar/toolbar/limited-mode-message-component/limited-mode-message.component.d.ts +9 -0
- package/app/plugins/toolbar/toolbar/limited-mode-message-component/limited-mode-message.component.scss +10 -0
- package/app/plugins/toolbar/toolbar/toolbar.component.d.ts +101 -0
- package/app/plugins/toolbar/toolbar/toolbar.component.scss +251 -0
- package/app/plugins/toolbar/toolbar.module.d.ts +44 -0
- package/app/root/root.component.scss +0 -0
- package/app/service/dynamic-script.service.d.ts +8 -0
- package/app/service/google-tag-manager.service.d.ts +19 -0
- package/app/service/local-storage.service.d.ts +18 -0
- package/app/service/service-locator.service.d.ts +4 -0
- package/app/shared/base64-images.d.ts +4 -0
- package/app/shared/button-elevation/button-elevation.component.d.ts +40 -0
- package/app/shared/button-elevation/button-elevation.component.scss +109 -0
- package/app/shared/button-elevation/button-elevation.module.d.ts +16 -0
- package/app/shared/camera-settings-dialog/camera-settings-dialog.component.d.ts +24 -0
- package/app/shared/camera-settings-dialog/camera-settings-dialog.component.scss +30 -0
- package/app/shared/camera-settings-dialog/camera-settings-dialog.module.d.ts +16 -0
- package/app/shared/category-library/category-library.component.d.ts +10 -0
- package/app/shared/category-library/category-library.component.scss +16 -0
- package/app/shared/category-library/category-library.module.d.ts +11 -0
- package/app/shared/context-menu/context-menu.component.d.ts +12 -0
- package/app/shared/context-menu/context-menu.component.scss +25 -0
- package/app/shared/context-menu/context-menu.module.d.ts +14 -0
- package/app/shared/context-menu/item-context-menu/item-context-menu.component.d.ts +30 -0
- package/app/shared/context-menu/item-context-menu/item-context-menu.component.scss +32 -0
- package/app/shared/dialog/dialog.component.d.ts +26 -0
- package/app/shared/dialog/dialog.component.scss +25 -0
- package/app/shared/dialog/dialog.module.d.ts +12 -0
- package/app/shared/dialog/enum/dialog-type.enum.d.ts +6 -0
- package/app/shared/dialog/interface/dialog-config.interface.d.ts +7 -0
- package/app/shared/dialog/service/dialog.service.d.ts +11 -0
- package/app/shared/error-dialog/error-dialog.component.d.ts +11 -0
- package/app/shared/error-dialog/error-dialog.component.scss +0 -0
- package/app/shared/error-dialog/error-dialog.module.d.ts +10 -0
- package/app/shared/export-dialog/export-dialog.component.d.ts +11 -0
- package/app/shared/export-dialog/export-dialog.component.scss +19 -0
- package/app/shared/export-dialog/export-dialog.module.d.ts +11 -0
- package/app/shared/info-dialog/info-dialog.component.d.ts +9 -0
- package/app/shared/info-dialog/info-dialog.component.scss +15 -0
- package/app/shared/info-dialog/info-dialog.module.d.ts +12 -0
- package/app/shared/loader/hd-loader.component.d.ts +6 -0
- package/app/shared/loader/hd-loader.component.scss +44 -0
- package/app/shared/loader/hd-loader.module.d.ts +9 -0
- package/app/shared/loader/loader.component.scss +42 -0
- package/app/shared/loading-overlay/dialog/loading-overlay-dialog.component.d.ts +8 -0
- package/app/shared/loading-overlay/dialog/loading-overlay-dialog.component.scss +3 -0
- package/app/shared/loading-overlay/loading-overlay.component.d.ts +19 -0
- package/app/shared/loading-overlay/loading-overlay.component.scss +9 -0
- package/app/shared/loading-overlay/loading-overlay.module.d.ts +11 -0
- package/app/shared/model-dialog/model-dialog-furniture-list.component.d.ts +35 -0
- package/app/shared/model-dialog/model-dialog-furniture-list.component.scss +221 -0
- package/app/shared/model-dialog/model-dialog.component.d.ts +31 -0
- package/app/shared/model-dialog/model-dialog.component.scss +22 -0
- package/app/shared/model-dialog/model-dialog.module.d.ts +16 -0
- package/app/shared/progress-bar/progress-bar.component.d.ts +9 -0
- package/app/shared/progress-bar/progress-bar.component.scss +11 -0
- package/app/shared/progress-bar/progress-bar.module.d.ts +9 -0
- package/app/shared/register-dialog/register-dialog.component.d.ts +26 -0
- package/app/shared/register-dialog/register-dialog.component.scss +21 -0
- package/app/shared/screen-size-analysis/device-size-type.d.ts +5 -0
- package/app/shared/screen-size-analysis/navigator-type.enum.d.ts +4 -0
- package/app/shared/screen-size-analysis/screen-size-analysis.service.d.ts +27 -0
- package/app/shared/screen-size-analysis/screen-size-config.d.ts +5 -0
- package/app/shared/screen-size-analysis/screen-size-info.d.ts +10 -0
- package/app/shared/slider-input/slider-input.component.d.ts +13 -0
- package/app/shared/slider-input/slider-input.component.scss +12 -0
- package/app/shared/slider-input/slider-input.module.d.ts +13 -0
- package/app/shared/toolbar-icon/toolbar-icon.component.d.ts +12 -0
- package/app/shared/toolbar-icon/toolbar-icon.component.scss +8 -0
- package/app/shared/toolbar-icon/toolbar-icon.module.d.ts +11 -0
- package/app/shared/zoom-controls/zoom-controls.component.d.ts +16 -0
- package/app/shared/zoom-controls/zoom-controls.component.scss +0 -0
- package/app/shared/zoom-controls/zoom-controls.module.d.ts +10 -0
- package/assets/.gitkeep +0 -0
- package/assets/3d-models/pin.mtl +12 -0
- package/assets/3d-models/pin.obj +1083 -0
- package/assets/colors/ral.json +2345 -0
- package/assets/cursors/pencil.png +0 -0
- package/assets/cursors/pencil.svg +1 -0
- package/assets/fonts/helvetiker_regular.ttf +0 -0
- package/assets/fonts/helvetiker_regular.typeface.json +1 -0
- package/assets/fonts/helvetiker_regular.woff +0 -0
- package/assets/fonts/optimer_regular.typeface.json +1 -0
- package/assets/hdri/TSStudio3Point.hdr +135 -0
- package/assets/hdri/ground_MASK.jpg +0 -0
- package/assets/hdri/std_env_v2_A.hdr +0 -0
- package/assets/hdri/std_env_v2_B.hdr +0 -0
- package/assets/hdri/std_env_v2_C.hdr +0 -0
- package/assets/hdri/std_env_v2_D.hdr +0 -0
- package/assets/hdri/std_env_v2_E.hdr +46 -0
- package/assets/icons/add-button.svg +10 -0
- package/assets/icons/ar_circle.svg +7 -0
- package/assets/icons/arrow_point_down.svg +6 -0
- package/assets/icons/brush.svg +1 -0
- package/assets/icons/cart-shopping-regular.svg +1 -0
- package/assets/icons/check.svg +6 -0
- package/assets/icons/cit_powered_white.svg +92 -0
- package/assets/icons/conf_frame.svg +1 -0
- package/assets/icons/conf_plane.svg +1 -0
- package/assets/icons/cross.svg +1 -0
- package/assets/icons/cube-outline.svg +1 -0
- package/assets/icons/cube-unfolded.svg +1 -0
- package/assets/icons/delete-button.svg +16 -0
- package/assets/icons/download.svg +4 -0
- package/assets/icons/edit-button.svg +18 -0
- package/assets/icons/google-cardboard-orange.svg +1 -0
- package/assets/icons/google-cardboard.svg +1 -0
- package/assets/icons/hand-pointer.svg +1 -0
- package/assets/icons/height_adjust.svg +1 -0
- package/assets/icons/magic-wand.svg +57 -0
- package/assets/icons/magnifier.svg +12 -0
- package/assets/icons/measurements.svg +1 -0
- package/assets/icons/move-phone-ar.svg +4 -0
- package/assets/icons/qrcode.svg +1 -0
- package/assets/icons/street-view-orange.svg +5 -0
- package/assets/icons/street-view.svg +6 -0
- package/assets/icons/swap-button.svg +12 -0
- package/assets/icons/tilt-phone.svg +29 -0
- package/assets/icons/triangle_down.svg +1 -0
- package/assets/icons/triangle_up.svg +1 -0
- package/assets/images/colijn-logo.webp +0 -0
- package/assets/images/favicon.ico +0 -0
- package/assets/images/favicon.png +0 -0
- package/assets/images/ione360-logo.webp +0 -0
- package/assets/images/logo.svg +35 -0
- package/assets/workers/indexedDB-web-worker.js +74 -0
- package/bundle-styles.scss +267 -0
- package/bundles/colijnit-homedecorator.umd.js +47374 -0
- package/bundles/colijnit-homedecorator.umd.js.map +1 -0
- package/colijnit-homedecorator.d.ts +5 -0
- package/environments/environment.d.ts +11 -0
- package/esm2015/app/app.version.js +9 -0
- package/esm2015/app/core/components/debug/debug.component.js +57 -0
- package/esm2015/app/core/components/error/error-message.component.js +55 -0
- package/esm2015/app/core/components/tooltip/tooltip.component.js +73 -0
- package/esm2015/app/core/const/dimensioning.js +28 -0
- package/esm2015/app/core/core.module.js +159 -0
- package/esm2015/app/core/directive/autofocus.directive.js +26 -0
- package/esm2015/app/core/directive/tooltip.directive.js +64 -0
- package/esm2015/app/core/directive/visibility-observer-master.directive.js +53 -0
- package/esm2015/app/core/directive/visibility-observer.directive.js +54 -0
- package/esm2015/app/core/enum/configuration-key.enum.js +37 -0
- package/esm2015/app/core/enum/export-type.enum.js +7 -0
- package/esm2015/app/core/enum/google-tag-manager-event.enum.js +14 -0
- package/esm2015/app/core/enum/icon-name.enum.js +17 -0
- package/esm2015/app/core/enum/icon.enum.js +35 -0
- package/esm2015/app/core/enum/light.enum.js +9 -0
- package/esm2015/app/core/enum/message-type.enum.js +71 -0
- package/esm2015/app/core/enum/model-type.enum.js +8 -0
- package/esm2015/app/core/enum/output-encoding.enum.js +6 -0
- package/esm2015/app/core/enum/shadow-map-type.enum.js +8 -0
- package/esm2015/app/core/enum/user-role-type.enum.js +22 -0
- package/esm2015/app/core/enum/view-mode.enum.js +11 -0
- package/esm2015/app/core/enum/xr-mode.enum.js +6 -0
- package/esm2015/app/core/interface/adjustable-element.interface.js +2 -0
- package/esm2015/app/core/interface/category.interface.js +2 -0
- package/esm2015/app/core/interface/changes.interface.js +2 -0
- package/esm2015/app/core/interface/child-params.interface.js +2 -0
- package/esm2015/app/core/interface/configuration-data.interface.js +2 -0
- package/esm2015/app/core/interface/external-settings.interface.js +2 -0
- package/esm2015/app/core/interface/info-dialog-data.interface.js +2 -0
- package/esm2015/app/core/interface/light-preset.interface.js +2 -0
- package/esm2015/app/core/interface/loading-overlay-data.interface.js +2 -0
- package/esm2015/app/core/interface/media-resource.interface.js +2 -0
- package/esm2015/app/core/interface/message-with-payload.interface.js +2 -0
- package/esm2015/app/core/interface/message-without-payload.interface.js +2 -0
- package/esm2015/app/core/interface/preset.interface.js +2 -0
- package/esm2015/app/core/interface/selected-floor-event.interface.js +2 -0
- package/esm2015/app/core/interface/selected-wall-event.interface.js +2 -0
- package/esm2015/app/core/interface/texture.interface.js +2 -0
- package/esm2015/app/core/interface/toolbar-icon.interface.js +2 -0
- package/esm2015/app/core/model/ar-position-indicator.js +21 -0
- package/esm2015/app/core/model/camera-settings.js +14 -0
- package/esm2015/app/core/model/category.js +15 -0
- package/esm2015/app/core/model/custom-button.js +16 -0
- package/esm2015/app/core/model/error-message.js +9 -0
- package/esm2015/app/core/model/export-object.js +3 -0
- package/esm2015/app/core/model/from-intersection-observer.js +64 -0
- package/esm2015/app/core/model/homedecorator-settings-options.js +49 -0
- package/esm2015/app/core/model/homedecorator-settings.js +22 -0
- package/esm2015/app/core/model/icon.js +34 -0
- package/esm2015/app/core/model/light-preset.js +59 -0
- package/esm2015/app/core/model/light-properties.js +45 -0
- package/esm2015/app/core/model/media-resource.js +10 -0
- package/esm2015/app/core/model/preset.js +15 -0
- package/esm2015/app/core/model/ral-color.js +2 -0
- package/esm2015/app/core/model/shadow-properties.js +10 -0
- package/esm2015/app/core/model/texture-type.js +8 -0
- package/esm2015/app/core/model/texture.js +58 -0
- package/esm2015/app/core/model/three-object.js +2 -0
- package/esm2015/app/core/model/toast-type.js +7 -0
- package/esm2015/app/core/model/toast.js +7 -0
- package/esm2015/app/core/model/xr-reticle.js +87 -0
- package/esm2015/app/core/pipe/append.pipe.js +21 -0
- package/esm2015/app/core/pipe/cm-to-measure.pipe.js +20 -0
- package/esm2015/app/core/pipe/filter.pipe.js +20 -0
- package/esm2015/app/core/pipe/keys.pipe.js +22 -0
- package/esm2015/app/core/pipe/localize.pipe.js +28 -0
- package/esm2015/app/core/pipe/m-to-measure.pipe.js +20 -0
- package/esm2015/app/core/pipe/prepend.pipe.js +21 -0
- package/esm2015/app/core/pipe/scm-to-measure.pipe.js +20 -0
- package/esm2015/app/core/pipe/sm-to-measure.pipe.js +20 -0
- package/esm2015/app/core/pipe/strip-html.pipe.js +17 -0
- package/esm2015/app/core/service/3dm-api.js +246 -0
- package/esm2015/app/core/service/app-state.service.js +128 -0
- package/esm2015/app/core/service/configuration.service.js +72 -0
- package/esm2015/app/core/service/debug.service.js +45 -0
- package/esm2015/app/core/service/dimensioning.service.js +45 -0
- package/esm2015/app/core/service/dynamic-camera.service.js +107 -0
- package/esm2015/app/core/service/environment.service.js +17 -0
- package/esm2015/app/core/service/error.service.js +30 -0
- package/esm2015/app/core/service/export.service.js +97 -0
- package/esm2015/app/core/service/file.service.js +44 -0
- package/esm2015/app/core/service/homedecorator-app-event.service.js +27 -0
- package/esm2015/app/core/service/homedecorator-app.service.js +201 -0
- package/esm2015/app/core/service/homedecorator-connector-adapter.service.js +455 -0
- package/esm2015/app/core/service/homedecorator-connector.service.js +604 -0
- package/esm2015/app/core/service/homedecorator-dictionary.service.js +73 -0
- package/esm2015/app/core/service/homedecorator-icon-cache.service.js +43 -0
- package/esm2015/app/core/service/homedecorator-settings.service.js +146 -0
- package/esm2015/app/core/service/homedecorator.service.js +37 -0
- package/esm2015/app/core/service/integration.service.js +56 -0
- package/esm2015/app/core/service/item-serialization.service.js +188 -0
- package/esm2015/app/core/service/json-utils.service.js +56 -0
- package/esm2015/app/core/service/message-bus.service.js +28 -0
- package/esm2015/app/core/service/permanent-store.service.js +135 -0
- package/esm2015/app/core/service/presets.service.js +297 -0
- package/esm2015/app/core/service/progress.service.js +74 -0
- package/esm2015/app/core/service/ral.service.js +98 -0
- package/esm2015/app/core/service/skip-button-info.service.js +60 -0
- package/esm2015/app/core/service/toast.service.js +23 -0
- package/esm2015/app/core/service/utils.service.js +566 -0
- package/esm2015/app/core/service/view-mode.service.js +61 -0
- package/esm2015/app/core/service/web-worker.service.js +44 -0
- package/esm2015/app/core/utils/clone-utils.js +41 -0
- package/esm2015/app/core/utils/color.utils.js +20 -0
- package/esm2015/app/core/utils/file.utils.js +234 -0
- package/esm2015/app/core/utils/function/is-empty.function.js +5 -0
- package/esm2015/app/core/utils/function/is-nill.function.js +5 -0
- package/esm2015/app/core/utils/material.utils.js +407 -0
- package/esm2015/app/core/utils/object.utils.js +191 -0
- package/esm2015/app/core/utils/relative-position.utils.js +74 -0
- package/esm2015/app/core/utils/variation-utils.js +314 -0
- package/esm2015/app/core/workers/enum/web-worker-message.enum.js +6 -0
- package/esm2015/app/core/workers/enum/web-worker-type.enum.js +5 -0
- package/esm2015/app/development/components/selected-child-material-texture.component.js +467 -0
- package/esm2015/app/development/components/selected-child-material.component.js +863 -0
- package/esm2015/app/development/components/selected-child.component.js +64 -0
- package/esm2015/app/development/components/selected-object-base.js +127 -0
- package/esm2015/app/development/components/selected-object.component.js +98 -0
- package/esm2015/app/development/development.module.js +74 -0
- package/esm2015/app/development/directive/development.directive.js +92 -0
- package/esm2015/app/development/service/development.service.js +212 -0
- package/esm2015/app/homedecorator.component.js +285 -0
- package/esm2015/app/homedecorator.module.js +60 -0
- package/esm2015/app/plugins/core3d/collision-manager/collision-manager.service.js +119 -0
- package/esm2015/app/plugins/core3d/collision-manager/floorplan-collision-detection.js +158 -0
- package/esm2015/app/plugins/core3d/collision-manager/snapping-collision.service.js +234 -0
- package/esm2015/app/plugins/core3d/components/ar-gui/ar-gui-root/ar-gui-elements/ar-gui-buttons/ar-gui-buttons.component.js +36 -0
- package/esm2015/app/plugins/core3d/components/ar-gui/ar-gui-root/ar-gui-elements/ar-gui-configurator/ar-gui-configurator.component.js +49 -0
- package/esm2015/app/plugins/core3d/components/ar-gui/ar-gui-root/ar-gui-elements/ar-gui-context-menu/ar-gui-context-menu.component.js +77 -0
- package/esm2015/app/plugins/core3d/components/ar-gui/ar-gui-root/ar-gui-elements/ar-gui-notifications/ar-gui-notifications.component.js +26 -0
- package/esm2015/app/plugins/core3d/components/ar-gui/ar-gui-root/ar-gui-root.component.js +46 -0
- package/esm2015/app/plugins/core3d/components/lightplan/edit-light/edit-light.component.js +197 -0
- package/esm2015/app/plugins/core3d/components/lightplan/edit-lightplan/edit-lightplan.component.js +197 -0
- package/esm2015/app/plugins/core3d/components/lightplan/lightplan.component.js +512 -0
- package/esm2015/app/plugins/core3d/components/scene-options/scene-options.component.js +88 -0
- package/esm2015/app/plugins/core3d/core/angles.js +19 -0
- package/esm2015/app/plugins/core3d/core/corner-utils.js +9 -0
- package/esm2015/app/plugins/core3d/core/dimensioning.js +79 -0
- package/esm2015/app/plugins/core3d/core/utils.js +606 -0
- package/esm2015/app/plugins/core3d/core3d/components/scenecontrol/scene-control.component.js +289 -0
- package/esm2015/app/plugins/core3d/core3d/core3d.component.js +243 -0
- package/esm2015/app/plugins/core3d/core3d.module.js +201 -0
- package/esm2015/app/plugins/core3d/directive/scene.directive.js +41 -0
- package/esm2015/app/plugins/core3d/enum/ar-feature.enum.js +14 -0
- package/esm2015/app/plugins/core3d/enum/direction.enum.js +10 -0
- package/esm2015/app/plugins/core3d/enum/result-type.enum.js +21 -0
- package/esm2015/app/plugins/core3d/hud/bounding-measurement-box/bounding-box-measurement.js +99 -0
- package/esm2015/app/plugins/core3d/hud/bounding-measurement-box/box-measurement.js +35 -0
- package/esm2015/app/plugins/core3d/hud/bounding-measurement-box/door-or-window-box-measurement.js +95 -0
- package/esm2015/app/plugins/core3d/hud/bounding-measurement-box/measurable.js +2 -0
- package/esm2015/app/plugins/core3d/hud/bounding-measurement-box/measurement-utils.js +22 -0
- package/esm2015/app/plugins/core3d/hud/custom-shape-name-label.js +31 -0
- package/esm2015/app/plugins/core3d/hud/floor-indicator.js +80 -0
- package/esm2015/app/plugins/core3d/hud/furniture-measurements.js +44 -0
- package/esm2015/app/plugins/core3d/hud/indicator-factory.js +49 -0
- package/esm2015/app/plugins/core3d/hud/measurements.js +165 -0
- package/esm2015/app/plugins/core3d/hud/on-wall-measurements.js +80 -0
- package/esm2015/app/plugins/core3d/hud/opening-symbol.js +74 -0
- package/esm2015/app/plugins/core3d/hud/rotation-helper.js +263 -0
- package/esm2015/app/plugins/core3d/hud/utils.js +30 -0
- package/esm2015/app/plugins/core3d/interface/dragged-data.interface.js +2 -0
- package/esm2015/app/plugins/core3d/interface/edge-visibility-changes.js +2 -0
- package/esm2015/app/plugins/core3d/interface/model.interface.js +2 -0
- package/esm2015/app/plugins/core3d/interface/opening.interface.js +2 -0
- package/esm2015/app/plugins/core3d/interface/scene-option-button.interface.js +6 -0
- package/esm2015/app/plugins/core3d/interface/scene-update.interface.js +2 -0
- package/esm2015/app/plugins/core3d/items/base-item.js +233 -0
- package/esm2015/app/plugins/core3d/items/custom-cylinder-floor-item.js +41 -0
- package/esm2015/app/plugins/core3d/items/custom-cylinder-wall-item.js +45 -0
- package/esm2015/app/plugins/core3d/items/custom-floor-item.js +11 -0
- package/esm2015/app/plugins/core3d/items/custom-objects.js +295 -0
- package/esm2015/app/plugins/core3d/items/custom-shape-floor-item.js +45 -0
- package/esm2015/app/plugins/core3d/items/custom-shape-wall-item.js +37 -0
- package/esm2015/app/plugins/core3d/items/custom-wall-floor-item.js +84 -0
- package/esm2015/app/plugins/core3d/items/custom-wall-item.js +11 -0
- package/esm2015/app/plugins/core3d/items/factory.js +130 -0
- package/esm2015/app/plugins/core3d/items/floor-item.js +29 -0
- package/esm2015/app/plugins/core3d/items/floor-pin.js +31 -0
- package/esm2015/app/plugins/core3d/items/floor-plane-item.js +95 -0
- package/esm2015/app/plugins/core3d/items/furniture.js +2 -0
- package/esm2015/app/plugins/core3d/items/in-wall-floor-item.js +14 -0
- package/esm2015/app/plugins/core3d/items/item-group.js +160 -0
- package/esm2015/app/plugins/core3d/items/item-type.js +23 -0
- package/esm2015/app/plugins/core3d/items/item.js +388 -0
- package/esm2015/app/plugins/core3d/items/metadata.js +2 -0
- package/esm2015/app/plugins/core3d/items/on-floor-item.js +10 -0
- package/esm2015/app/plugins/core3d/items/pin.js +2 -0
- package/esm2015/app/plugins/core3d/items/three-mesh.js +17 -0
- package/esm2015/app/plugins/core3d/items/wall-floor-item.js +9 -0
- package/esm2015/app/plugins/core3d/items/wall-objects.js +2381 -0
- package/esm2015/app/plugins/core3d/items/wall-pin.js +25 -0
- package/esm2015/app/plugins/core3d/model/ar-parameters.js +12 -0
- package/esm2015/app/plugins/core3d/model/box-skin-default.js +17 -0
- package/esm2015/app/plugins/core3d/model/collision-info.js +2 -0
- package/esm2015/app/plugins/core3d/model/custom-floor-group-result.js +13 -0
- package/esm2015/app/plugins/core3d/model/cylinder-skin-default.js +14 -0
- package/esm2015/app/plugins/core3d/model/dragged-status.js +51 -0
- package/esm2015/app/plugins/core3d/model/face.js +18 -0
- package/esm2015/app/plugins/core3d/model/geometry.js +52 -0
- package/esm2015/app/plugins/core3d/model/scene-event.enum.js +12 -0
- package/esm2015/app/plugins/core3d/model/skin.js +2 -0
- package/esm2015/app/plugins/core3d/model/threed-model.js +49 -0
- package/esm2015/app/plugins/core3d/service/ar.service.js +844 -0
- package/esm2015/app/plugins/core3d/service/camera.service.js +340 -0
- package/esm2015/app/plugins/core3d/service/ceiling.service.js +104 -0
- package/esm2015/app/plugins/core3d/service/controls.js +763 -0
- package/esm2015/app/plugins/core3d/service/drag-and-drop.service.js +369 -0
- package/esm2015/app/plugins/core3d/service/error-glow.service.js +131 -0
- package/esm2015/app/plugins/core3d/service/floor.service.js +229 -0
- package/esm2015/app/plugins/core3d/service/font.service.js +27 -0
- package/esm2015/app/plugins/core3d/service/hud.service.js +404 -0
- package/esm2015/app/plugins/core3d/service/intersection.service.js +55 -0
- package/esm2015/app/plugins/core3d/service/item-group.service.js +117 -0
- package/esm2015/app/plugins/core3d/service/item.service.js +205 -0
- package/esm2015/app/plugins/core3d/service/light-presets.service.js +296 -0
- package/esm2015/app/plugins/core3d/service/lights.service.js +190 -0
- package/esm2015/app/plugins/core3d/service/message-board.service.js +60 -0
- package/esm2015/app/plugins/core3d/service/models.service.js +146 -0
- package/esm2015/app/plugins/core3d/service/outline.service.js +150 -0
- package/esm2015/app/plugins/core3d/service/rotation.service.js +183 -0
- package/esm2015/app/plugins/core3d/service/scene-event.service.js +1000 -0
- package/esm2015/app/plugins/core3d/service/scene-options.service.js +24 -0
- package/esm2015/app/plugins/core3d/service/scene.service.js +351 -0
- package/esm2015/app/plugins/core3d/service/vr.service.js +198 -0
- package/esm2015/app/plugins/core3d/service/wall-measurements.service.js +79 -0
- package/esm2015/app/plugins/core3d/service/xr.service.js +397 -0
- package/esm2015/app/plugins/core3d/textures/DepthDataTexture.js +17 -0
- package/esm2015/app/plugins/core3d/walkthrough-camera-controls/walkthrough-camera-controls.component.js +54 -0
- package/esm2015/app/plugins/furniture-manager/furniture-library/furniture-library.component.js +92 -0
- package/esm2015/app/plugins/furniture-manager/furniture-manager/furniture-manager.component.js +458 -0
- package/esm2015/app/plugins/furniture-manager/furniture-manager.module.js +100 -0
- package/esm2015/app/plugins/help/help/help.component.js +71 -0
- package/esm2015/app/plugins/help/help-dialog/help-dialog.component.js +83 -0
- package/esm2015/app/plugins/help/help.module.js +35 -0
- package/esm2015/app/plugins/lite-selector/lite-selector/component/animation/animation.component.js +36 -0
- package/esm2015/app/plugins/lite-selector/lite-selector/component/answer-card/answer-card.component.js +187 -0
- package/esm2015/app/plugins/lite-selector/lite-selector/component/answers-slideout/answers-slideout.component.js +417 -0
- package/esm2015/app/plugins/lite-selector/lite-selector/component/color-filter/color-filter.component.js +44 -0
- package/esm2015/app/plugins/lite-selector/lite-selector/component/customizer/customizer.component.js +82 -0
- package/esm2015/app/plugins/lite-selector/lite-selector/component/image-zoom/image-zoom.component.js +27 -0
- package/esm2015/app/plugins/lite-selector/lite-selector/component/selections-summary/selections-summary-line.component.js +148 -0
- package/esm2015/app/plugins/lite-selector/lite-selector/component/selections-summary/selections-summary.component.js +167 -0
- package/esm2015/app/plugins/lite-selector/lite-selector/component/tag-filter/tag-filter.component.js +25 -0
- package/esm2015/app/plugins/lite-selector/lite-selector/lite-selector.component.js +150 -0
- package/esm2015/app/plugins/lite-selector/lite-selector/service/customizer.service.js +222 -0
- package/esm2015/app/plugins/lite-selector/lite-selector.module.js +108 -0
- package/esm2015/app/plugins/model-uploader/model-previewer/model-preview.component.js +470 -0
- package/esm2015/app/plugins/model-uploader/model-uploader/model-uploader.component.js +132 -0
- package/esm2015/app/plugins/model-uploader/model-uploader.module.js +60 -0
- package/esm2015/app/plugins/plugin-interface.js +2 -0
- package/esm2015/app/plugins/plugins.module.js +80 -0
- package/esm2015/app/plugins/presets/presets/presets.component.js +72 -0
- package/esm2015/app/plugins/presets/presets.module.js +33 -0
- package/esm2015/app/plugins/product-catalog/own-collection-catalog/product-own-collection.component.js +57 -0
- package/esm2015/app/plugins/product-catalog/own-collection-catalog/product-own-collection.module.js +34 -0
- package/esm2015/app/plugins/product-catalog/product-catalog/product-catalog.component.js +428 -0
- package/esm2015/app/plugins/product-catalog/product-catalog.module.js +61 -0
- package/esm2015/app/plugins/render/enum/connection-status.js +8 -0
- package/esm2015/app/plugins/render/enum/render-modes.js +7 -0
- package/esm2015/app/plugins/render/enum/render-status.js +9 -0
- package/esm2015/app/plugins/render/model/camera-position.js +6 -0
- package/esm2015/app/plugins/render/model/image-size.js +3 -0
- package/esm2015/app/plugins/render/model/lightning.js +3 -0
- package/esm2015/app/plugins/render/model/render-data.js +6 -0
- package/esm2015/app/plugins/render/model/render-environment.js +3 -0
- package/esm2015/app/plugins/render/model/render-parameters.js +15 -0
- package/esm2015/app/plugins/render/model/render-queue-item.js +11 -0
- package/esm2015/app/plugins/render/model/render-settings.js +12 -0
- package/esm2015/app/plugins/render/model/render.js +10 -0
- package/esm2015/app/plugins/render/render-controls/render-controls.component.js +89 -0
- package/esm2015/app/plugins/render/render-dialog/render-dialog.component.js +318 -0
- package/esm2015/app/plugins/render/render.module.js +85 -0
- package/esm2015/app/plugins/render/service/new-render.service.js +302 -0
- package/esm2015/app/plugins/render/service/render.service.js +650 -0
- package/esm2015/app/plugins/room-planner/components/appearance-section/appearance-section.component.js +190 -0
- package/esm2015/app/plugins/room-planner/components/color-picker/color-picker.component.js +32 -0
- package/esm2015/app/plugins/room-planner/components/custom-cylinder-creator/custom-cylinder-creator.component.js +219 -0
- package/esm2015/app/plugins/room-planner/components/custome-shape-creator/custom-shape-creator.component.js +257 -0
- package/esm2015/app/plugins/room-planner/components/dimension-input/dimension-input.component.js +66 -0
- package/esm2015/app/plugins/room-planner/components/edit-apply/edit-apply.component.js +57 -0
- package/esm2015/app/plugins/room-planner/components/edit-parameter/edit-parameter.component.js +79 -0
- package/esm2015/app/plugins/room-planner/components/file-drop/file-drop.component.js +107 -0
- package/esm2015/app/plugins/room-planner/components/floorplanner/const/defaults.js +57 -0
- package/esm2015/app/plugins/room-planner/components/floorplanner/floorplanner-mode.js +11 -0
- package/esm2015/app/plugins/room-planner/components/floorplanner/floorplanner.component.js +1303 -0
- package/esm2015/app/plugins/room-planner/components/floorplanner/service/floorplan.service.js +536 -0
- package/esm2015/app/plugins/room-planner/components/floorplanner/service/room.service.js +330 -0
- package/esm2015/app/plugins/room-planner/components/floorplanner/snap-indicator-mode.js +7 -0
- package/esm2015/app/plugins/room-planner/components/floorplanner/utils/context.utils.js +53 -0
- package/esm2015/app/plugins/room-planner/components/object-library/object-library.component.js +63 -0
- package/esm2015/app/plugins/room-planner/components/ral-color-picker/ral-color-picker.component.js +128 -0
- package/esm2015/app/plugins/room-planner/components/rgb-color-picker/rgb-color-picker.component.js +37 -0
- package/esm2015/app/plugins/room-planner/components/selected-floor/selected-floor.component.js +36 -0
- package/esm2015/app/plugins/room-planner/components/selected-object/selected-object.component.js +203 -0
- package/esm2015/app/plugins/room-planner/components/selected-threed-object/selected-threed-object.component.js +139 -0
- package/esm2015/app/plugins/room-planner/components/selected-wall/selected-wall.component.js +102 -0
- package/esm2015/app/plugins/room-planner/components/settings/settings-options.component.js +152 -0
- package/esm2015/app/plugins/room-planner/components/settings/settings.component.js +188 -0
- package/esm2015/app/plugins/room-planner/components/texture-editor/texture-editor.component.js +617 -0
- package/esm2015/app/plugins/room-planner/components/texture-picker/texture-picker.component.js +74 -0
- package/esm2015/app/plugins/room-planner/components/wall-length-input/wall-length-input.component.js +48 -0
- package/esm2015/app/plugins/room-planner/const/key.js +12 -0
- package/esm2015/app/plugins/room-planner/room-planner/room-planner.component.js +1681 -0
- package/esm2015/app/plugins/room-planner/room-planner.module.js +233 -0
- package/esm2015/app/plugins/threed-in-photo/components/threed-in-photo-scene/threed-in-photo-scene.component.js +43 -0
- package/esm2015/app/plugins/threed-in-photo/components/upload-image/upload-image.component.js +61 -0
- package/esm2015/app/plugins/threed-in-photo/components/view-control/view-control.component.js +164 -0
- package/esm2015/app/plugins/threed-in-photo/models/model-output.js +18 -0
- package/esm2015/app/plugins/threed-in-photo/services/threed-in-photo-build.service.js +243 -0
- package/esm2015/app/plugins/threed-in-photo/services/threed-in-photo-connection.service.js +50 -0
- package/esm2015/app/plugins/threed-in-photo/services/threed-in-photo-control.service.js +33 -0
- package/esm2015/app/plugins/threed-in-photo/services/threed-in-photo-event-listeners.service.js +36 -0
- package/esm2015/app/plugins/threed-in-photo/services/threed-in-photo-event.service.js +19 -0
- package/esm2015/app/plugins/threed-in-photo/services/threed-in-photo-initializer.service.js +53 -0
- package/esm2015/app/plugins/threed-in-photo/services/threed-in-photo-render.service.js +61 -0
- package/esm2015/app/plugins/threed-in-photo/services/threed-in-photo-scene.service.js +37 -0
- package/esm2015/app/plugins/threed-in-photo/services/threed-in-photo-view.service.js +21 -0
- package/esm2015/app/plugins/threed-in-photo/threed-in-photo.module.js +67 -0
- package/esm2015/app/plugins/threed-in-photo/utils/utils.js +21 -0
- package/esm2015/app/plugins/threedselector/element-buttons/element-buttons.component.js +95 -0
- package/esm2015/app/plugins/threedselector/element-slider/element-slider.component.js +28 -0
- package/esm2015/app/plugins/threedselector/element-toolbar/element-toolbar.component.js +80 -0
- package/esm2015/app/plugins/threedselector/threedselector/model/furniture-connected-part-integration.js +3 -0
- package/esm2015/app/plugins/threedselector/threedselector/model/furniture-integration.js +13 -0
- package/esm2015/app/plugins/threedselector/threedselector/model/furniture-part-integration.js +6 -0
- package/esm2015/app/plugins/threedselector/threedselector/model/furniture-part-variation.js +3 -0
- package/esm2015/app/plugins/threedselector/threedselector/model/material.js +11 -0
- package/esm2015/app/plugins/threedselector/threedselector/model/variation-settings.js +11 -0
- package/esm2015/app/plugins/threedselector/threedselector/model/variation.js +3 -0
- package/esm2015/app/plugins/threedselector/threedselector/service/animation.service.js +65 -0
- package/esm2015/app/plugins/threedselector/threedselector/service/build-furniture.service.js +1343 -0
- package/esm2015/app/plugins/threedselector/threedselector/service/dimensions.service.js +183 -0
- package/esm2015/app/plugins/threedselector/threedselector/service/element.service.js +373 -0
- package/esm2015/app/plugins/threedselector/threedselector/service/light-creation.service.js +35 -0
- package/esm2015/app/plugins/threedselector/threedselector/service/load-furniture.service.js +291 -0
- package/esm2015/app/plugins/threedselector/threedselector/service/resize.service.js +70 -0
- package/esm2015/app/plugins/threedselector/threedselector/service/third-party-model.service.js +156 -0
- package/esm2015/app/plugins/threedselector/threedselector/service/threedselector.service.js +101 -0
- package/esm2015/app/plugins/threedselector/threedselector/service/variation-cache.service.js +133 -0
- package/esm2015/app/plugins/threedselector/threedselector/service/variation.service.js +436 -0
- package/esm2015/app/plugins/threedselector/threedselector/threedselector.component.js +1116 -0
- package/esm2015/app/plugins/threedselector/threedselector/utils/asset.utils.js +128 -0
- package/esm2015/app/plugins/threedselector/threedselector/utils/image.utils.js +33 -0
- package/esm2015/app/plugins/threedselector/threedselector/utils/json-parser.utils.js +188 -0
- package/esm2015/app/plugins/threedselector/threedselector/utils/scene-3d.utils.js +159 -0
- package/esm2015/app/plugins/threedselector/threedselector.module.js +129 -0
- package/esm2015/app/plugins/toolbar/download-dialog/download-dialog.component.js +33 -0
- package/esm2015/app/plugins/toolbar/draw-dialog/draw-dialog.component.js +279 -0
- package/esm2015/app/plugins/toolbar/edit-preset-dialog/edit-preset-dialog.component.js +22 -0
- package/esm2015/app/plugins/toolbar/landing-screen-modal/landing-screen-modal.component.js +123 -0
- package/esm2015/app/plugins/toolbar/load-from-cloud-dialog/load-from-cloud-dialog.component.js +140 -0
- package/esm2015/app/plugins/toolbar/open-dialog/open-dialog.component.js +83 -0
- package/esm2015/app/plugins/toolbar/pdf-crop-dialog/pdf-crop-dialog.component.js +92 -0
- package/esm2015/app/plugins/toolbar/save-dialog/save-dialog.component.js +146 -0
- package/esm2015/app/plugins/toolbar/saved-dialog/saved-dialog.component.js +66 -0
- package/esm2015/app/plugins/toolbar/toolbar/limited-mode-message-component/limited-mode-message.component.js +26 -0
- package/esm2015/app/plugins/toolbar/toolbar/toolbar.component.js +676 -0
- package/esm2015/app/plugins/toolbar/toolbar.module.js +177 -0
- package/esm2015/app/service/dynamic-script.service.js +56 -0
- package/esm2015/app/service/google-tag-manager.service.js +89 -0
- package/esm2015/app/service/local-storage.service.js +93 -0
- package/esm2015/app/service/service-locator.service.js +4 -0
- package/esm2015/app/shared/base64-images.js +6 -0
- package/esm2015/app/shared/button-elevation/button-elevation.component.js +279 -0
- package/esm2015/app/shared/button-elevation/button-elevation.module.js +60 -0
- package/esm2015/app/shared/camera-settings-dialog/camera-settings-dialog.component.js +197 -0
- package/esm2015/app/shared/camera-settings-dialog/camera-settings-dialog.module.js +58 -0
- package/esm2015/app/shared/category-library/category-library.component.js +27 -0
- package/esm2015/app/shared/category-library/category-library.module.js +39 -0
- package/esm2015/app/shared/context-menu/context-menu.component.js +35 -0
- package/esm2015/app/shared/context-menu/context-menu.module.js +49 -0
- package/esm2015/app/shared/context-menu/item-context-menu/item-context-menu.component.js +93 -0
- package/esm2015/app/shared/dialog/dialog.component.js +119 -0
- package/esm2015/app/shared/dialog/dialog.module.js +45 -0
- package/esm2015/app/shared/dialog/enum/dialog-type.enum.js +8 -0
- package/esm2015/app/shared/dialog/interface/dialog-config.interface.js +2 -0
- package/esm2015/app/shared/dialog/service/dialog.service.js +21 -0
- package/esm2015/app/shared/error-dialog/error-dialog.component.js +24 -0
- package/esm2015/app/shared/error-dialog/error-dialog.module.js +30 -0
- package/esm2015/app/shared/export-dialog/export-dialog.component.js +68 -0
- package/esm2015/app/shared/export-dialog/export-dialog.module.js +35 -0
- package/esm2015/app/shared/info-dialog/info-dialog.component.js +54 -0
- package/esm2015/app/shared/info-dialog/info-dialog.module.js +37 -0
- package/esm2015/app/shared/loader/hd-loader.component.js +24 -0
- package/esm2015/app/shared/loader/hd-loader.module.js +33 -0
- package/esm2015/app/shared/loading-overlay/dialog/loading-overlay-dialog.component.js +26 -0
- package/esm2015/app/shared/loading-overlay/loading-overlay.component.js +55 -0
- package/esm2015/app/shared/loading-overlay/loading-overlay.module.js +42 -0
- package/esm2015/app/shared/model-dialog/model-dialog-furniture-list.component.js +325 -0
- package/esm2015/app/shared/model-dialog/model-dialog.component.js +104 -0
- package/esm2015/app/shared/model-dialog/model-dialog.module.js +64 -0
- package/esm2015/app/shared/progress-bar/progress-bar.component.js +39 -0
- package/esm2015/app/shared/progress-bar/progress-bar.module.js +33 -0
- package/esm2015/app/shared/register-dialog/register-dialog.component.js +112 -0
- package/esm2015/app/shared/screen-size-analysis/device-size-type.js +7 -0
- package/esm2015/app/shared/screen-size-analysis/navigator-type.enum.js +6 -0
- package/esm2015/app/shared/screen-size-analysis/screen-size-analysis.service.js +93 -0
- package/esm2015/app/shared/screen-size-analysis/screen-size-config.js +7 -0
- package/esm2015/app/shared/screen-size-analysis/screen-size-info.js +2 -0
- package/esm2015/app/shared/slider-input/slider-input.component.js +35 -0
- package/esm2015/app/shared/slider-input/slider-input.module.js +46 -0
- package/esm2015/app/shared/toolbar-icon/toolbar-icon.component.js +95 -0
- package/esm2015/app/shared/toolbar-icon/toolbar-icon.module.js +38 -0
- package/esm2015/app/shared/zoom-controls/zoom-controls.component.js +47 -0
- package/esm2015/app/shared/zoom-controls/zoom-controls.module.js +34 -0
- package/esm2015/colijnit-homedecorator.js +5 -0
- package/esm2015/environments/environment.js +17 -0
- package/esm2015/public_api.js +4 -0
- package/fesm2015/colijnit-homedecorator.js +45086 -0
- package/fesm2015/colijnit-homedecorator.js.map +1 -0
- package/homedecorator-globals.scss +361 -0
- package/package.json +48 -0
- package/palette.scss +32 -0
- package/public_api.d.ts +3 -0
- package/styles.scss +377 -0
|
@@ -0,0 +1,2381 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { BoxGeometry, BufferAttribute, BufferGeometry, Color, DoubleSide, Matrix4, Mesh, MeshBasicMaterial, MeshPhysicalMaterial, Path, Quaternion, Shape, ShapeGeometry, SRGBColorSpace, Vector2, Vector3 } from 'three';
|
|
11
|
+
import * as THREE from 'three';
|
|
12
|
+
import { sameTextures } from '../../../core/model/texture';
|
|
13
|
+
import { Item } from './item';
|
|
14
|
+
import { Utils } from '../core/utils';
|
|
15
|
+
import { defaultEdgeColor, defaultWallColor } from '../../room-planner/components/floorplanner/const/defaults';
|
|
16
|
+
import { ThreeMesh } from './three-mesh';
|
|
17
|
+
import { isNill } from '../../../core/utils/function/is-nill.function';
|
|
18
|
+
import { TextureType } from '../../../core/model/texture-type';
|
|
19
|
+
import { MaterialUtils } from '../../../core/utils/material.utils';
|
|
20
|
+
import { ItemType } from './item-type';
|
|
21
|
+
import * as Geometry from '../model/geometry';
|
|
22
|
+
import { ItemGroup } from './item-group';
|
|
23
|
+
/**
|
|
24
|
+
* A Wall is the basic element to create Rooms.
|
|
25
|
+
*
|
|
26
|
+
* Walls consists of two half edges.
|
|
27
|
+
*/
|
|
28
|
+
export class Wall {
|
|
29
|
+
/**
|
|
30
|
+
* Constructs a new wall.
|
|
31
|
+
* @param start Start corner.
|
|
32
|
+
* @param end End corner.
|
|
33
|
+
*/
|
|
34
|
+
constructor(start, end) {
|
|
35
|
+
this.start = start;
|
|
36
|
+
this.end = end;
|
|
37
|
+
/** Front is the plane from start to end. */
|
|
38
|
+
this.frontEdge = null;
|
|
39
|
+
/** Back is the plane from end to start. */
|
|
40
|
+
this.backEdge = null;
|
|
41
|
+
/** */
|
|
42
|
+
this.orphan = false;
|
|
43
|
+
/** Items attached to this wall */
|
|
44
|
+
this.items = [];
|
|
45
|
+
this.itemsChanged = false;
|
|
46
|
+
/** */
|
|
47
|
+
this.onItems = [];
|
|
48
|
+
/** The front-side color. */
|
|
49
|
+
this.frontColor = defaultWallColor;
|
|
50
|
+
/** The back-side color. */
|
|
51
|
+
this.backColor = defaultWallColor;
|
|
52
|
+
this.id = this.getUuid();
|
|
53
|
+
this.start.attachStart(this);
|
|
54
|
+
this.end.attachEnd(this);
|
|
55
|
+
}
|
|
56
|
+
set height(value) {
|
|
57
|
+
this._height = value;
|
|
58
|
+
if (this.frontEdge) {
|
|
59
|
+
this.frontEdge.height = this._height;
|
|
60
|
+
}
|
|
61
|
+
if (this.backEdge) {
|
|
62
|
+
this.backEdge.height = this._height;
|
|
63
|
+
}
|
|
64
|
+
this.items.forEach((item) => item.reposition());
|
|
65
|
+
this.onItems.forEach((item) => item.reposition());
|
|
66
|
+
}
|
|
67
|
+
get height() {
|
|
68
|
+
return this._height;
|
|
69
|
+
}
|
|
70
|
+
getUuid() {
|
|
71
|
+
return [this.start.id, this.end.id].join();
|
|
72
|
+
}
|
|
73
|
+
showHideWall(show) {
|
|
74
|
+
if (this.frontEdge) {
|
|
75
|
+
this.frontEdge.showHideEdge(show);
|
|
76
|
+
}
|
|
77
|
+
if (this.backEdge) {
|
|
78
|
+
this.backEdge.showHideEdge(show);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
resetFrontBack() {
|
|
82
|
+
if (this.frontEdge) {
|
|
83
|
+
this.frontEdge.disposePlane();
|
|
84
|
+
}
|
|
85
|
+
if (this.backEdge) {
|
|
86
|
+
this.backEdge.disposePlane();
|
|
87
|
+
}
|
|
88
|
+
this.frontEdge = null;
|
|
89
|
+
this.backEdge = null;
|
|
90
|
+
this.orphan = false;
|
|
91
|
+
}
|
|
92
|
+
move(x, y) {
|
|
93
|
+
if (!this.amountWallMoved) {
|
|
94
|
+
this.amountWallMoved = new Vector2();
|
|
95
|
+
}
|
|
96
|
+
const diffX = this.end.x - this.start.x;
|
|
97
|
+
const diffY = this.end.y - this.start.y;
|
|
98
|
+
const prevStartX = this.start.x;
|
|
99
|
+
const prevStartY = this.start.y;
|
|
100
|
+
this.start.move(x, y);
|
|
101
|
+
this.end.move(x + diffX, y + diffY);
|
|
102
|
+
this.amountWallMoved.add(new Vector2(this.start.x - prevStartX, this.start.y - prevStartY));
|
|
103
|
+
}
|
|
104
|
+
relativeMove(dx, dy) {
|
|
105
|
+
this.start.relativeMove(dx, dy);
|
|
106
|
+
this.end.relativeMove(dx, dy);
|
|
107
|
+
}
|
|
108
|
+
fireRedraw() {
|
|
109
|
+
if (this.frontEdge) {
|
|
110
|
+
this.frontEdge.redraw();
|
|
111
|
+
}
|
|
112
|
+
if (this.backEdge) {
|
|
113
|
+
this.backEdge.redraw();
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
getStart() {
|
|
117
|
+
return this.start;
|
|
118
|
+
}
|
|
119
|
+
getEnd() {
|
|
120
|
+
return this.end;
|
|
121
|
+
}
|
|
122
|
+
getStartX() {
|
|
123
|
+
return this.start.getX();
|
|
124
|
+
}
|
|
125
|
+
getEndX() {
|
|
126
|
+
return this.end.getX();
|
|
127
|
+
}
|
|
128
|
+
getStartY() {
|
|
129
|
+
return this.start.getY();
|
|
130
|
+
}
|
|
131
|
+
getEndY() {
|
|
132
|
+
return this.end.getY();
|
|
133
|
+
}
|
|
134
|
+
remove() {
|
|
135
|
+
this.start.detachWall(this);
|
|
136
|
+
this.end.detachWall(this);
|
|
137
|
+
this.frontTexture = undefined;
|
|
138
|
+
this.backTexture = undefined;
|
|
139
|
+
}
|
|
140
|
+
setStart(corner) {
|
|
141
|
+
this.start.detachWall(this);
|
|
142
|
+
corner.attachStart(this);
|
|
143
|
+
this.start = corner;
|
|
144
|
+
}
|
|
145
|
+
setEnd(corner) {
|
|
146
|
+
this.end.detachWall(this);
|
|
147
|
+
corner.attachEnd(this);
|
|
148
|
+
this.end = corner;
|
|
149
|
+
}
|
|
150
|
+
distanceFrom(x, y) {
|
|
151
|
+
return Utils.pointDistanceFromLine(x, y, this.getStartX(), this.getStartY(), this.getEndX(), this.getEndY());
|
|
152
|
+
}
|
|
153
|
+
closestPointTo(x, y) {
|
|
154
|
+
return Utils.closestPointOnLine(x, y, this.getStartX(), this.getStartY(), this.getEndX(), this.getEndY());
|
|
155
|
+
}
|
|
156
|
+
isToOrFrom(x, y) {
|
|
157
|
+
return (this.getStartX() === x && this.getStartY() === y) ||
|
|
158
|
+
(this.getEndX() === x && this.getEndY() === y);
|
|
159
|
+
}
|
|
160
|
+
/** Return the corner opposite of the one provided.
|
|
161
|
+
* @param corner The given corner.
|
|
162
|
+
* @returns The opposite corner.
|
|
163
|
+
*/
|
|
164
|
+
_oppositeCorner(corner) {
|
|
165
|
+
if (this.start === corner) {
|
|
166
|
+
return this.end;
|
|
167
|
+
}
|
|
168
|
+
else if (this.end === corner) {
|
|
169
|
+
return this.start;
|
|
170
|
+
}
|
|
171
|
+
else {
|
|
172
|
+
console.log('Wall does not connect to corner');
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
get length() {
|
|
176
|
+
return Utils.distance(this.getStartX(), this.getStartY(), this.getEndX(), this.getEndY());
|
|
177
|
+
}
|
|
178
|
+
get edgesLengths() {
|
|
179
|
+
const lengths = [];
|
|
180
|
+
if (this.frontEdge) {
|
|
181
|
+
lengths.push(this.frontEdge.interiorDistance());
|
|
182
|
+
}
|
|
183
|
+
if (this.backEdge) {
|
|
184
|
+
lengths.push(this.backEdge.interiorDistance());
|
|
185
|
+
}
|
|
186
|
+
return lengths;
|
|
187
|
+
}
|
|
188
|
+
updateInWallItems() {
|
|
189
|
+
this.items.filter(item => item instanceof InWallItem).forEach((item) => item.onWallUpdated(this));
|
|
190
|
+
}
|
|
191
|
+
updateWallItems() {
|
|
192
|
+
this.items.filter(item => item instanceof WallItem).forEach((item) => item.onWallMoved(this));
|
|
193
|
+
this.onItems.filter(item => item instanceof WallItem || item instanceof WallItemGroup).forEach((item) => item.onWallMoved(this));
|
|
194
|
+
this.amountWallMoved = undefined;
|
|
195
|
+
}
|
|
196
|
+
getItems() {
|
|
197
|
+
return this.items;
|
|
198
|
+
}
|
|
199
|
+
getWallItems() {
|
|
200
|
+
return this.items.filter(item => item instanceof WallItem);
|
|
201
|
+
}
|
|
202
|
+
get side() {
|
|
203
|
+
if (this.frontEdge && this.backEdge) {
|
|
204
|
+
return THREE.DoubleSide;
|
|
205
|
+
}
|
|
206
|
+
else if (this.frontEdge) {
|
|
207
|
+
return THREE.FrontSide;
|
|
208
|
+
}
|
|
209
|
+
else if (this.backEdge) {
|
|
210
|
+
return THREE.BackSide;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
addItem(item) {
|
|
214
|
+
this.items.push(item);
|
|
215
|
+
this.itemsChanged = true;
|
|
216
|
+
}
|
|
217
|
+
removeItem(item) {
|
|
218
|
+
this.items = this.items.filter(i => i !== item);
|
|
219
|
+
this.itemsChanged = true;
|
|
220
|
+
}
|
|
221
|
+
addOnItem(item) {
|
|
222
|
+
this.onItems.push(item);
|
|
223
|
+
this.itemsChanged = true;
|
|
224
|
+
}
|
|
225
|
+
removeOnItem(item) {
|
|
226
|
+
this.onItems = this.onItems.filter(i => i !== item);
|
|
227
|
+
this.itemsChanged = true;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Corners are used to define Walls.
|
|
232
|
+
*/
|
|
233
|
+
export class Corner {
|
|
234
|
+
/** Constructs a corner.
|
|
235
|
+
* @param x X coordinate.
|
|
236
|
+
* @param y Y coordinate.
|
|
237
|
+
* @param id An optional unique id. If not set, created internally.
|
|
238
|
+
*/
|
|
239
|
+
constructor(x, y, id) {
|
|
240
|
+
this.x = x;
|
|
241
|
+
this.y = y;
|
|
242
|
+
this.id = id;
|
|
243
|
+
/** Array of start walls. */
|
|
244
|
+
this.wallStarts = [];
|
|
245
|
+
/** Array of end walls. */
|
|
246
|
+
this.wallEnds = [];
|
|
247
|
+
this.id = id || Utils.guid();
|
|
248
|
+
}
|
|
249
|
+
absorbWallsFrom(corner) {
|
|
250
|
+
for (let i = corner.wallStarts.length - 1; i >= 0; i--) {
|
|
251
|
+
corner.wallStarts[i].setStart(this);
|
|
252
|
+
}
|
|
253
|
+
for (let i = corner.wallEnds.length - 1; i >= 0; i--) {
|
|
254
|
+
corner.wallEnds[i].setEnd(this);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* @returns
|
|
259
|
+
* @deprecated
|
|
260
|
+
*/
|
|
261
|
+
getX() {
|
|
262
|
+
return this.x;
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* @returns
|
|
266
|
+
* @deprecated
|
|
267
|
+
*/
|
|
268
|
+
getY() {
|
|
269
|
+
return this.y;
|
|
270
|
+
}
|
|
271
|
+
/** Moves corner relatively to new position.
|
|
272
|
+
* @param dx The delta x.
|
|
273
|
+
* @param dy The delta y.
|
|
274
|
+
*/
|
|
275
|
+
relativeMove(dx, dy) {
|
|
276
|
+
this.move(this.x + dx, this.y + dy);
|
|
277
|
+
}
|
|
278
|
+
/** Removes all walls. */
|
|
279
|
+
removeAll() {
|
|
280
|
+
for (let i = 0; i < this.wallStarts.length; i++) {
|
|
281
|
+
this.wallStarts[i].remove();
|
|
282
|
+
}
|
|
283
|
+
for (let i = 0; i < this.wallEnds.length; i++) {
|
|
284
|
+
this.wallEnds[i].remove();
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
/** Moves corner to new position.
|
|
288
|
+
* @param newX The new x position.
|
|
289
|
+
* @param newY The new y position.
|
|
290
|
+
*/
|
|
291
|
+
move(newX, newY) {
|
|
292
|
+
this.x = newX;
|
|
293
|
+
this.y = newY;
|
|
294
|
+
}
|
|
295
|
+
/** Gets the adjacent corners.
|
|
296
|
+
* @returns Array of corners.
|
|
297
|
+
*/
|
|
298
|
+
adjacentCorners() {
|
|
299
|
+
const retArray = [];
|
|
300
|
+
for (let i = 0; i < this.wallStarts.length; i++) {
|
|
301
|
+
retArray.push(this.wallStarts[i].getEnd());
|
|
302
|
+
}
|
|
303
|
+
for (let i = 0; i < this.wallEnds.length; i++) {
|
|
304
|
+
retArray.push(this.wallEnds[i].getStart());
|
|
305
|
+
}
|
|
306
|
+
return retArray;
|
|
307
|
+
}
|
|
308
|
+
/** Checks if a wall is connected.
|
|
309
|
+
* @param wall A wall.
|
|
310
|
+
* @returns True in case of connection.
|
|
311
|
+
*/
|
|
312
|
+
isWallConnected(wall) {
|
|
313
|
+
for (let i = 0; i < this.wallStarts.length; i++) {
|
|
314
|
+
if (this.wallStarts[i] === wall) {
|
|
315
|
+
return true;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
for (let i = 0; i < this.wallEnds.length; i++) {
|
|
319
|
+
if (this.wallEnds[i] === wall) {
|
|
320
|
+
return true;
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
return false;
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
*
|
|
327
|
+
*/
|
|
328
|
+
distanceFrom(x, y) {
|
|
329
|
+
const distance = Utils.distance(x, y, this.x, this.y);
|
|
330
|
+
return distance;
|
|
331
|
+
}
|
|
332
|
+
/** Gets the distance from a wall.
|
|
333
|
+
* @param wall A wall.
|
|
334
|
+
* @returns The distance.
|
|
335
|
+
*/
|
|
336
|
+
distanceFromWall(wall) {
|
|
337
|
+
return wall.distanceFrom(this.x, this.y);
|
|
338
|
+
}
|
|
339
|
+
/** Gets the distance from a corner.
|
|
340
|
+
* @param corner A corner.
|
|
341
|
+
* @returns The distance.
|
|
342
|
+
*/
|
|
343
|
+
distanceFromCorner(corner) {
|
|
344
|
+
return this.distanceFrom(corner.x, corner.y);
|
|
345
|
+
}
|
|
346
|
+
/** Detaches a wall.
|
|
347
|
+
* @param wall A wall.
|
|
348
|
+
*/
|
|
349
|
+
detachWall(wall) {
|
|
350
|
+
Utils.removeValue(this.wallStarts, wall);
|
|
351
|
+
Utils.removeValue(this.wallEnds, wall);
|
|
352
|
+
}
|
|
353
|
+
/** Attaches a start wall.
|
|
354
|
+
* @param wall A wall.
|
|
355
|
+
*/
|
|
356
|
+
attachStart(wall) {
|
|
357
|
+
this.wallStarts.push(wall);
|
|
358
|
+
}
|
|
359
|
+
/** Attaches an end wall.
|
|
360
|
+
* @param wall A wall.
|
|
361
|
+
*/
|
|
362
|
+
attachEnd(wall) {
|
|
363
|
+
this.wallEnds.push(wall);
|
|
364
|
+
}
|
|
365
|
+
/** Get wall to corner.
|
|
366
|
+
* @param corner A corner.
|
|
367
|
+
* @return The associated wall or null.
|
|
368
|
+
*/
|
|
369
|
+
wallTo(corner) {
|
|
370
|
+
for (let i = 0; i < this.wallStarts.length; i++) {
|
|
371
|
+
if (this.wallStarts[i].getEnd() === corner) {
|
|
372
|
+
return this.wallStarts[i];
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
return null;
|
|
376
|
+
}
|
|
377
|
+
/** Get wall from corner.
|
|
378
|
+
* @param corner A corner.
|
|
379
|
+
* @return The associated wall or null.
|
|
380
|
+
*/
|
|
381
|
+
wallFrom(corner) {
|
|
382
|
+
for (let i = 0; i < this.wallEnds.length; i++) {
|
|
383
|
+
if (this.wallEnds[i].getStart() === corner) {
|
|
384
|
+
return this.wallEnds[i];
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
return null;
|
|
388
|
+
}
|
|
389
|
+
/** Get wall to or from corner.
|
|
390
|
+
* @param corner A corner.
|
|
391
|
+
* @return The associated wall or null.
|
|
392
|
+
*/
|
|
393
|
+
wallToOrFrom(corner) {
|
|
394
|
+
return this.wallTo(corner) || this.wallFrom(corner);
|
|
395
|
+
}
|
|
396
|
+
get startWalls() {
|
|
397
|
+
return this.wallStarts;
|
|
398
|
+
}
|
|
399
|
+
get endWalls() {
|
|
400
|
+
return this.wallEnds;
|
|
401
|
+
}
|
|
402
|
+
/** Ensure we do not have duplicate walls (i.e. same start and end points) */
|
|
403
|
+
removeDuplicateWalls() {
|
|
404
|
+
// delete the wall between these corners, if it exists
|
|
405
|
+
const wallEndpoints = {};
|
|
406
|
+
const wallStartpoints = {};
|
|
407
|
+
for (let i = this.wallStarts.length - 1; i >= 0; i--) {
|
|
408
|
+
if (this.wallStarts[i].getEnd() === this) {
|
|
409
|
+
// remove zero length wall
|
|
410
|
+
this.wallStarts[i].remove();
|
|
411
|
+
}
|
|
412
|
+
else if (this.wallStarts[i].getEnd().id in wallEndpoints) {
|
|
413
|
+
// remove duplicated wall
|
|
414
|
+
this.wallStarts[i].remove();
|
|
415
|
+
}
|
|
416
|
+
else {
|
|
417
|
+
wallEndpoints[this.wallStarts[i].getEnd().id] = true;
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
for (let i = this.wallEnds.length - 1; i >= 0; i--) {
|
|
421
|
+
if (this.wallEnds[i].getStart() === this) {
|
|
422
|
+
// removed zero length wall
|
|
423
|
+
this.wallEnds[i].remove();
|
|
424
|
+
}
|
|
425
|
+
else if (this.wallEnds[i].getStart().id in wallStartpoints) {
|
|
426
|
+
// removed duplicated wall
|
|
427
|
+
this.wallEnds[i].remove();
|
|
428
|
+
}
|
|
429
|
+
else {
|
|
430
|
+
wallStartpoints[this.wallEnds[i].getStart().id] = true;
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
// find and remove cycle ~ more than a single wall between 2 corners
|
|
434
|
+
for (const outWall of this.wallStarts) {
|
|
435
|
+
for (const inWall of this.wallEnds) {
|
|
436
|
+
if (outWall.getEnd() === inWall.getStart()) {
|
|
437
|
+
outWall.remove();
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
/**
|
|
444
|
+
* Half Edges are created by Room.
|
|
445
|
+
*
|
|
446
|
+
* Once rooms have been identified, Half Edges are created for each interior wall.
|
|
447
|
+
*
|
|
448
|
+
* A wall can have two half edges if it is visible from both sides.
|
|
449
|
+
*/
|
|
450
|
+
export class HalfEdge {
|
|
451
|
+
/**
|
|
452
|
+
* Constructs a half edge.
|
|
453
|
+
* @param room The associated room.
|
|
454
|
+
* @param wall The corresponding wall.
|
|
455
|
+
* @param front True if front side.
|
|
456
|
+
*/
|
|
457
|
+
constructor(room, wall, front) {
|
|
458
|
+
this.room = room;
|
|
459
|
+
this.wall = wall;
|
|
460
|
+
this.front = front;
|
|
461
|
+
/** used for intersection testing... not convinced this belongs here */
|
|
462
|
+
this.plane = null;
|
|
463
|
+
/** transform from world coords to wall planes (z=0) */
|
|
464
|
+
this.interiorTransform = new Matrix4();
|
|
465
|
+
/** transform from world coords to wall planes (z=0) */
|
|
466
|
+
this.invInteriorTransform = new Matrix4();
|
|
467
|
+
/** transform from world coords to wall planes (z=0) */
|
|
468
|
+
this.exteriorTransform = new Matrix4();
|
|
469
|
+
/** transform from world coords to wall planes (z=0) */
|
|
470
|
+
this.invExteriorTransform = new Matrix4();
|
|
471
|
+
/** */
|
|
472
|
+
this.edges = [];
|
|
473
|
+
this.front = front || false;
|
|
474
|
+
this.offset = wall.thickness / 2.0;
|
|
475
|
+
this.height = wall.height;
|
|
476
|
+
if (this.front) {
|
|
477
|
+
this.wall.frontEdge = this;
|
|
478
|
+
}
|
|
479
|
+
else {
|
|
480
|
+
this.wall.backEdge = this;
|
|
481
|
+
}
|
|
482
|
+
this.wall.updateInWallItems();
|
|
483
|
+
}
|
|
484
|
+
/** When height of walls are modified, plane should be recreated */
|
|
485
|
+
set height(value) {
|
|
486
|
+
this._height = value;
|
|
487
|
+
this.disposePlane();
|
|
488
|
+
this.generatePlane();
|
|
489
|
+
}
|
|
490
|
+
get height() {
|
|
491
|
+
return this._height;
|
|
492
|
+
}
|
|
493
|
+
showHideEdge(show) {
|
|
494
|
+
this.edges.forEach(e => e.showHideEdge(show));
|
|
495
|
+
}
|
|
496
|
+
updateVisibility(cameraPosition) {
|
|
497
|
+
let visibilityChanged = null;
|
|
498
|
+
this.edges.forEach(e => {
|
|
499
|
+
const edgeVisibilityChanged = e.updateVisibility(cameraPosition);
|
|
500
|
+
if (edgeVisibilityChanged !== null) {
|
|
501
|
+
visibilityChanged = edgeVisibilityChanged;
|
|
502
|
+
}
|
|
503
|
+
});
|
|
504
|
+
return visibilityChanged;
|
|
505
|
+
}
|
|
506
|
+
updateVisiblity(visibility) {
|
|
507
|
+
this.edges.forEach(e => {
|
|
508
|
+
e.visible = visibility;
|
|
509
|
+
e.updateObjectVisibility();
|
|
510
|
+
e.setAllPlanesVisible();
|
|
511
|
+
});
|
|
512
|
+
}
|
|
513
|
+
redraw() {
|
|
514
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
515
|
+
// this.edges.forEach(e => e.redraw());
|
|
516
|
+
for (let i = 0; i < this.edges.length; i++) {
|
|
517
|
+
yield this.edges[i].redraw();
|
|
518
|
+
}
|
|
519
|
+
});
|
|
520
|
+
}
|
|
521
|
+
/**
|
|
522
|
+
*
|
|
523
|
+
*/
|
|
524
|
+
getTexture() {
|
|
525
|
+
if (this.front) {
|
|
526
|
+
return this.wall.frontTexture;
|
|
527
|
+
}
|
|
528
|
+
else {
|
|
529
|
+
return this.wall.backTexture;
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
getColor() {
|
|
533
|
+
if (this.front) {
|
|
534
|
+
return this.wall.frontColor;
|
|
535
|
+
}
|
|
536
|
+
else {
|
|
537
|
+
return this.wall.backColor;
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
/**
|
|
541
|
+
*
|
|
542
|
+
*/
|
|
543
|
+
setTexture(texture) {
|
|
544
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
545
|
+
if (texture) {
|
|
546
|
+
texture.roughness = !isNill(texture.roughness) ? texture.roughness : 0.8;
|
|
547
|
+
}
|
|
548
|
+
if (this.front) {
|
|
549
|
+
this.wall.frontTexture = texture;
|
|
550
|
+
this.wall.frontColor = defaultWallColor;
|
|
551
|
+
}
|
|
552
|
+
else {
|
|
553
|
+
this.wall.backTexture = texture;
|
|
554
|
+
this.wall.backColor = defaultWallColor;
|
|
555
|
+
}
|
|
556
|
+
// this.redrawCallbacks.fire();
|
|
557
|
+
yield this.redraw();
|
|
558
|
+
});
|
|
559
|
+
}
|
|
560
|
+
setColor(value) {
|
|
561
|
+
if (this.front) {
|
|
562
|
+
this.wall.frontTexture = null;
|
|
563
|
+
this.wall.frontColor = value;
|
|
564
|
+
}
|
|
565
|
+
else {
|
|
566
|
+
this.wall.backTexture = null;
|
|
567
|
+
this.wall.backColor = value;
|
|
568
|
+
}
|
|
569
|
+
// this.redrawCallbacks.fire();
|
|
570
|
+
this.redraw();
|
|
571
|
+
}
|
|
572
|
+
/**
|
|
573
|
+
* this feels hacky, but need wall items
|
|
574
|
+
*/
|
|
575
|
+
generatePlane() {
|
|
576
|
+
function transformCorner(corner) {
|
|
577
|
+
return new Vector3(corner.x, 0, corner.y);
|
|
578
|
+
}
|
|
579
|
+
this.offset = this.wall.thickness / 2.0;
|
|
580
|
+
this._height = this.wall.height;
|
|
581
|
+
const v1 = transformCorner(this.interiorStart());
|
|
582
|
+
const v2 = transformCorner(this.interiorEnd());
|
|
583
|
+
const v3 = v2.clone();
|
|
584
|
+
v3.y = this.wall.height;
|
|
585
|
+
const v4 = v1.clone();
|
|
586
|
+
v4.y = this.wall.height;
|
|
587
|
+
const geometry = new BufferGeometry().setFromPoints([v1, v2, v3, v4]);
|
|
588
|
+
const faceVertexIndexArray = new Uint16Array([0, 1, 2, 0, 2, 3]);
|
|
589
|
+
const faceBufferAttribute = new BufferAttribute(faceVertexIndexArray, 1);
|
|
590
|
+
geometry.setIndex(faceBufferAttribute);
|
|
591
|
+
geometry.computeVertexNormals();
|
|
592
|
+
geometry.computeBoundingBox();
|
|
593
|
+
this.plane = new ThreeMesh(geometry, new MeshPhysicalMaterial(null));
|
|
594
|
+
this.plane.name = `half-edge-plane-${this.front ? 'front' : 'back'}`;
|
|
595
|
+
this.plane.castShadow = true;
|
|
596
|
+
Utils.setPlaneVisibility(this.plane, true);
|
|
597
|
+
this.plane.userData.edge = this;
|
|
598
|
+
this.computeTransforms(this.interiorTransform, this.invInteriorTransform, this.interiorStart(), this.interiorEnd());
|
|
599
|
+
this.computeTransforms(this.exteriorTransform, this.invExteriorTransform, this.exteriorStart(), this.exteriorEnd());
|
|
600
|
+
}
|
|
601
|
+
disposePlane() {
|
|
602
|
+
if (this.plane) {
|
|
603
|
+
Utils.DisposeObject(this.plane);
|
|
604
|
+
this.plane = null;
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
interiorDistance() {
|
|
608
|
+
const start = this.interiorStart();
|
|
609
|
+
const end = this.interiorEnd();
|
|
610
|
+
return Utils.distance(start.x, start.y, end.x, end.y);
|
|
611
|
+
}
|
|
612
|
+
computeTransforms(transform, invTransform, start, end) {
|
|
613
|
+
const v1 = start;
|
|
614
|
+
const v2 = end;
|
|
615
|
+
const angle = Utils.angle(1, 0, v2.x - v1.x, v2.y - v1.y);
|
|
616
|
+
const tt = new Matrix4();
|
|
617
|
+
tt.makeTranslation(-v1.x, 0, -v1.y);
|
|
618
|
+
const tr = new Matrix4();
|
|
619
|
+
tr.makeRotationY(-angle);
|
|
620
|
+
transform.multiplyMatrices(tr, tt);
|
|
621
|
+
invTransform.copy(transform).invert();
|
|
622
|
+
}
|
|
623
|
+
/** Gets the distance from specified point.
|
|
624
|
+
* @param x X coordinate of the point.
|
|
625
|
+
* @param y Y coordinate of the point.
|
|
626
|
+
* @returns The distance.
|
|
627
|
+
*/
|
|
628
|
+
distanceTo(x, y) {
|
|
629
|
+
// x, y, x1, y1, x2, y2
|
|
630
|
+
return Utils.pointDistanceFromLine(x, y, this.interiorStart().x, this.interiorStart().y, this.interiorEnd().x, this.interiorEnd().y);
|
|
631
|
+
}
|
|
632
|
+
getStart() {
|
|
633
|
+
if (this.front) {
|
|
634
|
+
return this.wall.getStart();
|
|
635
|
+
}
|
|
636
|
+
else {
|
|
637
|
+
return this.wall.getEnd();
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
getEnd() {
|
|
641
|
+
if (this.front) {
|
|
642
|
+
return this.wall.getEnd();
|
|
643
|
+
}
|
|
644
|
+
else {
|
|
645
|
+
return this.wall.getStart();
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
getOppositeEdge() {
|
|
649
|
+
if (this.front) {
|
|
650
|
+
return this.wall.backEdge;
|
|
651
|
+
}
|
|
652
|
+
else {
|
|
653
|
+
return this.wall.frontEdge;
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
// these return an object with attributes x, y
|
|
657
|
+
interiorEnd() {
|
|
658
|
+
const vec = this.halfAngleVector(this, this.next);
|
|
659
|
+
return new Vector2(this.getEnd().x + vec.x, this.getEnd().y + vec.y);
|
|
660
|
+
}
|
|
661
|
+
interiorStart() {
|
|
662
|
+
const vec = this.halfAngleVector(this.prev, this);
|
|
663
|
+
return new Vector2(this.getStart().x + vec.x, this.getStart().y + vec.y);
|
|
664
|
+
}
|
|
665
|
+
interiorCenter() {
|
|
666
|
+
return new Vector2((this.interiorStart().x + this.interiorEnd().x) / 2.0, (this.interiorStart().y + this.interiorEnd().y) / 2.0);
|
|
667
|
+
}
|
|
668
|
+
exteriorEnd() {
|
|
669
|
+
const vec = this.halfAngleVector(this, this.next);
|
|
670
|
+
return new Vector2(this.getEnd().x - vec.x, this.getEnd().y - vec.y);
|
|
671
|
+
}
|
|
672
|
+
exteriorStart() {
|
|
673
|
+
const vec = this.halfAngleVector(this.prev, this);
|
|
674
|
+
return new Vector2(this.getStart().x - vec.x, this.getStart().y - vec.y);
|
|
675
|
+
}
|
|
676
|
+
/** Get the corners of the half edge.
|
|
677
|
+
* @returns An array of x,y pairs.
|
|
678
|
+
*/
|
|
679
|
+
corners() {
|
|
680
|
+
return [this.interiorStart(), this.interiorEnd(),
|
|
681
|
+
this.exteriorEnd(), this.exteriorStart()];
|
|
682
|
+
}
|
|
683
|
+
/**
|
|
684
|
+
* Gets CCW angle from v1 to v2
|
|
685
|
+
*/
|
|
686
|
+
halfAngleVector(v1, v2) {
|
|
687
|
+
// make the best of things if we dont have prev or next
|
|
688
|
+
let v1startX;
|
|
689
|
+
let v1startY;
|
|
690
|
+
let v1endX;
|
|
691
|
+
let v1endY;
|
|
692
|
+
let v2startX;
|
|
693
|
+
let v2startY;
|
|
694
|
+
let v2endX;
|
|
695
|
+
let v2endY;
|
|
696
|
+
if (!v1) {
|
|
697
|
+
v1startX = v2.getStart().x - (v2.getEnd().x - v2.getStart().x);
|
|
698
|
+
v1startY = v2.getStart().y - (v2.getEnd().y - v2.getStart().y);
|
|
699
|
+
v1endX = v2.getStart().x;
|
|
700
|
+
v1endY = v2.getStart().y;
|
|
701
|
+
}
|
|
702
|
+
else {
|
|
703
|
+
v1startX = v1.getStart().x;
|
|
704
|
+
v1startY = v1.getStart().y;
|
|
705
|
+
v1endX = v1.getEnd().x;
|
|
706
|
+
v1endY = v1.getEnd().y;
|
|
707
|
+
}
|
|
708
|
+
if (!v2) {
|
|
709
|
+
v2startX = v1.getEnd().x;
|
|
710
|
+
v2startY = v1.getEnd().y;
|
|
711
|
+
v2endX = v1.getEnd().x + (v1.getEnd().x - v1.getStart().x);
|
|
712
|
+
v2endY = v1.getEnd().y + (v1.getEnd().y - v1.getStart().y);
|
|
713
|
+
}
|
|
714
|
+
else {
|
|
715
|
+
v2startX = v2.getStart().x;
|
|
716
|
+
v2startY = v2.getStart().y;
|
|
717
|
+
v2endX = v2.getEnd().x;
|
|
718
|
+
v2endY = v2.getEnd().y;
|
|
719
|
+
}
|
|
720
|
+
// CCW angle between edges
|
|
721
|
+
const theta = Utils.angle2pi(v1startX - v1endX, v1startY - v1endY, v2endX - v1endX, v2endY - v1endY);
|
|
722
|
+
// cosine and sine of half angle
|
|
723
|
+
const cs = Math.cos(theta / 2.0);
|
|
724
|
+
const sn = Math.sin(theta / 2.0);
|
|
725
|
+
// rotate v2
|
|
726
|
+
const v2dx = v2endX - v2startX;
|
|
727
|
+
const v2dy = v2endY - v2startY;
|
|
728
|
+
const vx = v2dx * cs - v2dy * sn;
|
|
729
|
+
const vy = v2dx * sn + v2dy * cs;
|
|
730
|
+
// normalize
|
|
731
|
+
const mag = Utils.distance(0, 0, vx, vy);
|
|
732
|
+
const desiredMag = (this.offset) / sn;
|
|
733
|
+
const scalar = desiredMag / mag;
|
|
734
|
+
return new Vector2(vx * scalar, vy * scalar);
|
|
735
|
+
}
|
|
736
|
+
get invExteriorQuaternion() {
|
|
737
|
+
const quaternion = new Quaternion();
|
|
738
|
+
quaternion.setFromRotationMatrix(this.invExteriorTransform);
|
|
739
|
+
return quaternion;
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
export class Edge {
|
|
743
|
+
constructor(_halfEdge) {
|
|
744
|
+
this._halfEdge = _halfEdge;
|
|
745
|
+
this._fillerColor = new Color(0xdddddd);
|
|
746
|
+
this._planes = {
|
|
747
|
+
exterior: null,
|
|
748
|
+
interior: null,
|
|
749
|
+
sides: null,
|
|
750
|
+
bottom: null,
|
|
751
|
+
top: null
|
|
752
|
+
};
|
|
753
|
+
this._last = {
|
|
754
|
+
color: null,
|
|
755
|
+
texture: null,
|
|
756
|
+
fillerMaterial: null,
|
|
757
|
+
wallMaterial: null,
|
|
758
|
+
height: null
|
|
759
|
+
};
|
|
760
|
+
if (_halfEdge) {
|
|
761
|
+
this._wall = _halfEdge.wall;
|
|
762
|
+
this._front = _halfEdge.front;
|
|
763
|
+
// this.updatePlanes();
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
showHideEdge(show) {
|
|
767
|
+
this._planeList().forEach(p => p.visible = show);
|
|
768
|
+
}
|
|
769
|
+
_planeList() {
|
|
770
|
+
return (this._planes.sides || []).concat([
|
|
771
|
+
this._planes.top,
|
|
772
|
+
this._planes.bottom,
|
|
773
|
+
this._planes.interior,
|
|
774
|
+
this._planes.exterior
|
|
775
|
+
]).filter(x => x);
|
|
776
|
+
}
|
|
777
|
+
getPlanes() {
|
|
778
|
+
return this._planeList();
|
|
779
|
+
}
|
|
780
|
+
getTopSideFillers() {
|
|
781
|
+
return this._planes.sides.concat([this._planes.top]);
|
|
782
|
+
}
|
|
783
|
+
init() {
|
|
784
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
785
|
+
// this.halfEdge.redrawCallbacks.add(this.redraw);
|
|
786
|
+
// halfEdge.itemAddedCallbacks.add(updateObjectVisibility);
|
|
787
|
+
// controls.cameraMovedCallbacks.add(updateVisibility);
|
|
788
|
+
yield this.updatePlanes();
|
|
789
|
+
// addToScene();
|
|
790
|
+
});
|
|
791
|
+
}
|
|
792
|
+
redraw() {
|
|
793
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
794
|
+
yield this.updatePlanes();
|
|
795
|
+
});
|
|
796
|
+
}
|
|
797
|
+
// private removeFromScene() {
|
|
798
|
+
// this.planeList().forEach((plane) => {
|
|
799
|
+
// scene.remove(plane);
|
|
800
|
+
// Utils.disposeObject(plane);
|
|
801
|
+
// });
|
|
802
|
+
// Object.keys(planes).forEach((key: string) => planes[key] = null);
|
|
803
|
+
// Object.keys(last).forEach((key: string) => last[key] = null);
|
|
804
|
+
// }
|
|
805
|
+
// private addToScene() {
|
|
806
|
+
// planeList().forEach((plane) => {
|
|
807
|
+
// scene.add(plane);
|
|
808
|
+
// });
|
|
809
|
+
// updateVisibility();
|
|
810
|
+
// }
|
|
811
|
+
updateVisibility(cameraPosition) {
|
|
812
|
+
// finds the normal from the specified halfEdge
|
|
813
|
+
const start = this._halfEdge.interiorStart();
|
|
814
|
+
const end = this._halfEdge.interiorEnd();
|
|
815
|
+
const x = end.x - start.x;
|
|
816
|
+
const y = end.y - start.y;
|
|
817
|
+
// rotate 90 degrees CCW
|
|
818
|
+
const normal = new Vector3(-y, 0, x);
|
|
819
|
+
normal.normalize();
|
|
820
|
+
// setup camera
|
|
821
|
+
const position = cameraPosition.clone();
|
|
822
|
+
const focus = new Vector3((start.x + end.x) / 2.0, 0, (start.y + end.y) / 2.0);
|
|
823
|
+
const direction = position.sub(focus).normalize();
|
|
824
|
+
// find dot
|
|
825
|
+
const dot = normal.dot(direction);
|
|
826
|
+
// update visible
|
|
827
|
+
const newVisible = (dot >= 0);
|
|
828
|
+
// show or hide plans
|
|
829
|
+
this._planeList().forEach((plane) => Utils.setPlaneVisibility(plane, newVisible));
|
|
830
|
+
if (newVisible !== this.visible) {
|
|
831
|
+
this.visible = newVisible;
|
|
832
|
+
this.updateObjectVisibility();
|
|
833
|
+
return newVisible;
|
|
834
|
+
}
|
|
835
|
+
else {
|
|
836
|
+
return null;
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
updateObjectVisibility() {
|
|
840
|
+
this._wall.items.forEach((item) => {
|
|
841
|
+
item.updateEdgeVisibility(this);
|
|
842
|
+
});
|
|
843
|
+
this._wall.onItems.forEach((item) => {
|
|
844
|
+
item.updateEdgeVisibility(this);
|
|
845
|
+
});
|
|
846
|
+
}
|
|
847
|
+
setAllPlanesVisible() {
|
|
848
|
+
this._planeList().forEach((plane) => Utils.setPlaneVisibility(plane, true));
|
|
849
|
+
}
|
|
850
|
+
_addMaterialMap(material, texture) {
|
|
851
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
852
|
+
const dimensions = new THREE.Vector2(this._halfEdge.interiorDistance(), this._wall.height - this._wall.thickness);
|
|
853
|
+
texture.dimensions = dimensions.multiplyScalar(100);
|
|
854
|
+
switch (texture.type) {
|
|
855
|
+
case TextureType.Image:
|
|
856
|
+
material.map = yield MaterialUtils.FromImage(texture);
|
|
857
|
+
material.map.colorSpace = SRGBColorSpace;
|
|
858
|
+
material.needsUpdate = true;
|
|
859
|
+
break;
|
|
860
|
+
case TextureType.CustomPattern:
|
|
861
|
+
material.map = yield MaterialUtils.CustomTileMapTexture(texture, dimensions);
|
|
862
|
+
material.map.colorSpace = SRGBColorSpace;
|
|
863
|
+
material.needsUpdate = true;
|
|
864
|
+
break;
|
|
865
|
+
case TextureType.Basic:
|
|
866
|
+
material.map = yield MaterialUtils.FromUrl(texture.url, texture.stretch, texture.tileSize, null, null, texture.dimensions, texture.tileRotation);
|
|
867
|
+
material.map.colorSpace = SRGBColorSpace;
|
|
868
|
+
material.needsUpdate = true;
|
|
869
|
+
break;
|
|
870
|
+
case TextureType.PBR:
|
|
871
|
+
material = material;
|
|
872
|
+
if (texture.materializeUrl) {
|
|
873
|
+
yield MaterialUtils.loadMaterializeMaps(material, texture);
|
|
874
|
+
}
|
|
875
|
+
else {
|
|
876
|
+
material.map = yield MaterialUtils.FromUrl(texture.url, texture.stretch, texture.tileSize, texture.repeatX, texture.repeatY, texture.dimensions, texture.tileRotation);
|
|
877
|
+
material.map.colorSpace = SRGBColorSpace;
|
|
878
|
+
material.roughnessMap = texture.roughnessMap ? yield MaterialUtils.FromUrl(texture.roughnessMap, texture.stretch, texture.tileSize, texture.repeatX, texture.repeatY, texture.dimensions, texture.tileRotation) : null;
|
|
879
|
+
material.bumpMap = texture.bumpMap ? yield MaterialUtils.FromUrl(texture.bumpMap, texture.stretch, texture.tileSize, texture.repeatX, texture.repeatY, texture.dimensions, texture.tileRotation) : null;
|
|
880
|
+
material.normalMap = texture.normalMap ? yield MaterialUtils.FromUrl(texture.normalMap, texture.stretch, texture.tileSize, texture.repeatX, texture.repeatY, texture.dimensions, texture.tileRotation) : null;
|
|
881
|
+
material.metalnessMap = texture.metalnessMap ? yield MaterialUtils.FromUrl(texture.metalnessMap, texture.stretch, texture.tileSize, texture.repeatX, texture.repeatY, texture.dimensions, texture.tileRotation) : null;
|
|
882
|
+
material.aoMap = texture.aoMap ? yield MaterialUtils.FromUrl(texture.aoMap, texture.stretch, texture.tileSize, texture.repeatX, texture.repeatY, texture.dimensions, texture.tileRotation) : null;
|
|
883
|
+
material.needsUpdate = true;
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
});
|
|
887
|
+
}
|
|
888
|
+
_isValid(startEnd) {
|
|
889
|
+
return !startEnd.find(e => !isFinite(e.x) || !isFinite(e.y));
|
|
890
|
+
}
|
|
891
|
+
_updateFillerMaterial() {
|
|
892
|
+
if (this._fillerMaterial) {
|
|
893
|
+
return this._fillerMaterial;
|
|
894
|
+
}
|
|
895
|
+
const material = new MeshBasicMaterial({
|
|
896
|
+
color: this._fillerColor,
|
|
897
|
+
side: DoubleSide
|
|
898
|
+
});
|
|
899
|
+
return material;
|
|
900
|
+
}
|
|
901
|
+
_updateWallMaterial(texture, color = defaultEdgeColor) {
|
|
902
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
903
|
+
const isSameColor = color && this._last.color && color === this._last.color;
|
|
904
|
+
const isSameTexture = sameTextures(texture, this._last.texture);
|
|
905
|
+
if (isSameColor && isSameTexture) {
|
|
906
|
+
return this._wallMaterial;
|
|
907
|
+
}
|
|
908
|
+
if (!isSameColor) {
|
|
909
|
+
this._last.color = color;
|
|
910
|
+
}
|
|
911
|
+
if (!isSameTexture) {
|
|
912
|
+
this._last.texture = Object.assign({}, texture);
|
|
913
|
+
}
|
|
914
|
+
let material;
|
|
915
|
+
material = new THREE.MeshPhongMaterial({
|
|
916
|
+
color: color,
|
|
917
|
+
side: THREE.FrontSide
|
|
918
|
+
});
|
|
919
|
+
if (texture) {
|
|
920
|
+
material = new THREE.MeshStandardMaterial({
|
|
921
|
+
color: color,
|
|
922
|
+
side: THREE.FrontSide,
|
|
923
|
+
roughness: !isNill(texture.roughness) ? texture.roughness : 0.8,
|
|
924
|
+
metalness: !isNill(texture.metalness) ? texture.metalness : 0,
|
|
925
|
+
bumpScale: !isNill(texture.bumpScale) ? texture.bumpScale : 1
|
|
926
|
+
});
|
|
927
|
+
yield this._addMaterialMap(material, texture);
|
|
928
|
+
}
|
|
929
|
+
return material;
|
|
930
|
+
});
|
|
931
|
+
}
|
|
932
|
+
_equalLastVec2(plane, paramSuffix) {
|
|
933
|
+
const paramName = `${plane}${paramSuffix}`;
|
|
934
|
+
const getter = this._halfEdge[paramName]();
|
|
935
|
+
return this._last[paramName] &&
|
|
936
|
+
this._halfEdge[paramName] &&
|
|
937
|
+
this._last[paramName].x === getter.x &&
|
|
938
|
+
this._last[paramName].y === getter.y;
|
|
939
|
+
}
|
|
940
|
+
_copyLast(plane, params) {
|
|
941
|
+
params.forEach((param) => {
|
|
942
|
+
const paramName = param === 'InvTransform' ?
|
|
943
|
+
this._invTransformParam(plane) :
|
|
944
|
+
`${plane}${param}`;
|
|
945
|
+
const current = 'function' === typeof this._halfEdge[paramName] ?
|
|
946
|
+
this._halfEdge[paramName]() : this._halfEdge[paramName];
|
|
947
|
+
this._last[paramName] = current;
|
|
948
|
+
});
|
|
949
|
+
}
|
|
950
|
+
_transformParam(plane) {
|
|
951
|
+
return `${plane}Transform`;
|
|
952
|
+
}
|
|
953
|
+
_invTransformParam(plane) {
|
|
954
|
+
return `inv${plane.charAt(0).toUpperCase()}${plane.substr(1)}Transform`;
|
|
955
|
+
}
|
|
956
|
+
_updateMainPlane(plane, material) {
|
|
957
|
+
let updatePlane = this._planes[plane];
|
|
958
|
+
const geo = this._createGeometry(this._halfEdge[`${plane}Start`](), this._halfEdge[`${plane}End`](), this._halfEdge[this._transformParam(plane)], this._halfEdge[this._invTransformParam(plane)]);
|
|
959
|
+
if (!updatePlane) {
|
|
960
|
+
updatePlane = new ThreeMesh(geo, material);
|
|
961
|
+
updatePlane.name = 'edge';
|
|
962
|
+
updatePlane.userData.wall = this._wall;
|
|
963
|
+
updatePlane.castShadow = true;
|
|
964
|
+
updatePlane.receiveShadow = true;
|
|
965
|
+
}
|
|
966
|
+
else {
|
|
967
|
+
updatePlane.geometry = geo;
|
|
968
|
+
updatePlane.material = material;
|
|
969
|
+
updatePlane.material.needsUpdate = true;
|
|
970
|
+
} /* else {
|
|
971
|
+
updatePlane = this.makeWall(
|
|
972
|
+
this.halfEdge[`${plane}Start`](),
|
|
973
|
+
this.halfEdge[`${plane}End`](),
|
|
974
|
+
this.halfEdge[this.transformParam(plane)],
|
|
975
|
+
this.halfEdge[this.invTransformParam(plane)],
|
|
976
|
+
material
|
|
977
|
+
);
|
|
978
|
+
}*/
|
|
979
|
+
return updatePlane;
|
|
980
|
+
// const oldPlane = this.planes[plane];
|
|
981
|
+
// const newPlane = this.makeWall(
|
|
982
|
+
// this.halfEdge[`${plane}Start`](),
|
|
983
|
+
// this.halfEdge[`${plane}End`](),
|
|
984
|
+
// this.halfEdge[this.transformParam(plane)],
|
|
985
|
+
// this.halfEdge[this.invTransformParam(plane)],
|
|
986
|
+
// material
|
|
987
|
+
// );
|
|
988
|
+
// if (oldPlane) {
|
|
989
|
+
// // scene.remove(oldPlane);
|
|
990
|
+
// Utils.disposeObject(oldPlane);
|
|
991
|
+
// }
|
|
992
|
+
// // scene.add(newPlane);
|
|
993
|
+
// return newPlane;
|
|
994
|
+
}
|
|
995
|
+
_updateBottomPlane() {
|
|
996
|
+
const oldPlane = this._planes.bottom;
|
|
997
|
+
if (oldPlane &&
|
|
998
|
+
this._equalLastVec2('interior', 'Start') &&
|
|
999
|
+
this._equalLastVec2('interior', 'End') &&
|
|
1000
|
+
this._equalLastVec2('exterior', 'Start') &&
|
|
1001
|
+
this._equalLastVec2('exterior', 'End')) {
|
|
1002
|
+
return oldPlane;
|
|
1003
|
+
}
|
|
1004
|
+
const newPlane = this._buildFiller(0, this._fillerMaterial);
|
|
1005
|
+
if (oldPlane) {
|
|
1006
|
+
// Dispose function does not actually remove the object from the scene
|
|
1007
|
+
Utils.DisposeObject(oldPlane);
|
|
1008
|
+
oldPlane.visible = false;
|
|
1009
|
+
}
|
|
1010
|
+
// scene.add(newPlane);
|
|
1011
|
+
return newPlane;
|
|
1012
|
+
}
|
|
1013
|
+
_updateTopPlane() {
|
|
1014
|
+
const oldPlane = this._planes.top;
|
|
1015
|
+
if (oldPlane &&
|
|
1016
|
+
this._last.height === this._wall.height &&
|
|
1017
|
+
this._equalLastVec2('interior', 'Start') &&
|
|
1018
|
+
this._equalLastVec2('interior', 'End') &&
|
|
1019
|
+
this._equalLastVec2('exterior', 'Start') &&
|
|
1020
|
+
this._equalLastVec2('exterior', 'End')) {
|
|
1021
|
+
return oldPlane;
|
|
1022
|
+
}
|
|
1023
|
+
if (oldPlane) {
|
|
1024
|
+
// Dispose function does not actually remove the object from the scene
|
|
1025
|
+
Utils.DisposeObject(oldPlane);
|
|
1026
|
+
oldPlane.visible = false;
|
|
1027
|
+
}
|
|
1028
|
+
const newPlane = this._buildFiller(this._wall.height, this._fillerMaterial);
|
|
1029
|
+
// scene.add(newPlane);
|
|
1030
|
+
return newPlane;
|
|
1031
|
+
}
|
|
1032
|
+
_updateSidePlanes() {
|
|
1033
|
+
const oldPlanes = this._planes.sides;
|
|
1034
|
+
if (oldPlanes &&
|
|
1035
|
+
this._last.height === this._wall.height &&
|
|
1036
|
+
this._equalLastVec2('interior', 'Start') &&
|
|
1037
|
+
this._equalLastVec2('interior', 'End') &&
|
|
1038
|
+
this._equalLastVec2('exterior', 'Start') &&
|
|
1039
|
+
this._equalLastVec2('exterior', 'End')) {
|
|
1040
|
+
return oldPlanes;
|
|
1041
|
+
}
|
|
1042
|
+
const newPlanes = [
|
|
1043
|
+
this._buildSideFiller(this._halfEdge.interiorStart(), this._halfEdge.exteriorStart(), this._wall.height, this._fillerMaterial),
|
|
1044
|
+
this._buildSideFiller(this._halfEdge.interiorEnd(), this._halfEdge.exteriorEnd(), this._wall.height, this._fillerMaterial)
|
|
1045
|
+
];
|
|
1046
|
+
if (oldPlanes) {
|
|
1047
|
+
oldPlanes.forEach(p => {
|
|
1048
|
+
// Dispose function does not actually remove the object from the scene
|
|
1049
|
+
Utils.DisposeObject(p);
|
|
1050
|
+
p.visible = false;
|
|
1051
|
+
});
|
|
1052
|
+
}
|
|
1053
|
+
// newPlanes.forEach(p => scene.add(p));
|
|
1054
|
+
return newPlanes;
|
|
1055
|
+
}
|
|
1056
|
+
updatePlanes() {
|
|
1057
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1058
|
+
this._fillerMaterial = this._updateFillerMaterial();
|
|
1059
|
+
if (this._isValid([this._halfEdge.exteriorStart(), this._halfEdge.exteriorEnd()])) {
|
|
1060
|
+
this._planes.exterior = this._updateMainPlane('exterior', this._fillerMaterial);
|
|
1061
|
+
if (this._halfEdge.getTexture() && this._halfEdge.getTexture().type !== TextureType.Image) {
|
|
1062
|
+
this._updateUvs(this._planes.exterior);
|
|
1063
|
+
}
|
|
1064
|
+
}
|
|
1065
|
+
const oldWallMaterial = this._wallMaterial;
|
|
1066
|
+
this._wallMaterial = yield this._updateWallMaterial(this._halfEdge.getTexture(), this._halfEdge.getColor());
|
|
1067
|
+
if (this._isValid([this._halfEdge.interiorStart(), this._halfEdge.interiorEnd()])) {
|
|
1068
|
+
// this.planes.interior = (!oldWallMaterial || oldWallMaterial === this.wallMaterial)
|
|
1069
|
+
// ? this.updateMainPlane('interior', this.wallMaterial)
|
|
1070
|
+
// : this.updateMainPlaneMaterial('interior', this.wallMaterial);
|
|
1071
|
+
this._planes.interior = this._updateMainPlane('interior', this._wallMaterial);
|
|
1072
|
+
if (this._halfEdge.getTexture() && this._halfEdge.getTexture().type !== TextureType.Image) {
|
|
1073
|
+
this._updateUvs(this._planes.interior);
|
|
1074
|
+
}
|
|
1075
|
+
}
|
|
1076
|
+
this._planes.bottom = this._updateBottomPlane();
|
|
1077
|
+
this._planes.top = this._updateTopPlane();
|
|
1078
|
+
this._planes.sides = this._updateSidePlanes();
|
|
1079
|
+
this._last.fillerMaterial = this._fillerMaterial;
|
|
1080
|
+
this._last.wallMaterial = this._wallMaterial;
|
|
1081
|
+
this._last.height = this._wall.height;
|
|
1082
|
+
this._copyLast('exterior', ['Start', 'End', 'Transform', 'InvTransform']);
|
|
1083
|
+
this._copyLast('interior', ['Start', 'End', 'Transform', 'InvTransform']);
|
|
1084
|
+
});
|
|
1085
|
+
}
|
|
1086
|
+
_updateUvs(mesh) {
|
|
1087
|
+
const dimensions = new THREE.Vector2(this._halfEdge.interiorDistance(), this._wall.height - this._wall.thickness).multiplyScalar(100);
|
|
1088
|
+
const ratio = dimensions.x / dimensions.y;
|
|
1089
|
+
let uvY;
|
|
1090
|
+
const tempVector = new Vector2();
|
|
1091
|
+
const uvArray = mesh.geometry.attributes.uv;
|
|
1092
|
+
if (uvArray) {
|
|
1093
|
+
for (let i = 0; i < uvArray.count; i++) {
|
|
1094
|
+
tempVector.fromBufferAttribute(uvArray, i);
|
|
1095
|
+
uvY = tempVector.y;
|
|
1096
|
+
uvY -= 0.5;
|
|
1097
|
+
uvY /= ratio;
|
|
1098
|
+
uvY += 0.5;
|
|
1099
|
+
uvArray.setY(i, uvY);
|
|
1100
|
+
}
|
|
1101
|
+
uvArray.needsUpdate = true;
|
|
1102
|
+
}
|
|
1103
|
+
}
|
|
1104
|
+
// start, end have x and y attributes (i.e. corners)
|
|
1105
|
+
_createGeometry(start, end, transform, invTransform) {
|
|
1106
|
+
const v1 = this._toVec3(start);
|
|
1107
|
+
const v2 = this._toVec3(end);
|
|
1108
|
+
const v3 = v2.clone();
|
|
1109
|
+
v3.y = this._wall.height;
|
|
1110
|
+
const v4 = v1.clone();
|
|
1111
|
+
v4.y = this._wall.height;
|
|
1112
|
+
const points = [v1.clone(), v2.clone(), v3.clone(), v4.clone()];
|
|
1113
|
+
points.forEach((p) => {
|
|
1114
|
+
p.applyMatrix4(transform);
|
|
1115
|
+
});
|
|
1116
|
+
const shape = new Shape([
|
|
1117
|
+
new Vector2(points[0].x, points[0].y),
|
|
1118
|
+
new Vector2(points[1].x, points[1].y),
|
|
1119
|
+
new Vector2(points[2].x, points[2].y),
|
|
1120
|
+
new Vector2(points[3].x, points[3].y)
|
|
1121
|
+
]);
|
|
1122
|
+
// add holes for each wall item
|
|
1123
|
+
const itemHoles = this._wall.items
|
|
1124
|
+
.filter((item) => !isNaN(item.position.x))
|
|
1125
|
+
.map((item) => {
|
|
1126
|
+
const pos = item.position.clone();
|
|
1127
|
+
pos.applyMatrix4(transform);
|
|
1128
|
+
const halfSize = item.halfSize;
|
|
1129
|
+
const min = halfSize.clone().multiplyScalar(-1);
|
|
1130
|
+
const max = halfSize.clone();
|
|
1131
|
+
min.add(pos);
|
|
1132
|
+
max.add(pos);
|
|
1133
|
+
const holePoints = [
|
|
1134
|
+
new Vector2(min.x, min.y),
|
|
1135
|
+
new Vector2(max.x, min.y),
|
|
1136
|
+
new Vector2(max.x, max.y),
|
|
1137
|
+
new Vector2(min.x, max.y)
|
|
1138
|
+
];
|
|
1139
|
+
return holePoints;
|
|
1140
|
+
});
|
|
1141
|
+
const polygons = Utils.polygonsUnion(itemHoles);
|
|
1142
|
+
polygons.forEach(holePolygon => shape.holes.push(new Path(holePolygon)));
|
|
1143
|
+
const geometry = new ShapeGeometry(shape);
|
|
1144
|
+
const positionAttribute = geometry.getAttribute('position');
|
|
1145
|
+
const uvAttribute = geometry.getAttribute('uv');
|
|
1146
|
+
Utils.ApplyBufferAttributeMatrixTransform(positionAttribute, invTransform);
|
|
1147
|
+
// make UVs
|
|
1148
|
+
const totalDistance = Utils.distance(v1.x, v1.z, v2.x, v2.z);
|
|
1149
|
+
const height = this._wall.height;
|
|
1150
|
+
function vertexToUv(vertex) {
|
|
1151
|
+
const x = Utils.distance(v1.x, v1.z, vertex.x, vertex.z) / totalDistance;
|
|
1152
|
+
const y = vertex.y / height;
|
|
1153
|
+
return new THREE.Vector2(x, y);
|
|
1154
|
+
}
|
|
1155
|
+
const tempUVArray = [];
|
|
1156
|
+
const positionDataAsVector3Array = Utils.GetVector3ArrayFromBufferAttribute(positionAttribute.clone());
|
|
1157
|
+
positionDataAsVector3Array.forEach((vertex) => {
|
|
1158
|
+
tempUVArray.push(vertexToUv(vertex));
|
|
1159
|
+
});
|
|
1160
|
+
tempUVArray.forEach((uvVector, index) => {
|
|
1161
|
+
uvAttribute.setXY(index, uvVector.x, uvVector.y);
|
|
1162
|
+
});
|
|
1163
|
+
uvAttribute.needsUpdate = true;
|
|
1164
|
+
geometry.computeVertexNormals();
|
|
1165
|
+
return geometry;
|
|
1166
|
+
}
|
|
1167
|
+
_buildSideFiller(p1, p2, height, material) {
|
|
1168
|
+
const points = [
|
|
1169
|
+
this._toVec3(p1),
|
|
1170
|
+
this._toVec3(p2),
|
|
1171
|
+
this._toVec3(p2, height),
|
|
1172
|
+
this._toVec3(p1, height)
|
|
1173
|
+
];
|
|
1174
|
+
const geometry = new BufferGeometry().setFromPoints(points);
|
|
1175
|
+
const filler = new Mesh(geometry, material);
|
|
1176
|
+
filler.castShadow = true;
|
|
1177
|
+
filler.receiveShadow = true;
|
|
1178
|
+
filler.name = 'edge-side-filler';
|
|
1179
|
+
return filler;
|
|
1180
|
+
}
|
|
1181
|
+
_buildFiller(height, material) {
|
|
1182
|
+
const points = [
|
|
1183
|
+
this._toVec2(this._halfEdge.exteriorStart()),
|
|
1184
|
+
this._toVec2(this._halfEdge.exteriorEnd()),
|
|
1185
|
+
this._toVec2(this._halfEdge.interiorEnd()),
|
|
1186
|
+
this._toVec2(this._halfEdge.interiorStart())
|
|
1187
|
+
];
|
|
1188
|
+
const shape = new Shape(points);
|
|
1189
|
+
const geometry = new ShapeGeometry(shape);
|
|
1190
|
+
const filler = new Mesh(geometry, material);
|
|
1191
|
+
filler.name = 'edge-filler';
|
|
1192
|
+
filler.castShadow = true;
|
|
1193
|
+
filler.receiveShadow = true;
|
|
1194
|
+
filler.rotation.set(Math.PI / 2, 0, 0);
|
|
1195
|
+
filler.position.y = height;
|
|
1196
|
+
return filler;
|
|
1197
|
+
}
|
|
1198
|
+
_toVec2(pos) {
|
|
1199
|
+
return new Vector2(pos.x, pos.y);
|
|
1200
|
+
}
|
|
1201
|
+
_toVec3(pos, height = 0) {
|
|
1202
|
+
return new Vector3(pos.x, height, pos.y);
|
|
1203
|
+
}
|
|
1204
|
+
}
|
|
1205
|
+
export class Room {
|
|
1206
|
+
// private floorChangeCallbacks = $.Callbacks();
|
|
1207
|
+
constructor(corners, defaultTexture) {
|
|
1208
|
+
this.corners = corners;
|
|
1209
|
+
this.interiorCorners = [];
|
|
1210
|
+
this.edgePointer = null;
|
|
1211
|
+
this.edgeHeights = [];
|
|
1212
|
+
this.floorPlane = null;
|
|
1213
|
+
this.floorColor = 0xcccccc;
|
|
1214
|
+
this.ceilingPlane = null;
|
|
1215
|
+
if (defaultTexture) {
|
|
1216
|
+
this.floorTexture = defaultTexture;
|
|
1217
|
+
}
|
|
1218
|
+
this._setEdgePointer();
|
|
1219
|
+
this._updateInteriorCorners();
|
|
1220
|
+
}
|
|
1221
|
+
dispose() {
|
|
1222
|
+
Utils.DisposeObject(this.floorPlane);
|
|
1223
|
+
Utils.DisposeObject(this.ceilingPlane);
|
|
1224
|
+
}
|
|
1225
|
+
getInteriorCorners() {
|
|
1226
|
+
return this.interiorCorners.map((c) => new Vector2(c.x, c.y));
|
|
1227
|
+
}
|
|
1228
|
+
getUuid() {
|
|
1229
|
+
const cornerUuids = Utils.map(this.corners, function (c) {
|
|
1230
|
+
return c.id;
|
|
1231
|
+
});
|
|
1232
|
+
cornerUuids.sort();
|
|
1233
|
+
return cornerUuids.join();
|
|
1234
|
+
}
|
|
1235
|
+
getTexture() {
|
|
1236
|
+
// const uuid = this.getUuid();
|
|
1237
|
+
// return this.floorplan.getFloorTexture(uuid);
|
|
1238
|
+
return this.floorTexture;
|
|
1239
|
+
}
|
|
1240
|
+
getColor() {
|
|
1241
|
+
// const uuid = this.getUuid();
|
|
1242
|
+
// return this.floorplan.getFloorColor(uuid) || defaultFloorColor;
|
|
1243
|
+
return this.floorColor;
|
|
1244
|
+
}
|
|
1245
|
+
useTexture() {
|
|
1246
|
+
// return defaultFloorColor === this.getColor();
|
|
1247
|
+
}
|
|
1248
|
+
/**
|
|
1249
|
+
* textureStretch always true, just an argument for consistency with walls
|
|
1250
|
+
*/
|
|
1251
|
+
// public setTexture(texture: Texture) {
|
|
1252
|
+
// // const uuid = this.getUuid();
|
|
1253
|
+
// // this.floorplan.setFloorTexture(uuid, texture);
|
|
1254
|
+
// // this.floorplan.deleteFloorColor(uuid);
|
|
1255
|
+
// // this.floorChangeCallbacks.fire();
|
|
1256
|
+
// }
|
|
1257
|
+
// public setColor(color: number) {
|
|
1258
|
+
// // const uuid = this.getUuid();
|
|
1259
|
+
// // this.floorplan.deleteFloorTexture(uuid);
|
|
1260
|
+
// // this.floorplan.setFloorColor(uuid, color);
|
|
1261
|
+
// // this.floorChangeCallbacks.fire();
|
|
1262
|
+
// }
|
|
1263
|
+
updateWallHeights() {
|
|
1264
|
+
let edge = this.edgePointer;
|
|
1265
|
+
this.edgeHeights.length = 0;
|
|
1266
|
+
while (true) {
|
|
1267
|
+
this.edgeHeights.push(edge.wall.height);
|
|
1268
|
+
if (edge.next === this.edgePointer) {
|
|
1269
|
+
break;
|
|
1270
|
+
}
|
|
1271
|
+
else {
|
|
1272
|
+
edge = edge.next;
|
|
1273
|
+
}
|
|
1274
|
+
}
|
|
1275
|
+
}
|
|
1276
|
+
setDefaultFloorTexture() {
|
|
1277
|
+
// if (!this._defaultFloorTexture) {
|
|
1278
|
+
// return;
|
|
1279
|
+
// }
|
|
1280
|
+
// const uuid = this.getUuid();
|
|
1281
|
+
// if (!this.floorplan.getFloorTexture(uuid) && !this.floorplan.getFloorColor(uuid)) {
|
|
1282
|
+
// this.setTexture(this._defaultFloorTexture);
|
|
1283
|
+
// }
|
|
1284
|
+
}
|
|
1285
|
+
_updateInteriorCorners() {
|
|
1286
|
+
let edge = this.edgePointer;
|
|
1287
|
+
this.edgeHeights.length = 0;
|
|
1288
|
+
while (true) {
|
|
1289
|
+
this.interiorCorners.push(edge.interiorStart());
|
|
1290
|
+
edge.generatePlane();
|
|
1291
|
+
this.edgeHeights.push(edge.height);
|
|
1292
|
+
if (edge.next === this.edgePointer) {
|
|
1293
|
+
break;
|
|
1294
|
+
}
|
|
1295
|
+
else {
|
|
1296
|
+
edge = edge.next;
|
|
1297
|
+
}
|
|
1298
|
+
}
|
|
1299
|
+
}
|
|
1300
|
+
_setEdgePointer() {
|
|
1301
|
+
let prevEdge = null;
|
|
1302
|
+
let firstEdge = null;
|
|
1303
|
+
for (let i = 0; i < this.corners.length; i++) {
|
|
1304
|
+
const firstCorner = this.corners[i];
|
|
1305
|
+
const secondCorner = this.corners[(i + 1) % this.corners.length];
|
|
1306
|
+
// find if wall is heading in that direction
|
|
1307
|
+
const wallTo = firstCorner.wallTo(secondCorner);
|
|
1308
|
+
const wallFrom = firstCorner.wallFrom(secondCorner);
|
|
1309
|
+
let edge;
|
|
1310
|
+
if (wallTo) {
|
|
1311
|
+
edge = new HalfEdge(this, wallTo, true);
|
|
1312
|
+
}
|
|
1313
|
+
else if (wallFrom) {
|
|
1314
|
+
edge = new HalfEdge(this, wallFrom, false);
|
|
1315
|
+
}
|
|
1316
|
+
else {
|
|
1317
|
+
// something horrible has happened
|
|
1318
|
+
console.log('corners arent connected by a wall, uh oh');
|
|
1319
|
+
}
|
|
1320
|
+
if (i === 0) {
|
|
1321
|
+
firstEdge = edge;
|
|
1322
|
+
}
|
|
1323
|
+
else {
|
|
1324
|
+
edge.prev = prevEdge;
|
|
1325
|
+
prevEdge.next = edge;
|
|
1326
|
+
if (i + 1 === this.corners.length) {
|
|
1327
|
+
firstEdge.prev = edge;
|
|
1328
|
+
edge.next = firstEdge;
|
|
1329
|
+
}
|
|
1330
|
+
}
|
|
1331
|
+
prevEdge = edge;
|
|
1332
|
+
}
|
|
1333
|
+
// hold on to an edge reference
|
|
1334
|
+
this.edgePointer = firstEdge;
|
|
1335
|
+
}
|
|
1336
|
+
get area() {
|
|
1337
|
+
const polygon = this._polygonFromCorners(this.interiorCorners);
|
|
1338
|
+
return Utils.polygonArea(polygon);
|
|
1339
|
+
}
|
|
1340
|
+
get center() {
|
|
1341
|
+
const polygon = this._polygonFromCorners(this.corners);
|
|
1342
|
+
return Utils.polygonCenter(polygon);
|
|
1343
|
+
}
|
|
1344
|
+
_polygonFromCorners(corners) {
|
|
1345
|
+
return corners.map(c => new Vector2(c.x, c.y));
|
|
1346
|
+
}
|
|
1347
|
+
}
|
|
1348
|
+
/**
|
|
1349
|
+
* A Wall Item is an entity to be placed related to a wall.
|
|
1350
|
+
*/
|
|
1351
|
+
export class WallItem extends Item {
|
|
1352
|
+
constructor(metadata, object, texture, handlers) {
|
|
1353
|
+
super(metadata, object, texture, handlers);
|
|
1354
|
+
/** The currently applied wall */
|
|
1355
|
+
this.currentWall = null;
|
|
1356
|
+
/** The currently applied wall edge. */
|
|
1357
|
+
this.currentWallEdge = null;
|
|
1358
|
+
/** Used for finding rotations */
|
|
1359
|
+
this._refVec = new THREE.Vector2(0, 1.0);
|
|
1360
|
+
this._positionYTolerance = 0.005;
|
|
1361
|
+
/** */
|
|
1362
|
+
this._wallOffsetScalar = 0;
|
|
1363
|
+
/** */
|
|
1364
|
+
this._sizeX = 0;
|
|
1365
|
+
/** */
|
|
1366
|
+
this._sizeY = 0;
|
|
1367
|
+
this._flipped = false;
|
|
1368
|
+
/** */
|
|
1369
|
+
this.addToWall = false;
|
|
1370
|
+
/** */
|
|
1371
|
+
this.boundToFloor = false;
|
|
1372
|
+
/** */
|
|
1373
|
+
this.frontVisible = false;
|
|
1374
|
+
this.backVisible = false;
|
|
1375
|
+
this._hasFrontEdge = false;
|
|
1376
|
+
this._hasBackEdge = false;
|
|
1377
|
+
this.allowRotate = false;
|
|
1378
|
+
if (texture) {
|
|
1379
|
+
this.setTexture(texture);
|
|
1380
|
+
}
|
|
1381
|
+
}
|
|
1382
|
+
/** */
|
|
1383
|
+
removed() {
|
|
1384
|
+
if (!isNill(this.currentWallEdge) && this.addToWall) {
|
|
1385
|
+
this.currentWallEdge.wall.removeItem(this);
|
|
1386
|
+
this.redrawWall();
|
|
1387
|
+
}
|
|
1388
|
+
}
|
|
1389
|
+
removeFromWall() {
|
|
1390
|
+
if (this.currentWall) {
|
|
1391
|
+
this.currentWall.removeOnItem(this);
|
|
1392
|
+
this.currentWall = undefined;
|
|
1393
|
+
this.currentWallEdge = undefined;
|
|
1394
|
+
}
|
|
1395
|
+
}
|
|
1396
|
+
/**
|
|
1397
|
+
* Only hides item when entire wall is hidden
|
|
1398
|
+
* This prevents items being set hidden for inner walls
|
|
1399
|
+
* */
|
|
1400
|
+
updateEdgeVisibility(edge) {
|
|
1401
|
+
if (this.currentWall) {
|
|
1402
|
+
let shouldShow = false;
|
|
1403
|
+
if (this.currentWall.backEdge) {
|
|
1404
|
+
this.currentWall.backEdge.edges.forEach((e) => {
|
|
1405
|
+
if (e.visible) {
|
|
1406
|
+
shouldShow = true;
|
|
1407
|
+
}
|
|
1408
|
+
});
|
|
1409
|
+
}
|
|
1410
|
+
if (this.currentWall.frontEdge) {
|
|
1411
|
+
this.currentWall.frontEdge.edges.forEach(e => {
|
|
1412
|
+
if (e.visible) {
|
|
1413
|
+
shouldShow = true;
|
|
1414
|
+
}
|
|
1415
|
+
});
|
|
1416
|
+
}
|
|
1417
|
+
this.visible = shouldShow;
|
|
1418
|
+
}
|
|
1419
|
+
}
|
|
1420
|
+
/** */
|
|
1421
|
+
updateSize() {
|
|
1422
|
+
this._wallOffsetScalar = this.getDepth() / 2;
|
|
1423
|
+
this._sizeX = this.getWidth();
|
|
1424
|
+
this._sizeY = this.getHeight();
|
|
1425
|
+
}
|
|
1426
|
+
/** */
|
|
1427
|
+
resized() {
|
|
1428
|
+
if (this.boundToFloor) {
|
|
1429
|
+
this.position.y = this._boundToFloorY();
|
|
1430
|
+
}
|
|
1431
|
+
this.updateSize();
|
|
1432
|
+
this.redrawWall();
|
|
1433
|
+
}
|
|
1434
|
+
/** */
|
|
1435
|
+
placeOnEdge(edge) {
|
|
1436
|
+
if (!edge) {
|
|
1437
|
+
return;
|
|
1438
|
+
}
|
|
1439
|
+
this._onFrontSide = edge.wall.frontEdge === edge;
|
|
1440
|
+
this._changeWallEdge(edge);
|
|
1441
|
+
this.updateSize();
|
|
1442
|
+
// position not set
|
|
1443
|
+
const center = edge.interiorCenter();
|
|
1444
|
+
const newPos = this.positionSet ?
|
|
1445
|
+
(edge.wall.amountWallMoved ? this.position.add(new Vector3(edge.wall.amountWallMoved.x, 0, 0)) : this.position.clone()) :
|
|
1446
|
+
new THREE.Vector3(center.x, edge.wall.height / 2.0, center.y);
|
|
1447
|
+
this._boundMove(newPos);
|
|
1448
|
+
this.position.copy(newPos);
|
|
1449
|
+
this.redrawWall();
|
|
1450
|
+
}
|
|
1451
|
+
reposition() {
|
|
1452
|
+
const newPos = this.position.clone();
|
|
1453
|
+
this._boundMove(newPos);
|
|
1454
|
+
this.position.copy(newPos);
|
|
1455
|
+
}
|
|
1456
|
+
getFloorY() {
|
|
1457
|
+
if (this.halfSize && this.currentWallEdge) {
|
|
1458
|
+
return this._moveToYPosition(this.halfSize.y + this.elevation);
|
|
1459
|
+
}
|
|
1460
|
+
else {
|
|
1461
|
+
return this.position.y;
|
|
1462
|
+
}
|
|
1463
|
+
}
|
|
1464
|
+
isValidPosition(position, rotation, options) {
|
|
1465
|
+
return { valid: !!this.currentWallEdge };
|
|
1466
|
+
}
|
|
1467
|
+
/** */
|
|
1468
|
+
moveToPosition(vec3, intersection) {
|
|
1469
|
+
if (intersection && this.currentWallEdge) {
|
|
1470
|
+
if (intersection.object.userData.edge && intersection.object.userData.edge.wall !== this.currentWallEdge.wall) {
|
|
1471
|
+
this._changeWallEdge(intersection.object.userData.edge);
|
|
1472
|
+
}
|
|
1473
|
+
this._boundMove(vec3);
|
|
1474
|
+
this.position.copy(vec3);
|
|
1475
|
+
this.redrawWall();
|
|
1476
|
+
}
|
|
1477
|
+
}
|
|
1478
|
+
/** */
|
|
1479
|
+
moveTo2dPosition(x, y, edge) {
|
|
1480
|
+
const vec3 = new Vector3(x, this.position.y, y);
|
|
1481
|
+
this._changeWallEdge(edge);
|
|
1482
|
+
this._boundMove(vec3);
|
|
1483
|
+
this.position.copy(vec3);
|
|
1484
|
+
this.redrawWall();
|
|
1485
|
+
}
|
|
1486
|
+
/** */
|
|
1487
|
+
getWallOffset() {
|
|
1488
|
+
return this._wallOffsetScalar;
|
|
1489
|
+
}
|
|
1490
|
+
getStartX() {
|
|
1491
|
+
return this.position.x - this.getSizeX() / 2 * Math.cos(this.rotation.y);
|
|
1492
|
+
}
|
|
1493
|
+
getStartY() {
|
|
1494
|
+
return this.position.z + this.getSizeX() / 2 * Math.sin(this.rotation.y);
|
|
1495
|
+
}
|
|
1496
|
+
getEndX() {
|
|
1497
|
+
return this.position.x + this.getSizeX() / 2 * Math.cos(this.rotation.y);
|
|
1498
|
+
}
|
|
1499
|
+
getEndY() {
|
|
1500
|
+
return this.position.z - this.getSizeX() / 2 * Math.sin(this.rotation.y);
|
|
1501
|
+
}
|
|
1502
|
+
/**
|
|
1503
|
+
@returns x axis size of item's bounding box
|
|
1504
|
+
*/
|
|
1505
|
+
getSizeX() {
|
|
1506
|
+
return this._sizeX;
|
|
1507
|
+
}
|
|
1508
|
+
/**
|
|
1509
|
+
@returns y axis size of item's bounding box
|
|
1510
|
+
*/
|
|
1511
|
+
getSizeY() {
|
|
1512
|
+
return this._sizeY;
|
|
1513
|
+
}
|
|
1514
|
+
heightUpdated(amount) {
|
|
1515
|
+
if (!isNill(amount)) {
|
|
1516
|
+
this.position.y = this._moveToYPosition(this.position.y + amount);
|
|
1517
|
+
this.redrawWall();
|
|
1518
|
+
}
|
|
1519
|
+
else {
|
|
1520
|
+
super.heightUpdated();
|
|
1521
|
+
}
|
|
1522
|
+
}
|
|
1523
|
+
updateGeometry(width, height) {
|
|
1524
|
+
const geometry = Geometry.wallBox(width, height, this.getItemThickness());
|
|
1525
|
+
this.object.geometry.dispose();
|
|
1526
|
+
const rotation = this.rotation.y;
|
|
1527
|
+
this.rotation.y = 0;
|
|
1528
|
+
// this.initializeGeometry(geometry);
|
|
1529
|
+
this.rotation.y = rotation;
|
|
1530
|
+
this.resized();
|
|
1531
|
+
this.redrawWall();
|
|
1532
|
+
}
|
|
1533
|
+
setTexture(texture) {
|
|
1534
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1535
|
+
this.texture = texture && Object.assign({}, texture);
|
|
1536
|
+
return yield this.createMaterial(this.currentWallEdge ? this.currentWallEdge.wall.side : undefined);
|
|
1537
|
+
});
|
|
1538
|
+
}
|
|
1539
|
+
onWallMoved(wall) {
|
|
1540
|
+
if (wall.frontEdge) {
|
|
1541
|
+
this.placeOnEdge(wall.frontEdge);
|
|
1542
|
+
}
|
|
1543
|
+
if (wall.backEdge) {
|
|
1544
|
+
this.placeOnEdge(wall.backEdge);
|
|
1545
|
+
}
|
|
1546
|
+
}
|
|
1547
|
+
updateMaterialVisibility(side = THREE.DoubleSide) {
|
|
1548
|
+
if (!this.texture) {
|
|
1549
|
+
return;
|
|
1550
|
+
}
|
|
1551
|
+
if (this.currentWallEdge) {
|
|
1552
|
+
return;
|
|
1553
|
+
}
|
|
1554
|
+
const isSame = this._isWallSame();
|
|
1555
|
+
if (!isSame) {
|
|
1556
|
+
this.createMaterial(side, isSame);
|
|
1557
|
+
return;
|
|
1558
|
+
}
|
|
1559
|
+
const textureMaterialFront = this.object.material[4];
|
|
1560
|
+
const textureMaterialBack = this.object.material[5];
|
|
1561
|
+
switch (side) {
|
|
1562
|
+
case THREE.DoubleSide:
|
|
1563
|
+
textureMaterialFront.visible = true;
|
|
1564
|
+
textureMaterialBack.visible = true;
|
|
1565
|
+
break;
|
|
1566
|
+
case THREE.FrontSide:
|
|
1567
|
+
textureMaterialFront.visible = this.frontVisible;
|
|
1568
|
+
textureMaterialBack.visible = !this.frontVisible;
|
|
1569
|
+
break;
|
|
1570
|
+
case THREE.BackSide:
|
|
1571
|
+
textureMaterialFront.visible = !this.frontVisible;
|
|
1572
|
+
textureMaterialBack.visible = this.frontVisible;
|
|
1573
|
+
break;
|
|
1574
|
+
}
|
|
1575
|
+
}
|
|
1576
|
+
createTextureMaterial(options) {
|
|
1577
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1578
|
+
const { side = THREE.DoubleSide, flip = false } = options || {};
|
|
1579
|
+
const texture = this.getTexture();
|
|
1580
|
+
const material = new THREE.MeshPhongMaterial({ side });
|
|
1581
|
+
material.transparent = true;
|
|
1582
|
+
if (texture) {
|
|
1583
|
+
yield this.addMaterialMap(material, texture, flip);
|
|
1584
|
+
}
|
|
1585
|
+
return material;
|
|
1586
|
+
});
|
|
1587
|
+
}
|
|
1588
|
+
getTexture() {
|
|
1589
|
+
return this.texture;
|
|
1590
|
+
}
|
|
1591
|
+
createMaterial(side = THREE.DoubleSide, isSame = true) {
|
|
1592
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1593
|
+
let textureMaterialFront;
|
|
1594
|
+
let textureMaterialBack;
|
|
1595
|
+
switch (side) {
|
|
1596
|
+
case THREE.DoubleSide:
|
|
1597
|
+
this._flipped = !isSame;
|
|
1598
|
+
textureMaterialFront = yield this.createTextureMaterial({ side: THREE.FrontSide, flip: this._flipped });
|
|
1599
|
+
textureMaterialBack = yield this.createTextureMaterial({ side: THREE.FrontSide, flip: !this._flipped });
|
|
1600
|
+
break;
|
|
1601
|
+
case THREE.FrontSide:
|
|
1602
|
+
this._flipped = !isSame;
|
|
1603
|
+
if (this.frontVisible) {
|
|
1604
|
+
textureMaterialFront = yield this.createTextureMaterial({ side: THREE.FrontSide, flip: this._flipped });
|
|
1605
|
+
}
|
|
1606
|
+
else {
|
|
1607
|
+
textureMaterialBack = yield this.createTextureMaterial({ side: THREE.BackSide, flip: !this._flipped });
|
|
1608
|
+
}
|
|
1609
|
+
break;
|
|
1610
|
+
case THREE.BackSide: {
|
|
1611
|
+
this._flipped = !isSame;
|
|
1612
|
+
if (!this.frontVisible) {
|
|
1613
|
+
textureMaterialFront = yield this.createTextureMaterial({ side: THREE.FrontSide, flip: this._flipped });
|
|
1614
|
+
}
|
|
1615
|
+
else {
|
|
1616
|
+
textureMaterialBack = yield this.createTextureMaterial({
|
|
1617
|
+
side: THREE.BackSide, flip: !this._flipped
|
|
1618
|
+
});
|
|
1619
|
+
}
|
|
1620
|
+
break;
|
|
1621
|
+
}
|
|
1622
|
+
}
|
|
1623
|
+
this.object.material = this.getMaterials(textureMaterialFront, textureMaterialBack);
|
|
1624
|
+
});
|
|
1625
|
+
}
|
|
1626
|
+
setYPositionBasedOnElevation() {
|
|
1627
|
+
this.position.y = this.elevation + this.halfSize.y;
|
|
1628
|
+
}
|
|
1629
|
+
addMaterialMap(material, texture, flip) {
|
|
1630
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1631
|
+
const dimensions = this.getMaterialMapDimensions();
|
|
1632
|
+
texture.dimensions = dimensions.multiplyScalar(100);
|
|
1633
|
+
switch (texture.type) {
|
|
1634
|
+
case TextureType.Image:
|
|
1635
|
+
if (flip) {
|
|
1636
|
+
material.map = yield MaterialUtils.FromFlippedImage(texture, dimensions);
|
|
1637
|
+
}
|
|
1638
|
+
else {
|
|
1639
|
+
material.map = yield MaterialUtils.FromImage(texture);
|
|
1640
|
+
}
|
|
1641
|
+
break;
|
|
1642
|
+
case TextureType.CustomPattern:
|
|
1643
|
+
material.map = yield MaterialUtils.CustomTileMapTexture(texture, dimensions);
|
|
1644
|
+
break;
|
|
1645
|
+
case TextureType.Basic:
|
|
1646
|
+
material.map = yield MaterialUtils.FromUrl(texture.url, texture.stretch, texture.tileSize, null, null, texture.dimensions, texture.tileRotation);
|
|
1647
|
+
break;
|
|
1648
|
+
}
|
|
1649
|
+
// this.scene.needsUpdate = true;
|
|
1650
|
+
// this.scene.textureLoadedCallbacks.fire();
|
|
1651
|
+
});
|
|
1652
|
+
}
|
|
1653
|
+
getMaterialMapDimensions() {
|
|
1654
|
+
return new THREE.Vector2(this.getWidth(), this.getHeight());
|
|
1655
|
+
}
|
|
1656
|
+
getMaterials(textureMaterialFront, textureMaterialBack) {
|
|
1657
|
+
return [
|
|
1658
|
+
MaterialUtils.defaultWindow.clone(),
|
|
1659
|
+
MaterialUtils.defaultWindow.clone(),
|
|
1660
|
+
MaterialUtils.defaultWindow.clone(),
|
|
1661
|
+
MaterialUtils.defaultWindow.clone(),
|
|
1662
|
+
textureMaterialFront || MaterialUtils.defaultWindow.clone(),
|
|
1663
|
+
textureMaterialBack || MaterialUtils.defaultWindow.clone() // Back side
|
|
1664
|
+
];
|
|
1665
|
+
}
|
|
1666
|
+
getItemThickness() {
|
|
1667
|
+
return this.currentWall.thickness - 0.01;
|
|
1668
|
+
}
|
|
1669
|
+
/** */
|
|
1670
|
+
redrawWall() {
|
|
1671
|
+
if (this.currentWallEdge && this.currentWallEdge.wall) {
|
|
1672
|
+
this.currentWallEdge.wall.fireRedraw();
|
|
1673
|
+
}
|
|
1674
|
+
// this.updateEdgeVisibility(true, this._onFrontSide);
|
|
1675
|
+
}
|
|
1676
|
+
/** */
|
|
1677
|
+
_changeWallEdge(wallEdge) {
|
|
1678
|
+
if (this.currentWallEdge === wallEdge) {
|
|
1679
|
+
if (!this.currentWall) {
|
|
1680
|
+
this.currentWall = wallEdge.wall;
|
|
1681
|
+
}
|
|
1682
|
+
return;
|
|
1683
|
+
}
|
|
1684
|
+
if (!isNill(this.currentWallEdge)) {
|
|
1685
|
+
if (this.addToWall) {
|
|
1686
|
+
this.currentWallEdge.wall.removeItem(this);
|
|
1687
|
+
this.redrawWall();
|
|
1688
|
+
}
|
|
1689
|
+
else {
|
|
1690
|
+
this.currentWallEdge.wall.removeOnItem(this);
|
|
1691
|
+
}
|
|
1692
|
+
}
|
|
1693
|
+
if (!wallEdge) {
|
|
1694
|
+
return;
|
|
1695
|
+
}
|
|
1696
|
+
// find angle between wall normals
|
|
1697
|
+
const normal2 = new THREE.Vector2();
|
|
1698
|
+
const normal3 = Utils.GetFaceNormalFromBufferGeometry(wallEdge.plane.geometry, 0, 0);
|
|
1699
|
+
normal2.x = normal3.x;
|
|
1700
|
+
normal2.y = normal3.z;
|
|
1701
|
+
const angle = Utils.angle(this._refVec.x, this._refVec.y, normal2.x, normal2.y);
|
|
1702
|
+
this.rotation.y = (this.default180 ? Math.PI : 0) + angle;
|
|
1703
|
+
this.traverse(c => c.matrixWorldNeedsUpdate = true);
|
|
1704
|
+
// update currentWall
|
|
1705
|
+
this.currentWall = wallEdge.wall;
|
|
1706
|
+
this.currentWallEdge = wallEdge;
|
|
1707
|
+
if (this.addToWall) {
|
|
1708
|
+
wallEdge.wall.addItem(this);
|
|
1709
|
+
if (this.metadata.texture) {
|
|
1710
|
+
this.updateMaterialVisibility(wallEdge.wall.side);
|
|
1711
|
+
}
|
|
1712
|
+
this.redrawWall();
|
|
1713
|
+
}
|
|
1714
|
+
else {
|
|
1715
|
+
wallEdge.wall.addOnItem(this);
|
|
1716
|
+
}
|
|
1717
|
+
}
|
|
1718
|
+
_boundToFloorY() {
|
|
1719
|
+
return 0.5 * this.getHeight() * this.scale.y + 0.01;
|
|
1720
|
+
}
|
|
1721
|
+
/** takes the move vec3, and makes sure object stays bounded on plane */
|
|
1722
|
+
_boundMove(vec3) {
|
|
1723
|
+
const edge = this.currentWallEdge;
|
|
1724
|
+
vec3.applyMatrix4(edge.interiorTransform);
|
|
1725
|
+
edge.wall.itemsChanged = true;
|
|
1726
|
+
if (vec3.x < this._sizeX / 2.0 + this._positionYTolerance) {
|
|
1727
|
+
vec3.x = this._sizeX / 2.0 + this._positionYTolerance;
|
|
1728
|
+
}
|
|
1729
|
+
else if (vec3.x > (edge.interiorDistance() - this._sizeX / 2.0 - this._positionYTolerance)) {
|
|
1730
|
+
vec3.x = edge.interiorDistance() - this._sizeX / 2.0 - this._positionYTolerance;
|
|
1731
|
+
}
|
|
1732
|
+
if (this.boundToFloor) {
|
|
1733
|
+
vec3.y = this._boundToFloorY();
|
|
1734
|
+
}
|
|
1735
|
+
else {
|
|
1736
|
+
if (this.elevationFixed || !this.elevationAdjustable) {
|
|
1737
|
+
// if elevation is higher than the wall, use maxY
|
|
1738
|
+
vec3.y = Math.min(this._getMaxY(edge), this.halfSize.y + this.elevation);
|
|
1739
|
+
}
|
|
1740
|
+
else {
|
|
1741
|
+
const maxY = this._getMaxY(edge);
|
|
1742
|
+
const minY = this._getMinT();
|
|
1743
|
+
if (vec3.y < minY) {
|
|
1744
|
+
vec3.y = minY;
|
|
1745
|
+
}
|
|
1746
|
+
else if (vec3.y > maxY) {
|
|
1747
|
+
vec3.y = maxY;
|
|
1748
|
+
}
|
|
1749
|
+
this.elevation = vec3.y - this.halfSize.y;
|
|
1750
|
+
}
|
|
1751
|
+
}
|
|
1752
|
+
vec3.z = this.getWallOffset();
|
|
1753
|
+
vec3.applyMatrix4(edge.invInteriorTransform);
|
|
1754
|
+
}
|
|
1755
|
+
_isWallSame() {
|
|
1756
|
+
let isSame = false;
|
|
1757
|
+
if (this.currentWallEdge) {
|
|
1758
|
+
const onFrontSide = this.currentWallEdge === this.currentWallEdge.wall.frontEdge;
|
|
1759
|
+
if (this._onFrontSide === undefined) {
|
|
1760
|
+
this._onFrontSide = onFrontSide;
|
|
1761
|
+
}
|
|
1762
|
+
isSame = onFrontSide === this._onFrontSide;
|
|
1763
|
+
}
|
|
1764
|
+
return isSame;
|
|
1765
|
+
}
|
|
1766
|
+
_getMaxY(edge) {
|
|
1767
|
+
return edge.height - this._sizeY / 2.0 - this._positionYTolerance;
|
|
1768
|
+
}
|
|
1769
|
+
_getMinT() {
|
|
1770
|
+
return this._sizeY / 2.0 + this._positionYTolerance;
|
|
1771
|
+
}
|
|
1772
|
+
_moveToYPosition(position) {
|
|
1773
|
+
const maxY = this._getMaxY(this.currentWallEdge);
|
|
1774
|
+
const minY = this._getMinT();
|
|
1775
|
+
if (position > maxY) {
|
|
1776
|
+
this.elevation = maxY - this.halfSize.y;
|
|
1777
|
+
return maxY;
|
|
1778
|
+
}
|
|
1779
|
+
if (position < minY) {
|
|
1780
|
+
this.elevation = minY - this.halfSize.y;
|
|
1781
|
+
return minY;
|
|
1782
|
+
}
|
|
1783
|
+
return position;
|
|
1784
|
+
}
|
|
1785
|
+
}
|
|
1786
|
+
export class InWallItem extends WallItem {
|
|
1787
|
+
constructor(metadata, object, texture) {
|
|
1788
|
+
super(metadata, object, texture);
|
|
1789
|
+
this._frameWidth = 0.07;
|
|
1790
|
+
this._frameDepth = 0.1;
|
|
1791
|
+
this._defaultFrameColor = 9070146; // RAL-1011
|
|
1792
|
+
this._defaultDoorColor = 16777215; // RAL-9010
|
|
1793
|
+
this.opening = {
|
|
1794
|
+
show: false,
|
|
1795
|
+
double: false,
|
|
1796
|
+
invertDirection: false,
|
|
1797
|
+
invertSide: true
|
|
1798
|
+
};
|
|
1799
|
+
this.frameColor = this._defaultFrameColor;
|
|
1800
|
+
this.doorColor = this._defaultDoorColor;
|
|
1801
|
+
this.windowColor = new THREE.Color(0.0431, 0.0588, 0.0902);
|
|
1802
|
+
this.isGlass = false;
|
|
1803
|
+
this._isWindow = false;
|
|
1804
|
+
this._doorpost = false;
|
|
1805
|
+
this._setDefault();
|
|
1806
|
+
this.frameTitle = 'Frame';
|
|
1807
|
+
this.customMeshTitle = this._isWindow ? 'Window' : 'Door';
|
|
1808
|
+
this.canChangeCustomMeshColor = !this._isWindow;
|
|
1809
|
+
this.receiveShadow = true;
|
|
1810
|
+
this.addToWall = true;
|
|
1811
|
+
this._glassMaterialCheck();
|
|
1812
|
+
}
|
|
1813
|
+
get doorpost() {
|
|
1814
|
+
return this._doorpost;
|
|
1815
|
+
}
|
|
1816
|
+
dispose() {
|
|
1817
|
+
super.dispose();
|
|
1818
|
+
Utils.DisposeObject(this.topFrame);
|
|
1819
|
+
Utils.DisposeObject(this.leftFrame);
|
|
1820
|
+
Utils.DisposeObject(this.rightFrame);
|
|
1821
|
+
Utils.DisposeObject(this.bottomFrame);
|
|
1822
|
+
Utils.DisposeObject(this.customMesh);
|
|
1823
|
+
Utils.DisposeMaterial(this.frameMaterial);
|
|
1824
|
+
Utils.DisposeMaterial(this.doorMaterialFront);
|
|
1825
|
+
Utils.DisposeMaterial(this.windowMaterial);
|
|
1826
|
+
}
|
|
1827
|
+
placeOnEdge(edge) {
|
|
1828
|
+
if (this.isCustom) {
|
|
1829
|
+
const checkMaterial = this._isWindow ? this.windowMaterial : this.doorMaterialFront;
|
|
1830
|
+
if (!checkMaterial) {
|
|
1831
|
+
this._createMaterials(THREE.DoubleSide);
|
|
1832
|
+
}
|
|
1833
|
+
this.createCustomMesh(this.getWidth(), this.getHeight());
|
|
1834
|
+
}
|
|
1835
|
+
super.placeOnEdge(edge);
|
|
1836
|
+
}
|
|
1837
|
+
/** */
|
|
1838
|
+
getWallOffset() {
|
|
1839
|
+
return -this.currentWallEdge.offset;
|
|
1840
|
+
}
|
|
1841
|
+
distanceFrom2d(x, y) {
|
|
1842
|
+
return Utils.pointDistanceFromLine(x, y, this.getStartX(), this.getStartY(), this.getEndX(), this.getEndY());
|
|
1843
|
+
}
|
|
1844
|
+
onWallUpdated(wall) {
|
|
1845
|
+
if (this.metadata.texture) {
|
|
1846
|
+
this.updateMaterialVisibility(wall.side);
|
|
1847
|
+
}
|
|
1848
|
+
}
|
|
1849
|
+
updateFrameColor(color) {
|
|
1850
|
+
this.frameColor = color;
|
|
1851
|
+
this.frameMaterial.color.setHex(color);
|
|
1852
|
+
this.frameMaterial.needsUpdate = true;
|
|
1853
|
+
// this.scene.needsUpdate = true;
|
|
1854
|
+
}
|
|
1855
|
+
updateDoorColor(color) {
|
|
1856
|
+
this.doorColor = color;
|
|
1857
|
+
this.doorMaterialFront.color.setHex(color);
|
|
1858
|
+
this.doorMaterialFront.transparent = false;
|
|
1859
|
+
this.doorMaterialFront.opacity = 1;
|
|
1860
|
+
this.doorMaterialFront.map = undefined;
|
|
1861
|
+
this.doorMaterialFront.needsUpdate = true;
|
|
1862
|
+
// this.scene.needsUpdate = true;
|
|
1863
|
+
}
|
|
1864
|
+
updateGlassMaterial() {
|
|
1865
|
+
if (!this.isGlass) {
|
|
1866
|
+
this.doorMaterialFront.color.setHex(0xdff0f2);
|
|
1867
|
+
this.doorMaterialFront.transparent = true;
|
|
1868
|
+
this.doorMaterialFront.alphaTest = 0;
|
|
1869
|
+
this.doorMaterialFront.opacity = 0.2;
|
|
1870
|
+
this.doorMaterialFront.map = undefined;
|
|
1871
|
+
this.doorMaterialFront.needsUpdate = true;
|
|
1872
|
+
this.doorMaterialFront.side = THREE.FrontSide;
|
|
1873
|
+
this.isGlass = true;
|
|
1874
|
+
this.customMesh.castShadow = false;
|
|
1875
|
+
}
|
|
1876
|
+
else {
|
|
1877
|
+
this.doorMaterialFront.transparent = false;
|
|
1878
|
+
this.doorMaterialFront.opacity = 1;
|
|
1879
|
+
this.isGlass = false;
|
|
1880
|
+
this.customMesh.castShadow = true;
|
|
1881
|
+
}
|
|
1882
|
+
}
|
|
1883
|
+
updateGeometry(width, height) {
|
|
1884
|
+
if (this.isCustom) {
|
|
1885
|
+
this.createCustomMesh(width, height);
|
|
1886
|
+
// this.calculateHalfSize();
|
|
1887
|
+
this.redrawWall();
|
|
1888
|
+
}
|
|
1889
|
+
else {
|
|
1890
|
+
super.updateGeometry(width, height);
|
|
1891
|
+
}
|
|
1892
|
+
}
|
|
1893
|
+
adjustWallBox(geometry) {
|
|
1894
|
+
geometry.getAttribute('position').needsUpdate = true;
|
|
1895
|
+
geometry.computeBoundingBox();
|
|
1896
|
+
geometry.applyMatrix4(new Matrix4().makeTranslation(-0.5 * (geometry.boundingBox.max.x + geometry.boundingBox.min.x), -0.5 * (geometry.boundingBox.max.y + geometry.boundingBox.min.y), -0.5 * (geometry.boundingBox.max.z + geometry.boundingBox.min.z)));
|
|
1897
|
+
geometry.computeBoundingBox();
|
|
1898
|
+
this.object.geometry = geometry;
|
|
1899
|
+
this.calculateHalfSize();
|
|
1900
|
+
}
|
|
1901
|
+
getVisibleMeshes() {
|
|
1902
|
+
if (this.isCustom && this.visible) {
|
|
1903
|
+
const meshes = [
|
|
1904
|
+
this.leftFrame,
|
|
1905
|
+
this.topFrame,
|
|
1906
|
+
this.rightFrame,
|
|
1907
|
+
this.customMesh
|
|
1908
|
+
];
|
|
1909
|
+
if (this._isWindow /*|| this._doorpost*/) {
|
|
1910
|
+
meshes.push(this.bottomFrame);
|
|
1911
|
+
}
|
|
1912
|
+
return meshes;
|
|
1913
|
+
}
|
|
1914
|
+
else {
|
|
1915
|
+
return super.getVisibleMeshes();
|
|
1916
|
+
}
|
|
1917
|
+
}
|
|
1918
|
+
createTextureMaterial(options) {
|
|
1919
|
+
const _super = Object.create(null, {
|
|
1920
|
+
createTextureMaterial: { get: () => super.createTextureMaterial }
|
|
1921
|
+
});
|
|
1922
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1923
|
+
if (this.isCustom) {
|
|
1924
|
+
const { side = THREE.DoubleSide, flip = false } = options || {};
|
|
1925
|
+
const checkMaterial = this._isWindow ? this.windowMaterial : this.doorMaterialFront;
|
|
1926
|
+
if (!checkMaterial) {
|
|
1927
|
+
this._createMaterials(side);
|
|
1928
|
+
}
|
|
1929
|
+
const texture = this.getTexture();
|
|
1930
|
+
if (!texture) {
|
|
1931
|
+
// reset to default texture
|
|
1932
|
+
this._createMaterials(side);
|
|
1933
|
+
this.createCustomMesh(this.getWidth(), this.getHeight());
|
|
1934
|
+
return this._isWindow ? this.windowMaterial : this.doorMaterialFront;
|
|
1935
|
+
}
|
|
1936
|
+
const material = this._isWindow ? this.windowMaterial : this.doorMaterialFront;
|
|
1937
|
+
const defaultMaterial = new THREE.MeshPhongMaterial();
|
|
1938
|
+
material.transparent = false;
|
|
1939
|
+
material.color = defaultMaterial.color.clone();
|
|
1940
|
+
material.opacity = defaultMaterial.opacity;
|
|
1941
|
+
material.refractionRatio = defaultMaterial.refractionRatio;
|
|
1942
|
+
material.shininess = defaultMaterial.shininess;
|
|
1943
|
+
material.specular = defaultMaterial.specular.clone();
|
|
1944
|
+
// Allows for transparency in png's
|
|
1945
|
+
material.alphaTest = 0.5;
|
|
1946
|
+
// Makes sure the image in only projected once on the mesh
|
|
1947
|
+
material.side = THREE.FrontSide;
|
|
1948
|
+
// Removes white edges surrounding the image
|
|
1949
|
+
material.transparent = true;
|
|
1950
|
+
// material.color = new THREE.Color(1, 1, 1);
|
|
1951
|
+
yield this.addMaterialMap(material, texture, flip);
|
|
1952
|
+
material.needsUpdate = true;
|
|
1953
|
+
return material;
|
|
1954
|
+
}
|
|
1955
|
+
else {
|
|
1956
|
+
return yield _super.createTextureMaterial.call(this, options);
|
|
1957
|
+
}
|
|
1958
|
+
});
|
|
1959
|
+
}
|
|
1960
|
+
createCustomMesh(width, height) {
|
|
1961
|
+
const halfWidth = width / 2;
|
|
1962
|
+
const halfFrame = (this._frameWidth / 2);
|
|
1963
|
+
this.leftFrame = this._createFrameSide(this._frameWidth, this._getHeightFrame(height), this._frameDepth);
|
|
1964
|
+
this.leftFrame.rotation.set(this._isWindow ? 180 * (Math.PI / 180) : 0, 0, 0);
|
|
1965
|
+
this.leftFrame.position.x = -halfWidth + halfFrame;
|
|
1966
|
+
this.leftFrame.name = 'leftFrame';
|
|
1967
|
+
if (!this._isWindow) {
|
|
1968
|
+
this.leftFrame.position.y = -(this._frameWidth / 2) + 0.02;
|
|
1969
|
+
}
|
|
1970
|
+
this.topFrame = this._createFrameSide(this._frameWidth, width, this._frameDepth);
|
|
1971
|
+
this.topFrame.rotation.set(0, this._isWindow ? 180 * (Math.PI / 180) : 0, -90 * (Math.PI / 180));
|
|
1972
|
+
this.topFrame.position.y = (height / 2) - (this._frameWidth / 2);
|
|
1973
|
+
this.topFrame.name = 'topFrame';
|
|
1974
|
+
this.rightFrame = this._createFrameSide(this._frameWidth, this._getHeightFrame(height), this._frameDepth);
|
|
1975
|
+
this.rightFrame.rotation.set(this._isWindow ? 180 * (Math.PI / 180) : 0, 0, -180 * (Math.PI / 180));
|
|
1976
|
+
this.rightFrame.position.x = (width / 2) - (this._frameWidth / 2);
|
|
1977
|
+
this.rightFrame.name = 'rightFrame';
|
|
1978
|
+
if (!this._isWindow) {
|
|
1979
|
+
this.rightFrame.position.y = -(this._frameWidth / 2) + 0.02;
|
|
1980
|
+
}
|
|
1981
|
+
if (this._isWindow /*|| this._doorpost*/) {
|
|
1982
|
+
this.bottomFrame = this._createFrameSide(this._frameWidth, width, this._frameDepth);
|
|
1983
|
+
this.bottomFrame.rotation.set(0, 180 * (Math.PI / 180), 90 * (Math.PI / 180));
|
|
1984
|
+
this.bottomFrame.position.y = -(height / 2) + (this._frameWidth / 2);
|
|
1985
|
+
this.bottomFrame.name = 'bottomFrame';
|
|
1986
|
+
}
|
|
1987
|
+
let customGeo;
|
|
1988
|
+
if (this._isWindow) {
|
|
1989
|
+
customGeo = new THREE.BoxGeometry(width - (2 * this._frameWidth) + 0.04, height - (2 * this._frameWidth) + 0.04, 0.024);
|
|
1990
|
+
}
|
|
1991
|
+
else {
|
|
1992
|
+
customGeo = new THREE.BoxGeometry(width - 0.02 * (this._frameWidth - 0.02), height - (this._frameWidth - 0.02), 0.04);
|
|
1993
|
+
}
|
|
1994
|
+
this.customMesh = new THREE.Mesh(customGeo, this._isWindow ? this.windowMaterial : this.doorMaterialFront);
|
|
1995
|
+
this.customMesh.castShadow = this._isWindow ? false : !this.isGlass;
|
|
1996
|
+
this.customMesh.renderOrder = -1;
|
|
1997
|
+
this.customMesh.name = 'customMesh';
|
|
1998
|
+
if (this._isWindow) {
|
|
1999
|
+
this.customMesh.name += 'Window';
|
|
2000
|
+
}
|
|
2001
|
+
if (this.isGlass) {
|
|
2002
|
+
this.customMesh.name += 'Glass';
|
|
2003
|
+
}
|
|
2004
|
+
if (this._isWindow) {
|
|
2005
|
+
this.customMesh.position.z = -0.012;
|
|
2006
|
+
}
|
|
2007
|
+
else {
|
|
2008
|
+
this.customMesh.position.y = -(this._frameWidth / 2) + 0.01;
|
|
2009
|
+
this.customMesh.position.z = 0.02;
|
|
2010
|
+
}
|
|
2011
|
+
this._getAdditionalTexture().then((frontAdditionalObj) => {
|
|
2012
|
+
if (frontAdditionalObj) {
|
|
2013
|
+
const backAdditionalObj = frontAdditionalObj.clone(true);
|
|
2014
|
+
backAdditionalObj.rotation.x = 180 * (Math.PI / 180);
|
|
2015
|
+
if (this.additionalTexture.data) {
|
|
2016
|
+
frontAdditionalObj.position.set(-(width / 2) + this.additionalTexture.data.x, -(height / 2) + this.additionalTexture.data.y, 0.02);
|
|
2017
|
+
backAdditionalObj.position.set(-(width / 2) + this.additionalTexture.data.x, -(height / 2) + this.additionalTexture.data.y, -0.02);
|
|
2018
|
+
}
|
|
2019
|
+
this.customMesh.add(frontAdditionalObj);
|
|
2020
|
+
this.customMesh.add(backAdditionalObj);
|
|
2021
|
+
}
|
|
2022
|
+
});
|
|
2023
|
+
this.children.length = 0;
|
|
2024
|
+
this.add(this.leftFrame, this.rightFrame, this.topFrame, this.customMesh);
|
|
2025
|
+
if (this._isWindow /*|| this._doorpost*/) {
|
|
2026
|
+
this.add(this.bottomFrame);
|
|
2027
|
+
}
|
|
2028
|
+
this.calculateHalfSize();
|
|
2029
|
+
// this.scene.needsUpdate = true;
|
|
2030
|
+
}
|
|
2031
|
+
cloneItem() {
|
|
2032
|
+
const clone = this.createClass();
|
|
2033
|
+
this.cloneProperties(clone);
|
|
2034
|
+
clone.name = 'test clone';
|
|
2035
|
+
return clone;
|
|
2036
|
+
}
|
|
2037
|
+
createMaterial(side = THREE.DoubleSide, isSame = true) {
|
|
2038
|
+
const _super = Object.create(null, {
|
|
2039
|
+
createTextureMaterial: { get: () => super.createTextureMaterial }
|
|
2040
|
+
});
|
|
2041
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
2042
|
+
if (this.isCustom) {
|
|
2043
|
+
yield this.createTextureMaterial({ side: THREE.FrontSide, flip: false });
|
|
2044
|
+
}
|
|
2045
|
+
else {
|
|
2046
|
+
yield _super.createTextureMaterial.call(this, { side, isSame });
|
|
2047
|
+
}
|
|
2048
|
+
});
|
|
2049
|
+
}
|
|
2050
|
+
createClass() {
|
|
2051
|
+
// create new object for proper dimensions
|
|
2052
|
+
const mesh = new Mesh(new BoxGeometry(this.halfSize.x * 2, this.halfSize.y * 2, this.halfSize.z * 2));
|
|
2053
|
+
return new InWallItem(this.metadata, mesh);
|
|
2054
|
+
}
|
|
2055
|
+
cloneProperties(clone) {
|
|
2056
|
+
clone.userData = this.userData;
|
|
2057
|
+
clone.doorMaterialFront = this.doorMaterialFront ? this.doorMaterialFront.clone() : undefined;
|
|
2058
|
+
if (clone.doorMaterialFront) {
|
|
2059
|
+
clone.doorMaterialFront.emissive = new THREE.Color(0x000000);
|
|
2060
|
+
clone.doorMaterialFront.needsUpdate = true;
|
|
2061
|
+
}
|
|
2062
|
+
clone.windowMaterial = this.windowMaterial ? this.windowMaterial.clone() : undefined;
|
|
2063
|
+
if (clone.windowMaterial) {
|
|
2064
|
+
clone.windowMaterial.emissive = new THREE.Color(0x000000);
|
|
2065
|
+
clone.windowMaterial.needsUpdate = true;
|
|
2066
|
+
}
|
|
2067
|
+
clone.frameMaterial = this.frameMaterial ? this.frameMaterial.clone() : undefined;
|
|
2068
|
+
if (clone.frameMaterial) {
|
|
2069
|
+
clone.frameMaterial.emissive = new THREE.Color(0x000000);
|
|
2070
|
+
clone.frameMaterial.needsUpdate = true;
|
|
2071
|
+
}
|
|
2072
|
+
clone.frameColor = this.frameColor;
|
|
2073
|
+
clone.doorColor = this.doorColor;
|
|
2074
|
+
clone.object.material = [clone.frameMaterial, clone._isWindow ? clone.windowMaterial : clone.doorMaterialFront];
|
|
2075
|
+
clone.texture = this.texture;
|
|
2076
|
+
clone.additionalTexture = this.additionalTexture;
|
|
2077
|
+
clone.isGlass = this.isGlass;
|
|
2078
|
+
}
|
|
2079
|
+
getMaterials(textureMaterialFront, textureMaterialBack) {
|
|
2080
|
+
if (this.isCustom) {
|
|
2081
|
+
return this.object.material;
|
|
2082
|
+
}
|
|
2083
|
+
else {
|
|
2084
|
+
return super.getMaterials(textureMaterialFront, textureMaterialBack);
|
|
2085
|
+
}
|
|
2086
|
+
}
|
|
2087
|
+
getMaterialMapDimensions() {
|
|
2088
|
+
if (this.isCustom) {
|
|
2089
|
+
return new THREE.Vector2(this.getWidth() - 0.14, this.getHeight() - 0.07);
|
|
2090
|
+
}
|
|
2091
|
+
else {
|
|
2092
|
+
return super.getMaterialMapDimensions();
|
|
2093
|
+
}
|
|
2094
|
+
}
|
|
2095
|
+
initiateItemObject(data) {
|
|
2096
|
+
if (this.isCustom && data && data.geometry) {
|
|
2097
|
+
data.geometry.verticesNeedUpdate = true;
|
|
2098
|
+
data.geometry.computeBoundingBox();
|
|
2099
|
+
data.geometry.applyMatrix4(new Matrix4().makeTranslation(-0.5 * (data.geometry.boundingBox.max.x + data.geometry.boundingBox.min.x), -0.5 * (data.geometry.boundingBox.max.y + data.geometry.boundingBox.min.y), -0.5 * (data.geometry.boundingBox.max.z + data.geometry.boundingBox.min.z)));
|
|
2100
|
+
data.geometry.computeBoundingBox();
|
|
2101
|
+
const max = data.geometry.boundingBox.max.clone();
|
|
2102
|
+
const min = data.geometry.boundingBox.min.clone();
|
|
2103
|
+
this.halfSize = max.sub(min).divideScalar(2);
|
|
2104
|
+
}
|
|
2105
|
+
}
|
|
2106
|
+
_setDefault() {
|
|
2107
|
+
// workaround because properties are not available yet when creating window/door from loading from cloud/local
|
|
2108
|
+
this.frameColor = this.metadata.frameColor ? this.metadata.frameColor : this._defaultFrameColor; // RAL-1011
|
|
2109
|
+
this.doorColor = this.metadata.doorColor ? this.metadata.doorColor : this._defaultDoorColor; // RAL-9010
|
|
2110
|
+
this.windowColor = this.metadata.windowColor ? this.metadata.windowColor : new THREE.Color(0xdff0f2);
|
|
2111
|
+
this._isWindow = this.metadata.itemType === ItemType.InWall;
|
|
2112
|
+
this._doorpost = this.metadata.doorpost;
|
|
2113
|
+
this.isGlass = this.metadata.isGlass ? this.metadata.isGlass : false;
|
|
2114
|
+
}
|
|
2115
|
+
_createMaterials(side) {
|
|
2116
|
+
this._setDefault();
|
|
2117
|
+
this.frameMaterial = new THREE.MeshPhongMaterial({ side: side, name: 'frameMaterial' });
|
|
2118
|
+
this.frameMaterial.color = new THREE.Color(this.frameColor);
|
|
2119
|
+
if (this._isWindow) {
|
|
2120
|
+
this.windowMaterial = new THREE.MeshPhongMaterial({ side: side, color: this.windowColor, name: 'windowMaterial' });
|
|
2121
|
+
this.windowMaterial.transparent = true;
|
|
2122
|
+
this.windowMaterial.alphaTest = 0;
|
|
2123
|
+
this.windowMaterial.opacity = 0.2;
|
|
2124
|
+
this.windowMaterial.map = undefined;
|
|
2125
|
+
this.windowMaterial.needsUpdate = true;
|
|
2126
|
+
this.windowMaterial.side = THREE.FrontSide;
|
|
2127
|
+
this.object.material = [this.frameMaterial, this.windowMaterial];
|
|
2128
|
+
}
|
|
2129
|
+
else {
|
|
2130
|
+
this.doorMaterialFront = new THREE.MeshPhongMaterial({ side: side, name: 'doorMaterialFront' });
|
|
2131
|
+
this.doorMaterialFront.color = new THREE.Color(this.doorColor);
|
|
2132
|
+
if (this._doorpost) {
|
|
2133
|
+
this.doorMaterialFront.transparent = true;
|
|
2134
|
+
this.doorMaterialFront.opacity = 0;
|
|
2135
|
+
}
|
|
2136
|
+
this.object.material = [this.frameMaterial, this.doorMaterialFront];
|
|
2137
|
+
}
|
|
2138
|
+
}
|
|
2139
|
+
_getHeightFrame(height) {
|
|
2140
|
+
return height - (this._isWindow ? 2 * (this._frameWidth - 0.02) : this._frameWidth - 0.02);
|
|
2141
|
+
}
|
|
2142
|
+
_createFrameSide(width, height, depth) {
|
|
2143
|
+
const outerFrameWidth = width - 0.02;
|
|
2144
|
+
const outerFrameGeo = new THREE.BoxGeometry(outerFrameWidth, height, depth);
|
|
2145
|
+
const outerFrame = new THREE.Mesh(outerFrameGeo, this.frameMaterial);
|
|
2146
|
+
outerFrame.castShadow = true;
|
|
2147
|
+
outerFrame.receiveShadow = true;
|
|
2148
|
+
const innerFrameGeo = new THREE.BoxGeometry(0.02, height, depth / 2);
|
|
2149
|
+
const innerFrame = new THREE.Mesh(innerFrameGeo, this.frameMaterial);
|
|
2150
|
+
innerFrame.castShadow = true;
|
|
2151
|
+
innerFrame.receiveShadow = true;
|
|
2152
|
+
innerFrame.position.x = (outerFrameWidth / 2) + 0.01;
|
|
2153
|
+
innerFrame.position.z = -depth / 4;
|
|
2154
|
+
const frameSide = new THREE.Object3D();
|
|
2155
|
+
frameSide.add(outerFrame, innerFrame);
|
|
2156
|
+
const boundingBox = new THREE.Box3().setFromObject(frameSide);
|
|
2157
|
+
const bbCenterPivot = new THREE.Vector3();
|
|
2158
|
+
boundingBox.getCenter(bbCenterPivot);
|
|
2159
|
+
const delta = new THREE.Vector3().sub(bbCenterPivot).setY(0);
|
|
2160
|
+
frameSide.children.forEach((child) => {
|
|
2161
|
+
child.position.add(delta);
|
|
2162
|
+
});
|
|
2163
|
+
const frameSideMesh = new Mesh();
|
|
2164
|
+
frameSideMesh.add(outerFrame, innerFrame);
|
|
2165
|
+
return frameSideMesh;
|
|
2166
|
+
}
|
|
2167
|
+
_getAdditionalTexture() {
|
|
2168
|
+
return new Promise((resolve, reject) => {
|
|
2169
|
+
// if (this.additionalTexture) {
|
|
2170
|
+
// LoaderUtils.LoadObjModel(this.additionalTexture.url).then((obj: THREE.Mesh) => {
|
|
2171
|
+
// const additionalObj: THREE.Mesh = <Mesh>obj.clone(true);
|
|
2172
|
+
// additionalObj.children.map(c => c.position.set(0, 0, 0));
|
|
2173
|
+
// if (this.additionalTexture.scale) {
|
|
2174
|
+
// additionalObj.scale.multiplyScalar(this.additionalTexture.scale);
|
|
2175
|
+
// }
|
|
2176
|
+
// resolve(additionalObj);
|
|
2177
|
+
// });
|
|
2178
|
+
// } else {
|
|
2179
|
+
resolve(null);
|
|
2180
|
+
// }
|
|
2181
|
+
});
|
|
2182
|
+
}
|
|
2183
|
+
_glassMaterialCheck() {
|
|
2184
|
+
let meshesFound = 0;
|
|
2185
|
+
this.traverse((child) => {
|
|
2186
|
+
if (child instanceof Mesh && child.material) {
|
|
2187
|
+
meshesFound++;
|
|
2188
|
+
child.castShadow = true;
|
|
2189
|
+
const materials = !Array.isArray(child.material) ? [child.material] : child.material;
|
|
2190
|
+
materials.forEach(material => {
|
|
2191
|
+
if (material.name && (material.name === 'Fixed_Glass' || material.name === 'Default_Glass')) {
|
|
2192
|
+
child.castShadow = false;
|
|
2193
|
+
material.transparent = true;
|
|
2194
|
+
material.opacity = 0.2;
|
|
2195
|
+
material.format = THREE.RGBAFormat;
|
|
2196
|
+
material.needsUpdate = true;
|
|
2197
|
+
}
|
|
2198
|
+
});
|
|
2199
|
+
}
|
|
2200
|
+
});
|
|
2201
|
+
// Remove to ignore old door models
|
|
2202
|
+
if (meshesFound === 1) {
|
|
2203
|
+
this.traverse((child) => {
|
|
2204
|
+
if (child instanceof Mesh) {
|
|
2205
|
+
child.castShadow = true;
|
|
2206
|
+
const materials = !Array.isArray(child.material) ? [child.material] : child.material;
|
|
2207
|
+
materials.forEach(m => {
|
|
2208
|
+
m.visible = m.name && (m.name === 'Fixed_Glass' || m.name === 'Default_Glass') ? m.visible = false : m.visible = true;
|
|
2209
|
+
});
|
|
2210
|
+
}
|
|
2211
|
+
});
|
|
2212
|
+
}
|
|
2213
|
+
}
|
|
2214
|
+
}
|
|
2215
|
+
export class WallItemGroup extends ItemGroup {
|
|
2216
|
+
constructor() {
|
|
2217
|
+
super();
|
|
2218
|
+
this.elevationAdjustable = true;
|
|
2219
|
+
this._positionYTolerance = 0.005;
|
|
2220
|
+
this._wallOffsetScalar = 0;
|
|
2221
|
+
this._sizeX = 0;
|
|
2222
|
+
this._sizeY = 0;
|
|
2223
|
+
this._refVec = new THREE.Vector2(0, 1.0);
|
|
2224
|
+
this.metadata = {
|
|
2225
|
+
itemType: 22
|
|
2226
|
+
};
|
|
2227
|
+
this.userData.itemType = this.metadata.itemType;
|
|
2228
|
+
}
|
|
2229
|
+
redrawWall() {
|
|
2230
|
+
if (this.currentWallEdge && this.currentWallEdge.wall) {
|
|
2231
|
+
this.currentWallEdge.wall.fireRedraw();
|
|
2232
|
+
}
|
|
2233
|
+
}
|
|
2234
|
+
isValidPosition(position, rotation, options) {
|
|
2235
|
+
return { valid: true };
|
|
2236
|
+
}
|
|
2237
|
+
moveToPosition(vec3, intersection) {
|
|
2238
|
+
if (intersection) {
|
|
2239
|
+
if (!this.currentWallEdge && this.items[0].currentWallEdge) {
|
|
2240
|
+
this.currentWallEdge = this.items[0].currentWallEdge;
|
|
2241
|
+
}
|
|
2242
|
+
if (this.currentWallEdge) {
|
|
2243
|
+
this._boundMove(vec3);
|
|
2244
|
+
this.position.copy(vec3);
|
|
2245
|
+
this.redrawWall();
|
|
2246
|
+
}
|
|
2247
|
+
}
|
|
2248
|
+
}
|
|
2249
|
+
createBoundaryBox() {
|
|
2250
|
+
this.boundaryBox.setFromObject(this);
|
|
2251
|
+
const max = this.boundaryBox.max.clone();
|
|
2252
|
+
const min = this.boundaryBox.min.clone();
|
|
2253
|
+
this.halfSize = max.sub(min).divideScalar(2);
|
|
2254
|
+
this.updateSize();
|
|
2255
|
+
}
|
|
2256
|
+
centerPivot() {
|
|
2257
|
+
const boundaryBoxCenter = this.boundaryBoxCenter;
|
|
2258
|
+
this.position.copy(boundaryBoxCenter);
|
|
2259
|
+
this.items.forEach(i => {
|
|
2260
|
+
const originalPosition = i.position.clone();
|
|
2261
|
+
const newPosition = originalPosition.sub(boundaryBoxCenter);
|
|
2262
|
+
i.position.copy(newPosition);
|
|
2263
|
+
});
|
|
2264
|
+
}
|
|
2265
|
+
updateSize() {
|
|
2266
|
+
this._wallOffsetScalar = this.halfSize.z;
|
|
2267
|
+
this._sizeX = this.halfSize.x * 2;
|
|
2268
|
+
this._sizeY = this.halfSize.y * 2;
|
|
2269
|
+
}
|
|
2270
|
+
onWallMoved(wall) {
|
|
2271
|
+
if (wall.frontEdge) {
|
|
2272
|
+
this.placeOnEdge(wall.frontEdge);
|
|
2273
|
+
}
|
|
2274
|
+
if (wall.backEdge) {
|
|
2275
|
+
this.placeOnEdge(wall.backEdge);
|
|
2276
|
+
}
|
|
2277
|
+
}
|
|
2278
|
+
placeOnEdge(edge) {
|
|
2279
|
+
this._originalRotation = this.rotation.clone();
|
|
2280
|
+
if (!edge) {
|
|
2281
|
+
return;
|
|
2282
|
+
}
|
|
2283
|
+
this._onFrontSide = edge.wall.frontEdge === edge;
|
|
2284
|
+
this._changeWallEdge(edge);
|
|
2285
|
+
const newPos = edge.wall.amountWallMoved ? this.position.add(new Vector3(edge.wall.amountWallMoved.x, 0, 0)) : this.position.clone();
|
|
2286
|
+
this._boundMove(newPos);
|
|
2287
|
+
this.position.copy(newPos);
|
|
2288
|
+
this.redrawWall();
|
|
2289
|
+
this.allowRotate = false;
|
|
2290
|
+
}
|
|
2291
|
+
handleGroupCreation() {
|
|
2292
|
+
this.items.forEach((i) => {
|
|
2293
|
+
if (!this.currentWallEdge) {
|
|
2294
|
+
this.currentWallEdge = i.currentWallEdge;
|
|
2295
|
+
this.currentWall = this.currentWallEdge.wall;
|
|
2296
|
+
}
|
|
2297
|
+
this.currentWall.removeOnItem(i);
|
|
2298
|
+
});
|
|
2299
|
+
this.placeOnEdge(this.currentWallEdge);
|
|
2300
|
+
}
|
|
2301
|
+
_changeWallEdge(wallEdge) {
|
|
2302
|
+
// find angle between wall normals
|
|
2303
|
+
const normal2 = new THREE.Vector2();
|
|
2304
|
+
const normal3 = Utils.GetFaceNormalFromBufferGeometry(wallEdge.plane.geometry, 0, 0);
|
|
2305
|
+
normal2.x = normal3.x;
|
|
2306
|
+
normal2.y = normal3.z;
|
|
2307
|
+
const wallRotation = Utils.angle(this._refVec.x, this._refVec.y, normal2.x, normal2.y);
|
|
2308
|
+
// transfer rotation from child to parent and reset boundary box
|
|
2309
|
+
if (this.items[0].rotation.y !== 0) {
|
|
2310
|
+
this.items.forEach((i) => {
|
|
2311
|
+
const itemWorldPosition = i.getWorldPosition(new Vector3());
|
|
2312
|
+
this.remove(i);
|
|
2313
|
+
this.rotation.y = wallRotation;
|
|
2314
|
+
i.position.copy(itemWorldPosition);
|
|
2315
|
+
this.attach(i);
|
|
2316
|
+
this.rotation.y = 0;
|
|
2317
|
+
});
|
|
2318
|
+
this.createBoundaryBox();
|
|
2319
|
+
}
|
|
2320
|
+
this.rotation.y = wallRotation;
|
|
2321
|
+
this.traverse(c => c.matrixWorldNeedsUpdate = true);
|
|
2322
|
+
// update currentWall
|
|
2323
|
+
this.currentWall = wallEdge.wall;
|
|
2324
|
+
this.currentWallEdge = wallEdge;
|
|
2325
|
+
wallEdge.wall.addOnItem(this);
|
|
2326
|
+
}
|
|
2327
|
+
updateEdgeVisibility(edge) {
|
|
2328
|
+
if (this.currentWall) {
|
|
2329
|
+
let shouldShow = false;
|
|
2330
|
+
if (this.currentWall.backEdge) {
|
|
2331
|
+
this.currentWall.backEdge.edges.forEach((e) => {
|
|
2332
|
+
if (e.visible) {
|
|
2333
|
+
shouldShow = true;
|
|
2334
|
+
}
|
|
2335
|
+
});
|
|
2336
|
+
}
|
|
2337
|
+
if (this.currentWall.frontEdge) {
|
|
2338
|
+
this.currentWall.frontEdge.edges.forEach(e => {
|
|
2339
|
+
if (e.visible) {
|
|
2340
|
+
shouldShow = true;
|
|
2341
|
+
}
|
|
2342
|
+
});
|
|
2343
|
+
}
|
|
2344
|
+
this.visible = shouldShow;
|
|
2345
|
+
}
|
|
2346
|
+
}
|
|
2347
|
+
_boundMove(vec3) {
|
|
2348
|
+
const edge = this.currentWallEdge;
|
|
2349
|
+
vec3.applyMatrix4(edge.interiorTransform);
|
|
2350
|
+
edge.wall.itemsChanged = true;
|
|
2351
|
+
if (vec3.x < this._sizeX / 2.0 + this._positionYTolerance) {
|
|
2352
|
+
vec3.x = this._sizeX / 2.0 + this._positionYTolerance;
|
|
2353
|
+
}
|
|
2354
|
+
else if (vec3.x > (edge.interiorDistance() - this._sizeX / 2.0 - this._positionYTolerance)) {
|
|
2355
|
+
vec3.x = edge.interiorDistance() - this._sizeX / 2.0 - this._positionYTolerance;
|
|
2356
|
+
}
|
|
2357
|
+
if (this.elevationFixed || !this.elevationAdjustable) {
|
|
2358
|
+
vec3.y = this.position.y;
|
|
2359
|
+
}
|
|
2360
|
+
else {
|
|
2361
|
+
const maxY = this._getMaxY(edge);
|
|
2362
|
+
const minY = this._getMinY();
|
|
2363
|
+
if (vec3.y < minY) {
|
|
2364
|
+
vec3.y = minY;
|
|
2365
|
+
}
|
|
2366
|
+
else if (vec3.y > maxY) {
|
|
2367
|
+
vec3.y = maxY;
|
|
2368
|
+
}
|
|
2369
|
+
this.elevation = vec3.y - this.halfSize.y;
|
|
2370
|
+
}
|
|
2371
|
+
vec3.z = this._wallOffsetScalar;
|
|
2372
|
+
vec3.applyMatrix4(edge.invInteriorTransform);
|
|
2373
|
+
}
|
|
2374
|
+
_getMaxY(edge) {
|
|
2375
|
+
return edge.height - this.halfSize.y - this._positionYTolerance;
|
|
2376
|
+
}
|
|
2377
|
+
_getMinY() {
|
|
2378
|
+
return this.halfSize.y + this._positionYTolerance;
|
|
2379
|
+
}
|
|
2380
|
+
}
|
|
2381
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2FsbC1vYmplY3RzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2NsaWVudC9hcHAvcGx1Z2lucy9jb3JlM2QvaXRlbXMvd2FsbC1vYmplY3RzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7OztBQUFBLE9BQU8sRUFDSCxXQUFXLEVBQ1gsZUFBZSxFQUNmLGNBQWMsRUFDZCxLQUFLLEVBQUUsVUFBVSxFQUNqQixPQUFPLEVBQ1AsSUFBSSxFQUNKLGlCQUFpQixFQUNqQixvQkFBb0IsRUFBa0MsSUFBSSxFQUMxRCxVQUFVLEVBQUUsS0FBSyxFQUFFLGFBQWEsRUFBRSxjQUFjLEVBQ2hELE9BQU8sRUFDUCxPQUFPLEVBQ1YsTUFBTSxPQUFPLENBQUM7QUFDZixPQUFPLEtBQUssS0FBSyxNQUFNLE9BQU8sQ0FBQztBQUMvQixPQUFPLEVBQUMsWUFBWSxFQUFVLE1BQU0sNkJBQTZCLENBQUM7QUFDbEUsT0FBTyxFQUFDLElBQUksRUFBQyxNQUFNLFFBQVEsQ0FBQztBQUM1QixPQUFPLEVBQUMsS0FBSyxFQUFDLE1BQU0sZUFBZSxDQUFDO0FBQ3BDLE9BQU8sRUFBQyxnQkFBZ0IsRUFBRSxnQkFBZ0IsRUFBQyxNQUFNLDJEQUEyRCxDQUFDO0FBQzdHLE9BQU8sRUFBQyxTQUFTLEVBQUMsTUFBTSxjQUFjLENBQUM7QUFDdkMsT0FBTyxFQUFDLE1BQU0sRUFBQyxNQUFNLCtDQUErQyxDQUFDO0FBQ3JFLE9BQU8sRUFBQyxXQUFXLEVBQUMsTUFBTSxrQ0FBa0MsQ0FBQztBQUM3RCxPQUFPLEVBQUMsYUFBYSxFQUFDLE1BQU0sb0NBQW9DLENBQUM7QUFFakUsT0FBTyxFQUFDLFFBQVEsRUFBQyxNQUFNLGFBQWEsQ0FBQztBQUVyQyxPQUFPLEtBQUssUUFBUSxNQUFNLG1CQUFtQixDQUFDO0FBQzlDLE9BQU8sRUFBQyxTQUFTLEVBQUMsTUFBTSxjQUFjLENBQUM7QUFJdkM7Ozs7R0FJRztBQUNILE1B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LENBQUMsZUFBZSxDQUFDLE1BQU0sQ0FBQyxFQUFFLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUN6RyxJQUFJLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsR0FBRyxHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUUsR0FBRyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztRQUM5RSxJQUFJLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxTQUFTLEdBQUcsU0FBUyxDQUFDO1FBQ25ELElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxHQUFHLFdBQVcsQ0FBQztRQUNsQyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRTtZQUNqQixJQUFJLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksQ0FBQyxXQUFXLEdBQUcsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDO1NBQzlEO1FBRUQsSUFBSSxDQUFDLFFBQVEsR0FBRyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxLQUFLLEVBQUUsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDO1FBQ2pGLElBQUksQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsR0FBRyxHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUUsR0FBRyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUUsR0FBRyxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBQ2pHLElBQUksQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLENBQUMsR0FBRyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxXQUFX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bUJBQW1CLENBQUM7SUFDcEUsQ0FBQztJQUVPLFFBQVE7UUFDWixPQUFPLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxtQkFBbUIsQ0FBQztJQUN0RCxDQUFDO0NBQ0oiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xyXG4gICAgQm94R2VvbWV0cnksXHJcbiAgICBCdWZmZXJBdHRyaWJ1dGUsXHJcbiAgICBCdWZmZXJHZW9tZXRyeSxcclxuICAgIENvbG9yLCBEb3VibGVTaWRlLCBFdWxlciwgSW50ZXJzZWN0aW9uLCBNYXRlcmlhbCxcclxuICAgIE1hdHJpeDQsXHJcbiAgICBNZXNoLFxyXG4gICAgTWVzaEJhc2ljTWF0ZXJpYWwsIE1lc2hQaG9uZ01hdGVyaWFsLFxyXG4gICAgTWVzaFBoeXNpY2FsTWF0ZXJpYWwsIE1lc2hTdGFuZGFyZE1hdGVyaWFsLCBPYmplY3QzRCwgUGF0aCxcclxuICAgIFF1YXRlcm5pb24sIFNoYXBlLCBTaGFwZUdlb21ldHJ5LCBTUkdCQ29sb3JTcGFjZSxcclxuICAgIFZlY3RvcjIsXHJcbiAgICBWZWN0b3IzXHJcbn0gZnJvbSAndGhyZWUnO1xyXG5pbXBvcnQgKiBhcyBUSFJFRSBmcm9tICd0aHJlZSc7XHJcbmltcG9ydCB7c2FtZVRleHR1cmVzLCBUZXh0dXJlfSBmcm9tICcuLi8uLi8uLi9jb3JlL21vZGVsL3RleHR1cmUnO1xyXG5pbXBvcnQge0l0ZW19IGZyb20gJy4vaXRlbSc7XHJcbmltcG9ydCB7VXRpbHN9IGZyb20gJy4uL2NvcmUvdXRpbHMnO1xyXG5pbXBvcnQge2RlZmF1bHRFZGdlQ29sb3IsIGRlZmF1bHRXYWxsQ29sb3J9IGZyb20gJy4uLy4uL3Jvb20tcGxhbm5lci9jb21wb25lbnRzL2Zsb29ycGxhbm5lci9jb25zdC9kZWZhdWx0cyc7XHJcbmltcG9ydCB7VGhyZWVNZXNofSBmcm9tICcuL3RocmVlLW1lc2gnO1xyXG5pbXBvcnQge2lzTmlsbH0gZnJvbSAnLi4vLi4vLi4vY29yZS91dGlscy9mdW5jdGlvbi9pcy1uaWxsLmZ1bmN0aW9uJztcclxuaW1wb3J0IHtUZXh0dXJlVHlwZX0gZnJvbSAnLi4vLi4vLi4vY29yZS9tb2RlbC90ZXh0dXJlLXR5cGUnO1xyXG5pbXBvcnQge01hdGVyaWFsVXRpbHN9IGZyb20gJy4uLy4uLy4uL2NvcmUvdXRpbHMvbWF0ZXJpYWwudXRpbHMnO1xyXG5pbXBvcnQge01ldGFkYXRhfSBmcm9tICcuL21ldGFkYXRhJztcclxuaW1wb3J0IHtJdGVtVHlwZX0gZnJvbSAnLi9pdGVtLXR5cGUnO1xyXG5pbXBvcnQge0NvbGxpc2lvbkluZm99IGZyb20gJy4uL21vZGVsL2NvbGxpc2lvbi1pbmZvJztcclxuaW1wb3J0ICogYXMgR2VvbWV0cnkgZnJvbSAnLi4vbW9kZWwvZ2VvbWV0cnknO1xyXG5pbXBvcnQge0l0ZW1Hcm91cH0gZnJvbSAnLi9pdGVtLWdyb3VwJztcclxuaW1wb3J0IHtPdXRwdXRFbmNvZGluZ30gZnJvbSAnLi4vLi4vLi4vY29yZS9lbnVtL291dHB1dC1lbmNvZGluZy5lbnVtJztcclxuaW1wb3J0IHtGbG9vclBsYW5lSXRlbX0gZnJvbSAnLi9mbG9vci1wbGFuZS1pdGVtJztcclxuXHJcbi8qKlxyXG4gKiBBIFdhbGwgaXMgdGhlIGJhc2ljIGVsZW1lbnQgdG8gY3JlYXRlIFJvb21zLlxyXG4gKlxyXG4gKiBXYWxscyBjb25zaXN0cyBvZiB0d28gaGFsZiBlZGdlcy5cclxuICovXHJcbmV4cG9ydCBjbGFzcyBXYWxsIHtcclxuXHJcbiAgICAvKiogVGhlIHVuaXF1ZSBpZCBvZiBlYWNoIHdhbGwuICovXHJcbiAgICBwcml2YXRlIGlkOiBzdHJpbmc7XHJcblxyXG4gICAgLyoqIEZyb250IGlzIHRoZSBwbGFuZSBmcm9tIHN0YXJ0IHRvIGVuZC4gKi9cclxuICAgIHB1YmxpYyBmcm9udEVkZ2U6IEhhbGZFZGdlID0gbnVsbDtcclxuXHJcbiAgICAvKiogQmFjayBpcyB0aGUgcGxhbmUgZnJvbSBlbmQgdG8gc3RhcnQuICovXHJcbiAgICBwdWJsaWMgYmFja0VkZ2U6IEhhbGZFZGdlID0gbnVsbDtcclxuXHJcbiAgICAvKiogKi9cclxuICAgIHB1YmxpYyBvcnBoYW4gPSBmYWxzZTtcclxuXHJcbiAgICAvKiogSXRlbXMgYXR0YWNoZWQgdG8gdGhpcyB3YWxsICovXHJcbiAgICBwdWJsaWMgaXRlbXM6IEl0ZW1bXSA9IFtdO1xyXG4gICAgcHVibGljIGl0ZW1zQ2hhbmdlZCA9IGZhbHNlO1xyXG5cclxuICAgIC8qKiAqL1xyXG4gICAgcHVibGljIG9uSXRlbXM6IEl0ZW1bXSA9IFtdO1xyXG5cclxuICAgIC8qKiBUaGUgZnJvbnQtc2lkZSB0ZXh0dXJlLiAqL1xyXG4gICAgcHVibGljIGZyb250VGV4dHVyZTogVGV4dHVyZTtcclxuXHJcbiAgICAvKiogVGhlIGJhY2stc2lkZSB0ZXh0dXJlLiAqL1xyXG4gICAgcHVibGljIGJhY2tUZXh0dXJlOiBUZXh0dXJlO1xyXG5cclxuICAgIC8qKiBUaGUgZnJvbnQtc2lkZSBjb2xvci4gKi9cclxuICAgIHB1YmxpYyBmcm9udENvbG9yID0gZGVmYXVsdFdhbGxDb2xvcjtcclxuXHJcbiAgICAvKiogVGhlIGJhY2stc2lkZSBjb2xvci4gKi9cclxuICAgIHB1YmxpYyBiYWNrQ29sb3IgPSBkZWZhdWx0V2FsbENvbG9yO1xyXG5cclxuICAgIHB1YmxpYyB0aGlja25lc3M7XHJcblxyXG4gICAgcHVibGljIHNldCBoZWlnaHQodmFsdWU6IG51bWJlcikge1xyXG4gICAgICAgIHRoaXMuX2hlaWdodCA9IHZhbHVlO1xyXG4gICAgICAgIGlmICh0aGlzLmZyb250RWRnZSkge1xyXG4gICAgICAgICAgICB0aGlzLmZyb250RWRnZS5oZWlnaHQgPSB0aGlzLl9oZWlnaHQ7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGlmICh0aGlzLmJhY2tFZGdlKSB7XHJcbiAgICAgICAgICAgIHRoaXMuYmFja0VkZ2UuaGVpZ2h0ID0gdGhpcy5faGVpZ2h0O1xyXG4gICAgICAgIH1cclxuICAgICAgICB0aGlzLml0ZW1zLmZvckVhY2goKGl0ZW06IFdhbGxJdGVtKSA9PiBpdGVtLnJlcG9zaXRpb24oKSk7XHJcbiAgICAgICAgdGhpcy5vbkl0ZW1zLmZvckVhY2goKGl0ZW06IFdhbGxJdGVtKSA9PiBpdGVtLnJlcG9zaXRpb24oKSk7XHJcbiAgICB9XHJcblxyXG4gICAgcHVibGljIGdldCBoZWlnaHQoKTogbnVtYmVyIHtcclxuICAgICAgICByZXR1cm4gdGhpcy5faGVpZ2h0O1xyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyBhbW91bnRXYWxsTW92ZWQ6IFZlY3RvcjI7XHJcblxyXG4gICAgcHJpdmF0ZSBfaGVpZ2h0OiBudW1iZXI7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBDb25zdHJ1Y3RzIGEgbmV3IHdhbGwuXHJcbiAgICAgKiBAcGFyYW0gc3RhcnQgU3RhcnQgY29ybmVyLlxyXG4gICAgICogQHBhcmFtIGVuZCBFbmQgY29ybmVyLlxyXG4gICAgICovXHJcbiAgICBjb25zdHJ1Y3Rvcihwcml2YXRlIHN0YXJ0OiBDb3JuZXIsIHByaXZhdGUgZW5kOiBDb3JuZXIpIHtcclxuICAgICAgICB0aGlzLmlkID0gdGhpcy5nZXRVdWlkKCk7XHJcblxyXG4gICAgICAgIHRoaXMuc3RhcnQuYXR0YWNoU3RhcnQodGhpcyk7XHJcbiAgICAgICAgdGhpcy5lbmQuYXR0YWNoRW5kKHRoaXMpO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgZ2V0VXVpZCgpOiBzdHJpbmcge1xyXG4gICAgICAgIHJldHVybiBbdGhpcy5zdGFydC5pZCwgdGhpcy5lbmQuaWRdLmpvaW4oKTtcclxuICAgIH1cclxuXHJcbiAgICBwdWJsaWMgc2hvd0hpZGVXYWxsKHNob3c6IGJvb2xlYW4pOiB2b2lkIHtcclxuICAgICAgICBpZiAodGhpcy5mcm9udEVkZ2UpIHsgdGhpcy5mcm9udEVkZ2Uuc2hvd0hpZGVFZGdlKHNob3cpOyB9XHJcbiAgICAgICAgaWYgKHRoaXMuYmFja0VkZ2UpIHsgdGhpcy5iYWNrRWRnZS5zaG93SGlkZUVkZ2Uoc2hvdyk7IH1cclxuICAgIH1cclxuXHJcbiAgICBwdWJsaWMgcmVzZXRGcm9udEJhY2soKSB7XHJcbiAgICAgICAgaWYgKHRoaXMuZnJvbnRFZGdlKSB7IHRoaXMuZnJvbnRFZGdlLmRpc3Bvc2VQbGFuZSgpOyB9XHJcbiAgICAgICAgaWYgKHRoaXMuYmFja0VkZ2UpIHsgdGhpcy5iYWNrRWRnZS5kaXNwb3NlUGxhbmUoKTsgfVxyXG4gICAgICAgIHRoaXMuZnJvbnRFZGdlID0gbnVsbDtcclxuICAgICAgICB0aGlzLmJhY2tFZGdlID0gbnVsbDtcclxuICAgICAgICB0aGlzLm9ycGhhbiA9IGZhbHNlO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgbW92ZSh4OiBudW1iZXIsIHk6IG51bWJlcikge1xyXG4gICAgICAgIGlmICghdGhpcy5hbW91bnRXYWxsTW92ZWQpIHtcclxuICAgICAgICAgICAgdGhpcy5hbW91bnRXYWxsTW92ZWQgPSBuZXcgVmVjdG9yMigpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBjb25zdCBkaWZmWCA9IHRoaXMuZW5kLnggLSB0aGlzLnN0YXJ0Lng7XHJcbiAgICAgICAgY29uc3QgZGlmZlkgPSB0aGlzLmVuZC55IC0gdGhpcy5zdGFydC55O1xyXG4gICAgICAgIGNvbnN0IHByZXZTdGFydFg6IG51bWJlciA9IHRoaXMuc3RhcnQueDtcclxuICAgICAgICBjb25zdCBwcmV2U3RhcnRZOiBudW1iZXIgPSB0aGlzLnN0YXJ0Lnk7XHJcbiAgICAgICAgdGhpcy5zdGFydC5tb3ZlKHgsIHkpO1xyXG4gICAgICAgIHRoaXMuZW5kLm1vdmUoeCArIGRpZmZYLCB5ICsgZGlmZlkpO1xyXG4gICAgICAgIHRoaXMuYW1vdW50V2FsbE1vdmVkLmFkZChuZXcgVmVjdG9yMih0aGlzLnN0YXJ0LnggLSBwcmV2U3RhcnRYLCB0aGlzLnN0YXJ0LnkgLSBwcmV2U3RhcnRZKSk7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSByZWxhdGl2ZU1vdmUoZHg6IG51bWJlciwgZHk6IG51bWJlcikge1xyXG4gICAgICAgIHRoaXMuc3RhcnQucmVsYXRpdmVNb3ZlKGR4LCBkeSk7XHJcbiAgICAgICAgdGhpcy5lbmQucmVsYXRpdmVNb3ZlKGR4LCBkeSk7XHJcbiAgICB9XHJcblxyXG4gICAgcHVibGljIGZpcmVSZWRyYXcoKSB7XHJcbiAgICAgICAgaWYgKHRoaXMuZnJvbnRFZGdlKSB7XHJcbiAgICAgICAgICAgIHRoaXMuZnJvbnRFZGdlLnJlZHJhdygpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBpZiAodGhpcy5iYWNrRWRnZSkge1xyXG4gICAgICAgICAgICB0aGlzLmJhY2tFZGdlLnJlZHJhdygpO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBwdWJsaWMgZ2V0U3RhcnQoKTogQ29ybmVyIHtcclxuICAgICAgICByZXR1cm4gdGhpcy5zdGFydDtcclxuICAgIH1cclxuXHJcbiAgICBwdWJsaWMgZ2V0RW5kKCk6IENvcm5lciB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuZW5kO1xyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyBnZXRTdGFydFgoKTogbnVtYmVyIHtcclxuICAgICAgICByZXR1cm4gdGhpcy5zdGFydC5nZXRYKCk7XHJcbiAgICB9XHJcblxyXG4gICAgcHVibGljIGdldEVuZFgoKTogbnVtYmVyIHtcclxuICAgICAgICByZXR1cm4gdGhpcy5lbmQuZ2V0WCgpO1xyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyBnZXRTdGFydFkoKTogbnVtYmVyIHtcclxuICAgICAgICByZXR1cm4gdGhpcy5zdGFydC5nZXRZKCk7XHJcbiAgICB9XHJcblxyXG4gICAgcHVibGljIGdldEVuZFkoKTogbnVtYmVyIHtcclxuICAgICAgICByZXR1cm4gdGhpcy5lbmQuZ2V0WSgpO1xyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyByZW1vdmUoKSB7XHJcbiAgICAgICAgdGhpcy5zdGFydC5kZXRhY2hXYWxsKHRoaXMpO1xyXG4gICAgICAgIHRoaXMuZW5kLmRldGFjaFdhbGwodGhpcyk7XHJcbiAgICAgICAgdGhpcy5mcm9udFRleHR1cmUgPSB1bmRlZmluZWQ7XHJcbiAgICAgICAgdGhpcy5iYWNrVGV4dHVyZSA9IHVuZGVmaW5lZDtcclxuICAgIH1cclxuXHJcbiAgICBwdWJsaWMgc2V0U3RhcnQoY29ybmVyOiBDb3JuZXIpIHtcclxuICAgICAgICB0aGlzLnN0YXJ0LmRldGFjaFdhbGwodGhpcyk7XHJcbiAgICAgICAgY29ybmVyLmF0dGFjaFN0YXJ0KHRoaXMpO1xyXG4gICAgICAgIHRoaXMuc3RhcnQgPSBjb3JuZXI7XHJcbiAgICB9XHJcblxyXG4gICAgcHVibGljIHNldEVuZChjb3JuZXI6IENvcm5lcikge1xyXG4gICAgICAgIHRoaXMuZW5kLmRldGFjaFdhbGwodGhpcyk7XHJcbiAgICAgICAgY29ybmVyLmF0dGFjaEVuZCh0aGlzKTtcclxuICAgICAgICB0aGlzLmVuZCA9IGNvcm5lcjtcclxuICAgIH1cclxuXHJcbiAgICBwdWJsaWMgZGlzdGFuY2VGcm9tKHg6IG51bWJlciwgeTogbnVtYmVyKTogbnVtYmVyIHtcclxuICAgICAgICByZXR1cm4gVXRpbHMucG9pbnREaXN0YW5jZUZyb21MaW5lKHgsIHksXHJcbiAgICAgICAgICAgIHRoaXMuZ2V0U3RhcnRYKCksIHRoaXMuZ2V0U3RhcnRZKCksXHJcbiAgICAgICAgICAgIHRoaXMuZ2V0RW5kWCgpLCB0aGlzLmdldEVuZFkoKSk7XHJcbiAgICB9XHJcblxyXG4gICAgcHVibGljIGNsb3Nlc3RQb2ludFRvKHg6IG51bWJlciwgeTogbnVtYmVyKTogeyB4OiBudW1iZXIsIHk6IG51bWJlciB9IHtcclxuICAgICAgICByZXR1cm4gVXRpbHMuY2xvc2VzdFBvaW50T25MaW5lKHgsIHksXHJcbiAgICAgICAgICAgIHRoaXMuZ2V0U3RhcnRYKCksIHRoaXMuZ2V0U3RhcnRZKCksXHJcbiAgICAgICAgICAgIHRoaXMuZ2V0RW5kWCgpLCB0aGlzLmdldEVuZFkoKSk7XHJcbiAgICB9XHJcblxyXG4gICAgcHVibGljIGlzVG9PckZyb20oeDogbnVtYmVyLCB5OiBudW1iZXIpIHtcclxuICAgICAgICByZXR1cm4gKHRoaXMuZ2V0U3RhcnRYKCkgPT09IHggJiYgdGhpcy5nZXRTdGFydFkoKSA9PT0geSkgfHxcclxuICAgICAgICAgICAgKCB0aGlzLmdldEVuZFgoKSA9PT0geCAmJiB0aGlzLmdldEVuZFkoKSA9PT0geSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqIFJldHVybiB0aGUgY29ybmVyIG9wcG9zaXRlIG9mIHRoZSBvbmUgcHJvdmlkZWQuXHJcbiAgICAgKiBAcGFyYW0gY29ybmVyIFRoZSBnaXZlbiBjb3JuZXIuXHJcbiAgICAgKiBAcmV0dXJucyBUaGUgb3Bwb3NpdGUgY29ybmVyLlxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIF9vcHBvc2l0ZUNvcm5lcihjb3JuZXI6IENvcm5lcik6IENvcm5lciB7XHJcbiAgICAgICAgaWYgKHRoaXMuc3RhcnQgPT09IGNvcm5lcikge1xyXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5lbmQ7XHJcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLmVuZCA9PT0gY29ybmVyKSB7XHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnN0YXJ0O1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKCdXYWxsIGRvZXMgbm90IGNvbm5lY3QgdG8gY29ybmVyJyk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyBnZXQgbGVuZ3RoKCk6IG51bWJlciB7XHJcbiAgICAgICAgcmV0dXJuIFV0aWxzLmRpc3RhbmNlKHRoaXMuZ2V0U3RhcnRYKCksIHRoaXMuZ2V0U3RhcnRZKCksIHRoaXMuZ2V0RW5kWCgpLCB0aGlzLmdldEVuZFkoKSk7XHJcbiAgICB9XHJcblxyXG4gICAgcHVibGljIGdldCBlZGdlc0xlbmd0aHMoKTogbnVtYmVyW10ge1xyXG4gICAgICAgIGNvbnN0IGxlbmd0aHM6IG51bWJlcltdID0gW107XHJcbiAgICAgICAgaWYgKHRoaXMuZnJvbnRFZGdlKSB7XHJcbiAgICAgICAgICAgIGxlbmd0aHMucHVzaCh0aGlzLmZyb250RWRnZS5pbnRlcmlvckRpc3RhbmNlKCkpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBpZiAodGhpcy5iYWNrRWRnZSkge1xyXG4gICAgICAgICAgICBsZW5ndGhzLnB1c2godGhpcy5iYWNrRWRnZS5pbnRlcmlvckRpc3RhbmNlKCkpO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gbGVuZ3RocztcclxuICAgIH1cclxuXHJcbiAgICBwdWJsaWMgdXBkYXRlSW5XYWxsSXRlbXMoKSB7XHJcbiAgICAgICAgdGhpcy5pdGVtcy5maWx0ZXIoaXRlbSA9PiBpdGVtIGluc3RhbmNlb2YgSW5XYWxsSXRlbSkuZm9yRWFjaCgoaXRlbTogSW5XYWxsSXRlbSkgPT4gaXRlbS5vbldhbGxVcGRhdGVkKHRoaXMpKTtcclxuICAgIH1cclxuXHJcbiAgICBwdWJsaWMgdXBkYXRlV2FsbEl0ZW1zKCkge1xyXG4gICAgICAgIHRoaXMuaXRlbXMuZmlsdGVyKGl0ZW0gPT4gaXRlbSBpbnN0YW5jZW9mIFdhbGxJdGVtKS5mb3JFYWNoKChpdGVtOiBXYWxsSXRlbSkgPT4gaXRlbS5vbldhbGxNb3ZlZCh0aGlzKSk7XHJcbiAgICAgICAgdGhpcy5vbkl0ZW1zLmZpbHRlcihpdGVtID0+IGl0ZW0gaW5zdGFuY2VvZiBXYWxsSXRlbSB8fCBpdGVtIGluc3RhbmNlb2YgV2FsbEl0ZW1Hcm91cCkuZm9yRWFjaCgoaXRlbTogV2FsbEl0ZW0pID0+IGl0ZW0ub25XYWxsTW92ZWQodGhpcykpO1xyXG4gICAgICAgIHRoaXMuYW1vdW50V2FsbE1vdmVkID0gdW5kZWZpbmVkO1xyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyBnZXRJdGVtcygpOiBJdGVtW10ge1xyXG4gICAgICAgIHJldHVybiB0aGlzLml0ZW1zO1xyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyBnZXRXYWxsSXRlbXMoKTogV2FsbEl0ZW1bXSB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuaXRlbXMuZmlsdGVyKGl0ZW0gPT4gaXRlbSBpbnN0YW5jZW9mIFdhbGxJdGVtKSBhcyBXYWxsSXRlbVtdO1xyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyBnZXQgc2lkZSgpIHtcclxuICAgICAgICBpZiAodGhpcy5mcm9udEVkZ2UgJiYgdGhpcy5iYWNrRWRnZSkge1xyXG4gICAgICAgICAgICByZXR1cm4gVEhSRUUuRG91YmxlU2lkZTtcclxuICAgICAgICB9IGVsc2UgaWYgKHRoaXMuZnJvbnRFZGdlKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBUSFJFRS5Gcm9udFNpZGU7XHJcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLmJhY2tFZGdlKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBUSFJFRS5CYWNrU2lkZTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgcHVibGljIGFkZEl0ZW0oaXRlbTogSXRlbSkge1xyXG4gICAgICAgIHRoaXMuaXRlbXMucHVzaChpdGVtKTtcclxuICAgICAgICB0aGlzLml0ZW1zQ2hhbmdlZCA9IHRydWU7XHJcbiAgICB9XHJcblxyXG4gICAgcHVibGljIHJlbW92ZUl0ZW0oaXRlbTogSXRlbSkge1xyXG4gICAgICAgIHRoaXMuaXRlbXMgPSB0aGlzLml0ZW1zLmZpbHRlcihpID0+IGkgIT09IGl0ZW0pO1xyXG4gICAgICAgIHRoaXMuaXRlbXNDaGFuZ2VkID0gdHJ1ZTtcclxuICAgIH1cclxuXHJcbiAgICBwdWJsaWMgYWRkT25JdGVtKGl0ZW06IEl0ZW0pIHtcclxuICAgICAgICB0aGlzLm9uSXRlbXMucHVzaChpdGVtKTtcclxuICAgICAgICB0aGlzLml0ZW1zQ2hhbmdlZCA9IHRydWU7XHJcbiAgICB9XHJcblxyXG4gICAgcHVibGljIHJlbW92ZU9uSXRlbShpdGVtOiBJdGVtKSB7XHJcbiAgICAgICAgdGhpcy5vbkl0ZW1zID0gdGhpcy5vbkl0ZW1zLmZpbHRlcihpID0+IGkgIT09IGl0ZW0pO1xyXG4gICAgICAgIHRoaXMuaXRlbXNDaGFuZ2VkID0gdHJ1ZTtcclxuICAgIH1cclxufVxyXG5cclxuLyoqXHJcbiAqIENvcm5lcnMgYXJlIHVzZWQgdG8gZGVmaW5lIFdhbGxzLlxyXG4gKi9cclxuZXhwb3J0IGNsYXNzIENvcm5lciB7XHJcblxyXG4gICAgLyoqIEFycmF5IG9mIHN0YXJ0IHdhbGxzLiAqL1xyXG4gICAgcHVibGljIHdhbGxTdGFydHM6IFdhbGxbXSA9IFtdO1xyXG5cclxuICAgIC8qKiBBcnJheSBvZiBlbmQgd2FsbHMuICovXHJcbiAgICBwdWJsaWMgd2FsbEVuZHM6IFdhbGxbXSA9IFtdO1xyXG5cclxuICAgIC8qKiBDb25zdHJ1Y3RzIGEgY29ybmVyLlxyXG4gICAgICogQHBhcmFtIHggWCBjb29yZGluYXRlLlxyXG4gICAgICogQHBhcmFtIHkgWSBjb29yZGluYXRlLlxyXG4gICAgICogQHBhcmFtIGlkIEFuIG9wdGlvbmFsIHVuaXF1ZSBpZC4gSWYgbm90IHNldCwgY3JlYXRlZCBpbnRlcm5hbGx5LlxyXG4gICAgICovXHJcbiAgICBjb25zdHJ1Y3RvcihwdWJsaWMgeDogbnVtYmVyLCBwdWJsaWMgeTogbnVtYmVyLCBwdWJsaWMgaWQ/OiBzdHJpbmcpIHtcclxuICAgICAgICB0aGlzLmlkID0gaWQgfHwgVXRpbHMuZ3VpZCgpO1xyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyBhYnNvcmJXYWxsc0Zyb20oY29ybmVyOiBDb3JuZXIpIHtcclxuICAgICAgICBmb3IgKGxldCBpID0gY29ybmVyLndhbGxTdGFydHMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcclxuICAgICAgICAgICAgY29ybmVyLndhbGxTdGFydHNbaV0uc2V0U3RhcnQodGhpcyk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGZvciAobGV0IGkgPSBjb3JuZXIud2FsbEVuZHMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcclxuICAgICAgICAgICAgY29ybmVyLndhbGxFbmRzW2ldLnNldEVuZCh0aGlzKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBAcmV0dXJuc1xyXG4gICAgICogQGRlcHJlY2F0ZWRcclxuICAgICAqL1xyXG4gICAgcHVibGljIGdldFgoKTogbnVtYmVyIHtcclxuICAgICAgICByZXR1cm4gdGhpcy54O1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQHJldHVybnNcclxuICAgICAqIEBkZXByZWNhdGVkXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBnZXRZKCk6IG51bWJlciB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMueTtcclxuICAgIH1cclxuXHJcbiAgICAvKiogTW92ZXMgY29ybmVyIHJlbGF0aXZlbHkgdG8gbmV3IHBvc2l0aW9uLlxyXG4gICAgICogQHBhcmFtIGR4IFRoZSBkZWx0YSB4LlxyXG4gICAgICogQHBhcmFtIGR5IFRoZSBkZWx0YSB5LlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgcmVsYXRpdmVNb3ZlKGR4OiBudW1iZXIsIGR5OiBudW1iZXIpIHtcclxuICAgICAgICB0aGlzLm1vdmUodGhpcy54ICsgZHgsIHRoaXMueSArIGR5KTtcclxuICAgIH1cclxuXHJcbiAgICAvKiogUmVtb3ZlcyBhbGwgd2FsbHMuICovXHJcbiAgICBwdWJsaWMgcmVtb3ZlQWxsKCkge1xyXG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy53YWxsU3RhcnRzLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgICAgIHRoaXMud2FsbFN0YXJ0c1tpXS5yZW1vdmUoKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLndhbGxFbmRzLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgICAgIHRoaXMud2FsbEVuZHNbaV0ucmVtb3ZlKCk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8qKiBNb3ZlcyBjb3JuZXIgdG8gbmV3IHBvc2l0aW9uLlxyXG4gICAgICogQHBhcmFtIG5ld1ggVGhlIG5ldyB4IHBvc2l0aW9uLlxyXG4gICAgICogQHBhcmFtIG5ld1kgVGhlIG5ldyB5IHBvc2l0aW9uLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgbW92ZShuZXdYOiBudW1iZXIsIG5ld1k6IG51bWJlcikge1xyXG4gICAgICAgIHRoaXMueCA9IG5ld1g7XHJcbiAgICAgICAgdGhpcy55ID0gbmV3WTtcclxuICAgIH1cclxuXHJcbiAgICAvKiogR2V0cyB0aGUgYWRqYWNlbnQgY29ybmVycy5cclxuICAgICAqIEByZXR1cm5zIEFycmF5IG9mIGNvcm5lcnMuXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBhZGphY2VudENvcm5lcnMoKTogQ29ybmVyW10ge1xyXG4gICAgICAgIGNvbnN0IHJldEFycmF5ID0gW107XHJcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLndhbGxTdGFydHMubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICAgICAgcmV0QXJyYXkucHVzaCh0aGlzLndhbGxTdGFydHNbaV0uZ2V0RW5kKCkpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMud2FsbEVuZHMubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICAgICAgcmV0QXJyYXkucHVzaCh0aGlzLndhbGxFbmRzW2ldLmdldFN0YXJ0KCkpO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gcmV0QXJyYXk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqIENoZWNrcyBpZiBhIHdhbGwgaXMgY29ubmVjdGVkLlxyXG4gICAgICogQHBhcmFtIHdhbGwgQSB3YWxsLlxyXG4gICAgICogQHJldHVybnMgVHJ1ZSBpbiBjYXNlIG9mIGNvbm5lY3Rpb24uXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBpc1dhbGxDb25uZWN0ZWQod2FsbDogV2FsbCk6IGJvb2xlYW4ge1xyXG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy53YWxsU3RhcnRzLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgICAgIGlmICh0aGlzLndhbGxTdGFydHNbaV0gPT09IHdhbGwpIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy53YWxsRW5kcy5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgICAgICBpZiAodGhpcy53YWxsRW5kc1tpXSA9PT0gd2FsbCkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICpcclxuICAgICAqL1xyXG4gICAgcHVibGljIGRpc3RhbmNlRnJvbSh4OiBudW1iZXIsIHk6IG51bWJlcik6IG51bWJlciB7XHJcbiAgICAgICAgY29uc3QgZGlzdGFuY2UgPSBVdGlscy5kaXN0YW5jZSh4LCB5LCB0aGlzLngsIHRoaXMueSk7XHJcbiAgICAgICAgcmV0dXJuIGRpc3RhbmNlO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKiBHZXRzIHRoZSBkaXN0YW5jZSBmcm9tIGEgd2FsbC5cclxuICAgICAqIEBwYXJhbSB3YWxsIEEgd2FsbC5cclxuICAgICAqIEByZXR1cm5zIFRoZSBkaXN0YW5jZS5cclxuICAgICAqL1xyXG4gICAgcHVibGljIGRpc3RhbmNlRnJvbVdhbGwod2FsbDogV2FsbCk6IG51bWJlciB7XHJcbiAgICAgICAgcmV0dXJuIHdhbGwuZGlzdGFuY2VGcm9tKHRoaXMueCwgdGhpcy55KTtcclxuICAgIH1cclxuXHJcbiAgICAvKiogR2V0cyB0aGUgZGlzdGFuY2UgZnJvbSBhIGNvcm5lci5cclxuICAgICAqIEBwYXJhbSBjb3JuZXIgQSBjb3JuZXIuXHJcbiAgICAgKiBAcmV0dXJucyBUaGUgZGlzdGFuY2UuXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBkaXN0YW5jZUZyb21Db3JuZXIoY29ybmVyOiBDb3JuZXIpOiBudW1iZXIge1xyXG4gICAgICAgIHJldHVybiB0aGlzLmRpc3RhbmNlRnJvbShjb3JuZXIueCwgY29ybmVyLnkpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKiBEZXRhY2hlcyBhIHdhbGwuXHJcbiAgICAgKiBAcGFyYW0gd2FsbCBBIHdhbGwuXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBkZXRhY2hXYWxsKHdhbGw6IFdhbGwpIHtcclxuICAgICAgICBVdGlscy5yZW1vdmVWYWx1ZSh0aGlzLndhbGxTdGFydHMsIHdhbGwpO1xyXG4gICAgICAgIFV0aWxzLnJlbW92ZVZhbHVlKHRoaXMud2FsbEVuZHMsIHdhbGwpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKiBBdHRhY2hlcyBhIHN0YXJ0IHdhbGwuXHJcbiAgICAgKiBAcGFyYW0gd2FsbCBBIHdhbGwuXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBhdHRhY2hTdGFydCh3YWxsOiBXYWxsKSB7XHJcbiAgICAgICAgdGhpcy53YWxsU3RhcnRzLnB1c2god2FsbCk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqIEF0dGFjaGVzIGFuIGVuZCB3YWxsLlxyXG4gICAgICogQHBhcmFtIHdhbGwgQSB3YWxsLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgYXR0YWNoRW5kKHdhbGw6IFdhbGwpIHtcclxuICAgICAgICB0aGlzLndhbGxFbmRzLnB1c2god2FsbCk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqIEdldCB3YWxsIHRvIGNvcm5lci5cclxuICAgICAqIEBwYXJhbSBjb3JuZXIgQSBjb3JuZXIuXHJcbiAgICAgKiBAcmV0dXJuIFRoZSBhc3NvY2lhdGVkIHdhbGwgb3IgbnVsbC5cclxuICAgICAqL1xyXG4gICAgcHVibGljIHdhbGxUbyhjb3JuZXI6IENvcm5lcik6IFdhbGwge1xyXG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy53YWxsU3RhcnRzLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgICAgIGlmICh0aGlzLndhbGxTdGFydHNbaV0uZ2V0RW5kKCkgPT09IGNvcm5lcikge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMud2FsbFN0YXJ0c1tpXTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gbnVsbDtcclxuICAgIH1cclxuXHJcbiAgICAvKiogR2V0IHdhbGwgZnJvbSBjb3JuZXIuXHJcbiAgICAgKiBAcGFyYW0gY29ybmVyIEEgY29ybmVyLlxyXG4gICAgICogQHJldHVybiBUaGUgYXNzb2NpYXRlZCB3YWxsIG9yIG51bGwuXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyB3YWxsRnJvbShjb3JuZXI6IENvcm5lcik6IFdhbGwge1xyXG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy53YWxsRW5kcy5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgICAgICBpZiAodGhpcy53YWxsRW5kc1tpXS5nZXRTdGFydCgpID09PSBjb3JuZXIpIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLndhbGxFbmRzW2ldO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiBudWxsO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKiBHZXQgd2FsbCB0byBvciBmcm9tIGNvcm5lci5cclxuICAgICAqIEBwYXJhbSBjb3JuZXIgQSBjb3JuZXIuXHJcbiAgICAgKiBAcmV0dXJuIFRoZSBhc3NvY2lhdGVkIHdhbGwgb3IgbnVsbC5cclxuICAgICAqL1xyXG4gICAgcHVibGljIHdhbGxUb09yRnJvbShjb3JuZXI6IENvcm5lcik6IFdhbGwge1xyXG4gICAgICAgIHJldHVybiB0aGlzLndhbGxUbyhjb3JuZXIpIHx8IHRoaXMud2FsbEZyb20oY29ybmVyKTtcclxuICAgIH1cclxuXHJcbiAgICBwdWJsaWMgZ2V0IHN0YXJ0V2FsbHMoKTogV2FsbFtdIHtcclxuICAgICAgICByZXR1cm4gdGhpcy53YWxsU3RhcnRzO1xyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyBnZXQgZW5kV2FsbHMoKTogV2FsbFtdIHtcclxuICAgICAgICByZXR1cm4gdGhpcy53YWxsRW5kcztcclxuICAgIH1cclxuXHJcbiAgICAvKiogRW5zdXJlIHdlIGRvIG5vdCBoYXZlIGR1cGxpY2F0ZSB3YWxscyAoaS5lLiBzYW1lIHN0YXJ0IGFuZCBlbmQgcG9pbnRzKSAqL1xyXG4gICAgcHVibGljIHJlbW92ZUR1cGxpY2F0ZVdhbGxzKCkge1xyXG4gICAgICAgIC8vIGRlbGV0ZSB0aGUgd2FsbCBiZXR3ZWVuIHRoZXNlIGNvcm5lcnMsIGlmIGl0IGV4aXN0c1xyXG4gICAgICAgIGNvbnN0IHdhbGxFbmRwb2ludHMgPSB7fTtcclxuICAgICAgICBjb25zdCB3YWxsU3RhcnRwb2ludHMgPSB7fTtcclxuICAgICAgICBmb3IgKGxldCBpID0gdGhpcy53YWxsU3RhcnRzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XHJcbiAgICAgICAgICAgIGlmICh0aGlzLndhbGxTdGFydHNbaV0uZ2V0RW5kKCkgPT09IHRoaXMpIHtcclxuICAgICAgICAgICAgICAgIC8vIHJlbW92ZSB6ZXJvIGxlbmd0aCB3YWxsXHJcbiAgICAgICAgICAgICAgICB0aGlzLndhbGxTdGFydHNbaV0ucmVtb3ZlKCk7XHJcbiAgICAgICAgICAgIH0gZWxzZSBpZiAodGhpcy53YWxsU3RhcnRzW2ldLmdldEVuZCgpLmlkIGluIHdhbGxFbmRwb2ludHMpIHtcclxuICAgICAgICAgICAgICAgIC8vIHJlbW92ZSBkdXBsaWNhdGVkIHdhbGxcclxuICAgICAgICAgICAgICAgIHRoaXMud2FsbFN0YXJ0c1tpXS5yZW1vdmUoKTtcclxuICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgIHdhbGxFbmRwb2ludHNbdGhpcy53YWxsU3RhcnRzW2ldLmdldEVuZCgpLmlkXSA9IHRydWU7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgICAgZm9yIChsZXQgaSA9IHRoaXMud2FsbEVuZHMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcclxuICAgICAgICAgICAgaWYgKHRoaXMud2FsbEVuZHNbaV0uZ2V0U3RhcnQoKSA9PT0gdGhpcykge1xyXG4gICAgICAgICAgICAgICAgLy8gcmVtb3ZlZCB6ZXJvIGxlbmd0aCB3YWxsXHJcbiAgICAgICAgICAgICAgICB0aGlzLndhbGxFbmRzW2ldLnJlbW92ZSgpO1xyXG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMud2FsbEVuZHNbaV0uZ2V0U3RhcnQoKS5pZCBpbiB3YWxsU3RhcnRwb2ludHMpIHtcclxuICAgICAgICAgICAgICAgIC8vIHJlbW92ZWQgZHVwbGljYXRlZCB3YWxsXHJcbiAgICAgICAgICAgICAgICB0aGlzLndhbGxFbmRzW2ldLnJlbW92ZSgpO1xyXG4gICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgd2FsbFN0YXJ0cG9pbnRzW3RoaXMud2FsbEVuZHNbaV0uZ2V0U3RhcnQoKS5pZF0gPSB0cnVlO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvLyBmaW5kIGFuZCByZW1vdmUgY3ljbGUgfiBtb3JlIHRoYW4gYSBzaW5nbGUgd2FsbCBiZXR3ZWVuIDIgY29ybmVyc1xyXG4gICAgICAgIGZvciAoY29uc3Qgb3V0V2FsbCBvZiB0aGlzLndhbGxTdGFydHMpIHtcclxuICAgICAgICAgICAgZm9yIChjb25zdCBpbldhbGwgb2YgdGhpcy53YWxsRW5kcykge1xyXG4gICAgICAgICAgICAgICAgaWYgKG91dFdhbGwuZ2V0RW5kKCkgPT09IGluV2FsbC5nZXRTdGFydCgpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgb3V0V2FsbC5yZW1vdmUoKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgIH1cclxufVxyXG5cclxuLyoqXHJcbiAqIEhhbGYgRWRnZXMgYXJlIGNyZWF0ZWQgYnkgUm9vbS5cclxuICpcclxuICogT25jZSByb29tcyBoYXZlIGJlZW4gaWRlbnRpZmllZCwgSGFsZiBFZGdlcyBhcmUgY3JlYXRlZCBmb3IgZWFjaCBpbnRlcmlvciB3YWxsLlxyXG4gKlxyXG4gKiBBIHdhbGwgY2FuIGhhdmUgdHdvIGhhbGYgZWRnZXMgaWYgaXQgaXMgdmlzaWJsZSBmcm9tIGJvdGggc2lkZXMuXHJcbiAqL1xyXG5leHBvcnQgY2xhc3MgSGFsZkVkZ2Uge1xyXG5cclxuICAgIC8qKiBUaGUgc3VjY2Vzc29yIGVkZ2UgaW4gQ0NXID8/PyBkaXJlY3Rpb24uICovXHJcbiAgICBwdWJsaWMgbmV4dDogSGFsZkVkZ2U7XHJcblxyXG4gICAgLyoqIFRoZSBwcmVkZWNlc3NvciBlZGdlIGluIENDVyA/Pz8gZGlyZWN0aW9uLiAqL1xyXG4gICAgcHVibGljIHByZXY6IEhhbGZFZGdlO1xyXG5cclxuICAgIC8qKiAqL1xyXG4gICAgcHVibGljIG9mZnNldDogbnVtYmVyO1xyXG5cclxuICAgIC8qKiBXaGVuIGhlaWdodCBvZiB3YWxscyBhcmUgbW9kaWZpZWQsIHBsYW5lIHNob3VsZCBiZSByZWNyZWF0ZWQgKi9cclxuICAgIHB1YmxpYyBzZXQgaGVpZ2h0KHZhbHVlOiBudW1iZXIpIHtcclxuICAgICAgICB0aGlzLl9oZWlnaHQgPSB2YWx1ZTtcclxuICAgICAgICB0aGlzLmRpc3Bvc2VQbGFuZSgpO1xyXG4gICAgICAgIHRoaXMuZ2VuZXJhdGVQbGFuZSgpO1xyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyBnZXQgaGVpZ2h0KCk6IG51bWJlciB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuX2hlaWdodDtcclxuICAgIH1cclxuXHJcbiAgICAvKiogdXNlZCBmb3IgaW50ZXJzZWN0aW9uIHRlc3RpbmcuLi4gbm90IGNvbnZpbmNlZCB0aGlzIGJlbG9uZ3MgaGVyZSAqL1xyXG4gICAgcHVibGljIHBsYW5lOiBUaHJlZU1lc2ggPSBudWxsO1xyXG5cclxuICAgIC8qKiB0cmFuc2Zvcm0gZnJvbSB3b3JsZCBjb29yZHMgdG8gd2FsbCBwbGFuZXMgKHo9MCkgKi9cclxuICAgIHB1YmxpYyBpbnRlcmlvclRyYW5zZm9ybSA9IG5ldyBNYXRyaXg0KCk7XHJcblxyXG4gICAgLyoqIHRyYW5zZm9ybSBmcm9tIHdvcmxkIGNvb3JkcyB0byB3YWxsIHBsYW5lcyAoej0wKSAqL1xyXG4gICAgcHVibGljIGludkludGVyaW9yVHJhbnNmb3JtID0gbmV3IE1hdHJpeDQoKTtcclxuXHJcbiAgICAvKiogdHJhbnNmb3JtIGZyb20gd29ybGQgY29vcmRzIHRvIHdhbGwgcGxhbmVzICh6PTApICovXHJcbiAgICBwcml2YXRlIGV4dGVyaW9yVHJhbnNmb3JtID0gbmV3IE1hdHJpeDQoKTtcclxuXHJcbiAgICAvKiogdHJhbnNmb3JtIGZyb20gd29ybGQgY29vcmRzIHRvIHdhbGwgcGxhbmVzICh6PTApICovXHJcbiAgICBwcml2YXRlIGludkV4dGVyaW9yVHJhbnNmb3JtID0gbmV3IE1hdHJpeDQoKTtcclxuXHJcbiAgICBwcml2YXRlIF9oZWlnaHQ6IG51bWJlcjtcclxuXHJcbiAgICAvKiogKi9cclxuXHJcbiAgICBwdWJsaWMgZWRnZXM6IEVkZ2VbXSA9IFtdO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogQ29uc3RydWN0cyBhIGhhbGYgZWRnZS5cclxuICAgICAqIEBwYXJhbSByb29tIFRoZSBhc3NvY2lhdGVkIHJvb20uXHJcbiAgICAgKiBAcGFyYW0gd2FsbCBUaGUgY29ycmVzcG9uZGluZyB3YWxsLlxyXG4gICAgICogQHBhcmFtIGZyb250IFRydWUgaWYgZnJvbnQgc2lkZS5cclxuICAgICAqL1xyXG4gICAgY29uc3RydWN0b3IocHJpdmF0ZSByb29tOiBSb29tLCBwdWJsaWMgd2FsbDogV2FsbCwgcHVibGljIGZyb250OiBib29sZWFuKSB7XHJcbiAgICAgICAgdGhpcy5mcm9udCA9IGZyb250IHx8IGZhbHNlO1xyXG5cclxuICAgICAgICB0aGlzLm9mZnNldCA9IHdhbGwudGhpY2tuZXNzIC8gMi4wO1xyXG4gICAgICAgIHRoaXMuaGVpZ2h0ID0gd2FsbC5oZWlnaHQ7XHJcbiAgICAgICAgaWYgKHRoaXMuZnJvbnQpIHtcclxuICAgICAgICAgICAgdGhpcy53YWxsLmZyb250RWRnZSA9IHRoaXM7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgdGhpcy53YWxsLmJhY2tFZGdlID0gdGhpcztcclxuICAgICAgICB9XHJcbiAgICAgICAgdGhpcy53YWxsLnVwZGF0ZUluV2FsbEl0ZW1zKCk7XHJcbiAgICB9XHJcblxyXG4gICAgcHVibGljIHNob3dIaWRlRWRnZShzaG93OiBib29sZWFuKTogdm9pZCB7XHJcbiAgICAgICAgdGhpcy5lZGdlcy5mb3JFYWNoKGUgPT4gZS5zaG93SGlkZUVkZ2Uoc2hvdykpO1xyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyB1cGRhdGVWaXNpYmlsaXR5KGNhbWVyYVBvc2l0aW9uOiBWZWN0b3IzKTogYm9vbGVhbiB7XHJcbiAgICAgICAgbGV0IHZpc2liaWxpdHlDaGFuZ2VkOiBib29sZWFuID0gbnVsbDtcclxuICAgICAgICB0aGlzLmVkZ2VzLmZvckVhY2goZSA9PiB7XHJcbiAgICAgICAgICAgIGNvbnN0IGVkZ2VWaXNpYmlsaXR5Q2hhbmdlZCA9IGUudXBkYXRlVmlzaWJpbGl0eShjYW1lcmFQb3NpdGlvbik7XHJcbiAgICAgICAgICAgIGlmIChlZGdlVmlzaWJpbGl0eUNoYW5nZWQgIT09IG51bGwpIHtcclxuICAgICAgICAgICAgICAgIHZpc2liaWxpdHlDaGFuZ2VkID0gZWRnZVZpc2liaWxpdHlDaGFuZ2VkO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfSk7XHJcbiAgICAgICAgcmV0dXJuIHZpc2liaWxpdHlDaGFuZ2VkO1xyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyB1cGRhdGVWaXNpYmxpdHkodmlzaWJpbGl0eTogYm9vbGVhbikge1xyXG4gICAgICAgIHRoaXMuZWRnZXMuZm9yRWFjaChlID0+IHtcclxuICAgICAgICAgICAgZS52aXNpYmxlID0gdmlzaWJpbGl0eTtcclxuICAgICAgICAgICAgZS51cGRhdGVPYmplY3RWaXNpYmlsaXR5KCk7XHJcbiAgICAgICAgICAgIGUuc2V0QWxsUGxhbmVzVmlzaWJsZSgpO1xyXG4gICAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyBhc3luYyByZWRyYXcoKTogUHJvbWlzZTx2b2lkPiB7XHJcbiAgICAgICAgLy8gdGhpcy5lZGdlcy5mb3JFYWNoKGUgPT4gZS5yZWRyYXcoKSk7XHJcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLmVkZ2VzLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgICAgIGF3YWl0IHRoaXMuZWRnZXNbaV0ucmVkcmF3KCk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICpcclxuICAgICAqL1xyXG4gICAgcHVibGljIGdldFRleHR1cmUoKTogVGV4dHVyZSB7XHJcbiAgICAgICAgaWYgKHRoaXMuZnJvbnQpIHtcclxuICAgICAgICAgICAgcmV0dXJuIHRoaXMud2FsbC5mcm9udFRleHR1cmU7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgcmV0dXJuIHRoaXMud2FsbC5iYWNrVGV4dHVyZTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgcHVibGljIGdldENvbG9yKCk6IG51bWJlciB7XHJcbiAgICAgICAgaWYgKHRoaXMuZnJvbnQpIHtcclxuICAgICAgICAgICAgcmV0dXJuIHRoaXMud2FsbC5mcm9udENvbG9yO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLndhbGwuYmFja0NvbG9yO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBhc3luYyBzZXRUZXh0dXJlKHRleHR1cmU6IFRleHR1cmUpOiBQcm9taXNlPHZvaWQ+IHtcclxuICAgICAgICBpZiAodGV4dHVyZSkge1xyXG4gICAgICAgICAgICB0ZXh0dXJlLnJvdWdobmVzcyA9ICFpc05pbGwodGV4dHVyZS5yb3VnaG5lc3MpID8gdGV4dHVyZS5yb3VnaG5lc3MgOiAwLjg7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAodGhpcy5mcm9udCkge1xyXG4gICAgICAgICAgICB0aGlzLndhbGwuZnJvbnRUZXh0dXJlID0gdGV4dHVyZTtcclxuICAgICAgICAgICAgdGhpcy53YWxsLmZyb250Q29sb3IgPSBkZWZhdWx0V2FsbENvbG9yO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIHRoaXMud2FsbC5iYWNrVGV4dHVyZSA9IHRleHR1cmU7XHJcbiAgICAgICAgICAgIHRoaXMud2FsbC5iYWNrQ29sb3IgPSBkZWZhdWx0V2FsbENvbG9yO1xyXG4gICAgICAgIH1cclxuICAgICAgICAvLyB0aGlzLnJlZHJhd0NhbGxiYWNrcy5maXJlKCk7XHJcbiAgICAgICAgYXdhaXQgdGhpcy5yZWRyYXcoKTtcclxuICAgIH1cclxuXHJcbiAgICBwdWJsaWMgc2V0Q29sb3IodmFsdWU6IG51bWJlcikge1xyXG4gICAgICAgIGlmICh0aGlzLmZyb250KSB7XHJcbiAgICAgICAgICAgIHRoaXMud2FsbC5mcm9udFRleHR1cmUgPSBudWxsO1xyXG4gICAgICAgICAgICB0aGlzLndhbGwuZnJvbnRDb2xvciA9IHZhbHVlO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIHRoaXMud2FsbC5iYWNrVGV4dHVyZSA9IG51bGw7XHJcbiAgICAgICAgICAgIHRoaXMud2FsbC5iYWNrQ29sb3IgPSB2YWx1ZTtcclxuICAgICAgICB9XHJcbiAgICAgICAgLy8gdGhpcy5yZWRyYXdDYWxsYmFja3MuZmlyZSgpO1xyXG4gICAgICAgIHRoaXMucmVkcmF3KCk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiB0aGlzIGZlZWxzIGhhY2t5LCBidXQgbmVlZCB3YWxsIGl0ZW1zXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBnZW5lcmF0ZVBsYW5lKCkge1xyXG4gICAgICAgIGZ1bmN0aW9uIHRyYW5zZm9ybUNvcm5lcihjb3JuZXIpIHtcclxuICAgICAgICAgICAgcmV0dXJuIG5ldyBWZWN0b3IzKGNvcm5lci54LCAwLCBjb3JuZXIueSk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICB0aGlzLm9mZnNldCA9IHRoaXMud2FsbC50aGlja25lc3MgLyAyLjA7XHJcbiAgICAgICAgdGhpcy5faGVpZ2h0ID0gdGhpcy53YWxsLmhlaWdodDtcclxuXHJcbiAgICAgICAgY29uc3QgdjEgPSB0cmFuc2Zvcm1Db3JuZXIodGhpcy5pbnRlcmlvclN0YXJ0KCkpO1xyXG4gICAgICAgIGNvbnN0IHYyID0gdHJhbnNmb3JtQ29ybmVyKHRoaXMuaW50ZXJpb3JFbmQoKSk7XHJcbiAgICAgICAgY29uc3QgdjMgPSB2Mi5jbG9uZSgpO1xyXG4gICAgICAgIHYzLnkgPSB0aGlzLndhbGwuaGVpZ2h0O1xyXG4gICAgICAgIGNvbnN0IHY0ID0gdjEuY2xvbmUoKTtcclxuICAgICAgICB2NC55ID0gdGhpcy53YWxsLmhlaWdodDtcclxuXHJcbiAgICAgICAgY29uc3QgZ2VvbWV0cnkgPSBuZXcgQnVmZmVyR2VvbWV0cnkoKS5zZXRGcm9tUG9pbnRzKFt2MSwgdjIsIHYzLCB2NF0pO1xyXG4gICAgICAgIGNvbnN0IGZhY2VWZXJ0ZXhJbmRleEFycmF5OiBVaW50MTZBcnJheSA9IG5ldyBVaW50MTZBcnJheShbMCwgMSwgMiwgMCwgMiwgM10pO1xyXG4gICAgICAgIGNvbnN0IGZhY2VCdWZmZXJBdHRyaWJ1dGU6IEJ1ZmZlckF0dHJpYnV0ZSA9IG5ldyBCdWZmZXJBdHRyaWJ1dGUoZmFjZVZlcnRleEluZGV4QXJyYXksIDEpO1xyXG4gICAgICAgIGdlb21ldHJ5LnNldEluZGV4KGZhY2VCdWZmZXJBdHRyaWJ1dGUpO1xyXG4gICAgICAgIGdlb21ldHJ5LmNvbXB1dGVWZXJ0ZXhOb3JtYWxzKCk7XHJcbiAgICAgICAgZ2VvbWV0cnkuY29tcHV0ZUJvdW5kaW5nQm94KCk7XHJcblxyXG4gICAgICAgIHRoaXMucGxhbmUgPSBuZXcgVGhyZWVNZXNoKGdlb21ldHJ5LCBuZXcgTWVzaFBoeXNpY2FsTWF0ZXJpYWwobnVsbCkpO1xyXG4gICAgICAgIHRoaXMucGxhbmUubmFtZSA9IGBoYWxmLWVkZ2UtcGxhbmUtJHt0aGlzLmZyb250ID8gJ2Zyb250JyA6ICdiYWNrJ31gO1xyXG4gICAgICAgIHRoaXMucGxhbmUuY2FzdFNoYWRvdyA9IHRydWU7XHJcbiAgICAgICAgVXRpbHMuc2V0UGxhbmVWaXNpYmlsaXR5KHRoaXMucGxhbmUsIHRydWUpO1xyXG4gICAgICAgIHRoaXMucGxhbmUudXNlckRhdGEuZWRnZSA9IHRoaXM7XHJcblxyXG4gICAgICAgIHRoaXMuY29tcHV0ZVRyYW5zZm9ybXMoXHJcbiAgICAgICAgICAgIHRoaXMuaW50ZXJpb3JUcmFuc2Zvcm0sIHRoaXMuaW52SW50ZXJpb3JUcmFuc2Zvcm0sXHJcbiAgICAgICAgICAgIHRoaXMuaW50ZXJpb3JTdGFydCgpLCB0aGlzLmludGVyaW9yRW5kKCkpO1xyXG4gICAgICAgIHRoaXMuY29tcHV0ZVRyYW5zZm9ybXMoXHJcbiAgICAgICAgICAgIHRoaXMuZXh0ZXJpb3JUcmFuc2Zvcm0sIHRoaXMuaW52RXh0ZXJpb3JUcmFuc2Zvcm0sXHJcbiAgICAgICAgICAgIHRoaXMuZXh0ZXJpb3JTdGFydCgpLCB0aGlzLmV4dGVyaW9yRW5kKCkpO1xyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyBkaXNwb3NlUGxhbmUoKSB7XHJcbiAgICAgICAgaWYgKHRoaXMucGxhbmUpIHtcclxuICAgICAgICAgICAgVXRpbHMuRGlzcG9zZU9iamVjdCh0aGlzLnBsYW5lKTtcclxuICAgICAgICAgICAgdGhpcy5wbGFuZSA9IG51bGw7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyBpbnRlcmlvckRpc3RhbmNlKCk6IG51bWJlciB7XHJcbiAgICAgICAgY29uc3Qgc3RhcnQgPSB0aGlzLmludGVyaW9yU3RhcnQoKTtcclxuICAgICAgICBjb25zdCBlbmQgPSB0aGlzLmludGVyaW9yRW5kKCk7XHJcbiAgICAgICAgcmV0dXJuIFV0aWxzLmRpc3RhbmNlKHN0YXJ0LngsIHN0YXJ0LnksIGVuZC54LCBlbmQueSk7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBjb21wdXRlVHJhbnNmb3Jtcyh0cmFuc2Zvcm0sIGludlRyYW5zZm9ybSwgc3RhcnQsIGVuZCkge1xyXG5cclxuICAgICAgICBjb25zdCB2MSA9IHN0YXJ0O1xyXG4gICAgICAgIGNvbnN0IHYyID0gZW5kO1xyXG5cclxuICAgICAgICBjb25zdCBhbmdsZSA9IFV0aWxzLmFuZ2xlKDEsIDAsIHYyLnggLSB2MS54LCB2Mi55IC0gdjEueSk7XHJcblxyXG4gICAgICAgIGNvbnN0IHR0ID0gbmV3IE1hdHJpeDQoKTtcclxuICAgICAgICB0dC5tYWtlVHJhbnNsYXRpb24oLXYxLngsIDAsIC12MS55KTtcclxuICAgICAgICBjb25zdCB0ciA9IG5ldyBNYXRyaXg0KCk7XHJcbiAgICAgICAgdHIubWFrZVJvdGF0aW9uWSgtYW5nbGUpO1xyXG4gICAgICAgIHRyYW5zZm9ybS5tdWx0aXBseU1hdHJpY2VzKHRyLCB0dCk7XHJcbiAgICAgICAgaW52VHJhbnNmb3JtLmNvcHkodHJhbnNmb3JtKS5pbnZlcnQoKTtcclxuICAgIH1cclxuXHJcbiAgICAvKiogR2V0cyB0aGUgZGlzdGFuY2UgZnJvbSBzcGVjaWZpZWQgcG9pbnQuXHJcbiAgICAgKiBAcGFyYW0geCBYIGNvb3JkaW5hdGUgb2YgdGhlIHBvaW50LlxyXG4gICAgICogQHBhcmFtIHkgWSBjb29yZGluYXRlIG9mIHRoZSBwb2ludC5cclxuICAgICAqIEByZXR1cm5zIFRoZSBkaXN0YW5jZS5cclxuICAgICAqL1xyXG4gICAgcHVibGljIGRpc3RhbmNlVG8oeDogbnVtYmVyLCB5OiBudW1iZXIpOiBudW1iZXIge1xyXG4gICAgICAgIC8vIHgsIHksIHgxLCB5MSwgeDIsIHkyXHJcbiAgICAgICAgcmV0dXJuIFV0aWxzLnBvaW50RGlzdGFuY2VGcm9tTGluZSh4LCB5LFxyXG4gICAgICAgICAgICB0aGlzLmludGVyaW9yU3RhcnQoKS54LFxyXG4gICAgICAgICAgICB0aGlzLmludGVyaW9yU3RhcnQoKS55LFxyXG4gICAgICAgICAgICB0aGlzLmludGVyaW9yRW5kKCkueCxcclxuICAgICAgICAgICAgdGhpcy5pbnRlcmlvckVuZCgpLnkpO1xyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyBnZXRTdGFydCgpIHtcclxuICAgICAgICBpZiAodGhpcy5mcm9udCkge1xyXG4gICAgICAgICAgICByZXR1cm4gdGhpcy53YWxsLmdldFN0YXJ0KCk7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgcmV0dXJuIHRoaXMud2FsbC5nZXRFbmQoKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgcHVibGljIGdldEVuZCgpIHtcclxuICAgICAgICBpZiAodGhpcy5mcm9udCkge1xyXG4gICAgICAgICAgICByZXR1cm4gdGhpcy53YWxsLmdldEVuZCgpO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLndhbGwuZ2V0U3RhcnQoKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBnZXRPcHBvc2l0ZUVkZ2UoKTogSGFsZkVkZ2Uge1xyXG4gICAgICAgIGlmICh0aGlzLmZyb250KSB7XHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLndhbGwuYmFja0VkZ2U7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgcmV0dXJuIHRoaXMud2FsbC5mcm9udEVkZ2U7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8vIHRoZXNlIHJldHVybiBhbiBvYmplY3Qgd2l0aCBhdHRyaWJ1dGVzIHgsIHlcclxuICAgIHB1YmxpYyBpbnRlcmlvckVuZCgpOiBWZWN0b3IyIHtcclxuICAgICAgICBjb25zdCB2ZWMgPSB0aGlzLmhhbGZBbmdsZVZlY3Rvcih0aGlzLCB0aGlzLm5leHQpO1xyXG4gICAgICAgIHJldHVybiBuZXcgVmVjdG9yMih0aGlzLmdldEVuZCgpLnggKyB2ZWMueCwgdGhpcy5nZXRFbmQoKS55ICsgdmVjLnkpO1xyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyBpbnRlcmlvclN0YXJ0KCk6IFZlY3RvcjIge1xyXG4gICAgICAgIGNvbnN0IHZlYyA9IHRoaXMuaGFsZkFuZ2xlVmVjdG9yKHRoaXMucHJldiwgdGhpcyk7XHJcbiAgICAgICAgcmV0dXJuIG5ldyBWZWN0b3IyKHRoaXMuZ2V0U3RhcnQoKS54ICsgdmVjLngsIHRoaXMuZ2V0U3RhcnQoKS55ICsgdmVjLnkpO1xyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyBpbnRlcmlvckNlbnRlcigpOiBWZWN0b3IyIHtcclxuICAgICAgICByZXR1cm4gbmV3IFZlY3RvcjIoKHRoaXMuaW50ZXJpb3JTdGFydCgpLnggKyB0aGlzLmludGVyaW9yRW5kKCkueCkgLyAyLjAsICh0aGlzLmludGVyaW9yU3RhcnQoKS55ICsgdGhpcy5pbnRlcmlvckVuZCgpLnkpIC8gMi4wKTtcclxuICAgIH1cclxuXHJcbiAgICBwdWJsaWMgZXh0ZXJpb3JFbmQoKTogVmVjdG9yMiB7XHJcbiAgICAgICAgY29uc3QgdmVjID0gdGhpcy5oYWxmQW5nbGVWZWN0b3IodGhpcywgdGhpcy5uZXh0KTtcclxuICAgICAgICByZXR1cm4gbmV3IFZlY3RvcjIodGhpcy5nZXRFbmQoKS54IC0gdmVjLngsIHRoaXMuZ2V0RW5kKCkueSAtIHZlYy55KTtcclxuICAgIH1cclxuXHJcbiAgICBwdWJsaWMgZXh0ZXJpb3JTdGFydCgpOiBWZWN0b3IyIHtcclxuICAgICAgICBjb25zdCB2ZWMgPSB0aGlzLmhhbGZBbmdsZVZlY3Rvcih0aGlzLnByZXYsIHRoaXMpO1xyXG4gICAgICAgIHJldHVybiBuZXcgVmVjdG9yMih0aGlzLmdldFN0YXJ0KCkueCAtIHZlYy54LCB0aGlzLmdldFN0YXJ0KCkueSAtIHZlYy55KTtcclxuICAgIH1cclxuXHJcbiAgICAvKiogR2V0IHRoZSBjb3JuZXJzIG9mIHRoZSBoYWxmIGVkZ2UuXHJcbiAgICAgKiBAcmV0dXJucyBBbiBhcnJheSBvZiB4LHkgcGFpcnMuXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBjb3JuZXJzKCk6IHsgeDogbnVtYmVyLCB5OiBudW1iZXIgfVtdIHtcclxuICAgICAgICByZXR1cm4gW3RoaXMuaW50ZXJpb3JTdGFydCgpLCB0aGlzLmludGVyaW9yRW5kKCksXHJcbiAgICAgICAgICAgIHRoaXMuZXh0ZXJpb3JFbmQoKSwgdGhpcy5leHRlcmlvclN0YXJ0KCldO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogR2V0cyBDQ1cgYW5nbGUgZnJvbSB2MSB0byB2MlxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIGhhbGZBbmdsZVZlY3Rvcih2MTogSGFsZkVkZ2UsIHYyOiBIYWxmRWRnZSk6IFZlY3RvcjIge1xyXG4gICAgICAgIC8vIG1ha2UgdGhlIGJlc3Qgb2YgdGhpbmdzIGlmIHdlIGRvbnQgaGF2ZSBwcmV2IG9yIG5leHRcclxuICAgICAgICBsZXQgdjFzdGFydFg7XHJcbiAgICAgICAgbGV0IHYxc3RhcnRZO1xyXG4gICAgICAgIGxldCB2MWVuZFg7XHJcbiAgICAgICAgbGV0IHYxZW5kWTtcclxuICAgICAgICBsZXQgdjJzdGFydFg7XHJcbiAgICAgICAgbGV0IHYyc3RhcnRZO1xyXG4gICAgICAgIGxldCB2MmVuZFg7XHJcbiAgICAgICAgbGV0IHYyZW5kWTtcclxuXHJcbiAgICAgICAgaWYgKCF2MSkge1xyXG4gICAgICAgICAgICB2MXN0YXJ0WCA9IHYyLmdldFN0YXJ0KCkueCAtICh2Mi5nZXRFbmQoKS54IC0gdjIuZ2V0U3RhcnQoKS54KTtcclxuICAgICAgICAgICAgdjFzdGFydFkgPSB2Mi5nZXRTdGFydCgpLnkgLSAodjIuZ2V0RW5kKCkueSAtIHYyLmdldFN0YXJ0KCkueSk7XHJcbiAgICAgICAgICAgIHYxZW5kWCA9IHYyLmdldFN0YXJ0KCkueDtcclxuICAgICAgICAgICAgdjFlbmRZID0gdjIuZ2V0U3RhcnQoKS55O1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIHYxc3RhcnRYID0gPG51bWJlcj52MS5nZXRTdGFydCgpLng7XHJcbiAgICAgICAgICAgIHYxc3RhcnRZID0gPG51bWJlcj52MS5nZXRTdGFydCgpLnk7XHJcbiAgICAgICAgICAgIHYxZW5kWCA9IHYxLmdldEVuZCgpLng7XHJcbiAgICAgICAgICAgIHYxZW5kWSA9IHYxLmdldEVuZCgpLnk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAoIXYyKSB7XHJcbiAgICAgICAgICAgIHYyc3RhcnRYID0gdjEuZ2V0RW5kKCkueDtcclxuICAgICAgICAgICAgdjJzdGFydFkgPSB2MS5nZXRFbmQoKS55O1xyXG4gICAgICAgICAgICB2MmVuZFggPSB2MS5nZXRFbmQoKS54ICsgKHYxLmdldEVuZCgpLnggLSB2MS5nZXRTdGFydCgpLngpO1xyXG4gICAgICAgICAgICB2MmVuZFkgPSB2MS5nZXRFbmQoKS55ICsgKHYxLmdldEVuZCgpLnkgLSB2MS5nZXRTdGFydCgpLnkpO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIHYyc3RhcnRYID0gdjIuZ2V0U3RhcnQoKS54O1xyXG4gICAgICAgICAgICB2MnN0YXJ0WSA9IHYyLmdldFN0YXJ0KCkueTtcclxuICAgICAgICAgICAgdjJlbmRYID0gdjIuZ2V0RW5kKCkueDtcclxuICAgICAgICAgICAgdjJlbmRZID0gdjIuZ2V0RW5kKCkueTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIENDVyBhbmdsZSBiZXR3ZWVuIGVkZ2VzXHJcbiAgICAgICAgY29uc3QgdGhldGEgPSBVdGlscy5hbmdsZTJwaShcclxuICAgICAgICAgICAgdjFzdGFydFggLSB2MWVuZFgsXHJcbiAgICAgICAgICAgIHYxc3RhcnRZIC0gdjFlbmRZLFxyXG4gICAgICAgICAgICB2MmVuZFggLSB2MWVuZFgsXHJcbiAgICAgICAgICAgIHYyZW5kWSAtIHYxZW5kWSk7XHJcblxyXG4gICAgICAgIC8vIGNvc2luZSBhbmQgc2luZSBvZiBoYWxmIGFuZ2xlXHJcbiAgICAgICAgY29uc3QgY3MgPSBNYXRoLmNvcyh0aGV0YSAvIDIuMCk7XHJcbiAgICAgICAgY29uc3Qgc24gPSBNYXRoLnNpbih0aGV0YSAvIDIuMCk7XHJcblxyXG4gICAgICAgIC8vIHJvdGF0ZSB2MlxyXG4gICAgICAgIGNvbnN0IHYyZHggPSB2MmVuZFggLSB2MnN0YXJ0WDtcclxuICAgICAgICBjb25zdCB2MmR5ID0gdjJlbmRZIC0gdjJzdGFydFk7XHJcblxyXG4gICAgICAgIGNvbnN0IHZ4ID0gdjJkeCAqIGNzIC0gdjJkeSAqIHNuO1xyXG4gICAgICAgIGNvbnN0IHZ5ID0gdjJkeCAqIHNuICsgdjJkeSAqIGNzO1xyXG5cclxuICAgICAgICAvLyBub3JtYWxpemVcclxuICAgICAgICBjb25zdCBtYWcgPSBVdGlscy5kaXN0YW5jZSgwLCAwLCB2eCwgdnkpO1xyXG4gICAgICAgIGNvbnN0IGRlc2lyZWRNYWcgPSAodGhpcy5vZmZzZXQpIC8gc247XHJcbiAgICAgICAgY29uc3Qgc2NhbGFyID0gZGVzaXJlZE1hZyAvIG1hZztcclxuXHJcbiAgICAgICAgcmV0dXJuIG5ldyBWZWN0b3IyKHZ4ICogc2NhbGFyLCB2eSAqIHNjYWxhcik7XHJcbiAgICB9XHJcblxyXG4gICAgcHVibGljIGdldCBpbnZFeHRlcmlvclF1YXRlcm5pb24oKTogUXVhdGVybmlvbiB7XHJcbiAgICAgICAgY29uc3QgcXVhdGVybmlvbiA9IG5ldyBRdWF0ZXJuaW9uKCk7XHJcbiAgICAgICAgcXVhdGVybmlvbi5zZXRGcm9tUm90YXRpb25NYXRyaXgodGhpcy5pbnZFeHRlcmlvclRyYW5zZm9ybSk7XHJcbiAgICAgICAgcmV0dXJuIHF1YXRlcm5pb247XHJcbiAgICB9XHJcbn1cclxuXHJcbmV4cG9ydCBjbGFzcyBFZGdlIHtcclxuICAgIHByaXZhdGUgX2ZpbGxlckNvbG9yID0gbmV3IENvbG9yKDB4ZGRkZGRkKTtcclxuICAgIHByaXZhdGUgcmVhZG9ubHkgX3dhbGw6IFdhbGw7XHJcbiAgICBwcml2YXRlIHJlYWRvbmx5IF9mcm9udDogYm9vbGVhbjtcclxuXHJcbiAgICBwcml2YXRlIF9maWxsZXJNYXRlcmlhbDogVEhSRUUuTWVzaEJhc2ljTWF0ZXJpYWw7XHJcbiAgICBwcml2YXRlIF93YWxsTWF0ZXJpYWw6IFRIUkVFLk1lc2hQaG9uZ01hdGVyaWFsO1xyXG4gICAgcHJpdmF0ZSBfcGxhbmVzOiB7XHJcbiAgICAgICAgZXh0ZXJpb3I6IE1lc2gsXHJcbiAgICAgICAgaW50ZXJpb3I6IE1lc2gsXHJcbiAgICAgICAgc2lkZXM6IE1lc2hbXSxcclxuICAgICAgICBib3R0b206IE1lc2gsXHJcbiAgICAgICAgdG9wOiBNZXNoXHJcbiAgICB9ID0ge1xyXG4gICAgICAgIGV4dGVyaW9yOiBudWxsLFxyXG4gICAgICAgIGludGVyaW9yOiBudWxsLFxyXG4gICAgICAgIHNpZGVzOiBudWxsLFxyXG4gICAgICAgIGJvdHRvbTogbnVsbCxcclxuICAgICAgICB0b3A6IG51bGxcclxuICAgIH07XHJcblxyXG4gICAgcHJpdmF0ZSBfbGFzdDoge1xyXG4gICAgICAgIGNvbG9yOiBudW1iZXIsXHJcbiAgICAgICAgdGV4dHVyZTogVGV4dHVyZSxcclxuICAgICAgICBmaWxsZXJNYXRlcmlhbDogTWVzaEJhc2ljTWF0ZXJpYWwsXHJcbiAgICAgICAgd2FsbE1hdGVyaWFsOiBNZXNoUGhvbmdNYXRlcmlhbCxcclxuICAgICAgICBoZWlnaHQ6IG51bWJlclxyXG4gICAgfSA9IHtcclxuICAgICAgICBjb2xvcjogbnVsbCxcclxuICAgICAgICB0ZXh0dXJlOiBudWxsLFxyXG4gICAgICAgIGZpbGxlck1hdGVyaWFsOiBudWxsLFxyXG4gICAgICAgIHdhbGxNYXRlcmlhbDogbnVsbCxcclxuICAgICAgICBoZWlnaHQ6IG51bGxcclxuICAgIH07XHJcblxyXG4gICAgcHVibGljIHZpc2libGU7XHJcblxyXG4gICAgY29uc3RydWN0b3IocHJpdmF0ZSBfaGFsZkVkZ2U6IEhhbGZFZGdlKSB7XHJcbiAgICAgICAgaWYgKF9oYWxmRWRnZSkge1xyXG4gICAgICAgICAgICB0aGlzLl93YWxsID0gX2hhbGZFZGdlLndhbGw7XHJcbiAgICAgICAgICAgIHRoaXMuX2Zyb250ID0gX2hhbGZFZGdlLmZyb250O1xyXG4gICAgICAgICAgICAvLyB0aGlzLnVwZGF0ZVBsYW5lcygpO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBwdWJsaWMgc2hvd0hpZGVFZGdlKHNob3c6IGJvb2xlYW4pOiB2b2lkIHtcclxuICAgICAgICB0aGlzLl9wbGFuZUxpc3QoKS5mb3JFYWNoKHAgPT4gcC52aXNpYmxlID0gc2hvdyk7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBfcGxhbmVMaXN0KCk6IE1lc2hbXSB7XHJcbiAgICAgICAgcmV0dXJuICh0aGlzLl9wbGFuZXMuc2lkZXMgfHwgW10pLmNvbmNhdChbXHJcbiAgICAgICAgICAgIHRoaXMuX3BsYW5lcy50b3AsXHJcbiAgICAgICAgICAgIHRoaXMuX3BsYW5lcy5ib3R0b20sXHJcbiAgICAgICAgICAgIHRoaXMuX3BsYW5lcy5pbnRlcmlvcixcclxuICAgICAgICAgICAgdGhpcy5fcGxhbmVzLmV4dGVyaW9yXHJcbiAgICAgICAgXSkuZmlsdGVyKHggPT4geCk7XHJcbiAgICB9XHJcblxyXG4gICAgcHVibGljIGdldFBsYW5lcygpOiBNZXNoW10ge1xyXG4gICAgICAgIHJldHVybiB0aGlzLl9wbGFuZUxpc3QoKTtcclxuICAgIH1cclxuXHJcbiAgICBwdWJsaWMgZ2V0VG9wU2lkZUZpbGxlcnMoKTogTWVzaFtdIHtcclxuICAgICAgICByZXR1cm4gdGhpcy5fcGxhbmVzLnNpZGVzLmNvbmNhdChbdGhpcy5fcGxhbmVzLnRvcF0pO1xyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyBhc3luYyBpbml0KCk6IFByb21pc2U8dm9pZD4ge1xyXG4gICAgICAgIC8vIHRoaXMuaGFsZkVkZ2UucmVkcmF3Q2FsbGJhY2tzLmFkZCh0aGlzLnJlZHJhdyk7XHJcbiAgICAgICAgLy8gaGFsZkVkZ2UuaXRlbUFkZGVkQ2FsbGJhY2tzLmFkZCh1cGRhdGVPYmplY3RWaXNpYmlsaXR5KTtcclxuICAgICAgICAvLyBjb250cm9scy5jYW1lcmFNb3ZlZENhbGxiYWNrcy5hZGQodXBkYXRlVmlzaWJpbGl0eSk7XHJcbiAgICAgICAgYXdhaXQgdGhpcy51cGRhdGVQbGFuZXMoKTtcclxuICAgICAgICAvLyBhZGRUb1NjZW5lKCk7XHJcbiAgICB9XHJcblxyXG4gICAgcHVibGljIGFzeW5jIHJlZHJhdygpOiBQcm9taXNlPHZvaWQ+IHtcclxuICAgICAgICBhd2FpdCB0aGlzLnVwZGF0ZVBsYW5lcygpO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIHByaXZhdGUgcmVtb3ZlRnJvbVNjZW5lKCkge1xyXG4gICAgLy8gICB0aGlzLnBsYW5lTGlzdCgpLmZvckVhY2goKHBsYW5lKSA9PiB7XHJcbiAgICAvLyAgICAgc2NlbmUucmVtb3ZlKHBsYW5lKTtcclxuICAgIC8vICAgICBVdGlscy5kaXNwb3NlT2JqZWN0KHBsYW5lKTtcclxuICAgIC8vICAgfSk7XHJcbiAgICAvLyAgIE9iamVjdC5rZXlzKHBsYW5lcykuZm9yRWFjaCgoa2V5OiBzdHJpbmcpID0+IHBsYW5lc1trZXldID0gbnVsbCk7XHJcbiAgICAvLyAgIE9iamVjdC5rZXlzKGxhc3QpLmZvckVhY2goKGtleTogc3RyaW5nKSA9PiBsYXN0W2tleV0gPSBudWxsKTtcclxuICAgIC8vIH1cclxuXHJcbiAgICAvLyBwcml2YXRlIGFkZFRvU2NlbmUoKSB7XHJcbiAgICAvLyAgIHBsYW5lTGlzdCgpLmZvckVhY2goKHBsYW5lKSA9PiB7XHJcbiAgICAvLyAgICAgc2NlbmUuYWRkKHBsYW5lKTtcclxuICAgIC8vICAgfSk7XHJcbiAgICAvLyAgIHVwZGF0ZVZpc2liaWxpdHkoKTtcclxuICAgIC8vIH1cclxuXHJcbiAgICBwdWJsaWMgdXBkYXRlVmlzaWJpbGl0eShjYW1lcmFQb3NpdGlvbjogVmVjdG9yMyk6IGJvb2xlYW4ge1xyXG4gICAgICAgIC8vIGZpbmRzIHRoZSBub3JtYWwgZnJvbSB0aGUgc3BlY2lmaWVkIGhhbGZFZGdlXHJcbiAgICAgICAgY29uc3Qgc3RhcnQgPSB0aGlzLl9oYWxmRWRnZS5pbnRlcmlvclN0YXJ0KCk7XHJcbiAgICAgICAgY29uc3QgZW5kID0gdGhpcy5faGFsZkVkZ2UuaW50ZXJpb3JFbmQoKTtcclxuICAgICAgICBjb25zdCB4ID0gZW5kLnggLSBzdGFydC54O1xyXG4gICAgICAgIGNvbnN0IHkgPSBlbmQueSAtIHN0YXJ0Lnk7XHJcbiAgICAgICAgLy8gcm90YXRlIDkwIGRlZ3JlZXMgQ0NXXHJcbiAgICAgICAgY29uc3Qgbm9ybWFsID0gbmV3IFZlY3RvcjMoLXksIDAsIHgpO1xyXG4gICAgICAgIG5vcm1hbC5ub3JtYWxpemUoKTtcclxuXHJcbiAgICAgICAgLy8gc2V0dXAgY2FtZXJhXHJcbiAgICAgICAgY29uc3QgcG9zaXRpb24gPSBjYW1lcmFQb3NpdGlvbi5jbG9uZSgpO1xyXG4gICAgICAgIGNvbnN0IGZvY3VzID0gbmV3IFZlY3RvcjMoXHJcbiAgICAgICAgICAgIChzdGFydC54ICsgZW5kLngpIC8gMi4wLFxyXG4gICAgICAgICAgICAwLFxyXG4gICAgICAgICAgICAoc3RhcnQueSArIGVuZC55KSAvIDIuMCk7XHJcbiAgICAgICAgY29uc3QgZGlyZWN0aW9uID0gcG9zaXRpb24uc3ViKGZvY3VzKS5ub3JtYWxpemUoKTtcclxuXHJcbiAgICAgICAgLy8gZmluZCBkb3RcclxuICAgICAgICBjb25zdCBkb3QgPSBub3JtYWwuZG90KGRpcmVjdGlvbik7XHJcblxyXG4gICAgICAgIC8vIHVwZGF0ZSB2aXNpYmxlXHJcbiAgICAgICAgY29uc3QgbmV3VmlzaWJsZSA9IChkb3QgPj0gMCk7XHJcblxyXG4gICAgICAgIC8vIHNob3cgb3IgaGlkZSBwbGFuc1xyXG4gICAgICAgIHRoaXMuX3BsYW5lTGlzdCgpLmZvckVhY2goKHBsYW5lOiBUSFJFRS5NZXNoKSA9PlxyXG4gICAgICAgICAgICBVdGlscy5zZXRQbGFuZVZpc2liaWxpdHkocGxhbmUsIG5ld1Zpc2libGUpXHJcbiAgICAgICAgKTtcclxuICAgICAgICBpZiAobmV3VmlzaWJsZSAhPT0gdGhpcy52aXNpYmxlKSB7XHJcbiAgICAgICAgICAgIHRoaXMudmlzaWJsZSA9IG5ld1Zpc2libGU7XHJcbiAgICAgICAgICAgIHRoaXMudXBkYXRlT2JqZWN0VmlzaWJpbGl0eSgpO1xyXG4gICAgICAgICAgICByZXR1cm4gbmV3VmlzaWJsZTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgcHVibGljIHVwZGF0ZU9iamVjdFZpc2liaWxpdHkoKTogdm9pZCB7XHJcbiAgICAgICAgdGhpcy5fd2FsbC5pdGVtcy5mb3JFYWNoKChpdGVtOiBXYWxsSXRlbSkgPT4ge1xyXG4gICAgICAgICAgICBpdGVtLnVwZGF0ZUVkZ2VWaXNpYmlsaXR5KHRoaXMpO1xyXG4gICAgICAgIH0pO1xyXG4gICAgICAgIHRoaXMuX3dhbGwub25JdGVtcy5mb3JFYWNoKChpdGVtOiBXYWxsSXRlbSkgPT4ge1xyXG4gICAgICAgICAgICBpdGVtLnVwZGF0ZUVkZ2VWaXNpYmlsaXR5KHRoaXMpO1xyXG4gICAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyBzZXRBbGxQbGFuZXNWaXNpYmxlKCkge1xyXG4gICAgICAgIHRoaXMuX3BsYW5lTGlzdCgpLmZvckVhY2goKHBsYW5lOiBUSFJFRS5NZXNoKSA9PlxyXG4gICAgICAgICAgICBVdGlscy5zZXRQbGFuZVZpc2liaWxpdHkocGxhbmUsIHRydWUpXHJcbiAgICAgICAgKTtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIGFzeW5jIF9hZGRNYXRlcmlhbE1hcChtYXRlcmlhbDogVEhSRUUuTWVzaFBob25nTWF0ZXJpYWwgfCBUSFJFRS5NZXNoU3RhbmRhcmRNYXRlcmlhbCwgdGV4dHVyZTogVGV4dHVyZSk6IFByb21pc2U8dm9pZD4ge1xyXG4gICAgICAgIGNvbnN0IGRpbWVuc2lvbnMgPSBuZXcgVEhSRUUuVmVjdG9yMihcclxuICAgICAgICAgICAgdGhpcy5faGFsZkVkZ2UuaW50ZXJpb3JEaXN0YW5jZSgpLFxyXG4gICAgICAgICAgICB0aGlzLl93YWxsLmhlaWdodCAtIHRoaXMuX3dhbGwudGhpY2tuZXNzXHJcbiAgICAgICAgKTtcclxuICAgICAgICB0ZXh0dXJlLmRpbWVuc2lvbnMgPSBkaW1lbnNpb25zLm11bHRpcGx5U2NhbGFyKDEwMCk7XHJcbiAgICAgICAgc3dpdGNoICh0ZXh0dXJlLnR5cGUpIHtcclxuICAgICAgICAgICAgY2FzZSBUZXh0dXJlVHlwZS5JbWFnZTpcclxuICAgICAgICAgICAgICAgIG1hdGVyaWFsLm1hcCA9IGF3YWl0IE1hdGVyaWFsVXRpbHMuRnJvbUltYWdlKHRleHR1cmUpO1xyXG4gICAgICAgICAgICAgICAgbWF0ZXJpYWwubWFwLmNvbG9yU3BhY2UgPSBTUkdCQ29sb3JTcGFjZTtcclxuICAgICAgICAgICAgICAgIG1hdGVyaWFsLm5lZWRzVXBkYXRlID0gdHJ1ZTtcclxuICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICBjYXNlIFRleHR1cmVUeXBlLkN1c3RvbVBhdHRlcm46XHJcbiAgICAgICAgICAgICAgICBtYXRlcmlhbC5tYXAgPSBhd2FpdCBNYXRlcmlhbFV0aWxzLkN1c3RvbVRpbGVNYXBUZXh0dXJlKHRleHR1cmUsIGRpbWVuc2lvbnMpO1xyXG4gICAgICAgICAgICAgICAgbWF0ZXJpYWwubWFwLmNvbG9yU3BhY2UgPSBTUkdCQ29sb3JTcGFjZTtcclxuICAgICAgICAgICAgICAgIG1hdGVyaWFsLm5lZWRzVXBkYXRlID0gdHJ1ZTtcclxuICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICBjYXNlIFRleHR1cmVUeXBlLkJhc2ljOlxyXG4gICAgICAgICAgICAgICAgbWF0ZXJpYWwubWFwID0gYXdhaXQgTWF0ZXJpYWxVdGlscy5Gcm9tVXJsKHRleHR1cmUudXJsLCB0ZXh0dXJlLnN0cmV0Y2gsIHRleHR1cmUudGlsZVNpemUsIG51bGwsIG51bGwsIHRleHR1cmUuZGltZW5zaW9ucywgdGV4dHVyZS50aWxlUm90YXRpb24pO1xyXG4gICAgICAgICAgICAgICAgbWF0ZXJpYWwubWFwLmNvbG9yU3BhY2UgPSBTUkdCQ29sb3JTcGFjZTtcclxuICAgICAgICAgICAgICAgIG1hdGVyaWFsLm5lZWRzVXBkYXRlID0gdHJ1ZTtcclxuICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICBjYXNlIFRleHR1cmVUeXBlLlBCUjpcclxuICAgICAgICAgICAgICAgIG1hdGVyaWFsID0gbWF0ZXJpYWwgYXMgTWVzaFN0YW5kYXJkTWF0ZXJpYWw7XHJcbiAgICAgICAgICAgICAgICBpZiAodGV4dHVyZS5tYXRlcmlhbGl6ZVVybCkge1xyXG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IE1hdGVyaWFsVXRpbHMubG9hZE1hdGVyaWFsaXplTWFwcyhtYXRlcmlhbCwgdGV4dHVyZSk7XHJcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgIG1hdGVyaWFsLm1hcCA9IGF3YWl0IE1hdGVyaWFsVXRpbHMuRnJvbVVybCh0ZXh0dXJlLnVybCwgdGV4dHVyZS5zdHJldGNoLCB0ZXh0dXJlLnRpbGVTaXplLCB0ZXh0dXJlLnJlcGVhdFgsIHRleHR1cmUucmVwZWF0WSwgdGV4dHVyZS5kaW1lbnNpb25zLCB0ZXh0dXJlLnRpbGVSb3RhdGlvbik7XHJcbiAgICAgICAgICAgICAgICAgICAgbWF0ZXJpYWwubWFwLmNvbG9yU3BhY2UgPSBTUkdCQ29sb3JTcGFjZTtcclxuICAgICAgICAgICAgICAgICAgICBtYXRlcmlhbC5yb3VnaG5lc3NNYXAgPSB0ZXh0dXJlLnJvdWdobmVzc01hcCA/IGF3YWl0IE1hdGVyaWFsVXRpbHMuRnJvbVVybCh0ZXh0dXJlLnJvdWdobmVzc01hcCwgdGV4dHVyZS5zdHJldGNoLCB0ZXh0dXJlLnRpbGVTaXplLCB0ZXh0dXJlLnJlcGVhdFgsIHRleHR1cmUucmVwZWF0WSwgdGV4dHVyZS5kaW1lbnNpb25zLCB0ZXh0dXJlLnRpbGVSb3RhdGlvbikgOiBudWxsO1xyXG4gICAgICAgICAgICAgICAgICAgIG1hdGVyaWFsLmJ1bXBNYXAgPSB0ZXh0dXJlLmJ1bXBNYXAgPyBhd2FpdCBNYXRlcmlhbFV0aWxzLkZyb21VcmwodGV4dHVyZS5idW1wTWFwLCB0ZXh0dXJlLnN0cmV0Y2gsIHRleHR1cmUudGlsZVNpemUsIHRleHR1cmUucmVwZWF0WCwgdGV4dHVyZS5yZXBlYXRZLCB0ZXh0dXJlLmRpbWVuc2lvbnMsIHRleHR1cmUudGlsZVJvdGF0aW9uKSA6IG51bGw7XHJcbiAgICAgICAgICAgICAgICAgICAgbWF0ZXJpYWwubm9ybWFsTWFwID0gdGV4dHVyZS5ub3JtYWxNYXAgPyBhd2FpdCBNYXRlcmlhbFV0aWxzLkZyb21VcmwodGV4dHVyZS5ub3JtYWxNYXAsIHRleHR1cmUuc3RyZXRjaCwgdGV4dHVyZS50aWxlU2l6ZSwgdGV4dHVyZS5yZXBlYXRYLCB0ZXh0dXJlLnJlcGVhdFksIHRleHR1cmUuZGltZW5zaW9ucywgdGV4dHVyZS50aWxlUm90YXRpb24pIDogbnVsbDtcclxuICAgICAgICAgICAgICAgICAgICBtYXRlcmlhbC5tZXRhbG5lc3NNYXAgPSB0ZXh0dXJlLm1ldGFsbmVzc01hcCA/IGF3YWl0IE1hdGVyaWFsVXRpbHMuRnJvbVVybCh0ZXh0dXJlLm1ldGFsbmVzc01hcCwgdGV4dHVyZS5zdHJldGNoLCB0ZXh0dXJlLnRpbGVTaXplLCB0ZXh0dXJlLnJlcGVhdFgsIHRleHR1cmUucmVwZWF0WSwgdGV4dHVyZS5kaW1lbnNpb25zLCB0ZXh0dXJlLnRpbGVSb3RhdGlvbikgOiBudWxsO1xyXG4gICAgICAgICAgICAgICAgICAgIG1hdGVyaWFsLmFvTWFwID0gdGV4dHVyZS5hb01hcCA/IGF3YWl0IE1hdGVyaWFsVXRpbHMuRnJvbVVybCh0ZXh0dXJlLmFvTWFwLCB0ZXh0dXJlLnN0cmV0Y2gsIHRleHR1cmUudGlsZVNpemUsIHRleHR1cmUucmVwZWF0WCwgdGV4dHVyZS5yZXBlYXRZLCB0ZXh0dXJlLmRpbWVuc2lvbnMsIHRleHR1cmUudGlsZVJvdGF0aW9uKSA6IG51bGw7XHJcbiAgICAgICAgICAgICAgICAgICAgbWF0ZXJpYWwubmVlZHNVcGRhdGUgPSB0cnVlO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIF9pc1ZhbGlkKHN0YXJ0RW5kKTogYm9vbGVhbiB7XHJcbiAgICAgICAgcmV0dXJuICFzdGFydEVuZC5maW5kKGUgPT4gIWlzRmluaXRlKGUueCkgfHwgIWlzRmluaXRlKGUueSkpO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgX3VwZGF0ZUZpbGxlck1hdGVyaWFsKCk6IE1lc2hCYXNpY01hdGVyaWFsIHtcclxuICAgICAgICBpZiAodGhpcy5fZmlsbGVyTWF0ZXJpYWwpIHtcclxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2ZpbGxlck1hdGVyaWFsO1xyXG4gICAgICAgIH1cclxuICAgICAgICBjb25zdCBtYXRlcmlhbDogTWVzaEJhc2ljTWF0ZXJpYWwgPSBuZXcgTWVzaEJhc2ljTWF0ZXJpYWwoe1xyXG4gICAgICAgICAgICBjb2xvcjogdGhpcy5fZmlsbGVyQ29sb3IsXHJcbiAgICAgICAgICAgIHNpZGU6IERvdWJsZVNpZGVcclxuICAgICAgICB9KTtcclxuICAgICAgICByZXR1cm4gbWF0ZXJpYWw7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBhc3luYyBfdXBkYXRlV2FsbE1hdGVyaWFsKHRleHR1cmU6IFRleHR1cmUsIGNvbG9yOiBudW1iZXIgPSBkZWZhdWx0RWRnZUNvbG9yKTogUHJvbWlzZTxNZXNoUGhvbmdNYXRlcmlhbD4ge1xyXG4gICAgICAgIGNvbnN0IGlzU2FtZUNvbG9yID0gY29sb3IgJiYgdGhpcy5fbGFzdC5jb2xvciAmJiBjb2xvciA9PT0gdGhpcy5fbGFzdC5jb2xvcjtcclxuICAgICAgICBjb25zdCBpc1NhbWVUZXh0dXJlID0gc2FtZVRleHR1cmVzKHRleHR1cmUsIHRoaXMuX2xhc3QudGV4dHVyZSk7XHJcbiAgICAgICAgaWYgKGlzU2FtZUNvbG9yICYmIGlzU2FtZVRleHR1cmUpIHtcclxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX3dhbGxNYXRlcmlhbDtcclxuICAgICAgICB9XHJcbiAgICAgICAgaWYgKCFpc1NhbWVDb2xvcikge1xyXG4gICAgICAgICAgICB0aGlzLl9sYXN0LmNvbG9yID0gY29sb3I7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGlmICghaXNTYW1lVGV4dHVyZSkge1xyXG4gICAgICAgICAgICB0aGlzLl9sYXN0LnRleHR1cmUgPSBPYmplY3QuYXNzaWduKHt9LCB0ZXh0dXJlKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGxldCBtYXRlcmlhbDtcclxuICAgICAgICBtYXRlcmlhbCA9IG5ldyBUSFJFRS5NZXNoUGhvbmdNYXRlcmlhbCh7XHJcbiAgICAgICAgICAgIGNvbG9yOiBjb2xvcixcclxuICAgICAgICAgICAgc2lkZTogVEhSRUUuRnJvbnRTaWRlXHJcbiAgICAgICAgfSk7XHJcblxyXG4gICAgICAgIGlmICh0ZXh0dXJlKSB7XHJcbiAgICAgICAgICAgIG1hdGVyaWFsID0gbmV3IFRIUkVFLk1lc2hTdGFuZGFyZE1hdGVyaWFsKHtcclxuICAgICAgICAgICAgICAgIGNvbG9yOiBjb2xvcixcclxuICAgICAgICAgICAgICAgIHNpZGU6IFRIUkVFLkZyb250U2lkZSxcclxuICAgICAgICAgICAgICAgIHJvdWdobmVzczogIWlzTmlsbCh0ZXh0dXJlLnJvdWdobmVzcykgPyB0ZXh0dXJlLnJvdWdobmVzcyA6IDAuOCxcclxuICAgICAgICAgICAgICAgIG1ldGFsbmVzczogIWlzTmlsbCh0ZXh0dXJlLm1ldGFsbmVzcykgPyB0ZXh0dXJlLm1ldGFsbmVzcyA6IDAsXHJcbiAgICAgICAgICAgICAgICBidW1wU2NhbGU6ICFpc05pbGwodGV4dHVyZS5idW1wU2NhbGUpID8gdGV4dHVyZS5idW1wU2NhbGUgOiAxXHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICBhd2FpdCB0aGlzLl9hZGRNYXRlcmlhbE1hcChtYXRlcmlhbCwgdGV4dHVyZSk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiBtYXRlcmlhbDtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIF9lcXVhbExhc3RWZWMyKHBsYW5lOiBzdHJpbmcsIHBhcmFtU3VmZml4OiBzdHJpbmcpOiBib29sZWFuIHtcclxuICAgICAgICBjb25zdCBwYXJhbU5hbWUgPSBgJHtwbGFuZX0ke3BhcmFtU3VmZml4fWA7XHJcbiAgICAgICAgY29uc3QgZ2V0dGVyID0gdGhpcy5faGFsZkVkZ2VbcGFyYW1OYW1lXSgpO1xyXG4gICAgICAgIHJldHVybiB0aGlzLl9sYXN0W3BhcmFtTmFtZV0gJiZcclxuICAgICAgICAgICAgdGhpcy5faGFsZkVkZ2VbcGFyYW1OYW1lXSAmJlxyXG4gICAgICAgICAgICB0aGlzLl9sYXN0W3BhcmFtTmFtZV0ueCA9PT0gZ2V0dGVyLnggJiZcclxuICAgICAgICAgICAgdGhpcy5fbGFzdFtwYXJhbU5hbWVdLnkgPT09IGdldHRlci55O1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgX2NvcHlMYXN0KHBsYW5lOiBzdHJpbmcsIHBhcmFtczogc3RyaW5nW10pOiB2b2lkIHtcclxuICAgICAgICBwYXJhbXMuZm9yRWFjaCgocGFyYW06IHN0cmluZykgPT4ge1xyXG4gICAgICAgICAgICBjb25zdCBwYXJhbU5hbWUgPSBwYXJhbSA9PT0gJ0ludlRyYW5zZm9ybScgP1xyXG4gICAgICAgICAgICAgICAgdGhpcy5faW52VHJhbnNmb3JtUGFyYW0ocGxhbmUpIDpcclxuICAgICAgICAgICAgICAgIGAke3BsYW5lfSR7cGFyYW19YDtcclxuICAgICAgICAgICAgY29uc3QgY3VycmVudCA9ICdmdW5jdGlvbicgPT09IHR5cGVvZiB0aGlzLl9oYWxmRWRnZVtwYXJhbU5hbWVdID9cclxuICAgICAgICAgICAgICAgIHRoaXMuX2hhbGZFZGdlW3BhcmFtTmFtZV0oKSA6IHRoaXMuX2hhbGZFZGdlW3BhcmFtTmFtZV07XHJcbiAgICAgICAgICAgIHRoaXMuX2xhc3RbcGFyYW1OYW1lXSA9IGN1cnJlbnQ7XHJcbiAgICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBfdHJhbnNmb3JtUGFyYW0ocGxhbmU6IHN0cmluZyk6IHN0cmluZyB7XHJcbiAgICAgICAgcmV0dXJuIGAke3BsYW5lfVRyYW5zZm9ybWA7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBfaW52VHJhbnNmb3JtUGFyYW0ocGxhbmU6IHN0cmluZyk6IHN0cmluZyB7XHJcbiAgICAgICAgcmV0dXJuIGBpbnYke3BsYW5lLmNoYXJBdCgwKS50b1VwcGVyQ2FzZSgpfSR7cGxhbmUuc3Vic3RyKDEpfVRyYW5zZm9ybWA7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBfdXBkYXRlTWFpblBsYW5lKHBsYW5lOiBzdHJpbmcsIG1hdGVyaWFsOiBNZXNoQmFzaWNNYXRlcmlhbCB8IE1lc2hQaG9uZ01hdGVyaWFsKTogTWVzaCB7XHJcbiAgICAgICAgbGV0IHVwZGF0ZVBsYW5lOiBNZXNoID0gdGhpcy5fcGxhbmVzW3BsYW5lXTtcclxuICAgICAgICBjb25zdCBnZW86IFNoYXBlR2VvbWV0cnkgPSB0aGlzLl9jcmVhdGVHZW9tZXRyeShcclxuICAgICAgICAgICAgdGhpcy5faGFsZkVkZ2VbYCR7cGxhbmV9U3RhcnRgXSgpLFxyXG4gICAgICAgICAgICB0aGlzLl9oYWxmRWRnZVtgJHtwbGFuZX1FbmRgXSgpLFxyXG4gICAgICAgICAgICB0aGlzLl9oYWxmRWRnZVt0aGlzLl90cmFuc2Zvcm1QYXJhbShwbGFuZSldLFxyXG4gICAgICAgICAgICB0aGlzLl9oYWxmRWRnZVt0aGlzLl9pbnZUcmFuc2Zvcm1QYXJhbShwbGFuZSldLFxyXG4gICAgICAgICk7XHJcbiAgICAgICAgaWYgKCF1cGRhdGVQbGFuZSkge1xyXG4gICAgICAgICAgICB1cGRhdGVQbGFuZSA9IG5ldyBUaHJlZU1lc2goZ2VvLCBtYXRlcmlhbCk7XHJcbiAgICAgICAgICAgIHVwZGF0ZVBsYW5lLm5hbWUgPSAnZWRnZSc7XHJcbiAgICAgICAgICAgIHVwZGF0ZVBsYW5lLnVzZXJEYXRhLndhbGwgPSB0aGlzLl93YWxsO1xyXG4gICAgICAgICAgICB1cGRhdGVQbGFuZS5jYXN0U2hhZG93ID0gdHJ1ZTtcclxuICAgICAgICAgICAgdXBkYXRlUGxhbmUucmVjZWl2ZVNoYWRvdyA9IHRydWU7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgdXBkYXRlUGxhbmUuZ2VvbWV0cnkgPSBnZW87XHJcbiAgICAgICAgICAgIHVwZGF0ZVBsYW5lLm1hdGVyaWFsID0gbWF0ZXJpYWw7XHJcbiAgICAgICAgICAgIHVwZGF0ZVBsYW5lLm1hdGVyaWFsLm5lZWRzVXBkYXRlID0gdHJ1ZTtcclxuICAgICAgICB9LyogZWxzZSB7XHJcbiAgICAgIHVwZGF0ZVBsYW5lID0gdGhpcy5tYWtlV2FsbChcclxuICAgICAgICB0aGlzLmhhbGZFZGdlW2Ake3BsYW5lfVN0YXJ0YF0oKSxcclxuICAgICAgICB0aGlzLmhhbGZFZGdlW2Ake3BsYW5lfUVuZGBdKCksXHJcbiAgICAgICAgdGhpcy5oYWxmRWRnZVt0aGlzLnRyYW5zZm9ybVBhcmFtKHBsYW5lKV0sXHJcbiAgICAgICAgdGhpcy5oYWxmRWRnZVt0aGlzLmludlRyYW5zZm9ybVBhcmFtKHBsYW5lKV0sXHJcbiAgICAgICAgbWF0ZXJpYWxcclxuICAgICAgKTtcclxuICAgIH0qL1xyXG4gICAgICAgIHJldHVybiB1cGRhdGVQbGFuZTtcclxuICAgICAgICAvLyBjb25zdCBvbGRQbGFuZSA9IHRoaXMucGxhbmVzW3BsYW5lXTtcclxuICAgICAgICAvLyBjb25zdCBuZXdQbGFuZSA9IHRoaXMubWFrZVdhbGwoXHJcbiAgICAgICAgLy8gICB0aGlzLmhhbGZFZGdlW2Ake3BsYW5lfVN0YXJ0YF0oKSxcclxuICAgICAgICAvLyAgIHRoaXMuaGFsZkVkZ2VbYCR7cGxhbmV9RW5kYF0oKSxcclxuICAgICAgICAvLyAgIHRoaXMuaGFsZkVkZ2VbdGhpcy50cmFuc2Zvcm1QYXJhbShwbGFuZSldLFxyXG4gICAgICAgIC8vICAgdGhpcy5oYWxmRWRnZVt0aGlzLmludlRyYW5zZm9ybVBhcmFtKHBsYW5lKV0sXHJcbiAgICAgICAgLy8gICBtYXRlcmlhbFxyXG4gICAgICAgIC8vICk7XHJcbiAgICAgICAgLy8gaWYgKG9sZFBsYW5lKSB7XHJcbiAgICAgICAgLy8gICAvLyBzY2VuZS5yZW1vdmUob2xkUGxhbmUpO1xyXG4gICAgICAgIC8vICAgVXRpbHMuZGlzcG9zZU9iamVjdChvbGRQbGFuZSk7XHJcbiAgICAgICAgLy8gfVxyXG4gICAgICAgIC8vIC8vIHNjZW5lLmFkZChuZXdQbGFuZSk7XHJcbiAgICAgICAgLy8gcmV0dXJuIG5ld1BsYW5lO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgX3VwZGF0ZUJvdHRvbVBsYW5lKCk6IE1lc2gge1xyXG4gICAgICAgIGNvbnN0IG9sZFBsYW5lID0gdGhpcy5fcGxhbmVzLmJvdHRvbTtcclxuICAgICAgICBpZiAob2xkUGxhbmUgJiZcclxuICAgICAgICAgICAgdGhpcy5fZXF1YWxMYXN0VmVjMignaW50ZXJpb3InLCAnU3RhcnQnKSAmJlxyXG4gICAgICAgICAgICB0aGlzLl9lcXVhbExhc3RWZWMyKCdpbnRlcmlvcicsICdFbmQnKSAmJlxyXG4gICAgICAgICAgICB0aGlzLl9lcXVhbExhc3RWZWMyKCdleHRlcmlvcicsICdTdGFydCcpICYmXHJcbiAgICAgICAgICAgIHRoaXMuX2VxdWFsTGFzdFZlYzIoJ2V4dGVyaW9yJywgJ0VuZCcpXHJcbiAgICAgICAgKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBvbGRQbGFuZTtcclxuICAgICAgICB9XHJcbiAgICAgICAgY29uc3QgbmV3UGxhbmUgPSB0aGlzLl9idWlsZEZpbGxlcigwLCB0aGlzLl9maWxsZXJNYXRlcmlhbCk7XHJcbiAgICAgICAgaWYgKG9sZFBsYW5lKSB7XHJcbiAgICAgICAgICAgIC8vIERpc3Bvc2UgZnVuY3Rpb24gZG9lcyBub3QgYWN0dWFsbHkgcmVtb3ZlIHRoZSBvYmplY3QgZnJvbSB0aGUgc2NlbmVcclxuICAgICAgICAgICAgVXRpbHMuRGlzcG9zZU9iamVjdChvbGRQbGFuZSk7XHJcbiAgICAgICAgICAgIG9sZFBsYW5lLnZpc2libGUgPSBmYWxzZTtcclxuICAgICAgICB9XHJcbiAgICAgICAgLy8gc2NlbmUuYWRkKG5ld1BsYW5lKTtcclxuICAgICAgICByZXR1cm4gbmV3UGxhbmU7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBfdXBkYXRlVG9wUGxhbmUoKTogTWVzaCB7XHJcbiAgICAgICAgY29uc3Qgb2xkUGxhbmUgPSB0aGlzLl9wbGFuZXMudG9wO1xyXG4gICAgICAgIGlmIChvbGRQbGFuZSAmJlxyXG4gICAgICAgICAgICB0aGlzLl9sYXN0LmhlaWdodCA9PT0gdGhpcy5fd2FsbC5oZWlnaHQgJiZcclxuICAgICAgICAgICAgdGhpcy5fZXF1YWxMYXN0VmVjMignaW50ZXJpb3InLCAnU3RhcnQnKSAmJlxyXG4gICAgICAgICAgICB0aGlzLl9lcXVhbExhc3RWZWMyKCdpbnRlcmlvcicsICdFbmQnKSAmJlxyXG4gICAgICAgICAgICB0aGlzLl9lcXVhbExhc3RWZWMyKCdleHRlcmlvcicsICdTdGFydCcpICYmXHJcbiAgICAgICAgICAgIHRoaXMuX2VxdWFsTGFzdFZlYzIoJ2V4dGVyaW9yJywgJ0VuZCcpXHJcbiAgICAgICAgKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBvbGRQbGFuZTtcclxuICAgICAgICB9XHJcbiAgICAgICAgaWYgKG9sZFBsYW5lKSB7XHJcbiAgICAgICAgICAgIC8vIERpc3Bvc2UgZnVuY3Rpb24gZG9lcyBub3QgYWN0dWFsbHkgcmVtb3ZlIHRoZSBvYmplY3QgZnJvbSB0aGUgc2NlbmVcclxuICAgICAgICAgICAgVXRpbHMuRGlzcG9zZU9iamVjdChvbGRQbGFuZSk7XHJcbiAgICAgICAgICAgIG9sZFBsYW5lLnZpc2libGUgPSBmYWxzZTtcclxuICAgICAgICB9XHJcbiAgICAgICAgY29uc3QgbmV3UGxhbmUgPSB0aGlzLl9idWlsZEZpbGxlcih0aGlzLl93YWxsLmhlaWdodCwgdGhpcy5fZmlsbGVyTWF0ZXJpYWwpO1xyXG4gICAgICAgIC8vIHNjZW5lLmFkZChuZXdQbGFuZSk7XHJcbiAgICAgICAgcmV0dXJuIG5ld1BsYW5lO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgX3VwZGF0ZVNpZGVQbGFuZXMoKTogTWVzaFtdIHtcclxuICAgICAgICBjb25zdCBvbGRQbGFuZXMgPSB0aGlzLl9wbGFuZXMuc2lkZXM7XHJcbiAgICAgICAgaWYgKG9sZFBsYW5lcyAmJlxyXG4gICAgICAgICAgICB0aGlzLl9sYXN0LmhlaWdodCA9PT0gdGhpcy5fd2FsbC5oZWlnaHQgJiZcclxuICAgICAgICAgICAgdGhpcy5fZXF1YWxMYXN0VmVjMignaW50ZXJpb3InLCAnU3RhcnQnKSAmJlxyXG4gICAgICAgICAgICB0aGlzLl9lcXVhbExhc3RWZWMyKCdpbnRlcmlvcicsICdFbmQnKSAmJlxyXG4gICAgICAgICAgICB0aGlzLl9lcXVhbExhc3RWZWMyKCdleHRlcmlvcicsICdTdGFydCcpICYmXHJcbiAgICAgICAgICAgIHRoaXMuX2VxdWFsTGFzdFZlYzIoJ2V4dGVyaW9yJywgJ0VuZCcpXHJcbiAgICAgICAgKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBvbGRQbGFuZXM7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGNvbnN0IG5ld1BsYW5lcyA9IFtcclxuICAgICAgICAgICAgdGhpcy5fYnVpbGRTaWRlRmlsbGVyKHRoaXMuX2hhbGZFZGdlLmludGVyaW9yU3RhcnQoKSwgdGhpcy5faGFsZkVkZ2UuZXh0ZXJpb3JTdGFydCgpLCB0aGlzLl93YWxsLmhlaWdodCwgdGhpcy5fZmlsbGVyTWF0ZXJpYWwpLFxyXG4gICAgICAgICAgICB0aGlzLl9idWlsZFNpZGVGaWxsZXIodGhpcy5faGFsZkVkZ2UuaW50ZXJpb3JFbmQoKSwgdGhpcy5faGFsZkVkZ2UuZXh0ZXJpb3JFbmQoKSwgdGhpcy5fd2FsbC5oZWlnaHQsIHRoaXMuX2ZpbGxlck1hdGVyaWFsKVxyXG4gICAgICAgIF07XHJcbiAgICAgICAgaWYgKG9sZFBsYW5lcykge1xyXG4gICAgICAgICAgICBvbGRQbGFuZXMuZm9yRWFjaChwID0+IHtcclxuICAgICAgICAgICAgICAgIC8vIERpc3Bvc2UgZnVuY3Rpb24gZG9lcyBub3QgYWN0dWFsbHkgcmVtb3ZlIHRoZSBvYmplY3QgZnJvbSB0aGUgc2NlbmVcclxuICAgICAgICAgICAgICAgIFV0aWxzLkRpc3Bvc2VPYmplY3QocCk7XHJcbiAgICAgICAgICAgICAgICBwLnZpc2libGUgPSBmYWxzZTtcclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIC8vIG5ld1BsYW5lcy5mb3JFYWNoKHAgPT4gc2NlbmUuYWRkKHApKTtcclxuICAgICAgICByZXR1cm4gbmV3UGxhbmVzO1xyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyBhc3luYyB1cGRhdGVQbGFuZXMoKTogUHJvbWlzZTx2b2lkPiB7XHJcbiAgICAgICAgdGhpcy5fZmlsbGVyTWF0ZXJpYWwgPSB0aGlzLl91cGRhdGVGaWxsZXJNYXRlcmlhbCgpO1xyXG4gICAgICAgIGlmICh0aGlzLl9pc1ZhbGlkKFt0aGlzLl9oYWxmRWRnZS5leHRlcmlvclN0YXJ0KCksIHRoaXMuX2hhbGZFZGdlLmV4dGVyaW9yRW5kKCldKSkge1xyXG4gICAgICAgICAgICB0aGlzLl9wbGFuZXMuZXh0ZXJpb3IgPSB0aGlzLl91cGRhdGVNYWluUGxhbmUoJ2V4dGVyaW9yJywgdGhpcy5fZmlsbGVyTWF0ZXJpYWwpO1xyXG4gICAgICAgICAgICBpZiAodGhpcy5faGFsZkVkZ2UuZ2V0VGV4dHVyZSgpICYmIHRoaXMuX2hhbGZFZGdlLmdldFRleHR1cmUoKS50eXBlICE9PSBUZXh0dXJlVHlwZS5JbWFnZSkge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5fdXBkYXRlVXZzKHRoaXMuX3BsYW5lcy5leHRlcmlvcik7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGNvbnN0IG9sZFdhbGxNYXRlcmlhbCA9IHRoaXMuX3dhbGxNYXRlcmlhbDtcclxuICAgICAgICB0aGlzLl93YWxsTWF0ZXJpYWwgPSBhd2FpdCB0aGlzLl91cGRhdGVXYWxsTWF0ZXJpYWwodGhpcy5faGFsZkVkZ2UuZ2V0VGV4dHVyZSgpLCB0aGlzLl9oYWxmRWRnZS5nZXRDb2xvcigpKTtcclxuICAgICAgICBpZiAodGhpcy5faXNWYWxpZChbdGhpcy5faGFsZkVkZ2UuaW50ZXJpb3JTdGFydCgpLCB0aGlzLl9oYWxmRWRnZS5pbnRlcmlvckVuZCgpXSkpIHtcclxuICAgICAgICAgICAgLy8gdGhpcy5wbGFuZXMuaW50ZXJpb3IgPSAoIW9sZFdhbGxNYXRlcmlhbCB8fCBvbGRXYWxsTWF0ZXJpYWwgPT09IHRoaXMud2FsbE1hdGVyaWFsKVxyXG4gICAgICAgICAgICAvLyAgID8gdGhpcy51cGRhdGVNYWluUGxhbmUoJ2ludGVyaW9yJywgdGhpcy53YWxsTWF0ZXJpYWwpXHJcbiAgICAgICAgICAgIC8vICAgOiB0aGlzLnVwZGF0ZU1haW5QbGFuZU1hdGVyaWFsKCdpbnRlcmlvcicsIHRoaXMud2FsbE1hdGVyaWFsKTtcclxuICAgICAgICAgICAgdGhpcy5fcGxhbmVzLmludGVyaW9yID0gdGhpcy5fdXBkYXRlTWFpblBsYW5lKCdpbnRlcmlvcicsIHRoaXMuX3dhbGxNYXRlcmlhbCk7XHJcbiAgICAgICAgICAgIGlmICh0aGlzLl9oYWxmRWRnZS5nZXRUZXh0dXJlKCkgJiYgdGhpcy5faGFsZkVkZ2UuZ2V0VGV4dHVyZSgpLnR5cGUgIT09IFRleHR1cmVUeXBlLkltYWdlKSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLl91cGRhdGVVdnModGhpcy5fcGxhbmVzLmludGVyaW9yKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgdGhpcy5fcGxhbmVzLmJvdHRvbSA9IHRoaXMuX3VwZGF0ZUJvdHRvbVBsYW5lKCk7XHJcbiAgICAgICAgdGhpcy5fcGxhbmVzLnRvcCA9IHRoaXMuX3VwZGF0ZVRvcFBsYW5lKCk7XHJcbiAgICAgICAgdGhpcy5fcGxhbmVzLnNpZGVzID0gdGhpcy5fdXBkYXRlU2lkZVBsYW5lcygpO1xyXG5cclxuICAgICAgICB0aGlzLl9sYXN0LmZpbGxlck1hdGVyaWFsID0gdGhpcy5fZmlsbGVyTWF0ZXJpYWw7XHJcbiAgICAgICAgdGhpcy5fbGFzdC53YWxsTWF0ZXJpYWwgPSB0aGlzLl93YWxsTWF0ZXJpYWw7XHJcbiAgICAgICAgdGhpcy5fbGFzdC5oZWlnaHQgPSB0aGlzLl93YWxsLmhlaWdodDtcclxuICAgICAgICB0aGlzLl9jb3B5TGFzdCgnZXh0ZXJpb3InLCBbJ1N0YXJ0JywgJ0VuZCcsICdUcmFuc2Zvcm0nLCAnSW52VHJhbnNmb3JtJ10pO1xyXG4gICAgICAgIHRoaXMuX2NvcHlMYXN0KCdpbnRlcmlvcicsIFsnU3RhcnQnLCAnRW5kJywgJ1RyYW5zZm9ybScsICdJbnZUcmFuc2Zvcm0nXSk7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBfdXBkYXRlVXZzKG1lc2g6IE1lc2gpOiB2b2lkIHtcclxuICAgICAgICBjb25zdCBkaW1lbnNpb25zID0gbmV3IFRIUkVFLlZlY3RvcjIoXHJcbiAgICAgICAgICAgIHRoaXMuX2hhbGZFZGdlLmludGVyaW9yRGlzdGFuY2UoKSxcclxuICAgICAgICAgICAgdGhpcy5fd2FsbC5oZWlnaHQgLSB0aGlzLl93YWxsLnRoaWNrbmVzc1xyXG4gICAgICAgICkubXVsdGlwbHlTY2FsYXIoMTAwKTtcclxuICAgICAgICBjb25zdCByYXRpbzogbnVtYmVyID0gZGltZW5zaW9ucy54IC8gZGltZW5zaW9ucy55O1xyXG4gICAgICAgIGxldCB1dlk6IG51bWJlcjtcclxuICAgICAgICBjb25zdCB0ZW1wVmVjdG9yOiBWZWN0b3IyID0gbmV3IFZlY3RvcjIoKTtcclxuICAgICAgICBjb25zdCB1dkFycmF5OiBCdWZmZXJBdHRyaWJ1dGUgPSA8QnVmZmVyQXR0cmlidXRlPm1lc2guZ2VvbWV0cnkuYXR0cmlidXRlcy51djtcclxuICAgICAgICBpZiAodXZBcnJheSkge1xyXG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHV2QXJyYXkuY291bnQ7IGkrKykge1xyXG4gICAgICAgICAgICAgICAgdGVtcFZlY3Rvci5mcm9tQnVmZmVyQXR0cmlidXRlKHV2QXJyYXksIGkpO1xyXG4gICAgICAgICAgICAgICAgdXZZID0gdGVtcFZlY3Rvci55O1xyXG4gICAgICAgICAgICAgICAgdXZZIC09IDAuNTtcclxuICAgICAgICAgICAgICAgIHV2WSAvPSByYXRpbztcclxuICAgICAgICAgICAgICAgIHV2WSArPSAwLjU7XHJcbiAgICAgICAgICAgICAgICB1dkFycmF5LnNldFkoaSwgdXZZKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB1dkFycmF5Lm5lZWRzVXBkYXRlID0gdHJ1ZTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLy8gc3RhcnQsIGVuZCBoYXZlIHggYW5kIHkgYXR0cmlidXRlcyAoaS5lLiBjb3JuZXJzKVxyXG4gICAgcHJpdmF0ZSBfY3JlYXRlR2VvbWV0cnkoc3RhcnQsIGVuZCwgdHJhbnNmb3JtLCBpbnZUcmFuc2Zvcm0pOiBTaGFwZUdlb21ldHJ5IHtcclxuICAgICAgICBjb25zdCB2MSA9IHRoaXMuX3RvVmVjMyhzdGFydCk7XHJcbiAgICAgICAgY29uc3QgdjIgPSB0aGlzLl90b1ZlYzMoZW5kKTtcclxuICAgICAgICBjb25zdCB2MyA9IHYyLmNsb25lKCk7XHJcbiAgICAgICAgdjMueSA9IHRoaXMuX3dhbGwuaGVpZ2h0O1xyXG4gICAgICAgIGNvbnN0IHY0ID0gdjEuY2xvbmUoKTtcclxuICAgICAgICB2NC55ID0gdGhpcy5fd2FsbC5oZWlnaHQ7XHJcblxyXG4gICAgICAgIGNvbnN0IHBvaW50cyA9IFt2MS5jbG9uZSgpLCB2Mi5jbG9uZSgpLCB2My5jbG9uZSgpLCB2NC5jbG9uZSgpXTtcclxuXHJcbiAgICAgICAgcG9pbnRzLmZvckVhY2goKHApID0+IHtcclxuICAgICAgICAgICAgcC5hcHBseU1hdHJpeDQodHJhbnNmb3JtKTtcclxuICAgICAgICB9KTtcclxuXHJcbiAgICAgICAgY29uc3Qgc2hhcGUgPSBuZXcgU2hhcGUoW1xyXG4gICAgICAgICAgICBuZXcgVmVjdG9yMihwb2ludHNbMF0ueCwgcG9pbnRzWzBdLnkpLFxyXG4gICAgICAgICAgICBuZXcgVmVjdG9yMihwb2ludHNbMV0ueCwgcG9pbnRzWzFdLnkpLFxyXG4gICAgICAgICAgICBuZXcgVmVjdG9yMihwb2ludHNbMl0ueCwgcG9pbnRzWzJdLnkpLFxyXG4gICAgICAgICAgICBuZXcgVmVjdG9yMihwb2ludHNbM10ueCwgcG9pbnRzWzNdLnkpXHJcbiAgICAgICAgXSk7XHJcblxyXG4gICAgICAgIC8vIGFkZCBob2xlcyBmb3IgZWFjaCB3YWxsIGl0ZW1cclxuICAgICAgICBjb25zdCBpdGVtSG9sZXMgPSB0aGlzLl93YWxsLml0ZW1zXHJcbiAgICAgICAgICAgIC5maWx0ZXIoKGl0ZW06IFdhbGxJdGVtKSA9PiAhaXNOYU4oaXRlbS5wb3NpdGlvbi54KSlcclxuICAgICAgICAgICAgLm1hcCgoaXRlbTogV2FsbEl0ZW0pID0+IHtcclxuICAgICAgICAgICAgICAgIGNvbnN0IHBvcyA9IGl0ZW0ucG9zaXRpb24uY2xvbmUoKTtcclxuICAgICAgICAgICAgICAgIHBvcy5hcHBseU1hdHJpeDQodHJhbnNmb3JtKTtcclxuICAgICAgICAgICAgICAgIGNvbnN0IGhhbGZTaXplID0gaXRlbS5oYWxmU2l6ZTtcclxuICAgICAgICAgICAgICAgIGNvbnN0IG1pbiA9IGhhbGZTaXplLmNsb25lKCkubXVsdGlwbHlTY2FsYXIoLTEpO1xyXG4gICAgICAgICAgICAgICAgY29uc3QgbWF4ID0gaGFsZlNpemUuY2xvbmUoKTtcclxuICAgICAgICAgICAgICAgIG1pbi5hZGQocG9zKTtcclxuICAgICAgICAgICAgICAgIG1heC5hZGQocG9zKTtcclxuXHJcbiAgICAgICAgICAgICAgICBjb25zdCBob2xlUG9pbnRzID0gW1xyXG4gICAgICAgICAgICAgICAgICAgIG5ldyBWZWN0b3IyKG1pbi54LCBtaW4ueSksXHJcbiAgICAgICAgICAgICAgICAgICAgbmV3IFZlY3RvcjIobWF4LngsIG1pbi55KSxcclxuICAgICAgICAgICAgICAgICAgICBuZXcgVmVjdG9yMihtYXgueCwgbWF4LnkpLFxyXG4gICAgICAgICAgICAgICAgICAgIG5ldyBWZWN0b3IyKG1pbi54LCBtYXgueSlcclxuICAgICAgICAgICAgICAgIF07XHJcblxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIGhvbGVQb2ludHM7XHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgIGNvbnN0IHBvbHlnb25zID0gVXRpbHMucG9seWdvbnNVbmlvbihpdGVtSG9sZXMpO1xyXG4gICAgICAgIHBvbHlnb25zLmZvckVhY2goaG9sZVBvbHlnb24gPT4gc2hhcGUuaG9sZXMucHVzaChuZXcgUGF0aChob2xlUG9seWdvbikpKTtcclxuXHJcbiAgICAgICAgY29uc3QgZ2VvbWV0cnkgPSBuZXcgU2hhcGVHZW9tZXRyeShzaGFwZSk7XHJcblxyXG4gICAgICAgIGNvbnN0IHBvc2l0aW9uQXR0cmlidXRlOiBCdWZmZXJBdHRyaWJ1dGUgPSA8QnVmZmVyQXR0cmlidXRlPmdlb21ldHJ5LmdldEF0dHJpYnV0ZSgncG9zaXRpb24nKTtcclxuICAgICAgICBjb25zdCB1dkF0dHJpYnV0ZTogQnVmZmVyQXR0cmlidXRlID0gPEJ1ZmZlckF0dHJpYnV0ZT5nZW9tZXRyeS5nZXRBdHRyaWJ1dGUoJ3V2Jyk7XHJcbiAgICAgICAgVXRpbHMuQXBwbHlCdWZmZXJBdHRyaWJ1dGVNYXRyaXhUcmFuc2Zvcm0ocG9zaXRpb25BdHRyaWJ1dGUsIGludlRyYW5zZm9ybSk7XHJcblxyXG4gICAgICAgIC8vIG1ha2UgVVZzXHJcbiAgICAgICAgY29uc3QgdG90YWxEaXN0YW5jZSA9IFV0aWxzLmRpc3RhbmNlKHYxLngsIHYxLnosIHYyLngsIHYyLnopO1xyXG4gICAgICAgIGNvbnN0IGhlaWdodCA9IHRoaXMuX3dhbGwuaGVpZ2h0O1xyXG5cclxuICAgICAgICBmdW5jdGlvbiB2ZXJ0ZXhUb1V2KHZlcnRleCkge1xyXG4gICAgICAgICAgICBjb25zdCB4ID0gVXRpbHMuZGlzdGFuY2UodjEueCwgdjEueiwgdmVydGV4LngsIHZlcnRleC56KSAvIHRvdGFsRGlzdGFuY2U7XHJcbiAgICAgICAgICAgIGNvbnN0IHkgPSB2ZXJ0ZXgueSAvIGhlaWdodDtcclxuICAgICAgICAgICAgcmV0dXJuIG5ldyBUSFJFRS5WZWN0b3IyKHgsIHkpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgY29uc3QgdGVtcFVWQXJyYXk6IFZlY3RvcjJbXSA9IFtdO1xyXG4gICAgICAgIGNvbnN0IHBvc2l0aW9uRGF0YUFzVmVjdG9yM0FycmF5OiBWZWN0b3IzW10gPSBVdGlscy5HZXRWZWN0b3IzQXJyYXlGcm9tQnVmZmVyQXR0cmlidXRlKHBvc2l0aW9uQXR0cmlidXRlLmNsb25lKCkpO1xyXG5cclxuICAgICAgICBwb3NpdGlvbkRhdGFBc1ZlY3RvcjNBcnJheS5mb3JFYWNoKCh2ZXJ0ZXg6IFZlY3RvcjMpID0+IHtcclxuICAgICAgICAgICAgdGVtcFVWQXJyYXkucHVzaCh2ZXJ0ZXhUb1V2KHZlcnRleCkpO1xyXG4gICAgICAgIH0pO1xyXG5cclxuICAgICAgICB0ZW1wVVZBcnJheS5mb3JFYWNoKCh1dlZlY3RvcjogVmVjdG9yMiwgaW5kZXgpID0+IHtcclxuICAgICAgICAgICAgdXZBdHRyaWJ1dGUuc2V0WFkoaW5kZXgsIHV2VmVjdG9yLngsIHV2VmVjdG9yLnkpO1xyXG4gICAgICAgIH0pO1xyXG5cclxuICAgICAgICB1dkF0dHJpYnV0ZS5uZWVkc1VwZGF0ZSA9IHRydWU7XHJcbiAgICAgICAgZ2VvbWV0cnkuY29tcHV0ZVZlcnRleE5vcm1hbHMoKTtcclxuICAgICAgICByZXR1cm4gZ2VvbWV0cnk7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBfYnVpbGRTaWRlRmlsbGVyKHAxOiBWZWN0b3IyLCBwMjogVmVjdG9yMiwgaGVpZ2h0OiBudW1iZXIsIG1hdGVyaWFsOiBNYXRlcmlhbCk6IE1lc2gge1xyXG4gICAgICAgIGNvbnN0IHBvaW50cyA9IFtcclxuICAgICAgICAgICAgdGhpcy5fdG9WZWMzKHAxKSxcclxuICAgICAgICAgICAgdGhpcy5fdG9WZWMzKHAyKSxcclxuICAgICAgICAgICAgdGhpcy5fdG9WZWMzKHAyLCBoZWlnaHQpLFxyXG4gICAgICAgICAgICB0aGlzLl90b1ZlYzMocDEsIGhlaWdodClcclxuICAgICAgICBdO1xyXG5cclxuICAgICAgICBjb25zdCBnZW9tZXRyeSA9IG5ldyBCdWZmZXJHZW9tZXRyeSgpLnNldEZyb21Qb2ludHMocG9pbnRzKTtcclxuICAgICAgICBjb25zdCBmaWxsZXIgPSBuZXcgTWVzaChnZW9tZXRyeSwgbWF0ZXJpYWwpO1xyXG4gICAgICAgIGZpbGxlci5jYXN0U2hhZG93ID0gdHJ1ZTtcclxuICAgICAgICBmaWxsZXIucmVjZWl2ZVNoYWRvdyA9IHRydWU7XHJcbiAgICAgICAgZmlsbGVyLm5hbWUgPSAnZWRnZS1zaWRlLWZpbGxlcic7XHJcbiAgICAgICAgcmV0dXJuIGZpbGxlcjtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIF9idWlsZEZpbGxlcihoZWlnaHQ6IG51bWJlciwgbWF0ZXJpYWw6IE1hdGVyaWFsKTogTWVzaCB7XHJcbiAgICAgICAgY29uc3QgcG9pbnRzID0gW1xyXG4gICAgICAgICAgICB0aGlzLl90b1ZlYzIodGhpcy5faGFsZkVkZ2UuZXh0ZXJpb3JTdGFydCgpKSxcclxuICAgICAgICAgICAgdGhpcy5fdG9WZWMyKHRoaXMuX2hhbGZFZGdlLmV4dGVyaW9yRW5kKCkpLFxyXG4gICAgICAgICAgICB0aGlzLl90b1ZlYzIodGhpcy5faGFsZkVkZ2UuaW50ZXJpb3JFbmQoKSksXHJcbiAgICAgICAgICAgIHRoaXMuX3RvVmVjMih0aGlzLl9oYWxmRWRnZS5pbnRlcmlvclN0YXJ0KCkpXHJcbiAgICAgICAgXTtcclxuXHJcbiAgICAgICAgY29uc3Qgc2hhcGUgPSBuZXcgU2hhcGUocG9pbnRzKTtcclxuICAgICAgICBjb25zdCBnZW9tZXRyeSA9IG5ldyBTaGFwZUdlb21ldHJ5KHNoYXBlKTtcclxuXHJcbiAgICAgICAgY29uc3QgZmlsbGVyID0gbmV3IE1lc2goZ2VvbWV0cnksIG1hdGVyaWFsKTtcclxuICAgICAgICBmaWxsZXIubmFtZSA9ICdlZGdlLWZpbGxlcic7XHJcbiAgICAgICAgZmlsbGVyLmNhc3RTaGFkb3cgPSB0cnVlO1xyXG4gICAgICAgIGZpbGxlci5yZWNlaXZlU2hhZG93ID0gdHJ1ZTtcclxuICAgICAgICBmaWxsZXIucm90YXRpb24uc2V0KE1hdGguUEkgLyAyLCAwLCAwKTtcclxuICAgICAgICBmaWxsZXIucG9zaXRpb24ueSA9IGhlaWdodDtcclxuICAgICAgICByZXR1cm4gZmlsbGVyO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgX3RvVmVjMihwb3MpOiBWZWN0b3IyIHtcclxuICAgICAgICByZXR1cm4gbmV3IFZlY3RvcjIocG9zLngsIHBvcy55KTtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIF90b1ZlYzMocG9zOiB7IHg6IG51bWJlciwgeTogbnVtYmVyIH0sIGhlaWdodCA9IDApOiBWZWN0b3IzIHtcclxuICAgICAgICByZXR1cm4gbmV3IFZlY3RvcjMocG9zLngsIGhlaWdodCwgcG9zLnkpO1xyXG4gICAgfVxyXG59XHJcblxyXG5leHBvcnQgY2xhc3MgUm9vbSB7XHJcblxyXG4gICAgcHVibGljIGludGVyaW9yQ29ybmVyczogQ29ybmVyW10gPSBbXTtcclxuXHJcbiAgICBwcml2YXRlIGVkZ2VQb2ludGVyID0gbnVsbDtcclxuICAgIHB1YmxpYyBlZGdlSGVpZ2h0cyA9IFtdO1xyXG5cclxuICAgIHB1YmxpYyBmbG9vclBsYW5lOiBGbG9vclBsYW5lSXRlbSA9IG51bGw7XHJcbiAgICBwdWJsaWMgZmxvb3JUZXh0dXJlOiBUZXh0dXJlO1xyXG4gICAgcHVibGljIGZsb29yQ29sb3I6IG51bWJlciA9IDB4Y2NjY2NjO1xyXG4gICAgcHVibGljIGNlaWxpbmdQbGFuZTogTWVzaCA9IG51bGw7XHJcblxyXG4gICAgLy8gcHJpdmF0ZSBmbG9vckNoYW5nZUNhbGxiYWNrcyA9ICQuQ2FsbGJhY2tzKCk7XHJcblxyXG4gICAgY29uc3RydWN0b3IoXHJcbiAgICAgICAgcHVibGljIGNvcm5lcnM6IENvcm5lcltdLFxyXG4gICAgICAgIGRlZmF1bHRUZXh0dXJlPzogVGV4dHVyZVxyXG4gICAgKSB7XHJcbiAgICAgICAgaWYgKGRlZmF1bHRUZXh0dXJlKSB7XHJcbiAgICAgICAgICAgIHRoaXMuZmxvb3JUZXh0dXJlID0gZGVmYXVsdFRleHR1cmU7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHRoaXMuX3NldEVkZ2VQb2ludGVyKCk7XHJcbiAgICAgICAgdGhpcy5fdXBkYXRlSW50ZXJpb3JDb3JuZXJzKCk7XHJcbiAgICB9XHJcblxyXG4gICAgcHVibGljIGRpc3Bvc2UoKTogdm9pZCB7XHJcbiAgICAgICAgVXRpbHMuRGlzcG9zZU9iamVjdCh0aGlzLmZsb29yUGxhbmUpO1xyXG4gICAgICAgIFV0aWxzLkRpc3Bvc2VPYmplY3QodGhpcy5jZWlsaW5nUGxhbmUpO1xyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyBnZXRJbnRlcmlvckNvcm5lcnMoKTogVmVjdG9yMltdIHtcclxuICAgICAgICByZXR1cm4gdGhpcy5pbnRlcmlvckNvcm5lcnMubWFwKChjOiB7IHg6IG51bWJlciwgeTogbnVtYmVyIH0pID0+IG5ldyBWZWN0b3IyKGMueCwgYy55KSk7XHJcbiAgICB9XHJcblxyXG4gICAgcHVibGljIGdldFV1aWQoKTogc3RyaW5nIHtcclxuICAgICAgICBjb25zdCBjb3JuZXJVdWlkcyA9IFV0aWxzLm1hcCh0aGlzLmNvcm5lcnMsIGZ1bmN0aW9uIChjKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBjLmlkO1xyXG4gICAgICAgIH0pO1xyXG4gICAgICAgIGNvcm5lclV1aWRzLnNvcnQoKTtcclxuICAgICAgICByZXR1cm4gY29ybmVyVXVpZHMuam9pbigpO1xyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyBnZXRUZXh0dXJlKCkge1xyXG4gICAgICAgIC8vIGNvbnN0IHV1aWQgPSB0aGlzLmdldFV1aWQoKTtcclxuICAgICAgICAvLyByZXR1cm4gdGhpcy5mbG9vcnBsYW4uZ2V0Rmxvb3JUZXh0dXJlKHV1aWQpO1xyXG4gICAgICAgIHJldHVybiB0aGlzLmZsb29yVGV4dHVyZTtcclxuICAgIH1cclxuXHJcbiAgICBwdWJsaWMgZ2V0Q29sb3IoKSB7XHJcbiAgICAgICAgLy8gY29uc3QgdXVpZCA9IHRoaXMuZ2V0VXVpZCgpO1xyXG4gICAgICAgIC8vIHJldHVybiB0aGlzLmZsb29ycGxhbi5nZXRGbG9vckNvbG9yKHV1aWQpIHx8IGRlZmF1bHRGbG9vckNvbG9yO1xyXG4gICAgICAgIHJldHVybiB0aGlzLmZsb29yQ29sb3I7XHJcbiAgICB9XHJcblxyXG4gICAgcHVibGljIHVzZVRleHR1cmUoKSB7XHJcbiAgICAgICAgLy8gcmV0dXJuIGRlZmF1bHRGbG9vckNvbG9yID09PSB0aGlzLmdldENvbG9yKCk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiB0ZXh0dXJlU3RyZXRjaCBhbHdheXMgdHJ1ZSwganVzdCBhbiBhcmd1bWVudCBmb3IgY29uc2lzdGVuY3kgd2l0aCB3YWxsc1xyXG4gICAgICovXHJcbiAgICAvLyBwdWJsaWMgc2V0VGV4dHVyZSh0ZXh0dXJlOiBUZXh0dXJlKSB7XHJcbiAgICAvLyAgIC8vIGNvbnN0IHV1aWQgPSB0aGlzLmdldFV1aWQoKTtcclxuICAgIC8vICAgLy8gdGhpcy5mbG9vcnBsYW4uc2V0Rmxvb3JUZXh0dXJlKHV1aWQsIHRleHR1cmUpO1xyXG4gICAgLy8gICAvLyB0aGlzLmZsb29ycGxhbi5kZWxldGVGbG9vckNvbG9yKHV1aWQpO1xyXG4gICAgLy8gICAvLyB0aGlzLmZsb29yQ2hhbmdlQ2FsbGJhY2tzLmZpcmUoKTtcclxuICAgIC8vIH1cclxuXHJcbiAgICAvLyBwdWJsaWMgc2V0Q29sb3IoY29sb3I6IG51bWJlcikge1xyXG4gICAgLy8gICAvLyBjb25zdCB1dWlkID0gdGhpcy5nZXRVdWlkKCk7XHJcbiAgICAvLyAgIC8vIHRoaXMuZmxvb3JwbGFuLmRlbGV0ZUZsb29yVGV4dHVyZSh1dWlkKTtcclxuICAgIC8vICAgLy8gdGhpcy5mbG9vcnBsYW4uc2V0Rmxvb3JDb2xvcih1dWlkLCBjb2xvcik7XHJcbiAgICAvLyAgIC8vIHRoaXMuZmxvb3JDaGFuZ2VDYWxsYmFja3MuZmlyZSgpO1xyXG4gICAgLy8gfVxyXG5cclxuICAgIHB1YmxpYyB1cGRhdGVXYWxsSGVpZ2h0cygpIHtcclxuICAgICAgICBsZXQgZWRnZSA9IHRoaXMuZWRnZVBvaW50ZXI7XHJcbiAgICAgICAgdGhpcy5lZGdlSGVpZ2h0cy5sZW5ndGggPSAwO1xyXG4gICAgICAgIHdoaWxlICh0cnVlKSB7XHJcbiAgICAgICAgICAgIHRoaXMuZWRnZUhlaWdodHMucHVzaChlZGdlLndhbGwuaGVpZ2h0KTtcclxuICAgICAgICAgICAgaWYgKGVkZ2UubmV4dCA9PT0gdGhpcy5lZGdlUG9pbnRlcikge1xyXG4gICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICBlZGdlID0gZWRnZS5uZXh0O1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgc2V0RGVmYXVsdEZsb29yVGV4dHVyZSgpIHtcclxuICAgICAgICAvLyBpZiAoIXRoaXMuX2RlZmF1bHRGbG9vclRleHR1cmUpIHtcclxuICAgICAgICAvLyAgIHJldHVybjtcclxuICAgICAgICAvLyB9XHJcbiAgICAgICAgLy8gY29uc3QgdXVpZCA9IHRoaXMuZ2V0VXVpZCgpO1xyXG4gICAgICAgIC8vIGlmICghdGhpcy5mbG9vcnBsYW4uZ2V0Rmxvb3JUZXh0dXJlKHV1aWQpICYmICF0aGlzLmZsb29ycGxhbi5nZXRGbG9vckNvbG9yKHV1aWQpKSB7XHJcbiAgICAgICAgLy8gICB0aGlzLnNldFRleHR1cmUodGhpcy5fZGVmYXVsdEZsb29yVGV4dHVyZSk7XHJcbiAgICAgICAgLy8gfVxyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgX3VwZGF0ZUludGVyaW9yQ29ybmVycygpIHtcclxuICAgICAgICBsZXQgZWRnZSA9IHRoaXMuZWRnZVBvaW50ZXI7XHJcbiAgICAgICAgdGhpcy5lZGdlSGVpZ2h0cy5sZW5ndGggPSAwO1xyXG4gICAgICAgIHdoaWxlICh0cnVlKSB7XHJcbiAgICAgICAgICAgIHRoaXMuaW50ZXJpb3JDb3JuZXJzLnB1c2goZWRnZS5pbnRlcmlvclN0YXJ0KCkpO1xyXG4gICAgICAgICAgICBlZGdlLmdlbmVyYXRlUGxhbmUoKTtcclxuICAgICAgICAgICAgdGhpcy5lZGdlSGVpZ2h0cy5wdXNoKGVkZ2UuaGVpZ2h0KTtcclxuICAgICAgICAgICAgaWYgKGVkZ2UubmV4dCA9PT0gdGhpcy5lZGdlUG9pbnRlcikge1xyXG4gICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICBlZGdlID0gZWRnZS5uZXh0O1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgX3NldEVkZ2VQb2ludGVyKCkge1xyXG5cclxuICAgICAgICBsZXQgcHJldkVkZ2UgPSBudWxsO1xyXG4gICAgICAgIGxldCBmaXJzdEVkZ2UgPSBudWxsO1xyXG5cclxuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuY29ybmVycy5sZW5ndGg7IGkrKykge1xyXG5cclxuICAgICAgICAgICAgY29uc3QgZmlyc3RDb3JuZXIgPSB0aGlzLmNvcm5lcnNbaV07XHJcbiAgICAgICAgICAgIGNvbnN0IHNlY29uZENvcm5lciA9IHRoaXMuY29ybmVyc1soaSArIDEpICUgdGhpcy5jb3JuZXJzLmxlbmd0aF07XHJcblxyXG4gICAgICAgICAgICAvLyBmaW5kIGlmIHdhbGwgaXMgaGVhZGluZyBpbiB0aGF0IGRpcmVjdGlvblxyXG4gICAgICAgICAgICBjb25zdCB3YWxsVG8gPSBmaXJzdENvcm5lci53YWxsVG8oc2Vjb25kQ29ybmVyKTtcclxuICAgICAgICAgICAgY29uc3Qgd2FsbEZyb20gPSBmaXJzdENvcm5lci53YWxsRnJvbShzZWNvbmRDb3JuZXIpO1xyXG4gICAgICAgICAgICBsZXQgZWRnZTogSGFsZkVkZ2U7XHJcblxyXG4gICAgICAgICAgICBpZiAod2FsbFRvKSB7XHJcbiAgICAgICAgICAgICAgICBlZGdlID0gbmV3IEhhbGZFZGdlKHRoaXMsIHdhbGxUbywgdHJ1ZSk7XHJcbiAgICAgICAgICAgIH0gZWxzZSBpZiAod2FsbEZyb20pIHtcclxuICAgICAgICAgICAgICAgIGVkZ2UgPSBuZXcgSGFsZkVkZ2UodGhpcywgd2FsbEZyb20sIGZhbHNlKTtcclxuICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgIC8vIHNvbWV0aGluZyBob3JyaWJsZSBoYXMgaGFwcGVuZWRcclxuICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKCdjb3JuZXJzIGFyZW50IGNvbm5lY3RlZCBieSBhIHdhbGwsIHVoIG9oJyk7XHJcbiAgICAgICAgICAgIH1cclxuXHJcblxyXG4gICAgICAgICAgICBpZiAoaSA9PT0gMCkge1xyXG4gICAgICAgICAgICAgICAgZmlyc3RFZGdlID0gZWRnZTtcclxuICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgIGVkZ2UucHJldiA9IHByZXZFZGdlO1xyXG4gICAgICAgICAgICAgICAgcHJldkVkZ2UubmV4dCA9IGVkZ2U7XHJcbiAgICAgICAgICAgICAgICBpZiAoaSArIDEgPT09IHRoaXMuY29ybmVycy5sZW5ndGgpIHtcclxuICAgICAgICAgICAgICAgICAgICBmaXJzdEVkZ2UucHJldiA9IGVkZ2U7XHJcbiAgICAgICAgICAgICAgICAgICAgZWRnZS5uZXh0ID0gZmlyc3RFZGdlO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIHByZXZFZGdlID0gZWRnZTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIGhvbGQgb24gdG8gYW4gZWRnZSByZWZlcmVuY2VcclxuICAgICAgICB0aGlzLmVkZ2VQb2ludGVyID0gZmlyc3RFZGdlO1xyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyBnZXQgYXJlYSgpOiBudW1iZXIge1xyXG4gICAgICAgIGNvbnN0IHBvbHlnb24gPSB0aGlzLl9wb2x5Z29uRnJvbUNvcm5lcnModGhpcy5pbnRlcmlvckNvcm5lcnMpO1xyXG4gICAgICAgIHJldHVybiBVdGlscy5wb2x5Z29uQXJlYShwb2x5Z29uKTtcclxuICAgIH1cclxuXHJcbiAgICBwdWJsaWMgZ2V0IGNlbnRlcigpOiB7IHg6IG51bWJlciwgeTogbnVtYmVyIH0ge1xyXG4gICAgICAgIGNvbnN0IHBvbHlnb24gPSB0aGlzLl9wb2x5Z29uRnJvbUNvcm5lcnModGhpcy5jb3JuZXJzKTtcclxuICAgICAgICByZXR1cm4gVXRpbHMucG9seWdvbkNlbnRlcihwb2x5Z29uKTtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIF9wb2x5Z29uRnJvbUNvcm5lcnMoY29ybmVyczogQ29ybmVyW10pOiBWZWN0b3IyW10ge1xyXG4gICAgICAgIHJldHVybiBjb3JuZXJzLm1hcChjID0+IG5ldyBWZWN0b3IyKGMueCwgYy55KSk7XHJcbiAgICB9XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBBIFdhbGwgSXRlbSBpcyBhbiBlbnRpdHkgdG8gYmUgcGxhY2VkIHJlbGF0ZWQgdG8gYSB3YWxsLlxyXG4gKi9cclxuZXhwb3J0IGFic3RyYWN0IGNsYXNzIFdhbGxJdGVtIGV4dGVuZHMgSXRlbSB7XHJcblxyXG4gICAgLyoqIFRoZSBjdXJyZW50bHkgYXBwbGllZCB3YWxsICovXHJcbiAgICBwdWJsaWMgY3VycmVudFdhbGw6IFdhbGwgPSBudWxsO1xyXG5cclxuICAgIC8qKiBUaGUgY3VycmVudGx5IGFwcGxpZWQgd2FsbCBlZGdlLiAqL1xyXG4gICAgcHVibGljIGN1cnJlbnRXYWxsRWRnZTogSGFsZkVkZ2UgPSBudWxsO1xyXG5cclxuICAgIC8qKiBVc2VkIGZvciBmaW5kaW5nIHJvdGF0aW9ucyAqL1xyXG4gICAgcHJpdmF0ZSBfcmVmVmVjID0gbmV3IFRIUkVFLlZlY3RvcjIoMCwgMS4wKTtcclxuXHJcbiAgICBwcml2YXRlIF9wb3NpdGlvbllUb2xlcmFuY2UgPSAwLjAwNTtcclxuXHJcbiAgICAvKiogKi9cclxuICAgIHByaXZhdGUgX3dhbGxPZmZzZXRTY2FsYXIgPSAwO1xyXG5cclxuICAgIC8qKiAqL1xyXG4gICAgcHJpdmF0ZSBfc2l6ZVggPSAwO1xyXG5cclxuICAgIC8qKiAqL1xyXG4gICAgcHJpdmF0ZSBfc2l6ZVkgPSAwO1xyXG5cclxuICAgIHByaXZhdGUgX2ZsaXBwZWQgPSBmYWxzZTtcclxuICAgIHByb3RlY3RlZCB0ZXh0dXJlOiBUZXh0dXJlO1xyXG5cclxuICAgIC8qKiAqL1xyXG4gICAgcHJvdGVjdGVkIGFkZFRvV2FsbCA9IGZhbHNlO1xyXG5cclxuICAgIC8qKiAqL1xyXG4gICAgcHJvdGVjdGVkIGJvdW5kVG9GbG9vciA9IGZhbHNlO1xyXG5cclxuICAgIC8qKiAqL1xyXG4gICAgcHJvdGVjdGVkIGZyb250VmlzaWJsZSA9IGZhbHNlO1xyXG4gICAgcHJvdGVjdGVkIGJhY2tWaXNpYmxlID0gZmFsc2U7XHJcbiAgICBwcml2YXRlIF9oYXNGcm9udEVkZ2UgPSBmYWxzZTtcclxuICAgIHByaXZhdGUgX2hhc0JhY2tFZGdlID0gZmFsc2U7XHJcbiAgICBwcml2YXRlIF9vbkZyb250U2lkZTogYm9vbGVhbjtcclxuXHJcbiAgICBjb25zdHJ1Y3RvcihcclxuICAgICAgICBtZXRhZGF0YTogTWV0YWRhdGEsXHJcbiAgICAgICAgb2JqZWN0OiBPYmplY3QzRCB8IE1lc2gsXHJcbiAgICAgICAgdGV4dHVyZT86IFRleHR1cmUsXHJcbiAgICAgICAgaGFuZGxlcnM/OiBhbnlcclxuICAgICkge1xyXG4gICAgICAgIHN1cGVyKG1ldGFkYXRhLCBvYmplY3QsIHRleHR1cmUsIGhhbmRsZXJzKTtcclxuXHJcbiAgICAgICAgdGhpcy5hbGxvd1JvdGF0ZSA9IGZhbHNlO1xyXG4gICAgICAgIGlmICh0ZXh0dXJlKSB7XHJcbiAgICAgICAgICAgIHRoaXMuc2V0VGV4dHVyZSh0ZXh0dXJlKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLyoqICovXHJcbiAgICBwdWJsaWMgcmVtb3ZlZCgpIHtcclxuICAgICAgICBpZiAoIWlzTmlsbCh0aGlzLmN1cnJlbnRXYWxsRWRnZSkgJiYgdGhpcy5hZGRUb1dhbGwpIHtcclxuICAgICAgICAgICAgdGhpcy5jdXJyZW50V2FsbEVkZ2Uud2FsbC5yZW1vdmVJdGVtKHRoaXMpO1xyXG4gICAgICAgICAgICB0aGlzLnJlZHJhd1dhbGwoKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgcHVibGljIHJlbW92ZUZyb21XYWxsKCk6IHZvaWQge1xyXG4gICAgICAgIGlmICh0aGlzLmN1cnJlbnRXYWxsKSB7XHJcbiAgICAgICAgICAgIHRoaXMuY3VycmVudFdhbGwucmVtb3ZlT25JdGVtKHRoaXMpO1xyXG4gICAgICAgICAgICB0aGlzLmN1cnJlbnRXYWxsID0gdW5kZWZpbmVkO1xyXG4gICAgICAgICAgICB0aGlzLmN1cnJlbnRXYWxsRWRnZSA9IHVuZGVmaW5lZDtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBPbmx5IGhpZGVzIGl0ZW0gd2hlbiBlbnRpcmUgd2FsbCBpcyBoaWRkZW5cclxuICAgICAqIFRoaXMgcHJldmVudHMgaXRlbXMgYmVpbmcgc2V0IGhpZGRlbiBmb3IgaW5uZXIgd2FsbHNcclxuICAgICAqICovXHJcbiAgICBwdWJsaWMgdXBkYXRlRWRnZVZpc2liaWxpdHkoZWRnZTogRWRnZSkge1xyXG4gICAgICAgIGlmICh0aGlzLmN1cnJlbnRXYWxsKSB7XHJcbiAgICAgICAgICAgIGxldCBzaG91bGRTaG93OiBib29sZWFuID0gZmFsc2U7XHJcbiAgICAgICAgICAgIGlmICh0aGlzLmN1cnJlbnRXYWxsLmJhY2tFZGdlKSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLmN1cnJlbnRXYWxsLmJhY2tFZGdlLmVkZ2VzLmZvckVhY2goKGUpID0+IHtcclxuICAgICAgICAgICAgICAgICAgICBpZiAoZS52aXNpYmxlKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHNob3VsZFNob3cgPSB0cnVlO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGlmICh0aGlzLmN1cnJlbnRXYWxsLmZyb250RWRnZSkge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50V2FsbC5mcm9udEVkZ2UuZWRnZXMuZm9yRWFjaChlID0+IHtcclxuICAgICAgICAgICAgICAgICAgICBpZiAoZS52aXNpYmxlKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHNob3VsZFNob3cgPSB0cnVlO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIHRoaXMudmlzaWJsZSA9IHNob3VsZFNob3c7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8qKiAqL1xyXG4gICAgcHVibGljIHVwZGF0ZVNpemUoKSB7XHJcbiAgICAgICAgdGhpcy5fd2FsbE9mZnNldFNjYWxhciA9IHRoaXMuZ2V0RGVwdGgoKSAvIDI7XHJcbiAgICAgICAgdGhpcy5fc2l6ZVggPSB0aGlzLmdldFdpZHRoKCk7XHJcbiAgICAgICAgdGhpcy5fc2l6ZVkgPSB0aGlzLmdldEhlaWdodCgpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKiAqL1xyXG4gICAgcHVibGljIHJlc2l6ZWQoKSB7XHJcbiAgICAgICAgaWYgKHRoaXMuYm91bmRUb0Zsb29yKSB7XHJcbiAgICAgICAgICAgIHRoaXMucG9zaXRpb24ueSA9IHRoaXMuX2JvdW5kVG9GbG9vclkoKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHRoaXMudXBkYXRlU2l6ZSgpO1xyXG4gICAgICAgIHRoaXMucmVkcmF3V2FsbCgpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKiAqL1xyXG4gICAgcHVibGljIHBsYWNlT25FZGdlKGVkZ2U6IEhhbGZFZGdlKSB7XHJcbiAgICAgICAgaWYgKCFlZGdlKSB7XHJcbiAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcbiAgICAgICAgdGhpcy5fb25Gcm9udFNpZGUgPSBlZGdlLndhbGwuZnJvbnRFZGdlID09PSBlZGdlO1xyXG4gICAgICAgIHRoaXMuX2NoYW5nZVdhbGxFZGdlKGVkZ2UpO1xyXG4gICAgICAgIHRoaXMudXBkYXRlU2l6ZSgpO1xyXG5cclxuICAgICAgICAvLyBwb3NpdGlvbiBub3Qgc2V0XHJcbiAgICAgICAgY29uc3QgY2VudGVyID0gZWRnZS5pbnRlcmlvckNlbnRlcigpO1xyXG4gICAgICAgIGNvbnN0IG5ld1BvcyA9IHRoaXMucG9zaXRpb25TZXQgP1xyXG4gICAgICAgICAgICAoZWRnZS53YWxsLmFtb3VudFdhbGxNb3ZlZCA/IHRoaXMucG9zaXRpb24uYWRkKG5ldyBWZWN0b3IzKGVkZ2Uud2FsbC5hbW91bnRXYWxsTW92ZWQueCwgMCwgMCkpIDogdGhpcy5wb3NpdGlvbi5jbG9uZSgpKSA6XHJcbiAgICAgICAgICAgIG5ldyBUSFJFRS5WZWN0b3IzKGNlbnRlci54LCBlZGdlLndhbGwuaGVpZ2h0IC8gMi4wLCBjZW50ZXIueSk7XHJcbiAgICAgICAgdGhpcy5fYm91bmRNb3ZlKG5ld1Bvcyk7XHJcbiAgICAgICAgdGhpcy5wb3NpdGlvbi5jb3B5KG5ld1Bvcyk7XHJcbiAgICAgICAgdGhpcy5yZWRyYXdXYWxsKCk7XHJcbiAgICB9XHJcblxyXG4gICAgcHVibGljIHJlcG9zaXRpb24oKTogdm9pZCB7XHJcbiAgICAgICAgY29uc3QgbmV3UG9zOiBWZWN0b3IzID0gdGhpcy5wb3NpdGlvbi5jbG9uZSgpO1xyXG4gICAgICAgIHRoaXMuX2JvdW5kTW92ZShuZXdQb3MpO1xyXG4gICAgICAgIHRoaXMucG9zaXRpb24uY29weShuZXdQb3MpO1xyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyBnZXRGbG9vclkoKTogbnVtYmVyIHtcclxuICAgICAgICBpZiAodGhpcy5oYWxmU2l6ZSAmJiB0aGlzLmN1cnJlbnRXYWxsRWRnZSkge1xyXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fbW92ZVRvWVBvc2l0aW9uKHRoaXMuaGFsZlNpemUueSArIHRoaXMuZWxldmF0aW9uKTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5wb3NpdGlvbi55O1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBwdWJsaWMgaXNWYWxpZFBvc2l0aW9uKHBvc2l0aW9uOiBUSFJFRS5WZWN0b3IzLCByb3RhdGlvbj86IFRIUkVFLkV1bGVyLCBvcHRpb25zPzogYW55KTogQ29sbGlzaW9uSW5mbyB7XHJcbiAgICAgICAgcmV0dXJuIHt2YWxpZDogISF0aGlzLmN1cnJlbnRXYWxsRWRnZX07XHJcbiAgICB9XHJcblxyXG4gICAgLyoqICovXHJcbiAgICBwdWJsaWMgbW92ZVRvUG9zaXRpb24odmVjMzogVEhSRUUuVmVjdG9yMywgaW50ZXJzZWN0aW9uPzogVEhSRUUuSW50ZXJzZWN0aW9uKSB7XHJcbiAgICAgICAgaWYgKGludGVyc2VjdGlvbiAmJiB0aGlzLmN1cnJlbnRXYWxsRWRnZSkge1xyXG4gICAgICAgICAgICBpZiAoaW50ZXJzZWN0aW9uLm9iamVjdC51c2VyRGF0YS5lZGdlICYmIGludGVyc2VjdGlvbi5vYmplY3QudXNlckRhdGEuZWRnZS53YWxsICE9PSB0aGlzLmN1cnJlbnRXYWxsRWRnZS53YWxsKSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLl9jaGFuZ2VXYWxsRWRnZShpbnRlcnNlY3Rpb24ub2JqZWN0LnVzZXJEYXRhLmVkZ2UpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIHRoaXMuX2JvdW5kTW92ZSh2ZWMzKTtcclxuICAgICAgICAgICAgdGhpcy5wb3NpdGlvbi5jb3B5KHZlYzMpO1xyXG4gICAgICAgICAgICB0aGlzLnJlZHJhd1dhbGwoKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLyoqICovXHJcbiAgICBwdWJsaWMgbW92ZVRvMmRQb3NpdGlvbih4OiBudW1iZXIsIHk6IG51bWJlciwgZWRnZTogSGFsZkVkZ2UpIHtcclxuICAgICAgICBjb25zdCB2ZWMzID0gbmV3IFZlY3RvcjMoeCwgdGhpcy5wb3NpdGlvbi55LCB5KTtcclxuICAgICAgICB0aGlzLl9jaGFuZ2VXYWxsRWRnZShlZGdlKTtcclxuICAgICAgICB0aGlzLl9ib3VuZE1vdmUodmVjMyk7XHJcbiAgICAgICAgdGhpcy5wb3NpdGlvbi5jb3B5KHZlYzMpO1xyXG4gICAgICAgIHRoaXMucmVkcmF3V2FsbCgpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKiAqL1xyXG4gICAgcHVibGljIGdldFdhbGxPZmZzZXQoKSB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuX3dhbGxPZmZzZXRTY2FsYXI7XHJcbiAgICB9XHJcblxyXG4gICAgcHVibGljIGdldFN0YXJ0WCgpIHtcclxuICAgICAgICByZXR1cm4gdGhpcy5wb3NpdGlvbi54IC0gdGhpcy5nZXRTaXplWCgpIC8gMiAqIE1hdGguY29zKHRoaXMucm90YXRpb24ueSk7XHJcbiAgICB9XHJcblxyXG4gICAgcHVibGljIGdldFN0YXJ0WSgpIHtcclxuICAgICAgICByZXR1cm4gdGhpcy5wb3NpdGlvbi56ICsgdGhpcy5nZXRTaXplWCgpIC8gMiAqIE1hdGguc2luKHRoaXMucm90YXRpb24ueSk7XHJcbiAgICB9XHJcblxyXG4gICAgcHVibGljIGdldEVuZFgoKSB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMucG9zaXRpb24ueCArIHRoaXMuZ2V0U2l6ZVgoKSAvIDIgKiBNYXRoLmNvcyh0aGlzLnJvdGF0aW9uLnkpO1xyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyBnZXRFbmRZKCkge1xyXG4gICAgICAgIHJldHVybiB0aGlzLnBvc2l0aW9uLnogLSB0aGlzLmdldFNpemVYKCkgLyAyICogTWF0aC5zaW4odGhpcy5yb3RhdGlvbi55KTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICBAcmV0dXJucyB4IGF4aXMgc2l6ZSBvZiBpdGVtJ3MgYm91bmRpbmcgYm94XHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBnZXRTaXplWCgpIHtcclxuICAgICAgICByZXR1cm4gdGhpcy5fc2l6ZVg7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgQHJldHVybnMgeSBheGlzIHNpemUgb2YgaXRlbSdzIGJvdW5kaW5nIGJveFxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgZ2V0U2l6ZVkoKSB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuX3NpemVZO1xyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyBoZWlnaHRVcGRhdGVkKGFtb3VudD86IG51bWJlcik6IHZvaWQge1xyXG4gICAgICAgIGlmICghaXNOaWxsKGFtb3VudCkpIHtcclxuICAgICAgICAgICAgdGhpcy5wb3NpdGlvbi55ID0gdGhpcy5fbW92ZVRvWVBvc2l0aW9uKHRoaXMucG9zaXRpb24ueSArIGFtb3VudCk7XHJcbiAgICAgICAgICAgIHRoaXMucmVkcmF3V2FsbCgpO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIHN1cGVyLmhlaWdodFVwZGF0ZWQoKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgcHVibGljIHVwZGF0ZUdlb21ldHJ5KHdpZHRoOiBudW1iZXIsIGhlaWdodDogbnVtYmVyKSB7XHJcbiAgICAgICAgY29uc3QgZ2VvbWV0cnkgPSBHZW9tZXRyeS53YWxsQm94KHdpZHRoLCBoZWlnaHQsIHRoaXMuZ2V0SXRlbVRoaWNrbmVzcygpKTtcclxuICAgICAgICAodGhpcy5vYmplY3QgYXMgTWVzaCkuZ2VvbWV0cnkuZGlzcG9zZSgpO1xyXG4gICAgICAgIGNvbnN0IHJvdGF0aW9uID0gdGhpcy5yb3RhdGlvbi55O1xyXG4gICAgICAgIHRoaXMucm90YXRpb24ueSA9IDA7XHJcbiAgICAgICAgLy8gdGhpcy5pbml0aWFsaXplR2VvbWV0cnkoZ2VvbWV0cnkpO1xyXG4gICAgICAgIHRoaXMucm90YXRpb24ueSA9IHJvdGF0aW9uO1xyXG4gICAgICAgIHRoaXMucmVzaXplZCgpO1xyXG4gICAgICAgIHRoaXMucmVkcmF3V2FsbCgpO1xyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyBhc3luYyBzZXRUZXh0dXJlKHRleHR1cmU6IFRleHR1cmUpOiBQcm9taXNlPHZvaWQ+IHtcclxuICAgICAgICB0aGlzLnRleHR1cmUgPSB0ZXh0dXJlICYmIE9iamVjdC5hc3NpZ24oe30sIHRleHR1cmUpO1xyXG4gICAgICAgIHJldHVybiBhd2FpdCB0aGlzLmNyZWF0ZU1hdGVyaWFsKHRoaXMuY3VycmVudFdhbGxFZGdlID8gdGhpcy5jdXJyZW50V2FsbEVkZ2Uud2FsbC5zaWRlIDogdW5kZWZpbmVkKTtcclxuICAgIH1cclxuXHJcbiAgICBwdWJsaWMgb25XYWxsTW92ZWQod2FsbDogV2FsbCkge1xyXG4gICAgICAgIGlmICh3YWxsLmZyb250RWRnZSkge1xyXG4gICAgICAgICAgICB0aGlzLnBsYWNlT25FZGdlKHdhbGwuZnJvbnRFZGdlKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgaWYgKHdhbGwuYmFja0VkZ2UpIHtcclxuICAgICAgICAgICAgdGhpcy5wbGFjZU9uRWRnZSh3YWxsLmJhY2tFZGdlKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgcHVibGljIHVwZGF0ZU1hdGVyaWFsVmlzaWJpbGl0eShzaWRlOiBudW1iZXIgPSBUSFJFRS5Eb3VibGVTaWRlKSB7XHJcbiAgICAgICAgaWYgKCF0aGlzLnRleHR1cmUpIHtcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIH1cclxuICAgICAgICBpZiAodGhpcy5jdXJyZW50V2FsbEVkZ2UpIHtcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIH1cclxuICAgICAgICBjb25zdCBpc1NhbWUgPSB0aGlzLl9pc1dhbGxTYW1lKCk7XHJcbiAgICAgICAgaWYgKCFpc1NhbWUpIHtcclxuICAgICAgICAgICAgdGhpcy5jcmVhdGVNYXRlcmlhbChzaWRlLCBpc1NhbWUpO1xyXG4gICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGNvbnN0IHRleHR1cmVNYXRlcmlhbEZyb250ID0gKHRoaXMub2JqZWN0IGFzIGFueSkubWF0ZXJpYWxbNF07XHJcbiAgICAgICAgY29uc3QgdGV4dHVyZU1hdGVyaWFsQmFjayA9ICh0aGlzLm9iamVjdCBhcyBhbnkpLm1hdGVyaWFsWzVdO1xyXG4gICAgICAgIHN3aXRjaCAoc2lkZSkge1xyXG4gICAgICAgICAgICBjYXNlIFRIUkVFLkRvdWJsZVNpZGU6XHJcbiAgICAgICAgICAgICAgICB0ZXh0dXJlTWF0ZXJpYWxGcm9udC52aXNpYmxlID0gdHJ1ZTtcclxuICAgICAgICAgICAgICAgIHRleHR1cmVNYXRlcmlhbEJhY2sudmlzaWJsZSA9IHRydWU7XHJcbiAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgY2FzZSBUSFJFRS5Gcm9udFNpZGU6XHJcbiAgICAgICAgICAgICAgICB0ZXh0dXJlTWF0ZXJpYWxGcm9udC52aXNpYmxlID0gdGhpcy5mcm9udFZpc2libGU7XHJcbiAgICAgICAgICAgICAgICB0ZXh0dXJlTWF0ZXJpYWxCYWNrLnZpc2libGUgPSAhdGhpcy5mcm9udFZpc2libGU7XHJcbiAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgY2FzZSBUSFJFRS5CYWNrU2lkZTpcclxuICAgICAgICAgICAgICAgIHRleHR1cmVNYXRlcmlhbEZyb250LnZpc2libGUgPSAhdGhpcy5mcm9udFZpc2libGU7XHJcbiAgICAgICAgICAgICAgICB0ZXh0dXJlTWF0ZXJpYWxCYWNrLnZpc2libGUgPSB0aGlzLmZyb250VmlzaWJsZTtcclxuICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBwdWJsaWMgYXN5bmMgY3JlYXRlVGV4dHVyZU1hdGVyaWFsKG9wdGlvbnM/KTogUHJvbWlzZTxUSFJFRS5NZXNoUGhvbmdNYXRlcmlhbD4ge1xyXG4gICAgICAgIGNvbnN0IHtcclxuICAgICAgICAgICAgc2lkZSA9IFRIUkVFLkRvdWJsZVNpZGUsXHJcbiAgICAgICAgICAgIGZsaXAgPSBmYWxzZVxyXG4gICAgICAgIH0gPSBvcHRpb25zIHx8IHt9O1xyXG4gICAgICAgIGNvbnN0IHRleHR1cmUgPSB0aGlzLmdldFRleHR1cmUoKTtcclxuXHJcbiAgICAgICAgY29uc3QgbWF0ZXJpYWwgPSBuZXcgVEhSRUUuTWVzaFBob25nTWF0ZXJpYWwoe3NpZGV9KTtcclxuICAgICAgICBtYXRlcmlhbC50cmFuc3BhcmVudCA9IHRydWU7XHJcblxyXG4gICAgICAgIGlmICh0ZXh0dXJlKSB7XHJcbiAgICAgICAgICAgIGF3YWl0IHRoaXMuYWRkTWF0ZXJpYWxNYXAobWF0ZXJpYWwsIHRleHR1cmUsIGZsaXApO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuIG1hdGVyaWFsO1xyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyBnZXRUZXh0dXJlKCk6IFRleHR1cmUge1xyXG4gICAgICAgIHJldHVybiB0aGlzLnRleHR1cmU7XHJcbiAgICB9XHJcblxyXG4gICAgcHJvdGVjdGVkIGFzeW5jIGNyZWF0ZU1hdGVyaWFsKHNpZGU6IG51bWJlciA9IFRIUkVFLkRvdWJsZVNpZGUsIGlzU2FtZSA9IHRydWUpOiBQcm9taXNlPHZvaWQ+IHtcclxuICAgICAgICBsZXQgdGV4dHVyZU1hdGVyaWFsRnJvbnQ7XHJcbiAgICAgICAgbGV0IHRleHR1cmVNYXRlcmlhbEJhY2s7XHJcbiAgICAgICAgc3dpdGNoIChzaWRlKSB7XHJcbiAgICAgICAgICAgIGNhc2UgVEhSRUUuRG91YmxlU2lkZTpcclxuICAgICAgICAgICAgICAgIHRoaXMuX2ZsaXBwZWQgPSAhaXNTYW1lO1xyXG4gICAgICAgICAgICAgICAgdGV4dHVyZU1hdGVyaWFsRnJvbnQgPSBhd2FpdCB0aGlzLmNyZWF0ZVRleHR1cmVNYXRlcmlhbCh7c2lkZTogVEhSRUUuRnJvbnRTaWRlLCBmbGlwOiB0aGlzLl9mbGlwcGVkfSk7XHJcbiAgICAgICAgICAgICAgICB0ZXh0dXJlTWF0ZXJpYWxCYWNrID0gYXdhaXQgdGhpcy5jcmVhdGVUZXh0dXJlTWF0ZXJpYWwoe3NpZGU6IFRIUkVFLkZyb250U2lkZSwgZmxpcDogIXRoaXMuX2ZsaXBwZWR9KTtcclxuICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICBjYXNlIFRIUkVFLkZyb250U2lkZTpcclxuICAgICAgICAgICAgICAgIHRoaXMuX2ZsaXBwZWQgPSAhaXNTYW1lO1xyXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuZnJvbnRWaXNpYmxlKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGV4dHVyZU1hdGVyaWFsRnJvbnQgPSBhd2FpdCB0aGlzLmNyZWF0ZVRleHR1cmVNYXRlcmlhbCh7c2lkZTogVEhSRUUuRnJvbnRTaWRlLCBmbGlwOiB0aGlzLl9mbGlwcGVkfSk7XHJcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgIHRleHR1cmVNYXRlcmlhbEJhY2sgPSBhd2FpdCB0aGlzLmNyZWF0ZVRleHR1cmVNYXRlcmlhbCh7c2lkZTogVEhSRUUuQmFja1NpZGUsIGZsaXA6ICF0aGlzLl9mbGlwcGVkfSk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgY2FzZSBUSFJFRS5CYWNrU2lkZToge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5fZmxpcHBlZCA9ICFpc1NhbWU7XHJcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuZnJvbnRWaXNpYmxlKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGV4dHVyZU1hdGVyaWFsRnJvbnQgPSBhd2FpdCB0aGlzLmNyZWF0ZVRleHR1cmVNYXRlcmlhbCh7c2lkZTogVEhSRUUuRnJvbnRTaWRlLCBmbGlwOiB0aGlzLl9mbGlwcGVkfSk7XHJcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgIHRleHR1cmVNYXRlcmlhbEJhY2sgPSBhd2FpdCB0aGlzLmNyZWF0ZVRleHR1cmVNYXRlcmlhbCh7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHNpZGU6IFRIUkVFLkJhY2tTaWRlLCBmbGlwOiAhdGhpcy5fZmxpcHBlZFxyXG4gICAgICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgICAgKCh0aGlzLm9iamVjdCBhcyBhbnkpLm1hdGVyaWFsIGFzIGFueSkgPSB0aGlzLmdldE1hdGVyaWFscyh0ZXh0dXJlTWF0ZXJpYWxGcm9udCwgdGV4dHVyZU1hdGVyaWFsQmFjayk7XHJcbiAgICB9XHJcblxyXG4gICAgcHJvdGVjdGVkIHNldFlQb3NpdGlvbkJhc2VkT25FbGV2YXRpb24oKSB7XHJcbiAgICAgICAgdGhpcy5wb3NpdGlvbi55ID0gdGhpcy5lbGV2YXRpb24gKyB0aGlzLmhhbGZTaXplLnk7XHJcbiAgICB9XHJcblxyXG4gICAgcHJvdGVjdGVkIGFzeW5jIGFkZE1hdGVyaWFsTWFwKG1hdGVyaWFsOiBUSFJFRS5NZXNoUGhvbmdNYXRlcmlhbCwgdGV4dHVyZTogVGV4dHVyZSwgZmxpcDogYm9vbGVhbik6IFByb21pc2U8dm9pZD4ge1xyXG4gICAgICAgIGNvbnN0IGRpbWVuc2lvbnMgPSB0aGlzLmdldE1hdGVyaWFsTWFwRGltZW5zaW9ucygpO1xyXG4gICAgICAgIHRleHR1cmUuZGltZW5zaW9ucyA9IGRpbWVuc2lvbnMubXVsdGlwbHlTY2FsYXIoMTAwKTtcclxuICAgICAgICBzd2l0Y2ggKHRleHR1cmUudHlwZSkge1xyXG4gICAgICAgICAgICBjYXNlIFRleHR1cmVUeXBlLkltYWdlOlxyXG4gICAgICAgICAgICAgICAgaWYgKGZsaXApIHtcclxuICAgICAgICAgICAgICAgICAgICBtYXRlcmlhbC5tYXAgPSBhd2FpdCBNYXRlcmlhbFV0aWxzLkZyb21GbGlwcGVkSW1hZ2UodGV4dHVyZSwgZGltZW5zaW9ucyk7XHJcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgIG1hdGVyaWFsLm1hcCA9IGF3YWl0IE1hdGVyaWFsVXRpbHMuRnJvbUltYWdlKHRleHR1cmUpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgIGNhc2UgVGV4dHVyZVR5cGUuQ3VzdG9tUGF0dGVybjpcclxuICAgICAgICAgICAgICAgIG1hdGVyaWFsLm1hcCA9IGF3YWl0IE1hdGVyaWFsVXRpbHMuQ3VzdG9tVGlsZU1hcFRleHR1cmUodGV4dHVyZSwgZGltZW5zaW9ucyk7XHJcbiAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgY2FzZSBUZXh0dXJlVHlwZS5CYXNpYzpcclxuICAgICAgICAgICAgICAgIG1hdGVyaWFsLm1hcCA9IGF3YWl0IE1hdGVyaWFsVXRpbHMuRnJvbVVybCh0ZXh0dXJlLnVybCwgdGV4dHVyZS5zdHJldGNoLCB0ZXh0dXJlLnRpbGVTaXplLCBudWxsLCBudWxsLCB0ZXh0dXJlLmRpbWVuc2lvbnMsIHRleHR1cmUudGlsZVJvdGF0aW9uKTtcclxuICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgIH1cclxuICAgICAgICAvLyB0aGlzLnNjZW5lLm5lZWRzVXBkYXRlID0gdHJ1ZTtcclxuICAgICAgICAvLyB0aGlzLnNjZW5lLnRleHR1cmVMb2FkZWRDYWxsYmFja3MuZmlyZSgpO1xyXG4gICAgfVxyXG5cclxuICAgIHByb3RlY3RlZCBnZXRNYXRlcmlhbE1hcERpbWVuc2lvbnMoKTogVEhSRUUuVmVjdG9yMiB7XHJcbiAgICAgICAgcmV0dXJuIG5ldyBUSFJFRS5WZWN0b3IyKFxyXG4gICAgICAgICAgICB0aGlzLmdldFdpZHRoKCksXHJcbiAgICAgICAgICAgIHRoaXMuZ2V0SGVpZ2h0KClcclxuICAgICAgICApO1xyXG4gICAgfVxyXG5cclxuICAgIHByb3RlY3RlZCBnZXRNYXRlcmlhbHModGV4dHVyZU1hdGVyaWFsRnJvbnQ6IFRIUkVFLk1hdGVyaWFsLCB0ZXh0dXJlTWF0ZXJpYWxCYWNrOiBUSFJFRS5NYXRlcmlhbCk6IFRIUkVFLk1hdGVyaWFsW10ge1xyXG4gICAgICAgIHJldHVybiBbXHJcbiAgICAgICAgICAgIE1hdGVyaWFsVXRpbHMuZGVmYXVsdFdpbmRvdy5jbG9uZSgpLCAvLyBMZWZ0IHNpZGVcclxuICAgICAgICAgICAgTWF0ZXJpYWxVdGlscy5kZWZhdWx0V2luZG93LmNsb25lKCksIC8vIFJpZ2h0IHNpZGVcclxuICAgICAgICAgICAgTWF0ZXJpYWxVdGlscy5kZWZhdWx0V2luZG93LmNsb25lKCksIC8vIFRvcCBzaWRlXHJcbiAgICAgICAgICAgIE1hdGVyaWFsVXRpbHMuZGVmYXVsdFdpbmRvdy5jbG9uZSgpLCAvLyBCb3R0b20gc2lkZVxyXG4gICAgICAgICAgICB0ZXh0dXJlTWF0ZXJpYWxGcm9udCB8fCBNYXRlcmlhbFV0aWxzLmRlZmF1bHRXaW5kb3cuY2xvbmUoKSwgLy8gRnJvbnQgc2lkZVxyXG4gICAgICAgICAgICB0ZXh0dXJlTWF0ZXJpYWxCYWNrIHx8IE1hdGVyaWFsVXRpbHMuZGVmYXVsdFdpbmRvdy5jbG9uZSgpICAgLy8gQmFjayBzaWRlXHJcbiAgICAgICAgXTtcclxuICAgIH1cclxuXHJcbiAgICBwcm90ZWN0ZWQgZ2V0SXRlbVRoaWNrbmVzcygpOiBudW1iZXIge1xyXG4gICAgICAgIHJldHVybiB0aGlzLmN1cnJlbnRXYWxsLnRoaWNrbmVzcyAtIDAuMDE7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqICovXHJcbiAgICBwcm90ZWN0ZWQgcmVkcmF3V2FsbCgpIHtcclxuICAgICAgICBpZiAodGhpcy5jdXJyZW50V2FsbEVkZ2UgJiYgdGhpcy5jdXJyZW50V2FsbEVkZ2Uud2FsbCkge1xyXG4gICAgICAgICAgICB0aGlzLmN1cnJlbnRXYWxsRWRnZS53YWxsLmZpcmVSZWRyYXcoKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgLy8gdGhpcy51cGRhdGVFZGdlVmlzaWJpbGl0eSh0cnVlLCB0aGlzLl9vbkZyb250U2lkZSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqICovXHJcbiAgICBwcml2YXRlIF9jaGFuZ2VXYWxsRWRnZSh3YWxsRWRnZTogSGFsZkVkZ2UpIHtcclxuICAgICAgICBpZiAodGhpcy5jdXJyZW50V2FsbEVkZ2UgPT09IHdhbGxFZGdlKSB7XHJcbiAgICAgICAgICAgIGlmICghdGhpcy5jdXJyZW50V2FsbCkge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50V2FsbCA9IHdhbGxFZGdlLndhbGw7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIH1cclxuICAgICAgICBpZiAoIWlzTmlsbCh0aGlzLmN1cnJlbnRXYWxsRWRnZSkpIHtcclxuICAgICAgICAgICAgaWYgKHRoaXMuYWRkVG9XYWxsKSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLmN1cnJlbnRXYWxsRWRnZS53YWxsLnJlbW92ZUl0ZW0odGhpcyk7XHJcbiAgICAgICAgICAgICAgICB0aGlzLnJlZHJhd1dhbGwoKTtcclxuICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudFdhbGxFZGdlLndhbGwucmVtb3ZlT25JdGVtKHRoaXMpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGlmICghd2FsbEVkZ2UpIHtcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy8gZmluZCBhbmdsZSBiZXR3ZWVuIHdhbGwgbm9ybWFsc1xyXG4gICAgICAgIGNvbnN0IG5vcm1hbDIgPSBuZXcgVEhSRUUuVmVjdG9yMigpO1xyXG4gICAgICAgIGNvbnN0IG5vcm1hbDMgPSBVdGlscy5HZXRGYWNlTm9ybWFsRnJvbUJ1ZmZlckdlb21ldHJ5KHdhbGxFZGdlLnBsYW5lLmdlb21ldHJ5LCAwLCAwKTtcclxuICAgICAgICBub3JtYWwyLnggPSBub3JtYWwzLng7XHJcbiAgICAgICAgbm9ybWFsMi55ID0gbm9ybWFsMy56O1xyXG5cclxuICAgICAgICBjb25zdCBhbmdsZSA9IFV0aWxzLmFuZ2xlKFxyXG4gICAgICAgICAgICB0aGlzLl9yZWZWZWMueCwgdGhpcy5fcmVmVmVjLnksXHJcbiAgICAgICAgICAgIG5vcm1hbDIueCwgbm9ybWFsMi55KTtcclxuICAgICAgICB0aGlzLnJvdGF0aW9uLnkgPSAodGhpcy5kZWZhdWx0MTgwID8gTWF0aC5QSSA6IDApICsgYW5nbGU7XHJcbiAgICAgICAgdGhpcy50cmF2ZXJzZShjID0+IGMubWF0cml4V29ybGROZWVkc1VwZGF0ZSA9IHRydWUpO1xyXG5cclxuICAgICAgICAvLyB1cGRhdGUgY3VycmVudFdhbGxcclxuICAgICAgICB0aGlzLmN1cnJlbnRXYWxsID0gd2FsbEVkZ2Uud2FsbDtcclxuICAgICAgICB0aGlzLmN1cnJlbnRXYWxsRWRnZSA9IHdhbGxFZGdlO1xyXG4gICAgICAgIGlmICh0aGlzLmFkZFRvV2FsbCkge1xyXG4gICAgICAgICAgICB3YWxsRWRnZS53YWxsLmFkZEl0ZW0odGhpcyk7XHJcbiAgICAgICAgICAgIGlmICh0aGlzLm1ldGFkYXRhLnRleHR1cmUpIHtcclxuICAgICAgICAgICAgICAgIHRoaXMudXBkYXRlTWF0ZXJpYWxWaXNpYmlsaXR5KHdhbGxFZGdlLndhbGwuc2lkZSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgdGhpcy5yZWRyYXdXYWxsKCk7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgd2FsbEVkZ2Uud2FsbC5hZGRPbkl0ZW0odGhpcyk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgX2JvdW5kVG9GbG9vclkoKSB7XHJcbiAgICAgICAgcmV0dXJuIDAuNSAqIHRoaXMuZ2V0SGVpZ2h0KCkgKiB0aGlzLnNjYWxlLnkgKyAwLjAxO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKiB0YWtlcyB0aGUgbW92ZSB2ZWMzLCBhbmQgbWFrZXMgc3VyZSBvYmplY3Qgc3RheXMgYm91bmRlZCBvbiBwbGFuZSAqL1xyXG4gICAgcHJpdmF0ZSBfYm91bmRNb3ZlKHZlYzMpIHtcclxuICAgICAgICBjb25zdCBlZGdlID0gdGhpcy5jdXJyZW50V2FsbEVkZ2U7XHJcbiAgICAgICAgdmVjMy5hcHBseU1hdHJpeDQoZWRnZS5pbnRlcmlvclRyYW5zZm9ybSk7XHJcbiAgICAgICAgZWRnZS53YWxsLml0ZW1zQ2hhbmdlZCA9IHRydWU7XHJcblxyXG4gICAgICAgIGlmICh2ZWMzLnggPCB0aGlzLl9zaXplWCAvIDIuMCArIHRoaXMuX3Bvc2l0aW9uWVRvbGVyYW5jZSkge1xyXG4gICAgICAgICAgICB2ZWMzLnggPSB0aGlzLl9zaXplWCAvIDIuMCArIHRoaXMuX3Bvc2l0aW9uWVRvbGVyYW5jZTtcclxuICAgICAgICB9IGVsc2UgaWYgKHZlYzMueCA+IChlZGdlLmludGVyaW9yRGlzdGFuY2UoKSAtIHRoaXMuX3NpemVYIC8gMi4wIC0gdGhpcy5fcG9zaXRpb25ZVG9sZXJhbmNlKSkge1xyXG4gICAgICAgICAgICB2ZWMzLnggPSBlZGdlLmludGVyaW9yRGlzdGFuY2UoKSAtIHRoaXMuX3NpemVYIC8gMi4wIC0gdGhpcy5fcG9zaXRpb25ZVG9sZXJhbmNlO1xyXG4gICAgICAgIH1cclxuICAgICAgICBpZiAodGhpcy5ib3VuZFRvRmxvb3IpIHtcclxuICAgICAgICAgICAgdmVjMy55ID0gdGhpcy5fYm91bmRUb0Zsb29yWSgpO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIGlmICh0aGlzLmVsZXZhdGlvbkZpeGVkIHx8ICF0aGlzLmVsZXZhdGlvbkFkanVzdGFibGUpIHtcclxuICAgICAgICAgICAgICAgIC8vIGlmIGVsZXZhdGlvbiBpcyBoaWdoZXIgdGhhbiB0aGUgd2FsbCwgdXNlIG1heFlcclxuICAgICAgICAgICAgICAgIHZlYzMueSA9IE1hdGgubWluKHRoaXMuX2dldE1heFkoZWRnZSksIHRoaXMuaGFsZlNpemUueSArIHRoaXMuZWxldmF0aW9uKTtcclxuICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgIGNvbnN0IG1heFk6IG51bWJlciA9IHRoaXMuX2dldE1heFkoZWRnZSk7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBtaW5ZOiBudW1iZXIgPSB0aGlzLl9nZXRNaW5UKCk7XHJcbiAgICAgICAgICAgICAgICBpZiAodmVjMy55IDwgbWluWSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHZlYzMueSA9IG1pblk7XHJcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZlYzMueSA+IG1heFkpIHtcclxuICAgICAgICAgICAgICAgICAgICB2ZWMzLnkgPSBtYXhZO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgdGhpcy5lbGV2YXRpb24gPSB2ZWMzLnkgLSB0aGlzLmhhbGZTaXplLnk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHZlYzMueiA9IHRoaXMuZ2V0V2FsbE9mZnNldCgpO1xyXG4gICAgICAgIHZlYzMuYXBwbHlNYXRyaXg0KGVkZ2UuaW52SW50ZXJpb3JUcmFuc2Zvcm0pO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgX2lzV2FsbFNhbWUoKTogYm9vbGVhbiB7XHJcbiAgICAgICAgbGV0IGlzU2FtZSA9IGZhbHNlO1xyXG4gICAgICAgIGlmICh0aGlzLmN1cnJlbnRXYWxsRWRnZSkge1xyXG4gICAgICAgICAgICBjb25zdCBvbkZyb250U2lkZSA9IHRoaXMuY3VycmVudFdhbGxFZGdlID09PSB0aGlzLmN1cnJlbnRXYWxsRWRnZS53YWxsLmZyb250RWRnZTtcclxuICAgICAgICAgICAgaWYgKHRoaXMuX29uRnJvbnRTaWRlID09PSB1bmRlZmluZWQpIHtcclxuICAgICAgICAgICAgICAgIHRoaXMuX29uRnJvbnRTaWRlID0gb25Gcm9udFNpZGU7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgaXNTYW1lID0gb25Gcm9udFNpZGUgPT09IHRoaXMuX29uRnJvbnRTaWRlO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gaXNTYW1lO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgX2dldE1heFkoZWRnZTogSGFsZkVkZ2UpOiBudW1iZXIge1xyXG4gICAgICAgIHJldHVybiBlZGdlLmhlaWdodCAtIHRoaXMuX3NpemVZIC8gMi4wIC0gdGhpcy5fcG9zaXRpb25ZVG9sZXJhbmNlO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgX2dldE1pblQoKTogbnVtYmVyIHtcclxuICAgICAgICByZXR1cm4gdGhpcy5fc2l6ZVkgLyAyLjAgKyB0aGlzLl9wb3NpdGlvbllUb2xlcmFuY2U7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBfbW92ZVRvWVBvc2l0aW9uKHBvc2l0aW9uOiBudW1iZXIpOiBudW1iZXIge1xyXG4gICAgICAgIGNvbnN0IG1heFk6IG51bWJlciA9IHRoaXMuX2dldE1heFkodGhpcy5jdXJyZW50V2FsbEVkZ2UpO1xyXG4gICAgICAgIGNvbnN0IG1pblk6IG51bWJlciA9IHRoaXMuX2dldE1pblQoKTtcclxuICAgICAgICBpZiAocG9zaXRpb24gPiBtYXhZKSB7XHJcbiAgICAgICAgICAgIHRoaXMuZWxldmF0aW9uID0gbWF4WSAtIHRoaXMuaGFsZlNpemUueTtcclxuICAgICAgICAgICAgcmV0dXJuIG1heFk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGlmIChwb3NpdGlvbiA8IG1pblkpIHtcclxuICAgICAgICAgICAgdGhpcy5lbGV2YXRpb24gPSBtaW5ZIC0gdGhpcy5oYWxmU2l6ZS55O1xyXG4gICAgICAgICAgICByZXR1cm4gbWluWTtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIHBvc2l0aW9uO1xyXG4gICAgfVxyXG59XHJcblxyXG5leHBvcnQgY2xhc3MgSW5XYWxsSXRlbSBleHRlbmRzIFdhbGxJdGVtIHtcclxuXHJcbiAgICBwcml2YXRlIHJlYWRvbmx5IF9mcmFtZVdpZHRoOiBudW1iZXIgPSAwLjA3O1xyXG4gICAgcHJpdmF0ZSByZWFkb25seSBfZnJhbWVEZXB0aDogbnVtYmVyID0gMC4xO1xyXG4gICAgcHJpdmF0ZSByZWFkb25seSBfZGVmYXVsdEZyYW1lQ29sb3I6IG51bWJlciA9IDkwNzAxNDY7IC8vIFJBTC0xMDExXHJcbiAgICBwcml2YXRlIHJlYWRvbmx5IF9kZWZhdWx0RG9vckNvbG9yOiBudW1iZXIgPSAxNjc3NzIxNTsgLy8gUkFMLTkwMTBcclxuXHJcbiAgICBwdWJsaWMgb3BlbmluZyA9IHtcclxuICAgICAgICBzaG93OiBmYWxzZSxcclxuICAgICAgICBkb3VibGU6IGZhbHNlLFxyXG4gICAgICAgIGludmVydERpcmVjdGlvbjogZmFsc2UsXHJcbiAgICAgICAgaW52ZXJ0U2lkZTogdHJ1ZVxyXG4gICAgfTtcclxuXHJcbiAgICBwdWJsaWMgZnJhbWVDb2xvcjogbnVtYmVyID0gdGhpcy5fZGVmYXVsdEZyYW1lQ29sb3I7XHJcbiAgICBwdWJsaWMgZG9vckNvbG9yOiBudW1iZXIgPSB0aGlzLl9kZWZhdWx0RG9vckNvbG9yO1xyXG4gICAgcHVibGljIHdpbmRvd0NvbG9yOiBUSFJFRS5Db2xvciA9IG5ldyBUSFJFRS5Db2xvcigwLjA0MzEsIDAuMDU4OCwgMC4wOTAyKTtcclxuICAgIHB1YmxpYyBpc0dsYXNzOiBib29sZWFuID0gZmFsc2U7XHJcblxyXG4gICAgcHJvdGVjdGVkIHRvcEZyYW1lOiBUSFJFRS5NZXNoO1xyXG4gICAgcHJvdGVjdGVkIGxlZnRGcmFtZTogVEhSRUUuTWVzaDtcclxuICAgIHByb3RlY3RlZCByaWdodEZyYW1lOiBUSFJFRS5NZXNoO1xyXG4gICAgcHJvdGVjdGVkIGJvdHRvbUZyYW1lOiBUSFJFRS5NZXNoO1xyXG4gICAgcHJvdGVjdGVkIGN1c3RvbU1lc2g6IFRIUkVFLk1lc2g7XHJcbiAgICBwcm90ZWN0ZWQgZnJhbWVNYXRlcmlhbDogVEhSRUUuTWVzaFBob25nTWF0ZXJpYWw7XHJcbiAgICBwcm90ZWN0ZWQgZG9vck1hdGVyaWFsRnJvbnQ6IFRIUkVFLk1lc2hQaG9uZ01hdGVyaWFsO1xyXG5cclxuICAgIHByb3RlY3RlZCB3aW5kb3dNYXRlcmlhbDogVEhSRUUuTWVzaFBob25nTWF0ZXJpYWw7XHJcbiAgICBwcml2YXRlIF9pc1dpbmRvdzogYm9vbGVhbiA9IGZhbHNlO1xyXG4gICAgcHJpdmF0ZSBfZG9vcnBvc3Q6IGJvb2xlYW4gPSBmYWxzZTtcclxuXHJcbiAgICBnZXQgZG9vcnBvc3QoKTogYm9vbGVhbiB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuX2Rvb3Jwb3N0O1xyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0cnVjdG9yKFxyXG4gICAgICAgIG1ldGFkYXRhOiBNZXRhZGF0YSxcclxuICAgICAgICBvYmplY3Q6IE9iamVjdDNEIHwgTWVzaCxcclxuICAgICAgICB0ZXh0dXJlPzogVGV4dHVyZVxyXG4gICAgKSB7XHJcbiAgICAgICAgc3VwZXIobWV0YWRhdGEsIG9iamVjdCwgdGV4dHVyZSk7XHJcbiAgICAgICAgdGhpcy5fc2V0RGVmYXVsdCgpO1xyXG4gICAgICAgIHRoaXMuZnJhbWVUaXRsZSA9ICdGcmFtZSc7XHJcbiAgICAgICAgdGhpcy5jdXN0b21NZXNoVGl0bGUgPSB0aGlzLl9pc1dpbmRvdyA/ICdXaW5kb3cnIDogJ0Rvb3InO1xyXG4gICAgICAgIHRoaXMuY2FuQ2hhbmdlQ3VzdG9tTWVzaENvbG9yID0gIXRoaXMuX2lzV2luZG93O1xyXG5cclxuICAgICAgICB0aGlzLnJlY2VpdmVTaGFkb3cgPSB0cnVlO1xyXG4gICAgICAgIHRoaXMuYWRkVG9XYWxsID0gdHJ1ZTtcclxuICAgICAgICB0aGlzLl9nbGFzc01hdGVyaWFsQ2hlY2soKTtcclxuICAgIH1cclxuXHJcbiAgICBwdWJsaWMgZGlzcG9zZSgpOiB2b2lkIHtcclxuICAgICAgICBzdXBlci5kaXNwb3NlKCk7XHJcbiAgICAgICAgVXRpbHMuRGlzcG9zZU9iamVjdCh0aGlzLnRvcEZyYW1lKTtcclxuICAgICAgICBVdGlscy5EaXNwb3NlT2JqZWN0KHRoaXMubGVmdEZyYW1lKTtcclxuICAgICAgICBVdGlscy5EaXNwb3NlT2JqZWN0KHRoaXMucmlnaHRGcmFtZSk7XHJcbiAgICAgICAgVXRpbHMuRGlzcG9zZU9iamVjdCh0aGlzLmJvdHRvbUZyYW1lKTtcclxuICAgICAgICBVdGlscy5EaXNwb3NlT2JqZWN0KHRoaXMuY3VzdG9tTWVzaCk7XHJcbiAgICAgICAgVXRpbHMuRGlzcG9zZU1hdGVyaWFsKHRoaXMuZnJhbWVNYXRlcmlhbCk7XHJcbiAgICAgICAgVXRpbHMuRGlzcG9zZU1hdGVyaWFsKHRoaXMuZG9vck1hdGVyaWFsRnJvbnQpO1xyXG4gICAgICAgIFV0aWxzLkRpc3Bvc2VNYXRlcmlhbCh0aGlzLndpbmRvd01hdGVyaWFsKTtcclxuICAgIH1cclxuXHJcbiAgICBwdWJsaWMgcGxhY2VPbkVkZ2UoZWRnZTogSGFsZkVkZ2UpIHtcclxuICAgICAgICBpZiAodGhpcy5pc0N1c3RvbSkge1xyXG4gICAgICAgICAgICBjb25zdCBjaGVja01hdGVyaWFsOiBUSFJFRS5NZXNoUGhvbmdNYXRlcmlhbCA9IHRoaXMuX2lzV2luZG93ID8gdGhpcy53aW5kb3dNYXRlcmlhbCA6IHRoaXMuZG9vck1hdGVyaWFsRnJvbnQ7XHJcbiAgICAgICAgICAgIGlmICghY2hlY2tNYXRlcmlhbCkge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5fY3JlYXRlTWF0ZXJpYWxzKFRIUkVFLkRvdWJsZVNpZGUpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIHRoaXMuY3JlYXRlQ3VzdG9tTWVzaCh0aGlzLmdldFdpZHRoKCksIHRoaXMuZ2V0SGVpZ2h0KCkpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBzdXBlci5wbGFjZU9uRWRnZShlZGdlKTtcclxuICAgIH1cclxuXHJcbiAgICAvKiogKi9cclxuICAgIHB1YmxpYyBnZXRXYWxsT2Zmc2V0KCkge1xyXG4gICAgICAgIHJldHVybiAtdGhpcy5jdXJyZW50V2FsbEVkZ2Uub2Zmc2V0O1xyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyBkaXN0YW5jZUZyb20yZCh4OiBudW1iZXIsIHk6IG51bWJlcik6IG51bWJlciB7XHJcbiAgICAgICAgcmV0dXJuIFV0aWxzLnBvaW50RGlzdGFuY2VGcm9tTGluZSh4LCB5LFxyXG4gICAgICAgICAgICB0aGlzLmdldFN0YXJ0WCgpLCB0aGlzLmdldFN0YXJ0WSgpLFxyXG4gICAgICAgICAgICB0aGlzLmdldEVuZFgoKSwgdGhpcy5nZXRFbmRZKCkpO1xyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyBvbldhbGxVcGRhdGVkKHdhbGw6IFdhbGwpIHtcclxuICAgICAgICBpZiAodGhpcy5tZXRhZGF0YS50ZXh0dXJlKSB7XHJcbiAgICAgICAgICAgIHRoaXMudXBkYXRlTWF0ZXJpYWxWaXNpYmlsaXR5KHdhbGwuc2lkZSk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyB1cGRhdGVGcmFtZUNvbG9yKGNvbG9yOiBudW1iZXIpOiB2b2lkIHtcclxuICAgICAgICB0aGlzLmZyYW1lQ29sb3IgPSBjb2xvcjtcclxuICAgICAgICB0aGlzLmZyYW1lTWF0ZXJpYWwuY29sb3Iuc2V0SGV4KGNvbG9yKTtcclxuICAgICAgICB0aGlzLmZyYW1lTWF0ZXJpYWwubmVlZHNVcGRhdGUgPSB0cnVlO1xyXG4gICAgICAgIC8vIHRoaXMuc2NlbmUubmVlZHNVcGRhdGUgPSB0cnVlO1xyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyB1cGRhdGVEb29yQ29sb3IoY29sb3I6IG51bWJlcik6IHZvaWQge1xyXG4gICAgICAgIHRoaXMuZG9vckNvbG9yID0gY29sb3I7XHJcbiAgICAgICAgdGhpcy5kb29yTWF0ZXJpYWxGcm9udC5jb2xvci5zZXRIZXgoY29sb3IpO1xyXG4gICAgICAgIHRoaXMuZG9vck1hdGVyaWFsRnJvbnQudHJhbnNwYXJlbnQgPSBmYWxzZTtcclxuICAgICAgICB0aGlzLmRvb3JNYXRlcmlhbEZyb250Lm9wYWNpdHkgPSAxO1xyXG4gICAgICAgIHRoaXMuZG9vck1hdGVyaWFsRnJvbnQubWFwID0gdW5kZWZpbmVkO1xyXG4gICAgICAgIHRoaXMuZG9vck1hdGVyaWFsRnJvbnQubmVlZHNVcGRhdGUgPSB0cnVlO1xyXG4gICAgICAgIC8vIHRoaXMuc2NlbmUubmVlZHNVcGRhdGUgPSB0cnVlO1xyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyB1cGRhdGVHbGFzc01hdGVyaWFsKCkge1xyXG4gICAgICAgIGlmICghdGhpcy5pc0dsYXNzKSB7XHJcbiAgICAgICAgICAgIHRoaXMuZG9vck1hdGVyaWFsRnJvbnQuY29sb3Iuc2V0SGV4KDB4ZGZmMGYyKTtcclxuICAgICAgICAgICAgdGhpcy5kb29yTWF0ZXJpYWxGcm9udC50cmFuc3BhcmVudCA9IHRydWU7XHJcbiAgICAgICAgICAgIHRoaXMuZG9vck1hdGVyaWFsRnJvbnQuYWxwaGFUZXN0ID0gMDtcclxuICAgICAgICAgICAgdGhpcy5kb29yTWF0ZXJpYWxGcm9udC5vcGFjaXR5ID0gMC4yO1xyXG4gICAgICAgICAgICB0aGlzLmRvb3JNYXRlcmlhbEZyb250Lm1hcCA9IHVuZGVmaW5lZDtcclxuICAgICAgICAgICAgdGhpcy5kb29yTWF0ZXJpYWxGcm9udC5uZWVkc1VwZGF0ZSA9IHRydWU7XHJcbiAgICAgICAgICAgIHRoaXMuZG9vck1hdGVyaWFsRnJvbnQuc2lkZSA9IFRIUkVFLkZyb250U2lkZTtcclxuICAgICAgICAgICAgdGhpcy5pc0dsYXNzID0gdHJ1ZTtcclxuICAgICAgICAgICAgdGhpcy5jdXN0b21NZXNoLmNhc3RTaGFkb3cgPSBmYWxzZTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICB0aGlzLmRvb3JNYXRlcmlhbEZyb250LnRyYW5zcGFyZW50ID0gZmFsc2U7XHJcbiAgICAgICAgICAgIHRoaXMuZG9vck1hdGVyaWFsRnJvbnQub3BhY2l0eSA9IDE7XHJcbiAgICAgICAgICAgIHRoaXMuaXNHbGFzcyA9IGZhbHNlO1xyXG4gICAgICAgICAgICB0aGlzLmN1c3RvbU1lc2guY2FzdFNoYWRvdyA9IHRydWU7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyB1cGRhdGVHZW9tZXRyeSh3aWR0aDogbnVtYmVyLCBoZWlnaHQ6IG51bWJlcik6IHZvaWQge1xyXG4gICAgICAgIGlmICh0aGlzLmlzQ3VzdG9tKSB7XHJcbiAgICAgICAgICAgIHRoaXMuY3JlYXRlQ3VzdG9tTWVzaCh3aWR0aCwgaGVpZ2h0KTtcclxuICAgICAgICAgICAgLy8gdGhpcy5jYWxjdWxhdGVIYWxmU2l6ZSgpO1xyXG4gICAgICAgICAgICB0aGlzLnJlZHJhd1dhbGwoKTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICBzdXBlci51cGRhdGVHZW9tZXRyeSh3aWR0aCwgaGVpZ2h0KTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgcHVibGljIGFkanVzdFdhbGxCb3goZ2VvbWV0cnk6IEJveEdlb21ldHJ5KSB7XHJcbiAgICAgICAgZ2VvbWV0cnkuZ2V0QXR0cmlidXRlKCdwb3NpdGlvbicpLm5lZWRzVXBkYXRlID0gdHJ1ZTtcclxuICAgICAgICBnZW9tZXRyeS5jb21wdXRlQm91bmRpbmdCb3goKTtcclxuICAgICAgICBnZW9tZXRyeS5hcHBseU1hdHJpeDQobmV3IE1hdHJpeDQoKS5tYWtlVHJhbnNsYXRpb24oXHJcbiAgICAgICAgICAgIC0wLjUgKiAoZ2VvbWV0cnkuYm91bmRpbmdCb3gubWF4LnggKyBnZW9tZXRyeS5ib3VuZGluZ0JveC5taW4ueCksXHJcbiAgICAgICAgICAgIC0wLjUgKiAoZ2VvbWV0cnkuYm91bmRpbmdCb3gubWF4LnkgKyBnZW9tZXRyeS5ib3VuZGluZ0JveC5taW4ueSksXHJcbiAgICAgICAgICAgIC0wLjUgKiAoZ2VvbWV0cnkuYm91bmRpbmdCb3gubWF4LnogKyBnZW9tZXRyeS5ib3VuZGluZ0JveC5taW4ueilcclxuICAgICAgICApKTtcclxuICAgICAgICBnZW9tZXRyeS5jb21wdXRlQm91bmRpbmdCb3goKTtcclxuICAgICAgICAodGhpcy5vYmplY3QgYXMgTWVzaCkuZ2VvbWV0cnkgPSBnZW9tZXRyeTtcclxuICAgICAgICB0aGlzLmNhbGN1bGF0ZUhhbGZTaXplKCk7XHJcbiAgICB9XHJcblxyXG4gICAgcHVibGljIGdldFZpc2libGVNZXNoZXMoKTogVEhSRUUuTWVzaFtdIHtcclxuICAgICAgICBpZiAodGhpcy5pc0N1c3RvbSAmJiB0aGlzLnZpc2libGUpIHtcclxuICAgICAgICAgICAgY29uc3QgbWVzaGVzOiBUSFJFRS5NZXNoW10gPSBbXHJcbiAgICAgICAgICAgICAgICB0aGlzLmxlZnRGcmFtZSxcclxuICAgICAgICAgICAgICAgIHRoaXMudG9wRnJhbWUsXHJcbiAgICAgICAgICAgICAgICB0aGlzLnJpZ2h0RnJhbWUsXHJcbiAgICAgICAgICAgICAgICB0aGlzLmN1c3RvbU1lc2hcclxuICAgICAgICAgICAgXTtcclxuICAgICAgICAgICAgaWYgKHRoaXMuX2lzV2luZG93IC8qfHwgdGhpcy5fZG9vcnBvc3QqLykge1xyXG4gICAgICAgICAgICAgICAgbWVzaGVzLnB1c2godGhpcy5ib3R0b21GcmFtZSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgcmV0dXJuIG1lc2hlcztcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICByZXR1cm4gc3VwZXIuZ2V0VmlzaWJsZU1lc2hlcygpO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBwdWJsaWMgYXN5bmMgY3JlYXRlVGV4dHVyZU1hdGVyaWFsKG9wdGlvbnM/KTogUHJvbWlzZTxUSFJFRS5NZXNoUGhvbmdNYXRlcmlhbD4ge1xyXG4gICAgICAgIGlmICh0aGlzLmlzQ3VzdG9tKSB7XHJcbiAgICAgICAgICAgIGNvbnN0IHtcclxuICAgICAgICAgICAgICAgIHNpZGUgPSBUSFJFRS5Eb3VibGVTaWRlLFxyXG4gICAgICAgICAgICAgICAgZmxpcCA9IGZhbHNlXHJcbiAgICAgICAgICAgIH0gPSBvcHRpb25zIHx8IHt9O1xyXG4gICAgICAgICAgICBjb25zdCBjaGVja01hdGVyaWFsOiBUSFJFRS5NZXNoUGhvbmdNYXRlcmlhbCA9IHRoaXMuX2lzV2luZG93ID8gdGhpcy53aW5kb3dNYXRlcmlhbCA6IHRoaXMuZG9vck1hdGVyaWFsRnJvbnQ7XHJcbiAgICAgICAgICAgIGlmICghY2hlY2tNYXRlcmlhbCkge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5fY3JlYXRlTWF0ZXJpYWxzKHNpZGUpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGNvbnN0IHRleHR1cmUgPSB0aGlzLmdldFRleHR1cmUoKTtcclxuICAgICAgICAgICAgaWYgKCF0ZXh0dXJlKSB7XHJcbiAgICAgICAgICAgICAgICAvLyByZXNldCB0byBkZWZhdWx0IHRleHR1cmVcclxuICAgICAgICAgICAgICAgIHRoaXMuX2NyZWF0ZU1hdGVyaWFscyhzaWRlKTtcclxuICAgICAgICAgICAgICAgIHRoaXMuY3JlYXRlQ3VzdG9tTWVzaCh0aGlzLmdldFdpZHRoKCksIHRoaXMuZ2V0SGVpZ2h0KCkpO1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2lzV2luZG93ID8gdGhpcy53aW5kb3dNYXRlcmlhbCA6IHRoaXMuZG9vck1hdGVyaWFsRnJvbnQ7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgY29uc3QgbWF0ZXJpYWw6IFRIUkVFLk1lc2hQaG9uZ01hdGVyaWFsID0gdGhpcy5faXNXaW5kb3cgPyB0aGlzLndpbmRvd01hdGVyaWFsIDogdGhpcy5kb29yTWF0ZXJpYWxGcm9udDtcclxuICAgICAgICAgICAgY29uc3QgZGVmYXVsdE1hdGVyaWFsOiBUSFJFRS5NZXNoUGhvbmdNYXRlcmlhbCA9IG5ldyBUSFJFRS5NZXNoUGhvbmdNYXRlcmlhbCgpO1xyXG5cclxuICAgICAgICAgICAgbWF0ZXJpYWwudHJhbnNwYXJlbnQgPSBmYWxzZTtcclxuICAgICAgICAgICAgbWF0ZXJpYWwuY29sb3IgPSBkZWZhdWx0TWF0ZXJpYWwuY29sb3IuY2xvbmUoKTtcclxuICAgICAgICAgICAgbWF0ZXJpYWwub3BhY2l0eSA9IGRlZmF1bHRNYXRlcmlhbC5vcGFjaXR5O1xyXG4gICAgICAgICAgICBtYXRlcmlhbC5yZWZyYWN0aW9uUmF0aW8gPSBkZWZhdWx0TWF0ZXJpYWwucmVmcmFjdGlvblJhdGlvO1xyXG4gICAgICAgICAgICBtYXRlcmlhbC5zaGluaW5lc3MgPSBkZWZhdWx0TWF0ZXJpYWwuc2hpbmluZXNzO1xyXG4gICAgICAgICAgICBtYXRlcmlhbC5zcGVjdWxhciA9IGRlZmF1bHRNYXRlcmlhbC5zcGVjdWxhci5jbG9uZSgpO1xyXG5cclxuICAgICAgICAgICAgLy8gQWxsb3dzIGZvciB0cmFuc3BhcmVuY3kgaW4gcG5nJ3NcclxuICAgICAgICAgICAgbWF0ZXJpYWwuYWxwaGFUZXN0ID0gMC41O1xyXG4gICAgICAgICAgICAvLyBNYWtlcyBzdXJlIHRoZSBpbWFnZSBpbiBvbmx5IHByb2plY3RlZCBvbmNlIG9uIHRoZSBtZXNoXHJcbiAgICAgICAgICAgIG1hdGVyaWFsLnNpZGUgPSBUSFJFRS5Gcm9udFNpZGU7XHJcbiAgICAgICAgICAgIC8vIFJlbW92ZXMgd2hpdGUgZWRnZXMgc3Vycm91bmRpbmcgdGhlIGltYWdlXHJcbiAgICAgICAgICAgIG1hdGVyaWFsLnRyYW5zcGFyZW50ID0gdHJ1ZTtcclxuXHJcbiAgICAgICAgICAgIC8vIG1hdGVyaWFsLmNvbG9yID0gbmV3IFRIUkVFLkNvbG9yKDEsIDEsIDEpO1xyXG4gICAgICAgICAgICBhd2FpdCB0aGlzLmFkZE1hdGVyaWFsTWFwKG1hdGVyaWFsLCB0ZXh0dXJlLCBmbGlwKTtcclxuICAgICAgICAgICAgbWF0ZXJpYWwubmVlZHNVcGRhdGUgPSB0cnVlO1xyXG4gICAgICAgICAgICByZXR1cm4gbWF0ZXJpYWw7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgcmV0dXJuIGF3YWl0IHN1cGVyLmNyZWF0ZVRleHR1cmVNYXRlcmlhbChvcHRpb25zKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgcHVibGljIGNyZWF0ZUN1c3RvbU1lc2god2lkdGg6IG51bWJlciwgaGVpZ2h0OiBudW1iZXIpOiB2b2lkIHtcclxuICAgICAgICBjb25zdCBoYWxmV2lkdGg6IG51bWJlciA9IHdpZHRoIC8gMjtcclxuICAgICAgICBjb25zdCBoYWxmRnJhbWU6IG51bWJlciA9ICh0aGlzLl9mcmFtZVdpZHRoIC8gMik7XHJcblxyXG4gICAgICAgIHRoaXMubGVmdEZyYW1lID0gdGhpcy5fY3JlYXRlRnJhbWVTaWRlKHRoaXMuX2ZyYW1lV2lkdGgsIHRoaXMuX2dldEhlaWdodEZyYW1lKGhlaWdodCksIHRoaXMuX2ZyYW1lRGVwdGgpO1xyXG4gICAgICAgIHRoaXMubGVmdEZyYW1lLnJvdGF0aW9uLnNldCh0aGlzLl9pc1dpbmRvdyA/IDE4MCAqIChNYXRoLlBJIC8gMTgwKSA6IDAsIDAsIDApO1xyXG4gICAgICAgIHRoaXMubGVmdEZyYW1lLnBvc2l0aW9uLnggPSAtaGFsZldpZHRoICsgaGFsZkZyYW1lO1xyXG4gICAgICAgIHRoaXMubGVmdEZyYW1lLm5hbWUgPSAnbGVmdEZyYW1lJztcclxuICAgICAgICBpZiAoIXRoaXMuX2lzV2luZG93KSB7XHJcbiAgICAgICAgICAgIHRoaXMubGVmdEZyYW1lLnBvc2l0aW9uLnkgPSAtKHRoaXMuX2ZyYW1lV2lkdGggLyAyKSArIDAuMDI7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICB0aGlzLnRvcEZyYW1lID0gdGhpcy5fY3JlYXRlRnJhbWVTaWRlKHRoaXMuX2ZyYW1lV2lkdGgsIHdpZHRoLCB0aGlzLl9mcmFtZURlcHRoKTtcclxuICAgICAgICB0aGlzLnRvcEZyYW1lLnJvdGF0aW9uLnNldCgwLCB0aGlzLl9pc1dpbmRvdyA/IDE4MCAqIChNYXRoLlBJIC8gMTgwKSA6IDAsIC05MCAqIChNYXRoLlBJIC8gMTgwKSk7XHJcbiAgICAgICAgdGhpcy50b3BGcmFtZS5wb3NpdGlvbi55ID0gKGhlaWdodCAvIDIpIC0gKHRoaXMuX2ZyYW1lV2lkdGggLyAyKTtcclxuICAgICAgICB0aGlzLnRvcEZyYW1lLm5hbWUgPSAndG9wRnJhbWUnO1xyXG5cclxuICAgICAgICB0aGlzLnJpZ2h0RnJhbWUgPSB0aGlzLl9jcmVhdGVGcmFtZVNpZGUodGhpcy5fZnJhbWVXaWR0aCwgdGhpcy5fZ2V0SGVpZ2h0RnJhbWUoaGVpZ2h0KSwgdGhpcy5fZnJhbWVEZXB0aCk7XHJcbiAgICAgICAgdGhpcy5yaWdodEZyYW1lLnJvdGF0aW9uLnNldCh0aGlzLl9pc1dpbmRvdyA/IDE4MCAqIChNYXRoLlBJIC8gMTgwKSA6IDAsIDAsIC0xODAgKiAoTWF0aC5QSSAvIDE4MCkpO1xyXG4gICAgICAgIHRoaXMucmlnaHRGcmFtZS5wb3NpdGlvbi54ID0gKHdpZHRoIC8gMikgLSAodGhpcy5fZnJhbWVXaWR0aCAvIDIpO1xyXG4gICAgICAgIHRoaXMucmlnaHRGcmFtZS5uYW1lID0gJ3JpZ2h0RnJhbWUnO1xyXG4gICAgICAgIGlmICghdGhpcy5faXNXaW5kb3cpIHtcclxuICAgICAgICAgICAgdGhpcy5yaWdodEZyYW1lLnBvc2l0aW9uLnkgPSAtKHRoaXMuX2ZyYW1lV2lkdGggLyAyKSArIDAuMDI7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAodGhpcy5faXNXaW5kb3cgLyp8fCB0aGlzLl9kb29ycG9zdCovKSB7XHJcbiAgICAgICAgICAgIHRoaXMuYm90dG9tRnJhbWUgPSB0aGlzLl9jcmVhdGVGcmFtZVNpZGUodGhpcy5fZnJhbWVXaWR0aCwgd2lkdGgsIHRoaXMuX2ZyYW1lRGVwdGgpO1xyXG4gICAgICAgICAgICB0aGlzLmJvdHRvbUZyYW1lLnJvdGF0aW9uLnNldCgwLCAxODAgKiAoTWF0aC5QSSAvIDE4MCksIDkwICogKE1hdGguUEkgLyAxODApKTtcclxuICAgICAgICAgICAgdGhpcy5ib3R0b21GcmFtZS5wb3NpdGlvbi55ID0gLShoZWlnaHQgLyAyKSArICh0aGlzLl9mcmFtZVdpZHRoIC8gMik7XHJcbiAgICAgICAgICAgIHRoaXMuYm90dG9tRnJhbWUubmFtZSA9ICdib3R0b21GcmFtZSc7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBsZXQgY3VzdG9tR2VvOiBUSFJFRS5Cb3hHZW9tZXRyeTtcclxuICAgICAgICBpZiAodGhpcy5faXNXaW5kb3cpIHtcclxuICAgICAgICAgICAgY3VzdG9tR2VvID0gbmV3IFRIUkVFLkJveEdlb21ldHJ5KHdpZHRoIC0gKDIgKiB0aGlzLl9mcmFtZVdpZHRoKSArIDAuMDQsIGhlaWdodCAtICgyICogdGhpcy5fZnJhbWVXaWR0aCkgKyAwLjA0LCAwLjAyNCk7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgY3VzdG9tR2VvID0gbmV3IFRIUkVFLkJveEdlb21ldHJ5KHdpZHRoIC0gMC4wMiAqICh0aGlzLl9mcmFtZVdpZHRoIC0gMC4wMiksIGhlaWdodCAtICh0aGlzLl9mcmFtZVdpZHRoIC0gMC4wMiksIDAuMDQpO1xyXG4gICAgICAgIH1cclxuICAgICAgICB0aGlzLmN1c3RvbU1lc2ggPSBuZXcgVEhSRUUuTWVzaChjdXN0b21HZW8sIHRoaXMuX2lzV2luZG93ID8gdGhpcy53aW5kb3dNYXRlcmlhbCA6IHRoaXMuZG9vck1hdGVyaWFsRnJvbnQpO1xyXG4gICAgICAgIHRoaXMuY3VzdG9tTWVzaC5jYXN0U2hhZG93ID0gdGhpcy5faXNXaW5kb3cgPyBmYWxzZSA6ICF0aGlzLmlzR2xhc3M7XHJcbiAgICAgICAgdGhpcy5jdXN0b21NZXNoLnJlbmRlck9yZGVyID0gLTE7XHJcblxyXG4gICAgICAgIHRoaXMuY3VzdG9tTWVzaC5uYW1lID0gJ2N1c3RvbU1lc2gnO1xyXG4gICAgICAgIGlmICh0aGlzLl9pc1dpbmRvdykge1xyXG4gICAgICAgICAgICB0aGlzLmN1c3RvbU1lc2gubmFtZSArPSAnV2luZG93JztcclxuICAgICAgICB9XHJcbiAgICAgICAgaWYgKHRoaXMuaXNHbGFzcykge1xyXG4gICAgICAgICAgICB0aGlzLmN1c3RvbU1lc2gubmFtZSArPSAnR2xhc3MnO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKHRoaXMuX2lzV2luZG93KSB7XHJcbiAgICAgICAgICAgIHRoaXMuY3VzdG9tTWVzaC5wb3NpdGlvbi56ID0gLTAuMDEyO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIHRoaXMuY3VzdG9tTWVzaC5wb3NpdGlvbi55ID0gLSh0aGlzLl9mcmFtZVdpZHRoIC8gMikgKyAwLjAxO1xyXG4gICAgICAgICAgICB0aGlzLmN1c3RvbU1lc2gucG9zaXRpb24ueiA9IDAuMDI7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHRoaXMuX2dldEFkZGl0aW9uYWxUZXh0dXJlKCkudGhlbigoZnJvbnRBZGRpdGlvbmFsT2JqOiBUSFJFRS5NZXNoKSA9PiB7XHJcbiAgICAgICAgICAgIGlmIChmcm9udEFkZGl0aW9uYWxPYmopIHtcclxuICAgICAgICAgICAgICAgIGNvbnN0IGJhY2tBZGRpdGlvbmFsT2JqID0gZnJvbnRBZGRpdGlvbmFsT2JqLmNsb25lKHRydWUpO1xyXG4gICAgICAgICAgICAgICAgYmFja0FkZGl0aW9uYWxPYmoucm90YXRpb24ueCA9IDE4MCAqIChNYXRoLlBJIC8gMTgwKTtcclxuICAgICAgICAgICAgICAgIGlmICh0aGlzLmFkZGl0aW9uYWxUZXh0dXJlLmRhdGEpIHtcclxuICAgICAgICAgICAgICAgICAgICBmcm9udEFkZGl0aW9uYWxPYmoucG9zaXRpb24uc2V0KFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAtKHdpZHRoIC8gMikgKyB0aGlzLmFkZGl0aW9uYWxUZXh0dXJlLmRhdGEueCwgLShoZWlnaHQgLyAyKSArIHRoaXMuYWRkaXRpb25hbFRleHR1cmUuZGF0YS55LCAwLjAyKTtcclxuICAgICAgICAgICAgICAgICAgICBiYWNrQWRkaXRpb25hbE9iai5wb3NpdGlvbi5zZXQoXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIC0od2lkdGggLyAyKSArIHRoaXMuYWRkaXRpb25hbFRleHR1cmUuZGF0YS54LCAtKGhlaWdodCAvIDIpICsgdGhpcy5hZGRpdGlvbmFsVGV4dHVyZS5kYXRhLnksIC0wLjAyKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIHRoaXMuY3VzdG9tTWVzaC5hZGQoZnJvbnRBZGRpdGlvbmFsT2JqKTtcclxuICAgICAgICAgICAgICAgIHRoaXMuY3VzdG9tTWVzaC5hZGQoYmFja0FkZGl0aW9uYWxPYmopO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfSk7XHJcblxyXG4gICAgICAgIHRoaXMuY2hpbGRyZW4ubGVuZ3RoID0gMDtcclxuICAgICAgICB0aGlzLmFkZCh0aGlzLmxlZnRGcmFtZSwgdGhpcy5yaWdodEZyYW1lLCB0aGlzLnRvcEZyYW1lLCB0aGlzLmN1c3RvbU1lc2gpO1xyXG4gICAgICAgIGlmICh0aGlzLl9pc1dpbmRvdyAvKnx8IHRoaXMuX2Rvb3Jwb3N0Ki8pIHtcclxuICAgICAgICAgICAgdGhpcy5hZGQodGhpcy5ib3R0b21GcmFtZSk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHRoaXMuY2FsY3VsYXRlSGFsZlNpemUoKTtcclxuICAgICAgICAvLyB0aGlzLnNjZW5lLm5lZWRzVXBkYXRlID0gdHJ1ZTtcclxuICAgIH1cclxuXHJcbiAgICBwdWJsaWMgY2xvbmVJdGVtKCk6IEluV2FsbEl0ZW0ge1xyXG4gICAgICAgIGNvbnN0IGNsb25lOiBJbldhbGxJdGVtID0gdGhpcy5jcmVhdGVDbGFzcygpO1xyXG4gICAgICAgIHRoaXMuY2xvbmVQcm9wZXJ0aWVzKGNsb25lKTtcclxuICAgICAgICBjbG9uZS5uYW1lID0gJ3Rlc3QgY2xvbmUnO1xyXG4gICAgICAgIHJldHVybiBjbG9uZTtcclxuICAgIH1cclxuXHJcbiAgICBwcm90ZWN0ZWQgYXN5bmMgY3JlYXRlTWF0ZXJpYWwoc2lkZSA9IFRIUkVFLkRvdWJsZVNpZGUsIGlzU2FtZSA9IHRydWUpOiBQcm9taXNlPHZvaWQ+IHtcclxuICAgICAgICBpZiAodGhpcy5pc0N1c3RvbSkge1xyXG4gICAgICAgICAgICBhd2FpdCB0aGlzLmNyZWF0ZVRleHR1cmVNYXRlcmlhbCh7c2lkZTogVEhSRUUuRnJvbnRTaWRlLCBmbGlwOiBmYWxzZX0pO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIGF3YWl0IHN1cGVyLmNyZWF0ZVRleHR1cmVNYXRlcmlhbCh7c2lkZSwgaXNTYW1lfSk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHByb3RlY3RlZCBjcmVhdGVDbGFzcygpOiBJbldhbGxJdGVtIHtcclxuICAgICAgICAvLyBjcmVhdGUgbmV3IG9iamVjdCBmb3IgcHJvcGVyIGRpbWVuc2lvbnNcclxuICAgICAgICBjb25zdCBtZXNoOiBNZXNoID0gbmV3IE1lc2gobmV3IEJveEdlb21ldHJ5KHRoaXMuaGFsZlNpemUueCAqIDIsIHRoaXMuaGFsZlNpemUueSAqIDIsIHRoaXMuaGFsZlNpemUueiAqIDIpKTtcclxuICAgICAgICByZXR1cm4gbmV3IEluV2FsbEl0ZW0odGhpcy5tZXRhZGF0YSwgbWVzaCk7XHJcbiAgICB9XHJcblxyXG4gICAgcHJvdGVjdGVkIGNsb25lUHJvcGVydGllcyhjbG9uZTogSW5XYWxsSXRlbSk6IHZvaWQge1xyXG4gICAgICAgIGNsb25lLnVzZXJEYXRhID0gdGhpcy51c2VyRGF0YTtcclxuICAgICAgICBjbG9uZS5kb29yTWF0ZXJpYWxGcm9udCA9IHRoaXMuZG9vck1hdGVyaWFsRnJvbnQgPyA8TWVzaFBob25nTWF0ZXJpYWw+dGhpcy5kb29yTWF0ZXJpYWxGcm9udC5jbG9uZSgpIDogdW5kZWZpbmVkO1xyXG4gICAgICAgIGlmIChjbG9uZS5kb29yTWF0ZXJpYWxGcm9udCkge1xyXG4gICAgICAgICAgICBjbG9uZS5kb29yTWF0ZXJpYWxGcm9udC5lbWlzc2l2ZSA9IG5ldyBUSFJFRS5Db2xvcigweDAwMDAwMCk7XHJcbiAgICAgICAgICAgIGNsb25lLmRvb3JNYXRlcmlhbEZyb250Lm5lZWRzVXBkYXRlID0gdHJ1ZTtcclxuICAgICAgICB9XHJcbiAgICAgICAgY2xvbmUud2luZG93TWF0ZXJpYWwgPSB0aGlzLndpbmRvd01hdGVyaWFsID8gPE1lc2hQaG9uZ01hdGVyaWFsPnRoaXMud2luZG93TWF0ZXJpYWwuY2xvbmUoKSA6IHVuZGVmaW5lZDtcclxuICAgICAgICBpZiAoY2xvbmUud2luZG93TWF0ZXJpYWwpIHtcclxuICAgICAgICAgICAgY2xvbmUud2luZG93TWF0ZXJpYWwuZW1pc3NpdmUgPSBuZXcgVEhSRUUuQ29sb3IoMHgwMDAwMDApO1xyXG4gICAgICAgICAgICBjbG9uZS53aW5kb3dNYXRlcmlhbC5uZWVkc1VwZGF0ZSA9IHRydWU7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGNsb25lLmZyYW1lTWF0ZXJpYWwgPSB0aGlzLmZyYW1lTWF0ZXJpYWwgPyA8TWVzaFBob25nTWF0ZXJpYWw+dGhpcy5mcmFtZU1hdGVyaWFsLmNsb25lKCkgOiB1bmRlZmluZWQ7XHJcbiAgICAgICAgaWYgKGNsb25lLmZyYW1lTWF0ZXJpYWwpIHtcclxuICAgICAgICAgICAgY2xvbmUuZnJhbWVNYXRlcmlhbC5lbWlzc2l2ZSA9IG5ldyBUSFJFRS5Db2xvcigweDAwMDAwMCk7XHJcbiAgICAgICAgICAgIGNsb25lLmZyYW1lTWF0ZXJpYWwubmVlZHNVcGRhdGUgPSB0cnVlO1xyXG4gICAgICAgIH1cclxuICAgICAgICBjbG9uZS5mcmFtZUNvbG9yID0gdGhpcy5mcmFtZUNvbG9yO1xyXG4gICAgICAgIGNsb25lLmRvb3JDb2xvciA9IHRoaXMuZG9vckNvbG9yO1xyXG4gICAgICAgICgoY2xvbmUub2JqZWN0IGFzIE1lc2gpLm1hdGVyaWFsIGFzIGFueSkgPSBbY2xvbmUuZnJhbWVNYXRlcmlhbCwgY2xvbmUuX2lzV2luZG93ID8gY2xvbmUud2luZG93TWF0ZXJpYWwgOiBjbG9uZS5kb29yTWF0ZXJpYWxGcm9udF07XHJcbiAgICAgICAgY2xvbmUudGV4dHVyZSA9IHRoaXMudGV4dHVyZTtcclxuICAgICAgICBjbG9uZS5hZGRpdGlvbmFsVGV4dHVyZSA9IHRoaXMuYWRkaXRpb25hbFRleHR1cmU7XHJcbiAgICAgICAgY2xvbmUuaXNHbGFzcyA9IHRoaXMuaXNHbGFzcztcclxuICAgIH1cclxuXHJcbiAgICBwcm90ZWN0ZWQgZ2V0TWF0ZXJpYWxzKHRleHR1cmVNYXRlcmlhbEZyb250OiBUSFJFRS5NYXRlcmlhbCwgdGV4dHVyZU1hdGVyaWFsQmFjazogVEhSRUUuTWF0ZXJpYWwpOiBUSFJFRS5NYXRlcmlhbFtdIHtcclxuICAgICAgICBpZiAodGhpcy5pc0N1c3RvbSkge1xyXG4gICAgICAgICAgICByZXR1cm4gKHRoaXMub2JqZWN0IGFzIE1lc2gpLm1hdGVyaWFsIGFzIGFueTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICByZXR1cm4gc3VwZXIuZ2V0TWF0ZXJpYWxzKHRleHR1cmVNYXRlcmlhbEZyb250LCB0ZXh0dXJlTWF0ZXJpYWxCYWNrKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgcHJvdGVjdGVkIGdldE1hdGVyaWFsTWFwRGltZW5zaW9ucygpOiBUSFJFRS5WZWN0b3IyIHtcclxuICAgICAgICBpZiAodGhpcy5pc0N1c3RvbSkge1xyXG4gICAgICAgICAgICByZXR1cm4gbmV3IFRIUkVFLlZlY3RvcjIoXHJcbiAgICAgICAgICAgICAgICB0aGlzLmdldFdpZHRoKCkgLSAwLjE0LFxyXG4gICAgICAgICAgICAgICAgdGhpcy5nZXRIZWlnaHQoKSAtIDAuMDdcclxuICAgICAgICAgICAgKTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICByZXR1cm4gc3VwZXIuZ2V0TWF0ZXJpYWxNYXBEaW1lbnNpb25zKCk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHByb3RlY3RlZCBpbml0aWF0ZUl0ZW1PYmplY3QoZGF0YTogYW55KTogdm9pZCB7XHJcbiAgICAgICAgaWYgKHRoaXMuaXNDdXN0b20gJiYgZGF0YSAmJiBkYXRhLmdlb21ldHJ5KSB7XHJcbiAgICAgICAgICAgIGRhdGEuZ2VvbWV0cnkudmVydGljZXNOZWVkVXBkYXRlID0gdHJ1ZTtcclxuICAgICAgICAgICAgZGF0YS5nZW9tZXRyeS5jb21wdXRlQm91bmRpbmdCb3goKTtcclxuICAgICAgICAgICAgZGF0YS5nZW9tZXRyeS5hcHBseU1hdHJpeDQobmV3IE1hdHJpeDQoKS5tYWtlVHJhbnNsYXRpb24oXHJcbiAgICAgICAgICAgICAgICAtMC41ICogKGRhdGEuZ2VvbWV0cnkuYm91bmRpbmdCb3gubWF4LnggKyBkYXRhLmdlb21ldHJ5LmJvdW5kaW5nQm94Lm1pbi54KSxcclxuICAgICAgICAgICAgICAgIC0wLjUgKiAoZGF0YS5nZW9tZXRyeS5ib3VuZGluZ0JveC5tYXgueSArIGRhdGEuZ2VvbWV0cnkuYm91bmRpbmdCb3gubWluLnkpLFxyXG4gICAgICAgICAgICAgICAgLTAuNSAqIChkYXRhLmdlb21ldHJ5LmJvdW5kaW5nQm94Lm1heC56ICsgZGF0YS5nZW9tZXRyeS5ib3VuZGluZ0JveC5taW4ueilcclxuICAgICAgICAgICAgKSk7XHJcbiAgICAgICAgICAgIGRhdGEuZ2VvbWV0cnkuY29tcHV0ZUJvdW5kaW5nQm94KCk7XHJcbiAgICAgICAgICAgIGNvbnN0IG1heCA9IGRhdGEuZ2VvbWV0cnkuYm91bmRpbmdCb3gubWF4LmNsb25lKCk7XHJcbiAgICAgICAgICAgIGNvbnN0IG1pbiA9IGRhdGEuZ2VvbWV0cnkuYm91bmRpbmdCb3gubWluLmNsb25lKCk7XHJcbiAgICAgICAgICAgIHRoaXMuaGFsZlNpemUgPSBtYXguc3ViKG1pbikuZGl2aWRlU2NhbGFyKDIpO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIF9zZXREZWZhdWx0KCk6IHZvaWQge1xyXG4gICAgICAgIC8vIHdvcmthcm91bmQgYmVjYXVzZSBwcm9wZXJ0aWVzIGFyZSBub3QgYXZhaWxhYmxlIHlldCB3aGVuIGNyZWF0aW5nIHdpbmRvdy9kb29yIGZyb20gbG9hZGluZyBmcm9tIGNsb3VkL2xvY2FsXHJcbiAgICAgICAgdGhpcy5mcmFtZUNvbG9yID0gdGhpcy5tZXRhZGF0YS5mcmFtZUNvbG9yID8gdGhpcy5tZXRhZGF0YS5mcmFtZUNvbG9yIDogdGhpcy5fZGVmYXVsdEZyYW1lQ29sb3I7IC8vIFJBTC0xMDExXHJcbiAgICAgICAgdGhpcy5kb29yQ29sb3IgPSB0aGlzLm1ldGFkYXRhLmRvb3JDb2xvciA/IHRoaXMubWV0YWRhdGEuZG9vckNvbG9yIDogdGhpcy5fZGVmYXVsdERvb3JDb2xvcjsgLy8gUkFMLTkwMTBcclxuICAgICAgICB0aGlzLndpbmRvd0NvbG9yID0gdGhpcy5tZXRhZGF0YS53aW5kb3dDb2xvciA/IHRoaXMubWV0YWRhdGEud2luZG93Q29sb3IgOiBuZXcgVEhSRUUuQ29sb3IoMHhkZmYwZjIpO1xyXG4gICAgICAgIHRoaXMuX2lzV2luZG93ID0gdGhpcy5tZXRhZGF0YS5pdGVtVHlwZSA9PT0gSXRlbVR5cGUuSW5XYWxsO1xyXG4gICAgICAgIHRoaXMuX2Rvb3Jwb3N0ID0gdGhpcy5tZXRhZGF0YS5kb29ycG9zdDtcclxuICAgICAgICB0aGlzLmlzR2xhc3MgPSB0aGlzLm1ldGFkYXRhLmlzR2xhc3MgPyB0aGlzLm1ldGFkYXRhLmlzR2xhc3MgOiBmYWxzZTtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIF9jcmVhdGVNYXRlcmlhbHMoc2lkZTogVEhSRUUuU2lkZSk6IHZvaWQge1xyXG4gICAgICAgIHRoaXMuX3NldERlZmF1bHQoKTtcclxuICAgICAgICB0aGlzLmZyYW1lTWF0ZXJpYWwgPSBuZXcgVEhSRUUuTWVzaFBob25nTWF0ZXJpYWwoe3NpZGU6IHNpZGUsIG5hbWU6ICdmcmFtZU1hdGVyaWFsJ30pO1xyXG4gICAgICAgIHRoaXMuZnJhbWVNYXRlcmlhbC5jb2xvciA9IG5ldyBUSFJFRS5Db2xvcih0aGlzLmZyYW1lQ29sb3IpO1xyXG4gICAgICAgIGlmICh0aGlzLl9pc1dpbmRvdykge1xyXG4gICAgICAgICAgICB0aGlzLndpbmRvd01hdGVyaWFsID0gbmV3IFRIUkVFLk1lc2hQaG9uZ01hdGVyaWFsKHtzaWRlOiBzaWRlLCBjb2xvcjogdGhpcy53aW5kb3dDb2xvciwgbmFtZTogJ3dpbmRvd01hdGVyaWFsJ30pO1xyXG4gICAgICAgICAgICB0aGlzLndpbmRvd01hdGVyaWFsLnRyYW5zcGFyZW50ID0gdHJ1ZTtcclxuICAgICAgICAgICAgdGhpcy53aW5kb3dNYXRlcmlhbC5hbHBoYVRlc3QgPSAwO1xyXG4gICAgICAgICAgICB0aGlzLndpbmRvd01hdGVyaWFsLm9wYWNpdHkgPSAwLjI7XHJcbiAgICAgICAgICAgIHRoaXMud2luZG93TWF0ZXJpYWwubWFwID0gdW5kZWZpbmVkO1xyXG4gICAgICAgICAgICB0aGlzLndpbmRvd01hdGVyaWFsLm5lZWRzVXBkYXRlID0gdHJ1ZTtcclxuICAgICAgICAgICAgdGhpcy53aW5kb3dNYXRlcmlhbC5zaWRlID0gVEhSRUUuRnJvbnRTaWRlO1xyXG4gICAgICAgICAgICAoKHRoaXMub2JqZWN0IGFzIE1lc2gpLm1hdGVyaWFsIGFzIGFueSkgPSBbdGhpcy5mcmFtZU1hdGVyaWFsLCB0aGlzLndpbmRvd01hdGVyaWFsXTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICB0aGlzLmRvb3JNYXRlcmlhbEZyb250ID0gbmV3IFRIUkVFLk1lc2hQaG9uZ01hdGVyaWFsKHtzaWRlOiBzaWRlLCBuYW1lOiAnZG9vck1hdGVyaWFsRnJvbnQnfSk7XHJcbiAgICAgICAgICAgIHRoaXMuZG9vck1hdGVyaWFsRnJvbnQuY29sb3IgPSBuZXcgVEhSRUUuQ29sb3IodGhpcy5kb29yQ29sb3IpO1xyXG4gICAgICAgICAgICBpZiAodGhpcy5fZG9vcnBvc3QpIHtcclxuICAgICAgICAgICAgICAgIHRoaXMuZG9vck1hdGVyaWFsRnJvbnQudHJhbnNwYXJlbnQgPSB0cnVlO1xyXG4gICAgICAgICAgICAgICAgdGhpcy5kb29yTWF0ZXJpYWxGcm9udC5vcGFjaXR5ID0gMDtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAoKHRoaXMub2JqZWN0IGFzIE1lc2gpLm1hdGVyaWFsIGFzIGFueSkgPSBbdGhpcy5mcmFtZU1hdGVyaWFsLCB0aGlzLmRvb3JNYXRlcmlhbEZyb250XTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBfZ2V0SGVpZ2h0RnJhbWUoaGVpZ2h0OiBudW1iZXIpOiBudW1iZXIge1xyXG4gICAgICAgIHJldHVybiBoZWlnaHQgLSAodGhpcy5faXNXaW5kb3cgPyAyICogKHRoaXMuX2ZyYW1lV2lkdGggLSAwLjAyKSA6IHRoaXMuX2ZyYW1lV2lkdGggLSAwLjAyKTtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIF9jcmVhdGVGcmFtZVNpZGUod2lkdGg6IG51bWJlciwgaGVpZ2h0OiBudW1iZXIsIGRlcHRoOiBudW1iZXIpOiBUSFJFRS5NZXNoIHtcclxuICAgICAgICBjb25zdCBvdXRlckZyYW1lV2lkdGg6IG51bWJlciA9IHdpZHRoIC0gMC4wMjtcclxuICAgICAgICBjb25zdCBvdXRlckZyYW1lR2VvID0gbmV3IFRIUkVFLkJveEdlb21ldHJ5KG91dGVyRnJhbWVXaWR0aCwgaGVpZ2h0LCBkZXB0aCk7XHJcbiAgICAgICAgY29uc3Qgb3V0ZXJGcmFtZSA9IG5ldyBUSFJFRS5NZXNoKG91dGVyRnJhbWVHZW8sIHRoaXMuZnJhbWVNYXRlcmlhbCk7XHJcbiAgICAgICAgb3V0ZXJGcmFtZS5jYXN0U2hhZG93ID0gdHJ1ZTtcclxuICAgICAgICBvdXRlckZyYW1lLnJlY2VpdmVTaGFkb3cgPSB0cnVlO1xyXG5cclxuICAgICAgICBjb25zdCBpbm5lckZyYW1lR2VvID0gbmV3IFRIUkVFLkJveEdlb21ldHJ5KDAuMDIsIGhlaWdodCwgZGVwdGggLyAyKTtcclxuICAgICAgICBjb25zdCBpbm5lckZyYW1lID0gbmV3IFRIUkVFLk1lc2goaW5uZXJGcmFtZUdlbywgdGhpcy5mcmFtZU1hdGVyaWFsKTtcclxuICAgICAgICBpbm5lckZyYW1lLmNhc3RTaGFkb3cgPSB0cnVlO1xyXG4gICAgICAgIGlubmVyRnJhbWUucmVjZWl2ZVNoYWRvdyA9IHRydWU7XHJcbiAgICAgICAgaW5uZXJGcmFtZS5wb3NpdGlvbi54ID0gKG91dGVyRnJhbWVXaWR0aCAvIDIpICsgMC4wMTtcclxuICAgICAgICBpbm5lckZyYW1lLnBvc2l0aW9uLnogPSAtZGVwdGggLyA0O1xyXG5cclxuICAgICAgICBjb25zdCBmcmFtZVNpZGUgPSBuZXcgVEhSRUUuT2JqZWN0M0QoKTtcclxuICAgICAgICBmcmFtZVNpZGUuYWRkKG91dGVyRnJhbWUsIGlubmVyRnJhbWUpO1xyXG4gICAgICAgIGNvbnN0IGJvdW5kaW5nQm94ID0gbmV3IFRIUkVFLkJveDMoKS5zZXRGcm9tT2JqZWN0KGZyYW1lU2lkZSk7XHJcbiAgICAgICAgY29uc3QgYmJDZW50ZXJQaXZvdCA9IG5ldyBUSFJFRS5WZWN0b3IzKCk7XHJcbiAgICAgICAgYm91bmRpbmdCb3guZ2V0Q2VudGVyKGJiQ2VudGVyUGl2b3QpO1xyXG4gICAgICAgIGNvbnN0IGRlbHRhID0gbmV3IFRIUkVFLlZlY3RvcjMoKS5zdWIoYmJDZW50ZXJQaXZvdCkuc2V0WSgwKTtcclxuICAgICAgICBmcmFtZVNpZGUuY2hpbGRyZW4uZm9yRWFjaCgoY2hpbGQ6IGFueSkgPT4ge1xyXG4gICAgICAgICAgICBjaGlsZC5wb3NpdGlvbi5hZGQoZGVsdGEpO1xyXG4gICAgICAgIH0pO1xyXG4gICAgICAgIGNvbnN0IGZyYW1lU2lkZU1lc2ggPSBuZXcgTWVzaCgpO1xyXG4gICAgICAgIGZyYW1lU2lkZU1lc2guYWRkKG91dGVyRnJhbWUsIGlubmVyRnJhbWUpO1xyXG4gICAgICAgIHJldHVybiBmcmFtZVNpZGVNZXNoO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgX2dldEFkZGl0aW9uYWxUZXh0dXJlKCk6IFByb21pc2U8VEhSRUUuTWVzaD4ge1xyXG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZTogRnVuY3Rpb24sIHJlamVjdDogRnVuY3Rpb24pID0+IHtcclxuICAgICAgICAgICAgLy8gaWYgKHRoaXMuYWRkaXRpb25hbFRleHR1cmUpIHtcclxuICAgICAgICAgICAgLy8gICAgIExvYWRlclV0aWxzLkxvYWRPYmpNb2RlbCh0aGlzLmFkZGl0aW9uYWxUZXh0dXJlLnVybCkudGhlbigob2JqOiBUSFJFRS5NZXNoKSA9PiB7XHJcbiAgICAgICAgICAgIC8vICAgICAgICAgY29uc3QgYWRkaXRpb25hbE9iajogVEhSRUUuTWVzaCA9IDxNZXNoPm9iai5jbG9uZSh0cnVlKTtcclxuICAgICAgICAgICAgLy8gICAgICAgICBhZGRpdGlvbmFsT2JqLmNoaWxkcmVuLm1hcChjID0+IGMucG9zaXRpb24uc2V0KDAsIDAsIDApKTtcclxuICAgICAgICAgICAgLy8gICAgICAgICBpZiAodGhpcy5hZGRpdGlvbmFsVGV4dHVyZS5zY2FsZSkge1xyXG4gICAgICAgICAgICAvLyAgICAgICAgICAgICBhZGRpdGlvbmFsT2JqLnNjYWxlLm11bHRpcGx5U2NhbGFyKHRoaXMuYWRkaXRpb25hbFRleHR1cmUuc2NhbGUpO1xyXG4gICAgICAgICAgICAvLyAgICAgICAgIH1cclxuICAgICAgICAgICAgLy8gICAgICAgICByZXNvbHZlKGFkZGl0aW9uYWxPYmopO1xyXG4gICAgICAgICAgICAvLyAgICAgfSk7XHJcbiAgICAgICAgICAgIC8vIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICByZXNvbHZlKG51bGwpO1xyXG4gICAgICAgICAgICAvLyB9XHJcbiAgICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBfZ2xhc3NNYXRlcmlhbENoZWNrKCkge1xyXG4gICAgICAgIGxldCBtZXNoZXNGb3VuZCA9IDA7XHJcbiAgICAgICAgdGhpcy50cmF2ZXJzZSgoY2hpbGQpID0+IHtcclxuICAgICAgICAgICAgaWYgKGNoaWxkIGluc3RhbmNlb2YgTWVzaCAmJiBjaGlsZC5tYXRlcmlhbCkge1xyXG4gICAgICAgICAgICAgICAgbWVzaGVzRm91bmQrKztcclxuICAgICAgICAgICAgICAgIGNoaWxkLmNhc3RTaGFkb3cgPSB0cnVlO1xyXG4gICAgICAgICAgICAgICAgY29uc3QgbWF0ZXJpYWxzOiBhbnkgPSAhQXJyYXkuaXNBcnJheShjaGlsZC5tYXRlcmlhbCkgPyBbY2hpbGQubWF0ZXJpYWxdIDogY2hpbGQubWF0ZXJpYWw7XHJcbiAgICAgICAgICAgICAgICBtYXRlcmlhbHMuZm9yRWFjaChtYXRlcmlhbCA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKG1hdGVyaWFsLm5hbWUgJiYgKG1hdGVyaWFsLm5hbWUgPT09ICdGaXhlZF9HbGFzcycgfHwgbWF0ZXJpYWwubmFtZSA9PT0gJ0RlZmF1bHRfR2xhc3MnKSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBjaGlsZC5jYXN0U2hhZG93ID0gZmFsc2U7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIG1hdGVyaWFsLnRyYW5zcGFyZW50ID0gdHJ1ZTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgbWF0ZXJpYWwub3BhY2l0eSA9IDAuMjtcclxuICAgICAgICAgICAgICAgICAgICAgICAgbWF0ZXJpYWwuZm9ybWF0ID0gVEhSRUUuUkdCQUZvcm1hdDtcclxuICAgICAgICAgICAgICAgICAgICAgICAgbWF0ZXJpYWwubmVlZHNVcGRhdGUgPSB0cnVlO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfSk7XHJcblxyXG4gICAgICAgIC8vIFJlbW92ZSB0byBpZ25vcmUgb2xkIGRvb3IgbW9kZWxzXHJcbiAgICAgICAgaWYgKG1lc2hlc0ZvdW5kID09PSAxKSB7XHJcbiAgICAgICAgICAgIHRoaXMudHJhdmVyc2UoKGNoaWxkKSA9PiB7XHJcbiAgICAgICAgICAgICAgICBpZiAoY2hpbGQgaW5zdGFuY2VvZiBNZXNoKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgY2hpbGQuY2FzdFNoYWRvdyA9IHRydWU7XHJcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgbWF0ZXJpYWxzOiBhbnkgPSAhQXJyYXkuaXNBcnJheShjaGlsZC5tYXRlcmlhbCkgPyBbY2hpbGQubWF0ZXJpYWxdIDogY2hpbGQubWF0ZXJpYWw7XHJcbiAgICAgICAgICAgICAgICAgICAgbWF0ZXJpYWxzLmZvckVhY2gobSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIG0udmlzaWJsZSA9IG0ubmFtZSAmJiAobS5uYW1lID09PSAnRml4ZWRfR2xhc3MnIHx8IG0ubmFtZSA9PT0gJ0RlZmF1bHRfR2xhc3MnKSA/IG0udmlzaWJsZSA9IGZhbHNlIDogbS52aXNpYmxlID0gdHJ1ZTtcclxuICAgICAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG59XHJcblxyXG5leHBvcnQgY2xhc3MgV2FsbEl0ZW1Hcm91cCBleHRlbmRzIEl0ZW1Hcm91cCB7XHJcblxyXG4gICAgcHVibGljIGN1cnJlbnRXYWxsRWRnZTogSGFsZkVkZ2U7XHJcbiAgICBwdWJsaWMgY3VycmVudFdhbGw6IFdhbGw7XHJcbiAgICBwdWJsaWMgZWxldmF0aW9uQWRqdXN0YWJsZTogYm9vbGVhbiA9IHRydWU7XHJcblxyXG4gICAgcHJpdmF0ZSBfcG9zaXRpb25ZVG9sZXJhbmNlID0gMC4wMDU7XHJcbiAgICBwcml2YXRlIF9vcmlnaW5hbFJvdGF0aW9uOiBFdWxlcjtcclxuICAgIHByaXZhdGUgX29uRnJvbnRTaWRlOiBib29sZWFuO1xyXG4gICAgcHJpdmF0ZSBfd2FsbE9mZnNldFNjYWxhciA9IDA7XHJcbiAgICBwcml2YXRlIF9zaXplWCA9IDA7XHJcbiAgICBwcml2YXRlIF9zaXplWSA9IDA7XHJcbiAgICBwcml2YXRlIF9yZWZWZWMgPSBuZXcgVEhSRUUuVmVjdG9yMigwLCAxLjApO1xyXG5cclxuICAgIGNvbnN0cnVjdG9yKCkge1xyXG4gICAgICAgIHN1cGVyKCk7XHJcbiAgICAgICAgdGhpcy5tZXRhZGF0YSA9IHtcclxuICAgICAgICAgICAgaXRlbVR5cGU6IDIyXHJcbiAgICAgICAgfTtcclxuICAgICAgICB0aGlzLnVzZXJEYXRhLml0ZW1UeXBlID0gdGhpcy5tZXRhZGF0YS5pdGVtVHlwZTtcclxuICAgIH1cclxuXHJcbiAgICBwcm90ZWN0ZWQgcmVkcmF3V2FsbCgpIHtcclxuICAgICAgICBpZiAodGhpcy5jdXJyZW50V2FsbEVkZ2UgJiYgdGhpcy5jdXJyZW50V2FsbEVkZ2Uud2FsbCkge1xyXG4gICAgICAgICAgICB0aGlzLmN1cnJlbnRXYWxsRWRnZS53YWxsLmZpcmVSZWRyYXcoKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgcHVibGljIGlzVmFsaWRQb3NpdGlvbihwb3NpdGlvbjogVmVjdG9yMywgcm90YXRpb24/OiBFdWxlciwgb3B0aW9ucz86IGFueSk6IENvbGxpc2lvbkluZm8ge1xyXG4gICAgICAgIHJldHVybiB7IHZhbGlkOiB0cnVlIH07XHJcbiAgICB9XHJcblxyXG4gICAgcHVibGljIG1vdmVUb1Bvc2l0aW9uKHZlYzM6IFZlY3RvcjMsIGludGVyc2VjdGlvbj86IEludGVyc2VjdGlvbikge1xyXG4gICAgICAgIGlmIChpbnRlcnNlY3Rpb24pIHtcclxuICAgICAgICAgICAgaWYgKCF0aGlzLmN1cnJlbnRXYWxsRWRnZSAmJiAodGhpcy5pdGVtc1swXSBhcyBXYWxsSXRlbSkuY3VycmVudFdhbGxFZGdlKSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLmN1cnJlbnRXYWxsRWRnZSA9ICh0aGlzLml0ZW1zWzBdIGFzIFdhbGxJdGVtKS5jdXJyZW50V2FsbEVkZ2U7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgaWYgKHRoaXMuY3VycmVudFdhbGxFZGdlKSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLl9ib3VuZE1vdmUodmVjMyk7XHJcbiAgICAgICAgICAgICAgICB0aGlzLnBvc2l0aW9uLmNvcHkodmVjMyk7XHJcbiAgICAgICAgICAgICAgICB0aGlzLnJlZHJhd1dhbGwoKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBwdWJsaWMgY3JlYXRlQm91bmRhcnlCb3goKTogdm9pZCB7XHJcbiAgICAgICAgdGhpcy5ib3VuZGFyeUJveC5zZXRGcm9tT2JqZWN0KHRoaXMpO1xyXG4gICAgICAgIGNvbnN0IG1heCA9IHRoaXMuYm91bmRhcnlCb3gubWF4LmNsb25lKCk7XHJcbiAgICAgICAgY29uc3QgbWluID0gdGhpcy5ib3VuZGFyeUJveC5taW4uY2xvbmUoKTtcclxuICAgICAgICB0aGlzLmhhbGZTaXplID0gbWF4LnN1YihtaW4pLmRpdmlkZVNjYWxhcigyKTtcclxuICAgICAgICB0aGlzLnVwZGF0ZVNpemUoKTtcclxuICAgIH1cclxuXHJcbiAgICBwdWJsaWMgY2VudGVyUGl2b3QoKTogdm9pZCB7XHJcbiAgICAgICAgY29uc3QgYm91bmRhcnlCb3hDZW50ZXIgPSB0aGlzLmJvdW5kYXJ5Qm94Q2VudGVyO1xyXG4gICAgICAgIHRoaXMucG9zaXRpb24uY29weShib3VuZGFyeUJveENlbnRlcik7XHJcbiAgICAgICAgdGhpcy5pdGVtcy5mb3JFYWNoKGkgPT4ge1xyXG4gICAgICAgICAgICBjb25zdCBvcmlnaW5hbFBvc2l0aW9uID0gaS5wb3NpdGlvbi5jbG9uZSgpO1xyXG4gICAgICAgICAgICBjb25zdCBuZXdQb3NpdGlvbiA9IG9yaWdpbmFsUG9zaXRpb24uc3ViKGJvdW5kYXJ5Qm94Q2VudGVyKTtcclxuICAgICAgICAgICAgaS5wb3NpdGlvbi5jb3B5KG5ld1Bvc2l0aW9uKTtcclxuICAgICAgICB9KTtcclxuICAgIH1cclxuXHJcbiAgICBwdWJsaWMgdXBkYXRlU2l6ZSgpIHtcclxuICAgICAgICB0aGlzLl93YWxsT2Zmc2V0U2NhbGFyID0gdGhpcy5oYWxmU2l6ZS56O1xyXG4gICAgICAgIHRoaXMuX3NpemVYID0gdGhpcy5oYWxmU2l6ZS54ICogMjtcclxuICAgICAgICB0aGlzLl9zaXplWSA9IHRoaXMuaGFsZlNpemUueSAqIDI7XHJcbiAgICB9XHJcblxyXG4gICAgcHVibGljIG9uV2FsbE1vdmVkKHdhbGw6IFdhbGwpIHtcclxuICAgICAgICBpZiAod2FsbC5mcm9udEVkZ2UpIHtcclxuICAgICAgICAgICAgdGhpcy5wbGFjZU9uRWRnZSh3YWxsLmZyb250RWRnZSk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGlmICh3YWxsLmJhY2tFZGdlKSB7XHJcbiAgICAgICAgICAgIHRoaXMucGxhY2VPbkVkZ2Uod2FsbC5iYWNrRWRnZSk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyBwbGFjZU9uRWRnZShlZGdlOiBIYWxmRWRnZSkge1xyXG4gICAgICAgIHRoaXMuX29yaWdpbmFsUm90YXRpb24gPSB0aGlzLnJvdGF0aW9uLmNsb25lKCk7XHJcblxyXG4gICAgICAgIGlmICghZWRnZSkgeyByZXR1cm47IH1cclxuICAgICAgICB0aGlzLl9vbkZyb250U2lkZSA9IGVkZ2Uud2FsbC5mcm9udEVkZ2UgPT09IGVkZ2U7XHJcbiAgICAgICAgdGhpcy5fY2hhbmdlV2FsbEVkZ2UoZWRnZSk7XHJcblxyXG4gICAgICAgIGNvbnN0IG5ld1BvcyA9IGVkZ2Uud2FsbC5hbW91bnRXYWxsTW92ZWQgPyB0aGlzLnBvc2l0aW9uLmFkZChuZXcgVmVjdG9yMyhlZGdlLndhbGwuYW1vdW50V2FsbE1vdmVkLngsIDAsIDApKSA6IHRoaXMucG9zaXRpb24uY2xvbmUoKTtcclxuICAgICAgICB0aGlzLl9ib3VuZE1vdmUobmV3UG9zKTtcclxuICAgICAgICB0aGlzLnBvc2l0aW9uLmNvcHkobmV3UG9zKTtcclxuICAgICAgICB0aGlzLnJlZHJhd1dhbGwoKTtcclxuICAgICAgICB0aGlzLmFsbG93Um90YXRlID0gZmFsc2U7XHJcbiAgICB9XHJcblxyXG4gICAgcHVibGljIGhhbmRsZUdyb3VwQ3JlYXRpb24oKTogdm9pZCB7XHJcbiAgICAgICAgdGhpcy5pdGVtcy5mb3JFYWNoKChpKSA9PiB7XHJcbiAgICAgICAgICAgIGlmICghdGhpcy5jdXJyZW50V2FsbEVkZ2UpIHtcclxuICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudFdhbGxFZGdlID0gKGkgYXMgV2FsbEl0ZW0pLmN1cnJlbnRXYWxsRWRnZTtcclxuICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudFdhbGwgPSB0aGlzLmN1cnJlbnRXYWxsRWRnZS53YWxsO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIHRoaXMuY3VycmVudFdhbGwucmVtb3ZlT25JdGVtKGkpO1xyXG4gICAgICAgIH0pO1xyXG4gICAgICAgIHRoaXMucGxhY2VPbkVkZ2UodGhpcy5jdXJyZW50V2FsbEVkZ2UpO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgX2NoYW5nZVdhbGxFZGdlKHdhbGxFZGdlOiBIYWxmRWRnZSkge1xyXG4gICAgICAgIC8vIGZpbmQgYW5nbGUgYmV0d2VlbiB3YWxsIG5vcm1hbHNcclxuICAgICAgICBjb25zdCBub3JtYWwyID0gbmV3IFRIUkVFLlZlY3RvcjIoKTtcclxuICAgICAgICBjb25zdCBub3JtYWwzID0gVXRpbHMuR2V0RmFjZU5vcm1hbEZyb21CdWZmZXJHZW9tZXRyeSh3YWxsRWRnZS5wbGFuZS5nZW9tZXRyeSwgMCwgMCk7XHJcbiAgICAgICAgbm9ybWFsMi54ID0gbm9ybWFsMy54O1xyXG4gICAgICAgIG5vcm1hbDIueSA9IG5vcm1hbDMuejtcclxuXHJcbiAgICAgICAgY29uc3Qgd2FsbFJvdGF0aW9uID0gVXRpbHMuYW5nbGUoXHJcbiAgICAgICAgICAgIHRoaXMuX3JlZlZlYy54LCB0aGlzLl9yZWZWZWMueSxcclxuICAgICAgICAgICAgbm9ybWFsMi54LCBub3JtYWwyLnkpO1xyXG5cclxuICAgICAgICAvLyB0cmFuc2ZlciByb3RhdGlvbiBmcm9tIGNoaWxkIHRvIHBhcmVudCBhbmQgcmVzZXQgYm91bmRhcnkgYm94XHJcbiAgICAgICAgaWYgKHRoaXMuaXRlbXNbMF0ucm90YXRpb24ueSAhPT0gMCkge1xyXG4gICAgICAgICAgICB0aGlzLml0ZW1zLmZvckVhY2goKGkpID0+IHtcclxuICAgICAgICAgICAgICAgIGNvbnN0IGl0ZW1Xb3JsZFBvc2l0aW9uOiBWZWN0b3IzID0gaS5nZXRXb3JsZFBvc2l0aW9uKG5ldyBWZWN0b3IzKCkpO1xyXG4gICAgICAgICAgICAgICAgdGhpcy5yZW1vdmUoaSk7XHJcbiAgICAgICAgICAgICAgICB0aGlzLnJvdGF0aW9uLnkgPSB3YWxsUm90YXRpb247XHJcbiAgICAgICAgICAgICAgICBpLnBvc2l0aW9uLmNvcHkoaXRlbVdvcmxkUG9zaXRpb24pO1xyXG4gICAgICAgICAgICAgICAgdGhpcy5hdHRhY2goaSk7XHJcbiAgICAgICAgICAgICAgICB0aGlzLnJvdGF0aW9uLnkgPSAwO1xyXG4gICAgICAgICAgICB9KTtcclxuXHJcbiAgICAgICAgICAgIHRoaXMuY3JlYXRlQm91bmRhcnlCb3goKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHRoaXMucm90YXRpb24ueSA9IHdhbGxSb3RhdGlvbjtcclxuICAgICAgICB0aGlzLnRyYXZlcnNlKGMgPT4gYy5tYXRyaXhXb3JsZE5lZWRzVXBkYXRlID0gdHJ1ZSk7XHJcblxyXG4gICAgICAgIC8vIHVwZGF0ZSBjdXJyZW50V2FsbFxyXG4gICAgICAgIHRoaXMuY3VycmVudFdhbGwgPSB3YWxsRWRnZS53YWxsO1xyXG4gICAgICAgIHRoaXMuY3VycmVudFdhbGxFZGdlID0gd2FsbEVkZ2U7XHJcbiAgICAgICAgd2FsbEVkZ2Uud2FsbC5hZGRPbkl0ZW0odGhpcyBhcyBhbnkpO1xyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyB1cGRhdGVFZGdlVmlzaWJpbGl0eShlZGdlOiBFZGdlKSB7XHJcbiAgICAgICAgaWYgKHRoaXMuY3VycmVudFdhbGwpIHtcclxuICAgICAgICAgICAgbGV0IHNob3VsZFNob3c6IGJvb2xlYW4gPSBmYWxzZTtcclxuICAgICAgICAgICAgaWYgKHRoaXMuY3VycmVudFdhbGwuYmFja0VkZ2UpIHtcclxuICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudFdhbGwuYmFja0VkZ2UuZWRnZXMuZm9yRWFjaCgoZSkgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgIGlmIChlLnZpc2libGUpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgc2hvdWxkU2hvdyA9IHRydWU7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgaWYgKHRoaXMuY3VycmVudFdhbGwuZnJvbnRFZGdlKSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLmN1cnJlbnRXYWxsLmZyb250RWRnZS5lZGdlcy5mb3JFYWNoKGUgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgIGlmIChlLnZpc2libGUpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgc2hvdWxkU2hvdyA9IHRydWU7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgdGhpcy52aXNpYmxlID0gc2hvdWxkU2hvdztcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBfYm91bmRNb3ZlKHZlYzM6IFZlY3RvcjMpIHtcclxuICAgICAgICBjb25zdCBlZGdlID0gdGhpcy5jdXJyZW50V2FsbEVkZ2U7XHJcbiAgICAgICAgdmVjMy5hcHBseU1hdHJpeDQoZWRnZS5pbnRlcmlvclRyYW5zZm9ybSk7XHJcbiAgICAgICAgZWRnZS53YWxsLml0ZW1zQ2hhbmdlZCA9IHRydWU7XHJcblxyXG4gICAgICAgIGlmICh2ZWMzLnggPCB0aGlzLl9zaXplWCAvIDIuMCArIHRoaXMuX3Bvc2l0aW9uWVRvbGVyYW5jZSkge1xyXG4gICAgICAgICAgICB2ZWMzLnggPSB0aGlzLl9zaXplWCAvIDIuMCArIHRoaXMuX3Bvc2l0aW9uWVRvbGVyYW5jZTtcclxuICAgICAgICB9IGVsc2UgaWYgKHZlYzMueCA+IChlZGdlLmludGVyaW9yRGlzdGFuY2UoKSAtIHRoaXMuX3NpemVYIC8gMi4wIC0gdGhpcy5fcG9zaXRpb25ZVG9sZXJhbmNlKSkge1xyXG4gICAgICAgICAgICB2ZWMzLnggPSBlZGdlLmludGVyaW9yRGlzdGFuY2UoKSAtIHRoaXMuX3NpemVYIC8gMi4wIC0gdGhpcy5fcG9zaXRpb25ZVG9sZXJhbmNlO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKHRoaXMuZWxldmF0aW9uRml4ZWQgfHwgIXRoaXMuZWxldmF0aW9uQWRqdXN0YWJsZSkge1xyXG4gICAgICAgICAgICB2ZWMzLnkgPSB0aGlzLnBvc2l0aW9uLnk7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgY29uc3QgbWF4WTogbnVtYmVyID0gdGhpcy5fZ2V0TWF4WShlZGdlKTtcclxuICAgICAgICAgICAgY29uc3QgbWluWTogbnVtYmVyID0gdGhpcy5fZ2V0TWluWSgpO1xyXG4gICAgICAgICAgICBpZiAodmVjMy55IDwgbWluWSkge1xyXG4gICAgICAgICAgICAgICAgdmVjMy55ID0gbWluWTtcclxuICAgICAgICAgICAgfSBlbHNlIGlmICh2ZWMzLnkgPiBtYXhZKSB7XHJcbiAgICAgICAgICAgICAgICB2ZWMzLnkgPSBtYXhZO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIHRoaXMuZWxldmF0aW9uID0gdmVjMy55IC0gdGhpcy5oYWxmU2l6ZS55O1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgdmVjMy56ID0gdGhpcy5fd2FsbE9mZnNldFNjYWxhcjtcclxuICAgICAgICB2ZWMzLmFwcGx5TWF0cml4NChlZGdlLmludkludGVyaW9yVHJhbnNmb3JtKTtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIF9nZXRNYXhZKGVkZ2U6IEhhbGZFZGdlKTogbnVtYmVyIHtcclxuICAgICAgICByZXR1cm4gZWRnZS5oZWlnaHQgLSB0aGlzLmhhbGZTaXplLnkgLSB0aGlzLl9wb3NpdGlvbllUb2xlcmFuY2U7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBfZ2V0TWluWSgpOiBudW1iZXIge1xyXG4gICAgICAgIHJldHVybiB0aGlzLmhhbGZTaXplLnkgKyB0aGlzLl9wb3NpdGlvbllUb2xlcmFuY2U7XHJcbiAgICB9XHJcbn1cclxuIl19
|