mediasfu-angular 1.0.2 → 2.0.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/README.md +686 -578
- package/dist/README.md +677 -578
- package/dist/fesm2022/mediasfu-angular.mjs +5551 -2944
- package/dist/fesm2022/mediasfu-angular.mjs.map +1 -1
- package/dist/lib/@types/types.d.ts +22 -1
- package/dist/lib/components/breakout-components/breakout-rooms-modal.component.d.ts +1 -0
- package/dist/lib/components/mediasfu-components/mediasfu-broadcast.component.d.ts +153 -61
- package/dist/lib/components/mediasfu-components/mediasfu-chat.component.d.ts +154 -66
- package/dist/lib/components/mediasfu-components/mediasfu-conference.component.d.ts +190 -76
- package/dist/lib/components/mediasfu-components/mediasfu-generic.component.d.ts +184 -70
- package/dist/lib/components/mediasfu-components/mediasfu-webinar.component.d.ts +192 -78
- package/dist/lib/components/menu-components/menu-modal/menu-modal.component.d.ts +6 -1
- package/dist/lib/components/menu-components/share-buttons-component/share-buttons-component.component.d.ts +5 -2
- package/dist/lib/components/misc-components/confirm-here-modal/confirm-here-modal.component.d.ts +4 -2
- package/dist/lib/components/misc-components/pre-join-page/pre-join-page.component.d.ts +71 -66
- package/dist/lib/components/misc-components/share-event-modal/share-event-modal.component.d.ts +5 -1
- package/dist/lib/consumers/connect-local-ips.service.d.ts +81 -0
- package/dist/lib/consumers/connect-send-transport-audio.service.d.ts +43 -11
- package/dist/lib/consumers/connect-send-transport-screen.service.d.ts +87 -46
- package/dist/lib/consumers/connect-send-transport-video.service.d.ts +89 -43
- package/dist/lib/consumers/connect-send-transport.service.d.ts +5 -1
- package/dist/lib/consumers/create-send-transport.service.d.ts +130 -40
- package/dist/lib/consumers/disconnect-send-transport-audio.service.d.ts +77 -40
- package/dist/lib/consumers/disconnect-send-transport-screen.service.d.ts +48 -14
- package/dist/lib/consumers/disconnect-send-transport-video.service.d.ts +81 -44
- package/dist/lib/consumers/get-piped-producers-alt.service.d.ts +5 -1
- package/dist/lib/consumers/receive-all-piped-transports.service.d.ts +5 -1
- package/dist/lib/consumers/resume-send-transport-audio.service.d.ts +54 -21
- package/dist/lib/consumers/stream-success-audio-switch.service.d.ts +124 -40
- package/dist/lib/consumers/trigger.service.d.ts +3 -0
- package/dist/lib/methods/exit-methods/confirm-exit.service.d.ts +5 -1
- package/dist/lib/methods/recording-methods/start-recording.service.d.ts +3 -0
- package/dist/lib/methods/recording-methods/stop-recording.service.d.ts +4 -1
- package/dist/lib/methods/recording-methods/update-recording.service.d.ts +3 -0
- package/dist/lib/methods/stream-methods/click-audio.service.d.ts +3 -0
- package/dist/lib/methods/utils/check-limits-and-make-request.service.d.ts +23 -0
- package/dist/lib/methods/utils/create-response-join-room.util.d.ts +33 -0
- package/dist/lib/methods/utils/create-room-on-media-sfu.service.d.ts +25 -0
- package/dist/lib/methods/utils/initial-values.util.d.ts +6 -0
- package/dist/lib/methods/utils/join-room-on-media-sfu.service.d.ts +52 -0
- package/dist/lib/methods/whiteboard-methods/capture-canvas-stream.service.d.ts +37 -20
- package/dist/lib/producers/producer-emits/join-local-room.service.d.ts +125 -0
- package/dist/lib/producers/socket-receive-methods/all-members-rest.service.d.ts +7 -2
- package/dist/lib/producers/socket-receive-methods/all-members.service.d.ts +7 -2
- package/dist/lib/producers/socket-receive-methods/disconnect-user-self.service.d.ts +5 -1
- package/dist/lib/sockets/socket-manager.service.d.ts +90 -0
- package/dist/public-api.d.ts +11 -1
- package/package.json +17 -20
- package/dist/esm2022/lib/@types/types.mjs +0 -2
- package/dist/esm2022/lib/components/background-components/background-modal/background-modal.component.mjs +0 -799
- package/dist/esm2022/lib/components/breakout-components/breakout-rooms-modal.component.mjs +0 -366
- package/dist/esm2022/lib/components/breakout-components/edit-room-modal/edit-room-modal.component.mjs +0 -143
- package/dist/esm2022/lib/components/breakout-components/room-list/room-list.component.mjs +0 -40
- package/dist/esm2022/lib/components/co-host-components/co-host-modal/co-host-modal.component.mjs +0 -245
- package/dist/esm2022/lib/components/display-components/alert-component/alert.component.component.mjs +0 -79
- package/dist/esm2022/lib/components/display-components/audio-card/audio-card.component.mjs +0 -356
- package/dist/esm2022/lib/components/display-components/audio-grid/audio-grid.component.mjs +0 -80
- package/dist/esm2022/lib/components/display-components/card-video-display/card-video-display.component.mjs +0 -129
- package/dist/esm2022/lib/components/display-components/control-buttons-alt-component/control-buttons-alt-component.component.mjs +0 -138
- package/dist/esm2022/lib/components/display-components/control-buttons-component/control-buttons-component.component.mjs +0 -231
- package/dist/esm2022/lib/components/display-components/control-buttons-component-touch/control-buttons-component-touch.component.mjs +0 -282
- package/dist/esm2022/lib/components/display-components/control-widgets/menu-participants-widget.component.mjs +0 -82
- package/dist/esm2022/lib/components/display-components/control-widgets/menu-record-widget.component.mjs +0 -65
- package/dist/esm2022/lib/components/display-components/control-widgets/menu-widget.component.mjs +0 -137
- package/dist/esm2022/lib/components/display-components/control-widgets/message-widget.component.mjs +0 -137
- package/dist/esm2022/lib/components/display-components/control-widgets/record-timer-widget.component.mjs +0 -51
- package/dist/esm2022/lib/components/display-components/control-widgets/screenshare-widget.component.mjs +0 -101
- package/dist/esm2022/lib/components/display-components/flexible-grid/flexible-grid.component.mjs +0 -151
- package/dist/esm2022/lib/components/display-components/flexible-video/flexible-video.component.mjs +0 -250
- package/dist/esm2022/lib/components/display-components/loading-modal/loading-modal.component.mjs +0 -102
- package/dist/esm2022/lib/components/display-components/main-aspect-component/main-aspect-component.component.mjs +0 -140
- package/dist/esm2022/lib/components/display-components/main-container-component/main-container-component.component.mjs +0 -131
- package/dist/esm2022/lib/components/display-components/main-grid-component/main-grid-component.component.mjs +0 -120
- package/dist/esm2022/lib/components/display-components/main-screen-component/main-screen-component.component.mjs +0 -201
- package/dist/esm2022/lib/components/display-components/meeting-progress-timer/meeting-progress-timer.component.mjs +0 -115
- package/dist/esm2022/lib/components/display-components/mini-audio/mini-audio.component.mjs +0 -319
- package/dist/esm2022/lib/components/display-components/mini-card/mini-card.component.mjs +0 -161
- package/dist/esm2022/lib/components/display-components/mini-card-audio/mini-card-audio.component.mjs +0 -230
- package/dist/esm2022/lib/components/display-components/other-grid-component/other-grid-component.component.mjs +0 -126
- package/dist/esm2022/lib/components/display-components/pagination/pagination.component.mjs +0 -334
- package/dist/esm2022/lib/components/display-components/sub-aspect-component/sub-aspect-component.component.mjs +0 -112
- package/dist/esm2022/lib/components/display-components/video-card/video-card.component.mjs +0 -392
- package/dist/esm2022/lib/components/display-settings-components/display-settings-modal.component.mjs +0 -106
- package/dist/esm2022/lib/components/event-settings-components/event-settings-modal/event-settings-modal.component.mjs +0 -199
- package/dist/esm2022/lib/components/exit-components/confirm-exit-modal/confirm-exit-modal.component.mjs +0 -132
- package/dist/esm2022/lib/components/media-settings-components/media-settings-modal/media-settings-modal.component.mjs +0 -220
- package/dist/esm2022/lib/components/mediasfu-components/mediasfu-broadcast.component.mjs +0 -4238
- package/dist/esm2022/lib/components/mediasfu-components/mediasfu-chat.component.mjs +0 -3754
- package/dist/esm2022/lib/components/mediasfu-components/mediasfu-conference.component.mjs +0 -5071
- package/dist/esm2022/lib/components/mediasfu-components/mediasfu-generic.component.mjs +0 -5380
- package/dist/esm2022/lib/components/mediasfu-components/mediasfu-webinar.component.mjs +0 -5068
- package/dist/esm2022/lib/components/menu-components/custom-buttons/custom-buttons.component.mjs +0 -83
- package/dist/esm2022/lib/components/menu-components/meeting-id-component/meeting-id-component.component.mjs +0 -27
- package/dist/esm2022/lib/components/menu-components/meeting-passcode-component/meeting-passcode-component.component.mjs +0 -27
- package/dist/esm2022/lib/components/menu-components/menu-modal/menu-modal.component.mjs +0 -125
- package/dist/esm2022/lib/components/menu-components/share-buttons-component/share-buttons-component.component.mjs +0 -106
- package/dist/esm2022/lib/components/message-components/message-panel/message-panel.component.mjs +0 -228
- package/dist/esm2022/lib/components/message-components/messages-modal/messages-modal.component.mjs +0 -277
- package/dist/esm2022/lib/components/misc-components/confirm-here-modal/confirm-here-modal.component.mjs +0 -130
- package/dist/esm2022/lib/components/misc-components/pre-join-page/pre-join-page.component.mjs +0 -343
- package/dist/esm2022/lib/components/misc-components/share-event-modal/share-event-modal.component.mjs +0 -127
- package/dist/esm2022/lib/components/misc-components/welcome-page/welcome-page.component.mjs +0 -241
- package/dist/esm2022/lib/components/participants-components/participant-list/participant-list.component.mjs +0 -82
- package/dist/esm2022/lib/components/participants-components/participant-list-item/participant-list-item.component.mjs +0 -139
- package/dist/esm2022/lib/components/participants-components/participant-list-others/participant-list-others.component.mjs +0 -40
- package/dist/esm2022/lib/components/participants-components/participant-list-others-item/participant-list-others-item.component.mjs +0 -60
- package/dist/esm2022/lib/components/participants-components/participants-modal/participants-modal.component.mjs +0 -124
- package/dist/esm2022/lib/components/polls-components/poll-modal/poll-modal.component.mjs +0 -201
- package/dist/esm2022/lib/components/recording-components/advanced-panel-component/advanced-panel-components.component.mjs +0 -92
- package/dist/esm2022/lib/components/recording-components/recording-modal/recording-modal.component.mjs +0 -133
- package/dist/esm2022/lib/components/recording-components/standard-panel-component/standard-panel-component.component.mjs +0 -90
- package/dist/esm2022/lib/components/requests-components/render-request-component/render-request-component.component.mjs +0 -81
- package/dist/esm2022/lib/components/requests-components/requests-modal/requests-modal.component.mjs +0 -147
- package/dist/esm2022/lib/components/screenboard-components/screenboard/screenboard.component.mjs +0 -627
- package/dist/esm2022/lib/components/screenboard-components/screenboard-modal/screenboard-modal.component.mjs +0 -391
- package/dist/esm2022/lib/components/waiting-components/waiting-room-modal.component.mjs +0 -201
- package/dist/esm2022/lib/components/whiteboard-components/configure-whiteboard-modal/configure-whiteboard-modal.component.mjs +0 -286
- package/dist/esm2022/lib/components/whiteboard-components/whiteboard/whiteboard.component.mjs +0 -1833
- package/dist/esm2022/lib/consumers/add-videos-grid.service.mjs +0 -345
- package/dist/esm2022/lib/consumers/auto-adjust.service.mjs +0 -109
- package/dist/esm2022/lib/consumers/calculate-rows-and-columns.service.mjs +0 -60
- package/dist/esm2022/lib/consumers/change-vids.service.mjs +0 -551
- package/dist/esm2022/lib/consumers/check-grid.service.mjs +0 -93
- package/dist/esm2022/lib/consumers/check-permission.service.mjs +0 -105
- package/dist/esm2022/lib/consumers/check-screen-share.service.mjs +0 -106
- package/dist/esm2022/lib/consumers/close-and-resize.service.mjs +0 -331
- package/dist/esm2022/lib/consumers/compare-active-names.service.mjs +0 -106
- package/dist/esm2022/lib/consumers/compare-screen-states.service.mjs +0 -98
- package/dist/esm2022/lib/consumers/connect-ips.service.mjs +0 -154
- package/dist/esm2022/lib/consumers/connect-recv-transport.service.mjs +0 -146
- package/dist/esm2022/lib/consumers/connect-send-transport-audio.service.mjs +0 -84
- package/dist/esm2022/lib/consumers/connect-send-transport-screen.service.mjs +0 -102
- package/dist/esm2022/lib/consumers/connect-send-transport-video.service.mjs +0 -99
- package/dist/esm2022/lib/consumers/connect-send-transport.service.mjs +0 -140
- package/dist/esm2022/lib/consumers/consumer-resume.service.mjs +0 -368
- package/dist/esm2022/lib/consumers/control-media.service.mjs +0 -113
- package/dist/esm2022/lib/consumers/create-send-transport.service.mjs +0 -172
- package/dist/esm2022/lib/consumers/disconnect-send-transport-audio.service.mjs +0 -108
- package/dist/esm2022/lib/consumers/disconnect-send-transport-screen.service.mjs +0 -84
- package/dist/esm2022/lib/consumers/disconnect-send-transport-video.service.mjs +0 -101
- package/dist/esm2022/lib/consumers/disp-streams.service.mjs +0 -513
- package/dist/esm2022/lib/consumers/generate-page-content.service.mjs +0 -106
- package/dist/esm2022/lib/consumers/get-estimate.service.mjs +0 -120
- package/dist/esm2022/lib/consumers/get-piped-producers-alt.service.mjs +0 -82
- package/dist/esm2022/lib/consumers/get-producers-piped.service.mjs +0 -79
- package/dist/esm2022/lib/consumers/get-videos.service.mjs +0 -91
- package/dist/esm2022/lib/consumers/mix-streams.service.mjs +0 -95
- package/dist/esm2022/lib/consumers/on-screen-changes.service.mjs +0 -103
- package/dist/esm2022/lib/consumers/prepopulate-user-media.service.mjs +0 -541
- package/dist/esm2022/lib/consumers/process-consumer-transports-audio.service.mjs +0 -101
- package/dist/esm2022/lib/consumers/process-consumer-transports.service.mjs +0 -128
- package/dist/esm2022/lib/consumers/re-port.service.mjs +0 -114
- package/dist/esm2022/lib/consumers/re-update-inter.service.mjs +0 -239
- package/dist/esm2022/lib/consumers/readjust.service.mjs +0 -173
- package/dist/esm2022/lib/consumers/receive-all-piped-transports.service.mjs +0 -87
- package/dist/esm2022/lib/consumers/receive-room-messages.service.mjs +0 -69
- package/dist/esm2022/lib/consumers/reorder-streams.service.mjs +0 -239
- package/dist/esm2022/lib/consumers/request-screen-share.service.mjs +0 -101
- package/dist/esm2022/lib/consumers/resume-pause-audio-streams.service.mjs +0 -150
- package/dist/esm2022/lib/consumers/resume-pause-streams.service.mjs +0 -103
- package/dist/esm2022/lib/consumers/resume-send-transport-audio.service.mjs +0 -91
- package/dist/esm2022/lib/consumers/signal-new-consumer-transport.service.mjs +0 -136
- package/dist/esm2022/lib/consumers/socket-receive-methods/join-consume-room.service.mjs +0 -96
- package/dist/esm2022/lib/consumers/socket-receive-methods/new-pipe-producer.service.mjs +0 -100
- package/dist/esm2022/lib/consumers/socket-receive-methods/producer-closed.service.mjs +0 -78
- package/dist/esm2022/lib/consumers/start-share-screen.service.mjs +0 -120
- package/dist/esm2022/lib/consumers/stop-share-screen.service.mjs +0 -175
- package/dist/esm2022/lib/consumers/stream-success-audio-switch.service.mjs +0 -185
- package/dist/esm2022/lib/consumers/stream-success-audio.service.mjs +0 -210
- package/dist/esm2022/lib/consumers/stream-success-screen.service.mjs +0 -193
- package/dist/esm2022/lib/consumers/stream-success-video.service.mjs +0 -260
- package/dist/esm2022/lib/consumers/switch-user-audio.service.mjs +0 -120
- package/dist/esm2022/lib/consumers/switch-user-video-alt.service.mjs +0 -260
- package/dist/esm2022/lib/consumers/switch-user-video.service.mjs +0 -172
- package/dist/esm2022/lib/consumers/trigger.service.mjs +0 -210
- package/dist/esm2022/lib/consumers/update-mini-cards-grid.service.mjs +0 -135
- package/dist/esm2022/lib/consumers/update-participant-audio-decibels.service.mjs +0 -84
- package/dist/esm2022/lib/methods/background-methods/launch-background.service.mjs +0 -48
- package/dist/esm2022/lib/methods/breakout-room-methods/breakout-room-updated.service.mjs +0 -183
- package/dist/esm2022/lib/methods/breakout-room-methods/launch-breakout-rooms.service.mjs +0 -46
- package/dist/esm2022/lib/methods/co-host-methods/launch-co-host.service.mjs +0 -46
- package/dist/esm2022/lib/methods/co-host-methods/modify-co-host-settings.service.mjs +0 -104
- package/dist/esm2022/lib/methods/display-settings-methods/launch-display-settings.service.mjs +0 -46
- package/dist/esm2022/lib/methods/display-settings-methods/modify-display-settings.service.mjs +0 -194
- package/dist/esm2022/lib/methods/exit-methods/confirm-exit.service.mjs +0 -52
- package/dist/esm2022/lib/methods/exit-methods/launch-confirm-exit.service.mjs +0 -42
- package/dist/esm2022/lib/methods/media-settings-methods/launch-media-settings.service.mjs +0 -85
- package/dist/esm2022/lib/methods/menu-methods/launch-menu-modal.service.mjs +0 -44
- package/dist/esm2022/lib/methods/message-methods/launch-messages.service.mjs +0 -45
- package/dist/esm2022/lib/methods/message-methods/send-message.service.mjs +0 -143
- package/dist/esm2022/lib/methods/participants-methods/launch-participants.service.mjs +0 -47
- package/dist/esm2022/lib/methods/participants-methods/message-participants.service.mjs +0 -98
- package/dist/esm2022/lib/methods/participants-methods/mute-participants.service.mjs +0 -96
- package/dist/esm2022/lib/methods/participants-methods/remove-participants.service.mjs +0 -107
- package/dist/esm2022/lib/methods/polls-methods/handle-create-poll.service.mjs +0 -75
- package/dist/esm2022/lib/methods/polls-methods/handle-end-poll.service.mjs +0 -72
- package/dist/esm2022/lib/methods/polls-methods/handle-vote-poll.service.mjs +0 -83
- package/dist/esm2022/lib/methods/polls-methods/launch-poll.service.mjs +0 -43
- package/dist/esm2022/lib/methods/polls-methods/poll-updated.service.mjs +0 -95
- package/dist/esm2022/lib/methods/recording-methods/check-pause-state.service.mjs +0 -69
- package/dist/esm2022/lib/methods/recording-methods/check-resume-state.service.mjs +0 -56
- package/dist/esm2022/lib/methods/recording-methods/confirm-recording.service.mjs +0 -278
- package/dist/esm2022/lib/methods/recording-methods/launch-recording.service.mjs +0 -125
- package/dist/esm2022/lib/methods/recording-methods/record-pause-timer.service.mjs +0 -67
- package/dist/esm2022/lib/methods/recording-methods/record-resume-timer.service.mjs +0 -130
- package/dist/esm2022/lib/methods/recording-methods/record-start-timer.service.mjs +0 -134
- package/dist/esm2022/lib/methods/recording-methods/record-update-timer.service.mjs +0 -80
- package/dist/esm2022/lib/methods/recording-methods/start-recording.service.mjs +0 -197
- package/dist/esm2022/lib/methods/recording-methods/stop-recording.service.mjs +0 -112
- package/dist/esm2022/lib/methods/recording-methods/update-recording.service.mjs +0 -272
- package/dist/esm2022/lib/methods/requests-methods/launch-requests.service.mjs +0 -51
- package/dist/esm2022/lib/methods/requests-methods/respond-to-requests.service.mjs +0 -84
- package/dist/esm2022/lib/methods/settings-methods/launch-settings.service.mjs +0 -51
- package/dist/esm2022/lib/methods/settings-methods/modify-settings.service.mjs +0 -109
- package/dist/esm2022/lib/methods/stream-methods/click-audio.service.mjs +0 -275
- package/dist/esm2022/lib/methods/stream-methods/click-chat.service.mjs +0 -75
- package/dist/esm2022/lib/methods/stream-methods/click-screen-share.service.mjs +0 -178
- package/dist/esm2022/lib/methods/stream-methods/click-video.service.mjs +0 -271
- package/dist/esm2022/lib/methods/stream-methods/switch-audio.service.mjs +0 -80
- package/dist/esm2022/lib/methods/stream-methods/switch-video-alt.service.mjs +0 -116
- package/dist/esm2022/lib/methods/stream-methods/switch-video.service.mjs +0 -132
- package/dist/esm2022/lib/methods/utils/format-number.service.mjs +0 -57
- package/dist/esm2022/lib/methods/utils/generate-random-messages.service.mjs +0 -120
- package/dist/esm2022/lib/methods/utils/generate-random-participants.service.mjs +0 -126
- package/dist/esm2022/lib/methods/utils/generate-random-polls.service.mjs +0 -78
- package/dist/esm2022/lib/methods/utils/generate-random-request-list.service.mjs +0 -90
- package/dist/esm2022/lib/methods/utils/generate-random-waiting-room-list.service.mjs +0 -59
- package/dist/esm2022/lib/methods/utils/get-modal-position.util.mjs +0 -32
- package/dist/esm2022/lib/methods/utils/get-overlay-position.util.mjs +0 -31
- package/dist/esm2022/lib/methods/utils/initial-values.util.mjs +0 -379
- package/dist/esm2022/lib/methods/utils/meeting-timer/start-meeting-progress-timer.service.mjs +0 -96
- package/dist/esm2022/lib/methods/utils/mini-audio-player/mini-audio-player.component.mjs +0 -315
- package/dist/esm2022/lib/methods/utils/producer/a-params.service.mjs +0 -58
- package/dist/esm2022/lib/methods/utils/producer/h-params.service.mjs +0 -87
- package/dist/esm2022/lib/methods/utils/producer/screen-params.service.mjs +0 -61
- package/dist/esm2022/lib/methods/utils/producer/v-params.service.mjs +0 -87
- package/dist/esm2022/lib/methods/utils/producer/video-capture-constraints.service.mjs +0 -84
- package/dist/esm2022/lib/methods/utils/sleep.util.mjs +0 -17
- package/dist/esm2022/lib/methods/utils/sound-player.service.mjs +0 -63
- package/dist/esm2022/lib/methods/utils/validate-alphanumeric.service.mjs +0 -49
- package/dist/esm2022/lib/methods/waiting-methods/launch-waiting.service.mjs +0 -41
- package/dist/esm2022/lib/methods/waiting-methods/respond-to-waiting.service.mjs +0 -69
- package/dist/esm2022/lib/methods/whiteboard-methods/capture-canvas-stream.service.mjs +0 -98
- package/dist/esm2022/lib/methods/whiteboard-methods/launch-configure-whiteboard.service.mjs +0 -44
- package/dist/esm2022/lib/producer-client/producer-client-emits/create-device-client.service.mjs +0 -74
- package/dist/esm2022/lib/producer-client/producer-client-emits/join-room-client.service.mjs +0 -96
- package/dist/esm2022/lib/producer-client/producer-client-emits/update-room-parameters-client.service.mjs +0 -276
- package/dist/esm2022/lib/producers/producer-emits/join-con-room.service.mjs +0 -152
- package/dist/esm2022/lib/producers/producer-emits/join-room.service.mjs +0 -152
- package/dist/esm2022/lib/producers/socket-receive-methods/all-members-rest.service.mjs +0 -228
- package/dist/esm2022/lib/producers/socket-receive-methods/all-members.service.mjs +0 -218
- package/dist/esm2022/lib/producers/socket-receive-methods/all-waiting-room-members.service.mjs +0 -57
- package/dist/esm2022/lib/producers/socket-receive-methods/ban-participant.service.mjs +0 -76
- package/dist/esm2022/lib/producers/socket-receive-methods/control-media-host.service.mjs +0 -183
- package/dist/esm2022/lib/producers/socket-receive-methods/disconnect-user-self.service.mjs +0 -50
- package/dist/esm2022/lib/producers/socket-receive-methods/disconnect.service.mjs +0 -64
- package/dist/esm2022/lib/producers/socket-receive-methods/get-domains.service.mjs +0 -78
- package/dist/esm2022/lib/producers/socket-receive-methods/host-request-response.service.mjs +0 -150
- package/dist/esm2022/lib/producers/socket-receive-methods/meeting-ended.service.mjs +0 -73
- package/dist/esm2022/lib/producers/socket-receive-methods/meeting-still-there.service.mjs +0 -47
- package/dist/esm2022/lib/producers/socket-receive-methods/meeting-time-remaining.service.mjs +0 -63
- package/dist/esm2022/lib/producers/socket-receive-methods/participant-requested.service.mjs +0 -63
- package/dist/esm2022/lib/producers/socket-receive-methods/person-joined.service.mjs +0 -54
- package/dist/esm2022/lib/producers/socket-receive-methods/producer-media-closed.service.mjs +0 -129
- package/dist/esm2022/lib/producers/socket-receive-methods/producer-media-paused.service.mjs +0 -152
- package/dist/esm2022/lib/producers/socket-receive-methods/producer-media-resumed.service.mjs +0 -99
- package/dist/esm2022/lib/producers/socket-receive-methods/re-initiate-recording.service.mjs +0 -67
- package/dist/esm2022/lib/producers/socket-receive-methods/receive-message.service.mjs +0 -134
- package/dist/esm2022/lib/producers/socket-receive-methods/recording-notice.service.mjs +0 -233
- package/dist/esm2022/lib/producers/socket-receive-methods/room-record-params.service.mjs +0 -121
- package/dist/esm2022/lib/producers/socket-receive-methods/screen-producer-id.service.mjs +0 -86
- package/dist/esm2022/lib/producers/socket-receive-methods/start-records.service.mjs +0 -60
- package/dist/esm2022/lib/producers/socket-receive-methods/stopped-recording.service.mjs +0 -62
- package/dist/esm2022/lib/producers/socket-receive-methods/time-left-recording.service.mjs +0 -57
- package/dist/esm2022/lib/producers/socket-receive-methods/update-consuming-domains.service.mjs +0 -105
- package/dist/esm2022/lib/producers/socket-receive-methods/update-media-settings.service.mjs +0 -66
- package/dist/esm2022/lib/producers/socket-receive-methods/updated-co-host.service.mjs +0 -96
- package/dist/esm2022/lib/producers/socket-receive-methods/user-waiting.service.mjs +0 -52
- package/dist/esm2022/lib/sockets/socket-manager.service.mjs +0 -113
- package/dist/esm2022/mediasfu-angular.mjs +0 -5
- package/dist/esm2022/public-api.mjs +0 -187
package/dist/esm2022/lib/components/whiteboard-components/whiteboard/whiteboard.component.mjs
DELETED
|
@@ -1,1833 +0,0 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
|
2
|
-
/**
|
|
3
|
-
* Whiteboard component for drawing and manipulating shapes, text, and images on a canvas.
|
|
4
|
-
*
|
|
5
|
-
* @component
|
|
6
|
-
* @selector app-whiteboard
|
|
7
|
-
* @templateUrl ./whiteboard.component.html
|
|
8
|
-
* @styleUrls ./whiteboard.component.css
|
|
9
|
-
* @encapsulation ViewEncapsulation.None
|
|
10
|
-
* @imports [CommonModule, FormsModule, FontAwesomeModule]
|
|
11
|
-
*
|
|
12
|
-
* @class Whiteboard
|
|
13
|
-
* @implements OnInit, OnDestroy, OnChanges
|
|
14
|
-
*
|
|
15
|
-
* @property {number} customWidth - Custom width for the whiteboard.
|
|
16
|
-
* @property {number} customHeight - Custom height for the whiteboard.
|
|
17
|
-
* @property {WhiteboardParameters} parameters - Parameters for the whiteboard.
|
|
18
|
-
* @property {boolean} showAspect - Flag to show aspect ratio.
|
|
19
|
-
*
|
|
20
|
-
* @property {ElementRef<HTMLCanvasElement>} canvasRef - Reference to the canvas element.
|
|
21
|
-
* @property {ElementRef<HTMLTextAreaElement>} textInputRef - Reference to the text input element.
|
|
22
|
-
* @property {ElementRef<HTMLButtonElement>} toggleBackgroundRef - Reference to the toggle background button element.
|
|
23
|
-
* @property {ElementRef<HTMLAnchorElement>} downloadLinkRef - Reference to the download link element.
|
|
24
|
-
* @property {ElementRef<HTMLCanvasElement>} tempCanvasRef - Reference to the temporary canvas element.
|
|
25
|
-
*
|
|
26
|
-
* @property {IconDefinition} faTimes - FontAwesome icon for times.
|
|
27
|
-
* @property {IconDefinition} faUndo - FontAwesome icon for undo.
|
|
28
|
-
* @property {IconDefinition} faRedo - FontAwesome icon for redo.
|
|
29
|
-
* @property {IconDefinition} faEraser - FontAwesome icon for eraser.
|
|
30
|
-
* @property {IconDefinition} faShapes - FontAwesome icon for shapes.
|
|
31
|
-
* @property {IconDefinition} faMousePointer - FontAwesome icon for mouse pointer.
|
|
32
|
-
* @property {IconDefinition} faHandPaper - FontAwesome icon for hand paper.
|
|
33
|
-
* @property {IconDefinition} faTextHeight - FontAwesome icon for text height.
|
|
34
|
-
* @property {IconDefinition} faFont - FontAwesome icon for font.
|
|
35
|
-
* @property {IconDefinition} faPencilAlt - FontAwesome icon for pencil alt.
|
|
36
|
-
* @property {IconDefinition} faPaintBrush - FontAwesome icon for paint brush.
|
|
37
|
-
* @property {IconDefinition} faTrash - FontAwesome icon for trash.
|
|
38
|
-
* @property {IconDefinition} faSave - FontAwesome icon for save.
|
|
39
|
-
* @property {IconDefinition} faSearch - FontAwesome icon for search.
|
|
40
|
-
* @property {IconDefinition} faSearchMinus - FontAwesome icon for search minus.
|
|
41
|
-
* @property {IconDefinition} faSearchPlus - FontAwesome icon for search plus.
|
|
42
|
-
* @property {IconDefinition} faChevronLeft - FontAwesome icon for chevron left.
|
|
43
|
-
* @property {IconDefinition} faUpload - FontAwesome icon for upload.
|
|
44
|
-
* @property {IconDefinition} faChevronRight - FontAwesome icon for chevron right.
|
|
45
|
-
*
|
|
46
|
-
* @property {string} mode - Current mode of the whiteboard (e.g., 'pan', 'draw', 'erase').
|
|
47
|
-
* @property {boolean} isDrawing - Flag indicating if drawing is in progress.
|
|
48
|
-
* @property {boolean} isPanning - Flag indicating if panning is in progress.
|
|
49
|
-
* @property {boolean} isDragging - Flag indicating if dragging is in progress.
|
|
50
|
-
* @property {number} startX - Starting X coordinate for drawing.
|
|
51
|
-
* @property {number} startY - Starting Y coordinate for drawing.
|
|
52
|
-
* @property {number} currentX - Current X coordinate for drawing.
|
|
53
|
-
* @property {number} currentY - Current Y coordinate for drawing.
|
|
54
|
-
* @property {any[]} freehandDrawing - Array of points for freehand drawing.
|
|
55
|
-
* @property {any} selectedShape - Currently selected shape.
|
|
56
|
-
* @property {any} selectedHandle - Currently selected handle for resizing shapes.
|
|
57
|
-
* @property {boolean} movingShape - Flag indicating if a shape is being moved.
|
|
58
|
-
* @property {number} panX - X coordinate for panning.
|
|
59
|
-
* @property {number} panY - Y coordinate for panning.
|
|
60
|
-
* @property {number} scale - Current scale of the canvas.
|
|
61
|
-
* @property {number} minScale - Minimum scale of the canvas.
|
|
62
|
-
* @property {number} maxScale - Maximum scale of the canvas.
|
|
63
|
-
* @property {number} eraserThickness - Thickness of the eraser.
|
|
64
|
-
* @property {number} brushThickness - Thickness of the brush.
|
|
65
|
-
* @property {number} lineThickness - Thickness of the line.
|
|
66
|
-
* @property {string} lineType - Type of the line (e.g., 'solid', 'dashed').
|
|
67
|
-
* @property {string} color - Current color for drawing.
|
|
68
|
-
* @property {string} font - Current font for text.
|
|
69
|
-
* @property {number} fontSize - Current font size for text.
|
|
70
|
-
* @property {any} shape - Current shape being drawn.
|
|
71
|
-
* @property {HTMLImageElement} backgroundImage - Background image for the canvas.
|
|
72
|
-
* @property {boolean} toolbarVisible - Flag indicating if the toolbar is visible.
|
|
73
|
-
* @property {string | null} dropdownOpen - Currently open dropdown menu.
|
|
74
|
-
* @property {{ clientX: number, clientY: number, offsetX: number, offsetY: number } | null} currentClickPosition - Current click position on the canvas.
|
|
75
|
-
* @property {number} maxWidth - Maximum width of the canvas.
|
|
76
|
-
* @property {number} maxHeight - Maximum height of the canvas.
|
|
77
|
-
* @property {boolean} dimensionsFixed - Flag indicating if the canvas dimensions are fixed.
|
|
78
|
-
*
|
|
79
|
-
* @method updateLineThickness - Updates the thickness of the line.
|
|
80
|
-
* @param {number} thickness - New thickness for the line.
|
|
81
|
-
*
|
|
82
|
-
* @method updateBrushThickness - Updates the thickness of the brush.
|
|
83
|
-
* @param {number} thickness - New thickness for the brush.
|
|
84
|
-
*
|
|
85
|
-
* @method updateEraserThickness - Updates the thickness of the eraser.
|
|
86
|
-
* @param {number} thickness - New thickness for the eraser.
|
|
87
|
-
*
|
|
88
|
-
* @method updateColor - Updates the color for drawing.
|
|
89
|
-
* @param {string} color - New color for drawing.
|
|
90
|
-
*
|
|
91
|
-
* @method updateFont - Updates the font for text.
|
|
92
|
-
* @param {string} font - New font for text.
|
|
93
|
-
*
|
|
94
|
-
* @method updateFontSize - Updates the font size for text.
|
|
95
|
-
* @param {number} fontSize - New font size for text.
|
|
96
|
-
*
|
|
97
|
-
* @method updateShape - Updates the shape being drawn.
|
|
98
|
-
* @param {string} shape - New shape to be drawn.
|
|
99
|
-
*
|
|
100
|
-
* @constructor
|
|
101
|
-
*
|
|
102
|
-
* @method ngOnInit - Lifecycle hook that is called after data-bound properties are initialized.
|
|
103
|
-
*
|
|
104
|
-
* @method ngOnChanges - Lifecycle hook that is called when any data-bound property of a directive changes.
|
|
105
|
-
* @param {SimpleChanges} changes - Object of changes.
|
|
106
|
-
*
|
|
107
|
-
* @method ngOnDestroy - Lifecycle hook that is called when a directive, pipe, or service is destroyed.
|
|
108
|
-
*
|
|
109
|
-
* @method ngAfterViewInit - Lifecycle hook that is called after a component's view has been fully initialized.
|
|
110
|
-
*
|
|
111
|
-
* @method handleTextInput - Handles the text input event.
|
|
112
|
-
* @param {KeyboardEvent} event - Keyboard event.
|
|
113
|
-
*
|
|
114
|
-
* @method addListeners - Adds event listeners to the canvas and document.
|
|
115
|
-
*
|
|
116
|
-
* @method handleTouchStart - Handles the touch start event.
|
|
117
|
-
* @param {TouchEvent} e - Touch event.
|
|
118
|
-
*
|
|
119
|
-
* @method handleTouchMove - Handles the touch move event.
|
|
120
|
-
* @param {TouchEvent} e - Touch event.
|
|
121
|
-
*
|
|
122
|
-
* @method handleTouchEnd - Handles the touch end event.
|
|
123
|
-
* @param {TouchEvent} e - Touch event.
|
|
124
|
-
*
|
|
125
|
-
* @method handleClickOutside - Handles the click outside event.
|
|
126
|
-
* @param {MouseEvent} event - Mouse event.
|
|
127
|
-
*
|
|
128
|
-
* @method handleCanvasClick - Handles the canvas click event.
|
|
129
|
-
* @param {MouseEvent} e - Mouse event.
|
|
130
|
-
*
|
|
131
|
-
* @method startDrawing - Starts the drawing process.
|
|
132
|
-
* @param {MouseEvent} e - Mouse event.
|
|
133
|
-
*
|
|
134
|
-
* @method draw - Draws on the canvas.
|
|
135
|
-
* @param {MouseEvent} e - Mouse event.
|
|
136
|
-
*
|
|
137
|
-
* @method stopDrawing - Stops the drawing process.
|
|
138
|
-
* @param {MouseEvent} e - Mouse event.
|
|
139
|
-
*
|
|
140
|
-
* @method erase - Erases a part of the canvas.
|
|
141
|
-
* @param {number} x - X coordinate.
|
|
142
|
-
* @param {number} y - Y coordinate.
|
|
143
|
-
*
|
|
144
|
-
* @method isPointNearLine - Checks if a point is near a line.
|
|
145
|
-
* @param {number} px - X coordinate of the point.
|
|
146
|
-
* @param {number} py - Y coordinate of the point.
|
|
147
|
-
* @param {number} x1 - X coordinate of the line start.
|
|
148
|
-
* @param {number} y1 - Y coordinate of the line start.
|
|
149
|
-
* @param {number} x2 - X coordinate of the line end.
|
|
150
|
-
* @param {number} y2 - Y coordinate of the line end.
|
|
151
|
-
* @param {number} threshold - Distance threshold.
|
|
152
|
-
* @returns {boolean} - True if the point is near the line, false otherwise.
|
|
153
|
-
*
|
|
154
|
-
* @method zoomCanvas - Zooms the canvas.
|
|
155
|
-
* @param {number} scaleFactor - Scale factor for zooming.
|
|
156
|
-
* @param {MouseEvent} [event] - Mouse event.
|
|
157
|
-
*
|
|
158
|
-
* @method handleZoom - Handles the zoom event.
|
|
159
|
-
* @param {WheelEvent} e - Wheel event.
|
|
160
|
-
*
|
|
161
|
-
* @method drawEdgeMarkers - Draws edge markers on the canvas.
|
|
162
|
-
*
|
|
163
|
-
* @method drawShapes - Draws all shapes on the canvas.
|
|
164
|
-
*
|
|
165
|
-
* @method drawLine - Draws a line on the canvas.
|
|
166
|
-
* @param {number} x1 - X coordinate of the line start.
|
|
167
|
-
* @param {number} y1 - Y coordinate of the line start.
|
|
168
|
-
* @param {number} x2 - X coordinate of the line end.
|
|
169
|
-
* @param {number} y2 - Y coordinate of the line end.
|
|
170
|
-
* @param {string} color - Color of the line.
|
|
171
|
-
* @param {number} thickness - Thickness of the line.
|
|
172
|
-
* @param {string} lineType - Type of the line (e.g., 'solid', 'dashed').
|
|
173
|
-
*
|
|
174
|
-
* @method drawText - Draws text on the canvas.
|
|
175
|
-
* @param {string} text - Text to be drawn.
|
|
176
|
-
* @param {number} x - X coordinate of the text.
|
|
177
|
-
* @param {number} y - Y coordinate of the text.
|
|
178
|
-
* @param {string} color - Color of the text.
|
|
179
|
-
* @param {string} font - Font of the text.
|
|
180
|
-
*
|
|
181
|
-
* @method drawFreehand - Draws freehand lines on the canvas.
|
|
182
|
-
* @param {{ x: number, y: number }[]} points - Array of points for freehand drawing.
|
|
183
|
-
* @param {string} color - Color of the freehand drawing.
|
|
184
|
-
* @param {number} thickness - Thickness of the freehand drawing.
|
|
185
|
-
*
|
|
186
|
-
* @method drawShape - Draws a shape on the canvas.
|
|
187
|
-
* @param {string} type - Type of the shape.
|
|
188
|
-
* @param {number} x1 - X coordinate of the shape start.
|
|
189
|
-
* @param {number} y1 - Y coordinate of the shape start.
|
|
190
|
-
* @param {number} x2 - X coordinate of the shape end.
|
|
191
|
-
* @param {number} y2 - Y coordinate of the shape end.
|
|
192
|
-
* @param {string} color - Color of the shape.
|
|
193
|
-
* @param {number} thickness - Thickness of the shape.
|
|
194
|
-
* @param {string} lineType - Type of the line (e.g., 'solid', 'dashed').
|
|
195
|
-
* @param {CanvasRenderingContext2D} [ctx] - Canvas rendering context.
|
|
196
|
-
*
|
|
197
|
-
* @method drawPolygon - Draws a polygon on the canvas.
|
|
198
|
-
* @param {CanvasRenderingContext2D} ctx - Canvas rendering context.
|
|
199
|
-
* @param {number} sides - Number of sides of the polygon.
|
|
200
|
-
* @param {number} x1 - X coordinate of the polygon start.
|
|
201
|
-
* @param {number} y1 - Y coordinate of the polygon start.
|
|
202
|
-
* @param {number} x2 - X coordinate of the polygon end.
|
|
203
|
-
* @param {number} y2 - Y coordinate of the polygon end.
|
|
204
|
-
*
|
|
205
|
-
* @example
|
|
206
|
-
* ```html
|
|
207
|
-
* <app-whiteboard
|
|
208
|
-
* [customWidth]="1280"
|
|
209
|
-
* [customHeight]="720"
|
|
210
|
-
* [parameters]="{
|
|
211
|
-
* socket: socket,
|
|
212
|
-
* showAlert: showAlert,
|
|
213
|
-
* islevel: islevel,
|
|
214
|
-
* roomName: roomName,
|
|
215
|
-
* shapes: shapes,
|
|
216
|
-
* useImageBackground: useImageBackground,
|
|
217
|
-
* redoStack: redoStack,
|
|
218
|
-
* undoStack: undoStack,
|
|
219
|
-
* whiteboardStarted: whiteboardStarted,
|
|
220
|
-
* whiteboardEnded: whiteboardEnded,
|
|
221
|
-
* whiteboardUsers: whiteboardUsers,
|
|
222
|
-
* participants: participants,
|
|
223
|
-
* participantsAll: participantsAll,
|
|
224
|
-
* screenId: screenId,
|
|
225
|
-
* recordStarted: recordStarted,
|
|
226
|
-
* recordStopped: recordStopped,
|
|
227
|
-
* recordPaused: recordPaused,
|
|
228
|
-
* recordResumed: recordResumed,
|
|
229
|
-
* recordingMediaOptions: recordingMediaOptions,
|
|
230
|
-
* member: member,
|
|
231
|
-
* shareScreenStarted: shareScreenStarted,
|
|
232
|
-
* canvasWhiteboard: canvasWhiteboard,
|
|
233
|
-
* targetResolution: targetResolution,
|
|
234
|
-
* targetResolutionHost: targetResolutionHost,
|
|
235
|
-
* updateShapes: updateShapes,
|
|
236
|
-
* updateUseImageBackground: updateUseImageBackground,
|
|
237
|
-
* updateRedoStack: updateRedoStack,
|
|
238
|
-
* updateUndoStack: updateUndoStack,
|
|
239
|
-
* updateWhiteboardStarted: updateWhiteboardStarted,
|
|
240
|
-
* updateWhiteboardEnded: updateWhiteboardEnded,
|
|
241
|
-
* updateWhiteboardUsers: updateWhiteboardUsers,
|
|
242
|
-
* updateParticipants: updateParticipants,
|
|
243
|
-
* updateScreenId: updateScreenId,
|
|
244
|
-
* updateShareScreenStarted: updateShareScreenStarted,
|
|
245
|
-
* updateCanvasWhiteboard: updateCanvasWhiteboard,
|
|
246
|
-
* onScreenChanges: onScreenChanges,
|
|
247
|
-
* captureCanvasStream: captureCanvasStream,
|
|
248
|
-
* getUpdatedAllParams: getUpdatedAllParams
|
|
249
|
-
* }"
|
|
250
|
-
* [showAspect]="true"
|
|
251
|
-
* ></app-whiteboard>
|
|
252
|
-
* ```
|
|
253
|
-
*/
|
|
254
|
-
import { Component, Input, ViewChild, ViewEncapsulation, } from '@angular/core';
|
|
255
|
-
import { CommonModule } from '@angular/common';
|
|
256
|
-
import { FormsModule } from '@angular/forms';
|
|
257
|
-
import { FontAwesomeModule } from '@fortawesome/angular-fontawesome';
|
|
258
|
-
import { faTimes, faUndo, faRedo, faEraser, faShapes, faMousePointer, faHandPaper, faTextHeight, faFont, faPencilAlt, faPaintBrush, faTrash, faSave, faSearch, faSearchMinus, faSearchPlus, faChevronLeft, faUpload, faChevronRight, } from '@fortawesome/free-solid-svg-icons';
|
|
259
|
-
import * as i0 from "@angular/core";
|
|
260
|
-
import * as i1 from "@angular/common";
|
|
261
|
-
import * as i2 from "@angular/forms";
|
|
262
|
-
import * as i3 from "@fortawesome/angular-fontawesome";
|
|
263
|
-
export class Whiteboard {
|
|
264
|
-
customWidth;
|
|
265
|
-
customHeight;
|
|
266
|
-
parameters = {};
|
|
267
|
-
showAspect;
|
|
268
|
-
canvasRef;
|
|
269
|
-
textInputRef;
|
|
270
|
-
toggleBackgroundRef;
|
|
271
|
-
downloadLinkRef;
|
|
272
|
-
tempCanvasRef;
|
|
273
|
-
faTimes = faTimes;
|
|
274
|
-
faUndo = faUndo;
|
|
275
|
-
faRedo = faRedo;
|
|
276
|
-
faEraser = faEraser;
|
|
277
|
-
faShapes = faShapes;
|
|
278
|
-
faMousePointer = faMousePointer;
|
|
279
|
-
faHandPaper = faHandPaper;
|
|
280
|
-
faTextHeight = faTextHeight;
|
|
281
|
-
faFont = faFont;
|
|
282
|
-
faPencilAlt = faPencilAlt;
|
|
283
|
-
faPaintBrush = faPaintBrush;
|
|
284
|
-
faTrash = faTrash;
|
|
285
|
-
faSave = faSave;
|
|
286
|
-
faSearch = faSearch;
|
|
287
|
-
faSearchMinus = faSearchMinus;
|
|
288
|
-
faSearchPlus = faSearchPlus;
|
|
289
|
-
faChevronLeft = faChevronLeft;
|
|
290
|
-
faUpload = faUpload;
|
|
291
|
-
faChevronRight = faChevronRight;
|
|
292
|
-
mode = 'pan';
|
|
293
|
-
isDrawing = false;
|
|
294
|
-
isPanning = false;
|
|
295
|
-
isDragging = false;
|
|
296
|
-
startX = 0;
|
|
297
|
-
startY = 0;
|
|
298
|
-
currentX = 0;
|
|
299
|
-
currentY = 0;
|
|
300
|
-
freehandDrawing = [];
|
|
301
|
-
selectedShape = null;
|
|
302
|
-
selectedHandle = null;
|
|
303
|
-
movingShape = false;
|
|
304
|
-
panX = 0;
|
|
305
|
-
panY = 0;
|
|
306
|
-
scale = 1;
|
|
307
|
-
minScale = 0.25;
|
|
308
|
-
maxScale = 1.75;
|
|
309
|
-
eraserThickness = 10;
|
|
310
|
-
brushThickness = 6;
|
|
311
|
-
lineThickness = 6;
|
|
312
|
-
lineType = 'solid';
|
|
313
|
-
color = '#000000';
|
|
314
|
-
font = 'Arial';
|
|
315
|
-
fontSize = 20;
|
|
316
|
-
shape = null;
|
|
317
|
-
backgroundImage = new Image();
|
|
318
|
-
toolbarVisible = true;
|
|
319
|
-
dropdownOpen = null;
|
|
320
|
-
currentClickPosition = null;
|
|
321
|
-
maxWidth = 1280;
|
|
322
|
-
maxHeight = 720;
|
|
323
|
-
dimensionsFixed = false;
|
|
324
|
-
isValidShape = false;
|
|
325
|
-
updateLineThickness = (thickness) => {
|
|
326
|
-
this.lineThickness = thickness;
|
|
327
|
-
};
|
|
328
|
-
updateBrushThickness = (thickness) => {
|
|
329
|
-
this.brushThickness = thickness;
|
|
330
|
-
};
|
|
331
|
-
updateEraserThickness = (thickness) => {
|
|
332
|
-
this.eraserThickness = thickness;
|
|
333
|
-
};
|
|
334
|
-
updateColor = (color) => {
|
|
335
|
-
this.color = color;
|
|
336
|
-
};
|
|
337
|
-
updateFont = (font) => {
|
|
338
|
-
this.font = font;
|
|
339
|
-
};
|
|
340
|
-
updateFontSize = (fontSize) => {
|
|
341
|
-
this.fontSize = fontSize;
|
|
342
|
-
};
|
|
343
|
-
updateShape = (shape) => {
|
|
344
|
-
this.shape = shape;
|
|
345
|
-
};
|
|
346
|
-
ngOnInit() {
|
|
347
|
-
if (this.showAspect) {
|
|
348
|
-
this.addListeners();
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
ngOnChanges(changes) {
|
|
352
|
-
if (changes['parameters'] && changes['parameters'].currentValue) {
|
|
353
|
-
this.parameters = changes['parameters'].currentValue;
|
|
354
|
-
if (this.parameters.socket) {
|
|
355
|
-
this.parameters.socket.on('whiteboardUpdated', async (data) => {
|
|
356
|
-
this.WhiteboardUpdated(data);
|
|
357
|
-
});
|
|
358
|
-
this.parameters.socket.on('whiteboardAction', (data) => {
|
|
359
|
-
this.WhiteboardAction(data);
|
|
360
|
-
});
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
if (changes['showAspect']) {
|
|
364
|
-
if (changes['showAspect'].currentValue) {
|
|
365
|
-
this.addListeners();
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
ngOnDestroy() {
|
|
370
|
-
const canvas = this.canvasRef.nativeElement;
|
|
371
|
-
canvas.removeEventListener('mousedown', this.startDrawing.bind(this));
|
|
372
|
-
canvas.removeEventListener('mousemove', this.draw.bind(this));
|
|
373
|
-
canvas.removeEventListener('mouseup', this.stopDrawing.bind(this));
|
|
374
|
-
canvas.removeEventListener('wheel', this.handleZoom.bind(this));
|
|
375
|
-
canvas.removeEventListener('click', this.handleCanvasClick.bind(this));
|
|
376
|
-
// touch events
|
|
377
|
-
canvas.removeEventListener('touchstart', this.handleTouchStart.bind(this));
|
|
378
|
-
canvas.removeEventListener('touchmove', this.handleTouchMove.bind(this));
|
|
379
|
-
canvas.removeEventListener('touchend', this.handleTouchEnd.bind(this));
|
|
380
|
-
document.removeEventListener('mousedown', this.handleClickOutside.bind(this));
|
|
381
|
-
}
|
|
382
|
-
ngAfterViewInit() {
|
|
383
|
-
// Attach the event listener once after the view has been initialized
|
|
384
|
-
const textInput = this.textInputRef.nativeElement;
|
|
385
|
-
textInput.addEventListener('keypress', (event) => {
|
|
386
|
-
if (event.key === 'Enter') {
|
|
387
|
-
this.handleTextInput(event);
|
|
388
|
-
}
|
|
389
|
-
});
|
|
390
|
-
}
|
|
391
|
-
handleTextInput(event) {
|
|
392
|
-
const textInput = this.textInputRef.nativeElement;
|
|
393
|
-
if (event.key === 'Enter' && this.currentClickPosition) {
|
|
394
|
-
const { offsetX, offsetY } = this.currentClickPosition;
|
|
395
|
-
const text = textInput.value;
|
|
396
|
-
textInput.style.display = 'none';
|
|
397
|
-
textInput.value = '';
|
|
398
|
-
const x = (offsetX - this.panX) / this.scale;
|
|
399
|
-
const y = (offsetY - this.panY) / this.scale;
|
|
400
|
-
this.parameters.shapes.push({
|
|
401
|
-
type: 'text',
|
|
402
|
-
text,
|
|
403
|
-
x,
|
|
404
|
-
y,
|
|
405
|
-
color: this.color,
|
|
406
|
-
font: this.font,
|
|
407
|
-
fontSize: this.fontSize,
|
|
408
|
-
});
|
|
409
|
-
this.drawShapes();
|
|
410
|
-
this.parameters.updateShapes(this.parameters.shapes);
|
|
411
|
-
this.parameters.socket.emit('updateBoardAction', {
|
|
412
|
-
action: 'text',
|
|
413
|
-
payload: {
|
|
414
|
-
type: 'text',
|
|
415
|
-
text,
|
|
416
|
-
x,
|
|
417
|
-
y,
|
|
418
|
-
color: this.color,
|
|
419
|
-
font: this.font,
|
|
420
|
-
fontSize: this.fontSize,
|
|
421
|
-
},
|
|
422
|
-
}, this.handleServerResponse);
|
|
423
|
-
}
|
|
424
|
-
}
|
|
425
|
-
addListeners = () => {
|
|
426
|
-
if (this.parameters) {
|
|
427
|
-
this.parameters = this.parameters.getUpdatedAllParams();
|
|
428
|
-
}
|
|
429
|
-
this.backgroundImage.src = 'https://mediasfu.com/images/svg/graph_paper.jpg';
|
|
430
|
-
this.backgroundImage.crossOrigin = 'anonymous';
|
|
431
|
-
this.backgroundImage.onload = () => {
|
|
432
|
-
this.drawShapes();
|
|
433
|
-
};
|
|
434
|
-
const canvas = this.canvasRef.nativeElement;
|
|
435
|
-
if (this.canvasRef.nativeElement) {
|
|
436
|
-
try {
|
|
437
|
-
if (this.parameters.targetResolution == 'qhd' ||
|
|
438
|
-
this.parameters.targetResolutionHost == 'qhd') {
|
|
439
|
-
this.maxWidth = 1920;
|
|
440
|
-
this.maxHeight = 1080;
|
|
441
|
-
}
|
|
442
|
-
else if (this.parameters.targetResolution == 'fhd' ||
|
|
443
|
-
this.parameters.targetResolutionHost == 'fhd') {
|
|
444
|
-
this.maxWidth = 1920;
|
|
445
|
-
this.maxHeight = 1080;
|
|
446
|
-
}
|
|
447
|
-
canvas.width = this.maxWidth;
|
|
448
|
-
canvas.height = this.maxHeight;
|
|
449
|
-
this.dimensionsFixed = true;
|
|
450
|
-
}
|
|
451
|
-
catch {
|
|
452
|
-
/* handle error */
|
|
453
|
-
}
|
|
454
|
-
this.parameters.updateCanvasWhiteboard(this.canvasRef.nativeElement);
|
|
455
|
-
}
|
|
456
|
-
canvas.addEventListener('mousedown', this.startDrawing.bind(this));
|
|
457
|
-
canvas.addEventListener('mousemove', this.draw.bind(this));
|
|
458
|
-
canvas.addEventListener('mouseup', this.stopDrawing.bind(this));
|
|
459
|
-
canvas.addEventListener('wheel', this.handleZoom.bind(this));
|
|
460
|
-
canvas.addEventListener('click', this.handleCanvasClick.bind(this));
|
|
461
|
-
// touch events
|
|
462
|
-
canvas.addEventListener('touchstart', this.handleTouchStart.bind(this));
|
|
463
|
-
canvas.addEventListener('touchmove', this.handleTouchMove.bind(this));
|
|
464
|
-
canvas.addEventListener('touchend', this.handleTouchEnd.bind(this));
|
|
465
|
-
document.addEventListener('mousedown', this.handleClickOutside.bind(this));
|
|
466
|
-
};
|
|
467
|
-
handleTouchStart(e) {
|
|
468
|
-
e.preventDefault();
|
|
469
|
-
const touch = e.touches[0];
|
|
470
|
-
const mouseEvent = new MouseEvent('mousedown', {
|
|
471
|
-
clientX: touch.clientX,
|
|
472
|
-
clientY: touch.clientY,
|
|
473
|
-
});
|
|
474
|
-
this.canvasRef.nativeElement.dispatchEvent(mouseEvent);
|
|
475
|
-
}
|
|
476
|
-
handleTouchMove(e) {
|
|
477
|
-
e.preventDefault();
|
|
478
|
-
const touch = e.touches[0];
|
|
479
|
-
const mouseEvent = new MouseEvent('mousemove', {
|
|
480
|
-
clientX: touch.clientX,
|
|
481
|
-
clientY: touch.clientY,
|
|
482
|
-
});
|
|
483
|
-
this.canvasRef.nativeElement.dispatchEvent(mouseEvent);
|
|
484
|
-
}
|
|
485
|
-
handleTouchEnd(e) {
|
|
486
|
-
e.preventDefault();
|
|
487
|
-
const mouseEvent = new MouseEvent('mouseup', {});
|
|
488
|
-
this.canvasRef.nativeElement.dispatchEvent(mouseEvent);
|
|
489
|
-
}
|
|
490
|
-
handleClickOutside(event) {
|
|
491
|
-
const target = event.target;
|
|
492
|
-
if (this.dropdownOpen && !target.closest('.btn-group')) {
|
|
493
|
-
this.dropdownOpen = null;
|
|
494
|
-
}
|
|
495
|
-
}
|
|
496
|
-
handleCanvasClick(e) {
|
|
497
|
-
if (this.mode === 'text') {
|
|
498
|
-
const textInput = this.textInputRef.nativeElement;
|
|
499
|
-
textInput.style.left = e.clientX + 'px';
|
|
500
|
-
textInput.style.top = e.clientY + 'px';
|
|
501
|
-
textInput.style.display = 'block';
|
|
502
|
-
textInput.focus();
|
|
503
|
-
this.currentClickPosition = {
|
|
504
|
-
clientX: e.clientX,
|
|
505
|
-
clientY: e.clientY,
|
|
506
|
-
offsetX: e.offsetX,
|
|
507
|
-
offsetY: e.offsetY,
|
|
508
|
-
};
|
|
509
|
-
}
|
|
510
|
-
}
|
|
511
|
-
startDrawing(e) {
|
|
512
|
-
this.isDrawing = true;
|
|
513
|
-
this.startX = (e.offsetX - this.panX) / this.scale;
|
|
514
|
-
this.startY = (e.offsetY - this.panY) / this.scale;
|
|
515
|
-
if (this.mode === 'erase') {
|
|
516
|
-
this.erase(this.startX, this.startY);
|
|
517
|
-
}
|
|
518
|
-
else if (this.mode === 'draw' || this.mode === 'freehand') {
|
|
519
|
-
const ctx = this.canvasRef.nativeElement.getContext('2d');
|
|
520
|
-
ctx.beginPath();
|
|
521
|
-
ctx.moveTo(this.startX, this.startY);
|
|
522
|
-
if (this.mode === 'freehand') {
|
|
523
|
-
this.freehandDrawing = [{ x: this.startX, y: this.startY }];
|
|
524
|
-
}
|
|
525
|
-
}
|
|
526
|
-
else if (this.mode === 'pan') {
|
|
527
|
-
this.isPanning = true;
|
|
528
|
-
this.isDragging = false;
|
|
529
|
-
}
|
|
530
|
-
else if (this.mode === 'select') {
|
|
531
|
-
this.selectedHandle = this.getHandleAtPosition(this.startX, this.startY);
|
|
532
|
-
if (this.selectedHandle) {
|
|
533
|
-
this.isDragging = true;
|
|
534
|
-
this.movingShape = this.selectedHandle.isCenter;
|
|
535
|
-
}
|
|
536
|
-
else {
|
|
537
|
-
this.selectedShape = this.findShape(this.startX, this.startY);
|
|
538
|
-
if (this.selectedShape) {
|
|
539
|
-
this.drawShapes();
|
|
540
|
-
this.drawSelection(this.selectedShape);
|
|
541
|
-
}
|
|
542
|
-
}
|
|
543
|
-
}
|
|
544
|
-
}
|
|
545
|
-
draw = (e) => {
|
|
546
|
-
if (!this.dimensionsFixed) {
|
|
547
|
-
try {
|
|
548
|
-
if (this.parameters.targetResolution == 'qhd' ||
|
|
549
|
-
this.parameters.targetResolutionHost == 'qhd') {
|
|
550
|
-
this.maxWidth = 1920;
|
|
551
|
-
this.maxHeight = 1080;
|
|
552
|
-
}
|
|
553
|
-
else if (this.parameters.targetResolution == 'fhd' ||
|
|
554
|
-
this.parameters.targetResolutionHost == 'fhd') {
|
|
555
|
-
this.maxWidth = 1920;
|
|
556
|
-
this.maxHeight = 1080;
|
|
557
|
-
}
|
|
558
|
-
this.canvasRef.nativeElement.width = this.maxWidth;
|
|
559
|
-
this.canvasRef.nativeElement.height = this.maxHeight;
|
|
560
|
-
this.dimensionsFixed = true;
|
|
561
|
-
this.parameters.updateCanvasWhiteboard(this.canvasRef.nativeElement);
|
|
562
|
-
}
|
|
563
|
-
catch {
|
|
564
|
-
/* handle error */
|
|
565
|
-
}
|
|
566
|
-
}
|
|
567
|
-
if (!this.isDrawing)
|
|
568
|
-
return;
|
|
569
|
-
this.currentX = (e.offsetX - this.panX) / this.scale;
|
|
570
|
-
this.currentY = (e.offsetY - this.panY) / this.scale;
|
|
571
|
-
if (this.mode == 'draw' || this.mode == 'freehand' || this.mode == 'shape') {
|
|
572
|
-
//if more than max width or height or less than 0, return
|
|
573
|
-
if (this.currentX > this.maxWidth ||
|
|
574
|
-
this.currentY > this.maxHeight ||
|
|
575
|
-
this.currentX < 0 ||
|
|
576
|
-
this.currentY < 0) {
|
|
577
|
-
this.isValidShape = false;
|
|
578
|
-
return;
|
|
579
|
-
}
|
|
580
|
-
else {
|
|
581
|
-
this.isValidShape = true;
|
|
582
|
-
}
|
|
583
|
-
}
|
|
584
|
-
const ctx = this.canvasRef.nativeElement.getContext('2d');
|
|
585
|
-
if (this.mode === 'erase') {
|
|
586
|
-
this.erase(this.currentX, this.currentY);
|
|
587
|
-
}
|
|
588
|
-
else if (this.mode === 'draw') {
|
|
589
|
-
ctx.clearRect(0, 0, this.canvasRef.nativeElement.width, this.canvasRef.nativeElement.height);
|
|
590
|
-
this.drawShapes();
|
|
591
|
-
this.drawLine(this.startX, this.startY, this.currentX, this.currentY, this.color, this.lineThickness, this.lineType);
|
|
592
|
-
}
|
|
593
|
-
else if (this.mode === 'freehand') {
|
|
594
|
-
ctx.lineTo(this.currentX, this.currentY);
|
|
595
|
-
ctx.strokeStyle = this.color;
|
|
596
|
-
ctx.lineWidth = this.brushThickness;
|
|
597
|
-
ctx.stroke();
|
|
598
|
-
this.freehandDrawing.push({ x: this.currentX, y: this.currentY });
|
|
599
|
-
}
|
|
600
|
-
else if (this.mode === 'shape') {
|
|
601
|
-
ctx.clearRect(0, 0, this.canvasRef.nativeElement.width, this.canvasRef.nativeElement.height);
|
|
602
|
-
this.drawShapes();
|
|
603
|
-
this.drawShape(this.shape, this.startX, this.startY, this.currentX, this.currentY, this.color, this.lineThickness, this.lineType);
|
|
604
|
-
}
|
|
605
|
-
else if (this.mode === 'pan' && this.isPanning) {
|
|
606
|
-
this.isDragging = true;
|
|
607
|
-
const dx = e.clientX - this.startX;
|
|
608
|
-
const dy = e.clientY - this.startY;
|
|
609
|
-
this.panX += dx;
|
|
610
|
-
this.panY += dy;
|
|
611
|
-
this.startX = e.clientX;
|
|
612
|
-
this.startY = e.clientY;
|
|
613
|
-
ctx.setTransform(this.scale, 0, 0, this.scale, this.panX, this.panY);
|
|
614
|
-
this.drawShapes();
|
|
615
|
-
}
|
|
616
|
-
else if (this.mode === 'select' && this.selectedShape) {
|
|
617
|
-
ctx.clearRect(0, 0, this.canvasRef.nativeElement.width, this.canvasRef.nativeElement.height);
|
|
618
|
-
if (this.movingShape) {
|
|
619
|
-
const dx = this.currentX - this.startX;
|
|
620
|
-
const dy = this.currentY - this.startY;
|
|
621
|
-
this.moveShape(this.selectedShape, dx, dy);
|
|
622
|
-
this.startX = this.currentX;
|
|
623
|
-
this.startY = this.currentY;
|
|
624
|
-
}
|
|
625
|
-
else if (this.isDragging) {
|
|
626
|
-
this.resizeShape(this.selectedShape, this.selectedHandle, this.currentX, this.currentY);
|
|
627
|
-
}
|
|
628
|
-
this.drawShapes();
|
|
629
|
-
this.drawSelection(this.selectedShape);
|
|
630
|
-
}
|
|
631
|
-
};
|
|
632
|
-
stopDrawing() {
|
|
633
|
-
this.isDrawing = false;
|
|
634
|
-
this.isPanning = false;
|
|
635
|
-
this.isDragging = false;
|
|
636
|
-
const ctx = this.canvasRef.nativeElement.getContext('2d');
|
|
637
|
-
ctx.closePath();
|
|
638
|
-
if (this.mode === 'draw' && this.isValidShape) {
|
|
639
|
-
this.parameters.shapes.push({
|
|
640
|
-
type: 'line',
|
|
641
|
-
x1: this.startX,
|
|
642
|
-
y1: this.startY,
|
|
643
|
-
x2: this.currentX,
|
|
644
|
-
y2: this.currentY,
|
|
645
|
-
color: this.color,
|
|
646
|
-
thickness: this.lineThickness,
|
|
647
|
-
lineType: this.lineType,
|
|
648
|
-
});
|
|
649
|
-
this.parameters.updateShapes(this.parameters.shapes);
|
|
650
|
-
this.saveState();
|
|
651
|
-
this.parameters.socket.emit('updateBoardAction', {
|
|
652
|
-
action: 'draw',
|
|
653
|
-
payload: {
|
|
654
|
-
type: 'line',
|
|
655
|
-
x1: this.startX,
|
|
656
|
-
y1: this.startY,
|
|
657
|
-
x2: this.currentX,
|
|
658
|
-
y2: this.currentY,
|
|
659
|
-
color: this.color,
|
|
660
|
-
thickness: this.lineThickness,
|
|
661
|
-
lineType: this.lineType,
|
|
662
|
-
},
|
|
663
|
-
}, this.handleServerResponse);
|
|
664
|
-
}
|
|
665
|
-
else if (this.mode === 'freehand' && this.isValidShape) {
|
|
666
|
-
this.parameters.shapes.push({
|
|
667
|
-
type: 'freehand',
|
|
668
|
-
points: this.freehandDrawing,
|
|
669
|
-
color: this.color,
|
|
670
|
-
thickness: this.brushThickness,
|
|
671
|
-
});
|
|
672
|
-
this.parameters.updateShapes(this.parameters.shapes);
|
|
673
|
-
this.parameters.socket.emit('updateBoardAction', {
|
|
674
|
-
action: 'draw',
|
|
675
|
-
payload: {
|
|
676
|
-
type: 'freehand',
|
|
677
|
-
points: this.freehandDrawing,
|
|
678
|
-
color: this.color,
|
|
679
|
-
thickness: this.brushThickness,
|
|
680
|
-
},
|
|
681
|
-
}, this.handleServerResponse);
|
|
682
|
-
this.freehandDrawing = [];
|
|
683
|
-
this.saveState();
|
|
684
|
-
}
|
|
685
|
-
else if (this.mode === 'shape' && this.isValidShape) {
|
|
686
|
-
this.parameters.shapes.push({
|
|
687
|
-
type: this.shape,
|
|
688
|
-
x1: this.startX,
|
|
689
|
-
y1: this.startY,
|
|
690
|
-
x2: this.currentX,
|
|
691
|
-
y2: this.currentY,
|
|
692
|
-
color: this.color,
|
|
693
|
-
thickness: this.lineThickness,
|
|
694
|
-
lineType: this.lineType,
|
|
695
|
-
});
|
|
696
|
-
this.parameters.updateShapes(this.parameters.shapes);
|
|
697
|
-
this.saveState();
|
|
698
|
-
this.parameters.socket.emit('updateBoardAction', {
|
|
699
|
-
action: 'shape',
|
|
700
|
-
payload: {
|
|
701
|
-
type: this.shape,
|
|
702
|
-
x1: this.startX,
|
|
703
|
-
y1: this.startY,
|
|
704
|
-
x2: this.currentX,
|
|
705
|
-
y2: this.currentY,
|
|
706
|
-
color: this.color,
|
|
707
|
-
thickness: this.lineThickness,
|
|
708
|
-
lineType: this.lineType,
|
|
709
|
-
},
|
|
710
|
-
}, this.handleServerResponse);
|
|
711
|
-
}
|
|
712
|
-
else if (this.mode === 'select') {
|
|
713
|
-
if (this.selectedShape && !this.movingShape && !this.isDragging) {
|
|
714
|
-
const shapeFound = this.findShape(this.currentX, this.currentY);
|
|
715
|
-
if (shapeFound) {
|
|
716
|
-
this.selectedShape = shapeFound;
|
|
717
|
-
this.drawShapes();
|
|
718
|
-
this.drawSelection(shapeFound);
|
|
719
|
-
}
|
|
720
|
-
}
|
|
721
|
-
if (this.selectedShape) {
|
|
722
|
-
this.parameters.socket.emit('updateBoardAction', { action: 'shapes', payload: { shapes: this.parameters.shapes } }, this.handleServerResponse);
|
|
723
|
-
}
|
|
724
|
-
this.saveState();
|
|
725
|
-
}
|
|
726
|
-
}
|
|
727
|
-
erase(x, y) {
|
|
728
|
-
const ctx = this.canvasRef.nativeElement.getContext('2d');
|
|
729
|
-
ctx.save();
|
|
730
|
-
ctx.globalCompositeOperation = 'destination-out';
|
|
731
|
-
ctx.beginPath();
|
|
732
|
-
ctx.arc(x, y, this.eraserThickness / 2, 0, Math.PI * 2, false);
|
|
733
|
-
ctx.fill();
|
|
734
|
-
ctx.restore();
|
|
735
|
-
let changeOccurred = false;
|
|
736
|
-
this.parameters.shapes = this.parameters.shapes
|
|
737
|
-
.map((shape) => {
|
|
738
|
-
if (shape.type === 'freehand') {
|
|
739
|
-
return {
|
|
740
|
-
...shape,
|
|
741
|
-
points: shape.points.filter((point) => {
|
|
742
|
-
const distance = Math.sqrt(Math.pow(point.x - x, 2) + Math.pow(point.y - y, 2));
|
|
743
|
-
if (distance <= this.eraserThickness / 2) {
|
|
744
|
-
changeOccurred = true;
|
|
745
|
-
return false;
|
|
746
|
-
}
|
|
747
|
-
return distance > this.eraserThickness / 2;
|
|
748
|
-
}),
|
|
749
|
-
};
|
|
750
|
-
}
|
|
751
|
-
else if (shape.type === 'line') {
|
|
752
|
-
if (this.isPointNearLine(x, y, shape.x1, shape.y1, shape.x2, shape.y2, this.eraserThickness / 2)) {
|
|
753
|
-
changeOccurred = true;
|
|
754
|
-
return null;
|
|
755
|
-
}
|
|
756
|
-
}
|
|
757
|
-
else if (shape.type === 'text') {
|
|
758
|
-
const textWidth = ctx.measureText(shape.text).width;
|
|
759
|
-
if (x > shape.x &&
|
|
760
|
-
x < shape.x + textWidth &&
|
|
761
|
-
y > shape.y - shape.fontSize &&
|
|
762
|
-
y < shape.y) {
|
|
763
|
-
changeOccurred = true;
|
|
764
|
-
return null;
|
|
765
|
-
}
|
|
766
|
-
}
|
|
767
|
-
else if (shape.type === 'image') {
|
|
768
|
-
if (x > shape.x1 && x < shape.x2 && y > shape.y1 && y < shape.y2) {
|
|
769
|
-
changeOccurred = true;
|
|
770
|
-
return null;
|
|
771
|
-
}
|
|
772
|
-
}
|
|
773
|
-
else {
|
|
774
|
-
if (x > shape.x1 && x < shape.x2 && y > shape.y1 && y < shape.y2) {
|
|
775
|
-
changeOccurred = true;
|
|
776
|
-
return null;
|
|
777
|
-
}
|
|
778
|
-
}
|
|
779
|
-
return shape;
|
|
780
|
-
})
|
|
781
|
-
.filter((shape) => shape && (shape.type !== 'freehand' || shape.points.length > 0));
|
|
782
|
-
this.parameters.updateShapes(this.parameters.shapes);
|
|
783
|
-
this.drawShapes();
|
|
784
|
-
if (changeOccurred) {
|
|
785
|
-
this.parameters.socket.emit('updateBoardAction', { action: 'shapes', payload: { shapes: this.parameters.shapes } }, this.handleServerResponse);
|
|
786
|
-
}
|
|
787
|
-
}
|
|
788
|
-
isPointNearLine(px, py, x1, y1, x2, y2, threshold) {
|
|
789
|
-
const dx = x2 - x1;
|
|
790
|
-
const dy = y2 - y1;
|
|
791
|
-
const length = Math.sqrt(dx * dx + dy * dy);
|
|
792
|
-
const dot = ((px - x1) * dx + (py - y1) * dy) / (length * length);
|
|
793
|
-
const closestX = x1 + dot * dx;
|
|
794
|
-
const closestY = y1 + dot * dy;
|
|
795
|
-
const distance = Math.sqrt(Math.pow(px - closestX, 2) + Math.pow(py - closestY, 2));
|
|
796
|
-
return distance <= threshold;
|
|
797
|
-
}
|
|
798
|
-
zoomCanvas(scaleFactor, event = {
|
|
799
|
-
clientX: this.canvasRef.nativeElement.width / 2,
|
|
800
|
-
clientY: this.canvasRef.nativeElement.height / 2,
|
|
801
|
-
}) {
|
|
802
|
-
const canvas = this.canvasRef.nativeElement;
|
|
803
|
-
const ctx = canvas.getContext('2d');
|
|
804
|
-
if (scaleFactor === 10) {
|
|
805
|
-
this.scale = 1;
|
|
806
|
-
this.panX = 0;
|
|
807
|
-
this.panY = 0;
|
|
808
|
-
}
|
|
809
|
-
else {
|
|
810
|
-
let newScale = this.scale * scaleFactor;
|
|
811
|
-
if (newScale < this.minScale) {
|
|
812
|
-
newScale = this.minScale;
|
|
813
|
-
}
|
|
814
|
-
else if (newScale > this.maxScale) {
|
|
815
|
-
newScale = this.maxScale;
|
|
816
|
-
}
|
|
817
|
-
const rect = canvas.getBoundingClientRect();
|
|
818
|
-
const offsetX = (event.clientX - rect.left) / rect.width;
|
|
819
|
-
const offsetY = (event.clientY - rect.top) / rect.height;
|
|
820
|
-
const dx = offsetX * canvas.width * (1 - scaleFactor);
|
|
821
|
-
const dy = offsetY * canvas.height * (1 - scaleFactor);
|
|
822
|
-
this.scale = newScale;
|
|
823
|
-
this.panX = this.panX * scaleFactor + dx;
|
|
824
|
-
this.panY = this.panY * scaleFactor + dy;
|
|
825
|
-
const maxPanX = (canvas.width * (this.scale - 1)) / this.scale;
|
|
826
|
-
const maxPanY = (canvas.height * (this.scale - 1)) / this.scale;
|
|
827
|
-
this.panX = Math.min(Math.max(this.panX, -maxPanX), 0);
|
|
828
|
-
this.panY = Math.min(Math.max(this.panY, -maxPanY), 0);
|
|
829
|
-
}
|
|
830
|
-
ctx.setTransform(this.scale, 0, 0, this.scale, this.panX, this.panY);
|
|
831
|
-
this.drawShapes();
|
|
832
|
-
}
|
|
833
|
-
handleZoom(e) {
|
|
834
|
-
e.preventDefault();
|
|
835
|
-
if (e.deltaY < 0) {
|
|
836
|
-
this.zoomCanvas(1.2, e);
|
|
837
|
-
}
|
|
838
|
-
else {
|
|
839
|
-
this.zoomCanvas(0.8, e);
|
|
840
|
-
}
|
|
841
|
-
}
|
|
842
|
-
drawEdgeMarkers() {
|
|
843
|
-
const ctx = this.canvasRef.nativeElement.getContext('2d');
|
|
844
|
-
ctx.save();
|
|
845
|
-
ctx.setTransform(1, 0, 0, 1, 0, 0);
|
|
846
|
-
ctx.strokeStyle = 'red';
|
|
847
|
-
ctx.lineWidth = 5;
|
|
848
|
-
ctx.setLineDash([]); // reset line dash
|
|
849
|
-
const markerLength = 20;
|
|
850
|
-
const topLeftX = this.panX;
|
|
851
|
-
const topLeftY = this.panY;
|
|
852
|
-
const bottomRightX = this.panX + 1280 * this.scale;
|
|
853
|
-
const bottomRightY = this.panY + 720 * this.scale;
|
|
854
|
-
ctx.beginPath();
|
|
855
|
-
ctx.moveTo(topLeftX, topLeftY + markerLength);
|
|
856
|
-
ctx.lineTo(topLeftX, topLeftY);
|
|
857
|
-
ctx.lineTo(topLeftX + markerLength, topLeftY);
|
|
858
|
-
ctx.stroke();
|
|
859
|
-
ctx.beginPath();
|
|
860
|
-
ctx.moveTo(bottomRightX - markerLength, topLeftY);
|
|
861
|
-
ctx.lineTo(bottomRightX, topLeftY);
|
|
862
|
-
ctx.lineTo(bottomRightX, topLeftY + markerLength);
|
|
863
|
-
ctx.stroke();
|
|
864
|
-
ctx.beginPath();
|
|
865
|
-
ctx.moveTo(bottomRightX, bottomRightY - markerLength);
|
|
866
|
-
ctx.lineTo(bottomRightX, bottomRightY);
|
|
867
|
-
ctx.lineTo(bottomRightX - markerLength, bottomRightY);
|
|
868
|
-
ctx.stroke();
|
|
869
|
-
ctx.beginPath();
|
|
870
|
-
ctx.moveTo(topLeftX + markerLength, bottomRightY);
|
|
871
|
-
ctx.lineTo(topLeftX, bottomRightY);
|
|
872
|
-
ctx.lineTo(topLeftX, bottomRightY - markerLength);
|
|
873
|
-
ctx.stroke();
|
|
874
|
-
ctx.restore();
|
|
875
|
-
}
|
|
876
|
-
drawShapes() {
|
|
877
|
-
const canvas = this.canvasRef.nativeElement;
|
|
878
|
-
const ctx = canvas.getContext('2d');
|
|
879
|
-
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
880
|
-
ctx.save();
|
|
881
|
-
ctx.setTransform(this.scale, 0, 0, this.scale, this.panX, this.panY);
|
|
882
|
-
if (this.parameters.useImageBackground) {
|
|
883
|
-
ctx.drawImage(this.backgroundImage, -this.panX / this.scale, -this.panY / this.scale, canvas.width / this.scale, canvas.height / this.scale);
|
|
884
|
-
}
|
|
885
|
-
else {
|
|
886
|
-
ctx.fillStyle = '#fff';
|
|
887
|
-
ctx.fillRect(-this.panX / this.scale, -this.panY / this.scale, canvas.width / this.scale, canvas.height / this.scale);
|
|
888
|
-
}
|
|
889
|
-
this.parameters.shapes.forEach((shape) => {
|
|
890
|
-
if (shape.type === 'line') {
|
|
891
|
-
this.drawLine(shape.x1, shape.y1, shape.x2, shape.y2, shape.color, shape.thickness, shape.lineType);
|
|
892
|
-
}
|
|
893
|
-
else if (shape.type === 'freehand') {
|
|
894
|
-
this.drawFreehand(shape.points, shape.color, shape.thickness);
|
|
895
|
-
}
|
|
896
|
-
else if (shape.type === 'text') {
|
|
897
|
-
ctx.font = `${shape.fontSize}px ${shape.font}`;
|
|
898
|
-
ctx.fillStyle = shape.color;
|
|
899
|
-
ctx.fillText(shape.text, shape.x, shape.y);
|
|
900
|
-
}
|
|
901
|
-
else if (shape.type === 'image') {
|
|
902
|
-
ctx.drawImage(shape.img, shape.x1, shape.y1, shape.x2 - shape.x1, shape.y2 - shape.y1);
|
|
903
|
-
}
|
|
904
|
-
else {
|
|
905
|
-
this.drawShape(shape.type, shape.x1, shape.y1, shape.x2, shape.y2, shape.color, shape.thickness, shape.lineType);
|
|
906
|
-
}
|
|
907
|
-
});
|
|
908
|
-
ctx.restore();
|
|
909
|
-
this.drawEdgeMarkers();
|
|
910
|
-
}
|
|
911
|
-
drawLine(x1, y1, x2, y2, color, thickness, lineType) {
|
|
912
|
-
const ctx = this.canvasRef.nativeElement.getContext('2d');
|
|
913
|
-
ctx.beginPath();
|
|
914
|
-
ctx.strokeStyle = color;
|
|
915
|
-
ctx.lineWidth = thickness;
|
|
916
|
-
if (lineType === 'dashed') {
|
|
917
|
-
ctx.setLineDash([10, 10]);
|
|
918
|
-
}
|
|
919
|
-
else if (lineType === 'dotted') {
|
|
920
|
-
ctx.setLineDash([2, 10]);
|
|
921
|
-
}
|
|
922
|
-
else if (lineType === 'dashDot') {
|
|
923
|
-
ctx.setLineDash([10, 5, 2, 5]);
|
|
924
|
-
}
|
|
925
|
-
else {
|
|
926
|
-
ctx.setLineDash([]);
|
|
927
|
-
}
|
|
928
|
-
ctx.moveTo(x1, y1);
|
|
929
|
-
ctx.lineTo(x2, y2);
|
|
930
|
-
ctx.stroke();
|
|
931
|
-
ctx.setLineDash([]);
|
|
932
|
-
}
|
|
933
|
-
drawText(text, x, y, color, font) {
|
|
934
|
-
const ctx = this.canvasRef.nativeElement.getContext('2d');
|
|
935
|
-
ctx.font = `20px ${font}`;
|
|
936
|
-
ctx.fillStyle = color;
|
|
937
|
-
ctx.fillText(text, x, y);
|
|
938
|
-
}
|
|
939
|
-
drawFreehand(points, color, thickness) {
|
|
940
|
-
const ctx = this.canvasRef.nativeElement.getContext('2d');
|
|
941
|
-
if (points.length < 2)
|
|
942
|
-
return;
|
|
943
|
-
ctx.strokeStyle = color;
|
|
944
|
-
ctx.lineWidth = thickness;
|
|
945
|
-
ctx.beginPath();
|
|
946
|
-
ctx.moveTo(points[0].x, points[0].y);
|
|
947
|
-
for (let i = 1; i < points.length; i++) {
|
|
948
|
-
ctx.lineTo(points[i].x, points[i].y);
|
|
949
|
-
}
|
|
950
|
-
ctx.stroke();
|
|
951
|
-
}
|
|
952
|
-
drawShape(type, x1, y1, x2, y2, color, thickness, lineType, ctx = this.canvasRef.nativeElement.getContext('2d')) {
|
|
953
|
-
ctx.beginPath();
|
|
954
|
-
ctx.strokeStyle = color;
|
|
955
|
-
ctx.lineWidth = thickness;
|
|
956
|
-
if (lineType === 'dashed') {
|
|
957
|
-
ctx.setLineDash([10, 10]);
|
|
958
|
-
}
|
|
959
|
-
else if (lineType === 'dotted') {
|
|
960
|
-
ctx.setLineDash([2, 10]);
|
|
961
|
-
}
|
|
962
|
-
else if (lineType === 'dashDot') {
|
|
963
|
-
ctx.setLineDash([10, 5, 2, 5]);
|
|
964
|
-
}
|
|
965
|
-
else {
|
|
966
|
-
ctx.setLineDash([]);
|
|
967
|
-
}
|
|
968
|
-
if (type === 'rectangle') {
|
|
969
|
-
ctx.strokeRect(x1, y1, x2 - x1, y2 - y1);
|
|
970
|
-
}
|
|
971
|
-
else if (type === 'circle') {
|
|
972
|
-
const radius = Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2));
|
|
973
|
-
ctx.arc(x1, y1, radius, 0, 2 * Math.PI);
|
|
974
|
-
ctx.stroke();
|
|
975
|
-
}
|
|
976
|
-
else if (type === 'rhombus') {
|
|
977
|
-
const centerX = (x1 + x2) / 2;
|
|
978
|
-
const centerY = (y1 + y2) / 2;
|
|
979
|
-
ctx.moveTo(centerX, y1);
|
|
980
|
-
ctx.lineTo(x2, centerY);
|
|
981
|
-
ctx.lineTo(centerX, y2);
|
|
982
|
-
ctx.lineTo(x1, centerY);
|
|
983
|
-
ctx.closePath();
|
|
984
|
-
ctx.stroke();
|
|
985
|
-
}
|
|
986
|
-
else if (type === 'pentagon') {
|
|
987
|
-
this.drawPolygon(ctx, 5, x1, y1, x2, y2);
|
|
988
|
-
}
|
|
989
|
-
else if (type === 'hexagon') {
|
|
990
|
-
this.drawPolygon(ctx, 6, x1, y1, x2, y2);
|
|
991
|
-
}
|
|
992
|
-
else if (type === 'triangle') {
|
|
993
|
-
const centerX = (x1 + x2) / 2;
|
|
994
|
-
ctx.moveTo(centerX, y1);
|
|
995
|
-
ctx.lineTo(x2, y2);
|
|
996
|
-
ctx.lineTo(x1, y2);
|
|
997
|
-
ctx.closePath();
|
|
998
|
-
ctx.stroke();
|
|
999
|
-
}
|
|
1000
|
-
else if (type === 'square') {
|
|
1001
|
-
ctx.strokeRect(x1, y1, x2 - x1, x2 - x1);
|
|
1002
|
-
}
|
|
1003
|
-
else if (type === 'octagon') {
|
|
1004
|
-
this.drawPolygon(ctx, 8, x1, y1, x2, y2);
|
|
1005
|
-
}
|
|
1006
|
-
else if (type === 'oval') {
|
|
1007
|
-
const radiusX = Math.abs(x2 - x1) / 2;
|
|
1008
|
-
const radiusY = Math.abs(y2 - y1) / 2;
|
|
1009
|
-
const centerX = (x1 + x2) / 2;
|
|
1010
|
-
const centerY = (y1 + y2) / 2;
|
|
1011
|
-
ctx.ellipse(centerX, centerY, radiusX, radiusY, 0, 0, 2 * Math.PI);
|
|
1012
|
-
ctx.stroke();
|
|
1013
|
-
}
|
|
1014
|
-
else if (type === 'parallelogram') {
|
|
1015
|
-
const centerX = (x1 + x2) / 2;
|
|
1016
|
-
ctx.moveTo(centerX, y1);
|
|
1017
|
-
ctx.lineTo(x2, y2);
|
|
1018
|
-
ctx.lineTo(centerX, y2);
|
|
1019
|
-
ctx.lineTo(x1, y1);
|
|
1020
|
-
ctx.closePath();
|
|
1021
|
-
ctx.stroke();
|
|
1022
|
-
}
|
|
1023
|
-
else if (type === 'image') {
|
|
1024
|
-
ctx.drawImage(this.shape.img, x1, y1, x2 - x1, y2 - y1);
|
|
1025
|
-
}
|
|
1026
|
-
}
|
|
1027
|
-
drawPolygon(ctx, sides, x1, y1, x2, y2) {
|
|
1028
|
-
const centerX = (x1 + x2) / 2;
|
|
1029
|
-
const centerY = (y1 + y2) / 2;
|
|
1030
|
-
const radius = Math.min(Math.abs(x2 - x1), Math.abs(y2 - y1)) / 2;
|
|
1031
|
-
const angle = (2 * Math.PI) / sides;
|
|
1032
|
-
ctx.beginPath();
|
|
1033
|
-
for (let i = 0; i < sides; i++) {
|
|
1034
|
-
const x = centerX + radius * Math.cos(i * angle - Math.PI / 2);
|
|
1035
|
-
const y = centerY + radius * Math.sin(i * angle - Math.PI / 2);
|
|
1036
|
-
if (i === 0) {
|
|
1037
|
-
ctx.moveTo(x, y);
|
|
1038
|
-
}
|
|
1039
|
-
else {
|
|
1040
|
-
ctx.lineTo(x, y);
|
|
1041
|
-
}
|
|
1042
|
-
}
|
|
1043
|
-
ctx.closePath();
|
|
1044
|
-
ctx.stroke();
|
|
1045
|
-
}
|
|
1046
|
-
undo() {
|
|
1047
|
-
if (this.parameters.shapes.length > 0) {
|
|
1048
|
-
this.parameters.redoStack.push(this.parameters.shapes.pop());
|
|
1049
|
-
this.parameters.updateRedoStack(this.parameters.redoStack);
|
|
1050
|
-
this.drawShapes();
|
|
1051
|
-
this.parameters.socket.emit('updateBoardAction', { action: 'undo' }, this.handleServerResponse);
|
|
1052
|
-
}
|
|
1053
|
-
}
|
|
1054
|
-
redo() {
|
|
1055
|
-
if (this.parameters.redoStack.length > 0) {
|
|
1056
|
-
this.parameters.shapes.push(this.parameters.redoStack.pop());
|
|
1057
|
-
this.parameters.updateShapes(this.parameters.shapes);
|
|
1058
|
-
this.drawShapes();
|
|
1059
|
-
this.parameters.socket.emit('updateBoardAction', { action: 'redo' }, this.handleServerResponse);
|
|
1060
|
-
}
|
|
1061
|
-
}
|
|
1062
|
-
saveState() {
|
|
1063
|
-
this.parameters.undoStack.push(JSON.stringify(this.parameters.shapes));
|
|
1064
|
-
this.parameters.updateUndoStack(this.parameters.undoStack);
|
|
1065
|
-
}
|
|
1066
|
-
findShape(x, y) {
|
|
1067
|
-
return this.parameters.shapes.find((shape) => {
|
|
1068
|
-
if (shape.type === 'freehand') {
|
|
1069
|
-
return shape.points.some((point) => {
|
|
1070
|
-
const distance = Math.sqrt(Math.pow(point.x - x, 2) + Math.pow(point.y - y, 2));
|
|
1071
|
-
return distance < shape.thickness;
|
|
1072
|
-
});
|
|
1073
|
-
}
|
|
1074
|
-
else if (shape.type === 'text') {
|
|
1075
|
-
const ctx = this.canvasRef.nativeElement.getContext('2d');
|
|
1076
|
-
ctx.font = `${shape.fontSize}px ${shape.font}`;
|
|
1077
|
-
const textMetrics = ctx.measureText(shape.text);
|
|
1078
|
-
return (x > shape.x &&
|
|
1079
|
-
x < shape.x + textMetrics.width &&
|
|
1080
|
-
y > shape.y - shape.fontSize &&
|
|
1081
|
-
y < shape.y);
|
|
1082
|
-
}
|
|
1083
|
-
else if (shape.type === 'image') {
|
|
1084
|
-
return x > shape.x1 && x < shape.x2 && y > shape.y1 && y < shape.y2;
|
|
1085
|
-
}
|
|
1086
|
-
else {
|
|
1087
|
-
return x > shape.x1 && x < shape.x2 && y > shape.y1 && y < shape.y2;
|
|
1088
|
-
}
|
|
1089
|
-
});
|
|
1090
|
-
}
|
|
1091
|
-
drawSelection(shape) {
|
|
1092
|
-
const ctx = this.canvasRef.nativeElement.getContext('2d');
|
|
1093
|
-
if (!shape)
|
|
1094
|
-
return;
|
|
1095
|
-
const handles = this.getResizeHandles(shape);
|
|
1096
|
-
ctx.strokeStyle = 'red';
|
|
1097
|
-
ctx.lineWidth = 2;
|
|
1098
|
-
ctx.setLineDash([6, 3]);
|
|
1099
|
-
if (shape.type === 'line') {
|
|
1100
|
-
ctx.beginPath();
|
|
1101
|
-
ctx.moveTo(shape.x1, shape.y1);
|
|
1102
|
-
ctx.lineTo(shape.x2, shape.y2);
|
|
1103
|
-
ctx.stroke();
|
|
1104
|
-
}
|
|
1105
|
-
else if (shape.type === 'circle') {
|
|
1106
|
-
const radius = Math.sqrt(Math.pow(shape.x2 - shape.x1, 2) + Math.pow(shape.y2 - shape.y1, 2));
|
|
1107
|
-
ctx.beginPath();
|
|
1108
|
-
ctx.arc(shape.x1, shape.y1, radius, 0, 2 * Math.PI);
|
|
1109
|
-
ctx.stroke();
|
|
1110
|
-
}
|
|
1111
|
-
else {
|
|
1112
|
-
ctx.strokeRect(shape.x1, shape.y1, shape.x2 - shape.x1, shape.y2 - shape.y1);
|
|
1113
|
-
}
|
|
1114
|
-
ctx.setLineDash([]);
|
|
1115
|
-
handles.forEach((handle) => {
|
|
1116
|
-
ctx.fillStyle = handle.isCenter ? 'blue' : 'red';
|
|
1117
|
-
ctx.fillRect(handle.x - 6, handle.y - 6, 12, 12);
|
|
1118
|
-
});
|
|
1119
|
-
}
|
|
1120
|
-
getResizeHandles(shape) {
|
|
1121
|
-
const handles = [];
|
|
1122
|
-
if (shape.type === 'line') {
|
|
1123
|
-
handles.push({ x: shape.x1, y: shape.y1 });
|
|
1124
|
-
handles.push({ x: shape.x2, y: shape.y2 });
|
|
1125
|
-
}
|
|
1126
|
-
else if (shape.type === 'circle') {
|
|
1127
|
-
const radius = Math.sqrt(Math.pow(shape.x2 - shape.x1, 2) + Math.pow(shape.y2 - shape.y1, 2));
|
|
1128
|
-
handles.push({ x: shape.x1 + radius, y: shape.y1 });
|
|
1129
|
-
handles.push({ x: shape.x1 - radius, y: shape.y1 });
|
|
1130
|
-
handles.push({ x: shape.x1, y: shape.y1 + radius });
|
|
1131
|
-
handles.push({ x: shape.x1, y: shape.y1 - radius });
|
|
1132
|
-
handles.push({ x: shape.x1, y: shape.y1, isCenter: true });
|
|
1133
|
-
}
|
|
1134
|
-
else if (shape.type === 'text') {
|
|
1135
|
-
const ctx = this.canvasRef.nativeElement.getContext('2d');
|
|
1136
|
-
const textMetrics = ctx.measureText(shape.text);
|
|
1137
|
-
handles.push({ x: shape.x, y: shape.y - shape.fontSize, isCenter: true });
|
|
1138
|
-
handles.push({ x: shape.x + textMetrics.width, y: shape.y, isCenter: false });
|
|
1139
|
-
}
|
|
1140
|
-
else if (shape.type === 'image') {
|
|
1141
|
-
handles.push({ x: shape.x1, y: shape.y1 });
|
|
1142
|
-
handles.push({ x: shape.x2, y: shape.y1 });
|
|
1143
|
-
handles.push({ x: shape.x2, y: shape.y2 });
|
|
1144
|
-
handles.push({ x: shape.x1, y: shape.y2 });
|
|
1145
|
-
handles.push({ x: (shape.x1 + shape.x2) / 2, y: (shape.y1 + shape.y2) / 2, isCenter: true });
|
|
1146
|
-
}
|
|
1147
|
-
else {
|
|
1148
|
-
handles.push({ x: shape.x1, y: shape.y1 });
|
|
1149
|
-
handles.push({ x: shape.x2, y: shape.y1 });
|
|
1150
|
-
handles.push({ x: shape.x2, y: shape.y2 });
|
|
1151
|
-
handles.push({ x: shape.x1, y: shape.y2 });
|
|
1152
|
-
handles.push({ x: (shape.x1 + shape.x2) / 2, y: (shape.y1 + shape.y2) / 2, isCenter: true });
|
|
1153
|
-
}
|
|
1154
|
-
return handles.map((handle) => ({
|
|
1155
|
-
...handle,
|
|
1156
|
-
isCenter: handle.isCenter || false,
|
|
1157
|
-
}));
|
|
1158
|
-
}
|
|
1159
|
-
getHandleAtPosition(x, y) {
|
|
1160
|
-
if (!this.selectedShape)
|
|
1161
|
-
return null;
|
|
1162
|
-
return this.getResizeHandles(this.selectedShape).find((handle) => {
|
|
1163
|
-
return Math.abs(handle.x - x) < 6 && Math.abs(handle.y - y) < 6;
|
|
1164
|
-
});
|
|
1165
|
-
}
|
|
1166
|
-
resizeShape(shape, handle, x, y) {
|
|
1167
|
-
if (shape.type === 'line') {
|
|
1168
|
-
if (handle.x === shape.x1 && handle.y === shape.y1) {
|
|
1169
|
-
shape.x1 = x;
|
|
1170
|
-
shape.y1 = y;
|
|
1171
|
-
}
|
|
1172
|
-
else {
|
|
1173
|
-
shape.x2 = x;
|
|
1174
|
-
shape.y2 = y;
|
|
1175
|
-
}
|
|
1176
|
-
}
|
|
1177
|
-
else if (shape.type === 'circle') {
|
|
1178
|
-
const dx = x - shape.x1;
|
|
1179
|
-
const dy = y - shape.y1;
|
|
1180
|
-
const radius = Math.sqrt(dx * dx + dy * dy);
|
|
1181
|
-
shape.x2 = shape.x1 + radius;
|
|
1182
|
-
shape.y2 = shape.y1;
|
|
1183
|
-
}
|
|
1184
|
-
else if (shape.type === 'text') {
|
|
1185
|
-
if (handle.isCenter) {
|
|
1186
|
-
shape.x = x;
|
|
1187
|
-
shape.y = y;
|
|
1188
|
-
}
|
|
1189
|
-
else {
|
|
1190
|
-
const textMetrics = this.canvasRef.nativeElement.getContext('2d').measureText(shape.text);
|
|
1191
|
-
shape.x = x - textMetrics.width;
|
|
1192
|
-
shape.y = y;
|
|
1193
|
-
}
|
|
1194
|
-
}
|
|
1195
|
-
else if (shape.type === 'image') {
|
|
1196
|
-
if (handle.isCenter) {
|
|
1197
|
-
const dx = x - (shape.x1 + shape.x2) / 2;
|
|
1198
|
-
const dy = y - (shape.y1 + shape.y2) / 2;
|
|
1199
|
-
this.moveShape(shape, dx, dy);
|
|
1200
|
-
}
|
|
1201
|
-
else {
|
|
1202
|
-
if (handle.x === shape.x1 && handle.y === shape.y1) {
|
|
1203
|
-
shape.x1 = x;
|
|
1204
|
-
shape.y1 = y;
|
|
1205
|
-
}
|
|
1206
|
-
else if (handle.x === shape.x2 && handle.y === shape.y1) {
|
|
1207
|
-
shape.x2 = x;
|
|
1208
|
-
shape.y1 = y;
|
|
1209
|
-
}
|
|
1210
|
-
else if (handle.x === shape.x2 && handle.y === shape.y2) {
|
|
1211
|
-
shape.x2 = x;
|
|
1212
|
-
shape.y2 = y;
|
|
1213
|
-
}
|
|
1214
|
-
else {
|
|
1215
|
-
shape.x1 = x;
|
|
1216
|
-
shape.y2 = y;
|
|
1217
|
-
}
|
|
1218
|
-
}
|
|
1219
|
-
}
|
|
1220
|
-
else {
|
|
1221
|
-
if (handle.isCenter) {
|
|
1222
|
-
const dx = x - (shape.x1 + shape.x2) / 2;
|
|
1223
|
-
const dy = y - (shape.y1 + shape.y2) / 2;
|
|
1224
|
-
this.moveShape(shape, dx, dy);
|
|
1225
|
-
}
|
|
1226
|
-
else {
|
|
1227
|
-
if (handle.x === shape.x1 && handle.y === shape.y1) {
|
|
1228
|
-
shape.x1 = x;
|
|
1229
|
-
shape.y1 = y;
|
|
1230
|
-
}
|
|
1231
|
-
else if (handle.x === shape.x2 && handle.y === shape.y1) {
|
|
1232
|
-
shape.x2 = x;
|
|
1233
|
-
shape.y1 = y;
|
|
1234
|
-
}
|
|
1235
|
-
else if (handle.x === shape.x2 && handle.y === shape.y2) {
|
|
1236
|
-
shape.x2 = x;
|
|
1237
|
-
shape.y2 = y;
|
|
1238
|
-
}
|
|
1239
|
-
else {
|
|
1240
|
-
shape.x1 = x;
|
|
1241
|
-
shape.y2 = y;
|
|
1242
|
-
}
|
|
1243
|
-
}
|
|
1244
|
-
}
|
|
1245
|
-
this.drawShapes();
|
|
1246
|
-
}
|
|
1247
|
-
moveShape(shape, dx, dy) {
|
|
1248
|
-
if (shape.type === 'line' || shape.type === 'circle') {
|
|
1249
|
-
shape.x1 += dx;
|
|
1250
|
-
shape.y1 += dy;
|
|
1251
|
-
shape.x2 += dx;
|
|
1252
|
-
shape.y2 += dy;
|
|
1253
|
-
}
|
|
1254
|
-
else if (shape.type === 'freehand') {
|
|
1255
|
-
shape.points.forEach((point) => {
|
|
1256
|
-
point.x += dx;
|
|
1257
|
-
point.y += dy;
|
|
1258
|
-
});
|
|
1259
|
-
}
|
|
1260
|
-
else if (shape.type === 'text') {
|
|
1261
|
-
shape.x += dx;
|
|
1262
|
-
shape.y += dy;
|
|
1263
|
-
}
|
|
1264
|
-
else if (shape.type === 'image') {
|
|
1265
|
-
shape.x1 += dx;
|
|
1266
|
-
shape.y1 += dy;
|
|
1267
|
-
shape.x2 += dx;
|
|
1268
|
-
shape.y2 += dy;
|
|
1269
|
-
}
|
|
1270
|
-
else {
|
|
1271
|
-
shape.x1 += dx;
|
|
1272
|
-
shape.y1 += dy;
|
|
1273
|
-
shape.x2 += dx;
|
|
1274
|
-
shape.y2 += dy;
|
|
1275
|
-
}
|
|
1276
|
-
}
|
|
1277
|
-
downloadCanvas(tempCanvas) {
|
|
1278
|
-
const link = this.downloadLinkRef.nativeElement;
|
|
1279
|
-
link.href = tempCanvas.toDataURL();
|
|
1280
|
-
link.download = 'whiteboard.png';
|
|
1281
|
-
link.click();
|
|
1282
|
-
}
|
|
1283
|
-
saveCanvas() {
|
|
1284
|
-
const tempCanvas = this.tempCanvasRef.nativeElement;
|
|
1285
|
-
const tempCtx = tempCanvas.getContext('2d');
|
|
1286
|
-
tempCanvas.width = this.canvasRef.nativeElement.width;
|
|
1287
|
-
tempCanvas.height = this.canvasRef.nativeElement.height;
|
|
1288
|
-
const notShapes = ['freehand', 'text', 'image', 'line'];
|
|
1289
|
-
if (this.parameters.useImageBackground) {
|
|
1290
|
-
const backgroundImage = new Image();
|
|
1291
|
-
backgroundImage.crossOrigin = 'anonymous';
|
|
1292
|
-
backgroundImage.onload = () => {
|
|
1293
|
-
tempCtx.drawImage(backgroundImage, 0, 0, tempCanvas.width, tempCanvas.height);
|
|
1294
|
-
this.parameters.shapes.forEach((shape) => {
|
|
1295
|
-
!notShapes.includes(shape.type)
|
|
1296
|
-
? this.drawShape(shape.type, shape.x1, shape.y1, shape.x2, shape.y2, shape.color, shape.thickness, shape.lineType, tempCtx)
|
|
1297
|
-
: this.drawShapeOnCanvas(shape, tempCtx);
|
|
1298
|
-
});
|
|
1299
|
-
this.downloadCanvas(tempCanvas);
|
|
1300
|
-
};
|
|
1301
|
-
backgroundImage.src = 'https://mediasfu.com/images/svg/graph_paper.jpg';
|
|
1302
|
-
}
|
|
1303
|
-
else {
|
|
1304
|
-
tempCtx.fillStyle = 'white';
|
|
1305
|
-
tempCtx.fillRect(0, 0, tempCanvas.width, tempCanvas.height);
|
|
1306
|
-
this.parameters.shapes.forEach((shape) => {
|
|
1307
|
-
!notShapes.includes(shape.type)
|
|
1308
|
-
? this.drawShape(shape.type, shape.x1, shape.y1, shape.x2, shape.y2, shape.color, shape.thickness, shape.lineType, tempCtx)
|
|
1309
|
-
: this.drawShapeOnCanvas(shape, tempCtx);
|
|
1310
|
-
});
|
|
1311
|
-
this.downloadCanvas(tempCanvas);
|
|
1312
|
-
}
|
|
1313
|
-
}
|
|
1314
|
-
drawShapeOnCanvas(shape, ctx = this.canvasRef.nativeElement.getContext('2d')) {
|
|
1315
|
-
ctx.beginPath();
|
|
1316
|
-
ctx.strokeStyle = shape.color;
|
|
1317
|
-
ctx.lineWidth = shape.thickness || 2;
|
|
1318
|
-
ctx.fillStyle = shape.color;
|
|
1319
|
-
ctx.font = `${shape.fontSize}px ${shape.fontFamily}`;
|
|
1320
|
-
const lineType = shape.lineType ? shape.lineType : 'solid';
|
|
1321
|
-
if (lineType === 'dashed') {
|
|
1322
|
-
ctx.setLineDash([10, 10]);
|
|
1323
|
-
}
|
|
1324
|
-
else if (lineType === 'dotted') {
|
|
1325
|
-
ctx.setLineDash([2, 10]);
|
|
1326
|
-
}
|
|
1327
|
-
else if (lineType === 'dashDot') {
|
|
1328
|
-
ctx.setLineDash([10, 5, 2, 5]);
|
|
1329
|
-
}
|
|
1330
|
-
else {
|
|
1331
|
-
ctx.setLineDash([]);
|
|
1332
|
-
}
|
|
1333
|
-
switch (shape.type) {
|
|
1334
|
-
case 'line':
|
|
1335
|
-
ctx.moveTo(shape.x1, shape.y1);
|
|
1336
|
-
ctx.lineTo(shape.x2, shape.y2);
|
|
1337
|
-
break;
|
|
1338
|
-
case 'freehand':
|
|
1339
|
-
try {
|
|
1340
|
-
ctx.moveTo(shape.points[0].x, shape.points[0].y);
|
|
1341
|
-
shape.points.forEach((point) => ctx.lineTo(point.x, point.y));
|
|
1342
|
-
}
|
|
1343
|
-
catch {
|
|
1344
|
-
//console.log('Error drawing freehand shape');
|
|
1345
|
-
}
|
|
1346
|
-
break;
|
|
1347
|
-
case 'text':
|
|
1348
|
-
ctx.fillText(shape.text, shape.x, shape.y);
|
|
1349
|
-
break;
|
|
1350
|
-
case 'image':
|
|
1351
|
-
ctx.drawImage(shape.img, shape.x1, shape.y1, shape.x2 - shape.x1, shape.y2 - shape.y1);
|
|
1352
|
-
break;
|
|
1353
|
-
default:
|
|
1354
|
-
break;
|
|
1355
|
-
}
|
|
1356
|
-
ctx.stroke();
|
|
1357
|
-
}
|
|
1358
|
-
deleteShape(doEmits = true) {
|
|
1359
|
-
if (!this.checkBoardAccess())
|
|
1360
|
-
return;
|
|
1361
|
-
if (!this.selectedShape)
|
|
1362
|
-
return;
|
|
1363
|
-
if (this.selectedShape) {
|
|
1364
|
-
this.parameters.shapes = this.parameters.shapes.filter((shape) => shape !== this.selectedShape);
|
|
1365
|
-
this.parameters.updateShapes(this.parameters.shapes);
|
|
1366
|
-
this.selectedShape = null;
|
|
1367
|
-
if (doEmits) {
|
|
1368
|
-
this.parameters.socket.emit('updateBoardAction', { action: 'shapes', payload: { shapes: this.parameters.shapes } }, this.handleServerResponse);
|
|
1369
|
-
}
|
|
1370
|
-
this.drawShapes();
|
|
1371
|
-
}
|
|
1372
|
-
}
|
|
1373
|
-
toggleBackground = (doEmits = true) => {
|
|
1374
|
-
if (doEmits && !this.checkBoardAccess())
|
|
1375
|
-
return;
|
|
1376
|
-
this.parameters.useImageBackground = !this.parameters.useImageBackground;
|
|
1377
|
-
this.parameters.updateUseImageBackground(this.parameters.useImageBackground);
|
|
1378
|
-
const toggleButton = this.toggleBackgroundRef.nativeElement;
|
|
1379
|
-
if (this.parameters.useImageBackground) {
|
|
1380
|
-
this.canvasRef.nativeElement.style.backgroundImage = `url('https://mediasfu.com/images/svg/graph_paper.jpg')`;
|
|
1381
|
-
toggleButton.classList.remove('active');
|
|
1382
|
-
}
|
|
1383
|
-
else {
|
|
1384
|
-
this.canvasRef.nativeElement.style.backgroundImage = 'none';
|
|
1385
|
-
this.canvasRef.nativeElement.style.backgroundColor = 'white';
|
|
1386
|
-
toggleButton.classList.add('active');
|
|
1387
|
-
}
|
|
1388
|
-
this.drawShapes();
|
|
1389
|
-
if (doEmits) {
|
|
1390
|
-
this.parameters.socket.emit('updateBoardAction', { action: 'toggleBackground', payload: this.parameters.useImageBackground }, this.handleServerResponse);
|
|
1391
|
-
}
|
|
1392
|
-
};
|
|
1393
|
-
clearCanvas = (doEmits = true) => {
|
|
1394
|
-
if (this.parameters.islevel != '2' && doEmits) {
|
|
1395
|
-
this.parameters.showAlert?.({
|
|
1396
|
-
message: 'You do not have permission to clear the board',
|
|
1397
|
-
type: 'danger',
|
|
1398
|
-
});
|
|
1399
|
-
return;
|
|
1400
|
-
}
|
|
1401
|
-
if (this.parameters.shapes.length === 0)
|
|
1402
|
-
return;
|
|
1403
|
-
this.parameters.shapes = [];
|
|
1404
|
-
this.parameters.updateShapes([]);
|
|
1405
|
-
this.drawShapes();
|
|
1406
|
-
if (doEmits) {
|
|
1407
|
-
this.parameters.socket.emit('updateBoardAction', { action: 'clear' }, this.handleServerResponse);
|
|
1408
|
-
}
|
|
1409
|
-
};
|
|
1410
|
-
uploadImage = (event, doEmits = true) => {
|
|
1411
|
-
try {
|
|
1412
|
-
if (!this.checkBoardAccess())
|
|
1413
|
-
return;
|
|
1414
|
-
const file = event.target.files[0];
|
|
1415
|
-
if (file.size > 1024 * 1024) {
|
|
1416
|
-
this.parameters.showAlert?.({ message: 'File size must be less than 1MB', type: 'danger' });
|
|
1417
|
-
return;
|
|
1418
|
-
}
|
|
1419
|
-
const reader = new FileReader();
|
|
1420
|
-
reader.onload = (event) => {
|
|
1421
|
-
const img = new Image();
|
|
1422
|
-
img.crossOrigin = 'anonymous';
|
|
1423
|
-
img.onload = () => {
|
|
1424
|
-
if (img.height > 600 && img.height > img.width && !file.type.includes('jpeg')) {
|
|
1425
|
-
this.parameters.showAlert?.({
|
|
1426
|
-
message: 'For better performance, please upload the image in JPG format.',
|
|
1427
|
-
type: 'danger',
|
|
1428
|
-
});
|
|
1429
|
-
return;
|
|
1430
|
-
}
|
|
1431
|
-
let imageWidth = 350;
|
|
1432
|
-
const aspectRatio = img.height / img.width;
|
|
1433
|
-
let imageHeight = imageWidth * aspectRatio;
|
|
1434
|
-
const maxHeight = 600;
|
|
1435
|
-
if (imageHeight > maxHeight) {
|
|
1436
|
-
imageHeight = maxHeight;
|
|
1437
|
-
imageWidth = imageHeight / aspectRatio;
|
|
1438
|
-
if (imageWidth > 600) {
|
|
1439
|
-
imageWidth = 600;
|
|
1440
|
-
}
|
|
1441
|
-
}
|
|
1442
|
-
const imageShape = {
|
|
1443
|
-
type: 'image',
|
|
1444
|
-
img: img,
|
|
1445
|
-
src: event.target.result,
|
|
1446
|
-
x1: 50,
|
|
1447
|
-
y1: 50,
|
|
1448
|
-
x2: 50 + imageWidth,
|
|
1449
|
-
y2: 50 + imageHeight,
|
|
1450
|
-
};
|
|
1451
|
-
this.parameters.shapes.push(imageShape);
|
|
1452
|
-
this.parameters.updateShapes(this.parameters.shapes);
|
|
1453
|
-
this.drawShapes();
|
|
1454
|
-
if (doEmits) {
|
|
1455
|
-
this.parameters.socket.emit('updateBoardAction', { action: 'uploadImage', payload: imageShape }, this.handleServerResponse);
|
|
1456
|
-
}
|
|
1457
|
-
};
|
|
1458
|
-
img.onerror = () => {
|
|
1459
|
-
this.parameters.showAlert?.({ message: 'Error loading image', type: 'danger' });
|
|
1460
|
-
};
|
|
1461
|
-
img.src = event.target.result;
|
|
1462
|
-
};
|
|
1463
|
-
reader.onerror = () => {
|
|
1464
|
-
this.parameters.showAlert?.({ message: 'Error reading file', type: 'danger' });
|
|
1465
|
-
};
|
|
1466
|
-
reader.readAsDataURL(file);
|
|
1467
|
-
}
|
|
1468
|
-
catch (error) {
|
|
1469
|
-
//console.log(error);
|
|
1470
|
-
}
|
|
1471
|
-
};
|
|
1472
|
-
handleServerResponse = (response) => {
|
|
1473
|
-
if (!response.success) {
|
|
1474
|
-
this.parameters.showAlert?.({
|
|
1475
|
-
message: `Whiteboard action failed: ${response.reason}`,
|
|
1476
|
-
type: 'danger',
|
|
1477
|
-
});
|
|
1478
|
-
}
|
|
1479
|
-
};
|
|
1480
|
-
WhiteboardAction = (data) => {
|
|
1481
|
-
const { action, payload } = data;
|
|
1482
|
-
const ctx = this.canvasRef.nativeElement.getContext('2d');
|
|
1483
|
-
if (!ctx)
|
|
1484
|
-
return;
|
|
1485
|
-
this.parameters.updateCanvasWhiteboard(this.canvasRef.nativeElement);
|
|
1486
|
-
switch (action) {
|
|
1487
|
-
case 'draw':
|
|
1488
|
-
if (payload.type === 'freehand') {
|
|
1489
|
-
this.drawFreehand(payload.points, payload.color, payload.thickness);
|
|
1490
|
-
this.parameters.shapes.push({
|
|
1491
|
-
type: 'freehand',
|
|
1492
|
-
points: payload.points,
|
|
1493
|
-
color: payload.color,
|
|
1494
|
-
thickness: payload.thickness,
|
|
1495
|
-
});
|
|
1496
|
-
this.parameters.updateShapes(this.parameters.shapes);
|
|
1497
|
-
}
|
|
1498
|
-
else {
|
|
1499
|
-
this.drawLine(payload.x1, payload.y1, payload.x2, payload.y2, payload.color, payload.thickness, payload.lineType);
|
|
1500
|
-
this.parameters.shapes.push({
|
|
1501
|
-
type: 'line',
|
|
1502
|
-
x1: payload.x1,
|
|
1503
|
-
y1: payload.y1,
|
|
1504
|
-
x2: payload.x2,
|
|
1505
|
-
y2: payload.y2,
|
|
1506
|
-
color: payload.color,
|
|
1507
|
-
thickness: payload.thickness,
|
|
1508
|
-
lineType: payload.lineType,
|
|
1509
|
-
});
|
|
1510
|
-
this.parameters.updateShapes(this.parameters.shapes);
|
|
1511
|
-
}
|
|
1512
|
-
break;
|
|
1513
|
-
case 'shape':
|
|
1514
|
-
this.drawShape(payload.type, payload.x1, payload.y1, payload.x2, payload.y2, payload.color, payload.thickness, payload.lineType);
|
|
1515
|
-
this.parameters.shapes.push({
|
|
1516
|
-
type: payload.type,
|
|
1517
|
-
x1: payload.x1,
|
|
1518
|
-
y1: payload.y1,
|
|
1519
|
-
x2: payload.x2,
|
|
1520
|
-
y2: payload.y2,
|
|
1521
|
-
color: payload.color,
|
|
1522
|
-
thickness: payload.thickness,
|
|
1523
|
-
lineType: payload.lineType,
|
|
1524
|
-
});
|
|
1525
|
-
this.parameters.updateShapes(this.parameters.shapes);
|
|
1526
|
-
break;
|
|
1527
|
-
case 'erase':
|
|
1528
|
-
this.erase(payload.x, payload.y);
|
|
1529
|
-
break;
|
|
1530
|
-
case 'clear':
|
|
1531
|
-
this.clearCanvas(false);
|
|
1532
|
-
break;
|
|
1533
|
-
case 'uploadImage': {
|
|
1534
|
-
const img = new Image();
|
|
1535
|
-
img.crossOrigin = 'anonymous';
|
|
1536
|
-
img.onload = () => {
|
|
1537
|
-
const imageShape = {
|
|
1538
|
-
type: 'image',
|
|
1539
|
-
img,
|
|
1540
|
-
src: payload.src,
|
|
1541
|
-
x1: payload.x1,
|
|
1542
|
-
y1: payload.y1,
|
|
1543
|
-
x2: payload.x2,
|
|
1544
|
-
y2: payload.y2,
|
|
1545
|
-
};
|
|
1546
|
-
this.parameters.shapes.push(imageShape);
|
|
1547
|
-
this.parameters.updateShapes(this.parameters.shapes);
|
|
1548
|
-
this.drawShapes();
|
|
1549
|
-
};
|
|
1550
|
-
img.src = payload.src;
|
|
1551
|
-
break;
|
|
1552
|
-
}
|
|
1553
|
-
case 'toggleBackground':
|
|
1554
|
-
this.toggleBackground(false);
|
|
1555
|
-
this.drawShapes();
|
|
1556
|
-
break;
|
|
1557
|
-
case 'undo':
|
|
1558
|
-
if (this.parameters.shapes.length > 0) {
|
|
1559
|
-
this.parameters.redoStack.push(this.parameters.shapes.pop());
|
|
1560
|
-
this.parameters.updateRedoStack(this.parameters.redoStack);
|
|
1561
|
-
this.drawShapes();
|
|
1562
|
-
}
|
|
1563
|
-
break;
|
|
1564
|
-
case 'redo':
|
|
1565
|
-
if (this.parameters.redoStack.length > 0) {
|
|
1566
|
-
this.parameters.shapes.push(this.parameters.redoStack.pop());
|
|
1567
|
-
this.parameters.updateShapes(this.parameters.shapes);
|
|
1568
|
-
this.drawShapes();
|
|
1569
|
-
}
|
|
1570
|
-
break;
|
|
1571
|
-
case 'text':
|
|
1572
|
-
this.parameters.shapes.push({
|
|
1573
|
-
type: 'text',
|
|
1574
|
-
text: payload.text,
|
|
1575
|
-
x: payload.x,
|
|
1576
|
-
y: payload.y,
|
|
1577
|
-
color: payload.color,
|
|
1578
|
-
font: payload.font,
|
|
1579
|
-
fontSize: payload.fontSize,
|
|
1580
|
-
});
|
|
1581
|
-
this.parameters.updateShapes(this.parameters.shapes);
|
|
1582
|
-
this.drawShapes();
|
|
1583
|
-
break;
|
|
1584
|
-
case 'deleteShape':
|
|
1585
|
-
this.parameters.shapes = this.parameters.shapes.filter((shape) => shape !== payload);
|
|
1586
|
-
this.parameters.updateShapes(this.parameters.shapes);
|
|
1587
|
-
this.drawShapes();
|
|
1588
|
-
break;
|
|
1589
|
-
case 'shapes': {
|
|
1590
|
-
const oldShapes = this.parameters.shapes.filter((shape) => shape.type === 'image');
|
|
1591
|
-
this.parameters.shapes = payload.shapes.map((shape) => {
|
|
1592
|
-
if (shape.type === 'image') {
|
|
1593
|
-
const oldShape = oldShapes.find((oldShape) => oldShape.src === shape.src);
|
|
1594
|
-
if (oldShape) {
|
|
1595
|
-
return { ...shape, img: oldShape.img };
|
|
1596
|
-
}
|
|
1597
|
-
else {
|
|
1598
|
-
const img = new Image();
|
|
1599
|
-
img.crossOrigin = 'anonymous';
|
|
1600
|
-
img.src = shape.src;
|
|
1601
|
-
return { ...shape, img };
|
|
1602
|
-
}
|
|
1603
|
-
}
|
|
1604
|
-
else {
|
|
1605
|
-
return shape;
|
|
1606
|
-
}
|
|
1607
|
-
});
|
|
1608
|
-
this.parameters.updateShapes(this.parameters.shapes);
|
|
1609
|
-
this.drawShapes();
|
|
1610
|
-
break;
|
|
1611
|
-
}
|
|
1612
|
-
default:
|
|
1613
|
-
break;
|
|
1614
|
-
}
|
|
1615
|
-
};
|
|
1616
|
-
WhiteboardUpdated = (data) => {
|
|
1617
|
-
// data = { whiteboardUsers, status}
|
|
1618
|
-
// status = 'started', 'ended', 'updated'
|
|
1619
|
-
// whiteboardUsers array
|
|
1620
|
-
// members (participants) array only sent to the host
|
|
1621
|
-
//whiteboardData = {shapes=[], useImageBackground=Boolean, redoStack=[], undoStack=[]} or {} or null
|
|
1622
|
-
const ctx = this.canvasRef.nativeElement.getContext('2d');
|
|
1623
|
-
if (!ctx)
|
|
1624
|
-
return;
|
|
1625
|
-
if (this.parameters.islevel == '2' && data.members) {
|
|
1626
|
-
this.parameters.participantsAll = data.members.map((participant) => ({
|
|
1627
|
-
isBanned: participant.isBanned,
|
|
1628
|
-
name: participant.name,
|
|
1629
|
-
}));
|
|
1630
|
-
this.parameters.participants = data.members.filter((participant) => participant.isBanned == false);
|
|
1631
|
-
this.parameters.updateParticipants(this.parameters.participants);
|
|
1632
|
-
}
|
|
1633
|
-
this.parameters.whiteboardUsers = data.whiteboardUsers;
|
|
1634
|
-
this.parameters.updateWhiteboardUsers(this.parameters.whiteboardUsers);
|
|
1635
|
-
const useBoard = this.parameters.whiteboardUsers.find((user) => user.name == this.parameters.member && user.useBoard)
|
|
1636
|
-
? true
|
|
1637
|
-
: false;
|
|
1638
|
-
if (this.parameters.islevel != '2' && !useBoard && !this.parameters.whiteboardEnded) {
|
|
1639
|
-
this.changeMode('pan');
|
|
1640
|
-
}
|
|
1641
|
-
if (data.whiteboardData && Object.keys(data.whiteboardData).length > 0) {
|
|
1642
|
-
if (data.whiteboardData.shapes) {
|
|
1643
|
-
const oldShapes = this.parameters.shapes.filter((shape) => shape.type === 'image');
|
|
1644
|
-
this.parameters.shapes = data.whiteboardData.shapes.map((shape) => {
|
|
1645
|
-
if (shape.type === 'image') {
|
|
1646
|
-
const oldShape = oldShapes.find((oldShape) => oldShape.src === shape.src);
|
|
1647
|
-
if (oldShape) {
|
|
1648
|
-
return { ...shape, img: oldShape.img };
|
|
1649
|
-
}
|
|
1650
|
-
else {
|
|
1651
|
-
const img = new Image();
|
|
1652
|
-
img.crossOrigin = 'anonymous';
|
|
1653
|
-
img.src = shape.src;
|
|
1654
|
-
return { ...shape, img };
|
|
1655
|
-
}
|
|
1656
|
-
}
|
|
1657
|
-
else {
|
|
1658
|
-
return shape;
|
|
1659
|
-
}
|
|
1660
|
-
});
|
|
1661
|
-
this.parameters.updateShapes(this.parameters.shapes);
|
|
1662
|
-
}
|
|
1663
|
-
if (data.whiteboardData.useImageBackground != null) {
|
|
1664
|
-
this.parameters.useImageBackground = data.whiteboardData.useImageBackground;
|
|
1665
|
-
this.parameters.updateUseImageBackground(this.parameters.useImageBackground);
|
|
1666
|
-
}
|
|
1667
|
-
else {
|
|
1668
|
-
this.parameters.useImageBackground = true;
|
|
1669
|
-
this.parameters.updateUseImageBackground(true);
|
|
1670
|
-
}
|
|
1671
|
-
if (data.whiteboardData.redoStack) {
|
|
1672
|
-
this.parameters.redoStack = data.whiteboardData.redoStack;
|
|
1673
|
-
this.parameters.updateRedoStack(this.parameters.redoStack);
|
|
1674
|
-
}
|
|
1675
|
-
if (data.whiteboardData.undoStack) {
|
|
1676
|
-
this.parameters.undoStack = data.whiteboardData.undoStack;
|
|
1677
|
-
this.parameters.updateUndoStack(this.parameters.undoStack);
|
|
1678
|
-
}
|
|
1679
|
-
}
|
|
1680
|
-
if (data.status == 'started' && !this.parameters.whiteboardStarted) {
|
|
1681
|
-
this.parameters.whiteboardStarted = true;
|
|
1682
|
-
this.parameters.whiteboardEnded = false;
|
|
1683
|
-
this.parameters.screenId = `whiteboard-${this.parameters.roomName}`;
|
|
1684
|
-
this.parameters.updateWhiteboardStarted(true);
|
|
1685
|
-
this.parameters.updateWhiteboardEnded(false);
|
|
1686
|
-
this.parameters.updateScreenId(this.parameters.screenId);
|
|
1687
|
-
if (this.parameters.islevel != '2') {
|
|
1688
|
-
this.parameters.shareScreenStarted = true;
|
|
1689
|
-
this.parameters.updateShareScreenStarted(true);
|
|
1690
|
-
this.parameters.onScreenChanges({ changed: true, parameters: this.parameters });
|
|
1691
|
-
}
|
|
1692
|
-
}
|
|
1693
|
-
else if (data.status == 'ended') {
|
|
1694
|
-
const prevWhiteboardEnded = this.parameters.whiteboardEnded;
|
|
1695
|
-
const prevWhiteboardStarted = this.parameters.whiteboardStarted;
|
|
1696
|
-
this.parameters.whiteboardEnded = true;
|
|
1697
|
-
this.parameters.whiteboardStarted = false;
|
|
1698
|
-
this.parameters.updateWhiteboardStarted(false);
|
|
1699
|
-
this.parameters.updateWhiteboardEnded(true);
|
|
1700
|
-
if (this.parameters.islevel == '2' && prevWhiteboardEnded) {
|
|
1701
|
-
// No operation needed
|
|
1702
|
-
}
|
|
1703
|
-
else {
|
|
1704
|
-
this.parameters.shareScreenStarted = false;
|
|
1705
|
-
this.parameters.screenId = '';
|
|
1706
|
-
this.parameters.updateShareScreenStarted(false);
|
|
1707
|
-
this.parameters.updateScreenId('');
|
|
1708
|
-
this.parameters.onScreenChanges({ changed: true, parameters: this.parameters });
|
|
1709
|
-
}
|
|
1710
|
-
try {
|
|
1711
|
-
if (prevWhiteboardStarted &&
|
|
1712
|
-
this.parameters.islevel == '2' &&
|
|
1713
|
-
(this.parameters.recordStarted || this.parameters.recordResumed)) {
|
|
1714
|
-
if (!(this.parameters.recordPaused || this.parameters.recordStopped)) {
|
|
1715
|
-
if (this.parameters.recordingMediaOptions == 'video') {
|
|
1716
|
-
this.parameters.captureCanvasStream({ parameters: this.parameters, start: false });
|
|
1717
|
-
}
|
|
1718
|
-
}
|
|
1719
|
-
}
|
|
1720
|
-
}
|
|
1721
|
-
catch (error) {
|
|
1722
|
-
// Handle error
|
|
1723
|
-
}
|
|
1724
|
-
}
|
|
1725
|
-
else if (data.status == 'started' && this.parameters.whiteboardStarted) {
|
|
1726
|
-
this.parameters.whiteboardStarted = true;
|
|
1727
|
-
this.parameters.whiteboardEnded = false;
|
|
1728
|
-
this.parameters.updateWhiteboardStarted(true);
|
|
1729
|
-
this.parameters.updateWhiteboardEnded(false);
|
|
1730
|
-
this.parameters.shareScreenStarted = true;
|
|
1731
|
-
this.parameters.screenId = `whiteboard-${this.parameters.roomName}`;
|
|
1732
|
-
this.parameters.updateShareScreenStarted(true);
|
|
1733
|
-
this.parameters.updateScreenId(this.parameters.screenId);
|
|
1734
|
-
this.parameters.onScreenChanges({ changed: true, parameters: this.parameters });
|
|
1735
|
-
}
|
|
1736
|
-
};
|
|
1737
|
-
handleDropdownClick(id) {
|
|
1738
|
-
this.dropdownOpen = this.dropdownOpen === id ? null : id;
|
|
1739
|
-
}
|
|
1740
|
-
handleItemClick(callback, name, value) {
|
|
1741
|
-
callback(value);
|
|
1742
|
-
this.dropdownOpen = null;
|
|
1743
|
-
if (['draw', 'freehand', 'shape', 'text', 'erase'].includes(name)) {
|
|
1744
|
-
this.changeMode(name);
|
|
1745
|
-
}
|
|
1746
|
-
}
|
|
1747
|
-
dropdownItems(items, name, callback) {
|
|
1748
|
-
return items.map((item, index) => `<button key="${index}" class="dropdown-item" (click)="handleItemClick(${callback}, '${name}', ${item.value})" style="padding: 5px;">
|
|
1749
|
-
${item.label}
|
|
1750
|
-
</button>`);
|
|
1751
|
-
}
|
|
1752
|
-
toggleToolbar() {
|
|
1753
|
-
this.toolbarVisible = !this.toolbarVisible;
|
|
1754
|
-
}
|
|
1755
|
-
checkBoardAccess() {
|
|
1756
|
-
this.parameters = this.parameters.getUpdatedAllParams();
|
|
1757
|
-
if (this.parameters.whiteboardStarted && !this.parameters.whiteboardEnded) {
|
|
1758
|
-
const user = this.parameters.whiteboardUsers.find((user) => user.name === this.parameters.member);
|
|
1759
|
-
if ((!user || !user.useBoard) && this.parameters.islevel != '2') {
|
|
1760
|
-
this.parameters.showAlert?.({
|
|
1761
|
-
message: 'You are not allowed to use the whiteboard. Please ask the host to assign you.',
|
|
1762
|
-
type: 'danger',
|
|
1763
|
-
});
|
|
1764
|
-
return false;
|
|
1765
|
-
}
|
|
1766
|
-
else {
|
|
1767
|
-
return true;
|
|
1768
|
-
}
|
|
1769
|
-
}
|
|
1770
|
-
else {
|
|
1771
|
-
return true;
|
|
1772
|
-
}
|
|
1773
|
-
}
|
|
1774
|
-
changeMode(newMode) {
|
|
1775
|
-
if (newMode !== 'pan' && !this.checkBoardAccess())
|
|
1776
|
-
return;
|
|
1777
|
-
this.mode = newMode;
|
|
1778
|
-
const canvas = this.canvasRef.nativeElement;
|
|
1779
|
-
if (newMode === 'pan') {
|
|
1780
|
-
canvas.style.cursor = 'grab';
|
|
1781
|
-
}
|
|
1782
|
-
else if (newMode === 'select') {
|
|
1783
|
-
canvas.style.cursor = 'pointer';
|
|
1784
|
-
}
|
|
1785
|
-
else if (newMode === 'erase') {
|
|
1786
|
-
canvas.style.cursor = 'crosshair';
|
|
1787
|
-
}
|
|
1788
|
-
else {
|
|
1789
|
-
canvas.style.cursor = 'crosshair';
|
|
1790
|
-
}
|
|
1791
|
-
if (newMode !== 'freehand' && this.freehandDrawing.length > 0) {
|
|
1792
|
-
this.parameters.shapes.push({
|
|
1793
|
-
type: 'freehand',
|
|
1794
|
-
points: this.freehandDrawing,
|
|
1795
|
-
color: this.color,
|
|
1796
|
-
thickness: this.brushThickness,
|
|
1797
|
-
});
|
|
1798
|
-
this.parameters.updateShapes(this.parameters.shapes);
|
|
1799
|
-
this.freehandDrawing = [];
|
|
1800
|
-
this.saveState();
|
|
1801
|
-
}
|
|
1802
|
-
}
|
|
1803
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: Whiteboard, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1804
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.8", type: Whiteboard, isStandalone: true, selector: "app-whiteboard", inputs: { customWidth: "customWidth", customHeight: "customHeight", parameters: "parameters", showAspect: "showAspect" }, viewQueries: [{ propertyName: "canvasRef", first: true, predicate: ["canvasRef"], descendants: true }, { propertyName: "textInputRef", first: true, predicate: ["textInputRef"], descendants: true }, { propertyName: "toggleBackgroundRef", first: true, predicate: ["toggleBackgroundRef"], descendants: true }, { propertyName: "downloadLinkRef", first: true, predicate: ["downloadLinkRef"], descendants: true }, { propertyName: "tempCanvasRef", first: true, predicate: ["tempCanvasRef"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div id=\"whiteboard-interface\" [style.width.px]=\"customWidth\" [style.height.px]=\"customHeight\" [style.display]=\"showAspect ? 'block' : 'none'\" style=\"position: relative; display: flex; justify-content: center; align-items: center; border: 2px solid #000; background-color: #f0f0f0;\">\r\n <div id=\"whiteboardContent\" style=\"position: relative; display: flex; justify-content: center; align-items: center; width: 100%; height: 100%; max-width: 100%; max-height: 100%; overflow: auto;\">\r\n <button id=\"toolbarToggle\" class=\"btn btnBoard btn-primary\" style=\"position: absolute; top: 5px; left: 55px; z-index: 10;\" (click)=\"toggleToolbar()\">\r\n <fa-icon [icon]=\"toolbarVisible ? faChevronLeft : faChevronRight\"></fa-icon>\r\n </button>\r\n <div *ngIf=\"toolbarVisible\" class=\"toolbar mb-3\" id=\"toolbar\" style=\"position: absolute; top: 5px; left: 100px; z-index: 10; background-color: transparent;\">\r\n <div class=\"btn-group\" role=\"group\">\r\n <button class=\"btn btnBoard btn-secondary dropdown-toggle\" id=\"drawMode\" (click)=\"handleDropdownClick('drawMode')\">\r\n <fa-icon [icon]=\"faPencilAlt\"></fa-icon>\r\n </button>\r\n <div *ngIf=\"dropdownOpen === 'drawMode'\" class=\"dropdown-menu show\">\r\n <button *ngFor=\"let item of [{ label: 'XX-Small (3px)', value: 3 }, { label: 'X-Small (6px)', value: 6 }, { label: 'Small (12px)', value: 12 }, { label: 'Medium (18px)', value: 18 }, { label: 'Large (24px)', value: 24 }, { label: 'X-Large (36px)', value: 36 }]\" class=\"dropdown-item\" (click)=\"handleItemClick(updateLineThickness, 'draw', item.value)\" style=\"padding: 5px;\">\r\n {{ item.label }}\r\n </button>\r\n </div>\r\n </div>\r\n <div class=\"btn-group\" role=\"group\">\r\n <button class=\"btn btnBoard btn-secondary dropdown-toggle\" id=\"freehandMode\" (click)=\"handleDropdownClick('freehandMode')\">\r\n <fa-icon [icon]=\"faPaintBrush\"></fa-icon>\r\n </button>\r\n <div *ngIf=\"dropdownOpen === 'freehandMode'\" class=\"dropdown-menu show\">\r\n <button *ngFor=\"let item of [{ label: 'X-Small (5px)', value: 5 }, { label: 'Small (10px)', value: 10 }, { label: 'Medium (20px)', value: 20 }, { label: 'Large (40px)', value: 40 }, { label: 'X-Large (60px)', value: 60 }]\" class=\"dropdown-item\" (click)=\"handleItemClick(updateBrushThickness, 'freehand', item.value)\" style=\"padding: 5px;\">\r\n {{ item.label }}\r\n </button>\r\n </div>\r\n </div>\r\n <div class=\"btn-group\" role=\"group\">\r\n <button class=\"btn btnBoard btn-secondary dropdown-toggle\" id=\"shapeMode\" (click)=\"handleDropdownClick('shapeMode')\">\r\n <fa-icon [icon]=\"faShapes\"></fa-icon>\r\n </button>\r\n <div *ngIf=\"dropdownOpen === 'shapeMode'\" class=\"dropdown-menu show\">\r\n <button *ngFor=\"let item of [\r\n { label: '<img src=\\'https://mediasfu.com/images/svg/square.svg\\' alt=\\'Square\\' class=\\'shape-icon\\' />', value: 'square' },\r\n { label: '<img src=\\'https://mediasfu.com/images/svg/rectangle.svg\\' alt=\\'Rectangle\\' class=\\'shape-icon\\' />', value: 'rectangle' },\r\n { label: '<img src=\\'https://mediasfu.com/images/svg/circle.svg\\' alt=\\'Circle\\' class=\\'shape-icon\\' />', value: 'circle' },\r\n { label: '<img src=\\'https://mediasfu.com/images/svg/triangle.svg\\' alt=\\'Triangle\\' class=\\'shape-icon\\' />', value: 'triangle' },\r\n { label: '<img src=\\'https://mediasfu.com/images/svg/hexagon.svg\\' alt=\\'Hexagon\\' class=\\'shape-icon\\' />', value: 'hexagon' },\r\n { label: '<img src=\\'https://mediasfu.com/images/svg/pentagon.svg\\' alt=\\'Pentagon\\' class=\\'shape-icon\\' />', value: 'pentagon' },\r\n { label: '<img src=\\'https://mediasfu.com/images/svg/rhombus.svg\\' alt=\\'Rhombus\\' class=\\'shape-icon\\' />', value: 'rhombus' },\r\n { label: '<img src=\\'https://mediasfu.com/images/svg/octagon.svg\\' alt=\\'Octagon\\' class=\\'shape-icon\\' />', value: 'octagon' },\r\n { label: '<img src=\\'https://mediasfu.com/images/svg/parallelogram.svg\\' alt=\\'Parallelogram\\' class=\\'shape-icon\\' />', value: 'parallelogram' },\r\n { label: '<img src=\\'https://mediasfu.com/images/svg/oval.svg\\' alt=\\'Oval\\' class=\\'shape-icon\\' />', value: 'oval' }\r\n ]\" class=\"dropdown-item\" (click)=\"handleItemClick(updateShape, 'shape', item.value)\" style=\"padding: 5px;\" [innerHTML]=\"item.label\">\r\n </button>\r\n </div>\r\n </div>\r\n <button class=\"btn btnBoard btn-secondary\" id=\"selectMode\" (click)=\"changeMode('select')\">\r\n <fa-icon [icon]=\"faMousePointer\"></fa-icon>\r\n </button>\r\n <div class=\"btn-group\" role=\"group\">\r\n <button class=\"btn btnBoard btn-danger dropdown-toggle\" id=\"eraseMode\" (click)=\"handleDropdownClick('eraseMode')\">\r\n <fa-icon [icon]=\"faEraser\"></fa-icon>\r\n </button>\r\n <div *ngIf=\"dropdownOpen === 'eraseMode'\" class=\"dropdown-menu show\">\r\n <button *ngFor=\"let item of [{ label: 'X-Small (5px)', value: 5 }, { label: 'Small (10px)', value: 10 }, { label: 'Medium (20px)', value: 20 }, { label: 'Large (30px)', value: 30 }, { label: 'X-Large (60px)', value: 60 }]\" class=\"dropdown-item\" (click)=\"handleItemClick(updateEraserThickness, 'erase', item.value)\" style=\"padding: 5px;\">\r\n {{ item.label }}\r\n </button>\r\n </div>\r\n </div>\r\n <button class=\"btn btnBoard btn-info\" id=\"panMode\" (click)=\"changeMode('pan')\">\r\n <fa-icon [icon]=\"faHandPaper\"></fa-icon>\r\n </button>\r\n <button class=\"btn btnBoard btn-success\" id=\"zoomIn\" (click)=\"zoomCanvas(1.2, $event)\">\r\n <fa-icon [icon]=\"faSearchPlus\"></fa-icon>\r\n </button>\r\n <button class=\"btn btnBoard btn-success\" id=\"zoomReset\" (click)=\"zoomCanvas(10, $event)\">\r\n <fa-icon [icon]=\"faSearch\"></fa-icon>\r\n </button>\r\n <button class=\"btn btnBoard btn-success\" id=\"zoomOut\" (click)=\"zoomCanvas(0.8, $event)\">\r\n <fa-icon [icon]=\"faSearchMinus\"></fa-icon>\r\n </button>\r\n <div class=\"btn-group\" role=\"group\">\r\n <button class=\"btn btnBoard btn-secondary dropdown-toggle\" id=\"addText\" (click)=\"handleDropdownClick('addText')\">\r\n <fa-icon [icon]=\"faFont\"></fa-icon>\r\n </button>\r\n <div *ngIf=\"dropdownOpen === 'addText'\" class=\"dropdown-menu show\">\r\n <button *ngFor=\"let item of [{ label: 'Arial', value: 'Arial' }, { label: 'Times New Roman', value: 'Times New Roman' }, { label: 'Courier New', value: 'Courier New' }, { label: 'Verdana', value: 'Verdana' }]\" class=\"dropdown-item\" (click)=\"handleItemClick(updateFont, 'text', item.value)\" style=\"padding: 5px;\">\r\n {{ item.label }}\r\n </button>\r\n </div>\r\n </div>\r\n <div class=\"btn-group\" role=\"group\">\r\n <button class=\"btn btnBoard btn-secondary dropdown-toggle\" id=\"fontSize\" (click)=\"handleDropdownClick('fontSize')\">\r\n <fa-icon [icon]=\"faTextHeight\"></fa-icon>\r\n </button>\r\n <div *ngIf=\"dropdownOpen === 'fontSize'\" class=\"dropdown-menu show\">\r\n <button *ngFor=\"let item of [{ label: 'X-Small (5px)', value: 5 }, { label: 'Small (10px)', value: 10 }, { label: 'Medium (20px)', value: 20 }, { label: 'Large (40px)', value: 40 }, { label: 'X-Large (60px)', value: 60 }]\" class=\"dropdown-item\" (click)=\"handleItemClick(updateFontSize, '', item.value)\" style=\"padding: 5px;\">\r\n {{ item.label }}\r\n </button>\r\n </div>\r\n </div>\r\n <button class=\"btn btnBoard btn-secondary\" id=\"undo\" (click)=\"undo()\">\r\n <fa-icon [icon]=\"faUndo\"></fa-icon>\r\n </button>\r\n <button class=\"btn btnBoard btn-secondary\" id=\"redo\" (click)=\"redo()\">\r\n <fa-icon [icon]=\"faRedo\"></fa-icon>\r\n </button>\r\n <button class=\"btn btnBoard btn-secondary\" id=\"save\" (click)=\"saveCanvas()\">\r\n <fa-icon [icon]=\"faSave\"></fa-icon>\r\n </button>\r\n <button class=\"btn btnBoard btn-danger\" id=\"delete\" (click)=\"deleteShape()\">\r\n <fa-icon [icon]=\"faTrash\"></fa-icon>\r\n </button>\r\n <button class=\"btn btnBoard btn-secondary\" id=\"clearCanvas\" (click)=\"clearCanvas()\">\r\n <fa-icon [icon]=\"faTimes\"></fa-icon>\r\n </button>\r\n <button id=\"toggleBackgroundRef\" #toggleBackgroundRef class=\"btn btnBoard btn-secondary\" (click)=\"toggleBackground()\">\r\n <img src=\"https://mediasfu.com/images/svg/graph.jpg\" alt=\"Background\" class=\"toggle-icon\" id=\"backgroundIcon\" />\r\n </button>\r\n <input type=\"file\" id=\"uploadBoardImage\" accept=\"image/*\" style=\"display: none;\" (change)=\"uploadImage($event)\" />\r\n <label for=\"uploadBoardImage\" class=\"btn btnBoard btn-primary\">\r\n <fa-icon [icon]=\"faUpload\"></fa-icon>\r\n </label>\r\n <input type=\"color\" id=\"colorPicker\" class=\"btn\" [(ngModel)]=\"color\" />\r\n <select id=\"lineTypePicker\" class=\"custom-select\" style=\"width: auto;\" [(ngModel)]=\"lineType\">\r\n <option value=\"solid\">Solid</option>\r\n <option value=\"dashed\">Dashed</option>\r\n <option value=\"dotted\">Dotted</option>\r\n <option value=\"dashDot\">Dash-Dot</option>\r\n </select>\r\n </div>\r\n <canvas id=\"canvasRef\" width=\"1280\" height=\"720\" style=\"border: 2px solid red;\" #canvasRef></canvas>\r\n <textarea id=\"textInputRef\" class=\"form-control\" #textInputRef style=\"display: none; position: absolute;\"></textarea>\r\n <a href=\"#\" id=\"downloadLinkRef\" #downloadLinkRef style=\"display: none;\">Download</a>\r\n <canvas id=\"tempCanvasRef\" #tempCanvasRef style=\"display: none;\"></canvas>\r\n </div>\r\n</div>\r\n", styles: ["#whiteboardCanvas,#canvsRef{border:1px solid #000;cursor:crosshair;background-color:#fff}.resize-handle,.move-handle{width:8px;height:8px;background:red;position:absolute}.move-handle{background:#00f}#textInput,#textInputRef{display:none;position:absolute;z-index:10;width:200px}.shape-icon{width:20px!important;height:20px!important;color:#fff}.toolbar .btn-group button,.toolbar .dropdown-menu a{font-size:.8rem;padding:5px 10px;margin:0 2px;border-radius:4px;transition:background-color .2s}.toolbar .dropdown-menu a{background-color:transparent;color:#1b1a1a}.toolbar .btn-group button:hover,.toolbar .dropdown-menu a:hover{background-color:#e3e7eb}.toolbar .btn-group button.active{background-color:#454d55}.toolbarScreen .btn-group button,.toolbarScreen .dropdown-menu a{font-size:.8rem;padding:5px 10px;margin:0 2px;border-radius:4px;transition:background-color .2s;color:\"black\"}.toolbarScreen .btn-group button{background-color:#e3e7eb;border:none}.toolbarScreen .dropdown-menu a{background-color:transparent;color:#1b1a1a}.toolbarScreen .btn-group button:hover,.toolbarScreen .dropdown-menu a:hover{background-color:#d6d1d166;color:#000}.toolbarScreen .btn-group button.active{background-color:#454d55}#toolbarToggleScreen{background-color:#d6d1d166;border:\"1px solid black\"}#toolbar,#toolbarScreen{transition:display .3s ease-in-out}#toolbarToggle,#toolbarToggleScreen{cursor:pointer}#colorPicker,#colorPickerScreen{font-size:.8rem;padding:2px;width:32px;height:32px}#lineTypePicker{font-size:.8rem;padding:2px auto;width:32px;height:32px}.btnBoard{font-size:1rem;padding:2px;width:40px;height:40px;margin:2px}#lineTypePickerScreen{font-size:.8rem;padding:2px auto;width:32px;height:32px;background-color:#d6d1d166;color:#000}.toggle-icon{width:34px;height:34px;padding:0;margin:0}#toggleBackground.active{background-color:#fdfeff}.annotateScreenBtn{background-color:#2d2e2f!important;border:2px solid #000!important;color:green!important}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: FontAwesomeModule }, { kind: "component", type: i3.FaIconComponent, selector: "fa-icon", inputs: ["icon", "title", "animation", "mask", "flip", "size", "pull", "border", "inverse", "symbol", "rotate", "fixedWidth", "transform", "a11yRole"] }], encapsulation: i0.ViewEncapsulation.None });
|
|
1805
|
-
}
|
|
1806
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: Whiteboard, decorators: [{
|
|
1807
|
-
type: Component,
|
|
1808
|
-
args: [{ selector: 'app-whiteboard', standalone: true, encapsulation: ViewEncapsulation.None, imports: [CommonModule, FormsModule, FontAwesomeModule], template: "<div id=\"whiteboard-interface\" [style.width.px]=\"customWidth\" [style.height.px]=\"customHeight\" [style.display]=\"showAspect ? 'block' : 'none'\" style=\"position: relative; display: flex; justify-content: center; align-items: center; border: 2px solid #000; background-color: #f0f0f0;\">\r\n <div id=\"whiteboardContent\" style=\"position: relative; display: flex; justify-content: center; align-items: center; width: 100%; height: 100%; max-width: 100%; max-height: 100%; overflow: auto;\">\r\n <button id=\"toolbarToggle\" class=\"btn btnBoard btn-primary\" style=\"position: absolute; top: 5px; left: 55px; z-index: 10;\" (click)=\"toggleToolbar()\">\r\n <fa-icon [icon]=\"toolbarVisible ? faChevronLeft : faChevronRight\"></fa-icon>\r\n </button>\r\n <div *ngIf=\"toolbarVisible\" class=\"toolbar mb-3\" id=\"toolbar\" style=\"position: absolute; top: 5px; left: 100px; z-index: 10; background-color: transparent;\">\r\n <div class=\"btn-group\" role=\"group\">\r\n <button class=\"btn btnBoard btn-secondary dropdown-toggle\" id=\"drawMode\" (click)=\"handleDropdownClick('drawMode')\">\r\n <fa-icon [icon]=\"faPencilAlt\"></fa-icon>\r\n </button>\r\n <div *ngIf=\"dropdownOpen === 'drawMode'\" class=\"dropdown-menu show\">\r\n <button *ngFor=\"let item of [{ label: 'XX-Small (3px)', value: 3 }, { label: 'X-Small (6px)', value: 6 }, { label: 'Small (12px)', value: 12 }, { label: 'Medium (18px)', value: 18 }, { label: 'Large (24px)', value: 24 }, { label: 'X-Large (36px)', value: 36 }]\" class=\"dropdown-item\" (click)=\"handleItemClick(updateLineThickness, 'draw', item.value)\" style=\"padding: 5px;\">\r\n {{ item.label }}\r\n </button>\r\n </div>\r\n </div>\r\n <div class=\"btn-group\" role=\"group\">\r\n <button class=\"btn btnBoard btn-secondary dropdown-toggle\" id=\"freehandMode\" (click)=\"handleDropdownClick('freehandMode')\">\r\n <fa-icon [icon]=\"faPaintBrush\"></fa-icon>\r\n </button>\r\n <div *ngIf=\"dropdownOpen === 'freehandMode'\" class=\"dropdown-menu show\">\r\n <button *ngFor=\"let item of [{ label: 'X-Small (5px)', value: 5 }, { label: 'Small (10px)', value: 10 }, { label: 'Medium (20px)', value: 20 }, { label: 'Large (40px)', value: 40 }, { label: 'X-Large (60px)', value: 60 }]\" class=\"dropdown-item\" (click)=\"handleItemClick(updateBrushThickness, 'freehand', item.value)\" style=\"padding: 5px;\">\r\n {{ item.label }}\r\n </button>\r\n </div>\r\n </div>\r\n <div class=\"btn-group\" role=\"group\">\r\n <button class=\"btn btnBoard btn-secondary dropdown-toggle\" id=\"shapeMode\" (click)=\"handleDropdownClick('shapeMode')\">\r\n <fa-icon [icon]=\"faShapes\"></fa-icon>\r\n </button>\r\n <div *ngIf=\"dropdownOpen === 'shapeMode'\" class=\"dropdown-menu show\">\r\n <button *ngFor=\"let item of [\r\n { label: '<img src=\\'https://mediasfu.com/images/svg/square.svg\\' alt=\\'Square\\' class=\\'shape-icon\\' />', value: 'square' },\r\n { label: '<img src=\\'https://mediasfu.com/images/svg/rectangle.svg\\' alt=\\'Rectangle\\' class=\\'shape-icon\\' />', value: 'rectangle' },\r\n { label: '<img src=\\'https://mediasfu.com/images/svg/circle.svg\\' alt=\\'Circle\\' class=\\'shape-icon\\' />', value: 'circle' },\r\n { label: '<img src=\\'https://mediasfu.com/images/svg/triangle.svg\\' alt=\\'Triangle\\' class=\\'shape-icon\\' />', value: 'triangle' },\r\n { label: '<img src=\\'https://mediasfu.com/images/svg/hexagon.svg\\' alt=\\'Hexagon\\' class=\\'shape-icon\\' />', value: 'hexagon' },\r\n { label: '<img src=\\'https://mediasfu.com/images/svg/pentagon.svg\\' alt=\\'Pentagon\\' class=\\'shape-icon\\' />', value: 'pentagon' },\r\n { label: '<img src=\\'https://mediasfu.com/images/svg/rhombus.svg\\' alt=\\'Rhombus\\' class=\\'shape-icon\\' />', value: 'rhombus' },\r\n { label: '<img src=\\'https://mediasfu.com/images/svg/octagon.svg\\' alt=\\'Octagon\\' class=\\'shape-icon\\' />', value: 'octagon' },\r\n { label: '<img src=\\'https://mediasfu.com/images/svg/parallelogram.svg\\' alt=\\'Parallelogram\\' class=\\'shape-icon\\' />', value: 'parallelogram' },\r\n { label: '<img src=\\'https://mediasfu.com/images/svg/oval.svg\\' alt=\\'Oval\\' class=\\'shape-icon\\' />', value: 'oval' }\r\n ]\" class=\"dropdown-item\" (click)=\"handleItemClick(updateShape, 'shape', item.value)\" style=\"padding: 5px;\" [innerHTML]=\"item.label\">\r\n </button>\r\n </div>\r\n </div>\r\n <button class=\"btn btnBoard btn-secondary\" id=\"selectMode\" (click)=\"changeMode('select')\">\r\n <fa-icon [icon]=\"faMousePointer\"></fa-icon>\r\n </button>\r\n <div class=\"btn-group\" role=\"group\">\r\n <button class=\"btn btnBoard btn-danger dropdown-toggle\" id=\"eraseMode\" (click)=\"handleDropdownClick('eraseMode')\">\r\n <fa-icon [icon]=\"faEraser\"></fa-icon>\r\n </button>\r\n <div *ngIf=\"dropdownOpen === 'eraseMode'\" class=\"dropdown-menu show\">\r\n <button *ngFor=\"let item of [{ label: 'X-Small (5px)', value: 5 }, { label: 'Small (10px)', value: 10 }, { label: 'Medium (20px)', value: 20 }, { label: 'Large (30px)', value: 30 }, { label: 'X-Large (60px)', value: 60 }]\" class=\"dropdown-item\" (click)=\"handleItemClick(updateEraserThickness, 'erase', item.value)\" style=\"padding: 5px;\">\r\n {{ item.label }}\r\n </button>\r\n </div>\r\n </div>\r\n <button class=\"btn btnBoard btn-info\" id=\"panMode\" (click)=\"changeMode('pan')\">\r\n <fa-icon [icon]=\"faHandPaper\"></fa-icon>\r\n </button>\r\n <button class=\"btn btnBoard btn-success\" id=\"zoomIn\" (click)=\"zoomCanvas(1.2, $event)\">\r\n <fa-icon [icon]=\"faSearchPlus\"></fa-icon>\r\n </button>\r\n <button class=\"btn btnBoard btn-success\" id=\"zoomReset\" (click)=\"zoomCanvas(10, $event)\">\r\n <fa-icon [icon]=\"faSearch\"></fa-icon>\r\n </button>\r\n <button class=\"btn btnBoard btn-success\" id=\"zoomOut\" (click)=\"zoomCanvas(0.8, $event)\">\r\n <fa-icon [icon]=\"faSearchMinus\"></fa-icon>\r\n </button>\r\n <div class=\"btn-group\" role=\"group\">\r\n <button class=\"btn btnBoard btn-secondary dropdown-toggle\" id=\"addText\" (click)=\"handleDropdownClick('addText')\">\r\n <fa-icon [icon]=\"faFont\"></fa-icon>\r\n </button>\r\n <div *ngIf=\"dropdownOpen === 'addText'\" class=\"dropdown-menu show\">\r\n <button *ngFor=\"let item of [{ label: 'Arial', value: 'Arial' }, { label: 'Times New Roman', value: 'Times New Roman' }, { label: 'Courier New', value: 'Courier New' }, { label: 'Verdana', value: 'Verdana' }]\" class=\"dropdown-item\" (click)=\"handleItemClick(updateFont, 'text', item.value)\" style=\"padding: 5px;\">\r\n {{ item.label }}\r\n </button>\r\n </div>\r\n </div>\r\n <div class=\"btn-group\" role=\"group\">\r\n <button class=\"btn btnBoard btn-secondary dropdown-toggle\" id=\"fontSize\" (click)=\"handleDropdownClick('fontSize')\">\r\n <fa-icon [icon]=\"faTextHeight\"></fa-icon>\r\n </button>\r\n <div *ngIf=\"dropdownOpen === 'fontSize'\" class=\"dropdown-menu show\">\r\n <button *ngFor=\"let item of [{ label: 'X-Small (5px)', value: 5 }, { label: 'Small (10px)', value: 10 }, { label: 'Medium (20px)', value: 20 }, { label: 'Large (40px)', value: 40 }, { label: 'X-Large (60px)', value: 60 }]\" class=\"dropdown-item\" (click)=\"handleItemClick(updateFontSize, '', item.value)\" style=\"padding: 5px;\">\r\n {{ item.label }}\r\n </button>\r\n </div>\r\n </div>\r\n <button class=\"btn btnBoard btn-secondary\" id=\"undo\" (click)=\"undo()\">\r\n <fa-icon [icon]=\"faUndo\"></fa-icon>\r\n </button>\r\n <button class=\"btn btnBoard btn-secondary\" id=\"redo\" (click)=\"redo()\">\r\n <fa-icon [icon]=\"faRedo\"></fa-icon>\r\n </button>\r\n <button class=\"btn btnBoard btn-secondary\" id=\"save\" (click)=\"saveCanvas()\">\r\n <fa-icon [icon]=\"faSave\"></fa-icon>\r\n </button>\r\n <button class=\"btn btnBoard btn-danger\" id=\"delete\" (click)=\"deleteShape()\">\r\n <fa-icon [icon]=\"faTrash\"></fa-icon>\r\n </button>\r\n <button class=\"btn btnBoard btn-secondary\" id=\"clearCanvas\" (click)=\"clearCanvas()\">\r\n <fa-icon [icon]=\"faTimes\"></fa-icon>\r\n </button>\r\n <button id=\"toggleBackgroundRef\" #toggleBackgroundRef class=\"btn btnBoard btn-secondary\" (click)=\"toggleBackground()\">\r\n <img src=\"https://mediasfu.com/images/svg/graph.jpg\" alt=\"Background\" class=\"toggle-icon\" id=\"backgroundIcon\" />\r\n </button>\r\n <input type=\"file\" id=\"uploadBoardImage\" accept=\"image/*\" style=\"display: none;\" (change)=\"uploadImage($event)\" />\r\n <label for=\"uploadBoardImage\" class=\"btn btnBoard btn-primary\">\r\n <fa-icon [icon]=\"faUpload\"></fa-icon>\r\n </label>\r\n <input type=\"color\" id=\"colorPicker\" class=\"btn\" [(ngModel)]=\"color\" />\r\n <select id=\"lineTypePicker\" class=\"custom-select\" style=\"width: auto;\" [(ngModel)]=\"lineType\">\r\n <option value=\"solid\">Solid</option>\r\n <option value=\"dashed\">Dashed</option>\r\n <option value=\"dotted\">Dotted</option>\r\n <option value=\"dashDot\">Dash-Dot</option>\r\n </select>\r\n </div>\r\n <canvas id=\"canvasRef\" width=\"1280\" height=\"720\" style=\"border: 2px solid red;\" #canvasRef></canvas>\r\n <textarea id=\"textInputRef\" class=\"form-control\" #textInputRef style=\"display: none; position: absolute;\"></textarea>\r\n <a href=\"#\" id=\"downloadLinkRef\" #downloadLinkRef style=\"display: none;\">Download</a>\r\n <canvas id=\"tempCanvasRef\" #tempCanvasRef style=\"display: none;\"></canvas>\r\n </div>\r\n</div>\r\n", styles: ["#whiteboardCanvas,#canvsRef{border:1px solid #000;cursor:crosshair;background-color:#fff}.resize-handle,.move-handle{width:8px;height:8px;background:red;position:absolute}.move-handle{background:#00f}#textInput,#textInputRef{display:none;position:absolute;z-index:10;width:200px}.shape-icon{width:20px!important;height:20px!important;color:#fff}.toolbar .btn-group button,.toolbar .dropdown-menu a{font-size:.8rem;padding:5px 10px;margin:0 2px;border-radius:4px;transition:background-color .2s}.toolbar .dropdown-menu a{background-color:transparent;color:#1b1a1a}.toolbar .btn-group button:hover,.toolbar .dropdown-menu a:hover{background-color:#e3e7eb}.toolbar .btn-group button.active{background-color:#454d55}.toolbarScreen .btn-group button,.toolbarScreen .dropdown-menu a{font-size:.8rem;padding:5px 10px;margin:0 2px;border-radius:4px;transition:background-color .2s;color:\"black\"}.toolbarScreen .btn-group button{background-color:#e3e7eb;border:none}.toolbarScreen .dropdown-menu a{background-color:transparent;color:#1b1a1a}.toolbarScreen .btn-group button:hover,.toolbarScreen .dropdown-menu a:hover{background-color:#d6d1d166;color:#000}.toolbarScreen .btn-group button.active{background-color:#454d55}#toolbarToggleScreen{background-color:#d6d1d166;border:\"1px solid black\"}#toolbar,#toolbarScreen{transition:display .3s ease-in-out}#toolbarToggle,#toolbarToggleScreen{cursor:pointer}#colorPicker,#colorPickerScreen{font-size:.8rem;padding:2px;width:32px;height:32px}#lineTypePicker{font-size:.8rem;padding:2px auto;width:32px;height:32px}.btnBoard{font-size:1rem;padding:2px;width:40px;height:40px;margin:2px}#lineTypePickerScreen{font-size:.8rem;padding:2px auto;width:32px;height:32px;background-color:#d6d1d166;color:#000}.toggle-icon{width:34px;height:34px;padding:0;margin:0}#toggleBackground.active{background-color:#fdfeff}.annotateScreenBtn{background-color:#2d2e2f!important;border:2px solid #000!important;color:green!important}\n"] }]
|
|
1809
|
-
}], propDecorators: { customWidth: [{
|
|
1810
|
-
type: Input
|
|
1811
|
-
}], customHeight: [{
|
|
1812
|
-
type: Input
|
|
1813
|
-
}], parameters: [{
|
|
1814
|
-
type: Input
|
|
1815
|
-
}], showAspect: [{
|
|
1816
|
-
type: Input
|
|
1817
|
-
}], canvasRef: [{
|
|
1818
|
-
type: ViewChild,
|
|
1819
|
-
args: ['canvasRef', { static: false }]
|
|
1820
|
-
}], textInputRef: [{
|
|
1821
|
-
type: ViewChild,
|
|
1822
|
-
args: ['textInputRef', { static: false }]
|
|
1823
|
-
}], toggleBackgroundRef: [{
|
|
1824
|
-
type: ViewChild,
|
|
1825
|
-
args: ['toggleBackgroundRef', { static: false }]
|
|
1826
|
-
}], downloadLinkRef: [{
|
|
1827
|
-
type: ViewChild,
|
|
1828
|
-
args: ['downloadLinkRef', { static: false }]
|
|
1829
|
-
}], tempCanvasRef: [{
|
|
1830
|
-
type: ViewChild,
|
|
1831
|
-
args: ['tempCanvasRef', { static: false }]
|
|
1832
|
-
}] } });
|
|
1833
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2hpdGVib2FyZC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9tZWRpYXNmdS1hbmd1bGFyL3NyYy9saWIvY29tcG9uZW50cy93aGl0ZWJvYXJkLWNvbXBvbmVudHMvd2hpdGVib2FyZC93aGl0ZWJvYXJkLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL21lZGlhc2Z1LWFuZ3VsYXIvc3JjL2xpYi9jb21wb25lbnRzL3doaXRlYm9hcmQtY29tcG9uZW50cy93aGl0ZWJvYXJkL3doaXRlYm9hcmQuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsNkRBQTZEO0FBQzdEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQTJQRztBQUNILE9BQU8sRUFDTCxTQUFTLEVBRVQsS0FBSyxFQUdMLFNBQVMsRUFDVCxpQkFBaUIsR0FHbEIsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQy9DLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUM3QyxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxrQ0FBa0MsQ0FBQztBQUNyRSxPQUFPLEVBQ0wsT0FBTyxFQUNQLE1BQU0sRUFDTixNQUFNLEVBQ04sUUFBUSxFQUNSLFFBQVEsRUFDUixjQUFjLEVB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SUFBSSxLQUFLLE1BQU0sRUFBRSxDQUFDO1lBQzFCLE9BQU8sQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLEVBQUUsS0FBSyxDQUFDLEVBQUUsRUFBRSxDQUFDLEVBQUUsS0FBSyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7WUFDM0MsT0FBTyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsRUFBRSxLQUFLLENBQUMsRUFBRSxFQUFFLENBQUMsRUFBRSxLQUFLLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQztRQUM3QyxDQUFDO2FBQU0sSUFBSSxLQUFLLENBQUMsSUFBSSxLQUFLLFFBQVEsRUFBRSxDQUFDO1lBQ25DLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsRUFBRSxHQUFHLEtBQUssQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsRUFBRSxHQUFHLEtBQUssQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUM5RixPQUFPLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEtBQUssQ0FBQyxFQUFFLEdBQUcsTUFBTSxFQUFFLENBQUMsRUFBRSxLQUFLLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQztZQUNwRCxPQUFPLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEtBQUssQ0FBQyxFQUFFLEdBQUcsTUFBTSxFQUFFLENBQUMsRUFBRSxLQUFLLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQztZQUNwRCxPQUFPLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEtBQUssQ0FBQyxFQUFFLEVBQUUsQ0FBQyxFQUFFLEtBQUssQ0FBQyxFQUFFLEdBQUcsTUFBTSxFQUFFLENBQUMsQ0FBQztZQUNwRCxPQUFPLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEtBQUssQ0FBQyxFQUFFLEVBQUUsQ0FBQyxFQUFFLEtBQUssQ0FBQyxFQUFFLEdBQUcsTUFBTSxFQUFFLENBQUMsQ0FBQztZQUNwRCxPQUFPLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEtBQUssQ0FBQyxFQUFFLEVBQUUsQ0FBQyxFQUFFLEtBQUssQ0FBQyxFQUFFLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7UUFDN0QsQ0FBQzthQUFNLElBQUksS0FBSyxDQUFDLElBQUksS0FBSyxNQUFNLEVBQUUsQ0FBQztZQUNqQyxNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLGFBQWEsQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDMUQsTUFBTSxXQUFXLEdBQUcsR0FBSSxDQUFDLFdBQVcsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDakQsT0FBTyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsRUFBRSxLQUFLLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxLQUFLLENBQUMsQ0FBQyxHQUFHLEtBQUssQ0FBQyxRQUFRLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7WUFDMUUsT0FBTyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsRUFBRSxLQUFLLENBQUMsQ0FBQyxHQUFHLFdBQVcsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7UUFDaEYsQ0FBQzthQUFNLElBQUksS0FBSyxDQUFDLElBQUksS0FBSyxPQUFPLEVBQUUsQ0FBQztZQUNsQyxPQUFPLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEtBQUssQ0FBQyxFQUFFLEVBQUUsQ0FBQyxFQUFFLEtBQUssQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1lBQzNDLE9BQU8sQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLEVBQUUsS0FBSyxDQUFDLEVBQUUsRUFBRSxDQUFDLEVBQUUsS0FBSyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7WUFDM0MsT0FBTyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsRUFBRSxLQUFLLENBQUMsRUFBRSxFQUFFLENBQUMsRUFBRSxLQUFLLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQztZQUMzQyxPQUFPLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEtBQUssQ0FBQyxFQUFFLEVBQUUsQ0FBQyxFQUFFLEtBQUssQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1lBQzNDLE9BQU8sQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxLQUFLLENBQUMsRUFBRSxHQUFHLEtBQUssQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsS0FBSyxDQUFDLEVBQUUsR0FBRyxLQUFLLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO1FBQy9GLENBQUM7YUFBTSxDQUFDO1lBQ04sT0FBTyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsRUFBRSxLQUFLLENBQUMsRUFBRSxFQUFFLENBQUMsRUFBRSxLQUFLLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQztZQUMzQyxPQUFPLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEtBQUssQ0FBQyxFQUFFLEVBQUUsQ0FBQyxFQUFFLEtBQUssQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1lBQzNDLE9BQU8sQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLEVBQUUsS0FBSyxDQUFDLEVBQUUsRUFBRSxDQUFDLEVBQUUsS0FBSyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7WUFDM0MsT0FBTyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsRUFBRSxLQUFLLENBQUMsRUFBRSxFQUFFLENBQUMsRUFBRSxLQUFLLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQztZQUMzQyxPQUFPLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsS0FBSyxDQUFDLEVBQUUsR0FBRyxLQUFLLENBQUMsRUFBRSxDQUFDLEdBQUcs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O2dCQUNHLFVBQVU7c0JBQWxCLEtBQUs7Z0JBRXFDLFNBQVM7c0JBQW5ELFNBQVM7dUJBQUMsV0FBVyxFQUFFLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRTtnQkFDSyxZQUFZO3NCQUF6RCxTQUFTO3VCQUFDLGNBQWMsRUFBRSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUU7Z0JBRTVDLG1CQUFtQjtzQkFEbEIsU0FBUzt1QkFBQyxxQkFBcUIsRUFBRSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUU7Z0JBRUYsZUFBZTtzQkFBL0QsU0FBUzt1QkFBQyxpQkFBaUIsRUFBRSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUU7Z0JBQ0EsYUFBYTtzQkFBM0QsU0FBUzt1QkFBQyxlQUFlLEVBQUUsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFIiwic291cmNlc0NvbnRlbnQiOlsiLyogZXNsaW50LWRpc2FibGUgQHR5cGVzY3JpcHQtZXNsaW50L25vLW5vbi1udWxsLWFzc2VydGlvbiAqL1xuLyoqXG4gKiBXaGl0ZWJvYXJkIGNvbXBvbmVudCBmb3IgZHJhd2luZyBhbmQgbWFuaXB1bGF0aW5nIHNoYXBlcywgdGV4dCwgYW5kIGltYWdlcyBvbiBhIGNhbnZhcy5cbiAqXG4gKiBAY29tcG9uZW50XG4gKiBAc2VsZWN0b3IgYXBwLXdoaXRlYm9hcmRcbiAqIEB0ZW1wbGF0ZVVybCAuL3doaXRlYm9hcmQuY29tcG9uZW50Lmh0bWxcbiAqIEBzdHlsZVVybHMgLi93aGl0ZWJvYXJkLmNvbXBvbmVudC5jc3NcbiAqIEBlbmNhcHN1bGF0aW9uIFZpZXdFbmNhcHN1bGF0aW9uLk5vbmVcbiAqIEBpbXBvcnRzIFtDb21tb25Nb2R1bGUsIEZvcm1zTW9kdWxlLCBGb250QXdlc29tZU1vZHVsZV1cbiAqXG4gKiBAY2xhc3MgV2hpdGVib2FyZFxuICogQGltcGxlbWVudHMgT25Jbml0LCBPbkRlc3Ryb3ksIE9uQ2hhbmdlc1xuICpcbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBjdXN0b21XaWR0aCAtIEN1c3RvbSB3aWR0aCBmb3IgdGhlIHdoaXRlYm9hcmQuXG4gKiBAcHJvcGVydHkge251bWJlcn0gY3VzdG9tSGVpZ2h0IC0gQ3VzdG9tIGhlaWdodCBmb3IgdGhlIHdoaXRlYm9hcmQuXG4gKiBAcHJvcGVydHkge1doaXRlYm9hcmRQYXJhbWV0ZXJzfSBwYXJhbWV0ZXJzIC0gUGFyYW1ldGVycyBmb3IgdGhlIHdoaXRlYm9hcmQuXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IHNob3dBc3BlY3QgLSBGbGFnIHRvIHNob3cgYXNwZWN0IHJhdGlvLlxuICpcbiAqIEBwcm9wZXJ0eSB7RWxlbWVudFJlZjxIVE1MQ2FudmFzRWxlbWVudD59IGNhbnZhc1JlZiAtIFJlZmVyZW5jZSB0byB0aGUgY2FudmFzIGVsZW1lbnQuXG4gKiBAcHJvcGVydHkge0VsZW1lbnRSZWY8SFRNTFRleHRBcmVhRWxlbWVudD59IHRleHRJbnB1dFJlZiAtIFJlZmVyZW5jZSB0byB0aGUgdGV4dCBpbnB1dCBlbGVtZW50LlxuICogQHByb3BlcnR5IHtFbGVtZW50UmVmPEhUTUxCdXR0b25FbGVtZW50Pn0gdG9nZ2xlQmFja2dyb3VuZFJlZiAtIFJlZmVyZW5jZSB0byB0aGUgdG9nZ2xlIGJhY2tncm91bmQgYnV0dG9uIGVsZW1lbnQuXG4gKiBAcHJvcGVydHkge0VsZW1lbnRSZWY8SFRNTEFuY2hvckVsZW1lbnQ+fSBkb3dubG9hZExpbmtSZWYgLSBSZWZlcmVuY2UgdG8gdGhlIGRvd25sb2FkIGxpbmsgZWxlbWVudC5cbiAqIEBwcm9wZXJ0eSB7RWxlbWVudFJlZjxIVE1MQ2FudmFzRWxlbWVudD59IHRlbXBDYW52YXNSZWYgLSBSZWZlcmVuY2UgdG8gdGhlIHRlbXBvcmFyeSBjYW52YXMgZWxlbWVudC5cbiAqXG4gKiBAcHJvcGVydHkge0ljb25EZWZpbml0aW9ufSBmYVRpbWVzIC0gRm9udEF3ZXNvbWUgaWNvbiBmb3IgdGltZXMuXG4gKiBAcHJvcGVydHkge0ljb25EZWZpbml0aW9ufSBmYVVuZG8gLSBGb250QXdlc29tZSBpY29uIGZvciB1bmRvLlxuICogQHByb3BlcnR5IHtJY29uRGVmaW5pdGlvbn0gZmFSZWRvIC0gRm9udEF3ZXNvbWUgaWNvbiBmb3IgcmVkby5cbiAqIEBwcm9wZXJ0eSB7SWNvbkRlZmluaXRpb259IGZhRXJhc2VyIC0gRm9udEF3ZXNvbWUgaWNvbiBmb3IgZXJhc2VyLlxuICogQHByb3BlcnR5IHtJY29uRGVmaW5pdGlvbn0gZmFTaGFwZXMgLSBGb250QXdlc29tZSBpY29uIGZvciBzaGFwZXMuXG4gKiBAcHJvcGVydHkge0ljb25EZWZpbml0aW9ufSBmYU1vdXNlUG9pbnRlciAtIEZvbnRBd2Vzb21lIGljb24gZm9yIG1vdXNlIHBvaW50ZXIuXG4gKiBAcHJvcGVydHkge0ljb25EZWZpbml0aW9ufSBmYUhhbmRQYXBlciAtIEZvbnRBd2Vzb21lIGljb24gZm9yIGhhbmQgcGFwZXIuXG4gKiBAcHJvcGVydHkge0ljb25EZWZpbml0aW9ufSBmYVRleHRIZWlnaHQgLSBGb250QXdlc29tZSBpY29uIGZvciB0ZXh0IGhlaWdodC5cbiAqIEBwcm9wZXJ0eSB7SWNvbkRlZmluaXRpb259IGZhRm9udCAtIEZvbnRBd2Vzb21lIGljb24gZm9yIGZvbnQuXG4gKiBAcHJvcGVydHkge0ljb25EZWZpbml0aW9ufSBmYVBlbmNpbEFsdCAtIEZvbnRBd2Vzb21lIGljb24gZm9yIHBlbmNpbCBhbHQuXG4gKiBAcHJvcGVydHkge0ljb25EZWZpbml0aW9ufSBmYVBhaW50QnJ1c2ggLSBGb250QXdlc29tZSBpY29uIGZvciBwYWludCBicnVzaC5cbiAqIEBwcm9wZXJ0eSB7SWNvbkRlZmluaXRpb259IGZhVHJhc2ggLSBGb250QXdlc29tZSBpY29uIGZvciB0cmFzaC5cbiAqIEBwcm9wZXJ0eSB7SWNvbkRlZmluaXRpb259IGZhU2F2ZSAtIEZvbnRBd2Vzb21lIGljb24gZm9yIHNhdmUuXG4gKiBAcHJvcGVydHkge0ljb25EZWZpbml0aW9ufSBmYVNlYXJjaCAtIEZvbnRBd2Vzb21lIGljb24gZm9yIHNlYXJjaC5cbiAqIEBwcm9wZXJ0eSB7SWNvbkRlZmluaXRpb259IGZhU2VhcmNoTWludXMgLSBGb250QXdlc29tZSBpY29uIGZvciBzZWFyY2ggbWludXMuXG4gKiBAcHJvcGVydHkge0ljb25EZWZpbml0aW9ufSBmYVNlYXJjaFBsdXMgLSBGb250QXdlc29tZSBpY29uIGZvciBzZWFyY2ggcGx1cy5cbiAqIEBwcm9wZXJ0eSB7SWNvbkRlZmluaXRpb259IGZhQ2hldnJvbkxlZnQgLSBGb250QXdlc29tZSBpY29uIGZvciBjaGV2cm9uIGxlZnQuXG4gKiBAcHJvcGVydHkge0ljb25EZWZpbml0aW9ufSBmYVVwbG9hZCAtIEZvbnRBd2Vzb21lIGljb24gZm9yIHVwbG9hZC5cbiAqIEBwcm9wZXJ0eSB7SWNvbkRlZmluaXRpb259IGZhQ2hldnJvblJpZ2h0IC0gRm9udEF3ZXNvbWUgaWNvbiBmb3IgY2hldnJvbiByaWdodC5cbiAqXG4gKiBAcHJvcGVydHkge3N0cmluZ30gbW9kZSAtIEN1cnJlbnQgbW9kZSBvZiB0aGUgd2hpdGVib2FyZCAoZS5nLiwgJ3BhbicsICdkcmF3JywgJ2VyYXNlJykuXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IGlzRHJhd2luZyAtIEZsYWcgaW5kaWNhdGluZyBpZiBkcmF3aW5nIGlzIGluIHByb2dyZXNzLlxuICogQHByb3BlcnR5IHtib29sZWFufSBpc1Bhbm5pbmcgLSBGbGFnIGluZGljYXRpbmcgaWYgcGFubmluZyBpcyBpbiBwcm9ncmVzcy5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gaXNEcmFnZ2luZyAtIEZsYWcgaW5kaWNhdGluZyBpZiBkcmFnZ2luZyBpcyBpbiBwcm9ncmVzcy5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBzdGFydFggLSBTdGFydGluZyBYIGNvb3JkaW5hdGUgZm9yIGRyYXdpbmcuXG4gKiBAcHJvcGVydHkge251bWJlcn0gc3RhcnRZIC0gU3RhcnRpbmcgWSBjb29yZGluYXRlIGZvciBkcmF3aW5nLlxuICogQHByb3BlcnR5IHtudW1iZXJ9IGN1cnJlbnRYIC0gQ3VycmVudCBYIGNvb3JkaW5hdGUgZm9yIGRyYXdpbmcuXG4gKiBAcHJvcGVydHkge251bWJlcn0gY3VycmVudFkgLSBDdXJyZW50IFkgY29vcmRpbmF0ZSBmb3IgZHJhd2luZy5cbiAqIEBwcm9wZXJ0eSB7YW55W119IGZyZWVoYW5kRHJhd2luZyAtIEFycmF5IG9mIHBvaW50cyBmb3IgZnJlZWhhbmQgZHJhd2luZy5cbiAqIEBwcm9wZXJ0eSB7YW55fSBzZWxlY3RlZFNoYXBlIC0gQ3VycmVudGx5IHNlbGVjdGVkIHNoYXBlLlxuICogQHByb3BlcnR5IHthbnl9IHNlbGVjdGVkSGFuZGxlIC0gQ3VycmVudGx5IHNlbGVjdGVkIGhhbmRsZSBmb3IgcmVzaXppbmcgc2hhcGVzLlxuICogQHByb3BlcnR5IHtib29sZWFufSBtb3ZpbmdTaGFwZSAtIEZsYWcgaW5kaWNhdGluZyBpZiBhIHNoYXBlIGlzIGJlaW5nIG1vdmVkLlxuICogQHByb3BlcnR5IHtudW1iZXJ9IHBhblggLSBYIGNvb3JkaW5hdGUgZm9yIHBhbm5pbmcuXG4gKiBAcHJvcGVydHkge251bWJlcn0gcGFuWSAtIFkgY29vcmRpbmF0ZSBmb3IgcGFubmluZy5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBzY2FsZSAtIEN1cnJlbnQgc2NhbGUgb2YgdGhlIGNhbnZhcy5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBtaW5TY2FsZSAtIE1pbmltdW0gc2NhbGUgb2YgdGhlIGNhbnZhcy5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBtYXhTY2FsZSAtIE1heGltdW0gc2NhbGUgb2YgdGhlIGNhbnZhcy5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBlcmFzZXJUaGlja25lc3MgLSBUaGlja25lc3Mgb2YgdGhlIGVyYXNlci5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBicnVzaFRoaWNrbmVzcyAtIFRoaWNrbmVzcyBvZiB0aGUgYnJ1c2guXG4gKiBAcHJvcGVydHkge251bWJlcn0gbGluZVRoaWNrbmVzcyAtIFRoaWNrbmVzcyBvZiB0aGUgbGluZS5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBsaW5lVHlwZSAtIFR5cGUgb2YgdGhlIGxpbmUgKGUuZy4sICdzb2xpZCcsICdkYXNoZWQnKS5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBjb2xvciAtIEN1cnJlbnQgY29sb3IgZm9yIGRyYXdpbmcuXG4gKiBAcHJvcGVydHkge3N0cmluZ30gZm9udCAtIEN1cnJlbnQgZm9udCBmb3IgdGV4dC5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBmb250U2l6ZSAtIEN1cnJlbnQgZm9udCBzaXplIGZvciB0ZXh0LlxuICogQHByb3BlcnR5IHthbnl9IHNoYXBlIC0gQ3VycmVudCBzaGFwZSBiZWluZyBkcmF3bi5cbiAqIEBwcm9wZXJ0eSB7SFRNTEltYWdlRWxlbWVudH0gYmFja2dyb3VuZEltYWdlIC0gQmFja2dyb3VuZCBpbWFnZSBmb3IgdGhlIGNhbnZhcy5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gdG9vbGJhclZpc2libGUgLSBGbGFnIGluZGljYXRpbmcgaWYgdGhlIHRvb2xiYXIgaXMgdmlzaWJsZS5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nIHwgbnVsbH0gZHJvcGRvd25PcGVuIC0gQ3VycmVudGx5IG9wZW4gZHJvcGRvd24gbWVudS5cbiAqIEBwcm9wZXJ0eSB7eyBjbGllbnRYOiBudW1iZXIsIGNsaWVudFk6IG51bWJlciwgb2Zmc2V0WDogbnVtYmVyLCBvZmZzZXRZOiBudW1iZXIgfSB8IG51bGx9IGN1cnJlbnRDbGlja1Bvc2l0aW9uIC0gQ3VycmVudCBjbGljayBwb3NpdGlvbiBvbiB0aGUgY2FudmFzLlxuICogQHByb3BlcnR5IHtudW1iZXJ9IG1heFdpZHRoIC0gTWF4aW11bSB3aWR0aCBvZiB0aGUgY2FudmFzLlxuICogQHByb3BlcnR5IHtudW1iZXJ9IG1heEhlaWdodCAtIE1heGltdW0gaGVpZ2h0IG9mIHRoZSBjYW52YXMuXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IGRpbWVuc2lvbnNGaXhlZCAtIEZsYWcgaW5kaWNhdGluZyBpZiB0aGUgY2FudmFzIGRpbWVuc2lvbnMgYXJlIGZpeGVkLlxuICpcbiAqIEBtZXRob2QgdXBkYXRlTGluZVRoaWNrbmVzcyAtIFVwZGF0ZXMgdGhlIHRoaWNrbmVzcyBvZiB0aGUgbGluZS5cbiAqIEBwYXJhbSB7bnVtYmVyfSB0aGlja25lc3MgLSBOZXcgdGhpY2tuZXNzIGZvciB0aGUgbGluZS5cbiAqXG4gKiBAbWV0aG9kIHVwZGF0ZUJydXNoVGhpY2tuZXNzIC0gVXBkYXRlcyB0aGUgdGhpY2tuZXNzIG9mIHRoZSBicnVzaC5cbiAqIEBwYXJhbSB7bnVtYmVyfSB0aGlja25lc3MgLSBOZXcgdGhpY2tuZXNzIGZvciB0aGUgYnJ1c2guXG4gKlxuICogQG1ldGhvZCB1cGRhdGVFcmFzZXJUaGlja25lc3MgLSBVcGRhdGVzIHRoZSB0aGlja25lc3Mgb2YgdGhlIGVyYXNlci5cbiAqIEBwYXJhbSB7bnVtYmVyfSB0aGlja25lc3MgLSBOZXcgdGhpY2tuZXNzIGZvciB0aGUgZXJhc2VyLlxuICpcbiAqIEBtZXRob2QgdXBkYXRlQ29sb3IgLSBVcGRhdGVzIHRoZSBjb2xvciBmb3IgZHJhd2luZy5cbiAqIEBwYXJhbSB7c3RyaW5nfSBjb2xvciAtIE5ldyBjb2xvciBmb3IgZHJhd2luZy5cbiAqXG4gKiBAbWV0aG9kIHVwZGF0ZUZvbnQgLSBVcGRhdGVzIHRoZSBmb250IGZvciB0ZXh0LlxuICogQHBhcmFtIHtzdHJpbmd9IGZvbnQgLSBOZXcgZm9udCBmb3IgdGV4dC5cbiAqXG4gKiBAbWV0aG9kIHVwZGF0ZUZvbnRTaXplIC0gVXBkYXRlcyB0aGUgZm9udCBzaXplIGZvciB0ZXh0LlxuICogQHBhcmFtIHtudW1iZXJ9IGZvbnRTaXplIC0gTmV3IGZvbnQgc2l6ZSBmb3IgdGV4dC5cbiAqXG4gKiBAbWV0aG9kIHVwZGF0ZVNoYXBlIC0gVXBkYXRlcyB0aGUgc2hhcGUgYmVpbmcgZHJhd24uXG4gKiBAcGFyYW0ge3N0cmluZ30gc2hhcGUgLSBOZXcgc2hhcGUgdG8gYmUgZHJhd24uXG4gKlxuICogQGNvbnN0cnVjdG9yXG4gKlxuICogQG1ldGhvZCBuZ09uSW5pdCAtIExpZmVjeWNsZSBob29rIHRoYXQgaXMgY2FsbGVkIGFmdGVyIGRhdGEtYm91bmQgcHJvcGVydGllcyBhcmUgaW5pdGlhbGl6ZWQuXG4gKlxuICogQG1ldGhvZCBuZ09uQ2hhbmdlcyAtIExpZmVjeWNsZSBob29rIHRoYXQgaXMgY2FsbGVkIHdoZW4gYW55IGRhdGEtYm91bmQgcHJvcGVydHkgb2YgYSBkaXJlY3RpdmUgY2hhbmdlcy5cbiAqIEBwYXJhbSB7U2ltcGxlQ2hhbmdlc30gY2hhbmdlcyAtIE9iamVjdCBvZiBjaGFuZ2VzLlxuICpcbiAqIEBtZXRob2QgbmdPbkRlc3Ryb3kgLSBMaWZlY3ljbGUgaG9vayB0aGF0IGlzIGNhbGxlZCB3aGVuIGEgZGlyZWN0aXZlLCBwaXBlLCBvciBzZXJ2aWNlIGlzIGRlc3Ryb3llZC5cbiAqXG4gKiBAbWV0aG9kIG5nQWZ0ZXJWaWV3SW5pdCAtIExpZmVjeWNsZSBob29rIHRoYXQgaXMgY2FsbGVkIGFmdGVyIGEgY29tcG9uZW50J3MgdmlldyBoYXMgYmVlbiBmdWxseSBpbml0aWFsaXplZC5cbiAqXG4gKiBAbWV0aG9kIGhhbmRsZVRleHRJbnB1dCAtIEhhbmRsZXMgdGhlIHRleHQgaW5wdXQgZXZlbnQuXG4gKiBAcGFyYW0ge0tleWJvYXJkRXZlbnR9IGV2ZW50IC0gS2V5Ym9hcmQgZXZlbnQuXG4gKlxuICogQG1ldGhvZCBhZGRMaXN0ZW5lcnMgLSBBZGRzIGV2ZW50IGxpc3RlbmVycyB0byB0aGUgY2FudmFzIGFuZCBkb2N1bWVudC5cbiAqXG4gKiBAbWV0aG9kIGhhbmRsZVRvdWNoU3RhcnQgLSBIYW5kbGVzIHRoZSB0b3VjaCBzdGFydCBldmVudC5cbiAqIEBwYXJhbSB7VG91Y2hFdmVudH0gZSAtIFRvdWNoIGV2ZW50LlxuICpcbiAqIEBtZXRob2QgaGFuZGxlVG91Y2hNb3ZlIC0gSGFuZGxlcyB0aGUgdG91Y2ggbW92ZSBldmVudC5cbiAqIEBwYXJhbSB7VG91Y2hFdmVudH0gZSAtIFRvdWNoIGV2ZW50LlxuICpcbiAqIEBtZXRob2QgaGFuZGxlVG91Y2hFbmQgLSBIYW5kbGVzIHRoZSB0b3VjaCBlbmQgZXZlbnQuXG4gKiBAcGFyYW0ge1RvdWNoRXZlbnR9IGUgLSBUb3VjaCBldmVudC5cbiAqXG4gKiBAbWV0aG9kIGhhbmRsZUNsaWNrT3V0c2lkZSAtIEhhbmRsZXMgdGhlIGNsaWNrIG91dHNpZGUgZXZlbnQuXG4gKiBAcGFyYW0ge01vdXNlRXZlbnR9IGV2ZW50IC0gTW91c2UgZXZlbnQuXG4gKlxuICogQG1ldGhvZCBoYW5kbGVDYW52YXNDbGljayAtIEhhbmRsZXMgdGhlIGNhbnZhcyBjbGljayBldmVudC5cbiAqIEBwYXJhbSB7TW91c2VFdmVudH0gZSAtIE1vdXNlIGV2ZW50LlxuICpcbiAqIEBtZXRob2Qgc3RhcnREcmF3aW5nIC0gU3RhcnRzIHRoZSBkcmF3aW5nIHByb2Nlc3MuXG4gKiBAcGFyYW0ge01vdXNlRXZlbnR9IGUgLSBNb3VzZSBldmVudC5cbiAqXG4gKiBAbWV0aG9kIGRyYXcgLSBEcmF3cyBvbiB0aGUgY2FudmFzLlxuICogQHBhcmFtIHtNb3VzZUV2ZW50fSBlIC0gTW91c2UgZXZlbnQuXG4gKlxuICogQG1ldGhvZCBzdG9wRHJhd2luZyAtIFN0b3BzIHRoZSBkcmF3aW5nIHByb2Nlc3MuXG4gKiBAcGFyYW0ge01vdXNlRXZlbnR9IGUgLSBNb3VzZSBldmVudC5cbiAqXG4gKiBAbWV0aG9kIGVyYXNlIC0gRXJhc2VzIGEgcGFydCBvZiB0aGUgY2FudmFzLlxuICogQHBhcmFtIHtudW1iZXJ9IHggLSBYIGNvb3JkaW5hdGUuXG4gKiBAcGFyYW0ge251bWJlcn0geSAtIFkgY29vcmRpbmF0ZS5cbiAqXG4gKiBAbWV0aG9kIGlzUG9pbnROZWFyTGluZSAtIENoZWNrcyBpZiBhIHBvaW50IGlzIG5lYXIgYSBsaW5lLlxuICogQHBhcmFtIHtudW1iZXJ9IHB4IC0gWCBjb29yZGluYXRlIG9mIHRoZSBwb2ludC5cbiAqIEBwYXJhbSB7bnVtYmVyfSBweSAtIFkgY29vcmRpbmF0ZSBvZiB0aGUgcG9pbnQuXG4gKiBAcGFyYW0ge251bWJlcn0geDEgLSBYIGNvb3JkaW5hdGUgb2YgdGhlIGxpbmUgc3RhcnQuXG4gKiBAcGFyYW0ge251bWJlcn0geTEgLSBZIGNvb3JkaW5hdGUgb2YgdGhlIGxpbmUgc3RhcnQuXG4gKiBAcGFyYW0ge251bWJlcn0geDIgLSBYIGNvb3JkaW5hdGUgb2YgdGhlIGxpbmUgZW5kLlxuICogQHBhcmFtIHtudW1iZXJ9IHkyIC0gWSBjb29yZGluYXRlIG9mIHRoZSBsaW5lIGVuZC5cbiAqIEBwYXJhbSB7bnVtYmVyfSB0aHJlc2hvbGQgLSBEaXN0YW5jZSB0aHJlc2hvbGQuXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gLSBUcnVlIGlmIHRoZSBwb2ludCBpcyBuZWFyIHRoZSBsaW5lLCBmYWxzZSBvdGhlcndpc2UuXG4gKlxuICogQG1ldGhvZCB6b29tQ2FudmFzIC0gWm9vbXMgdGhlIGNhbnZhcy5cbiAqIEBwYXJhbSB7bnVtYmVyfSBzY2FsZUZhY3RvciAtIFNjYWxlIGZhY3RvciBmb3Igem9vbWluZy5cbiAqIEBwYXJhbSB7TW91c2VFdmVudH0gW2V2ZW50XSAtIE1vdXNlIGV2ZW50LlxuICpcbiAqIEBtZXRob2QgaGFuZGxlWm9vbSAtIEhhbmRsZXMgdGhlIHpvb20gZXZlbnQuXG4gKiBAcGFyYW0ge1doZWVsRXZlbnR9IGUgLSBXaGVlbCBldmVudC5cbiAqXG4gKiBAbWV0aG9kIGRyYXdFZGdlTWFya2VycyAtIERyYXdzIGVkZ2UgbWFya2VycyBvbiB0aGUgY2FudmFzLlxuICpcbiAqIEBtZXRob2QgZHJhd1NoYXBlcyAtIERyYXdzIGFsbCBzaGFwZXMgb24gdGhlIGNhbnZhcy5cbiAqXG4gKiBAbWV0aG9kIGRyYXdMaW5lIC0gRHJhd3MgYSBsaW5lIG9uIHRoZSBjYW52YXMuXG4gKiBAcGFyYW0ge251bWJlcn0geDEgLSBYIGNvb3JkaW5hdGUgb2YgdGhlIGxpbmUgc3RhcnQuXG4gKiBAcGFyYW0ge251bWJlcn0geTEgLSBZIGNvb3JkaW5hdGUgb2YgdGhlIGxpbmUgc3RhcnQuXG4gKiBAcGFyYW0ge251bWJlcn0geDIgLSBYIGNvb3JkaW5hdGUgb2YgdGhlIGxpbmUgZW5kLlxuICogQHBhcmFtIHtudW1iZXJ9IHkyIC0gWSBjb29yZGluYXRlIG9mIHRoZSBsaW5lIGVuZC5cbiAqIEBwYXJhbSB7c3RyaW5nfSBjb2xvciAtIENvbG9yIG9mIHRoZSBsaW5lLlxuICogQHBhcmFtIHtudW1iZXJ9IHRoaWNrbmVzcyAtIFRoaWNrbmVzcyBvZiB0aGUgbGluZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBsaW5lVHlwZSAtIFR5cGUgb2YgdGhlIGxpbmUgKGUuZy4sICdzb2xpZCcsICdkYXNoZWQnKS5cbiAqXG4gKiBAbWV0aG9kIGRyYXdUZXh0IC0gRHJhd3MgdGV4dCBvbiB0aGUgY2FudmFzLlxuICogQHBhcmFtIHtzdHJpbmd9IHRleHQgLSBUZXh0IHRvIGJlIGRyYXduLlxuICogQHBhcmFtIHtudW1iZXJ9IHggLSBYIGNvb3JkaW5hdGUgb2YgdGhlIHRleHQuXG4gKiBAcGFyYW0ge251bWJlcn0geSAtIFkgY29vcmRpbmF0ZSBvZiB0aGUgdGV4dC5cbiAqIEBwYXJhbSB7c3RyaW5nfSBjb2xvciAtIENvbG9yIG9mIHRoZSB0ZXh0LlxuICogQHBhcmFtIHtzdHJpbmd9IGZvbnQgLSBGb250IG9mIHRoZSB0ZXh0LlxuICpcbiAqIEBtZXRob2QgZHJhd0ZyZWVoYW5kIC0gRHJhd3MgZnJlZWhhbmQgbGluZXMgb24gdGhlIGNhbnZhcy5cbiAqIEBwYXJhbSB7eyB4OiBudW1iZXIsIHk6IG51bWJlciB9W119IHBvaW50cyAtIEFycmF5IG9mIHBvaW50cyBmb3IgZnJlZWhhbmQgZHJhd2luZy5cbiAqIEBwYXJhbSB7c3RyaW5nfSBjb2xvciAtIENvbG9yIG9mIHRoZSBmcmVlaGFuZCBkcmF3aW5nLlxuICogQHBhcmFtIHtudW1iZXJ9IHRoaWNrbmVzcyAtIFRoaWNrbmVzcyBvZiB0aGUgZnJlZWhhbmQgZHJhd2luZy5cbiAqXG4gKiBAbWV0aG9kIGRyYXdTaGFwZSAtIERyYXdzIGEgc2hhcGUgb24gdGhlIGNhbnZhcy5cbiAqIEBwYXJhbSB7c3RyaW5nfSB0eXBlIC0gVHlwZSBvZiB0aGUgc2hhcGUuXG4gKiBAcGFyYW0ge251bWJlcn0geDEgLSBYIGNvb3JkaW5hdGUgb2YgdGhlIHNoYXBlIHN0YXJ0LlxuICogQHBhcmFtIHtudW1iZXJ9IHkxIC0gWSBjb29yZGluYXRlIG9mIHRoZSBzaGFwZSBzdGFydC5cbiAqIEBwYXJhbSB7bnVtYmVyfSB4MiAtIFggY29vcmRpbmF0ZSBvZiB0aGUgc2hhcGUgZW5kLlxuICogQHBhcmFtIHtudW1iZXJ9IHkyIC0gWSBjb29yZGluYXRlIG9mIHRoZSBzaGFwZSBlbmQuXG4gKiBAcGFyYW0ge3N0cmluZ30gY29sb3IgLSBDb2xvciBvZiB0aGUgc2hhcGUuXG4gKiBAcGFyYW0ge251bWJlcn0gdGhpY2tuZXNzIC0gVGhpY2tuZXNzIG9mIHRoZSBzaGFwZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBsaW5lVHlwZSAtIFR5cGUgb2YgdGhlIGxpbmUgKGUuZy4sICdzb2xpZCcsICdkYXNoZWQnKS5cbiAqIEBwYXJhbSB7Q2FudmFzUmVuZGVyaW5nQ29udGV4dDJEfSBbY3R4XSAtIENhbnZhcyByZW5kZXJpbmcgY29udGV4dC5cbiAqXG4gKiBAbWV0aG9kIGRyYXdQb2x5Z29uIC0gRHJhd3MgYSBwb2x5Z29uIG9uIHRoZSBjYW52YXMuXG4gKiBAcGFyYW0ge0NhbnZhc1JlbmRlcmluZ0NvbnRleHQyRH0gY3R4IC0gQ2FudmFzIHJlbmRlcmluZyBjb250ZXh0LlxuICogQHBhcmFtIHtudW1iZXJ9IHNpZGVzIC0gTnVtYmVyIG9mIHNpZGVzIG9mIHRoZSBwb2x5Z29uLlxuICogQHBhcmFtIHtudW1iZXJ9IHgxIC0gWCBjb29yZGluYXRlIG9mIHRoZSBwb2x5Z29uIHN0YXJ0LlxuICogQHBhcmFtIHtudW1iZXJ9IHkxIC0gWSBjb29yZGluYXRlIG9mIHRoZSBwb2x5Z29uIHN0YXJ0LlxuICogQHBhcmFtIHtudW1iZXJ9IHgyIC0gWCBjb29yZGluYXRlIG9mIHRoZSBwb2x5Z29uIGVuZC5cbiAqIEBwYXJhbSB7bnVtYmVyfSB5MiAtIFkgY29vcmRpbmF0ZSBvZiB0aGUgcG9seWdvbiBlbmQuXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYGh0bWxcbiAqIDxhcHAtd2hpdGVib2FyZFxuICogIFtjdXN0b21XaWR0aF09XCIxMjgwXCJcbiAqIFtjdXN0b21IZWlnaHRdPVwiNzIwXCJcbiAqIFtwYXJhbWV0ZXJzXT1cIntcbiAqICBzb2NrZXQ6IHNvY2tldCxcbiAqIHNob3dBbGVydDogc2hvd0FsZXJ0LFxuICogaXNsZXZlbDogaXNsZXZlbCxcbiAqIHJvb21OYW1lOiByb29tTmFtZSxcbiAqIHNoYXBlczogc2hhcGVzLFxuICogdXNlSW1hZ2VCYWNrZ3JvdW5kOiB1c2VJbWFnZUJhY2tncm91bmQsXG4gKiByZWRvU3RhY2s6IHJlZG9TdGFjayxcbiAqIHVuZG9TdGFjazogdW5kb1N0YWNrLFxuICogd2hpdGVib2FyZFN0YXJ0ZWQ6IHdoaXRlYm9hcmRTdGFydGVkLFxuICogd2hpdGVib2FyZEVuZGVkOiB3aGl0ZWJvYXJkRW5kZWQsXG4gKiB3aGl0ZWJvYXJkVXNlcnM6IHdoaXRlYm9hcmRVc2VycyxcbiAqIHBhcnRpY2lwYW50czogcGFydGljaXBhbnRzLFxuICogcGFydGljaXBhbnRzQWxsOiBwYXJ0aWNpcGFudHNBbGwsXG4gKiBzY3JlZW5JZDogc2NyZWVuSWQsXG4gKiByZWNvcmRTdGFydGVkOiByZWNvcmRTdGFydGVkLFxuICogcmVjb3JkU3RvcHBlZDogcmVjb3JkU3RvcHBlZCxcbiAqIHJlY29yZFBhdXNlZDogcmVjb3JkUGF1c2VkLFxuICogcmVjb3JkUmVzdW1lZDogcmVjb3JkUmVzdW1lZCxcbiAqIHJlY29yZGluZ01lZGlhT3B0aW9uczogcmVjb3JkaW5nTWVkaWFPcHRpb25zLFxuICogbWVtYmVyOiBtZW1iZXIsXG4gKiBzaGFyZVNjcmVlblN0YXJ0ZWQ6IHNoYXJlU2NyZWVuU3RhcnRlZCxcbiAqIGNhbnZhc1doaXRlYm9hcmQ6IGNhbnZhc1doaXRlYm9hcmQsXG4gKiB0YXJnZXRSZXNvbHV0aW9uOiB0YXJnZXRSZXNvbHV0aW9uLFxuICogdGFyZ2V0UmVzb2x1dGlvbkhvc3Q6IHRhcmdldFJlc29sdXRpb25Ib3N0LFxuICogdXBkYXRlU2hhcGVzOiB1cGRhdGVTaGFwZXMsXG4gKiB1cGRhdGVVc2VJbWFnZUJhY2tncm91bmQ6IHVwZGF0ZVVzZUltYWdlQmFja2dyb3VuZCxcbiAqIHVwZGF0ZVJlZG9TdGFjazogdXBkYXRlUmVkb1N0YWNrLFxuICogdXBkYXRlVW5kb1N0YWNrOiB1cGRhdGVVbmRvU3RhY2ssXG4gKiB1cGRhdGVXaGl0ZWJvYXJkU3RhcnRlZDogdXBkYXRlV2hpdGVib2FyZFN0YXJ0ZWQsXG4gKiB1cGRhdGVXaGl0ZWJvYXJkRW5kZWQ6IHVwZGF0ZVdoaXRlYm9hcmRFbmRlZCxcbiAqIHVwZGF0ZVdoaXRlYm9hcmRVc2VyczogdXBkYXRlV2hpdGVib2FyZFVzZXJzLFxuICogdXBkYXRlUGFydGljaXBhbnRzOiB1cGRhdGVQYXJ0aWNpcGFudHMsXG4gKiB1cGRhdGVTY3JlZW5JZDogdXBkYXRlU2NyZWVuSWQsXG4gKiB1cGRhdGVTaGFyZVNjcmVlblN0YXJ0ZWQ6IHVwZGF0ZVNoYXJlU2NyZWVuU3RhcnRlZCxcbiAqIHVwZGF0ZUNhbnZhc1doaXRlYm9hcmQ6IHVwZGF0ZUNhbnZhc1doaXRlYm9hcmQsXG4gKiBvblNjcmVlbkNoYW5nZXM6IG9uU2NyZWVuQ2hhbmdlcyxcbiAqIGNhcHR1cmVDYW52YXNTdHJlYW06IGNhcHR1cmVDYW52YXNTdHJlYW0sXG4gKiBnZXRVcGRhdGVkQWxsUGFyYW1zOiBnZXRVcGRhdGVkQWxsUGFyYW1zXG4gKiB9XCJcbiAqIFtzaG93QXNwZWN0XT1cInRydWVcIlxuICogPjwvYXBwLXdoaXRlYm9hcmQ+XG4gKiBgYGBcbiAqL1xuaW1wb3J0IHtcbiAgQ29tcG9uZW50LFxuICBFbGVtZW50UmVmLFxuICBJbnB1dCxcbiAgT25EZXN0cm95LFxuICBPbkluaXQsXG4gIFZpZXdDaGlsZCxcbiAgVmlld0VuY2Fwc3VsYXRpb24sXG4gIE9uQ2hhbmdlcyxcbiAgU2ltcGxlQ2hhbmdlcyxcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBDb21tb25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHsgRm9ybXNNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgeyBGb250QXdlc29tZU1vZHVsZSB9IGZyb20gJ0Bmb3J0YXdlc29tZS9hbmd1bGFyLWZvbnRhd2Vzb21lJztcbmltcG9ydCB7XG4gIGZhVGltZXMsXG4gIGZhVW5kbyxcbiAgZmFSZWRvLFxuICBmYUVyYXNlcixcbiAgZmFTaGFwZXMsXG4gIGZhTW91c2VQb2ludGVyLFxuICBmYUhhbmRQYXBlcixcbiAgZmFUZXh0SGVpZ2h0LFxuICBmYUZvbnQsXG4gIGZhUGVuY2lsQWx0LFxuICBmYVBhaW50QnJ1c2gsXG4gIGZhVHJhc2gsXG4gIGZhU2F2ZSxcbiAgZmFTZWFyY2gsXG4gIGZhU2VhcmNoTWludXMsXG4gIGZhU2VhcmNoUGx1cyxcbiAgZmFDaGV2cm9uTGVmdCxcbiAgZmFVcGxvYWQsXG4gIGZhQ2hldnJvblJpZ2h0LFxufSBmcm9tICdAZm9ydGF3ZXNvbWUvZnJlZS1zb2xpZC1zdmctaWNvbnMnO1xuaW1wb3J0IHsgU29ja2V0IH0gZnJvbSAnc29ja2V0LmlvLWNsaWVudCc7XG5pbXBvcnQge1xuICBPblNjcmVlbkNoYW5nZXNQYXJhbWV0ZXJzLFxuICBPblNjcmVlbkNoYW5nZXNUeXBlLFxufSBmcm9tICcuLi8uLi8uLi9jb25zdW1lcnMvb24tc2NyZWVuLWNoYW5nZXMuc2VydmljZSc7XG5pbXBvcnQge1xuICBDYXB0dXJlQ2FudmFzU3RyZWFtUGFyYW1ldGVycyxcbiAgU2hvd0FsZXJ0LFxuICBXaGl0ZWJvYXJkVXNlcixcbiAgUGFydGljaXBhbnQsXG4gIENhcHR1cmVDYW52YXNTdHJlYW1UeXBlLFxufSBmcm9tICcuLi8uLi8uLi9AdHlwZXMvdHlwZXMnO1xuXG5leHBvcnQgaW50ZXJmYWNlIFNoYXBlIHtcbiAgdHlwZTogc3RyaW5nO1xuICB4PzogbnVtYmVyO1xuICB5PzogbnVtYmVyO1xuICB4MT86IG51bWJlcjtcbiAgeTE/OiBudW1iZXI7XG4gIHgyPzogbnVtYmVyO1xuICB5Mj86IG51bWJlcjtcbiAgdGV4dD86IHN0cmluZztcbiAgY29sb3I/OiBzdHJpbmc7XG4gIGZvbnQ/OiBzdHJpbmc7XG4gIGZvbnRTaXplPzogbnVtYmVyO1xuICB0aGlja25lc3M/OiBudW1iZXI7XG4gIGxpbmVUeXBlPzogc3RyaW5nO1xuICBwb2ludHM/OiBBcnJheTx7IHg6IG51bWJlcjsgeTogbnVtYmVyIH0+O1xuICBpbWc/OiBIVE1MSW1hZ2VFbGVtZW50O1xuICBzcmM/OiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgV2hpdGVib2FyZFBhcmFtZXRlcnNcbiAgZXh0ZW5kcyBPblNjcmVlbkNoYW5nZXNQYXJhbWV0ZXJzLFxuICAgIENhcHR1cmVDYW52YXNTdHJlYW1QYXJhbWV0ZXJzIHtcbiAgc29ja2V0OiBTb2NrZXQ7XG4gIHNob3dBbGVydD86IFNob3dBbGVydDtcbiAgaXNsZXZlbDogc3RyaW5nO1xuICByb29tTmFtZTogc3RyaW5nO1xuICBzaGFwZXM6IFNoYXBlW107XG4gIHVzZUltYWdlQmFja2dyb3VuZDogYm9vbGVhbjtcbiAgcmVkb1N0YWNrOiBTaGFwZVtdO1xuICB1bmRvU3RhY2s6IHN0cmluZ1tdO1xuICB3aGl0ZWJvYXJkU3RhcnRlZDogYm9vbGVhbjtcbiAgd2hpdGVib2FyZEVuZGVkOiBib29sZWFuO1xuICB3aGl0ZWJvYXJkVXNlcnM6IFdoaXRlYm9hcmRVc2VyW107XG4gIHBhcnRpY2lwYW50czogUGFydGljaXBhbnRbXTtcbiAgcGFydGljaXBhbnRzQWxsOiBQYXJ0aWNpcGFudFtdO1xuICBzY3JlZW5JZDogc3RyaW5nO1xuICByZWNvcmRTdGFydGVkOiBib29sZWFuO1xuICByZWNvcmRTdG9wcGVkOiBib29sZWFuO1xuICByZWNvcmRQYXVzZWQ6IGJvb2xlYW47XG4gIHJlY29yZFJlc3VtZWQ6IGJvb2xlYW47XG4gIHJlY29yZGluZ01lZGlhT3B0aW9uczogc3RyaW5nO1xuICBtZW1iZXI6IHN0cmluZztcbiAgc2hhcmVTY3JlZW5TdGFydGVkOiBib29sZWFuO1xuICBjYW52YXNXaGl0ZWJvYXJkOiBIVE1MQ2FudmFzRWxlbWVudCB8IG51bGw7XG4gIHRhcmdldFJlc29sdXRpb24/OiBzdHJpbmc7XG4gIHRhcmdldFJlc29sdXRpb25Ib3N0Pzogc3RyaW5nO1xuXG4gIHVwZGF0ZVNoYXBlczogKHNoYXBlczogU2hhcGVbXSkgPT4gdm9pZDtcbiAgdXBkYXRlVXNlSW1hZ2VCYWNrZ3JvdW5kOiAodXNlSW1hZ2VCYWNrZ3JvdW5kOiBib29sZWFuKSA9PiB2b2lkO1xuICB1cGRhdGVSZWRvU3RhY2s6IChyZWRvU3RhY2s6IFNoYXBlW10pID0+IHZvaWQ7XG4gIHVwZGF0ZVVuZG9TdGFjazogKHVuZG9TdGFjazogc3RyaW5nW10pID0+IHZvaWQ7XG4gIHVwZGF0ZVdoaXRlYm9hcmRTdGFydGVkOiAod2hpdGVib2FyZFN0YXJ0ZWQ6IGJvb2xlYW4pID0+IHZvaWQ7XG4gIHVwZGF0ZVdoaXRlYm9hcmRFbmRlZDogKHdoaXRlYm9hcmRFbmRlZDogYm9vbGVhbikgPT4gdm9pZDtcbiAgdXBkYXRlV2hpdGVib2FyZFVzZXJzOiAod2hpdGVib2FyZFVzZXJzOiBXaGl0ZWJvYXJkVXNlcltdKSA9PiB2b2lkO1xuICB1cGRhdGVQYXJ0aWNpcGFudHM6IChwYXJ0aWNpcGFudHM6IFBhcnRpY2lwYW50W10pID0+IHZvaWQ7XG4gIHVwZGF0ZVNjcmVlbklkOiAoc2NyZWVuSWQ6IHN0cmluZykgPT4gdm9pZDtcbiAgdXBkYXRlU2hhcmVTY3JlZW5TdGFydGVkOiAoc2hhcmVTY3JlZW5TdGFydGVkOiBib29sZWFuKSA9PiB2b2lkO1xuICB1cGRhdGVDYW52YXNXaGl0ZWJvYXJkOiAoY2FudmFzV2hpdGVib2FyZDogSFRNTENhbnZhc0VsZW1lbnQgfCBudWxsKSA9PiB2b2lkO1xuXG4gIC8vIG1lZGlhc2Z1IGZ1bmN0aW9uc1xuICBvblNjcmVlbkNoYW5nZXM6IE9uU2NyZWVuQ2hhbmdlc1R5cGU7XG4gIGNhcHR1cmVDYW52YXNTdHJlYW06IENhcHR1cmVDYW52YXNTdHJlYW1UeXBlO1xuXG4gIGdldFVwZGF0ZWRBbGxQYXJhbXM6ICgpID0+IFdoaXRlYm9hcmRQYXJhbWV0ZXJzO1xuICBba2V5OiBzdHJpbmddOiBhbnk7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgV2hpdGVib2FyZE9wdGlvbnMge1xuICBjdXN0b21XaWR0aDogbnVtYmVyO1xuICBjdXN0b21IZWlnaHQ6IG51bWJlcjtcbiAgcGFyYW1ldGVyczogV2hpdGVib2FyZFBhcmFtZXRlcnM7XG4gIHNob3dBc3BlY3Q6IGJvb2xlYW47XG59XG5cbmV4cG9ydCB0eXBlIFdoaXRlYm9hcmRUeXBlID0gKG9wdGlvbnM6IFdoaXRlYm9hcmRPcHRpb25zKSA9PiB2b2lkO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdhcHAtd2hpdGVib2FyZCcsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIHRlbXBsYXRlVXJsOiAnLi93aGl0ZWJvYXJkLmNvbXBvbmVudC5odG1sJyxcbiAgc3R5bGVVcmxzOiBbJy4vd2hpdGVib2FyZC5jb21wb25lbnQuY3NzJ10sXG4gIGVuY2Fwc3VsYXRpb246IFZpZXdFbmNhcHN1bGF0aW9uLk5vbmUsXG4gIGltcG9ydHM6IFtDb21tb25Nb2R1bGUsIEZvcm1zTW9kdWxlLCBGb250QXdlc29tZU1vZHVsZV0sXG59KVxuZXhwb3J0IGNsYXNzIFdoaXRlYm9hcmQgaW1wbGVtZW50cyBPbkluaXQsIE9uRGVzdHJveSwgT25DaGFuZ2VzIHtcbiAgQElucHV0KCkgY3VzdG9tV2lkdGghOiBudW1iZXI7XG4gIEBJbnB1dCgpIGN1c3RvbUhlaWdodCE6IG51bWJlcjtcbiAgQElucHV0KCkgcGFyYW1ldGVyczogV2hpdGVib2FyZFBhcmFtZXRlcnMgPSB7fSBhcyBXaGl0ZWJvYXJkUGFyYW1ldGVycztcbiAgQElucHV0KCkgc2hvd0FzcGVjdCE6IGJvb2xlYW47XG5cbiAgQFZpZXdDaGlsZCgnY2FudmFzUmVmJywgeyBzdGF0aWM6IGZhbHNlIH0pIGNhbnZhc1JlZiE6IEVsZW1lbnRSZWY8SFRNTENhbnZhc0VsZW1lbnQ+O1xuICBAVmlld0NoaWxkKCd0ZXh0SW5wdXRSZWYnLCB7IHN0YXRpYzogZmFsc2UgfSkgdGV4dElucHV0UmVmITogRWxlbWVudFJlZjxIVE1MVGV4dEFyZWFFbGVtZW50PjtcbiAgQFZpZXdDaGlsZCgndG9nZ2xlQmFja2dyb3VuZFJlZicsIHsgc3RhdGljOiBmYWxzZSB9KVxuICB0b2dnbGVCYWNrZ3JvdW5kUmVmITogRWxlbWVudFJlZjxIVE1MQnV0dG9uRWxlbWVudD47XG4gIEBWaWV3Q2hpbGQoJ2Rvd25sb2FkTGlua1JlZicsIHsgc3RhdGljOiBmYWxzZSB9KSBkb3dubG9hZExpbmtSZWYhOiBFbGVtZW50UmVmPEhUTUxBbmNob3JFbGVtZW50PjtcbiAgQFZpZXdDaGlsZCgndGVtcENhbnZhc1JlZicsIHsgc3RhdGljOiBmYWxzZSB9KSB0ZW1wQ2FudmFzUmVmITogRWxlbWVudFJlZjxIVE1MQ2FudmFzRWxlbWVudD47XG5cbiAgZmFUaW1lcyA9IGZhVGltZXM7XG4gIGZhVW5kbyA9IGZhVW5kbztcbiAgZmFSZWRvID0gZmFSZWRvO1xuICBmYUVyYXNlciA9IGZhRXJhc2VyO1xuICBmYVNoYXBlcyA9IGZhU2hhcGVzO1xuICBmYU1vdXNlUG9pbnRlciA9IGZhTW91c2VQb2ludGVyO1xuICBmYUhhbmRQYXBlciA9IGZhSGFuZFBhcGVyO1xuICBmYVRleHRIZWlnaHQgPSBmYVRleHRIZWlnaHQ7XG4gIGZhRm9udCA9IGZhRm9udDtcbiAgZmFQZW5jaWxBbHQgPSBmYVBlbmNpbEFsdDtcbiAgZmFQYWludEJydXNoID0gZmFQYWludEJydXNoO1xuICBmYVRyYXNoID0gZmFUcmFzaDtcbiAgZmFTYXZlID0gZmFTYXZlO1xuICBmYVNlYXJjaCA9IGZhU2VhcmNoO1xuICBmYVNlYXJjaE1pbnVzID0gZmFTZWFyY2hNaW51cztcbiAgZmFTZWFyY2hQbHVzID0gZmFTZWFyY2hQbHVzO1xuICBmYUNoZXZyb25MZWZ0ID0gZmFDaGV2cm9uTGVmdDtcbiAgZmFVcGxvYWQgPSBmYVVwbG9hZDtcbiAgZmFDaGV2cm9uUmlnaHQgPSBmYUNoZXZyb25SaWdodDtcblxuICBwcml2YXRlIG1vZGUgPSAncGFuJztcbiAgcHJpdmF0ZSBpc0RyYXdpbmcgPSBmYWxzZTtcbiAgcHJpdmF0ZSBpc1Bhbm5pbmcgPSBmYWxzZTtcbiAgcHJpdmF0ZSBpc0RyYWdnaW5nID0gZmFsc2U7XG4gIHByaXZhdGUgc3RhcnRYID0gMDtcbiAgcHJpdmF0ZSBzdGFydFkgPSAwO1xuICBwcml2YXRlIGN1cnJlbnRYID0gMDtcbiAgcHJpdmF0ZSBjdXJyZW50WSA9IDA7XG4gIHByaXZhdGUgZnJlZWhhbmREcmF3aW5nOiBhbnlbXSA9IFtdO1xuICBwcml2YXRlIHNlbGVjdGVkU2hhcGU6IGFueSA9IG51bGw7XG4gIHByaXZhdGUgc2VsZWN0ZWRIYW5kbGU6IGFueSA9IG51bGw7XG4gIHByaXZhdGUgbW92aW5nU2hhcGUgPSBmYWxzZTtcbiAgcHJpdmF0ZSBwYW5YID0gMDtcbiAgcHJpdmF0ZSBwYW5ZID0gMDtcbiAgcHJpdmF0ZSBzY2FsZSA9IDE7XG4gIHByaXZhdGUgbWluU2NhbGUgPSAwLjI1O1xuICBwcml2YXRlIG1heFNjYWxlID0gMS43NTtcbiAgcHJpdmF0ZSBlcmFzZXJUaGlja25lc3MgPSAxMDtcbiAgcHJpdmF0ZSBicnVzaFRoaWNrbmVzcyA9IDY7XG4gIHByaXZhdGUgbGluZVRoaWNrbmVzcyA9IDY7XG4gIGxpbmVUeXBlID0gJ3NvbGlkJztcbiAgY29sb3IgPSAnIzAwMDAwMCc7XG4gIHByaXZhdGUgZm9udCA9ICdBcmlhbCc7XG4gIHByaXZhdGUgZm9udFNpemUgPSAyMDtcbiAgcHJpdmF0ZSBzaGFwZTogYW55ID0gbnVsbDtcbiAgcHJpdmF0ZSBiYWNrZ3JvdW5kSW1hZ2UgPSBuZXcgSW1hZ2UoKTtcbiAgdG9vbGJhclZpc2libGUgPSB0cnVlO1xuICBkcm9wZG93bk9wZW46IHN0cmluZyB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIGN1cnJlbnRDbGlja1Bvc2l0aW9uOiB7XG4gICAgY2xpZW50WDogbnVtYmVyO1xuICAgIGNsaWVudFk6IG51bWJlcjtcbiAgICBvZmZzZXRYOiBudW1iZXI7XG4gICAgb2Zmc2V0WTogbnVtYmVyO1xuICB9IHwgbnVsbCA9IG51bGw7XG5cbiAgcHJpdmF0ZSBtYXhXaWR0aCA9IDEyODA7XG4gIHByaXZhdGUgbWF4SGVpZ2h0ID0gNzIwO1xuICBwcml2YXRlIGRpbWVuc2lvbnNGaXhlZCA9IGZhbHNlO1xuICBwcml2YXRlIGlzVmFsaWRTaGFwZSA9IGZhbHNlO1xuXG4gIHVwZGF0ZUxpbmVUaGlja25lc3MgPSAodGhpY2tuZXNzOiBudW1iZXIpID0+IHtcbiAgICB0aGlzLmxpbmVUaGlja25lc3MgPSB0aGlja25lc3M7XG4gIH07XG5cbiAgdXBkYXRlQnJ1c2hUaGlja25lc3MgPSAodGhpY2tuZXNzOiBudW1iZXIpID0+IHtcbiAgICB0aGlzLmJydXNoVGhpY2tuZXNzID0gdGhpY2tuZXNzO1xuICB9O1xuXG4gIHVwZGF0ZUVyYXNlclRoaWNrbmVzcyA9ICh0aGlja25lc3M6IG51bWJlcikgPT4ge1xuICAgIHRoaXMuZXJhc2VyVGhpY2tuZXNzID0gdGhpY2tuZXNzO1xuICB9O1xuXG4gIHVwZGF0ZUNvbG9yID0gKGNvbG9yOiBzdHJpbmcpID0+IHtcbiAgICB0aGlzLmNvbG9yID0gY29sb3I7XG4gIH07XG5cbiAgdXBkYXRlRm9udCA9IChmb250OiBzdHJpbmcpID0+IHtcbiAgICB0aGlzLmZvbnQgPSBmb250O1xuICB9O1xuXG4gIHVwZGF0ZUZvbnRTaXplID0gKGZvbnRTaXplOiBudW1iZXIpID0+IHtcbiAgICB0aGlzLmZvbnRTaXplID0gZm9udFNpemU7XG4gIH07XG5cbiAgdXBkYXRlU2hhcGUgPSAoc2hhcGU6IHN0cmluZykgPT4ge1xuICAgIHRoaXMuc2hhcGUgPSBzaGFwZTtcbiAgfTtcblxuICBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5zaG93QXNwZWN0KSB7XG4gICAgICB0aGlzLmFkZExpc3RlbmVycygpO1xuICAgIH1cbiAgfVxuXG4gIG5nT25DaGFuZ2VzKGNoYW5nZXM6IFNpbXBsZUNoYW5nZXMpIHtcbiAgICBpZiAoY2hhbmdlc1sncGFyYW1ldGVycyddICYmIGNoYW5nZXNbJ3BhcmFtZXRlcnMnXS5jdXJyZW50VmFsdWUpIHtcbiAgICAgIHRoaXMucGFyYW1ldGVycyA9IGNoYW5nZXNbJ3BhcmFtZXRlcnMnXS5jdXJyZW50VmFsdWU7XG5cbiAgICAgIGlmICh0aGlzLnBhcmFtZXRlcnMuc29ja2V0KSB7XG4gICAgICAgIHRoaXMucGFyYW1ldGVycy5zb2NrZXQub24oJ3doaXRlYm9hcmRVcGRhdGVkJywgYXN5bmMgKGRhdGE6IGFueSkgPT4ge1xuICAgICAgICAgIHRoaXMuV2hpdGVib2FyZFVwZGF0ZWQoZGF0YSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHRoaXMucGFyYW1ldGVycy5zb2NrZXQub24oJ3doaXRlYm9hcmRBY3Rpb24nLCAoZGF0YTogYW55KSA9PiB7XG4gICAgICAgICAgdGhpcy5XaGl0ZWJvYXJkQWN0aW9uKGRhdGEpO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoY2hhbmdlc1snc2hvd0FzcGVjdCddKSB7XG4gICAgICBpZiAoY2hhbmdlc1snc2hvd0FzcGVjdCddLmN1cnJlbnRWYWx1ZSkge1xuICAgICAgICB0aGlzLmFkZExpc3RlbmVycygpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIG5nT25EZXN0cm95KCk6IHZvaWQge1xuICAgIGNvbnN0IGNhbnZhcyA9IHRoaXMuY2FudmFzUmVmLm5hdGl2ZUVsZW1lbnQ7XG4gICAgY2FudmFzLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21vdXNlZG93bicsIHRoaXMuc3RhcnREcmF3aW5nLmJpbmQodGhpcykpO1xuICAgIGNhbnZhcy5yZW1vdmVFdmVudExpc3RlbmVyKCdtb3VzZW1vdmUnLCB0aGlzLmRyYXcuYmluZCh0aGlzKSk7XG4gICAgY2FudmFzLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21vdXNldXAnLCB0aGlzLnN0b3BEcmF3aW5nLmJpbmQodGhpcykpO1xuICAgIGNhbnZhcy5yZW1vdmVFdmVudExpc3RlbmVyKCd3aGVlbCcsIHRoaXMuaGFuZGxlWm9vbS5iaW5kKHRoaXMpKTtcbiAgICBjYW52YXMucmVtb3ZlRXZlbnRMaXN0ZW5lcignY2xpY2snLCB0aGlzLmhhbmRsZUNhbnZhc0NsaWNrLmJpbmQodGhpcykpO1xuXG4gICAgLy8gdG91Y2ggZXZlbnRzXG4gICAgY2FudmFzLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3RvdWNoc3RhcnQnLCB0aGlzLmhhbmRsZVRvdWNoU3RhcnQuYmluZCh0aGlzKSk7XG4gICAgY2FudmFzLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3RvdWNobW92ZScsIHRoaXMuaGFuZGxlVG91Y2hNb3ZlLmJpbmQodGhpcykpO1xuICAgIGNhbnZhcy5yZW1vdmVFdmVudExpc3RlbmVyKCd0b3VjaGVuZCcsIHRoaXMuaGFuZGxlVG91Y2hFbmQuYmluZCh0aGlzKSk7XG5cbiAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdtb3VzZWRvd24nLCB0aGlzLmhhbmRsZUNsaWNrT3V0c2lkZS5iaW5kKHRoaXMpKTtcbiAgfVxuXG4gIG5nQWZ0ZXJWaWV3SW5pdCgpIHtcbiAgICAvLyBBdHRhY2ggdGhlIGV2ZW50IGxpc3RlbmVyIG9uY2UgYWZ0ZXIgdGhlIHZpZXcgaGFzIGJlZW4gaW5pdGlhbGl6ZWRcbiAgICBjb25zdCB0ZXh0SW5wdXQgPSB0aGlzLnRleHRJbnB1dFJlZi5uYXRpdmVFbGVtZW50O1xuICAgIHRleHRJbnB1dC5hZGRFdmVudExpc3RlbmVyKCdrZXlwcmVzcycsIChldmVudDogS2V5Ym9hcmRFdmVudCkgPT4ge1xuICAgICAgaWYgKGV2ZW50LmtleSA9PT0gJ0VudGVyJykge1xuICAgICAgICB0aGlzLmhhbmRsZVRleHRJbnB1dChldmVudCk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICBoYW5kbGVUZXh0SW5wdXQoZXZlbnQ6IEtleWJvYXJkRXZlbnQpIHtcbiAgICBjb25zdCB0ZXh0SW5wdXQgPSB0aGlzLnRleHRJbnB1dFJlZi5uYXRpdmVFbGVtZW50O1xuICAgIGlmIChldmVudC5rZXkgPT09ICdFbnRlcicgJiYgdGhpcy5jdXJyZW50Q2xpY2tQb3NpdGlvbikge1xuICAgICAgY29uc3QgeyBvZmZzZXRYLCBvZmZzZXRZIH0gPSB0aGlzLmN1cnJlbnRDbGlja1Bvc2l0aW9uO1xuICAgICAgY29uc3QgdGV4dCA9IHRleHRJbnB1dC52YWx1ZTtcbiAgICAgIHRleHRJbnB1dC5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xuICAgICAgdGV4dElucHV0LnZhbHVlID0gJyc7XG5cbiAgICAgIGNvbnN0IHggPSAob2Zmc2V0WCAtIHRoaXMucGFuWCkgLyB0aGlzLnNjYWxlO1xuICAgICAgY29uc3QgeSA9IChvZmZzZXRZIC0gdGhpcy5wYW5ZKSAvIHRoaXMuc2NhbGU7XG5cbiAgICAgIHRoaXMucGFyYW1ldGVycy5zaGFwZXMucHVzaCh7XG4gICAgICAgIHR5cGU6ICd0ZXh0JyxcbiAgICAgICAgdGV4dCxcbiAgICAgICAgeCxcbiAgICAgICAgeSxcbiAgICAgICAgY29sb3I6IHRoaXMuY29sb3IsXG4gICAgICAgIGZvbnQ6IHRoaXMuZm9udCxcbiAgICAgICAgZm9udFNpemU6IHRoaXMuZm9udFNpemUsXG4gICAgICB9KTtcblxuICAgICAgdGhpcy5kcmF3U2hhcGVzKCk7XG4gICAgICB0aGlzLnBhcmFtZXRlcnMudXBkYXRlU2hhcGVzKHRoaXMucGFyYW1ldGVycy5zaGFwZXMpO1xuICAgICAgdGhpcy5wYXJhbWV0ZXJzLnNvY2tldC5lbWl0KFxuICAgICAgICAndXBkYXRlQm9hcmRBY3Rpb24nLFxuICAgICAgICB7XG4gICAgICAgICAgYWN0aW9uOiAndGV4dCcsXG4gICAgICAgICAgcGF5bG9hZDoge1xuICAgICAgICAgICAgdHlwZTogJ3RleHQnLFxuICAgICAgICAgICAgdGV4dCxcbiAgICAgICAgICAgIHgsXG4gICAgICAgICAgICB5LFxuICAgICAgICAgICAgY29sb3I6IHRoaXMuY29sb3IsXG4gICAgICAgICAgICBmb250OiB0aGlzLmZvbnQsXG4gICAgICAgICAgICBmb250U2l6ZTogdGhpcy5mb250U2l6ZSxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgICB0aGlzLmhhbmRsZVNlcnZlclJlc3BvbnNlLFxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICBhZGRMaXN0ZW5lcnMgPSAoKSA9PiB7XG4gICAgaWYgKHRoaXMucGFyYW1ldGVycykge1xuICAgICAgdGhpcy5wYXJhbWV0ZXJzID0gdGhpcy5wYXJhbWV0ZXJzLmdldFVwZGF0ZWRBbGxQYXJhbXMoKTtcbiAgICB9XG5cbiAgICB0aGlzLmJhY2tncm91bmRJbWFnZS5zcmMgPSAnaHR0cHM6Ly9tZWRpYXNmdS5jb20vaW1hZ2VzL3N2Zy9ncmFwaF9wYXBlci5qcGcnO1xuICAgIHRoaXMuYmFja2dyb3VuZEltYWdlLmNyb3NzT3JpZ2luID0gJ2Fub255bW91cyc7XG4gICAgdGhpcy5iYWNrZ3JvdW5kSW1hZ2Uub25sb2FkID0gKCkgPT4ge1xuICAgICAgdGhpcy5kcmF3U2hhcGVzKCk7XG4gICAgfTtcblxuICAgIGNvbnN0IGNhbnZhcyA9IHRoaXMuY2FudmFzUmVmLm5hdGl2ZUVsZW1lbnQ7XG5cbiAgICBpZiAodGhpcy5jYW52YXNSZWYubmF0aXZlRWxlbWVudCkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgaWYgKFxuICAgICAgICAgIHRoaXMucGFyYW1ldGVycy50YXJnZXRSZXNvbHV0aW9uID09ICdxaGQnIHx8XG4gICAgICAgICAgdGhpcy5wYXJhbWV0ZXJzLnRhcmdldFJlc29sdXRpb25Ib3N0ID09ICdxaGQnXG4gICAgICAgICkge1xuICAgICAgICAgIHRoaXMubWF4V2lkdGggPSAxOTIwO1xuICAgICAgICAgIHRoaXMubWF4SGVpZ2h0ID0gMTA4MDtcbiAgICAgICAgfSBlbHNlIGlmIChcbiAgICAgICAgICB0aGlzLnBhcmFtZXRlcnMudGFyZ2V0UmVzb2x1dGlvbiA9PSAnZmhkJyB8fFxuICAgICAgICAgIHRoaXMucGFyYW1ldGVycy50YXJnZXRSZXNvbHV0aW9uSG9zdCA9PSAnZmhkJ1xuICAgICAgICApIHtcbiAgICAgICAgICB0aGlzLm1heFdpZHRoID0gMTkyMDtcbiAgICAgICAgICB0aGlzLm1heEhlaWdodCA9IDEwODA7XG4gICAgICAgIH1cbiAgICAgICAgY2FudmFzLndpZHRoID0gdGhpcy5tYXhXaWR0aDtcbiAgICAgICAgY2FudmFzLmhlaWdodCA9IHRoaXMubWF4SGVpZ2h0O1xuICAgICAgICB0aGlzLmRpbWVuc2lvbnNGaXhlZCA9IHRydWU7XG4gICAgICB9IGNhdGNoIHtcbiAgICAgICAgLyogaGFuZGxlIGVycm9yICovXG4gICAgICB9XG4gICAgICB0aGlzLnBhcmFtZXRlcnMudXBkYXRlQ2FudmFzV2hpdGVib2FyZCh0aGlzLmNhbnZhc1JlZi5uYXRpdmVFbGVtZW50KTtcbiAgICB9XG5cbiAgICBjYW52YXMuYWRkRXZlbnRMaXN0ZW5lcignbW91c2Vkb3duJywgdGhpcy5zdGFydERyYXdpbmcuYmluZCh0aGlzKSk7XG4gICAgY2FudmFzLmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlbW92ZScsIHRoaXMuZHJhdy5iaW5kKHRoaXMpKTtcbiAgICBjYW52YXMuYWRkRXZlbnRMaXN0ZW5lcignbW91c2V1cCcsIHRoaXMuc3RvcERyYXdpbmcuYmluZCh0aGlzKSk7XG4gICAgY2FudmFzLmFkZEV2ZW50TGlzdGVuZXIoJ3doZWVsJywgdGhpcy5oYW5kbGVab29tLmJpbmQodGhpcykpO1xuICAgIGNhbnZhcy5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIHRoaXMuaGFuZGxlQ2FudmFzQ2xpY2suYmluZCh0aGlzKSk7XG5cbiAgICAvLyB0b3VjaCBldmVudHNcbiAgICBjYW52YXMuYWRkRXZlbnRMaXN0ZW5lcigndG91Y2hzdGFydCcsIHRoaXMuaGFuZGxlVG91Y2hTdGFydC5iaW5kKHRoaXMpKTtcbiAgICBjYW52YXMuYWRkRXZlbnRMaXN0ZW5lcigndG91Y2htb3ZlJywgdGhpcy5oYW5kbGVUb3VjaE1vdmUuYmluZCh0aGlzKSk7XG4gICAgY2FudmFzLmFkZEV2ZW50TGlzdGVuZXIoJ3RvdWNoZW5kJywgdGhpcy5oYW5kbGVUb3VjaEVuZC5iaW5kKHRoaXMpKTtcblxuICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlZG93bicsIHRoaXMuaGFuZGxlQ2xpY2tPdXRzaWRlLmJpbmQodGhpcykpO1xuICB9O1xuXG4gIGhhbmRsZVRvdWNoU3RhcnQoZTogVG91Y2hFdmVudCkge1xuICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICBjb25zdCB0b3VjaCA9IGUudG91Y2hlc1swXTtcbiAgICBjb25zdCBtb3VzZUV2ZW50ID0gbmV3IE1vdXNlRXZlbnQoJ21vdXNlZG93bicsIHtcbiAgICAgIGNsaWVudFg6IHRvdWNoLmNsaWVudFgsXG4gICAgICBjbGllbnRZOiB0b3VjaC5jbGllbnRZLFxuICAgIH0pO1xuICAgIHRoaXMuY2FudmFzUmVmLm5hdGl2ZUVsZW1lbnQuZGlzcGF0Y2hFdmVudChtb3VzZUV2ZW50KTtcbiAgfVxuXG4gIGhhbmRsZVRvdWNoTW92ZShlOiBUb3VjaEV2ZW50KSB7XG4gICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIGNvbnN0IHRvdWNoID0gZS50b3VjaGVzWzBdO1xuICAgIGNvbnN0IG1vdXNlRXZlbnQgPSBuZXcgTW91c2VFdmVudCgnbW91c2Vtb3ZlJywge1xuICAgICAgY2xpZW50WDogdG91Y2guY2xpZW50WCxcbiAgICAgIGNsaWVudFk6IHRvdWNoLmNsaWVudFksXG4gICAgfSk7XG4gICAgdGhpcy5jYW52YXNSZWYubmF0aXZlRWxlbWVudC5kaXNwYXRjaEV2ZW50KG1vdXNlRXZlbnQpO1xuICB9XG5cbiAgaGFuZGxlVG91Y2hFbmQoZTogVG91Y2hFdmVudCkge1xuICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICBjb25zdCBtb3VzZUV2ZW50ID0gbmV3IE1vdXNlRXZlbnQoJ21vdXNldXAnLCB7fSk7XG4gICAgdGhpcy5jYW52YXNSZWYubmF0aXZlRWxlbWVudC5kaXNwYXRjaEV2ZW50KG1vdXNlRXZlbnQpO1xuICB9XG5cbiAgaGFuZGxlQ2xpY2tPdXRzaWRlKGV2ZW50OiBNb3VzZUV2ZW50KSB7XG4gICAgY29uc3QgdGFyZ2V0ID0gZXZlbnQudGFyZ2V0IGFzIEVsZW1lbnQ7XG4gICAgaWYgKHRoaXMuZHJvcGRvd25PcGVuICYmICF0YXJnZXQuY2xvc2VzdCgnLmJ0bi1ncm91cCcpKSB7XG4gICAgICB0aGlzLmRyb3Bkb3duT3BlbiA9IG51bGw7XG4gICAgfVxuICB9XG5cbiAgaGFuZGxlQ2FudmFzQ2xpY2soZTogTW91c2VFdmVudCkge1xuICAgIGlmICh0aGlzLm1vZGUgPT09ICd0ZXh0Jykge1xuICAgICAgY29uc3QgdGV4dElucHV0ID0gdGhpcy50ZXh0SW5wdXRSZWYubmF0aXZlRWxlbWVudDtcbiAgICAgIHRleHRJbnB1dC5zdHlsZS5sZWZ0ID0gZS5jbGllbnRYICsgJ3B4JztcbiAgICAgIHRleHRJbnB1dC5zdHlsZS50b3AgPSBlLmNsaWVudFkgKyAncHgnO1xuICAgICAgdGV4dElucHV0LnN0eWxlLmRpc3BsYXkgPSAnYmxvY2snO1xuICAgICAgdGV4dElucHV0LmZvY3VzKCk7XG4gICAgICB0aGlzLmN1cnJlbnRDbGlja1Bvc2l0aW9uID0ge1xuICAgICAgICBjbGllbnRYOiBlLmNsaWVudFgsXG4gICAgICAgIGNsaWVudFk6IGUuY2xpZW50WSxcbiAgICAgICAgb2Zmc2V0WDogZS5vZmZzZXRYLFxuICAgICAgICBvZmZzZXRZOiBlLm9mZnNldFksXG4gICAgICB9O1xuICAgIH1cbiAgfVxuXG4gIHN0YXJ0RHJhd2luZyhlOiBNb3VzZUV2ZW50KSB7XG4gICAgdGhpcy5pc0RyYXdpbmcgPSB0cnVlO1xuICAgIHRoaXMuc3RhcnRYID0gKGUub2Zmc2V0WCAtIHRoaXMucGFuWCkgLyB0aGlzLnNjYWxlO1xuICAgIHRoaXMuc3RhcnRZID0gKGUub2Zmc2V0WSAtIHRoaXMucGFuWSkgLyB0aGlzLnNjYWxlO1xuXG4gICAgaWYgKHRoaXMubW9kZSA9PT0gJ2VyYXNlJykge1xuICAgICAgdGhpcy5lcmFzZSh0aGlzLnN0YXJ0WCwgdGhpcy5zdGFydFkpO1xuICAgIH0gZWxzZSBpZiAodGhpcy5tb2RlID09PSAnZHJhdycgfHwgdGhpcy5tb2RlID09PSAnZnJlZWhhbmQnKSB7XG4gICAgICBjb25zdCBjdHggPSB0aGlzLmNhbnZhc1JlZi5uYXRpdmVFbGVtZW50LmdldENvbnRleHQoJzJkJyk7XG4gICAgICBjdHghLmJlZ2luUGF0aCgpO1xuICAgICAgY3R4IS5tb3ZlVG8odGhpcy5zdGFydFgsIHRoaXMuc3RhcnRZKTtcbiAgICAgIGlmICh0aGlzLm1vZGUgPT09ICdmcmVlaGFuZCcpIHtcbiAgICAgICAgdGhpcy5mcmVlaGFuZERyYXdpbmcgPSBbeyB4OiB0aGlzLnN0YXJ0WCwgeTogdGhpcy5zdGFydFkgfV07XG4gICAgICB9XG4gICAgfSBlbHNlIGlmICh0aGlzLm1vZGUgPT09ICdwYW4nKSB7XG4gICAgICB0aGlzLmlzUGFubmluZyA9IHRydWU7XG4gICAgICB0aGlzLmlzRHJhZ2dpbmcgPSBmYWxzZTtcbiAgICB9IGVsc2UgaWYgKHRoaXMubW9kZSA9PT0gJ3NlbGVjdCcpIHtcbiAgICAgIHRoaXMuc2VsZWN0ZWRIYW5kbGUgPSB0aGlzLmdldEhhbmRsZUF0UG9zaXRpb24odGhpcy5zdGFydFgsIHRoaXMuc3RhcnRZKTtcbiAgICAgIGlmICh0aGlzLnNlbGVjdGVkSGFuZGxlKSB7XG4gICAgICAgIHRoaXMuaXNEcmFnZ2luZyA9IHRydWU7XG4gICAgICAgIHRoaXMubW92aW5nU2hhcGUgPSB0aGlzLnNlbGVjdGVkSGFuZGxlLmlzQ2VudGVyO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5zZWxlY3RlZFNoYXBlID0gdGhpcy5maW5kU2hhcGUodGhpcy5zdGFydFgsIHRoaXMuc3RhcnRZKTtcbiAgICAgICAgaWYgKHRoaXMuc2VsZWN0ZWRTaGFwZSkge1xuICAgICAgICAgIHRoaXMuZHJhd1NoYXBlcygpO1xuICAgICAgICAgIHRoaXMuZHJhd1NlbGVjdGlvbih0aGlzLnNlbGVjdGVkU2hhcGUpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgZHJhdyA9IChlOiBNb3VzZUV2ZW50KSA9PiB7XG4gICAgaWYgKCF0aGlzLmRpbWVuc2lvbnNGaXhlZCkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgaWYgKFxuICAgICAgICAgIHRoaXMucGFyYW1ldGVycy50YXJnZXRSZXNvbHV0aW9uID09ICdxaGQnIHx8XG4gICAgICAgICAgdGhpcy5wYXJhbWV0ZXJzLnRhcmdldFJlc29sdXRpb25Ib3N0ID09ICdxaGQnXG4gICAgICAgICkge1xuICAgICAgICAgIHRoaXMubWF4V2lkdGggPSAxOTIwO1xuICAgICAgICAgIHRoaXMubWF4SGVpZ2h0ID0gMTA4MDtcbiAgICAgICAgfSBlbHNlIGlmIChcbiAgICAgICAgICB0aGlzLnBhcmFtZXRlcnMudGFyZ2V0UmVzb2x1dGlvbiA9PSAnZmhkJyB8fFxuICAgICAgICAgIHRoaXMucGFyYW1ldGVycy50YXJnZXRSZXNvbHV0aW9uSG9zdCA9PSAnZmhkJ1xuICAgICAgICApIHtcbiAgICAgICAgICB0aGlzLm1heFdpZHRoID0gMTkyMDtcbiAgICAgICAgICB0aGlzLm1heEhlaWdodCA9IDEwODA7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5jYW52YXNSZWYubmF0aXZlRWxlbWVudC53aWR0aCA9IHRoaXMubWF4V2lkdGg7XG4gICAgICAgIHRoaXMuY2FudmFzUmVmLm5hdGl2ZUVsZW1lbnQuaGVpZ2h0ID0gdGhpcy5tYXhIZWlnaHQ7XG4gICAgICAgIHRoaXMuZGltZW5zaW9uc0ZpeGVkID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5wYXJhbWV0ZXJzLnVwZGF0ZUNhbnZhc1doaXRlYm9hcmQodGhpcy5jYW52YXNSZWYubmF0aXZlRWxlbWVudCk7XG4gICAgICB9IGNhdGNoIHtcbiAgICAgICAgLyogaGFuZGxlIGVycm9yICovXG4gICAgICB9XG4gICAgfVxuICAgIGlmICghdGhpcy5pc0RyYXdpbmcpIHJldHVybjtcbiAgICB0aGlzLmN1cnJlbnRYID0gKGUub2Zmc2V0WCAtIHRoaXMucGFuWCkgLyB0aGlzLnNjYWxlO1xuICAgIHRoaXMuY3VycmVudFkgPSAoZS5vZmZzZXRZIC0gdGhpcy5wYW5ZKSAvIHRoaXMuc2NhbGU7XG5cbiAgICBpZiAodGhpcy5tb2RlID09ICdkcmF3JyB8fCB0aGlzLm1vZGUgPT0gJ2ZyZWVoYW5kJyB8fCB0aGlzLm1vZGUgPT0gJ3NoYXBlJykge1xuICAgICAgLy9pZiBtb3JlIHRoYW4gbWF4IHdpZHRoIG9yIGhlaWdodCBvciBsZXNzIHRoYW4gMCwgcmV0dXJuXG4gICAgICBpZiAoXG4gICAgICAgIHRoaXMuY3VycmVudFggPiB0aGlzLm1heFdpZHRoIHx8XG4gICAgICAgIHRoaXMuY3VycmVudFkgPiB0aGlzLm1heEhlaWdodCB8fFxuICAgICAgICB0aGlzLmN1cnJlbnRYIDwgMCB8fFxuICAgICAgICB0aGlzLmN1cnJlbnRZIDwgMFxuICAgICAgKSB7XG4gICAgICAgIHRoaXMuaXNWYWxpZFNoYXBlID0gZmFsc2U7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuaXNWYWxpZFNoYXBlID0gdHJ1ZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBjdHggPSB0aGlzLmNhbnZhc1JlZi5uYXRpdmVFbGVtZW50LmdldENvbnRleHQoJzJkJyk7XG4gICAgaWYgKHRoaXMubW9kZSA9PT0gJ2VyYXNlJykge1xuICAgICAgdGhpcy5lcmFzZSh0aGlzLmN1cnJlbnRYLCB0aGlzLmN1cnJlbnRZKTtcbiAgICB9IGVsc2UgaWYgKHRoaXMubW9kZSA9PT0gJ2RyYXcnKSB7XG4gICAgICBjdHghLmNsZWFyUmVjdCgwLCAwLCB0aGlzLmNhbnZhc1JlZi5uYXRpdmVFbGVtZW50LndpZHRoLCB0aGlzLmNhbnZhc1JlZi5uYXRpdmVFbGVtZW50LmhlaWdodCk7XG4gICAgICB0aGlzLmRyYXdTaGFwZXMoKTtcbiAgICAgIHRoaXMuZHJhd0xpbmUoXG4gICAgICAgIHRoaXMuc3RhcnRYLFxuICAgICAgICB0aGlzLnN0YXJ0WSxcbiAgICAgICAgdGhpcy5jdXJyZW50WCxcbiAgICAgICAgdGhpcy5jdXJyZW50WSxcbiAgICAgICAgdGhpcy5jb2xvcixcbiAgICAgICAgdGhpcy5saW5lVGhpY2tuZXNzLFxuICAgICAgICB0aGlzLmxpbmVUeXBlLFxuICAgICAgKTtcbiAgICB9IGVsc2UgaWYgKHRoaXMubW9kZSA9PT0gJ2ZyZWVoYW5kJykge1xuICAgICAgY3R4IS5saW5lVG8odGhpcy5jdXJyZW50WCwgdGhpcy5jdXJyZW50WSk7XG4gICAgICBjdHghLnN0cm9rZVN0eWxlID0gdGhpcy5jb2xvcjtcbiAgICAgIGN0eCEubGluZVdpZHRoID0gdGhpcy5icnVzaFRoaWNrbmVzcztcbiAgICAgIGN0eCEuc3Ryb2tlKCk7XG4gICAgICB0aGlzLmZyZWVoYW5kRHJhd2luZy5wdXNoKHsgeDogdGhpcy5jdXJyZW50WCwgeTogdGhpcy5jdXJyZW50WSB9KTtcbiAgICB9IGVsc2UgaWYgKHRoaXMubW9kZSA9PT0gJ3NoYXBlJykge1xuICAgICAgY3R4IS5jbGVhclJlY3QoMCwgMCwgdGhpcy5jYW52YXNSZWYubmF0aXZlRWxlbWVudC53aWR0aCwgdGhpcy5jYW52YXNSZWYubmF0aXZlRWxlbWVudC5oZWlnaHQpO1xuICAgICAgdGhpcy5kcmF3U2hhcGVzKCk7XG4gICAgICB0aGlzLmRyYXdTaGFwZShcbiAgICAgICAgdGhpcy5zaGFwZSxcbiAgICAgICAgdGhpcy5zdGFydFgsXG4gICAgICAgIHRoaXMuc3RhcnRZLFxuICAgICAgICB0aGlzLmN1cnJlbnRYLFxuICAgICAgICB0aGlzLmN1cnJlbnRZLFxuICAgICAgICB0aGlzLmNvbG9yLFxuICAgICAgICB0aGlzLmxpbmVUaGlja25lc3MsXG4gICAgICAgIHRoaXMubGluZVR5cGUsXG4gICAgICApO1xuICAgIH0gZWxzZSBpZiAodGhpcy5tb2RlID09PSAncGFuJyAmJiB0aGlzLmlzUGFubmluZykge1xuICAgICAgdGhpcy5pc0RyYWdnaW5nID0gdHJ1ZTtcbiAgICAgIGNvbnN0IGR4ID0gZS5jbGllbnRYIC0gdGhpcy5zdGFydFg7XG4gICAgICBjb25zdCBkeSA9IGUuY2xpZW50WSAtIHRoaXMuc3RhcnRZO1xuICAgICAgdGhpcy5wYW5YICs9IGR4O1xuICAgICAgdGhpcy5wYW5ZICs9IGR5O1xuICAgICAgdGhpcy5zdGFydFggPSBlLmNsaWVudFg7XG4gICAgICB0aGlzLnN0YXJ0WSA9IGUuY2xpZW50WTtcblxuICAgICAgY3R4IS5zZXRUcmFuc2Zvcm0odGhpcy5zY2FsZSwgMCwgMCwgdGhpcy5zY2FsZSwgdGhpcy5wYW5YLCB0aGlzLnBhblkpO1xuICAgICAgdGhpcy5kcmF3U2hhcGVzKCk7XG4gICAgfSBlbHNlIGlmICh0aGlzLm1vZGUgPT09ICdzZWxlY3QnICYmIHRoaXMuc2VsZWN0ZWRTaGFwZSkge1xuICAgICAgY3R4IS5jbGVhclJlY3QoMCwgMCwgdGhpcy5jYW52YXNSZWYubmF0aXZlRWxlbWVudC53aWR0aCwgdGhpcy5jYW52YXNSZWYubmF0aXZlRWxlbWVudC5oZWlnaHQpO1xuICAgICAgaWYgKHRoaXMubW92aW5nU2hhcGUpIHtcbiAgICAgICAgY29uc3QgZHggPSB0aGlzLmN1cnJlbnRYIC0gdGhpcy5zdGFydFg7XG4gICAgICAgIGNvbnN0IGR5ID0gdGhpcy5jdXJyZW50WSAtIHRoaXMuc3RhcnRZO1xuICAgICAgICB0aGlzLm1vdmVTaGFwZSh0aGlzLnNlbGVjdGVkU2hhcGUsIGR4LCBkeSk7XG4gICAgICAgIHRoaXMuc3RhcnRYID0gdGhpcy5jdXJyZW50WDtcbiAgICAgICAgdGhpcy5zdGFydFkgPSB0aGlzLmN1cnJlbnRZO1xuICAgICAgfSBlbHNlIGlmICh0aGlzLmlzRHJhZ2dpbmcpIHtcbiAgICAgICAgdGhpcy5yZXNpemVTaGFwZSh0aGlzLnNlbGVjdGVkU2hhcGUsIHRoaXMuc2VsZWN0ZWRIYW5kbGUsIHRoaXMuY3VycmVudFgsIHRoaXMuY3VycmVudFkpO1xuICAgICAgfVxuICAgICAgdGhpcy5kcmF3U2hhcGVzKCk7XG4gICAgICB0aGlzLmRyYXdTZWxlY3Rpb24odGhpcy5zZWxlY3RlZFNoYXBlKTtcbiAgICB9XG4gIH07XG5cbiAgc3RvcERyYXdpbmcoKSB7XG4gICAgdGhpcy5pc0RyYXdpbmcgPSBmYWxzZTtcbiAgICB0aGlzLmlzUGFubmluZyA9IGZhbHNlO1xuICAgIHRoaXMuaXNEcmFnZ2luZyA9IGZhbHNlO1xuXG4gICAgY29uc3QgY3R4ID0gdGhpcy5jYW52YXNSZWYubmF0aXZlRWxlbWVudC5nZXRDb250ZXh0KCcyZCcpO1xuICAgIGN0eCEuY2xvc2VQYXRoKCk7XG5cbiAgICBpZiAodGhpcy5tb2RlID09PSAnZHJhdycgJiYgdGhpcy5pc1ZhbGlkU2hhcGUpIHtcbiAgICAgIHRoaXMucGFyYW1ldGVycy5zaGFwZXMucHVzaCh7XG4gICAgICAgIHR5cGU6ICdsaW5lJyxcbiAgICAgICAgeDE6IHRoaXMuc3RhcnRYLFxuICAgICAgICB5MTogdGhpcy5zdGFydFksXG4gICAgICAgIHgyOiB0aGlzLmN1cnJlbnRYLFxuICAgICAgICB5MjogdGhpcy5jdXJyZW50WSxcbiAgICAgICAgY29sb3I6IHRoaXMuY29sb3IsXG4gICAgICAgIHRoaWNrbmVzczogdGhpcy5saW5lVGhpY2tuZXNzLFxuICAgICAgICBsaW5lVHlwZTogdGhpcy5saW5lVHlwZSxcbiAgICAgIH0pO1xuICAgICAgdGhpcy5wYXJhbWV0ZXJzLnVwZGF0ZVNoYXBlcyh0aGlzLnBhcmFtZXRlcnMuc2hhcGVzKTtcbiAgICAgIHRoaXMuc2F2ZVN0YXRlKCk7XG4gICAgICB0aGlzLnBhcmFtZXRlcnMuc29ja2V0LmVtaXQoXG4gICAgICAgICd1cGRhdGVCb2FyZEFjdGlvbicsXG4gICAgICAgIHtcbiAgICAgICAgICBhY3Rpb246ICdkcmF3JyxcbiAgICAgICAgICBwYXlsb2FkOiB7XG4gICAgICAgICAgICB0eXBlOiAnbGluZScsXG4gICAgICAgICAgICB4MTogdGhpcy5zdGFydFgsXG4gICAgICAgICAgICB5MTogdGhpcy5zdGFydFksXG4gICAgICAgICAgICB4MjogdGhpcy5jdXJyZW50WCxcbiAgICAgICAgICAgIHkyOiB0aGlzLmN1cnJlbnRZLFxuICAgICAgICAgICAgY29sb3I6IHRoaXMuY29sb3IsXG4gICAgICAgICAgICB0aGlja25lc3M6IHRoaXMubGluZVRoaWNrbmVzcyxcbiAgICAgICAgICAgIGxpbmVUeXBlOiB0aGlzLmxpbmVUeXBlLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICAgIHRoaXMuaGFuZGxlU2VydmVyUmVzcG9uc2UsXG4gICAgICApO1xuICAgIH0gZWxzZSBpZiAodGhpcy5tb2RlID09PSAnZnJlZWhhbmQnICYmIHRoaXMuaXNWYWxpZFNoYXBlKSB7XG4gICAgICB0aGlzLnBhcmFtZXRlcnMuc2hhcGVzLnB1c2goe1xuICAgICAgICB0eXBlOiAnZnJlZWhhbmQnLFxuICAgICAgICBwb2ludHM6IHRoaXMuZnJlZWhhbmREcmF3aW5nLFxuICAgICAgICBjb2xvcjogdGhpcy5jb2xvcixcbiAgICAgICAgdGhpY2tuZXNzOiB0aGlzLmJydXNoVGhpY2tuZXNzLFxuICAgICAgfSk7XG4gICAgICB0aGlzLnBhcmFtZXRlcnMudXBkYXRlU2hhcGVzKHRoaXMucGFyYW1ldGVycy5zaGFwZXMpO1xuICAgICAgdGhpcy5wYXJhbWV0ZXJzLnNvY2tldC5lbWl0KFxuICAgICAgICAndXBkYXRlQm9hcmRBY3Rpb24nLFxuICAgICAgICB7XG4gICAgICAgICAgYWN0aW9uOiAnZHJhdycsXG4gICAgICAgICAgcGF5bG9hZDoge1xuICAgICAgICAgICAgdHlwZTogJ2ZyZWVoYW5kJyxcbiAgICAgICAgICAgIHBvaW50czogdGhpcy5mcmVlaGFuZERyYXdpbmcsXG4gICAgICAgICAgICBjb2xvcjogdGhpcy5jb2xvcixcbiAgICAgICAgICAgIHRoaWNrbmVzczogdGhpcy5icnVzaFRoaWNrbmVzcyxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgICB0aGlzLmhhbmRsZVNlcnZlclJlc3BvbnNlLFxuICAgICAgKTtcbiAgICAgIHRoaXMuZnJlZWhhbmREcmF3aW5nID0gW107XG4gICAgICB0aGlzLnNhdmVTdGF0ZSgpO1xuICAgIH0gZWxzZSBpZiAodGhpcy5tb2RlID09PSAnc2hhcGUnICYmIHRoaXMuaXNWYWxpZFNoYXBlKSB7XG4gICAgICB0aGlzLnBhcmFtZXRlcnMuc2hhcGVzLnB1c2goe1xuICAgICAgICB0eXBlOiB0aGlzLnNoYXBlLFxuICAgICAgICB4MTogdGhpcy5zdGFydFgsXG4gICAgICAgIHkxOiB0aGlzLnN0YXJ0WSxcbiAgICAgICAgeDI6IHRoaXMuY3VycmVudFgsXG4gICAgICAgIHkyOiB0aGlzLmN1cnJlbnRZLFxuICAgICAgICBjb2xvcjogdGhpcy5jb2xvcixcbiAgICAgICAgdGhpY2tuZXNzOiB0aGlzLmxpbmVUaGlja25lc3MsXG4gICAgICAgIGxpbmVUeXBlOiB0aGlzLmxpbmVUeXBlLFxuICAgICAgfSk7XG4gICAgICB0aGlzLnBhcmFtZXRlcnMudXBkYXRlU2hhcGVzKHRoaXMucGFyYW1ldGVycy5zaGFwZXMpO1xuICAgICAgdGhpcy5zYXZlU3RhdGUoKTtcbiAgICAgIHRoaXMucGFyYW1ldGVycy5zb2NrZXQuZW1pdChcbiAgICAgICAgJ3VwZGF0ZUJvYXJkQWN0aW9uJyxcbiAgICAgICAge1xuICAgICAgICAgIGFjdGlvbjogJ3NoYXBlJyxcbiAgICAgICAgICBwYXlsb2FkOiB7XG4gICAgICAgICAgICB0eXBlOiB0aGlzLnNoYXBlLFxuICAgICAgICAgICAgeDE6IHRoaXMuc3RhcnRYLFxuICAgICAgICAgICAgeTE6IHRoaXMuc3RhcnRZLFxuICAgICAgICAgICAgeDI6IHRoaXMuY3VycmVudFgsXG4gICAgICAgICAgICB5MjogdGhpcy5jdXJyZW50WSxcbiAgICAgICAgICAgIGNvbG9yOiB0aGlzLmNvbG9yLFxuICAgICAgICAgICAgdGhpY2tuZXNzOiB0aGlzLmxpbmVUaGlja25lc3MsXG4gICAgICAgICAgICBsaW5lVHlwZTogdGhpcy5saW5lVHlwZSxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgICB0aGlzLmhhbmRsZVNlcnZlclJlc3BvbnNlLFxuICAgICAgKTtcbiAgICB9IGVsc2UgaWYgKHRoaXMubW9kZSA9PT0gJ3NlbGVjdCcpIHtcbiAgICAgIGlmICh0aGlzLnNlbGVjdGVkU2hhcGUgJiYgIXRoaXMubW92aW5nU2hhcGUgJiYgIXRoaXMuaXNEcmFnZ2luZykge1xuICAgICAgICBjb25zdCBzaGFwZUZvdW5kID0gdGhpcy5maW5kU2hhcGUodGhpcy5jdXJyZW50WCwgdGhpcy5jdXJyZW50WSk7XG4gICAgICAgIGlmIChzaGFwZUZvdW5kKSB7XG4gICAgICAgICAgdGhpcy5zZWxlY3RlZFNoYXBlID0gc2hhcGVGb3VuZDtcbiAgICAgICAgICB0aGlzLmRyYXdTaGFwZXMoKTtcbiAgICAgICAgICB0aGlzLmRyYXdTZWxlY3Rpb24oc2hhcGVGb3VuZCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGlmICh0aGlzLnNlbGVjdGVkU2hhcGUpIHtcbiAgICAgICAgdGhpcy5wYXJhbWV0ZXJzLnNvY2tldC5lbWl0KFxuICAgICAgICAgICd1cGRhdGVCb2FyZEFjdGlvbicsXG4gICAgICAgICAgeyBhY3Rpb246ICdzaGFwZXMnLCBwYXlsb2FkOiB7IHNoYXBlczogdGhpcy5wYXJhbWV0ZXJzLnNoYXBlcyB9IH0sXG4gICAgICAgICAgdGhpcy5oYW5kbGVTZXJ2ZXJSZXNwb25zZSxcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICAgIHRoaXMuc2F2ZVN0YXRlKCk7XG4gICAgfVxuICB9XG5cbiAgZXJhc2UoeDogbnVtYmVyLCB5OiBudW1iZXIpIHtcbiAgICBjb25zdCBjdHggPSB0aGlzLmNhbnZhc1JlZi5uYXRpdmVFbGVtZW50LmdldENvbnRleHQoJzJkJyk7XG4gICAgY3R4IS5zYXZlKCk7XG4gICAgY3R4IS5nbG9iYWxDb21wb3NpdGVPcGVyYXRpb24gPSAnZGVzdGluYXRpb24tb3V0JztcbiAgICBjdHghLmJlZ2luUGF0aCgpO1xuICAgIGN0eCEuYXJjKHgsIHksIHRoaXMuZXJhc2VyVGhpY2tuZXNzIC8gMiwgMCwgTWF0aC5QSSAqIDIsIGZhbHNlKTtcbiAgICBjdHghLmZpbGwoKTtcbiAgICBjdHghLnJlc3RvcmUoKTtcblxuICAgIGxldCBjaGFuZ2VPY2N1cnJlZCA9IGZhbHNlO1xuICAgIHRoaXMucGFyYW1ldGVycy5zaGFwZXMgPSB0aGlzLnBhcmFtZXRlcnMuc2hhcGVzXG4gICAgICAubWFwKChzaGFwZTogYW55KSA9PiB7XG4gICAgICAgIGlmIChzaGFwZS50eXBlID09PSAnZnJlZWhhbmQnKSB7XG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIC4uLnNoYXBlLFxuICAgICAgICAgICAgcG9pbnRzOiBzaGFwZS5wb2ludHMuZmlsdGVyKChwb2ludDogYW55KSA9PiB7XG4gICAgICAgICAgICAgIGNvbnN0IGRpc3RhbmNlID0gTWF0aC5zcXJ0KE1hdGgucG93KHBvaW50LnggLSB4LCAyKSArIE1hdGgucG93KHBvaW50LnkgLSB5LCAyKSk7XG4gICAgICAgICAgICAgIGlmIChkaXN0YW5jZSA8PSB0aGlzLmVyYXNlclRoaWNrbmVzcyAvIDIpIHtcbiAgICAgICAgICAgICAgICBjaGFuZ2VPY2N1cnJlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIHJldHVybiBkaXN0YW5jZSA+IHRoaXMuZXJhc2VyVGhpY2tuZXNzIC8gMjtcbiAgICAgICAgICAgIH0pLFxuICAgICAgICAgIH07XG4gICAgICAgIH0gZWxzZSBpZiAoc2hhcGUudHlwZSA9PT0gJ2xpbmUnKSB7XG4gICAgICAgICAgaWYgKFxuICAgICAgICAgICAgdGhpcy5pc1BvaW50TmVhckxpbmUoXG4gICAgICAgICAgICAgIHgsXG4gICAgICAgICAgICAgIHksXG4gICAgICAgICAgICAgIHNoYXBlLngxLFxuICAgICAgICAgICAgICBzaGFwZS55MSxcbiAgICAgICAgICAgICAgc2hhcGUueDIsXG4gICAgICAgICAgICAgIHNoYXBlLnkyLFxuICAgICAgICAgICAgICB0aGlzLmVyYXNlclRoaWNrbmVzcyAvIDIsXG4gICAgICAgICAgICApXG4gICAgICAgICAgKSB7XG4gICAgICAgICAgICBjaGFuZ2VPY2N1cnJlZCA9IHRydWU7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAoc2hhcGUudHlwZSA9PT0gJ3RleHQnKSB7XG4gICAgICAgICAgY29uc3QgdGV4dFdpZHRoID0gY3R4IS5tZWFzdXJlVGV4dChzaGFwZS50ZXh0KS53aWR0aDtcbiAgICAgICAgICBpZiAoXG4gICAgICAgICAgICB4ID4gc2hhcGUueCAmJlxuICAgICAgICAgICAgeCA8IHNoYXBlLnggKyB0ZXh0V2lkdGggJiZcbiAgICAgICAgICAgIHkgPiBzaGFwZS55IC0gc2hhcGUuZm9udFNpemUgJiZcbiAgICAgICAgICAgIHkgPCBzaGFwZS55XG4gICAgICAgICAgKSB7XG4gICAgICAgICAgICBjaGFuZ2VPY2N1cnJlZCA9IHRydWU7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAoc2hhcGUudHlwZSA9PT0gJ2ltYWdlJykge1xuICAgICAgICAgIGlmICh4ID4gc2hhcGUueDEgJiYgeCA8IHNoYXBlLngyICYmIHkgPiBzaGFwZS55MSAmJiB5IDwgc2hhcGUueTIpIHtcbiAgICAgICAgICAgIGNoYW5nZU9jY3VycmVkID0gdHJ1ZTtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBpZiAoeCA+IHNoYXBlLngxICYmIHggPCBzaGFwZS54MiAmJiB5ID4gc2hhcGUueTEgJiYgeSA8IHNoYXBlLnkyKSB7XG4gICAgICAgICAgICBjaGFuZ2VPY2N1cnJlZCA9IHRydWU7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHNoYXBlO1xuICAgICAgfSlcbiAgICAgIC5maWx0ZXIoKHNoYXBlOiBhbnkpID0+IHNoYXBlICYmIChzaGFwZS50eXBlICE9PSAnZnJlZWhhbmQnIHx8IHNoYXBlLnBvaW50cy5sZW5ndGggPiAwKSk7XG4gICAgdGhpcy5wYXJhbWV0ZXJzLnVwZGF0ZVNoYXBlcyh0aGlzLnBhcmFtZXRlcnMuc2hhcGVzKTtcblxuICAgIHRoaXMuZHJhd1NoYXBlcygpO1xuICAgIGlmIChjaGFuZ2VPY2N1cnJlZCkge1xuICAgICAgdGhpcy5wYXJhbWV0ZXJzLnNvY2tldC5lbWl0KFxuICAgICAgICAndXBkYXRlQm9hcmRBY3Rpb24nLFxuICAgICAgICB7IGFjdGlvbjogJ3NoYXBlcycsIHBheWxvYWQ6IHsgc2hhcGVzOiB0aGlzLnBhcmFtZXRlcnMuc2hhcGVzIH0gfSxcbiAgICAgICAgdGhpcy5oYW5kbGVTZXJ2ZXJSZXNwb25zZSxcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgaXNQb2ludE5lYXJMaW5lKFxuICAgIHB4OiBudW1iZXIsXG4gICAgcHk6IG51bWJlcixcbiAgICB4MTogbnVtYmVyLFxuICAgIHkxOiBudW1iZXIsXG4gICAgeDI6IG51bWJlcixcbiAgICB5MjogbnVtYmVyLFxuICAgIHRocmVzaG9sZDogbnVtYmVyLFxuICApOiBib29sZWFuIHtcbiAgICBjb25zdCBkeCA9IHgyIC0geDE7XG4gICAgY29uc3QgZHkgPSB5MiAtIHkxO1xuICAgIGNvbnN0IGxlbmd0aCA9IE1hdGguc3FydChkeCAqIGR4ICsgZHkgKiBkeSk7XG4gICAgY29uc3QgZG90ID0gKChweCAtIHgxKSAqIGR4ICsgKHB5IC0geTEpICogZHkpIC8gKGxlbmd0aCAqIGxlbmd0aCk7XG4gICAgY29uc3QgY2xvc2VzdFggPSB4MSArIGRvdCAqIGR4O1xuICAgIGNvbnN0IGNsb3Nlc3RZID0geTEgKyBkb3QgKiBkeTtcbiAgICBjb25zdCBkaXN0YW5jZSA9IE1hdGguc3FydChNYXRoLnBvdyhweCAtIGNsb3Nlc3RYLCAyKSArIE1hdGgucG93KHB5IC0gY2xvc2VzdFksIDIpKTtcbiAgICByZXR1cm4gZGlzdGFuY2UgPD0gdGhyZXNob2xkO1xuICB9XG5cbiAgem9vbUNhbnZhcyhcbiAgICBzY2FsZUZhY3RvcjogbnVtYmVyLFxuICAgIGV2ZW50OiBNb3VzZUV2ZW50ID0ge1xuICAgICAgY2xpZW50WDogdGhpcy5jYW52YXNSZWYubmF0aXZlRWxlbWVudC53aWR0aCAvIDIsXG4gICAgICBjbGllbnRZOiB0aGlzLmNhbnZhc1JlZi5uYXRpdmVFbGVtZW50LmhlaWdodCAvIDIsXG4gICAgfSBhcyBNb3VzZUV2ZW50LFxuICApIHtcbiAgICBjb25zdCBjYW52YXMgPSB0aGlzLmNhbnZhc1JlZi5uYXRpdmVFbGVtZW50O1xuICAgIGNvbnN0IGN0eCA9IGNhbnZhcy5nZXRDb250ZXh0KCcyZCcpO1xuICAgIGlmIChzY2FsZUZhY3RvciA9PT0gMTApIHtcbiAgICAgIHRoaXMuc2NhbGUgPSAxO1xuICAgICAgdGhpcy5wYW5YID0gMDtcbiAgICAgIHRoaXMucGFuWSA9IDA7XG4gICAgfSBlbHNlIHtcbiAgICAgIGxldCBuZXdTY2FsZSA9IHRoaXMuc2NhbGUgKiBzY2FsZUZhY3RvcjtcbiAgICAgIGlmIChuZXdTY2FsZSA8IHRoaXMubWluU2NhbGUpIHtcbiAgICAgICAgbmV3U2NhbGUgPSB0aGlzLm1pblNjYWxlO1xuICAgICAgfSBlbHNlIGlmIChuZXdTY2FsZSA+IHRoaXMubWF4U2NhbGUpIHtcbiAgICAgICAgbmV3U2NhbGUgPSB0aGlzLm1heFNjYWxlO1xuICAgICAgfVxuXG4gICAgICBjb25zdCByZWN0ID0gY2FudmFzLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgY29uc3Qgb2Zmc2V0WCA9IChldmVudC5jbGllbnRYIC0gcmVjdC5sZWZ0KSAvIHJlY3Qud2lkdGg7XG4gICAgICBjb25zdCBvZmZzZXRZID0gKGV2ZW50LmNsaWVudFkgLSByZWN0LnRvcCkgLyByZWN0LmhlaWdodDtcblxuICAgICAgY29uc3QgZHggPSBvZmZzZXRYICogY2FudmFzLndpZHRoICogKDEgLSBzY2FsZUZhY3Rvcik7XG4gICAgICBjb25zdCBkeSA9IG9mZnNldFkgKiBjYW52YXMuaGVpZ2h0ICogKDEgLSBzY2FsZUZhY3Rvcik7XG5cbiAgICAgIHRoaXMuc2NhbGUgPSBuZXdTY2FsZTtcbiAgICAgIHRoaXMucGFuWCA9IHRoaXMucGFuWCAqIHNjYWxlRmFjdG9yICsgZHg7XG4gICAgICB0aGlzLnBhblkgPSB0aGlzLnBhblkgKiBzY2FsZUZhY3RvciArIGR5O1xuXG4gICAgICBjb25zdCBtYXhQYW5YID0gKGNhbnZhcy53aWR0aCAqICh0aGlzLnNjYWxlIC0gMSkpIC8gdGhpcy5zY2FsZTtcbiAgICAgIGNvbnN0IG1heFBhblkgPSAoY2FudmFzLmhlaWdodCAqICh0aGlzLnNjYWxlIC0gMSkpIC8gdGhpcy5zY2FsZTtcbiAgICAgIHRoaXMucGFuWCA9IE1hdGgubWluKE1hdGgubWF4KHRoaXMucGFuWCwgLW1heFBhblgpLCAwKTtcbiAgICAgIHRoaXMucGFuWSA9IE1hdGgubWluKE1hdGgubWF4KHRoaXMucGFuWSwgLW1heFBhblkpLCAwKTtcbiAgICB9XG5cbiAgICBjdHghLnNldFRyYW5zZm9ybSh0aGlzLnNjYWxlLCAwLCAwLCB0aGlzLnNjYWxlLCB0aGlzLnBhblgsIHRoaXMucGFuWSk7XG4gICAgdGhpcy5kcmF3U2hhcGVzKCk7XG4gIH1cblxuICBoYW5kbGVab29tKGU6IFdoZWVsRXZlbnQpIHtcbiAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgaWYgKGUuZGVsdGFZIDwgMCkge1xuICAgICAgdGhpcy56b29tQ2FudmFzKDEuMiwgZSBhcyBhbnkpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnpvb21DYW52YXMoMC44LCBlIGFzIGFueSk7XG4gICAgfVxuICB9XG5cbiAgZHJhd0VkZ2VNYXJrZXJzKCkge1xuICAgIGNvbnN0IGN0eCA9IHRoaXMuY2FudmFzUmVmLm5hdGl2ZUVsZW1lbnQuZ2V0Q29udGV4dCgnMmQnKTtcbiAgICBjdHghLnNhdmUoKTtcbiAgICBjdHghLnNldFRyYW5zZm9ybSgxLCAwLCAwLCAxLCAwLCAwKTtcbiAgICBjdHghLnN0cm9rZVN0eWxlID0gJ3JlZCc7XG4gICAgY3R4IS5saW5lV2lkdGggPSA1O1xuICAgIGN0eCEuc2V0TGluZURhc2goW10pOyAvLyByZXNldCBsaW5lIGRhc2hcblxuICAgIGNvbnN0IG1hcmtlckxlbmd0aCA9IDIwO1xuICAgIGNvbnN0IHRvcExlZnRYID0gdGhpcy5wYW5YO1xuICAgIGNvbnN0IHRvcExlZnRZID0gdGhpcy5wYW5ZO1xuICAgIGNvbnN0IGJvdHRvbVJpZ2h0WCA9IHRoaXMucGFuWCArIDEyODAgKiB0aGlzLnNjYWxlO1xuICAgIGNvbnN0IGJvdHRvbVJpZ2h0WSA9IHRoaXMucGFuWSArIDcyMCAqIHRoaXMuc2NhbGU7XG5cbiAgICBjdHghLmJlZ2luUGF0aCgpO1xuICAgIGN0eCEubW92ZVRvKHRvcExlZnRYLCB0b3BMZWZ0WSArIG1hcmtlckxlbmd0aCk7XG4gICAgY3R4IS5saW5lVG8odG9wTGVmdFgsIHRvcExlZnRZKTtcbiAgICBjdHghLmxpbmVUbyh0b3BMZWZ0WCArIG1hcmtlckxlbmd0aCwgdG9wTGVmdFkpO1xuICAgIGN0eCEuc3Ryb2tlKCk7XG5cbiAgICBjdHghLmJlZ2luUGF0aCgpO1xuICAgIGN0eCEubW92ZVRvKGJvdHRvbVJpZ2h0WCAtIG1hcmtlckxlbmd0aCwgdG9wTGVmdFkpO1xuICAgIGN0eCEubGluZVRvKGJvdHRvbVJpZ2h0WCwgdG9wTGVmdFkpO1xuICAgIGN0eCEubGluZVRvKGJvdHRvbVJpZ2h0WCwgdG9wTGVmdFkgKyBtYXJrZXJMZW5ndGgpO1xuICAgIGN0eCEuc3Ryb2tlKCk7XG5cbiAgICBjdHghLmJlZ2luUGF0aCgpO1xuICAgIGN0eCEubW92ZVRvKGJvdHRvbVJpZ2h0WCwgYm90dG9tUmlnaHRZIC0gbWFya2VyTGVuZ3RoKTtcbiAgICBjdHghLmxpbmVUbyhib3R0b21SaWdodFgsIGJvdHRvbVJpZ2h0WSk7XG4gICAgY3R4IS5saW5lVG8oYm90dG9tUmlnaHRYIC0gbWFya2VyTGVuZ3RoLCBib3R0b21SaWdodFkpO1xuICAgIGN0eCEuc3Ryb2tlKCk7XG5cbiAgICBjdHghLmJlZ2luUGF0aCgpO1xuICAgIGN0eCEubW92ZVRvKHRvcExlZnRYICsgbWFya2VyTGVuZ3RoLCBib3R0b21SaWdodFkpO1xuICAgIGN0eCEubGluZVRvKHRvcExlZnRYLCBib3R0b21SaWdodFkpO1xuICAgIGN0eCEubGluZVRvKHRvcExlZnRYLCBib3R0b21SaWdodFkgLSBtYXJrZXJMZW5ndGgpO1xuICAgIGN0eCEuc3Ryb2tlKCk7XG5cbiAgICBjdHghLnJlc3RvcmUoKTtcbiAgfVxuXG4gIGRyYXdTaGFwZXMoKSB7XG4gICAgY29uc3QgY2FudmFzID0gdGhpcy5jYW52YXNSZWYubmF0aXZlRWxlbWVudDtcbiAgICBjb25zdCBjdHggPSBjYW52YXMuZ2V0Q29udGV4dCgnMmQnKTtcbiAgICBjdHghLmNsZWFyUmVjdCgwLCAwLCBjYW52YXMud2lkdGgsIGNhbnZhcy5oZWlnaHQpO1xuICAgIGN0eCEuc2F2ZSgpO1xuICAgIGN0eCEuc2V0VHJhbnNmb3JtKHRoaXMuc2NhbGUsIDAsIDAsIHRoaXMuc2NhbGUsIHRoaXMucGFuWCwgdGhpcy5wYW5ZKTtcbiAgICBpZiAodGhpcy5wYXJhbWV0ZXJzLnVzZUltYWdlQmFja2dyb3VuZCkge1xuICAgICAgY3R4IS5kcmF3SW1hZ2UoXG4gICAgICAgIHRoaXMuYmFja2dyb3VuZEltYWdlLFxuICAgICAgICAtdGhpcy5wYW5YIC8gdGhpcy5zY2FsZSxcbiAgICAgICAgLXRoaXMucGFuWSAvIHRoaXMuc2NhbGUsXG4gICAgICAgIGNhbnZhcy53aWR0aCAvIHRoaXMuc2NhbGUsXG4gICAgICAgIGNhbnZhcy5oZWlnaHQgLyB0aGlzLnNjYWxlLFxuICAgICAgKTtcbiAgICB9IGVsc2Uge1xuICAgICAgY3R4IS5maWxsU3R5bGUgPSAnI2ZmZic7XG4gICAgICBjdHghLmZpbGxSZWN0KFxuICAgICAgICAtdGhpcy5wYW5YIC8gdGhpcy5zY2FsZSxcbiAgICAgICAgLXRoaXMucGFuWSAvIHRoaXMuc2NhbGUsXG4gICAgICAgIGNhbnZhcy53aWR0aCAvIHRoaXMuc2NhbGUsXG4gICAgICAgIGNhbnZhcy5oZWlnaHQgLyB0aGlzLnNjYWxlLFxuICAgICAgKTtcbiAgICB9XG4gICAgdGhpcy5wYXJhbWV0ZXJzLnNoYXBlcy5mb3JFYWNoKChzaGFwZTogYW55KSA9PiB7XG4gICAgICBpZiAoc2hhcGUudHlwZSA9PT0gJ2xpbmUnKSB7XG4gICAgICAgIHRoaXMuZHJhd0xpbmUoXG4gICAgICAgICAgc2hhcGUueDEsXG4gICAgICAgICAgc2hhcGUueTEsXG4gICAgICAgICAgc2hhcGUueDIsXG4gICAgICAgICAgc2hhcGUueTIsXG4gICAgICAgICAgc2hhcGUuY29sb3IsXG4gICAgICAgICAgc2hhcGUudGhpY2tuZXNzLFxuICAgICAgICAgIHNoYXBlLmxpbmVUeXBlLFxuICAgICAgICApO1xuICAgICAgfSBlbHNlIGlmIChzaGFwZS50eXBlID09PSAnZnJlZWhhbmQnKSB7XG4gICAgICAgIHRoaXMuZHJhd0ZyZWVoYW5kKHNoYXBlLnBvaW50cywgc2hhcGUuY29sb3IsIHNoYXBlLnRoaWNrbmVzcyk7XG4gICAgICB9IGVsc2UgaWYgKHNoYXBlLnR5cGUgPT09ICd0ZXh0Jykge1xuICAgICAgICBjdHghLmZvbnQgPSBgJHtzaGFwZS5mb250U2l6ZX1weCAke3NoYXBlLmZvbnR9YDtcbiAgICAgICAgY3R4IS5maWxsU3R5bGUgPSBzaGFwZS5jb2xvcjtcbiAgICAgICAgY3R4IS5maWxsVGV4dChzaGFwZS50ZXh0LCBzaGFwZS54LCBzaGFwZS55KTtcbiAgICAgIH0gZWxzZSBpZiAoc2hhcGUudHlwZSA9PT0gJ2ltYWdlJykge1xuICAgICAgICBjdHghLmRyYXdJbWFnZShzaGFwZS5pbWcsIHNoYXBlLngxLCBzaGFwZS55MSwgc2hhcGUueDIgLSBzaGFwZS54MSwgc2hhcGUueTIgLSBzaGFwZS55MSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLmRyYXdTaGFwZShcbiAgICAgICAgICBzaGFwZS50eXBlLFxuICAgICAgICAgIHNoYXBlLngxLFxuICAgICAgICAgIHNoYXBlLnkxLFxuICAgICAgICAgIHNoYXBlLngyLFxuICAgICAgICAgIHNoYXBlLnkyLFxuICAgICAgICAgIHNoYXBlLmNvbG9yLFxuICAgICAgICAgIHNoYXBlLnRoaWNrbmVzcyxcbiAgICAgICAgICBzaGFwZS5saW5lVHlwZSxcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICBjdHghLnJlc3RvcmUoKTtcbiAgICB0aGlzLmRyYXdFZGdlTWFya2VycygpO1xuICB9XG5cbiAgZHJhd0xpbmUoXG4gICAgeDE6IG51bWJlcixcbiAgICB5MTogbnVtYmVyLFxuICAgIHgyOiBudW1iZXIsXG4gICAgeTI6IG51bWJlcixcbiAgICBjb2xvcjogc3RyaW5nLFxuICAgIHRoaWNrbmVzczogbnVtYmVyLFxuICAgIGxpbmVUeXBlOiBzdHJpbmcsXG4gICkge1xuICAgIGNvbnN0IGN0eCA9IHRoaXMuY2FudmFzUmVmLm5hdGl2ZUVsZW1lbnQuZ2V0Q29udGV4dCgnMmQnKTtcbiAgICBjdHghLmJlZ2luUGF0aCgpO1xuICAgIGN0eCEuc3Ryb2tlU3R5bGUgPSBjb2xvcjtcbiAgICBjdHghLmxpbmVXaWR0aCA9IHRoaWNrbmVzcztcbiAgICBpZiAobGluZVR5cGUgPT09ICdkYXNoZWQnKSB7XG4gICAgICBjdHghLnNldExpbmVEYXNoKFsxMCwgMTBdKTtcbiAgICB9IGVsc2UgaWYgKGxpbmVUeXBlID09PSAnZG90dGVkJykge1xuICAgICAgY3R4IS5zZXRMaW5lRGFzaChbMiwgMTBdKTtcbiAgICB9IGVsc2UgaWYgKGxpbmVUeXBlID09PSAnZGFzaERvdCcpIHtcbiAgICAgIGN0eCEuc2V0TGluZURhc2goWzEwLCA1LCAyLCA1XSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGN0eCEuc2V0TGluZURhc2goW10pO1xuICAgIH1cbiAgICBjdHghLm1vdmVUbyh4MSwgeTEpO1xuICAgIGN0eCEubGluZVRvKHgyLCB5Mik7XG4gICAgY3R4IS5zdHJva2UoKTtcbiAgICBjdHghLnNldExpbmVEYXNoKFtdKTtcbiAgfVxuXG4gIGRyYXdUZXh0KHRleHQ6IHN0cmluZywgeDogbnVtYmVyLCB5OiBudW1iZXIsIGNvbG9yOiBzdHJpbmcsIGZvbnQ6IHN0cmluZykge1xuICAgIGNvbnN0IGN0eCA9IHRoaXMuY2FudmFzUmVmLm5hdGl2ZUVsZW1lbnQuZ2V0Q29udGV4dCgnMmQnKTtcbiAgICBjdHghLmZvbnQgPSBgMjBweCAke2ZvbnR9YDtcbiAgICBjdHghLmZpbGxTdHlsZSA9IGNvbG9yO1xuICAgIGN0eCEuZmlsbFRleHQodGV4dCwgeCwgeSk7XG4gIH1cblxuICBkcmF3RnJlZWhhbmQocG9pbnRzOiB7IHg6IG51bWJlcjsgeTogbnVtYmVyIH1bXSwgY29sb3I6IHN0cmluZywgdGhpY2tuZXNzOiBudW1iZXIpIHtcbiAgICBjb25zdCBjdHggPSB0aGlzLmNhbnZhc1JlZi5uYXRpdmVFbGVtZW50LmdldENvbnRleHQoJzJkJyk7XG4gICAgaWYgKHBvaW50cy5sZW5ndGggPCAyKSByZXR1cm47XG4gICAgY3R4IS5zdHJva2VTdHlsZSA9IGNvbG9yO1xuICAgIGN0eCEubGluZVdpZHRoID0gdGhpY2tuZXNzO1xuICAgIGN0eCEuYmVnaW5QYXRoKCk7XG4gICAgY3R4IS5tb3ZlVG8ocG9pbnRzWzBdLngsIHBvaW50c1swXS55KTtcbiAgICBmb3IgKGxldCBpID0gMTsgaSA8IHBvaW50cy5sZW5ndGg7IGkrKykge1xuICAgICAgY3R4IS5saW5lVG8ocG9pbnRzW2ldLngsIHBvaW50c1tpXS55KTtcbiAgICB9XG4gICAgY3R4IS5zdHJva2UoKTtcbiAgfVxuXG4gIGRyYXdTaGFwZShcbiAgICB0eXBlOiBzdHJpbmcsXG4gICAgeDE6IG51bWJlcixcbiAgICB5MTogbnVtYmVyLFxuICAgIHgyOiBudW1iZXIsXG4gICAgeTI6IG51bWJlcixcbiAgICBjb2xvcjogc3RyaW5nLFxuICAgIHRoaWNrbmVzczogbnVtYmVyLFxuICAgIGxpbmVUeXBlOiBzdHJpbmcsXG4gICAgY3R4OiBDYW52YXNSZW5kZXJpbmdDb250ZXh0MkQgPSB0aGlzLmNhbnZhc1JlZi5uYXRpdmVFbGVtZW50LmdldENvbnRleHQoJzJkJykhLFxuICApIHtcbiAgICBjdHguYmVnaW5QYXRoKCk7XG4gICAgY3R4LnN0cm9rZVN0eWxlID0gY29sb3I7XG4gICAgY3R4LmxpbmVXaWR0aCA9IHRoaWNrbmVzcztcbiAgICBpZiAobGluZVR5cGUgPT09ICdkYXNoZWQnKSB7XG4gICAgICBjdHguc2V0TGluZURhc2goWzEwLCAxMF0pO1xuICAgIH0gZWxzZSBpZiAobGluZVR5cGUgPT09ICdkb3R0ZWQnKSB7XG4gICAgICBjdHguc2V0TGluZURhc2goWzIsIDEwXSk7XG4gICAgfSBlbHNlIGlmIChsaW5lVHlwZSA9PT0gJ2Rhc2hEb3QnKSB7XG4gICAgICBjdHguc2V0TGluZURhc2goWzEwLCA1LCAyLCA1XSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGN0eC5zZXRMaW5lRGFzaChbXSk7XG4gICAgfVxuICAgIGlmICh0eXBlID09PSAncmVjdGFuZ2xlJykge1xuICAgICAgY3R4LnN0cm9rZVJlY3QoeDEsIHkxLCB4MiAtIHgxLCB5MiAtIHkxKTtcbiAgICB9IGVsc2UgaWYgKHR5cGUgPT09ICdjaXJjbGUnKSB7XG4gICAgICBjb25zdCByYWRpdXMgPSBNYXRoLnNxcnQoTWF0aC5wb3coeDIgLSB4MSwgMikgKyBNYXRoLnBvdyh5MiAtIHkxLCAyKSk7XG4gICAgICBjdHguYXJjKHgxLCB5MSwgcmFkaXVzLCAwLCAyICogTWF0aC5QSSk7XG4gICAgICBjdHguc3Ryb2tlKCk7XG4gICAgfSBlbHNlIGlmICh0eXBlID09PSAncmhvbWJ1cycpIHtcbiAgICAgIGNvbnN0IGNlbnRlclggPSAoeDEgKyB4MikgLyAyO1xuICAgICAgY29uc3QgY2VudGVyWSA9ICh5MSArIHkyKSAvIDI7XG4gICAgICBjdHgubW92ZVRvKGNlbnRlclgsIHkxKTtcbiAgICAgIGN0eC5saW5lVG8oeDIsIGNlbnRlclkpO1xuICAgICAgY3R4LmxpbmVUbyhjZW50ZXJYLCB5Mik7XG4gICAgICBjdHgubGluZVRvKHgxLCBjZW50ZXJZKTtcbiAgICAgIGN0eC5jbG9zZVBhdGgoKTtcbiAgICAgIGN0eC5zdHJva2UoKTtcbiAgICB9IGVsc2UgaWYgKHR5cGUgPT09ICdwZW50YWdvbicpIHtcbiAgICAgIHRoaXMuZHJhd1BvbHlnb24oY3R4LCA1LCB4MSwgeTEsIHgyLCB5Mik7XG4gICAgfSBlbHNlIGlmICh0eXBlID09PSAnaGV4YWdvbicpIHtcbiAgICAgIHRoaXMuZHJhd1BvbHlnb24oY3R4LCA2LCB4MSwgeTEsIHgyLCB5Mik7XG4gICAgfSBlbHNlIGlmICh0eXBlID09PSAndHJpYW5nbGUnKSB7XG4gICAgICBjb25zdCBjZW50ZXJYID0gKHgxICsgeDIpIC8gMjtcbiAgICAgIGN0eC5tb3ZlVG8oY2VudGVyWCwgeTEpO1xuICAgICAgY3R4LmxpbmVUbyh4MiwgeTIpO1xuICAgICAgY3R4LmxpbmVUbyh4MSwgeTIpO1xuICAgICAgY3R4LmNsb3NlUGF0aCgpO1xuICAgICAgY3R4LnN0cm9rZSgpO1xuICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gJ3NxdWFyZScpIHtcbiAgICAgIGN0eC5zdHJva2VSZWN0KHgxLCB5MSwgeDIgLSB4MSwgeDIgLSB4MSk7XG4gICAgfSBlbHNlIGlmICh0eXBlID09PSAnb2N0YWdvbicpIHtcbiAgICAgIHRoaXMuZHJhd1BvbHlnb24oY3R4LCA4LCB4MSwgeTEsIHgyLCB5Mik7XG4gICAgfSBlbHNlIGlmICh0eXBlID09PSAnb3ZhbCcpIHtcbiAgICAgIGNvbnN0IHJhZGl1c1ggPSBNYXRoLmFicyh4MiAtIHgxKSAvIDI7XG4gICAgICBjb25zdCByYWRpdXNZID0gTWF0aC5hYnMoeTIgLSB5MSkgLyAyO1xuICAgICAgY29uc3QgY2VudGVyWCA9ICh4MSArIHgyKSAvIDI7XG4gICAgICBjb25zdCBjZW50ZXJZID0gKHkxICsgeTIpIC8gMjtcbiAgICAgIGN0eC5lbGxpcHNlKGNlbnRlclgsIGNlbnRlclksIHJhZGl1c1gsIHJhZGl1c1ksIDAsIDAsIDIgKiBNYXRoLlBJKTtcbiAgICAgIGN0eC5zdHJva2UoKTtcbiAgICB9IGVsc2UgaWYgKHR5cGUgPT09ICdwYXJhbGxlbG9ncmFtJykge1xuICAgICAgY29uc3QgY2VudGVyWCA9ICh4MSArIHgyKSAvIDI7XG4gICAgICBjdHgubW92ZVRvKGNlbnRlclgsIHkxKTtcbiAgICAgIGN0eC5saW5lVG8oeDIsIHkyKTtcbiAgICAgIGN0eC5saW5lVG8oY2VudGVyWCwgeTIpO1xuICAgICAgY3R4LmxpbmVUbyh4MSwgeTEpO1xuICAgICAgY3R4LmNsb3NlUGF0aCgpO1xuICAgICAgY3R4LnN0cm9rZSgpO1xuICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gJ2ltYWdlJykge1xuICAgICAgY3R4LmRyYXdJbWFnZSh0aGlzLnNoYXBlLmltZywgeDEsIHkxLCB4MiAtIHgxLCB5MiAtIHkxKTtcbiAgICB9XG4gIH1cblxuICBkcmF3UG9seWdvbihcbiAgICBjdHg6IENhbnZhc1JlbmRlcmluZ0NvbnRleHQyRCxcbiAgICBzaWRlczogbnVtYmVyLFxuICAgIHgxOiBudW1iZXIsXG4gICAgeTE6IG51bWJlcixcbiAgICB4MjogbnVtYmVyLFxuICAgIHkyOiBudW1iZXIsXG4gICkge1xuICAgIGNvbnN0IGNlbnRlclggPSAoeDEgKyB4MikgLyAyO1xuICAgIGNvbnN0IGNlbnRlclkgPSAoeTEgKyB5MikgLyAyO1xuICAgIGNvbnN0IHJhZGl1cyA9IE1hdGgubWluKE1hdGguYWJzKHgyIC0geDEpLCBNYXRoLmFicyh5MiAtIHkxKSkgLyAyO1xuICAgIGNvbnN0IGFuZ2xlID0gKDIgKiBNYXRoLlBJKSAvIHNpZGVzO1xuICAgIGN0eC5iZWdpblBhdGgoKTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNpZGVzOyBpKyspIHtcbiAgICAgIGNvbnN0IHggPSBjZW50ZXJYICsgcmFkaXVzICogTWF0aC5jb3MoaSAqIGFuZ2xlIC0gTWF0aC5QSSAvIDIpO1xuICAgICAgY29uc3QgeSA9IGNlbnRlclkgKyByYWRpdXMgKiBNYXRoLnNpbihpICogYW5nbGUgLSBNYXRoLlBJIC8gMik7XG4gICAgICBpZiAoaSA9PT0gMCkge1xuICAgICAgICBjdHgubW92ZVRvKHgsIHkpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY3R4LmxpbmVUbyh4LCB5KTtcbiAgICAgIH1cbiAgICB9XG4gICAgY3R4LmNsb3NlUGF0aCgpO1xuICAgIGN0eC5zdHJva2UoKTtcbiAgfVxuXG4gIHVuZG8oKSB7XG4gICAgaWYgKHRoaXMucGFyYW1ldGVycy5zaGFwZXMubGVuZ3RoID4gMCkge1xuICAgICAgdGhpcy5wYXJhbWV0ZXJzLnJlZG9TdGFjay5wdXNoKHRoaXMucGFyYW1ldGVycy5zaGFwZXMucG9wKCkhKTtcbiAgICAgIHRoaXMucGFyYW1ldGVycy51cGRhdGVSZWRvU3RhY2sodGhpcy5wYXJhbWV0ZXJzLnJlZG9TdGFjayk7XG4gICAgICB0aGlzLmRyYXdTaGFwZXMoKTtcbiAgICAgIHRoaXMucGFyYW1ldGVycy5zb2NrZXQuZW1pdChcbiAgICAgICAgJ3VwZGF0ZUJvYXJkQWN0aW9uJyxcbiAgICAgICAgeyBhY3Rpb246ICd1bmRvJyB9LFxuICAgICAgICB0aGlzLmhhbmRsZVNlcnZlclJlc3BvbnNlLFxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICByZWRvKCkge1xuICAgIGlmICh0aGlzLnBhcmFtZXRlcnMucmVkb1N0YWNrLmxlbmd0aCA+IDApIHtcbiAgICAgIHRoaXMucGFyYW1ldGVycy5zaGFwZXMucHVzaCh0aGlzLnBhcmFtZXRlcnMucmVkb1N0YWNrLnBvcCgpISk7XG4gICAgICB0aGlzLnBhcmFtZXRlcnMudXBkYXRlU2hhcGVzKHRoaXMucGFyYW1ldGVycy5zaGFwZXMpO1xuICAgICAgdGhpcy5kcmF3U2hhcGVzKCk7XG4gICAgICB0aGlzLnBhcmFtZXRlcnMuc29ja2V0LmVtaXQoXG4gICAgICAgICd1cGRhdGVCb2FyZEFjdGlvbicsXG4gICAgICAgIHsgYWN0aW9uOiAncmVkbycgfSxcbiAgICAgICAgdGhpcy5oYW5kbGVTZXJ2ZXJSZXNwb25zZSxcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgc2F2ZVN0YXRlKCkge1xuICAgIHRoaXMucGFyYW1ldGVycy51bmRvU3RhY2sucHVzaChKU09OLnN0cmluZ2lmeSh0aGlzLnBhcmFtZXRlcnMuc2hhcGVzKSk7XG4gICAgdGhpcy5wYXJhbWV0ZXJzLnVwZGF0ZVVuZG9TdGFjayh0aGlzLnBhcmFtZXRlcnMudW5kb1N0YWNrKTtcbiAgfVxuXG4gIGZpbmRTaGFwZSh4OiBudW1iZXIsIHk6IG51bWJlcikge1xuICAgIHJldHVybiB0aGlzLnBhcmFtZXRlcnMuc2hhcGVzLmZpbmQoKHNoYXBlOiBhbnkpID0+IHtcbiAgICAgIGlmIChzaGFwZS50eXBlID09PSAnZnJlZWhhbmQnKSB7XG4gICAgICAgIHJldHVybiBzaGFwZS5wb2ludHMuc29tZSgocG9pbnQ6IGFueSkgPT4ge1xuICAgICAgICAgIGNvbnN0IGRpc3RhbmNlID0gTWF0aC5zcXJ0KE1hdGgucG93KHBvaW50LnggLSB4LCAyKSArIE1hdGgucG93KHBvaW50LnkgLSB5LCAyKSk7XG4gICAgICAgICAgcmV0dXJuIGRpc3RhbmNlIDwgc2hhcGUudGhpY2tuZXNzO1xuICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSBpZiAoc2hhcGUudHlwZSA9PT0gJ3RleHQnKSB7XG4gICAgICAgIGNvbnN0IGN0eCA9IHRoaXMuY2FudmFzUmVmLm5hdGl2ZUVsZW1lbnQuZ2V0Q29udGV4dCgnMmQnKTtcbiAgICAgICAgY3R4IS5mb250ID0gYCR7c2hhcGUuZm9udFNpemV9cHggJHtzaGFwZS5mb250fWA7XG4gICAgICAgIGNvbnN0IHRleHRNZXRyaWNzID0gY3R4IS5tZWFzdXJlVGV4dChzaGFwZS50ZXh0KTtcbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICB4ID4gc2hhcGUueCAmJlxuICAgICAgICAgIHggPCBzaGFwZS54ICsgdGV4dE1ldHJpY3Mud2lkdGggJiZcbiAgICAgICAgICB5ID4gc2hhcGUueSAtIHNoYXBlLmZvbnRTaXplICYmXG4gICAgICAgICAgeSA8IHNoYXBlLnlcbiAgICAgICAgKTtcbiAgICAgIH0gZWxzZSBpZiAoc2hhcGUudHlwZSA9PT0gJ2ltYWdlJykge1xuICAgICAgICByZXR1cm4geCA+IHNoYXBlLngxICYmIHggPCBzaGFwZS54MiAmJiB5ID4gc2hhcGUueTEgJiYgeSA8IHNoYXBlLnkyO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIHggPiBzaGFwZS54MSAmJiB4IDwgc2hhcGUueDIgJiYgeSA+IHNoYXBlLnkxICYmIHkgPCBzaGFwZS55MjtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIGRyYXdTZWxlY3Rpb24oc2hhcGU6IGFueSkge1xuICAgIGNvbnN0IGN0eCA9IHRoaXMuY2FudmFzUmVmLm5hdGl2ZUVsZW1lbnQuZ2V0Q29udGV4dCgnMmQnKTtcbiAgICBpZiAoIXNoYXBlKSByZXR1cm47XG5cbiAgICBjb25zdCBoYW5kbGVzID0gdGhpcy5nZXRSZXNpemVIYW5kbGVzKHNoYXBlKTtcbiAgICBjdHghLnN0cm9rZVN0eWxlID0gJ3JlZCc7XG4gICAgY3R4IS5saW5lV2lkdGggPSAyO1xuICAgIGN0eCEuc2V0TGluZURhc2goWzYsIDNdKTtcbiAgICBpZiAoc2hhcGUudHlwZSA9PT0gJ2xpbmUnKSB7XG4gICAgICBjdHghLmJlZ2luUGF0aCgpO1xuICAgICAgY3R4IS5tb3ZlVG8oc2hhcGUueDEsIHNoYXBlLnkxKTtcbiAgICAgIGN0eCEubGluZVRvKHNoYXBlLngyLCBzaGFwZS55Mik7XG4gICAgICBjdHghLnN0cm9rZSgpO1xuICAgIH0gZWxzZSBpZiAoc2hhcGUudHlwZSA9PT0gJ2NpcmNsZScpIHtcbiAgICAgIGNvbnN0IHJhZGl1cyA9IE1hdGguc3FydChNYXRoLnBvdyhzaGFwZS54MiAtIHNoYXBlLngxLCAyKSArIE1hdGgucG93KHNoYXBlLnkyIC0gc2hhcGUueTEsIDIpKTtcbiAgICAgIGN0eCEuYmVnaW5QYXRoKCk7XG4gICAgICBjdHghLmFyYyhzaGFwZS54MSwgc2hhcGUueTEsIHJhZGl1cywgMCwgMiAqIE1hdGguUEkpO1xuICAgICAgY3R4IS5zdHJva2UoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgY3R4IS5zdHJva2VSZWN0KHNoYXBlLngxLCBzaGFwZS55MSwgc2hhcGUueDIgLSBzaGFwZS54MSwgc2hhcGUueTIgLSBzaGFwZS55MSk7XG4gICAgfVxuXG4gICAgY3R4IS5zZXRMaW5lRGFzaChbXSk7XG5cbiAgICBoYW5kbGVzLmZvckVhY2goKGhhbmRsZSkgPT4ge1xuICAgICAgY3R4IS5maWxsU3R5bGUgPSBoYW5kbGUuaXNDZW50ZXIgPyAnYmx1ZScgOiAncmVkJztcbiAgICAgIGN0eCEuZmlsbFJlY3QoaGFuZGxlLnggLSA2LCBoYW5kbGUueSAtIDYsIDEyLCAxMik7XG4gICAgfSk7XG4gIH1cblxuICBnZXRSZXNpemVIYW5kbGVzKHNoYXBlOiBhbnkpIHtcbiAgICBjb25zdCBoYW5kbGVzID0gW107XG4gICAgaWYgKHNoYXBlLnR5cGUgPT09ICdsaW5lJykge1xuICAgICAgaGFuZGxlcy5wdXNoKHsgeDogc2hhcGUueDEsIHk6IHNoYXBlLnkxIH0pO1xuICAgICAgaGFuZGxlcy5wdXNoKHsgeDogc2hhcGUueDIsIHk6IHNoYXBlLnkyIH0pO1xuICAgIH0gZWxzZSBpZiAoc2hhcGUudHlwZSA9PT0gJ2NpcmNsZScpIHtcbiAgICAgIGNvbnN0IHJhZGl1cyA9IE1hdGguc3FydChNYXRoLnBvdyhzaGFwZS54MiAtIHNoYXBlLngxLCAyKSArIE1hdGgucG93KHNoYXBlLnkyIC0gc2hhcGUueTEsIDIpKTtcbiAgICAgIGhhbmRsZXMucHVzaCh7IHg6IHNoYXBlLngxICsgcmFkaXVzLCB5OiBzaGFwZS55MSB9KTtcbiAgICAgIGhhbmRsZXMucHVzaCh7IHg6IHNoYXBlLngxIC0gcmFkaXVzLCB5OiBzaGFwZS55MSB9KTtcbiAgICAgIGhhbmRsZXMucHVzaCh7IHg6IHNoYXBlLngxLCB5OiBzaGFwZS55MSArIHJhZGl1cyB9KTtcbiAgICAgIGhhbmRsZXMucHVzaCh7IHg6IHNoYXBlLngxLCB5OiBzaGFwZS55MSAtIHJhZGl1cyB9KTtcbiAgICAgIGhhbmRsZXMucHVzaCh7IHg6IHNoYXBlLngxLCB5OiBzaGFwZS55MSwgaXNDZW50ZXI6IHRydWUgfSk7XG4gICAgfSBlbHNlIGlmIChzaGFwZS50eXBlID09PSAndGV4dCcpIHtcbiAgICAgIGNvbnN0IGN0eCA9IHRoaXMuY2FudmFzUmVmLm5hdGl2ZUVsZW1lbnQuZ2V0Q29udGV4dCgnMmQnKTtcbiAgICAgIGNvbnN0IHRleHRNZXRyaWNzID0gY3R4IS5tZWFzdXJlVGV4dChzaGFwZS50ZXh0KTtcbiAgICAgIGhhbmRsZXMucHVzaCh7IHg6IHNoYXBlLngsIHk6IHNoYXBlLnkgLSBzaGFwZS5mb250U2l6ZSwgaXNDZW50ZXI6IHRydWUgfSk7XG4gICAgICBoYW5kbGVzLnB1c2goeyB4OiBzaGFwZS54ICsgdGV4dE1ldHJpY3Mud2lkdGgsIHk6IHNoYXBlLnksIGlzQ2VudGVyOiBmYWxzZSB9KTtcbiAgICB9IGVsc2UgaWYgKHNoYXBlLnR5cGUgPT09ICdpbWFnZScpIHtcbiAgICAgIGhhbmRsZXMucHVzaCh7IHg6IHNoYXBlLngxLCB5OiBzaGFwZS55MSB9KTtcbiAgICAgIGhhbmRsZXMucHVzaCh7IHg6IHNoYXBlLngyLCB5OiBzaGFwZS55MSB9KTtcbiAgICAgIGhhbmRsZXMucHVzaCh7IHg6IHNoYXBlLngyLCB5OiBzaGFwZS55MiB9KTtcbiAgICAgIGhhbmRsZXMucHVzaCh7IHg6IHNoYXBlLngxLCB5OiBzaGFwZS55MiB9KTtcbiAgICAgIGhhbmRsZXMucHVzaCh7IHg6IChzaGFwZS54MSArIHNoYXBlLngyKSAvIDIsIHk6IChzaGFwZS55MSArIHNoYXBlLnkyKSAvIDIsIGlzQ2VudGVyOiB0cnVlIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICBoYW5kbGVzLnB1c2goeyB4OiBzaGFwZS54MSwgeTogc2hhcGUueTEgfSk7XG4gICAgICBoYW5kbGVzLnB1c2goeyB4OiBzaGFwZS54MiwgeTogc2hhcGUueTEgfSk7XG4gICAgICBoYW5kbGVzLnB1c2goeyB4OiBzaGFwZS54MiwgeTogc2hhcGUueTIgfSk7XG4gICAgICBoYW5kbGVzLnB1c2goeyB4OiBzaGFwZS54MSwgeTogc2hhcGUueTIgfSk7XG4gICAgICBoYW5kbGVzLnB1c2goeyB4OiAoc2hhcGUueDEgKyBzaGFwZS54MikgLyAyLCB5OiAoc2hhcGUueTEgKyBzaGFwZS55MikgLyAyLCBpc0NlbnRlcjogdHJ1ZSB9KTtcbiAgICB9XG4gICAgcmV0dXJuIGhhbmRsZXMubWFwKChoYW5kbGUpID0+ICh7XG4gICAgICAuLi5oYW5kbGUsXG4gICAgICBpc0NlbnRlcjogaGFuZGxlLmlzQ2VudGVyIHx8IGZhbHNlLFxuICAgIH0pKTtcbiAgfVxuXG4gIGdldEhhbmRsZUF0UG9zaXRpb24oeDogbnVtYmVyLCB5OiBudW1iZXIpIHtcbiAgICBpZiAoIXRoaXMuc2VsZWN0ZWRTaGFwZSkgcmV0dXJuIG51bGw7XG4gICAgcmV0dXJuIHRoaXMuZ2V0UmVzaXplSGFuZGxlcyh0aGlzLnNlbGVjdGVkU2hhcGUpLmZpbmQoKGhhbmRsZSkgPT4ge1xuICAgICAgcmV0dXJuIE1hdGguYWJzKGhhbmRsZS54IC0geCkgPCA2ICYmIE1hdGguYWJzKGhhbmRsZS55IC0geSkgPCA2O1xuICAgIH0pO1xuICB9XG5cbiAgcmVzaXplU2hhcGUoc2hhcGU6IGFueSwgaGFuZGxlOiBhbnksIHg6IG51bWJlciwgeTogbnVtYmVyKSB7XG4gICAgaWYgKHNoYXBlLnR5cGUgPT09ICdsaW5lJykge1xuICAgICAgaWYgKGhhbmRsZS54ID09PSBzaGFwZS54MSAmJiBoYW5kbGUueSA9PT0gc2hhcGUueTEpIHtcbiAgICAgICAgc2hhcGUueDEgPSB4O1xuICAgICAgICBzaGFwZS55MSA9IHk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzaGFwZS54MiA9IHg7XG4gICAgICAgIHNoYXBlLnkyID0geTtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKHNoYXBlLnR5cGUgPT09ICdjaXJjbGUnKSB7XG4gICAgICBjb25zdCBkeCA9IHggLSBzaGFwZS54MTtcbiAgICAgIGNvbnN0IGR5ID0geSAtIHNoYXBlLnkxO1xuICAgICAgY29uc3QgcmFkaXVzID0gTWF0aC5zcXJ0KGR4ICogZHggKyBkeSAqIGR5KTtcbiAgICAgIHNoYXBlLngyID0gc2hhcGUueDEgKyByYWRpdXM7XG4gICAgICBzaGFwZS55MiA9IHNoYXBlLnkxO1xuICAgIH0gZWxzZSBpZiAoc2hhcGUudHlwZSA9PT0gJ3RleHQnKSB7XG4gICAgICBpZiAoaGFuZGxlLmlzQ2VudGVyKSB7XG4gICAgICAgIHNoYXBlLnggPSB4O1xuICAgICAgICBzaGFwZS55ID0geTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnN0IHRleHRNZXRyaWNzID0gdGhpcy5jYW52YXNSZWYubmF0aXZlRWxlbWVudC5nZXRDb250ZXh0KCcyZCcpIS5tZWFzdXJlVGV4dChzaGFwZS50ZXh0KTtcbiAgICAgICAgc2hhcGUueCA9IHggLSB0ZXh0TWV0cmljcy53aWR0aDtcbiAgICAgICAgc2hhcGUueSA9IHk7XG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChzaGFwZS50eXBlID09PSAnaW1hZ2UnKSB7XG4gICAgICBpZiAoaGFuZGxlLmlzQ2VudGVyKSB7XG4gICAgICAgIGNvbnN0IGR4ID0geCAtIChzaGFwZS54MSArIHNoYXBlLngyKSAvIDI7XG4gICAgICAgIGNvbnN0IGR5ID0geSAtIChzaGFwZS55MSArIHNoYXBlLnkyKSAvIDI7XG4gICAgICAgIHRoaXMubW92ZVNoYXBlKHNoYXBlLCBkeCwgZHkpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaWYgKGhhbmRsZS54ID09PSBzaGFwZS54MSAmJiBoYW5kbGUueSA9PT0gc2hhcGUueTEpIHtcbiAgICAgICAgICBzaGFwZS54MSA9IHg7XG4gICAgICAgICAgc2hhcGUueTEgPSB5O1xuICAgICAgICB9IGVsc2UgaWYgKGhhbmRsZS54ID09PSBzaGFwZS54MiAmJiBoYW5kbGUueSA9PT0gc2hhcGUueTEpIHtcbiAgICAgICAgICBzaGFwZS54MiA9IHg7XG4gICAgICAgICAgc2hhcGUueTEgPSB5O1xuICAgICAgICB9IGVsc2UgaWYgKGhhbmRsZS54ID09PSBzaGFwZS54MiAmJiBoYW5kbGUueSA9PT0gc2hhcGUueTIpIHtcbiAgICAgICAgICBzaGFwZS54MiA9IHg7XG4gICAgICAgICAgc2hhcGUueTIgPSB5O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHNoYXBlLngxID0geDtcbiAgICAgICAgICBzaGFwZS55MiA9IHk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKGhhbmRsZS5pc0NlbnRlcikge1xuICAgICAgICBjb25zdCBkeCA9IHggLSAoc2hhcGUueDEgKyBzaGFwZS54MikgLyAyO1xuICAgICAgICBjb25zdCBkeSA9IHkgLSAoc2hhcGUueTEgKyBzaGFwZS55MikgLyAyO1xuICAgICAgICB0aGlzLm1vdmVTaGFwZShzaGFwZSwgZHgsIGR5KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlmIChoYW5kbGUueCA9PT0gc2hhcGUueDEgJiYgaGFuZGxlLnkgPT09IHNoYXBlLnkxKSB7XG4gICAgICAgICAgc2hhcGUueDEgPSB4O1xuICAgICAgICAgIHNoYXBlLnkxID0geTtcbiAgICAgICAgfSBlbHNlIGlmIChoYW5kbGUueCA9PT0gc2hhcGUueDIgJiYgaGFuZGxlLnkgPT09IHNoYXBlLnkxKSB7XG4gICAgICAgICAgc2hhcGUueDIgPSB4O1xuICAgICAgICAgIHNoYXBlLnkxID0geTtcbiAgICAgICAgfSBlbHNlIGlmIChoYW5kbGUueCA9PT0gc2hhcGUueDIgJiYgaGFuZGxlLnkgPT09IHNoYXBlLnkyKSB7XG4gICAgICAgICAgc2hhcGUueDIgPSB4O1xuICAgICAgICAgIHNoYXBlLnkyID0geTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBzaGFwZS54MSA9IHg7XG4gICAgICAgICAgc2hhcGUueTIgPSB5O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIHRoaXMuZHJhd1NoYXBlcygpO1xuICB9XG5cbiAgbW92ZVNoYXBlKHNoYXBlOiBhbnksIGR4OiBudW1iZXIsIGR5OiBudW1iZXIpIHtcbiAgICBpZiAoc2hhcGUudHlwZSA9PT0gJ2xpbmUnIHx8IHNoYXBlLnR5cGUgPT09ICdjaXJjbGUnKSB7XG4gICAgICBzaGFwZS54MSArPSBkeDtcbiAgICAgIHNoYXBlLnkxICs9IGR5O1xuICAgICAgc2hhcGUueDIgKz0gZHg7XG4gICAgICBzaGFwZS55MiArPSBkeTtcbiAgICB9IGVsc2UgaWYgKHNoYXBlLnR5cGUgPT09ICdmcmVlaGFuZCcpIHtcbiAgICAgIHNoYXBlLnBvaW50cy5mb3JFYWNoKChwb2ludDogYW55KSA9PiB7XG4gICAgICAgIHBvaW50LnggKz0gZHg7XG4gICAgICAgIHBvaW50LnkgKz0gZHk7XG4gICAgICB9KTtcbiAgICB9IGVsc2UgaWYgKHNoYXBlLnR5cGUgPT09ICd0ZXh0Jykge1xuICAgICAgc2hhcGUueCArPSBkeDtcbiAgICAgIHNoYXBlLnkgKz0gZHk7XG4gICAgfSBlbHNlIGlmIChzaGFwZS50eXBlID09PSAnaW1hZ2UnKSB7XG4gICAgICBzaGFwZS54MSArPSBkeDtcbiAgICAgIHNoYXBlLnkxICs9IGR5O1xuICAgICAgc2hhcGUueDIgKz0gZHg7XG4gICAgICBzaGFwZS55MiArPSBkeTtcbiAgICB9IGVsc2Uge1xuICAgICAgc2hhcGUueDEgKz0gZHg7XG4gICAgICBzaGFwZS55MSArPSBkeTtcbiAgICAgIHNoYXBlLngyICs9IGR4O1xuICAgICAgc2hhcGUueTIgKz0gZHk7XG4gICAgfVxuICB9XG5cbiAgZG93bmxvYWRDYW52YXModGVtcENhbnZhczogSFRNTENhbnZhc0VsZW1lbnQpIHtcbiAgICBjb25zdCBsaW5rID0gdGhpcy5kb3dubG9hZExpbmtSZWYubmF0aXZlRWxlbWVudDtcbiAgICBsaW5rLmhyZWYgPSB0ZW1wQ2FudmFzLnRvRGF0YVVSTCgpO1xuICAgIGxpbmsuZG93bmxvYWQgPSAnd2hpdGVib2FyZC5wbmcnO1xuICAgIGxpbmsuY2xpY2soKTtcbiAgfVxuXG4gIHNhdmVDYW52YXMoKSB7XG4gICAgY29uc3QgdGVtcENhbnZhcyA9IHRoaXMudGVtcENhbnZhc1JlZi5uYXRpdmVFbGVtZW50O1xuICAgIGNvbnN0IHRlbXBDdHggPSB0ZW1wQ2FudmFzLmdldENvbnRleHQoJzJkJyk7XG4gICAgdGVtcENhbnZhcy53aWR0aCA9IHRoaXMuY2FudmFzUmVmLm5hdGl2ZUVsZW1lbnQud2lkdGg7XG4gICAgdGVtcENhbnZhcy5oZWlnaHQgPSB0aGlzLmNhbnZhc1JlZi5uYXRpdmVFbGVtZW50LmhlaWdodDtcbiAgICBjb25zdCBub3RTaGFwZXMgPSBbJ2ZyZWVoYW5kJywgJ3RleHQnLCAnaW1hZ2UnLCAnbGluZSddO1xuXG4gICAgaWYgKHRoaXMucGFyYW1ldGVycy51c2VJbWFnZUJhY2tncm91bmQpIHtcbiAgICAgIGNvbnN0IGJhY2tncm91bmRJbWFnZSA9IG5ldyBJbWFnZSgpO1xuICAgICAgYmFja2dyb3VuZEltYWdlLmNyb3NzT3JpZ2luID0gJ2Fub255bW91cyc7XG4gICAgICBiYWNrZ3JvdW5kSW1hZ2Uub25sb2FkID0gKCkgPT4ge1xuICAgICAgICB0ZW1wQ3R4IS5kcmF3SW1hZ2UoYmFja2dyb3VuZEltYWdlLCAwLCAwLCB0ZW1wQ2FudmFzLndpZHRoLCB0ZW1wQ2FudmFzLmhlaWdodCk7XG4gICAgICAgIHRoaXMucGFyYW1ldGVycy5zaGFwZXMuZm9yRWFjaCgoc2hhcGU6IGFueSkgPT4ge1xuICAgICAgICAgICFub3RTaGFwZXMuaW5jbHVkZXMoc2hhcGUudHlwZSlcbiAgICAgICAgICAgID8gdGhpcy5kcmF3U2hhcGUoXG4gICAgICAgICAgICAgICAgc2hhcGUudHlwZSxcbiAgICAgICAgICAgICAgICBzaGFwZS54MSxcbiAgICAgICAgICAgICAgICBzaGFwZS55MSxcbiAgICAgICAgICAgICAgICBzaGFwZS54MixcbiAgICAgICAgICAgICAgICBzaGFwZS55MixcbiAgICAgICAgICAgICAgICBzaGFwZS5jb2xvcixcbiAgICAgICAgICAgICAgICBzaGFwZS50aGlja25lc3MsXG4gICAgICAgICAgICAgICAgc2hhcGUubGluZVR5cGUsXG4gICAgICAgICAgICAgICAgdGVtcEN0eCEsXG4gICAgICAgICAgICAgIClcbiAgICAgICAgICAgIDogdGhpcy5kcmF3U2hhcGVPbkNhbnZhcyhzaGFwZSwgdGVtcEN0eCEpO1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5kb3dubG9hZENhbnZhcyh0ZW1wQ2FudmFzKTtcbiAgICAgIH07XG4gICAgICBiYWNrZ3JvdW5kSW1hZ2Uuc3JjID0gJ2h0dHBzOi8vbWVkaWFzZnUuY29tL2ltYWdlcy9zdmcvZ3JhcGhfcGFwZXIuanBnJztcbiAgICB9IGVsc2Uge1xuICAgICAgdGVtcEN0eCEuZmlsbFN0eWxlID0gJ3doaXRlJztcbiAgICAgIHRlbXBDdHghLmZpbGxSZWN0KDAsIDAsIHRlbXBDYW52YXMud2lkdGgsIHRlbXBDYW52YXMuaGVpZ2h0KTtcblxuICAgICAgdGhpcy5wYXJhbWV0ZXJzLnNoYXBlcy5mb3JFYWNoKChzaGFwZTogYW55KSA9PiB7XG4gICAgICAgICFub3RTaGFwZXMuaW5jbHVkZXMoc2hhcGUudHlwZSlcbiAgICAgICAgICA/IHRoaXMuZHJhd1NoYXBlKFxuICAgICAgICAgICAgICBzaGFwZS50eXBlLFxuICAgICAgICAgICAgICBzaGFwZS54MSxcbiAgICAgICAgICAgICAgc2hhcGUueTEsXG4gICAgICAgICAgICAgIHNoYXBlLngyLFxuICAgICAgICAgICAgICBzaGFwZS55MixcbiAgICAgICAgICAgICAgc2hhcGUuY29sb3IsXG4gICAgICAgICAgICAgIHNoYXBlLnRoaWNrbmVzcyxcbiAgICAgICAgICAgICAgc2hhcGUubGluZVR5cGUsXG4gICAgICAgICAgICAgIHRlbXBDdHghLFxuICAgICAgICAgICAgKVxuICAgICAgICAgIDogdGhpcy5kcmF3U2hhcGVPbkNhbnZhcyhzaGFwZSwgdGVtcEN0eCEpO1xuICAgICAgfSk7XG4gICAgICB0aGlzLmRvd25sb2FkQ2FudmFzKHRlbXBDYW52YXMpO1xuICAgIH1cbiAgfVxuXG4gIGRyYXdTaGFwZU9uQ2FudmFzKFxuICAgIHNoYXBlOiBhbnksXG4gICAgY3R4OiBDYW52YXNSZW5kZXJpbmdDb250ZXh0MkQgPSB0aGlzLmNhbnZhc1JlZi5uYXRpdmVFbGVtZW50LmdldENvbnRleHQoJzJkJykhLFxuICApIHtcbiAgICBjdHguYmVnaW5QYXRoKCk7XG4gICAgY3R4LnN0cm9rZVN0eWxlID0gc2hhcGUuY29sb3I7XG4gICAgY3R4LmxpbmVXaWR0aCA9IHNoYXBlLnRoaWNrbmVzcyB8fCAyO1xuICAgIGN0eC5maWxsU3R5bGUgPSBzaGFwZS5jb2xvcjtcbiAgICBjdHguZm9udCA9IGAke3NoYXBlLmZvbnRTaXplfXB4ICR7c2hhcGUuZm9udEZhbWlseX1gO1xuXG4gICAgY29uc3QgbGluZVR5cGUgPSBzaGFwZS5saW5lVHlwZSA/IHNoYXBlLmxpbmVUeXBlIDogJ3NvbGlkJztcblxuICAgIGlmIChsaW5lVHlwZSA9PT0gJ2Rhc2hlZCcpIHtcbiAgICAgIGN0eC5zZXRMaW5lRGFzaChbMTAsIDEwXSk7XG4gICAgfSBlbHNlIGlmIChsaW5lVHlwZSA9PT0gJ2RvdHRlZCcpIHtcbiAgICAgIGN0eC5zZXRMaW5lRGFzaChbMiwgMTBdKTtcbiAgICB9IGVsc2UgaWYgKGxpbmVUeXBlID09PSAnZGFzaERvdCcpIHtcbiAgICAgIGN0eC5zZXRMaW5lRGFzaChbMTAsIDUsIDIsIDVdKTtcbiAgICB9IGVsc2Uge1xuICAgICAgY3R4LnNldExpbmVEYXNoKFtdKTtcbiAgICB9XG4gICAgc3dpdGNoIChzaGFwZS50eXBlKSB7XG4gICAgICBjYXNlICdsaW5lJzpcbiAgICAgICAgY3R4Lm1vdmVUbyhzaGFwZS54MSwgc2hhcGUueTEpO1xuICAgICAgICBjdHgubGluZVRvKHNoYXBlLngyLCBzaGFwZS55Mik7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnZnJlZWhhbmQnOlxuICAgICAgICB0cnkge1xuICAgICAgICAgIGN0eC5tb3ZlVG8oc2hhcGUucG9pbnRzWzBdLngsIHNoYXBlLnBvaW50c1swXS55KTtcbiAgICAgICAgICBzaGFwZS5wb2ludHMuZm9yRWFjaCgocG9pbnQ6IGFueSkgPT4gY3R4LmxpbmVUbyhwb2ludC54LCBwb2ludC55KSk7XG4gICAgICAgIH0gY2F0Y2gge1xuICAgICAgICAgIC8vY29uc29sZS5sb2coJ0Vycm9yIGRyYXdpbmcgZnJlZWhhbmQgc2hhcGUnKTtcbiAgICAgICAgfVxuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ3RleHQnOlxuICAgICAgICBjdHguZmlsbFRleHQoc2hhcGUudGV4dCwgc2hhcGUueCwgc2hhcGUueSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnaW1hZ2UnOlxuICAgICAgICBjdHguZHJhd0ltYWdlKHNoYXBlLmltZywgc2hhcGUueDEsIHNoYXBlLnkxLCBzaGFwZS54MiAtIHNoYXBlLngxLCBzaGFwZS55MiAtIHNoYXBlLnkxKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICBicmVhaztcbiAgICB9XG4gICAgY3R4LnN0cm9rZSgpO1xuICB9XG5cbiAgZGVsZXRlU2hhcGUoZG9FbWl0cyA9IHRydWUpIHtcbiAgICBpZiAoIXRoaXMuY2hlY2tCb2FyZEFjY2VzcygpKSByZXR1cm47XG5cbiAgICBpZiAoIXRoaXMuc2VsZWN0ZWRTaGFwZSkgcmV0dXJuO1xuICAgIGlmICh0aGlzLnNlbGVjdGVkU2hhcGUpIHtcbiAgICAgIHRoaXMucGFyYW1ldGVycy5zaGFwZXMgPSB0aGlzLnBhcmFtZXRlcnMuc2hhcGVzLmZpbHRlcihcbiAgICAgICAgKHNoYXBlOiBhbnkpID0+IHNoYXBlICE9PSB0aGlzLnNlbGVjdGVkU2hhcGUsXG4gICAgICApO1xuICAgICAgdGhpcy5wYXJhbWV0ZXJzLnVwZGF0ZVNoYXBlcyh0aGlzLnBhcmFtZXRlcnMuc2hhcGVzKTtcbiAgICAgIHRoaXMuc2VsZWN0ZWRTaGFwZSA9IG51bGw7XG4gICAgICBpZiAoZG9FbWl0cykge1xuICAgICAgICB0aGlzLnBhcmFtZXRlcnMuc29ja2V0LmVtaXQoXG4gICAgICAgICAgJ3VwZGF0ZUJvYXJkQWN0aW9uJyxcbiAgICAgICAgICB7IGFjdGlvbjogJ3NoYXBlcycsIHBheWxvYWQ6IHsgc2hhcGVzOiB0aGlzLnBhcmFtZXRlcnMuc2hhcGVzIH0gfSxcbiAgICAgICAgICB0aGlzLmhhbmRsZVNlcnZlclJlc3BvbnNlLFxuICAgICAgICApO1xuICAgICAgfVxuICAgICAgdGhpcy5kcmF3U2hhcGVzKCk7XG4gICAgfVxuICB9XG5cbiAgdG9nZ2xlQmFja2dyb3VuZCA9IChkb0VtaXRzID0gdHJ1ZSkgPT4ge1xuICAgIGlmIChkb0VtaXRzICYmICF0aGlzLmNoZWNrQm9hcmRBY2Nlc3MoKSkgcmV0dXJuO1xuICAgIHRoaXMucGFyYW1ldGVycy51c2VJbWFnZUJhY2tncm91bmQgPSAhdGhpcy5wYXJhbWV0ZXJzLnVzZUltYWdlQmFja2dyb3VuZDtcbiAgICB0aGlzLnBhcmFtZXRlcnMudXBkYXRlVXNlSW1hZ2VCYWNrZ3JvdW5kKHRoaXMucGFyYW1ldGVycy51c2VJbWFnZUJhY2tncm91bmQpO1xuICAgIGNvbnN0IHRvZ2dsZUJ1dHRvbiA9IHRoaXMudG9nZ2xlQmFja2dyb3VuZFJlZi5uYXRpdmVFbGVtZW50O1xuICAgIGlmICh0aGlzLnBhcmFtZXRlcnMudXNlSW1hZ2VCYWNrZ3JvdW5kKSB7XG4gICAgICB0aGlzLmNhbnZhc1JlZi5uYXRpdmVFbGVtZW50LnN0eWxlLmJhY2tncm91bmRJbWFnZSA9IGB1cmwoJ2h0dHBzOi8vbWVkaWFzZnUuY29tL2ltYWdlcy9zdmcvZ3JhcGhfcGFwZXIuanBnJylgO1xuICAgICAgdG9nZ2xlQnV0dG9uLmNsYXNzTGlzdC5yZW1vdmUoJ2FjdGl2ZScpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmNhbnZhc1JlZi5uYXRpdmVFbGVtZW50LnN0eWxlLmJhY2tncm91bmRJbWFnZSA9ICdub25lJztcbiAgICAgIHRoaXMuY2FudmFzUmVmLm5hdGl2ZUVsZW1lbnQuc3R5bGUuYmFja2dyb3VuZENvbG9yID0gJ3doaXRlJztcbiAgICAgIHRvZ2dsZUJ1dHRvbi5jbGFzc0xpc3QuYWRkKCdhY3RpdmUnKTtcbiAgICB9XG4gICAgdGhpcy5kcmF3U2hhcGVzKCk7XG4gICAgaWYgKGRvRW1pdHMpIHtcbiAgICAgIHRoaXMucGFyYW1ldGVycy5zb2NrZXQuZW1pdChcbiAgICAgICAgJ3VwZGF0ZUJvYXJkQWN0aW9uJyxcbiAgICAgICAgeyBhY3Rpb246ICd0b2dnbGVCYWNrZ3JvdW5kJywgcGF5bG9hZDogdGhpcy5wYXJhbWV0ZXJzLnVzZUltYWdlQmFja2dyb3VuZCB9LFxuICAgICAgICB0aGlzLmhhbmRsZVNlcnZlclJlc3BvbnNlLFxuICAgICAgKTtcbiAgICB9XG4gIH07XG5cbiAgY2xlYXJDYW52YXMgPSAoZG9FbWl0cyA9IHRydWUpID0+IHtcbiAgICBpZiAodGhpcy5wYXJhbWV0ZXJzLmlzbGV2ZWwgIT0gJzInICYmIGRvRW1pdHMpIHtcbiAgICAgIHRoaXMucGFyYW1ldGVycy5zaG93QWxlcnQ/Lih7XG4gICAgICAgIG1lc3NhZ2U6ICdZb3UgZG8gbm90IGhhdmUgcGVybWlzc2lvbiB0byBjbGVhciB0aGUgYm9hcmQnLFxuICAgICAgICB0eXBlOiAnZGFuZ2VyJyxcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAodGhpcy5wYXJhbWV0ZXJzLnNoYXBlcy5sZW5ndGggPT09IDApIHJldHVybjtcbiAgICB0aGlzLnBhcmFtZXRlcnMuc2hhcGVzID0gW107XG4gICAgdGhpcy5wYXJhbWV0ZXJzLnVwZGF0ZVNoYXBlcyhbXSk7XG4gICAgdGhpcy5kcmF3U2hhcGVzKCk7XG4gICAgaWYgKGRvRW1pdHMpIHtcbiAgICAgIHRoaXMucGFyYW1ldGVycy5zb2NrZXQuZW1pdChcbiAgICAgICAgJ3VwZGF0ZUJvYXJkQWN0aW9uJyxcbiAgICAgICAgeyBhY3Rpb246ICdjbGVhcicgfSxcbiAgICAgICAgdGhpcy5oYW5kbGVTZXJ2ZXJSZXNwb25zZSxcbiAgICAgICk7XG4gICAgfVxuICB9O1xuXG4gIHVwbG9hZEltYWdlID0gKGV2ZW50OiBhbnksIGRvRW1pdHMgPSB0cnVlKSA9PiB7XG4gICAgdHJ5IHtcbiAgICAgIGlmICghdGhpcy5jaGVja0JvYXJkQWNjZXNzKCkpIHJldHVybjtcbiAgICAgIGNvbnN0IGZpbGUgPSBldmVudC50YXJnZXQuZmlsZXNbMF07XG4gICAgICBpZiAoZmlsZS5zaXplID4gMTAyNCAqIDEwMjQpIHtcbiAgICAgICAgdGhpcy5wYXJhbWV0ZXJzLnNob3dBbGVydD8uKHsgbWVzc2FnZTogJ0ZpbGUgc2l6ZSBtdXN0IGJlIGxlc3MgdGhhbiAxTUInLCB0eXBlOiAnZGFuZ2VyJyB9KTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBjb25zdCByZWFkZXIgPSBuZXcgRmlsZVJlYWRlcigpO1xuICAgICAgcmVhZGVyLm9ubG9hZCA9IChldmVudDogYW55KSA9PiB7XG4gICAgICAgIGNvbnN0IGltZyA9IG5ldyBJbWFnZSgpO1xuICAgICAgICBpbWcuY3Jvc3NPcmlnaW4gPSAnYW5vbnltb3VzJztcbiAgICAgICAgaW1nLm9ubG9hZCA9ICgpID0+IHtcbiAgICAgICAgICBpZiAoaW1nLmhlaWdodCA+IDYwMCAmJiBpbWcuaGVpZ2h0ID4gaW1nLndpZHRoICYmICFmaWxlLnR5cGUuaW5jbHVkZXMoJ2pwZWcnKSkge1xuICAgICAgICAgICAgdGhpcy5wYXJhbWV0ZXJzLnNob3dBbGVydD8uKHtcbiAgICAgICAgICAgICAgbWVzc2FnZTogJ0ZvciBiZXR0ZXIgcGVyZm9ybWFuY2UsIHBsZWFzZSB1cGxvYWQgdGhlIGltYWdlIGluIEpQRyBmb3JtYXQuJyxcbiAgICAgICAgICAgICAgdHlwZTogJ2RhbmdlcicsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBsZXQgaW1hZ2VXaWR0aCA9IDM1MDtcbiAgICAgICAgICBjb25zdCBhc3BlY3RSYXRpbyA9IGltZy5oZWlnaHQgLyBpbWcud2lkdGg7XG4gICAgICAgICAgbGV0IGltYWdlSGVpZ2h0ID0gaW1hZ2VXaWR0aCAqIGFzcGVjdFJhdGlvO1xuICAgICAgICAgIGNvbnN0IG1heEhlaWdodCA9IDYwMDtcbiAgICAgICAgICBpZiAoaW1hZ2VIZWlnaHQgPiBtYXhIZWlnaHQpIHtcbiAgICAgICAgICAgIGltYWdlSGVpZ2h0ID0gbWF4SGVpZ2h0O1xuICAgICAgICAgICAgaW1hZ2VXaWR0aCA9IGltYWdlSGVpZ2h0IC8gYXNwZWN0UmF0aW87XG4gICAgICAgICAgICBpZiAoaW1hZ2VXaWR0aCA+IDYwMCkge1xuICAgICAgICAgICAgICBpbWFnZVdpZHRoID0gNjAwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBjb25zdCBpbWFnZVNoYXBlID0ge1xuICAgICAgICAgICAgdHlwZTogJ2ltYWdlJyxcbiAgICAgICAgICAgIGltZzogaW1nLFxuICAgICAgICAgICAgc3JjOiBldmVudC50YXJnZXQucmVzdWx0LFxuICAgICAgICAgICAgeDE6IDUwLFxuICAgICAgICAgICAgeTE6IDUwLFxuICAgICAgICAgICAgeDI6IDUwICsgaW1hZ2VXaWR0aCxcbiAgICAgICAgICAgIHkyOiA1MCArIGltYWdlSGVpZ2h0LFxuICAgICAgICAgIH07XG4gICAgICAgICAgdGhpcy5wYXJhbWV0ZXJzLnNoYXBlcy5wdXNoKGltYWdlU2hhcGUpO1xuICAgICAgICAgIHRoaXMucGFyYW1ldGVycy51cGRhdGVTaGFwZXModGhpcy5wYXJhbWV0ZXJzLnNoYXBlcyk7XG4gICAgICAgICAgdGhpcy5kcmF3U2hhcGVzKCk7XG4gICAgICAgICAgaWYgKGRvRW1pdHMpIHtcbiAgICAgICAgICAgIHRoaXMucGFyYW1ldGVycy5zb2NrZXQuZW1pdChcbiAgICAgICAgICAgICAgJ3VwZGF0ZUJvYXJkQWN0aW9uJyxcbiAgICAgICAgICAgICAgeyBhY3Rpb246ICd1cGxvYWRJbWFnZScsIHBheWxvYWQ6IGltYWdlU2hhcGUgfSxcbiAgICAgICAgICAgICAgdGhpcy5oYW5kbGVTZXJ2ZXJSZXNwb25zZSxcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBpbWcub25lcnJvciA9ICgpID0+IHtcbiAgICAgICAgICB0aGlzLnBhcmFtZXRlcnMuc2hvd0FsZXJ0Py4oeyBtZXNzYWdlOiAnRXJyb3IgbG9hZGluZyBpbWFnZScsIHR5cGU6ICdkYW5nZXInIH0pO1xuICAgICAgICB9O1xuICAgICAgICBpbWcuc3JjID0gZXZlbnQudGFyZ2V0LnJlc3VsdDtcbiAgICAgIH07XG4gICAgICByZWFkZXIub25lcnJvciA9ICgpID0+IHtcbiAgICAgICAgdGhpcy5wYXJhbWV0ZXJzLnNob3dBbGVydD8uKHsgbWVzc2FnZTogJ0Vycm9yIHJlYWRpbmcgZmlsZScsIHR5cGU6ICdkYW5nZXInIH0pO1xuICAgICAgfTtcbiAgICAgIHJlYWRlci5yZWFkQXNEYXRhVVJMKGZpbGUpO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAvL2NvbnNvbGUubG9nKGVycm9yKTtcbiAgICB9XG4gIH07XG5cbiAgaGFuZGxlU2VydmVyUmVzcG9uc2UgPSAocmVzcG9uc2U6IGFueSkgPT4ge1xuICAgIGlmICghcmVzcG9uc2Uuc3VjY2Vzcykge1xuICAgICAgdGhpcy5wYXJhbWV0ZXJzLnNob3dBbGVydD8uKHtcbiAgICAgICAgbWVzc2FnZTogYFdoaXRlYm9hcmQgYWN0aW9uIGZhaWxlZDogJHtyZXNwb25zZS5yZWFzb259YCxcbiAgICAgICAgdHlwZTogJ2RhbmdlcicsXG4gICAgICB9KTtcbiAgICB9XG4gIH07XG5cbiAgV2hpdGVib2FyZEFjdGlvbiA9IChkYXRhOiBhbnkpID0+IHtcbiAgICBjb25zdCB7IGFjdGlvbiwgcGF5bG9hZCB9ID0gZGF0YTtcblxuICAgIGNvbnN0IGN0eCA9IHRoaXMuY2FudmFzUmVmLm5hdGl2ZUVsZW1lbnQuZ2V0Q29udGV4dCgnMmQnKTtcbiAgICBpZiAoIWN0eCkgcmV0dXJuO1xuICAgIHRoaXMucGFyYW1ldGVycy51cGRhdGVDYW52YXNXaGl0ZWJvYXJkKHRoaXMuY2FudmFzUmVmLm5hdGl2ZUVsZW1lbnQpO1xuXG4gICAgc3dpdGNoIChhY3Rpb24pIHtcbiAgICAgIGNhc2UgJ2RyYXcnOlxuICAgICAgICBpZiAocGF5bG9hZC50eXBlID09PSAnZnJlZWhhbmQnKSB7XG4gICAgICAgICAgdGhpcy5kcmF3RnJlZWhhbmQocGF5bG9hZC5wb2ludHMsIHBheWxvYWQuY29sb3IsIHBheWxvYWQudGhpY2tuZXNzKTtcbiAgICAgICAgICB0aGlzLnBhcmFtZXRlcnMuc2hhcGVzLnB1c2goe1xuICAgICAgICAgICAgdHlwZTogJ2ZyZWVoYW5kJyxcbiAgICAgICAgICAgIHBvaW50czogcGF5bG9hZC5wb2ludHMsXG4gICAgICAgICAgICBjb2xvcjogcGF5bG9hZC5jb2xvcixcbiAgICAgICAgICAgIHRoaWNrbmVzczogcGF5bG9hZC50aGlja25lc3MsXG4gICAgICAgICAgfSk7XG4gICAgICAgICAgdGhpcy5wYXJhbWV0ZXJzLnVwZGF0ZVNoYXBlcyh0aGlzLnBhcmFtZXRlcnMuc2hhcGVzKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aGlzLmRyYXdMaW5lKFxuICAgICAgICAgICAgcGF5bG9hZC54MSxcbiAgICAgICAgICAgIHBheWxvYWQueTEsXG4gICAgICAgICAgICBwYXlsb2FkLngyLFxuICAgICAgICAgICAgcGF5bG9hZC55MixcbiAgICAgICAgICAgIHBheWxvYWQuY29sb3IsXG4gICAgICAgICAgICBwYXlsb2FkLnRoaWNrbmVzcyxcbiAgICAgICAgICAgIHBheWxvYWQubGluZVR5cGUsXG4gICAgICAgICAgKTtcbiAgICAgICAgICB0aGlzLnBhcmFtZXRlcnMuc2hhcGVzLnB1c2goe1xuICAgICAgICAgICAgdHlwZTogJ2xpbmUnLFxuICAgICAgICAgICAgeDE6IHBheWxvYWQueDEsXG4gICAgICAgICAgICB5MTogcGF5bG9hZC55MSxcbiAgICAgICAgICAgIHgyOiBwYXlsb2FkLngyLFxuICAgICAgICAgICAgeTI6IHBheWxvYWQueTIsXG4gICAgICAgICAgICBjb2xvcjogcGF5bG9hZC5jb2xvcixcbiAgICAgICAgICAgIHRoaWNrbmVzczogcGF5bG9hZC50aGlja25lc3MsXG4gICAgICAgICAgICBsaW5lVHlwZTogcGF5bG9hZC5saW5lVHlwZSxcbiAgICAgICAgICB9KTtcbiAgICAgICAgICB0aGlzLnBhcmFtZXRlcnMudXBkYXRlU2hhcGVzKHRoaXMucGFyYW1ldGVycy5zaGFwZXMpO1xuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnc2hhcGUnOlxuICAgICAgICB0aGlzLmRyYXdTaGFwZShcbiAgICAgICAgICBwYXlsb2FkLnR5cGUsXG4gICAgICAgICAgcGF5bG9hZC54MSxcbiAgICAgICAgICBwYXlsb2FkLnkxLFxuICAgICAgICAgIHBheWxvYWQueDIsXG4gICAgICAgICAgcGF5bG9hZC55MixcbiAgICAgICAgICBwYXlsb2FkLmNvbG9yLFxuICAgICAgICAgIHBheWxvYWQudGhpY2tuZXNzLFxuICAgICAgICAgIHBheWxvYWQubGluZVR5cGUsXG4gICAgICAgICk7XG4gICAgICAgIHRoaXMucGFyYW1ldGVycy5zaGFwZXMucHVzaCh7XG4gICAgICAgICAgdHlwZTogcGF5bG9hZC50eXBlLFxuICAgICAgICAgIHgxOiBwYXlsb2FkLngxLFxuICAgICAgICAgIHkxOiBwYXlsb2FkLnkxLFxuICAgICAgICAgIHgyOiBwYXlsb2FkLngyLFxuICAgICAgICAgIHkyOiBwYXlsb2FkLnkyLFxuICAgICAgICAgIGNvbG9yOiBwYXlsb2FkLmNvbG9yLFxuICAgICAgICAgIHRoaWNrbmVzczogcGF5bG9hZC50aGlja25lc3MsXG4gICAgICAgICAgbGluZVR5cGU6IHBheWxvYWQubGluZVR5cGUsXG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLnBhcmFtZXRlcnMudXBkYXRlU2hhcGVzKHRoaXMucGFyYW1ldGVycy5zaGFwZXMpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ2VyYXNlJzpcbiAgICAgICAgdGhpcy5lcmFzZShwYXlsb2FkLngsIHBheWxvYWQueSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnY2xlYXInOlxuICAgICAgICB0aGlzLmNsZWFyQ2FudmFzKGZhbHNlKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICd1cGxvYWRJbWFnZSc6IHtcbiAgICAgICAgY29uc3QgaW1nID0gbmV3IEltYWdlKCk7XG4gICAgICAgIGltZy5jcm9zc09yaWdpbiA9ICdhbm9ueW1vdXMnO1xuICAgICAgICBpbWcub25sb2FkID0gKCkgPT4ge1xuICAgICAgICAgIGNvbnN0IGltYWdlU2hhcGUgPSB7XG4gICAgICAgICAgICB0eXBlOiAnaW1hZ2UnLFxuICAgICAgICAgICAgaW1nLFxuICAgICAgICAgICAgc3JjOiBwYXlsb2FkLnNyYyxcbiAgICAgICAgICAgIHgxOiBwYXlsb2FkLngxLFxuICAgICAgICAgICAgeTE6IHBheWxvYWQueTEsXG4gICAgICAgICAgICB4MjogcGF5bG9hZC54MixcbiAgICAgICAgICAgIHkyOiBwYXlsb2FkLnkyLFxuICAgICAgICAgIH07XG4gICAgICAgICAgdGhpcy5wYXJhbWV0ZXJzLnNoYXBlcy5wdXNoKGltYWdlU2hhcGUpO1xuICAgICAgICAgIHRoaXMucGFyYW1ldGVycy51cGRhdGVTaGFwZXModGhpcy5wYXJhbWV0ZXJzLnNoYXBlcyk7XG4gICAgICAgICAgdGhpcy5kcmF3U2hhcGVzKCk7XG4gICAgICAgIH07XG4gICAgICAgIGltZy5zcmMgPSBwYXlsb2FkLnNyYztcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICBjYXNlICd0b2dnbGVCYWNrZ3JvdW5kJzpcbiAgICAgICAgdGhpcy50b2dnbGVCYWNrZ3JvdW5kKGZhbHNlKTtcbiAgICAgICAgdGhpcy5kcmF3U2hhcGVzKCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAndW5kbyc6XG4gICAgICAgIGlmICh0aGlzLnBhcmFtZXRlcnMuc2hhcGVzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICB0aGlzLnBhcmFtZXRlcnMucmVkb1N0YWNrLnB1c2godGhpcy5wYXJhbWV0ZXJzLnNoYXBlcy5wb3AoKSEpO1xuICAgICAgICAgIHRoaXMucGFyYW1ldGVycy51cGRhdGVSZWRvU3RhY2sodGhpcy5wYXJhbWV0ZXJzLnJlZG9TdGFjayk7XG4gICAgICAgICAgdGhpcy5kcmF3U2hhcGVzKCk7XG4gICAgICAgIH1cbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdyZWRvJzpcbiAgICAgICAgaWYgKHRoaXMucGFyYW1ldGVycy5yZWRvU3RhY2subGVuZ3RoID4gMCkge1xuICAgICAgICAgIHRoaXMucGFyYW1ldGVycy5zaGFwZXMucHVzaCh0aGlzLnBhcmFtZXRlcnMucmVkb1N0YWNrLnBvcCgpISk7XG4gICAgICAgICAgdGhpcy5wYXJhbWV0ZXJzLnVwZGF0ZVNoYXBlcyh0aGlzLnBhcmFtZXRlcnMuc2hhcGVzKTtcbiAgICAgICAgICB0aGlzLmRyYXdTaGFwZXMoKTtcbiAgICAgICAgfVxuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ3RleHQnOlxuICAgICAgICB0aGlzLnBhcmFtZXRlcnMuc2hhcGVzLnB1c2goe1xuICAgICAgICAgIHR5cGU6ICd0ZXh0JyxcbiAgICAgICAgICB0ZXh0OiBwYXlsb2FkLnRleHQsXG4gICAgICAgICAgeDogcGF5bG9hZC54LFxuICAgICAgICAgIHk6IHBheWxvYWQueSxcbiAgICAgICAgICBjb2xvcjogcGF5bG9hZC5jb2xvcixcbiAgICAgICAgICBmb250OiBwYXlsb2FkLmZvbnQsXG4gICAgICAgICAgZm9udFNpemU6IHBheWxvYWQuZm9udFNpemUsXG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLnBhcmFtZXRlcnMudXBkYXRlU2hhcGVzKHRoaXMucGFyYW1ldGVycy5zaGFwZXMpO1xuICAgICAgICB0aGlzLmRyYXdTaGFwZXMoKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdkZWxldGVTaGFwZSc6XG4gICAgICAgIHRoaXMucGFyYW1ldGVycy5zaGFwZXMgPSB0aGlzLnBhcmFtZXRlcnMuc2hhcGVzLmZpbHRlcigoc2hhcGU6IGFueSkgPT4gc2hhcGUgIT09IHBheWxvYWQpO1xuICAgICAgICB0aGlzLnBhcmFtZXRlcnMudXBkYXRlU2hhcGVzKHRoaXMucGFyYW1ldGVycy5zaGFwZXMpO1xuICAgICAgICB0aGlzLmRyYXdTaGFwZXMoKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdzaGFwZXMnOiB7XG4gICAgICAgIGNvbnN0IG9sZFNoYXBlcyA9IHRoaXMucGFyYW1ldGVycy5zaGFwZXMuZmlsdGVyKChzaGFwZTogYW55KSA9PiBzaGFwZS50eXBlID09PSAnaW1hZ2UnKTtcbiAgICAgICAgdGhpcy5wYXJhbWV0ZXJzLnNoYXBlcyA9IHBheWxvYWQuc2hhcGVzLm1hcCgoc2hhcGU6IGFueSkgPT4ge1xuICAgICAgICAgIGlmIChzaGFwZS50eXBlID09PSAnaW1hZ2UnKSB7XG4gICAgICAgICAgICBjb25zdCBvbGRTaGFwZSA9IG9sZFNoYXBlcy5maW5kKChvbGRTaGFwZTogYW55KSA9PiBvbGRTaGFwZS5zcmMgPT09IHNoYXBlLnNyYyk7XG4gICAgICAgICAgICBpZiAob2xkU2hhcGUpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIHsgLi4uc2hhcGUsIGltZzogb2xkU2hhcGUuaW1nIH07XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBjb25zdCBpbWcgPSBuZXcgSW1hZ2UoKTtcbiAgICAgICAgICAgICAgaW1nLmNyb3NzT3JpZ2luID0gJ2Fub255bW91cyc7XG4gICAgICAgICAgICAgIGltZy5zcmMgPSBzaGFwZS5zcmM7XG4gICAgICAgICAgICAgIHJldHVybiB7IC4uLnNoYXBlLCBpbWcgfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIHNoYXBlO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMucGFyYW1ldGVycy51cGRhdGVTaGFwZXModGhpcy5wYXJhbWV0ZXJzLnNoYXBlcyk7XG4gICAgICAgIHRoaXMuZHJhd1NoYXBlcygpO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIGJyZWFrO1xuICAgIH1cbiAgfTtcblxuICBXaGl0ZWJvYXJkVXBkYXRlZCA9IChkYXRhOiBhbnkpID0+IHtcbiAgICAvLyBkYXRhID0geyB3aGl0ZWJvYXJkVXNlcnMsIHN0YXR1c31cbiAgICAvLyBzdGF0dXMgPSAnc3RhcnRlZCcsICdlbmRlZCcsICd1cGRhdGVkJ1xuICAgIC8vIHdoaXRlYm9hcmRVc2VycyBhcnJheVxuICAgIC8vIG1lbWJlcnMgKHBhcnRpY2lwYW50cykgYXJyYXkgb25seSBzZW50IHRvIHRoZSBob3N0XG4gICAgLy93aGl0ZWJvYXJkRGF0YSA9IHtzaGFwZXM9W10sIHVzZUltYWdlQmFja2dyb3VuZD1Cb29sZWFuLCByZWRvU3RhY2s9W10sIHVuZG9TdGFjaz1bXX0gb3Ige30gb3IgbnVsbFxuICAgIGNvbnN0IGN0eCA9IHRoaXMuY2FudmFzUmVmLm5hdGl2ZUVsZW1lbnQuZ2V0Q29udGV4dCgnMmQnKTtcbiAgICBpZiAoIWN0eCkgcmV0dXJuO1xuXG4gICAgaWYgKHRoaXMucGFyYW1ldGVycy5pc2xldmVsID09ICcyJyAmJiBkYXRhLm1lbWJlcnMpIHtcbiAgICAgIHRoaXMucGFyYW1ldGVycy5wYXJ0aWNpcGFudHNBbGwgPSBkYXRhLm1lbWJlcnMubWFwKChwYXJ0aWNpcGFudDogYW55KSA9PiAoe1xuICAgICAgICBpc0Jhbm5lZDogcGFydGljaXBhbnQuaXNCYW5uZWQsXG4gICAgICAgIG5hbWU6IHBhcnRpY2lwYW50Lm5hbWUsXG4gICAgICB9KSk7XG4gICAgICB0aGlzLnBhcmFtZXRlcnMucGFydGljaXBhbnRzID0gZGF0YS5tZW1iZXJzLmZpbHRlcihcbiAgICAgICAgKHBhcnRpY2lwYW50OiBhbnkpID0+IHBhcnRpY2lwYW50LmlzQmFubmVkID09IGZhbHNlLFxuICAgICAgKTtcbiAgICAgIHRoaXMucGFyYW1ldGVycy51cGRhdGVQYXJ0aWNpcGFudHModGhpcy5wYXJhbWV0ZXJzLnBhcnRpY2lwYW50cyk7XG4gICAgfVxuXG4gICAgdGhpcy5wYXJhbWV0ZXJzLndoaXRlYm9hcmRVc2VycyA9IGRhdGEud2hpdGVib2FyZFVzZXJzO1xuICAgIHRoaXMucGFyYW1ldGVycy51cGRhdGVXaGl0ZWJvYXJkVXNlcnModGhpcy5wYXJhbWV0ZXJzLndoaXRlYm9hcmRVc2Vycyk7XG5cbiAgICBjb25zdCB1c2VCb2FyZCA9IHRoaXMucGFyYW1ldGVycy53aGl0ZWJvYXJkVXNlcnMuZmluZChcbiAgICAgICh1c2VyOiBhbnkpID0+IHVzZXIubmFtZSA9PSB0aGlzLnBhcmFtZXRlcnMubWVtYmVyICYmIHVzZXIudXNlQm9hcmQsXG4gICAgKVxuICAgICAgPyB0cnVlXG4gICAgICA6IGZhbHNlO1xuICAgIGlmICh0aGlzLnBhcmFtZXRlcnMuaXNsZXZlbCAhPSAnMicgJiYgIXVzZUJvYXJkICYmICF0aGlzLnBhcmFtZXRlcnMud2hpdGVib2FyZEVuZGVkKSB7XG4gICAgICB0aGlzLmNoYW5nZU1vZGUoJ3BhbicpO1xuICAgIH1cblxuICAgIGlmIChkYXRhLndoaXRlYm9hcmREYXRhICYmIE9iamVjdC5rZXlzKGRhdGEud2hpdGVib2FyZERhdGEpLmxlbmd0aCA+IDApIHtcbiAgICAgIGlmIChkYXRhLndoaXRlYm9hcmREYXRhLnNoYXBlcykge1xuICAgICAgICBjb25zdCBvbGRTaGFwZXMgPSB0aGlzLnBhcmFtZXRlcnMuc2hhcGVzLmZpbHRlcigoc2hhcGU6IGFueSkgPT4gc2hhcGUudHlwZSA9PT0gJ2ltYWdlJyk7XG4gICAgICAgIHRoaXMucGFyYW1ldGVycy5zaGFwZXMgPSBkYXRhLndoaXRlYm9hcmREYXRhLnNoYXBlcy5tYXAoKHNoYXBlOiBhbnkpID0+IHtcbiAgICAgICAgICBpZiAoc2hhcGUudHlwZSA9PT0gJ2ltYWdlJykge1xuICAgICAgICAgICAgY29uc3Qgb2xkU2hhcGUgPSBvbGRTaGFwZXMuZmluZCgob2xkU2hhcGU6IGFueSkgPT4gb2xkU2hhcGUuc3JjID09PSBzaGFwZS5zcmMpO1xuICAgICAgICAgICAgaWYgKG9sZFNoYXBlKSB7XG4gICAgICAgICAgICAgIHJldHVybiB7IC4uLnNoYXBlLCBpbWc6IG9sZFNoYXBlLmltZyB9O1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgY29uc3QgaW1nID0gbmV3IEltYWdlKCk7XG4gICAgICAgICAgICAgIGltZy5jcm9zc09yaWdpbiA9ICdhbm9ueW1vdXMnO1xuICAgICAgICAgICAgICBpbWcuc3JjID0gc2hhcGUuc3JjO1xuICAgICAgICAgICAgICByZXR1cm4geyAuLi5zaGFwZSwgaW1nIH07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBzaGFwZTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLnBhcmFtZXRlcnMudXBkYXRlU2hhcGVzKHRoaXMucGFyYW1ldGVycy5zaGFwZXMpO1xuICAgICAgfVxuICAgICAgaWYgKGRhdGEud2hpdGVib2FyZERhdGEudXNlSW1hZ2VCYWNrZ3JvdW5kICE9IG51bGwpIHtcbiAgICAgICAgdGhpcy5wYXJhbWV0ZXJzLnVzZUltYWdlQmFja2dyb3VuZCA9IGRhdGEud2hpdGVib2FyZERhdGEudXNlSW1hZ2VCYWNrZ3JvdW5kO1xuICAgICAgICB0aGlzLnBhcmFtZXRlcnMudXBkYXRlVXNlSW1hZ2VCYWNrZ3JvdW5kKHRoaXMucGFyYW1ldGVycy51c2VJbWFnZUJhY2tncm91bmQpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5wYXJhbWV0ZXJzLnVzZUltYWdlQmFja2dyb3VuZCA9IHRydWU7XG4gICAgICAgIHRoaXMucGFyYW1ldGVycy51cGRhdGVVc2VJbWFnZUJhY2tncm91bmQodHJ1ZSk7XG4gICAgICB9XG4gICAgICBpZiAoZGF0YS53aGl0ZWJvYXJkRGF0YS5yZWRvU3RhY2spIHtcbiAgICAgICAgdGhpcy5wYXJhbWV0ZXJzLnJlZG9TdGFjayA9IGRhdGEud2hpdGVib2FyZERhdGEucmVkb1N0YWNrO1xuICAgICAgICB0aGlzLnBhcmFtZXRlcnMudXBkYXRlUmVkb1N0YWNrKHRoaXMucGFyYW1ldGVycy5yZWRvU3RhY2spO1xuICAgICAgfVxuICAgICAgaWYgKGRhdGEud2hpdGVib2FyZERhdGEudW5kb1N0YWNrKSB7XG4gICAgICAgIHRoaXMucGFyYW1ldGVycy51bmRvU3RhY2sgPSBkYXRhLndoaXRlYm9hcmREYXRhLnVuZG9TdGFjaztcbiAgICAgICAgdGhpcy5wYXJhbWV0ZXJzLnVwZGF0ZVVuZG9TdGFjayh0aGlzLnBhcmFtZXRlcnMudW5kb1N0YWNrKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoZGF0YS5zdGF0dXMgPT0gJ3N0YXJ0ZWQnICYmICF0aGlzLnBhcmFtZXRlcnMud2hpdGVib2FyZFN0YXJ0ZWQpIHtcbiAgICAgIHRoaXMucGFyYW1ldGVycy53aGl0ZWJvYXJkU3RhcnRlZCA9IHRydWU7XG4gICAgICB0aGlzLnBhcmFtZXRlcnMud2hpdGVib2FyZEVuZGVkID0gZmFsc2U7XG4gICAgICB0aGlzLnBhcmFtZXRlcnMuc2NyZWVuSWQgPSBgd2hpdGVib2FyZC0ke3RoaXMucGFyYW1ldGVycy5yb29tTmFtZX1gO1xuXG4gICAgICB0aGlzLnBhcmFtZXRlcnMudXBkYXRlV2hpdGVib2FyZFN0YXJ0ZWQodHJ1ZSk7XG4gICAgICB0aGlzLnBhcmFtZXRlcnMudXBkYXRlV2hpdGVib2FyZEVuZGVkKGZhbHNlKTtcbiAgICAgIHRoaXMucGFyYW1ldGVycy51cGRhdGVTY3JlZW5JZCh0aGlzLnBhcmFtZXRlcnMuc2NyZWVuSWQpO1xuXG4gICAgICBpZiAodGhpcy5wYXJhbWV0ZXJzLmlzbGV2ZWwgIT0gJzInKSB7XG4gICAgICAgIHRoaXMucGFyYW1ldGVycy5zaGFyZVNjcmVlblN0YXJ0ZWQgPSB0cnVlO1xuICAgICAgICB0aGlzLnBhcmFtZXRlcnMudXBkYXRlU2hhcmVTY3JlZW5TdGFydGVkKHRydWUpO1xuICAgICAgICB0aGlzLnBhcmFtZXRlcnMub25TY3JlZW5DaGFuZ2VzKHsgY2hhbmdlZDogdHJ1ZSwgcGFyYW1ldGVyczogdGhpcy5wYXJhbWV0ZXJzIH0pO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAoZGF0YS5zdGF0dXMgPT0gJ2VuZGVkJykge1xuICAgICAgY29uc3QgcHJldldoaXRlYm9hcmRFbmRlZCA9IHRoaXMucGFyYW1ldGVycy53aGl0ZWJvYXJkRW5kZWQ7XG4gICAgICBjb25zdCBwcmV2V2hpdGVib2FyZFN0YXJ0ZWQgPSB0aGlzLnBhcmFtZXRlcnMud2hpdGVib2FyZFN0YXJ0ZWQ7XG4gICAgICB0aGlzLnBhcmFtZXRlcnMud2hpdGVib2FyZEVuZGVkID0gdHJ1ZTtcbiAgICAgIHRoaXMucGFyYW1ldGVycy53aGl0ZWJvYXJkU3RhcnRlZCA9IGZhbHNlO1xuICAgICAgdGhpcy5wYXJhbWV0ZXJzLnVwZGF0ZVdoaXRlYm9hcmRTdGFydGVkKGZhbHNlKTtcbiAgICAgIHRoaXMucGFyYW1ldGVycy51cGRhdGVXaGl0ZWJvYXJkRW5kZWQodHJ1ZSk7XG4gICAgICBpZiAodGhpcy5wYXJhbWV0ZXJzLmlzbGV2ZWwgPT0gJzInICYmIHByZXZXaGl0ZWJvYXJkRW5kZWQpIHtcbiAgICAgICAgLy8gTm8gb3BlcmF0aW9uIG5lZWRlZFxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5wYXJhbWV0ZXJzLnNoYXJlU2NyZWVuU3RhcnRlZCA9IGZhbHNlO1xuICAgICAgICB0aGlzLnBhcmFtZXRlcnMuc2NyZWVuSWQgPSAnJztcblxuICAgICAgICB0aGlzLnBhcmFtZXRlcnMudXBkYXRlU2hhcmVTY3JlZW5TdGFydGVkKGZhbHNlKTtcbiAgICAgICAgdGhpcy5wYXJhbWV0ZXJzLnVwZGF0ZVNjcmVlbklkKCcnKTtcbiAgICAgICAgdGhpcy5wYXJhbWV0ZXJzLm9uU2NyZWVuQ2hhbmdlcyh7IGNoYW5nZWQ6IHRydWUsIHBhcmFtZXRlcnM6IHRoaXMucGFyYW1ldGVycyB9KTtcbiAgICAgIH1cblxuICAgICAgdHJ5IHtcbiAgICAgICAgaWYgKFxuICAgICAgICAgIHByZXZXaGl0ZWJvYXJkU3RhcnRlZCAmJlxuICAgICAgICAgIHRoaXMucGFyYW1ldGVycy5pc2xldmVsID09ICcyJyAmJlxuICAgICAgICAgICh0aGlzLnBhcmFtZXRlcnMucmVjb3JkU3RhcnRlZCB8fCB0aGlzLnBhcmFtZXRlcnMucmVjb3JkUmVzdW1lZClcbiAgICAgICAgKSB7XG4gICAgICAgICAgaWYgKCEodGhpcy5wYXJhbWV0ZXJzLnJlY29yZFBhdXNlZCB8fCB0aGlzLnBhcmFtZXRlcnMucmVjb3JkU3RvcHBlZCkpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnBhcmFtZXRlcnMucmVjb3JkaW5nTWVkaWFPcHRpb25zID09ICd2aWRlbycpIHtcbiAgICAgICAgICAgICAgdGhpcy5wYXJhbWV0ZXJzLmNhcHR1cmVDYW52YXNTdHJlYW0oeyBwYXJhbWV0ZXJzOiB0aGlzLnBhcmFtZXRlcnMsIHN0YXJ0OiBmYWxzZSB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIC8vIEhhbmRsZSBlcnJvclxuICAgICAgfVxuICAgIH0gZWxzZSBpZiAoZGF0YS5zdGF0dXMgPT0gJ3N0YXJ0ZWQnICYmIHRoaXMucGFyYW1ldGVycy53aGl0ZWJvYXJkU3RhcnRlZCkge1xuICAgICAgdGhpcy5wYXJhbWV0ZXJzLndoaXRlYm9hcmRTdGFydGVkID0gdHJ1ZTtcbiAgICAgIHRoaXMucGFyYW1ldGVycy53aGl0ZWJvYXJkRW5kZWQgPSBmYWxzZTtcblxuICAgICAgdGhpcy5wYXJhbWV0ZXJzLnVwZGF0ZVdoaXRlYm9hcmRTdGFydGVkKHRydWUpO1xuICAgICAgdGhpcy5wYXJhbWV0ZXJzLnVwZGF0ZVdoaXRlYm9hcmRFbmRlZChmYWxzZSk7XG5cbiAgICAgIHRoaXMucGFyYW1ldGVycy5zaGFyZVNjcmVlblN0YXJ0ZWQgPSB0cnVlO1xuICAgICAgdGhpcy5wYXJhbWV0ZXJzLnNjcmVlbklkID0gYHdoaXRlYm9hcmQtJHt0aGlzLnBhcmFtZXRlcnMucm9vbU5hbWV9YDtcblxuICAgICAgdGhpcy5wYXJhbWV0ZXJzLnVwZGF0ZVNoYXJlU2NyZWVuU3RhcnRlZCh0cnVlKTtcbiAgICAgIHRoaXMucGFyYW1ldGVycy51cGRhdGVTY3JlZW5JZCh0aGlzLnBhcmFtZXRlcnMuc2NyZWVuSWQpO1xuICAgICAgdGhpcy5wYXJhbWV0ZXJzLm9uU2NyZWVuQ2hhbmdlcyh7IGNoYW5nZWQ6IHRydWUsIHBhcmFtZXRlcnM6IHRoaXMucGFyYW1ldGVycyB9KTtcbiAgICB9XG4gIH07XG5cbiAgaGFuZGxlRHJvcGRvd25DbGljayhpZDogc3RyaW5nKSB7XG4gICAgdGhpcy5kcm9wZG93bk9wZW4gPSB0aGlzLmRyb3Bkb3duT3BlbiA9PT0gaWQgPyBudWxsIDogaWQ7XG4gIH1cblxuICBoYW5kbGVJdGVtQ2xpY2soY2FsbGJhY2s6IGFueSwgbmFtZTogc3RyaW5nLCB2YWx1ZTogYW55KSB7XG4gICAgY2FsbGJhY2sodmFsdWUpO1xuICAgIHRoaXMuZHJvcGRvd25PcGVuID0gbnVsbDtcbiAgICBpZiAoWydkcmF3JywgJ2ZyZWVoYW5kJywgJ3NoYXBlJywgJ3RleHQnLCAnZXJhc2UnXS5pbmNsdWRlcyhuYW1lKSkge1xuICAgICAgdGhpcy5jaGFuZ2VNb2RlKG5hbWUpO1xuICAgIH1cbiAgfVxuXG4gIGRyb3Bkb3duSXRlbXMoaXRlbXM6IGFueVtdLCBuYW1lOiBzdHJpbmcsIGNhbGxiYWNrOiBhbnkpIHtcbiAgICByZXR1cm4gaXRlbXMubWFwKFxuICAgICAgKGl0ZW0sIGluZGV4KSA9PlxuICAgICAgICBgPGJ1dHRvbiBrZXk9XCIke2luZGV4fVwiIGNsYXNzPVwiZHJvcGRvd24taXRlbVwiIChjbGljayk9XCJoYW5kbGVJdGVtQ2xpY2soJHtjYWxsYmFja30sICcke25hbWV9JywgJHtpdGVtLnZhbHVlfSlcIiBzdHlsZT1cInBhZGRpbmc6IDVweDtcIj5cbiAgICAgICAgJHtpdGVtLmxhYmVsfVxuICAgICAgPC9idXR0b24+YCxcbiAgICApO1xuICB9XG5cbiAgdG9nZ2xlVG9vbGJhcigpIHtcbiAgICB0aGlzLnRvb2xiYXJWaXNpYmxlID0gIXRoaXMudG9vbGJhclZpc2libGU7XG4gIH1cblxuICBjaGVja0JvYXJkQWNjZXNzKCkge1xuICAgIHRoaXMucGFyYW1ldGVycyA9IHRoaXMucGFyYW1ldGVycy5nZXRVcGRhdGVkQWxsUGFyYW1zKCk7XG4gICAgaWYgKHRoaXMucGFyYW1ldGVycy53aGl0ZWJvYXJkU3RhcnRlZCAmJiAhdGhpcy5wYXJhbWV0ZXJzLndoaXRlYm9hcmRFbmRlZCkge1xuICAgICAgY29uc3QgdXNlciA9IHRoaXMucGFyYW1ldGVycy53aGl0ZWJvYXJkVXNlcnMuZmluZChcbiAgICAgICAgKHVzZXI6IGFueSkgPT4gdXNlci5uYW1lID09PSB0aGlzLnBhcmFtZXRlcnMubWVtYmVyLFxuICAgICAgKTtcbiAgICAgIGlmICgoIXVzZXIgfHwgIXVzZXIudXNlQm9hcmQpICYmIHRoaXMucGFyYW1ldGVycy5pc2xldmVsICE9ICcyJykge1xuICAgICAgICB0aGlzLnBhcmFtZXRlcnMuc2hvd0FsZXJ0Py4oe1xuICAgICAgICAgIG1lc3NhZ2U6ICdZb3UgYXJlIG5vdCBhbGxvd2VkIHRvIHVzZSB0aGUgd2hpdGVib2FyZC4gUGxlYXNlIGFzayB0aGUgaG9zdCB0byBhc3NpZ24geW91LicsXG4gICAgICAgICAgdHlwZTogJ2RhbmdlcicsXG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9XG5cbiAgY2hhbmdlTW9kZShuZXdNb2RlOiBzdHJpbmcpIHtcbiAgICBpZiAobmV3TW9kZSAhPT0gJ3BhbicgJiYgIXRoaXMuY2hlY2tCb2FyZEFjY2VzcygpKSByZXR1cm47XG4gICAgdGhpcy5tb2RlID0gbmV3TW9kZTtcbiAgICBjb25zdCBjYW52YXMgPSB0aGlzLmNhbnZhc1JlZi5uYXRpdmVFbGVtZW50O1xuICAgIGlmIChuZXdNb2RlID09PSAncGFuJykge1xuICAgICAgY2FudmFzLnN0eWxlLmN1cnNvciA9ICdncmFiJztcbiAgICB9IGVsc2UgaWYgKG5ld01vZGUgPT09ICdzZWxlY3QnKSB7XG4gICAgICBjYW52YXMuc3R5bGUuY3Vyc29yID0gJ3BvaW50ZXInO1xuICAgIH0gZWxzZSBpZiAobmV3TW9kZSA9PT0gJ2VyYXNlJykge1xuICAgICAgY2FudmFzLnN0eWxlLmN1cnNvciA9ICdjcm9zc2hhaXInO1xuICAgIH0gZWxzZSB7XG4gICAgICBjYW52YXMuc3R5bGUuY3Vyc29yID0gJ2Nyb3NzaGFpcic7XG4gICAgfVxuICAgIGlmIChuZXdNb2RlICE9PSAnZnJlZWhhbmQnICYmIHRoaXMuZnJlZWhhbmREcmF3aW5nLmxlbmd0aCA+IDApIHtcbiAgICAgIHRoaXMucGFyYW1ldGVycy5zaGFwZXMucHVzaCh7XG4gICAgICAgIHR5cGU6ICdmcmVlaGFuZCcsXG4gICAgICAgIHBvaW50czogdGhpcy5mcmVlaGFuZERyYXdpbmcsXG4gICAgICAgIGNvbG9yOiB0aGlzLmNvbG9yLFxuICAgICAgICB0aGlja25lc3M6IHRoaXMuYnJ1c2hUaGlja25lc3MsXG4gICAgICB9KTtcbiAgICAgIHRoaXMucGFyYW1ldGVycy51cGRhdGVTaGFwZXModGhpcy5wYXJhbWV0ZXJzLnNoYXBlcyk7XG4gICAgICB0aGlzLmZyZWVoYW5kRHJhd2luZyA9IFtdO1xuICAgICAgdGhpcy5zYXZlU3RhdGUoKTtcbiAgICB9XG4gIH1cbn1cbiIsIjxkaXYgaWQ9XCJ3aGl0ZWJvYXJkLWludGVyZmFjZVwiIFtzdHlsZS53aWR0aC5weF09XCJjdXN0b21XaWR0aFwiIFtzdHlsZS5oZWlnaHQucHhdPVwiY3VzdG9tSGVpZ2h0XCIgW3N0eWxlLmRpc3BsYXldPVwic2hvd0FzcGVjdCA/ICdibG9jaycgOiAnbm9uZSdcIiBzdHlsZT1cInBvc2l0aW9uOiByZWxhdGl2ZTsgZGlzcGxheTogZmxleDsganVzdGlmeS1jb250ZW50OiBjZW50ZXI7IGFsaWduLWl0ZW1zOiBjZW50ZXI7IGJvcmRlcjogMnB4IHNvbGlkICMwMDA7IGJhY2tncm91bmQtY29sb3I6ICNmMGYwZjA7XCI+XHJcbiAgPGRpdiBpZD1cIndoaXRlYm9hcmRDb250ZW50XCIgc3R5bGU9XCJwb3NpdGlvbjogcmVsYXRpdmU7IGRpc3BsYXk6IGZsZXg7IGp1c3RpZnktY29udGVudDogY2VudGVyOyBhbGlnbi1pdGVtczogY2VudGVyOyB3aWR0aDogMTAwJTsgaGVpZ2h0OiAxMDAlOyBtYXgtd2lkdGg6IDEwMCU7IG1heC1oZWlnaHQ6IDEwMCU7IG92ZXJmbG93OiBhdXRvO1wiPlxyXG4gICAgPGJ1dHRvbiBpZD1cInRvb2xiYXJUb2dnbGVcIiBjbGFzcz1cImJ0biBidG5Cb2FyZCBidG4tcHJpbWFyeVwiIHN0eWxlPVwicG9zaXRpb246IGFic29sdXRlOyB0b3A6IDVweDsgbGVmdDogNTVweDsgei1pbmRleDogMTA7XCIgKGNsaWNrKT1cInRvZ2dsZVRvb2xiYXIoKVwiPlxyXG4gICAgICA8ZmEtaWNvbiBbaWNvbl09XCJ0b29sYmFyVmlzaWJsZSA/IGZhQ2hldnJvbkxlZnQgOiBmYUNoZXZyb25SaWdodFwiPjwvZmEtaWNvbj5cclxuICAgIDwvYnV0dG9uPlxyXG4gICAgPGRpdiAqbmdJZj1cInRvb2xiYXJWaXNpYmxlXCIgY2xhc3M9XCJ0b29sYmFyIG1iLTNcIiBpZD1cInRvb2xiYXJcIiBzdHlsZT1cInBvc2l0aW9uOiBhYnNvbHV0ZTsgdG9wOiA1cHg7IGxlZnQ6IDEwMHB4OyB6LWluZGV4OiAxMDsgYmFja2dyb3VuZC1jb2xvcjogdHJhbnNwYXJlbnQ7XCI+XHJcbiAgICAgIDxkaXYgY2xhc3M9XCJidG4tZ3JvdXBcIiByb2xlPVwiZ3JvdXBcIj5cclxuICAgICAgICA8YnV0dG9uIGNsYXNzPVwiYnRuIGJ0bkJvYXJkIGJ0bi1zZWNvbmRhcnkgZHJvcGRvd24tdG9nZ2xlXCIgaWQ9XCJkcmF3TW9kZVwiIChjbGljayk9XCJoYW5kbGVEcm9wZG93bkNsaWNrKCdkcmF3TW9kZScpXCI+XHJcbiAgICAgICAgICA8ZmEtaWNvbiBbaWNvbl09XCJmYVBlbmNpbEFsdFwiPjwvZmEtaWNvbj5cclxuICAgICAgICA8L2J1dHRvbj5cclxuICAgICAgICA8ZGl2ICpuZ0lmPVwiZHJvcGRvd25PcGVuID09PSAnZHJhd01vZGUnXCIgY2xhc3M9XCJkcm9wZG93bi1tZW51IHNob3dcIj5cclxuICAgICAgICAgIDxidXR0b24gKm5nRm9yPVwibGV0IGl0ZW0gb2YgW3sgbGFiZWw6ICdYWC1TbWFsbCAoM3B4KScsIHZhbHVlOiAzIH0sIHsgbGFiZWw6ICdYLVNtYWxsICg2cHgpJywgdmFsdWU6IDYgfSwgeyBsYWJlbDogJ1NtYWxsICgxMnB4KScsIHZhbHVlOiAxMiB9LCB7IGxhYmVsOiAnTWVkaXVtICgxOHB4KScsIHZhbHVlOiAxOCB9LCB7IGxhYmVsOiAnTGFyZ2UgKDI0cHgpJywgdmFsdWU6IDI0IH0sIHsgbGFiZWw6ICdYLUxhcmdlICgzNnB4KScsIHZhbHVlOiAzNiB9XVwiIGNsYXNzPVwiZHJvcGRvd24taXRlbVwiIChjbGljayk9XCJoYW5kbGVJdGVtQ2xpY2sodXBkYXRlTGluZVRoaWNrbmVzcywgJ2RyYXcnLCBpdGVtLnZhbHVlKVwiIHN0eWxlPVwicGFkZGluZzogNXB4O1wiPlxyXG4gICAgICAgICAgICB7eyBpdGVtLmxhYmVsIH19XHJcbiAgICAgICAgICA8L2J1dHRvbj5cclxuICAgICAgICA8L2Rpdj5cclxuICAgICAgPC9kaXY+XHJcbiAgICAgIDxkaXYgY2xhc3M9XCJidG4tZ3JvdXBcIiByb2xlPVwiZ3JvdXBcIj5cclxuICAgICAgICA8YnV0dG9uIGNsYXNzPVwiYnRuIGJ0bkJvYXJkIGJ0bi1zZWNvbmRhcnkgZHJvcGRvd24tdG9nZ2xlXCIgaWQ9XCJmcmVlaGFuZE1vZGVcIiAoY2xpY2spPVwiaGFuZGxlRHJvcGRvd25DbGljaygnZnJlZWhhbmRNb2RlJylcIj5cclxuICAgICAgICAgIDxmYS1pY29uIFtpY29uXT1cImZhUGFpbnRCcnVzaFwiPjwvZmEtaWNvbj5cclxuICAgICAgICA8L2J1dHRvbj5cclxuICAgICAgICA8ZGl2ICpuZ0lmPVwiZHJvcGRvd25PcGVuID09PSAnZnJlZWhhbmRNb2RlJ1wiIGNsYXNzPVwiZHJvcGRvd24tbWVudSBzaG93XCI+XHJcbiAgICAgICAgICA8YnV0dG9uICpuZ0Zvcj1cImxldCBpdGVtIG9mIFt7IGxhYmVsOiAnWC1TbWFsbCAoNXB4KScsIHZhbHVlOiA1IH0sIHsgbGFiZWw6ICdTbWFsbCAoMTBweCknLCB2YWx1ZTogMTAgfSwgeyBsYWJlbDogJ01lZGl1bSAoMjBweCknLCB2YWx1ZTogMjAgfSwgeyBsYWJlbDogJ0xhcmdlICg0MHB4KScsIHZhbHVlOiA0MCB9LCB7IGxhYmVsOiAnWC1MYXJnZSAoNjBweCknLCB2YWx1ZTogNjAgfV1cIiBjbGFzcz1cImRyb3Bkb3duLWl0ZW1cIiAoY2xpY2spPVwiaGFuZGxlSXRlbUNsaWNrKHVwZGF0ZUJydXNoVGhpY2tuZXNzLCAnZnJlZWhhbmQnLCBpdGVtLnZhbHVlKVwiIHN0eWxlPVwicGFkZGluZzogNXB4O1wiPlxyXG4gICAgICAgICAgICB7eyBpdGVtLmxhYmVsIH19XHJcbiAgICAgICAgICA8L2J1dHRvbj5cclxuICAgICAgICA8L2Rpdj5cclxuICAgICAgPC9kaXY+XHJcbiAgICAgIDxkaXYgY2xhc3M9XCJidG4tZ3JvdXBcIiByb2xlPVwiZ3JvdXBcIj5cclxuICAgICAgICA8YnV0dG9uIGNsYXNzPVwiYnRuIGJ0bkJvYXJkIGJ0bi1zZWNvbmRhcnkgZHJvcGRvd24tdG9nZ2xlXCIgaWQ9XCJzaGFwZU1vZGVcIiAoY2xpY2spPVwiaGFuZGxlRHJvcGRvd25DbGljaygnc2hhcGVNb2RlJylcIj5cclxuICAgICAgICAgIDxmYS1pY29uIFtpY29uXT1cImZhU2hhcGVzXCI+PC9mYS1pY29uPlxyXG4gICAgICAgIDwvYnV0dG9uPlxyXG4gICAgICAgIDxkaXYgKm5nSWY9XCJkcm9wZG93bk9wZW4gPT09ICdzaGFwZU1vZGUnXCIgY2xhc3M9XCJkcm9wZG93bi1tZW51IHNob3dcIj5cclxuICAgICAgICAgIDxidXR0b24gKm5nRm9yPVwibGV0IGl0ZW0gb2YgW1xyXG4gICAgICAgICAgICB7IGxhYmVsOiAnPGltZyBzcmM9XFwnaHR0cHM6Ly9tZWRpYXNmdS5jb20vaW1hZ2VzL3N2Zy9zcXVhcmUuc3ZnXFwnIGFsdD1cXCdTcXVhcmVcXCcgY2xhc3M9XFwnc2hhcGUtaWNvblxcJyAvPicsIHZhbHVlOiAnc3F1YXJlJyB9LFxyXG4gICAgICAgICAgICB7IGxhYmVsOiAnPGltZyBzcmM9XFwnaHR0cHM6Ly9tZWRpYXNmdS5jb20vaW1hZ2VzL3N2Zy9yZWN0YW5nbGUuc3ZnXFwnIGFsdD1cXCdSZWN0YW5nbGVcXCcgY2xhc3M9XFwnc2hhcGUtaWNvblxcJyAvPicsIHZhbHVlOiAncmVjdGFuZ2xlJyB9LFxyXG4gICAgICAgICAgICB7IGxhYmVsOiAnPGltZyBzcmM9XFwnaHR0cHM6Ly9tZWRpYXNmdS5jb20vaW1hZ2VzL3N2Zy9jaXJjbGUuc3ZnXFwnIGFsdD1cXCdDaXJjbGVcXCcgY2xhc3M9XFwnc2hhcGUtaWNvblxcJyAvPicsIHZhbHVlOiAnY2lyY2xlJyB9LFxyXG4gICAgICAgICAgICB7IGxhYmVsOiAnPGltZyBzcmM9XFwnaHR0cHM6Ly9tZWRpYXNmdS5jb20vaW1hZ2VzL3N2Zy90cmlhbmdsZS5zdmdcXCcgYWx0PVxcJ1RyaWFuZ2xlXFwnIGNsYXNzPVxcJ3NoYXBlLWljb25cXCcgLz4nLCB2YWx1ZTogJ3RyaWFuZ2xlJyB9LFxyXG4gICAgICAgICAgICB7IGxhYmVsOiAnPGltZyBzcmM9XFwnaHR0cHM6Ly9tZWRpYXNmdS5jb20vaW1hZ2VzL3N2Zy9oZXhhZ29uLnN2Z1xcJyBhbHQ9XFwnSGV4YWdvblxcJyBjbGFzcz1cXCdzaGFwZS1pY29uXFwnIC8+JywgdmFsdWU6ICdoZXhhZ29uJyB9LFxyXG4gICAgICAgICAgICB7IGxhYmVsOiAnPGltZyBzcmM9XFwnaHR0cHM6Ly9tZWRpYXNmdS5jb20vaW1hZ2VzL3N2Zy9wZW50YWdvbi5zdmdcXCcgYWx0PVxcJ1BlbnRhZ29uXFwnIGNsYXNzPVxcJ3NoYXBlLWljb25cXCcgLz4nLCB2YWx1ZTogJ3BlbnRhZ29uJyB9LFxyXG4gICAgICAgICAgICB7IGxhYmVsOiAnPGltZyBzcmM9XFwnaHR0cHM6Ly9tZWRpYXNmdS5jb20vaW1hZ2VzL3N2Zy9yaG9tYnVzLnN2Z1xcJyBhbHQ9XFwnUmhvbWJ1c1xcJyBjbGFzcz1cXCdzaGFwZS1pY29uXFwnIC8+JywgdmFsdWU6ICdyaG9tYnVzJyB9LFxyXG4gICAgICAgICAgICB7IGxhYmVsOiAnPGltZyBzcmM9XFwnaHR0cHM6Ly9tZWRpYXNmdS5jb20vaW1hZ2VzL3N2Zy9vY3RhZ29uLnN2Z1xcJyBhbHQ9XFwnT2N0YWdvblxcJyBjbGFzcz1cXCdzaGFwZS1pY29uXFwnIC8+JywgdmFsdWU6ICdvY3RhZ29uJyB9LFxyXG4gICAgICAgICAgICB7IGxhYmVsOiAnPGltZyBzcmM9XFwnaHR0cHM6Ly9tZWRpYXNmdS5jb20vaW1hZ2VzL3N2Zy9wYXJhbGxlbG9ncmFtLnN2Z1xcJyBhbHQ9XFwnUGFyYWxsZWxvZ3JhbVxcJyBjbGFzcz1cXCdzaGFwZS1pY29uXFwnIC8+JywgdmFsdWU6ICdwYXJhbGxlbG9ncmFtJyB9LFxyXG4gICAgICAgICAgICB7IGxhYmVsOiAnPGltZyBzcmM9XFwnaHR0cHM6Ly9tZWRpYXNmdS5jb20vaW1hZ2VzL3N2Zy9vdmFsLnN2Z1xcJyBhbHQ9XFwnT3ZhbFxcJyBjbGFzcz1cXCdzaGFwZS1pY29uXFwnIC8+JywgdmFsdWU6ICdvdmFsJyB9XHJcbiAgICAgICAgICBdXCIgY2xhc3M9XCJkcm9wZG93bi1pdGVtXCIgKGNsaWNrKT1cImhhbmRsZUl0ZW1DbGljayh1cGRhdGVTaGFwZSwgJ3NoYXBlJywgaXRlbS52YWx1ZSlcIiBzdHlsZT1cInBhZGRpbmc6IDVweDtcIiBbaW5uZXJIVE1MXT1cIml0ZW0ubGFiZWxcIj5cclxuICAgICAgICAgIDwvYnV0dG9uPlxyXG4gICAgICAgIDwvZGl2PlxyXG4gICAgICA8L2Rpdj5cclxuICAgICAgPGJ1dHRvbiBjbGFzcz1cImJ0biBidG5Cb2FyZCBidG4tc2Vjb25kYXJ5XCIgaWQ9XCJzZWxlY3RNb2RlXCIgKGNsaWNrKT1cImNoYW5nZU1vZGUoJ3NlbGVjdCcpXCI+XHJcbiAgICAgICAgPGZhLWljb24gW2ljb25dPVwiZmFNb3VzZVBvaW50ZXJcIj48L2ZhLWljb24+XHJcbiAgICAgIDwvYnV0dG9uPlxyXG4gICAgICA8ZGl2IGNsYXNzPVwiYnRuLWdyb3VwXCIgcm9sZT1cImdyb3VwXCI+XHJcbiAgICAgICAgPGJ1dHRvbiBjbGFzcz1cImJ0biBidG5Cb2FyZCBidG4tZGFuZ2VyIGRyb3Bkb3duLXRvZ2dsZVwiIGlkPVwiZXJhc2VNb2RlXCIgKGNsaWNrKT1cImhhbmRsZURyb3Bkb3duQ2xpY2soJ2VyYXNlTW9kZScpXCI+XHJcbiAgICAgICAgICA8ZmEtaWNvbiBbaWNvbl09XCJmYUVyYXNlclwiPjwvZmEtaWNvbj5cclxuICAgICAgICA8L2J1dHRvbj5cclxuICAgICAgICA8ZGl2ICpuZ0lmPVwiZHJvcGRvd25PcGVuID09PSAnZXJhc2VNb2RlJ1wiIGNsYXNzPVwiZHJvcGRvd24tbWVudSBzaG93XCI+XHJcbiAgICAgICAgICA8YnV0dG9uICpuZ0Zvcj1cImxldCBpdGVtIG9mIFt7IGxhYmVsOiAnWC1TbWFsbCAoNXB4KScsIHZhbHVlOiA1IH0sIHsgbGFiZWw6ICdTbWFsbCAoMTBweCknLCB2YWx1ZTogMTAgfSwgeyBsYWJlbDogJ01lZGl1bSAoMjBweCknLCB2YWx1ZTogMjAgfSwgeyBsYWJlbDogJ0xhcmdlICgzMHB4KScsIHZhbHVlOiAzMCB9LCB7IGxhYmVsOiAnWC1MYXJnZSAoNjBweCknLCB2YWx1ZTogNjAgfV1cIiBjbGFzcz1cImRyb3Bkb3duLWl0ZW1cIiAoY2xpY2spPVwiaGFuZGxlSXRlbUNsaWNrKHVwZGF0ZUVyYXNlclRoaWNrbmVzcywgJ2VyYXNlJywgaXRlbS52YWx1ZSlcIiBzdHlsZT1cInBhZGRpbmc6IDVweDtcIj5cclxuICAgICAgICAgICAge3sgaXRlbS5sYWJlbCB9fVxyXG4gICAgICAgICAgPC9idXR0b24+XHJcbiAgICAgICAgPC9kaXY+XHJcbiAgICAgIDwvZGl2PlxyXG4gICAgICA8YnV0dG9uIGNsYXNzPVwiYnRuIGJ0bkJvYXJkIGJ0bi1pbmZvXCIgaWQ9XCJwYW5Nb2RlXCIgKGNsaWNrKT1cImNoYW5nZU1vZGUoJ3BhbicpXCI+XHJcbiAgICAgICAgPGZhLWljb24gW2ljb25dPVwiZmFIYW5kUGFwZXJcIj48L2ZhLWljb24+XHJcbiAgICAgIDwvYnV0dG9uPlxyXG4gICAgICA8YnV0dG9uIGNsYXNzPVwiYnRuIGJ0bkJvYXJkIGJ0bi1zdWNjZXNzXCIgaWQ9XCJ6b29tSW5cIiAoY2xpY2spPVwiem9vbUNhbnZhcygxLjIsICRldmVudClcIj5cclxuICAgICAgICA8ZmEtaWNvbiBbaWNvbl09XCJmYVNlYXJjaFBsdXNcIj48L2ZhLWljb24+XHJcbiAgICAgIDwvYnV0dG9uPlxyXG4gICAgICA8YnV0dG9uIGNsYXNzPVwiYnRuIGJ0bkJvYXJkIGJ0bi1zdWNjZXNzXCIgaWQ9XCJ6b29tUmVzZXRcIiAoY2xpY2spPVwiem9vbUNhbnZhcygxMCwgJGV2ZW50KVwiPlxyXG4gICAgICAgIDxmYS1pY29uIFtpY29uXT1cImZhU2VhcmNoXCI+PC9mYS1pY29uPlxyXG4gICAgICA8L2J1dHRvbj5cclxuICAgICAgPGJ1dHRvbiBjbGFzcz1cImJ0biBidG5Cb2FyZCBidG4tc3VjY2Vzc1wiIGlkPVwiem9vbU91dFwiIChjbGljayk9XCJ6b29tQ2FudmFzKDAuOCwgJGV2ZW50KVwiPlxyXG4gICAgICAgIDxmYS1pY29uIFtpY29uXT1cImZhU2VhcmNoTWludXNcIj48L2ZhLWljb24+XHJcbiAgICAgIDwvYnV0dG9uPlxyXG4gICAgICA8ZGl2IGNsYXNzPVwiYnRuLWdyb3VwXCIgcm9sZT1cImdyb3VwXCI+XHJcbiAgICAgICAgPGJ1dHRvbiBjbGFzcz1cImJ0biBidG5Cb2FyZCBidG4tc2Vjb25kYXJ5IGRyb3Bkb3duLXRvZ2dsZVwiIGlkPVwiYWRkVGV4dFwiIChjbGljayk9XCJoYW5kbGVEcm9wZG93bkNsaWNrKCdhZGRUZXh0JylcIj5cclxuICAgICAgICAgIDxmYS1pY29uIFtpY29uXT1cImZhRm9udFwiPjwvZmEtaWNvbj5cclxuICAgICAgICA8L2J1dHRvbj5cclxuICAgICAgICA8ZGl2ICpuZ0lmPVwiZHJvcGRvd25PcGVuID09PSAnYWRkVGV4dCdcIiBjbGFzcz1cImRyb3Bkb3duLW1lbnUgc2hvd1wiPlxyXG4gICAgICAgICAgPGJ1dHRvbiAqbmdGb3I9XCJsZXQgaXRlbSBvZiBbeyBsYWJlbDogJ0FyaWFsJywgdmFsdWU6ICdBcmlhbCcgfSwgeyBsYWJlbDogJ1RpbWVzIE5ldyBSb21hbicsIHZhbHVlOiAnVGltZXMgTmV3IFJvbWFuJyB9LCB7IGxhYmVsOiAnQ291cmllciBOZXcnLCB2YWx1ZTogJ0NvdXJpZXIgTmV3JyB9LCB7IGxhYmVsOiAnVmVyZGFuYScsIHZhbHVlOiAnVmVyZGFuYScgfV1cIiBjbGFzcz1cImRyb3Bkb3duLWl0ZW1cIiAoY2xpY2spPVwiaGFuZGxlSXRlbUNsaWNrKHVwZGF0ZUZvbnQsICd0ZXh0JywgaXRlbS52YWx1ZSlcIiBzdHlsZT1cInBhZGRpbmc6IDVweDtcIj5cclxuICAgICAgICAgICAge3sgaXRlbS5sYWJlbCB9fVxyXG4gICAgICAgICAgPC9idXR0b24+XHJcbiAgICAgICAgPC9kaXY+XHJcbiAgICAgIDwvZGl2PlxyXG4gICAgICA8ZGl2IGNsYXNzPVwiYnRuLWdyb3VwXCIgcm9sZT1cImdyb3VwXCI+XHJcbiAgICAgICAgPGJ1dHRvbiBjbGFzcz1cImJ0biBidG5Cb2FyZCBidG4tc2Vjb25kYXJ5IGRyb3Bkb3duLXRvZ2dsZVwiIGlkPVwiZm9udFNpemVcIiAoY2xpY2spPVwiaGFuZGxlRHJvcGRvd25DbGljaygnZm9udFNpemUnKVwiPlxyXG4gICAgICAgICAgPGZhLWljb24gW2ljb25dPVwiZmFUZXh0SGVpZ2h0XCI+PC9mYS1pY29uPlxyXG4gICAgICAgIDwvYnV0dG9uPlxyXG4gICAgICAgIDxkaXYgKm5nSWY9XCJkcm9wZG93bk9wZW4gPT09ICdmb250U2l6ZSdcIiBjbGFzcz1cImRyb3Bkb3duLW1lbnUgc2hvd1wiPlxyXG4gICAgICAgICAgPGJ1dHRvbiAqbmdGb3I9XCJsZXQgaXRlbSBvZiBbeyBsYWJlbDogJ1gtU21hbGwgKDVweCknLCB2YWx1ZTogNSB9LCB7IGxhYmVsOiAnU21hbGwgKDEwcHgpJywgdmFsdWU6IDEwIH0sIHsgbGFiZWw6ICdNZWRpdW0gKDIwcHgpJywgdmFsdWU6IDIwIH0sIHsgbGFiZWw6ICdMYXJnZSAoNDBweCknLCB2YWx1ZTogNDAgfSwgeyBsYWJlbDogJ1gtTGFyZ2UgKDYwcHgpJywgdmFsdWU6IDYwIH1dXCIgY2xhc3M9XCJkcm9wZG93bi1pdGVtXCIgKGNsaWNrKT1cImhhbmRsZUl0ZW1DbGljayh1cGRhdGVGb250U2l6ZSwgJycsIGl0ZW0udmFsdWUpXCIgc3R5bGU9XCJwYWRkaW5nOiA1cHg7XCI+XHJcbiAgICAgICAgICAgIHt7IGl0ZW0ubGFiZWwgfX1cclxuICAgICAgICAgIDwvYnV0dG9uPlxyXG4gICAgICAgIDwvZGl2PlxyXG4gICAgICA8L2Rpdj5cclxuICAgICAgPGJ1dHRvbiBjbGFzcz1cImJ0biBidG5Cb2FyZCBidG4tc2Vjb25kYXJ5XCIgaWQ9XCJ1bmRvXCIgKGNsaWNrKT1cInVuZG8oKVwiPlxyXG4gICAgICAgIDxmYS1pY29uIFtpY29uXT1cImZhVW5kb1wiPjwvZmEtaWNvbj5cclxuICAgICAgPC9idXR0b24+XHJcbiAgICAgIDxidXR0b24gY2xhc3M9XCJidG4gYnRuQm9hcmQgYnRuLXNlY29uZGFyeVwiIGlkPVwicmVkb1wiIChjbGljayk9XCJyZWRvKClcIj5cclxuICAgICAgICA8ZmEtaWNvbiBbaWNvbl09XCJmYVJlZG9cIj48L2ZhLWljb24+XHJcbiAgICAgIDwvYnV0dG9uPlxyXG4gICAgICA8YnV0dG9uIGNsYXNzPVwiYnRuIGJ0bkJvYXJkIGJ0bi1zZWNvbmRhcnlcIiBpZD1cInNhdmVcIiAoY2xpY2spPVwic2F2ZUNhbnZhcygpXCI+XHJcbiAgICAgICAgPGZhLWljb24gW2ljb25dPVwiZmFTYXZlXCI+PC9mYS1pY29uPlxyXG4gICAgICA8L2J1dHRvbj5cclxuICAgICAgPGJ1dHRvbiBjbGFzcz1cImJ0biBidG5Cb2FyZCBidG4tZGFuZ2VyXCIgaWQ9XCJkZWxldGVcIiAoY2xpY2spPVwiZGVsZXRlU2hhcGUoKVwiPlxyXG4gICAgICAgIDxmYS1pY29uIFtpY29uXT1cImZhVHJhc2hcIj48L2ZhLWljb24+XHJcbiAgICAgIDwvYnV0dG9uPlxyXG4gICAgICA8YnV0dG9uIGNsYXNzPVwiYnRuIGJ0bkJvYXJkIGJ0bi1zZWNvbmRhcnlcIiBpZD1cImNsZWFyQ2FudmFzXCIgKGNsaWNrKT1cImNsZWFyQ2FudmFzKClcIj5cclxuICAgICAgICA8ZmEtaWNvbiBbaWNvbl09XCJmYVRpbWVzXCI+PC9mYS1pY29uPlxyXG4gICAgICA8L2J1dHRvbj5cclxuICAgICAgPGJ1dHRvbiBpZD1cInRvZ2dsZUJhY2tncm91bmRSZWZcIiAjdG9nZ2xlQmFja2dyb3VuZFJlZiBjbGFzcz1cImJ0biBidG5Cb2FyZCBidG4tc2Vjb25kYXJ5XCIgKGNsaWNrKT1cInRvZ2dsZUJhY2tncm91bmQoKVwiPlxyXG4gICAgICAgIDxpbWcgc3JjPVwiaHR0cHM6Ly9tZWRpYXNmdS5jb20vaW1hZ2VzL3N2Zy9ncmFwaC5qcGdcIiBhbHQ9XCJCYWNrZ3JvdW5kXCIgY2xhc3M9XCJ0b2dnbGUtaWNvblwiIGlkPVwiYmFja2dyb3VuZEljb25cIiAvPlxyXG4gICAgICA8L2J1dHRvbj5cclxuICAgICAgPGlucHV0IHR5cGU9XCJmaWxlXCIgaWQ9XCJ1cGxvYWRCb2FyZEltYWdlXCIgYWNjZXB0PVwiaW1hZ2UvKlwiIHN0eWxlPVwiZGlzcGxheTogbm9uZTtcIiAoY2hhbmdlKT1cInVwbG9hZEltYWdlKCRldmVudClcIiAvPlxyXG4gICAgICA8bGFiZWwgZm9yPVwidXBsb2FkQm9hcmRJbWFnZVwiIGNsYXNzPVwiYnRuIGJ0bkJvYXJkIGJ0bi1wcmltYXJ5XCI+XHJcbiAgICAgICAgPGZhLWljb24gW2ljb25dPVwiZmFVcGxvYWRcIj48L2ZhLWljb24+XHJcbiAgICAgIDwvbGFiZWw+XHJcbiAgICAgIDxpbnB1dCB0eXBlPVwiY29sb3JcIiBpZD1cImNvbG9yUGlja2VyXCIgY2xhc3M9XCJidG5cIiBbKG5nTW9kZWwpXT1cImNvbG9yXCIgLz5cclxuICAgICAgPHNlbGVjdCBpZD1cImxpbmVUeXBlUGlja2VyXCIgY2xhc3M9XCJjdXN0b20tc2VsZWN0XCIgc3R5bGU9XCJ3aWR0aDogYXV0bztcIiBbKG5nTW9kZWwpXT1cImxpbmVUeXBlXCI+XHJcbiAgICAgICAgPG9wdGlvbiB2YWx1ZT1cInNvbGlkXCI+U29saWQ8L29wdGlvbj5cclxuICAgICAgICA8b3B0aW9uIHZhbHVlPVwiZGFzaGVkXCI+RGFzaGVkPC9vcHRpb24+XHJcbiAgICAgICAgPG9wdGlvbiB2YWx1ZT1cImRvdHRlZFwiPkRvdHRlZDwvb3B0aW9uPlxyXG4gICAgICAgIDxvcHRpb24gdmFsdWU9XCJkYXNoRG90XCI+RGFzaC1Eb3Q8L29wdGlvbj5cclxuICAgICAgPC9zZWxlY3Q+XHJcbiAgICA8L2Rpdj5cclxuICAgIDxjYW52YXMgaWQ9XCJjYW52YXNSZWZcIiB3aWR0aD1cIjEyODBcIiBoZWlnaHQ9XCI3MjBcIiBzdHlsZT1cImJvcmRlcjogMnB4IHNvbGlkIHJlZDtcIiAjY2FudmFzUmVmPjwvY2FudmFzPlxyXG4gICAgPHRleHRhcmVhIGlkPVwidGV4dElucHV0UmVmXCIgY2xhc3M9XCJmb3JtLWNvbnRyb2xcIiAjdGV4dElucHV0UmVmIHN0eWxlPVwiZGlzcGxheTogbm9uZTsgcG9zaXRpb246IGFic29sdXRlO1wiPjwvdGV4dGFyZWE+XHJcbiAgICA8YSBocmVmPVwiI1wiIGlkPVwiZG93bmxvYWRMaW5rUmVmXCIgI2Rvd25sb2FkTGlua1JlZiBzdHlsZT1cImRpc3BsYXk6IG5vbmU7XCI+RG93bmxvYWQ8L2E+XHJcbiAgICA8Y2FudmFzIGlkPVwidGVtcENhbnZhc1JlZlwiICN0ZW1wQ2FudmFzUmVmIHN0eWxlPVwiZGlzcGxheTogbm9uZTtcIj48L2NhbnZhcz5cclxuICA8L2Rpdj5cclxuPC9kaXY+XHJcbiJdfQ==
|