diff --git a/CHANGELOG.md b/CHANGELOG.md index 8084d93..6f982c1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +### 1.1 +* Moved Filesharing code out from React code to RoomClient +* Major cleanup of CSS. Variables for most colors and sizes exposed in :root +* Started using React Context instead of middleware +* Small fixes to buttons and layout + ### 1.0 * Fixed toolarea button based on feedback from users * Added possibility to move video to separate window diff --git a/app/.babelrc b/app/.babelrc index b566ca5..3aadd5a 100644 --- a/app/.babelrc +++ b/app/.babelrc @@ -2,6 +2,7 @@ "plugins": [ "@babel/plugin-proposal-object-rest-spread", + "jsx-control-statements", "@babel/plugin-proposal-class-properties", "@babel/plugin-transform-runtime" ], diff --git a/app/.eslintrc.js b/app/.eslintrc.js index ebced28..9231726 100644 --- a/app/.eslintrc.js +++ b/app/.eslintrc.js @@ -15,7 +15,8 @@ module.exports = extends: [ 'eslint:recommended', - 'plugin:react/recommended' + 'plugin:react/recommended', + 'plugin:jsx-control-statements/recommended' ], settings: { diff --git a/app/lib/RoomClient.js b/app/lib/RoomClient.js index a902c73..6700f5a 100644 --- a/app/lib/RoomClient.js +++ b/app/lib/RoomClient.js @@ -1,5 +1,8 @@ import io from 'socket.io-client'; import * as mediasoupClient from 'mediasoup-client'; +import WebTorrent from 'webtorrent'; +import createTorrent from 'create-torrent'; +import { saveAs } from 'file-saver/FileSaver'; import Logger from './Logger'; import hark from 'hark'; import ScreenShare from './ScreenShare'; @@ -30,10 +33,21 @@ const VIDEO_CONSTRAINS = aspectRatio : 1.334 }; +let store; + export default class RoomClient { + /** + * @param {Object} data + * @param {Object} data.store - The Redux store. + */ + static init(data) + { + store = data.store; + } + constructor( - { roomId, peerName, displayName, device, useSimulcast, produce, dispatch, getState }) + { roomId, peerName, displayName, device, useSimulcast, produce }) { logger.debug( 'constructor() [roomId:"%s", peerName:"%s", displayName:"%s", device:%s]', @@ -50,15 +64,12 @@ export default class RoomClient // Whether we should produce. this._produce = produce; + // Torrent support + this._torrentSupport = WebTorrent.WEBRTC_SUPPORT; + // Whether simulcast should be used. this._useSimulcast = useSimulcast; - // Redux store dispatch function. - this._dispatch = dispatch; - - // Redux store getState function. - this._getState = getState; - // This device this._device = device; @@ -78,6 +89,15 @@ export default class RoomClient this._room = new mediasoupClient.Room(ROOM_OPTIONS); this._room.roomId = roomId; + // Our WebTorrent client + this._webTorrent = this._torrentSupport && new WebTorrent({ + tracker : { + rtcConfig : { + iceServers : ROOM_OPTIONS.turnServers + } + } + }); + // Max spotlights this._maxSpotlights = ROOM_OPTIONS.maxSpotlights; @@ -139,7 +159,7 @@ export default class RoomClient // the 'leaveRoom' notification). setTimeout(() => this._signalingSocket.close(), 250); - this._dispatch(stateActions.setRoomState('closed')); + store.dispatch(stateActions.setRoomState('closed')); } _startKeyListener() @@ -161,21 +181,21 @@ export default class RoomClient { case 'a': // Activate advanced mode { - this._dispatch(stateActions.toggleAdvancedMode()); + store.dispatch(stateActions.toggleAdvancedMode()); this.notify('Toggled advanced mode.'); break; } case '1': // Set democratic view { - this._dispatch(stateActions.setDisplayMode('democratic')); + store.dispatch(stateActions.setDisplayMode('democratic')); this.notify('Changed layout to democratic view.'); break; } case '2': // Set filmstrip view { - this._dispatch(stateActions.setDisplayMode('filmstrip')); + store.dispatch(stateActions.setDisplayMode('filmstrip')); this.notify('Changed layout to filmstrip view.'); break; } @@ -225,7 +245,7 @@ export default class RoomClient notify(text) { - this._dispatch(requestActions.notify({ text: text })); + store.dispatch(requestActions.notify({ text: text })); } timeoutCallback(callback) @@ -290,7 +310,7 @@ export default class RoomClient { await this.sendRequest('change-display-name', { displayName }); - this._dispatch(stateActions.setDisplayName(displayName)); + store.dispatch(stateActions.setDisplayName(displayName)); this.notify(`Your display name changed to ${displayName}.`); } @@ -302,7 +322,7 @@ export default class RoomClient // We need to refresh the component for it to render the previous // displayName again. - this._dispatch(stateActions.setDisplayName()); + store.dispatch(stateActions.setDisplayName()); } } @@ -326,6 +346,9 @@ export default class RoomClient try { + store.dispatch( + stateActions.addUserMessage(chatMessage.text)); + await this.sendRequest('chat-message', { chatMessage }); } catch (error) @@ -336,7 +359,130 @@ export default class RoomClient } } - async sendFile(file) + saveFile(file) + { + file.getBlob((err, blob) => + { + if (err) + { + return this.notify('An error occurred while saving a file'); + } + + saveAs(blob, file.name); + }); + } + + handleDownload(magnetUri) + { + store.dispatch( + stateActions.setFileActive(magnetUri)); + + const existingTorrent = this._webTorrent.get(magnetUri); + + if (existingTorrent) + { + // Never add duplicate torrents, use the existing one instead. + return this._handleTorrent(existingTorrent); + } + + this._webTorrent.add(magnetUri, this._handleTorrent); + } + + _handleTorrent(torrent) + { + // Torrent already done, this can happen if the + // same file was sent multiple times. + if (torrent.progress === 1) + { + return store.dispatch( + stateActions.setFileDone( + torrent.magnetURI, + torrent.files + )); + } + + let lastMove = 0; + + torrent.on('download', () => + { + if (Date.now() - lastMove > 1000) + { + store.dispatch( + stateActions.setFileProgress( + torrent.magnetURI, + torrent.progress + )); + + lastMove = Date.now(); + } + }); + + torrent.on('done', () => + { + store.dispatch( + stateActions.setFileDone( + torrent.magnetURI, + torrent.files + )); + }); + } + + async shareFiles(files) + { + this.notify('Creating torrent'); + + createTorrent(files, (err, torrent) => + { + if (err) + { + return this.notify( + 'An error occured while uploading a file' + ); + } + + const existingTorrent = this._webTorrent.get(torrent); + + if (existingTorrent) + { + const { displayName, picture } = store.getState().me; + + const file = { + magnetUri : existingTorrent.magnetURI, + displayName, + picture + }; + + return this._sendFile(file); + } + + this._webTorrent.seed(files, (newTorrent) => + { + this.notify( + 'Torrent successfully created' + ); + + const { displayName, picture } = store.getState().me; + const file = { + magnetUri : newTorrent.magnetURI, + displayName, + picture + }; + + store.dispatch(stateActions.addFile( + { + magnetUri : file.magnetUri, + displayName : displayName, + picture : picture, + me : true + })); + + this._sendFile(file); + }); + }); + } + + // { file, name, picture } + async _sendFile(file) { logger.debug('sendFile() [file: %o]', file); @@ -367,7 +513,7 @@ export default class RoomClient if (chatHistory.length > 0) { logger.debug('Got chat history'); - this._dispatch( + store.dispatch( stateActions.addChatHistory(chatHistory)); } @@ -375,7 +521,7 @@ export default class RoomClient { logger.debug('Got files history'); - this._dispatch(stateActions.addFileHistory(fileHistory)); + store.dispatch(stateActions.addFileHistory(fileHistory)); } if (lastN.length > 0) @@ -466,7 +612,7 @@ export default class RoomClient return new Promise((resolve, reject) => { window.addEventListener('message', _onExtensionMessage, false); - // eslint-disable-next-line no-undef + // eslint-disable-next-line chrome.webstore.install(null, _successfulInstall, _failedInstall); function _onExtensionMessage({ data }) { @@ -494,7 +640,7 @@ export default class RoomClient .then(() => { // This should be handled better - this._dispatch(stateActions.setScreenCapabilities( + store.dispatch(stateActions.setScreenCapabilities( { canShareScreen : this._room.canSend('video'), needExtension : false @@ -510,7 +656,7 @@ export default class RoomClient { logger.debug('enableScreenSharing()'); - this._dispatch(stateActions.setScreenShareInProgress(true)); + store.dispatch(stateActions.setScreenShareInProgress(true)); try { @@ -521,7 +667,7 @@ export default class RoomClient logger.error('enableScreenSharing() | failed: %o', error); } - this._dispatch(stateActions.setScreenShareInProgress(false)); + store.dispatch(stateActions.setScreenShareInProgress(false)); } async enableWebcam() @@ -531,7 +677,7 @@ export default class RoomClient // Store in cookie. cookiesManager.setDevices({ webcamEnabled: true }); - this._dispatch(stateActions.setWebcamInProgress(true)); + store.dispatch(stateActions.setWebcamInProgress(true)); try { @@ -542,14 +688,14 @@ export default class RoomClient logger.error('enableWebcam() | failed: %o', error); } - this._dispatch(stateActions.setWebcamInProgress(false)); + store.dispatch(stateActions.setWebcamInProgress(false)); } async disableScreenSharing() { logger.debug('disableScreenSharing()'); - this._dispatch(stateActions.setScreenShareInProgress(true)); + store.dispatch(stateActions.setScreenShareInProgress(true)); try { @@ -560,7 +706,7 @@ export default class RoomClient logger.error('disableScreenSharing() | failed: %o', error); } - this._dispatch(stateActions.setScreenShareInProgress(false)); + store.dispatch(stateActions.setScreenShareInProgress(false)); } async disableWebcam() @@ -570,7 +716,7 @@ export default class RoomClient // Store in cookie. cookiesManager.setDevices({ webcamEnabled: false }); - this._dispatch(stateActions.setWebcamInProgress(true)); + store.dispatch(stateActions.setWebcamInProgress(true)); try { @@ -581,14 +727,14 @@ export default class RoomClient logger.error('disableWebcam() | failed: %o', error); } - this._dispatch(stateActions.setWebcamInProgress(false)); + store.dispatch(stateActions.setWebcamInProgress(false)); } async changeAudioDevice(deviceId) { logger.debug('changeAudioDevice() [deviceId: %s]', deviceId); - this._dispatch( + store.dispatch( stateActions.setAudioInProgress(true)); try @@ -642,13 +788,13 @@ export default class RoomClient if (volume !== this._micProducer.volume) { this._micProducer.volume = volume; - this._dispatch(stateActions.setProducerVolume(this._micProducer.id, volume)); + store.dispatch(stateActions.setProducerVolume(this._micProducer.id, volume)); } }); track.stop(); - this._dispatch( + store.dispatch( stateActions.setProducerTrack(this._micProducer.id, newTrack)); cookiesManager.setAudioDevice({ audioDeviceId: deviceId }); @@ -660,7 +806,7 @@ export default class RoomClient logger.error('changeAudioDevice() failed: %o', error); } - this._dispatch( + store.dispatch( stateActions.setAudioInProgress(false)); } @@ -668,7 +814,7 @@ export default class RoomClient { logger.debug('changeWebcam() [deviceId: %s]', deviceId); - this._dispatch( + store.dispatch( stateActions.setWebcamInProgress(true)); try @@ -704,7 +850,7 @@ export default class RoomClient track.stop(); - this._dispatch( + store.dispatch( stateActions.setProducerTrack(this._webcamProducer.id, newTrack)); cookiesManager.setVideoDevice({ videoDeviceId: deviceId }); @@ -716,69 +862,7 @@ export default class RoomClient logger.error('changeWebcam() failed: %o', error); } - this._dispatch( - stateActions.setWebcamInProgress(false)); - } - - async changeWebcamResolution() - { - logger.debug('changeWebcamResolution()'); - - let oldResolution; - let newResolution; - - this._dispatch( - stateActions.setWebcamInProgress(true)); - - try - { - oldResolution = this._webcam.resolution; - - switch (oldResolution) - { - case 'qvga': - newResolution = 'vga'; - break; - case 'vga': - newResolution = 'hd'; - break; - case 'hd': - newResolution = 'qvga'; - break; - } - - this._webcam.resolution = newResolution; - - const { device } = this._webcam; - - logger.debug('changeWebcamResolution() | calling getUserMedia()'); - - const stream = await navigator.mediaDevices.getUserMedia( - { - video : - { - deviceId : { exact: device.deviceId }, - ...VIDEO_CONSTRAINS - } - }); - - const track = stream.getVideoTracks()[0]; - - const newTrack = await this._webcamProducer.replaceTrack(track); - - track.stop(); - - this._dispatch( - stateActions.setProducerTrack(this._webcamProducer.id, newTrack)); - } - catch (error) - { - logger.error('changeWebcamResolution() failed: %o', error); - - this._webcam.resolution = oldResolution; - } - - this._dispatch( + store.dispatch( stateActions.setWebcamInProgress(false)); } @@ -788,16 +872,29 @@ export default class RoomClient this._spotlights.setPeerSpotlight(peerName); - this._dispatch( + store.dispatch( stateActions.setSelectedPeer(peerName)); } - async mutePeerAudio(peerName) + // type: mic/webcam/screen + // mute: true/false + modifyPeerConsumer(peerName, type, mute) { - logger.debug('mutePeerAudio() [peerName:"%s"]', peerName); + logger.debug( + 'modifyPeerConsumer() [peerName:"%s", type:"%s"]', + peerName, + type + ); - this._dispatch( - stateActions.setPeerAudioInProgress(peerName, true)); + if (type === 'mic') + store.dispatch( + stateActions.setPeerAudioInProgress(peerName, true)); + else if (type === 'webcam') + store.dispatch( + stateActions.setPeerVideoInProgress(peerName, true)); + else if (type === 'screen') + store.dispatch( + stateActions.setPeerScreenInProgress(peerName, true)); try { @@ -807,265 +904,45 @@ export default class RoomClient { for (const consumer of peer.consumers) { - if (consumer.appData.source !== 'mic') + if (consumer.appData.source !== type || !consumer.supported) continue; - await consumer.pause('mute-audio'); + if (mute) + consumer.pause(`mute-${type}`); + else + consumer.resume(); } } } } catch (error) { - logger.error('mutePeerAudio() failed: %o', error); + logger.error('modifyPeerConsumer() failed: %o', error); } - this._dispatch( - stateActions.setPeerAudioInProgress(peerName, false)); - } - - async unmutePeerAudio(peerName) - { - logger.debug('unmutePeerAudio() [peerName:"%s"]', peerName); - - this._dispatch( - stateActions.setPeerAudioInProgress(peerName, true)); - - try - { - for (const peer of this._room.peers) - { - if (peer.name === peerName) - { - for (const consumer of peer.consumers) - { - if (consumer.appData.source !== 'mic' || !consumer.supported) - continue; - - await consumer.resume(); - } - } - } - } - catch (error) - { - logger.error('unmutePeerAudio() failed: %o', error); - } - - this._dispatch( - stateActions.setPeerAudioInProgress(peerName, false)); - } - - async pausePeerVideo(peerName) - { - logger.debug('pausePeerVideo() [peerName:"%s"]', peerName); - - this._dispatch( - stateActions.setPeerVideoInProgress(peerName, true)); - - try - { - for (const peer of this._room.peers) - { - if (peer.name === peerName) - { - for (const consumer of peer.consumers) - { - if (consumer.appData.source !== 'webcam') - continue; - - await consumer.pause('pause-video'); - } - } - } - } - catch (error) - { - logger.error('pausePeerVideo() failed: %o', error); - } - - this._dispatch( - stateActions.setPeerVideoInProgress(peerName, false)); - } - - async resumePeerVideo(peerName) - { - logger.debug('resumePeerVideo() [peerName:"%s"]', peerName); - - this._dispatch( - stateActions.setPeerVideoInProgress(peerName, true)); - - try - { - for (const peer of this._room.peers) - { - if (peer.name === peerName) - { - for (const consumer of peer.consumers) - { - if (consumer.appData.source !== 'webcam' || !consumer.supported) - continue; - - await consumer.resume(); - } - } - } - } - catch (error) - { - logger.error('resumePeerVideo() failed: %o', error); - } - - this._dispatch( - stateActions.setPeerVideoInProgress(peerName, false)); - } - - async pausePeerScreen(peerName) - { - logger.debug('pausePeerScreen() [peerName:"%s"]', peerName); - - this._dispatch( - stateActions.setPeerScreenInProgress(peerName, true)); - - try - { - for (const peer of this._room.peers) - { - if (peer.name === peerName) - { - for (const consumer of peer.consumers) - { - if (consumer.appData.source !== 'screen') - continue; - - await consumer.pause('pause-screen'); - } - } - } - } - catch (error) - { - logger.error('pausePeerScreen() failed: %o', error); - } - - this._dispatch( - stateActions.setPeerScreenInProgress(peerName, false)); - } - - async resumePeerScreen(peerName) - { - logger.debug('resumePeerScreen() [peerName:"%s"]', peerName); - - this._dispatch( - stateActions.setPeerScreenInProgress(peerName, true)); - - try - { - for (const peer of this._room.peers) - { - if (peer.name === peerName) - { - for (const consumer of peer.consumers) - { - if (consumer.appData.source !== 'screen' || !consumer.supported) - continue; - - await consumer.resume(); - } - } - } - } - catch (error) - { - logger.error('resumePeerScreen() failed: %o', error); - } - - this._dispatch( - stateActions.setPeerScreenInProgress(peerName, false)); - } - - async enableAudioOnly() - { - logger.debug('enableAudioOnly()'); - - this._dispatch( - stateActions.setAudioOnlyInProgress(true)); - - try - { - if (this._webcamProducer) - await this._webcamProducer.close(); - - for (const peer of this._room.peers) - { - for (const consumer of peer.consumers) - { - if (consumer.kind !== 'video') - continue; - - await consumer.pause('audio-only-mode'); - } - } - - this._dispatch( - stateActions.setAudioOnlyState(true)); - } - catch (error) - { - logger.error('enableAudioOnly() failed: %o', error); - } - - this._dispatch( - stateActions.setAudioOnlyInProgress(false)); - } - - async disableAudioOnly() - { - logger.debug('disableAudioOnly()'); - - this._dispatch( - stateActions.setAudioOnlyInProgress(true)); - - try - { - if (!this._webcamProducer && this._room.canSend('video')) - await this.enableWebcam(); - - for (const peer of this._room.peers) - { - for (const consumer of peer.consumers) - { - if (consumer.kind !== 'video' || !consumer.supported) - continue; - - await consumer.resume(); - } - } - - this._dispatch( - stateActions.setAudioOnlyState(false)); - } - catch (error) - { - logger.error('disableAudioOnly() failed: %o', error); - } - - this._dispatch( - stateActions.setAudioOnlyInProgress(false)); + if (type === 'mic') + store.dispatch( + stateActions.setPeerAudioInProgress(peerName, false)); + else if (type === 'webcam') + store.dispatch( + stateActions.setPeerVideoInProgress(peerName, false)); + else if (type === 'screen') + store.dispatch( + stateActions.setPeerScreenInProgress(peerName, false)); } async sendRaiseHandState(state) { logger.debug('sendRaiseHandState: ', state); - this._dispatch( + store.dispatch( stateActions.setMyRaiseHandStateInProgress(true)); try { await this.sendRequest('raisehand-message', { raiseHandState: state }); - this._dispatch( + store.dispatch( stateActions.setMyRaiseHandState(state)); } catch (error) @@ -1075,10 +952,10 @@ export default class RoomClient this.notify(`An error occured while ${state ? 'raising' : 'lowering'} hand.`); // We need to refresh the component for it to render changed state - this._dispatch(stateActions.setMyRaiseHandState(!state)); + store.dispatch(stateActions.setMyRaiseHandState(!state)); } - this._dispatch( + store.dispatch( stateActions.setMyRaiseHandStateInProgress(false)); } @@ -1086,7 +963,7 @@ export default class RoomClient { logger.debug('restartIce()'); - this._dispatch( + store.dispatch( stateActions.setRestartIceInProgress(true)); try @@ -1101,14 +978,14 @@ export default class RoomClient // Make it artificially longer. setTimeout(() => { - this._dispatch( + store.dispatch( stateActions.setRestartIceInProgress(false)); }, 500); } _join({ displayName, device }) { - this._dispatch(stateActions.setRoomState('connecting')); + store.dispatch(stateActions.setRoomState('connecting')); this._signalingSocket.on('connect', () => { @@ -1127,7 +1004,7 @@ export default class RoomClient try { this._room.remoteClose({ cause: 'signaling disconnected' }); } catch (error) {} - this._dispatch(stateActions.setRoomState('connecting')); + store.dispatch(stateActions.setRoomState('connecting')); }); this._signalingSocket.on('close', () => @@ -1151,7 +1028,7 @@ export default class RoomClient { const { peerName } = data; - this._dispatch( + store.dispatch( stateActions.setRoomActiveSpeaker(peerName)); if (peerName && peerName !== this._peerName) @@ -1177,7 +1054,7 @@ export default class RoomClient peer.appData.displayName = displayName; - this._dispatch( + store.dispatch( stateActions.setPeerDisplayName(displayName, peerName)); this.notify(`${oldDisplayName} changed their display name to ${displayName}.`); @@ -1187,7 +1064,7 @@ export default class RoomClient { const { peerName, picture } = data; - this._dispatch(stateActions.setPeerPicture(peerName, picture)); + store.dispatch(stateActions.setPeerPicture(peerName, picture)); }); // This means: server wants to change MY user information @@ -1198,8 +1075,8 @@ export default class RoomClient this.changeDisplayName(data.name); this.changeProfilePicture(data.picture); - this._dispatch(stateActions.setPicture(data.picture)); - this._dispatch(stateActions.loggedIn()); + store.dispatch(stateActions.setPicture(data.picture)); + store.dispatch(stateActions.loggedIn()); this.notify('You are logged in.'); @@ -1224,7 +1101,7 @@ export default class RoomClient this.notify(`${peer.appData.displayName} ${raiseHandState ? 'raised' : 'lowered'} their hand.`); - this._dispatch( + store.dispatch( stateActions.setPeerRaiseHandState(peerName, raiseHandState)); }); @@ -1234,12 +1111,12 @@ export default class RoomClient logger.debug('Got chat from "%s"', peerName); - this._dispatch( + store.dispatch( stateActions.addResponseMessage({ ...chatMessage, peerName })); - if (!this._getState().toolarea.toolAreaOpen || - (this._getState().toolarea.toolAreaOpen && - this._getState().toolarea.currentToolTab !== 'chat')) // Make sound + if (!store.getState().toolarea.toolAreaOpen || + (store.getState().toolarea.toolAreaOpen && + store.getState().toolarea.currentToolTab !== 'chat')) // Make sound { this._soundNotification(); } @@ -1259,13 +1136,13 @@ export default class RoomClient return; } - this._dispatch(stateActions.addFile(file)); + store.dispatch(stateActions.addFile(file)); this.notify(`${peer.appData.displayName} shared a file.`); - if (!this._getState().toolarea.toolAreaOpen || - (this._getState().toolarea.toolAreaOpen && - this._getState().toolarea.currentToolTab !== 'files')) // Make sound + if (!store.getState().toolarea.toolAreaOpen || + (store.getState().toolarea.toolAreaOpen && + store.getState().toolarea.currentToolTab !== 'files')) // Make sound { this._soundNotification(); } @@ -1287,7 +1164,7 @@ export default class RoomClient { logger.warn('mediasoup Peer/Room remotely closed [appData:%o]', appData); - this._dispatch(stateActions.setRoomState('closed')); + store.dispatch(stateActions.setRoomState('closed')); return; } @@ -1330,6 +1207,9 @@ export default class RoomClient { await this._room.join(this._peerName, { displayName, device }); + store.dispatch( + stateActions.setFileSharingSupported(this._torrentSupport)); + this._sendTransport = this._room.createTransport('send', { media: 'SEND_MIC_WEBCAM' }); @@ -1350,12 +1230,12 @@ export default class RoomClient }); // Set our media capabilities. - this._dispatch(stateActions.setMediaCapabilities( + store.dispatch(stateActions.setMediaCapabilities( { canSendMic : this._room.canSend('audio'), canSendWebcam : this._room.canSend('video') })); - this._dispatch(stateActions.setScreenCapabilities( + store.dispatch(stateActions.setScreenCapabilities( { canShareScreen : this._room.canSend('video') && this._screenSharing.isScreenShareAvailable(), @@ -1378,10 +1258,10 @@ export default class RoomClient } } - this._dispatch(stateActions.setRoomState('connected')); + store.dispatch(stateActions.setRoomState('connected')); // Clean all the existing notifcations. - this._dispatch(stateActions.removeAllNotifications()); + store.dispatch(stateActions.removeAllNotifications()); this.getServerHistory(); @@ -1389,7 +1269,7 @@ export default class RoomClient this._spotlights.on('spotlights-updated', (spotlights) => { - this._dispatch(stateActions.setSpotlights(spotlights)); + store.dispatch(stateActions.setSpotlights(spotlights)); this.updateSpotlights(spotlights); }); @@ -1440,7 +1320,7 @@ export default class RoomClient this._micProducer = producer; - this._dispatch(stateActions.addProducer( + store.dispatch(stateActions.addProducer( { id : producer.id, source : 'mic', @@ -1460,7 +1340,7 @@ export default class RoomClient 'mic Producer "close" event [originator:%s]', originator); this._micProducer = null; - this._dispatch(stateActions.removeProducer(producer.id)); + store.dispatch(stateActions.removeProducer(producer.id)); }); producer.on('pause', (originator) => @@ -1468,7 +1348,7 @@ export default class RoomClient logger.debug( 'mic Producer "pause" event [originator:%s]', originator); - this._dispatch(stateActions.setProducerPaused(producer.id, originator)); + store.dispatch(stateActions.setProducerPaused(producer.id, originator)); }); producer.on('resume', (originator) => @@ -1476,7 +1356,7 @@ export default class RoomClient logger.debug( 'mic Producer "resume" event [originator:%s]', originator); - this._dispatch(stateActions.setProducerResumed(producer.id, originator)); + store.dispatch(stateActions.setProducerResumed(producer.id, originator)); }); producer.on('handled', () => @@ -1512,7 +1392,7 @@ export default class RoomClient if (volume !== producer.volume) { producer.volume = volume; - this._dispatch(stateActions.setProducerVolume(producer.id, volume)); + store.dispatch(stateActions.setProducerVolume(producer.id, volume)); } }); } @@ -1565,7 +1445,7 @@ export default class RoomClient this._screenSharingProducer = producer; - this._dispatch(stateActions.addProducer( + store.dispatch(stateActions.addProducer( { id : producer.id, source : 'screen', @@ -1583,7 +1463,7 @@ export default class RoomClient 'webcam Producer "close" event [originator:%s]', originator); this._screenSharingProducer = null; - this._dispatch(stateActions.removeProducer(producer.id)); + store.dispatch(stateActions.removeProducer(producer.id)); }); producer.on('trackended', (originator) => @@ -1599,7 +1479,7 @@ export default class RoomClient logger.debug( 'webcam Producer "pause" event [originator:%s]', originator); - this._dispatch(stateActions.setProducerPaused(producer.id, originator)); + store.dispatch(stateActions.setProducerPaused(producer.id, originator)); }); producer.on('resume', (originator) => @@ -1607,7 +1487,7 @@ export default class RoomClient logger.debug( 'webcam Producer "resume" event [originator:%s]', originator); - this._dispatch(stateActions.setProducerResumed(producer.id, originator)); + store.dispatch(stateActions.setProducerResumed(producer.id, originator)); }); producer.on('handled', () => @@ -1677,7 +1557,7 @@ export default class RoomClient this._webcamProducer = producer; - this._dispatch(stateActions.addProducer( + store.dispatch(stateActions.addProducer( { id : producer.id, source : 'webcam', @@ -1696,7 +1576,7 @@ export default class RoomClient 'webcam Producer "close" event [originator:%s]', originator); this._webcamProducer = null; - this._dispatch(stateActions.removeProducer(producer.id)); + store.dispatch(stateActions.removeProducer(producer.id)); }); producer.on('pause', (originator) => @@ -1704,7 +1584,7 @@ export default class RoomClient logger.debug( 'webcam Producer "pause" event [originator:%s]', originator); - this._dispatch(stateActions.setProducerPaused(producer.id, originator)); + store.dispatch(stateActions.setProducerPaused(producer.id, originator)); }); producer.on('resume', (originator) => @@ -1712,7 +1592,7 @@ export default class RoomClient logger.debug( 'webcam Producer "resume" event [originator:%s]', originator); - this._dispatch(stateActions.setProducerResumed(producer.id, originator)); + store.dispatch(stateActions.setProducerResumed(producer.id, originator)); }); producer.on('handled', () => @@ -1775,10 +1655,10 @@ export default class RoomClient else if (!this._audioDevices.has(currentAudioDeviceId)) this._audioDevice.device = array[0]; - this._dispatch( + store.dispatch( stateActions.setCanChangeAudioDevice(len >= 2)); if (len >= 1) - this._dispatch( + store.dispatch( stateActions.setAudioDevices(this._audioDevices)); } catch (error) @@ -1823,7 +1703,7 @@ export default class RoomClient this._webcam.device = array[0]; if (len >= 1) - this._dispatch( + store.dispatch( stateActions.setWebcamDevices(this._webcams)); } catch (error) @@ -1836,7 +1716,7 @@ export default class RoomClient { const displayName = peer.appData.displayName; - this._dispatch(stateActions.addPeer( + store.dispatch(stateActions.addPeer( { name : peer.name, displayName : displayName, @@ -1861,7 +1741,7 @@ export default class RoomClient 'peer "close" event [name:"%s", originator:%s]', peer.name, originator); - this._dispatch(stateActions.removePeer(peer.name)); + store.dispatch(stateActions.removePeer(peer.name)); if (this._room.joined) { @@ -1883,7 +1763,7 @@ export default class RoomClient { const codec = consumer.rtpParameters.codecs[0]; - this._dispatch(stateActions.addConsumer( + store.dispatch(stateActions.addConsumer( { id : consumer.id, peerName : consumer.peer.name, @@ -1903,7 +1783,7 @@ export default class RoomClient 'consumer "close" event [id:%s, originator:%s, consumer:%o]', consumer.id, originator, consumer); - this._dispatch(stateActions.removeConsumer( + store.dispatch(stateActions.removeConsumer( consumer.id, consumer.peer.name)); }); @@ -1938,7 +1818,7 @@ export default class RoomClient if (volume !== consumer.volume) { consumer.volume = volume; - this._dispatch(stateActions.setConsumerVolume(consumer.id, volume)); + store.dispatch(stateActions.setConsumerVolume(consumer.id, volume)); } }); } @@ -1950,7 +1830,7 @@ export default class RoomClient 'consumer "pause" event [id:%s, originator:%s, consumer:%o]', consumer.id, originator, consumer); - this._dispatch(stateActions.setConsumerPaused(consumer.id, originator)); + store.dispatch(stateActions.setConsumerPaused(consumer.id, originator)); }); consumer.on('resume', (originator) => @@ -1959,7 +1839,7 @@ export default class RoomClient 'consumer "resume" event [id:%s, originator:%s, consumer:%o]', consumer.id, originator, consumer); - this._dispatch(stateActions.setConsumerResumed(consumer.id, originator)); + store.dispatch(stateActions.setConsumerResumed(consumer.id, originator)); }); consumer.on('effectiveprofilechange', (profile) => @@ -1968,7 +1848,7 @@ export default class RoomClient 'consumer "effectiveprofilechange" event [id:%s, consumer:%o, profile:%s]', consumer.id, consumer, profile); - this._dispatch(stateActions.setConsumerEffectiveProfile(consumer.id, profile)); + store.dispatch(stateActions.setConsumerEffectiveProfile(consumer.id, profile)); }); // Receive the consumer (if we can). @@ -1985,7 +1865,7 @@ export default class RoomClient consumer.receive(this._recvTransport) .then((track) => { - this._dispatch(stateActions.setConsumerTrack(consumer.id, track)); + store.dispatch(stateActions.setConsumerTrack(consumer.id, track)); }) .catch((error) => { diff --git a/app/lib/RoomContext.js b/app/lib/RoomContext.js new file mode 100644 index 0000000..8ec42aa --- /dev/null +++ b/app/lib/RoomContext.js @@ -0,0 +1,14 @@ +import React from 'react'; + +const RoomContext = React.createContext(); + +export default RoomContext; + +export function withRoomContext(Component) +{ + return (props) => ( // eslint-disable-line react/display-name + + {(roomClient) => } + + ); +} \ No newline at end of file diff --git a/app/lib/components/Chat/MessageList.jsx b/app/lib/components/Chat/MessageList.jsx deleted file mode 100644 index 43a9671..0000000 --- a/app/lib/components/Chat/MessageList.jsx +++ /dev/null @@ -1,92 +0,0 @@ -import React, { Component } from 'react'; -import { compose } from 'redux'; -import PropTypes from 'prop-types'; -import marked from 'marked'; -import { connect } from 'react-redux'; -import scrollToBottom from './scrollToBottom'; - -const linkRenderer = new marked.Renderer(); - -linkRenderer.link = (href, title, text) => -{ - title = title ? title : href; - text = text ? text : href; - - return (`${ text }`); -}; - -class MessageList extends Component -{ - getTimeString(time) - { - return `${(time.getHours() < 10 ? '0' : '')}${time.getHours()}:${(time.getMinutes() < 10 ? '0' : '')}${time.getMinutes()}`; - } - - render() - { - const { - chatmessages - } = this.props; - - return ( -
- { chatmessages.length > 0 ? - chatmessages.map((message, i) => - { - const messageTime = new Date(message.time); - - const picture = (message.sender === 'response' ? - message.picture : this.props.myPicture) || 'resources/images/avatar-empty.jpeg'; - - return ( -
-
- - -
-
- - - {message.name} - {this.getTimeString(messageTime)} - -
-
-
- ); - }) - :
-

No one has said anything yet...

-
- } -
- ); - } -} - -MessageList.propTypes = -{ - chatmessages : PropTypes.arrayOf(PropTypes.object).isRequired, - myPicture : PropTypes.string -}; - -const mapStateToProps = (state) => -{ - return { - chatmessages : state.chatmessages, - myPicture : state.me.picture - }; -}; - -const MessageListContainer = compose( - connect(mapStateToProps), - scrollToBottom() -)(MessageList); - -export default MessageListContainer; diff --git a/app/lib/components/HiddenPeers.jsx b/app/lib/components/Containers/HiddenPeers.jsx similarity index 71% rename from app/lib/components/HiddenPeers.jsx rename to app/lib/components/Containers/HiddenPeers.jsx index 5c34d70..595a838 100644 --- a/app/lib/components/HiddenPeers.jsx +++ b/app/lib/components/Containers/HiddenPeers.jsx @@ -2,7 +2,7 @@ import React, { Component } from 'react'; import { connect } from 'react-redux'; import PropTypes from 'prop-types'; import classnames from 'classnames'; -import * as stateActions from '../redux/stateActions'; +import * as stateActions from '../../redux/stateActions'; class HiddenPeers extends Component { @@ -29,7 +29,7 @@ class HiddenPeers extends Component this.timeout = setTimeout(() => { this.setState({ className: '' }); - }, 2000); + }, 500); }); } } @@ -42,18 +42,11 @@ class HiddenPeers extends Component } = this.props; return ( -
-
-
openUsersTab()}> -

+{hiddenPeersCount}
participant - {(hiddenPeersCount === 1) ? null : 's'} -

-
+
+
openUsersTab()}> +

+{hiddenPeersCount}
participant + {(hiddenPeersCount === 1) ? null : 's'} +

); diff --git a/app/lib/components/Me.jsx b/app/lib/components/Containers/Me.jsx similarity index 73% rename from app/lib/components/Me.jsx rename to app/lib/components/Containers/Me.jsx index a8de66d..673cd52 100644 --- a/app/lib/components/Me.jsx +++ b/app/lib/components/Containers/Me.jsx @@ -4,10 +4,10 @@ import ReactTooltip from 'react-tooltip'; import PropTypes from 'prop-types'; import classnames from 'classnames'; import { getDeviceInfo } from 'mediasoup-client'; -import * as appPropTypes from './appPropTypes'; -import * as requestActions from '../redux/requestActions'; -import PeerView from './PeerView'; -import ScreenView from './ScreenView'; +import * as appPropTypes from '../appPropTypes'; +import { withRoomContext } from '../../RoomContext'; +import PeerView from '../VideoContainers/PeerView'; +import ScreenView from '../VideoContainers/ScreenView'; class Me extends React.Component { @@ -46,17 +46,13 @@ class Me extends React.Component render() { const { + roomClient, connected, me, advancedMode, micProducer, webcamProducer, - screenProducer, - onChangeDisplayName, - onMuteMic, - onUnmuteMic, - onEnableWebcam, - onDisableWebcam + screenProducer } = this.props; let micState; @@ -107,7 +103,7 @@ class Me extends React.Component onMouseOut={this.handleMouseOut} >
- {connected ? +
{ - micState === 'on' ? onMuteMic() : onUnmuteMic(); + micState === 'on' ? + roomClient.muteMic() : + roomClient.unmuteMic(); }} /> { - webcamState === 'on' ? onDisableWebcam() : onEnableWebcam(); + webcamState === 'on' ? + roomClient.disableWebcam() : + roomClient.enableWebcam(); }} />
- :null - } + onChangeDisplayName(displayName)} + onChangeDisplayName={(displayName) => + { + roomClient.changeDisplayName(displayName); + }} />
- {screenProducer ? +
- :null - } +
); } @@ -204,17 +205,13 @@ class Me extends React.Component Me.propTypes = { - connected : PropTypes.bool.isRequired, - advancedMode : PropTypes.bool, - me : appPropTypes.Me.isRequired, - micProducer : appPropTypes.Producer, - webcamProducer : appPropTypes.Producer, - screenProducer : appPropTypes.Producer, - onChangeDisplayName : PropTypes.func.isRequired, - onMuteMic : PropTypes.func.isRequired, - onUnmuteMic : PropTypes.func.isRequired, - onEnableWebcam : PropTypes.func.isRequired, - onDisableWebcam : PropTypes.func.isRequired + roomClient : PropTypes.any.isRequired, + connected : PropTypes.bool.isRequired, + advancedMode : PropTypes.bool, + me : appPropTypes.Me.isRequired, + micProducer : appPropTypes.Producer, + webcamProducer : appPropTypes.Producer, + screenProducer : appPropTypes.Producer }; const mapStateToProps = (state) => @@ -236,23 +233,8 @@ const mapStateToProps = (state) => }; }; -const mapDispatchToProps = (dispatch) => -{ - return { - onChangeDisplayName : (displayName) => - { - dispatch(requestActions.changeDisplayName(displayName)); - }, - onMuteMic : () => dispatch(requestActions.muteMic()), - onUnmuteMic : () => dispatch(requestActions.unmuteMic()), - onEnableWebcam : () => dispatch(requestActions.enableWebcam()), - onDisableWebcam : () => dispatch(requestActions.disableWebcam()) - }; -}; - -const MeContainer = connect( - mapStateToProps, - mapDispatchToProps -)(Me); +const MeContainer = withRoomContext(connect( + mapStateToProps +)(Me)); export default MeContainer; diff --git a/app/lib/components/Peer.jsx b/app/lib/components/Containers/Peer.jsx similarity index 82% rename from app/lib/components/Peer.jsx rename to app/lib/components/Containers/Peer.jsx index 7a4777f..cb54edc 100644 --- a/app/lib/components/Peer.jsx +++ b/app/lib/components/Containers/Peer.jsx @@ -2,11 +2,11 @@ import React, { Component } from 'react'; import { connect } from 'react-redux'; import PropTypes from 'prop-types'; import classnames from 'classnames'; -import * as appPropTypes from './appPropTypes'; -import * as requestActions from '../redux/requestActions'; -import * as stateActions from '../redux/stateActions'; -import PeerView from './PeerView'; -import ScreenView from './ScreenView'; +import * as appPropTypes from '../appPropTypes'; +import { withRoomContext } from '../../RoomContext'; +import * as stateActions from '../../redux/stateActions'; +import PeerView from '../VideoContainers/PeerView'; +import ScreenView from '../VideoContainers/ScreenView'; class Peer extends Component { @@ -31,13 +31,12 @@ class Peer extends Component render() { const { + roomClient, advancedMode, peer, micConsumer, webcamConsumer, screenConsumer, - onMuteMic, - onUnmuteMic, toggleConsumerFullscreen, toggleConsumerWindow, style, @@ -81,23 +80,21 @@ class Peer extends Component onMouseOver={this.handleMouseOver} onMouseOut={this.handleMouseOut} > - {videoVisible && !webcamConsumer.supported ? +

incompatible video

- :null - } +
- {!videoVisible ? +

this video is paused

- :null - } +
- {peer.raiseHandState ? +
- :null - } +
{ e.stopPropagation(); - micEnabled ? onMuteMic(peer.name) : onUnmuteMic(peer.name); + micEnabled ? + roomClient.modifyPeerConsumer(peer.name, 'mic', true) : + roomClient.modifyPeerConsumer(peer.name, 'mic', false); }} /> @@ -141,7 +139,9 @@ class Peer extends Component />
{ e.stopPropagation(); @@ -162,7 +162,7 @@ class Peer extends Component />
- {screenConsumer ? +
{ e.stopPropagation(); @@ -179,7 +182,9 @@ class Peer extends Component />
{ e.stopPropagation(); @@ -195,8 +200,7 @@ class Peer extends Component screenCodec={screenConsumer ? screenConsumer.codec : null} />
- :null - } +
); } @@ -204,14 +208,13 @@ class Peer extends Component Peer.propTypes = { + roomClient : PropTypes.any.isRequired, advancedMode : PropTypes.bool, peer : appPropTypes.Peer.isRequired, micConsumer : appPropTypes.Consumer, webcamConsumer : appPropTypes.Consumer, screenConsumer : appPropTypes.Consumer, windowConsumer : PropTypes.number, - onMuteMic : PropTypes.func.isRequired, - onUnmuteMic : PropTypes.func.isRequired, streamDimensions : PropTypes.object, style : PropTypes.object, toggleConsumerFullscreen : PropTypes.func.isRequired, @@ -242,14 +245,6 @@ const mapStateToProps = (state, { name }) => const mapDispatchToProps = (dispatch) => { return { - onMuteMic : (peerName) => - { - dispatch(requestActions.mutePeerAudio(peerName)); - }, - onUnmuteMic : (peerName) => - { - dispatch(requestActions.unmutePeerAudio(peerName)); - }, toggleConsumerFullscreen : (consumer) => { if (consumer) @@ -263,9 +258,9 @@ const mapDispatchToProps = (dispatch) => }; }; -const PeerContainer = connect( +const PeerContainer = withRoomContext(connect( mapStateToProps, mapDispatchToProps -)(Peer); +)(Peer)); export default PeerContainer; diff --git a/app/lib/components/EditableInput.jsx b/app/lib/components/Controls/EditableInput.jsx similarity index 100% rename from app/lib/components/EditableInput.jsx rename to app/lib/components/Controls/EditableInput.jsx diff --git a/app/lib/components/Sidebar.jsx b/app/lib/components/Controls/Sidebar.jsx similarity index 64% rename from app/lib/components/Sidebar.jsx rename to app/lib/components/Controls/Sidebar.jsx index fc9f9ae..473c523 100644 --- a/app/lib/components/Sidebar.jsx +++ b/app/lib/components/Controls/Sidebar.jsx @@ -2,9 +2,9 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import { connect } from 'react-redux'; import classnames from 'classnames'; -import * as appPropTypes from './appPropTypes'; -import * as requestActions from '../redux/requestActions'; -import FullScreen from './FullScreen'; +import * as appPropTypes from '../appPropTypes'; +import { withRoomContext } from '../../RoomContext'; +import FullScreen from '../FullScreen'; class Sidebar extends Component { @@ -56,8 +56,10 @@ class Sidebar extends Component render() { const { - toolbarsVisible, me, screenProducer, onLogin, onShareScreen, - onUnShareScreen, onNeedExtension, onLeaveMeeting, onLogout, onToggleHand + roomClient, + toolbarsVisible, + me, + screenProducer } = this.props; let screenState; @@ -91,7 +93,7 @@ class Sidebar extends Component })} data-component='Sidebar' > - {this.fullscreen.fullscreenEnabled && ( +
- )} +
- {me.loginEnabled && (me.loggedIn ? ( -
- -
- ) : ( -
- ))} + + + +
roomClient.logout()} + > + +
+
+ +
roomClient.login()} + /> + + +
onToggleHand(!me.raiseHand)} + onClick={() => roomClient.sendRaiseHandState(!me.raiseHand)} />
onLeaveMeeting()} + onClick={() => roomClient.close()} />
); @@ -178,15 +185,9 @@ class Sidebar extends Component } Sidebar.propTypes = { + roomClient : PropTypes.any.isRequired, toolbarsVisible : PropTypes.bool.isRequired, me : appPropTypes.Me.isRequired, - onShareScreen : PropTypes.func.isRequired, - onUnShareScreen : PropTypes.func.isRequired, - onNeedExtension : PropTypes.func.isRequired, - onToggleHand : PropTypes.func.isRequired, - onLeaveMeeting : PropTypes.func.isRequired, - onLogin : PropTypes.func.isRequired, - onLogout : PropTypes.func.isRequired, screenProducer : appPropTypes.Producer }; @@ -198,17 +199,6 @@ const mapStateToProps = (state) => me : state.me }); -const mapDispatchToProps = { - onLeaveMeeting : requestActions.leaveRoom, - onShareScreen : requestActions.enableScreenSharing, - onUnShareScreen : requestActions.disableScreenSharing, - onNeedExtension : requestActions.installExtension, - onToggleHand : requestActions.toggleHand, - onLogin : requestActions.userLogin, - onLogout : requestActions.userLogout -}; - -export default connect( - mapStateToProps, - mapDispatchToProps -)(Sidebar); +export default withRoomContext(connect( + mapStateToProps +)(Sidebar)); diff --git a/app/lib/components/FileSharing/FileEntry.jsx b/app/lib/components/FileSharing/FileEntry.jsx deleted file mode 100644 index e8f17b0..0000000 --- a/app/lib/components/FileSharing/FileEntry.jsx +++ /dev/null @@ -1,196 +0,0 @@ -import React, { Component, Fragment } from 'react'; -import PropTypes from 'prop-types'; -import { connect } from 'react-redux'; -import magnet from 'magnet-uri'; -import WebTorrent from 'webtorrent'; -import * as requestActions from '../../redux/requestActions'; -import { saveAs } from 'file-saver/FileSaver'; -import { client } from './index'; - -const DEFAULT_PICTURE = 'resources/images/avatar-empty.jpeg'; - -class FileEntry extends Component -{ - state = { - active : false, - numPeers : 0, - progress : 0, - files : null - }; - - saveFile = (file) => - { - file.getBlob((err, blob) => - { - if (err) - { - return this.props.notify({ - text : 'An error occurred while saving a file' - }); - } - - saveAs(blob, file.name); - }); - }; - - handleTorrent = (torrent) => - { - // Torrent already done, this can happen if the - // same file was sent multiple times. - if (torrent.progress === 1) - { - this.setState({ - files : torrent.files, - numPeers : torrent.numPeers, - progress : 1, - active : false, - timeout : false - }); - - return; - } - - const onProgress = () => - { - this.setState({ - numPeers : torrent.numPeers, - progress : torrent.progress - }); - }; - - onProgress(); - - setInterval(onProgress, 500); - - torrent.on('done', () => - { - onProgress(); - clearInterval(onProgress); - - this.setState({ - files : torrent.files, - active : false - }); - }); - }; - - handleDownload = () => - { - this.setState({ - active : true - }); - - const magnetURI = this.props.data.file.magnet; - - const existingTorrent = client.get(magnetURI); - - if (existingTorrent) - { - // Never add duplicate torrents, use the existing one instead. - return this.handleTorrent(existingTorrent); - } - - client.add(magnetURI, this.handleTorrent); - - setTimeout(() => - { - if (this.state.active && this.state.numPeers === 0) - { - this.setState({ - timeout : true - }); - } - }, 10 * 1000); - } - - render() - { - return ( -
- - -
- {this.props.data.me ? ( -

You shared a file.

- ) : ( -

{this.props.data.name} shared a file.

- )} - - {!this.state.active && !this.state.files && ( -
- {WebTorrent.WEBRTC_SUPPORT ? ( - - - - ) : ( -

- Your browser does not support downloading files using WebTorrent. -

- )} - -

{magnet.decode(this.props.data.file.magnet).dn}

-
- )} - - {this.state.active && this.state.numPeers === 0 && ( - -

- Locating peers -

- - {this.state.timeout && ( -

- If this process takes a long time, there might not be anyone seeding - this torrent. Try asking someone to reupload the file that you want. -

- )} -
- )} - - {this.state.active && this.state.numPeers > 0 && ( - - )} - - {this.state.files && ( - -

Torrent finished downloading.

- - {this.state.files.map((file, i) => ( -
- this.saveFile(file)}> - - - -

{file.name}

-
- ))} -
- )} -
-
- ); - } -} - -export const FileEntryProps = { - data : PropTypes.shape({ - name : PropTypes.string.isRequired, - picture : PropTypes.string, - file : PropTypes.shape({ - magnet : PropTypes.string.isRequired - }).isRequired, - me : PropTypes.bool - }).isRequired, - notify : PropTypes.func.isRequired -}; - -FileEntry.propTypes = FileEntryProps; - -const mapDispatchToProps = { - notify : requestActions.notify -}; - -export default connect( - undefined, - mapDispatchToProps -)(FileEntry); \ No newline at end of file diff --git a/app/lib/components/FileSharing/SharedFilesList.jsx b/app/lib/components/FileSharing/SharedFilesList.jsx deleted file mode 100644 index 28fc6b1..0000000 --- a/app/lib/components/FileSharing/SharedFilesList.jsx +++ /dev/null @@ -1,54 +0,0 @@ -import React, { Component } from 'react'; -import { compose } from 'redux'; -import { connect } from 'react-redux'; -import PropTypes from 'prop-types'; -import FileEntry, { FileEntryProps } from './FileEntry'; -import scrollToBottom from '../Chat/scrollToBottom'; - -/** - * This component cannot be pure, as we need to use - * refs to scroll to the bottom when new files arrive. - */ -class SharedFilesList extends Component -{ - render() - { - const { sharing } = this.props; - - return ( -
- { sharing.length > 0 ? - sharing.map((entry, i) => ( - - )) - :
-

No one has shared files yet...

-
- } -
- ); - } -} - -SharedFilesList.propTypes = { - sharing : PropTypes.arrayOf(FileEntryProps.data).isRequired -}; - -const mapStateToProps = (state) => - ({ - sharing : state.sharing, - - // Included to scroll to the bottom when the user - // actually opens the tab. When the component first - // mounts, the component is not visible and so the - // component has no height which can be used for scrolling. - tabOpen : state.toolarea.currentToolTab === 'files' - }); - -export default compose( - connect(mapStateToProps), - scrollToBottom() -)(SharedFilesList); diff --git a/app/lib/components/FileSharing/index.jsx b/app/lib/components/FileSharing/index.jsx deleted file mode 100644 index fd41051..0000000 --- a/app/lib/components/FileSharing/index.jsx +++ /dev/null @@ -1,131 +0,0 @@ -import React, { Component } from 'react'; -import WebTorrent from 'webtorrent'; -import createTorrent from 'create-torrent'; -import randomString from 'random-string'; -import classNames from 'classnames'; -import * as stateActions from '../../redux/stateActions'; -import * as requestActions from '../../redux/requestActions'; -import { store } from '../../store'; -import config from '../../../config'; -import SharedFilesList from './SharedFilesList'; - -export const client = WebTorrent.WEBRTC_SUPPORT && new WebTorrent({ - tracker : { - rtcConfig : { - iceServers : config.turnServers - } - } -}); - -const notifyPeers = (file) => -{ - const { displayName, picture } = store.getState().me; - - store.dispatch(requestActions.sendFile(file, displayName, picture)); -}; - -export const shareFiles = async (files) => -{ - const notification = - { - id : randomString({ length: 6 }).toLowerCase(), - text : 'Creating torrent', - type : 'info' - }; - - store.dispatch(stateActions.addNotification(notification)); - - createTorrent(files, (err, torrent) => - { - if (err) - { - return store.dispatch(requestActions.notify({ - text : 'An error occured while uploading a file' - })); - } - - const existingTorrent = client.get(torrent); - - if (existingTorrent) - { - return notifyPeers({ - magnet : existingTorrent.magnetURI - }); - } - - client.seed(files, (newTorrent) => - { - store.dispatch(stateActions.removeNotification(notification.id)); - - store.dispatch(requestActions.notify({ - text : 'Torrent successfully created' - })); - - notifyPeers({ - magnet : newTorrent.magnetURI - }); - }); - }); -}; - -class FileSharing extends Component -{ - constructor(props) - { - super(props); - - this.fileInput = React.createRef(); - } - - handleFileChange = async (event) => - { - if (event.target.files.length > 0) - { - await shareFiles(event.target.files); - } - }; - - handleClick = () => - { - if (WebTorrent.WEBRTC_SUPPORT) - { - // We want to open the file dialog when we click a button - // instead of actually rendering the input element itself. - this.fileInput.current.click(); - } - }; - - render() - { - const buttonDescription = WebTorrent.WEBRTC_SUPPORT ? - 'Share file' : 'File sharing not supported'; - - return ( -
-
- - -
- {buttonDescription} -
-
- - -
- ); - } -} - -export default FileSharing; \ No newline at end of file diff --git a/app/lib/components/Filmstrip.jsx b/app/lib/components/Layouts/Filmstrip.jsx similarity index 77% rename from app/lib/components/Filmstrip.jsx rename to app/lib/components/Layouts/Filmstrip.jsx index b0fe105..f5b1916 100644 --- a/app/lib/components/Filmstrip.jsx +++ b/app/lib/components/Layouts/Filmstrip.jsx @@ -4,9 +4,9 @@ import ResizeObserver from 'resize-observer-polyfill'; import { connect } from 'react-redux'; import debounce from 'lodash/debounce'; import classnames from 'classnames'; -import * as requestActions from '../redux/requestActions'; -import Peer from './Peer'; -import HiddenPeers from './HiddenPeers'; +import { withRoomContext } from '../../RoomContext'; +import Peer from '../Containers/Peer'; +import HiddenPeers from '../Containers/HiddenPeers'; class Filmstrip extends Component { @@ -114,14 +114,20 @@ class Filmstrip extends Component render() { - const { peers, advancedMode, spotlights, spotlightsLength } = this.props; + const { + roomClient, + peers, + advancedMode, + spotlights, + spotlightsLength + } = this.props; const activePeerName = this.getActivePeerName(); return (
- {peers[activePeerName] && ( +
- )} +
+ { Object.keys(peers).map((peerName) => { - Object.keys(peers).map((peerName) => + if (spotlights.find((spotlightsElement) => spotlightsElement === peerName)) { return ( - spotlights.find((spotlightsElement) => spotlightsElement === peerName)? -
this.props.setSelectedPeer(peerName)} - className={classnames('film', { - selected : this.props.selectedPeerName === peerName, - active : this.state.lastSpeaker === peerName - })} - > -
- -
+
roomClient.setSelectedPeer(peerName)} + className={classnames('film', { + selected : this.props.selectedPeerName === peerName, + active : this.state.lastSpeaker === peerName + })} + > +
+
- :null +
); - }) - } + } + })}
- { (spotlightsLength :null - } + /> +
@@ -179,13 +184,13 @@ class Filmstrip extends Component } Filmstrip.propTypes = { + roomClient : PropTypes.any.isRequired, activeSpeakerName : PropTypes.string, advancedMode : PropTypes.bool, peers : PropTypes.object.isRequired, consumers : PropTypes.object.isRequired, myName : PropTypes.string.isRequired, selectedPeerName : PropTypes.string, - setSelectedPeer : PropTypes.func.isRequired, spotlightsLength : PropTypes.number, spotlights : PropTypes.array.isRequired }; @@ -205,11 +210,7 @@ const mapStateToProps = (state) => }; }; -const mapDispatchToProps = { - setSelectedPeer : requestActions.setSelectedPeer -}; - -export default connect( +export default withRoomContext(connect( mapStateToProps, - mapDispatchToProps -)(Filmstrip); + undefined +)(Filmstrip)); diff --git a/app/lib/components/Peers.jsx b/app/lib/components/Layouts/Peers.jsx similarity index 72% rename from app/lib/components/Peers.jsx rename to app/lib/components/Layouts/Peers.jsx index 6a40fe8..573d277 100644 --- a/app/lib/components/Peers.jsx +++ b/app/lib/components/Layouts/Peers.jsx @@ -3,10 +3,9 @@ import { connect } from 'react-redux'; import PropTypes from 'prop-types'; import classnames from 'classnames'; import debounce from 'lodash/debounce'; -import * as appPropTypes from './appPropTypes'; -import { Appear } from './transitions'; -import Peer from './Peer'; -import HiddenPeers from './HiddenPeers'; +import { Appear } from '../transitions'; +import Peer from '../Containers/Peer'; +import HiddenPeers from '../Containers/HiddenPeers'; import ResizeObserver from 'resize-observer-polyfill'; const RATIO = 1.334; @@ -105,38 +104,36 @@ class Peers extends React.Component return (
+ { Object.keys(peers).map((peerName) => { - peers.map((peer) => + if (spotlights.find((spotlightsElement) => spotlightsElement === peerName)) { return ( - (spotlights.find(function(spotlightsElement) - { return spotlightsElement == peer.name; }))? - -
-
- -
+ +
+
+
- - :null +
+
); - }) - } -
- { (spotlightsLength:null } + })} +
+ + +
); @@ -146,7 +143,7 @@ class Peers extends React.Component Peers.propTypes = { advancedMode : PropTypes.bool, - peers : PropTypes.arrayOf(appPropTypes.Peer).isRequired, + peers : PropTypes.object.isRequired, boxes : PropTypes.number, activeSpeakerName : PropTypes.string, selectedPeerName : PropTypes.string, @@ -156,14 +153,13 @@ Peers.propTypes = const mapStateToProps = (state) => { - const peers = Object.values(state.peers); const spotlights = state.room.spotlights; const spotlightsLength = spotlights ? state.room.spotlights.length : 0; const boxes = spotlightsLength + Object.values(state.consumers) .filter((consumer) => consumer.source === 'screen').length; return { - peers, + peers : state.peers, boxes, activeSpeakerName : state.room.activeSpeakerName, selectedPeerName : state.room.selectedPeerName, diff --git a/app/lib/components/Room.jsx b/app/lib/components/Room.jsx index 47a5a44..12fd006 100644 --- a/app/lib/components/Room.jsx +++ b/app/lib/components/Room.jsx @@ -9,21 +9,17 @@ import * as appPropTypes from './appPropTypes'; import * as requestActions from '../redux/requestActions'; import * as stateActions from '../redux/stateActions'; import { Appear } from './transitions'; -import Me from './Me'; -import Peers from './Peers'; +import Me from './Containers/Me'; +import Peers from './Layouts/Peers'; import AudioPeers from './PeerAudio/AudioPeers'; import Notifications from './Notifications'; -// import ToolAreaButton from './ToolArea/ToolAreaButton'; import ToolArea from './ToolArea/ToolArea'; -import FullScreenView from './FullScreenView'; +import FullScreenView from './VideoContainers/FullScreenView'; import VideoWindow from './VideoWindow/VideoWindow'; import Draggable from 'react-draggable'; import { idle } from '../utils'; -import Sidebar from './Sidebar'; -import Filmstrip from './Filmstrip'; -import { configureDragDrop, HoldingOverlay } from './FileSharing/DragDropSharing'; - -configureDragDrop(); +import Sidebar from './Controls/Sidebar'; +import Filmstrip from './Layouts/Filmstrip'; // Hide toolbars after 10 seconds of inactivity. const TIMEOUT = 10 * 1000; @@ -79,8 +75,6 @@ class Room extends React.Component return ( - -
@@ -97,13 +91,12 @@ class Room extends React.Component - {room.advancedMode ? +

{room.state}

- :null - } +
options.find((option) => option.value === value); - -const Settings = ({ - room, me, onToggleAdvancedMode, handleChangeWebcam, - handleChangeAudioDevice, handleChangeMode -}) => -{ - let webcams; - - if (me.webcamDevices) - webcams = Array.from(me.webcamDevices.values()); - else - webcams = []; - - let audioDevices; - let audioDevicesText; - - if (me.canChangeAudioDevice) - audioDevicesText = 'Select audio input device'; - else - audioDevicesText = 'Unable to select audio input device'; - - if (me.audioDevices) - audioDevices = Array.from(me.audioDevices.values()); - else - audioDevices = []; - - return ( -
-
- handleChangeWebcam(webcam.value)} - placeholder={'Select camera'} - /> - - handleChangeAudioDevice(device.value)} - placeholder={audioDevicesText} - /> - -
- - -
- -
- handleChangeMode(mode.value)} - /> -
-
-
- ); -}; - -Settings.propTypes = -{ - me : appPropTypes.Me.isRequired, - room : appPropTypes.Room.isRequired, - handleChangeWebcam : PropTypes.func.isRequired, - handleChangeAudioDevice : PropTypes.func.isRequired, - onToggleAdvancedMode : PropTypes.func.isRequired, - handleChangeMode : PropTypes.func.isRequired -}; - -const mapStateToProps = (state) => -{ - return { - me : state.me, - room : state.room - }; -}; - -const mapDispatchToProps = { - handleChangeWebcam : requestActions.changeWebcam, - handleChangeAudioDevice : requestActions.changeAudioDevice, - onToggleAdvancedMode : stateActions.toggleAdvancedMode, - handleChangeMode : stateActions.setDisplayMode -}; - -const SettingsContainer = connect( - mapStateToProps, - mapDispatchToProps -)(Settings); - -export default SettingsContainer; diff --git a/app/lib/components/Chat/Chat.jsx b/app/lib/components/ToolArea/Chat/Chat.jsx similarity index 53% rename from app/lib/components/Chat/Chat.jsx rename to app/lib/components/ToolArea/Chat/Chat.jsx index 20f330c..9eb52b2 100644 --- a/app/lib/components/Chat/Chat.jsx +++ b/app/lib/components/ToolArea/Chat/Chat.jsx @@ -1,18 +1,28 @@ import React, { Component } from 'react'; import { connect } from 'react-redux'; import PropTypes from 'prop-types'; -import * as stateActions from '../../redux/stateActions'; -import * as requestActions from '../../redux/requestActions'; +import { withRoomContext } from '../../../RoomContext'; import MessageList from './MessageList'; class Chat extends Component { + createNewMessage(text, sender, name, picture) + { + return { + type : 'message', + text, + time : Date.now(), + name, + sender, + picture + }; + } + render() { const { + roomClient, senderPlaceHolder, - onSendMessage, - disabledInput, autofocus, displayName, picture @@ -23,14 +33,25 @@ class Chat extends Component
{ onSendMessage(e, displayName, picture); }} + onSubmit={(e) => + { + e.preventDefault(); + const userInput = e.target.message.value; + + if (userInput) + { + const message = this.createNewMessage(userInput, 'response', displayName, picture); + + roomClient.sendChatMessage(message); + } + e.target.message.value = ''; + }} > @@ -47,9 +68,8 @@ class Chat extends Component Chat.propTypes = { + roomClient : PropTypes.any.isRequired, senderPlaceHolder : PropTypes.string, - onSendMessage : PropTypes.func, - disabledInput : PropTypes.bool, autofocus : PropTypes.bool, displayName : PropTypes.string, picture : PropTypes.string @@ -65,33 +85,13 @@ Chat.defaultProps = const mapStateToProps = (state) => { return { - disabledInput : state.chatbehavior.disabledInput, - displayName : state.me.displayName, - picture : state.me.picture + displayName : state.me.displayName, + picture : state.me.picture }; }; -const mapDispatchToProps = (dispatch) => -{ - return { - onSendMessage : (event, displayName, picture) => - { - event.preventDefault(); - const userInput = event.target.message.value; - - if (userInput) - { - dispatch(stateActions.addUserMessage(userInput)); - dispatch(requestActions.sendChatMessage(userInput, displayName, picture)); - } - event.target.message.value = ''; - } - }; -}; - -const ChatContainer = connect( - mapStateToProps, - mapDispatchToProps -)(Chat); +const ChatContainer = withRoomContext(connect( + mapStateToProps +)(Chat)); export default ChatContainer; diff --git a/app/lib/components/ToolArea/Chat/MessageList.jsx b/app/lib/components/ToolArea/Chat/MessageList.jsx new file mode 100644 index 0000000..66d4eda --- /dev/null +++ b/app/lib/components/ToolArea/Chat/MessageList.jsx @@ -0,0 +1,98 @@ +import React, { Component } from 'react'; +import { compose } from 'redux'; +import PropTypes from 'prop-types'; +import marked from 'marked'; +import { connect } from 'react-redux'; +import scrollToBottom from '../scrollToBottom'; + +const linkRenderer = new marked.Renderer(); + +linkRenderer.link = (href, title, text) => +{ + title = title ? title : href; + text = text ? text : href; + + return (`${ text }`); +}; + +class MessageList extends Component +{ + getTimeString(time) + { + return `${(time.getHours() < 10 ? '0' : '')}${time.getHours()}:${(time.getMinutes() < 10 ? '0' : '')}${time.getMinutes()}`; + } + + render() + { + const { + chatmessages + } = this.props; + + return ( +
+ + 0}> + { + chatmessages.map((message, i) => + { + const messageTime = new Date(message.time); + + const picture = (message.sender === 'response' ? + message.picture : this.props.myPicture) || 'resources/images/avatar-empty.jpeg'; + + return ( +
+
+ + +
+
+ + + {message.name} - {this.getTimeString(messageTime)} + +
+
+
+ ); + }) + } + + +
+

No one has said anything yet...

+
+
+ +
+ ); + } +} + +MessageList.propTypes = +{ + chatmessages : PropTypes.arrayOf(PropTypes.object).isRequired, + myPicture : PropTypes.string +}; + +const mapStateToProps = (state) => +{ + return { + chatmessages : state.chatmessages, + myPicture : state.me.picture + }; +}; + +const MessageListContainer = compose( + connect(mapStateToProps), + scrollToBottom() +)(MessageList); + +export default MessageListContainer; diff --git a/app/lib/components/FileSharing/DragDropSharing.jsx b/app/lib/components/ToolArea/FileSharing/DragDropSharing.jsx similarity index 100% rename from app/lib/components/FileSharing/DragDropSharing.jsx rename to app/lib/components/ToolArea/FileSharing/DragDropSharing.jsx diff --git a/app/lib/components/ToolArea/FileSharing/File.jsx b/app/lib/components/ToolArea/FileSharing/File.jsx new file mode 100644 index 0000000..08a9db3 --- /dev/null +++ b/app/lib/components/ToolArea/FileSharing/File.jsx @@ -0,0 +1,113 @@ +import React, { Component, Fragment } from 'react'; +import PropTypes from 'prop-types'; +import { connect } from 'react-redux'; +import { withRoomContext } from '../../../RoomContext'; +import magnet from 'magnet-uri'; + +const DEFAULT_PICTURE = 'resources/images/avatar-empty.jpeg'; + +class File extends Component +{ + render() + { + const { + roomClient, + torrentSupport, + file + } = this.props; + + return ( +
+ + +
+ + +

You shared a file.

+
+ +

{file.displayName} shared a file.

+
+
+ + +
+ + + + { + roomClient.handleDownload(file.magnetUri); + }} + > + + + + +

+ Your browser does not support downloading files using WebTorrent. +

+
+
+

{magnet.decode(file.magnetUri).dn}

+
+
+ + + +

+ If this process takes a long time, there might not be anyone seeding + this torrent. Try asking someone to reupload the file that you want. +

+
+
+ + + + + + + +

File finished downloading.

+ + {file.files.map((sharedFile, i) => ( +
+ + { + roomClient.saveFile(sharedFile); + }} + > + + + +

{sharedFile.name}

+
+ ))} +
+
+
+
+ ); + } +} + +File.propTypes = { + roomClient : PropTypes.object.isRequired, + torrentSupport : PropTypes.bool.isRequired, + file : PropTypes.object.isRequired +}; + +const mapStateToProps = (state, { magnetUri }) => +{ + return { + file : state.files[magnetUri], + torrentSupport : state.room.torrentSupport + }; +}; + +export default withRoomContext(connect( + mapStateToProps +)(File)); \ No newline at end of file diff --git a/app/lib/components/ToolArea/FileSharing/FileList.jsx b/app/lib/components/ToolArea/FileSharing/FileList.jsx new file mode 100644 index 0000000..6028a9e --- /dev/null +++ b/app/lib/components/ToolArea/FileSharing/FileList.jsx @@ -0,0 +1,40 @@ +import React, { Component } from 'react'; +import { compose } from 'redux'; +import PropTypes from 'prop-types'; +import { connect } from 'react-redux'; +import scrollToBottom from '../scrollToBottom'; +import File from './File'; + +class FileList extends Component +{ + render() + { + const { + files + } = this.props; + + return ( +
+ { Object.keys(files).map((magnetUri) => + + )} +
+ ); + } +} + +FileList.propTypes = { + files : PropTypes.object.isRequired +}; + +const mapStateToProps = (state) => +{ + return { + files : state.files + }; +}; + +export default compose( + connect(mapStateToProps), + scrollToBottom() +)(FileList); diff --git a/app/lib/components/ToolArea/FileSharing/FileSharing.jsx b/app/lib/components/ToolArea/FileSharing/FileSharing.jsx new file mode 100644 index 0000000..60574c2 --- /dev/null +++ b/app/lib/components/ToolArea/FileSharing/FileSharing.jsx @@ -0,0 +1,88 @@ +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import { connect } from 'react-redux'; +import classNames from 'classnames'; +import { withRoomContext } from '../../../RoomContext'; +import FileList from './FileList'; + +class FileSharing extends Component +{ + constructor(props) + { + super(props); + + this._fileInput = React.createRef(); + } + + handleFileChange = async (event) => + { + if (event.target.files.length > 0) + { + this.props.roomClient.shareFiles(event.target.files); + } + }; + + handleClick = () => + { + if (this.props.torrentSupport) + { + // We want to open the file dialog when we click a button + // instead of actually rendering the input element itself. + this._fileInput.current.click(); + } + }; + + render() + { + const { + torrentSupport + } = this.props; + + const buttonDescription = torrentSupport ? + 'Share file' : 'File sharing not supported'; + + return ( +
+
+ + +
+ {buttonDescription} +
+
+ + +
+ ); + } +} + +FileSharing.propTypes = { + roomClient : PropTypes.any.isRequired, + torrentSupport : PropTypes.bool.isRequired, + tabOpen : PropTypes.bool.isRequired +}; + +const mapStateToProps = (state) => +{ + return { + torrentSupport : state.room.torrentSupport, + tabOpen : state.toolarea.currentToolTab === 'files' + }; +}; + +export default withRoomContext(connect( + mapStateToProps +)(FileSharing)); diff --git a/app/lib/components/ParticipantList/ListMe.jsx b/app/lib/components/ToolArea/ParticipantList/ListMe.jsx similarity index 87% rename from app/lib/components/ParticipantList/ListMe.jsx rename to app/lib/components/ToolArea/ParticipantList/ListMe.jsx index 460c738..eda33a4 100644 --- a/app/lib/components/ParticipantList/ListMe.jsx +++ b/app/lib/components/ToolArea/ParticipantList/ListMe.jsx @@ -1,6 +1,6 @@ import React from 'react'; import { connect } from 'react-redux'; -import { Me } from '../appPropTypes'; +import { Me } from '../../appPropTypes'; const ListMe = ({ me }) => { @@ -16,9 +16,9 @@ const ListMe = ({ me }) =>
- {me.raisedHand && ( +
- )} +
diff --git a/app/lib/components/ParticipantList/ListPeer.jsx b/app/lib/components/ToolArea/ParticipantList/ListPeer.jsx similarity index 57% rename from app/lib/components/ParticipantList/ListPeer.jsx rename to app/lib/components/ToolArea/ParticipantList/ListPeer.jsx index 82e252c..577d6b5 100644 --- a/app/lib/components/ParticipantList/ListPeer.jsx +++ b/app/lib/components/ToolArea/ParticipantList/ListPeer.jsx @@ -2,19 +2,16 @@ import React from 'react'; import { connect } from 'react-redux'; import PropTypes from 'prop-types'; import classnames from 'classnames'; -import * as appPropTypes from '../appPropTypes'; -import * as requestActions from '../../redux/requestActions'; +import * as appPropTypes from '../../appPropTypes'; +import { withRoomContext } from '../../../RoomContext'; const ListPeer = (props) => { const { + roomClient, peer, micConsumer, - screenConsumer, - onMuteMic, - onUnmuteMic, - onDisableScreen, - onEnableScreen + screenConsumer } = props; const micEnabled = ( @@ -39,7 +36,7 @@ const ListPeer = (props) => {peer.displayName}
- {peer.raiseHandState ? +
) } /> - :null - } +
- { screenConsumer ? +
{ e.stopPropagation(); screenVisible ? - onDisableScreen(peer.name) : onEnableScreen(peer.name); + roomClient.modifyPeerConsumer(peer.name, 'screen', true) : + roomClient.modifyPeerConsumer(peer.name, 'screen', false); }} /> - :null - } +
onClick={(e) => { e.stopPropagation(); - micEnabled ? onMuteMic(peer.name) : onUnmuteMic(peer.name); + micEnabled ? + roomClient.modifyPeerConsumer(peer.name, 'mic', true) : + roomClient.modifyPeerConsumer(peer.name, 'mic', false); }} />
@@ -91,17 +89,12 @@ const ListPeer = (props) => ListPeer.propTypes = { - advancedMode : PropTypes.bool, - peer : appPropTypes.Peer.isRequired, - micConsumer : appPropTypes.Consumer, - webcamConsumer : appPropTypes.Consumer, - screenConsumer : appPropTypes.Consumer, - onMuteMic : PropTypes.func.isRequired, - onUnmuteMic : PropTypes.func.isRequired, - onEnableWebcam : PropTypes.func.isRequired, - onDisableWebcam : PropTypes.func.isRequired, - onEnableScreen : PropTypes.func.isRequired, - onDisableScreen : PropTypes.func.isRequired + roomClient : PropTypes.any.isRequired, + advancedMode : PropTypes.bool, + peer : appPropTypes.Peer.isRequired, + micConsumer : appPropTypes.Consumer, + webcamConsumer : appPropTypes.Consumer, + screenConsumer : appPropTypes.Consumer }; const mapStateToProps = (state, { name }) => @@ -124,40 +117,8 @@ const mapStateToProps = (state, { name }) => }; }; -const mapDispatchToProps = (dispatch) => -{ - return { - onMuteMic : (peerName) => - { - dispatch(requestActions.mutePeerAudio(peerName)); - }, - onUnmuteMic : (peerName) => - { - dispatch(requestActions.unmutePeerAudio(peerName)); - }, - onEnableWebcam : (peerName) => - { - - dispatch(requestActions.resumePeerVideo(peerName)); - }, - onDisableWebcam : (peerName) => - { - dispatch(requestActions.pausePeerVideo(peerName)); - }, - onEnableScreen : (peerName) => - { - dispatch(requestActions.resumePeerScreen(peerName)); - }, - onDisableScreen : (peerName) => - { - dispatch(requestActions.pausePeerScreen(peerName)); - } - }; -}; - -const ListPeerContainer = connect( - mapStateToProps, - mapDispatchToProps -)(ListPeer); +const ListPeerContainer = withRoomContext(connect( + mapStateToProps +)(ListPeer)); export default ListPeerContainer; diff --git a/app/lib/components/ParticipantList/ParticipantList.jsx b/app/lib/components/ToolArea/ParticipantList/ParticipantList.jsx similarity index 80% rename from app/lib/components/ParticipantList/ParticipantList.jsx rename to app/lib/components/ToolArea/ParticipantList/ParticipantList.jsx index e9f8492..5537542 100644 --- a/app/lib/components/ParticipantList/ParticipantList.jsx +++ b/app/lib/components/ToolArea/ParticipantList/ParticipantList.jsx @@ -1,17 +1,17 @@ import React from 'react'; import { connect } from 'react-redux'; import classNames from 'classnames'; -import * as appPropTypes from '../appPropTypes'; -import * as requestActions from '../../redux/requestActions'; +import * as appPropTypes from '../../appPropTypes'; +import { withRoomContext } from '../../../RoomContext'; import PropTypes from 'prop-types'; import ListPeer from './ListPeer'; import ListMe from './ListMe'; const ParticipantList = ({ + roomClient, advancedMode, peers, - setSelectedPeer, selectedPeerName, spotlights }) => ( @@ -33,7 +33,7 @@ const ParticipantList = className={classNames('list-item', { selected : peer.name === selectedPeerName })} - onClick={() => setSelectedPeer(peer.name)} + onClick={() => roomClient.setSelectedPeer(peer.name)} > @@ -52,7 +52,7 @@ const ParticipantList = className={classNames('list-item', { selected : peer.name === selectedPeerName })} - onClick={() => setSelectedPeer(peer.name)} + onClick={() => roomClient.setSelectedPeer(peer.name)} > @@ -64,9 +64,9 @@ const ParticipantList = ParticipantList.propTypes = { + roomClient : PropTypes.any.isRequired, advancedMode : PropTypes.bool, peers : PropTypes.arrayOf(appPropTypes.Peer).isRequired, - setSelectedPeer : PropTypes.func.isRequired, selectedPeerName : PropTypes.string, spotlights : PropTypes.array.isRequired }; @@ -82,13 +82,8 @@ const mapStateToProps = (state) => }; }; -const mapDispatchToProps = { - setSelectedPeer : requestActions.setSelectedPeer -}; - -const ParticipantListContainer = connect( - mapStateToProps, - mapDispatchToProps -)(ParticipantList); +const ParticipantListContainer = withRoomContext(connect( + mapStateToProps +)(ParticipantList)); export default ParticipantListContainer; diff --git a/app/lib/components/ToolArea/Settings/Settings.jsx b/app/lib/components/ToolArea/Settings/Settings.jsx new file mode 100644 index 0000000..12bddfe --- /dev/null +++ b/app/lib/components/ToolArea/Settings/Settings.jsx @@ -0,0 +1,123 @@ +import React from 'react'; +import { connect } from 'react-redux'; +import * as appPropTypes from '../../appPropTypes'; +import { withRoomContext } from '../../../RoomContext'; +import * as stateActions from '../../../redux/stateActions'; +import PropTypes from 'prop-types'; +import Dropdown from 'react-dropdown'; +import ReactTooltip from 'react-tooltip'; + +const modes = [ { + value : 'democratic', + label : 'Democratic view' +}, { + value : 'filmstrip', + label : 'Filmstrip view' +} ]; + +const findOption = (options, value) => options.find((option) => option.value === value); + +const Settings = ({ + roomClient, + room, + me, + onToggleAdvancedMode, + handleChangeMode +}) => +{ + let webcams; + + if (me.webcamDevices) + webcams = Array.from(me.webcamDevices.values()); + else + webcams = []; + + let audioDevices; + let audioDevicesText; + + if (me.canChangeAudioDevice) + audioDevicesText = 'Select audio input device'; + else + audioDevicesText = 'Unable to select audio input device'; + + if (me.audioDevices) + audioDevices = Array.from(me.audioDevices.values()); + else + audioDevices = []; + + return ( +
+ roomClient.changeWebcam(webcam.value)} + placeholder={'Select camera'} + /> + + roomClient.changeAudioDevice(device.value)} + placeholder={audioDevicesText} + /> + +
+ + +
+ +
+ handleChangeMode(mode.value)} + /> +
+
+ ); +}; + +Settings.propTypes = +{ + roomClient : PropTypes.any.isRequired, + me : appPropTypes.Me.isRequired, + room : appPropTypes.Room.isRequired, + onToggleAdvancedMode : PropTypes.func.isRequired, + handleChangeMode : PropTypes.func.isRequired +}; + +const mapStateToProps = (state) => +{ + return { + me : state.me, + room : state.room + }; +}; + +const mapDispatchToProps = { + onToggleAdvancedMode : stateActions.toggleAdvancedMode, + handleChangeMode : stateActions.setDisplayMode +}; + +const SettingsContainer = withRoomContext(connect( + mapStateToProps, + mapDispatchToProps +)(Settings)); + +export default SettingsContainer; diff --git a/app/lib/components/ToolArea/TabHeader.jsx b/app/lib/components/ToolArea/TabHeader.jsx index a9514b1..eeec596 100644 --- a/app/lib/components/ToolArea/TabHeader.jsx +++ b/app/lib/components/ToolArea/TabHeader.jsx @@ -13,9 +13,9 @@ const TabHeader = ({ currentToolTab, setToolTab, id, name, badge }) => ( > {name} - {badge > 0 && ( + 0}> {badge} - )} +
); diff --git a/app/lib/components/ToolArea/ToolArea.jsx b/app/lib/components/ToolArea/ToolArea.jsx index 5165796..fa57884 100644 --- a/app/lib/components/ToolArea/ToolArea.jsx +++ b/app/lib/components/ToolArea/ToolArea.jsx @@ -3,10 +3,10 @@ import { connect } from 'react-redux'; import PropTypes from 'prop-types'; import classNames from 'classnames'; import * as stateActions from '../../redux/stateActions'; -import ParticipantList from '../ParticipantList/ParticipantList'; -import Chat from '../Chat/Chat'; -import Settings from '../Settings'; -import FileSharing from '../FileSharing'; +import ParticipantList from './ParticipantList/ParticipantList'; +import Chat from './Chat/Chat'; +import Settings from './Settings/Settings'; +import FileSharing from './FileSharing/FileSharing'; import TabHeader from './TabHeader'; class ToolArea extends React.Component @@ -59,11 +59,11 @@ class ToolArea extends React.Component />

Toolbox

- {!toolAreaOpen && unread > 0 && ( + 0}> = 10 })}> {unread} - )} +
-
toggleToolArea()} - /> - - {!toolAreaOpen && unread > 0 && ( - = 10 })}> - {unread} - - )} -
- ); - } -} - -ToolAreaButton.propTypes = -{ - toolAreaOpen : PropTypes.bool.isRequired, - toggleToolArea : PropTypes.func.isRequired, - unread : PropTypes.number.isRequired, - visible : PropTypes.bool.isRequired -}; - -const mapStateToProps = (state) => -{ - return { - toolAreaOpen : state.toolarea.toolAreaOpen, - visible : state.room.toolbarsVisible, - unread : state.toolarea.unreadMessages + state.toolarea.unreadFiles - }; -}; - -const mapDispatchToProps = (dispatch) => -{ - return { - toggleToolArea : () => - { - dispatch(stateActions.toggleToolArea()); - } - }; -}; - -const ToolAreaButtonContainer = connect( - mapStateToProps, - mapDispatchToProps -)(ToolAreaButton); - -export default ToolAreaButtonContainer; diff --git a/app/lib/components/Chat/scrollToBottom.jsx b/app/lib/components/ToolArea/scrollToBottom.jsx similarity index 100% rename from app/lib/components/Chat/scrollToBottom.jsx rename to app/lib/components/ToolArea/scrollToBottom.jsx diff --git a/app/lib/components/FullScreenView.jsx b/app/lib/components/VideoContainers/FullScreenView.jsx similarity index 91% rename from app/lib/components/FullScreenView.jsx rename to app/lib/components/VideoContainers/FullScreenView.jsx index f01ce7a..e60f346 100644 --- a/app/lib/components/FullScreenView.jsx +++ b/app/lib/components/VideoContainers/FullScreenView.jsx @@ -2,8 +2,8 @@ import React from 'react'; import { connect } from 'react-redux'; import PropTypes from 'prop-types'; import classnames from 'classnames'; -import * as appPropTypes from './appPropTypes'; -import * as stateActions from '../redux/stateActions'; +import * as appPropTypes from '../appPropTypes'; +import * as stateActions from '../../redux/stateActions'; import FullView from './FullView'; const FullScreenView = (props) => @@ -31,12 +31,11 @@ const FullScreenView = (props) => return (
- {consumerVisible && !consumer.supported ? +

incompatible video

- :null - } +
- - {videoProfile === 'none' ? -
- -
- :null - }
); } diff --git a/app/lib/components/PeerView.jsx b/app/lib/components/VideoContainers/PeerView.jsx similarity index 78% rename from app/lib/components/PeerView.jsx rename to app/lib/components/VideoContainers/PeerView.jsx index 4a512a6..1ca4543 100644 --- a/app/lib/components/PeerView.jsx +++ b/app/lib/components/VideoContainers/PeerView.jsx @@ -1,9 +1,8 @@ import React from 'react'; import PropTypes from 'prop-types'; import classnames from 'classnames'; -import Spinner from 'react-spinner'; -import * as appPropTypes from './appPropTypes'; -import EditableInput from './EditableInput'; +import * as appPropTypes from '../appPropTypes'; +import EditableInput from '../Controls/EditableInput'; export default class PeerView extends React.Component { @@ -52,51 +51,50 @@ export default class PeerView extends React.Component return (
- {advancedMode ? +
- {audioCodec ? +

{audioCodec}

- :null - } +
- {videoCodec ? +

{videoCodec} {videoProfile}

- :null - } +
- {(videoVisible && videoWidth !== null) ? +

{videoWidth}x{videoHeight}

- :null - } +
- :null - } +
- {isMe ? - onChangeDisplayName(displayName)} - /> - : - - {peer.displayName} - - } + + + onChangeDisplayName(displayName)} + /> + + + + {peer.displayName} + + + - {advancedMode ? +
- :null - } +
@@ -118,19 +115,13 @@ export default class PeerView extends React.Component loading : videoProfile === 'none' })} autoPlay + playsInline muted={isMe} />
- - {videoProfile === 'none' ? -
- -
- :null - }
); } diff --git a/app/lib/components/ScreenView.jsx b/app/lib/components/VideoContainers/ScreenView.jsx similarity index 87% rename from app/lib/components/ScreenView.jsx rename to app/lib/components/VideoContainers/ScreenView.jsx index 719c406..9ffa0d3 100644 --- a/app/lib/components/ScreenView.jsx +++ b/app/lib/components/VideoContainers/ScreenView.jsx @@ -1,7 +1,6 @@ import React from 'react'; import PropTypes from 'prop-types'; import classnames from 'classnames'; -import Spinner from 'react-spinner'; export default class ScreenView extends React.Component { @@ -41,25 +40,21 @@ export default class ScreenView extends React.Component return (
- {advancedMode ? +
- {screenVisible ? +
- {screenCodec ? +

{screenCodec} {screenProfile}

- :null - } +
- {(screenVisible && screenWidth !== null) ? +

{screenWidth}x{screenHeight}

- :null - } +
- :null - } +
- :null - } +
); } diff --git a/app/lib/components/VideoWindow/VideoWindow.jsx b/app/lib/components/VideoWindow/VideoWindow.jsx index c5a4a56..ce5ab01 100644 --- a/app/lib/components/VideoWindow/VideoWindow.jsx +++ b/app/lib/components/VideoWindow/VideoWindow.jsx @@ -4,7 +4,7 @@ import NewWindow from './NewWindow'; import PropTypes from 'prop-types'; import * as appPropTypes from '../appPropTypes'; import * as stateActions from '../../redux/stateActions'; -import FullView from '../FullView'; +import FullView from '../VideoContainers/FullView'; const VideoWindow = (props) => { diff --git a/app/lib/components/appPropTypes.js b/app/lib/components/appPropTypes.js index 392e854..74b52e3 100644 --- a/app/lib/components/appPropTypes.js +++ b/app/lib/components/appPropTypes.js @@ -76,3 +76,16 @@ export const Message = PropTypes.shape( text : PropTypes.string, sender : PropTypes.string }); + +export const FileEntryProps = PropTypes.shape( + { + data : PropTypes.shape({ + name : PropTypes.string.isRequired, + picture : PropTypes.string, + file : PropTypes.shape({ + magnet : PropTypes.string.isRequired + }).isRequired, + me : PropTypes.bool + }).isRequired, + notify : PropTypes.func.isRequired + }); \ No newline at end of file diff --git a/app/lib/index.jsx b/app/lib/index.jsx index 1348b09..3fefebe 100644 --- a/app/lib/index.jsx +++ b/app/lib/index.jsx @@ -7,8 +7,9 @@ import { getDeviceInfo } from 'mediasoup-client'; import randomString from 'random-string'; import Logger from './Logger'; import * as utils from './utils'; +import RoomClient from './RoomClient'; +import RoomContext from './RoomContext'; import * as cookiesManager from './cookiesManager'; -import * as requestActions from './redux/requestActions'; import * as stateActions from './redux/stateActions'; import Room from './components/Room'; import { loginEnabled } from '../config'; @@ -16,6 +17,10 @@ import { store } from './store'; const logger = new Logger(); +let roomClient; + +RoomClient.init({ store }); + domready(() => { logger.debug('DOM ready'); @@ -93,39 +98,38 @@ function run() device.version = undefined; } - // NOTE: I don't like this. store.dispatch( stateActions.setRoomUrl(roomUrl)); - // NOTE: I don't like this. store.dispatch( stateActions.setMe({ peerName, displayName, displayNameSet, device, loginEnabled })); - // NOTE: I don't like this. - store.dispatch( - requestActions.joinRoom( - { roomId, peerName, displayName, device, useSimulcast, produce })); + roomClient = new RoomClient( + { roomId, peerName, displayName, device, useSimulcast, produce }); render( - + + + , document.getElementById('multiparty-meeting') ); } // TODO: Debugging stuff. +global.CLIENT = roomClient; setInterval(() => { - if (!global.CLIENT._room.peers[0]) + if (!roomClient._room.peers[0]) { delete global.CONSUMER; return; } - const peer = global.CLIENT._room.peers[0]; + const peer = roomClient._room.peers[0]; global.CONSUMER = peer.consumers[peer.consumers.length - 1]; }, 2000); @@ -134,20 +138,20 @@ global.sendSdp = function() { logger.debug('---------- SEND_TRANSPORT LOCAL SDP OFFER:'); logger.debug( - global.CLIENT._sendTransport._handler._pc.localDescription.sdp); + roomClient._sendTransport._handler._pc.localDescription.sdp); logger.debug('---------- SEND_TRANSPORT REMOTE SDP ANSWER:'); logger.debug( - global.CLIENT._sendTransport._handler._pc.remoteDescription.sdp); + roomClient._sendTransport._handler._pc.remoteDescription.sdp); }; global.recvSdp = function() { logger.debug('---------- RECV_TRANSPORT REMOTE SDP OFFER:'); logger.debug( - global.CLIENT._recvTransport._handler._pc.remoteDescription.sdp); + roomClient._recvTransport._handler._pc.remoteDescription.sdp); logger.debug('---------- RECV_TRANSPORT LOCAL SDP ANSWER:'); logger.debug( - global.CLIENT._recvTransport._handler._pc.localDescription.sdp); + roomClient._recvTransport._handler._pc.localDescription.sdp); }; diff --git a/app/lib/redux/reducers/chatbehavior.js b/app/lib/redux/reducers/chatbehavior.js deleted file mode 100644 index 12e3e51..0000000 --- a/app/lib/redux/reducers/chatbehavior.js +++ /dev/null @@ -1,36 +0,0 @@ -const initialState = -{ - showChat : false, - disabledInput : false, - badge : 0 -}; - -const chatbehavior = (state = initialState, action) => -{ - switch (action.type) - { - case 'TOGGLE_CHAT': - { - const showChat = !state.showChat; - const badge = 0; - - return { ...state, showChat, badge }; - } - - case 'TOGGLE_INPUT_DISABLED': - { - const disabledInput = !state.disabledInput; - - return { ...state, disabledInput }; - } - - case 'INCREASE_BADGE': - { - return { ...state, badge: state.badge + (state.showChat ? 0 : 1) }; - } - default: - return state; - } -}; - -export default chatbehavior; diff --git a/app/lib/redux/reducers/files.js b/app/lib/redux/reducers/files.js new file mode 100644 index 0000000..19d5369 --- /dev/null +++ b/app/lib/redux/reducers/files.js @@ -0,0 +1,99 @@ +const files = (state = {}, action) => +{ + switch (action.type) + { + case 'ADD_FILE': + { + const { file } = action.payload; + + const newFile = { + active : false, + progress : 0, + files : null, + me : false, + ...file + }; + + return { ...state, [file.magnetUri]: newFile }; + } + + case 'ADD_FILE_HISTORY': + { + const { fileHistory } = action.payload; + const newFileHistory = {}; + + fileHistory.map((file) => + { + const newFile = { + active : false, + progress : 0, + files : null, + me : false, + ...file + }; + + newFileHistory[file.magnetUri] = newFile; + }); + + return { ...state, ...newFileHistory }; + } + + case 'SET_FILE_ACTIVE': + { + const { magnetUri } = action.payload; + const file = state[magnetUri]; + + const newFile = { ...file, active: true }; + + return { ...state, [magnetUri]: newFile }; + } + + case 'SET_FILE_INACTIVE': + { + const { magnetUri } = action.payload; + const file = state[magnetUri]; + + const newFile = { ...file, active: false }; + + return { ...state, [magnetUri]: newFile }; + } + + case 'SET_FILE_PROGRESS': + { + const { magnetUri, progress } = action.payload; + const file = state[magnetUri]; + + const newFile = { ...file, progress: progress }; + + return { ...state, [magnetUri]: newFile }; + } + + case 'SET_FILE_DONE': + { + const { magnetUri, sharedFiles } = action.payload; + const file = state[magnetUri]; + + const newFile = { + ...file, + files : sharedFiles, + progress : 1, + active : false, + timeout : false + }; + + return { ...state, [magnetUri]: newFile }; + } + + case 'REMOVE_FILE': + { + const { magnetUri } = action.payload; + + return state.filter((file) => file.magnetUri !== magnetUri); + } + + default: + return state; + } +}; + +export default files; diff --git a/app/lib/redux/reducers/index.js b/app/lib/redux/reducers/index.js index 1f59ace..e51dc85 100644 --- a/app/lib/redux/reducers/index.js +++ b/app/lib/redux/reducers/index.js @@ -6,9 +6,8 @@ import peers from './peers'; import consumers from './consumers'; import notifications from './notifications'; import chatmessages from './chatmessages'; -import chatbehavior from './chatbehavior'; import toolarea from './toolarea'; -import sharing from './sharing'; +import files from './files'; const reducers = combineReducers( { @@ -19,9 +18,8 @@ const reducers = combineReducers( consumers, notifications, chatmessages, - chatbehavior, toolarea, - sharing + files }); export default reducers; diff --git a/app/lib/redux/reducers/notifications.js b/app/lib/redux/reducers/notifications.js index bf3e6c0..142308e 100644 --- a/app/lib/redux/reducers/notifications.js +++ b/app/lib/redux/reducers/notifications.js @@ -1,6 +1,4 @@ -const initialState = []; - -const notifications = (state = initialState, action) => +const notifications = (state = [], action) => { switch (action.type) { diff --git a/app/lib/redux/reducers/room.js b/app/lib/redux/reducers/room.js index 89d2b21..eed2e8a 100644 --- a/app/lib/redux/reducers/room.js +++ b/app/lib/redux/reducers/room.js @@ -3,6 +3,7 @@ const initialState = url : null, state : 'new', // new/connecting/connected/disconnected/closed, activeSpeakerName : null, + torrentSupport : false, showSettings : false, advancedMode : false, fullScreenConsumer : null, // ConsumerID @@ -41,6 +42,13 @@ const room = (state = initialState, action) => return { ...state, activeSpeakerName: peerName }; } + case 'FILE_SHARING_SUPPORTED': + { + const { supported } = action.payload; + + return { ...state, torrentSupport: supported }; + } + case 'TOGGLE_SETTINGS': { const showSettings = !state.showSettings; diff --git a/app/lib/redux/reducers/sharing.js b/app/lib/redux/reducers/sharing.js deleted file mode 100644 index 299a155..0000000 --- a/app/lib/redux/reducers/sharing.js +++ /dev/null @@ -1,19 +0,0 @@ -const sharing = (state = [], action) => -{ - switch (action.type) - { - case 'SEND_FILE': - return [ ...state, { ...action.payload, me: true } ]; - - case 'ADD_FILE': - return [ ...state, action.payload ]; - - case 'ADD_FILE_HISTORY': - return [ ...action.payload.fileHistory, ...state ]; - - default: - return state; - } -}; - -export default sharing; \ No newline at end of file diff --git a/app/lib/redux/requestActions.js b/app/lib/redux/requestActions.js index d9ba059..ae2db27 100644 --- a/app/lib/redux/requestActions.js +++ b/app/lib/redux/requestActions.js @@ -1,233 +1,5 @@ import randomString from 'random-string'; import * as stateActions from './stateActions'; -import -{ - createNewMessage -} from './reducers/helper'; - -export const joinRoom = ( - { roomId, peerName, displayName, device, useSimulcast, produce }) => -{ - return { - type : 'JOIN_ROOM', - payload : { roomId, peerName, displayName, device, useSimulcast, produce } - }; -}; - -export const leaveRoom = () => -{ - return { - type : 'LEAVE_ROOM' - }; -}; - -export const changeDisplayName = (displayName) => -{ - return { - type : 'CHANGE_DISPLAY_NAME', - payload : { displayName } - }; -}; - -export const muteMic = () => -{ - return { - type : 'MUTE_MIC' - }; -}; - -export const unmuteMic = () => -{ - return { - type : 'UNMUTE_MIC' - }; -}; - -export const enableWebcam = () => -{ - return { - type : 'ENABLE_WEBCAM' - }; -}; - -export const disableWebcam = () => -{ - return { - type : 'DISABLE_WEBCAM' - }; -}; - -export const changeWebcam = (deviceId) => -{ - return { - type : 'CHANGE_WEBCAM', - payload : { deviceId } - }; -}; - -export const changeAudioDevice = (deviceId) => -{ - return { - type : 'CHANGE_AUDIO_DEVICE', - payload : { deviceId } - }; -}; - -export const enableAudioOnly = () => -{ - return { - type : 'ENABLE_AUDIO_ONLY' - }; -}; - -export const disableAudioOnly = () => -{ - return { - type : 'DISABLE_AUDIO_ONLY' - }; -}; - -export const mutePeerAudio = (peerName) => -{ - return { - type : 'MUTE_PEER_AUDIO', - payload : { peerName } - }; -}; - -export const unmutePeerAudio = (peerName) => -{ - return { - type : 'UNMUTE_PEER_AUDIO', - payload : { peerName } - }; -}; - -export const pausePeerVideo = (peerName) => -{ - return { - type : 'PAUSE_PEER_VIDEO', - payload : { peerName } - }; -}; - -export const resumePeerVideo = (peerName) => -{ - return { - type : 'RESUME_PEER_VIDEO', - payload : { peerName } - }; -}; - -export const pausePeerScreen = (peerName) => -{ - return { - type : 'PAUSE_PEER_SCREEN', - payload : { peerName } - }; -}; - -export const resumePeerScreen = (peerName) => -{ - return { - type : 'RESUME_PEER_SCREEN', - payload : { peerName } - }; -}; - -export const userLogin = () => -{ - return { - type : 'USER_LOGIN' - }; -}; - -export const userLogout = () => -{ - return { - type : 'USER_LOGOUT' - }; -}; - -export const raiseHand = () => -{ - return { - type : 'RAISE_HAND' - }; -}; - -export const lowerHand = () => -{ - return { - type : 'LOWER_HAND' - }; -}; - -export const restartIce = () => -{ - return { - type : 'RESTART_ICE' - }; -}; - -export const enableScreenSharing = () => -{ - return { - type : 'ENABLE_SCREEN_SHARING' - }; -}; - -export const disableScreenSharing = () => -{ - return { - type : 'DISABLE_SCREEN_SHARING' - }; -}; - -export const installExtension = () => -{ - return { - type : 'INSTALL_EXTENSION' - }; -}; - -export const toggleHand = (enable) => -{ - if (enable) - return { - type : 'RAISE_HAND' - }; - else - return { - type : 'LOWER_HAND' - }; -}; - -export const sendChatMessage = (text, name, picture) => -{ - const message = createNewMessage(text, 'response', name, picture); - - return { - type : 'SEND_CHAT_MESSAGE', - payload : { message } - }; -}; - -export const sendFile = (file, name, picture) => -{ - return { - type : 'SEND_FILE', - payload : { file, name, picture } - }; -}; - -export const setSelectedPeer = (selectedPeerName) => -{ - return { - type : 'REQUEST_SELECTED_PEER', - payload : { selectedPeerName } - }; -}; // This returns a redux-thunk action (a function). export const notify = ({ type = 'info', text, timeout }) => diff --git a/app/lib/redux/roomClientMiddleware.js b/app/lib/redux/roomClientMiddleware.js deleted file mode 100644 index 265c8cb..0000000 --- a/app/lib/redux/roomClientMiddleware.js +++ /dev/null @@ -1,253 +0,0 @@ -import RoomClient from '../RoomClient'; - -export default ({ dispatch, getState }) => (next) => -{ - let client; - - return (action) => - { - switch (action.type) - { - case 'JOIN_ROOM': - { - const { - roomId, - peerName, - displayName, - device, - useSimulcast, - produce - } = action.payload; - - client = new RoomClient( - { - roomId, - peerName, - displayName, - device, - useSimulcast, - produce, - dispatch, - getState - }); - - // TODO: TMP - global.CLIENT = client; - - break; - } - - case 'LEAVE_ROOM': - { - client.close(); - - break; - } - - case 'CHANGE_DISPLAY_NAME': - { - const { displayName } = action.payload; - - client.changeDisplayName(displayName); - - break; - } - - case 'MUTE_MIC': - { - client.muteMic(); - - break; - } - - case 'UNMUTE_MIC': - { - client.unmuteMic(); - - break; - } - - case 'ENABLE_WEBCAM': - { - client.enableWebcam(); - - break; - } - - case 'DISABLE_WEBCAM': - { - client.disableWebcam(); - - break; - } - - case 'CHANGE_WEBCAM': - { - const { deviceId } = action.payload; - - client.changeWebcam(deviceId); - - break; - } - - case 'CHANGE_AUDIO_DEVICE': - { - const { deviceId } = action.payload; - - client.changeAudioDevice(deviceId); - - break; - } - - case 'ENABLE_AUDIO_ONLY': - { - client.enableAudioOnly(); - - break; - } - - case 'DISABLE_AUDIO_ONLY': - { - client.disableAudioOnly(); - - break; - } - - case 'MUTE_PEER_AUDIO': - { - const { peerName } = action.payload; - - client.mutePeerAudio(peerName); - - break; - } - - case 'UNMUTE_PEER_AUDIO': - { - const { peerName } = action.payload; - - client.unmutePeerAudio(peerName); - - break; - } - - case 'PAUSE_PEER_VIDEO': - { - const { peerName } = action.payload; - - client.pausePeerVideo(peerName); - - break; - } - - case 'RESUME_PEER_VIDEO': - { - const { peerName } = action.payload; - - client.resumePeerVideo(peerName); - - break; - } - - case 'PAUSE_PEER_SCREEN': - { - const { peerName } = action.payload; - - client.pausePeerScreen(peerName); - - break; - } - - case 'RESUME_PEER_SCREEN': - { - const { peerName } = action.payload; - - client.resumePeerScreen(peerName); - - break; - } - - case 'RAISE_HAND': - { - client.sendRaiseHandState(true); - - break; - } - - case 'USER_LOGIN': - { - client.login(); - - break; - } - - case 'USER_LOGOUT': - { - client.logout(); - - break; - } - - case 'LOWER_HAND': - { - client.sendRaiseHandState(false); - - break; - } - - case 'RESTART_ICE': - { - client.restartIce(); - - break; - } - - case 'ENABLE_SCREEN_SHARING': - { - client.enableScreenSharing(); - - break; - } - - case 'DISABLE_SCREEN_SHARING': - { - client.disableScreenSharing(); - - break; - } - - case 'INSTALL_EXTENSION': - { - client.installExtension(); - - break; - } - - case 'SEND_CHAT_MESSAGE': - { - const { message } = action.payload; - - client.sendChatMessage(message); - - break; - } - - case 'SEND_FILE': - { - client.sendFile(action.payload); - break; - } - - case 'REQUEST_SELECTED_PEER': - { - const { selectedPeerName } = action.payload; - - client.setSelectedPeer(selectedPeerName); - - break; - } - } - - return next(action); - }; -}; diff --git a/app/lib/redux/stateActions.js b/app/lib/redux/stateActions.js index 3ced6b6..a837631 100644 --- a/app/lib/redux/stateActions.js +++ b/app/lib/redux/stateActions.js @@ -70,6 +70,14 @@ export const setWebcamDevices = (devices) => }; }; +export const setFileSharingSupported = (supported) => +{ + return { + type : 'FILE_SHARING_SUPPORTED', + payload : { supported } + }; +}; + export const setDisplayName = (displayName) => { return { @@ -455,11 +463,11 @@ export const dropMessages = () => }; }; -export const addFile = (payload) => +export const addFile = (file) => { return { - type : 'ADD_FILE', - payload + type : 'ADD_FILE', + payload : { file } }; }; @@ -471,6 +479,38 @@ export const addFileHistory = (fileHistory) => }; }; +export const setFileActive = (magnetUri) => +{ + return { + type : 'SET_FILE_ACTIVE', + payload : { magnetUri } + }; +}; + +export const setFileInActive = (magnetUri) => +{ + return { + type : 'SET_FILE_INACTIVE', + payload : { magnetUri } + }; +}; + +export const setFileProgress = (magnetUri, progress) => +{ + return { + type : 'SET_FILE_PROGRESS', + payload : { magnetUri, progress } + }; +}; + +export const setFileDone = (magnetUri, sharedFiles) => +{ + return { + type : 'SET_FILE_DONE', + payload : { magnetUri, sharedFiles } + }; +}; + export const setPicture = (picture) => ({ type : 'SET_PICTURE', diff --git a/app/lib/store.js b/app/lib/store.js index f3652f2..8553661 100644 --- a/app/lib/store.js +++ b/app/lib/store.js @@ -6,12 +6,10 @@ import { import thunk from 'redux-thunk'; import { createLogger } from 'redux-logger'; import reducers from './redux/reducers'; -import roomClientMiddleware from './redux/roomClientMiddleware'; const reduxMiddlewares = [ - thunk, - roomClientMiddleware + thunk ]; if (process.env.NODE_ENV === 'development') diff --git a/app/package.json b/app/package.json index 314e8f2..340b688 100644 --- a/app/package.json +++ b/app/package.json @@ -1,6 +1,6 @@ { "name": "multiparty-meeting", - "version": "1.0.0", + "version": "1.1.0", "private": true, "description": "multiparty meeting service", "author": "Håvar Aambø Fosstveit ", @@ -47,6 +47,7 @@ "@babel/plugin-transform-runtime": "^7.1.0", "@babel/preset-env": "^7.1.0", "@babel/preset-react": "^7.0.0", + "babel-plugin-jsx-control-statements": "^3.2.8", "babel-eslint": "^10.0.1", "babelify": "^10.0.0", "browser-sync": "^2.26.3", diff --git a/app/stylus/components/Chat.styl b/app/stylus/components/Chat.styl index b6a480d..c495496 100644 --- a/app/stylus/components/Chat.styl +++ b/app/stylus/components/Chat.styl @@ -23,7 +23,7 @@ } > .client, > .response { - background-color: rgba(#000, 0.1); + background-color: var(--chat-message-color); border-radius: 5px; max-width: 85%; display: flex; @@ -70,8 +70,8 @@ [data-component='Sender'] { display: flex; - background-color: #fff; - color: #000; + background-color: var(--chat-input-bg-color); + color: var(--chat-input-text-color); flex-shrink: 0; margin-top: 0.5rem; height: 3rem; @@ -84,7 +84,6 @@ margin-right: 1vmin; border-radius: 0.5vmin; padding-left: 1vmin; - color: #000; &.focus { outline: none; @@ -95,8 +94,7 @@ width: 20%; box-shadow: 0vmin 0vmin 1vmin 0vmin rgba(17,17,17,0.5); border: 0; - background-color: #aef; - color: #000; + background-color: var(--chat-send-bg-color); font-size: 1rem; border-radius: 0.5vmin; } diff --git a/app/stylus/components/FileSharing.styl b/app/stylus/components/FileSharing.styl index 1bf88fa..9019bdb 100644 --- a/app/stylus/components/FileSharing.styl +++ b/app/stylus/components/FileSharing.styl @@ -7,11 +7,15 @@ > .share-file { cursor: pointer; width: 100%; - background: #aef; + background: var(--filesharing-bg-color); padding: 1rem; border-radius: 1vmin; box-shadow: 0vmin 0vmin 1vmin 0vmin rgba(17,17,17,0.5); + &:hover { + opacity: 0.85; + } + &.disabled { cursor: not-allowed; } diff --git a/app/stylus/components/Filmstrip.styl b/app/stylus/components/Filmstrip.styl index 5753049..ab92a9f 100644 --- a/app/stylus/components/Filmstrip.styl +++ b/app/stylus/components/Filmstrip.styl @@ -63,13 +63,13 @@ &.active { > .film-content { - border-color: #FFF; + border-color: var(--active-speaker-border-color); } } &.selected { > .film-content { - border-color: #377EFF; + border-color: var(--selected-peer-border-color); } } } diff --git a/app/stylus/components/FullView.styl b/app/stylus/components/FullView.styl index 251a04a..8c5b799 100644 --- a/app/stylus/components/FullView.styl +++ b/app/stylus/components/FullView.styl @@ -69,37 +69,4 @@ filter: blur(5px); } } - - > .spinner-container { - position: absolute; - top: 0 - bottom: 0; - left: 0; - right: 0; - background-color: rgba(#000, 0.75); - - .react-spinner { - position: relative; - width: 48px; - height: 48px; - top: 50%; - left: 50%; - - .react-spinner_bar { - position: absolute; - width: 20%; - height: 7.8%; - top: -3.9%; - left: -10%; - animation: PeerView-spinner 1.2s linear infinite; - border-radius: 5px; - background-color: rgba(#fff, 0.5); - } - } - } -} - -@keyframes FullView-spinner { - 0% { opacity: 1; } - 100% { opacity: 0.15; } } diff --git a/app/stylus/components/HiddenPeersView.styl b/app/stylus/components/HiddenPeers.styl similarity index 53% rename from app/stylus/components/HiddenPeersView.styl rename to app/stylus/components/HiddenPeers.styl index b87ddf0..6ca7ec8 100644 --- a/app/stylus/components/HiddenPeersView.styl +++ b/app/stylus/components/HiddenPeers.styl @@ -1,4 +1,4 @@ -[data-component='HiddenPeersView'] { +[data-component='HiddenPeers'] { height: 100%; width: 100%; display: flex; @@ -31,6 +31,8 @@ background-position: bottom; background-size: auto 85%; background-repeat: no-repeat; + border: var(--peer-border); + box-shadow: var(--peer-shadow); text-align: center; vertical-align: middle; line-height: 1.8vmin; @@ -39,55 +41,28 @@ animation: none; &.pulse { - animation: pulse 2s; + animation: pulse 0.5s; } } .view-container>p{ transform: translate(0%,50%); } - - .view-container, - .view-container::before, - .view-container::after { - /* Add shadow to distinguish sheets from one another */ - box-shadow: 2px 1px 1px rgba(0,0,0,0.15); - } - - .view-container::before, - .view-container::after { - content: ""; - position: absolute; - width: 100%; - height: 100%; - background-color: #2a4b58; - } - - /* Second sheet of paper */ - .view-container::before { - left: .7vmin; - top: .7vmin; - z-index: -1; - } - - /* Third sheet of paper */ - .view-container::after { - left: 1.4vmin; - top: 1.4vmin; - z-index: -2; - } } @keyframes pulse { - 0% { - box-shadow: 0 0 0 0 rgba(255, 255, 255, 1.0); + 0% + { + transform: scale3d(1, 1, 1); } - 70% { - box-shadow: 0 0 0 10px rgba(255, 255, 255, 0); + 50% + { + transform: scale3d(1.2, 1.2, 1.2); } - 100% { - box-shadow: 0 0 0 0 rgba(255, 255, 255, 0); + 100% + { + transform: scale3d(1, 1, 1); } } diff --git a/app/stylus/components/Logo.styl b/app/stylus/components/Logo.styl index b52cabc..f34410a 100644 --- a/app/stylus/components/Logo.styl +++ b/app/stylus/components/Logo.styl @@ -1,19 +1,18 @@ [data-component='Logo'] { - position: absolute; - height: 4%; - width: 8%; + position: absolute; + width: var(--logo-width); + height: var(--logo-height); top: 1%; left: 1%; z-index: 20; background-position: left; background-size: 100%; background-repeat: no-repeat; + +desktop() { opacity: 1; } - +mobile() { - } - background-image: url('/resources/images/logo.svg'); + background-image: var(--logo); background-size: contain; } diff --git a/app/stylus/components/Me.styl b/app/stylus/components/Me.styl index 2d70e8f..d4b0a26 100644 --- a/app/stylus/components/Me.styl +++ b/app/stylus/components/Me.styl @@ -6,8 +6,8 @@ > .view-container { position: relative; - width: 20vmin; - height: 15vmin; + width: var(--me-width); + height: var(--me-height); &.webcam { order: 2; @@ -23,9 +23,7 @@ right: 0; top: 0; display: flex; - flex-direction:; row; - justify-content: flex-start; - align-items: center; + flex-direction: row; padding: 0.4vmin; opacity: 0; transition: opacity 0.3s; @@ -41,41 +39,37 @@ background-position: center; background-size: 75%; background-repeat: no-repeat; - background-color: rgba(#000, 0.5); + background-color: var(--media-control-button-color); cursor: pointer; opacity: 0; transition-property: opacity, background-color; transition-duration: 0.15s; + width: var(--media-control-button-size); + height: var(--media-control-button-size); + + &:hover { + opacity: 1; + } &.visible { opacity: 0.85; } - +desktop() { - width: 24px; - height: 24px; - - &:hover { - opacity: 1; - } - } - - +mobile() { - width: 22px; - height: 22px; - } - &.unsupported { pointer-events: none; } &.disabled { pointer-events: none; - opacity: 0.5; + background-color: var(--media-control-botton-disabled); } &.on { - background-color: rgba(#fff, 0.7); + background-color: var(--media-control-botton-on); + } + + &.off { + background-color: var(--media-control-botton-off); } &.mic { @@ -85,7 +79,6 @@ &.off { background-image: url('/resources/images/icon_remote_mic_white_off.svg'); - background-color: rgba(#d42241, 0.7); } &.unsupported { @@ -100,33 +93,12 @@ &.off { background-image: url('/resources/images/icon_remote_webcam_white_off.svg'); - background-color: rgba(#d42241, 0.7); } &.unsupported { background-image: url('/resources/images/icon_webcam_white_unsupported.svg'); } } - - &.screen { - &.on { - background-image: url('/resources/images/share-screen-black.svg'); - } - - &.off { - background-image: url('/resources/images/no-share-screen-white.svg'); - background-color: rgba(#d42241, 0.7); - } - - &.unsupported { - background-image: url('/resources/images/no-share-screen-white.svg'); - } - } - - &.fullscreen { - background-image: url('/resources/images/icon_fullscreen_black.svg'); - background-color: rgba(#fff, 0.7); - } } } } diff --git a/app/stylus/components/Notifications.styl b/app/stylus/components/Notifications.styl index b247cb7..fcaeded 100644 --- a/app/stylus/components/Notifications.styl +++ b/app/stylus/components/Notifications.styl @@ -84,8 +84,8 @@ } &.info { - background-color: rgba(#0a1d26, 0.75); - color: rgba(#fff, 0.65); + background-color: var(--notification-info-bg-color); + color: var(--notification-info-text-color); >.icon { opacity: 0.65; @@ -94,8 +94,8 @@ } &.error { - background-color: rgba(#ff1914, 0.65); - color: rgba(#fff, 0.85); + background-color: var(--notification-error-bg-color); + color: var(--notification-error-text-color); >.icon { opacity: 0.85; diff --git a/app/stylus/components/ParticipantList.styl b/app/stylus/components/ParticipantList.styl index 06ea717..fefa8da 100644 --- a/app/stylus/components/ParticipantList.styl +++ b/app/stylus/components/ParticipantList.styl @@ -51,20 +51,12 @@ background-color: rgba(#000, 0.5); transition-property: opacity, background-color; transition-duration: 0.15s; + width: var(--media-control-button-size); + height: var(--media-control-button-size); + opacity: 0.85; - +desktop() { - width: 24px; - height: 24px; - opacity: 0.85; - - &:hover { - opacity: 1; - } - } - - +mobile() { - width: 22px; - height: 22px; + &:hover { + opacity: 1; } &.on { @@ -102,19 +94,20 @@ position: absolute; bottom: 0px; - &.level0 { height: 0; background-color: rgba(#000, 0.8); } - &.level1 { height: 0.2vh; background-color: rgba(#000, 0.8); } - &.level2 { height: 0.4vh; background-color: rgba(#000, 0.8); } - &.level3 { height: 0.6vh; background-color: rgba(#000, 0.8); } - &.level4 { height: 0.8vh; background-color: rgba(#000, 0.8); } - &.level5 { height: 1.0vh; background-color: rgba(#000, 0.8); } - &.level6 { height: 1.2vh; background-color: rgba(#000, 0.8); } - &.level7 { height: 1.4vh; background-color: rgba(#000, 0.8); } - &.level8 { height: 1.6vh; background-color: rgba(#000, 0.8); } - &.level9 { height: 1.8vh; background-color: rgba(#000, 0.8); } - &.level10 { height: 2.0vh; background-color: rgba(#000, 0.8); } + &.level0 { height: 0; } + &.level1 { height: 0.2vh; } + &.level2 { height: 0.4vh; } + &.level3 { height: 0.6vh; } + &.level4 { height: 0.8vh; } + &.level5 { height: 1.0vh; } + &.level6 { height: 1.2vh; } + &.level7 { height: 1.4vh; } + &.level8 { height: 1.6vh; } + &.level9 { height: 1.8vh; } + &.level10 { height: 2.0vh; } } } + > .controls { float: right; display: flex; @@ -133,20 +126,12 @@ cursor: pointer; transition-property: opacity, background-color; transition-duration: 0.15s; + width: var(--media-control-button-size); + height: var(--media-control-button-size); + opacity: 0.85; - +desktop() { - width: 24px; - height: 24px; - opacity: 0.85; - - &:hover { - opacity: 1; - } - } - - +mobile() { - width: 22px; - height: 22px; + &:hover { + opacity: 1; } &.unsupported { @@ -155,11 +140,15 @@ &.disabled { pointer-events: none; - opacity: 0.5; + background-color: var(--media-control-botton-disabled); } &.on { - background-color: rgba(#fff, 0.7); + background-color: var(--media-control-botton-on); + } + + &.off { + background-color: var(--media-control-botton-off); } &.mic { @@ -169,7 +158,6 @@ &.off { background-image: url('/resources/images/icon_remote_mic_white_off.svg'); - background-color: rgba(#d42241, 0.7); } &.unsupported { @@ -184,7 +172,6 @@ &.off { background-image: url('/resources/images/icon_remote_webcam_white_off.svg'); - background-color: rgba(#d42241, 0.7); } &.unsupported { @@ -199,7 +186,6 @@ &.off { background-image: url('/resources/images/no-share-screen-white.svg'); - background-color: rgba(#d42241, 0.7); } &.unsupported { @@ -210,16 +196,16 @@ } > .avatar { - border-radius: 50%; - height: 2rem; + border-radius: 50%; + height: 2rem; } > .peer-info { - font-size: 1rem; - border: none; - display: flex; - padding-left: 0.5rem; - flex-grow: 1; - align-items: center; + font-size: 1rem; + border: none; + display: flex; + padding-left: 0.5rem; + flex-grow: 1; + align-items: center; } } diff --git a/app/stylus/components/Peer.styl b/app/stylus/components/Peer.styl index 9e38042..b90be85 100644 --- a/app/stylus/components/Peer.styl +++ b/app/stylus/components/Peer.styl @@ -54,20 +54,12 @@ background-color: rgba(#000, 0.5); transition-property: opacity, background-color; transition-duration: 0.15s; + width: var(--media-control-button-size); + height: var(--media-control-button-size); + opacity: 0.85; - +desktop() { - width: 24px; - height: 24px; - opacity: 0.85; - - &:hover { - opacity: 1; - } - } - - +mobile() { - width: 22px; - height: 22px; + &:hover { + opacity: 1; } &.on { @@ -107,24 +99,16 @@ background-position: center; background-size: 75%; background-repeat: no-repeat; - background-color: rgba(#000, 0.5); + background-color: var(--media-control-button-color); cursor: pointer; transition-property: opacity, background-color; transition-duration: 0.15s; + width: var(--media-control-button-size); + height: var(--media-control-button-size); + opacity: 0.85; - +desktop() { - width: 24px; - height: 24px; - opacity: 0.85; - - &:hover { - opacity: 1; - } - } - - +mobile() { - width: 22px; - height: 22px; + &:hover { + opacity: 1; } &.unsupported { @@ -133,11 +117,15 @@ &.disabled { pointer-events: none; - opacity: 0.5; + background-color: var(--media-control-botton-disabled); } &.on { - background-color: rgba(#fff, 0.7); + background-color: var(--media-control-botton-on); + } + + &.off { + background-color: var(--media-control-botton-off); } &.mic { @@ -147,7 +135,6 @@ &.off { background-image: url('/resources/images/icon_remote_mic_white_off.svg'); - background-color: rgba(#d42241, 0.7); } &.unsupported { @@ -155,21 +142,6 @@ } } - &.webcam { - &.on { - background-image: url('/resources/images/icon_webcam_black_on.svg'); - } - - &.off { - background-image: url('/resources/images/icon_remote_webcam_white_off.svg'); - background-color: rgba(#d42241, 0.7); - } - - &.unsupported { - background-image: url('/resources/images/icon_webcam_white_unsupported.svg'); - } - } - &.screen { &.on { background-image: url('/resources/images/share-screen-black.svg'); @@ -177,7 +149,6 @@ &.off { background-image: url('/resources/images/no-share-screen-white.svg'); - background-color: rgba(#d42241, 0.7); } &.unsupported { @@ -187,12 +158,10 @@ &.fullscreen { background-image: url('/resources/images/icon_fullscreen_black.svg'); - background-color: rgba(#fff, 0.7); } &.newwindow { background-image: url('/resources/images/icon_new_window_black.svg'); - background-color: rgba(#fff, 0.7); } } } diff --git a/app/stylus/components/PeerView.styl b/app/stylus/components/PeerView.styl index 907c7e2..9a02380 100644 --- a/app/stylus/components/PeerView.styl +++ b/app/stylus/components/PeerView.styl @@ -6,15 +6,13 @@ display: flex; flex-direction: column; overflow: hidden; - background-color: rgba(#2a4b58, 0.9); - background-image: url('/resources/images/buddy.svg'); + background-color: var(--peer-bg-color); + background-image: var(--peer-empty-avatar); background-position: bottom; background-size: auto 85%; background-repeat: no-repeat; > .info { - $backgroundTint = #000; - position: absolute; z-index: 10; top: 0.6vmin; @@ -178,7 +176,7 @@ user-select: none; transition-property: opacity; transition-duration: .15s; - background-color: rgba(#000, 0.75); + background-color: var(--peer-video-bg-color); &.is-me { transform: scaleX(-1); @@ -225,37 +223,4 @@ &.level10 { height: 100%; background-color: rgba(#000, 0.65); } } } - - > .spinner-container { - position: absolute; - top: 0 - bottom: 0; - left: 0; - right: 0; - background-color: rgba(#000, 0.75); - - .react-spinner { - position: relative; - width: 48px; - height: 48px; - top: 50%; - left: 50%; - - .react-spinner_bar { - position: absolute; - width: 20%; - height: 7.8%; - top: -3.9%; - left: -10%; - animation: PeerView-spinner 1.2s linear infinite; - border-radius: 5px; - background-color: rgba(#fff, 0.5); - } - } - } -} - -@keyframes PeerView-spinner { - 0% { opacity: 1; } - 100% { opacity: 0.15; } } diff --git a/app/stylus/components/Peers.styl b/app/stylus/components/Peers.styl index f9283f0..85ee7c3 100644 --- a/app/stylus/components/Peers.styl +++ b/app/stylus/components/Peers.styl @@ -31,18 +31,18 @@ +desktop() { flex: 0 0 auto; margin: 6px; - border: 1px solid rgba(#fff, 0.15); - box-shadow: 0px 5px 12px 2px rgba(#111, 0.5); + border: var(--peer-border); + box-shadow: var(--peer-shadow); transition-property: border-color; transition-duration: 0.15s; &.active-speaker { - border-color: #fff; + border-color: var(--active-speaker-border-color); } &.selected { > .peer-content { - border: 1px solid #377eff; + border-color: var(--selected-peer-border-color); } } } diff --git a/app/stylus/components/Room.styl b/app/stylus/components/Room.styl index 5984bfb..f107704 100644 --- a/app/stylus/components/Room.styl +++ b/app/stylus/components/Room.styl @@ -143,24 +143,15 @@ position: fixed; z-index: 110; overflow: hidden; - box-shadow: 0px 5px 12px 2px rgba(#111, 0.5); + box-shadow: var(--me-shadow); transition-property: border-color; transition-duration: 0.15s; + top: 6%; + left:1%; + border: var(--me-border); &.active-speaker { - border-color: #fff; - } - - +desktop() { - top: 6%; - left:1%; - border: 1px solid rgba(#fff, 0.15); - } - - +mobile() { - top: 6%; - left: 1%; - border: 1px solid rgba(#fff, 0.25); + border-color: var(--active-speaker-border-color); } } } diff --git a/app/stylus/components/ScreenView.styl b/app/stylus/components/ScreenView.styl index 4c4dc66..84a038c 100644 --- a/app/stylus/components/ScreenView.styl +++ b/app/stylus/components/ScreenView.styl @@ -6,15 +6,13 @@ display: flex; flex-direction: column; overflow: hidden; - background-color: rgba(#2a4b58, 0.9); - background-image: url('/resources/images/buddy.svg'); + background-color: var(--peer-bg-color); + background-image: var(--peer-empty-avatar); background-position: bottom; background-size: auto 85%; background-repeat: no-repeat; > .info { - $backgroundTint = #000; - position: absolute; z-index: 10; top: 0.6vmin; @@ -58,7 +56,7 @@ user-select: none; transition-property: opacity; transition-duration: .15s; - background-color: rgba(#000, 0.75); + background-color: var(--peer-video-bg-color); &.is-me { transform: scaleX(-1); @@ -73,37 +71,4 @@ filter: blur(5px); } } - - > .spinner-container { - position: absolute; - top: 0 - bottom: 0; - left: 0; - right: 0; - background-color: rgba(#000, 0.75); - - .react-spinner { - position: relative; - width: 48px; - height: 48px; - top: 50%; - left: 50%; - - .react-spinner_bar { - position: absolute; - width: 20%; - height: 7.8%; - top: -3.9%; - left: -10%; - animation: PeerView-spinner 1.2s linear infinite; - border-radius: 5px; - background-color: rgba(#fff, 0.5); - } - } - } -} - -@keyframes ScreenView-spinner { - 0% { opacity: 1; } - 100% { opacity: 0.15; } } diff --git a/app/stylus/components/Settings.styl b/app/stylus/components/Settings.styl deleted file mode 100644 index b5f818d..0000000 --- a/app/stylus/components/Settings.styl +++ /dev/null @@ -1,3 +0,0 @@ -[data-component='Settings'] { - -} diff --git a/app/stylus/components/Sidebar.styl b/app/stylus/components/Sidebar.styl index 0c69fa8..145b80f 100644 --- a/app/stylus/components/Sidebar.styl +++ b/app/stylus/components/Sidebar.styl @@ -1,8 +1,8 @@ [data-component='Sidebar'] { position: fixed; z-index: 500; - top: calc(50% - 60px); - height: 120px; + top: 50%; + transform: translate(0%, -50%); display: flex; flex-direction: column; justify-content: center; @@ -24,7 +24,7 @@ background-position: center; background-size: 75%; background-repeat: no-repeat; - background-color: rgba(#fff, 0.3); + background-color: var(--circle-button-color); cursor: pointer; transition-property: opacity, background-color; transition-duration: 0.15s; @@ -32,24 +32,20 @@ display: flex; align-items: center; justify-content: center; - - +desktop() { - height: 2.5em; - width: 2.5em; - } - - +mobile() { - height: 2.5em; - width: 2.5em; - } + height: var(--circle-button-size); + width: var(--circle-button-size); &.on { - background-color: rgba(#fff, 0.7); + background-color: var(--circle-button-toggled-color); + } + + &.unsupported { + background-color: var(--circle-button-unsupported-color); } &.disabled { pointer-events: none; - opacity: 0.5; + background-color: var(--circle-button-diabled-color); } &.login { @@ -93,7 +89,6 @@ &.unsupported { background-image: url('/resources/images/no-share-screen-white.svg'); - background-color: rgba(#d42241, 0.7); } &.need-extension { diff --git a/app/stylus/components/ToolArea.styl b/app/stylus/components/ToolArea.styl index 9283d42..154802b 100644 --- a/app/stylus/components/ToolArea.styl +++ b/app/stylus/components/ToolArea.styl @@ -19,12 +19,6 @@ } } -[data-component='ToolAreaButton'] { - &.on { - right: 80%; - } -} - [data-component='ToolArea'] { &.open { width: 80%; @@ -33,35 +27,6 @@ .toolarea-shade.open { display: block; } - > .button { - background-position: center; - background-size: 100%; - background-repeat: no-repeat; - background-color: rgba(#aef); - cursor: pointer; - border-radius: 15%; - padding: 1px; - - +desktop() { - height: 36px; - width: 18px; - } - - +mobile() { - height: 32px; - width: 16px; - } - &.toolarea-close-button { - background-image: url('/resources/images/arrow_right.svg'); - position: absolute; - top: 50%; - left: -22px; - display: none; - &.on { - display: block; - } - } - } > .toolarea-button { text-align: center; @@ -153,12 +118,6 @@ } @media (min-width: 600px) { - [data-component='ToolAreaButton'] { - &.on { - right: 60%; - } - } - [data-component='ToolArea'] { &.open { width: 60%; @@ -167,12 +126,6 @@ } @media (min-width: 900px) { - [data-component='ToolAreaButton'] { - &.on { - right: 40%; - } - } - [data-component='ToolArea'] { &.open { width: 40%; @@ -181,12 +134,6 @@ } @media (min-width: 1500px) { - [data-component='ToolAreaButton'] { - &.on { - right: 25%; - } - } - [data-component='ToolArea'] { &.open { width: 25%; @@ -194,79 +141,6 @@ } } -[data-component='ToolAreaButton'] { - position: absolute; - z-index: 1020; - right: 0; - height: 36px; - width: 36px; - margin: 2rem; - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - transition: right 0.3s; - - > .button { - flex: 0 0 auto; - margin: 4px 0; - background-position: center; - background-size: 75%; - background-repeat: no-repeat; - background-color: rgba(#fff, 0.3); - cursor: pointer; - transition-property: opacity, background-color; - transition-duration: 0.15s; - border-radius: 100%; - - +desktop() { - height: 36px; - width: 36px; - } - - +mobile() { - height: 32px; - width: 32px; - } - - &.on { - background-color: rgba(#fff, 0.7); - } - - &.disabled { - pointer-events: none; - opacity: 0.5; - } - - &.toolarea-button { - background-image: url('/resources/images/icon_tool_area_white.svg'); - - &.on { - background-image: url('/resources/images/icon_tool_area_black.svg'); - } - } - } - - > .badge { - border-radius: 50%; - font-size: 1rem; - background: #b12525; - color: #fff; - text-align: center; - margin-top: -8px; - line-height: 1rem; - margin-right: -8px; - position: absolute; - padding: 0.2rem 0.4rem; - top: 0; - right: 0; - - &.long { - border-radius: 25% / 50%; - } - } -} - [data-component='ToolArea'] { width: 100%; height: 100%; diff --git a/app/stylus/index.styl b/app/stylus/index.styl index 309fa2b..ad67260 100644 --- a/app/stylus/index.styl +++ b/app/stylus/index.styl @@ -7,6 +7,53 @@ global-reset(); @import './reset'; @import './keyframes'; +:root { + --logo: url('/resources/images/logo.svg'); + --logo-width: 8%; + --logo-height: 4%; + + --background: url('/resources/images/background.svg'); + --background-color: rgba(51, 51, 51, 1.0); + + --circle-button-color: rgba(255, 255, 255, 0.3); + --circle-button-toggled-color: rgba(255, 255, 255, 0.7); + --circle-button-unsupported-color: rgba(212, 34, 65, 0.7); + --circle-button-diabled-color: rgba(255, 255, 255, 0.5); + --circle-button-size: 2.5em; + + --media-control-button-color: rgba(255, 255, 255, 0.85); + --media-control-botton-on: rgba(255, 255, 255, 0.7); + --media-control-botton-off: rgba(212, 34, 65, 0.7); + --media-control-botton-disabled: rgba(255, 255, 255, 0.5) + --media-control-button-size: 1.5em; + + --me-shadow: 0px 5px 12px 2px rgba(17, 17, 17, 0.5); + --me-border: 1px solid rgba(255, 255, 255, 0.15); + --me-width: 20vmin; + --me-height: 15vmin; + + --peer-shadow: 0px 5px 12px 2px rgba(17, 17, 17, 0.5); + --peer-border: 1px solid rgba(255, 255, 255, 0.15); + --peer-empty-avatar: url('/resources/images/buddy.svg'); + --peer-bg-color: rgba(42, 75, 88, 0.9); + --peer-video-bg-color: rgba(0, 0, 0, 0.75); + + --chat-message-color: rgba(0, 0, 0, 0.1); + --chat-input-bg-color: rgba(255, 255, 255, 1.0); + --chat-input-text-color: rgba(0, 0, 0, 1.0); + --chat-send-bg-color: rgba(170, 238, 255, 1.0); + + --filesharing-bg-color: rgba(170, 238, 255, 1.0); + + --notification-info-bg-color: rgba(10, 29, 38, 0.75); + --notification-info-text-color: rgba(255, 255, 255, 0.65); + --notification-error-bg-color: rgba(255, 25, 20, 0.65); + --notification-error-text-color: rgba(255, 255, 255, 0.85); + + --active-speaker-border-color: rgba(255, 255, 255, 1.0); + --selected-peer-border-color: rgba(55, 126, 255, 1.0); +} + html { height: 100%; font-family: 'Roboto'; @@ -23,11 +70,11 @@ body { height: 100%; overflow-x: hidden; overflow-y: hidden; - background-color: #333; + background-color: var(--background-color); +desktop() { font-size: 16px; - background-image: url('/resources/images/background.svg'); + background-image: var(--background); background-attachment: fixed; background-position: center; background-size: cover; @@ -48,11 +95,10 @@ body { @import './components/Peers'; @import './components/Peer'; @import './components/PeerView'; -@import './components/HiddenPeersView'; +@import './components/HiddenPeers'; @import './components/ScreenView'; @import './components/Notifications'; @import './components/Chat'; -@import './components/Settings'; @import './components/ToolArea'; @import './components/ParticipantList'; @import './components/FullScreenView'; diff --git a/app/test/DATA.js b/app/test/DATA.js deleted file mode 100644 index 350584c..0000000 --- a/app/test/DATA.js +++ /dev/null @@ -1,401 +0,0 @@ -/* eslint-disable key-spacing */ - -exports.ROOM_OPTIONS = -{ - requestTimeout: 10000, - transportOptions: - { - tcp: false - }, - __turnServers: - [ - { - urls: [ 'turn:worker2.versatica.com:3478?transport=udp' ], - username: 'testuser1', - credential: 'testpasswd1' - } - ], - hidden: false -}; - -exports.ROOM_RTP_CAPABILITIES = -{ - codecs: - [ - { - name: 'PCMA', - mimeType: 'audio/PCMA', - kind: 'audio', - clockRate: 8000, - preferredPayloadType: 8, - rtcpFeedback: [], - parameters: {} - }, - { - name: 'opus', - mimeType: 'audio/opus', - kind: 'audio', - clockRate: 48000, - channels: 2, - preferredPayloadType: 96, - rtcpFeedback: [], - parameters: {} - }, - { - name: 'SILK', - mimeType: 'audio/SILK', - kind: 'audio', - clockRate: 16000, - preferredPayloadType: 97, - rtcpFeedback: [], - parameters: {} - }, - { - name: 'VP9', - mimeType: 'video/VP9', - kind: 'video', - clockRate: 90000, - preferredPayloadType: 102, - rtcpFeedback: - [ - { - parameter: '', - type: 'nack' - }, - { - parameter: 'pli', - type: 'nack' - }, - { - parameter: '', - type: 'goog-remb' - }, - { - parameter: 'bar', - type: 'foo' - } - ], - parameters: {} - }, - { - name: 'rtx', - mimeType: 'video/rtx', - kind: 'video', - clockRate: 90000, - preferredPayloadType: 103, - rtcpFeedback: [], - parameters: { - apt: 102 - } - }, - { - name: 'VP8', - mimeType: 'video/VP8', - kind: 'video', - clockRate: 90000, - preferredPayloadType: 100, - rtcpFeedback: - [ - { - parameter: '', - type: 'nack' - }, - { - parameter: 'pli', - type: 'nack' - }, - { - parameter: '', - type: 'goog-remb' - }, - { - parameter: 'bar', - type: 'foo' - } - ], - parameters: {} - }, - { - name: 'rtx', - mimeType: 'video/rtx', - kind: 'video', - clockRate: 90000, - preferredPayloadType: 101, - rtcpFeedback: [], - parameters: { - apt: 100 - } - } - ], - headerExtensions: [ - { - kind: 'audio', - uri: 'urn:ietf:params:rtp-hdrext:ssrc-audio-level', - preferredId: 10 - }, - { - kind: 'video', - uri: 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', - preferredId: 11 - }, - { - kind: 'video', - uri: 'http://foo.bar', - preferredId: 12 - } - ], - fecMechanisms: [] -}; - -exports.QUERY_ROOM_RESPONSE = -{ - rtpCapabilities: exports.ROOM_RTP_CAPABILITIES -}; - -exports.JOIN_ROOM_RESPONSE = -{ - peers: - [ - { - name: 'alice', - appData: 'Alice iPad Pro', - consumers: - [ - { - id: 3333, - kind: 'audio', - paused: false, - appData: 'ALICE_MIC', - rtpParameters: - { - muxId: null, - codecs: - [ - { - name: 'PCMA', - mimeType: 'audio/PCMA', - clockRate: 8000, - payloadType: 8, - rtcpFeedback: [], - parameters: {} - } - ], - headerExtensions: - [ - { - uri: 'urn:ietf:params:rtp-hdrext:ssrc-audio-level', - id: 1 - } - ], - encodings: - [ - { - ssrc: 33333333 - } - ], - rtcp: - { - cname: 'ALICECNAME', - reducedSize: true, - mux: true - } - } - } - ] - }, - { - name: 'bob', - appData: 'Bob HP Laptop', - consumers: - [ - { - id: 6666, - kind: 'audio', - paused: false, - appData: 'BOB_MIC', - rtpParameters: - { - muxId: null, - codecs: - [ - { - name: 'opus', - mimeType: 'audio/opus', - clockRate: 48000, - channels: 2, - payloadType: 96, - rtcpFeedback: [], - parameters: {} - } - ], - headerExtensions: - [ - { - uri: 'urn:ietf:params:rtp-hdrext:ssrc-audio-level', - id: 1 - } - ], - encodings: - [ - { - ssrc: 66666666 - } - ], - rtcp: - { - cname: 'BOBCNAME', - reducedSize: true, - mux: true - } - } - } - ] - } - ] -}; - -exports.CREATE_TRANSPORT_1_RESPONSE = -{ - iceParameters: - { - usernameFragment: 'server-usernamefragment-12345678', - password: 'server-password-xxxxxxxx', - iceLite: true - }, - iceCandidates: - [ - { - foundation: 'F1', - priority: 1234, - ip: '1.2.3.4', - protocol: 'udp', - port: 9999, - type: 'host' - } - ], - dtlsParameters: - { - fingerprints: - [ - { - algorithm: 'sha-256', - value: 'FF:FF:39:66:A4:E2:66:60:30:18:A7:59:B3:AF:A5:33:58:5E:7F:69:A4:62:A6:D4:EB:9F:B7:42:05:35:FF:FF' - } - ], - role: 'client' - } -}; - -exports.CREATE_TRANSPORT_2_RESPONSE = -{ - iceParameters: - { - usernameFragment: 'server-usernamefragment-12345678', - password: 'server-password-xxxxxxxx', - iceLite: true - }, - iceCandidates: - [ - { - foundation: 'F1', - priority: 1234, - ip: '1.2.3.4', - protocol: 'udp', - port: 9999, - type: 'host' - } - ], - dtlsParameters: - { - fingerprints: - [ - { - algorithm: 'sha-256', - value: 'FF:FF:39:66:A4:E2:66:60:30:18:A7:59:B3:AF:A5:33:58:5E:7F:69:A4:62:A6:D4:EB:9F:B7:42:05:35:FF:FF' - } - ], - role: 'auto' - } -}; - -exports.ALICE_WEBCAM_NEW_CONSUMER_NOTIFICATION = -{ - method: 'newConsumer', - notification: true, - id: 4444, - peerName: 'alice', - kind: 'video', - paused: true, - appData: 'ALICE_WEBCAM', - rtpParameters: - { - muxId: null, - codecs: - [ - { - name: 'VP8', - mimeType: 'video/VP8', - clockRate: 90000, - payloadType: 100, - rtcpFeedback: - [ - { - parameter: '', - type: 'nack' - }, - { - parameter: 'pli', - type: 'nack' - }, - { - parameter: '', - type: 'goog-remb' - }, - { - parameter: 'bar', - type: 'foo' - } - ], - parameters: {} - }, - { - name: 'rtx', - mimeType: 'video/rtx', - clockRate: 90000, - payloadType: 101, - rtcpFeedback: [], - parameters: { - apt: 100 - } - } - ], - headerExtensions: - [ - { - kind: 'video', - uri: 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', - id: 11 - }, - { - kind: 'video', - uri: 'http://foo.bar', - id: 12 - } - ], - encodings: - [ - { - ssrc: 444444441, - rtx: { - ssrc: 444444442 - } - } - ], - rtcp: - { - cname: 'ALICECNAME', - reducedSize: true, - mux: true - } - } -}; diff --git a/app/test/gulpfile.js b/app/test/gulpfile.js deleted file mode 100644 index fdeca18..0000000 --- a/app/test/gulpfile.js +++ /dev/null @@ -1,145 +0,0 @@ -const path = require('path'); -const gulp = require('gulp'); -const gutil = require('gulp-util'); -const plumber = require('gulp-plumber'); -const rename = require('gulp-rename'); -const browserify = require('browserify'); -const watchify = require('watchify'); -const envify = require('envify/custom'); -const source = require('vinyl-source-stream'); -const buffer = require('vinyl-buffer'); -const eslint = require('gulp-eslint'); -const browserSync = require('browser-sync'); - -const OUTPUT_DIR = 'output'; -const APP_NAME = 'mediasoup-client-test'; - -// Node environment. -process.env.NODE_ENV = 'development'; - -function logError(error) -{ - gutil.log(gutil.colors.red(error.stack)); -} - -gulp.task('lint', () => -{ - const src = - [ - 'gulpfile.js', - '**/*.js', - '**/*.jsx' - ]; - - return gulp.src(src) - .pipe(plumber()) - .pipe(eslint()) - .pipe(eslint.format()); -}); - -gulp.task('html', () => -{ - return gulp.src('index.html') - .pipe(gulp.dest(OUTPUT_DIR)); -}); - -gulp.task('bundle', () => -{ - const watch = true; - - let bundler = browserify( - { - entries : 'index.jsx', - extensions : [ '.js', '.jsx' ], - // required for sourcemaps (must be false otherwise). - debug : process.env.NODE_ENV === 'development', - // required for watchify. - cache : {}, - // required for watchify. - packageCache : {}, - // required to be true only for watchify. - fullPaths : watch - }) - .transform('babelify', - { - presets : [ 'es2015', 'es2017', 'react' ], - plugins : - [ - 'transform-runtime', - 'transform-object-assign', - 'transform-object-rest-spread' - ] - }) - .transform(envify( - { - NODE_ENV : process.env.NODE_ENV, - _ : 'purge' - })); - - if (watch) - { - bundler = watchify(bundler); - - bundler.on('update', () => - { - const start = Date.now(); - - gutil.log('bundling...'); - rebundle(); - gutil.log('bundle took %sms', (Date.now() - start)); - }); - } - - function rebundle() - { - return bundler.bundle() - .on('error', logError) - .pipe(plumber()) - .pipe(source(`${APP_NAME}.js`)) - .pipe(buffer()) - .pipe(rename(`${APP_NAME}.js`)) - .pipe(gulp.dest(OUTPUT_DIR)); - } - - return rebundle(); -}); - -gulp.task('livebrowser', (done) => -{ - browserSync( - { - server : - { - baseDir : OUTPUT_DIR - }, - ghostMode : false, - files : path.join(OUTPUT_DIR, '**', '*') - }); - - done(); -}); - -gulp.task('watch', (done) => -{ - // Watch changes in HTML. - gulp.watch([ 'index.html' ], gulp.series( - 'html' - )); - - // Watch changes in JS files. - gulp.watch([ 'gulpfile.js', '**/*.js', '**/*.jsx' ], gulp.series( - 'lint' - )); - - done(); -}); - -gulp.task('live', gulp.series( - 'lint', - 'html', - 'bundle', - 'watch', - 'livebrowser' -)); - -gulp.task('default', gulp.series('live')); diff --git a/app/test/index.html b/app/test/index.html deleted file mode 100644 index 7fba1d4..0000000 --- a/app/test/index.html +++ /dev/null @@ -1,16 +0,0 @@ - - - - - mediasoup-client test - - - - - - - - -

mediasoup-client test

- - diff --git a/app/test/index.jsx b/app/test/index.jsx deleted file mode 100644 index 93e46c8..0000000 --- a/app/test/index.jsx +++ /dev/null @@ -1,692 +0,0 @@ -import * as mediasoupClient from 'mediasoup-client'; -import domready from 'domready'; -import Logger from '../lib/Logger'; -const DATA = require('./DATA'); - -window.mediasoupClient = mediasoupClient; - -const logger = new Logger(); - - -const SEND = true; -const SEND_AUDIO = true; -const SEND_VIDEO = false; -const RECV = true; - - -domready(() => -{ - logger.debug('DOM ready'); - - run(); -}); - -function run() -{ - logger.debug('run() [environment:%s]', process.env.NODE_ENV); - - let transport1; - let transport2; - let audioTrack; - let videoTrack; - let audioProducer1; - let audioProducer2; - let videoProducer; - - logger.debug('calling room = new mediasoupClient.Room()'); - - // const room = new mediasoupClient.Room(); - const room = new mediasoupClient.Room(DATA.ROOM_OPTIONS); - - window.room = room; - - room.on('closed', (originator, appData) => - { - logger.warn( - 'room "closed" event [originator:%s, appData:%o]', originator, appData); - }); - - room.on('request', (request, callback, errback) => - { - logger.warn('sending request [method:%s]:%o', request.method, request); - - switch (request.method) - { - case 'queryRoom': - { - setTimeout(() => - { - callback(DATA.QUERY_ROOM_RESPONSE); - errback('upppps'); - }, 200); - break; - } - - case 'joinRoom': - { - setTimeout(() => - { - callback(DATA.JOIN_ROOM_RESPONSE); - // errback('upppps'); - }, 200); - break; - } - - case 'createTransport': - { - setTimeout(() => - { - switch (request.appData) - { - case 'TRANSPORT_1': - callback(DATA.CREATE_TRANSPORT_1_RESPONSE); - break; - case 'TRANSPORT_2': - callback(DATA.CREATE_TRANSPORT_2_RESPONSE); - break; - default: - errback('upppps'); - } - }, 250); - break; - } - - case 'createProducer': - { - setTimeout(() => - { - callback(); - }, 250); - break; - } - - case 'enableConsumer': - { - setTimeout(() => - { - callback(); - }, 500); - break; - } - - default: - errback(`NO IDEA ABOUT REQUEST METHOD "${request.method}"`); - } - }); - - room.on('notify', (notification) => - { - logger.warn( - 'sending notification [method:%s]:%o', notification.method, notification); - - switch (notification.method) - { - case 'leaveRoom': - case 'updateTransport': - case 'closeTransport': - case 'closeProducer': - case 'pauseProducer': - case 'resumeProducer': - case 'pauseConsumer': - case 'resumeConsumer': - break; - - default: - logger.error(`NO IDEA ABOUT NOTIFICATION METHOD "${notification.method}"`); - } - }); - - room.on('newpeer', (peer) => - { - logger.warn('room "newpeer" event [name:"%s", peer:%o]', peer.name, peer); - - handlePeer(peer); - }); - - Promise.resolve() - .then(() => - { - logger.debug('calling room.join()'); - - const deviceInfo = mediasoupClient.getDeviceInfo(); - const appData = - { - device : `${deviceInfo.name} ${deviceInfo.version}` - }; - - return room.join(null, appData); - // return room.join(DATA.ROOM_RTP_CAPABILITIES, appData); - }) - .then((peers) => - { - if (!RECV) - return; - - logger.debug('room.join() succeeded'); - - logger.debug('calling transport2 = room.createTransport("recv")'); - - transport2 = room.createTransport('recv', 'TRANSPORT_2'); - window.transport2 = transport2; - window.pc2 = transport2._handler._pc; - - handleTransport(transport2); - - for (const peer of peers) - { - handlePeer(peer); - } - }) - .then(() => - { - if (!SEND) - return; - - if (room.canSend('audio')) - logger.debug('can send audio'); - else - logger.warn('cannot send audio'); - - if (room.canSend('video')) - logger.debug('can send video'); - else - logger.warn('cannot send video'); - - logger.debug('calling transport1 = room.createTransport("send")'); - - transport1 = room.createTransport('send', 'TRANSPORT_1'); - window.transport1 = transport1; - window.pc1 = transport1._handler._pc; - - handleTransport(transport1); - - logger.debug('calling getUserMedia()'); - - return navigator.mediaDevices - .getUserMedia({ audio: SEND_AUDIO, video: SEND_VIDEO }); - }) - .then((stream) => - { - if (!SEND) - return; - - audioTrack = stream.getAudioTracks()[0]; - videoTrack = stream.getVideoTracks()[0]; - window.audioTrack = audioTrack; - window.videoTrack = videoTrack; - }) - // Add Producers. - .then(() => - { - if (audioTrack) - { - const deviceId = audioTrack.getSettings().deviceId; - - logger.debug('calling audioProducer1 = room.createProducer(audioTrack)'); - - try - { - audioProducer1 = room.createProducer(audioTrack, `${deviceId}-1`); - window.audioProducer1 = audioProducer1; - - handleProducer(audioProducer1); - } - catch (error) - { - logger.error(error); - } - - logger.debug('calling audioProducer2 = room.createProducer(audioTrack)'); - - try - { - audioProducer2 = room.createProducer(audioTrack, `${deviceId}-2`); - window.audioProducer2 = audioProducer2; - - handleProducer(audioProducer2); - } - catch (error) - { - logger.error(error); - } - } - - if (videoTrack) - { - const deviceId = videoTrack.getSettings().deviceId; - - logger.debug('calling videoProducer = room.createProducer(videoTrack)'); - - try - { - videoProducer = room.createProducer(videoTrack, `${deviceId}-1`); - window.videoProducer = videoProducer; - - handleProducer(videoProducer); - } - catch (error) - { - logger.error(error); - } - } - }) - // Receive notifications. - .then(() => - { - if (!RECV) - return; - - setTimeout(() => - { - room.receiveNotification(DATA.ALICE_WEBCAM_NEW_CONSUMER_NOTIFICATION); - }, 2000); - }); -} - -function handleTransport(transport) -{ - logger.warn( - 'handleTransport() [direction:%s, appData:"%s", transport:%o]', - transport.direction, transport.appData, transport); - - transport.on('closed', (originator, appData) => - { - logger.warn( - 'transport "closed" event [originator:%s, appData:%o, transport:%o]', - originator, appData, transport); - }); - - transport.on('connectionstatechange', (state) => - { - logger.warn( - 'transport "connectionstatechange" event [direction:%s, state:%s, transport:%o]', - transport.direction, state, transport); - }); - - setInterval(() => - { - const queue = transport._commandQueue._queue; - - if (queue.length !== 0) - logger.error('queue not empty [transport:%o, queue:%o]', transport, queue); - }, 15000); -} - -function handlePeer(peer) -{ - logger.warn('handlePeer() [name:"%s", peer:%o]', peer.name, peer); - - switch (peer.name) - { - case 'alice': - window.alice = peer; - break; - case 'bob': - window.bob = peer; - break; - } - - for (const consumer of peer.consumers) - { - handleConsumer(consumer); - } - - peer.on('closed', (originator, appData) => - { - logger.warn( - 'peer "closed" event [name:"%s", originator:%s, appData:%o]', - peer.name, originator, appData); - }); - - peer.on('newconsumer', (consumer) => - { - logger.warn( - 'peer "newconsumer" event [name:"%s", id:%s, consumer:%o]', - peer.name, consumer.id, consumer); - - handleConsumer(consumer); - }); -} - -function handleProducer(producer) -{ - const transport1 = window.transport1; - - logger.debug( - 'handleProducer() [id:"%s", appData:%o, producer:%o]', - producer.id, producer.appData, producer); - - logger.debug('handleProducer() | calling transport1.send(producer)'); - - transport1.send(producer) - .then(() => - { - logger.debug('transport1.send(producer) succeeded'); - }) - .catch((error) => - { - logger.error('transport1.send(producer) failed: %o', error); - }); - - producer.on('closed', (originator, appData) => - { - logger.warn( - 'producer "closed" event [id:%s, originator:%s, appData:%o, producer:%o]', - producer.id, originator, appData, producer); - }); - - producer.on('paused', (originator, appData) => - { - logger.warn( - 'producer "paused" event [id:%s, originator:%s, appData:%o, producer:%o]', - producer.id, originator, appData, producer); - }); - - producer.on('resumed', (originator, appData) => - { - logger.warn( - 'producer "resumed" event [id:%s, originator:%s, appData:%o, producer:%o]', - producer.id, originator, appData, producer); - }); - - producer.on('unhandled', () => - { - logger.warn( - 'producer "unhandled" event [id:%s, producer:%o]', producer.id, producer); - }); -} - -function handleConsumer(consumer) -{ - const transport2 = window.transport2; - - logger.debug( - 'handleConsumer() [id:"%s", appData:%o, consumer:%o]', - consumer.id, consumer.appData, consumer); - - switch (consumer.appData) - { - case 'ALICE_MIC': - window.aliceAudioConsumer = consumer; - break; - case 'ALICE_WEBCAM': - window.aliceVideoConsumer = consumer; - break; - case 'BOB_MIC': - window.bobAudioConsumer = consumer; - break; - } - - logger.debug('handleConsumer() calling transport2.receive(consumer)'); - - transport2.receive(consumer) - .then((track) => - { - logger.warn( - 'transport2.receive(consumer) succeeded [track:%o]', track); - }) - .catch((error) => - { - logger.error('transport2.receive() failed:%o', error); - }); - - consumer.on('closed', (originator, appData) => - { - logger.warn( - 'consumer "closed" event [id:%s, originator:%s, appData:%o, consumer:%o]', - consumer.id, originator, appData, consumer); - }); - - consumer.on('paused', (originator, appData) => - { - logger.warn( - 'consumer "paused" event [id:%s, originator:%s, appData:%o, consumer:%o]', - consumer.id, originator, appData, consumer); - }); - - consumer.on('resumed', (originator, appData) => - { - logger.warn( - 'consumer "resumed" event [id:%s, originator:%s, appData:%o, consumer:%o]', - consumer.id, originator, appData, consumer); - }); - - consumer.on('unhandled', () => - { - logger.warn( - 'consumer "unhandled" event [id:%s, consumer:%o]', consumer.id, consumer); - }); -} - - -// NOTE: Trigger server notifications. - -window.notifyRoomClosed = function() -{ - const room = window.room; - const notification = - { - method : 'roomClosed', - notification : true, - appData : 'ha cascao la room remota!!!' - }; - - room.receiveNotification(notification); -}; - -window.notifyTransportClosed = function() -{ - const room = window.room; - const notification = - { - method : 'transportClosed', - notification : true, - id : room.transports[0].id, - appData : 'admin closed your transport' - }; - - room.receiveNotification(notification); -}; - -window.notifyAudioProducer1Closed = function() -{ - const room = window.room; - const notification = - { - method : 'producerClosed', - notification : true, - id : window.audioProducer1.id, - appData : 'te paro el micro por la fuerza' - }; - - room.receiveNotification(notification); -}; - -window.notifyAudioProducer1Paused = function() -{ - const room = window.room; - const notification = - { - method : 'producerPaused', - notification : true, - id : window.audioProducer1.id, - appData : 'te pause el micro por la fuerza' - }; - - room.receiveNotification(notification); -}; - -window.notifyAudioProducer1Resumed = function() -{ - const room = window.room; - const notification = - { - method : 'producerResumed', - notification : true, - id : window.audioProducer1.id, - appData : 'te resumo el micro' - }; - - room.receiveNotification(notification); -}; - -window.notifyAlicePeerClosed = function() -{ - const room = window.room; - const notification = - { - method : 'peerClosed', - notification : true, - name : 'alice', - appData : 'peer left' - }; - - room.receiveNotification(notification); -}; - -window.notifyAliceAudioConsumerClosed = function() -{ - const room = window.room; - const notification = - { - method : 'consumerClosed', - notification : true, - peerName : 'alice', - id : 3333, - appData : 'mic broken' - }; - - room.receiveNotification(notification); -}; - -window.notifyAliceVideoConsumerClosed = function() -{ - const room = window.room; - const notification = - { - method : 'consumerClosed', - notification : true, - peerName : 'alice', - id : 4444, - appData : 'webcam broken' - }; - - room.receiveNotification(notification); -}; - -window.notifyAliceVideoConsumerPaused = function() -{ - const room = window.room; - const notification = - { - method : 'consumerPaused', - notification : true, - peerName : 'alice', - id : 4444, - appData : 'webcam paused' - }; - - room.receiveNotification(notification); -}; - -window.notifyAliceVideoConsumerResumed = function() -{ - const room = window.room; - const notification = - { - method : 'consumerResumed', - notification : true, - peerName : 'alice', - id : 4444, - appData : 'webcam resumed' - }; - - room.receiveNotification(notification); -}; - - -// NOTE: Test pause/resume. - -window.testPauseResume = function() -{ - logger.debug('testPauseResume() with audioProducer1'); - - const producer = window.audioProducer1; - - // producer.once('paused', () => - // { - // producer.resume('I RESUME TO FUACK!!!'); - // }); - - logger.debug('testPauseResume() | (1) calling producer.pause()'); - - if (producer.pause('I PAUSE (1)')) - { - logger.warn( - 'testPauseResume() | (1) producer.pause() succeeded [locallyPaused:%s]', - producer.locallyPaused); - } - else - { - logger.error( - 'testPauseResume() | (1) producer.pause() failed [locallyPaused:%s]', - producer.locallyPaused); - } - - logger.debug('testPauseResume() | (2) calling producer.pause()'); - - if (producer.pause('I PAUSE (2)')) - { - logger.warn( - 'testPauseResume() | (2) producer.pause() succeeded [locallyPaused:%s]', - producer.locallyPaused); - } - else - { - logger.error( - 'testPauseResume() | (2) producer.pause() failed [locallyPaused:%s]', - producer.locallyPaused); - } - - logger.debug('testPauseResume() | (3) calling producer.resume()'); - - if (producer.resume('I RESUME (3)')) - { - logger.warn( - 'testPauseResume() | (3) producer.resume() succeeded [locallyPaused:%s]', - producer.locallyPaused); - } - else - { - logger.error( - 'testPauseResume() | (3) producer.resume() failed [locallyPaused:%s]', - producer.locallyPaused); - } -}; - - -// NOTE: For debugging. - -window.dump1 = function() -{ - const transport1 = window.transport1; - const pc1 = transport1._handler._pc; - - if (pc1 && pc1.localDescription) - logger.warn('PC1 SEND LOCAL OFFER:\n%s', pc1.localDescription.sdp); - - if (pc1 && pc1.remoteDescription) - logger.warn('PC1 SEND REMOTE ANSWER:\n%s', pc1.remoteDescription.sdp); -}; - -window.dump2 = function() -{ - const transport2 = window.transport2; - const pc2 = transport2._handler._pc; - - if (pc2 && pc2.remoteDescription) - logger.warn('PC2 RECV REMOTE OFFER:\n%s', pc2.remoteDescription.sdp); - - if (pc2 && pc2.localDescription) - logger.warn('PC2 RECV LOCAL ANSWER:\n%s', pc2.localDescription.sdp); -}; diff --git a/app/test/output/index.html b/app/test/output/index.html deleted file mode 100644 index 7fba1d4..0000000 --- a/app/test/output/index.html +++ /dev/null @@ -1,16 +0,0 @@ - - - - - mediasoup-client test - - - - - - - - -

mediasoup-client test

- - diff --git a/app/test/output/mediasoup-client-test.js b/app/test/output/mediasoup-client-test.js deleted file mode 100644 index d50e1fb..0000000 --- a/app/test/output/mediasoup-client-test.js +++ /dev/null @@ -1,14243 +0,0 @@ -(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o} - _this._queue = []; - return _this; - } - - (0, _createClass3.default)(CommandQueue, [{ - key: 'close', - value: function close() { - this._closed = true; - } - }, { - key: 'push', - value: function push(method, data) { - var _this2 = this; - - var command = (0, _extends3.default)({ method: method }, data); - - logger.debug('push() [method:%s]', method); - - return new _promise2.default(function (resolve, reject) { - var queue = _this2._queue; - - command.resolve = resolve; - command.reject = reject; - - // Append command to the queue. - queue.push(command); - _this2._handlePendingCommands(); - }); - } - }, { - key: '_handlePendingCommands', - value: function _handlePendingCommands() { - var _this3 = this; - - if (this._busy) return; - - var queue = this._queue; - - // Take the first command. - var command = queue[0]; - - if (!command) return; - - this._busy = true; - - // Execute it. - this._handleCommand(command).then(function () { - _this3._busy = false; - - // Remove the first command (the completed one) from the queue. - queue.shift(); - - // And continue. - _this3._handlePendingCommands(); - }); - } - }, { - key: '_handleCommand', - value: function _handleCommand(command) { - var _this4 = this; - - logger.debug('_handleCommand() [method:%s]', command.method); - - if (this._closed) { - command.reject(new _errors.InvalidStateError('closed')); - - return _promise2.default.resolve(); - } - - var promiseHolder = { promise: null }; - - this.emit('exec', command, promiseHolder); - - return _promise2.default.resolve().then(function () { - return promiseHolder.promise; - }).then(function (result) { - logger.debug('_handleCommand() | command succeeded [method:%s]', command.method); - - if (_this4._closed) { - command.reject(new _errors.InvalidStateError('closed')); - - return; - } - - // Resolve the command with the given result (if any). - command.resolve(result); - }).catch(function (error) { - logger.error('_handleCommand() | command failed [method:%s]: %o', command.method, error); - - // Reject the command with the error. - command.reject(error); - }); - } - }]); - return CommandQueue; -}(_events.EventEmitter); - -exports.default = CommandQueue; - -},{"./Logger":"/Users/ibc/src/mediasoup-client/lib/Logger.js","./errors":"/Users/ibc/src/mediasoup-client/lib/errors.js","babel-runtime/core-js/object/get-prototype-of":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/core-js/object/get-prototype-of.js","babel-runtime/core-js/promise":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/core-js/promise.js","babel-runtime/helpers/classCallCheck":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/helpers/classCallCheck.js","babel-runtime/helpers/createClass":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/helpers/createClass.js","babel-runtime/helpers/extends":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/helpers/extends.js","babel-runtime/helpers/inherits":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/helpers/inherits.js","babel-runtime/helpers/possibleConstructorReturn":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/helpers/possibleConstructorReturn.js","events":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/events/events.js"}],"/Users/ibc/src/mediasoup-client/lib/Consumer.js":[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); - -var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); - -var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); - -var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); - -var _createClass2 = require('babel-runtime/helpers/createClass'); - -var _createClass3 = _interopRequireDefault(_createClass2); - -var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); - -var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); - -var _inherits2 = require('babel-runtime/helpers/inherits'); - -var _inherits3 = _interopRequireDefault(_inherits2); - -var _Logger = require('./Logger'); - -var _Logger2 = _interopRequireDefault(_Logger); - -var _EnhancedEventEmitter2 = require('./EnhancedEventEmitter'); - -var _EnhancedEventEmitter3 = _interopRequireDefault(_EnhancedEventEmitter2); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -var logger = new _Logger2.default('Consumer'); - -var Consumer = function (_EnhancedEventEmitter) { - (0, _inherits3.default)(Consumer, _EnhancedEventEmitter); - - /** - * @private - * - * @emits {originator: String, [appData]: Any} paused - * @emits {originator: String, [appData]: Any} resumed - * @emits unhandled - * @emits {originator: String, [appData]: Any} closed - * - * @emits {[appData]: Any} @pause - * @emits {[appData]: Any} @resume - * @emits {originator: String} @close - */ - function Consumer(id, kind, rtpParameters, peer, appData) { - (0, _classCallCheck3.default)(this, Consumer); - - // Id. - // @type {Number} - var _this = (0, _possibleConstructorReturn3.default)(this, (Consumer.__proto__ || (0, _getPrototypeOf2.default)(Consumer)).call(this)); - - _this._id = id; - - // Closed flag. - // @type {Boolean} - _this._closed = false; - - // Media kind. - // @type {String} - _this._kind = kind; - - // RTP parameters. - // @type {RTCRtpParameters} - _this._rtpParameters = rtpParameters; - - // Associated Peer. - // @type {Peer} - _this._peer = peer; - - // App custom data. - // @type {Any} - _this._appData = appData; - - // Whether we can receive this Consumer (based on our RTP capabilities). - // @type {Boolean} - _this._supported = false; - - // Whether this Consumer is being handled by a Transport. - // @type {Boolean} - _this._handled = false; - - // Remote track. - // @type {MediaStreamTrack} - _this._track = null; - - // Locally paused flag. - // @type {Boolean} - _this._locallyPaused = false; - - // Remotely paused flag. - // @type {Boolean} - _this._remotelyPaused = false; - return _this; - } - - /** - * Class name. - * - * @return {String} - */ - - - (0, _createClass3.default)(Consumer, [{ - key: 'close', - - - /** - * Closes the Consumer. - * This is called when the local Room is closed. - * - * @private - */ - value: function close() { - logger.debug('close()'); - - if (this._closed) return; - - this._closed = true; - - this.emit('@close', 'local'); - this.safeEmit('closed', 'local'); - - this._destroy(); - } - - /** - * My remote Consumer was closed. - * Invoked via remote notification. - * - * @private - * - * @param {Any} [appData] - App custom data. - */ - - }, { - key: 'remoteClose', - value: function remoteClose(appData) { - logger.debug('remoteClose()'); - - if (this._closed) return; - - this._closed = true; - - this.emit('@close', 'remote'); - this.safeEmit('closed', 'remote', appData); - - this._destroy(); - } - }, { - key: '_destroy', - value: function _destroy() { - this._handled = false; - - try { - this._track.stop(); - } catch (error) {} - - this._track = null; - } - - /** - * Pauses receiving media. - * - * @param {Any} [appData] - App custom data. - * - * @return {Boolean} true if paused. - */ - - }, { - key: 'pause', - value: function pause(appData) { - logger.debug('pause()'); - - if (this._closed) { - logger.error('pause() | Consumer closed'); - - return false; - } else if (!this._handled) { - logger.error('pause() | Consumer not handled'); - - return false; - } else if (this._locallyPaused) { - return true; - } - - this._locallyPaused = true; - this._track.enabled = false; - - this.emit('@pause', appData); - - if (!this._remotelyPaused) this.safeEmit('paused', 'local', appData); - - // Return true if really paused. - return this.paused; - } - - /** - * My remote Consumer was paused. - * Invoked via remote notification. - * - * @private - * - * @param {Any} [appData] - App custom data. - */ - - }, { - key: 'remotePause', - value: function remotePause(appData) { - logger.debug('remotePause()'); - - if (this._closed || this._remotelyPaused) return; - - this._remotelyPaused = true; - - if (this._track) this._track.enabled = false; - - if (!this._locallyPaused) this.safeEmit('paused', 'remote', appData); - } - - /** - * Resumes receiving media. - * - * @param {Any} [appData] - App custom data. - * - * @return {Boolean} true if not paused. - */ - - }, { - key: 'resume', - value: function resume(appData) { - logger.debug('resume()'); - - if (this._closed) { - logger.error('resume() | Consumer closed'); - - return false; - } else if (!this._handled) { - logger.error('pause() | Consumer not handled'); - - return false; - } else if (!this._locallyPaused) { - return true; - } - - this._locallyPaused = false; - - this.emit('@resume', appData); - - if (!this._remotelyPaused) { - this._track.enabled = true; - - this.safeEmit('resumed', 'local', appData); - } - - // Return true if not paused. - return !this.paused; - } - - /** - * My remote Consumer was resumed. - * Invoked via remote notification. - * - * @private - * - * @param {Any} [appData] - App custom data. - */ - - }, { - key: 'remoteResume', - value: function remoteResume(appData) { - logger.debug('remoteResume()'); - - if (this._closed || !this._remotelyPaused) return; - - this._remotelyPaused = false; - - if (!this._locallyPaused) { - if (this._track) this._track.enabled = false; - - this.safeEmit('resumed', 'remote', appData); - } - } - - /** - * Mark this Consumer as suitable for reception or not. - * - * @private - * - * @param {Boolean} flag - */ - - }, { - key: 'setSupported', - value: function setSupported(flag) { - this._supported = flag; - } - - /** - * Set this Consumer as handled or unhandled by a Transport. - * - * @private - * - * @param {Boolean|String} flag - If 'tmp' (String) it's considered as termporal. - * @param {track} MediaStreamTrack - */ - - }, { - key: 'setHandled', - value: function setHandled(flag, track) { - if (this._closed) return; - - var previous = this._handled; - - this._handled = flag; - this._track = track || null; - - if (track && this.paused) this._track.enabled = false; - - if (flag === false || flag === 'tmp') { - try { - this._track.stop(); - } catch (error) {} - - this._track = null; - } - - if (previous === true && flag === false) this.safeEmit('unhandled'); - } - }, { - key: 'klass', - get: function get() { - return 'Consumer'; - } - - /** - * Consumer id. - * - * @return {Number} - */ - - }, { - key: 'id', - get: function get() { - return this._id; - } - - /** - * Whether the Consumer is closed. - * - * @return {Boolean} - */ - - }, { - key: 'closed', - get: function get() { - return this._closed; - } - - /** - * Media kind. - * - * @return {String} - */ - - }, { - key: 'kind', - get: function get() { - return this._kind; - } - - /** - * RTP parameters. - * - * @return {RTCRtpParameters} - */ - - }, { - key: 'rtpParameters', - get: function get() { - return this._rtpParameters; - } - - /** - * Associated Peer. - * - * @return {Peer} - */ - - }, { - key: 'peer', - get: function get() { - return this._peer; - } - - /** - * App custom data. - * - * @return {Any} - */ - - }, { - key: 'appData', - get: function get() { - return this._appData; - } - - /** - * Whether we can receive this Consumer (based on our RTP capabilities). - * - * @return {Boolean} - */ - - }, { - key: 'supported', - get: function get() { - return this._supported; - } - - /** - * Whether this is being handled by a Transport. - * - * @return {Boolean} - */ - - }, { - key: 'handled', - get: function get() { - return Boolean(this._handled); - } - - /** - * The associated track (if any yet). - * - * @return {MediaStreamTrack|Null} - */ - - }, { - key: 'track', - get: function get() { - return this._track; - } - - /** - * Whether the Consumer is locally paused. - * - * @return {Boolean} - */ - - }, { - key: 'locallyPaused', - get: function get() { - return this._locallyPaused; - } - - /** - * Whether the Consumer is remotely paused. - * - * @return {Boolean} - */ - - }, { - key: 'remotelyPaused', - get: function get() { - return this._remotelyPaused; - } - - /** - * Whether the Consumer is paused. - * - * @return {Boolean} - */ - - }, { - key: 'paused', - get: function get() { - return this._locallyPaused || this._remotelyPaused; - } - - /** - * Whether the Consumer is actually receiving media. - * - * @return {Boolean} - */ - - }, { - key: 'active', - get: function get() { - return !this._closed && this.handled === true && !this.paused; - } - }]); - return Consumer; -}(_EnhancedEventEmitter3.default); - -exports.default = Consumer; - -},{"./EnhancedEventEmitter":"/Users/ibc/src/mediasoup-client/lib/EnhancedEventEmitter.js","./Logger":"/Users/ibc/src/mediasoup-client/lib/Logger.js","babel-runtime/core-js/object/get-prototype-of":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/core-js/object/get-prototype-of.js","babel-runtime/helpers/classCallCheck":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/helpers/classCallCheck.js","babel-runtime/helpers/createClass":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/helpers/createClass.js","babel-runtime/helpers/inherits":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/helpers/inherits.js","babel-runtime/helpers/possibleConstructorReturn":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/helpers/possibleConstructorReturn.js"}],"/Users/ibc/src/mediasoup-client/lib/Device.js":[function(require,module,exports){ -(function (global){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); - -var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); - -var _createClass2 = require('babel-runtime/helpers/createClass'); - -var _createClass3 = _interopRequireDefault(_createClass2); - -var _bowser = require('bowser'); - -var _bowser2 = _interopRequireDefault(_bowser); - -var _Logger = require('./Logger'); - -var _Logger2 = _interopRequireDefault(_Logger); - -var _Chrome = require('./handlers/Chrome55'); - -var _Chrome2 = _interopRequireDefault(_Chrome); - -var _Safari = require('./handlers/Safari11'); - -var _Safari2 = _interopRequireDefault(_Safari); - -var _Firefox = require('./handlers/Firefox50'); - -var _Firefox2 = _interopRequireDefault(_Firefox); - -var _Edge = require('./handlers/Edge11'); - -var _Edge2 = _interopRequireDefault(_Edge); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -var logger = new _Logger2.default('Device'); - -/** - * Class with static members representing the underlying device or browser. - */ - -var Device = function () { - function Device() { - (0, _classCallCheck3.default)(this, Device); - } - - (0, _createClass3.default)(Device, null, [{ - key: 'isSupported', - - - /** - * Whether this device is supported. - * - * @return {Boolean} - */ - value: function isSupported() { - if (!Device._detected) Device._detect(); - - return Boolean(Device._handlerClass); - } - - /** - * Returns a suitable WebRTC handler class. - * - * @type {Class} - */ - - }, { - key: '_detect', - - - /** - * Detects the current device/browser. - * - * @private - */ - value: function _detect() { - var ua = global.navigator.userAgent; - var browser = _bowser2.default._detect(ua); - - Device._detected = true; - Device._name = browser.name || 'unknown device'; - Device._version = browser.version || 'unknown vesion'; - Device._handlerClass = null; - - // Chrome, Chromium, Opera (desktop and mobile). - if (_bowser2.default.check({ chrome: '55', chromium: '55', opera: '44' }, true, ua)) { - Device._handlerClass = _Chrome2.default; - } - // Safari (desktop and mobile). - else if (_bowser2.default.check({ safari: '11' }, true, ua)) { - Device._handlerClass = _Safari2.default; - } - // Firefox (desktop and mobile). - else if (_bowser2.default.check({ firefox: '50' }, true, ua)) { - Device._handlerClass = _Firefox2.default; - } - // Edge (desktop). - else if (_bowser2.default.check({ msedge: '11' }, true, ua)) { - Device._handlerClass = _Edge2.default; - } - - // TODO: More devices. - - if (Device.isSupported()) { - logger.debug('device supported [name:%s, version:%s, handler:%s]', Device._name, Device._version, Device._handlerClass.name); - } else { - logger.warn('device not supported [name:%s, version:%s]', Device._name, Device._version); - } - } - }, { - key: 'name', - - /** - * Get the device name. - * - * @return {String} - */ - get: function get() { - if (!Device._detected) Device._detect(); - - return Device._name; - } - - /** - * Get the device version. - * - * @return {String} - */ - - }, { - key: 'version', - get: function get() { - if (!Device._detected) Device._detect(); - - return Device._version; - } - }, { - key: 'Handler', - get: function get() { - if (!Device._detected) Device._detect(); - - return Device._handlerClass; - } - }]); - return Device; -}(); - -// Initialized flag. -// @type {Boolean} - - -exports.default = Device; -Device._detected = false; - -// Device name. -// @type {String} -Device._name = undefined; - -// Device version. -// @type {String} -Device._version = undefined; - -// WebRTC hander for this device. -// @type {Class} -Device._handlerClass = null; - -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) - -},{"./Logger":"/Users/ibc/src/mediasoup-client/lib/Logger.js","./handlers/Chrome55":"/Users/ibc/src/mediasoup-client/lib/handlers/Chrome55.js","./handlers/Edge11":"/Users/ibc/src/mediasoup-client/lib/handlers/Edge11.js","./handlers/Firefox50":"/Users/ibc/src/mediasoup-client/lib/handlers/Firefox50.js","./handlers/Safari11":"/Users/ibc/src/mediasoup-client/lib/handlers/Safari11.js","babel-runtime/helpers/classCallCheck":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/helpers/classCallCheck.js","babel-runtime/helpers/createClass":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/helpers/createClass.js","bowser":"/Users/ibc/src/mediasoup-client/node_modules/bowser/src/bowser.js"}],"/Users/ibc/src/mediasoup-client/lib/EnhancedEventEmitter.js":[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _promise = require('babel-runtime/core-js/promise'); - -var _promise2 = _interopRequireDefault(_promise); - -var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); - -var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); - -var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); - -var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); - -var _createClass2 = require('babel-runtime/helpers/createClass'); - -var _createClass3 = _interopRequireDefault(_createClass2); - -var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); - -var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); - -var _inherits2 = require('babel-runtime/helpers/inherits'); - -var _inherits3 = _interopRequireDefault(_inherits2); - -var _events = require('events'); - -var _Logger = require('./Logger'); - -var _Logger2 = _interopRequireDefault(_Logger); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -var logger = new _Logger2.default('EnhancedEventEmitter'); - -var EnhancedEventEmitter = function (_EventEmitter) { - (0, _inherits3.default)(EnhancedEventEmitter, _EventEmitter); - - function EnhancedEventEmitter() { - (0, _classCallCheck3.default)(this, EnhancedEventEmitter); - - var _this = (0, _possibleConstructorReturn3.default)(this, (EnhancedEventEmitter.__proto__ || (0, _getPrototypeOf2.default)(EnhancedEventEmitter)).call(this)); - - _this.setMaxListeners(Infinity); - return _this; - } - - (0, _createClass3.default)(EnhancedEventEmitter, [{ - key: 'safeEmit', - value: function safeEmit(event) { - try { - for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { - args[_key - 1] = arguments[_key]; - } - - this.emit.apply(this, [event].concat(args)); - } catch (error) { - logger.error('event listener threw an error [event:%s]: %o', event, error); - } - } - }, { - key: 'safeEmitAsPromise', - value: function safeEmitAsPromise() { - var _this2 = this; - - for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { - args[_key2] = arguments[_key2]; - } - - return new _promise2.default(function (resolve, reject) { - var callback = function callback(result) { - resolve(result); - }; - - var errback = function errback(error) { - reject(error); - }; - - _this2.safeEmit.apply(_this2, args.concat([callback, errback])); - }); - } - }]); - return EnhancedEventEmitter; -}(_events.EventEmitter); - -exports.default = EnhancedEventEmitter; - -},{"./Logger":"/Users/ibc/src/mediasoup-client/lib/Logger.js","babel-runtime/core-js/object/get-prototype-of":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/core-js/object/get-prototype-of.js","babel-runtime/core-js/promise":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/core-js/promise.js","babel-runtime/helpers/classCallCheck":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/helpers/classCallCheck.js","babel-runtime/helpers/createClass":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/helpers/createClass.js","babel-runtime/helpers/inherits":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/helpers/inherits.js","babel-runtime/helpers/possibleConstructorReturn":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/helpers/possibleConstructorReturn.js","events":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/events/events.js"}],"/Users/ibc/src/mediasoup-client/lib/Logger.js":[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); - -var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); - -var _createClass2 = require('babel-runtime/helpers/createClass'); - -var _createClass3 = _interopRequireDefault(_createClass2); - -var _debug = require('debug'); - -var _debug2 = _interopRequireDefault(_debug); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -var APP_NAME = 'mediasoup-client'; - -var Logger = function () { - function Logger(prefix) { - (0, _classCallCheck3.default)(this, Logger); - - if (prefix) { - this._debug = (0, _debug2.default)(APP_NAME + ':' + prefix); - this._warn = (0, _debug2.default)(APP_NAME + ':WARN:' + prefix); - this._error = (0, _debug2.default)(APP_NAME + ':ERROR:' + prefix); - } else { - this._debug = (0, _debug2.default)(APP_NAME); - this._warn = (0, _debug2.default)(APP_NAME + ':WARN'); - this._error = (0, _debug2.default)(APP_NAME + ':ERROR'); - } - - /* eslint-disable no-console */ - this._debug.log = console.info.bind(console); - this._warn.log = console.warn.bind(console); - this._error.log = console.error.bind(console); - /* eslint-enable no-console */ - } - - (0, _createClass3.default)(Logger, [{ - key: 'debug', - get: function get() { - return this._debug; - } - }, { - key: 'warn', - get: function get() { - return this._warn; - } - }, { - key: 'error', - get: function get() { - return this._error; - } - }]); - return Logger; -}(); - -exports.default = Logger; - -},{"babel-runtime/helpers/classCallCheck":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/helpers/classCallCheck.js","babel-runtime/helpers/createClass":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/helpers/createClass.js","debug":"/Users/ibc/src/mediasoup-client/node_modules/debug/src/browser.js"}],"/Users/ibc/src/mediasoup-client/lib/Peer.js":[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _from = require('babel-runtime/core-js/array/from'); - -var _from2 = _interopRequireDefault(_from); - -var _getIterator2 = require('babel-runtime/core-js/get-iterator'); - -var _getIterator3 = _interopRequireDefault(_getIterator2); - -var _map = require('babel-runtime/core-js/map'); - -var _map2 = _interopRequireDefault(_map); - -var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); - -var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); - -var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); - -var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); - -var _createClass2 = require('babel-runtime/helpers/createClass'); - -var _createClass3 = _interopRequireDefault(_createClass2); - -var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); - -var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); - -var _inherits2 = require('babel-runtime/helpers/inherits'); - -var _inherits3 = _interopRequireDefault(_inherits2); - -var _Logger = require('./Logger'); - -var _Logger2 = _interopRequireDefault(_Logger); - -var _EnhancedEventEmitter2 = require('./EnhancedEventEmitter'); - -var _EnhancedEventEmitter3 = _interopRequireDefault(_EnhancedEventEmitter2); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -var logger = new _Logger2.default('Peer'); - -var Peer = function (_EnhancedEventEmitter) { - (0, _inherits3.default)(Peer, _EnhancedEventEmitter); - - /** - * @private - * - * @emits {consumer: Consumer} newconsumer - * @emits {originator: String, [appData]: Any} closed - * @emits {originator: String} @close - */ - function Peer(name, appData) { - (0, _classCallCheck3.default)(this, Peer); - - // Name. - // @type {String} - var _this = (0, _possibleConstructorReturn3.default)(this, (Peer.__proto__ || (0, _getPrototypeOf2.default)(Peer)).call(this)); - - _this._name = name; - - // Closed flag. - // @type {Boolean} - _this._closed = false; - - // App custom data. - // @type {Any} - _this._appData = appData; - - // Map of Consumers indexed by id. - // @type {map} - _this._consumers = new _map2.default(); - return _this; - } - - /** - * Peer name. - * - * @return {String} - */ - - - (0, _createClass3.default)(Peer, [{ - key: 'close', - - - /** - * Closes the Peer. - * This is called when the local Room is closed. - * - * @private - */ - value: function close() { - logger.debug('close()'); - - if (this._closed) return; - - this._closed = true; - - this.emit('@close', 'local'); - this.safeEmit('closed', 'local'); - - // Close all the Consumers. - var _iteratorNormalCompletion = true; - var _didIteratorError = false; - var _iteratorError = undefined; - - try { - for (var _iterator = (0, _getIterator3.default)(this._consumers.values()), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { - var consumer = _step.value; - - consumer.close(); - } - } catch (err) { - _didIteratorError = true; - _iteratorError = err; - } finally { - try { - if (!_iteratorNormalCompletion && _iterator.return) { - _iterator.return(); - } - } finally { - if (_didIteratorError) { - throw _iteratorError; - } - } - } - } - - /** - * The remote Peer or Room was closed. - * Invoked via remote notification. - * - * @private - * - * @param {Any} [appData] - App custom data. - */ - - }, { - key: 'remoteClose', - value: function remoteClose(appData) { - logger.debug('remoteClose()'); - - if (this._closed) return; - - this._closed = true; - - this.emit('@close', 'remote'); - this.safeEmit('closed', 'remote', appData); - - // Close all the Consumers. - var _iteratorNormalCompletion2 = true; - var _didIteratorError2 = false; - var _iteratorError2 = undefined; - - try { - for (var _iterator2 = (0, _getIterator3.default)(this._consumers.values()), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { - var consumer = _step2.value; - - consumer.remoteClose(); - } - } catch (err) { - _didIteratorError2 = true; - _iteratorError2 = err; - } finally { - try { - if (!_iteratorNormalCompletion2 && _iterator2.return) { - _iterator2.return(); - } - } finally { - if (_didIteratorError2) { - throw _iteratorError2; - } - } - } - } - - /** - * Get the Consumer with the given id. - * - * @param {Number} id - * - * @return {Consumer} - */ - - }, { - key: 'getConsumerById', - value: function getConsumerById(id) { - return this._consumers.get(id); - } - - /** - * Add an associated Consumer. - * - * @private - * - * @param {Consumer} consumer - */ - - }, { - key: 'addConsumer', - value: function addConsumer(consumer) { - var _this2 = this; - - if (this._consumers.has(consumer.id)) throw new Error('Consumer already exists [id:' + consumer.id + ']'); - - // Store it. - this._consumers.set(consumer.id, consumer); - - // Handle it. - consumer.on('@close', function () { - _this2._consumers.delete(consumer.id); - }); - - // Emit event. - this.safeEmit('newconsumer', consumer); - } - }, { - key: 'name', - get: function get() { - return this._name; - } - - /** - * Whether the Peer is closed. - * - * @return {Boolean} - */ - - }, { - key: 'closed', - get: function get() { - return this._closed; - } - - /** - * App custom data. - * - * @return {Any} - */ - - }, { - key: 'appData', - get: function get() { - return this._appData; - } - - /** - * The list of Consumers. - * - * @return {Array} - */ - - }, { - key: 'consumers', - get: function get() { - return (0, _from2.default)(this._consumers.values()); - } - }]); - return Peer; -}(_EnhancedEventEmitter3.default); - -exports.default = Peer; - -},{"./EnhancedEventEmitter":"/Users/ibc/src/mediasoup-client/lib/EnhancedEventEmitter.js","./Logger":"/Users/ibc/src/mediasoup-client/lib/Logger.js","babel-runtime/core-js/array/from":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/core-js/array/from.js","babel-runtime/core-js/get-iterator":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/core-js/get-iterator.js","babel-runtime/core-js/map":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/core-js/map.js","babel-runtime/core-js/object/get-prototype-of":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/core-js/object/get-prototype-of.js","babel-runtime/helpers/classCallCheck":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/helpers/classCallCheck.js","babel-runtime/helpers/createClass":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/helpers/createClass.js","babel-runtime/helpers/inherits":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/helpers/inherits.js","babel-runtime/helpers/possibleConstructorReturn":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/helpers/possibleConstructorReturn.js"}],"/Users/ibc/src/mediasoup-client/lib/Producer.js":[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); - -var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); - -var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); - -var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); - -var _createClass2 = require('babel-runtime/helpers/createClass'); - -var _createClass3 = _interopRequireDefault(_createClass2); - -var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); - -var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); - -var _inherits2 = require('babel-runtime/helpers/inherits'); - -var _inherits3 = _interopRequireDefault(_inherits2); - -var _Logger = require('./Logger'); - -var _Logger2 = _interopRequireDefault(_Logger); - -var _EnhancedEventEmitter2 = require('./EnhancedEventEmitter'); - -var _EnhancedEventEmitter3 = _interopRequireDefault(_EnhancedEventEmitter2); - -var _utils = require('./utils'); - -var utils = _interopRequireWildcard(_utils); - -function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -var logger = new _Logger2.default('Producer'); - -var Producer = function (_EnhancedEventEmitter) { - (0, _inherits3.default)(Producer, _EnhancedEventEmitter); - - /** - * @private - * - * @emits {originator: String, [appData]: Any} paused - * @emits {originator: String, [appData]: Any} resumed - * @emits unhandled - * @emits {originator: String, [appData]: Any} closed - * - * @emits {[appData]: Any} @pause - * @emits {[appData]: Any} @resume - * @emits {originator: String, [appData]: Any} @close - * - */ - function Producer(track, appData) { - (0, _classCallCheck3.default)(this, Producer); - - // Id. - // @type {Number} - var _this = (0, _possibleConstructorReturn3.default)(this, (Producer.__proto__ || (0, _getPrototypeOf2.default)(Producer)).call(this)); - - _this._id = utils.randomNumber(); - - // Closed flag. - // @type {Boolean} - _this._closed = false; - - // Original track. - // @type {MediaStreamTrack} - _this._originalTrack = track; - - // Track cloned from the original one. - // @type {MediaStreamTrack} - _this._track = track.clone(); - - // App custom data. - // @type {Any} - _this._appData = appData; - - // Whether this Producer is being handled by a Transport. - // @type {Boolean} - _this._handled = false; - - // RTP parameters. - // @type {RTCRtpParameters} - _this._rtpParameters = null; - - // Locally paused flag. - // @type {Boolean} - _this._locallyPaused = !_this._track.enabled; - - // Remotely paused flag. - // @type {Boolean} - _this._remotelyPaused = false; - return _this; - } - - /** - * Class name. - * - * @return {String} - */ - - - (0, _createClass3.default)(Producer, [{ - key: 'close', - - - /** - * Closes the Producer. - * - * @param {Any} [appData] - App custom data. - */ - value: function close(appData) { - logger.debug('close()'); - - if (this._closed) return; - - this._closed = true; - - this.emit('@close', 'local', appData); - this.safeEmit('closed', 'local', appData); - - this._destroy(); - } - - /** - * My remote Producer was closed. - * Invoked via remote notification. - * - * @private - * - * @param {Any} [appData] - App custom data. - */ - - }, { - key: 'remoteClose', - value: function remoteClose(appData) { - logger.debug('remoteClose()'); - - if (this._closed) return; - - this._closed = true; - - this.emit('@close', 'remote', appData); - this.safeEmit('closed', 'remote', appData); - - this._destroy(); - } - }, { - key: '_destroy', - value: function _destroy() { - this._closed = true; - this._handled = false; - this._rtpParameters = null; - - try { - this._track.stop(); - } catch (error) {} - } - - /** - * Pauses sending media. - * - * @param {Any} [appData] - App custom data. - * - * @return {Boolean} true if paused. - */ - - }, { - key: 'pause', - value: function pause(appData) { - logger.debug('pause()'); - - if (this._closed) { - logger.error('pause() | Producer closed'); - - return false; - } else if (!this._handled) { - logger.error('pause() | Producer not handled'); - - return false; - } else if (this._locallyPaused) { - return true; - } - - this._locallyPaused = true; - this._track.enabled = false; - - this.emit('@pause', appData); - - if (!this._remotelyPaused) this.safeEmit('paused', 'local', appData); - - // Return true if really paused. - return this.paused; - } - - /** - * My remote Producer was paused. - * Invoked via remote notification. - * - * @private - * - * @param {Any} [appData] - App custom data. - */ - - }, { - key: 'remotePause', - value: function remotePause(appData) { - logger.debug('remotePause()'); - - if (this._closed || !this._handled || this._remotelyPaused) return; - - this._remotelyPaused = true; - this._track.enabled = false; - - if (!this._locallyPaused) this.safeEmit('paused', 'remote', appData); - } - - /** - * Resumes sending media. - * - * @param {Any} [appData] - App custom data. - * - * @return {Boolean} true if not paused. - */ - - }, { - key: 'resume', - value: function resume(appData) { - logger.debug('resume()'); - - if (this._closed) { - logger.error('resume() | Producer closed'); - - return false; - } else if (!this._handled) { - logger.error('pause() | Producer not handled'); - - return false; - } else if (!this._locallyPaused) { - return true; - } - - this._locallyPaused = false; - - this.emit('@resume', appData); - - if (!this._remotelyPaused) { - this._track.enabled = true; - - this.safeEmit('resumed', 'local', appData); - } - - // Return true if not paused. - return !this.paused; - } - - /** - * My remote Producer was resumed. - * Invoked via remote notification. - * - * @private - * - * @param {Any} [appData] - App custom data. - */ - - }, { - key: 'remoteResume', - value: function remoteResume(appData) { - logger.debug('remoteResume()'); - - if (this._closed || !this._handled || !this._remotelyPaused) return; - - this._remotelyPaused = false; - - if (!this._locallyPaused) { - this._track.enabled = true; - - this.safeEmit('resumed', 'remote', appData); - } - } - - /** - * Set this Producer as handled or unhandled by a Transport. - * - * @private - * - * @param {Boolean|String} flag - If 'tmp' (String) it's considered as termporal. - * @param {RTCRtpParameters} rtpParameters - */ - - }, { - key: 'setHandled', - value: function setHandled(flag, rtpParameters) { - if (this._closed) return; - - var previous = this._handled; - - this._handled = flag; - this._rtpParameters = rtpParameters; - - if (flag === false || flag === 'tmp') this._rtpParameters = null; - - if (previous === true && flag === false) this.safeEmit('unhandled'); - } - }, { - key: 'klass', - get: function get() { - return 'Producer'; - } - - /** - * Producer id. - * - * @return {Number} - */ - - }, { - key: 'id', - get: function get() { - return this._id; - } - - /** - * Whether the Producer is closed. - * - * @return {Boolean} - */ - - }, { - key: 'closed', - get: function get() { - return this._closed; - } - - /** - * Media kind. - * - * @return {String} - */ - - }, { - key: 'kind', - get: function get() { - return this._track.kind; - } - - /** - * The associated track. - * - * @return {MediaStreamTrack} - */ - - }, { - key: 'track', - get: function get() { - return this._track; - } - - /** - * The associated original track. - * - * @return {MediaStreamTrack} - */ - - }, { - key: 'originalTrack', - get: function get() { - return this._originalTrack; - } - - /** - * App custom data. - * - * @return {Any} - */ - - }, { - key: 'appData', - get: function get() { - return this._appData; - } - - /** - * Whether this is being handled by a Transport. - * - * @return {Boolean} - */ - - }, { - key: 'handled', - get: function get() { - return Boolean(this._handled); - } - - /** - * RTP parameters. - * - * @return {RTCRtpParameters} - */ - - }, { - key: 'rtpParameters', - get: function get() { - return this._rtpParameters; - } - - /** - * Whether the Producer is locally paused. - * - * @return {Boolean} - */ - - }, { - key: 'locallyPaused', - get: function get() { - return this._locallyPaused; - } - - /** - * Whether the Producer is remotely paused. - * - * @return {Boolean} - */ - - }, { - key: 'remotelyPaused', - get: function get() { - return this._remotelyPaused; - } - - /** - * Whether the Producer is paused. - * - * @return {Boolean} - */ - - }, { - key: 'paused', - get: function get() { - return this._locallyPaused || this._remotelyPaused; - } - - /** - * Whether the Producer is actually sending media. - * - * @return {Boolean} - */ - - }, { - key: 'active', - get: function get() { - return !this._closed && this.handled === true && !this.paused; - } - }]); - return Producer; -}(_EnhancedEventEmitter3.default); - -exports.default = Producer; - -},{"./EnhancedEventEmitter":"/Users/ibc/src/mediasoup-client/lib/EnhancedEventEmitter.js","./Logger":"/Users/ibc/src/mediasoup-client/lib/Logger.js","./utils":"/Users/ibc/src/mediasoup-client/lib/utils.js","babel-runtime/core-js/object/get-prototype-of":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/core-js/object/get-prototype-of.js","babel-runtime/helpers/classCallCheck":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/helpers/classCallCheck.js","babel-runtime/helpers/createClass":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/helpers/createClass.js","babel-runtime/helpers/inherits":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/helpers/inherits.js","babel-runtime/helpers/possibleConstructorReturn":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/helpers/possibleConstructorReturn.js"}],"/Users/ibc/src/mediasoup-client/lib/Room.js":[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _from = require('babel-runtime/core-js/array/from'); - -var _from2 = _interopRequireDefault(_from); - -var _extends2 = require('babel-runtime/helpers/extends'); - -var _extends3 = _interopRequireDefault(_extends2); - -var _typeof2 = require('babel-runtime/helpers/typeof'); - -var _typeof3 = _interopRequireDefault(_typeof2); - -var _getIterator2 = require('babel-runtime/core-js/get-iterator'); - -var _getIterator3 = _interopRequireDefault(_getIterator2); - -var _promise = require('babel-runtime/core-js/promise'); - -var _promise2 = _interopRequireDefault(_promise); - -var _map = require('babel-runtime/core-js/map'); - -var _map2 = _interopRequireDefault(_map); - -var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); - -var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); - -var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); - -var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); - -var _createClass2 = require('babel-runtime/helpers/createClass'); - -var _createClass3 = _interopRequireDefault(_createClass2); - -var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); - -var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); - -var _inherits2 = require('babel-runtime/helpers/inherits'); - -var _inherits3 = _interopRequireDefault(_inherits2); - -var _Logger = require('./Logger'); - -var _Logger2 = _interopRequireDefault(_Logger); - -var _EnhancedEventEmitter2 = require('./EnhancedEventEmitter'); - -var _EnhancedEventEmitter3 = _interopRequireDefault(_EnhancedEventEmitter2); - -var _errors = require('./errors'); - -var _utils = require('./utils'); - -var utils = _interopRequireWildcard(_utils); - -var _Device = require('./Device'); - -var _Device2 = _interopRequireDefault(_Device); - -var _Transport = require('./Transport'); - -var _Transport2 = _interopRequireDefault(_Transport); - -var _Producer = require('./Producer'); - -var _Producer2 = _interopRequireDefault(_Producer); - -var _Peer = require('./Peer'); - -var _Peer2 = _interopRequireDefault(_Peer); - -var _Consumer = require('./Consumer'); - -var _Consumer2 = _interopRequireDefault(_Consumer); - -function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -var logger = new _Logger2.default('Room'); - -var RoomState = { - new: 'new', - joining: 'joining', - joined: 'joined', - closed: 'closed' -}; - -/** - * An instance of Room represents a remote multi conference and a local - * peer that joins it. - */ - -var Room = function (_EnhancedEventEmitter) { - (0, _inherits3.default)(Room, _EnhancedEventEmitter); - - /** - * Room class. - * - * @param {Object} [options] - * @param {Number} [options.requestTimeout=10000] - Timeout for sent requests - * (in milliseconds). Defaults to 10000 (10 seconds). - * @param {Object} [options.transportOptions] - Transport options for mediasoup. - * @param {Array} [options.turnServers] - Array of TURN servers. - * @param {Boolean} [hidden=false] - If true no remote Peers will be notified. - * - * @throws {Error} if device is not supported. - * - * @emits {request: Object, callback: Function, errback: Function} request - * @emits {notification: Object} notify - * @emits {peer: Peer} newpeer - * @emits {originator: String, [appData]: Any} closed - */ - function Room(options) { - (0, _classCallCheck3.default)(this, Room); - - logger.debug('constructor() [options:%o]', options); - - var _this = (0, _possibleConstructorReturn3.default)(this, (Room.__proto__ || (0, _getPrototypeOf2.default)(Room)).call(this)); - - if (!_Device2.default.isSupported()) throw new Error('current browser/device not supported'); - - options = options || {}; - - // Computed settings. - // @type {Object} - _this._settings = { - requestTimeout: options.requestTimeout || 10000, - transportOptions: options.transportOptions || {}, - turnServers: options.turnServers || [], - hidden: Boolean(options.hidden) - }; - - // Room state. - // @type {Boolean} - _this._state = RoomState.new; - - // Map of Transports indexed by id. - // @type {map} - _this._transports = new _map2.default(); - - // Map of Producers indexed by id. - // @type {map} - _this._producers = new _map2.default(); - - // Map of Peers indexed by name. - // @type {map} - _this._peers = new _map2.default(); - - // Extended RTP capabilities. - // @type {Object} - _this._extendedRtpCapabilities = null; - - // Whether we can send audio/video based on computed extended RTP - // capabilities. - // @type {Object} - _this._canSendByKind = { - audio: false, - video: false - }; - return _this; - } - - /** - * Whether the Room is joined. - * - * @return {Boolean} - */ - - - (0, _createClass3.default)(Room, [{ - key: 'join', - - - /** - * Start the procedures to join a remote room. - * - * @param {RTCRtpCapabilities} [roomRtpCapabilities] Remote room RTP capabilities. - * If given, no request is sent to the server to discover them. - * @param {Any} [appData] - App custom data. - * @return {Promise} - */ - value: function join(roomRtpCapabilities, appData) { - var _this2 = this; - - if (!roomRtpCapabilities) logger.debug('join()');else logger.debug('join() [roomRtpCapabilities:%o]', roomRtpCapabilities); - - if (this._state !== RoomState.new) { - return _promise2.default.reject(new _errors.InvalidStateError('invalid state "' + this._state + '"')); - } - - this._state = RoomState.joining; - - var remoteRtpCapabilities = void 0; - var localRtpCapabilities = void 0; - - return _promise2.default.resolve().then(function () { - if (roomRtpCapabilities) return roomRtpCapabilities; - - return _this2._sendRequest('queryRoom').then(function (response) { - var rtpCapabilities = response.rtpCapabilities; - - - logger.debug('join() | got Room RTP capabilities:%o', rtpCapabilities); - - return rtpCapabilities; - }); - }).then(function (rtpCapabilities) { - remoteRtpCapabilities = rtpCapabilities; - - return _Device2.default.Handler.getLocalRtpCapabilities(); - }).then(function (rtpCapabilities) { - localRtpCapabilities = rtpCapabilities; - - // Get extended RTP capabilities. - _this2._extendedRtpCapabilities = utils.getExtendedRtpCapabilities(localRtpCapabilities, remoteRtpCapabilities); - - // Check whether we can send audio/video. - _this2._canSendByKind.audio = utils.canSend('audio', _this2._extendedRtpCapabilities); - _this2._canSendByKind.video = utils.canSend('video', _this2._extendedRtpCapabilities); - - // Generate our effective RTP capabilities for receiving media. - var effectiveLocalRtpCapabilities = utils.getRtpCapabilities(_this2._extendedRtpCapabilities); - - logger.debug('join() | effective local RTP capabilities:%o', effectiveLocalRtpCapabilities); - - var data = { - rtpCapabilities: effectiveLocalRtpCapabilities, - appData: appData - }; - - return _this2._sendRequest('joinRoom', data).then(function (response) { - return response.peers; - }); - }).then(function (peers) { - if (!_this2._settings.hidden) { - // Handle Peers already existing in the room. - var _iteratorNormalCompletion = true; - var _didIteratorError = false; - var _iteratorError = undefined; - - try { - for (var _iterator = (0, _getIterator3.default)(peers || []), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { - var peerData = _step.value; - - try { - _this2._handlePeerData(peerData); - } catch (error) { - logger.error('join() | error handling Peer:%o', error); - } - } - } catch (err) { - _didIteratorError = true; - _iteratorError = err; - } finally { - try { - if (!_iteratorNormalCompletion && _iterator.return) { - _iterator.return(); - } - } finally { - if (_didIteratorError) { - throw _iteratorError; - } - } - } - } else if (peers.length > 0) { - logger.error('join() | should not receive Peer list in hidden mode'); - } - - _this2._state = RoomState.joined; - - logger.debug('join() | joined the Room'); - - // Return the list of already existing Peers. - return _this2.peers; - }).catch(function (error) { - _this2._state = RoomState.new; - - throw error; - }); - } - - /** - * Leave the Room. - * - * @param {Any} [appData] - App custom data. - */ - - }, { - key: 'leave', - value: function leave(appData) { - logger.debug('leave()'); - - if (this.closed) return; - - // Send a notification. - this._sendNotification('leaveRoom', { appData: appData }); - - // Set closed state after sending the notification (otherwise the - // notification won't be sent). - this._state = RoomState.closed; - - this.safeEmit('closed', 'local', appData); - - // Close all the Transports. - var _iteratorNormalCompletion2 = true; - var _didIteratorError2 = false; - var _iteratorError2 = undefined; - - try { - for (var _iterator2 = (0, _getIterator3.default)(this._transports.values()), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { - var transport = _step2.value; - - transport.close(); - } - - // Close all the Producers. - } catch (err) { - _didIteratorError2 = true; - _iteratorError2 = err; - } finally { - try { - if (!_iteratorNormalCompletion2 && _iterator2.return) { - _iterator2.return(); - } - } finally { - if (_didIteratorError2) { - throw _iteratorError2; - } - } - } - - var _iteratorNormalCompletion3 = true; - var _didIteratorError3 = false; - var _iteratorError3 = undefined; - - try { - for (var _iterator3 = (0, _getIterator3.default)(this._producers.values()), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) { - var producer = _step3.value; - - producer.close(); - } - - // Close all the Peers. - } catch (err) { - _didIteratorError3 = true; - _iteratorError3 = err; - } finally { - try { - if (!_iteratorNormalCompletion3 && _iterator3.return) { - _iterator3.return(); - } - } finally { - if (_didIteratorError3) { - throw _iteratorError3; - } - } - } - - var _iteratorNormalCompletion4 = true; - var _didIteratorError4 = false; - var _iteratorError4 = undefined; - - try { - for (var _iterator4 = (0, _getIterator3.default)(this._peers.values()), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) { - var peer = _step4.value; - - peer.close(); - } - } catch (err) { - _didIteratorError4 = true; - _iteratorError4 = err; - } finally { - try { - if (!_iteratorNormalCompletion4 && _iterator4.return) { - _iterator4.return(); - } - } finally { - if (_didIteratorError4) { - throw _iteratorError4; - } - } - } - } - - /** - * The remote Room was closed or our remote Peer has been closed. - * Invoked via remote notification. - * - * @private - * @param {Any} [appData] - App custom data. - */ - - }, { - key: 'remoteClose', - value: function remoteClose(appData) { - logger.debug('remoteClose()'); - - if (this.closed) return; - - this._state = RoomState.closed; - - this.safeEmit('closed', 'remote', appData); - - // Close all the Transports. - var _iteratorNormalCompletion5 = true; - var _didIteratorError5 = false; - var _iteratorError5 = undefined; - - try { - for (var _iterator5 = (0, _getIterator3.default)(this._transports.values()), _step5; !(_iteratorNormalCompletion5 = (_step5 = _iterator5.next()).done); _iteratorNormalCompletion5 = true) { - var transport = _step5.value; - - transport.remoteClose(); - } - - // Close all the Producers. - } catch (err) { - _didIteratorError5 = true; - _iteratorError5 = err; - } finally { - try { - if (!_iteratorNormalCompletion5 && _iterator5.return) { - _iterator5.return(); - } - } finally { - if (_didIteratorError5) { - throw _iteratorError5; - } - } - } - - var _iteratorNormalCompletion6 = true; - var _didIteratorError6 = false; - var _iteratorError6 = undefined; - - try { - for (var _iterator6 = (0, _getIterator3.default)(this._producers.values()), _step6; !(_iteratorNormalCompletion6 = (_step6 = _iterator6.next()).done); _iteratorNormalCompletion6 = true) { - var producer = _step6.value; - - producer.remoteClose(); - } - - // Close all the Peers. - } catch (err) { - _didIteratorError6 = true; - _iteratorError6 = err; - } finally { - try { - if (!_iteratorNormalCompletion6 && _iterator6.return) { - _iterator6.return(); - } - } finally { - if (_didIteratorError6) { - throw _iteratorError6; - } - } - } - - var _iteratorNormalCompletion7 = true; - var _didIteratorError7 = false; - var _iteratorError7 = undefined; - - try { - for (var _iterator7 = (0, _getIterator3.default)(this._peers.values()), _step7; !(_iteratorNormalCompletion7 = (_step7 = _iterator7.next()).done); _iteratorNormalCompletion7 = true) { - var peer = _step7.value; - - peer.remoteClose(); - } - } catch (err) { - _didIteratorError7 = true; - _iteratorError7 = err; - } finally { - try { - if (!_iteratorNormalCompletion7 && _iterator7.return) { - _iterator7.return(); - } - } finally { - if (_didIteratorError7) { - throw _iteratorError7; - } - } - } - } - - /** - * Whether we can send audio/video. - * - * @param {String} kind - 'audio' or 'video'. - * - * @return {Boolean} - */ - - }, { - key: 'canSend', - value: function canSend(kind) { - if (!this.joined) throw new _errors.InvalidStateError('invalid state "' + this._state + '"');else if (kind !== 'audio' && kind !== 'video') throw new TypeError('invalid kind "' + kind + '"'); - - return this._canSendByKind[kind]; - } - - /** - * Creates a Transport. - * - * @param {String} direction - Must be 'send' or 'recv'. - * @param {Any} [appData] - App custom data. - * - * @return {Transport} - * - * @throws {InvalidStateError} if not joined. - * @throws {TypeError} if wrong arguments. - */ - - }, { - key: 'createTransport', - value: function createTransport(direction, appData) { - var _this3 = this; - - logger.debug('createTransport() [direction:%s]', direction); - - if (!this.joined) throw new _errors.InvalidStateError('invalid state "' + this._state + '"');else if (direction !== 'send' && direction !== 'recv') throw new TypeError('invalid direction "' + direction + '"'); - - // Create a new Transport. - var transport = new _Transport2.default(direction, this._extendedRtpCapabilities, this._settings, appData); - - // Store it. - this._transports.set(transport.id, transport); - - transport.on('@request', function (method, data, callback, errback) { - _this3._sendRequest(method, data).then(callback || function () {}).catch(errback || function () {}); - }); - - transport.on('@notify', function (method, data) { - _this3._sendNotification(method, data); - }); - - transport.on('@close', function () { - _this3._transports.delete(transport.id); - }); - - return transport; - } - - /** - * Creates a Producer. - * - * @param {MediaStreamTrack} track - * @param {Any} [appData] - App custom data. - * - * @return {Producer} - * - * @throws {InvalidStateError} if not joined. - * @throws {TypeError} if wrong arguments. - * @throws {Error} if cannot send the given kind. - */ - - }, { - key: 'createProducer', - value: function createProducer(track, appData) { - var _this4 = this; - - logger.debug('createProducer() [track:%o]', track); - - if (!this.joined) throw new _errors.InvalidStateError('invalid state "' + this._state + '"');else if (!(track instanceof MediaStreamTrack)) throw new TypeError('track is not a MediaStreamTrack');else if (!this._canSendByKind[track.kind]) throw new Error('cannot send ' + track.kind);else if (track.readyState === 'ended') throw new Error('track.readyState is "ended"'); - - // Create a new Producer. - var producer = new _Producer2.default(track, appData); - - // Store it. - this._producers.set(producer.id, producer); - - producer.on('@close', function () { - _this4._producers.delete(producer.id); - }); - - return producer; - } - - /** - * Get the Transport with the given id. - * - * @param {Number} id - * - * @return {Transport} - */ - - }, { - key: 'getTransportById', - value: function getTransportById(id) { - return this._transports.get(id); - } - - /** - * Get the Producer with the given id. - * - * @param {Number} id - * - * @return {Producer} - */ - - }, { - key: 'getProducerById', - value: function getProducerById(id) { - return this._producers.get(id); - } - - /** - * Get the Peer with the given name. - * - * @param {String} name - * - * @return {Peer} - */ - - }, { - key: 'getPeerById', - value: function getPeerById(name) { - return this._peers.get(name); - } - - /** - * Provide the local Room with a notification generated by mediasoup server. - * - * @param {Object} notification - */ - - }, { - key: 'receiveNotification', - value: function receiveNotification(notification) { - try { - if (this.closed) throw new _errors.InvalidStateError('Room closed');else if ((typeof notification === 'undefined' ? 'undefined' : (0, _typeof3.default)(notification)) !== 'object') throw new TypeError('wrong notification Object');else if (notification.notification !== true) throw new TypeError('not a notification');else if (typeof notification.method !== 'string') throw new TypeError('wrong/missing notification method'); - - var method = notification.method; - - logger.debug('receiveNotification() [method:%s, notification:%o]', method, notification); - - switch (method) { - case 'roomClosed': - { - var appData = notification.appData; - - - this.remoteClose(appData); - - break; - } - - case 'transportClosed': - { - var id = notification.id, - _appData = notification.appData; - - var transport = this._transports.get(id); - - if (!transport) throw new Error('Transport does not exist [id:"' + id + '"]'); - - transport.remoteClose(_appData); - - break; - } - - case 'newPeer': - { - this._ensureNotHidden(); - - var name = notification.name; - - - if (this._peers.has(name)) throw new Error('Peer already exists [name:"' + name + '"]'); - - var peerData = notification; - - this._handlePeerData(peerData); - - break; - } - - case 'peerClosed': - { - this._ensureNotHidden(); - - var peerName = notification.name; - var _appData2 = notification.appData; - - var peer = this._peers.get(peerName); - - if (!peer) throw new Error('no Peer found [name:"' + peerName + '"]'); - - peer.remoteClose(_appData2); - - break; - } - - case 'producerClosed': - { - var _id = notification.id, - _appData3 = notification.appData; - - var producer = this._producers.get(_id); - - if (!producer) throw new Error('Producer not found [id:' + _id + ']'); - - producer.remoteClose(_appData3); - - break; - } - - case 'producerPaused': - { - var _id2 = notification.id, - _appData4 = notification.appData; - - var _producer = this._producers.get(_id2); - - if (!_producer) throw new Error('Producer not found [id:' + _id2 + ']'); - - _producer.remotePause(_appData4); - - break; - } - - case 'producerResumed': - { - var _id3 = notification.id, - _appData5 = notification.appData; - - var _producer2 = this._producers.get(_id3); - - if (!_producer2) throw new Error('Producer not found [id:' + _id3 + ']'); - - _producer2.remoteResume(_appData5); - - break; - } - - case 'newConsumer': - { - this._ensureNotHidden(); - - var _peerName = notification.peerName; - - var _peer = this._peers.get(_peerName); - - if (!_peer) throw new Error('no Peer found [name:"' + _peerName + '"]'); - - var consumerData = notification; - - this._handleConsumerData(consumerData, _peer); - - break; - } - - case 'consumerClosed': - { - this._ensureNotHidden(); - - var _id4 = notification.id, - _peerName2 = notification.peerName, - _appData6 = notification.appData; - - var _peer2 = this._peers.get(_peerName2); - - if (!_peer2) throw new Error('no Peer found [name:"' + _peerName2 + '"]'); - - var consumer = _peer2.getConsumerById(_id4); - - if (!consumer) throw new Error('Consumer not found [id:' + _id4 + ']'); - - consumer.remoteClose(_appData6); - - break; - } - - case 'consumerPaused': - { - this._ensureNotHidden(); - - var _id5 = notification.id, - _peerName3 = notification.peerName, - _appData7 = notification.appData; - - var _peer3 = this._peers.get(_peerName3); - - if (!_peer3) throw new Error('no Peer found [name:"' + _peerName3 + '"]'); - - var _consumer = _peer3.getConsumerById(_id5); - - if (!_consumer) throw new Error('Consumer not found [id:' + _id5 + ']'); - - _consumer.remotePause(_appData7); - - break; - } - - case 'consumerResumed': - { - this._ensureNotHidden(); - - var _id6 = notification.id, - _peerName4 = notification.peerName, - _appData8 = notification.appData; - - var _peer4 = this._peers.get(_peerName4); - - var _consumer2 = _peer4.getConsumerById(_id6); - - if (!_consumer2) throw new Error('Consumer not found [id:' + _id6 + ']'); - - _consumer2.remoteResume(_appData8); - - break; - } - - default: - throw new Error('unknown notification method "' + method + '"'); - } - } catch (error) { - logger.error('receiveNotification() failed [notification:%o]: %s', notification, error.toString()); - } - } - }, { - key: '_sendRequest', - value: function _sendRequest(method, data) { - var _this5 = this; - - var request = (0, _extends3.default)({ method: method }, data); - - // Should never happen. - // Ignore if closed. - if (this.closed) { - logger.error('_sendRequest() | Room closed [method:%s, request:%o]', method, request); - - return _promise2.default.reject(new _errors.InvalidStateError('Room closed')); - } - - logger.debug('_sendRequest() [method:%s, request:%o]', method, request); - - return new _promise2.default(function (resolve, reject) { - var done = false; - - var timer = setTimeout(function () { - logger.error('request failed [method:%s]: timeout', method); - - done = true; - reject(new _errors.TimeoutError('timeout')); - }, _this5._settings.requestTimeout); - - // TODO: We could also handle room 'closed' event here. - - var callback = function callback(response) { - if (done) return; - - done = true; - clearTimeout(timer); - - if (_this5.closed) { - logger.error('request failed [method:%s]: Room closed', method); - - reject(new Error('Room closed')); - - return; - } - - logger.debug('request succeeded [method:%s, response:%o]', method, response); - - resolve(response); - }; - - var errback = function errback(message) { - if (done) return; - - done = true; - clearTimeout(timer); - - if (_this5.closed) { - logger.error('request failed [method:%s]: Room closed', method); - - reject(new Error('Room closed')); - - return; - } - - // Make sure message is a String. - message = String(message); - - logger.error('request failed [method:%s]: %s', method, message); - - reject(new Error(message)); - }; - - _this5.safeEmit('request', request, callback, errback); - }); - } - }, { - key: '_sendNotification', - value: function _sendNotification(method, data) { - // Ignore if closed. - if (this.closed) return; - - var notification = (0, _extends3.default)({ method: method, notification: true }, data); - - logger.debug('_sendNotification() [method:%s, notification:%o]', method, notification); - - this.safeEmit('notify', notification); - } - }, { - key: '_ensureNotHidden', - value: function _ensureNotHidden() { - if (this._settings.hidden) throw new Error('hidden mode set'); - } - }, { - key: '_handlePeerData', - value: function _handlePeerData(peerData) { - var _this6 = this; - - var name = peerData.name, - consumers = peerData.consumers, - appData = peerData.appData; - - var peer = new _Peer2.default(name, appData); - - // Store it. - this._peers.set(peer.name, peer); - - peer.on('@close', function () { - _this6._peers.delete(peer.name); - }); - - // Add consumers. - var _iteratorNormalCompletion8 = true; - var _didIteratorError8 = false; - var _iteratorError8 = undefined; - - try { - for (var _iterator8 = (0, _getIterator3.default)(consumers), _step8; !(_iteratorNormalCompletion8 = (_step8 = _iterator8.next()).done); _iteratorNormalCompletion8 = true) { - var consumerData = _step8.value; - - try { - this._handleConsumerData(consumerData, peer); - } catch (error) { - logger.error('error handling existing Consumer in Peer:%o', error); - } - } - - // If already joined emit event. - } catch (err) { - _didIteratorError8 = true; - _iteratorError8 = err; - } finally { - try { - if (!_iteratorNormalCompletion8 && _iterator8.return) { - _iterator8.return(); - } - } finally { - if (_didIteratorError8) { - throw _iteratorError8; - } - } - } - - if (this.joined) this.safeEmit('newpeer', peer); - } - }, { - key: '_handleConsumerData', - value: function _handleConsumerData(producerData, peer) { - var id = producerData.id, - kind = producerData.kind, - rtpParameters = producerData.rtpParameters, - paused = producerData.paused, - appData = producerData.appData; - - var consumer = new _Consumer2.default(id, kind, rtpParameters, peer, appData); - var supported = utils.canReceive(consumer.rtpParameters, this._extendedRtpCapabilities); - - if (supported) consumer.setSupported(true); - - if (paused) consumer.remotePause(); - - peer.addConsumer(consumer); - } - }, { - key: 'joined', - get: function get() { - return this._state === RoomState.joined; - } - - /** - * Whether the Room is closed. - * - * @return {Boolean} - */ - - }, { - key: 'closed', - get: function get() { - return this._state === RoomState.closed; - } - - /** - * The list of Transports. - * - * @return {Array} - */ - - }, { - key: 'transports', - get: function get() { - return (0, _from2.default)(this._transports.values()); - } - - /** - * The list of Producers. - * - * @return {Array} - */ - - }, { - key: 'producers', - get: function get() { - return (0, _from2.default)(this._producers.values()); - } - - /** - * The list of Peers. - * - * @return {Array} - */ - - }, { - key: 'peers', - get: function get() { - return (0, _from2.default)(this._peers.values()); - } - }]); - return Room; -}(_EnhancedEventEmitter3.default); - -exports.default = Room; - -},{"./Consumer":"/Users/ibc/src/mediasoup-client/lib/Consumer.js","./Device":"/Users/ibc/src/mediasoup-client/lib/Device.js","./EnhancedEventEmitter":"/Users/ibc/src/mediasoup-client/lib/EnhancedEventEmitter.js","./Logger":"/Users/ibc/src/mediasoup-client/lib/Logger.js","./Peer":"/Users/ibc/src/mediasoup-client/lib/Peer.js","./Producer":"/Users/ibc/src/mediasoup-client/lib/Producer.js","./Transport":"/Users/ibc/src/mediasoup-client/lib/Transport.js","./errors":"/Users/ibc/src/mediasoup-client/lib/errors.js","./utils":"/Users/ibc/src/mediasoup-client/lib/utils.js","babel-runtime/core-js/array/from":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/core-js/array/from.js","babel-runtime/core-js/get-iterator":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/core-js/get-iterator.js","babel-runtime/core-js/map":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/core-js/map.js","babel-runtime/core-js/object/get-prototype-of":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/core-js/object/get-prototype-of.js","babel-runtime/core-js/promise":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/core-js/promise.js","babel-runtime/helpers/classCallCheck":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/helpers/classCallCheck.js","babel-runtime/helpers/createClass":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/helpers/createClass.js","babel-runtime/helpers/extends":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/helpers/extends.js","babel-runtime/helpers/inherits":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/helpers/inherits.js","babel-runtime/helpers/possibleConstructorReturn":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/helpers/possibleConstructorReturn.js","babel-runtime/helpers/typeof":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/helpers/typeof.js"}],"/Users/ibc/src/mediasoup-client/lib/Transport.js":[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _promise = require('babel-runtime/core-js/promise'); - -var _promise2 = _interopRequireDefault(_promise); - -var _getIterator2 = require('babel-runtime/core-js/get-iterator'); - -var _getIterator3 = _interopRequireDefault(_getIterator2); - -var _map = require('babel-runtime/core-js/map'); - -var _map2 = _interopRequireDefault(_map); - -var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); - -var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); - -var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); - -var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); - -var _createClass2 = require('babel-runtime/helpers/createClass'); - -var _createClass3 = _interopRequireDefault(_createClass2); - -var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); - -var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); - -var _inherits2 = require('babel-runtime/helpers/inherits'); - -var _inherits3 = _interopRequireDefault(_inherits2); - -var _Logger = require('./Logger'); - -var _Logger2 = _interopRequireDefault(_Logger); - -var _EnhancedEventEmitter2 = require('./EnhancedEventEmitter'); - -var _EnhancedEventEmitter3 = _interopRequireDefault(_EnhancedEventEmitter2); - -var _utils = require('./utils'); - -var utils = _interopRequireWildcard(_utils); - -var _Device = require('./Device'); - -var _Device2 = _interopRequireDefault(_Device); - -var _CommandQueue = require('./CommandQueue'); - -var _CommandQueue2 = _interopRequireDefault(_CommandQueue); - -function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -var logger = new _Logger2.default('Transport'); - -var Transport = function (_EnhancedEventEmitter) { - (0, _inherits3.default)(Transport, _EnhancedEventEmitter); - - /** - * @private - * - * @emits {state: String} connectionstatechange - * @emits {originator: String, [appData]: Any} closed - * @emits {method: String, [data]: Object, callback: Function, errback: Function} @request - * @emits {method: String, [data]: Object} @notify - * @emits {originator: String} @close - */ - function Transport(direction, extendedRtpCapabilities, settings, appData) { - (0, _classCallCheck3.default)(this, Transport); - - logger.debug('constructor() [direction:%s, extendedRtpCapabilities:%o]', direction, extendedRtpCapabilities); - - // Id. - // @type {Number} - var _this = (0, _possibleConstructorReturn3.default)(this, (Transport.__proto__ || (0, _getPrototypeOf2.default)(Transport)).call(this)); - - _this._id = utils.randomNumber(); - - // Closed flag. - // @type {Boolean} - _this._closed = false; - - // Direction. - // @type {String} - _this._direction = direction; - - // Room settings. - // @type {Object} - _this._settings = settings; - - // App custom data. - // @type {Any} - _this._appData = appData; - - // Map of Producers indexed by id. - // @type {map} - _this._producers = new _map2.default(); - - // Map of Consumers indexed by id. - // @type {map} - _this._consumers = new _map2.default(); - - // Commands handler. - // @type {CommandQueue} - _this._commandQueue = new _CommandQueue2.default(); - - // Device specific handler. - _this._handler = new _Device2.default.Handler(direction, extendedRtpCapabilities, settings); - - // Transport state. Values can be: - // 'new'/'connecting'/'connected'/'failed'/'disconnected'/'closed' - // @type {String} - _this._connectionState = 'new'; - - _this._commandQueue.on('exec', _this._execCommand.bind(_this)); - _this._handleHandler(); - return _this; - } - - /** - * Transport id. - * - * @return {Number} - */ - - - (0, _createClass3.default)(Transport, [{ - key: 'close', - - - /** - * Close the Transport. - * - * @param {Any} [appData] - App custom data. - */ - value: function close(appData) { - logger.debug('close()'); - - if (this._closed) return; - - this._closed = true; - - this.safeEmit('@notify', 'closeTransport', { id: this._id, appData: appData }); - - this.emit('@close', 'local'); - this.safeEmit('closed', 'local', appData); - - this._destroy(); - } - - /** - * My remote Transport was closed. - * Invoked via remote notification. - * - * @param {Any} [appData] - App custom data. - */ - - }, { - key: 'remoteClose', - value: function remoteClose(appData) { - logger.debug('remoteClose()'); - - if (this._closed) return; - - this._closed = true; - - this.emit('@close', 'remote'); - this.safeEmit('closed', 'remote', appData); - - this._destroy(); - } - }, { - key: '_destroy', - value: function _destroy() { - // Close the CommandQueue. - this._commandQueue.close(); - - // Close the handler. - this._handler.close(); - - // Unhandle all the Producers. - var _iteratorNormalCompletion = true; - var _didIteratorError = false; - var _iteratorError = undefined; - - try { - for (var _iterator = (0, _getIterator3.default)(this._producers.values()), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { - var producer = _step.value; - - producer.setHandled(false); - } - - // Unhandle all the Consumers. - } catch (err) { - _didIteratorError = true; - _iteratorError = err; - } finally { - try { - if (!_iteratorNormalCompletion && _iterator.return) { - _iterator.return(); - } - } finally { - if (_didIteratorError) { - throw _iteratorError; - } - } - } - - var _iteratorNormalCompletion2 = true; - var _didIteratorError2 = false; - var _iteratorError2 = undefined; - - try { - for (var _iterator2 = (0, _getIterator3.default)(this._consumers.values()), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { - var consumer = _step2.value; - - consumer.setHandled(false); - } - } catch (err) { - _didIteratorError2 = true; - _iteratorError2 = err; - } finally { - try { - if (!_iteratorNormalCompletion2 && _iterator2.return) { - _iterator2.return(); - } - } finally { - if (_didIteratorError2) { - throw _iteratorError2; - } - } - } - } - - /** - * Send the given Producer over this Transport. - * - * @param {Producer} producer - * - * @return {Promise} - * - * @example - * transport.send(videoProducer) - * .then(() => { - * // Done - * }); - */ - - }, { - key: 'send', - value: function send(producer) { - logger.debug('send() [producer:%o]', producer); - - if (this._direction !== 'send') return _promise2.default.reject(new Error('cannot send on a receiving Transport'));else if (!producer || producer.klass !== 'Producer') return _promise2.default.reject(new TypeError('wrong Producer')); - - // Enqueue command. - return this._commandQueue.push('addProducer', { producer: producer }); - } - - /** - * Receive the given Consumer over this Transport. - * - * @param {Consumer} consumer - * - * @return {Promise} - * - * @example - * transport.receive(aliceVideoConsumer) - * .then(() => { - * // Done - * }); - */ - - }, { - key: 'receive', - value: function receive(consumer) { - logger.debug('receive() [consumer:%o]', consumer); - - if (this._direction !== 'recv') return _promise2.default.reject(new Error('cannot receive on a sending Transport'));else if (!consumer || consumer.klass !== 'Consumer') return _promise2.default.reject(new TypeError('wrong Consumer')); - - // Enqueue command. - return this._commandQueue.push('addConsumer', { consumer: consumer }); - } - }, { - key: '_handleHandler', - value: function _handleHandler() { - var _this2 = this; - - var handler = this._handler; - - handler.on('@connectionstatechange', function (state) { - if (_this2._connectionState === state) return; - - _this2._connectionState = state; - - if (!_this2._closed) _this2.safeEmit('connectionstatechange', state); - }); - - handler.on('@needcreatetransport', function (transportLocalParameters, callback, errback) { - var data = { - id: _this2._id, - options: _this2._settings.transportOptions, - appData: _this2._appData - }; - - if (transportLocalParameters) data.dtlsParameters = transportLocalParameters.dtlsParameters; - - _this2.safeEmit('@request', 'createTransport', data, callback, errback); - }); - - handler.on('@needupdatetransport', function (transportLocalParameters) { - var data = { - id: _this2._id, - dtlsParameters: transportLocalParameters.dtlsParameters - }; - - _this2.safeEmit('@notify', 'updateTransport', data); - }); - } - }, { - key: '_execCommand', - value: function _execCommand(command, promiseHolder) { - var promise = void 0; - - try { - switch (command.method) { - case 'addProducer': - { - var producer = command.producer; - - - promise = this._execAddProducer(producer); - break; - } - - case 'removeProducer': - { - var _producer = command.producer; - - - promise = this._execRemoveProducer(_producer); - break; - } - - case 'addConsumer': - { - var consumer = command.consumer; - - - promise = this._execAddConsumer(consumer); - break; - } - - case 'removeConsumer': - { - var _consumer = command.consumer; - - - promise = this._execRemoveConsumer(_consumer); - break; - } - - default: - { - promise = _promise2.default.reject(new Error('unknown command method "' + command.method + '"')); - } - } - } catch (error) { - promise = _promise2.default.reject(error); - } - - // Fill the given Promise holder. - promiseHolder.promise = promise; - } - }, { - key: '_execAddProducer', - value: function _execAddProducer(producer) { - var _this3 = this; - - logger.debug('_execAddProducer()'); - - if (producer.closed) return _promise2.default.reject(new Error('Producer closed'));else if (producer.handled) return _promise2.default.reject(new Error('Producer already handled by a Transport')); - - var producerRtpParameters = void 0; - - producer.setHandled('tmp'); - - // Call the handler. - return _promise2.default.resolve().then(function () { - return _this3._handler.addProducer(producer); - }).then(function (rtpParameters) { - producerRtpParameters = rtpParameters; - - var data = { - id: producer.id, - kind: producer.kind, - transportId: _this3._id, - rtpParameters: rtpParameters, - appData: producer.appData - }; - - return _this3.safeEmitAsPromise('@request', 'createProducer', data); - }).then(function () { - producer.setHandled(true, producerRtpParameters); - _this3._producers.set(producer.id, producer); - _this3._handleProducer(producer); - }).catch(function (error) { - producer.setHandled(false); - - throw error; - }); - } - }, { - key: '_execRemoveProducer', - value: function _execRemoveProducer(producer) { - logger.debug('_execRemoveProducer()'); - - // Call the handler. - return this._handler.removeProducer(producer); - } - }, { - key: '_execAddConsumer', - value: function _execAddConsumer(consumer) { - var _this4 = this; - - logger.debug('_execAddConsumer()'); - - if (consumer.closed) return _promise2.default.reject(new Error('Consumer closed'));else if (consumer.handled) return _promise2.default.reject(new Error('Consumer already handled by a Transport')); - - // Check whether we can receive this Consumer. - if (!consumer.supported) { - return _promise2.default.reject(new Error('cannot receive this Consumer, unsupported codecs')); - } - - var consumerTrack = void 0; - - consumer.setHandled('tmp'); - - // Call the handler. - return _promise2.default.resolve().then(function () { - return _this4._handler.addConsumer(consumer); - }).then(function (track) { - consumerTrack = track; - - var data = { - id: consumer.id - }; - - return _this4.safeEmitAsPromise('@request', 'enableConsumer', data); - }).then(function () { - consumer.setHandled(true, consumerTrack); - _this4._consumers.set(consumer.id, consumer); - _this4._handleConsumer(consumer); - - return consumerTrack; - }).catch(function (error) { - consumer.setHandled(false); - - throw error; - }); - } - }, { - key: '_execRemoveConsumer', - value: function _execRemoveConsumer(consumer) { - logger.debug('_execRemoveConsumer()'); - - // Call the handler. - return this._handler.removeConsumer(consumer); - } - }, { - key: '_handleProducer', - value: function _handleProducer(producer) { - var _this5 = this; - - producer.on('@close', function (originator, appData) { - _this5._producers.delete(producer.id); - - // Enqueue command. - _this5._commandQueue.push('removeProducer', { producer: producer }).catch(function () {}); - - if (originator === 'local') { - _this5.safeEmit('@notify', 'closeProducer', { id: producer.id, appData: appData }); - } - }); - - producer.on('@pause', function (appData) { - var data = { - id: producer.id, - appData: appData - }; - - _this5.safeEmit('@notify', 'pauseProducer', data); - }); - - producer.on('@resume', function (appData) { - var data = { - id: producer.id, - appData: appData - }; - - _this5.safeEmit('@notify', 'resumeProducer', data); - }); - } - }, { - key: '_handleConsumer', - value: function _handleConsumer(consumer) { - var _this6 = this; - - consumer.on('@close', function () { - _this6._consumers.delete(consumer.id); - - // Enqueue command. - _this6._commandQueue.push('removeConsumer', { consumer: consumer }).catch(function () {}); - }); - - consumer.on('@pause', function (appData) { - var data = { - id: consumer.id, - appData: appData - }; - - _this6.safeEmit('@notify', 'pauseConsumer', data); - }); - - consumer.on('@resume', function (appData) { - var data = { - id: consumer.id, - appData: appData - }; - - _this6.safeEmit('@notify', 'resumeConsumer', data); - }); - } - }, { - key: 'id', - get: function get() { - return this._id; - } - - /** - * Whether the Transport is closed. - * - * @return {Boolean} - */ - - }, { - key: 'closed', - get: function get() { - return this._closed; - } - - /** - * Transport direction. - * - * @return {String} - */ - - }, { - key: 'direction', - get: function get() { - return this._direction; - } - - /** - * App custom data. - * - * @return {Any} - */ - - }, { - key: 'appData', - get: function get() { - return this._appData; - } - - /** - * Connection state. - * - * @return {String} - */ - - }, { - key: 'connectionState', - get: function get() { - return this._connectionState; - } - }]); - return Transport; -}(_EnhancedEventEmitter3.default); - -exports.default = Transport; - -},{"./CommandQueue":"/Users/ibc/src/mediasoup-client/lib/CommandQueue.js","./Device":"/Users/ibc/src/mediasoup-client/lib/Device.js","./EnhancedEventEmitter":"/Users/ibc/src/mediasoup-client/lib/EnhancedEventEmitter.js","./Logger":"/Users/ibc/src/mediasoup-client/lib/Logger.js","./utils":"/Users/ibc/src/mediasoup-client/lib/utils.js","babel-runtime/core-js/get-iterator":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/core-js/get-iterator.js","babel-runtime/core-js/map":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/core-js/map.js","babel-runtime/core-js/object/get-prototype-of":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/core-js/object/get-prototype-of.js","babel-runtime/core-js/promise":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/core-js/promise.js","babel-runtime/helpers/classCallCheck":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/helpers/classCallCheck.js","babel-runtime/helpers/createClass":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/helpers/createClass.js","babel-runtime/helpers/inherits":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/helpers/inherits.js","babel-runtime/helpers/possibleConstructorReturn":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/helpers/possibleConstructorReturn.js"}],"/Users/ibc/src/mediasoup-client/lib/errors.js":[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.TimeoutError = exports.InvalidStateError = undefined; - -var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); - -var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); - -var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); - -var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); - -var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); - -var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); - -var _inherits2 = require('babel-runtime/helpers/inherits'); - -var _inherits3 = _interopRequireDefault(_inherits2); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * Error produced when calling a method in an invalid state. - */ -var InvalidStateError = exports.InvalidStateError = function (_Error) { - (0, _inherits3.default)(InvalidStateError, _Error); - - function InvalidStateError(message) { - (0, _classCallCheck3.default)(this, InvalidStateError); - - var _this = (0, _possibleConstructorReturn3.default)(this, (InvalidStateError.__proto__ || (0, _getPrototypeOf2.default)(InvalidStateError)).call(this, message)); - - Object.defineProperty(_this, 'name', { - enumerable: false, - writable: false, - value: 'InvalidStateError' - }); - - if (Error.hasOwnProperty('captureStackTrace')) // Just in V8. - { - Error.captureStackTrace(_this, InvalidStateError); - } else { - Object.defineProperty(_this, 'stack', { - enumerable: false, - writable: false, - value: new Error(message).stack - }); - } - return _this; - } - - return InvalidStateError; -}(Error); - -/** - * Error produced when a Promise is rejected due to a timeout. - */ - - -var TimeoutError = exports.TimeoutError = function (_Error2) { - (0, _inherits3.default)(TimeoutError, _Error2); - - function TimeoutError(message) { - (0, _classCallCheck3.default)(this, TimeoutError); - - var _this2 = (0, _possibleConstructorReturn3.default)(this, (TimeoutError.__proto__ || (0, _getPrototypeOf2.default)(TimeoutError)).call(this, message)); - - Object.defineProperty(_this2, 'name', { - enumerable: false, - writable: false, - value: 'TimeoutError' - }); - - if (Error.hasOwnProperty('captureStackTrace')) // Just in V8. - { - Error.captureStackTrace(_this2, TimeoutError); - } else { - Object.defineProperty(_this2, 'stack', { - enumerable: false, - writable: false, - value: new Error(message).stack - }); - } - return _this2; - } - - return TimeoutError; -}(Error); - -},{"babel-runtime/core-js/object/get-prototype-of":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/core-js/object/get-prototype-of.js","babel-runtime/helpers/classCallCheck":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/helpers/classCallCheck.js","babel-runtime/helpers/inherits":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/helpers/inherits.js","babel-runtime/helpers/possibleConstructorReturn":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/helpers/possibleConstructorReturn.js"}],"/Users/ibc/src/mediasoup-client/lib/handlers/Chrome55.js":[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _from = require('babel-runtime/core-js/array/from'); - -var _from2 = _interopRequireDefault(_from); - -var _map = require('babel-runtime/core-js/map'); - -var _map2 = _interopRequireDefault(_map); - -var _set = require('babel-runtime/core-js/set'); - -var _set2 = _interopRequireDefault(_set); - -var _promise = require('babel-runtime/core-js/promise'); - -var _promise2 = _interopRequireDefault(_promise); - -var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); - -var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); - -var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); - -var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); - -var _createClass2 = require('babel-runtime/helpers/createClass'); - -var _createClass3 = _interopRequireDefault(_createClass2); - -var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); - -var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); - -var _inherits2 = require('babel-runtime/helpers/inherits'); - -var _inherits3 = _interopRequireDefault(_inherits2); - -var _sdpTransform = require('sdp-transform'); - -var _sdpTransform2 = _interopRequireDefault(_sdpTransform); - -var _Logger = require('../Logger'); - -var _Logger2 = _interopRequireDefault(_Logger); - -var _EnhancedEventEmitter2 = require('../EnhancedEventEmitter'); - -var _EnhancedEventEmitter3 = _interopRequireDefault(_EnhancedEventEmitter2); - -var _utils = require('../utils'); - -var utils = _interopRequireWildcard(_utils); - -var _commonUtils = require('./sdp/commonUtils'); - -var sdpCommonUtils = _interopRequireWildcard(_commonUtils); - -var _planBUtils = require('./sdp/planBUtils'); - -var sdpPlanBUtils = _interopRequireWildcard(_planBUtils); - -var _RemotePlanBSdp = require('./sdp/RemotePlanBSdp'); - -var _RemotePlanBSdp2 = _interopRequireDefault(_RemotePlanBSdp); - -function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -var logger = new _Logger2.default('Chrome55'); - -var Handler = function (_EnhancedEventEmitter) { - (0, _inherits3.default)(Handler, _EnhancedEventEmitter); - - function Handler(direction, rtpParametersByKind, settings) { - (0, _classCallCheck3.default)(this, Handler); - - // RTCPeerConnection instance. - // @type {RTCPeerConnection} - var _this = (0, _possibleConstructorReturn3.default)(this, (Handler.__proto__ || (0, _getPrototypeOf2.default)(Handler)).call(this)); - - _this._pc = new RTCPeerConnection({ - iceServers: settings.turnServers || [], - iceTransportPolicy: 'relay', - bundlePolicy: 'max-bundle', - rtcpMuxPolicy: 'require' - }); - - // Generic sending RTP parameters for audio and video. - // @type {Object} - _this._rtpParametersByKind = rtpParametersByKind; - - // Remote SDP handler. - // @type {RemotePlanBSdp} - _this._remoteSdp = new _RemotePlanBSdp2.default(direction, rtpParametersByKind); - - // Handle RTCPeerConnection connection status. - _this._pc.addEventListener('iceconnectionstatechange', function () { - switch (_this._pc.iceConnectionState) { - case 'checking': - _this.emit('@connectionstatechange', 'connecting'); - break; - case 'connected': - case 'completed': - _this.emit('@connectionstatechange', 'connected'); - break; - case 'failed': - _this.emit('@connectionstatechange', 'failed'); - break; - case 'disconnected': - _this.emit('@connectionstatechange', 'disconnected'); - break; - case 'closed': - _this.emit('@connectionstatechange', 'closed'); - break; - } - }); - return _this; - } - - (0, _createClass3.default)(Handler, [{ - key: 'close', - value: function close() { - logger.debug('close()'); - - // Close RTCPeerConnection. - try { - this._pc.close(); - } catch (error) {} - } - }]); - return Handler; -}(_EnhancedEventEmitter3.default); - -var SendHandler = function (_Handler) { - (0, _inherits3.default)(SendHandler, _Handler); - - function SendHandler(rtpParametersByKind, settings) { - (0, _classCallCheck3.default)(this, SendHandler); - - // Got transport local and remote parameters. - // @type {Boolean} - var _this2 = (0, _possibleConstructorReturn3.default)(this, (SendHandler.__proto__ || (0, _getPrototypeOf2.default)(SendHandler)).call(this, 'send', rtpParametersByKind, settings)); - - _this2._transportReady = false; - - // Local stream. - // @type {MediaStream} - _this2._stream = new MediaStream(); - return _this2; - } - - (0, _createClass3.default)(SendHandler, [{ - key: 'addProducer', - value: function addProducer(producer) { - var _this3 = this; - - var track = producer.track; - - - logger.debug('addProducer() [id:%s, kind:%s, trackId:%s]', producer.id, producer.kind, track.id); - - var localSdpObj = void 0; - - return _promise2.default.resolve().then(function () { - // Add the track to the local stream. - _this3._stream.addTrack(track); - - // Add the stream to the PeerConnection. - _this3._pc.addStream(_this3._stream); - - return _this3._pc.createOffer(); - }).then(function (offer) { - return _this3._pc.setLocalDescription(offer); - }).then(function () { - if (!_this3._transportReady) return _this3._setupTransport(); - }).then(function () { - localSdpObj = _sdpTransform2.default.parse(_this3._pc.localDescription.sdp); - - var remoteSdp = _this3._remoteSdp.createAnswerSdp(localSdpObj); - var answer = { type: 'answer', sdp: remoteSdp }; - - return _this3._pc.setRemoteDescription(answer); - }).then(function () { - var rtpParameters = utils.clone(_this3._rtpParametersByKind[producer.kind]); - - // Fill the RTP parameters for this track. - sdpPlanBUtils.fillRtpParametersForTrack(rtpParameters, localSdpObj, track); - - return rtpParameters; - }).catch(function (error) { - // Panic here. Try to undo things. - - _this3._stream.removeTrack(track); - _this3._pc.addStream(_this3._stream); - - throw error; - }); - } - }, { - key: 'removeProducer', - value: function removeProducer(producer) { - var _this4 = this; - - var track = producer.track; - - - logger.debug('removeProducer() [id:%s, kind:%s, trackId:%s]', producer.id, producer.kind, track.id); - - return _promise2.default.resolve().then(function () { - // Remove the track from the local stream. - _this4._stream.removeTrack(track); - - // Add the stream to the PeerConnection. - _this4._pc.addStream(_this4._stream); - - return _this4._pc.createOffer(); - }).then(function (offer) { - return _this4._pc.setLocalDescription(offer); - }).catch(function (error) { - // NOTE: If there are no sending tracks, setLocalDescription() will fail with - // "Failed to create channels". If so, ignore it. - if (_this4._stream.getTracks().length === 0) { - logger.warn('removeProducer() | ignoring expected error due no sending tracks: %s', error.toString()); - - return; - } - - throw error; - }).then(function () { - if (_this4._pc.signalingState === 'stable') return; - - var localSdpObj = _sdpTransform2.default.parse(_this4._pc.localDescription.sdp); - var remoteSdp = _this4._remoteSdp.createAnswerSdp(localSdpObj); - var answer = { type: 'answer', sdp: remoteSdp }; - - return _this4._pc.setRemoteDescription(answer); - }); - } - }, { - key: '_setupTransport', - value: function _setupTransport() { - var _this5 = this; - - logger.debug('_setupTransport()'); - - return _promise2.default.resolve().then(function () { - // Get our local DTLS parameters. - var transportLocalParameters = {}; - var sdp = _this5._pc.localDescription.sdp; - var sdpObj = _sdpTransform2.default.parse(sdp); - var dtlsParameters = sdpCommonUtils.extractDtlsParameters(sdpObj); - - // Let's decide that we'll be DTLS server (because we can). - dtlsParameters.role = 'server'; - - transportLocalParameters.dtlsParameters = dtlsParameters; - - // Provide the remote SDP handler with transport local parameters. - _this5._remoteSdp.setTransportLocalParameters(transportLocalParameters); - - // We need transport remote parameters. - return _this5.safeEmitAsPromise('@needcreatetransport', transportLocalParameters); - }).then(function (transportRemoteParameters) { - // Provide the remote SDP handler with transport remote parameters. - _this5._remoteSdp.setTransportRemoteParameters(transportRemoteParameters); - - _this5._transportReady = true; - }); - } - }]); - return SendHandler; -}(Handler); - -var RecvHandler = function (_Handler2) { - (0, _inherits3.default)(RecvHandler, _Handler2); - - function RecvHandler(rtpParametersByKind, settings) { - (0, _classCallCheck3.default)(this, RecvHandler); - - // Got transport remote parameters. - // @type {Boolean} - var _this6 = (0, _possibleConstructorReturn3.default)(this, (RecvHandler.__proto__ || (0, _getPrototypeOf2.default)(RecvHandler)).call(this, 'recv', rtpParametersByKind, settings)); - - _this6._transportCreated = false; - - // Got transport local parameters. - // @type {Boolean} - _this6._transportUpdated = false; - - // Seen media kinds. - // @type {Set} - _this6._kinds = new _set2.default(); - - // Map of Consumers information indexed by consumer.id. - // - kind {String} - // - trackId {String} - // - ssrc {Number} - // - rtxSsrc {Number} - // - cname {String} - // @type {Map} - _this6._consumerInfos = new _map2.default(); - return _this6; - } - - (0, _createClass3.default)(RecvHandler, [{ - key: 'addConsumer', - value: function addConsumer(consumer) { - var _this7 = this; - - logger.debug('addConsumer() [id:%s, kind:%s]', consumer.id, consumer.kind); - - if (this._consumerInfos.has(consumer.id)) return _promise2.default.reject('Consumer already added'); - - var encoding = consumer.rtpParameters.encodings[0]; - var cname = consumer.rtpParameters.rtcp.cname; - var consumerInfo = { - kind: consumer.kind, - trackId: 'consumer-' + consumer.kind + '-' + consumer.id, - ssrc: encoding.ssrc, - cname: cname - }; - - if (encoding.rtx && encoding.rtx.ssrc) consumerInfo.rtxSsrc = encoding.rtx.ssrc; - - this._consumerInfos.set(consumer.id, consumerInfo); - this._kinds.add(consumer.kind); - - return _promise2.default.resolve().then(function () { - if (!_this7._transportCreated) return _this7._setupTransport(); - }).then(function () { - var remoteSdp = _this7._remoteSdp.createOfferSdp((0, _from2.default)(_this7._kinds), (0, _from2.default)(_this7._consumerInfos.values())); - var offer = { type: 'offer', sdp: remoteSdp }; - - return _this7._pc.setRemoteDescription(offer); - }).then(function () { - return _this7._pc.createAnswer(); - }).then(function (answer) { - return _this7._pc.setLocalDescription(answer); - }).then(function () { - if (!_this7._transportUpdated) return _this7._updateTransport(); - }).then(function () { - var stream = _this7._pc.getRemoteStreams()[0]; - var track = stream.getTrackById(consumerInfo.trackId); - - if (!track) throw new Error('remote track not found'); - - return track; - }); - } - }, { - key: 'removeConsumer', - value: function removeConsumer(consumer) { - var _this8 = this; - - logger.debug('removeConsumer() [id:%s, kind:%s]', consumer.id, consumer.kind); - - if (!this._consumerInfos.has(consumer.id)) return _promise2.default.reject('Consumer not found'); - - this._consumerInfos.delete(consumer.id); - - return _promise2.default.resolve().then(function () { - var remoteSdp = _this8._remoteSdp.createOfferSdp((0, _from2.default)(_this8._kinds), (0, _from2.default)(_this8._consumerInfos.values())); - var offer = { type: 'offer', sdp: remoteSdp }; - - return _this8._pc.setRemoteDescription(offer); - }).then(function () { - return _this8._pc.createAnswer(); - }).then(function (answer) { - return _this8._pc.setLocalDescription(answer); - }); - } - }, { - key: '_setupTransport', - value: function _setupTransport() { - var _this9 = this; - - logger.debug('_setupTransport()'); - - return _promise2.default.resolve().then(function () { - // We need transport remote parameters. - return _this9.safeEmitAsPromise('@needcreatetransport', null); - }).then(function (transportRemoteParameters) { - // Provide the remote SDP handler with transport remote parameters. - _this9._remoteSdp.setTransportRemoteParameters(transportRemoteParameters); - - _this9._transportCreated = true; - }); - } - }, { - key: '_updateTransport', - value: function _updateTransport() { - logger.debug('_updateTransport()'); - - // Get our local DTLS parameters. - // const transportLocalParameters = {}; - var sdp = this._pc.localDescription.sdp; - var sdpObj = _sdpTransform2.default.parse(sdp); - var dtlsParameters = sdpCommonUtils.extractDtlsParameters(sdpObj); - var transportLocalParameters = { dtlsParameters: dtlsParameters }; - - // We need to provide transport local parameters. - this.safeEmit('@needupdatetransport', transportLocalParameters); - - this._transportUpdated = true; - } - }]); - return RecvHandler; -}(Handler); - -var Chrome55 = function () { - (0, _createClass3.default)(Chrome55, null, [{ - key: 'getLocalRtpCapabilities', - value: function getLocalRtpCapabilities() { - logger.debug('getLocalRtpCapabilities()'); - - var pc = new RTCPeerConnection({ - iceServers: [], - iceTransportPolicy: 'relay', - bundlePolicy: 'max-bundle', - rtcpMuxPolicy: 'require' - }); - - return pc.createOffer({ - offerToReceiveAudio: true, - offerToReceiveVideo: true - }).then(function (offer) { - try { - pc.close(); - } catch (error) {} - - var sdpObj = _sdpTransform2.default.parse(offer.sdp); - var localRtpCapabilities = sdpCommonUtils.extractRtpCapabilities(sdpObj); - - return localRtpCapabilities; - }).catch(function (error) { - try { - pc.close(); - } catch (error2) {} - - throw error; - }); - } - }, { - key: 'name', - get: function get() { - return 'Chrome55'; - } - }]); - - function Chrome55(direction, extendedRtpCapabilities, settings) { - (0, _classCallCheck3.default)(this, Chrome55); - - logger.debug('constructor() [direction:%s, extendedRtpCapabilities:%o]', direction, extendedRtpCapabilities); - - var rtpParametersByKind = void 0; - - switch (direction) { - case 'send': - { - rtpParametersByKind = { - audio: utils.getSendingRtpParameters('audio', extendedRtpCapabilities), - video: utils.getSendingRtpParameters('video', extendedRtpCapabilities) - }; - - return new SendHandler(rtpParametersByKind, settings); - } - case 'recv': - { - rtpParametersByKind = { - audio: utils.getReceivingFullRtpParameters('audio', extendedRtpCapabilities), - video: utils.getReceivingFullRtpParameters('video', extendedRtpCapabilities) - }; - - return new RecvHandler(rtpParametersByKind, settings); - } - } - } - - return Chrome55; -}(); - -exports.default = Chrome55; - -},{"../EnhancedEventEmitter":"/Users/ibc/src/mediasoup-client/lib/EnhancedEventEmitter.js","../Logger":"/Users/ibc/src/mediasoup-client/lib/Logger.js","../utils":"/Users/ibc/src/mediasoup-client/lib/utils.js","./sdp/RemotePlanBSdp":"/Users/ibc/src/mediasoup-client/lib/handlers/sdp/RemotePlanBSdp.js","./sdp/commonUtils":"/Users/ibc/src/mediasoup-client/lib/handlers/sdp/commonUtils.js","./sdp/planBUtils":"/Users/ibc/src/mediasoup-client/lib/handlers/sdp/planBUtils.js","babel-runtime/core-js/array/from":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/core-js/array/from.js","babel-runtime/core-js/map":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/core-js/map.js","babel-runtime/core-js/object/get-prototype-of":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/core-js/object/get-prototype-of.js","babel-runtime/core-js/promise":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/core-js/promise.js","babel-runtime/core-js/set":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/core-js/set.js","babel-runtime/helpers/classCallCheck":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/helpers/classCallCheck.js","babel-runtime/helpers/createClass":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/helpers/createClass.js","babel-runtime/helpers/inherits":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/helpers/inherits.js","babel-runtime/helpers/possibleConstructorReturn":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/helpers/possibleConstructorReturn.js","sdp-transform":"/Users/ibc/src/mediasoup-client/node_modules/sdp-transform/lib/index.js"}],"/Users/ibc/src/mediasoup-client/lib/handlers/Edge11.js":[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _promise = require('babel-runtime/core-js/promise'); - -var _promise2 = _interopRequireDefault(_promise); - -var _getIterator2 = require('babel-runtime/core-js/get-iterator'); - -var _getIterator3 = _interopRequireDefault(_getIterator2); - -var _map = require('babel-runtime/core-js/map'); - -var _map2 = _interopRequireDefault(_map); - -var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); - -var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); - -var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); - -var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); - -var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); - -var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); - -var _createClass2 = require('babel-runtime/helpers/createClass'); - -var _createClass3 = _interopRequireDefault(_createClass2); - -var _inherits2 = require('babel-runtime/helpers/inherits'); - -var _inherits3 = _interopRequireDefault(_inherits2); - -var _Logger = require('../Logger'); - -var _Logger2 = _interopRequireDefault(_Logger); - -var _EnhancedEventEmitter2 = require('../EnhancedEventEmitter'); - -var _EnhancedEventEmitter3 = _interopRequireDefault(_EnhancedEventEmitter2); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -// import * as utils from '../utils'; - -/* global RTCIceGatherer, RTCIceTransport, RTCDtlsTransport, RTCRtpReceiver */ - -var logger = new _Logger2.default('Edge11'); - -// const CNAME = `cname-${utils.randomNumber()}`; - -var Edge11 = function (_EnhancedEventEmitter) { - (0, _inherits3.default)(Edge11, _EnhancedEventEmitter); - (0, _createClass3.default)(Edge11, null, [{ - key: 'getLocalRtpCapabilities', - value: function getLocalRtpCapabilities() { - logger.debug('getLocalRtpCapabilities()'); - - // TODO: Not enough since Edge does not set mimeType, etc. - return RTCRtpReceiver.getCapabilities(); - } - }, { - key: 'name', - get: function get() { - return 'Edge11'; - } - }]); - - function Edge11(direction, extendedRtpCapabilities, settings) { - (0, _classCallCheck3.default)(this, Edge11); - - logger.debug('constructor() [direction:%s, extendedRtpCapabilities:%o]', direction, extendedRtpCapabilities); - - // Got transport local and remote parameters. - // @type {Boolean} - var _this = (0, _possibleConstructorReturn3.default)(this, (Edge11.__proto__ || (0, _getPrototypeOf2.default)(Edge11)).call(this)); - - _this._transportReady = false; - - // ICE gatherer. - _this._iceGatherer = null; - - // ICE transport. - _this._iceTransport = null; - - // DTLS transport. - // @type {RTCDtlsTransport} - _this._dtlsTransport = null; - - // Map of RTCRtpSenders indexed by Producer.id. - // @type {Map} - _this6._consumerInfos = new _map2.default(); - return _this6; - } - - (0, _createClass3.default)(RecvHandler, [{ - key: 'addConsumer', - value: function addConsumer(consumer) { - var _this7 = this; - - logger.debug('addConsumer() [id:%s, kind:%s]', consumer.id, consumer.kind); - - if (this._consumerInfos.has(consumer.id)) return _promise2.default.reject('Consumer already added'); - - var encoding = consumer.rtpParameters.encodings[0]; - var cname = consumer.rtpParameters.rtcp.cname; - var consumerInfo = { - mid: 'consumer-' + consumer.kind + '-' + consumer.id, - kind: consumer.kind, - closed: consumer.closed, - trackId: 'consumer-' + consumer.kind + '-' + consumer.id, - ssrc: encoding.ssrc, - cname: cname - }; - - if (encoding.rtx && encoding.rtx.ssrc) consumerInfo.rtxSsrc = encoding.rtx.ssrc; - - this._consumerInfos.set(consumer.id, consumerInfo); - - return _promise2.default.resolve().then(function () { - if (!_this7._transportCreated) return _this7._setupTransport(); - }).then(function () { - var remoteSdp = _this7._remoteSdp.createOfferSdp((0, _from2.default)(_this7._consumerInfos.values())); - var offer = { type: 'offer', sdp: remoteSdp }; - - return _this7._pc.setRemoteDescription(offer); - }).then(function () { - return _this7._pc.createAnswer(); - }).then(function (answer) { - return _this7._pc.setLocalDescription(answer); - }).then(function () { - if (!_this7._transportUpdated) return _this7._updateTransport(); - }).then(function () { - var newRtpReceiver = _this7._pc.getReceivers().find(function (rtpReceiver) { - var track = rtpReceiver.track; - - - if (!track) return false; - - return track.id === consumerInfo.trackId; - }); - - if (!newRtpReceiver) throw new Error('remote track not found'); - - return newRtpReceiver.track; - }); - } - }, { - key: 'removeConsumer', - value: function removeConsumer(consumer) { - var _this8 = this; - - // TODO: If this is the last active Consumer, Firefox will close the DTLS. - // This is noted in the TODO.md file. - - logger.debug('removeConsumer() [id:%s, kind:%s]', consumer.id, consumer.kind); - - var consumerInfo = this._consumerInfos.get(consumer.id); - - if (!consumerInfo) return _promise2.default.reject('Consumer not found'); - - consumerInfo.closed = true; - - return _promise2.default.resolve().then(function () { - var remoteSdp = _this8._remoteSdp.createOfferSdp((0, _from2.default)(_this8._consumerInfos.values())); - var offer = { type: 'offer', sdp: remoteSdp }; - - return _this8._pc.setRemoteDescription(offer); - }).then(function () { - return _this8._pc.createAnswer(); - }).then(function (answer) { - return _this8._pc.setLocalDescription(answer); - }); - } - }, { - key: '_setupTransport', - value: function _setupTransport() { - var _this9 = this; - - logger.debug('_setupTransport()'); - - return _promise2.default.resolve().then(function () { - // We need transport remote parameters. - return _this9.safeEmitAsPromise('@needcreatetransport', null); - }).then(function (transportRemoteParameters) { - // Provide the remote SDP handler with transport remote parameters. - _this9._remoteSdp.setTransportRemoteParameters(transportRemoteParameters); - - _this9._transportCreated = true; - }); - } - }, { - key: '_updateTransport', - value: function _updateTransport() { - logger.debug('_updateTransport()'); - - // Get our local DTLS parameters. - // const transportLocalParameters = {}; - var sdp = this._pc.localDescription.sdp; - var sdpObj = _sdpTransform2.default.parse(sdp); - var dtlsParameters = sdpCommonUtils.extractDtlsParameters(sdpObj); - var transportLocalParameters = { dtlsParameters: dtlsParameters }; - - // We need to provide transport local parameters. - this.safeEmit('@needupdatetransport', transportLocalParameters); - - this._transportUpdated = true; - } - }]); - return RecvHandler; -}(Handler); - -var Firefox50 = function () { - (0, _createClass3.default)(Firefox50, null, [{ - key: 'getLocalRtpCapabilities', - value: function getLocalRtpCapabilities() { - logger.debug('getLocalRtpCapabilities()'); - - var pc = new RTCPeerConnection({ - iceServers: [], - iceTransportPolicy: 'relay', - bundlePolicy: 'max-bundle', - rtcpMuxPolicy: 'require' - }); - - return pc.createOffer({ - offerToReceiveAudio: true, - offerToReceiveVideo: true - }).then(function (offer) { - try { - pc.close(); - } catch (error) {} - - var sdpObj = _sdpTransform2.default.parse(offer.sdp); - var localRtpCapabilities = sdpCommonUtils.extractRtpCapabilities(sdpObj); - - return localRtpCapabilities; - }).catch(function (error) { - try { - pc.close(); - } catch (error2) {} - - throw error; - }); - } - }, { - key: 'name', - get: function get() { - return 'Firefox50'; - } - }]); - - function Firefox50(direction, extendedRtpCapabilities, settings) { - (0, _classCallCheck3.default)(this, Firefox50); - - logger.debug('constructor() [direction:%s, extendedRtpCapabilities:%o]', direction, extendedRtpCapabilities); - - var rtpParametersByKind = void 0; - - switch (direction) { - case 'send': - { - rtpParametersByKind = { - audio: utils.getSendingRtpParameters('audio', extendedRtpCapabilities), - video: utils.getSendingRtpParameters('video', extendedRtpCapabilities) - }; - - return new SendHandler(rtpParametersByKind, settings); - } - case 'recv': - { - rtpParametersByKind = { - audio: utils.getReceivingFullRtpParameters('audio', extendedRtpCapabilities), - video: utils.getReceivingFullRtpParameters('video', extendedRtpCapabilities) - }; - - return new RecvHandler(rtpParametersByKind, settings); - } - } - } - - return Firefox50; -}(); - -exports.default = Firefox50; - -},{"../EnhancedEventEmitter":"/Users/ibc/src/mediasoup-client/lib/EnhancedEventEmitter.js","../Logger":"/Users/ibc/src/mediasoup-client/lib/Logger.js","../utils":"/Users/ibc/src/mediasoup-client/lib/utils.js","./sdp/RemoteUnifiedPlanSdp":"/Users/ibc/src/mediasoup-client/lib/handlers/sdp/RemoteUnifiedPlanSdp.js","./sdp/commonUtils":"/Users/ibc/src/mediasoup-client/lib/handlers/sdp/commonUtils.js","./sdp/unifiedPlanUtils":"/Users/ibc/src/mediasoup-client/lib/handlers/sdp/unifiedPlanUtils.js","babel-runtime/core-js/array/from":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/core-js/array/from.js","babel-runtime/core-js/map":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/core-js/map.js","babel-runtime/core-js/object/get-prototype-of":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/core-js/object/get-prototype-of.js","babel-runtime/core-js/promise":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/core-js/promise.js","babel-runtime/helpers/classCallCheck":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/helpers/classCallCheck.js","babel-runtime/helpers/createClass":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/helpers/createClass.js","babel-runtime/helpers/inherits":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/helpers/inherits.js","babel-runtime/helpers/possibleConstructorReturn":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/helpers/possibleConstructorReturn.js","sdp-transform":"/Users/ibc/src/mediasoup-client/node_modules/sdp-transform/lib/index.js"}],"/Users/ibc/src/mediasoup-client/lib/handlers/Safari11.js":[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _from = require('babel-runtime/core-js/array/from'); - -var _from2 = _interopRequireDefault(_from); - -var _map = require('babel-runtime/core-js/map'); - -var _map2 = _interopRequireDefault(_map); - -var _set = require('babel-runtime/core-js/set'); - -var _set2 = _interopRequireDefault(_set); - -var _promise = require('babel-runtime/core-js/promise'); - -var _promise2 = _interopRequireDefault(_promise); - -var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); - -var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); - -var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); - -var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); - -var _createClass2 = require('babel-runtime/helpers/createClass'); - -var _createClass3 = _interopRequireDefault(_createClass2); - -var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); - -var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); - -var _inherits2 = require('babel-runtime/helpers/inherits'); - -var _inherits3 = _interopRequireDefault(_inherits2); - -var _sdpTransform = require('sdp-transform'); - -var _sdpTransform2 = _interopRequireDefault(_sdpTransform); - -var _Logger = require('../Logger'); - -var _Logger2 = _interopRequireDefault(_Logger); - -var _EnhancedEventEmitter2 = require('../EnhancedEventEmitter'); - -var _EnhancedEventEmitter3 = _interopRequireDefault(_EnhancedEventEmitter2); - -var _utils = require('../utils'); - -var utils = _interopRequireWildcard(_utils); - -var _commonUtils = require('./sdp/commonUtils'); - -var sdpCommonUtils = _interopRequireWildcard(_commonUtils); - -var _planBUtils = require('./sdp/planBUtils'); - -var sdpPlanBUtils = _interopRequireWildcard(_planBUtils); - -var _RemotePlanBSdp = require('./sdp/RemotePlanBSdp'); - -var _RemotePlanBSdp2 = _interopRequireDefault(_RemotePlanBSdp); - -function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -var logger = new _Logger2.default('Safari11'); - -var Handler = function (_EnhancedEventEmitter) { - (0, _inherits3.default)(Handler, _EnhancedEventEmitter); - - function Handler(direction, rtpParametersByKind, settings) { - (0, _classCallCheck3.default)(this, Handler); - - // RTCPeerConnection instance. - // @type {RTCPeerConnection} - var _this = (0, _possibleConstructorReturn3.default)(this, (Handler.__proto__ || (0, _getPrototypeOf2.default)(Handler)).call(this)); - - _this._pc = new RTCPeerConnection({ - iceServers: settings.turnServers || [], - iceTransportPolicy: 'relay', - bundlePolicy: 'max-bundle', - rtcpMuxPolicy: 'require' - }); - - // Generic sending RTP parameters for audio and video. - // @type {Object} - _this._rtpParametersByKind = rtpParametersByKind; - - // Remote SDP handler. - // @type {RemotePlanBSdp} - _this._remoteSdp = new _RemotePlanBSdp2.default(direction, rtpParametersByKind); - - // Handle RTCPeerConnection connection status. - _this._pc.addEventListener('iceconnectionstatechange', function () { - switch (_this._pc.iceConnectionState) { - case 'checking': - _this.emit('@connectionstatechange', 'connecting'); - break; - case 'connected': - case 'completed': - _this.emit('@connectionstatechange', 'connected'); - break; - case 'failed': - _this.emit('@connectionstatechange', 'failed'); - break; - case 'disconnected': - _this.emit('@connectionstatechange', 'disconnected'); - break; - case 'closed': - _this.emit('@connectionstatechange', 'closed'); - break; - } - }); - return _this; - } - - (0, _createClass3.default)(Handler, [{ - key: 'close', - value: function close() { - logger.debug('close()'); - - // Close RTCPeerConnection. - try { - this._pc.close(); - } catch (error) {} - } - }]); - return Handler; -}(_EnhancedEventEmitter3.default); - -var SendHandler = function (_Handler) { - (0, _inherits3.default)(SendHandler, _Handler); - - function SendHandler(rtpParametersByKind, settings) { - (0, _classCallCheck3.default)(this, SendHandler); - - // Got transport local and remote parameters. - // @type {Boolean} - var _this2 = (0, _possibleConstructorReturn3.default)(this, (SendHandler.__proto__ || (0, _getPrototypeOf2.default)(SendHandler)).call(this, 'send', rtpParametersByKind, settings)); - - _this2._transportReady = false; - - // Local stream. - // @type {MediaStream} - _this2._stream = new MediaStream(); - return _this2; - } - - (0, _createClass3.default)(SendHandler, [{ - key: 'addProducer', - value: function addProducer(producer) { - var _this3 = this; - - var track = producer.track; - - - logger.debug('addProducer() [id:%s, kind:%s, trackId:%s]', producer.id, producer.kind, track.id); - - var rtpSender = void 0; - var localSdpObj = void 0; - - return _promise2.default.resolve().then(function () { - _this3._stream.addTrack(track); - - // Add the stream to the PeerConnection. - rtpSender = _this3._pc.addTrack(track, _this3._stream); - - return _this3._pc.createOffer(); - }).then(function (offer) { - return _this3._pc.setLocalDescription(offer); - }).then(function () { - if (!_this3._transportReady) return _this3._setupTransport(); - }).then(function () { - localSdpObj = _sdpTransform2.default.parse(_this3._pc.localDescription.sdp); - - var remoteSdp = _this3._remoteSdp.createAnswerSdp(localSdpObj); - var answer = { type: 'answer', sdp: remoteSdp }; - - return _this3._pc.setRemoteDescription(answer); - }).then(function () { - var rtpParameters = utils.clone(_this3._rtpParametersByKind[producer.kind]); - - // Fill the RTP parameters for this track. - sdpPlanBUtils.fillRtpParametersForTrack(rtpParameters, localSdpObj, track); - - return rtpParameters; - }).catch(function (error) { - // Panic here. Try to undo things. - - try { - _this3._pc.removeTrack(rtpSender); - } catch (error2) {} - - _this3._stream.removeTrack(track); - - throw error; - }); - } - }, { - key: 'removeProducer', - value: function removeProducer(producer) { - var _this4 = this; - - var track = producer.track; - - - logger.debug('removeProducer() [id:%s, kind:%s, trackId:%s]', producer.id, producer.kind, track.id); - - return _promise2.default.resolve().then(function () { - // Get the associated RTCRtpSender. - var rtpSender = _this4._pc.getSenders().find(function (s) { - return s.track === track; - }); - - if (!rtpSender) throw new Error('local track not found'); - - // Remove the associated RtpSender. - _this4._pc.removeTrack(rtpSender); - - // Remove the track from the local stream. - _this4._stream.removeTrack(track); - - return _this4._pc.createOffer(); - }).then(function (offer) { - return _this4._pc.setLocalDescription(offer); - }).catch(function (error) { - // NOTE: If there are no sending tracks, setLocalDescription() will fail with - // "Failed to create channels". If so, ignore it. - if (_this4._stream.getTracks().length === 0) { - logger.warn('removeLocalTrack() | ignoring expected error due no sending tracks: %s', error.toString()); - - return; - } - - throw error; - }).then(function () { - if (_this4._pc.signalingState === 'stable') return; - - var localSdpObj = _sdpTransform2.default.parse(_this4._pc.localDescription.sdp); - var remoteSdp = _this4._remoteSdp.createAnswerSdp(localSdpObj); - var answer = { type: 'answer', sdp: remoteSdp }; - - return _this4._pc.setRemoteDescription(answer); - }); - } - }, { - key: '_setupTransport', - value: function _setupTransport() { - var _this5 = this; - - logger.debug('_setupTransport()'); - - return _promise2.default.resolve().then(function () { - // Get our local DTLS parameters. - var transportLocalParameters = {}; - var sdp = _this5._pc.localDescription.sdp; - var sdpObj = _sdpTransform2.default.parse(sdp); - var dtlsParameters = sdpCommonUtils.extractDtlsParameters(sdpObj); - - // Let's decide that we'll be DTLS server (because we can). - dtlsParameters.role = 'server'; - - transportLocalParameters.dtlsParameters = dtlsParameters; - - // Provide the remote SDP handler with transport local parameters. - _this5._remoteSdp.setTransportLocalParameters(transportLocalParameters); - - // We need transport remote parameters. - return _this5.safeEmitAsPromise('@needcreatetransport', transportLocalParameters); - }).then(function (transportRemoteParameters) { - // Provide the remote SDP handler with transport remote parameters. - _this5._remoteSdp.setTransportRemoteParameters(transportRemoteParameters); - - _this5._transportReady = true; - }); - } - }]); - return SendHandler; -}(Handler); - -var RecvHandler = function (_Handler2) { - (0, _inherits3.default)(RecvHandler, _Handler2); - - function RecvHandler(rtpParametersByKind, settings) { - (0, _classCallCheck3.default)(this, RecvHandler); - - // Got transport remote parameters. - // @type {Boolean} - var _this6 = (0, _possibleConstructorReturn3.default)(this, (RecvHandler.__proto__ || (0, _getPrototypeOf2.default)(RecvHandler)).call(this, 'recv', rtpParametersByKind, settings)); - - _this6._transportCreated = false; - - // Got transport local parameters. - // @type {Boolean} - _this6._transportUpdated = false; - - // Seen media kinds. - // @type {Set} - _this6._kinds = new _set2.default(); - - // Map of Consumers information indexed by consumer.id. - // - kind {String} - // - trackId {String} - // - ssrc {Number} - // - rtxSsrc {Number} - // - cname {String} - // @type {Map} - _this6._consumerInfos = new _map2.default(); - return _this6; - } - - (0, _createClass3.default)(RecvHandler, [{ - key: 'addConsumer', - value: function addConsumer(consumer) { - var _this7 = this; - - logger.debug('addConsumer() [id:%s, kind:%s]', consumer.id, consumer.kind); - - if (this._consumerInfos.has(consumer.id)) return _promise2.default.reject('Consumer already added'); - - var encoding = consumer.rtpParameters.encodings[0]; - var cname = consumer.rtpParameters.rtcp.cname; - var consumerInfo = { - kind: consumer.kind, - trackId: 'consumer-' + consumer.kind + '-' + consumer.id, - ssrc: encoding.ssrc, - cname: cname - }; - - if (encoding.rtx && encoding.rtx.ssrc) consumerInfo.rtxSsrc = encoding.rtx.ssrc; - - this._consumerInfos.set(consumer.id, consumerInfo); - this._kinds.add(consumer.kind); - - return _promise2.default.resolve().then(function () { - if (!_this7._transportCreated) return _this7._setupTransport(); - }).then(function () { - var remoteSdp = _this7._remoteSdp.createOfferSdp((0, _from2.default)(_this7._kinds), (0, _from2.default)(_this7._consumerInfos.values())); - var offer = { type: 'offer', sdp: remoteSdp }; - - return _this7._pc.setRemoteDescription(offer); - }).then(function () { - return _this7._pc.createAnswer(); - }).then(function (answer) { - return _this7._pc.setLocalDescription(answer); - }).then(function () { - if (!_this7._transportUpdated) return _this7._updateTransport(); - }).then(function () { - var newRtpReceiver = _this7._pc.getReceivers().find(function (rtpReceiver) { - var track = rtpReceiver.track; - - - if (!track) return false; - - return track.id === consumerInfo.trackId; - }); - - if (!newRtpReceiver) throw new Error('remote track not found'); - - return newRtpReceiver.track; - }); - } - }, { - key: 'removeConsumer', - value: function removeConsumer(consumer) { - var _this8 = this; - - logger.debug('removeConsumer() [id:%s, kind:%s]', consumer.id, consumer.kind); - - if (!this._consumerInfos.has(consumer.id)) return _promise2.default.reject('Consumer not found'); - - this._consumerInfos.delete(consumer.id); - - return _promise2.default.resolve().then(function () { - var remoteSdp = _this8._remoteSdp.createOfferSdp((0, _from2.default)(_this8._kinds), (0, _from2.default)(_this8._consumerInfos.values())); - var offer = { type: 'offer', sdp: remoteSdp }; - - return _this8._pc.setRemoteDescription(offer); - }).then(function () { - return _this8._pc.createAnswer(); - }).then(function (answer) { - return _this8._pc.setLocalDescription(answer); - }); - } - }, { - key: '_setupTransport', - value: function _setupTransport() { - var _this9 = this; - - logger.debug('_setupTransport()'); - - return _promise2.default.resolve().then(function () { - // We need transport remote parameters. - return _this9.safeEmitAsPromise('@needcreatetransport', null); - }).then(function (transportRemoteParameters) { - // Provide the remote SDP handler with transport remote parameters. - _this9._remoteSdp.setTransportRemoteParameters(transportRemoteParameters); - - _this9._transportCreated = true; - }); - } - }, { - key: '_updateTransport', - value: function _updateTransport() { - logger.debug('_updateTransport()'); - - // Get our local DTLS parameters. - // const transportLocalParameters = {}; - var sdp = this._pc.localDescription.sdp; - var sdpObj = _sdpTransform2.default.parse(sdp); - var dtlsParameters = sdpCommonUtils.extractDtlsParameters(sdpObj); - var transportLocalParameters = { dtlsParameters: dtlsParameters }; - - // We need to provide transport local parameters. - this.safeEmit('@needupdatetransport', transportLocalParameters); - - this._transportUpdated = true; - } - }]); - return RecvHandler; -}(Handler); - -var Safari11 = function () { - (0, _createClass3.default)(Safari11, null, [{ - key: 'getLocalRtpCapabilities', - value: function getLocalRtpCapabilities() { - logger.debug('getLocalRtpCapabilities()'); - - var pc = new RTCPeerConnection({ - iceServers: [], - iceTransportPolicy: 'relay', - bundlePolicy: 'max-bundle', - rtcpMuxPolicy: 'require' - }); - - pc.addTransceiver('audio'); - pc.addTransceiver('video'); - - return pc.createOffer().then(function (offer) { - try { - pc.close(); - } catch (error) {} - - var sdpObj = _sdpTransform2.default.parse(offer.sdp); - var localRtpCapabilities = sdpCommonUtils.extractRtpCapabilities(sdpObj); - - return localRtpCapabilities; - }).catch(function (error) { - try { - pc.close(); - } catch (error2) {} - - throw error; - }); - } - }, { - key: 'name', - get: function get() { - return 'Safari11'; - } - }]); - - function Safari11(direction, extendedRtpCapabilities, settings) { - (0, _classCallCheck3.default)(this, Safari11); - - logger.debug('constructor() [direction:%s, extendedRtpCapabilities:%o]', direction, extendedRtpCapabilities); - - var rtpParametersByKind = void 0; - - switch (direction) { - case 'send': - { - rtpParametersByKind = { - audio: utils.getSendingRtpParameters('audio', extendedRtpCapabilities), - video: utils.getSendingRtpParameters('video', extendedRtpCapabilities) - }; - - return new SendHandler(rtpParametersByKind, settings); - } - case 'recv': - { - rtpParametersByKind = { - audio: utils.getReceivingFullRtpParameters('audio', extendedRtpCapabilities), - video: utils.getReceivingFullRtpParameters('video', extendedRtpCapabilities) - }; - - return new RecvHandler(rtpParametersByKind, settings); - } - } - } - - return Safari11; -}(); - -exports.default = Safari11; - -},{"../EnhancedEventEmitter":"/Users/ibc/src/mediasoup-client/lib/EnhancedEventEmitter.js","../Logger":"/Users/ibc/src/mediasoup-client/lib/Logger.js","../utils":"/Users/ibc/src/mediasoup-client/lib/utils.js","./sdp/RemotePlanBSdp":"/Users/ibc/src/mediasoup-client/lib/handlers/sdp/RemotePlanBSdp.js","./sdp/commonUtils":"/Users/ibc/src/mediasoup-client/lib/handlers/sdp/commonUtils.js","./sdp/planBUtils":"/Users/ibc/src/mediasoup-client/lib/handlers/sdp/planBUtils.js","babel-runtime/core-js/array/from":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/core-js/array/from.js","babel-runtime/core-js/map":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/core-js/map.js","babel-runtime/core-js/object/get-prototype-of":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/core-js/object/get-prototype-of.js","babel-runtime/core-js/promise":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/core-js/promise.js","babel-runtime/core-js/set":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/core-js/set.js","babel-runtime/helpers/classCallCheck":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/helpers/classCallCheck.js","babel-runtime/helpers/createClass":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/helpers/createClass.js","babel-runtime/helpers/inherits":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/helpers/inherits.js","babel-runtime/helpers/possibleConstructorReturn":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/helpers/possibleConstructorReturn.js","sdp-transform":"/Users/ibc/src/mediasoup-client/node_modules/sdp-transform/lib/index.js"}],"/Users/ibc/src/mediasoup-client/lib/handlers/sdp/RemotePlanBSdp.js":[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _keys = require('babel-runtime/core-js/object/keys'); - -var _keys2 = _interopRequireDefault(_keys); - -var _getIterator2 = require('babel-runtime/core-js/get-iterator'); - -var _getIterator3 = _interopRequireDefault(_getIterator2); - -var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); - -var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); - -var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); - -var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); - -var _inherits2 = require('babel-runtime/helpers/inherits'); - -var _inherits3 = _interopRequireDefault(_inherits2); - -var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); - -var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); - -var _createClass2 = require('babel-runtime/helpers/createClass'); - -var _createClass3 = _interopRequireDefault(_createClass2); - -var _sdpTransform = require('sdp-transform'); - -var _sdpTransform2 = _interopRequireDefault(_sdpTransform); - -var _Logger = require('../../Logger'); - -var _Logger2 = _interopRequireDefault(_Logger); - -var _utils = require('../../utils'); - -var utils = _interopRequireWildcard(_utils); - -function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -var logger = new _Logger2.default('RemotePlanBSdp'); - -var RemoteSdp = function () { - function RemoteSdp(rtpParametersByKind) { - (0, _classCallCheck3.default)(this, RemoteSdp); - - // Generic sending RTP parameters for audio and video. - // @type {Object} - this._rtpParametersByKind = rtpParametersByKind; - - // Transport local parameters, including DTLS parameteres. - // @type {Object} - this._transportLocalParameters = null; - - // Transport remote parameters, including ICE parameters, ICE candidates - // and DTLS parameteres. - // @type {Object} - this._transportRemoteParameters = null; - - // SDP global fields. - // @type {Object} - this._sdpGlobalFields = { - id: utils.randomNumber(), - version: 0 - }; - } - - (0, _createClass3.default)(RemoteSdp, [{ - key: 'setTransportLocalParameters', - value: function setTransportLocalParameters(transportLocalParameters) { - logger.debug('setTransportLocalParameters() [transportLocalParameters:%o]', transportLocalParameters); - - this._transportLocalParameters = transportLocalParameters; - } - }, { - key: 'setTransportRemoteParameters', - value: function setTransportRemoteParameters(transportRemoteParameters) { - logger.debug('setTransportRemoteParameters() [transportRemoteParameters:%o]', transportRemoteParameters); - - this._transportRemoteParameters = transportRemoteParameters; - } - }]); - return RemoteSdp; -}(); - -var SendRemoteSdp = function (_RemoteSdp) { - (0, _inherits3.default)(SendRemoteSdp, _RemoteSdp); - - function SendRemoteSdp(rtpParametersByKind) { - (0, _classCallCheck3.default)(this, SendRemoteSdp); - return (0, _possibleConstructorReturn3.default)(this, (SendRemoteSdp.__proto__ || (0, _getPrototypeOf2.default)(SendRemoteSdp)).call(this, rtpParametersByKind)); - } - - (0, _createClass3.default)(SendRemoteSdp, [{ - key: 'createAnswerSdp', - value: function createAnswerSdp(localSdpObj) { - logger.debug('createAnswerSdp()'); - - if (!this._transportLocalParameters) throw new Error('no transport local parameters');else if (!this._transportRemoteParameters) throw new Error('no transport remote parameters'); - - var localDtlsParameters = this._transportLocalParameters.dtlsParameters; - var remoteIceParameters = this._transportRemoteParameters.iceParameters; - var remoteIceCandidates = this._transportRemoteParameters.iceCandidates; - var remoteDtlsParameters = this._transportRemoteParameters.dtlsParameters; - var sdpObj = {}; - var mids = (localSdpObj.media || []).map(function (m) { - return m.mid; - }); - - // Increase our SDP version. - this._sdpGlobalFields.version++; - - sdpObj.version = 0; - sdpObj.origin = { - address: '0.0.0.0', - ipVer: 4, - netType: 'IN', - sessionId: this._sdpGlobalFields.id, - sessionVersion: this._sdpGlobalFields.version, - username: 'mediasoup-client' - }; - sdpObj.name = '-'; - sdpObj.timing = { start: 0, stop: 0 }; - sdpObj.icelite = remoteIceParameters.iceLite ? 'ice-lite' : null; - sdpObj.msidSemantic = { - semantic: 'WMS', - token: '*' - }; - sdpObj.groups = [{ - type: 'BUNDLE', - mids: mids.join(' ') - }]; - sdpObj.media = []; - - sdpObj.fingerprint = { - type: remoteDtlsParameters.fingerprints[0].algorithm, - hash: remoteDtlsParameters.fingerprints[0].value - }; - - var _iteratorNormalCompletion = true; - var _didIteratorError = false; - var _iteratorError = undefined; - - try { - for (var _iterator = (0, _getIterator3.default)(localSdpObj.media || []), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { - var localMediaObj = _step.value; - - var kind = localMediaObj.type; - var codecs = this._rtpParametersByKind[kind].codecs; - var headerExtensions = this._rtpParametersByKind[kind].headerExtensions; - var remoteMediaObj = {}; - - remoteMediaObj.type = localMediaObj.type; - remoteMediaObj.port = 7; - remoteMediaObj.protocol = 'RTP/SAVPF'; - remoteMediaObj.connection = { ip: '127.0.0.1', version: 4 }; - remoteMediaObj.mid = localMediaObj.mid; - - remoteMediaObj.iceUfrag = remoteIceParameters.usernameFragment; - remoteMediaObj.icePwd = remoteIceParameters.password; - remoteMediaObj.candidates = []; - - var _iteratorNormalCompletion2 = true; - var _didIteratorError2 = false; - var _iteratorError2 = undefined; - - try { - for (var _iterator2 = (0, _getIterator3.default)(remoteIceCandidates), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { - var candidate = _step2.value; - - var candidateObj = {}; - - // mediasoup does not support non rtcp-mux so candidates component is - // always RTP (1). - candidateObj.component = 1; - candidateObj.foundation = candidate.foundation; - candidateObj.ip = candidate.ip; - candidateObj.port = candidate.port; - candidateObj.priority = candidate.priority; - candidateObj.transport = candidate.protocol; - candidateObj.type = candidate.type; - if (candidate.tcpType) candidateObj.tcptype = candidate.tcpType; - - remoteMediaObj.candidates.push(candidateObj); - } - } catch (err) { - _didIteratorError2 = true; - _iteratorError2 = err; - } finally { - try { - if (!_iteratorNormalCompletion2 && _iterator2.return) { - _iterator2.return(); - } - } finally { - if (_didIteratorError2) { - throw _iteratorError2; - } - } - } - - remoteMediaObj.endOfCandidates = 'end-of-candidates'; - - // Announce support for ICE renomination. - // https://tools.ietf.org/html/draft-thatcher-ice-renomination - remoteMediaObj.iceOptions = 'renomination'; - - switch (localDtlsParameters.role) { - case 'client': - remoteMediaObj.setup = 'active'; - break; - case 'server': - remoteMediaObj.setup = 'passive'; - break; - } - - switch (localMediaObj.direction) { - case 'sendrecv': - case 'sendonly': - remoteMediaObj.direction = 'recvonly'; - break; - case 'recvonly': - case 'inactive': - remoteMediaObj.direction = 'inactive'; - break; - } - - remoteMediaObj.rtp = []; - remoteMediaObj.rtcpFb = []; - remoteMediaObj.fmtp = []; - - var _iteratorNormalCompletion3 = true; - var _didIteratorError3 = false; - var _iteratorError3 = undefined; - - try { - for (var _iterator3 = (0, _getIterator3.default)(codecs), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) { - var codec = _step3.value; - - var rtp = { - payload: codec.payloadType, - codec: codec.name, - rate: codec.clockRate - }; - - if (codec.channels > 1) rtp.encoding = codec.channels; - - remoteMediaObj.rtp.push(rtp); - - if (codec.parameters) { - var paramFmtp = { - payload: codec.payloadType, - config: '' - }; - - var _iteratorNormalCompletion5 = true; - var _didIteratorError5 = false; - var _iteratorError5 = undefined; - - try { - for (var _iterator5 = (0, _getIterator3.default)((0, _keys2.default)(codec.parameters)), _step5; !(_iteratorNormalCompletion5 = (_step5 = _iterator5.next()).done); _iteratorNormalCompletion5 = true) { - var key = _step5.value; - - if (paramFmtp.config) paramFmtp.config += ';'; - - paramFmtp.config += key + '=' + codec.parameters[key]; - } - } catch (err) { - _didIteratorError5 = true; - _iteratorError5 = err; - } finally { - try { - if (!_iteratorNormalCompletion5 && _iterator5.return) { - _iterator5.return(); - } - } finally { - if (_didIteratorError5) { - throw _iteratorError5; - } - } - } - - if (paramFmtp.config) remoteMediaObj.fmtp.push(paramFmtp); - } - - if (codec.rtcpFeedback) { - var _iteratorNormalCompletion6 = true; - var _didIteratorError6 = false; - var _iteratorError6 = undefined; - - try { - for (var _iterator6 = (0, _getIterator3.default)(codec.rtcpFeedback), _step6; !(_iteratorNormalCompletion6 = (_step6 = _iterator6.next()).done); _iteratorNormalCompletion6 = true) { - var fb = _step6.value; - - remoteMediaObj.rtcpFb.push({ - payload: codec.payloadType, - type: fb.type, - subtype: fb.parameter - }); - } - } catch (err) { - _didIteratorError6 = true; - _iteratorError6 = err; - } finally { - try { - if (!_iteratorNormalCompletion6 && _iterator6.return) { - _iterator6.return(); - } - } finally { - if (_didIteratorError6) { - throw _iteratorError6; - } - } - } - } - } - } catch (err) { - _didIteratorError3 = true; - _iteratorError3 = err; - } finally { - try { - if (!_iteratorNormalCompletion3 && _iterator3.return) { - _iterator3.return(); - } - } finally { - if (_didIteratorError3) { - throw _iteratorError3; - } - } - } - - remoteMediaObj.payloads = codecs.map(function (codec) { - return codec.payloadType; - }).join(' '); - - remoteMediaObj.ext = []; - - var _iteratorNormalCompletion4 = true; - var _didIteratorError4 = false; - var _iteratorError4 = undefined; - - try { - for (var _iterator4 = (0, _getIterator3.default)(headerExtensions), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) { - var ext = _step4.value; - - remoteMediaObj.ext.push({ - uri: ext.uri, - value: ext.id - }); - } - } catch (err) { - _didIteratorError4 = true; - _iteratorError4 = err; - } finally { - try { - if (!_iteratorNormalCompletion4 && _iterator4.return) { - _iterator4.return(); - } - } finally { - if (_didIteratorError4) { - throw _iteratorError4; - } - } - } - - remoteMediaObj.rtcpMux = 'rtcp-mux'; - remoteMediaObj.rtcpRsize = 'rtcp-rsize'; - - // Push it. - sdpObj.media.push(remoteMediaObj); - } - } catch (err) { - _didIteratorError = true; - _iteratorError = err; - } finally { - try { - if (!_iteratorNormalCompletion && _iterator.return) { - _iterator.return(); - } - } finally { - if (_didIteratorError) { - throw _iteratorError; - } - } - } - - var sdp = _sdpTransform2.default.write(sdpObj); - - return sdp; - } - }]); - return SendRemoteSdp; -}(RemoteSdp); - -var RecvRemoteSdp = function (_RemoteSdp2) { - (0, _inherits3.default)(RecvRemoteSdp, _RemoteSdp2); - - function RecvRemoteSdp(rtpParametersByKind) { - (0, _classCallCheck3.default)(this, RecvRemoteSdp); - - // Id of the unique MediaStream for all the remote tracks. - var _this2 = (0, _possibleConstructorReturn3.default)(this, (RecvRemoteSdp.__proto__ || (0, _getPrototypeOf2.default)(RecvRemoteSdp)).call(this, rtpParametersByKind)); - - _this2._streamId = 'recv-stream-' + utils.randomNumber(); - return _this2; - } - - /** - * @param {Array} kinds - Media kinds. - * @param {Array} consumerInfos - Consumer informations. - * @return {String} - */ - - - (0, _createClass3.default)(RecvRemoteSdp, [{ - key: 'createOfferSdp', - value: function createOfferSdp(kinds, consumerInfos) { - var _this3 = this; - - logger.debug('createOfferSdp()'); - - if (!this._transportRemoteParameters) throw new Error('no transport remote parameters'); - - var remoteIceParameters = this._transportRemoteParameters.iceParameters; - var remoteIceCandidates = this._transportRemoteParameters.iceCandidates; - var remoteDtlsParameters = this._transportRemoteParameters.dtlsParameters; - var sdpObj = {}; - var mids = kinds; - - // Increase our SDP version. - this._sdpGlobalFields.version++; - - sdpObj.version = 0; - sdpObj.origin = { - address: '0.0.0.0', - ipVer: 4, - netType: 'IN', - sessionId: this._sdpGlobalFields.id, - sessionVersion: this._sdpGlobalFields.version, - username: 'mediasoup-client' - }; - sdpObj.name = '-'; - sdpObj.timing = { start: 0, stop: 0 }; - sdpObj.icelite = remoteIceParameters.iceLite ? 'ice-lite' : null; - sdpObj.msidSemantic = { - semantic: 'WMS', - token: '*' - }; - sdpObj.groups = [{ - type: 'BUNDLE', - mids: mids.join(' ') - }]; - sdpObj.media = []; - - sdpObj.fingerprint = { - type: remoteDtlsParameters.fingerprints[0].algorithm, - hash: remoteDtlsParameters.fingerprints[0].value - }; - - var _iteratorNormalCompletion7 = true; - var _didIteratorError7 = false; - var _iteratorError7 = undefined; - - try { - var _loop = function _loop() { - var kind = _step7.value; - - var codecs = _this3._rtpParametersByKind[kind].codecs; - var headerExtensions = _this3._rtpParametersByKind[kind].headerExtensions; - var remoteMediaObj = {}; - - remoteMediaObj.type = kind; - remoteMediaObj.port = 7; - remoteMediaObj.protocol = 'RTP/SAVPF'; - remoteMediaObj.connection = { ip: '127.0.0.1', version: 4 }; - remoteMediaObj.mid = kind; - - remoteMediaObj.iceUfrag = remoteIceParameters.usernameFragment; - remoteMediaObj.icePwd = remoteIceParameters.password; - remoteMediaObj.candidates = []; - - var _iteratorNormalCompletion8 = true; - var _didIteratorError8 = false; - var _iteratorError8 = undefined; - - try { - for (var _iterator8 = (0, _getIterator3.default)(remoteIceCandidates), _step8; !(_iteratorNormalCompletion8 = (_step8 = _iterator8.next()).done); _iteratorNormalCompletion8 = true) { - var candidate = _step8.value; - - var candidateObj = {}; - - // mediasoup does not support non rtcp-mux so candidates component is - // always RTP (1). - candidateObj.component = 1; - candidateObj.foundation = candidate.foundation; - candidateObj.ip = candidate.ip; - candidateObj.port = candidate.port; - candidateObj.priority = candidate.priority; - candidateObj.transport = candidate.protocol; - candidateObj.type = candidate.type; - if (candidate.tcpType) candidateObj.tcptype = candidate.tcpType; - - remoteMediaObj.candidates.push(candidateObj); - } - } catch (err) { - _didIteratorError8 = true; - _iteratorError8 = err; - } finally { - try { - if (!_iteratorNormalCompletion8 && _iterator8.return) { - _iterator8.return(); - } - } finally { - if (_didIteratorError8) { - throw _iteratorError8; - } - } - } - - remoteMediaObj.endOfCandidates = 'end-of-candidates'; - - // Announce support for ICE renomination. - // https://tools.ietf.org/html/draft-thatcher-ice-renomination - remoteMediaObj.iceOptions = 'renomination'; - - remoteMediaObj.setup = 'actpass'; - - if (consumerInfos.some(function (info) { - return info.kind === kind; - })) remoteMediaObj.direction = 'sendonly';else remoteMediaObj.direction = 'inactive'; - - remoteMediaObj.rtp = []; - remoteMediaObj.rtcpFb = []; - remoteMediaObj.fmtp = []; - - var _iteratorNormalCompletion9 = true; - var _didIteratorError9 = false; - var _iteratorError9 = undefined; - - try { - for (var _iterator9 = (0, _getIterator3.default)(codecs), _step9; !(_iteratorNormalCompletion9 = (_step9 = _iterator9.next()).done); _iteratorNormalCompletion9 = true) { - var codec = _step9.value; - - var rtp = { - payload: codec.payloadType, - codec: codec.name, - rate: codec.clockRate - }; - - if (codec.channels > 1) rtp.encoding = codec.channels; - - remoteMediaObj.rtp.push(rtp); - - if (codec.parameters) { - var paramFmtp = { - payload: codec.payloadType, - config: '' - }; - - var _iteratorNormalCompletion12 = true; - var _didIteratorError12 = false; - var _iteratorError12 = undefined; - - try { - for (var _iterator12 = (0, _getIterator3.default)((0, _keys2.default)(codec.parameters)), _step12; !(_iteratorNormalCompletion12 = (_step12 = _iterator12.next()).done); _iteratorNormalCompletion12 = true) { - var key = _step12.value; - - if (paramFmtp.config) paramFmtp.config += ';'; - - paramFmtp.config += key + '=' + codec.parameters[key]; - } - } catch (err) { - _didIteratorError12 = true; - _iteratorError12 = err; - } finally { - try { - if (!_iteratorNormalCompletion12 && _iterator12.return) { - _iterator12.return(); - } - } finally { - if (_didIteratorError12) { - throw _iteratorError12; - } - } - } - - if (paramFmtp.config) remoteMediaObj.fmtp.push(paramFmtp); - } - - if (codec.rtcpFeedback) { - var _iteratorNormalCompletion13 = true; - var _didIteratorError13 = false; - var _iteratorError13 = undefined; - - try { - for (var _iterator13 = (0, _getIterator3.default)(codec.rtcpFeedback), _step13; !(_iteratorNormalCompletion13 = (_step13 = _iterator13.next()).done); _iteratorNormalCompletion13 = true) { - var fb = _step13.value; - - remoteMediaObj.rtcpFb.push({ - payload: codec.payloadType, - type: fb.type, - subtype: fb.parameter - }); - } - } catch (err) { - _didIteratorError13 = true; - _iteratorError13 = err; - } finally { - try { - if (!_iteratorNormalCompletion13 && _iterator13.return) { - _iterator13.return(); - } - } finally { - if (_didIteratorError13) { - throw _iteratorError13; - } - } - } - } - } - } catch (err) { - _didIteratorError9 = true; - _iteratorError9 = err; - } finally { - try { - if (!_iteratorNormalCompletion9 && _iterator9.return) { - _iterator9.return(); - } - } finally { - if (_didIteratorError9) { - throw _iteratorError9; - } - } - } - - remoteMediaObj.payloads = codecs.map(function (codec) { - return codec.payloadType; - }).join(' '); - - remoteMediaObj.ext = []; - - var _iteratorNormalCompletion10 = true; - var _didIteratorError10 = false; - var _iteratorError10 = undefined; - - try { - for (var _iterator10 = (0, _getIterator3.default)(headerExtensions), _step10; !(_iteratorNormalCompletion10 = (_step10 = _iterator10.next()).done); _iteratorNormalCompletion10 = true) { - var ext = _step10.value; - - remoteMediaObj.ext.push({ - uri: ext.uri, - value: ext.id - }); - } - } catch (err) { - _didIteratorError10 = true; - _iteratorError10 = err; - } finally { - try { - if (!_iteratorNormalCompletion10 && _iterator10.return) { - _iterator10.return(); - } - } finally { - if (_didIteratorError10) { - throw _iteratorError10; - } - } - } - - remoteMediaObj.rtcpMux = 'rtcp-mux'; - remoteMediaObj.rtcpRsize = 'rtcp-rsize'; - - remoteMediaObj.ssrcs = []; - remoteMediaObj.ssrcGroups = []; - - var _iteratorNormalCompletion11 = true; - var _didIteratorError11 = false; - var _iteratorError11 = undefined; - - try { - for (var _iterator11 = (0, _getIterator3.default)(consumerInfos), _step11; !(_iteratorNormalCompletion11 = (_step11 = _iterator11.next()).done); _iteratorNormalCompletion11 = true) { - var info = _step11.value; - - if (info.kind !== kind) continue; - - remoteMediaObj.ssrcs.push({ - id: info.ssrc, - attribute: 'msid', - value: _this3._streamId + ' ' + info.trackId - }); - - remoteMediaObj.ssrcs.push({ - id: info.ssrc, - attribute: 'mslabel', - value: _this3._streamId - }); - - remoteMediaObj.ssrcs.push({ - id: info.ssrc, - attribute: 'label', - value: info.trackId - }); - - remoteMediaObj.ssrcs.push({ - id: info.ssrc, - attribute: 'cname', - value: info.cname - }); - - if (info.rtxSsrc) { - remoteMediaObj.ssrcs.push({ - id: info.rtxSsrc, - attribute: 'msid', - value: _this3._streamId + ' ' + info.trackId - }); - - remoteMediaObj.ssrcs.push({ - id: info.rtxSsrc, - attribute: 'mslabel', - value: _this3._streamId - }); - - remoteMediaObj.ssrcs.push({ - id: info.rtxSsrc, - attribute: 'label', - value: info.trackId - }); - - remoteMediaObj.ssrcs.push({ - id: info.rtxSsrc, - attribute: 'cname', - value: info.cname - }); - - // Associate original and retransmission SSRC. - remoteMediaObj.ssrcGroups.push({ - semantics: 'FID', - ssrcs: info.ssrc + ' ' + info.rtxSsrc - }); - } - } - - // Push it. - } catch (err) { - _didIteratorError11 = true; - _iteratorError11 = err; - } finally { - try { - if (!_iteratorNormalCompletion11 && _iterator11.return) { - _iterator11.return(); - } - } finally { - if (_didIteratorError11) { - throw _iteratorError11; - } - } - } - - sdpObj.media.push(remoteMediaObj); - }; - - for (var _iterator7 = (0, _getIterator3.default)(kinds), _step7; !(_iteratorNormalCompletion7 = (_step7 = _iterator7.next()).done); _iteratorNormalCompletion7 = true) { - _loop(); - } - } catch (err) { - _didIteratorError7 = true; - _iteratorError7 = err; - } finally { - try { - if (!_iteratorNormalCompletion7 && _iterator7.return) { - _iterator7.return(); - } - } finally { - if (_didIteratorError7) { - throw _iteratorError7; - } - } - } - - var sdp = _sdpTransform2.default.write(sdpObj); - - return sdp; - } - }]); - return RecvRemoteSdp; -}(RemoteSdp); - -var RemotePlanBSdp = function RemotePlanBSdp(direction, rtpParametersByKind) { - (0, _classCallCheck3.default)(this, RemotePlanBSdp); - - logger.debug('constructor() [direction:%s, rtpParametersByKind:%o]', direction, rtpParametersByKind); - - switch (direction) { - case 'send': - return new SendRemoteSdp(rtpParametersByKind); - case 'recv': - return new RecvRemoteSdp(rtpParametersByKind); - } -}; - -exports.default = RemotePlanBSdp; - -},{"../../Logger":"/Users/ibc/src/mediasoup-client/lib/Logger.js","../../utils":"/Users/ibc/src/mediasoup-client/lib/utils.js","babel-runtime/core-js/get-iterator":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/core-js/get-iterator.js","babel-runtime/core-js/object/get-prototype-of":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/core-js/object/get-prototype-of.js","babel-runtime/core-js/object/keys":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/core-js/object/keys.js","babel-runtime/helpers/classCallCheck":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/helpers/classCallCheck.js","babel-runtime/helpers/createClass":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/helpers/createClass.js","babel-runtime/helpers/inherits":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/helpers/inherits.js","babel-runtime/helpers/possibleConstructorReturn":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/helpers/possibleConstructorReturn.js","sdp-transform":"/Users/ibc/src/mediasoup-client/node_modules/sdp-transform/lib/index.js"}],"/Users/ibc/src/mediasoup-client/lib/handlers/sdp/RemoteUnifiedPlanSdp.js":[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _keys = require('babel-runtime/core-js/object/keys'); - -var _keys2 = _interopRequireDefault(_keys); - -var _getIterator2 = require('babel-runtime/core-js/get-iterator'); - -var _getIterator3 = _interopRequireDefault(_getIterator2); - -var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); - -var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); - -var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); - -var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); - -var _inherits2 = require('babel-runtime/helpers/inherits'); - -var _inherits3 = _interopRequireDefault(_inherits2); - -var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); - -var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); - -var _createClass2 = require('babel-runtime/helpers/createClass'); - -var _createClass3 = _interopRequireDefault(_createClass2); - -var _sdpTransform = require('sdp-transform'); - -var _sdpTransform2 = _interopRequireDefault(_sdpTransform); - -var _Logger = require('../../Logger'); - -var _Logger2 = _interopRequireDefault(_Logger); - -var _utils = require('../../utils'); - -var utils = _interopRequireWildcard(_utils); - -function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -var logger = new _Logger2.default('RemoteUnifiedPlanSdp'); - -var RemoteSdp = function () { - function RemoteSdp(rtpParametersByKind) { - (0, _classCallCheck3.default)(this, RemoteSdp); - - // Generic sending RTP parameters for audio and video. - // @type {Object} - this._rtpParametersByKind = rtpParametersByKind; - - // Transport local parameters, including DTLS parameteres. - // @type {Object} - this._transportLocalParameters = null; - - // Transport remote parameters, including ICE parameters, ICE candidates - // and DTLS parameteres. - // @type {Object} - this._transportRemoteParameters = null; - - // SDP global fields. - // @type {Object} - this._sdpGlobalFields = { - id: utils.randomNumber(), - version: 0 - }; - } - - (0, _createClass3.default)(RemoteSdp, [{ - key: 'setTransportLocalParameters', - value: function setTransportLocalParameters(transportLocalParameters) { - logger.debug('setTransportLocalParameters() [transportLocalParameters:%o]', transportLocalParameters); - - this._transportLocalParameters = transportLocalParameters; - } - }, { - key: 'setTransportRemoteParameters', - value: function setTransportRemoteParameters(transportRemoteParameters) { - logger.debug('setTransportRemoteParameters() [transportRemoteParameters:%o]', transportRemoteParameters); - - this._transportRemoteParameters = transportRemoteParameters; - } - }]); - return RemoteSdp; -}(); - -var SendRemoteSdp = function (_RemoteSdp) { - (0, _inherits3.default)(SendRemoteSdp, _RemoteSdp); - - function SendRemoteSdp(rtpParametersByKind) { - (0, _classCallCheck3.default)(this, SendRemoteSdp); - return (0, _possibleConstructorReturn3.default)(this, (SendRemoteSdp.__proto__ || (0, _getPrototypeOf2.default)(SendRemoteSdp)).call(this, rtpParametersByKind)); - } - - (0, _createClass3.default)(SendRemoteSdp, [{ - key: 'createAnswerSdp', - value: function createAnswerSdp(localSdpObj) { - logger.debug('createAnswerSdp()'); - - if (!this._transportLocalParameters) throw new Error('no transport local parameters');else if (!this._transportRemoteParameters) throw new Error('no transport remote parameters'); - - var localDtlsParameters = this._transportLocalParameters.dtlsParameters; - var remoteIceParameters = this._transportRemoteParameters.iceParameters; - var remoteIceCandidates = this._transportRemoteParameters.iceCandidates; - var remoteDtlsParameters = this._transportRemoteParameters.dtlsParameters; - var sdpObj = {}; - var mids = (localSdpObj.media || []).filter(function (m) { - return m.mid; - }).map(function (m) { - return m.mid; - }); - - // Increase our SDP version. - this._sdpGlobalFields.version++; - - sdpObj.version = 0; - sdpObj.origin = { - address: '0.0.0.0', - ipVer: 4, - netType: 'IN', - sessionId: this._sdpGlobalFields.id, - sessionVersion: this._sdpGlobalFields.version, - username: 'mediasoup-client' - }; - sdpObj.name = '-'; - sdpObj.timing = { start: 0, stop: 0 }; - sdpObj.icelite = remoteIceParameters.iceLite ? 'ice-lite' : null; - sdpObj.msidSemantic = { - semantic: 'WMS', - token: '*' - }; - - if (mids.length > 0) { - sdpObj.groups = [{ - type: 'BUNDLE', - mids: mids.join(' ') - }]; - } - - sdpObj.media = []; - - sdpObj.fingerprint = { - type: remoteDtlsParameters.fingerprints[0].algorithm, - hash: remoteDtlsParameters.fingerprints[0].value - }; - - var _iteratorNormalCompletion = true; - var _didIteratorError = false; - var _iteratorError = undefined; - - try { - for (var _iterator = (0, _getIterator3.default)(localSdpObj.media || []), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { - var localMediaObj = _step.value; - - var closed = localMediaObj.direction === 'inactive'; - var kind = localMediaObj.type; - var codecs = this._rtpParametersByKind[kind].codecs; - var headerExtensions = this._rtpParametersByKind[kind].headerExtensions; - var remoteMediaObj = {}; - - remoteMediaObj.type = localMediaObj.type; - remoteMediaObj.port = 7; - remoteMediaObj.protocol = 'RTP/SAVPF'; - remoteMediaObj.connection = { ip: '127.0.0.1', version: 4 }; - remoteMediaObj.mid = localMediaObj.mid; - - remoteMediaObj.iceUfrag = remoteIceParameters.usernameFragment; - remoteMediaObj.icePwd = remoteIceParameters.password; - remoteMediaObj.candidates = []; - - var _iteratorNormalCompletion2 = true; - var _didIteratorError2 = false; - var _iteratorError2 = undefined; - - try { - for (var _iterator2 = (0, _getIterator3.default)(remoteIceCandidates), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { - var candidate = _step2.value; - - var candidateObj = {}; - - // mediasoup does not support non rtcp-mux so candidates component is - // always RTP (1). - candidateObj.component = 1; - candidateObj.foundation = candidate.foundation; - candidateObj.ip = candidate.ip; - candidateObj.port = candidate.port; - candidateObj.priority = candidate.priority; - candidateObj.transport = candidate.protocol; - candidateObj.type = candidate.type; - if (candidate.tcpType) candidateObj.tcptype = candidate.tcpType; - - remoteMediaObj.candidates.push(candidateObj); - } - } catch (err) { - _didIteratorError2 = true; - _iteratorError2 = err; - } finally { - try { - if (!_iteratorNormalCompletion2 && _iterator2.return) { - _iterator2.return(); - } - } finally { - if (_didIteratorError2) { - throw _iteratorError2; - } - } - } - - remoteMediaObj.endOfCandidates = 'end-of-candidates'; - - // Announce support for ICE renomination. - // https://tools.ietf.org/html/draft-thatcher-ice-renomination - remoteMediaObj.iceOptions = 'renomination'; - - switch (localDtlsParameters.role) { - case 'client': - remoteMediaObj.setup = 'active'; - break; - case 'server': - remoteMediaObj.setup = 'passive'; - break; - } - - switch (localMediaObj.direction) { - case 'sendrecv': - case 'sendonly': - remoteMediaObj.direction = 'recvonly'; - break; - case 'recvonly': - case 'inactive': - remoteMediaObj.direction = 'inactive'; - break; - } - - remoteMediaObj.rtp = []; - remoteMediaObj.rtcpFb = []; - remoteMediaObj.fmtp = []; - - var _iteratorNormalCompletion3 = true; - var _didIteratorError3 = false; - var _iteratorError3 = undefined; - - try { - for (var _iterator3 = (0, _getIterator3.default)(codecs), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) { - var codec = _step3.value; - - var rtp = { - payload: codec.payloadType, - codec: codec.name, - rate: codec.clockRate - }; - - if (codec.channels > 1) rtp.encoding = codec.channels; - - remoteMediaObj.rtp.push(rtp); - - if (codec.parameters) { - var paramFmtp = { - payload: codec.payloadType, - config: '' - }; - - var _iteratorNormalCompletion5 = true; - var _didIteratorError5 = false; - var _iteratorError5 = undefined; - - try { - for (var _iterator5 = (0, _getIterator3.default)((0, _keys2.default)(codec.parameters)), _step5; !(_iteratorNormalCompletion5 = (_step5 = _iterator5.next()).done); _iteratorNormalCompletion5 = true) { - var key = _step5.value; - - if (paramFmtp.config) paramFmtp.config += ';'; - - paramFmtp.config += key + '=' + codec.parameters[key]; - } - } catch (err) { - _didIteratorError5 = true; - _iteratorError5 = err; - } finally { - try { - if (!_iteratorNormalCompletion5 && _iterator5.return) { - _iterator5.return(); - } - } finally { - if (_didIteratorError5) { - throw _iteratorError5; - } - } - } - - if (paramFmtp.config) remoteMediaObj.fmtp.push(paramFmtp); - } - - if (codec.rtcpFeedback) { - var _iteratorNormalCompletion6 = true; - var _didIteratorError6 = false; - var _iteratorError6 = undefined; - - try { - for (var _iterator6 = (0, _getIterator3.default)(codec.rtcpFeedback), _step6; !(_iteratorNormalCompletion6 = (_step6 = _iterator6.next()).done); _iteratorNormalCompletion6 = true) { - var fb = _step6.value; - - remoteMediaObj.rtcpFb.push({ - payload: codec.payloadType, - type: fb.type, - subtype: fb.parameter - }); - } - } catch (err) { - _didIteratorError6 = true; - _iteratorError6 = err; - } finally { - try { - if (!_iteratorNormalCompletion6 && _iterator6.return) { - _iterator6.return(); - } - } finally { - if (_didIteratorError6) { - throw _iteratorError6; - } - } - } - } - } - } catch (err) { - _didIteratorError3 = true; - _iteratorError3 = err; - } finally { - try { - if (!_iteratorNormalCompletion3 && _iterator3.return) { - _iterator3.return(); - } - } finally { - if (_didIteratorError3) { - throw _iteratorError3; - } - } - } - - remoteMediaObj.payloads = codecs.map(function (codec) { - return codec.payloadType; - }).join(' '); - - // NOTE: Firefox does not like a=extmap lines if a=inactive. - if (!closed) { - remoteMediaObj.ext = []; - - var _iteratorNormalCompletion4 = true; - var _didIteratorError4 = false; - var _iteratorError4 = undefined; - - try { - for (var _iterator4 = (0, _getIterator3.default)(headerExtensions), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) { - var ext = _step4.value; - - remoteMediaObj.ext.push({ - uri: ext.uri, - value: ext.id - }); - } - } catch (err) { - _didIteratorError4 = true; - _iteratorError4 = err; - } finally { - try { - if (!_iteratorNormalCompletion4 && _iterator4.return) { - _iterator4.return(); - } - } finally { - if (_didIteratorError4) { - throw _iteratorError4; - } - } - } - } - - remoteMediaObj.rtcpMux = 'rtcp-mux'; - remoteMediaObj.rtcpRsize = 'rtcp-rsize'; - - // Push it. - sdpObj.media.push(remoteMediaObj); - } - } catch (err) { - _didIteratorError = true; - _iteratorError = err; - } finally { - try { - if (!_iteratorNormalCompletion && _iterator.return) { - _iterator.return(); - } - } finally { - if (_didIteratorError) { - throw _iteratorError; - } - } - } - - var sdp = _sdpTransform2.default.write(sdpObj); - - return sdp; - } - }]); - return SendRemoteSdp; -}(RemoteSdp); - -var RecvRemoteSdp = function (_RemoteSdp2) { - (0, _inherits3.default)(RecvRemoteSdp, _RemoteSdp2); - - function RecvRemoteSdp(rtpParametersByKind) { - (0, _classCallCheck3.default)(this, RecvRemoteSdp); - - // Id of the unique MediaStream for all the remote tracks. - var _this2 = (0, _possibleConstructorReturn3.default)(this, (RecvRemoteSdp.__proto__ || (0, _getPrototypeOf2.default)(RecvRemoteSdp)).call(this, rtpParametersByKind)); - - _this2._streamId = 'recv-stream-' + utils.randomNumber(); - return _this2; - } - - /** - * @param {Array} consumerInfos - Consumer informations. - * @return {String} - */ - - - (0, _createClass3.default)(RecvRemoteSdp, [{ - key: 'createOfferSdp', - value: function createOfferSdp(consumerInfos) { - logger.debug('createOfferSdp()'); - - if (!this._transportRemoteParameters) throw new Error('no transport remote parameters'); - - var remoteIceParameters = this._transportRemoteParameters.iceParameters; - var remoteIceCandidates = this._transportRemoteParameters.iceCandidates; - var remoteDtlsParameters = this._transportRemoteParameters.dtlsParameters; - var sdpObj = {}; - var mids = consumerInfos.filter(function (info) { - return !info.closed; - }).map(function (info) { - return info.mid; - }); - - // Increase our SDP version. - this._sdpGlobalFields.version++; - - sdpObj.version = 0; - sdpObj.origin = { - address: '0.0.0.0', - ipVer: 4, - netType: 'IN', - sessionId: this._sdpGlobalFields.id, - sessionVersion: this._sdpGlobalFields.version, - username: 'mediasoup-client' - }; - sdpObj.name = '-'; - sdpObj.timing = { start: 0, stop: 0 }; - sdpObj.icelite = remoteIceParameters.iceLite ? 'ice-lite' : null; - sdpObj.msidSemantic = { - semantic: 'WMS', - token: '*' - }; - - if (mids.length > 0) { - sdpObj.groups = [{ - type: 'BUNDLE', - mids: mids.join(' ') - }]; - } - - sdpObj.media = []; - - sdpObj.fingerprint = { - type: remoteDtlsParameters.fingerprints[0].algorithm, - hash: remoteDtlsParameters.fingerprints[0].value - }; - - var _iteratorNormalCompletion7 = true; - var _didIteratorError7 = false; - var _iteratorError7 = undefined; - - try { - for (var _iterator7 = (0, _getIterator3.default)(consumerInfos), _step7; !(_iteratorNormalCompletion7 = (_step7 = _iterator7.next()).done); _iteratorNormalCompletion7 = true) { - var info = _step7.value; - - var closed = info.closed; - var kind = info.kind; - var codecs = this._rtpParametersByKind[kind].codecs; - var headerExtensions = this._rtpParametersByKind[kind].headerExtensions; - var remoteMediaObj = {}; - - remoteMediaObj.type = kind; - remoteMediaObj.port = 7; - remoteMediaObj.protocol = 'RTP/SAVPF'; - remoteMediaObj.connection = { ip: '127.0.0.1', version: 4 }; - remoteMediaObj.mid = info.mid; - remoteMediaObj.msid = this._streamId + ' ' + info.trackId; - - remoteMediaObj.iceUfrag = remoteIceParameters.usernameFragment; - remoteMediaObj.icePwd = remoteIceParameters.password; - remoteMediaObj.candidates = []; - - var _iteratorNormalCompletion8 = true; - var _didIteratorError8 = false; - var _iteratorError8 = undefined; - - try { - for (var _iterator8 = (0, _getIterator3.default)(remoteIceCandidates), _step8; !(_iteratorNormalCompletion8 = (_step8 = _iterator8.next()).done); _iteratorNormalCompletion8 = true) { - var candidate = _step8.value; - - var candidateObj = {}; - - // mediasoup does not support non rtcp-mux so candidates component is - // always RTP (1). - candidateObj.component = 1; - candidateObj.foundation = candidate.foundation; - candidateObj.ip = candidate.ip; - candidateObj.port = candidate.port; - candidateObj.priority = candidate.priority; - candidateObj.transport = candidate.protocol; - candidateObj.type = candidate.type; - if (candidate.tcpType) candidateObj.tcptype = candidate.tcpType; - - remoteMediaObj.candidates.push(candidateObj); - } - } catch (err) { - _didIteratorError8 = true; - _iteratorError8 = err; - } finally { - try { - if (!_iteratorNormalCompletion8 && _iterator8.return) { - _iterator8.return(); - } - } finally { - if (_didIteratorError8) { - throw _iteratorError8; - } - } - } - - remoteMediaObj.endOfCandidates = 'end-of-candidates'; - - // Announce support for ICE renomination. - // https://tools.ietf.org/html/draft-thatcher-ice-renomination - remoteMediaObj.iceOptions = 'renomination'; - - remoteMediaObj.setup = 'actpass'; - - if (!closed) remoteMediaObj.direction = 'sendonly';else remoteMediaObj.direction = 'inactive'; - - remoteMediaObj.rtp = []; - remoteMediaObj.rtcpFb = []; - remoteMediaObj.fmtp = []; - - var _iteratorNormalCompletion9 = true; - var _didIteratorError9 = false; - var _iteratorError9 = undefined; - - try { - for (var _iterator9 = (0, _getIterator3.default)(codecs), _step9; !(_iteratorNormalCompletion9 = (_step9 = _iterator9.next()).done); _iteratorNormalCompletion9 = true) { - var codec = _step9.value; - - var rtp = { - payload: codec.payloadType, - codec: codec.name, - rate: codec.clockRate - }; - - if (codec.channels > 1) rtp.encoding = codec.channels; - - remoteMediaObj.rtp.push(rtp); - - if (codec.parameters) { - var paramFmtp = { - payload: codec.payloadType, - config: '' - }; - - var _iteratorNormalCompletion11 = true; - var _didIteratorError11 = false; - var _iteratorError11 = undefined; - - try { - for (var _iterator11 = (0, _getIterator3.default)((0, _keys2.default)(codec.parameters)), _step11; !(_iteratorNormalCompletion11 = (_step11 = _iterator11.next()).done); _iteratorNormalCompletion11 = true) { - var key = _step11.value; - - if (paramFmtp.config) paramFmtp.config += ';'; - - paramFmtp.config += key + '=' + codec.parameters[key]; - } - } catch (err) { - _didIteratorError11 = true; - _iteratorError11 = err; - } finally { - try { - if (!_iteratorNormalCompletion11 && _iterator11.return) { - _iterator11.return(); - } - } finally { - if (_didIteratorError11) { - throw _iteratorError11; - } - } - } - - if (paramFmtp.config) remoteMediaObj.fmtp.push(paramFmtp); - } - - if (codec.rtcpFeedback) { - var _iteratorNormalCompletion12 = true; - var _didIteratorError12 = false; - var _iteratorError12 = undefined; - - try { - for (var _iterator12 = (0, _getIterator3.default)(codec.rtcpFeedback), _step12; !(_iteratorNormalCompletion12 = (_step12 = _iterator12.next()).done); _iteratorNormalCompletion12 = true) { - var fb = _step12.value; - - remoteMediaObj.rtcpFb.push({ - payload: codec.payloadType, - type: fb.type, - subtype: fb.parameter - }); - } - } catch (err) { - _didIteratorError12 = true; - _iteratorError12 = err; - } finally { - try { - if (!_iteratorNormalCompletion12 && _iterator12.return) { - _iterator12.return(); - } - } finally { - if (_didIteratorError12) { - throw _iteratorError12; - } - } - } - } - } - } catch (err) { - _didIteratorError9 = true; - _iteratorError9 = err; - } finally { - try { - if (!_iteratorNormalCompletion9 && _iterator9.return) { - _iterator9.return(); - } - } finally { - if (_didIteratorError9) { - throw _iteratorError9; - } - } - } - - remoteMediaObj.payloads = codecs.map(function (codec) { - return codec.payloadType; - }).join(' '); - - // NOTE: Firefox does not like a=extmap lines if a=inactive. - if (!closed) { - remoteMediaObj.ext = []; - - var _iteratorNormalCompletion10 = true; - var _didIteratorError10 = false; - var _iteratorError10 = undefined; - - try { - for (var _iterator10 = (0, _getIterator3.default)(headerExtensions), _step10; !(_iteratorNormalCompletion10 = (_step10 = _iterator10.next()).done); _iteratorNormalCompletion10 = true) { - var ext = _step10.value; - - remoteMediaObj.ext.push({ - uri: ext.uri, - value: ext.id - }); - } - } catch (err) { - _didIteratorError10 = true; - _iteratorError10 = err; - } finally { - try { - if (!_iteratorNormalCompletion10 && _iterator10.return) { - _iterator10.return(); - } - } finally { - if (_didIteratorError10) { - throw _iteratorError10; - } - } - } - } - - remoteMediaObj.rtcpMux = 'rtcp-mux'; - remoteMediaObj.rtcpRsize = 'rtcp-rsize'; - - if (!closed) { - remoteMediaObj.ssrcs = []; - remoteMediaObj.ssrcGroups = []; - - remoteMediaObj.ssrcs.push({ - id: info.ssrc, - attribute: 'cname', - value: info.cname - }); - - if (info.rtxSsrc) { - remoteMediaObj.ssrcs.push({ - id: info.rtxSsrc, - attribute: 'cname', - value: info.cname - }); - - // Associate original and retransmission SSRC. - remoteMediaObj.ssrcGroups.push({ - semantics: 'FID', - ssrcs: info.ssrc + ' ' + info.rtxSsrc - }); - } - } - - // Push it. - sdpObj.media.push(remoteMediaObj); - } - } catch (err) { - _didIteratorError7 = true; - _iteratorError7 = err; - } finally { - try { - if (!_iteratorNormalCompletion7 && _iterator7.return) { - _iterator7.return(); - } - } finally { - if (_didIteratorError7) { - throw _iteratorError7; - } - } - } - - var sdp = _sdpTransform2.default.write(sdpObj); - - return sdp; - } - }]); - return RecvRemoteSdp; -}(RemoteSdp); - -var RemoteUnifiedPlanSdp = function RemoteUnifiedPlanSdp(direction, rtpParametersByKind) { - (0, _classCallCheck3.default)(this, RemoteUnifiedPlanSdp); - - logger.debug('constructor() [direction:%s, rtpParametersByKind:%o]', direction, rtpParametersByKind); - - switch (direction) { - case 'send': - return new SendRemoteSdp(rtpParametersByKind); - case 'recv': - return new RecvRemoteSdp(rtpParametersByKind); - } -}; - -exports.default = RemoteUnifiedPlanSdp; - -},{"../../Logger":"/Users/ibc/src/mediasoup-client/lib/Logger.js","../../utils":"/Users/ibc/src/mediasoup-client/lib/utils.js","babel-runtime/core-js/get-iterator":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/core-js/get-iterator.js","babel-runtime/core-js/object/get-prototype-of":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/core-js/object/get-prototype-of.js","babel-runtime/core-js/object/keys":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/core-js/object/keys.js","babel-runtime/helpers/classCallCheck":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/helpers/classCallCheck.js","babel-runtime/helpers/createClass":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/helpers/createClass.js","babel-runtime/helpers/inherits":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/helpers/inherits.js","babel-runtime/helpers/possibleConstructorReturn":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/helpers/possibleConstructorReturn.js","sdp-transform":"/Users/ibc/src/mediasoup-client/node_modules/sdp-transform/lib/index.js"}],"/Users/ibc/src/mediasoup-client/lib/handlers/sdp/commonUtils.js":[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _getIterator2 = require('babel-runtime/core-js/get-iterator'); - -var _getIterator3 = _interopRequireDefault(_getIterator2); - -var _from = require('babel-runtime/core-js/array/from'); - -var _from2 = _interopRequireDefault(_from); - -var _map = require('babel-runtime/core-js/map'); - -var _map2 = _interopRequireDefault(_map); - -exports.extractRtpCapabilities = extractRtpCapabilities; -exports.extractDtlsParameters = extractDtlsParameters; - -var _sdpTransform = require('sdp-transform'); - -var _sdpTransform2 = _interopRequireDefault(_sdpTransform); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * Extract RTP capabilities from a SDP. - * - * @param {Object} sdpObj - SDP Object generated by sdp-transform. - * @return {RTCRtpCapabilities} - */ -function extractRtpCapabilities(sdpObj) { - // Map of RtpCodecParameters indexed by payload type. - var codecsMap = new _map2.default(); - - // Array of RtpHeaderExtensions. - var headerExtensions = []; - - // Whether a m=audio/video section has been already found. - var gotAudio = false; - var gotVideo = false; - - var _iteratorNormalCompletion = true; - var _didIteratorError = false; - var _iteratorError = undefined; - - try { - for (var _iterator = (0, _getIterator3.default)(sdpObj.media), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { - var m = _step.value; - - var kind = m.type; - - switch (kind) { - case 'audio': - { - if (gotAudio) continue; - - gotAudio = true; - break; - } - case 'video': - { - if (gotVideo) continue; - - gotVideo = true; - break; - } - default: - { - continue; - } - } - - // Get codecs. - var _iteratorNormalCompletion2 = true; - var _didIteratorError2 = false; - var _iteratorError2 = undefined; - - try { - for (var _iterator2 = (0, _getIterator3.default)(m.rtp), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { - var rtp = _step2.value; - - var codec = { - name: rtp.codec, - mimeType: kind + '/' + rtp.codec, - kind: kind, - clockRate: rtp.rate, - preferredPayloadType: rtp.payload, - channels: rtp.encoding, - rtcpFeedback: [], - parameters: {} - }; - - if (!(codec.channels > 1)) delete codec.channels; - - codecsMap.set(codec.preferredPayloadType, codec); - } - - // Get codec parameters. - } catch (err) { - _didIteratorError2 = true; - _iteratorError2 = err; - } finally { - try { - if (!_iteratorNormalCompletion2 && _iterator2.return) { - _iterator2.return(); - } - } finally { - if (_didIteratorError2) { - throw _iteratorError2; - } - } - } - - var _iteratorNormalCompletion3 = true; - var _didIteratorError3 = false; - var _iteratorError3 = undefined; - - try { - for (var _iterator3 = (0, _getIterator3.default)(m.fmtp || []), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) { - var fmtp = _step3.value; - - var parameters = _sdpTransform2.default.parseFmtpConfig(fmtp.config); - var _codec = codecsMap.get(fmtp.payload); - - if (!_codec) continue; - - _codec.parameters = parameters; - } - - // Get RTCP feedback for each codec. - } catch (err) { - _didIteratorError3 = true; - _iteratorError3 = err; - } finally { - try { - if (!_iteratorNormalCompletion3 && _iterator3.return) { - _iterator3.return(); - } - } finally { - if (_didIteratorError3) { - throw _iteratorError3; - } - } - } - - var _iteratorNormalCompletion4 = true; - var _didIteratorError4 = false; - var _iteratorError4 = undefined; - - try { - for (var _iterator4 = (0, _getIterator3.default)(m.rtcpFb || []), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) { - var fb = _step4.value; - - var _codec2 = codecsMap.get(fb.payload); - - if (!_codec2) continue; - - var feedback = { - type: fb.type, - parameter: fb.subtype || '' - }; - - _codec2.rtcpFeedback.push(feedback); - } - - // Get RTP header extensions. - } catch (err) { - _didIteratorError4 = true; - _iteratorError4 = err; - } finally { - try { - if (!_iteratorNormalCompletion4 && _iterator4.return) { - _iterator4.return(); - } - } finally { - if (_didIteratorError4) { - throw _iteratorError4; - } - } - } - - var _iteratorNormalCompletion5 = true; - var _didIteratorError5 = false; - var _iteratorError5 = undefined; - - try { - for (var _iterator5 = (0, _getIterator3.default)(m.ext || []), _step5; !(_iteratorNormalCompletion5 = (_step5 = _iterator5.next()).done); _iteratorNormalCompletion5 = true) { - var ext = _step5.value; - - var headerExtension = { - kind: kind, - uri: ext.uri, - preferredId: ext.value - }; - - headerExtensions.push(headerExtension); - } - } catch (err) { - _didIteratorError5 = true; - _iteratorError5 = err; - } finally { - try { - if (!_iteratorNormalCompletion5 && _iterator5.return) { - _iterator5.return(); - } - } finally { - if (_didIteratorError5) { - throw _iteratorError5; - } - } - } - } - } catch (err) { - _didIteratorError = true; - _iteratorError = err; - } finally { - try { - if (!_iteratorNormalCompletion && _iterator.return) { - _iterator.return(); - } - } finally { - if (_didIteratorError) { - throw _iteratorError; - } - } - } - - var rtpCapabilities = { - codecs: (0, _from2.default)(codecsMap.values()), - headerExtensions: headerExtensions, - fecMechanisms: [] // TODO - }; - - return rtpCapabilities; -} - -/** - * Extract DTLS parameters from a SDP. - * - * @param {Object} sdpObj - SDP Object generated by sdp-transform. - * @return {RTCDtlsParameters} - */ -function extractDtlsParameters(sdpObj) { - var media = getFirstActiveMediaSection(sdpObj); - var fingerprint = media.fingerprint || sdpObj.fingerprint; - var role = void 0; - - switch (media.setup) { - case 'active': - role = 'client'; - break; - case 'passive': - role = 'server'; - break; - case 'actpass': - role = 'auto'; - break; - } - - var dtlsParameters = { - role: role, - fingerprints: [{ - algorithm: fingerprint.type, - value: fingerprint.hash - }] - }; - - return dtlsParameters; -} - -/** - * Get the first acive media section. - * - * @private - * @param {Object} sdpObj - SDP Object generated by sdp-transform. - * @return {Object} SDP media section as parsed by sdp-transform. - */ -function getFirstActiveMediaSection(sdpObj) { - return (sdpObj.media || []).find(function (m) { - return m.iceUfrag && m.port !== 0; - }); -} - -},{"babel-runtime/core-js/array/from":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/core-js/array/from.js","babel-runtime/core-js/get-iterator":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/core-js/get-iterator.js","babel-runtime/core-js/map":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/core-js/map.js","sdp-transform":"/Users/ibc/src/mediasoup-client/node_modules/sdp-transform/lib/index.js"}],"/Users/ibc/src/mediasoup-client/lib/handlers/sdp/planBUtils.js":[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.fillRtpParametersForTrack = fillRtpParametersForTrack; -/** - * Fill the given RTP parameters for the given track. - * - * NOTE: Currently it assumes a single encoding (no simulcast). - * - * @param {RTCRtpParameters} rtpParameters - RTP parameters to be filled. - * @param {Object} sdpObj - Local SDP Object generated by sdp-transform. - * @param {MediaStreamTrack} track - */ -function fillRtpParametersForTrack(rtpParameters, sdpObj, track) { - var kind = track.kind; - var encoding = {}; - var rtcp = { - cname: null, - reducedSize: true, - mux: true - }; - - var mSection = (sdpObj.media || []).find(function (m) { - return m.type === kind; - }); - - if (!mSection) throw new Error('m=' + kind + ' section not found'); - - // Get the SSRC. - - var ssrcMsidLine = (mSection.ssrcs || []).find(function (line) { - if (line.attribute !== 'msid') return false; - - var trackId = line.value.split(' ')[1]; - - if (trackId === track.id) return true; - }); - - if (!ssrcMsidLine) throw new Error('a=ssrc line not found for local track [track.id:' + track.id + ']'); - - var ssrc = ssrcMsidLine.id; - - encoding.ssrc = ssrc; - - // Get the SSRC for RTX. - - (mSection.ssrcGroups || []).some(function (line) { - if (line.semantics !== 'FID') return; - - var ssrcs = line.ssrcs.split(/[ ]+/); - - if (Number(ssrcs[0]) === ssrc) { - var rtxSsrc = Number(ssrcs[1]); - - encoding.rtx = { ssrc: rtxSsrc }; - - return true; - } - }); - - // Get RTCP info. - - var ssrcCnameLine = mSection.ssrcs.find(function (line) { - return line.attribute === 'cname' && line.id === ssrc; - }); - - if (ssrcCnameLine) rtcp.cname = ssrcCnameLine.value; - - // Fill RTP parameters. - rtpParameters.encodings = [encoding]; - rtpParameters.rtcp = rtcp; -} - -},{}],"/Users/ibc/src/mediasoup-client/lib/handlers/sdp/unifiedPlanUtils.js":[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.fillRtpParametersForTrack = fillRtpParametersForTrack; -/** - * Fill the given RTP parameters for the given track. - * - * NOTE: Currently it assumes a single encoding (no simulcast). - * - * @param {RTCRtpParameters} rtpParameters - RTP parameters to be filled. - * @param {Object} sdpObj - Local SDP Object generated by sdp-transform. - * @param {MediaStreamTrack} track - */ -function fillRtpParametersForTrack(rtpParameters, sdpObj, track) { - var kind = track.kind; - var encoding = {}; - var rtcp = { - cname: null, - reducedSize: true, - mux: true - }; - - var mSection = (sdpObj.media || []).find(function (m) { - if (m.type !== kind) return; - - var msidLine = m.msid; - - if (!msidLine) return; - - var trackId = msidLine.split(' ')[1]; - - if (trackId === track.id) return true; - }); - - if (!mSection) throw new Error('m=' + kind + ' section not found'); - - // Get the SSRC and CNAME. - - var ssrcCnameLine = (mSection.ssrcs || []).find(function (line) { - return line.attribute === 'cname'; - }); - - if (!ssrcCnameLine) throw new Error('a=ssrc line not found for local track [track.id:' + track.id + ']'); - - var ssrc = ssrcCnameLine.id; - - encoding.ssrc = ssrcCnameLine.id; - rtcp.cname = ssrcCnameLine.value; - - // Get the SSRC for RTX. - - (mSection.ssrcGroups || []).some(function (line) { - if (line.semantics !== 'FID') return; - - var ssrcs = line.ssrcs.split(/[ ]+/); - - if (Number(ssrcs[0]) === ssrc) { - var rtxSsrc = Number(ssrcs[1]); - - encoding.rtx = { ssrc: rtxSsrc }; - - return true; - } - }); - - // Fill RTP parameters. - rtpParameters.encodings = [encoding]; - rtpParameters.rtcp = rtcp; -} - -},{}],"/Users/ibc/src/mediasoup-client/lib/index.js":[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.Room = undefined; -exports.isDeviceSupported = isDeviceSupported; -exports.getDeviceInfo = getDeviceInfo; - -var _Device = require('./Device'); - -var _Device2 = _interopRequireDefault(_Device); - -var _Room = require('./Room'); - -var _Room2 = _interopRequireDefault(_Room); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * Whether the current browser or device is supported. - * - * @return {Boolean} - * - * @example - * isDeviceSupported() - * // => true - */ -function isDeviceSupported() { - return _Device2.default.isSupported(); -} - -/** - * Get information regarding the current browser or device. - * - * @return {Object} - Object with `name` (String) and version {String}. - * - * @example - * getDeviceInfo() - * // => { name: "Chrome", version: "59.0" } - */ -function getDeviceInfo() { - return { - name: _Device2.default.name, - version: _Device2.default.version - }; -} - -/** - * Expose the Room class. - * - * @example - * const room = new Room();` - */ -exports.Room = _Room2.default; - -},{"./Device":"/Users/ibc/src/mediasoup-client/lib/Device.js","./Room":"/Users/ibc/src/mediasoup-client/lib/Room.js"}],"/Users/ibc/src/mediasoup-client/lib/utils.js":[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _getIterator2 = require('babel-runtime/core-js/get-iterator'); - -var _getIterator3 = _interopRequireDefault(_getIterator2); - -var _stringify = require('babel-runtime/core-js/json/stringify'); - -var _stringify2 = _interopRequireDefault(_stringify); - -exports.randomNumber = randomNumber; -exports.clone = clone; -exports.getExtendedRtpCapabilities = getExtendedRtpCapabilities; -exports.getRtpCapabilities = getRtpCapabilities; -exports.canSend = canSend; -exports.canReceive = canReceive; -exports.getSendingRtpParameters = getSendingRtpParameters; -exports.getReceivingFullRtpParameters = getReceivingFullRtpParameters; - -var _randomNumber = require('random-number'); - -var _randomNumber2 = _interopRequireDefault(_randomNumber); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -var randomNumberGenerator = _randomNumber2.default.generator({ - min: 10000000, - max: 99999999, - integer: true -}); - -/** - * Generates a random positive number between 10000000 and 99999999. - * - * @return {Number} - */ -function randomNumber() { - return randomNumberGenerator(); -} - -/** - * Clones the given Object/Array. - * - * @param {Object|Array} obj - * @return {Object|Array} - */ -function clone(obj) { - return JSON.parse((0, _stringify2.default)(obj)); -} - -/** - * Generate extended RTP capabilities for sending and receiving. - * - * @param {RTCRtpCapabilities} localCaps - Local capabilities. - * @param {RTCRtpCapabilities} remoteCaps - Remote capabilities. - * @return {RTCExtendedRtpCapabilities} - */ -function getExtendedRtpCapabilities(localCaps, remoteCaps) { - var extendedCaps = { - codecs: [], - headerExtensions: [], - fecMechanisms: [] - }; - - // Match media codecs and keep the order preferred by remoteCaps. - var _iteratorNormalCompletion = true; - var _didIteratorError = false; - var _iteratorError = undefined; - - try { - var _loop = function _loop() { - var remoteCodec = _step.value; - - // TODO: Ignore pseudo-codecs and feature codecs. - if (remoteCodec.name === 'rtx') return 'continue'; - - var matchingLocalCodec = (localCaps.codecs || []).find(function (localCodec) { - return matchCodecs(localCodec, remoteCodec); - }); - - if (matchingLocalCodec) { - var extendedCodec = { - name: remoteCodec.name, - mimeType: remoteCodec.mimeType, - kind: remoteCodec.kind, - clockRate: remoteCodec.clockRate, - sendPayloadType: matchingLocalCodec.preferredPayloadType, - sendRtxPayloadType: null, - recvPayloadType: remoteCodec.preferredPayloadType, - recvRtxPayloadType: null, - channels: remoteCodec.channels, - rtcpFeedback: reduceRtcpFeedback(matchingLocalCodec, remoteCodec), - parameters: remoteCodec.parameters - }; - - if (!(extendedCodec.channels > 1)) delete extendedCodec.channels; - - extendedCaps.codecs.push(extendedCodec); - } - }; - - for (var _iterator = (0, _getIterator3.default)(remoteCaps.codecs || []), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { - var _ret = _loop(); - - if (_ret === 'continue') continue; - } - - // Match RTX codecs. - } catch (err) { - _didIteratorError = true; - _iteratorError = err; - } finally { - try { - if (!_iteratorNormalCompletion && _iterator.return) { - _iterator.return(); - } - } finally { - if (_didIteratorError) { - throw _iteratorError; - } - } - } - - var _iteratorNormalCompletion2 = true; - var _didIteratorError2 = false; - var _iteratorError2 = undefined; - - try { - var _loop2 = function _loop2() { - var extendedCodec = _step2.value; - - var matchingLocalRtxCodec = (localCaps.codecs || []).find(function (localCodec) { - return localCodec.name === 'rtx' && localCodec.parameters.apt === extendedCodec.sendPayloadType; - }); - - var matchingRemoteRtxCodec = (remoteCaps.codecs || []).find(function (remoteCodec) { - return remoteCodec.name === 'rtx' && remoteCodec.parameters.apt === extendedCodec.recvPayloadType; - }); - - if (matchingLocalRtxCodec && matchingRemoteRtxCodec) { - extendedCodec.sendRtxPayloadType = matchingLocalRtxCodec.preferredPayloadType; - extendedCodec.recvRtxPayloadType = matchingRemoteRtxCodec.preferredPayloadType; - } - }; - - for (var _iterator2 = (0, _getIterator3.default)(extendedCaps.codecs || []), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { - _loop2(); - } - - // Match header extensions. - } catch (err) { - _didIteratorError2 = true; - _iteratorError2 = err; - } finally { - try { - if (!_iteratorNormalCompletion2 && _iterator2.return) { - _iterator2.return(); - } - } finally { - if (_didIteratorError2) { - throw _iteratorError2; - } - } - } - - var _iteratorNormalCompletion3 = true; - var _didIteratorError3 = false; - var _iteratorError3 = undefined; - - try { - var _loop3 = function _loop3() { - var remoteExt = _step3.value; - - var matchingLocalExt = (localCaps.headerExtensions || []).find(function (localExt) { - return matchHeaderExtensions(localExt, remoteExt); - }); - - if (matchingLocalExt) { - var extendedExt = { - kind: remoteExt.kind, - uri: remoteExt.uri, - sendId: matchingLocalExt.preferredId, - recvId: remoteExt.preferredId - }; - - extendedCaps.headerExtensions.push(extendedExt); - } - }; - - for (var _iterator3 = (0, _getIterator3.default)(remoteCaps.headerExtensions || []), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) { - _loop3(); - } - } catch (err) { - _didIteratorError3 = true; - _iteratorError3 = err; - } finally { - try { - if (!_iteratorNormalCompletion3 && _iterator3.return) { - _iterator3.return(); - } - } finally { - if (_didIteratorError3) { - throw _iteratorError3; - } - } - } - - return extendedCaps; -} - -/** - * Generate RTP capabilities based on the given extended RTP capabilities. - * - * @param {RTCExtendedRtpCapabilities} extendedRtpCapabilities - * @return {RTCRtpCapabilities} - */ -function getRtpCapabilities(extendedRtpCapabilities) { - var caps = { - codecs: [], - headerExtensions: [], - fecMechanisms: [] - }; - - var _iteratorNormalCompletion4 = true; - var _didIteratorError4 = false; - var _iteratorError4 = undefined; - - try { - for (var _iterator4 = (0, _getIterator3.default)(extendedRtpCapabilities.codecs), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) { - var capCodec = _step4.value; - - var codec = { - name: capCodec.name, - mimeType: capCodec.mimeType, - kind: capCodec.kind, - clockRate: capCodec.clockRate, - preferredPayloadType: capCodec.recvPayloadType, - channels: capCodec.channels, - rtcpFeedback: capCodec.rtcpFeedback, - parameters: capCodec.parameters - }; - - if (!(codec.channels > 1)) delete codec.channels; - - caps.codecs.push(codec); - - // Add RTX codec. - if (capCodec.recvRtxPayloadType) { - var rtxCapCodec = { - name: 'rtx', - mimeType: capCodec.kind + '/rtx', - clockRate: capCodec.clockRate, - payloadType: capCodec.recvRtxPayloadType, - parameters: { - apt: capCodec.recvPayloadType - } - }; - - caps.codecs.push(rtxCapCodec); - } - - // TODO: In the future, we need to add FEC, CN, etc, codecs. - } - } catch (err) { - _didIteratorError4 = true; - _iteratorError4 = err; - } finally { - try { - if (!_iteratorNormalCompletion4 && _iterator4.return) { - _iterator4.return(); - } - } finally { - if (_didIteratorError4) { - throw _iteratorError4; - } - } - } - - var _iteratorNormalCompletion5 = true; - var _didIteratorError5 = false; - var _iteratorError5 = undefined; - - try { - for (var _iterator5 = (0, _getIterator3.default)(extendedRtpCapabilities.headerExtensions), _step5; !(_iteratorNormalCompletion5 = (_step5 = _iterator5.next()).done); _iteratorNormalCompletion5 = true) { - var capExt = _step5.value; - - var ext = { - kind: capExt.kind, - uri: capExt.uri, - preferredId: capExt.recvId - }; - - caps.headerExtensions.push(ext); - } - } catch (err) { - _didIteratorError5 = true; - _iteratorError5 = err; - } finally { - try { - if (!_iteratorNormalCompletion5 && _iterator5.return) { - _iterator5.return(); - } - } finally { - if (_didIteratorError5) { - throw _iteratorError5; - } - } - } - - caps.fecMechanisms = extendedRtpCapabilities.fecMechanisms; - - return caps; -} - -/** - * Whether media can be sent based on the given RTP capabilities. - * - * @param {String} kind - * @param {RTCExtendedRtpCapabilities} extendedRtpCapabilities - * @return {Boolean} - */ -function canSend(kind, extendedRtpCapabilities) { - return extendedRtpCapabilities.codecs.some(function (codec) { - return codec.kind === kind; - }); -} - -/** - * Whether the given RTP parameters can be received with the given RTP - * capabilities. - * - * @param {RTCRtpParameters} rtpParameters - * @param {RTCExtendedRtpCapabilities} extendedRtpCapabilities - * @return {Boolean} - */ -function canReceive(rtpParameters, extendedRtpCapabilities) { - var firstMediaCodec = rtpParameters.codecs[0]; - - return extendedRtpCapabilities.codecs.some(function (codec) { - return codec.recvPayloadType === firstMediaCodec.payloadType; - }); -} - -/** - * Generate RTP parameters of the given kind for sending media. - * Just the first media codec per kind is considered. - * NOTE: muxId, encodings and rtcp fields are left empty. - * - * @param {kind} kind - * @param {RTCExtendedRtpCapabilities} extendedRtpCapabilities - * @return {RTCRtpParameters} - */ -function getSendingRtpParameters(kind, extendedRtpCapabilities) { - var params = { - muxId: null, - codecs: [], - headerExtensions: [], - encodings: [], - rtcp: {} - }; - - var _iteratorNormalCompletion6 = true; - var _didIteratorError6 = false; - var _iteratorError6 = undefined; - - try { - for (var _iterator6 = (0, _getIterator3.default)(extendedRtpCapabilities.codecs), _step6; !(_iteratorNormalCompletion6 = (_step6 = _iterator6.next()).done); _iteratorNormalCompletion6 = true) { - var capCodec = _step6.value; - - if (capCodec.kind !== kind) continue; - - var codec = { - name: capCodec.name, - mimeType: capCodec.mimeType, - clockRate: capCodec.clockRate, - payloadType: capCodec.sendPayloadType, - channels: capCodec.channels, - rtcpFeedback: capCodec.rtcpFeedback, - parameters: capCodec.parameters - }; - - if (!(codec.channels > 1)) delete codec.channels; - - params.codecs.push(codec); - - // Add RTX codec. - if (capCodec.sendRtxPayloadType) { - var rtxCodec = { - name: 'rtx', - mimeType: capCodec.kind + '/rtx', - clockRate: capCodec.clockRate, - payloadType: capCodec.sendRtxPayloadType, - parameters: { - apt: capCodec.sendPayloadType - } - }; - - params.codecs.push(rtxCodec); - } - - // NOTE: We assume a single media codec plus an optional RTX codec for now. - // TODO: In the future, we need to add FEC, CN, etc, codecs. - break; - } - } catch (err) { - _didIteratorError6 = true; - _iteratorError6 = err; - } finally { - try { - if (!_iteratorNormalCompletion6 && _iterator6.return) { - _iterator6.return(); - } - } finally { - if (_didIteratorError6) { - throw _iteratorError6; - } - } - } - - var _iteratorNormalCompletion7 = true; - var _didIteratorError7 = false; - var _iteratorError7 = undefined; - - try { - for (var _iterator7 = (0, _getIterator3.default)(extendedRtpCapabilities.headerExtensions), _step7; !(_iteratorNormalCompletion7 = (_step7 = _iterator7.next()).done); _iteratorNormalCompletion7 = true) { - var capExt = _step7.value; - - if (capExt.kind !== kind) continue; - - var ext = { - uri: capExt.uri, - id: capExt.sendId - }; - - params.headerExtensions.push(ext); - } - } catch (err) { - _didIteratorError7 = true; - _iteratorError7 = err; - } finally { - try { - if (!_iteratorNormalCompletion7 && _iterator7.return) { - _iterator7.return(); - } - } finally { - if (_didIteratorError7) { - throw _iteratorError7; - } - } - } - - return params; -} - -/** - * Generate RTP parameters of the given kind for receiving media. - * All the media codecs per kind are considered. This is useful for generating - * a SDP remote offer. - * NOTE: muxId, encodings and rtcp fields are left empty. - * - * @param {String} kind - * @param {RTCExtendedRtpCapabilities} extendedRtpCapabilities - * @return {RTCRtpParameters} - */ -function getReceivingFullRtpParameters(kind, extendedRtpCapabilities) { - var params = { - muxId: null, - codecs: [], - headerExtensions: [], - encodings: [], - rtcp: {} - }; - - var _iteratorNormalCompletion8 = true; - var _didIteratorError8 = false; - var _iteratorError8 = undefined; - - try { - for (var _iterator8 = (0, _getIterator3.default)(extendedRtpCapabilities.codecs), _step8; !(_iteratorNormalCompletion8 = (_step8 = _iterator8.next()).done); _iteratorNormalCompletion8 = true) { - var capCodec = _step8.value; - - if (capCodec.kind !== kind) continue; - - var codec = { - name: capCodec.name, - mimeType: capCodec.mimeType, - clockRate: capCodec.clockRate, - payloadType: capCodec.recvPayloadType, - channels: capCodec.channels, - rtcpFeedback: capCodec.rtcpFeedback, - parameters: capCodec.parameters - }; - - if (!(codec.channels > 1)) delete codec.channels; - - params.codecs.push(codec); - - // Add RTX codec. - if (capCodec.recvRtxPayloadType) { - var rtxCodec = { - name: 'rtx', - mimeType: capCodec.kind + '/rtx', - clockRate: capCodec.clockRate, - payloadType: capCodec.recvRtxPayloadType, - parameters: { - apt: capCodec.recvPayloadType - } - }; - - params.codecs.push(rtxCodec); - } - - // TODO: In the future, we need to add FEC, CN, etc, codecs. - } - } catch (err) { - _didIteratorError8 = true; - _iteratorError8 = err; - } finally { - try { - if (!_iteratorNormalCompletion8 && _iterator8.return) { - _iterator8.return(); - } - } finally { - if (_didIteratorError8) { - throw _iteratorError8; - } - } - } - - var _iteratorNormalCompletion9 = true; - var _didIteratorError9 = false; - var _iteratorError9 = undefined; - - try { - for (var _iterator9 = (0, _getIterator3.default)(extendedRtpCapabilities.headerExtensions), _step9; !(_iteratorNormalCompletion9 = (_step9 = _iterator9.next()).done); _iteratorNormalCompletion9 = true) { - var capExt = _step9.value; - - if (capExt.kind !== kind) continue; - - var ext = { - uri: capExt.uri, - id: capExt.recvId - }; - - params.headerExtensions.push(ext); - } - } catch (err) { - _didIteratorError9 = true; - _iteratorError9 = err; - } finally { - try { - if (!_iteratorNormalCompletion9 && _iterator9.return) { - _iterator9.return(); - } - } finally { - if (_didIteratorError9) { - throw _iteratorError9; - } - } - } - - return params; -} - -function matchCodecs(aCodec, bCodec) { - return aCodec.mimeType === bCodec.mimeType && aCodec.clockRate === bCodec.clockRate; -} - -function matchHeaderExtensions(aExt, bExt) { - return aExt.kind === bExt.kind && aExt.uri === bExt.uri; -} - -function reduceRtcpFeedback(codecA, codecB) { - var reducedRtcpFeedback = []; - - var _iteratorNormalCompletion10 = true; - var _didIteratorError10 = false; - var _iteratorError10 = undefined; - - try { - var _loop4 = function _loop4() { - var aFb = _step10.value; - - var matchingBFb = (codecB.rtcpFeedback || []).find(function (bFb) { - return bFb.type === aFb.type && bFb.parameter === aFb.parameter; - }); - - if (matchingBFb) reducedRtcpFeedback.push(matchingBFb); - }; - - for (var _iterator10 = (0, _getIterator3.default)(codecA.rtcpFeedback || []), _step10; !(_iteratorNormalCompletion10 = (_step10 = _iterator10.next()).done); _iteratorNormalCompletion10 = true) { - _loop4(); - } - } catch (err) { - _didIteratorError10 = true; - _iteratorError10 = err; - } finally { - try { - if (!_iteratorNormalCompletion10 && _iterator10.return) { - _iterator10.return(); - } - } finally { - if (_didIteratorError10) { - throw _iteratorError10; - } - } - } - - return reducedRtcpFeedback; -} - -},{"babel-runtime/core-js/get-iterator":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/core-js/get-iterator.js","babel-runtime/core-js/json/stringify":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/core-js/json/stringify.js","random-number":"/Users/ibc/src/mediasoup-client/node_modules/random-number/index.js"}],"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/core-js/array/from.js":[function(require,module,exports){ -module.exports = { "default": require("core-js/library/fn/array/from"), __esModule: true }; -},{"core-js/library/fn/array/from":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/fn/array/from.js"}],"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/core-js/get-iterator.js":[function(require,module,exports){ -module.exports = { "default": require("core-js/library/fn/get-iterator"), __esModule: true }; -},{"core-js/library/fn/get-iterator":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/fn/get-iterator.js"}],"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/core-js/json/stringify.js":[function(require,module,exports){ -module.exports = { "default": require("core-js/library/fn/json/stringify"), __esModule: true }; -},{"core-js/library/fn/json/stringify":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/fn/json/stringify.js"}],"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/core-js/map.js":[function(require,module,exports){ -module.exports = { "default": require("core-js/library/fn/map"), __esModule: true }; -},{"core-js/library/fn/map":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/fn/map.js"}],"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/core-js/object/assign.js":[function(require,module,exports){ -module.exports = { "default": require("core-js/library/fn/object/assign"), __esModule: true }; -},{"core-js/library/fn/object/assign":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/fn/object/assign.js"}],"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/core-js/object/create.js":[function(require,module,exports){ -module.exports = { "default": require("core-js/library/fn/object/create"), __esModule: true }; -},{"core-js/library/fn/object/create":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/fn/object/create.js"}],"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/core-js/object/define-property.js":[function(require,module,exports){ -module.exports = { "default": require("core-js/library/fn/object/define-property"), __esModule: true }; -},{"core-js/library/fn/object/define-property":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/fn/object/define-property.js"}],"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/core-js/object/get-prototype-of.js":[function(require,module,exports){ -module.exports = { "default": require("core-js/library/fn/object/get-prototype-of"), __esModule: true }; -},{"core-js/library/fn/object/get-prototype-of":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/fn/object/get-prototype-of.js"}],"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/core-js/object/keys.js":[function(require,module,exports){ -module.exports = { "default": require("core-js/library/fn/object/keys"), __esModule: true }; -},{"core-js/library/fn/object/keys":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/fn/object/keys.js"}],"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/core-js/object/set-prototype-of.js":[function(require,module,exports){ -module.exports = { "default": require("core-js/library/fn/object/set-prototype-of"), __esModule: true }; -},{"core-js/library/fn/object/set-prototype-of":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/fn/object/set-prototype-of.js"}],"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/core-js/promise.js":[function(require,module,exports){ -module.exports = { "default": require("core-js/library/fn/promise"), __esModule: true }; -},{"core-js/library/fn/promise":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/fn/promise.js"}],"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/core-js/set.js":[function(require,module,exports){ -module.exports = { "default": require("core-js/library/fn/set"), __esModule: true }; -},{"core-js/library/fn/set":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/fn/set.js"}],"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/core-js/symbol.js":[function(require,module,exports){ -module.exports = { "default": require("core-js/library/fn/symbol"), __esModule: true }; -},{"core-js/library/fn/symbol":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/fn/symbol/index.js"}],"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/core-js/symbol/iterator.js":[function(require,module,exports){ -module.exports = { "default": require("core-js/library/fn/symbol/iterator"), __esModule: true }; -},{"core-js/library/fn/symbol/iterator":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/fn/symbol/iterator.js"}],"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/helpers/classCallCheck.js":[function(require,module,exports){ -"use strict"; - -exports.__esModule = true; - -exports.default = function (instance, Constructor) { - if (!(instance instanceof Constructor)) { - throw new TypeError("Cannot call a class as a function"); - } -}; -},{}],"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/helpers/createClass.js":[function(require,module,exports){ -"use strict"; - -exports.__esModule = true; - -var _defineProperty = require("../core-js/object/define-property"); - -var _defineProperty2 = _interopRequireDefault(_defineProperty); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -exports.default = function () { - function defineProperties(target, props) { - for (var i = 0; i < props.length; i++) { - var descriptor = props[i]; - descriptor.enumerable = descriptor.enumerable || false; - descriptor.configurable = true; - if ("value" in descriptor) descriptor.writable = true; - (0, _defineProperty2.default)(target, descriptor.key, descriptor); - } - } - - return function (Constructor, protoProps, staticProps) { - if (protoProps) defineProperties(Constructor.prototype, protoProps); - if (staticProps) defineProperties(Constructor, staticProps); - return Constructor; - }; -}(); -},{"../core-js/object/define-property":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/core-js/object/define-property.js"}],"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/helpers/extends.js":[function(require,module,exports){ -"use strict"; - -exports.__esModule = true; - -var _assign = require("../core-js/object/assign"); - -var _assign2 = _interopRequireDefault(_assign); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -exports.default = _assign2.default || function (target) { - for (var i = 1; i < arguments.length; i++) { - var source = arguments[i]; - - for (var key in source) { - if (Object.prototype.hasOwnProperty.call(source, key)) { - target[key] = source[key]; - } - } - } - - return target; -}; -},{"../core-js/object/assign":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/core-js/object/assign.js"}],"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/helpers/inherits.js":[function(require,module,exports){ -"use strict"; - -exports.__esModule = true; - -var _setPrototypeOf = require("../core-js/object/set-prototype-of"); - -var _setPrototypeOf2 = _interopRequireDefault(_setPrototypeOf); - -var _create = require("../core-js/object/create"); - -var _create2 = _interopRequireDefault(_create); - -var _typeof2 = require("../helpers/typeof"); - -var _typeof3 = _interopRequireDefault(_typeof2); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -exports.default = function (subClass, superClass) { - if (typeof superClass !== "function" && superClass !== null) { - throw new TypeError("Super expression must either be null or a function, not " + (typeof superClass === "undefined" ? "undefined" : (0, _typeof3.default)(superClass))); - } - - subClass.prototype = (0, _create2.default)(superClass && superClass.prototype, { - constructor: { - value: subClass, - enumerable: false, - writable: true, - configurable: true - } - }); - if (superClass) _setPrototypeOf2.default ? (0, _setPrototypeOf2.default)(subClass, superClass) : subClass.__proto__ = superClass; -}; -},{"../core-js/object/create":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/core-js/object/create.js","../core-js/object/set-prototype-of":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/core-js/object/set-prototype-of.js","../helpers/typeof":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/helpers/typeof.js"}],"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/helpers/possibleConstructorReturn.js":[function(require,module,exports){ -"use strict"; - -exports.__esModule = true; - -var _typeof2 = require("../helpers/typeof"); - -var _typeof3 = _interopRequireDefault(_typeof2); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -exports.default = function (self, call) { - if (!self) { - throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); - } - - return call && ((typeof call === "undefined" ? "undefined" : (0, _typeof3.default)(call)) === "object" || typeof call === "function") ? call : self; -}; -},{"../helpers/typeof":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/helpers/typeof.js"}],"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/helpers/typeof.js":[function(require,module,exports){ -"use strict"; - -exports.__esModule = true; - -var _iterator = require("../core-js/symbol/iterator"); - -var _iterator2 = _interopRequireDefault(_iterator); - -var _symbol = require("../core-js/symbol"); - -var _symbol2 = _interopRequireDefault(_symbol); - -var _typeof = typeof _symbol2.default === "function" && typeof _iterator2.default === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof _symbol2.default === "function" && obj.constructor === _symbol2.default && obj !== _symbol2.default.prototype ? "symbol" : typeof obj; }; - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -exports.default = typeof _symbol2.default === "function" && _typeof(_iterator2.default) === "symbol" ? function (obj) { - return typeof obj === "undefined" ? "undefined" : _typeof(obj); -} : function (obj) { - return obj && typeof _symbol2.default === "function" && obj.constructor === _symbol2.default && obj !== _symbol2.default.prototype ? "symbol" : typeof obj === "undefined" ? "undefined" : _typeof(obj); -}; -},{"../core-js/symbol":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/core-js/symbol.js","../core-js/symbol/iterator":"/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/core-js/symbol/iterator.js"}],"/Users/ibc/src/mediasoup-client/node_modules/bowser/src/bowser.js":[function(require,module,exports){ -/*! - * Bowser - a browser detector - * https://github.com/ded/bowser - * MIT License | (c) Dustin Diaz 2015 - */ - -!function (root, name, definition) { - if (typeof module != 'undefined' && module.exports) module.exports = definition() - else if (typeof define == 'function' && define.amd) define(name, definition) - else root[name] = definition() -}(this, 'bowser', function () { - /** - * See useragents.js for examples of navigator.userAgent - */ - - var t = true - - function detect(ua) { - - function getFirstMatch(regex) { - var match = ua.match(regex); - return (match && match.length > 1 && match[1]) || ''; - } - - function getSecondMatch(regex) { - var match = ua.match(regex); - return (match && match.length > 1 && match[2]) || ''; - } - - var iosdevice = getFirstMatch(/(ipod|iphone|ipad)/i).toLowerCase() - , likeAndroid = /like android/i.test(ua) - , android = !likeAndroid && /android/i.test(ua) - , nexusMobile = /nexus\s*[0-6]\s*/i.test(ua) - , nexusTablet = !nexusMobile && /nexus\s*[0-9]+/i.test(ua) - , chromeos = /CrOS/.test(ua) - , silk = /silk/i.test(ua) - , sailfish = /sailfish/i.test(ua) - , tizen = /tizen/i.test(ua) - , webos = /(web|hpw)os/i.test(ua) - , windowsphone = /windows phone/i.test(ua) - , samsungBrowser = /SamsungBrowser/i.test(ua) - , windows = !windowsphone && /windows/i.test(ua) - , mac = !iosdevice && !silk && /macintosh/i.test(ua) - , linux = !android && !sailfish && !tizen && !webos && /linux/i.test(ua) - , edgeVersion = getFirstMatch(/edge\/(\d+(\.\d+)?)/i) - , versionIdentifier = getFirstMatch(/version\/(\d+(\.\d+)?)/i) - , tablet = /tablet/i.test(ua) && !/tablet pc/i.test(ua) - , mobile = !tablet && /[^-]mobi/i.test(ua) - , xbox = /xbox/i.test(ua) - , result - - if (/opera/i.test(ua)) { - // an old Opera - result = { - name: 'Opera' - , opera: t - , version: versionIdentifier || getFirstMatch(/(?:opera|opr|opios)[\s\/](\d+(\.\d+)?)/i) - } - } else if (/opr|opios/i.test(ua)) { - // a new Opera - result = { - name: 'Opera' - , opera: t - , version: getFirstMatch(/(?:opr|opios)[\s\/](\d+(\.\d+)?)/i) || versionIdentifier - } - } - else if (/SamsungBrowser/i.test(ua)) { - result = { - name: 'Samsung Internet for Android' - , samsungBrowser: t - , version: versionIdentifier || getFirstMatch(/(?:SamsungBrowser)[\s\/](\d+(\.\d+)?)/i) - } - } - else if (/coast/i.test(ua)) { - result = { - name: 'Opera Coast' - , coast: t - , version: versionIdentifier || getFirstMatch(/(?:coast)[\s\/](\d+(\.\d+)?)/i) - } - } - else if (/yabrowser/i.test(ua)) { - result = { - name: 'Yandex Browser' - , yandexbrowser: t - , version: versionIdentifier || getFirstMatch(/(?:yabrowser)[\s\/](\d+(\.\d+)?)/i) - } - } - else if (/ucbrowser/i.test(ua)) { - result = { - name: 'UC Browser' - , ucbrowser: t - , version: getFirstMatch(/(?:ucbrowser)[\s\/](\d+(?:\.\d+)+)/i) - } - } - else if (/mxios/i.test(ua)) { - result = { - name: 'Maxthon' - , maxthon: t - , version: getFirstMatch(/(?:mxios)[\s\/](\d+(?:\.\d+)+)/i) - } - } - else if (/epiphany/i.test(ua)) { - result = { - name: 'Epiphany' - , epiphany: t - , version: getFirstMatch(/(?:epiphany)[\s\/](\d+(?:\.\d+)+)/i) - } - } - else if (/puffin/i.test(ua)) { - result = { - name: 'Puffin' - , puffin: t - , version: getFirstMatch(/(?:puffin)[\s\/](\d+(?:\.\d+)?)/i) - } - } - else if (/sleipnir/i.test(ua)) { - result = { - name: 'Sleipnir' - , sleipnir: t - , version: getFirstMatch(/(?:sleipnir)[\s\/](\d+(?:\.\d+)+)/i) - } - } - else if (/k-meleon/i.test(ua)) { - result = { - name: 'K-Meleon' - , kMeleon: t - , version: getFirstMatch(/(?:k-meleon)[\s\/](\d+(?:\.\d+)+)/i) - } - } - else if (windowsphone) { - result = { - name: 'Windows Phone' - , windowsphone: t - } - if (edgeVersion) { - result.msedge = t - result.version = edgeVersion - } - else { - result.msie = t - result.version = getFirstMatch(/iemobile\/(\d+(\.\d+)?)/i) - } - } - else if (/msie|trident/i.test(ua)) { - result = { - name: 'Internet Explorer' - , msie: t - , version: getFirstMatch(/(?:msie |rv:)(\d+(\.\d+)?)/i) - } - } else if (chromeos) { - result = { - name: 'Chrome' - , chromeos: t - , chromeBook: t - , chrome: t - , version: getFirstMatch(/(?:chrome|crios|crmo)\/(\d+(\.\d+)?)/i) - } - } else if (/chrome.+? edge/i.test(ua)) { - result = { - name: 'Microsoft Edge' - , msedge: t - , version: edgeVersion - } - } - else if (/vivaldi/i.test(ua)) { - result = { - name: 'Vivaldi' - , vivaldi: t - , version: getFirstMatch(/vivaldi\/(\d+(\.\d+)?)/i) || versionIdentifier - } - } - else if (sailfish) { - result = { - name: 'Sailfish' - , sailfish: t - , version: getFirstMatch(/sailfish\s?browser\/(\d+(\.\d+)?)/i) - } - } - else if (/seamonkey\//i.test(ua)) { - result = { - name: 'SeaMonkey' - , seamonkey: t - , version: getFirstMatch(/seamonkey\/(\d+(\.\d+)?)/i) - } - } - else if (/firefox|iceweasel|fxios/i.test(ua)) { - result = { - name: 'Firefox' - , firefox: t - , version: getFirstMatch(/(?:firefox|iceweasel|fxios)[ \/](\d+(\.\d+)?)/i) - } - if (/\((mobile|tablet);[^\)]*rv:[\d\.]+\)/i.test(ua)) { - result.firefoxos = t - } - } - else if (silk) { - result = { - name: 'Amazon Silk' - , silk: t - , version : getFirstMatch(/silk\/(\d+(\.\d+)?)/i) - } - } - else if (/phantom/i.test(ua)) { - result = { - name: 'PhantomJS' - , phantom: t - , version: getFirstMatch(/phantomjs\/(\d+(\.\d+)?)/i) - } - } - else if (/slimerjs/i.test(ua)) { - result = { - name: 'SlimerJS' - , slimer: t - , version: getFirstMatch(/slimerjs\/(\d+(\.\d+)?)/i) - } - } - else if (/blackberry|\bbb\d+/i.test(ua) || /rim\stablet/i.test(ua)) { - result = { - name: 'BlackBerry' - , blackberry: t - , version: versionIdentifier || getFirstMatch(/blackberry[\d]+\/(\d+(\.\d+)?)/i) - } - } - else if (webos) { - result = { - name: 'WebOS' - , webos: t - , version: versionIdentifier || getFirstMatch(/w(?:eb)?osbrowser\/(\d+(\.\d+)?)/i) - }; - /touchpad\//i.test(ua) && (result.touchpad = t) - } - else if (/bada/i.test(ua)) { - result = { - name: 'Bada' - , bada: t - , version: getFirstMatch(/dolfin\/(\d+(\.\d+)?)/i) - }; - } - else if (tizen) { - result = { - name: 'Tizen' - , tizen: t - , version: getFirstMatch(/(?:tizen\s?)?browser\/(\d+(\.\d+)?)/i) || versionIdentifier - }; - } - else if (/qupzilla/i.test(ua)) { - result = { - name: 'QupZilla' - , qupzilla: t - , version: getFirstMatch(/(?:qupzilla)[\s\/](\d+(?:\.\d+)+)/i) || versionIdentifier - } - } - else if (/chromium/i.test(ua)) { - result = { - name: 'Chromium' - , chromium: t - , version: getFirstMatch(/(?:chromium)[\s\/](\d+(?:\.\d+)?)/i) || versionIdentifier - } - } - else if (/chrome|crios|crmo/i.test(ua)) { - result = { - name: 'Chrome' - , chrome: t - , version: getFirstMatch(/(?:chrome|crios|crmo)\/(\d+(\.\d+)?)/i) - } - } - else if (android) { - result = { - name: 'Android' - , version: versionIdentifier - } - } - else if (/safari|applewebkit/i.test(ua)) { - result = { - name: 'Safari' - , safari: t - } - if (versionIdentifier) { - result.version = versionIdentifier - } - } - else if (iosdevice) { - result = { - name : iosdevice == 'iphone' ? 'iPhone' : iosdevice == 'ipad' ? 'iPad' : 'iPod' - } - // WTF: version is not part of user agent in web apps - if (versionIdentifier) { - result.version = versionIdentifier - } - } - else if(/googlebot/i.test(ua)) { - result = { - name: 'Googlebot' - , googlebot: t - , version: getFirstMatch(/googlebot\/(\d+(\.\d+))/i) || versionIdentifier - } - } - else { - result = { - name: getFirstMatch(/^(.*)\/(.*) /), - version: getSecondMatch(/^(.*)\/(.*) /) - }; - } - - // set webkit or gecko flag for browsers based on these engines - if (!result.msedge && /(apple)?webkit/i.test(ua)) { - if (/(apple)?webkit\/537\.36/i.test(ua)) { - result.name = result.name || "Blink" - result.blink = t - } else { - result.name = result.name || "Webkit" - result.webkit = t - } - if (!result.version && versionIdentifier) { - result.version = versionIdentifier - } - } else if (!result.opera && /gecko\//i.test(ua)) { - result.name = result.name || "Gecko" - result.gecko = t - result.version = result.version || getFirstMatch(/gecko\/(\d+(\.\d+)?)/i) - } - - // set OS flags for platforms that have multiple browsers - if (!result.windowsphone && !result.msedge && (android || result.silk)) { - result.android = t - } else if (!result.windowsphone && !result.msedge && iosdevice) { - result[iosdevice] = t - result.ios = t - } else if (mac) { - result.mac = t - } else if (xbox) { - result.xbox = t - } else if (windows) { - result.windows = t - } else if (linux) { - result.linux = t - } - - function getWindowsVersion (s) { - switch (s) { - case 'NT': return 'NT' - case 'XP': return 'XP' - case 'NT 5.0': return '2000' - case 'NT 5.1': return 'XP' - case 'NT 5.2': return '2003' - case 'NT 6.0': return 'Vista' - case 'NT 6.1': return '7' - case 'NT 6.2': return '8' - case 'NT 6.3': return '8.1' - case 'NT 10.0': return '10' - default: return undefined - } - } - - // OS version extraction - var osVersion = ''; - if (result.windows) { - osVersion = getWindowsVersion(getFirstMatch(/Windows ((NT|XP)( \d\d?.\d)?)/i)) - } else if (result.windowsphone) { - osVersion = getFirstMatch(/windows phone (?:os)?\s?(\d+(\.\d+)*)/i); - } else if (result.mac) { - osVersion = getFirstMatch(/Mac OS X (\d+([_\.\s]\d+)*)/i); - osVersion = osVersion.replace(/[_\s]/g, '.'); - } else if (iosdevice) { - osVersion = getFirstMatch(/os (\d+([_\s]\d+)*) like mac os x/i); - osVersion = osVersion.replace(/[_\s]/g, '.'); - } else if (android) { - osVersion = getFirstMatch(/android[ \/-](\d+(\.\d+)*)/i); - } else if (result.webos) { - osVersion = getFirstMatch(/(?:web|hpw)os\/(\d+(\.\d+)*)/i); - } else if (result.blackberry) { - osVersion = getFirstMatch(/rim\stablet\sos\s(\d+(\.\d+)*)/i); - } else if (result.bada) { - osVersion = getFirstMatch(/bada\/(\d+(\.\d+)*)/i); - } else if (result.tizen) { - osVersion = getFirstMatch(/tizen[\/\s](\d+(\.\d+)*)/i); - } - if (osVersion) { - result.osversion = osVersion; - } - - // device type extraction - var osMajorVersion = !result.windows && osVersion.split('.')[0]; - if ( - tablet - || nexusTablet - || iosdevice == 'ipad' - || (android && (osMajorVersion == 3 || (osMajorVersion >= 4 && !mobile))) - || result.silk - ) { - result.tablet = t - } else if ( - mobile - || iosdevice == 'iphone' - || iosdevice == 'ipod' - || android - || nexusMobile - || result.blackberry - || result.webos - || result.bada - ) { - result.mobile = t - } - - // Graded Browser Support - // http://developer.yahoo.com/yui/articles/gbs - if (result.msedge || - (result.msie && result.version >= 10) || - (result.yandexbrowser && result.version >= 15) || - (result.vivaldi && result.version >= 1.0) || - (result.chrome && result.version >= 20) || - (result.samsungBrowser && result.version >= 4) || - (result.firefox && result.version >= 20.0) || - (result.safari && result.version >= 6) || - (result.opera && result.version >= 10.0) || - (result.ios && result.osversion && result.osversion.split(".")[0] >= 6) || - (result.blackberry && result.version >= 10.1) - || (result.chromium && result.version >= 20) - ) { - result.a = t; - } - else if ((result.msie && result.version < 10) || - (result.chrome && result.version < 20) || - (result.firefox && result.version < 20.0) || - (result.safari && result.version < 6) || - (result.opera && result.version < 10.0) || - (result.ios && result.osversion && result.osversion.split(".")[0] < 6) - || (result.chromium && result.version < 20) - ) { - result.c = t - } else result.x = t - - return result - } - - var bowser = detect(typeof navigator !== 'undefined' ? navigator.userAgent || '' : '') - - bowser.test = function (browserList) { - for (var i = 0; i < browserList.length; ++i) { - var browserItem = browserList[i]; - if (typeof browserItem=== 'string') { - if (browserItem in bowser) { - return true; - } - } - } - return false; - } - - /** - * Get version precisions count - * - * @example - * getVersionPrecision("1.10.3") // 3 - * - * @param {string} version - * @return {number} - */ - function getVersionPrecision(version) { - return version.split(".").length; - } - - /** - * Array::map polyfill - * - * @param {Array} arr - * @param {Function} iterator - * @return {Array} - */ - function map(arr, iterator) { - var result = [], i; - if (Array.prototype.map) { - return Array.prototype.map.call(arr, iterator); - } - for (i = 0; i < arr.length; i++) { - result.push(iterator(arr[i])); - } - return result; - } - - /** - * Calculate browser version weight - * - * @example - * compareVersions(['1.10.2.1', '1.8.2.1.90']) // 1 - * compareVersions(['1.010.2.1', '1.09.2.1.90']); // 1 - * compareVersions(['1.10.2.1', '1.10.2.1']); // 0 - * compareVersions(['1.10.2.1', '1.0800.2']); // -1 - * - * @param {Array} versions versions to compare - * @return {Number} comparison result - */ - function compareVersions(versions) { - // 1) get common precision for both versions, for example for "10.0" and "9" it should be 2 - var precision = Math.max(getVersionPrecision(versions[0]), getVersionPrecision(versions[1])); - var chunks = map(versions, function (version) { - var delta = precision - getVersionPrecision(version); - - // 2) "9" -> "9.0" (for precision = 2) - version = version + new Array(delta + 1).join(".0"); - - // 3) "9.0" -> ["000000000"", "000000009"] - return map(version.split("."), function (chunk) { - return new Array(20 - chunk.length).join("0") + chunk; - }).reverse(); - }); - - // iterate in reverse order by reversed chunks array - while (--precision >= 0) { - // 4) compare: "000000009" > "000000010" = false (but "9" > "10" = true) - if (chunks[0][precision] > chunks[1][precision]) { - return 1; - } - else if (chunks[0][precision] === chunks[1][precision]) { - if (precision === 0) { - // all version chunks are same - return 0; - } - } - else { - return -1; - } - } - } - - /** - * Check if browser is unsupported - * - * @example - * bowser.isUnsupportedBrowser({ - * msie: "10", - * firefox: "23", - * chrome: "29", - * safari: "5.1", - * opera: "16", - * phantom: "534" - * }); - * - * @param {Object} minVersions map of minimal version to browser - * @param {Boolean} [strictMode = false] flag to return false if browser wasn't found in map - * @param {String} [ua] user agent string - * @return {Boolean} - */ - function isUnsupportedBrowser(minVersions, strictMode, ua) { - var _bowser = bowser; - - // make strictMode param optional with ua param usage - if (typeof strictMode === 'string') { - ua = strictMode; - strictMode = void(0); - } - - if (strictMode === void(0)) { - strictMode = false; - } - if (ua) { - _bowser = detect(ua); - } - - var version = "" + _bowser.version; - for (var browser in minVersions) { - if (minVersions.hasOwnProperty(browser)) { - if (_bowser[browser]) { - if (typeof minVersions[browser] !== 'string') { - throw new Error('Browser version in the minVersion map should be a string: ' + browser + ': ' + String(minVersions)); - } - - // browser version and min supported version. - return compareVersions([version, minVersions[browser]]) < 0; - } - } - } - - return strictMode; // not found - } - - /** - * Check if browser is supported - * - * @param {Object} minVersions map of minimal version to browser - * @param {Boolean} [strictMode = false] flag to return false if browser wasn't found in map - * @param {String} [ua] user agent string - * @return {Boolean} - */ - function check(minVersions, strictMode, ua) { - return !isUnsupportedBrowser(minVersions, strictMode, ua); - } - - bowser.isUnsupportedBrowser = isUnsupportedBrowser; - bowser.compareVersions = compareVersions; - bowser.check = check; - - /* - * Set our detect method to the main bowser object so we can - * reuse it to test other user agents. - * This is needed to implement future tests. - */ - bowser._detect = detect; - - return bowser -}); - -},{}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/fn/array/from.js":[function(require,module,exports){ -require('../../modules/es6.string.iterator'); -require('../../modules/es6.array.from'); -module.exports = require('../../modules/_core').Array.from; -},{"../../modules/_core":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_core.js","../../modules/es6.array.from":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/es6.array.from.js","../../modules/es6.string.iterator":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/es6.string.iterator.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/fn/get-iterator.js":[function(require,module,exports){ -require('../modules/web.dom.iterable'); -require('../modules/es6.string.iterator'); -module.exports = require('../modules/core.get-iterator'); -},{"../modules/core.get-iterator":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/core.get-iterator.js","../modules/es6.string.iterator":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/es6.string.iterator.js","../modules/web.dom.iterable":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/web.dom.iterable.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/fn/json/stringify.js":[function(require,module,exports){ -var core = require('../../modules/_core') - , $JSON = core.JSON || (core.JSON = {stringify: JSON.stringify}); -module.exports = function stringify(it){ // eslint-disable-line no-unused-vars - return $JSON.stringify.apply($JSON, arguments); -}; -},{"../../modules/_core":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_core.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/fn/map.js":[function(require,module,exports){ -require('../modules/es6.object.to-string'); -require('../modules/es6.string.iterator'); -require('../modules/web.dom.iterable'); -require('../modules/es6.map'); -require('../modules/es7.map.to-json'); -module.exports = require('../modules/_core').Map; -},{"../modules/_core":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_core.js","../modules/es6.map":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/es6.map.js","../modules/es6.object.to-string":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/es6.object.to-string.js","../modules/es6.string.iterator":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/es6.string.iterator.js","../modules/es7.map.to-json":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/es7.map.to-json.js","../modules/web.dom.iterable":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/web.dom.iterable.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/fn/object/assign.js":[function(require,module,exports){ -require('../../modules/es6.object.assign'); -module.exports = require('../../modules/_core').Object.assign; -},{"../../modules/_core":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_core.js","../../modules/es6.object.assign":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/es6.object.assign.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/fn/object/create.js":[function(require,module,exports){ -require('../../modules/es6.object.create'); -var $Object = require('../../modules/_core').Object; -module.exports = function create(P, D){ - return $Object.create(P, D); -}; -},{"../../modules/_core":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_core.js","../../modules/es6.object.create":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/es6.object.create.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/fn/object/define-property.js":[function(require,module,exports){ -require('../../modules/es6.object.define-property'); -var $Object = require('../../modules/_core').Object; -module.exports = function defineProperty(it, key, desc){ - return $Object.defineProperty(it, key, desc); -}; -},{"../../modules/_core":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_core.js","../../modules/es6.object.define-property":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/es6.object.define-property.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/fn/object/get-prototype-of.js":[function(require,module,exports){ -require('../../modules/es6.object.get-prototype-of'); -module.exports = require('../../modules/_core').Object.getPrototypeOf; -},{"../../modules/_core":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_core.js","../../modules/es6.object.get-prototype-of":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/es6.object.get-prototype-of.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/fn/object/keys.js":[function(require,module,exports){ -require('../../modules/es6.object.keys'); -module.exports = require('../../modules/_core').Object.keys; -},{"../../modules/_core":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_core.js","../../modules/es6.object.keys":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/es6.object.keys.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/fn/object/set-prototype-of.js":[function(require,module,exports){ -require('../../modules/es6.object.set-prototype-of'); -module.exports = require('../../modules/_core').Object.setPrototypeOf; -},{"../../modules/_core":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_core.js","../../modules/es6.object.set-prototype-of":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/es6.object.set-prototype-of.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/fn/promise.js":[function(require,module,exports){ -require('../modules/es6.object.to-string'); -require('../modules/es6.string.iterator'); -require('../modules/web.dom.iterable'); -require('../modules/es6.promise'); -module.exports = require('../modules/_core').Promise; -},{"../modules/_core":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_core.js","../modules/es6.object.to-string":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/es6.object.to-string.js","../modules/es6.promise":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/es6.promise.js","../modules/es6.string.iterator":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/es6.string.iterator.js","../modules/web.dom.iterable":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/web.dom.iterable.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/fn/set.js":[function(require,module,exports){ -require('../modules/es6.object.to-string'); -require('../modules/es6.string.iterator'); -require('../modules/web.dom.iterable'); -require('../modules/es6.set'); -require('../modules/es7.set.to-json'); -module.exports = require('../modules/_core').Set; -},{"../modules/_core":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_core.js","../modules/es6.object.to-string":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/es6.object.to-string.js","../modules/es6.set":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/es6.set.js","../modules/es6.string.iterator":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/es6.string.iterator.js","../modules/es7.set.to-json":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/es7.set.to-json.js","../modules/web.dom.iterable":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/web.dom.iterable.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/fn/symbol/index.js":[function(require,module,exports){ -require('../../modules/es6.symbol'); -require('../../modules/es6.object.to-string'); -require('../../modules/es7.symbol.async-iterator'); -require('../../modules/es7.symbol.observable'); -module.exports = require('../../modules/_core').Symbol; -},{"../../modules/_core":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_core.js","../../modules/es6.object.to-string":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/es6.object.to-string.js","../../modules/es6.symbol":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/es6.symbol.js","../../modules/es7.symbol.async-iterator":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/es7.symbol.async-iterator.js","../../modules/es7.symbol.observable":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/es7.symbol.observable.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/fn/symbol/iterator.js":[function(require,module,exports){ -require('../../modules/es6.string.iterator'); -require('../../modules/web.dom.iterable'); -module.exports = require('../../modules/_wks-ext').f('iterator'); -},{"../../modules/_wks-ext":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_wks-ext.js","../../modules/es6.string.iterator":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/es6.string.iterator.js","../../modules/web.dom.iterable":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/web.dom.iterable.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_a-function.js":[function(require,module,exports){ -module.exports = function(it){ - if(typeof it != 'function')throw TypeError(it + ' is not a function!'); - return it; -}; -},{}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_add-to-unscopables.js":[function(require,module,exports){ -module.exports = function(){ /* empty */ }; -},{}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_an-instance.js":[function(require,module,exports){ -module.exports = function(it, Constructor, name, forbiddenField){ - if(!(it instanceof Constructor) || (forbiddenField !== undefined && forbiddenField in it)){ - throw TypeError(name + ': incorrect invocation!'); - } return it; -}; -},{}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_an-object.js":[function(require,module,exports){ -var isObject = require('./_is-object'); -module.exports = function(it){ - if(!isObject(it))throw TypeError(it + ' is not an object!'); - return it; -}; -},{"./_is-object":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_is-object.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_array-from-iterable.js":[function(require,module,exports){ -var forOf = require('./_for-of'); - -module.exports = function(iter, ITERATOR){ - var result = []; - forOf(iter, false, result.push, result, ITERATOR); - return result; -}; - -},{"./_for-of":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_for-of.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_array-includes.js":[function(require,module,exports){ -// false -> Array#indexOf -// true -> Array#includes -var toIObject = require('./_to-iobject') - , toLength = require('./_to-length') - , toIndex = require('./_to-index'); -module.exports = function(IS_INCLUDES){ - return function($this, el, fromIndex){ - var O = toIObject($this) - , length = toLength(O.length) - , index = toIndex(fromIndex, length) - , value; - // Array#includes uses SameValueZero equality algorithm - if(IS_INCLUDES && el != el)while(length > index){ - value = O[index++]; - if(value != value)return true; - // Array#toIndex ignores holes, Array#includes - not - } else for(;length > index; index++)if(IS_INCLUDES || index in O){ - if(O[index] === el)return IS_INCLUDES || index || 0; - } return !IS_INCLUDES && -1; - }; -}; -},{"./_to-index":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_to-index.js","./_to-iobject":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_to-iobject.js","./_to-length":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_to-length.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_array-methods.js":[function(require,module,exports){ -// 0 -> Array#forEach -// 1 -> Array#map -// 2 -> Array#filter -// 3 -> Array#some -// 4 -> Array#every -// 5 -> Array#find -// 6 -> Array#findIndex -var ctx = require('./_ctx') - , IObject = require('./_iobject') - , toObject = require('./_to-object') - , toLength = require('./_to-length') - , asc = require('./_array-species-create'); -module.exports = function(TYPE, $create){ - var IS_MAP = TYPE == 1 - , IS_FILTER = TYPE == 2 - , IS_SOME = TYPE == 3 - , IS_EVERY = TYPE == 4 - , IS_FIND_INDEX = TYPE == 6 - , NO_HOLES = TYPE == 5 || IS_FIND_INDEX - , create = $create || asc; - return function($this, callbackfn, that){ - var O = toObject($this) - , self = IObject(O) - , f = ctx(callbackfn, that, 3) - , length = toLength(self.length) - , index = 0 - , result = IS_MAP ? create($this, length) : IS_FILTER ? create($this, 0) : undefined - , val, res; - for(;length > index; index++)if(NO_HOLES || index in self){ - val = self[index]; - res = f(val, index, O); - if(TYPE){ - if(IS_MAP)result[index] = res; // map - else if(res)switch(TYPE){ - case 3: return true; // some - case 5: return val; // find - case 6: return index; // findIndex - case 2: result.push(val); // filter - } else if(IS_EVERY)return false; // every - } - } - return IS_FIND_INDEX ? -1 : IS_SOME || IS_EVERY ? IS_EVERY : result; - }; -}; -},{"./_array-species-create":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_array-species-create.js","./_ctx":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_ctx.js","./_iobject":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_iobject.js","./_to-length":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_to-length.js","./_to-object":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_to-object.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_array-species-constructor.js":[function(require,module,exports){ -var isObject = require('./_is-object') - , isArray = require('./_is-array') - , SPECIES = require('./_wks')('species'); - -module.exports = function(original){ - var C; - if(isArray(original)){ - C = original.constructor; - // cross-realm fallback - if(typeof C == 'function' && (C === Array || isArray(C.prototype)))C = undefined; - if(isObject(C)){ - C = C[SPECIES]; - if(C === null)C = undefined; - } - } return C === undefined ? Array : C; -}; -},{"./_is-array":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_is-array.js","./_is-object":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_is-object.js","./_wks":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_wks.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_array-species-create.js":[function(require,module,exports){ -// 9.4.2.3 ArraySpeciesCreate(originalArray, length) -var speciesConstructor = require('./_array-species-constructor'); - -module.exports = function(original, length){ - return new (speciesConstructor(original))(length); -}; -},{"./_array-species-constructor":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_array-species-constructor.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_classof.js":[function(require,module,exports){ -// getting tag from 19.1.3.6 Object.prototype.toString() -var cof = require('./_cof') - , TAG = require('./_wks')('toStringTag') - // ES3 wrong here - , ARG = cof(function(){ return arguments; }()) == 'Arguments'; - -// fallback for IE11 Script Access Denied error -var tryGet = function(it, key){ - try { - return it[key]; - } catch(e){ /* empty */ } -}; - -module.exports = function(it){ - var O, T, B; - return it === undefined ? 'Undefined' : it === null ? 'Null' - // @@toStringTag case - : typeof (T = tryGet(O = Object(it), TAG)) == 'string' ? T - // builtinTag case - : ARG ? cof(O) - // ES3 arguments fallback - : (B = cof(O)) == 'Object' && typeof O.callee == 'function' ? 'Arguments' : B; -}; -},{"./_cof":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_cof.js","./_wks":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_wks.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_cof.js":[function(require,module,exports){ -var toString = {}.toString; - -module.exports = function(it){ - return toString.call(it).slice(8, -1); -}; -},{}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_collection-strong.js":[function(require,module,exports){ -'use strict'; -var dP = require('./_object-dp').f - , create = require('./_object-create') - , redefineAll = require('./_redefine-all') - , ctx = require('./_ctx') - , anInstance = require('./_an-instance') - , defined = require('./_defined') - , forOf = require('./_for-of') - , $iterDefine = require('./_iter-define') - , step = require('./_iter-step') - , setSpecies = require('./_set-species') - , DESCRIPTORS = require('./_descriptors') - , fastKey = require('./_meta').fastKey - , SIZE = DESCRIPTORS ? '_s' : 'size'; - -var getEntry = function(that, key){ - // fast case - var index = fastKey(key), entry; - if(index !== 'F')return that._i[index]; - // frozen object case - for(entry = that._f; entry; entry = entry.n){ - if(entry.k == key)return entry; - } -}; - -module.exports = { - getConstructor: function(wrapper, NAME, IS_MAP, ADDER){ - var C = wrapper(function(that, iterable){ - anInstance(that, C, NAME, '_i'); - that._i = create(null); // index - that._f = undefined; // first entry - that._l = undefined; // last entry - that[SIZE] = 0; // size - if(iterable != undefined)forOf(iterable, IS_MAP, that[ADDER], that); - }); - redefineAll(C.prototype, { - // 23.1.3.1 Map.prototype.clear() - // 23.2.3.2 Set.prototype.clear() - clear: function clear(){ - for(var that = this, data = that._i, entry = that._f; entry; entry = entry.n){ - entry.r = true; - if(entry.p)entry.p = entry.p.n = undefined; - delete data[entry.i]; - } - that._f = that._l = undefined; - that[SIZE] = 0; - }, - // 23.1.3.3 Map.prototype.delete(key) - // 23.2.3.4 Set.prototype.delete(value) - 'delete': function(key){ - var that = this - , entry = getEntry(that, key); - if(entry){ - var next = entry.n - , prev = entry.p; - delete that._i[entry.i]; - entry.r = true; - if(prev)prev.n = next; - if(next)next.p = prev; - if(that._f == entry)that._f = next; - if(that._l == entry)that._l = prev; - that[SIZE]--; - } return !!entry; - }, - // 23.2.3.6 Set.prototype.forEach(callbackfn, thisArg = undefined) - // 23.1.3.5 Map.prototype.forEach(callbackfn, thisArg = undefined) - forEach: function forEach(callbackfn /*, that = undefined */){ - anInstance(this, C, 'forEach'); - var f = ctx(callbackfn, arguments.length > 1 ? arguments[1] : undefined, 3) - , entry; - while(entry = entry ? entry.n : this._f){ - f(entry.v, entry.k, this); - // revert to the last existing entry - while(entry && entry.r)entry = entry.p; - } - }, - // 23.1.3.7 Map.prototype.has(key) - // 23.2.3.7 Set.prototype.has(value) - has: function has(key){ - return !!getEntry(this, key); - } - }); - if(DESCRIPTORS)dP(C.prototype, 'size', { - get: function(){ - return defined(this[SIZE]); - } - }); - return C; - }, - def: function(that, key, value){ - var entry = getEntry(that, key) - , prev, index; - // change existing entry - if(entry){ - entry.v = value; - // create new entry - } else { - that._l = entry = { - i: index = fastKey(key, true), // <- index - k: key, // <- key - v: value, // <- value - p: prev = that._l, // <- previous entry - n: undefined, // <- next entry - r: false // <- removed - }; - if(!that._f)that._f = entry; - if(prev)prev.n = entry; - that[SIZE]++; - // add to index - if(index !== 'F')that._i[index] = entry; - } return that; - }, - getEntry: getEntry, - setStrong: function(C, NAME, IS_MAP){ - // add .keys, .values, .entries, [@@iterator] - // 23.1.3.4, 23.1.3.8, 23.1.3.11, 23.1.3.12, 23.2.3.5, 23.2.3.8, 23.2.3.10, 23.2.3.11 - $iterDefine(C, NAME, function(iterated, kind){ - this._t = iterated; // target - this._k = kind; // kind - this._l = undefined; // previous - }, function(){ - var that = this - , kind = that._k - , entry = that._l; - // revert to the last existing entry - while(entry && entry.r)entry = entry.p; - // get next entry - if(!that._t || !(that._l = entry = entry ? entry.n : that._t._f)){ - // or finish the iteration - that._t = undefined; - return step(1); - } - // return step by kind - if(kind == 'keys' )return step(0, entry.k); - if(kind == 'values')return step(0, entry.v); - return step(0, [entry.k, entry.v]); - }, IS_MAP ? 'entries' : 'values' , !IS_MAP, true); - - // add [@@species], 23.1.2.2, 23.2.2.2 - setSpecies(NAME); - } -}; -},{"./_an-instance":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_an-instance.js","./_ctx":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_ctx.js","./_defined":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_defined.js","./_descriptors":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_descriptors.js","./_for-of":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_for-of.js","./_iter-define":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_iter-define.js","./_iter-step":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_iter-step.js","./_meta":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_meta.js","./_object-create":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_object-create.js","./_object-dp":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_object-dp.js","./_redefine-all":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_redefine-all.js","./_set-species":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_set-species.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_collection-to-json.js":[function(require,module,exports){ -// https://github.com/DavidBruant/Map-Set.prototype.toJSON -var classof = require('./_classof') - , from = require('./_array-from-iterable'); -module.exports = function(NAME){ - return function toJSON(){ - if(classof(this) != NAME)throw TypeError(NAME + "#toJSON isn't generic"); - return from(this); - }; -}; -},{"./_array-from-iterable":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_array-from-iterable.js","./_classof":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_classof.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_collection.js":[function(require,module,exports){ -'use strict'; -var global = require('./_global') - , $export = require('./_export') - , meta = require('./_meta') - , fails = require('./_fails') - , hide = require('./_hide') - , redefineAll = require('./_redefine-all') - , forOf = require('./_for-of') - , anInstance = require('./_an-instance') - , isObject = require('./_is-object') - , setToStringTag = require('./_set-to-string-tag') - , dP = require('./_object-dp').f - , each = require('./_array-methods')(0) - , DESCRIPTORS = require('./_descriptors'); - -module.exports = function(NAME, wrapper, methods, common, IS_MAP, IS_WEAK){ - var Base = global[NAME] - , C = Base - , ADDER = IS_MAP ? 'set' : 'add' - , proto = C && C.prototype - , O = {}; - if(!DESCRIPTORS || typeof C != 'function' || !(IS_WEAK || proto.forEach && !fails(function(){ - new C().entries().next(); - }))){ - // create collection constructor - C = common.getConstructor(wrapper, NAME, IS_MAP, ADDER); - redefineAll(C.prototype, methods); - meta.NEED = true; - } else { - C = wrapper(function(target, iterable){ - anInstance(target, C, NAME, '_c'); - target._c = new Base; - if(iterable != undefined)forOf(iterable, IS_MAP, target[ADDER], target); - }); - each('add,clear,delete,forEach,get,has,set,keys,values,entries,toJSON'.split(','),function(KEY){ - var IS_ADDER = KEY == 'add' || KEY == 'set'; - if(KEY in proto && !(IS_WEAK && KEY == 'clear'))hide(C.prototype, KEY, function(a, b){ - anInstance(this, C, KEY); - if(!IS_ADDER && IS_WEAK && !isObject(a))return KEY == 'get' ? undefined : false; - var result = this._c[KEY](a === 0 ? 0 : a, b); - return IS_ADDER ? this : result; - }); - }); - if('size' in proto)dP(C.prototype, 'size', { - get: function(){ - return this._c.size; - } - }); - } - - setToStringTag(C, NAME); - - O[NAME] = C; - $export($export.G + $export.W + $export.F, O); - - if(!IS_WEAK)common.setStrong(C, NAME, IS_MAP); - - return C; -}; -},{"./_an-instance":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_an-instance.js","./_array-methods":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_array-methods.js","./_descriptors":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_descriptors.js","./_export":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_export.js","./_fails":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_fails.js","./_for-of":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_for-of.js","./_global":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_global.js","./_hide":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_hide.js","./_is-object":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_is-object.js","./_meta":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_meta.js","./_object-dp":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_object-dp.js","./_redefine-all":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_redefine-all.js","./_set-to-string-tag":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_set-to-string-tag.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_core.js":[function(require,module,exports){ -var core = module.exports = {version: '2.4.0'}; -if(typeof __e == 'number')__e = core; // eslint-disable-line no-undef -},{}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_create-property.js":[function(require,module,exports){ -'use strict'; -var $defineProperty = require('./_object-dp') - , createDesc = require('./_property-desc'); - -module.exports = function(object, index, value){ - if(index in object)$defineProperty.f(object, index, createDesc(0, value)); - else object[index] = value; -}; -},{"./_object-dp":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_object-dp.js","./_property-desc":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_property-desc.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_ctx.js":[function(require,module,exports){ -// optional / simple context binding -var aFunction = require('./_a-function'); -module.exports = function(fn, that, length){ - aFunction(fn); - if(that === undefined)return fn; - switch(length){ - case 1: return function(a){ - return fn.call(that, a); - }; - case 2: return function(a, b){ - return fn.call(that, a, b); - }; - case 3: return function(a, b, c){ - return fn.call(that, a, b, c); - }; - } - return function(/* ...args */){ - return fn.apply(that, arguments); - }; -}; -},{"./_a-function":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_a-function.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_defined.js":[function(require,module,exports){ -// 7.2.1 RequireObjectCoercible(argument) -module.exports = function(it){ - if(it == undefined)throw TypeError("Can't call method on " + it); - return it; -}; -},{}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_descriptors.js":[function(require,module,exports){ -// Thank's IE8 for his funny defineProperty -module.exports = !require('./_fails')(function(){ - return Object.defineProperty({}, 'a', {get: function(){ return 7; }}).a != 7; -}); -},{"./_fails":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_fails.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_dom-create.js":[function(require,module,exports){ -var isObject = require('./_is-object') - , document = require('./_global').document - // in old IE typeof document.createElement is 'object' - , is = isObject(document) && isObject(document.createElement); -module.exports = function(it){ - return is ? document.createElement(it) : {}; -}; -},{"./_global":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_global.js","./_is-object":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_is-object.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_enum-bug-keys.js":[function(require,module,exports){ -// IE 8- don't enum bug keys -module.exports = ( - 'constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf' -).split(','); -},{}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_enum-keys.js":[function(require,module,exports){ -// all enumerable object keys, includes symbols -var getKeys = require('./_object-keys') - , gOPS = require('./_object-gops') - , pIE = require('./_object-pie'); -module.exports = function(it){ - var result = getKeys(it) - , getSymbols = gOPS.f; - if(getSymbols){ - var symbols = getSymbols(it) - , isEnum = pIE.f - , i = 0 - , key; - while(symbols.length > i)if(isEnum.call(it, key = symbols[i++]))result.push(key); - } return result; -}; -},{"./_object-gops":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_object-gops.js","./_object-keys":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_object-keys.js","./_object-pie":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_object-pie.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_export.js":[function(require,module,exports){ -var global = require('./_global') - , core = require('./_core') - , ctx = require('./_ctx') - , hide = require('./_hide') - , PROTOTYPE = 'prototype'; - -var $export = function(type, name, source){ - var IS_FORCED = type & $export.F - , IS_GLOBAL = type & $export.G - , IS_STATIC = type & $export.S - , IS_PROTO = type & $export.P - , IS_BIND = type & $export.B - , IS_WRAP = type & $export.W - , exports = IS_GLOBAL ? core : core[name] || (core[name] = {}) - , expProto = exports[PROTOTYPE] - , target = IS_GLOBAL ? global : IS_STATIC ? global[name] : (global[name] || {})[PROTOTYPE] - , key, own, out; - if(IS_GLOBAL)source = name; - for(key in source){ - // contains in native - own = !IS_FORCED && target && target[key] !== undefined; - if(own && key in exports)continue; - // export native or passed - out = own ? target[key] : source[key]; - // prevent global pollution for namespaces - exports[key] = IS_GLOBAL && typeof target[key] != 'function' ? source[key] - // bind timers to global for call from export context - : IS_BIND && own ? ctx(out, global) - // wrap global constructors for prevent change them in library - : IS_WRAP && target[key] == out ? (function(C){ - var F = function(a, b, c){ - if(this instanceof C){ - switch(arguments.length){ - case 0: return new C; - case 1: return new C(a); - case 2: return new C(a, b); - } return new C(a, b, c); - } return C.apply(this, arguments); - }; - F[PROTOTYPE] = C[PROTOTYPE]; - return F; - // make static versions for prototype methods - })(out) : IS_PROTO && typeof out == 'function' ? ctx(Function.call, out) : out; - // export proto methods to core.%CONSTRUCTOR%.methods.%NAME% - if(IS_PROTO){ - (exports.virtual || (exports.virtual = {}))[key] = out; - // export proto methods to core.%CONSTRUCTOR%.prototype.%NAME% - if(type & $export.R && expProto && !expProto[key])hide(expProto, key, out); - } - } -}; -// type bitmap -$export.F = 1; // forced -$export.G = 2; // global -$export.S = 4; // static -$export.P = 8; // proto -$export.B = 16; // bind -$export.W = 32; // wrap -$export.U = 64; // safe -$export.R = 128; // real proto method for `library` -module.exports = $export; -},{"./_core":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_core.js","./_ctx":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_ctx.js","./_global":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_global.js","./_hide":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_hide.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_fails.js":[function(require,module,exports){ -module.exports = function(exec){ - try { - return !!exec(); - } catch(e){ - return true; - } -}; -},{}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_for-of.js":[function(require,module,exports){ -var ctx = require('./_ctx') - , call = require('./_iter-call') - , isArrayIter = require('./_is-array-iter') - , anObject = require('./_an-object') - , toLength = require('./_to-length') - , getIterFn = require('./core.get-iterator-method') - , BREAK = {} - , RETURN = {}; -var exports = module.exports = function(iterable, entries, fn, that, ITERATOR){ - var iterFn = ITERATOR ? function(){ return iterable; } : getIterFn(iterable) - , f = ctx(fn, that, entries ? 2 : 1) - , index = 0 - , length, step, iterator, result; - if(typeof iterFn != 'function')throw TypeError(iterable + ' is not iterable!'); - // fast case for arrays with default iterator - if(isArrayIter(iterFn))for(length = toLength(iterable.length); length > index; index++){ - result = entries ? f(anObject(step = iterable[index])[0], step[1]) : f(iterable[index]); - if(result === BREAK || result === RETURN)return result; - } else for(iterator = iterFn.call(iterable); !(step = iterator.next()).done; ){ - result = call(iterator, f, step.value, entries); - if(result === BREAK || result === RETURN)return result; - } -}; -exports.BREAK = BREAK; -exports.RETURN = RETURN; -},{"./_an-object":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_an-object.js","./_ctx":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_ctx.js","./_is-array-iter":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_is-array-iter.js","./_iter-call":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_iter-call.js","./_to-length":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_to-length.js","./core.get-iterator-method":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/core.get-iterator-method.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_global.js":[function(require,module,exports){ -// https://github.com/zloirock/core-js/issues/86#issuecomment-115759028 -var global = module.exports = typeof window != 'undefined' && window.Math == Math - ? window : typeof self != 'undefined' && self.Math == Math ? self : Function('return this')(); -if(typeof __g == 'number')__g = global; // eslint-disable-line no-undef -},{}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_has.js":[function(require,module,exports){ -var hasOwnProperty = {}.hasOwnProperty; -module.exports = function(it, key){ - return hasOwnProperty.call(it, key); -}; -},{}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_hide.js":[function(require,module,exports){ -var dP = require('./_object-dp') - , createDesc = require('./_property-desc'); -module.exports = require('./_descriptors') ? function(object, key, value){ - return dP.f(object, key, createDesc(1, value)); -} : function(object, key, value){ - object[key] = value; - return object; -}; -},{"./_descriptors":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_descriptors.js","./_object-dp":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_object-dp.js","./_property-desc":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_property-desc.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_html.js":[function(require,module,exports){ -module.exports = require('./_global').document && document.documentElement; -},{"./_global":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_global.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_ie8-dom-define.js":[function(require,module,exports){ -module.exports = !require('./_descriptors') && !require('./_fails')(function(){ - return Object.defineProperty(require('./_dom-create')('div'), 'a', {get: function(){ return 7; }}).a != 7; -}); -},{"./_descriptors":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_descriptors.js","./_dom-create":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_dom-create.js","./_fails":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_fails.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_invoke.js":[function(require,module,exports){ -// fast apply, http://jsperf.lnkit.com/fast-apply/5 -module.exports = function(fn, args, that){ - var un = that === undefined; - switch(args.length){ - case 0: return un ? fn() - : fn.call(that); - case 1: return un ? fn(args[0]) - : fn.call(that, args[0]); - case 2: return un ? fn(args[0], args[1]) - : fn.call(that, args[0], args[1]); - case 3: return un ? fn(args[0], args[1], args[2]) - : fn.call(that, args[0], args[1], args[2]); - case 4: return un ? fn(args[0], args[1], args[2], args[3]) - : fn.call(that, args[0], args[1], args[2], args[3]); - } return fn.apply(that, args); -}; -},{}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_iobject.js":[function(require,module,exports){ -// fallback for non-array-like ES3 and non-enumerable old V8 strings -var cof = require('./_cof'); -module.exports = Object('z').propertyIsEnumerable(0) ? Object : function(it){ - return cof(it) == 'String' ? it.split('') : Object(it); -}; -},{"./_cof":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_cof.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_is-array-iter.js":[function(require,module,exports){ -// check on default Array iterator -var Iterators = require('./_iterators') - , ITERATOR = require('./_wks')('iterator') - , ArrayProto = Array.prototype; - -module.exports = function(it){ - return it !== undefined && (Iterators.Array === it || ArrayProto[ITERATOR] === it); -}; -},{"./_iterators":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_iterators.js","./_wks":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_wks.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_is-array.js":[function(require,module,exports){ -// 7.2.2 IsArray(argument) -var cof = require('./_cof'); -module.exports = Array.isArray || function isArray(arg){ - return cof(arg) == 'Array'; -}; -},{"./_cof":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_cof.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_is-object.js":[function(require,module,exports){ -module.exports = function(it){ - return typeof it === 'object' ? it !== null : typeof it === 'function'; -}; -},{}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_iter-call.js":[function(require,module,exports){ -// call something on iterator step with safe closing on error -var anObject = require('./_an-object'); -module.exports = function(iterator, fn, value, entries){ - try { - return entries ? fn(anObject(value)[0], value[1]) : fn(value); - // 7.4.6 IteratorClose(iterator, completion) - } catch(e){ - var ret = iterator['return']; - if(ret !== undefined)anObject(ret.call(iterator)); - throw e; - } -}; -},{"./_an-object":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_an-object.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_iter-create.js":[function(require,module,exports){ -'use strict'; -var create = require('./_object-create') - , descriptor = require('./_property-desc') - , setToStringTag = require('./_set-to-string-tag') - , IteratorPrototype = {}; - -// 25.1.2.1.1 %IteratorPrototype%[@@iterator]() -require('./_hide')(IteratorPrototype, require('./_wks')('iterator'), function(){ return this; }); - -module.exports = function(Constructor, NAME, next){ - Constructor.prototype = create(IteratorPrototype, {next: descriptor(1, next)}); - setToStringTag(Constructor, NAME + ' Iterator'); -}; -},{"./_hide":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_hide.js","./_object-create":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_object-create.js","./_property-desc":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_property-desc.js","./_set-to-string-tag":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_set-to-string-tag.js","./_wks":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_wks.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_iter-define.js":[function(require,module,exports){ -'use strict'; -var LIBRARY = require('./_library') - , $export = require('./_export') - , redefine = require('./_redefine') - , hide = require('./_hide') - , has = require('./_has') - , Iterators = require('./_iterators') - , $iterCreate = require('./_iter-create') - , setToStringTag = require('./_set-to-string-tag') - , getPrototypeOf = require('./_object-gpo') - , ITERATOR = require('./_wks')('iterator') - , BUGGY = !([].keys && 'next' in [].keys()) // Safari has buggy iterators w/o `next` - , FF_ITERATOR = '@@iterator' - , KEYS = 'keys' - , VALUES = 'values'; - -var returnThis = function(){ return this; }; - -module.exports = function(Base, NAME, Constructor, next, DEFAULT, IS_SET, FORCED){ - $iterCreate(Constructor, NAME, next); - var getMethod = function(kind){ - if(!BUGGY && kind in proto)return proto[kind]; - switch(kind){ - case KEYS: return function keys(){ return new Constructor(this, kind); }; - case VALUES: return function values(){ return new Constructor(this, kind); }; - } return function entries(){ return new Constructor(this, kind); }; - }; - var TAG = NAME + ' Iterator' - , DEF_VALUES = DEFAULT == VALUES - , VALUES_BUG = false - , proto = Base.prototype - , $native = proto[ITERATOR] || proto[FF_ITERATOR] || DEFAULT && proto[DEFAULT] - , $default = $native || getMethod(DEFAULT) - , $entries = DEFAULT ? !DEF_VALUES ? $default : getMethod('entries') : undefined - , $anyNative = NAME == 'Array' ? proto.entries || $native : $native - , methods, key, IteratorPrototype; - // Fix native - if($anyNative){ - IteratorPrototype = getPrototypeOf($anyNative.call(new Base)); - if(IteratorPrototype !== Object.prototype){ - // Set @@toStringTag to native iterators - setToStringTag(IteratorPrototype, TAG, true); - // fix for some old engines - if(!LIBRARY && !has(IteratorPrototype, ITERATOR))hide(IteratorPrototype, ITERATOR, returnThis); - } - } - // fix Array#{values, @@iterator}.name in V8 / FF - if(DEF_VALUES && $native && $native.name !== VALUES){ - VALUES_BUG = true; - $default = function values(){ return $native.call(this); }; - } - // Define iterator - if((!LIBRARY || FORCED) && (BUGGY || VALUES_BUG || !proto[ITERATOR])){ - hide(proto, ITERATOR, $default); - } - // Plug for library - Iterators[NAME] = $default; - Iterators[TAG] = returnThis; - if(DEFAULT){ - methods = { - values: DEF_VALUES ? $default : getMethod(VALUES), - keys: IS_SET ? $default : getMethod(KEYS), - entries: $entries - }; - if(FORCED)for(key in methods){ - if(!(key in proto))redefine(proto, key, methods[key]); - } else $export($export.P + $export.F * (BUGGY || VALUES_BUG), NAME, methods); - } - return methods; -}; -},{"./_export":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_export.js","./_has":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_has.js","./_hide":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_hide.js","./_iter-create":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_iter-create.js","./_iterators":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_iterators.js","./_library":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_library.js","./_object-gpo":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_object-gpo.js","./_redefine":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_redefine.js","./_set-to-string-tag":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_set-to-string-tag.js","./_wks":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_wks.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_iter-detect.js":[function(require,module,exports){ -var ITERATOR = require('./_wks')('iterator') - , SAFE_CLOSING = false; - -try { - var riter = [7][ITERATOR](); - riter['return'] = function(){ SAFE_CLOSING = true; }; - Array.from(riter, function(){ throw 2; }); -} catch(e){ /* empty */ } - -module.exports = function(exec, skipClosing){ - if(!skipClosing && !SAFE_CLOSING)return false; - var safe = false; - try { - var arr = [7] - , iter = arr[ITERATOR](); - iter.next = function(){ return {done: safe = true}; }; - arr[ITERATOR] = function(){ return iter; }; - exec(arr); - } catch(e){ /* empty */ } - return safe; -}; -},{"./_wks":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_wks.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_iter-step.js":[function(require,module,exports){ -module.exports = function(done, value){ - return {value: value, done: !!done}; -}; -},{}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_iterators.js":[function(require,module,exports){ -module.exports = {}; -},{}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_keyof.js":[function(require,module,exports){ -var getKeys = require('./_object-keys') - , toIObject = require('./_to-iobject'); -module.exports = function(object, el){ - var O = toIObject(object) - , keys = getKeys(O) - , length = keys.length - , index = 0 - , key; - while(length > index)if(O[key = keys[index++]] === el)return key; -}; -},{"./_object-keys":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_object-keys.js","./_to-iobject":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_to-iobject.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_library.js":[function(require,module,exports){ -module.exports = true; -},{}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_meta.js":[function(require,module,exports){ -var META = require('./_uid')('meta') - , isObject = require('./_is-object') - , has = require('./_has') - , setDesc = require('./_object-dp').f - , id = 0; -var isExtensible = Object.isExtensible || function(){ - return true; -}; -var FREEZE = !require('./_fails')(function(){ - return isExtensible(Object.preventExtensions({})); -}); -var setMeta = function(it){ - setDesc(it, META, {value: { - i: 'O' + ++id, // object ID - w: {} // weak collections IDs - }}); -}; -var fastKey = function(it, create){ - // return primitive with prefix - if(!isObject(it))return typeof it == 'symbol' ? it : (typeof it == 'string' ? 'S' : 'P') + it; - if(!has(it, META)){ - // can't set metadata to uncaught frozen object - if(!isExtensible(it))return 'F'; - // not necessary to add metadata - if(!create)return 'E'; - // add missing metadata - setMeta(it); - // return object ID - } return it[META].i; -}; -var getWeak = function(it, create){ - if(!has(it, META)){ - // can't set metadata to uncaught frozen object - if(!isExtensible(it))return true; - // not necessary to add metadata - if(!create)return false; - // add missing metadata - setMeta(it); - // return hash weak collections IDs - } return it[META].w; -}; -// add metadata on freeze-family methods calling -var onFreeze = function(it){ - if(FREEZE && meta.NEED && isExtensible(it) && !has(it, META))setMeta(it); - return it; -}; -var meta = module.exports = { - KEY: META, - NEED: false, - fastKey: fastKey, - getWeak: getWeak, - onFreeze: onFreeze -}; -},{"./_fails":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_fails.js","./_has":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_has.js","./_is-object":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_is-object.js","./_object-dp":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_object-dp.js","./_uid":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_uid.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_microtask.js":[function(require,module,exports){ -var global = require('./_global') - , macrotask = require('./_task').set - , Observer = global.MutationObserver || global.WebKitMutationObserver - , process = global.process - , Promise = global.Promise - , isNode = require('./_cof')(process) == 'process'; - -module.exports = function(){ - var head, last, notify; - - var flush = function(){ - var parent, fn; - if(isNode && (parent = process.domain))parent.exit(); - while(head){ - fn = head.fn; - head = head.next; - try { - fn(); - } catch(e){ - if(head)notify(); - else last = undefined; - throw e; - } - } last = undefined; - if(parent)parent.enter(); - }; - - // Node.js - if(isNode){ - notify = function(){ - process.nextTick(flush); - }; - // browsers with MutationObserver - } else if(Observer){ - var toggle = true - , node = document.createTextNode(''); - new Observer(flush).observe(node, {characterData: true}); // eslint-disable-line no-new - notify = function(){ - node.data = toggle = !toggle; - }; - // environments with maybe non-completely correct, but existent Promise - } else if(Promise && Promise.resolve){ - var promise = Promise.resolve(); - notify = function(){ - promise.then(flush); - }; - // for other environments - macrotask based on: - // - setImmediate - // - MessageChannel - // - window.postMessag - // - onreadystatechange - // - setTimeout - } else { - notify = function(){ - // strange IE + webpack dev server bug - use .call(global) - macrotask.call(global, flush); - }; - } - - return function(fn){ - var task = {fn: fn, next: undefined}; - if(last)last.next = task; - if(!head){ - head = task; - notify(); - } last = task; - }; -}; -},{"./_cof":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_cof.js","./_global":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_global.js","./_task":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_task.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_object-assign.js":[function(require,module,exports){ -'use strict'; -// 19.1.2.1 Object.assign(target, source, ...) -var getKeys = require('./_object-keys') - , gOPS = require('./_object-gops') - , pIE = require('./_object-pie') - , toObject = require('./_to-object') - , IObject = require('./_iobject') - , $assign = Object.assign; - -// should work with symbols and should have deterministic property order (V8 bug) -module.exports = !$assign || require('./_fails')(function(){ - var A = {} - , B = {} - , S = Symbol() - , K = 'abcdefghijklmnopqrst'; - A[S] = 7; - K.split('').forEach(function(k){ B[k] = k; }); - return $assign({}, A)[S] != 7 || Object.keys($assign({}, B)).join('') != K; -}) ? function assign(target, source){ // eslint-disable-line no-unused-vars - var T = toObject(target) - , aLen = arguments.length - , index = 1 - , getSymbols = gOPS.f - , isEnum = pIE.f; - while(aLen > index){ - var S = IObject(arguments[index++]) - , keys = getSymbols ? getKeys(S).concat(getSymbols(S)) : getKeys(S) - , length = keys.length - , j = 0 - , key; - while(length > j)if(isEnum.call(S, key = keys[j++]))T[key] = S[key]; - } return T; -} : $assign; -},{"./_fails":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_fails.js","./_iobject":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_iobject.js","./_object-gops":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_object-gops.js","./_object-keys":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_object-keys.js","./_object-pie":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_object-pie.js","./_to-object":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_to-object.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_object-create.js":[function(require,module,exports){ -// 19.1.2.2 / 15.2.3.5 Object.create(O [, Properties]) -var anObject = require('./_an-object') - , dPs = require('./_object-dps') - , enumBugKeys = require('./_enum-bug-keys') - , IE_PROTO = require('./_shared-key')('IE_PROTO') - , Empty = function(){ /* empty */ } - , PROTOTYPE = 'prototype'; - -// Create object with fake `null` prototype: use iframe Object with cleared prototype -var createDict = function(){ - // Thrash, waste and sodomy: IE GC bug - var iframe = require('./_dom-create')('iframe') - , i = enumBugKeys.length - , lt = '<' - , gt = '>' - , iframeDocument; - iframe.style.display = 'none'; - require('./_html').appendChild(iframe); - iframe.src = 'javascript:'; // eslint-disable-line no-script-url - // createDict = iframe.contentWindow.Object; - // html.removeChild(iframe); - iframeDocument = iframe.contentWindow.document; - iframeDocument.open(); - iframeDocument.write(lt + 'script' + gt + 'document.F=Object' + lt + '/script' + gt); - iframeDocument.close(); - createDict = iframeDocument.F; - while(i--)delete createDict[PROTOTYPE][enumBugKeys[i]]; - return createDict(); -}; - -module.exports = Object.create || function create(O, Properties){ - var result; - if(O !== null){ - Empty[PROTOTYPE] = anObject(O); - result = new Empty; - Empty[PROTOTYPE] = null; - // add "__proto__" for Object.getPrototypeOf polyfill - result[IE_PROTO] = O; - } else result = createDict(); - return Properties === undefined ? result : dPs(result, Properties); -}; - -},{"./_an-object":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_an-object.js","./_dom-create":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_dom-create.js","./_enum-bug-keys":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_enum-bug-keys.js","./_html":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_html.js","./_object-dps":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_object-dps.js","./_shared-key":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_shared-key.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_object-dp.js":[function(require,module,exports){ -var anObject = require('./_an-object') - , IE8_DOM_DEFINE = require('./_ie8-dom-define') - , toPrimitive = require('./_to-primitive') - , dP = Object.defineProperty; - -exports.f = require('./_descriptors') ? Object.defineProperty : function defineProperty(O, P, Attributes){ - anObject(O); - P = toPrimitive(P, true); - anObject(Attributes); - if(IE8_DOM_DEFINE)try { - return dP(O, P, Attributes); - } catch(e){ /* empty */ } - if('get' in Attributes || 'set' in Attributes)throw TypeError('Accessors not supported!'); - if('value' in Attributes)O[P] = Attributes.value; - return O; -}; -},{"./_an-object":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_an-object.js","./_descriptors":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_descriptors.js","./_ie8-dom-define":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_ie8-dom-define.js","./_to-primitive":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_to-primitive.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_object-dps.js":[function(require,module,exports){ -var dP = require('./_object-dp') - , anObject = require('./_an-object') - , getKeys = require('./_object-keys'); - -module.exports = require('./_descriptors') ? Object.defineProperties : function defineProperties(O, Properties){ - anObject(O); - var keys = getKeys(Properties) - , length = keys.length - , i = 0 - , P; - while(length > i)dP.f(O, P = keys[i++], Properties[P]); - return O; -}; -},{"./_an-object":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_an-object.js","./_descriptors":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_descriptors.js","./_object-dp":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_object-dp.js","./_object-keys":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_object-keys.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_object-gopd.js":[function(require,module,exports){ -var pIE = require('./_object-pie') - , createDesc = require('./_property-desc') - , toIObject = require('./_to-iobject') - , toPrimitive = require('./_to-primitive') - , has = require('./_has') - , IE8_DOM_DEFINE = require('./_ie8-dom-define') - , gOPD = Object.getOwnPropertyDescriptor; - -exports.f = require('./_descriptors') ? gOPD : function getOwnPropertyDescriptor(O, P){ - O = toIObject(O); - P = toPrimitive(P, true); - if(IE8_DOM_DEFINE)try { - return gOPD(O, P); - } catch(e){ /* empty */ } - if(has(O, P))return createDesc(!pIE.f.call(O, P), O[P]); -}; -},{"./_descriptors":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_descriptors.js","./_has":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_has.js","./_ie8-dom-define":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_ie8-dom-define.js","./_object-pie":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_object-pie.js","./_property-desc":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_property-desc.js","./_to-iobject":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_to-iobject.js","./_to-primitive":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_to-primitive.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_object-gopn-ext.js":[function(require,module,exports){ -// fallback for IE11 buggy Object.getOwnPropertyNames with iframe and window -var toIObject = require('./_to-iobject') - , gOPN = require('./_object-gopn').f - , toString = {}.toString; - -var windowNames = typeof window == 'object' && window && Object.getOwnPropertyNames - ? Object.getOwnPropertyNames(window) : []; - -var getWindowNames = function(it){ - try { - return gOPN(it); - } catch(e){ - return windowNames.slice(); - } -}; - -module.exports.f = function getOwnPropertyNames(it){ - return windowNames && toString.call(it) == '[object Window]' ? getWindowNames(it) : gOPN(toIObject(it)); -}; - -},{"./_object-gopn":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_object-gopn.js","./_to-iobject":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_to-iobject.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_object-gopn.js":[function(require,module,exports){ -// 19.1.2.7 / 15.2.3.4 Object.getOwnPropertyNames(O) -var $keys = require('./_object-keys-internal') - , hiddenKeys = require('./_enum-bug-keys').concat('length', 'prototype'); - -exports.f = Object.getOwnPropertyNames || function getOwnPropertyNames(O){ - return $keys(O, hiddenKeys); -}; -},{"./_enum-bug-keys":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_enum-bug-keys.js","./_object-keys-internal":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_object-keys-internal.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_object-gops.js":[function(require,module,exports){ -exports.f = Object.getOwnPropertySymbols; -},{}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_object-gpo.js":[function(require,module,exports){ -// 19.1.2.9 / 15.2.3.2 Object.getPrototypeOf(O) -var has = require('./_has') - , toObject = require('./_to-object') - , IE_PROTO = require('./_shared-key')('IE_PROTO') - , ObjectProto = Object.prototype; - -module.exports = Object.getPrototypeOf || function(O){ - O = toObject(O); - if(has(O, IE_PROTO))return O[IE_PROTO]; - if(typeof O.constructor == 'function' && O instanceof O.constructor){ - return O.constructor.prototype; - } return O instanceof Object ? ObjectProto : null; -}; -},{"./_has":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_has.js","./_shared-key":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_shared-key.js","./_to-object":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_to-object.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_object-keys-internal.js":[function(require,module,exports){ -var has = require('./_has') - , toIObject = require('./_to-iobject') - , arrayIndexOf = require('./_array-includes')(false) - , IE_PROTO = require('./_shared-key')('IE_PROTO'); - -module.exports = function(object, names){ - var O = toIObject(object) - , i = 0 - , result = [] - , key; - for(key in O)if(key != IE_PROTO)has(O, key) && result.push(key); - // Don't enum bug & hidden keys - while(names.length > i)if(has(O, key = names[i++])){ - ~arrayIndexOf(result, key) || result.push(key); - } - return result; -}; -},{"./_array-includes":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_array-includes.js","./_has":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_has.js","./_shared-key":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_shared-key.js","./_to-iobject":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_to-iobject.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_object-keys.js":[function(require,module,exports){ -// 19.1.2.14 / 15.2.3.14 Object.keys(O) -var $keys = require('./_object-keys-internal') - , enumBugKeys = require('./_enum-bug-keys'); - -module.exports = Object.keys || function keys(O){ - return $keys(O, enumBugKeys); -}; -},{"./_enum-bug-keys":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_enum-bug-keys.js","./_object-keys-internal":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_object-keys-internal.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_object-pie.js":[function(require,module,exports){ -exports.f = {}.propertyIsEnumerable; -},{}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_object-sap.js":[function(require,module,exports){ -// most Object methods by ES6 should accept primitives -var $export = require('./_export') - , core = require('./_core') - , fails = require('./_fails'); -module.exports = function(KEY, exec){ - var fn = (core.Object || {})[KEY] || Object[KEY] - , exp = {}; - exp[KEY] = exec(fn); - $export($export.S + $export.F * fails(function(){ fn(1); }), 'Object', exp); -}; -},{"./_core":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_core.js","./_export":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_export.js","./_fails":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_fails.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_property-desc.js":[function(require,module,exports){ -module.exports = function(bitmap, value){ - return { - enumerable : !(bitmap & 1), - configurable: !(bitmap & 2), - writable : !(bitmap & 4), - value : value - }; -}; -},{}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_redefine-all.js":[function(require,module,exports){ -var hide = require('./_hide'); -module.exports = function(target, src, safe){ - for(var key in src){ - if(safe && target[key])target[key] = src[key]; - else hide(target, key, src[key]); - } return target; -}; -},{"./_hide":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_hide.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_redefine.js":[function(require,module,exports){ -module.exports = require('./_hide'); -},{"./_hide":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_hide.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_set-proto.js":[function(require,module,exports){ -// Works with __proto__ only. Old v8 can't work with null proto objects. -/* eslint-disable no-proto */ -var isObject = require('./_is-object') - , anObject = require('./_an-object'); -var check = function(O, proto){ - anObject(O); - if(!isObject(proto) && proto !== null)throw TypeError(proto + ": can't set as prototype!"); -}; -module.exports = { - set: Object.setPrototypeOf || ('__proto__' in {} ? // eslint-disable-line - function(test, buggy, set){ - try { - set = require('./_ctx')(Function.call, require('./_object-gopd').f(Object.prototype, '__proto__').set, 2); - set(test, []); - buggy = !(test instanceof Array); - } catch(e){ buggy = true; } - return function setPrototypeOf(O, proto){ - check(O, proto); - if(buggy)O.__proto__ = proto; - else set(O, proto); - return O; - }; - }({}, false) : undefined), - check: check -}; -},{"./_an-object":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_an-object.js","./_ctx":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_ctx.js","./_is-object":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_is-object.js","./_object-gopd":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_object-gopd.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_set-species.js":[function(require,module,exports){ -'use strict'; -var global = require('./_global') - , core = require('./_core') - , dP = require('./_object-dp') - , DESCRIPTORS = require('./_descriptors') - , SPECIES = require('./_wks')('species'); - -module.exports = function(KEY){ - var C = typeof core[KEY] == 'function' ? core[KEY] : global[KEY]; - if(DESCRIPTORS && C && !C[SPECIES])dP.f(C, SPECIES, { - configurable: true, - get: function(){ return this; } - }); -}; -},{"./_core":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_core.js","./_descriptors":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_descriptors.js","./_global":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_global.js","./_object-dp":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_object-dp.js","./_wks":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_wks.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_set-to-string-tag.js":[function(require,module,exports){ -var def = require('./_object-dp').f - , has = require('./_has') - , TAG = require('./_wks')('toStringTag'); - -module.exports = function(it, tag, stat){ - if(it && !has(it = stat ? it : it.prototype, TAG))def(it, TAG, {configurable: true, value: tag}); -}; -},{"./_has":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_has.js","./_object-dp":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_object-dp.js","./_wks":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_wks.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_shared-key.js":[function(require,module,exports){ -var shared = require('./_shared')('keys') - , uid = require('./_uid'); -module.exports = function(key){ - return shared[key] || (shared[key] = uid(key)); -}; -},{"./_shared":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_shared.js","./_uid":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_uid.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_shared.js":[function(require,module,exports){ -var global = require('./_global') - , SHARED = '__core-js_shared__' - , store = global[SHARED] || (global[SHARED] = {}); -module.exports = function(key){ - return store[key] || (store[key] = {}); -}; -},{"./_global":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_global.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_species-constructor.js":[function(require,module,exports){ -// 7.3.20 SpeciesConstructor(O, defaultConstructor) -var anObject = require('./_an-object') - , aFunction = require('./_a-function') - , SPECIES = require('./_wks')('species'); -module.exports = function(O, D){ - var C = anObject(O).constructor, S; - return C === undefined || (S = anObject(C)[SPECIES]) == undefined ? D : aFunction(S); -}; -},{"./_a-function":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_a-function.js","./_an-object":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_an-object.js","./_wks":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_wks.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_string-at.js":[function(require,module,exports){ -var toInteger = require('./_to-integer') - , defined = require('./_defined'); -// true -> String#at -// false -> String#codePointAt -module.exports = function(TO_STRING){ - return function(that, pos){ - var s = String(defined(that)) - , i = toInteger(pos) - , l = s.length - , a, b; - if(i < 0 || i >= l)return TO_STRING ? '' : undefined; - a = s.charCodeAt(i); - return a < 0xd800 || a > 0xdbff || i + 1 === l || (b = s.charCodeAt(i + 1)) < 0xdc00 || b > 0xdfff - ? TO_STRING ? s.charAt(i) : a - : TO_STRING ? s.slice(i, i + 2) : (a - 0xd800 << 10) + (b - 0xdc00) + 0x10000; - }; -}; -},{"./_defined":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_defined.js","./_to-integer":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_to-integer.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_task.js":[function(require,module,exports){ -var ctx = require('./_ctx') - , invoke = require('./_invoke') - , html = require('./_html') - , cel = require('./_dom-create') - , global = require('./_global') - , process = global.process - , setTask = global.setImmediate - , clearTask = global.clearImmediate - , MessageChannel = global.MessageChannel - , counter = 0 - , queue = {} - , ONREADYSTATECHANGE = 'onreadystatechange' - , defer, channel, port; -var run = function(){ - var id = +this; - if(queue.hasOwnProperty(id)){ - var fn = queue[id]; - delete queue[id]; - fn(); - } -}; -var listener = function(event){ - run.call(event.data); -}; -// Node.js 0.9+ & IE10+ has setImmediate, otherwise: -if(!setTask || !clearTask){ - setTask = function setImmediate(fn){ - var args = [], i = 1; - while(arguments.length > i)args.push(arguments[i++]); - queue[++counter] = function(){ - invoke(typeof fn == 'function' ? fn : Function(fn), args); - }; - defer(counter); - return counter; - }; - clearTask = function clearImmediate(id){ - delete queue[id]; - }; - // Node.js 0.8- - if(require('./_cof')(process) == 'process'){ - defer = function(id){ - process.nextTick(ctx(run, id, 1)); - }; - // Browsers with MessageChannel, includes WebWorkers - } else if(MessageChannel){ - channel = new MessageChannel; - port = channel.port2; - channel.port1.onmessage = listener; - defer = ctx(port.postMessage, port, 1); - // Browsers with postMessage, skip WebWorkers - // IE8 has postMessage, but it's sync & typeof its postMessage is 'object' - } else if(global.addEventListener && typeof postMessage == 'function' && !global.importScripts){ - defer = function(id){ - global.postMessage(id + '', '*'); - }; - global.addEventListener('message', listener, false); - // IE8- - } else if(ONREADYSTATECHANGE in cel('script')){ - defer = function(id){ - html.appendChild(cel('script'))[ONREADYSTATECHANGE] = function(){ - html.removeChild(this); - run.call(id); - }; - }; - // Rest old browsers - } else { - defer = function(id){ - setTimeout(ctx(run, id, 1), 0); - }; - } -} -module.exports = { - set: setTask, - clear: clearTask -}; -},{"./_cof":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_cof.js","./_ctx":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_ctx.js","./_dom-create":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_dom-create.js","./_global":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_global.js","./_html":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_html.js","./_invoke":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_invoke.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_to-index.js":[function(require,module,exports){ -var toInteger = require('./_to-integer') - , max = Math.max - , min = Math.min; -module.exports = function(index, length){ - index = toInteger(index); - return index < 0 ? max(index + length, 0) : min(index, length); -}; -},{"./_to-integer":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_to-integer.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_to-integer.js":[function(require,module,exports){ -// 7.1.4 ToInteger -var ceil = Math.ceil - , floor = Math.floor; -module.exports = function(it){ - return isNaN(it = +it) ? 0 : (it > 0 ? floor : ceil)(it); -}; -},{}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_to-iobject.js":[function(require,module,exports){ -// to indexed object, toObject with fallback for non-array-like ES3 strings -var IObject = require('./_iobject') - , defined = require('./_defined'); -module.exports = function(it){ - return IObject(defined(it)); -}; -},{"./_defined":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_defined.js","./_iobject":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_iobject.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_to-length.js":[function(require,module,exports){ -// 7.1.15 ToLength -var toInteger = require('./_to-integer') - , min = Math.min; -module.exports = function(it){ - return it > 0 ? min(toInteger(it), 0x1fffffffffffff) : 0; // pow(2, 53) - 1 == 9007199254740991 -}; -},{"./_to-integer":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_to-integer.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_to-object.js":[function(require,module,exports){ -// 7.1.13 ToObject(argument) -var defined = require('./_defined'); -module.exports = function(it){ - return Object(defined(it)); -}; -},{"./_defined":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_defined.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_to-primitive.js":[function(require,module,exports){ -// 7.1.1 ToPrimitive(input [, PreferredType]) -var isObject = require('./_is-object'); -// instead of the ES6 spec version, we didn't implement @@toPrimitive case -// and the second argument - flag - preferred type is a string -module.exports = function(it, S){ - if(!isObject(it))return it; - var fn, val; - if(S && typeof (fn = it.toString) == 'function' && !isObject(val = fn.call(it)))return val; - if(typeof (fn = it.valueOf) == 'function' && !isObject(val = fn.call(it)))return val; - if(!S && typeof (fn = it.toString) == 'function' && !isObject(val = fn.call(it)))return val; - throw TypeError("Can't convert object to primitive value"); -}; -},{"./_is-object":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_is-object.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_uid.js":[function(require,module,exports){ -var id = 0 - , px = Math.random(); -module.exports = function(key){ - return 'Symbol('.concat(key === undefined ? '' : key, ')_', (++id + px).toString(36)); -}; -},{}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_wks-define.js":[function(require,module,exports){ -var global = require('./_global') - , core = require('./_core') - , LIBRARY = require('./_library') - , wksExt = require('./_wks-ext') - , defineProperty = require('./_object-dp').f; -module.exports = function(name){ - var $Symbol = core.Symbol || (core.Symbol = LIBRARY ? {} : global.Symbol || {}); - if(name.charAt(0) != '_' && !(name in $Symbol))defineProperty($Symbol, name, {value: wksExt.f(name)}); -}; -},{"./_core":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_core.js","./_global":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_global.js","./_library":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_library.js","./_object-dp":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_object-dp.js","./_wks-ext":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_wks-ext.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_wks-ext.js":[function(require,module,exports){ -exports.f = require('./_wks'); -},{"./_wks":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_wks.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_wks.js":[function(require,module,exports){ -var store = require('./_shared')('wks') - , uid = require('./_uid') - , Symbol = require('./_global').Symbol - , USE_SYMBOL = typeof Symbol == 'function'; - -var $exports = module.exports = function(name){ - return store[name] || (store[name] = - USE_SYMBOL && Symbol[name] || (USE_SYMBOL ? Symbol : uid)('Symbol.' + name)); -}; - -$exports.store = store; -},{"./_global":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_global.js","./_shared":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_shared.js","./_uid":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_uid.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/core.get-iterator-method.js":[function(require,module,exports){ -var classof = require('./_classof') - , ITERATOR = require('./_wks')('iterator') - , Iterators = require('./_iterators'); -module.exports = require('./_core').getIteratorMethod = function(it){ - if(it != undefined)return it[ITERATOR] - || it['@@iterator'] - || Iterators[classof(it)]; -}; -},{"./_classof":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_classof.js","./_core":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_core.js","./_iterators":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_iterators.js","./_wks":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_wks.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/core.get-iterator.js":[function(require,module,exports){ -var anObject = require('./_an-object') - , get = require('./core.get-iterator-method'); -module.exports = require('./_core').getIterator = function(it){ - var iterFn = get(it); - if(typeof iterFn != 'function')throw TypeError(it + ' is not iterable!'); - return anObject(iterFn.call(it)); -}; -},{"./_an-object":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_an-object.js","./_core":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_core.js","./core.get-iterator-method":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/core.get-iterator-method.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/es6.array.from.js":[function(require,module,exports){ -'use strict'; -var ctx = require('./_ctx') - , $export = require('./_export') - , toObject = require('./_to-object') - , call = require('./_iter-call') - , isArrayIter = require('./_is-array-iter') - , toLength = require('./_to-length') - , createProperty = require('./_create-property') - , getIterFn = require('./core.get-iterator-method'); - -$export($export.S + $export.F * !require('./_iter-detect')(function(iter){ Array.from(iter); }), 'Array', { - // 22.1.2.1 Array.from(arrayLike, mapfn = undefined, thisArg = undefined) - from: function from(arrayLike/*, mapfn = undefined, thisArg = undefined*/){ - var O = toObject(arrayLike) - , C = typeof this == 'function' ? this : Array - , aLen = arguments.length - , mapfn = aLen > 1 ? arguments[1] : undefined - , mapping = mapfn !== undefined - , index = 0 - , iterFn = getIterFn(O) - , length, result, step, iterator; - if(mapping)mapfn = ctx(mapfn, aLen > 2 ? arguments[2] : undefined, 2); - // if object isn't iterable or it's array with default iterator - use simple case - if(iterFn != undefined && !(C == Array && isArrayIter(iterFn))){ - for(iterator = iterFn.call(O), result = new C; !(step = iterator.next()).done; index++){ - createProperty(result, index, mapping ? call(iterator, mapfn, [step.value, index], true) : step.value); - } - } else { - length = toLength(O.length); - for(result = new C(length); length > index; index++){ - createProperty(result, index, mapping ? mapfn(O[index], index) : O[index]); - } - } - result.length = index; - return result; - } -}); - -},{"./_create-property":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_create-property.js","./_ctx":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_ctx.js","./_export":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_export.js","./_is-array-iter":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_is-array-iter.js","./_iter-call":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_iter-call.js","./_iter-detect":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_iter-detect.js","./_to-length":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_to-length.js","./_to-object":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_to-object.js","./core.get-iterator-method":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/core.get-iterator-method.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/es6.array.iterator.js":[function(require,module,exports){ -'use strict'; -var addToUnscopables = require('./_add-to-unscopables') - , step = require('./_iter-step') - , Iterators = require('./_iterators') - , toIObject = require('./_to-iobject'); - -// 22.1.3.4 Array.prototype.entries() -// 22.1.3.13 Array.prototype.keys() -// 22.1.3.29 Array.prototype.values() -// 22.1.3.30 Array.prototype[@@iterator]() -module.exports = require('./_iter-define')(Array, 'Array', function(iterated, kind){ - this._t = toIObject(iterated); // target - this._i = 0; // next index - this._k = kind; // kind -// 22.1.5.2.1 %ArrayIteratorPrototype%.next() -}, function(){ - var O = this._t - , kind = this._k - , index = this._i++; - if(!O || index >= O.length){ - this._t = undefined; - return step(1); - } - if(kind == 'keys' )return step(0, index); - if(kind == 'values')return step(0, O[index]); - return step(0, [index, O[index]]); -}, 'values'); - -// argumentsList[@@iterator] is %ArrayProto_values% (9.4.4.6, 9.4.4.7) -Iterators.Arguments = Iterators.Array; - -addToUnscopables('keys'); -addToUnscopables('values'); -addToUnscopables('entries'); -},{"./_add-to-unscopables":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_add-to-unscopables.js","./_iter-define":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_iter-define.js","./_iter-step":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_iter-step.js","./_iterators":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_iterators.js","./_to-iobject":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_to-iobject.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/es6.map.js":[function(require,module,exports){ -'use strict'; -var strong = require('./_collection-strong'); - -// 23.1 Map Objects -module.exports = require('./_collection')('Map', function(get){ - return function Map(){ return get(this, arguments.length > 0 ? arguments[0] : undefined); }; -}, { - // 23.1.3.6 Map.prototype.get(key) - get: function get(key){ - var entry = strong.getEntry(this, key); - return entry && entry.v; - }, - // 23.1.3.9 Map.prototype.set(key, value) - set: function set(key, value){ - return strong.def(this, key === 0 ? 0 : key, value); - } -}, strong, true); -},{"./_collection":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_collection.js","./_collection-strong":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_collection-strong.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/es6.object.assign.js":[function(require,module,exports){ -// 19.1.3.1 Object.assign(target, source) -var $export = require('./_export'); - -$export($export.S + $export.F, 'Object', {assign: require('./_object-assign')}); -},{"./_export":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_export.js","./_object-assign":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_object-assign.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/es6.object.create.js":[function(require,module,exports){ -var $export = require('./_export') -// 19.1.2.2 / 15.2.3.5 Object.create(O [, Properties]) -$export($export.S, 'Object', {create: require('./_object-create')}); -},{"./_export":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_export.js","./_object-create":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_object-create.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/es6.object.define-property.js":[function(require,module,exports){ -var $export = require('./_export'); -// 19.1.2.4 / 15.2.3.6 Object.defineProperty(O, P, Attributes) -$export($export.S + $export.F * !require('./_descriptors'), 'Object', {defineProperty: require('./_object-dp').f}); -},{"./_descriptors":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_descriptors.js","./_export":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_export.js","./_object-dp":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_object-dp.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/es6.object.get-prototype-of.js":[function(require,module,exports){ -// 19.1.2.9 Object.getPrototypeOf(O) -var toObject = require('./_to-object') - , $getPrototypeOf = require('./_object-gpo'); - -require('./_object-sap')('getPrototypeOf', function(){ - return function getPrototypeOf(it){ - return $getPrototypeOf(toObject(it)); - }; -}); -},{"./_object-gpo":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_object-gpo.js","./_object-sap":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_object-sap.js","./_to-object":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_to-object.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/es6.object.keys.js":[function(require,module,exports){ -// 19.1.2.14 Object.keys(O) -var toObject = require('./_to-object') - , $keys = require('./_object-keys'); - -require('./_object-sap')('keys', function(){ - return function keys(it){ - return $keys(toObject(it)); - }; -}); -},{"./_object-keys":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_object-keys.js","./_object-sap":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_object-sap.js","./_to-object":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_to-object.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/es6.object.set-prototype-of.js":[function(require,module,exports){ -// 19.1.3.19 Object.setPrototypeOf(O, proto) -var $export = require('./_export'); -$export($export.S, 'Object', {setPrototypeOf: require('./_set-proto').set}); -},{"./_export":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_export.js","./_set-proto":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_set-proto.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/es6.object.to-string.js":[function(require,module,exports){ - -},{}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/es6.promise.js":[function(require,module,exports){ -'use strict'; -var LIBRARY = require('./_library') - , global = require('./_global') - , ctx = require('./_ctx') - , classof = require('./_classof') - , $export = require('./_export') - , isObject = require('./_is-object') - , aFunction = require('./_a-function') - , anInstance = require('./_an-instance') - , forOf = require('./_for-of') - , speciesConstructor = require('./_species-constructor') - , task = require('./_task').set - , microtask = require('./_microtask')() - , PROMISE = 'Promise' - , TypeError = global.TypeError - , process = global.process - , $Promise = global[PROMISE] - , process = global.process - , isNode = classof(process) == 'process' - , empty = function(){ /* empty */ } - , Internal, GenericPromiseCapability, Wrapper; - -var USE_NATIVE = !!function(){ - try { - // correct subclassing with @@species support - var promise = $Promise.resolve(1) - , FakePromise = (promise.constructor = {})[require('./_wks')('species')] = function(exec){ exec(empty, empty); }; - // unhandled rejections tracking support, NodeJS Promise without it fails @@species test - return (isNode || typeof PromiseRejectionEvent == 'function') && promise.then(empty) instanceof FakePromise; - } catch(e){ /* empty */ } -}(); - -// helpers -var sameConstructor = function(a, b){ - // with library wrapper special case - return a === b || a === $Promise && b === Wrapper; -}; -var isThenable = function(it){ - var then; - return isObject(it) && typeof (then = it.then) == 'function' ? then : false; -}; -var newPromiseCapability = function(C){ - return sameConstructor($Promise, C) - ? new PromiseCapability(C) - : new GenericPromiseCapability(C); -}; -var PromiseCapability = GenericPromiseCapability = function(C){ - var resolve, reject; - this.promise = new C(function($$resolve, $$reject){ - if(resolve !== undefined || reject !== undefined)throw TypeError('Bad Promise constructor'); - resolve = $$resolve; - reject = $$reject; - }); - this.resolve = aFunction(resolve); - this.reject = aFunction(reject); -}; -var perform = function(exec){ - try { - exec(); - } catch(e){ - return {error: e}; - } -}; -var notify = function(promise, isReject){ - if(promise._n)return; - promise._n = true; - var chain = promise._c; - microtask(function(){ - var value = promise._v - , ok = promise._s == 1 - , i = 0; - var run = function(reaction){ - var handler = ok ? reaction.ok : reaction.fail - , resolve = reaction.resolve - , reject = reaction.reject - , domain = reaction.domain - , result, then; - try { - if(handler){ - if(!ok){ - if(promise._h == 2)onHandleUnhandled(promise); - promise._h = 1; - } - if(handler === true)result = value; - else { - if(domain)domain.enter(); - result = handler(value); - if(domain)domain.exit(); - } - if(result === reaction.promise){ - reject(TypeError('Promise-chain cycle')); - } else if(then = isThenable(result)){ - then.call(result, resolve, reject); - } else resolve(result); - } else reject(value); - } catch(e){ - reject(e); - } - }; - while(chain.length > i)run(chain[i++]); // variable length - can't use forEach - promise._c = []; - promise._n = false; - if(isReject && !promise._h)onUnhandled(promise); - }); -}; -var onUnhandled = function(promise){ - task.call(global, function(){ - var value = promise._v - , abrupt, handler, console; - if(isUnhandled(promise)){ - abrupt = perform(function(){ - if(isNode){ - process.emit('unhandledRejection', value, promise); - } else if(handler = global.onunhandledrejection){ - handler({promise: promise, reason: value}); - } else if((console = global.console) && console.error){ - console.error('Unhandled promise rejection', value); - } - }); - // Browsers should not trigger `rejectionHandled` event if it was handled here, NodeJS - should - promise._h = isNode || isUnhandled(promise) ? 2 : 1; - } promise._a = undefined; - if(abrupt)throw abrupt.error; - }); -}; -var isUnhandled = function(promise){ - if(promise._h == 1)return false; - var chain = promise._a || promise._c - , i = 0 - , reaction; - while(chain.length > i){ - reaction = chain[i++]; - if(reaction.fail || !isUnhandled(reaction.promise))return false; - } return true; -}; -var onHandleUnhandled = function(promise){ - task.call(global, function(){ - var handler; - if(isNode){ - process.emit('rejectionHandled', promise); - } else if(handler = global.onrejectionhandled){ - handler({promise: promise, reason: promise._v}); - } - }); -}; -var $reject = function(value){ - var promise = this; - if(promise._d)return; - promise._d = true; - promise = promise._w || promise; // unwrap - promise._v = value; - promise._s = 2; - if(!promise._a)promise._a = promise._c.slice(); - notify(promise, true); -}; -var $resolve = function(value){ - var promise = this - , then; - if(promise._d)return; - promise._d = true; - promise = promise._w || promise; // unwrap - try { - if(promise === value)throw TypeError("Promise can't be resolved itself"); - if(then = isThenable(value)){ - microtask(function(){ - var wrapper = {_w: promise, _d: false}; // wrap - try { - then.call(value, ctx($resolve, wrapper, 1), ctx($reject, wrapper, 1)); - } catch(e){ - $reject.call(wrapper, e); - } - }); - } else { - promise._v = value; - promise._s = 1; - notify(promise, false); - } - } catch(e){ - $reject.call({_w: promise, _d: false}, e); // wrap - } -}; - -// constructor polyfill -if(!USE_NATIVE){ - // 25.4.3.1 Promise(executor) - $Promise = function Promise(executor){ - anInstance(this, $Promise, PROMISE, '_h'); - aFunction(executor); - Internal.call(this); - try { - executor(ctx($resolve, this, 1), ctx($reject, this, 1)); - } catch(err){ - $reject.call(this, err); - } - }; - Internal = function Promise(executor){ - this._c = []; // <- awaiting reactions - this._a = undefined; // <- checked in isUnhandled reactions - this._s = 0; // <- state - this._d = false; // <- done - this._v = undefined; // <- value - this._h = 0; // <- rejection state, 0 - default, 1 - handled, 2 - unhandled - this._n = false; // <- notify - }; - Internal.prototype = require('./_redefine-all')($Promise.prototype, { - // 25.4.5.3 Promise.prototype.then(onFulfilled, onRejected) - then: function then(onFulfilled, onRejected){ - var reaction = newPromiseCapability(speciesConstructor(this, $Promise)); - reaction.ok = typeof onFulfilled == 'function' ? onFulfilled : true; - reaction.fail = typeof onRejected == 'function' && onRejected; - reaction.domain = isNode ? process.domain : undefined; - this._c.push(reaction); - if(this._a)this._a.push(reaction); - if(this._s)notify(this, false); - return reaction.promise; - }, - // 25.4.5.1 Promise.prototype.catch(onRejected) - 'catch': function(onRejected){ - return this.then(undefined, onRejected); - } - }); - PromiseCapability = function(){ - var promise = new Internal; - this.promise = promise; - this.resolve = ctx($resolve, promise, 1); - this.reject = ctx($reject, promise, 1); - }; -} - -$export($export.G + $export.W + $export.F * !USE_NATIVE, {Promise: $Promise}); -require('./_set-to-string-tag')($Promise, PROMISE); -require('./_set-species')(PROMISE); -Wrapper = require('./_core')[PROMISE]; - -// statics -$export($export.S + $export.F * !USE_NATIVE, PROMISE, { - // 25.4.4.5 Promise.reject(r) - reject: function reject(r){ - var capability = newPromiseCapability(this) - , $$reject = capability.reject; - $$reject(r); - return capability.promise; - } -}); -$export($export.S + $export.F * (LIBRARY || !USE_NATIVE), PROMISE, { - // 25.4.4.6 Promise.resolve(x) - resolve: function resolve(x){ - // instanceof instead of internal slot check because we should fix it without replacement native Promise core - if(x instanceof $Promise && sameConstructor(x.constructor, this))return x; - var capability = newPromiseCapability(this) - , $$resolve = capability.resolve; - $$resolve(x); - return capability.promise; - } -}); -$export($export.S + $export.F * !(USE_NATIVE && require('./_iter-detect')(function(iter){ - $Promise.all(iter)['catch'](empty); -})), PROMISE, { - // 25.4.4.1 Promise.all(iterable) - all: function all(iterable){ - var C = this - , capability = newPromiseCapability(C) - , resolve = capability.resolve - , reject = capability.reject; - var abrupt = perform(function(){ - var values = [] - , index = 0 - , remaining = 1; - forOf(iterable, false, function(promise){ - var $index = index++ - , alreadyCalled = false; - values.push(undefined); - remaining++; - C.resolve(promise).then(function(value){ - if(alreadyCalled)return; - alreadyCalled = true; - values[$index] = value; - --remaining || resolve(values); - }, reject); - }); - --remaining || resolve(values); - }); - if(abrupt)reject(abrupt.error); - return capability.promise; - }, - // 25.4.4.4 Promise.race(iterable) - race: function race(iterable){ - var C = this - , capability = newPromiseCapability(C) - , reject = capability.reject; - var abrupt = perform(function(){ - forOf(iterable, false, function(promise){ - C.resolve(promise).then(capability.resolve, reject); - }); - }); - if(abrupt)reject(abrupt.error); - return capability.promise; - } -}); -},{"./_a-function":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_a-function.js","./_an-instance":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_an-instance.js","./_classof":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_classof.js","./_core":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_core.js","./_ctx":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_ctx.js","./_export":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_export.js","./_for-of":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_for-of.js","./_global":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_global.js","./_is-object":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_is-object.js","./_iter-detect":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_iter-detect.js","./_library":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_library.js","./_microtask":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_microtask.js","./_redefine-all":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_redefine-all.js","./_set-species":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_set-species.js","./_set-to-string-tag":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_set-to-string-tag.js","./_species-constructor":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_species-constructor.js","./_task":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_task.js","./_wks":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_wks.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/es6.set.js":[function(require,module,exports){ -'use strict'; -var strong = require('./_collection-strong'); - -// 23.2 Set Objects -module.exports = require('./_collection')('Set', function(get){ - return function Set(){ return get(this, arguments.length > 0 ? arguments[0] : undefined); }; -}, { - // 23.2.3.1 Set.prototype.add(value) - add: function add(value){ - return strong.def(this, value = value === 0 ? 0 : value, value); - } -}, strong); -},{"./_collection":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_collection.js","./_collection-strong":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_collection-strong.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/es6.string.iterator.js":[function(require,module,exports){ -'use strict'; -var $at = require('./_string-at')(true); - -// 21.1.3.27 String.prototype[@@iterator]() -require('./_iter-define')(String, 'String', function(iterated){ - this._t = String(iterated); // target - this._i = 0; // next index -// 21.1.5.2.1 %StringIteratorPrototype%.next() -}, function(){ - var O = this._t - , index = this._i - , point; - if(index >= O.length)return {value: undefined, done: true}; - point = $at(O, index); - this._i += point.length; - return {value: point, done: false}; -}); -},{"./_iter-define":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_iter-define.js","./_string-at":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_string-at.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/es6.symbol.js":[function(require,module,exports){ -'use strict'; -// ECMAScript 6 symbols shim -var global = require('./_global') - , has = require('./_has') - , DESCRIPTORS = require('./_descriptors') - , $export = require('./_export') - , redefine = require('./_redefine') - , META = require('./_meta').KEY - , $fails = require('./_fails') - , shared = require('./_shared') - , setToStringTag = require('./_set-to-string-tag') - , uid = require('./_uid') - , wks = require('./_wks') - , wksExt = require('./_wks-ext') - , wksDefine = require('./_wks-define') - , keyOf = require('./_keyof') - , enumKeys = require('./_enum-keys') - , isArray = require('./_is-array') - , anObject = require('./_an-object') - , toIObject = require('./_to-iobject') - , toPrimitive = require('./_to-primitive') - , createDesc = require('./_property-desc') - , _create = require('./_object-create') - , gOPNExt = require('./_object-gopn-ext') - , $GOPD = require('./_object-gopd') - , $DP = require('./_object-dp') - , $keys = require('./_object-keys') - , gOPD = $GOPD.f - , dP = $DP.f - , gOPN = gOPNExt.f - , $Symbol = global.Symbol - , $JSON = global.JSON - , _stringify = $JSON && $JSON.stringify - , PROTOTYPE = 'prototype' - , HIDDEN = wks('_hidden') - , TO_PRIMITIVE = wks('toPrimitive') - , isEnum = {}.propertyIsEnumerable - , SymbolRegistry = shared('symbol-registry') - , AllSymbols = shared('symbols') - , OPSymbols = shared('op-symbols') - , ObjectProto = Object[PROTOTYPE] - , USE_NATIVE = typeof $Symbol == 'function' - , QObject = global.QObject; -// Don't use setters in Qt Script, https://github.com/zloirock/core-js/issues/173 -var setter = !QObject || !QObject[PROTOTYPE] || !QObject[PROTOTYPE].findChild; - -// fallback for old Android, https://code.google.com/p/v8/issues/detail?id=687 -var setSymbolDesc = DESCRIPTORS && $fails(function(){ - return _create(dP({}, 'a', { - get: function(){ return dP(this, 'a', {value: 7}).a; } - })).a != 7; -}) ? function(it, key, D){ - var protoDesc = gOPD(ObjectProto, key); - if(protoDesc)delete ObjectProto[key]; - dP(it, key, D); - if(protoDesc && it !== ObjectProto)dP(ObjectProto, key, protoDesc); -} : dP; - -var wrap = function(tag){ - var sym = AllSymbols[tag] = _create($Symbol[PROTOTYPE]); - sym._k = tag; - return sym; -}; - -var isSymbol = USE_NATIVE && typeof $Symbol.iterator == 'symbol' ? function(it){ - return typeof it == 'symbol'; -} : function(it){ - return it instanceof $Symbol; -}; - -var $defineProperty = function defineProperty(it, key, D){ - if(it === ObjectProto)$defineProperty(OPSymbols, key, D); - anObject(it); - key = toPrimitive(key, true); - anObject(D); - if(has(AllSymbols, key)){ - if(!D.enumerable){ - if(!has(it, HIDDEN))dP(it, HIDDEN, createDesc(1, {})); - it[HIDDEN][key] = true; - } else { - if(has(it, HIDDEN) && it[HIDDEN][key])it[HIDDEN][key] = false; - D = _create(D, {enumerable: createDesc(0, false)}); - } return setSymbolDesc(it, key, D); - } return dP(it, key, D); -}; -var $defineProperties = function defineProperties(it, P){ - anObject(it); - var keys = enumKeys(P = toIObject(P)) - , i = 0 - , l = keys.length - , key; - while(l > i)$defineProperty(it, key = keys[i++], P[key]); - return it; -}; -var $create = function create(it, P){ - return P === undefined ? _create(it) : $defineProperties(_create(it), P); -}; -var $propertyIsEnumerable = function propertyIsEnumerable(key){ - var E = isEnum.call(this, key = toPrimitive(key, true)); - if(this === ObjectProto && has(AllSymbols, key) && !has(OPSymbols, key))return false; - return E || !has(this, key) || !has(AllSymbols, key) || has(this, HIDDEN) && this[HIDDEN][key] ? E : true; -}; -var $getOwnPropertyDescriptor = function getOwnPropertyDescriptor(it, key){ - it = toIObject(it); - key = toPrimitive(key, true); - if(it === ObjectProto && has(AllSymbols, key) && !has(OPSymbols, key))return; - var D = gOPD(it, key); - if(D && has(AllSymbols, key) && !(has(it, HIDDEN) && it[HIDDEN][key]))D.enumerable = true; - return D; -}; -var $getOwnPropertyNames = function getOwnPropertyNames(it){ - var names = gOPN(toIObject(it)) - , result = [] - , i = 0 - , key; - while(names.length > i){ - if(!has(AllSymbols, key = names[i++]) && key != HIDDEN && key != META)result.push(key); - } return result; -}; -var $getOwnPropertySymbols = function getOwnPropertySymbols(it){ - var IS_OP = it === ObjectProto - , names = gOPN(IS_OP ? OPSymbols : toIObject(it)) - , result = [] - , i = 0 - , key; - while(names.length > i){ - if(has(AllSymbols, key = names[i++]) && (IS_OP ? has(ObjectProto, key) : true))result.push(AllSymbols[key]); - } return result; -}; - -// 19.4.1.1 Symbol([description]) -if(!USE_NATIVE){ - $Symbol = function Symbol(){ - if(this instanceof $Symbol)throw TypeError('Symbol is not a constructor!'); - var tag = uid(arguments.length > 0 ? arguments[0] : undefined); - var $set = function(value){ - if(this === ObjectProto)$set.call(OPSymbols, value); - if(has(this, HIDDEN) && has(this[HIDDEN], tag))this[HIDDEN][tag] = false; - setSymbolDesc(this, tag, createDesc(1, value)); - }; - if(DESCRIPTORS && setter)setSymbolDesc(ObjectProto, tag, {configurable: true, set: $set}); - return wrap(tag); - }; - redefine($Symbol[PROTOTYPE], 'toString', function toString(){ - return this._k; - }); - - $GOPD.f = $getOwnPropertyDescriptor; - $DP.f = $defineProperty; - require('./_object-gopn').f = gOPNExt.f = $getOwnPropertyNames; - require('./_object-pie').f = $propertyIsEnumerable; - require('./_object-gops').f = $getOwnPropertySymbols; - - if(DESCRIPTORS && !require('./_library')){ - redefine(ObjectProto, 'propertyIsEnumerable', $propertyIsEnumerable, true); - } - - wksExt.f = function(name){ - return wrap(wks(name)); - } -} - -$export($export.G + $export.W + $export.F * !USE_NATIVE, {Symbol: $Symbol}); - -for(var symbols = ( - // 19.4.2.2, 19.4.2.3, 19.4.2.4, 19.4.2.6, 19.4.2.8, 19.4.2.9, 19.4.2.10, 19.4.2.11, 19.4.2.12, 19.4.2.13, 19.4.2.14 - 'hasInstance,isConcatSpreadable,iterator,match,replace,search,species,split,toPrimitive,toStringTag,unscopables' -).split(','), i = 0; symbols.length > i; )wks(symbols[i++]); - -for(var symbols = $keys(wks.store), i = 0; symbols.length > i; )wksDefine(symbols[i++]); - -$export($export.S + $export.F * !USE_NATIVE, 'Symbol', { - // 19.4.2.1 Symbol.for(key) - 'for': function(key){ - return has(SymbolRegistry, key += '') - ? SymbolRegistry[key] - : SymbolRegistry[key] = $Symbol(key); - }, - // 19.4.2.5 Symbol.keyFor(sym) - keyFor: function keyFor(key){ - if(isSymbol(key))return keyOf(SymbolRegistry, key); - throw TypeError(key + ' is not a symbol!'); - }, - useSetter: function(){ setter = true; }, - useSimple: function(){ setter = false; } -}); - -$export($export.S + $export.F * !USE_NATIVE, 'Object', { - // 19.1.2.2 Object.create(O [, Properties]) - create: $create, - // 19.1.2.4 Object.defineProperty(O, P, Attributes) - defineProperty: $defineProperty, - // 19.1.2.3 Object.defineProperties(O, Properties) - defineProperties: $defineProperties, - // 19.1.2.6 Object.getOwnPropertyDescriptor(O, P) - getOwnPropertyDescriptor: $getOwnPropertyDescriptor, - // 19.1.2.7 Object.getOwnPropertyNames(O) - getOwnPropertyNames: $getOwnPropertyNames, - // 19.1.2.8 Object.getOwnPropertySymbols(O) - getOwnPropertySymbols: $getOwnPropertySymbols -}); - -// 24.3.2 JSON.stringify(value [, replacer [, space]]) -$JSON && $export($export.S + $export.F * (!USE_NATIVE || $fails(function(){ - var S = $Symbol(); - // MS Edge converts symbol values to JSON as {} - // WebKit converts symbol values to JSON as null - // V8 throws on boxed symbols - return _stringify([S]) != '[null]' || _stringify({a: S}) != '{}' || _stringify(Object(S)) != '{}'; -})), 'JSON', { - stringify: function stringify(it){ - if(it === undefined || isSymbol(it))return; // IE8 returns string on undefined - var args = [it] - , i = 1 - , replacer, $replacer; - while(arguments.length > i)args.push(arguments[i++]); - replacer = args[1]; - if(typeof replacer == 'function')$replacer = replacer; - if($replacer || !isArray(replacer))replacer = function(key, value){ - if($replacer)value = $replacer.call(this, key, value); - if(!isSymbol(value))return value; - }; - args[1] = replacer; - return _stringify.apply($JSON, args); - } -}); - -// 19.4.3.4 Symbol.prototype[@@toPrimitive](hint) -$Symbol[PROTOTYPE][TO_PRIMITIVE] || require('./_hide')($Symbol[PROTOTYPE], TO_PRIMITIVE, $Symbol[PROTOTYPE].valueOf); -// 19.4.3.5 Symbol.prototype[@@toStringTag] -setToStringTag($Symbol, 'Symbol'); -// 20.2.1.9 Math[@@toStringTag] -setToStringTag(Math, 'Math', true); -// 24.3.3 JSON[@@toStringTag] -setToStringTag(global.JSON, 'JSON', true); -},{"./_an-object":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_an-object.js","./_descriptors":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_descriptors.js","./_enum-keys":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_enum-keys.js","./_export":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_export.js","./_fails":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_fails.js","./_global":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_global.js","./_has":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_has.js","./_hide":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_hide.js","./_is-array":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_is-array.js","./_keyof":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_keyof.js","./_library":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_library.js","./_meta":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_meta.js","./_object-create":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_object-create.js","./_object-dp":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_object-dp.js","./_object-gopd":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_object-gopd.js","./_object-gopn":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_object-gopn.js","./_object-gopn-ext":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_object-gopn-ext.js","./_object-gops":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_object-gops.js","./_object-keys":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_object-keys.js","./_object-pie":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_object-pie.js","./_property-desc":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_property-desc.js","./_redefine":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_redefine.js","./_set-to-string-tag":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_set-to-string-tag.js","./_shared":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_shared.js","./_to-iobject":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_to-iobject.js","./_to-primitive":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_to-primitive.js","./_uid":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_uid.js","./_wks":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_wks.js","./_wks-define":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_wks-define.js","./_wks-ext":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_wks-ext.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/es7.map.to-json.js":[function(require,module,exports){ -// https://github.com/DavidBruant/Map-Set.prototype.toJSON -var $export = require('./_export'); - -$export($export.P + $export.R, 'Map', {toJSON: require('./_collection-to-json')('Map')}); -},{"./_collection-to-json":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_collection-to-json.js","./_export":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_export.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/es7.set.to-json.js":[function(require,module,exports){ -// https://github.com/DavidBruant/Map-Set.prototype.toJSON -var $export = require('./_export'); - -$export($export.P + $export.R, 'Set', {toJSON: require('./_collection-to-json')('Set')}); -},{"./_collection-to-json":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_collection-to-json.js","./_export":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_export.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/es7.symbol.async-iterator.js":[function(require,module,exports){ -require('./_wks-define')('asyncIterator'); -},{"./_wks-define":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_wks-define.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/es7.symbol.observable.js":[function(require,module,exports){ -require('./_wks-define')('observable'); -},{"./_wks-define":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_wks-define.js"}],"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/web.dom.iterable.js":[function(require,module,exports){ -require('./es6.array.iterator'); -var global = require('./_global') - , hide = require('./_hide') - , Iterators = require('./_iterators') - , TO_STRING_TAG = require('./_wks')('toStringTag'); - -for(var collections = ['NodeList', 'DOMTokenList', 'MediaList', 'StyleSheetList', 'CSSRuleList'], i = 0; i < 5; i++){ - var NAME = collections[i] - , Collection = global[NAME] - , proto = Collection && Collection.prototype; - if(proto && !proto[TO_STRING_TAG])hide(proto, TO_STRING_TAG, NAME); - Iterators[NAME] = Iterators.Array; -} -},{"./_global":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_global.js","./_hide":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_hide.js","./_iterators":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_iterators.js","./_wks":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_wks.js","./es6.array.iterator":"/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/es6.array.iterator.js"}],"/Users/ibc/src/mediasoup-client/node_modules/debug/src/browser.js":[function(require,module,exports){ -(function (process){ -/** - * This is the web browser implementation of `debug()`. - * - * Expose `debug()` as the module. - */ - -exports = module.exports = require('./debug'); -exports.log = log; -exports.formatArgs = formatArgs; -exports.save = save; -exports.load = load; -exports.useColors = useColors; -exports.storage = 'undefined' != typeof chrome - && 'undefined' != typeof chrome.storage - ? chrome.storage.local - : localstorage(); - -/** - * Colors. - */ - -exports.colors = [ - 'lightseagreen', - 'forestgreen', - 'goldenrod', - 'dodgerblue', - 'darkorchid', - 'crimson' -]; - -/** - * Currently only WebKit-based Web Inspectors, Firefox >= v31, - * and the Firebug extension (any Firefox version) are known - * to support "%c" CSS customizations. - * - * TODO: add a `localStorage` variable to explicitly enable/disable colors - */ - -function useColors() { - // NB: In an Electron preload script, document will be defined but not fully - // initialized. Since we know we're in Chrome, we'll just detect this case - // explicitly - if (typeof window !== 'undefined' && window.process && window.process.type === 'renderer') { - return true; - } - - // is webkit? http://stackoverflow.com/a/16459606/376773 - // document is undefined in react-native: https://github.com/facebook/react-native/pull/1632 - return (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) || - // is firebug? http://stackoverflow.com/a/398120/376773 - (typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) || - // is firefox >= v31? - // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages - (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31) || - // double check webkit in userAgent just in case we are in a worker - (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/)); -} - -/** - * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default. - */ - -exports.formatters.j = function(v) { - try { - return JSON.stringify(v); - } catch (err) { - return '[UnexpectedJSONParseError]: ' + err.message; - } -}; - - -/** - * Colorize log arguments if enabled. - * - * @api public - */ - -function formatArgs(args) { - var useColors = this.useColors; - - args[0] = (useColors ? '%c' : '') - + this.namespace - + (useColors ? ' %c' : ' ') - + args[0] - + (useColors ? '%c ' : ' ') - + '+' + exports.humanize(this.diff); - - if (!useColors) return; - - var c = 'color: ' + this.color; - args.splice(1, 0, c, 'color: inherit') - - // the final "%c" is somewhat tricky, because there could be other - // arguments passed either before or after the %c, so we need to - // figure out the correct index to insert the CSS into - var index = 0; - var lastC = 0; - args[0].replace(/%[a-zA-Z%]/g, function(match) { - if ('%%' === match) return; - index++; - if ('%c' === match) { - // we only are interested in the *last* %c - // (the user may have provided their own) - lastC = index; - } - }); - - args.splice(lastC, 0, c); -} - -/** - * Invokes `console.log()` when available. - * No-op when `console.log` is not a "function". - * - * @api public - */ - -function log() { - // this hackery is required for IE8/9, where - // the `console.log` function doesn't have 'apply' - return 'object' === typeof console - && console.log - && Function.prototype.apply.call(console.log, console, arguments); -} - -/** - * Save `namespaces`. - * - * @param {String} namespaces - * @api private - */ - -function save(namespaces) { - try { - if (null == namespaces) { - exports.storage.removeItem('debug'); - } else { - exports.storage.debug = namespaces; - } - } catch(e) {} -} - -/** - * Load `namespaces`. - * - * @return {String} returns the previously persisted debug modes - * @api private - */ - -function load() { - var r; - try { - r = exports.storage.debug; - } catch(e) {} - - // If debug isn't set in LS, and we're in Electron, try to load $DEBUG - if (!r && typeof process !== 'undefined' && 'env' in process) { - r = process.env.DEBUG; - } - - return r; -} - -/** - * Enable namespaces listed in `localStorage.debug` initially. - */ - -exports.enable(load()); - -/** - * Localstorage attempts to return the localstorage. - * - * This is necessary because safari throws - * when a user disables cookies/localstorage - * and you attempt to access it. - * - * @return {LocalStorage} - * @api private - */ - -function localstorage() { - try { - return window.localStorage; - } catch (e) {} -} - -}).call(this,require('_process')) - -},{"./debug":"/Users/ibc/src/mediasoup-client/node_modules/debug/src/debug.js","_process":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/process/browser.js"}],"/Users/ibc/src/mediasoup-client/node_modules/debug/src/debug.js":[function(require,module,exports){ - -/** - * This is the common logic for both the Node.js and web browser - * implementations of `debug()`. - * - * Expose `debug()` as the module. - */ - -exports = module.exports = createDebug.debug = createDebug['default'] = createDebug; -exports.coerce = coerce; -exports.disable = disable; -exports.enable = enable; -exports.enabled = enabled; -exports.humanize = require('ms'); - -/** - * The currently active debug mode names, and names to skip. - */ - -exports.names = []; -exports.skips = []; - -/** - * Map of special "%n" handling functions, for the debug "format" argument. - * - * Valid key names are a single, lower or upper-case letter, i.e. "n" and "N". - */ - -exports.formatters = {}; - -/** - * Previous log timestamp. - */ - -var prevTime; - -/** - * Select a color. - * @param {String} namespace - * @return {Number} - * @api private - */ - -function selectColor(namespace) { - var hash = 0, i; - - for (i in namespace) { - hash = ((hash << 5) - hash) + namespace.charCodeAt(i); - hash |= 0; // Convert to 32bit integer - } - - return exports.colors[Math.abs(hash) % exports.colors.length]; -} - -/** - * Create a debugger with the given `namespace`. - * - * @param {String} namespace - * @return {Function} - * @api public - */ - -function createDebug(namespace) { - - function debug() { - // disabled? - if (!debug.enabled) return; - - var self = debug; - - // set `diff` timestamp - var curr = +new Date(); - var ms = curr - (prevTime || curr); - self.diff = ms; - self.prev = prevTime; - self.curr = curr; - prevTime = curr; - - // turn the `arguments` into a proper Array - var args = new Array(arguments.length); - for (var i = 0; i < args.length; i++) { - args[i] = arguments[i]; - } - - args[0] = exports.coerce(args[0]); - - if ('string' !== typeof args[0]) { - // anything else let's inspect with %O - args.unshift('%O'); - } - - // apply any `formatters` transformations - var index = 0; - args[0] = args[0].replace(/%([a-zA-Z%])/g, function(match, format) { - // if we encounter an escaped % then don't increase the array index - if (match === '%%') return match; - index++; - var formatter = exports.formatters[format]; - if ('function' === typeof formatter) { - var val = args[index]; - match = formatter.call(self, val); - - // now we need to remove `args[index]` since it's inlined in the `format` - args.splice(index, 1); - index--; - } - return match; - }); - - // apply env-specific formatting (colors, etc.) - exports.formatArgs.call(self, args); - - var logFn = debug.log || exports.log || console.log.bind(console); - logFn.apply(self, args); - } - - debug.namespace = namespace; - debug.enabled = exports.enabled(namespace); - debug.useColors = exports.useColors(); - debug.color = selectColor(namespace); - - // env-specific initialization logic for debug instances - if ('function' === typeof exports.init) { - exports.init(debug); - } - - return debug; -} - -/** - * Enables a debug mode by namespaces. This can include modes - * separated by a colon and wildcards. - * - * @param {String} namespaces - * @api public - */ - -function enable(namespaces) { - exports.save(namespaces); - - exports.names = []; - exports.skips = []; - - var split = (typeof namespaces === 'string' ? namespaces : '').split(/[\s,]+/); - var len = split.length; - - for (var i = 0; i < len; i++) { - if (!split[i]) continue; // ignore empty strings - namespaces = split[i].replace(/\*/g, '.*?'); - if (namespaces[0] === '-') { - exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$')); - } else { - exports.names.push(new RegExp('^' + namespaces + '$')); - } - } -} - -/** - * Disable debug output. - * - * @api public - */ - -function disable() { - exports.enable(''); -} - -/** - * Returns true if the given mode name is enabled, false otherwise. - * - * @param {String} name - * @return {Boolean} - * @api public - */ - -function enabled(name) { - var i, len; - for (i = 0, len = exports.skips.length; i < len; i++) { - if (exports.skips[i].test(name)) { - return false; - } - } - for (i = 0, len = exports.names.length; i < len; i++) { - if (exports.names[i].test(name)) { - return true; - } - } - return false; -} - -/** - * Coerce `val`. - * - * @param {Mixed} val - * @return {Mixed} - * @api private - */ - -function coerce(val) { - if (val instanceof Error) return val.stack || val.message; - return val; -} - -},{"ms":"/Users/ibc/src/mediasoup-client/node_modules/ms/index.js"}],"/Users/ibc/src/mediasoup-client/node_modules/ms/index.js":[function(require,module,exports){ -/** - * Helpers. - */ - -var s = 1000; -var m = s * 60; -var h = m * 60; -var d = h * 24; -var y = d * 365.25; - -/** - * Parse or format the given `val`. - * - * Options: - * - * - `long` verbose formatting [false] - * - * @param {String|Number} val - * @param {Object} [options] - * @throws {Error} throw an error if val is not a non-empty string or a number - * @return {String|Number} - * @api public - */ - -module.exports = function(val, options) { - options = options || {}; - var type = typeof val; - if (type === 'string' && val.length > 0) { - return parse(val); - } else if (type === 'number' && isNaN(val) === false) { - return options.long ? fmtLong(val) : fmtShort(val); - } - throw new Error( - 'val is not a non-empty string or a valid number. val=' + - JSON.stringify(val) - ); -}; - -/** - * Parse the given `str` and return milliseconds. - * - * @param {String} str - * @return {Number} - * @api private - */ - -function parse(str) { - str = String(str); - if (str.length > 100) { - return; - } - var match = /^((?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec( - str - ); - if (!match) { - return; - } - var n = parseFloat(match[1]); - var type = (match[2] || 'ms').toLowerCase(); - switch (type) { - case 'years': - case 'year': - case 'yrs': - case 'yr': - case 'y': - return n * y; - case 'days': - case 'day': - case 'd': - return n * d; - case 'hours': - case 'hour': - case 'hrs': - case 'hr': - case 'h': - return n * h; - case 'minutes': - case 'minute': - case 'mins': - case 'min': - case 'm': - return n * m; - case 'seconds': - case 'second': - case 'secs': - case 'sec': - case 's': - return n * s; - case 'milliseconds': - case 'millisecond': - case 'msecs': - case 'msec': - case 'ms': - return n; - default: - return undefined; - } -} - -/** - * Short format for `ms`. - * - * @param {Number} ms - * @return {String} - * @api private - */ - -function fmtShort(ms) { - if (ms >= d) { - return Math.round(ms / d) + 'd'; - } - if (ms >= h) { - return Math.round(ms / h) + 'h'; - } - if (ms >= m) { - return Math.round(ms / m) + 'm'; - } - if (ms >= s) { - return Math.round(ms / s) + 's'; - } - return ms + 'ms'; -} - -/** - * Long format for `ms`. - * - * @param {Number} ms - * @return {String} - * @api private - */ - -function fmtLong(ms) { - return plural(ms, d, 'day') || - plural(ms, h, 'hour') || - plural(ms, m, 'minute') || - plural(ms, s, 'second') || - ms + ' ms'; -} - -/** - * Pluralization helper. - */ - -function plural(ms, n, name) { - if (ms < n) { - return; - } - if (ms < n * 1.5) { - return Math.floor(ms / n) + ' ' + name; - } - return Math.ceil(ms / n) + ' ' + name + 's'; -} - -},{}],"/Users/ibc/src/mediasoup-client/node_modules/random-number/index.js":[function(require,module,exports){ -void function(root){ - - function defaults(options){ - var options = options || {} - var min = options.min - var max = options.max - var integer = options.integer || false - if ( min == null && max == null ) { - min = 0 - max = 1 - } else if ( min == null ) { - min = max - 1 - } else if ( max == null ) { - max = min + 1 - } - if ( max < min ) throw new Error('invalid options, max must be >= min') - return { - min: min - , max: max - , integer: integer - } - } - - function random(options){ - options = defaults(options) - if ( options.max === options.min ) return options.min - var r = Math.random() * (options.max - options.min + Number(!!options.integer)) + options.min - return options.integer ? Math.floor(r) : r - } - - function generator(options){ - options = defaults(options) - return function(min, max, integer){ - options.min = min != null ? min : options.min - options.max = max != null ? max : options.max - options.integer = integer != null ? integer : options.integer - return random(options) - } - } - - module.exports = random - module.exports.generator = generator - module.exports.defaults = defaults -}(this) - -},{}],"/Users/ibc/src/mediasoup-client/node_modules/sdp-transform/lib/grammar.js":[function(require,module,exports){ -var grammar = module.exports = { - v: [{ - name: 'version', - reg: /^(\d*)$/ - }], - o: [{ //o=- 20518 0 IN IP4 203.0.113.1 - // NB: sessionId will be a String in most cases because it is huge - name: 'origin', - reg: /^(\S*) (\d*) (\d*) (\S*) IP(\d) (\S*)/, - names: ['username', 'sessionId', 'sessionVersion', 'netType', 'ipVer', 'address'], - format: '%s %s %d %s IP%d %s' - }], - // default parsing of these only (though some of these feel outdated) - s: [{ name: 'name' }], - i: [{ name: 'description' }], - u: [{ name: 'uri' }], - e: [{ name: 'email' }], - p: [{ name: 'phone' }], - z: [{ name: 'timezones' }], // TODO: this one can actually be parsed properly.. - r: [{ name: 'repeats' }], // TODO: this one can also be parsed properly - //k: [{}], // outdated thing ignored - t: [{ //t=0 0 - name: 'timing', - reg: /^(\d*) (\d*)/, - names: ['start', 'stop'], - format: '%d %d' - }], - c: [{ //c=IN IP4 10.47.197.26 - name: 'connection', - reg: /^IN IP(\d) (\S*)/, - names: ['version', 'ip'], - format: 'IN IP%d %s' - }], - b: [{ //b=AS:4000 - push: 'bandwidth', - reg: /^(TIAS|AS|CT|RR|RS):(\d*)/, - names: ['type', 'limit'], - format: '%s:%s' - }], - m: [{ //m=video 51744 RTP/AVP 126 97 98 34 31 - // NB: special - pushes to session - // TODO: rtp/fmtp should be filtered by the payloads found here? - reg: /^(\w*) (\d*) ([\w\/]*)(?: (.*))?/, - names: ['type', 'port', 'protocol', 'payloads'], - format: '%s %d %s %s' - }], - a: [ - { //a=rtpmap:110 opus/48000/2 - push: 'rtp', - reg: /^rtpmap:(\d*) ([\w\-\.]*)(?:\s*\/(\d*)(?:\s*\/(\S*))?)?/, - names: ['payload', 'codec', 'rate', 'encoding'], - format: function (o) { - return (o.encoding) ? - 'rtpmap:%d %s/%s/%s': - o.rate ? - 'rtpmap:%d %s/%s': - 'rtpmap:%d %s'; - } - }, - { //a=fmtp:108 profile-level-id=24;object=23;bitrate=64000 - //a=fmtp:111 minptime=10; useinbandfec=1 - push: 'fmtp', - reg: /^fmtp:(\d*) ([\S| ]*)/, - names: ['payload', 'config'], - format: 'fmtp:%d %s' - }, - { //a=control:streamid=0 - name: 'control', - reg: /^control:(.*)/, - format: 'control:%s' - }, - { //a=rtcp:65179 IN IP4 193.84.77.194 - name: 'rtcp', - reg: /^rtcp:(\d*)(?: (\S*) IP(\d) (\S*))?/, - names: ['port', 'netType', 'ipVer', 'address'], - format: function (o) { - return (o.address != null) ? - 'rtcp:%d %s IP%d %s': - 'rtcp:%d'; - } - }, - { //a=rtcp-fb:98 trr-int 100 - push: 'rtcpFbTrrInt', - reg: /^rtcp-fb:(\*|\d*) trr-int (\d*)/, - names: ['payload', 'value'], - format: 'rtcp-fb:%d trr-int %d' - }, - { //a=rtcp-fb:98 nack rpsi - push: 'rtcpFb', - reg: /^rtcp-fb:(\*|\d*) ([\w-_]*)(?: ([\w-_]*))?/, - names: ['payload', 'type', 'subtype'], - format: function (o) { - return (o.subtype != null) ? - 'rtcp-fb:%s %s %s': - 'rtcp-fb:%s %s'; - } - }, - { //a=extmap:2 urn:ietf:params:rtp-hdrext:toffset - //a=extmap:1/recvonly URI-gps-string - push: 'ext', - reg: /^extmap:(\d+)(?:\/(\w+))? (\S*)(?: (\S*))?/, - names: ['value', 'direction', 'uri', 'config'], - format: function (o) { - return 'extmap:%d' + (o.direction ? '/%s' : '%v') + ' %s' + (o.config ? ' %s' : ''); - } - }, - { //a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:PS1uQCVeeCFCanVmcjkpPywjNWhcYD0mXXtxaVBR|2^20|1:32 - push: 'crypto', - reg: /^crypto:(\d*) ([\w_]*) (\S*)(?: (\S*))?/, - names: ['id', 'suite', 'config', 'sessionConfig'], - format: function (o) { - return (o.sessionConfig != null) ? - 'crypto:%d %s %s %s': - 'crypto:%d %s %s'; - } - }, - { //a=setup:actpass - name: 'setup', - reg: /^setup:(\w*)/, - format: 'setup:%s' - }, - { //a=mid:1 - name: 'mid', - reg: /^mid:([^\s]*)/, - format: 'mid:%s' - }, - { //a=msid:0c8b064d-d807-43b4-b434-f92a889d8587 98178685-d409-46e0-8e16-7ef0db0db64a - name: 'msid', - reg: /^msid:(.*)/, - format: 'msid:%s' - }, - { //a=ptime:20 - name: 'ptime', - reg: /^ptime:(\d*)/, - format: 'ptime:%d' - }, - { //a=maxptime:60 - name: 'maxptime', - reg: /^maxptime:(\d*)/, - format: 'maxptime:%d' - }, - { //a=sendrecv - name: 'direction', - reg: /^(sendrecv|recvonly|sendonly|inactive)/ - }, - { //a=ice-lite - name: 'icelite', - reg: /^(ice-lite)/ - }, - { //a=ice-ufrag:F7gI - name: 'iceUfrag', - reg: /^ice-ufrag:(\S*)/, - format: 'ice-ufrag:%s' - }, - { //a=ice-pwd:x9cml/YzichV2+XlhiMu8g - name: 'icePwd', - reg: /^ice-pwd:(\S*)/, - format: 'ice-pwd:%s' - }, - { //a=fingerprint:SHA-1 00:11:22:33:44:55:66:77:88:99:AA:BB:CC:DD:EE:FF:00:11:22:33 - name: 'fingerprint', - reg: /^fingerprint:(\S*) (\S*)/, - names: ['type', 'hash'], - format: 'fingerprint:%s %s' - }, - { //a=candidate:0 1 UDP 2113667327 203.0.113.1 54400 typ host - //a=candidate:1162875081 1 udp 2113937151 192.168.34.75 60017 typ host generation 0 network-id 3 network-cost 10 - //a=candidate:3289912957 2 udp 1845501695 193.84.77.194 60017 typ srflx raddr 192.168.34.75 rport 60017 generation 0 network-id 3 network-cost 10 - //a=candidate:229815620 1 tcp 1518280447 192.168.150.19 60017 typ host tcptype active generation 0 network-id 3 network-cost 10 - //a=candidate:3289912957 2 tcp 1845501695 193.84.77.194 60017 typ srflx raddr 192.168.34.75 rport 60017 tcptype passive generation 0 network-id 3 network-cost 10 - push:'candidates', - reg: /^candidate:(\S*) (\d*) (\S*) (\d*) (\S*) (\d*) typ (\S*)(?: raddr (\S*) rport (\d*))?(?: tcptype (\S*))?(?: generation (\d*))?(?: network-id (\d*))?(?: network-cost (\d*))?/, - names: ['foundation', 'component', 'transport', 'priority', 'ip', 'port', 'type', 'raddr', 'rport', 'tcptype', 'generation', 'network-id', 'network-cost'], - format: function (o) { - var str = 'candidate:%s %d %s %d %s %d typ %s'; - - str += (o.raddr != null) ? ' raddr %s rport %d' : '%v%v'; - - // NB: candidate has three optional chunks, so %void middles one if it's missing - str += (o.tcptype != null) ? ' tcptype %s' : '%v'; - - if (o.generation != null) { - str += ' generation %d'; - } - - str += (o['network-id'] != null) ? ' network-id %d' : '%v'; - str += (o['network-cost'] != null) ? ' network-cost %d' : '%v'; - return str; - } - }, - { //a=end-of-candidates (keep after the candidates line for readability) - name: 'endOfCandidates', - reg: /^(end-of-candidates)/ - }, - { //a=remote-candidates:1 203.0.113.1 54400 2 203.0.113.1 54401 ... - name: 'remoteCandidates', - reg: /^remote-candidates:(.*)/, - format: 'remote-candidates:%s' - }, - { //a=ice-options:google-ice - name: 'iceOptions', - reg: /^ice-options:(\S*)/, - format: 'ice-options:%s' - }, - { //a=ssrc:2566107569 cname:t9YU8M1UxTF8Y1A1 - push: 'ssrcs', - reg: /^ssrc:(\d*) ([\w_]*)(?::(.*))?/, - names: ['id', 'attribute', 'value'], - format: function (o) { - var str = 'ssrc:%d'; - if (o.attribute != null) { - str += ' %s'; - if (o.value != null) { - str += ':%s'; - } - } - return str; - } - }, - { //a=ssrc-group:FEC 1 2 - //a=ssrc-group:FEC-FR 3004364195 1080772241 - push: 'ssrcGroups', - // token-char = %x21 / %x23-27 / %x2A-2B / %x2D-2E / %x30-39 / %x41-5A / %x5E-7E - reg: /^ssrc-group:([\x21\x23\x24\x25\x26\x27\x2A\x2B\x2D\x2E\w]*) (.*)/, - names: ['semantics', 'ssrcs'], - format: 'ssrc-group:%s %s' - }, - { //a=msid-semantic: WMS Jvlam5X3SX1OP6pn20zWogvaKJz5Hjf9OnlV - name: 'msidSemantic', - reg: /^msid-semantic:\s?(\w*) (\S*)/, - names: ['semantic', 'token'], - format: 'msid-semantic: %s %s' // space after ':' is not accidental - }, - { //a=group:BUNDLE audio video - push: 'groups', - reg: /^group:(\w*) (.*)/, - names: ['type', 'mids'], - format: 'group:%s %s' - }, - { //a=rtcp-mux - name: 'rtcpMux', - reg: /^(rtcp-mux)/ - }, - { //a=rtcp-rsize - name: 'rtcpRsize', - reg: /^(rtcp-rsize)/ - }, - { //a=sctpmap:5000 webrtc-datachannel 1024 - name: 'sctpmap', - reg: /^sctpmap:([\w_\/]*) (\S*)(?: (\S*))?/, - names: ['sctpmapNumber', 'app', 'maxMessageSize'], - format: function (o) { - return (o.maxMessageSize != null) ? - 'sctpmap:%s %s %s' : - 'sctpmap:%s %s'; - } - }, - { //a=x-google-flag:conference - name: 'xGoogleFlag', - reg: /^x-google-flag:([^\s]*)/, - format: 'x-google-flag:%s' - }, - { //a=rid:1 send max-width=1280;max-height=720;max-fps=30;depend=0 - push: 'rids', - reg: /^rid:([\d\w]+) (\w+)(?: ([\S| ]*))?/, - names: ['id', 'direction', 'params'], - format: function (o) { - return (o.params) ? 'rid:%s %s %s' : 'rid:%s %s'; - } - }, - { //a=imageattr:97 send [x=800,y=640,sar=1.1,q=0.6] [x=480,y=320] recv [x=330,y=250] - //a=imageattr:* send [x=800,y=640] recv * - //a=imageattr:100 recv [x=320,y=240] - push: 'imageattrs', - reg: new RegExp( - //a=imageattr:97 - '^imageattr:(\\d+|\\*)' + - //send [x=800,y=640,sar=1.1,q=0.6] [x=480,y=320] - '[\\s\\t]+(send|recv)[\\s\\t]+(\\*|\\[\\S+\\](?:[\\s\\t]+\\[\\S+\\])*)' + - //recv [x=330,y=250] - '(?:[\\s\\t]+(recv|send)[\\s\\t]+(\\*|\\[\\S+\\](?:[\\s\\t]+\\[\\S+\\])*))?' - ), - names: ['pt', 'dir1', 'attrs1', 'dir2', 'attrs2'], - format: function (o) { - return 'imageattr:%s %s %s' + (o.dir2 ? ' %s %s' : ''); - } - }, - { //a=simulcast:send 1,2,3;~4,~5 recv 6;~7,~8 - //a=simulcast:recv 1;4,5 send 6;7 - name: 'simulcast', - reg: new RegExp( - //a=simulcast: - '^simulcast:' + - //send 1,2,3;~4,~5 - '(send|recv) ([a-zA-Z0-9\\-_~;,]+)' + - //space + recv 6;~7,~8 - '(?:\\s?(send|recv) ([a-zA-Z0-9\\-_~;,]+))?' + - //end - '$' - ), - names: ['dir1', 'list1', 'dir2', 'list2'], - format: function (o) { - return 'simulcast:%s %s' + (o.dir2 ? ' %s %s' : ''); - } - }, - { //Old simulcast draft 03 (implemented by Firefox) - // https://tools.ietf.org/html/draft-ietf-mmusic-sdp-simulcast-03 - //a=simulcast: recv pt=97;98 send pt=97 - //a=simulcast: send rid=5;6;7 paused=6,7 - name: 'simulcast_03', - reg: /^simulcast:[\s\t]+([\S+\s\t]+)$/, - names: ['value'], - format: 'simulcast: %s' - }, - { - //a=framerate:25 - //a=framerate:29.97 - name: 'framerate', - reg: /^framerate:(\d+(?:$|\.\d+))/, - format: 'framerate:%s' - }, - { // any a= that we don't understand is kepts verbatim on media.invalid - push: 'invalid', - names: ['value'] - } - ] -}; - -// set sensible defaults to avoid polluting the grammar with boring details -Object.keys(grammar).forEach(function (key) { - var objs = grammar[key]; - objs.forEach(function (obj) { - if (!obj.reg) { - obj.reg = /(.*)/; - } - if (!obj.format) { - obj.format = '%s'; - } - }); -}); - -},{}],"/Users/ibc/src/mediasoup-client/node_modules/sdp-transform/lib/index.js":[function(require,module,exports){ -var parser = require('./parser'); -var writer = require('./writer'); - -exports.write = writer; -exports.parse = parser.parse; -exports.parseFmtpConfig = parser.parseFmtpConfig; -exports.parseParams = parser.parseParams; -exports.parsePayloads = parser.parsePayloads; -exports.parseRemoteCandidates = parser.parseRemoteCandidates; -exports.parseImageAttributes = parser.parseImageAttributes; -exports.parseSimulcastStreamList = parser.parseSimulcastStreamList; - -},{"./parser":"/Users/ibc/src/mediasoup-client/node_modules/sdp-transform/lib/parser.js","./writer":"/Users/ibc/src/mediasoup-client/node_modules/sdp-transform/lib/writer.js"}],"/Users/ibc/src/mediasoup-client/node_modules/sdp-transform/lib/parser.js":[function(require,module,exports){ -var toIntIfInt = function (v) { - return String(Number(v)) === v ? Number(v) : v; -}; - -var attachProperties = function (match, location, names, rawName) { - if (rawName && !names) { - location[rawName] = toIntIfInt(match[1]); - } - else { - for (var i = 0; i < names.length; i += 1) { - if (match[i+1] != null) { - location[names[i]] = toIntIfInt(match[i+1]); - } - } - } -}; - -var parseReg = function (obj, location, content) { - var needsBlank = obj.name && obj.names; - if (obj.push && !location[obj.push]) { - location[obj.push] = []; - } - else if (needsBlank && !location[obj.name]) { - location[obj.name] = {}; - } - var keyLocation = obj.push ? - {} : // blank object that will be pushed - needsBlank ? location[obj.name] : location; // otherwise, named location or root - - attachProperties(content.match(obj.reg), keyLocation, obj.names, obj.name); - - if (obj.push) { - location[obj.push].push(keyLocation); - } -}; - -var grammar = require('./grammar'); -var validLine = RegExp.prototype.test.bind(/^([a-z])=(.*)/); - -exports.parse = function (sdp) { - var session = {} - , media = [] - , location = session; // points at where properties go under (one of the above) - - // parse lines we understand - sdp.split(/(\r\n|\r|\n)/).filter(validLine).forEach(function (l) { - var type = l[0]; - var content = l.slice(2); - if (type === 'm') { - media.push({rtp: [], fmtp: []}); - location = media[media.length-1]; // point at latest media line - } - - for (var j = 0; j < (grammar[type] || []).length; j += 1) { - var obj = grammar[type][j]; - if (obj.reg.test(content)) { - return parseReg(obj, location, content); - } - } - }); - - session.media = media; // link it up - return session; -}; - -var paramReducer = function (acc, expr) { - var s = expr.split(/=(.+)/, 2); - if (s.length === 2) { - acc[s[0]] = toIntIfInt(s[1]); - } - return acc; -}; - -exports.parseParams = function (str) { - return str.split(/\;\s?/).reduce(paramReducer, {}); -}; - -// For backward compatibility - alias will be removed in 3.0.0 -exports.parseFmtpConfig = exports.parseParams; - -exports.parsePayloads = function (str) { - return str.split(' ').map(Number); -}; - -exports.parseRemoteCandidates = function (str) { - var candidates = []; - var parts = str.split(' ').map(toIntIfInt); - for (var i = 0; i < parts.length; i += 3) { - candidates.push({ - component: parts[i], - ip: parts[i + 1], - port: parts[i + 2] - }); - } - return candidates; -}; - -exports.parseImageAttributes = function (str) { - return str.split(' ').map(function (item) { - return item.substring(1, item.length-1).split(',').reduce(paramReducer, {}); - }); -}; - -exports.parseSimulcastStreamList = function (str) { - return str.split(';').map(function (stream) { - return stream.split(',').map(function (format) { - var scid, paused = false; - - if (format[0] !== '~') { - scid = toIntIfInt(format); - } else { - scid = toIntIfInt(format.substring(1, format.length)); - paused = true; - } - - return { - scid: scid, - paused: paused - }; - }); - }); -}; - -},{"./grammar":"/Users/ibc/src/mediasoup-client/node_modules/sdp-transform/lib/grammar.js"}],"/Users/ibc/src/mediasoup-client/node_modules/sdp-transform/lib/writer.js":[function(require,module,exports){ -var grammar = require('./grammar'); - -// customized util.format - discards excess arguments and can void middle ones -var formatRegExp = /%[sdv%]/g; -var format = function (formatStr) { - var i = 1; - var args = arguments; - var len = args.length; - return formatStr.replace(formatRegExp, function (x) { - if (i >= len) { - return x; // missing argument - } - var arg = args[i]; - i += 1; - switch (x) { - case '%%': - return '%'; - case '%s': - return String(arg); - case '%d': - return Number(arg); - case '%v': - return ''; - } - }); - // NB: we discard excess arguments - they are typically undefined from makeLine -}; - -var makeLine = function (type, obj, location) { - var str = obj.format instanceof Function ? - (obj.format(obj.push ? location : location[obj.name])) : - obj.format; - - var args = [type + '=' + str]; - if (obj.names) { - for (var i = 0; i < obj.names.length; i += 1) { - var n = obj.names[i]; - if (obj.name) { - args.push(location[obj.name][n]); - } - else { // for mLine and push attributes - args.push(location[obj.names[i]]); - } - } - } - else { - args.push(location[obj.name]); - } - return format.apply(null, args); -}; - -// RFC specified order -// TODO: extend this with all the rest -var defaultOuterOrder = [ - 'v', 'o', 's', 'i', - 'u', 'e', 'p', 'c', - 'b', 't', 'r', 'z', 'a' -]; -var defaultInnerOrder = ['i', 'c', 'b', 'a']; - - -module.exports = function (session, opts) { - opts = opts || {}; - // ensure certain properties exist - if (session.version == null) { - session.version = 0; // 'v=0' must be there (only defined version atm) - } - if (session.name == null) { - session.name = ' '; // 's= ' must be there if no meaningful name set - } - session.media.forEach(function (mLine) { - if (mLine.payloads == null) { - mLine.payloads = ''; - } - }); - - var outerOrder = opts.outerOrder || defaultOuterOrder; - var innerOrder = opts.innerOrder || defaultInnerOrder; - var sdp = []; - - // loop through outerOrder for matching properties on session - outerOrder.forEach(function (type) { - grammar[type].forEach(function (obj) { - if (obj.name in session && session[obj.name] != null) { - sdp.push(makeLine(type, obj, session)); - } - else if (obj.push in session && session[obj.push] != null) { - session[obj.push].forEach(function (el) { - sdp.push(makeLine(type, obj, el)); - }); - } - }); - }); - - // then for each media line, follow the innerOrder - session.media.forEach(function (mLine) { - sdp.push(makeLine('m', grammar.m[0], mLine)); - - innerOrder.forEach(function (type) { - grammar[type].forEach(function (obj) { - if (obj.name in mLine && mLine[obj.name] != null) { - sdp.push(makeLine(type, obj, mLine)); - } - else if (obj.push in mLine && mLine[obj.push] != null) { - mLine[obj.push].forEach(function (el) { - sdp.push(makeLine(type, obj, el)); - }); - } - }); - }); - }); - - return sdp.join('\r\n') + '\r\n'; -}; - -},{"./grammar":"/Users/ibc/src/mediasoup-client/node_modules/sdp-transform/lib/grammar.js"}],"/Users/ibc/src/mediasoup-demo-2/app/lib/Logger.js":[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); - -var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); - -var _createClass2 = require('babel-runtime/helpers/createClass'); - -var _createClass3 = _interopRequireDefault(_createClass2); - -var _debug = require('debug'); - -var _debug2 = _interopRequireDefault(_debug); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -var APP_NAME = 'mediasoup-demo'; - -var Logger = function () { - function Logger(prefix) { - (0, _classCallCheck3.default)(this, Logger); - - if (prefix) { - this._debug = (0, _debug2.default)(APP_NAME + ':' + prefix); - this._warn = (0, _debug2.default)(APP_NAME + ':WARN:' + prefix); - this._error = (0, _debug2.default)(APP_NAME + ':ERROR:' + prefix); - } else { - this._debug = (0, _debug2.default)(APP_NAME); - this._warn = (0, _debug2.default)(APP_NAME + ':WARN'); - this._error = (0, _debug2.default)(APP_NAME + ':ERROR'); - } - - /* eslint-disable no-console */ - this._debug.log = console.info.bind(console); - this._warn.log = console.warn.bind(console); - this._error.log = console.error.bind(console); - /* eslint-enable no-console */ - } - - (0, _createClass3.default)(Logger, [{ - key: 'debug', - get: function get() { - return this._debug; - } - }, { - key: 'warn', - get: function get() { - return this._warn; - } - }, { - key: 'error', - get: function get() { - return this._error; - } - }]); - return Logger; -}(); - -exports.default = Logger; - -},{"babel-runtime/helpers/classCallCheck":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/babel-runtime/helpers/classCallCheck.js","babel-runtime/helpers/createClass":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/babel-runtime/helpers/createClass.js","debug":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/debug/src/browser.js"}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/babel-runtime/core-js/get-iterator.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/core-js/get-iterator.js"][0].apply(exports,arguments) -},{"core-js/library/fn/get-iterator":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/fn/get-iterator.js"}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/babel-runtime/core-js/object/define-property.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/core-js/object/define-property.js"][0].apply(exports,arguments) -},{"core-js/library/fn/object/define-property":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/fn/object/define-property.js"}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/babel-runtime/core-js/promise.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/core-js/promise.js"][0].apply(exports,arguments) -},{"core-js/library/fn/promise":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/fn/promise.js"}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/babel-runtime/helpers/classCallCheck.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/helpers/classCallCheck.js"][0].apply(exports,arguments) -},{}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/babel-runtime/helpers/createClass.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/babel-runtime/helpers/createClass.js"][0].apply(exports,arguments) -},{"../core-js/object/define-property":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/babel-runtime/core-js/object/define-property.js"}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/fn/get-iterator.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/core-js/library/fn/get-iterator.js"][0].apply(exports,arguments) -},{"../modules/core.get-iterator":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/core.get-iterator.js","../modules/es6.string.iterator":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/es6.string.iterator.js","../modules/web.dom.iterable":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/web.dom.iterable.js"}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/fn/object/define-property.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/core-js/library/fn/object/define-property.js"][0].apply(exports,arguments) -},{"../../modules/_core":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_core.js","../../modules/es6.object.define-property":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/es6.object.define-property.js"}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/fn/promise.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/core-js/library/fn/promise.js"][0].apply(exports,arguments) -},{"../modules/_core":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_core.js","../modules/es6.object.to-string":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/es6.object.to-string.js","../modules/es6.promise":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/es6.promise.js","../modules/es6.string.iterator":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/es6.string.iterator.js","../modules/web.dom.iterable":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/web.dom.iterable.js"}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_a-function.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_a-function.js"][0].apply(exports,arguments) -},{}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_add-to-unscopables.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_add-to-unscopables.js"][0].apply(exports,arguments) -},{}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_an-instance.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_an-instance.js"][0].apply(exports,arguments) -},{}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_an-object.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_an-object.js"][0].apply(exports,arguments) -},{"./_is-object":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_is-object.js"}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_array-includes.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_array-includes.js"][0].apply(exports,arguments) -},{"./_to-index":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_to-index.js","./_to-iobject":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_to-iobject.js","./_to-length":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_to-length.js"}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_classof.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_classof.js"][0].apply(exports,arguments) -},{"./_cof":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_cof.js","./_wks":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_wks.js"}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_cof.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_cof.js"][0].apply(exports,arguments) -},{}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_core.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_core.js"][0].apply(exports,arguments) -},{}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_ctx.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_ctx.js"][0].apply(exports,arguments) -},{"./_a-function":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_a-function.js"}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_defined.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_defined.js"][0].apply(exports,arguments) -},{}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_descriptors.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_descriptors.js"][0].apply(exports,arguments) -},{"./_fails":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_fails.js"}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_dom-create.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_dom-create.js"][0].apply(exports,arguments) -},{"./_global":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_global.js","./_is-object":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_is-object.js"}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_enum-bug-keys.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_enum-bug-keys.js"][0].apply(exports,arguments) -},{}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_export.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_export.js"][0].apply(exports,arguments) -},{"./_core":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_core.js","./_ctx":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_ctx.js","./_global":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_global.js","./_hide":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_hide.js"}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_fails.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_fails.js"][0].apply(exports,arguments) -},{}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_for-of.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_for-of.js"][0].apply(exports,arguments) -},{"./_an-object":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_an-object.js","./_ctx":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_ctx.js","./_is-array-iter":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_is-array-iter.js","./_iter-call":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_iter-call.js","./_to-length":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_to-length.js","./core.get-iterator-method":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/core.get-iterator-method.js"}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_global.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_global.js"][0].apply(exports,arguments) -},{}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_has.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_has.js"][0].apply(exports,arguments) -},{}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_hide.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_hide.js"][0].apply(exports,arguments) -},{"./_descriptors":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_descriptors.js","./_object-dp":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_object-dp.js","./_property-desc":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_property-desc.js"}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_html.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_html.js"][0].apply(exports,arguments) -},{"./_global":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_global.js"}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_ie8-dom-define.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_ie8-dom-define.js"][0].apply(exports,arguments) -},{"./_descriptors":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_descriptors.js","./_dom-create":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_dom-create.js","./_fails":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_fails.js"}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_invoke.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_invoke.js"][0].apply(exports,arguments) -},{}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_iobject.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_iobject.js"][0].apply(exports,arguments) -},{"./_cof":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_cof.js"}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_is-array-iter.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_is-array-iter.js"][0].apply(exports,arguments) -},{"./_iterators":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_iterators.js","./_wks":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_wks.js"}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_is-object.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_is-object.js"][0].apply(exports,arguments) -},{}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_iter-call.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_iter-call.js"][0].apply(exports,arguments) -},{"./_an-object":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_an-object.js"}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_iter-create.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_iter-create.js"][0].apply(exports,arguments) -},{"./_hide":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_hide.js","./_object-create":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_object-create.js","./_property-desc":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_property-desc.js","./_set-to-string-tag":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_set-to-string-tag.js","./_wks":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_wks.js"}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_iter-define.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_iter-define.js"][0].apply(exports,arguments) -},{"./_export":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_export.js","./_has":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_has.js","./_hide":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_hide.js","./_iter-create":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_iter-create.js","./_iterators":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_iterators.js","./_library":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_library.js","./_object-gpo":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_object-gpo.js","./_redefine":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_redefine.js","./_set-to-string-tag":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_set-to-string-tag.js","./_wks":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_wks.js"}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_iter-detect.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_iter-detect.js"][0].apply(exports,arguments) -},{"./_wks":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_wks.js"}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_iter-step.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_iter-step.js"][0].apply(exports,arguments) -},{}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_iterators.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_iterators.js"][0].apply(exports,arguments) -},{}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_library.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_library.js"][0].apply(exports,arguments) -},{}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_microtask.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_microtask.js"][0].apply(exports,arguments) -},{"./_cof":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_cof.js","./_global":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_global.js","./_task":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_task.js"}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_object-create.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_object-create.js"][0].apply(exports,arguments) -},{"./_an-object":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_an-object.js","./_dom-create":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_dom-create.js","./_enum-bug-keys":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_enum-bug-keys.js","./_html":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_html.js","./_object-dps":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_object-dps.js","./_shared-key":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_shared-key.js"}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_object-dp.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_object-dp.js"][0].apply(exports,arguments) -},{"./_an-object":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_an-object.js","./_descriptors":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_descriptors.js","./_ie8-dom-define":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_ie8-dom-define.js","./_to-primitive":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_to-primitive.js"}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_object-dps.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_object-dps.js"][0].apply(exports,arguments) -},{"./_an-object":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_an-object.js","./_descriptors":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_descriptors.js","./_object-dp":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_object-dp.js","./_object-keys":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_object-keys.js"}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_object-gpo.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_object-gpo.js"][0].apply(exports,arguments) -},{"./_has":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_has.js","./_shared-key":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_shared-key.js","./_to-object":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_to-object.js"}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_object-keys-internal.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_object-keys-internal.js"][0].apply(exports,arguments) -},{"./_array-includes":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_array-includes.js","./_has":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_has.js","./_shared-key":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_shared-key.js","./_to-iobject":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_to-iobject.js"}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_object-keys.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_object-keys.js"][0].apply(exports,arguments) -},{"./_enum-bug-keys":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_enum-bug-keys.js","./_object-keys-internal":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_object-keys-internal.js"}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_property-desc.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_property-desc.js"][0].apply(exports,arguments) -},{}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_redefine-all.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_redefine-all.js"][0].apply(exports,arguments) -},{"./_hide":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_hide.js"}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_redefine.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_redefine.js"][0].apply(exports,arguments) -},{"./_hide":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_hide.js"}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_set-species.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_set-species.js"][0].apply(exports,arguments) -},{"./_core":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_core.js","./_descriptors":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_descriptors.js","./_global":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_global.js","./_object-dp":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_object-dp.js","./_wks":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_wks.js"}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_set-to-string-tag.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_set-to-string-tag.js"][0].apply(exports,arguments) -},{"./_has":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_has.js","./_object-dp":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_object-dp.js","./_wks":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_wks.js"}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_shared-key.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_shared-key.js"][0].apply(exports,arguments) -},{"./_shared":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_shared.js","./_uid":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_uid.js"}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_shared.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_shared.js"][0].apply(exports,arguments) -},{"./_global":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_global.js"}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_species-constructor.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_species-constructor.js"][0].apply(exports,arguments) -},{"./_a-function":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_a-function.js","./_an-object":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_an-object.js","./_wks":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_wks.js"}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_string-at.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_string-at.js"][0].apply(exports,arguments) -},{"./_defined":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_defined.js","./_to-integer":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_to-integer.js"}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_task.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_task.js"][0].apply(exports,arguments) -},{"./_cof":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_cof.js","./_ctx":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_ctx.js","./_dom-create":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_dom-create.js","./_global":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_global.js","./_html":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_html.js","./_invoke":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_invoke.js"}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_to-index.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_to-index.js"][0].apply(exports,arguments) -},{"./_to-integer":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_to-integer.js"}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_to-integer.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_to-integer.js"][0].apply(exports,arguments) -},{}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_to-iobject.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_to-iobject.js"][0].apply(exports,arguments) -},{"./_defined":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_defined.js","./_iobject":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_iobject.js"}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_to-length.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_to-length.js"][0].apply(exports,arguments) -},{"./_to-integer":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_to-integer.js"}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_to-object.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_to-object.js"][0].apply(exports,arguments) -},{"./_defined":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_defined.js"}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_to-primitive.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_to-primitive.js"][0].apply(exports,arguments) -},{"./_is-object":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_is-object.js"}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_uid.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_uid.js"][0].apply(exports,arguments) -},{}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_wks.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/_wks.js"][0].apply(exports,arguments) -},{"./_global":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_global.js","./_shared":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_shared.js","./_uid":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_uid.js"}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/core.get-iterator-method.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/core.get-iterator-method.js"][0].apply(exports,arguments) -},{"./_classof":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_classof.js","./_core":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_core.js","./_iterators":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_iterators.js","./_wks":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_wks.js"}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/core.get-iterator.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/core.get-iterator.js"][0].apply(exports,arguments) -},{"./_an-object":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_an-object.js","./_core":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_core.js","./core.get-iterator-method":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/core.get-iterator-method.js"}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/es6.array.iterator.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/es6.array.iterator.js"][0].apply(exports,arguments) -},{"./_add-to-unscopables":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_add-to-unscopables.js","./_iter-define":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_iter-define.js","./_iter-step":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_iter-step.js","./_iterators":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_iterators.js","./_to-iobject":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_to-iobject.js"}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/es6.object.define-property.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/es6.object.define-property.js"][0].apply(exports,arguments) -},{"./_descriptors":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_descriptors.js","./_export":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_export.js","./_object-dp":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_object-dp.js"}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/es6.object.to-string.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/es6.object.to-string.js"][0].apply(exports,arguments) -},{}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/es6.promise.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/es6.promise.js"][0].apply(exports,arguments) -},{"./_a-function":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_a-function.js","./_an-instance":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_an-instance.js","./_classof":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_classof.js","./_core":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_core.js","./_ctx":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_ctx.js","./_export":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_export.js","./_for-of":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_for-of.js","./_global":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_global.js","./_is-object":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_is-object.js","./_iter-detect":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_iter-detect.js","./_library":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_library.js","./_microtask":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_microtask.js","./_redefine-all":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_redefine-all.js","./_set-species":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_set-species.js","./_set-to-string-tag":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_set-to-string-tag.js","./_species-constructor":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_species-constructor.js","./_task":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_task.js","./_wks":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_wks.js"}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/es6.string.iterator.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/es6.string.iterator.js"][0].apply(exports,arguments) -},{"./_iter-define":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_iter-define.js","./_string-at":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_string-at.js"}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/web.dom.iterable.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/core-js/library/modules/web.dom.iterable.js"][0].apply(exports,arguments) -},{"./_global":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_global.js","./_hide":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_hide.js","./_iterators":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_iterators.js","./_wks":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/_wks.js","./es6.array.iterator":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/core-js/library/modules/es6.array.iterator.js"}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/debug/node_modules/ms/index.js":[function(require,module,exports){ -arguments[4]["/Users/ibc/src/mediasoup-client/node_modules/ms/index.js"][0].apply(exports,arguments) -},{}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/debug/src/browser.js":[function(require,module,exports){ -(function (process){ -/** - * This is the web browser implementation of `debug()`. - * - * Expose `debug()` as the module. - */ - -exports = module.exports = require('./debug'); -exports.log = log; -exports.formatArgs = formatArgs; -exports.save = save; -exports.load = load; -exports.useColors = useColors; -exports.storage = 'undefined' != typeof chrome - && 'undefined' != typeof chrome.storage - ? chrome.storage.local - : localstorage(); - -/** - * Colors. - */ - -exports.colors = [ - '#0000CC', '#0000FF', '#0033CC', '#0033FF', '#0066CC', '#0066FF', '#0099CC', - '#0099FF', '#00CC00', '#00CC33', '#00CC66', '#00CC99', '#00CCCC', '#00CCFF', - '#3300CC', '#3300FF', '#3333CC', '#3333FF', '#3366CC', '#3366FF', '#3399CC', - '#3399FF', '#33CC00', '#33CC33', '#33CC66', '#33CC99', '#33CCCC', '#33CCFF', - '#6600CC', '#6600FF', '#6633CC', '#6633FF', '#66CC00', '#66CC33', '#9900CC', - '#9900FF', '#9933CC', '#9933FF', '#99CC00', '#99CC33', '#CC0000', '#CC0033', - '#CC0066', '#CC0099', '#CC00CC', '#CC00FF', '#CC3300', '#CC3333', '#CC3366', - '#CC3399', '#CC33CC', '#CC33FF', '#CC6600', '#CC6633', '#CC9900', '#CC9933', - '#CCCC00', '#CCCC33', '#FF0000', '#FF0033', '#FF0066', '#FF0099', '#FF00CC', - '#FF00FF', '#FF3300', '#FF3333', '#FF3366', '#FF3399', '#FF33CC', '#FF33FF', - '#FF6600', '#FF6633', '#FF9900', '#FF9933', '#FFCC00', '#FFCC33' -]; - -/** - * Currently only WebKit-based Web Inspectors, Firefox >= v31, - * and the Firebug extension (any Firefox version) are known - * to support "%c" CSS customizations. - * - * TODO: add a `localStorage` variable to explicitly enable/disable colors - */ - -function useColors() { - // NB: In an Electron preload script, document will be defined but not fully - // initialized. Since we know we're in Chrome, we'll just detect this case - // explicitly - if (typeof window !== 'undefined' && window.process && window.process.type === 'renderer') { - return true; - } - - // is webkit? http://stackoverflow.com/a/16459606/376773 - // document is undefined in react-native: https://github.com/facebook/react-native/pull/1632 - return (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) || - // is firebug? http://stackoverflow.com/a/398120/376773 - (typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) || - // is firefox >= v31? - // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages - (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31) || - // double check webkit in userAgent just in case we are in a worker - (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/)); -} - -/** - * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default. - */ - -exports.formatters.j = function(v) { - try { - return JSON.stringify(v); - } catch (err) { - return '[UnexpectedJSONParseError]: ' + err.message; - } -}; - - -/** - * Colorize log arguments if enabled. - * - * @api public - */ - -function formatArgs(args) { - var useColors = this.useColors; - - args[0] = (useColors ? '%c' : '') - + this.namespace - + (useColors ? ' %c' : ' ') - + args[0] - + (useColors ? '%c ' : ' ') - + '+' + exports.humanize(this.diff); - - if (!useColors) return; - - var c = 'color: ' + this.color; - args.splice(1, 0, c, 'color: inherit') - - // the final "%c" is somewhat tricky, because there could be other - // arguments passed either before or after the %c, so we need to - // figure out the correct index to insert the CSS into - var index = 0; - var lastC = 0; - args[0].replace(/%[a-zA-Z%]/g, function(match) { - if ('%%' === match) return; - index++; - if ('%c' === match) { - // we only are interested in the *last* %c - // (the user may have provided their own) - lastC = index; - } - }); - - args.splice(lastC, 0, c); -} - -/** - * Invokes `console.log()` when available. - * No-op when `console.log` is not a "function". - * - * @api public - */ - -function log() { - // this hackery is required for IE8/9, where - // the `console.log` function doesn't have 'apply' - return 'object' === typeof console - && console.log - && Function.prototype.apply.call(console.log, console, arguments); -} - -/** - * Save `namespaces`. - * - * @param {String} namespaces - * @api private - */ - -function save(namespaces) { - try { - if (null == namespaces) { - exports.storage.removeItem('debug'); - } else { - exports.storage.debug = namespaces; - } - } catch(e) {} -} - -/** - * Load `namespaces`. - * - * @return {String} returns the previously persisted debug modes - * @api private - */ - -function load() { - var r; - try { - r = exports.storage.debug; - } catch(e) {} - - // If debug isn't set in LS, and we're in Electron, try to load $DEBUG - if (!r && typeof process !== 'undefined' && 'env' in process) { - r = process.env.DEBUG; - } - - return r; -} - -/** - * Enable namespaces listed in `localStorage.debug` initially. - */ - -exports.enable(load()); - -/** - * Localstorage attempts to return the localstorage. - * - * This is necessary because safari throws - * when a user disables cookies/localstorage - * and you attempt to access it. - * - * @return {LocalStorage} - * @api private - */ - -function localstorage() { - try { - return window.localStorage; - } catch (e) {} -} - -}).call(this,require('_process')) - -},{"./debug":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/debug/src/debug.js","_process":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/process/browser.js"}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/debug/src/debug.js":[function(require,module,exports){ - -/** - * This is the common logic for both the Node.js and web browser - * implementations of `debug()`. - * - * Expose `debug()` as the module. - */ - -exports = module.exports = createDebug.debug = createDebug['default'] = createDebug; -exports.coerce = coerce; -exports.disable = disable; -exports.enable = enable; -exports.enabled = enabled; -exports.humanize = require('ms'); - -/** - * Active `debug` instances. - */ -exports.instances = []; - -/** - * The currently active debug mode names, and names to skip. - */ - -exports.names = []; -exports.skips = []; - -/** - * Map of special "%n" handling functions, for the debug "format" argument. - * - * Valid key names are a single, lower or upper-case letter, i.e. "n" and "N". - */ - -exports.formatters = {}; - -/** - * Select a color. - * @param {String} namespace - * @return {Number} - * @api private - */ - -function selectColor(namespace) { - var hash = 0, i; - - for (i in namespace) { - hash = ((hash << 5) - hash) + namespace.charCodeAt(i); - hash |= 0; // Convert to 32bit integer - } - - return exports.colors[Math.abs(hash) % exports.colors.length]; -} - -/** - * Create a debugger with the given `namespace`. - * - * @param {String} namespace - * @return {Function} - * @api public - */ - -function createDebug(namespace) { - - var prevTime; - - function debug() { - // disabled? - if (!debug.enabled) return; - - var self = debug; - - // set `diff` timestamp - var curr = +new Date(); - var ms = curr - (prevTime || curr); - self.diff = ms; - self.prev = prevTime; - self.curr = curr; - prevTime = curr; - - // turn the `arguments` into a proper Array - var args = new Array(arguments.length); - for (var i = 0; i < args.length; i++) { - args[i] = arguments[i]; - } - - args[0] = exports.coerce(args[0]); - - if ('string' !== typeof args[0]) { - // anything else let's inspect with %O - args.unshift('%O'); - } - - // apply any `formatters` transformations - var index = 0; - args[0] = args[0].replace(/%([a-zA-Z%])/g, function(match, format) { - // if we encounter an escaped % then don't increase the array index - if (match === '%%') return match; - index++; - var formatter = exports.formatters[format]; - if ('function' === typeof formatter) { - var val = args[index]; - match = formatter.call(self, val); - - // now we need to remove `args[index]` since it's inlined in the `format` - args.splice(index, 1); - index--; - } - return match; - }); - - // apply env-specific formatting (colors, etc.) - exports.formatArgs.call(self, args); - - var logFn = debug.log || exports.log || console.log.bind(console); - logFn.apply(self, args); - } - - debug.namespace = namespace; - debug.enabled = exports.enabled(namespace); - debug.useColors = exports.useColors(); - debug.color = selectColor(namespace); - debug.destroy = destroy; - - // env-specific initialization logic for debug instances - if ('function' === typeof exports.init) { - exports.init(debug); - } - - exports.instances.push(debug); - - return debug; -} - -function destroy () { - var index = exports.instances.indexOf(this); - if (index !== -1) { - exports.instances.splice(index, 1); - return true; - } else { - return false; - } -} - -/** - * Enables a debug mode by namespaces. This can include modes - * separated by a colon and wildcards. - * - * @param {String} namespaces - * @api public - */ - -function enable(namespaces) { - exports.save(namespaces); - - exports.names = []; - exports.skips = []; - - var i; - var split = (typeof namespaces === 'string' ? namespaces : '').split(/[\s,]+/); - var len = split.length; - - for (i = 0; i < len; i++) { - if (!split[i]) continue; // ignore empty strings - namespaces = split[i].replace(/\*/g, '.*?'); - if (namespaces[0] === '-') { - exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$')); - } else { - exports.names.push(new RegExp('^' + namespaces + '$')); - } - } - - for (i = 0; i < exports.instances.length; i++) { - var instance = exports.instances[i]; - instance.enabled = exports.enabled(instance.namespace); - } -} - -/** - * Disable debug output. - * - * @api public - */ - -function disable() { - exports.enable(''); -} - -/** - * Returns true if the given mode name is enabled, false otherwise. - * - * @param {String} name - * @return {Boolean} - * @api public - */ - -function enabled(name) { - if (name[name.length - 1] === '*') { - return true; - } - var i, len; - for (i = 0, len = exports.skips.length; i < len; i++) { - if (exports.skips[i].test(name)) { - return false; - } - } - for (i = 0, len = exports.names.length; i < len; i++) { - if (exports.names[i].test(name)) { - return true; - } - } - return false; -} - -/** - * Coerce `val`. - * - * @param {Mixed} val - * @return {Mixed} - * @api private - */ - -function coerce(val) { - if (val instanceof Error) return val.stack || val.message; - return val; -} - -},{"ms":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/debug/node_modules/ms/index.js"}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/domready/ready.js":[function(require,module,exports){ -/*! - * domready (c) Dustin Diaz 2014 - License MIT - */ -!function (name, definition) { - - if (typeof module != 'undefined') module.exports = definition() - else if (typeof define == 'function' && typeof define.amd == 'object') define(definition) - else this[name] = definition() - -}('domready', function () { - - var fns = [], listener - , doc = document - , hack = doc.documentElement.doScroll - , domContentLoaded = 'DOMContentLoaded' - , loaded = (hack ? /^loaded|^c/ : /^loaded|^i|^c/).test(doc.readyState) - - - if (!loaded) - doc.addEventListener(domContentLoaded, listener = function () { - doc.removeEventListener(domContentLoaded, listener) - loaded = 1 - while (listener = fns.shift()) listener() - }) - - return function (fn) { - loaded ? setTimeout(fn, 0) : fns.push(fn) - } - -}); - -},{}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/events/events.js":[function(require,module,exports){ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -function EventEmitter() { - this._events = this._events || {}; - this._maxListeners = this._maxListeners || undefined; -} -module.exports = EventEmitter; - -// Backwards-compat with node 0.10.x -EventEmitter.EventEmitter = EventEmitter; - -EventEmitter.prototype._events = undefined; -EventEmitter.prototype._maxListeners = undefined; - -// By default EventEmitters will print a warning if more than 10 listeners are -// added to it. This is a useful default which helps finding memory leaks. -EventEmitter.defaultMaxListeners = 10; - -// Obviously not all Emitters should be limited to 10. This function allows -// that to be increased. Set to zero for unlimited. -EventEmitter.prototype.setMaxListeners = function(n) { - if (!isNumber(n) || n < 0 || isNaN(n)) - throw TypeError('n must be a positive number'); - this._maxListeners = n; - return this; -}; - -EventEmitter.prototype.emit = function(type) { - var er, handler, len, args, i, listeners; - - if (!this._events) - this._events = {}; - - // If there is no 'error' event listener then throw. - if (type === 'error') { - if (!this._events.error || - (isObject(this._events.error) && !this._events.error.length)) { - er = arguments[1]; - if (er instanceof Error) { - throw er; // Unhandled 'error' event - } else { - // At least give some kind of context to the user - var err = new Error('Uncaught, unspecified "error" event. (' + er + ')'); - err.context = er; - throw err; - } - } - } - - handler = this._events[type]; - - if (isUndefined(handler)) - return false; - - if (isFunction(handler)) { - switch (arguments.length) { - // fast cases - case 1: - handler.call(this); - break; - case 2: - handler.call(this, arguments[1]); - break; - case 3: - handler.call(this, arguments[1], arguments[2]); - break; - // slower - default: - args = Array.prototype.slice.call(arguments, 1); - handler.apply(this, args); - } - } else if (isObject(handler)) { - args = Array.prototype.slice.call(arguments, 1); - listeners = handler.slice(); - len = listeners.length; - for (i = 0; i < len; i++) - listeners[i].apply(this, args); - } - - return true; -}; - -EventEmitter.prototype.addListener = function(type, listener) { - var m; - - if (!isFunction(listener)) - throw TypeError('listener must be a function'); - - if (!this._events) - this._events = {}; - - // To avoid recursion in the case that type === "newListener"! Before - // adding it to the listeners, first emit "newListener". - if (this._events.newListener) - this.emit('newListener', type, - isFunction(listener.listener) ? - listener.listener : listener); - - if (!this._events[type]) - // Optimize the case of one listener. Don't need the extra array object. - this._events[type] = listener; - else if (isObject(this._events[type])) - // If we've already got an array, just append. - this._events[type].push(listener); - else - // Adding the second element, need to change to array. - this._events[type] = [this._events[type], listener]; - - // Check for listener leak - if (isObject(this._events[type]) && !this._events[type].warned) { - if (!isUndefined(this._maxListeners)) { - m = this._maxListeners; - } else { - m = EventEmitter.defaultMaxListeners; - } - - if (m && m > 0 && this._events[type].length > m) { - this._events[type].warned = true; - console.error('(node) warning: possible EventEmitter memory ' + - 'leak detected. %d listeners added. ' + - 'Use emitter.setMaxListeners() to increase limit.', - this._events[type].length); - if (typeof console.trace === 'function') { - // not supported in IE 10 - console.trace(); - } - } - } - - return this; -}; - -EventEmitter.prototype.on = EventEmitter.prototype.addListener; - -EventEmitter.prototype.once = function(type, listener) { - if (!isFunction(listener)) - throw TypeError('listener must be a function'); - - var fired = false; - - function g() { - this.removeListener(type, g); - - if (!fired) { - fired = true; - listener.apply(this, arguments); - } - } - - g.listener = listener; - this.on(type, g); - - return this; -}; - -// emits a 'removeListener' event iff the listener was removed -EventEmitter.prototype.removeListener = function(type, listener) { - var list, position, length, i; - - if (!isFunction(listener)) - throw TypeError('listener must be a function'); - - if (!this._events || !this._events[type]) - return this; - - list = this._events[type]; - length = list.length; - position = -1; - - if (list === listener || - (isFunction(list.listener) && list.listener === listener)) { - delete this._events[type]; - if (this._events.removeListener) - this.emit('removeListener', type, listener); - - } else if (isObject(list)) { - for (i = length; i-- > 0;) { - if (list[i] === listener || - (list[i].listener && list[i].listener === listener)) { - position = i; - break; - } - } - - if (position < 0) - return this; - - if (list.length === 1) { - list.length = 0; - delete this._events[type]; - } else { - list.splice(position, 1); - } - - if (this._events.removeListener) - this.emit('removeListener', type, listener); - } - - return this; -}; - -EventEmitter.prototype.removeAllListeners = function(type) { - var key, listeners; - - if (!this._events) - return this; - - // not listening for removeListener, no need to emit - if (!this._events.removeListener) { - if (arguments.length === 0) - this._events = {}; - else if (this._events[type]) - delete this._events[type]; - return this; - } - - // emit removeListener for all listeners on all events - if (arguments.length === 0) { - for (key in this._events) { - if (key === 'removeListener') continue; - this.removeAllListeners(key); - } - this.removeAllListeners('removeListener'); - this._events = {}; - return this; - } - - listeners = this._events[type]; - - if (isFunction(listeners)) { - this.removeListener(type, listeners); - } else if (listeners) { - // LIFO order - while (listeners.length) - this.removeListener(type, listeners[listeners.length - 1]); - } - delete this._events[type]; - - return this; -}; - -EventEmitter.prototype.listeners = function(type) { - var ret; - if (!this._events || !this._events[type]) - ret = []; - else if (isFunction(this._events[type])) - ret = [this._events[type]]; - else - ret = this._events[type].slice(); - return ret; -}; - -EventEmitter.prototype.listenerCount = function(type) { - if (this._events) { - var evlistener = this._events[type]; - - if (isFunction(evlistener)) - return 1; - else if (evlistener) - return evlistener.length; - } - return 0; -}; - -EventEmitter.listenerCount = function(emitter, type) { - return emitter.listenerCount(type); -}; - -function isFunction(arg) { - return typeof arg === 'function'; -} - -function isNumber(arg) { - return typeof arg === 'number'; -} - -function isObject(arg) { - return typeof arg === 'object' && arg !== null; -} - -function isUndefined(arg) { - return arg === void 0; -} - -},{}],"/Users/ibc/src/mediasoup-demo-2/app/node_modules/process/browser.js":[function(require,module,exports){ -// shim for using process in browser -var process = module.exports = {}; - -// cached from whatever global is present so that test runners that stub it -// don't break things. But we need to wrap it in a try catch in case it is -// wrapped in strict mode code which doesn't define any globals. It's inside a -// function because try/catches deoptimize in certain engines. - -var cachedSetTimeout; -var cachedClearTimeout; - -function defaultSetTimout() { - throw new Error('setTimeout has not been defined'); -} -function defaultClearTimeout () { - throw new Error('clearTimeout has not been defined'); -} -(function () { - try { - if (typeof setTimeout === 'function') { - cachedSetTimeout = setTimeout; - } else { - cachedSetTimeout = defaultSetTimout; - } - } catch (e) { - cachedSetTimeout = defaultSetTimout; - } - try { - if (typeof clearTimeout === 'function') { - cachedClearTimeout = clearTimeout; - } else { - cachedClearTimeout = defaultClearTimeout; - } - } catch (e) { - cachedClearTimeout = defaultClearTimeout; - } -} ()) -function runTimeout(fun) { - if (cachedSetTimeout === setTimeout) { - //normal enviroments in sane situations - return setTimeout(fun, 0); - } - // if setTimeout wasn't available but was latter defined - if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) { - cachedSetTimeout = setTimeout; - return setTimeout(fun, 0); - } - try { - // when when somebody has screwed with setTimeout but no I.E. maddness - return cachedSetTimeout(fun, 0); - } catch(e){ - try { - // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally - return cachedSetTimeout.call(null, fun, 0); - } catch(e){ - // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error - return cachedSetTimeout.call(this, fun, 0); - } - } - - -} -function runClearTimeout(marker) { - if (cachedClearTimeout === clearTimeout) { - //normal enviroments in sane situations - return clearTimeout(marker); - } - // if clearTimeout wasn't available but was latter defined - if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) { - cachedClearTimeout = clearTimeout; - return clearTimeout(marker); - } - try { - // when when somebody has screwed with setTimeout but no I.E. maddness - return cachedClearTimeout(marker); - } catch (e){ - try { - // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally - return cachedClearTimeout.call(null, marker); - } catch (e){ - // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error. - // Some versions of I.E. have different rules for clearTimeout vs setTimeout - return cachedClearTimeout.call(this, marker); - } - } - - - -} -var queue = []; -var draining = false; -var currentQueue; -var queueIndex = -1; - -function cleanUpNextTick() { - if (!draining || !currentQueue) { - return; - } - draining = false; - if (currentQueue.length) { - queue = currentQueue.concat(queue); - } else { - queueIndex = -1; - } - if (queue.length) { - drainQueue(); - } -} - -function drainQueue() { - if (draining) { - return; - } - var timeout = runTimeout(cleanUpNextTick); - draining = true; - - var len = queue.length; - while(len) { - currentQueue = queue; - queue = []; - while (++queueIndex < len) { - if (currentQueue) { - currentQueue[queueIndex].run(); - } - } - queueIndex = -1; - len = queue.length; - } - currentQueue = null; - draining = false; - runClearTimeout(timeout); -} - -process.nextTick = function (fun) { - var args = new Array(arguments.length - 1); - if (arguments.length > 1) { - for (var i = 1; i < arguments.length; i++) { - args[i - 1] = arguments[i]; - } - } - queue.push(new Item(fun, args)); - if (queue.length === 1 && !draining) { - runTimeout(drainQueue); - } -}; - -// v8 likes predictible objects -function Item(fun, array) { - this.fun = fun; - this.array = array; -} -Item.prototype.run = function () { - this.fun.apply(null, this.array); -}; -process.title = 'browser'; -process.browser = true; -process.env = {}; -process.argv = []; -process.version = ''; // empty string to avoid regexp issues -process.versions = {}; - -function noop() {} - -process.on = noop; -process.addListener = noop; -process.once = noop; -process.off = noop; -process.removeListener = noop; -process.removeAllListeners = noop; -process.emit = noop; -process.prependListener = noop; -process.prependOnceListener = noop; - -process.listeners = function (name) { return [] } - -process.binding = function (name) { - throw new Error('process.binding is not supported'); -}; - -process.cwd = function () { return '/' }; -process.chdir = function (dir) { - throw new Error('process.chdir is not supported'); -}; -process.umask = function() { return 0; }; - -},{}],"/Users/ibc/src/mediasoup-demo-2/app/test/DATA.js":[function(require,module,exports){ -'use strict'; - -/* eslint-disable key-spacing */ - -exports.ROOM_OPTIONS = { - requestTimeout: 10000, - transportOptions: { - tcp: false - }, - __turnServers: [{ - urls: ['turn:worker2.versatica.com:3478?transport=udp'], - username: 'testuser1', - credential: 'testpasswd1' - }], - hidden: false -}; - -exports.ROOM_RTP_CAPABILITIES = { - codecs: [{ - name: 'PCMA', - mimeType: 'audio/PCMA', - kind: 'audio', - clockRate: 8000, - preferredPayloadType: 8, - rtcpFeedback: [], - parameters: {} - }, { - name: 'opus', - mimeType: 'audio/opus', - kind: 'audio', - clockRate: 48000, - channels: 2, - preferredPayloadType: 96, - rtcpFeedback: [], - parameters: {} - }, { - name: 'SILK', - mimeType: 'audio/SILK', - kind: 'audio', - clockRate: 16000, - preferredPayloadType: 97, - rtcpFeedback: [], - parameters: {} - }, { - name: 'VP9', - mimeType: 'video/VP9', - kind: 'video', - clockRate: 90000, - preferredPayloadType: 102, - rtcpFeedback: [{ - parameter: '', - type: 'nack' - }, { - parameter: 'pli', - type: 'nack' - }, { - parameter: '', - type: 'goog-remb' - }, { - parameter: 'bar', - type: 'foo' - }], - parameters: {} - }, { - name: 'rtx', - mimeType: 'video/rtx', - kind: 'video', - clockRate: 90000, - preferredPayloadType: 103, - rtcpFeedback: [], - parameters: { - apt: 102 - } - }, { - name: 'VP8', - mimeType: 'video/VP8', - kind: 'video', - clockRate: 90000, - preferredPayloadType: 100, - rtcpFeedback: [{ - parameter: '', - type: 'nack' - }, { - parameter: 'pli', - type: 'nack' - }, { - parameter: '', - type: 'goog-remb' - }, { - parameter: 'bar', - type: 'foo' - }], - parameters: {} - }, { - name: 'rtx', - mimeType: 'video/rtx', - kind: 'video', - clockRate: 90000, - preferredPayloadType: 101, - rtcpFeedback: [], - parameters: { - apt: 100 - } - }], - headerExtensions: [{ - kind: 'audio', - uri: 'urn:ietf:params:rtp-hdrext:ssrc-audio-level', - preferredId: 10 - }, { - kind: 'video', - uri: 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', - preferredId: 11 - }, { - kind: 'video', - uri: 'http://foo.bar', - preferredId: 12 - }], - fecMechanisms: [] -}; - -exports.QUERY_ROOM_RESPONSE = { - rtpCapabilities: exports.ROOM_RTP_CAPABILITIES -}; - -exports.JOIN_ROOM_RESPONSE = { - peers: [{ - name: 'alice', - appData: 'Alice iPad Pro', - consumers: [{ - id: 3333, - kind: 'audio', - paused: false, - appData: 'ALICE_MIC', - rtpParameters: { - muxId: null, - codecs: [{ - name: 'PCMA', - mimeType: 'audio/PCMA', - clockRate: 8000, - payloadType: 8, - rtcpFeedback: [], - parameters: {} - }], - headerExtensions: [{ - uri: 'urn:ietf:params:rtp-hdrext:ssrc-audio-level', - id: 1 - }], - encodings: [{ - ssrc: 33333333 - }], - rtcp: { - cname: 'ALICECNAME', - reducedSize: true, - mux: true - } - } - }] - }, { - name: 'bob', - appData: 'Bob HP Laptop', - consumers: [{ - id: 6666, - kind: 'audio', - paused: false, - appData: 'BOB_MIC', - rtpParameters: { - muxId: null, - codecs: [{ - name: 'opus', - mimeType: 'audio/opus', - clockRate: 48000, - channels: 2, - payloadType: 96, - rtcpFeedback: [], - parameters: {} - }], - headerExtensions: [{ - uri: 'urn:ietf:params:rtp-hdrext:ssrc-audio-level', - id: 1 - }], - encodings: [{ - ssrc: 66666666 - }], - rtcp: { - cname: 'BOBCNAME', - reducedSize: true, - mux: true - } - } - }] - }] -}; - -exports.CREATE_TRANSPORT_1_RESPONSE = { - iceParameters: { - usernameFragment: 'server-usernamefragment-12345678', - password: 'server-password-xxxxxxxx', - iceLite: true - }, - iceCandidates: [{ - foundation: 'F1', - priority: 1234, - ip: '1.2.3.4', - protocol: 'udp', - port: 9999, - type: 'host' - }], - dtlsParameters: { - fingerprints: [{ - algorithm: 'sha-256', - value: 'FF:FF:39:66:A4:E2:66:60:30:18:A7:59:B3:AF:A5:33:58:5E:7F:69:A4:62:A6:D4:EB:9F:B7:42:05:35:FF:FF' - }], - role: 'client' - } -}; - -exports.CREATE_TRANSPORT_2_RESPONSE = { - iceParameters: { - usernameFragment: 'server-usernamefragment-12345678', - password: 'server-password-xxxxxxxx', - iceLite: true - }, - iceCandidates: [{ - foundation: 'F1', - priority: 1234, - ip: '1.2.3.4', - protocol: 'udp', - port: 9999, - type: 'host' - }], - dtlsParameters: { - fingerprints: [{ - algorithm: 'sha-256', - value: 'FF:FF:39:66:A4:E2:66:60:30:18:A7:59:B3:AF:A5:33:58:5E:7F:69:A4:62:A6:D4:EB:9F:B7:42:05:35:FF:FF' - }], - role: 'auto' - } -}; - -exports.ALICE_WEBCAM_NEW_CONSUMER_NOTIFICATION = { - method: 'newConsumer', - notification: true, - id: 4444, - peerName: 'alice', - kind: 'video', - paused: true, - appData: 'ALICE_WEBCAM', - rtpParameters: { - muxId: null, - codecs: [{ - name: 'VP8', - mimeType: 'video/VP8', - clockRate: 90000, - payloadType: 100, - rtcpFeedback: [{ - parameter: '', - type: 'nack' - }, { - parameter: 'pli', - type: 'nack' - }, { - parameter: '', - type: 'goog-remb' - }, { - parameter: 'bar', - type: 'foo' - }], - parameters: {} - }, { - name: 'rtx', - mimeType: 'video/rtx', - clockRate: 90000, - payloadType: 101, - rtcpFeedback: [], - parameters: { - apt: 100 - } - }], - headerExtensions: [{ - kind: 'video', - uri: 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', - id: 11 - }, { - kind: 'video', - uri: 'http://foo.bar', - id: 12 - }], - encodings: [{ - ssrc: 444444441, - rtx: { - ssrc: 444444442 - } - }], - rtcp: { - cname: 'ALICECNAME', - reducedSize: true, - mux: true - } - } -}; - -},{}],"/Users/ibc/src/mediasoup-demo-2/app/test/index.jsx":[function(require,module,exports){ -'use strict'; - -var _getIterator2 = require('babel-runtime/core-js/get-iterator'); - -var _getIterator3 = _interopRequireDefault(_getIterator2); - -var _promise = require('babel-runtime/core-js/promise'); - -var _promise2 = _interopRequireDefault(_promise); - -var _mediasoupClient = require('mediasoup-client'); - -var mediasoupClient = _interopRequireWildcard(_mediasoupClient); - -var _domready = require('domready'); - -var _domready2 = _interopRequireDefault(_domready); - -var _Logger = require('../lib/Logger'); - -var _Logger2 = _interopRequireDefault(_Logger); - -function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -var DATA = require('./DATA'); - -window.mediasoupClient = mediasoupClient; - -var logger = new _Logger2.default(); - -var SEND = true; -var SEND_AUDIO = true; -var SEND_VIDEO = false; -var RECV = true; - -(0, _domready2.default)(function () { - logger.debug('DOM ready'); - - run(); -}); - -function run() { - logger.debug('run() [environment:%s]', "development"); - - var transport1 = void 0; - var transport2 = void 0; - var audioTrack = void 0; - var videoTrack = void 0; - var audioProducer1 = void 0; - var audioProducer2 = void 0; - var videoProducer = void 0; - - logger.debug('calling room = new mediasoupClient.Room()'); - - // const room = new mediasoupClient.Room(); - var room = new mediasoupClient.Room(DATA.ROOM_OPTIONS); - - window.room = room; - - room.on('closed', function (originator, appData) { - logger.warn('room "closed" event [originator:%s, appData:%o]', originator, appData); - }); - - room.on('request', function (request, callback, errback) { - logger.warn('sending request [method:%s]:%o', request.method, request); - - switch (request.method) { - case 'queryRoom': - { - setTimeout(function () { - callback(DATA.QUERY_ROOM_RESPONSE); - errback('upppps'); - }, 200); - break; - } - - case 'joinRoom': - { - setTimeout(function () { - callback(DATA.JOIN_ROOM_RESPONSE); - // errback('upppps'); - }, 200); - break; - } - - case 'createTransport': - { - setTimeout(function () { - switch (request.appData) { - case 'TRANSPORT_1': - callback(DATA.CREATE_TRANSPORT_1_RESPONSE); - break; - case 'TRANSPORT_2': - callback(DATA.CREATE_TRANSPORT_2_RESPONSE); - break; - default: - errback('upppps'); - } - }, 250); - break; - } - - case 'createProducer': - { - setTimeout(function () { - callback(); - }, 250); - break; - } - - case 'enableConsumer': - { - setTimeout(function () { - callback(); - }, 500); - break; - } - - default: - errback('NO IDEA ABOUT REQUEST METHOD "' + request.method + '"'); - } - }); - - room.on('notify', function (notification) { - logger.warn('sending notification [method:%s]:%o', notification.method, notification); - - switch (notification.method) { - case 'leaveRoom': - case 'updateTransport': - case 'closeTransport': - case 'closeProducer': - case 'pauseProducer': - case 'resumeProducer': - case 'pauseConsumer': - case 'resumeConsumer': - break; - - default: - logger.error('NO IDEA ABOUT NOTIFICATION METHOD "' + notification.method + '"'); - } - }); - - room.on('newpeer', function (peer) { - logger.warn('room "newpeer" event [name:"%s", peer:%o]', peer.name, peer); - - handlePeer(peer); - }); - - _promise2.default.resolve().then(function () { - logger.debug('calling room.join()'); - - var deviceInfo = mediasoupClient.getDeviceInfo(); - var appData = { - device: deviceInfo.name + ' ' + deviceInfo.version - }; - - return room.join(null, appData); - // return room.join(DATA.ROOM_RTP_CAPABILITIES, appData); - }).then(function (peers) { - if (!RECV) return; - - logger.debug('room.join() succeeded'); - - logger.debug('calling transport2 = room.createTransport("recv")'); - - transport2 = room.createTransport('recv', 'TRANSPORT_2'); - window.transport2 = transport2; - window.pc2 = transport2._handler._pc; - - handleTransport(transport2); - - var _iteratorNormalCompletion = true; - var _didIteratorError = false; - var _iteratorError = undefined; - - try { - for (var _iterator = (0, _getIterator3.default)(peers), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { - var peer = _step.value; - - handlePeer(peer); - } - } catch (err) { - _didIteratorError = true; - _iteratorError = err; - } finally { - try { - if (!_iteratorNormalCompletion && _iterator.return) { - _iterator.return(); - } - } finally { - if (_didIteratorError) { - throw _iteratorError; - } - } - } - }).then(function () { - if (!SEND) return; - - if (room.canSend('audio')) logger.debug('can send audio');else logger.warn('cannot send audio'); - - if (room.canSend('video')) logger.debug('can send video');else logger.warn('cannot send video'); - - logger.debug('calling transport1 = room.createTransport("send")'); - - transport1 = room.createTransport('send', 'TRANSPORT_1'); - window.transport1 = transport1; - window.pc1 = transport1._handler._pc; - - handleTransport(transport1); - - logger.debug('calling getUserMedia()'); - - return navigator.mediaDevices.getUserMedia({ audio: SEND_AUDIO, video: SEND_VIDEO }); - }).then(function (stream) { - if (!SEND) return; - - audioTrack = stream.getAudioTracks()[0]; - videoTrack = stream.getVideoTracks()[0]; - window.audioTrack = audioTrack; - window.videoTrack = videoTrack; - }) - // Add Producers. - .then(function () { - if (audioTrack) { - var deviceId = audioTrack.getSettings().deviceId; - - logger.debug('calling audioProducer1 = room.createProducer(audioTrack)'); - - try { - audioProducer1 = room.createProducer(audioTrack, deviceId + '-1'); - window.audioProducer1 = audioProducer1; - - handleProducer(audioProducer1); - } catch (error) { - logger.error(error); - } - - logger.debug('calling audioProducer2 = room.createProducer(audioTrack)'); - - try { - audioProducer2 = room.createProducer(audioTrack, deviceId + '-2'); - window.audioProducer2 = audioProducer2; - - handleProducer(audioProducer2); - } catch (error) { - logger.error(error); - } - } - - if (videoTrack) { - var _deviceId = videoTrack.getSettings().deviceId; - - logger.debug('calling videoProducer = room.createProducer(videoTrack)'); - - try { - videoProducer = room.createProducer(videoTrack, _deviceId + '-1'); - window.videoProducer = videoProducer; - - handleProducer(videoProducer); - } catch (error) { - logger.error(error); - } - } - }) - // Receive notifications. - .then(function () { - if (!RECV) return; - - setTimeout(function () { - room.receiveNotification(DATA.ALICE_WEBCAM_NEW_CONSUMER_NOTIFICATION); - }, 2000); - }); -} - -function handleTransport(transport) { - logger.warn('handleTransport() [direction:%s, appData:"%s", transport:%o]', transport.direction, transport.appData, transport); - - transport.on('closed', function (originator, appData) { - logger.warn('transport "closed" event [originator:%s, appData:%o, transport:%o]', originator, appData, transport); - }); - - transport.on('connectionstatechange', function (state) { - logger.warn('transport "connectionstatechange" event [direction:%s, state:%s, transport:%o]', transport.direction, state, transport); - }); - - setInterval(function () { - var queue = transport._commandQueue._queue; - - if (queue.length !== 0) logger.error('queue not empty [transport:%o, queue:%o]', transport, queue); - }, 15000); -} - -function handlePeer(peer) { - logger.warn('handlePeer() [name:"%s", peer:%o]', peer.name, peer); - - switch (peer.name) { - case 'alice': - window.alice = peer; - break; - case 'bob': - window.bob = peer; - break; - } - - var _iteratorNormalCompletion2 = true; - var _didIteratorError2 = false; - var _iteratorError2 = undefined; - - try { - for (var _iterator2 = (0, _getIterator3.default)(peer.consumers), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { - var consumer = _step2.value; - - handleConsumer(consumer); - } - } catch (err) { - _didIteratorError2 = true; - _iteratorError2 = err; - } finally { - try { - if (!_iteratorNormalCompletion2 && _iterator2.return) { - _iterator2.return(); - } - } finally { - if (_didIteratorError2) { - throw _iteratorError2; - } - } - } - - peer.on('closed', function (originator, appData) { - logger.warn('peer "closed" event [name:"%s", originator:%s, appData:%o]', peer.name, originator, appData); - }); - - peer.on('newconsumer', function (consumer) { - logger.warn('peer "newconsumer" event [name:"%s", id:%s, consumer:%o]', peer.name, consumer.id, consumer); - - handleConsumer(consumer); - }); -} - -function handleProducer(producer) { - var transport1 = window.transport1; - - logger.debug('handleProducer() [id:"%s", appData:%o, producer:%o]', producer.id, producer.appData, producer); - - logger.debug('handleProducer() | calling transport1.send(producer)'); - - transport1.send(producer).then(function () { - logger.debug('transport1.send(producer) succeeded'); - }).catch(function (error) { - logger.error('transport1.send(producer) failed: %o', error); - }); - - producer.on('closed', function (originator, appData) { - logger.warn('producer "closed" event [id:%s, originator:%s, appData:%o, producer:%o]', producer.id, originator, appData, producer); - }); - - producer.on('paused', function (originator, appData) { - logger.warn('producer "paused" event [id:%s, originator:%s, appData:%o, producer:%o]', producer.id, originator, appData, producer); - }); - - producer.on('resumed', function (originator, appData) { - logger.warn('producer "resumed" event [id:%s, originator:%s, appData:%o, producer:%o]', producer.id, originator, appData, producer); - }); - - producer.on('unhandled', function () { - logger.warn('producer "unhandled" event [id:%s, producer:%o]', producer.id, producer); - }); -} - -function handleConsumer(consumer) { - var transport2 = window.transport2; - - logger.debug('handleConsumer() [id:"%s", appData:%o, consumer:%o]', consumer.id, consumer.appData, consumer); - - switch (consumer.appData) { - case 'ALICE_MIC': - window.aliceAudioConsumer = consumer; - break; - case 'ALICE_WEBCAM': - window.aliceVideoConsumer = consumer; - break; - case 'BOB_MIC': - window.bobAudioConsumer = consumer; - break; - } - - logger.debug('handleConsumer() calling transport2.receive(consumer)'); - - transport2.receive(consumer).then(function (track) { - logger.warn('transport2.receive(consumer) succeeded [track:%o]', track); - }).catch(function (error) { - logger.error('transport2.receive() failed:%o', error); - }); - - consumer.on('closed', function (originator, appData) { - logger.warn('consumer "closed" event [id:%s, originator:%s, appData:%o, consumer:%o]', consumer.id, originator, appData, consumer); - }); - - consumer.on('paused', function (originator, appData) { - logger.warn('consumer "paused" event [id:%s, originator:%s, appData:%o, consumer:%o]', consumer.id, originator, appData, consumer); - }); - - consumer.on('resumed', function (originator, appData) { - logger.warn('consumer "resumed" event [id:%s, originator:%s, appData:%o, consumer:%o]', consumer.id, originator, appData, consumer); - }); - - consumer.on('unhandled', function () { - logger.warn('consumer "unhandled" event [id:%s, consumer:%o]', consumer.id, consumer); - }); -} - -// NOTE: Trigger server notifications. - -window.notifyRoomClosed = function () { - var room = window.room; - var notification = { - method: 'roomClosed', - notification: true, - appData: 'ha cascao la room remota!!!' - }; - - room.receiveNotification(notification); -}; - -window.notifyTransportClosed = function () { - var room = window.room; - var notification = { - method: 'transportClosed', - notification: true, - id: room.transports[0].id, - appData: 'admin closed your transport' - }; - - room.receiveNotification(notification); -}; - -window.notifyAudioProducer1Closed = function () { - var room = window.room; - var notification = { - method: 'producerClosed', - notification: true, - id: window.audioProducer1.id, - appData: 'te paro el micro por la fuerza' - }; - - room.receiveNotification(notification); -}; - -window.notifyAudioProducer1Paused = function () { - var room = window.room; - var notification = { - method: 'producerPaused', - notification: true, - id: window.audioProducer1.id, - appData: 'te pause el micro por la fuerza' - }; - - room.receiveNotification(notification); -}; - -window.notifyAudioProducer1Resumed = function () { - var room = window.room; - var notification = { - method: 'producerResumed', - notification: true, - id: window.audioProducer1.id, - appData: 'te resumo el micro' - }; - - room.receiveNotification(notification); -}; - -window.notifyAlicePeerClosed = function () { - var room = window.room; - var notification = { - method: 'peerClosed', - notification: true, - name: 'alice', - appData: 'peer left' - }; - - room.receiveNotification(notification); -}; - -window.notifyAliceAudioConsumerClosed = function () { - var room = window.room; - var notification = { - method: 'consumerClosed', - notification: true, - peerName: 'alice', - id: 3333, - appData: 'mic broken' - }; - - room.receiveNotification(notification); -}; - -window.notifyAliceVideoConsumerClosed = function () { - var room = window.room; - var notification = { - method: 'consumerClosed', - notification: true, - peerName: 'alice', - id: 4444, - appData: 'webcam broken' - }; - - room.receiveNotification(notification); -}; - -window.notifyAliceVideoConsumerPaused = function () { - var room = window.room; - var notification = { - method: 'consumerPaused', - notification: true, - peerName: 'alice', - id: 4444, - appData: 'webcam paused' - }; - - room.receiveNotification(notification); -}; - -window.notifyAliceVideoConsumerResumed = function () { - var room = window.room; - var notification = { - method: 'consumerResumed', - notification: true, - peerName: 'alice', - id: 4444, - appData: 'webcam resumed' - }; - - room.receiveNotification(notification); -}; - -// NOTE: Test pause/resume. - -window.testPauseResume = function () { - logger.debug('testPauseResume() with audioProducer1'); - - var producer = window.audioProducer1; - - // producer.once('paused', () => - // { - // producer.resume('I RESUME TO FUACK!!!'); - // }); - - logger.debug('testPauseResume() | (1) calling producer.pause()'); - - if (producer.pause('I PAUSE (1)')) { - logger.warn('testPauseResume() | (1) producer.pause() succeeded [locallyPaused:%s]', producer.locallyPaused); - } else { - logger.error('testPauseResume() | (1) producer.pause() failed [locallyPaused:%s]', producer.locallyPaused); - } - - logger.debug('testPauseResume() | (2) calling producer.pause()'); - - if (producer.pause('I PAUSE (2)')) { - logger.warn('testPauseResume() | (2) producer.pause() succeeded [locallyPaused:%s]', producer.locallyPaused); - } else { - logger.error('testPauseResume() | (2) producer.pause() failed [locallyPaused:%s]', producer.locallyPaused); - } - - logger.debug('testPauseResume() | (3) calling producer.resume()'); - - if (producer.resume('I RESUME (3)')) { - logger.warn('testPauseResume() | (3) producer.resume() succeeded [locallyPaused:%s]', producer.locallyPaused); - } else { - logger.error('testPauseResume() | (3) producer.resume() failed [locallyPaused:%s]', producer.locallyPaused); - } -}; - -// NOTE: For debugging. - -window.dump1 = function () { - var transport1 = window.transport1; - var pc1 = transport1._handler._pc; - - if (pc1 && pc1.localDescription) logger.warn('PC1 SEND LOCAL OFFER:\n%s', pc1.localDescription.sdp); - - if (pc1 && pc1.remoteDescription) logger.warn('PC1 SEND REMOTE ANSWER:\n%s', pc1.remoteDescription.sdp); -}; - -window.dump2 = function () { - var transport2 = window.transport2; - var pc2 = transport2._handler._pc; - - if (pc2 && pc2.remoteDescription) logger.warn('PC2 RECV REMOTE OFFER:\n%s', pc2.remoteDescription.sdp); - - if (pc2 && pc2.localDescription) logger.warn('PC2 RECV LOCAL ANSWER:\n%s', pc2.localDescription.sdp); -}; - -},{"../lib/Logger":"/Users/ibc/src/mediasoup-demo-2/app/lib/Logger.js","./DATA":"/Users/ibc/src/mediasoup-demo-2/app/test/DATA.js","babel-runtime/core-js/get-iterator":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/babel-runtime/core-js/get-iterator.js","babel-runtime/core-js/promise":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/babel-runtime/core-js/promise.js","domready":"/Users/ibc/src/mediasoup-demo-2/app/node_modules/domready/ready.js","mediasoup-client":"/Users/ibc/src/mediasoup-client/lib/index.js"}]},{},["/Users/ibc/src/mediasoup-demo-2/app/test/index.jsx"]) -//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL25vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCIuLi8uLi8uLi9tZWRpYXNvdXAtY2xpZW50L2xpYi9Db21tYW5kUXVldWUuanMiLCIuLi8uLi8uLi9tZWRpYXNvdXAtY2xpZW50L2xpYi9Db25zdW1lci5qcyIsIi4uLy4uLy4uL21lZGlhc291cC1jbGllbnQvbGliL0RldmljZS5qcyIsIi4uLy4uLy4uL21lZGlhc291cC1jbGllbnQvbGliL0VuaGFuY2VkRXZlbnRFbWl0dGVyLmpzIiwiLi4vLi4vLi4vbWVkaWFzb3VwLWNsaWVudC9saWIvTG9nZ2VyLmpzIiwiLi4vLi4vLi4vbWVkaWFzb3VwLWNsaWVudC9saWIvUGVlci5qcyIsIi4uLy4uLy4uL21lZGlhc291cC1jbGllbnQvbGliL1Byb2R1Y2VyLmpzIiwiLi4vLi4vLi4vbWVkaWFzb3VwLWNsaWVudC9saWIvUm9vbS5qcyIsIi4uLy4uLy4uL21lZGlhc291cC1jbGllbnQvbGliL1RyYW5zcG9ydC5qcyIsIi4uLy4uLy4uL21lZGlhc291cC1jbGllbnQvbGliL2Vycm9ycy5qcyIsIi4uLy4uLy4uL21lZGlhc291cC1jbGllbnQvbGliL2hhbmRsZXJzL0Nocm9tZTU1LmpzIiwiLi4vLi4vLi4vbWVkaWFzb3VwLWNsaWVudC9saWIvaGFuZGxlcnMvRWRnZTExLmpzIiwiLi4vLi4vLi4vbWVkaWFzb3VwLWNsaWVudC9saWIvaGFuZGxlcnMvRmlyZWZveDUwLmpzIiwiLi4vLi4vLi4vbWVkaWFzb3VwLWNsaWVudC9saWIvaGFuZGxlcnMvU2FmYXJpMTEuanMiLCIuLi8uLi8uLi9tZWRpYXNvdXAtY2xpZW50L2xpYi9oYW5kbGVycy9zZHAvUmVtb3RlUGxhbkJTZHAuanMiLCIuLi8uLi8uLi9tZWRpYXNvdXAtY2xpZW50L2xpYi9oYW5kbGVycy9zZHAvUmVtb3RlVW5pZmllZFBsYW5TZHAuanMiLCIuLi8uLi8uLi9tZWRpYXNvdXAtY2xpZW50L2xpYi9oYW5kbGVycy9zZHAvY29tbW9uVXRpbHMuanMiLCIuLi8uLi8uLi9tZWRpYXNvdXAtY2xpZW50L2xpYi9oYW5kbGVycy9zZHAvcGxhbkJVdGlscy5qcyIsIi4uLy4uLy4uL21lZGlhc291cC1jbGllbnQvbGliL2hhbmRsZXJzL3NkcC91bmlmaWVkUGxhblV0aWxzLmpzIiwiLi4vLi4vLi4vbWVkaWFzb3VwLWNsaWVudC9saWIvaW5kZXguanMiLCIuLi8uLi8uLi9tZWRpYXNvdXAtY2xpZW50L2xpYi91dGlscy5qcyIsIi4uLy4uLy4uL21lZGlhc291cC1jbGllbnQvbm9kZV9tb2R1bGVzL2JhYmVsLXJ1bnRpbWUvY29yZS1qcy9hcnJheS9mcm9tLmpzIiwiLi4vLi4vLi4vbWVkaWFzb3VwLWNsaWVudC9ub2RlX21vZHVsZXMvYmFiZWwtcnVudGltZS9jb3JlLWpzL2dldC1pdGVyYXRvci5qcyIsIi4uLy4uLy4uL21lZGlhc291cC1jbGllbnQvbm9kZV9tb2R1bGVzL2JhYmVsLXJ1bnRpbWUvY29yZS1qcy9qc29uL3N0cmluZ2lmeS5qcyIsIi4uLy4uLy4uL21lZGlhc291cC1jbGllbnQvbm9kZV9tb2R1bGVzL2JhYmVsLXJ1bnRpbWUvY29yZS1qcy9tYXAuanMiLCIuLi8uLi8uLi9tZWRpYXNvdXAtY2xpZW50L25vZGVfbW9kdWxlcy9iYWJlbC1ydW50aW1lL2NvcmUtanMvb2JqZWN0L2Fzc2lnbi5qcyIsIi4uLy4uLy4uL21lZGlhc291cC1jbGllbnQvbm9kZV9tb2R1bGVzL2JhYmVsLXJ1bnRpbWUvY29yZS1qcy9vYmplY3QvY3JlYXRlLmpzIiwiLi4vLi4vLi4vbWVkaWFzb3VwLWNsaWVudC9ub2RlX21vZHVsZXMvYmFiZWwtcnVudGltZS9jb3JlLWpzL29iamVjdC9kZWZpbmUtcHJvcGVydHkuanMiLCIuLi8uLi8uLi9tZWRpYXNvdXAtY2xpZW50L25vZGVfbW9kdWxlcy9iYWJlbC1ydW50aW1lL2NvcmUtanMvb2JqZWN0L2dldC1wcm90b3R5cGUtb2YuanMiLCIuLi8uLi8uLi9tZWRpYXNvdXAtY2xpZW50L25vZGVfbW9kdWxlcy9iYWJlbC1ydW50aW1lL2NvcmUtanMvb2JqZWN0L2tleXMuanMiLCIuLi8uLi8uLi9tZWRpYXNvdXAtY2xpZW50L25vZGVfbW9kdWxlcy9iYWJlbC1ydW50aW1lL2NvcmUtanMvb2JqZWN0L3NldC1wcm90b3R5cGUtb2YuanMiLCIuLi8uLi8uLi9tZWRpYXNvdXAtY2xpZW50L25vZGVfbW9kdWxlcy9iYWJlbC1ydW50aW1lL2NvcmUtanMvcHJvbWlzZS5qcyIsIi4uLy4uLy4uL21lZGlhc291cC1jbGllbnQvbm9kZV9tb2R1bGVzL2JhYmVsLXJ1bnRpbWUvY29yZS1qcy9zZXQuanMiLCIuLi8uLi8uLi9tZWRpYXNvdXAtY2xpZW50L25vZGVfbW9kdWxlcy9iYWJlbC1ydW50aW1lL2NvcmUtanMvc3ltYm9sLmpzIiwiLi4vLi4vLi4vbWVkaWFzb3VwLWNsaWVudC9ub2RlX21vZHVsZXMvYmFiZWwtcnVudGltZS9jb3JlLWpzL3N5bWJvbC9pdGVyYXRvci5qcyIsIi4uLy4uLy4uL21lZGlhc291cC1jbGllbnQvbm9kZV9tb2R1bGVzL2JhYmVsLXJ1bnRpbWUvaGVscGVycy9jbGFzc0NhbGxDaGVjay5qcyIsIi4uLy4uLy4uL21lZGlhc291cC1jbGllbnQvbm9kZV9tb2R1bGVzL2JhYmVsLXJ1bnRpbWUvaGVscGVycy9jcmVhdGVDbGFzcy5qcyIsIi4uLy4uLy4uL21lZGlhc291cC1jbGllbnQvbm9kZV9tb2R1bGVzL2JhYmVsLXJ1bnRpbWUvaGVscGVycy9leHRlbmRzLmpzIiwiLi4vLi4vLi4vbWVkaWFzb3VwLWNsaWVudC9ub2RlX21vZHVsZXMvYmFiZWwtcnVudGltZS9oZWxwZXJzL2luaGVyaXRzLmpzIiwiLi4vLi4vLi4vbWVkaWFzb3VwLWNsaWVudC9ub2RlX21vZHVsZXMvYmFiZWwtcnVudGltZS9oZWxwZXJzL3Bvc3NpYmxlQ29uc3RydWN0b3JSZXR1cm4uanMiLCIuLi8uLi8uLi9tZWRpYXNvdXAtY2xpZW50L25vZGVfbW9kdWxlcy9iYWJlbC1ydW50aW1lL2hlbHBlcnMvdHlwZW9mLmpzIiwiLi4vLi4vLi4vbWVkaWFzb3VwLWNsaWVudC9ub2RlX21vZHVsZXMvYm93c2VyL3NyYy9ib3dzZXIuanMiLCIuLi8uLi8uLi9tZWRpYXNvdXAtY2xpZW50L25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvZm4vYXJyYXkvZnJvbS5qcyIsIi4uLy4uLy4uL21lZGlhc291cC1jbGllbnQvbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9mbi9nZXQtaXRlcmF0b3IuanMiLCIuLi8uLi8uLi9tZWRpYXNvdXAtY2xpZW50L25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvZm4vanNvbi9zdHJpbmdpZnkuanMiLCIuLi8uLi8uLi9tZWRpYXNvdXAtY2xpZW50L25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvZm4vbWFwLmpzIiwiLi4vLi4vLi4vbWVkaWFzb3VwLWNsaWVudC9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L2ZuL29iamVjdC9hc3NpZ24uanMiLCIuLi8uLi8uLi9tZWRpYXNvdXAtY2xpZW50L25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvZm4vb2JqZWN0L2NyZWF0ZS5qcyIsIi4uLy4uLy4uL21lZGlhc291cC1jbGllbnQvbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9mbi9vYmplY3QvZGVmaW5lLXByb3BlcnR5LmpzIiwiLi4vLi4vLi4vbWVkaWFzb3VwLWNsaWVudC9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L2ZuL29iamVjdC9nZXQtcHJvdG90eXBlLW9mLmpzIiwiLi4vLi4vLi4vbWVkaWFzb3VwLWNsaWVudC9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L2ZuL29iamVjdC9rZXlzLmpzIiwiLi4vLi4vLi4vbWVkaWFzb3VwLWNsaWVudC9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L2ZuL29iamVjdC9zZXQtcHJvdG90eXBlLW9mLmpzIiwiLi4vLi4vLi4vbWVkaWFzb3VwLWNsaWVudC9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L2ZuL3Byb21pc2UuanMiLCIuLi8uLi8uLi9tZWRpYXNvdXAtY2xpZW50L25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvZm4vc2V0LmpzIiwiLi4vLi4vLi4vbWVkaWFzb3VwLWNsaWVudC9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L2ZuL3N5bWJvbC9pbmRleC5qcyIsIi4uLy4uLy4uL21lZGlhc291cC1jbGllbnQvbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9mbi9zeW1ib2wvaXRlcmF0b3IuanMiLCIuLi8uLi8uLi9tZWRpYXNvdXAtY2xpZW50L25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fYS1mdW5jdGlvbi5qcyIsIi4uLy4uLy4uL21lZGlhc291cC1jbGllbnQvbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19hZGQtdG8tdW5zY29wYWJsZXMuanMiLCIuLi8uLi8uLi9tZWRpYXNvdXAtY2xpZW50L25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fYW4taW5zdGFuY2UuanMiLCIuLi8uLi8uLi9tZWRpYXNvdXAtY2xpZW50L25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fYW4tb2JqZWN0LmpzIiwiLi4vLi4vLi4vbWVkaWFzb3VwLWNsaWVudC9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX2FycmF5LWZyb20taXRlcmFibGUuanMiLCIuLi8uLi8uLi9tZWRpYXNvdXAtY2xpZW50L25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fYXJyYXktaW5jbHVkZXMuanMiLCIuLi8uLi8uLi9tZWRpYXNvdXAtY2xpZW50L25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fYXJyYXktbWV0aG9kcy5qcyIsIi4uLy4uLy4uL21lZGlhc291cC1jbGllbnQvbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19hcnJheS1zcGVjaWVzLWNvbnN0cnVjdG9yLmpzIiwiLi4vLi4vLi4vbWVkaWFzb3VwLWNsaWVudC9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX2FycmF5LXNwZWNpZXMtY3JlYXRlLmpzIiwiLi4vLi4vLi4vbWVkaWFzb3VwLWNsaWVudC9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX2NsYXNzb2YuanMiLCIuLi8uLi8uLi9tZWRpYXNvdXAtY2xpZW50L25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fY29mLmpzIiwiLi4vLi4vLi4vbWVkaWFzb3VwLWNsaWVudC9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX2NvbGxlY3Rpb24tc3Ryb25nLmpzIiwiLi4vLi4vLi4vbWVkaWFzb3VwLWNsaWVudC9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX2NvbGxlY3Rpb24tdG8tanNvbi5qcyIsIi4uLy4uLy4uL21lZGlhc291cC1jbGllbnQvbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19jb2xsZWN0aW9uLmpzIiwiLi4vLi4vLi4vbWVkaWFzb3VwLWNsaWVudC9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX2NvcmUuanMiLCIuLi8uLi8uLi9tZWRpYXNvdXAtY2xpZW50L25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fY3JlYXRlLXByb3BlcnR5LmpzIiwiLi4vLi4vLi4vbWVkaWFzb3VwLWNsaWVudC9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX2N0eC5qcyIsIi4uLy4uLy4uL21lZGlhc291cC1jbGllbnQvbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19kZWZpbmVkLmpzIiwiLi4vLi4vLi4vbWVkaWFzb3VwLWNsaWVudC9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX2Rlc2NyaXB0b3JzLmpzIiwiLi4vLi4vLi4vbWVkaWFzb3VwLWNsaWVudC9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX2RvbS1jcmVhdGUuanMiLCIuLi8uLi8uLi9tZWRpYXNvdXAtY2xpZW50L25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fZW51bS1idWcta2V5cy5qcyIsIi4uLy4uLy4uL21lZGlhc291cC1jbGllbnQvbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19lbnVtLWtleXMuanMiLCIuLi8uLi8uLi9tZWRpYXNvdXAtY2xpZW50L25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fZXhwb3J0LmpzIiwiLi4vLi4vLi4vbWVkaWFzb3VwLWNsaWVudC9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX2ZhaWxzLmpzIiwiLi4vLi4vLi4vbWVkaWFzb3VwLWNsaWVudC9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX2Zvci1vZi5qcyIsIi4uLy4uLy4uL21lZGlhc291cC1jbGllbnQvbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19nbG9iYWwuanMiLCIuLi8uLi8uLi9tZWRpYXNvdXAtY2xpZW50L25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9faGFzLmpzIiwiLi4vLi4vLi4vbWVkaWFzb3VwLWNsaWVudC9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX2hpZGUuanMiLCIuLi8uLi8uLi9tZWRpYXNvdXAtY2xpZW50L25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9faHRtbC5qcyIsIi4uLy4uLy4uL21lZGlhc291cC1jbGllbnQvbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19pZTgtZG9tLWRlZmluZS5qcyIsIi4uLy4uLy4uL21lZGlhc291cC1jbGllbnQvbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19pbnZva2UuanMiLCIuLi8uLi8uLi9tZWRpYXNvdXAtY2xpZW50L25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9faW9iamVjdC5qcyIsIi4uLy4uLy4uL21lZGlhc291cC1jbGllbnQvbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19pcy1hcnJheS1pdGVyLmpzIiwiLi4vLi4vLi4vbWVkaWFzb3VwLWNsaWVudC9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX2lzLWFycmF5LmpzIiwiLi4vLi4vLi4vbWVkaWFzb3VwLWNsaWVudC9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX2lzLW9iamVjdC5qcyIsIi4uLy4uLy4uL21lZGlhc291cC1jbGllbnQvbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19pdGVyLWNhbGwuanMiLCIuLi8uLi8uLi9tZWRpYXNvdXAtY2xpZW50L25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9faXRlci1jcmVhdGUuanMiLCIuLi8uLi8uLi9tZWRpYXNvdXAtY2xpZW50L25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9faXRlci1kZWZpbmUuanMiLCIuLi8uLi8uLi9tZWRpYXNvdXAtY2xpZW50L25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9faXRlci1kZXRlY3QuanMiLCIuLi8uLi8uLi9tZWRpYXNvdXAtY2xpZW50L25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9faXRlci1zdGVwLmpzIiwiLi4vLi4vLi4vbWVkaWFzb3VwLWNsaWVudC9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX2l0ZXJhdG9ycy5qcyIsIi4uLy4uLy4uL21lZGlhc291cC1jbGllbnQvbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19rZXlvZi5qcyIsIi4uLy4uLy4uL21lZGlhc291cC1jbGllbnQvbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19saWJyYXJ5LmpzIiwiLi4vLi4vLi4vbWVkaWFzb3VwLWNsaWVudC9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX21ldGEuanMiLCIuLi8uLi8uLi9tZWRpYXNvdXAtY2xpZW50L25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fbWljcm90YXNrLmpzIiwiLi4vLi4vLi4vbWVkaWFzb3VwLWNsaWVudC9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX29iamVjdC1hc3NpZ24uanMiLCIuLi8uLi8uLi9tZWRpYXNvdXAtY2xpZW50L25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fb2JqZWN0LWNyZWF0ZS5qcyIsIi4uLy4uLy4uL21lZGlhc291cC1jbGllbnQvbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19vYmplY3QtZHAuanMiLCIuLi8uLi8uLi9tZWRpYXNvdXAtY2xpZW50L25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fb2JqZWN0LWRwcy5qcyIsIi4uLy4uLy4uL21lZGlhc291cC1jbGllbnQvbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19vYmplY3QtZ29wZC5qcyIsIi4uLy4uLy4uL21lZGlhc291cC1jbGllbnQvbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19vYmplY3QtZ29wbi1leHQuanMiLCIuLi8uLi8uLi9tZWRpYXNvdXAtY2xpZW50L25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fb2JqZWN0LWdvcG4uanMiLCIuLi8uLi8uLi9tZWRpYXNvdXAtY2xpZW50L25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fb2JqZWN0LWdvcHMuanMiLCIuLi8uLi8uLi9tZWRpYXNvdXAtY2xpZW50L25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fb2JqZWN0LWdwby5qcyIsIi4uLy4uLy4uL21lZGlhc291cC1jbGllbnQvbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19vYmplY3Qta2V5cy1pbnRlcm5hbC5qcyIsIi4uLy4uLy4uL21lZGlhc291cC1jbGllbnQvbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19vYmplY3Qta2V5cy5qcyIsIi4uLy4uLy4uL21lZGlhc291cC1jbGllbnQvbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19vYmplY3QtcGllLmpzIiwiLi4vLi4vLi4vbWVkaWFzb3VwLWNsaWVudC9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX29iamVjdC1zYXAuanMiLCIuLi8uLi8uLi9tZWRpYXNvdXAtY2xpZW50L25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fcHJvcGVydHktZGVzYy5qcyIsIi4uLy4uLy4uL21lZGlhc291cC1jbGllbnQvbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19yZWRlZmluZS1hbGwuanMiLCIuLi8uLi8uLi9tZWRpYXNvdXAtY2xpZW50L25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fcmVkZWZpbmUuanMiLCIuLi8uLi8uLi9tZWRpYXNvdXAtY2xpZW50L25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fc2V0LXByb3RvLmpzIiwiLi4vLi4vLi4vbWVkaWFzb3VwLWNsaWVudC9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX3NldC1zcGVjaWVzLmpzIiwiLi4vLi4vLi4vbWVkaWFzb3VwLWNsaWVudC9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX3NldC10by1zdHJpbmctdGFnLmpzIiwiLi4vLi4vLi4vbWVkaWFzb3VwLWNsaWVudC9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX3NoYXJlZC1rZXkuanMiLCIuLi8uLi8uLi9tZWRpYXNvdXAtY2xpZW50L25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fc2hhcmVkLmpzIiwiLi4vLi4vLi4vbWVkaWFzb3VwLWNsaWVudC9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX3NwZWNpZXMtY29uc3RydWN0b3IuanMiLCIuLi8uLi8uLi9tZWRpYXNvdXAtY2xpZW50L25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fc3RyaW5nLWF0LmpzIiwiLi4vLi4vLi4vbWVkaWFzb3VwLWNsaWVudC9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX3Rhc2suanMiLCIuLi8uLi8uLi9tZWRpYXNvdXAtY2xpZW50L25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fdG8taW5kZXguanMiLCIuLi8uLi8uLi9tZWRpYXNvdXAtY2xpZW50L25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fdG8taW50ZWdlci5qcyIsIi4uLy4uLy4uL21lZGlhc291cC1jbGllbnQvbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL190by1pb2JqZWN0LmpzIiwiLi4vLi4vLi4vbWVkaWFzb3VwLWNsaWVudC9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX3RvLWxlbmd0aC5qcyIsIi4uLy4uLy4uL21lZGlhc291cC1jbGllbnQvbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL190by1vYmplY3QuanMiLCIuLi8uLi8uLi9tZWRpYXNvdXAtY2xpZW50L25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fdG8tcHJpbWl0aXZlLmpzIiwiLi4vLi4vLi4vbWVkaWFzb3VwLWNsaWVudC9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX3VpZC5qcyIsIi4uLy4uLy4uL21lZGlhc291cC1jbGllbnQvbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL193a3MtZGVmaW5lLmpzIiwiLi4vLi4vLi4vbWVkaWFzb3VwLWNsaWVudC9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX3drcy1leHQuanMiLCIuLi8uLi8uLi9tZWRpYXNvdXAtY2xpZW50L25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fd2tzLmpzIiwiLi4vLi4vLi4vbWVkaWFzb3VwLWNsaWVudC9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvY29yZS5nZXQtaXRlcmF0b3ItbWV0aG9kLmpzIiwiLi4vLi4vLi4vbWVkaWFzb3VwLWNsaWVudC9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvY29yZS5nZXQtaXRlcmF0b3IuanMiLCIuLi8uLi8uLi9tZWRpYXNvdXAtY2xpZW50L25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9lczYuYXJyYXkuZnJvbS5qcyIsIi4uLy4uLy4uL21lZGlhc291cC1jbGllbnQvbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL2VzNi5hcnJheS5pdGVyYXRvci5qcyIsIi4uLy4uLy4uL21lZGlhc291cC1jbGllbnQvbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL2VzNi5tYXAuanMiLCIuLi8uLi8uLi9tZWRpYXNvdXAtY2xpZW50L25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9lczYub2JqZWN0LmFzc2lnbi5qcyIsIi4uLy4uLy4uL21lZGlhc291cC1jbGllbnQvbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL2VzNi5vYmplY3QuY3JlYXRlLmpzIiwiLi4vLi4vLi4vbWVkaWFzb3VwLWNsaWVudC9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvZXM2Lm9iamVjdC5kZWZpbmUtcHJvcGVydHkuanMiLCIuLi8uLi8uLi9tZWRpYXNvdXAtY2xpZW50L25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9lczYub2JqZWN0LmdldC1wcm90b3R5cGUtb2YuanMiLCIuLi8uLi8uLi9tZWRpYXNvdXAtY2xpZW50L25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9lczYub2JqZWN0LmtleXMuanMiLCIuLi8uLi8uLi9tZWRpYXNvdXAtY2xpZW50L25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9lczYub2JqZWN0LnNldC1wcm90b3R5cGUtb2YuanMiLCIuLi8uLi8uLi9tZWRpYXNvdXAtY2xpZW50L25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9lczYub2JqZWN0LnRvLXN0cmluZy5qcyIsIi4uLy4uLy4uL21lZGlhc291cC1jbGllbnQvbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL2VzNi5wcm9taXNlLmpzIiwiLi4vLi4vLi4vbWVkaWFzb3VwLWNsaWVudC9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvZXM2LnNldC5qcyIsIi4uLy4uLy4uL21lZGlhc291cC1jbGllbnQvbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL2VzNi5zdHJpbmcuaXRlcmF0b3IuanMiLCIuLi8uLi8uLi9tZWRpYXNvdXAtY2xpZW50L25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9lczYuc3ltYm9sLmpzIiwiLi4vLi4vLi4vbWVkaWFzb3VwLWNsaWVudC9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvZXM3Lm1hcC50by1qc29uLmpzIiwiLi4vLi4vLi4vbWVkaWFzb3VwLWNsaWVudC9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvZXM3LnNldC50by1qc29uLmpzIiwiLi4vLi4vLi4vbWVkaWFzb3VwLWNsaWVudC9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvZXM3LnN5bWJvbC5hc3luYy1pdGVyYXRvci5qcyIsIi4uLy4uLy4uL21lZGlhc291cC1jbGllbnQvbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL2VzNy5zeW1ib2wub2JzZXJ2YWJsZS5qcyIsIi4uLy4uLy4uL21lZGlhc291cC1jbGllbnQvbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL3dlYi5kb20uaXRlcmFibGUuanMiLCIuLi8uLi8uLi9tZWRpYXNvdXAtY2xpZW50L25vZGVfbW9kdWxlcy9kZWJ1Zy9zcmMvYnJvd3Nlci5qcyIsIi4uLy4uLy4uL21lZGlhc291cC1jbGllbnQvbm9kZV9tb2R1bGVzL2RlYnVnL3NyYy9kZWJ1Zy5qcyIsIi4uLy4uLy4uL21lZGlhc291cC1jbGllbnQvbm9kZV9tb2R1bGVzL21zL2luZGV4LmpzIiwiLi4vLi4vLi4vbWVkaWFzb3VwLWNsaWVudC9ub2RlX21vZHVsZXMvcmFuZG9tLW51bWJlci9pbmRleC5qcyIsIi4uLy4uLy4uL21lZGlhc291cC1jbGllbnQvbm9kZV9tb2R1bGVzL3NkcC10cmFuc2Zvcm0vbGliL2dyYW1tYXIuanMiLCIuLi8uLi8uLi9tZWRpYXNvdXAtY2xpZW50L25vZGVfbW9kdWxlcy9zZHAtdHJhbnNmb3JtL2xpYi9pbmRleC5qcyIsIi4uLy4uLy4uL21lZGlhc291cC1jbGllbnQvbm9kZV9tb2R1bGVzL3NkcC10cmFuc2Zvcm0vbGliL3BhcnNlci5qcyIsIi4uLy4uLy4uL21lZGlhc291cC1jbGllbnQvbm9kZV9tb2R1bGVzL3NkcC10cmFuc2Zvcm0vbGliL3dyaXRlci5qcyIsIi4uL2xpYi9Mb2dnZXIuanMiLCIuLi9ub2RlX21vZHVsZXMvZGVidWcvc3JjL2Jyb3dzZXIuanMiLCIuLi9ub2RlX21vZHVsZXMvZGVidWcvc3JjL2RlYnVnLmpzIiwiLi4vbm9kZV9tb2R1bGVzL2RvbXJlYWR5L3JlYWR5LmpzIiwiLi4vbm9kZV9tb2R1bGVzL2V2ZW50cy9ldmVudHMuanMiLCIuLi9ub2RlX21vZHVsZXMvcHJvY2Vzcy9icm93c2VyLmpzIiwiREFUQS5qcyIsImluZGV4LmpzeCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUNBQTs7QUFDQTs7OztBQUNBOzs7O0FBRUEsSUFBTSxTQUFTLHFCQUFXLGNBQVgsQ0FBZjs7SUFFcUIsWTs7O0FBRXBCLHlCQUNBO0FBQUE7O0FBQUE7O0FBRUMsUUFBSyxlQUFMLENBQXFCLFFBQXJCOztBQUVBO0FBQ0E7QUFDQSxRQUFLLE9BQUwsR0FBZSxLQUFmOztBQUVBO0FBQ0E7QUFDQSxRQUFLLEtBQUwsR0FBYSxLQUFiOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFFBQUssTUFBTCxHQUFjLEVBQWQ7QUFmRDtBQWdCQzs7OzswQkFHRDtBQUNDLFFBQUssT0FBTCxHQUFlLElBQWY7QUFDQTs7O3VCQUVJLE0sRUFBUSxJLEVBQ2I7QUFBQTs7QUFDQyxPQUFNLFVBQVUsdUJBQWMsRUFBRSxjQUFGLEVBQWQsRUFBMEIsSUFBMUIsQ0FBaEI7O0FBRUEsVUFBTyxLQUFQLENBQWEsb0JBQWIsRUFBbUMsTUFBbkM7O0FBRUEsVUFBTyxzQkFBWSxVQUFDLE9BQUQsRUFBVSxNQUFWLEVBQ25CO0FBQ0MsUUFBTSxRQUFRLE9BQUssTUFBbkI7O0FBRUEsWUFBUSxPQUFSLEdBQWtCLE9BQWxCO0FBQ0EsWUFBUSxNQUFSLEdBQWlCLE1BQWpCOztBQUVBO0FBQ0EsVUFBTSxJQUFOLENBQVcsT0FBWDtBQUNBLFdBQUssc0JBQUw7QUFDQSxJQVZNLENBQVA7QUFXQTs7OzJDQUdEO0FBQUE7O0FBQ0MsT0FBSSxLQUFLLEtBQVQsRUFDQzs7QUFFRCxPQUFNLFFBQVEsS0FBSyxNQUFuQjs7QUFFQTtBQUNBLE9BQU0sVUFBVSxNQUFNLENBQU4sQ0FBaEI7O0FBRUEsT0FBSSxDQUFDLE9B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QUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3psQkE7QUFDQTtBQUNBOztBQ0ZBO0FBQ0E7QUFDQTs7QUNGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ0pBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNMQTtBQUNBOztBQ0RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDSkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNKQTtBQUNBOztBQ0RBO0FBQ0E7O0FDREE7QUFDQTs7QUNEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ0pBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNMQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ0pBO0FBQ0E7QUFDQTs7QUNGQTtBQUNBO0FBQ0E7QUFDQTs7QUNIQTs7QUNBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ0pBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDSkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNQQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM0NBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2ZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNMQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3RCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ0pBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzdJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDUkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMxREE7QUFDQTs7QUNEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1BBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbkJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDSkE7QUFDQTtBQUNBO0FBQ0E7O0FDSEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDTkE7QUFDQTtBQUNBO0FBQ0E7O0FDSEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNOQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4QkE7QUFDQTtBQUNBO0FBQ0E7O0FDSEE7QUFDQTtBQUNBO0FBQ0E7O0FDSEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNQQTs7QUNBQTtBQUNBO0FBQ0E7O0FDRkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDZkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNKQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1BBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDSkE7QUFDQTtBQUNBOztBQ0ZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNYQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNaQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNyRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BCQTtBQUNBO0FBQ0E7O0FDRkE7O0FDQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDVEE7O0FDQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDekNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2ZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1pBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2ZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbkJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ05BOztBQ0FBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1pBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ05BOztBQ0FBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDUEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDTkE7O0FDQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDYkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDTkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNKQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDTEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNQQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDMUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ05BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNMQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDTEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ0xBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDSkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1hBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDSkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1JBOztBQ0FBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDVkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNQQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNOQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoQkE7QUFDQTtBQUNBO0FBQ0E7O0FDSEE7QUFDQTtBQUNBOztBQ0ZBO0FBQ0E7QUFDQTs7QUNGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDUkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1JBO0FBQ0E7QUFDQTs7QUNGQTs7QUNBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzFTQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDWEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDMU9BO0FBQ0E7QUFDQTtBQUNBOztBQ0hBO0FBQ0E7QUFDQTtBQUNBOztBQ0hBOztBQ0FBOztBQ0FBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUNaQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7QUN6TEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMxTUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3hKQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDNUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcFZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNYQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDMUhBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7Ozs7O0FDbEhBOzs7Ozs7QUFFQSxJQUFNLFdBQVcsZ0JBQWpCOztJQUVxQixNO0FBRXBCLGlCQUFZLE1BQVosRUFDQTtBQUFBOztBQUNDLE1BQUksTUFBSixFQUNBO0FBQ0MsUUFBSyxNQUFMLEdBQWMscUJBQVMsUUFBVCxTQUFxQixNQUFyQixDQUFkO0FBQ0EsUUFBSyxLQUFMLEdBQWEscUJBQVMsUUFBVCxjQUEwQixNQUExQixDQUFiO0FBQ0EsUUFBSyxNQUFMLEdBQWMscUJBQVMsUUFBVCxlQUEyQixNQUEzQixDQUFkO0FBQ0EsR0FMRCxNQU9BO0FBQ0MsUUFBSyxNQUFMLEdBQWMscUJBQU0sUUFBTixDQUFkO0FBQ0EsUUFBSyxLQUFMLEdBQWEscUJBQVMsUUFBVCxXQUFiO0FBQ0EsUUFBSyxNQUFMLEdBQWMscUJBQVMsUUFBVCxZQUFkO0FBQ0E7O0FBRUQ7QUFDQSxPQUFLLE1BQUwsQ0FBWSxHQUFaLEdBQWtCLFFBQVEsSUFBUixDQUFhLElBQWIsQ0FBa0IsT0FBbEIsQ0FBbEI7QUFDQSxPQUFLLEtBQUwsQ0FBVyxHQUFYLEdBQWlCLFFBQVEsSUFBUixDQUFhLElBQWIsQ0FBa0IsT0FBbEIsQ0FBakI7QUFDQSxPQUFLLE1BQUwsQ0FBWSxHQUFaLEdBQWtCLFFBQVEsS0FBUixDQUFjLElBQWQsQ0FBbUIsT0FBbkIsQ0FBbEI7QUFDQTtBQUNBOzs7O3NCQUdEO0FBQ0MsVUFBTyxLQUFLLE1BQVo7QUFDQTs7O3NCQUdEO0FBQ0MsVUFBTyxLQUFLLEtBQVo7QUFDQTs7O3NCQUdEO0FBQ0MsVUFBTyxLQUFLLE1BQVo7QUFDQTs7Ozs7a0JBckNtQixNOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQ0pyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FDOUxBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pPQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzlTQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7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Q0MsT0FBTyxJQUFQLENBQVksMkJBQVosRUFBeUMsSUFBSSxnQkFBSixDQUFxQixHQUE5RDs7QUFFRCxLQUFJLE9BQU8sSUFBSSxpQkFBZixFQUNDLE9BQU8sSUFBUCxDQUFZLDZCQUFaLEVBQTJDLElBQUksaUJBQUosQ0FBc0IsR0FBakU7QUFDRCxDQVZEOztBQVlBLE9BQU8sS0FBUCxHQUFlLFlBQ2Y7QUFDQyxLQUFNLGFBQWEsT0FBTyxVQUExQjtBQUNBLEtBQU0sTUFBTSxXQUFXLFFBQVgsQ0FBb0IsR0FBaEM7O0FBRUEsS0FBSSxPQUFPLElBQUksaUJBQWYsRUFDQyxPQUFPLElBQVAsQ0FBWSw0QkFBWixFQUEwQyxJQUFJLGlCQUFKLENBQXNCLEdBQWhFOztBQUVELEtBQUksT0FBTyxJQUFJLGdCQUFmLEVBQ0MsT0FBTyxJQUFQLENBQVksNEJBQVosRUFBMEMsSUFBSSxnQkFBSixDQUFxQixHQUEvRDtBQUNELENBVkQiLCJmaWxlIjoiZ2VuZXJhdGVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXNDb250ZW50IjpbIihmdW5jdGlvbiBlKHQsbixyKXtmdW5jdGlvbiBzKG8sdSl7aWYoIW5bb10pe2lmKCF0W29dKXt2YXIgYT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2lmKCF1JiZhKXJldHVybiBhKG8sITApO2lmKGkpcmV0dXJuIGkobywhMCk7dmFyIGY9bmV3IEVycm9yKFwiQ2Fubm90IGZpbmQgbW9kdWxlICdcIitvK1wiJ1wiKTt0aHJvdyBmLmNvZGU9XCJNT0RVTEVfTk9UX0ZPVU5EXCIsZn12YXIgbD1uW29dPXtleHBvcnRzOnt9fTt0W29dWzBdLmNhbGwobC5leHBvcnRzLGZ1bmN0aW9uKGUpe3ZhciBuPXRbb11bMV1bZV07cmV0dXJuIHMobj9uOmUpfSxsLGwuZXhwb3J0cyxlLHQsbixyKX1yZXR1cm4gbltvXS5leHBvcnRzfXZhciBpPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7Zm9yKHZhciBvPTA7bzxyLmxlbmd0aDtvKyspcyhyW29dKTtyZXR1cm4gc30pIiwiaW1wb3J0IHsgRXZlbnRFbWl0dGVyIH0gZnJvbSAnZXZlbnRzJztcbmltcG9ydCBMb2dnZXIgZnJvbSAnLi9Mb2dnZXInO1xuaW1wb3J0IHsgSW52YWxpZFN0YXRlRXJyb3IgfSBmcm9tICcuL2Vycm9ycyc7XG5cbmNvbnN0IGxvZ2dlciA9IG5ldyBMb2dnZXIoJ0NvbW1hbmRRdWV1ZScpO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBDb21tYW5kUXVldWUgZXh0ZW5kcyBFdmVudEVtaXR0ZXJcbntcblx0Y29uc3RydWN0b3IoKVxuXHR7XG5cdFx0c3VwZXIoKTtcblx0XHR0aGlzLnNldE1heExpc3RlbmVycyhJbmZpbml0eSk7XG5cblx0XHQvLyBDbG9zZWQgZmxhZy5cblx0XHQvLyBAdHlwZSB7Qm9vbGVhbn1cblx0XHR0aGlzLl9jbG9zZWQgPSBmYWxzZTtcblxuXHRcdC8vIEJ1c3kgcnVubmluZyBhIGNvbW1hbmQuXG5cdFx0Ly8gQHR5cGUge0Jvb2xlYW59XG5cdFx0dGhpcy5fYnVzeSA9IGZhbHNlO1xuXG5cdFx0Ly8gUXVldWUgZm9yIHBlbmRpbmcgY29tbWFuZHMuIEVhY2ggY29tbWFuZCBpcyBhbiBPYmplY3Qgd2l0aCBtZXRob2QsXG5cdFx0Ly8gcmVzb2x2ZSwgcmVqZWN0LCBhbmQgb3RoZXIgbWVtYmVycyAoZGVwZW5kaW5nIHRoZSBjYXNlKS5cblx0XHQvLyBAdHlwZSB7QXJyYXk8T2JqZWN0Pn1cblx0XHR0aGlzLl9xdWV1ZSA9IFtdO1xuXHR9XG5cblx0Y2xvc2UoKVxuXHR7XG5cdFx0dGhpcy5fY2xvc2VkID0gdHJ1ZTtcblx0fVxuXG5cdHB1c2gobWV0aG9kLCBkYXRhKVxuXHR7XG5cdFx0Y29uc3QgY29tbWFuZCA9IE9iamVjdC5hc3NpZ24oeyBtZXRob2QgfSwgZGF0YSk7XG5cblx0XHRsb2dnZXIuZGVidWcoJ3B1c2goKSBbbWV0aG9kOiVzXScsIG1ldGhvZCk7XG5cblx0XHRyZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT5cblx0XHR7XG5cdFx0XHRjb25zdCBxdWV1ZSA9IHRoaXMuX3F1ZXVlO1xuXG5cdFx0XHRjb21tYW5kLnJlc29sdmUgPSByZXNvbHZlO1xuXHRcdFx0Y29tbWFuZC5yZWplY3QgPSByZWplY3Q7XG5cblx0XHRcdC8vIEFwcGVuZCBjb21tYW5kIHRvIHRoZSBxdWV1ZS5cblx0XHRcdHF1ZXVlLnB1c2goY29tbWFuZCk7XG5cdFx0XHR0aGlzLl9oYW5kbGVQZW5kaW5nQ29tbWFuZHMoKTtcblx0XHR9KTtcblx0fVxuXG5cdF9oYW5kbGVQZW5kaW5nQ29tbWFuZHMoKVxuXHR7XG5cdFx0aWYgKHRoaXMuX2J1c3kpXG5cdFx0XHRyZXR1cm47XG5cblx0XHRjb25zdCBxdWV1ZSA9IHRoaXMuX3F1ZXVlO1xuXG5cdFx0Ly8gVGFrZSB0aGUgZmlyc3QgY29tbWFuZC5cblx0XHRjb25zdCBjb21tYW5kID0gcXVldWVbMF07XG5cblx0XHRpZiAoIWNvbW1hbmQpXG5cdFx0XHRyZXR1cm47XG5cblx0XHR0aGlzLl9idXN5ID0gdHJ1ZTtcblxuXHRcdC8vIEV4ZWN1dGUgaXQuXG5cdFx0dGhpcy5faGFuZGxlQ29tbWFuZChjb21tYW5kKVxuXHRcdFx0LnRoZW4oKCkgPT5cblx0XHRcdHtcblx0XHRcdFx0dGhpcy5fYnVzeSA9IGZhbHNlO1xuXG5cdFx0XHRcdC8vIFJlbW92ZSB0aGUgZmlyc3QgY29tbWFuZCAodGhlIGNvbXBsZXRlZCBvbmUpIGZyb20gdGhlIHF1ZXVlLlxuXHRcdFx0XHRxdWV1ZS5zaGlmdCgpO1xuXG5cdFx0XHRcdC8vIEFuZCBjb250aW51ZS5cblx0XHRcdFx0dGhpcy5faGFuZGxlUGVuZGluZ0NvbW1hbmRzKCk7XG5cdFx0XHR9KTtcblx0fVxuXG5cdF9oYW5kbGVDb21tYW5kKGNvbW1hbmQpXG5cdHtcblx0XHRsb2dnZXIuZGVidWcoJ19oYW5kbGVDb21tYW5kKCkgW21ldGhvZDolc10nLCBjb21tYW5kLm1ldGhvZCk7XG5cblx0XHRpZiAodGhpcy5fY2xvc2VkKVxuXHRcdHtcblx0XHRcdGNvbW1hbmQucmVqZWN0KG5ldyBJbnZhbGlkU3RhdGVFcnJvcignY2xvc2VkJykpO1xuXG5cdFx0XHRyZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG5cdFx0fVxuXG5cdFx0Y29uc3QgcHJvbWlzZUhvbGRlciA9IHsgcHJvbWlzZTogbnVsbCB9O1xuXG5cdFx0dGhpcy5lbWl0KCdleGVjJywgY29tbWFuZCwgcHJvbWlzZUhvbGRlcik7XG5cblx0XHRyZXR1cm4gUHJvbWlzZS5yZXNvbHZlKClcblx0XHRcdC50aGVuKCgpID0+XG5cdFx0XHR7XG5cdFx0XHRcdHJldHVybiBwcm9taXNlSG9sZGVyLnByb21pc2U7XG5cdFx0XHR9KVxuXHRcdFx0LnRoZW4oKHJlc3VsdCkgPT5cblx0XHRcdHtcblx0XHRcdFx0bG9nZ2VyLmRlYnVnKCdfaGFuZGxlQ29tbWFuZCgpIHwgY29tbWFuZCBzdWNjZWVkZWQgW21ldGhvZDolc10nLCBjb21tYW5kLm1ldGhvZCk7XG5cblx0XHRcdFx0aWYgKHRoaXMuX2Nsb3NlZClcblx0XHRcdFx0e1xuXHRcdFx0XHRcdGNvbW1hbmQucmVqZWN0KG5ldyBJbnZhbGlkU3RhdGVFcnJvcignY2xvc2VkJykpO1xuXG5cdFx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0Ly8gUmVzb2x2ZSB0aGUgY29tbWFuZCB3aXRoIHRoZSBnaXZlbiByZXN1bHQgKGlmIGFueSkuXG5cdFx0XHRcdGNvbW1hbmQucmVzb2x2ZShyZXN1bHQpO1xuXHRcdFx0fSlcblx0XHRcdC5jYXRjaCgoZXJyb3IpID0+XG5cdFx0XHR7XG5cdFx0XHRcdGxvZ2dlci5lcnJvcihcblx0XHRcdFx0XHQnX2hhbmRsZUNvbW1hbmQoKSB8IGNvbW1hbmQgZmFpbGVkIFttZXRob2Q6JXNdOiAlbycsIGNvbW1hbmQubWV0aG9kLCBlcnJvcik7XG5cblx0XHRcdFx0Ly8gUmVqZWN0IHRoZSBjb21tYW5kIHdpdGggdGhlIGVycm9yLlxuXHRcdFx0XHRjb21tYW5kLnJlamVjdChlcnJvcik7XG5cdFx0XHR9KTtcblx0fVxufVxuIiwiaW1wb3J0IExvZ2dlciBmcm9tICcuL0xvZ2dlcic7XG5pbXBvcnQgRW5oYW5jZWRFdmVudEVtaXR0ZXIgZnJvbSAnLi9FbmhhbmNlZEV2ZW50RW1pdHRlcic7XG5cbmNvbnN0IGxvZ2dlciA9IG5ldyBMb2dnZXIoJ0NvbnN1bWVyJyk7XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIENvbnN1bWVyIGV4dGVuZHMgRW5oYW5jZWRFdmVudEVtaXR0ZXJcbntcblx0LyoqXG5cdCAqIEBwcml2YXRlXG5cdCAqXG5cdCAqIEBlbWl0cyB7b3JpZ2luYXRvcjogU3RyaW5nLCBbYXBwRGF0YV06IEFueX0gcGF1c2VkXG5cdCAqIEBlbWl0cyB7b3JpZ2luYXRvcjogU3RyaW5nLCBbYXBwRGF0YV06IEFueX0gcmVzdW1lZFxuXHQgKiBAZW1pdHMgdW5oYW5kbGVkXG5cdCAqIEBlbWl0cyB7b3JpZ2luYXRvcjogU3RyaW5nLCBbYXBwRGF0YV06IEFueX0gY2xvc2VkXG5cdCAqXG5cdCAqIEBlbWl0cyB7W2FwcERhdGFdOiBBbnl9IEBwYXVzZVxuXHQgKiBAZW1pdHMge1thcHBEYXRhXTogQW55fSBAcmVzdW1lXG5cdCAqIEBlbWl0cyB7b3JpZ2luYXRvcjogU3RyaW5nfSBAY2xvc2Vcblx0ICovXG5cdGNvbnN0cnVjdG9yKGlkLCBraW5kLCBydHBQYXJhbWV0ZXJzLCBwZWVyLCBhcHBEYXRhKVxuXHR7XG5cdFx0c3VwZXIoKTtcblxuXHRcdC8vIElkLlxuXHRcdC8vIEB0eXBlIHtOdW1iZXJ9XG5cdFx0dGhpcy5faWQgPSBpZDtcblxuXHRcdC8vIENsb3NlZCBmbGFnLlxuXHRcdC8vIEB0eXBlIHtCb29sZWFufVxuXHRcdHRoaXMuX2Nsb3NlZCA9IGZhbHNlO1xuXG5cdFx0Ly8gTWVkaWEga2luZC5cblx0XHQvLyBAdHlwZSB7U3RyaW5nfVxuXHRcdHRoaXMuX2tpbmQgPSBraW5kO1xuXG5cdFx0Ly8gUlRQIHBhcmFtZXRlcnMuXG5cdFx0Ly8gQHR5cGUge1JUQ1J0cFBhcmFtZXRlcnN9XG5cdFx0dGhpcy5fcnRwUGFyYW1ldGVycyA9IHJ0cFBhcmFtZXRlcnM7XG5cblx0XHQvLyBBc3NvY2lhdGVkIFBlZXIuXG5cdFx0Ly8gQHR5cGUge1BlZXJ9XG5cdFx0dGhpcy5fcGVlciA9IHBlZXI7XG5cblx0XHQvLyBBcHAgY3VzdG9tIGRhdGEuXG5cdFx0Ly8gQHR5cGUge0FueX1cblx0XHR0aGlzLl9hcHBEYXRhID0gYXBwRGF0YTtcblxuXHRcdC8vIFdoZXRoZXIgd2UgY2FuIHJlY2VpdmUgdGhpcyBDb25zdW1lciAoYmFzZWQgb24gb3VyIFJUUCBjYXBhYmlsaXRpZXMpLlxuXHRcdC8vIEB0eXBlIHtCb29sZWFufVxuXHRcdHRoaXMuX3N1cHBvcnRlZCA9IGZhbHNlO1xuXG5cdFx0Ly8gV2hldGhlciB0aGlzIENvbnN1bWVyIGlzIGJlaW5nIGhhbmRsZWQgYnkgYSBUcmFuc3BvcnQuXG5cdFx0Ly8gQHR5cGUge0Jvb2xlYW59XG5cdFx0dGhpcy5faGFuZGxlZCA9IGZhbHNlO1xuXG5cdFx0Ly8gUmVtb3RlIHRyYWNrLlxuXHRcdC8vIEB0eXBlIHtNZWRpYVN0cmVhbVRyYWNrfVxuXHRcdHRoaXMuX3RyYWNrID0gbnVsbDtcblxuXHRcdC8vIExvY2FsbHkgcGF1c2VkIGZsYWcuXG5cdFx0Ly8gQHR5cGUge0Jvb2xlYW59XG5cdFx0dGhpcy5fbG9jYWxseVBhdXNlZCA9IGZhbHNlO1xuXG5cdFx0Ly8gUmVtb3RlbHkgcGF1c2VkIGZsYWcuXG5cdFx0Ly8gQHR5cGUge0Jvb2xlYW59XG5cdFx0dGhpcy5fcmVtb3RlbHlQYXVzZWQgPSBmYWxzZTtcblx0fVxuXG5cdC8qKlxuXHQgKiBDbGFzcyBuYW1lLlxuXHQgKlxuXHQgKiBAcmV0dXJuIHtTdHJpbmd9XG5cdCAqL1xuXHRnZXQga2xhc3MoKVxuXHR7XG5cdFx0cmV0dXJuICdDb25zdW1lcic7XG5cdH1cblxuXHQvKipcblx0ICogQ29uc3VtZXIgaWQuXG5cdCAqXG5cdCAqIEByZXR1cm4ge051bWJlcn1cblx0ICovXG5cdGdldCBpZCgpXG5cdHtcblx0XHRyZXR1cm4gdGhpcy5faWQ7XG5cdH1cblxuXHQvKipcblx0ICogV2hldGhlciB0aGUgQ29uc3VtZXIgaXMgY2xvc2VkLlxuXHQgKlxuXHQgKiBAcmV0dXJuIHtCb29sZWFufVxuXHQgKi9cblx0Z2V0IGNsb3NlZCgpXG5cdHtcblx0XHRyZXR1cm4gdGhpcy5fY2xvc2VkO1xuXHR9XG5cblx0LyoqXG5cdCAqIE1lZGlhIGtpbmQuXG5cdCAqXG5cdCAqIEByZXR1cm4ge1N0cmluZ31cblx0ICovXG5cdGdldCBraW5kKClcblx0e1xuXHRcdHJldHVybiB0aGlzLl9raW5kO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJUUCBwYXJhbWV0ZXJzLlxuXHQgKlxuXHQgKiBAcmV0dXJuIHtSVENSdHBQYXJhbWV0ZXJzfVxuXHQgKi9cblx0Z2V0IHJ0cFBhcmFtZXRlcnMoKVxuXHR7XG5cdFx0cmV0dXJuIHRoaXMuX3J0cFBhcmFtZXRlcnM7XG5cdH1cblxuXHQvKipcblx0ICogQXNzb2NpYXRlZCBQZWVyLlxuXHQgKlxuXHQgKiBAcmV0dXJuIHtQZWVyfVxuXHQgKi9cblx0Z2V0IHBlZXIoKVxuXHR7XG5cdFx0cmV0dXJuIHRoaXMuX3BlZXI7XG5cdH1cblxuXHQvKipcblx0ICogQXBwIGN1c3RvbSBkYXRhLlxuXHQgKlxuXHQgKiBAcmV0dXJuIHtBbnl9XG5cdCAqL1xuXHRnZXQgYXBwRGF0YSgpXG5cdHtcblx0XHRyZXR1cm4gdGhpcy5fYXBwRGF0YTtcblx0fVxuXG5cdC8qKlxuXHQgKiBXaGV0aGVyIHdlIGNhbiByZWNlaXZlIHRoaXMgQ29uc3VtZXIgKGJhc2VkIG9uIG91ciBSVFAgY2FwYWJpbGl0aWVzKS5cblx0ICpcblx0ICogQHJldHVybiB7Qm9vbGVhbn1cblx0ICovXG5cdGdldCBzdXBwb3J0ZWQoKVxuXHR7XG5cdFx0cmV0dXJuIHRoaXMuX3N1cHBvcnRlZDtcblx0fVxuXG5cdC8qKlxuXHQgKiBXaGV0aGVyIHRoaXMgaXMgYmVpbmcgaGFuZGxlZCBieSBhIFRyYW5zcG9ydC5cblx0ICpcblx0ICogQHJldHVybiB7Qm9vbGVhbn1cblx0ICovXG5cdGdldCBoYW5kbGVkKClcblx0e1xuXHRcdHJldHVybiBCb29sZWFuKHRoaXMuX2hhbmRsZWQpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFRoZSBhc3NvY2lhdGVkIHRyYWNrIChpZiBhbnkgeWV0KS5cblx0ICpcblx0ICogQHJldHVybiB7TWVkaWFTdHJlYW1UcmFja3xOdWxsfVxuXHQgKi9cblx0Z2V0IHRyYWNrKClcblx0e1xuXHRcdHJldHVybiB0aGlzLl90cmFjaztcblx0fVxuXG5cdC8qKlxuXHQgKiBXaGV0aGVyIHRoZSBDb25zdW1lciBpcyBsb2NhbGx5IHBhdXNlZC5cblx0ICpcblx0ICogQHJldHVybiB7Qm9vbGVhbn1cblx0ICovXG5cdGdldCBsb2NhbGx5UGF1c2VkKClcblx0e1xuXHRcdHJldHVybiB0aGlzLl9sb2NhbGx5UGF1c2VkO1xuXHR9XG5cblx0LyoqXG5cdCAqIFdoZXRoZXIgdGhlIENvbnN1bWVyIGlzIHJlbW90ZWx5IHBhdXNlZC5cblx0ICpcblx0ICogQHJldHVybiB7Qm9vbGVhbn1cblx0ICovXG5cdGdldCByZW1vdGVseVBhdXNlZCgpXG5cdHtcblx0XHRyZXR1cm4gdGhpcy5fcmVtb3RlbHlQYXVzZWQ7XG5cdH1cblxuXHQvKipcblx0ICogV2hldGhlciB0aGUgQ29uc3VtZXIgaXMgcGF1c2VkLlxuXHQgKlxuXHQgKiBAcmV0dXJuIHtCb29sZWFufVxuXHQgKi9cblx0Z2V0IHBhdXNlZCgpXG5cdHtcblx0XHRyZXR1cm4gdGhpcy5fbG9jYWxseVBhdXNlZCB8fCB0aGlzLl9yZW1vdGVseVBhdXNlZDtcblx0fVxuXG5cdC8qKlxuXHQgKiBXaGV0aGVyIHRoZSBDb25zdW1lciBpcyBhY3R1YWxseSByZWNlaXZpbmcgbWVkaWEuXG5cdCAqXG5cdCAqIEByZXR1cm4ge0Jvb2xlYW59XG5cdCAqL1xuXHRnZXQgYWN0aXZlKClcblx0e1xuXHRcdHJldHVybiAoIXRoaXMuX2Nsb3NlZCAmJiB0aGlzLmhhbmRsZWQgPT09IHRydWUgJiYgIXRoaXMucGF1c2VkKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBDbG9zZXMgdGhlIENvbnN1bWVyLlxuXHQgKiBUaGlzIGlzIGNhbGxlZCB3aGVuIHRoZSBsb2NhbCBSb29tIGlzIGNsb3NlZC5cblx0ICpcblx0ICogQHByaXZhdGVcblx0ICovXG5cdGNsb3NlKClcblx0e1xuXHRcdGxvZ2dlci5kZWJ1ZygnY2xvc2UoKScpO1xuXG5cdFx0aWYgKHRoaXMuX2Nsb3NlZClcblx0XHRcdHJldHVybjtcblxuXHRcdHRoaXMuX2Nsb3NlZCA9IHRydWU7XG5cblx0XHR0aGlzLmVtaXQoJ0BjbG9zZScsICdsb2NhbCcpO1xuXHRcdHRoaXMuc2FmZUVtaXQoJ2Nsb3NlZCcsICdsb2NhbCcpO1xuXG5cdFx0dGhpcy5fZGVzdHJveSgpO1xuXHR9XG5cblx0LyoqXG5cdCAqIE15IHJlbW90ZSBDb25zdW1lciB3YXMgY2xvc2VkLlxuXHQgKiBJbnZva2VkIHZpYSByZW1vdGUgbm90aWZpY2F0aW9uLlxuXHQgKlxuXHQgKiBAcHJpdmF0ZVxuXHQgKlxuXHQgKiBAcGFyYW0ge0FueX0gW2FwcERhdGFdIC0gQXBwIGN1c3RvbSBkYXRhLlxuXHQgKi9cblx0cmVtb3RlQ2xvc2UoYXBwRGF0YSlcblx0e1xuXHRcdGxvZ2dlci5kZWJ1ZygncmVtb3RlQ2xvc2UoKScpO1xuXG5cdFx0aWYgKHRoaXMuX2Nsb3NlZClcblx0XHRcdHJldHVybjtcblxuXHRcdHRoaXMuX2Nsb3NlZCA9IHRydWU7XG5cblx0XHR0aGlzLmVtaXQoJ0BjbG9zZScsICdyZW1vdGUnKTtcblx0XHR0aGlzLnNhZmVFbWl0KCdjbG9zZWQnLCAncmVtb3RlJywgYXBwRGF0YSk7XG5cblx0XHR0aGlzLl9kZXN0cm95KCk7XG5cdH1cblxuXHRfZGVzdHJveSgpXG5cdHtcblx0XHR0aGlzLl9oYW5kbGVkID0gZmFsc2U7XG5cblx0XHR0cnkgeyB0aGlzLl90cmFjay5zdG9wKCk7IH1cblx0XHRjYXRjaCAoZXJyb3IpIHt9XG5cblx0XHR0aGlzLl90cmFjayA9IG51bGw7XG5cdH1cblxuXHQvKipcblx0ICogUGF1c2VzIHJlY2VpdmluZyBtZWRpYS5cblx0ICpcblx0ICogQHBhcmFtIHtBbnl9IFthcHBEYXRhXSAtIEFwcCBjdXN0b20gZGF0YS5cblx0ICpcblx0ICogQHJldHVybiB7Qm9vbGVhbn0gdHJ1ZSBpZiBwYXVzZWQuXG5cdCAqL1xuXHRwYXVzZShhcHBEYXRhKVxuXHR7XG5cdFx0bG9nZ2VyLmRlYnVnKCdwYXVzZSgpJyk7XG5cblx0XHRpZiAodGhpcy5fY2xvc2VkKVxuXHRcdHtcblx0XHRcdGxvZ2dlci5lcnJvcigncGF1c2UoKSB8IENvbnN1bWVyIGNsb3NlZCcpO1xuXG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fVxuXHRcdGVsc2UgaWYgKCF0aGlzLl9oYW5kbGVkKVxuXHRcdHtcblx0XHRcdGxvZ2dlci5lcnJvcigncGF1c2UoKSB8IENvbnN1bWVyIG5vdCBoYW5kbGVkJyk7XG5cblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9XG5cdFx0ZWxzZSBpZiAodGhpcy5fbG9jYWxseVBhdXNlZClcblx0XHR7XG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHR9XG5cblx0XHR0aGlzLl9sb2NhbGx5UGF1c2VkID0gdHJ1ZTtcblx0XHR0aGlzLl90cmFjay5lbmFibGVkID0gZmFsc2U7XG5cblx0XHR0aGlzLmVtaXQoJ0BwYXVzZScsIGFwcERhdGEpO1xuXG5cdFx0aWYgKCF0aGlzLl9yZW1vdGVseVBhdXNlZClcblx0XHRcdHRoaXMuc2FmZUVtaXQoJ3BhdXNlZCcsICdsb2NhbCcsIGFwcERhdGEpO1xuXG5cdFx0Ly8gUmV0dXJuIHRydWUgaWYgcmVhbGx5IHBhdXNlZC5cblx0XHRyZXR1cm4gdGhpcy5wYXVzZWQ7XG5cdH1cblxuXHQvKipcblx0ICogTXkgcmVtb3RlIENvbnN1bWVyIHdhcyBwYXVzZWQuXG5cdCAqIEludm9rZWQgdmlhIHJlbW90ZSBub3RpZmljYXRpb24uXG5cdCAqXG5cdCAqIEBwcml2YXRlXG5cdCAqXG5cdCAqIEBwYXJhbSB7QW55fSBbYXBwRGF0YV0gLSBBcHAgY3VzdG9tIGRhdGEuXG5cdCAqL1xuXHRyZW1vdGVQYXVzZShhcHBEYXRhKVxuXHR7XG5cdFx0bG9nZ2VyLmRlYnVnKCdyZW1vdGVQYXVzZSgpJyk7XG5cblx0XHRpZiAodGhpcy5fY2xvc2VkIHx8IHRoaXMuX3JlbW90ZWx5UGF1c2VkKVxuXHRcdFx0cmV0dXJuO1xuXG5cdFx0dGhpcy5fcmVtb3RlbHlQYXVzZWQgPSB0cnVlO1xuXG5cdFx0aWYgKHRoaXMuX3RyYWNrKVxuXHRcdFx0dGhpcy5fdHJhY2suZW5hYmxlZCA9IGZhbHNlO1xuXG5cdFx0aWYgKCF0aGlzLl9sb2NhbGx5UGF1c2VkKVxuXHRcdFx0dGhpcy5zYWZlRW1pdCgncGF1c2VkJywgJ3JlbW90ZScsIGFwcERhdGEpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJlc3VtZXMgcmVjZWl2aW5nIG1lZGlhLlxuXHQgKlxuXHQgKiBAcGFyYW0ge0FueX0gW2FwcERhdGFdIC0gQXBwIGN1c3RvbSBkYXRhLlxuXHQgKlxuXHQgKiBAcmV0dXJuIHtCb29sZWFufSB0cnVlIGlmIG5vdCBwYXVzZWQuXG5cdCAqL1xuXHRyZXN1bWUoYXBwRGF0YSlcblx0e1xuXHRcdGxvZ2dlci5kZWJ1ZygncmVzdW1lKCknKTtcblxuXHRcdGlmICh0aGlzLl9jbG9zZWQpXG5cdFx0e1xuXHRcdFx0bG9nZ2VyLmVycm9yKCdyZXN1bWUoKSB8IENvbnN1bWVyIGNsb3NlZCcpO1xuXG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fVxuXHRcdGVsc2UgaWYgKCF0aGlzLl9oYW5kbGVkKVxuXHRcdHtcblx0XHRcdGxvZ2dlci5lcnJvcigncGF1c2UoKSB8IENvbnN1bWVyIG5vdCBoYW5kbGVkJyk7XG5cblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9XG5cdFx0ZWxzZSBpZiAoIXRoaXMuX2xvY2FsbHlQYXVzZWQpXG5cdFx0e1xuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fVxuXG5cdFx0dGhpcy5fbG9jYWxseVBhdXNlZCA9IGZhbHNlO1xuXG5cdFx0dGhpcy5lbWl0KCdAcmVzdW1lJywgYXBwRGF0YSk7XG5cblx0XHRpZiAoIXRoaXMuX3JlbW90ZWx5UGF1c2VkKVxuXHRcdHtcblx0XHRcdHRoaXMuX3RyYWNrLmVuYWJsZWQgPSB0cnVlO1xuXG5cdFx0XHR0aGlzLnNhZmVFbWl0KCdyZXN1bWVkJywgJ2xvY2FsJywgYXBwRGF0YSk7XG5cdFx0fVxuXG5cdFx0Ly8gUmV0dXJuIHRydWUgaWYgbm90IHBhdXNlZC5cblx0XHRyZXR1cm4gIXRoaXMucGF1c2VkO1xuXHR9XG5cblx0LyoqXG5cdCAqIE15IHJlbW90ZSBDb25zdW1lciB3YXMgcmVzdW1lZC5cblx0ICogSW52b2tlZCB2aWEgcmVtb3RlIG5vdGlmaWNhdGlvbi5cblx0ICpcblx0ICogQHByaXZhdGVcblx0ICpcblx0ICogQHBhcmFtIHtBbnl9IFthcHBEYXRhXSAtIEFwcCBjdXN0b20gZGF0YS5cblx0ICovXG5cdHJlbW90ZVJlc3VtZShhcHBEYXRhKVxuXHR7XG5cdFx0bG9nZ2VyLmRlYnVnKCdyZW1vdGVSZXN1bWUoKScpO1xuXG5cdFx0aWYgKHRoaXMuX2Nsb3NlZCB8fCAhdGhpcy5fcmVtb3RlbHlQYXVzZWQpXG5cdFx0XHRyZXR1cm47XG5cblx0XHR0aGlzLl9yZW1vdGVseVBhdXNlZCA9IGZhbHNlO1xuXG5cdFx0aWYgKCF0aGlzLl9sb2NhbGx5UGF1c2VkKVxuXHRcdHtcblx0XHRcdGlmICh0aGlzLl90cmFjaylcblx0XHRcdFx0dGhpcy5fdHJhY2suZW5hYmxlZCA9IGZhbHNlO1xuXG5cdFx0XHR0aGlzLnNhZmVFbWl0KCdyZXN1bWVkJywgJ3JlbW90ZScsIGFwcERhdGEpO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBNYXJrIHRoaXMgQ29uc3VtZXIgYXMgc3VpdGFibGUgZm9yIHJlY2VwdGlvbiBvciBub3QuXG5cdCAqXG5cdCAqIEBwcml2YXRlXG5cdCAqXG5cdCAqIEBwYXJhbSB7Qm9vbGVhbn0gZmxhZ1xuXHQgKi9cblx0c2V0U3VwcG9ydGVkKGZsYWcpXG5cdHtcblx0XHR0aGlzLl9zdXBwb3J0ZWQgPSBmbGFnO1xuXHR9XG5cblx0LyoqXG5cdCAqIFNldCB0aGlzIENvbnN1bWVyIGFzIGhhbmRsZWQgb3IgdW5oYW5kbGVkIGJ5IGEgVHJhbnNwb3J0LlxuXHQgKlxuXHQgKiBAcHJpdmF0ZVxuXHQgKlxuXHQgKiBAcGFyYW0ge0Jvb2xlYW58U3RyaW5nfSBmbGFnIC0gSWYgJ3RtcCcgKFN0cmluZykgaXQncyBjb25zaWRlcmVkIGFzIHRlcm1wb3JhbC5cblx0ICogQHBhcmFtIHt0cmFja30gTWVkaWFTdHJlYW1UcmFja1xuXHQgKi9cblx0c2V0SGFuZGxlZChmbGFnLCB0cmFjaylcblx0e1xuXHRcdGlmICh0aGlzLl9jbG9zZWQpXG5cdFx0XHRyZXR1cm47XG5cblx0XHRjb25zdCBwcmV2aW91cyA9IHRoaXMuX2hhbmRsZWQ7XG5cblx0XHR0aGlzLl9oYW5kbGVkID0gZmxhZztcblx0XHR0aGlzLl90cmFjayA9IHRyYWNrIHx8IG51bGw7XG5cblx0XHRpZiAodHJhY2sgJiYgdGhpcy5wYXVzZWQpXG5cdFx0XHR0aGlzLl90cmFjay5lbmFibGVkID0gZmFsc2U7XG5cblx0XHRpZiAoZmxhZyA9PT0gZmFsc2UgfHwgZmxhZyA9PT0gJ3RtcCcpXG5cdFx0e1xuXHRcdFx0dHJ5IHsgdGhpcy5fdHJhY2suc3RvcCgpOyB9XG5cdFx0XHRjYXRjaCAoZXJyb3IpIHt9XG5cblx0XHRcdHRoaXMuX3RyYWNrID0gbnVsbDtcblx0XHR9XG5cblx0XHRpZiAocHJldmlvdXMgPT09IHRydWUgJiYgZmxhZyA9PT0gZmFsc2UpXG5cdFx0XHR0aGlzLnNhZmVFbWl0KCd1bmhhbmRsZWQnKTtcblx0fVxufVxuIiwiaW1wb3J0IGJvd3NlciBmcm9tICdib3dzZXInO1xuaW1wb3J0IExvZ2dlciBmcm9tICcuL0xvZ2dlcic7XG5pbXBvcnQgQ2hyb21lNTUgZnJvbSAnLi9oYW5kbGVycy9DaHJvbWU1NSc7XG5pbXBvcnQgU2FmYXJpMTEgZnJvbSAnLi9oYW5kbGVycy9TYWZhcmkxMSc7XG5pbXBvcnQgRmlyZWZveDUwIGZyb20gJy4vaGFuZGxlcnMvRmlyZWZveDUwJztcbmltcG9ydCBFZGdlMTEgZnJvbSAnLi9oYW5kbGVycy9FZGdlMTEnO1xuXG5jb25zdCBsb2dnZXIgPSBuZXcgTG9nZ2VyKCdEZXZpY2UnKTtcblxuLyoqXG4gKiBDbGFzcyB3aXRoIHN0YXRpYyBtZW1iZXJzIHJlcHJlc2VudGluZyB0aGUgdW5kZXJseWluZyBkZXZpY2Ugb3IgYnJvd3Nlci5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgRGV2aWNlXG57XG5cdC8qKlxuXHQgKiBHZXQgdGhlIGRldmljZSBuYW1lLlxuXHQgKlxuXHQgKiBAcmV0dXJuIHtTdHJpbmd9XG5cdCAqL1xuXHRzdGF0aWMgZ2V0IG5hbWUoKVxuXHR7XG5cdFx0aWYgKCFEZXZpY2UuX2RldGVjdGVkKVxuXHRcdFx0RGV2aWNlLl9kZXRlY3QoKTtcblxuXHRcdHJldHVybiBEZXZpY2UuX25hbWU7XG5cdH1cblxuXHQvKipcblx0ICogR2V0IHRoZSBkZXZpY2UgdmVyc2lvbi5cblx0ICpcblx0ICogQHJldHVybiB7U3RyaW5nfVxuXHQgKi9cblx0c3RhdGljIGdldCB2ZXJzaW9uKClcblx0e1xuXHRcdGlmICghRGV2aWNlLl9kZXRlY3RlZClcblx0XHRcdERldmljZS5fZGV0ZWN0KCk7XG5cblx0XHRyZXR1cm4gRGV2aWNlLl92ZXJzaW9uO1xuXHR9XG5cblx0LyoqXG5cdCAqIFdoZXRoZXIgdGhpcyBkZXZpY2UgaXMgc3VwcG9ydGVkLlxuXHQgKlxuXHQgKiBAcmV0dXJuIHtCb29sZWFufVxuXHQgKi9cblx0c3RhdGljIGlzU3VwcG9ydGVkKClcblx0e1xuXHRcdGlmICghRGV2aWNlLl9kZXRlY3RlZClcblx0XHRcdERldmljZS5fZGV0ZWN0KCk7XG5cblx0XHRyZXR1cm4gQm9vbGVhbihEZXZpY2UuX2hhbmRsZXJDbGFzcyk7XG5cdH1cblxuXHQvKipcblx0ICogUmV0dXJucyBhIHN1aXRhYmxlIFdlYlJUQyBoYW5kbGVyIGNsYXNzLlxuXHQgKlxuXHQgKiBAdHlwZSB7Q2xhc3N9XG5cdCAqL1xuXHRzdGF0aWMgZ2V0IEhhbmRsZXIoKVxuXHR7XG5cdFx0aWYgKCFEZXZpY2UuX2RldGVjdGVkKVxuXHRcdFx0RGV2aWNlLl9kZXRlY3QoKTtcblxuXHRcdHJldHVybiBEZXZpY2UuX2hhbmRsZXJDbGFzcztcblx0fVxuXG5cdC8qKlxuXHQgKiBEZXRlY3RzIHRoZSBjdXJyZW50IGRldmljZS9icm93c2VyLlxuXHQgKlxuXHQgKiBAcHJpdmF0ZVxuXHQgKi9cblx0c3RhdGljIF9kZXRlY3QoKVxuXHR7XG5cdFx0Y29uc3QgdWEgPSBnbG9iYWwubmF2aWdhdG9yLnVzZXJBZ2VudDtcblx0XHRjb25zdCBicm93c2VyID0gYm93c2VyLl9kZXRlY3QodWEpO1xuXG5cdFx0RGV2aWNlLl9kZXRlY3RlZCA9IHRydWU7XG5cdFx0RGV2aWNlLl9uYW1lID0gYnJvd3Nlci5uYW1lIHx8ICd1bmtub3duIGRldmljZSc7XG5cdFx0RGV2aWNlLl92ZXJzaW9uID0gYnJvd3Nlci52ZXJzaW9uIHx8ICd1bmtub3duIHZlc2lvbic7XG5cdFx0RGV2aWNlLl9oYW5kbGVyQ2xhc3MgPSBudWxsO1xuXG5cdFx0Ly8gQ2hyb21lLCBDaHJvbWl1bSwgT3BlcmEgKGRlc2t0b3AgYW5kIG1vYmlsZSkuXG5cdFx0aWYgKGJvd3Nlci5jaGVjayh7IGNocm9tZTogJzU1JywgY2hyb21pdW06ICc1NScsIG9wZXJhOiAnNDQnIH0sIHRydWUsIHVhKSlcblx0XHR7XG5cdFx0XHREZXZpY2UuX2hhbmRsZXJDbGFzcyA9IENocm9tZTU1O1xuXHRcdH1cblx0XHQvLyBTYWZhcmkgKGRlc2t0b3AgYW5kIG1vYmlsZSkuXG5cdFx0ZWxzZSBpZiAoYm93c2VyLmNoZWNrKHsgc2FmYXJpOiAnMTEnIH0sIHRydWUsIHVhKSlcblx0XHR7XG5cdFx0XHREZXZpY2UuX2hhbmRsZXJDbGFzcyA9IFNhZmFyaTExO1xuXHRcdH1cblx0XHQvLyBGaXJlZm94IChkZXNrdG9wIGFuZCBtb2JpbGUpLlxuXHRcdGVsc2UgaWYgKGJvd3Nlci5jaGVjayh7IGZpcmVmb3g6ICc1MCcgfSwgdHJ1ZSwgdWEpKVxuXHRcdHtcblx0XHRcdERldmljZS5faGFuZGxlckNsYXNzID0gRmlyZWZveDUwO1xuXHRcdH1cblx0XHQvLyBFZGdlIChkZXNrdG9wKS5cblx0XHRlbHNlIGlmIChib3dzZXIuY2hlY2soeyBtc2VkZ2U6ICcxMScgfSwgdHJ1ZSwgdWEpKVxuXHRcdHtcblx0XHRcdERldmljZS5faGFuZGxlckNsYXNzID0gRWRnZTExO1xuXHRcdH1cblxuXHRcdC8vIFRPRE86IE1vcmUgZGV2aWNlcy5cblxuXHRcdGlmIChEZXZpY2UuaXNTdXBwb3J0ZWQoKSlcblx0XHR7XG5cdFx0XHRsb2dnZXIuZGVidWcoXG5cdFx0XHRcdCdkZXZpY2Ugc3VwcG9ydGVkIFtuYW1lOiVzLCB2ZXJzaW9uOiVzLCBoYW5kbGVyOiVzXScsXG5cdFx0XHRcdERldmljZS5fbmFtZSwgRGV2aWNlLl92ZXJzaW9uLCBEZXZpY2UuX2hhbmRsZXJDbGFzcy5uYW1lKTtcblx0XHR9XG5cdFx0ZWxzZVxuXHRcdHtcblx0XHRcdGxvZ2dlci53YXJuKFxuXHRcdFx0XHQnZGV2aWNlIG5vdCBzdXBwb3J0ZWQgW25hbWU6JXMsIHZlcnNpb246JXNdJyxcblx0XHRcdFx0RGV2aWNlLl9uYW1lLCBEZXZpY2UuX3ZlcnNpb24pO1xuXHRcdH1cblx0fVxufVxuXG4vLyBJbml0aWFsaXplZCBmbGFnLlxuLy8gQHR5cGUge0Jvb2xlYW59XG5EZXZpY2UuX2RldGVjdGVkID0gZmFsc2U7XG5cbi8vIERldmljZSBuYW1lLlxuLy8gQHR5cGUge1N0cmluZ31cbkRldmljZS5fbmFtZSA9IHVuZGVmaW5lZDtcblxuLy8gRGV2aWNlIHZlcnNpb24uXG4vLyBAdHlwZSB7U3RyaW5nfVxuRGV2aWNlLl92ZXJzaW9uID0gdW5kZWZpbmVkO1xuXG4vLyBXZWJSVEMgaGFuZGVyIGZvciB0aGlzIGRldmljZS5cbi8vIEB0eXBlIHtDbGFzc31cbkRldmljZS5faGFuZGxlckNsYXNzID0gbnVsbDtcbiIsImltcG9ydCB7IEV2ZW50RW1pdHRlciB9IGZyb20gJ2V2ZW50cyc7XG5pbXBvcnQgTG9nZ2VyIGZyb20gJy4vTG9nZ2VyJztcblxuY29uc3QgbG9nZ2VyID0gbmV3IExvZ2dlcignRW5oYW5jZWRFdmVudEVtaXR0ZXInKTtcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgRW5oYW5jZWRFdmVudEVtaXR0ZXIgZXh0ZW5kcyBFdmVudEVtaXR0ZXJcbntcblx0Y29uc3RydWN0b3IoKVxuXHR7XG5cdFx0c3VwZXIoKTtcblx0XHR0aGlzLnNldE1heExpc3RlbmVycyhJbmZpbml0eSk7XG5cdH1cblxuXHRzYWZlRW1pdChldmVudCwgLi4uYXJncylcblx0e1xuXHRcdHRyeVxuXHRcdHtcblx0XHRcdHRoaXMuZW1pdChldmVudCwgLi4uYXJncyk7XG5cdFx0fVxuXHRcdGNhdGNoIChlcnJvcilcblx0XHR7XG5cdFx0XHRsb2dnZXIuZXJyb3IoJ2V2ZW50IGxpc3RlbmVyIHRocmV3IGFuIGVycm9yIFtldmVudDolc106ICVvJyxcblx0XHRcdFx0ZXZlbnQsIGVycm9yKTtcblx0XHR9XG5cdH1cblxuXHRzYWZlRW1pdEFzUHJvbWlzZSguLi5hcmdzKVxuXHR7XG5cdFx0cmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+XG5cdFx0e1xuXHRcdFx0Y29uc3QgY2FsbGJhY2sgPSAocmVzdWx0KSA9PlxuXHRcdFx0e1xuXHRcdFx0XHRyZXNvbHZlKHJlc3VsdCk7XG5cdFx0XHR9O1xuXG5cdFx0XHRjb25zdCBlcnJiYWNrID0gKGVycm9yKSA9PlxuXHRcdFx0e1xuXHRcdFx0XHRyZWplY3QoZXJyb3IpO1xuXHRcdFx0fTtcblxuXHRcdFx0dGhpcy5zYWZlRW1pdCguLi5hcmdzLCBjYWxsYmFjaywgZXJyYmFjayk7XG5cdFx0fSk7XG5cdH1cbn1cbiIsImltcG9ydCBkZWJ1ZyBmcm9tICdkZWJ1Zyc7XG5cbmNvbnN0IEFQUF9OQU1FID0gJ21lZGlhc291cC1jbGllbnQnO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBMb2dnZXJcbntcblx0Y29uc3RydWN0b3IocHJlZml4KVxuXHR7XG5cdFx0aWYgKHByZWZpeClcblx0XHR7XG5cdFx0XHR0aGlzLl9kZWJ1ZyA9IGRlYnVnKGAke0FQUF9OQU1FfToke3ByZWZpeH1gKTtcblx0XHRcdHRoaXMuX3dhcm4gPSBkZWJ1ZyhgJHtBUFBfTkFNRX06V0FSTjoke3ByZWZpeH1gKTtcblx0XHRcdHRoaXMuX2Vycm9yID0gZGVidWcoYCR7QVBQX05BTUV9OkVSUk9SOiR7cHJlZml4fWApO1xuXHRcdH1cblx0XHRlbHNlXG5cdFx0e1xuXHRcdFx0dGhpcy5fZGVidWcgPSBkZWJ1ZyhBUFBfTkFNRSk7XG5cdFx0XHR0aGlzLl93YXJuID0gZGVidWcoYCR7QVBQX05BTUV9OldBUk5gKTtcblx0XHRcdHRoaXMuX2Vycm9yID0gZGVidWcoYCR7QVBQX05BTUV9OkVSUk9SYCk7XG5cdFx0fVxuXG5cdFx0LyogZXNsaW50LWRpc2FibGUgbm8tY29uc29sZSAqL1xuXHRcdHRoaXMuX2RlYnVnLmxvZyA9IGNvbnNvbGUuaW5mby5iaW5kKGNvbnNvbGUpO1xuXHRcdHRoaXMuX3dhcm4ubG9nID0gY29uc29sZS53YXJuLmJpbmQoY29uc29sZSk7XG5cdFx0dGhpcy5fZXJyb3IubG9nID0gY29uc29sZS5lcnJvci5iaW5kKGNvbnNvbGUpO1xuXHRcdC8qIGVzbGludC1lbmFibGUgbm8tY29uc29sZSAqL1xuXHR9XG5cblx0Z2V0IGRlYnVnKClcblx0e1xuXHRcdHJldHVybiB0aGlzLl9kZWJ1Zztcblx0fVxuXG5cdGdldCB3YXJuKClcblx0e1xuXHRcdHJldHVybiB0aGlzLl93YXJuO1xuXHR9XG5cblx0Z2V0IGVycm9yKClcblx0e1xuXHRcdHJldHVybiB0aGlzLl9lcnJvcjtcblx0fVxufVxuIiwiaW1wb3J0IExvZ2dlciBmcm9tICcuL0xvZ2dlcic7XG5pbXBvcnQgRW5oYW5jZWRFdmVudEVtaXR0ZXIgZnJvbSAnLi9FbmhhbmNlZEV2ZW50RW1pdHRlcic7XG5cbmNvbnN0IGxvZ2dlciA9IG5ldyBMb2dnZXIoJ1BlZXInKTtcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgUGVlciBleHRlbmRzIEVuaGFuY2VkRXZlbnRFbWl0dGVyXG57XG5cdC8qKlxuXHQgKiBAcHJpdmF0ZVxuXHQgKlxuXHQgKiBAZW1pdHMge2NvbnN1bWVyOiBDb25zdW1lcn0gbmV3Y29uc3VtZXJcblx0ICogQGVtaXRzIHtvcmlnaW5hdG9yOiBTdHJpbmcsIFthcHBEYXRhXTogQW55fSBjbG9zZWRcblx0ICogQGVtaXRzIHtvcmlnaW5hdG9yOiBTdHJpbmd9IEBjbG9zZVxuXHQgKi9cblx0Y29uc3RydWN0b3IobmFtZSwgYXBwRGF0YSlcblx0e1xuXHRcdHN1cGVyKCk7XG5cblx0XHQvLyBOYW1lLlxuXHRcdC8vIEB0eXBlIHtTdHJpbmd9XG5cdFx0dGhpcy5fbmFtZSA9IG5hbWU7XG5cblx0XHQvLyBDbG9zZWQgZmxhZy5cblx0XHQvLyBAdHlwZSB7Qm9vbGVhbn1cblx0XHR0aGlzLl9jbG9zZWQgPSBmYWxzZTtcblxuXHRcdC8vIEFwcCBjdXN0b20gZGF0YS5cblx0XHQvLyBAdHlwZSB7QW55fVxuXHRcdHRoaXMuX2FwcERhdGEgPSBhcHBEYXRhO1xuXG5cdFx0Ly8gTWFwIG9mIENvbnN1bWVycyBpbmRleGVkIGJ5IGlkLlxuXHRcdC8vIEB0eXBlIHttYXA8TnVtYmVyLCBDb25zdW1lcj59XG5cdFx0dGhpcy5fY29uc3VtZXJzID0gbmV3IE1hcCgpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFBlZXIgbmFtZS5cblx0ICpcblx0ICogQHJldHVybiB7U3RyaW5nfVxuXHQgKi9cblx0Z2V0IG5hbWUoKVxuXHR7XG5cdFx0cmV0dXJuIHRoaXMuX25hbWU7XG5cdH1cblxuXHQvKipcblx0ICogV2hldGhlciB0aGUgUGVlciBpcyBjbG9zZWQuXG5cdCAqXG5cdCAqIEByZXR1cm4ge0Jvb2xlYW59XG5cdCAqL1xuXHRnZXQgY2xvc2VkKClcblx0e1xuXHRcdHJldHVybiB0aGlzLl9jbG9zZWQ7XG5cdH1cblxuXHQvKipcblx0ICogQXBwIGN1c3RvbSBkYXRhLlxuXHQgKlxuXHQgKiBAcmV0dXJuIHtBbnl9XG5cdCAqL1xuXHRnZXQgYXBwRGF0YSgpXG5cdHtcblx0XHRyZXR1cm4gdGhpcy5fYXBwRGF0YTtcblx0fVxuXG5cdC8qKlxuXHQgKiBUaGUgbGlzdCBvZiBDb25zdW1lcnMuXG5cdCAqXG5cdCAqIEByZXR1cm4ge0FycmF5PENvbnN1bWVyPn1cblx0ICovXG5cdGdldCBjb25zdW1lcnMoKVxuXHR7XG5cdFx0cmV0dXJuIEFycmF5LmZyb20odGhpcy5fY29uc3VtZXJzLnZhbHVlcygpKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBDbG9zZXMgdGhlIFBlZXIuXG5cdCAqIFRoaXMgaXMgY2FsbGVkIHdoZW4gdGhlIGxvY2FsIFJvb20gaXMgY2xvc2VkLlxuXHQgKlxuXHQgKiBAcHJpdmF0ZVxuXHQgKi9cblx0Y2xvc2UoKVxuXHR7XG5cdFx0bG9nZ2VyLmRlYnVnKCdjbG9zZSgpJyk7XG5cblx0XHRpZiAodGhpcy5fY2xvc2VkKVxuXHRcdFx0cmV0dXJuO1xuXG5cdFx0dGhpcy5fY2xvc2VkID0gdHJ1ZTtcblxuXHRcdHRoaXMuZW1pdCgnQGNsb3NlJywgJ2xvY2FsJyk7XG5cdFx0dGhpcy5zYWZlRW1pdCgnY2xvc2VkJywgJ2xvY2FsJyk7XG5cblx0XHQvLyBDbG9zZSBhbGwgdGhlIENvbnN1bWVycy5cblx0XHRmb3IgKGNvbnN0IGNvbnN1bWVyIG9mIHRoaXMuX2NvbnN1bWVycy52YWx1ZXMoKSlcblx0XHR7XG5cdFx0XHRjb25zdW1lci5jbG9zZSgpO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBUaGUgcmVtb3RlIFBlZXIgb3IgUm9vbSB3YXMgY2xvc2VkLlxuXHQgKiBJbnZva2VkIHZpYSByZW1vdGUgbm90aWZpY2F0aW9uLlxuXHQgKlxuXHQgKiBAcHJpdmF0ZVxuXHQgKlxuXHQgKiBAcGFyYW0ge0FueX0gW2FwcERhdGFdIC0gQXBwIGN1c3RvbSBkYXRhLlxuXHQgKi9cblx0cmVtb3RlQ2xvc2UoYXBwRGF0YSlcblx0e1xuXHRcdGxvZ2dlci5kZWJ1ZygncmVtb3RlQ2xvc2UoKScpO1xuXG5cdFx0aWYgKHRoaXMuX2Nsb3NlZClcblx0XHRcdHJldHVybjtcblxuXHRcdHRoaXMuX2Nsb3NlZCA9IHRydWU7XG5cblx0XHR0aGlzLmVtaXQoJ0BjbG9zZScsICdyZW1vdGUnKTtcblx0XHR0aGlzLnNhZmVFbWl0KCdjbG9zZWQnLCAncmVtb3RlJywgYXBwRGF0YSk7XG5cblx0XHQvLyBDbG9zZSBhbGwgdGhlIENvbnN1bWVycy5cblx0XHRmb3IgKGNvbnN0IGNvbnN1bWVyIG9mIHRoaXMuX2NvbnN1bWVycy52YWx1ZXMoKSlcblx0XHR7XG5cdFx0XHRjb25zdW1lci5yZW1vdGVDbG9zZSgpO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBHZXQgdGhlIENvbnN1bWVyIHdpdGggdGhlIGdpdmVuIGlkLlxuXHQgKlxuXHQgKiBAcGFyYW0ge051bWJlcn0gaWRcblx0ICpcblx0ICogQHJldHVybiB7Q29uc3VtZXJ9XG5cdCAqL1xuXHRnZXRDb25zdW1lckJ5SWQoaWQpXG5cdHtcblx0XHRyZXR1cm4gdGhpcy5fY29uc3VtZXJzLmdldChpZCk7XG5cdH1cblxuXHQvKipcblx0ICogQWRkIGFuIGFzc29jaWF0ZWQgQ29uc3VtZXIuXG5cdCAqXG5cdCAqIEBwcml2YXRlXG5cdCAqXG5cdCAqIEBwYXJhbSB7Q29uc3VtZXJ9IGNvbnN1bWVyXG5cdCAqL1xuXHRhZGRDb25zdW1lcihjb25zdW1lcilcblx0e1xuXHRcdGlmICh0aGlzLl9jb25zdW1lcnMuaGFzKGNvbnN1bWVyLmlkKSlcblx0XHRcdHRocm93IG5ldyBFcnJvcihgQ29uc3VtZXIgYWxyZWFkeSBleGlzdHMgW2lkOiR7Y29uc3VtZXIuaWR9XWApO1xuXG5cdFx0Ly8gU3RvcmUgaXQuXG5cdFx0dGhpcy5fY29uc3VtZXJzLnNldChjb25zdW1lci5pZCwgY29uc3VtZXIpO1xuXG5cdFx0Ly8gSGFuZGxlIGl0LlxuXHRcdGNvbnN1bWVyLm9uKCdAY2xvc2UnLCAoKSA9PlxuXHRcdHtcblx0XHRcdHRoaXMuX2NvbnN1bWVycy5kZWxldGUoY29uc3VtZXIuaWQpO1xuXHRcdH0pO1xuXG5cdFx0Ly8gRW1pdCBldmVudC5cblx0XHR0aGlzLnNhZmVFbWl0KCduZXdjb25zdW1lcicsIGNvbnN1bWVyKTtcblx0fVxufVxuIiwiaW1wb3J0IExvZ2dlciBmcm9tICcuL0xvZ2dlcic7XG5pbXBvcnQgRW5oYW5jZWRFdmVudEVtaXR0ZXIgZnJvbSAnLi9FbmhhbmNlZEV2ZW50RW1pdHRlcic7XG5pbXBvcnQgKiBhcyB1dGlscyBmcm9tICcuL3V0aWxzJztcblxuY29uc3QgbG9nZ2VyID0gbmV3IExvZ2dlcignUHJvZHVjZXInKTtcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgUHJvZHVjZXIgZXh0ZW5kcyBFbmhhbmNlZEV2ZW50RW1pdHRlclxue1xuXHQvKipcblx0ICogQHByaXZhdGVcblx0ICpcblx0ICogQGVtaXRzIHtvcmlnaW5hdG9yOiBTdHJpbmcsIFthcHBEYXRhXTogQW55fSBwYXVzZWRcblx0ICogQGVtaXRzIHtvcmlnaW5hdG9yOiBTdHJpbmcsIFthcHBEYXRhXTogQW55fSByZXN1bWVkXG5cdCAqIEBlbWl0cyB1bmhhbmRsZWRcblx0ICogQGVtaXRzIHtvcmlnaW5hdG9yOiBTdHJpbmcsIFthcHBEYXRhXTogQW55fSBjbG9zZWRcblx0ICpcblx0ICogQGVtaXRzIHtbYXBwRGF0YV06IEFueX0gQHBhdXNlXG5cdCAqIEBlbWl0cyB7W2FwcERhdGFdOiBBbnl9IEByZXN1bWVcblx0ICogQGVtaXRzIHtvcmlnaW5hdG9yOiBTdHJpbmcsIFthcHBEYXRhXTogQW55fSBAY2xvc2Vcblx0ICpcblx0ICovXG5cdGNvbnN0cnVjdG9yKHRyYWNrLCBhcHBEYXRhKVxuXHR7XG5cdFx0c3VwZXIoKTtcblxuXHRcdC8vIElkLlxuXHRcdC8vIEB0eXBlIHtOdW1iZXJ9XG5cdFx0dGhpcy5faWQgPSB1dGlscy5yYW5kb21OdW1iZXIoKTtcblxuXHRcdC8vIENsb3NlZCBmbGFnLlxuXHRcdC8vIEB0eXBlIHtCb29sZWFufVxuXHRcdHRoaXMuX2Nsb3NlZCA9IGZhbHNlO1xuXG5cdFx0Ly8gT3JpZ2luYWwgdHJhY2suXG5cdFx0Ly8gQHR5cGUge01lZGlhU3RyZWFtVHJhY2t9XG5cdFx0dGhpcy5fb3JpZ2luYWxUcmFjayA9IHRyYWNrO1xuXG5cdFx0Ly8gVHJhY2sgY2xvbmVkIGZyb20gdGhlIG9yaWdpbmFsIG9uZS5cblx0XHQvLyBAdHlwZSB7TWVkaWFTdHJlYW1UcmFja31cblx0XHR0aGlzLl90cmFjayA9IHRyYWNrLmNsb25lKCk7XG5cblx0XHQvLyBBcHAgY3VzdG9tIGRhdGEuXG5cdFx0Ly8gQHR5cGUge0FueX1cblx0XHR0aGlzLl9hcHBEYXRhID0gYXBwRGF0YTtcblxuXHRcdC8vIFdoZXRoZXIgdGhpcyBQcm9kdWNlciBpcyBiZWluZyBoYW5kbGVkIGJ5IGEgVHJhbnNwb3J0LlxuXHRcdC8vIEB0eXBlIHtCb29sZWFufVxuXHRcdHRoaXMuX2hhbmRsZWQgPSBmYWxzZTtcblxuXHRcdC8vIFJUUCBwYXJhbWV0ZXJzLlxuXHRcdC8vIEB0eXBlIHtSVENSdHBQYXJhbWV0ZXJzfVxuXHRcdHRoaXMuX3J0cFBhcmFtZXRlcnMgPSBudWxsO1xuXG5cdFx0Ly8gTG9jYWxseSBwYXVzZWQgZmxhZy5cblx0XHQvLyBAdHlwZSB7Qm9vbGVhbn1cblx0XHR0aGlzLl9sb2NhbGx5UGF1c2VkID0gIXRoaXMuX3RyYWNrLmVuYWJsZWQ7XG5cblx0XHQvLyBSZW1vdGVseSBwYXVzZWQgZmxhZy5cblx0XHQvLyBAdHlwZSB7Qm9vbGVhbn1cblx0XHR0aGlzLl9yZW1vdGVseVBhdXNlZCA9IGZhbHNlO1xuXHR9XG5cblx0LyoqXG5cdCAqIENsYXNzIG5hbWUuXG5cdCAqXG5cdCAqIEByZXR1cm4ge1N0cmluZ31cblx0ICovXG5cdGdldCBrbGFzcygpXG5cdHtcblx0XHRyZXR1cm4gJ1Byb2R1Y2VyJztcblx0fVxuXG5cdC8qKlxuXHQgKiBQcm9kdWNlciBpZC5cblx0ICpcblx0ICogQHJldHVybiB7TnVtYmVyfVxuXHQgKi9cblx0Z2V0IGlkKClcblx0e1xuXHRcdHJldHVybiB0aGlzLl9pZDtcblx0fVxuXG5cdC8qKlxuXHQgKiBXaGV0aGVyIHRoZSBQcm9kdWNlciBpcyBjbG9zZWQuXG5cdCAqXG5cdCAqIEByZXR1cm4ge0Jvb2xlYW59XG5cdCAqL1xuXHRnZXQgY2xvc2VkKClcblx0e1xuXHRcdHJldHVybiB0aGlzLl9jbG9zZWQ7XG5cdH1cblxuXHQvKipcblx0ICogTWVkaWEga2luZC5cblx0ICpcblx0ICogQHJldHVybiB7U3RyaW5nfVxuXHQgKi9cblx0Z2V0IGtpbmQoKVxuXHR7XG5cdFx0cmV0dXJuIHRoaXMuX3RyYWNrLmtpbmQ7XG5cdH1cblxuXHQvKipcblx0ICogVGhlIGFzc29jaWF0ZWQgdHJhY2suXG5cdCAqXG5cdCAqIEByZXR1cm4ge01lZGlhU3RyZWFtVHJhY2t9XG5cdCAqL1xuXHRnZXQgdHJhY2soKVxuXHR7XG5cdFx0cmV0dXJuIHRoaXMuX3RyYWNrO1xuXHR9XG5cblx0LyoqXG5cdCAqIFRoZSBhc3NvY2lhdGVkIG9yaWdpbmFsIHRyYWNrLlxuXHQgKlxuXHQgKiBAcmV0dXJuIHtNZWRpYVN0cmVhbVRyYWNrfVxuXHQgKi9cblx0Z2V0IG9yaWdpbmFsVHJhY2soKVxuXHR7XG5cdFx0cmV0dXJuIHRoaXMuX29yaWdpbmFsVHJhY2s7XG5cdH1cblxuXHQvKipcblx0ICogQXBwIGN1c3RvbSBkYXRhLlxuXHQgKlxuXHQgKiBAcmV0dXJuIHtBbnl9XG5cdCAqL1xuXHRnZXQgYXBwRGF0YSgpXG5cdHtcblx0XHRyZXR1cm4gdGhpcy5fYXBwRGF0YTtcblx0fVxuXG5cdC8qKlxuXHQgKiBXaGV0aGVyIHRoaXMgaXMgYmVpbmcgaGFuZGxlZCBieSBhIFRyYW5zcG9ydC5cblx0ICpcblx0ICogQHJldHVybiB7Qm9vbGVhbn1cblx0ICovXG5cdGdldCBoYW5kbGVkKClcblx0e1xuXHRcdHJldHVybiBCb29sZWFuKHRoaXMuX2hhbmRsZWQpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJUUCBwYXJhbWV0ZXJzLlxuXHQgKlxuXHQgKiBAcmV0dXJuIHtSVENSdHBQYXJhbWV0ZXJzfVxuXHQgKi9cblx0Z2V0IHJ0cFBhcmFtZXRlcnMoKVxuXHR7XG5cdFx0cmV0dXJuIHRoaXMuX3J0cFBhcmFtZXRlcnM7XG5cdH1cblxuXHQvKipcblx0ICogV2hldGhlciB0aGUgUHJvZHVjZXIgaXMgbG9jYWxseSBwYXVzZWQuXG5cdCAqXG5cdCAqIEByZXR1cm4ge0Jvb2xlYW59XG5cdCAqL1xuXHRnZXQgbG9jYWxseVBhdXNlZCgpXG5cdHtcblx0XHRyZXR1cm4gdGhpcy5fbG9jYWxseVBhdXNlZDtcblx0fVxuXG5cdC8qKlxuXHQgKiBXaGV0aGVyIHRoZSBQcm9kdWNlciBpcyByZW1vdGVseSBwYXVzZWQuXG5cdCAqXG5cdCAqIEByZXR1cm4ge0Jvb2xlYW59XG5cdCAqL1xuXHRnZXQgcmVtb3RlbHlQYXVzZWQoKVxuXHR7XG5cdFx0cmV0dXJuIHRoaXMuX3JlbW90ZWx5UGF1c2VkO1xuXHR9XG5cblx0LyoqXG5cdCAqIFdoZXRoZXIgdGhlIFByb2R1Y2VyIGlzIHBhdXNlZC5cblx0ICpcblx0ICogQHJldHVybiB7Qm9vbGVhbn1cblx0ICovXG5cdGdldCBwYXVzZWQoKVxuXHR7XG5cdFx0cmV0dXJuIHRoaXMuX2xvY2FsbHlQYXVzZWQgfHwgdGhpcy5fcmVtb3RlbHlQYXVzZWQ7XG5cdH1cblxuXHQvKipcblx0ICogV2hldGhlciB0aGUgUHJvZHVjZXIgaXMgYWN0dWFsbHkgc2VuZGluZyBtZWRpYS5cblx0ICpcblx0ICogQHJldHVybiB7Qm9vbGVhbn1cblx0ICovXG5cdGdldCBhY3RpdmUoKVxuXHR7XG5cdFx0cmV0dXJuICghdGhpcy5fY2xvc2VkICYmIHRoaXMuaGFuZGxlZCA9PT0gdHJ1ZSAmJiAhdGhpcy5wYXVzZWQpO1xuXHR9XG5cblx0LyoqXG5cdCAqIENsb3NlcyB0aGUgUHJvZHVjZXIuXG5cdCAqXG5cdCAqIEBwYXJhbSB7QW55fSBbYXBwRGF0YV0gLSBBcHAgY3VzdG9tIGRhdGEuXG5cdCAqL1xuXHRjbG9zZShhcHBEYXRhKVxuXHR7XG5cdFx0bG9nZ2VyLmRlYnVnKCdjbG9zZSgpJyk7XG5cblx0XHRpZiAodGhpcy5fY2xvc2VkKVxuXHRcdFx0cmV0dXJuO1xuXG5cdFx0dGhpcy5fY2xvc2VkID0gdHJ1ZTtcblxuXHRcdHRoaXMuZW1pdCgnQGNsb3NlJywgJ2xvY2FsJywgYXBwRGF0YSk7XG5cdFx0dGhpcy5zYWZlRW1pdCgnY2xvc2VkJywgJ2xvY2FsJywgYXBwRGF0YSk7XG5cblx0XHR0aGlzLl9kZXN0cm95KCk7XG5cdH1cblxuXHQvKipcblx0ICogTXkgcmVtb3RlIFByb2R1Y2VyIHdhcyBjbG9zZWQuXG5cdCAqIEludm9rZWQgdmlhIHJlbW90ZSBub3RpZmljYXRpb24uXG5cdCAqXG5cdCAqIEBwcml2YXRlXG5cdCAqXG5cdCAqIEBwYXJhbSB7QW55fSBbYXBwRGF0YV0gLSBBcHAgY3VzdG9tIGRhdGEuXG5cdCAqL1xuXHRyZW1vdGVDbG9zZShhcHBEYXRhKVxuXHR7XG5cdFx0bG9nZ2VyLmRlYnVnKCdyZW1vdGVDbG9zZSgpJyk7XG5cblx0XHRpZiAodGhpcy5fY2xvc2VkKVxuXHRcdFx0cmV0dXJuO1xuXG5cdFx0dGhpcy5fY2xvc2VkID0gdHJ1ZTtcblxuXHRcdHRoaXMuZW1pdCgnQGNsb3NlJywgJ3JlbW90ZScsIGFwcERhdGEpO1xuXHRcdHRoaXMuc2FmZUVtaXQoJ2Nsb3NlZCcsICdyZW1vdGUnLCBhcHBEYXRhKTtcblxuXHRcdHRoaXMuX2Rlc3Ryb3koKTtcblx0fVxuXG5cdF9kZXN0cm95KClcblx0e1xuXHRcdHRoaXMuX2Nsb3NlZCA9IHRydWU7XG5cdFx0dGhpcy5faGFuZGxlZCA9IGZhbHNlO1xuXHRcdHRoaXMuX3J0cFBhcmFtZXRlcnMgPSBudWxsO1xuXG5cdFx0dHJ5IHsgdGhpcy5fdHJhY2suc3RvcCgpOyB9XG5cdFx0Y2F0Y2ggKGVycm9yKSB7fVxuXHR9XG5cblx0LyoqXG5cdCAqIFBhdXNlcyBzZW5kaW5nIG1lZGlhLlxuXHQgKlxuXHQgKiBAcGFyYW0ge0FueX0gW2FwcERhdGFdIC0gQXBwIGN1c3RvbSBkYXRhLlxuXHQgKlxuXHQgKiBAcmV0dXJuIHtCb29sZWFufSB0cnVlIGlmIHBhdXNlZC5cblx0ICovXG5cdHBhdXNlKGFwcERhdGEpXG5cdHtcblx0XHRsb2dnZXIuZGVidWcoJ3BhdXNlKCknKTtcblxuXHRcdGlmICh0aGlzLl9jbG9zZWQpXG5cdFx0e1xuXHRcdFx0bG9nZ2VyLmVycm9yKCdwYXVzZSgpIHwgUHJvZHVjZXIgY2xvc2VkJyk7XG5cblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9XG5cdFx0ZWxzZSBpZiAoIXRoaXMuX2hhbmRsZWQpXG5cdFx0e1xuXHRcdFx0bG9nZ2VyLmVycm9yKCdwYXVzZSgpIHwgUHJvZHVjZXIgbm90IGhhbmRsZWQnKTtcblxuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdH1cblx0XHRlbHNlIGlmICh0aGlzLl9sb2NhbGx5UGF1c2VkKVxuXHRcdHtcblx0XHRcdHJldHVybiB0cnVlO1xuXHRcdH1cblxuXHRcdHRoaXMuX2xvY2FsbHlQYXVzZWQgPSB0cnVlO1xuXHRcdHRoaXMuX3RyYWNrLmVuYWJsZWQgPSBmYWxzZTtcblxuXHRcdHRoaXMuZW1pdCgnQHBhdXNlJywgYXBwRGF0YSk7XG5cblx0XHRpZiAoIXRoaXMuX3JlbW90ZWx5UGF1c2VkKVxuXHRcdFx0dGhpcy5zYWZlRW1pdCgncGF1c2VkJywgJ2xvY2FsJywgYXBwRGF0YSk7XG5cblx0XHQvLyBSZXR1cm4gdHJ1ZSBpZiByZWFsbHkgcGF1c2VkLlxuXHRcdHJldHVybiB0aGlzLnBhdXNlZDtcblx0fVxuXG5cdC8qKlxuXHQgKiBNeSByZW1vdGUgUHJvZHVjZXIgd2FzIHBhdXNlZC5cblx0ICogSW52b2tlZCB2aWEgcmVtb3RlIG5vdGlmaWNhdGlvbi5cblx0ICpcblx0ICogQHByaXZhdGVcblx0ICpcblx0ICogQHBhcmFtIHtBbnl9IFthcHBEYXRhXSAtIEFwcCBjdXN0b20gZGF0YS5cblx0ICovXG5cdHJlbW90ZVBhdXNlKGFwcERhdGEpXG5cdHtcblx0XHRsb2dnZXIuZGVidWcoJ3JlbW90ZVBhdXNlKCknKTtcblxuXHRcdGlmICh0aGlzLl9jbG9zZWQgfHwgIXRoaXMuX2hhbmRsZWQgfHwgdGhpcy5fcmVtb3RlbHlQYXVzZWQpXG5cdFx0XHRyZXR1cm47XG5cblx0XHR0aGlzLl9yZW1vdGVseVBhdXNlZCA9IHRydWU7XG5cdFx0dGhpcy5fdHJhY2suZW5hYmxlZCA9IGZhbHNlO1xuXG5cdFx0aWYgKCF0aGlzLl9sb2NhbGx5UGF1c2VkKVxuXHRcdFx0dGhpcy5zYWZlRW1pdCgncGF1c2VkJywgJ3JlbW90ZScsIGFwcERhdGEpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJlc3VtZXMgc2VuZGluZyBtZWRpYS5cblx0ICpcblx0ICogQHBhcmFtIHtBbnl9IFthcHBEYXRhXSAtIEFwcCBjdXN0b20gZGF0YS5cblx0ICpcblx0ICogQHJldHVybiB7Qm9vbGVhbn0gdHJ1ZSBpZiBub3QgcGF1c2VkLlxuXHQgKi9cblx0cmVzdW1lKGFwcERhdGEpXG5cdHtcblx0XHRsb2dnZXIuZGVidWcoJ3Jlc3VtZSgpJyk7XG5cblx0XHRpZiAodGhpcy5fY2xvc2VkKVxuXHRcdHtcblx0XHRcdGxvZ2dlci5lcnJvcigncmVzdW1lKCkgfCBQcm9kdWNlciBjbG9zZWQnKTtcblxuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdH1cblx0XHRlbHNlIGlmICghdGhpcy5faGFuZGxlZClcblx0XHR7XG5cdFx0XHRsb2dnZXIuZXJyb3IoJ3BhdXNlKCkgfCBQcm9kdWNlciBub3QgaGFuZGxlZCcpO1xuXG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fVxuXHRcdGVsc2UgaWYgKCF0aGlzLl9sb2NhbGx5UGF1c2VkKVxuXHRcdHtcblx0XHRcdHJldHVybiB0cnVlO1xuXHRcdH1cblxuXHRcdHRoaXMuX2xvY2FsbHlQYXVzZWQgPSBmYWxzZTtcblxuXHRcdHRoaXMuZW1pdCgnQHJlc3VtZScsIGFwcERhdGEpO1xuXG5cdFx0aWYgKCF0aGlzLl9yZW1vdGVseVBhdXNlZClcblx0XHR7XG5cdFx0XHR0aGlzLl90cmFjay5lbmFibGVkID0gdHJ1ZTtcblxuXHRcdFx0dGhpcy5zYWZlRW1pdCgncmVzdW1lZCcsICdsb2NhbCcsIGFwcERhdGEpO1xuXHRcdH1cblxuXHRcdC8vIFJldHVybiB0cnVlIGlmIG5vdCBwYXVzZWQuXG5cdFx0cmV0dXJuICF0aGlzLnBhdXNlZDtcblx0fVxuXG5cdC8qKlxuXHQgKiBNeSByZW1vdGUgUHJvZHVjZXIgd2FzIHJlc3VtZWQuXG5cdCAqIEludm9rZWQgdmlhIHJlbW90ZSBub3RpZmljYXRpb24uXG5cdCAqXG5cdCAqIEBwcml2YXRlXG5cdCAqXG5cdCAqIEBwYXJhbSB7QW55fSBbYXBwRGF0YV0gLSBBcHAgY3VzdG9tIGRhdGEuXG5cdCAqL1xuXHRyZW1vdGVSZXN1bWUoYXBwRGF0YSlcblx0e1xuXHRcdGxvZ2dlci5kZWJ1ZygncmVtb3RlUmVzdW1lKCknKTtcblxuXHRcdGlmICh0aGlzLl9jbG9zZWQgfHwgIXRoaXMuX2hhbmRsZWQgfHwgIXRoaXMuX3JlbW90ZWx5UGF1c2VkKVxuXHRcdFx0cmV0dXJuO1xuXG5cdFx0dGhpcy5fcmVtb3RlbHlQYXVzZWQgPSBmYWxzZTtcblxuXHRcdGlmICghdGhpcy5fbG9jYWxseVBhdXNlZClcblx0XHR7XG5cdFx0XHR0aGlzLl90cmFjay5lbmFibGVkID0gdHJ1ZTtcblxuXHRcdFx0dGhpcy5zYWZlRW1pdCgncmVzdW1lZCcsICdyZW1vdGUnLCBhcHBEYXRhKTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogU2V0IHRoaXMgUHJvZHVjZXIgYXMgaGFuZGxlZCBvciB1bmhhbmRsZWQgYnkgYSBUcmFuc3BvcnQuXG5cdCAqXG5cdCAqIEBwcml2YXRlXG5cdCAqXG5cdCAqIEBwYXJhbSB7Qm9vbGVhbnxTdHJpbmd9IGZsYWcgLSBJZiAndG1wJyAoU3RyaW5nKSBpdCdzIGNvbnNpZGVyZWQgYXMgdGVybXBvcmFsLlxuXHQgKiBAcGFyYW0ge1JUQ1J0cFBhcmFtZXRlcnN9IHJ0cFBhcmFtZXRlcnNcblx0ICovXG5cdHNldEhhbmRsZWQoZmxhZywgcnRwUGFyYW1ldGVycylcblx0e1xuXHRcdGlmICh0aGlzLl9jbG9zZWQpXG5cdFx0XHRyZXR1cm47XG5cblx0XHRjb25zdCBwcmV2aW91cyA9IHRoaXMuX2hhbmRsZWQ7XG5cblx0XHR0aGlzLl9oYW5kbGVkID0gZmxhZztcblx0XHR0aGlzLl9ydHBQYXJhbWV0ZXJzID0gcnRwUGFyYW1ldGVycztcblxuXHRcdGlmIChmbGFnID09PSBmYWxzZSB8fCBmbGFnID09PSAndG1wJylcblx0XHRcdHRoaXMuX3J0cFBhcmFtZXRlcnMgPSBudWxsO1xuXG5cdFx0aWYgKHByZXZpb3VzID09PSB0cnVlICYmIGZsYWcgPT09IGZhbHNlKVxuXHRcdFx0dGhpcy5zYWZlRW1pdCgndW5oYW5kbGVkJyk7XG5cdH1cbn1cbiIsImltcG9ydCBMb2dnZXIgZnJvbSAnLi9Mb2dnZXInO1xuaW1wb3J0IEVuaGFuY2VkRXZlbnRFbWl0dGVyIGZyb20gJy4vRW5oYW5jZWRFdmVudEVtaXR0ZXInO1xuaW1wb3J0IHsgSW52YWxpZFN0YXRlRXJyb3IsIFRpbWVvdXRFcnJvciB9IGZyb20gJy4vZXJyb3JzJztcbmltcG9ydCAqIGFzIHV0aWxzIGZyb20gJy4vdXRpbHMnO1xuaW1wb3J0IERldmljZSBmcm9tICcuL0RldmljZSc7XG5pbXBvcnQgVHJhbnNwb3J0IGZyb20gJy4vVHJhbnNwb3J0JztcbmltcG9ydCBQcm9kdWNlciBmcm9tICcuL1Byb2R1Y2VyJztcbmltcG9ydCBQZWVyIGZyb20gJy4vUGVlcic7XG5pbXBvcnQgQ29uc3VtZXIgZnJvbSAnLi9Db25zdW1lcic7XG5cbmNvbnN0IGxvZ2dlciA9IG5ldyBMb2dnZXIoJ1Jvb20nKTtcblxuY29uc3QgUm9vbVN0YXRlID1cbntcblx0bmV3ICAgICA6ICduZXcnLFxuXHRqb2luaW5nIDogJ2pvaW5pbmcnLFxuXHRqb2luZWQgIDogJ2pvaW5lZCcsXG5cdGNsb3NlZCAgOiAnY2xvc2VkJ1xufTtcblxuLyoqXG4gKiBBbiBpbnN0YW5jZSBvZiBSb29tIHJlcHJlc2VudHMgYSByZW1vdGUgbXVsdGkgY29uZmVyZW5jZSBhbmQgYSBsb2NhbFxuICogcGVlciB0aGF0IGpvaW5zIGl0LlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBSb29tIGV4dGVuZHMgRW5oYW5jZWRFdmVudEVtaXR0ZXJcbntcblx0LyoqXG5cdCAqIFJvb20gY2xhc3MuXG5cdCAqXG5cdCAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9uc11cblx0ICogQHBhcmFtIHtOdW1iZXJ9IFtvcHRpb25zLnJlcXVlc3RUaW1lb3V0PTEwMDAwXSAtIFRpbWVvdXQgZm9yIHNlbnQgcmVxdWVzdHNcblx0ICogKGluIG1pbGxpc2Vjb25kcykuIERlZmF1bHRzIHRvIDEwMDAwICgxMCBzZWNvbmRzKS5cblx0ICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zLnRyYW5zcG9ydE9wdGlvbnNdIC0gVHJhbnNwb3J0IG9wdGlvbnMgZm9yIG1lZGlhc291cC5cblx0ICogQHBhcmFtIHtBcnJheTxSVENJY2VTZXJ2ZXI+fSBbb3B0aW9ucy50dXJuU2VydmVyc10gLSBBcnJheSBvZiBUVVJOIHNlcnZlcnMuXG5cdCAqIEBwYXJhbSB7Qm9vbGVhbn0gW2hpZGRlbj1mYWxzZV0gLSBJZiB0cnVlIG5vIHJlbW90ZSBQZWVycyB3aWxsIGJlIG5vdGlmaWVkLlxuXHQgKlxuXHQgKiBAdGhyb3dzIHtFcnJvcn0gaWYgZGV2aWNlIGlzIG5vdCBzdXBwb3J0ZWQuXG5cdCAqXG5cdCAqIEBlbWl0cyB7cmVxdWVzdDogT2JqZWN0LCBjYWxsYmFjazogRnVuY3Rpb24sIGVycmJhY2s6IEZ1bmN0aW9ufSByZXF1ZXN0XG5cdCAqIEBlbWl0cyB7bm90aWZpY2F0aW9uOiBPYmplY3R9IG5vdGlmeVxuXHQgKiBAZW1pdHMge3BlZXI6IFBlZXJ9IG5ld3BlZXJcblx0ICogQGVtaXRzIHtvcmlnaW5hdG9yOiBTdHJpbmcsIFthcHBEYXRhXTogQW55fSBjbG9zZWRcblx0ICovXG5cdGNvbnN0cnVjdG9yKG9wdGlvbnMpXG5cdHtcblx0XHRsb2dnZXIuZGVidWcoJ2NvbnN0cnVjdG9yKCkgW29wdGlvbnM6JW9dJywgb3B0aW9ucyk7XG5cblx0XHRzdXBlcigpO1xuXG5cdFx0aWYgKCFEZXZpY2UuaXNTdXBwb3J0ZWQoKSlcblx0XHRcdHRocm93IG5ldyBFcnJvcignY3VycmVudCBicm93c2VyL2RldmljZSBub3Qgc3VwcG9ydGVkJyk7XG5cblx0XHRvcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcblxuXHRcdC8vIENvbXB1dGVkIHNldHRpbmdzLlxuXHRcdC8vIEB0eXBlIHtPYmplY3R9XG5cdFx0dGhpcy5fc2V0dGluZ3MgPVxuXHRcdHtcblx0XHRcdHJlcXVlc3RUaW1lb3V0ICAgOiBvcHRpb25zLnJlcXVlc3RUaW1lb3V0IHx8IDEwMDAwLFxuXHRcdFx0dHJhbnNwb3J0T3B0aW9ucyA6IG9wdGlvbnMudHJhbnNwb3J0T3B0aW9ucyB8fCB7fSxcblx0XHRcdHR1cm5TZXJ2ZXJzICAgICAgOiBvcHRpb25zLnR1cm5TZXJ2ZXJzIHx8IFtdLFxuXHRcdFx0aGlkZGVuICAgICAgICAgICA6IEJvb2xlYW4ob3B0aW9ucy5oaWRkZW4pXG5cdFx0fTtcblxuXHRcdC8vIFJvb20gc3RhdGUuXG5cdFx0Ly8gQHR5cGUge0Jvb2xlYW59XG5cdFx0dGhpcy5fc3RhdGUgPSBSb29tU3RhdGUubmV3O1xuXG5cdFx0Ly8gTWFwIG9mIFRyYW5zcG9ydHMgaW5kZXhlZCBieSBpZC5cblx0XHQvLyBAdHlwZSB7bWFwPE51bWJlciwgVHJhbnNwb3J0Pn1cblx0XHR0aGlzLl90cmFuc3BvcnRzID0gbmV3IE1hcCgpO1xuXG5cdFx0Ly8gTWFwIG9mIFByb2R1Y2VycyBpbmRleGVkIGJ5IGlkLlxuXHRcdC8vIEB0eXBlIHttYXA8TnVtYmVyLCBQcm9kdWNlcj59XG5cdFx0dGhpcy5fcHJvZHVjZXJzID0gbmV3IE1hcCgpO1xuXG5cdFx0Ly8gTWFwIG9mIFBlZXJzIGluZGV4ZWQgYnkgbmFtZS5cblx0XHQvLyBAdHlwZSB7bWFwPFN0cmluZywgUGVlcj59XG5cdFx0dGhpcy5fcGVlcnMgPSBuZXcgTWFwKCk7XG5cblx0XHQvLyBFeHRlbmRlZCBSVFAgY2FwYWJpbGl0aWVzLlxuXHRcdC8vIEB0eXBlIHtPYmplY3R9XG5cdFx0dGhpcy5fZXh0ZW5kZWRSdHBDYXBhYmlsaXRpZXMgPSBudWxsO1xuXG5cdFx0Ly8gV2hldGhlciB3ZSBjYW4gc2VuZCBhdWRpby92aWRlbyBiYXNlZCBvbiBjb21wdXRlZCBleHRlbmRlZCBSVFBcblx0XHQvLyBjYXBhYmlsaXRpZXMuXG5cdFx0Ly8gQHR5cGUge09iamVjdH1cblx0XHR0aGlzLl9jYW5TZW5kQnlLaW5kID1cblx0XHR7XG5cdFx0XHRhdWRpbyA6IGZhbHNlLFxuXHRcdFx0dmlkZW8gOiBmYWxzZVxuXHRcdH07XG5cdH1cblxuXHQvKipcblx0ICogV2hldGhlciB0aGUgUm9vbSBpcyBqb2luZWQuXG5cdCAqXG5cdCAqIEByZXR1cm4ge0Jvb2xlYW59XG5cdCAqL1xuXHRnZXQgam9pbmVkKClcblx0e1xuXHRcdHJldHVybiB0aGlzLl9zdGF0ZSA9PT0gUm9vbVN0YXRlLmpvaW5lZDtcblx0fVxuXG5cdC8qKlxuXHQgKiBXaGV0aGVyIHRoZSBSb29tIGlzIGNsb3NlZC5cblx0ICpcblx0ICogQHJldHVybiB7Qm9vbGVhbn1cblx0ICovXG5cdGdldCBjbG9zZWQoKVxuXHR7XG5cdFx0cmV0dXJuIHRoaXMuX3N0YXRlID09PSBSb29tU3RhdGUuY2xvc2VkO1xuXHR9XG5cblx0LyoqXG5cdCAqIFRoZSBsaXN0IG9mIFRyYW5zcG9ydHMuXG5cdCAqXG5cdCAqIEByZXR1cm4ge0FycmF5PFRyYW5zcG9ydD59XG5cdCAqL1xuXHRnZXQgdHJhbnNwb3J0cygpXG5cdHtcblx0XHRyZXR1cm4gQXJyYXkuZnJvbSh0aGlzLl90cmFuc3BvcnRzLnZhbHVlcygpKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBUaGUgbGlzdCBvZiBQcm9kdWNlcnMuXG5cdCAqXG5cdCAqIEByZXR1cm4ge0FycmF5PFByb2R1Y2VyPn1cblx0ICovXG5cdGdldCBwcm9kdWNlcnMoKVxuXHR7XG5cdFx0cmV0dXJuIEFycmF5LmZyb20odGhpcy5fcHJvZHVjZXJzLnZhbHVlcygpKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBUaGUgbGlzdCBvZiBQZWVycy5cblx0ICpcblx0ICogQHJldHVybiB7QXJyYXk8UGVlcj59XG5cdCAqL1xuXHRnZXQgcGVlcnMoKVxuXHR7XG5cdFx0cmV0dXJuIEFycmF5LmZyb20odGhpcy5fcGVlcnMudmFsdWVzKCkpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFN0YXJ0IHRoZSBwcm9jZWR1cmVzIHRvIGpvaW4gYSByZW1vdGUgcm9vbS5cblx0ICpcblx0ICogQHBhcmFtIHtSVENSdHBDYXBhYmlsaXRpZXN9IFtyb29tUnRwQ2FwYWJpbGl0aWVzXSBSZW1vdGUgcm9vbSBSVFAgY2FwYWJpbGl0aWVzLlxuXHQgKiBJZiBnaXZlbiwgbm8gcmVxdWVzdCBpcyBzZW50IHRvIHRoZSBzZXJ2ZXIgdG8gZGlzY292ZXIgdGhlbS5cblx0ICogQHBhcmFtIHtBbnl9IFthcHBEYXRhXSAtIEFwcCBjdXN0b20gZGF0YS5cblx0ICogQHJldHVybiB7UHJvbWlzZX1cblx0ICovXG5cdGpvaW4ocm9vbVJ0cENhcGFiaWxpdGllcywgYXBwRGF0YSlcblx0e1xuXHRcdGlmICghcm9vbVJ0cENhcGFiaWxpdGllcylcblx0XHRcdGxvZ2dlci5kZWJ1Zygnam9pbigpJyk7XG5cdFx0ZWxzZVxuXHRcdFx0bG9nZ2VyLmRlYnVnKCdqb2luKCkgW3Jvb21SdHBDYXBhYmlsaXRpZXM6JW9dJywgcm9vbVJ0cENhcGFiaWxpdGllcyk7XG5cblx0XHRpZiAodGhpcy5fc3RhdGUgIT09IFJvb21TdGF0ZS5uZXcpXG5cdFx0e1xuXHRcdFx0cmV0dXJuIFByb21pc2UucmVqZWN0KFxuXHRcdFx0XHRuZXcgSW52YWxpZFN0YXRlRXJyb3IoYGludmFsaWQgc3RhdGUgXCIke3RoaXMuX3N0YXRlfVwiYCkpO1xuXHRcdH1cblxuXHRcdHRoaXMuX3N0YXRlID0gUm9vbVN0YXRlLmpvaW5pbmc7XG5cblx0XHRsZXQgcmVtb3RlUnRwQ2FwYWJpbGl0aWVzO1xuXHRcdGxldCBsb2NhbFJ0cENhcGFiaWxpdGllcztcblxuXHRcdHJldHVybiBQcm9taXNlLnJlc29sdmUoKVxuXHRcdFx0LnRoZW4oKCkgPT5cblx0XHRcdHtcblx0XHRcdFx0aWYgKHJvb21SdHBDYXBhYmlsaXRpZXMpXG5cdFx0XHRcdFx0cmV0dXJuIHJvb21SdHBDYXBhYmlsaXRpZXM7XG5cblx0XHRcdFx0cmV0dXJuIHRoaXMuX3NlbmRSZXF1ZXN0KCdxdWVyeVJvb20nKVxuXHRcdFx0XHRcdC50aGVuKChyZXNwb25zZSkgPT5cblx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRjb25zdCB7IHJ0cENhcGFiaWxpdGllcyB9ID0gcmVzcG9uc2U7XG5cblx0XHRcdFx0XHRcdGxvZ2dlci5kZWJ1Zyhcblx0XHRcdFx0XHRcdFx0J2pvaW4oKSB8IGdvdCBSb29tIFJUUCBjYXBhYmlsaXRpZXM6JW8nLCBydHBDYXBhYmlsaXRpZXMpO1xuXG5cdFx0XHRcdFx0XHRyZXR1cm4gcnRwQ2FwYWJpbGl0aWVzO1xuXHRcdFx0XHRcdH0pO1xuXHRcdFx0fSlcblx0XHRcdC50aGVuKChydHBDYXBhYmlsaXRpZXMpID0+XG5cdFx0XHR7XG5cdFx0XHRcdHJlbW90ZVJ0cENhcGFiaWxpdGllcyA9IHJ0cENhcGFiaWxpdGllcztcblxuXHRcdFx0XHRyZXR1cm4gRGV2aWNlLkhhbmRsZXIuZ2V0TG9jYWxSdHBDYXBhYmlsaXRpZXMoKTtcblx0XHRcdH0pXG5cdFx0XHQudGhlbigocnRwQ2FwYWJpbGl0aWVzKSA9PlxuXHRcdFx0e1xuXHRcdFx0XHRsb2NhbFJ0cENhcGFiaWxpdGllcyA9IHJ0cENhcGFiaWxpdGllcztcblxuXHRcdFx0XHQvLyBHZXQgZXh0ZW5kZWQgUlRQIGNhcGFiaWxpdGllcy5cblx0XHRcdFx0dGhpcy5fZXh0ZW5kZWRSdHBDYXBhYmlsaXRpZXMgPSB1dGlscy5nZXRFeHRlbmRlZFJ0cENhcGFiaWxpdGllcyhcblx0XHRcdFx0XHRsb2NhbFJ0cENhcGFiaWxpdGllcywgcmVtb3RlUnRwQ2FwYWJpbGl0aWVzKTtcblxuXHRcdFx0XHQvLyBDaGVjayB3aGV0aGVyIHdlIGNhbiBzZW5kIGF1ZGlvL3ZpZGVvLlxuXHRcdFx0XHR0aGlzLl9jYW5TZW5kQnlLaW5kLmF1ZGlvID1cblx0XHRcdFx0XHR1dGlscy5jYW5TZW5kKCdhdWRpbycsIHRoaXMuX2V4dGVuZGVkUnRwQ2FwYWJpbGl0aWVzKTtcblx0XHRcdFx0dGhpcy5fY2FuU2VuZEJ5S2luZC52aWRlbyA9XG5cdFx0XHRcdFx0dXRpbHMuY2FuU2VuZCgndmlkZW8nLCB0aGlzLl9leHRlbmRlZFJ0cENhcGFiaWxpdGllcyk7XG5cblx0XHRcdFx0Ly8gR2VuZXJhdGUgb3VyIGVmZmVjdGl2ZSBSVFAgY2FwYWJpbGl0aWVzIGZvciByZWNlaXZpbmcgbWVkaWEuXG5cdFx0XHRcdGNvbnN0IGVmZmVjdGl2ZUxvY2FsUnRwQ2FwYWJpbGl0aWVzID1cblx0XHRcdFx0XHR1dGlscy5nZXRSdHBDYXBhYmlsaXRpZXModGhpcy5fZXh0ZW5kZWRSdHBDYXBhYmlsaXRpZXMpO1xuXG5cdFx0XHRcdGxvZ2dlci5kZWJ1Zyhcblx0XHRcdFx0XHQnam9pbigpIHwgZWZmZWN0aXZlIGxvY2FsIFJUUCBjYXBhYmlsaXRpZXM6JW8nLFxuXHRcdFx0XHRcdGVmZmVjdGl2ZUxvY2FsUnRwQ2FwYWJpbGl0aWVzKTtcblxuXHRcdFx0XHRjb25zdCBkYXRhID1cblx0XHRcdFx0e1xuXHRcdFx0XHRcdHJ0cENhcGFiaWxpdGllcyA6IGVmZmVjdGl2ZUxvY2FsUnRwQ2FwYWJpbGl0aWVzLFxuXHRcdFx0XHRcdGFwcERhdGEgICAgICAgICA6IGFwcERhdGFcblx0XHRcdFx0fTtcblxuXHRcdFx0XHRyZXR1cm4gdGhpcy5fc2VuZFJlcXVlc3QoJ2pvaW5Sb29tJywgZGF0YSlcblx0XHRcdFx0XHQudGhlbigocmVzcG9uc2UpID0+IHJlc3BvbnNlLnBlZXJzKTtcblx0XHRcdH0pXG5cdFx0XHQudGhlbigocGVlcnMpID0+XG5cdFx0XHR7XG5cdFx0XHRcdGlmICghdGhpcy5fc2V0dGluZ3MuaGlkZGVuKVxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0Ly8gSGFuZGxlIFBlZXJzIGFscmVhZHkgZXhpc3RpbmcgaW4gdGhlIHJvb20uXG5cdFx0XHRcdFx0Zm9yIChjb25zdCBwZWVyRGF0YSBvZiBwZWVycyB8fCBbXSlcblx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHR0cnlcblx0XHRcdFx0XHRcdHtcblx0XHRcdFx0XHRcdFx0dGhpcy5faGFuZGxlUGVlckRhdGEocGVlckRhdGEpO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0Y2F0Y2ggKGVycm9yKVxuXHRcdFx0XHRcdFx0e1xuXHRcdFx0XHRcdFx0XHRsb2dnZXIuZXJyb3IoJ2pvaW4oKSB8IGVycm9yIGhhbmRsaW5nIFBlZXI6JW8nLCBlcnJvcik7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHRcdGVsc2UgaWYgKHBlZXJzLmxlbmd0aCA+IDApXG5cdFx0XHRcdHtcblx0XHRcdFx0XHRsb2dnZXIuZXJyb3IoJ2pvaW4oKSB8IHNob3VsZCBub3QgcmVjZWl2ZSBQZWVyIGxpc3QgaW4gaGlkZGVuIG1vZGUnKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdHRoaXMuX3N0YXRlID0gUm9vbVN0YXRlLmpvaW5lZDtcblxuXHRcdFx0XHRsb2dnZXIuZGVidWcoJ2pvaW4oKSB8IGpvaW5lZCB0aGUgUm9vbScpO1xuXG5cdFx0XHRcdC8vIFJldHVybiB0aGUgbGlzdCBvZiBhbHJlYWR5IGV4aXN0aW5nIFBlZXJzLlxuXHRcdFx0XHRyZXR1cm4gdGhpcy5wZWVycztcblx0XHRcdH0pXG5cdFx0XHQuY2F0Y2goKGVycm9yKSA9PlxuXHRcdFx0e1xuXHRcdFx0XHR0aGlzLl9zdGF0ZSA9IFJvb21TdGF0ZS5uZXc7XG5cblx0XHRcdFx0dGhyb3cgZXJyb3I7XG5cdFx0XHR9KTtcblx0fVxuXG5cdC8qKlxuXHQgKiBMZWF2ZSB0aGUgUm9vbS5cblx0ICpcblx0ICogQHBhcmFtIHtBbnl9IFthcHBEYXRhXSAtIEFwcCBjdXN0b20gZGF0YS5cblx0ICovXG5cdGxlYXZlKGFwcERhdGEpXG5cdHtcblx0XHRsb2dnZXIuZGVidWcoJ2xlYXZlKCknKTtcblxuXHRcdGlmICh0aGlzLmNsb3NlZClcblx0XHRcdHJldHVybjtcblxuXHRcdC8vIFNlbmQgYSBub3RpZmljYXRpb24uXG5cdFx0dGhpcy5fc2VuZE5vdGlmaWNhdGlvbignbGVhdmVSb29tJywgeyBhcHBEYXRhIH0pO1xuXG5cdFx0Ly8gU2V0IGNsb3NlZCBzdGF0ZSBhZnRlciBzZW5kaW5nIHRoZSBub3RpZmljYXRpb24gKG90aGVyd2lzZSB0aGVcblx0XHQvLyBub3RpZmljYXRpb24gd29uJ3QgYmUgc2VudCkuXG5cdFx0dGhpcy5fc3RhdGUgPSBSb29tU3RhdGUuY2xvc2VkO1xuXG5cdFx0dGhpcy5zYWZlRW1pdCgnY2xvc2VkJywgJ2xvY2FsJywgYXBwRGF0YSk7XG5cblx0XHQvLyBDbG9zZSBhbGwgdGhlIFRyYW5zcG9ydHMuXG5cdFx0Zm9yIChjb25zdCB0cmFuc3BvcnQgb2YgdGhpcy5fdHJhbnNwb3J0cy52YWx1ZXMoKSlcblx0XHR7XG5cdFx0XHR0cmFuc3BvcnQuY2xvc2UoKTtcblx0XHR9XG5cblx0XHQvLyBDbG9zZSBhbGwgdGhlIFByb2R1Y2Vycy5cblx0XHRmb3IgKGNvbnN0IHByb2R1Y2VyIG9mIHRoaXMuX3Byb2R1Y2Vycy52YWx1ZXMoKSlcblx0XHR7XG5cdFx0XHRwcm9kdWNlci5jbG9zZSgpO1xuXHRcdH1cblxuXHRcdC8vIENsb3NlIGFsbCB0aGUgUGVlcnMuXG5cdFx0Zm9yIChjb25zdCBwZWVyIG9mIHRoaXMuX3BlZXJzLnZhbHVlcygpKVxuXHRcdHtcblx0XHRcdHBlZXIuY2xvc2UoKTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogVGhlIHJlbW90ZSBSb29tIHdhcyBjbG9zZWQgb3Igb3VyIHJlbW90ZSBQZWVyIGhhcyBiZWVuIGNsb3NlZC5cblx0ICogSW52b2tlZCB2aWEgcmVtb3RlIG5vdGlmaWNhdGlvbi5cblx0ICpcblx0ICogQHByaXZhdGVcblx0ICogQHBhcmFtIHtBbnl9IFthcHBEYXRhXSAtIEFwcCBjdXN0b20gZGF0YS5cblx0ICovXG5cdHJlbW90ZUNsb3NlKGFwcERhdGEpXG5cdHtcblx0XHRsb2dnZXIuZGVidWcoJ3JlbW90ZUNsb3NlKCknKTtcblxuXHRcdGlmICh0aGlzLmNsb3NlZClcblx0XHRcdHJldHVybjtcblxuXHRcdHRoaXMuX3N0YXRlID0gUm9vbVN0YXRlLmNsb3NlZDtcblxuXHRcdHRoaXMuc2FmZUVtaXQoJ2Nsb3NlZCcsICdyZW1vdGUnLCBhcHBEYXRhKTtcblxuXHRcdC8vIENsb3NlIGFsbCB0aGUgVHJhbnNwb3J0cy5cblx0XHRmb3IgKGNvbnN0IHRyYW5zcG9ydCBvZiB0aGlzLl90cmFuc3BvcnRzLnZhbHVlcygpKVxuXHRcdHtcblx0XHRcdHRyYW5zcG9ydC5yZW1vdGVDbG9zZSgpO1xuXHRcdH1cblxuXHRcdC8vIENsb3NlIGFsbCB0aGUgUHJvZHVjZXJzLlxuXHRcdGZvciAoY29uc3QgcHJvZHVjZXIgb2YgdGhpcy5fcHJvZHVjZXJzLnZhbHVlcygpKVxuXHRcdHtcblx0XHRcdHByb2R1Y2VyLnJlbW90ZUNsb3NlKCk7XG5cdFx0fVxuXG5cdFx0Ly8gQ2xvc2UgYWxsIHRoZSBQZWVycy5cblx0XHRmb3IgKGNvbnN0IHBlZXIgb2YgdGhpcy5fcGVlcnMudmFsdWVzKCkpXG5cdFx0e1xuXHRcdFx0cGVlci5yZW1vdGVDbG9zZSgpO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBXaGV0aGVyIHdlIGNhbiBzZW5kIGF1ZGlvL3ZpZGVvLlxuXHQgKlxuXHQgKiBAcGFyYW0ge1N0cmluZ30ga2luZCAtICdhdWRpbycgb3IgJ3ZpZGVvJy5cblx0ICpcblx0ICogQHJldHVybiB7Qm9vbGVhbn1cblx0ICovXG5cdGNhblNlbmQoa2luZClcblx0e1xuXHRcdGlmICghdGhpcy5qb2luZWQpXG5cdFx0XHR0aHJvdyBuZXcgSW52YWxpZFN0YXRlRXJyb3IoYGludmFsaWQgc3RhdGUgXCIke3RoaXMuX3N0YXRlfVwiYCk7XG5cdFx0ZWxzZSBpZiAoa2luZCAhPT0gJ2F1ZGlvJyAmJiBraW5kICE9PSAndmlkZW8nKVxuXHRcdFx0dGhyb3cgbmV3IFR5cGVFcnJvcihgaW52YWxpZCBraW5kIFwiJHtraW5kfVwiYCk7XG5cblx0XHRyZXR1cm4gdGhpcy5fY2FuU2VuZEJ5S2luZFtraW5kXTtcblx0fVxuXG5cdC8qKlxuXHQgKiBDcmVhdGVzIGEgVHJhbnNwb3J0LlxuXHQgKlxuXHQgKiBAcGFyYW0ge1N0cmluZ30gZGlyZWN0aW9uIC0gTXVzdCBiZSAnc2VuZCcgb3IgJ3JlY3YnLlxuXHQgKiBAcGFyYW0ge0FueX0gW2FwcERhdGFdIC0gQXBwIGN1c3RvbSBkYXRhLlxuXHQgKlxuXHQgKiBAcmV0dXJuIHtUcmFuc3BvcnR9XG5cdCAqXG5cdCAqIEB0aHJvd3Mge0ludmFsaWRTdGF0ZUVycm9yfSBpZiBub3Qgam9pbmVkLlxuXHQgKiBAdGhyb3dzIHtUeXBlRXJyb3J9IGlmIHdyb25nIGFyZ3VtZW50cy5cblx0ICovXG5cdGNyZWF0ZVRyYW5zcG9ydChkaXJlY3Rpb24sIGFwcERhdGEpXG5cdHtcblx0XHRsb2dnZXIuZGVidWcoJ2NyZWF0ZVRyYW5zcG9ydCgpIFtkaXJlY3Rpb246JXNdJywgZGlyZWN0aW9uKTtcblxuXHRcdGlmICghdGhpcy5qb2luZWQpXG5cdFx0XHR0aHJvdyBuZXcgSW52YWxpZFN0YXRlRXJyb3IoYGludmFsaWQgc3RhdGUgXCIke3RoaXMuX3N0YXRlfVwiYCk7XG5cdFx0ZWxzZSBpZiAoZGlyZWN0aW9uICE9PSAnc2VuZCcgJiYgZGlyZWN0aW9uICE9PSAncmVjdicpXG5cdFx0XHR0aHJvdyBuZXcgVHlwZUVycm9yKGBpbnZhbGlkIGRpcmVjdGlvbiBcIiR7ZGlyZWN0aW9ufVwiYCk7XG5cblx0XHQvLyBDcmVhdGUgYSBuZXcgVHJhbnNwb3J0LlxuXHRcdGNvbnN0IHRyYW5zcG9ydCA9IG5ldyBUcmFuc3BvcnQoXG5cdFx0XHRkaXJlY3Rpb24sIHRoaXMuX2V4dGVuZGVkUnRwQ2FwYWJpbGl0aWVzLCB0aGlzLl9zZXR0aW5ncywgYXBwRGF0YSk7XG5cblx0XHQvLyBTdG9yZSBpdC5cblx0XHR0aGlzLl90cmFuc3BvcnRzLnNldCh0cmFuc3BvcnQuaWQsIHRyYW5zcG9ydCk7XG5cblx0XHR0cmFuc3BvcnQub24oJ0ByZXF1ZXN0JywgKG1ldGhvZCwgZGF0YSwgY2FsbGJhY2ssIGVycmJhY2spID0+XG5cdFx0e1xuXHRcdFx0dGhpcy5fc2VuZFJlcXVlc3QobWV0aG9kLCBkYXRhKVxuXHRcdFx0XHQudGhlbihjYWxsYmFjayB8fCBmdW5jdGlvbigpIHt9KVxuXHRcdFx0XHQuY2F0Y2goZXJyYmFjayB8fCBmdW5jdGlvbigpIHt9KTtcblx0XHR9KTtcblxuXHRcdHRyYW5zcG9ydC5vbignQG5vdGlmeScsIChtZXRob2QsIGRhdGEpID0+XG5cdFx0e1xuXHRcdFx0dGhpcy5fc2VuZE5vdGlmaWNhdGlvbihtZXRob2QsIGRhdGEpO1xuXHRcdH0pO1xuXG5cdFx0dHJhbnNwb3J0Lm9uKCdAY2xvc2UnLCAoKSA9PlxuXHRcdHtcblx0XHRcdHRoaXMuX3RyYW5zcG9ydHMuZGVsZXRlKHRyYW5zcG9ydC5pZCk7XG5cdFx0fSk7XG5cblx0XHRyZXR1cm4gdHJhbnNwb3J0O1xuXHR9XG5cblx0LyoqXG5cdCAqIENyZWF0ZXMgYSBQcm9kdWNlci5cblx0ICpcblx0ICogQHBhcmFtIHtNZWRpYVN0cmVhbVRyYWNrfSB0cmFja1xuXHQgKiBAcGFyYW0ge0FueX0gW2FwcERhdGFdIC0gQXBwIGN1c3RvbSBkYXRhLlxuXHQgKlxuXHQgKiBAcmV0dXJuIHtQcm9kdWNlcn1cblx0ICpcblx0ICogQHRocm93cyB7SW52YWxpZFN0YXRlRXJyb3J9IGlmIG5vdCBqb2luZWQuXG5cdCAqIEB0aHJvd3Mge1R5cGVFcnJvcn0gaWYgd3JvbmcgYXJndW1lbnRzLlxuXHQgKiBAdGhyb3dzIHtFcnJvcn0gaWYgY2Fubm90IHNlbmQgdGhlIGdpdmVuIGtpbmQuXG5cdCAqL1xuXHRjcmVhdGVQcm9kdWNlcih0cmFjaywgYXBwRGF0YSlcblx0e1xuXHRcdGxvZ2dlci5kZWJ1ZygnY3JlYXRlUHJvZHVjZXIoKSBbdHJhY2s6JW9dJywgdHJhY2spO1xuXG5cdFx0aWYgKCF0aGlzLmpvaW5lZClcblx0XHRcdHRocm93IG5ldyBJbnZhbGlkU3RhdGVFcnJvcihgaW52YWxpZCBzdGF0ZSBcIiR7dGhpcy5fc3RhdGV9XCJgKTtcblx0XHRlbHNlIGlmICghKHRyYWNrIGluc3RhbmNlb2YgTWVkaWFTdHJlYW1UcmFjaykpXG5cdFx0XHR0aHJvdyBuZXcgVHlwZUVycm9yKCd0cmFjayBpcyBub3QgYSBNZWRpYVN0cmVhbVRyYWNrJyk7XG5cdFx0ZWxzZSBpZiAoIXRoaXMuX2NhblNlbmRCeUtpbmRbdHJhY2sua2luZF0pXG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoYGNhbm5vdCBzZW5kICR7dHJhY2sua2luZH1gKTtcblx0XHRlbHNlIGlmICh0cmFjay5yZWFkeVN0YXRlID09PSAnZW5kZWQnKVxuXHRcdFx0dGhyb3cgbmV3IEVycm9yKCd0cmFjay5yZWFkeVN0YXRlIGlzIFwiZW5kZWRcIicpO1xuXG5cdFx0Ly8gQ3JlYXRlIGEgbmV3IFByb2R1Y2VyLlxuXHRcdGNvbnN0IHByb2R1Y2VyID0gbmV3IFByb2R1Y2VyKHRyYWNrLCBhcHBEYXRhKTtcblxuXHRcdC8vIFN0b3JlIGl0LlxuXHRcdHRoaXMuX3Byb2R1Y2Vycy5zZXQocHJvZHVjZXIuaWQsIHByb2R1Y2VyKTtcblxuXHRcdHByb2R1Y2VyLm9uKCdAY2xvc2UnLCAoKSA9PlxuXHRcdHtcblx0XHRcdHRoaXMuX3Byb2R1Y2Vycy5kZWxldGUocHJvZHVjZXIuaWQpO1xuXHRcdH0pO1xuXG5cdFx0cmV0dXJuIHByb2R1Y2VyO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldCB0aGUgVHJhbnNwb3J0IHdpdGggdGhlIGdpdmVuIGlkLlxuXHQgKlxuXHQgKiBAcGFyYW0ge051bWJlcn0gaWRcblx0ICpcblx0ICogQHJldHVybiB7VHJhbnNwb3J0fVxuXHQgKi9cblx0Z2V0VHJhbnNwb3J0QnlJZChpZClcblx0e1xuXHRcdHJldHVybiB0aGlzLl90cmFuc3BvcnRzLmdldChpZCk7XG5cdH1cblxuXHQvKipcblx0ICogR2V0IHRoZSBQcm9kdWNlciB3aXRoIHRoZSBnaXZlbiBpZC5cblx0ICpcblx0ICogQHBhcmFtIHtOdW1iZXJ9IGlkXG5cdCAqXG5cdCAqIEByZXR1cm4ge1Byb2R1Y2VyfVxuXHQgKi9cblx0Z2V0UHJvZHVjZXJCeUlkKGlkKVxuXHR7XG5cdFx0cmV0dXJuIHRoaXMuX3Byb2R1Y2Vycy5nZXQoaWQpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldCB0aGUgUGVlciB3aXRoIHRoZSBnaXZlbiBuYW1lLlxuXHQgKlxuXHQgKiBAcGFyYW0ge1N0cmluZ30gbmFtZVxuXHQgKlxuXHQgKiBAcmV0dXJuIHtQZWVyfVxuXHQgKi9cblx0Z2V0UGVlckJ5SWQobmFtZSlcblx0e1xuXHRcdHJldHVybiB0aGlzLl9wZWVycy5nZXQobmFtZSk7XG5cdH1cblxuXHQvKipcblx0ICogUHJvdmlkZSB0aGUgbG9jYWwgUm9vbSB3aXRoIGEgbm90aWZpY2F0aW9uIGdlbmVyYXRlZCBieSBtZWRpYXNvdXAgc2VydmVyLlxuXHQgKlxuXHQgKiBAcGFyYW0ge09iamVjdH0gbm90aWZpY2F0aW9uXG5cdCAqL1xuXHRyZWNlaXZlTm90aWZpY2F0aW9uKG5vdGlmaWNhdGlvbilcblx0e1xuXHRcdHRyeVxuXHRcdHtcblx0XHRcdGlmICh0aGlzLmNsb3NlZClcblx0XHRcdFx0dGhyb3cgbmV3IEludmFsaWRTdGF0ZUVycm9yKCdSb29tIGNsb3NlZCcpO1xuXHRcdFx0ZWxzZSBpZiAodHlwZW9mIG5vdGlmaWNhdGlvbiAhPT0gJ29iamVjdCcpXG5cdFx0XHRcdHRocm93IG5ldyBUeXBlRXJyb3IoJ3dyb25nIG5vdGlmaWNhdGlvbiBPYmplY3QnKTtcblx0XHRcdGVsc2UgaWYgKG5vdGlmaWNhdGlvbi5ub3RpZmljYXRpb24gIT09IHRydWUpXG5cdFx0XHRcdHRocm93IG5ldyBUeXBlRXJyb3IoJ25vdCBhIG5vdGlmaWNhdGlvbicpO1xuXHRcdFx0ZWxzZSBpZiAodHlwZW9mIG5vdGlmaWNhdGlvbi5tZXRob2QgIT09ICdzdHJpbmcnKVxuXHRcdFx0XHR0aHJvdyBuZXcgVHlwZUVycm9yKCd3cm9uZy9taXNzaW5nIG5vdGlmaWNhdGlvbiBtZXRob2QnKTtcblxuXHRcdFx0Y29uc3QgbWV0aG9kID0gbm90aWZpY2F0aW9uLm1ldGhvZDtcblxuXHRcdFx0bG9nZ2VyLmRlYnVnKFxuXHRcdFx0XHQncmVjZWl2ZU5vdGlmaWNhdGlvbigpIFttZXRob2Q6JXMsIG5vdGlmaWNhdGlvbjolb10nLFxuXHRcdFx0XHRtZXRob2QsIG5vdGlmaWNhdGlvbik7XG5cblx0XHRcdHN3aXRjaCAobWV0aG9kKVxuXHRcdFx0e1xuXHRcdFx0XHRjYXNlICdyb29tQ2xvc2VkJzpcblx0XHRcdFx0e1xuXHRcdFx0XHRcdGNvbnN0IHsgYXBwRGF0YSB9ID0gbm90aWZpY2F0aW9uO1xuXG5cdFx0XHRcdFx0dGhpcy5yZW1vdGVDbG9zZShhcHBEYXRhKTtcblxuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0Y2FzZSAndHJhbnNwb3J0Q2xvc2VkJzpcblx0XHRcdFx0e1xuXHRcdFx0XHRcdGNvbnN0IHsgaWQsIGFwcERhdGEgfSA9IG5vdGlmaWNhdGlvbjtcblx0XHRcdFx0XHRjb25zdCB0cmFuc3BvcnQgPSB0aGlzLl90cmFuc3BvcnRzLmdldChpZCk7XG5cblx0XHRcdFx0XHRpZiAoIXRyYW5zcG9ydClcblx0XHRcdFx0XHRcdHRocm93IG5ldyBFcnJvcihgVHJhbnNwb3J0IGRvZXMgbm90IGV4aXN0IFtpZDpcIiR7aWR9XCJdYCk7XG5cblx0XHRcdFx0XHR0cmFuc3BvcnQucmVtb3RlQ2xvc2UoYXBwRGF0YSk7XG5cblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGNhc2UgJ25ld1BlZXInOlxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0dGhpcy5fZW5zdXJlTm90SGlkZGVuKCk7XG5cblx0XHRcdFx0XHRjb25zdCB7IG5hbWUgfSA9IG5vdGlmaWNhdGlvbjtcblxuXHRcdFx0XHRcdGlmICh0aGlzLl9wZWVycy5oYXMobmFtZSkpXG5cdFx0XHRcdFx0XHR0aHJvdyBuZXcgRXJyb3IoYFBlZXIgYWxyZWFkeSBleGlzdHMgW25hbWU6XCIke25hbWV9XCJdYCk7XG5cblx0XHRcdFx0XHRjb25zdCBwZWVyRGF0YSA9IG5vdGlmaWNhdGlvbjtcblxuXHRcdFx0XHRcdHRoaXMuX2hhbmRsZVBlZXJEYXRhKHBlZXJEYXRhKTtcblxuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0Y2FzZSAncGVlckNsb3NlZCc6XG5cdFx0XHRcdHtcblx0XHRcdFx0XHR0aGlzLl9lbnN1cmVOb3RIaWRkZW4oKTtcblxuXHRcdFx0XHRcdGNvbnN0IHBlZXJOYW1lID0gbm90aWZpY2F0aW9uLm5hbWU7XG5cdFx0XHRcdFx0Y29uc3QgeyBhcHBEYXRhIH0gPSBub3RpZmljYXRpb247XG5cdFx0XHRcdFx0Y29uc3QgcGVlciA9IHRoaXMuX3BlZXJzLmdldChwZWVyTmFtZSk7XG5cblx0XHRcdFx0XHRpZiAoIXBlZXIpXG5cdFx0XHRcdFx0XHR0aHJvdyBuZXcgRXJyb3IoYG5vIFBlZXIgZm91bmQgW25hbWU6XCIke3BlZXJOYW1lfVwiXWApO1xuXG5cdFx0XHRcdFx0cGVlci5yZW1vdGVDbG9zZShhcHBEYXRhKTtcblxuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0Y2FzZSAncHJvZHVjZXJDbG9zZWQnOlxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0Y29uc3QgeyBpZCwgYXBwRGF0YSB9ID0gbm90aWZpY2F0aW9uO1xuXHRcdFx0XHRcdGNvbnN0IHByb2R1Y2VyID0gdGhpcy5fcHJvZHVjZXJzLmdldChpZCk7XG5cblx0XHRcdFx0XHRpZiAoIXByb2R1Y2VyKVxuXHRcdFx0XHRcdFx0dGhyb3cgbmV3IEVycm9yKGBQcm9kdWNlciBub3QgZm91bmQgW2lkOiR7aWR9XWApO1xuXG5cdFx0XHRcdFx0cHJvZHVjZXIucmVtb3RlQ2xvc2UoYXBwRGF0YSk7XG5cblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGNhc2UgJ3Byb2R1Y2VyUGF1c2VkJzpcblx0XHRcdFx0e1xuXHRcdFx0XHRcdGNvbnN0IHsgaWQsIGFwcERhdGEgfSA9IG5vdGlmaWNhdGlvbjtcblx0XHRcdFx0XHRjb25zdCBwcm9kdWNlciA9IHRoaXMuX3Byb2R1Y2Vycy5nZXQoaWQpO1xuXG5cdFx0XHRcdFx0aWYgKCFwcm9kdWNlcilcblx0XHRcdFx0XHRcdHRocm93IG5ldyBFcnJvcihgUHJvZHVjZXIgbm90IGZvdW5kIFtpZDoke2lkfV1gKTtcblxuXHRcdFx0XHRcdHByb2R1Y2VyLnJlbW90ZVBhdXNlKGFwcERhdGEpO1xuXG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRjYXNlICdwcm9kdWNlclJlc3VtZWQnOlxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0Y29uc3QgeyBpZCwgYXBwRGF0YSB9ID0gbm90aWZpY2F0aW9uO1xuXHRcdFx0XHRcdGNvbnN0IHByb2R1Y2VyID0gdGhpcy5fcHJvZHVjZXJzLmdldChpZCk7XG5cblx0XHRcdFx0XHRpZiAoIXByb2R1Y2VyKVxuXHRcdFx0XHRcdFx0dGhyb3cgbmV3IEVycm9yKGBQcm9kdWNlciBub3QgZm91bmQgW2lkOiR7aWR9XWApO1xuXG5cdFx0XHRcdFx0cHJvZHVjZXIucmVtb3RlUmVzdW1lKGFwcERhdGEpO1xuXG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRjYXNlICduZXdDb25zdW1lcic6XG5cdFx0XHRcdHtcblx0XHRcdFx0XHR0aGlzLl9lbnN1cmVOb3RIaWRkZW4oKTtcblxuXHRcdFx0XHRcdGNvbnN0IHsgcGVlck5hbWUgfSA9IG5vdGlmaWNhdGlvbjtcblx0XHRcdFx0XHRjb25zdCBwZWVyID0gdGhpcy5fcGVlcnMuZ2V0KHBlZXJOYW1lKTtcblxuXHRcdFx0XHRcdGlmICghcGVlcilcblx0XHRcdFx0XHRcdHRocm93IG5ldyBFcnJvcihgbm8gUGVlciBmb3VuZCBbbmFtZTpcIiR7cGVlck5hbWV9XCJdYCk7XG5cblx0XHRcdFx0XHRjb25zdCBjb25zdW1lckRhdGEgPSBub3RpZmljYXRpb247XG5cblx0XHRcdFx0XHR0aGlzLl9oYW5kbGVDb25zdW1lckRhdGEoY29uc3VtZXJEYXRhLCBwZWVyKTtcblxuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0Y2FzZSAnY29uc3VtZXJDbG9zZWQnOlxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0dGhpcy5fZW5zdXJlTm90SGlkZGVuKCk7XG5cblx0XHRcdFx0XHRjb25zdCB7IGlkLCBwZWVyTmFtZSwgYXBwRGF0YSB9ID0gbm90aWZpY2F0aW9uO1xuXHRcdFx0XHRcdGNvbnN0IHBlZXIgPSB0aGlzLl9wZWVycy5nZXQocGVlck5hbWUpO1xuXG5cdFx0XHRcdFx0aWYgKCFwZWVyKVxuXHRcdFx0XHRcdFx0dGhyb3cgbmV3IEVycm9yKGBubyBQZWVyIGZvdW5kIFtuYW1lOlwiJHtwZWVyTmFtZX1cIl1gKTtcblxuXHRcdFx0XHRcdGNvbnN0IGNvbnN1bWVyID0gcGVlci5nZXRDb25zdW1lckJ5SWQoaWQpO1xuXG5cdFx0XHRcdFx0aWYgKCFjb25zdW1lcilcblx0XHRcdFx0XHRcdHRocm93IG5ldyBFcnJvcihgQ29uc3VtZXIgbm90IGZvdW5kIFtpZDoke2lkfV1gKTtcblxuXHRcdFx0XHRcdGNvbnN1bWVyLnJlbW90ZUNsb3NlKGFwcERhdGEpO1xuXG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRjYXNlICdjb25zdW1lclBhdXNlZCc6XG5cdFx0XHRcdHtcblx0XHRcdFx0XHR0aGlzLl9lbnN1cmVOb3RIaWRkZW4oKTtcblxuXHRcdFx0XHRcdGNvbnN0IHsgaWQsIHBlZXJOYW1lLCBhcHBEYXRhIH0gPSBub3RpZmljYXRpb247XG5cdFx0XHRcdFx0Y29uc3QgcGVlciA9IHRoaXMuX3BlZXJzLmdldChwZWVyTmFtZSk7XG5cblx0XHRcdFx0XHRpZiAoIXBlZXIpXG5cdFx0XHRcdFx0XHR0aHJvdyBuZXcgRXJyb3IoYG5vIFBlZXIgZm91bmQgW25hbWU6XCIke3BlZXJOYW1lfVwiXWApO1xuXG5cdFx0XHRcdFx0Y29uc3QgY29uc3VtZXIgPSBwZWVyLmdldENvbnN1bWVyQnlJZChpZCk7XG5cblx0XHRcdFx0XHRpZiAoIWNvbnN1bWVyKVxuXHRcdFx0XHRcdFx0dGhyb3cgbmV3IEVycm9yKGBDb25zdW1lciBub3QgZm91bmQgW2lkOiR7aWR9XWApO1xuXG5cdFx0XHRcdFx0Y29uc3VtZXIucmVtb3RlUGF1c2UoYXBwRGF0YSk7XG5cblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGNhc2UgJ2NvbnN1bWVyUmVzdW1lZCc6XG5cdFx0XHRcdHtcblx0XHRcdFx0XHR0aGlzLl9lbnN1cmVOb3RIaWRkZW4oKTtcblxuXHRcdFx0XHRcdGNvbnN0IHsgaWQsIHBlZXJOYW1lLCBhcHBEYXRhIH0gPSBub3RpZmljYXRpb247XG5cdFx0XHRcdFx0Y29uc3QgcGVlciA9IHRoaXMuX3BlZXJzLmdldChwZWVyTmFtZSk7XG5cblx0XHRcdFx0XHRjb25zdCBjb25zdW1lciA9IHBlZXIuZ2V0Q29uc3VtZXJCeUlkKGlkKTtcblxuXHRcdFx0XHRcdGlmICghY29uc3VtZXIpXG5cdFx0XHRcdFx0XHR0aHJvdyBuZXcgRXJyb3IoYENvbnN1bWVyIG5vdCBmb3VuZCBbaWQ6JHtpZH1dYCk7XG5cblx0XHRcdFx0XHRjb25zdW1lci5yZW1vdGVSZXN1bWUoYXBwRGF0YSk7XG5cblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGRlZmF1bHQ6XG5cdFx0XHRcdFx0dGhyb3cgbmV3IEVycm9yKGB1bmtub3duIG5vdGlmaWNhdGlvbiBtZXRob2QgXCIke21ldGhvZH1cImApO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRjYXRjaCAoZXJyb3IpXG5cdFx0e1xuXHRcdFx0bG9nZ2VyLmVycm9yKFxuXHRcdFx0XHQncmVjZWl2ZU5vdGlmaWNhdGlvbigpIGZhaWxlZCBbbm90aWZpY2F0aW9uOiVvXTogJXMnLFxuXHRcdFx0XHRub3RpZmljYXRpb24sIGVycm9yLnRvU3RyaW5nKCkpO1xuXHRcdH1cblx0fVxuXG5cdF9zZW5kUmVxdWVzdChtZXRob2QsIGRhdGEpXG5cdHtcblx0XHRjb25zdCByZXF1ZXN0ID0gT2JqZWN0LmFzc2lnbih7IG1ldGhvZCB9LCBkYXRhKTtcblxuXHRcdC8vIFNob3VsZCBuZXZlciBoYXBwZW4uXG5cdFx0Ly8gSWdub3JlIGlmIGNsb3NlZC5cblx0XHRpZiAodGhpcy5jbG9zZWQpXG5cdFx0e1xuXHRcdFx0bG9nZ2VyLmVycm9yKFxuXHRcdFx0XHQnX3NlbmRSZXF1ZXN0KCkgfCBSb29tIGNsb3NlZCBbbWV0aG9kOiVzLCByZXF1ZXN0OiVvXScsXG5cdFx0XHRcdG1ldGhvZCwgcmVxdWVzdCk7XG5cblx0XHRcdHJldHVybiBQcm9taXNlLnJlamVjdChuZXcgSW52YWxpZFN0YXRlRXJyb3IoJ1Jvb20gY2xvc2VkJykpO1xuXHRcdH1cblxuXHRcdGxvZ2dlci5kZWJ1ZygnX3NlbmRSZXF1ZXN0KCkgW21ldGhvZDolcywgcmVxdWVzdDolb10nLCBtZXRob2QsIHJlcXVlc3QpO1xuXG5cdFx0cmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+XG5cdFx0e1xuXHRcdFx0bGV0IGRvbmUgPSBmYWxzZTtcblxuXHRcdFx0Y29uc3QgdGltZXIgPSBzZXRUaW1lb3V0KCgpID0+XG5cdFx0XHR7XG5cdFx0XHRcdGxvZ2dlci5lcnJvcihcblx0XHRcdFx0XHQncmVxdWVzdCBmYWlsZWQgW21ldGhvZDolc106IHRpbWVvdXQnLCBtZXRob2QpO1xuXG5cdFx0XHRcdGRvbmUgPSB0cnVlO1xuXHRcdFx0XHRyZWplY3QobmV3IFRpbWVvdXRFcnJvcigndGltZW91dCcpKTtcblx0XHRcdH0sIHRoaXMuX3NldHRpbmdzLnJlcXVlc3RUaW1lb3V0KTtcblxuXHRcdFx0Ly8gVE9ETzogV2UgY291bGQgYWxzbyBoYW5kbGUgcm9vbSAnY2xvc2VkJyBldmVudCBoZXJlLlxuXG5cdFx0XHRjb25zdCBjYWxsYmFjayA9IChyZXNwb25zZSkgPT5cblx0XHRcdHtcblx0XHRcdFx0aWYgKGRvbmUpXG5cdFx0XHRcdFx0cmV0dXJuO1xuXG5cdFx0XHRcdGRvbmUgPSB0cnVlO1xuXHRcdFx0XHRjbGVhclRpbWVvdXQodGltZXIpO1xuXG5cdFx0XHRcdGlmICh0aGlzLmNsb3NlZClcblx0XHRcdFx0e1xuXHRcdFx0XHRcdGxvZ2dlci5lcnJvcihcblx0XHRcdFx0XHRcdCdyZXF1ZXN0IGZhaWxlZCBbbWV0aG9kOiVzXTogUm9vbSBjbG9zZWQnLCBtZXRob2QpO1xuXG5cdFx0XHRcdFx0cmVqZWN0KG5ldyBFcnJvcignUm9vbSBjbG9zZWQnKSk7XG5cblx0XHRcdFx0XHRyZXR1cm47XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRsb2dnZXIuZGVidWcoXG5cdFx0XHRcdFx0J3JlcXVlc3Qgc3VjY2VlZGVkIFttZXRob2Q6JXMsIHJlc3BvbnNlOiVvXScsIG1ldGhvZCwgcmVzcG9uc2UpO1xuXG5cdFx0XHRcdHJlc29sdmUocmVzcG9uc2UpO1xuXHRcdFx0fTtcblxuXHRcdFx0Y29uc3QgZXJyYmFjayA9IChtZXNzYWdlKSA9PlxuXHRcdFx0e1xuXHRcdFx0XHRpZiAoZG9uZSlcblx0XHRcdFx0XHRyZXR1cm47XG5cblx0XHRcdFx0ZG9uZSA9IHRydWU7XG5cdFx0XHRcdGNsZWFyVGltZW91dCh0aW1lcik7XG5cblx0XHRcdFx0aWYgKHRoaXMuY2xvc2VkKVxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0bG9nZ2VyLmVycm9yKFxuXHRcdFx0XHRcdFx0J3JlcXVlc3QgZmFpbGVkIFttZXRob2Q6JXNdOiBSb29tIGNsb3NlZCcsIG1ldGhvZCk7XG5cblx0XHRcdFx0XHRyZWplY3QobmV3IEVycm9yKCdSb29tIGNsb3NlZCcpKTtcblxuXHRcdFx0XHRcdHJldHVybjtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIE1ha2Ugc3VyZSBtZXNzYWdlIGlzIGEgU3RyaW5nLlxuXHRcdFx0XHRtZXNzYWdlID0gU3RyaW5nKG1lc3NhZ2UpO1xuXG5cdFx0XHRcdGxvZ2dlci5lcnJvcihcblx0XHRcdFx0XHQncmVxdWVzdCBmYWlsZWQgW21ldGhvZDolc106ICVzJywgbWV0aG9kLCBtZXNzYWdlKTtcblxuXHRcdFx0XHRyZWplY3QobmV3IEVycm9yKG1lc3NhZ2UpKTtcblx0XHRcdH07XG5cblx0XHRcdHRoaXMuc2FmZUVtaXQoJ3JlcXVlc3QnLCByZXF1ZXN0LCBjYWxsYmFjaywgZXJyYmFjayk7XG5cdFx0fSk7XG5cdH1cblxuXHRfc2VuZE5vdGlmaWNhdGlvbihtZXRob2QsIGRhdGEpXG5cdHtcblx0XHQvLyBJZ25vcmUgaWYgY2xvc2VkLlxuXHRcdGlmICh0aGlzLmNsb3NlZClcblx0XHRcdHJldHVybjtcblxuXHRcdGNvbnN0IG5vdGlmaWNhdGlvbiA9IE9iamVjdC5hc3NpZ24oeyBtZXRob2QsIG5vdGlmaWNhdGlvbjogdHJ1ZSB9LCBkYXRhKTtcblxuXHRcdGxvZ2dlci5kZWJ1Zyhcblx0XHRcdCdfc2VuZE5vdGlmaWNhdGlvbigpIFttZXRob2Q6JXMsIG5vdGlmaWNhdGlvbjolb10nLCBtZXRob2QsIG5vdGlmaWNhdGlvbik7XG5cblx0XHR0aGlzLnNhZmVFbWl0KCdub3RpZnknLCBub3RpZmljYXRpb24pO1xuXHR9XG5cblx0X2Vuc3VyZU5vdEhpZGRlbigpXG5cdHtcblx0XHRpZiAodGhpcy5fc2V0dGluZ3MuaGlkZGVuKVxuXHRcdFx0dGhyb3cgbmV3IEVycm9yKCdoaWRkZW4gbW9kZSBzZXQnKTtcblx0fVxuXG5cdF9oYW5kbGVQZWVyRGF0YShwZWVyRGF0YSlcblx0e1xuXHRcdGNvbnN0IHsgbmFtZSwgY29uc3VtZXJzLCBhcHBEYXRhIH0gPSBwZWVyRGF0YTtcblx0XHRjb25zdCBwZWVyID0gbmV3IFBlZXIobmFtZSwgYXBwRGF0YSk7XG5cblx0XHQvLyBTdG9yZSBpdC5cblx0XHR0aGlzLl9wZWVycy5zZXQocGVlci5uYW1lLCBwZWVyKTtcblxuXHRcdHBlZXIub24oJ0BjbG9zZScsICgpID0+XG5cdFx0e1xuXHRcdFx0dGhpcy5fcGVlcnMuZGVsZXRlKHBlZXIubmFtZSk7XG5cdFx0fSk7XG5cblx0XHQvLyBBZGQgY29uc3VtZXJzLlxuXHRcdGZvciAoY29uc3QgY29uc3VtZXJEYXRhIG9mIGNvbnN1bWVycylcblx0XHR7XG5cdFx0XHR0cnlcblx0XHRcdHtcblx0XHRcdFx0dGhpcy5faGFuZGxlQ29uc3VtZXJEYXRhKGNvbnN1bWVyRGF0YSwgcGVlcik7XG5cdFx0XHR9XG5cdFx0XHRjYXRjaCAoZXJyb3IpXG5cdFx0XHR7XG5cdFx0XHRcdGxvZ2dlci5lcnJvcignZXJyb3IgaGFuZGxpbmcgZXhpc3RpbmcgQ29uc3VtZXIgaW4gUGVlcjolbycsIGVycm9yKTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHQvLyBJZiBhbHJlYWR5IGpvaW5lZCBlbWl0IGV2ZW50LlxuXHRcdGlmICh0aGlzLmpvaW5lZClcblx0XHRcdHRoaXMuc2FmZUVtaXQoJ25ld3BlZXInLCBwZWVyKTtcblx0fVxuXG5cdF9oYW5kbGVDb25zdW1lckRhdGEocHJvZHVjZXJEYXRhLCBwZWVyKVxuXHR7XG5cdFx0Y29uc3QgeyBpZCwga2luZCwgcnRwUGFyYW1ldGVycywgcGF1c2VkLCBhcHBEYXRhIH0gPSBwcm9kdWNlckRhdGE7XG5cdFx0Y29uc3QgY29uc3VtZXIgPSBuZXcgQ29uc3VtZXIoaWQsIGtpbmQsIHJ0cFBhcmFtZXRlcnMsIHBlZXIsIGFwcERhdGEpO1xuXHRcdGNvbnN0IHN1cHBvcnRlZCA9XG5cdFx0XHR1dGlscy5jYW5SZWNlaXZlKGNvbnN1bWVyLnJ0cFBhcmFtZXRlcnMsIHRoaXMuX2V4dGVuZGVkUnRwQ2FwYWJpbGl0aWVzKTtcblxuXHRcdGlmIChzdXBwb3J0ZWQpXG5cdFx0XHRjb25zdW1lci5zZXRTdXBwb3J0ZWQodHJ1ZSk7XG5cblx0XHRpZiAocGF1c2VkKVxuXHRcdFx0Y29uc3VtZXIucmVtb3RlUGF1c2UoKTtcblxuXHRcdHBlZXIuYWRkQ29uc3VtZXIoY29uc3VtZXIpO1xuXHR9XG59XG4iLCJpbXBvcnQgTG9nZ2VyIGZyb20gJy4vTG9nZ2VyJztcbmltcG9ydCBFbmhhbmNlZEV2ZW50RW1pdHRlciBmcm9tICcuL0VuaGFuY2VkRXZlbnRFbWl0dGVyJztcbmltcG9ydCAqIGFzIHV0aWxzIGZyb20gJy4vdXRpbHMnO1xuaW1wb3J0IERldmljZSBmcm9tICcuL0RldmljZSc7XG5pbXBvcnQgQ29tbWFuZFF1ZXVlIGZyb20gJy4vQ29tbWFuZFF1ZXVlJztcblxuY29uc3QgbG9nZ2VyID0gbmV3IExvZ2dlcignVHJhbnNwb3J0Jyk7XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFRyYW5zcG9ydCBleHRlbmRzIEVuaGFuY2VkRXZlbnRFbWl0dGVyXG57XG5cdC8qKlxuXHQgKiBAcHJpdmF0ZVxuXHQgKlxuXHQgKiBAZW1pdHMge3N0YXRlOiBTdHJpbmd9IGNvbm5lY3Rpb25zdGF0ZWNoYW5nZVxuXHQgKiBAZW1pdHMge29yaWdpbmF0b3I6IFN0cmluZywgW2FwcERhdGFdOiBBbnl9IGNsb3NlZFxuXHQgKiBAZW1pdHMge21ldGhvZDogU3RyaW5nLCBbZGF0YV06IE9iamVjdCwgY2FsbGJhY2s6IEZ1bmN0aW9uLCBlcnJiYWNrOiBGdW5jdGlvbn0gQHJlcXVlc3Rcblx0ICogQGVtaXRzIHttZXRob2Q6IFN0cmluZywgW2RhdGFdOiBPYmplY3R9IEBub3RpZnlcblx0ICogQGVtaXRzIHtvcmlnaW5hdG9yOiBTdHJpbmd9IEBjbG9zZVxuXHQgKi9cblx0Y29uc3RydWN0b3IoZGlyZWN0aW9uLCBleHRlbmRlZFJ0cENhcGFiaWxpdGllcywgc2V0dGluZ3MsIGFwcERhdGEpXG5cdHtcblx0XHRsb2dnZXIuZGVidWcoJ2NvbnN0cnVjdG9yKCkgW2RpcmVjdGlvbjolcywgZXh0ZW5kZWRSdHBDYXBhYmlsaXRpZXM6JW9dJyxcblx0XHRcdGRpcmVjdGlvbiwgZXh0ZW5kZWRSdHBDYXBhYmlsaXRpZXMpO1xuXG5cdFx0c3VwZXIoKTtcblxuXHRcdC8vIElkLlxuXHRcdC8vIEB0eXBlIHtOdW1iZXJ9XG5cdFx0dGhpcy5faWQgPSB1dGlscy5yYW5kb21OdW1iZXIoKTtcblxuXHRcdC8vIENsb3NlZCBmbGFnLlxuXHRcdC8vIEB0eXBlIHtCb29sZWFufVxuXHRcdHRoaXMuX2Nsb3NlZCA9IGZhbHNlO1xuXG5cdFx0Ly8gRGlyZWN0aW9uLlxuXHRcdC8vIEB0eXBlIHtTdHJpbmd9XG5cdFx0dGhpcy5fZGlyZWN0aW9uID0gZGlyZWN0aW9uO1xuXG5cdFx0Ly8gUm9vbSBzZXR0aW5ncy5cblx0XHQvLyBAdHlwZSB7T2JqZWN0fVxuXHRcdHRoaXMuX3NldHRpbmdzID0gc2V0dGluZ3M7XG5cblx0XHQvLyBBcHAgY3VzdG9tIGRhdGEuXG5cdFx0Ly8gQHR5cGUge0FueX1cblx0XHR0aGlzLl9hcHBEYXRhID0gYXBwRGF0YTtcblxuXHRcdC8vIE1hcCBvZiBQcm9kdWNlcnMgaW5kZXhlZCBieSBpZC5cblx0XHQvLyBAdHlwZSB7bWFwPE51bWJlciwgUHJvZHVjZXI+fVxuXHRcdHRoaXMuX3Byb2R1Y2VycyA9IG5ldyBNYXAoKTtcblxuXHRcdC8vIE1hcCBvZiBDb25zdW1lcnMgaW5kZXhlZCBieSBpZC5cblx0XHQvLyBAdHlwZSB7bWFwPE51bWJlciwgQ29uc3VtZXI+fVxuXHRcdHRoaXMuX2NvbnN1bWVycyA9IG5ldyBNYXAoKTtcblxuXHRcdC8vIENvbW1hbmRzIGhhbmRsZXIuXG5cdFx0Ly8gQHR5cGUge0NvbW1hbmRRdWV1ZX1cblx0XHR0aGlzLl9jb21tYW5kUXVldWUgPSBuZXcgQ29tbWFuZFF1ZXVlKCk7XG5cblx0XHQvLyBEZXZpY2Ugc3BlY2lmaWMgaGFuZGxlci5cblx0XHR0aGlzLl9oYW5kbGVyID0gbmV3IERldmljZS5IYW5kbGVyKGRpcmVjdGlvbiwgZXh0ZW5kZWRSdHBDYXBhYmlsaXRpZXMsIHNldHRpbmdzKTtcblxuXHRcdC8vIFRyYW5zcG9ydCBzdGF0ZS4gVmFsdWVzIGNhbiBiZTpcblx0XHQvLyAnbmV3Jy8nY29ubmVjdGluZycvJ2Nvbm5lY3RlZCcvJ2ZhaWxlZCcvJ2Rpc2Nvbm5lY3RlZCcvJ2Nsb3NlZCdcblx0XHQvLyBAdHlwZSB7U3RyaW5nfVxuXHRcdHRoaXMuX2Nvbm5lY3Rpb25TdGF0ZSA9ICduZXcnO1xuXG5cdFx0dGhpcy5fY29tbWFuZFF1ZXVlLm9uKCdleGVjJywgdGhpcy5fZXhlY0NvbW1hbmQuYmluZCh0aGlzKSk7XG5cdFx0dGhpcy5faGFuZGxlSGFuZGxlcigpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFRyYW5zcG9ydCBpZC5cblx0ICpcblx0ICogQHJldHVybiB7TnVtYmVyfVxuXHQgKi9cblx0Z2V0IGlkKClcblx0e1xuXHRcdHJldHVybiB0aGlzLl9pZDtcblx0fVxuXG5cdC8qKlxuXHQgKiBXaGV0aGVyIHRoZSBUcmFuc3BvcnQgaXMgY2xvc2VkLlxuXHQgKlxuXHQgKiBAcmV0dXJuIHtCb29sZWFufVxuXHQgKi9cblx0Z2V0IGNsb3NlZCgpXG5cdHtcblx0XHRyZXR1cm4gdGhpcy5fY2xvc2VkO1xuXHR9XG5cblx0LyoqXG5cdCAqIFRyYW5zcG9ydCBkaXJlY3Rpb24uXG5cdCAqXG5cdCAqIEByZXR1cm4ge1N0cmluZ31cblx0ICovXG5cdGdldCBkaXJlY3Rpb24oKVxuXHR7XG5cdFx0cmV0dXJuIHRoaXMuX2RpcmVjdGlvbjtcblx0fVxuXG5cdC8qKlxuXHQgKiBBcHAgY3VzdG9tIGRhdGEuXG5cdCAqXG5cdCAqIEByZXR1cm4ge0FueX1cblx0ICovXG5cdGdldCBhcHBEYXRhKClcblx0e1xuXHRcdHJldHVybiB0aGlzLl9hcHBEYXRhO1xuXHR9XG5cblx0LyoqXG5cdCAqIENvbm5lY3Rpb24gc3RhdGUuXG5cdCAqXG5cdCAqIEByZXR1cm4ge1N0cmluZ31cblx0ICovXG5cdGdldCBjb25uZWN0aW9uU3RhdGUoKVxuXHR7XG5cdFx0cmV0dXJuIHRoaXMuX2Nvbm5lY3Rpb25TdGF0ZTtcblx0fVxuXG5cdC8qKlxuXHQgKiBDbG9zZSB0aGUgVHJhbnNwb3J0LlxuXHQgKlxuXHQgKiBAcGFyYW0ge0FueX0gW2FwcERhdGFdIC0gQXBwIGN1c3RvbSBkYXRhLlxuXHQgKi9cblx0Y2xvc2UoYXBwRGF0YSlcblx0e1xuXHRcdGxvZ2dlci5kZWJ1ZygnY2xvc2UoKScpO1xuXG5cdFx0aWYgKHRoaXMuX2Nsb3NlZClcblx0XHRcdHJldHVybjtcblxuXHRcdHRoaXMuX2Nsb3NlZCA9IHRydWU7XG5cblx0XHR0aGlzLnNhZmVFbWl0KFxuXHRcdFx0J0Bub3RpZnknLCAnY2xvc2VUcmFuc3BvcnQnLCB7IGlkOiB0aGlzLl9pZCwgYXBwRGF0YSB9KTtcblxuXHRcdHRoaXMuZW1pdCgnQGNsb3NlJywgJ2xvY2FsJyk7XG5cdFx0dGhpcy5zYWZlRW1pdCgnY2xvc2VkJywgJ2xvY2FsJywgYXBwRGF0YSk7XG5cblx0XHR0aGlzLl9kZXN0cm95KCk7XG5cdH1cblxuXHQvKipcblx0ICogTXkgcmVtb3RlIFRyYW5zcG9ydCB3YXMgY2xvc2VkLlxuXHQgKiBJbnZva2VkIHZpYSByZW1vdGUgbm90aWZpY2F0aW9uLlxuXHQgKlxuXHQgKiBAcGFyYW0ge0FueX0gW2FwcERhdGFdIC0gQXBwIGN1c3RvbSBkYXRhLlxuXHQgKi9cblx0cmVtb3RlQ2xvc2UoYXBwRGF0YSlcblx0e1xuXHRcdGxvZ2dlci5kZWJ1ZygncmVtb3RlQ2xvc2UoKScpO1xuXG5cdFx0aWYgKHRoaXMuX2Nsb3NlZClcblx0XHRcdHJldHVybjtcblxuXHRcdHRoaXMuX2Nsb3NlZCA9IHRydWU7XG5cblx0XHR0aGlzLmVtaXQoJ0BjbG9zZScsICdyZW1vdGUnKTtcblx0XHR0aGlzLnNhZmVFbWl0KCdjbG9zZWQnLCAncmVtb3RlJywgYXBwRGF0YSk7XG5cblx0XHR0aGlzLl9kZXN0cm95KCk7XG5cdH1cblxuXHRfZGVzdHJveSgpXG5cdHtcblx0XHQvLyBDbG9zZSB0aGUgQ29tbWFuZFF1ZXVlLlxuXHRcdHRoaXMuX2NvbW1hbmRRdWV1ZS5jbG9zZSgpO1xuXG5cdFx0Ly8gQ2xvc2UgdGhlIGhhbmRsZXIuXG5cdFx0dGhpcy5faGFuZGxlci5jbG9zZSgpO1xuXG5cdFx0Ly8gVW5oYW5kbGUgYWxsIHRoZSBQcm9kdWNlcnMuXG5cdFx0Zm9yIChjb25zdCBwcm9kdWNlciBvZiB0aGlzLl9wcm9kdWNlcnMudmFsdWVzKCkpXG5cdFx0e1xuXHRcdFx0cHJvZHVjZXIuc2V0SGFuZGxlZChmYWxzZSk7XG5cdFx0fVxuXG5cdFx0Ly8gVW5oYW5kbGUgYWxsIHRoZSBDb25zdW1lcnMuXG5cdFx0Zm9yIChjb25zdCBjb25zdW1lciBvZiB0aGlzLl9jb25zdW1lcnMudmFsdWVzKCkpXG5cdFx0e1xuXHRcdFx0Y29uc3VtZXIuc2V0SGFuZGxlZChmYWxzZSk7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIFNlbmQgdGhlIGdpdmVuIFByb2R1Y2VyIG92ZXIgdGhpcyBUcmFuc3BvcnQuXG5cdCAqXG5cdCAqIEBwYXJhbSB7UHJvZHVjZXJ9IHByb2R1Y2VyXG5cdCAqXG5cdCAqIEByZXR1cm4ge1Byb21pc2V9XG5cdCAqXG5cdCAqIEBleGFtcGxlXG5cdCAqIHRyYW5zcG9ydC5zZW5kKHZpZGVvUHJvZHVjZXIpXG5cdCAqICAgLnRoZW4oKCkgPT4ge1xuXHQgKiAgICAgLy8gRG9uZVxuXHQgKiAgIH0pO1xuXHQgKi9cblx0c2VuZChwcm9kdWNlcilcblx0e1xuXHRcdGxvZ2dlci5kZWJ1Zygnc2VuZCgpIFtwcm9kdWNlcjolb10nLCBwcm9kdWNlcik7XG5cblx0XHRpZiAodGhpcy5fZGlyZWN0aW9uICE9PSAnc2VuZCcpXG5cdFx0XHRyZXR1cm4gUHJvbWlzZS5yZWplY3QobmV3IEVycm9yKCdjYW5ub3Qgc2VuZCBvbiBhIHJlY2VpdmluZyBUcmFuc3BvcnQnKSk7XG5cdFx0ZWxzZSBpZiAoIXByb2R1Y2VyIHx8IHByb2R1Y2VyLmtsYXNzICE9PSAnUHJvZHVjZXInKVxuXHRcdFx0cmV0dXJuIFByb21pc2UucmVqZWN0KG5ldyBUeXBlRXJyb3IoJ3dyb25nIFByb2R1Y2VyJykpO1xuXG5cdFx0Ly8gRW5xdWV1ZSBjb21tYW5kLlxuXHRcdHJldHVybiB0aGlzLl9jb21tYW5kUXVldWUucHVzaCgnYWRkUHJvZHVjZXInLCB7IHByb2R1Y2VyIH0pO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJlY2VpdmUgdGhlIGdpdmVuIENvbnN1bWVyIG92ZXIgdGhpcyBUcmFuc3BvcnQuXG5cdCAqXG5cdCAqIEBwYXJhbSB7Q29uc3VtZXJ9IGNvbnN1bWVyXG5cdCAqXG5cdCAqIEByZXR1cm4ge1Byb21pc2V9XG5cdCAqXG5cdCAqIEBleGFtcGxlXG5cdCAqIHRyYW5zcG9ydC5yZWNlaXZlKGFsaWNlVmlkZW9Db25zdW1lcilcblx0ICogICAudGhlbigoKSA9PiB7XG5cdCAqICAgICAvLyBEb25lXG5cdCAqICAgfSk7XG5cdCAqL1xuXHRyZWNlaXZlKGNvbnN1bWVyKVxuXHR7XG5cdFx0bG9nZ2VyLmRlYnVnKCdyZWNlaXZlKCkgW2NvbnN1bWVyOiVvXScsIGNvbnN1bWVyKTtcblxuXHRcdGlmICh0aGlzLl9kaXJlY3Rpb24gIT09ICdyZWN2Jylcblx0XHRcdHJldHVybiBQcm9taXNlLnJlamVjdChuZXcgRXJyb3IoJ2Nhbm5vdCByZWNlaXZlIG9uIGEgc2VuZGluZyBUcmFuc3BvcnQnKSk7XG5cdFx0ZWxzZSBpZiAoIWNvbnN1bWVyIHx8IGNvbnN1bWVyLmtsYXNzICE9PSAnQ29uc3VtZXInKVxuXHRcdFx0cmV0dXJuIFByb21pc2UucmVqZWN0KG5ldyBUeXBlRXJyb3IoJ3dyb25nIENvbnN1bWVyJykpO1xuXG5cdFx0Ly8gRW5xdWV1ZSBjb21tYW5kLlxuXHRcdHJldHVybiB0aGlzLl9jb21tYW5kUXVldWUucHVzaCgnYWRkQ29uc3VtZXInLCB7IGNvbnN1bWVyIH0pO1xuXHR9XG5cblx0X2hhbmRsZUhhbmRsZXIoKVxuXHR7XG5cdFx0Y29uc3QgaGFuZGxlciA9IHRoaXMuX2hhbmRsZXI7XG5cblx0XHRoYW5kbGVyLm9uKCdAY29ubmVjdGlvbnN0YXRlY2hhbmdlJywgKHN0YXRlKSA9PlxuXHRcdHtcblx0XHRcdGlmICh0aGlzLl9jb25uZWN0aW9uU3RhdGUgPT09IHN0YXRlKVxuXHRcdFx0XHRyZXR1cm47XG5cblx0XHRcdHRoaXMuX2Nvbm5lY3Rpb25TdGF0ZSA9IHN0YXRlO1xuXG5cdFx0XHRpZiAoIXRoaXMuX2Nsb3NlZClcblx0XHRcdFx0dGhpcy5zYWZlRW1pdCgnY29ubmVjdGlvbnN0YXRlY2hhbmdlJywgc3RhdGUpO1xuXHRcdH0pO1xuXG5cdFx0aGFuZGxlci5vbihcblx0XHRcdCdAbmVlZGNyZWF0ZXRyYW5zcG9ydCcsXG5cdFx0XHQodHJhbnNwb3J0TG9jYWxQYXJhbWV0ZXJzLCBjYWxsYmFjaywgZXJyYmFjaykgPT5cblx0XHRcdHtcblx0XHRcdFx0Y29uc3QgZGF0YSA9XG5cdFx0XHRcdHtcblx0XHRcdFx0XHRpZCAgICAgIDogdGhpcy5faWQsXG5cdFx0XHRcdFx0b3B0aW9ucyA6IHRoaXMuX3NldHRpbmdzLnRyYW5zcG9ydE9wdGlvbnMsXG5cdFx0XHRcdFx0YXBwRGF0YSA6IHRoaXMuX2FwcERhdGFcblx0XHRcdFx0fTtcblxuXHRcdFx0XHRpZiAodHJhbnNwb3J0TG9jYWxQYXJhbWV0ZXJzKVxuXHRcdFx0XHRcdGRhdGEuZHRsc1BhcmFtZXRlcnMgPSB0cmFuc3BvcnRMb2NhbFBhcmFtZXRlcnMuZHRsc1BhcmFtZXRlcnM7XG5cblx0XHRcdFx0dGhpcy5zYWZlRW1pdCgnQHJlcXVlc3QnLCAnY3JlYXRlVHJhbnNwb3J0JywgZGF0YSwgY2FsbGJhY2ssIGVycmJhY2spO1xuXHRcdFx0fSk7XG5cblx0XHRoYW5kbGVyLm9uKCdAbmVlZHVwZGF0ZXRyYW5zcG9ydCcsICh0cmFuc3BvcnRMb2NhbFBhcmFtZXRlcnMpID0+XG5cdFx0e1xuXHRcdFx0Y29uc3QgZGF0YSA9XG5cdFx0XHR7XG5cdFx0XHRcdGlkICAgICAgICAgICAgIDogdGhpcy5faWQsXG5cdFx0XHRcdGR0bHNQYXJhbWV0ZXJzIDogdHJhbnNwb3J0TG9jYWxQYXJhbWV0ZXJzLmR0bHNQYXJhbWV0ZXJzXG5cdFx0XHR9O1xuXG5cdFx0XHR0aGlzLnNhZmVFbWl0KCdAbm90aWZ5JywgJ3VwZGF0ZVRyYW5zcG9ydCcsIGRhdGEpO1xuXHRcdH0pO1xuXHR9XG5cblx0X2V4ZWNDb21tYW5kKGNvbW1hbmQsIHByb21pc2VIb2xkZXIpXG5cdHtcblx0XHRsZXQgcHJvbWlzZTtcblxuXHRcdHRyeVxuXHRcdHtcblx0XHRcdHN3aXRjaCAoY29tbWFuZC5tZXRob2QpXG5cdFx0XHR7XG5cdFx0XHRcdGNhc2UgJ2FkZFByb2R1Y2VyJzpcblx0XHRcdFx0e1xuXHRcdFx0XHRcdGNvbnN0IHsgcHJvZHVjZXIgfSA9IGNvbW1hbmQ7XG5cblx0XHRcdFx0XHRwcm9taXNlID0gdGhpcy5fZXhlY0FkZFByb2R1Y2VyKHByb2R1Y2VyKTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGNhc2UgJ3JlbW92ZVByb2R1Y2VyJzpcblx0XHRcdFx0e1xuXHRcdFx0XHRcdGNvbnN0IHsgcHJvZHVjZXIgfSA9IGNvbW1hbmQ7XG5cblx0XHRcdFx0XHRwcm9taXNlID0gdGhpcy5fZXhlY1JlbW92ZVByb2R1Y2VyKHByb2R1Y2VyKTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGNhc2UgJ2FkZENvbnN1bWVyJzpcblx0XHRcdFx0e1xuXHRcdFx0XHRcdGNvbnN0IHsgY29uc3VtZXIgfSA9IGNvbW1hbmQ7XG5cblx0XHRcdFx0XHRwcm9taXNlID0gdGhpcy5fZXhlY0FkZENvbnN1bWVyKGNvbnN1bWVyKTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGNhc2UgJ3JlbW92ZUNvbnN1bWVyJzpcblx0XHRcdFx0e1xuXHRcdFx0XHRcdGNvbnN0IHsgY29uc3VtZXIgfSA9IGNvbW1hbmQ7XG5cblx0XHRcdFx0XHRwcm9taXNlID0gdGhpcy5fZXhlY1JlbW92ZUNvbnN1bWVyKGNvbnN1bWVyKTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGRlZmF1bHQ6XG5cdFx0XHRcdHtcblx0XHRcdFx0XHRwcm9taXNlID0gUHJvbWlzZS5yZWplY3QoXG5cdFx0XHRcdFx0XHRuZXcgRXJyb3IoYHVua25vd24gY29tbWFuZCBtZXRob2QgXCIke2NvbW1hbmQubWV0aG9kfVwiYCkpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHRcdGNhdGNoIChlcnJvcilcblx0XHR7XG5cdFx0XHRwcm9taXNlID0gUHJvbWlzZS5yZWplY3QoZXJyb3IpO1xuXHRcdH1cblxuXHRcdC8vIEZpbGwgdGhlIGdpdmVuIFByb21pc2UgaG9sZGVyLlxuXHRcdHByb21pc2VIb2xkZXIucHJvbWlzZSA9IHByb21pc2U7XG5cdH1cblxuXHRfZXhlY0FkZFByb2R1Y2VyKHByb2R1Y2VyKVxuXHR7XG5cdFx0bG9nZ2VyLmRlYnVnKCdfZXhlY0FkZFByb2R1Y2VyKCknKTtcblxuXHRcdGlmIChwcm9kdWNlci5jbG9zZWQpXG5cdFx0XHRyZXR1cm4gUHJvbWlzZS5yZWplY3QobmV3IEVycm9yKCdQcm9kdWNlciBjbG9zZWQnKSk7XG5cdFx0ZWxzZSBpZiAocHJvZHVjZXIuaGFuZGxlZClcblx0XHRcdHJldHVybiBQcm9taXNlLnJlamVjdChuZXcgRXJyb3IoJ1Byb2R1Y2VyIGFscmVhZHkgaGFuZGxlZCBieSBhIFRyYW5zcG9ydCcpKTtcblxuXHRcdGxldCBwcm9kdWNlclJ0cFBhcmFtZXRlcnM7XG5cblx0XHRwcm9kdWNlci5zZXRIYW5kbGVkKCd0bXAnKTtcblxuXHRcdC8vIENhbGwgdGhlIGhhbmRsZXIuXG5cdFx0cmV0dXJuIFByb21pc2UucmVzb2x2ZSgpXG5cdFx0XHQudGhlbigoKSA9PlxuXHRcdFx0e1xuXHRcdFx0XHRyZXR1cm4gdGhpcy5faGFuZGxlci5hZGRQcm9kdWNlcihwcm9kdWNlcik7XG5cdFx0XHR9KVxuXHRcdFx0LnRoZW4oKHJ0cFBhcmFtZXRlcnMpID0+XG5cdFx0XHR7XG5cdFx0XHRcdHByb2R1Y2VyUnRwUGFyYW1ldGVycyA9IHJ0cFBhcmFtZXRlcnM7XG5cblx0XHRcdFx0Y29uc3QgZGF0YSA9XG5cdFx0XHRcdHtcblx0XHRcdFx0XHRpZCAgICAgICAgICAgIDogcHJvZHVjZXIuaWQsXG5cdFx0XHRcdFx0a2luZCAgICAgICAgICA6IHByb2R1Y2VyLmtpbmQsXG5cdFx0XHRcdFx0dHJhbnNwb3J0SWQgICA6IHRoaXMuX2lkLFxuXHRcdFx0XHRcdHJ0cFBhcmFtZXRlcnMgOiBydHBQYXJhbWV0ZXJzLFxuXHRcdFx0XHRcdGFwcERhdGEgICAgICAgOiBwcm9kdWNlci5hcHBEYXRhXG5cdFx0XHRcdH07XG5cblx0XHRcdFx0cmV0dXJuIHRoaXMuc2FmZUVtaXRBc1Byb21pc2UoJ0ByZXF1ZXN0JywgJ2NyZWF0ZVByb2R1Y2VyJywgZGF0YSk7XG5cdFx0XHR9KVxuXHRcdFx0LnRoZW4oKCkgPT5cblx0XHRcdHtcblx0XHRcdFx0cHJvZHVjZXIuc2V0SGFuZGxlZCh0cnVlLCBwcm9kdWNlclJ0cFBhcmFtZXRlcnMpO1xuXHRcdFx0XHR0aGlzLl9wcm9kdWNlcnMuc2V0KHByb2R1Y2VyLmlkLCBwcm9kdWNlcik7XG5cdFx0XHRcdHRoaXMuX2hhbmRsZVByb2R1Y2VyKHByb2R1Y2VyKTtcblx0XHRcdH0pXG5cdFx0XHQuY2F0Y2goKGVycm9yKSA9PlxuXHRcdFx0e1xuXHRcdFx0XHRwcm9kdWNlci5zZXRIYW5kbGVkKGZhbHNlKTtcblxuXHRcdFx0XHR0aHJvdyBlcnJvcjtcblx0XHRcdH0pO1xuXHR9XG5cblx0X2V4ZWNSZW1vdmVQcm9kdWNlcihwcm9kdWNlcilcblx0e1xuXHRcdGxvZ2dlci5kZWJ1ZygnX2V4ZWNSZW1vdmVQcm9kdWNlcigpJyk7XG5cblx0XHQvLyBDYWxsIHRoZSBoYW5kbGVyLlxuXHRcdHJldHVybiB0aGlzLl9oYW5kbGVyLnJlbW92ZVByb2R1Y2VyKHByb2R1Y2VyKTtcblx0fVxuXG5cdF9leGVjQWRkQ29uc3VtZXIoY29uc3VtZXIpXG5cdHtcblx0XHRsb2dnZXIuZGVidWcoJ19leGVjQWRkQ29uc3VtZXIoKScpO1xuXG5cdFx0aWYgKGNvbnN1bWVyLmNsb3NlZClcblx0XHRcdHJldHVybiBQcm9taXNlLnJlamVjdChuZXcgRXJyb3IoJ0NvbnN1bWVyIGNsb3NlZCcpKTtcblx0XHRlbHNlIGlmIChjb25zdW1lci5oYW5kbGVkKVxuXHRcdFx0cmV0dXJuIFByb21pc2UucmVqZWN0KG5ldyBFcnJvcignQ29uc3VtZXIgYWxyZWFkeSBoYW5kbGVkIGJ5IGEgVHJhbnNwb3J0JykpO1xuXG5cdFx0Ly8gQ2hlY2sgd2hldGhlciB3ZSBjYW4gcmVjZWl2ZSB0aGlzIENvbnN1bWVyLlxuXHRcdGlmICghY29uc3VtZXIuc3VwcG9ydGVkKVxuXHRcdHtcblx0XHRcdHJldHVybiBQcm9taXNlLnJlamVjdChcblx0XHRcdFx0bmV3IEVycm9yKCdjYW5ub3QgcmVjZWl2ZSB0aGlzIENvbnN1bWVyLCB1bnN1cHBvcnRlZCBjb2RlY3MnKSk7XG5cdFx0fVxuXG5cdFx0bGV0IGNvbnN1bWVyVHJhY2s7XG5cblx0XHRjb25zdW1lci5zZXRIYW5kbGVkKCd0bXAnKTtcblxuXHRcdC8vIENhbGwgdGhlIGhhbmRsZXIuXG5cdFx0cmV0dXJuIFByb21pc2UucmVzb2x2ZSgpXG5cdFx0XHQudGhlbigoKSA9PlxuXHRcdFx0e1xuXHRcdFx0XHRyZXR1cm4gdGhpcy5faGFuZGxlci5hZGRDb25zdW1lcihjb25zdW1lcik7XG5cdFx0XHR9KVxuXHRcdFx0LnRoZW4oKHRyYWNrKSA9PlxuXHRcdFx0e1xuXHRcdFx0XHRjb25zdW1lclRyYWNrID0gdHJhY2s7XG5cblx0XHRcdFx0Y29uc3QgZGF0YSA9XG5cdFx0XHRcdHtcblx0XHRcdFx0XHRpZCA6IGNvbnN1bWVyLmlkXG5cdFx0XHRcdH07XG5cblx0XHRcdFx0cmV0dXJuIHRoaXMuc2FmZUVtaXRBc1Byb21pc2UoJ0ByZXF1ZXN0JywgJ2VuYWJsZUNvbnN1bWVyJywgZGF0YSk7XG5cdFx0XHR9KVxuXHRcdFx0LnRoZW4oKCkgPT5cblx0XHRcdHtcblx0XHRcdFx0Y29uc3VtZXIuc2V0SGFuZGxlZCh0cnVlLCBjb25zdW1lclRyYWNrKTtcblx0XHRcdFx0dGhpcy5fY29uc3VtZXJzLnNldChjb25zdW1lci5pZCwgY29uc3VtZXIpO1xuXHRcdFx0XHR0aGlzLl9oYW5kbGVDb25zdW1lcihjb25zdW1lcik7XG5cblx0XHRcdFx0cmV0dXJuIGNvbnN1bWVyVHJhY2s7XG5cdFx0XHR9KVxuXHRcdFx0LmNhdGNoKChlcnJvcikgPT5cblx0XHRcdHtcblx0XHRcdFx0Y29uc3VtZXIuc2V0SGFuZGxlZChmYWxzZSk7XG5cblx0XHRcdFx0dGhyb3cgZXJyb3I7XG5cdFx0XHR9KTtcblx0fVxuXG5cdF9leGVjUmVtb3ZlQ29uc3VtZXIoY29uc3VtZXIpXG5cdHtcblx0XHRsb2dnZXIuZGVidWcoJ19leGVjUmVtb3ZlQ29uc3VtZXIoKScpO1xuXG5cdFx0Ly8gQ2FsbCB0aGUgaGFuZGxlci5cblx0XHRyZXR1cm4gdGhpcy5faGFuZGxlci5yZW1vdmVDb25zdW1lcihjb25zdW1lcik7XG5cdH1cblxuXHRfaGFuZGxlUHJvZHVjZXIocHJvZHVjZXIpXG5cdHtcblx0XHRwcm9kdWNlci5vbignQGNsb3NlJywgKG9yaWdpbmF0b3IsIGFwcERhdGEpID0+XG5cdFx0e1xuXHRcdFx0dGhpcy5fcHJvZHVjZXJzLmRlbGV0ZShwcm9kdWNlci5pZCk7XG5cblx0XHRcdC8vIEVucXVldWUgY29tbWFuZC5cblx0XHRcdHRoaXMuX2NvbW1hbmRRdWV1ZS5wdXNoKCdyZW1vdmVQcm9kdWNlcicsIHsgcHJvZHVjZXIgfSlcblx0XHRcdFx0LmNhdGNoKCgpID0+IHt9KTtcblxuXHRcdFx0aWYgKG9yaWdpbmF0b3IgPT09ICdsb2NhbCcpXG5cdFx0XHR7XG5cdFx0XHRcdHRoaXMuc2FmZUVtaXQoXG5cdFx0XHRcdFx0J0Bub3RpZnknLCAnY2xvc2VQcm9kdWNlcicsIHsgaWQ6IHByb2R1Y2VyLmlkLCBhcHBEYXRhIH0pO1xuXHRcdFx0fVxuXHRcdH0pO1xuXG5cdFx0cHJvZHVjZXIub24oJ0BwYXVzZScsIChhcHBEYXRhKSA9PlxuXHRcdHtcblx0XHRcdGNvbnN0IGRhdGEgPVxuXHRcdFx0e1xuXHRcdFx0XHRpZCAgICAgIDogcHJvZHVjZXIuaWQsXG5cdFx0XHRcdGFwcERhdGEgOiBhcHBEYXRhXG5cdFx0XHR9O1xuXG5cdFx0XHR0aGlzLnNhZmVFbWl0KCdAbm90aWZ5JywgJ3BhdXNlUHJvZHVjZXInLCBkYXRhKTtcblx0XHR9KTtcblxuXHRcdHByb2R1Y2VyLm9uKCdAcmVzdW1lJywgKGFwcERhdGEpID0+XG5cdFx0e1xuXHRcdFx0Y29uc3QgZGF0YSA9XG5cdFx0XHR7XG5cdFx0XHRcdGlkICAgICAgOiBwcm9kdWNlci5pZCxcblx0XHRcdFx0YXBwRGF0YSA6IGFwcERhdGFcblx0XHRcdH07XG5cblx0XHRcdHRoaXMuc2FmZUVtaXQoJ0Bub3RpZnknLCAncmVzdW1lUHJvZHVjZXInLCBkYXRhKTtcblx0XHR9KTtcblx0fVxuXG5cdF9oYW5kbGVDb25zdW1lcihjb25zdW1lcilcblx0e1xuXHRcdGNvbnN1bWVyLm9uKCdAY2xvc2UnLCAoKSA9PlxuXHRcdHtcblx0XHRcdHRoaXMuX2NvbnN1bWVycy5kZWxldGUoY29uc3VtZXIuaWQpO1xuXG5cdFx0XHQvLyBFbnF1ZXVlIGNvbW1hbmQuXG5cdFx0XHR0aGlzLl9jb21tYW5kUXVldWUucHVzaCgncmVtb3ZlQ29uc3VtZXInLCB7IGNvbnN1bWVyIH0pXG5cdFx0XHRcdC5jYXRjaCgoKSA9PiB7fSk7XG5cdFx0fSk7XG5cblx0XHRjb25zdW1lci5vbignQHBhdXNlJywgKGFwcERhdGEpID0+XG5cdFx0e1xuXHRcdFx0Y29uc3QgZGF0YSA9XG5cdFx0XHR7XG5cdFx0XHRcdGlkICAgICAgOiBjb25zdW1lci5pZCxcblx0XHRcdFx0YXBwRGF0YSA6IGFwcERhdGFcblx0XHRcdH07XG5cblx0XHRcdHRoaXMuc2FmZUVtaXQoJ0Bub3RpZnknLCAncGF1c2VDb25zdW1lcicsIGRhdGEpO1xuXHRcdH0pO1xuXG5cdFx0Y29uc3VtZXIub24oJ0ByZXN1bWUnLCAoYXBwRGF0YSkgPT5cblx0XHR7XG5cdFx0XHRjb25zdCBkYXRhID1cblx0XHRcdHtcblx0XHRcdFx0aWQgICAgICA6IGNvbnN1bWVyLmlkLFxuXHRcdFx0XHRhcHBEYXRhIDogYXBwRGF0YVxuXHRcdFx0fTtcblxuXHRcdFx0dGhpcy5zYWZlRW1pdCgnQG5vdGlmeScsICdyZXN1bWVDb25zdW1lcicsIGRhdGEpO1xuXHRcdH0pO1xuXHR9XG59XG4iLCIvKipcbiAqIEVycm9yIHByb2R1Y2VkIHdoZW4gY2FsbGluZyBhIG1ldGhvZCBpbiBhbiBpbnZhbGlkIHN0YXRlLlxuICovXG5leHBvcnQgY2xhc3MgSW52YWxpZFN0YXRlRXJyb3IgZXh0ZW5kcyBFcnJvclxue1xuXHRjb25zdHJ1Y3RvcihtZXNzYWdlKVxuXHR7XG5cdFx0c3VwZXIobWVzc2FnZSk7XG5cblx0XHRPYmplY3QuZGVmaW5lUHJvcGVydHkodGhpcywgJ25hbWUnLFxuXHRcdFx0e1xuXHRcdFx0XHRlbnVtZXJhYmxlIDogZmFsc2UsXG5cdFx0XHRcdHdyaXRhYmxlICAgOiBmYWxzZSxcblx0XHRcdFx0dmFsdWUgICAgICA6ICdJbnZhbGlkU3RhdGVFcnJvcidcblx0XHRcdH0pO1xuXG5cdFx0aWYgKEVycm9yLmhhc093blByb3BlcnR5KCdjYXB0dXJlU3RhY2tUcmFjZScpKSAvLyBKdXN0IGluIFY4LlxuXHRcdHtcblx0XHRcdEVycm9yLmNhcHR1cmVTdGFja1RyYWNlKHRoaXMsIEludmFsaWRTdGF0ZUVycm9yKTtcblx0XHR9XG5cdFx0ZWxzZVxuXHRcdHtcblx0XHRcdE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAnc3RhY2snLFxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0ZW51bWVyYWJsZSA6IGZhbHNlLFxuXHRcdFx0XHRcdHdyaXRhYmxlICAgOiBmYWxzZSxcblx0XHRcdFx0XHR2YWx1ZSAgICAgIDogKG5ldyBFcnJvcihtZXNzYWdlKSkuc3RhY2tcblx0XHRcdFx0fSk7XG5cdFx0fVxuXHR9XG59XG5cbi8qKlxuICogRXJyb3IgcHJvZHVjZWQgd2hlbiBhIFByb21pc2UgaXMgcmVqZWN0ZWQgZHVlIHRvIGEgdGltZW91dC5cbiAqL1xuZXhwb3J0IGNsYXNzIFRpbWVvdXRFcnJvciBleHRlbmRzIEVycm9yXG57XG5cdGNvbnN0cnVjdG9yKG1lc3NhZ2UpXG5cdHtcblx0XHRzdXBlcihtZXNzYWdlKTtcblxuXHRcdE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAnbmFtZScsXG5cdFx0XHR7XG5cdFx0XHRcdGVudW1lcmFibGUgOiBmYWxzZSxcblx0XHRcdFx0d3JpdGFibGUgICA6IGZhbHNlLFxuXHRcdFx0XHR2YWx1ZSAgICAgIDogJ1RpbWVvdXRFcnJvcidcblx0XHRcdH0pO1xuXG5cdFx0aWYgKEVycm9yLmhhc093blByb3BlcnR5KCdjYXB0dXJlU3RhY2tUcmFjZScpKSAvLyBKdXN0IGluIFY4LlxuXHRcdHtcblx0XHRcdEVycm9yLmNhcHR1cmVTdGFja1RyYWNlKHRoaXMsIFRpbWVvdXRFcnJvcik7XG5cdFx0fVxuXHRcdGVsc2Vcblx0XHR7XG5cdFx0XHRPYmplY3QuZGVmaW5lUHJvcGVydHkodGhpcywgJ3N0YWNrJyxcblx0XHRcdFx0e1xuXHRcdFx0XHRcdGVudW1lcmFibGUgOiBmYWxzZSxcblx0XHRcdFx0XHR3cml0YWJsZSAgIDogZmFsc2UsXG5cdFx0XHRcdFx0dmFsdWUgICAgICA6IChuZXcgRXJyb3IobWVzc2FnZSkpLnN0YWNrXG5cdFx0XHRcdH0pO1xuXHRcdH1cblx0fVxufVxuIiwiaW1wb3J0IHNkcFRyYW5zZm9ybSBmcm9tICdzZHAtdHJhbnNmb3JtJztcbmltcG9ydCBMb2dnZXIgZnJvbSAnLi4vTG9nZ2VyJztcbmltcG9ydCBFbmhhbmNlZEV2ZW50RW1pdHRlciBmcm9tICcuLi9FbmhhbmNlZEV2ZW50RW1pdHRlcic7XG5pbXBvcnQgKiBhcyB1dGlscyBmcm9tICcuLi91dGlscyc7XG5pbXBvcnQgKiBhcyBzZHBDb21tb25VdGlscyBmcm9tICcuL3NkcC9jb21tb25VdGlscyc7XG5pbXBvcnQgKiBhcyBzZHBQbGFuQlV0aWxzIGZyb20gJy4vc2RwL3BsYW5CVXRpbHMnO1xuaW1wb3J0IFJlbW90ZVBsYW5CU2RwIGZyb20gJy4vc2RwL1JlbW90ZVBsYW5CU2RwJztcblxuY29uc3QgbG9nZ2VyID0gbmV3IExvZ2dlcignQ2hyb21lNTUnKTtcblxuY2xhc3MgSGFuZGxlciBleHRlbmRzIEVuaGFuY2VkRXZlbnRFbWl0dGVyXG57XG5cdGNvbnN0cnVjdG9yKGRpcmVjdGlvbiwgcnRwUGFyYW1ldGVyc0J5S2luZCwgc2V0dGluZ3MpXG5cdHtcblx0XHRzdXBlcigpO1xuXG5cdFx0Ly8gUlRDUGVlckNvbm5lY3Rpb24gaW5zdGFuY2UuXG5cdFx0Ly8gQHR5cGUge1JUQ1BlZXJDb25uZWN0aW9ufVxuXHRcdHRoaXMuX3BjID0gbmV3IFJUQ1BlZXJDb25uZWN0aW9uKFxuXHRcdFx0e1xuXHRcdFx0XHRpY2VTZXJ2ZXJzICAgICAgICAgOiBzZXR0aW5ncy50dXJuU2VydmVycyB8fCBbXSxcblx0XHRcdFx0aWNlVHJhbnNwb3J0UG9saWN5IDogJ3JlbGF5Jyxcblx0XHRcdFx0YnVuZGxlUG9saWN5ICAgICAgIDogJ21heC1idW5kbGUnLFxuXHRcdFx0XHRydGNwTXV4UG9saWN5ICAgICAgOiAncmVxdWlyZSdcblx0XHRcdH0pO1xuXG5cdFx0Ly8gR2VuZXJpYyBzZW5kaW5nIFJUUCBwYXJhbWV0ZXJzIGZvciBhdWRpbyBhbmQgdmlkZW8uXG5cdFx0Ly8gQHR5cGUge09iamVjdH1cblx0XHR0aGlzLl9ydHBQYXJhbWV0ZXJzQnlLaW5kID0gcnRwUGFyYW1ldGVyc0J5S2luZDtcblxuXHRcdC8vIFJlbW90ZSBTRFAgaGFuZGxlci5cblx0XHQvLyBAdHlwZSB7UmVtb3RlUGxhbkJTZHB9XG5cdFx0dGhpcy5fcmVtb3RlU2RwID0gbmV3IFJlbW90ZVBsYW5CU2RwKGRpcmVjdGlvbiwgcnRwUGFyYW1ldGVyc0J5S2luZCk7XG5cblx0XHQvLyBIYW5kbGUgUlRDUGVlckNvbm5lY3Rpb24gY29ubmVjdGlvbiBzdGF0dXMuXG5cdFx0dGhpcy5fcGMuYWRkRXZlbnRMaXN0ZW5lcignaWNlY29ubmVjdGlvbnN0YXRlY2hhbmdlJywgKCkgPT5cblx0XHR7XG5cdFx0XHRzd2l0Y2ggKHRoaXMuX3BjLmljZUNvbm5lY3Rpb25TdGF0ZSlcblx0XHRcdHtcblx0XHRcdFx0Y2FzZSAnY2hlY2tpbmcnOlxuXHRcdFx0XHRcdHRoaXMuZW1pdCgnQGNvbm5lY3Rpb25zdGF0ZWNoYW5nZScsICdjb25uZWN0aW5nJyk7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdGNhc2UgJ2Nvbm5lY3RlZCc6XG5cdFx0XHRcdGNhc2UgJ2NvbXBsZXRlZCc6XG5cdFx0XHRcdFx0dGhpcy5lbWl0KCdAY29ubmVjdGlvbnN0YXRlY2hhbmdlJywgJ2Nvbm5lY3RlZCcpO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRjYXNlICdmYWlsZWQnOlxuXHRcdFx0XHRcdHRoaXMuZW1pdCgnQGNvbm5lY3Rpb25zdGF0ZWNoYW5nZScsICdmYWlsZWQnKTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0Y2FzZSAnZGlzY29ubmVjdGVkJzpcblx0XHRcdFx0XHR0aGlzLmVtaXQoJ0Bjb25uZWN0aW9uc3RhdGVjaGFuZ2UnLCAnZGlzY29ubmVjdGVkJyk7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdGNhc2UgJ2Nsb3NlZCc6XG5cdFx0XHRcdFx0dGhpcy5lbWl0KCdAY29ubmVjdGlvbnN0YXRlY2hhbmdlJywgJ2Nsb3NlZCcpO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0fVxuXHRcdH0pO1xuXHR9XG5cblx0Y2xvc2UoKVxuXHR7XG5cdFx0bG9nZ2VyLmRlYnVnKCdjbG9zZSgpJyk7XG5cblx0XHQvLyBDbG9zZSBSVENQZWVyQ29ubmVjdGlvbi5cblx0XHR0cnkgeyB0aGlzLl9wYy5jbG9zZSgpOyB9XG5cdFx0Y2F0Y2ggKGVycm9yKSB7fVxuXHR9XG59XG5cbmNsYXNzIFNlbmRIYW5kbGVyIGV4dGVuZHMgSGFuZGxlclxue1xuXHRjb25zdHJ1Y3RvcihydHBQYXJhbWV0ZXJzQnlLaW5kLCBzZXR0aW5ncylcblx0e1xuXHRcdHN1cGVyKCdzZW5kJywgcnRwUGFyYW1ldGVyc0J5S2luZCwgc2V0dGluZ3MpO1xuXG5cdFx0Ly8gR290IHRyYW5zcG9ydCBsb2NhbCBhbmQgcmVtb3RlIHBhcmFtZXRlcnMuXG5cdFx0Ly8gQHR5cGUge0Jvb2xlYW59XG5cdFx0dGhpcy5fdHJhbnNwb3J0UmVhZHkgPSBmYWxzZTtcblxuXHRcdC8vIExvY2FsIHN0cmVhbS5cblx0XHQvLyBAdHlwZSB7TWVkaWFTdHJlYW19XG5cdFx0dGhpcy5fc3RyZWFtID0gbmV3IE1lZGlhU3RyZWFtKCk7XG5cdH1cblxuXHRhZGRQcm9kdWNlcihwcm9kdWNlcilcblx0e1xuXHRcdGNvbnN0IHsgdHJhY2sgfSA9IHByb2R1Y2VyO1xuXG5cdFx0bG9nZ2VyLmRlYnVnKFxuXHRcdFx0J2FkZFByb2R1Y2VyKCkgW2lkOiVzLCBraW5kOiVzLCB0cmFja0lkOiVzXScsXG5cdFx0XHRwcm9kdWNlci5pZCwgcHJvZHVjZXIua2luZCwgdHJhY2suaWQpO1xuXG5cdFx0bGV0IGxvY2FsU2RwT2JqO1xuXG5cdFx0cmV0dXJuIFByb21pc2UucmVzb2x2ZSgpXG5cdFx0XHQudGhlbigoKSA9PlxuXHRcdFx0e1xuXHRcdFx0XHQvLyBBZGQgdGhlIHRyYWNrIHRvIHRoZSBsb2NhbCBzdHJlYW0uXG5cdFx0XHRcdHRoaXMuX3N0cmVhbS5hZGRUcmFjayh0cmFjayk7XG5cblx0XHRcdFx0Ly8gQWRkIHRoZSBzdHJlYW0gdG8gdGhlIFBlZXJDb25uZWN0aW9uLlxuXHRcdFx0XHR0aGlzLl9wYy5hZGRTdHJlYW0odGhpcy5fc3RyZWFtKTtcblxuXHRcdFx0XHRyZXR1cm4gdGhpcy5fcGMuY3JlYXRlT2ZmZXIoKTtcblx0XHRcdH0pXG5cdFx0XHQudGhlbigob2ZmZXIpID0+XG5cdFx0XHR7XG5cdFx0XHRcdHJldHVybiB0aGlzLl9wYy5zZXRMb2NhbERlc2NyaXB0aW9uKG9mZmVyKTtcblx0XHRcdH0pXG5cdFx0XHQudGhlbigoKSA9PlxuXHRcdFx0e1xuXHRcdFx0XHRpZiAoIXRoaXMuX3RyYW5zcG9ydFJlYWR5KVxuXHRcdFx0XHRcdHJldHVybiB0aGlzLl9zZXR1cFRyYW5zcG9ydCgpO1xuXHRcdFx0fSlcblx0XHRcdC50aGVuKCgpID0+XG5cdFx0XHR7XG5cdFx0XHRcdGxvY2FsU2RwT2JqID0gc2RwVHJhbnNmb3JtLnBhcnNlKHRoaXMuX3BjLmxvY2FsRGVzY3JpcHRpb24uc2RwKTtcblxuXHRcdFx0XHRjb25zdCByZW1vdGVTZHAgPSB0aGlzLl9yZW1vdGVTZHAuY3JlYXRlQW5zd2VyU2RwKGxvY2FsU2RwT2JqKTtcblx0XHRcdFx0Y29uc3QgYW5zd2VyID0geyB0eXBlOiAnYW5zd2VyJywgc2RwOiByZW1vdGVTZHAgfTtcblxuXHRcdFx0XHRyZXR1cm4gdGhpcy5fcGMuc2V0UmVtb3RlRGVzY3JpcHRpb24oYW5zd2VyKTtcblx0XHRcdH0pXG5cdFx0XHQudGhlbigoKSA9PlxuXHRcdFx0e1xuXHRcdFx0XHRjb25zdCBydHBQYXJhbWV0ZXJzID0gdXRpbHMuY2xvbmUodGhpcy5fcnRwUGFyYW1ldGVyc0J5S2luZFtwcm9kdWNlci5raW5kXSk7XG5cblx0XHRcdFx0Ly8gRmlsbCB0aGUgUlRQIHBhcmFtZXRlcnMgZm9yIHRoaXMgdHJhY2suXG5cdFx0XHRcdHNkcFBsYW5CVXRpbHMuZmlsbFJ0cFBhcmFtZXRlcnNGb3JUcmFjayhcblx0XHRcdFx0XHRydHBQYXJhbWV0ZXJzLCBsb2NhbFNkcE9iaiwgdHJhY2spO1xuXG5cdFx0XHRcdHJldHVybiBydHBQYXJhbWV0ZXJzO1xuXHRcdFx0fSlcblx0XHRcdC5jYXRjaCgoZXJyb3IpID0+XG5cdFx0XHR7XG5cdFx0XHRcdC8vIFBhbmljIGhlcmUuIFRyeSB0byB1bmRvIHRoaW5ncy5cblxuXHRcdFx0XHR0aGlzLl9zdHJlYW0ucmVtb3ZlVHJhY2sodHJhY2spO1xuXHRcdFx0XHR0aGlzLl9wYy5hZGRTdHJlYW0odGhpcy5fc3RyZWFtKTtcblxuXHRcdFx0XHR0aHJvdyBlcnJvcjtcblx0XHRcdH0pO1xuXHR9XG5cblx0cmVtb3ZlUHJvZHVjZXIocHJvZHVjZXIpXG5cdHtcblx0XHRjb25zdCB7IHRyYWNrIH0gPSBwcm9kdWNlcjtcblxuXHRcdGxvZ2dlci5kZWJ1Zyhcblx0XHRcdCdyZW1vdmVQcm9kdWNlcigpIFtpZDolcywga2luZDolcywgdHJhY2tJZDolc10nLFxuXHRcdFx0cHJvZHVjZXIuaWQsIHByb2R1Y2VyLmtpbmQsIHRyYWNrLmlkKTtcblxuXHRcdHJldHVybiBQcm9taXNlLnJlc29sdmUoKVxuXHRcdFx0LnRoZW4oKCkgPT5cblx0XHRcdHtcblx0XHRcdFx0Ly8gUmVtb3ZlIHRoZSB0cmFjayBmcm9tIHRoZSBsb2NhbCBzdHJlYW0uXG5cdFx0XHRcdHRoaXMuX3N0cmVhbS5yZW1vdmVUcmFjayh0cmFjayk7XG5cblx0XHRcdFx0Ly8gQWRkIHRoZSBzdHJlYW0gdG8gdGhlIFBlZXJDb25uZWN0aW9uLlxuXHRcdFx0XHR0aGlzLl9wYy5hZGRTdHJlYW0odGhpcy5fc3RyZWFtKTtcblxuXHRcdFx0XHRyZXR1cm4gdGhpcy5fcGMuY3JlYXRlT2ZmZXIoKTtcblx0XHRcdH0pXG5cdFx0XHQudGhlbigob2ZmZXIpID0+XG5cdFx0XHR7XG5cdFx0XHRcdHJldHVybiB0aGlzLl9wYy5zZXRMb2NhbERlc2NyaXB0aW9uKG9mZmVyKTtcblx0XHRcdH0pXG5cdFx0XHQuY2F0Y2goKGVycm9yKSA9PlxuXHRcdFx0e1xuXHRcdFx0XHQvLyBOT1RFOiBJZiB0aGVyZSBhcmUgbm8gc2VuZGluZyB0cmFja3MsIHNldExvY2FsRGVzY3JpcHRpb24oKSB3aWxsIGZhaWwgd2l0aFxuXHRcdFx0XHQvLyBcIkZhaWxlZCB0byBjcmVhdGUgY2hhbm5lbHNcIi4gSWYgc28sIGlnbm9yZSBpdC5cblx0XHRcdFx0aWYgKHRoaXMuX3N0cmVhbS5nZXRUcmFja3MoKS5sZW5ndGggPT09IDApXG5cdFx0XHRcdHtcblx0XHRcdFx0XHRsb2dnZXIud2Fybihcblx0XHRcdFx0XHRcdCdyZW1vdmVQcm9kdWNlcigpIHwgaWdub3JpbmcgZXhwZWN0ZWQgZXJyb3IgZHVlIG5vIHNlbmRpbmcgdHJhY2tzOiAlcycsXG5cdFx0XHRcdFx0XHRlcnJvci50b1N0cmluZygpKTtcblxuXHRcdFx0XHRcdHJldHVybjtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdHRocm93IGVycm9yO1xuXHRcdFx0fSlcblx0XHRcdC50aGVuKCgpID0+XG5cdFx0XHR7XG5cdFx0XHRcdGlmICh0aGlzLl9wYy5zaWduYWxpbmdTdGF0ZSA9PT0gJ3N0YWJsZScpXG5cdFx0XHRcdFx0cmV0dXJuO1xuXG5cdFx0XHRcdGNvbnN0IGxvY2FsU2RwT2JqID0gc2RwVHJhbnNmb3JtLnBhcnNlKHRoaXMuX3BjLmxvY2FsRGVzY3JpcHRpb24uc2RwKTtcblx0XHRcdFx0Y29uc3QgcmVtb3RlU2RwID0gdGhpcy5fcmVtb3RlU2RwLmNyZWF0ZUFuc3dlclNkcChsb2NhbFNkcE9iaik7XG5cdFx0XHRcdGNvbnN0IGFuc3dlciA9IHsgdHlwZTogJ2Fuc3dlcicsIHNkcDogcmVtb3RlU2RwIH07XG5cblx0XHRcdFx0cmV0dXJuIHRoaXMuX3BjLnNldFJlbW90ZURlc2NyaXB0aW9uKGFuc3dlcik7XG5cdFx0XHR9KTtcblx0fVxuXG5cdF9zZXR1cFRyYW5zcG9ydCgpXG5cdHtcblx0XHRsb2dnZXIuZGVidWcoJ19zZXR1cFRyYW5zcG9ydCgpJyk7XG5cblx0XHRyZXR1cm4gUHJvbWlzZS5yZXNvbHZlKClcblx0XHRcdC50aGVuKCgpID0+XG5cdFx0XHR7XG5cdFx0XHRcdC8vIEdldCBvdXIgbG9jYWwgRFRMUyBwYXJhbWV0ZXJzLlxuXHRcdFx0XHRjb25zdCB0cmFuc3BvcnRMb2NhbFBhcmFtZXRlcnMgPSB7fTtcblx0XHRcdFx0Y29uc3Qgc2RwID0gdGhpcy5fcGMubG9jYWxEZXNjcmlwdGlvbi5zZHA7XG5cdFx0XHRcdGNvbnN0IHNkcE9iaiA9IHNkcFRyYW5zZm9ybS5wYXJzZShzZHApO1xuXHRcdFx0XHRjb25zdCBkdGxzUGFyYW1ldGVycyA9IHNkcENvbW1vblV0aWxzLmV4dHJhY3REdGxzUGFyYW1ldGVycyhzZHBPYmopO1xuXG5cdFx0XHRcdC8vIExldCdzIGRlY2lkZSB0aGF0IHdlJ2xsIGJlIERUTFMgc2VydmVyIChiZWNhdXNlIHdlIGNhbikuXG5cdFx0XHRcdGR0bHNQYXJhbWV0ZXJzLnJvbGUgPSAnc2VydmVyJztcblxuXHRcdFx0XHR0cmFuc3BvcnRMb2NhbFBhcmFtZXRlcnMuZHRsc1BhcmFtZXRlcnMgPSBkdGxzUGFyYW1ldGVycztcblxuXHRcdFx0XHQvLyBQcm92aWRlIHRoZSByZW1vdGUgU0RQIGhhbmRsZXIgd2l0aCB0cmFuc3BvcnQgbG9jYWwgcGFyYW1ldGVycy5cblx0XHRcdFx0dGhpcy5fcmVtb3RlU2RwLnNldFRyYW5zcG9ydExvY2FsUGFyYW1ldGVycyh0cmFuc3BvcnRMb2NhbFBhcmFtZXRlcnMpO1xuXG5cdFx0XHRcdC8vIFdlIG5lZWQgdHJhbnNwb3J0IHJlbW90ZSBwYXJhbWV0ZXJzLlxuXHRcdFx0XHRyZXR1cm4gdGhpcy5zYWZlRW1pdEFzUHJvbWlzZShcblx0XHRcdFx0XHQnQG5lZWRjcmVhdGV0cmFuc3BvcnQnLCB0cmFuc3BvcnRMb2NhbFBhcmFtZXRlcnMpO1xuXHRcdFx0fSlcblx0XHRcdC50aGVuKCh0cmFuc3BvcnRSZW1vdGVQYXJhbWV0ZXJzKSA9PlxuXHRcdFx0e1xuXHRcdFx0XHQvLyBQcm92aWRlIHRoZSByZW1vdGUgU0RQIGhhbmRsZXIgd2l0aCB0cmFuc3BvcnQgcmVtb3RlIHBhcmFtZXRlcnMuXG5cdFx0XHRcdHRoaXMuX3JlbW90ZVNkcC5zZXRUcmFuc3BvcnRSZW1vdGVQYXJhbWV0ZXJzKHRyYW5zcG9ydFJlbW90ZVBhcmFtZXRlcnMpO1xuXG5cdFx0XHRcdHRoaXMuX3RyYW5zcG9ydFJlYWR5ID0gdHJ1ZTtcblx0XHRcdH0pO1xuXHR9XG59XG5cbmNsYXNzIFJlY3ZIYW5kbGVyIGV4dGVuZHMgSGFuZGxlclxue1xuXHRjb25zdHJ1Y3RvcihydHBQYXJhbWV0ZXJzQnlLaW5kLCBzZXR0aW5ncylcblx0e1xuXHRcdHN1cGVyKCdyZWN2JywgcnRwUGFyYW1ldGVyc0J5S2luZCwgc2V0dGluZ3MpO1xuXG5cdFx0Ly8gR290IHRyYW5zcG9ydCByZW1vdGUgcGFyYW1ldGVycy5cblx0XHQvLyBAdHlwZSB7Qm9vbGVhbn1cblx0XHR0aGlzLl90cmFuc3BvcnRDcmVhdGVkID0gZmFsc2U7XG5cblx0XHQvLyBHb3QgdHJhbnNwb3J0IGxvY2FsIHBhcmFtZXRlcnMuXG5cdFx0Ly8gQHR5cGUge0Jvb2xlYW59XG5cdFx0dGhpcy5fdHJhbnNwb3J0VXBkYXRlZCA9IGZhbHNlO1xuXG5cdFx0Ly8gU2VlbiBtZWRpYSBraW5kcy5cblx0XHQvLyBAdHlwZSB7U2V0PFN0cmluZz59XG5cdFx0dGhpcy5fa2luZHMgPSBuZXcgU2V0KCk7XG5cblx0XHQvLyBNYXAgb2YgQ29uc3VtZXJzIGluZm9ybWF0aW9uIGluZGV4ZWQgYnkgY29uc3VtZXIuaWQuXG5cdFx0Ly8gLSBraW5kIHtTdHJpbmd9XG5cdFx0Ly8gLSB0cmFja0lkIHtTdHJpbmd9XG5cdFx0Ly8gLSBzc3JjIHtOdW1iZXJ9XG5cdFx0Ly8gLSBydHhTc3JjIHtOdW1iZXJ9XG5cdFx0Ly8gLSBjbmFtZSB7U3RyaW5nfVxuXHRcdC8vIEB0eXBlIHtNYXA8TnVtYmVyLCBPYmplY3Q+fVxuXHRcdHRoaXMuX2NvbnN1bWVySW5mb3MgPSBuZXcgTWFwKCk7XG5cdH1cblxuXHRhZGRDb25zdW1lcihjb25zdW1lcilcblx0e1xuXHRcdGxvZ2dlci5kZWJ1Zyhcblx0XHRcdCdhZGRDb25zdW1lcigpIFtpZDolcywga2luZDolc10nLCBjb25zdW1lci5pZCwgY29uc3VtZXIua2luZCk7XG5cblx0XHRpZiAodGhpcy5fY29uc3VtZXJJbmZvcy5oYXMoY29uc3VtZXIuaWQpKVxuXHRcdFx0cmV0dXJuIFByb21pc2UucmVqZWN0KCdDb25zdW1lciBhbHJlYWR5IGFkZGVkJyk7XG5cblx0XHRjb25zdCBlbmNvZGluZyA9IGNvbnN1bWVyLnJ0cFBhcmFtZXRlcnMuZW5jb2RpbmdzWzBdO1xuXHRcdGNvbnN0IGNuYW1lID0gY29uc3VtZXIucnRwUGFyYW1ldGVycy5ydGNwLmNuYW1lO1xuXHRcdGNvbnN0IGNvbnN1bWVySW5mbyA9XG5cdFx0e1xuXHRcdFx0a2luZCAgICA6IGNvbnN1bWVyLmtpbmQsXG5cdFx0XHR0cmFja0lkIDogYGNvbnN1bWVyLSR7Y29uc3VtZXIua2luZH0tJHtjb25zdW1lci5pZH1gLFxuXHRcdFx0c3NyYyAgICA6IGVuY29kaW5nLnNzcmMsXG5cdFx0XHRjbmFtZSAgIDogY25hbWVcblx0XHR9O1xuXG5cdFx0aWYgKGVuY29kaW5nLnJ0eCAmJiBlbmNvZGluZy5ydHguc3NyYylcblx0XHRcdGNvbnN1bWVySW5mby5ydHhTc3JjID0gZW5jb2RpbmcucnR4LnNzcmM7XG5cblx0XHR0aGlzLl9jb25zdW1lckluZm9zLnNldChjb25zdW1lci5pZCwgY29uc3VtZXJJbmZvKTtcblx0XHR0aGlzLl9raW5kcy5hZGQoY29uc3VtZXIua2luZCk7XG5cblx0XHRyZXR1cm4gUHJvbWlzZS5yZXNvbHZlKClcblx0XHRcdC50aGVuKCgpID0+XG5cdFx0XHR7XG5cdFx0XHRcdGlmICghdGhpcy5fdHJhbnNwb3J0Q3JlYXRlZClcblx0XHRcdFx0XHRyZXR1cm4gdGhpcy5fc2V0dXBUcmFuc3BvcnQoKTtcblx0XHRcdH0pXG5cdFx0XHQudGhlbigoKSA9PlxuXHRcdFx0e1xuXHRcdFx0XHRjb25zdCByZW1vdGVTZHAgPSB0aGlzLl9yZW1vdGVTZHAuY3JlYXRlT2ZmZXJTZHAoXG5cdFx0XHRcdFx0QXJyYXkuZnJvbSh0aGlzLl9raW5kcyksIEFycmF5LmZyb20odGhpcy5fY29uc3VtZXJJbmZvcy52YWx1ZXMoKSkpO1xuXHRcdFx0XHRjb25zdCBvZmZlciA9IHsgdHlwZTogJ29mZmVyJywgc2RwOiByZW1vdGVTZHAgfTtcblxuXHRcdFx0XHRyZXR1cm4gdGhpcy5fcGMuc2V0UmVtb3RlRGVzY3JpcHRpb24ob2ZmZXIpO1xuXHRcdFx0fSlcblx0XHRcdC50aGVuKCgpID0+XG5cdFx0XHR7XG5cdFx0XHRcdHJldHVybiB0aGlzLl9wYy5jcmVhdGVBbnN3ZXIoKTtcblx0XHRcdH0pXG5cdFx0XHQudGhlbigoYW5zd2VyKSA9PlxuXHRcdFx0e1xuXHRcdFx0XHRyZXR1cm4gdGhpcy5fcGMuc2V0TG9jYWxEZXNjcmlwdGlvbihhbnN3ZXIpO1xuXHRcdFx0fSlcblx0XHRcdC50aGVuKCgpID0+XG5cdFx0XHR7XG5cdFx0XHRcdGlmICghdGhpcy5fdHJhbnNwb3J0VXBkYXRlZClcblx0XHRcdFx0XHRyZXR1cm4gdGhpcy5fdXBkYXRlVHJhbnNwb3J0KCk7XG5cdFx0XHR9KVxuXHRcdFx0LnRoZW4oKCkgPT5cblx0XHRcdHtcblx0XHRcdFx0Y29uc3Qgc3RyZWFtID0gdGhpcy5fcGMuZ2V0UmVtb3RlU3RyZWFtcygpWzBdO1xuXHRcdFx0XHRjb25zdCB0cmFjayA9IHN0cmVhbS5nZXRUcmFja0J5SWQoY29uc3VtZXJJbmZvLnRyYWNrSWQpO1xuXG5cdFx0XHRcdGlmICghdHJhY2spXG5cdFx0XHRcdFx0dGhyb3cgbmV3IEVycm9yKCdyZW1vdGUgdHJhY2sgbm90IGZvdW5kJyk7XG5cblx0XHRcdFx0cmV0dXJuIHRyYWNrO1xuXHRcdFx0fSk7XG5cdH1cblxuXHRyZW1vdmVDb25zdW1lcihjb25zdW1lcilcblx0e1xuXHRcdGxvZ2dlci5kZWJ1Zyhcblx0XHRcdCdyZW1vdmVDb25zdW1lcigpIFtpZDolcywga2luZDolc10nLCBjb25zdW1lci5pZCwgY29uc3VtZXIua2luZCk7XG5cblx0XHRpZiAoIXRoaXMuX2NvbnN1bWVySW5mb3MuaGFzKGNvbnN1bWVyLmlkKSlcblx0XHRcdHJldHVybiBQcm9taXNlLnJlamVjdCgnQ29uc3VtZXIgbm90IGZvdW5kJyk7XG5cblx0XHR0aGlzLl9jb25zdW1lckluZm9zLmRlbGV0ZShjb25zdW1lci5pZCk7XG5cblx0XHRyZXR1cm4gUHJvbWlzZS5yZXNvbHZlKClcblx0XHRcdC50aGVuKCgpID0+XG5cdFx0XHR7XG5cdFx0XHRcdGNvbnN0IHJlbW90ZVNkcCA9IHRoaXMuX3JlbW90ZVNkcC5jcmVhdGVPZmZlclNkcChcblx0XHRcdFx0XHRBcnJheS5mcm9tKHRoaXMuX2tpbmRzKSwgQXJyYXkuZnJvbSh0aGlzLl9jb25zdW1lckluZm9zLnZhbHVlcygpKSk7XG5cdFx0XHRcdGNvbnN0IG9mZmVyID0geyB0eXBlOiAnb2ZmZXInLCBzZHA6IHJlbW90ZVNkcCB9O1xuXG5cdFx0XHRcdHJldHVybiB0aGlzLl9wYy5zZXRSZW1vdGVEZXNjcmlwdGlvbihvZmZlcik7XG5cdFx0XHR9KVxuXHRcdFx0LnRoZW4oKCkgPT5cblx0XHRcdHtcblx0XHRcdFx0cmV0dXJuIHRoaXMuX3BjLmNyZWF0ZUFuc3dlcigpO1xuXHRcdFx0fSlcblx0XHRcdC50aGVuKChhbnN3ZXIpID0+XG5cdFx0XHR7XG5cdFx0XHRcdHJldHVybiB0aGlzLl9wYy5zZXRMb2NhbERlc2NyaXB0aW9uKGFuc3dlcik7XG5cdFx0XHR9KTtcblx0fVxuXG5cdF9zZXR1cFRyYW5zcG9ydCgpXG5cdHtcblx0XHRsb2dnZXIuZGVidWcoJ19zZXR1cFRyYW5zcG9ydCgpJyk7XG5cblx0XHRyZXR1cm4gUHJvbWlzZS5yZXNvbHZlKClcblx0XHRcdC50aGVuKCgpID0+XG5cdFx0XHR7XG5cdFx0XHRcdC8vIFdlIG5lZWQgdHJhbnNwb3J0IHJlbW90ZSBwYXJhbWV0ZXJzLlxuXHRcdFx0XHRyZXR1cm4gdGhpcy5zYWZlRW1pdEFzUHJvbWlzZSgnQG5lZWRjcmVhdGV0cmFuc3BvcnQnLCBudWxsKTtcblx0XHRcdH0pXG5cdFx0XHQudGhlbigodHJhbnNwb3J0UmVtb3RlUGFyYW1ldGVycykgPT5cblx0XHRcdHtcblx0XHRcdFx0Ly8gUHJvdmlkZSB0aGUgcmVtb3RlIFNEUCBoYW5kbGVyIHdpdGggdHJhbnNwb3J0IHJlbW90ZSBwYXJhbWV0ZXJzLlxuXHRcdFx0XHR0aGlzLl9yZW1vdGVTZHAuc2V0VHJhbnNwb3J0UmVtb3RlUGFyYW1ldGVycyh0cmFuc3BvcnRSZW1vdGVQYXJhbWV0ZXJzKTtcblxuXHRcdFx0XHR0aGlzLl90cmFuc3BvcnRDcmVhdGVkID0gdHJ1ZTtcblx0XHRcdH0pO1xuXHR9XG5cblx0X3VwZGF0ZVRyYW5zcG9ydCgpXG5cdHtcblx0XHRsb2dnZXIuZGVidWcoJ191cGRhdGVUcmFuc3BvcnQoKScpO1xuXG5cdFx0Ly8gR2V0IG91ciBsb2NhbCBEVExTIHBhcmFtZXRlcnMuXG5cdFx0Ly8gY29uc3QgdHJhbnNwb3J0TG9jYWxQYXJhbWV0ZXJzID0ge307XG5cdFx0Y29uc3Qgc2RwID0gdGhpcy5fcGMubG9jYWxEZXNjcmlwdGlvbi5zZHA7XG5cdFx0Y29uc3Qgc2RwT2JqID0gc2RwVHJhbnNmb3JtLnBhcnNlKHNkcCk7XG5cdFx0Y29uc3QgZHRsc1BhcmFtZXRlcnMgPSBzZHBDb21tb25VdGlscy5leHRyYWN0RHRsc1BhcmFtZXRlcnMoc2RwT2JqKTtcblx0XHRjb25zdCB0cmFuc3BvcnRMb2NhbFBhcmFtZXRlcnMgPSB7IGR0bHNQYXJhbWV0ZXJzIH07XG5cblx0XHQvLyBXZSBuZWVkIHRvIHByb3ZpZGUgdHJhbnNwb3J0IGxvY2FsIHBhcmFtZXRlcnMuXG5cdFx0dGhpcy5zYWZlRW1pdCgnQG5lZWR1cGRhdGV0cmFuc3BvcnQnLCB0cmFuc3BvcnRMb2NhbFBhcmFtZXRlcnMpO1xuXG5cdFx0dGhpcy5fdHJhbnNwb3J0VXBkYXRlZCA9IHRydWU7XG5cdH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgQ2hyb21lNTVcbntcblx0c3RhdGljIGdldCBuYW1lKClcblx0e1xuXHRcdHJldHVybiAnQ2hyb21lNTUnO1xuXHR9XG5cblx0c3RhdGljIGdldExvY2FsUnRwQ2FwYWJpbGl0aWVzKClcblx0e1xuXHRcdGxvZ2dlci5kZWJ1ZygnZ2V0TG9jYWxSdHBDYXBhYmlsaXRpZXMoKScpO1xuXG5cdFx0Y29uc3QgcGMgPSBuZXcgUlRDUGVlckNvbm5lY3Rpb24oXG5cdFx0XHR7XG5cdFx0XHRcdGljZVNlcnZlcnMgICAgICAgICA6IFtdLFxuXHRcdFx0XHRpY2VUcmFuc3BvcnRQb2xpY3kgOiAncmVsYXknLFxuXHRcdFx0XHRidW5kbGVQb2xpY3kgICAgICAgOiAnbWF4LWJ1bmRsZScsXG5cdFx0XHRcdHJ0Y3BNdXhQb2xpY3kgICAgICA6ICdyZXF1aXJlJ1xuXHRcdFx0fSk7XG5cblx0XHRyZXR1cm4gcGMuY3JlYXRlT2ZmZXIoXG5cdFx0XHR7XG5cdFx0XHRcdG9mZmVyVG9SZWNlaXZlQXVkaW8gOiB0cnVlLFxuXHRcdFx0XHRvZmZlclRvUmVjZWl2ZVZpZGVvIDogdHJ1ZVxuXHRcdFx0fSlcblx0XHRcdC50aGVuKChvZmZlcikgPT5cblx0XHRcdHtcblx0XHRcdFx0dHJ5IHsgcGMuY2xvc2UoKTsgfVxuXHRcdFx0XHRjYXRjaCAoZXJyb3IpIHt9XG5cblx0XHRcdFx0Y29uc3Qgc2RwT2JqID0gc2RwVHJhbnNmb3JtLnBhcnNlKG9mZmVyLnNkcCk7XG5cdFx0XHRcdGNvbnN0IGxvY2FsUnRwQ2FwYWJpbGl0aWVzID0gc2RwQ29tbW9uVXRpbHMuZXh0cmFjdFJ0cENhcGFiaWxpdGllcyhzZHBPYmopO1xuXG5cdFx0XHRcdHJldHVybiBsb2NhbFJ0cENhcGFiaWxpdGllcztcblx0XHRcdH0pXG5cdFx0XHQuY2F0Y2goKGVycm9yKSA9PlxuXHRcdFx0e1xuXHRcdFx0XHR0cnkgeyBwYy5jbG9zZSgpOyB9XG5cdFx0XHRcdGNhdGNoIChlcnJvcjIpIHt9XG5cblx0XHRcdFx0dGhyb3cgZXJyb3I7XG5cdFx0XHR9KTtcblx0fVxuXG5cdGNvbnN0cnVjdG9yKGRpcmVjdGlvbiwgZXh0ZW5kZWRSdHBDYXBhYmlsaXRpZXMsIHNldHRpbmdzKVxuXHR7XG5cdFx0bG9nZ2VyLmRlYnVnKFxuXHRcdFx0J2NvbnN0cnVjdG9yKCkgW2RpcmVjdGlvbjolcywgZXh0ZW5kZWRSdHBDYXBhYmlsaXRpZXM6JW9dJyxcblx0XHRcdGRpcmVjdGlvbiwgZXh0ZW5kZWRSdHBDYXBhYmlsaXRpZXMpO1xuXG5cdFx0bGV0IHJ0cFBhcmFtZXRlcnNCeUtpbmQ7XG5cblx0XHRzd2l0Y2ggKGRpcmVjdGlvbilcblx0XHR7XG5cdFx0XHRjYXNlICdzZW5kJzpcblx0XHRcdHtcblx0XHRcdFx0cnRwUGFyYW1ldGVyc0J5S2luZCA9XG5cdFx0XHRcdHtcblx0XHRcdFx0XHRhdWRpbyA6IHV0aWxzLmdldFNlbmRpbmdSdHBQYXJhbWV0ZXJzKCdhdWRpbycsIGV4dGVuZGVkUnRwQ2FwYWJpbGl0aWVzKSxcblx0XHRcdFx0XHR2aWRlbyA6IHV0aWxzLmdldFNlbmRpbmdSdHBQYXJhbWV0ZXJzKCd2aWRlbycsIGV4dGVuZGVkUnRwQ2FwYWJpbGl0aWVzKVxuXHRcdFx0XHR9O1xuXG5cdFx0XHRcdHJldHVybiBuZXcgU2VuZEhhbmRsZXIocnRwUGFyYW1ldGVyc0J5S2luZCwgc2V0dGluZ3MpO1xuXHRcdFx0fVxuXHRcdFx0Y2FzZSAncmVjdic6XG5cdFx0XHR7XG5cdFx0XHRcdHJ0cFBhcmFtZXRlcnNCeUtpbmQgPVxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0YXVkaW8gOiB1dGlscy5nZXRSZWNlaXZpbmdGdWxsUnRwUGFyYW1ldGVycygnYXVkaW8nLCBleHRlbmRlZFJ0cENhcGFiaWxpdGllcyksXG5cdFx0XHRcdFx0dmlkZW8gOiB1dGlscy5nZXRSZWNlaXZpbmdGdWxsUnRwUGFyYW1ldGVycygndmlkZW8nLCBleHRlbmRlZFJ0cENhcGFiaWxpdGllcylcblx0XHRcdFx0fTtcblxuXHRcdFx0XHRyZXR1cm4gbmV3IFJlY3ZIYW5kbGVyKHJ0cFBhcmFtZXRlcnNCeUtpbmQsIHNldHRpbmdzKTtcblx0XHRcdH1cblx0XHR9XG5cdH1cbn1cbiIsIi8qIGdsb2JhbCBSVENJY2VHYXRoZXJlciwgUlRDSWNlVHJhbnNwb3J0LCBSVENEdGxzVHJhbnNwb3J0LCBSVENSdHBSZWNlaXZlciAqL1xuXG5pbXBvcnQgTG9nZ2VyIGZyb20gJy4uL0xvZ2dlcic7XG5pbXBvcnQgRW5oYW5jZWRFdmVudEVtaXR0ZXIgZnJvbSAnLi4vRW5oYW5jZWRFdmVudEVtaXR0ZXInO1xuLy8gaW1wb3J0ICogYXMgdXRpbHMgZnJvbSAnLi4vdXRpbHMnO1xuXG5jb25zdCBsb2dnZXIgPSBuZXcgTG9nZ2VyKCdFZGdlMTEnKTtcblxuLy8gY29uc3QgQ05BTUUgPSBgY25hbWUtJHt1dGlscy5yYW5kb21OdW1iZXIoKX1gO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBFZGdlMTEgZXh0ZW5kcyBFbmhhbmNlZEV2ZW50RW1pdHRlclxue1xuXHRzdGF0aWMgZ2V0IG5hbWUoKVxuXHR7XG5cdFx0cmV0dXJuICdFZGdlMTEnO1xuXHR9XG5cblx0c3RhdGljIGdldExvY2FsUnRwQ2FwYWJpbGl0aWVzKClcblx0e1xuXHRcdGxvZ2dlci5kZWJ1ZygnZ2V0TG9jYWxSdHBDYXBhYmlsaXRpZXMoKScpO1xuXG5cdFx0Ly8gVE9ETzogTm90IGVub3VnaCBzaW5jZSBFZGdlIGRvZXMgbm90IHNldCBtaW1lVHlwZSwgZXRjLlxuXHRcdHJldHVybiBSVENSdHBSZWNlaXZlci5nZXRDYXBhYmlsaXRpZXMoKTtcblx0fVxuXG5cdGNvbnN0cnVjdG9yKGRpcmVjdGlvbiwgZXh0ZW5kZWRSdHBDYXBhYmlsaXRpZXMsIHNldHRpbmdzKVxuXHR7XG5cdFx0bG9nZ2VyLmRlYnVnKFxuXHRcdFx0J2NvbnN0cnVjdG9yKCkgW2RpcmVjdGlvbjolcywgZXh0ZW5kZWRSdHBDYXBhYmlsaXRpZXM6JW9dJyxcblx0XHRcdGRpcmVjdGlvbiwgZXh0ZW5kZWRSdHBDYXBhYmlsaXRpZXMpO1xuXG5cdFx0c3VwZXIoKTtcblxuXHRcdC8vIEdvdCB0cmFuc3BvcnQgbG9jYWwgYW5kIHJlbW90ZSBwYXJhbWV0ZXJzLlxuXHRcdC8vIEB0eXBlIHtCb29sZWFufVxuXHRcdHRoaXMuX3RyYW5zcG9ydFJlYWR5ID0gZmFsc2U7XG5cblx0XHQvLyBJQ0UgZ2F0aGVyZXIuXG5cdFx0dGhpcy5faWNlR2F0aGVyZXIgPSBudWxsO1xuXG5cdFx0Ly8gSUNFIHRyYW5zcG9ydC5cblx0XHR0aGlzLl9pY2VUcmFuc3BvcnQgPSBudWxsO1xuXG5cdFx0Ly8gRFRMUyB0cmFuc3BvcnQuXG5cdFx0Ly8gQHR5cGUge1JUQ0R0bHNUcmFuc3BvcnR9XG5cdFx0dGhpcy5fZHRsc1RyYW5zcG9ydCA9IG51bGw7XG5cblx0XHQvLyBNYXAgb2YgUlRDUnRwU2VuZGVycyBpbmRleGVkIGJ5IFByb2R1Y2VyLmlkLlxuXHRcdC8vIEB0eXBlIHtNYXA8TnVtYmVyLCBSVENSdHBTZW5kZXJ9XG5cdFx0dGhpcy5fcnRwU2VuZGVycyA9IG5ldyBNYXAoKTtcblxuXHRcdC8vIE1hcCBvZiBSVENSdHBSZWNlaXZlcnMgaW5kZXhlZCBieSBDb25zdW1lci5pZC5cblx0XHQvLyBAdHlwZSB7TWFwPE51bWJlciwgUlRDUnRwUmVjZWl2ZXJ9XG5cdFx0dGhpcy5fcnRwUmVjZWl2ZXJzID0gbmV3IE1hcCgpO1xuXG5cdFx0dGhpcy5fc2V0SWNlR2F0aGVyZXIoc2V0dGluZ3MpO1xuXHRcdHRoaXMuX3NldEljZVRyYW5zcG9ydCgpO1xuXHRcdHRoaXMuX3NldER0bHNUcmFuc3BvcnQoKTtcblxuXHRcdC8vIFRPRE9cblx0fVxuXG5cdGNsb3NlKClcblx0e1xuXHRcdGxvZ2dlci5kZWJ1ZygnY2xvc2UoKScpO1xuXG5cdFx0Ly8gQ2xvc2UgdGhlIElDRSBnYXRoZXJlci5cblx0XHQvLyBOT1RFOiBOb3QgeWV0IGltcGxlbWVudGVkIGJ5IEVkZ2UuXG5cdFx0dHJ5IHsgdGhpcy5faWNlR2F0aGVyZXIuY2xvc2UoKTsgfVxuXHRcdGNhdGNoIChlcnJvcikge31cblxuXHRcdC8vIENsb3NlIHRoZSBJQ0UgdHJhbnNwb3J0LlxuXHRcdHRyeSB7IHRoaXMuX2ljZVRyYW5zcG9ydC5zdG9wKCk7IH1cblx0XHRjYXRjaCAoZXJyb3IpIHt9XG5cblx0XHQvLyBDbG9zZSB0aGUgRFRMUyB0cmFuc3BvcnQuXG5cdFx0dHJ5IHsgdGhpcy5fZHRsc1RyYW5zcG9ydC5zdG9wKCk7IH1cblx0XHRjYXRjaCAoZXJyb3IpIHt9XG5cblx0XHQvLyBDbG9zZSBSVENSdHBTZW5kZXJzLlxuXHRcdGZvciAoY29uc3QgcnRwU2VuZGVyIG9mIHRoaXMuX3J0cFNlbmRlcnMudmFsdWVzKCkpXG5cdFx0e1xuXHRcdFx0dHJ5IHsgcnRwU2VuZGVyLnN0b3AoKTsgfVxuXHRcdFx0Y2F0Y2ggKGVycm9yKSB7fVxuXHRcdH1cblxuXHRcdC8vIENsb3NlIFJUQ1J0cFJlY2VpdmVycy5cblx0XHRmb3IgKGNvbnN0IHJ0cFJlY2VpdmVyIG9mIHRoaXMuX3J0cFJlY2VpdmVycy52YWx1ZXMoKSlcblx0XHR7XG5cdFx0XHR0cnkgeyBydHBSZWNlaXZlci5zdG9wKCk7IH1cblx0XHRcdGNhdGNoIChlcnJvcikge31cblx0XHR9XG5cdH1cblxuXHRhZGRQcm9kdWNlcihwcm9kdWNlcilcblx0e1xuXHRcdGNvbnN0IHsgdHJhY2sgfSA9IHByb2R1Y2VyO1xuXG5cdFx0bG9nZ2VyLmRlYnVnKFxuXHRcdFx0J2FkZFByb2R1Y2VyKCkgW2lkOiVzLCBraW5kOiVzLCB0cmFja0lkOiVzXScsXG5cdFx0XHRwcm9kdWNlci5pZCwgcHJvZHVjZXIua2luZCwgdHJhY2suaWQpO1xuXG5cdFx0cmV0dXJuIFByb21pc2UucmVzb2x2ZSgpXG5cdFx0XHQudGhlbigoKSA9PlxuXHRcdFx0e1xuXHRcdFx0XHRpZiAoIXRoaXMuX3RyYW5zcG9ydFJlYWR5KVxuXHRcdFx0XHRcdHJldHVybiB0aGlzLl9zZXR1cFRyYW5zcG9ydCgpO1xuXHRcdFx0fSk7XG5cblx0XHQvLyBUT0RPXG5cdH1cblxuXHRyZW1vdmVQcm9kdWNlcihwcm9kdWNlcilcblx0e1xuXHRcdGNvbnN0IHsgdHJhY2sgfSA9IHByb2R1Y2VyO1xuXG5cdFx0bG9nZ2VyLmRlYnVnKFxuXHRcdFx0J3JlbW92ZVByb2R1Y2VyKCkgW2lkOiVzLCBraW5kOiVzLCB0cmFja0lkOiVzXScsXG5cdFx0XHRwcm9kdWNlci5pZCwgcHJvZHVjZXIua2luZCwgdHJhY2suaWQpO1xuXG5cdFx0Ly8gVE9ET1xuXHR9XG5cblx0YWRkQ29uc3VtZXIoY29uc3VtZXIpXG5cdHtcblx0XHRsb2dnZXIuZGVidWcoXG5cdFx0XHQnYWRkQ29uc3VtZXIoKSBbaWQ6JXMsIGtpbmQ6JXNdJywgY29uc3VtZXIuaWQsIGNvbnN1bWVyLmtpbmQpO1xuXG5cdFx0Ly8gVE9ET1xuXHR9XG5cblx0cmVtb3ZlQ29uc3VtZXIoY29uc3VtZXIpXG5cdHtcblx0XHRsb2dnZXIuZGVidWcoXG5cdFx0XHQncmVtb3ZlQ29uc3VtZXIoKSBbaWQ6JXMsIGtpbmQ6JXNdJywgY29uc3VtZXIuaWQsIGNvbnN1bWVyLmtpbmQpO1xuXG5cdFx0Ly8gVE9ET1xuXHR9XG5cblx0X3NldEljZUdhdGhlcmVyKHNldHRpbmdzKVxuXHR7XG5cdFx0Y29uc3QgaWNlR2F0aGVyZXIgPSBuZXcgUlRDSWNlR2F0aGVyZXIoXG5cdFx0XHR7XG5cdFx0XHRcdGljZVNlcnZlcnMgICA6IHNldHRpbmdzLnR1cm5TZXJ2ZXJzIHx8IFtdLFxuXHRcdFx0XHRnYXRoZXJQb2xpY3kgOiAncmVsYXknXG5cdFx0XHR9KTtcblxuXHRcdGljZUdhdGhlcmVyLmFkZEV2ZW50TGlzdGVuZXIoJ2Vycm9yJywgKGV2ZW50KSA9PlxuXHRcdHtcblx0XHRcdGNvbnN0IHsgZXJyb3JDb2RlLCBlcnJvclRleHQgfSA9IGV2ZW50O1xuXG5cdFx0XHRsb2dnZXIuZXJyb3IoXG5cdFx0XHRcdGBpY2VHYXRoZXJlciBcImVycm9yXCIgZXZlbnQgW2Vycm9yQ29kZToke2Vycm9yQ29kZX0sIGVycm9yVGV4dDoke2Vycm9yVGV4dH1dYCk7XG5cdFx0fSk7XG5cblx0XHQvLyBOT1RFOiBOb3QgeWV0IGltcGxlbWVudGVkIGJ5IEVkZ2UsIHdoaWNoIHN0YXJ0cyBnYXRoZXJpbmcgYXV0b21hdGljYWxseS5cblx0XHR0cnlcblx0XHR7XG5cdFx0XHRpY2VHYXRoZXJlci5nYXRoZXIoKTtcblx0XHR9XG5cdFx0Y2F0Y2ggKGVycm9yKVxuXHRcdHtcblx0XHRcdGxvZ2dlci5kZWJ1ZyhgaWNlR2F0aGVyZXIuZ2F0aGVyKCkgZmFpbGVkOiR7ZXJyb3J9YCk7XG5cdFx0fVxuXG5cdFx0dGhpcy5faWNlR2F0aGVyZXIgPSBpY2VHYXRoZXJlcjtcblx0fVxuXG5cdF9zZXRJY2VUcmFuc3BvcnQoKVxuXHR7XG5cdFx0Y29uc3QgaWNlVHJhbnNwb3J0ID0gbmV3IFJUQ0ljZVRyYW5zcG9ydCh0aGlzLl9pY2VHYXRoZXJlcik7XG5cblx0XHQvLyBOT1RFOiBOb3QgeWV0IGltcGxlbWVudGVkIGJ5IEVkZ2UuXG5cdFx0aWNlVHJhbnNwb3J0LmFkZEV2ZW50TGlzdGVuZXIoJ3N0YXRlY2hhbmdlJywgKCkgPT5cblx0XHR7XG5cdFx0XHRzd2l0Y2ggKGljZVRyYW5zcG9ydC5zdGF0ZSlcblx0XHRcdHtcblx0XHRcdFx0Y2FzZSAnY2hlY2tpbmcnOlxuXHRcdFx0XHRcdHRoaXMuZW1pdCgnQGNvbm5lY3Rpb25zdGF0ZWNoYW5nZScsICdjb25uZWN0aW5nJyk7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdGNhc2UgJ2Nvbm5lY3RlZCc6XG5cdFx0XHRcdGNhc2UgJ2NvbXBsZXRlZCc6XG5cdFx0XHRcdFx0dGhpcy5lbWl0KCdAY29ubmVjdGlvbnN0YXRlY2hhbmdlJywgJ2Nvbm5lY3RlZCcpO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRjYXNlICdmYWlsZWQnOlxuXHRcdFx0XHRcdHRoaXMuZW1pdCgnQGNvbm5lY3Rpb25zdGF0ZWNoYW5nZScsICdmYWlsZWQnKTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0Y2FzZSAnZGlzY29ubmVjdGVkJzpcblx0XHRcdFx0XHR0aGlzLmVtaXQoJ0Bjb25uZWN0aW9uc3RhdGVjaGFuZ2UnLCAnZGlzY29ubmVjdGVkJyk7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdGNhc2UgJ2Nsb3NlZCc6XG5cdFx0XHRcdFx0dGhpcy5lbWl0KCdAY29ubmVjdGlvbnN0YXRlY2hhbmdlJywgJ2Nsb3NlZCcpO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0fVxuXHRcdH0pO1xuXG5cdFx0Ly8gTk9URTogTm90IHN0YW5kYXJkLCBidXQgaW1wbGVtZW50ZWQgYnkgRWRnZS5cblx0XHRpY2VUcmFuc3BvcnQuYWRkRXZlbnRMaXN0ZW5lcignaWNlc3RhdGVjaGFuZ2UnLCAoKSA9PlxuXHRcdHtcblx0XHRcdHN3aXRjaCAoaWNlVHJhbnNwb3J0LnN0YXRlKVxuXHRcdFx0e1xuXHRcdFx0XHRjYXNlICdjaGVja2luZyc6XG5cdFx0XHRcdFx0dGhpcy5lbWl0KCdAY29ubmVjdGlvbnN0YXRlY2hhbmdlJywgJ2Nvbm5lY3RpbmcnKTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0Y2FzZSAnY29ubmVjdGVkJzpcblx0XHRcdFx0Y2FzZSAnY29tcGxldGVkJzpcblx0XHRcdFx0XHR0aGlzLmVtaXQoJ0Bjb25uZWN0aW9uc3RhdGVjaGFuZ2UnLCAnY29ubmVjdGVkJyk7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdGNhc2UgJ2ZhaWxlZCc6XG5cdFx0XHRcdFx0dGhpcy5lbWl0KCdAY29ubmVjdGlvbnN0YXRlY2hhbmdlJywgJ2ZhaWxlZCcpO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRjYXNlICdkaXNjb25uZWN0ZWQnOlxuXHRcdFx0XHRcdHRoaXMuZW1pdCgnQGNvbm5lY3Rpb25zdGF0ZWNoYW5nZScsICdkaXNjb25uZWN0ZWQnKTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0Y2FzZSAnY2xvc2VkJzpcblx0XHRcdFx0XHR0aGlzLmVtaXQoJ0Bjb25uZWN0aW9uc3RhdGVjaGFuZ2UnLCAnY2xvc2VkJyk7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHR9XG5cdFx0fSk7XG5cblx0XHRpY2VUcmFuc3BvcnQuYWRkRXZlbnRMaXN0ZW5lcignY2FuZGlkYXRlcGFpcmNoYW5nZScsIChldmVudCkgPT5cblx0XHR7XG5cdFx0XHRsb2dnZXIuZGVidWcoXG5cdFx0XHRcdGBpY2VUcmFuc3BvcnQgXCJjYW5kaWRhdGVwYWlyY2hhbmdlXCIgZXZlbnQgW3BhaXI6JHtldmVudC5wYWlyfV1gKTtcblx0XHR9KTtcblxuXHRcdHRoaXMuX2ljZVRyYW5zcG9ydCA9IGljZVRyYW5zcG9ydDtcblx0fVxuXG5cdF9zZXREdGxzVHJhbnNwb3J0KClcblx0e1xuXHRcdGNvbnN0IGR0bHNUcmFuc3BvcnQgPSBuZXcgUlRDRHRsc1RyYW5zcG9ydCh0aGlzLl9pY2VUcmFuc3BvcnQpO1xuXG5cdFx0Ly8gTk9URTogTm90IHlldCBpbXBsZW1lbnRlZCBieSBFZGdlLlxuXHRcdGR0bHNUcmFuc3BvcnQuYWRkRXZlbnRMaXN0ZW5lcignc3RhdGVjaGFuZ2UnLCAoKSA9PlxuXHRcdHtcblx0XHRcdGxvZ2dlci5kZWJ1Zyhcblx0XHRcdFx0YGR0bHNUcmFuc3BvcnQgXCJzdGF0ZWNoYW5nZVwiIGV2ZW50IFtzdGF0ZToke2R0bHNUcmFuc3BvcnQuc3RhdGV9XWApO1xuXHRcdH0pO1xuXG5cdFx0Ly8gTk9URTogTm90IHN0YW5kYXJkLCBidXQgaW1wbGVtZW50ZWQgYnkgRWRnZS5cblx0XHRkdGxzVHJhbnNwb3J0LmFkZEV2ZW50TGlzdGVuZXIoJ2R0bHNzdGF0ZWNoYW5nZScsICgpID0+XG5cdFx0e1xuXHRcdFx0bG9nZ2VyLmRlYnVnKFxuXHRcdFx0XHRgZHRsc1RyYW5zcG9ydCBcImR0bHNzdGF0ZWNoYW5nZVwiIGV2ZW50IFtzdGF0ZToke2R0bHNUcmFuc3BvcnQuc3RhdGV9XWApO1xuXHRcdH0pO1xuXG5cdFx0ZHRsc1RyYW5zcG9ydC5hZGRFdmVudExpc3RlbmVyKCdlcnJvcicsIChldmVudCkgPT5cblx0XHR7XG5cdFx0XHRsZXQgZXJyb3I7XG5cblx0XHRcdGlmIChldmVudC5tZXNzYWdlKVxuXHRcdFx0XHRlcnJvciA9IGV2ZW50Lm1lc3NhZ2U7XG5cdFx0XHRlbHNlIGlmIChldmVudC5lcnJvcilcblx0XHRcdFx0ZXJyb3IgPSBldmVudC5lcnJvci5tZXNzYWdlO1xuXG5cdFx0XHRsb2dnZXIuZXJyb3IoYGR0bHNUcmFuc3BvcnQgXCJlcnJvclwiIGV2ZW50OiR7ZXJyb3J9YCk7XG5cdFx0fSk7XG5cblx0XHR0aGlzLl9kdGxzVHJhbnNwb3J0ID0gZHRsc1RyYW5zcG9ydDtcblx0fVxuXG5cdF9zZXR1cFRyYW5zcG9ydCgpXG5cdHtcblx0XHRsb2dnZXIuZGVidWcoJ19zZXR1cFRyYW5zcG9ydCgpJyk7XG5cblx0XHRyZXR1cm4gUHJvbWlzZS5yZXNvbHZlKClcblx0XHRcdC50aGVuKCgpID0+XG5cdFx0XHR7XG5cdFx0XHRcdC8vIEdldCBvdXIgbG9jYWwgRFRMUyBwYXJhbWV0ZXJzLlxuXHRcdFx0XHRjb25zdCB0cmFuc3BvcnRMb2NhbFBhcmFtZXRlcnMgPSB7fTtcblx0XHRcdFx0Y29uc3QgZHRsc1BhcmFtZXRlcnMgPSB0aGlzLl9kdGxzVHJhbnNwb3J0LmdldExvY2FsUGFyYW1ldGVycygpO1xuXG5cdFx0XHRcdC8vIExldCdzIGRlY2lkZSB0aGF0IHdlJ2xsIGJlIERUTFMgc2VydmVyIChiZWNhdXNlIHdlIGNhbikuXG5cdFx0XHRcdGR0bHNQYXJhbWV0ZXJzLnJvbGUgPSAnc2VydmVyJztcblxuXHRcdFx0XHR0cmFuc3BvcnRMb2NhbFBhcmFtZXRlcnMuZHRsc1BhcmFtZXRlcnMgPSBkdGxzUGFyYW1ldGVycztcblxuXHRcdFx0XHQvLyBXZSBuZWVkIHRyYW5zcG9ydCByZW1vdGUgcGFyYW1ldGVycy5cblx0XHRcdFx0cmV0dXJuIHRoaXMuc2FmZUVtaXRBc1Byb21pc2UoXG5cdFx0XHRcdFx0J0BuZWVkY3JlYXRldHJhbnNwb3J0JywgdHJhbnNwb3J0TG9jYWxQYXJhbWV0ZXJzKTtcblx0XHRcdH0pXG5cdFx0XHQudGhlbigodHJhbnNwb3J0UmVtb3RlUGFyYW1ldGVycykgPT5cblx0XHRcdHtcblx0XHRcdFx0Y29uc3QgcmVtb3RlSWNlUGFyYW1ldGVycyA9IHRyYW5zcG9ydFJlbW90ZVBhcmFtZXRlcnMuaWNlUGFyYW1ldGVycztcblx0XHRcdFx0Y29uc3QgcmVtb3RlSWNlQ2FuZGlkYXRlcyA9IHRyYW5zcG9ydFJlbW90ZVBhcmFtZXRlcnMuaWNlQ2FuZGlkYXRlcztcblx0XHRcdFx0Y29uc3QgcmVtb3RlRHRsc1BhcmFtZXRlcnMgPSB0cmFuc3BvcnRSZW1vdGVQYXJhbWV0ZXJzLmR0bHNQYXJhbWV0ZXJzO1xuXG5cdFx0XHRcdC8vIFN0YXJ0IHRoZSBSVENJY2VUcmFuc3BvcnQuXG5cdFx0XHRcdHRoaXMuX2ljZVRyYW5zcG9ydC5zdGFydChcblx0XHRcdFx0XHR0aGlzLl9pY2VHYXRoZXJlciwgcmVtb3RlSWNlUGFyYW1ldGVycywgJ2NvbnRyb2xsaW5nJyk7XG5cblx0XHRcdFx0Ly8gQWRkIHJlbW90ZSBJQ0UgY2FuZGlkYXRlcy5cblx0XHRcdFx0Zm9yIChjb25zdCBjYW5kaWRhdGUgb2YgcmVtb3RlSWNlQ2FuZGlkYXRlcylcblx0XHRcdFx0e1xuXHRcdFx0XHRcdHRoaXMuX2ljZVRyYW5zcG9ydC5hZGRSZW1vdGVDYW5kaWRhdGUoY2FuZGlkYXRlKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIEFsc28gc2lnbmFsIGEgJ2NvbXBsZXRlJyBjYW5kaWRhdGUgYXMgcGVyIHNwZWMuXG5cdFx0XHRcdC8vIE5PVEU6IEl0IHNob3VsZCBiZSB7Y29tcGxldGU6IHRydWV9IGJ1dCBFZGdlIHByZWZlcnMge30uXG5cdFx0XHRcdC8vIE5PVEU6IElmIHdlIGRvbid0IHNpZ25hbCBlbmQgb2YgY2FuZGlkYXRlcywgdGhlIEVkZ2UgUlRDSWNlVHJhbnNwb3J0XG5cdFx0XHRcdC8vIHdvbid0IGVudGVyIHRoZSAnY29tcGxldGVkJyBzdGF0ZS5cblx0XHRcdFx0dGhpcy5faWNlVHJhbnNwb3J0LmFkZFJlbW90ZUNhbmRpZGF0ZSh7fSk7XG5cblx0XHRcdFx0Ly8gU3RhcnQgdGhlIFJUQ0R0bHNUcmFuc3BvcnQuXG5cdFx0XHRcdHRoaXMuX2R0bHNUcmFuc3BvcnQuc3RhcnQocmVtb3RlRHRsc1BhcmFtZXRlcnMpO1xuXG5cdFx0XHRcdHRoaXMuX3RyYW5zcG9ydFJlYWR5ID0gdHJ1ZTtcblx0XHRcdH0pO1xuXHR9XG59XG4iLCJpbXBvcnQgc2RwVHJhbnNmb3JtIGZyb20gJ3NkcC10cmFuc2Zvcm0nO1xuaW1wb3J0IExvZ2dlciBmcm9tICcuLi9Mb2dnZXInO1xuaW1wb3J0IEVuaGFuY2VkRXZlbnRFbWl0dGVyIGZyb20gJy4uL0VuaGFuY2VkRXZlbnRFbWl0dGVyJztcbmltcG9ydCAqIGFzIHV0aWxzIGZyb20gJy4uL3V0aWxzJztcbmltcG9ydCAqIGFzIHNkcENvbW1vblV0aWxzIGZyb20gJy4vc2RwL2NvbW1vblV0aWxzJztcbmltcG9ydCAqIGFzIHNkcFVuaWZpZWRQbGFuVXRpbHMgZnJvbSAnLi9zZHAvdW5pZmllZFBsYW5VdGlscyc7XG5pbXBvcnQgUmVtb3RlVW5pZmllZFBsYW5TZHAgZnJvbSAnLi9zZHAvUmVtb3RlVW5pZmllZFBsYW5TZHAnO1xuXG5jb25zdCBsb2dnZXIgPSBuZXcgTG9nZ2VyKCdGaXJlZm94NTAnKTtcblxuY2xhc3MgSGFuZGxlciBleHRlbmRzIEVuaGFuY2VkRXZlbnRFbWl0dGVyXG57XG5cdGNvbnN0cnVjdG9yKGRpcmVjdGlvbiwgcnRwUGFyYW1ldGVyc0J5S2luZCwgc2V0dGluZ3MpXG5cdHtcblx0XHRzdXBlcigpO1xuXG5cdFx0Ly8gUlRDUGVlckNvbm5lY3Rpb24gaW5zdGFuY2UuXG5cdFx0Ly8gQHR5cGUge1JUQ1BlZXJDb25uZWN0aW9ufVxuXHRcdHRoaXMuX3BjID0gbmV3IFJUQ1BlZXJDb25uZWN0aW9uKFxuXHRcdFx0e1xuXHRcdFx0XHRpY2VTZXJ2ZXJzICAgICAgICAgOiBzZXR0aW5ncy50dXJuU2VydmVycyB8fCBbXSxcblx0XHRcdFx0aWNlVHJhbnNwb3J0UG9saWN5IDogJ3JlbGF5Jyxcblx0XHRcdFx0YnVuZGxlUG9saWN5ICAgICAgIDogJ21heC1idW5kbGUnLFxuXHRcdFx0XHRydGNwTXV4UG9saWN5ICAgICAgOiAncmVxdWlyZSdcblx0XHRcdH0pO1xuXG5cdFx0Ly8gR2VuZXJpYyBzZW5kaW5nIFJUUCBwYXJhbWV0ZXJzIGZvciBhdWRpbyBhbmQgdmlkZW8uXG5cdFx0Ly8gQHR5cGUge09iamVjdH1cblx0XHR0aGlzLl9ydHBQYXJhbWV0ZXJzQnlLaW5kID0gcnRwUGFyYW1ldGVyc0J5S2luZDtcblxuXHRcdC8vIFJlbW90ZSBTRFAgaGFuZGxlci5cblx0XHQvLyBAdHlwZSB7UmVtb3RlVW5pZmllZFBsYW5TZHB9XG5cdFx0dGhpcy5fcmVtb3RlU2RwID0gbmV3IFJlbW90ZVVuaWZpZWRQbGFuU2RwKGRpcmVjdGlvbiwgcnRwUGFyYW1ldGVyc0J5S2luZCk7XG5cblx0XHQvLyBIYW5kbGUgUlRDUGVlckNvbm5lY3Rpb24gY29ubmVjdGlvbiBzdGF0dXMuXG5cdFx0dGhpcy5fcGMuYWRkRXZlbnRMaXN0ZW5lcignaWNlY29ubmVjdGlvbnN0YXRlY2hhbmdlJywgKCkgPT5cblx0XHR7XG5cdFx0XHRzd2l0Y2ggKHRoaXMuX3BjLmljZUNvbm5lY3Rpb25TdGF0ZSlcblx0XHRcdHtcblx0XHRcdFx0Y2FzZSAnY2hlY2tpbmcnOlxuXHRcdFx0XHRcdHRoaXMuZW1pdCgnQGNvbm5lY3Rpb25zdGF0ZWNoYW5nZScsICdjb25uZWN0aW5nJyk7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdGNhc2UgJ2Nvbm5lY3RlZCc6XG5cdFx0XHRcdGNhc2UgJ2NvbXBsZXRlZCc6XG5cdFx0XHRcdFx0dGhpcy5lbWl0KCdAY29ubmVjdGlvbnN0YXRlY2hhbmdlJywgJ2Nvbm5lY3RlZCcpO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRjYXNlICdmYWlsZWQnOlxuXHRcdFx0XHRcdHRoaXMuZW1pdCgnQGNvbm5lY3Rpb25zdGF0ZWNoYW5nZScsICdmYWlsZWQnKTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0Y2FzZSAnZGlzY29ubmVjdGVkJzpcblx0XHRcdFx0XHR0aGlzLmVtaXQoJ0Bjb25uZWN0aW9uc3RhdGVjaGFuZ2UnLCAnZGlzY29ubmVjdGVkJyk7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdGNhc2UgJ2Nsb3NlZCc6XG5cdFx0XHRcdFx0dGhpcy5lbWl0KCdAY29ubmVjdGlvbnN0YXRlY2hhbmdlJywgJ2Nsb3NlZCcpO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0fVxuXHRcdH0pO1xuXHR9XG5cblx0Y2xvc2UoKVxuXHR7XG5cdFx0bG9nZ2VyLmRlYnVnKCdjbG9zZSgpJyk7XG5cblx0XHQvLyBDbG9zZSBSVENQZWVyQ29ubmVjdGlvbi5cblx0XHR0cnkgeyB0aGlzLl9wYy5jbG9zZSgpOyB9XG5cdFx0Y2F0Y2ggKGVycm9yKSB7fVxuXHR9XG59XG5cbmNsYXNzIFNlbmRIYW5kbGVyIGV4dGVuZHMgSGFuZGxlclxue1xuXHRjb25zdHJ1Y3RvcihydHBQYXJhbWV0ZXJzQnlLaW5kLCBzZXR0aW5ncylcblx0e1xuXHRcdHN1cGVyKCdzZW5kJywgcnRwUGFyYW1ldGVyc0J5S2luZCwgc2V0dGluZ3MpO1xuXG5cdFx0Ly8gR290IHRyYW5zcG9ydCBsb2NhbCBhbmQgcmVtb3RlIHBhcmFtZXRlcnMuXG5cdFx0Ly8gQHR5cGUge0Jvb2xlYW59XG5cdFx0dGhpcy5fdHJhbnNwb3J0UmVhZHkgPSBmYWxzZTtcblxuXHRcdC8vIExvY2FsIHN0cmVhbS5cblx0XHQvLyBAdHlwZSB7TWVkaWFTdHJlYW19XG5cdFx0dGhpcy5fc3RyZWFtID0gbmV3IE1lZGlhU3RyZWFtKCk7XG5cdH1cblxuXHRhZGRQcm9kdWNlcihwcm9kdWNlcilcblx0e1xuXHRcdGNvbnN0IHsgdHJhY2sgfSA9IHByb2R1Y2VyO1xuXG5cdFx0bG9nZ2VyLmRlYnVnKFxuXHRcdFx0J2FkZFByb2R1Y2VyKCkgW2lkOiVzLCBraW5kOiVzLCB0cmFja0lkOiVzXScsXG5cdFx0XHRwcm9kdWNlci5pZCwgcHJvZHVjZXIua2luZCwgdHJhY2suaWQpO1xuXG5cdFx0bGV0IHJ0cFNlbmRlcjtcblx0XHRsZXQgbG9jYWxTZHBPYmo7XG5cblx0XHRyZXR1cm4gUHJvbWlzZS5yZXNvbHZlKClcblx0XHRcdC50aGVuKCgpID0+XG5cdFx0XHR7XG5cdFx0XHRcdHRoaXMuX3N0cmVhbS5hZGRUcmFjayh0cmFjayk7XG5cblx0XHRcdFx0Ly8gQWRkIHRoZSBzdHJlYW0gdG8gdGhlIFBlZXJDb25uZWN0aW9uLlxuXHRcdFx0XHRydHBTZW5kZXIgPSB0aGlzLl9wYy5hZGRUcmFjayh0cmFjaywgdGhpcy5fc3RyZWFtKTtcblxuXHRcdFx0XHRyZXR1cm4gdGhpcy5fcGMuY3JlYXRlT2ZmZXIoKTtcblx0XHRcdH0pXG5cdFx0XHQudGhlbigob2ZmZXIpID0+XG5cdFx0XHR7XG5cdFx0XHRcdHJldHVybiB0aGlzLl9wYy5zZXRMb2NhbERlc2NyaXB0aW9uKG9mZmVyKTtcblx0XHRcdH0pXG5cdFx0XHQudGhlbigoKSA9PlxuXHRcdFx0e1xuXHRcdFx0XHRpZiAoIXRoaXMuX3RyYW5zcG9ydFJlYWR5KVxuXHRcdFx0XHRcdHJldHVybiB0aGlzLl9zZXR1cFRyYW5zcG9ydCgpO1xuXHRcdFx0fSlcblx0XHRcdC50aGVuKCgpID0+XG5cdFx0XHR7XG5cdFx0XHRcdGxvY2FsU2RwT2JqID0gc2RwVHJhbnNmb3JtLnBhcnNlKHRoaXMuX3BjLmxvY2FsRGVzY3JpcHRpb24uc2RwKTtcblxuXHRcdFx0XHRjb25zdCByZW1vdGVTZHAgPSB0aGlzLl9yZW1vdGVTZHAuY3JlYXRlQW5zd2VyU2RwKGxvY2FsU2RwT2JqKTtcblx0XHRcdFx0Y29uc3QgYW5zd2VyID0geyB0eXBlOiAnYW5zd2VyJywgc2RwOiByZW1vdGVTZHAgfTtcblxuXHRcdFx0XHRyZXR1cm4gdGhpcy5fcGMuc2V0UmVtb3RlRGVzY3JpcHRpb24oYW5zd2VyKTtcblx0XHRcdH0pXG5cdFx0XHQudGhlbigoKSA9PlxuXHRcdFx0e1xuXHRcdFx0XHRjb25zdCBydHBQYXJhbWV0ZXJzID0gdXRpbHMuY2xvbmUodGhpcy5fcnRwUGFyYW1ldGVyc0J5S2luZFtwcm9kdWNlci5raW5kXSk7XG5cblx0XHRcdFx0Ly8gRmlsbCB0aGUgUlRQIHBhcmFtZXRlcnMgZm9yIHRoaXMgdHJhY2suXG5cdFx0XHRcdHNkcFVuaWZpZWRQbGFuVXRpbHMuZmlsbFJ0cFBhcmFtZXRlcnNGb3JUcmFjayhcblx0XHRcdFx0XHRydHBQYXJhbWV0ZXJzLCBsb2NhbFNkcE9iaiwgdHJhY2spO1xuXG5cdFx0XHRcdHJldHVybiBydHBQYXJhbWV0ZXJzO1xuXHRcdFx0fSlcblx0XHRcdC5jYXRjaCgoZXJyb3IpID0+XG5cdFx0XHR7XG5cdFx0XHRcdC8vIFBhbmljIGhlcmUuIFRyeSB0byB1bmRvIHRoaW5ncy5cblxuXHRcdFx0XHR0cnkgeyB0aGlzLl9wYy5yZW1vdmVUcmFjayhydHBTZW5kZXIpOyB9XG5cdFx0XHRcdGNhdGNoIChlcnJvcjIpIHt9XG5cblx0XHRcdFx0dGhpcy5fc3RyZWFtLnJlbW92ZVRyYWNrKHRyYWNrKTtcblxuXHRcdFx0XHR0aHJvdyBlcnJvcjtcblx0XHRcdH0pO1xuXHR9XG5cblx0cmVtb3ZlUHJvZHVjZXIocHJvZHVjZXIpXG5cdHtcblx0XHRjb25zdCB7IHRyYWNrIH0gPSBwcm9kdWNlcjtcblxuXHRcdGxvZ2dlci5kZWJ1Zyhcblx0XHRcdCdyZW1vdmVQcm9kdWNlcigpIFtpZDolcywga2luZDolcywgdHJhY2tJZDolc10nLFxuXHRcdFx0cHJvZHVjZXIuaWQsIHByb2R1Y2VyLmtpbmQsIHRyYWNrLmlkKTtcblxuXHRcdHJldHVybiBQcm9taXNlLnJlc29sdmUoKVxuXHRcdFx0LnRoZW4oKCkgPT5cblx0XHRcdHtcblx0XHRcdFx0Ly8gR2V0IHRoZSBhc3NvY2lhdGVkIFJUQ1J0cFNlbmRlci5cblx0XHRcdFx0Y29uc3QgcnRwU2VuZGVyID0gdGhpcy5fcGMuZ2V0U2VuZGVycygpXG5cdFx0XHRcdFx0LmZpbmQoKHMpID0+IHMudHJhY2sgPT09IHRyYWNrKTtcblxuXHRcdFx0XHRpZiAoIXJ0cFNlbmRlcilcblx0XHRcdFx0XHR0aHJvdyBuZXcgRXJyb3IoJ2xvY2FsIHRyYWNrIG5vdCBmb3VuZCcpO1xuXG5cdFx0XHRcdC8vIFJlbW92ZSB0aGUgYXNzb2NpYXRlZCBSdHBTZW5kZXIuXG5cdFx0XHRcdHRoaXMuX3BjLnJlbW92ZVRyYWNrKHJ0cFNlbmRlcik7XG5cblx0XHRcdFx0Ly8gUmVtb3ZlIHRoZSB0cmFjayBmcm9tIHRoZSBsb2NhbCBzdHJlYW0uXG5cdFx0XHRcdHRoaXMuX3N0cmVhbS5yZW1vdmVUcmFjayh0cmFjayk7XG5cblx0XHRcdFx0Ly8gTk9URTogSWYgdGhlcmUgYXJlIG5vIHNlbmRpbmcgdHJhY2tzLCBzZXRMb2NhbERlc2NyaXB0aW9uKCkgd2lsbCBjYXVzZVxuXHRcdFx0XHQvLyBGaXJlZm94IHRvIGNsb3NlIERUTFMuIFNvIGZvciBub3csIGxldCdzIGF2b2lkIHN1Y2ggYSBTRFAgTy9BIGFuZCBsZWF2ZVxuXHRcdFx0XHQvLyBhdCBsZWFzdCBhIGZha2UtYWN0aXZlIHNlbmRpbmcgdHJhY2suXG5cdFx0XHRcdGlmICh0aGlzLl9zdHJlYW0uZ2V0VHJhY2tzKCkubGVuZ3RoID09PSAwKVxuXHRcdFx0XHRcdHJldHVybjtcblxuXHRcdFx0XHRyZXR1cm4gUHJvbWlzZS5yZXNvbHZlKClcblx0XHRcdFx0XHQudGhlbigoKSA9PiB0aGlzLl9wYy5jcmVhdGVPZmZlcigpKVxuXHRcdFx0XHRcdC50aGVuKChvZmZlcikgPT4gdGhpcy5fcGMuc2V0TG9jYWxEZXNjcmlwdGlvbihvZmZlcikpO1xuXHRcdFx0fSlcblx0XHRcdC50aGVuKCgpID0+XG5cdFx0XHR7XG5cdFx0XHRcdGlmICh0aGlzLl9wYy5zaWduYWxpbmdTdGF0ZSA9PT0gJ3N0YWJsZScpXG5cdFx0XHRcdFx0cmV0dXJuO1xuXG5cdFx0XHRcdGNvbnN0IGxvY2FsU2RwT2JqID0gc2RwVHJhbnNmb3JtLnBhcnNlKHRoaXMuX3BjLmxvY2FsRGVzY3JpcHRpb24uc2RwKTtcblx0XHRcdFx0Y29uc3QgcmVtb3RlU2RwID0gdGhpcy5fcmVtb3RlU2RwLmNyZWF0ZUFuc3dlclNkcChsb2NhbFNkcE9iaik7XG5cdFx0XHRcdGNvbnN0IGFuc3dlciA9IHsgdHlwZTogJ2Fuc3dlcicsIHNkcDogcmVtb3RlU2RwIH07XG5cblx0XHRcdFx0cmV0dXJuIHRoaXMuX3BjLnNldFJlbW90ZURlc2NyaXB0aW9uKGFuc3dlcik7XG5cdFx0XHR9KTtcblx0fVxuXG5cdF9zZXR1cFRyYW5zcG9ydCgpXG5cdHtcblx0XHRsb2dnZXIuZGVidWcoJ19zZXR1cFRyYW5zcG9ydCgpJyk7XG5cblx0XHRyZXR1cm4gUHJvbWlzZS5yZXNvbHZlKClcblx0XHRcdC50aGVuKCgpID0+XG5cdFx0XHR7XG5cdFx0XHRcdC8vIEdldCBvdXIgbG9jYWwgRFRMUyBwYXJhbWV0ZXJzLlxuXHRcdFx0XHRjb25zdCB0cmFuc3BvcnRMb2NhbFBhcmFtZXRlcnMgPSB7fTtcblx0XHRcdFx0Y29uc3Qgc2RwID0gdGhpcy5fcGMubG9jYWxEZXNjcmlwdGlvbi5zZHA7XG5cdFx0XHRcdGNvbnN0IHNkcE9iaiA9IHNkcFRyYW5zZm9ybS5wYXJzZShzZHApO1xuXHRcdFx0XHRjb25zdCBkdGxzUGFyYW1ldGVycyA9IHNkcENvbW1vblV0aWxzLmV4dHJhY3REdGxzUGFyYW1ldGVycyhzZHBPYmopO1xuXG5cdFx0XHRcdC8vIExldCdzIGRlY2lkZSB0aGF0IHdlJ2xsIGJlIERUTFMgc2VydmVyIChiZWNhdXNlIHdlIGNhbikuXG5cdFx0XHRcdGR0bHNQYXJhbWV0ZXJzLnJvbGUgPSAnc2VydmVyJztcblxuXHRcdFx0XHR0cmFuc3BvcnRMb2NhbFBhcmFtZXRlcnMuZHRsc1BhcmFtZXRlcnMgPSBkdGxzUGFyYW1ldGVycztcblxuXHRcdFx0XHQvLyBQcm92aWRlIHRoZSByZW1vdGUgU0RQIGhhbmRsZXIgd2l0aCB0cmFuc3BvcnQgbG9jYWwgcGFyYW1ldGVycy5cblx0XHRcdFx0dGhpcy5fcmVtb3RlU2RwLnNldFRyYW5zcG9ydExvY2FsUGFyYW1ldGVycyh0cmFuc3BvcnRMb2NhbFBhcmFtZXRlcnMpO1xuXG5cdFx0XHRcdC8vIFdlIG5lZWQgdHJhbnNwb3J0IHJlbW90ZSBwYXJhbWV0ZXJzLlxuXHRcdFx0XHRyZXR1cm4gdGhpcy5zYWZlRW1pdEFzUHJvbWlzZShcblx0XHRcdFx0XHQnQG5lZWRjcmVhdGV0cmFuc3BvcnQnLCB0cmFuc3BvcnRMb2NhbFBhcmFtZXRlcnMpO1xuXHRcdFx0fSlcblx0XHRcdC50aGVuKCh0cmFuc3BvcnRSZW1vdGVQYXJhbWV0ZXJzKSA9PlxuXHRcdFx0e1xuXHRcdFx0XHQvLyBQcm92aWRlIHRoZSByZW1vdGUgU0RQIGhhbmRsZXIgd2l0aCB0cmFuc3BvcnQgcmVtb3RlIHBhcmFtZXRlcnMuXG5cdFx0XHRcdHRoaXMuX3JlbW90ZVNkcC5zZXRUcmFuc3BvcnRSZW1vdGVQYXJhbWV0ZXJzKHRyYW5zcG9ydFJlbW90ZVBhcmFtZXRlcnMpO1xuXG5cdFx0XHRcdHRoaXMuX3RyYW5zcG9ydFJlYWR5ID0gdHJ1ZTtcblx0XHRcdH0pO1xuXHR9XG59XG5cbmNsYXNzIFJlY3ZIYW5kbGVyIGV4dGVuZHMgSGFuZGxlclxue1xuXHRjb25zdHJ1Y3RvcihydHBQYXJhbWV0ZXJzQnlLaW5kLCBzZXR0aW5ncylcblx0e1xuXHRcdHN1cGVyKCdyZWN2JywgcnRwUGFyYW1ldGVyc0J5S2luZCwgc2V0dGluZ3MpO1xuXG5cdFx0Ly8gR290IHRyYW5zcG9ydCByZW1vdGUgcGFyYW1ldGVycy5cblx0XHQvLyBAdHlwZSB7Qm9vbGVhbn1cblx0XHR0aGlzLl90cmFuc3BvcnRDcmVhdGVkID0gZmFsc2U7XG5cblx0XHQvLyBHb3QgdHJhbnNwb3J0IGxvY2FsIHBhcmFtZXRlcnMuXG5cdFx0Ly8gQHR5cGUge0Jvb2xlYW59XG5cdFx0dGhpcy5fdHJhbnNwb3J0VXBkYXRlZCA9IGZhbHNlO1xuXG5cdFx0Ly8gTWFwIG9mIENvbnN1bWVycyBpbmZvcm1hdGlvbiBpbmRleGVkIGJ5IGNvbnN1bWVyLmlkLlxuXHRcdC8vIC0gbWlkIHtTdHJpbmd9XG5cdFx0Ly8gLSBraW5kIHtTdHJpbmd9XG5cdFx0Ly8gLSBjbG9zZWQge0Jvb2xlYW59XG5cdFx0Ly8gLSB0cmFja0lkIHtTdHJpbmd9XG5cdFx0Ly8gLSBzc3JjIHtOdW1iZXJ9XG5cdFx0Ly8gLSBydHhTc3JjIHtOdW1iZXJ9XG5cdFx0Ly8gLSBjbmFtZSB7U3RyaW5nfVxuXHRcdC8vIEB0eXBlIHtNYXA8TnVtYmVyLCBPYmplY3Q+fVxuXHRcdHRoaXMuX2NvbnN1bWVySW5mb3MgPSBuZXcgTWFwKCk7XG5cdH1cblxuXHRhZGRDb25zdW1lcihjb25zdW1lcilcblx0e1xuXHRcdGxvZ2dlci5kZWJ1Zyhcblx0XHRcdCdhZGRDb25zdW1lcigpIFtpZDolcywga2luZDolc10nLCBjb25zdW1lci5pZCwgY29uc3VtZXIua2luZCk7XG5cblx0XHRpZiAodGhpcy5fY29uc3VtZXJJbmZvcy5oYXMoY29uc3VtZXIuaWQpKVxuXHRcdFx0cmV0dXJuIFByb21pc2UucmVqZWN0KCdDb25zdW1lciBhbHJlYWR5IGFkZGVkJyk7XG5cblx0XHRjb25zdCBlbmNvZGluZyA9IGNvbnN1bWVyLnJ0cFBhcmFtZXRlcnMuZW5jb2RpbmdzWzBdO1xuXHRcdGNvbnN0IGNuYW1lID0gY29uc3VtZXIucnRwUGFyYW1ldGVycy5ydGNwLmNuYW1lO1xuXHRcdGNvbnN0IGNvbnN1bWVySW5mbyA9XG5cdFx0e1xuXHRcdFx0bWlkICAgICA6IGBjb25zdW1lci0ke2NvbnN1bWVyLmtpbmR9LSR7Y29uc3VtZXIuaWR9YCxcblx0XHRcdGtpbmQgICAgOiBjb25zdW1lci5raW5kLFxuXHRcdFx0Y2xvc2VkICA6IGNvbnN1bWVyLmNsb3NlZCxcblx0XHRcdHRyYWNrSWQgOiBgY29uc3VtZXItJHtjb25zdW1lci5raW5kfS0ke2NvbnN1bWVyLmlkfWAsXG5cdFx0XHRzc3JjICAgIDogZW5jb2Rpbmcuc3NyYyxcblx0XHRcdGNuYW1lICAgOiBjbmFtZVxuXHRcdH07XG5cblx0XHRpZiAoZW5jb2RpbmcucnR4ICYmIGVuY29kaW5nLnJ0eC5zc3JjKVxuXHRcdFx0Y29uc3VtZXJJbmZvLnJ0eFNzcmMgPSBlbmNvZGluZy5ydHguc3NyYztcblxuXHRcdHRoaXMuX2NvbnN1bWVySW5mb3Muc2V0KGNvbnN1bWVyLmlkLCBjb25zdW1lckluZm8pO1xuXG5cdFx0cmV0dXJuIFByb21pc2UucmVzb2x2ZSgpXG5cdFx0XHQudGhlbigoKSA9PlxuXHRcdFx0e1xuXHRcdFx0XHRpZiAoIXRoaXMuX3RyYW5zcG9ydENyZWF0ZWQpXG5cdFx0XHRcdFx0cmV0dXJuIHRoaXMuX3NldHVwVHJhbnNwb3J0KCk7XG5cdFx0XHR9KVxuXHRcdFx0LnRoZW4oKCkgPT5cblx0XHRcdHtcblx0XHRcdFx0Y29uc3QgcmVtb3RlU2RwID0gdGhpcy5fcmVtb3RlU2RwLmNyZWF0ZU9mZmVyU2RwKFxuXHRcdFx0XHRcdEFycmF5LmZyb20odGhpcy5fY29uc3VtZXJJbmZvcy52YWx1ZXMoKSkpO1xuXHRcdFx0XHRjb25zdCBvZmZlciA9IHsgdHlwZTogJ29mZmVyJywgc2RwOiByZW1vdGVTZHAgfTtcblxuXHRcdFx0XHRyZXR1cm4gdGhpcy5fcGMuc2V0UmVtb3RlRGVzY3JpcHRpb24ob2ZmZXIpO1xuXHRcdFx0fSlcblx0XHRcdC50aGVuKCgpID0+XG5cdFx0XHR7XG5cdFx0XHRcdHJldHVybiB0aGlzLl9wYy5jcmVhdGVBbnN3ZXIoKTtcblx0XHRcdH0pXG5cdFx0XHQudGhlbigoYW5zd2VyKSA9PlxuXHRcdFx0e1xuXHRcdFx0XHRyZXR1cm4gdGhpcy5fcGMuc2V0TG9jYWxEZXNjcmlwdGlvbihhbnN3ZXIpO1xuXHRcdFx0fSlcblx0XHRcdC50aGVuKCgpID0+XG5cdFx0XHR7XG5cdFx0XHRcdGlmICghdGhpcy5fdHJhbnNwb3J0VXBkYXRlZClcblx0XHRcdFx0XHRyZXR1cm4gdGhpcy5fdXBkYXRlVHJhbnNwb3J0KCk7XG5cdFx0XHR9KVxuXHRcdFx0LnRoZW4oKCkgPT5cblx0XHRcdHtcblx0XHRcdFx0Y29uc3QgbmV3UnRwUmVjZWl2ZXIgPSB0aGlzLl9wYy5nZXRSZWNlaXZlcnMoKVxuXHRcdFx0XHRcdC5maW5kKChydHBSZWNlaXZlcikgPT5cblx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRjb25zdCB7IHRyYWNrIH0gPSBydHBSZWNlaXZlcjtcblxuXHRcdFx0XHRcdFx0aWYgKCF0cmFjaylcblx0XHRcdFx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXG5cdFx0XHRcdFx0XHRyZXR1cm4gdHJhY2suaWQgPT09IGNvbnN1bWVySW5mby50cmFja0lkO1xuXHRcdFx0XHRcdH0pO1xuXG5cdFx0XHRcdGlmICghbmV3UnRwUmVjZWl2ZXIpXG5cdFx0XHRcdFx0dGhyb3cgbmV3IEVycm9yKCdyZW1vdGUgdHJhY2sgbm90IGZvdW5kJyk7XG5cblx0XHRcdFx0cmV0dXJuIG5ld1J0cFJlY2VpdmVyLnRyYWNrO1xuXHRcdFx0fSk7XG5cdH1cblxuXHRyZW1vdmVDb25zdW1lcihjb25zdW1lcilcblx0e1xuXHRcdC8vIFRPRE86IElmIHRoaXMgaXMgdGhlIGxhc3QgYWN0aXZlIENvbnN1bWVyLCBGaXJlZm94IHdpbGwgY2xvc2UgdGhlIERUTFMuXG5cdFx0Ly8gVGhpcyBpcyBub3RlZCBpbiB0aGUgVE9ETy5tZCBmaWxlLlxuXG5cdFx0bG9nZ2VyLmRlYnVnKFxuXHRcdFx0J3JlbW92ZUNvbnN1bWVyKCkgW2lkOiVzLCBraW5kOiVzXScsIGNvbnN1bWVyLmlkLCBjb25zdW1lci5raW5kKTtcblxuXHRcdGNvbnN0IGNvbnN1bWVySW5mbyA9IHRoaXMuX2NvbnN1bWVySW5mb3MuZ2V0KGNvbnN1bWVyLmlkKTtcblxuXHRcdGlmICghY29uc3VtZXJJbmZvKVxuXHRcdFx0cmV0dXJuIFByb21pc2UucmVqZWN0KCdDb25zdW1lciBub3QgZm91bmQnKTtcblxuXHRcdGNvbnN1bWVySW5mby5jbG9zZWQgPSB0cnVlO1xuXG5cdFx0cmV0dXJuIFByb21pc2UucmVzb2x2ZSgpXG5cdFx0XHQudGhlbigoKSA9PlxuXHRcdFx0e1xuXHRcdFx0XHRjb25zdCByZW1vdGVTZHAgPSB0aGlzLl9yZW1vdGVTZHAuY3JlYXRlT2ZmZXJTZHAoXG5cdFx0XHRcdFx0QXJyYXkuZnJvbSh0aGlzLl9jb25zdW1lckluZm9zLnZhbHVlcygpKSk7XG5cdFx0XHRcdGNvbnN0IG9mZmVyID0geyB0eXBlOiAnb2ZmZXInLCBzZHA6IHJlbW90ZVNkcCB9O1xuXG5cdFx0XHRcdHJldHVybiB0aGlzLl9wYy5zZXRSZW1vdGVEZXNjcmlwdGlvbihvZmZlcik7XG5cdFx0XHR9KVxuXHRcdFx0LnRoZW4oKCkgPT5cblx0XHRcdHtcblx0XHRcdFx0cmV0dXJuIHRoaXMuX3BjLmNyZWF0ZUFuc3dlcigpO1xuXHRcdFx0fSlcblx0XHRcdC50aGVuKChhbnN3ZXIpID0+XG5cdFx0XHR7XG5cdFx0XHRcdHJldHVybiB0aGlzLl9wYy5zZXRMb2NhbERlc2NyaXB0aW9uKGFuc3dlcik7XG5cdFx0XHR9KTtcblx0fVxuXG5cdF9zZXR1cFRyYW5zcG9ydCgpXG5cdHtcblx0XHRsb2dnZXIuZGVidWcoJ19zZXR1cFRyYW5zcG9ydCgpJyk7XG5cblx0XHRyZXR1cm4gUHJvbWlzZS5yZXNvbHZlKClcblx0XHRcdC50aGVuKCgpID0+XG5cdFx0XHR7XG5cdFx0XHRcdC8vIFdlIG5lZWQgdHJhbnNwb3J0IHJlbW90ZSBwYXJhbWV0ZXJzLlxuXHRcdFx0XHRyZXR1cm4gdGhpcy5zYWZlRW1pdEFzUHJvbWlzZSgnQG5lZWRjcmVhdGV0cmFuc3BvcnQnLCBudWxsKTtcblx0XHRcdH0pXG5cdFx0XHQudGhlbigodHJhbnNwb3J0UmVtb3RlUGFyYW1ldGVycykgPT5cblx0XHRcdHtcblx0XHRcdFx0Ly8gUHJvdmlkZSB0aGUgcmVtb3RlIFNEUCBoYW5kbGVyIHdpdGggdHJhbnNwb3J0IHJlbW90ZSBwYXJhbWV0ZXJzLlxuXHRcdFx0XHR0aGlzLl9yZW1vdGVTZHAuc2V0VHJhbnNwb3J0UmVtb3RlUGFyYW1ldGVycyh0cmFuc3BvcnRSZW1vdGVQYXJhbWV0ZXJzKTtcblxuXHRcdFx0XHR0aGlzLl90cmFuc3BvcnRDcmVhdGVkID0gdHJ1ZTtcblx0XHRcdH0pO1xuXHR9XG5cblx0X3VwZGF0ZVRyYW5zcG9ydCgpXG5cdHtcblx0XHRsb2dnZXIuZGVidWcoJ191cGRhdGVUcmFuc3BvcnQoKScpO1xuXG5cdFx0Ly8gR2V0IG91ciBsb2NhbCBEVExTIHBhcmFtZXRlcnMuXG5cdFx0Ly8gY29uc3QgdHJhbnNwb3J0TG9jYWxQYXJhbWV0ZXJzID0ge307XG5cdFx0Y29uc3Qgc2RwID0gdGhpcy5fcGMubG9jYWxEZXNjcmlwdGlvbi5zZHA7XG5cdFx0Y29uc3Qgc2RwT2JqID0gc2RwVHJhbnNmb3JtLnBhcnNlKHNkcCk7XG5cdFx0Y29uc3QgZHRsc1BhcmFtZXRlcnMgPSBzZHBDb21tb25VdGlscy5leHRyYWN0RHRsc1BhcmFtZXRlcnMoc2RwT2JqKTtcblx0XHRjb25zdCB0cmFuc3BvcnRMb2NhbFBhcmFtZXRlcnMgPSB7IGR0bHNQYXJhbWV0ZXJzIH07XG5cblx0XHQvLyBXZSBuZWVkIHRvIHByb3ZpZGUgdHJhbnNwb3J0IGxvY2FsIHBhcmFtZXRlcnMuXG5cdFx0dGhpcy5zYWZlRW1pdCgnQG5lZWR1cGRhdGV0cmFuc3BvcnQnLCB0cmFuc3BvcnRMb2NhbFBhcmFtZXRlcnMpO1xuXG5cdFx0dGhpcy5fdHJhbnNwb3J0VXBkYXRlZCA9IHRydWU7XG5cdH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgRmlyZWZveDUwXG57XG5cdHN0YXRpYyBnZXQgbmFtZSgpXG5cdHtcblx0XHRyZXR1cm4gJ0ZpcmVmb3g1MCc7XG5cdH1cblxuXHRzdGF0aWMgZ2V0TG9jYWxSdHBDYXBhYmlsaXRpZXMoKVxuXHR7XG5cdFx0bG9nZ2VyLmRlYnVnKCdnZXRMb2NhbFJ0cENhcGFiaWxpdGllcygpJyk7XG5cblx0XHRjb25zdCBwYyA9IG5ldyBSVENQZWVyQ29ubmVjdGlvbihcblx0XHRcdHtcblx0XHRcdFx0aWNlU2VydmVycyAgICAgICAgIDogW10sXG5cdFx0XHRcdGljZVRyYW5zcG9ydFBvbGljeSA6ICdyZWxheScsXG5cdFx0XHRcdGJ1bmRsZVBvbGljeSAgICAgICA6ICdtYXgtYnVuZGxlJyxcblx0XHRcdFx0cnRjcE11eFBvbGljeSAgICAgIDogJ3JlcXVpcmUnXG5cdFx0XHR9KTtcblxuXHRcdHJldHVybiBwYy5jcmVhdGVPZmZlcihcblx0XHRcdHtcblx0XHRcdFx0b2ZmZXJUb1JlY2VpdmVBdWRpbyA6IHRydWUsXG5cdFx0XHRcdG9mZmVyVG9SZWNlaXZlVmlkZW8gOiB0cnVlXG5cdFx0XHR9KVxuXHRcdFx0LnRoZW4oKG9mZmVyKSA9PlxuXHRcdFx0e1xuXHRcdFx0XHR0cnkgeyBwYy5jbG9zZSgpOyB9XG5cdFx0XHRcdGNhdGNoIChlcnJvcikge31cblxuXHRcdFx0XHRjb25zdCBzZHBPYmogPSBzZHBUcmFuc2Zvcm0ucGFyc2Uob2ZmZXIuc2RwKTtcblx0XHRcdFx0Y29uc3QgbG9jYWxSdHBDYXBhYmlsaXRpZXMgPSBzZHBDb21tb25VdGlscy5leHRyYWN0UnRwQ2FwYWJpbGl0aWVzKHNkcE9iaik7XG5cblx0XHRcdFx0cmV0dXJuIGxvY2FsUnRwQ2FwYWJpbGl0aWVzO1xuXHRcdFx0fSlcblx0XHRcdC5jYXRjaCgoZXJyb3IpID0+XG5cdFx0XHR7XG5cdFx0XHRcdHRyeSB7IHBjLmNsb3NlKCk7IH1cblx0XHRcdFx0Y2F0Y2ggKGVycm9yMikge31cblxuXHRcdFx0XHR0aHJvdyBlcnJvcjtcblx0XHRcdH0pO1xuXHR9XG5cblx0Y29uc3RydWN0b3IoZGlyZWN0aW9uLCBleHRlbmRlZFJ0cENhcGFiaWxpdGllcywgc2V0dGluZ3MpXG5cdHtcblx0XHRsb2dnZXIuZGVidWcoXG5cdFx0XHQnY29uc3RydWN0b3IoKSBbZGlyZWN0aW9uOiVzLCBleHRlbmRlZFJ0cENhcGFiaWxpdGllczolb10nLFxuXHRcdFx0ZGlyZWN0aW9uLCBleHRlbmRlZFJ0cENhcGFiaWxpdGllcyk7XG5cblx0XHRsZXQgcnRwUGFyYW1ldGVyc0J5S2luZDtcblxuXHRcdHN3aXRjaCAoZGlyZWN0aW9uKVxuXHRcdHtcblx0XHRcdGNhc2UgJ3NlbmQnOlxuXHRcdFx0e1xuXHRcdFx0XHRydHBQYXJhbWV0ZXJzQnlLaW5kID1cblx0XHRcdFx0e1xuXHRcdFx0XHRcdGF1ZGlvIDogdXRpbHMuZ2V0U2VuZGluZ1J0cFBhcmFtZXRlcnMoJ2F1ZGlvJywgZXh0ZW5kZWRSdHBDYXBhYmlsaXRpZXMpLFxuXHRcdFx0XHRcdHZpZGVvIDogdXRpbHMuZ2V0U2VuZGluZ1J0cFBhcmFtZXRlcnMoJ3ZpZGVvJywgZXh0ZW5kZWRSdHBDYXBhYmlsaXRpZXMpXG5cdFx0XHRcdH07XG5cblx0XHRcdFx0cmV0dXJuIG5ldyBTZW5kSGFuZGxlcihydHBQYXJhbWV0ZXJzQnlLaW5kLCBzZXR0aW5ncyk7XG5cdFx0XHR9XG5cdFx0XHRjYXNlICdyZWN2Jzpcblx0XHRcdHtcblx0XHRcdFx0cnRwUGFyYW1ldGVyc0J5S2luZCA9XG5cdFx0XHRcdHtcblx0XHRcdFx0XHRhdWRpbyA6IHV0aWxzLmdldFJlY2VpdmluZ0Z1bGxSdHBQYXJhbWV0ZXJzKCdhdWRpbycsIGV4dGVuZGVkUnRwQ2FwYWJpbGl0aWVzKSxcblx0XHRcdFx0XHR2aWRlbyA6IHV0aWxzLmdldFJlY2VpdmluZ0Z1bGxSdHBQYXJhbWV0ZXJzKCd2aWRlbycsIGV4dGVuZGVkUnRwQ2FwYWJpbGl0aWVzKVxuXHRcdFx0XHR9O1xuXG5cdFx0XHRcdHJldHVybiBuZXcgUmVjdkhhbmRsZXIocnRwUGFyYW1ldGVyc0J5S2luZCwgc2V0dGluZ3MpO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxufVxuIiwiaW1wb3J0IHNkcFRyYW5zZm9ybSBmcm9tICdzZHAtdHJhbnNmb3JtJztcbmltcG9ydCBMb2dnZXIgZnJvbSAnLi4vTG9nZ2VyJztcbmltcG9ydCBFbmhhbmNlZEV2ZW50RW1pdHRlciBmcm9tICcuLi9FbmhhbmNlZEV2ZW50RW1pdHRlcic7XG5pbXBvcnQgKiBhcyB1dGlscyBmcm9tICcuLi91dGlscyc7XG5pbXBvcnQgKiBhcyBzZHBDb21tb25VdGlscyBmcm9tICcuL3NkcC9jb21tb25VdGlscyc7XG5pbXBvcnQgKiBhcyBzZHBQbGFuQlV0aWxzIGZyb20gJy4vc2RwL3BsYW5CVXRpbHMnO1xuaW1wb3J0IFJlbW90ZVBsYW5CU2RwIGZyb20gJy4vc2RwL1JlbW90ZVBsYW5CU2RwJztcblxuY29uc3QgbG9nZ2VyID0gbmV3IExvZ2dlcignU2FmYXJpMTEnKTtcblxuY2xhc3MgSGFuZGxlciBleHRlbmRzIEVuaGFuY2VkRXZlbnRFbWl0dGVyXG57XG5cdGNvbnN0cnVjdG9yKGRpcmVjdGlvbiwgcnRwUGFyYW1ldGVyc0J5S2luZCwgc2V0dGluZ3MpXG5cdHtcblx0XHRzdXBlcigpO1xuXG5cdFx0Ly8gUlRDUGVlckNvbm5lY3Rpb24gaW5zdGFuY2UuXG5cdFx0Ly8gQHR5cGUge1JUQ1BlZXJDb25uZWN0aW9ufVxuXHRcdHRoaXMuX3BjID0gbmV3IFJUQ1BlZXJDb25uZWN0aW9uKFxuXHRcdFx0e1xuXHRcdFx0XHRpY2VTZXJ2ZXJzICAgICAgICAgOiBzZXR0aW5ncy50dXJuU2VydmVycyB8fCBbXSxcblx0XHRcdFx0aWNlVHJhbnNwb3J0UG9saWN5IDogJ3JlbGF5Jyxcblx0XHRcdFx0YnVuZGxlUG9saWN5ICAgICAgIDogJ21heC1idW5kbGUnLFxuXHRcdFx0XHRydGNwTXV4UG9saWN5ICAgICAgOiAncmVxdWlyZSdcblx0XHRcdH0pO1xuXG5cdFx0Ly8gR2VuZXJpYyBzZW5kaW5nIFJUUCBwYXJhbWV0ZXJzIGZvciBhdWRpbyBhbmQgdmlkZW8uXG5cdFx0Ly8gQHR5cGUge09iamVjdH1cblx0XHR0aGlzLl9ydHBQYXJhbWV0ZXJzQnlLaW5kID0gcnRwUGFyYW1ldGVyc0J5S2luZDtcblxuXHRcdC8vIFJlbW90ZSBTRFAgaGFuZGxlci5cblx0XHQvLyBAdHlwZSB7UmVtb3RlUGxhbkJTZHB9XG5cdFx0dGhpcy5fcmVtb3RlU2RwID0gbmV3IFJlbW90ZVBsYW5CU2RwKGRpcmVjdGlvbiwgcnRwUGFyYW1ldGVyc0J5S2luZCk7XG5cblx0XHQvLyBIYW5kbGUgUlRDUGVlckNvbm5lY3Rpb24gY29ubmVjdGlvbiBzdGF0dXMuXG5cdFx0dGhpcy5fcGMuYWRkRXZlbnRMaXN0ZW5lcignaWNlY29ubmVjdGlvbnN0YXRlY2hhbmdlJywgKCkgPT5cblx0XHR7XG5cdFx0XHRzd2l0Y2ggKHRoaXMuX3BjLmljZUNvbm5lY3Rpb25TdGF0ZSlcblx0XHRcdHtcblx0XHRcdFx0Y2FzZSAnY2hlY2tpbmcnOlxuXHRcdFx0XHRcdHRoaXMuZW1pdCgnQGNvbm5lY3Rpb25zdGF0ZWNoYW5nZScsICdjb25uZWN0aW5nJyk7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdGNhc2UgJ2Nvbm5lY3RlZCc6XG5cdFx0XHRcdGNhc2UgJ2NvbXBsZXRlZCc6XG5cdFx0XHRcdFx0dGhpcy5lbWl0KCdAY29ubmVjdGlvbnN0YXRlY2hhbmdlJywgJ2Nvbm5lY3RlZCcpO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRjYXNlICdmYWlsZWQnOlxuXHRcdFx0XHRcdHRoaXMuZW1pdCgnQGNvbm5lY3Rpb25zdGF0ZWNoYW5nZScsICdmYWlsZWQnKTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0Y2FzZSAnZGlzY29ubmVjdGVkJzpcblx0XHRcdFx0XHR0aGlzLmVtaXQoJ0Bjb25uZWN0aW9uc3RhdGVjaGFuZ2UnLCAnZGlzY29ubmVjdGVkJyk7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdGNhc2UgJ2Nsb3NlZCc6XG5cdFx0XHRcdFx0dGhpcy5lbWl0KCdAY29ubmVjdGlvbnN0YXRlY2hhbmdlJywgJ2Nsb3NlZCcpO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0fVxuXHRcdH0pO1xuXHR9XG5cblx0Y2xvc2UoKVxuXHR7XG5cdFx0bG9nZ2VyLmRlYnVnKCdjbG9zZSgpJyk7XG5cblx0XHQvLyBDbG9zZSBSVENQZWVyQ29ubmVjdGlvbi5cblx0XHR0cnkgeyB0aGlzLl9wYy5jbG9zZSgpOyB9XG5cdFx0Y2F0Y2ggKGVycm9yKSB7fVxuXHR9XG59XG5cbmNsYXNzIFNlbmRIYW5kbGVyIGV4dGVuZHMgSGFuZGxlclxue1xuXHRjb25zdHJ1Y3RvcihydHBQYXJhbWV0ZXJzQnlLaW5kLCBzZXR0aW5ncylcblx0e1xuXHRcdHN1cGVyKCdzZW5kJywgcnRwUGFyYW1ldGVyc0J5S2luZCwgc2V0dGluZ3MpO1xuXG5cdFx0Ly8gR290IHRyYW5zcG9ydCBsb2NhbCBhbmQgcmVtb3RlIHBhcmFtZXRlcnMuXG5cdFx0Ly8gQHR5cGUge0Jvb2xlYW59XG5cdFx0dGhpcy5fdHJhbnNwb3J0UmVhZHkgPSBmYWxzZTtcblxuXHRcdC8vIExvY2FsIHN0cmVhbS5cblx0XHQvLyBAdHlwZSB7TWVkaWFTdHJlYW19XG5cdFx0dGhpcy5fc3RyZWFtID0gbmV3IE1lZGlhU3RyZWFtKCk7XG5cdH1cblxuXHRhZGRQcm9kdWNlcihwcm9kdWNlcilcblx0e1xuXHRcdGNvbnN0IHsgdHJhY2sgfSA9IHByb2R1Y2VyO1xuXG5cdFx0bG9nZ2VyLmRlYnVnKFxuXHRcdFx0J2FkZFByb2R1Y2VyKCkgW2lkOiVzLCBraW5kOiVzLCB0cmFja0lkOiVzXScsXG5cdFx0XHRwcm9kdWNlci5pZCwgcHJvZHVjZXIua2luZCwgdHJhY2suaWQpO1xuXG5cdFx0bGV0IHJ0cFNlbmRlcjtcblx0XHRsZXQgbG9jYWxTZHBPYmo7XG5cblx0XHRyZXR1cm4gUHJvbWlzZS5yZXNvbHZlKClcblx0XHRcdC50aGVuKCgpID0+XG5cdFx0XHR7XG5cdFx0XHRcdHRoaXMuX3N0cmVhbS5hZGRUcmFjayh0cmFjayk7XG5cblx0XHRcdFx0Ly8gQWRkIHRoZSBzdHJlYW0gdG8gdGhlIFBlZXJDb25uZWN0aW9uLlxuXHRcdFx0XHRydHBTZW5kZXIgPSB0aGlzLl9wYy5hZGRUcmFjayh0cmFjaywgdGhpcy5fc3RyZWFtKTtcblxuXHRcdFx0XHRyZXR1cm4gdGhpcy5fcGMuY3JlYXRlT2ZmZXIoKTtcblx0XHRcdH0pXG5cdFx0XHQudGhlbigob2ZmZXIpID0+XG5cdFx0XHR7XG5cdFx0XHRcdHJldHVybiB0aGlzLl9wYy5zZXRMb2NhbERlc2NyaXB0aW9uKG9mZmVyKTtcblx0XHRcdH0pXG5cdFx0XHQudGhlbigoKSA9PlxuXHRcdFx0e1xuXHRcdFx0XHRpZiAoIXRoaXMuX3RyYW5zcG9ydFJlYWR5KVxuXHRcdFx0XHRcdHJldHVybiB0aGlzLl9zZXR1cFRyYW5zcG9ydCgpO1xuXHRcdFx0fSlcblx0XHRcdC50aGVuKCgpID0+XG5cdFx0XHR7XG5cdFx0XHRcdGxvY2FsU2RwT2JqID0gc2RwVHJhbnNmb3JtLnBhcnNlKHRoaXMuX3BjLmxvY2FsRGVzY3JpcHRpb24uc2RwKTtcblxuXHRcdFx0XHRjb25zdCByZW1vdGVTZHAgPSB0aGlzLl9yZW1vdGVTZHAuY3JlYXRlQW5zd2VyU2RwKGxvY2FsU2RwT2JqKTtcblx0XHRcdFx0Y29uc3QgYW5zd2VyID0geyB0eXBlOiAnYW5zd2VyJywgc2RwOiByZW1vdGVTZHAgfTtcblxuXHRcdFx0XHRyZXR1cm4gdGhpcy5fcGMuc2V0UmVtb3RlRGVzY3JpcHRpb24oYW5zd2VyKTtcblx0XHRcdH0pXG5cdFx0XHQudGhlbigoKSA9PlxuXHRcdFx0e1xuXHRcdFx0XHRjb25zdCBydHBQYXJhbWV0ZXJzID0gdXRpbHMuY2xvbmUodGhpcy5fcnRwUGFyYW1ldGVyc0J5S2luZFtwcm9kdWNlci5raW5kXSk7XG5cblx0XHRcdFx0Ly8gRmlsbCB0aGUgUlRQIHBhcmFtZXRlcnMgZm9yIHRoaXMgdHJhY2suXG5cdFx0XHRcdHNkcFBsYW5CVXRpbHMuZmlsbFJ0cFBhcmFtZXRlcnNGb3JUcmFjayhcblx0XHRcdFx0XHRydHBQYXJhbWV0ZXJzLCBsb2NhbFNkcE9iaiwgdHJhY2spO1xuXG5cdFx0XHRcdHJldHVybiBydHBQYXJhbWV0ZXJzO1xuXHRcdFx0fSlcblx0XHRcdC5jYXRjaCgoZXJyb3IpID0+XG5cdFx0XHR7XG5cdFx0XHRcdC8vIFBhbmljIGhlcmUuIFRyeSB0byB1bmRvIHRoaW5ncy5cblxuXHRcdFx0XHR0cnkgeyB0aGlzLl9wYy5yZW1vdmVUcmFjayhydHBTZW5kZXIpOyB9XG5cdFx0XHRcdGNhdGNoIChlcnJvcjIpIHt9XG5cblx0XHRcdFx0dGhpcy5fc3RyZWFtLnJlbW92ZVRyYWNrKHRyYWNrKTtcblxuXHRcdFx0XHR0aHJvdyBlcnJvcjtcblx0XHRcdH0pO1xuXHR9XG5cblx0cmVtb3ZlUHJvZHVjZXIocHJvZHVjZXIpXG5cdHtcblx0XHRjb25zdCB7IHRyYWNrIH0gPSBwcm9kdWNlcjtcblxuXHRcdGxvZ2dlci5kZWJ1Zyhcblx0XHRcdCdyZW1vdmVQcm9kdWNlcigpIFtpZDolcywga2luZDolcywgdHJhY2tJZDolc10nLFxuXHRcdFx0cHJvZHVjZXIuaWQsIHByb2R1Y2VyLmtpbmQsIHRyYWNrLmlkKTtcblxuXHRcdHJldHVybiBQcm9taXNlLnJlc29sdmUoKVxuXHRcdFx0LnRoZW4oKCkgPT5cblx0XHRcdHtcblx0XHRcdFx0Ly8gR2V0IHRoZSBhc3NvY2lhdGVkIFJUQ1J0cFNlbmRlci5cblx0XHRcdFx0Y29uc3QgcnRwU2VuZGVyID0gdGhpcy5fcGMuZ2V0U2VuZGVycygpXG5cdFx0XHRcdFx0LmZpbmQoKHMpID0+IHMudHJhY2sgPT09IHRyYWNrKTtcblxuXHRcdFx0XHRpZiAoIXJ0cFNlbmRlcilcblx0XHRcdFx0XHR0aHJvdyBuZXcgRXJyb3IoJ2xvY2FsIHRyYWNrIG5vdCBmb3VuZCcpO1xuXG5cdFx0XHRcdC8vIFJlbW92ZSB0aGUgYXNzb2NpYXRlZCBSdHBTZW5kZXIuXG5cdFx0XHRcdHRoaXMuX3BjLnJlbW92ZVRyYWNrKHJ0cFNlbmRlcik7XG5cblx0XHRcdFx0Ly8gUmVtb3ZlIHRoZSB0cmFjayBmcm9tIHRoZSBsb2NhbCBzdHJlYW0uXG5cdFx0XHRcdHRoaXMuX3N0cmVhbS5yZW1vdmVUcmFjayh0cmFjayk7XG5cblx0XHRcdFx0cmV0dXJuIHRoaXMuX3BjLmNyZWF0ZU9mZmVyKCk7XG5cdFx0XHR9KVxuXHRcdFx0LnRoZW4oKG9mZmVyKSA9PlxuXHRcdFx0e1xuXHRcdFx0XHRyZXR1cm4gdGhpcy5fcGMuc2V0TG9jYWxEZXNjcmlwdGlvbihvZmZlcik7XG5cdFx0XHR9KVxuXHRcdFx0LmNhdGNoKChlcnJvcikgPT5cblx0XHRcdHtcblx0XHRcdFx0Ly8gTk9URTogSWYgdGhlcmUgYXJlIG5vIHNlbmRpbmcgdHJhY2tzLCBzZXRMb2NhbERlc2NyaXB0aW9uKCkgd2lsbCBmYWlsIHdpdGhcblx0XHRcdFx0Ly8gXCJGYWlsZWQgdG8gY3JlYXRlIGNoYW5uZWxzXCIuIElmIHNvLCBpZ25vcmUgaXQuXG5cdFx0XHRcdGlmICh0aGlzLl9zdHJlYW0uZ2V0VHJhY2tzKCkubGVuZ3RoID09PSAwKVxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0bG9nZ2VyLndhcm4oXG5cdFx0XHRcdFx0XHQncmVtb3ZlTG9jYWxUcmFjaygpIHwgaWdub3JpbmcgZXhwZWN0ZWQgZXJyb3IgZHVlIG5vIHNlbmRpbmcgdHJhY2tzOiAlcycsXG5cdFx0XHRcdFx0XHRlcnJvci50b1N0cmluZygpKTtcblxuXHRcdFx0XHRcdHJldHVybjtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdHRocm93IGVycm9yO1xuXHRcdFx0fSlcblx0XHRcdC50aGVuKCgpID0+XG5cdFx0XHR7XG5cdFx0XHRcdGlmICh0aGlzLl9wYy5zaWduYWxpbmdTdGF0ZSA9PT0gJ3N0YWJsZScpXG5cdFx0XHRcdFx0cmV0dXJuO1xuXG5cdFx0XHRcdGNvbnN0IGxvY2FsU2RwT2JqID0gc2RwVHJhbnNmb3JtLnBhcnNlKHRoaXMuX3BjLmxvY2FsRGVzY3JpcHRpb24uc2RwKTtcblx0XHRcdFx0Y29uc3QgcmVtb3RlU2RwID0gdGhpcy5fcmVtb3RlU2RwLmNyZWF0ZUFuc3dlclNkcChsb2NhbFNkcE9iaik7XG5cdFx0XHRcdGNvbnN0IGFuc3dlciA9IHsgdHlwZTogJ2Fuc3dlcicsIHNkcDogcmVtb3RlU2RwIH07XG5cblx0XHRcdFx0cmV0dXJuIHRoaXMuX3BjLnNldFJlbW90ZURlc2NyaXB0aW9uKGFuc3dlcik7XG5cdFx0XHR9KTtcblx0fVxuXG5cdF9zZXR1cFRyYW5zcG9ydCgpXG5cdHtcblx0XHRsb2dnZXIuZGVidWcoJ19zZXR1cFRyYW5zcG9ydCgpJyk7XG5cblx0XHRyZXR1cm4gUHJvbWlzZS5yZXNvbHZlKClcblx0XHRcdC50aGVuKCgpID0+XG5cdFx0XHR7XG5cdFx0XHRcdC8vIEdldCBvdXIgbG9jYWwgRFRMUyBwYXJhbWV0ZXJzLlxuXHRcdFx0XHRjb25zdCB0cmFuc3BvcnRMb2NhbFBhcmFtZXRlcnMgPSB7fTtcblx0XHRcdFx0Y29uc3Qgc2RwID0gdGhpcy5fcGMubG9jYWxEZXNjcmlwdGlvbi5zZHA7XG5cdFx0XHRcdGNvbnN0IHNkcE9iaiA9IHNkcFRyYW5zZm9ybS5wYXJzZShzZHApO1xuXHRcdFx0XHRjb25zdCBkdGxzUGFyYW1ldGVycyA9IHNkcENvbW1vblV0aWxzLmV4dHJhY3REdGxzUGFyYW1ldGVycyhzZHBPYmopO1xuXG5cdFx0XHRcdC8vIExldCdzIGRlY2lkZSB0aGF0IHdlJ2xsIGJlIERUTFMgc2VydmVyIChiZWNhdXNlIHdlIGNhbikuXG5cdFx0XHRcdGR0bHNQYXJhbWV0ZXJzLnJvbGUgPSAnc2VydmVyJztcblxuXHRcdFx0XHR0cmFuc3BvcnRMb2NhbFBhcmFtZXRlcnMuZHRsc1BhcmFtZXRlcnMgPSBkdGxzUGFyYW1ldGVycztcblxuXHRcdFx0XHQvLyBQcm92aWRlIHRoZSByZW1vdGUgU0RQIGhhbmRsZXIgd2l0aCB0cmFuc3BvcnQgbG9jYWwgcGFyYW1ldGVycy5cblx0XHRcdFx0dGhpcy5fcmVtb3RlU2RwLnNldFRyYW5zcG9ydExvY2FsUGFyYW1ldGVycyh0cmFuc3BvcnRMb2NhbFBhcmFtZXRlcnMpO1xuXG5cdFx0XHRcdC8vIFdlIG5lZWQgdHJhbnNwb3J0IHJlbW90ZSBwYXJhbWV0ZXJzLlxuXHRcdFx0XHRyZXR1cm4gdGhpcy5zYWZlRW1pdEFzUHJvbWlzZShcblx0XHRcdFx0XHQnQG5lZWRjcmVhdGV0cmFuc3BvcnQnLCB0cmFuc3BvcnRMb2NhbFBhcmFtZXRlcnMpO1xuXHRcdFx0fSlcblx0XHRcdC50aGVuKCh0cmFuc3BvcnRSZW1vdGVQYXJhbWV0ZXJzKSA9PlxuXHRcdFx0e1xuXHRcdFx0XHQvLyBQcm92aWRlIHRoZSByZW1vdGUgU0RQIGhhbmRsZXIgd2l0aCB0cmFuc3BvcnQgcmVtb3RlIHBhcmFtZXRlcnMuXG5cdFx0XHRcdHRoaXMuX3JlbW90ZVNkcC5zZXRUcmFuc3BvcnRSZW1vdGVQYXJhbWV0ZXJzKHRyYW5zcG9ydFJlbW90ZVBhcmFtZXRlcnMpO1xuXG5cdFx0XHRcdHRoaXMuX3RyYW5zcG9ydFJlYWR5ID0gdHJ1ZTtcblx0XHRcdH0pO1xuXHR9XG59XG5cbmNsYXNzIFJlY3ZIYW5kbGVyIGV4dGVuZHMgSGFuZGxlclxue1xuXHRjb25zdHJ1Y3RvcihydHBQYXJhbWV0ZXJzQnlLaW5kLCBzZXR0aW5ncylcblx0e1xuXHRcdHN1cGVyKCdyZWN2JywgcnRwUGFyYW1ldGVyc0J5S2luZCwgc2V0dGluZ3MpO1xuXG5cdFx0Ly8gR290IHRyYW5zcG9ydCByZW1vdGUgcGFyYW1ldGVycy5cblx0XHQvLyBAdHlwZSB7Qm9vbGVhbn1cblx0XHR0aGlzLl90cmFuc3BvcnRDcmVhdGVkID0gZmFsc2U7XG5cblx0XHQvLyBHb3QgdHJhbnNwb3J0IGxvY2FsIHBhcmFtZXRlcnMuXG5cdFx0Ly8gQHR5cGUge0Jvb2xlYW59XG5cdFx0dGhpcy5fdHJhbnNwb3J0VXBkYXRlZCA9IGZhbHNlO1xuXG5cdFx0Ly8gU2VlbiBtZWRpYSBraW5kcy5cblx0XHQvLyBAdHlwZSB7U2V0PFN0cmluZz59XG5cdFx0dGhpcy5fa2luZHMgPSBuZXcgU2V0KCk7XG5cblx0XHQvLyBNYXAgb2YgQ29uc3VtZXJzIGluZm9ybWF0aW9uIGluZGV4ZWQgYnkgY29uc3VtZXIuaWQuXG5cdFx0Ly8gLSBraW5kIHtTdHJpbmd9XG5cdFx0Ly8gLSB0cmFja0lkIHtTdHJpbmd9XG5cdFx0Ly8gLSBzc3JjIHtOdW1iZXJ9XG5cdFx0Ly8gLSBydHhTc3JjIHtOdW1iZXJ9XG5cdFx0Ly8gLSBjbmFtZSB7U3RyaW5nfVxuXHRcdC8vIEB0eXBlIHtNYXA8TnVtYmVyLCBPYmplY3Q+fVxuXHRcdHRoaXMuX2NvbnN1bWVySW5mb3MgPSBuZXcgTWFwKCk7XG5cdH1cblxuXHRhZGRDb25zdW1lcihjb25zdW1lcilcblx0e1xuXHRcdGxvZ2dlci5kZWJ1Zyhcblx0XHRcdCdhZGRDb25zdW1lcigpIFtpZDolcywga2luZDolc10nLCBjb25zdW1lci5pZCwgY29uc3VtZXIua2luZCk7XG5cblx0XHRpZiAodGhpcy5fY29uc3VtZXJJbmZvcy5oYXMoY29uc3VtZXIuaWQpKVxuXHRcdFx0cmV0dXJuIFByb21pc2UucmVqZWN0KCdDb25zdW1lciBhbHJlYWR5IGFkZGVkJyk7XG5cblx0XHRjb25zdCBlbmNvZGluZyA9IGNvbnN1bWVyLnJ0cFBhcmFtZXRlcnMuZW5jb2RpbmdzWzBdO1xuXHRcdGNvbnN0IGNuYW1lID0gY29uc3VtZXIucnRwUGFyYW1ldGVycy5ydGNwLmNuYW1lO1xuXHRcdGNvbnN0IGNvbnN1bWVySW5mbyA9XG5cdFx0e1xuXHRcdFx0a2luZCAgICA6IGNvbnN1bWVyLmtpbmQsXG5cdFx0XHR0cmFja0lkIDogYGNvbnN1bWVyLSR7Y29uc3VtZXIua2luZH0tJHtjb25zdW1lci5pZH1gLFxuXHRcdFx0c3NyYyAgICA6IGVuY29kaW5nLnNzcmMsXG5cdFx0XHRjbmFtZSAgIDogY25hbWVcblx0XHR9O1xuXG5cdFx0aWYgKGVuY29kaW5nLnJ0eCAmJiBlbmNvZGluZy5ydHguc3NyYylcblx0XHRcdGNvbnN1bWVySW5mby5ydHhTc3JjID0gZW5jb2RpbmcucnR4LnNzcmM7XG5cblx0XHR0aGlzLl9jb25zdW1lckluZm9zLnNldChjb25zdW1lci5pZCwgY29uc3VtZXJJbmZvKTtcblx0XHR0aGlzLl9raW5kcy5hZGQoY29uc3VtZXIua2luZCk7XG5cblx0XHRyZXR1cm4gUHJvbWlzZS5yZXNvbHZlKClcblx0XHRcdC50aGVuKCgpID0+XG5cdFx0XHR7XG5cdFx0XHRcdGlmICghdGhpcy5fdHJhbnNwb3J0Q3JlYXRlZClcblx0XHRcdFx0XHRyZXR1cm4gdGhpcy5fc2V0dXBUcmFuc3BvcnQoKTtcblx0XHRcdH0pXG5cdFx0XHQudGhlbigoKSA9PlxuXHRcdFx0e1xuXHRcdFx0XHRjb25zdCByZW1vdGVTZHAgPSB0aGlzLl9yZW1vdGVTZHAuY3JlYXRlT2ZmZXJTZHAoXG5cdFx0XHRcdFx0QXJyYXkuZnJvbSh0aGlzLl9raW5kcyksIEFycmF5LmZyb20odGhpcy5fY29uc3VtZXJJbmZvcy52YWx1ZXMoKSkpO1xuXHRcdFx0XHRjb25zdCBvZmZlciA9IHsgdHlwZTogJ29mZmVyJywgc2RwOiByZW1vdGVTZHAgfTtcblxuXHRcdFx0XHRyZXR1cm4gdGhpcy5fcGMuc2V0UmVtb3RlRGVzY3JpcHRpb24ob2ZmZXIpO1xuXHRcdFx0fSlcblx0XHRcdC50aGVuKCgpID0+XG5cdFx0XHR7XG5cdFx0XHRcdHJldHVybiB0aGlzLl9wYy5jcmVhdGVBbnN3ZXIoKTtcblx0XHRcdH0pXG5cdFx0XHQudGhlbigoYW5zd2VyKSA9PlxuXHRcdFx0e1xuXHRcdFx0XHRyZXR1cm4gdGhpcy5fcGMuc2V0TG9jYWxEZXNjcmlwdGlvbihhbnN3ZXIpO1xuXHRcdFx0fSlcblx0XHRcdC50aGVuKCgpID0+XG5cdFx0XHR7XG5cdFx0XHRcdGlmICghdGhpcy5fdHJhbnNwb3J0VXBkYXRlZClcblx0XHRcdFx0XHRyZXR1cm4gdGhpcy5fdXBkYXRlVHJhbnNwb3J0KCk7XG5cdFx0XHR9KVxuXHRcdFx0LnRoZW4oKCkgPT5cblx0XHRcdHtcblx0XHRcdFx0Y29uc3QgbmV3UnRwUmVjZWl2ZXIgPSB0aGlzLl9wYy5nZXRSZWNlaXZlcnMoKVxuXHRcdFx0XHRcdC5maW5kKChydHBSZWNlaXZlcikgPT5cblx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRjb25zdCB7IHRyYWNrIH0gPSBydHBSZWNlaXZlcjtcblxuXHRcdFx0XHRcdFx0aWYgKCF0cmFjaylcblx0XHRcdFx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXG5cdFx0XHRcdFx0XHRyZXR1cm4gdHJhY2suaWQgPT09IGNvbnN1bWVySW5mby50cmFja0lkO1xuXHRcdFx0XHRcdH0pO1xuXG5cdFx0XHRcdGlmICghbmV3UnRwUmVjZWl2ZXIpXG5cdFx0XHRcdFx0dGhyb3cgbmV3IEVycm9yKCdyZW1vdGUgdHJhY2sgbm90IGZvdW5kJyk7XG5cblx0XHRcdFx0cmV0dXJuIG5ld1J0cFJlY2VpdmVyLnRyYWNrO1xuXHRcdFx0fSk7XG5cdH1cblxuXHRyZW1vdmVDb25zdW1lcihjb25zdW1lcilcblx0e1xuXHRcdGxvZ2dlci5kZWJ1Zyhcblx0XHRcdCdyZW1vdmVDb25zdW1lcigpIFtpZDolcywga2luZDolc10nLCBjb25zdW1lci5pZCwgY29uc3VtZXIua2luZCk7XG5cblx0XHRpZiAoIXRoaXMuX2NvbnN1bWVySW5mb3MuaGFzKGNvbnN1bWVyLmlkKSlcblx0XHRcdHJldHVybiBQcm9taXNlLnJlamVjdCgnQ29uc3VtZXIgbm90IGZvdW5kJyk7XG5cblx0XHR0aGlzLl9jb25zdW1lckluZm9zLmRlbGV0ZShjb25zdW1lci5pZCk7XG5cblx0XHRyZXR1cm4gUHJvbWlzZS5yZXNvbHZlKClcblx0XHRcdC50aGVuKCgpID0+XG5cdFx0XHR7XG5cdFx0XHRcdGNvbnN0IHJlbW90ZVNkcCA9IHRoaXMuX3JlbW90ZVNkcC5jcmVhdGVPZmZlclNkcChcblx0XHRcdFx0XHRBcnJheS5mcm9tKHRoaXMuX2tpbmRzKSwgQXJyYXkuZnJvbSh0aGlzLl9jb25zdW1lckluZm9zLnZhbHVlcygpKSk7XG5cdFx0XHRcdGNvbnN0IG9mZmVyID0geyB0eXBlOiAnb2ZmZXInLCBzZHA6IHJlbW90ZVNkcCB9O1xuXG5cdFx0XHRcdHJldHVybiB0aGlzLl9wYy5zZXRSZW1vdGVEZXNjcmlwdGlvbihvZmZlcik7XG5cdFx0XHR9KVxuXHRcdFx0LnRoZW4oKCkgPT5cblx0XHRcdHtcblx0XHRcdFx0cmV0dXJuIHRoaXMuX3BjLmNyZWF0ZUFuc3dlcigpO1xuXHRcdFx0fSlcblx0XHRcdC50aGVuKChhbnN3ZXIpID0+XG5cdFx0XHR7XG5cdFx0XHRcdHJldHVybiB0aGlzLl9wYy5zZXRMb2NhbERlc2NyaXB0aW9uKGFuc3dlcik7XG5cdFx0XHR9KTtcblx0fVxuXG5cdF9zZXR1cFRyYW5zcG9ydCgpXG5cdHtcblx0XHRsb2dnZXIuZGVidWcoJ19zZXR1cFRyYW5zcG9ydCgpJyk7XG5cblx0XHRyZXR1cm4gUHJvbWlzZS5yZXNvbHZlKClcblx0XHRcdC50aGVuKCgpID0+XG5cdFx0XHR7XG5cdFx0XHRcdC8vIFdlIG5lZWQgdHJhbnNwb3J0IHJlbW90ZSBwYXJhbWV0ZXJzLlxuXHRcdFx0XHRyZXR1cm4gdGhpcy5zYWZlRW1pdEFzUHJvbWlzZSgnQG5lZWRjcmVhdGV0cmFuc3BvcnQnLCBudWxsKTtcblx0XHRcdH0pXG5cdFx0XHQudGhlbigodHJhbnNwb3J0UmVtb3RlUGFyYW1ldGVycykgPT5cblx0XHRcdHtcblx0XHRcdFx0Ly8gUHJvdmlkZSB0aGUgcmVtb3RlIFNEUCBoYW5kbGVyIHdpdGggdHJhbnNwb3J0IHJlbW90ZSBwYXJhbWV0ZXJzLlxuXHRcdFx0XHR0aGlzLl9yZW1vdGVTZHAuc2V0VHJhbnNwb3J0UmVtb3RlUGFyYW1ldGVycyh0cmFuc3BvcnRSZW1vdGVQYXJhbWV0ZXJzKTtcblxuXHRcdFx0XHR0aGlzLl90cmFuc3BvcnRDcmVhdGVkID0gdHJ1ZTtcblx0XHRcdH0pO1xuXHR9XG5cblx0X3VwZGF0ZVRyYW5zcG9ydCgpXG5cdHtcblx0XHRsb2dnZXIuZGVidWcoJ191cGRhdGVUcmFuc3BvcnQoKScpO1xuXG5cdFx0Ly8gR2V0IG91ciBsb2NhbCBEVExTIHBhcmFtZXRlcnMuXG5cdFx0Ly8gY29uc3QgdHJhbnNwb3J0TG9jYWxQYXJhbWV0ZXJzID0ge307XG5cdFx0Y29uc3Qgc2RwID0gdGhpcy5fcGMubG9jYWxEZXNjcmlwdGlvbi5zZHA7XG5cdFx0Y29uc3Qgc2RwT2JqID0gc2RwVHJhbnNmb3JtLnBhcnNlKHNkcCk7XG5cdFx0Y29uc3QgZHRsc1BhcmFtZXRlcnMgPSBzZHBDb21tb25VdGlscy5leHRyYWN0RHRsc1BhcmFtZXRlcnMoc2RwT2JqKTtcblx0XHRjb25zdCB0cmFuc3BvcnRMb2NhbFBhcmFtZXRlcnMgPSB7IGR0bHNQYXJhbWV0ZXJzIH07XG5cblx0XHQvLyBXZSBuZWVkIHRvIHByb3ZpZGUgdHJhbnNwb3J0IGxvY2FsIHBhcmFtZXRlcnMuXG5cdFx0dGhpcy5zYWZlRW1pdCgnQG5lZWR1cGRhdGV0cmFuc3BvcnQnLCB0cmFuc3BvcnRMb2NhbFBhcmFtZXRlcnMpO1xuXG5cdFx0dGhpcy5fdHJhbnNwb3J0VXBkYXRlZCA9IHRydWU7XG5cdH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgU2FmYXJpMTFcbntcblx0c3RhdGljIGdldCBuYW1lKClcblx0e1xuXHRcdHJldHVybiAnU2FmYXJpMTEnO1xuXHR9XG5cblx0c3RhdGljIGdldExvY2FsUnRwQ2FwYWJpbGl0aWVzKClcblx0e1xuXHRcdGxvZ2dlci5kZWJ1ZygnZ2V0TG9jYWxSdHBDYXBhYmlsaXRpZXMoKScpO1xuXG5cdFx0Y29uc3QgcGMgPSBuZXcgUlRDUGVlckNvbm5lY3Rpb24oXG5cdFx0XHR7XG5cdFx0XHRcdGljZVNlcnZlcnMgICAgICAgICA6IFtdLFxuXHRcdFx0XHRpY2VUcmFuc3BvcnRQb2xpY3kgOiAncmVsYXknLFxuXHRcdFx0XHRidW5kbGVQb2xpY3kgICAgICAgOiAnbWF4LWJ1bmRsZScsXG5cdFx0XHRcdHJ0Y3BNdXhQb2xpY3kgICAgICA6ICdyZXF1aXJlJ1xuXHRcdFx0fSk7XG5cblx0XHRwYy5hZGRUcmFuc2NlaXZlcignYXVkaW8nKTtcblx0XHRwYy5hZGRUcmFuc2NlaXZlcigndmlkZW8nKTtcblxuXHRcdHJldHVybiBwYy5jcmVhdGVPZmZlcigpXG5cdFx0XHQudGhlbigob2ZmZXIpID0+XG5cdFx0XHR7XG5cdFx0XHRcdHRyeSB7IHBjLmNsb3NlKCk7IH1cblx0XHRcdFx0Y2F0Y2ggKGVycm9yKSB7fVxuXG5cdFx0XHRcdGNvbnN0IHNkcE9iaiA9IHNkcFRyYW5zZm9ybS5wYXJzZShvZmZlci5zZHApO1xuXHRcdFx0XHRjb25zdCBsb2NhbFJ0cENhcGFiaWxpdGllcyA9IHNkcENvbW1vblV0aWxzLmV4dHJhY3RSdHBDYXBhYmlsaXRpZXMoc2RwT2JqKTtcblxuXHRcdFx0XHRyZXR1cm4gbG9jYWxSdHBDYXBhYmlsaXRpZXM7XG5cdFx0XHR9KVxuXHRcdFx0LmNhdGNoKChlcnJvcikgPT5cblx0XHRcdHtcblx0XHRcdFx0dHJ5IHsgcGMuY2xvc2UoKTsgfVxuXHRcdFx0XHRjYXRjaCAoZXJyb3IyKSB7fVxuXG5cdFx0XHRcdHRocm93IGVycm9yO1xuXHRcdFx0fSk7XG5cdH1cblxuXHRjb25zdHJ1Y3RvcihkaXJlY3Rpb24sIGV4dGVuZGVkUnRwQ2FwYWJpbGl0aWVzLCBzZXR0aW5ncylcblx0e1xuXHRcdGxvZ2dlci5kZWJ1Zyhcblx0XHRcdCdjb25zdHJ1Y3RvcigpIFtkaXJlY3Rpb246JXMsIGV4dGVuZGVkUnRwQ2FwYWJpbGl0aWVzOiVvXScsXG5cdFx0XHRkaXJlY3Rpb24sIGV4dGVuZGVkUnRwQ2FwYWJpbGl0aWVzKTtcblxuXHRcdGxldCBydHBQYXJhbWV0ZXJzQnlLaW5kO1xuXG5cdFx0c3dpdGNoIChkaXJlY3Rpb24pXG5cdFx0e1xuXHRcdFx0Y2FzZSAnc2VuZCc6XG5cdFx0XHR7XG5cdFx0XHRcdHJ0cFBhcmFtZXRlcnNCeUtpbmQgPVxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0YXVkaW8gOiB1dGlscy5nZXRTZW5kaW5nUnRwUGFyYW1ldGVycygnYXVkaW8nLCBleHRlbmRlZFJ0cENhcGFiaWxpdGllcyksXG5cdFx0XHRcdFx0dmlkZW8gOiB1dGlscy5nZXRTZW5kaW5nUnRwUGFyYW1ldGVycygndmlkZW8nLCBleHRlbmRlZFJ0cENhcGFiaWxpdGllcylcblx0XHRcdFx0fTtcblxuXHRcdFx0XHRyZXR1cm4gbmV3IFNlbmRIYW5kbGVyKHJ0cFBhcmFtZXRlcnNCeUtpbmQsIHNldHRpbmdzKTtcblx0XHRcdH1cblx0XHRcdGNhc2UgJ3JlY3YnOlxuXHRcdFx0e1xuXHRcdFx0XHRydHBQYXJhbWV0ZXJzQnlLaW5kID1cblx0XHRcdFx0e1xuXHRcdFx0XHRcdGF1ZGlvIDogdXRpbHMuZ2V0UmVjZWl2aW5nRnVsbFJ0cFBhcmFtZXRlcnMoJ2F1ZGlvJywgZXh0ZW5kZWRSdHBDYXBhYmlsaXRpZXMpLFxuXHRcdFx0XHRcdHZpZGVvIDogdXRpbHMuZ2V0UmVjZWl2aW5nRnVsbFJ0cFBhcmFtZXRlcnMoJ3ZpZGVvJywgZXh0ZW5kZWRSdHBDYXBhYmlsaXRpZXMpXG5cdFx0XHRcdH07XG5cblx0XHRcdFx0cmV0dXJuIG5ldyBSZWN2SGFuZGxlcihydHBQYXJhbWV0ZXJzQnlLaW5kLCBzZXR0aW5ncyk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG59XG4iLCJpbXBvcnQgc2RwVHJhbnNmb3JtIGZyb20gJ3NkcC10cmFuc2Zvcm0nO1xuaW1wb3J0IExvZ2dlciBmcm9tICcuLi8uLi9Mb2dnZXInO1xuaW1wb3J0ICogYXMgdXRpbHMgZnJvbSAnLi4vLi4vdXRpbHMnO1xuXG5jb25zdCBsb2dnZXIgPSBuZXcgTG9nZ2VyKCdSZW1vdGVQbGFuQlNkcCcpO1xuXG5jbGFzcyBSZW1vdGVTZHBcbntcblx0Y29uc3RydWN0b3IocnRwUGFyYW1ldGVyc0J5S2luZClcblx0e1xuXHRcdC8vIEdlbmVyaWMgc2VuZGluZyBSVFAgcGFyYW1ldGVycyBmb3IgYXVkaW8gYW5kIHZpZGVvLlxuXHRcdC8vIEB0eXBlIHtPYmplY3R9XG5cdFx0dGhpcy5fcnRwUGFyYW1ldGVyc0J5S2luZCA9IHJ0cFBhcmFtZXRlcnNCeUtpbmQ7XG5cblx0XHQvLyBUcmFuc3BvcnQgbG9jYWwgcGFyYW1ldGVycywgaW5jbHVkaW5nIERUTFMgcGFyYW1ldGVyZXMuXG5cdFx0Ly8gQHR5cGUge09iamVjdH1cblx0XHR0aGlzLl90cmFuc3BvcnRMb2NhbFBhcmFtZXRlcnMgPSBudWxsO1xuXG5cdFx0Ly8gVHJhbnNwb3J0IHJlbW90ZSBwYXJhbWV0ZXJzLCBpbmNsdWRpbmcgSUNFIHBhcmFtZXRlcnMsIElDRSBjYW5kaWRhdGVzXG5cdFx0Ly8gYW5kIERUTFMgcGFyYW1ldGVyZXMuXG5cdFx0Ly8gQHR5cGUge09iamVjdH1cblx0XHR0aGlzLl90cmFuc3BvcnRSZW1vdGVQYXJhbWV0ZXJzID0gbnVsbDtcblxuXHRcdC8vIFNEUCBnbG9iYWwgZmllbGRzLlxuXHRcdC8vIEB0eXBlIHtPYmplY3R9XG5cdFx0dGhpcy5fc2RwR2xvYmFsRmllbGRzID1cblx0XHR7XG5cdFx0XHRpZCAgICAgIDogdXRpbHMucmFuZG9tTnVtYmVyKCksXG5cdFx0XHR2ZXJzaW9uIDogMFxuXHRcdH07XG5cdH1cblxuXHRzZXRUcmFuc3BvcnRMb2NhbFBhcmFtZXRlcnModHJhbnNwb3J0TG9jYWxQYXJhbWV0ZXJzKVxuXHR7XG5cdFx0bG9nZ2VyLmRlYnVnKFxuXHRcdFx0J3NldFRyYW5zcG9ydExvY2FsUGFyYW1ldGVycygpIFt0cmFuc3BvcnRMb2NhbFBhcmFtZXRlcnM6JW9dJyxcblx0XHRcdHRyYW5zcG9ydExvY2FsUGFyYW1ldGVycyk7XG5cblx0XHR0aGlzLl90cmFuc3BvcnRMb2NhbFBhcmFtZXRlcnMgPSB0cmFuc3BvcnRMb2NhbFBhcmFtZXRlcnM7XG5cdH1cblxuXHRzZXRUcmFuc3BvcnRSZW1vdGVQYXJhbWV0ZXJzKHRyYW5zcG9ydFJlbW90ZVBhcmFtZXRlcnMpXG5cdHtcblx0XHRsb2dnZXIuZGVidWcoXG5cdFx0XHQnc2V0VHJhbnNwb3J0UmVtb3RlUGFyYW1ldGVycygpIFt0cmFuc3BvcnRSZW1vdGVQYXJhbWV0ZXJzOiVvXScsXG5cdFx0XHR0cmFuc3BvcnRSZW1vdGVQYXJhbWV0ZXJzKTtcblxuXHRcdHRoaXMuX3RyYW5zcG9ydFJlbW90ZVBhcmFtZXRlcnMgPSB0cmFuc3BvcnRSZW1vdGVQYXJhbWV0ZXJzO1xuXHR9XG59XG5cbmNsYXNzIFNlbmRSZW1vdGVTZHAgZXh0ZW5kcyBSZW1vdGVTZHBcbntcblx0Y29uc3RydWN0b3IocnRwUGFyYW1ldGVyc0J5S2luZClcblx0e1xuXHRcdHN1cGVyKHJ0cFBhcmFtZXRlcnNCeUtpbmQpO1xuXHR9XG5cblx0Y3JlYXRlQW5zd2VyU2RwKGxvY2FsU2RwT2JqKVxuXHR7XG5cdFx0bG9nZ2VyLmRlYnVnKCdjcmVhdGVBbnN3ZXJTZHAoKScpO1xuXG5cdFx0aWYgKCF0aGlzLl90cmFuc3BvcnRMb2NhbFBhcmFtZXRlcnMpXG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoJ25vIHRyYW5zcG9ydCBsb2NhbCBwYXJhbWV0ZXJzJyk7XG5cdFx0ZWxzZSBpZiAoIXRoaXMuX3RyYW5zcG9ydFJlbW90ZVBhcmFtZXRlcnMpXG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoJ25vIHRyYW5zcG9ydCByZW1vdGUgcGFyYW1ldGVycycpO1xuXG5cdFx0Y29uc3QgbG9jYWxEdGxzUGFyYW1ldGVycyA9IHRoaXMuX3RyYW5zcG9ydExvY2FsUGFyYW1ldGVycy5kdGxzUGFyYW1ldGVycztcblx0XHRjb25zdCByZW1vdGVJY2VQYXJhbWV0ZXJzID0gdGhpcy5fdHJhbnNwb3J0UmVtb3RlUGFyYW1ldGVycy5pY2VQYXJhbWV0ZXJzO1xuXHRcdGNvbnN0IHJlbW90ZUljZUNhbmRpZGF0ZXMgPSB0aGlzLl90cmFuc3BvcnRSZW1vdGVQYXJhbWV0ZXJzLmljZUNhbmRpZGF0ZXM7XG5cdFx0Y29uc3QgcmVtb3RlRHRsc1BhcmFtZXRlcnMgPSB0aGlzLl90cmFuc3BvcnRSZW1vdGVQYXJhbWV0ZXJzLmR0bHNQYXJhbWV0ZXJzO1xuXHRcdGNvbnN0IHNkcE9iaiA9IHt9O1xuXHRcdGNvbnN0IG1pZHMgPSAobG9jYWxTZHBPYmoubWVkaWEgfHwgW10pXG5cdFx0XHQubWFwKChtKSA9PiBtLm1pZCk7XG5cblx0XHQvLyBJbmNyZWFzZSBvdXIgU0RQIHZlcnNpb24uXG5cdFx0dGhpcy5fc2RwR2xvYmFsRmllbGRzLnZlcnNpb24rKztcblxuXHRcdHNkcE9iai52ZXJzaW9uID0gMDtcblx0XHRzZHBPYmoub3JpZ2luID1cblx0XHR7XG5cdFx0XHRhZGRyZXNzICAgICAgICA6ICcwLjAuMC4wJyxcblx0XHRcdGlwVmVyICAgICAgICAgIDogNCxcblx0XHRcdG5ldFR5cGUgICAgICAgIDogJ0lOJyxcblx0XHRcdHNlc3Npb25JZCAgICAgIDogdGhpcy5fc2RwR2xvYmFsRmllbGRzLmlkLFxuXHRcdFx0c2Vzc2lvblZlcnNpb24gOiB0aGlzLl9zZHBHbG9iYWxGaWVsZHMudmVyc2lvbixcblx0XHRcdHVzZXJuYW1lICAgICAgIDogJ21lZGlhc291cC1jbGllbnQnXG5cdFx0fTtcblx0XHRzZHBPYmoubmFtZSA9ICctJztcblx0XHRzZHBPYmoudGltaW5nID0geyBzdGFydDogMCwgc3RvcDogMCB9O1xuXHRcdHNkcE9iai5pY2VsaXRlID0gcmVtb3RlSWNlUGFyYW1ldGVycy5pY2VMaXRlID8gJ2ljZS1saXRlJyA6IG51bGw7XG5cdFx0c2RwT2JqLm1zaWRTZW1hbnRpYyA9XG5cdFx0e1xuXHRcdFx0c2VtYW50aWMgOiAnV01TJyxcblx0XHRcdHRva2VuICAgIDogJyonXG5cdFx0fTtcblx0XHRzZHBPYmouZ3JvdXBzID1cblx0XHRbXG5cdFx0XHR7XG5cdFx0XHRcdHR5cGUgOiAnQlVORExFJyxcblx0XHRcdFx0bWlkcyA6IG1pZHMuam9pbignICcpXG5cdFx0XHR9XG5cdFx0XTtcblx0XHRzZHBPYmoubWVkaWEgPSBbXTtcblxuXHRcdHNkcE9iai5maW5nZXJwcmludCA9XG5cdFx0e1xuXHRcdFx0dHlwZSA6IHJlbW90ZUR0bHNQYXJhbWV0ZXJzLmZpbmdlcnByaW50c1swXS5hbGdvcml0aG0sXG5cdFx0XHRoYXNoIDogcmVtb3RlRHRsc1BhcmFtZXRlcnMuZmluZ2VycHJpbnRzWzBdLnZhbHVlXG5cdFx0fTtcblxuXHRcdGZvciAoY29uc3QgbG9jYWxNZWRpYU9iaiBvZiBsb2NhbFNkcE9iai5tZWRpYSB8fCBbXSlcblx0XHR7XG5cdFx0XHRjb25zdCBraW5kID0gbG9jYWxNZWRpYU9iai50eXBlO1xuXHRcdFx0Y29uc3QgY29kZWNzID0gdGhpcy5fcnRwUGFyYW1ldGVyc0J5S2luZFtraW5kXS5jb2RlY3M7XG5cdFx0XHRjb25zdCBoZWFkZXJFeHRlbnNpb25zID0gdGhpcy5fcnRwUGFyYW1ldGVyc0J5S2luZFtraW5kXS5oZWFkZXJFeHRlbnNpb25zO1xuXHRcdFx0Y29uc3QgcmVtb3RlTWVkaWFPYmogPSB7fTtcblxuXHRcdFx0cmVtb3RlTWVkaWFPYmoudHlwZSA9IGxvY2FsTWVkaWFPYmoudHlwZTtcblx0XHRcdHJlbW90ZU1lZGlhT2JqLnBvcnQgPSA3O1xuXHRcdFx0cmVtb3RlTWVkaWFPYmoucHJvdG9jb2wgPSAnUlRQL1NBVlBGJztcblx0XHRcdHJlbW90ZU1lZGlhT2JqLmNvbm5lY3Rpb24gPSB7IGlwOiAnMTI3LjAuMC4xJywgdmVyc2lvbjogNCB9O1xuXHRcdFx0cmVtb3RlTWVkaWFPYmoubWlkID0gbG9jYWxNZWRpYU9iai5taWQ7XG5cblx0XHRcdHJlbW90ZU1lZGlhT2JqLmljZVVmcmFnID0gcmVtb3RlSWNlUGFyYW1ldGVycy51c2VybmFtZUZyYWdtZW50O1xuXHRcdFx0cmVtb3RlTWVkaWFPYmouaWNlUHdkID0gcmVtb3RlSWNlUGFyYW1ldGVycy5wYXNzd29yZDtcblx0XHRcdHJlbW90ZU1lZGlhT2JqLmNhbmRpZGF0ZXMgPSBbXTtcblxuXHRcdFx0Zm9yIChjb25zdCBjYW5kaWRhdGUgb2YgcmVtb3RlSWNlQ2FuZGlkYXRlcylcblx0XHRcdHtcblx0XHRcdFx0Y29uc3QgY2FuZGlkYXRlT2JqID0ge307XG5cblx0XHRcdFx0Ly8gbWVkaWFzb3VwIGRvZXMgbm90IHN1cHBvcnQgbm9uIHJ0Y3AtbXV4IHNvIGNhbmRpZGF0ZXMgY29tcG9uZW50IGlzXG5cdFx0XHRcdC8vIGFsd2F5cyBSVFAgKDEpLlxuXHRcdFx0XHRjYW5kaWRhdGVPYmouY29tcG9uZW50ID0gMTtcblx0XHRcdFx0Y2FuZGlkYXRlT2JqLmZvdW5kYXRpb24gPSBjYW5kaWRhdGUuZm91bmRhdGlvbjtcblx0XHRcdFx0Y2FuZGlkYXRlT2JqLmlwID0gY2FuZGlkYXRlLmlwO1xuXHRcdFx0XHRjYW5kaWRhdGVPYmoucG9ydCA9IGNhbmRpZGF0ZS5wb3J0O1xuXHRcdFx0XHRjYW5kaWRhdGVPYmoucHJpb3JpdHkgPSBjYW5kaWRhdGUucHJpb3JpdHk7XG5cdFx0XHRcdGNhbmRpZGF0ZU9iai50cmFuc3BvcnQgPSBjYW5kaWRhdGUucHJvdG9jb2w7XG5cdFx0XHRcdGNhbmRpZGF0ZU9iai50eXBlID0gY2FuZGlkYXRlLnR5cGU7XG5cdFx0XHRcdGlmIChjYW5kaWRhdGUudGNwVHlwZSlcblx0XHRcdFx0XHRjYW5kaWRhdGVPYmoudGNwdHlwZSA9IGNhbmRpZGF0ZS50Y3BUeXBlO1xuXG5cdFx0XHRcdHJlbW90ZU1lZGlhT2JqLmNhbmRpZGF0ZXMucHVzaChjYW5kaWRhdGVPYmopO1xuXHRcdFx0fVxuXG5cdFx0XHRyZW1vdGVNZWRpYU9iai5lbmRPZkNhbmRpZGF0ZXMgPSAnZW5kLW9mLWNhbmRpZGF0ZXMnO1xuXG5cdFx0XHQvLyBBbm5vdW5jZSBzdXBwb3J0IGZvciBJQ0UgcmVub21pbmF0aW9uLlxuXHRcdFx0Ly8gaHR0cHM6Ly90b29scy5pZXRmLm9yZy9odG1sL2RyYWZ0LXRoYXRjaGVyLWljZS1yZW5vbWluYXRpb25cblx0XHRcdHJlbW90ZU1lZGlhT2JqLmljZU9wdGlvbnMgPSAncmVub21pbmF0aW9uJztcblxuXHRcdFx0c3dpdGNoIChsb2NhbER0bHNQYXJhbWV0ZXJzLnJvbGUpXG5cdFx0XHR7XG5cdFx0XHRcdGNhc2UgJ2NsaWVudCc6XG5cdFx0XHRcdFx0cmVtb3RlTWVkaWFPYmouc2V0dXAgPSAnYWN0aXZlJztcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0Y2FzZSAnc2VydmVyJzpcblx0XHRcdFx0XHRyZW1vdGVNZWRpYU9iai5zZXR1cCA9ICdwYXNzaXZlJztcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdH1cblxuXHRcdFx0c3dpdGNoIChsb2NhbE1lZGlhT2JqLmRpcmVjdGlvbilcblx0XHRcdHtcblx0XHRcdFx0Y2FzZSAnc2VuZHJlY3YnOlxuXHRcdFx0XHRjYXNlICdzZW5kb25seSc6XG5cdFx0XHRcdFx0cmVtb3RlTWVkaWFPYmouZGlyZWN0aW9uID0gJ3JlY3Zvbmx5Jztcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0Y2FzZSAncmVjdm9ubHknOlxuXHRcdFx0XHRjYXNlICdpbmFjdGl2ZSc6XG5cdFx0XHRcdFx0cmVtb3RlTWVkaWFPYmouZGlyZWN0aW9uID0gJ2luYWN0aXZlJztcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdH1cblxuXHRcdFx0cmVtb3RlTWVkaWFPYmoucnRwID0gW107XG5cdFx0XHRyZW1vdGVNZWRpYU9iai5ydGNwRmIgPSBbXTtcblx0XHRcdHJlbW90ZU1lZGlhT2JqLmZtdHAgPSBbXTtcblxuXHRcdFx0Zm9yIChjb25zdCBjb2RlYyBvZiBjb2RlY3MpXG5cdFx0XHR7XG5cdFx0XHRcdGNvbnN0IHJ0cCA9XG5cdFx0XHRcdHtcblx0XHRcdFx0XHRwYXlsb2FkIDogY29kZWMucGF5bG9hZFR5cGUsXG5cdFx0XHRcdFx0Y29kZWMgICA6IGNvZGVjLm5hbWUsXG5cdFx0XHRcdFx0cmF0ZSAgICA6IGNvZGVjLmNsb2NrUmF0ZVxuXHRcdFx0XHR9O1xuXG5cdFx0XHRcdGlmIChjb2RlYy5jaGFubmVscyA+IDEpXG5cdFx0XHRcdFx0cnRwLmVuY29kaW5nID0gY29kZWMuY2hhbm5lbHM7XG5cblx0XHRcdFx0cmVtb3RlTWVkaWFPYmoucnRwLnB1c2gocnRwKTtcblxuXHRcdFx0XHRpZiAoY29kZWMucGFyYW1ldGVycylcblx0XHRcdFx0e1xuXHRcdFx0XHRcdGNvbnN0IHBhcmFtRm10cCA9XG5cdFx0XHRcdFx0e1xuXHRcdFx0XHRcdFx0cGF5bG9hZCA6IGNvZGVjLnBheWxvYWRUeXBlLFxuXHRcdFx0XHRcdFx0Y29uZmlnICA6ICcnXG5cdFx0XHRcdFx0fTtcblxuXHRcdFx0XHRcdGZvciAoY29uc3Qga2V5IG9mIE9iamVjdC5rZXlzKGNvZGVjLnBhcmFtZXRlcnMpKVxuXHRcdFx0XHRcdHtcblx0XHRcdFx0XHRcdGlmIChwYXJhbUZtdHAuY29uZmlnKVxuXHRcdFx0XHRcdFx0XHRwYXJhbUZtdHAuY29uZmlnICs9ICc7JztcblxuXHRcdFx0XHRcdFx0cGFyYW1GbXRwLmNvbmZpZyArPSBgJHtrZXl9PSR7Y29kZWMucGFyYW1ldGVyc1trZXldfWA7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0aWYgKHBhcmFtRm10cC5jb25maWcpXG5cdFx0XHRcdFx0XHRyZW1vdGVNZWRpYU9iai5mbXRwLnB1c2gocGFyYW1GbXRwKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGlmIChjb2RlYy5ydGNwRmVlZGJhY2spXG5cdFx0XHRcdHtcblx0XHRcdFx0XHRmb3IgKGNvbnN0IGZiIG9mIGNvZGVjLnJ0Y3BGZWVkYmFjaylcblx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRyZW1vdGVNZWRpYU9iai5ydGNwRmIucHVzaChcblx0XHRcdFx0XHRcdFx0e1xuXHRcdFx0XHRcdFx0XHRcdHBheWxvYWQgOiBjb2RlYy5wYXlsb2FkVHlwZSxcblx0XHRcdFx0XHRcdFx0XHR0eXBlICAgIDogZmIudHlwZSxcblx0XHRcdFx0XHRcdFx0XHRzdWJ0eXBlIDogZmIucGFyYW1ldGVyXG5cdFx0XHRcdFx0XHRcdH0pO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0XHRyZW1vdGVNZWRpYU9iai5wYXlsb2FkcyA9IGNvZGVjc1xuXHRcdFx0XHQubWFwKChjb2RlYykgPT4gY29kZWMucGF5bG9hZFR5cGUpXG5cdFx0XHRcdC5qb2luKCcgJyk7XG5cblx0XHRcdHJlbW90ZU1lZGlhT2JqLmV4dCA9IFtdO1xuXG5cdFx0XHRmb3IgKGNvbnN0IGV4dCBvZiBoZWFkZXJFeHRlbnNpb25zKVxuXHRcdFx0e1xuXHRcdFx0XHRyZW1vdGVNZWRpYU9iai5leHQucHVzaChcblx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHR1cmkgICA6IGV4dC51cmksXG5cdFx0XHRcdFx0XHR2YWx1ZSA6IGV4dC5pZFxuXHRcdFx0XHRcdH0pO1xuXHRcdFx0fVxuXG5cdFx0XHRyZW1vdGVNZWRpYU9iai5ydGNwTXV4ID0gJ3J0Y3AtbXV4Jztcblx0XHRcdHJlbW90ZU1lZGlhT2JqLnJ0Y3BSc2l6ZSA9ICdydGNwLXJzaXplJztcblxuXHRcdFx0Ly8gUHVzaCBpdC5cblx0XHRcdHNkcE9iai5tZWRpYS5wdXNoKHJlbW90ZU1lZGlhT2JqKTtcblx0XHR9XG5cblx0XHRjb25zdCBzZHAgPSBzZHBUcmFuc2Zvcm0ud3JpdGUoc2RwT2JqKTtcblxuXHRcdHJldHVybiBzZHA7XG5cdH1cbn1cblxuY2xhc3MgUmVjdlJlbW90ZVNkcCBleHRlbmRzIFJlbW90ZVNkcFxue1xuXHRjb25zdHJ1Y3RvcihydHBQYXJhbWV0ZXJzQnlLaW5kKVxuXHR7XG5cdFx0c3VwZXIocnRwUGFyYW1ldGVyc0J5S2luZCk7XG5cblx0XHQvLyBJZCBvZiB0aGUgdW5pcXVlIE1lZGlhU3RyZWFtIGZvciBhbGwgdGhlIHJlbW90ZSB0cmFja3MuXG5cdFx0dGhpcy5fc3RyZWFtSWQgPSBgcmVjdi1zdHJlYW0tJHt1dGlscy5yYW5kb21OdW1iZXIoKX1gO1xuXHR9XG5cblx0LyoqXG5cdCAqIEBwYXJhbSB7QXJyYXk8U3RyaW5nPn0ga2luZHMgLSBNZWRpYSBraW5kcy5cblx0ICogQHBhcmFtIHtBcnJheTxPYmplY3Q+fSBjb25zdW1lckluZm9zIC0gQ29uc3VtZXIgaW5mb3JtYXRpb25zLlxuXHQgKiBAcmV0dXJuIHtTdHJpbmd9XG5cdCAqL1xuXHRjcmVhdGVPZmZlclNkcChraW5kcywgY29uc3VtZXJJbmZvcylcblx0e1xuXHRcdGxvZ2dlci5kZWJ1ZygnY3JlYXRlT2ZmZXJTZHAoKScpO1xuXG5cdFx0aWYgKCF0aGlzLl90cmFuc3BvcnRSZW1vdGVQYXJhbWV0ZXJzKVxuXHRcdFx0dGhyb3cgbmV3IEVycm9yKCdubyB0cmFuc3BvcnQgcmVtb3RlIHBhcmFtZXRlcnMnKTtcblxuXHRcdGNvbnN0IHJlbW90ZUljZVBhcmFtZXRlcnMgPSB0aGlzLl90cmFuc3BvcnRSZW1vdGVQYXJhbWV0ZXJzLmljZVBhcmFtZXRlcnM7XG5cdFx0Y29uc3QgcmVtb3RlSWNlQ2FuZGlkYXRlcyA9IHRoaXMuX3RyYW5zcG9ydFJlbW90ZVBhcmFtZXRlcnMuaWNlQ2FuZGlkYXRlcztcblx0XHRjb25zdCByZW1vdGVEdGxzUGFyYW1ldGVycyA9IHRoaXMuX3RyYW5zcG9ydFJlbW90ZVBhcmFtZXRlcnMuZHRsc1BhcmFtZXRlcnM7XG5cdFx0Y29uc3Qgc2RwT2JqID0ge307XG5cdFx0Y29uc3QgbWlkcyA9IGtpbmRzO1xuXG5cdFx0Ly8gSW5jcmVhc2Ugb3VyIFNEUCB2ZXJzaW9uLlxuXHRcdHRoaXMuX3NkcEdsb2JhbEZpZWxkcy52ZXJzaW9uKys7XG5cblx0XHRzZHBPYmoudmVyc2lvbiA9IDA7XG5cdFx0c2RwT2JqLm9yaWdpbiA9XG5cdFx0e1xuXHRcdFx0YWRkcmVzcyAgICAgICAgOiAnMC4wLjAuMCcsXG5cdFx0XHRpcFZlciAgICAgICAgICA6IDQsXG5cdFx0XHRuZXRUeXBlICAgICAgICA6ICdJTicsXG5cdFx0XHRzZXNzaW9uSWQgICAgICA6IHRoaXMuX3NkcEdsb2JhbEZpZWxkcy5pZCxcblx0XHRcdHNlc3Npb25WZXJzaW9uIDogdGhpcy5fc2RwR2xvYmFsRmllbGRzLnZlcnNpb24sXG5cdFx0XHR1c2VybmFtZSAgICAgICA6ICdtZWRpYXNvdXAtY2xpZW50J1xuXHRcdH07XG5cdFx0c2RwT2JqLm5hbWUgPSAnLSc7XG5cdFx0c2RwT2JqLnRpbWluZyA9IHsgc3RhcnQ6IDAsIHN0b3A6IDAgfTtcblx0XHRzZHBPYmouaWNlbGl0ZSA9IHJlbW90ZUljZVBhcmFtZXRlcnMuaWNlTGl0ZSA/ICdpY2UtbGl0ZScgOiBudWxsO1xuXHRcdHNkcE9iai5tc2lkU2VtYW50aWMgPVxuXHRcdHtcblx0XHRcdHNlbWFudGljIDogJ1dNUycsXG5cdFx0XHR0b2tlbiAgICA6ICcqJ1xuXHRcdH07XG5cdFx0c2RwT2JqLmdyb3VwcyA9XG5cdFx0W1xuXHRcdFx0e1xuXHRcdFx0XHR0eXBlIDogJ0JVTkRMRScsXG5cdFx0XHRcdG1pZHMgOiBtaWRzLmpvaW4oJyAnKVxuXHRcdFx0fVxuXHRcdF07XG5cdFx0c2RwT2JqLm1lZGlhID0gW107XG5cblx0XHRzZHBPYmouZmluZ2VycHJpbnQgPVxuXHRcdHtcblx0XHRcdHR5cGUgOiByZW1vdGVEdGxzUGFyYW1ldGVycy5maW5nZXJwcmludHNbMF0uYWxnb3JpdGhtLFxuXHRcdFx0aGFzaCA6IHJlbW90ZUR0bHNQYXJhbWV0ZXJzLmZpbmdlcnByaW50c1swXS52YWx1ZVxuXHRcdH07XG5cblx0XHRmb3IgKGNvbnN0IGtpbmQgb2Yga2luZHMpXG5cdFx0e1xuXHRcdFx0Y29uc3QgY29kZWNzID0gdGhpcy5fcnRwUGFyYW1ldGVyc0J5S2luZFtraW5kXS5jb2RlY3M7XG5cdFx0XHRjb25zdCBoZWFkZXJFeHRlbnNpb25zID0gdGhpcy5fcnRwUGFyYW1ldGVyc0J5S2luZFtraW5kXS5oZWFkZXJFeHRlbnNpb25zO1xuXHRcdFx0Y29uc3QgcmVtb3RlTWVkaWFPYmogPSB7fTtcblxuXHRcdFx0cmVtb3RlTWVkaWFPYmoudHlwZSA9IGtpbmQ7XG5cdFx0XHRyZW1vdGVNZWRpYU9iai5wb3J0ID0gNztcblx0XHRcdHJlbW90ZU1lZGlhT2JqLnByb3RvY29sID0gJ1JUUC9TQVZQRic7XG5cdFx0XHRyZW1vdGVNZWRpYU9iai5jb25uZWN0aW9uID0geyBpcDogJzEyNy4wLjAuMScsIHZlcnNpb246IDQgfTtcblx0XHRcdHJlbW90ZU1lZGlhT2JqLm1pZCA9IGtpbmQ7XG5cblx0XHRcdHJlbW90ZU1lZGlhT2JqLmljZVVmcmFnID0gcmVtb3RlSWNlUGFyYW1ldGVycy51c2VybmFtZUZyYWdtZW50O1xuXHRcdFx0cmVtb3RlTWVkaWFPYmouaWNlUHdkID0gcmVtb3RlSWNlUGFyYW1ldGVycy5wYXNzd29yZDtcblx0XHRcdHJlbW90ZU1lZGlhT2JqLmNhbmRpZGF0ZXMgPSBbXTtcblxuXHRcdFx0Zm9yIChjb25zdCBjYW5kaWRhdGUgb2YgcmVtb3RlSWNlQ2FuZGlkYXRlcylcblx0XHRcdHtcblx0XHRcdFx0Y29uc3QgY2FuZGlkYXRlT2JqID0ge307XG5cblx0XHRcdFx0Ly8gbWVkaWFzb3VwIGRvZXMgbm90IHN1cHBvcnQgbm9uIHJ0Y3AtbXV4IHNvIGNhbmRpZGF0ZXMgY29tcG9uZW50IGlzXG5cdFx0XHRcdC8vIGFsd2F5cyBSVFAgKDEpLlxuXHRcdFx0XHRjYW5kaWRhdGVPYmouY29tcG9uZW50ID0gMTtcblx0XHRcdFx0Y2FuZGlkYXRlT2JqLmZvdW5kYXRpb24gPSBjYW5kaWRhdGUuZm91bmRhdGlvbjtcblx0XHRcdFx0Y2FuZGlkYXRlT2JqLmlwID0gY2FuZGlkYXRlLmlwO1xuXHRcdFx0XHRjYW5kaWRhdGVPYmoucG9ydCA9IGNhbmRpZGF0ZS5wb3J0O1xuXHRcdFx0XHRjYW5kaWRhdGVPYmoucHJpb3JpdHkgPSBjYW5kaWRhdGUucHJpb3JpdHk7XG5cdFx0XHRcdGNhbmRpZGF0ZU9iai50cmFuc3BvcnQgPSBjYW5kaWRhdGUucHJvdG9jb2w7XG5cdFx0XHRcdGNhbmRpZGF0ZU9iai50eXBlID0gY2FuZGlkYXRlLnR5cGU7XG5cdFx0XHRcdGlmIChjYW5kaWRhdGUudGNwVHlwZSlcblx0XHRcdFx0XHRjYW5kaWRhdGVPYmoudGNwdHlwZSA9IGNhbmRpZGF0ZS50Y3BUeXBlO1xuXG5cdFx0XHRcdHJlbW90ZU1lZGlhT2JqLmNhbmRpZGF0ZXMucHVzaChjYW5kaWRhdGVPYmopO1xuXHRcdFx0fVxuXG5cdFx0XHRyZW1vdGVNZWRpYU9iai5lbmRPZkNhbmRpZGF0ZXMgPSAnZW5kLW9mLWNhbmRpZGF0ZXMnO1xuXG5cdFx0XHQvLyBBbm5vdW5jZSBzdXBwb3J0IGZvciBJQ0UgcmVub21pbmF0aW9uLlxuXHRcdFx0Ly8gaHR0cHM6Ly90b29scy5pZXRmLm9yZy9odG1sL2RyYWZ0LXRoYXRjaGVyLWljZS1yZW5vbWluYXRpb25cblx0XHRcdHJlbW90ZU1lZGlhT2JqLmljZU9wdGlvbnMgPSAncmVub21pbmF0aW9uJztcblxuXHRcdFx0cmVtb3RlTWVkaWFPYmouc2V0dXAgPSAnYWN0cGFzcyc7XG5cblx0XHRcdGlmIChjb25zdW1lckluZm9zLnNvbWUoKGluZm8pID0+IGluZm8ua2luZCA9PT0ga2luZCkpXG5cdFx0XHRcdHJlbW90ZU1lZGlhT2JqLmRpcmVjdGlvbiA9ICdzZW5kb25seSc7XG5cdFx0XHRlbHNlXG5cdFx0XHRcdHJlbW90ZU1lZGlhT2JqLmRpcmVjdGlvbiA9ICdpbmFjdGl2ZSc7XG5cblx0XHRcdHJlbW90ZU1lZGlhT2JqLnJ0cCA9IFtdO1xuXHRcdFx0cmVtb3RlTWVkaWFPYmoucnRjcEZiID0gW107XG5cdFx0XHRyZW1vdGVNZWRpYU9iai5mbXRwID0gW107XG5cblx0XHRcdGZvciAoY29uc3QgY29kZWMgb2YgY29kZWNzKVxuXHRcdFx0e1xuXHRcdFx0XHRjb25zdCBydHAgPVxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0cGF5bG9hZCA6IGNvZGVjLnBheWxvYWRUeXBlLFxuXHRcdFx0XHRcdGNvZGVjICAgOiBjb2RlYy5uYW1lLFxuXHRcdFx0XHRcdHJhdGUgICAgOiBjb2RlYy5jbG9ja1JhdGVcblx0XHRcdFx0fTtcblxuXHRcdFx0XHRpZiAoY29kZWMuY2hhbm5lbHMgPiAxKVxuXHRcdFx0XHRcdHJ0cC5lbmNvZGluZyA9IGNvZGVjLmNoYW5uZWxzO1xuXG5cdFx0XHRcdHJlbW90ZU1lZGlhT2JqLnJ0cC5wdXNoKHJ0cCk7XG5cblx0XHRcdFx0aWYgKGNvZGVjLnBhcmFtZXRlcnMpXG5cdFx0XHRcdHtcblx0XHRcdFx0XHRjb25zdCBwYXJhbUZtdHAgPVxuXHRcdFx0XHRcdHtcblx0XHRcdFx0XHRcdHBheWxvYWQgOiBjb2RlYy5wYXlsb2FkVHlwZSxcblx0XHRcdFx0XHRcdGNvbmZpZyAgOiAnJ1xuXHRcdFx0XHRcdH07XG5cblx0XHRcdFx0XHRmb3IgKGNvbnN0IGtleSBvZiBPYmplY3Qua2V5cyhjb2RlYy5wYXJhbWV0ZXJzKSlcblx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRpZiAocGFyYW1GbXRwLmNvbmZpZylcblx0XHRcdFx0XHRcdFx0cGFyYW1GbXRwLmNvbmZpZyArPSAnOyc7XG5cblx0XHRcdFx0XHRcdHBhcmFtRm10cC5jb25maWcgKz0gYCR7a2V5fT0ke2NvZGVjLnBhcmFtZXRlcnNba2V5XX1gO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdGlmIChwYXJhbUZtdHAuY29uZmlnKVxuXHRcdFx0XHRcdFx0cmVtb3RlTWVkaWFPYmouZm10cC5wdXNoKHBhcmFtRm10cCk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRpZiAoY29kZWMucnRjcEZlZWRiYWNrKVxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0Zm9yIChjb25zdCBmYiBvZiBjb2RlYy5ydGNwRmVlZGJhY2spXG5cdFx0XHRcdFx0e1xuXHRcdFx0XHRcdFx0cmVtb3RlTWVkaWFPYmoucnRjcEZiLnB1c2goXG5cdFx0XHRcdFx0XHRcdHtcblx0XHRcdFx0XHRcdFx0XHRwYXlsb2FkIDogY29kZWMucGF5bG9hZFR5cGUsXG5cdFx0XHRcdFx0XHRcdFx0dHlwZSAgICA6IGZiLnR5cGUsXG5cdFx0XHRcdFx0XHRcdFx0c3VidHlwZSA6IGZiLnBhcmFtZXRlclxuXHRcdFx0XHRcdFx0XHR9KTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0cmVtb3RlTWVkaWFPYmoucGF5bG9hZHMgPSBjb2RlY3Ncblx0XHRcdFx0Lm1hcCgoY29kZWMpID0+IGNvZGVjLnBheWxvYWRUeXBlKVxuXHRcdFx0XHQuam9pbignICcpO1xuXG5cdFx0XHRyZW1vdGVNZWRpYU9iai5leHQgPSBbXTtcblxuXHRcdFx0Zm9yIChjb25zdCBleHQgb2YgaGVhZGVyRXh0ZW5zaW9ucylcblx0XHRcdHtcblx0XHRcdFx0cmVtb3RlTWVkaWFPYmouZXh0LnB1c2goXG5cdFx0XHRcdFx0e1xuXHRcdFx0XHRcdFx0dXJpICAgOiBleHQudXJpLFxuXHRcdFx0XHRcdFx0dmFsdWUgOiBleHQuaWRcblx0XHRcdFx0XHR9KTtcblx0XHRcdH1cblxuXHRcdFx0cmVtb3RlTWVkaWFPYmoucnRjcE11eCA9ICdydGNwLW11eCc7XG5cdFx0XHRyZW1vdGVNZWRpYU9iai5ydGNwUnNpemUgPSAncnRjcC1yc2l6ZSc7XG5cblx0XHRcdHJlbW90ZU1lZGlhT2JqLnNzcmNzID0gW107XG5cdFx0XHRyZW1vdGVNZWRpYU9iai5zc3JjR3JvdXBzID0gW107XG5cblx0XHRcdGZvciAoY29uc3QgaW5mbyBvZiBjb25zdW1lckluZm9zKVxuXHRcdFx0e1xuXHRcdFx0XHRpZiAoaW5mby5raW5kICE9PSBraW5kKVxuXHRcdFx0XHRcdGNvbnRpbnVlO1xuXG5cdFx0XHRcdHJlbW90ZU1lZGlhT2JqLnNzcmNzLnB1c2goXG5cdFx0XHRcdFx0e1xuXHRcdFx0XHRcdFx0aWQgICAgICAgIDogaW5mby5zc3JjLFxuXHRcdFx0XHRcdFx0YXR0cmlidXRlIDogJ21zaWQnLFxuXHRcdFx0XHRcdFx0dmFsdWUgICAgIDogYCR7dGhpcy5fc3RyZWFtSWR9ICR7aW5mby50cmFja0lkfWBcblx0XHRcdFx0XHR9KTtcblxuXHRcdFx0XHRyZW1vdGVNZWRpYU9iai5zc3Jjcy5wdXNoKFxuXHRcdFx0XHRcdHtcblx0XHRcdFx0XHRcdGlkICAgICAgICA6IGluZm8uc3NyYyxcblx0XHRcdFx0XHRcdGF0dHJpYnV0ZSA6ICdtc2xhYmVsJyxcblx0XHRcdFx0XHRcdHZhbHVlICAgICA6IHRoaXMuX3N0cmVhbUlkXG5cdFx0XHRcdFx0fSk7XG5cblx0XHRcdFx0cmVtb3RlTWVkaWFPYmouc3NyY3MucHVzaChcblx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRpZCAgICAgICAgOiBpbmZvLnNzcmMsXG5cdFx0XHRcdFx0XHRhdHRyaWJ1dGUgOiAnbGFiZWwnLFxuXHRcdFx0XHRcdFx0dmFsdWUgICAgIDogaW5mby50cmFja0lkXG5cdFx0XHRcdFx0fSk7XG5cblx0XHRcdFx0cmVtb3RlTWVkaWFPYmouc3NyY3MucHVzaChcblx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRpZCAgICAgICAgOiBpbmZvLnNzcmMsXG5cdFx0XHRcdFx0XHRhdHRyaWJ1dGUgOiAnY25hbWUnLFxuXHRcdFx0XHRcdFx0dmFsdWUgICAgIDogaW5mby5jbmFtZVxuXHRcdFx0XHRcdH0pO1xuXG5cdFx0XHRcdGlmIChpbmZvLnJ0eFNzcmMpXG5cdFx0XHRcdHtcblx0XHRcdFx0XHRyZW1vdGVNZWRpYU9iai5zc3Jjcy5wdXNoKFxuXHRcdFx0XHRcdFx0e1xuXHRcdFx0XHRcdFx0XHRpZCAgICAgICAgOiBpbmZvLnJ0eFNzcmMsXG5cdFx0XHRcdFx0XHRcdGF0dHJpYnV0ZSA6ICdtc2lkJyxcblx0XHRcdFx0XHRcdFx0dmFsdWUgICAgIDogYCR7dGhpcy5fc3RyZWFtSWR9ICR7aW5mby50cmFja0lkfWBcblx0XHRcdFx0XHRcdH0pO1xuXG5cdFx0XHRcdFx0cmVtb3RlTWVkaWFPYmouc3NyY3MucHVzaChcblx0XHRcdFx0XHRcdHtcblx0XHRcdFx0XHRcdFx0aWQgICAgICAgIDogaW5mby5ydHhTc3JjLFxuXHRcdFx0XHRcdFx0XHRhdHRyaWJ1dGUgOiAnbXNsYWJlbCcsXG5cdFx0XHRcdFx0XHRcdHZhbHVlICAgICA6IHRoaXMuX3N0cmVhbUlkXG5cdFx0XHRcdFx0XHR9KTtcblxuXHRcdFx0XHRcdHJlbW90ZU1lZGlhT2JqLnNzcmNzLnB1c2goXG5cdFx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRcdGlkICAgICAgICA6IGluZm8ucnR4U3NyYyxcblx0XHRcdFx0XHRcdFx0YXR0cmlidXRlIDogJ2xhYmVsJyxcblx0XHRcdFx0XHRcdFx0dmFsdWUgICAgIDogaW5mby50cmFja0lkXG5cdFx0XHRcdFx0XHR9KTtcblxuXHRcdFx0XHRcdHJlbW90ZU1lZGlhT2JqLnNzcmNzLnB1c2goXG5cdFx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRcdGlkICAgICAgICA6IGluZm8ucnR4U3NyYyxcblx0XHRcdFx0XHRcdFx0YXR0cmlidXRlIDogJ2NuYW1lJyxcblx0XHRcdFx0XHRcdFx0dmFsdWUgICAgIDogaW5mby5jbmFtZVxuXHRcdFx0XHRcdFx0fSk7XG5cblx0XHRcdFx0XHQvLyBBc3NvY2lhdGUgb3JpZ2luYWwgYW5kIHJldHJhbnNtaXNzaW9uIFNTUkMuXG5cdFx0XHRcdFx0cmVtb3RlTWVkaWFPYmouc3NyY0dyb3Vwcy5wdXNoKFxuXHRcdFx0XHRcdFx0e1xuXHRcdFx0XHRcdFx0XHRzZW1hbnRpY3MgOiAnRklEJyxcblx0XHRcdFx0XHRcdFx0c3NyY3MgICAgIDogYCR7aW5mby5zc3JjfSAke2luZm8ucnR4U3NyY31gXG5cdFx0XHRcdFx0XHR9KTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0XHQvLyBQdXNoIGl0LlxuXHRcdFx0c2RwT2JqLm1lZGlhLnB1c2gocmVtb3RlTWVkaWFPYmopO1xuXHRcdH1cblxuXHRcdGNvbnN0IHNkcCA9IHNkcFRyYW5zZm9ybS53cml0ZShzZHBPYmopO1xuXG5cdFx0cmV0dXJuIHNkcDtcblx0fVxufVxuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBSZW1vdGVQbGFuQlNkcFxue1xuXHRjb25zdHJ1Y3RvcihkaXJlY3Rpb24sIHJ0cFBhcmFtZXRlcnNCeUtpbmQpXG5cdHtcblx0XHRsb2dnZXIuZGVidWcoXG5cdFx0XHQnY29uc3RydWN0b3IoKSBbZGlyZWN0aW9uOiVzLCBydHBQYXJhbWV0ZXJzQnlLaW5kOiVvXScsXG5cdFx0XHRkaXJlY3Rpb24sIHJ0cFBhcmFtZXRlcnNCeUtpbmQpO1xuXG5cdFx0c3dpdGNoIChkaXJlY3Rpb24pXG5cdFx0e1xuXHRcdFx0Y2FzZSAnc2VuZCc6XG5cdFx0XHRcdHJldHVybiBuZXcgU2VuZFJlbW90ZVNkcChydHBQYXJhbWV0ZXJzQnlLaW5kKTtcblx0XHRcdGNhc2UgJ3JlY3YnOlxuXHRcdFx0XHRyZXR1cm4gbmV3IFJlY3ZSZW1vdGVTZHAocnRwUGFyYW1ldGVyc0J5S2luZCk7XG5cdFx0fVxuXHR9XG59XG4iLCJpbXBvcnQgc2RwVHJhbnNmb3JtIGZyb20gJ3NkcC10cmFuc2Zvcm0nO1xuaW1wb3J0IExvZ2dlciBmcm9tICcuLi8uLi9Mb2dnZXInO1xuaW1wb3J0ICogYXMgdXRpbHMgZnJvbSAnLi4vLi4vdXRpbHMnO1xuXG5jb25zdCBsb2dnZXIgPSBuZXcgTG9nZ2VyKCdSZW1vdGVVbmlmaWVkUGxhblNkcCcpO1xuXG5jbGFzcyBSZW1vdGVTZHBcbntcblx0Y29uc3RydWN0b3IocnRwUGFyYW1ldGVyc0J5S2luZClcblx0e1xuXHRcdC8vIEdlbmVyaWMgc2VuZGluZyBSVFAgcGFyYW1ldGVycyBmb3IgYXVkaW8gYW5kIHZpZGVvLlxuXHRcdC8vIEB0eXBlIHtPYmplY3R9XG5cdFx0dGhpcy5fcnRwUGFyYW1ldGVyc0J5S2luZCA9IHJ0cFBhcmFtZXRlcnNCeUtpbmQ7XG5cblx0XHQvLyBUcmFuc3BvcnQgbG9jYWwgcGFyYW1ldGVycywgaW5jbHVkaW5nIERUTFMgcGFyYW1ldGVyZXMuXG5cdFx0Ly8gQHR5cGUge09iamVjdH1cblx0XHR0aGlzLl90cmFuc3BvcnRMb2NhbFBhcmFtZXRlcnMgPSBudWxsO1xuXG5cdFx0Ly8gVHJhbnNwb3J0IHJlbW90ZSBwYXJhbWV0ZXJzLCBpbmNsdWRpbmcgSUNFIHBhcmFtZXRlcnMsIElDRSBjYW5kaWRhdGVzXG5cdFx0Ly8gYW5kIERUTFMgcGFyYW1ldGVyZXMuXG5cdFx0Ly8gQHR5cGUge09iamVjdH1cblx0XHR0aGlzLl90cmFuc3BvcnRSZW1vdGVQYXJhbWV0ZXJzID0gbnVsbDtcblxuXHRcdC8vIFNEUCBnbG9iYWwgZmllbGRzLlxuXHRcdC8vIEB0eXBlIHtPYmplY3R9XG5cdFx0dGhpcy5fc2RwR2xvYmFsRmllbGRzID1cblx0XHR7XG5cdFx0XHRpZCAgICAgIDogdXRpbHMucmFuZG9tTnVtYmVyKCksXG5cdFx0XHR2ZXJzaW9uIDogMFxuXHRcdH07XG5cdH1cblxuXHRzZXRUcmFuc3BvcnRMb2NhbFBhcmFtZXRlcnModHJhbnNwb3J0TG9jYWxQYXJhbWV0ZXJzKVxuXHR7XG5cdFx0bG9nZ2VyLmRlYnVnKFxuXHRcdFx0J3NldFRyYW5zcG9ydExvY2FsUGFyYW1ldGVycygpIFt0cmFuc3BvcnRMb2NhbFBhcmFtZXRlcnM6JW9dJyxcblx0XHRcdHRyYW5zcG9ydExvY2FsUGFyYW1ldGVycyk7XG5cblx0XHR0aGlzLl90cmFuc3BvcnRMb2NhbFBhcmFtZXRlcnMgPSB0cmFuc3BvcnRMb2NhbFBhcmFtZXRlcnM7XG5cdH1cblxuXHRzZXRUcmFuc3BvcnRSZW1vdGVQYXJhbWV0ZXJzKHRyYW5zcG9ydFJlbW90ZVBhcmFtZXRlcnMpXG5cdHtcblx0XHRsb2dnZXIuZGVidWcoXG5cdFx0XHQnc2V0VHJhbnNwb3J0UmVtb3RlUGFyYW1ldGVycygpIFt0cmFuc3BvcnRSZW1vdGVQYXJhbWV0ZXJzOiVvXScsXG5cdFx0XHR0cmFuc3BvcnRSZW1vdGVQYXJhbWV0ZXJzKTtcblxuXHRcdHRoaXMuX3RyYW5zcG9ydFJlbW90ZVBhcmFtZXRlcnMgPSB0cmFuc3BvcnRSZW1vdGVQYXJhbWV0ZXJzO1xuXHR9XG59XG5cbmNsYXNzIFNlbmRSZW1vdGVTZHAgZXh0ZW5kcyBSZW1vdGVTZHBcbntcblx0Y29uc3RydWN0b3IocnRwUGFyYW1ldGVyc0J5S2luZClcblx0e1xuXHRcdHN1cGVyKHJ0cFBhcmFtZXRlcnNCeUtpbmQpO1xuXHR9XG5cblx0Y3JlYXRlQW5zd2VyU2RwKGxvY2FsU2RwT2JqKVxuXHR7XG5cdFx0bG9nZ2VyLmRlYnVnKCdjcmVhdGVBbnN3ZXJTZHAoKScpO1xuXG5cdFx0aWYgKCF0aGlzLl90cmFuc3BvcnRMb2NhbFBhcmFtZXRlcnMpXG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoJ25vIHRyYW5zcG9ydCBsb2NhbCBwYXJhbWV0ZXJzJyk7XG5cdFx0ZWxzZSBpZiAoIXRoaXMuX3RyYW5zcG9ydFJlbW90ZVBhcmFtZXRlcnMpXG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoJ25vIHRyYW5zcG9ydCByZW1vdGUgcGFyYW1ldGVycycpO1xuXG5cdFx0Y29uc3QgbG9jYWxEdGxzUGFyYW1ldGVycyA9IHRoaXMuX3RyYW5zcG9ydExvY2FsUGFyYW1ldGVycy5kdGxzUGFyYW1ldGVycztcblx0XHRjb25zdCByZW1vdGVJY2VQYXJhbWV0ZXJzID0gdGhpcy5fdHJhbnNwb3J0UmVtb3RlUGFyYW1ldGVycy5pY2VQYXJhbWV0ZXJzO1xuXHRcdGNvbnN0IHJlbW90ZUljZUNhbmRpZGF0ZXMgPSB0aGlzLl90cmFuc3BvcnRSZW1vdGVQYXJhbWV0ZXJzLmljZUNhbmRpZGF0ZXM7XG5cdFx0Y29uc3QgcmVtb3RlRHRsc1BhcmFtZXRlcnMgPSB0aGlzLl90cmFuc3BvcnRSZW1vdGVQYXJhbWV0ZXJzLmR0bHNQYXJhbWV0ZXJzO1xuXHRcdGNvbnN0IHNkcE9iaiA9IHt9O1xuXHRcdGNvbnN0IG1pZHMgPSAobG9jYWxTZHBPYmoubWVkaWEgfHwgW10pXG5cdFx0XHQuZmlsdGVyKChtKSA9PiBtLm1pZClcblx0XHRcdC5tYXAoKG0pID0+IG0ubWlkKTtcblxuXHRcdC8vIEluY3JlYXNlIG91ciBTRFAgdmVyc2lvbi5cblx0XHR0aGlzLl9zZHBHbG9iYWxGaWVsZHMudmVyc2lvbisrO1xuXG5cdFx0c2RwT2JqLnZlcnNpb24gPSAwO1xuXHRcdHNkcE9iai5vcmlnaW4gPVxuXHRcdHtcblx0XHRcdGFkZHJlc3MgICAgICAgIDogJzAuMC4wLjAnLFxuXHRcdFx0aXBWZXIgICAgICAgICAgOiA0LFxuXHRcdFx0bmV0VHlwZSAgICAgICAgOiAnSU4nLFxuXHRcdFx0c2Vzc2lvbklkICAgICAgOiB0aGlzLl9zZHBHbG9iYWxGaWVsZHMuaWQsXG5cdFx0XHRzZXNzaW9uVmVyc2lvbiA6IHRoaXMuX3NkcEdsb2JhbEZpZWxkcy52ZXJzaW9uLFxuXHRcdFx0dXNlcm5hbWUgICAgICAgOiAnbWVkaWFzb3VwLWNsaWVudCdcblx0XHR9O1xuXHRcdHNkcE9iai5uYW1lID0gJy0nO1xuXHRcdHNkcE9iai50aW1pbmcgPSB7IHN0YXJ0OiAwLCBzdG9wOiAwIH07XG5cdFx0c2RwT2JqLmljZWxpdGUgPSByZW1vdGVJY2VQYXJhbWV0ZXJzLmljZUxpdGUgPyAnaWNlLWxpdGUnIDogbnVsbDtcblx0XHRzZHBPYmoubXNpZFNlbWFudGljID1cblx0XHR7XG5cdFx0XHRzZW1hbnRpYyA6ICdXTVMnLFxuXHRcdFx0dG9rZW4gICAgOiAnKidcblx0XHR9O1xuXG5cdFx0aWYgKG1pZHMubGVuZ3RoID4gMClcblx0XHR7XG5cdFx0XHRzZHBPYmouZ3JvdXBzID1cblx0XHRcdFtcblx0XHRcdFx0e1xuXHRcdFx0XHRcdHR5cGUgOiAnQlVORExFJyxcblx0XHRcdFx0XHRtaWRzIDogbWlkcy5qb2luKCcgJylcblx0XHRcdFx0fVxuXHRcdFx0XTtcblx0XHR9XG5cblx0XHRzZHBPYmoubWVkaWEgPSBbXTtcblxuXHRcdHNkcE9iai5maW5nZXJwcmludCA9XG5cdFx0e1xuXHRcdFx0dHlwZSA6IHJlbW90ZUR0bHNQYXJhbWV0ZXJzLmZpbmdlcnByaW50c1swXS5hbGdvcml0aG0sXG5cdFx0XHRoYXNoIDogcmVtb3RlRHRsc1BhcmFtZXRlcnMuZmluZ2VycHJpbnRzWzBdLnZhbHVlXG5cdFx0fTtcblxuXHRcdGZvciAoY29uc3QgbG9jYWxNZWRpYU9iaiBvZiBsb2NhbFNkcE9iai5tZWRpYSB8fCBbXSlcblx0XHR7XG5cdFx0XHRjb25zdCBjbG9zZWQgPSBsb2NhbE1lZGlhT2JqLmRpcmVjdGlvbiA9PT0gJ2luYWN0aXZlJztcblx0XHRcdGNvbnN0IGtpbmQgPSBsb2NhbE1lZGlhT2JqLnR5cGU7XG5cdFx0XHRjb25zdCBjb2RlY3MgPSB0aGlzLl9ydHBQYXJhbWV0ZXJzQnlLaW5kW2tpbmRdLmNvZGVjcztcblx0XHRcdGNvbnN0IGhlYWRlckV4dGVuc2lvbnMgPSB0aGlzLl9ydHBQYXJhbWV0ZXJzQnlLaW5kW2tpbmRdLmhlYWRlckV4dGVuc2lvbnM7XG5cdFx0XHRjb25zdCByZW1vdGVNZWRpYU9iaiA9IHt9O1xuXG5cdFx0XHRyZW1vdGVNZWRpYU9iai50eXBlID0gbG9jYWxNZWRpYU9iai50eXBlO1xuXHRcdFx0cmVtb3RlTWVkaWFPYmoucG9ydCA9IDc7XG5cdFx0XHRyZW1vdGVNZWRpYU9iai5wcm90b2NvbCA9ICdSVFAvU0FWUEYnO1xuXHRcdFx0cmVtb3RlTWVkaWFPYmouY29ubmVjdGlvbiA9IHsgaXA6ICcxMjcuMC4wLjEnLCB2ZXJzaW9uOiA0IH07XG5cdFx0XHRyZW1vdGVNZWRpYU9iai5taWQgPSBsb2NhbE1lZGlhT2JqLm1pZDtcblxuXHRcdFx0cmVtb3RlTWVkaWFPYmouaWNlVWZyYWcgPSByZW1vdGVJY2VQYXJhbWV0ZXJzLnVzZXJuYW1lRnJhZ21lbnQ7XG5cdFx0XHRyZW1vdGVNZWRpYU9iai5pY2VQd2QgPSByZW1vdGVJY2VQYXJhbWV0ZXJzLnBhc3N3b3JkO1xuXHRcdFx0cmVtb3RlTWVkaWFPYmouY2FuZGlkYXRlcyA9IFtdO1xuXG5cdFx0XHRmb3IgKGNvbnN0IGNhbmRpZGF0ZSBvZiByZW1vdGVJY2VDYW5kaWRhdGVzKVxuXHRcdFx0e1xuXHRcdFx0XHRjb25zdCBjYW5kaWRhdGVPYmogPSB7fTtcblxuXHRcdFx0XHQvLyBtZWRpYXNvdXAgZG9lcyBub3Qgc3VwcG9ydCBub24gcnRjcC1tdXggc28gY2FuZGlkYXRlcyBjb21wb25lbnQgaXNcblx0XHRcdFx0Ly8gYWx3YXlzIFJUUCAoMSkuXG5cdFx0XHRcdGNhbmRpZGF0ZU9iai5jb21wb25lbnQgPSAxO1xuXHRcdFx0XHRjYW5kaWRhdGVPYmouZm91bmRhdGlvbiA9IGNhbmRpZGF0ZS5mb3VuZGF0aW9uO1xuXHRcdFx0XHRjYW5kaWRhdGVPYmouaXAgPSBjYW5kaWRhdGUuaXA7XG5cdFx0XHRcdGNhbmRpZGF0ZU9iai5wb3J0ID0gY2FuZGlkYXRlLnBvcnQ7XG5cdFx0XHRcdGNhbmRpZGF0ZU9iai5wcmlvcml0eSA9IGNhbmRpZGF0ZS5wcmlvcml0eTtcblx0XHRcdFx0Y2FuZGlkYXRlT2JqLnRyYW5zcG9ydCA9IGNhbmRpZGF0ZS5wcm90b2NvbDtcblx0XHRcdFx0Y2FuZGlkYXRlT2JqLnR5cGUgPSBjYW5kaWRhdGUudHlwZTtcblx0XHRcdFx0aWYgKGNhbmRpZGF0ZS50Y3BUeXBlKVxuXHRcdFx0XHRcdGNhbmRpZGF0ZU9iai50Y3B0eXBlID0gY2FuZGlkYXRlLnRjcFR5cGU7XG5cblx0XHRcdFx0cmVtb3RlTWVkaWFPYmouY2FuZGlkYXRlcy5wdXNoKGNhbmRpZGF0ZU9iaik7XG5cdFx0XHR9XG5cblx0XHRcdHJlbW90ZU1lZGlhT2JqLmVuZE9mQ2FuZGlkYXRlcyA9ICdlbmQtb2YtY2FuZGlkYXRlcyc7XG5cblx0XHRcdC8vIEFubm91bmNlIHN1cHBvcnQgZm9yIElDRSByZW5vbWluYXRpb24uXG5cdFx0XHQvLyBodHRwczovL3Rvb2xzLmlldGYub3JnL2h0bWwvZHJhZnQtdGhhdGNoZXItaWNlLXJlbm9taW5hdGlvblxuXHRcdFx0cmVtb3RlTWVkaWFPYmouaWNlT3B0aW9ucyA9ICdyZW5vbWluYXRpb24nO1xuXG5cdFx0XHRzd2l0Y2ggKGxvY2FsRHRsc1BhcmFtZXRlcnMucm9sZSlcblx0XHRcdHtcblx0XHRcdFx0Y2FzZSAnY2xpZW50Jzpcblx0XHRcdFx0XHRyZW1vdGVNZWRpYU9iai5zZXR1cCA9ICdhY3RpdmUnO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRjYXNlICdzZXJ2ZXInOlxuXHRcdFx0XHRcdHJlbW90ZU1lZGlhT2JqLnNldHVwID0gJ3Bhc3NpdmUnO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0fVxuXG5cdFx0XHRzd2l0Y2ggKGxvY2FsTWVkaWFPYmouZGlyZWN0aW9uKVxuXHRcdFx0e1xuXHRcdFx0XHRjYXNlICdzZW5kcmVjdic6XG5cdFx0XHRcdGNhc2UgJ3NlbmRvbmx5Jzpcblx0XHRcdFx0XHRyZW1vdGVNZWRpYU9iai5kaXJlY3Rpb24gPSAncmVjdm9ubHknO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRjYXNlICdyZWN2b25seSc6XG5cdFx0XHRcdGNhc2UgJ2luYWN0aXZlJzpcblx0XHRcdFx0XHRyZW1vdGVNZWRpYU9iai5kaXJlY3Rpb24gPSAnaW5hY3RpdmUnO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0fVxuXG5cdFx0XHRyZW1vdGVNZWRpYU9iai5ydHAgPSBbXTtcblx0XHRcdHJlbW90ZU1lZGlhT2JqLnJ0Y3BGYiA9IFtdO1xuXHRcdFx0cmVtb3RlTWVkaWFPYmouZm10cCA9IFtdO1xuXG5cdFx0XHRmb3IgKGNvbnN0IGNvZGVjIG9mIGNvZGVjcylcblx0XHRcdHtcblx0XHRcdFx0Y29uc3QgcnRwID1cblx0XHRcdFx0e1xuXHRcdFx0XHRcdHBheWxvYWQgOiBjb2RlYy5wYXlsb2FkVHlwZSxcblx0XHRcdFx0XHRjb2RlYyAgIDogY29kZWMubmFtZSxcblx0XHRcdFx0XHRyYXRlICAgIDogY29kZWMuY2xvY2tSYXRlXG5cdFx0XHRcdH07XG5cblx0XHRcdFx0aWYgKGNvZGVjLmNoYW5uZWxzID4gMSlcblx0XHRcdFx0XHRydHAuZW5jb2RpbmcgPSBjb2RlYy5jaGFubmVscztcblxuXHRcdFx0XHRyZW1vdGVNZWRpYU9iai5ydHAucHVzaChydHApO1xuXG5cdFx0XHRcdGlmIChjb2RlYy5wYXJhbWV0ZXJzKVxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0Y29uc3QgcGFyYW1GbXRwID1cblx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRwYXlsb2FkIDogY29kZWMucGF5bG9hZFR5cGUsXG5cdFx0XHRcdFx0XHRjb25maWcgIDogJydcblx0XHRcdFx0XHR9O1xuXG5cdFx0XHRcdFx0Zm9yIChjb25zdCBrZXkgb2YgT2JqZWN0LmtleXMoY29kZWMucGFyYW1ldGVycykpXG5cdFx0XHRcdFx0e1xuXHRcdFx0XHRcdFx0aWYgKHBhcmFtRm10cC5jb25maWcpXG5cdFx0XHRcdFx0XHRcdHBhcmFtRm10cC5jb25maWcgKz0gJzsnO1xuXG5cdFx0XHRcdFx0XHRwYXJhbUZtdHAuY29uZmlnICs9IGAke2tleX09JHtjb2RlYy5wYXJhbWV0ZXJzW2tleV19YDtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRpZiAocGFyYW1GbXRwLmNvbmZpZylcblx0XHRcdFx0XHRcdHJlbW90ZU1lZGlhT2JqLmZtdHAucHVzaChwYXJhbUZtdHApO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0aWYgKGNvZGVjLnJ0Y3BGZWVkYmFjaylcblx0XHRcdFx0e1xuXHRcdFx0XHRcdGZvciAoY29uc3QgZmIgb2YgY29kZWMucnRjcEZlZWRiYWNrKVxuXHRcdFx0XHRcdHtcblx0XHRcdFx0XHRcdHJlbW90ZU1lZGlhT2JqLnJ0Y3BGYi5wdXNoKFxuXHRcdFx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRcdFx0cGF5bG9hZCA6IGNvZGVjLnBheWxvYWRUeXBlLFxuXHRcdFx0XHRcdFx0XHRcdHR5cGUgICAgOiBmYi50eXBlLFxuXHRcdFx0XHRcdFx0XHRcdHN1YnR5cGUgOiBmYi5wYXJhbWV0ZXJcblx0XHRcdFx0XHRcdFx0fSk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdHJlbW90ZU1lZGlhT2JqLnBheWxvYWRzID0gY29kZWNzXG5cdFx0XHRcdC5tYXAoKGNvZGVjKSA9PiBjb2RlYy5wYXlsb2FkVHlwZSlcblx0XHRcdFx0LmpvaW4oJyAnKTtcblxuXHRcdFx0Ly8gTk9URTogRmlyZWZveCBkb2VzIG5vdCBsaWtlIGE9ZXh0bWFwIGxpbmVzIGlmIGE9aW5hY3RpdmUuXG5cdFx0XHRpZiAoIWNsb3NlZClcblx0XHRcdHtcblx0XHRcdFx0cmVtb3RlTWVkaWFPYmouZXh0ID0gW107XG5cblx0XHRcdFx0Zm9yIChjb25zdCBleHQgb2YgaGVhZGVyRXh0ZW5zaW9ucylcblx0XHRcdFx0e1xuXHRcdFx0XHRcdHJlbW90ZU1lZGlhT2JqLmV4dC5wdXNoKFxuXHRcdFx0XHRcdFx0e1xuXHRcdFx0XHRcdFx0XHR1cmkgICA6IGV4dC51cmksXG5cdFx0XHRcdFx0XHRcdHZhbHVlIDogZXh0LmlkXG5cdFx0XHRcdFx0XHR9KTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0XHRyZW1vdGVNZWRpYU9iai5ydGNwTXV4ID0gJ3J0Y3AtbXV4Jztcblx0XHRcdHJlbW90ZU1lZGlhT2JqLnJ0Y3BSc2l6ZSA9ICdydGNwLXJzaXplJztcblxuXHRcdFx0Ly8gUHVzaCBpdC5cblx0XHRcdHNkcE9iai5tZWRpYS5wdXNoKHJlbW90ZU1lZGlhT2JqKTtcblx0XHR9XG5cblx0XHRjb25zdCBzZHAgPSBzZHBUcmFuc2Zvcm0ud3JpdGUoc2RwT2JqKTtcblxuXHRcdHJldHVybiBzZHA7XG5cdH1cbn1cblxuY2xhc3MgUmVjdlJlbW90ZVNkcCBleHRlbmRzIFJlbW90ZVNkcFxue1xuXHRjb25zdHJ1Y3RvcihydHBQYXJhbWV0ZXJzQnlLaW5kKVxuXHR7XG5cdFx0c3VwZXIocnRwUGFyYW1ldGVyc0J5S2luZCk7XG5cblx0XHQvLyBJZCBvZiB0aGUgdW5pcXVlIE1lZGlhU3RyZWFtIGZvciBhbGwgdGhlIHJlbW90ZSB0cmFja3MuXG5cdFx0dGhpcy5fc3RyZWFtSWQgPSBgcmVjdi1zdHJlYW0tJHt1dGlscy5yYW5kb21OdW1iZXIoKX1gO1xuXHR9XG5cblx0LyoqXG5cdCAqIEBwYXJhbSB7QXJyYXk8T2JqZWN0Pn0gY29uc3VtZXJJbmZvcyAtIENvbnN1bWVyIGluZm9ybWF0aW9ucy5cblx0ICogQHJldHVybiB7U3RyaW5nfVxuXHQgKi9cblx0Y3JlYXRlT2ZmZXJTZHAoY29uc3VtZXJJbmZvcylcblx0e1xuXHRcdGxvZ2dlci5kZWJ1ZygnY3JlYXRlT2ZmZXJTZHAoKScpO1xuXG5cdFx0aWYgKCF0aGlzLl90cmFuc3BvcnRSZW1vdGVQYXJhbWV0ZXJzKVxuXHRcdFx0dGhyb3cgbmV3IEVycm9yKCdubyB0cmFuc3BvcnQgcmVtb3RlIHBhcmFtZXRlcnMnKTtcblxuXHRcdGNvbnN0IHJlbW90ZUljZVBhcmFtZXRlcnMgPSB0aGlzLl90cmFuc3BvcnRSZW1vdGVQYXJhbWV0ZXJzLmljZVBhcmFtZXRlcnM7XG5cdFx0Y29uc3QgcmVtb3RlSWNlQ2FuZGlkYXRlcyA9IHRoaXMuX3RyYW5zcG9ydFJlbW90ZVBhcmFtZXRlcnMuaWNlQ2FuZGlkYXRlcztcblx0XHRjb25zdCByZW1vdGVEdGxzUGFyYW1ldGVycyA9IHRoaXMuX3RyYW5zcG9ydFJlbW90ZVBhcmFtZXRlcnMuZHRsc1BhcmFtZXRlcnM7XG5cdFx0Y29uc3Qgc2RwT2JqID0ge307XG5cdFx0Y29uc3QgbWlkcyA9IGNvbnN1bWVySW5mb3Ncblx0XHRcdC5maWx0ZXIoKGluZm8pID0+ICFpbmZvLmNsb3NlZClcblx0XHRcdC5tYXAoKGluZm8pID0+IGluZm8ubWlkKTtcblxuXHRcdC8vIEluY3JlYXNlIG91ciBTRFAgdmVyc2lvbi5cblx0XHR0aGlzLl9zZHBHbG9iYWxGaWVsZHMudmVyc2lvbisrO1xuXG5cdFx0c2RwT2JqLnZlcnNpb24gPSAwO1xuXHRcdHNkcE9iai5vcmlnaW4gPVxuXHRcdHtcblx0XHRcdGFkZHJlc3MgICAgICAgIDogJzAuMC4wLjAnLFxuXHRcdFx0aXBWZXIgICAgICAgICAgOiA0LFxuXHRcdFx0bmV0VHlwZSAgICAgICAgOiAnSU4nLFxuXHRcdFx0c2Vzc2lvbklkICAgICAgOiB0aGlzLl9zZHBHbG9iYWxGaWVsZHMuaWQsXG5cdFx0XHRzZXNzaW9uVmVyc2lvbiA6IHRoaXMuX3NkcEdsb2JhbEZpZWxkcy52ZXJzaW9uLFxuXHRcdFx0dXNlcm5hbWUgICAgICAgOiAnbWVkaWFzb3VwLWNsaWVudCdcblx0XHR9O1xuXHRcdHNkcE9iai5uYW1lID0gJy0nO1xuXHRcdHNkcE9iai50aW1pbmcgPSB7IHN0YXJ0OiAwLCBzdG9wOiAwIH07XG5cdFx0c2RwT2JqLmljZWxpdGUgPSByZW1vdGVJY2VQYXJhbWV0ZXJzLmljZUxpdGUgPyAnaWNlLWxpdGUnIDogbnVsbDtcblx0XHRzZHBPYmoubXNpZFNlbWFudGljID1cblx0XHR7XG5cdFx0XHRzZW1hbnRpYyA6ICdXTVMnLFxuXHRcdFx0dG9rZW4gICAgOiAnKidcblx0XHR9O1xuXG5cdFx0aWYgKG1pZHMubGVuZ3RoID4gMClcblx0XHR7XG5cdFx0XHRzZHBPYmouZ3JvdXBzID1cblx0XHRcdFtcblx0XHRcdFx0e1xuXHRcdFx0XHRcdHR5cGUgOiAnQlVORExFJyxcblx0XHRcdFx0XHRtaWRzIDogbWlkcy5qb2luKCcgJylcblx0XHRcdFx0fVxuXHRcdFx0XTtcblx0XHR9XG5cblx0XHRzZHBPYmoubWVkaWEgPSBbXTtcblxuXHRcdHNkcE9iai5maW5nZXJwcmludCA9XG5cdFx0e1xuXHRcdFx0dHlwZSA6IHJlbW90ZUR0bHNQYXJhbWV0ZXJzLmZpbmdlcnByaW50c1swXS5hbGdvcml0aG0sXG5cdFx0XHRoYXNoIDogcmVtb3RlRHRsc1BhcmFtZXRlcnMuZmluZ2VycHJpbnRzWzBdLnZhbHVlXG5cdFx0fTtcblxuXHRcdGZvciAoY29uc3QgaW5mbyBvZiBjb25zdW1lckluZm9zKVxuXHRcdHtcblx0XHRcdGNvbnN0IGNsb3NlZCA9IGluZm8uY2xvc2VkO1xuXHRcdFx0Y29uc3Qga2luZCA9IGluZm8ua2luZDtcblx0XHRcdGNvbnN0IGNvZGVjcyA9IHRoaXMuX3J0cFBhcmFtZXRlcnNCeUtpbmRba2luZF0uY29kZWNzO1xuXHRcdFx0Y29uc3QgaGVhZGVyRXh0ZW5zaW9ucyA9IHRoaXMuX3J0cFBhcmFtZXRlcnNCeUtpbmRba2luZF0uaGVhZGVyRXh0ZW5zaW9ucztcblx0XHRcdGNvbnN0IHJlbW90ZU1lZGlhT2JqID0ge307XG5cblx0XHRcdHJlbW90ZU1lZGlhT2JqLnR5cGUgPSBraW5kO1xuXHRcdFx0cmVtb3RlTWVkaWFPYmoucG9ydCA9IDc7XG5cdFx0XHRyZW1vdGVNZWRpYU9iai5wcm90b2NvbCA9ICdSVFAvU0FWUEYnO1xuXHRcdFx0cmVtb3RlTWVkaWFPYmouY29ubmVjdGlvbiA9IHsgaXA6ICcxMjcuMC4wLjEnLCB2ZXJzaW9uOiA0IH07XG5cdFx0XHRyZW1vdGVNZWRpYU9iai5taWQgPSBpbmZvLm1pZDtcblx0XHRcdHJlbW90ZU1lZGlhT2JqLm1zaWQgPSBgJHt0aGlzLl9zdHJlYW1JZH0gJHtpbmZvLnRyYWNrSWR9YDtcblxuXHRcdFx0cmVtb3RlTWVkaWFPYmouaWNlVWZyYWcgPSByZW1vdGVJY2VQYXJhbWV0ZXJzLnVzZXJuYW1lRnJhZ21lbnQ7XG5cdFx0XHRyZW1vdGVNZWRpYU9iai5pY2VQd2QgPSByZW1vdGVJY2VQYXJhbWV0ZXJzLnBhc3N3b3JkO1xuXHRcdFx0cmVtb3RlTWVkaWFPYmouY2FuZGlkYXRlcyA9IFtdO1xuXG5cdFx0XHRmb3IgKGNvbnN0IGNhbmRpZGF0ZSBvZiByZW1vdGVJY2VDYW5kaWRhdGVzKVxuXHRcdFx0e1xuXHRcdFx0XHRjb25zdCBjYW5kaWRhdGVPYmogPSB7fTtcblxuXHRcdFx0XHQvLyBtZWRpYXNvdXAgZG9lcyBub3Qgc3VwcG9ydCBub24gcnRjcC1tdXggc28gY2FuZGlkYXRlcyBjb21wb25lbnQgaXNcblx0XHRcdFx0Ly8gYWx3YXlzIFJUUCAoMSkuXG5cdFx0XHRcdGNhbmRpZGF0ZU9iai5jb21wb25lbnQgPSAxO1xuXHRcdFx0XHRjYW5kaWRhdGVPYmouZm91bmRhdGlvbiA9IGNhbmRpZGF0ZS5mb3VuZGF0aW9uO1xuXHRcdFx0XHRjYW5kaWRhdGVPYmouaXAgPSBjYW5kaWRhdGUuaXA7XG5cdFx0XHRcdGNhbmRpZGF0ZU9iai5wb3J0ID0gY2FuZGlkYXRlLnBvcnQ7XG5cdFx0XHRcdGNhbmRpZGF0ZU9iai5wcmlvcml0eSA9IGNhbmRpZGF0ZS5wcmlvcml0eTtcblx0XHRcdFx0Y2FuZGlkYXRlT2JqLnRyYW5zcG9ydCA9IGNhbmRpZGF0ZS5wcm90b2NvbDtcblx0XHRcdFx0Y2FuZGlkYXRlT2JqLnR5cGUgPSBjYW5kaWRhdGUudHlwZTtcblx0XHRcdFx0aWYgKGNhbmRpZGF0ZS50Y3BUeXBlKVxuXHRcdFx0XHRcdGNhbmRpZGF0ZU9iai50Y3B0eXBlID0gY2FuZGlkYXRlLnRjcFR5cGU7XG5cblx0XHRcdFx0cmVtb3RlTWVkaWFPYmouY2FuZGlkYXRlcy5wdXNoKGNhbmRpZGF0ZU9iaik7XG5cdFx0XHR9XG5cblx0XHRcdHJlbW90ZU1lZGlhT2JqLmVuZE9mQ2FuZGlkYXRlcyA9ICdlbmQtb2YtY2FuZGlkYXRlcyc7XG5cblx0XHRcdC8vIEFubm91bmNlIHN1cHBvcnQgZm9yIElDRSByZW5vbWluYXRpb24uXG5cdFx0XHQvLyBodHRwczovL3Rvb2xzLmlldGYub3JnL2h0bWwvZHJhZnQtdGhhdGNoZXItaWNlLXJlbm9taW5hdGlvblxuXHRcdFx0cmVtb3RlTWVkaWFPYmouaWNlT3B0aW9ucyA9ICdyZW5vbWluYXRpb24nO1xuXG5cdFx0XHRyZW1vdGVNZWRpYU9iai5zZXR1cCA9ICdhY3RwYXNzJztcblxuXHRcdFx0aWYgKCFjbG9zZWQpXG5cdFx0XHRcdHJlbW90ZU1lZGlhT2JqLmRpcmVjdGlvbiA9ICdzZW5kb25seSc7XG5cdFx0XHRlbHNlXG5cdFx0XHRcdHJlbW90ZU1lZGlhT2JqLmRpcmVjdGlvbiA9ICdpbmFjdGl2ZSc7XG5cblx0XHRcdHJlbW90ZU1lZGlhT2JqLnJ0cCA9IFtdO1xuXHRcdFx0cmVtb3RlTWVkaWFPYmoucnRjcEZiID0gW107XG5cdFx0XHRyZW1vdGVNZWRpYU9iai5mbXRwID0gW107XG5cblx0XHRcdGZvciAoY29uc3QgY29kZWMgb2YgY29kZWNzKVxuXHRcdFx0e1xuXHRcdFx0XHRjb25zdCBydHAgPVxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0cGF5bG9hZCA6IGNvZGVjLnBheWxvYWRUeXBlLFxuXHRcdFx0XHRcdGNvZGVjICAgOiBjb2RlYy5uYW1lLFxuXHRcdFx0XHRcdHJhdGUgICAgOiBjb2RlYy5jbG9ja1JhdGVcblx0XHRcdFx0fTtcblxuXHRcdFx0XHRpZiAoY29kZWMuY2hhbm5lbHMgPiAxKVxuXHRcdFx0XHRcdHJ0cC5lbmNvZGluZyA9IGNvZGVjLmNoYW5uZWxzO1xuXG5cdFx0XHRcdHJlbW90ZU1lZGlhT2JqLnJ0cC5wdXNoKHJ0cCk7XG5cblx0XHRcdFx0aWYgKGNvZGVjLnBhcmFtZXRlcnMpXG5cdFx0XHRcdHtcblx0XHRcdFx0XHRjb25zdCBwYXJhbUZtdHAgPVxuXHRcdFx0XHRcdHtcblx0XHRcdFx0XHRcdHBheWxvYWQgOiBjb2RlYy5wYXlsb2FkVHlwZSxcblx0XHRcdFx0XHRcdGNvbmZpZyAgOiAnJ1xuXHRcdFx0XHRcdH07XG5cblx0XHRcdFx0XHRmb3IgKGNvbnN0IGtleSBvZiBPYmplY3Qua2V5cyhjb2RlYy5wYXJhbWV0ZXJzKSlcblx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRpZiAocGFyYW1GbXRwLmNvbmZpZylcblx0XHRcdFx0XHRcdFx0cGFyYW1GbXRwLmNvbmZpZyArPSAnOyc7XG5cblx0XHRcdFx0XHRcdHBhcmFtRm10cC5jb25maWcgKz0gYCR7a2V5fT0ke2NvZGVjLnBhcmFtZXRlcnNba2V5XX1gO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdGlmIChwYXJhbUZtdHAuY29uZmlnKVxuXHRcdFx0XHRcdFx0cmVtb3RlTWVkaWFPYmouZm10cC5wdXNoKHBhcmFtRm10cCk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRpZiAoY29kZWMucnRjcEZlZWRiYWNrKVxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0Zm9yIChjb25zdCBmYiBvZiBjb2RlYy5ydGNwRmVlZGJhY2spXG5cdFx0XHRcdFx0e1xuXHRcdFx0XHRcdFx0cmVtb3RlTWVkaWFPYmoucnRjcEZiLnB1c2goXG5cdFx0XHRcdFx0XHRcdHtcblx0XHRcdFx0XHRcdFx0XHRwYXlsb2FkIDogY29kZWMucGF5bG9hZFR5cGUsXG5cdFx0XHRcdFx0XHRcdFx0dHlwZSAgICA6IGZiLnR5cGUsXG5cdFx0XHRcdFx0XHRcdFx0c3VidHlwZSA6IGZiLnBhcmFtZXRlclxuXHRcdFx0XHRcdFx0XHR9KTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0cmVtb3RlTWVkaWFPYmoucGF5bG9hZHMgPSBjb2RlY3Ncblx0XHRcdFx0Lm1hcCgoY29kZWMpID0+IGNvZGVjLnBheWxvYWRUeXBlKVxuXHRcdFx0XHQuam9pbignICcpO1xuXG5cdFx0XHQvLyBOT1RFOiBGaXJlZm94IGRvZXMgbm90IGxpa2UgYT1leHRtYXAgbGluZXMgaWYgYT1pbmFjdGl2ZS5cblx0XHRcdGlmICghY2xvc2VkKVxuXHRcdFx0e1xuXHRcdFx0XHRyZW1vdGVNZWRpYU9iai5leHQgPSBbXTtcblxuXHRcdFx0XHRmb3IgKGNvbnN0IGV4dCBvZiBoZWFkZXJFeHRlbnNpb25zKVxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0cmVtb3RlTWVkaWFPYmouZXh0LnB1c2goXG5cdFx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRcdHVyaSAgIDogZXh0LnVyaSxcblx0XHRcdFx0XHRcdFx0dmFsdWUgOiBleHQuaWRcblx0XHRcdFx0XHRcdH0pO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdHJlbW90ZU1lZGlhT2JqLnJ0Y3BNdXggPSAncnRjcC1tdXgnO1xuXHRcdFx0cmVtb3RlTWVkaWFPYmoucnRjcFJzaXplID0gJ3J0Y3AtcnNpemUnO1xuXG5cdFx0XHRpZiAoIWNsb3NlZClcblx0XHRcdHtcblx0XHRcdFx0cmVtb3RlTWVkaWFPYmouc3NyY3MgPSBbXTtcblx0XHRcdFx0cmVtb3RlTWVkaWFPYmouc3NyY0dyb3VwcyA9IFtdO1xuXG5cdFx0XHRcdHJlbW90ZU1lZGlhT2JqLnNzcmNzLnB1c2goXG5cdFx0XHRcdFx0e1xuXHRcdFx0XHRcdFx0aWQgICAgICAgIDogaW5mby5zc3JjLFxuXHRcdFx0XHRcdFx0YXR0cmlidXRlIDogJ2NuYW1lJyxcblx0XHRcdFx0XHRcdHZhbHVlICAgICA6IGluZm8uY25hbWVcblx0XHRcdFx0XHR9KTtcblxuXHRcdFx0XHRpZiAoaW5mby5ydHhTc3JjKVxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0cmVtb3RlTWVkaWFPYmouc3NyY3MucHVzaChcblx0XHRcdFx0XHRcdHtcblx0XHRcdFx0XHRcdFx0aWQgICAgICAgIDogaW5mby5ydHhTc3JjLFxuXHRcdFx0XHRcdFx0XHRhdHRyaWJ1dGUgOiAnY25hbWUnLFxuXHRcdFx0XHRcdFx0XHR2YWx1ZSAgICAgOiBpbmZvLmNuYW1lXG5cdFx0XHRcdFx0XHR9KTtcblxuXHRcdFx0XHRcdC8vIEFzc29jaWF0ZSBvcmlnaW5hbCBhbmQgcmV0cmFuc21pc3Npb24gU1NSQy5cblx0XHRcdFx0XHRyZW1vdGVNZWRpYU9iai5zc3JjR3JvdXBzLnB1c2goXG5cdFx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRcdHNlbWFudGljcyA6ICdGSUQnLFxuXHRcdFx0XHRcdFx0XHRzc3JjcyAgICAgOiBgJHtpbmZvLnNzcmN9ICR7aW5mby5ydHhTc3JjfWBcblx0XHRcdFx0XHRcdH0pO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdC8vIFB1c2ggaXQuXG5cdFx0XHRzZHBPYmoubWVkaWEucHVzaChyZW1vdGVNZWRpYU9iaik7XG5cdFx0fVxuXG5cdFx0Y29uc3Qgc2RwID0gc2RwVHJhbnNmb3JtLndyaXRlKHNkcE9iaik7XG5cblx0XHRyZXR1cm4gc2RwO1xuXHR9XG59XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFJlbW90ZVVuaWZpZWRQbGFuU2RwXG57XG5cdGNvbnN0cnVjdG9yKGRpcmVjdGlvbiwgcnRwUGFyYW1ldGVyc0J5S2luZClcblx0e1xuXHRcdGxvZ2dlci5kZWJ1Zyhcblx0XHRcdCdjb25zdHJ1Y3RvcigpIFtkaXJlY3Rpb246JXMsIHJ0cFBhcmFtZXRlcnNCeUtpbmQ6JW9dJyxcblx0XHRcdGRpcmVjdGlvbiwgcnRwUGFyYW1ldGVyc0J5S2luZCk7XG5cblx0XHRzd2l0Y2ggKGRpcmVjdGlvbilcblx0XHR7XG5cdFx0XHRjYXNlICdzZW5kJzpcblx0XHRcdFx0cmV0dXJuIG5ldyBTZW5kUmVtb3RlU2RwKHJ0cFBhcmFtZXRlcnNCeUtpbmQpO1xuXHRcdFx0Y2FzZSAncmVjdic6XG5cdFx0XHRcdHJldHVybiBuZXcgUmVjdlJlbW90ZVNkcChydHBQYXJhbWV0ZXJzQnlLaW5kKTtcblx0XHR9XG5cdH1cbn1cbiIsImltcG9ydCBzZHBUcmFuc2Zvcm0gZnJvbSAnc2RwLXRyYW5zZm9ybSc7XG5cbi8qKlxuICogRXh0cmFjdCBSVFAgY2FwYWJpbGl0aWVzIGZyb20gYSBTRFAuXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IHNkcE9iaiAtIFNEUCBPYmplY3QgZ2VuZXJhdGVkIGJ5IHNkcC10cmFuc2Zvcm0uXG4gKiBAcmV0dXJuIHtSVENSdHBDYXBhYmlsaXRpZXN9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBleHRyYWN0UnRwQ2FwYWJpbGl0aWVzKHNkcE9iailcbntcblx0Ly8gTWFwIG9mIFJ0cENvZGVjUGFyYW1ldGVycyBpbmRleGVkIGJ5IHBheWxvYWQgdHlwZS5cblx0Y29uc3QgY29kZWNzTWFwID0gbmV3IE1hcCgpO1xuXG5cdC8vIEFycmF5IG9mIFJ0cEhlYWRlckV4dGVuc2lvbnMuXG5cdGNvbnN0IGhlYWRlckV4dGVuc2lvbnMgPSBbXTtcblxuXHQvLyBXaGV0aGVyIGEgbT1hdWRpby92aWRlbyBzZWN0aW9uIGhhcyBiZWVuIGFscmVhZHkgZm91bmQuXG5cdGxldCBnb3RBdWRpbyA9IGZhbHNlO1xuXHRsZXQgZ290VmlkZW8gPSBmYWxzZTtcblxuXHRmb3IgKGNvbnN0IG0gb2Ygc2RwT2JqLm1lZGlhKVxuXHR7XG5cdFx0Y29uc3Qga2luZCA9IG0udHlwZTtcblxuXHRcdHN3aXRjaCAoa2luZClcblx0XHR7XG5cdFx0XHRjYXNlICdhdWRpbyc6XG5cdFx0XHR7XG5cdFx0XHRcdGlmIChnb3RBdWRpbylcblx0XHRcdFx0XHRjb250aW51ZTtcblxuXHRcdFx0XHRnb3RBdWRpbyA9IHRydWU7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0fVxuXHRcdFx0Y2FzZSAndmlkZW8nOlxuXHRcdFx0e1xuXHRcdFx0XHRpZiAoZ290VmlkZW8pXG5cdFx0XHRcdFx0Y29udGludWU7XG5cblx0XHRcdFx0Z290VmlkZW8gPSB0cnVlO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdH1cblx0XHRcdGRlZmF1bHQ6XG5cdFx0XHR7XG5cdFx0XHRcdGNvbnRpbnVlO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdC8vIEdldCBjb2RlY3MuXG5cdFx0Zm9yIChjb25zdCBydHAgb2YgbS5ydHApXG5cdFx0e1xuXHRcdFx0Y29uc3QgY29kZWMgPVxuXHRcdFx0e1xuXHRcdFx0XHRuYW1lICAgICAgICAgICAgICAgICA6IHJ0cC5jb2RlYyxcblx0XHRcdFx0bWltZVR5cGUgICAgICAgICAgICAgOiBgJHtraW5kfS8ke3J0cC5jb2RlY31gLFxuXHRcdFx0XHRraW5kICAgICAgICAgICAgICAgICA6IGtpbmQsXG5cdFx0XHRcdGNsb2NrUmF0ZSAgICAgICAgICAgIDogcnRwLnJhdGUsXG5cdFx0XHRcdHByZWZlcnJlZFBheWxvYWRUeXBlIDogcnRwLnBheWxvYWQsXG5cdFx0XHRcdGNoYW5uZWxzICAgICAgICAgICAgIDogcnRwLmVuY29kaW5nLFxuXHRcdFx0XHRydGNwRmVlZGJhY2sgICAgICAgICA6IFtdLFxuXHRcdFx0XHRwYXJhbWV0ZXJzICAgICAgICAgICA6IHt9XG5cdFx0XHR9O1xuXG5cdFx0XHRpZiAoIShjb2RlYy5jaGFubmVscyA+IDEpKVxuXHRcdFx0XHRkZWxldGUgY29kZWMuY2hhbm5lbHM7XG5cblx0XHRcdGNvZGVjc01hcC5zZXQoY29kZWMucHJlZmVycmVkUGF5bG9hZFR5cGUsIGNvZGVjKTtcblx0XHR9XG5cblx0XHQvLyBHZXQgY29kZWMgcGFyYW1ldGVycy5cblx0XHRmb3IgKGNvbnN0IGZtdHAgb2YgbS5mbXRwIHx8IFtdKVxuXHRcdHtcblx0XHRcdGNvbnN0IHBhcmFtZXRlcnMgPSBzZHBUcmFuc2Zvcm0ucGFyc2VGbXRwQ29uZmlnKGZtdHAuY29uZmlnKTtcblx0XHRcdGNvbnN0IGNvZGVjID0gY29kZWNzTWFwLmdldChmbXRwLnBheWxvYWQpO1xuXG5cdFx0XHRpZiAoIWNvZGVjKVxuXHRcdFx0XHRjb250aW51ZTtcblxuXHRcdFx0Y29kZWMucGFyYW1ldGVycyA9IHBhcmFtZXRlcnM7XG5cdFx0fVxuXG5cdFx0Ly8gR2V0IFJUQ1AgZmVlZGJhY2sgZm9yIGVhY2ggY29kZWMuXG5cdFx0Zm9yIChjb25zdCBmYiBvZiBtLnJ0Y3BGYiB8fCBbXSlcblx0XHR7XG5cdFx0XHRjb25zdCBjb2RlYyA9IGNvZGVjc01hcC5nZXQoZmIucGF5bG9hZCk7XG5cblx0XHRcdGlmICghY29kZWMpXG5cdFx0XHRcdGNvbnRpbnVlO1xuXG5cdFx0XHRjb25zdCBmZWVkYmFjayA9XG5cdFx0XHR7XG5cdFx0XHRcdHR5cGUgICAgICA6IGZiLnR5cGUsXG5cdFx0XHRcdHBhcmFtZXRlciA6IGZiLnN1YnR5cGUgfHwgJydcblx0XHRcdH07XG5cblx0XHRcdGNvZGVjLnJ0Y3BGZWVkYmFjay5wdXNoKGZlZWRiYWNrKTtcblx0XHR9XG5cblx0XHQvLyBHZXQgUlRQIGhlYWRlciBleHRlbnNpb25zLlxuXHRcdGZvciAoY29uc3QgZXh0IG9mIG0uZXh0IHx8IFtdKVxuXHRcdHtcblx0XHRcdGNvbnN0IGhlYWRlckV4dGVuc2lvbiA9XG5cdFx0XHR7XG5cdFx0XHRcdGtpbmQgICAgICAgIDoga2luZCxcblx0XHRcdFx0dXJpICAgICAgICAgOiBleHQudXJpLFxuXHRcdFx0XHRwcmVmZXJyZWRJZCA6IGV4dC52YWx1ZVxuXHRcdFx0fTtcblxuXHRcdFx0aGVhZGVyRXh0ZW5zaW9ucy5wdXNoKGhlYWRlckV4dGVuc2lvbik7XG5cdFx0fVxuXHR9XG5cblx0Y29uc3QgcnRwQ2FwYWJpbGl0aWVzID1cblx0e1xuXHRcdGNvZGVjcyAgICAgICAgICAgOiBBcnJheS5mcm9tKGNvZGVjc01hcC52YWx1ZXMoKSksXG5cdFx0aGVhZGVyRXh0ZW5zaW9ucyA6IGhlYWRlckV4dGVuc2lvbnMsXG5cdFx0ZmVjTWVjaGFuaXNtcyAgICA6IFtdIC8vIFRPRE9cblx0fTtcblxuXHRyZXR1cm4gcnRwQ2FwYWJpbGl0aWVzO1xufVxuXG4vKipcbiAqIEV4dHJhY3QgRFRMUyBwYXJhbWV0ZXJzIGZyb20gYSBTRFAuXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IHNkcE9iaiAtIFNEUCBPYmplY3QgZ2VuZXJhdGVkIGJ5IHNkcC10cmFuc2Zvcm0uXG4gKiBAcmV0dXJuIHtSVENEdGxzUGFyYW1ldGVyc31cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGV4dHJhY3REdGxzUGFyYW1ldGVycyhzZHBPYmopXG57XG5cdGNvbnN0IG1lZGlhID0gZ2V0Rmlyc3RBY3RpdmVNZWRpYVNlY3Rpb24oc2RwT2JqKTtcblx0Y29uc3QgZmluZ2VycHJpbnQgPSBtZWRpYS5maW5nZXJwcmludCB8fCBzZHBPYmouZmluZ2VycHJpbnQ7XG5cdGxldCByb2xlO1xuXG5cdHN3aXRjaCAobWVkaWEuc2V0dXApXG5cdHtcblx0XHRjYXNlICdhY3RpdmUnOlxuXHRcdFx0cm9sZSA9ICdjbGllbnQnO1xuXHRcdFx0YnJlYWs7XG5cdFx0Y2FzZSAncGFzc2l2ZSc6XG5cdFx0XHRyb2xlID0gJ3NlcnZlcic7XG5cdFx0XHRicmVhaztcblx0XHRjYXNlICdhY3RwYXNzJzpcblx0XHRcdHJvbGUgPSAnYXV0byc7XG5cdFx0XHRicmVhaztcblx0fVxuXG5cdGNvbnN0IGR0bHNQYXJhbWV0ZXJzID1cblx0e1xuXHRcdHJvbGUgICAgICAgICA6IHJvbGUsXG5cdFx0ZmluZ2VycHJpbnRzIDpcblx0XHRbXG5cdFx0XHR7XG5cdFx0XHRcdGFsZ29yaXRobSA6IGZpbmdlcnByaW50LnR5cGUsXG5cdFx0XHRcdHZhbHVlICAgICA6IGZpbmdlcnByaW50Lmhhc2hcblx0XHRcdH1cblx0XHRdXG5cdH07XG5cblx0cmV0dXJuIGR0bHNQYXJhbWV0ZXJzO1xufVxuXG4vKipcbiAqIEdldCB0aGUgZmlyc3QgYWNpdmUgbWVkaWEgc2VjdGlvbi5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHtPYmplY3R9IHNkcE9iaiAtIFNEUCBPYmplY3QgZ2VuZXJhdGVkIGJ5IHNkcC10cmFuc2Zvcm0uXG4gKiBAcmV0dXJuIHtPYmplY3R9IFNEUCBtZWRpYSBzZWN0aW9uIGFzIHBhcnNlZCBieSBzZHAtdHJhbnNmb3JtLlxuICovXG5mdW5jdGlvbiBnZXRGaXJzdEFjdGl2ZU1lZGlhU2VjdGlvbihzZHBPYmopXG57XG5cdHJldHVybiAoc2RwT2JqLm1lZGlhIHx8IFtdKVxuXHRcdC5maW5kKChtKSA9PiBtLmljZVVmcmFnICYmIG0ucG9ydCAhPT0gMCk7XG59XG4iLCIvKipcbiAqIEZpbGwgdGhlIGdpdmVuIFJUUCBwYXJhbWV0ZXJzIGZvciB0aGUgZ2l2ZW4gdHJhY2suXG4gKlxuICogTk9URTogQ3VycmVudGx5IGl0IGFzc3VtZXMgYSBzaW5nbGUgZW5jb2RpbmcgKG5vIHNpbXVsY2FzdCkuXG4gKlxuICogQHBhcmFtIHtSVENSdHBQYXJhbWV0ZXJzfSBydHBQYXJhbWV0ZXJzIC0gIFJUUCBwYXJhbWV0ZXJzIHRvIGJlIGZpbGxlZC5cbiAqIEBwYXJhbSB7T2JqZWN0fSBzZHBPYmogLSBMb2NhbCBTRFAgT2JqZWN0IGdlbmVyYXRlZCBieSBzZHAtdHJhbnNmb3JtLlxuICogQHBhcmFtIHtNZWRpYVN0cmVhbVRyYWNrfSB0cmFja1xuICovXG5leHBvcnQgZnVuY3Rpb24gZmlsbFJ0cFBhcmFtZXRlcnNGb3JUcmFjayhydHBQYXJhbWV0ZXJzLCBzZHBPYmosIHRyYWNrKVxue1xuXHRjb25zdCBraW5kID0gdHJhY2sua2luZDtcblx0Y29uc3QgZW5jb2RpbmcgPSB7fTtcblx0Y29uc3QgcnRjcCA9XG5cdHtcblx0XHRjbmFtZSAgICAgICA6IG51bGwsXG5cdFx0cmVkdWNlZFNpemUgOiB0cnVlLFxuXHRcdG11eCAgICAgICAgIDogdHJ1ZVxuXHR9O1xuXG5cdGNvbnN0IG1TZWN0aW9uID0gKHNkcE9iai5tZWRpYSB8fCBbXSlcblx0XHQuZmluZCgobSkgPT4gbS50eXBlID09PSBraW5kKTtcblxuXHRpZiAoIW1TZWN0aW9uKVxuXHRcdHRocm93IG5ldyBFcnJvcihgbT0ke2tpbmR9IHNlY3Rpb24gbm90IGZvdW5kYCk7XG5cblx0Ly8gR2V0IHRoZSBTU1JDLlxuXG5cdGNvbnN0IHNzcmNNc2lkTGluZSA9IChtU2VjdGlvbi5zc3JjcyB8fCBbXSlcblx0XHQuZmluZCgobGluZSkgPT5cblx0XHR7XG5cdFx0XHRpZiAobGluZS5hdHRyaWJ1dGUgIT09ICdtc2lkJylcblx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXG5cdFx0XHRjb25zdCB0cmFja0lkID0gbGluZS52YWx1ZS5zcGxpdCgnICcpWzFdO1xuXG5cdFx0XHRpZiAodHJhY2tJZCA9PT0gdHJhY2suaWQpXG5cdFx0XHRcdHJldHVybiB0cnVlO1xuXHRcdH0pO1xuXG5cdGlmICghc3NyY01zaWRMaW5lKVxuXHRcdHRocm93IG5ldyBFcnJvcihgYT1zc3JjIGxpbmUgbm90IGZvdW5kIGZvciBsb2NhbCB0cmFjayBbdHJhY2suaWQ6JHt0cmFjay5pZH1dYCk7XG5cblx0Y29uc3Qgc3NyYyA9IHNzcmNNc2lkTGluZS5pZDtcblxuXHRlbmNvZGluZy5zc3JjID0gc3NyYztcblxuXHQvLyBHZXQgdGhlIFNTUkMgZm9yIFJUWC5cblxuXHQobVNlY3Rpb24uc3NyY0dyb3VwcyB8fCBbXSlcblx0XHQuc29tZSgobGluZSkgPT5cblx0XHR7XG5cdFx0XHRpZiAobGluZS5zZW1hbnRpY3MgIT09ICdGSUQnKVxuXHRcdFx0XHRyZXR1cm47XG5cblx0XHRcdGNvbnN0IHNzcmNzID0gbGluZS5zc3Jjcy5zcGxpdCgvWyBdKy8pO1xuXG5cdFx0XHRpZiAoTnVtYmVyKHNzcmNzWzBdKSA9PT0gc3NyYylcblx0XHRcdHtcblx0XHRcdFx0Y29uc3QgcnR4U3NyYyA9IE51bWJlcihzc3Jjc1sxXSk7XG5cblx0XHRcdFx0ZW5jb2RpbmcucnR4ID0geyBzc3JjOiBydHhTc3JjIH07XG5cblx0XHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0XHR9XG5cdFx0fSk7XG5cblx0Ly8gR2V0IFJUQ1AgaW5mby5cblxuXHRjb25zdCBzc3JjQ25hbWVMaW5lID0gbVNlY3Rpb24uc3NyY3Ncblx0XHQuZmluZCgobGluZSkgPT5cblx0XHR7XG5cdFx0XHRyZXR1cm4gKGxpbmUuYXR0cmlidXRlID09PSAnY25hbWUnICYmIGxpbmUuaWQgPT09IHNzcmMpO1xuXHRcdH0pO1xuXG5cdGlmIChzc3JjQ25hbWVMaW5lKVxuXHRcdHJ0Y3AuY25hbWUgPSBzc3JjQ25hbWVMaW5lLnZhbHVlO1xuXG5cdC8vIEZpbGwgUlRQIHBhcmFtZXRlcnMuXG5cdHJ0cFBhcmFtZXRlcnMuZW5jb2RpbmdzID0gWyBlbmNvZGluZyBdO1xuXHRydHBQYXJhbWV0ZXJzLnJ0Y3AgPSBydGNwO1xufVxuIiwiLyoqXG4gKiBGaWxsIHRoZSBnaXZlbiBSVFAgcGFyYW1ldGVycyBmb3IgdGhlIGdpdmVuIHRyYWNrLlxuICpcbiAqIE5PVEU6IEN1cnJlbnRseSBpdCBhc3N1bWVzIGEgc2luZ2xlIGVuY29kaW5nIChubyBzaW11bGNhc3QpLlxuICpcbiAqIEBwYXJhbSB7UlRDUnRwUGFyYW1ldGVyc30gcnRwUGFyYW1ldGVycyAtICBSVFAgcGFyYW1ldGVycyB0byBiZSBmaWxsZWQuXG4gKiBAcGFyYW0ge09iamVjdH0gc2RwT2JqIC0gTG9jYWwgU0RQIE9iamVjdCBnZW5lcmF0ZWQgYnkgc2RwLXRyYW5zZm9ybS5cbiAqIEBwYXJhbSB7TWVkaWFTdHJlYW1UcmFja30gdHJhY2tcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGZpbGxSdHBQYXJhbWV0ZXJzRm9yVHJhY2socnRwUGFyYW1ldGVycywgc2RwT2JqLCB0cmFjaylcbntcblx0Y29uc3Qga2luZCA9IHRyYWNrLmtpbmQ7XG5cdGNvbnN0IGVuY29kaW5nID0ge307XG5cdGNvbnN0IHJ0Y3AgPVxuXHR7XG5cdFx0Y25hbWUgICAgICAgOiBudWxsLFxuXHRcdHJlZHVjZWRTaXplIDogdHJ1ZSxcblx0XHRtdXggICAgICAgICA6IHRydWVcblx0fTtcblxuXHRjb25zdCBtU2VjdGlvbiA9IChzZHBPYmoubWVkaWEgfHwgW10pXG5cdFx0LmZpbmQoKG0pID0+XG5cdFx0e1xuXHRcdFx0aWYgKG0udHlwZSAhPT0ga2luZClcblx0XHRcdFx0cmV0dXJuO1xuXG5cdFx0XHRjb25zdCBtc2lkTGluZSA9IG0ubXNpZDtcblxuXHRcdFx0aWYgKCFtc2lkTGluZSlcblx0XHRcdFx0cmV0dXJuO1xuXG5cdFx0XHRjb25zdCB0cmFja0lkID0gbXNpZExpbmUuc3BsaXQoJyAnKVsxXTtcblxuXHRcdFx0aWYgKHRyYWNrSWQgPT09IHRyYWNrLmlkKVxuXHRcdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHR9KTtcblxuXHRpZiAoIW1TZWN0aW9uKVxuXHRcdHRocm93IG5ldyBFcnJvcihgbT0ke2tpbmR9IHNlY3Rpb24gbm90IGZvdW5kYCk7XG5cblx0Ly8gR2V0IHRoZSBTU1JDIGFuZCBDTkFNRS5cblxuXHRjb25zdCBzc3JjQ25hbWVMaW5lID0gKG1TZWN0aW9uLnNzcmNzIHx8IFtdKVxuXHRcdC5maW5kKChsaW5lKSA9PiBsaW5lLmF0dHJpYnV0ZSA9PT0gJ2NuYW1lJyk7XG5cblx0aWYgKCFzc3JjQ25hbWVMaW5lKVxuXHRcdHRocm93IG5ldyBFcnJvcihgYT1zc3JjIGxpbmUgbm90IGZvdW5kIGZvciBsb2NhbCB0cmFjayBbdHJhY2suaWQ6JHt0cmFjay5pZH1dYCk7XG5cblx0Y29uc3Qgc3NyYyA9IHNzcmNDbmFtZUxpbmUuaWQ7XG5cblx0ZW5jb2Rpbmcuc3NyYyA9IHNzcmNDbmFtZUxpbmUuaWQ7XG5cdHJ0Y3AuY25hbWUgPSBzc3JjQ25hbWVMaW5lLnZhbHVlO1xuXG5cdC8vIEdldCB0aGUgU1NSQyBmb3IgUlRYLlxuXG5cdChtU2VjdGlvbi5zc3JjR3JvdXBzIHx8IFtdKVxuXHRcdC5zb21lKChsaW5lKSA9PlxuXHRcdHtcblx0XHRcdGlmIChsaW5lLnNlbWFudGljcyAhPT0gJ0ZJRCcpXG5cdFx0XHRcdHJldHVybjtcblxuXHRcdFx0Y29uc3Qgc3NyY3MgPSBsaW5lLnNzcmNzLnNwbGl0KC9bIF0rLyk7XG5cblx0XHRcdGlmIChOdW1iZXIoc3NyY3NbMF0pID09PSBzc3JjKVxuXHRcdFx0e1xuXHRcdFx0XHRjb25zdCBydHhTc3JjID0gTnVtYmVyKHNzcmNzWzFdKTtcblxuXHRcdFx0XHRlbmNvZGluZy5ydHggPSB7IHNzcmM6IHJ0eFNzcmMgfTtcblxuXHRcdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHRcdH1cblx0XHR9KTtcblxuXHQvLyBGaWxsIFJUUCBwYXJhbWV0ZXJzLlxuXHRydHBQYXJhbWV0ZXJzLmVuY29kaW5ncyA9IFsgZW5jb2RpbmcgXTtcblx0cnRwUGFyYW1ldGVycy5ydGNwID0gcnRjcDtcbn1cbiIsImltcG9ydCBEZXZpY2UgZnJvbSAnLi9EZXZpY2UnO1xuaW1wb3J0IFJvb20gZnJvbSAnLi9Sb29tJztcblxuLyoqXG4gKiBXaGV0aGVyIHRoZSBjdXJyZW50IGJyb3dzZXIgb3IgZGV2aWNlIGlzIHN1cHBvcnRlZC5cbiAqXG4gKiBAcmV0dXJuIHtCb29sZWFufVxuICpcbiAqIEBleGFtcGxlXG4gKiBpc0RldmljZVN1cHBvcnRlZCgpXG4gKiAvLyA9PiB0cnVlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc0RldmljZVN1cHBvcnRlZCgpXG57XG5cdHJldHVybiBEZXZpY2UuaXNTdXBwb3J0ZWQoKTtcbn1cblxuLyoqXG4gKiBHZXQgaW5mb3JtYXRpb24gcmVnYXJkaW5nIHRoZSBjdXJyZW50IGJyb3dzZXIgb3IgZGV2aWNlLlxuICpcbiAqIEByZXR1cm4ge09iamVjdH0gLSBPYmplY3Qgd2l0aCBgbmFtZWAgKFN0cmluZykgYW5kIHZlcnNpb24ge1N0cmluZ30uXG4gKlxuICogQGV4YW1wbGVcbiAqIGdldERldmljZUluZm8oKVxuICogLy8gPT4geyBuYW1lOiBcIkNocm9tZVwiLCB2ZXJzaW9uOiBcIjU5LjBcIiB9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXREZXZpY2VJbmZvKClcbntcblx0cmV0dXJuIHtcblx0XHRuYW1lICAgIDogRGV2aWNlLm5hbWUsXG5cdFx0dmVyc2lvbiA6IERldmljZS52ZXJzaW9uXG5cdH07XG59XG5cbi8qKlxuICogRXhwb3NlIHRoZSBSb29tIGNsYXNzLlxuICpcbiAqIEBleGFtcGxlXG4gKiBjb25zdCByb29tID0gbmV3IFJvb20oKTtgXG4gKi9cbmV4cG9ydCB7IFJvb20gfTtcbiIsImltcG9ydCByYW5kb21OdW1iZXJMaWIgZnJvbSAncmFuZG9tLW51bWJlcic7XG5cbmNvbnN0IHJhbmRvbU51bWJlckdlbmVyYXRvciA9IHJhbmRvbU51bWJlckxpYi5nZW5lcmF0b3IoXG5cdHtcblx0XHRtaW4gICAgIDogMTAwMDAwMDAsXG5cdFx0bWF4ICAgICA6IDk5OTk5OTk5LFxuXHRcdGludGVnZXIgOiB0cnVlXG5cdH0pO1xuXG4vKipcbiAqIEdlbmVyYXRlcyBhIHJhbmRvbSBwb3NpdGl2ZSBudW1iZXIgYmV0d2VlbiAxMDAwMDAwMCBhbmQgOTk5OTk5OTkuXG4gKlxuICogQHJldHVybiB7TnVtYmVyfVxuICovXG5leHBvcnQgZnVuY3Rpb24gcmFuZG9tTnVtYmVyKClcbntcblx0cmV0dXJuIHJhbmRvbU51bWJlckdlbmVyYXRvcigpO1xufVxuXG4vKipcbiAqIENsb25lcyB0aGUgZ2l2ZW4gT2JqZWN0L0FycmF5LlxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fEFycmF5fSBvYmpcbiAqIEByZXR1cm4ge09iamVjdHxBcnJheX1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNsb25lKG9iailcbntcblx0cmV0dXJuIEpTT04ucGFyc2UoSlNPTi5zdHJpbmdpZnkob2JqKSk7XG59XG5cbi8qKlxuICogR2VuZXJhdGUgZXh0ZW5kZWQgUlRQIGNhcGFiaWxpdGllcyBmb3Igc2VuZGluZyBhbmQgcmVjZWl2aW5nLlxuICpcbiAqIEBwYXJhbSB7UlRDUnRwQ2FwYWJpbGl0aWVzfSBsb2NhbENhcHMgLSBMb2NhbCBjYXBhYmlsaXRpZXMuXG4gKiBAcGFyYW0ge1JUQ1J0cENhcGFiaWxpdGllc30gcmVtb3RlQ2FwcyAtIFJlbW90ZSBjYXBhYmlsaXRpZXMuXG4gKiBAcmV0dXJuIHtSVENFeHRlbmRlZFJ0cENhcGFiaWxpdGllc31cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldEV4dGVuZGVkUnRwQ2FwYWJpbGl0aWVzKGxvY2FsQ2FwcywgcmVtb3RlQ2Fwcylcbntcblx0Y29uc3QgZXh0ZW5kZWRDYXBzID1cblx0e1xuXHRcdGNvZGVjcyAgICAgICAgICAgOiBbXSxcblx0XHRoZWFkZXJFeHRlbnNpb25zIDogW10sXG5cdFx0ZmVjTWVjaGFuaXNtcyAgICA6IFtdXG5cdH07XG5cblx0Ly8gTWF0Y2ggbWVkaWEgY29kZWNzIGFuZCBrZWVwIHRoZSBvcmRlciBwcmVmZXJyZWQgYnkgcmVtb3RlQ2Fwcy5cblx0Zm9yIChjb25zdCByZW1vdGVDb2RlYyBvZiByZW1vdGVDYXBzLmNvZGVjcyB8fCBbXSlcblx0e1xuXHRcdC8vIFRPRE86IElnbm9yZSBwc2V1ZG8tY29kZWNzIGFuZCBmZWF0dXJlIGNvZGVjcy5cblx0XHRpZiAocmVtb3RlQ29kZWMubmFtZSA9PT0gJ3J0eCcpXG5cdFx0XHRjb250aW51ZTtcblxuXHRcdGNvbnN0IG1hdGNoaW5nTG9jYWxDb2RlYyA9IChsb2NhbENhcHMuY29kZWNzIHx8IFtdKVxuXHRcdFx0LmZpbmQoKGxvY2FsQ29kZWMpID0+IG1hdGNoQ29kZWNzKGxvY2FsQ29kZWMsIHJlbW90ZUNvZGVjKSk7XG5cblx0XHRpZiAobWF0Y2hpbmdMb2NhbENvZGVjKVxuXHRcdHtcblx0XHRcdGNvbnN0IGV4dGVuZGVkQ29kZWMgPVxuXHRcdFx0e1xuXHRcdFx0XHRuYW1lICAgICAgICAgICAgICAgOiByZW1vdGVDb2RlYy5uYW1lLFxuXHRcdFx0XHRtaW1lVHlwZSAgICAgICAgICAgOiByZW1vdGVDb2RlYy5taW1lVHlwZSxcblx0XHRcdFx0a2luZCAgICAgICAgICAgICAgIDogcmVtb3RlQ29kZWMua2luZCxcblx0XHRcdFx0Y2xvY2tSYXRlICAgICAgICAgIDogcmVtb3RlQ29kZWMuY2xvY2tSYXRlLFxuXHRcdFx0XHRzZW5kUGF5bG9hZFR5cGUgICAgOiBtYXRjaGluZ0xvY2FsQ29kZWMucHJlZmVycmVkUGF5bG9hZFR5cGUsXG5cdFx0XHRcdHNlbmRSdHhQYXlsb2FkVHlwZSA6IG51bGwsXG5cdFx0XHRcdHJlY3ZQYXlsb2FkVHlwZSAgICA6IHJlbW90ZUNvZGVjLnByZWZlcnJlZFBheWxvYWRUeXBlLFxuXHRcdFx0XHRyZWN2UnR4UGF5bG9hZFR5cGUgOiBudWxsLFxuXHRcdFx0XHRjaGFubmVscyAgICAgICAgICAgOiByZW1vdGVDb2RlYy5jaGFubmVscyxcblx0XHRcdFx0cnRjcEZlZWRiYWNrICAgICAgIDogcmVkdWNlUnRjcEZlZWRiYWNrKG1hdGNoaW5nTG9jYWxDb2RlYywgcmVtb3RlQ29kZWMpLFxuXHRcdFx0XHRwYXJhbWV0ZXJzICAgICAgICAgOiByZW1vdGVDb2RlYy5wYXJhbWV0ZXJzXG5cdFx0XHR9O1xuXG5cdFx0XHRpZiAoIShleHRlbmRlZENvZGVjLmNoYW5uZWxzID4gMSkpXG5cdFx0XHRcdGRlbGV0ZSBleHRlbmRlZENvZGVjLmNoYW5uZWxzO1xuXG5cdFx0XHRleHRlbmRlZENhcHMuY29kZWNzLnB1c2goZXh0ZW5kZWRDb2RlYyk7XG5cdFx0fVxuXHR9XG5cblx0Ly8gTWF0Y2ggUlRYIGNvZGVjcy5cblx0Zm9yIChjb25zdCBleHRlbmRlZENvZGVjIG9mIGV4dGVuZGVkQ2Fwcy5jb2RlY3MgfHwgW10pXG5cdHtcblx0XHRjb25zdCBtYXRjaGluZ0xvY2FsUnR4Q29kZWMgPSAobG9jYWxDYXBzLmNvZGVjcyB8fCBbXSlcblx0XHRcdC5maW5kKChsb2NhbENvZGVjKSA9PlxuXHRcdFx0e1xuXHRcdFx0XHRyZXR1cm4gKFxuXHRcdFx0XHRcdGxvY2FsQ29kZWMubmFtZSA9PT0gJ3J0eCcgJiZcblx0XHRcdFx0XHRsb2NhbENvZGVjLnBhcmFtZXRlcnMuYXB0ID09PSBleHRlbmRlZENvZGVjLnNlbmRQYXlsb2FkVHlwZVxuXHRcdFx0XHQpO1xuXHRcdFx0fSk7XG5cblx0XHRjb25zdCBtYXRjaGluZ1JlbW90ZVJ0eENvZGVjID0gKHJlbW90ZUNhcHMuY29kZWNzIHx8IFtdKVxuXHRcdFx0LmZpbmQoKHJlbW90ZUNvZGVjKSA9PlxuXHRcdFx0e1xuXHRcdFx0XHRyZXR1cm4gKFxuXHRcdFx0XHRcdHJlbW90ZUNvZGVjLm5hbWUgPT09ICdydHgnICYmXG5cdFx0XHRcdFx0cmVtb3RlQ29kZWMucGFyYW1ldGVycy5hcHQgPT09IGV4dGVuZGVkQ29kZWMucmVjdlBheWxvYWRUeXBlXG5cdFx0XHRcdCk7XG5cdFx0XHR9KTtcblxuXHRcdGlmIChtYXRjaGluZ0xvY2FsUnR4Q29kZWMgJiYgbWF0Y2hpbmdSZW1vdGVSdHhDb2RlYylcblx0XHR7XG5cdFx0XHRleHRlbmRlZENvZGVjLnNlbmRSdHhQYXlsb2FkVHlwZSA9IG1hdGNoaW5nTG9jYWxSdHhDb2RlYy5wcmVmZXJyZWRQYXlsb2FkVHlwZTtcblx0XHRcdGV4dGVuZGVkQ29kZWMucmVjdlJ0eFBheWxvYWRUeXBlID0gbWF0Y2hpbmdSZW1vdGVSdHhDb2RlYy5wcmVmZXJyZWRQYXlsb2FkVHlwZTtcblx0XHR9XG5cdH1cblxuXHQvLyBNYXRjaCBoZWFkZXIgZXh0ZW5zaW9ucy5cblx0Zm9yIChjb25zdCByZW1vdGVFeHQgb2YgcmVtb3RlQ2Fwcy5oZWFkZXJFeHRlbnNpb25zIHx8IFtdKVxuXHR7XG5cdFx0Y29uc3QgbWF0Y2hpbmdMb2NhbEV4dCA9IChsb2NhbENhcHMuaGVhZGVyRXh0ZW5zaW9ucyB8fCBbXSlcblx0XHRcdC5maW5kKChsb2NhbEV4dCkgPT4gbWF0Y2hIZWFkZXJFeHRlbnNpb25zKGxvY2FsRXh0LCByZW1vdGVFeHQpKTtcblxuXHRcdGlmIChtYXRjaGluZ0xvY2FsRXh0KVxuXHRcdHtcblx0XHRcdGNvbnN0IGV4dGVuZGVkRXh0ID1cblx0XHRcdHtcblx0XHRcdFx0a2luZCAgIDogcmVtb3RlRXh0LmtpbmQsXG5cdFx0XHRcdHVyaSAgICA6IHJlbW90ZUV4dC51cmksXG5cdFx0XHRcdHNlbmRJZCA6IG1hdGNoaW5nTG9jYWxFeHQucHJlZmVycmVkSWQsXG5cdFx0XHRcdHJlY3ZJZCA6IHJlbW90ZUV4dC5wcmVmZXJyZWRJZFxuXHRcdFx0fTtcblxuXHRcdFx0ZXh0ZW5kZWRDYXBzLmhlYWRlckV4dGVuc2lvbnMucHVzaChleHRlbmRlZEV4dCk7XG5cdFx0fVxuXHR9XG5cblx0cmV0dXJuIGV4dGVuZGVkQ2Fwcztcbn1cblxuLyoqXG4gKiBHZW5lcmF0ZSBSVFAgY2FwYWJpbGl0aWVzIGJhc2VkIG9uIHRoZSBnaXZlbiBleHRlbmRlZCBSVFAgY2FwYWJpbGl0aWVzLlxuICpcbiAqIEBwYXJhbSB7UlRDRXh0ZW5kZWRSdHBDYXBhYmlsaXRpZXN9IGV4dGVuZGVkUnRwQ2FwYWJpbGl0aWVzXG4gKiBAcmV0dXJuIHtSVENSdHBDYXBhYmlsaXRpZXN9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRSdHBDYXBhYmlsaXRpZXMoZXh0ZW5kZWRSdHBDYXBhYmlsaXRpZXMpXG57XG5cdGNvbnN0IGNhcHMgPVxuXHR7XG5cdFx0Y29kZWNzICAgICAgICAgICA6IFtdLFxuXHRcdGhlYWRlckV4dGVuc2lvbnMgOiBbXSxcblx0XHRmZWNNZWNoYW5pc21zICAgIDogW11cblx0fTtcblxuXHRmb3IgKGNvbnN0IGNhcENvZGVjIG9mIGV4dGVuZGVkUnRwQ2FwYWJpbGl0aWVzLmNvZGVjcylcblx0e1xuXHRcdGNvbnN0IGNvZGVjID1cblx0XHR7XG5cdFx0XHRuYW1lICAgICAgICAgICAgICAgICA6IGNhcENvZGVjLm5hbWUsXG5cdFx0XHRtaW1lVHlwZSAgICAgICAgICAgICA6IGNhcENvZGVjLm1pbWVUeXBlLFxuXHRcdFx0a2luZCAgICAgICAgICAgICAgICAgOiBjYXBDb2RlYy5raW5kLFxuXHRcdFx0Y2xvY2tSYXRlICAgICAgICAgICAgOiBjYXBDb2RlYy5jbG9ja1JhdGUsXG5cdFx0XHRwcmVmZXJyZWRQYXlsb2FkVHlwZSA6IGNhcENvZGVjLnJlY3ZQYXlsb2FkVHlwZSxcblx0XHRcdGNoYW5uZWxzICAgICAgICAgICAgIDogY2FwQ29kZWMuY2hhbm5lbHMsXG5cdFx0XHRydGNwRmVlZGJhY2sgICAgICAgICA6IGNhcENvZGVjLnJ0Y3BGZWVkYmFjayxcblx0XHRcdHBhcmFtZXRlcnMgICAgICAgICAgIDogY2FwQ29kZWMucGFyYW1ldGVyc1xuXHRcdH07XG5cblx0XHRpZiAoIShjb2RlYy5jaGFubmVscyA+IDEpKVxuXHRcdFx0ZGVsZXRlIGNvZGVjLmNoYW5uZWxzO1xuXG5cdFx0Y2Fwcy5jb2RlY3MucHVzaChjb2RlYyk7XG5cblx0XHQvLyBBZGQgUlRYIGNvZGVjLlxuXHRcdGlmIChjYXBDb2RlYy5yZWN2UnR4UGF5bG9hZFR5cGUpXG5cdFx0e1xuXHRcdFx0Y29uc3QgcnR4Q2FwQ29kZWMgPVxuXHRcdFx0e1xuXHRcdFx0XHRuYW1lICAgICAgICA6ICdydHgnLFxuXHRcdFx0XHRtaW1lVHlwZSAgICA6IGAke2NhcENvZGVjLmtpbmR9L3J0eGAsXG5cdFx0XHRcdGNsb2NrUmF0ZSAgIDogY2FwQ29kZWMuY2xvY2tSYXRlLFxuXHRcdFx0XHRwYXlsb2FkVHlwZSA6IGNhcENvZGVjLnJlY3ZSdHhQYXlsb2FkVHlwZSxcblx0XHRcdFx0cGFyYW1ldGVycyAgOlxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0YXB0IDogY2FwQ29kZWMucmVjdlBheWxvYWRUeXBlXG5cdFx0XHRcdH1cblx0XHRcdH07XG5cblx0XHRcdGNhcHMuY29kZWNzLnB1c2gocnR4Q2FwQ29kZWMpO1xuXHRcdH1cblxuXHRcdC8vIFRPRE86IEluIHRoZSBmdXR1cmUsIHdlIG5lZWQgdG8gYWRkIEZFQywgQ04sIGV0YywgY29kZWNzLlxuXHR9XG5cblx0Zm9yIChjb25zdCBjYXBFeHQgb2YgZXh0ZW5kZWRSdHBDYXBhYmlsaXRpZXMuaGVhZGVyRXh0ZW5zaW9ucylcblx0e1xuXHRcdGNvbnN0IGV4dCA9XG5cdFx0e1xuXHRcdFx0a2luZCAgICAgICAgOiBjYXBFeHQua2luZCxcblx0XHRcdHVyaSAgICAgICAgIDogY2FwRXh0LnVyaSxcblx0XHRcdHByZWZlcnJlZElkIDogY2FwRXh0LnJlY3ZJZFxuXHRcdH07XG5cblx0XHRjYXBzLmhlYWRlckV4dGVuc2lvbnMucHVzaChleHQpO1xuXHR9XG5cblx0Y2Fwcy5mZWNNZWNoYW5pc21zID0gZXh0ZW5kZWRSdHBDYXBhYmlsaXRpZXMuZmVjTWVjaGFuaXNtcztcblxuXHRyZXR1cm4gY2Fwcztcbn1cblxuLyoqXG4gKiBXaGV0aGVyIG1lZGlhIGNhbiBiZSBzZW50IGJhc2VkIG9uIHRoZSBnaXZlbiBSVFAgY2FwYWJpbGl0aWVzLlxuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSBraW5kXG4gKiBAcGFyYW0ge1JUQ0V4dGVuZGVkUnRwQ2FwYWJpbGl0aWVzfSBleHRlbmRlZFJ0cENhcGFiaWxpdGllc1xuICogQHJldHVybiB7Qm9vbGVhbn1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNhblNlbmQoa2luZCwgZXh0ZW5kZWRSdHBDYXBhYmlsaXRpZXMpXG57XG5cdHJldHVybiBleHRlbmRlZFJ0cENhcGFiaWxpdGllcy5jb2RlY3MuXG5cdFx0c29tZSgoY29kZWMpID0+IGNvZGVjLmtpbmQgPT09IGtpbmQpO1xufVxuXG4vKipcbiAqIFdoZXRoZXIgdGhlIGdpdmVuIFJUUCBwYXJhbWV0ZXJzIGNhbiBiZSByZWNlaXZlZCB3aXRoIHRoZSBnaXZlbiBSVFBcbiAqIGNhcGFiaWxpdGllcy5cbiAqXG4gKiBAcGFyYW0ge1JUQ1J0cFBhcmFtZXRlcnN9IHJ0cFBhcmFtZXRlcnNcbiAqIEBwYXJhbSB7UlRDRXh0ZW5kZWRSdHBDYXBhYmlsaXRpZXN9IGV4dGVuZGVkUnRwQ2FwYWJpbGl0aWVzXG4gKiBAcmV0dXJuIHtCb29sZWFufVxuICovXG5leHBvcnQgZnVuY3Rpb24gY2FuUmVjZWl2ZShydHBQYXJhbWV0ZXJzLCBleHRlbmRlZFJ0cENhcGFiaWxpdGllcylcbntcblx0Y29uc3QgZmlyc3RNZWRpYUNvZGVjID0gcnRwUGFyYW1ldGVycy5jb2RlY3NbMF07XG5cblx0cmV0dXJuIGV4dGVuZGVkUnRwQ2FwYWJpbGl0aWVzLmNvZGVjc1xuXHRcdC5zb21lKChjb2RlYykgPT4gY29kZWMucmVjdlBheWxvYWRUeXBlID09PSBmaXJzdE1lZGlhQ29kZWMucGF5bG9hZFR5cGUpO1xufVxuXG4vKipcbiAqIEdlbmVyYXRlIFJUUCBwYXJhbWV0ZXJzIG9mIHRoZSBnaXZlbiBraW5kIGZvciBzZW5kaW5nIG1lZGlhLlxuICogSnVzdCB0aGUgZmlyc3QgbWVkaWEgY29kZWMgcGVyIGtpbmQgaXMgY29uc2lkZXJlZC5cbiAqIE5PVEU6IG11eElkLCBlbmNvZGluZ3MgYW5kIHJ0Y3AgZmllbGRzIGFyZSBsZWZ0IGVtcHR5LlxuICpcbiAqIEBwYXJhbSB7a2luZH0ga2luZFxuICogQHBhcmFtIHtSVENFeHRlbmRlZFJ0cENhcGFiaWxpdGllc30gZXh0ZW5kZWRSdHBDYXBhYmlsaXRpZXNcbiAqIEByZXR1cm4ge1JUQ1J0cFBhcmFtZXRlcnN9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRTZW5kaW5nUnRwUGFyYW1ldGVycyhraW5kLCBleHRlbmRlZFJ0cENhcGFiaWxpdGllcylcbntcblx0Y29uc3QgcGFyYW1zID1cblx0e1xuXHRcdG11eElkICAgICAgICAgICAgOiBudWxsLFxuXHRcdGNvZGVjcyAgICAgICAgICAgOiBbXSxcblx0XHRoZWFkZXJFeHRlbnNpb25zIDogW10sXG5cdFx0ZW5jb2RpbmdzICAgICAgICA6IFtdLFxuXHRcdHJ0Y3AgICAgICAgICAgICAgOiB7fVxuXHR9O1xuXG5cdGZvciAoY29uc3QgY2FwQ29kZWMgb2YgZXh0ZW5kZWRSdHBDYXBhYmlsaXRpZXMuY29kZWNzKVxuXHR7XG5cdFx0aWYgKGNhcENvZGVjLmtpbmQgIT09IGtpbmQpXG5cdFx0XHRjb250aW51ZTtcblxuXHRcdGNvbnN0IGNvZGVjID1cblx0XHR7XG5cdFx0XHRuYW1lICAgICAgICAgOiBjYXBDb2RlYy5uYW1lLFxuXHRcdFx0bWltZVR5cGUgICAgIDogY2FwQ29kZWMubWltZVR5cGUsXG5cdFx0XHRjbG9ja1JhdGUgICAgOiBjYXBDb2RlYy5jbG9ja1JhdGUsXG5cdFx0XHRwYXlsb2FkVHlwZSAgOiBjYXBDb2RlYy5zZW5kUGF5bG9hZFR5cGUsXG5cdFx0XHRjaGFubmVscyAgICAgOiBjYXBDb2RlYy5jaGFubmVscyxcblx0XHRcdHJ0Y3BGZWVkYmFjayA6IGNhcENvZGVjLnJ0Y3BGZWVkYmFjayxcblx0XHRcdHBhcmFtZXRlcnMgICA6IGNhcENvZGVjLnBhcmFtZXRlcnNcblx0XHR9O1xuXG5cdFx0aWYgKCEoY29kZWMuY2hhbm5lbHMgPiAxKSlcblx0XHRcdGRlbGV0ZSBjb2RlYy5jaGFubmVscztcblxuXHRcdHBhcmFtcy5jb2RlY3MucHVzaChjb2RlYyk7XG5cblx0XHQvLyBBZGQgUlRYIGNvZGVjLlxuXHRcdGlmIChjYXBDb2RlYy5zZW5kUnR4UGF5bG9hZFR5cGUpXG5cdFx0e1xuXHRcdFx0Y29uc3QgcnR4Q29kZWMgPVxuXHRcdFx0e1xuXHRcdFx0XHRuYW1lICAgICAgICA6ICdydHgnLFxuXHRcdFx0XHRtaW1lVHlwZSAgICA6IGAke2NhcENvZGVjLmtpbmR9L3J0eGAsXG5cdFx0XHRcdGNsb2NrUmF0ZSAgIDogY2FwQ29kZWMuY2xvY2tSYXRlLFxuXHRcdFx0XHRwYXlsb2FkVHlwZSA6IGNhcENvZGVjLnNlbmRSdHhQYXlsb2FkVHlwZSxcblx0XHRcdFx0cGFyYW1ldGVycyAgOlxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0YXB0IDogY2FwQ29kZWMuc2VuZFBheWxvYWRUeXBlXG5cdFx0XHRcdH1cblx0XHRcdH07XG5cblx0XHRcdHBhcmFtcy5jb2RlY3MucHVzaChydHhDb2RlYyk7XG5cdFx0fVxuXG5cdFx0Ly8gTk9URTogV2UgYXNzdW1lIGEgc2luZ2xlIG1lZGlhIGNvZGVjIHBsdXMgYW4gb3B0aW9uYWwgUlRYIGNvZGVjIGZvciBub3cuXG5cdFx0Ly8gVE9ETzogSW4gdGhlIGZ1dHVyZSwgd2UgbmVlZCB0byBhZGQgRkVDLCBDTiwgZXRjLCBjb2RlY3MuXG5cdFx0YnJlYWs7XG5cdH1cblxuXHRmb3IgKGNvbnN0IGNhcEV4dCBvZiBleHRlbmRlZFJ0cENhcGFiaWxpdGllcy5oZWFkZXJFeHRlbnNpb25zKVxuXHR7XG5cdFx0aWYgKGNhcEV4dC5raW5kICE9PSBraW5kKVxuXHRcdFx0Y29udGludWU7XG5cblx0XHRjb25zdCBleHQgPVxuXHRcdHtcblx0XHRcdHVyaSA6IGNhcEV4dC51cmksXG5cdFx0XHRpZCAgOiBjYXBFeHQuc2VuZElkXG5cdFx0fTtcblxuXHRcdHBhcmFtcy5oZWFkZXJFeHRlbnNpb25zLnB1c2goZXh0KTtcblx0fVxuXG5cdHJldHVybiBwYXJhbXM7XG59XG5cbi8qKlxuICogR2VuZXJhdGUgUlRQIHBhcmFtZXRlcnMgb2YgdGhlIGdpdmVuIGtpbmQgZm9yIHJlY2VpdmluZyBtZWRpYS5cbiAqIEFsbCB0aGUgbWVkaWEgY29kZWNzIHBlciBraW5kIGFyZSBjb25zaWRlcmVkLiBUaGlzIGlzIHVzZWZ1bCBmb3IgZ2VuZXJhdGluZ1xuICogYSBTRFAgcmVtb3RlIG9mZmVyLlxuICogTk9URTogbXV4SWQsIGVuY29kaW5ncyBhbmQgcnRjcCBmaWVsZHMgYXJlIGxlZnQgZW1wdHkuXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IGtpbmRcbiAqIEBwYXJhbSB7UlRDRXh0ZW5kZWRSdHBDYXBhYmlsaXRpZXN9IGV4dGVuZGVkUnRwQ2FwYWJpbGl0aWVzXG4gKiBAcmV0dXJuIHtSVENSdHBQYXJhbWV0ZXJzfVxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0UmVjZWl2aW5nRnVsbFJ0cFBhcmFtZXRlcnMoa2luZCwgZXh0ZW5kZWRSdHBDYXBhYmlsaXRpZXMpXG57XG5cdGNvbnN0IHBhcmFtcyA9XG5cdHtcblx0XHRtdXhJZCAgICAgICAgICAgIDogbnVsbCxcblx0XHRjb2RlY3MgICAgICAgICAgIDogW10sXG5cdFx0aGVhZGVyRXh0ZW5zaW9ucyA6IFtdLFxuXHRcdGVuY29kaW5ncyAgICAgICAgOiBbXSxcblx0XHRydGNwICAgICAgICAgICAgIDoge31cblx0fTtcblxuXHRmb3IgKGNvbnN0IGNhcENvZGVjIG9mIGV4dGVuZGVkUnRwQ2FwYWJpbGl0aWVzLmNvZGVjcylcblx0e1xuXHRcdGlmIChjYXBDb2RlYy5raW5kICE9PSBraW5kKVxuXHRcdFx0Y29udGludWU7XG5cblx0XHRjb25zdCBjb2RlYyA9XG5cdFx0e1xuXHRcdFx0bmFtZSAgICAgICAgIDogY2FwQ29kZWMubmFtZSxcblx0XHRcdG1pbWVUeXBlICAgICA6IGNhcENvZGVjLm1pbWVUeXBlLFxuXHRcdFx0Y2xvY2tSYXRlICAgIDogY2FwQ29kZWMuY2xvY2tSYXRlLFxuXHRcdFx0cGF5bG9hZFR5cGUgIDogY2FwQ29kZWMucmVjdlBheWxvYWRUeXBlLFxuXHRcdFx0Y2hhbm5lbHMgICAgIDogY2FwQ29kZWMuY2hhbm5lbHMsXG5cdFx0XHRydGNwRmVlZGJhY2sgOiBjYXBDb2RlYy5ydGNwRmVlZGJhY2ssXG5cdFx0XHRwYXJhbWV0ZXJzICAgOiBjYXBDb2RlYy5wYXJhbWV0ZXJzXG5cdFx0fTtcblxuXHRcdGlmICghKGNvZGVjLmNoYW5uZWxzID4gMSkpXG5cdFx0XHRkZWxldGUgY29kZWMuY2hhbm5lbHM7XG5cblx0XHRwYXJhbXMuY29kZWNzLnB1c2goY29kZWMpO1xuXG5cdFx0Ly8gQWRkIFJUWCBjb2RlYy5cblx0XHRpZiAoY2FwQ29kZWMucmVjdlJ0eFBheWxvYWRUeXBlKVxuXHRcdHtcblx0XHRcdGNvbnN0IHJ0eENvZGVjID1cblx0XHRcdHtcblx0XHRcdFx0bmFtZSAgICAgICAgOiAncnR4Jyxcblx0XHRcdFx0bWltZVR5cGUgICAgOiBgJHtjYXBDb2RlYy5raW5kfS9ydHhgLFxuXHRcdFx0XHRjbG9ja1JhdGUgICA6IGNhcENvZGVjLmNsb2NrUmF0ZSxcblx0XHRcdFx0cGF5bG9hZFR5cGUgOiBjYXBDb2RlYy5yZWN2UnR4UGF5bG9hZFR5cGUsXG5cdFx0XHRcdHBhcmFtZXRlcnMgIDpcblx0XHRcdFx0e1xuXHRcdFx0XHRcdGFwdCA6IGNhcENvZGVjLnJlY3ZQYXlsb2FkVHlwZVxuXHRcdFx0XHR9XG5cdFx0XHR9O1xuXG5cdFx0XHRwYXJhbXMuY29kZWNzLnB1c2gocnR4Q29kZWMpO1xuXHRcdH1cblxuXHRcdC8vIFRPRE86IEluIHRoZSBmdXR1cmUsIHdlIG5lZWQgdG8gYWRkIEZFQywgQ04sIGV0YywgY29kZWNzLlxuXHR9XG5cblx0Zm9yIChjb25zdCBjYXBFeHQgb2YgZXh0ZW5kZWRSdHBDYXBhYmlsaXRpZXMuaGVhZGVyRXh0ZW5zaW9ucylcblx0e1xuXHRcdGlmIChjYXBFeHQua2luZCAhPT0ga2luZClcblx0XHRcdGNvbnRpbnVlO1xuXG5cdFx0Y29uc3QgZXh0ID1cblx0XHR7XG5cdFx0XHR1cmkgOiBjYXBFeHQudXJpLFxuXHRcdFx0aWQgIDogY2FwRXh0LnJlY3ZJZFxuXHRcdH07XG5cblx0XHRwYXJhbXMuaGVhZGVyRXh0ZW5zaW9ucy5wdXNoKGV4dCk7XG5cdH1cblxuXHRyZXR1cm4gcGFyYW1zO1xufVxuXG5mdW5jdGlvbiBtYXRjaENvZGVjcyhhQ29kZWMsIGJDb2RlYylcbntcblx0cmV0dXJuIChcblx0XHRhQ29kZWMubWltZVR5cGUgPT09IGJDb2RlYy5taW1lVHlwZSAmJlxuXHRcdGFDb2RlYy5jbG9ja1JhdGUgPT09IGJDb2RlYy5jbG9ja1JhdGVcblx0KTtcbn1cblxuZnVuY3Rpb24gbWF0Y2hIZWFkZXJFeHRlbnNpb25zKGFFeHQsIGJFeHQpXG57XG5cdHJldHVybiAoXG5cdFx0YUV4dC5raW5kID09PSBiRXh0LmtpbmQgJiZcblx0XHRhRXh0LnVyaSA9PT0gYkV4dC51cmlcblx0KTtcbn1cblxuZnVuY3Rpb24gcmVkdWNlUnRjcEZlZWRiYWNrKGNvZGVjQSwgY29kZWNCKVxue1xuXHRjb25zdCByZWR1Y2VkUnRjcEZlZWRiYWNrID0gW107XG5cblx0Zm9yIChjb25zdCBhRmIgb2YgY29kZWNBLnJ0Y3BGZWVkYmFjayB8fCBbXSlcblx0e1xuXHRcdGNvbnN0IG1hdGNoaW5nQkZiID0gKGNvZGVjQi5ydGNwRmVlZGJhY2sgfHwgW10pXG5cdFx0XHQuZmluZCgoYkZiKSA9PlxuXHRcdFx0e1xuXHRcdFx0XHRyZXR1cm4gKFxuXHRcdFx0XHRcdGJGYi50eXBlID09PSBhRmIudHlwZSAmJlxuXHRcdFx0XHRcdGJGYi5wYXJhbWV0ZXIgPT09IGFGYi5wYXJhbWV0ZXJcblx0XHRcdFx0KTtcblx0XHRcdH0pO1xuXG5cdFx0aWYgKG1hdGNoaW5nQkZiKVxuXHRcdFx0cmVkdWNlZFJ0Y3BGZWVkYmFjay5wdXNoKG1hdGNoaW5nQkZiKTtcblx0fVxuXG5cdHJldHVybiByZWR1Y2VkUnRjcEZlZWRiYWNrO1xufVxuIiwibW9kdWxlLmV4cG9ydHMgPSB7IFwiZGVmYXVsdFwiOiByZXF1aXJlKFwiY29yZS1qcy9saWJyYXJ5L2ZuL2FycmF5L2Zyb21cIiksIF9fZXNNb2R1bGU6IHRydWUgfTsiLCJtb2R1bGUuZXhwb3J0cyA9IHsgXCJkZWZhdWx0XCI6IHJlcXVpcmUoXCJjb3JlLWpzL2xpYnJhcnkvZm4vZ2V0LWl0ZXJhdG9yXCIpLCBfX2VzTW9kdWxlOiB0cnVlIH07IiwibW9kdWxlLmV4cG9ydHMgPSB7IFwiZGVmYXVsdFwiOiByZXF1aXJlKFwiY29yZS1qcy9saWJyYXJ5L2ZuL2pzb24vc3RyaW5naWZ5XCIpLCBfX2VzTW9kdWxlOiB0cnVlIH07IiwibW9kdWxlLmV4cG9ydHMgPSB7IFwiZGVmYXVsdFwiOiByZXF1aXJlKFwiY29yZS1qcy9saWJyYXJ5L2ZuL21hcFwiKSwgX19lc01vZHVsZTogdHJ1ZSB9OyIsIm1vZHVsZS5leHBvcnRzID0geyBcImRlZmF1bHRcIjogcmVxdWlyZShcImNvcmUtanMvbGlicmFyeS9mbi9vYmplY3QvYXNzaWduXCIpLCBfX2VzTW9kdWxlOiB0cnVlIH07IiwibW9kdWxlLmV4cG9ydHMgPSB7IFwiZGVmYXVsdFwiOiByZXF1aXJlKFwiY29yZS1qcy9saWJyYXJ5L2ZuL29iamVjdC9jcmVhdGVcIiksIF9fZXNNb2R1bGU6IHRydWUgfTsiLCJtb2R1bGUuZXhwb3J0cyA9IHsgXCJkZWZhdWx0XCI6IHJlcXVpcmUoXCJjb3JlLWpzL2xpYnJhcnkvZm4vb2JqZWN0L2RlZmluZS1wcm9wZXJ0eVwiKSwgX19lc01vZHVsZTogdHJ1ZSB9OyIsIm1vZHVsZS5leHBvcnRzID0geyBcImRlZmF1bHRcIjogcmVxdWlyZShcImNvcmUtanMvbGlicmFyeS9mbi9vYmplY3QvZ2V0LXByb3RvdHlwZS1vZlwiKSwgX19lc01vZHVsZTogdHJ1ZSB9OyIsIm1vZHVsZS5leHBvcnRzID0geyBcImRlZmF1bHRcIjogcmVxdWlyZShcImNvcmUtanMvbGlicmFyeS9mbi9vYmplY3Qva2V5c1wiKSwgX19lc01vZHVsZTogdHJ1ZSB9OyIsIm1vZHVsZS5leHBvcnRzID0geyBcImRlZmF1bHRcIjogcmVxdWlyZShcImNvcmUtanMvbGlicmFyeS9mbi9vYmplY3Qvc2V0LXByb3RvdHlwZS1vZlwiKSwgX19lc01vZHVsZTogdHJ1ZSB9OyIsIm1vZHVsZS5leHBvcnRzID0geyBcImRlZmF1bHRcIjogcmVxdWlyZShcImNvcmUtanMvbGlicmFyeS9mbi9wcm9taXNlXCIpLCBfX2VzTW9kdWxlOiB0cnVlIH07IiwibW9kdWxlLmV4cG9ydHMgPSB7IFwiZGVmYXVsdFwiOiByZXF1aXJlKFwiY29yZS1qcy9saWJyYXJ5L2ZuL3NldFwiKSwgX19lc01vZHVsZTogdHJ1ZSB9OyIsIm1vZHVsZS5leHBvcnRzID0geyBcImRlZmF1bHRcIjogcmVxdWlyZShcImNvcmUtanMvbGlicmFyeS9mbi9zeW1ib2xcIiksIF9fZXNNb2R1bGU6IHRydWUgfTsiLCJtb2R1bGUuZXhwb3J0cyA9IHsgXCJkZWZhdWx0XCI6IHJlcXVpcmUoXCJjb3JlLWpzL2xpYnJhcnkvZm4vc3ltYm9sL2l0ZXJhdG9yXCIpLCBfX2VzTW9kdWxlOiB0cnVlIH07IiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbmV4cG9ydHMuX19lc01vZHVsZSA9IHRydWU7XG5cbmV4cG9ydHMuZGVmYXVsdCA9IGZ1bmN0aW9uIChpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHtcbiAgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uXCIpO1xuICB9XG59OyIsIlwidXNlIHN0cmljdFwiO1xuXG5leHBvcnRzLl9fZXNNb2R1bGUgPSB0cnVlO1xuXG52YXIgX2RlZmluZVByb3BlcnR5ID0gcmVxdWlyZShcIi4uL2NvcmUtanMvb2JqZWN0L2RlZmluZS1wcm9wZXJ0eVwiKTtcblxudmFyIF9kZWZpbmVQcm9wZXJ0eTIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9kZWZpbmVQcm9wZXJ0eSk7XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7IGRlZmF1bHQ6IG9iaiB9OyB9XG5cbmV4cG9ydHMuZGVmYXVsdCA9IGZ1bmN0aW9uICgpIHtcbiAgZnVuY3Rpb24gZGVmaW5lUHJvcGVydGllcyh0YXJnZXQsIHByb3BzKSB7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTtcbiAgICAgIGRlc2NyaXB0b3IuZW51bWVyYWJsZSA9IGRlc2NyaXB0b3IuZW51bWVyYWJsZSB8fCBmYWxzZTtcbiAgICAgIGRlc2NyaXB0b3IuY29uZmlndXJhYmxlID0gdHJ1ZTtcbiAgICAgIGlmIChcInZhbHVlXCIgaW4gZGVzY3JpcHRvcikgZGVzY3JpcHRvci53cml0YWJsZSA9IHRydWU7XG4gICAgICAoMCwgX2RlZmluZVByb3BlcnR5Mi5kZWZhdWx0KSh0YXJnZXQsIGRlc2NyaXB0b3Iua2V5LCBkZXNjcmlwdG9yKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZnVuY3Rpb24gKENvbnN0cnVjdG9yLCBwcm90b1Byb3BzLCBzdGF0aWNQcm9wcykge1xuICAgIGlmIChwcm90b1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLnByb3RvdHlwZSwgcHJvdG9Qcm9wcyk7XG4gICAgaWYgKHN0YXRpY1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLCBzdGF0aWNQcm9wcyk7XG4gICAgcmV0dXJuIENvbnN0cnVjdG9yO1xuICB9O1xufSgpOyIsIlwidXNlIHN0cmljdFwiO1xuXG5leHBvcnRzLl9fZXNNb2R1bGUgPSB0cnVlO1xuXG52YXIgX2Fzc2lnbiA9IHJlcXVpcmUoXCIuLi9jb3JlLWpzL29iamVjdC9hc3NpZ25cIik7XG5cbnZhciBfYXNzaWduMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2Fzc2lnbik7XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7IGRlZmF1bHQ6IG9iaiB9OyB9XG5cbmV4cG9ydHMuZGVmYXVsdCA9IF9hc3NpZ24yLmRlZmF1bHQgfHwgZnVuY3Rpb24gKHRhcmdldCkge1xuICBmb3IgKHZhciBpID0gMTsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykge1xuICAgIHZhciBzb3VyY2UgPSBhcmd1bWVudHNbaV07XG5cbiAgICBmb3IgKHZhciBrZXkgaW4gc291cmNlKSB7XG4gICAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHNvdXJjZSwga2V5KSkge1xuICAgICAgICB0YXJnZXRba2V5XSA9IHNvdXJjZVtrZXldO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0YXJnZXQ7XG59OyIsIlwidXNlIHN0cmljdFwiO1xuXG5leHBvcnRzLl9fZXNNb2R1bGUgPSB0cnVlO1xuXG52YXIgX3NldFByb3RvdHlwZU9mID0gcmVxdWlyZShcIi4uL2NvcmUtanMvb2JqZWN0L3NldC1wcm90b3R5cGUtb2ZcIik7XG5cbnZhciBfc2V0UHJvdG90eXBlT2YyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfc2V0UHJvdG90eXBlT2YpO1xuXG52YXIgX2NyZWF0ZSA9IHJlcXVpcmUoXCIuLi9jb3JlLWpzL29iamVjdC9jcmVhdGVcIik7XG5cbnZhciBfY3JlYXRlMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2NyZWF0ZSk7XG5cbnZhciBfdHlwZW9mMiA9IHJlcXVpcmUoXCIuLi9oZWxwZXJzL3R5cGVvZlwiKTtcblxudmFyIF90eXBlb2YzID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfdHlwZW9mMik7XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7IGRlZmF1bHQ6IG9iaiB9OyB9XG5cbmV4cG9ydHMuZGVmYXVsdCA9IGZ1bmN0aW9uIChzdWJDbGFzcywgc3VwZXJDbGFzcykge1xuICBpZiAodHlwZW9mIHN1cGVyQ2xhc3MgIT09IFwiZnVuY3Rpb25cIiAmJiBzdXBlckNsYXNzICE9PSBudWxsKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlN1cGVyIGV4cHJlc3Npb24gbXVzdCBlaXRoZXIgYmUgbnVsbCBvciBhIGZ1bmN0aW9uLCBub3QgXCIgKyAodHlwZW9mIHN1cGVyQ2xhc3MgPT09IFwidW5kZWZpbmVkXCIgPyBcInVuZGVmaW5lZFwiIDogKDAsIF90eXBlb2YzLmRlZmF1bHQpKHN1cGVyQ2xhc3MpKSk7XG4gIH1cblxuICBzdWJDbGFzcy5wcm90b3R5cGUgPSAoMCwgX2NyZWF0ZTIuZGVmYXVsdCkoc3VwZXJDbGFzcyAmJiBzdXBlckNsYXNzLnByb3RvdHlwZSwge1xuICAgIGNvbnN0cnVjdG9yOiB7XG4gICAgICB2YWx1ZTogc3ViQ2xhc3MsXG4gICAgICBlbnVtZXJhYmxlOiBmYWxzZSxcbiAgICAgIHdyaXRhYmxlOiB0cnVlLFxuICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgfVxuICB9KTtcbiAgaWYgKHN1cGVyQ2xhc3MpIF9zZXRQcm90b3R5cGVPZjIuZGVmYXVsdCA/ICgwLCBfc2V0UHJvdG90eXBlT2YyLmRlZmF1bHQpKHN1YkNsYXNzLCBzdXBlckNsYXNzKSA6IHN1YkNsYXNzLl9fcHJvdG9fXyA9IHN1cGVyQ2xhc3M7XG59OyIsIlwidXNlIHN0cmljdFwiO1xuXG5leHBvcnRzLl9fZXNNb2R1bGUgPSB0cnVlO1xuXG52YXIgX3R5cGVvZjIgPSByZXF1aXJlKFwiLi4vaGVscGVycy90eXBlb2ZcIik7XG5cbnZhciBfdHlwZW9mMyA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX3R5cGVvZjIpO1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyBkZWZhdWx0OiBvYmogfTsgfVxuXG5leHBvcnRzLmRlZmF1bHQgPSBmdW5jdGlvbiAoc2VsZiwgY2FsbCkge1xuICBpZiAoIXNlbGYpIHtcbiAgICB0aHJvdyBuZXcgUmVmZXJlbmNlRXJyb3IoXCJ0aGlzIGhhc24ndCBiZWVuIGluaXRpYWxpc2VkIC0gc3VwZXIoKSBoYXNuJ3QgYmVlbiBjYWxsZWRcIik7XG4gIH1cblxuICByZXR1cm4gY2FsbCAmJiAoKHR5cGVvZiBjYWxsID09PSBcInVuZGVmaW5lZFwiID8gXCJ1bmRlZmluZWRcIiA6ICgwLCBfdHlwZW9mMy5kZWZhdWx0KShjYWxsKSkgPT09IFwib2JqZWN0XCIgfHwgdHlwZW9mIGNhbGwgPT09IFwiZnVuY3Rpb25cIikgPyBjYWxsIDogc2VsZjtcbn07IiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbmV4cG9ydHMuX19lc01vZHVsZSA9IHRydWU7XG5cbnZhciBfaXRlcmF0b3IgPSByZXF1aXJlKFwiLi4vY29yZS1qcy9zeW1ib2wvaXRlcmF0b3JcIik7XG5cbnZhciBfaXRlcmF0b3IyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfaXRlcmF0b3IpO1xuXG52YXIgX3N5bWJvbCA9IHJlcXVpcmUoXCIuLi9jb3JlLWpzL3N5bWJvbFwiKTtcblxudmFyIF9zeW1ib2wyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfc3ltYm9sKTtcblxudmFyIF90eXBlb2YgPSB0eXBlb2YgX3N5bWJvbDIuZGVmYXVsdCA9PT0gXCJmdW5jdGlvblwiICYmIHR5cGVvZiBfaXRlcmF0b3IyLmRlZmF1bHQgPT09IFwic3ltYm9sXCIgPyBmdW5jdGlvbiAob2JqKSB7IHJldHVybiB0eXBlb2Ygb2JqOyB9IDogZnVuY3Rpb24gKG9iaikgeyByZXR1cm4gb2JqICYmIHR5cGVvZiBfc3ltYm9sMi5kZWZhdWx0ID09PSBcImZ1bmN0aW9uXCIgJiYgb2JqLmNvbnN0cnVjdG9yID09PSBfc3ltYm9sMi5kZWZhdWx0ICYmIG9iaiAhPT0gX3N5bWJvbDIuZGVmYXVsdC5wcm90b3R5cGUgPyBcInN5bWJvbFwiIDogdHlwZW9mIG9iajsgfTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHsgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHsgZGVmYXVsdDogb2JqIH07IH1cblxuZXhwb3J0cy5kZWZhdWx0ID0gdHlwZW9mIF9zeW1ib2wyLmRlZmF1bHQgPT09IFwiZnVuY3Rpb25cIiAmJiBfdHlwZW9mKF9pdGVyYXRvcjIuZGVmYXVsdCkgPT09IFwic3ltYm9sXCIgPyBmdW5jdGlvbiAob2JqKSB7XG4gIHJldHVybiB0eXBlb2Ygb2JqID09PSBcInVuZGVmaW5lZFwiID8gXCJ1bmRlZmluZWRcIiA6IF90eXBlb2Yob2JqKTtcbn0gOiBmdW5jdGlvbiAob2JqKSB7XG4gIHJldHVybiBvYmogJiYgdHlwZW9mIF9zeW1ib2wyLmRlZmF1bHQgPT09IFwiZnVuY3Rpb25cIiAmJiBvYmouY29uc3RydWN0b3IgPT09IF9zeW1ib2wyLmRlZmF1bHQgJiYgb2JqICE9PSBfc3ltYm9sMi5kZWZhdWx0LnByb3RvdHlwZSA/IFwic3ltYm9sXCIgOiB0eXBlb2Ygb2JqID09PSBcInVuZGVmaW5lZFwiID8gXCJ1bmRlZmluZWRcIiA6IF90eXBlb2Yob2JqKTtcbn07IiwiLyohXG4gKiBCb3dzZXIgLSBhIGJyb3dzZXIgZGV0ZWN0b3JcbiAqIGh0dHBzOi8vZ2l0aHViLmNvbS9kZWQvYm93c2VyXG4gKiBNSVQgTGljZW5zZSB8IChjKSBEdXN0aW4gRGlheiAyMDE1XG4gKi9cblxuIWZ1bmN0aW9uIChyb290LCBuYW1lLCBkZWZpbml0aW9uKSB7XG4gIGlmICh0eXBlb2YgbW9kdWxlICE9ICd1bmRlZmluZWQnICYmIG1vZHVsZS5leHBvcnRzKSBtb2R1bGUuZXhwb3J0cyA9IGRlZmluaXRpb24oKVxuICBlbHNlIGlmICh0eXBlb2YgZGVmaW5lID09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCkgZGVmaW5lKG5hbWUsIGRlZmluaXRpb24pXG4gIGVsc2Ugcm9vdFtuYW1lXSA9IGRlZmluaXRpb24oKVxufSh0aGlzLCAnYm93c2VyJywgZnVuY3Rpb24gKCkge1xuICAvKipcbiAgICAqIFNlZSB1c2VyYWdlbnRzLmpzIGZvciBleGFtcGxlcyBvZiBuYXZpZ2F0b3IudXNlckFnZW50XG4gICAgKi9cblxuICB2YXIgdCA9IHRydWVcblxuICBmdW5jdGlvbiBkZXRlY3QodWEpIHtcblxuICAgIGZ1bmN0aW9uIGdldEZpcnN0TWF0Y2gocmVnZXgpIHtcbiAgICAgIHZhciBtYXRjaCA9IHVhLm1hdGNoKHJlZ2V4KTtcbiAgICAgIHJldHVybiAobWF0Y2ggJiYgbWF0Y2gubGVuZ3RoID4gMSAmJiBtYXRjaFsxXSkgfHwgJyc7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZ2V0U2Vjb25kTWF0Y2gocmVnZXgpIHtcbiAgICAgIHZhciBtYXRjaCA9IHVhLm1hdGNoKHJlZ2V4KTtcbiAgICAgIHJldHVybiAobWF0Y2ggJiYgbWF0Y2gubGVuZ3RoID4gMSAmJiBtYXRjaFsyXSkgfHwgJyc7XG4gICAgfVxuXG4gICAgdmFyIGlvc2RldmljZSA9IGdldEZpcnN0TWF0Y2goLyhpcG9kfGlwaG9uZXxpcGFkKS9pKS50b0xvd2VyQ2FzZSgpXG4gICAgICAsIGxpa2VBbmRyb2lkID0gL2xpa2UgYW5kcm9pZC9pLnRlc3QodWEpXG4gICAgICAsIGFuZHJvaWQgPSAhbGlrZUFuZHJvaWQgJiYgL2FuZHJvaWQvaS50ZXN0KHVhKVxuICAgICAgLCBuZXh1c01vYmlsZSA9IC9uZXh1c1xccypbMC02XVxccyovaS50ZXN0KHVhKVxuICAgICAgLCBuZXh1c1RhYmxldCA9ICFuZXh1c01vYmlsZSAmJiAvbmV4dXNcXHMqWzAtOV0rL2kudGVzdCh1YSlcbiAgICAgICwgY2hyb21lb3MgPSAvQ3JPUy8udGVzdCh1YSlcbiAgICAgICwgc2lsayA9IC9zaWxrL2kudGVzdCh1YSlcbiAgICAgICwgc2FpbGZpc2ggPSAvc2FpbGZpc2gvaS50ZXN0KHVhKVxuICAgICAgLCB0aXplbiA9IC90aXplbi9pLnRlc3QodWEpXG4gICAgICAsIHdlYm9zID0gLyh3ZWJ8aHB3KW9zL2kudGVzdCh1YSlcbiAgICAgICwgd2luZG93c3Bob25lID0gL3dpbmRvd3MgcGhvbmUvaS50ZXN0KHVhKVxuICAgICAgLCBzYW1zdW5nQnJvd3NlciA9IC9TYW1zdW5nQnJvd3Nlci9pLnRlc3QodWEpXG4gICAgICAsIHdpbmRvd3MgPSAhd2luZG93c3Bob25lICYmIC93aW5kb3dzL2kudGVzdCh1YSlcbiAgICAgICwgbWFjID0gIWlvc2RldmljZSAmJiAhc2lsayAmJiAvbWFjaW50b3NoL2kudGVzdCh1YSlcbiAgICAgICwgbGludXggPSAhYW5kcm9pZCAmJiAhc2FpbGZpc2ggJiYgIXRpemVuICYmICF3ZWJvcyAmJiAvbGludXgvaS50ZXN0KHVhKVxuICAgICAgLCBlZGdlVmVyc2lvbiA9IGdldEZpcnN0TWF0Y2goL2VkZ2VcXC8oXFxkKyhcXC5cXGQrKT8pL2kpXG4gICAgICAsIHZlcnNpb25JZGVudGlmaWVyID0gZ2V0Rmlyc3RNYXRjaCgvdmVyc2lvblxcLyhcXGQrKFxcLlxcZCspPykvaSlcbiAgICAgICwgdGFibGV0ID0gL3RhYmxldC9pLnRlc3QodWEpICYmICEvdGFibGV0IHBjL2kudGVzdCh1YSlcbiAgICAgICwgbW9iaWxlID0gIXRhYmxldCAmJiAvW14tXW1vYmkvaS50ZXN0KHVhKVxuICAgICAgLCB4Ym94ID0gL3hib3gvaS50ZXN0KHVhKVxuICAgICAgLCByZXN1bHRcblxuICAgIGlmICgvb3BlcmEvaS50ZXN0KHVhKSkge1xuICAgICAgLy8gIGFuIG9sZCBPcGVyYVxuICAgICAgcmVzdWx0ID0ge1xuICAgICAgICBuYW1lOiAnT3BlcmEnXG4gICAgICAsIG9wZXJhOiB0XG4gICAgICAsIHZlcnNpb246IHZlcnNpb25JZGVudGlmaWVyIHx8IGdldEZpcnN0TWF0Y2goLyg/Om9wZXJhfG9wcnxvcGlvcylbXFxzXFwvXShcXGQrKFxcLlxcZCspPykvaSlcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKC9vcHJ8b3Bpb3MvaS50ZXN0KHVhKSkge1xuICAgICAgLy8gYSBuZXcgT3BlcmFcbiAgICAgIHJlc3VsdCA9IHtcbiAgICAgICAgbmFtZTogJ09wZXJhJ1xuICAgICAgICAsIG9wZXJhOiB0XG4gICAgICAgICwgdmVyc2lvbjogZ2V0Rmlyc3RNYXRjaCgvKD86b3ByfG9waW9zKVtcXHNcXC9dKFxcZCsoXFwuXFxkKyk/KS9pKSB8fCB2ZXJzaW9uSWRlbnRpZmllclxuICAgICAgfVxuICAgIH1cbiAgICBlbHNlIGlmICgvU2Ftc3VuZ0Jyb3dzZXIvaS50ZXN0KHVhKSkge1xuICAgICAgcmVzdWx0ID0ge1xuICAgICAgICBuYW1lOiAnU2Ftc3VuZyBJbnRlcm5ldCBmb3IgQW5kcm9pZCdcbiAgICAgICAgLCBzYW1zdW5nQnJvd3NlcjogdFxuICAgICAgICAsIHZlcnNpb246IHZlcnNpb25JZGVudGlmaWVyIHx8IGdldEZpcnN0TWF0Y2goLyg/OlNhbXN1bmdCcm93c2VyKVtcXHNcXC9dKFxcZCsoXFwuXFxkKyk/KS9pKVxuICAgICAgfVxuICAgIH1cbiAgICBlbHNlIGlmICgvY29hc3QvaS50ZXN0KHVhKSkge1xuICAgICAgcmVzdWx0ID0ge1xuICAgICAgICBuYW1lOiAnT3BlcmEgQ29hc3QnXG4gICAgICAgICwgY29hc3Q6IHRcbiAgICAgICAgLCB2ZXJzaW9uOiB2ZXJzaW9uSWRlbnRpZmllciB8fCBnZXRGaXJzdE1hdGNoKC8oPzpjb2FzdClbXFxzXFwvXShcXGQrKFxcLlxcZCspPykvaSlcbiAgICAgIH1cbiAgICB9XG4gICAgZWxzZSBpZiAoL3lhYnJvd3Nlci9pLnRlc3QodWEpKSB7XG4gICAgICByZXN1bHQgPSB7XG4gICAgICAgIG5hbWU6ICdZYW5kZXggQnJvd3NlcidcbiAgICAgICwgeWFuZGV4YnJvd3NlcjogdFxuICAgICAgLCB2ZXJzaW9uOiB2ZXJzaW9uSWRlbnRpZmllciB8fCBnZXRGaXJzdE1hdGNoKC8oPzp5YWJyb3dzZXIpW1xcc1xcL10oXFxkKyhcXC5cXGQrKT8pL2kpXG4gICAgICB9XG4gICAgfVxuICAgIGVsc2UgaWYgKC91Y2Jyb3dzZXIvaS50ZXN0KHVhKSkge1xuICAgICAgcmVzdWx0ID0ge1xuICAgICAgICAgIG5hbWU6ICdVQyBCcm93c2VyJ1xuICAgICAgICAsIHVjYnJvd3NlcjogdFxuICAgICAgICAsIHZlcnNpb246IGdldEZpcnN0TWF0Y2goLyg/OnVjYnJvd3NlcilbXFxzXFwvXShcXGQrKD86XFwuXFxkKykrKS9pKVxuICAgICAgfVxuICAgIH1cbiAgICBlbHNlIGlmICgvbXhpb3MvaS50ZXN0KHVhKSkge1xuICAgICAgcmVzdWx0ID0ge1xuICAgICAgICBuYW1lOiAnTWF4dGhvbidcbiAgICAgICAgLCBtYXh0aG9uOiB0XG4gICAgICAgICwgdmVyc2lvbjogZ2V0Rmlyc3RNYXRjaCgvKD86bXhpb3MpW1xcc1xcL10oXFxkKyg/OlxcLlxcZCspKykvaSlcbiAgICAgIH1cbiAgICB9XG4gICAgZWxzZSBpZiAoL2VwaXBoYW55L2kudGVzdCh1YSkpIHtcbiAgICAgIHJlc3VsdCA9IHtcbiAgICAgICAgbmFtZTogJ0VwaXBoYW55J1xuICAgICAgICAsIGVwaXBoYW55OiB0XG4gICAgICAgICwgdmVyc2lvbjogZ2V0Rmlyc3RNYXRjaCgvKD86ZXBpcGhhbnkpW1xcc1xcL10oXFxkKyg/OlxcLlxcZCspKykvaSlcbiAgICAgIH1cbiAgICB9XG4gICAgZWxzZSBpZiAoL3B1ZmZpbi9pLnRlc3QodWEpKSB7XG4gICAgICByZXN1bHQgPSB7XG4gICAgICAgIG5hbWU6ICdQdWZmaW4nXG4gICAgICAgICwgcHVmZmluOiB0XG4gICAgICAgICwgdmVyc2lvbjogZ2V0Rmlyc3RNYXRjaCgvKD86cHVmZmluKVtcXHNcXC9dKFxcZCsoPzpcXC5cXGQrKT8pL2kpXG4gICAgICB9XG4gICAgfVxuICAgIGVsc2UgaWYgKC9zbGVpcG5pci9pLnRlc3QodWEpKSB7XG4gICAgICByZXN1bHQgPSB7XG4gICAgICAgIG5hbWU6ICdTbGVpcG5pcidcbiAgICAgICAgLCBzbGVpcG5pcjogdFxuICAgICAgICAsIHZlcnNpb246IGdldEZpcnN0TWF0Y2goLyg/OnNsZWlwbmlyKVtcXHNcXC9dKFxcZCsoPzpcXC5cXGQrKSspL2kpXG4gICAgICB9XG4gICAgfVxuICAgIGVsc2UgaWYgKC9rLW1lbGVvbi9pLnRlc3QodWEpKSB7XG4gICAgICByZXN1bHQgPSB7XG4gICAgICAgIG5hbWU6ICdLLU1lbGVvbidcbiAgICAgICAgLCBrTWVsZW9uOiB0XG4gICAgICAgICwgdmVyc2lvbjogZ2V0Rmlyc3RNYXRjaCgvKD86ay1tZWxlb24pW1xcc1xcL10oXFxkKyg/OlxcLlxcZCspKykvaSlcbiAgICAgIH1cbiAgICB9XG4gICAgZWxzZSBpZiAod2luZG93c3Bob25lKSB7XG4gICAgICByZXN1bHQgPSB7XG4gICAgICAgIG5hbWU6ICdXaW5kb3dzIFBob25lJ1xuICAgICAgLCB3aW5kb3dzcGhvbmU6IHRcbiAgICAgIH1cbiAgICAgIGlmIChlZGdlVmVyc2lvbikge1xuICAgICAgICByZXN1bHQubXNlZGdlID0gdFxuICAgICAgICByZXN1bHQudmVyc2lvbiA9IGVkZ2VWZXJzaW9uXG4gICAgICB9XG4gICAgICBlbHNlIHtcbiAgICAgICAgcmVzdWx0Lm1zaWUgPSB0XG4gICAgICAgIHJlc3VsdC52ZXJzaW9uID0gZ2V0Rmlyc3RNYXRjaCgvaWVtb2JpbGVcXC8oXFxkKyhcXC5cXGQrKT8pL2kpXG4gICAgICB9XG4gICAgfVxuICAgIGVsc2UgaWYgKC9tc2llfHRyaWRlbnQvaS50ZXN0KHVhKSkge1xuICAgICAgcmVzdWx0ID0ge1xuICAgICAgICBuYW1lOiAnSW50ZXJuZXQgRXhwbG9yZXInXG4gICAgICAsIG1zaWU6IHRcbiAgICAgICwgdmVyc2lvbjogZ2V0Rmlyc3RNYXRjaCgvKD86bXNpZSB8cnY6KShcXGQrKFxcLlxcZCspPykvaSlcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKGNocm9tZW9zKSB7XG4gICAgICByZXN1bHQgPSB7XG4gICAgICAgIG5hbWU6ICdDaHJvbWUnXG4gICAgICAsIGNocm9tZW9zOiB0XG4gICAgICAsIGNocm9tZUJvb2s6IHRcbiAgICAgICwgY2hyb21lOiB0XG4gICAgICAsIHZlcnNpb246IGdldEZpcnN0TWF0Y2goLyg/OmNocm9tZXxjcmlvc3xjcm1vKVxcLyhcXGQrKFxcLlxcZCspPykvaSlcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKC9jaHJvbWUuKz8gZWRnZS9pLnRlc3QodWEpKSB7XG4gICAgICByZXN1bHQgPSB7XG4gICAgICAgIG5hbWU6ICdNaWNyb3NvZnQgRWRnZSdcbiAgICAgICwgbXNlZGdlOiB0XG4gICAgICAsIHZlcnNpb246IGVkZ2VWZXJzaW9uXG4gICAgICB9XG4gICAgfVxuICAgIGVsc2UgaWYgKC92aXZhbGRpL2kudGVzdCh1YSkpIHtcbiAgICAgIHJlc3VsdCA9IHtcbiAgICAgICAgbmFtZTogJ1ZpdmFsZGknXG4gICAgICAgICwgdml2YWxkaTogdFxuICAgICAgICAsIHZlcnNpb246IGdldEZpcnN0TWF0Y2goL3ZpdmFsZGlcXC8oXFxkKyhcXC5cXGQrKT8pL2kpIHx8IHZlcnNpb25JZGVudGlmaWVyXG4gICAgICB9XG4gICAgfVxuICAgIGVsc2UgaWYgKHNhaWxmaXNoKSB7XG4gICAgICByZXN1bHQgPSB7XG4gICAgICAgIG5hbWU6ICdTYWlsZmlzaCdcbiAgICAgICwgc2FpbGZpc2g6IHRcbiAgICAgICwgdmVyc2lvbjogZ2V0Rmlyc3RNYXRjaCgvc2FpbGZpc2hcXHM/YnJvd3NlclxcLyhcXGQrKFxcLlxcZCspPykvaSlcbiAgICAgIH1cbiAgICB9XG4gICAgZWxzZSBpZiAoL3NlYW1vbmtleVxcLy9pLnRlc3QodWEpKSB7XG4gICAgICByZXN1bHQgPSB7XG4gICAgICAgIG5hbWU6ICdTZWFNb25rZXknXG4gICAgICAsIHNlYW1vbmtleTogdFxuICAgICAgLCB2ZXJzaW9uOiBnZXRGaXJzdE1hdGNoKC9zZWFtb25rZXlcXC8oXFxkKyhcXC5cXGQrKT8pL2kpXG4gICAgICB9XG4gICAgfVxuICAgIGVsc2UgaWYgKC9maXJlZm94fGljZXdlYXNlbHxmeGlvcy9pLnRlc3QodWEpKSB7XG4gICAgICByZXN1bHQgPSB7XG4gICAgICAgIG5hbWU6ICdGaXJlZm94J1xuICAgICAgLCBmaXJlZm94OiB0XG4gICAgICAsIHZlcnNpb246IGdldEZpcnN0TWF0Y2goLyg/OmZpcmVmb3h8aWNld2Vhc2VsfGZ4aW9zKVsgXFwvXShcXGQrKFxcLlxcZCspPykvaSlcbiAgICAgIH1cbiAgICAgIGlmICgvXFwoKG1vYmlsZXx0YWJsZXQpO1teXFwpXSpydjpbXFxkXFwuXStcXCkvaS50ZXN0KHVhKSkge1xuICAgICAgICByZXN1bHQuZmlyZWZveG9zID0gdFxuICAgICAgfVxuICAgIH1cbiAgICBlbHNlIGlmIChzaWxrKSB7XG4gICAgICByZXN1bHQgPSAge1xuICAgICAgICBuYW1lOiAnQW1hem9uIFNpbGsnXG4gICAgICAsIHNpbGs6IHRcbiAgICAgICwgdmVyc2lvbiA6IGdldEZpcnN0TWF0Y2goL3NpbGtcXC8oXFxkKyhcXC5cXGQrKT8pL2kpXG4gICAgICB9XG4gICAgfVxuICAgIGVsc2UgaWYgKC9waGFudG9tL2kudGVzdCh1YSkpIHtcbiAgICAgIHJlc3VsdCA9IHtcbiAgICAgICAgbmFtZTogJ1BoYW50b21KUydcbiAgICAgICwgcGhhbnRvbTogdFxuICAgICAgLCB2ZXJzaW9uOiBnZXRGaXJzdE1hdGNoKC9waGFudG9tanNcXC8oXFxkKyhcXC5cXGQrKT8pL2kpXG4gICAgICB9XG4gICAgfVxuICAgIGVsc2UgaWYgKC9zbGltZXJqcy9pLnRlc3QodWEpKSB7XG4gICAgICByZXN1bHQgPSB7XG4gICAgICAgIG5hbWU6ICdTbGltZXJKUydcbiAgICAgICAgLCBzbGltZXI6IHRcbiAgICAgICAgLCB2ZXJzaW9uOiBnZXRGaXJzdE1hdGNoKC9zbGltZXJqc1xcLyhcXGQrKFxcLlxcZCspPykvaSlcbiAgICAgIH1cbiAgICB9XG4gICAgZWxzZSBpZiAoL2JsYWNrYmVycnl8XFxiYmJcXGQrL2kudGVzdCh1YSkgfHwgL3JpbVxcc3RhYmxldC9pLnRlc3QodWEpKSB7XG4gICAgICByZXN1bHQgPSB7XG4gICAgICAgIG5hbWU6ICdCbGFja0JlcnJ5J1xuICAgICAgLCBibGFja2JlcnJ5OiB0XG4gICAgICAsIHZlcnNpb246IHZlcnNpb25JZGVudGlmaWVyIHx8IGdldEZpcnN0TWF0Y2goL2JsYWNrYmVycnlbXFxkXStcXC8oXFxkKyhcXC5cXGQrKT8pL2kpXG4gICAgICB9XG4gICAgfVxuICAgIGVsc2UgaWYgKHdlYm9zKSB7XG4gICAgICByZXN1bHQgPSB7XG4gICAgICAgIG5hbWU6ICdXZWJPUydcbiAgICAgICwgd2Vib3M6IHRcbiAgICAgICwgdmVyc2lvbjogdmVyc2lvbklkZW50aWZpZXIgfHwgZ2V0Rmlyc3RNYXRjaCgvdyg/OmViKT9vc2Jyb3dzZXJcXC8oXFxkKyhcXC5cXGQrKT8pL2kpXG4gICAgICB9O1xuICAgICAgL3RvdWNocGFkXFwvL2kudGVzdCh1YSkgJiYgKHJlc3VsdC50b3VjaHBhZCA9IHQpXG4gICAgfVxuICAgIGVsc2UgaWYgKC9iYWRhL2kudGVzdCh1YSkpIHtcbiAgICAgIHJlc3VsdCA9IHtcbiAgICAgICAgbmFtZTogJ0JhZGEnXG4gICAgICAsIGJhZGE6IHRcbiAgICAgICwgdmVyc2lvbjogZ2V0Rmlyc3RNYXRjaCgvZG9sZmluXFwvKFxcZCsoXFwuXFxkKyk/KS9pKVxuICAgICAgfTtcbiAgICB9XG4gICAgZWxzZSBpZiAodGl6ZW4pIHtcbiAgICAgIHJlc3VsdCA9IHtcbiAgICAgICAgbmFtZTogJ1RpemVuJ1xuICAgICAgLCB0aXplbjogdFxuICAgICAgLCB2ZXJzaW9uOiBnZXRGaXJzdE1hdGNoKC8oPzp0aXplblxccz8pP2Jyb3dzZXJcXC8oXFxkKyhcXC5cXGQrKT8pL2kpIHx8IHZlcnNpb25JZGVudGlmaWVyXG4gICAgICB9O1xuICAgIH1cbiAgICBlbHNlIGlmICgvcXVwemlsbGEvaS50ZXN0KHVhKSkge1xuICAgICAgcmVzdWx0ID0ge1xuICAgICAgICBuYW1lOiAnUXVwWmlsbGEnXG4gICAgICAgICwgcXVwemlsbGE6IHRcbiAgICAgICAgLCB2ZXJzaW9uOiBnZXRGaXJzdE1hdGNoKC8oPzpxdXB6aWxsYSlbXFxzXFwvXShcXGQrKD86XFwuXFxkKykrKS9pKSB8fCB2ZXJzaW9uSWRlbnRpZmllclxuICAgICAgfVxuICAgIH1cbiAgICBlbHNlIGlmICgvY2hyb21pdW0vaS50ZXN0KHVhKSkge1xuICAgICAgcmVzdWx0ID0ge1xuICAgICAgICBuYW1lOiAnQ2hyb21pdW0nXG4gICAgICAgICwgY2hyb21pdW06IHRcbiAgICAgICAgLCB2ZXJzaW9uOiBnZXRGaXJzdE1hdGNoKC8oPzpjaHJvbWl1bSlbXFxzXFwvXShcXGQrKD86XFwuXFxkKyk/KS9pKSB8fCB2ZXJzaW9uSWRlbnRpZmllclxuICAgICAgfVxuICAgIH1cbiAgICBlbHNlIGlmICgvY2hyb21lfGNyaW9zfGNybW8vaS50ZXN0KHVhKSkge1xuICAgICAgcmVzdWx0ID0ge1xuICAgICAgICBuYW1lOiAnQ2hyb21lJ1xuICAgICAgICAsIGNocm9tZTogdFxuICAgICAgICAsIHZlcnNpb246IGdldEZpcnN0TWF0Y2goLyg/OmNocm9tZXxjcmlvc3xjcm1vKVxcLyhcXGQrKFxcLlxcZCspPykvaSlcbiAgICAgIH1cbiAgICB9XG4gICAgZWxzZSBpZiAoYW5kcm9pZCkge1xuICAgICAgcmVzdWx0ID0ge1xuICAgICAgICBuYW1lOiAnQW5kcm9pZCdcbiAgICAgICAgLCB2ZXJzaW9uOiB2ZXJzaW9uSWRlbnRpZmllclxuICAgICAgfVxuICAgIH1cbiAgICBlbHNlIGlmICgvc2FmYXJpfGFwcGxld2Via2l0L2kudGVzdCh1YSkpIHtcbiAgICAgIHJlc3VsdCA9IHtcbiAgICAgICAgbmFtZTogJ1NhZmFyaSdcbiAgICAgICwgc2FmYXJpOiB0XG4gICAgICB9XG4gICAgICBpZiAodmVyc2lvbklkZW50aWZpZXIpIHtcbiAgICAgICAgcmVzdWx0LnZlcnNpb24gPSB2ZXJzaW9uSWRlbnRpZmllclxuICAgICAgfVxuICAgIH1cbiAgICBlbHNlIGlmIChpb3NkZXZpY2UpIHtcbiAgICAgIHJlc3VsdCA9IHtcbiAgICAgICAgbmFtZSA6IGlvc2RldmljZSA9PSAnaXBob25lJyA/ICdpUGhvbmUnIDogaW9zZGV2aWNlID09ICdpcGFkJyA/ICdpUGFkJyA6ICdpUG9kJ1xuICAgICAgfVxuICAgICAgLy8gV1RGOiB2ZXJzaW9uIGlzIG5vdCBwYXJ0IG9mIHVzZXIgYWdlbnQgaW4gd2ViIGFwcHNcbiAgICAgIGlmICh2ZXJzaW9uSWRlbnRpZmllcikge1xuICAgICAgICByZXN1bHQudmVyc2lvbiA9IHZlcnNpb25JZGVudGlmaWVyXG4gICAgICB9XG4gICAgfVxuICAgIGVsc2UgaWYoL2dvb2dsZWJvdC9pLnRlc3QodWEpKSB7XG4gICAgICByZXN1bHQgPSB7XG4gICAgICAgIG5hbWU6ICdHb29nbGVib3QnXG4gICAgICAsIGdvb2dsZWJvdDogdFxuICAgICAgLCB2ZXJzaW9uOiBnZXRGaXJzdE1hdGNoKC9nb29nbGVib3RcXC8oXFxkKyhcXC5cXGQrKSkvaSkgfHwgdmVyc2lvbklkZW50aWZpZXJcbiAgICAgIH1cbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICByZXN1bHQgPSB7XG4gICAgICAgIG5hbWU6IGdldEZpcnN0TWF0Y2goL14oLiopXFwvKC4qKSAvKSxcbiAgICAgICAgdmVyc2lvbjogZ2V0U2Vjb25kTWF0Y2goL14oLiopXFwvKC4qKSAvKVxuICAgICB9O1xuICAgfVxuXG4gICAgLy8gc2V0IHdlYmtpdCBvciBnZWNrbyBmbGFnIGZvciBicm93c2VycyBiYXNlZCBvbiB0aGVzZSBlbmdpbmVzXG4gICAgaWYgKCFyZXN1bHQubXNlZGdlICYmIC8oYXBwbGUpP3dlYmtpdC9pLnRlc3QodWEpKSB7XG4gICAgICBpZiAoLyhhcHBsZSk/d2Via2l0XFwvNTM3XFwuMzYvaS50ZXN0KHVhKSkge1xuICAgICAgICByZXN1bHQubmFtZSA9IHJlc3VsdC5uYW1lIHx8IFwiQmxpbmtcIlxuICAgICAgICByZXN1bHQuYmxpbmsgPSB0XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXN1bHQubmFtZSA9IHJlc3VsdC5uYW1lIHx8IFwiV2Via2l0XCJcbiAgICAgICAgcmVzdWx0LndlYmtpdCA9IHRcbiAgICAgIH1cbiAgICAgIGlmICghcmVzdWx0LnZlcnNpb24gJiYgdmVyc2lvbklkZW50aWZpZXIpIHtcbiAgICAgICAgcmVzdWx0LnZlcnNpb24gPSB2ZXJzaW9uSWRlbnRpZmllclxuICAgICAgfVxuICAgIH0gZWxzZSBpZiAoIXJlc3VsdC5vcGVyYSAmJiAvZ2Vja29cXC8vaS50ZXN0KHVhKSkge1xuICAgICAgcmVzdWx0Lm5hbWUgPSByZXN1bHQubmFtZSB8fCBcIkdlY2tvXCJcbiAgICAgIHJlc3VsdC5nZWNrbyA9IHRcbiAgICAgIHJlc3VsdC52ZXJzaW9uID0gcmVzdWx0LnZlcnNpb24gfHwgZ2V0Rmlyc3RNYXRjaCgvZ2Vja29cXC8oXFxkKyhcXC5cXGQrKT8pL2kpXG4gICAgfVxuXG4gICAgLy8gc2V0IE9TIGZsYWdzIGZvciBwbGF0Zm9ybXMgdGhhdCBoYXZlIG11bHRpcGxlIGJyb3dzZXJzXG4gICAgaWYgKCFyZXN1bHQud2luZG93c3Bob25lICYmICFyZXN1bHQubXNlZGdlICYmIChhbmRyb2lkIHx8IHJlc3VsdC5zaWxrKSkge1xuICAgICAgcmVzdWx0LmFuZHJvaWQgPSB0XG4gICAgfSBlbHNlIGlmICghcmVzdWx0LndpbmRvd3NwaG9uZSAmJiAhcmVzdWx0Lm1zZWRnZSAmJiBpb3NkZXZpY2UpIHtcbiAgICAgIHJlc3VsdFtpb3NkZXZpY2VdID0gdFxuICAgICAgcmVzdWx0LmlvcyA9IHRcbiAgICB9IGVsc2UgaWYgKG1hYykge1xuICAgICAgcmVzdWx0Lm1hYyA9IHRcbiAgICB9IGVsc2UgaWYgKHhib3gpIHtcbiAgICAgIHJlc3VsdC54Ym94ID0gdFxuICAgIH0gZWxzZSBpZiAod2luZG93cykge1xuICAgICAgcmVzdWx0LndpbmRvd3MgPSB0XG4gICAgfSBlbHNlIGlmIChsaW51eCkge1xuICAgICAgcmVzdWx0LmxpbnV4ID0gdFxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGdldFdpbmRvd3NWZXJzaW9uIChzKSB7XG4gICAgICBzd2l0Y2ggKHMpIHtcbiAgICAgICAgY2FzZSAnTlQnOiByZXR1cm4gJ05UJ1xuICAgICAgICBjYXNlICdYUCc6IHJldHVybiAnWFAnXG4gICAgICAgIGNhc2UgJ05UIDUuMCc6IHJldHVybiAnMjAwMCdcbiAgICAgICAgY2FzZSAnTlQgNS4xJzogcmV0dXJuICdYUCdcbiAgICAgICAgY2FzZSAnTlQgNS4yJzogcmV0dXJuICcyMDAzJ1xuICAgICAgICBjYXNlICdOVCA2LjAnOiByZXR1cm4gJ1Zpc3RhJ1xuICAgICAgICBjYXNlICdOVCA2LjEnOiByZXR1cm4gJzcnXG4gICAgICAgIGNhc2UgJ05UIDYuMic6IHJldHVybiAnOCdcbiAgICAgICAgY2FzZSAnTlQgNi4zJzogcmV0dXJuICc4LjEnXG4gICAgICAgIGNhc2UgJ05UIDEwLjAnOiByZXR1cm4gJzEwJ1xuICAgICAgICBkZWZhdWx0OiByZXR1cm4gdW5kZWZpbmVkXG4gICAgICB9XG4gICAgfVxuICAgIFxuICAgIC8vIE9TIHZlcnNpb24gZXh0cmFjdGlvblxuICAgIHZhciBvc1ZlcnNpb24gPSAnJztcbiAgICBpZiAocmVzdWx0LndpbmRvd3MpIHtcbiAgICAgIG9zVmVyc2lvbiA9IGdldFdpbmRvd3NWZXJzaW9uKGdldEZpcnN0TWF0Y2goL1dpbmRvd3MgKChOVHxYUCkoIFxcZFxcZD8uXFxkKT8pL2kpKVxuICAgIH0gZWxzZSBpZiAocmVzdWx0LndpbmRvd3NwaG9uZSkge1xuICAgICAgb3NWZXJzaW9uID0gZ2V0Rmlyc3RNYXRjaCgvd2luZG93cyBwaG9uZSAoPzpvcyk/XFxzPyhcXGQrKFxcLlxcZCspKikvaSk7XG4gICAgfSBlbHNlIGlmIChyZXN1bHQubWFjKSB7XG4gICAgICBvc1ZlcnNpb24gPSBnZXRGaXJzdE1hdGNoKC9NYWMgT1MgWCAoXFxkKyhbX1xcLlxcc11cXGQrKSopL2kpO1xuICAgICAgb3NWZXJzaW9uID0gb3NWZXJzaW9uLnJlcGxhY2UoL1tfXFxzXS9nLCAnLicpO1xuICAgIH0gZWxzZSBpZiAoaW9zZGV2aWNlKSB7XG4gICAgICBvc1ZlcnNpb24gPSBnZXRGaXJzdE1hdGNoKC9vcyAoXFxkKyhbX1xcc11cXGQrKSopIGxpa2UgbWFjIG9zIHgvaSk7XG4gICAgICBvc1ZlcnNpb24gPSBvc1ZlcnNpb24ucmVwbGFjZSgvW19cXHNdL2csICcuJyk7XG4gICAgfSBlbHNlIGlmIChhbmRyb2lkKSB7XG4gICAgICBvc1ZlcnNpb24gPSBnZXRGaXJzdE1hdGNoKC9hbmRyb2lkWyBcXC8tXShcXGQrKFxcLlxcZCspKikvaSk7XG4gICAgfSBlbHNlIGlmIChyZXN1bHQud2Vib3MpIHtcbiAgICAgIG9zVmVyc2lvbiA9IGdldEZpcnN0TWF0Y2goLyg/OndlYnxocHcpb3NcXC8oXFxkKyhcXC5cXGQrKSopL2kpO1xuICAgIH0gZWxzZSBpZiAocmVzdWx0LmJsYWNrYmVycnkpIHtcbiAgICAgIG9zVmVyc2lvbiA9IGdldEZpcnN0TWF0Y2goL3JpbVxcc3RhYmxldFxcc29zXFxzKFxcZCsoXFwuXFxkKykqKS9pKTtcbiAgICB9IGVsc2UgaWYgKHJlc3VsdC5iYWRhKSB7XG4gICAgICBvc1ZlcnNpb24gPSBnZXRGaXJzdE1hdGNoKC9iYWRhXFwvKFxcZCsoXFwuXFxkKykqKS9pKTtcbiAgICB9IGVsc2UgaWYgKHJlc3VsdC50aXplbikge1xuICAgICAgb3NWZXJzaW9uID0gZ2V0Rmlyc3RNYXRjaCgvdGl6ZW5bXFwvXFxzXShcXGQrKFxcLlxcZCspKikvaSk7XG4gICAgfVxuICAgIGlmIChvc1ZlcnNpb24pIHtcbiAgICAgIHJlc3VsdC5vc3ZlcnNpb24gPSBvc1ZlcnNpb247XG4gICAgfVxuXG4gICAgLy8gZGV2aWNlIHR5cGUgZXh0cmFjdGlvblxuICAgIHZhciBvc01ham9yVmVyc2lvbiA9ICFyZXN1bHQud2luZG93cyAmJiBvc1ZlcnNpb24uc3BsaXQoJy4nKVswXTtcbiAgICBpZiAoXG4gICAgICAgICB0YWJsZXRcbiAgICAgIHx8IG5leHVzVGFibGV0XG4gICAgICB8fCBpb3NkZXZpY2UgPT0gJ2lwYWQnXG4gICAgICB8fCAoYW5kcm9pZCAmJiAob3NNYWpvclZlcnNpb24gPT0gMyB8fCAob3NNYWpvclZlcnNpb24gPj0gNCAmJiAhbW9iaWxlKSkpXG4gICAgICB8fCByZXN1bHQuc2lsa1xuICAgICkge1xuICAgICAgcmVzdWx0LnRhYmxldCA9IHRcbiAgICB9IGVsc2UgaWYgKFxuICAgICAgICAgbW9iaWxlXG4gICAgICB8fCBpb3NkZXZpY2UgPT0gJ2lwaG9uZSdcbiAgICAgIHx8IGlvc2RldmljZSA9PSAnaXBvZCdcbiAgICAgIHx8IGFuZHJvaWRcbiAgICAgIHx8IG5leHVzTW9iaWxlXG4gICAgICB8fCByZXN1bHQuYmxhY2tiZXJyeVxuICAgICAgfHwgcmVzdWx0LndlYm9zXG4gICAgICB8fCByZXN1bHQuYmFkYVxuICAgICkge1xuICAgICAgcmVzdWx0Lm1vYmlsZSA9IHRcbiAgICB9XG5cbiAgICAvLyBHcmFkZWQgQnJvd3NlciBTdXBwb3J0XG4gICAgLy8gaHR0cDovL2RldmVsb3Blci55YWhvby5jb20veXVpL2FydGljbGVzL2dic1xuICAgIGlmIChyZXN1bHQubXNlZGdlIHx8XG4gICAgICAgIChyZXN1bHQubXNpZSAmJiByZXN1bHQudmVyc2lvbiA+PSAxMCkgfHxcbiAgICAgICAgKHJlc3VsdC55YW5kZXhicm93c2VyICYmIHJlc3VsdC52ZXJzaW9uID49IDE1KSB8fFxuXHRcdCAgICAocmVzdWx0LnZpdmFsZGkgJiYgcmVzdWx0LnZlcnNpb24gPj0gMS4wKSB8fFxuICAgICAgICAocmVzdWx0LmNocm9tZSAmJiByZXN1bHQudmVyc2lvbiA+PSAyMCkgfHxcbiAgICAgICAgKHJlc3VsdC5zYW1zdW5nQnJvd3NlciAmJiByZXN1bHQudmVyc2lvbiA+PSA0KSB8fFxuICAgICAgICAocmVzdWx0LmZpcmVmb3ggJiYgcmVzdWx0LnZlcnNpb24gPj0gMjAuMCkgfHxcbiAgICAgICAgKHJlc3VsdC5zYWZhcmkgJiYgcmVzdWx0LnZlcnNpb24gPj0gNikgfHxcbiAgICAgICAgKHJlc3VsdC5vcGVyYSAmJiByZXN1bHQudmVyc2lvbiA+PSAxMC4wKSB8fFxuICAgICAgICAocmVzdWx0LmlvcyAmJiByZXN1bHQub3N2ZXJzaW9uICYmIHJlc3VsdC5vc3ZlcnNpb24uc3BsaXQoXCIuXCIpWzBdID49IDYpIHx8XG4gICAgICAgIChyZXN1bHQuYmxhY2tiZXJyeSAmJiByZXN1bHQudmVyc2lvbiA+PSAxMC4xKVxuICAgICAgICB8fCAocmVzdWx0LmNocm9taXVtICYmIHJlc3VsdC52ZXJzaW9uID49IDIwKVxuICAgICAgICApIHtcbiAgICAgIHJlc3VsdC5hID0gdDtcbiAgICB9XG4gICAgZWxzZSBpZiAoKHJlc3VsdC5tc2llICYmIHJlc3VsdC52ZXJzaW9uIDwgMTApIHx8XG4gICAgICAgIChyZXN1bHQuY2hyb21lICYmIHJlc3VsdC52ZXJzaW9uIDwgMjApIHx8XG4gICAgICAgIChyZXN1bHQuZmlyZWZveCAmJiByZXN1bHQudmVyc2lvbiA8IDIwLjApIHx8XG4gICAgICAgIChyZXN1bHQuc2FmYXJpICYmIHJlc3VsdC52ZXJzaW9uIDwgNikgfHxcbiAgICAgICAgKHJlc3VsdC5vcGVyYSAmJiByZXN1bHQudmVyc2lvbiA8IDEwLjApIHx8XG4gICAgICAgIChyZXN1bHQuaW9zICYmIHJlc3VsdC5vc3ZlcnNpb24gJiYgcmVzdWx0Lm9zdmVyc2lvbi5zcGxpdChcIi5cIilbMF0gPCA2KVxuICAgICAgICB8fCAocmVzdWx0LmNocm9taXVtICYmIHJlc3VsdC52ZXJzaW9uIDwgMjApXG4gICAgICAgICkge1xuICAgICAgcmVzdWx0LmMgPSB0XG4gICAgfSBlbHNlIHJlc3VsdC54ID0gdFxuXG4gICAgcmV0dXJuIHJlc3VsdFxuICB9XG5cbiAgdmFyIGJvd3NlciA9IGRldGVjdCh0eXBlb2YgbmF2aWdhdG9yICE9PSAndW5kZWZpbmVkJyA/IG5hdmlnYXRvci51c2VyQWdlbnQgfHwgJycgOiAnJylcblxuICBib3dzZXIudGVzdCA9IGZ1bmN0aW9uIChicm93c2VyTGlzdCkge1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYnJvd3Nlckxpc3QubGVuZ3RoOyArK2kpIHtcbiAgICAgIHZhciBicm93c2VySXRlbSA9IGJyb3dzZXJMaXN0W2ldO1xuICAgICAgaWYgKHR5cGVvZiBicm93c2VySXRlbT09PSAnc3RyaW5nJykge1xuICAgICAgICBpZiAoYnJvd3Nlckl0ZW0gaW4gYm93c2VyKSB7XG4gICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCB2ZXJzaW9uIHByZWNpc2lvbnMgY291bnRcbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogICBnZXRWZXJzaW9uUHJlY2lzaW9uKFwiMS4xMC4zXCIpIC8vIDNcbiAgICpcbiAgICogQHBhcmFtICB7c3RyaW5nfSB2ZXJzaW9uXG4gICAqIEByZXR1cm4ge251bWJlcn1cbiAgICovXG4gIGZ1bmN0aW9uIGdldFZlcnNpb25QcmVjaXNpb24odmVyc2lvbikge1xuICAgIHJldHVybiB2ZXJzaW9uLnNwbGl0KFwiLlwiKS5sZW5ndGg7XG4gIH1cblxuICAvKipcbiAgICogQXJyYXk6Om1hcCBwb2x5ZmlsbFxuICAgKlxuICAgKiBAcGFyYW0gIHtBcnJheX0gYXJyXG4gICAqIEBwYXJhbSAge0Z1bmN0aW9ufSBpdGVyYXRvclxuICAgKiBAcmV0dXJuIHtBcnJheX1cbiAgICovXG4gIGZ1bmN0aW9uIG1hcChhcnIsIGl0ZXJhdG9yKSB7XG4gICAgdmFyIHJlc3VsdCA9IFtdLCBpO1xuICAgIGlmIChBcnJheS5wcm90b3R5cGUubWFwKSB7XG4gICAgICByZXR1cm4gQXJyYXkucHJvdG90eXBlLm1hcC5jYWxsKGFyciwgaXRlcmF0b3IpO1xuICAgIH1cbiAgICBmb3IgKGkgPSAwOyBpIDwgYXJyLmxlbmd0aDsgaSsrKSB7XG4gICAgICByZXN1bHQucHVzaChpdGVyYXRvcihhcnJbaV0pKTtcbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIC8qKlxuICAgKiBDYWxjdWxhdGUgYnJvd3NlciB2ZXJzaW9uIHdlaWdodFxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiAgIGNvbXBhcmVWZXJzaW9ucyhbJzEuMTAuMi4xJywgICcxLjguMi4xLjkwJ10pICAgIC8vIDFcbiAgICogICBjb21wYXJlVmVyc2lvbnMoWycxLjAxMC4yLjEnLCAnMS4wOS4yLjEuOTAnXSk7ICAvLyAxXG4gICAqICAgY29tcGFyZVZlcnNpb25zKFsnMS4xMC4yLjEnLCAgJzEuMTAuMi4xJ10pOyAgICAgLy8gMFxuICAgKiAgIGNvbXBhcmVWZXJzaW9ucyhbJzEuMTAuMi4xJywgICcxLjA4MDAuMiddKTsgICAgIC8vIC0xXG4gICAqXG4gICAqIEBwYXJhbSAge0FycmF5PFN0cmluZz59IHZlcnNpb25zIHZlcnNpb25zIHRvIGNvbXBhcmVcbiAgICogQHJldHVybiB7TnVtYmVyfSBjb21wYXJpc29uIHJlc3VsdFxuICAgKi9cbiAgZnVuY3Rpb24gY29tcGFyZVZlcnNpb25zKHZlcnNpb25zKSB7XG4gICAgLy8gMSkgZ2V0IGNvbW1vbiBwcmVjaXNpb24gZm9yIGJvdGggdmVyc2lvbnMsIGZvciBleGFtcGxlIGZvciBcIjEwLjBcIiBhbmQgXCI5XCIgaXQgc2hvdWxkIGJlIDJcbiAgICB2YXIgcHJlY2lzaW9uID0gTWF0aC5tYXgoZ2V0VmVyc2lvblByZWNpc2lvbih2ZXJzaW9uc1swXSksIGdldFZlcnNpb25QcmVjaXNpb24odmVyc2lvbnNbMV0pKTtcbiAgICB2YXIgY2h1bmtzID0gbWFwKHZlcnNpb25zLCBmdW5jdGlvbiAodmVyc2lvbikge1xuICAgICAgdmFyIGRlbHRhID0gcHJlY2lzaW9uIC0gZ2V0VmVyc2lvblByZWNpc2lvbih2ZXJzaW9uKTtcblxuICAgICAgLy8gMikgXCI5XCIgLT4gXCI5LjBcIiAoZm9yIHByZWNpc2lvbiA9IDIpXG4gICAgICB2ZXJzaW9uID0gdmVyc2lvbiArIG5ldyBBcnJheShkZWx0YSArIDEpLmpvaW4oXCIuMFwiKTtcblxuICAgICAgLy8gMykgXCI5LjBcIiAtPiBbXCIwMDAwMDAwMDBcIlwiLCBcIjAwMDAwMDAwOVwiXVxuICAgICAgcmV0dXJuIG1hcCh2ZXJzaW9uLnNwbGl0KFwiLlwiKSwgZnVuY3Rpb24gKGNodW5rKSB7XG4gICAgICAgIHJldHVybiBuZXcgQXJyYXkoMjAgLSBjaHVuay5sZW5ndGgpLmpvaW4oXCIwXCIpICsgY2h1bms7XG4gICAgICB9KS5yZXZlcnNlKCk7XG4gICAgfSk7XG5cbiAgICAvLyBpdGVyYXRlIGluIHJldmVyc2Ugb3JkZXIgYnkgcmV2ZXJzZWQgY2h1bmtzIGFycmF5XG4gICAgd2hpbGUgKC0tcHJlY2lzaW9uID49IDApIHtcbiAgICAgIC8vIDQpIGNvbXBhcmU6IFwiMDAwMDAwMDA5XCIgPiBcIjAwMDAwMDAxMFwiID0gZmFsc2UgKGJ1dCBcIjlcIiA+IFwiMTBcIiA9IHRydWUpXG4gICAgICBpZiAoY2h1bmtzWzBdW3ByZWNpc2lvbl0gPiBjaHVua3NbMV1bcHJlY2lzaW9uXSkge1xuICAgICAgICByZXR1cm4gMTtcbiAgICAgIH1cbiAgICAgIGVsc2UgaWYgKGNodW5rc1swXVtwcmVjaXNpb25dID09PSBjaHVua3NbMV1bcHJlY2lzaW9uXSkge1xuICAgICAgICBpZiAocHJlY2lzaW9uID09PSAwKSB7XG4gICAgICAgICAgLy8gYWxsIHZlcnNpb24gY2h1bmtzIGFyZSBzYW1lXG4gICAgICAgICAgcmV0dXJuIDA7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGVsc2Uge1xuICAgICAgICByZXR1cm4gLTE7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrIGlmIGJyb3dzZXIgaXMgdW5zdXBwb3J0ZWRcbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogICBib3dzZXIuaXNVbnN1cHBvcnRlZEJyb3dzZXIoe1xuICAgKiAgICAgbXNpZTogXCIxMFwiLFxuICAgKiAgICAgZmlyZWZveDogXCIyM1wiLFxuICAgKiAgICAgY2hyb21lOiBcIjI5XCIsXG4gICAqICAgICBzYWZhcmk6IFwiNS4xXCIsXG4gICAqICAgICBvcGVyYTogXCIxNlwiLFxuICAgKiAgICAgcGhhbnRvbTogXCI1MzRcIlxuICAgKiAgIH0pO1xuICAgKlxuICAgKiBAcGFyYW0gIHtPYmplY3R9ICBtaW5WZXJzaW9ucyBtYXAgb2YgbWluaW1hbCB2ZXJzaW9uIHRvIGJyb3dzZXJcbiAgICogQHBhcmFtICB7Qm9vbGVhbn0gW3N0cmljdE1vZGUgPSBmYWxzZV0gZmxhZyB0byByZXR1cm4gZmFsc2UgaWYgYnJvd3NlciB3YXNuJ3QgZm91bmQgaW4gbWFwXG4gICAqIEBwYXJhbSAge1N0cmluZ30gIFt1YV0gdXNlciBhZ2VudCBzdHJpbmdcbiAgICogQHJldHVybiB7Qm9vbGVhbn1cbiAgICovXG4gIGZ1bmN0aW9uIGlzVW5zdXBwb3J0ZWRCcm93c2VyKG1pblZlcnNpb25zLCBzdHJpY3RNb2RlLCB1YSkge1xuICAgIHZhciBfYm93c2VyID0gYm93c2VyO1xuXG4gICAgLy8gbWFrZSBzdHJpY3RNb2RlIHBhcmFtIG9wdGlvbmFsIHdpdGggdWEgcGFyYW0gdXNhZ2VcbiAgICBpZiAodHlwZW9mIHN0cmljdE1vZGUgPT09ICdzdHJpbmcnKSB7XG4gICAgICB1YSA9IHN0cmljdE1vZGU7XG4gICAgICBzdHJpY3RNb2RlID0gdm9pZCgwKTtcbiAgICB9XG5cbiAgICBpZiAoc3RyaWN0TW9kZSA9PT0gdm9pZCgwKSkge1xuICAgICAgc3RyaWN0TW9kZSA9IGZhbHNlO1xuICAgIH1cbiAgICBpZiAodWEpIHtcbiAgICAgIF9ib3dzZXIgPSBkZXRlY3QodWEpO1xuICAgIH1cblxuICAgIHZhciB2ZXJzaW9uID0gXCJcIiArIF9ib3dzZXIudmVyc2lvbjtcbiAgICBmb3IgKHZhciBicm93c2VyIGluIG1pblZlcnNpb25zKSB7XG4gICAgICBpZiAobWluVmVyc2lvbnMuaGFzT3duUHJvcGVydHkoYnJvd3NlcikpIHtcbiAgICAgICAgaWYgKF9ib3dzZXJbYnJvd3Nlcl0pIHtcbiAgICAgICAgICBpZiAodHlwZW9mIG1pblZlcnNpb25zW2Jyb3dzZXJdICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdCcm93c2VyIHZlcnNpb24gaW4gdGhlIG1pblZlcnNpb24gbWFwIHNob3VsZCBiZSBhIHN0cmluZzogJyArIGJyb3dzZXIgKyAnOiAnICsgU3RyaW5nKG1pblZlcnNpb25zKSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgLy8gYnJvd3NlciB2ZXJzaW9uIGFuZCBtaW4gc3VwcG9ydGVkIHZlcnNpb24uXG4gICAgICAgICAgcmV0dXJuIGNvbXBhcmVWZXJzaW9ucyhbdmVyc2lvbiwgbWluVmVyc2lvbnNbYnJvd3Nlcl1dKSA8IDA7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gc3RyaWN0TW9kZTsgLy8gbm90IGZvdW5kXG4gIH1cblxuICAvKipcbiAgICogQ2hlY2sgaWYgYnJvd3NlciBpcyBzdXBwb3J0ZWRcbiAgICpcbiAgICogQHBhcmFtICB7T2JqZWN0fSBtaW5WZXJzaW9ucyBtYXAgb2YgbWluaW1hbCB2ZXJzaW9uIHRvIGJyb3dzZXJcbiAgICogQHBhcmFtICB7Qm9vbGVhbn0gW3N0cmljdE1vZGUgPSBmYWxzZV0gZmxhZyB0byByZXR1cm4gZmFsc2UgaWYgYnJvd3NlciB3YXNuJ3QgZm91bmQgaW4gbWFwXG4gICAqIEBwYXJhbSAge1N0cmluZ30gIFt1YV0gdXNlciBhZ2VudCBzdHJpbmdcbiAgICogQHJldHVybiB7Qm9vbGVhbn1cbiAgICovXG4gIGZ1bmN0aW9uIGNoZWNrKG1pblZlcnNpb25zLCBzdHJpY3RNb2RlLCB1YSkge1xuICAgIHJldHVybiAhaXNVbnN1cHBvcnRlZEJyb3dzZXIobWluVmVyc2lvbnMsIHN0cmljdE1vZGUsIHVhKTtcbiAgfVxuXG4gIGJvd3Nlci5pc1Vuc3VwcG9ydGVkQnJvd3NlciA9IGlzVW5zdXBwb3J0ZWRCcm93c2VyO1xuICBib3dzZXIuY29tcGFyZVZlcnNpb25zID0gY29tcGFyZVZlcnNpb25zO1xuICBib3dzZXIuY2hlY2sgPSBjaGVjaztcblxuICAvKlxuICAgKiBTZXQgb3VyIGRldGVjdCBtZXRob2QgdG8gdGhlIG1haW4gYm93c2VyIG9iamVjdCBzbyB3ZSBjYW5cbiAgICogcmV1c2UgaXQgdG8gdGVzdCBvdGhlciB1c2VyIGFnZW50cy5cbiAgICogVGhpcyBpcyBuZWVkZWQgdG8gaW1wbGVtZW50IGZ1dHVyZSB0ZXN0cy5cbiAgICovXG4gIGJvd3Nlci5fZGV0ZWN0ID0gZGV0ZWN0O1xuXG4gIHJldHVybiBib3dzZXJcbn0pO1xuIiwicmVxdWlyZSgnLi4vLi4vbW9kdWxlcy9lczYuc3RyaW5nLml0ZXJhdG9yJyk7XG5yZXF1aXJlKCcuLi8uLi9tb2R1bGVzL2VzNi5hcnJheS5mcm9tJyk7XG5tb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4uLy4uL21vZHVsZXMvX2NvcmUnKS5BcnJheS5mcm9tOyIsInJlcXVpcmUoJy4uL21vZHVsZXMvd2ViLmRvbS5pdGVyYWJsZScpO1xucmVxdWlyZSgnLi4vbW9kdWxlcy9lczYuc3RyaW5nLml0ZXJhdG9yJyk7XG5tb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4uL21vZHVsZXMvY29yZS5nZXQtaXRlcmF0b3InKTsiLCJ2YXIgY29yZSAgPSByZXF1aXJlKCcuLi8uLi9tb2R1bGVzL19jb3JlJylcbiAgLCAkSlNPTiA9IGNvcmUuSlNPTiB8fCAoY29yZS5KU09OID0ge3N0cmluZ2lmeTogSlNPTi5zdHJpbmdpZnl9KTtcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gc3RyaW5naWZ5KGl0KXsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby11bnVzZWQtdmFyc1xuICByZXR1cm4gJEpTT04uc3RyaW5naWZ5LmFwcGx5KCRKU09OLCBhcmd1bWVudHMpO1xufTsiLCJyZXF1aXJlKCcuLi9tb2R1bGVzL2VzNi5vYmplY3QudG8tc3RyaW5nJyk7XG5yZXF1aXJlKCcuLi9tb2R1bGVzL2VzNi5zdHJpbmcuaXRlcmF0b3InKTtcbnJlcXVpcmUoJy4uL21vZHVsZXMvd2ViLmRvbS5pdGVyYWJsZScpO1xucmVxdWlyZSgnLi4vbW9kdWxlcy9lczYubWFwJyk7XG5yZXF1aXJlKCcuLi9tb2R1bGVzL2VzNy5tYXAudG8tanNvbicpO1xubW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKCcuLi9tb2R1bGVzL19jb3JlJykuTWFwOyIsInJlcXVpcmUoJy4uLy4uL21vZHVsZXMvZXM2Lm9iamVjdC5hc3NpZ24nKTtcbm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi4vLi4vbW9kdWxlcy9fY29yZScpLk9iamVjdC5hc3NpZ247IiwicmVxdWlyZSgnLi4vLi4vbW9kdWxlcy9lczYub2JqZWN0LmNyZWF0ZScpO1xudmFyICRPYmplY3QgPSByZXF1aXJlKCcuLi8uLi9tb2R1bGVzL19jb3JlJykuT2JqZWN0O1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBjcmVhdGUoUCwgRCl7XG4gIHJldHVybiAkT2JqZWN0LmNyZWF0ZShQLCBEKTtcbn07IiwicmVxdWlyZSgnLi4vLi4vbW9kdWxlcy9lczYub2JqZWN0LmRlZmluZS1wcm9wZXJ0eScpO1xudmFyICRPYmplY3QgPSByZXF1aXJlKCcuLi8uLi9tb2R1bGVzL19jb3JlJykuT2JqZWN0O1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBkZWZpbmVQcm9wZXJ0eShpdCwga2V5LCBkZXNjKXtcbiAgcmV0dXJuICRPYmplY3QuZGVmaW5lUHJvcGVydHkoaXQsIGtleSwgZGVzYyk7XG59OyIsInJlcXVpcmUoJy4uLy4uL21vZHVsZXMvZXM2Lm9iamVjdC5nZXQtcHJvdG90eXBlLW9mJyk7XG5tb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4uLy4uL21vZHVsZXMvX2NvcmUnKS5PYmplY3QuZ2V0UHJvdG90eXBlT2Y7IiwicmVxdWlyZSgnLi4vLi4vbW9kdWxlcy9lczYub2JqZWN0LmtleXMnKTtcbm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi4vLi4vbW9kdWxlcy9fY29yZScpLk9iamVjdC5rZXlzOyIsInJlcXVpcmUoJy4uLy4uL21vZHVsZXMvZXM2Lm9iamVjdC5zZXQtcHJvdG90eXBlLW9mJyk7XG5tb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4uLy4uL21vZHVsZXMvX2NvcmUnKS5PYmplY3Quc2V0UHJvdG90eXBlT2Y7IiwicmVxdWlyZSgnLi4vbW9kdWxlcy9lczYub2JqZWN0LnRvLXN0cmluZycpO1xucmVxdWlyZSgnLi4vbW9kdWxlcy9lczYuc3RyaW5nLml0ZXJhdG9yJyk7XG5yZXF1aXJlKCcuLi9tb2R1bGVzL3dlYi5kb20uaXRlcmFibGUnKTtcbnJlcXVpcmUoJy4uL21vZHVsZXMvZXM2LnByb21pc2UnKTtcbm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi4vbW9kdWxlcy9fY29yZScpLlByb21pc2U7IiwicmVxdWlyZSgnLi4vbW9kdWxlcy9lczYub2JqZWN0LnRvLXN0cmluZycpO1xucmVxdWlyZSgnLi4vbW9kdWxlcy9lczYuc3RyaW5nLml0ZXJhdG9yJyk7XG5yZXF1aXJlKCcuLi9tb2R1bGVzL3dlYi5kb20uaXRlcmFibGUnKTtcbnJlcXVpcmUoJy4uL21vZHVsZXMvZXM2LnNldCcpO1xucmVxdWlyZSgnLi4vbW9kdWxlcy9lczcuc2V0LnRvLWpzb24nKTtcbm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi4vbW9kdWxlcy9fY29yZScpLlNldDsiLCJyZXF1aXJlKCcuLi8uLi9tb2R1bGVzL2VzNi5zeW1ib2wnKTtcbnJlcXVpcmUoJy4uLy4uL21vZHVsZXMvZXM2Lm9iamVjdC50by1zdHJpbmcnKTtcbnJlcXVpcmUoJy4uLy4uL21vZHVsZXMvZXM3LnN5bWJvbC5hc3luYy1pdGVyYXRvcicpO1xucmVxdWlyZSgnLi4vLi4vbW9kdWxlcy9lczcuc3ltYm9sLm9ic2VydmFibGUnKTtcbm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi4vLi4vbW9kdWxlcy9fY29yZScpLlN5bWJvbDsiLCJyZXF1aXJlKCcuLi8uLi9tb2R1bGVzL2VzNi5zdHJpbmcuaXRlcmF0b3InKTtcbnJlcXVpcmUoJy4uLy4uL21vZHVsZXMvd2ViLmRvbS5pdGVyYWJsZScpO1xubW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKCcuLi8uLi9tb2R1bGVzL193a3MtZXh0JykuZignaXRlcmF0b3InKTsiLCJtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKGl0KXtcbiAgaWYodHlwZW9mIGl0ICE9ICdmdW5jdGlvbicpdGhyb3cgVHlwZUVycm9yKGl0ICsgJyBpcyBub3QgYSBmdW5jdGlvbiEnKTtcbiAgcmV0dXJuIGl0O1xufTsiLCJtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKCl7IC8qIGVtcHR5ICovIH07IiwibW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihpdCwgQ29uc3RydWN0b3IsIG5hbWUsIGZvcmJpZGRlbkZpZWxkKXtcbiAgaWYoIShpdCBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSB8fCAoZm9yYmlkZGVuRmllbGQgIT09IHVuZGVmaW5lZCAmJiBmb3JiaWRkZW5GaWVsZCBpbiBpdCkpe1xuICAgIHRocm93IFR5cGVFcnJvcihuYW1lICsgJzogaW5jb3JyZWN0IGludm9jYXRpb24hJyk7XG4gIH0gcmV0dXJuIGl0O1xufTsiLCJ2YXIgaXNPYmplY3QgPSByZXF1aXJlKCcuL19pcy1vYmplY3QnKTtcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oaXQpe1xuICBpZighaXNPYmplY3QoaXQpKXRocm93IFR5cGVFcnJvcihpdCArICcgaXMgbm90IGFuIG9iamVjdCEnKTtcbiAgcmV0dXJuIGl0O1xufTsiLCJ2YXIgZm9yT2YgPSByZXF1aXJlKCcuL19mb3Itb2YnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihpdGVyLCBJVEVSQVRPUil7XG4gIHZhciByZXN1bHQgPSBbXTtcbiAgZm9yT2YoaXRlciwgZmFsc2UsIHJlc3VsdC5wdXNoLCByZXN1bHQsIElURVJBVE9SKTtcbiAgcmV0dXJuIHJlc3VsdDtcbn07XG4iLCIvLyBmYWxzZSAtPiBBcnJheSNpbmRleE9mXG4vLyB0cnVlICAtPiBBcnJheSNpbmNsdWRlc1xudmFyIHRvSU9iamVjdCA9IHJlcXVpcmUoJy4vX3RvLWlvYmplY3QnKVxuICAsIHRvTGVuZ3RoICA9IHJlcXVpcmUoJy4vX3RvLWxlbmd0aCcpXG4gICwgdG9JbmRleCAgID0gcmVxdWlyZSgnLi9fdG8taW5kZXgnKTtcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oSVNfSU5DTFVERVMpe1xuICByZXR1cm4gZnVuY3Rpb24oJHRoaXMsIGVsLCBmcm9tSW5kZXgpe1xuICAgIHZhciBPICAgICAgPSB0b0lPYmplY3QoJHRoaXMpXG4gICAgICAsIGxlbmd0aCA9IHRvTGVuZ3RoKE8ubGVuZ3RoKVxuICAgICAgLCBpbmRleCAgPSB0b0luZGV4KGZyb21JbmRleCwgbGVuZ3RoKVxuICAgICAgLCB2YWx1ZTtcbiAgICAvLyBBcnJheSNpbmNsdWRlcyB1c2VzIFNhbWVWYWx1ZVplcm8gZXF1YWxpdHkgYWxnb3JpdGhtXG4gICAgaWYoSVNfSU5DTFVERVMgJiYgZWwgIT0gZWwpd2hpbGUobGVuZ3RoID4gaW5kZXgpe1xuICAgICAgdmFsdWUgPSBPW2luZGV4KytdO1xuICAgICAgaWYodmFsdWUgIT0gdmFsdWUpcmV0dXJuIHRydWU7XG4gICAgLy8gQXJyYXkjdG9JbmRleCBpZ25vcmVzIGhvbGVzLCBBcnJheSNpbmNsdWRlcyAtIG5vdFxuICAgIH0gZWxzZSBmb3IoO2xlbmd0aCA+IGluZGV4OyBpbmRleCsrKWlmKElTX0lOQ0xVREVTIHx8IGluZGV4IGluIE8pe1xuICAgICAgaWYoT1tpbmRleF0gPT09IGVsKXJldHVybiBJU19JTkNMVURFUyB8fCBpbmRleCB8fCAwO1xuICAgIH0gcmV0dXJuICFJU19JTkNMVURFUyAmJiAtMTtcbiAgfTtcbn07IiwiLy8gMCAtPiBBcnJheSNmb3JFYWNoXG4vLyAxIC0+IEFycmF5I21hcFxuLy8gMiAtPiBBcnJheSNmaWx0ZXJcbi8vIDMgLT4gQXJyYXkjc29tZVxuLy8gNCAtPiBBcnJheSNldmVyeVxuLy8gNSAtPiBBcnJheSNmaW5kXG4vLyA2IC0+IEFycmF5I2ZpbmRJbmRleFxudmFyIGN0eCAgICAgID0gcmVxdWlyZSgnLi9fY3R4JylcbiAgLCBJT2JqZWN0ICA9IHJlcXVpcmUoJy4vX2lvYmplY3QnKVxuICAsIHRvT2JqZWN0ID0gcmVxdWlyZSgnLi9fdG8tb2JqZWN0JylcbiAgLCB0b0xlbmd0aCA9IHJlcXVpcmUoJy4vX3RvLWxlbmd0aCcpXG4gICwgYXNjICAgICAgPSByZXF1aXJlKCcuL19hcnJheS1zcGVjaWVzLWNyZWF0ZScpO1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihUWVBFLCAkY3JlYXRlKXtcbiAgdmFyIElTX01BUCAgICAgICAgPSBUWVBFID09IDFcbiAgICAsIElTX0ZJTFRFUiAgICAgPSBUWVBFID09IDJcbiAgICAsIElTX1NPTUUgICAgICAgPSBUWVBFID09IDNcbiAgICAsIElTX0VWRVJZICAgICAgPSBUWVBFID09IDRcbiAgICAsIElTX0ZJTkRfSU5ERVggPSBUWVBFID09IDZcbiAgICAsIE5PX0hPTEVTICAgICAgPSBUWVBFID09IDUgfHwgSVNfRklORF9JTkRFWFxuICAgICwgY3JlYXRlICAgICAgICA9ICRjcmVhdGUgfHwgYXNjO1xuICByZXR1cm4gZnVuY3Rpb24oJHRoaXMsIGNhbGxiYWNrZm4sIHRoYXQpe1xuICAgIHZhciBPICAgICAgPSB0b09iamVjdCgkdGhpcylcbiAgICAgICwgc2VsZiAgID0gSU9iamVjdChPKVxuICAgICAgLCBmICAgICAgPSBjdHgoY2FsbGJhY2tmbiwgdGhhdCwgMylcbiAgICAgICwgbGVuZ3RoID0gdG9MZW5ndGgoc2VsZi5sZW5ndGgpXG4gICAgICAsIGluZGV4ICA9IDBcbiAgICAgICwgcmVzdWx0ID0gSVNfTUFQID8gY3JlYXRlKCR0aGlzLCBsZW5ndGgpIDogSVNfRklMVEVSID8gY3JlYXRlKCR0aGlzLCAwKSA6IHVuZGVmaW5lZFxuICAgICAgLCB2YWwsIHJlcztcbiAgICBmb3IoO2xlbmd0aCA+IGluZGV4OyBpbmRleCsrKWlmKE5PX0hPTEVTIHx8IGluZGV4IGluIHNlbGYpe1xuICAgICAgdmFsID0gc2VsZltpbmRleF07XG4gICAgICByZXMgPSBmKHZhbCwgaW5kZXgsIE8pO1xuICAgICAgaWYoVFlQRSl7XG4gICAgICAgIGlmKElTX01BUClyZXN1bHRbaW5kZXhdID0gcmVzOyAgICAgICAgICAgIC8vIG1hcFxuICAgICAgICBlbHNlIGlmKHJlcylzd2l0Y2goVFlQRSl7XG4gICAgICAgICAgY2FzZSAzOiByZXR1cm4gdHJ1ZTsgICAgICAgICAgICAgICAgICAgIC8vIHNvbWVcbiAgICAgICAgICBjYXNlIDU6IHJldHVybiB2YWw7ICAgICAgICAgICAgICAgICAgICAgLy8gZmluZFxuICAgICAgICAgIGNhc2UgNjogcmV0dXJuIGluZGV4OyAgICAgICAgICAgICAgICAgICAvLyBmaW5kSW5kZXhcbiAgICAgICAgICBjYXNlIDI6IHJlc3VsdC5wdXNoKHZhbCk7ICAgICAgICAgICAgICAgLy8gZmlsdGVyXG4gICAgICAgIH0gZWxzZSBpZihJU19FVkVSWSlyZXR1cm4gZmFsc2U7ICAgICAgICAgIC8vIGV2ZXJ5XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBJU19GSU5EX0lOREVYID8gLTEgOiBJU19TT01FIHx8IElTX0VWRVJZID8gSVNfRVZFUlkgOiByZXN1bHQ7XG4gIH07XG59OyIsInZhciBpc09iamVjdCA9IHJlcXVpcmUoJy4vX2lzLW9iamVjdCcpXG4gICwgaXNBcnJheSAgPSByZXF1aXJlKCcuL19pcy1hcnJheScpXG4gICwgU1BFQ0lFUyAgPSByZXF1aXJlKCcuL193a3MnKSgnc3BlY2llcycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKG9yaWdpbmFsKXtcbiAgdmFyIEM7XG4gIGlmKGlzQXJyYXkob3JpZ2luYWwpKXtcbiAgICBDID0gb3JpZ2luYWwuY29uc3RydWN0b3I7XG4gICAgLy8gY3Jvc3MtcmVhbG0gZmFsbGJhY2tcbiAgICBpZih0eXBlb2YgQyA9PSAnZnVuY3Rpb24nICYmIChDID09PSBBcnJheSB8fCBpc0FycmF5KEMucHJvdG90eXBlKSkpQyA9IHVuZGVmaW5lZDtcbiAgICBpZihpc09iamVjdChDKSl7XG4gICAgICBDID0gQ1tTUEVDSUVTXTtcbiAgICAgIGlmKEMgPT09IG51bGwpQyA9IHVuZGVmaW5lZDtcbiAgICB9XG4gIH0gcmV0dXJuIEMgPT09IHVuZGVmaW5lZCA/IEFycmF5IDogQztcbn07IiwiLy8gOS40LjIuMyBBcnJheVNwZWNpZXNDcmVhdGUob3JpZ2luYWxBcnJheSwgbGVuZ3RoKVxudmFyIHNwZWNpZXNDb25zdHJ1Y3RvciA9IHJlcXVpcmUoJy4vX2FycmF5LXNwZWNpZXMtY29uc3RydWN0b3InKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihvcmlnaW5hbCwgbGVuZ3RoKXtcbiAgcmV0dXJuIG5ldyAoc3BlY2llc0NvbnN0cnVjdG9yKG9yaWdpbmFsKSkobGVuZ3RoKTtcbn07IiwiLy8gZ2V0dGluZyB0YWcgZnJvbSAxOS4xLjMuNiBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nKClcbnZhciBjb2YgPSByZXF1aXJlKCcuL19jb2YnKVxuICAsIFRBRyA9IHJlcXVpcmUoJy4vX3drcycpKCd0b1N0cmluZ1RhZycpXG4gIC8vIEVTMyB3cm9uZyBoZXJlXG4gICwgQVJHID0gY29mKGZ1bmN0aW9uKCl7IHJldHVybiBhcmd1bWVudHM7IH0oKSkgPT0gJ0FyZ3VtZW50cyc7XG5cbi8vIGZhbGxiYWNrIGZvciBJRTExIFNjcmlwdCBBY2Nlc3MgRGVuaWVkIGVycm9yXG52YXIgdHJ5R2V0ID0gZnVuY3Rpb24oaXQsIGtleSl7XG4gIHRyeSB7XG4gICAgcmV0dXJuIGl0W2tleV07XG4gIH0gY2F0Y2goZSl7IC8qIGVtcHR5ICovIH1cbn07XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oaXQpe1xuICB2YXIgTywgVCwgQjtcbiAgcmV0dXJuIGl0ID09PSB1bmRlZmluZWQgPyAnVW5kZWZpbmVkJyA6IGl0ID09PSBudWxsID8gJ051bGwnXG4gICAgLy8gQEB0b1N0cmluZ1RhZyBjYXNlXG4gICAgOiB0eXBlb2YgKFQgPSB0cnlHZXQoTyA9IE9iamVjdChpdCksIFRBRykpID09ICdzdHJpbmcnID8gVFxuICAgIC8vIGJ1aWx0aW5UYWcgY2FzZVxuICAgIDogQVJHID8gY29mKE8pXG4gICAgLy8gRVMzIGFyZ3VtZW50cyBmYWxsYmFja1xuICAgIDogKEIgPSBjb2YoTykpID09ICdPYmplY3QnICYmIHR5cGVvZiBPLmNhbGxlZSA9PSAnZnVuY3Rpb24nID8gJ0FyZ3VtZW50cycgOiBCO1xufTsiLCJ2YXIgdG9TdHJpbmcgPSB7fS50b1N0cmluZztcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihpdCl7XG4gIHJldHVybiB0b1N0cmluZy5jYWxsKGl0KS5zbGljZSg4LCAtMSk7XG59OyIsIid1c2Ugc3RyaWN0JztcbnZhciBkUCAgICAgICAgICA9IHJlcXVpcmUoJy4vX29iamVjdC1kcCcpLmZcbiAgLCBjcmVhdGUgICAgICA9IHJlcXVpcmUoJy4vX29iamVjdC1jcmVhdGUnKVxuICAsIHJlZGVmaW5lQWxsID0gcmVxdWlyZSgnLi9fcmVkZWZpbmUtYWxsJylcbiAgLCBjdHggICAgICAgICA9IHJlcXVpcmUoJy4vX2N0eCcpXG4gICwgYW5JbnN0YW5jZSAgPSByZXF1aXJlKCcuL19hbi1pbnN0YW5jZScpXG4gICwgZGVmaW5lZCAgICAgPSByZXF1aXJlKCcuL19kZWZpbmVkJylcbiAgLCBmb3JPZiAgICAgICA9IHJlcXVpcmUoJy4vX2Zvci1vZicpXG4gICwgJGl0ZXJEZWZpbmUgPSByZXF1aXJlKCcuL19pdGVyLWRlZmluZScpXG4gICwgc3RlcCAgICAgICAgPSByZXF1aXJlKCcuL19pdGVyLXN0ZXAnKVxuICAsIHNldFNwZWNpZXMgID0gcmVxdWlyZSgnLi9fc2V0LXNwZWNpZXMnKVxuICAsIERFU0NSSVBUT1JTID0gcmVxdWlyZSgnLi9fZGVzY3JpcHRvcnMnKVxuICAsIGZhc3RLZXkgICAgID0gcmVxdWlyZSgnLi9fbWV0YScpLmZhc3RLZXlcbiAgLCBTSVpFICAgICAgICA9IERFU0NSSVBUT1JTID8gJ19zJyA6ICdzaXplJztcblxudmFyIGdldEVudHJ5ID0gZnVuY3Rpb24odGhhdCwga2V5KXtcbiAgLy8gZmFzdCBjYXNlXG4gIHZhciBpbmRleCA9IGZhc3RLZXkoa2V5KSwgZW50cnk7XG4gIGlmKGluZGV4ICE9PSAnRicpcmV0dXJuIHRoYXQuX2lbaW5kZXhdO1xuICAvLyBmcm96ZW4gb2JqZWN0IGNhc2VcbiAgZm9yKGVudHJ5ID0gdGhhdC5fZjsgZW50cnk7IGVudHJ5ID0gZW50cnkubil7XG4gICAgaWYoZW50cnkuayA9PSBrZXkpcmV0dXJuIGVudHJ5O1xuICB9XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgZ2V0Q29uc3RydWN0b3I6IGZ1bmN0aW9uKHdyYXBwZXIsIE5BTUUsIElTX01BUCwgQURERVIpe1xuICAgIHZhciBDID0gd3JhcHBlcihmdW5jdGlvbih0aGF0LCBpdGVyYWJsZSl7XG4gICAgICBhbkluc3RhbmNlKHRoYXQsIEMsIE5BTUUsICdfaScpO1xuICAgICAgdGhhdC5faSA9IGNyZWF0ZShudWxsKTsgLy8gaW5kZXhcbiAgICAgIHRoYXQuX2YgPSB1bmRlZmluZWQ7ICAgIC8vIGZpcnN0IGVudHJ5XG4gICAgICB0aGF0Ll9sID0gdW5kZWZpbmVkOyAgICAvLyBsYXN0IGVudHJ5XG4gICAgICB0aGF0W1NJWkVdID0gMDsgICAgICAgICAvLyBzaXplXG4gICAgICBpZihpdGVyYWJsZSAhPSB1bmRlZmluZWQpZm9yT2YoaXRlcmFibGUsIElTX01BUCwgdGhhdFtBRERFUl0sIHRoYXQpO1xuICAgIH0pO1xuICAgIHJlZGVmaW5lQWxsKEMucHJvdG90eXBlLCB7XG4gICAgICAvLyAyMy4xLjMuMSBNYXAucHJvdG90eXBlLmNsZWFyKClcbiAgICAgIC8vIDIzLjIuMy4yIFNldC5wcm90b3R5cGUuY2xlYXIoKVxuICAgICAgY2xlYXI6IGZ1bmN0aW9uIGNsZWFyKCl7XG4gICAgICAgIGZvcih2YXIgdGhhdCA9IHRoaXMsIGRhdGEgPSB0aGF0Ll9pLCBlbnRyeSA9IHRoYXQuX2Y7IGVudHJ5OyBlbnRyeSA9IGVudHJ5Lm4pe1xuICAgICAgICAgIGVudHJ5LnIgPSB0cnVlO1xuICAgICAgICAgIGlmKGVudHJ5LnApZW50cnkucCA9IGVudHJ5LnAubiA9IHVuZGVmaW5lZDtcbiAgICAgICAgICBkZWxldGUgZGF0YVtlbnRyeS5pXTtcbiAgICAgICAgfVxuICAgICAgICB0aGF0Ll9mID0gdGhhdC5fbCA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhhdFtTSVpFXSA9IDA7XG4gICAgICB9LFxuICAgICAgLy8gMjMuMS4zLjMgTWFwLnByb3RvdHlwZS5kZWxldGUoa2V5KVxuICAgICAgLy8gMjMuMi4zLjQgU2V0LnByb3RvdHlwZS5kZWxldGUodmFsdWUpXG4gICAgICAnZGVsZXRlJzogZnVuY3Rpb24oa2V5KXtcbiAgICAgICAgdmFyIHRoYXQgID0gdGhpc1xuICAgICAgICAgICwgZW50cnkgPSBnZXRFbnRyeSh0aGF0LCBrZXkpO1xuICAgICAgICBpZihlbnRyeSl7XG4gICAgICAgICAgdmFyIG5leHQgPSBlbnRyeS5uXG4gICAgICAgICAgICAsIHByZXYgPSBlbnRyeS5wO1xuICAgICAgICAgIGRlbGV0ZSB0aGF0Ll9pW2VudHJ5LmldO1xuICAgICAgICAgIGVudHJ5LnIgPSB0cnVlO1xuICAgICAgICAgIGlmKHByZXYpcHJldi5uID0gbmV4dDtcbiAgICAgICAgICBpZihuZXh0KW5leHQucCA9IHByZXY7XG4gICAgICAgICAgaWYodGhhdC5fZiA9PSBlbnRyeSl0aGF0Ll9mID0gbmV4dDtcbiAgICAgICAgICBpZih0aGF0Ll9sID09IGVudHJ5KXRoYXQuX2wgPSBwcmV2O1xuICAgICAgICAgIHRoYXRbU0laRV0tLTtcbiAgICAgICAgfSByZXR1cm4gISFlbnRyeTtcbiAgICAgIH0sXG4gICAgICAvLyAyMy4yLjMuNiBTZXQucHJvdG90eXBlLmZvckVhY2goY2FsbGJhY2tmbiwgdGhpc0FyZyA9IHVuZGVmaW5lZClcbiAgICAgIC8vIDIzLjEuMy41IE1hcC5wcm90b3R5cGUuZm9yRWFjaChjYWxsYmFja2ZuLCB0aGlzQXJnID0gdW5kZWZpbmVkKVxuICAgICAgZm9yRWFjaDogZnVuY3Rpb24gZm9yRWFjaChjYWxsYmFja2ZuIC8qLCB0aGF0ID0gdW5kZWZpbmVkICovKXtcbiAgICAgICAgYW5JbnN0YW5jZSh0aGlzLCBDLCAnZm9yRWFjaCcpO1xuICAgICAgICB2YXIgZiA9IGN0eChjYWxsYmFja2ZuLCBhcmd1bWVudHMubGVuZ3RoID4gMSA/IGFyZ3VtZW50c1sxXSA6IHVuZGVmaW5lZCwgMylcbiAgICAgICAgICAsIGVudHJ5O1xuICAgICAgICB3aGlsZShlbnRyeSA9IGVudHJ5ID8gZW50cnkubiA6IHRoaXMuX2Ype1xuICAgICAgICAgIGYoZW50cnkudiwgZW50cnkuaywgdGhpcyk7XG4gICAgICAgICAgLy8gcmV2ZXJ0IHRvIHRoZSBsYXN0IGV4aXN0aW5nIGVudHJ5XG4gICAgICAgICAgd2hpbGUoZW50cnkgJiYgZW50cnkucillbnRyeSA9IGVudHJ5LnA7XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgICAvLyAyMy4xLjMuNyBNYXAucHJvdG90eXBlLmhhcyhrZXkpXG4gICAgICAvLyAyMy4yLjMuNyBTZXQucHJvdG90eXBlLmhhcyh2YWx1ZSlcbiAgICAgIGhhczogZnVuY3Rpb24gaGFzKGtleSl7XG4gICAgICAgIHJldHVybiAhIWdldEVudHJ5KHRoaXMsIGtleSk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgaWYoREVTQ1JJUFRPUlMpZFAoQy5wcm90b3R5cGUsICdzaXplJywge1xuICAgICAgZ2V0OiBmdW5jdGlvbigpe1xuICAgICAgICByZXR1cm4gZGVmaW5lZCh0aGlzW1NJWkVdKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICByZXR1cm4gQztcbiAgfSxcbiAgZGVmOiBmdW5jdGlvbih0aGF0LCBrZXksIHZhbHVlKXtcbiAgICB2YXIgZW50cnkgPSBnZXRFbnRyeSh0aGF0LCBrZXkpXG4gICAgICAsIHByZXYsIGluZGV4O1xuICAgIC8vIGNoYW5nZSBleGlzdGluZyBlbnRyeVxuICAgIGlmKGVudHJ5KXtcbiAgICAgIGVudHJ5LnYgPSB2YWx1ZTtcbiAgICAvLyBjcmVhdGUgbmV3IGVudHJ5XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoYXQuX2wgPSBlbnRyeSA9IHtcbiAgICAgICAgaTogaW5kZXggPSBmYXN0S2V5KGtleSwgdHJ1ZSksIC8vIDwtIGluZGV4XG4gICAgICAgIGs6IGtleSwgICAgICAgICAgICAgICAgICAgICAgICAvLyA8LSBrZXlcbiAgICAgICAgdjogdmFsdWUsICAgICAgICAgICAgICAgICAgICAgIC8vIDwtIHZhbHVlXG4gICAgICAgIHA6IHByZXYgPSB0aGF0Ll9sLCAgICAgICAgICAgICAvLyA8LSBwcmV2aW91cyBlbnRyeVxuICAgICAgICBuOiB1bmRlZmluZWQsICAgICAgICAgICAgICAgICAgLy8gPC0gbmV4dCBlbnRyeVxuICAgICAgICByOiBmYWxzZSAgICAgICAgICAgICAgICAgICAgICAgLy8gPC0gcmVtb3ZlZFxuICAgICAgfTtcbiAgICAgIGlmKCF0aGF0Ll9mKXRoYXQuX2YgPSBlbnRyeTtcbiAgICAgIGlmKHByZXYpcHJldi5uID0gZW50cnk7XG4gICAgICB0aGF0W1NJWkVdKys7XG4gICAgICAvLyBhZGQgdG8gaW5kZXhcbiAgICAgIGlmKGluZGV4ICE9PSAnRicpdGhhdC5faVtpbmRleF0gPSBlbnRyeTtcbiAgICB9IHJldHVybiB0aGF0O1xuICB9LFxuICBnZXRFbnRyeTogZ2V0RW50cnksXG4gIHNldFN0cm9uZzogZnVuY3Rpb24oQywgTkFNRSwgSVNfTUFQKXtcbiAgICAvLyBhZGQgLmtleXMsIC52YWx1ZXMsIC5lbnRyaWVzLCBbQEBpdGVyYXRvcl1cbiAgICAvLyAyMy4xLjMuNCwgMjMuMS4zLjgsIDIzLjEuMy4xMSwgMjMuMS4zLjEyLCAyMy4yLjMuNSwgMjMuMi4zLjgsIDIzLjIuMy4xMCwgMjMuMi4zLjExXG4gICAgJGl0ZXJEZWZpbmUoQywgTkFNRSwgZnVuY3Rpb24oaXRlcmF0ZWQsIGtpbmQpe1xuICAgICAgdGhpcy5fdCA9IGl0ZXJhdGVkOyAgLy8gdGFyZ2V0XG4gICAgICB0aGlzLl9rID0ga2luZDsgICAgICAvLyBraW5kXG4gICAgICB0aGlzLl9sID0gdW5kZWZpbmVkOyAvLyBwcmV2aW91c1xuICAgIH0sIGZ1bmN0aW9uKCl7XG4gICAgICB2YXIgdGhhdCAgPSB0aGlzXG4gICAgICAgICwga2luZCAgPSB0aGF0Ll9rXG4gICAgICAgICwgZW50cnkgPSB0aGF0Ll9sO1xuICAgICAgLy8gcmV2ZXJ0IHRvIHRoZSBsYXN0IGV4aXN0aW5nIGVudHJ5XG4gICAgICB3aGlsZShlbnRyeSAmJiBlbnRyeS5yKWVudHJ5ID0gZW50cnkucDtcbiAgICAgIC8vIGdldCBuZXh0IGVudHJ5XG4gICAgICBpZighdGhhdC5fdCB8fCAhKHRoYXQuX2wgPSBlbnRyeSA9IGVudHJ5ID8gZW50cnkubiA6IHRoYXQuX3QuX2YpKXtcbiAgICAgICAgLy8gb3IgZmluaXNoIHRoZSBpdGVyYXRpb25cbiAgICAgICAgdGhhdC5fdCA9IHVuZGVmaW5lZDtcbiAgICAgICAgcmV0dXJuIHN0ZXAoMSk7XG4gICAgICB9XG4gICAgICAvLyByZXR1cm4gc3RlcCBieSBraW5kXG4gICAgICBpZihraW5kID09ICdrZXlzJyAgKXJldHVybiBzdGVwKDAsIGVudHJ5LmspO1xuICAgICAgaWYoa2luZCA9PSAndmFsdWVzJylyZXR1cm4gc3RlcCgwLCBlbnRyeS52KTtcbiAgICAgIHJldHVybiBzdGVwKDAsIFtlbnRyeS5rLCBlbnRyeS52XSk7XG4gICAgfSwgSVNfTUFQID8gJ2VudHJpZXMnIDogJ3ZhbHVlcycgLCAhSVNfTUFQLCB0cnVlKTtcblxuICAgIC8vIGFkZCBbQEBzcGVjaWVzXSwgMjMuMS4yLjIsIDIzLjIuMi4yXG4gICAgc2V0U3BlY2llcyhOQU1FKTtcbiAgfVxufTsiLCIvLyBodHRwczovL2dpdGh1Yi5jb20vRGF2aWRCcnVhbnQvTWFwLVNldC5wcm90b3R5cGUudG9KU09OXG52YXIgY2xhc3NvZiA9IHJlcXVpcmUoJy4vX2NsYXNzb2YnKVxuICAsIGZyb20gICAgPSByZXF1aXJlKCcuL19hcnJheS1mcm9tLWl0ZXJhYmxlJyk7XG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKE5BTUUpe1xuICByZXR1cm4gZnVuY3Rpb24gdG9KU09OKCl7XG4gICAgaWYoY2xhc3NvZih0aGlzKSAhPSBOQU1FKXRocm93IFR5cGVFcnJvcihOQU1FICsgXCIjdG9KU09OIGlzbid0IGdlbmVyaWNcIik7XG4gICAgcmV0dXJuIGZyb20odGhpcyk7XG4gIH07XG59OyIsIid1c2Ugc3RyaWN0JztcbnZhciBnbG9iYWwgICAgICAgICA9IHJlcXVpcmUoJy4vX2dsb2JhbCcpXG4gICwgJGV4cG9ydCAgICAgICAgPSByZXF1aXJlKCcuL19leHBvcnQnKVxuICAsIG1ldGEgICAgICAgICAgID0gcmVxdWlyZSgnLi9fbWV0YScpXG4gICwgZmFpbHMgICAgICAgICAgPSByZXF1aXJlKCcuL19mYWlscycpXG4gICwgaGlkZSAgICAgICAgICAgPSByZXF1aXJlKCcuL19oaWRlJylcbiAgLCByZWRlZmluZUFsbCAgICA9IHJlcXVpcmUoJy4vX3JlZGVmaW5lLWFsbCcpXG4gICwgZm9yT2YgICAgICAgICAgPSByZXF1aXJlKCcuL19mb3Itb2YnKVxuICAsIGFuSW5zdGFuY2UgICAgID0gcmVxdWlyZSgnLi9fYW4taW5zdGFuY2UnKVxuICAsIGlzT2JqZWN0ICAgICAgID0gcmVxdWlyZSgnLi9faXMtb2JqZWN0JylcbiAgLCBzZXRUb1N0cmluZ1RhZyA9IHJlcXVpcmUoJy4vX3NldC10by1zdHJpbmctdGFnJylcbiAgLCBkUCAgICAgICAgICAgICA9IHJlcXVpcmUoJy4vX29iamVjdC1kcCcpLmZcbiAgLCBlYWNoICAgICAgICAgICA9IHJlcXVpcmUoJy4vX2FycmF5LW1ldGhvZHMnKSgwKVxuICAsIERFU0NSSVBUT1JTICAgID0gcmVxdWlyZSgnLi9fZGVzY3JpcHRvcnMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihOQU1FLCB3cmFwcGVyLCBtZXRob2RzLCBjb21tb24sIElTX01BUCwgSVNfV0VBSyl7XG4gIHZhciBCYXNlICA9IGdsb2JhbFtOQU1FXVxuICAgICwgQyAgICAgPSBCYXNlXG4gICAgLCBBRERFUiA9IElTX01BUCA/ICdzZXQnIDogJ2FkZCdcbiAgICAsIHByb3RvID0gQyAmJiBDLnByb3RvdHlwZVxuICAgICwgTyAgICAgPSB7fTtcbiAgaWYoIURFU0NSSVBUT1JTIHx8IHR5cGVvZiBDICE9ICdmdW5jdGlvbicgfHwgIShJU19XRUFLIHx8IHByb3RvLmZvckVhY2ggJiYgIWZhaWxzKGZ1bmN0aW9uKCl7XG4gICAgbmV3IEMoKS5lbnRyaWVzKCkubmV4dCgpO1xuICB9KSkpe1xuICAgIC8vIGNyZWF0ZSBjb2xsZWN0aW9uIGNvbnN0cnVjdG9yXG4gICAgQyA9IGNvbW1vbi5nZXRDb25zdHJ1Y3Rvcih3cmFwcGVyLCBOQU1FLCBJU19NQVAsIEFEREVSKTtcbiAgICByZWRlZmluZUFsbChDLnByb3RvdHlwZSwgbWV0aG9kcyk7XG4gICAgbWV0YS5ORUVEID0gdHJ1ZTtcbiAgfSBlbHNlIHtcbiAgICBDID0gd3JhcHBlcihmdW5jdGlvbih0YXJnZXQsIGl0ZXJhYmxlKXtcbiAgICAgIGFuSW5zdGFuY2UodGFyZ2V0LCBDLCBOQU1FLCAnX2MnKTtcbiAgICAgIHRhcmdldC5fYyA9IG5ldyBCYXNlO1xuICAgICAgaWYoaXRlcmFibGUgIT0gdW5kZWZpbmVkKWZvck9mKGl0ZXJhYmxlLCBJU19NQVAsIHRhcmdldFtBRERFUl0sIHRhcmdldCk7XG4gICAgfSk7XG4gICAgZWFjaCgnYWRkLGNsZWFyLGRlbGV0ZSxmb3JFYWNoLGdldCxoYXMsc2V0LGtleXMsdmFsdWVzLGVudHJpZXMsdG9KU09OJy5zcGxpdCgnLCcpLGZ1bmN0aW9uKEtFWSl7XG4gICAgICB2YXIgSVNfQURERVIgPSBLRVkgPT0gJ2FkZCcgfHwgS0VZID09ICdzZXQnO1xuICAgICAgaWYoS0VZIGluIHByb3RvICYmICEoSVNfV0VBSyAmJiBLRVkgPT0gJ2NsZWFyJykpaGlkZShDLnByb3RvdHlwZSwgS0VZLCBmdW5jdGlvbihhLCBiKXtcbiAgICAgICAgYW5JbnN0YW5jZSh0aGlzLCBDLCBLRVkpO1xuICAgICAgICBpZighSVNfQURERVIgJiYgSVNfV0VBSyAmJiAhaXNPYmplY3QoYSkpcmV0dXJuIEtFWSA9PSAnZ2V0JyA/IHVuZGVmaW5lZCA6IGZhbHNlO1xuICAgICAgICB2YXIgcmVzdWx0ID0gdGhpcy5fY1tLRVldKGEgPT09IDAgPyAwIDogYSwgYik7XG4gICAgICAgIHJldHVybiBJU19BRERFUiA/IHRoaXMgOiByZXN1bHQ7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgICBpZignc2l6ZScgaW4gcHJvdG8pZFAoQy5wcm90b3R5cGUsICdzaXplJywge1xuICAgICAgZ2V0OiBmdW5jdGlvbigpe1xuICAgICAgICByZXR1cm4gdGhpcy5fYy5zaXplO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgc2V0VG9TdHJpbmdUYWcoQywgTkFNRSk7XG5cbiAgT1tOQU1FXSA9IEM7XG4gICRleHBvcnQoJGV4cG9ydC5HICsgJGV4cG9ydC5XICsgJGV4cG9ydC5GLCBPKTtcblxuICBpZighSVNfV0VBSyljb21tb24uc2V0U3Ryb25nKEMsIE5BTUUsIElTX01BUCk7XG5cbiAgcmV0dXJuIEM7XG59OyIsInZhciBjb3JlID0gbW9kdWxlLmV4cG9ydHMgPSB7dmVyc2lvbjogJzIuNC4wJ307XG5pZih0eXBlb2YgX19lID09ICdudW1iZXInKV9fZSA9IGNvcmU7IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgbm8tdW5kZWYiLCIndXNlIHN0cmljdCc7XG52YXIgJGRlZmluZVByb3BlcnR5ID0gcmVxdWlyZSgnLi9fb2JqZWN0LWRwJylcbiAgLCBjcmVhdGVEZXNjICAgICAgPSByZXF1aXJlKCcuL19wcm9wZXJ0eS1kZXNjJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24ob2JqZWN0LCBpbmRleCwgdmFsdWUpe1xuICBpZihpbmRleCBpbiBvYmplY3QpJGRlZmluZVByb3BlcnR5LmYob2JqZWN0LCBpbmRleCwgY3JlYXRlRGVzYygwLCB2YWx1ZSkpO1xuICBlbHNlIG9iamVjdFtpbmRleF0gPSB2YWx1ZTtcbn07IiwiLy8gb3B0aW9uYWwgLyBzaW1wbGUgY29udGV4dCBiaW5kaW5nXG52YXIgYUZ1bmN0aW9uID0gcmVxdWlyZSgnLi9fYS1mdW5jdGlvbicpO1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihmbiwgdGhhdCwgbGVuZ3RoKXtcbiAgYUZ1bmN0aW9uKGZuKTtcbiAgaWYodGhhdCA9PT0gdW5kZWZpbmVkKXJldHVybiBmbjtcbiAgc3dpdGNoKGxlbmd0aCl7XG4gICAgY2FzZSAxOiByZXR1cm4gZnVuY3Rpb24oYSl7XG4gICAgICByZXR1cm4gZm4uY2FsbCh0aGF0LCBhKTtcbiAgICB9O1xuICAgIGNhc2UgMjogcmV0dXJuIGZ1bmN0aW9uKGEsIGIpe1xuICAgICAgcmV0dXJuIGZuLmNhbGwodGhhdCwgYSwgYik7XG4gICAgfTtcbiAgICBjYXNlIDM6IHJldHVybiBmdW5jdGlvbihhLCBiLCBjKXtcbiAgICAgIHJldHVybiBmbi5jYWxsKHRoYXQsIGEsIGIsIGMpO1xuICAgIH07XG4gIH1cbiAgcmV0dXJuIGZ1bmN0aW9uKC8qIC4uLmFyZ3MgKi8pe1xuICAgIHJldHVybiBmbi5hcHBseSh0aGF0LCBhcmd1bWVudHMpO1xuICB9O1xufTsiLCIvLyA3LjIuMSBSZXF1aXJlT2JqZWN0Q29lcmNpYmxlKGFyZ3VtZW50KVxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihpdCl7XG4gIGlmKGl0ID09IHVuZGVmaW5lZCl0aHJvdyBUeXBlRXJyb3IoXCJDYW4ndCBjYWxsIG1ldGhvZCBvbiAgXCIgKyBpdCk7XG4gIHJldHVybiBpdDtcbn07IiwiLy8gVGhhbmsncyBJRTggZm9yIGhpcyBmdW5ueSBkZWZpbmVQcm9wZXJ0eVxubW9kdWxlLmV4cG9ydHMgPSAhcmVxdWlyZSgnLi9fZmFpbHMnKShmdW5jdGlvbigpe1xuICByZXR1cm4gT2JqZWN0LmRlZmluZVByb3BlcnR5KHt9LCAnYScsIHtnZXQ6IGZ1bmN0aW9uKCl7IHJldHVybiA3OyB9fSkuYSAhPSA3O1xufSk7IiwidmFyIGlzT2JqZWN0ID0gcmVxdWlyZSgnLi9faXMtb2JqZWN0JylcbiAgLCBkb2N1bWVudCA9IHJlcXVpcmUoJy4vX2dsb2JhbCcpLmRvY3VtZW50XG4gIC8vIGluIG9sZCBJRSB0eXBlb2YgZG9jdW1lbnQuY3JlYXRlRWxlbWVudCBpcyAnb2JqZWN0J1xuICAsIGlzID0gaXNPYmplY3QoZG9jdW1lbnQpICYmIGlzT2JqZWN0KGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQpO1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihpdCl7XG4gIHJldHVybiBpcyA/IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoaXQpIDoge307XG59OyIsIi8vIElFIDgtIGRvbid0IGVudW0gYnVnIGtleXNcbm1vZHVsZS5leHBvcnRzID0gKFxuICAnY29uc3RydWN0b3IsaGFzT3duUHJvcGVydHksaXNQcm90b3R5cGVPZixwcm9wZXJ0eUlzRW51bWVyYWJsZSx0b0xvY2FsZVN0cmluZyx0b1N0cmluZyx2YWx1ZU9mJ1xuKS5zcGxpdCgnLCcpOyIsIi8vIGFsbCBlbnVtZXJhYmxlIG9iamVjdCBrZXlzLCBpbmNsdWRlcyBzeW1ib2xzXG52YXIgZ2V0S2V5cyA9IHJlcXVpcmUoJy4vX29iamVjdC1rZXlzJylcbiAgLCBnT1BTICAgID0gcmVxdWlyZSgnLi9fb2JqZWN0LWdvcHMnKVxuICAsIHBJRSAgICAgPSByZXF1aXJlKCcuL19vYmplY3QtcGllJyk7XG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKGl0KXtcbiAgdmFyIHJlc3VsdCAgICAgPSBnZXRLZXlzKGl0KVxuICAgICwgZ2V0U3ltYm9scyA9IGdPUFMuZjtcbiAgaWYoZ2V0U3ltYm9scyl7XG4gICAgdmFyIHN5bWJvbHMgPSBnZXRTeW1ib2xzKGl0KVxuICAgICAgLCBpc0VudW0gID0gcElFLmZcbiAgICAgICwgaSAgICAgICA9IDBcbiAgICAgICwga2V5O1xuICAgIHdoaWxlKHN5bWJvbHMubGVuZ3RoID4gaSlpZihpc0VudW0uY2FsbChpdCwga2V5ID0gc3ltYm9sc1tpKytdKSlyZXN1bHQucHVzaChrZXkpO1xuICB9IHJldHVybiByZXN1bHQ7XG59OyIsInZhciBnbG9iYWwgICAgPSByZXF1aXJlKCcuL19nbG9iYWwnKVxuICAsIGNvcmUgICAgICA9IHJlcXVpcmUoJy4vX2NvcmUnKVxuICAsIGN0eCAgICAgICA9IHJlcXVpcmUoJy4vX2N0eCcpXG4gICwgaGlkZSAgICAgID0gcmVxdWlyZSgnLi9faGlkZScpXG4gICwgUFJPVE9UWVBFID0gJ3Byb3RvdHlwZSc7XG5cbnZhciAkZXhwb3J0ID0gZnVuY3Rpb24odHlwZSwgbmFtZSwgc291cmNlKXtcbiAgdmFyIElTX0ZPUkNFRCA9IHR5cGUgJiAkZXhwb3J0LkZcbiAgICAsIElTX0dMT0JBTCA9IHR5cGUgJiAkZXhwb3J0LkdcbiAgICAsIElTX1NUQVRJQyA9IHR5cGUgJiAkZXhwb3J0LlNcbiAgICAsIElTX1BST1RPICA9IHR5cGUgJiAkZXhwb3J0LlBcbiAgICAsIElTX0JJTkQgICA9IHR5cGUgJiAkZXhwb3J0LkJcbiAgICAsIElTX1dSQVAgICA9IHR5cGUgJiAkZXhwb3J0LldcbiAgICAsIGV4cG9ydHMgICA9IElTX0dMT0JBTCA/IGNvcmUgOiBjb3JlW25hbWVdIHx8IChjb3JlW25hbWVdID0ge30pXG4gICAgLCBleHBQcm90byAgPSBleHBvcnRzW1BST1RPVFlQRV1cbiAgICAsIHRhcmdldCAgICA9IElTX0dMT0JBTCA/IGdsb2JhbCA6IElTX1NUQVRJQyA/IGdsb2JhbFtuYW1lXSA6IChnbG9iYWxbbmFtZV0gfHwge30pW1BST1RPVFlQRV1cbiAgICAsIGtleSwgb3duLCBvdXQ7XG4gIGlmKElTX0dMT0JBTClzb3VyY2UgPSBuYW1lO1xuICBmb3Ioa2V5IGluIHNvdXJjZSl7XG4gICAgLy8gY29udGFpbnMgaW4gbmF0aXZlXG4gICAgb3duID0gIUlTX0ZPUkNFRCAmJiB0YXJnZXQgJiYgdGFyZ2V0W2tleV0gIT09IHVuZGVmaW5lZDtcbiAgICBpZihvd24gJiYga2V5IGluIGV4cG9ydHMpY29udGludWU7XG4gICAgLy8gZXhwb3J0IG5hdGl2ZSBvciBwYXNzZWRcbiAgICBvdXQgPSBvd24gPyB0YXJnZXRba2V5XSA6IHNvdXJjZVtrZXldO1xuICAgIC8vIHByZXZlbnQgZ2xvYmFsIHBvbGx1dGlvbiBmb3IgbmFtZXNwYWNlc1xuICAgIGV4cG9ydHNba2V5XSA9IElTX0dMT0JBTCAmJiB0eXBlb2YgdGFyZ2V0W2tleV0gIT0gJ2Z1bmN0aW9uJyA/IHNvdXJjZVtrZXldXG4gICAgLy8gYmluZCB0aW1lcnMgdG8gZ2xvYmFsIGZvciBjYWxsIGZyb20gZXhwb3J0IGNvbnRleHRcbiAgICA6IElTX0JJTkQgJiYgb3duID8gY3R4KG91dCwgZ2xvYmFsKVxuICAgIC8vIHdyYXAgZ2xvYmFsIGNvbnN0cnVjdG9ycyBmb3IgcHJldmVudCBjaGFuZ2UgdGhlbSBpbiBsaWJyYXJ5XG4gICAgOiBJU19XUkFQICYmIHRhcmdldFtrZXldID09IG91dCA/IChmdW5jdGlvbihDKXtcbiAgICAgIHZhciBGID0gZnVuY3Rpb24oYSwgYiwgYyl7XG4gICAgICAgIGlmKHRoaXMgaW5zdGFuY2VvZiBDKXtcbiAgICAgICAgICBzd2l0Y2goYXJndW1lbnRzLmxlbmd0aCl7XG4gICAgICAgICAgICBjYXNlIDA6IHJldHVybiBuZXcgQztcbiAgICAgICAgICAgIGNhc2UgMTogcmV0dXJuIG5ldyBDKGEpO1xuICAgICAgICAgICAgY2FzZSAyOiByZXR1cm4gbmV3IEMoYSwgYik7XG4gICAgICAgICAgfSByZXR1cm4gbmV3IEMoYSwgYiwgYyk7XG4gICAgICAgIH0gcmV0dXJuIEMuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgIH07XG4gICAgICBGW1BST1RPVFlQRV0gPSBDW1BST1RPVFlQRV07XG4gICAgICByZXR1cm4gRjtcbiAgICAvLyBtYWtlIHN0YXRpYyB2ZXJzaW9ucyBmb3IgcHJvdG90eXBlIG1ldGhvZHNcbiAgICB9KShvdXQpIDogSVNfUFJPVE8gJiYgdHlwZW9mIG91dCA9PSAnZnVuY3Rpb24nID8gY3R4KEZ1bmN0aW9uLmNhbGwsIG91dCkgOiBvdXQ7XG4gICAgLy8gZXhwb3J0IHByb3RvIG1ldGhvZHMgdG8gY29yZS4lQ09OU1RSVUNUT1IlLm1ldGhvZHMuJU5BTUUlXG4gICAgaWYoSVNfUFJPVE8pe1xuICAgICAgKGV4cG9ydHMudmlydHVhbCB8fCAoZXhwb3J0cy52aXJ0dWFsID0ge30pKVtrZXldID0gb3V0O1xuICAgICAgLy8gZXhwb3J0IHByb3RvIG1ldGhvZHMgdG8gY29yZS4lQ09OU1RSVUNUT1IlLnByb3RvdHlwZS4lTkFNRSVcbiAgICAgIGlmKHR5cGUgJiAkZXhwb3J0LlIgJiYgZXhwUHJvdG8gJiYgIWV4cFByb3RvW2tleV0paGlkZShleHBQcm90bywga2V5LCBvdXQpO1xuICAgIH1cbiAgfVxufTtcbi8vIHR5cGUgYml0bWFwXG4kZXhwb3J0LkYgPSAxOyAgIC8vIGZvcmNlZFxuJGV4cG9ydC5HID0gMjsgICAvLyBnbG9iYWxcbiRleHBvcnQuUyA9IDQ7ICAgLy8gc3RhdGljXG4kZXhwb3J0LlAgPSA4OyAgIC8vIHByb3RvXG4kZXhwb3J0LkIgPSAxNjsgIC8vIGJpbmRcbiRleHBvcnQuVyA9IDMyOyAgLy8gd3JhcFxuJGV4cG9ydC5VID0gNjQ7ICAvLyBzYWZlXG4kZXhwb3J0LlIgPSAxMjg7IC8vIHJlYWwgcHJvdG8gbWV0aG9kIGZvciBgbGlicmFyeWAgXG5tb2R1bGUuZXhwb3J0cyA9ICRleHBvcnQ7IiwibW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihleGVjKXtcbiAgdHJ5IHtcbiAgICByZXR1cm4gISFleGVjKCk7XG4gIH0gY2F0Y2goZSl7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cbn07IiwidmFyIGN0eCAgICAgICAgID0gcmVxdWlyZSgnLi9fY3R4JylcbiAgLCBjYWxsICAgICAgICA9IHJlcXVpcmUoJy4vX2l0ZXItY2FsbCcpXG4gICwgaXNBcnJheUl0ZXIgPSByZXF1aXJlKCcuL19pcy1hcnJheS1pdGVyJylcbiAgLCBhbk9iamVjdCAgICA9IHJlcXVpcmUoJy4vX2FuLW9iamVjdCcpXG4gICwgdG9MZW5ndGggICAgPSByZXF1aXJlKCcuL190by1sZW5ndGgnKVxuICAsIGdldEl0ZXJGbiAgID0gcmVxdWlyZSgnLi9jb3JlLmdldC1pdGVyYXRvci1tZXRob2QnKVxuICAsIEJSRUFLICAgICAgID0ge31cbiAgLCBSRVRVUk4gICAgICA9IHt9O1xudmFyIGV4cG9ydHMgPSBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKGl0ZXJhYmxlLCBlbnRyaWVzLCBmbiwgdGhhdCwgSVRFUkFUT1Ipe1xuICB2YXIgaXRlckZuID0gSVRFUkFUT1IgPyBmdW5jdGlvbigpeyByZXR1cm4gaXRlcmFibGU7IH0gOiBnZXRJdGVyRm4oaXRlcmFibGUpXG4gICAgLCBmICAgICAgPSBjdHgoZm4sIHRoYXQsIGVudHJpZXMgPyAyIDogMSlcbiAgICAsIGluZGV4ICA9IDBcbiAgICAsIGxlbmd0aCwgc3RlcCwgaXRlcmF0b3IsIHJlc3VsdDtcbiAgaWYodHlwZW9mIGl0ZXJGbiAhPSAnZnVuY3Rpb24nKXRocm93IFR5cGVFcnJvcihpdGVyYWJsZSArICcgaXMgbm90IGl0ZXJhYmxlIScpO1xuICAvLyBmYXN0IGNhc2UgZm9yIGFycmF5cyB3aXRoIGRlZmF1bHQgaXRlcmF0b3JcbiAgaWYoaXNBcnJheUl0ZXIoaXRlckZuKSlmb3IobGVuZ3RoID0gdG9MZW5ndGgoaXRlcmFibGUubGVuZ3RoKTsgbGVuZ3RoID4gaW5kZXg7IGluZGV4Kyspe1xuICAgIHJlc3VsdCA9IGVudHJpZXMgPyBmKGFuT2JqZWN0KHN0ZXAgPSBpdGVyYWJsZVtpbmRleF0pWzBdLCBzdGVwWzFdKSA6IGYoaXRlcmFibGVbaW5kZXhdKTtcbiAgICBpZihyZXN1bHQgPT09IEJSRUFLIHx8IHJlc3VsdCA9PT0gUkVUVVJOKXJldHVybiByZXN1bHQ7XG4gIH0gZWxzZSBmb3IoaXRlcmF0b3IgPSBpdGVyRm4uY2FsbChpdGVyYWJsZSk7ICEoc3RlcCA9IGl0ZXJhdG9yLm5leHQoKSkuZG9uZTsgKXtcbiAgICByZXN1bHQgPSBjYWxsKGl0ZXJhdG9yLCBmLCBzdGVwLnZhbHVlLCBlbnRyaWVzKTtcbiAgICBpZihyZXN1bHQgPT09IEJSRUFLIHx8IHJlc3VsdCA9PT0gUkVUVVJOKXJldHVybiByZXN1bHQ7XG4gIH1cbn07XG5leHBvcnRzLkJSRUFLICA9IEJSRUFLO1xuZXhwb3J0cy5SRVRVUk4gPSBSRVRVUk47IiwiLy8gaHR0cHM6Ly9naXRodWIuY29tL3psb2lyb2NrL2NvcmUtanMvaXNzdWVzLzg2I2lzc3VlY29tbWVudC0xMTU3NTkwMjhcbnZhciBnbG9iYWwgPSBtb2R1bGUuZXhwb3J0cyA9IHR5cGVvZiB3aW5kb3cgIT0gJ3VuZGVmaW5lZCcgJiYgd2luZG93Lk1hdGggPT0gTWF0aFxuICA/IHdpbmRvdyA6IHR5cGVvZiBzZWxmICE9ICd1bmRlZmluZWQnICYmIHNlbGYuTWF0aCA9PSBNYXRoID8gc2VsZiA6IEZ1bmN0aW9uKCdyZXR1cm4gdGhpcycpKCk7XG5pZih0eXBlb2YgX19nID09ICdudW1iZXInKV9fZyA9IGdsb2JhbDsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby11bmRlZiIsInZhciBoYXNPd25Qcm9wZXJ0eSA9IHt9Lmhhc093blByb3BlcnR5O1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihpdCwga2V5KXtcbiAgcmV0dXJuIGhhc093blByb3BlcnR5LmNhbGwoaXQsIGtleSk7XG59OyIsInZhciBkUCAgICAgICAgID0gcmVxdWlyZSgnLi9fb2JqZWN0LWRwJylcbiAgLCBjcmVhdGVEZXNjID0gcmVxdWlyZSgnLi9fcHJvcGVydHktZGVzYycpO1xubW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKCcuL19kZXNjcmlwdG9ycycpID8gZnVuY3Rpb24ob2JqZWN0LCBrZXksIHZhbHVlKXtcbiAgcmV0dXJuIGRQLmYob2JqZWN0LCBrZXksIGNyZWF0ZURlc2MoMSwgdmFsdWUpKTtcbn0gOiBmdW5jdGlvbihvYmplY3QsIGtleSwgdmFsdWUpe1xuICBvYmplY3Rba2V5XSA9IHZhbHVlO1xuICByZXR1cm4gb2JqZWN0O1xufTsiLCJtb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4vX2dsb2JhbCcpLmRvY3VtZW50ICYmIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudDsiLCJtb2R1bGUuZXhwb3J0cyA9ICFyZXF1aXJlKCcuL19kZXNjcmlwdG9ycycpICYmICFyZXF1aXJlKCcuL19mYWlscycpKGZ1bmN0aW9uKCl7XG4gIHJldHVybiBPYmplY3QuZGVmaW5lUHJvcGVydHkocmVxdWlyZSgnLi9fZG9tLWNyZWF0ZScpKCdkaXYnKSwgJ2EnLCB7Z2V0OiBmdW5jdGlvbigpeyByZXR1cm4gNzsgfX0pLmEgIT0gNztcbn0pOyIsIi8vIGZhc3QgYXBwbHksIGh0dHA6Ly9qc3BlcmYubG5raXQuY29tL2Zhc3QtYXBwbHkvNVxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihmbiwgYXJncywgdGhhdCl7XG4gIHZhciB1biA9IHRoYXQgPT09IHVuZGVmaW5lZDtcbiAgc3dpdGNoKGFyZ3MubGVuZ3RoKXtcbiAgICBjYXNlIDA6IHJldHVybiB1biA/IGZuKClcbiAgICAgICAgICAgICAgICAgICAgICA6IGZuLmNhbGwodGhhdCk7XG4gICAgY2FzZSAxOiByZXR1cm4gdW4gPyBmbihhcmdzWzBdKVxuICAgICAgICAgICAgICAgICAgICAgIDogZm4uY2FsbCh0aGF0LCBhcmdzWzBdKTtcbiAgICBjYXNlIDI6IHJldHVybiB1biA/IGZuKGFyZ3NbMF0sIGFyZ3NbMV0pXG4gICAgICAgICAgICAgICAgICAgICAgOiBmbi5jYWxsKHRoYXQsIGFyZ3NbMF0sIGFyZ3NbMV0pO1xuICAgIGNhc2UgMzogcmV0dXJuIHVuID8gZm4oYXJnc1swXSwgYXJnc1sxXSwgYXJnc1syXSlcbiAgICAgICAgICAgICAgICAgICAgICA6IGZuLmNhbGwodGhhdCwgYXJnc1swXSwgYXJnc1sxXSwgYXJnc1syXSk7XG4gICAgY2FzZSA0OiByZXR1cm4gdW4gPyBmbihhcmdzWzBdLCBhcmdzWzFdLCBhcmdzWzJdLCBhcmdzWzNdKVxuICAgICAgICAgICAgICAgICAgICAgIDogZm4uY2FsbCh0aGF0LCBhcmdzWzBdLCBhcmdzWzFdLCBhcmdzWzJdLCBhcmdzWzNdKTtcbiAgfSByZXR1cm4gICAgICAgICAgICAgIGZuLmFwcGx5KHRoYXQsIGFyZ3MpO1xufTsiLCIvLyBmYWxsYmFjayBmb3Igbm9uLWFycmF5LWxpa2UgRVMzIGFuZCBub24tZW51bWVyYWJsZSBvbGQgVjggc3RyaW5nc1xudmFyIGNvZiA9IHJlcXVpcmUoJy4vX2NvZicpO1xubW9kdWxlLmV4cG9ydHMgPSBPYmplY3QoJ3onKS5wcm9wZXJ0eUlzRW51bWVyYWJsZSgwKSA/IE9iamVjdCA6IGZ1bmN0aW9uKGl0KXtcbiAgcmV0dXJuIGNvZihpdCkgPT0gJ1N0cmluZycgPyBpdC5zcGxpdCgnJykgOiBPYmplY3QoaXQpO1xufTsiLCIvLyBjaGVjayBvbiBkZWZhdWx0IEFycmF5IGl0ZXJhdG9yXG52YXIgSXRlcmF0b3JzICA9IHJlcXVpcmUoJy4vX2l0ZXJhdG9ycycpXG4gICwgSVRFUkFUT1IgICA9IHJlcXVpcmUoJy4vX3drcycpKCdpdGVyYXRvcicpXG4gICwgQXJyYXlQcm90byA9IEFycmF5LnByb3RvdHlwZTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihpdCl7XG4gIHJldHVybiBpdCAhPT0gdW5kZWZpbmVkICYmIChJdGVyYXRvcnMuQXJyYXkgPT09IGl0IHx8IEFycmF5UHJvdG9bSVRFUkFUT1JdID09PSBpdCk7XG59OyIsIi8vIDcuMi4yIElzQXJyYXkoYXJndW1lbnQpXG52YXIgY29mID0gcmVxdWlyZSgnLi9fY29mJyk7XG5tb2R1bGUuZXhwb3J0cyA9IEFycmF5LmlzQXJyYXkgfHwgZnVuY3Rpb24gaXNBcnJheShhcmcpe1xuICByZXR1cm4gY29mKGFyZykgPT0gJ0FycmF5Jztcbn07IiwibW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihpdCl7XG4gIHJldHVybiB0eXBlb2YgaXQgPT09ICdvYmplY3QnID8gaXQgIT09IG51bGwgOiB0eXBlb2YgaXQgPT09ICdmdW5jdGlvbic7XG59OyIsIi8vIGNhbGwgc29tZXRoaW5nIG9uIGl0ZXJhdG9yIHN0ZXAgd2l0aCBzYWZlIGNsb3Npbmcgb24gZXJyb3JcbnZhciBhbk9iamVjdCA9IHJlcXVpcmUoJy4vX2FuLW9iamVjdCcpO1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihpdGVyYXRvciwgZm4sIHZhbHVlLCBlbnRyaWVzKXtcbiAgdHJ5IHtcbiAgICByZXR1cm4gZW50cmllcyA/IGZuKGFuT2JqZWN0KHZhbHVlKVswXSwgdmFsdWVbMV0pIDogZm4odmFsdWUpO1xuICAvLyA3LjQuNiBJdGVyYXRvckNsb3NlKGl0ZXJhdG9yLCBjb21wbGV0aW9uKVxuICB9IGNhdGNoKGUpe1xuICAgIHZhciByZXQgPSBpdGVyYXRvclsncmV0dXJuJ107XG4gICAgaWYocmV0ICE9PSB1bmRlZmluZWQpYW5PYmplY3QocmV0LmNhbGwoaXRlcmF0b3IpKTtcbiAgICB0aHJvdyBlO1xuICB9XG59OyIsIid1c2Ugc3RyaWN0JztcbnZhciBjcmVhdGUgICAgICAgICA9IHJlcXVpcmUoJy4vX29iamVjdC1jcmVhdGUnKVxuICAsIGRlc2NyaXB0b3IgICAgID0gcmVxdWlyZSgnLi9fcHJvcGVydHktZGVzYycpXG4gICwgc2V0VG9TdHJpbmdUYWcgPSByZXF1aXJlKCcuL19zZXQtdG8tc3RyaW5nLXRhZycpXG4gICwgSXRlcmF0b3JQcm90b3R5cGUgPSB7fTtcblxuLy8gMjUuMS4yLjEuMSAlSXRlcmF0b3JQcm90b3R5cGUlW0BAaXRlcmF0b3JdKClcbnJlcXVpcmUoJy4vX2hpZGUnKShJdGVyYXRvclByb3RvdHlwZSwgcmVxdWlyZSgnLi9fd2tzJykoJ2l0ZXJhdG9yJyksIGZ1bmN0aW9uKCl7IHJldHVybiB0aGlzOyB9KTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihDb25zdHJ1Y3RvciwgTkFNRSwgbmV4dCl7XG4gIENvbnN0cnVjdG9yLnByb3RvdHlwZSA9IGNyZWF0ZShJdGVyYXRvclByb3RvdHlwZSwge25leHQ6IGRlc2NyaXB0b3IoMSwgbmV4dCl9KTtcbiAgc2V0VG9TdHJpbmdUYWcoQ29uc3RydWN0b3IsIE5BTUUgKyAnIEl0ZXJhdG9yJyk7XG59OyIsIid1c2Ugc3RyaWN0JztcbnZhciBMSUJSQVJZICAgICAgICA9IHJlcXVpcmUoJy4vX2xpYnJhcnknKVxuICAsICRleHBvcnQgICAgICAgID0gcmVxdWlyZSgnLi9fZXhwb3J0JylcbiAgLCByZWRlZmluZSAgICAgICA9IHJlcXVpcmUoJy4vX3JlZGVmaW5lJylcbiAgLCBoaWRlICAgICAgICAgICA9IHJlcXVpcmUoJy4vX2hpZGUnKVxuICAsIGhhcyAgICAgICAgICAgID0gcmVxdWlyZSgnLi9faGFzJylcbiAgLCBJdGVyYXRvcnMgICAgICA9IHJlcXVpcmUoJy4vX2l0ZXJhdG9ycycpXG4gICwgJGl0ZXJDcmVhdGUgICAgPSByZXF1aXJlKCcuL19pdGVyLWNyZWF0ZScpXG4gICwgc2V0VG9TdHJpbmdUYWcgPSByZXF1aXJlKCcuL19zZXQtdG8tc3RyaW5nLXRhZycpXG4gICwgZ2V0UHJvdG90eXBlT2YgPSByZXF1aXJlKCcuL19vYmplY3QtZ3BvJylcbiAgLCBJVEVSQVRPUiAgICAgICA9IHJlcXVpcmUoJy4vX3drcycpKCdpdGVyYXRvcicpXG4gICwgQlVHR1kgICAgICAgICAgPSAhKFtdLmtleXMgJiYgJ25leHQnIGluIFtdLmtleXMoKSkgLy8gU2FmYXJpIGhhcyBidWdneSBpdGVyYXRvcnMgdy9vIGBuZXh0YFxuICAsIEZGX0lURVJBVE9SICAgID0gJ0BAaXRlcmF0b3InXG4gICwgS0VZUyAgICAgICAgICAgPSAna2V5cydcbiAgLCBWQUxVRVMgICAgICAgICA9ICd2YWx1ZXMnO1xuXG52YXIgcmV0dXJuVGhpcyA9IGZ1bmN0aW9uKCl7IHJldHVybiB0aGlzOyB9O1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKEJhc2UsIE5BTUUsIENvbnN0cnVjdG9yLCBuZXh0LCBERUZBVUxULCBJU19TRVQsIEZPUkNFRCl7XG4gICRpdGVyQ3JlYXRlKENvbnN0cnVjdG9yLCBOQU1FLCBuZXh0KTtcbiAgdmFyIGdldE1ldGhvZCA9IGZ1bmN0aW9uKGtpbmQpe1xuICAgIGlmKCFCVUdHWSAmJiBraW5kIGluIHByb3RvKXJldHVybiBwcm90b1traW5kXTtcbiAgICBzd2l0Y2goa2luZCl7XG4gICAgICBjYXNlIEtFWVM6IHJldHVybiBmdW5jdGlvbiBrZXlzKCl7IHJldHVybiBuZXcgQ29uc3RydWN0b3IodGhpcywga2luZCk7IH07XG4gICAgICBjYXNlIFZBTFVFUzogcmV0dXJuIGZ1bmN0aW9uIHZhbHVlcygpeyByZXR1cm4gbmV3IENvbnN0cnVjdG9yKHRoaXMsIGtpbmQpOyB9O1xuICAgIH0gcmV0dXJuIGZ1bmN0aW9uIGVudHJpZXMoKXsgcmV0dXJuIG5ldyBDb25zdHJ1Y3Rvcih0aGlzLCBraW5kKTsgfTtcbiAgfTtcbiAgdmFyIFRBRyAgICAgICAgPSBOQU1FICsgJyBJdGVyYXRvcidcbiAgICAsIERFRl9WQUxVRVMgPSBERUZBVUxUID09IFZBTFVFU1xuICAgICwgVkFMVUVTX0JVRyA9IGZhbHNlXG4gICAgLCBwcm90byAgICAgID0gQmFzZS5wcm90b3R5cGVcbiAgICAsICRuYXRpdmUgICAgPSBwcm90b1tJVEVSQVRPUl0gfHwgcHJvdG9bRkZfSVRFUkFUT1JdIHx8IERFRkFVTFQgJiYgcHJvdG9bREVGQVVMVF1cbiAgICAsICRkZWZhdWx0ICAgPSAkbmF0aXZlIHx8IGdldE1ldGhvZChERUZBVUxUKVxuICAgICwgJGVudHJpZXMgICA9IERFRkFVTFQgPyAhREVGX1ZBTFVFUyA/ICRkZWZhdWx0IDogZ2V0TWV0aG9kKCdlbnRyaWVzJykgOiB1bmRlZmluZWRcbiAgICAsICRhbnlOYXRpdmUgPSBOQU1FID09ICdBcnJheScgPyBwcm90by5lbnRyaWVzIHx8ICRuYXRpdmUgOiAkbmF0aXZlXG4gICAgLCBtZXRob2RzLCBrZXksIEl0ZXJhdG9yUHJvdG90eXBlO1xuICAvLyBGaXggbmF0aXZlXG4gIGlmKCRhbnlOYXRpdmUpe1xuICAgIEl0ZXJhdG9yUHJvdG90eXBlID0gZ2V0UHJvdG90eXBlT2YoJGFueU5hdGl2ZS5jYWxsKG5ldyBCYXNlKSk7XG4gICAgaWYoSXRlcmF0b3JQcm90b3R5cGUgIT09IE9iamVjdC5wcm90b3R5cGUpe1xuICAgICAgLy8gU2V0IEBAdG9TdHJpbmdUYWcgdG8gbmF0aXZlIGl0ZXJhdG9yc1xuICAgICAgc2V0VG9TdHJpbmdUYWcoSXRlcmF0b3JQcm90b3R5cGUsIFRBRywgdHJ1ZSk7XG4gICAgICAvLyBmaXggZm9yIHNvbWUgb2xkIGVuZ2luZXNcbiAgICAgIGlmKCFMSUJSQVJZICYmICFoYXMoSXRlcmF0b3JQcm90b3R5cGUsIElURVJBVE9SKSloaWRlKEl0ZXJhdG9yUHJvdG90eXBlLCBJVEVSQVRPUiwgcmV0dXJuVGhpcyk7XG4gICAgfVxuICB9XG4gIC8vIGZpeCBBcnJheSN7dmFsdWVzLCBAQGl0ZXJhdG9yfS5uYW1lIGluIFY4IC8gRkZcbiAgaWYoREVGX1ZBTFVFUyAmJiAkbmF0aXZlICYmICRuYXRpdmUubmFtZSAhPT0gVkFMVUVTKXtcbiAgICBWQUxVRVNfQlVHID0gdHJ1ZTtcbiAgICAkZGVmYXVsdCA9IGZ1bmN0aW9uIHZhbHVlcygpeyByZXR1cm4gJG5hdGl2ZS5jYWxsKHRoaXMpOyB9O1xuICB9XG4gIC8vIERlZmluZSBpdGVyYXRvclxuICBpZigoIUxJQlJBUlkgfHwgRk9SQ0VEKSAmJiAoQlVHR1kgfHwgVkFMVUVTX0JVRyB8fCAhcHJvdG9bSVRFUkFUT1JdKSl7XG4gICAgaGlkZShwcm90bywgSVRFUkFUT1IsICRkZWZhdWx0KTtcbiAgfVxuICAvLyBQbHVnIGZvciBsaWJyYXJ5XG4gIEl0ZXJhdG9yc1tOQU1FXSA9ICRkZWZhdWx0O1xuICBJdGVyYXRvcnNbVEFHXSAgPSByZXR1cm5UaGlzO1xuICBpZihERUZBVUxUKXtcbiAgICBtZXRob2RzID0ge1xuICAgICAgdmFsdWVzOiAgREVGX1ZBTFVFUyA/ICRkZWZhdWx0IDogZ2V0TWV0aG9kKFZBTFVFUyksXG4gICAgICBrZXlzOiAgICBJU19TRVQgICAgID8gJGRlZmF1bHQgOiBnZXRNZXRob2QoS0VZUyksXG4gICAgICBlbnRyaWVzOiAkZW50cmllc1xuICAgIH07XG4gICAgaWYoRk9SQ0VEKWZvcihrZXkgaW4gbWV0aG9kcyl7XG4gICAgICBpZighKGtleSBpbiBwcm90bykpcmVkZWZpbmUocHJvdG8sIGtleSwgbWV0aG9kc1trZXldKTtcbiAgICB9IGVsc2UgJGV4cG9ydCgkZXhwb3J0LlAgKyAkZXhwb3J0LkYgKiAoQlVHR1kgfHwgVkFMVUVTX0JVRyksIE5BTUUsIG1ldGhvZHMpO1xuICB9XG4gIHJldHVybiBtZXRob2RzO1xufTsiLCJ2YXIgSVRFUkFUT1IgICAgID0gcmVxdWlyZSgnLi9fd2tzJykoJ2l0ZXJhdG9yJylcbiAgLCBTQUZFX0NMT1NJTkcgPSBmYWxzZTtcblxudHJ5IHtcbiAgdmFyIHJpdGVyID0gWzddW0lURVJBVE9SXSgpO1xuICByaXRlclsncmV0dXJuJ10gPSBmdW5jdGlvbigpeyBTQUZFX0NMT1NJTkcgPSB0cnVlOyB9O1xuICBBcnJheS5mcm9tKHJpdGVyLCBmdW5jdGlvbigpeyB0aHJvdyAyOyB9KTtcbn0gY2F0Y2goZSl7IC8qIGVtcHR5ICovIH1cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihleGVjLCBza2lwQ2xvc2luZyl7XG4gIGlmKCFza2lwQ2xvc2luZyAmJiAhU0FGRV9DTE9TSU5HKXJldHVybiBmYWxzZTtcbiAgdmFyIHNhZmUgPSBmYWxzZTtcbiAgdHJ5IHtcbiAgICB2YXIgYXJyICA9IFs3XVxuICAgICAgLCBpdGVyID0gYXJyW0lURVJBVE9SXSgpO1xuICAgIGl0ZXIubmV4dCA9IGZ1bmN0aW9uKCl7IHJldHVybiB7ZG9uZTogc2FmZSA9IHRydWV9OyB9O1xuICAgIGFycltJVEVSQVRPUl0gPSBmdW5jdGlvbigpeyByZXR1cm4gaXRlcjsgfTtcbiAgICBleGVjKGFycik7XG4gIH0gY2F0Y2goZSl7IC8qIGVtcHR5ICovIH1cbiAgcmV0dXJuIHNhZmU7XG59OyIsIm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oZG9uZSwgdmFsdWUpe1xuICByZXR1cm4ge3ZhbHVlOiB2YWx1ZSwgZG9uZTogISFkb25lfTtcbn07IiwibW9kdWxlLmV4cG9ydHMgPSB7fTsiLCJ2YXIgZ2V0S2V5cyAgID0gcmVxdWlyZSgnLi9fb2JqZWN0LWtleXMnKVxuICAsIHRvSU9iamVjdCA9IHJlcXVpcmUoJy4vX3RvLWlvYmplY3QnKTtcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24ob2JqZWN0LCBlbCl7XG4gIHZhciBPICAgICAgPSB0b0lPYmplY3Qob2JqZWN0KVxuICAgICwga2V5cyAgID0gZ2V0S2V5cyhPKVxuICAgICwgbGVuZ3RoID0ga2V5cy5sZW5ndGhcbiAgICAsIGluZGV4ICA9IDBcbiAgICAsIGtleTtcbiAgd2hpbGUobGVuZ3RoID4gaW5kZXgpaWYoT1trZXkgPSBrZXlzW2luZGV4KytdXSA9PT0gZWwpcmV0dXJuIGtleTtcbn07IiwibW9kdWxlLmV4cG9ydHMgPSB0cnVlOyIsInZhciBNRVRBICAgICA9IHJlcXVpcmUoJy4vX3VpZCcpKCdtZXRhJylcbiAgLCBpc09iamVjdCA9IHJlcXVpcmUoJy4vX2lzLW9iamVjdCcpXG4gICwgaGFzICAgICAgPSByZXF1aXJlKCcuL19oYXMnKVxuICAsIHNldERlc2MgID0gcmVxdWlyZSgnLi9fb2JqZWN0LWRwJykuZlxuICAsIGlkICAgICAgID0gMDtcbnZhciBpc0V4dGVuc2libGUgPSBPYmplY3QuaXNFeHRlbnNpYmxlIHx8IGZ1bmN0aW9uKCl7XG4gIHJldHVybiB0cnVlO1xufTtcbnZhciBGUkVFWkUgPSAhcmVxdWlyZSgnLi9fZmFpbHMnKShmdW5jdGlvbigpe1xuICByZXR1cm4gaXNFeHRlbnNpYmxlKE9iamVjdC5wcmV2ZW50RXh0ZW5zaW9ucyh7fSkpO1xufSk7XG52YXIgc2V0TWV0YSA9IGZ1bmN0aW9uKGl0KXtcbiAgc2V0RGVzYyhpdCwgTUVUQSwge3ZhbHVlOiB7XG4gICAgaTogJ08nICsgKytpZCwgLy8gb2JqZWN0IElEXG4gICAgdzoge30gICAgICAgICAgLy8gd2VhayBjb2xsZWN0aW9ucyBJRHNcbiAgfX0pO1xufTtcbnZhciBmYXN0S2V5ID0gZnVuY3Rpb24oaXQsIGNyZWF0ZSl7XG4gIC8vIHJldHVybiBwcmltaXRpdmUgd2l0aCBwcmVmaXhcbiAgaWYoIWlzT2JqZWN0KGl0KSlyZXR1cm4gdHlwZW9mIGl0ID09ICdzeW1ib2wnID8gaXQgOiAodHlwZW9mIGl0ID09ICdzdHJpbmcnID8gJ1MnIDogJ1AnKSArIGl0O1xuICBpZighaGFzKGl0LCBNRVRBKSl7XG4gICAgLy8gY2FuJ3Qgc2V0IG1ldGFkYXRhIHRvIHVuY2F1Z2h0IGZyb3plbiBvYmplY3RcbiAgICBpZighaXNFeHRlbnNpYmxlKGl0KSlyZXR1cm4gJ0YnO1xuICAgIC8vIG5vdCBuZWNlc3NhcnkgdG8gYWRkIG1ldGFkYXRhXG4gICAgaWYoIWNyZWF0ZSlyZXR1cm4gJ0UnO1xuICAgIC8vIGFkZCBtaXNzaW5nIG1ldGFkYXRhXG4gICAgc2V0TWV0YShpdCk7XG4gIC8vIHJldHVybiBvYmplY3QgSURcbiAgfSByZXR1cm4gaXRbTUVUQV0uaTtcbn07XG52YXIgZ2V0V2VhayA9IGZ1bmN0aW9uKGl0LCBjcmVhdGUpe1xuICBpZighaGFzKGl0LCBNRVRBKSl7XG4gICAgLy8gY2FuJ3Qgc2V0IG1ldGFkYXRhIHRvIHVuY2F1Z2h0IGZyb3plbiBvYmplY3RcbiAgICBpZighaXNFeHRlbnNpYmxlKGl0KSlyZXR1cm4gdHJ1ZTtcbiAgICAvLyBub3QgbmVjZXNzYXJ5IHRvIGFkZCBtZXRhZGF0YVxuICAgIGlmKCFjcmVhdGUpcmV0dXJuIGZhbHNlO1xuICAgIC8vIGFkZCBtaXNzaW5nIG1ldGFkYXRhXG4gICAgc2V0TWV0YShpdCk7XG4gIC8vIHJldHVybiBoYXNoIHdlYWsgY29sbGVjdGlvbnMgSURzXG4gIH0gcmV0dXJuIGl0W01FVEFdLnc7XG59O1xuLy8gYWRkIG1ldGFkYXRhIG9uIGZyZWV6ZS1mYW1pbHkgbWV0aG9kcyBjYWxsaW5nXG52YXIgb25GcmVlemUgPSBmdW5jdGlvbihpdCl7XG4gIGlmKEZSRUVaRSAmJiBtZXRhLk5FRUQgJiYgaXNFeHRlbnNpYmxlKGl0KSAmJiAhaGFzKGl0LCBNRVRBKSlzZXRNZXRhKGl0KTtcbiAgcmV0dXJuIGl0O1xufTtcbnZhciBtZXRhID0gbW9kdWxlLmV4cG9ydHMgPSB7XG4gIEtFWTogICAgICBNRVRBLFxuICBORUVEOiAgICAgZmFsc2UsXG4gIGZhc3RLZXk6ICBmYXN0S2V5LFxuICBnZXRXZWFrOiAgZ2V0V2VhayxcbiAgb25GcmVlemU6IG9uRnJlZXplXG59OyIsInZhciBnbG9iYWwgICAgPSByZXF1aXJlKCcuL19nbG9iYWwnKVxuICAsIG1hY3JvdGFzayA9IHJlcXVpcmUoJy4vX3Rhc2snKS5zZXRcbiAgLCBPYnNlcnZlciAgPSBnbG9iYWwuTXV0YXRpb25PYnNlcnZlciB8fCBnbG9iYWwuV2ViS2l0TXV0YXRpb25PYnNlcnZlclxuICAsIHByb2Nlc3MgICA9IGdsb2JhbC5wcm9jZXNzXG4gICwgUHJvbWlzZSAgID0gZ2xvYmFsLlByb21pc2VcbiAgLCBpc05vZGUgICAgPSByZXF1aXJlKCcuL19jb2YnKShwcm9jZXNzKSA9PSAncHJvY2Vzcyc7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oKXtcbiAgdmFyIGhlYWQsIGxhc3QsIG5vdGlmeTtcblxuICB2YXIgZmx1c2ggPSBmdW5jdGlvbigpe1xuICAgIHZhciBwYXJlbnQsIGZuO1xuICAgIGlmKGlzTm9kZSAmJiAocGFyZW50ID0gcHJvY2Vzcy5kb21haW4pKXBhcmVudC5leGl0KCk7XG4gICAgd2hpbGUoaGVhZCl7XG4gICAgICBmbiAgID0gaGVhZC5mbjtcbiAgICAgIGhlYWQgPSBoZWFkLm5leHQ7XG4gICAgICB0cnkge1xuICAgICAgICBmbigpO1xuICAgICAgfSBjYXRjaChlKXtcbiAgICAgICAgaWYoaGVhZClub3RpZnkoKTtcbiAgICAgICAgZWxzZSBsYXN0ID0gdW5kZWZpbmVkO1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgIH0gbGFzdCA9IHVuZGVmaW5lZDtcbiAgICBpZihwYXJlbnQpcGFyZW50LmVudGVyKCk7XG4gIH07XG5cbiAgLy8gTm9kZS5qc1xuICBpZihpc05vZGUpe1xuICAgIG5vdGlmeSA9IGZ1bmN0aW9uKCl7XG4gICAgICBwcm9jZXNzLm5leHRUaWNrKGZsdXNoKTtcbiAgICB9O1xuICAvLyBicm93c2VycyB3aXRoIE11dGF0aW9uT2JzZXJ2ZXJcbiAgfSBlbHNlIGlmKE9ic2VydmVyKXtcbiAgICB2YXIgdG9nZ2xlID0gdHJ1ZVxuICAgICAgLCBub2RlICAgPSBkb2N1bWVudC5jcmVhdGVUZXh0Tm9kZSgnJyk7XG4gICAgbmV3IE9ic2VydmVyKGZsdXNoKS5vYnNlcnZlKG5vZGUsIHtjaGFyYWN0ZXJEYXRhOiB0cnVlfSk7IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgbm8tbmV3XG4gICAgbm90aWZ5ID0gZnVuY3Rpb24oKXtcbiAgICAgIG5vZGUuZGF0YSA9IHRvZ2dsZSA9ICF0b2dnbGU7XG4gICAgfTtcbiAgLy8gZW52aXJvbm1lbnRzIHdpdGggbWF5YmUgbm9uLWNvbXBsZXRlbHkgY29ycmVjdCwgYnV0IGV4aXN0ZW50IFByb21pc2VcbiAgfSBlbHNlIGlmKFByb21pc2UgJiYgUHJvbWlzZS5yZXNvbHZlKXtcbiAgICB2YXIgcHJvbWlzZSA9IFByb21pc2UucmVzb2x2ZSgpO1xuICAgIG5vdGlmeSA9IGZ1bmN0aW9uKCl7XG4gICAgICBwcm9taXNlLnRoZW4oZmx1c2gpO1xuICAgIH07XG4gIC8vIGZvciBvdGhlciBlbnZpcm9ubWVudHMgLSBtYWNyb3Rhc2sgYmFzZWQgb246XG4gIC8vIC0gc2V0SW1tZWRpYXRlXG4gIC8vIC0gTWVzc2FnZUNoYW5uZWxcbiAgLy8gLSB3aW5kb3cucG9zdE1lc3NhZ1xuICAvLyAtIG9ucmVhZHlzdGF0ZWNoYW5nZVxuICAvLyAtIHNldFRpbWVvdXRcbiAgfSBlbHNlIHtcbiAgICBub3RpZnkgPSBmdW5jdGlvbigpe1xuICAgICAgLy8gc3RyYW5nZSBJRSArIHdlYnBhY2sgZGV2IHNlcnZlciBidWcgLSB1c2UgLmNhbGwoZ2xvYmFsKVxuICAgICAgbWFjcm90YXNrLmNhbGwoZ2xvYmFsLCBmbHVzaCk7XG4gICAgfTtcbiAgfVxuXG4gIHJldHVybiBmdW5jdGlvbihmbil7XG4gICAgdmFyIHRhc2sgPSB7Zm46IGZuLCBuZXh0OiB1bmRlZmluZWR9O1xuICAgIGlmKGxhc3QpbGFzdC5uZXh0ID0gdGFzaztcbiAgICBpZighaGVhZCl7XG4gICAgICBoZWFkID0gdGFzaztcbiAgICAgIG5vdGlmeSgpO1xuICAgIH0gbGFzdCA9IHRhc2s7XG4gIH07XG59OyIsIid1c2Ugc3RyaWN0Jztcbi8vIDE5LjEuMi4xIE9iamVjdC5hc3NpZ24odGFyZ2V0LCBzb3VyY2UsIC4uLilcbnZhciBnZXRLZXlzICA9IHJlcXVpcmUoJy4vX29iamVjdC1rZXlzJylcbiAgLCBnT1BTICAgICA9IHJlcXVpcmUoJy4vX29iamVjdC1nb3BzJylcbiAgLCBwSUUgICAgICA9IHJlcXVpcmUoJy4vX29iamVjdC1waWUnKVxuICAsIHRvT2JqZWN0ID0gcmVxdWlyZSgnLi9fdG8tb2JqZWN0JylcbiAgLCBJT2JqZWN0ICA9IHJlcXVpcmUoJy4vX2lvYmplY3QnKVxuICAsICRhc3NpZ24gID0gT2JqZWN0LmFzc2lnbjtcblxuLy8gc2hvdWxkIHdvcmsgd2l0aCBzeW1ib2xzIGFuZCBzaG91bGQgaGF2ZSBkZXRlcm1pbmlzdGljIHByb3BlcnR5IG9yZGVyIChWOCBidWcpXG5tb2R1bGUuZXhwb3J0cyA9ICEkYXNzaWduIHx8IHJlcXVpcmUoJy4vX2ZhaWxzJykoZnVuY3Rpb24oKXtcbiAgdmFyIEEgPSB7fVxuICAgICwgQiA9IHt9XG4gICAgLCBTID0gU3ltYm9sKClcbiAgICAsIEsgPSAnYWJjZGVmZ2hpamtsbW5vcHFyc3QnO1xuICBBW1NdID0gNztcbiAgSy5zcGxpdCgnJykuZm9yRWFjaChmdW5jdGlvbihrKXsgQltrXSA9IGs7IH0pO1xuICByZXR1cm4gJGFzc2lnbih7fSwgQSlbU10gIT0gNyB8fCBPYmplY3Qua2V5cygkYXNzaWduKHt9LCBCKSkuam9pbignJykgIT0gSztcbn0pID8gZnVuY3Rpb24gYXNzaWduKHRhcmdldCwgc291cmNlKXsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby11bnVzZWQtdmFyc1xuICB2YXIgVCAgICAgPSB0b09iamVjdCh0YXJnZXQpXG4gICAgLCBhTGVuICA9IGFyZ3VtZW50cy5sZW5ndGhcbiAgICAsIGluZGV4ID0gMVxuICAgICwgZ2V0U3ltYm9scyA9IGdPUFMuZlxuICAgICwgaXNFbnVtICAgICA9IHBJRS5mO1xuICB3aGlsZShhTGVuID4gaW5kZXgpe1xuICAgIHZhciBTICAgICAgPSBJT2JqZWN0KGFyZ3VtZW50c1tpbmRleCsrXSlcbiAgICAgICwga2V5cyAgID0gZ2V0U3ltYm9scyA/IGdldEtleXMoUykuY29uY2F0KGdldFN5bWJvbHMoUykpIDogZ2V0S2V5cyhTKVxuICAgICAgLCBsZW5ndGggPSBrZXlzLmxlbmd0aFxuICAgICAgLCBqICAgICAgPSAwXG4gICAgICAsIGtleTtcbiAgICB3aGlsZShsZW5ndGggPiBqKWlmKGlzRW51bS5jYWxsKFMsIGtleSA9IGtleXNbaisrXSkpVFtrZXldID0gU1trZXldO1xuICB9IHJldHVybiBUO1xufSA6ICRhc3NpZ247IiwiLy8gMTkuMS4yLjIgLyAxNS4yLjMuNSBPYmplY3QuY3JlYXRlKE8gWywgUHJvcGVydGllc10pXG52YXIgYW5PYmplY3QgICAgPSByZXF1aXJlKCcuL19hbi1vYmplY3QnKVxuICAsIGRQcyAgICAgICAgID0gcmVxdWlyZSgnLi9fb2JqZWN0LWRwcycpXG4gICwgZW51bUJ1Z0tleXMgPSByZXF1aXJlKCcuL19lbnVtLWJ1Zy1rZXlzJylcbiAgLCBJRV9QUk9UTyAgICA9IHJlcXVpcmUoJy4vX3NoYXJlZC1rZXknKSgnSUVfUFJPVE8nKVxuICAsIEVtcHR5ICAgICAgID0gZnVuY3Rpb24oKXsgLyogZW1wdHkgKi8gfVxuICAsIFBST1RPVFlQRSAgID0gJ3Byb3RvdHlwZSc7XG5cbi8vIENyZWF0ZSBvYmplY3Qgd2l0aCBmYWtlIGBudWxsYCBwcm90b3R5cGU6IHVzZSBpZnJhbWUgT2JqZWN0IHdpdGggY2xlYXJlZCBwcm90b3R5cGVcbnZhciBjcmVhdGVEaWN0ID0gZnVuY3Rpb24oKXtcbiAgLy8gVGhyYXNoLCB3YXN0ZSBhbmQgc29kb215OiBJRSBHQyBidWdcbiAgdmFyIGlmcmFtZSA9IHJlcXVpcmUoJy4vX2RvbS1jcmVhdGUnKSgnaWZyYW1lJylcbiAgICAsIGkgICAgICA9IGVudW1CdWdLZXlzLmxlbmd0aFxuICAgICwgbHQgICAgID0gJzwnXG4gICAgLCBndCAgICAgPSAnPidcbiAgICAsIGlmcmFtZURvY3VtZW50O1xuICBpZnJhbWUuc3R5bGUuZGlzcGxheSA9ICdub25lJztcbiAgcmVxdWlyZSgnLi9faHRtbCcpLmFwcGVuZENoaWxkKGlmcmFtZSk7XG4gIGlmcmFtZS5zcmMgPSAnamF2YXNjcmlwdDonOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLXNjcmlwdC11cmxcbiAgLy8gY3JlYXRlRGljdCA9IGlmcmFtZS5jb250ZW50V2luZG93Lk9iamVjdDtcbiAgLy8gaHRtbC5yZW1vdmVDaGlsZChpZnJhbWUpO1xuICBpZnJhbWVEb2N1bWVudCA9IGlmcmFtZS5jb250ZW50V2luZG93LmRvY3VtZW50O1xuICBpZnJhbWVEb2N1bWVudC5vcGVuKCk7XG4gIGlmcmFtZURvY3VtZW50LndyaXRlKGx0ICsgJ3NjcmlwdCcgKyBndCArICdkb2N1bWVudC5GPU9iamVjdCcgKyBsdCArICcvc2NyaXB0JyArIGd0KTtcbiAgaWZyYW1lRG9jdW1lbnQuY2xvc2UoKTtcbiAgY3JlYXRlRGljdCA9IGlmcmFtZURvY3VtZW50LkY7XG4gIHdoaWxlKGktLSlkZWxldGUgY3JlYXRlRGljdFtQUk9UT1RZUEVdW2VudW1CdWdLZXlzW2ldXTtcbiAgcmV0dXJuIGNyZWF0ZURpY3QoKTtcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gT2JqZWN0LmNyZWF0ZSB8fCBmdW5jdGlvbiBjcmVhdGUoTywgUHJvcGVydGllcyl7XG4gIHZhciByZXN1bHQ7XG4gIGlmKE8gIT09IG51bGwpe1xuICAgIEVtcHR5W1BST1RPVFlQRV0gPSBhbk9iamVjdChPKTtcbiAgICByZXN1bHQgPSBuZXcgRW1wdHk7XG4gICAgRW1wdHlbUFJPVE9UWVBFXSA9IG51bGw7XG4gICAgLy8gYWRkIFwiX19wcm90b19fXCIgZm9yIE9iamVjdC5nZXRQcm90b3R5cGVPZiBwb2x5ZmlsbFxuICAgIHJlc3VsdFtJRV9QUk9UT10gPSBPO1xuICB9IGVsc2UgcmVzdWx0ID0gY3JlYXRlRGljdCgpO1xuICByZXR1cm4gUHJvcGVydGllcyA9PT0gdW5kZWZpbmVkID8gcmVzdWx0IDogZFBzKHJlc3VsdCwgUHJvcGVydGllcyk7XG59O1xuIiwidmFyIGFuT2JqZWN0ICAgICAgID0gcmVxdWlyZSgnLi9fYW4tb2JqZWN0JylcbiAgLCBJRThfRE9NX0RFRklORSA9IHJlcXVpcmUoJy4vX2llOC1kb20tZGVmaW5lJylcbiAgLCB0b1ByaW1pdGl2ZSAgICA9IHJlcXVpcmUoJy4vX3RvLXByaW1pdGl2ZScpXG4gICwgZFAgICAgICAgICAgICAgPSBPYmplY3QuZGVmaW5lUHJvcGVydHk7XG5cbmV4cG9ydHMuZiA9IHJlcXVpcmUoJy4vX2Rlc2NyaXB0b3JzJykgPyBPYmplY3QuZGVmaW5lUHJvcGVydHkgOiBmdW5jdGlvbiBkZWZpbmVQcm9wZXJ0eShPLCBQLCBBdHRyaWJ1dGVzKXtcbiAgYW5PYmplY3QoTyk7XG4gIFAgPSB0b1ByaW1pdGl2ZShQLCB0cnVlKTtcbiAgYW5PYmplY3QoQXR0cmlidXRlcyk7XG4gIGlmKElFOF9ET01fREVGSU5FKXRyeSB7XG4gICAgcmV0dXJuIGRQKE8sIFAsIEF0dHJpYnV0ZXMpO1xuICB9IGNhdGNoKGUpeyAvKiBlbXB0eSAqLyB9XG4gIGlmKCdnZXQnIGluIEF0dHJpYnV0ZXMgfHwgJ3NldCcgaW4gQXR0cmlidXRlcyl0aHJvdyBUeXBlRXJyb3IoJ0FjY2Vzc29ycyBub3Qgc3VwcG9ydGVkIScpO1xuICBpZigndmFsdWUnIGluIEF0dHJpYnV0ZXMpT1tQXSA9IEF0dHJpYnV0ZXMudmFsdWU7XG4gIHJldHVybiBPO1xufTsiLCJ2YXIgZFAgICAgICAgPSByZXF1aXJlKCcuL19vYmplY3QtZHAnKVxuICAsIGFuT2JqZWN0ID0gcmVxdWlyZSgnLi9fYW4tb2JqZWN0JylcbiAgLCBnZXRLZXlzICA9IHJlcXVpcmUoJy4vX29iamVjdC1rZXlzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi9fZGVzY3JpcHRvcnMnKSA/IE9iamVjdC5kZWZpbmVQcm9wZXJ0aWVzIDogZnVuY3Rpb24gZGVmaW5lUHJvcGVydGllcyhPLCBQcm9wZXJ0aWVzKXtcbiAgYW5PYmplY3QoTyk7XG4gIHZhciBrZXlzICAgPSBnZXRLZXlzKFByb3BlcnRpZXMpXG4gICAgLCBsZW5ndGggPSBrZXlzLmxlbmd0aFxuICAgICwgaSA9IDBcbiAgICAsIFA7XG4gIHdoaWxlKGxlbmd0aCA+IGkpZFAuZihPLCBQID0ga2V5c1tpKytdLCBQcm9wZXJ0aWVzW1BdKTtcbiAgcmV0dXJuIE87XG59OyIsInZhciBwSUUgICAgICAgICAgICA9IHJlcXVpcmUoJy4vX29iamVjdC1waWUnKVxuICAsIGNyZWF0ZURlc2MgICAgID0gcmVxdWlyZSgnLi9fcHJvcGVydHktZGVzYycpXG4gICwgdG9JT2JqZWN0ICAgICAgPSByZXF1aXJlKCcuL190by1pb2JqZWN0JylcbiAgLCB0b1ByaW1pdGl2ZSAgICA9IHJlcXVpcmUoJy4vX3RvLXByaW1pdGl2ZScpXG4gICwgaGFzICAgICAgICAgICAgPSByZXF1aXJlKCcuL19oYXMnKVxuICAsIElFOF9ET01fREVGSU5FID0gcmVxdWlyZSgnLi9faWU4LWRvbS1kZWZpbmUnKVxuICAsIGdPUEQgICAgICAgICAgID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcjtcblxuZXhwb3J0cy5mID0gcmVxdWlyZSgnLi9fZGVzY3JpcHRvcnMnKSA/IGdPUEQgOiBmdW5jdGlvbiBnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IoTywgUCl7XG4gIE8gPSB0b0lPYmplY3QoTyk7XG4gIFAgPSB0b1ByaW1pdGl2ZShQLCB0cnVlKTtcbiAgaWYoSUU4X0RPTV9ERUZJTkUpdHJ5IHtcbiAgICByZXR1cm4gZ09QRChPLCBQKTtcbiAgfSBjYXRjaChlKXsgLyogZW1wdHkgKi8gfVxuICBpZihoYXMoTywgUCkpcmV0dXJuIGNyZWF0ZURlc2MoIXBJRS5mLmNhbGwoTywgUCksIE9bUF0pO1xufTsiLCIvLyBmYWxsYmFjayBmb3IgSUUxMSBidWdneSBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyB3aXRoIGlmcmFtZSBhbmQgd2luZG93XG52YXIgdG9JT2JqZWN0ID0gcmVxdWlyZSgnLi9fdG8taW9iamVjdCcpXG4gICwgZ09QTiAgICAgID0gcmVxdWlyZSgnLi9fb2JqZWN0LWdvcG4nKS5mXG4gICwgdG9TdHJpbmcgID0ge30udG9TdHJpbmc7XG5cbnZhciB3aW5kb3dOYW1lcyA9IHR5cGVvZiB3aW5kb3cgPT0gJ29iamVjdCcgJiYgd2luZG93ICYmIE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzXG4gID8gT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXMod2luZG93KSA6IFtdO1xuXG52YXIgZ2V0V2luZG93TmFtZXMgPSBmdW5jdGlvbihpdCl7XG4gIHRyeSB7XG4gICAgcmV0dXJuIGdPUE4oaXQpO1xuICB9IGNhdGNoKGUpe1xuICAgIHJldHVybiB3aW5kb3dOYW1lcy5zbGljZSgpO1xuICB9XG59O1xuXG5tb2R1bGUuZXhwb3J0cy5mID0gZnVuY3Rpb24gZ2V0T3duUHJvcGVydHlOYW1lcyhpdCl7XG4gIHJldHVybiB3aW5kb3dOYW1lcyAmJiB0b1N0cmluZy5jYWxsKGl0KSA9PSAnW29iamVjdCBXaW5kb3ddJyA/IGdldFdpbmRvd05hbWVzKGl0KSA6IGdPUE4odG9JT2JqZWN0KGl0KSk7XG59O1xuIiwiLy8gMTkuMS4yLjcgLyAxNS4yLjMuNCBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyhPKVxudmFyICRrZXlzICAgICAgPSByZXF1aXJlKCcuL19vYmplY3Qta2V5cy1pbnRlcm5hbCcpXG4gICwgaGlkZGVuS2V5cyA9IHJlcXVpcmUoJy4vX2VudW0tYnVnLWtleXMnKS5jb25jYXQoJ2xlbmd0aCcsICdwcm90b3R5cGUnKTtcblxuZXhwb3J0cy5mID0gT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXMgfHwgZnVuY3Rpb24gZ2V0T3duUHJvcGVydHlOYW1lcyhPKXtcbiAgcmV0dXJuICRrZXlzKE8sIGhpZGRlbktleXMpO1xufTsiLCJleHBvcnRzLmYgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzOyIsIi8vIDE5LjEuMi45IC8gMTUuMi4zLjIgT2JqZWN0LmdldFByb3RvdHlwZU9mKE8pXG52YXIgaGFzICAgICAgICAgPSByZXF1aXJlKCcuL19oYXMnKVxuICAsIHRvT2JqZWN0ICAgID0gcmVxdWlyZSgnLi9fdG8tb2JqZWN0JylcbiAgLCBJRV9QUk9UTyAgICA9IHJlcXVpcmUoJy4vX3NoYXJlZC1rZXknKSgnSUVfUFJPVE8nKVxuICAsIE9iamVjdFByb3RvID0gT2JqZWN0LnByb3RvdHlwZTtcblxubW9kdWxlLmV4cG9ydHMgPSBPYmplY3QuZ2V0UHJvdG90eXBlT2YgfHwgZnVuY3Rpb24oTyl7XG4gIE8gPSB0b09iamVjdChPKTtcbiAgaWYoaGFzKE8sIElFX1BST1RPKSlyZXR1cm4gT1tJRV9QUk9UT107XG4gIGlmKHR5cGVvZiBPLmNvbnN0cnVjdG9yID09ICdmdW5jdGlvbicgJiYgTyBpbnN0YW5jZW9mIE8uY29uc3RydWN0b3Ipe1xuICAgIHJldHVybiBPLmNvbnN0cnVjdG9yLnByb3RvdHlwZTtcbiAgfSByZXR1cm4gTyBpbnN0YW5jZW9mIE9iamVjdCA/IE9iamVjdFByb3RvIDogbnVsbDtcbn07IiwidmFyIGhhcyAgICAgICAgICA9IHJlcXVpcmUoJy4vX2hhcycpXG4gICwgdG9JT2JqZWN0ICAgID0gcmVxdWlyZSgnLi9fdG8taW9iamVjdCcpXG4gICwgYXJyYXlJbmRleE9mID0gcmVxdWlyZSgnLi9fYXJyYXktaW5jbHVkZXMnKShmYWxzZSlcbiAgLCBJRV9QUk9UTyAgICAgPSByZXF1aXJlKCcuL19zaGFyZWQta2V5JykoJ0lFX1BST1RPJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24ob2JqZWN0LCBuYW1lcyl7XG4gIHZhciBPICAgICAgPSB0b0lPYmplY3Qob2JqZWN0KVxuICAgICwgaSAgICAgID0gMFxuICAgICwgcmVzdWx0ID0gW11cbiAgICAsIGtleTtcbiAgZm9yKGtleSBpbiBPKWlmKGtleSAhPSBJRV9QUk9UTyloYXMoTywga2V5KSAmJiByZXN1bHQucHVzaChrZXkpO1xuICAvLyBEb24ndCBlbnVtIGJ1ZyAmIGhpZGRlbiBrZXlzXG4gIHdoaWxlKG5hbWVzLmxlbmd0aCA+IGkpaWYoaGFzKE8sIGtleSA9IG5hbWVzW2krK10pKXtcbiAgICB+YXJyYXlJbmRleE9mKHJlc3VsdCwga2V5KSB8fCByZXN1bHQucHVzaChrZXkpO1xuICB9XG4gIHJldHVybiByZXN1bHQ7XG59OyIsIi8vIDE5LjEuMi4xNCAvIDE1LjIuMy4xNCBPYmplY3Qua2V5cyhPKVxudmFyICRrZXlzICAgICAgID0gcmVxdWlyZSgnLi9fb2JqZWN0LWtleXMtaW50ZXJuYWwnKVxuICAsIGVudW1CdWdLZXlzID0gcmVxdWlyZSgnLi9fZW51bS1idWcta2V5cycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IE9iamVjdC5rZXlzIHx8IGZ1bmN0aW9uIGtleXMoTyl7XG4gIHJldHVybiAka2V5cyhPLCBlbnVtQnVnS2V5cyk7XG59OyIsImV4cG9ydHMuZiA9IHt9LnByb3BlcnR5SXNFbnVtZXJhYmxlOyIsIi8vIG1vc3QgT2JqZWN0IG1ldGhvZHMgYnkgRVM2IHNob3VsZCBhY2NlcHQgcHJpbWl0aXZlc1xudmFyICRleHBvcnQgPSByZXF1aXJlKCcuL19leHBvcnQnKVxuICAsIGNvcmUgICAgPSByZXF1aXJlKCcuL19jb3JlJylcbiAgLCBmYWlscyAgID0gcmVxdWlyZSgnLi9fZmFpbHMnKTtcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oS0VZLCBleGVjKXtcbiAgdmFyIGZuICA9IChjb3JlLk9iamVjdCB8fCB7fSlbS0VZXSB8fCBPYmplY3RbS0VZXVxuICAgICwgZXhwID0ge307XG4gIGV4cFtLRVldID0gZXhlYyhmbik7XG4gICRleHBvcnQoJGV4cG9ydC5TICsgJGV4cG9ydC5GICogZmFpbHMoZnVuY3Rpb24oKXsgZm4oMSk7IH0pLCAnT2JqZWN0JywgZXhwKTtcbn07IiwibW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihiaXRtYXAsIHZhbHVlKXtcbiAgcmV0dXJuIHtcbiAgICBlbnVtZXJhYmxlICA6ICEoYml0bWFwICYgMSksXG4gICAgY29uZmlndXJhYmxlOiAhKGJpdG1hcCAmIDIpLFxuICAgIHdyaXRhYmxlICAgIDogIShiaXRtYXAgJiA0KSxcbiAgICB2YWx1ZSAgICAgICA6IHZhbHVlXG4gIH07XG59OyIsInZhciBoaWRlID0gcmVxdWlyZSgnLi9faGlkZScpO1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbih0YXJnZXQsIHNyYywgc2FmZSl7XG4gIGZvcih2YXIga2V5IGluIHNyYyl7XG4gICAgaWYoc2FmZSAmJiB0YXJnZXRba2V5XSl0YXJnZXRba2V5XSA9IHNyY1trZXldO1xuICAgIGVsc2UgaGlkZSh0YXJnZXQsIGtleSwgc3JjW2tleV0pO1xuICB9IHJldHVybiB0YXJnZXQ7XG59OyIsIm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi9faGlkZScpOyIsIi8vIFdvcmtzIHdpdGggX19wcm90b19fIG9ubHkuIE9sZCB2OCBjYW4ndCB3b3JrIHdpdGggbnVsbCBwcm90byBvYmplY3RzLlxuLyogZXNsaW50LWRpc2FibGUgbm8tcHJvdG8gKi9cbnZhciBpc09iamVjdCA9IHJlcXVpcmUoJy4vX2lzLW9iamVjdCcpXG4gICwgYW5PYmplY3QgPSByZXF1aXJlKCcuL19hbi1vYmplY3QnKTtcbnZhciBjaGVjayA9IGZ1bmN0aW9uKE8sIHByb3RvKXtcbiAgYW5PYmplY3QoTyk7XG4gIGlmKCFpc09iamVjdChwcm90bykgJiYgcHJvdG8gIT09IG51bGwpdGhyb3cgVHlwZUVycm9yKHByb3RvICsgXCI6IGNhbid0IHNldCBhcyBwcm90b3R5cGUhXCIpO1xufTtcbm1vZHVsZS5leHBvcnRzID0ge1xuICBzZXQ6IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fCAoJ19fcHJvdG9fXycgaW4ge30gPyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lXG4gICAgZnVuY3Rpb24odGVzdCwgYnVnZ3ksIHNldCl7XG4gICAgICB0cnkge1xuICAgICAgICBzZXQgPSByZXF1aXJlKCcuL19jdHgnKShGdW5jdGlvbi5jYWxsLCByZXF1aXJlKCcuL19vYmplY3QtZ29wZCcpLmYoT2JqZWN0LnByb3RvdHlwZSwgJ19fcHJvdG9fXycpLnNldCwgMik7XG4gICAgICAgIHNldCh0ZXN0LCBbXSk7XG4gICAgICAgIGJ1Z2d5ID0gISh0ZXN0IGluc3RhbmNlb2YgQXJyYXkpO1xuICAgICAgfSBjYXRjaChlKXsgYnVnZ3kgPSB0cnVlOyB9XG4gICAgICByZXR1cm4gZnVuY3Rpb24gc2V0UHJvdG90eXBlT2YoTywgcHJvdG8pe1xuICAgICAgICBjaGVjayhPLCBwcm90byk7XG4gICAgICAgIGlmKGJ1Z2d5KU8uX19wcm90b19fID0gcHJvdG87XG4gICAgICAgIGVsc2Ugc2V0KE8sIHByb3RvKTtcbiAgICAgICAgcmV0dXJuIE87XG4gICAgICB9O1xuICAgIH0oe30sIGZhbHNlKSA6IHVuZGVmaW5lZCksXG4gIGNoZWNrOiBjaGVja1xufTsiLCIndXNlIHN0cmljdCc7XG52YXIgZ2xvYmFsICAgICAgPSByZXF1aXJlKCcuL19nbG9iYWwnKVxuICAsIGNvcmUgICAgICAgID0gcmVxdWlyZSgnLi9fY29yZScpXG4gICwgZFAgICAgICAgICAgPSByZXF1aXJlKCcuL19vYmplY3QtZHAnKVxuICAsIERFU0NSSVBUT1JTID0gcmVxdWlyZSgnLi9fZGVzY3JpcHRvcnMnKVxuICAsIFNQRUNJRVMgICAgID0gcmVxdWlyZSgnLi9fd2tzJykoJ3NwZWNpZXMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihLRVkpe1xuICB2YXIgQyA9IHR5cGVvZiBjb3JlW0tFWV0gPT0gJ2Z1bmN0aW9uJyA/IGNvcmVbS0VZXSA6IGdsb2JhbFtLRVldO1xuICBpZihERVNDUklQVE9SUyAmJiBDICYmICFDW1NQRUNJRVNdKWRQLmYoQywgU1BFQ0lFUywge1xuICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSxcbiAgICBnZXQ6IGZ1bmN0aW9uKCl7IHJldHVybiB0aGlzOyB9XG4gIH0pO1xufTsiLCJ2YXIgZGVmID0gcmVxdWlyZSgnLi9fb2JqZWN0LWRwJykuZlxuICAsIGhhcyA9IHJlcXVpcmUoJy4vX2hhcycpXG4gICwgVEFHID0gcmVxdWlyZSgnLi9fd2tzJykoJ3RvU3RyaW5nVGFnJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oaXQsIHRhZywgc3RhdCl7XG4gIGlmKGl0ICYmICFoYXMoaXQgPSBzdGF0ID8gaXQgOiBpdC5wcm90b3R5cGUsIFRBRykpZGVmKGl0LCBUQUcsIHtjb25maWd1cmFibGU6IHRydWUsIHZhbHVlOiB0YWd9KTtcbn07IiwidmFyIHNoYXJlZCA9IHJlcXVpcmUoJy4vX3NoYXJlZCcpKCdrZXlzJylcbiAgLCB1aWQgICAgPSByZXF1aXJlKCcuL191aWQnKTtcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oa2V5KXtcbiAgcmV0dXJuIHNoYXJlZFtrZXldIHx8IChzaGFyZWRba2V5XSA9IHVpZChrZXkpKTtcbn07IiwidmFyIGdsb2JhbCA9IHJlcXVpcmUoJy4vX2dsb2JhbCcpXG4gICwgU0hBUkVEID0gJ19fY29yZS1qc19zaGFyZWRfXydcbiAgLCBzdG9yZSAgPSBnbG9iYWxbU0hBUkVEXSB8fCAoZ2xvYmFsW1NIQVJFRF0gPSB7fSk7XG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKGtleSl7XG4gIHJldHVybiBzdG9yZVtrZXldIHx8IChzdG9yZVtrZXldID0ge30pO1xufTsiLCIvLyA3LjMuMjAgU3BlY2llc0NvbnN0cnVjdG9yKE8sIGRlZmF1bHRDb25zdHJ1Y3RvcilcbnZhciBhbk9iamVjdCAgPSByZXF1aXJlKCcuL19hbi1vYmplY3QnKVxuICAsIGFGdW5jdGlvbiA9IHJlcXVpcmUoJy4vX2EtZnVuY3Rpb24nKVxuICAsIFNQRUNJRVMgICA9IHJlcXVpcmUoJy4vX3drcycpKCdzcGVjaWVzJyk7XG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKE8sIEQpe1xuICB2YXIgQyA9IGFuT2JqZWN0KE8pLmNvbnN0cnVjdG9yLCBTO1xuICByZXR1cm4gQyA9PT0gdW5kZWZpbmVkIHx8IChTID0gYW5PYmplY3QoQylbU1BFQ0lFU10pID09IHVuZGVmaW5lZCA/IEQgOiBhRnVuY3Rpb24oUyk7XG59OyIsInZhciB0b0ludGVnZXIgPSByZXF1aXJlKCcuL190by1pbnRlZ2VyJylcbiAgLCBkZWZpbmVkICAgPSByZXF1aXJlKCcuL19kZWZpbmVkJyk7XG4vLyB0cnVlICAtPiBTdHJpbmcjYXRcbi8vIGZhbHNlIC0+IFN0cmluZyNjb2RlUG9pbnRBdFxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihUT19TVFJJTkcpe1xuICByZXR1cm4gZnVuY3Rpb24odGhhdCwgcG9zKXtcbiAgICB2YXIgcyA9IFN0cmluZyhkZWZpbmVkKHRoYXQpKVxuICAgICAgLCBpID0gdG9JbnRlZ2VyKHBvcylcbiAgICAgICwgbCA9IHMubGVuZ3RoXG4gICAgICAsIGEsIGI7XG4gICAgaWYoaSA8IDAgfHwgaSA+PSBsKXJldHVybiBUT19TVFJJTkcgPyAnJyA6IHVuZGVmaW5lZDtcbiAgICBhID0gcy5jaGFyQ29kZUF0KGkpO1xuICAgIHJldHVybiBhIDwgMHhkODAwIHx8IGEgPiAweGRiZmYgfHwgaSArIDEgPT09IGwgfHwgKGIgPSBzLmNoYXJDb2RlQXQoaSArIDEpKSA8IDB4ZGMwMCB8fCBiID4gMHhkZmZmXG4gICAgICA/IFRPX1NUUklORyA/IHMuY2hhckF0KGkpIDogYVxuICAgICAgOiBUT19TVFJJTkcgPyBzLnNsaWNlKGksIGkgKyAyKSA6IChhIC0gMHhkODAwIDw8IDEwKSArIChiIC0gMHhkYzAwKSArIDB4MTAwMDA7XG4gIH07XG59OyIsInZhciBjdHggICAgICAgICAgICAgICAgPSByZXF1aXJlKCcuL19jdHgnKVxuICAsIGludm9rZSAgICAgICAgICAgICA9IHJlcXVpcmUoJy4vX2ludm9rZScpXG4gICwgaHRtbCAgICAgICAgICAgICAgID0gcmVxdWlyZSgnLi9faHRtbCcpXG4gICwgY2VsICAgICAgICAgICAgICAgID0gcmVxdWlyZSgnLi9fZG9tLWNyZWF0ZScpXG4gICwgZ2xvYmFsICAgICAgICAgICAgID0gcmVxdWlyZSgnLi9fZ2xvYmFsJylcbiAgLCBwcm9jZXNzICAgICAgICAgICAgPSBnbG9iYWwucHJvY2Vzc1xuICAsIHNldFRhc2sgICAgICAgICAgICA9IGdsb2JhbC5zZXRJbW1lZGlhdGVcbiAgLCBjbGVhclRhc2sgICAgICAgICAgPSBnbG9iYWwuY2xlYXJJbW1lZGlhdGVcbiAgLCBNZXNzYWdlQ2hhbm5lbCAgICAgPSBnbG9iYWwuTWVzc2FnZUNoYW5uZWxcbiAgLCBjb3VudGVyICAgICAgICAgICAgPSAwXG4gICwgcXVldWUgICAgICAgICAgICAgID0ge31cbiAgLCBPTlJFQURZU1RBVEVDSEFOR0UgPSAnb25yZWFkeXN0YXRlY2hhbmdlJ1xuICAsIGRlZmVyLCBjaGFubmVsLCBwb3J0O1xudmFyIHJ1biA9IGZ1bmN0aW9uKCl7XG4gIHZhciBpZCA9ICt0aGlzO1xuICBpZihxdWV1ZS5oYXNPd25Qcm9wZXJ0eShpZCkpe1xuICAgIHZhciBmbiA9IHF1ZXVlW2lkXTtcbiAgICBkZWxldGUgcXVldWVbaWRdO1xuICAgIGZuKCk7XG4gIH1cbn07XG52YXIgbGlzdGVuZXIgPSBmdW5jdGlvbihldmVudCl7XG4gIHJ1bi5jYWxsKGV2ZW50LmRhdGEpO1xufTtcbi8vIE5vZGUuanMgMC45KyAmIElFMTArIGhhcyBzZXRJbW1lZGlhdGUsIG90aGVyd2lzZTpcbmlmKCFzZXRUYXNrIHx8ICFjbGVhclRhc2spe1xuICBzZXRUYXNrID0gZnVuY3Rpb24gc2V0SW1tZWRpYXRlKGZuKXtcbiAgICB2YXIgYXJncyA9IFtdLCBpID0gMTtcbiAgICB3aGlsZShhcmd1bWVudHMubGVuZ3RoID4gaSlhcmdzLnB1c2goYXJndW1lbnRzW2krK10pO1xuICAgIHF1ZXVlWysrY291bnRlcl0gPSBmdW5jdGlvbigpe1xuICAgICAgaW52b2tlKHR5cGVvZiBmbiA9PSAnZnVuY3Rpb24nID8gZm4gOiBGdW5jdGlvbihmbiksIGFyZ3MpO1xuICAgIH07XG4gICAgZGVmZXIoY291bnRlcik7XG4gICAgcmV0dXJuIGNvdW50ZXI7XG4gIH07XG4gIGNsZWFyVGFzayA9IGZ1bmN0aW9uIGNsZWFySW1tZWRpYXRlKGlkKXtcbiAgICBkZWxldGUgcXVldWVbaWRdO1xuICB9O1xuICAvLyBOb2RlLmpzIDAuOC1cbiAgaWYocmVxdWlyZSgnLi9fY29mJykocHJvY2VzcykgPT0gJ3Byb2Nlc3MnKXtcbiAgICBkZWZlciA9IGZ1bmN0aW9uKGlkKXtcbiAgICAgIHByb2Nlc3MubmV4dFRpY2soY3R4KHJ1biwgaWQsIDEpKTtcbiAgICB9O1xuICAvLyBCcm93c2VycyB3aXRoIE1lc3NhZ2VDaGFubmVsLCBpbmNsdWRlcyBXZWJXb3JrZXJzXG4gIH0gZWxzZSBpZihNZXNzYWdlQ2hhbm5lbCl7XG4gICAgY2hhbm5lbCA9IG5ldyBNZXNzYWdlQ2hhbm5lbDtcbiAgICBwb3J0ICAgID0gY2hhbm5lbC5wb3J0MjtcbiAgICBjaGFubmVsLnBvcnQxLm9ubWVzc2FnZSA9IGxpc3RlbmVyO1xuICAgIGRlZmVyID0gY3R4KHBvcnQucG9zdE1lc3NhZ2UsIHBvcnQsIDEpO1xuICAvLyBCcm93c2VycyB3aXRoIHBvc3RNZXNzYWdlLCBza2lwIFdlYldvcmtlcnNcbiAgLy8gSUU4IGhhcyBwb3N0TWVzc2FnZSwgYnV0IGl0J3Mgc3luYyAmIHR5cGVvZiBpdHMgcG9zdE1lc3NhZ2UgaXMgJ29iamVjdCdcbiAgfSBlbHNlIGlmKGdsb2JhbC5hZGRFdmVudExpc3RlbmVyICYmIHR5cGVvZiBwb3N0TWVzc2FnZSA9PSAnZnVuY3Rpb24nICYmICFnbG9iYWwuaW1wb3J0U2NyaXB0cyl7XG4gICAgZGVmZXIgPSBmdW5jdGlvbihpZCl7XG4gICAgICBnbG9iYWwucG9zdE1lc3NhZ2UoaWQgKyAnJywgJyonKTtcbiAgICB9O1xuICAgIGdsb2JhbC5hZGRFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgbGlzdGVuZXIsIGZhbHNlKTtcbiAgLy8gSUU4LVxuICB9IGVsc2UgaWYoT05SRUFEWVNUQVRFQ0hBTkdFIGluIGNlbCgnc2NyaXB0Jykpe1xuICAgIGRlZmVyID0gZnVuY3Rpb24oaWQpe1xuICAgICAgaHRtbC5hcHBlbmRDaGlsZChjZWwoJ3NjcmlwdCcpKVtPTlJFQURZU1RBVEVDSEFOR0VdID0gZnVuY3Rpb24oKXtcbiAgICAgICAgaHRtbC5yZW1vdmVDaGlsZCh0aGlzKTtcbiAgICAgICAgcnVuLmNhbGwoaWQpO1xuICAgICAgfTtcbiAgICB9O1xuICAvLyBSZXN0IG9sZCBicm93c2Vyc1xuICB9IGVsc2Uge1xuICAgIGRlZmVyID0gZnVuY3Rpb24oaWQpe1xuICAgICAgc2V0VGltZW91dChjdHgocnVuLCBpZCwgMSksIDApO1xuICAgIH07XG4gIH1cbn1cbm1vZHVsZS5leHBvcnRzID0ge1xuICBzZXQ6ICAgc2V0VGFzayxcbiAgY2xlYXI6IGNsZWFyVGFza1xufTsiLCJ2YXIgdG9JbnRlZ2VyID0gcmVxdWlyZSgnLi9fdG8taW50ZWdlcicpXG4gICwgbWF4ICAgICAgID0gTWF0aC5tYXhcbiAgLCBtaW4gICAgICAgPSBNYXRoLm1pbjtcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oaW5kZXgsIGxlbmd0aCl7XG4gIGluZGV4ID0gdG9JbnRlZ2VyKGluZGV4KTtcbiAgcmV0dXJuIGluZGV4IDwgMCA/IG1heChpbmRleCArIGxlbmd0aCwgMCkgOiBtaW4oaW5kZXgsIGxlbmd0aCk7XG59OyIsIi8vIDcuMS40IFRvSW50ZWdlclxudmFyIGNlaWwgID0gTWF0aC5jZWlsXG4gICwgZmxvb3IgPSBNYXRoLmZsb29yO1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihpdCl7XG4gIHJldHVybiBpc05hTihpdCA9ICtpdCkgPyAwIDogKGl0ID4gMCA/IGZsb29yIDogY2VpbCkoaXQpO1xufTsiLCIvLyB0byBpbmRleGVkIG9iamVjdCwgdG9PYmplY3Qgd2l0aCBmYWxsYmFjayBmb3Igbm9uLWFycmF5LWxpa2UgRVMzIHN0cmluZ3NcbnZhciBJT2JqZWN0ID0gcmVxdWlyZSgnLi9faW9iamVjdCcpXG4gICwgZGVmaW5lZCA9IHJlcXVpcmUoJy4vX2RlZmluZWQnKTtcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oaXQpe1xuICByZXR1cm4gSU9iamVjdChkZWZpbmVkKGl0KSk7XG59OyIsIi8vIDcuMS4xNSBUb0xlbmd0aFxudmFyIHRvSW50ZWdlciA9IHJlcXVpcmUoJy4vX3RvLWludGVnZXInKVxuICAsIG1pbiAgICAgICA9IE1hdGgubWluO1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihpdCl7XG4gIHJldHVybiBpdCA+IDAgPyBtaW4odG9JbnRlZ2VyKGl0KSwgMHgxZmZmZmZmZmZmZmZmZikgOiAwOyAvLyBwb3coMiwgNTMpIC0gMSA9PSA5MDA3MTk5MjU0NzQwOTkxXG59OyIsIi8vIDcuMS4xMyBUb09iamVjdChhcmd1bWVudClcbnZhciBkZWZpbmVkID0gcmVxdWlyZSgnLi9fZGVmaW5lZCcpO1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihpdCl7XG4gIHJldHVybiBPYmplY3QoZGVmaW5lZChpdCkpO1xufTsiLCIvLyA3LjEuMSBUb1ByaW1pdGl2ZShpbnB1dCBbLCBQcmVmZXJyZWRUeXBlXSlcbnZhciBpc09iamVjdCA9IHJlcXVpcmUoJy4vX2lzLW9iamVjdCcpO1xuLy8gaW5zdGVhZCBvZiB0aGUgRVM2IHNwZWMgdmVyc2lvbiwgd2UgZGlkbid0IGltcGxlbWVudCBAQHRvUHJpbWl0aXZlIGNhc2Vcbi8vIGFuZCB0aGUgc2Vjb25kIGFyZ3VtZW50IC0gZmxhZyAtIHByZWZlcnJlZCB0eXBlIGlzIGEgc3RyaW5nXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKGl0LCBTKXtcbiAgaWYoIWlzT2JqZWN0KGl0KSlyZXR1cm4gaXQ7XG4gIHZhciBmbiwgdmFsO1xuICBpZihTICYmIHR5cGVvZiAoZm4gPSBpdC50b1N0cmluZykgPT0gJ2Z1bmN0aW9uJyAmJiAhaXNPYmplY3QodmFsID0gZm4uY2FsbChpdCkpKXJldHVybiB2YWw7XG4gIGlmKHR5cGVvZiAoZm4gPSBpdC52YWx1ZU9mKSA9PSAnZnVuY3Rpb24nICYmICFpc09iamVjdCh2YWwgPSBmbi5jYWxsKGl0KSkpcmV0dXJuIHZhbDtcbiAgaWYoIVMgJiYgdHlwZW9mIChmbiA9IGl0LnRvU3RyaW5nKSA9PSAnZnVuY3Rpb24nICYmICFpc09iamVjdCh2YWwgPSBmbi5jYWxsKGl0KSkpcmV0dXJuIHZhbDtcbiAgdGhyb3cgVHlwZUVycm9yKFwiQ2FuJ3QgY29udmVydCBvYmplY3QgdG8gcHJpbWl0aXZlIHZhbHVlXCIpO1xufTsiLCJ2YXIgaWQgPSAwXG4gICwgcHggPSBNYXRoLnJhbmRvbSgpO1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihrZXkpe1xuICByZXR1cm4gJ1N5bWJvbCgnLmNvbmNhdChrZXkgPT09IHVuZGVmaW5lZCA/ICcnIDoga2V5LCAnKV8nLCAoKytpZCArIHB4KS50b1N0cmluZygzNikpO1xufTsiLCJ2YXIgZ2xvYmFsICAgICAgICAgPSByZXF1aXJlKCcuL19nbG9iYWwnKVxuICAsIGNvcmUgICAgICAgICAgID0gcmVxdWlyZSgnLi9fY29yZScpXG4gICwgTElCUkFSWSAgICAgICAgPSByZXF1aXJlKCcuL19saWJyYXJ5JylcbiAgLCB3a3NFeHQgICAgICAgICA9IHJlcXVpcmUoJy4vX3drcy1leHQnKVxuICAsIGRlZmluZVByb3BlcnR5ID0gcmVxdWlyZSgnLi9fb2JqZWN0LWRwJykuZjtcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24obmFtZSl7XG4gIHZhciAkU3ltYm9sID0gY29yZS5TeW1ib2wgfHwgKGNvcmUuU3ltYm9sID0gTElCUkFSWSA/IHt9IDogZ2xvYmFsLlN5bWJvbCB8fCB7fSk7XG4gIGlmKG5hbWUuY2hhckF0KDApICE9ICdfJyAmJiAhKG5hbWUgaW4gJFN5bWJvbCkpZGVmaW5lUHJvcGVydHkoJFN5bWJvbCwgbmFtZSwge3ZhbHVlOiB3a3NFeHQuZihuYW1lKX0pO1xufTsiLCJleHBvcnRzLmYgPSByZXF1aXJlKCcuL193a3MnKTsiLCJ2YXIgc3RvcmUgICAgICA9IHJlcXVpcmUoJy4vX3NoYXJlZCcpKCd3a3MnKVxuICAsIHVpZCAgICAgICAgPSByZXF1aXJlKCcuL191aWQnKVxuICAsIFN5bWJvbCAgICAgPSByZXF1aXJlKCcuL19nbG9iYWwnKS5TeW1ib2xcbiAgLCBVU0VfU1lNQk9MID0gdHlwZW9mIFN5bWJvbCA9PSAnZnVuY3Rpb24nO1xuXG52YXIgJGV4cG9ydHMgPSBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKG5hbWUpe1xuICByZXR1cm4gc3RvcmVbbmFtZV0gfHwgKHN0b3JlW25hbWVdID1cbiAgICBVU0VfU1lNQk9MICYmIFN5bWJvbFtuYW1lXSB8fCAoVVNFX1NZTUJPTCA/IFN5bWJvbCA6IHVpZCkoJ1N5bWJvbC4nICsgbmFtZSkpO1xufTtcblxuJGV4cG9ydHMuc3RvcmUgPSBzdG9yZTsiLCJ2YXIgY2xhc3NvZiAgID0gcmVxdWlyZSgnLi9fY2xhc3NvZicpXG4gICwgSVRFUkFUT1IgID0gcmVxdWlyZSgnLi9fd2tzJykoJ2l0ZXJhdG9yJylcbiAgLCBJdGVyYXRvcnMgPSByZXF1aXJlKCcuL19pdGVyYXRvcnMnKTtcbm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi9fY29yZScpLmdldEl0ZXJhdG9yTWV0aG9kID0gZnVuY3Rpb24oaXQpe1xuICBpZihpdCAhPSB1bmRlZmluZWQpcmV0dXJuIGl0W0lURVJBVE9SXVxuICAgIHx8IGl0WydAQGl0ZXJhdG9yJ11cbiAgICB8fCBJdGVyYXRvcnNbY2xhc3NvZihpdCldO1xufTsiLCJ2YXIgYW5PYmplY3QgPSByZXF1aXJlKCcuL19hbi1vYmplY3QnKVxuICAsIGdldCAgICAgID0gcmVxdWlyZSgnLi9jb3JlLmdldC1pdGVyYXRvci1tZXRob2QnKTtcbm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi9fY29yZScpLmdldEl0ZXJhdG9yID0gZnVuY3Rpb24oaXQpe1xuICB2YXIgaXRlckZuID0gZ2V0KGl0KTtcbiAgaWYodHlwZW9mIGl0ZXJGbiAhPSAnZnVuY3Rpb24nKXRocm93IFR5cGVFcnJvcihpdCArICcgaXMgbm90IGl0ZXJhYmxlIScpO1xuICByZXR1cm4gYW5PYmplY3QoaXRlckZuLmNhbGwoaXQpKTtcbn07IiwiJ3VzZSBzdHJpY3QnO1xudmFyIGN0eCAgICAgICAgICAgID0gcmVxdWlyZSgnLi9fY3R4JylcbiAgLCAkZXhwb3J0ICAgICAgICA9IHJlcXVpcmUoJy4vX2V4cG9ydCcpXG4gICwgdG9PYmplY3QgICAgICAgPSByZXF1aXJlKCcuL190by1vYmplY3QnKVxuICAsIGNhbGwgICAgICAgICAgID0gcmVxdWlyZSgnLi9faXRlci1jYWxsJylcbiAgLCBpc0FycmF5SXRlciAgICA9IHJlcXVpcmUoJy4vX2lzLWFycmF5LWl0ZXInKVxuICAsIHRvTGVuZ3RoICAgICAgID0gcmVxdWlyZSgnLi9fdG8tbGVuZ3RoJylcbiAgLCBjcmVhdGVQcm9wZXJ0eSA9IHJlcXVpcmUoJy4vX2NyZWF0ZS1wcm9wZXJ0eScpXG4gICwgZ2V0SXRlckZuICAgICAgPSByZXF1aXJlKCcuL2NvcmUuZ2V0LWl0ZXJhdG9yLW1ldGhvZCcpO1xuXG4kZXhwb3J0KCRleHBvcnQuUyArICRleHBvcnQuRiAqICFyZXF1aXJlKCcuL19pdGVyLWRldGVjdCcpKGZ1bmN0aW9uKGl0ZXIpeyBBcnJheS5mcm9tKGl0ZXIpOyB9KSwgJ0FycmF5Jywge1xuICAvLyAyMi4xLjIuMSBBcnJheS5mcm9tKGFycmF5TGlrZSwgbWFwZm4gPSB1bmRlZmluZWQsIHRoaXNBcmcgPSB1bmRlZmluZWQpXG4gIGZyb206IGZ1bmN0aW9uIGZyb20oYXJyYXlMaWtlLyosIG1hcGZuID0gdW5kZWZpbmVkLCB0aGlzQXJnID0gdW5kZWZpbmVkKi8pe1xuICAgIHZhciBPICAgICAgID0gdG9PYmplY3QoYXJyYXlMaWtlKVxuICAgICAgLCBDICAgICAgID0gdHlwZW9mIHRoaXMgPT0gJ2Z1bmN0aW9uJyA/IHRoaXMgOiBBcnJheVxuICAgICAgLCBhTGVuICAgID0gYXJndW1lbnRzLmxlbmd0aFxuICAgICAgLCBtYXBmbiAgID0gYUxlbiA+IDEgPyBhcmd1bWVudHNbMV0gOiB1bmRlZmluZWRcbiAgICAgICwgbWFwcGluZyA9IG1hcGZuICE9PSB1bmRlZmluZWRcbiAgICAgICwgaW5kZXggICA9IDBcbiAgICAgICwgaXRlckZuICA9IGdldEl0ZXJGbihPKVxuICAgICAgLCBsZW5ndGgsIHJlc3VsdCwgc3RlcCwgaXRlcmF0b3I7XG4gICAgaWYobWFwcGluZyltYXBmbiA9IGN0eChtYXBmbiwgYUxlbiA+IDIgPyBhcmd1bWVudHNbMl0gOiB1bmRlZmluZWQsIDIpO1xuICAgIC8vIGlmIG9iamVjdCBpc24ndCBpdGVyYWJsZSBvciBpdCdzIGFycmF5IHdpdGggZGVmYXVsdCBpdGVyYXRvciAtIHVzZSBzaW1wbGUgY2FzZVxuICAgIGlmKGl0ZXJGbiAhPSB1bmRlZmluZWQgJiYgIShDID09IEFycmF5ICYmIGlzQXJyYXlJdGVyKGl0ZXJGbikpKXtcbiAgICAgIGZvcihpdGVyYXRvciA9IGl0ZXJGbi5jYWxsKE8pLCByZXN1bHQgPSBuZXcgQzsgIShzdGVwID0gaXRlcmF0b3IubmV4dCgpKS5kb25lOyBpbmRleCsrKXtcbiAgICAgICAgY3JlYXRlUHJvcGVydHkocmVzdWx0LCBpbmRleCwgbWFwcGluZyA/IGNhbGwoaXRlcmF0b3IsIG1hcGZuLCBbc3RlcC52YWx1ZSwgaW5kZXhdLCB0cnVlKSA6IHN0ZXAudmFsdWUpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBsZW5ndGggPSB0b0xlbmd0aChPLmxlbmd0aCk7XG4gICAgICBmb3IocmVzdWx0ID0gbmV3IEMobGVuZ3RoKTsgbGVuZ3RoID4gaW5kZXg7IGluZGV4Kyspe1xuICAgICAgICBjcmVhdGVQcm9wZXJ0eShyZXN1bHQsIGluZGV4LCBtYXBwaW5nID8gbWFwZm4oT1tpbmRleF0sIGluZGV4KSA6IE9baW5kZXhdKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmVzdWx0Lmxlbmd0aCA9IGluZGV4O1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cbn0pO1xuIiwiJ3VzZSBzdHJpY3QnO1xudmFyIGFkZFRvVW5zY29wYWJsZXMgPSByZXF1aXJlKCcuL19hZGQtdG8tdW5zY29wYWJsZXMnKVxuICAsIHN0ZXAgICAgICAgICAgICAgPSByZXF1aXJlKCcuL19pdGVyLXN0ZXAnKVxuICAsIEl0ZXJhdG9ycyAgICAgICAgPSByZXF1aXJlKCcuL19pdGVyYXRvcnMnKVxuICAsIHRvSU9iamVjdCAgICAgICAgPSByZXF1aXJlKCcuL190by1pb2JqZWN0Jyk7XG5cbi8vIDIyLjEuMy40IEFycmF5LnByb3RvdHlwZS5lbnRyaWVzKClcbi8vIDIyLjEuMy4xMyBBcnJheS5wcm90b3R5cGUua2V5cygpXG4vLyAyMi4xLjMuMjkgQXJyYXkucHJvdG90eXBlLnZhbHVlcygpXG4vLyAyMi4xLjMuMzAgQXJyYXkucHJvdG90eXBlW0BAaXRlcmF0b3JdKClcbm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi9faXRlci1kZWZpbmUnKShBcnJheSwgJ0FycmF5JywgZnVuY3Rpb24oaXRlcmF0ZWQsIGtpbmQpe1xuICB0aGlzLl90ID0gdG9JT2JqZWN0KGl0ZXJhdGVkKTsgLy8gdGFyZ2V0XG4gIHRoaXMuX2kgPSAwOyAgICAgICAgICAgICAgICAgICAvLyBuZXh0IGluZGV4XG4gIHRoaXMuX2sgPSBraW5kOyAgICAgICAgICAgICAgICAvLyBraW5kXG4vLyAyMi4xLjUuMi4xICVBcnJheUl0ZXJhdG9yUHJvdG90eXBlJS5uZXh0KClcbn0sIGZ1bmN0aW9uKCl7XG4gIHZhciBPICAgICA9IHRoaXMuX3RcbiAgICAsIGtpbmQgID0gdGhpcy5fa1xuICAgICwgaW5kZXggPSB0aGlzLl9pKys7XG4gIGlmKCFPIHx8IGluZGV4ID49IE8ubGVuZ3RoKXtcbiAgICB0aGlzLl90ID0gdW5kZWZpbmVkO1xuICAgIHJldHVybiBzdGVwKDEpO1xuICB9XG4gIGlmKGtpbmQgPT0gJ2tleXMnICApcmV0dXJuIHN0ZXAoMCwgaW5kZXgpO1xuICBpZihraW5kID09ICd2YWx1ZXMnKXJldHVybiBzdGVwKDAsIE9baW5kZXhdKTtcbiAgcmV0dXJuIHN0ZXAoMCwgW2luZGV4LCBPW2luZGV4XV0pO1xufSwgJ3ZhbHVlcycpO1xuXG4vLyBhcmd1bWVudHNMaXN0W0BAaXRlcmF0b3JdIGlzICVBcnJheVByb3RvX3ZhbHVlcyUgKDkuNC40LjYsIDkuNC40LjcpXG5JdGVyYXRvcnMuQXJndW1lbnRzID0gSXRlcmF0b3JzLkFycmF5O1xuXG5hZGRUb1Vuc2NvcGFibGVzKCdrZXlzJyk7XG5hZGRUb1Vuc2NvcGFibGVzKCd2YWx1ZXMnKTtcbmFkZFRvVW5zY29wYWJsZXMoJ2VudHJpZXMnKTsiLCIndXNlIHN0cmljdCc7XG52YXIgc3Ryb25nID0gcmVxdWlyZSgnLi9fY29sbGVjdGlvbi1zdHJvbmcnKTtcblxuLy8gMjMuMSBNYXAgT2JqZWN0c1xubW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKCcuL19jb2xsZWN0aW9uJykoJ01hcCcsIGZ1bmN0aW9uKGdldCl7XG4gIHJldHVybiBmdW5jdGlvbiBNYXAoKXsgcmV0dXJuIGdldCh0aGlzLCBhcmd1bWVudHMubGVuZ3RoID4gMCA/IGFyZ3VtZW50c1swXSA6IHVuZGVmaW5lZCk7IH07XG59LCB7XG4gIC8vIDIzLjEuMy42IE1hcC5wcm90b3R5cGUuZ2V0KGtleSlcbiAgZ2V0OiBmdW5jdGlvbiBnZXQoa2V5KXtcbiAgICB2YXIgZW50cnkgPSBzdHJvbmcuZ2V0RW50cnkodGhpcywga2V5KTtcbiAgICByZXR1cm4gZW50cnkgJiYgZW50cnkudjtcbiAgfSxcbiAgLy8gMjMuMS4zLjkgTWFwLnByb3RvdHlwZS5zZXQoa2V5LCB2YWx1ZSlcbiAgc2V0OiBmdW5jdGlvbiBzZXQoa2V5LCB2YWx1ZSl7XG4gICAgcmV0dXJuIHN0cm9uZy5kZWYodGhpcywga2V5ID09PSAwID8gMCA6IGtleSwgdmFsdWUpO1xuICB9XG59LCBzdHJvbmcsIHRydWUpOyIsIi8vIDE5LjEuMy4xIE9iamVjdC5hc3NpZ24odGFyZ2V0LCBzb3VyY2UpXG52YXIgJGV4cG9ydCA9IHJlcXVpcmUoJy4vX2V4cG9ydCcpO1xuXG4kZXhwb3J0KCRleHBvcnQuUyArICRleHBvcnQuRiwgJ09iamVjdCcsIHthc3NpZ246IHJlcXVpcmUoJy4vX29iamVjdC1hc3NpZ24nKX0pOyIsInZhciAkZXhwb3J0ID0gcmVxdWlyZSgnLi9fZXhwb3J0Jylcbi8vIDE5LjEuMi4yIC8gMTUuMi4zLjUgT2JqZWN0LmNyZWF0ZShPIFssIFByb3BlcnRpZXNdKVxuJGV4cG9ydCgkZXhwb3J0LlMsICdPYmplY3QnLCB7Y3JlYXRlOiByZXF1aXJlKCcuL19vYmplY3QtY3JlYXRlJyl9KTsiLCJ2YXIgJGV4cG9ydCA9IHJlcXVpcmUoJy4vX2V4cG9ydCcpO1xuLy8gMTkuMS4yLjQgLyAxNS4yLjMuNiBPYmplY3QuZGVmaW5lUHJvcGVydHkoTywgUCwgQXR0cmlidXRlcylcbiRleHBvcnQoJGV4cG9ydC5TICsgJGV4cG9ydC5GICogIXJlcXVpcmUoJy4vX2Rlc2NyaXB0b3JzJyksICdPYmplY3QnLCB7ZGVmaW5lUHJvcGVydHk6IHJlcXVpcmUoJy4vX29iamVjdC1kcCcpLmZ9KTsiLCIvLyAxOS4xLjIuOSBPYmplY3QuZ2V0UHJvdG90eXBlT2YoTylcbnZhciB0b09iamVjdCAgICAgICAgPSByZXF1aXJlKCcuL190by1vYmplY3QnKVxuICAsICRnZXRQcm90b3R5cGVPZiA9IHJlcXVpcmUoJy4vX29iamVjdC1ncG8nKTtcblxucmVxdWlyZSgnLi9fb2JqZWN0LXNhcCcpKCdnZXRQcm90b3R5cGVPZicsIGZ1bmN0aW9uKCl7XG4gIHJldHVybiBmdW5jdGlvbiBnZXRQcm90b3R5cGVPZihpdCl7XG4gICAgcmV0dXJuICRnZXRQcm90b3R5cGVPZih0b09iamVjdChpdCkpO1xuICB9O1xufSk7IiwiLy8gMTkuMS4yLjE0IE9iamVjdC5rZXlzKE8pXG52YXIgdG9PYmplY3QgPSByZXF1aXJlKCcuL190by1vYmplY3QnKVxuICAsICRrZXlzICAgID0gcmVxdWlyZSgnLi9fb2JqZWN0LWtleXMnKTtcblxucmVxdWlyZSgnLi9fb2JqZWN0LXNhcCcpKCdrZXlzJywgZnVuY3Rpb24oKXtcbiAgcmV0dXJuIGZ1bmN0aW9uIGtleXMoaXQpe1xuICAgIHJldHVybiAka2V5cyh0b09iamVjdChpdCkpO1xuICB9O1xufSk7IiwiLy8gMTkuMS4zLjE5IE9iamVjdC5zZXRQcm90b3R5cGVPZihPLCBwcm90bylcbnZhciAkZXhwb3J0ID0gcmVxdWlyZSgnLi9fZXhwb3J0Jyk7XG4kZXhwb3J0KCRleHBvcnQuUywgJ09iamVjdCcsIHtzZXRQcm90b3R5cGVPZjogcmVxdWlyZSgnLi9fc2V0LXByb3RvJykuc2V0fSk7IiwiIiwiJ3VzZSBzdHJpY3QnO1xudmFyIExJQlJBUlkgICAgICAgICAgICA9IHJlcXVpcmUoJy4vX2xpYnJhcnknKVxuICAsIGdsb2JhbCAgICAgICAgICAgICA9IHJlcXVpcmUoJy4vX2dsb2JhbCcpXG4gICwgY3R4ICAgICAgICAgICAgICAgID0gcmVxdWlyZSgnLi9fY3R4JylcbiAgLCBjbGFzc29mICAgICAgICAgICAgPSByZXF1aXJlKCcuL19jbGFzc29mJylcbiAgLCAkZXhwb3J0ICAgICAgICAgICAgPSByZXF1aXJlKCcuL19leHBvcnQnKVxuICAsIGlzT2JqZWN0ICAgICAgICAgICA9IHJlcXVpcmUoJy4vX2lzLW9iamVjdCcpXG4gICwgYUZ1bmN0aW9uICAgICAgICAgID0gcmVxdWlyZSgnLi9fYS1mdW5jdGlvbicpXG4gICwgYW5JbnN0YW5jZSAgICAgICAgID0gcmVxdWlyZSgnLi9fYW4taW5zdGFuY2UnKVxuICAsIGZvck9mICAgICAgICAgICAgICA9IHJlcXVpcmUoJy4vX2Zvci1vZicpXG4gICwgc3BlY2llc0NvbnN0cnVjdG9yID0gcmVxdWlyZSgnLi9fc3BlY2llcy1jb25zdHJ1Y3RvcicpXG4gICwgdGFzayAgICAgICAgICAgICAgID0gcmVxdWlyZSgnLi9fdGFzaycpLnNldFxuICAsIG1pY3JvdGFzayAgICAgICAgICA9IHJlcXVpcmUoJy4vX21pY3JvdGFzaycpKClcbiAgLCBQUk9NSVNFICAgICAgICAgICAgPSAnUHJvbWlzZSdcbiAgLCBUeXBlRXJyb3IgICAgICAgICAgPSBnbG9iYWwuVHlwZUVycm9yXG4gICwgcHJvY2VzcyAgICAgICAgICAgID0gZ2xvYmFsLnByb2Nlc3NcbiAgLCAkUHJvbWlzZSAgICAgICAgICAgPSBnbG9iYWxbUFJPTUlTRV1cbiAgLCBwcm9jZXNzICAgICAgICAgICAgPSBnbG9iYWwucHJvY2Vzc1xuICAsIGlzTm9kZSAgICAgICAgICAgICA9IGNsYXNzb2YocHJvY2VzcykgPT0gJ3Byb2Nlc3MnXG4gICwgZW1wdHkgICAgICAgICAgICAgID0gZnVuY3Rpb24oKXsgLyogZW1wdHkgKi8gfVxuICAsIEludGVybmFsLCBHZW5lcmljUHJvbWlzZUNhcGFiaWxpdHksIFdyYXBwZXI7XG5cbnZhciBVU0VfTkFUSVZFID0gISFmdW5jdGlvbigpe1xuICB0cnkge1xuICAgIC8vIGNvcnJlY3Qgc3ViY2xhc3Npbmcgd2l0aCBAQHNwZWNpZXMgc3VwcG9ydFxuICAgIHZhciBwcm9taXNlICAgICA9ICRQcm9taXNlLnJlc29sdmUoMSlcbiAgICAgICwgRmFrZVByb21pc2UgPSAocHJvbWlzZS5jb25zdHJ1Y3RvciA9IHt9KVtyZXF1aXJlKCcuL193a3MnKSgnc3BlY2llcycpXSA9IGZ1bmN0aW9uKGV4ZWMpeyBleGVjKGVtcHR5LCBlbXB0eSk7IH07XG4gICAgLy8gdW5oYW5kbGVkIHJlamVjdGlvbnMgdHJhY2tpbmcgc3VwcG9ydCwgTm9kZUpTIFByb21pc2Ugd2l0aG91dCBpdCBmYWlscyBAQHNwZWNpZXMgdGVzdFxuICAgIHJldHVybiAoaXNOb2RlIHx8IHR5cGVvZiBQcm9taXNlUmVqZWN0aW9uRXZlbnQgPT0gJ2Z1bmN0aW9uJykgJiYgcHJvbWlzZS50aGVuKGVtcHR5KSBpbnN0YW5jZW9mIEZha2VQcm9taXNlO1xuICB9IGNhdGNoKGUpeyAvKiBlbXB0eSAqLyB9XG59KCk7XG5cbi8vIGhlbHBlcnNcbnZhciBzYW1lQ29uc3RydWN0b3IgPSBmdW5jdGlvbihhLCBiKXtcbiAgLy8gd2l0aCBsaWJyYXJ5IHdyYXBwZXIgc3BlY2lhbCBjYXNlXG4gIHJldHVybiBhID09PSBiIHx8IGEgPT09ICRQcm9taXNlICYmIGIgPT09IFdyYXBwZXI7XG59O1xudmFyIGlzVGhlbmFibGUgPSBmdW5jdGlvbihpdCl7XG4gIHZhciB0aGVuO1xuICByZXR1cm4gaXNPYmplY3QoaXQpICYmIHR5cGVvZiAodGhlbiA9IGl0LnRoZW4pID09ICdmdW5jdGlvbicgPyB0aGVuIDogZmFsc2U7XG59O1xudmFyIG5ld1Byb21pc2VDYXBhYmlsaXR5ID0gZnVuY3Rpb24oQyl7XG4gIHJldHVybiBzYW1lQ29uc3RydWN0b3IoJFByb21pc2UsIEMpXG4gICAgPyBuZXcgUHJvbWlzZUNhcGFiaWxpdHkoQylcbiAgICA6IG5ldyBHZW5lcmljUHJvbWlzZUNhcGFiaWxpdHkoQyk7XG59O1xudmFyIFByb21pc2VDYXBhYmlsaXR5ID0gR2VuZXJpY1Byb21pc2VDYXBhYmlsaXR5ID0gZnVuY3Rpb24oQyl7XG4gIHZhciByZXNvbHZlLCByZWplY3Q7XG4gIHRoaXMucHJvbWlzZSA9IG5ldyBDKGZ1bmN0aW9uKCQkcmVzb2x2ZSwgJCRyZWplY3Qpe1xuICAgIGlmKHJlc29sdmUgIT09IHVuZGVmaW5lZCB8fCByZWplY3QgIT09IHVuZGVmaW5lZCl0aHJvdyBUeXBlRXJyb3IoJ0JhZCBQcm9taXNlIGNvbnN0cnVjdG9yJyk7XG4gICAgcmVzb2x2ZSA9ICQkcmVzb2x2ZTtcbiAgICByZWplY3QgID0gJCRyZWplY3Q7XG4gIH0pO1xuICB0aGlzLnJlc29sdmUgPSBhRnVuY3Rpb24ocmVzb2x2ZSk7XG4gIHRoaXMucmVqZWN0ICA9IGFGdW5jdGlvbihyZWplY3QpO1xufTtcbnZhciBwZXJmb3JtID0gZnVuY3Rpb24oZXhlYyl7XG4gIHRyeSB7XG4gICAgZXhlYygpO1xuICB9IGNhdGNoKGUpe1xuICAgIHJldHVybiB7ZXJyb3I6IGV9O1xuICB9XG59O1xudmFyIG5vdGlmeSA9IGZ1bmN0aW9uKHByb21pc2UsIGlzUmVqZWN0KXtcbiAgaWYocHJvbWlzZS5fbilyZXR1cm47XG4gIHByb21pc2UuX24gPSB0cnVlO1xuICB2YXIgY2hhaW4gPSBwcm9taXNlLl9jO1xuICBtaWNyb3Rhc2soZnVuY3Rpb24oKXtcbiAgICB2YXIgdmFsdWUgPSBwcm9taXNlLl92XG4gICAgICAsIG9rICAgID0gcHJvbWlzZS5fcyA9PSAxXG4gICAgICAsIGkgICAgID0gMDtcbiAgICB2YXIgcnVuID0gZnVuY3Rpb24ocmVhY3Rpb24pe1xuICAgICAgdmFyIGhhbmRsZXIgPSBvayA/IHJlYWN0aW9uLm9rIDogcmVhY3Rpb24uZmFpbFxuICAgICAgICAsIHJlc29sdmUgPSByZWFjdGlvbi5yZXNvbHZlXG4gICAgICAgICwgcmVqZWN0ICA9IHJlYWN0aW9uLnJlamVjdFxuICAgICAgICAsIGRvbWFpbiAgPSByZWFjdGlvbi5kb21haW5cbiAgICAgICAgLCByZXN1bHQsIHRoZW47XG4gICAgICB0cnkge1xuICAgICAgICBpZihoYW5kbGVyKXtcbiAgICAgICAgICBpZighb2spe1xuICAgICAgICAgICAgaWYocHJvbWlzZS5faCA9PSAyKW9uSGFuZGxlVW5oYW5kbGVkKHByb21pc2UpO1xuICAgICAgICAgICAgcHJvbWlzZS5faCA9IDE7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmKGhhbmRsZXIgPT09IHRydWUpcmVzdWx0ID0gdmFsdWU7XG4gICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBpZihkb21haW4pZG9tYWluLmVudGVyKCk7XG4gICAgICAgICAgICByZXN1bHQgPSBoYW5kbGVyKHZhbHVlKTtcbiAgICAgICAgICAgIGlmKGRvbWFpbilkb21haW4uZXhpdCgpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZihyZXN1bHQgPT09IHJlYWN0aW9uLnByb21pc2Upe1xuICAgICAgICAgICAgcmVqZWN0KFR5cGVFcnJvcignUHJvbWlzZS1jaGFpbiBjeWNsZScpKTtcbiAgICAgICAgICB9IGVsc2UgaWYodGhlbiA9IGlzVGhlbmFibGUocmVzdWx0KSl7XG4gICAgICAgICAgICB0aGVuLmNhbGwocmVzdWx0LCByZXNvbHZlLCByZWplY3QpO1xuICAgICAgICAgIH0gZWxzZSByZXNvbHZlKHJlc3VsdCk7XG4gICAgICAgIH0gZWxzZSByZWplY3QodmFsdWUpO1xuICAgICAgfSBjYXRjaChlKXtcbiAgICAgICAgcmVqZWN0KGUpO1xuICAgICAgfVxuICAgIH07XG4gICAgd2hpbGUoY2hhaW4ubGVuZ3RoID4gaSlydW4oY2hhaW5baSsrXSk7IC8vIHZhcmlhYmxlIGxlbmd0aCAtIGNhbid0IHVzZSBmb3JFYWNoXG4gICAgcHJvbWlzZS5fYyA9IFtdO1xuICAgIHByb21pc2UuX24gPSBmYWxzZTtcbiAgICBpZihpc1JlamVjdCAmJiAhcHJvbWlzZS5faClvblVuaGFuZGxlZChwcm9taXNlKTtcbiAgfSk7XG59O1xudmFyIG9uVW5oYW5kbGVkID0gZnVuY3Rpb24ocHJvbWlzZSl7XG4gIHRhc2suY2FsbChnbG9iYWwsIGZ1bmN0aW9uKCl7XG4gICAgdmFyIHZhbHVlID0gcHJvbWlzZS5fdlxuICAgICAgLCBhYnJ1cHQsIGhhbmRsZXIsIGNvbnNvbGU7XG4gICAgaWYoaXNVbmhhbmRsZWQocHJvbWlzZSkpe1xuICAgICAgYWJydXB0ID0gcGVyZm9ybShmdW5jdGlvbigpe1xuICAgICAgICBpZihpc05vZGUpe1xuICAgICAgICAgIHByb2Nlc3MuZW1pdCgndW5oYW5kbGVkUmVqZWN0aW9uJywgdmFsdWUsIHByb21pc2UpO1xuICAgICAgICB9IGVsc2UgaWYoaGFuZGxlciA9IGdsb2JhbC5vbnVuaGFuZGxlZHJlamVjdGlvbil7XG4gICAgICAgICAgaGFuZGxlcih7cHJvbWlzZTogcHJvbWlzZSwgcmVhc29uOiB2YWx1ZX0pO1xuICAgICAgICB9IGVsc2UgaWYoKGNvbnNvbGUgPSBnbG9iYWwuY29uc29sZSkgJiYgY29uc29sZS5lcnJvcil7XG4gICAgICAgICAgY29uc29sZS5lcnJvcignVW5oYW5kbGVkIHByb21pc2UgcmVqZWN0aW9uJywgdmFsdWUpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIC8vIEJyb3dzZXJzIHNob3VsZCBub3QgdHJpZ2dlciBgcmVqZWN0aW9uSGFuZGxlZGAgZXZlbnQgaWYgaXQgd2FzIGhhbmRsZWQgaGVyZSwgTm9kZUpTIC0gc2hvdWxkXG4gICAgICBwcm9taXNlLl9oID0gaXNOb2RlIHx8IGlzVW5oYW5kbGVkKHByb21pc2UpID8gMiA6IDE7XG4gICAgfSBwcm9taXNlLl9hID0gdW5kZWZpbmVkO1xuICAgIGlmKGFicnVwdCl0aHJvdyBhYnJ1cHQuZXJyb3I7XG4gIH0pO1xufTtcbnZhciBpc1VuaGFuZGxlZCA9IGZ1bmN0aW9uKHByb21pc2Upe1xuICBpZihwcm9taXNlLl9oID09IDEpcmV0dXJuIGZhbHNlO1xuICB2YXIgY2hhaW4gPSBwcm9taXNlLl9hIHx8IHByb21pc2UuX2NcbiAgICAsIGkgICAgID0gMFxuICAgICwgcmVhY3Rpb247XG4gIHdoaWxlKGNoYWluLmxlbmd0aCA+IGkpe1xuICAgIHJlYWN0aW9uID0gY2hhaW5baSsrXTtcbiAgICBpZihyZWFjdGlvbi5mYWlsIHx8ICFpc1VuaGFuZGxlZChyZWFjdGlvbi5wcm9taXNlKSlyZXR1cm4gZmFsc2U7XG4gIH0gcmV0dXJuIHRydWU7XG59O1xudmFyIG9uSGFuZGxlVW5oYW5kbGVkID0gZnVuY3Rpb24ocHJvbWlzZSl7XG4gIHRhc2suY2FsbChnbG9iYWwsIGZ1bmN0aW9uKCl7XG4gICAgdmFyIGhhbmRsZXI7XG4gICAgaWYoaXNOb2RlKXtcbiAgICAgIHByb2Nlc3MuZW1pdCgncmVqZWN0aW9uSGFuZGxlZCcsIHByb21pc2UpO1xuICAgIH0gZWxzZSBpZihoYW5kbGVyID0gZ2xvYmFsLm9ucmVqZWN0aW9uaGFuZGxlZCl7XG4gICAgICBoYW5kbGVyKHtwcm9taXNlOiBwcm9taXNlLCByZWFzb246IHByb21pc2UuX3Z9KTtcbiAgICB9XG4gIH0pO1xufTtcbnZhciAkcmVqZWN0ID0gZnVuY3Rpb24odmFsdWUpe1xuICB2YXIgcHJvbWlzZSA9IHRoaXM7XG4gIGlmKHByb21pc2UuX2QpcmV0dXJuO1xuICBwcm9taXNlLl9kID0gdHJ1ZTtcbiAgcHJvbWlzZSA9IHByb21pc2UuX3cgfHwgcHJvbWlzZTsgLy8gdW53cmFwXG4gIHByb21pc2UuX3YgPSB2YWx1ZTtcbiAgcHJvbWlzZS5fcyA9IDI7XG4gIGlmKCFwcm9taXNlLl9hKXByb21pc2UuX2EgPSBwcm9taXNlLl9jLnNsaWNlKCk7XG4gIG5vdGlmeShwcm9taXNlLCB0cnVlKTtcbn07XG52YXIgJHJlc29sdmUgPSBmdW5jdGlvbih2YWx1ZSl7XG4gIHZhciBwcm9taXNlID0gdGhpc1xuICAgICwgdGhlbjtcbiAgaWYocHJvbWlzZS5fZClyZXR1cm47XG4gIHByb21pc2UuX2QgPSB0cnVlO1xuICBwcm9taXNlID0gcHJvbWlzZS5fdyB8fCBwcm9taXNlOyAvLyB1bndyYXBcbiAgdHJ5IHtcbiAgICBpZihwcm9taXNlID09PSB2YWx1ZSl0aHJvdyBUeXBlRXJyb3IoXCJQcm9taXNlIGNhbid0IGJlIHJlc29sdmVkIGl0c2VsZlwiKTtcbiAgICBpZih0aGVuID0gaXNUaGVuYWJsZSh2YWx1ZSkpe1xuICAgICAgbWljcm90YXNrKGZ1bmN0aW9uKCl7XG4gICAgICAgIHZhciB3cmFwcGVyID0ge193OiBwcm9taXNlLCBfZDogZmFsc2V9OyAvLyB3cmFwXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgdGhlbi5jYWxsKHZhbHVlLCBjdHgoJHJlc29sdmUsIHdyYXBwZXIsIDEpLCBjdHgoJHJlamVjdCwgd3JhcHBlciwgMSkpO1xuICAgICAgICB9IGNhdGNoKGUpe1xuICAgICAgICAgICRyZWplY3QuY2FsbCh3cmFwcGVyLCBlKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHByb21pc2UuX3YgPSB2YWx1ZTtcbiAgICAgIHByb21pc2UuX3MgPSAxO1xuICAgICAgbm90aWZ5KHByb21pc2UsIGZhbHNlKTtcbiAgICB9XG4gIH0gY2F0Y2goZSl7XG4gICAgJHJlamVjdC5jYWxsKHtfdzogcHJvbWlzZSwgX2Q6IGZhbHNlfSwgZSk7IC8vIHdyYXBcbiAgfVxufTtcblxuLy8gY29uc3RydWN0b3IgcG9seWZpbGxcbmlmKCFVU0VfTkFUSVZFKXtcbiAgLy8gMjUuNC4zLjEgUHJvbWlzZShleGVjdXRvcilcbiAgJFByb21pc2UgPSBmdW5jdGlvbiBQcm9taXNlKGV4ZWN1dG9yKXtcbiAgICBhbkluc3RhbmNlKHRoaXMsICRQcm9taXNlLCBQUk9NSVNFLCAnX2gnKTtcbiAgICBhRnVuY3Rpb24oZXhlY3V0b3IpO1xuICAgIEludGVybmFsLmNhbGwodGhpcyk7XG4gICAgdHJ5IHtcbiAgICAgIGV4ZWN1dG9yKGN0eCgkcmVzb2x2ZSwgdGhpcywgMSksIGN0eCgkcmVqZWN0LCB0aGlzLCAxKSk7XG4gICAgfSBjYXRjaChlcnIpe1xuICAgICAgJHJlamVjdC5jYWxsKHRoaXMsIGVycik7XG4gICAgfVxuICB9O1xuICBJbnRlcm5hbCA9IGZ1bmN0aW9uIFByb21pc2UoZXhlY3V0b3Ipe1xuICAgIHRoaXMuX2MgPSBbXTsgICAgICAgICAgICAgLy8gPC0gYXdhaXRpbmcgcmVhY3Rpb25zXG4gICAgdGhpcy5fYSA9IHVuZGVmaW5lZDsgICAgICAvLyA8LSBjaGVja2VkIGluIGlzVW5oYW5kbGVkIHJlYWN0aW9uc1xuICAgIHRoaXMuX3MgPSAwOyAgICAgICAgICAgICAgLy8gPC0gc3RhdGVcbiAgICB0aGlzLl9kID0gZmFsc2U7ICAgICAgICAgIC8vIDwtIGRvbmVcbiAgICB0aGlzLl92ID0gdW5kZWZpbmVkOyAgICAgIC8vIDwtIHZhbHVlXG4gICAgdGhpcy5faCA9IDA7ICAgICAgICAgICAgICAvLyA8LSByZWplY3Rpb24gc3RhdGUsIDAgLSBkZWZhdWx0LCAxIC0gaGFuZGxlZCwgMiAtIHVuaGFuZGxlZFxuICAgIHRoaXMuX24gPSBmYWxzZTsgICAgICAgICAgLy8gPC0gbm90aWZ5XG4gIH07XG4gIEludGVybmFsLnByb3RvdHlwZSA9IHJlcXVpcmUoJy4vX3JlZGVmaW5lLWFsbCcpKCRQcm9taXNlLnByb3RvdHlwZSwge1xuICAgIC8vIDI1LjQuNS4zIFByb21pc2UucHJvdG90eXBlLnRoZW4ob25GdWxmaWxsZWQsIG9uUmVqZWN0ZWQpXG4gICAgdGhlbjogZnVuY3Rpb24gdGhlbihvbkZ1bGZpbGxlZCwgb25SZWplY3RlZCl7XG4gICAgICB2YXIgcmVhY3Rpb24gICAgPSBuZXdQcm9taXNlQ2FwYWJpbGl0eShzcGVjaWVzQ29uc3RydWN0b3IodGhpcywgJFByb21pc2UpKTtcbiAgICAgIHJlYWN0aW9uLm9rICAgICA9IHR5cGVvZiBvbkZ1bGZpbGxlZCA9PSAnZnVuY3Rpb24nID8gb25GdWxmaWxsZWQgOiB0cnVlO1xuICAgICAgcmVhY3Rpb24uZmFpbCAgID0gdHlwZW9mIG9uUmVqZWN0ZWQgPT0gJ2Z1bmN0aW9uJyAmJiBvblJlamVjdGVkO1xuICAgICAgcmVhY3Rpb24uZG9tYWluID0gaXNOb2RlID8gcHJvY2Vzcy5kb21haW4gOiB1bmRlZmluZWQ7XG4gICAgICB0aGlzLl9jLnB1c2gocmVhY3Rpb24pO1xuICAgICAgaWYodGhpcy5fYSl0aGlzLl9hLnB1c2gocmVhY3Rpb24pO1xuICAgICAgaWYodGhpcy5fcylub3RpZnkodGhpcywgZmFsc2UpO1xuICAgICAgcmV0dXJuIHJlYWN0aW9uLnByb21pc2U7XG4gICAgfSxcbiAgICAvLyAyNS40LjUuMSBQcm9taXNlLnByb3RvdHlwZS5jYXRjaChvblJlamVjdGVkKVxuICAgICdjYXRjaCc6IGZ1bmN0aW9uKG9uUmVqZWN0ZWQpe1xuICAgICAgcmV0dXJuIHRoaXMudGhlbih1bmRlZmluZWQsIG9uUmVqZWN0ZWQpO1xuICAgIH1cbiAgfSk7XG4gIFByb21pc2VDYXBhYmlsaXR5ID0gZnVuY3Rpb24oKXtcbiAgICB2YXIgcHJvbWlzZSAgPSBuZXcgSW50ZXJuYWw7XG4gICAgdGhpcy5wcm9taXNlID0gcHJvbWlzZTtcbiAgICB0aGlzLnJlc29sdmUgPSBjdHgoJHJlc29sdmUsIHByb21pc2UsIDEpO1xuICAgIHRoaXMucmVqZWN0ICA9IGN0eCgkcmVqZWN0LCBwcm9taXNlLCAxKTtcbiAgfTtcbn1cblxuJGV4cG9ydCgkZXhwb3J0LkcgKyAkZXhwb3J0LlcgKyAkZXhwb3J0LkYgKiAhVVNFX05BVElWRSwge1Byb21pc2U6ICRQcm9taXNlfSk7XG5yZXF1aXJlKCcuL19zZXQtdG8tc3RyaW5nLXRhZycpKCRQcm9taXNlLCBQUk9NSVNFKTtcbnJlcXVpcmUoJy4vX3NldC1zcGVjaWVzJykoUFJPTUlTRSk7XG5XcmFwcGVyID0gcmVxdWlyZSgnLi9fY29yZScpW1BST01JU0VdO1xuXG4vLyBzdGF0aWNzXG4kZXhwb3J0KCRleHBvcnQuUyArICRleHBvcnQuRiAqICFVU0VfTkFUSVZFLCBQUk9NSVNFLCB7XG4gIC8vIDI1LjQuNC41IFByb21pc2UucmVqZWN0KHIpXG4gIHJlamVjdDogZnVuY3Rpb24gcmVqZWN0KHIpe1xuICAgIHZhciBjYXBhYmlsaXR5ID0gbmV3UHJvbWlzZUNhcGFiaWxpdHkodGhpcylcbiAgICAgICwgJCRyZWplY3QgICA9IGNhcGFiaWxpdHkucmVqZWN0O1xuICAgICQkcmVqZWN0KHIpO1xuICAgIHJldHVybiBjYXBhYmlsaXR5LnByb21pc2U7XG4gIH1cbn0pO1xuJGV4cG9ydCgkZXhwb3J0LlMgKyAkZXhwb3J0LkYgKiAoTElCUkFSWSB8fCAhVVNFX05BVElWRSksIFBST01JU0UsIHtcbiAgLy8gMjUuNC40LjYgUHJvbWlzZS5yZXNvbHZlKHgpXG4gIHJlc29sdmU6IGZ1bmN0aW9uIHJlc29sdmUoeCl7XG4gICAgLy8gaW5zdGFuY2VvZiBpbnN0ZWFkIG9mIGludGVybmFsIHNsb3QgY2hlY2sgYmVjYXVzZSB3ZSBzaG91bGQgZml4IGl0IHdpdGhvdXQgcmVwbGFjZW1lbnQgbmF0aXZlIFByb21pc2UgY29yZVxuICAgIGlmKHggaW5zdGFuY2VvZiAkUHJvbWlzZSAmJiBzYW1lQ29uc3RydWN0b3IoeC5jb25zdHJ1Y3RvciwgdGhpcykpcmV0dXJuIHg7XG4gICAgdmFyIGNhcGFiaWxpdHkgPSBuZXdQcm9taXNlQ2FwYWJpbGl0eSh0aGlzKVxuICAgICAgLCAkJHJlc29sdmUgID0gY2FwYWJpbGl0eS5yZXNvbHZlO1xuICAgICQkcmVzb2x2ZSh4KTtcbiAgICByZXR1cm4gY2FwYWJpbGl0eS5wcm9taXNlO1xuICB9XG59KTtcbiRleHBvcnQoJGV4cG9ydC5TICsgJGV4cG9ydC5GICogIShVU0VfTkFUSVZFICYmIHJlcXVpcmUoJy4vX2l0ZXItZGV0ZWN0JykoZnVuY3Rpb24oaXRlcil7XG4gICRQcm9taXNlLmFsbChpdGVyKVsnY2F0Y2gnXShlbXB0eSk7XG59KSksIFBST01JU0UsIHtcbiAgLy8gMjUuNC40LjEgUHJvbWlzZS5hbGwoaXRlcmFibGUpXG4gIGFsbDogZnVuY3Rpb24gYWxsKGl0ZXJhYmxlKXtcbiAgICB2YXIgQyAgICAgICAgICA9IHRoaXNcbiAgICAgICwgY2FwYWJpbGl0eSA9IG5ld1Byb21pc2VDYXBhYmlsaXR5KEMpXG4gICAgICAsIHJlc29sdmUgICAgPSBjYXBhYmlsaXR5LnJlc29sdmVcbiAgICAgICwgcmVqZWN0ICAgICA9IGNhcGFiaWxpdHkucmVqZWN0O1xuICAgIHZhciBhYnJ1cHQgPSBwZXJmb3JtKGZ1bmN0aW9uKCl7XG4gICAgICB2YXIgdmFsdWVzICAgID0gW11cbiAgICAgICAgLCBpbmRleCAgICAgPSAwXG4gICAgICAgICwgcmVtYWluaW5nID0gMTtcbiAgICAgIGZvck9mKGl0ZXJhYmxlLCBmYWxzZSwgZnVuY3Rpb24ocHJvbWlzZSl7XG4gICAgICAgIHZhciAkaW5kZXggICAgICAgID0gaW5kZXgrK1xuICAgICAgICAgICwgYWxyZWFkeUNhbGxlZCA9IGZhbHNlO1xuICAgICAgICB2YWx1ZXMucHVzaCh1bmRlZmluZWQpO1xuICAgICAgICByZW1haW5pbmcrKztcbiAgICAgICAgQy5yZXNvbHZlKHByb21pc2UpLnRoZW4oZnVuY3Rpb24odmFsdWUpe1xuICAgICAgICAgIGlmKGFscmVhZHlDYWxsZWQpcmV0dXJuO1xuICAgICAgICAgIGFscmVhZHlDYWxsZWQgID0gdHJ1ZTtcbiAgICAgICAgICB2YWx1ZXNbJGluZGV4XSA9IHZhbHVlO1xuICAgICAgICAgIC0tcmVtYWluaW5nIHx8IHJlc29sdmUodmFsdWVzKTtcbiAgICAgICAgfSwgcmVqZWN0KTtcbiAgICAgIH0pO1xuICAgICAgLS1yZW1haW5pbmcgfHwgcmVzb2x2ZSh2YWx1ZXMpO1xuICAgIH0pO1xuICAgIGlmKGFicnVwdClyZWplY3QoYWJydXB0LmVycm9yKTtcbiAgICByZXR1cm4gY2FwYWJpbGl0eS5wcm9taXNlO1xuICB9LFxuICAvLyAyNS40LjQuNCBQcm9taXNlLnJhY2UoaXRlcmFibGUpXG4gIHJhY2U6IGZ1bmN0aW9uIHJhY2UoaXRlcmFibGUpe1xuICAgIHZhciBDICAgICAgICAgID0gdGhpc1xuICAgICAgLCBjYXBhYmlsaXR5ID0gbmV3UHJvbWlzZUNhcGFiaWxpdHkoQylcbiAgICAgICwgcmVqZWN0ICAgICA9IGNhcGFiaWxpdHkucmVqZWN0O1xuICAgIHZhciBhYnJ1cHQgPSBwZXJmb3JtKGZ1bmN0aW9uKCl7XG4gICAgICBmb3JPZihpdGVyYWJsZSwgZmFsc2UsIGZ1bmN0aW9uKHByb21pc2Upe1xuICAgICAgICBDLnJlc29sdmUocHJvbWlzZSkudGhlbihjYXBhYmlsaXR5LnJlc29sdmUsIHJlamVjdCk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgICBpZihhYnJ1cHQpcmVqZWN0KGFicnVwdC5lcnJvcik7XG4gICAgcmV0dXJuIGNhcGFiaWxpdHkucHJvbWlzZTtcbiAgfVxufSk7IiwiJ3VzZSBzdHJpY3QnO1xudmFyIHN0cm9uZyA9IHJlcXVpcmUoJy4vX2NvbGxlY3Rpb24tc3Ryb25nJyk7XG5cbi8vIDIzLjIgU2V0IE9iamVjdHNcbm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi9fY29sbGVjdGlvbicpKCdTZXQnLCBmdW5jdGlvbihnZXQpe1xuICByZXR1cm4gZnVuY3Rpb24gU2V0KCl7IHJldHVybiBnZXQodGhpcywgYXJndW1lbnRzLmxlbmd0aCA+IDAgPyBhcmd1bWVudHNbMF0gOiB1bmRlZmluZWQpOyB9O1xufSwge1xuICAvLyAyMy4yLjMuMSBTZXQucHJvdG90eXBlLmFkZCh2YWx1ZSlcbiAgYWRkOiBmdW5jdGlvbiBhZGQodmFsdWUpe1xuICAgIHJldHVybiBzdHJvbmcuZGVmKHRoaXMsIHZhbHVlID0gdmFsdWUgPT09IDAgPyAwIDogdmFsdWUsIHZhbHVlKTtcbiAgfVxufSwgc3Ryb25nKTsiLCIndXNlIHN0cmljdCc7XG52YXIgJGF0ICA9IHJlcXVpcmUoJy4vX3N0cmluZy1hdCcpKHRydWUpO1xuXG4vLyAyMS4xLjMuMjcgU3RyaW5nLnByb3RvdHlwZVtAQGl0ZXJhdG9yXSgpXG5yZXF1aXJlKCcuL19pdGVyLWRlZmluZScpKFN0cmluZywgJ1N0cmluZycsIGZ1bmN0aW9uKGl0ZXJhdGVkKXtcbiAgdGhpcy5fdCA9IFN0cmluZyhpdGVyYXRlZCk7IC8vIHRhcmdldFxuICB0aGlzLl9pID0gMDsgICAgICAgICAgICAgICAgLy8gbmV4dCBpbmRleFxuLy8gMjEuMS41LjIuMSAlU3RyaW5nSXRlcmF0b3JQcm90b3R5cGUlLm5leHQoKVxufSwgZnVuY3Rpb24oKXtcbiAgdmFyIE8gICAgID0gdGhpcy5fdFxuICAgICwgaW5kZXggPSB0aGlzLl9pXG4gICAgLCBwb2ludDtcbiAgaWYoaW5kZXggPj0gTy5sZW5ndGgpcmV0dXJuIHt2YWx1ZTogdW5kZWZpbmVkLCBkb25lOiB0cnVlfTtcbiAgcG9pbnQgPSAkYXQoTywgaW5kZXgpO1xuICB0aGlzLl9pICs9IHBvaW50Lmxlbmd0aDtcbiAgcmV0dXJuIHt2YWx1ZTogcG9pbnQsIGRvbmU6IGZhbHNlfTtcbn0pOyIsIid1c2Ugc3RyaWN0Jztcbi8vIEVDTUFTY3JpcHQgNiBzeW1ib2xzIHNoaW1cbnZhciBnbG9iYWwgICAgICAgICA9IHJlcXVpcmUoJy4vX2dsb2JhbCcpXG4gICwgaGFzICAgICAgICAgICAgPSByZXF1aXJlKCcuL19oYXMnKVxuICAsIERFU0NSSVBUT1JTICAgID0gcmVxdWlyZSgnLi9fZGVzY3JpcHRvcnMnKVxuICAsICRleHBvcnQgICAgICAgID0gcmVxdWlyZSgnLi9fZXhwb3J0JylcbiAgLCByZWRlZmluZSAgICAgICA9IHJlcXVpcmUoJy4vX3JlZGVmaW5lJylcbiAgLCBNRVRBICAgICAgICAgICA9IHJlcXVpcmUoJy4vX21ldGEnKS5LRVlcbiAgLCAkZmFpbHMgICAgICAgICA9IHJlcXVpcmUoJy4vX2ZhaWxzJylcbiAgLCBzaGFyZWQgICAgICAgICA9IHJlcXVpcmUoJy4vX3NoYXJlZCcpXG4gICwgc2V0VG9TdHJpbmdUYWcgPSByZXF1aXJlKCcuL19zZXQtdG8tc3RyaW5nLXRhZycpXG4gICwgdWlkICAgICAgICAgICAgPSByZXF1aXJlKCcuL191aWQnKVxuICAsIHdrcyAgICAgICAgICAgID0gcmVxdWlyZSgnLi9fd2tzJylcbiAgLCB3a3NFeHQgICAgICAgICA9IHJlcXVpcmUoJy4vX3drcy1leHQnKVxuICAsIHdrc0RlZmluZSAgICAgID0gcmVxdWlyZSgnLi9fd2tzLWRlZmluZScpXG4gICwga2V5T2YgICAgICAgICAgPSByZXF1aXJlKCcuL19rZXlvZicpXG4gICwgZW51bUtleXMgICAgICAgPSByZXF1aXJlKCcuL19lbnVtLWtleXMnKVxuICAsIGlzQXJyYXkgICAgICAgID0gcmVxdWlyZSgnLi9faXMtYXJyYXknKVxuICAsIGFuT2JqZWN0ICAgICAgID0gcmVxdWlyZSgnLi9fYW4tb2JqZWN0JylcbiAgLCB0b0lPYmplY3QgICAgICA9IHJlcXVpcmUoJy4vX3RvLWlvYmplY3QnKVxuICAsIHRvUHJpbWl0aXZlICAgID0gcmVxdWlyZSgnLi9fdG8tcHJpbWl0aXZlJylcbiAgLCBjcmVhdGVEZXNjICAgICA9IHJlcXVpcmUoJy4vX3Byb3BlcnR5LWRlc2MnKVxuICAsIF9jcmVhdGUgICAgICAgID0gcmVxdWlyZSgnLi9fb2JqZWN0LWNyZWF0ZScpXG4gICwgZ09QTkV4dCAgICAgICAgPSByZXF1aXJlKCcuL19vYmplY3QtZ29wbi1leHQnKVxuICAsICRHT1BEICAgICAgICAgID0gcmVxdWlyZSgnLi9fb2JqZWN0LWdvcGQnKVxuICAsICREUCAgICAgICAgICAgID0gcmVxdWlyZSgnLi9fb2JqZWN0LWRwJylcbiAgLCAka2V5cyAgICAgICAgICA9IHJlcXVpcmUoJy4vX29iamVjdC1rZXlzJylcbiAgLCBnT1BEICAgICAgICAgICA9ICRHT1BELmZcbiAgLCBkUCAgICAgICAgICAgICA9ICREUC5mXG4gICwgZ09QTiAgICAgICAgICAgPSBnT1BORXh0LmZcbiAgLCAkU3ltYm9sICAgICAgICA9IGdsb2JhbC5TeW1ib2xcbiAgLCAkSlNPTiAgICAgICAgICA9IGdsb2JhbC5KU09OXG4gICwgX3N0cmluZ2lmeSAgICAgPSAkSlNPTiAmJiAkSlNPTi5zdHJpbmdpZnlcbiAgLCBQUk9UT1RZUEUgICAgICA9ICdwcm90b3R5cGUnXG4gICwgSElEREVOICAgICAgICAgPSB3a3MoJ19oaWRkZW4nKVxuICAsIFRPX1BSSU1JVElWRSAgID0gd2tzKCd0b1ByaW1pdGl2ZScpXG4gICwgaXNFbnVtICAgICAgICAgPSB7fS5wcm9wZXJ0eUlzRW51bWVyYWJsZVxuICAsIFN5bWJvbFJlZ2lzdHJ5ID0gc2hhcmVkKCdzeW1ib2wtcmVnaXN0cnknKVxuICAsIEFsbFN5bWJvbHMgICAgID0gc2hhcmVkKCdzeW1ib2xzJylcbiAgLCBPUFN5bWJvbHMgICAgICA9IHNoYXJlZCgnb3Atc3ltYm9scycpXG4gICwgT2JqZWN0UHJvdG8gICAgPSBPYmplY3RbUFJPVE9UWVBFXVxuICAsIFVTRV9OQVRJVkUgICAgID0gdHlwZW9mICRTeW1ib2wgPT0gJ2Z1bmN0aW9uJ1xuICAsIFFPYmplY3QgICAgICAgID0gZ2xvYmFsLlFPYmplY3Q7XG4vLyBEb24ndCB1c2Ugc2V0dGVycyBpbiBRdCBTY3JpcHQsIGh0dHBzOi8vZ2l0aHViLmNvbS96bG9pcm9jay9jb3JlLWpzL2lzc3Vlcy8xNzNcbnZhciBzZXR0ZXIgPSAhUU9iamVjdCB8fCAhUU9iamVjdFtQUk9UT1RZUEVdIHx8ICFRT2JqZWN0W1BST1RPVFlQRV0uZmluZENoaWxkO1xuXG4vLyBmYWxsYmFjayBmb3Igb2xkIEFuZHJvaWQsIGh0dHBzOi8vY29kZS5nb29nbGUuY29tL3AvdjgvaXNzdWVzL2RldGFpbD9pZD02ODdcbnZhciBzZXRTeW1ib2xEZXNjID0gREVTQ1JJUFRPUlMgJiYgJGZhaWxzKGZ1bmN0aW9uKCl7XG4gIHJldHVybiBfY3JlYXRlKGRQKHt9LCAnYScsIHtcbiAgICBnZXQ6IGZ1bmN0aW9uKCl7IHJldHVybiBkUCh0aGlzLCAnYScsIHt2YWx1ZTogN30pLmE7IH1cbiAgfSkpLmEgIT0gNztcbn0pID8gZnVuY3Rpb24oaXQsIGtleSwgRCl7XG4gIHZhciBwcm90b0Rlc2MgPSBnT1BEKE9iamVjdFByb3RvLCBrZXkpO1xuICBpZihwcm90b0Rlc2MpZGVsZXRlIE9iamVjdFByb3RvW2tleV07XG4gIGRQKGl0LCBrZXksIEQpO1xuICBpZihwcm90b0Rlc2MgJiYgaXQgIT09IE9iamVjdFByb3RvKWRQKE9iamVjdFByb3RvLCBrZXksIHByb3RvRGVzYyk7XG59IDogZFA7XG5cbnZhciB3cmFwID0gZnVuY3Rpb24odGFnKXtcbiAgdmFyIHN5bSA9IEFsbFN5bWJvbHNbdGFnXSA9IF9jcmVhdGUoJFN5bWJvbFtQUk9UT1RZUEVdKTtcbiAgc3ltLl9rID0gdGFnO1xuICByZXR1cm4gc3ltO1xufTtcblxudmFyIGlzU3ltYm9sID0gVVNFX05BVElWRSAmJiB0eXBlb2YgJFN5bWJvbC5pdGVyYXRvciA9PSAnc3ltYm9sJyA/IGZ1bmN0aW9uKGl0KXtcbiAgcmV0dXJuIHR5cGVvZiBpdCA9PSAnc3ltYm9sJztcbn0gOiBmdW5jdGlvbihpdCl7XG4gIHJldHVybiBpdCBpbnN0YW5jZW9mICRTeW1ib2w7XG59O1xuXG52YXIgJGRlZmluZVByb3BlcnR5ID0gZnVuY3Rpb24gZGVmaW5lUHJvcGVydHkoaXQsIGtleSwgRCl7XG4gIGlmKGl0ID09PSBPYmplY3RQcm90bykkZGVmaW5lUHJvcGVydHkoT1BTeW1ib2xzLCBrZXksIEQpO1xuICBhbk9iamVjdChpdCk7XG4gIGtleSA9IHRvUHJpbWl0aXZlKGtleSwgdHJ1ZSk7XG4gIGFuT2JqZWN0KEQpO1xuICBpZihoYXMoQWxsU3ltYm9scywga2V5KSl7XG4gICAgaWYoIUQuZW51bWVyYWJsZSl7XG4gICAgICBpZighaGFzKGl0LCBISURERU4pKWRQKGl0LCBISURERU4sIGNyZWF0ZURlc2MoMSwge30pKTtcbiAgICAgIGl0W0hJRERFTl1ba2V5XSA9IHRydWU7XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmKGhhcyhpdCwgSElEREVOKSAmJiBpdFtISURERU5dW2tleV0paXRbSElEREVOXVtrZXldID0gZmFsc2U7XG4gICAgICBEID0gX2NyZWF0ZShELCB7ZW51bWVyYWJsZTogY3JlYXRlRGVzYygwLCBmYWxzZSl9KTtcbiAgICB9IHJldHVybiBzZXRTeW1ib2xEZXNjKGl0LCBrZXksIEQpO1xuICB9IHJldHVybiBkUChpdCwga2V5LCBEKTtcbn07XG52YXIgJGRlZmluZVByb3BlcnRpZXMgPSBmdW5jdGlvbiBkZWZpbmVQcm9wZXJ0aWVzKGl0LCBQKXtcbiAgYW5PYmplY3QoaXQpO1xuICB2YXIga2V5cyA9IGVudW1LZXlzKFAgPSB0b0lPYmplY3QoUCkpXG4gICAgLCBpICAgID0gMFxuICAgICwgbCA9IGtleXMubGVuZ3RoXG4gICAgLCBrZXk7XG4gIHdoaWxlKGwgPiBpKSRkZWZpbmVQcm9wZXJ0eShpdCwga2V5ID0ga2V5c1tpKytdLCBQW2tleV0pO1xuICByZXR1cm4gaXQ7XG59O1xudmFyICRjcmVhdGUgPSBmdW5jdGlvbiBjcmVhdGUoaXQsIFApe1xuICByZXR1cm4gUCA9PT0gdW5kZWZpbmVkID8gX2NyZWF0ZShpdCkgOiAkZGVmaW5lUHJvcGVydGllcyhfY3JlYXRlKGl0KSwgUCk7XG59O1xudmFyICRwcm9wZXJ0eUlzRW51bWVyYWJsZSA9IGZ1bmN0aW9uIHByb3BlcnR5SXNFbnVtZXJhYmxlKGtleSl7XG4gIHZhciBFID0gaXNFbnVtLmNhbGwodGhpcywga2V5ID0gdG9QcmltaXRpdmUoa2V5LCB0cnVlKSk7XG4gIGlmKHRoaXMgPT09IE9iamVjdFByb3RvICYmIGhhcyhBbGxTeW1ib2xzLCBrZXkpICYmICFoYXMoT1BTeW1ib2xzLCBrZXkpKXJldHVybiBmYWxzZTtcbiAgcmV0dXJuIEUgfHwgIWhhcyh0aGlzLCBrZXkpIHx8ICFoYXMoQWxsU3ltYm9scywga2V5KSB8fCBoYXModGhpcywgSElEREVOKSAmJiB0aGlzW0hJRERFTl1ba2V5XSA/IEUgOiB0cnVlO1xufTtcbnZhciAkZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yID0gZnVuY3Rpb24gZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKGl0LCBrZXkpe1xuICBpdCAgPSB0b0lPYmplY3QoaXQpO1xuICBrZXkgPSB0b1ByaW1pdGl2ZShrZXksIHRydWUpO1xuICBpZihpdCA9PT0gT2JqZWN0UHJvdG8gJiYgaGFzKEFsbFN5bWJvbHMsIGtleSkgJiYgIWhhcyhPUFN5bWJvbHMsIGtleSkpcmV0dXJuO1xuICB2YXIgRCA9IGdPUEQoaXQsIGtleSk7XG4gIGlmKEQgJiYgaGFzKEFsbFN5bWJvbHMsIGtleSkgJiYgIShoYXMoaXQsIEhJRERFTikgJiYgaXRbSElEREVOXVtrZXldKSlELmVudW1lcmFibGUgPSB0cnVlO1xuICByZXR1cm4gRDtcbn07XG52YXIgJGdldE93blByb3BlcnR5TmFtZXMgPSBmdW5jdGlvbiBnZXRPd25Qcm9wZXJ0eU5hbWVzKGl0KXtcbiAgdmFyIG5hbWVzICA9IGdPUE4odG9JT2JqZWN0KGl0KSlcbiAgICAsIHJlc3VsdCA9IFtdXG4gICAgLCBpICAgICAgPSAwXG4gICAgLCBrZXk7XG4gIHdoaWxlKG5hbWVzLmxlbmd0aCA+IGkpe1xuICAgIGlmKCFoYXMoQWxsU3ltYm9scywga2V5ID0gbmFtZXNbaSsrXSkgJiYga2V5ICE9IEhJRERFTiAmJiBrZXkgIT0gTUVUQSlyZXN1bHQucHVzaChrZXkpO1xuICB9IHJldHVybiByZXN1bHQ7XG59O1xudmFyICRnZXRPd25Qcm9wZXJ0eVN5bWJvbHMgPSBmdW5jdGlvbiBnZXRPd25Qcm9wZXJ0eVN5bWJvbHMoaXQpe1xuICB2YXIgSVNfT1AgID0gaXQgPT09IE9iamVjdFByb3RvXG4gICAgLCBuYW1lcyAgPSBnT1BOKElTX09QID8gT1BTeW1ib2xzIDogdG9JT2JqZWN0KGl0KSlcbiAgICAsIHJlc3VsdCA9IFtdXG4gICAgLCBpICAgICAgPSAwXG4gICAgLCBrZXk7XG4gIHdoaWxlKG5hbWVzLmxlbmd0aCA+IGkpe1xuICAgIGlmKGhhcyhBbGxTeW1ib2xzLCBrZXkgPSBuYW1lc1tpKytdKSAmJiAoSVNfT1AgPyBoYXMoT2JqZWN0UHJvdG8sIGtleSkgOiB0cnVlKSlyZXN1bHQucHVzaChBbGxTeW1ib2xzW2tleV0pO1xuICB9IHJldHVybiByZXN1bHQ7XG59O1xuXG4vLyAxOS40LjEuMSBTeW1ib2woW2Rlc2NyaXB0aW9uXSlcbmlmKCFVU0VfTkFUSVZFKXtcbiAgJFN5bWJvbCA9IGZ1bmN0aW9uIFN5bWJvbCgpe1xuICAgIGlmKHRoaXMgaW5zdGFuY2VvZiAkU3ltYm9sKXRocm93IFR5cGVFcnJvcignU3ltYm9sIGlzIG5vdCBhIGNvbnN0cnVjdG9yIScpO1xuICAgIHZhciB0YWcgPSB1aWQoYXJndW1lbnRzLmxlbmd0aCA+IDAgPyBhcmd1bWVudHNbMF0gOiB1bmRlZmluZWQpO1xuICAgIHZhciAkc2V0ID0gZnVuY3Rpb24odmFsdWUpe1xuICAgICAgaWYodGhpcyA9PT0gT2JqZWN0UHJvdG8pJHNldC5jYWxsKE9QU3ltYm9scywgdmFsdWUpO1xuICAgICAgaWYoaGFzKHRoaXMsIEhJRERFTikgJiYgaGFzKHRoaXNbSElEREVOXSwgdGFnKSl0aGlzW0hJRERFTl1bdGFnXSA9IGZhbHNlO1xuICAgICAgc2V0U3ltYm9sRGVzYyh0aGlzLCB0YWcsIGNyZWF0ZURlc2MoMSwgdmFsdWUpKTtcbiAgICB9O1xuICAgIGlmKERFU0NSSVBUT1JTICYmIHNldHRlcilzZXRTeW1ib2xEZXNjKE9iamVjdFByb3RvLCB0YWcsIHtjb25maWd1cmFibGU6IHRydWUsIHNldDogJHNldH0pO1xuICAgIHJldHVybiB3cmFwKHRhZyk7XG4gIH07XG4gIHJlZGVmaW5lKCRTeW1ib2xbUFJPVE9UWVBFXSwgJ3RvU3RyaW5nJywgZnVuY3Rpb24gdG9TdHJpbmcoKXtcbiAgICByZXR1cm4gdGhpcy5faztcbiAgfSk7XG5cbiAgJEdPUEQuZiA9ICRnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3I7XG4gICREUC5mICAgPSAkZGVmaW5lUHJvcGVydHk7XG4gIHJlcXVpcmUoJy4vX29iamVjdC1nb3BuJykuZiA9IGdPUE5FeHQuZiA9ICRnZXRPd25Qcm9wZXJ0eU5hbWVzO1xuICByZXF1aXJlKCcuL19vYmplY3QtcGllJykuZiAgPSAkcHJvcGVydHlJc0VudW1lcmFibGU7XG4gIHJlcXVpcmUoJy4vX29iamVjdC1nb3BzJykuZiA9ICRnZXRPd25Qcm9wZXJ0eVN5bWJvbHM7XG5cbiAgaWYoREVTQ1JJUFRPUlMgJiYgIXJlcXVpcmUoJy4vX2xpYnJhcnknKSl7XG4gICAgcmVkZWZpbmUoT2JqZWN0UHJvdG8sICdwcm9wZXJ0eUlzRW51bWVyYWJsZScsICRwcm9wZXJ0eUlzRW51bWVyYWJsZSwgdHJ1ZSk7XG4gIH1cblxuICB3a3NFeHQuZiA9IGZ1bmN0aW9uKG5hbWUpe1xuICAgIHJldHVybiB3cmFwKHdrcyhuYW1lKSk7XG4gIH1cbn1cblxuJGV4cG9ydCgkZXhwb3J0LkcgKyAkZXhwb3J0LlcgKyAkZXhwb3J0LkYgKiAhVVNFX05BVElWRSwge1N5bWJvbDogJFN5bWJvbH0pO1xuXG5mb3IodmFyIHN5bWJvbHMgPSAoXG4gIC8vIDE5LjQuMi4yLCAxOS40LjIuMywgMTkuNC4yLjQsIDE5LjQuMi42LCAxOS40LjIuOCwgMTkuNC4yLjksIDE5LjQuMi4xMCwgMTkuNC4yLjExLCAxOS40LjIuMTIsIDE5LjQuMi4xMywgMTkuNC4yLjE0XG4gICdoYXNJbnN0YW5jZSxpc0NvbmNhdFNwcmVhZGFibGUsaXRlcmF0b3IsbWF0Y2gscmVwbGFjZSxzZWFyY2gsc3BlY2llcyxzcGxpdCx0b1ByaW1pdGl2ZSx0b1N0cmluZ1RhZyx1bnNjb3BhYmxlcydcbikuc3BsaXQoJywnKSwgaSA9IDA7IHN5bWJvbHMubGVuZ3RoID4gaTsgKXdrcyhzeW1ib2xzW2krK10pO1xuXG5mb3IodmFyIHN5bWJvbHMgPSAka2V5cyh3a3Muc3RvcmUpLCBpID0gMDsgc3ltYm9scy5sZW5ndGggPiBpOyApd2tzRGVmaW5lKHN5bWJvbHNbaSsrXSk7XG5cbiRleHBvcnQoJGV4cG9ydC5TICsgJGV4cG9ydC5GICogIVVTRV9OQVRJVkUsICdTeW1ib2wnLCB7XG4gIC8vIDE5LjQuMi4xIFN5bWJvbC5mb3Ioa2V5KVxuICAnZm9yJzogZnVuY3Rpb24oa2V5KXtcbiAgICByZXR1cm4gaGFzKFN5bWJvbFJlZ2lzdHJ5LCBrZXkgKz0gJycpXG4gICAgICA/IFN5bWJvbFJlZ2lzdHJ5W2tleV1cbiAgICAgIDogU3ltYm9sUmVnaXN0cnlba2V5XSA9ICRTeW1ib2woa2V5KTtcbiAgfSxcbiAgLy8gMTkuNC4yLjUgU3ltYm9sLmtleUZvcihzeW0pXG4gIGtleUZvcjogZnVuY3Rpb24ga2V5Rm9yKGtleSl7XG4gICAgaWYoaXNTeW1ib2woa2V5KSlyZXR1cm4ga2V5T2YoU3ltYm9sUmVnaXN0cnksIGtleSk7XG4gICAgdGhyb3cgVHlwZUVycm9yKGtleSArICcgaXMgbm90IGEgc3ltYm9sIScpO1xuICB9LFxuICB1c2VTZXR0ZXI6IGZ1bmN0aW9uKCl7IHNldHRlciA9IHRydWU7IH0sXG4gIHVzZVNpbXBsZTogZnVuY3Rpb24oKXsgc2V0dGVyID0gZmFsc2U7IH1cbn0pO1xuXG4kZXhwb3J0KCRleHBvcnQuUyArICRleHBvcnQuRiAqICFVU0VfTkFUSVZFLCAnT2JqZWN0Jywge1xuICAvLyAxOS4xLjIuMiBPYmplY3QuY3JlYXRlKE8gWywgUHJvcGVydGllc10pXG4gIGNyZWF0ZTogJGNyZWF0ZSxcbiAgLy8gMTkuMS4yLjQgT2JqZWN0LmRlZmluZVByb3BlcnR5KE8sIFAsIEF0dHJpYnV0ZXMpXG4gIGRlZmluZVByb3BlcnR5OiAkZGVmaW5lUHJvcGVydHksXG4gIC8vIDE5LjEuMi4zIE9iamVjdC5kZWZpbmVQcm9wZXJ0aWVzKE8sIFByb3BlcnRpZXMpXG4gIGRlZmluZVByb3BlcnRpZXM6ICRkZWZpbmVQcm9wZXJ0aWVzLFxuICAvLyAxOS4xLjIuNiBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKE8sIFApXG4gIGdldE93blByb3BlcnR5RGVzY3JpcHRvcjogJGdldE93blByb3BlcnR5RGVzY3JpcHRvcixcbiAgLy8gMTkuMS4yLjcgT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXMoTylcbiAgZ2V0T3duUHJvcGVydHlOYW1lczogJGdldE93blByb3BlcnR5TmFtZXMsXG4gIC8vIDE5LjEuMi44IE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMoTylcbiAgZ2V0T3duUHJvcGVydHlTeW1ib2xzOiAkZ2V0T3duUHJvcGVydHlTeW1ib2xzXG59KTtcblxuLy8gMjQuMy4yIEpTT04uc3RyaW5naWZ5KHZhbHVlIFssIHJlcGxhY2VyIFssIHNwYWNlXV0pXG4kSlNPTiAmJiAkZXhwb3J0KCRleHBvcnQuUyArICRleHBvcnQuRiAqICghVVNFX05BVElWRSB8fCAkZmFpbHMoZnVuY3Rpb24oKXtcbiAgdmFyIFMgPSAkU3ltYm9sKCk7XG4gIC8vIE1TIEVkZ2UgY29udmVydHMgc3ltYm9sIHZhbHVlcyB0byBKU09OIGFzIHt9XG4gIC8vIFdlYktpdCBjb252ZXJ0cyBzeW1ib2wgdmFsdWVzIHRvIEpTT04gYXMgbnVsbFxuICAvLyBWOCB0aHJvd3Mgb24gYm94ZWQgc3ltYm9sc1xuICByZXR1cm4gX3N0cmluZ2lmeShbU10pICE9ICdbbnVsbF0nIHx8IF9zdHJpbmdpZnkoe2E6IFN9KSAhPSAne30nIHx8IF9zdHJpbmdpZnkoT2JqZWN0KFMpKSAhPSAne30nO1xufSkpLCAnSlNPTicsIHtcbiAgc3RyaW5naWZ5OiBmdW5jdGlvbiBzdHJpbmdpZnkoaXQpe1xuICAgIGlmKGl0ID09PSB1bmRlZmluZWQgfHwgaXNTeW1ib2woaXQpKXJldHVybjsgLy8gSUU4IHJldHVybnMgc3RyaW5nIG9uIHVuZGVmaW5lZFxuICAgIHZhciBhcmdzID0gW2l0XVxuICAgICAgLCBpICAgID0gMVxuICAgICAgLCByZXBsYWNlciwgJHJlcGxhY2VyO1xuICAgIHdoaWxlKGFyZ3VtZW50cy5sZW5ndGggPiBpKWFyZ3MucHVzaChhcmd1bWVudHNbaSsrXSk7XG4gICAgcmVwbGFjZXIgPSBhcmdzWzFdO1xuICAgIGlmKHR5cGVvZiByZXBsYWNlciA9PSAnZnVuY3Rpb24nKSRyZXBsYWNlciA9IHJlcGxhY2VyO1xuICAgIGlmKCRyZXBsYWNlciB8fCAhaXNBcnJheShyZXBsYWNlcikpcmVwbGFjZXIgPSBmdW5jdGlvbihrZXksIHZhbHVlKXtcbiAgICAgIGlmKCRyZXBsYWNlcil2YWx1ZSA9ICRyZXBsYWNlci5jYWxsKHRoaXMsIGtleSwgdmFsdWUpO1xuICAgICAgaWYoIWlzU3ltYm9sKHZhbHVlKSlyZXR1cm4gdmFsdWU7XG4gICAgfTtcbiAgICBhcmdzWzFdID0gcmVwbGFjZXI7XG4gICAgcmV0dXJuIF9zdHJpbmdpZnkuYXBwbHkoJEpTT04sIGFyZ3MpO1xuICB9XG59KTtcblxuLy8gMTkuNC4zLjQgU3ltYm9sLnByb3RvdHlwZVtAQHRvUHJpbWl0aXZlXShoaW50KVxuJFN5bWJvbFtQUk9UT1RZUEVdW1RPX1BSSU1JVElWRV0gfHwgcmVxdWlyZSgnLi9faGlkZScpKCRTeW1ib2xbUFJPVE9UWVBFXSwgVE9fUFJJTUlUSVZFLCAkU3ltYm9sW1BST1RPVFlQRV0udmFsdWVPZik7XG4vLyAxOS40LjMuNSBTeW1ib2wucHJvdG90eXBlW0BAdG9TdHJpbmdUYWddXG5zZXRUb1N0cmluZ1RhZygkU3ltYm9sLCAnU3ltYm9sJyk7XG4vLyAyMC4yLjEuOSBNYXRoW0BAdG9TdHJpbmdUYWddXG5zZXRUb1N0cmluZ1RhZyhNYXRoLCAnTWF0aCcsIHRydWUpO1xuLy8gMjQuMy4zIEpTT05bQEB0b1N0cmluZ1RhZ11cbnNldFRvU3RyaW5nVGFnKGdsb2JhbC5KU09OLCAnSlNPTicsIHRydWUpOyIsIi8vIGh0dHBzOi8vZ2l0aHViLmNvbS9EYXZpZEJydWFudC9NYXAtU2V0LnByb3RvdHlwZS50b0pTT05cbnZhciAkZXhwb3J0ICA9IHJlcXVpcmUoJy4vX2V4cG9ydCcpO1xuXG4kZXhwb3J0KCRleHBvcnQuUCArICRleHBvcnQuUiwgJ01hcCcsIHt0b0pTT046IHJlcXVpcmUoJy4vX2NvbGxlY3Rpb24tdG8tanNvbicpKCdNYXAnKX0pOyIsIi8vIGh0dHBzOi8vZ2l0aHViLmNvbS9EYXZpZEJydWFudC9NYXAtU2V0LnByb3RvdHlwZS50b0pTT05cbnZhciAkZXhwb3J0ICA9IHJlcXVpcmUoJy4vX2V4cG9ydCcpO1xuXG4kZXhwb3J0KCRleHBvcnQuUCArICRleHBvcnQuUiwgJ1NldCcsIHt0b0pTT046IHJlcXVpcmUoJy4vX2NvbGxlY3Rpb24tdG8tanNvbicpKCdTZXQnKX0pOyIsInJlcXVpcmUoJy4vX3drcy1kZWZpbmUnKSgnYXN5bmNJdGVyYXRvcicpOyIsInJlcXVpcmUoJy4vX3drcy1kZWZpbmUnKSgnb2JzZXJ2YWJsZScpOyIsInJlcXVpcmUoJy4vZXM2LmFycmF5Lml0ZXJhdG9yJyk7XG52YXIgZ2xvYmFsICAgICAgICA9IHJlcXVpcmUoJy4vX2dsb2JhbCcpXG4gICwgaGlkZSAgICAgICAgICA9IHJlcXVpcmUoJy4vX2hpZGUnKVxuICAsIEl0ZXJhdG9ycyAgICAgPSByZXF1aXJlKCcuL19pdGVyYXRvcnMnKVxuICAsIFRPX1NUUklOR19UQUcgPSByZXF1aXJlKCcuL193a3MnKSgndG9TdHJpbmdUYWcnKTtcblxuZm9yKHZhciBjb2xsZWN0aW9ucyA9IFsnTm9kZUxpc3QnLCAnRE9NVG9rZW5MaXN0JywgJ01lZGlhTGlzdCcsICdTdHlsZVNoZWV0TGlzdCcsICdDU1NSdWxlTGlzdCddLCBpID0gMDsgaSA8IDU7IGkrKyl7XG4gIHZhciBOQU1FICAgICAgID0gY29sbGVjdGlvbnNbaV1cbiAgICAsIENvbGxlY3Rpb24gPSBnbG9iYWxbTkFNRV1cbiAgICAsIHByb3RvICAgICAgPSBDb2xsZWN0aW9uICYmIENvbGxlY3Rpb24ucHJvdG90eXBlO1xuICBpZihwcm90byAmJiAhcHJvdG9bVE9fU1RSSU5HX1RBR10paGlkZShwcm90bywgVE9fU1RSSU5HX1RBRywgTkFNRSk7XG4gIEl0ZXJhdG9yc1tOQU1FXSA9IEl0ZXJhdG9ycy5BcnJheTtcbn0iLCIvKipcbiAqIFRoaXMgaXMgdGhlIHdlYiBicm93c2VyIGltcGxlbWVudGF0aW9uIG9mIGBkZWJ1ZygpYC5cbiAqXG4gKiBFeHBvc2UgYGRlYnVnKClgIGFzIHRoZSBtb2R1bGUuXG4gKi9cblxuZXhwb3J0cyA9IG1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi9kZWJ1ZycpO1xuZXhwb3J0cy5sb2cgPSBsb2c7XG5leHBvcnRzLmZvcm1hdEFyZ3MgPSBmb3JtYXRBcmdzO1xuZXhwb3J0cy5zYXZlID0gc2F2ZTtcbmV4cG9ydHMubG9hZCA9IGxvYWQ7XG5leHBvcnRzLnVzZUNvbG9ycyA9IHVzZUNvbG9ycztcbmV4cG9ydHMuc3RvcmFnZSA9ICd1bmRlZmluZWQnICE9IHR5cGVvZiBjaHJvbWVcbiAgICAgICAgICAgICAgICYmICd1bmRlZmluZWQnICE9IHR5cGVvZiBjaHJvbWUuc3RvcmFnZVxuICAgICAgICAgICAgICAgICAgPyBjaHJvbWUuc3RvcmFnZS5sb2NhbFxuICAgICAgICAgICAgICAgICAgOiBsb2NhbHN0b3JhZ2UoKTtcblxuLyoqXG4gKiBDb2xvcnMuXG4gKi9cblxuZXhwb3J0cy5jb2xvcnMgPSBbXG4gICdsaWdodHNlYWdyZWVuJyxcbiAgJ2ZvcmVzdGdyZWVuJyxcbiAgJ2dvbGRlbnJvZCcsXG4gICdkb2RnZXJibHVlJyxcbiAgJ2RhcmtvcmNoaWQnLFxuICAnY3JpbXNvbidcbl07XG5cbi8qKlxuICogQ3VycmVudGx5IG9ubHkgV2ViS2l0LWJhc2VkIFdlYiBJbnNwZWN0b3JzLCBGaXJlZm94ID49IHYzMSxcbiAqIGFuZCB0aGUgRmlyZWJ1ZyBleHRlbnNpb24gKGFueSBGaXJlZm94IHZlcnNpb24pIGFyZSBrbm93blxuICogdG8gc3VwcG9ydCBcIiVjXCIgQ1NTIGN1c3RvbWl6YXRpb25zLlxuICpcbiAqIFRPRE86IGFkZCBhIGBsb2NhbFN0b3JhZ2VgIHZhcmlhYmxlIHRvIGV4cGxpY2l0bHkgZW5hYmxlL2Rpc2FibGUgY29sb3JzXG4gKi9cblxuZnVuY3Rpb24gdXNlQ29sb3JzKCkge1xuICAvLyBOQjogSW4gYW4gRWxlY3Ryb24gcHJlbG9hZCBzY3JpcHQsIGRvY3VtZW50IHdpbGwgYmUgZGVmaW5lZCBidXQgbm90IGZ1bGx5XG4gIC8vIGluaXRpYWxpemVkLiBTaW5jZSB3ZSBrbm93IHdlJ3JlIGluIENocm9tZSwgd2UnbGwganVzdCBkZXRlY3QgdGhpcyBjYXNlXG4gIC8vIGV4cGxpY2l0bHlcbiAgaWYgKHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnICYmIHdpbmRvdy5wcm9jZXNzICYmIHdpbmRvdy5wcm9jZXNzLnR5cGUgPT09ICdyZW5kZXJlcicpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIC8vIGlzIHdlYmtpdD8gaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL2EvMTY0NTk2MDYvMzc2NzczXG4gIC8vIGRvY3VtZW50IGlzIHVuZGVmaW5lZCBpbiByZWFjdC1uYXRpdmU6IGh0dHBzOi8vZ2l0aHViLmNvbS9mYWNlYm9vay9yZWFjdC1uYXRpdmUvcHVsbC8xNjMyXG4gIHJldHVybiAodHlwZW9mIGRvY3VtZW50ICE9PSAndW5kZWZpbmVkJyAmJiBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQgJiYgZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LnN0eWxlICYmIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5zdHlsZS5XZWJraXRBcHBlYXJhbmNlKSB8fFxuICAgIC8vIGlzIGZpcmVidWc/IGh0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9hLzM5ODEyMC8zNzY3NzNcbiAgICAodHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcgJiYgd2luZG93LmNvbnNvbGUgJiYgKHdpbmRvdy5jb25zb2xlLmZpcmVidWcgfHwgKHdpbmRvdy5jb25zb2xlLmV4Y2VwdGlvbiAmJiB3aW5kb3cuY29uc29sZS50YWJsZSkpKSB8fFxuICAgIC8vIGlzIGZpcmVmb3ggPj0gdjMxP1xuICAgIC8vIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvVG9vbHMvV2ViX0NvbnNvbGUjU3R5bGluZ19tZXNzYWdlc1xuICAgICh0eXBlb2YgbmF2aWdhdG9yICE9PSAndW5kZWZpbmVkJyAmJiBuYXZpZ2F0b3IudXNlckFnZW50ICYmIG5hdmlnYXRvci51c2VyQWdlbnQudG9Mb3dlckNhc2UoKS5tYXRjaCgvZmlyZWZveFxcLyhcXGQrKS8pICYmIHBhcnNlSW50KFJlZ0V4cC4kMSwgMTApID49IDMxKSB8fFxuICAgIC8vIGRvdWJsZSBjaGVjayB3ZWJraXQgaW4gdXNlckFnZW50IGp1c3QgaW4gY2FzZSB3ZSBhcmUgaW4gYSB3b3JrZXJcbiAgICAodHlwZW9mIG5hdmlnYXRvciAhPT0gJ3VuZGVmaW5lZCcgJiYgbmF2aWdhdG9yLnVzZXJBZ2VudCAmJiBuYXZpZ2F0b3IudXNlckFnZW50LnRvTG93ZXJDYXNlKCkubWF0Y2goL2FwcGxld2Via2l0XFwvKFxcZCspLykpO1xufVxuXG4vKipcbiAqIE1hcCAlaiB0byBgSlNPTi5zdHJpbmdpZnkoKWAsIHNpbmNlIG5vIFdlYiBJbnNwZWN0b3JzIGRvIHRoYXQgYnkgZGVmYXVsdC5cbiAqL1xuXG5leHBvcnRzLmZvcm1hdHRlcnMuaiA9IGZ1bmN0aW9uKHYpIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodik7XG4gIH0gY2F0Y2ggKGVycikge1xuICAgIHJldHVybiAnW1VuZXhwZWN0ZWRKU09OUGFyc2VFcnJvcl06ICcgKyBlcnIubWVzc2FnZTtcbiAgfVxufTtcblxuXG4vKipcbiAqIENvbG9yaXplIGxvZyBhcmd1bWVudHMgaWYgZW5hYmxlZC5cbiAqXG4gKiBAYXBpIHB1YmxpY1xuICovXG5cbmZ1bmN0aW9uIGZvcm1hdEFyZ3MoYXJncykge1xuICB2YXIgdXNlQ29sb3JzID0gdGhpcy51c2VDb2xvcnM7XG5cbiAgYXJnc1swXSA9ICh1c2VDb2xvcnMgPyAnJWMnIDogJycpXG4gICAgKyB0aGlzLm5hbWVzcGFjZVxuICAgICsgKHVzZUNvbG9ycyA/ICcgJWMnIDogJyAnKVxuICAgICsgYXJnc1swXVxuICAgICsgKHVzZUNvbG9ycyA/ICclYyAnIDogJyAnKVxuICAgICsgJysnICsgZXhwb3J0cy5odW1hbml6ZSh0aGlzLmRpZmYpO1xuXG4gIGlmICghdXNlQ29sb3JzKSByZXR1cm47XG5cbiAgdmFyIGMgPSAnY29sb3I6ICcgKyB0aGlzLmNvbG9yO1xuICBhcmdzLnNwbGljZSgxLCAwLCBjLCAnY29sb3I6IGluaGVyaXQnKVxuXG4gIC8vIHRoZSBmaW5hbCBcIiVjXCIgaXMgc29tZXdoYXQgdHJpY2t5LCBiZWNhdXNlIHRoZXJlIGNvdWxkIGJlIG90aGVyXG4gIC8vIGFyZ3VtZW50cyBwYXNzZWQgZWl0aGVyIGJlZm9yZSBvciBhZnRlciB0aGUgJWMsIHNvIHdlIG5lZWQgdG9cbiAgLy8gZmlndXJlIG91dCB0aGUgY29ycmVjdCBpbmRleCB0byBpbnNlcnQgdGhlIENTUyBpbnRvXG4gIHZhciBpbmRleCA9IDA7XG4gIHZhciBsYXN0QyA9IDA7XG4gIGFyZ3NbMF0ucmVwbGFjZSgvJVthLXpBLVolXS9nLCBmdW5jdGlvbihtYXRjaCkge1xuICAgIGlmICgnJSUnID09PSBtYXRjaCkgcmV0dXJuO1xuICAgIGluZGV4Kys7XG4gICAgaWYgKCclYycgPT09IG1hdGNoKSB7XG4gICAgICAvLyB3ZSBvbmx5IGFyZSBpbnRlcmVzdGVkIGluIHRoZSAqbGFzdCogJWNcbiAgICAgIC8vICh0aGUgdXNlciBtYXkgaGF2ZSBwcm92aWRlZCB0aGVpciBvd24pXG4gICAgICBsYXN0QyA9IGluZGV4O1xuICAgIH1cbiAgfSk7XG5cbiAgYXJncy5zcGxpY2UobGFzdEMsIDAsIGMpO1xufVxuXG4vKipcbiAqIEludm9rZXMgYGNvbnNvbGUubG9nKClgIHdoZW4gYXZhaWxhYmxlLlxuICogTm8tb3Agd2hlbiBgY29uc29sZS5sb2dgIGlzIG5vdCBhIFwiZnVuY3Rpb25cIi5cbiAqXG4gKiBAYXBpIHB1YmxpY1xuICovXG5cbmZ1bmN0aW9uIGxvZygpIHtcbiAgLy8gdGhpcyBoYWNrZXJ5IGlzIHJlcXVpcmVkIGZvciBJRTgvOSwgd2hlcmVcbiAgLy8gdGhlIGBjb25zb2xlLmxvZ2AgZnVuY3Rpb24gZG9lc24ndCBoYXZlICdhcHBseSdcbiAgcmV0dXJuICdvYmplY3QnID09PSB0eXBlb2YgY29uc29sZVxuICAgICYmIGNvbnNvbGUubG9nXG4gICAgJiYgRnVuY3Rpb24ucHJvdG90eXBlLmFwcGx5LmNhbGwoY29uc29sZS5sb2csIGNvbnNvbGUsIGFyZ3VtZW50cyk7XG59XG5cbi8qKlxuICogU2F2ZSBgbmFtZXNwYWNlc2AuXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IG5hbWVzcGFjZXNcbiAqIEBhcGkgcHJpdmF0ZVxuICovXG5cbmZ1bmN0aW9uIHNhdmUobmFtZXNwYWNlcykge1xuICB0cnkge1xuICAgIGlmIChudWxsID09IG5hbWVzcGFjZXMpIHtcbiAgICAgIGV4cG9ydHMuc3RvcmFnZS5yZW1vdmVJdGVtKCdkZWJ1ZycpO1xuICAgIH0gZWxzZSB7XG4gICAgICBleHBvcnRzLnN0b3JhZ2UuZGVidWcgPSBuYW1lc3BhY2VzO1xuICAgIH1cbiAgfSBjYXRjaChlKSB7fVxufVxuXG4vKipcbiAqIExvYWQgYG5hbWVzcGFjZXNgLlxuICpcbiAqIEByZXR1cm4ge1N0cmluZ30gcmV0dXJucyB0aGUgcHJldmlvdXNseSBwZXJzaXN0ZWQgZGVidWcgbW9kZXNcbiAqIEBhcGkgcHJpdmF0ZVxuICovXG5cbmZ1bmN0aW9uIGxvYWQoKSB7XG4gIHZhciByO1xuICB0cnkge1xuICAgIHIgPSBleHBvcnRzLnN0b3JhZ2UuZGVidWc7XG4gIH0gY2F0Y2goZSkge31cblxuICAvLyBJZiBkZWJ1ZyBpc24ndCBzZXQgaW4gTFMsIGFuZCB3ZSdyZSBpbiBFbGVjdHJvbiwgdHJ5IHRvIGxvYWQgJERFQlVHXG4gIGlmICghciAmJiB0eXBlb2YgcHJvY2VzcyAhPT0gJ3VuZGVmaW5lZCcgJiYgJ2VudicgaW4gcHJvY2Vzcykge1xuICAgIHIgPSBwcm9jZXNzLmVudi5ERUJVRztcbiAgfVxuXG4gIHJldHVybiByO1xufVxuXG4vKipcbiAqIEVuYWJsZSBuYW1lc3BhY2VzIGxpc3RlZCBpbiBgbG9jYWxTdG9yYWdlLmRlYnVnYCBpbml0aWFsbHkuXG4gKi9cblxuZXhwb3J0cy5lbmFibGUobG9hZCgpKTtcblxuLyoqXG4gKiBMb2NhbHN0b3JhZ2UgYXR0ZW1wdHMgdG8gcmV0dXJuIHRoZSBsb2NhbHN0b3JhZ2UuXG4gKlxuICogVGhpcyBpcyBuZWNlc3NhcnkgYmVjYXVzZSBzYWZhcmkgdGhyb3dzXG4gKiB3aGVuIGEgdXNlciBkaXNhYmxlcyBjb29raWVzL2xvY2Fsc3RvcmFnZVxuICogYW5kIHlvdSBhdHRlbXB0IHRvIGFjY2VzcyBpdC5cbiAqXG4gKiBAcmV0dXJuIHtMb2NhbFN0b3JhZ2V9XG4gKiBAYXBpIHByaXZhdGVcbiAqL1xuXG5mdW5jdGlvbiBsb2NhbHN0b3JhZ2UoKSB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIHdpbmRvdy5sb2NhbFN0b3JhZ2U7XG4gIH0gY2F0Y2ggKGUpIHt9XG59XG4iLCJcbi8qKlxuICogVGhpcyBpcyB0aGUgY29tbW9uIGxvZ2ljIGZvciBib3RoIHRoZSBOb2RlLmpzIGFuZCB3ZWIgYnJvd3NlclxuICogaW1wbGVtZW50YXRpb25zIG9mIGBkZWJ1ZygpYC5cbiAqXG4gKiBFeHBvc2UgYGRlYnVnKClgIGFzIHRoZSBtb2R1bGUuXG4gKi9cblxuZXhwb3J0cyA9IG1vZHVsZS5leHBvcnRzID0gY3JlYXRlRGVidWcuZGVidWcgPSBjcmVhdGVEZWJ1Z1snZGVmYXVsdCddID0gY3JlYXRlRGVidWc7XG5leHBvcnRzLmNvZXJjZSA9IGNvZXJjZTtcbmV4cG9ydHMuZGlzYWJsZSA9IGRpc2FibGU7XG5leHBvcnRzLmVuYWJsZSA9IGVuYWJsZTtcbmV4cG9ydHMuZW5hYmxlZCA9IGVuYWJsZWQ7XG5leHBvcnRzLmh1bWFuaXplID0gcmVxdWlyZSgnbXMnKTtcblxuLyoqXG4gKiBUaGUgY3VycmVudGx5IGFjdGl2ZSBkZWJ1ZyBtb2RlIG5hbWVzLCBhbmQgbmFtZXMgdG8gc2tpcC5cbiAqL1xuXG5leHBvcnRzLm5hbWVzID0gW107XG5leHBvcnRzLnNraXBzID0gW107XG5cbi8qKlxuICogTWFwIG9mIHNwZWNpYWwgXCIlblwiIGhhbmRsaW5nIGZ1bmN0aW9ucywgZm9yIHRoZSBkZWJ1ZyBcImZvcm1hdFwiIGFyZ3VtZW50LlxuICpcbiAqIFZhbGlkIGtleSBuYW1lcyBhcmUgYSBzaW5nbGUsIGxvd2VyIG9yIHVwcGVyLWNhc2UgbGV0dGVyLCBpLmUuIFwiblwiIGFuZCBcIk5cIi5cbiAqL1xuXG5leHBvcnRzLmZvcm1hdHRlcnMgPSB7fTtcblxuLyoqXG4gKiBQcmV2aW91cyBsb2cgdGltZXN0YW1wLlxuICovXG5cbnZhciBwcmV2VGltZTtcblxuLyoqXG4gKiBTZWxlY3QgYSBjb2xvci5cbiAqIEBwYXJhbSB7U3RyaW5nfSBuYW1lc3BhY2VcbiAqIEByZXR1cm4ge051bWJlcn1cbiAqIEBhcGkgcHJpdmF0ZVxuICovXG5cbmZ1bmN0aW9uIHNlbGVjdENvbG9yKG5hbWVzcGFjZSkge1xuICB2YXIgaGFzaCA9IDAsIGk7XG5cbiAgZm9yIChpIGluIG5hbWVzcGFjZSkge1xuICAgIGhhc2ggID0gKChoYXNoIDw8IDUpIC0gaGFzaCkgKyBuYW1lc3BhY2UuY2hhckNvZGVBdChpKTtcbiAgICBoYXNoIHw9IDA7IC8vIENvbnZlcnQgdG8gMzJiaXQgaW50ZWdlclxuICB9XG5cbiAgcmV0dXJuIGV4cG9ydHMuY29sb3JzW01hdGguYWJzKGhhc2gpICUgZXhwb3J0cy5jb2xvcnMubGVuZ3RoXTtcbn1cblxuLyoqXG4gKiBDcmVhdGUgYSBkZWJ1Z2dlciB3aXRoIHRoZSBnaXZlbiBgbmFtZXNwYWNlYC5cbiAqXG4gKiBAcGFyYW0ge1N0cmluZ30gbmFtZXNwYWNlXG4gKiBAcmV0dXJuIHtGdW5jdGlvbn1cbiAqIEBhcGkgcHVibGljXG4gKi9cblxuZnVuY3Rpb24gY3JlYXRlRGVidWcobmFtZXNwYWNlKSB7XG5cbiAgZnVuY3Rpb24gZGVidWcoKSB7XG4gICAgLy8gZGlzYWJsZWQ/XG4gICAgaWYgKCFkZWJ1Zy5lbmFibGVkKSByZXR1cm47XG5cbiAgICB2YXIgc2VsZiA9IGRlYnVnO1xuXG4gICAgLy8gc2V0IGBkaWZmYCB0aW1lc3RhbXBcbiAgICB2YXIgY3VyciA9ICtuZXcgRGF0ZSgpO1xuICAgIHZhciBtcyA9IGN1cnIgLSAocHJldlRpbWUgfHwgY3Vycik7XG4gICAgc2VsZi5kaWZmID0gbXM7XG4gICAgc2VsZi5wcmV2ID0gcHJldlRpbWU7XG4gICAgc2VsZi5jdXJyID0gY3VycjtcbiAgICBwcmV2VGltZSA9IGN1cnI7XG5cbiAgICAvLyB0dXJuIHRoZSBgYXJndW1lbnRzYCBpbnRvIGEgcHJvcGVyIEFycmF5XG4gICAgdmFyIGFyZ3MgPSBuZXcgQXJyYXkoYXJndW1lbnRzLmxlbmd0aCk7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBhcmdzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBhcmdzW2ldID0gYXJndW1lbnRzW2ldO1xuICAgIH1cblxuICAgIGFyZ3NbMF0gPSBleHBvcnRzLmNvZXJjZShhcmdzWzBdKTtcblxuICAgIGlmICgnc3RyaW5nJyAhPT0gdHlwZW9mIGFyZ3NbMF0pIHtcbiAgICAgIC8vIGFueXRoaW5nIGVsc2UgbGV0J3MgaW5zcGVjdCB3aXRoICVPXG4gICAgICBhcmdzLnVuc2hpZnQoJyVPJyk7XG4gICAgfVxuXG4gICAgLy8gYXBwbHkgYW55IGBmb3JtYXR0ZXJzYCB0cmFuc2Zvcm1hdGlvbnNcbiAgICB2YXIgaW5kZXggPSAwO1xuICAgIGFyZ3NbMF0gPSBhcmdzWzBdLnJlcGxhY2UoLyUoW2EtekEtWiVdKS9nLCBmdW5jdGlvbihtYXRjaCwgZm9ybWF0KSB7XG4gICAgICAvLyBpZiB3ZSBlbmNvdW50ZXIgYW4gZXNjYXBlZCAlIHRoZW4gZG9uJ3QgaW5jcmVhc2UgdGhlIGFycmF5IGluZGV4XG4gICAgICBpZiAobWF0Y2ggPT09ICclJScpIHJldHVybiBtYXRjaDtcbiAgICAgIGluZGV4Kys7XG4gICAgICB2YXIgZm9ybWF0dGVyID0gZXhwb3J0cy5mb3JtYXR0ZXJzW2Zvcm1hdF07XG4gICAgICBpZiAoJ2Z1bmN0aW9uJyA9PT0gdHlwZW9mIGZvcm1hdHRlcikge1xuICAgICAgICB2YXIgdmFsID0gYXJnc1tpbmRleF07XG4gICAgICAgIG1hdGNoID0gZm9ybWF0dGVyLmNhbGwoc2VsZiwgdmFsKTtcblxuICAgICAgICAvLyBub3cgd2UgbmVlZCB0byByZW1vdmUgYGFyZ3NbaW5kZXhdYCBzaW5jZSBpdCdzIGlubGluZWQgaW4gdGhlIGBmb3JtYXRgXG4gICAgICAgIGFyZ3Muc3BsaWNlKGluZGV4LCAxKTtcbiAgICAgICAgaW5kZXgtLTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBtYXRjaDtcbiAgICB9KTtcblxuICAgIC8vIGFwcGx5IGVudi1zcGVjaWZpYyBmb3JtYXR0aW5nIChjb2xvcnMsIGV0Yy4pXG4gICAgZXhwb3J0cy5mb3JtYXRBcmdzLmNhbGwoc2VsZiwgYXJncyk7XG5cbiAgICB2YXIgbG9nRm4gPSBkZWJ1Zy5sb2cgfHwgZXhwb3J0cy5sb2cgfHwgY29uc29sZS5sb2cuYmluZChjb25zb2xlKTtcbiAgICBsb2dGbi5hcHBseShzZWxmLCBhcmdzKTtcbiAgfVxuXG4gIGRlYnVnLm5hbWVzcGFjZSA9IG5hbWVzcGFjZTtcbiAgZGVidWcuZW5hYmxlZCA9IGV4cG9ydHMuZW5hYmxlZChuYW1lc3BhY2UpO1xuICBkZWJ1Zy51c2VDb2xvcnMgPSBleHBvcnRzLnVzZUNvbG9ycygpO1xuICBkZWJ1Zy5jb2xvciA9IHNlbGVjdENvbG9yKG5hbWVzcGFjZSk7XG5cbiAgLy8gZW52LXNwZWNpZmljIGluaXRpYWxpemF0aW9uIGxvZ2ljIGZvciBkZWJ1ZyBpbnN0YW5jZXNcbiAgaWYgKCdmdW5jdGlvbicgPT09IHR5cGVvZiBleHBvcnRzLmluaXQpIHtcbiAgICBleHBvcnRzLmluaXQoZGVidWcpO1xuICB9XG5cbiAgcmV0dXJuIGRlYnVnO1xufVxuXG4vKipcbiAqIEVuYWJsZXMgYSBkZWJ1ZyBtb2RlIGJ5IG5hbWVzcGFjZXMuIFRoaXMgY2FuIGluY2x1ZGUgbW9kZXNcbiAqIHNlcGFyYXRlZCBieSBhIGNvbG9uIGFuZCB3aWxkY2FyZHMuXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IG5hbWVzcGFjZXNcbiAqIEBhcGkgcHVibGljXG4gKi9cblxuZnVuY3Rpb24gZW5hYmxlKG5hbWVzcGFjZXMpIHtcbiAgZXhwb3J0cy5zYXZlKG5hbWVzcGFjZXMpO1xuXG4gIGV4cG9ydHMubmFtZXMgPSBbXTtcbiAgZXhwb3J0cy5za2lwcyA9IFtdO1xuXG4gIHZhciBzcGxpdCA9ICh0eXBlb2YgbmFtZXNwYWNlcyA9PT0gJ3N0cmluZycgPyBuYW1lc3BhY2VzIDogJycpLnNwbGl0KC9bXFxzLF0rLyk7XG4gIHZhciBsZW4gPSBzcGxpdC5sZW5ndGg7XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgIGlmICghc3BsaXRbaV0pIGNvbnRpbnVlOyAvLyBpZ25vcmUgZW1wdHkgc3RyaW5nc1xuICAgIG5hbWVzcGFjZXMgPSBzcGxpdFtpXS5yZXBsYWNlKC9cXCovZywgJy4qPycpO1xuICAgIGlmIChuYW1lc3BhY2VzWzBdID09PSAnLScpIHtcbiAgICAgIGV4cG9ydHMuc2tpcHMucHVzaChuZXcgUmVnRXhwKCdeJyArIG5hbWVzcGFjZXMuc3Vic3RyKDEpICsgJyQnKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGV4cG9ydHMubmFtZXMucHVzaChuZXcgUmVnRXhwKCdeJyArIG5hbWVzcGFjZXMgKyAnJCcpKTtcbiAgICB9XG4gIH1cbn1cblxuLyoqXG4gKiBEaXNhYmxlIGRlYnVnIG91dHB1dC5cbiAqXG4gKiBAYXBpIHB1YmxpY1xuICovXG5cbmZ1bmN0aW9uIGRpc2FibGUoKSB7XG4gIGV4cG9ydHMuZW5hYmxlKCcnKTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRydWUgaWYgdGhlIGdpdmVuIG1vZGUgbmFtZSBpcyBlbmFibGVkLCBmYWxzZSBvdGhlcndpc2UuXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IG5hbWVcbiAqIEByZXR1cm4ge0Jvb2xlYW59XG4gKiBAYXBpIHB1YmxpY1xuICovXG5cbmZ1bmN0aW9uIGVuYWJsZWQobmFtZSkge1xuICB2YXIgaSwgbGVuO1xuICBmb3IgKGkgPSAwLCBsZW4gPSBleHBvcnRzLnNraXBzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgaWYgKGV4cG9ydHMuc2tpcHNbaV0udGVzdChuYW1lKSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuICBmb3IgKGkgPSAwLCBsZW4gPSBleHBvcnRzLm5hbWVzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgaWYgKGV4cG9ydHMubmFtZXNbaV0udGVzdChuYW1lKSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9XG4gIHJldHVybiBmYWxzZTtcbn1cblxuLyoqXG4gKiBDb2VyY2UgYHZhbGAuXG4gKlxuICogQHBhcmFtIHtNaXhlZH0gdmFsXG4gKiBAcmV0dXJuIHtNaXhlZH1cbiAqIEBhcGkgcHJpdmF0ZVxuICovXG5cbmZ1bmN0aW9uIGNvZXJjZSh2YWwpIHtcbiAgaWYgKHZhbCBpbnN0YW5jZW9mIEVycm9yKSByZXR1cm4gdmFsLnN0YWNrIHx8IHZhbC5tZXNzYWdlO1xuICByZXR1cm4gdmFsO1xufVxuIiwiLyoqXG4gKiBIZWxwZXJzLlxuICovXG5cbnZhciBzID0gMTAwMDtcbnZhciBtID0gcyAqIDYwO1xudmFyIGggPSBtICogNjA7XG52YXIgZCA9IGggKiAyNDtcbnZhciB5ID0gZCAqIDM2NS4yNTtcblxuLyoqXG4gKiBQYXJzZSBvciBmb3JtYXQgdGhlIGdpdmVuIGB2YWxgLlxuICpcbiAqIE9wdGlvbnM6XG4gKlxuICogIC0gYGxvbmdgIHZlcmJvc2UgZm9ybWF0dGluZyBbZmFsc2VdXG4gKlxuICogQHBhcmFtIHtTdHJpbmd8TnVtYmVyfSB2YWxcbiAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9uc11cbiAqIEB0aHJvd3Mge0Vycm9yfSB0aHJvdyBhbiBlcnJvciBpZiB2YWwgaXMgbm90IGEgbm9uLWVtcHR5IHN0cmluZyBvciBhIG51bWJlclxuICogQHJldHVybiB7U3RyaW5nfE51bWJlcn1cbiAqIEBhcGkgcHVibGljXG4gKi9cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbih2YWwsIG9wdGlvbnMpIHtcbiAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge307XG4gIHZhciB0eXBlID0gdHlwZW9mIHZhbDtcbiAgaWYgKHR5cGUgPT09ICdzdHJpbmcnICYmIHZhbC5sZW5ndGggPiAwKSB7XG4gICAgcmV0dXJuIHBhcnNlKHZhbCk7XG4gIH0gZWxzZSBpZiAodHlwZSA9PT0gJ251bWJlcicgJiYgaXNOYU4odmFsKSA9PT0gZmFsc2UpIHtcbiAgICByZXR1cm4gb3B0aW9ucy5sb25nID8gZm10TG9uZyh2YWwpIDogZm10U2hvcnQodmFsKTtcbiAgfVxuICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgJ3ZhbCBpcyBub3QgYSBub24tZW1wdHkgc3RyaW5nIG9yIGEgdmFsaWQgbnVtYmVyLiB2YWw9JyArXG4gICAgICBKU09OLnN0cmluZ2lmeSh2YWwpXG4gICk7XG59O1xuXG4vKipcbiAqIFBhcnNlIHRoZSBnaXZlbiBgc3RyYCBhbmQgcmV0dXJuIG1pbGxpc2Vjb25kcy5cbiAqXG4gKiBAcGFyYW0ge1N0cmluZ30gc3RyXG4gKiBAcmV0dXJuIHtOdW1iZXJ9XG4gKiBAYXBpIHByaXZhdGVcbiAqL1xuXG5mdW5jdGlvbiBwYXJzZShzdHIpIHtcbiAgc3RyID0gU3RyaW5nKHN0cik7XG4gIGlmIChzdHIubGVuZ3RoID4gMTAwKSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIHZhciBtYXRjaCA9IC9eKCg/OlxcZCspP1xcLj9cXGQrKSAqKG1pbGxpc2Vjb25kcz98bXNlY3M/fG1zfHNlY29uZHM/fHNlY3M/fHN8bWludXRlcz98bWlucz98bXxob3Vycz98aHJzP3xofGRheXM/fGR8eWVhcnM/fHlycz98eSk/JC9pLmV4ZWMoXG4gICAgc3RyXG4gICk7XG4gIGlmICghbWF0Y2gpIHtcbiAgICByZXR1cm47XG4gIH1cbiAgdmFyIG4gPSBwYXJzZUZsb2F0KG1hdGNoWzFdKTtcbiAgdmFyIHR5cGUgPSAobWF0Y2hbMl0gfHwgJ21zJykudG9Mb3dlckNhc2UoKTtcbiAgc3dpdGNoICh0eXBlKSB7XG4gICAgY2FzZSAneWVhcnMnOlxuICAgIGNhc2UgJ3llYXInOlxuICAgIGNhc2UgJ3lycyc6XG4gICAgY2FzZSAneXInOlxuICAgIGNhc2UgJ3knOlxuICAgICAgcmV0dXJuIG4gKiB5O1xuICAgIGNhc2UgJ2RheXMnOlxuICAgIGNhc2UgJ2RheSc6XG4gICAgY2FzZSAnZCc6XG4gICAgICByZXR1cm4gbiAqIGQ7XG4gICAgY2FzZSAnaG91cnMnOlxuICAgIGNhc2UgJ2hvdXInOlxuICAgIGNhc2UgJ2hycyc6XG4gICAgY2FzZSAnaHInOlxuICAgIGNhc2UgJ2gnOlxuICAgICAgcmV0dXJuIG4gKiBoO1xuICAgIGNhc2UgJ21pbnV0ZXMnOlxuICAgIGNhc2UgJ21pbnV0ZSc6XG4gICAgY2FzZSAnbWlucyc6XG4gICAgY2FzZSAnbWluJzpcbiAgICBjYXNlICdtJzpcbiAgICAgIHJldHVybiBuICogbTtcbiAgICBjYXNlICdzZWNvbmRzJzpcbiAgICBjYXNlICdzZWNvbmQnOlxuICAgIGNhc2UgJ3NlY3MnOlxuICAgIGNhc2UgJ3NlYyc6XG4gICAgY2FzZSAncyc6XG4gICAgICByZXR1cm4gbiAqIHM7XG4gICAgY2FzZSAnbWlsbGlzZWNvbmRzJzpcbiAgICBjYXNlICdtaWxsaXNlY29uZCc6XG4gICAgY2FzZSAnbXNlY3MnOlxuICAgIGNhc2UgJ21zZWMnOlxuICAgIGNhc2UgJ21zJzpcbiAgICAgIHJldHVybiBuO1xuICAgIGRlZmF1bHQ6XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG59XG5cbi8qKlxuICogU2hvcnQgZm9ybWF0IGZvciBgbXNgLlxuICpcbiAqIEBwYXJhbSB7TnVtYmVyfSBtc1xuICogQHJldHVybiB7U3RyaW5nfVxuICogQGFwaSBwcml2YXRlXG4gKi9cblxuZnVuY3Rpb24gZm10U2hvcnQobXMpIHtcbiAgaWYgKG1zID49IGQpIHtcbiAgICByZXR1cm4gTWF0aC5yb3VuZChtcyAvIGQpICsgJ2QnO1xuICB9XG4gIGlmIChtcyA+PSBoKSB7XG4gICAgcmV0dXJuIE1hdGgucm91bmQobXMgLyBoKSArICdoJztcbiAgfVxuICBpZiAobXMgPj0gbSkge1xuICAgIHJldHVybiBNYXRoLnJvdW5kKG1zIC8gbSkgKyAnbSc7XG4gIH1cbiAgaWYgKG1zID49IHMpIHtcbiAgICByZXR1cm4gTWF0aC5yb3VuZChtcyAvIHMpICsgJ3MnO1xuICB9XG4gIHJldHVybiBtcyArICdtcyc7XG59XG5cbi8qKlxuICogTG9uZyBmb3JtYXQgZm9yIGBtc2AuXG4gKlxuICogQHBhcmFtIHtOdW1iZXJ9IG1zXG4gKiBAcmV0dXJuIHtTdHJpbmd9XG4gKiBAYXBpIHByaXZhdGVcbiAqL1xuXG5mdW5jdGlvbiBmbXRMb25nKG1zKSB7XG4gIHJldHVybiBwbHVyYWwobXMsIGQsICdkYXknKSB8fFxuICAgIHBsdXJhbChtcywgaCwgJ2hvdXInKSB8fFxuICAgIHBsdXJhbChtcywgbSwgJ21pbnV0ZScpIHx8XG4gICAgcGx1cmFsKG1zLCBzLCAnc2Vjb25kJykgfHxcbiAgICBtcyArICcgbXMnO1xufVxuXG4vKipcbiAqIFBsdXJhbGl6YXRpb24gaGVscGVyLlxuICovXG5cbmZ1bmN0aW9uIHBsdXJhbChtcywgbiwgbmFtZSkge1xuICBpZiAobXMgPCBuKSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIGlmIChtcyA8IG4gKiAxLjUpIHtcbiAgICByZXR1cm4gTWF0aC5mbG9vcihtcyAvIG4pICsgJyAnICsgbmFtZTtcbiAgfVxuICByZXR1cm4gTWF0aC5jZWlsKG1zIC8gbikgKyAnICcgKyBuYW1lICsgJ3MnO1xufVxuIiwidm9pZCBmdW5jdGlvbihyb290KXtcblxuICBmdW5jdGlvbiBkZWZhdWx0cyhvcHRpb25zKXtcbiAgICB2YXIgb3B0aW9ucyA9IG9wdGlvbnMgfHwge31cbiAgICB2YXIgbWluID0gb3B0aW9ucy5taW5cbiAgICB2YXIgbWF4ID0gb3B0aW9ucy5tYXhcbiAgICB2YXIgaW50ZWdlciA9IG9wdGlvbnMuaW50ZWdlciB8fCBmYWxzZVxuICAgIGlmICggbWluID09IG51bGwgJiYgbWF4ID09IG51bGwgKSB7XG4gICAgICBtaW4gPSAwXG4gICAgICBtYXggPSAxXG4gICAgfSBlbHNlIGlmICggbWluID09IG51bGwgKSB7XG4gICAgICBtaW4gPSBtYXggLSAxXG4gICAgfSBlbHNlIGlmICggbWF4ID09IG51bGwgKSB7XG4gICAgICBtYXggPSBtaW4gKyAxXG4gICAgfVxuICAgIGlmICggbWF4IDwgbWluICkgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkIG9wdGlvbnMsIG1heCBtdXN0IGJlID49IG1pbicpXG4gICAgcmV0dXJuIHtcbiAgICAgIG1pbjogICAgIG1pblxuICAgICwgbWF4OiAgICAgbWF4XG4gICAgLCBpbnRlZ2VyOiBpbnRlZ2VyXG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gcmFuZG9tKG9wdGlvbnMpe1xuICAgIG9wdGlvbnMgPSBkZWZhdWx0cyhvcHRpb25zKVxuICAgIGlmICggb3B0aW9ucy5tYXggPT09IG9wdGlvbnMubWluICkgcmV0dXJuIG9wdGlvbnMubWluXG4gICAgdmFyIHIgPSBNYXRoLnJhbmRvbSgpICogKG9wdGlvbnMubWF4IC0gb3B0aW9ucy5taW4gKyBOdW1iZXIoISFvcHRpb25zLmludGVnZXIpKSArIG9wdGlvbnMubWluXG4gICAgcmV0dXJuIG9wdGlvbnMuaW50ZWdlciA/IE1hdGguZmxvb3IocikgOiByXG4gIH1cblxuICBmdW5jdGlvbiBnZW5lcmF0b3Iob3B0aW9ucyl7XG4gICAgb3B0aW9ucyA9IGRlZmF1bHRzKG9wdGlvbnMpXG4gICAgcmV0dXJuIGZ1bmN0aW9uKG1pbiwgbWF4LCBpbnRlZ2VyKXtcbiAgICAgIG9wdGlvbnMubWluICAgICA9IG1pbiAhPSBudWxsID8gbWluIDogb3B0aW9ucy5taW5cbiAgICAgIG9wdGlvbnMubWF4ICAgICA9IG1heCAhPSBudWxsID8gbWF4IDogb3B0aW9ucy5tYXhcbiAgICAgIG9wdGlvbnMuaW50ZWdlciA9IGludGVnZXIgIT0gbnVsbCA/IGludGVnZXIgOiBvcHRpb25zLmludGVnZXJcbiAgICAgIHJldHVybiByYW5kb20ob3B0aW9ucylcbiAgICB9XG4gIH1cblxuICBtb2R1bGUuZXhwb3J0cyA9ICByYW5kb21cbiAgbW9kdWxlLmV4cG9ydHMuZ2VuZXJhdG9yID0gZ2VuZXJhdG9yXG4gIG1vZHVsZS5leHBvcnRzLmRlZmF1bHRzID0gZGVmYXVsdHNcbn0odGhpcylcbiIsInZhciBncmFtbWFyID0gbW9kdWxlLmV4cG9ydHMgPSB7XG4gIHY6IFt7XG4gICAgbmFtZTogJ3ZlcnNpb24nLFxuICAgIHJlZzogL14oXFxkKikkL1xuICB9XSxcbiAgbzogW3sgLy9vPS0gMjA1MTggMCBJTiBJUDQgMjAzLjAuMTEzLjFcbiAgICAvLyBOQjogc2Vzc2lvbklkIHdpbGwgYmUgYSBTdHJpbmcgaW4gbW9zdCBjYXNlcyBiZWNhdXNlIGl0IGlzIGh1Z2VcbiAgICBuYW1lOiAnb3JpZ2luJyxcbiAgICByZWc6IC9eKFxcUyopIChcXGQqKSAoXFxkKikgKFxcUyopIElQKFxcZCkgKFxcUyopLyxcbiAgICBuYW1lczogWyd1c2VybmFtZScsICdzZXNzaW9uSWQnLCAnc2Vzc2lvblZlcnNpb24nLCAnbmV0VHlwZScsICdpcFZlcicsICdhZGRyZXNzJ10sXG4gICAgZm9ybWF0OiAnJXMgJXMgJWQgJXMgSVAlZCAlcydcbiAgfV0sXG4gIC8vIGRlZmF1bHQgcGFyc2luZyBvZiB0aGVzZSBvbmx5ICh0aG91Z2ggc29tZSBvZiB0aGVzZSBmZWVsIG91dGRhdGVkKVxuICBzOiBbeyBuYW1lOiAnbmFtZScgfV0sXG4gIGk6IFt7IG5hbWU6ICdkZXNjcmlwdGlvbicgfV0sXG4gIHU6IFt7IG5hbWU6ICd1cmknIH1dLFxuICBlOiBbeyBuYW1lOiAnZW1haWwnIH1dLFxuICBwOiBbeyBuYW1lOiAncGhvbmUnIH1dLFxuICB6OiBbeyBuYW1lOiAndGltZXpvbmVzJyB9XSwgLy8gVE9ETzogdGhpcyBvbmUgY2FuIGFjdHVhbGx5IGJlIHBhcnNlZCBwcm9wZXJseS4uXG4gIHI6IFt7IG5hbWU6ICdyZXBlYXRzJyB9XSwgICAvLyBUT0RPOiB0aGlzIG9uZSBjYW4gYWxzbyBiZSBwYXJzZWQgcHJvcGVybHlcbiAgLy9rOiBbe31dLCAvLyBvdXRkYXRlZCB0aGluZyBpZ25vcmVkXG4gIHQ6IFt7IC8vdD0wIDBcbiAgICBuYW1lOiAndGltaW5nJyxcbiAgICByZWc6IC9eKFxcZCopIChcXGQqKS8sXG4gICAgbmFtZXM6IFsnc3RhcnQnLCAnc3RvcCddLFxuICAgIGZvcm1hdDogJyVkICVkJ1xuICB9XSxcbiAgYzogW3sgLy9jPUlOIElQNCAxMC40Ny4xOTcuMjZcbiAgICBuYW1lOiAnY29ubmVjdGlvbicsXG4gICAgcmVnOiAvXklOIElQKFxcZCkgKFxcUyopLyxcbiAgICBuYW1lczogWyd2ZXJzaW9uJywgJ2lwJ10sXG4gICAgZm9ybWF0OiAnSU4gSVAlZCAlcydcbiAgfV0sXG4gIGI6IFt7IC8vYj1BUzo0MDAwXG4gICAgcHVzaDogJ2JhbmR3aWR0aCcsXG4gICAgcmVnOiAvXihUSUFTfEFTfENUfFJSfFJTKTooXFxkKikvLFxuICAgIG5hbWVzOiBbJ3R5cGUnLCAnbGltaXQnXSxcbiAgICBmb3JtYXQ6ICclczolcydcbiAgfV0sXG4gIG06IFt7IC8vbT12aWRlbyA1MTc0NCBSVFAvQVZQIDEyNiA5NyA5OCAzNCAzMVxuICAgIC8vIE5COiBzcGVjaWFsIC0gcHVzaGVzIHRvIHNlc3Npb25cbiAgICAvLyBUT0RPOiBydHAvZm10cCBzaG91bGQgYmUgZmlsdGVyZWQgYnkgdGhlIHBheWxvYWRzIGZvdW5kIGhlcmU/XG4gICAgcmVnOiAvXihcXHcqKSAoXFxkKikgKFtcXHdcXC9dKikoPzogKC4qKSk/LyxcbiAgICBuYW1lczogWyd0eXBlJywgJ3BvcnQnLCAncHJvdG9jb2wnLCAncGF5bG9hZHMnXSxcbiAgICBmb3JtYXQ6ICclcyAlZCAlcyAlcydcbiAgfV0sXG4gIGE6IFtcbiAgICB7IC8vYT1ydHBtYXA6MTEwIG9wdXMvNDgwMDAvMlxuICAgICAgcHVzaDogJ3J0cCcsXG4gICAgICByZWc6IC9ecnRwbWFwOihcXGQqKSAoW1xcd1xcLVxcLl0qKSg/OlxccypcXC8oXFxkKikoPzpcXHMqXFwvKFxcUyopKT8pPy8sXG4gICAgICBuYW1lczogWydwYXlsb2FkJywgJ2NvZGVjJywgJ3JhdGUnLCAnZW5jb2RpbmcnXSxcbiAgICAgIGZvcm1hdDogZnVuY3Rpb24gKG8pIHtcbiAgICAgICAgcmV0dXJuIChvLmVuY29kaW5nKSA/XG4gICAgICAgICAgJ3J0cG1hcDolZCAlcy8lcy8lcyc6XG4gICAgICAgICAgby5yYXRlID9cbiAgICAgICAgICAncnRwbWFwOiVkICVzLyVzJzpcbiAgICAgICAgICAncnRwbWFwOiVkICVzJztcbiAgICAgIH1cbiAgICB9LFxuICAgIHsgLy9hPWZtdHA6MTA4IHByb2ZpbGUtbGV2ZWwtaWQ9MjQ7b2JqZWN0PTIzO2JpdHJhdGU9NjQwMDBcbiAgICAgIC8vYT1mbXRwOjExMSBtaW5wdGltZT0xMDsgdXNlaW5iYW5kZmVjPTFcbiAgICAgIHB1c2g6ICdmbXRwJyxcbiAgICAgIHJlZzogL15mbXRwOihcXGQqKSAoW1xcU3wgXSopLyxcbiAgICAgIG5hbWVzOiBbJ3BheWxvYWQnLCAnY29uZmlnJ10sXG4gICAgICBmb3JtYXQ6ICdmbXRwOiVkICVzJ1xuICAgIH0sXG4gICAgeyAvL2E9Y29udHJvbDpzdHJlYW1pZD0wXG4gICAgICBuYW1lOiAnY29udHJvbCcsXG4gICAgICByZWc6IC9eY29udHJvbDooLiopLyxcbiAgICAgIGZvcm1hdDogJ2NvbnRyb2w6JXMnXG4gICAgfSxcbiAgICB7IC8vYT1ydGNwOjY1MTc5IElOIElQNCAxOTMuODQuNzcuMTk0XG4gICAgICBuYW1lOiAncnRjcCcsXG4gICAgICByZWc6IC9ecnRjcDooXFxkKikoPzogKFxcUyopIElQKFxcZCkgKFxcUyopKT8vLFxuICAgICAgbmFtZXM6IFsncG9ydCcsICduZXRUeXBlJywgJ2lwVmVyJywgJ2FkZHJlc3MnXSxcbiAgICAgIGZvcm1hdDogZnVuY3Rpb24gKG8pIHtcbiAgICAgICAgcmV0dXJuIChvLmFkZHJlc3MgIT0gbnVsbCkgP1xuICAgICAgICAgICdydGNwOiVkICVzIElQJWQgJXMnOlxuICAgICAgICAgICdydGNwOiVkJztcbiAgICAgIH1cbiAgICB9LFxuICAgIHsgLy9hPXJ0Y3AtZmI6OTggdHJyLWludCAxMDBcbiAgICAgIHB1c2g6ICdydGNwRmJUcnJJbnQnLFxuICAgICAgcmVnOiAvXnJ0Y3AtZmI6KFxcKnxcXGQqKSB0cnItaW50IChcXGQqKS8sXG4gICAgICBuYW1lczogWydwYXlsb2FkJywgJ3ZhbHVlJ10sXG4gICAgICBmb3JtYXQ6ICdydGNwLWZiOiVkIHRyci1pbnQgJWQnXG4gICAgfSxcbiAgICB7IC8vYT1ydGNwLWZiOjk4IG5hY2sgcnBzaVxuICAgICAgcHVzaDogJ3J0Y3BGYicsXG4gICAgICByZWc6IC9ecnRjcC1mYjooXFwqfFxcZCopIChbXFx3LV9dKikoPzogKFtcXHctX10qKSk/LyxcbiAgICAgIG5hbWVzOiBbJ3BheWxvYWQnLCAndHlwZScsICdzdWJ0eXBlJ10sXG4gICAgICBmb3JtYXQ6IGZ1bmN0aW9uIChvKSB7XG4gICAgICAgIHJldHVybiAoby5zdWJ0eXBlICE9IG51bGwpID9cbiAgICAgICAgICAncnRjcC1mYjolcyAlcyAlcyc6XG4gICAgICAgICAgJ3J0Y3AtZmI6JXMgJXMnO1xuICAgICAgfVxuICAgIH0sXG4gICAgeyAvL2E9ZXh0bWFwOjIgdXJuOmlldGY6cGFyYW1zOnJ0cC1oZHJleHQ6dG9mZnNldFxuICAgICAgLy9hPWV4dG1hcDoxL3JlY3Zvbmx5IFVSSS1ncHMtc3RyaW5nXG4gICAgICBwdXNoOiAnZXh0JyxcbiAgICAgIHJlZzogL15leHRtYXA6KFxcZCspKD86XFwvKFxcdyspKT8gKFxcUyopKD86IChcXFMqKSk/LyxcbiAgICAgIG5hbWVzOiBbJ3ZhbHVlJywgJ2RpcmVjdGlvbicsICd1cmknLCAnY29uZmlnJ10sXG4gICAgICBmb3JtYXQ6IGZ1bmN0aW9uIChvKSB7XG4gICAgICAgIHJldHVybiAnZXh0bWFwOiVkJyArIChvLmRpcmVjdGlvbiA/ICcvJXMnIDogJyV2JykgKyAnICVzJyArIChvLmNvbmZpZyA/ICcgJXMnIDogJycpO1xuICAgICAgfVxuICAgIH0sXG4gICAgeyAvL2E9Y3J5cHRvOjEgQUVTX0NNXzEyOF9ITUFDX1NIQTFfODAgaW5saW5lOlBTMXVRQ1ZlZUNGQ2FuVm1jamtwUHl3ak5XaGNZRDBtWFh0eGFWQlJ8Ml4yMHwxOjMyXG4gICAgICBwdXNoOiAnY3J5cHRvJyxcbiAgICAgIHJlZzogL15jcnlwdG86KFxcZCopIChbXFx3X10qKSAoXFxTKikoPzogKFxcUyopKT8vLFxuICAgICAgbmFtZXM6IFsnaWQnLCAnc3VpdGUnLCAnY29uZmlnJywgJ3Nlc3Npb25Db25maWcnXSxcbiAgICAgIGZvcm1hdDogZnVuY3Rpb24gKG8pIHtcbiAgICAgICAgcmV0dXJuIChvLnNlc3Npb25Db25maWcgIT0gbnVsbCkgP1xuICAgICAgICAgICdjcnlwdG86JWQgJXMgJXMgJXMnOlxuICAgICAgICAgICdjcnlwdG86JWQgJXMgJXMnO1xuICAgICAgfVxuICAgIH0sXG4gICAgeyAvL2E9c2V0dXA6YWN0cGFzc1xuICAgICAgbmFtZTogJ3NldHVwJyxcbiAgICAgIHJlZzogL15zZXR1cDooXFx3KikvLFxuICAgICAgZm9ybWF0OiAnc2V0dXA6JXMnXG4gICAgfSxcbiAgICB7IC8vYT1taWQ6MVxuICAgICAgbmFtZTogJ21pZCcsXG4gICAgICByZWc6IC9ebWlkOihbXlxcc10qKS8sXG4gICAgICBmb3JtYXQ6ICdtaWQ6JXMnXG4gICAgfSxcbiAgICB7IC8vYT1tc2lkOjBjOGIwNjRkLWQ4MDctNDNiNC1iNDM0LWY5MmE4ODlkODU4NyA5ODE3ODY4NS1kNDA5LTQ2ZTAtOGUxNi03ZWYwZGIwZGI2NGFcbiAgICAgIG5hbWU6ICdtc2lkJyxcbiAgICAgIHJlZzogL15tc2lkOiguKikvLFxuICAgICAgZm9ybWF0OiAnbXNpZDolcydcbiAgICB9LFxuICAgIHsgLy9hPXB0aW1lOjIwXG4gICAgICBuYW1lOiAncHRpbWUnLFxuICAgICAgcmVnOiAvXnB0aW1lOihcXGQqKS8sXG4gICAgICBmb3JtYXQ6ICdwdGltZTolZCdcbiAgICB9LFxuICAgIHsgLy9hPW1heHB0aW1lOjYwXG4gICAgICBuYW1lOiAnbWF4cHRpbWUnLFxuICAgICAgcmVnOiAvXm1heHB0aW1lOihcXGQqKS8sXG4gICAgICBmb3JtYXQ6ICdtYXhwdGltZTolZCdcbiAgICB9LFxuICAgIHsgLy9hPXNlbmRyZWN2XG4gICAgICBuYW1lOiAnZGlyZWN0aW9uJyxcbiAgICAgIHJlZzogL14oc2VuZHJlY3Z8cmVjdm9ubHl8c2VuZG9ubHl8aW5hY3RpdmUpL1xuICAgIH0sXG4gICAgeyAvL2E9aWNlLWxpdGVcbiAgICAgIG5hbWU6ICdpY2VsaXRlJyxcbiAgICAgIHJlZzogL14oaWNlLWxpdGUpL1xuICAgIH0sXG4gICAgeyAvL2E9aWNlLXVmcmFnOkY3Z0lcbiAgICAgIG5hbWU6ICdpY2VVZnJhZycsXG4gICAgICByZWc6IC9eaWNlLXVmcmFnOihcXFMqKS8sXG4gICAgICBmb3JtYXQ6ICdpY2UtdWZyYWc6JXMnXG4gICAgfSxcbiAgICB7IC8vYT1pY2UtcHdkOng5Y21sL1l6aWNoVjIrWGxoaU11OGdcbiAgICAgIG5hbWU6ICdpY2VQd2QnLFxuICAgICAgcmVnOiAvXmljZS1wd2Q6KFxcUyopLyxcbiAgICAgIGZvcm1hdDogJ2ljZS1wd2Q6JXMnXG4gICAgfSxcbiAgICB7IC8vYT1maW5nZXJwcmludDpTSEEtMSAwMDoxMToyMjozMzo0NDo1NTo2Njo3Nzo4ODo5OTpBQTpCQjpDQzpERDpFRTpGRjowMDoxMToyMjozM1xuICAgICAgbmFtZTogJ2ZpbmdlcnByaW50JyxcbiAgICAgIHJlZzogL15maW5nZXJwcmludDooXFxTKikgKFxcUyopLyxcbiAgICAgIG5hbWVzOiBbJ3R5cGUnLCAnaGFzaCddLFxuICAgICAgZm9ybWF0OiAnZmluZ2VycHJpbnQ6JXMgJXMnXG4gICAgfSxcbiAgICB7IC8vYT1jYW5kaWRhdGU6MCAxIFVEUCAyMTEzNjY3MzI3IDIwMy4wLjExMy4xIDU0NDAwIHR5cCBob3N0XG4gICAgICAvL2E9Y2FuZGlkYXRlOjExNjI4NzUwODEgMSB1ZHAgMjExMzkzNzE1MSAxOTIuMTY4LjM0Ljc1IDYwMDE3IHR5cCBob3N0IGdlbmVyYXRpb24gMCBuZXR3b3JrLWlkIDMgbmV0d29yay1jb3N0IDEwXG4gICAgICAvL2E9Y2FuZGlkYXRlOjMyODk5MTI5NTcgMiB1ZHAgMTg0NTUwMTY5NSAxOTMuODQuNzcuMTk0IDYwMDE3IHR5cCBzcmZseCByYWRkciAxOTIuMTY4LjM0Ljc1IHJwb3J0IDYwMDE3IGdlbmVyYXRpb24gMCBuZXR3b3JrLWlkIDMgbmV0d29yay1jb3N0IDEwXG4gICAgICAvL2E9Y2FuZGlkYXRlOjIyOTgxNTYyMCAxIHRjcCAxNTE4MjgwNDQ3IDE5Mi4xNjguMTUwLjE5IDYwMDE3IHR5cCBob3N0IHRjcHR5cGUgYWN0aXZlIGdlbmVyYXRpb24gMCBuZXR3b3JrLWlkIDMgbmV0d29yay1jb3N0IDEwXG4gICAgICAvL2E9Y2FuZGlkYXRlOjMyODk5MTI5NTcgMiB0Y3AgMTg0NTUwMTY5NSAxOTMuODQuNzcuMTk0IDYwMDE3IHR5cCBzcmZseCByYWRkciAxOTIuMTY4LjM0Ljc1IHJwb3J0IDYwMDE3IHRjcHR5cGUgcGFzc2l2ZSBnZW5lcmF0aW9uIDAgbmV0d29yay1pZCAzIG5ldHdvcmstY29zdCAxMFxuICAgICAgcHVzaDonY2FuZGlkYXRlcycsXG4gICAgICByZWc6IC9eY2FuZGlkYXRlOihcXFMqKSAoXFxkKikgKFxcUyopIChcXGQqKSAoXFxTKikgKFxcZCopIHR5cCAoXFxTKikoPzogcmFkZHIgKFxcUyopIHJwb3J0IChcXGQqKSk/KD86IHRjcHR5cGUgKFxcUyopKT8oPzogZ2VuZXJhdGlvbiAoXFxkKikpPyg/OiBuZXR3b3JrLWlkIChcXGQqKSk/KD86IG5ldHdvcmstY29zdCAoXFxkKikpPy8sXG4gICAgICBuYW1lczogWydmb3VuZGF0aW9uJywgJ2NvbXBvbmVudCcsICd0cmFuc3BvcnQnLCAncHJpb3JpdHknLCAnaXAnLCAncG9ydCcsICd0eXBlJywgJ3JhZGRyJywgJ3Jwb3J0JywgJ3RjcHR5cGUnLCAnZ2VuZXJhdGlvbicsICduZXR3b3JrLWlkJywgJ25ldHdvcmstY29zdCddLFxuICAgICAgZm9ybWF0OiBmdW5jdGlvbiAobykge1xuICAgICAgICB2YXIgc3RyID0gJ2NhbmRpZGF0ZTolcyAlZCAlcyAlZCAlcyAlZCB0eXAgJXMnO1xuXG4gICAgICAgIHN0ciArPSAoby5yYWRkciAhPSBudWxsKSA/ICcgcmFkZHIgJXMgcnBvcnQgJWQnIDogJyV2JXYnO1xuXG4gICAgICAgIC8vIE5COiBjYW5kaWRhdGUgaGFzIHRocmVlIG9wdGlvbmFsIGNodW5rcywgc28gJXZvaWQgbWlkZGxlcyBvbmUgaWYgaXQncyBtaXNzaW5nXG4gICAgICAgIHN0ciArPSAoby50Y3B0eXBlICE9IG51bGwpID8gJyB0Y3B0eXBlICVzJyA6ICcldic7XG5cbiAgICAgICAgaWYgKG8uZ2VuZXJhdGlvbiAhPSBudWxsKSB7XG4gICAgICAgICAgc3RyICs9ICcgZ2VuZXJhdGlvbiAlZCc7XG4gICAgICAgIH1cblxuICAgICAgICBzdHIgKz0gKG9bJ25ldHdvcmstaWQnXSAhPSBudWxsKSA/ICcgbmV0d29yay1pZCAlZCcgOiAnJXYnO1xuICAgICAgICBzdHIgKz0gKG9bJ25ldHdvcmstY29zdCddICE9IG51bGwpID8gJyBuZXR3b3JrLWNvc3QgJWQnIDogJyV2JztcbiAgICAgICAgcmV0dXJuIHN0cjtcbiAgICAgIH1cbiAgICB9LFxuICAgIHsgLy9hPWVuZC1vZi1jYW5kaWRhdGVzIChrZWVwIGFmdGVyIHRoZSBjYW5kaWRhdGVzIGxpbmUgZm9yIHJlYWRhYmlsaXR5KVxuICAgICAgbmFtZTogJ2VuZE9mQ2FuZGlkYXRlcycsXG4gICAgICByZWc6IC9eKGVuZC1vZi1jYW5kaWRhdGVzKS9cbiAgICB9LFxuICAgIHsgLy9hPXJlbW90ZS1jYW5kaWRhdGVzOjEgMjAzLjAuMTEzLjEgNTQ0MDAgMiAyMDMuMC4xMTMuMSA1NDQwMSAuLi5cbiAgICAgIG5hbWU6ICdyZW1vdGVDYW5kaWRhdGVzJyxcbiAgICAgIHJlZzogL15yZW1vdGUtY2FuZGlkYXRlczooLiopLyxcbiAgICAgIGZvcm1hdDogJ3JlbW90ZS1jYW5kaWRhdGVzOiVzJ1xuICAgIH0sXG4gICAgeyAvL2E9aWNlLW9wdGlvbnM6Z29vZ2xlLWljZVxuICAgICAgbmFtZTogJ2ljZU9wdGlvbnMnLFxuICAgICAgcmVnOiAvXmljZS1vcHRpb25zOihcXFMqKS8sXG4gICAgICBmb3JtYXQ6ICdpY2Utb3B0aW9uczolcydcbiAgICB9LFxuICAgIHsgLy9hPXNzcmM6MjU2NjEwNzU2OSBjbmFtZTp0OVlVOE0xVXhURjhZMUExXG4gICAgICBwdXNoOiAnc3NyY3MnLFxuICAgICAgcmVnOiAvXnNzcmM6KFxcZCopIChbXFx3X10qKSg/OjooLiopKT8vLFxuICAgICAgbmFtZXM6IFsnaWQnLCAnYXR0cmlidXRlJywgJ3ZhbHVlJ10sXG4gICAgICBmb3JtYXQ6IGZ1bmN0aW9uIChvKSB7XG4gICAgICAgIHZhciBzdHIgPSAnc3NyYzolZCc7XG4gICAgICAgIGlmIChvLmF0dHJpYnV0ZSAhPSBudWxsKSB7XG4gICAgICAgICAgc3RyICs9ICcgJXMnO1xuICAgICAgICAgIGlmIChvLnZhbHVlICE9IG51bGwpIHtcbiAgICAgICAgICAgIHN0ciArPSAnOiVzJztcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHN0cjtcbiAgICAgIH1cbiAgICB9LFxuICAgIHsgLy9hPXNzcmMtZ3JvdXA6RkVDIDEgMlxuICAgICAgLy9hPXNzcmMtZ3JvdXA6RkVDLUZSIDMwMDQzNjQxOTUgMTA4MDc3MjI0MVxuICAgICAgcHVzaDogJ3NzcmNHcm91cHMnLFxuICAgICAgLy8gdG9rZW4tY2hhciA9ICV4MjEgLyAleDIzLTI3IC8gJXgyQS0yQiAvICV4MkQtMkUgLyAleDMwLTM5IC8gJXg0MS01QSAvICV4NUUtN0VcbiAgICAgIHJlZzogL15zc3JjLWdyb3VwOihbXFx4MjFcXHgyM1xceDI0XFx4MjVcXHgyNlxceDI3XFx4MkFcXHgyQlxceDJEXFx4MkVcXHddKikgKC4qKS8sXG4gICAgICBuYW1lczogWydzZW1hbnRpY3MnLCAnc3NyY3MnXSxcbiAgICAgIGZvcm1hdDogJ3NzcmMtZ3JvdXA6JXMgJXMnXG4gICAgfSxcbiAgICB7IC8vYT1tc2lkLXNlbWFudGljOiBXTVMgSnZsYW01WDNTWDFPUDZwbjIweldvZ3ZhS0p6NUhqZjlPbmxWXG4gICAgICBuYW1lOiAnbXNpZFNlbWFudGljJyxcbiAgICAgIHJlZzogL15tc2lkLXNlbWFudGljOlxccz8oXFx3KikgKFxcUyopLyxcbiAgICAgIG5hbWVzOiBbJ3NlbWFudGljJywgJ3Rva2VuJ10sXG4gICAgICBmb3JtYXQ6ICdtc2lkLXNlbWFudGljOiAlcyAlcycgLy8gc3BhY2UgYWZ0ZXIgJzonIGlzIG5vdCBhY2NpZGVudGFsXG4gICAgfSxcbiAgICB7IC8vYT1ncm91cDpCVU5ETEUgYXVkaW8gdmlkZW9cbiAgICAgIHB1c2g6ICdncm91cHMnLFxuICAgICAgcmVnOiAvXmdyb3VwOihcXHcqKSAoLiopLyxcbiAgICAgIG5hbWVzOiBbJ3R5cGUnLCAnbWlkcyddLFxuICAgICAgZm9ybWF0OiAnZ3JvdXA6JXMgJXMnXG4gICAgfSxcbiAgICB7IC8vYT1ydGNwLW11eFxuICAgICAgbmFtZTogJ3J0Y3BNdXgnLFxuICAgICAgcmVnOiAvXihydGNwLW11eCkvXG4gICAgfSxcbiAgICB7IC8vYT1ydGNwLXJzaXplXG4gICAgICBuYW1lOiAncnRjcFJzaXplJyxcbiAgICAgIHJlZzogL14ocnRjcC1yc2l6ZSkvXG4gICAgfSxcbiAgICB7IC8vYT1zY3RwbWFwOjUwMDAgd2VicnRjLWRhdGFjaGFubmVsIDEwMjRcbiAgICAgIG5hbWU6ICdzY3RwbWFwJyxcbiAgICAgIHJlZzogL15zY3RwbWFwOihbXFx3X1xcL10qKSAoXFxTKikoPzogKFxcUyopKT8vLFxuICAgICAgbmFtZXM6IFsnc2N0cG1hcE51bWJlcicsICdhcHAnLCAnbWF4TWVzc2FnZVNpemUnXSxcbiAgICAgIGZvcm1hdDogZnVuY3Rpb24gKG8pIHtcbiAgICAgICAgcmV0dXJuIChvLm1heE1lc3NhZ2VTaXplICE9IG51bGwpID9cbiAgICAgICAgICAnc2N0cG1hcDolcyAlcyAlcycgOlxuICAgICAgICAgICdzY3RwbWFwOiVzICVzJztcbiAgICAgIH1cbiAgICB9LFxuICAgIHsgLy9hPXgtZ29vZ2xlLWZsYWc6Y29uZmVyZW5jZVxuICAgICAgbmFtZTogJ3hHb29nbGVGbGFnJyxcbiAgICAgIHJlZzogL154LWdvb2dsZS1mbGFnOihbXlxcc10qKS8sXG4gICAgICBmb3JtYXQ6ICd4LWdvb2dsZS1mbGFnOiVzJ1xuICAgIH0sXG4gICAgeyAvL2E9cmlkOjEgc2VuZCBtYXgtd2lkdGg9MTI4MDttYXgtaGVpZ2h0PTcyMDttYXgtZnBzPTMwO2RlcGVuZD0wXG4gICAgICBwdXNoOiAncmlkcycsXG4gICAgICByZWc6IC9ecmlkOihbXFxkXFx3XSspIChcXHcrKSg/OiAoW1xcU3wgXSopKT8vLFxuICAgICAgbmFtZXM6IFsnaWQnLCAnZGlyZWN0aW9uJywgJ3BhcmFtcyddLFxuICAgICAgZm9ybWF0OiBmdW5jdGlvbiAobykge1xuICAgICAgICByZXR1cm4gKG8ucGFyYW1zKSA/ICdyaWQ6JXMgJXMgJXMnIDogJ3JpZDolcyAlcyc7XG4gICAgICB9XG4gICAgfSxcbiAgICB7IC8vYT1pbWFnZWF0dHI6OTcgc2VuZCBbeD04MDAseT02NDAsc2FyPTEuMSxxPTAuNl0gW3g9NDgwLHk9MzIwXSByZWN2IFt4PTMzMCx5PTI1MF1cbiAgICAgIC8vYT1pbWFnZWF0dHI6KiBzZW5kIFt4PTgwMCx5PTY0MF0gcmVjdiAqXG4gICAgICAvL2E9aW1hZ2VhdHRyOjEwMCByZWN2IFt4PTMyMCx5PTI0MF1cbiAgICAgIHB1c2g6ICdpbWFnZWF0dHJzJyxcbiAgICAgIHJlZzogbmV3IFJlZ0V4cChcbiAgICAgICAgLy9hPWltYWdlYXR0cjo5N1xuICAgICAgICAnXmltYWdlYXR0cjooXFxcXGQrfFxcXFwqKScgK1xuICAgICAgICAvL3NlbmQgW3g9ODAwLHk9NjQwLHNhcj0xLjEscT0wLjZdIFt4PTQ4MCx5PTMyMF1cbiAgICAgICAgJ1tcXFxcc1xcXFx0XSsoc2VuZHxyZWN2KVtcXFxcc1xcXFx0XSsoXFxcXCp8XFxcXFtcXFxcUytcXFxcXSg/OltcXFxcc1xcXFx0XStcXFxcW1xcXFxTK1xcXFxdKSopJyArXG4gICAgICAgIC8vcmVjdiBbeD0zMzAseT0yNTBdXG4gICAgICAgICcoPzpbXFxcXHNcXFxcdF0rKHJlY3Z8c2VuZClbXFxcXHNcXFxcdF0rKFxcXFwqfFxcXFxbXFxcXFMrXFxcXF0oPzpbXFxcXHNcXFxcdF0rXFxcXFtcXFxcUytcXFxcXSkqKSk/J1xuICAgICAgKSxcbiAgICAgIG5hbWVzOiBbJ3B0JywgJ2RpcjEnLCAnYXR0cnMxJywgJ2RpcjInLCAnYXR0cnMyJ10sXG4gICAgICBmb3JtYXQ6IGZ1bmN0aW9uIChvKSB7XG4gICAgICAgIHJldHVybiAnaW1hZ2VhdHRyOiVzICVzICVzJyArIChvLmRpcjIgPyAnICVzICVzJyA6ICcnKTtcbiAgICAgIH1cbiAgICB9LFxuICAgIHsgLy9hPXNpbXVsY2FzdDpzZW5kIDEsMiwzO340LH41IHJlY3YgNjt+Nyx+OFxuICAgICAgLy9hPXNpbXVsY2FzdDpyZWN2IDE7NCw1IHNlbmQgNjs3XG4gICAgICBuYW1lOiAnc2ltdWxjYXN0JyxcbiAgICAgIHJlZzogbmV3IFJlZ0V4cChcbiAgICAgICAgLy9hPXNpbXVsY2FzdDpcbiAgICAgICAgJ15zaW11bGNhc3Q6JyArXG4gICAgICAgIC8vc2VuZCAxLDIsMzt+NCx+NVxuICAgICAgICAnKHNlbmR8cmVjdikgKFthLXpBLVowLTlcXFxcLV9+OyxdKyknICtcbiAgICAgICAgLy9zcGFjZSArIHJlY3YgNjt+Nyx+OFxuICAgICAgICAnKD86XFxcXHM/KHNlbmR8cmVjdikgKFthLXpBLVowLTlcXFxcLV9+OyxdKykpPycgK1xuICAgICAgICAvL2VuZFxuICAgICAgICAnJCdcbiAgICAgICksXG4gICAgICBuYW1lczogWydkaXIxJywgJ2xpc3QxJywgJ2RpcjInLCAnbGlzdDInXSxcbiAgICAgIGZvcm1hdDogZnVuY3Rpb24gKG8pIHtcbiAgICAgICAgcmV0dXJuICdzaW11bGNhc3Q6JXMgJXMnICsgKG8uZGlyMiA/ICcgJXMgJXMnIDogJycpO1xuICAgICAgfVxuICAgIH0sXG4gICAgeyAvL09sZCBzaW11bGNhc3QgZHJhZnQgMDMgKGltcGxlbWVudGVkIGJ5IEZpcmVmb3gpXG4gICAgICAvLyAgaHR0cHM6Ly90b29scy5pZXRmLm9yZy9odG1sL2RyYWZ0LWlldGYtbW11c2ljLXNkcC1zaW11bGNhc3QtMDNcbiAgICAgIC8vYT1zaW11bGNhc3Q6IHJlY3YgcHQ9OTc7OTggc2VuZCBwdD05N1xuICAgICAgLy9hPXNpbXVsY2FzdDogc2VuZCByaWQ9NTs2OzcgcGF1c2VkPTYsN1xuICAgICAgbmFtZTogJ3NpbXVsY2FzdF8wMycsXG4gICAgICByZWc6IC9ec2ltdWxjYXN0OltcXHNcXHRdKyhbXFxTK1xcc1xcdF0rKSQvLFxuICAgICAgbmFtZXM6IFsndmFsdWUnXSxcbiAgICAgIGZvcm1hdDogJ3NpbXVsY2FzdDogJXMnXG4gICAgfSxcbiAgICB7XG4gICAgICAvL2E9ZnJhbWVyYXRlOjI1XG4gICAgICAvL2E9ZnJhbWVyYXRlOjI5Ljk3XG4gICAgICBuYW1lOiAnZnJhbWVyYXRlJyxcbiAgICAgIHJlZzogL15mcmFtZXJhdGU6KFxcZCsoPzokfFxcLlxcZCspKS8sXG4gICAgICBmb3JtYXQ6ICdmcmFtZXJhdGU6JXMnXG4gICAgfSxcbiAgICB7IC8vIGFueSBhPSB0aGF0IHdlIGRvbid0IHVuZGVyc3RhbmQgaXMga2VwdHMgdmVyYmF0aW0gb24gbWVkaWEuaW52YWxpZFxuICAgICAgcHVzaDogJ2ludmFsaWQnLFxuICAgICAgbmFtZXM6IFsndmFsdWUnXVxuICAgIH1cbiAgXVxufTtcblxuLy8gc2V0IHNlbnNpYmxlIGRlZmF1bHRzIHRvIGF2b2lkIHBvbGx1dGluZyB0aGUgZ3JhbW1hciB3aXRoIGJvcmluZyBkZXRhaWxzXG5PYmplY3Qua2V5cyhncmFtbWFyKS5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHtcbiAgdmFyIG9ianMgPSBncmFtbWFyW2tleV07XG4gIG9ianMuZm9yRWFjaChmdW5jdGlvbiAob2JqKSB7XG4gICAgaWYgKCFvYmoucmVnKSB7XG4gICAgICBvYmoucmVnID0gLyguKikvO1xuICAgIH1cbiAgICBpZiAoIW9iai5mb3JtYXQpIHtcbiAgICAgIG9iai5mb3JtYXQgPSAnJXMnO1xuICAgIH1cbiAgfSk7XG59KTtcbiIsInZhciBwYXJzZXIgPSByZXF1aXJlKCcuL3BhcnNlcicpO1xudmFyIHdyaXRlciA9IHJlcXVpcmUoJy4vd3JpdGVyJyk7XG5cbmV4cG9ydHMud3JpdGUgPSB3cml0ZXI7XG5leHBvcnRzLnBhcnNlID0gcGFyc2VyLnBhcnNlO1xuZXhwb3J0cy5wYXJzZUZtdHBDb25maWcgPSBwYXJzZXIucGFyc2VGbXRwQ29uZmlnO1xuZXhwb3J0cy5wYXJzZVBhcmFtcyA9IHBhcnNlci5wYXJzZVBhcmFtcztcbmV4cG9ydHMucGFyc2VQYXlsb2FkcyA9IHBhcnNlci5wYXJzZVBheWxvYWRzO1xuZXhwb3J0cy5wYXJzZVJlbW90ZUNhbmRpZGF0ZXMgPSBwYXJzZXIucGFyc2VSZW1vdGVDYW5kaWRhdGVzO1xuZXhwb3J0cy5wYXJzZUltYWdlQXR0cmlidXRlcyA9IHBhcnNlci5wYXJzZUltYWdlQXR0cmlidXRlcztcbmV4cG9ydHMucGFyc2VTaW11bGNhc3RTdHJlYW1MaXN0ID0gcGFyc2VyLnBhcnNlU2ltdWxjYXN0U3RyZWFtTGlzdDtcbiIsInZhciB0b0ludElmSW50ID0gZnVuY3Rpb24gKHYpIHtcbiAgcmV0dXJuIFN0cmluZyhOdW1iZXIodikpID09PSB2ID8gTnVtYmVyKHYpIDogdjtcbn07XG5cbnZhciBhdHRhY2hQcm9wZXJ0aWVzID0gZnVuY3Rpb24gKG1hdGNoLCBsb2NhdGlvbiwgbmFtZXMsIHJhd05hbWUpIHtcbiAgaWYgKHJhd05hbWUgJiYgIW5hbWVzKSB7XG4gICAgbG9jYXRpb25bcmF3TmFtZV0gPSB0b0ludElmSW50KG1hdGNoWzFdKTtcbiAgfVxuICBlbHNlIHtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IG5hbWVzLmxlbmd0aDsgaSArPSAxKSB7XG4gICAgICBpZiAobWF0Y2hbaSsxXSAhPSBudWxsKSB7XG4gICAgICAgIGxvY2F0aW9uW25hbWVzW2ldXSA9IHRvSW50SWZJbnQobWF0Y2hbaSsxXSk7XG4gICAgICB9XG4gICAgfVxuICB9XG59O1xuXG52YXIgcGFyc2VSZWcgPSBmdW5jdGlvbiAob2JqLCBsb2NhdGlvbiwgY29udGVudCkge1xuICB2YXIgbmVlZHNCbGFuayA9IG9iai5uYW1lICYmIG9iai5uYW1lcztcbiAgaWYgKG9iai5wdXNoICYmICFsb2NhdGlvbltvYmoucHVzaF0pIHtcbiAgICBsb2NhdGlvbltvYmoucHVzaF0gPSBbXTtcbiAgfVxuICBlbHNlIGlmIChuZWVkc0JsYW5rICYmICFsb2NhdGlvbltvYmoubmFtZV0pIHtcbiAgICBsb2NhdGlvbltvYmoubmFtZV0gPSB7fTtcbiAgfVxuICB2YXIga2V5TG9jYXRpb24gPSBvYmoucHVzaCA/XG4gICAge30gOiAgLy8gYmxhbmsgb2JqZWN0IHRoYXQgd2lsbCBiZSBwdXNoZWRcbiAgICBuZWVkc0JsYW5rID8gbG9jYXRpb25bb2JqLm5hbWVdIDogbG9jYXRpb247IC8vIG90aGVyd2lzZSwgbmFtZWQgbG9jYXRpb24gb3Igcm9vdFxuXG4gIGF0dGFjaFByb3BlcnRpZXMoY29udGVudC5tYXRjaChvYmoucmVnKSwga2V5TG9jYXRpb24sIG9iai5uYW1lcywgb2JqLm5hbWUpO1xuXG4gIGlmIChvYmoucHVzaCkge1xuICAgIGxvY2F0aW9uW29iai5wdXNoXS5wdXNoKGtleUxvY2F0aW9uKTtcbiAgfVxufTtcblxudmFyIGdyYW1tYXIgPSByZXF1aXJlKCcuL2dyYW1tYXInKTtcbnZhciB2YWxpZExpbmUgPSBSZWdFeHAucHJvdG90eXBlLnRlc3QuYmluZCgvXihbYS16XSk9KC4qKS8pO1xuXG5leHBvcnRzLnBhcnNlID0gZnVuY3Rpb24gKHNkcCkge1xuICB2YXIgc2Vzc2lvbiA9IHt9XG4gICAgLCBtZWRpYSA9IFtdXG4gICAgLCBsb2NhdGlvbiA9IHNlc3Npb247IC8vIHBvaW50cyBhdCB3aGVyZSBwcm9wZXJ0aWVzIGdvIHVuZGVyIChvbmUgb2YgdGhlIGFib3ZlKVxuXG4gIC8vIHBhcnNlIGxpbmVzIHdlIHVuZGVyc3RhbmRcbiAgc2RwLnNwbGl0KC8oXFxyXFxufFxccnxcXG4pLykuZmlsdGVyKHZhbGlkTGluZSkuZm9yRWFjaChmdW5jdGlvbiAobCkge1xuICAgIHZhciB0eXBlID0gbFswXTtcbiAgICB2YXIgY29udGVudCA9IGwuc2xpY2UoMik7XG4gICAgaWYgKHR5cGUgPT09ICdtJykge1xuICAgICAgbWVkaWEucHVzaCh7cnRwOiBbXSwgZm10cDogW119KTtcbiAgICAgIGxvY2F0aW9uID0gbWVkaWFbbWVkaWEubGVuZ3RoLTFdOyAvLyBwb2ludCBhdCBsYXRlc3QgbWVkaWEgbGluZVxuICAgIH1cblxuICAgIGZvciAodmFyIGogPSAwOyBqIDwgKGdyYW1tYXJbdHlwZV0gfHwgW10pLmxlbmd0aDsgaiArPSAxKSB7XG4gICAgICB2YXIgb2JqID0gZ3JhbW1hclt0eXBlXVtqXTtcbiAgICAgIGlmIChvYmoucmVnLnRlc3QoY29udGVudCkpIHtcbiAgICAgICAgcmV0dXJuIHBhcnNlUmVnKG9iaiwgbG9jYXRpb24sIGNvbnRlbnQpO1xuICAgICAgfVxuICAgIH1cbiAgfSk7XG5cbiAgc2Vzc2lvbi5tZWRpYSA9IG1lZGlhOyAvLyBsaW5rIGl0IHVwXG4gIHJldHVybiBzZXNzaW9uO1xufTtcblxudmFyIHBhcmFtUmVkdWNlciA9IGZ1bmN0aW9uIChhY2MsIGV4cHIpIHtcbiAgdmFyIHMgPSBleHByLnNwbGl0KC89KC4rKS8sIDIpO1xuICBpZiAocy5sZW5ndGggPT09IDIpIHtcbiAgICBhY2Nbc1swXV0gPSB0b0ludElmSW50KHNbMV0pO1xuICB9XG4gIHJldHVybiBhY2M7XG59O1xuXG5leHBvcnRzLnBhcnNlUGFyYW1zID0gZnVuY3Rpb24gKHN0cikge1xuICByZXR1cm4gc3RyLnNwbGl0KC9cXDtcXHM/LykucmVkdWNlKHBhcmFtUmVkdWNlciwge30pO1xufTtcblxuLy8gRm9yIGJhY2t3YXJkIGNvbXBhdGliaWxpdHkgLSBhbGlhcyB3aWxsIGJlIHJlbW92ZWQgaW4gMy4wLjBcbmV4cG9ydHMucGFyc2VGbXRwQ29uZmlnID0gZXhwb3J0cy5wYXJzZVBhcmFtcztcblxuZXhwb3J0cy5wYXJzZVBheWxvYWRzID0gZnVuY3Rpb24gKHN0cikge1xuICByZXR1cm4gc3RyLnNwbGl0KCcgJykubWFwKE51bWJlcik7XG59O1xuXG5leHBvcnRzLnBhcnNlUmVtb3RlQ2FuZGlkYXRlcyA9IGZ1bmN0aW9uIChzdHIpIHtcbiAgdmFyIGNhbmRpZGF0ZXMgPSBbXTtcbiAgdmFyIHBhcnRzID0gc3RyLnNwbGl0KCcgJykubWFwKHRvSW50SWZJbnQpO1xuICBmb3IgKHZhciBpID0gMDsgaSA8IHBhcnRzLmxlbmd0aDsgaSArPSAzKSB7XG4gICAgY2FuZGlkYXRlcy5wdXNoKHtcbiAgICAgIGNvbXBvbmVudDogcGFydHNbaV0sXG4gICAgICBpcDogcGFydHNbaSArIDFdLFxuICAgICAgcG9ydDogcGFydHNbaSArIDJdXG4gICAgfSk7XG4gIH1cbiAgcmV0dXJuIGNhbmRpZGF0ZXM7XG59O1xuXG5leHBvcnRzLnBhcnNlSW1hZ2VBdHRyaWJ1dGVzID0gZnVuY3Rpb24gKHN0cikge1xuICByZXR1cm4gc3RyLnNwbGl0KCcgJykubWFwKGZ1bmN0aW9uIChpdGVtKSB7XG4gICAgcmV0dXJuIGl0ZW0uc3Vic3RyaW5nKDEsIGl0ZW0ubGVuZ3RoLTEpLnNwbGl0KCcsJykucmVkdWNlKHBhcmFtUmVkdWNlciwge30pO1xuICB9KTtcbn07XG5cbmV4cG9ydHMucGFyc2VTaW11bGNhc3RTdHJlYW1MaXN0ID0gZnVuY3Rpb24gKHN0cikge1xuICByZXR1cm4gc3RyLnNwbGl0KCc7JykubWFwKGZ1bmN0aW9uIChzdHJlYW0pIHtcbiAgICByZXR1cm4gc3RyZWFtLnNwbGl0KCcsJykubWFwKGZ1bmN0aW9uIChmb3JtYXQpIHtcbiAgICAgIHZhciBzY2lkLCBwYXVzZWQgPSBmYWxzZTtcblxuICAgICAgaWYgKGZvcm1hdFswXSAhPT0gJ34nKSB7XG4gICAgICAgIHNjaWQgPSB0b0ludElmSW50KGZvcm1hdCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzY2lkID0gdG9JbnRJZkludChmb3JtYXQuc3Vic3RyaW5nKDEsIGZvcm1hdC5sZW5ndGgpKTtcbiAgICAgICAgcGF1c2VkID0gdHJ1ZTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgc2NpZDogc2NpZCxcbiAgICAgICAgcGF1c2VkOiBwYXVzZWRcbiAgICAgIH07XG4gICAgfSk7XG4gIH0pO1xufTtcbiIsInZhciBncmFtbWFyID0gcmVxdWlyZSgnLi9ncmFtbWFyJyk7XG5cbi8vIGN1c3RvbWl6ZWQgdXRpbC5mb3JtYXQgLSBkaXNjYXJkcyBleGNlc3MgYXJndW1lbnRzIGFuZCBjYW4gdm9pZCBtaWRkbGUgb25lc1xudmFyIGZvcm1hdFJlZ0V4cCA9IC8lW3NkdiVdL2c7XG52YXIgZm9ybWF0ID0gZnVuY3Rpb24gKGZvcm1hdFN0cikge1xuICB2YXIgaSA9IDE7XG4gIHZhciBhcmdzID0gYXJndW1lbnRzO1xuICB2YXIgbGVuID0gYXJncy5sZW5ndGg7XG4gIHJldHVybiBmb3JtYXRTdHIucmVwbGFjZShmb3JtYXRSZWdFeHAsIGZ1bmN0aW9uICh4KSB7XG4gICAgaWYgKGkgPj0gbGVuKSB7XG4gICAgICByZXR1cm4geDsgLy8gbWlzc2luZyBhcmd1bWVudFxuICAgIH1cbiAgICB2YXIgYXJnID0gYXJnc1tpXTtcbiAgICBpICs9IDE7XG4gICAgc3dpdGNoICh4KSB7XG4gICAgY2FzZSAnJSUnOlxuICAgICAgcmV0dXJuICclJztcbiAgICBjYXNlICclcyc6XG4gICAgICByZXR1cm4gU3RyaW5nKGFyZyk7XG4gICAgY2FzZSAnJWQnOlxuICAgICAgcmV0dXJuIE51bWJlcihhcmcpO1xuICAgIGNhc2UgJyV2JzpcbiAgICAgIHJldHVybiAnJztcbiAgICB9XG4gIH0pO1xuICAvLyBOQjogd2UgZGlzY2FyZCBleGNlc3MgYXJndW1lbnRzIC0gdGhleSBhcmUgdHlwaWNhbGx5IHVuZGVmaW5lZCBmcm9tIG1ha2VMaW5lXG59O1xuXG52YXIgbWFrZUxpbmUgPSBmdW5jdGlvbiAodHlwZSwgb2JqLCBsb2NhdGlvbikge1xuICB2YXIgc3RyID0gb2JqLmZvcm1hdCBpbnN0YW5jZW9mIEZ1bmN0aW9uID9cbiAgICAob2JqLmZvcm1hdChvYmoucHVzaCA/IGxvY2F0aW9uIDogbG9jYXRpb25bb2JqLm5hbWVdKSkgOlxuICAgIG9iai5mb3JtYXQ7XG5cbiAgdmFyIGFyZ3MgPSBbdHlwZSArICc9JyArIHN0cl07XG4gIGlmIChvYmoubmFtZXMpIHtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IG9iai5uYW1lcy5sZW5ndGg7IGkgKz0gMSkge1xuICAgICAgdmFyIG4gPSBvYmoubmFtZXNbaV07XG4gICAgICBpZiAob2JqLm5hbWUpIHtcbiAgICAgICAgYXJncy5wdXNoKGxvY2F0aW9uW29iai5uYW1lXVtuXSk7XG4gICAgICB9XG4gICAgICBlbHNlIHsgLy8gZm9yIG1MaW5lIGFuZCBwdXNoIGF0dHJpYnV0ZXNcbiAgICAgICAgYXJncy5wdXNoKGxvY2F0aW9uW29iai5uYW1lc1tpXV0pO1xuICAgICAgfVxuICAgIH1cbiAgfVxuICBlbHNlIHtcbiAgICBhcmdzLnB1c2gobG9jYXRpb25bb2JqLm5hbWVdKTtcbiAgfVxuICByZXR1cm4gZm9ybWF0LmFwcGx5KG51bGwsIGFyZ3MpO1xufTtcblxuLy8gUkZDIHNwZWNpZmllZCBvcmRlclxuLy8gVE9ETzogZXh0ZW5kIHRoaXMgd2l0aCBhbGwgdGhlIHJlc3RcbnZhciBkZWZhdWx0T3V0ZXJPcmRlciA9IFtcbiAgJ3YnLCAnbycsICdzJywgJ2knLFxuICAndScsICdlJywgJ3AnLCAnYycsXG4gICdiJywgJ3QnLCAncicsICd6JywgJ2EnXG5dO1xudmFyIGRlZmF1bHRJbm5lck9yZGVyID0gWydpJywgJ2MnLCAnYicsICdhJ107XG5cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoc2Vzc2lvbiwgb3B0cykge1xuICBvcHRzID0gb3B0cyB8fCB7fTtcbiAgLy8gZW5zdXJlIGNlcnRhaW4gcHJvcGVydGllcyBleGlzdFxuICBpZiAoc2Vzc2lvbi52ZXJzaW9uID09IG51bGwpIHtcbiAgICBzZXNzaW9uLnZlcnNpb24gPSAwOyAvLyAndj0wJyBtdXN0IGJlIHRoZXJlIChvbmx5IGRlZmluZWQgdmVyc2lvbiBhdG0pXG4gIH1cbiAgaWYgKHNlc3Npb24ubmFtZSA9PSBudWxsKSB7XG4gICAgc2Vzc2lvbi5uYW1lID0gJyAnOyAvLyAncz0gJyBtdXN0IGJlIHRoZXJlIGlmIG5vIG1lYW5pbmdmdWwgbmFtZSBzZXRcbiAgfVxuICBzZXNzaW9uLm1lZGlhLmZvckVhY2goZnVuY3Rpb24gKG1MaW5lKSB7XG4gICAgaWYgKG1MaW5lLnBheWxvYWRzID09IG51bGwpIHtcbiAgICAgIG1MaW5lLnBheWxvYWRzID0gJyc7XG4gICAgfVxuICB9KTtcblxuICB2YXIgb3V0ZXJPcmRlciA9IG9wdHMub3V0ZXJPcmRlciB8fCBkZWZhdWx0T3V0ZXJPcmRlcjtcbiAgdmFyIGlubmVyT3JkZXIgPSBvcHRzLmlubmVyT3JkZXIgfHwgZGVmYXVsdElubmVyT3JkZXI7XG4gIHZhciBzZHAgPSBbXTtcblxuICAvLyBsb29wIHRocm91Z2ggb3V0ZXJPcmRlciBmb3IgbWF0Y2hpbmcgcHJvcGVydGllcyBvbiBzZXNzaW9uXG4gIG91dGVyT3JkZXIuZm9yRWFjaChmdW5jdGlvbiAodHlwZSkge1xuICAgIGdyYW1tYXJbdHlwZV0uZm9yRWFjaChmdW5jdGlvbiAob2JqKSB7XG4gICAgICBpZiAob2JqLm5hbWUgaW4gc2Vzc2lvbiAmJiBzZXNzaW9uW29iai5uYW1lXSAhPSBudWxsKSB7XG4gICAgICAgIHNkcC5wdXNoKG1ha2VMaW5lKHR5cGUsIG9iaiwgc2Vzc2lvbikpO1xuICAgICAgfVxuICAgICAgZWxzZSBpZiAob2JqLnB1c2ggaW4gc2Vzc2lvbiAmJiBzZXNzaW9uW29iai5wdXNoXSAhPSBudWxsKSB7XG4gICAgICAgIHNlc3Npb25bb2JqLnB1c2hdLmZvckVhY2goZnVuY3Rpb24gKGVsKSB7XG4gICAgICAgICAgc2RwLnB1c2gobWFrZUxpbmUodHlwZSwgb2JqLCBlbCkpO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfSk7XG5cbiAgLy8gdGhlbiBmb3IgZWFjaCBtZWRpYSBsaW5lLCBmb2xsb3cgdGhlIGlubmVyT3JkZXJcbiAgc2Vzc2lvbi5tZWRpYS5mb3JFYWNoKGZ1bmN0aW9uIChtTGluZSkge1xuICAgIHNkcC5wdXNoKG1ha2VMaW5lKCdtJywgZ3JhbW1hci5tWzBdLCBtTGluZSkpO1xuXG4gICAgaW5uZXJPcmRlci5mb3JFYWNoKGZ1bmN0aW9uICh0eXBlKSB7XG4gICAgICBncmFtbWFyW3R5cGVdLmZvckVhY2goZnVuY3Rpb24gKG9iaikge1xuICAgICAgICBpZiAob2JqLm5hbWUgaW4gbUxpbmUgJiYgbUxpbmVbb2JqLm5hbWVdICE9IG51bGwpIHtcbiAgICAgICAgICBzZHAucHVzaChtYWtlTGluZSh0eXBlLCBvYmosIG1MaW5lKSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAob2JqLnB1c2ggaW4gbUxpbmUgJiYgbUxpbmVbb2JqLnB1c2hdICE9IG51bGwpIHtcbiAgICAgICAgICBtTGluZVtvYmoucHVzaF0uZm9yRWFjaChmdW5jdGlvbiAoZWwpIHtcbiAgICAgICAgICAgIHNkcC5wdXNoKG1ha2VMaW5lKHR5cGUsIG9iaiwgZWwpKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIHJldHVybiBzZHAuam9pbignXFxyXFxuJykgKyAnXFxyXFxuJztcbn07XG4iLCJpbXBvcnQgZGVidWcgZnJvbSAnZGVidWcnO1xuXG5jb25zdCBBUFBfTkFNRSA9ICdtZWRpYXNvdXAtZGVtbyc7XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIExvZ2dlclxue1xuXHRjb25zdHJ1Y3RvcihwcmVmaXgpXG5cdHtcblx0XHRpZiAocHJlZml4KVxuXHRcdHtcblx0XHRcdHRoaXMuX2RlYnVnID0gZGVidWcoYCR7QVBQX05BTUV9OiR7cHJlZml4fWApO1xuXHRcdFx0dGhpcy5fd2FybiA9IGRlYnVnKGAke0FQUF9OQU1FfTpXQVJOOiR7cHJlZml4fWApO1xuXHRcdFx0dGhpcy5fZXJyb3IgPSBkZWJ1ZyhgJHtBUFBfTkFNRX06RVJST1I6JHtwcmVmaXh9YCk7XG5cdFx0fVxuXHRcdGVsc2Vcblx0XHR7XG5cdFx0XHR0aGlzLl9kZWJ1ZyA9IGRlYnVnKEFQUF9OQU1FKTtcblx0XHRcdHRoaXMuX3dhcm4gPSBkZWJ1ZyhgJHtBUFBfTkFNRX06V0FSTmApO1xuXHRcdFx0dGhpcy5fZXJyb3IgPSBkZWJ1ZyhgJHtBUFBfTkFNRX06RVJST1JgKTtcblx0XHR9XG5cblx0XHQvKiBlc2xpbnQtZGlzYWJsZSBuby1jb25zb2xlICovXG5cdFx0dGhpcy5fZGVidWcubG9nID0gY29uc29sZS5pbmZvLmJpbmQoY29uc29sZSk7XG5cdFx0dGhpcy5fd2Fybi5sb2cgPSBjb25zb2xlLndhcm4uYmluZChjb25zb2xlKTtcblx0XHR0aGlzLl9lcnJvci5sb2cgPSBjb25zb2xlLmVycm9yLmJpbmQoY29uc29sZSk7XG5cdFx0LyogZXNsaW50LWVuYWJsZSBuby1jb25zb2xlICovXG5cdH1cblxuXHRnZXQgZGVidWcoKVxuXHR7XG5cdFx0cmV0dXJuIHRoaXMuX2RlYnVnO1xuXHR9XG5cblx0Z2V0IHdhcm4oKVxuXHR7XG5cdFx0cmV0dXJuIHRoaXMuX3dhcm47XG5cdH1cblxuXHRnZXQgZXJyb3IoKVxuXHR7XG5cdFx0cmV0dXJuIHRoaXMuX2Vycm9yO1xuXHR9XG59XG4iLCIvKipcbiAqIFRoaXMgaXMgdGhlIHdlYiBicm93c2VyIGltcGxlbWVudGF0aW9uIG9mIGBkZWJ1ZygpYC5cbiAqXG4gKiBFeHBvc2UgYGRlYnVnKClgIGFzIHRoZSBtb2R1bGUuXG4gKi9cblxuZXhwb3J0cyA9IG1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi9kZWJ1ZycpO1xuZXhwb3J0cy5sb2cgPSBsb2c7XG5leHBvcnRzLmZvcm1hdEFyZ3MgPSBmb3JtYXRBcmdzO1xuZXhwb3J0cy5zYXZlID0gc2F2ZTtcbmV4cG9ydHMubG9hZCA9IGxvYWQ7XG5leHBvcnRzLnVzZUNvbG9ycyA9IHVzZUNvbG9ycztcbmV4cG9ydHMuc3RvcmFnZSA9ICd1bmRlZmluZWQnICE9IHR5cGVvZiBjaHJvbWVcbiAgICAgICAgICAgICAgICYmICd1bmRlZmluZWQnICE9IHR5cGVvZiBjaHJvbWUuc3RvcmFnZVxuICAgICAgICAgICAgICAgICAgPyBjaHJvbWUuc3RvcmFnZS5sb2NhbFxuICAgICAgICAgICAgICAgICAgOiBsb2NhbHN0b3JhZ2UoKTtcblxuLyoqXG4gKiBDb2xvcnMuXG4gKi9cblxuZXhwb3J0cy5jb2xvcnMgPSBbXG4gICcjMDAwMENDJywgJyMwMDAwRkYnLCAnIzAwMzNDQycsICcjMDAzM0ZGJywgJyMwMDY2Q0MnLCAnIzAwNjZGRicsICcjMDA5OUNDJyxcbiAgJyMwMDk5RkYnLCAnIzAwQ0MwMCcsICcjMDBDQzMzJywgJyMwMENDNjYnLCAnIzAwQ0M5OScsICcjMDBDQ0NDJywgJyMwMENDRkYnLFxuICAnIzMzMDBDQycsICcjMzMwMEZGJywgJyMzMzMzQ0MnLCAnIzMzMzNGRicsICcjMzM2NkNDJywgJyMzMzY2RkYnLCAnIzMzOTlDQycsXG4gICcjMzM5OUZGJywgJyMzM0NDMDAnLCAnIzMzQ0MzMycsICcjMzNDQzY2JywgJyMzM0NDOTknLCAnIzMzQ0NDQycsICcjMzNDQ0ZGJyxcbiAgJyM2NjAwQ0MnLCAnIzY2MDBGRicsICcjNjYzM0NDJywgJyM2NjMzRkYnLCAnIzY2Q0MwMCcsICcjNjZDQzMzJywgJyM5OTAwQ0MnLFxuICAnIzk5MDBGRicsICcjOTkzM0NDJywgJyM5OTMzRkYnLCAnIzk5Q0MwMCcsICcjOTlDQzMzJywgJyNDQzAwMDAnLCAnI0NDMDAzMycsXG4gICcjQ0MwMDY2JywgJyNDQzAwOTknLCAnI0NDMDBDQycsICcjQ0MwMEZGJywgJyNDQzMzMDAnLCAnI0NDMzMzMycsICcjQ0MzMzY2JyxcbiAgJyNDQzMzOTknLCAnI0NDMzNDQycsICcjQ0MzM0ZGJywgJyNDQzY2MDAnLCAnI0NDNjYzMycsICcjQ0M5OTAwJywgJyNDQzk5MzMnLFxuICAnI0NDQ0MwMCcsICcjQ0NDQzMzJywgJyNGRjAwMDAnLCAnI0ZGMDAzMycsICcjRkYwMDY2JywgJyNGRjAwOTknLCAnI0ZGMDBDQycsXG4gICcjRkYwMEZGJywgJyNGRjMzMDAnLCAnI0ZGMzMzMycsICcjRkYzMzY2JywgJyNGRjMzOTknLCAnI0ZGMzNDQycsICcjRkYzM0ZGJyxcbiAgJyNGRjY2MDAnLCAnI0ZGNjYzMycsICcjRkY5OTAwJywgJyNGRjk5MzMnLCAnI0ZGQ0MwMCcsICcjRkZDQzMzJ1xuXTtcblxuLyoqXG4gKiBDdXJyZW50bHkgb25seSBXZWJLaXQtYmFzZWQgV2ViIEluc3BlY3RvcnMsIEZpcmVmb3ggPj0gdjMxLFxuICogYW5kIHRoZSBGaXJlYnVnIGV4dGVuc2lvbiAoYW55IEZpcmVmb3ggdmVyc2lvbikgYXJlIGtub3duXG4gKiB0byBzdXBwb3J0IFwiJWNcIiBDU1MgY3VzdG9taXphdGlvbnMuXG4gKlxuICogVE9ETzogYWRkIGEgYGxvY2FsU3RvcmFnZWAgdmFyaWFibGUgdG8gZXhwbGljaXRseSBlbmFibGUvZGlzYWJsZSBjb2xvcnNcbiAqL1xuXG5mdW5jdGlvbiB1c2VDb2xvcnMoKSB7XG4gIC8vIE5COiBJbiBhbiBFbGVjdHJvbiBwcmVsb2FkIHNjcmlwdCwgZG9jdW1lbnQgd2lsbCBiZSBkZWZpbmVkIGJ1dCBub3QgZnVsbHlcbiAgLy8gaW5pdGlhbGl6ZWQuIFNpbmNlIHdlIGtub3cgd2UncmUgaW4gQ2hyb21lLCB3ZSdsbCBqdXN0IGRldGVjdCB0aGlzIGNhc2VcbiAgLy8gZXhwbGljaXRseVxuICBpZiAodHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcgJiYgd2luZG93LnByb2Nlc3MgJiYgd2luZG93LnByb2Nlc3MudHlwZSA9PT0gJ3JlbmRlcmVyJykge1xuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgLy8gaXMgd2Via2l0PyBodHRwOi8vc3RhY2tvdmVyZmxvdy5jb20vYS8xNjQ1OTYwNi8zNzY3NzNcbiAgLy8gZG9jdW1lbnQgaXMgdW5kZWZpbmVkIGluIHJlYWN0LW5hdGl2ZTogaHR0cHM6Ly9naXRodWIuY29tL2ZhY2Vib29rL3JlYWN0LW5hdGl2ZS9wdWxsLzE2MzJcbiAgcmV0dXJuICh0eXBlb2YgZG9jdW1lbnQgIT09ICd1bmRlZmluZWQnICYmIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudCAmJiBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuc3R5bGUgJiYgZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LnN0eWxlLldlYmtpdEFwcGVhcmFuY2UpIHx8XG4gICAgLy8gaXMgZmlyZWJ1Zz8gaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL2EvMzk4MTIwLzM3Njc3M1xuICAgICh0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJyAmJiB3aW5kb3cuY29uc29sZSAmJiAod2luZG93LmNvbnNvbGUuZmlyZWJ1ZyB8fCAod2luZG93LmNvbnNvbGUuZXhjZXB0aW9uICYmIHdpbmRvdy5jb25zb2xlLnRhYmxlKSkpIHx8XG4gICAgLy8gaXMgZmlyZWZveCA+PSB2MzE/XG4gICAgLy8gaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9Ub29scy9XZWJfQ29uc29sZSNTdHlsaW5nX21lc3NhZ2VzXG4gICAgKHR5cGVvZiBuYXZpZ2F0b3IgIT09ICd1bmRlZmluZWQnICYmIG5hdmlnYXRvci51c2VyQWdlbnQgJiYgbmF2aWdhdG9yLnVzZXJBZ2VudC50b0xvd2VyQ2FzZSgpLm1hdGNoKC9maXJlZm94XFwvKFxcZCspLykgJiYgcGFyc2VJbnQoUmVnRXhwLiQxLCAxMCkgPj0gMzEpIHx8XG4gICAgLy8gZG91YmxlIGNoZWNrIHdlYmtpdCBpbiB1c2VyQWdlbnQganVzdCBpbiBjYXNlIHdlIGFyZSBpbiBhIHdvcmtlclxuICAgICh0eXBlb2YgbmF2aWdhdG9yICE9PSAndW5kZWZpbmVkJyAmJiBuYXZpZ2F0b3IudXNlckFnZW50ICYmIG5hdmlnYXRvci51c2VyQWdlbnQudG9Mb3dlckNhc2UoKS5tYXRjaCgvYXBwbGV3ZWJraXRcXC8oXFxkKykvKSk7XG59XG5cbi8qKlxuICogTWFwICVqIHRvIGBKU09OLnN0cmluZ2lmeSgpYCwgc2luY2Ugbm8gV2ViIEluc3BlY3RvcnMgZG8gdGhhdCBieSBkZWZhdWx0LlxuICovXG5cbmV4cG9ydHMuZm9ybWF0dGVycy5qID0gZnVuY3Rpb24odikge1xuICB0cnkge1xuICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh2KTtcbiAgfSBjYXRjaCAoZXJyKSB7XG4gICAgcmV0dXJuICdbVW5leHBlY3RlZEpTT05QYXJzZUVycm9yXTogJyArIGVyci5tZXNzYWdlO1xuICB9XG59O1xuXG5cbi8qKlxuICogQ29sb3JpemUgbG9nIGFyZ3VtZW50cyBpZiBlbmFibGVkLlxuICpcbiAqIEBhcGkgcHVibGljXG4gKi9cblxuZnVuY3Rpb24gZm9ybWF0QXJncyhhcmdzKSB7XG4gIHZhciB1c2VDb2xvcnMgPSB0aGlzLnVzZUNvbG9ycztcblxuICBhcmdzWzBdID0gKHVzZUNvbG9ycyA/ICclYycgOiAnJylcbiAgICArIHRoaXMubmFtZXNwYWNlXG4gICAgKyAodXNlQ29sb3JzID8gJyAlYycgOiAnICcpXG4gICAgKyBhcmdzWzBdXG4gICAgKyAodXNlQ29sb3JzID8gJyVjICcgOiAnICcpXG4gICAgKyAnKycgKyBleHBvcnRzLmh1bWFuaXplKHRoaXMuZGlmZik7XG5cbiAgaWYgKCF1c2VDb2xvcnMpIHJldHVybjtcblxuICB2YXIgYyA9ICdjb2xvcjogJyArIHRoaXMuY29sb3I7XG4gIGFyZ3Muc3BsaWNlKDEsIDAsIGMsICdjb2xvcjogaW5oZXJpdCcpXG5cbiAgLy8gdGhlIGZpbmFsIFwiJWNcIiBpcyBzb21ld2hhdCB0cmlja3ksIGJlY2F1c2UgdGhlcmUgY291bGQgYmUgb3RoZXJcbiAgLy8gYXJndW1lbnRzIHBhc3NlZCBlaXRoZXIgYmVmb3JlIG9yIGFmdGVyIHRoZSAlYywgc28gd2UgbmVlZCB0b1xuICAvLyBmaWd1cmUgb3V0IHRoZSBjb3JyZWN0IGluZGV4IHRvIGluc2VydCB0aGUgQ1NTIGludG9cbiAgdmFyIGluZGV4ID0gMDtcbiAgdmFyIGxhc3RDID0gMDtcbiAgYXJnc1swXS5yZXBsYWNlKC8lW2EtekEtWiVdL2csIGZ1bmN0aW9uKG1hdGNoKSB7XG4gICAgaWYgKCclJScgPT09IG1hdGNoKSByZXR1cm47XG4gICAgaW5kZXgrKztcbiAgICBpZiAoJyVjJyA9PT0gbWF0Y2gpIHtcbiAgICAgIC8vIHdlIG9ubHkgYXJlIGludGVyZXN0ZWQgaW4gdGhlICpsYXN0KiAlY1xuICAgICAgLy8gKHRoZSB1c2VyIG1heSBoYXZlIHByb3ZpZGVkIHRoZWlyIG93bilcbiAgICAgIGxhc3RDID0gaW5kZXg7XG4gICAgfVxuICB9KTtcblxuICBhcmdzLnNwbGljZShsYXN0QywgMCwgYyk7XG59XG5cbi8qKlxuICogSW52b2tlcyBgY29uc29sZS5sb2coKWAgd2hlbiBhdmFpbGFibGUuXG4gKiBOby1vcCB3aGVuIGBjb25zb2xlLmxvZ2AgaXMgbm90IGEgXCJmdW5jdGlvblwiLlxuICpcbiAqIEBhcGkgcHVibGljXG4gKi9cblxuZnVuY3Rpb24gbG9nKCkge1xuICAvLyB0aGlzIGhhY2tlcnkgaXMgcmVxdWlyZWQgZm9yIElFOC85LCB3aGVyZVxuICAvLyB0aGUgYGNvbnNvbGUubG9nYCBmdW5jdGlvbiBkb2Vzbid0IGhhdmUgJ2FwcGx5J1xuICByZXR1cm4gJ29iamVjdCcgPT09IHR5cGVvZiBjb25zb2xlXG4gICAgJiYgY29uc29sZS5sb2dcbiAgICAmJiBGdW5jdGlvbi5wcm90b3R5cGUuYXBwbHkuY2FsbChjb25zb2xlLmxvZywgY29uc29sZSwgYXJndW1lbnRzKTtcbn1cblxuLyoqXG4gKiBTYXZlIGBuYW1lc3BhY2VzYC5cbiAqXG4gKiBAcGFyYW0ge1N0cmluZ30gbmFtZXNwYWNlc1xuICogQGFwaSBwcml2YXRlXG4gKi9cblxuZnVuY3Rpb24gc2F2ZShuYW1lc3BhY2VzKSB7XG4gIHRyeSB7XG4gICAgaWYgKG51bGwgPT0gbmFtZXNwYWNlcykge1xuICAgICAgZXhwb3J0cy5zdG9yYWdlLnJlbW92ZUl0ZW0oJ2RlYnVnJyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGV4cG9ydHMuc3RvcmFnZS5kZWJ1ZyA9IG5hbWVzcGFjZXM7XG4gICAgfVxuICB9IGNhdGNoKGUpIHt9XG59XG5cbi8qKlxuICogTG9hZCBgbmFtZXNwYWNlc2AuXG4gKlxuICogQHJldHVybiB7U3RyaW5nfSByZXR1cm5zIHRoZSBwcmV2aW91c2x5IHBlcnNpc3RlZCBkZWJ1ZyBtb2Rlc1xuICogQGFwaSBwcml2YXRlXG4gKi9cblxuZnVuY3Rpb24gbG9hZCgpIHtcbiAgdmFyIHI7XG4gIHRyeSB7XG4gICAgciA9IGV4cG9ydHMuc3RvcmFnZS5kZWJ1ZztcbiAgfSBjYXRjaChlKSB7fVxuXG4gIC8vIElmIGRlYnVnIGlzbid0IHNldCBpbiBMUywgYW5kIHdlJ3JlIGluIEVsZWN0cm9uLCB0cnkgdG8gbG9hZCAkREVCVUdcbiAgaWYgKCFyICYmIHR5cGVvZiBwcm9jZXNzICE9PSAndW5kZWZpbmVkJyAmJiAnZW52JyBpbiBwcm9jZXNzKSB7XG4gICAgciA9IHByb2Nlc3MuZW52LkRFQlVHO1xuICB9XG5cbiAgcmV0dXJuIHI7XG59XG5cbi8qKlxuICogRW5hYmxlIG5hbWVzcGFjZXMgbGlzdGVkIGluIGBsb2NhbFN0b3JhZ2UuZGVidWdgIGluaXRpYWxseS5cbiAqL1xuXG5leHBvcnRzLmVuYWJsZShsb2FkKCkpO1xuXG4vKipcbiAqIExvY2Fsc3RvcmFnZSBhdHRlbXB0cyB0byByZXR1cm4gdGhlIGxvY2Fsc3RvcmFnZS5cbiAqXG4gKiBUaGlzIGlzIG5lY2Vzc2FyeSBiZWNhdXNlIHNhZmFyaSB0aHJvd3NcbiAqIHdoZW4gYSB1c2VyIGRpc2FibGVzIGNvb2tpZXMvbG9jYWxzdG9yYWdlXG4gKiBhbmQgeW91IGF0dGVtcHQgdG8gYWNjZXNzIGl0LlxuICpcbiAqIEByZXR1cm4ge0xvY2FsU3RvcmFnZX1cbiAqIEBhcGkgcHJpdmF0ZVxuICovXG5cbmZ1bmN0aW9uIGxvY2Fsc3RvcmFnZSgpIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gd2luZG93LmxvY2FsU3RvcmFnZTtcbiAgfSBjYXRjaCAoZSkge31cbn1cbiIsIlxuLyoqXG4gKiBUaGlzIGlzIHRoZSBjb21tb24gbG9naWMgZm9yIGJvdGggdGhlIE5vZGUuanMgYW5kIHdlYiBicm93c2VyXG4gKiBpbXBsZW1lbnRhdGlvbnMgb2YgYGRlYnVnKClgLlxuICpcbiAqIEV4cG9zZSBgZGVidWcoKWAgYXMgdGhlIG1vZHVsZS5cbiAqL1xuXG5leHBvcnRzID0gbW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVEZWJ1Zy5kZWJ1ZyA9IGNyZWF0ZURlYnVnWydkZWZhdWx0J10gPSBjcmVhdGVEZWJ1ZztcbmV4cG9ydHMuY29lcmNlID0gY29lcmNlO1xuZXhwb3J0cy5kaXNhYmxlID0gZGlzYWJsZTtcbmV4cG9ydHMuZW5hYmxlID0gZW5hYmxlO1xuZXhwb3J0cy5lbmFibGVkID0gZW5hYmxlZDtcbmV4cG9ydHMuaHVtYW5pemUgPSByZXF1aXJlKCdtcycpO1xuXG4vKipcbiAqIEFjdGl2ZSBgZGVidWdgIGluc3RhbmNlcy5cbiAqL1xuZXhwb3J0cy5pbnN0YW5jZXMgPSBbXTtcblxuLyoqXG4gKiBUaGUgY3VycmVudGx5IGFjdGl2ZSBkZWJ1ZyBtb2RlIG5hbWVzLCBhbmQgbmFtZXMgdG8gc2tpcC5cbiAqL1xuXG5leHBvcnRzLm5hbWVzID0gW107XG5leHBvcnRzLnNraXBzID0gW107XG5cbi8qKlxuICogTWFwIG9mIHNwZWNpYWwgXCIlblwiIGhhbmRsaW5nIGZ1bmN0aW9ucywgZm9yIHRoZSBkZWJ1ZyBcImZvcm1hdFwiIGFyZ3VtZW50LlxuICpcbiAqIFZhbGlkIGtleSBuYW1lcyBhcmUgYSBzaW5nbGUsIGxvd2VyIG9yIHVwcGVyLWNhc2UgbGV0dGVyLCBpLmUuIFwiblwiIGFuZCBcIk5cIi5cbiAqL1xuXG5leHBvcnRzLmZvcm1hdHRlcnMgPSB7fTtcblxuLyoqXG4gKiBTZWxlY3QgYSBjb2xvci5cbiAqIEBwYXJhbSB7U3RyaW5nfSBuYW1lc3BhY2VcbiAqIEByZXR1cm4ge051bWJlcn1cbiAqIEBhcGkgcHJpdmF0ZVxuICovXG5cbmZ1bmN0aW9uIHNlbGVjdENvbG9yKG5hbWVzcGFjZSkge1xuICB2YXIgaGFzaCA9IDAsIGk7XG5cbiAgZm9yIChpIGluIG5hbWVzcGFjZSkge1xuICAgIGhhc2ggID0gKChoYXNoIDw8IDUpIC0gaGFzaCkgKyBuYW1lc3BhY2UuY2hhckNvZGVBdChpKTtcbiAgICBoYXNoIHw9IDA7IC8vIENvbnZlcnQgdG8gMzJiaXQgaW50ZWdlclxuICB9XG5cbiAgcmV0dXJuIGV4cG9ydHMuY29sb3JzW01hdGguYWJzKGhhc2gpICUgZXhwb3J0cy5jb2xvcnMubGVuZ3RoXTtcbn1cblxuLyoqXG4gKiBDcmVhdGUgYSBkZWJ1Z2dlciB3aXRoIHRoZSBnaXZlbiBgbmFtZXNwYWNlYC5cbiAqXG4gKiBAcGFyYW0ge1N0cmluZ30gbmFtZXNwYWNlXG4gKiBAcmV0dXJuIHtGdW5jdGlvbn1cbiAqIEBhcGkgcHVibGljXG4gKi9cblxuZnVuY3Rpb24gY3JlYXRlRGVidWcobmFtZXNwYWNlKSB7XG5cbiAgdmFyIHByZXZUaW1lO1xuXG4gIGZ1bmN0aW9uIGRlYnVnKCkge1xuICAgIC8vIGRpc2FibGVkP1xuICAgIGlmICghZGVidWcuZW5hYmxlZCkgcmV0dXJuO1xuXG4gICAgdmFyIHNlbGYgPSBkZWJ1ZztcblxuICAgIC8vIHNldCBgZGlmZmAgdGltZXN0YW1wXG4gICAgdmFyIGN1cnIgPSArbmV3IERhdGUoKTtcbiAgICB2YXIgbXMgPSBjdXJyIC0gKHByZXZUaW1lIHx8IGN1cnIpO1xuICAgIHNlbGYuZGlmZiA9IG1zO1xuICAgIHNlbGYucHJldiA9IHByZXZUaW1lO1xuICAgIHNlbGYuY3VyciA9IGN1cnI7XG4gICAgcHJldlRpbWUgPSBjdXJyO1xuXG4gICAgLy8gdHVybiB0aGUgYGFyZ3VtZW50c2AgaW50byBhIHByb3BlciBBcnJheVxuICAgIHZhciBhcmdzID0gbmV3IEFycmF5KGFyZ3VtZW50cy5sZW5ndGgpO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYXJncy5sZW5ndGg7IGkrKykge1xuICAgICAgYXJnc1tpXSA9IGFyZ3VtZW50c1tpXTtcbiAgICB9XG5cbiAgICBhcmdzWzBdID0gZXhwb3J0cy5jb2VyY2UoYXJnc1swXSk7XG5cbiAgICBpZiAoJ3N0cmluZycgIT09IHR5cGVvZiBhcmdzWzBdKSB7XG4gICAgICAvLyBhbnl0aGluZyBlbHNlIGxldCdzIGluc3BlY3Qgd2l0aCAlT1xuICAgICAgYXJncy51bnNoaWZ0KCclTycpO1xuICAgIH1cblxuICAgIC8vIGFwcGx5IGFueSBgZm9ybWF0dGVyc2AgdHJhbnNmb3JtYXRpb25zXG4gICAgdmFyIGluZGV4ID0gMDtcbiAgICBhcmdzWzBdID0gYXJnc1swXS5yZXBsYWNlKC8lKFthLXpBLVolXSkvZywgZnVuY3Rpb24obWF0Y2gsIGZvcm1hdCkge1xuICAgICAgLy8gaWYgd2UgZW5jb3VudGVyIGFuIGVzY2FwZWQgJSB0aGVuIGRvbid0IGluY3JlYXNlIHRoZSBhcnJheSBpbmRleFxuICAgICAgaWYgKG1hdGNoID09PSAnJSUnKSByZXR1cm4gbWF0Y2g7XG4gICAgICBpbmRleCsrO1xuICAgICAgdmFyIGZvcm1hdHRlciA9IGV4cG9ydHMuZm9ybWF0dGVyc1tmb3JtYXRdO1xuICAgICAgaWYgKCdmdW5jdGlvbicgPT09IHR5cGVvZiBmb3JtYXR0ZXIpIHtcbiAgICAgICAgdmFyIHZhbCA9IGFyZ3NbaW5kZXhdO1xuICAgICAgICBtYXRjaCA9IGZvcm1hdHRlci5jYWxsKHNlbGYsIHZhbCk7XG5cbiAgICAgICAgLy8gbm93IHdlIG5lZWQgdG8gcmVtb3ZlIGBhcmdzW2luZGV4XWAgc2luY2UgaXQncyBpbmxpbmVkIGluIHRoZSBgZm9ybWF0YFxuICAgICAgICBhcmdzLnNwbGljZShpbmRleCwgMSk7XG4gICAgICAgIGluZGV4LS07XG4gICAgICB9XG4gICAgICByZXR1cm4gbWF0Y2g7XG4gICAgfSk7XG5cbiAgICAvLyBhcHBseSBlbnYtc3BlY2lmaWMgZm9ybWF0dGluZyAoY29sb3JzLCBldGMuKVxuICAgIGV4cG9ydHMuZm9ybWF0QXJncy5jYWxsKHNlbGYsIGFyZ3MpO1xuXG4gICAgdmFyIGxvZ0ZuID0gZGVidWcubG9nIHx8IGV4cG9ydHMubG9nIHx8IGNvbnNvbGUubG9nLmJpbmQoY29uc29sZSk7XG4gICAgbG9nRm4uYXBwbHkoc2VsZiwgYXJncyk7XG4gIH1cblxuICBkZWJ1Zy5uYW1lc3BhY2UgPSBuYW1lc3BhY2U7XG4gIGRlYnVnLmVuYWJsZWQgPSBleHBvcnRzLmVuYWJsZWQobmFtZXNwYWNlKTtcbiAgZGVidWcudXNlQ29sb3JzID0gZXhwb3J0cy51c2VDb2xvcnMoKTtcbiAgZGVidWcuY29sb3IgPSBzZWxlY3RDb2xvcihuYW1lc3BhY2UpO1xuICBkZWJ1Zy5kZXN0cm95ID0gZGVzdHJveTtcblxuICAvLyBlbnYtc3BlY2lmaWMgaW5pdGlhbGl6YXRpb24gbG9naWMgZm9yIGRlYnVnIGluc3RhbmNlc1xuICBpZiAoJ2Z1bmN0aW9uJyA9PT0gdHlwZW9mIGV4cG9ydHMuaW5pdCkge1xuICAgIGV4cG9ydHMuaW5pdChkZWJ1Zyk7XG4gIH1cblxuICBleHBvcnRzLmluc3RhbmNlcy5wdXNoKGRlYnVnKTtcblxuICByZXR1cm4gZGVidWc7XG59XG5cbmZ1bmN0aW9uIGRlc3Ryb3kgKCkge1xuICB2YXIgaW5kZXggPSBleHBvcnRzLmluc3RhbmNlcy5pbmRleE9mKHRoaXMpO1xuICBpZiAoaW5kZXggIT09IC0xKSB7XG4gICAgZXhwb3J0cy5pbnN0YW5jZXMuc3BsaWNlKGluZGV4LCAxKTtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbn1cblxuLyoqXG4gKiBFbmFibGVzIGEgZGVidWcgbW9kZSBieSBuYW1lc3BhY2VzLiBUaGlzIGNhbiBpbmNsdWRlIG1vZGVzXG4gKiBzZXBhcmF0ZWQgYnkgYSBjb2xvbiBhbmQgd2lsZGNhcmRzLlxuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSBuYW1lc3BhY2VzXG4gKiBAYXBpIHB1YmxpY1xuICovXG5cbmZ1bmN0aW9uIGVuYWJsZShuYW1lc3BhY2VzKSB7XG4gIGV4cG9ydHMuc2F2ZShuYW1lc3BhY2VzKTtcblxuICBleHBvcnRzLm5hbWVzID0gW107XG4gIGV4cG9ydHMuc2tpcHMgPSBbXTtcblxuICB2YXIgaTtcbiAgdmFyIHNwbGl0ID0gKHR5cGVvZiBuYW1lc3BhY2VzID09PSAnc3RyaW5nJyA/IG5hbWVzcGFjZXMgOiAnJykuc3BsaXQoL1tcXHMsXSsvKTtcbiAgdmFyIGxlbiA9IHNwbGl0Lmxlbmd0aDtcblxuICBmb3IgKGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICBpZiAoIXNwbGl0W2ldKSBjb250aW51ZTsgLy8gaWdub3JlIGVtcHR5IHN0cmluZ3NcbiAgICBuYW1lc3BhY2VzID0gc3BsaXRbaV0ucmVwbGFjZSgvXFwqL2csICcuKj8nKTtcbiAgICBpZiAobmFtZXNwYWNlc1swXSA9PT0gJy0nKSB7XG4gICAgICBleHBvcnRzLnNraXBzLnB1c2gobmV3IFJlZ0V4cCgnXicgKyBuYW1lc3BhY2VzLnN1YnN0cigxKSArICckJykpO1xuICAgIH0gZWxzZSB7XG4gICAgICBleHBvcnRzLm5hbWVzLnB1c2gobmV3IFJlZ0V4cCgnXicgKyBuYW1lc3BhY2VzICsgJyQnKSk7XG4gICAgfVxuICB9XG5cbiAgZm9yIChpID0gMDsgaSA8IGV4cG9ydHMuaW5zdGFuY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIGluc3RhbmNlID0gZXhwb3J0cy5pbnN0YW5jZXNbaV07XG4gICAgaW5zdGFuY2UuZW5hYmxlZCA9IGV4cG9ydHMuZW5hYmxlZChpbnN0YW5jZS5uYW1lc3BhY2UpO1xuICB9XG59XG5cbi8qKlxuICogRGlzYWJsZSBkZWJ1ZyBvdXRwdXQuXG4gKlxuICogQGFwaSBwdWJsaWNcbiAqL1xuXG5mdW5jdGlvbiBkaXNhYmxlKCkge1xuICBleHBvcnRzLmVuYWJsZSgnJyk7XG59XG5cbi8qKlxuICogUmV0dXJucyB0cnVlIGlmIHRoZSBnaXZlbiBtb2RlIG5hbWUgaXMgZW5hYmxlZCwgZmFsc2Ugb3RoZXJ3aXNlLlxuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSBuYW1lXG4gKiBAcmV0dXJuIHtCb29sZWFufVxuICogQGFwaSBwdWJsaWNcbiAqL1xuXG5mdW5jdGlvbiBlbmFibGVkKG5hbWUpIHtcbiAgaWYgKG5hbWVbbmFtZS5sZW5ndGggLSAxXSA9PT0gJyonKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cbiAgdmFyIGksIGxlbjtcbiAgZm9yIChpID0gMCwgbGVuID0gZXhwb3J0cy5za2lwcy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuICAgIGlmIChleHBvcnRzLnNraXBzW2ldLnRlc3QobmFtZSkpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cbiAgZm9yIChpID0gMCwgbGVuID0gZXhwb3J0cy5uYW1lcy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuICAgIGlmIChleHBvcnRzLm5hbWVzW2ldLnRlc3QobmFtZSkpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfVxuICByZXR1cm4gZmFsc2U7XG59XG5cbi8qKlxuICogQ29lcmNlIGB2YWxgLlxuICpcbiAqIEBwYXJhbSB7TWl4ZWR9IHZhbFxuICogQHJldHVybiB7TWl4ZWR9XG4gKiBAYXBpIHByaXZhdGVcbiAqL1xuXG5mdW5jdGlvbiBjb2VyY2UodmFsKSB7XG4gIGlmICh2YWwgaW5zdGFuY2VvZiBFcnJvcikgcmV0dXJuIHZhbC5zdGFjayB8fCB2YWwubWVzc2FnZTtcbiAgcmV0dXJuIHZhbDtcbn1cbiIsIi8qIVxuICAqIGRvbXJlYWR5IChjKSBEdXN0aW4gRGlheiAyMDE0IC0gTGljZW5zZSBNSVRcbiAgKi9cbiFmdW5jdGlvbiAobmFtZSwgZGVmaW5pdGlvbikge1xuXG4gIGlmICh0eXBlb2YgbW9kdWxlICE9ICd1bmRlZmluZWQnKSBtb2R1bGUuZXhwb3J0cyA9IGRlZmluaXRpb24oKVxuICBlbHNlIGlmICh0eXBlb2YgZGVmaW5lID09ICdmdW5jdGlvbicgJiYgdHlwZW9mIGRlZmluZS5hbWQgPT0gJ29iamVjdCcpIGRlZmluZShkZWZpbml0aW9uKVxuICBlbHNlIHRoaXNbbmFtZV0gPSBkZWZpbml0aW9uKClcblxufSgnZG9tcmVhZHknLCBmdW5jdGlvbiAoKSB7XG5cbiAgdmFyIGZucyA9IFtdLCBsaXN0ZW5lclxuICAgICwgZG9jID0gZG9jdW1lbnRcbiAgICAsIGhhY2sgPSBkb2MuZG9jdW1lbnRFbGVtZW50LmRvU2Nyb2xsXG4gICAgLCBkb21Db250ZW50TG9hZGVkID0gJ0RPTUNvbnRlbnRMb2FkZWQnXG4gICAgLCBsb2FkZWQgPSAoaGFjayA/IC9ebG9hZGVkfF5jLyA6IC9ebG9hZGVkfF5pfF5jLykudGVzdChkb2MucmVhZHlTdGF0ZSlcblxuXG4gIGlmICghbG9hZGVkKVxuICBkb2MuYWRkRXZlbnRMaXN0ZW5lcihkb21Db250ZW50TG9hZGVkLCBsaXN0ZW5lciA9IGZ1bmN0aW9uICgpIHtcbiAgICBkb2MucmVtb3ZlRXZlbnRMaXN0ZW5lcihkb21Db250ZW50TG9hZGVkLCBsaXN0ZW5lcilcbiAgICBsb2FkZWQgPSAxXG4gICAgd2hpbGUgKGxpc3RlbmVyID0gZm5zLnNoaWZ0KCkpIGxpc3RlbmVyKClcbiAgfSlcblxuICByZXR1cm4gZnVuY3Rpb24gKGZuKSB7XG4gICAgbG9hZGVkID8gc2V0VGltZW91dChmbiwgMCkgOiBmbnMucHVzaChmbilcbiAgfVxuXG59KTtcbiIsIi8vIENvcHlyaWdodCBKb3llbnQsIEluYy4gYW5kIG90aGVyIE5vZGUgY29udHJpYnV0b3JzLlxuLy9cbi8vIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhXG4vLyBjb3B5IG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlXG4vLyBcIlNvZnR3YXJlXCIpLCB0byBkZWFsIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmdcbi8vIHdpdGhvdXQgbGltaXRhdGlvbiB0aGUgcmlnaHRzIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCxcbi8vIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vciBzZWxsIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXRcbi8vIHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXMgZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZVxuLy8gZm9sbG93aW5nIGNvbmRpdGlvbnM6XG4vL1xuLy8gVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWRcbi8vIGluIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuLy9cbi8vIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsIEVYUFJFU1Ncbi8vIE9SIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0Zcbi8vIE1FUkNIQU5UQUJJTElUWSwgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU5cbi8vIE5PIEVWRU5UIFNIQUxMIFRIRSBBVVRIT1JTIE9SIENPUFlSSUdIVCBIT0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLFxuLy8gREFNQUdFUyBPUiBPVEhFUiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SXG4vLyBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSwgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFXG4vLyBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU4gVEhFIFNPRlRXQVJFLlxuXG5mdW5jdGlvbiBFdmVudEVtaXR0ZXIoKSB7XG4gIHRoaXMuX2V2ZW50cyA9IHRoaXMuX2V2ZW50cyB8fCB7fTtcbiAgdGhpcy5fbWF4TGlzdGVuZXJzID0gdGhpcy5fbWF4TGlzdGVuZXJzIHx8IHVuZGVmaW5lZDtcbn1cbm1vZHVsZS5leHBvcnRzID0gRXZlbnRFbWl0dGVyO1xuXG4vLyBCYWNrd2FyZHMtY29tcGF0IHdpdGggbm9kZSAwLjEwLnhcbkV2ZW50RW1pdHRlci5FdmVudEVtaXR0ZXIgPSBFdmVudEVtaXR0ZXI7XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuX2V2ZW50cyA9IHVuZGVmaW5lZDtcbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuX21heExpc3RlbmVycyA9IHVuZGVmaW5lZDtcblxuLy8gQnkgZGVmYXVsdCBFdmVudEVtaXR0ZXJzIHdpbGwgcHJpbnQgYSB3YXJuaW5nIGlmIG1vcmUgdGhhbiAxMCBsaXN0ZW5lcnMgYXJlXG4vLyBhZGRlZCB0byBpdC4gVGhpcyBpcyBhIHVzZWZ1bCBkZWZhdWx0IHdoaWNoIGhlbHBzIGZpbmRpbmcgbWVtb3J5IGxlYWtzLlxuRXZlbnRFbWl0dGVyLmRlZmF1bHRNYXhMaXN0ZW5lcnMgPSAxMDtcblxuLy8gT2J2aW91c2x5IG5vdCBhbGwgRW1pdHRlcnMgc2hvdWxkIGJlIGxpbWl0ZWQgdG8gMTAuIFRoaXMgZnVuY3Rpb24gYWxsb3dzXG4vLyB0aGF0IHRvIGJlIGluY3JlYXNlZC4gU2V0IHRvIHplcm8gZm9yIHVubGltaXRlZC5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuc2V0TWF4TGlzdGVuZXJzID0gZnVuY3Rpb24obikge1xuICBpZiAoIWlzTnVtYmVyKG4pIHx8IG4gPCAwIHx8IGlzTmFOKG4pKVxuICAgIHRocm93IFR5cGVFcnJvcignbiBtdXN0IGJlIGEgcG9zaXRpdmUgbnVtYmVyJyk7XG4gIHRoaXMuX21heExpc3RlbmVycyA9IG47XG4gIHJldHVybiB0aGlzO1xufTtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5lbWl0ID0gZnVuY3Rpb24odHlwZSkge1xuICB2YXIgZXIsIGhhbmRsZXIsIGxlbiwgYXJncywgaSwgbGlzdGVuZXJzO1xuXG4gIGlmICghdGhpcy5fZXZlbnRzKVxuICAgIHRoaXMuX2V2ZW50cyA9IHt9O1xuXG4gIC8vIElmIHRoZXJlIGlzIG5vICdlcnJvcicgZXZlbnQgbGlzdGVuZXIgdGhlbiB0aHJvdy5cbiAgaWYgKHR5cGUgPT09ICdlcnJvcicpIHtcbiAgICBpZiAoIXRoaXMuX2V2ZW50cy5lcnJvciB8fFxuICAgICAgICAoaXNPYmplY3QodGhpcy5fZXZlbnRzLmVycm9yKSAmJiAhdGhpcy5fZXZlbnRzLmVycm9yLmxlbmd0aCkpIHtcbiAgICAgIGVyID0gYXJndW1lbnRzWzFdO1xuICAgICAgaWYgKGVyIGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgdGhyb3cgZXI7IC8vIFVuaGFuZGxlZCAnZXJyb3InIGV2ZW50XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBBdCBsZWFzdCBnaXZlIHNvbWUga2luZCBvZiBjb250ZXh0IHRvIHRoZSB1c2VyXG4gICAgICAgIHZhciBlcnIgPSBuZXcgRXJyb3IoJ1VuY2F1Z2h0LCB1bnNwZWNpZmllZCBcImVycm9yXCIgZXZlbnQuICgnICsgZXIgKyAnKScpO1xuICAgICAgICBlcnIuY29udGV4dCA9IGVyO1xuICAgICAgICB0aHJvdyBlcnI7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgaGFuZGxlciA9IHRoaXMuX2V2ZW50c1t0eXBlXTtcblxuICBpZiAoaXNVbmRlZmluZWQoaGFuZGxlcikpXG4gICAgcmV0dXJuIGZhbHNlO1xuXG4gIGlmIChpc0Z1bmN0aW9uKGhhbmRsZXIpKSB7XG4gICAgc3dpdGNoIChhcmd1bWVudHMubGVuZ3RoKSB7XG4gICAgICAvLyBmYXN0IGNhc2VzXG4gICAgICBjYXNlIDE6XG4gICAgICAgIGhhbmRsZXIuY2FsbCh0aGlzKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDI6XG4gICAgICAgIGhhbmRsZXIuY2FsbCh0aGlzLCBhcmd1bWVudHNbMV0pO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgMzpcbiAgICAgICAgaGFuZGxlci5jYWxsKHRoaXMsIGFyZ3VtZW50c1sxXSwgYXJndW1lbnRzWzJdKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICAvLyBzbG93ZXJcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIGFyZ3MgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpO1xuICAgICAgICBoYW5kbGVyLmFwcGx5KHRoaXMsIGFyZ3MpO1xuICAgIH1cbiAgfSBlbHNlIGlmIChpc09iamVjdChoYW5kbGVyKSkge1xuICAgIGFyZ3MgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpO1xuICAgIGxpc3RlbmVycyA9IGhhbmRsZXIuc2xpY2UoKTtcbiAgICBsZW4gPSBsaXN0ZW5lcnMubGVuZ3RoO1xuICAgIGZvciAoaSA9IDA7IGkgPCBsZW47IGkrKylcbiAgICAgIGxpc3RlbmVyc1tpXS5hcHBseSh0aGlzLCBhcmdzKTtcbiAgfVxuXG4gIHJldHVybiB0cnVlO1xufTtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5hZGRMaXN0ZW5lciA9IGZ1bmN0aW9uKHR5cGUsIGxpc3RlbmVyKSB7XG4gIHZhciBtO1xuXG4gIGlmICghaXNGdW5jdGlvbihsaXN0ZW5lcikpXG4gICAgdGhyb3cgVHlwZUVycm9yKCdsaXN0ZW5lciBtdXN0IGJlIGEgZnVuY3Rpb24nKTtcblxuICBpZiAoIXRoaXMuX2V2ZW50cylcbiAgICB0aGlzLl9ldmVudHMgPSB7fTtcblxuICAvLyBUbyBhdm9pZCByZWN1cnNpb24gaW4gdGhlIGNhc2UgdGhhdCB0eXBlID09PSBcIm5ld0xpc3RlbmVyXCIhIEJlZm9yZVxuICAvLyBhZGRpbmcgaXQgdG8gdGhlIGxpc3RlbmVycywgZmlyc3QgZW1pdCBcIm5ld0xpc3RlbmVyXCIuXG4gIGlmICh0aGlzLl9ldmVudHMubmV3TGlzdGVuZXIpXG4gICAgdGhpcy5lbWl0KCduZXdMaXN0ZW5lcicsIHR5cGUsXG4gICAgICAgICAgICAgIGlzRnVuY3Rpb24obGlzdGVuZXIubGlzdGVuZXIpID9cbiAgICAgICAgICAgICAgbGlzdGVuZXIubGlzdGVuZXIgOiBsaXN0ZW5lcik7XG5cbiAgaWYgKCF0aGlzLl9ldmVudHNbdHlwZV0pXG4gICAgLy8gT3B0aW1pemUgdGhlIGNhc2Ugb2Ygb25lIGxpc3RlbmVyLiBEb24ndCBuZWVkIHRoZSBleHRyYSBhcnJheSBvYmplY3QuXG4gICAgdGhpcy5fZXZlbnRzW3R5cGVdID0gbGlzdGVuZXI7XG4gIGVsc2UgaWYgKGlzT2JqZWN0KHRoaXMuX2V2ZW50c1t0eXBlXSkpXG4gICAgLy8gSWYgd2UndmUgYWxyZWFkeSBnb3QgYW4gYXJyYXksIGp1c3QgYXBwZW5kLlxuICAgIHRoaXMuX2V2ZW50c1t0eXBlXS5wdXNoKGxpc3RlbmVyKTtcbiAgZWxzZVxuICAgIC8vIEFkZGluZyB0aGUgc2Vjb25kIGVsZW1lbnQsIG5lZWQgdG8gY2hhbmdlIHRvIGFycmF5LlxuICAgIHRoaXMuX2V2ZW50c1t0eXBlXSA9IFt0aGlzLl9ldmVudHNbdHlwZV0sIGxpc3RlbmVyXTtcblxuICAvLyBDaGVjayBmb3IgbGlzdGVuZXIgbGVha1xuICBpZiAoaXNPYmplY3QodGhpcy5fZXZlbnRzW3R5cGVdKSAmJiAhdGhpcy5fZXZlbnRzW3R5cGVdLndhcm5lZCkge1xuICAgIGlmICghaXNVbmRlZmluZWQodGhpcy5fbWF4TGlzdGVuZXJzKSkge1xuICAgICAgbSA9IHRoaXMuX21heExpc3RlbmVycztcbiAgICB9IGVsc2Uge1xuICAgICAgbSA9IEV2ZW50RW1pdHRlci5kZWZhdWx0TWF4TGlzdGVuZXJzO1xuICAgIH1cblxuICAgIGlmIChtICYmIG0gPiAwICYmIHRoaXMuX2V2ZW50c1t0eXBlXS5sZW5ndGggPiBtKSB7XG4gICAgICB0aGlzLl9ldmVudHNbdHlwZV0ud2FybmVkID0gdHJ1ZTtcbiAgICAgIGNvbnNvbGUuZXJyb3IoJyhub2RlKSB3YXJuaW5nOiBwb3NzaWJsZSBFdmVudEVtaXR0ZXIgbWVtb3J5ICcgK1xuICAgICAgICAgICAgICAgICAgICAnbGVhayBkZXRlY3RlZC4gJWQgbGlzdGVuZXJzIGFkZGVkLiAnICtcbiAgICAgICAgICAgICAgICAgICAgJ1VzZSBlbWl0dGVyLnNldE1heExpc3RlbmVycygpIHRvIGluY3JlYXNlIGxpbWl0LicsXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX2V2ZW50c1t0eXBlXS5sZW5ndGgpO1xuICAgICAgaWYgKHR5cGVvZiBjb25zb2xlLnRyYWNlID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIC8vIG5vdCBzdXBwb3J0ZWQgaW4gSUUgMTBcbiAgICAgICAgY29uc29sZS50cmFjZSgpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0aGlzO1xufTtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5vbiA9IEV2ZW50RW1pdHRlci5wcm90b3R5cGUuYWRkTGlzdGVuZXI7XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUub25jZSA9IGZ1bmN0aW9uKHR5cGUsIGxpc3RlbmVyKSB7XG4gIGlmICghaXNGdW5jdGlvbihsaXN0ZW5lcikpXG4gICAgdGhyb3cgVHlwZUVycm9yKCdsaXN0ZW5lciBtdXN0IGJlIGEgZnVuY3Rpb24nKTtcblxuICB2YXIgZmlyZWQgPSBmYWxzZTtcblxuICBmdW5jdGlvbiBnKCkge1xuICAgIHRoaXMucmVtb3ZlTGlzdGVuZXIodHlwZSwgZyk7XG5cbiAgICBpZiAoIWZpcmVkKSB7XG4gICAgICBmaXJlZCA9IHRydWU7XG4gICAgICBsaXN0ZW5lci5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgIH1cbiAgfVxuXG4gIGcubGlzdGVuZXIgPSBsaXN0ZW5lcjtcbiAgdGhpcy5vbih0eXBlLCBnKTtcblxuICByZXR1cm4gdGhpcztcbn07XG5cbi8vIGVtaXRzIGEgJ3JlbW92ZUxpc3RlbmVyJyBldmVudCBpZmYgdGhlIGxpc3RlbmVyIHdhcyByZW1vdmVkXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLnJlbW92ZUxpc3RlbmVyID0gZnVuY3Rpb24odHlwZSwgbGlzdGVuZXIpIHtcbiAgdmFyIGxpc3QsIHBvc2l0aW9uLCBsZW5ndGgsIGk7XG5cbiAgaWYgKCFpc0Z1bmN0aW9uKGxpc3RlbmVyKSlcbiAgICB0aHJvdyBUeXBlRXJyb3IoJ2xpc3RlbmVyIG11c3QgYmUgYSBmdW5jdGlvbicpO1xuXG4gIGlmICghdGhpcy5fZXZlbnRzIHx8ICF0aGlzLl9ldmVudHNbdHlwZV0pXG4gICAgcmV0dXJuIHRoaXM7XG5cbiAgbGlzdCA9IHRoaXMuX2V2ZW50c1t0eXBlXTtcbiAgbGVuZ3RoID0gbGlzdC5sZW5ndGg7XG4gIHBvc2l0aW9uID0gLTE7XG5cbiAgaWYgKGxpc3QgPT09IGxpc3RlbmVyIHx8XG4gICAgICAoaXNGdW5jdGlvbihsaXN0Lmxpc3RlbmVyKSAmJiBsaXN0Lmxpc3RlbmVyID09PSBsaXN0ZW5lcikpIHtcbiAgICBkZWxldGUgdGhpcy5fZXZlbnRzW3R5cGVdO1xuICAgIGlmICh0aGlzLl9ldmVudHMucmVtb3ZlTGlzdGVuZXIpXG4gICAgICB0aGlzLmVtaXQoJ3JlbW92ZUxpc3RlbmVyJywgdHlwZSwgbGlzdGVuZXIpO1xuXG4gIH0gZWxzZSBpZiAoaXNPYmplY3QobGlzdCkpIHtcbiAgICBmb3IgKGkgPSBsZW5ndGg7IGktLSA+IDA7KSB7XG4gICAgICBpZiAobGlzdFtpXSA9PT0gbGlzdGVuZXIgfHxcbiAgICAgICAgICAobGlzdFtpXS5saXN0ZW5lciAmJiBsaXN0W2ldLmxpc3RlbmVyID09PSBsaXN0ZW5lcikpIHtcbiAgICAgICAgcG9zaXRpb24gPSBpO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAocG9zaXRpb24gPCAwKVxuICAgICAgcmV0dXJuIHRoaXM7XG5cbiAgICBpZiAobGlzdC5sZW5ndGggPT09IDEpIHtcbiAgICAgIGxpc3QubGVuZ3RoID0gMDtcbiAgICAgIGRlbGV0ZSB0aGlzLl9ldmVudHNbdHlwZV07XG4gICAgfSBlbHNlIHtcbiAgICAgIGxpc3Quc3BsaWNlKHBvc2l0aW9uLCAxKTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5fZXZlbnRzLnJlbW92ZUxpc3RlbmVyKVxuICAgICAgdGhpcy5lbWl0KCdyZW1vdmVMaXN0ZW5lcicsIHR5cGUsIGxpc3RlbmVyKTtcbiAgfVxuXG4gIHJldHVybiB0aGlzO1xufTtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5yZW1vdmVBbGxMaXN0ZW5lcnMgPSBmdW5jdGlvbih0eXBlKSB7XG4gIHZhciBrZXksIGxpc3RlbmVycztcblxuICBpZiAoIXRoaXMuX2V2ZW50cylcbiAgICByZXR1cm4gdGhpcztcblxuICAvLyBub3QgbGlzdGVuaW5nIGZvciByZW1vdmVMaXN0ZW5lciwgbm8gbmVlZCB0byBlbWl0XG4gIGlmICghdGhpcy5fZXZlbnRzLnJlbW92ZUxpc3RlbmVyKSB7XG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApXG4gICAgICB0aGlzLl9ldmVudHMgPSB7fTtcbiAgICBlbHNlIGlmICh0aGlzLl9ldmVudHNbdHlwZV0pXG4gICAgICBkZWxldGUgdGhpcy5fZXZlbnRzW3R5cGVdO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLy8gZW1pdCByZW1vdmVMaXN0ZW5lciBmb3IgYWxsIGxpc3RlbmVycyBvbiBhbGwgZXZlbnRzXG4gIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgZm9yIChrZXkgaW4gdGhpcy5fZXZlbnRzKSB7XG4gICAgICBpZiAoa2V5ID09PSAncmVtb3ZlTGlzdGVuZXInKSBjb250aW51ZTtcbiAgICAgIHRoaXMucmVtb3ZlQWxsTGlzdGVuZXJzKGtleSk7XG4gICAgfVxuICAgIHRoaXMucmVtb3ZlQWxsTGlzdGVuZXJzKCdyZW1vdmVMaXN0ZW5lcicpO1xuICAgIHRoaXMuX2V2ZW50cyA9IHt9O1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgbGlzdGVuZXJzID0gdGhpcy5fZXZlbnRzW3R5cGVdO1xuXG4gIGlmIChpc0Z1bmN0aW9uKGxpc3RlbmVycykpIHtcbiAgICB0aGlzLnJlbW92ZUxpc3RlbmVyKHR5cGUsIGxpc3RlbmVycyk7XG4gIH0gZWxzZSBpZiAobGlzdGVuZXJzKSB7XG4gICAgLy8gTElGTyBvcmRlclxuICAgIHdoaWxlIChsaXN0ZW5lcnMubGVuZ3RoKVxuICAgICAgdGhpcy5yZW1vdmVMaXN0ZW5lcih0eXBlLCBsaXN0ZW5lcnNbbGlzdGVuZXJzLmxlbmd0aCAtIDFdKTtcbiAgfVxuICBkZWxldGUgdGhpcy5fZXZlbnRzW3R5cGVdO1xuXG4gIHJldHVybiB0aGlzO1xufTtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5saXN0ZW5lcnMgPSBmdW5jdGlvbih0eXBlKSB7XG4gIHZhciByZXQ7XG4gIGlmICghdGhpcy5fZXZlbnRzIHx8ICF0aGlzLl9ldmVudHNbdHlwZV0pXG4gICAgcmV0ID0gW107XG4gIGVsc2UgaWYgKGlzRnVuY3Rpb24odGhpcy5fZXZlbnRzW3R5cGVdKSlcbiAgICByZXQgPSBbdGhpcy5fZXZlbnRzW3R5cGVdXTtcbiAgZWxzZVxuICAgIHJldCA9IHRoaXMuX2V2ZW50c1t0eXBlXS5zbGljZSgpO1xuICByZXR1cm4gcmV0O1xufTtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5saXN0ZW5lckNvdW50ID0gZnVuY3Rpb24odHlwZSkge1xuICBpZiAodGhpcy5fZXZlbnRzKSB7XG4gICAgdmFyIGV2bGlzdGVuZXIgPSB0aGlzLl9ldmVudHNbdHlwZV07XG5cbiAgICBpZiAoaXNGdW5jdGlvbihldmxpc3RlbmVyKSlcbiAgICAgIHJldHVybiAxO1xuICAgIGVsc2UgaWYgKGV2bGlzdGVuZXIpXG4gICAgICByZXR1cm4gZXZsaXN0ZW5lci5sZW5ndGg7XG4gIH1cbiAgcmV0dXJuIDA7XG59O1xuXG5FdmVudEVtaXR0ZXIubGlzdGVuZXJDb3VudCA9IGZ1bmN0aW9uKGVtaXR0ZXIsIHR5cGUpIHtcbiAgcmV0dXJuIGVtaXR0ZXIubGlzdGVuZXJDb3VudCh0eXBlKTtcbn07XG5cbmZ1bmN0aW9uIGlzRnVuY3Rpb24oYXJnKSB7XG4gIHJldHVybiB0eXBlb2YgYXJnID09PSAnZnVuY3Rpb24nO1xufVxuXG5mdW5jdGlvbiBpc051bWJlcihhcmcpIHtcbiAgcmV0dXJuIHR5cGVvZiBhcmcgPT09ICdudW1iZXInO1xufVxuXG5mdW5jdGlvbiBpc09iamVjdChhcmcpIHtcbiAgcmV0dXJuIHR5cGVvZiBhcmcgPT09ICdvYmplY3QnICYmIGFyZyAhPT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gaXNVbmRlZmluZWQoYXJnKSB7XG4gIHJldHVybiBhcmcgPT09IHZvaWQgMDtcbn1cbiIsIi8vIHNoaW0gZm9yIHVzaW5nIHByb2Nlc3MgaW4gYnJvd3NlclxudmFyIHByb2Nlc3MgPSBtb2R1bGUuZXhwb3J0cyA9IHt9O1xuXG4vLyBjYWNoZWQgZnJvbSB3aGF0ZXZlciBnbG9iYWwgaXMgcHJlc2VudCBzbyB0aGF0IHRlc3QgcnVubmVycyB0aGF0IHN0dWIgaXRcbi8vIGRvbid0IGJyZWFrIHRoaW5ncy4gIEJ1dCB3ZSBuZWVkIHRvIHdyYXAgaXQgaW4gYSB0cnkgY2F0Y2ggaW4gY2FzZSBpdCBpc1xuLy8gd3JhcHBlZCBpbiBzdHJpY3QgbW9kZSBjb2RlIHdoaWNoIGRvZXNuJ3QgZGVmaW5lIGFueSBnbG9iYWxzLiAgSXQncyBpbnNpZGUgYVxuLy8gZnVuY3Rpb24gYmVjYXVzZSB0cnkvY2F0Y2hlcyBkZW9wdGltaXplIGluIGNlcnRhaW4gZW5naW5lcy5cblxudmFyIGNhY2hlZFNldFRpbWVvdXQ7XG52YXIgY2FjaGVkQ2xlYXJUaW1lb3V0O1xuXG5mdW5jdGlvbiBkZWZhdWx0U2V0VGltb3V0KCkge1xuICAgIHRocm93IG5ldyBFcnJvcignc2V0VGltZW91dCBoYXMgbm90IGJlZW4gZGVmaW5lZCcpO1xufVxuZnVuY3Rpb24gZGVmYXVsdENsZWFyVGltZW91dCAoKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdjbGVhclRpbWVvdXQgaGFzIG5vdCBiZWVuIGRlZmluZWQnKTtcbn1cbihmdW5jdGlvbiAoKSB7XG4gICAgdHJ5IHtcbiAgICAgICAgaWYgKHR5cGVvZiBzZXRUaW1lb3V0ID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICBjYWNoZWRTZXRUaW1lb3V0ID0gc2V0VGltZW91dDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNhY2hlZFNldFRpbWVvdXQgPSBkZWZhdWx0U2V0VGltb3V0O1xuICAgICAgICB9XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBjYWNoZWRTZXRUaW1lb3V0ID0gZGVmYXVsdFNldFRpbW91dDtcbiAgICB9XG4gICAgdHJ5IHtcbiAgICAgICAgaWYgKHR5cGVvZiBjbGVhclRpbWVvdXQgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIGNhY2hlZENsZWFyVGltZW91dCA9IGNsZWFyVGltZW91dDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNhY2hlZENsZWFyVGltZW91dCA9IGRlZmF1bHRDbGVhclRpbWVvdXQ7XG4gICAgICAgIH1cbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGNhY2hlZENsZWFyVGltZW91dCA9IGRlZmF1bHRDbGVhclRpbWVvdXQ7XG4gICAgfVxufSAoKSlcbmZ1bmN0aW9uIHJ1blRpbWVvdXQoZnVuKSB7XG4gICAgaWYgKGNhY2hlZFNldFRpbWVvdXQgPT09IHNldFRpbWVvdXQpIHtcbiAgICAgICAgLy9ub3JtYWwgZW52aXJvbWVudHMgaW4gc2FuZSBzaXR1YXRpb25zXG4gICAgICAgIHJldHVybiBzZXRUaW1lb3V0KGZ1biwgMCk7XG4gICAgfVxuICAgIC8vIGlmIHNldFRpbWVvdXQgd2Fzbid0IGF2YWlsYWJsZSBidXQgd2FzIGxhdHRlciBkZWZpbmVkXG4gICAgaWYgKChjYWNoZWRTZXRUaW1lb3V0ID09PSBkZWZhdWx0U2V0VGltb3V0IHx8ICFjYWNoZWRTZXRUaW1lb3V0KSAmJiBzZXRUaW1lb3V0KSB7XG4gICAgICAgIGNhY2hlZFNldFRpbWVvdXQgPSBzZXRUaW1lb3V0O1xuICAgICAgICByZXR1cm4gc2V0VGltZW91dChmdW4sIDApO1xuICAgIH1cbiAgICB0cnkge1xuICAgICAgICAvLyB3aGVuIHdoZW4gc29tZWJvZHkgaGFzIHNjcmV3ZWQgd2l0aCBzZXRUaW1lb3V0IGJ1dCBubyBJLkUuIG1hZGRuZXNzXG4gICAgICAgIHJldHVybiBjYWNoZWRTZXRUaW1lb3V0KGZ1biwgMCk7XG4gICAgfSBjYXRjaChlKXtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIC8vIFdoZW4gd2UgYXJlIGluIEkuRS4gYnV0IHRoZSBzY3JpcHQgaGFzIGJlZW4gZXZhbGVkIHNvIEkuRS4gZG9lc24ndCB0cnVzdCB0aGUgZ2xvYmFsIG9iamVjdCB3aGVuIGNhbGxlZCBub3JtYWxseVxuICAgICAgICAgICAgcmV0dXJuIGNhY2hlZFNldFRpbWVvdXQuY2FsbChudWxsLCBmdW4sIDApO1xuICAgICAgICB9IGNhdGNoKGUpe1xuICAgICAgICAgICAgLy8gc2FtZSBhcyBhYm92ZSBidXQgd2hlbiBpdCdzIGEgdmVyc2lvbiBvZiBJLkUuIHRoYXQgbXVzdCBoYXZlIHRoZSBnbG9iYWwgb2JqZWN0IGZvciAndGhpcycsIGhvcGZ1bGx5IG91ciBjb250ZXh0IGNvcnJlY3Qgb3RoZXJ3aXNlIGl0IHdpbGwgdGhyb3cgYSBnbG9iYWwgZXJyb3JcbiAgICAgICAgICAgIHJldHVybiBjYWNoZWRTZXRUaW1lb3V0LmNhbGwodGhpcywgZnVuLCAwKTtcbiAgICAgICAgfVxuICAgIH1cblxuXG59XG5mdW5jdGlvbiBydW5DbGVhclRpbWVvdXQobWFya2VyKSB7XG4gICAgaWYgKGNhY2hlZENsZWFyVGltZW91dCA9PT0gY2xlYXJUaW1lb3V0KSB7XG4gICAgICAgIC8vbm9ybWFsIGVudmlyb21lbnRzIGluIHNhbmUgc2l0dWF0aW9uc1xuICAgICAgICByZXR1cm4gY2xlYXJUaW1lb3V0KG1hcmtlcik7XG4gICAgfVxuICAgIC8vIGlmIGNsZWFyVGltZW91dCB3YXNuJ3QgYXZhaWxhYmxlIGJ1dCB3YXMgbGF0dGVyIGRlZmluZWRcbiAgICBpZiAoKGNhY2hlZENsZWFyVGltZW91dCA9PT0gZGVmYXVsdENsZWFyVGltZW91dCB8fCAhY2FjaGVkQ2xlYXJUaW1lb3V0KSAmJiBjbGVhclRpbWVvdXQpIHtcbiAgICAgICAgY2FjaGVkQ2xlYXJUaW1lb3V0ID0gY2xlYXJUaW1lb3V0O1xuICAgICAgICByZXR1cm4gY2xlYXJUaW1lb3V0KG1hcmtlcik7XG4gICAgfVxuICAgIHRyeSB7XG4gICAgICAgIC8vIHdoZW4gd2hlbiBzb21lYm9keSBoYXMgc2NyZXdlZCB3aXRoIHNldFRpbWVvdXQgYnV0IG5vIEkuRS4gbWFkZG5lc3NcbiAgICAgICAgcmV0dXJuIGNhY2hlZENsZWFyVGltZW91dChtYXJrZXIpO1xuICAgIH0gY2F0Y2ggKGUpe1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgLy8gV2hlbiB3ZSBhcmUgaW4gSS5FLiBidXQgdGhlIHNjcmlwdCBoYXMgYmVlbiBldmFsZWQgc28gSS5FLiBkb2Vzbid0ICB0cnVzdCB0aGUgZ2xvYmFsIG9iamVjdCB3aGVuIGNhbGxlZCBub3JtYWxseVxuICAgICAgICAgICAgcmV0dXJuIGNhY2hlZENsZWFyVGltZW91dC5jYWxsKG51bGwsIG1hcmtlcik7XG4gICAgICAgIH0gY2F0Y2ggKGUpe1xuICAgICAgICAgICAgLy8gc2FtZSBhcyBhYm92ZSBidXQgd2hlbiBpdCdzIGEgdmVyc2lvbiBvZiBJLkUuIHRoYXQgbXVzdCBoYXZlIHRoZSBnbG9iYWwgb2JqZWN0IGZvciAndGhpcycsIGhvcGZ1bGx5IG91ciBjb250ZXh0IGNvcnJlY3Qgb3RoZXJ3aXNlIGl0IHdpbGwgdGhyb3cgYSBnbG9iYWwgZXJyb3IuXG4gICAgICAgICAgICAvLyBTb21lIHZlcnNpb25zIG9mIEkuRS4gaGF2ZSBkaWZmZXJlbnQgcnVsZXMgZm9yIGNsZWFyVGltZW91dCB2cyBzZXRUaW1lb3V0XG4gICAgICAgICAgICByZXR1cm4gY2FjaGVkQ2xlYXJUaW1lb3V0LmNhbGwodGhpcywgbWFya2VyKTtcbiAgICAgICAgfVxuICAgIH1cblxuXG5cbn1cbnZhciBxdWV1ZSA9IFtdO1xudmFyIGRyYWluaW5nID0gZmFsc2U7XG52YXIgY3VycmVudFF1ZXVlO1xudmFyIHF1ZXVlSW5kZXggPSAtMTtcblxuZnVuY3Rpb24gY2xlYW5VcE5leHRUaWNrKCkge1xuICAgIGlmICghZHJhaW5pbmcgfHwgIWN1cnJlbnRRdWV1ZSkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIGRyYWluaW5nID0gZmFsc2U7XG4gICAgaWYgKGN1cnJlbnRRdWV1ZS5sZW5ndGgpIHtcbiAgICAgICAgcXVldWUgPSBjdXJyZW50UXVldWUuY29uY2F0KHF1ZXVlKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBxdWV1ZUluZGV4ID0gLTE7XG4gICAgfVxuICAgIGlmIChxdWV1ZS5sZW5ndGgpIHtcbiAgICAgICAgZHJhaW5RdWV1ZSgpO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gZHJhaW5RdWV1ZSgpIHtcbiAgICBpZiAoZHJhaW5pbmcpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB2YXIgdGltZW91dCA9IHJ1blRpbWVvdXQoY2xlYW5VcE5leHRUaWNrKTtcbiAgICBkcmFpbmluZyA9IHRydWU7XG5cbiAgICB2YXIgbGVuID0gcXVldWUubGVuZ3RoO1xuICAgIHdoaWxlKGxlbikge1xuICAgICAgICBjdXJyZW50UXVldWUgPSBxdWV1ZTtcbiAgICAgICAgcXVldWUgPSBbXTtcbiAgICAgICAgd2hpbGUgKCsrcXVldWVJbmRleCA8IGxlbikge1xuICAgICAgICAgICAgaWYgKGN1cnJlbnRRdWV1ZSkge1xuICAgICAgICAgICAgICAgIGN1cnJlbnRRdWV1ZVtxdWV1ZUluZGV4XS5ydW4oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBxdWV1ZUluZGV4ID0gLTE7XG4gICAgICAgIGxlbiA9IHF1ZXVlLmxlbmd0aDtcbiAgICB9XG4gICAgY3VycmVudFF1ZXVlID0gbnVsbDtcbiAgICBkcmFpbmluZyA9IGZhbHNlO1xuICAgIHJ1bkNsZWFyVGltZW91dCh0aW1lb3V0KTtcbn1cblxucHJvY2Vzcy5uZXh0VGljayA9IGZ1bmN0aW9uIChmdW4pIHtcbiAgICB2YXIgYXJncyA9IG5ldyBBcnJheShhcmd1bWVudHMubGVuZ3RoIC0gMSk7XG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPiAxKSB7XG4gICAgICAgIGZvciAodmFyIGkgPSAxOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBhcmdzW2kgLSAxXSA9IGFyZ3VtZW50c1tpXTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBxdWV1ZS5wdXNoKG5ldyBJdGVtKGZ1biwgYXJncykpO1xuICAgIGlmIChxdWV1ZS5sZW5ndGggPT09IDEgJiYgIWRyYWluaW5nKSB7XG4gICAgICAgIHJ1blRpbWVvdXQoZHJhaW5RdWV1ZSk7XG4gICAgfVxufTtcblxuLy8gdjggbGlrZXMgcHJlZGljdGlibGUgb2JqZWN0c1xuZnVuY3Rpb24gSXRlbShmdW4sIGFycmF5KSB7XG4gICAgdGhpcy5mdW4gPSBmdW47XG4gICAgdGhpcy5hcnJheSA9IGFycmF5O1xufVxuSXRlbS5wcm90b3R5cGUucnVuID0gZnVuY3Rpb24gKCkge1xuICAgIHRoaXMuZnVuLmFwcGx5KG51bGwsIHRoaXMuYXJyYXkpO1xufTtcbnByb2Nlc3MudGl0bGUgPSAnYnJvd3Nlcic7XG5wcm9jZXNzLmJyb3dzZXIgPSB0cnVlO1xucHJvY2Vzcy5lbnYgPSB7fTtcbnByb2Nlc3MuYXJndiA9IFtdO1xucHJvY2Vzcy52ZXJzaW9uID0gJyc7IC8vIGVtcHR5IHN0cmluZyB0byBhdm9pZCByZWdleHAgaXNzdWVzXG5wcm9jZXNzLnZlcnNpb25zID0ge307XG5cbmZ1bmN0aW9uIG5vb3AoKSB7fVxuXG5wcm9jZXNzLm9uID0gbm9vcDtcbnByb2Nlc3MuYWRkTGlzdGVuZXIgPSBub29wO1xucHJvY2Vzcy5vbmNlID0gbm9vcDtcbnByb2Nlc3Mub2ZmID0gbm9vcDtcbnByb2Nlc3MucmVtb3ZlTGlzdGVuZXIgPSBub29wO1xucHJvY2Vzcy5yZW1vdmVBbGxMaXN0ZW5lcnMgPSBub29wO1xucHJvY2Vzcy5lbWl0ID0gbm9vcDtcbnByb2Nlc3MucHJlcGVuZExpc3RlbmVyID0gbm9vcDtcbnByb2Nlc3MucHJlcGVuZE9uY2VMaXN0ZW5lciA9IG5vb3A7XG5cbnByb2Nlc3MubGlzdGVuZXJzID0gZnVuY3Rpb24gKG5hbWUpIHsgcmV0dXJuIFtdIH1cblxucHJvY2Vzcy5iaW5kaW5nID0gZnVuY3Rpb24gKG5hbWUpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3Byb2Nlc3MuYmluZGluZyBpcyBub3Qgc3VwcG9ydGVkJyk7XG59O1xuXG5wcm9jZXNzLmN3ZCA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuICcvJyB9O1xucHJvY2Vzcy5jaGRpciA9IGZ1bmN0aW9uIChkaXIpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3Byb2Nlc3MuY2hkaXIgaXMgbm90IHN1cHBvcnRlZCcpO1xufTtcbnByb2Nlc3MudW1hc2sgPSBmdW5jdGlvbigpIHsgcmV0dXJuIDA7IH07XG4iLCIvKiBlc2xpbnQtZGlzYWJsZSBrZXktc3BhY2luZyAqL1xuXG5leHBvcnRzLlJPT01fT1BUSU9OUyA9XG57XG5cdHJlcXVlc3RUaW1lb3V0OiAxMDAwMCxcblx0dHJhbnNwb3J0T3B0aW9uczpcblx0e1xuXHRcdHRjcDogZmFsc2Vcblx0fSxcblx0X190dXJuU2VydmVyczpcblx0W1xuXHRcdHtcblx0XHRcdHVybHM6IFsgJ3R1cm46d29ya2VyMi52ZXJzYXRpY2EuY29tOjM0Nzg/dHJhbnNwb3J0PXVkcCcgXSxcblx0XHRcdHVzZXJuYW1lOiAndGVzdHVzZXIxJyxcblx0XHRcdGNyZWRlbnRpYWw6ICd0ZXN0cGFzc3dkMSdcblx0XHR9XG5cdF0sXG5cdGhpZGRlbjogZmFsc2Vcbn07XG5cbmV4cG9ydHMuUk9PTV9SVFBfQ0FQQUJJTElUSUVTID1cbntcblx0Y29kZWNzOlxuXHRbXG5cdFx0e1xuXHRcdFx0bmFtZTogJ1BDTUEnLFxuXHRcdFx0bWltZVR5cGU6ICdhdWRpby9QQ01BJyxcblx0XHRcdGtpbmQ6ICdhdWRpbycsXG5cdFx0XHRjbG9ja1JhdGU6IDgwMDAsXG5cdFx0XHRwcmVmZXJyZWRQYXlsb2FkVHlwZTogOCxcblx0XHRcdHJ0Y3BGZWVkYmFjazogW10sXG5cdFx0XHRwYXJhbWV0ZXJzOiB7fVxuXHRcdH0sXG5cdFx0e1xuXHRcdFx0bmFtZTogJ29wdXMnLFxuXHRcdFx0bWltZVR5cGU6ICdhdWRpby9vcHVzJyxcblx0XHRcdGtpbmQ6ICdhdWRpbycsXG5cdFx0XHRjbG9ja1JhdGU6IDQ4MDAwLFxuXHRcdFx0Y2hhbm5lbHM6IDIsXG5cdFx0XHRwcmVmZXJyZWRQYXlsb2FkVHlwZTogOTYsXG5cdFx0XHRydGNwRmVlZGJhY2s6IFtdLFxuXHRcdFx0cGFyYW1ldGVyczoge31cblx0XHR9LFxuXHRcdHtcblx0XHRcdG5hbWU6ICdTSUxLJyxcblx0XHRcdG1pbWVUeXBlOiAnYXVkaW8vU0lMSycsXG5cdFx0XHRraW5kOiAnYXVkaW8nLFxuXHRcdFx0Y2xvY2tSYXRlOiAxNjAwMCxcblx0XHRcdHByZWZlcnJlZFBheWxvYWRUeXBlOiA5Nyxcblx0XHRcdHJ0Y3BGZWVkYmFjazogW10sXG5cdFx0XHRwYXJhbWV0ZXJzOiB7fVxuXHRcdH0sXG5cdFx0e1xuXHRcdFx0bmFtZTogJ1ZQOScsXG5cdFx0XHRtaW1lVHlwZTogJ3ZpZGVvL1ZQOScsXG5cdFx0XHRraW5kOiAndmlkZW8nLFxuXHRcdFx0Y2xvY2tSYXRlOiA5MDAwMCxcblx0XHRcdHByZWZlcnJlZFBheWxvYWRUeXBlOiAxMDIsXG5cdFx0XHRydGNwRmVlZGJhY2s6XG5cdFx0XHRbXG5cdFx0XHRcdHtcblx0XHRcdFx0XHRwYXJhbWV0ZXI6ICcnLFxuXHRcdFx0XHRcdHR5cGU6ICduYWNrJ1xuXHRcdFx0XHR9LFxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0cGFyYW1ldGVyOiAncGxpJyxcblx0XHRcdFx0XHR0eXBlOiAnbmFjaydcblx0XHRcdFx0fSxcblx0XHRcdFx0e1xuXHRcdFx0XHRcdHBhcmFtZXRlcjogJycsXG5cdFx0XHRcdFx0dHlwZTogJ2dvb2ctcmVtYidcblx0XHRcdFx0fSxcblx0XHRcdFx0e1xuXHRcdFx0XHRcdHBhcmFtZXRlcjogJ2JhcicsXG5cdFx0XHRcdFx0dHlwZTogJ2Zvbydcblx0XHRcdFx0fVxuXHRcdFx0XSxcblx0XHRcdHBhcmFtZXRlcnM6IHt9XG5cdFx0fSxcblx0XHR7XG5cdFx0XHRuYW1lOiAncnR4Jyxcblx0XHRcdG1pbWVUeXBlOiAndmlkZW8vcnR4Jyxcblx0XHRcdGtpbmQ6ICd2aWRlbycsXG5cdFx0XHRjbG9ja1JhdGU6IDkwMDAwLFxuXHRcdFx0cHJlZmVycmVkUGF5bG9hZFR5cGU6IDEwMyxcblx0XHRcdHJ0Y3BGZWVkYmFjazogW10sXG5cdFx0XHRwYXJhbWV0ZXJzOiB7XG5cdFx0XHRcdGFwdDogMTAyXG5cdFx0XHR9XG5cdFx0fSxcblx0XHR7XG5cdFx0XHRuYW1lOiAnVlA4Jyxcblx0XHRcdG1pbWVUeXBlOiAndmlkZW8vVlA4Jyxcblx0XHRcdGtpbmQ6ICd2aWRlbycsXG5cdFx0XHRjbG9ja1JhdGU6IDkwMDAwLFxuXHRcdFx0cHJlZmVycmVkUGF5bG9hZFR5cGU6IDEwMCxcblx0XHRcdHJ0Y3BGZWVkYmFjazpcblx0XHRcdFtcblx0XHRcdFx0e1xuXHRcdFx0XHRcdHBhcmFtZXRlcjogJycsXG5cdFx0XHRcdFx0dHlwZTogJ25hY2snXG5cdFx0XHRcdH0sXG5cdFx0XHRcdHtcblx0XHRcdFx0XHRwYXJhbWV0ZXI6ICdwbGknLFxuXHRcdFx0XHRcdHR5cGU6ICduYWNrJ1xuXHRcdFx0XHR9LFxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0cGFyYW1ldGVyOiAnJyxcblx0XHRcdFx0XHR0eXBlOiAnZ29vZy1yZW1iJ1xuXHRcdFx0XHR9LFxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0cGFyYW1ldGVyOiAnYmFyJyxcblx0XHRcdFx0XHR0eXBlOiAnZm9vJ1xuXHRcdFx0XHR9XG5cdFx0XHRdLFxuXHRcdFx0cGFyYW1ldGVyczoge31cblx0XHR9LFxuXHRcdHtcblx0XHRcdG5hbWU6ICdydHgnLFxuXHRcdFx0bWltZVR5cGU6ICd2aWRlby9ydHgnLFxuXHRcdFx0a2luZDogJ3ZpZGVvJyxcblx0XHRcdGNsb2NrUmF0ZTogOTAwMDAsXG5cdFx0XHRwcmVmZXJyZWRQYXlsb2FkVHlwZTogMTAxLFxuXHRcdFx0cnRjcEZlZWRiYWNrOiBbXSxcblx0XHRcdHBhcmFtZXRlcnM6IHtcblx0XHRcdFx0YXB0OiAxMDBcblx0XHRcdH1cblx0XHR9XG5cdF0sXG5cdGhlYWRlckV4dGVuc2lvbnM6IFtcblx0XHR7XG5cdFx0XHRraW5kOiAnYXVkaW8nLFxuXHRcdFx0dXJpOiAndXJuOmlldGY6cGFyYW1zOnJ0cC1oZHJleHQ6c3NyYy1hdWRpby1sZXZlbCcsXG5cdFx0XHRwcmVmZXJyZWRJZDogMTBcblx0XHR9LFxuXHRcdHtcblx0XHRcdGtpbmQ6ICd2aWRlbycsXG5cdFx0XHR1cmk6ICdodHRwOi8vd3d3LndlYnJ0Yy5vcmcvZXhwZXJpbWVudHMvcnRwLWhkcmV4dC9hYnMtc2VuZC10aW1lJyxcblx0XHRcdHByZWZlcnJlZElkOiAxMVxuXHRcdH0sXG5cdFx0e1xuXHRcdFx0a2luZDogJ3ZpZGVvJyxcblx0XHRcdHVyaTogJ2h0dHA6Ly9mb28uYmFyJyxcblx0XHRcdHByZWZlcnJlZElkOiAxMlxuXHRcdH1cblx0XSxcblx0ZmVjTWVjaGFuaXNtczogW11cbn07XG5cbmV4cG9ydHMuUVVFUllfUk9PTV9SRVNQT05TRSA9XG57XG5cdHJ0cENhcGFiaWxpdGllczogZXhwb3J0cy5ST09NX1JUUF9DQVBBQklMSVRJRVNcbn07XG5cbmV4cG9ydHMuSk9JTl9ST09NX1JFU1BPTlNFID1cbntcblx0cGVlcnM6XG5cdFtcblx0XHR7XG5cdFx0XHRuYW1lOiAnYWxpY2UnLFxuXHRcdFx0YXBwRGF0YTogJ0FsaWNlIGlQYWQgUHJvJyxcblx0XHRcdGNvbnN1bWVyczpcblx0XHRcdFtcblx0XHRcdFx0e1xuXHRcdFx0XHRcdGlkOiAzMzMzLFxuXHRcdFx0XHRcdGtpbmQ6ICdhdWRpbycsXG5cdFx0XHRcdFx0cGF1c2VkOiBmYWxzZSxcblx0XHRcdFx0XHRhcHBEYXRhOiAnQUxJQ0VfTUlDJyxcblx0XHRcdFx0XHRydHBQYXJhbWV0ZXJzOlxuXHRcdFx0XHRcdHtcblx0XHRcdFx0XHRcdG11eElkOiBudWxsLFxuXHRcdFx0XHRcdFx0Y29kZWNzOlxuXHRcdFx0XHRcdFx0W1xuXHRcdFx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRcdFx0bmFtZTogJ1BDTUEnLFxuXHRcdFx0XHRcdFx0XHRcdG1pbWVUeXBlOiAnYXVkaW8vUENNQScsXG5cdFx0XHRcdFx0XHRcdFx0Y2xvY2tSYXRlOiA4MDAwLFxuXHRcdFx0XHRcdFx0XHRcdHBheWxvYWRUeXBlOiA4LFxuXHRcdFx0XHRcdFx0XHRcdHJ0Y3BGZWVkYmFjazogW10sXG5cdFx0XHRcdFx0XHRcdFx0cGFyYW1ldGVyczoge31cblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XSxcblx0XHRcdFx0XHRcdGhlYWRlckV4dGVuc2lvbnM6XG5cdFx0XHRcdFx0XHRbXG5cdFx0XHRcdFx0XHRcdHtcblx0XHRcdFx0XHRcdFx0XHR1cmk6ICd1cm46aWV0ZjpwYXJhbXM6cnRwLWhkcmV4dDpzc3JjLWF1ZGlvLWxldmVsJyxcblx0XHRcdFx0XHRcdFx0XHRpZDogMVxuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRdLFxuXHRcdFx0XHRcdFx0ZW5jb2RpbmdzOlxuXHRcdFx0XHRcdFx0W1xuXHRcdFx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRcdFx0c3NyYzogMzMzMzMzMzNcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XSxcblx0XHRcdFx0XHRcdHJ0Y3A6XG5cdFx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRcdGNuYW1lOiAnQUxJQ0VDTkFNRScsXG5cdFx0XHRcdFx0XHRcdHJlZHVjZWRTaXplOiB0cnVlLFxuXHRcdFx0XHRcdFx0XHRtdXg6IHRydWVcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdF1cblx0XHR9LFxuXHRcdHtcblx0XHRcdG5hbWU6ICdib2InLFxuXHRcdFx0YXBwRGF0YTogJ0JvYiBIUCBMYXB0b3AnLFxuXHRcdFx0Y29uc3VtZXJzOlxuXHRcdFx0W1xuXHRcdFx0XHR7XG5cdFx0XHRcdFx0aWQ6IDY2NjYsXG5cdFx0XHRcdFx0a2luZDogJ2F1ZGlvJyxcblx0XHRcdFx0XHRwYXVzZWQ6IGZhbHNlLFxuXHRcdFx0XHRcdGFwcERhdGE6ICdCT0JfTUlDJyxcblx0XHRcdFx0XHRydHBQYXJhbWV0ZXJzOlxuXHRcdFx0XHRcdHtcblx0XHRcdFx0XHRcdG11eElkOiBudWxsLFxuXHRcdFx0XHRcdFx0Y29kZWNzOlxuXHRcdFx0XHRcdFx0W1xuXHRcdFx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRcdFx0bmFtZTogJ29wdXMnLFxuXHRcdFx0XHRcdFx0XHRcdG1pbWVUeXBlOiAnYXVkaW8vb3B1cycsXG5cdFx0XHRcdFx0XHRcdFx0Y2xvY2tSYXRlOiA0ODAwMCxcblx0XHRcdFx0XHRcdFx0XHRjaGFubmVsczogMixcblx0XHRcdFx0XHRcdFx0XHRwYXlsb2FkVHlwZTogOTYsXG5cdFx0XHRcdFx0XHRcdFx0cnRjcEZlZWRiYWNrOiBbXSxcblx0XHRcdFx0XHRcdFx0XHRwYXJhbWV0ZXJzOiB7fVxuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRdLFxuXHRcdFx0XHRcdFx0aGVhZGVyRXh0ZW5zaW9uczpcblx0XHRcdFx0XHRcdFtcblx0XHRcdFx0XHRcdFx0e1xuXHRcdFx0XHRcdFx0XHRcdHVyaTogJ3VybjppZXRmOnBhcmFtczpydHAtaGRyZXh0OnNzcmMtYXVkaW8tbGV2ZWwnLFxuXHRcdFx0XHRcdFx0XHRcdGlkOiAxXG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdF0sXG5cdFx0XHRcdFx0XHRlbmNvZGluZ3M6XG5cdFx0XHRcdFx0XHRbXG5cdFx0XHRcdFx0XHRcdHtcblx0XHRcdFx0XHRcdFx0XHRzc3JjOiA2NjY2NjY2NlxuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRdLFxuXHRcdFx0XHRcdFx0cnRjcDpcblx0XHRcdFx0XHRcdHtcblx0XHRcdFx0XHRcdFx0Y25hbWU6ICdCT0JDTkFNRScsXG5cdFx0XHRcdFx0XHRcdHJlZHVjZWRTaXplOiB0cnVlLFxuXHRcdFx0XHRcdFx0XHRtdXg6IHRydWVcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdF1cblx0XHR9XG5cdF1cbn07XG5cbmV4cG9ydHMuQ1JFQVRFX1RSQU5TUE9SVF8xX1JFU1BPTlNFID1cbntcblx0aWNlUGFyYW1ldGVyczpcblx0e1xuXHRcdHVzZXJuYW1lRnJhZ21lbnQ6ICdzZXJ2ZXItdXNlcm5hbWVmcmFnbWVudC0xMjM0NTY3OCcsXG5cdFx0cGFzc3dvcmQ6ICdzZXJ2ZXItcGFzc3dvcmQteHh4eHh4eHgnLFxuXHRcdGljZUxpdGU6IHRydWVcblx0fSxcblx0aWNlQ2FuZGlkYXRlczpcblx0W1xuXHRcdHtcblx0XHRcdGZvdW5kYXRpb246ICdGMScsXG5cdFx0XHRwcmlvcml0eTogMTIzNCxcblx0XHRcdGlwOiAnMS4yLjMuNCcsXG5cdFx0XHRwcm90b2NvbDogJ3VkcCcsXG5cdFx0XHRwb3J0OiA5OTk5LFxuXHRcdFx0dHlwZTogJ2hvc3QnXG5cdFx0fVxuXHRdLFxuXHRkdGxzUGFyYW1ldGVyczpcblx0e1xuXHRcdGZpbmdlcnByaW50czpcblx0XHRbXG5cdFx0XHR7XG5cdFx0XHRcdGFsZ29yaXRobTogJ3NoYS0yNTYnLFxuXHRcdFx0XHR2YWx1ZTogJ0ZGOkZGOjM5OjY2OkE0OkUyOjY2OjYwOjMwOjE4OkE3OjU5OkIzOkFGOkE1OjMzOjU4OjVFOjdGOjY5OkE0OjYyOkE2OkQ0OkVCOjlGOkI3OjQyOjA1OjM1OkZGOkZGJ1xuXHRcdFx0fVxuXHRcdF0sXG5cdFx0cm9sZTogJ2NsaWVudCdcblx0fVxufTtcblxuZXhwb3J0cy5DUkVBVEVfVFJBTlNQT1JUXzJfUkVTUE9OU0UgPVxue1xuXHRpY2VQYXJhbWV0ZXJzOlxuXHR7XG5cdFx0dXNlcm5hbWVGcmFnbWVudDogJ3NlcnZlci11c2VybmFtZWZyYWdtZW50LTEyMzQ1Njc4Jyxcblx0XHRwYXNzd29yZDogJ3NlcnZlci1wYXNzd29yZC14eHh4eHh4eCcsXG5cdFx0aWNlTGl0ZTogdHJ1ZVxuXHR9LFxuXHRpY2VDYW5kaWRhdGVzOlxuXHRbXG5cdFx0e1xuXHRcdFx0Zm91bmRhdGlvbjogJ0YxJyxcblx0XHRcdHByaW9yaXR5OiAxMjM0LFxuXHRcdFx0aXA6ICcxLjIuMy40Jyxcblx0XHRcdHByb3RvY29sOiAndWRwJyxcblx0XHRcdHBvcnQ6IDk5OTksXG5cdFx0XHR0eXBlOiAnaG9zdCdcblx0XHR9XG5cdF0sXG5cdGR0bHNQYXJhbWV0ZXJzOlxuXHR7XG5cdFx0ZmluZ2VycHJpbnRzOlxuXHRcdFtcblx0XHRcdHtcblx0XHRcdFx0YWxnb3JpdGhtOiAnc2hhLTI1NicsXG5cdFx0XHRcdHZhbHVlOiAnRkY6RkY6Mzk6NjY6QTQ6RTI6NjY6NjA6MzA6MTg6QTc6NTk6QjM6QUY6QTU6MzM6NTg6NUU6N0Y6Njk6QTQ6NjI6QTY6RDQ6RUI6OUY6Qjc6NDI6MDU6MzU6RkY6RkYnXG5cdFx0XHR9XG5cdFx0XSxcblx0XHRyb2xlOiAnYXV0bydcblx0fVxufTtcblxuZXhwb3J0cy5BTElDRV9XRUJDQU1fTkVXX0NPTlNVTUVSX05PVElGSUNBVElPTiA9XG57XG5cdG1ldGhvZDogJ25ld0NvbnN1bWVyJyxcblx0bm90aWZpY2F0aW9uOiB0cnVlLFxuXHRpZDogNDQ0NCxcblx0cGVlck5hbWU6ICdhbGljZScsXG5cdGtpbmQ6ICd2aWRlbycsXG5cdHBhdXNlZDogdHJ1ZSxcblx0YXBwRGF0YTogJ0FMSUNFX1dFQkNBTScsXG5cdHJ0cFBhcmFtZXRlcnM6XG5cdHtcblx0XHRtdXhJZDogbnVsbCxcblx0XHRjb2RlY3M6XG5cdFx0W1xuXHRcdFx0e1xuXHRcdFx0XHRuYW1lOiAnVlA4Jyxcblx0XHRcdFx0bWltZVR5cGU6ICd2aWRlby9WUDgnLFxuXHRcdFx0XHRjbG9ja1JhdGU6IDkwMDAwLFxuXHRcdFx0XHRwYXlsb2FkVHlwZTogMTAwLFxuXHRcdFx0XHRydGNwRmVlZGJhY2s6XG5cdFx0XHRcdFtcblx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRwYXJhbWV0ZXI6ICcnLFxuXHRcdFx0XHRcdFx0dHlwZTogJ25hY2snXG5cdFx0XHRcdFx0fSxcblx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRwYXJhbWV0ZXI6ICdwbGknLFxuXHRcdFx0XHRcdFx0dHlwZTogJ25hY2snXG5cdFx0XHRcdFx0fSxcblx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRwYXJhbWV0ZXI6ICcnLFxuXHRcdFx0XHRcdFx0dHlwZTogJ2dvb2ctcmVtYidcblx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdHtcblx0XHRcdFx0XHRcdHBhcmFtZXRlcjogJ2JhcicsXG5cdFx0XHRcdFx0XHR0eXBlOiAnZm9vJ1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XSxcblx0XHRcdFx0cGFyYW1ldGVyczoge31cblx0XHRcdH0sXG5cdFx0XHR7XG5cdFx0XHRcdG5hbWU6ICdydHgnLFxuXHRcdFx0XHRtaW1lVHlwZTogJ3ZpZGVvL3J0eCcsXG5cdFx0XHRcdGNsb2NrUmF0ZTogOTAwMDAsXG5cdFx0XHRcdHBheWxvYWRUeXBlOiAxMDEsXG5cdFx0XHRcdHJ0Y3BGZWVkYmFjazogW10sXG5cdFx0XHRcdHBhcmFtZXRlcnM6IHtcblx0XHRcdFx0XHRhcHQ6IDEwMFxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XSxcblx0XHRoZWFkZXJFeHRlbnNpb25zOlxuXHRcdFtcblx0XHRcdHtcblx0XHRcdFx0a2luZDogJ3ZpZGVvJyxcblx0XHRcdFx0dXJpOiAnaHR0cDovL3d3dy53ZWJydGMub3JnL2V4cGVyaW1lbnRzL3J0cC1oZHJleHQvYWJzLXNlbmQtdGltZScsXG5cdFx0XHRcdGlkOiAxMVxuXHRcdFx0fSxcblx0XHRcdHtcblx0XHRcdFx0a2luZDogJ3ZpZGVvJyxcblx0XHRcdFx0dXJpOiAnaHR0cDovL2Zvby5iYXInLFxuXHRcdFx0XHRpZDogMTJcblx0XHRcdH1cblx0XHRdLFxuXHRcdGVuY29kaW5nczpcblx0XHRbXG5cdFx0XHR7XG5cdFx0XHRcdHNzcmM6IDQ0NDQ0NDQ0MSxcblx0XHRcdFx0cnR4OiB7XG5cdFx0XHRcdFx0c3NyYzogNDQ0NDQ0NDQyXG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHRdLFxuXHRcdHJ0Y3A6XG5cdFx0e1xuXHRcdFx0Y25hbWU6ICdBTElDRUNOQU1FJyxcblx0XHRcdHJlZHVjZWRTaXplOiB0cnVlLFxuXHRcdFx0bXV4OiB0cnVlXG5cdFx0fVxuXHR9XG59O1xuIiwiaW1wb3J0ICogYXMgbWVkaWFzb3VwQ2xpZW50IGZyb20gJ21lZGlhc291cC1jbGllbnQnO1xuaW1wb3J0IGRvbXJlYWR5IGZyb20gJ2RvbXJlYWR5JztcbmltcG9ydCBMb2dnZXIgZnJvbSAnLi4vbGliL0xvZ2dlcic7XG5jb25zdCBEQVRBID0gcmVxdWlyZSgnLi9EQVRBJyk7XG5cbndpbmRvdy5tZWRpYXNvdXBDbGllbnQgPSBtZWRpYXNvdXBDbGllbnQ7XG5cbmNvbnN0IGxvZ2dlciA9IG5ldyBMb2dnZXIoKTtcblxuXG5jb25zdCBTRU5EID0gdHJ1ZTtcbmNvbnN0IFNFTkRfQVVESU8gPSB0cnVlO1xuY29uc3QgU0VORF9WSURFTyA9IGZhbHNlO1xuY29uc3QgUkVDViA9IHRydWU7XG5cblxuZG9tcmVhZHkoKCkgPT5cbntcblx0bG9nZ2VyLmRlYnVnKCdET00gcmVhZHknKTtcblxuXHRydW4oKTtcbn0pO1xuXG5mdW5jdGlvbiBydW4oKVxue1xuXHRsb2dnZXIuZGVidWcoJ3J1bigpIFtlbnZpcm9ubWVudDolc10nLCBwcm9jZXNzLmVudi5OT0RFX0VOVik7XG5cblx0bGV0IHRyYW5zcG9ydDE7XG5cdGxldCB0cmFuc3BvcnQyO1xuXHRsZXQgYXVkaW9UcmFjaztcblx0bGV0IHZpZGVvVHJhY2s7XG5cdGxldCBhdWRpb1Byb2R1Y2VyMTtcblx0bGV0IGF1ZGlvUHJvZHVjZXIyO1xuXHRsZXQgdmlkZW9Qcm9kdWNlcjtcblxuXHRsb2dnZXIuZGVidWcoJ2NhbGxpbmcgcm9vbSA9IG5ldyBtZWRpYXNvdXBDbGllbnQuUm9vbSgpJyk7XG5cblx0Ly8gY29uc3Qgcm9vbSA9IG5ldyBtZWRpYXNvdXBDbGllbnQuUm9vbSgpO1xuXHRjb25zdCByb29tID0gbmV3IG1lZGlhc291cENsaWVudC5Sb29tKERBVEEuUk9PTV9PUFRJT05TKTtcblxuXHR3aW5kb3cucm9vbSA9IHJvb207XG5cblx0cm9vbS5vbignY2xvc2VkJywgKG9yaWdpbmF0b3IsIGFwcERhdGEpID0+XG5cdHtcblx0XHRsb2dnZXIud2Fybihcblx0XHRcdCdyb29tIFwiY2xvc2VkXCIgZXZlbnQgW29yaWdpbmF0b3I6JXMsIGFwcERhdGE6JW9dJywgb3JpZ2luYXRvciwgYXBwRGF0YSk7XG5cdH0pO1xuXG5cdHJvb20ub24oJ3JlcXVlc3QnLCAocmVxdWVzdCwgY2FsbGJhY2ssIGVycmJhY2spID0+XG5cdHtcblx0XHRsb2dnZXIud2Fybignc2VuZGluZyByZXF1ZXN0IFttZXRob2Q6JXNdOiVvJywgcmVxdWVzdC5tZXRob2QsIHJlcXVlc3QpO1xuXG5cdFx0c3dpdGNoIChyZXF1ZXN0Lm1ldGhvZClcblx0XHR7XG5cdFx0XHRjYXNlICdxdWVyeVJvb20nOlxuXHRcdFx0e1xuXHRcdFx0XHRzZXRUaW1lb3V0KCgpID0+XG5cdFx0XHRcdHtcblx0XHRcdFx0XHRjYWxsYmFjayhEQVRBLlFVRVJZX1JPT01fUkVTUE9OU0UpO1xuXHRcdFx0XHRcdGVycmJhY2soJ3VwcHBwcycpO1xuXHRcdFx0XHR9LCAyMDApO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdH1cblxuXHRcdFx0Y2FzZSAnam9pblJvb20nOlxuXHRcdFx0e1xuXHRcdFx0XHRzZXRUaW1lb3V0KCgpID0+XG5cdFx0XHRcdHtcblx0XHRcdFx0XHRjYWxsYmFjayhEQVRBLkpPSU5fUk9PTV9SRVNQT05TRSk7XG5cdFx0XHRcdFx0Ly8gZXJyYmFjaygndXBwcHBzJyk7XG5cdFx0XHRcdH0sIDIwMCk7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0fVxuXG5cdFx0XHRjYXNlICdjcmVhdGVUcmFuc3BvcnQnOlxuXHRcdFx0e1xuXHRcdFx0XHRzZXRUaW1lb3V0KCgpID0+XG5cdFx0XHRcdHtcblx0XHRcdFx0XHRzd2l0Y2ggKHJlcXVlc3QuYXBwRGF0YSlcblx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRjYXNlICdUUkFOU1BPUlRfMSc6XG5cdFx0XHRcdFx0XHRcdGNhbGxiYWNrKERBVEEuQ1JFQVRFX1RSQU5TUE9SVF8xX1JFU1BPTlNFKTtcblx0XHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0XHRjYXNlICdUUkFOU1BPUlRfMic6XG5cdFx0XHRcdFx0XHRcdGNhbGxiYWNrKERBVEEuQ1JFQVRFX1RSQU5TUE9SVF8yX1JFU1BPTlNFKTtcblx0XHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0XHRkZWZhdWx0OlxuXHRcdFx0XHRcdFx0XHRlcnJiYWNrKCd1cHBwcHMnKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0sIDI1MCk7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0fVxuXG5cdFx0XHRjYXNlICdjcmVhdGVQcm9kdWNlcic6XG5cdFx0XHR7XG5cdFx0XHRcdHNldFRpbWVvdXQoKCkgPT5cblx0XHRcdFx0e1xuXHRcdFx0XHRcdGNhbGxiYWNrKCk7XG5cdFx0XHRcdH0sIDI1MCk7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0fVxuXG5cdFx0XHRjYXNlICdlbmFibGVDb25zdW1lcic6XG5cdFx0XHR7XG5cdFx0XHRcdHNldFRpbWVvdXQoKCkgPT5cblx0XHRcdFx0e1xuXHRcdFx0XHRcdGNhbGxiYWNrKCk7XG5cdFx0XHRcdH0sIDUwMCk7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0fVxuXG5cdFx0XHRkZWZhdWx0OlxuXHRcdFx0XHRlcnJiYWNrKGBOTyBJREVBIEFCT1VUIFJFUVVFU1QgTUVUSE9EIFwiJHtyZXF1ZXN0Lm1ldGhvZH1cImApO1xuXHRcdH1cblx0fSk7XG5cblx0cm9vbS5vbignbm90aWZ5JywgKG5vdGlmaWNhdGlvbikgPT5cblx0e1xuXHRcdGxvZ2dlci53YXJuKFxuXHRcdFx0J3NlbmRpbmcgbm90aWZpY2F0aW9uIFttZXRob2Q6JXNdOiVvJywgbm90aWZpY2F0aW9uLm1ldGhvZCwgbm90aWZpY2F0aW9uKTtcblxuXHRcdHN3aXRjaCAobm90aWZpY2F0aW9uLm1ldGhvZClcblx0XHR7XG5cdFx0XHRjYXNlICdsZWF2ZVJvb20nOlxuXHRcdFx0Y2FzZSAndXBkYXRlVHJhbnNwb3J0Jzpcblx0XHRcdGNhc2UgJ2Nsb3NlVHJhbnNwb3J0Jzpcblx0XHRcdGNhc2UgJ2Nsb3NlUHJvZHVjZXInOlxuXHRcdFx0Y2FzZSAncGF1c2VQcm9kdWNlcic6XG5cdFx0XHRjYXNlICdyZXN1bWVQcm9kdWNlcic6XG5cdFx0XHRjYXNlICdwYXVzZUNvbnN1bWVyJzpcblx0XHRcdGNhc2UgJ3Jlc3VtZUNvbnN1bWVyJzpcblx0XHRcdFx0YnJlYWs7XG5cblx0XHRcdGRlZmF1bHQ6XG5cdFx0XHRcdGxvZ2dlci5lcnJvcihgTk8gSURFQSBBQk9VVCBOT1RJRklDQVRJT04gTUVUSE9EIFwiJHtub3RpZmljYXRpb24ubWV0aG9kfVwiYCk7XG5cdFx0fVxuXHR9KTtcblxuXHRyb29tLm9uKCduZXdwZWVyJywgKHBlZXIpID0+XG5cdHtcblx0XHRsb2dnZXIud2Fybigncm9vbSBcIm5ld3BlZXJcIiBldmVudCBbbmFtZTpcIiVzXCIsIHBlZXI6JW9dJywgcGVlci5uYW1lLCBwZWVyKTtcblxuXHRcdGhhbmRsZVBlZXIocGVlcik7XG5cdH0pO1xuXG5cdFByb21pc2UucmVzb2x2ZSgpXG5cdFx0LnRoZW4oKCkgPT5cblx0XHR7XG5cdFx0XHRsb2dnZXIuZGVidWcoJ2NhbGxpbmcgcm9vbS5qb2luKCknKTtcblxuXHRcdFx0Y29uc3QgZGV2aWNlSW5mbyA9IG1lZGlhc291cENsaWVudC5nZXREZXZpY2VJbmZvKCk7XG5cdFx0XHRjb25zdCBhcHBEYXRhID1cblx0XHRcdHtcblx0XHRcdFx0ZGV2aWNlIDogYCR7ZGV2aWNlSW5mby5uYW1lfSAke2RldmljZUluZm8udmVyc2lvbn1gXG5cdFx0XHR9O1xuXG5cdFx0XHRyZXR1cm4gcm9vbS5qb2luKG51bGwsIGFwcERhdGEpO1xuXHRcdFx0Ly8gcmV0dXJuIHJvb20uam9pbihEQVRBLlJPT01fUlRQX0NBUEFCSUxJVElFUywgYXBwRGF0YSk7XG5cdFx0fSlcblx0XHQudGhlbigocGVlcnMpID0+XG5cdFx0e1xuXHRcdFx0aWYgKCFSRUNWKVxuXHRcdFx0XHRyZXR1cm47XG5cblx0XHRcdGxvZ2dlci5kZWJ1Zygncm9vbS5qb2luKCkgc3VjY2VlZGVkJyk7XG5cblx0XHRcdGxvZ2dlci5kZWJ1ZygnY2FsbGluZyB0cmFuc3BvcnQyID0gcm9vbS5jcmVhdGVUcmFuc3BvcnQoXCJyZWN2XCIpJyk7XG5cblx0XHRcdHRyYW5zcG9ydDIgPSByb29tLmNyZWF0ZVRyYW5zcG9ydCgncmVjdicsICdUUkFOU1BPUlRfMicpO1xuXHRcdFx0d2luZG93LnRyYW5zcG9ydDIgPSB0cmFuc3BvcnQyO1xuXHRcdFx0d2luZG93LnBjMiA9IHRyYW5zcG9ydDIuX2hhbmRsZXIuX3BjO1xuXG5cdFx0XHRoYW5kbGVUcmFuc3BvcnQodHJhbnNwb3J0Mik7XG5cblx0XHRcdGZvciAoY29uc3QgcGVlciBvZiBwZWVycylcblx0XHRcdHtcblx0XHRcdFx0aGFuZGxlUGVlcihwZWVyKTtcblx0XHRcdH1cblx0XHR9KVxuXHRcdC50aGVuKCgpID0+XG5cdFx0e1xuXHRcdFx0aWYgKCFTRU5EKVxuXHRcdFx0XHRyZXR1cm47XG5cblx0XHRcdGlmIChyb29tLmNhblNlbmQoJ2F1ZGlvJykpXG5cdFx0XHRcdGxvZ2dlci5kZWJ1ZygnY2FuIHNlbmQgYXVkaW8nKTtcblx0XHRcdGVsc2Vcblx0XHRcdFx0bG9nZ2VyLndhcm4oJ2Nhbm5vdCBzZW5kIGF1ZGlvJyk7XG5cblx0XHRcdGlmIChyb29tLmNhblNlbmQoJ3ZpZGVvJykpXG5cdFx0XHRcdGxvZ2dlci5kZWJ1ZygnY2FuIHNlbmQgdmlkZW8nKTtcblx0XHRcdGVsc2Vcblx0XHRcdFx0bG9nZ2VyLndhcm4oJ2Nhbm5vdCBzZW5kIHZpZGVvJyk7XG5cblx0XHRcdGxvZ2dlci5kZWJ1ZygnY2FsbGluZyB0cmFuc3BvcnQxID0gcm9vbS5jcmVhdGVUcmFuc3BvcnQoXCJzZW5kXCIpJyk7XG5cblx0XHRcdHRyYW5zcG9ydDEgPSByb29tLmNyZWF0ZVRyYW5zcG9ydCgnc2VuZCcsICdUUkFOU1BPUlRfMScpO1xuXHRcdFx0d2luZG93LnRyYW5zcG9ydDEgPSB0cmFuc3BvcnQxO1xuXHRcdFx0d2luZG93LnBjMSA9IHRyYW5zcG9ydDEuX2hhbmRsZXIuX3BjO1xuXG5cdFx0XHRoYW5kbGVUcmFuc3BvcnQodHJhbnNwb3J0MSk7XG5cblx0XHRcdGxvZ2dlci5kZWJ1ZygnY2FsbGluZyBnZXRVc2VyTWVkaWEoKScpO1xuXG5cdFx0XHRyZXR1cm4gbmF2aWdhdG9yLm1lZGlhRGV2aWNlc1xuXHRcdFx0XHQuZ2V0VXNlck1lZGlhKHsgYXVkaW86IFNFTkRfQVVESU8sIHZpZGVvOiBTRU5EX1ZJREVPIH0pO1xuXHRcdH0pXG5cdFx0LnRoZW4oKHN0cmVhbSkgPT5cblx0XHR7XG5cdFx0XHRpZiAoIVNFTkQpXG5cdFx0XHRcdHJldHVybjtcblxuXHRcdFx0YXVkaW9UcmFjayA9IHN0cmVhbS5nZXRBdWRpb1RyYWNrcygpWzBdO1xuXHRcdFx0dmlkZW9UcmFjayA9IHN0cmVhbS5nZXRWaWRlb1RyYWNrcygpWzBdO1xuXHRcdFx0d2luZG93LmF1ZGlvVHJhY2sgPSBhdWRpb1RyYWNrO1xuXHRcdFx0d2luZG93LnZpZGVvVHJhY2sgPSB2aWRlb1RyYWNrO1xuXHRcdH0pXG5cdFx0Ly8gQWRkIFByb2R1Y2Vycy5cblx0XHQudGhlbigoKSA9PlxuXHRcdHtcblx0XHRcdGlmIChhdWRpb1RyYWNrKVxuXHRcdFx0e1xuXHRcdFx0XHRjb25zdCBkZXZpY2VJZCA9IGF1ZGlvVHJhY2suZ2V0U2V0dGluZ3MoKS5kZXZpY2VJZDtcblxuXHRcdFx0XHRsb2dnZXIuZGVidWcoJ2NhbGxpbmcgYXVkaW9Qcm9kdWNlcjEgPSByb29tLmNyZWF0ZVByb2R1Y2VyKGF1ZGlvVHJhY2spJyk7XG5cblx0XHRcdFx0dHJ5XG5cdFx0XHRcdHtcblx0XHRcdFx0XHRhdWRpb1Byb2R1Y2VyMSA9IHJvb20uY3JlYXRlUHJvZHVjZXIoYXVkaW9UcmFjaywgYCR7ZGV2aWNlSWR9LTFgKTtcblx0XHRcdFx0XHR3aW5kb3cuYXVkaW9Qcm9kdWNlcjEgPSBhdWRpb1Byb2R1Y2VyMTtcblxuXHRcdFx0XHRcdGhhbmRsZVByb2R1Y2VyKGF1ZGlvUHJvZHVjZXIxKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRjYXRjaCAoZXJyb3IpXG5cdFx0XHRcdHtcblx0XHRcdFx0XHRsb2dnZXIuZXJyb3IoZXJyb3IpO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0bG9nZ2VyLmRlYnVnKCdjYWxsaW5nIGF1ZGlvUHJvZHVjZXIyID0gcm9vbS5jcmVhdGVQcm9kdWNlcihhdWRpb1RyYWNrKScpO1xuXG5cdFx0XHRcdHRyeVxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0YXVkaW9Qcm9kdWNlcjIgPSByb29tLmNyZWF0ZVByb2R1Y2VyKGF1ZGlvVHJhY2ssIGAke2RldmljZUlkfS0yYCk7XG5cdFx0XHRcdFx0d2luZG93LmF1ZGlvUHJvZHVjZXIyID0gYXVkaW9Qcm9kdWNlcjI7XG5cblx0XHRcdFx0XHRoYW5kbGVQcm9kdWNlcihhdWRpb1Byb2R1Y2VyMik7XG5cdFx0XHRcdH1cblx0XHRcdFx0Y2F0Y2ggKGVycm9yKVxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0bG9nZ2VyLmVycm9yKGVycm9yKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0XHRpZiAodmlkZW9UcmFjaylcblx0XHRcdHtcblx0XHRcdFx0Y29uc3QgZGV2aWNlSWQgPSB2aWRlb1RyYWNrLmdldFNldHRpbmdzKCkuZGV2aWNlSWQ7XG5cblx0XHRcdFx0bG9nZ2VyLmRlYnVnKCdjYWxsaW5nIHZpZGVvUHJvZHVjZXIgPSByb29tLmNyZWF0ZVByb2R1Y2VyKHZpZGVvVHJhY2spJyk7XG5cblx0XHRcdFx0dHJ5XG5cdFx0XHRcdHtcblx0XHRcdFx0XHR2aWRlb1Byb2R1Y2VyID0gcm9vbS5jcmVhdGVQcm9kdWNlcih2aWRlb1RyYWNrLCBgJHtkZXZpY2VJZH0tMWApO1xuXHRcdFx0XHRcdHdpbmRvdy52aWRlb1Byb2R1Y2VyID0gdmlkZW9Qcm9kdWNlcjtcblxuXHRcdFx0XHRcdGhhbmRsZVByb2R1Y2VyKHZpZGVvUHJvZHVjZXIpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGNhdGNoIChlcnJvcilcblx0XHRcdFx0e1xuXHRcdFx0XHRcdGxvZ2dlci5lcnJvcihlcnJvcik7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9KVxuXHRcdC8vIFJlY2VpdmUgbm90aWZpY2F0aW9ucy5cblx0XHQudGhlbigoKSA9PlxuXHRcdHtcblx0XHRcdGlmICghUkVDVilcblx0XHRcdFx0cmV0dXJuO1xuXG5cdFx0XHRzZXRUaW1lb3V0KCgpID0+XG5cdFx0XHR7XG5cdFx0XHRcdHJvb20ucmVjZWl2ZU5vdGlmaWNhdGlvbihEQVRBLkFMSUNFX1dFQkNBTV9ORVdfQ09OU1VNRVJfTk9USUZJQ0FUSU9OKTtcblx0XHRcdH0sIDIwMDApO1xuXHRcdH0pO1xufVxuXG5mdW5jdGlvbiBoYW5kbGVUcmFuc3BvcnQodHJhbnNwb3J0KVxue1xuXHRsb2dnZXIud2Fybihcblx0XHQnaGFuZGxlVHJhbnNwb3J0KCkgW2RpcmVjdGlvbjolcywgYXBwRGF0YTpcIiVzXCIsIHRyYW5zcG9ydDolb10nLFxuXHRcdHRyYW5zcG9ydC5kaXJlY3Rpb24sIHRyYW5zcG9ydC5hcHBEYXRhLCB0cmFuc3BvcnQpO1xuXG5cdHRyYW5zcG9ydC5vbignY2xvc2VkJywgKG9yaWdpbmF0b3IsIGFwcERhdGEpID0+XG5cdHtcblx0XHRsb2dnZXIud2Fybihcblx0XHRcdCd0cmFuc3BvcnQgXCJjbG9zZWRcIiBldmVudCBbb3JpZ2luYXRvcjolcywgYXBwRGF0YTolbywgdHJhbnNwb3J0OiVvXScsXG5cdFx0XHRvcmlnaW5hdG9yLCBhcHBEYXRhLCB0cmFuc3BvcnQpO1xuXHR9KTtcblxuXHR0cmFuc3BvcnQub24oJ2Nvbm5lY3Rpb25zdGF0ZWNoYW5nZScsIChzdGF0ZSkgPT5cblx0e1xuXHRcdGxvZ2dlci53YXJuKFxuXHRcdFx0J3RyYW5zcG9ydCBcImNvbm5lY3Rpb25zdGF0ZWNoYW5nZVwiIGV2ZW50IFtkaXJlY3Rpb246JXMsIHN0YXRlOiVzLCB0cmFuc3BvcnQ6JW9dJyxcblx0XHRcdHRyYW5zcG9ydC5kaXJlY3Rpb24sIHN0YXRlLCB0cmFuc3BvcnQpO1xuXHR9KTtcblxuXHRzZXRJbnRlcnZhbCgoKSA9PlxuXHR7XG5cdFx0Y29uc3QgcXVldWUgPSB0cmFuc3BvcnQuX2NvbW1hbmRRdWV1ZS5fcXVldWU7XG5cblx0XHRpZiAocXVldWUubGVuZ3RoICE9PSAwKVxuXHRcdFx0bG9nZ2VyLmVycm9yKCdxdWV1ZSBub3QgZW1wdHkgW3RyYW5zcG9ydDolbywgcXVldWU6JW9dJywgdHJhbnNwb3J0LCBxdWV1ZSk7XG5cdH0sIDE1MDAwKTtcbn1cblxuZnVuY3Rpb24gaGFuZGxlUGVlcihwZWVyKVxue1xuXHRsb2dnZXIud2FybignaGFuZGxlUGVlcigpIFtuYW1lOlwiJXNcIiwgcGVlcjolb10nLCBwZWVyLm5hbWUsIHBlZXIpO1xuXG5cdHN3aXRjaCAocGVlci5uYW1lKVxuXHR7XG5cdFx0Y2FzZSAnYWxpY2UnOlxuXHRcdFx0d2luZG93LmFsaWNlID0gcGVlcjtcblx0XHRcdGJyZWFrO1xuXHRcdGNhc2UgJ2JvYic6XG5cdFx0XHR3aW5kb3cuYm9iID0gcGVlcjtcblx0XHRcdGJyZWFrO1xuXHR9XG5cblx0Zm9yIChjb25zdCBjb25zdW1lciBvZiBwZWVyLmNvbnN1bWVycylcblx0e1xuXHRcdGhhbmRsZUNvbnN1bWVyKGNvbnN1bWVyKTtcblx0fVxuXG5cdHBlZXIub24oJ2Nsb3NlZCcsIChvcmlnaW5hdG9yLCBhcHBEYXRhKSA9PlxuXHR7XG5cdFx0bG9nZ2VyLndhcm4oXG5cdFx0XHQncGVlciBcImNsb3NlZFwiIGV2ZW50IFtuYW1lOlwiJXNcIiwgb3JpZ2luYXRvcjolcywgYXBwRGF0YTolb10nLFxuXHRcdFx0cGVlci5uYW1lLCBvcmlnaW5hdG9yLCBhcHBEYXRhKTtcblx0fSk7XG5cblx0cGVlci5vbignbmV3Y29uc3VtZXInLCAoY29uc3VtZXIpID0+XG5cdHtcblx0XHRsb2dnZXIud2Fybihcblx0XHRcdCdwZWVyIFwibmV3Y29uc3VtZXJcIiBldmVudCBbbmFtZTpcIiVzXCIsIGlkOiVzLCBjb25zdW1lcjolb10nLFxuXHRcdFx0cGVlci5uYW1lLCBjb25zdW1lci5pZCwgY29uc3VtZXIpO1xuXG5cdFx0aGFuZGxlQ29uc3VtZXIoY29uc3VtZXIpO1xuXHR9KTtcbn1cblxuZnVuY3Rpb24gaGFuZGxlUHJvZHVjZXIocHJvZHVjZXIpXG57XG5cdGNvbnN0IHRyYW5zcG9ydDEgPSB3aW5kb3cudHJhbnNwb3J0MTtcblxuXHRsb2dnZXIuZGVidWcoXG5cdFx0J2hhbmRsZVByb2R1Y2VyKCkgW2lkOlwiJXNcIiwgYXBwRGF0YTolbywgcHJvZHVjZXI6JW9dJyxcblx0XHRwcm9kdWNlci5pZCwgcHJvZHVjZXIuYXBwRGF0YSwgcHJvZHVjZXIpO1xuXG5cdGxvZ2dlci5kZWJ1ZygnaGFuZGxlUHJvZHVjZXIoKSB8IGNhbGxpbmcgdHJhbnNwb3J0MS5zZW5kKHByb2R1Y2VyKScpO1xuXG5cdHRyYW5zcG9ydDEuc2VuZChwcm9kdWNlcilcblx0XHQudGhlbigoKSA9PlxuXHRcdHtcblx0XHRcdGxvZ2dlci5kZWJ1ZygndHJhbnNwb3J0MS5zZW5kKHByb2R1Y2VyKSBzdWNjZWVkZWQnKTtcblx0XHR9KVxuXHRcdC5jYXRjaCgoZXJyb3IpID0+XG5cdFx0e1xuXHRcdFx0bG9nZ2VyLmVycm9yKCd0cmFuc3BvcnQxLnNlbmQocHJvZHVjZXIpIGZhaWxlZDogJW8nLCBlcnJvcik7XG5cdFx0fSk7XG5cblx0cHJvZHVjZXIub24oJ2Nsb3NlZCcsIChvcmlnaW5hdG9yLCBhcHBEYXRhKSA9PlxuXHR7XG5cdFx0bG9nZ2VyLndhcm4oXG5cdFx0XHQncHJvZHVjZXIgXCJjbG9zZWRcIiBldmVudCBbaWQ6JXMsIG9yaWdpbmF0b3I6JXMsIGFwcERhdGE6JW8sIHByb2R1Y2VyOiVvXScsXG5cdFx0XHRwcm9kdWNlci5pZCwgb3JpZ2luYXRvciwgYXBwRGF0YSwgcHJvZHVjZXIpO1xuXHR9KTtcblxuXHRwcm9kdWNlci5vbigncGF1c2VkJywgKG9yaWdpbmF0b3IsIGFwcERhdGEpID0+XG5cdHtcblx0XHRsb2dnZXIud2Fybihcblx0XHRcdCdwcm9kdWNlciBcInBhdXNlZFwiIGV2ZW50IFtpZDolcywgb3JpZ2luYXRvcjolcywgYXBwRGF0YTolbywgcHJvZHVjZXI6JW9dJyxcblx0XHRcdHByb2R1Y2VyLmlkLCBvcmlnaW5hdG9yLCBhcHBEYXRhLCBwcm9kdWNlcik7XG5cdH0pO1xuXG5cdHByb2R1Y2VyLm9uKCdyZXN1bWVkJywgKG9yaWdpbmF0b3IsIGFwcERhdGEpID0+XG5cdHtcblx0XHRsb2dnZXIud2Fybihcblx0XHRcdCdwcm9kdWNlciBcInJlc3VtZWRcIiBldmVudCBbaWQ6JXMsIG9yaWdpbmF0b3I6JXMsIGFwcERhdGE6JW8sIHByb2R1Y2VyOiVvXScsXG5cdFx0XHRwcm9kdWNlci5pZCwgb3JpZ2luYXRvciwgYXBwRGF0YSwgcHJvZHVjZXIpO1xuXHR9KTtcblxuXHRwcm9kdWNlci5vbigndW5oYW5kbGVkJywgKCkgPT5cblx0e1xuXHRcdGxvZ2dlci53YXJuKFxuXHRcdFx0J3Byb2R1Y2VyIFwidW5oYW5kbGVkXCIgZXZlbnQgW2lkOiVzLCBwcm9kdWNlcjolb10nLCBwcm9kdWNlci5pZCwgcHJvZHVjZXIpO1xuXHR9KTtcbn1cblxuZnVuY3Rpb24gaGFuZGxlQ29uc3VtZXIoY29uc3VtZXIpXG57XG5cdGNvbnN0IHRyYW5zcG9ydDIgPSB3aW5kb3cudHJhbnNwb3J0MjtcblxuXHRsb2dnZXIuZGVidWcoXG5cdFx0J2hhbmRsZUNvbnN1bWVyKCkgW2lkOlwiJXNcIiwgYXBwRGF0YTolbywgY29uc3VtZXI6JW9dJyxcblx0XHRjb25zdW1lci5pZCwgY29uc3VtZXIuYXBwRGF0YSwgY29uc3VtZXIpO1xuXG5cdHN3aXRjaCAoY29uc3VtZXIuYXBwRGF0YSlcblx0e1xuXHRcdGNhc2UgJ0FMSUNFX01JQyc6XG5cdFx0XHR3aW5kb3cuYWxpY2VBdWRpb0NvbnN1bWVyID0gY29uc3VtZXI7XG5cdFx0XHRicmVhaztcblx0XHRjYXNlICdBTElDRV9XRUJDQU0nOlxuXHRcdFx0d2luZG93LmFsaWNlVmlkZW9Db25zdW1lciA9IGNvbnN1bWVyO1xuXHRcdFx0YnJlYWs7XG5cdFx0Y2FzZSAnQk9CX01JQyc6XG5cdFx0XHR3aW5kb3cuYm9iQXVkaW9Db25zdW1lciA9IGNvbnN1bWVyO1xuXHRcdFx0YnJlYWs7XG5cdH1cblxuXHRsb2dnZXIuZGVidWcoJ2hhbmRsZUNvbnN1bWVyKCkgY2FsbGluZyB0cmFuc3BvcnQyLnJlY2VpdmUoY29uc3VtZXIpJyk7XG5cblx0dHJhbnNwb3J0Mi5yZWNlaXZlKGNvbnN1bWVyKVxuXHRcdC50aGVuKCh0cmFjaykgPT5cblx0XHR7XG5cdFx0XHRsb2dnZXIud2Fybihcblx0XHRcdFx0J3RyYW5zcG9ydDIucmVjZWl2ZShjb25zdW1lcikgc3VjY2VlZGVkIFt0cmFjazolb10nLCB0cmFjayk7XG5cdFx0fSlcblx0XHQuY2F0Y2goKGVycm9yKSA9PlxuXHRcdHtcblx0XHRcdGxvZ2dlci5lcnJvcigndHJhbnNwb3J0Mi5yZWNlaXZlKCkgZmFpbGVkOiVvJywgZXJyb3IpO1xuXHRcdH0pO1xuXG5cdGNvbnN1bWVyLm9uKCdjbG9zZWQnLCAob3JpZ2luYXRvciwgYXBwRGF0YSkgPT5cblx0e1xuXHRcdGxvZ2dlci53YXJuKFxuXHRcdFx0J2NvbnN1bWVyIFwiY2xvc2VkXCIgZXZlbnQgW2lkOiVzLCBvcmlnaW5hdG9yOiVzLCBhcHBEYXRhOiVvLCBjb25zdW1lcjolb10nLFxuXHRcdFx0Y29uc3VtZXIuaWQsIG9yaWdpbmF0b3IsIGFwcERhdGEsIGNvbnN1bWVyKTtcblx0fSk7XG5cblx0Y29uc3VtZXIub24oJ3BhdXNlZCcsIChvcmlnaW5hdG9yLCBhcHBEYXRhKSA9PlxuXHR7XG5cdFx0bG9nZ2VyLndhcm4oXG5cdFx0XHQnY29uc3VtZXIgXCJwYXVzZWRcIiBldmVudCBbaWQ6JXMsIG9yaWdpbmF0b3I6JXMsIGFwcERhdGE6JW8sIGNvbnN1bWVyOiVvXScsXG5cdFx0XHRjb25zdW1lci5pZCwgb3JpZ2luYXRvciwgYXBwRGF0YSwgY29uc3VtZXIpO1xuXHR9KTtcblxuXHRjb25zdW1lci5vbigncmVzdW1lZCcsIChvcmlnaW5hdG9yLCBhcHBEYXRhKSA9PlxuXHR7XG5cdFx0bG9nZ2VyLndhcm4oXG5cdFx0XHQnY29uc3VtZXIgXCJyZXN1bWVkXCIgZXZlbnQgW2lkOiVzLCBvcmlnaW5hdG9yOiVzLCBhcHBEYXRhOiVvLCBjb25zdW1lcjolb10nLFxuXHRcdFx0Y29uc3VtZXIuaWQsIG9yaWdpbmF0b3IsIGFwcERhdGEsIGNvbnN1bWVyKTtcblx0fSk7XG5cblx0Y29uc3VtZXIub24oJ3VuaGFuZGxlZCcsICgpID0+XG5cdHtcblx0XHRsb2dnZXIud2Fybihcblx0XHRcdCdjb25zdW1lciBcInVuaGFuZGxlZFwiIGV2ZW50IFtpZDolcywgY29uc3VtZXI6JW9dJywgY29uc3VtZXIuaWQsIGNvbnN1bWVyKTtcblx0fSk7XG59XG5cblxuLy8gTk9URTogVHJpZ2dlciBzZXJ2ZXIgbm90aWZpY2F0aW9ucy5cblxud2luZG93Lm5vdGlmeVJvb21DbG9zZWQgPSBmdW5jdGlvbigpXG57XG5cdGNvbnN0IHJvb20gPSB3aW5kb3cucm9vbTtcblx0Y29uc3Qgbm90aWZpY2F0aW9uID1cblx0e1xuXHRcdG1ldGhvZCAgICAgICA6ICdyb29tQ2xvc2VkJyxcblx0XHRub3RpZmljYXRpb24gOiB0cnVlLFxuXHRcdGFwcERhdGEgICAgICA6ICdoYSBjYXNjYW8gbGEgcm9vbSByZW1vdGEhISEnXG5cdH07XG5cblx0cm9vbS5yZWNlaXZlTm90aWZpY2F0aW9uKG5vdGlmaWNhdGlvbik7XG59O1xuXG53aW5kb3cubm90aWZ5VHJhbnNwb3J0Q2xvc2VkID0gZnVuY3Rpb24oKVxue1xuXHRjb25zdCByb29tID0gd2luZG93LnJvb207XG5cdGNvbnN0IG5vdGlmaWNhdGlvbiA9XG5cdHtcblx0XHRtZXRob2QgICAgICAgOiAndHJhbnNwb3J0Q2xvc2VkJyxcblx0XHRub3RpZmljYXRpb24gOiB0cnVlLFxuXHRcdGlkICAgICAgICAgICA6IHJvb20udHJhbnNwb3J0c1swXS5pZCxcblx0XHRhcHBEYXRhICAgICAgOiAnYWRtaW4gY2xvc2VkIHlvdXIgdHJhbnNwb3J0J1xuXHR9O1xuXG5cdHJvb20ucmVjZWl2ZU5vdGlmaWNhdGlvbihub3RpZmljYXRpb24pO1xufTtcblxud2luZG93Lm5vdGlmeUF1ZGlvUHJvZHVjZXIxQ2xvc2VkID0gZnVuY3Rpb24oKVxue1xuXHRjb25zdCByb29tID0gd2luZG93LnJvb207XG5cdGNvbnN0IG5vdGlmaWNhdGlvbiA9XG5cdHtcblx0XHRtZXRob2QgICAgICAgOiAncHJvZHVjZXJDbG9zZWQnLFxuXHRcdG5vdGlmaWNhdGlvbiA6IHRydWUsXG5cdFx0aWQgICAgICAgICAgIDogd2luZG93LmF1ZGlvUHJvZHVjZXIxLmlkLFxuXHRcdGFwcERhdGEgICAgICA6ICd0ZSBwYXJvIGVsIG1pY3JvIHBvciBsYSBmdWVyemEnXG5cdH07XG5cblx0cm9vbS5yZWNlaXZlTm90aWZpY2F0aW9uKG5vdGlmaWNhdGlvbik7XG59O1xuXG53aW5kb3cubm90aWZ5QXVkaW9Qcm9kdWNlcjFQYXVzZWQgPSBmdW5jdGlvbigpXG57XG5cdGNvbnN0IHJvb20gPSB3aW5kb3cucm9vbTtcblx0Y29uc3Qgbm90aWZpY2F0aW9uID1cblx0e1xuXHRcdG1ldGhvZCAgICAgICA6ICdwcm9kdWNlclBhdXNlZCcsXG5cdFx0bm90aWZpY2F0aW9uIDogdHJ1ZSxcblx0XHRpZCAgICAgICAgICAgOiB3aW5kb3cuYXVkaW9Qcm9kdWNlcjEuaWQsXG5cdFx0YXBwRGF0YSAgICAgIDogJ3RlIHBhdXNlIGVsIG1pY3JvIHBvciBsYSBmdWVyemEnXG5cdH07XG5cblx0cm9vbS5yZWNlaXZlTm90aWZpY2F0aW9uKG5vdGlmaWNhdGlvbik7XG59O1xuXG53aW5kb3cubm90aWZ5QXVkaW9Qcm9kdWNlcjFSZXN1bWVkID0gZnVuY3Rpb24oKVxue1xuXHRjb25zdCByb29tID0gd2luZG93LnJvb207XG5cdGNvbnN0IG5vdGlmaWNhdGlvbiA9XG5cdHtcblx0XHRtZXRob2QgICAgICAgOiAncHJvZHVjZXJSZXN1bWVkJyxcblx0XHRub3RpZmljYXRpb24gOiB0cnVlLFxuXHRcdGlkICAgICAgICAgICA6IHdpbmRvdy5hdWRpb1Byb2R1Y2VyMS5pZCxcblx0XHRhcHBEYXRhICAgICAgOiAndGUgcmVzdW1vIGVsIG1pY3JvJ1xuXHR9O1xuXG5cdHJvb20ucmVjZWl2ZU5vdGlmaWNhdGlvbihub3RpZmljYXRpb24pO1xufTtcblxud2luZG93Lm5vdGlmeUFsaWNlUGVlckNsb3NlZCA9IGZ1bmN0aW9uKClcbntcblx0Y29uc3Qgcm9vbSA9IHdpbmRvdy5yb29tO1xuXHRjb25zdCBub3RpZmljYXRpb24gPVxuXHR7XG5cdFx0bWV0aG9kICAgICAgIDogJ3BlZXJDbG9zZWQnLFxuXHRcdG5vdGlmaWNhdGlvbiA6IHRydWUsXG5cdFx0bmFtZSAgICAgICAgIDogJ2FsaWNlJyxcblx0XHRhcHBEYXRhICAgICAgOiAncGVlciBsZWZ0J1xuXHR9O1xuXG5cdHJvb20ucmVjZWl2ZU5vdGlmaWNhdGlvbihub3RpZmljYXRpb24pO1xufTtcblxud2luZG93Lm5vdGlmeUFsaWNlQXVkaW9Db25zdW1lckNsb3NlZCA9IGZ1bmN0aW9uKClcbntcblx0Y29uc3Qgcm9vbSA9IHdpbmRvdy5yb29tO1xuXHRjb25zdCBub3RpZmljYXRpb24gPVxuXHR7XG5cdFx0bWV0aG9kICAgICAgIDogJ2NvbnN1bWVyQ2xvc2VkJyxcblx0XHRub3RpZmljYXRpb24gOiB0cnVlLFxuXHRcdHBlZXJOYW1lICAgICA6ICdhbGljZScsXG5cdFx0aWQgICAgICAgICAgIDogMzMzMyxcblx0XHRhcHBEYXRhICAgICAgOiAnbWljIGJyb2tlbidcblx0fTtcblxuXHRyb29tLnJlY2VpdmVOb3RpZmljYXRpb24obm90aWZpY2F0aW9uKTtcbn07XG5cbndpbmRvdy5ub3RpZnlBbGljZVZpZGVvQ29uc3VtZXJDbG9zZWQgPSBmdW5jdGlvbigpXG57XG5cdGNvbnN0IHJvb20gPSB3aW5kb3cucm9vbTtcblx0Y29uc3Qgbm90aWZpY2F0aW9uID1cblx0e1xuXHRcdG1ldGhvZCAgICAgICA6ICdjb25zdW1lckNsb3NlZCcsXG5cdFx0bm90aWZpY2F0aW9uIDogdHJ1ZSxcblx0XHRwZWVyTmFtZSAgICAgOiAnYWxpY2UnLFxuXHRcdGlkICAgICAgICAgICA6IDQ0NDQsXG5cdFx0YXBwRGF0YSAgICAgIDogJ3dlYmNhbSBicm9rZW4nXG5cdH07XG5cblx0cm9vbS5yZWNlaXZlTm90aWZpY2F0aW9uKG5vdGlmaWNhdGlvbik7XG59O1xuXG53aW5kb3cubm90aWZ5QWxpY2VWaWRlb0NvbnN1bWVyUGF1c2VkID0gZnVuY3Rpb24oKVxue1xuXHRjb25zdCByb29tID0gd2luZG93LnJvb207XG5cdGNvbnN0IG5vdGlmaWNhdGlvbiA9XG5cdHtcblx0XHRtZXRob2QgICAgICAgOiAnY29uc3VtZXJQYXVzZWQnLFxuXHRcdG5vdGlmaWNhdGlvbiA6IHRydWUsXG5cdFx0cGVlck5hbWUgICAgIDogJ2FsaWNlJyxcblx0XHRpZCAgICAgICAgICAgOiA0NDQ0LFxuXHRcdGFwcERhdGEgICAgICA6ICd3ZWJjYW0gcGF1c2VkJ1xuXHR9O1xuXG5cdHJvb20ucmVjZWl2ZU5vdGlmaWNhdGlvbihub3RpZmljYXRpb24pO1xufTtcblxud2luZG93Lm5vdGlmeUFsaWNlVmlkZW9Db25zdW1lclJlc3VtZWQgPSBmdW5jdGlvbigpXG57XG5cdGNvbnN0IHJvb20gPSB3aW5kb3cucm9vbTtcblx0Y29uc3Qgbm90aWZpY2F0aW9uID1cblx0e1xuXHRcdG1ldGhvZCAgICAgICA6ICdjb25zdW1lclJlc3VtZWQnLFxuXHRcdG5vdGlmaWNhdGlvbiA6IHRydWUsXG5cdFx0cGVlck5hbWUgICAgIDogJ2FsaWNlJyxcblx0XHRpZCAgICAgICAgICAgOiA0NDQ0LFxuXHRcdGFwcERhdGEgICAgICA6ICd3ZWJjYW0gcmVzdW1lZCdcblx0fTtcblxuXHRyb29tLnJlY2VpdmVOb3RpZmljYXRpb24obm90aWZpY2F0aW9uKTtcbn07XG5cblxuLy8gTk9URTogVGVzdCBwYXVzZS9yZXN1bWUuXG5cbndpbmRvdy50ZXN0UGF1c2VSZXN1bWUgPSBmdW5jdGlvbigpXG57XG5cdGxvZ2dlci5kZWJ1ZygndGVzdFBhdXNlUmVzdW1lKCkgd2l0aCBhdWRpb1Byb2R1Y2VyMScpO1xuXG5cdGNvbnN0IHByb2R1Y2VyID0gd2luZG93LmF1ZGlvUHJvZHVjZXIxO1xuXG5cdC8vIHByb2R1Y2VyLm9uY2UoJ3BhdXNlZCcsICgpID0+XG5cdC8vIHtcblx0Ly8gXHRwcm9kdWNlci5yZXN1bWUoJ0kgUkVTVU1FIFRPIEZVQUNLISEhJyk7XG5cdC8vIH0pO1xuXG5cdGxvZ2dlci5kZWJ1ZygndGVzdFBhdXNlUmVzdW1lKCkgfCAoMSkgY2FsbGluZyBwcm9kdWNlci5wYXVzZSgpJyk7XG5cblx0aWYgKHByb2R1Y2VyLnBhdXNlKCdJIFBBVVNFICgxKScpKVxuXHR7XG5cdFx0bG9nZ2VyLndhcm4oXG5cdFx0XHQndGVzdFBhdXNlUmVzdW1lKCkgfCAoMSkgcHJvZHVjZXIucGF1c2UoKSBzdWNjZWVkZWQgW2xvY2FsbHlQYXVzZWQ6JXNdJyxcblx0XHRcdHByb2R1Y2VyLmxvY2FsbHlQYXVzZWQpO1xuXHR9XG5cdGVsc2Vcblx0e1xuXHRcdGxvZ2dlci5lcnJvcihcblx0XHRcdCd0ZXN0UGF1c2VSZXN1bWUoKSB8ICgxKSBwcm9kdWNlci5wYXVzZSgpIGZhaWxlZCBbbG9jYWxseVBhdXNlZDolc10nLFxuXHRcdFx0cHJvZHVjZXIubG9jYWxseVBhdXNlZCk7XG5cdH1cblxuXHRsb2dnZXIuZGVidWcoJ3Rlc3RQYXVzZVJlc3VtZSgpIHwgKDIpIGNhbGxpbmcgcHJvZHVjZXIucGF1c2UoKScpO1xuXG5cdGlmIChwcm9kdWNlci5wYXVzZSgnSSBQQVVTRSAoMiknKSlcblx0e1xuXHRcdGxvZ2dlci53YXJuKFxuXHRcdFx0J3Rlc3RQYXVzZVJlc3VtZSgpIHwgKDIpIHByb2R1Y2VyLnBhdXNlKCkgc3VjY2VlZGVkIFtsb2NhbGx5UGF1c2VkOiVzXScsXG5cdFx0XHRwcm9kdWNlci5sb2NhbGx5UGF1c2VkKTtcblx0fVxuXHRlbHNlXG5cdHtcblx0XHRsb2dnZXIuZXJyb3IoXG5cdFx0XHQndGVzdFBhdXNlUmVzdW1lKCkgfCAoMikgcHJvZHVjZXIucGF1c2UoKSBmYWlsZWQgW2xvY2FsbHlQYXVzZWQ6JXNdJyxcblx0XHRcdHByb2R1Y2VyLmxvY2FsbHlQYXVzZWQpO1xuXHR9XG5cblx0bG9nZ2VyLmRlYnVnKCd0ZXN0UGF1c2VSZXN1bWUoKSB8ICgzKSBjYWxsaW5nIHByb2R1Y2VyLnJlc3VtZSgpJyk7XG5cblx0aWYgKHByb2R1Y2VyLnJlc3VtZSgnSSBSRVNVTUUgKDMpJykpXG5cdHtcblx0XHRsb2dnZXIud2Fybihcblx0XHRcdCd0ZXN0UGF1c2VSZXN1bWUoKSB8ICgzKSBwcm9kdWNlci5yZXN1bWUoKSBzdWNjZWVkZWQgW2xvY2FsbHlQYXVzZWQ6JXNdJyxcblx0XHRcdHByb2R1Y2VyLmxvY2FsbHlQYXVzZWQpO1xuXHR9XG5cdGVsc2Vcblx0e1xuXHRcdGxvZ2dlci5lcnJvcihcblx0XHRcdCd0ZXN0UGF1c2VSZXN1bWUoKSB8ICgzKSBwcm9kdWNlci5yZXN1bWUoKSBmYWlsZWQgW2xvY2FsbHlQYXVzZWQ6JXNdJyxcblx0XHRcdHByb2R1Y2VyLmxvY2FsbHlQYXVzZWQpO1xuXHR9XG59O1xuXG5cbi8vIE5PVEU6IEZvciBkZWJ1Z2dpbmcuXG5cbndpbmRvdy5kdW1wMSA9IGZ1bmN0aW9uKClcbntcblx0Y29uc3QgdHJhbnNwb3J0MSA9IHdpbmRvdy50cmFuc3BvcnQxO1xuXHRjb25zdCBwYzEgPSB0cmFuc3BvcnQxLl9oYW5kbGVyLl9wYztcblxuXHRpZiAocGMxICYmIHBjMS5sb2NhbERlc2NyaXB0aW9uKVxuXHRcdGxvZ2dlci53YXJuKCdQQzEgU0VORCBMT0NBTCBPRkZFUjpcXG4lcycsIHBjMS5sb2NhbERlc2NyaXB0aW9uLnNkcCk7XG5cblx0aWYgKHBjMSAmJiBwYzEucmVtb3RlRGVzY3JpcHRpb24pXG5cdFx0bG9nZ2VyLndhcm4oJ1BDMSBTRU5EIFJFTU9URSBBTlNXRVI6XFxuJXMnLCBwYzEucmVtb3RlRGVzY3JpcHRpb24uc2RwKTtcbn07XG5cbndpbmRvdy5kdW1wMiA9IGZ1bmN0aW9uKClcbntcblx0Y29uc3QgdHJhbnNwb3J0MiA9IHdpbmRvdy50cmFuc3BvcnQyO1xuXHRjb25zdCBwYzIgPSB0cmFuc3BvcnQyLl9oYW5kbGVyLl9wYztcblxuXHRpZiAocGMyICYmIHBjMi5yZW1vdGVEZXNjcmlwdGlvbilcblx0XHRsb2dnZXIud2FybignUEMyIFJFQ1YgUkVNT1RFIE9GRkVSOlxcbiVzJywgcGMyLnJlbW90ZURlc2NyaXB0aW9uLnNkcCk7XG5cblx0aWYgKHBjMiAmJiBwYzIubG9jYWxEZXNjcmlwdGlvbilcblx0XHRsb2dnZXIud2FybignUEMyIFJFQ1YgTE9DQUwgQU5TV0VSOlxcbiVzJywgcGMyLmxvY2FsRGVzY3JpcHRpb24uc2RwKTtcbn07XG4iXX0= diff --git a/server/package.json b/server/package.json index 404ecaf..f549bc3 100644 --- a/server/package.json +++ b/server/package.json @@ -1,6 +1,6 @@ { "name": "multiparty-meeting-server", - "version": "2.0.0", + "version": "1.1.0", "private": true, "description": "multiparty meeting server", "author": "Håvar Aambø Fosstveit ",